summaryrefslogtreecommitdiff
path: root/sys/decklink
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian@centricular.com>2015-02-09 16:18:03 +0100
committerSebastian Dröge <sebastian@centricular.com>2015-02-09 16:22:39 +0100
commit4de7fdfa3a664a1880566e43b95a92f5ed8d8bb2 (patch)
tree565c3b52a915fb899d15482b8461f74ba568a552 /sys/decklink
parenta6bcd09b6c8266bd9adbffa9902eedf43ffa724f (diff)
downloadgstreamer-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.cpp60
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)