mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
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
This commit is contained in:
parent
4c488d425d
commit
ad969ffda3
1 changed files with 56 additions and 0 deletions
|
@ -1167,6 +1167,53 @@ done:
|
|||
return err;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue