@ -56,6 +56,15 @@ typedef struct {
int h264_initialized ;
struct vda_context vda_ctx ;
enum AVPixelFormat pix_fmt ;
/* for backing-up fields set by user.
* we have to gain full control of such fields here */
void * hwaccel_context ;
enum AVPixelFormat ( * get_format ) ( struct AVCodecContext * s , const enum AVPixelFormat * fmt ) ;
int ( * get_buffer2 ) ( struct AVCodecContext * s , AVFrame * frame , int flags ) ;
# if FF_API_GET_BUFFER
int ( * get_buffer ) ( struct AVCodecContext * c , AVFrame * pic ) ;
# endif
} VDADecoderContext ;
static enum AVPixelFormat get_format ( struct AVCodecContext * avctx ,
@ -90,6 +99,32 @@ static int get_buffer2(AVCodecContext *avctx, AVFrame *pic, int flag)
return 0 ;
}
static inline void set_context ( AVCodecContext * avctx )
{
VDADecoderContext * ctx = avctx - > priv_data ;
ctx - > hwaccel_context = avctx - > hwaccel_context ;
avctx - > hwaccel_context = & ctx - > vda_ctx ;
ctx - > get_format = avctx - > get_format ;
avctx - > get_format = get_format ;
ctx - > get_buffer2 = avctx - > get_buffer2 ;
avctx - > get_buffer2 = get_buffer2 ;
# if FF_API_GET_BUFFER
ctx - > get_buffer = avctx - > get_buffer ;
avctx - > get_buffer = NULL ;
# endif
}
static inline void restore_context ( AVCodecContext * avctx )
{
VDADecoderContext * ctx = avctx - > priv_data ;
avctx - > hwaccel_context = ctx - > hwaccel_context ;
avctx - > get_format = ctx - > get_format ;
avctx - > get_buffer2 = ctx - > get_buffer2 ;
# if FF_API_GET_BUFFER
avctx - > get_buffer = ctx - > get_buffer ;
# endif
}
static int vdadec_decode ( AVCodecContext * avctx ,
void * data , int * got_frame , AVPacket * avpkt )
{
@ -97,7 +132,9 @@ static int vdadec_decode(AVCodecContext *avctx,
AVFrame * pic = data ;
int ret ;
set_context ( avctx ) ;
ret = ff_h264_decoder . decode ( avctx , data , got_frame , avpkt ) ;
restore_context ( avctx ) ;
if ( * got_frame ) {
AVBufferRef * buffer = pic - > buf [ 0 ] ;
VDABufferContext * context = av_buffer_get_opaque ( buffer ) ;
@ -130,8 +167,11 @@ static av_cold int vdadec_close(AVCodecContext *avctx)
/* release buffers and decoder */
ff_vda_destroy_decoder ( & ctx - > vda_ctx ) ;
/* close H.264 decoder */
if ( ctx - > h264_initialized )
if ( ctx - > h264_initialized ) {
set_context ( avctx ) ;
ff_h264_decoder . close ( avctx ) ;
restore_context ( avctx ) ;
}
return 0 ;
}
@ -184,18 +224,11 @@ static av_cold int vdadec_init(AVCodecContext *avctx)
" Failed to init VDA decoder: %d. \n " , status ) ;
goto failed ;
}
avctx - > hwaccel_context = vda_ctx ;
/* changes callback functions */
avctx - > get_format = get_format ;
avctx - > get_buffer2 = get_buffer2 ;
# if FF_API_GET_BUFFER
// force the old get_buffer to be empty
avctx - > get_buffer = NULL ;
# endif
/* init H.264 decoder */
set_context ( avctx ) ;
ret = ff_h264_decoder . init ( avctx ) ;
restore_context ( avctx ) ;
if ( ret < 0 ) {
av_log ( avctx , AV_LOG_ERROR , " Failed to open H.264 decoder. \n " ) ;
goto failed ;
@ -211,7 +244,9 @@ failed:
static void vdadec_flush ( AVCodecContext * avctx )
{
return ff_h264_decoder . flush ( avctx ) ;
set_context ( avctx ) ;
ff_h264_decoder . flush ( avctx ) ;
restore_context ( avctx ) ;
}
AVCodec ff_h264_vda_decoder = {