From 0f2336cff6bf32922dd99236d3363598a0c4261c Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 21 Nov 2005 17:14:02 +0000 Subject: [PATCH] gst/: Segment update fix. Original commit message from CVS: * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_class_init), (gst_base_audio_sink_init), (gst_base_audio_sink_provide_clock), (gst_base_audio_sink_set_clock), (gst_base_audio_sink_render), (gst_base_audio_sink_change_state): * gst/audioresample/gstaudioresample.c: Segment update fix. --- ChangeLog | 10 ++++ gst-libs/gst/audio/gstbaseaudiosink.c | 73 ++++++++++++++++++++------- gst/audioresample/gstaudioresample.c | 4 +- 3 files changed, 67 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3b2ae24261..c972406e14 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2005-11-21 Wim Taymans + + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_class_init), (gst_base_audio_sink_init), + (gst_base_audio_sink_provide_clock), + (gst_base_audio_sink_set_clock), (gst_base_audio_sink_render), + (gst_base_audio_sink_change_state): + * gst/audioresample/gstaudioresample.c: + Segment update fix. + 2005-11-21 Andy Wingo * *.h: diff --git a/gst-libs/gst/audio/gstbaseaudiosink.c b/gst-libs/gst/audio/gstbaseaudiosink.c index 032e003535..3ae18ddf35 100644 --- a/gst-libs/gst/audio/gstbaseaudiosink.c +++ b/gst-libs/gst/audio/gstbaseaudiosink.c @@ -65,6 +65,7 @@ static GstStateChangeReturn gst_base_audio_sink_change_state (GstElement * element, GstStateChange transition); static GstClock *gst_base_audio_sink_provide_clock (GstElement * elem); +static void gst_base_audio_sink_set_clock (GstElement * elem, GstClock * clock); static GstClockTime gst_base_audio_sink_get_time (GstClock * clock, GstBaseAudioSink * sink); static void gst_base_audio_sink_callback (GstRingBuffer * rbuf, guint8 * data, @@ -118,6 +119,8 @@ gst_base_audio_sink_class_init (GstBaseAudioSinkClass * klass) GST_DEBUG_FUNCPTR (gst_base_audio_sink_change_state); gstelement_class->provide_clock = GST_DEBUG_FUNCPTR (gst_base_audio_sink_provide_clock); + gstelement_class->set_clock = + GST_DEBUG_FUNCPTR (gst_base_audio_sink_set_clock); gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_base_audio_sink_event); gstbasesink_class->preroll = GST_DEBUG_FUNCPTR (gst_base_audio_sink_preroll); @@ -134,10 +137,8 @@ gst_base_audio_sink_init (GstBaseAudioSink * baseaudiosink, baseaudiosink->buffer_time = DEFAULT_BUFFER_TIME; baseaudiosink->latency_time = DEFAULT_LATENCY_TIME; - baseaudiosink->clock = gst_audio_clock_new ("clock", (GstAudioClockGetTimeFunc) gst_base_audio_sink_get_time, baseaudiosink); - } static void @@ -166,15 +167,27 @@ gst_base_audio_sink_provide_clock (GstElement * elem) sink = GST_BASE_AUDIO_SINK (elem); -#if 1 clock = GST_CLOCK_CAST (gst_object_ref (sink->clock)); -#else - clock = gst_system_clock_obtain (); -#endif return clock; } +static void +gst_base_audio_sink_set_clock (GstElement * elem, GstClock * clock) +{ + GstBaseAudioSink *sink; + + sink = GST_BASE_AUDIO_SINK (elem); + + GST_OBJECT_LOCK (sink); + if (clock != sink->clock) { + gst_clock_set_master (sink->clock, clock); + } else { + gst_clock_set_master (sink->clock, NULL); + } + GST_OBJECT_UNLOCK (sink); +} + static GstClockTime gst_base_audio_sink_get_time (GstClock * clock, GstBaseAudioSink * sink) { @@ -385,6 +398,8 @@ gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf) guint size; guint samples; gint bps; + gdouble crate; + GstClockTime cinternal, cexternal; sink = GST_BASE_AUDIO_SINK (bsink); @@ -408,7 +423,7 @@ gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf) data = GST_BUFFER_DATA (buf); GST_DEBUG ("time %" GST_TIME_FORMAT ", offset %llu, start %" GST_TIME_FORMAT, - GST_TIME_ARGS (time), in_offset, GST_TIME_ARGS (bsink->segment_start)); + GST_TIME_ARGS (time), in_offset, GST_TIME_ARGS (bsink->segment.start)); /* if not valid timestamp or we don't need to sync, try to play * sample ASAP */ @@ -417,23 +432,30 @@ gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf) goto no_sync; } - render_diff = time - bsink->segment_start; + render_diff = time - bsink->segment.start; /* samples should be rendered based on their timestamp. All samples - * arriving before the segment_start are to be thrown away */ + * arriving before the segment.start are to be thrown away */ /* FIXME, for now we drop the sample completely, we should - * in fact clip the sample. Same for the segment_stop, actually. */ + * in fact clip the sample. Same for the segment.stop, actually. */ if (render_diff < 0) goto out_of_segment; + gst_clock_get_calibration (sink->clock, &cinternal, &cexternal, &crate); + GST_DEBUG_OBJECT (sink, + "internal %" G_GUINT64_FORMAT ", %" G_GUINT64_FORMAT ", rate %g", + cinternal, cexternal, crate); + /* bring buffer timestamp to stream time */ render_time = render_diff; /* adjust for rate */ - render_time /= ABS (bsink->segment_rate); + render_time /= ABS (bsink->segment.rate); /* adjust for accumulated segments */ - render_time += bsink->segment_accum; + render_time += bsink->segment.accum; /* add base time to get absolute clock time */ - render_time += gst_element_get_base_time (GST_ELEMENT_CAST (bsink)); + render_time += + (gst_element_get_base_time (GST_ELEMENT_CAST (bsink)) - cexternal) + + cinternal; /* and bring the time to the offset in the buffer */ render_offset = render_time * ringbuf->spec.rate / GST_SECOND; @@ -461,14 +483,14 @@ gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf) no_sync: /* clip length based on rate */ - samples = MIN (samples, samples / ABS (bsink->segment_rate)); + samples = MIN (samples, samples / (crate * ABS (bsink->segment.rate))); /* the next sample should be current sample and its length */ sink->next_sample = render_offset + samples; gst_ring_buffer_commit (ringbuf, render_offset, data, samples); - if (GST_CLOCK_TIME_IS_VALID (time) && time + duration >= bsink->segment_stop) { + if (GST_CLOCK_TIME_IS_VALID (time) && time + duration >= bsink->segment.stop) { GST_DEBUG ("start playback because we are at the end of segment"); gst_ring_buffer_start (ringbuf); } @@ -479,7 +501,7 @@ out_of_segment: { GST_DEBUG ("dropping sample out of segment time %" GST_TIME_FORMAT ", start %" GST_TIME_FORMAT, - GST_TIME_ARGS (time), GST_TIME_ARGS (bsink->segment_start)); + GST_TIME_ARGS (time), GST_TIME_ARGS (bsink->segment.start)); return GST_FLOW_OK; } wrong_state: @@ -544,6 +566,23 @@ gst_base_audio_sink_change_state (GstElement * element, gst_ring_buffer_set_flushing (sink->ringbuffer, FALSE); break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + { + GstClockTime time; + gdouble rate; + + time = gst_clock_get_internal_time (sink->clock); + + GST_DEBUG_OBJECT (sink, "time: %" GST_TIME_FORMAT, GST_TIME_ARGS (time)); + + gst_clock_get_calibration (sink->clock, NULL, NULL, &rate); + /* Does not work yet. + gst_clock_set_calibration (sink->clock, + time, element->base_time, rate); + */ + break; + } + case GST_STATE_CHANGE_PAUSED_TO_READY: + gst_ring_buffer_set_flushing (sink->ringbuffer, TRUE); break; default: break; @@ -556,8 +595,6 @@ gst_base_audio_sink_change_state (GstElement * element, gst_ring_buffer_pause (sink->ringbuffer); break; case GST_STATE_CHANGE_PAUSED_TO_READY: - gst_ring_buffer_set_flushing (sink->ringbuffer, TRUE); - gst_ring_buffer_stop (sink->ringbuffer); gst_ring_buffer_release (sink->ringbuffer); gst_pad_set_caps (GST_BASE_SINK_PAD (sink), NULL); break; diff --git a/gst/audioresample/gstaudioresample.c b/gst/audioresample/gstaudioresample.c index c141c1a21f..6077a610d0 100644 --- a/gst/audioresample/gstaudioresample.c +++ b/gst/audioresample/gstaudioresample.c @@ -399,7 +399,7 @@ static GstFlowReturn outsize, outsamples); GST_BUFFER_OFFSET (outbuf) = audioresample->offset; - GST_BUFFER_TIMESTAMP (outbuf) = base->segment_start + + GST_BUFFER_TIMESTAMP (outbuf) = base->segment.start + audioresample->offset * GST_SECOND / audioresample->o_rate; audioresample->offset += outsamples; @@ -408,7 +408,7 @@ static GstFlowReturn /* we calculate DURATION as the difference between "next" timestamp * and current timestamp so we ensure a contiguous stream, instead of * having rounding errors. */ - GST_BUFFER_DURATION (outbuf) = base->segment_start + + GST_BUFFER_DURATION (outbuf) = base->segment.start + audioresample->offset * GST_SECOND / audioresample->o_rate - GST_BUFFER_TIMESTAMP (outbuf);