summaryrefslogtreecommitdiffstats
path: root/audio/audio.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-11-11 21:20:21 +0100
committerwm4 <wm4@nowhere>2014-11-11 21:20:21 +0100
commitd4cc41bbcd378d30a3c52c5342c395e7f64539ca (patch)
tree23d1883cb41ce40d9a33a12a94596e39e625738e /audio/audio.c
parent475226c783cd3ce17a90ee5312727e013b2436cf (diff)
downloadmpv-d4cc41bbcd378d30a3c52c5342c395e7f64539ca.tar.bz2
mpv-d4cc41bbcd378d30a3c52c5342c395e7f64539ca.tar.xz
audio: make sure AVFrame is actually refcounted
The mp_audio_from_avframe() function requires the AVFrame to be refcounted, and merely increases its refcount while referencing the same data. For non-refcounted frames, it simply did nothing and potentially would make the caller pass around a frame with dangling pointers. (libavcodec should always return refcounted frames, but it's not clear what other code does; and also the function should simply work, instead of having weird requirements on its arguments.)
Diffstat (limited to 'audio/audio.c')
-rw-r--r--audio/audio.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/audio/audio.c b/audio/audio.c
index 24539e6db5..0458e813e7 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -272,6 +272,7 @@ int mp_audio_make_writeable(struct mp_audio *data)
struct mp_audio *mp_audio_from_avframe(struct AVFrame *avframe)
{
+ AVFrame *tmp = NULL;
struct mp_audio *new = talloc_zero(NULL, struct mp_audio);
talloc_set_destructor(new, mp_audio_destructor);
@@ -290,6 +291,16 @@ struct mp_audio *mp_audio_from_avframe(struct AVFrame *avframe)
mp_audio_set_channels(new, &lavc_chmap);
+ // Force refcounted frame.
+ if (!avframe->buf[0]) {
+ tmp = av_frame_alloc();
+ if (!tmp)
+ goto fail;
+ if (av_frame_ref(tmp, avframe) < 0)
+ goto fail;
+ avframe = tmp;
+ }
+
// If we can't handle the format (e.g. too many channels), bail out.
if (!mp_audio_config_valid(new) || avframe->nb_extended_buf)
goto fail;
@@ -312,6 +323,7 @@ struct mp_audio *mp_audio_from_avframe(struct AVFrame *avframe)
fail:
talloc_free(new);
+ av_frame_free(&tmp);
return NULL;
}