decklinkvideosrc: Automatically detect widescreen vs. normal NTSC/PAL
authorSebastian Dröge <sebastian@centricular.com>
Fri, 23 Apr 2021 15:05:06 +0000 (18:05 +0300)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Mon, 26 Apr 2021 15:03:34 +0000 (15:03 +0000)
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>

sys/decklink/gstdecklinkvideosrc.cpp
sys/decklink/gstdecklinkvideosrc.h

index 41de397..bf71e38 100644 (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;
index edd52d3..5e98766 100644 (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;