From 5e4d10e2968348dee3dbe72ca6ab293820d76947 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 20 Jun 2019 10:04:06 +0300 Subject: [PATCH] decklinkvideosrc: Notify about signal loss even when dropping no-signal frames Otherwise the application has no way of knowing that signal loss happened other than noticing a gap between actual frames. --- sys/decklink/gstdecklinkvideosrc.cpp | 71 ++++++++++++++++++---------- 1 file changed, 45 insertions(+), 26 deletions(-) diff --git a/sys/decklink/gstdecklinkvideosrc.cpp b/sys/decklink/gstdecklinkvideosrc.cpp index 3894da4990..5d7246f227 100644 --- a/sys/decklink/gstdecklinkvideosrc.cpp +++ b/sys/decklink/gstdecklinkvideosrc.cpp @@ -190,7 +190,8 @@ typedef struct static void capture_frame_clear (CaptureFrame * frame) { - frame->frame->Release (); + if (frame->frame) + frame->frame->Release (); if (frame->tc) gst_video_time_code_free (frame->tc); memset (frame, 0, sizeof (*frame)); @@ -823,9 +824,6 @@ gst_decklink_video_src_got_frame (GstElement * element, GST_TIME_FORMAT "), no signal: %d", GST_TIME_ARGS (capture_time), GST_TIME_ARGS (stream_time), GST_TIME_ARGS (stream_duration), no_signal); - if (self->drop_no_signal_frames && no_signal) - return; - g_mutex_lock (&self->lock); if (self->first_time == GST_CLOCK_TIME_NONE) self->first_time = stream_time; @@ -840,6 +838,18 @@ gst_decklink_video_src_got_frame (GstElement * element, return; } + if (self->drop_no_signal_frames && no_signal) { + CaptureFrame f; + memset (&f, 0, sizeof (f)); + + /* Notify the streaming thread about the signal loss */ + gst_queue_array_push_tail_struct (self->current_frames, &f); + g_cond_signal (&self->cond); + g_mutex_unlock (&self->lock); + + return; + } + gst_decklink_video_src_update_time_mapping (self, capture_time, stream_time); if (self->output_stream_time) { timestamp = stream_time; @@ -871,10 +881,12 @@ gst_decklink_video_src_got_frame (GstElement * element, self->buffer_size) { CaptureFrame *tmp = (CaptureFrame *) gst_queue_array_pop_head_struct (self->current_frames); - if (skipped_frames == 0) - from_timestamp = tmp->timestamp; - skipped_frames++; - to_timestamp = tmp->timestamp; + if (tmp->frame) { + if (skipped_frames == 0) + from_timestamp = tmp->timestamp; + skipped_frames++; + to_timestamp = tmp->timestamp; + } capture_frame_clear (tmp); } @@ -1198,6 +1210,7 @@ gst_decklink_video_src_create (GstPushSrc * bsrc, GstBuffer ** buffer) GST_STATIC_CAPS ("timestamp/x-decklink-hardware"); g_mutex_lock (&self->lock); +retry: while (gst_queue_array_is_empty (self->current_frames) && !self->flushing) { g_cond_wait (&self->cond, &self->lock); } @@ -1209,11 +1222,33 @@ gst_decklink_video_src_create (GstPushSrc * bsrc, GstBuffer ** buffer) } f = *(CaptureFrame *) gst_queue_array_pop_head_struct (self->current_frames); - g_mutex_unlock (&self->lock); + + // We will have no frame if frames without signal are dropped immediately + // but we still have to signal that it's lost here. + if (f.no_signal || !f.frame) { + if (!self->no_signal) { + self->no_signal = TRUE; + g_object_notify (G_OBJECT (self), "signal"); + GST_ELEMENT_WARNING (GST_ELEMENT (self), RESOURCE, READ, ("No signal"), + ("No input source was detected - video frames invalid")); + } + // If we have no frame here, simply retry until we got one + if (!f.frame) { + capture_frame_clear (&f); + goto retry; + } + } else { + if (self->no_signal) { + self->no_signal = FALSE; + g_object_notify (G_OBJECT (self), "signal"); + GST_ELEMENT_INFO (GST_ELEMENT (self), RESOURCE, READ, ("Signal found"), + ("Input source detected")); + } + } + // If we're not flushing, we should have a valid frame from the queue g_assert (f.frame != NULL); - g_mutex_lock (&self->lock); if (self->caps_mode != f.mode) { if (self->mode == GST_DECKLINK_MODE_AUTO) { GST_DEBUG_OBJECT (self, "Mode changed from %d to %d", self->caps_mode, @@ -1304,22 +1339,6 @@ gst_decklink_video_src_create (GstPushSrc * bsrc, GstBuffer ** buffer) vf->input = self->input->input; vf->input->AddRef (); - if (f.no_signal) { - if (!self->no_signal) { - self->no_signal = TRUE; - g_object_notify (G_OBJECT (self), "signal"); - GST_ELEMENT_WARNING (GST_ELEMENT (self), RESOURCE, READ, ("No signal"), - ("No input source was detected - video frames invalid")); - } - } else { - if (self->no_signal) { - self->no_signal = FALSE; - g_object_notify (G_OBJECT (self), "signal"); - GST_ELEMENT_INFO (GST_ELEMENT (self), RESOURCE, READ, ("Signal found"), - ("Input source detected")); - } - } - mode = gst_decklink_get_mode (self->mode); // If we have a format that supports VANC and we are asked to extract CC, -- 2.34.1