mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-11 09:55:36 +00:00
videodecoder: finetune missing timestamp estimating
Monitor for reordered output timestamps, and then avoid oldest DTS as PTS approach, and try for an oldest PTS as out PTS approach, if at least all valid PTS available. Avoids bogus estimating upon sparse available input PTS, and tries to handle all-keyframe input, or input PTS which are actually DTS.
This commit is contained in:
parent
80e4f3e912
commit
706498cb6e
2 changed files with 49 additions and 2 deletions
|
@ -352,6 +352,7 @@ struct _GstVideoDecoderPrivate
|
|||
GstClockTime last_timestamp_out;
|
||||
/* incoming pts - dts */
|
||||
GstClockTime pts_delta;
|
||||
gboolean reordered_output;
|
||||
|
||||
/* reverse playback */
|
||||
/* collect input */
|
||||
|
@ -1620,6 +1621,7 @@ gst_video_decoder_reset (GstVideoDecoder * decoder, gboolean full)
|
|||
gst_tag_list_unref (priv->tags);
|
||||
priv->tags = NULL;
|
||||
priv->tags_changed = FALSE;
|
||||
priv->reordered_output = FALSE;
|
||||
}
|
||||
|
||||
priv->discont = TRUE;
|
||||
|
@ -2174,13 +2176,51 @@ gst_video_decoder_prepare_finish_frame (GstVideoDecoder *
|
|||
|
||||
/* and set if needed;
|
||||
* valid delta means we have reasonable DTS input */
|
||||
if (!GST_CLOCK_TIME_IS_VALID (frame->pts) && !seen_none &&
|
||||
/* also, if we ended up reordered, means this approach is conflicting
|
||||
* with some sparse existing PTS, and so it does not work out */
|
||||
if (!priv->reordered_output &&
|
||||
!GST_CLOCK_TIME_IS_VALID (frame->pts) && !seen_none &&
|
||||
GST_CLOCK_TIME_IS_VALID (priv->pts_delta)) {
|
||||
frame->pts = min_ts + priv->pts_delta;
|
||||
GST_DEBUG_OBJECT (decoder,
|
||||
"no valid PTS, using oldest DTS %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (frame->pts));
|
||||
}
|
||||
|
||||
/* some more maintenance, ts2 holds PTS */
|
||||
min_ts = GST_CLOCK_TIME_NONE;
|
||||
seen_none = FALSE;
|
||||
for (l = priv->frames; l; l = l->next) {
|
||||
GstVideoCodecFrame *tmp = l->data;
|
||||
|
||||
if (!GST_CLOCK_TIME_IS_VALID (tmp->abidata.ABI.ts2)) {
|
||||
seen_none = TRUE;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!GST_CLOCK_TIME_IS_VALID (min_ts) || tmp->abidata.ABI.ts2 < min_ts) {
|
||||
min_ts = tmp->abidata.ABI.ts2;
|
||||
oframe = tmp;
|
||||
}
|
||||
}
|
||||
/* save a ts if needed */
|
||||
if (oframe && oframe != frame) {
|
||||
oframe->abidata.ABI.ts2 = frame->abidata.ABI.ts2;
|
||||
}
|
||||
|
||||
/* if we detected reordered output, then PTS are void,
|
||||
* however those were obtained; bogus input, subclass etc */
|
||||
if (priv->reordered_output && !seen_none) {
|
||||
GST_DEBUG_OBJECT (decoder, "invaliding PTS");
|
||||
frame->pts = GST_CLOCK_TIME_NONE;
|
||||
}
|
||||
|
||||
if (!GST_CLOCK_TIME_IS_VALID (frame->pts) && !seen_none) {
|
||||
frame->pts = min_ts;
|
||||
GST_DEBUG_OBJECT (decoder,
|
||||
"no valid PTS, using oldest PTS %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (frame->pts));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -2202,6 +2242,7 @@ gst_video_decoder_prepare_finish_frame (GstVideoDecoder *
|
|||
"decreasing timestamp (%" GST_TIME_FORMAT " < %"
|
||||
GST_TIME_FORMAT ")",
|
||||
GST_TIME_ARGS (frame->pts), GST_TIME_ARGS (priv->last_timestamp_out));
|
||||
priv->reordered_output = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2590,9 +2631,11 @@ gst_video_decoder_decode_frame (GstVideoDecoder * decoder,
|
|||
frame->pts = GST_BUFFER_PTS (frame->input_buffer);
|
||||
frame->dts = GST_BUFFER_DTS (frame->input_buffer);
|
||||
frame->duration = GST_BUFFER_DURATION (frame->input_buffer);
|
||||
frame->abidata.ABI.ts = frame->dts;
|
||||
|
||||
/* For keyframes, PTS = DTS */
|
||||
/* FIXME upstream can be quite wrong about the keyframe aspect,
|
||||
* so we could be going off here as well,
|
||||
* maybe let subclass decide if it really is/was a keyframe */
|
||||
if (GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame)) {
|
||||
if (!GST_CLOCK_TIME_IS_VALID (frame->pts)) {
|
||||
frame->pts = frame->dts;
|
||||
|
@ -2605,6 +2648,9 @@ gst_video_decoder_decode_frame (GstVideoDecoder * decoder,
|
|||
}
|
||||
}
|
||||
|
||||
frame->abidata.ABI.ts = frame->dts;
|
||||
frame->abidata.ABI.ts2 = frame->pts;
|
||||
|
||||
GST_LOG_OBJECT (decoder, "PTS %" GST_TIME_FORMAT ", DTS %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (frame->pts), GST_TIME_ARGS (frame->dts));
|
||||
GST_LOG_OBJECT (decoder, "dist %d", frame->distance_from_sync);
|
||||
|
|
|
@ -249,6 +249,7 @@ struct _GstVideoCodecFrame
|
|||
union {
|
||||
struct {
|
||||
GstClockTime ts;
|
||||
GstClockTime ts2;
|
||||
} ABI;
|
||||
void *padding[GST_PADDING_LARGE];
|
||||
} abidata;
|
||||
|
|
Loading…
Reference in a new issue