/**
- * 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
#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,
"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,
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)
{
/* 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,
}
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;
+}
#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)
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}