v4l2: use opened device caps instead of physical device ones
authorReynaldo H. Verdejo Pinochet <reynaldo@osg.samsung.com>
Sat, 2 Jul 2016 08:56:07 +0000 (01:56 -0700)
committerNicolas Dufresne <nicolas.dufresne@collabora.com>
Thu, 7 Jul 2016 21:46:06 +0000 (17:46 -0400)
The same physical device can export multiple devices. In
this case, the capabilities field now contains a union of
all caps available from all exported V4L2 devices alongside
a V4L2_CAP_DEVICE_CAPS flag that should be used to decide
what capabilities to consider. In our case, we need the
ones from the exported device we are using.

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

sys/v4l2/gstv4l2.c
sys/v4l2/gstv4l2bufferpool.c
sys/v4l2/gstv4l2deviceprovider.c
sys/v4l2/gstv4l2object.c
sys/v4l2/gstv4l2object.h
sys/v4l2/gstv4l2radio.c
sys/v4l2/gstv4l2sink.c
sys/v4l2/v4l2_calls.c

index 83fcc98..d2b9a34 100644 (file)
@@ -119,6 +119,7 @@ gst_v4l2_probe_and_register (GstPlugin * plugin)
   gint video_fd = -1;
   struct v4l2_capability vcap;
   gboolean ret = TRUE;
+  guint32 device_caps;
 
   it = gst_v4l2_iterator_new ();
 
@@ -143,12 +144,16 @@ gst_v4l2_probe_and_register (GstPlugin * plugin)
       continue;
     }
 
