diff options
author | Aurélien Zanelli <aurelien.zanelli@parrot.com> | 2014-05-30 15:29:15 +0200 |
---|---|---|
committer | Sebastian Dröge <sebastian@centricular.com> | 2014-06-04 16:36:02 +0200 |
commit | ad969ffda34f671252d115fbb3293fae43f1b0e6 (patch) | |
tree | b6630a376d1e0fffbd0237aa44ec0374858b44b9 | |
parent | 4c488d425d2dfb3dbb7225aa55b0425050f0531b (diff) | |
download | gst-omx-ad969ffda34f671252d115fbb3293fae43f1b0e6.tar.gz |
omxvideodec: release frames with old PTS to avoid memory issue
Interlaced stream could make the decoder use two input frames to produce
one output frame causing the gstvideodecoder frame list to grow.
Assuming the video decoder output frame in display order rather than in
decoding order, this commit add a way to release frames with PTS less
than current output frame.
https://bugzilla.gnome.org/show_bug.cgi?id=730995
-rw-r--r-- | omx/gstomxvideodec.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/omx/gstomxvideodec.c b/omx/gstomxvideodec.c index 207ba88..2fc7f19 100644 --- a/omx/gstomxvideodec.c +++ b/omx/gstomxvideodec.c @@ -1168,6 +1168,53 @@ done: } static void +gst_omx_video_dec_clean_older_frames (GstOMXVideoDec * self, + GstOMXBuffer * buf, GList * frames) +{ + GList *l; + GstClockTime timestamp; + + timestamp = gst_util_uint64_scale (buf->omx_buf->nTimeStamp, GST_SECOND, + OMX_TICKS_PER_SECOND); + + if (GST_CLOCK_TIME_IS_VALID (timestamp)) { + /* We could release all frames stored with pts < timestamp since the + * decoder will likely output frames in display order */ + for (l = frames; l; l = l->next) { + GstVideoCodecFrame *tmp = l->data; + + if (tmp->pts < timestamp) { + gst_video_decoder_release_frame (GST_VIDEO_DECODER (self), tmp); + GST_LOG_OBJECT (self, + "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)); + } else { + gst_video_codec_frame_unref (tmp); + } + } + } else { + /* We will release all frames with invalid timestamp because we don't even + * know if they will be output some day. */ + for (l = frames; l; l = l->next) { + GstVideoCodecFrame *tmp = l->data; + + if (!GST_CLOCK_TIME_IS_VALID (tmp->pts)) { + gst_video_decoder_release_frame (GST_VIDEO_DECODER (self), tmp); + GST_LOG_OBJECT (self, + "discarding frame %p (#%d) with invalid PTS:%" GST_TIME_FORMAT + " DTS:%" GST_TIME_FORMAT, tmp, tmp->system_frame_number, + GST_TIME_ARGS (tmp->pts), GST_TIME_ARGS (tmp->dts)); + } else { + gst_video_codec_frame_unref (tmp); + } + } + } + + g_list_free (frames); +} + +static void gst_omx_video_dec_loop (GstOMXVideoDec * self) { GstOMXPort *port; @@ -1297,6 +1344,15 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self) frame = gst_omx_video_find_nearest_frame (buf, gst_video_decoder_get_frames (GST_VIDEO_DECODER (self))); + /* So we have a timestamped OMX buffer and get, or not, corresponding frame. + * Assuming decoder output frames in display order, frames preceding this + * frame could be discarded as they seems useless due to e.g interlaced + * stream, corrupted input data... + * In any cases, not likely to be seen again. so drop it before they pile up + * and use all the memory. */ + gst_omx_video_dec_clean_older_frames (self, buf, + gst_video_decoder_get_frames (GST_VIDEO_DECODER (self))); + if (frame && (deadline = gst_video_decoder_get_max_decode_time (GST_VIDEO_DECODER (self), frame)) < 0) { |