mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-10 17:35:59 +00:00
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:
parent
f0ba7a5ca4
commit
4b16b16aaf
8 changed files with 52 additions and 32 deletions
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue