@ -45,8 +45,10 @@ enum { kCMVideoCodecType_HEVC = 'hvc1' };
static void videotoolbox_buffer_release ( void * opaque , uint8_t * data )
static void videotoolbox_buffer_release ( void * opaque , uint8_t * data )
{
{
CVPixelBufferRef cv_buffer = ( CVImageBufferRef ) data ;
CVPixelBufferRef cv_buffer = * ( CVPixelBufferRef * ) data ;
CVPixelBufferRelease ( cv_buffer ) ;
CVPixelBufferRelease ( cv_buffer ) ;
av_free ( data ) ;
}
}
static int videotoolbox_buffer_copy ( VTContext * vtctx ,
static int videotoolbox_buffer_copy ( VTContext * vtctx ,
@ -69,19 +71,47 @@ static int videotoolbox_buffer_copy(VTContext *vtctx,
return 0 ;
return 0 ;
}
}
static int videotoolbox_postproc_frame ( void * avctx , AVFrame * frame )
{
CVPixelBufferRef ref = * ( CVPixelBufferRef * ) frame - > buf [ 0 ] - > data ;
if ( ! ref ) {
av_log ( avctx , AV_LOG_ERROR , " No frame decoded? \n " ) ;
av_frame_unref ( frame ) ;
return AVERROR_EXTERNAL ;
}
frame - > data [ 3 ] = ( uint8_t * ) ref ;
return 0 ;
}
int ff_videotoolbox_alloc_frame ( AVCodecContext * avctx , AVFrame * frame )
int ff_videotoolbox_alloc_frame ( AVCodecContext * avctx , AVFrame * frame )
{
{
size_t size = sizeof ( CVPixelBufferRef ) ;
uint8_t * data = NULL ;
AVBufferRef * buf = NULL ;
int ret = ff_attach_decode_data ( frame ) ;
int ret = ff_attach_decode_data ( frame ) ;
FrameDecodeData * fdd ;
if ( ret < 0 )
if ( ret < 0 )
return ret ;
return ret ;
data = av_mallocz ( size ) ;
if ( ! data )
return AVERROR ( ENOMEM ) ;
buf = av_buffer_create ( data , size , videotoolbox_buffer_release , NULL , 0 ) ;
if ( ! buf ) {
av_freep ( & data ) ;
return AVERROR ( ENOMEM ) ;
}
frame - > buf [ 0 ] = buf ;
fdd = ( FrameDecodeData * ) frame - > private_ref - > data ;
fdd - > post_process = videotoolbox_postproc_frame ;
frame - > width = avctx - > width ;
frame - > width = avctx - > width ;
frame - > height = avctx - > height ;
frame - > height = avctx - > height ;
frame - > format = avctx - > pix_fmt ;
frame - > format = avctx - > pix_fmt ;
frame - > buf [ 0 ] = av_buffer_alloc ( 1 ) ;
if ( ! frame - > buf [ 0 ] )
return AVERROR ( ENOMEM ) ;
return 0 ;
return 0 ;
}
}
@ -285,20 +315,24 @@ CFDataRef ff_videotoolbox_hvcc_extradata_create(AVCodecContext *avctx)
return data ;
return data ;
}
}
int ff_videotoolbox_buffer_create ( VT Context * vt ctx , AVFrame * frame )
static int videotoolbox_set_frame ( AVCodec Context * a vctx, AVFrame * frame )
{
{
av_buffer_unref ( & frame - > buf [ 0 ] ) ;
VTContext * vtctx = avctx - > internal - > hwaccel_priv_data ;
if ( ! frame - > buf [ 0 ] | | frame - > data [ 3 ] ) {
frame - > buf [ 0 ] = av_buffer_create ( ( uint8_t * ) vtctx - > frame ,
av_log ( avctx , AV_LOG_ERROR , " videotoolbox: invalid state \n " ) ;
sizeof ( vtctx - > frame ) ,
av_frame_unref ( frame ) ;
videotoolbox_buffer_release ,
return AVERROR_EXTERNAL ;
NULL ,
}
AV_BUFFER_FLAG_READONLY ) ;
if ( ! frame - > buf [ 0 ] ) {
CVPixelBufferRef * ref = ( CVPixelBufferRef * ) frame - > buf [ 0 ] - > data ;
return AVERROR ( ENOMEM ) ;
if ( * ref ) {
av_log ( avctx , AV_LOG_ERROR , " videotoolbox: frame already set? \n " ) ;
av_frame_unref ( frame ) ;
return AVERROR_EXTERNAL ;
}
}
frame - > data [ 3 ] = ( uint8_t * ) vtctx - > frame ;
* ref = vtctx - > frame ;
vtctx - > frame = NULL ;
vtctx - > frame = NULL ;
return 0 ;
return 0 ;
@ -406,7 +440,7 @@ static int videotoolbox_buffer_create(AVCodecContext *avctx, AVFrame *frame)
AVHWFramesContext * cached_frames ;
AVHWFramesContext * cached_frames ;
int ret ;
int ret ;
ret = ff_videotoolbox_buffer_create ( vt ctx, frame ) ;
ret = videotoolbox_set_frame ( av ctx, frame ) ;
if ( ret < 0 )
if ( ret < 0 )
return ret ;
return ret ;