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.
This commit is contained in:
wm4 2013-10-31 18:12:39 +01:00
parent d64b165b2a
commit 3ac568714c
1 changed files with 13 additions and 7 deletions

View File

@ -349,7 +349,6 @@ static void init_avctx(sh_video_t *sh, const char *decoder,
ctx->image_params = (struct mp_image_params){0}; ctx->image_params = (struct mp_image_params){0};
ctx->vo_image_params = (struct mp_image_params){0}; ctx->vo_image_params = (struct mp_image_params){0};
ctx->hwdec = hwdec; ctx->hwdec = hwdec;
ctx->pic = avcodec_alloc_frame();
ctx->avctx = avcodec_alloc_context3(lavc_codec); ctx->avctx = avcodec_alloc_context3(lavc_codec);
AVCodecContext *avctx = ctx->avctx; AVCodecContext *avctx = ctx->avctx;
avctx->opaque = sh; avctx->opaque = sh;
@ -358,6 +357,14 @@ static void init_avctx(sh_video_t *sh, const char *decoder,
avctx->thread_count = lavc_param->threads; 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) { if (ctx->hwdec && ctx->hwdec->allocate_image) {
ctx->do_hw_dr1 = true; ctx->do_hw_dr1 = true;
avctx->thread_count = 1; avctx->thread_count = 1;
@ -369,9 +376,7 @@ static void init_avctx(sh_video_t *sh, const char *decoder,
return; return;
} }
} else { } else {
#if HAVE_AVUTIL_REFCOUNTING #if !HAVE_AVUTIL_REFCOUNTING
avctx->refcounted_frames = 1;
#else
if (lavc_codec->capabilities & CODEC_CAP_DR1) { if (lavc_codec->capabilities & CODEC_CAP_DR1) {
ctx->do_dr1 = true; ctx->do_dr1 = true;
avctx->get_buffer = mp_codec_get_buffer; avctx->get_buffer = mp_codec_get_buffer;
@ -449,12 +454,14 @@ static void uninit_avctx(sh_video_t *sh)
} }
av_freep(&ctx->avctx); av_freep(&ctx->avctx);
avcodec_free_frame(&ctx->pic);
if (ctx->hwdec && ctx->hwdec->uninit) if (ctx->hwdec && ctx->hwdec->uninit)
ctx->hwdec->uninit(ctx); 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); mp_buffer_pool_free(&ctx->dr1_buffer_pool);
#endif #endif
ctx->last_sample_aspect_ratio = (AVRational){0, 0}; 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) static void setup_refcounting_hw(AVCodecContext *avctx)
{ {
avctx->get_buffer2 = get_buffer2_hwdec; avctx->get_buffer2 = get_buffer2_hwdec;
avctx->refcounted_frames = 1;
} }
#else /* HAVE_AVUTIL_REFCOUNTING */ #else /* HAVE_AVUTIL_REFCOUNTING */