Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 121 additions & 15 deletions uvcSupport/libuvc/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@
int uvc_already_open(uvc_context_t *ctx, struct libusb_device *usb_dev);
void uvc_free_devh(uvc_device_handle_t *devh);

uvc_error_t uvc_get_device_info(uvc_device_t *dev, uvc_device_info_t **info);
uvc_error_t uvc_get_device_info(uvc_device_handle_t *devh, uvc_device_info_t **info);
void uvc_free_device_info(uvc_device_info_t *info);

uvc_error_t uvc_scan_control(uvc_device_t *dev, uvc_device_info_t *info);
uvc_error_t uvc_scan_control(uvc_device_handle_t *devh, uvc_device_info_t *info);
uvc_error_t uvc_parse_vc(uvc_device_t *dev,
uvc_device_info_t *info,
const unsigned char *block, size_t block_size);
Expand Down Expand Up @@ -263,6 +263,49 @@ uint8_t uvc_get_device_address(uvc_device_t *dev) {
return libusb_get_device_address(dev->usb_dev);
}

static uvc_error_t uvc_open_internal(uvc_device_t *dev, struct libusb_device_handle *usb_devh, uvc_device_handle_t **devh);

#if LIBUSB_API_VERSION >= 0x01000107
/** @brief Wrap a platform-specific system device handle and obtain a UVC device handle.
* The handle allows you to use libusb to perform I/O on the device in question.
*
* On Linux, the system device handle must be a valid file descriptor opened on the device node.
*
* The system device handle must remain open until uvc_close() is called. The system device handle will not be closed by uvc_close().
* @ingroup device
*
* @param sys_dev the platform-specific system device handle
* @param context UVC context to prepare the device
* @param[out] devh Handle on opened device
* @return Error opening device or SUCCESS
*/
uvc_error_t uvc_wrap(
int sys_dev,
uvc_context_t *context,
uvc_device_handle_t **devh) {
uvc_error_t ret;
struct libusb_device_handle *usb_devh;

UVC_ENTER();

uvc_device_t *dev = NULL;
int err = libusb_wrap_sys_device(context->usb_ctx, sys_dev, &usb_devh);
UVC_DEBUG("libusb_wrap_sys_device() = %d", err);
if (err != LIBUSB_SUCCESS) {
UVC_EXIT(err);
return err;
}

dev = calloc(1, sizeof(uvc_device_t));
dev->ctx = context;
dev->usb_dev = libusb_get_device(usb_devh);

ret = uvc_open_internal(dev, usb_devh, devh);
UVC_EXIT(ret);
return ret;
}
#endif