-    if (!((vcap.capabilities & (V4L2_CAP_VIDEO_M2M |
-                    V4L2_CAP_VIDEO_M2M_MPLANE)) ||
+    if (vcap.capabilities & V4L2_CAP_DEVICE_CAPS)
+      device_caps = vcap.device_caps;
+    else
+      device_caps = vcap.capabilitites;
+
+    if (!((device_caps & (V4L2_CAP_VIDEO_M2M | V4L2_CAP_VIDEO_M2M_MPLANE)) ||
             /* But legacy driver may expose both CAPTURE and OUTPUT */
-            ((vcap.capabilities &
+            ((device_caps &
                     (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE)) &&
-                (vcap.capabilities &
+                (device_caps &
                     (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_MPLANE)))))
       continue;
 
index 3184bd8..bfcfbaa 100644 (file)
@@ -716,7 +716,7 @@ gst_v4l2_buffer_pool_start (GstBufferPool * bpool)
        * poll before that will always fail. Doing an empty read, forces the
        * queue to be initialized now. We only do this if we have a streaming
        * driver. */
-      if (obj->vcap.capabilities & V4L2_CAP_STREAMING)
+      if (obj->device_caps & V4L2_CAP_STREAMING)
         v4l2_read (obj->video_fd, NULL, 0);
 #endif
       break;
index d521838..68e0657 100644 (file)
@@ -136,10 +136,10 @@ gst_v4l2_device_provider_probe_device (GstV4l2DeviceProvider * provider,
   gst_structure_set (props, "v4l2.device.device_caps", G_TYPE_UINT,
       v4l2obj->vcap.device_caps, NULL);
 
-  if (v4l2obj->vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE)
+  if (v4l2obj->device_caps & V4L2_CAP_VIDEO_CAPTURE)
     type = GST_V4L2_DEVICE_TYPE_SOURCE;
 
-  if (v4l2obj->vcap.capabilities & V4L2_CAP_VIDEO_OUTPUT) {
+  if (v4l2obj->device_caps & V4L2_CAP_VIDEO_OUTPUT) {
     /* Morph it in case our initial guess was wrong */
     v4l2obj->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
 
index d4acbf9..ab7e52f 100644 (file)
@@ -700,17 +700,17 @@ gst_v4l2_object_get_property_helper (GstV4l2Object * v4l2object,
       guint flags = 0;
 
       if (GST_V4L2_IS_OPEN (v4l2object)) {
-        flags |= v4l2object->vcap.capabilities &
+        flags |= v4l2object->device_caps &
             (V4L2_CAP_VIDEO_CAPTURE |
             V4L2_CAP_VIDEO_OUTPUT |
             V4L2_CAP_VIDEO_OVERLAY |
             V4L2_CAP_VBI_CAPTURE |
             V4L2_CAP_VBI_OUTPUT | V4L2_CAP_TUNER | V4L2_CAP_AUDIO);
 
-        if (v4l2object->vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE)
+        if (v4l2object->device_caps & V4L2_CAP_VIDEO_CAPTURE_MPLANE)
           flags |= V4L2_CAP_VIDEO_CAPTURE;
 
-        if (v4l2object->vcap.capabilities & V4L2_CAP_VIDEO_OUTPUT_MPLANE)
+        if (v4l2object->device_caps & V4L2_CAP_VIDEO_OUTPUT_MPLANE)
           flags |= V4L2_CAP_VIDEO_OUTPUT;
       }
       g_value_set_flags (value, flags);
@@ -873,6 +873,9 @@ gst_v4l2_object_close (GstV4l2Object * v4l2object)
 
   gst_caps_replace (&v4l2object->probed_caps, NULL);
 
+  /* reset our copy of the device caps */
+  v4l2object->device_caps = 0;
+
   if (v4l2object->formats) {
     gst_v4l2_object_clear_format_list (v4l2object);
   }
@@ -2824,13 +2827,13 @@ gst_v4l2_object_setup_pool (GstV4l2Object * v4l2object, GstCaps * caps)
   /* find transport */
   mode = v4l2object->req_mode;
 
-  if (v4l2object->vcap.capabilities & V4L2_CAP_READWRITE) {
+  if (v4l2object->device_caps & V4L2_CAP_READWRITE) {
     if (v4l2object->req_mode == GST_V4L2_IO_AUTO)
       mode = GST_V4L2_IO_RW;
   } else if (v4l2object->req_mode == GST_V4L2_IO_RW)
     goto method_not_supported;
 
-  if (v4l2object->vcap.capabilities & V4L2_CAP_STREAMING) {
+  if (v4l2object->device_caps & V4L2_CAP_STREAMING) {
     if (v4l2object->req_mode == GST_V4L2_IO_AUTO)
       mode = GST_V4L2_IO_MMAP;
   } else if (v4l2object->req_mode == GST_V4L2_IO_MMAP)
index 7117d43..5fff161 100644 (file)
@@ -133,6 +133,8 @@ struct _GstV4l2Object {
 
   /* the video device's capabilities */
   struct v4l2_capability vcap;
+  /* opened device specific capabilities */
+  guint32 device_caps;
 
   /* the video device's window properties */
   struct v4l2_window vwin;
index 7a6463c..5d74e7e 100644 (file)
@@ -90,7 +90,12 @@ gst_v4l2radio_fill_channel_list (GstV4l2Radio * radio)
   if (res < 0)
     goto caps_failed;
 
-  if (!(vc.capabilities & V4L2_CAP_TUNER))
+  if (vc.capabilities & V4L2_CAP_DEVICE_CAPS)
+    v4l2object->device_caps = vc.device_caps;
+  else
+    v4l2object->device_caps = vc.capabilities;
+
+  if (!(v4l2object->device_caps & V4L2_CAP_TUNER))
     goto not_a_tuner;
 
   /* getting audio input */
index ae4a3c2..b5f34eb 100644 (file)
@@ -250,10 +250,10 @@ gst_v4l2sink_sync_overlay_fields (GstV4l2Sink * v4l2sink)
     struct v4l2_format format;
 
     memset (&format, 0x00, sizeof (struct v4l2_format));
-    if ( v4l2sink->v4l2object->vcap.capabilities & V4L2_CAP_VIDEO_OUTPUT_OVERLAY )
-               format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY;
-       else
-               format.type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
+    if (v4l2sink->v4l2object->device_caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)
+      format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY;
+    else
+      format.type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
 
     if (v4l2_ioctl (fd, VIDIOC_G_FMT, &format) < 0) {
       GST_WARNING_OBJECT (v4l2sink, "VIDIOC_G_FMT failed");
index bfb6557..8d8337e 100644 (file)
@@ -74,11 +74,16 @@ gst_v4l2_get_capabilities (GstV4l2Object * v4l2object)
   if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_QUERYCAP, &v4l2object->vcap) < 0)
     goto cap_failed;
 
+  if (v4l2object->vcap.capabilities & V4L2_CAP_DEVICE_CAPS)
+    v4l2object->device_caps = v4l2object->vcap.device_caps;
+  else
+    v4l2object->device_caps = v4l2object->vcap.capabilities;
+
   GST_LOG_OBJECT (e, "driver:      '%s'", v4l2object->vcap.driver);
   GST_LOG_OBJECT (e, "card:        '%s'", v4l2object->vcap.card);
   GST_LOG_OBJECT (e, "bus_info:    '%s'", v4l2object->vcap.bus_info);
   GST_LOG_OBJECT (e, "version:     %08x", v4l2object->vcap.version);
-  GST_LOG_OBJECT (e, "capabilites: %08x", v4l2object->vcap.capabilities);
+  GST_LOG_OBJECT (e, "capabilites: %08x", v4l2object->device_caps);
 
   return TRUE;
 
@@ -487,13 +492,13 @@ gst_v4l2_adjust_buf_type (GstV4l2Object * v4l2object)
 #define CHECK_CAPS (V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_VIDEO_M2M_MPLANE)
   switch (v4l2object->type) {
     case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-      if (v4l2object->vcap.capabilities & CHECK_CAPS) {
+      if (v4l2object->device_caps & CHECK_CAPS) {
         GST_DEBUG ("adjust type to multi-planar output");
         v4l2object->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
       }
       break;
     case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-      if (v4l2object->vcap.capabilities & CHECK_CAPS) {
+      if (v4l2object->device_caps & CHECK_CAPS) {
         GST_DEBUG ("adjust type to multi-planar capture");
         v4l2object->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
       }
@@ -556,23 +561,23 @@ gst_v4l2_open (GstV4l2Object * v4l2object)
 
   /* do we need to be a capture device? */
   if (GST_IS_V4L2SRC (v4l2object->element) &&
-      !(v4l2object->vcap.capabilities & (V4L2_CAP_VIDEO_CAPTURE |
+      !(v4l2object->device_caps & (V4L2_CAP_VIDEO_CAPTURE |
               V4L2_CAP_VIDEO_CAPTURE_MPLANE)))
     goto not_capture;
 
   if (GST_IS_V4L2SINK (v4l2object->element) &&
-      !(v4l2object->vcap.capabilities & (V4L2_CAP_VIDEO_OUTPUT |
+      !(v4l2object->device_caps & (V4L2_CAP_VIDEO_OUTPUT |
               V4L2_CAP_VIDEO_OUTPUT_MPLANE)))
     goto not_output;
 
   if (GST_IS_V4L2_VIDEO_DEC (v4l2object->element) &&
       /* Today's M2M device only expose M2M */
-      !((v4l2object->vcap.capabilities & (V4L2_CAP_VIDEO_M2M |
+      !((v4l2object->device_caps & (V4L2_CAP_VIDEO_M2M |
                   V4L2_CAP_VIDEO_M2M_MPLANE)) ||
           /* But legacy driver may expose both CAPTURE and OUTPUT */
-          ((v4l2object->vcap.capabilities &
+          ((v4l2object->device_caps &
                   (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE)) &&
-              (v4l2object->vcap.capabilities &
+              (v4l2object->device_caps &
                   (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_MPLANE)))))
     goto not_m2m;
 
@@ -625,7 +630,7 @@ not_capture:
     GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, NOT_FOUND,
         (_("Device '%s' is not a capture device."),
             v4l2object->videodev),
-        ("Capabilities: 0x%x", v4l2object->vcap.capabilities));
+        ("Capabilities: 0x%x", v4l2object->device_caps));
     goto error;
   }
 not_output:
@@ -633,7 +638,7 @@ not_output:
     GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, NOT_FOUND,
         (_("Device '%s' is not a output device."),
             v4l2object->videodev),
-        ("Capabilities: 0x%x", v4l2object->vcap.capabilities));
+        ("Capabilities: 0x%x", v4l2object->device_caps));
     goto error;
   }
 not_m2m:
@@ -641,7 +646,7 @@ not_m2m:
     GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, NOT_FOUND,
         (_("Device '%s' is not a M2M device."),
             v4l2object->videodev),
-        ("Capabilities: 0x%x", v4l2object->vcap.capabilities));
+        ("Capabilities: 0x%x", v4l2object->device_caps));
     goto error;
   }
 error:
@@ -1034,7 +1039,7 @@ gst_v4l2_get_input (GstV4l2Object * v4l2object, gint * input)
 
   /* ERRORS */
 input_failed:
-  if (v4l2object->vcap.capabilities & V4L2_CAP_TUNER) {
+  if (v4l2object->device_caps & V4L2_CAP_TUNER) {
     /* only give a warning message if driver actually claims to have tuner
      * support
      */
@@ -1059,7 +1064,7 @@ gst_v4l2_set_input (GstV4l2Object * v4l2object, gint input)
 
   /* ERRORS */
 input_failed:
-  if (v4l2object->vcap.capabilities & V4L2_CAP_TUNER) {
+  if (v4l2object->device_caps & V4L2_CAP_TUNER) {
     /* only give a warning message if driver actually claims to have tuner
      * support
      */
@@ -1091,7 +1096,7 @@ gst_v4l2_get_output (GstV4l2Object * v4l2object, gint * output)
 
   /* ERRORS */
 output_failed:
-  if (v4l2object->vcap.capabilities & V4L2_CAP_TUNER) {
+  if (v4l2object->device_caps & V4L2_CAP_TUNER) {
     /* only give a warning message if driver actually claims to have tuner
      * support
      */
@@ -1116,7 +1121,7 @@ gst_v4l2_set_output (GstV4l2Object * v4l2object, gint output)
 
   /* ERRORS */
 output_failed:
-  if (v4l2object->vcap.capabilities & V4L2_CAP_TUNER) {
+  if (v4l2object->device_caps & V4L2_CAP_TUNER) {
     /* only give a warning message if driver actually claims to have tuner
      * support
      */