1 /*********************************************************************
2 *********************************************************************/
3 /*********************************************************************
4 * modified some function to avoid crash, support Android
5 * Copyright (C) 2014-2016 saki@serenegiant All rights reserved.
6 *********************************************************************/
7 /*********************************************************************
8 * Software License Agreement (BSD License)
10 * Copyright (C) 2010-2012 Ken Tossell
11 * All rights reserved.
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
17 * * Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * * Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials provided
22 * with the distribution.
23 * * Neither the name of the author nor other contributors may be
24 * used to endorse or promote products derived from this software
25 * without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
30 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
31 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
32 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
33 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
34 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
35 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *********************************************************************/
41 * @defgroup streaming Streaming control functions
42 * @brief Tools for creating, managing and consuming video streams
47 #define LOG_TAG "libuvc/stream"
48 #if 1 // デバッグ情報を出さない時1
50 #define LOG_NDEBUG // LOGV/LOGD/MARKを出力しない時
52 #undef USE_LOGALL // 指定したLOGxだけを出力
57 #define GET_RAW_DESCRIPTOR
60 #include <assert.h> // XXX add assert for debugging
62 #include "libuvc/libuvc.h"
63 #include "libuvc/libuvc_internal.h"
65 uvc_frame_desc_t *uvc_find_frame_desc_stream(uvc_stream_handle_t *strmh,
66 uint16_t format_id, uint16_t frame_id);
67 uvc_frame_desc_t *uvc_find_frame_desc(uvc_device_handle_t *devh,
68 uint16_t format_id, uint16_t frame_id);
69 static void *_uvc_user_caller(void *arg);
70 static void _uvc_populate_frame(uvc_stream_handle_t *strmh);
72 struct format_table_entry {
73 enum uvc_frame_format format;
77 enum uvc_frame_format *children;
80 struct format_table_entry *_get_format_entry(enum uvc_frame_format format) {
81 #define ABS_FMT(_fmt, ...) \
83 static enum uvc_frame_format _fmt##_children[] = __VA_ARGS__; \
84 static struct format_table_entry _fmt##_entry = { \
85 _fmt, 0, {}, ARRAYSIZE(_fmt##_children), _fmt##_children }; \
86 return &_fmt##_entry; }
88 #define FMT(_fmt, ...) \
90 static struct format_table_entry _fmt##_entry = { \
91 _fmt, 0, __VA_ARGS__, 0, NULL }; \
92 return &_fmt##_entry; }
95 /* Define new formats here */
96 ABS_FMT(UVC_FRAME_FORMAT_ANY,
97 {UVC_FRAME_FORMAT_UNCOMPRESSED, UVC_FRAME_FORMAT_COMPRESSED})
99 ABS_FMT(UVC_FRAME_FORMAT_UNCOMPRESSED,
100 {UVC_FRAME_FORMAT_YUYV, UVC_FRAME_FORMAT_UYVY, UVC_FRAME_FORMAT_GRAY8})
101 FMT(UVC_FRAME_FORMAT_YUYV,
102 {'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71})
103 FMT(UVC_FRAME_FORMAT_UYVY,
104 {'U', 'Y', 'V', 'Y', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71})
105 FMT(UVC_FRAME_FORMAT_GRAY8,
106 {'Y', '8', '0', '0', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71})
107 FMT(UVC_FRAME_FORMAT_BY8,
108 {'B', 'Y', '8', ' ', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71})
110 ABS_FMT(UVC_FRAME_FORMAT_COMPRESSED,
111 {UVC_FRAME_FORMAT_MJPEG})
112 FMT(UVC_FRAME_FORMAT_MJPEG,
113 {'M', 'J', 'P', 'G'})
123 static uint8_t _uvc_frame_format_matches_guid(enum uvc_frame_format fmt,
125 struct format_table_entry *format;
128 format = _get_format_entry(fmt);
129 if (UNLIKELY(!format))
132 if (!format->abstract_fmt && !memcmp(guid, format->guid, 16))
135 for (child_idx = 0; child_idx < format->children_count; child_idx++) {
136 if (_uvc_frame_format_matches_guid(format->children[child_idx], guid))
143 static enum uvc_frame_format uvc_frame_format_for_guid(uint8_t guid[16]) {
144 struct format_table_entry *format;
145 enum uvc_frame_format fmt;
147 for (fmt = 0; fmt < UVC_FRAME_FORMAT_COUNT; ++fmt) {
148 format = _get_format_entry(fmt);
149 if (!format || format->abstract_fmt)
151 if (!memcmp(format->guid, guid, 16))
152 return format->format;
155 return UVC_FRAME_FORMAT_UNKNOWN;
159 * Run a streaming control query
160 * @param[in] devh UVC device
161 * @param[in,out] ctrl Control block
162 * @param[in] probe Whether this is a probe query or a commit query
163 * @param[in] req Query type
165 uvc_error_t uvc_query_stream_ctrl(uvc_device_handle_t *devh,
166 uvc_stream_ctrl_t *ctrl, uint8_t probe, enum uvc_req_code req) {
167 uint8_t buf[48]; // XXX support UVC 1.1 & 1.5
171 memset(buf, 0, sizeof(buf)); // bzero(buf, sizeof(buf)); // bzero is deprecated
173 const uint16_t bcdUVC = devh->info->ctrl_if.bcdUVC;
174 if (bcdUVC >= 0x0150)
176 else if (bcdUVC >= 0x0110)
180 // LOGI("bcdUVC:%x,req:0x%02x,probe:%d", bcdUVC, req, probe);
181 /* prepare for a SET transfer */
182 if (req == UVC_SET_CUR) {
183 SHORT_TO_SW(ctrl->bmHint, buf);
184 buf[2] = ctrl->bFormatIndex;
185 buf[3] = ctrl->bFrameIndex;
186 INT_TO_DW(ctrl->dwFrameInterval, buf + 4);
187 SHORT_TO_SW(ctrl->wKeyFrameRate, buf + 8);
188 SHORT_TO_SW(ctrl->wPFrameRate, buf + 10);
189 SHORT_TO_SW(ctrl->wCompQuality, buf + 12);
190 SHORT_TO_SW(ctrl->wCompWindowSize, buf + 14);
191 SHORT_TO_SW(ctrl->wDelay, buf + 16);
192 INT_TO_DW(ctrl->dwMaxVideoFrameSize, buf + 18);
193 INT_TO_DW(ctrl->dwMaxPayloadTransferSize, buf + 22);
195 if (len > 26) { // len == 34
196 // XXX add to support UVC 1.1
197 INT_TO_DW(ctrl->dwClockFrequency, buf + 26);
198 buf[30] = ctrl->bmFramingInfo;
199 buf[31] = ctrl->bPreferedVersion;
200 buf[32] = ctrl->bMinVersion;
201 buf[33] = ctrl->bMaxVersion;
203 // XXX add to support UVC1.5
204 buf[34] = ctrl->bUsage;
205 buf[35] = ctrl->bBitDepthLuma;
206 buf[36] = ctrl->bmSettings;
207 buf[37] = ctrl->bMaxNumberOfRefFramesPlus1;
208 SHORT_TO_SW(ctrl->bmRateControlModes, buf + 38);
209 LONG_TO_QW(ctrl->bmLayoutPerStream, buf + 40);
214 /* do the transfer */
215 err = libusb_control_transfer(devh->usb_devh,
216 req == UVC_SET_CUR ? 0x21 : 0xA1, req,
217 probe ? (UVC_VS_PROBE_CONTROL << 8) : (UVC_VS_COMMIT_CONTROL << 8),
218 ctrl->bInterfaceNumber, buf, len, 0);
220 if (UNLIKELY(err <= 0)) {
221 // when libusb_control_transfer returned error or transfer bytes was zero.
223 UVC_DEBUG("libusb_control_transfer transfered zero length data");
224 err = UVC_ERROR_OTHER;
229 #if !defined(__LP64__)
230 LOGE("transfered bytes is smaller than data bytes:%d expected %d", err, len);
232 LOGE("transfered bytes is smaller than data bytes:%d expected %ld", err, len);
234 return UVC_ERROR_OTHER;
236 /* now decode following a GET transfer */
237 if (req != UVC_SET_CUR) {
238 ctrl->bmHint = SW_TO_SHORT(buf);
239 ctrl->bFormatIndex = buf[2];
240 ctrl->bFrameIndex = buf[3];
241 ctrl->dwFrameInterval = DW_TO_INT(buf + 4);
242 ctrl->wKeyFrameRate = SW_TO_SHORT(buf + 8);
243 ctrl->wPFrameRate = SW_TO_SHORT(buf + 10);
244 ctrl->wCompQuality = SW_TO_SHORT(buf + 12);
245 ctrl->wCompWindowSize = SW_TO_SHORT(buf + 14);
246 ctrl->wDelay = SW_TO_SHORT(buf + 16);
247 ctrl->dwMaxVideoFrameSize = DW_TO_INT(buf + 18);
248 ctrl->dwMaxPayloadTransferSize = DW_TO_INT(buf + 22);
250 if (len > 26) { // len == 34
251 // XXX add to support UVC 1.1
252 ctrl->dwClockFrequency = DW_TO_INT(buf + 26);
253 ctrl->bmFramingInfo = buf[30];
254 ctrl->bPreferedVersion = buf[31];
255 ctrl->bMinVersion = buf[32];
256 ctrl->bMaxVersion = buf[33];
258 // XXX add to support UVC1.5
259 ctrl->bUsage = buf[34];
260 ctrl->bBitDepthLuma = buf[35];
261 ctrl->bmSettings = buf[36];
262 ctrl->bMaxNumberOfRefFramesPlus1 = buf[37];
263 ctrl->bmRateControlModes = SW_TO_SHORT(buf + 38);
264 ctrl->bmLayoutPerStream = QW_TO_LONG(buf + 40);
268 /* fix up block for cameras that fail to set dwMax */
269 if (!ctrl->dwMaxVideoFrameSize) {
270 LOGW("fix up block for cameras that fail to set dwMax");
271 uvc_frame_desc_t *frame_desc = uvc_find_frame_desc(devh,
272 ctrl->bFormatIndex, ctrl->bFrameIndex);
275 ctrl->dwMaxVideoFrameSize = frame_desc->dwMaxVideoFrameBufferSize;
283 /** @brief Reconfigure stream with a new stream format.
286 * This may be executed whether or not the stream is running.
288 * @param[in] strmh Stream handle
289 * @param[in] ctrl Control block, processed using {uvc_probe_stream_ctrl} or
290 * {uvc_get_stream_ctrl_format_size}
292 uvc_error_t uvc_stream_ctrl(uvc_stream_handle_t *strmh, uvc_stream_ctrl_t *ctrl) {
295 if (UNLIKELY(strmh->stream_if->bInterfaceNumber != ctrl->bInterfaceNumber))
296 return UVC_ERROR_INVALID_PARAM;
298 /* @todo Allow the stream to be modified without restarting the stream */
299 if (UNLIKELY(strmh->running))
300 return UVC_ERROR_BUSY;
302 ret = uvc_query_stream_ctrl(strmh->devh, ctrl, 0, UVC_SET_CUR); // commit query
303 if (UNLIKELY(ret != UVC_SUCCESS))
306 strmh->cur_ctrl = *ctrl;
311 * @brief Find the descriptor for a specific frame configuration
312 * @param stream_if Stream interface
313 * @param format_id Index of format class descriptor
314 * @param frame_id Index of frame descriptor
316 static uvc_frame_desc_t *_uvc_find_frame_desc_stream_if(
317 uvc_streaming_interface_t *stream_if, uint16_t format_id,
320 uvc_format_desc_t *format = NULL;
321 uvc_frame_desc_t *frame = NULL;
323 DL_FOREACH(stream_if->format_descs, format)
325 if (format->bFormatIndex == format_id) {
326 DL_FOREACH(format->frame_descs, frame)
328 if (frame->bFrameIndex == frame_id)
337 uvc_error_t uvc_get_frame_desc(uvc_device_handle_t *devh,
338 uvc_stream_ctrl_t *ctrl, uvc_frame_desc_t **desc) {
340 *desc = uvc_find_frame_desc(devh, ctrl->bFormatIndex, ctrl->bFrameIndex);
341 return *desc ? UVC_SUCCESS : UVC_ERROR_INVALID_PARAM;
344 uvc_frame_desc_t *uvc_find_frame_desc_stream(uvc_stream_handle_t *strmh,
345 uint16_t format_id, uint16_t frame_id) {
346 return _uvc_find_frame_desc_stream_if(strmh->stream_if, format_id, frame_id);
350 * @brief Find the descriptor for a specific frame configuration
351 * @param devh UVC device
352 * @param format_id Index of format class descriptor
353 * @param frame_id Index of frame descriptor
355 uvc_frame_desc_t *uvc_find_frame_desc(uvc_device_handle_t *devh,
356 uint16_t format_id, uint16_t frame_id) {
358 uvc_streaming_interface_t *stream_if;
359 uvc_frame_desc_t *frame;
361 DL_FOREACH(devh->info->stream_ifs, stream_if)
363 frame = _uvc_find_frame_desc_stream_if(stream_if, format_id, frame_id);
371 static void _uvc_print_streaming_interface_one(uvc_streaming_interface_t *stream_if) {
372 // struct uvc_device_info *parent;
373 // struct uvc_streaming_interface *prev, *next;
374 MARK("bInterfaceNumber:%d", stream_if->bInterfaceNumber);
375 uvc_print_format_desc_one(stream_if->format_descs, NULL);
376 MARK("bEndpointAddress:%d", stream_if->bEndpointAddress);
377 MARK("bTerminalLink:%d", stream_if->bTerminalLink);
380 static uvc_error_t _prepare_stream_ctrl(uvc_device_handle_t *devh, uvc_stream_ctrl_t *ctrl) {
381 // XXX some camera may need to call uvc_query_stream_ctrl with UVC_GET_CUR/UVC_GET_MAX/UVC_GET_MIN
382 // before negotiation otherwise stream stall. added by saki
383 uvc_error_t result = uvc_query_stream_ctrl(devh, ctrl, 1, UVC_GET_CUR); // probe query
384 if (LIKELY(!result)) {
385 result = uvc_query_stream_ctrl(devh, ctrl, 1, UVC_GET_MIN); // probe query
386 if (LIKELY(!result)) {
387 result = uvc_query_stream_ctrl(devh, ctrl, 1, UVC_GET_MAX); // probe query
388 if (UNLIKELY(result))
389 LOGE("uvc_query_stream_ctrl:UVC_GET_MAX:err=%d", result); // XXX 最大値の方を後で取得しないとだめ
391 LOGE("uvc_query_stream_ctrl:UVC_GET_MIN:err=%d", result);
394 LOGE("uvc_query_stream_ctrl:UVC_GET_CUR:err=%d", result);
397 if (UNLIKELY(result)) {
398 enum uvc_error_code_control error_code;
399 uvc_get_error_code(devh, &error_code, UVC_GET_CUR);
400 LOGE("uvc_query_stream_ctrl:ret=%d,err_code=%d", result, error_code);
401 uvc_print_format_desc(devh->info->stream_ifs->format_descs, NULL);
407 static uvc_error_t _uvc_get_stream_ctrl_format(uvc_device_handle_t *devh,
408 uvc_streaming_interface_t *stream_if, uvc_stream_ctrl_t *ctrl, uvc_format_desc_t *format,
409 const int width, const int height,
410 const int min_fps, const int max_fps) {
415 uvc_frame_desc_t *frame;
417 ctrl->bInterfaceNumber = stream_if->bInterfaceNumber;
418 uvc_error_t result = uvc_claim_if(devh, ctrl->bInterfaceNumber);
419 if (UNLIKELY(result)) {
420 LOGE("uvc_claim_if:err=%d", result);
423 for (i = 0; i < 2; i++) {
424 result = _prepare_stream_ctrl(devh, ctrl);
426 if (UNLIKELY(result)) {
427 LOGE("_prepare_stream_ctrl:err=%d", result);
431 // XXX add check ctrl values
432 uint64_t bmaControl = stream_if->bmaControls[format->bFormatIndex - 1];
433 if (bmaControl & 0x001) { // wKeyFrameRate
434 if (UNLIKELY(!ctrl->wKeyFrameRate)) {
435 LOGE("wKeyFrameRate should be set");
436 RETURN(UVC_ERROR_INVALID_MODE, uvc_error_t);
439 if (bmaControl & 0x002) { // wPFrameRate
440 if (UNLIKELY(!ctrl->wPFrameRate)) {
441 LOGE("wPFrameRate should be set");
442 RETURN(UVC_ERROR_INVALID_MODE, uvc_error_t);
445 if (bmaControl & 0x004) { // wCompQuality
446 if (UNLIKELY(!ctrl->wCompQuality)) {
447 LOGE("wCompQuality should be set");
448 RETURN(UVC_ERROR_INVALID_MODE, uvc_error_t);
451 if (bmaControl & 0x008) { // wCompWindowSize
452 if (UNLIKELY(!ctrl->wCompWindowSize)) {
453 LOGE("wCompWindowSize should be set");
454 RETURN(UVC_ERROR_INVALID_MODE, uvc_error_t);
458 DL_FOREACH(format->frame_descs, frame)
460 if (frame->wWidth != width || frame->wHeight != height)
465 if (frame->intervals) {
466 for (interval = frame->intervals; *interval; ++interval) {
467 if (UNLIKELY(!(*interval))) continue;
468 uint32_t it = 10000000 / *interval;
470 if ((it >= (uint32_t) min_fps) && (it <= (uint32_t) max_fps)) {
471 ctrl->bmHint = (1 << 0); /* don't negotiate interval */
472 ctrl->bFormatIndex = format->bFormatIndex;
473 ctrl->bFrameIndex = frame->bFrameIndex;
474 ctrl->dwFrameInterval = *interval;
481 for (fps = max_fps; fps >= min_fps; fps--) {
482 if (UNLIKELY(!fps)) continue;
483 uint32_t interval_100ns = 10000000 / fps;
484 uint32_t interval_offset = interval_100ns - frame->dwMinFrameInterval;
486 if (interval_100ns >= frame->dwMinFrameInterval
487 && interval_100ns <= frame->dwMaxFrameInterval
489 && (interval_offset % frame->dwFrameIntervalStep) ) ) {
490 ctrl->bmHint = (1 << 0); /* don't negotiate interval */
491 ctrl->bFormatIndex = format->bFormatIndex;
492 ctrl->bFrameIndex = frame->bFrameIndex;
493 ctrl->dwFrameInterval = interval_100ns;
500 result = UVC_ERROR_INVALID_MODE;
502 uvc_release_if(devh, ctrl->bInterfaceNumber);
503 RETURN(result, uvc_error_t);
506 RETURN(UVC_SUCCESS, uvc_error_t);
509 /** Get a negotiated streaming control block for some common parameters.
512 * @param[in] devh Device handle
513 * @param[in,out] ctrl Control block
514 * @param[in] cf Type of streaming format
515 * @param[in] width Desired frame width
516 * @param[in] height Desired frame height
517 * @param[in] fps Frame rate, frames per second
519 uvc_error_t uvc_get_stream_ctrl_format_size(uvc_device_handle_t *devh,
520 uvc_stream_ctrl_t *ctrl, enum uvc_frame_format cf, int width, int height, int fps) {
522 return uvc_get_stream_ctrl_format_size_fps(devh, ctrl, cf, width, height, fps, fps);
525 /** Get a negotiated streaming control block for some common parameters.
528 * @param[in] devh Device handle
529 * @param[in,out] ctrl Control block
530 * @param[in] cf Type of streaming format
531 * @param[in] width Desired frame width
532 * @param[in] height Desired frame height
533 * @param[in] min_fps Frame rate, minimum frames per second, this value is included
534 * @param[in] max_fps Frame rate, maximum frames per second, this value is included
536 uvc_error_t uvc_get_stream_ctrl_format_size_fps(uvc_device_handle_t *devh,
537 uvc_stream_ctrl_t *ctrl, enum uvc_frame_format cf, int width,
538 int height, int min_fps, int max_fps) {
542 uvc_streaming_interface_t *stream_if;
545 memset(ctrl, 0, sizeof(*ctrl)); // XXX add
546 /* find a matching frame descriptor and interval */
547 uvc_format_desc_t *format;
548 DL_FOREACH(devh->info->stream_ifs, stream_if)
550 DL_FOREACH(stream_if->format_descs, format)
552 if (!_uvc_frame_format_matches_guid(cf, format->guidFormat))
555 result = _uvc_get_stream_ctrl_format(devh, stream_if, ctrl, format, width, height, min_fps, max_fps);
556 if (!result) { // UVC_SUCCESS
562 RETURN(UVC_ERROR_INVALID_MODE, uvc_error_t);
565 RETURN(uvc_probe_stream_ctrl(devh, ctrl), uvc_error_t);
569 * Negotiate streaming parameters with the device
571 * @param[in] devh UVC device
572 * @param[in,out] ctrl Control block
574 uvc_error_t uvc_probe_stream_ctrl(uvc_device_handle_t *devh,
575 uvc_stream_ctrl_t *ctrl) {
578 err = uvc_claim_if(devh, ctrl->bInterfaceNumber);
580 LOGE("uvc_claim_if:err=%d", err);
584 err = uvc_query_stream_ctrl(devh, ctrl, 1, UVC_SET_CUR); // probe query
586 LOGE("uvc_query_stream_ctrl(UVC_SET_CUR):err=%d", err);
590 err = uvc_query_stream_ctrl(devh, ctrl, 1, UVC_GET_CUR); // probe query ここでエラーが返ってくる
592 LOGE("uvc_query_stream_ctrl(UVC_GET_CUR):err=%d", err);
600 * @brief Swap the working buffer with the presented buffer and notify consumers
602 static void _uvc_swap_buffers(uvc_stream_handle_t *strmh) {
605 pthread_mutex_lock(&strmh->cb_mutex);
607 /* swap the buffers */
608 tmp_buf = strmh->holdbuf;
609 strmh->hold_bfh_err = strmh->bfh_err; // XXX
610 strmh->hold_bytes = strmh->got_bytes;
611 strmh->holdbuf = strmh->outbuf;
612 strmh->outbuf = tmp_buf;
613 strmh->hold_last_scr = strmh->last_scr;
614 strmh->hold_pts = strmh->pts;
615 strmh->hold_seq = strmh->seq;
617 pthread_cond_broadcast(&strmh->cb_cond);
619 pthread_mutex_unlock(&strmh->cb_mutex);
622 strmh->got_bytes = 0;
625 strmh->bfh_err = 0; // XXX
628 static void _uvc_delete_transfer(struct libusb_transfer *transfer) {
632 uvc_stream_handle_t *strmh = transfer->user_data;
633 if (UNLIKELY(!strmh)) EXIT(); // XXX
636 pthread_mutex_lock(&strmh->cb_mutex); // XXX crash while calling uvc_stop_streaming
638 // Mark transfer as deleted.
639 for (i = 0; i < LIBUVC_NUM_TRANSFER_BUFS; i++) {
640 if (strmh->transfers[i] == transfer) {
641 libusb_cancel_transfer(strmh->transfers[i]); // XXX 20141112追加
642 UVC_DEBUG("Freeing transfer %d (%p)", i, transfer);
643 free(transfer->buffer);
644 libusb_free_transfer(transfer);
645 strmh->transfers[i] = NULL;
649 if (UNLIKELY(i == LIBUVC_NUM_TRANSFER_BUFS)) {
650 UVC_DEBUG("transfer %p not found; not freeing!", transfer);
653 pthread_cond_broadcast(&strmh->cb_cond);
655 pthread_mutex_unlock(&strmh->cb_mutex);
662 * @brief Process a payload transfer
664 * Processes stream, places frames into buffer, signals listeners
665 * (such as user callback thread and any polling thread) on new frame
667 * @param payload Contents of the payload transfer, either a packet (isochronous) or a full
668 * transfer (bulk mode)
669 * @param payload_len Length of the payload transfer
671 static void _uvc_process_payload(uvc_stream_handle_t *strmh, const uint8_t *payload, size_t const payload_len) {
675 struct libusb_iso_packet_descriptor *pkt;
676 uvc_vc_error_code_control_t vc_error_code;
677 uvc_vs_error_code_control_t vs_error_code;
679 // magic numbers for identifying header packets from some iSight cameras
680 static const uint8_t isight_tag[] = {
681 0x11, 0x22, 0x33, 0x44,
682 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xfa, 0xce
685 // ignore empty payload transfers
686 if (UNLIKELY(!payload || !payload_len || !strmh->outbuf))
689 /* Certain iSight cameras have strange behavior: They send header
690 * information in a packet with no image data, and then the following
691 * packets have only image data, with no more headers until the next frame.
693 * The iSight header: len(1), flags(1 or 2), 0x11223344(4),
694 * 0xdeadbeefdeadface(8), ??(16)
697 if (UNLIKELY(strmh->devh->is_isight &&
698 ((payload_len < 14) || memcmp(isight_tag, payload + 2, sizeof(isight_tag)) ) &&
699 ((payload_len < 15) || memcmp(isight_tag, payload + 3, sizeof(isight_tag)) ) )) {
700 // The payload transfer doesn't have any iSight magic, so it's all image data
702 data_len = payload_len;
704 header_len = payload[0];
706 if (UNLIKELY(header_len > payload_len)) {
707 strmh->bfh_err |= UVC_STREAM_ERR;
708 UVC_DEBUG("bogus packet: actual_len=%zd, header_len=%zd\n", payload_len, header_len);
712 if (UNLIKELY(strmh->devh->is_isight))
715 data_len = payload_len - header_len;
718 if (UNLIKELY(header_len < 2)) {
721 // @todo we should be checking the end-of-header bit
722 size_t variable_offset = 2;
724 header_info = payload[1];
726 if (UNLIKELY(header_info & UVC_STREAM_ERR)) {
727 // strmh->bfh_err |= UVC_STREAM_ERR;
728 UVC_DEBUG("bad packet: error bit set");
729 libusb_clear_halt(strmh->devh->usb_devh, strmh->stream_if->bEndpointAddress);
730 // uvc_vc_get_error_code(strmh->devh, &vc_error_code, UVC_GET_CUR);
731 uvc_vs_get_error_code(strmh->devh, &vs_error_code, UVC_GET_CUR);
735 if ((strmh->fid != (header_info & UVC_STREAM_FID)) && strmh->got_bytes) {
736 /* The frame ID bit was flipped, but we have image data sitting
737 around from prior transfers. This means the camera didn't send
738 an EOF for the last transfer of the previous frame. */
739 _uvc_swap_buffers(strmh);
742 strmh->fid = header_info & UVC_STREAM_FID;
744 if (header_info & UVC_STREAM_PTS) {
745 // XXX saki some camera may send broken packet or failed to receive all data
746 if (LIKELY(variable_offset + 4 <= header_len)) {
747 strmh->pts = DW_TO_INT(payload + variable_offset);
748 variable_offset += 4;
750 MARK("bogus packet: header info has UVC_STREAM_PTS, but no data");
755 if (header_info & UVC_STREAM_SCR) {
756 // @todo read the SOF token counter
757 // XXX saki some camera may send broken packet or failed to receive all data
758 if (LIKELY(variable_offset + 4 <= header_len)) {
759 strmh->last_scr = DW_TO_INT(payload + variable_offset);
760 variable_offset += 4;
762 MARK("bogus packet: header info has UVC_STREAM_SCR, but no data");
768 if (LIKELY(data_len > 0)) {
769 if (LIKELY(strmh->got_bytes + data_len < strmh->size_buf)) {
770 memcpy(strmh->outbuf + strmh->got_bytes, payload + header_len, data_len);
771 strmh->got_bytes += data_len;
773 strmh->bfh_err |= UVC_STREAM_ERR;
776 if (header_info & UVC_STREAM_EOF/*(1 << 1)*/) {
777 // The EOF bit is set, so publish the complete frame
778 _uvc_swap_buffers(strmh);
784 static inline void _uvc_process_payload_iso(uvc_stream_handle_t *strmh, struct libusb_transfer *transfer) {
785 /* This is an isochronous mode transfer, so each packet has a payload transfer */
787 for (packet_id = 0; packet_id < transfer->num_iso_packets; packet_id++) {
788 struct libusb_iso_packet_descriptor *pkt = transfer->iso_packet_desc + packet_id;
790 if UNLIKELY(pkt->status) {
791 // UVC_DEBUG("bad packet:status=%d,actual_length=%d", pkt->status, pkt->actual_length);
792 MARK("bad packet:status=%d,actual_length=%d", pkt->status, pkt->actual_length);
795 if UNLIKELY(!pkt->actual_length) {
796 MARK("zero packet (transfer):");
799 // libusb_get_iso_packet_buffer_simple will return NULL
800 uint8_t *pktbuf = libusb_get_iso_packet_buffer_simple(transfer, packet_id);
801 _uvc_process_payload(strmh, pktbuf, pkt->actual_length);
805 static inline void _uvc_process_payload_iso(uvc_stream_handle_t *strmh, struct libusb_transfer *transfer) {
808 uint8_t check_header;
811 struct libusb_iso_packet_descriptor *pkt;
813 /* magic numbers for identifying header packets from some iSight cameras */
814 static const uint8_t isight_tag[] = {
815 0x11, 0x22, 0x33, 0x44, 0xde, 0xad,
816 0xbe, 0xef, 0xde, 0xad, 0xfa, 0xce };
818 uvc_vc_error_code_control_t vc_error_code;
819 uvc_vs_error_code_control_t vs_error_code;
821 for (packet_id = 0; packet_id < transfer->num_iso_packets; ++packet_id) {
824 pkt = transfer->iso_packet_desc + packet_id;
826 if (UNLIKELY(pkt->status != 0)) {
827 MARK("bad packet:status=%d,actual_length=%d", pkt->status, pkt->actual_length);
828 strmh->bfh_err |= UVC_STREAM_ERR;
829 libusb_clear_halt(strmh->devh->usb_devh, strmh->stream_if->bEndpointAddress);
830 // uvc_vc_get_error_code(strmh->devh, &vc_error_code, UVC_GET_CUR);
831 // uvc_vs_get_error_code(strmh->devh, &vs_error_code, UVC_GET_CUR);
835 if (UNLIKELY(!pkt->actual_length)) { // why transfered byte is zero...
836 // MARK("zero packet (transfer):");
837 // strmh->bfh_err |= UVC_STREAM_ERR; // don't set this flag here
840 // XXX accessing to pktbuf could lead to crash on the original implementation
841 // because the substances of pktbuf will be deleted in uvc_stream_stop.
842 pktbuf = libusb_get_iso_packet_buffer_simple(transfer, packet_id);
843 if (LIKELY(pktbuf)) { // XXX add null check because libusb_get_iso_packet_buffer_simple could return null
844 // assert(pktbuf < transfer->buffer + transfer->length - 1); // XXX
846 // XXX optimaization because this flag never become true on Android devices
847 if (UNLIKELY(strmh->devh->is_isight))
849 if (strmh->devh->is_isight)
852 if (pkt->actual_length < 30
853 || (memcmp(isight_tag, pktbuf + 2, sizeof(isight_tag))
854 && memcmp(isight_tag, pktbuf + 3, sizeof(isight_tag)))) {
858 header_len = pktbuf[0];
861 header_len = pktbuf[0]; // Header length field of Stream Header
864 if (LIKELY(check_header)) {
865 header_info = pktbuf[1];
866 if (UNLIKELY(header_info & UVC_STREAM_ERR)) {
867 // strmh->bfh_err |= UVC_STREAM_ERR;
868 MARK("bad packet:status=0x%2x", header_info);
869 libusb_clear_halt(strmh->devh->usb_devh, strmh->stream_if->bEndpointAddress);
870 // uvc_vc_get_error_code(strmh->devh, &vc_error_code, UVC_GET_CUR);
871 uvc_vs_get_error_code(strmh->devh, &vs_error_code, UVC_GET_CUR);
875 if ((strmh->fid != (header_info & UVC_STREAM_FID)) && strmh->got_bytes) { // got_bytesを取ると殆ど画面更新されない
876 /* The frame ID bit was flipped, but we have image data sitting
877 around from prior transfers. This means the camera didn't send
878 an EOF for the last transfer of the previous frame or some frames losted. */
879 _uvc_swap_buffers(strmh);
881 strmh->fid = header_info & UVC_STREAM_FID;
883 if (strmh->fid != (header_info & UVC_STREAM_FID)) { // when FID is toggled
884 _uvc_swap_buffers(strmh);
885 strmh->fid = header_info & UVC_STREAM_FID;
888 if (header_info & UVC_STREAM_PTS) {
889 // XXX saki some camera may send broken packet or failed to receive all data
890 if (LIKELY(header_len >= 6)) {
891 strmh->pts = DW_TO_INT(pktbuf + 2);
893 MARK("bogus packet: header info has UVC_STREAM_PTS, but no data");
898 if (header_info & UVC_STREAM_SCR) {
899 // XXX saki some camera may send broken packet or failed to receive all data
900 if (LIKELY(header_len >= 10)) {
901 strmh->last_scr = DW_TO_INT(pktbuf + 6);
903 MARK("bogus packet: header info has UVC_STREAM_SCR, but no data");
908 #ifdef __ANDROID__ // XXX optimaization because this flag never become true on Android devices
909 if (UNLIKELY(strmh->devh->is_isight))
910 continue; // don't look for data after an iSight header
912 if (strmh->devh->is_isight) {
914 continue; // don't look for data after an iSight header
917 } // if LIKELY(check_header)
919 if (UNLIKELY(pkt->actual_length < header_len)) {
920 /* Bogus packet received */
921 strmh->bfh_err |= UVC_STREAM_ERR;
922 MARK("bogus packet: actual_len=%d, header_len=%zd", pkt->actual_length, header_len);
926 // XXX original implementation could lead to trouble because unsigned values
927 // and there calculated value never become minus.
928 // therefor changed to "if (pkt->actual_length > header_len)"
929 // from "if (pkt->actual_length - header_len > 0)"
930 if (LIKELY(pkt->actual_length > header_len)) {
931 const size_t odd_bytes = pkt->actual_length - header_len;
932 assert(strmh->got_bytes + odd_bytes < strmh->size_buf);
933 assert(strmh->outbuf);
935 memcpy(strmh->outbuf + strmh->got_bytes, pktbuf + header_len, odd_bytes);
936 strmh->got_bytes += odd_bytes;
939 if ((pktbuf[1] & UVC_STREAM_EOF) && strmh->got_bytes != 0) {
940 /* The EOF bit is set, so publish the complete frame */
941 _uvc_swap_buffers(strmh);
944 } else { // if (LIKELY(pktbuf))
945 strmh->bfh_err |= UVC_STREAM_ERR;
946 MARK("libusb_get_iso_packet_buffer_simple returned null");
954 * @brief Isochronous transfer callback
956 * Processes stream, places frames into buffer, signals listeners
957 * (such as user callback thread and any polling thread) on new frame
959 * @param transfer Active transfer
961 static void _uvc_stream_callback(struct libusb_transfer *transfer) {
962 if UNLIKELY(!transfer) return;
964 uvc_stream_handle_t *strmh = transfer->user_data;
965 if UNLIKELY(!strmh) return;
971 if UNLIKELY((++cnt % 1000) == 0)
974 switch (transfer->status) {
975 case LIBUSB_TRANSFER_COMPLETED:
976 if (!transfer->num_iso_packets) {
977 /* This is a bulk mode transfer, so it just has one payload transfer */
978 _uvc_process_payload(strmh, transfer->buffer, transfer->actual_length);
980 /* This is an isochronous mode transfer, so each packet has a payload transfer */
981 _uvc_process_payload_iso(strmh, transfer);
984 case LIBUSB_TRANSFER_NO_DEVICE:
985 strmh->running = 0; // this needs for unexpected disconnect of cable otherwise hangup
986 // pass through to following lines
987 case LIBUSB_TRANSFER_CANCELLED:
988 case LIBUSB_TRANSFER_ERROR:
989 UVC_DEBUG("not retrying transfer, status = %d", transfer->status);
990 // MARK("not retrying transfer, status = %d", transfer->status);
991 // _uvc_delete_transfer(transfer);
994 case LIBUSB_TRANSFER_TIMED_OUT:
995 case LIBUSB_TRANSFER_STALL:
996 case LIBUSB_TRANSFER_OVERFLOW:
997 UVC_DEBUG("retrying transfer, status = %d", transfer->status);
998 // MARK("retrying transfer, status = %d", transfer->status);
1002 if (LIKELY(strmh->running && resubmit)) {
1003 libusb_submit_transfer(transfer);
1005 // XXX delete non-reusing transfer
1006 // real implementation of deleting transfer moves to _uvc_delete_transfer
1007 _uvc_delete_transfer(transfer);
1013 * @brief Isochronous transfer callback
1015 * Processes stream, places frames into buffer, signals listeners
1016 * (such as user callback thread and any polling thread) on new frame
1018 * @param transfer Active transfer
1020 static void _uvc_iso_callback(struct libusb_transfer *transfer) {
1021 uvc_stream_handle_t *strmh;
1026 uint8_t check_header;
1027 size_t header_len; // XXX unsigned int header_len
1028 uint8_t header_info;
1029 struct libusb_iso_packet_descriptor *pkt;
1031 /* magic numbers for identifying header packets from some iSight cameras */
1032 static const uint8_t isight_tag[] = {
1033 0x11, 0x22, 0x33, 0x44, 0xde, 0xad,
1034 0xbe, 0xef, 0xde, 0xad, 0xfa, 0xce };
1036 strmh = transfer->user_data;
1039 if ((++cnt % 1000) == 0)
1040 MARK("cnt=%d", cnt);
1042 switch (transfer->status) {
1043 case LIBUSB_TRANSFER_COMPLETED:
1044 if (UNLIKELY(!transfer->num_iso_packets))
1045 MARK("num_iso_packets is zero");
1046 for (packet_id = 0; packet_id < transfer->num_iso_packets; ++packet_id) {
1049 pkt = transfer->iso_packet_desc + packet_id;
1051 if (UNLIKELY(pkt->status != 0)) {
1052 MARK("bad packet:status=%d,actual_length=%d", pkt->status, pkt->actual_length);
1053 strmh->bfh_err |= UVC_STREAM_ERR;
1057 if (UNLIKELY(!pkt->actual_length)) { // why transfered byte is zero...
1058 // MARK("zero packet (transfer):");
1059 // strmh->bfh_err |= UVC_STREAM_ERR; // don't set this flag here
1062 // XXX accessing to pktbuf could lead to crash on the original implementation
1063 // because the substances of pktbuf will be deleted in uvc_stream_stop.
1064 pktbuf = libusb_get_iso_packet_buffer_simple(transfer, packet_id);
1065 if (LIKELY(pktbuf)) { // XXX add null check because libusb_get_iso_packet_buffer_simple could return null
1066 // assert(pktbuf < transfer->buffer + transfer->length - 1); // XXX
1068 // XXX optimaization because this flag never become true on Android devices
1069 if (UNLIKELY(strmh->devh->is_isight))
1071 if (strmh->devh->is_isight)
1074 if (pkt->actual_length < 30
1075 || (memcmp(isight_tag, pktbuf + 2, sizeof(isight_tag))
1076 && memcmp(isight_tag, pktbuf + 3, sizeof(isight_tag)))) {
1080 header_len = pktbuf[0];
1083 header_len = pktbuf[0]; // Header length field of Stream Header
1086 if (LIKELY(check_header)) {
1087 header_info = pktbuf[1];
1088 if (UNLIKELY(header_info & UVC_STREAM_ERR)) {
1089 strmh->bfh_err |= UVC_STREAM_ERR;
1091 // libusb_clear_halt(strmh->devh->usb_devh, strmh->stream_if->bEndpointAddress);
1092 uvc_vc_get_error_code(strmh->devh, &vc_error_code, UVC_GET_CUR);
1093 uvc_vs_get_error_code(strmh->devh, &vs_error_code, UVC_GET_CUR);
1097 if ((strmh->fid != (header_info & UVC_STREAM_FID)) && strmh->got_bytes) { // got_bytesを取ると殆ど画面更新されない
1098 /* The frame ID bit was flipped, but we have image data sitting
1099 around from prior transfers. This means the camera didn't send
1100 an EOF for the last transfer of the previous frame or some frames losted. */
1101 _uvc_swap_buffers(strmh);
1103 strmh->fid = header_info & UVC_STREAM_FID;
1105 if (strmh->fid != (header_info & UVC_STREAM_FID)) { // when FID is toggled
1106 _uvc_swap_buffers(strmh);
1107 strmh->fid = header_info & UVC_STREAM_FID;
1110 if (header_info & UVC_STREAM_PTS) {
1111 // XXX saki some camera may send broken packet or failed to receive all data
1112 if (LIKELY(header_len >= 6)) {
1113 strmh->pts = DW_TO_INT(pktbuf + 2);
1115 MARK("bogus packet: header info has UVC_STREAM_PTS, but no data");
1120 if (header_info & UVC_STREAM_SCR) {
1121 // XXX saki some camera may send broken packet or failed to receive all data
1122 if (LIKELY(header_len >= 10)) {
1123 strmh->last_scr = DW_TO_INT(pktbuf + 6);
1125 MARK("bogus packet: header info has UVC_STREAM_SCR, but no data");
1126 strmh->last_scr = 0;
1130 #ifdef __ANDROID__ // XXX optimaization because this flag never become true on Android devices
1131 if (UNLIKELY(strmh->devh->is_isight))
1132 continue; // don't look for data after an iSight header
1134 if (strmh->devh->is_isight) {
1136 continue; // don't look for data after an iSight header
1139 } // if LIKELY(check_header)
1141 if (UNLIKELY(pkt->actual_length < header_len)) {
1142 /* Bogus packet received */
1143 strmh->bfh_err |= UVC_STREAM_ERR;
1144 MARK("bogus packet: actual_len=%d, header_len=%zd", pkt->actual_length, header_len);
1148 // XXX original implementation could lead to trouble because unsigned values
1149 // and there calculated value never become minus.
1150 // therefor changed to "if (pkt->actual_length > header_len)"
1151 // from "if (pkt->actual_length - header_len > 0)"
1152 if (LIKELY(pkt->actual_length > header_len)) {
1153 const size_t odd_bytes = pkt->actual_length - header_len;
1154 assert(strmh->got_bytes + odd_bytes < strmh->size_buf);
1155 assert(strmh->outbuf);
1157 memcpy(strmh->outbuf + strmh->got_bytes, pktbuf + header_len, odd_bytes);
1158 strmh->got_bytes += odd_bytes;
1161 if ((pktbuf[1] & STREAM_HEADER_BFH_EOF) && strmh->got_bytes != 0) {
1162 /* The EOF bit is set, so publish the complete frame */
1163 _uvc_swap_buffers(strmh);
1166 } else { // if (LIKELY(pktbuf))
1167 strmh->bfh_err |= UVC_STREAM_ERR;
1168 MARK("libusb_get_iso_packet_buffer_simple returned null");
1173 case LIBUSB_TRANSFER_NO_DEVICE:
1174 strmh->running = 0; // this needs for unexpected disconnect of cable otherwise hangup
1175 case LIBUSB_TRANSFER_CANCELLED:
1176 case LIBUSB_TRANSFER_ERROR:
1177 UVC_DEBUG("not retrying transfer, status = %d", transfer->status);
1178 // MARK("not retrying transfer, status = %d", transfer->status);
1179 _uvc_delete_transfer(transfer);
1181 case LIBUSB_TRANSFER_TIMED_OUT:
1182 case LIBUSB_TRANSFER_STALL:
1183 case LIBUSB_TRANSFER_OVERFLOW:
1184 UVC_DEBUG("retrying transfer, status = %d", transfer->status);
1185 // MARK("retrying transfer, status = %d", transfer->status);
1189 if (LIKELY(strmh->running)) {
1190 libusb_submit_transfer(transfer);
1192 // XXX delete non-reusing transfer
1193 // real implementation of deleting transfer moves to _uvc_delete_transfer
1194 _uvc_delete_transfer(transfer);
1199 /** Begin streaming video from the camera into the callback function.
1200 * @ingroup streaming
1202 * @param devh UVC device
1203 * @param ctrl Control block, processed using {uvc_probe_stream_ctrl} or
1204 * {uvc_get_stream_ctrl_format_size}
1205 * @param cb User callback function. See {uvc_frame_callback_t} for restrictions.
1206 * @param flags Stream setup flags, currently undefined. Set this to zero. The lower bit
1207 * is reserved for backward compatibility.
1209 uvc_error_t uvc_start_streaming(uvc_device_handle_t *devh,
1210 uvc_stream_ctrl_t *ctrl, uvc_frame_callback_t *cb, void *user_ptr,
1212 return uvc_start_streaming_bandwidth(devh, ctrl, cb, user_ptr, 0, flags);
1215 /** Begin streaming video from the camera into the callback function.
1216 * @ingroup streaming
1218 * @param devh UVC device
1219 * @param ctrl Control block, processed using {uvc_probe_stream_ctrl} or
1220 * {uvc_get_stream_ctrl_format_size}
1221 * @param cb User callback function. See {uvc_frame_callback_t} for restrictions.
1222 * @param bandwidth_factor [0.0f, 1.0f]
1223 * @param flags Stream setup flags, currently undefined. Set this to zero. The lower bit
1224 * is reserved for backward compatibility.
1226 uvc_error_t uvc_start_streaming_bandwidth(uvc_device_handle_t *devh,
1227 uvc_stream_ctrl_t *ctrl, uvc_frame_callback_t *cb, void *user_ptr,
1228 float bandwidth_factor,
1231 uvc_stream_handle_t *strmh;
1233 ret = uvc_stream_open_ctrl(devh, &strmh, ctrl);
1234 if (UNLIKELY(ret != UVC_SUCCESS))
1237 ret = uvc_stream_start_bandwidth(strmh, cb, user_ptr, bandwidth_factor, flags);
1238 if (UNLIKELY(ret != UVC_SUCCESS)) {
1239 uvc_stream_close(strmh);
1246 /** Begin streaming video from the camera into the callback function.
1247 * @ingroup streaming
1249 * @deprecated The stream type (bulk vs. isochronous) will be determined by the
1250 * type of interface associated with the uvc_stream_ctrl_t parameter, regardless
1251 * of whether the caller requests isochronous streaming. Please switch to
1252 * uvc_start_streaming().
1254 * @param devh UVC device
1255 * @param ctrl Control block, processed using {uvc_probe_stream_ctrl} or
1256 * {uvc_get_stream_ctrl_format_size}
1257 * @param cb User callback function. See {uvc_frame_callback_t} for restrictions.
1259 uvc_error_t uvc_start_iso_streaming(uvc_device_handle_t *devh,
1260 uvc_stream_ctrl_t *ctrl, uvc_frame_callback_t *cb, void *user_ptr) {
1261 return uvc_start_streaming_bandwidth(devh, ctrl, cb, user_ptr, 0.0f, 0);
1264 static uvc_stream_handle_t *_uvc_get_stream_by_interface(
1265 uvc_device_handle_t *devh, int interface_idx) {
1266 uvc_stream_handle_t *strmh;
1268 DL_FOREACH(devh->streams, strmh)
1270 if (strmh->stream_if->bInterfaceNumber == interface_idx)
1277 static uvc_streaming_interface_t *_uvc_get_stream_if(uvc_device_handle_t *devh,
1278 int interface_idx) {
1279 uvc_streaming_interface_t *stream_if;
1281 DL_FOREACH(devh->info->stream_ifs, stream_if)
1283 if (stream_if->bInterfaceNumber == interface_idx)
1290 /** Open a new video stream.
1291 * @ingroup streaming
1293 * @param devh UVC device
1294 * @param ctrl Control block, processed using {uvc_probe_stream_ctrl} or
1295 * {uvc_get_stream_ctrl_format_size}
1297 uvc_error_t uvc_stream_open_ctrl(uvc_device_handle_t *devh,
1298 uvc_stream_handle_t **strmhp, uvc_stream_ctrl_t *ctrl) {
1299 /* Chosen frame and format descriptors */
1300 uvc_stream_handle_t *strmh = NULL;
1301 uvc_streaming_interface_t *stream_if;
1306 if (UNLIKELY(_uvc_get_stream_by_interface(devh, ctrl->bInterfaceNumber) != NULL)) {
1307 ret = UVC_ERROR_BUSY; /* Stream is already opened */
1311 stream_if = _uvc_get_stream_if(devh, ctrl->bInterfaceNumber);
1312 if (UNLIKELY(!stream_if)) {
1313 ret = UVC_ERROR_INVALID_PARAM;
1317 strmh = calloc(1, sizeof(*strmh));
1318 if (UNLIKELY(!strmh)) {
1319 ret = UVC_ERROR_NO_MEM;
1323 strmh->stream_if = stream_if;
1324 strmh->frame.library_owns_data = 1;
1326 ret = uvc_claim_if(strmh->devh, strmh->stream_if->bInterfaceNumber);
1327 if (UNLIKELY(ret != UVC_SUCCESS))
1330 ret = uvc_stream_ctrl(strmh, ctrl);
1331 if (UNLIKELY(ret != UVC_SUCCESS))
1334 // Set up the streaming status and data space
1336 /** @todo take only what we need */
1337 strmh->outbuf = malloc(LIBUVC_XFER_BUF_SIZE);
1338 strmh->holdbuf = malloc(LIBUVC_XFER_BUF_SIZE);
1339 strmh->size_buf = LIBUVC_XFER_BUF_SIZE; // xxx for boundary check
1341 pthread_mutex_init(&strmh->cb_mutex, NULL);
1342 pthread_cond_init(&strmh->cb_cond, NULL);
1344 DL_APPEND(devh->streams, strmh);
1358 /** Begin streaming video from the stream into the callback function.
1359 * @ingroup streaming
1361 * @param strmh UVC stream
1362 * @param cb User callback function. See {uvc_frame_callback_t} for restrictions.
1363 * @param flags Stream setup flags, currently undefined. Set this to zero. The lower bit
1364 * is reserved for backward compatibility.
1366 uvc_error_t uvc_stream_start(uvc_stream_handle_t *strmh,
1367 uvc_frame_callback_t *cb, void *user_ptr, uint8_t flags) {
1368 return uvc_stream_start_bandwidth(strmh, cb, user_ptr, 0, flags);
1371 /** Begin streaming video from the stream into the callback function.
1372 * @ingroup streaming
1374 * @param strmh UVC stream
1375 * @param cb User callback function. See {uvc_frame_callback_t} for restrictions.
1376 * @param bandwidth_factor [0.0f, 1.0f]
1377 * @param flags Stream setup flags, currently undefined. Set this to zero. The lower bit
1378 * is reserved for backward compatibility.
1380 uvc_error_t uvc_stream_start_bandwidth(uvc_stream_handle_t *strmh,
1381 uvc_frame_callback_t *cb, void *user_ptr, float bandwidth_factor, uint8_t flags) {
1382 /* USB interface we'll be using */
1383 const struct libusb_interface *interface;
1386 uvc_frame_desc_t *frame_desc;
1387 uvc_format_desc_t *format_desc;
1388 uvc_stream_ctrl_t *ctrl;
1390 /* Total amount of data per transfer */
1391 size_t total_transfer_size;
1392 struct libusb_transfer *transfer;
1395 ctrl = &strmh->cur_ctrl;
1399 if (UNLIKELY(strmh->running)) {
1400 UVC_EXIT(UVC_ERROR_BUSY);
1401 return UVC_ERROR_BUSY;
1408 strmh->last_scr = 0;
1409 strmh->bfh_err = 0; // XXX
1411 frame_desc = uvc_find_frame_desc_stream(strmh, ctrl->bFormatIndex, ctrl->bFrameIndex);
1412 if (UNLIKELY(!frame_desc)) {
1413 ret = UVC_ERROR_INVALID_PARAM;
1414 LOGE("UVC_ERROR_INVALID_PARAM");
1417 format_desc = frame_desc->parent;
1419 strmh->frame_format = uvc_frame_format_for_guid(format_desc->guidFormat);
1420 if (UNLIKELY(strmh->frame_format == UVC_FRAME_FORMAT_UNKNOWN)) {
1421 ret = UVC_ERROR_NOT_SUPPORTED;
1422 LOGE("unlnown frame format");
1425 const uint32_t dwMaxVideoFrameSize = ctrl->dwMaxVideoFrameSize <= frame_desc->dwMaxVideoFrameBufferSize
1426 ? ctrl->dwMaxVideoFrameSize : frame_desc->dwMaxVideoFrameBufferSize;
1428 // Get the interface that provides the chosen format and frame configuration
1429 interface_id = strmh->stream_if->bInterfaceNumber;
1430 interface = &strmh->devh->info->config->interface[interface_id];
1432 /* A VS interface uses isochronous transfers if it has multiple altsettings.
1433 * (UVC 1.5: 2.4.3. VideoStreaming Interface, on page 19) */
1434 isochronous = interface->num_altsetting > 1;
1437 MARK("isochronous transfer mode:num_altsetting=%d", interface->num_altsetting);
1438 /* For isochronous streaming, we choose an appropriate altsetting for the endpoint
1439 * and set up several transfers */
1440 const struct libusb_interface_descriptor *altsetting;
1441 const struct libusb_endpoint_descriptor *endpoint;
1442 /* The greatest number of bytes that the device might provide, per packet, in this
1444 size_t config_bytes_per_packet;
1445 /* Number of packets per transfer */
1446 size_t packets_per_transfer;
1447 /* Total amount of data per transfer */
1448 size_t total_transfer_size;
1449 /* Size of packet transferable from the chosen endpoint */
1450 size_t endpoint_bytes_per_packet;
1451 /* Index of the altsetting */
1452 int alt_idx, ep_idx;
1454 struct libusb_transfer *transfer;
1457 if ((bandwidth_factor > 0) && (bandwidth_factor < 1.0f)) {
1458 config_bytes_per_packet = (size_t)(strmh->cur_ctrl.dwMaxPayloadTransferSize * bandwidth_factor);
1459 if (!config_bytes_per_packet) {
1460 config_bytes_per_packet = strmh->cur_ctrl.dwMaxPayloadTransferSize;
1463 config_bytes_per_packet = strmh->cur_ctrl.dwMaxPayloadTransferSize;
1465 //#if !defined(__LP64__)
1466 // LOGI("config_bytes_per_packet=%d", config_bytes_per_packet);
1468 // LOGI("config_bytes_per_packet=%ld", config_bytes_per_packet);
1470 if (UNLIKELY(!config_bytes_per_packet)) { // XXX added to privent zero divided exception at the following code
1472 LOGE("config_bytes_per_packet is zero");
1476 /* Go through the altsettings and find one whose packets are at least
1477 * as big as our format's maximum per-packet usage. Assume that the
1478 * packet sizes are increasing. */
1479 const int num_alt = interface->num_altsetting - 1;
1480 for (alt_idx = 0; alt_idx <= num_alt ; alt_idx++) {
1481 altsetting = interface->altsetting + alt_idx;
1482 endpoint_bytes_per_packet = 0;
1484 /* Find the endpoint with the number specified in the VS header */
1485 for (ep_idx = 0; ep_idx < altsetting->bNumEndpoints; ep_idx++) {
1486 endpoint = altsetting->endpoint + ep_idx;
1487 if (endpoint->bEndpointAddress == format_desc->parent->bEndpointAddress) {
1488 endpoint_bytes_per_packet = endpoint->wMaxPacketSize;
1489 // wMaxPacketSize: [unused:2 (multiplier-1):3 size:11]
1490 // bit10…0: maximum packet size
1491 // bit12…11: the number of additional transaction opportunities per microframe for high-speed
1492 // 00 = None (1 transaction per microframe)
1493 // 01 = 1 additional (2 per microframe)
1494 // 10 = 2 additional (3 per microframe)
1496 endpoint_bytes_per_packet
1497 = (endpoint_bytes_per_packet & 0x07ff)
1498 * (((endpoint_bytes_per_packet >> 11) & 3) + 1);
1502 // XXX config_bytes_per_packet should not be zero otherwise zero divided exception occur
1503 if (LIKELY(endpoint_bytes_per_packet)) {
1504 if ( (endpoint_bytes_per_packet >= config_bytes_per_packet)
1505 || (alt_idx == num_alt) ) { // XXX always match to last altsetting for buggy device
1506 /* Transfers will be at most one frame long: Divide the maximum frame size
1507 * by the size of the endpoint and round up */
1508 packets_per_transfer = (dwMaxVideoFrameSize
1509 + endpoint_bytes_per_packet - 1)
1510 / endpoint_bytes_per_packet; // XXX cashed by zero divided exception occured
1512 /* But keep a reasonable limit: Otherwise we start dropping data */
1513 if (packets_per_transfer > 32)
1514 packets_per_transfer = 32;
1516 total_transfer_size = packets_per_transfer * endpoint_bytes_per_packet;
1521 if (UNLIKELY(!endpoint_bytes_per_packet)) {
1522 LOGE("endpoint_bytes_per_packet is zero");
1523 ret = UVC_ERROR_INVALID_MODE;
1526 if (UNLIKELY(!total_transfer_size)) {
1527 LOGE("total_transfer_size is zero");
1528 ret = UVC_ERROR_INVALID_MODE;
1532 /* If we searched through all the altsettings and found nothing usable */
1533 /* if (UNLIKELY(alt_idx == interface->num_altsetting)) { // XXX never hit this condition
1534 UVC_DEBUG("libusb_set_interface_alt_setting failed");
1535 ret = UVC_ERROR_INVALID_MODE;
1539 /* Select the altsetting */
1540 MARK("Select the altsetting");
1541 ret = libusb_set_interface_alt_setting(strmh->devh->usb_devh,
1542 altsetting->bInterfaceNumber, altsetting->bAlternateSetting);
1543 if (UNLIKELY(ret != UVC_SUCCESS)) {
1544 UVC_DEBUG("libusb_set_interface_alt_setting failed");
1548 /* Set up the transfers */
1549 MARK("Set up the transfers");
1550 for (transfer_id = 0; transfer_id < LIBUVC_NUM_TRANSFER_BUFS; ++transfer_id) {
1551 transfer = libusb_alloc_transfer(packets_per_transfer);
1552 strmh->transfers[transfer_id] = transfer;
1553 strmh->transfer_bufs[transfer_id] = malloc(total_transfer_size);
1555 libusb_fill_iso_transfer(transfer, strmh->devh->usb_devh,
1556 format_desc->parent->bEndpointAddress,
1557 strmh->transfer_bufs[transfer_id], total_transfer_size,
1558 packets_per_transfer, _uvc_stream_callback,
1559 (void*) strmh, 5000);
1561 libusb_set_iso_packet_lengths(transfer, endpoint_bytes_per_packet);
1564 MARK("bulk transfer mode");
1565 /** prepare for bulk transfer */
1566 for (transfer_id = 0; transfer_id < LIBUVC_NUM_TRANSFER_BUFS; ++transfer_id) {
1567 transfer = libusb_alloc_transfer(0);
1568 strmh->transfers[transfer_id] = transfer;
1569 strmh->transfer_bufs[transfer_id] = malloc(strmh->cur_ctrl.dwMaxPayloadTransferSize);
1570 libusb_fill_bulk_transfer(transfer, strmh->devh->usb_devh,
1571 format_desc->parent->bEndpointAddress,
1572 strmh->transfer_bufs[transfer_id],
1573 strmh->cur_ctrl.dwMaxPayloadTransferSize, _uvc_stream_callback,
1574 (void *)strmh, 5000);
1578 strmh->user_cb = cb;
1579 strmh->user_ptr = user_ptr;
1581 /* If the user wants it, set up a thread that calls the user's function
1582 * with the contents of each frame.
1584 MARK("create callback thread");
1586 pthread_create(&strmh->cb_thread, NULL, _uvc_user_caller, (void*) strmh);
1588 MARK("submit transfers");
1589 for (transfer_id = 0; transfer_id < LIBUVC_NUM_TRANSFER_BUFS; transfer_id++) {
1590 ret = libusb_submit_transfer(strmh->transfers[transfer_id]);
1591 if (UNLIKELY(ret != UVC_SUCCESS)) {
1592 UVC_DEBUG("libusb_submit_transfer failed");
1597 if (UNLIKELY(ret != UVC_SUCCESS)) {
1598 /** @todo clean up transfers and memory */
1611 /** Begin streaming video from the stream into the callback function.
1612 * @ingroup streaming
1614 * @deprecated The stream type (bulk vs. isochronous) will be determined by the
1615 * type of interface associated with the uvc_stream_ctrl_t parameter, regardless
1616 * of whether the caller requests isochronous streaming. Please switch to
1617 * uvc_stream_start().
1619 * @param strmh UVC stream
1620 * @param cb User callback function. See {uvc_frame_callback_t} for restrictions.
1622 uvc_error_t uvc_stream_start_iso(uvc_stream_handle_t *strmh,
1623 uvc_frame_callback_t *cb, void *user_ptr) {
1624 return uvc_stream_start(strmh, cb, user_ptr, 0);
1628 * @brief User callback runner thread
1629 * @note There should be at most one of these per currently streaming device
1630 * @param arg Device handle
1632 static void *_uvc_user_caller(void *arg) {
1633 uvc_stream_handle_t *strmh = (uvc_stream_handle_t *) arg;
1635 uint32_t last_seq = 0;
1638 pthread_mutex_lock(&strmh->cb_mutex);
1640 for (; strmh->running && (last_seq == strmh->hold_seq) ;) {
1641 pthread_cond_wait(&strmh->cb_cond, &strmh->cb_mutex);
1644 if (UNLIKELY(!strmh->running)) {
1645 pthread_mutex_unlock(&strmh->cb_mutex);
1649 last_seq = strmh->hold_seq;
1650 if (LIKELY(!strmh->hold_bfh_err)) // XXX
1651 _uvc_populate_frame(strmh);
1653 pthread_mutex_unlock(&strmh->cb_mutex);
1655 if (LIKELY(!strmh->hold_bfh_err)) // XXX
1656 strmh->user_cb(&strmh->frame, strmh->user_ptr); // call user callback function
1659 return NULL; // return value ignored
1663 * @brief Populate the fields of a frame to be handed to user code
1664 * must be called with stream cb lock held!
1666 void _uvc_populate_frame(uvc_stream_handle_t *strmh) {
1667 size_t alloc_size = strmh->cur_ctrl.dwMaxVideoFrameSize;
1668 uvc_frame_t *frame = &strmh->frame;
1669 uvc_frame_desc_t *frame_desc;
1671 /** @todo this stuff that hits the main config cache should really happen
1672 * in start() so that only one thread hits these data. all of this stuff
1673 * is going to be reopen_on_change anyway
1676 frame_desc = uvc_find_frame_desc(strmh->devh, strmh->cur_ctrl.bFormatIndex,
1677 strmh->cur_ctrl.bFrameIndex);
1679 frame->frame_format = strmh->frame_format;
1681 frame->width = frame_desc->wWidth;
1682 frame->height = frame_desc->wHeight;
1683 // XXX set actual_bytes to zero when erro bits is on
1684 frame->actual_bytes = LIKELY(!strmh->hold_bfh_err) ? strmh->hold_bytes : 0;
1686 switch (frame->frame_format) {
1687 case UVC_FRAME_FORMAT_YUYV:
1688 frame->step = frame->width * 2;
1690 case UVC_FRAME_FORMAT_MJPEG:
1698 /* copy the image data from the hold buffer to the frame (unnecessary extra buf?) */
1699 if (UNLIKELY(frame->data_bytes < strmh->hold_bytes)) {
1700 frame->data = realloc(frame->data, strmh->hold_bytes); // TODO add error handling when failed realloc
1701 frame->data_bytes = strmh->hold_bytes;
1703 memcpy(frame->data, strmh->holdbuf, strmh->hold_bytes/*frame->data_bytes*/); // XXX
1705 /** @todo set the frame time */
1708 /** Poll for a frame
1709 * @ingroup streaming
1711 * @param devh UVC device
1712 * @param[out] frame Location to store pointer to captured frame (NULL on error)
1713 * @param timeout_us >0: Wait at most N microseconds; 0: Wait indefinitely; -1: return immediately
1715 uvc_error_t uvc_stream_get_frame(uvc_stream_handle_t *strmh,
1716 uvc_frame_t **frame, int32_t timeout_us) {
1722 if (UNLIKELY(!strmh->running))
1723 return UVC_ERROR_INVALID_PARAM;
1725 if (UNLIKELY(strmh->user_cb))
1726 return UVC_ERROR_CALLBACK_EXISTS;
1728 pthread_mutex_lock(&strmh->cb_mutex);
1730 if (strmh->last_polled_seq < strmh->hold_seq) {
1731 _uvc_populate_frame(strmh);
1732 *frame = &strmh->frame;
1733 strmh->last_polled_seq = strmh->hold_seq;
1734 } else if (timeout_us != -1) {
1736 pthread_cond_wait(&strmh->cb_cond, &strmh->cb_mutex);
1738 add_secs = timeout_us / 1000000;
1739 add_nsecs = (timeout_us % 1000000) * 1000;
1743 #if _POSIX_TIMERS > 0
1744 clock_gettime(CLOCK_REALTIME, &ts);
1746 gettimeofday(&tv, NULL);
1747 ts.tv_sec = tv.tv_sec;
1748 ts.tv_nsec = tv.tv_usec * 1000;
1751 ts.tv_sec += add_secs;
1752 ts.tv_nsec += add_nsecs;
1754 pthread_cond_timedwait(&strmh->cb_cond, &strmh->cb_mutex, &ts);
1757 if (LIKELY(strmh->last_polled_seq < strmh->hold_seq)) {
1758 _uvc_populate_frame(strmh);
1759 *frame = &strmh->frame;
1760 strmh->last_polled_seq = strmh->hold_seq;
1768 pthread_mutex_unlock(&strmh->cb_mutex);
1773 /** @brief Stop streaming video
1774 * @ingroup streaming
1776 * Closes all streams, ends threads and cancels pollers
1778 * @param devh UVC device
1780 void uvc_stop_streaming(uvc_device_handle_t *devh) {
1781 uvc_stream_handle_t *strmh, *strmh_tmp;
1784 DL_FOREACH_SAFE(devh->streams, strmh, strmh_tmp)
1786 uvc_stream_close(strmh);
1791 /** @brief Stop stream.
1792 * @ingroup streaming
1794 * Stops stream, ends threads and cancels pollers
1796 * @param devh UVC device
1798 uvc_error_t uvc_stream_stop(uvc_stream_handle_t *strmh) {
1803 if (!strmh) RETURN(UVC_SUCCESS, uvc_error_t);
1805 if (UNLIKELY(!strmh->running)) {
1806 UVC_EXIT(UVC_ERROR_INVALID_PARAM);
1807 RETURN(UVC_ERROR_INVALID_PARAM, uvc_error_t);
1812 pthread_mutex_lock(&strmh->cb_mutex);
1814 for (i = 0; i < LIBUVC_NUM_TRANSFER_BUFS; i++) {
1815 if (strmh->transfers[i]) {
1816 int res = libusb_cancel_transfer(strmh->transfers[i]);
1817 if ((res < 0) && (res != LIBUSB_ERROR_NOT_FOUND)) {
1818 UVC_DEBUG("libusb_cancel_transfer failed");
1819 // XXX originally freed buffers and transfer here
1820 // but this could lead to crash in _uvc_callback
1821 // therefore we comment out these lines
1822 // and free these objects in _uvc_iso_callback when strmh->running is false
1823 /* free(strmh->transfers[i]->buffer);
1824 libusb_free_transfer(strmh->transfers[i]);
1825 strmh->transfers[i] = NULL; */
1830 /* Wait for transfers to complete/cancel */
1832 for (i = 0; i < LIBUVC_NUM_TRANSFER_BUFS; i++) {
1833 if (strmh->transfers[i] != NULL)
1836 if (i == LIBUVC_NUM_TRANSFER_BUFS)
1838 pthread_cond_wait(&strmh->cb_cond, &strmh->cb_mutex);
1840 // Kick the user thread awake
1841 pthread_cond_broadcast(&strmh->cb_cond);
1843 pthread_mutex_unlock(&strmh->cb_mutex);
1845 /** @todo stop the actual stream, camera side? */
1847 if (strmh->user_cb) {
1848 /* wait for the thread to stop (triggered by LIBUSB_TRANSFER_CANCELLED transfer) */
1849 pthread_join(strmh->cb_thread, NULL);
1852 RETURN(UVC_SUCCESS, uvc_error_t);
1855 /** @brief Close stream.
1856 * @ingroup streaming
1858 * Closes stream, frees handle and all streaming resources.
1860 * @param strmh UVC stream handle
1862 void uvc_stream_close(uvc_stream_handle_t *strmh) {
1865 if (!strmh) { UVC_EXIT_VOID(); };
1868 uvc_stream_stop(strmh);
1870 uvc_release_if(strmh->devh, strmh->stream_if->bInterfaceNumber);
1872 if (strmh->frame.data) {
1873 free(strmh->frame.data);
1874 strmh->frame.data = NULL;
1877 if (strmh->outbuf) {
1878 free(strmh->outbuf);
1879 strmh->outbuf = NULL;
1881 if (strmh->holdbuf) {
1882 free(strmh->holdbuf);
1883 strmh->holdbuf = NULL;
1886 pthread_cond_destroy(&strmh->cb_cond);
1887 pthread_mutex_destroy(&strmh->cb_mutex);
1889 DL_DELETE(strmh->devh->streams, strmh);