1 /*********************************************************************
2 * Software License Agreement (BSD License)
4 * Copyright (C) 2010-2012 Ken Tossell
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * * Neither the name of the author nor other contributors may be
18 * used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *********************************************************************/
35 * @defgroup streaming Streaming control functions
38 #include "libuvc/libuvc.h"
39 #include "libuvc/libuvc_internal.h"
41 uvc_frame_desc_t *uvc_find_frame_desc_stream(uvc_stream_handle_t *strmh,
42 uint16_t format_id, uint16_t frame_id);
43 uvc_frame_desc_t *uvc_find_frame_desc(uvc_device_handle_t *devh,
44 uint16_t format_id, uint16_t frame_id);
45 void *_uvc_user_caller(void *arg);
46 void _uvc_populate_frame(uvc_stream_handle_t *strmh);
48 struct format_table_entry {
49 enum uvc_frame_format format;
53 enum uvc_frame_format *children;
56 struct format_table_entry *_get_format_entry(enum uvc_frame_format format) {
57 #define ABS_FMT(_fmt, ...) \
59 static enum uvc_frame_format _fmt##_children[] = __VA_ARGS__; \
60 static struct format_table_entry _fmt##_entry = { \
61 _fmt, 0, {}, ARRAYSIZE(_fmt##_children), _fmt##_children }; \
62 return &_fmt##_entry; }
64 #define FMT(_fmt, ...) \
66 static struct format_table_entry _fmt##_entry = { \
67 _fmt, 0, __VA_ARGS__, 0, NULL }; \
68 return &_fmt##_entry; }
71 /* Define new formats here */
72 ABS_FMT(UVC_FRAME_FORMAT_ANY,
73 {UVC_FRAME_FORMAT_UNCOMPRESSED, UVC_FRAME_FORMAT_COMPRESSED})
75 ABS_FMT(UVC_FRAME_FORMAT_UNCOMPRESSED,
76 {UVC_FRAME_FORMAT_YUYV, UVC_FRAME_FORMAT_UYVY, UVC_FRAME_FORMAT_GRAY8})
77 FMT(UVC_FRAME_FORMAT_YUYV,
78 {'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71})
79 FMT(UVC_FRAME_FORMAT_UYVY,
80 {'U', 'Y', 'V', 'Y', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71})
81 FMT(UVC_FRAME_FORMAT_GRAY8,
82 {'Y', '8', '0', '0', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71})
84 ABS_FMT(UVC_FRAME_FORMAT_COMPRESSED,
85 {UVC_FRAME_FORMAT_MJPEG})
86 FMT(UVC_FRAME_FORMAT_MJPEG,
97 static uint8_t _uvc_frame_format_matches_guid(enum uvc_frame_format fmt, uint8_t guid[16]) {
98 struct format_table_entry *format;
101 format = _get_format_entry(fmt);
105 if (!format->abstract_fmt && !memcmp(guid, format->guid, 16))
108 for (child_idx = 0; child_idx < format->children_count; child_idx++) {
109 if (_uvc_frame_format_matches_guid(format->children[child_idx], guid))
116 static enum uvc_frame_format uvc_frame_format_for_guid(uint8_t guid[16]) {
117 struct format_table_entry *format;
118 enum uvc_frame_format fmt;
120 for (fmt = 0; fmt < UVC_FRAME_FORMAT_COUNT; ++fmt) {
121 format = _get_format_entry(fmt);
122 if (!format || format->abstract_fmt)
124 if (!memcmp(format->guid, guid, 16))
125 return format->format;
128 return UVC_FRAME_FORMAT_UNKNOWN;
132 * Run a streaming control query
133 * @param[in] devh UVC device
134 * @param[in,out] ctrl Control block
135 * @param[in] probe Whether this is a probe query or a commit query
136 * @param[in] req Query type
138 uvc_error_t uvc_query_stream_ctrl(
139 uvc_device_handle_t *devh,
140 uvc_stream_ctrl_t *ctrl,
142 enum uvc_req_code req) {
147 bzero(buf, sizeof(buf));
149 if (devh->info->ctrl_if.bcdUVC >= 0x0110)
154 /* prepare for a SET transfer */
155 if (req == UVC_SET_CUR) {
156 SHORT_TO_SW(ctrl->bmHint, buf);
157 buf[2] = ctrl->bFormatIndex;
158 buf[3] = ctrl->bFrameIndex;
159 INT_TO_DW(ctrl->dwFrameInterval, buf + 4);
160 SHORT_TO_SW(ctrl->wKeyFrameRate, buf + 8);
161 SHORT_TO_SW(ctrl->wPFrameRate, buf + 10);
162 SHORT_TO_SW(ctrl->wCompQuality, buf + 12);
163 SHORT_TO_SW(ctrl->wCompWindowSize, buf + 14);
164 SHORT_TO_SW(ctrl->wDelay, buf + 16);
165 INT_TO_DW(ctrl->dwMaxVideoFrameSize, buf + 18);
166 INT_TO_DW(ctrl->dwMaxPayloadTransferSize, buf + 22);
169 /** @todo support UVC 1.1 */
170 return UVC_ERROR_NOT_SUPPORTED;
174 /* do the transfer */
175 err = libusb_control_transfer(
177 req == UVC_SET_CUR ? 0x21 : 0xA1,
179 probe ? (UVC_VS_PROBE_CONTROL << 8) : (UVC_VS_COMMIT_CONTROL << 8),
180 ctrl->bInterfaceNumber,
188 /* now decode following a GET transfer */
189 if (req != UVC_SET_CUR) {
190 ctrl->bmHint = SW_TO_SHORT(buf);
191 ctrl->bFormatIndex = buf[2];
192 ctrl->bFrameIndex = buf[3];
193 ctrl->dwFrameInterval = DW_TO_INT(buf + 4);
194 ctrl->wKeyFrameRate = SW_TO_SHORT(buf + 8);
195 ctrl->wPFrameRate = SW_TO_SHORT(buf + 10);
196 ctrl->wCompQuality = SW_TO_SHORT(buf + 12);
197 ctrl->wCompWindowSize = SW_TO_SHORT(buf + 14);
198 ctrl->wDelay = SW_TO_SHORT(buf + 16);
199 ctrl->dwMaxVideoFrameSize = DW_TO_INT(buf + 18);
200 ctrl->dwMaxPayloadTransferSize = DW_TO_INT(buf + 22);
203 /** @todo support UVC 1.1 */
204 return UVC_ERROR_NOT_SUPPORTED;
207 /* fix up block for cameras that fail to set dwMax* */
208 if (ctrl->dwMaxVideoFrameSize == 0) {
209 uvc_frame_desc_t *frame = uvc_find_frame_desc(devh, ctrl->bFormatIndex, ctrl->bFrameIndex);
212 ctrl->dwMaxVideoFrameSize = frame->dwMaxVideoFrameBufferSize;
220 /** @brief Reconfigure stream with a new stream format.
223 * This may be executed whether or not the stream is running.
225 * @param[in] strmh Stream handle
226 * @param[in] ctrl Control block, processed using {uvc_probe_stream_ctrl} or
227 * {uvc_get_stream_ctrl_format_size}
229 uvc_error_t uvc_stream_ctrl(uvc_stream_handle_t *strmh, uvc_stream_ctrl_t *ctrl) {
232 if (strmh->stream_if->bInterfaceNumber != ctrl->bInterfaceNumber)
233 return UVC_ERROR_INVALID_PARAM;
235 /* @todo Allow the stream to be modified without restarting the stream */
237 return UVC_ERROR_BUSY;
239 ret = uvc_query_stream_ctrl(strmh->devh, ctrl, 0, UVC_SET_CUR);
240 if (ret != UVC_SUCCESS)
243 strmh->cur_ctrl = *ctrl;
248 * @brief Find the descriptor for a specific frame configuration
249 * @param stream_if Stream interface
250 * @param format_id Index of format class descriptor
251 * @param frame_id Index of frame descriptor
253 static uvc_frame_desc_t *_uvc_find_frame_desc_stream_if(uvc_streaming_interface_t *stream_if,
254 uint16_t format_id, uint16_t frame_id) {
256 uvc_format_desc_t *format = NULL;
257 uvc_frame_desc_t *frame = NULL;
259 DL_FOREACH(stream_if->format_descs, format) {
260 if (format->bFormatIndex == format_id) {
261 DL_FOREACH(format->frame_descs, frame) {
262 if (frame->bFrameIndex == frame_id)
271 uvc_frame_desc_t *uvc_find_frame_desc_stream(uvc_stream_handle_t *strmh,
272 uint16_t format_id, uint16_t frame_id) {
273 return _uvc_find_frame_desc_stream_if(strmh->stream_if, format_id, frame_id);
277 * @brief Find the descriptor for a specific frame configuration
278 * @param devh UVC device
279 * @param format_id Index of format class descriptor
280 * @param frame_id Index of frame descriptor
282 uvc_frame_desc_t *uvc_find_frame_desc(uvc_device_handle_t *devh,
283 uint16_t format_id, uint16_t frame_id) {
285 uvc_streaming_interface_t *stream_if;
286 uvc_frame_desc_t *frame;
288 DL_FOREACH(devh->info->stream_ifs, stream_if) {
289 frame = _uvc_find_frame_desc_stream_if(stream_if, format_id, frame_id);
297 /** Get a negotiated streaming control block for some common parameters.
300 * @param[in] devh Device handle
301 * @param[in,out] ctrl Control block
302 * @param[in] format_class Type of streaming format
303 * @param[in] width Desired frame width
304 * @param[in] height Desired frame height
305 * @param[in] fps Frame rate, frames per second
307 uvc_error_t uvc_get_stream_ctrl_format_size(
308 uvc_device_handle_t *devh,
309 uvc_stream_ctrl_t *ctrl,
310 enum uvc_frame_format cf,
311 int width, int height,
313 uvc_streaming_interface_t *stream_if;
314 enum uvc_vs_desc_subtype format_class;
316 /* get the max values */
317 uvc_query_stream_ctrl(
318 devh, ctrl, 1, UVC_GET_MAX
321 /* find a matching frame descriptor and interval */
322 DL_FOREACH(devh->info->stream_ifs, stream_if) {
323 uvc_format_desc_t *format;
325 DL_FOREACH(stream_if->format_descs, format) {
326 uvc_frame_desc_t *frame;
328 if (!_uvc_frame_format_matches_guid(cf, format->guidFormat))
331 DL_FOREACH(format->frame_descs, frame) {
332 if (frame->wWidth != width || frame->wHeight != height)
337 if (frame->intervals) {
338 for (interval = frame->intervals; *interval; ++interval) {
339 if (10000000 / *interval == (unsigned int) fps) {
340 ctrl->bmHint = (1 << 0); /* don't negotiate interval */
341 ctrl->bFormatIndex = format->bFormatIndex;
342 ctrl->bFrameIndex = frame->bFrameIndex;
343 ctrl->bInterfaceNumber = stream_if->bInterfaceNumber;
344 ctrl->dwFrameInterval = *interval;
350 uint32_t interval_100ns = 10000000 / fps;
351 uint32_t interval_offset = interval_100ns - frame->dwMinFrameInterval;
353 if (interval_100ns >= frame->dwMinFrameInterval
354 && interval_100ns <= frame->dwMaxFrameInterval
356 && (interval_offset % frame->dwFrameIntervalStep))) {
357 ctrl->bmHint = (1 << 0);
358 ctrl->bFormatIndex = format->bFormatIndex;
359 ctrl->bFrameIndex = frame->bFrameIndex;
360 ctrl->bInterfaceNumber = stream_if->bInterfaceNumber;
361 ctrl->dwFrameInterval = interval_100ns;
370 return UVC_ERROR_INVALID_MODE;
373 return uvc_probe_stream_ctrl(devh, ctrl);
377 * Negotiate streaming parameters with the device
379 * @param[in] devh UVC device
380 * @param[in,out] ctrl Control block
382 uvc_error_t uvc_probe_stream_ctrl(
383 uvc_device_handle_t *devh,
384 uvc_stream_ctrl_t *ctrl) {
386 uvc_claim_if(devh, ctrl->bInterfaceNumber);
388 uvc_query_stream_ctrl(
389 devh, ctrl, 1, UVC_SET_CUR
392 uvc_query_stream_ctrl(
393 devh, ctrl, 1, UVC_GET_CUR
396 /** @todo make sure that worked */
401 * @brief Isochronous transfer callback
403 * Processes stream, places frames into buffer, signals listeners
404 * (such as user callback thread and any polling thread) on new frame
406 * @param transfer Active transfer
408 void _uvc_iso_callback(struct libusb_transfer *transfer) {
409 uvc_stream_handle_t *strmh;
414 uint8_t check_header;
416 struct libusb_iso_packet_descriptor *pkt;
419 static uint8_t isight_tag[] = {
420 0x11, 0x22, 0x33, 0x44,
421 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xfa, 0xce
424 strmh = transfer->user_data;
426 switch (transfer->status) {
427 case LIBUSB_TRANSFER_COMPLETED:
428 for (packet_id = 0; packet_id < transfer->num_iso_packets; ++packet_id) {
431 pkt = transfer->iso_packet_desc + packet_id;
433 if (pkt->status != 0) {
434 printf("bad packet (transfer): %d\n", pkt->status);
438 if (pkt->actual_length == 0) {
442 pktbuf = libusb_get_iso_packet_buffer_simple(transfer, packet_id);
444 if (strmh->devh->is_isight) {
445 if (pkt->actual_length < 30 ||
446 (memcmp(isight_tag, pktbuf + 2, sizeof(isight_tag))
447 && memcmp(isight_tag, pktbuf + 3, sizeof(isight_tag)))) {
451 header_len = pktbuf[0];
454 header_len = pktbuf[0];
457 if (check_header && pktbuf[1] & 0x40) {
458 printf("bad packet\n");
462 /** @todo support sending the frame on EOF instead of on flip(FID) */
463 if (check_header && strmh->fid != (pktbuf[1] & 1)) {
464 pthread_mutex_lock(&strmh->cb_mutex);
466 /* swap the buffers */
467 tmp_buf = strmh->holdbuf;
468 strmh->hold_bytes = strmh->got_bytes;
469 strmh->holdbuf = strmh->outbuf;
470 strmh->outbuf = tmp_buf;
471 strmh->hold_last_scr = strmh->last_scr;
472 strmh->hold_pts = strmh->pts;
473 strmh->hold_seq = strmh->seq;
475 pthread_cond_broadcast(&strmh->cb_cond);
476 pthread_mutex_unlock(&strmh->cb_mutex);
479 strmh->got_bytes = 0;
482 strmh->fid = pktbuf[1] & 1;
486 if (pktbuf[1] & (1 << 2))
487 strmh->pts = DW_TO_INT(pktbuf + 2);
489 if (pktbuf[1] & (1 << 3))
490 strmh->last_scr = DW_TO_INT(pktbuf + 6);
492 if (strmh->devh->is_isight)
493 continue; // don't look for data after an iSight header
496 if (pkt->actual_length < header_len) {
497 /* Bogus packet received */
498 printf("bogus packet: actual_len=%d, header_len=%zd\n", pkt->actual_length, header_len);
501 if (pkt->actual_length - header_len > 0)
502 memcpy(strmh->outbuf + strmh->got_bytes, pktbuf + header_len, pkt->actual_length - header_len);
504 strmh->got_bytes += pkt->actual_length - header_len;
507 case LIBUSB_TRANSFER_CANCELLED:
508 case LIBUSB_TRANSFER_ERROR:
509 case LIBUSB_TRANSFER_NO_DEVICE: {
511 UVC_DEBUG("not retrying transfer, status = %d", transfer->status);
512 pthread_mutex_lock(&strmh->cb_mutex);
514 /* Mark transfer as deleted. */
515 for(i=0; i<ARRAYSIZE(strmh->transfers); i++) {
516 if(strmh->transfers[i] == transfer) {
517 UVC_DEBUG("Freeing transfer %d (%p)", i, transfer);
518 free(transfer->buffer);
519 libusb_free_transfer(transfer);
520 strmh->transfers[i] = NULL;
524 if(i == ARRAYSIZE(strmh->transfers)) {
525 UVC_DEBUG("transfer %p not found; not freeing!", transfer);
528 pthread_cond_broadcast(&strmh->cb_cond);
529 pthread_mutex_unlock(&strmh->cb_mutex);
533 case LIBUSB_TRANSFER_TIMED_OUT:
534 case LIBUSB_TRANSFER_STALL:
535 case LIBUSB_TRANSFER_OVERFLOW:
536 UVC_DEBUG("retrying transfer, status = %d", transfer->status);
541 libusb_submit_transfer(transfer);
544 /** Begin streaming video from the camera into the callback function.
547 * @param devh UVC device
548 * @param ctrl Control block, processed using {uvc_probe_stream_ctrl} or
549 * {uvc_get_stream_ctrl_format_size}
550 * @param cb User callback function. See {uvc_frame_callback_t} for restrictions.
551 * @param isochronous Whether to use isochronous transfers rather than bulk ones
553 uvc_error_t uvc_start_streaming(
554 uvc_device_handle_t *devh,
555 uvc_stream_ctrl_t *ctrl,
556 uvc_frame_callback_t *cb,
561 uvc_stream_handle_t *strmh;
563 ret = uvc_stream_open_ctrl(devh, &strmh, ctrl);
564 if (ret != UVC_SUCCESS)
567 ret = uvc_stream_start(strmh, cb, user_ptr, isochronous);
568 if (ret != UVC_SUCCESS) {
569 uvc_stream_close(strmh);
576 /** Begin streaming video from the camera into the callback function.
579 * @param devh UVC device
580 * @param ctrl Control block, processed using {uvc_probe_stream_ctrl} or
581 * {uvc_get_stream_ctrl_format_size}
582 * @param cb User callback function. See {uvc_frame_callback_t} for restrictions.
584 uvc_error_t uvc_start_iso_streaming(
585 uvc_device_handle_t *devh,
586 uvc_stream_ctrl_t *ctrl,
587 uvc_frame_callback_t *cb,
590 return uvc_start_streaming(devh, ctrl, cb, user_ptr, 1);
593 static uvc_stream_handle_t *_uvc_get_stream_by_interface(uvc_device_handle_t *devh, int interface_idx) {
594 uvc_stream_handle_t *strmh;
596 DL_FOREACH(devh->streams, strmh) {
597 if (strmh->stream_if->bInterfaceNumber == interface_idx)
604 static uvc_streaming_interface_t *_uvc_get_stream_if(uvc_device_handle_t *devh, int interface_idx) {
605 uvc_streaming_interface_t *stream_if;
607 DL_FOREACH(devh->info->stream_ifs, stream_if) {
608 if (stream_if->bInterfaceNumber == interface_idx)
615 /** Open a new video stream.
618 * @param devh UVC device
619 * @param ctrl Control block, processed using {uvc_probe_stream_ctrl} or
620 * {uvc_get_stream_ctrl_format_size}
622 uvc_error_t uvc_stream_open_ctrl(uvc_device_handle_t *devh, uvc_stream_handle_t **strmhp, uvc_stream_ctrl_t *ctrl) {
623 /* Chosen frame and format descriptors */
624 uvc_stream_handle_t *strmh = NULL;
625 uvc_streaming_interface_t *stream_if;
630 if (_uvc_get_stream_by_interface(devh, ctrl->bInterfaceNumber) != NULL) {
631 ret = UVC_ERROR_BUSY; /* Stream is already opened */
635 stream_if = _uvc_get_stream_if(devh, ctrl->bInterfaceNumber);
637 ret = UVC_ERROR_INVALID_PARAM;
641 strmh = calloc(1, sizeof(*strmh));
643 ret = UVC_ERROR_NO_MEM;
647 strmh->stream_if = stream_if;
648 strmh->frame.library_owns_data = 1;
650 ret = uvc_claim_if(strmh->devh, strmh->stream_if->bInterfaceNumber);
651 if (ret != UVC_SUCCESS)
654 ret = uvc_stream_ctrl(strmh, ctrl);
655 if (ret != UVC_SUCCESS)
658 // Set up the streaming status and data space
660 strmh->outbuf = malloc(8 * 1024 * 1024); /** @todo take only what we need */
661 strmh->holdbuf = malloc(8 * 1024 * 1024);
663 pthread_mutex_init(&strmh->cb_mutex, NULL);
664 pthread_cond_init(&strmh->cb_cond, NULL);
666 DL_APPEND(devh->streams, strmh);
680 /** Begin streaming video from the stream into the callback function.
683 * @param strmh UVC stream
684 * @param cb User callback function. See {uvc_frame_callback_t} for restrictions.
685 * @param isochronous Whether to use isochronous transfers rather than bulk ones
687 uvc_error_t uvc_stream_start(
688 uvc_stream_handle_t *strmh,
689 uvc_frame_callback_t *cb,
693 /* USB interface we'll be using */
694 const struct libusb_interface *interface;
696 uvc_frame_desc_t *frame_desc;
697 uvc_format_desc_t *format_desc;
698 uvc_stream_ctrl_t *ctrl;
701 ctrl = &strmh->cur_ctrl;
705 if (strmh->running) {
706 UVC_EXIT(UVC_ERROR_BUSY);
707 return UVC_ERROR_BUSY;
716 frame_desc = uvc_find_frame_desc_stream(strmh, ctrl->bFormatIndex, ctrl->bFrameIndex);
718 ret = UVC_ERROR_INVALID_PARAM;
721 format_desc = frame_desc->parent;
723 strmh->frame_format = uvc_frame_format_for_guid(format_desc->guidFormat);
724 if (strmh->frame_format == UVC_FRAME_FORMAT_UNKNOWN) {
725 ret = UVC_ERROR_NOT_SUPPORTED;
729 // Get the interface that provides the chosen format and frame configuration
730 interface_id = strmh->stream_if->bInterfaceNumber;
731 interface = &strmh->devh->info->config->interface[interface_id];
734 /* For isochronous streaming, we choose an appropriate altsetting for the endpoint
735 * and set up several transfers */
736 const struct libusb_interface_descriptor *altsetting;
737 const struct libusb_endpoint_descriptor *endpoint;
738 /* The greatest number of bytes that the device might provide, per packet, in this
740 size_t config_bytes_per_packet;
741 /* Number of packets per transfer */
742 size_t packets_per_transfer;
743 /* Total amount of data per transfer */
744 size_t total_transfer_size;
745 /* Size of packet transferable from the chosen endpoint */
746 size_t endpoint_bytes_per_packet;
747 /* Index of the altsetting */
750 struct libusb_transfer *transfer;
753 /* If the interface doesn't support isochronous mode, give up */
754 if (interface->num_altsetting == 0) {
755 ret = UVC_ERROR_INVALID_DEVICE;
759 config_bytes_per_packet = strmh->cur_ctrl.dwMaxPayloadTransferSize;
761 /* Go through the altsettings and find one whose packets are at least
762 * as big as our format's maximum per-packet usage. Assume that the
763 * packet sizes are increasing. */
764 for (alt_idx = 0; alt_idx < interface->num_altsetting; alt_idx++) {
765 altsetting = interface->altsetting + alt_idx;
766 endpoint_bytes_per_packet = 0;
768 /* Find the endpoint with the number specified in the VS header */
769 for (ep_idx = 0; ep_idx < altsetting->bNumEndpoints; ep_idx++) {
770 endpoint = altsetting->endpoint + ep_idx;
772 if (endpoint->bEndpointAddress == format_desc->parent->bEndpointAddress) {
773 endpoint_bytes_per_packet = endpoint->wMaxPacketSize;
774 // wMaxPacketSize: [unused:2 (multiplier-1):3 size:11]
775 endpoint_bytes_per_packet = (endpoint_bytes_per_packet & 0x07ff) *
776 (((endpoint_bytes_per_packet >> 11) & 3) + 1);
781 if (endpoint_bytes_per_packet >= config_bytes_per_packet) {
782 /* Transfers will be at most one frame long: Divide the maximum frame size
783 * by the size of the endpoint and round up */
784 packets_per_transfer = (ctrl->dwMaxVideoFrameSize +
785 endpoint_bytes_per_packet - 1) / endpoint_bytes_per_packet;
787 /* But keep a reasonable limit: Otherwise we start dropping data */
788 if (packets_per_transfer > 32)
789 packets_per_transfer = 32;
791 total_transfer_size = packets_per_transfer * endpoint_bytes_per_packet;
796 /* If we searched through all the altsettings and found nothing usable */
797 if (alt_idx == interface->num_altsetting) {
798 ret = UVC_ERROR_INVALID_MODE;
802 /* Select the altsetting */
803 ret = libusb_set_interface_alt_setting(strmh->devh->usb_devh,
804 altsetting->bInterfaceNumber,
805 altsetting->bAlternateSetting);
806 if (ret != UVC_SUCCESS) {
807 UVC_DEBUG("libusb_set_interface_alt_setting failed");
811 /* Set up the transfers */
812 for (transfer_id = 0; transfer_id < ARRAYSIZE(strmh->transfers); ++transfer_id) {
813 transfer = libusb_alloc_transfer(packets_per_transfer);
814 strmh->transfers[transfer_id] = transfer;
815 strmh->transfer_bufs[transfer_id] = malloc(total_transfer_size);
817 libusb_fill_iso_transfer(
818 transfer, strmh->devh->usb_devh, format_desc->parent->bEndpointAddress,
819 strmh->transfer_bufs[transfer_id],
820 total_transfer_size, packets_per_transfer, _uvc_iso_callback, (void*) strmh, 5000);
822 libusb_set_iso_packet_lengths(transfer, endpoint_bytes_per_packet);
825 /** @todo prepare for bulk transfer */
829 strmh->user_ptr = user_ptr;
831 /* If the user wants it, set up a thread that calls the user's function
832 * with the contents of each frame.
835 pthread_create(&strmh->cb_thread, NULL, _uvc_user_caller, (void*) strmh);
841 for (transfer_id = 0; transfer_id < ARRAYSIZE(strmh->transfers); transfer_id++) {
842 ret = libusb_submit_transfer(strmh->transfers[transfer_id]);
843 if (ret != UVC_SUCCESS) {
844 UVC_DEBUG("libusb_submit_transfer failed");
849 /** @todo submit bulk transfer */
852 if (ret != UVC_SUCCESS) {
853 /** @todo clean up transfers and memory */
865 /** Begin streaming video from the stream into the callback function.
868 * @param strmh UVC stream
869 * @param cb User callback function. See {uvc_frame_callback_t} for restrictions.
870 * @param isochronous Whether to use isochronous transfers rather than bulk ones
872 uvc_error_t uvc_stream_start_iso(
873 uvc_stream_handle_t *strmh,
874 uvc_frame_callback_t *cb,
877 return uvc_stream_start(strmh, cb, user_ptr, 1);
881 * @brief User callback runner thread
882 * @note There should be at most one of these per currently streaming device
883 * @param arg Device handle
885 void *_uvc_user_caller(void *arg) {
886 uvc_stream_handle_t *strmh = (uvc_stream_handle_t *) arg;
888 uint32_t last_seq = 0;
891 pthread_mutex_lock(&strmh->cb_mutex);
893 while (strmh->running && last_seq == strmh->hold_seq) {
894 pthread_cond_wait(&strmh->cb_cond, &strmh->cb_mutex);
897 if (!strmh->running) {
898 pthread_mutex_unlock(&strmh->cb_mutex);
902 last_seq = strmh->hold_seq;
903 _uvc_populate_frame(strmh);
905 pthread_mutex_unlock(&strmh->cb_mutex);
907 strmh->user_cb(&strmh->frame, strmh->user_ptr);
910 return NULL; // return value ignored
914 * @brief Populate the fields of a frame to be handed to user code
915 * must be called with stream cb lock held!
917 void _uvc_populate_frame(uvc_stream_handle_t *strmh) {
918 size_t alloc_size = strmh->cur_ctrl.dwMaxVideoFrameSize;
919 uvc_frame_t *frame = &strmh->frame;
920 uvc_frame_desc_t *frame_desc;
922 /** @todo this stuff that hits the main config cache should really happen
923 * in start() so that only one thread hits these data. all of this stuff
924 * is going to be reopen_on_change anyway
927 frame_desc = uvc_find_frame_desc(strmh->devh, strmh->cur_ctrl.bFormatIndex,
928 strmh->cur_ctrl.bFrameIndex);
930 frame->frame_format = strmh->frame_format;
932 frame->width = frame_desc->wWidth;
933 frame->height = frame_desc->wHeight;
935 switch (frame->frame_format) {
936 case UVC_FRAME_FORMAT_YUYV:
937 frame->step = frame->width * 2;
939 case UVC_FRAME_FORMAT_MJPEG:
947 /* copy the image data from the hold buffer to the frame (unnecessary extra buf?) */
948 if (frame->data_bytes < strmh->hold_bytes) {
949 frame->data = realloc(frame->data, strmh->hold_bytes);
950 frame->data_bytes = strmh->hold_bytes;
952 memcpy(frame->data, strmh->holdbuf, frame->data_bytes);
954 /** @todo set the frame time */
960 * @param devh UVC device
961 * @param[out] frame Location to store pointer to captured frame (NULL on error)
962 * @param timeout_us >0: Wait at most N microseconds; 0: Wait indefinitely; -1: return immediately
964 uvc_error_t uvc_stream_get_frame(uvc_stream_handle_t *strmh,
966 int32_t timeout_us) {
973 return UVC_ERROR_INVALID_PARAM;
976 return UVC_ERROR_CALLBACK_EXISTS;
978 pthread_mutex_lock(&strmh->cb_mutex);
980 if (strmh->last_polled_seq < strmh->hold_seq) {
981 _uvc_populate_frame(strmh);
982 *frame = &strmh->frame;
983 strmh->last_polled_seq = strmh->hold_seq;
984 } else if (timeout_us != -1) {
985 if (timeout_us == 0) {
986 pthread_cond_wait(&strmh->cb_cond, &strmh->cb_mutex);
988 add_secs = timeout_us / 1000000;
989 add_nsecs = (timeout_us % 1000000) * 1000;
993 #if _POSIX_TIMERS > 0
994 clock_gettime(CLOCK_REALTIME, &ts);
996 gettimeofday(&tv, NULL);
997 ts.tv_sec = tv.tv_sec;
998 ts.tv_nsec = tv.tv_usec * 1000;
1001 ts.tv_sec += add_secs;
1002 ts.tv_nsec += add_nsecs;
1004 pthread_cond_timedwait(&strmh->cb_cond, &strmh->cb_mutex, &ts);
1007 if (strmh->last_polled_seq < strmh->hold_seq) {
1008 _uvc_populate_frame(strmh);
1009 *frame = &strmh->frame;
1010 strmh->last_polled_seq = strmh->hold_seq;
1018 pthread_mutex_unlock(&strmh->cb_mutex);
1023 /** @brief Stop streaming video
1024 * @ingroup streaming
1026 * Closes all streams, ends threads and cancels pollers
1028 * @param devh UVC device
1030 void uvc_stop_streaming(uvc_device_handle_t *devh) {
1031 uvc_stream_handle_t *strmh, *strmh_tmp;
1033 DL_FOREACH_SAFE(devh->streams, strmh, strmh_tmp) {
1034 uvc_stream_close(strmh);
1038 /** @brief Stop stream.
1039 * @ingroup streaming
1041 * Stops stream, ends threads and cancels pollers
1043 * @param devh UVC device
1045 uvc_error_t uvc_stream_stop(uvc_stream_handle_t *strmh) {
1048 if (!strmh->running)
1049 return UVC_ERROR_INVALID_PARAM;
1053 pthread_mutex_lock(&strmh->cb_mutex);
1055 for(i=0; i<ARRAYSIZE(strmh->transfers); i++) {
1056 if(strmh->transfers[i] != NULL) {
1057 int res = libusb_cancel_transfer(strmh->transfers[i]);
1059 free(strmh->transfers[i]->buffer);
1060 libusb_free_transfer(strmh->transfers[i]);
1061 strmh->transfers[i] = NULL;
1066 /* Wait for transfers to complete/cancel */
1068 for(i=0; i<ARRAYSIZE(strmh->transfers); i++) {
1069 if(strmh->transfers[i] != NULL)
1072 if(i == ARRAYSIZE(strmh->transfers))
1074 pthread_cond_wait(&strmh->cb_cond, &strmh->cb_mutex);
1076 // Kick the user thread awake
1077 pthread_cond_broadcast(&strmh->cb_cond);
1078 pthread_mutex_unlock(&strmh->cb_mutex);
1080 /** @todo stop the actual stream, camera side? */
1082 if (strmh->user_cb) {
1083 /* wait for the thread to stop (triggered by
1084 * LIBUSB_TRANSFER_CANCELLED transfer) */
1085 pthread_join(strmh->cb_thread, NULL);
1091 /** @brief Close stream.
1092 * @ingroup streaming
1094 * Closes stream, frees handle and all streaming resources.
1096 * @param strmh UVC stream handle
1098 void uvc_stream_close(uvc_stream_handle_t *strmh) {
1100 uvc_stream_stop(strmh);
1102 uvc_release_if(strmh->devh, strmh->stream_if->bInterfaceNumber);
1104 if (strmh->frame.data)
1105 free(strmh->frame.data);
1107 free(strmh->outbuf);
1108 free(strmh->holdbuf);
1110 pthread_cond_destroy(&strmh->cb_cond);
1111 pthread_mutex_destroy(&strmh->cb_mutex);
1113 DL_DELETE(strmh->devh->streams, strmh);