Skip to content

Commit 4ffb67b

Browse files
authored
Merge pull request #49 from jwlodek/new-libuvc-version
New version of libuvc library
2 parents 470ca0f + 89f8d2b commit 4ffb67b

File tree

8 files changed

+276
-85
lines changed

8 files changed

+276
-85
lines changed

uvcSupport/libuvc/device.c

Lines changed: 121 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@
4242
int uvc_already_open(uvc_context_t *ctx, struct libusb_device *usb_dev);
4343
void uvc_free_devh(uvc_device_handle_t *devh);
4444

45-
uvc_error_t uvc_get_device_info(uvc_device_t *dev, uvc_device_info_t **info);
45+
uvc_error_t uvc_get_device_info(uvc_device_handle_t *devh, uvc_device_info_t **info);
4646
void uvc_free_device_info(uvc_device_info_t *info);
4747

48-
uvc_error_t uvc_scan_control(uvc_device_t *dev, uvc_device_info_t *info);
48+
uvc_error_t uvc_scan_control(uvc_device_handle_t *devh, uvc_device_info_t *info);
4949
uvc_error_t uvc_parse_vc(uvc_device_t *dev,
5050
uvc_device_info_t *info,
5151
const unsigned char *block, size_t block_size);
@@ -263,6 +263,49 @@ uint8_t uvc_get_device_address(uvc_device_t *dev) {
263263
return libusb_get_device_address(dev->usb_dev);
264264
}
265265

266+
static uvc_error_t uvc_open_internal(uvc_device_t *dev, struct libusb_device_handle *usb_devh, uvc_device_handle_t **devh);
267+
268+
#if LIBUSB_API_VERSION >= 0x01000107
269+
/** @brief Wrap a platform-specific system device handle and obtain a UVC device handle.
270+
* The handle allows you to use libusb to perform I/O on the device in question.
271+
*
272+
* On Linux, the system device handle must be a valid file descriptor opened on the device node.
273+
*
274+
* The system device handle must remain open until uvc_close() is called. The system device handle will not be closed by uvc_close().
275+
* @ingroup device
276+
*
277+
* @param sys_dev the platform-specific system device handle
278+
* @param context UVC context to prepare the device
279+
* @param[out] devh Handle on opened device
280+
* @return Error opening device or SUCCESS
281+
*/
282+
uvc_error_t uvc_wrap(
283+
int sys_dev,
284+
uvc_context_t *context,
285+
uvc_device_handle_t **devh) {
286+
uvc_error_t ret;
287+
struct libusb_device_handle *usb_devh;
288+
289+
UVC_ENTER();
290+
291+
uvc_device_t *dev = NULL;
292+
int err = libusb_wrap_sys_device(context->usb_ctx, sys_dev, &usb_devh);
293+
UVC_DEBUG("libusb_wrap_sys_device() = %d", err);
294+
if (err != LIBUSB_SUCCESS) {
295+
UVC_EXIT(err);
296+
return err;
297+
}
298+
299+
dev = calloc(1, sizeof(uvc_device_t));
300+
dev->ctx = context;
301+
dev->usb_dev = libusb_get_device(usb_devh);
302+
303+
ret = uvc_open_internal(dev, usb_devh, devh);
304+
UVC_EXIT(ret);
305+
return ret;
306+
}
307+
#endif
308+
266309
/** @brief Open a UVC device
267310
* @ingroup device
268311
*
@@ -275,8 +318,6 @@ uvc_error_t uvc_open(
275318
uvc_device_handle_t **devh) {
276319
uvc_error_t ret;
277320
struct libusb_device_handle *usb_devh;
278-
uvc_device_handle_t *internal_devh;
279-
struct libusb_device_descriptor desc;
280321

281322
UVC_ENTER();
282323

@@ -288,13 +329,28 @@ uvc_error_t uvc_open(
288329
return ret;
289330
}
290331

332+
ret = uvc_open_internal(dev, usb_devh, devh);
333+
UVC_EXIT(ret);
334+
return ret;
335+
}
336+
337+
static uvc_error_t uvc_open_internal(
338+
uvc_device_t *dev,
339+
struct libusb_device_handle *usb_devh,
340+
uvc_device_handle_t **devh) {
341+
uvc_error_t ret;
342+
uvc_device_handle_t *internal_devh;
343+
struct libusb_device_descriptor desc;
344+
345+
UVC_ENTER();
346+
291347
uvc_ref_device(dev);
292348

293349
internal_devh = calloc(1, sizeof(*internal_devh));
294350
internal_devh->dev = dev;
295351
internal_devh->usb_devh = usb_devh;
296352

297-
ret = uvc_get_device_info(dev, &(internal_devh->info));
353+
ret = uvc_get_device_info(internal_devh, &(internal_devh->info));
298354

299355
if (ret != UVC_SUCCESS)
300356
goto fail;
@@ -366,7 +422,7 @@ uvc_error_t uvc_open(
366422
* @param dev Device to parse descriptor for
367423
* @param info Where to store a pointer to the new info struct
368424
*/
369-
uvc_error_t uvc_get_device_info(uvc_device_t *dev,
425+
uvc_error_t uvc_get_device_info(uvc_device_handle_t *devh,
370426
uvc_device_info_t **info) {
371427
uvc_error_t ret;
372428
uvc_device_info_t *internal_info;
@@ -379,15 +435,15 @@ uvc_error_t uvc_get_device_info(uvc_device_t *dev,
379435
return UVC_ERROR_NO_MEM;
380436
}
381437

382-
if (libusb_get_config_descriptor(dev->usb_dev,
438+
if (libusb_get_config_descriptor(devh->dev->usb_dev,
383439
0,
384440
&(internal_info->config)) != 0) {
385441
free(internal_info);
386442
UVC_EXIT(UVC_ERROR_IO);
387443
return UVC_ERROR_IO;
388444
}
389445

390-
ret = uvc_scan_control(dev, internal_info);
446+
ret = uvc_scan_control(devh, internal_info);
391447
if (ret != UVC_SUCCESS) {
392448
uvc_free_device_info(internal_info);
393449
UVC_EXIT(ret);
@@ -474,6 +530,53 @@ void uvc_free_device_info(uvc_device_info_t *info) {
474530
UVC_EXIT_VOID();
475531
}
476532

533+
static uvc_error_t get_device_descriptor(
534+
uvc_device_handle_t *devh,
535+
uvc_device_descriptor_t **desc) {
536+
uvc_device_descriptor_t *desc_internal;
537+
struct libusb_device_descriptor usb_desc;
538+
struct libusb_device_handle *usb_devh = devh->usb_devh;
539+
uvc_error_t ret;
540+
541+
UVC_ENTER();
542+
543+
ret = libusb_get_device_descriptor(devh->dev->usb_dev, &usb_desc);
544+
545+
if (ret != UVC_SUCCESS) {
546+
UVC_EXIT(ret);
547+
return ret;
548+
}
549+
550+
desc_internal = calloc(1, sizeof(*desc_internal));
551+
desc_internal->idVendor = usb_desc.idVendor;
552+
desc_internal->idProduct = usb_desc.idProduct;
553+
554+
unsigned char buf[64];
555+
556+
int bytes = libusb_get_string_descriptor_ascii(
557+
usb_devh, usb_desc.iSerialNumber, buf, sizeof(buf));
558+
559+
if (bytes > 0)
560+
desc_internal->serialNumber = strdup((const char*) buf);
561+
562+
bytes = libusb_get_string_descriptor_ascii(
563+
usb_devh, usb_desc.iManufacturer, buf, sizeof(buf));
564+
565+
if (bytes > 0)
566+
desc_internal->manufacturer = strdup((const char*) buf);
567+
568+
bytes = libusb_get_string_descriptor_ascii(
569+
usb_devh, usb_desc.iProduct, buf, sizeof(buf));
570+
571+
if (bytes > 0)
572+
desc_internal->product = strdup((const char*) buf);
573+
574+
*desc = desc_internal;
575+
576+
UVC_EXIT(ret);
577+
return ret;
578+
}
579+
477580
/**
478581
* @brief Get a descriptor that contains the general information about
479582
* a device
@@ -943,7 +1046,7 @@ uvc_error_t uvc_release_if(uvc_device_handle_t *devh, int idx) {
9431046
* Find a device's VideoControl interface and process its descriptor
9441047
* @ingroup device
9451048
*/
946-
uvc_error_t uvc_scan_control(uvc_device_t *dev, uvc_device_info_t *info) {
1049+
uvc_error_t uvc_scan_control(uvc_device_handle_t *devh, uvc_device_info_t *info) {
9471050
const struct libusb_interface_descriptor *if_desc;
9481051
uvc_error_t parse_ret, ret;
9491052
int interface_idx;
@@ -957,12 +1060,13 @@ uvc_error_t uvc_scan_control(uvc_device_t *dev, uvc_device_info_t *info) {
9571060

9581061
uvc_device_descriptor_t* dev_desc;
9591062
int haveTISCamera = 0;
960-
uvc_get_device_descriptor ( dev, &dev_desc );
961-
if ( 0x199e == dev_desc->idVendor && ( 0x8101 == dev_desc->idProduct ||
962-
0x8102 == dev_desc->idProduct )) {
963-
haveTISCamera = 1;
1063+
if ( get_device_descriptor ( devh, &dev_desc ) == UVC_SUCCESS ) {
1064+
if ( 0x199e == dev_desc->idVendor && ( 0x8101 == dev_desc->idProduct ||
1065+
0x8102 == dev_desc->idProduct )) {
1066+
haveTISCamera = 1;
1067+
}
1068+
uvc_free_device_descriptor ( dev_desc );
9641069
}
965-
uvc_free_device_descriptor ( dev_desc );
9661070

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

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

9961100
if (parse_ret != UVC_SUCCESS) {
9971101
ret = parse_ret;
@@ -1029,8 +1133,10 @@ uvc_error_t uvc_parse_vc_header(uvc_device_t *dev,
10291133
switch (info->ctrl_if.bcdUVC) {
10301134
case 0x0100:
10311135
info->ctrl_if.dwClockFrequency = DW_TO_INT(block + 7);
1136+
break;
10321137
case 0x010a:
10331138
info->ctrl_if.dwClockFrequency = DW_TO_INT(block + 7);
1139+
break;
10341140
case 0x0110:
10351141
break;
10361142
default:

uvcSupport/libuvc/frame-mjpeg.c

Lines changed: 58 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -122,32 +122,10 @@ static void insert_huff_tables(j_decompress_ptr dinfo) {
122122
COPY_HUFF_TABLE(dinfo, ac_huff_tbl_ptrs[1], ac_chromi);
123123
}
124124

125-
/** @brief Convert an MJPEG frame to RGB
126-
* @ingroup frame
127-
*
128-
* @param in MJPEG frame
129-
* @param out RGB frame
130-
*/
131-
uvc_error_t uvc_mjpeg2rgb(uvc_frame_t *in, uvc_frame_t *out) {
125+
static uvc_error_t uvc_mjpeg_convert(uvc_frame_t *in, uvc_frame_t *out) {
132126
struct jpeg_decompress_struct dinfo;
133127
struct error_mgr jerr;
134128
size_t lines_read;
135-
136-
if (in->frame_format != UVC_FRAME_FORMAT_MJPEG)
137-
return UVC_ERROR_INVALID_PARAM;
138-
139-
if (uvc_ensure_frame_size(out, in->width * in->height * 3) < 0)
140-
return UVC_ERROR_NO_MEM;
141-
142-
out->width = in->width;
143-
out->height = in->height;
144-
out->frame_format = UVC_FRAME_FORMAT_RGB;
145-
out->step = in->width * 3;
146-
out->sequence = in->sequence;
147-
out->capture_time = in->capture_time;
148-
out->capture_time_finished = in->capture_time_finished;
149-
out->source = in->source;
150-
151129
dinfo.err = jpeg_std_error(&jerr.super);
152130
jerr.super.error_exit = _error_exit;
153131

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

167-
dinfo.out_color_space = JCS_RGB;
145+
if (out->frame_format == UVC_FRAME_FORMAT_RGB)
146+
dinfo.out_color_space = JCS_RGB;
147+
else if (out->frame_format == UVC_FRAME_FORMAT_GRAY8)
148+
dinfo.out_color_space = JCS_GRAYSCALE;
149+
else
150+
goto fail;
151+
168152
dinfo.dct_method = JDCT_IFAST;
169153

170154
jpeg_start_decompress(&dinfo);
@@ -186,3 +170,53 @@ uvc_error_t uvc_mjpeg2rgb(uvc_frame_t *in, uvc_frame_t *out) {
186170
jpeg_destroy_decompress(&dinfo);
187171
return UVC_ERROR_OTHER;
188172
}
173+
174+
/** @brief Convert an MJPEG frame to RGB
175+
* @ingroup frame
176+
*
177+
* @param in MJPEG frame
178+
* @param out RGB frame
179+
*/
180+
uvc_error_t uvc_mjpeg2rgb(uvc_frame_t *in, uvc_frame_t *out) {
181+
if (in->frame_format != UVC_FRAME_FORMAT_MJPEG)
182+
return UVC_ERROR_INVALID_PARAM;
183+
184+
if (uvc_ensure_frame_size(out, in->width * in->height * 3) < 0)
185+
return UVC_ERROR_NO_MEM;
186+
187+
out->width = in->width;
188+
out->height = in->height;
189+
out->frame_format = UVC_FRAME_FORMAT_RGB;
190+
out->step = in->width * 3;
191+
out->sequence = in->sequence;
192+
out->capture_time = in->capture_time;
193+
out->capture_time_finished = in->capture_time_finished;
194+
out->source = in->source;
195+
196+
return uvc_mjpeg_convert(in, out);
197+
}
198+
199+
/** @brief Convert an MJPEG frame to GRAY8
200+
* @ingroup frame
201+
*
202+
* @param in MJPEG frame
203+
* @param out GRAY8 frame
204+
*/
205+
uvc_error_t uvc_mjpeg2gray(uvc_frame_t *in, uvc_frame_t *out) {
206+
if (in->frame_format != UVC_FRAME_FORMAT_MJPEG)
207+
return UVC_ERROR_INVALID_PARAM;
208+
209+
if (uvc_ensure_frame_size(out, in->width * in->height) < 0)
210+
return UVC_ERROR_NO_MEM;
211+
212+
out->width = in->width;
213+
out->height = in->height;
214+
out->frame_format = UVC_FRAME_FORMAT_GRAY8;
215+
out->step = in->width;
216+
out->sequence = in->sequence;
217+
out->capture_time = in->capture_time;
218+
out->capture_time_finished = in->capture_time_finished;
219+
out->source = in->source;
220+
221+
return uvc_mjpeg_convert(in, out);
222+
}

uvcSupport/libuvc/frame.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,10 @@ uvc_error_t uvc_uyvy2bgr(uvc_frame_t *in, uvc_frame_t *out) {
440440
*/
441441
uvc_error_t uvc_any2rgb(uvc_frame_t *in, uvc_frame_t *out) {
442442
switch (in->frame_format) {
443+
#ifdef LIBUVC_HAS_JPEG
444+
case UVC_FRAME_FORMAT_MJPEG:
445+
return uvc_mjpeg2rgb(in, out);
446+
#endif
443447
case UVC_FRAME_FORMAT_YUYV:
444448
return uvc_yuyv2rgb(in, out);
445449
case UVC_FRAME_FORMAT_UYVY:

uvcSupport/libuvc/init.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,11 @@ for USB Video Class (UVC) devices, such as consumer webcams.
5151
\li Support for "extended" (vendor-defined) settings
5252
5353
\section misc Misc.
54-
\p The source code can be found at https://github.com/ktossell/libuvc. To build
55-
the library, install <a href="http://libusb.org/">libusb</a> 1.0+ and run:
54+
\p The source code can be found at https://github.com/libuvc/libuvc/. To build
55+
the library, install <a href="https://libusb.info/">libusb</a> 1.0+ and run:
5656
5757
\code
58-
$ git clone https://github.com/ktossell/libuvc.git
58+
$ git clone https://github.com/libuvc/libuvc.git
5959
$ cd libuvc
6060
$ mkdir build
6161
$ cd build

uvcSupport/libuvc/libuvc/libuvc.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ enum uvc_frame_format {
7272
UVC_FRAME_FORMAT_BGR,
7373
/** Motion-JPEG (or JPEG) encoded images */
7474
UVC_FRAME_FORMAT_MJPEG,
75+
UVC_FRAME_FORMAT_H264,
7576
/** Greyscale images */
7677
UVC_FRAME_FORMAT_GRAY8,
7778
UVC_FRAME_FORMAT_GRAY16,
@@ -84,6 +85,8 @@ enum uvc_frame_format {
8485
UVC_FRAME_FORMAT_SBGGR8,
8586
/** YUV420: NV12 */
8687
UVC_FRAME_FORMAT_NV12,
88+
/** YUV: P010 */
89+
UVC_FRAME_FORMAT_P010,
8790
/** Number of formats understood */
8891
UVC_FRAME_FORMAT_COUNT,
8992
};
@@ -553,6 +556,13 @@ uvc_error_t uvc_find_devices(
553556
uvc_device_t ***devs,
554557
int vid, int pid, const char *sn);
555558

559+
#if LIBUSB_API_VERSION >= 0x01000107
560+
uvc_error_t uvc_wrap(
561+
int sys_dev,
562+
uvc_context_t *context,
563+
uvc_device_handle_t **devh);
564+
#endif
565+
556566
uvc_error_t uvc_open(
557567
uvc_device_t *dev,
558568
uvc_device_handle_t **devh);
@@ -791,6 +801,7 @@ uvc_error_t uvc_yuyv2uv(uvc_frame_t *in, uvc_frame_t *out);
791801

792802
#ifdef LIBUVC_HAS_JPEG
793803
uvc_error_t uvc_mjpeg2rgb(uvc_frame_t *in, uvc_frame_t *out);
804+
uvc_error_t uvc_mjpeg2gray(uvc_frame_t *in, uvc_frame_t *out);
794805
#endif
795806

796807
#ifdef __cplusplus

0 commit comments

Comments
 (0)