diff options
author | Sebastian Dröge <sebastian@centricular.com> | 2015-02-09 16:18:03 +0100 |
---|---|---|
committer | Sebastian Dröge <sebastian@centricular.com> | 2015-02-09 16:22:39 +0100 |
commit | 4de7fdfa3a664a1880566e43b95a92f5ed8d8bb2 (patch) | |
tree | 565c3b52a915fb899d15482b8461f74ba568a552 /sys/decklink | |
parent | a6bcd09b6c8266bd9adbffa9902eedf43ffa724f (diff) | |
download | gstreamer-plugins-bad-4de7fdfa3a664a1880566e43b95a92f5ed8d8bb2.tar.gz |
decklinkaudiosink: Throttle reading from the ringbuffer
The driver has an internal buffer of unspecified and unconfigurable size, and
it will pull data from our ring buffer as fast as it can until that is full.
Unfortunately that means that we pull silence from the ringbuffer unless its
size is by conincidence larger than the driver's internal ringbuffer.
The good news is that it's not required to completely fill the buffer for
proper playback. So we now throttle reading from the ringbuffer whenever
the driver has buffered more than half of our ringbuffer size by waiting
on the clock for the amount of time until it has buffered less than that
again.
Diffstat (limited to 'sys/decklink')
-rw-r--r-- | sys/decklink/gstdecklinkaudiosink.cpp | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/sys/decklink/gstdecklinkaudiosink.cpp b/sys/decklink/gstdecklinkaudiosink.cpp index 2e6d871cd..e4a0ec809 100644 --- a/sys/decklink/gstdecklinkaudiosink.cpp +++ b/sys/decklink/gstdecklinkaudiosink.cpp @@ -54,6 +54,9 @@ struct _GstDecklinkAudioSinkRingBuffer GstDecklinkOutput *output; GstDecklinkAudioSink *sink; + + GMutex clock_id_lock; + GstClockID clock_id; }; struct _GstDecklinkAudioSinkRingBufferClass @@ -122,6 +125,7 @@ static void static void gst_decklink_audio_sink_ringbuffer_init (GstDecklinkAudioSinkRingBuffer * self) { + g_mutex_init (&self->clock_id_lock); } static void @@ -132,6 +136,7 @@ gst_decklink_audio_sink_ringbuffer_finalize (GObject * object) gst_object_unref (self->sink); self->sink = NULL; + g_mutex_clear (&self->clock_id_lock); G_OBJECT_CLASS (ringbuffer_parent_class)->finalize (object); } @@ -193,10 +198,60 @@ public: gint bpf; guint written, written_sum; HRESULT res; + const GstAudioRingBufferSpec *spec = + &GST_AUDIO_RING_BUFFER_CAST (m_ringbuffer)->spec; + guint delay, max_delay; GST_LOG_OBJECT (m_ringbuffer->sink, "Writing audio samples (preroll: %d)", preroll); + delay = + gst_audio_ring_buffer_delay (GST_AUDIO_RING_BUFFER_CAST (m_ringbuffer)); + max_delay = MAX ((spec->segtotal * spec->segsize) / 2, spec->segsize); + max_delay /= GST_AUDIO_INFO_BPF (&spec->info); + if (delay > max_delay) { + GstClock *clock = + gst_element_get_clock (GST_ELEMENT_CAST (m_ringbuffer->sink)); + GstClockTime wait_time; + GstClockID clock_id; + GstClockReturn clock_ret; + + GST_DEBUG_OBJECT (m_ringbuffer->sink, "Delay %u > max delay %u", delay, + max_delay); + + wait_time = + gst_util_uint64_scale (delay - max_delay, GST_SECOND, + GST_AUDIO_INFO_RATE (&spec->info)); + GST_DEBUG_OBJECT (m_ringbuffer->sink, "Waiting for %" GST_TIME_FORMAT, + GST_TIME_ARGS (wait_time)); + wait_time += gst_clock_get_time (clock); + + g_mutex_lock (&m_ringbuffer->clock_id_lock); + if (!GST_AUDIO_RING_BUFFER_CAST (m_ringbuffer)->acquired) { + GST_DEBUG_OBJECT (m_ringbuffer->sink, + "Ringbuffer not acquired anymore"); + g_mutex_unlock (&m_ringbuffer->clock_id_lock); + gst_object_unref (clock); + return S_OK; + } + clock_id = gst_clock_new_single_shot_id (clock, wait_time); + m_ringbuffer->clock_id = clock_id; + g_mutex_unlock (&m_ringbuffer->clock_id_lock); + gst_object_unref (clock); + + clock_ret = gst_clock_id_wait (clock_id, NULL); + + g_mutex_lock (&m_ringbuffer->clock_id_lock); + gst_clock_id_unref (clock_id); + m_ringbuffer->clock_id = NULL; + g_mutex_unlock (&m_ringbuffer->clock_id_lock); + + if (clock_ret == GST_CLOCK_UNSCHEDULED) { + GST_DEBUG_OBJECT (m_ringbuffer->sink, "Flushing"); + return S_OK; + } + } + if (!gst_audio_ring_buffer_prepare_read (GST_AUDIO_RING_BUFFER_CAST (m_ringbuffer), &seg, &ptr, &len)) { GST_WARNING_OBJECT (m_ringbuffer->sink, "No segment available"); @@ -392,6 +447,11 @@ gst_decklink_audio_sink_ringbuffer_release (GstAudioRingBuffer * rb) GST_DEBUG_OBJECT (self->sink, "Release"); if (self->output) { + g_mutex_lock (&self->clock_id_lock); + if (self->clock_id) + gst_clock_id_unschedule (self->clock_id); + g_mutex_unlock (&self->clock_id_lock); + g_mutex_lock (&self->output->lock); self->output->audio_enabled = FALSE; if (self->output->start_scheduled_playback) |