decklinkvideosink: Wait until scheduled playback is actually stopped before continuing

Otherwise we might "start" again, just to get finally stopped and then
getting errors all over the place.

https://bugzilla.gnome.org/show_bug.cgi?id=790114
This commit is contained in:
Sebastian Dröge 2017-11-22 10:42:37 +02:00
parent 2b39d1876e
commit 02e4d92cbf
3 changed files with 28 additions and 2 deletions

View file

@ -1152,6 +1152,10 @@ init_devices (gpointer data)
i = 0; i = 0;
ret = iterator->Next (&decklink); ret = iterator->Next (&decklink);
while (ret == S_OK) { while (ret == S_OK) {
g_mutex_init (&devices[i].input.lock);
g_mutex_init (&devices[i].output.lock);
g_cond_init (&devices[i].output.cond);
ret = decklink->QueryInterface (IID_IDeckLinkInput, ret = decklink->QueryInterface (IID_IDeckLinkInput,
(void **) &devices[i].input.input); (void **) &devices[i].input.input);
if (ret != S_OK) { if (ret != S_OK) {

View file

@ -215,10 +215,12 @@ struct _GstDecklinkOutput {
GstClock *clock; GstClock *clock;
GstClockTime clock_start_time, clock_last_time, clock_epoch; GstClockTime clock_start_time, clock_last_time, clock_epoch;
GstClockTimeDiff clock_offset; GstClockTimeDiff clock_offset;
gboolean started, clock_restart; gboolean started;
gboolean clock_restart;
/* Everything below protected by mutex */ /* Everything below protected by mutex */
GMutex lock; GMutex lock;
GCond cond;
/* Set by the video source */ /* Set by the video source */
/* Configured mode or NULL */ /* Configured mode or NULL */

View file

@ -100,6 +100,12 @@ public:
{ {
GST_LOG_OBJECT (m_sink, "Scheduled playback stopped"); GST_LOG_OBJECT (m_sink, "Scheduled playback stopped");
if (m_sink->output) {
g_mutex_lock (&m_sink->output->lock);
g_cond_signal (&m_sink->output->cond);
g_mutex_unlock (&m_sink->output->lock);
}
return S_OK; return S_OK;
} }
@ -900,6 +906,12 @@ gst_decklink_video_sink_start_scheduled_playback (GstElement * element)
gst_object_unref (clock); gst_object_unref (clock);
return; return;
} }
// Wait until scheduled playback actually stopped
do {
g_cond_wait (&self->output->cond, &self->output->lock);
self->output->output->IsScheduledPlaybackRunning (&active);
} while (active);
} }
GST_DEBUG_OBJECT (self, GST_DEBUG_OBJECT (self,
@ -976,16 +988,24 @@ gst_decklink_video_sink_stop_scheduled_playback (GstDecklinkVideoSink * self)
g_mutex_lock (&self->output->lock); g_mutex_lock (&self->output->lock);
self->output->started = FALSE; self->output->started = FALSE;
g_mutex_unlock (&self->output->lock);
res = self->output->output->StopScheduledPlayback (start_time, 0, GST_SECOND); res = self->output->output->StopScheduledPlayback (start_time, 0, GST_SECOND);
if (res != S_OK) { if (res != S_OK) {
GST_ELEMENT_ERROR (self, STREAM, FAILED, GST_ELEMENT_ERROR (self, STREAM, FAILED,
(NULL), ("Failed to stop scheduled playback: 0x%08lx", (unsigned long) (NULL), ("Failed to stop scheduled playback: 0x%08lx", (unsigned long)
res)); res));
ret = GST_STATE_CHANGE_FAILURE; ret = GST_STATE_CHANGE_FAILURE;
} else {
bool active = false;
// Wait until scheduled playback actually stopped
do {
g_cond_wait (&self->output->cond, &self->output->lock);
self->output->output->IsScheduledPlaybackRunning (&active);
} while (active);
} }
self->internal_base_time = GST_CLOCK_TIME_NONE; self->internal_base_time = GST_CLOCK_TIME_NONE;
self->external_base_time = GST_CLOCK_TIME_NONE; self->external_base_time = GST_CLOCK_TIME_NONE;
g_mutex_unlock (&self->output->lock);
return ret; return ret;
} }