diff options
author | Mark Nauwelaerts <mnauw@users.sourceforge.net> | 2013-11-26 20:57:37 +0100 |
---|---|---|
committer | Sebastian Dröge <sebastian@centricular.com> | 2013-12-13 14:38:47 +0100 |
commit | f2d11ffaffb941363f042ef703e4ceeaf51557e1 (patch) | |
tree | b6ca000e0c5b6d232241c8f13d2f5854d672b9c3 | |
parent | 3b928851d00d3e4460cdefdd0a393b1465b4513c (diff) |
avviddec: discard unused input frames
... to avoid these piling up in list of pending frames.
Fixes https://bugzilla.gnome.org/show_bug.cgi?id=693772
-rw-r--r-- | ext/libav/gstavviddec.c | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/ext/libav/gstavviddec.c b/ext/libav/gstavviddec.c index ada68e2..cadae6f 100644 --- a/ext/libav/gstavviddec.c +++ b/ext/libav/gstavviddec.c @@ -575,6 +575,11 @@ gst_ffmpegviddec_get_buffer (AVCodecContext * context, AVFrame * picture) if (G_UNLIKELY (frame == NULL)) goto no_frame; + /* now it has a buffer allocated, so it is real and will also + * be _released */ + GST_VIDEO_CODEC_FRAME_FLAG_UNSET (frame, + GST_VIDEO_CODEC_FRAME_FLAG_DECODE_ONLY); + if (G_UNLIKELY (frame->output_buffer != NULL)) goto duplicate_frame; @@ -1253,6 +1258,41 @@ gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec, GST_VIDEO_BUFFER_FLAG_INTERLACED); } + /* cleaning time */ + /* so we decoded this frame, frames preceding it in decoding order + * that still do not have a buffer allocated seem rather useless, + * and can be discarded, due to e.g. misparsed bogus frame + * or non-keyframe in skipped decoding, ... + * In any case, not likely to be seen again, so discard those, + * before they pile up and/or mess with timestamping */ + { + GList *l, *ol; + GstVideoDecoder *dec = GST_VIDEO_DECODER (ffmpegdec); + gboolean old = TRUE; + + ol = l = gst_video_decoder_get_frames (dec); + while (l) { + GstVideoCodecFrame *tmp = l->data; + + if (tmp == frame) + old = FALSE; + + if (old && GST_VIDEO_CODEC_FRAME_IS_DECODE_ONLY (tmp)) { + GST_LOG_OBJECT (dec, + "discarding ghost frame %p (#%d) PTS:%" GST_TIME_FORMAT " DTS:%" + GST_TIME_FORMAT, tmp, tmp->system_frame_number, + GST_TIME_ARGS (tmp->pts), GST_TIME_ARGS (tmp->dts)); + /* drop extra ref and remove from frame list */ + gst_video_decoder_release_frame (dec, tmp); + } else { + /* drop extra ref we got */ + gst_video_codec_frame_unref (tmp); + } + l = l->next; + } + g_list_free (ol); + } + *ret = gst_video_decoder_finish_frame (GST_VIDEO_DECODER (ffmpegdec), out_frame); @@ -1388,6 +1428,10 @@ gst_ffmpegviddec_handle_frame (GstVideoDecoder * decoder, return GST_FLOW_ERROR; } + /* treat frame as void until a buffer is requested for it */ + GST_VIDEO_CODEC_FRAME_FLAG_SET (frame, + GST_VIDEO_CODEC_FRAME_FLAG_DECODE_ONLY); + bdata = minfo.data; bsize = minfo.size; |