v4l2: use opened device caps instead of physical device ones

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
This commit is contained in:
Reynaldo H. Verdejo Pinochet 2016-07-02 01:56:07 -07:00 committed by Nicolas Dufresne
parent f0ba7a5ca4
commit 4b16b16aaf
8 changed files with 52 additions and 32 deletions

View 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;

View 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;

View 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;

View 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)

View 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;

View 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 */

View 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");

View 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
*/