/** @brief Open a UVC device
* @ingroup device
*
Expand All @@ -275,8 +318,6 @@ uvc_error_t uvc_open(
uvc_device_handle_t **devh) {
uvc_error_t ret;
struct libusb_device_handle *usb_devh;
uvc_device_handle_t *internal_devh;
struct libusb_device_descriptor desc;

UVC_ENTER();

Expand All @@ -288,13 +329,28 @@ uvc_error_t uvc_open(
return ret;
}

ret = uvc_open_internal(dev, usb_devh, devh);
UVC_EXIT(ret);
return ret;
}

static uvc_error_t uvc_open_internal(
uvc_device_t *dev,
struct libusb_device_handle *usb_devh,
uvc_device_handle_t **devh) {
uvc_error_t ret;
uvc_device_handle_t *internal_devh;
struct libusb_device_descriptor desc;

UVC_ENTER();

uvc_ref_device(dev);

internal_devh = calloc(1, sizeof(*internal_devh));
internal_devh->dev = dev;
internal_devh->usb_devh = usb_devh;

ret = uvc_get_device_info(dev, &(internal_devh->info));
ret = uvc_get_device_info(internal_devh, &(internal_devh->info));

if (ret != UVC_SUCCESS)
goto fail;
Expand Down Expand Up @@ -366,7 +422,7 @@ uvc_error_t uvc_open(
* @param dev Device to parse descriptor for
* @param info Where to store a pointer to the new info struct
*/
uvc_error_t uvc_get_device_info(uvc_device_t *dev,
uvc_error_t uvc_get_device_info(uvc_device_handle_t *devh,
uvc_device_info_t **info) {
uvc_error_t ret;
uvc_device_info_t *internal_info;
Expand All @@ -379,15 +435,15 @@ uvc_error_t uvc_get_device_info(uvc_device_t *dev,
return UVC_ERROR_NO_MEM;
}

if (libusb_get_config_descriptor(dev->usb_dev,
if (libusb_get_config_descriptor(devh->dev->usb_dev,
0,
&(internal_info->config)) != 0) {
free(internal_info);
UVC_EXIT(UVC_ERROR_IO);
return UVC_ERROR_IO;
}

ret = uvc_scan_control(dev, internal_info);
ret = uvc_scan_control(devh, internal_info);
if (ret != UVC_SUCCESS) {
uvc_free_device_info(internal_info);
UVC_EXIT(ret);
Expand Down Expand Up @@ -474,6 +530,53 @@ void uvc_free_device_info(uvc_device_info_t *info) {
UVC_EXIT_VOID();
}

static uvc_error_t get_device_descriptor(
uvc_device_handle_t *devh,
uvc_device_descriptor_t **desc) {
uvc_device_descriptor_t *desc_internal;
struct libusb_device_descriptor usb_desc;
struct libusb_device_handle *usb_devh = devh->usb_devh;
uvc_error_t ret;

UVC_ENTER();

ret = libusb_get_device_descriptor(devh->dev->usb_dev, &usb_desc);

if (ret != UVC_SUCCESS) {
UVC_EXIT(ret);
return ret;
}

desc_internal = calloc(1, sizeof(*desc_internal));
desc_internal->idVendor = usb_desc.idVendor;
desc_internal->idProduct = usb_desc.idProduct;

unsigned char buf[64];

int bytes = libusb_get_string_descriptor_ascii(
usb_devh, usb_desc.iSerialNumber, buf, sizeof(buf));

if (bytes > 0)
desc_internal->serialNumber = strdup((const char*) buf);

bytes = libusb_get_string_descriptor_ascii(
usb_devh, usb_desc.iManufacturer, buf, sizeof(buf));

if (bytes > 0)
desc_internal->manufacturer = strdup((const char*) buf);

bytes = libusb_get_string_descriptor_ascii(
usb_devh, usb_desc.iProduct, buf, sizeof(buf));

if (bytes > 0)
desc_internal->product = strdup((const char*) buf);

*desc = desc_internal;

UVC_EXIT(ret);
return ret;
}

/**
* @brief Get a descriptor that contains the general information about
* a device
Expand Down Expand Up @@ -943,7 +1046,7 @@ uvc_error_t uvc_release_if(uvc_device_handle_t *devh, int idx) {
* Find a device's VideoControl interface and process its descriptor
* @ingroup device
*/
uvc_error_t uvc_scan_control(uvc_device_t *dev, uvc_device_info_t *info) {
uvc_error_t uvc_scan_control(uvc_device_handle_t *devh, uvc_device_info_t *info) {
const struct libusb_interface_descriptor *if_desc;
uvc_error_t parse_ret, ret;
int interface_idx;
Expand All @@ -957,12 +1060,13 @@ uvc_error_t uvc_scan_control(uvc_device_t *dev, uvc_device_info_t *info) {

uvc_device_descriptor_t* dev_desc;
int haveTISCamera = 0;
uvc_get_device_descriptor ( dev, &dev_desc );
if ( 0x199e == dev_desc->idVendor && ( 0x8101 == dev_desc->idProduct ||
0x8102 == dev_desc->idProduct )) {
haveTISCamera = 1;
if ( get_device_descriptor ( devh, &dev_desc ) == UVC_SUCCESS ) {
if ( 0x199e == dev_desc->idVendor && ( 0x8101 == dev_desc->idProduct ||
0x8102 == dev_desc->idProduct )) {
haveTISCamera = 1;
}
uvc_free_device_descriptor ( dev_desc );
}
uvc_free_device_descriptor ( dev_desc );

for (interface_idx = 0; interface_idx < info->config->bNumInterfaces; ++interface_idx) {
if_desc = &info->config->interface[interface_idx].altsetting[0];
Expand Down Expand Up @@ -991,7 +1095,7 @@ uvc_error_t uvc_scan_control(uvc_device_t *dev, uvc_device_info_t *info) {

while (buffer_left >= 3) { // parseX needs to see buf[0,2] = length,type
block_size = buffer[0];
parse_ret = uvc_parse_vc(dev, info, buffer, block_size);
parse_ret = uvc_parse_vc(devh->dev, info, buffer, block_size);

if (parse_ret != UVC_SUCCESS) {
ret = parse_ret;
Expand Down Expand Up @@ -1029,8 +1133,10 @@ uvc_error_t uvc_parse_vc_header(uvc_device_t *dev,
switch (info->ctrl_if.bcdUVC) {
case 0x0100:
info->ctrl_if.dwClockFrequency = DW_TO_INT(block + 7);
break;
case 0x010a:
info->ctrl_if.dwClockFrequency = DW_TO_INT(block + 7);
break;
case 0x0110:
break;
default:
Expand Down
82 changes: 58 additions & 24 deletions uvcSupport/libuvc/frame-mjpeg.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,32 +122,10 @@ static void insert_huff_tables(j_decompress_ptr dinfo) {
COPY_HUFF_TABLE(dinfo, ac_huff_tbl_ptrs[1], ac_chromi);
}

/** @brief Convert an MJPEG frame to RGB
* @ingroup frame
*
* @param in MJPEG frame
* @param out RGB frame
*/
uvc_error_t uvc_mjpeg2rgb(uvc_frame_t *in, uvc_frame_t *out) {
static uvc_error_t uvc_mjpeg_convert(uvc_frame_t *in, uvc_frame_t *out) {
struct jpeg_decompress_struct dinfo;
struct error_mgr jerr;
size_t lines_read;

if (in->frame_format != UVC_FRAME_FORMAT_MJPEG)
return UVC_ERROR_INVALID_PARAM;

if (uvc_ensure_frame_size(out, in->width * in->height * 3) < 0)
return UVC_ERROR_NO_MEM;

out->width = in->width;
out->height = in->height;
out->frame_format = UVC_FRAME_FORMAT_RGB;
out->step = in->width * 3;
out->sequence = in->sequence;
out->capture_time = in->capture_time;
out->capture_time_finished = in->capture_time_finished;
out->source = in->source;

dinfo.err = jpeg_std_error(&jerr.super);
jerr.super.error_exit = _error_exit;

Expand All @@ -164,7 +142,13 @@ uvc_error_t uvc_mjpeg2rgb(uvc_frame_t *in, uvc_frame_t *out) {
insert_huff_tables(&dinfo);
}

dinfo.out_color_space = JCS_RGB;
if (out->frame_format == UVC_FRAME_FORMAT_RGB)
dinfo.out_color_space = JCS_RGB;
else if (out->frame_format == UVC_FRAME_FORMAT_GRAY8)
dinfo.out_color_space = JCS_GRAYSCALE;
else
goto fail;

dinfo.dct_method = JDCT_IFAST;

jpeg_start_decompress(&dinfo);
Expand All @@ -186,3 +170,53 @@ uvc_error_t uvc_mjpeg2rgb(uvc_frame_t *in, uvc_frame_t *out) {
jpeg_destroy_decompress(&dinfo);
return UVC_ERROR_OTHER;
}

/** @brief Convert an MJPEG frame to RGB
* @ingroup frame
*
* @param in MJPEG frame
* @param out RGB frame
*/
uvc_error_t uvc_mjpeg2rgb(uvc_frame_t *in, uvc_frame_t *out) {
if (in->frame_format != UVC_FRAME_FORMAT_MJPEG)
return UVC_ERROR_INVALID_PARAM;

if (uvc_ensure_frame_size(out, in->width * in->height * 3) < 0)
return UVC_ERROR_NO_MEM;

out->width = in->width;
out->height = in->height;
out->frame_format = UVC_FRAME_FORMAT_RGB;
out->step = in->width * 3;
out->sequence = in->sequence;
out->capture_time = in->capture_time;
out->capture_time_finished = in->capture_time_finished;
out->source = in->source;

return uvc_mjpeg_convert(in, out);
}

/** @brief Convert an MJPEG frame to GRAY8
* @ingroup frame
*
* @param in MJPEG frame
* @param out GRAY8 frame
*/
uvc_error_t uvc_mjpeg2gray(uvc_frame_t *in, uvc_frame_t *out) {
if (in->frame_format != UVC_FRAME_FORMAT_MJPEG)
return UVC_ERROR_INVALID_PARAM;

if (uvc_ensure_frame_size(out, in->width * in->height) < 0)
return UVC_ERROR_NO_MEM;

out->width = in->width;
out->height = in->height;
out->frame_format = UVC_FRAME_FORMAT_GRAY8;
out->step = in->width;
out->sequence = in->sequence;
out->capture_time = in->capture_time;
out->capture_time_finished = in->capture_time_finished;
out->source = in->source;

return uvc_mjpeg_convert(in, out);
}
4 changes: 4 additions & 0 deletions uvcSupport/libuvc/frame.c
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,10 @@ uvc_error_t uvc_uyvy2bgr(uvc_frame_t *in, uvc_frame_t *out) {
*/
uvc_error_t uvc_any2rgb(uvc_frame_t *in, uvc_frame_t *out) {
switch (in->frame_format) {
#ifdef LIBUVC_HAS_JPEG
case UVC_FRAME_FORMAT_MJPEG:
return uvc_mjpeg2rgb(in, out);
#endif
case UVC_FRAME_FORMAT_YUYV:
return uvc_yuyv2rgb(in, out);
case UVC_FRAME_FORMAT_UYVY:
Expand Down
6 changes: 3 additions & 3 deletions uvcSupport/libuvc/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ for USB Video Class (UVC) devices, such as consumer webcams.
\li Support for "extended" (vendor-defined) settings

\section misc Misc.
\p The source code can be found at https://github.com/ktossell/libuvc. To build
the library, install <a href="http://libusb.org/">libusb</a> 1.0+ and run:
\p The source code can be found at https://github.com/libuvc/libuvc/. To build
the library, install <a href="https://libusb.info/">libusb</a> 1.0+ and run:

\code
$ git clone https://github.com/ktossell/libuvc.git
$ git clone https://github.com/libuvc/libuvc.git
$ cd libuvc
$ mkdir build
$ cd build
Expand Down
11 changes: 11 additions & 0 deletions uvcSupport/libuvc/libuvc/libuvc.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ enum uvc_frame_format {
UVC_FRAME_FORMAT_BGR,
/** Motion-JPEG (or JPEG) encoded images */
UVC_FRAME_FORMAT_MJPEG,
UVC_FRAME_FORMAT_H264,
/** Greyscale images */
UVC_FRAME_FORMAT_GRAY8,
UVC_FRAME_FORMAT_GRAY16,
Expand All @@ -84,6 +85,8 @@ enum uvc_frame_format {
UVC_FRAME_FORMAT_SBGGR8,
/** YUV420: NV12 */
UVC_FRAME_FORMAT_NV12,
/** YUV: P010 */
UVC_FRAME_FORMAT_P010,
/** Number of formats understood */
UVC_FRAME_FORMAT_COUNT,
};
Expand Down Expand Up @@ -553,6 +556,13 @@ uvc_error_t uvc_find_devices(
uvc_device_t ***devs,
int vid, int pid, const char *sn);

#if LIBUSB_API_VERSION >= 0x01000107
uvc_error_t uvc_wrap(
int sys_dev,
uvc_context_t *context,
uvc_device_handle_t **devh);
#endif

uvc_error_t uvc_open(
uvc_device_t *dev,
uvc_device_handle_t **devh);
Expand Down Expand Up @@ -791,6 +801,7 @@ uvc_error_t uvc_yuyv2uv(uvc_frame_t *in, uvc_frame_t *out);

#ifdef LIBUVC_HAS_JPEG
uvc_error_t uvc_mjpeg2rgb(uvc_frame_t *in, uvc_frame_t *out);
uvc_error_t uvc_mjpeg2gray(uvc_frame_t *in, uvc_frame_t *out);
#endif

#ifdef __cplusplus
Expand Down
Loading