From 3ac568714c385ddc6e2a87bbd74f3ac7faad6d68 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 31 Oct 2013 18:12:39 +0100 Subject: [PATCH] vd_lavc: add more ifdeffery and ffmpeg cargo culting for correctness We mixed the "old" AVFrame management functions (avcodec_alloc_frame, avcodec_free_frame) with reference counting. This doesn't work correctly; you must use av_frame_alloc and av_frame_free. Of course ffmpeg doesn't warn us about the bad usage, but will just mess up things silently. (Thanks a lot...) While the alloc function seems to be 100% compatible, the free function will do bad things, such as freeing memory that might still be referenced by another frame. I didn't experience any actual bugs, but maybe that was pure luck. --- video/decode/vd_lavc.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c index 6f395ea843..479e36df6a 100644 --- a/video/decode/vd_lavc.c +++ b/video/decode/vd_lavc.c @@ -349,7 +349,6 @@ static void init_avctx(sh_video_t *sh, const char *decoder, ctx->image_params = (struct mp_image_params){0}; ctx->vo_image_params = (struct mp_image_params){0}; ctx->hwdec = hwdec; - ctx->pic = avcodec_alloc_frame(); ctx->avctx = avcodec_alloc_context3(lavc_codec); AVCodecContext *avctx = ctx->avctx; avctx->opaque = sh; @@ -358,6 +357,14 @@ static void init_avctx(sh_video_t *sh, const char *decoder, avctx->thread_count = lavc_param->threads; + +#if HAVE_AVUTIL_REFCOUNTING + avctx->refcounted_frames = 1; + ctx->pic = av_frame_alloc(); +#else + ctx->pic = avcodec_alloc_frame(); +#endif + if (ctx->hwdec && ctx->hwdec->allocate_image) { ctx->do_hw_dr1 = true; avctx->thread_count = 1; @@ -369,9 +376,7 @@ static void init_avctx(sh_video_t *sh, const char *decoder, return; } } else { -#if HAVE_AVUTIL_REFCOUNTING - avctx->refcounted_frames = 1; -#else +#if !HAVE_AVUTIL_REFCOUNTING if (lavc_codec->capabilities & CODEC_CAP_DR1) { ctx->do_dr1 = true; avctx->get_buffer = mp_codec_get_buffer; @@ -449,12 +454,14 @@ static void uninit_avctx(sh_video_t *sh) } av_freep(&ctx->avctx); - avcodec_free_frame(&ctx->pic); if (ctx->hwdec && ctx->hwdec->uninit) ctx->hwdec->uninit(ctx); -#if !HAVE_AVUTIL_REFCOUNTING +#if HAVE_AVUTIL_REFCOUNTING + av_frame_free(&ctx->pic); +#else + avcodec_free_frame(&ctx->pic); mp_buffer_pool_free(&ctx->dr1_buffer_pool); #endif ctx->last_sample_aspect_ratio = (AVRational){0, 0}; @@ -603,7 +610,6 @@ static int get_buffer2_hwdec(AVCodecContext *avctx, AVFrame *pic, int flags) static void setup_refcounting_hw(AVCodecContext *avctx) { avctx->get_buffer2 = get_buffer2_hwdec; - avctx->refcounted_frames = 1; } #else /* HAVE_AVUTIL_REFCOUNTING */