v4l2object: set colorspace in caps for capture devices
authorAurélien Zanelli <aurelien.zanelli@parrot.com>
Mon, 19 Jan 2015 14:29:24 +0000 (15:29 +0100)
committerNicolas Dufresne <nicolas.dufresne@collabora.co.uk>
Wed, 25 Feb 2015 19:48:20 +0000 (14:48 -0500)
This information is set by the driver for a capture device, and so could
be forwarded to pipeline by setting the colorimetry in caps.

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

sys/v4l2/gstv4l2object.c

index 6d1856b4077df682aa45d1a29a7ab512cc825f17..3e572140fb34bb0def87e4fa77a5505f328b4c8d 100644 (file)
@@ -1663,6 +1663,37 @@ gst_v4l2_object_get_interlace_mode (enum v4l2_field field,
   }
 }
 
+static gboolean
+gst_v4l2_object_get_colorspace (enum v4l2_colorspace colorspace,
+    GstVideoColorimetry * cinfo)
+{
+  gboolean ret = FALSE;
+
+  switch (colorspace) {
+    case V4L2_COLORSPACE_SMPTE170M:
+      ret = gst_video_colorimetry_from_string (cinfo,
+          GST_VIDEO_COLORIMETRY_BT601);
+      break;
+    case V4L2_COLORSPACE_REC709:
+      ret = gst_video_colorimetry_from_string (cinfo,
+          GST_VIDEO_COLORIMETRY_BT709);
+      break;
+    case V4L2_COLORSPACE_SMPTE240M:
+      ret = gst_video_colorimetry_from_string (cinfo,
+          GST_VIDEO_COLORIMETRY_SMPTE240M);
+      break;
+    case V4L2_COLORSPACE_SRGB:
+      ret = gst_video_colorimetry_from_string (cinfo,
+          GST_VIDEO_COLORIMETRY_SRGB);
+      break;
+    default:
+      GST_DEBUG ("Unknown enum v4l2_colorspace %d", colorspace);
+      ret = FALSE;
+      break;
+  }
+  return ret;
+}
+
 static int
 gst_v4l2_object_try_fmt (GstV4l2Object * v4l2object,
     struct v4l2_format *try_fmt)
@@ -1753,6 +1784,39 @@ gst_v4l2_object_add_interlace_mode (GstV4l2Object * v4l2object,
   return;
 }
 
+static void
+gst_v4l2_object_add_colorspace (GstV4l2Object * v4l2object, GstStructure * s,
+    guint32 width, guint32 height, guint32 pixelformat)
+{
+  struct v4l2_format fmt;
+  GValue colorimetry = G_VALUE_INIT;
+  GstVideoColorimetry cinfo;
+
+  memset (&fmt, 0, sizeof (fmt));
+  fmt.type = v4l2object->type;
+  fmt.fmt.pix.width = width;
+  fmt.fmt.pix.height = height;
+  fmt.fmt.pix.pixelformat = pixelformat;
+
+  if (gst_v4l2_object_try_fmt (v4l2object, &fmt) == 0) {
+    enum v4l2_colorspace colorspace;
+
+    if (V4L2_TYPE_IS_MULTIPLANAR (v4l2object->type))
+      colorspace = fmt.fmt.pix_mp.colorspace;
+    else
+      colorspace = fmt.fmt.pix.colorspace;
+
+    if (gst_v4l2_object_get_colorspace (colorspace, &cinfo)) {
+      g_value_init (&colorimetry, G_TYPE_STRING);
+      g_value_take_string (&colorimetry,
+          gst_video_colorimetry_to_string (&cinfo));
+      gst_structure_take_value (s, "colorimetry", &colorimetry);
+    }
+  }
+
+  return;
+}
+
 /* The frame interval enumeration code first appeared in Linux 2.6.19. */
 static GstStructure *
 gst_v4l2_object_probe_caps_for_format_and_size (GstV4l2Object * v4l2object,
@@ -1925,6 +1989,7 @@ return_data:
   gst_v4l2_object_add_aspect_ratio (v4l2object, s);
   gst_v4l2_object_add_interlace_mode (v4l2object, s, width, height,
       pixelformat);
+  gst_v4l2_object_add_colorspace (v4l2object, s, width, height, pixelformat);
 
   if (G_IS_VALUE (&rates)) {
     gst_v4l2src_value_simplify (&rates);
@@ -2248,6 +2313,9 @@ default_frame_sizes:
     gst_v4l2_object_add_interlace_mode (v4l2object, tmp, max_w, max_h,
         pixelformat);
     gst_v4l2_object_add_aspect_ratio (v4l2object, tmp);
+    /* We could consider to check colorspace for min too, in case it depends on
+     * the size. But in this case, min and max could not be enough */
+    gst_v4l2_object_add_colorspace (v4l2object, tmp, max_w, max_h, pixelformat);
 
     gst_v4l2_object_update_and_append (v4l2object, pixelformat, ret, tmp);
     return ret;