From e2ff5587fe36823a8677ce1d3374b9ac8d00e4e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 28 Jan 2015 15:26:17 +0100 Subject: [PATCH] decklink{audio,video}src: Only start the streams once both sources are ready and we are in PLAYING Otherwise we might start the streams before the audio or video streams are actually enabled, and then error out later because they are enabled to late. We enable the streams when getting the caps, which might be *after* we were set to PLAYING state. --- sys/decklink/gstdecklink.h | 3 +- sys/decklink/gstdecklinkaudiosrc.cpp | 4 +++ sys/decklink/gstdecklinkvideosrc.cpp | 45 ++++++++++++++++++++-------- 3 files changed, 38 insertions(+), 14 deletions(-) diff --git a/sys/decklink/gstdecklink.h b/sys/decklink/gstdecklink.h index c85f8b24e5..e58987e4b0 100644 --- a/sys/decklink/gstdecklink.h +++ b/sys/decklink/gstdecklink.h @@ -148,7 +148,6 @@ struct _GstDecklinkOutput { /* Set by the audio sink */ GstClock *audio_clock; - /* */ GstElement *audiosink; gboolean audio_enabled; GstElement *videosink; @@ -176,11 +175,11 @@ struct _GstDecklinkInput { /* Set by the audio source */ void (*got_audio_packet) (GstElement *videosrc, IDeckLinkAudioInputPacket * packet, GstClockTime capture_time); - /* */ GstElement *audiosrc; gboolean audio_enabled; GstElement *videosrc; gboolean video_enabled; + void (*start_streams) (GstElement *videosrc); }; GstDecklinkOutput * gst_decklink_acquire_nth_output (gint n, GstElement * sink, gboolean is_audio); diff --git a/sys/decklink/gstdecklinkaudiosrc.cpp b/sys/decklink/gstdecklinkaudiosrc.cpp index 99b8a0fc37..1a63f379be 100644 --- a/sys/decklink/gstdecklinkaudiosrc.cpp +++ b/sys/decklink/gstdecklinkaudiosrc.cpp @@ -381,6 +381,8 @@ gst_decklink_audio_src_set_caps (GstBaseSrc * bsrc, GstCaps * caps) g_mutex_lock (&self->input->lock); self->input->audio_enabled = TRUE; + if (self->input->start_streams) + self->input->start_streams (self->input->videosrc); g_mutex_unlock (&self->input->lock); return TRUE; @@ -657,6 +659,8 @@ gst_decklink_audio_src_close (GstDecklinkAudioSrc * self) g_mutex_lock (&self->input->lock); self->input->got_audio_packet = NULL; self->input->audio_enabled = FALSE; + if (self->input->start_streams) + self->input->start_streams (self->input->videosrc); g_mutex_unlock (&self->input->lock); self->input->input->DisableAudioInput (); diff --git a/sys/decklink/gstdecklinkvideosrc.cpp b/sys/decklink/gstdecklinkvideosrc.cpp index 095a7c65f0..e015c5d32a 100644 --- a/sys/decklink/gstdecklinkvideosrc.cpp +++ b/sys/decklink/gstdecklinkvideosrc.cpp @@ -100,6 +100,8 @@ static GstFlowReturn gst_decklink_video_src_create (GstPushSrc * psrc, static gboolean gst_decklink_video_src_open (GstDecklinkVideoSrc * self); static gboolean gst_decklink_video_src_close (GstDecklinkVideoSrc * self); +static void gst_decklink_video_src_start_streams (GstElement * element); + #define parent_class gst_decklink_video_src_parent_class G_DEFINE_TYPE (GstDecklinkVideoSrc, gst_decklink_video_src, GST_TYPE_PUSH_SRC); @@ -329,6 +331,8 @@ gst_decklink_video_src_set_caps (GstBaseSrc * bsrc, GstCaps * caps) g_mutex_lock (&self->input->lock); self->input->mode = mode; self->input->video_enabled = TRUE; + if (self->input->start_streams) + self->input->start_streams (self->input->videosrc); g_mutex_unlock (&self->input->lock); return TRUE; @@ -551,6 +555,7 @@ gst_decklink_video_src_open (GstDecklinkVideoSrc * self) g_mutex_lock (&self->input->lock); self->input->mode = mode; self->input->got_video_frame = gst_decklink_video_src_got_frame; + self->input->start_streams = gst_decklink_video_src_start_streams; self->input->clock_start_time = GST_CLOCK_TIME_NONE; self->input->clock_last_time = 0; self->input->clock_offset = 0; @@ -570,6 +575,8 @@ gst_decklink_video_src_close (GstDecklinkVideoSrc * self) self->input->got_video_frame = NULL; self->input->mode = NULL; self->input->video_enabled = FALSE; + if (self->input->start_streams) + self->input->start_streams (self->input->videosrc); g_mutex_unlock (&self->input->lock); self->input->input->DisableVideoInput (); @@ -581,6 +588,29 @@ gst_decklink_video_src_close (GstDecklinkVideoSrc * self) return TRUE; } +static void +gst_decklink_video_src_start_streams (GstElement * element) +{ + GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (element); + HRESULT res; + + if (self->input->video_enabled && (!self->input->audiosrc + || self->input->audio_enabled) + && GST_STATE (self) == GST_STATE_PLAYING) { + GST_DEBUG_OBJECT (self, "Starting streams"); + res = self->input->input->StartStreams (); + if (res != S_OK) { + GST_ELEMENT_ERROR (self, STREAM, FAILED, + (NULL), ("Failed to start streams: 0x%08x", res)); + return; + } + self->input->started = TRUE; + self->input->clock_restart = TRUE; + } else { + GST_DEBUG_OBJECT (self, "Not starting streams yet"); + } +} + static GstStateChangeReturn gst_decklink_video_src_change_state (GstElement * element, GstStateChange transition) @@ -588,7 +618,6 @@ gst_decklink_video_src_change_state (GstElement * element, GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (element); GstStateChangeReturn ret; - switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: if (!gst_decklink_video_src_open (self)) { @@ -660,19 +689,11 @@ gst_decklink_video_src_change_state (GstElement * element, break; } case GST_STATE_CHANGE_PAUSED_TO_PLAYING:{ - HRESULT res; - - GST_DEBUG_OBJECT (self, "Starting streams"); - res = self->input->input->StartStreams (); - if (res != S_OK) { - GST_ELEMENT_ERROR (self, STREAM, FAILED, - (NULL), ("Failed to start streams: 0x%08x", res)); - ret = GST_STATE_CHANGE_FAILURE; - } g_mutex_lock (&self->input->lock); - self->input->started = TRUE; - self->input->clock_restart = TRUE; + if (self->input->start_streams) + self->input->start_streams (self->input->videosrc); g_mutex_unlock (&self->input->lock); + break; } case GST_STATE_CHANGE_READY_TO_NULL: