From 2d3de7afa4029be9024f4786259aafb4df1e8264 Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Mon, 3 Jun 2019 12:17:22 -0400 Subject: [PATCH] uvch264: Factor out checking if v4l2device is uvc compatible --- sys/uvch264/gstuvch264_src.c | 139 +++---------------------------------------- sys/uvch264/gstuvch264_src.h | 1 - sys/uvch264/uvc_h264.c | 95 +++++++++++++++++++++++++++++ sys/uvch264/uvc_h264.h | 36 +++++++++++ 4 files changed, 140 insertions(+), 131 deletions(-) diff --git a/sys/uvch264/gstuvch264_src.c b/sys/uvch264/gstuvch264_src.c index 66a69b7..f4f153f 100644 --- a/sys/uvch264/gstuvch264_src.c +++ b/sys/uvch264/gstuvch264_src.c @@ -22,8 +22,8 @@ /** - * SECTION:element-uvch264-src - * @title: uvch264-src + * SECTION:element-uvch264src + * @title: uvch264src * * A camera bin src element that wraps v4l2src and implements UVC H264 * Extension Units (XU) to control the H264 encoder in the camera @@ -35,39 +35,6 @@ #include "gstuvch264_src.h" -#include -#include -#include -#include -#include - -#include "gstuvch264_src.h" -#include -#include -#ifndef LIBUSB_CLASS_VIDEO -#define LIBUSB_CLASS_VIDEO 0x0e -#endif - -typedef struct -{ - int8_t bLength; - int8_t bDescriptorType; - int8_t bDescriptorSubType; - int8_t bUnitID; - uint8_t guidExtensionCode[16]; -} __attribute__ ((__packed__)) xu_descriptor; - -#define GUID_FORMAT "02X%02X%02X%02X-%02X%02X%02X%02X-"\ - "%02X%02X%02X%02X-%02X%02X%02X%02X" -#define GUID_ARGS(guid) guid[0], guid[1], guid[2], guid[3], \ - guid[4], guid[5], guid[6], guid[7], \ - guid[8], guid[9], guid[10], guid[11], \ - guid[12], guid[13], guid[14], guid[15] - -#define USB_VIDEO_CONTROL 1 -#define USB_VIDEO_CONTROL_INTERFACE 0x24 -#define USB_VIDEO_CONTROL_XU_TYPE 0x06 - enum { PROP_0, @@ -174,6 +141,11 @@ G_DEFINE_TYPE (GstUvcH264Src, gst_uvc_h264_src, GST_TYPE_BASE_CAMERA_SRC); "alignment = (string) au, " \ "profile = (string) { high, main, baseline, constrained-baseline }" +/** + * GstUvcH264Src!vfsrc: + * + * The video src pad template + */ static GstStaticPadTemplate vfsrc_template = GST_STATIC_PAD_TEMPLATE (GST_BASE_CAMERA_SRC_VIEWFINDER_PAD_NAME, GST_PAD_SRC, @@ -1794,100 +1766,6 @@ gst_uvc_h264_src_event (GstPad * pad, GstObject * parent, GstEvent * event) return self->srcpad_event_func (pad, parent, event); } -static guint8 -xu_get_id (GstUvcH264Src * self) -{ - static const __u8 guid[16] = GUID_UVCX_H264_XU; - GUdevClient *client; - GUdevDevice *udevice; - GUdevDevice *parent; - guint64 busnum; - guint64 devnum; - libusb_device **device_list = NULL; - libusb_device *device = NULL; - ssize_t cnt; - int i, j, k; - - - if (self->usb_ctx == NULL) - libusb_init (&self->usb_ctx); - - client = g_udev_client_new (NULL); - if (client) { - udevice = g_udev_client_query_by_device_file (client, self->device); - if (udevice) { - parent = g_udev_device_get_parent_with_subsystem (udevice, "usb", - "usb_device"); - if (parent) { - busnum = g_udev_device_get_sysfs_attr_as_uint64 (parent, "busnum"); - devnum = g_udev_device_get_sysfs_attr_as_uint64 (parent, "devnum"); - - cnt = libusb_get_device_list (self->usb_ctx, &device_list); - for (i = 0; i < cnt; i++) { - if (busnum == libusb_get_bus_number (device_list[i]) && - devnum == libusb_get_device_address (device_list[i])) { - device = libusb_ref_device (device_list[i]); - break; - } - } - libusb_free_device_list (device_list, 1); - g_object_unref (parent); - } - g_object_unref (udevice); - } - g_object_unref (client); - } - - if (device) { - struct libusb_device_descriptor desc; - - if (libusb_get_device_descriptor (device, &desc) == 0) { - for (i = 0; i < desc.bNumConfigurations; ++i) { - struct libusb_config_descriptor *config = NULL; - - if (libusb_get_config_descriptor (device, i, &config) == 0) { - for (j = 0; j < config->bNumInterfaces; j++) { - for (k = 0; k < config->interface[j].num_altsetting; k++) { - const struct libusb_interface_descriptor *interface; - const guint8 *ptr = NULL; - - interface = &config->interface[j].altsetting[k]; - if (interface->bInterfaceClass != LIBUSB_CLASS_VIDEO || - interface->bInterfaceSubClass != USB_VIDEO_CONTROL) - continue; - ptr = interface->extra; - while (ptr - interface->extra + - sizeof (xu_descriptor) < interface->extra_length) { - xu_descriptor *desc = (xu_descriptor *) ptr; - - GST_DEBUG_OBJECT (self, "Found VideoControl interface with " - "unit id %d : %" GUID_FORMAT, desc->bUnitID, - GUID_ARGS (desc->guidExtensionCode)); - if (desc->bDescriptorType == USB_VIDEO_CONTROL_INTERFACE && - desc->bDescriptorSubType == USB_VIDEO_CONTROL_XU_TYPE && - memcmp (desc->guidExtensionCode, guid, 16) == 0) { - guint8 unit_id = desc->bUnitID; - - GST_DEBUG_OBJECT (self, "Found H264 XU unit : %d", unit_id); - - libusb_free_config_descriptor (config); - libusb_unref_device (device); - return unit_id; - } - ptr += desc->bLength; - } - } - } - libusb_free_config_descriptor (config); - } - } - } - libusb_unref_device (device); - } - - return 0; -} - static gboolean xu_query (GstUvcH264Src * self, guint selector, guint query, guchar * data) { @@ -2530,7 +2408,8 @@ ensure_v4l2src (GstUvcH264Src * self) /* Set/Update the fd and unit id after we go to READY */ g_object_get (self->v4l2_src, "device-fd", &self->v4l2_fd, NULL); - self->h264_unit_id = xu_get_id (self); + self->h264_unit_id = + xu_get_id (GST_OBJECT (self), self->device, &self->usb_ctx); if (self->h264_unit_id == 0) { GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS, diff --git a/sys/uvch264/gstuvch264_src.h b/sys/uvch264/gstuvch264_src.h index f220ed0..535a187 100644 --- a/sys/uvch264/gstuvch264_src.h +++ b/sys/uvch264/gstuvch264_src.h @@ -30,7 +30,6 @@ #include #include -#include #include "uvc_h264.h" diff --git a/sys/uvch264/uvc_h264.c b/sys/uvch264/uvc_h264.c index 07632f3..ef1e311 100644 --- a/sys/uvch264/uvc_h264.c +++ b/sys/uvch264/uvc_h264.c @@ -120,3 +120,98 @@ uvc_h264_entropy_get_type (void) } return type; } + +guint8 +xu_get_id (GstObject * self, const gchar * devicename, + libusb_context ** usb_ctx) +{ + static const __u8 guid[16] = GUID_UVCX_H264_XU; + GUdevClient *client; + GUdevDevice *udevice; + GUdevDevice *parent; + guint64 busnum; + guint64 devnum; + libusb_device **device_list = NULL; + libusb_device *device = NULL; + ssize_t cnt; + int i, j, k; + + + if (*usb_ctx == NULL) + libusb_init (usb_ctx); + + client = g_udev_client_new (NULL); + if (client) { + udevice = g_udev_client_query_by_device_file (client, devicename); + if (udevice) { + parent = g_udev_device_get_parent_with_subsystem (udevice, "usb", + "usb_device"); + if (parent) { + busnum = g_udev_device_get_sysfs_attr_as_uint64 (parent, "busnum"); + devnum = g_udev_device_get_sysfs_attr_as_uint64 (parent, "devnum"); + + cnt = libusb_get_device_list (*usb_ctx, &device_list); + for (i = 0; i < cnt; i++) { + if (busnum == libusb_get_bus_number (device_list[i]) && + devnum == libusb_get_device_address (device_list[i])) { + device = libusb_ref_device (device_list[i]); + break; + } + } + libusb_free_device_list (device_list, 1); + g_object_unref (parent); + } + g_object_unref (udevice); + } + g_object_unref (client); + } + + if (device) { + struct libusb_device_descriptor desc; + + if (libusb_get_device_descriptor (device, &desc) == 0) { + for (i = 0; i < desc.bNumConfigurations; ++i) { + struct libusb_config_descriptor *config = NULL; + + if (libusb_get_config_descriptor (device, i, &config) == 0) { + for (j = 0; j < config->bNumInterfaces; j++) { + for (k = 0; k < config->interface[j].num_altsetting; k++) { + const struct libusb_interface_descriptor *interface; + const guint8 *ptr = NULL; + + interface = &config->interface[j].altsetting[k]; + if (interface->bInterfaceClass != LIBUSB_CLASS_VIDEO || + interface->bInterfaceSubClass != USB_VIDEO_CONTROL) + continue; + ptr = interface->extra; + while (ptr - interface->extra + + sizeof (xu_descriptor) < interface->extra_length) { + xu_descriptor *desc = (xu_descriptor *) ptr; + + GST_DEBUG_OBJECT (self, "Found VideoControl interface with " + "unit id %d : %" GUID_FORMAT, desc->bUnitID, + GUID_ARGS (desc->guidExtensionCode)); + if (desc->bDescriptorType == USB_VIDEO_CONTROL_INTERFACE && + desc->bDescriptorSubType == USB_VIDEO_CONTROL_XU_TYPE && + memcmp (desc->guidExtensionCode, guid, 16) == 0) { + guint8 unit_id = desc->bUnitID; + + GST_DEBUG_OBJECT (self, "Found H264 XU unit : %d", unit_id); + + libusb_free_config_descriptor (config); + libusb_unref_device (device); + return unit_id; + } + ptr += desc->bLength; + } + } + } + libusb_free_config_descriptor (config); + } + } + } + libusb_unref_device (device); + } + + return 0; +} diff --git a/sys/uvch264/uvc_h264.h b/sys/uvch264/uvc_h264.h index d27104e..01046ac 100644 --- a/sys/uvch264/uvc_h264.h +++ b/sys/uvch264/uvc_h264.h @@ -33,6 +33,25 @@ #include #include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#define USB_VIDEO_CONTROL 1 +#define USB_VIDEO_CONTROL_INTERFACE 0x24 +#define USB_VIDEO_CONTROL_XU_TYPE 0x06 +#ifndef LIBUSB_CLASS_VIDEO +#define LIBUSB_CLASS_VIDEO 0x0e +#endif + /* bmHints defines */ #define UVC_H264_BMHINTS_RESOLUTION (0x0001) @@ -323,6 +342,23 @@ typedef struct _uvcx_qp_steps_layers_t guint8 bMaxQp; } __attribute__((packed)) uvcx_qp_steps_layers_t; +typedef struct +{ + int8_t bLength; + int8_t bDescriptorType; + int8_t bDescriptorSubType; + int8_t bUnitID; + uint8_t guidExtensionCode[16]; +} __attribute__ ((__packed__)) xu_descriptor; + +#define GUID_FORMAT "02X%02X%02X%02X-%02X%02X%02X%02X-"\ + "%02X%02X%02X%02X-%02X%02X%02X%02X" +#define GUID_ARGS(guid) guid[0], guid[1], guid[2], guid[3], \ + guid[4], guid[5], guid[6], guid[7], \ + guid[8], guid[9], guid[10], guid[11], \ + guid[12], guid[13], guid[14], guid[15] + +guint8 xu_get_id (GstObject *self, const gchar *devname, libusb_context **usb_ctx); #ifdef _WIN32 // GUID of the UVC H.264 extension unit: {A29E7641-DE04-47E3-8B2B-F4341AFF003B} -- 2.7.4