gst-libs/gst/audio/gstbaseaudiosink.c: When skew slaving, try to hover around the middle of a segment so that we at m...

Original commit message from CVS:
* gst-libs/gst/audio/gstbaseaudiosink.c:
(gst_base_audio_sink_skew_slaving), (gst_base_audio_sink_render),
(gst_base_audio_sink_change_state):
When skew slaving, try to hover around the middle of a segment so that
we at most drift by half a segment.
If we are aligning in the oposite direction of the clock skew, we don't
have to resync.
This commit is contained in:
Wim Taymans 2007-09-03 19:17:33 +00:00
parent 210100078d
commit c2460052b3
2 changed files with 56 additions and 12 deletions

View file

@ -1,3 +1,13 @@
2007-09-03 Wim Taymans <wim.taymans@gmail.com>
* gst-libs/gst/audio/gstbaseaudiosink.c:
(gst_base_audio_sink_skew_slaving), (gst_base_audio_sink_render),
(gst_base_audio_sink_change_state):
When skew slaving, try to hover around the middle of a segment so that
we at most drift by half a segment.
If we are aligning in the oposite direction of the clock skew, we don't
have to resync.
2007-08-31 Wim Taymans <wim.taymans@gmail.com> 2007-08-31 Wim Taymans <wim.taymans@gmail.com>
* gst-libs/gst/rtp/gstbasertpdepayload.c: * gst-libs/gst/rtp/gstbasertpdepayload.c:

View file

