diff --git a/sys/decklink/gstdecklink.h b/sys/decklink/gstdecklink.h index 9954591a60..465d3685a3 100644 --- a/sys/decklink/gstdecklink.h +++ b/sys/decklink/gstdecklink.h @@ -121,6 +121,10 @@ struct _GstDecklinkOutput { /* Everything below protected by mutex */ GMutex lock; + /* Set by the video source */ + /* Configured mode or NULL */ + const GstDecklinkMode *mode; + /* Set by the audio sink */ GstClock *audio_clock; @@ -141,6 +145,8 @@ struct _GstDecklinkInput { /* Set by the video source */ void (*got_video_frame) (GstElement *videosrc, IDeckLinkVideoInputFrame * frame, GstClockTime capture_time); + /* Configured mode or NULL */ + const GstDecklinkMode *mode; /* Set by the audio source */ void (*got_audio_packet) (GstElement *videosrc, IDeckLinkAudioInputPacket * packet, GstClockTime capture_time); diff --git a/sys/decklink/gstdecklinkaudiosink.cpp b/sys/decklink/gstdecklinkaudiosink.cpp index da4b85203a..325f7098b4 100644 --- a/sys/decklink/gstdecklinkaudiosink.cpp +++ b/sys/decklink/gstdecklinkaudiosink.cpp @@ -498,8 +498,11 @@ gst_decklink_audio_sink_init (GstDecklinkAudioSink * self) { self->device_number = 0; - // 25ms latency time seems to be needed at least, + // 25.000ms latency time seems to be needed at least, // everything below can cause drop-outs + // TODO: This is probably related to the video mode that + // is selected, but not directly it seems. Choosing the + // duration of a frame does not work. GST_AUDIO_BASE_SINK_CAST (self)->latency_time = 25000; } diff --git a/sys/decklink/gstdecklinkaudiosrc.cpp b/sys/decklink/gstdecklinkaudiosrc.cpp index 7152825cab..24d6239d22 100644 --- a/sys/decklink/gstdecklinkaudiosrc.cpp +++ b/sys/decklink/gstdecklinkaudiosrc.cpp @@ -60,6 +60,8 @@ static GstCaps *gst_decklink_audio_src_get_caps (GstBaseSrc * bsrc, GstCaps * filter); static gboolean gst_decklink_audio_src_unlock (GstBaseSrc * bsrc); static gboolean gst_decklink_audio_src_unlock_stop (GstBaseSrc * bsrc); +static gboolean gst_decklink_audio_src_query (GstBaseSrc * bsrc, + GstQuery * query); static GstFlowReturn gst_decklink_audio_src_create (GstPushSrc * psrc, GstBuffer ** buffer); @@ -89,6 +91,7 @@ gst_decklink_audio_src_class_init (GstDecklinkAudioSrcClass * klass) basesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_decklink_audio_src_get_caps); basesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_decklink_audio_src_set_caps); + basesrc_class->query = GST_DEBUG_FUNCPTR (gst_decklink_audio_src_query); basesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_decklink_audio_src_unlock); basesrc_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_decklink_audio_src_unlock_stop); @@ -333,6 +336,44 @@ gst_decklink_audio_src_create (GstPushSrc * bsrc, GstBuffer ** buffer) return flow_ret; } +static gboolean +gst_decklink_audio_src_query (GstBaseSrc * bsrc, GstQuery * query) +{ + GstDecklinkAudioSrc *self = GST_DECKLINK_AUDIO_SRC_CAST (bsrc); + gboolean ret = TRUE; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_LATENCY:{ + if (self->input) { + g_mutex_lock (&self->input->lock); + if (self->input->mode) { + GstClockTime min, max; + + min = + gst_util_uint64_scale_ceil (GST_MSECOND, self->input->mode->fps_d, + self->input->mode->fps_n); + max = min; + + gst_query_set_latency (query, TRUE, min, max); + ret = TRUE; + } else { + ret = FALSE; + } + g_mutex_unlock (&self->input->lock); + } else { + ret = FALSE; + } + + break; + } + default: + ret = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query); + break; + } + + return ret; +} + static gboolean gst_decklink_audio_src_unlock (GstBaseSrc * bsrc) { diff --git a/sys/decklink/gstdecklinkvideosink.cpp b/sys/decklink/gstdecklinkvideosink.cpp index c627b568b2..1e8936f153 100644 --- a/sys/decklink/gstdecklinkvideosink.cpp +++ b/sys/decklink/gstdecklinkvideosink.cpp @@ -313,6 +313,10 @@ gst_decklink_video_sink_open (GstBaseSink * bsink) return FALSE; } + g_mutex_lock (&self->output->lock); + self->output->mode = mode; + g_mutex_unlock (&self->output->lock); + caps = gst_decklink_mode_get_caps (self->mode); gst_video_info_from_caps (&self->info, caps); gst_caps_unref (caps); @@ -328,6 +332,10 @@ gst_decklink_video_sink_close (GstBaseSink * bsink) GST_DEBUG_OBJECT (self, "Stopping"); if (self->output) { + g_mutex_lock (&self->output->lock); + self->output->mode = NULL; + g_mutex_unlock (&self->output->lock); + self->output->output->DisableVideoOutput (); gst_decklink_release_nth_output (self->device_number, GST_ELEMENT_CAST (self), FALSE); diff --git a/sys/decklink/gstdecklinkvideosrc.cpp b/sys/decklink/gstdecklinkvideosrc.cpp index fd2b737925..ac0f350f90 100644 --- a/sys/decklink/gstdecklinkvideosrc.cpp +++ b/sys/decklink/gstdecklinkvideosrc.cpp @@ -48,6 +48,8 @@ static GstClock *gst_decklink_video_src_provide_clock (GstElement * element); static GstCaps *gst_decklink_video_src_get_caps (GstBaseSrc * bsrc, GstCaps * filter); +static gboolean gst_decklink_video_src_query (GstBaseSrc * bsrc, + GstQuery * query); static gboolean gst_decklink_video_src_unlock (GstBaseSrc * bsrc); static gboolean gst_decklink_video_src_unlock_stop (GstBaseSrc * bsrc); @@ -79,6 +81,7 @@ gst_decklink_video_src_class_init (GstDecklinkVideoSrcClass * klass) GST_DEBUG_FUNCPTR (gst_decklink_video_src_provide_clock); basesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_decklink_video_src_get_caps); + basesrc_class->query = GST_DEBUG_FUNCPTR (gst_decklink_video_src_query); basesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_decklink_video_src_unlock); basesrc_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_decklink_video_src_unlock_stop); @@ -197,7 +200,8 @@ gst_decklink_video_src_got_frame (GstElement * element, { GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (element); - GST_LOG_OBJECT (self, "Got video frame at %" GST_TIME_FORMAT, GST_TIME_ARGS (capture_time)); + GST_LOG_OBJECT (self, "Got video frame at %" GST_TIME_FORMAT, + GST_TIME_ARGS (capture_time)); g_mutex_lock (&self->lock); if (!self->flushing) { @@ -276,6 +280,40 @@ gst_decklink_video_src_create (GstPushSrc * bsrc, GstBuffer ** buffer) return flow_ret; } +static gboolean +gst_decklink_video_src_query (GstBaseSrc * bsrc, GstQuery * query) +{ + GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (bsrc); + gboolean ret = TRUE; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_LATENCY:{ + if (self->input) { + GstClockTime min, max; + const GstDecklinkMode *mode; + + mode = gst_decklink_get_mode (self->mode); + + min = + gst_util_uint64_scale_ceil (GST_MSECOND, mode->fps_d, mode->fps_n); + max = min; + + gst_query_set_latency (query, TRUE, min, max); + ret = TRUE; + } else { + ret = FALSE; + } + + break; + } + default: + ret = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query); + break; + } + + return ret; +} + static gboolean gst_decklink_video_src_unlock (GstBaseSrc * bsrc) { @@ -331,6 +369,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; g_mutex_unlock (&self->input->lock); @@ -350,6 +389,7 @@ gst_decklink_video_src_close (GstDecklinkVideoSrc * self) if (self->input) { g_mutex_lock (&self->input->lock); self->input->got_video_frame = NULL; + self->input->mode = NULL; g_mutex_unlock (&self->input->lock); self->input->input->DisableVideoInput ();