summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--omx/gstomxvideodec.c56
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) {