mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-11 19:06:33 +00:00
gst-libs/gst/audio/gstbaseaudiosrc.c: Implement skew clock slaving. Fixes #552559.
Original commit message from CVS: Patch by: Håvard Graff <havard dot graff at tandberg dot com> * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_create): Implement skew clock slaving. Fixes #552559.
This commit is contained in:
parent
dd01a1e56a
commit
11086cf6f8
2 changed files with 121 additions and 3 deletions
|
@ -1,3 +1,11 @@
|
||||||
|
2008-10-08 Wim Taymans <wim.taymans@collabora.co.uk>
|
||||||
|
|
||||||
|
Patch by: Håvard Graff <havard dot graff at tandberg dot com>
|
||||||
|
|
||||||
|
* gst-libs/gst/audio/gstbaseaudiosrc.c:
|
||||||
|
(gst_base_audio_src_create):
|
||||||
|
Implement skew clock slaving. Fixes #552559.
|
||||||
|
|
||||||
2008-10-08 Wim Taymans <wim.taymans@collabora.co.uk>
|
2008-10-08 Wim Taymans <wim.taymans@collabora.co.uk>
|
||||||
|
|
||||||
* gst-libs/gst/audio/multichannel.c:
|
* gst-libs/gst/audio/multichannel.c:
|
||||||
|
|
|
@ -823,12 +823,122 @@ gst_base_audio_src_create (GstBaseSrc * bsrc, guint64 offset, guint length,
|
||||||
/* we are slaved, check how to handle this */
|
/* we are slaved, check how to handle this */
|
||||||
switch (src->priv->slave_method) {
|
switch (src->priv->slave_method) {
|
||||||
case GST_BASE_AUDIO_SRC_SLAVE_RESAMPLE:
|
case GST_BASE_AUDIO_SRC_SLAVE_RESAMPLE:
|
||||||
/* not implemented, use retimestamp algorithm. This algorithm should
|
/* not implemented, use skew algorithm. This algorithm should
|
||||||
* work on the readout pointer and produces more or less samples based
|
* work on the readout pointer and produces more or less samples based
|
||||||
* on the clock drift */
|
* on the clock drift */
|
||||||
case GST_BASE_AUDIO_SRC_SLAVE_SKEW:
|
case GST_BASE_AUDIO_SRC_SLAVE_SKEW:
|
||||||
/* not implemented, use retimestamp algorithm. This algortihm should work
|
{
|
||||||
* on the readout pointer above and creates small jumps when needed. */
|
GstClockTime running_time;
|
||||||
|
GstClockTime base_time;
|
||||||
|
GstClockTime current_time;
|
||||||
|
guint64 running_time_sample;
|
||||||
|
gint running_time_segment;
|
||||||
|
gint current_segment;
|
||||||
|
gint segment_skew;
|
||||||
|
gint sps;
|
||||||
|
|
||||||
|
/* samples per segment */
|
||||||
|
sps = ringbuffer->samples_per_seg;
|
||||||
|
|
||||||
|
/* get the current time */
|
||||||
|
current_time = gst_clock_get_time (clock);
|
||||||
|
|
||||||
|
/* get the basetime */
|
||||||
|
base_time = GST_ELEMENT_CAST (src)->base_time;
|
||||||
|
|
||||||
|
/* get the running_time */
|
||||||
|
running_time = current_time - base_time;
|
||||||
|
|
||||||
|
/* the running_time converted to a sample (relative to the ringbuffer) */
|
||||||
|
running_time_sample =
|
||||||
|
gst_util_uint64_scale_int (running_time, spec->rate, GST_SECOND);
|
||||||
|
|
||||||
|
/* the segmentnr corrensponding to running_time, round down */
|
||||||
|
running_time_segment = running_time_sample / sps;
|
||||||
|
|
||||||
|
/* the segment currently read from the ringbuffer */
|
||||||
|
current_segment = sample / sps;
|
||||||
|
|
||||||
|
/* the skew we have between running_time and the ringbuffertime */
|
||||||
|
segment_skew = running_time_segment - current_segment;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (bsrc, "\n running_time = % " GST_TIME_FORMAT
|
||||||
|
"\n timestamp = % " GST_TIME_FORMAT
|
||||||
|
"\n running_time_segment = %d"
|
||||||
|
"\n current_segment = %d"
|
||||||
|
"\n segment_skew = %d",
|
||||||
|
GST_TIME_ARGS (running_time),
|
||||||
|
GST_TIME_ARGS (timestamp),
|
||||||
|
running_time_segment, current_segment, segment_skew);
|
||||||
|
|
||||||
|
/* Resync the ringbuffer if:
|
||||||
|
* 1. We get one segment into the future.
|
||||||
|
* This is clearly a lie, because we can't
|
||||||
|
* possibly have a buffer with timestamp 1 at
|
||||||
|
* time 0. (unless it has time-travelled...)
|
||||||
|
*
|
||||||
|
* 2. We are more than the length of the ringbuffer behind.
|
||||||
|
* The length of the ringbuffer then gets to dictate
|
||||||
|
* the threshold for what is concidered "too late"
|
||||||
|
*
|
||||||
|
* 3. If this is our first buffer.
|
||||||
|
* We know that we should catch up to running_time
|
||||||
|
* the first time we are ran.
|
||||||
|
*/
|
||||||
|
if ((segment_skew < 0) ||
|
||||||
|
(segment_skew >= ringbuffer->spec.segtotal) ||
|
||||||
|
(current_segment == 0)) {
|
||||||
|
gint segments_written;
|
||||||
|
gint first_segment;
|
||||||
|
gint last_segment;
|
||||||
|
gint new_last_segment;
|
||||||
|
gint segment_diff;
|
||||||
|
gint new_first_segment;
|
||||||
|
guint64 new_sample;
|
||||||
|
|
||||||
|
/* we are going to say that the last segment was captured at the current time
|
||||||
|
(running_time), minus one segment of creation-latency in the ringbuffer.
|
||||||
|
This can be thought of as: The segment arrived in the ringbuffer at time X, and
|
||||||
|
that means it was created at time X - (one segment). */
|
||||||
|
new_last_segment = running_time_segment - 1;
|
||||||
|
|
||||||
|
/* for better readablity */
|
||||||
|
first_segment = current_segment;
|
||||||
|
|
||||||
|
/* get the amount of segments written from the device by now */
|
||||||
|
segments_written = g_atomic_int_get (&ringbuffer->segdone);
|
||||||
|
|
||||||
|
/* subtract the base to segments_written to get the number of the
|
||||||
|
last written segment in the ringbuffer (one segment written = segment 0) */
|
||||||
|
last_segment = segments_written - ringbuffer->segbase - 1;
|
||||||
|
|
||||||
|
/* we see how many segments the ringbuffer was timeshifted */
|
||||||
|
segment_diff = new_last_segment - last_segment;
|
||||||
|
|
||||||
|
/* we move the first segment an equal amount */
|
||||||
|
new_first_segment = first_segment + segment_diff;
|
||||||
|
|
||||||
|
/* and we also move the segmentbase the same amount */
|
||||||
|
ringbuffer->segbase -= segment_diff;
|
||||||
|
|
||||||
|
/* we calculate the new sample value */
|
||||||
|
new_sample = new_first_segment * sps;
|
||||||
|
|
||||||
|
/* and get the relative time to this -> our new timestamp */
|
||||||
|
timestamp =
|
||||||
|
gst_util_uint64_scale_int (new_sample, GST_SECOND, spec->rate);
|
||||||
|
|
||||||
|
/* we update the next sample accordingly */
|
||||||
|
src->next_sample = new_sample + samples;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (bsrc,
|
||||||
|
"Timeshifted the ringbuffer with %d segments: "
|
||||||
|
"Updating the timestamp to % " GST_TIME_FORMAT ", "
|
||||||
|
"and src->next_sample to % " G_GUINT64_FORMAT, segment_diff,
|
||||||
|
GST_TIME_ARGS (timestamp), src->next_sample);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case GST_BASE_AUDIO_SRC_SLAVE_RETIMESTAMP:
|
case GST_BASE_AUDIO_SRC_SLAVE_RETIMESTAMP:
|
||||||
{
|
{
|
||||||
GstClockTime base_time, latency;
|
GstClockTime base_time, latency;
|
||||||
|
|
Loading…
Reference in a new issue