summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-03-16 01:34:48 +0100
committerwm4 <wm4@nowhere>2014-03-30 17:50:11 +0200
commit1685d198b9f9b2a3edb8d204a6f29f3c827cd599 (patch)
tree89c893ef563bf9f7607bb77c117474cd8cd0b5f6
parent1e2d28f56707886d1a40470502f18c079444aeb9 (diff)
downloadmpv-1685d198b9f9b2a3edb8d204a6f29f3c827cd599.tar.bz2
mpv-1685d198b9f9b2a3edb8d204a6f29f3c827cd599.tar.xz
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.)
-rw-r--r--video/decode/lavc.h1
-rw-r--r--video/decode/lavc_dr1.c10
-rw-r--r--video/decode/vd_lavc.c13
3 files changed, 23 insertions, 1 deletions
diff --git a/video/decode/lavc.h b/video/decode/lavc.h
index 867488de95..305c0b551d 100644
--- a/video/decode/lavc.h
+++ b/video/decode/lavc.h
@@ -91,5 +91,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 355db26556..3533841502 100644
--- a/video/decode/vd_lavc.c
+++ b/video/decode/vd_lavc.c
@@ -706,7 +706,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 {
@@ -752,6 +761,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, &params);