From: Wim Taymans Date: Fri, 9 May 2008 16:38:10 +0000 (+0000) Subject: gst-libs/gst/audio/gstaudiosink.c: Choose to allocate one less segment but require... X-Git-Tag: RELEASE-0_10_20~108 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=fc523e047ceefcba5db19b94bcfd66289a409374;p=platform%2Fupstream%2Fgst-plugins-base.git gst-libs/gst/audio/gstaudiosink.c: Choose to allocate one less segment but require one additional segment as latency. Original commit message from CVS: * gst-libs/gst/audio/gstaudiosink.c: (gst_audioringbuffer_acquire): Choose to allocate one less segment but require one additional segment as latency. * gst-libs/gst/audio/gstaudiosrc.c: (gst_audioringbuffer_acquire): No need to increment the number of segments in the source. * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_get_time), (clock_convert_external), (gst_base_audio_sink_resample_slaving), (gst_base_audio_sink_skew_slaving), (gst_base_audio_sink_none_slaving), (gst_base_audio_sink_render), (gst_base_audio_sink_async_play): Remove adding latency when returning the internal time while subtracting it again when we use the value a little later. When calculating the end timestamp, we are making a rounding error with the current algorithm. Ensure that we don't accumulate these rounding errors when aligning samples by not resampling at all if we don't need to. Fixes #419351. Make the initial calibration of the clock slaving a little more predictable and accurate. Also handle the case where we don't do clock slaving. --- diff --git a/ChangeLog b/ChangeLog index 139a9a1..09a24cf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +2008-05-09 Wim Taymans + + * gst-libs/gst/audio/gstaudiosink.c: (gst_audioringbuffer_acquire): + Choose to allocate one less segment but require one additional segment + as latency. + + * gst-libs/gst/audio/gstaudiosrc.c: (gst_audioringbuffer_acquire): + No need to increment the number of segments in the source. + + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_get_time), (clock_convert_external), + (gst_base_audio_sink_resample_slaving), + (gst_base_audio_sink_skew_slaving), + (gst_base_audio_sink_none_slaving), (gst_base_audio_sink_render), + (gst_base_audio_sink_async_play): + Remove adding latency when returning the internal time while subtracting + it again when we use the value a little later. + When calculating the end timestamp, we are making a rounding error + with the current algorithm. Ensure that we don't accumulate these + rounding errors when aligning samples by not resampling at all if we + don't need to. Fixes #419351. + Make the initial calibration of the clock slaving a little more + predictable and accurate. Also handle the case where we don't do + clock slaving. + 2008-05-09 Sebastian Dröge Based on a patch by: diff --git a/gst-libs/gst/audio/gstaudiosink.c b/gst-libs/gst/audio/gstaudiosink.c index fd10b83..39e71ea 100644 --- a/gst-libs/gst/audio/gstaudiosink.c +++ b/gst-libs/gst/audio/gstaudiosink.c @@ -366,8 +366,8 @@ gst_audioringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec) if (!result) goto could_not_prepare; - /* allocate one more segment as we need some headroom */ - spec->segtotal++; + /* set latency to one more segment as we need some headroom */ + spec->seglatency = spec->segtotal + 1; buf->data = gst_buffer_new_and_alloc (spec->segtotal * spec->segsize); memset (GST_BUFFER_DATA (buf->data), 0, GST_BUFFER_SIZE (buf->data)); diff --git a/gst-libs/gst/audio/gstaudiosrc.c b/gst-libs/gst/audio/gstaudiosrc.c index 2587035..2afb397 100644 --- a/gst-libs/gst/audio/gstaudiosrc.c +++ b/gst-libs/gst/audio/gstaudiosrc.c @@ -360,9 +360,6 @@ gst_audioringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec) if (!result) goto could_not_open; - /* allocate one more segment as we need some headroom */ - spec->segtotal++; - buf->data = gst_buffer_new_and_alloc (spec->segtotal * spec->segsize); memset (GST_BUFFER_DATA (buf->data), 0, GST_BUFFER_SIZE (buf->data)); diff --git a/gst-libs/gst/audio/gstbaseaudiosink.c b/gst-libs/gst/audio/gstbaseaudiosink.c index c889c69..82abaf4 100644 --- a/gst-libs/gst/audio/gstbaseaudiosink.c +++ b/gst-libs/gst/audio/gstbaseaudiosink.c @@ -371,7 +371,7 @@ gst_base_audio_sink_get_time (GstClock * clock, GstBaseAudioSink * sink) { guint64 raw, samples; guint delay; - GstClockTime result, us_latency; + GstClockTime result; if (sink->ringbuffer == NULL || sink->ringbuffer->spec.rate == 0) return GST_CLOCK_TIME_NONE; @@ -391,15 +391,9 @@ gst_base_audio_sink_get_time (GstClock * clock, GstBaseAudioSink * sink) result = gst_util_uint64_scale_int (samples, GST_SECOND, sink->ringbuffer->spec.rate); - /* latency before starting the clock */ - us_latency = sink->priv->us_latency; - - result += us_latency; - GST_DEBUG_OBJECT (sink, "processed samples: raw %llu, delay %u, real %llu, time %" - GST_TIME_FORMAT ", upstream latency %" GST_TIME_FORMAT, raw, delay, - samples, GST_TIME_ARGS (result), GST_TIME_ARGS (us_latency)); + GST_TIME_FORMAT, raw, delay, samples, GST_TIME_ARGS (result)); return result; } @@ -787,8 +781,7 @@ gst_base_audio_sink_get_offset (GstBaseAudioSink * sink) static GstClockTime clock_convert_external (GstClockTime external, GstClockTime cinternal, - GstClockTime cexternal, GstClockTime crate_num, GstClockTime crate_denom, - GstClockTime us_latency) + GstClockTime cexternal, GstClockTime crate_num, GstClockTime crate_denom) { /* adjust for rate and speed */ if (external >= cexternal) { @@ -803,12 +796,6 @@ clock_convert_external (GstClockTime external, GstClockTime cinternal, else external = 0; } - /* adjust for offset when slaving started */ - if (external > us_latency) - external -= us_latency; - else - external = 0; - return external; } @@ -838,9 +825,9 @@ gst_base_audio_sink_resample_slaving (GstBaseAudioSink * sink, /* bring external time to internal time */ render_start = clock_convert_external (render_start, cinternal, cexternal, - crate_num, crate_denom, sink->priv->us_latency); + crate_num, crate_denom); render_stop = clock_convert_external (render_stop, cinternal, cexternal, - crate_num, crate_denom, sink->priv->us_latency); + crate_num, crate_denom); GST_DEBUG_OBJECT (sink, "after slaving: start %" GST_TIME_FORMAT " - stop %" GST_TIME_FORMAT, @@ -875,6 +862,9 @@ gst_base_audio_sink_skew_slaving (GstBaseAudioSink * sink, etime = etime > cexternal ? etime - cexternal : 0; itime = itime > cinternal ? itime - cinternal : 0; + /* do itime - etime. + * positive value means external clock goes slower + * negative value means external clock goes faster */ skew = GST_CLOCK_DIFF (etime, itime); if (sink->priv->avg_skew == -1) { /* first observation */ @@ -945,9 +935,9 @@ gst_base_audio_sink_skew_slaving (GstBaseAudioSink * sink, /* convert, ignoring speed */ render_start = clock_convert_external (render_start, cinternal, cexternal, - crate_num, crate_denom, sink->priv->us_latency); + crate_num, crate_denom); render_stop = clock_convert_external (render_stop, cinternal, cexternal, - crate_num, crate_denom, sink->priv->us_latency); + crate_num, crate_denom); *srender_start = render_start; *srender_stop = render_stop; @@ -967,9 +957,9 @@ gst_base_audio_sink_none_slaving (GstBaseAudioSink * sink, /* convert, ignoring speed */ render_start = clock_convert_external (render_start, cinternal, cexternal, - crate_num, crate_denom, sink->priv->us_latency); + crate_num, crate_denom); render_stop = clock_convert_external (render_stop, cinternal, cexternal, - crate_num, crate_denom, sink->priv->us_latency); + crate_num, crate_denom); *srender_start = render_start; *srender_stop = render_stop; @@ -1153,26 +1143,34 @@ gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf) render_stop = gst_util_uint64_scale_int (render_stop, ringbuf->spec.rate, GST_SECOND); + /* positive playback rate, first sample is render_start, negative rate, first + * sample is render_stop. When no rate conversion is active, render exactly + * the amount of input samples to avoid aligning to rounding errors. */ + if (bsink->segment.rate >= 0.0) { + sample_offset = render_start; + if (bsink->segment.rate == 1.0) + render_stop = sample_offset + samples; + } else { + sample_offset = render_stop; + if (bsink->segment.rate == -1.0) + render_start = sample_offset + samples; + } + /* always resync after a discont */ if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT))) { GST_DEBUG_OBJECT (sink, "resync after discont"); goto no_align; } + /* resync when we don't know what to align the sample with */ if (G_UNLIKELY (sink->next_sample == -1)) { GST_DEBUG_OBJECT (sink, "no align possible: no previous sample position known"); goto no_align; } - /* positive playback rate, first sample is render_start, negative rate, first - * sample is render_stop */ - if (bsink->segment.rate >= 0.0) - sample_offset = render_start; - else - sample_offset = render_stop; - - /* now try to align the sample to the previous one */ + /* now try to align the sample to the previous one, first see how big the + * difference is. */ if (sample_offset >= sink->next_sample) diff = sample_offset - sink->next_sample; else @@ -1422,12 +1420,22 @@ gst_base_audio_sink_async_play (GstBaseSink * basesink) /* if we are slaved to a clock, we need to set the initial * calibration */ /* get external and internal time to set as calibration params */ - etime = gst_clock_get_time (clock); - itime = gst_clock_get_internal_time (sink->provided_clock); - - sink->priv->avg_skew = -1; - sink->next_sample = -1; + etime = GST_ELEMENT_CAST (sink)->base_time; + itime = gst_base_audio_sink_get_time (sink->provided_clock, sink); + switch (sink->priv->slave_method) { + case GST_BASE_AUDIO_SINK_SLAVE_SKEW: + case GST_BASE_AUDIO_SINK_SLAVE_RESAMPLE: + /* adjust with upstream latency, when we are prerolled, our internal clock + * should exactly have been the time of the upstream latency */ + etime += sink->priv->us_latency; + break; + case GST_BASE_AUDIO_SINK_SLAVE_NONE: + /* no slaving, base_time corresponds to our 0 time */ + itime = 0; + default: + break; + } GST_DEBUG_OBJECT (sink, "internal time: %" GST_TIME_FORMAT " external time: %" GST_TIME_FORMAT, GST_TIME_ARGS (itime), GST_TIME_ARGS (etime)); @@ -1439,14 +1447,19 @@ gst_base_audio_sink_async_play (GstBaseSink * basesink) switch (sink->priv->slave_method) { case GST_BASE_AUDIO_SINK_SLAVE_RESAMPLE: - /* only set as master if we need to resample */ + /* only set as master when we are resampling */ GST_DEBUG_OBJECT (sink, "Setting clock as master"); gst_clock_set_master (sink->provided_clock, clock); break; + case GST_BASE_AUDIO_SINK_SLAVE_SKEW: + case GST_BASE_AUDIO_SINK_SLAVE_NONE: default: break; } + sink->priv->avg_skew = -1; + sink->next_sample = -1; + /* start ringbuffer so we can start slaving right away when we need to */ gst_ring_buffer_start (sink->ringbuffer);