basesink: improve duration calculation

Keep track of the average distance between incomming timestamps and
use that to estimate the frame duration when buffers have no duration set on
them.
This commit is contained in:
Wim Taymans 2011-02-14 14:00:38 +01:00
parent 79665e8247
commit f8828eace6

View file

@ -196,6 +196,8 @@ struct _GstBaseSinkPrivate
GstClockTime current_rstart; GstClockTime current_rstart;
GstClockTime current_rstop; GstClockTime current_rstop;
GstClockTimeDiff current_jitter; GstClockTimeDiff current_jitter;
/* the running time of the previous buffer */
GstClockTime prev_rstart;
/* EOS sync time in running time */ /* EOS sync time in running time */
GstClockTime eos_rtime; GstClockTime eos_rtime;
@ -209,6 +211,7 @@ struct _GstBaseSinkPrivate
GstClockTime avg_pt; GstClockTime avg_pt;
GstClockTime avg_duration; GstClockTime avg_duration;
gdouble avg_rate; gdouble avg_rate;
GstClockTime avg_in_diff;
/* these are done on system time. avg_jitter and avg_render are /* these are done on system time. avg_jitter and avg_render are
* compared to eachother to see if the rendering time takes a * compared to eachother to see if the rendering time takes a
@ -2491,6 +2494,23 @@ do_step:
/* save sync time for eos when the previous object needed sync */ /* save sync time for eos when the previous object needed sync */
priv->eos_rtime = (do_sync ? priv->current_rstop : GST_CLOCK_TIME_NONE); priv->eos_rtime = (do_sync ? priv->current_rstop : GST_CLOCK_TIME_NONE);
/* calculate inter frame spacing */
if (G_UNLIKELY (priv->prev_rstart != -1 && priv->prev_rstart < rstart)) {
GstClockTime in_diff;
in_diff = rstart - priv->prev_rstart;
if (priv->avg_in_diff == -1)
priv->avg_in_diff = in_diff;
else
priv->avg_in_diff = UPDATE_RUNNING_AVG (priv->avg_in_diff, in_diff);
GST_LOG_OBJECT (basesink, "avg frame diff %" GST_TIME_FORMAT,
GST_TIME_ARGS (priv->avg_in_diff));
}
priv->prev_rstart = rstart;
if (G_UNLIKELY (priv->earliest_in_time != -1 if (G_UNLIKELY (priv->earliest_in_time != -1
&& rstart < priv->earliest_in_time)) && rstart < priv->earliest_in_time))
goto qos_dropped; goto qos_dropped;
@ -2663,7 +2683,7 @@ gst_base_sink_perform_qos (GstBaseSink * sink, gboolean dropped)
if (GST_CLOCK_TIME_IS_VALID (stop) && stop != start) if (GST_CLOCK_TIME_IS_VALID (stop) && stop != start)
duration = stop - start; duration = stop - start;
else else
duration = GST_CLOCK_TIME_NONE; duration = priv->avg_in_diff;
/* if we have the time when the last buffer left us, calculate /* if we have the time when the last buffer left us, calculate
* processing time */ * processing time */
@ -2765,12 +2785,14 @@ gst_base_sink_reset_qos (GstBaseSink * sink)
priv = sink->priv; priv = sink->priv;
priv->last_render_time = GST_CLOCK_TIME_NONE; priv->last_render_time = GST_CLOCK_TIME_NONE;
priv->prev_rstart = GST_CLOCK_TIME_NONE;
priv->earliest_in_time = GST_CLOCK_TIME_NONE; priv->earliest_in_time = GST_CLOCK_TIME_NONE;
priv->last_left = GST_CLOCK_TIME_NONE; priv->last_left = GST_CLOCK_TIME_NONE;
priv->avg_duration = GST_CLOCK_TIME_NONE; priv->avg_duration = GST_CLOCK_TIME_NONE;
priv->avg_pt = GST_CLOCK_TIME_NONE; priv->avg_pt = GST_CLOCK_TIME_NONE;
priv->avg_rate = -1.0; priv->avg_rate = -1.0;
priv->avg_render = GST_CLOCK_TIME_NONE; priv->avg_render = GST_CLOCK_TIME_NONE;
priv->avg_in_diff = GST_CLOCK_TIME_NONE;
priv->rendered = 0; priv->rendered = 0;
priv->dropped = 0; priv->dropped = 0;
@ -2819,8 +2841,12 @@ gst_base_sink_is_too_late (GstBaseSink * basesink, GstMiniObject * obj,
/* we can add a valid stop time */ /* we can add a valid stop time */
if (GST_CLOCK_TIME_IS_VALID (rstop)) if (GST_CLOCK_TIME_IS_VALID (rstop))
max_lateness += rstop; max_lateness += rstop;
else else {
max_lateness += rstart; max_lateness += rstart;
/* no stop time, use avg frame diff */
if (priv->avg_in_diff != -1)
max_lateness += priv->avg_in_diff;
}
/* if the jitter bigger than duration and lateness we are too late */ /* if the jitter bigger than duration and lateness we are too late */
if ((late = rstart + jitter > max_lateness)) { if ((late = rstart + jitter > max_lateness)) {