baseparse: Remember if we interpolated DTS from PTS and refresh it whenever we update the PTS

Otherwise PTS and DTS will come out of sync if upstream continues to provide
PTS and not DTS, and we have to skip some data from the stream or PTS are not
exactly increasing with the duration of each packet.

https://bugzilla.gnome.org/show_bug.cgi?id=765260
This commit is contained in:
Sebastian Dröge 2016-04-20 11:46:19 +03:00
parent c434b6486d
commit 5294065985

View file

@ -273,6 +273,7 @@ struct _GstBaseParsePrivate
GstClockTime next_dts; GstClockTime next_dts;
GstClockTime prev_pts; GstClockTime prev_pts;
GstClockTime prev_dts; GstClockTime prev_dts;
gboolean prev_dts_from_pts;
GstClockTime frame_duration; GstClockTime frame_duration;
gboolean seen_keyframe; gboolean seen_keyframe;
gboolean is_video; gboolean is_video;
@ -1308,6 +1309,7 @@ gst_base_parse_sink_event_default (GstBaseParse * parse, GstEvent * event)
parse->priv->last_dts = GST_CLOCK_TIME_NONE; parse->priv->last_dts = GST_CLOCK_TIME_NONE;
parse->priv->prev_pts = GST_CLOCK_TIME_NONE; parse->priv->prev_pts = GST_CLOCK_TIME_NONE;
parse->priv->prev_dts = GST_CLOCK_TIME_NONE; parse->priv->prev_dts = GST_CLOCK_TIME_NONE;
parse->priv->prev_dts_from_pts = FALSE;
parse->priv->discont = TRUE; parse->priv->discont = TRUE;
parse->priv->seen_keyframe = FALSE; parse->priv->seen_keyframe = FALSE;
parse->priv->skip = 0; parse->priv->skip = 0;
@ -2772,6 +2774,7 @@ gst_base_parse_start_fragment (GstBaseParse * parse)
parse->priv->prev_pts = GST_CLOCK_TIME_NONE; parse->priv->prev_pts = GST_CLOCK_TIME_NONE;
parse->priv->next_dts = GST_CLOCK_TIME_NONE; parse->priv->next_dts = GST_CLOCK_TIME_NONE;
parse->priv->prev_dts = GST_CLOCK_TIME_NONE; parse->priv->prev_dts = GST_CLOCK_TIME_NONE;
parse->priv->prev_dts_from_pts = FALSE;
/* prevent it hanging around stop all the time */ /* prevent it hanging around stop all the time */
parse->segment.position = GST_CLOCK_TIME_NONE; parse->segment.position = GST_CLOCK_TIME_NONE;
/* mark next run */ /* mark next run */
@ -3142,6 +3145,7 @@ gst_base_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
/* Stop either when adapter is empty or we are flushing */ /* Stop either when adapter is empty or we are flushing */
while (!parse->priv->flushing) { while (!parse->priv->flushing) {
gint flush = 0; gint flush = 0;
gboolean updated_prev_pts = FALSE;
/* note: if subclass indicates MAX fsize, /* note: if subclass indicates MAX fsize,
* this will not likely be available anyway ... */ * this will not likely be available anyway ... */
@ -3166,11 +3170,15 @@ gst_base_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
* but interpolate in between */ * but interpolate in between */
pts = gst_adapter_prev_pts (parse->priv->adapter, NULL); pts = gst_adapter_prev_pts (parse->priv->adapter, NULL);
dts = gst_adapter_prev_dts (parse->priv->adapter, NULL); dts = gst_adapter_prev_dts (parse->priv->adapter, NULL);
if (GST_CLOCK_TIME_IS_VALID (pts) && (parse->priv->prev_pts != pts)) if (GST_CLOCK_TIME_IS_VALID (pts) && (parse->priv->prev_pts != pts)) {
parse->priv->prev_pts = parse->priv->next_pts = pts; parse->priv->prev_pts = parse->priv->next_pts = pts;
updated_prev_pts = TRUE;
}
if (GST_CLOCK_TIME_IS_VALID (dts) && (parse->priv->prev_dts != dts)) if (GST_CLOCK_TIME_IS_VALID (dts) && (parse->priv->prev_dts != dts)) {
parse->priv->prev_dts = parse->priv->next_dts = dts; parse->priv->prev_dts = parse->priv->next_dts = dts;
parse->priv->prev_dts_from_pts = FALSE;
}
/* we can mess with, erm interpolate, timestamps, /* we can mess with, erm interpolate, timestamps,
* and incoming stuff has PTS but no DTS seen so far, * and incoming stuff has PTS but no DTS seen so far,
@ -3178,9 +3186,12 @@ gst_base_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
if (parse->priv->infer_ts && if (parse->priv->infer_ts &&
parse->priv->pts_interpolate && parse->priv->pts_interpolate &&
!GST_CLOCK_TIME_IS_VALID (dts) && !GST_CLOCK_TIME_IS_VALID (dts) &&
!GST_CLOCK_TIME_IS_VALID (parse->priv->prev_dts) && (!GST_CLOCK_TIME_IS_VALID (parse->priv->prev_dts)
GST_CLOCK_TIME_IS_VALID (pts)) || (parse->priv->prev_dts_from_pts && updated_prev_pts))
&& GST_CLOCK_TIME_IS_VALID (pts)) {
parse->priv->prev_dts = parse->priv->next_dts = pts; parse->priv->prev_dts = parse->priv->next_dts = pts;
parse->priv->prev_dts_from_pts = TRUE;
}
/* always pass all available data */ /* always pass all available data */
tmpbuf = gst_adapter_get_buffer (parse->priv->adapter, av); tmpbuf = gst_adapter_get_buffer (parse->priv->adapter, av);
@ -4847,8 +4858,10 @@ gst_base_parse_set_ts_at_offset (GstBaseParse * parse, gsize offset)
if (GST_CLOCK_TIME_IS_VALID (pts) && (parse->priv->prev_pts != pts)) if (GST_CLOCK_TIME_IS_VALID (pts) && (parse->priv->prev_pts != pts))
parse->priv->prev_pts = parse->priv->next_pts = pts; parse->priv->prev_pts = parse->priv->next_pts = pts;
if (GST_CLOCK_TIME_IS_VALID (dts) && (parse->priv->prev_dts != dts)) if (GST_CLOCK_TIME_IS_VALID (dts) && (parse->priv->prev_dts != dts)) {
parse->priv->prev_dts = parse->priv->next_dts = dts; parse->priv->prev_dts = parse->priv->next_dts = dts;
parse->priv->prev_dts_from_pts = FALSE;
}
} }
/** /**