summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Nauwelaerts <mnauw@users.sourceforge.net>2014-04-15 21:32:07 +0200
committerMark Nauwelaerts <mnauw@users.sourceforge.net>2014-04-15 21:32:07 +0200
commitbdbd29017d8b709ce851a5b5fac48de1ca27e3b2 (patch)
tree93fedb99b346a6ac1e0fab6e19fd7ca579d444ec
parent9946e5b0649eb38ff4d704657bbef513e4ecd427 (diff)
downloadgst-libav-bdbd29017d8b709ce851a5b5fac48de1ca27e3b2.tar.gz
avviddec: guard against invalid libav opaque
Fixes https://bugzilla.gnome.org/show_bug.cgi?id=727779
-rw-r--r--ext/libav/gstavviddec.c19
-rw-r--r--ext/libav/gstavviddec.h2
2 files changed, 19 insertions, 2 deletions
diff --git a/ext/libav/gstavviddec.c b/ext/libav/gstavviddec.c
index 6c9c0c9..f369cf4 100644
--- a/ext/libav/gstavviddec.c
+++ b/ext/libav/gstavviddec.c
@@ -591,6 +591,8 @@ gst_ffmpegviddec_get_buffer (AVCodecContext * context, AVFrame * picture)
/* GstFFMpegVidDecVideoFrame receives the frame ref */
picture->opaque = dframe = gst_ffmpegviddec_video_frame_new (frame);
+ ffmpegdec->opaques = g_slist_prepend (ffmpegdec->opaques, dframe);
+
GST_DEBUG_OBJECT (ffmpegdec, "storing opaque %p", dframe);
ffmpegdec->context->pix_fmt = context->pix_fmt;
@@ -695,6 +697,7 @@ fallback:
int c;
int ret = avcodec_default_get_buffer (context, picture);
+ GST_LOG_OBJECT (ffmpegdec, "performing fallback alloc");
for (c = 0; c < AV_NUM_DATA_POINTERS; c++)
ffmpegdec->stride[c] = picture->linesize[c];
@@ -775,8 +778,8 @@ gst_ffmpegviddec_release_buffer (AVCodecContext * context, AVFrame * picture)
ffmpegdec = (GstFFMpegVidDec *) context->opaque;
frame = (GstFFMpegVidDecVideoFrame *) picture->opaque;
- GST_DEBUG_OBJECT (ffmpegdec, "release frame SN %d",
- frame->frame->system_frame_number);
+ GST_DEBUG_OBJECT (ffmpegdec, "release frame SN %d (%p)",
+ frame->frame->system_frame_number, frame);
/* check if it was our buffer */
if (picture->type != FF_BUFFER_TYPE_USER) {
@@ -789,6 +792,8 @@ gst_ffmpegviddec_release_buffer (AVCodecContext * context, AVFrame * picture)
gst_ffmpegviddec_video_frame_free (ffmpegdec, frame);
+ ffmpegdec->opaques = g_slist_remove (ffmpegdec->opaques, frame);
+
/* zero out the reference in ffmpeg */
for (i = 0; i < 4; i++) {
picture->data[i] = NULL;
@@ -1221,6 +1226,14 @@ gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec,
if (len < 0 || have_data <= 0)
goto beach;
+ GST_LOG_OBJECT (ffmpegdec, "picture opaque %p", ffmpegdec->picture->opaque);
+ /* libav might be tripping, and handing a picture with invalid opaque
+ * (e.g. already released) (sigh), so double-check here ... */
+ if (!g_slist_find (ffmpegdec->opaques, ffmpegdec->picture->opaque)) {
+ GST_ERROR_OBJECT (ffmpegdec, "invalid picture opaque");
+ goto beach;
+ }
+
/* get the output picture timing info again */
out_dframe = ffmpegdec->picture->opaque;
out_frame = gst_video_codec_frame_ref (out_dframe->frame);
@@ -1578,6 +1591,8 @@ gst_ffmpegviddec_stop (GstVideoDecoder * decoder)
if (ffmpegdec->output_state)
gst_video_codec_state_unref (ffmpegdec->output_state);
ffmpegdec->output_state = NULL;
+ g_slist_free (ffmpegdec->opaques);
+ ffmpegdec->opaques = NULL;
ffmpegdec->ctx_width = 0;
ffmpegdec->ctx_height = 0;
diff --git a/ext/libav/gstavviddec.h b/ext/libav/gstavviddec.h
index cd691ec..5f4d7af 100644
--- a/ext/libav/gstavviddec.h
+++ b/ext/libav/gstavviddec.h
@@ -67,6 +67,8 @@ struct _GstFFMpegVidDec
gboolean is_realvideo;
GstCaps *last_caps;
+
+ GSList *opaques;
};
typedef struct _GstFFMpegVidDecClass GstFFMpegVidDecClass;