decklinkvideosrc: Automatically detect widescreen vs. normal NTSC/PAL

Based on the AFD aspect ratio flag the source can detect (in mode=auto)
whether this NTSC/PAL mode is actually a normal or a widescreen one and
select the caps according to that.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/2193>
This commit is contained in:
Sebastian Dröge 2021-04-23 18:05:06 +03:00 committed by GStreamer Marge Bot
parent 4b47b96ae1
commit 56af02f9c8
2 changed files with 52 additions and 21 deletions

View file

@ -666,6 +666,7 @@ gst_decklink_video_src_start (GstDecklinkVideoSrc * self)
self->skipped_last = 0;
self->skip_from_timestamp = GST_CLOCK_TIME_NONE;
self->skip_to_timestamp = GST_CLOCK_TIME_NONE;
self->aspect_ratio_flag = -1;
return TRUE;
}
@ -1014,6 +1015,8 @@ extract_vbi_line (GstDecklinkVideoSrc * self, GstBuffer ** buffer,
continue;
}
self->aspect_ratio_flag = (gstanc.data[0] >> 2) & 0x1;
afd = (GstVideoAFDValue) ((gstanc.data[0] >> 3) & 0xf);
is_letterbox = ((gstanc.data[3] >> 4) & 0x3) == 0;
bar1 = GST_READ_UINT16_BE (&gstanc.data[4]);
@ -1246,9 +1249,55 @@ retry:
// If we're not flushing, we should have a valid frame from the queue
g_assert (f.frame != NULL);
// Create output buffer
f.frame->GetBytes ((gpointer *) & data);
data_size = f.frame->GetHeight() * f.frame->GetRowBytes();
vf = (VideoFrame *) g_malloc0 (sizeof (VideoFrame));
*buffer =
gst_buffer_new_wrapped_full ((GstMemoryFlags) GST_MEMORY_FLAG_READONLY,
(gpointer) data, data_size, 0, data_size, vf,
(GDestroyNotify) video_frame_free);
vf->frame = f.frame;
f.frame->AddRef ();
vf->input = self->input->input;
vf->input->AddRef ();
// If we have a format that supports VANC and we are asked to extract CC,
// then do it here.
if ((self->output_cc || self->output_afd_bar)
&& self->signal_state != SIGNAL_STATE_LOST)
extract_vbi (self, buffer, vf);
if (!gst_pad_has_current_caps (GST_BASE_SRC_PAD (self))) {
caps_changed = TRUE;
}
// If there was AFD information with the aspect ratio flag set and the mode
// is auto then we have to switch from normal NTSC/PAL to the widescreen
// variants
if (self->aspect_ratio_flag == 1 && self->mode == GST_DECKLINK_MODE_AUTO) {
switch (f.mode) {
case GST_DECKLINK_MODE_NTSC:
f.mode = GST_DECKLINK_MODE_NTSC_WIDESCREEN;
break;
case GST_DECKLINK_MODE_NTSC_P:
f.mode = GST_DECKLINK_MODE_NTSC_P_WIDESCREEN;
break;
case GST_DECKLINK_MODE_NTSC2398:
f.mode = GST_DECKLINK_MODE_NTSC2398_WIDESCREEN;
break;
case GST_DECKLINK_MODE_PAL:
f.mode = GST_DECKLINK_MODE_PAL_WIDESCREEN;
break;
case GST_DECKLINK_MODE_PAL_P:
f.mode = GST_DECKLINK_MODE_PAL_P_WIDESCREEN;
break;
default:
break;
}
}
if (self->caps_mode != f.mode) {
if (self->mode == GST_DECKLINK_MODE_AUTO
@ -1263,6 +1312,7 @@ retry:
("Invalid mode in captured frame"),
("Mode set to %d but captured %d", self->caps_mode, f.mode));
capture_frame_clear (&f);
gst_clear_buffer (buffer);
return GST_FLOW_NOT_NEGOTIATED;
}
}
@ -1279,6 +1329,7 @@ retry:
("Invalid pixel format in captured frame"),
("Format set to %d but captured %d", self->caps_format, f.format));
capture_frame_clear (&f);
gst_clear_buffer (buffer);
return GST_FLOW_NOT_NEGOTIATED;
}
}
@ -1328,27 +1379,6 @@ retry:
}
}
f.frame->GetBytes ((gpointer *) & data);
data_size = self->info.size;
vf = (VideoFrame *) g_malloc0 (sizeof (VideoFrame));
*buffer =
gst_buffer_new_wrapped_full ((GstMemoryFlags) GST_MEMORY_FLAG_READONLY,
(gpointer) data, data_size, 0, data_size, vf,
(GDestroyNotify) video_frame_free);
vf->frame = f.frame;
f.frame->AddRef ();
vf->input = self->input->input;
vf->input->AddRef ();
// If we have a format that supports VANC and we are asked to extract CC,
// then do it here.
if ((self->output_cc || self->output_afd_bar)
&& self->signal_state != SIGNAL_STATE_LOST)
extract_vbi (self, buffer, vf);
if (f.no_signal)
GST_BUFFER_FLAG_SET (*buffer, GST_BUFFER_FLAG_GAP);
GST_BUFFER_TIMESTAMP (*buffer) = f.timestamp;

View file

@ -58,6 +58,7 @@ struct _GstDecklinkVideoSrc
GstDecklinkModeEnum mode;
GstDecklinkModeEnum caps_mode;
gint aspect_ratio_flag; /* -1 when unknown, 0 not set, 1 set */
BMDPixelFormat caps_format;
GstDecklinkConnectionEnum connection;
gint device_number;