gst-libs/gst/audio/gstbaseaudiosink.c: patch to make timestamp checking more tollerant to rounding errors given that ...

Original commit message from CVS:
* gst-libs/gst/audio/gstbaseaudiosink.c:
(gst_base_audio_sink_drain), (gst_base_audio_sink_event),
(gst_base_audio_sink_render), (gst_base_audio_sink_change_state):
patch to make timestamp checking more tollerant to rounding
errors given that real discontinuities are to be marked on
buffers. Fixes some asf files and #338778.
Also avoid some crashers when we receive an event in the
NULL state.
This commit is contained in:
Wim Taymans 2006-04-28 15:08:09 +00:00
parent ea8b333274
commit 102b79e46e
2 changed files with 38 additions and 12 deletions

View file

@ -1,3 +1,14 @@
2006-04-28 Wim Taymans <wim@fluendo.com>
* gst-libs/gst/audio/gstbaseaudiosink.c:
(gst_base_audio_sink_drain), (gst_base_audio_sink_event),
(gst_base_audio_sink_render), (gst_base_audio_sink_change_state):
patch to make timestamp checking more tollerant to rounding
errors given that real discontinuities are to be marked on
buffers. Fixes some asf files and #338778.
Also avoid some crashers when we receive an event in the
NULL state.
2006-04-28 Michael Smith <msmith@fluendo.com> 2006-04-28 Michael Smith <msmith@fluendo.com>
* ext/gnomevfs/gstgnomevfssrc.c: (gst_gnome_vfs_src_class_init), * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnome_vfs_src_class_init),

View file

@ -34,10 +34,14 @@ enum
LAST_SIGNAL LAST_SIGNAL
}; };
/* we tollerate a 10th of a second diff before we start resyncing. This /* we tollerate half a second diff before we start resyncing. This
* should be enough to compensate for various rounding errors in the timestamp * should be enough to compensate for various rounding errors in the timestamp
* and sample offset position. */ * and sample offset position.
#define DIFF_TOLERANCE 10 * This is an emergency resync fallback since buffers marked as DISCONT will
* always lock to the correct timestamp immediatly and buffers not marked as
* DISCONT are contiguous bu definition.
*/
#define DIFF_TOLERANCE 2
#define DEFAULT_BUFFER_TIME 200 * GST_USECOND #define DEFAULT_BUFFER_TIME 200 * GST_USECOND
#define DEFAULT_LATENCY_TIME 10 * GST_USECOND #define DEFAULT_LATENCY_TIME 10 * GST_USECOND
@ -361,6 +365,12 @@ gst_base_audio_sink_drain (GstBaseAudioSink * sink)
if (!sink->ringbuffer->spec.rate) if (!sink->ringbuffer->spec.rate)
return TRUE; return TRUE;
/* need to start playback before we can drain, but only when
* we have successfully negotiated a format and thus aqcuired the
* ringbuffer. */
if (gst_ring_buffer_is_acquired (sink->ringbuffer))
gst_ring_buffer_start (sink->ringbuffer);
if (sink->next_sample != -1) { if (sink->next_sample != -1) {
GstClockTime time; GstClockTime time;
GstClock *clock; GstClock *clock;
@ -394,18 +404,16 @@ gst_base_audio_sink_event (GstBaseSink * bsink, GstEvent * event)
switch (GST_EVENT_TYPE (event)) { switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_FLUSH_START: case GST_EVENT_FLUSH_START:
gst_ring_buffer_set_flushing (sink->ringbuffer, TRUE); if (sink->ringbuffer)
gst_ring_buffer_set_flushing (sink->ringbuffer, TRUE);
break; break;
case GST_EVENT_FLUSH_STOP: case GST_EVENT_FLUSH_STOP:
/* always resync on sample after a flush */ /* always resync on sample after a flush */
sink->next_sample = -1; sink->next_sample = -1;
gst_ring_buffer_set_flushing (sink->ringbuffer, FALSE); if (sink->ringbuffer)
gst_ring_buffer_set_flushing (sink->ringbuffer, FALSE);
break; break;
case GST_EVENT_EOS: case GST_EVENT_EOS:
/* need to start playback when we reach EOS, but only when
* we have successfully negotiated a format. */
if (gst_ring_buffer_is_acquired (sink->ringbuffer))
gst_ring_buffer_start (sink->ringbuffer);
/* now wait till we played everything */ /* now wait till we played everything */
gst_base_audio_sink_drain (sink); gst_base_audio_sink_drain (sink);
break; break;
@ -583,9 +591,10 @@ gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf)
if (G_LIKELY (sink->next_sample != -1)) { if (G_LIKELY (sink->next_sample != -1)) {
diff = ABS ((gint64) render_offset - (gint64) sink->next_sample); diff = ABS ((gint64) render_offset - (gint64) sink->next_sample);
/* we tollerate a 10th of a second diff before we start resyncing. This /* we tollerate half a second diff before we start resyncing. This
* should be enough to compensate for various rounding errors in the timestamp * should be enough to compensate for various rounding errors in the timestamp
* and sample offset position. We always resync if we got a discont anyway. */ * and sample offset position. We always resync if we got a discont anyway and
* non-discont should be aligned by definition. */
if (diff < ringbuf->spec.rate / DIFF_TOLERANCE) { if (diff < ringbuf->spec.rate / DIFF_TOLERANCE) {
GST_DEBUG_OBJECT (sink, GST_DEBUG_OBJECT (sink,
"align with prev sample, %" G_GINT64_FORMAT " < %lu", diff, "align with prev sample, %" G_GINT64_FORMAT " < %lu", diff,
@ -593,7 +602,9 @@ gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf)
/* just align with previous sample then */ /* just align with previous sample then */
render_offset = sink->next_sample; render_offset = sink->next_sample;
} else { } else {
GST_DEBUG_OBJECT (sink, /* timestamps drifted apart from previous samples too much, we need to
* resync. */
GST_WARNING_OBJECT (sink,
"resync after discont with previous sample of diff: %lu", diff); "resync after discont with previous sample of diff: %lu", diff);
} }
} else { } else {
@ -787,6 +798,8 @@ gst_base_audio_sink_change_state (GstElement * element,
GST_OBJECT_UNLOCK (sink); GST_OBJECT_UNLOCK (sink);
break; break;
case GST_STATE_CHANGE_PAUSED_TO_READY: case GST_STATE_CHANGE_PAUSED_TO_READY:
/* make sure we unblock before calling the parent state change
* so it can grab the STREAM_LOCK */
gst_ring_buffer_set_flushing (sink->ringbuffer, TRUE); gst_ring_buffer_set_flushing (sink->ringbuffer, TRUE);
break; break;
default: default:
@ -813,8 +826,10 @@ gst_base_audio_sink_change_state (GstElement * element,
return ret; return ret;
/* ERRORS */
open_failed: open_failed:
{ {
/* subclass must post a meaningfull error message */
GST_DEBUG_OBJECT (sink, "open failed"); GST_DEBUG_OBJECT (sink, "open failed");
return GST_STATE_CHANGE_FAILURE; return GST_STATE_CHANGE_FAILURE;
} }