Merged-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
Michael Niedermayer 2013-11-21 14:25:47 +01:00
commit 78bfc417d4

View File

@ -56,6 +56,15 @@ typedef struct {
int h264_initialized; int h264_initialized;
struct vda_context vda_ctx; struct vda_context vda_ctx;
enum AVPixelFormat pix_fmt; 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; } VDADecoderContext;
static enum AVPixelFormat get_format(struct AVCodecContext *avctx, static enum AVPixelFormat get_format(struct AVCodecContext *avctx,
@ -90,6 +99,32 @@ static int get_buffer2(AVCodecContext *avctx, AVFrame *pic, int flag)
return 0; 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, static int vdadec_decode(AVCodecContext *avctx,
void *data, int *got_frame, AVPacket *avpkt) void *data, int *got_frame, AVPacket *avpkt)
{ {
@ -97,7 +132,9 @@ static int vdadec_decode(AVCodecContext *avctx,
AVFrame *pic = data; AVFrame *pic = data;
int ret; int ret;
set_context(avctx);
ret = ff_h264_decoder.decode(avctx, data, got_frame, avpkt); ret = ff_h264_decoder.decode(avctx, data, got_frame, avpkt);
restore_context(avctx);
if (*got_frame) { if (*got_frame) {
AVBufferRef *buffer = pic->buf[0]; AVBufferRef *buffer = pic->buf[0];
VDABufferContext *context = av_buffer_get_opaque(buffer); VDABufferContext *context = av_buffer_get_opaque(buffer);
@ -130,8 +167,11 @@ static av_cold int vdadec_close(AVCodecContext *avctx)
/* release buffers and decoder */ /* release buffers and decoder */
ff_vda_destroy_decoder(&ctx->vda_ctx); ff_vda_destroy_decoder(&ctx->vda_ctx);
/* close H.264 decoder */ /* close H.264 decoder */
if (ctx->h264_initialized) if (ctx->h264_initialized) {
set_context(avctx);
ff_h264_decoder.close(avctx); ff_h264_decoder.close(avctx);
restore_context(avctx);
}
return 0; return 0;
} }
@ -184,18 +224,11 @@ static av_cold int vdadec_init(AVCodecContext *avctx)
"Failed to init VDA decoder: %d.\n", status); "Failed to init VDA decoder: %d.\n", status);
goto failed; 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 */ /* init H.264 decoder */
set_context(avctx);
ret = ff_h264_decoder.init(avctx); ret = ff_h264_decoder.init(avctx);
restore_context(avctx);
if (ret < 0) { if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "Failed to open H.264 decoder.\n"); av_log(avctx, AV_LOG_ERROR, "Failed to open H.264 decoder.\n");
goto failed; goto failed;
@ -211,7 +244,9 @@ failed:
static void vdadec_flush(AVCodecContext *avctx) 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 = { AVCodec ff_h264_vda_decoder = {