diff options
author | Nirbheek Chauhan <nirbheek@centricular.com> | 2017-05-09 16:06:10 +0530 |
---|---|---|
committer | Nirbheek Chauhan <nirbheek@centricular.com> | 2017-05-12 14:51:10 +0530 |
commit | 8494f1e709649234c6c7ed4ededd7a9a5f4852a3 (patch) | |
tree | e76a47fe0d24fd148bfd96f20a81f4787c290b54 /sys/directsound/gstdirectsoundsrc.c | |
parent | 6026d12d90e5b86da1110ecd8873a7fcdcc43348 (diff) | |
download | gstreamer-plugins-bad-8494f1e709649234c6c7ed4ededd7a9a5f4852a3.tar.gz |
directsoundsrc: Use a GstClockID to wait instead of Sleep()
The main advantage is that our sleeps can be interrupted in case of
an src_reset(). Earlier, we would need to wait for a read to complete
before we could do a reset, which could take a long time.
https://bugzilla.gnome.org/show_bug.cgi?id=781249
Diffstat (limited to 'sys/directsound/gstdirectsoundsrc.c')
-rw-r--r-- | sys/directsound/gstdirectsoundsrc.c | 56 |
1 files changed, 44 insertions, 12 deletions
diff --git a/sys/directsound/gstdirectsoundsrc.c b/sys/directsound/gstdirectsoundsrc.c index 24821ec02..087efcd73 100644 --- a/sys/directsound/gstdirectsoundsrc.c +++ b/sys/directsound/gstdirectsoundsrc.c @@ -163,6 +163,9 @@ gst_directsound_src_finalize (GObject * object) GstDirectSoundSrc *dsoundsrc = GST_DIRECTSOUND_SRC (object); g_mutex_clear (&dsoundsrc->dsound_lock); + gst_object_unref (dsoundsrc->system_clock); + if (dsoundsrc->read_wait_clock_id != NULL) + gst_clock_id_unref (dsoundsrc->read_wait_clock_id); g_free (dsoundsrc->device_name); @@ -321,6 +324,9 @@ gst_directsound_src_init (GstDirectSoundSrc * src) { GST_DEBUG_OBJECT (src, "initializing directsoundsrc"); g_mutex_init (&src->dsound_lock); + src->system_clock = gst_system_clock_obtain (); + src->read_wait_clock_id = NULL; + src->reset_while_sleeping = FALSE; src->device_guid = NULL; src->device_id = NULL; src->device_name = NULL; @@ -647,8 +653,8 @@ gst_directsound_src_read (GstAudioSrc * asrc, gpointer data, guint length, GstClockTime * timestamp) { GstDirectSoundSrc *dsoundsrc; - guint64 sleep_time_ms; - guint64 slept_time_ms = 0; + guint64 sleep_time_ms, sleep_until; + GstClockID clock_id; HRESULT hRes; /* Result for windows functions */ DWORD dwCurrentCaptureCursor = 0; @@ -684,7 +690,7 @@ gst_directsound_src_read (GstAudioSrc * asrc, gpointer data, guint length, } /* Loop till the source has produced bytes equal to or greater than @length. - * + * * DirectSound has a notification-based API that uses Windows CreateEvent() * + WaitForSingleObject(), but it is completely useless for live streams. * @@ -730,15 +736,40 @@ gst_directsound_src_read (GstAudioSrc * asrc, gpointer data, guint length, length - dwBufferSize, length * 1000); /* Make sure we don't run in a tight loop unnecessarily */ sleep_time_ms = MAX (sleep_time_ms, 10); - GST_DEBUG_OBJECT (asrc, "sleeping for %" G_GUINT64_FORMAT "ms", + /* Sleep using gst_clock_id_wait() so that we can be interrupted */ + sleep_until = gst_clock_get_time (dsoundsrc->system_clock) + + sleep_time_ms * GST_MSECOND; + /* Setup the clock id wait */ + if (G_UNLIKELY (dsoundsrc->read_wait_clock_id == NULL || + gst_clock_single_shot_id_reinit (dsoundsrc->system_clock, + dsoundsrc->read_wait_clock_id, sleep_until) == FALSE)) { + if (dsoundsrc->read_wait_clock_id != NULL) + gst_clock_id_unref (dsoundsrc->read_wait_clock_id); + dsoundsrc->read_wait_clock_id = + gst_clock_new_single_shot_id (dsoundsrc->system_clock, sleep_until); + } + + clock_id = dsoundsrc->read_wait_clock_id; + dsoundsrc->reset_while_sleeping = FALSE; + + GST_DEBUG_OBJECT (asrc, "waiting %" G_GUINT64_FORMAT "ms for more data", sleep_time_ms); - Sleep (sleep_time_ms); - slept_time_ms += sleep_time_ms; + GST_DSOUND_UNLOCK (dsoundsrc); + + gst_clock_id_wait (clock_id, NULL); + + GST_DSOUND_LOCK (dsoundsrc); + + if (dsoundsrc->reset_while_sleeping == TRUE) { + GST_DEBUG_OBJECT (asrc, "reset while sleeping, cancelled read"); + GST_DSOUND_UNLOCK (dsoundsrc); + return -1; + } } } - GST_DEBUG_OBJECT (asrc, "Got enough data: %lu bytes (wanted at least %u), " - "slept for %" G_GUINT64_FORMAT "ms", dwBufferSize, length, slept_time_ms); + GST_DEBUG_OBJECT (asrc, "Got enough data: %lu bytes (wanted at least %u)", + dwBufferSize, length); /* Lock the buffer and read only the first @length bytes. Keep the rest in * the capture buffer for the next read. */ @@ -819,12 +850,13 @@ gst_directsound_src_reset (GstAudioSrc * asrc) dsoundsrc = GST_DIRECTSOUND_SRC (asrc); -#if 0 - IDirectSoundCaptureBuffer_Stop (dsoundsrc->pDSBSecondary); -#endif - GST_DSOUND_LOCK (dsoundsrc); + dsoundsrc->reset_while_sleeping = TRUE; + /* Interrupt read sleep if required */ + if (dsoundsrc->read_wait_clock_id != NULL) + gst_clock_id_unschedule (dsoundsrc->read_wait_clock_id); + if (dsoundsrc->pDSBSecondary) { /*stop capturing */ HRESULT hRes = IDirectSoundCaptureBuffer_Stop (dsoundsrc->pDSBSecondary); |