@ -50,6 +50,8 @@ struct _GstBaseAudioSinkPrivate
GstBaseAudioSinkSlaveMethod slave_method; GstBaseAudioSinkSlaveMethod slave_method;
/* running average of clock skew */ /* running average of clock skew */
GstClockTimeDiff avg_skew; GstClockTimeDiff avg_skew;
/* the number of samples we aligned last time */
gint64 last_align;
}; };
/* BaseAudioSink signals and args */ /* BaseAudioSink signals and args */
@ -754,7 +756,9 @@ gst_base_audio_sink_skew_slaving (GstBaseAudioSink * sink,
{ {
GstClockTime cinternal, cexternal, crate_num, crate_denom; GstClockTime cinternal, cexternal, crate_num, crate_denom;
GstClockTime etime, itime; GstClockTime etime, itime;
GstClockTimeDiff skew, segtime; GstClockTimeDiff skew, segtime, segtime2;
gint segsamples;
gint64 last_align;
/* get calibration parameters to compensate for offsets */ /* get calibration parameters to compensate for offsets */
gst_clock_get_calibration (sink->provided_clock, &cinternal, &cexternal, gst_clock_get_calibration (sink->provided_clock, &cinternal, &cexternal,
@ -782,26 +786,55 @@ gst_base_audio_sink_skew_slaving (GstBaseAudioSink * sink,
/* the max drift we allow is the length of a segment */ /* the max drift we allow is the length of a segment */
segtime = sink->ringbuffer->spec.latency_time * 1000; segtime = sink->ringbuffer->spec.latency_time * 1000;
segtime2 = segtime / 2;
/* adjust playout pointer based on skew */ /* adjust playout pointer based on skew */
if (sink->priv->avg_skew > segtime) { if (sink->priv->avg_skew > segtime2) {
/* master is running slower, move internal time forward */ /* master is running slower, move internal time forward */
GST_WARNING_OBJECT (sink, GST_WARNING_OBJECT (sink,
"correct clock skew %" G_GINT64_FORMAT " > %" G_GINT64_FORMAT, "correct clock skew %" G_GINT64_FORMAT " > %" G_GINT64_FORMAT,
sink->priv->avg_skew, segtime); sink->priv->avg_skew, segtime2);
cinternal += segtime; cinternal += segtime;
sink->priv->avg_skew -= segtime; sink->priv->avg_skew -= segtime;
sink->next_sample = -1;
segsamples =
sink->ringbuffer->spec.segsize /
sink->ringbuffer->spec.bytes_per_sample;
last_align = sink->priv->last_align;
/* if we were aligning in the wrong direction or we aligned more than what we
* will correct, resync */
if (last_align < 0 || last_align > segsamples)
sink->next_sample = -1;
GST_DEBUG_OBJECT (sink,
"last_align %" G_GINT64_FORMAT " segsamples %u, next %"
G_GUINT64_FORMAT, last_align, segsamples, sink->next_sample);
gst_clock_set_calibration (sink->provided_clock, cinternal, cexternal, gst_clock_set_calibration (sink->provided_clock, cinternal, cexternal,
crate_num, crate_denom); crate_num, crate_denom);
} else if (sink->priv->avg_skew < -segtime) { } else if (sink->priv->avg_skew < -segtime2) {
/* master is running faster, move external time forwards */ /* master is running faster, move external time forwards */
GST_WARNING_OBJECT (sink, GST_WARNING_OBJECT (sink,
"correct clock skew %" G_GINT64_FORMAT " < %" G_GINT64_FORMAT, "correct clock skew %" G_GINT64_FORMAT " < %" G_GINT64_FORMAT,
sink->priv->avg_skew, -segtime); sink->priv->avg_skew, -segtime2);
cexternal += segtime; cexternal += segtime;
sink->priv->avg_skew += segtime; sink->priv->avg_skew += segtime;
sink->next_sample = -1;
segsamples =
sink->ringbuffer->spec.segsize /
sink->ringbuffer->spec.bytes_per_sample;
last_align = sink->priv->last_align;
/* if we were aligning in the wrong direction or we aligned more than what we
* will correct, resync */
if (last_align > 0 || -last_align > segsamples)
sink->next_sample = -1;
GST_DEBUG_OBJECT (sink,
"last_align %" G_GINT64_FORMAT " segsamples %u, next %"
G_GUINT64_FORMAT, last_align, segsamples, sink->next_sample);
gst_clock_set_calibration (sink->provided_clock, cinternal, cexternal, gst_clock_set_calibration (sink->provided_clock, cinternal, cexternal,
crate_num, crate_denom); crate_num, crate_denom);
} }
@ -973,8 +1006,7 @@ gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf)
"after latency: start %" GST_TIME_FORMAT " - stop %" GST_TIME_FORMAT, "after latency: start %" GST_TIME_FORMAT " - stop %" GST_TIME_FORMAT,
GST_TIME_ARGS (render_start), GST_TIME_ARGS (render_stop)); GST_TIME_ARGS (render_start), GST_TIME_ARGS (render_stop));
slaved = clock != sink->provided_clock; if ((slaved = clock != sink->provided_clock)) {
if (slaved) {
/* handle clock slaving */ /* handle clock slaving */
gst_base_audio_sink_handle_slaving (sink, render_start, render_stop, gst_base_audio_sink_handle_slaving (sink, render_start, render_stop,
&render_start, &render_stop); &render_start, &render_stop);
@ -1016,11 +1048,11 @@ gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf)
* and sample offset position. We always resync if we got a discont anyway and * and sample offset position. We always resync if we got a discont anyway and
* non-discont should be aligned by definition. */ * non-discont should be aligned by definition. */
if (G_LIKELY (diff < ringbuf->spec.rate / DIFF_TOLERANCE)) { if (G_LIKELY (diff < ringbuf->spec.rate / DIFF_TOLERANCE)) {
GST_DEBUG_OBJECT (sink,
"align with prev sample, %" G_GINT64_FORMAT " < %d", diff,
ringbuf->spec.rate / DIFF_TOLERANCE);
/* calc align with previous sample */ /* calc align with previous sample */
align = sink->next_sample - sample_offset; align = sink->next_sample - sample_offset;
GST_DEBUG_OBJECT (sink,
"align with prev sample, ABS (%" G_GINT64_FORMAT ") < %d", align,
ringbuf->spec.rate / DIFF_TOLERANCE);
} else { } else {
/* bring sample diff to seconds for error message */ /* bring sample diff to seconds for error message */
diff = gst_util_uint64_scale_int (diff, GST_SECOND, ringbuf->spec.rate); diff = gst_util_uint64_scale_int (diff, GST_SECOND, ringbuf->spec.rate);
@ -1033,6 +1065,7 @@ gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf)
GST_TIME_ARGS (diff))); GST_TIME_ARGS (diff)));
align = 0; align = 0;
} }
sink->priv->last_align = align;
/* apply alignment */ /* apply alignment */
render_start += align; render_start += align;
@ -1314,6 +1347,7 @@ gst_base_audio_sink_change_state (GstElement * element,
break; break;
case GST_STATE_CHANGE_READY_TO_PAUSED: case GST_STATE_CHANGE_READY_TO_PAUSED:
sink->next_sample = -1; sink->next_sample = -1;
sink->priv->last_align = -1;
gst_ring_buffer_set_flushing (sink->ringbuffer, FALSE); gst_ring_buffer_set_flushing (sink->ringbuffer, FALSE);
gst_ring_buffer_may_start (sink->ringbuffer, FALSE); gst_ring_buffer_may_start (sink->ringbuffer, FALSE);
break; break;