mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-25 01:30:38 +00:00
uvch264: Factor out checking if v4l2device is uvc compatible
This commit is contained in:
parent
59d8e56e95
commit
2d3de7afa4
4 changed files with 140 additions and 131 deletions
|
@ -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 <gst/video/video.h>
|
||||
#include <linux/uvcvideo.h>
|
||||
#include <linux/usb/video.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gstuvch264_src.h"
|
||||
#include <gudev/gudev.h>
|
||||
#include <libusb.h>
|
||||
#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,
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/basecamerabinsrc/gstbasecamerasrc.h>
|
||||
#include <libusb.h>
|
||||
|
||||
#include "uvc_h264.h"
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,25 @@
|
|||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
#include <gst/video/video.h>
|
||||
#include <linux/uvcvideo.h>
|
||||
#include <linux/usb/video.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <gudev/gudev.h>
|
||||
#include <libusb.h>
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <libusb.h>
|
||||
|
||||
#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}
|
||||
|
|
Loading…
Reference in a new issue