diff options
author | Mark Nauwelaerts <mnauw@users.sourceforge.net> | 2014-04-15 21:32:07 +0200 |
---|---|---|
committer | Mark Nauwelaerts <mnauw@users.sourceforge.net> | 2014-04-15 21:32:07 +0200 |
commit | bdbd29017d8b709ce851a5b5fac48de1ca27e3b2 (patch) | |
tree | 93fedb99b346a6ac1e0fab6e19fd7ca579d444ec | |
parent | 9946e5b0649eb38ff4d704657bbef513e4ecd427 (diff) | |
download | gst-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.c | 19 | ||||
-rw-r--r-- | ext/libav/gstavviddec.h | 2 |
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; |