From f8828eace691a20f37a7dcad7766ab3e6e13331c Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 14 Feb 2011 14:00:38 +0100 Subject: [PATCH] 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. --- libs/gst/base/gstbasesink.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/libs/gst/base/gstbasesink.c b/libs/gst/base/gstbasesink.c index ede235bd83..040c25f82c 100644 --- a/libs/gst/base/gstbasesink.c +++ b/libs/gst/base/gstbasesink.c @@ -196,6 +196,8 @@ struct _GstBaseSinkPrivate GstClockTime current_rstart; GstClockTime current_rstop; GstClockTimeDiff current_jitter; + /* the running time of the previous buffer */ + GstClockTime prev_rstart; /* EOS sync time in running time */ GstClockTime eos_rtime; @@ -209,6 +211,7 @@ struct _GstBaseSinkPrivate GstClockTime avg_pt; GstClockTime avg_duration; gdouble avg_rate; + GstClockTime avg_in_diff; /* these are done on system time. avg_jitter and avg_render are * 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 */ 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 && rstart < priv->earliest_in_time)) 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) duration = stop - start; else - duration = GST_CLOCK_TIME_NONE; + duration = priv->avg_in_diff; /* if we have the time when the last buffer left us, calculate * processing time */ @@ -2765,12 +2785,14 @@ gst_base_sink_reset_qos (GstBaseSink * sink) priv = sink->priv; priv->last_render_time = GST_CLOCK_TIME_NONE; + priv->prev_rstart = GST_CLOCK_TIME_NONE; priv->earliest_in_time = GST_CLOCK_TIME_NONE; priv->last_left = GST_CLOCK_TIME_NONE; priv->avg_duration = GST_CLOCK_TIME_NONE; priv->avg_pt = GST_CLOCK_TIME_NONE; priv->avg_rate = -1.0; priv->avg_render = GST_CLOCK_TIME_NONE; + priv->avg_in_diff = GST_CLOCK_TIME_NONE; priv->rendered = 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 */ if (GST_CLOCK_TIME_IS_VALID (rstop)) max_lateness += rstop; - else + else { 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 ((late = rstart + jitter > max_lateness)) {