decklink2src: Implement soft restart

Instead of stopping stream, do pause, flush, and reset time mapping.
This commit is contained in:
Seungha Yang 2023-12-14 22:43:35 +09:00
parent e5ad448f47
commit 7c4cae61b9
3 changed files with 33 additions and 16 deletions

View file

@ -339,6 +339,7 @@ struct GstDeckLink2InputPrivate
signal = false; signal = false;
was_restarted = false; was_restarted = false;
stopping = false; stopping = false;
need_restart = false;
} }
std::mutex lock; std::mutex lock;
@ -346,6 +347,7 @@ struct GstDeckLink2InputPrivate
std::atomic < bool >signal; std::atomic < bool >signal;
std::atomic < bool >was_restarted; std::atomic < bool >was_restarted;
std::atomic <bool> stopping; std::atomic <bool> stopping;
std::atomic <bool> need_restart;
}; };
struct _GstDeckLink2Input struct _GstDeckLink2Input
@ -1503,20 +1505,27 @@ gst_decklink2_input_update_time_mapping (GstDeckLink2Input * self,
} }
} }
/* Must be called with lock taken */
static void static void
gst_decklink2_input_do_restart (GstDeckLink2Input * self) gst_decklink2_input_do_restart (GstDeckLink2Input * self)
{ {
GstDeckLink2InputPrivate *priv = self->priv; GstDeckLink2InputPrivate *priv = self->priv;
GST_DEBUG_OBJECT (self, "Restaring input");
priv->was_restarted = true; priv->was_restarted = true;
gst_decklink2_input_reset_time_mapping (self); priv->need_restart = false;
gst_decklink2_input_stop_streams (self); priv->lock.unlock ();
gst_decklink2_input_pause_streams (self);
gst_decklink2_input_flush_streams (self); gst_decklink2_input_flush_streams (self);
gst_decklink2_input_start_streams (self);
priv->lock.lock ();
gst_decklink2_input_reset_time_mapping (self);
gst_adapter_clear (self->audio_buf); gst_adapter_clear (self->audio_buf);
gst_queue_array_clear (self->queue);
self->audio_offset = INVALID_AUDIO_OFFSET; self->audio_offset = INVALID_AUDIO_OFFSET;
self->next_audio_offset = INVALID_AUDIO_OFFSET; self->next_audio_offset = INVALID_AUDIO_OFFSET;
gst_decklink2_input_start_streams (self);
} }
static void static void
@ -1538,6 +1547,7 @@ gst_decklink2_input_on_frame_arrived (GstDeckLink2Input * self,
BMDTimeValue stream_dur; BMDTimeValue stream_dur;
BMDFrameFlags flags = bmdFrameFlagDefault; BMDFrameFlags flags = bmdFrameFlagDefault;
std::unique_lock < std::mutex > lk (priv->lock);
if (frame) { if (frame) {
gboolean has_signal; gboolean has_signal;
flags = frame->GetFlags (); flags = frame->GetFlags ();
@ -1566,7 +1576,13 @@ gst_decklink2_input_on_frame_arrived (GstDeckLink2Input * self,
} }
} }
std::unique_lock < std::mutex > lk (priv->lock); /* Restart requested, flush everything */
if (priv->need_restart) {
GST_DEBUG_OBJECT (self, "Restring as requested");
gst_decklink2_input_do_restart (self);
return;
}
hr = gst_decklink2_input_get_reference_clock (self, GST_SECOND, hr = gst_decklink2_input_get_reference_clock (self, GST_SECOND,
&hw_now, &dummy, &dummy2); &hw_now, &dummy, &dummy2);
if (!gst_decklink2_result (hr)) { if (!gst_decklink2_result (hr)) {
@ -1622,7 +1638,6 @@ gst_decklink2_input_on_frame_arrived (GstDeckLink2Input * self,
pixel_format = frame->GetPixelFormat (); pixel_format = frame->GetPixelFormat ();
if (pixel_format != self->pixel_format) { if (pixel_format != self->pixel_format) {
lk.unlock ();
GST_DEBUG_OBJECT (self, "Unexpected pixel format change %d -> %d", GST_DEBUG_OBJECT (self, "Unexpected pixel format change %d -> %d",
self->pixel_format, pixel_format); self->pixel_format, pixel_format);
@ -1635,7 +1650,6 @@ gst_decklink2_input_on_frame_arrived (GstDeckLink2Input * self,
auto frame_height = frame->GetHeight (); auto frame_height = frame->GetHeight ();
if (self->video_info.width != (gint) frame_width || if (self->video_info.width != (gint) frame_width ||
self->video_info.height != (gint) frame_height) { self->video_info.height != (gint) frame_height) {
lk.unlock ();
GST_WARNING_OBJECT (self, "Unexpected resolution change %dx%d -> %dx%d", GST_WARNING_OBJECT (self, "Unexpected resolution change %dx%d -> %dx%d",
self->video_info.width, self->video_info.height, self->video_info.width, self->video_info.height,
@ -1958,6 +1972,7 @@ gst_decklink2_input_stop_unlocked (GstDeckLink2Input * self)
gst_clear_caps (&self->selected_audio_caps); gst_clear_caps (&self->selected_audio_caps);
priv->signal = false; priv->signal = false;
priv->was_restarted = false; priv->was_restarted = false;
priv->need_restart = false;
self->skip_first_time = GST_CLOCK_TIME_NONE; self->skip_first_time = GST_CLOCK_TIME_NONE;
self->start_time = GST_CLOCK_TIME_NONE; self->start_time = GST_CLOCK_TIME_NONE;
self->started = FALSE; self->started = FALSE;
@ -2145,6 +2160,12 @@ error:
return E_FAIL; return E_FAIL;
} }
void
gst_decklink2_input_schedule_restart (GstDeckLink2Input * input)
{
input->priv->need_restart = true;
}
void void
gst_decklink2_input_stop (GstDeckLink2Input * input) gst_decklink2_input_stop (GstDeckLink2Input * input)
{ {

View file

@ -67,6 +67,8 @@ HRESULT gst_decklink2_input_start (GstDeckLink2Input * input,
const GstDeckLink2InputVideoConfig * video_config, const GstDeckLink2InputVideoConfig * video_config,
const GstDeckLink2InputAudioConfig * audio_config); const GstDeckLink2InputAudioConfig * audio_config);
void gst_decklink2_input_schedule_restart (GstDeckLink2Input * input);
void gst_decklink2_input_stop (GstDeckLink2Input * input); void gst_decklink2_input_stop (GstDeckLink2Input * input);
void gst_decklink2_input_set_flushing (GstDeckLink2Input * input, void gst_decklink2_input_set_flushing (GstDeckLink2Input * input,

View file

@ -680,12 +680,7 @@ again:
GST_STIME_FORMAT ", threshold %" GST_TIME_FORMAT, GST_STIME_FORMAT ", threshold %" GST_TIME_FORMAT,
GST_STIME_ARGS (av_sync), GST_TIME_ARGS (self->desync_threshold)); GST_STIME_ARGS (av_sync), GST_TIME_ARGS (self->desync_threshold));
self->running = FALSE; gst_decklink2_input_schedule_restart (self->input);
gst_decklink2_input_stop (self->input);
if (!gst_decklink2_src_run_unlocked (self, TRUE)) {
GST_ERROR_OBJECT (self, "Couldn't restart input");
return GST_FLOW_ERROR;
}
} }
} }
@ -801,8 +796,7 @@ gst_decklink2_src_restart (GstDeckLink2Src * self)
std::lock_guard < std::mutex > lk (priv->lock); std::lock_guard < std::mutex > lk (priv->lock);
if (self->input && self->running) { if (self->input && self->running) {
GST_INFO_OBJECT (self, "Stopping input for restart"); GST_INFO_OBJECT (self, "Scheduling restart");
self->running = FALSE; gst_decklink2_input_schedule_restart (self->input);
gst_decklink2_input_stop (self->input);
} }
} }