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
36 * @brief Tools for creating, managing and consuming video streams
39 #include "libuvc/libuvc.h"
40 #include "libuvc/libuvc_internal.h"
45 #define DELTA_EPOCH_IN_MICROSECS 116444736000000000Ui64
47 // gettimeofday - get time of day for Windows;
48 // A gettimeofday implementation for Microsoft Windows;
49 // Public domain code, author "ponnada";
50 int gettimeofday(struct timeval *tv, struct timezone *tz)
53 unsigned __int64 tmpres = 0;
54 static int tzflag = 0;
57 GetSystemTimeAsFileTime(&ft);
58 tmpres |= ft.dwHighDateTime;
60 tmpres |= ft.dwLowDateTime;
62 tmpres -= DELTA_EPOCH_IN_MICROSECS;
63 tv->tv_sec = (long)(tmpres / 1000000UL);
64 tv->tv_usec = (long)(tmpres % 1000000UL);
69 uvc_frame_desc_t *uvc_find_frame_desc_stream(uvc_stream_handle_t *strmh,
70 uint16_t format_id, uint16_t frame_id);
71 uvc_frame_desc_t *uvc_find_frame_desc(uvc_device_handle_t *devh,
72 uint16_t format_id, uint16_t frame_id);
73 void *_uvc_user_caller(void *arg);
74 void _uvc_populate_frame(uvc_stream_handle_t *strmh);
76 struct format_table_entry {
77 enum uvc_frame_format format;
81 enum uvc_frame_format *children;
84 struct format_table_entry *_get_format_entry(enum uvc_frame_format format) {
85 #define ABS_FMT(_fmt, _num, ...) \
87 static enum uvc_frame_format _fmt##_children[] = __VA_ARGS__; \
88 static struct format_table_entry _fmt##_entry = { \
89 _fmt, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, _num, _fmt##_children }; \
90 return &_fmt##_entry; }
92 #define FMT(_fmt, ...) \
94 static struct format_table_entry _fmt##_entry = { \
95 _fmt, 0, __VA_ARGS__, 0, NULL }; \
96 return &_fmt##_entry; }
99 /* Define new formats here */
100 ABS_FMT(UVC_FRAME_FORMAT_ANY, 2,
101 {UVC_FRAME_FORMAT_UNCOMPRESSED, UVC_FRAME_FORMAT_COMPRESSED})
103 ABS_FMT(UVC_FRAME_FORMAT_UNCOMPRESSED, 4,
104 {UVC_FRAME_FORMAT_YUYV, UVC_FRAME_FORMAT_UYVY, UVC_FRAME_FORMAT_GRAY8,
105 UVC_FRAME_FORMAT_GRAY16})
106 FMT(UVC_FRAME_FORMAT_YUYV,
107 {'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71})
108 FMT(UVC_FRAME_FORMAT_UYVY,
109 {'U', 'Y', 'V', 'Y', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71})
110 FMT(UVC_FRAME_FORMAT_GRAY8,
111 {'Y', '8', '0', '0', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71})
112 FMT(UVC_FRAME_FORMAT_GRAY16,
113 {'Y', '1', '6', ' ', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71})
114 FMT(UVC_FRAME_FORMAT_BY8,
115 {'B', 'Y', '8', ' ', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71})
116 FMT(UVC_FRAME_FORMAT_BA81,
117 {'B', 'A', '8', '1', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71})
118 FMT(UVC_FRAME_FORMAT_SGRBG8,
119 {'G', 'R', 'B', 'G', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71})
120 FMT(UVC_FRAME_FORMAT_SGBRG8,
121 {'G', 'B', 'R', 'G', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71})
122 FMT(UVC_FRAME_FORMAT_SRGGB8,
123 {'R', 'G', 'G', 'B', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71})
124 FMT(UVC_FRAME_FORMAT_SBGGR8,
125 {'B', 'G', 'G', 'R', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71})
126 ABS_FMT(UVC_FRAME_FORMAT_COMPRESSED, 1,
127 {UVC_FRAME_FORMAT_MJPEG})
128 FMT(UVC_FRAME_FORMAT_MJPEG,
129 {'M', 'J', 'P', 'G'})
139 static uint8_t _uvc_frame_format_matches_guid(enum uvc_frame_format fmt, uint8_t guid[16]) {
140 struct format_table_entry *format;
143 format = _get_format_entry(fmt);
147 if (!format->abstract_fmt && !memcmp(guid, format->guid, 16))
150 for (child_idx = 0; child_idx < format->children_count; child_idx++) {
151 if (_uvc_frame_format_matches_guid(format->children[child_idx], guid))
158 static enum uvc_frame_format uvc_frame_format_for_guid(uint8_t guid[16]) {
159 struct format_table_entry *format;
160 enum uvc_frame_format fmt;
162 for (fmt = 0; fmt < UVC_FRAME_FORMAT_COUNT; ++fmt) {
163 format = _get_format_entry(fmt);
164 if (!format || format->abstract_fmt)
166 if (!memcmp(format->guid, guid, 16))
167 return format->format;
170 return UVC_FRAME_FORMAT_UNKNOWN;
174 * Run a streaming control query
175 * @param[in] devh UVC device
176 * @param[in,out] ctrl Control block
177 * @param[in] probe Whether this is a probe query or a commit query
178 * @param[in] req Query type
180 uvc_error_t uvc_query_stream_ctrl(
181 uvc_device_handle_t *devh,
182 uvc_stream_ctrl_t *ctrl,
184 enum uvc_req_code req) {
189 memset(buf, 0, sizeof(buf));
191 if (devh->info->ctrl_if.bcdUVC >= 0x0110)
196 /* prepare for a SET transfer */
197 if (req == UVC_SET_CUR) {
198 SHORT_TO_SW(ctrl->bmHint, buf);
199 buf[2] = ctrl->bFormatIndex;
200 buf[3] = ctrl->bFrameIndex;
201 INT_TO_DW(ctrl->dwFrameInterval, buf + 4);
202 SHORT_TO_SW(ctrl->wKeyFrameRate, buf + 8);
203 SHORT_TO_SW(ctrl->wPFrameRate, buf + 10);
204 SHORT_TO_SW(ctrl->wCompQuality, buf + 12);
205 SHORT_TO_SW(ctrl->wCompWindowSize, buf + 14);
206 SHORT_TO_SW(ctrl->wDelay, buf + 16);
207 INT_TO_DW(ctrl->dwMaxVideoFrameSize, buf + 18);
208 INT_TO_DW(ctrl->dwMaxPayloadTransferSize, buf + 22);
211 INT_TO_DW ( ctrl->dwClockFrequency, buf + 26 );
212 buf[30] = ctrl->bmFramingInfo;
213 buf[31] = ctrl->bPreferredVersion;
214 buf[32] = ctrl->bMinVersion;
215 buf[33] = ctrl->bMaxVersion;
216 /** @todo support UVC 1.1 */
220 /* do the transfer */
221 err = libusb_control_transfer(
223 req == UVC_SET_CUR ? 0x21 : 0xA1,
225 probe ? (UVC_VS_PROBE_CONTROL << 8) : (UVC_VS_COMMIT_CONTROL << 8),
226 ctrl->bInterfaceNumber,
234 /* now decode following a GET transfer */
235 if (req != UVC_SET_CUR) {
236 ctrl->bmHint = SW_TO_SHORT(buf);
237 ctrl->bFormatIndex = buf[2];
238 ctrl->bFrameIndex = buf[3];
239 ctrl->dwFrameInterval = DW_TO_INT(buf + 4);
240 ctrl->wKeyFrameRate = SW_TO_SHORT(buf + 8);
241 ctrl->wPFrameRate = SW_TO_SHORT(buf + 10);
242 ctrl->wCompQuality = SW_TO_SHORT(buf + 12);
243 ctrl->wCompWindowSize = SW_TO_SHORT(buf + 14);
244 ctrl->wDelay = SW_TO_SHORT(buf + 16);
245 ctrl->dwMaxVideoFrameSize = DW_TO_INT(buf + 18);
246 ctrl->dwMaxPayloadTransferSize = DW_TO_INT(buf + 22);
249 ctrl->dwClockFrequency = DW_TO_INT ( buf + 26 );
250 ctrl->bmFramingInfo = buf[30];
251 ctrl->bPreferredVersion = buf[31];
252 ctrl->bMinVersion = buf[32];
253 ctrl->bMaxVersion = buf[33];
254 /** @todo support UVC 1.1 */
257 ctrl->dwClockFrequency = devh->info->ctrl_if.dwClockFrequency;
259 /* fix up block for cameras that fail to set dwMax* */
260 if (ctrl->dwMaxVideoFrameSize == 0) {
261 uvc_frame_desc_t *frame = uvc_find_frame_desc(devh, ctrl->bFormatIndex, ctrl->bFrameIndex);
264 ctrl->dwMaxVideoFrameSize = frame->dwMaxVideoFrameBufferSize;
272 /** @brief Reconfigure stream with a new stream format.
275 * This may be executed whether or not the stream is running.
277 * @param[in] strmh Stream handle
278 * @param[in] ctrl Control block, processed using {uvc_probe_stream_ctrl} or
279 * {uvc_get_stream_ctrl_format_size}
281 uvc_error_t uvc_stream_ctrl(uvc_stream_handle_t *strmh, uvc_stream_ctrl_t *ctrl) {
284 if (strmh->stream_if->bInterfaceNumber != ctrl->bInterfaceNumber)
285 return UVC_ERROR_INVALID_PARAM;
287 /* @todo Allow the stream to be modified without restarting the stream */
289 return UVC_ERROR_BUSY;
291 ret = uvc_query_stream_ctrl(strmh->devh, ctrl, 0, UVC_SET_CUR);
292 if (ret != UVC_SUCCESS)
295 strmh->cur_ctrl = *ctrl;
300 * @brief Find the descriptor for a specific frame configuration
301 * @param stream_if Stream interface
302 * @param format_id Index of format class descriptor
303 * @param frame_id Index of frame descriptor
305 static uvc_frame_desc_t *_uvc_find_frame_desc_stream_if(uvc_streaming_interface_t *stream_if,
306 uint16_t format_id, uint16_t frame_id) {
308 uvc_format_desc_t *format = NULL;
309 uvc_frame_desc_t *frame = NULL;
311 DL_FOREACH(stream_if->format_descs, format) {
312 if (format->bFormatIndex == format_id) {
313 DL_FOREACH(format->frame_descs, frame) {
314 if (frame->bFrameIndex == frame_id)
323 uvc_frame_desc_t *uvc_find_frame_desc_stream(uvc_stream_handle_t *strmh,
324 uint16_t format_id, uint16_t frame_id) {
325 return _uvc_find_frame_desc_stream_if(strmh->stream_if, format_id, frame_id);
329 * @brief Find the descriptor for a specific frame configuration
330 * @param devh UVC device
331 * @param format_id Index of format class descriptor
332 * @param frame_id Index of frame descriptor
334 uvc_frame_desc_t *uvc_find_frame_desc(uvc_device_handle_t *devh,
335 uint16_t format_id, uint16_t frame_id) {
337 uvc_streaming_interface_t *stream_if;
338 uvc_frame_desc_t *frame;
340 DL_FOREACH(devh->info->stream_ifs, stream_if) {
341 frame = _uvc_find_frame_desc_stream_if(stream_if, format_id, frame_id);
349 /** Get a negotiated streaming control block for some common parameters.
352 * @param[in] devh Device handle
353 * @param[in,out] ctrl Control block
354 * @param[in] format_class Type of streaming format
355 * @param[in] width Desired frame width
356 * @param[in] height Desired frame height
357 * @param[in] fps Frame rate, frames per second
359 uvc_error_t uvc_get_stream_ctrl_format_size(
360 uvc_device_handle_t *devh,
361 uvc_stream_ctrl_t *ctrl,
362 enum uvc_frame_format cf,
363 int width, int height,
365 uvc_streaming_interface_t *stream_if;
367 /* find a matching frame descriptor and interval */
368 DL_FOREACH(devh->info->stream_ifs, stream_if) {
369 uvc_format_desc_t *format;
371 DL_FOREACH(stream_if->format_descs, format) {
372 uvc_frame_desc_t *frame;
374 if (!_uvc_frame_format_matches_guid(cf, format->guidFormat))
377 DL_FOREACH(format->frame_descs, frame) {
378 if (frame->wWidth != width || frame->wHeight != height)
383 ctrl->bInterfaceNumber = stream_if->bInterfaceNumber;
384 UVC_DEBUG("claiming streaming interface %d", stream_if->bInterfaceNumber );
385 uvc_claim_if(devh, ctrl->bInterfaceNumber);
386 /* get the max values */
387 uvc_query_stream_ctrl( devh, ctrl, 1, UVC_GET_MAX);
389 if (frame->intervals) {
390 for (interval = frame->intervals; *interval; ++interval) {
391 // allow a fps rate of zero to mean "accept first rate available"
392 if (10000000 / *interval == (unsigned int) fps || fps == 0) {
394 ctrl->bmHint = (1 << 0); /* don't negotiate interval */
395 ctrl->bFormatIndex = format->bFormatIndex;
396 ctrl->bFrameIndex = frame->bFrameIndex;
397 ctrl->dwFrameInterval = *interval;
403 uint32_t interval_100ns = 10000000 / fps;
404 uint32_t interval_offset = interval_100ns - frame->dwMinFrameInterval;
406 if (interval_100ns >= frame->dwMinFrameInterval
407 && interval_100ns <= frame->dwMaxFrameInterval
409 && (interval_offset % frame->dwFrameIntervalStep))) {
411 ctrl->bmHint = (1 << 0);
412 ctrl->bFormatIndex = format->bFormatIndex;
413 ctrl->bFrameIndex = frame->bFrameIndex;
414 ctrl->dwFrameInterval = interval_100ns;
423 return UVC_ERROR_INVALID_MODE;
426 return uvc_probe_stream_ctrl(devh, ctrl);
430 * Negotiate streaming parameters with the device
432 * @param[in] devh UVC device
433 * @param[in,out] ctrl Control block
435 uvc_error_t uvc_probe_stream_ctrl(
436 uvc_device_handle_t *devh,
437 uvc_stream_ctrl_t *ctrl) {
439 uvc_query_stream_ctrl(
440 devh, ctrl, 1, UVC_SET_CUR
443 uvc_query_stream_ctrl(
444 devh, ctrl, 1, UVC_GET_CUR
447 /** @todo make sure that worked */
452 * @brief Swap the working buffer with the presented buffer and notify consumers
454 void _uvc_swap_buffers(uvc_stream_handle_t *strmh) {
457 pthread_mutex_lock(&strmh->cb_mutex);
459 /* swap the buffers */
460 tmp_buf = strmh->holdbuf;
461 strmh->hold_bytes = strmh->got_bytes;
462 strmh->holdbuf = strmh->outbuf;
463 strmh->outbuf = tmp_buf;
464 strmh->hold_last_scr = strmh->last_scr;
465 strmh->hold_pts = strmh->pts;
466 strmh->hold_seq = strmh->seq;
468 pthread_cond_broadcast(&strmh->cb_cond);
469 pthread_mutex_unlock(&strmh->cb_mutex);
472 strmh->got_bytes = 0;
478 * @brief Process a payload transfer
480 * Processes stream, places frames into buffer, signals listeners
481 * (such as user callback thread and any polling thread) on new frame
483 * @param payload Contents of the payload transfer, either a packet (isochronous) or a full
484 * transfer (bulk mode)
485 * @param payload_len Length of the payload transfer
487 void _uvc_process_payload(uvc_stream_handle_t *strmh, uint8_t *payload, size_t payload_len) {
492 /* magic numbers for identifying header packets from some iSight cameras */
493 static uint8_t isight_tag[] = {
494 0x11, 0x22, 0x33, 0x44,
495 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xfa, 0xce
498 /* ignore empty payload transfers */
499 if (payload_len == 0)
502 /* Certain iSight cameras have strange behavior: They send header
503 * information in a packet with no image data, and then the following
504 * packets have only image data, with no more headers until the next frame.
506 * The iSight header: len(1), flags(1 or 2), 0x11223344(4),
507 * 0xdeadbeefdeadface(8), ??(16)
510 if (strmh->devh->is_isight &&
511 (payload_len < 14 || memcmp(isight_tag, payload + 2, sizeof(isight_tag))) &&
512 (payload_len < 15 || memcmp(isight_tag, payload + 3, sizeof(isight_tag)))) {
513 /* The payload transfer doesn't have any iSight magic, so it's all image data */
515 data_len = payload_len;
517 header_len = payload[0];
519 if (header_len > payload_len) {
520 UVC_DEBUG("bogus packet: actual_len=%zd, header_len=%zd\n", payload_len, header_len);
524 if (strmh->devh->is_isight)
527 data_len = payload_len - header_len;
530 if (header_len < 2) {
533 /** @todo we should be checking the end-of-header bit */
534 size_t variable_offset = 2;
536 header_info = payload[1];
538 if (header_info & 0x40) {
539 UVC_DEBUG("bad packet: error bit set");
543 if (strmh->fid != (header_info & 1) && strmh->got_bytes != 0) {
544 /* The frame ID bit was flipped, but we have image data sitting
545 around from prior transfers. This means the camera didn't send
546 an EOF for the last transfer of the previous frame. */
547 _uvc_swap_buffers(strmh);
550 strmh->fid = header_info & 1;
552 if (header_info & (1 << 2)) {
553 strmh->pts = DW_TO_INT(payload + variable_offset);
554 variable_offset += 4;
557 if (header_info & (1 << 3)) {
558 /** @todo read the SOF token counter */
559 strmh->last_scr = DW_TO_INT(payload + variable_offset);
560 variable_offset += 6;
565 memcpy(strmh->outbuf + strmh->got_bytes, payload + header_len, data_len);
566 strmh->got_bytes += data_len;
568 if (header_info & (1 << 1)) {
569 /* The EOF bit is set, so publish the complete frame */
570 _uvc_swap_buffers(strmh);
576 * @brief Stream transfer callback
578 * Processes stream, places frames into buffer, signals listeners
579 * (such as user callback thread and any polling thread) on new frame
581 * @param transfer Active transfer
583 void LIBUSB_CALL _uvc_stream_callback(struct libusb_transfer *transfer) {
584 uvc_stream_handle_t *strmh = transfer->user_data;
588 switch (transfer->status) {
589 case LIBUSB_TRANSFER_COMPLETED:
590 if (transfer->num_iso_packets == 0) {
591 /* This is a bulk mode transfer, so it just has one payload transfer */
592 _uvc_process_payload(strmh, transfer->buffer, transfer->actual_length);
594 /* This is an isochronous mode transfer, so each packet has a payload transfer */
597 for (packet_id = 0; packet_id < transfer->num_iso_packets; ++packet_id) {
599 struct libusb_iso_packet_descriptor *pkt;
601 pkt = transfer->iso_packet_desc + packet_id;
603 if (pkt->status != 0) {
604 UVC_DEBUG("bad packet (isochronous transfer); status: %d", pkt->status);
608 pktbuf = libusb_get_iso_packet_buffer_simple(transfer, packet_id);
610 _uvc_process_payload(strmh, pktbuf, pkt->actual_length);
615 case LIBUSB_TRANSFER_CANCELLED:
616 case LIBUSB_TRANSFER_ERROR:
617 case LIBUSB_TRANSFER_NO_DEVICE: {
619 UVC_DEBUG("not retrying transfer, status = %d", transfer->status);
620 pthread_mutex_lock(&strmh->cb_mutex);
622 /* Mark transfer as deleted. */
623 for(i=0; i < LIBUVC_NUM_TRANSFER_BUFS; i++) {
624 if(strmh->transfers[i] == transfer) {
625 UVC_DEBUG("Freeing transfer %d (%p)", i, transfer);
626 free(transfer->buffer);
627 libusb_free_transfer(transfer);
628 strmh->transfers[i] = NULL;
632 if(i == LIBUVC_NUM_TRANSFER_BUFS ) {
633 UVC_DEBUG("transfer %p not found; not freeing!", transfer);
638 pthread_cond_broadcast(&strmh->cb_cond);
639 pthread_mutex_unlock(&strmh->cb_mutex);
643 case LIBUSB_TRANSFER_TIMED_OUT:
644 case LIBUSB_TRANSFER_STALL:
645 case LIBUSB_TRANSFER_OVERFLOW:
646 UVC_DEBUG("retrying transfer, status = %d", transfer->status);
651 if ( strmh->running ) {
652 libusb_submit_transfer(transfer);
655 pthread_mutex_lock(&strmh->cb_mutex);
657 /* Mark transfer as deleted. */
658 for(i=0; i < LIBUVC_NUM_TRANSFER_BUFS; i++) {
659 if(strmh->transfers[i] == transfer) {
660 UVC_DEBUG("Freeing orphan transfer %d (%p)", i, transfer);
661 free(transfer->buffer);
662 libusb_free_transfer(transfer);
663 strmh->transfers[i] = NULL;
666 if(i == LIBUVC_NUM_TRANSFER_BUFS ) {
667 UVC_DEBUG("orphan transfer %p not found; not freeing!", transfer);
670 pthread_cond_broadcast(&strmh->cb_cond);
671 pthread_mutex_unlock(&strmh->cb_mutex);
676 /** Begin streaming video from the camera into the callback function.
679 * @param devh UVC device
680 * @param ctrl Control block, processed using {uvc_probe_stream_ctrl} or
681 * {uvc_get_stream_ctrl_format_size}
682 * @param cb User callback function. See {uvc_frame_callback_t} for restrictions.
683 * @param flags Stream setup flags, currently undefined. Set this to zero. The lower bit
684 * is reserved for backward compatibility.
686 uvc_error_t uvc_start_streaming(
687 uvc_device_handle_t *devh,
688 uvc_stream_ctrl_t *ctrl,
689 uvc_frame_callback_t *cb,
694 uvc_stream_handle_t *strmh;
696 ret = uvc_stream_open_ctrl(devh, &strmh, ctrl);
697 if (ret != UVC_SUCCESS)
700 ret = uvc_stream_start(strmh, cb, user_ptr, flags);
701 if (ret != UVC_SUCCESS) {
702 uvc_stream_close(strmh);
709 /** Begin streaming video from the camera into the callback function.
712 * @deprecated The stream type (bulk vs. isochronous) will be determined by the
713 * type of interface associated with the uvc_stream_ctrl_t parameter, regardless
714 * of whether the caller requests isochronous streaming. Please switch to
715 * uvc_start_streaming().
717 * @param devh UVC device
718 * @param ctrl Control block, processed using {uvc_probe_stream_ctrl} or
719 * {uvc_get_stream_ctrl_format_size}
720 * @param cb User callback function. See {uvc_frame_callback_t} for restrictions.
722 uvc_error_t uvc_start_iso_streaming(
723 uvc_device_handle_t *devh,
724 uvc_stream_ctrl_t *ctrl,
725 uvc_frame_callback_t *cb,
728 return uvc_start_streaming(devh, ctrl, cb, user_ptr, 0);
731 static uvc_stream_handle_t *_uvc_get_stream_by_interface(uvc_device_handle_t *devh, int interface_idx) {
732 uvc_stream_handle_t *strmh;
734 DL_FOREACH(devh->streams, strmh) {
735 if (strmh->stream_if->bInterfaceNumber == interface_idx)
742 static uvc_streaming_interface_t *_uvc_get_stream_if(uvc_device_handle_t *devh, int interface_idx) {
743 uvc_streaming_interface_t *stream_if;
745 DL_FOREACH(devh->info->stream_ifs, stream_if) {
746 if (stream_if->bInterfaceNumber == interface_idx)
753 /** Open a new video stream.
756 * @param devh UVC device
757 * @param ctrl Control block, processed using {uvc_probe_stream_ctrl} or
758 * {uvc_get_stream_ctrl_format_size}
760 uvc_error_t uvc_stream_open_ctrl(uvc_device_handle_t *devh, uvc_stream_handle_t **strmhp, uvc_stream_ctrl_t *ctrl) {
761 /* Chosen frame and format descriptors */
762 uvc_stream_handle_t *strmh = NULL;
763 uvc_streaming_interface_t *stream_if;
768 if (_uvc_get_stream_by_interface(devh, ctrl->bInterfaceNumber) != NULL) {
769 ret = UVC_ERROR_BUSY; /* Stream is already opened */
773 stream_if = _uvc_get_stream_if(devh, ctrl->bInterfaceNumber);
775 ret = UVC_ERROR_INVALID_PARAM;
779 strmh = calloc(1, sizeof(*strmh));
781 ret = UVC_ERROR_NO_MEM;
785 strmh->stream_if = stream_if;
786 strmh->frame.library_owns_data = 1;
788 ret = uvc_claim_if(strmh->devh, strmh->stream_if->bInterfaceNumber);
789 if (ret != UVC_SUCCESS)
792 ret = uvc_stream_ctrl(strmh, ctrl);
793 if (ret != UVC_SUCCESS)
796 // Set up the streaming status and data space
798 /** @todo take only what we need */
799 strmh->outbuf = malloc( LIBUVC_XFER_BUF_SIZE );
800 strmh->holdbuf = malloc( LIBUVC_XFER_BUF_SIZE );
802 pthread_mutex_init(&strmh->cb_mutex, NULL);
803 pthread_cond_init(&strmh->cb_cond, NULL);
805 DL_APPEND(devh->streams, strmh);
819 /** Begin streaming video from the stream into the callback function.
822 * @param strmh UVC stream
823 * @param cb User callback function. See {uvc_frame_callback_t} for restrictions.
824 * @param flags Stream setup flags, currently undefined. Set this to zero. The lower bit
825 * is reserved for backward compatibility.
827 uvc_error_t uvc_stream_start(
828 uvc_stream_handle_t *strmh,
829 uvc_frame_callback_t *cb,
833 /* USB interface we'll be using */
834 const struct libusb_interface *interface;
837 uvc_frame_desc_t *frame_desc;
838 uvc_format_desc_t *format_desc;
839 uvc_stream_ctrl_t *ctrl;
841 /* Total amount of data per transfer */
842 size_t total_transfer_size = 0;
843 struct libusb_transfer *transfer;
846 ctrl = &strmh->cur_ctrl;
850 if (strmh->running) {
851 UVC_EXIT(UVC_ERROR_BUSY);
852 return UVC_ERROR_BUSY;
861 frame_desc = uvc_find_frame_desc_stream(strmh, ctrl->bFormatIndex, ctrl->bFrameIndex);
863 ret = UVC_ERROR_INVALID_PARAM;
866 format_desc = frame_desc->parent;
868 strmh->frame_format = uvc_frame_format_for_guid(format_desc->guidFormat);
869 if (strmh->frame_format == UVC_FRAME_FORMAT_UNKNOWN) {
870 ret = UVC_ERROR_NOT_SUPPORTED;
874 // Get the interface that provides the chosen format and frame configuration
875 interface_id = strmh->stream_if->bInterfaceNumber;
876 interface = &strmh->devh->info->config->interface[interface_id];
878 /* A VS interface uses isochronous transfers iff it has multiple altsettings.
879 * (UVC 1.5: 2.4.3. VideoStreaming Interface) */
880 isochronous = interface->num_altsetting > 1;
883 /* For isochronous streaming, we choose an appropriate altsetting for the endpoint
884 * and set up several transfers */
885 const struct libusb_interface_descriptor *altsetting = 0;
886 const struct libusb_endpoint_descriptor *endpoint;
887 /* The greatest number of bytes that the device might provide, per packet, in this
889 size_t config_bytes_per_packet;
890 /* Number of packets per transfer */
891 size_t packets_per_transfer = 0;
892 /* Size of packet transferable from the chosen endpoint */
893 size_t endpoint_bytes_per_packet = 0;
894 /* Index of the altsetting */
897 config_bytes_per_packet = strmh->cur_ctrl.dwMaxPayloadTransferSize;
899 /* Go through the altsettings and find one whose packets are at least
900 * as big as our format's maximum per-packet usage. Assume that the
901 * packet sizes are increasing. */
902 for (alt_idx = 0; alt_idx < interface->num_altsetting; alt_idx++) {
903 altsetting = interface->altsetting + alt_idx;
904 endpoint_bytes_per_packet = 0;
906 /* Find the endpoint with the number specified in the VS header */
907 for (ep_idx = 0; ep_idx < altsetting->bNumEndpoints; ep_idx++) {
908 endpoint = altsetting->endpoint + ep_idx;
910 if (endpoint->bEndpointAddress == format_desc->parent->bEndpointAddress) {
911 endpoint_bytes_per_packet = endpoint->wMaxPacketSize;
912 // wMaxPacketSize: [unused:2 (multiplier-1):3 size:11]
913 endpoint_bytes_per_packet = (endpoint_bytes_per_packet & 0x07ff) *
914 (((endpoint_bytes_per_packet >> 11) & 3) + 1);
919 if (endpoint_bytes_per_packet >= config_bytes_per_packet) {
920 /* Transfers will be at most one frame long: Divide the maximum frame size
921 * by the size of the endpoint and round up */
922 packets_per_transfer = (ctrl->dwMaxVideoFrameSize +
923 endpoint_bytes_per_packet - 1) / endpoint_bytes_per_packet;
925 /* But keep a reasonable limit: Otherwise we start dropping data */
926 if (packets_per_transfer > 32)
927 packets_per_transfer = 32;
929 total_transfer_size = packets_per_transfer * endpoint_bytes_per_packet;
934 /* If we searched through all the altsettings and found nothing usable */
935 if (alt_idx == interface->num_altsetting) {
936 ret = UVC_ERROR_INVALID_MODE;
940 /* Select the altsetting */
941 ret = libusb_set_interface_alt_setting(strmh->devh->usb_devh,
942 altsetting->bInterfaceNumber,
943 altsetting->bAlternateSetting);
944 if (ret != UVC_SUCCESS) {
945 UVC_DEBUG("libusb_set_interface_alt_setting failed");
949 /* Set up the transfers */
950 for (transfer_id = 0; transfer_id < LIBUVC_NUM_TRANSFER_BUFS; ++transfer_id) {
951 transfer = libusb_alloc_transfer(packets_per_transfer);
952 strmh->transfers[transfer_id] = transfer;
953 strmh->transfer_bufs[transfer_id] = malloc(total_transfer_size);
955 libusb_fill_iso_transfer(
956 transfer, strmh->devh->usb_devh, format_desc->parent->bEndpointAddress,
957 strmh->transfer_bufs[transfer_id],
958 total_transfer_size, packets_per_transfer, _uvc_stream_callback, (void*) strmh, 5000);
960 libusb_set_iso_packet_lengths(transfer, endpoint_bytes_per_packet);
963 for (transfer_id = 0; transfer_id < LIBUVC_NUM_TRANSFER_BUFS;
965 transfer = libusb_alloc_transfer(0);
966 strmh->transfers[transfer_id] = transfer;
967 strmh->transfer_bufs[transfer_id] = malloc (
968 strmh->cur_ctrl.dwMaxPayloadTransferSize );
969 libusb_fill_bulk_transfer ( transfer, strmh->devh->usb_devh,
970 format_desc->parent->bEndpointAddress,
971 strmh->transfer_bufs[transfer_id],
972 strmh->cur_ctrl.dwMaxPayloadTransferSize, _uvc_stream_callback,
973 ( void* ) strmh, 5000 );
978 strmh->user_ptr = user_ptr;
980 /* If the user wants it, set up a thread that calls the user's function
981 * with the contents of each frame.
984 pthread_create(&strmh->cb_thread, NULL, _uvc_user_caller, (void*) strmh);
987 for (transfer_id = 0; transfer_id < LIBUVC_NUM_TRANSFER_BUFS;
989 ret = libusb_submit_transfer(strmh->transfers[transfer_id]);
990 if (ret != UVC_SUCCESS) {
991 UVC_DEBUG("libusb_submit_transfer failed: %d",ret);
996 if ( ret != UVC_SUCCESS && transfer_id > 0 ) {
997 for ( ; transfer_id < LIBUVC_NUM_TRANSFER_BUFS; transfer_id++) {
998 free ( strmh->transfers[transfer_id]->buffer );
999 libusb_free_transfer ( strmh->transfers[transfer_id]);
1000 strmh->transfers[transfer_id] = 0;
1013 /** Begin streaming video from the stream into the callback function.
1014 * @ingroup streaming
1016 * @deprecated The stream type (bulk vs. isochronous) will be determined by the
1017 * type of interface associated with the uvc_stream_ctrl_t parameter, regardless
1018 * of whether the caller requests isochronous streaming. Please switch to
1019 * uvc_stream_start().
1021 * @param strmh UVC stream
1022 * @param cb User callback function. See {uvc_frame_callback_t} for restrictions.
1024 uvc_error_t uvc_stream_start_iso(
1025 uvc_stream_handle_t *strmh,
1026 uvc_frame_callback_t *cb,
1029 return uvc_stream_start(strmh, cb, user_ptr, 0);
1033 * @brief User callback runner thread
1034 * @note There should be at most one of these per currently streaming device
1035 * @param arg Device handle
1037 void *_uvc_user_caller(void *arg) {
1038 uvc_stream_handle_t *strmh = (uvc_stream_handle_t *) arg;
1040 uint32_t last_seq = 0;
1043 pthread_mutex_lock(&strmh->cb_mutex);
1045 while (strmh->running && last_seq == strmh->hold_seq) {
1046 pthread_cond_wait(&strmh->cb_cond, &strmh->cb_mutex);
1049 if (!strmh->running) {
1050 pthread_mutex_unlock(&strmh->cb_mutex);
1054 last_seq = strmh->hold_seq;
1055 _uvc_populate_frame(strmh);
1057 pthread_mutex_unlock(&strmh->cb_mutex);
1059 strmh->user_cb(&strmh->frame, strmh->user_ptr);
1062 return NULL; // return value ignored
1066 * @brief Populate the fields of a frame to be handed to user code
1067 * must be called with stream cb lock held!
1069 void _uvc_populate_frame(uvc_stream_handle_t *strmh) {
1070 uvc_frame_t *frame = &strmh->frame;
1071 uvc_frame_desc_t *frame_desc;
1073 /** @todo this stuff that hits the main config cache should really happen
1074 * in start() so that only one thread hits these data. all of this stuff
1075 * is going to be reopen_on_change anyway
1078 frame_desc = uvc_find_frame_desc(strmh->devh, strmh->cur_ctrl.bFormatIndex,
1079 strmh->cur_ctrl.bFrameIndex);
1081 frame->frame_format = strmh->frame_format;
1083 frame->width = frame_desc->wWidth;
1084 frame->height = frame_desc->wHeight;
1086 switch (frame->frame_format) {
1087 case UVC_FRAME_FORMAT_YUYV:
1088 frame->step = frame->width * 2;
1090 case UVC_FRAME_FORMAT_MJPEG:
1098 frame->sequence = strmh->hold_seq;
1099 /** @todo set the frame time */
1100 // frame->capture_time
1102 /* copy the image data from the hold buffer to the frame (unnecessary extra buf?) */
1103 if (frame->data_bytes < strmh->hold_bytes) {
1104 frame->data = realloc(frame->data, strmh->hold_bytes);
1106 frame->data_bytes = strmh->hold_bytes;
1107 memcpy(frame->data, strmh->holdbuf, frame->data_bytes);
1113 /** Poll for a frame
1114 * @ingroup streaming
1116 * @param devh UVC device
1117 * @param[out] frame Location to store pointer to captured frame (NULL on error)
1118 * @param timeout_us >0: Wait at most N microseconds; 0: Wait indefinitely; -1: return immediately
1120 uvc_error_t uvc_stream_get_frame(uvc_stream_handle_t *strmh,
1121 uvc_frame_t **frame,
1122 int32_t timeout_us) {
1128 if (!strmh->running)
1129 return UVC_ERROR_INVALID_PARAM;
1132 return UVC_ERROR_CALLBACK_EXISTS;
1134 pthread_mutex_lock(&strmh->cb_mutex);
1136 if (strmh->last_polled_seq < strmh->hold_seq) {
1137 _uvc_populate_frame(strmh);
1138 *frame = &strmh->frame;
1139 strmh->last_polled_seq = strmh->hold_seq;
1140 } else if (timeout_us != -1) {
1141 if (timeout_us == 0) {
1142 pthread_cond_wait(&strmh->cb_cond, &strmh->cb_mutex);
1144 add_secs = timeout_us / 1000000;
1145 add_nsecs = (timeout_us % 1000000) * 1000;
1149 #if _POSIX_TIMERS > 0
1150 clock_gettime(CLOCK_REALTIME, &ts);
1152 gettimeofday(&tv, NULL);
1153 ts.tv_sec = tv.tv_sec;
1154 ts.tv_nsec = tv.tv_usec * 1000;
1157 ts.tv_sec += add_secs;
1158 ts.tv_nsec += add_nsecs;
1160 /* pthread_cond_timedwait FAILS with EINVAL if ts.tv_nsec > 1000000000 (1 billion)
1161 * Since we are just adding values to the timespec, we have to increment the seconds if nanoseconds is greater than 1 billion,
1162 * and then re-adjust the nanoseconds in the correct range.
1164 ts.tv_sec += ts.tv_nsec / 1000000000;
1165 ts.tv_nsec = ts.tv_nsec % 1000000000;
1167 int err = pthread_cond_timedwait(&strmh->cb_cond, &strmh->cb_mutex, &ts);
1169 //TODO: How should we handle EINVAL?
1173 return UVC_ERROR_OTHER;
1176 return UVC_ERROR_TIMEOUT;
1180 if (strmh->last_polled_seq < strmh->hold_seq) {
1181 _uvc_populate_frame(strmh);
1182 *frame = &strmh->frame;
1183 strmh->last_polled_seq = strmh->hold_seq;
1191 pthread_mutex_unlock(&strmh->cb_mutex);
1196 /** @brief Stop streaming video
1197 * @ingroup streaming
1199 * Closes all streams, ends threads and cancels pollers
1201 * @param devh UVC device
1203 void uvc_stop_streaming(uvc_device_handle_t *devh) {
1204 uvc_stream_handle_t *strmh, *strmh_tmp;
1206 DL_FOREACH_SAFE(devh->streams, strmh, strmh_tmp) {
1207 uvc_stream_close(strmh);
1211 /** @brief Stop stream.
1212 * @ingroup streaming
1214 * Stops stream, ends threads and cancels pollers
1216 * @param devh UVC device
1218 uvc_error_t uvc_stream_stop(uvc_stream_handle_t *strmh) {
1221 if (!strmh->running)
1222 return UVC_ERROR_INVALID_PARAM;
1226 pthread_mutex_lock(&strmh->cb_mutex);
1228 for(i=0; i < LIBUVC_NUM_TRANSFER_BUFS; i++) {
1229 if(strmh->transfers[i] != NULL) {
1230 int res = libusb_cancel_transfer(strmh->transfers[i]);
1231 if(res < 0 && res != LIBUSB_ERROR_NOT_FOUND ) {
1232 free(strmh->transfers[i]->buffer);
1233 libusb_free_transfer(strmh->transfers[i]);
1234 strmh->transfers[i] = NULL;
1239 /* Wait for transfers to complete/cancel */
1241 for(i=0; i < LIBUVC_NUM_TRANSFER_BUFS; i++) {
1242 if(strmh->transfers[i] != NULL)
1245 if(i == LIBUVC_NUM_TRANSFER_BUFS )
1247 pthread_cond_wait(&strmh->cb_cond, &strmh->cb_mutex);
1249 // Kick the user thread awake
1250 pthread_cond_broadcast(&strmh->cb_cond);
1251 pthread_mutex_unlock(&strmh->cb_mutex);
1253 /** @todo stop the actual stream, camera side? */
1255 if (strmh->user_cb) {
1256 /* wait for the thread to stop (triggered by
1257 * LIBUSB_TRANSFER_CANCELLED transfer) */
1258 pthread_join(strmh->cb_thread, NULL);
1264 /** @brief Close stream.
1265 * @ingroup streaming
1267 * Closes stream, frees handle and all streaming resources.
1269 * @param strmh UVC stream handle
1271 void uvc_stream_close(uvc_stream_handle_t *strmh) {
1273 uvc_stream_stop(strmh);
1275 uvc_release_if(strmh->devh, strmh->stream_if->bInterfaceNumber);
1277 if (strmh->frame.data)
1278 free(strmh->frame.data);
1280 free(strmh->outbuf);
1281 free(strmh->holdbuf);
1283 pthread_cond_destroy(&strmh->cb_cond);
1284 pthread_mutex_destroy(&strmh->cb_mutex);
1286 DL_DELETE(strmh->devh->streams, strmh);