video: Add GST_VIDEO_INTERLACE_MODE_ALTERNATE
authorZeeshan Ali <zeenix@collabora.co.uk>
Fri, 4 May 2018 14:16:28 +0000 (16:16 +0200)
committerNicolas Dufresne <nicolas.dufresne@collabora.com>
Wed, 29 Aug 2018 16:14:38 +0000 (12:14 -0400)
Add a new interlace mode enum to represent buffers containing a single
field of an interlaced video in a buffer. The name is based on the
equivalent video format in the V4L2 API, V4L2_FIELD_ALTERNATE:

https://01.org/linuxgraphics/gfx-docs/drm/media/uapi/v4l/field-order.html

Since caps fields are optional, we also introduce a new caps feature,
"format:Interlaced" that always goes with "alternate" interlace mode to ensure
that caps for this incompatible format are incompatible with other interlaced
and progressive video caps.

https://bugzilla.gnome.org/show_bug.cgi?id=796106

gst-libs/gst/video/video-info.c
gst-libs/gst/video/video-info.h
tests/check/libs/video.c

index 5b09afbf7d4776e16be29daffd6c36b99f23f859..0e764a7c7c71b50d1c35db5a74e66a7d9707f43e 100644 (file)
@@ -237,7 +237,8 @@ static const gchar *interlace_mode[] = {
   "progressive",
   "interleaved",
   "mixed",
-  "fields"
+  "fields",
+  "alternate"
 };
 
 /**
@@ -604,6 +605,15 @@ gst_video_info_to_caps (GstVideoInfo * info)
         NULL);
   }
 
+  if (info->interlace_mode == GST_VIDEO_INTERLACE_MODE_ALTERNATE) {
+    /* 'alternate' mode must always be accompanied by interlaced caps feature.
+     */
+    GstCapsFeatures *features;
+
+    features = gst_caps_features_new (GST_CAPS_FEATURE_FORMAT_INTERLACED, NULL);
+    gst_caps_set_features (caps, 0, features);
+  }
+
   if (GST_VIDEO_INFO_MULTIVIEW_MODE (info) != GST_VIDEO_MULTIVIEW_MODE_NONE) {
     const gchar *caps_str = NULL;
 
@@ -683,7 +693,11 @@ fill_planes (GstVideoInfo * info)
   gint bpp = 0, i;
 
   width = (gsize) info->width;
-  height = (gsize) info->height;
+  if (GST_VIDEO_INFO_INTERLACE_MODE (info) ==
+      GST_VIDEO_INTERLACE_MODE_ALTERNATE)
+    height = (gsize) info->height / 2;
+  else
+    height = (gsize) info->height;
 
   /* Sanity check the resulting frame size for overflows */
   for (i = 0; i < GST_VIDEO_INFO_N_COMPONENTS (info); i++)
index 002679b161efe5b7f135623d171f02a4286ade71..f9de93833af61b5916f4f3891ce89ecb3e2aa8d4 100644 (file)
@@ -30,6 +30,16 @@ G_BEGIN_DECLS
 
 typedef struct _GstVideoInfo GstVideoInfo;
 
+/**
+ * GST_CAPS_FEATURE_FORMAT_INTERLACED:
+ *
+ * Name of the caps feature indicating that the stream is interlaced. Currently
+ * it is only used for video.
+ *
+ * Since: 1.16.
+ */
+#define GST_CAPS_FEATURE_FORMAT_INTERLACED "format:Interlaced"
+
 /**
  * GstVideoInterlaceMode:
  * @GST_VIDEO_INTERLACE_MODE_PROGRESSIVE: all frames are progressive
@@ -44,6 +54,11 @@ typedef struct _GstVideoInfo GstVideoInfo;
  *     Each field has only half the amount of lines as noted in the
  *     height property. This mode requires multiple GstVideoMeta metadata
  *     to describe the fields.
+ * @GST_VIDEO_INTERLACE_MODE_ALTERNATE: 1 field is stored in one buffer,
+ *     @GST_VIDEO_BUFFER_FLAG_TF or @GST_VIDEO_BUFFER_FLAG_BF indicates if
+ *     the buffer is carrying the top or bottom field, respectively. The top and
+ *     bottom buffers are expected to alternate in the pipeline, with this mode
+ *     (Since: 1.16).
  *
  * The possible values of the #GstVideoInterlaceMode describing the interlace
  * mode of the stream.
@@ -52,7 +67,8 @@ typedef enum {
   GST_VIDEO_INTERLACE_MODE_PROGRESSIVE = 0,
   GST_VIDEO_INTERLACE_MODE_INTERLEAVED,
   GST_VIDEO_INTERLACE_MODE_MIXED,
-  GST_VIDEO_INTERLACE_MODE_FIELDS
+  GST_VIDEO_INTERLACE_MODE_FIELDS,
+  GST_VIDEO_INTERLACE_MODE_ALTERNATE,
 } GstVideoInterlaceMode;
 
 GST_VIDEO_API
index 7fffcddbfe3438200ca2c29226dc9d7bdb33da2c..ade6276e9ac33ac7b6947c325d1e221b19c925a5 100644 (file)
@@ -1194,6 +1194,62 @@ GST_START_TEST (test_video_size_from_caps)
 
 GST_END_TEST;
 
+GST_START_TEST (test_interlace_mode)
+{
+  GstVideoInfo vinfo;
+  GstCaps *caps;
+  GstStructure *structure;
+  GstCapsFeatures *features;
+  const char *mode_str;
+  int mode;
+
+  gst_video_info_init (&vinfo);
+
+  /* Progressive */
+  gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_YV12, 320, 240);
+  GST_VIDEO_INFO_INTERLACE_MODE (&vinfo) = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
+
+  caps = gst_video_info_to_caps (&vinfo);
+  fail_unless (caps != NULL);
+  structure = gst_caps_get_structure (caps, 0);
+  fail_unless (structure != NULL);
+  mode_str = gst_structure_get_string (structure, "interlace-mode");
+  mode = gst_video_interlace_mode_from_string (mode_str);
+  fail_unless (mode == GST_VIDEO_INTERLACE_MODE_PROGRESSIVE);
+
+  /* Converting back to video info */
+  fail_unless (gst_video_info_from_caps (&vinfo, caps));
+  fail_unless (GST_VIDEO_INFO_INTERLACE_MODE (&vinfo) ==
+      GST_VIDEO_INTERLACE_MODE_PROGRESSIVE);
+
+  gst_caps_unref (caps);
+
+  /* Interlaced with alternate frame on buffers */
+  gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_YV12, 320, 240);
+  GST_VIDEO_INFO_INTERLACE_MODE (&vinfo) = GST_VIDEO_INTERLACE_MODE_ALTERNATE;
+
+  caps = gst_video_info_to_caps (&vinfo);
+  fail_unless (caps != NULL);
+  structure = gst_caps_get_structure (caps, 0);
+  fail_unless (structure != NULL);
+  mode_str = gst_structure_get_string (structure, "interlace-mode");
+  mode = gst_video_interlace_mode_from_string (mode_str);
+  fail_unless (mode == GST_VIDEO_INTERLACE_MODE_ALTERNATE);
+  /* 'alternate' mode must always be accompanied by interlaced caps feature. */
+  features = gst_caps_get_features (caps, 0);
+  fail_unless (gst_caps_features_contains (features,
+          GST_CAPS_FEATURE_FORMAT_INTERLACED));
+
+  /* Converting back to video info */
+  fail_unless (gst_video_info_from_caps (&vinfo, caps));
+  fail_unless (GST_VIDEO_INFO_INTERLACE_MODE (&vinfo) ==
+      GST_VIDEO_INTERLACE_MODE_ALTERNATE);
+
+  gst_caps_unref (caps);
+}
+
+GST_END_TEST;
+
 GST_START_TEST (test_overlay_composition)
 {
   GstVideoOverlayComposition *comp1, *comp2;
@@ -2851,6 +2907,7 @@ video_suite (void)
   tcase_add_test (tc_chain, test_convert_frame);
   tcase_add_test (tc_chain, test_convert_frame_async);
   tcase_add_test (tc_chain, test_video_size_from_caps);
+  tcase_add_test (tc_chain, test_interlace_mode);
   tcase_add_test (tc_chain, test_overlay_composition);
   tcase_add_test (tc_chain, test_overlay_composition_premultiplied_alpha);
   tcase_add_test (tc_chain, test_overlay_composition_global_alpha);