diff options
-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) { |