From ba160f5c8455d984ae51664c1df007e5e6333b5b Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 16 Mar 2014 01:34:48 +0100 Subject: vd_lavc: ridiculous workaround for Libav 9 compatibility This "sometimes" crashed when seeking. The fault apparently lies in libavcodec: the decoder returns an unreferenced frame! This is completely insane, but somehow I'm apparently still expected to work this around. As a reaction, I will drop Libav 9 support in the next commit. (While this commit will go into release/0.3.) --- video/decode/lavc.h | 1 + video/decode/lavc_dr1.c | 10 ++++++++++ video/decode/vd_lavc.c | 13 ++++++++++++- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/video/decode/lavc.h b/video/decode/lavc.h index 71d568aa8a..45d2d9b5cd 100644 --- a/video/decode/lavc.h +++ b/video/decode/lavc.h @@ -98,5 +98,6 @@ void mp_buffer_ref(struct FrameBuffer *buffer); void mp_buffer_unref(struct FrameBuffer *buffer); bool mp_buffer_is_unique(struct FrameBuffer *buffer); void mp_buffer_pool_free(struct FramePool **pool); +bool mp_buffer_check(struct FrameBuffer *buffer); #endif diff --git a/video/decode/lavc_dr1.c b/video/decode/lavc_dr1.c index 03e2b5b873..f730a6c231 100644 --- a/video/decode/lavc_dr1.c +++ b/video/decode/lavc_dr1.c @@ -204,6 +204,16 @@ void mp_buffer_ref(struct FrameBuffer *buf) pool_unlock(); } +bool mp_buffer_check(struct FrameBuffer *buf) +{ + pool_lock(); + bool ok = buf->refcount > 0; + if (ok) + buf->refcount++; + pool_unlock(); + return ok; +} + void mp_buffer_unref(struct FrameBuffer *buf) { FramePool *pool = buf->pool; diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c index eed79e81b1..454251f4ad 100644 --- a/video/decode/vd_lavc.c +++ b/video/decode/vd_lavc.c @@ -688,7 +688,16 @@ static struct mp_image *image_from_decoder(struct dec_video *vd) mp_image_copy_attributes(mpi, &new); } else if (ctx->do_dr1 && pic->opaque) { struct FrameBuffer *fb = pic->opaque; - mp_buffer_ref(fb); // initial reference for mpi + // initial reference for mpi + if (!new.planes[0] || !mp_buffer_check(fb)) { + // Decoder returned an unreferenced buffer! Taking this would just + // lead to an eventual double-free. Nothing we can do about this. + // So just say "fuck you" in a nice way. + MP_FATAL(vd, + "Impossible condition detected! This version of Libav/FFmpeg is not\n" + "supported anymore. Please update.\n"); + return NULL; + } mpi = mp_image_new_external_ref(&new, fb, fb_ref, fb_unref, fb_is_unique, NULL); } else { @@ -734,6 +743,8 @@ static int decode(struct dec_video *vd, struct demux_packet *packet, // Note: potentially resets ctx->pic as it is transferred to mpi struct mp_image *mpi = image_from_decoder(vd); + if (!mpi) + return 0; assert(mpi->planes[0]); mp_image_set_params(mpi, ¶ms); -- cgit v1.2.3