style(uvc osx) remove useless file
This commit is contained in:
parent
263658834a
commit
c490e09de0
|
@ -137,6 +137,9 @@ elseif(OS_MAC)
|
|||
## set_target_properties(usbBusProber PROPERTIES FRAMEWORK TRUE )
|
||||
## add_library(vvuvckit SHARED ${MAC_VVUVCKIT_SRC_LIST})
|
||||
## set_target_properties(vvuvckit PROPERTIES FRAMEWORK TRUE )
|
||||
## find_package(libuvc REQUIRED)
|
||||
## set(UVC_LIB ${libuvc_LIBRARIES})
|
||||
## include_directories(${libuvc_INCLUDE_DIRS})
|
||||
|
||||
INCLUDE_DIRECTORIES(src/mynteye/uvc/macosx/USBBusProber.framework/Headers)
|
||||
INCLUDE_DIRECTORIES(src/mynteye/uvc/macosx/VVUVCKit.framework/Headers)
|
||||
|
@ -147,11 +150,6 @@ elseif(OS_MAC)
|
|||
|
||||
set(UVC_SRC src/mynteye/uvc/macosx/CameraEngine.cpp src/mynteye/uvc/macosx/AVfoundationCamera.mm src/mynteye/uvc/macosx/uvc-vvuvckit.cc )
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -framework CoreFoundation -framework AVFoundation -framework IOKit -framework AppKit -framework Cocoa -framework CoreMedia -framework CoreData -framework Foundation -framework CoreVideo ${__MACUVCLOG_FLAGS}")
|
||||
|
||||
find_package(libuvc REQUIRED)
|
||||
set(UVC_LIB ${libuvc_LIBRARIES})
|
||||
|
||||
include_directories(${libuvc_INCLUDE_DIRS})
|
||||
elseif(OS_LINUX)
|
||||
set(UVC_SRC src/mynteye/uvc/linux/uvc-v4l2.cc)
|
||||
else()
|
||||
|
|
|
@ -1,490 +0,0 @@
|
|||
/*
|
||||
Copyright (c) 2007-2010, Troy D. Hanson http://uthash.sourceforge.net
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef UTLIST_H
|
||||
#define UTLIST_H
|
||||
|
||||
#define UTLIST_VERSION 1.9.1
|
||||
|
||||
/*
|
||||
* This file contains macros to manipulate singly and doubly-linked lists.
|
||||
*
|
||||
* 1. LL_ macros: singly-linked lists.
|
||||
* 2. DL_ macros: doubly-linked lists.
|
||||
* 3. CDL_ macros: circular doubly-linked lists.
|
||||
*
|
||||
* To use singly-linked lists, your structure must have a "next" pointer.
|
||||
* To use doubly-linked lists, your structure must "prev" and "next" pointers.
|
||||
* Either way, the pointer to the head of the list must be initialized to NULL.
|
||||
*
|
||||
* ----------------.EXAMPLE -------------------------
|
||||
* struct item {
|
||||
* int id;
|
||||
* struct item *prev, *next;
|
||||
* }
|
||||
*
|
||||
* struct item *list = NULL:
|
||||
*
|
||||
* int main() {
|
||||
* struct item *item;
|
||||
* ... allocate and populate item ...
|
||||
* DL_APPEND(list, item);
|
||||
* }
|
||||
* --------------------------------------------------
|
||||
*
|
||||
* For doubly-linked lists, the append and delete macros are O(1)
|
||||
* For singly-linked lists, append and delete are O(n) but prepend is O(1)
|
||||
* The sort macro is O(n log(n)) for all types of single/double/circular lists.
|
||||
*/
|
||||
|
||||
/* These macros use decltype or the earlier __typeof GNU extension.
|
||||
As decltype is only available in newer compilers (VS2010 or gcc 4.3+
|
||||
when compiling c++ code), this code uses whatever method is needed
|
||||
or, for VS2008 where neither is available, uses casting workarounds. */
|
||||
#ifdef _MSC_VER /* MS compiler */
|
||||
#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */
|
||||
#define LDECLTYPE(x) decltype(x)
|
||||
#else /* VS2008 or older (or VS2010 in C mode) */
|
||||
#define NO_DECLTYPE
|
||||
#define LDECLTYPE(x) char*
|
||||
#endif
|
||||
#else /* GNU, Sun and other compilers */
|
||||
#define LDECLTYPE(x) __typeof(x)
|
||||
#endif
|
||||
|
||||
/* for VS2008 we use some workarounds to get around the lack of decltype,
|
||||
* namely, we always reassign our tmp variable to the list head if we need
|
||||
* to dereference its prev/next pointers, and save/restore the real head.*/
|
||||
#ifdef NO_DECLTYPE
|
||||
#define _SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); }
|
||||
#define _NEXT(elt,list) ((char*)((list)->next))
|
||||
#define _NEXTASGN(elt,list,to) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); }
|
||||
#define _PREV(elt,list) ((char*)((list)->prev))
|
||||
#define _PREVASGN(elt,list,to) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); }
|
||||
#define _RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; }
|
||||
#define _CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); }
|
||||
#else
|
||||
#define _SV(elt,list)
|
||||
#define _NEXT(elt,list) ((elt)->next)
|
||||
#define _NEXTASGN(elt,list,to) ((elt)->next)=(to)
|
||||
#define _PREV(elt,list) ((elt)->prev)
|
||||
#define _PREVASGN(elt,list,to) ((elt)->prev)=(to)
|
||||
#define _RS(list)
|
||||
#define _CASTASGN(a,b) (a)=(b)
|
||||
#endif
|
||||
|
||||
/******************************************************************************
|
||||
* The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort *
|
||||
* Unwieldy variable names used here to avoid shadowing passed-in variables. *
|
||||
*****************************************************************************/
|
||||
#define LL_SORT(list, cmp) \
|
||||
do { \
|
||||
LDECLTYPE(list) _ls_p; \
|
||||
LDECLTYPE(list) _ls_q; \
|
||||
LDECLTYPE(list) _ls_e; \
|
||||
LDECLTYPE(list) _ls_tail; \
|
||||
LDECLTYPE(list) _ls_oldhead; \
|
||||
LDECLTYPE(list) _tmp; \
|
||||
int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
|
||||
if (list) { \
|
||||
_ls_insize = 1; \
|
||||
_ls_looping = 1; \
|
||||
while (_ls_looping) { \
|
||||
_CASTASGN(_ls_p,list); \
|
||||
_CASTASGN(_ls_oldhead,list); \
|
||||
list = NULL; \
|
||||
_ls_tail = NULL; \
|
||||
_ls_nmerges = 0; \
|
||||
while (_ls_p) { \
|
||||
_ls_nmerges++; \
|
||||
_ls_q = _ls_p; \
|
||||
_ls_psize = 0; \
|
||||
for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
|
||||
_ls_psize++; \
|
||||
_SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); \
|
||||
if (!_ls_q) break; \
|
||||
} \
|
||||
_ls_qsize = _ls_insize; \
|
||||
while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
|
||||
if (_ls_psize == 0) { \
|
||||
_ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
|
||||
} else if (_ls_qsize == 0 || !_ls_q) { \
|
||||
_ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
|
||||
} else if (cmp(_ls_p,_ls_q) <= 0) { \
|
||||
_ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
|
||||
} else { \
|
||||
_ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
|
||||
} \
|
||||
if (_ls_tail) { \
|
||||
_SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \
|
||||
} else { \
|
||||
_CASTASGN(list,_ls_e); \
|
||||
} \
|
||||
_ls_tail = _ls_e; \
|
||||
} \
|
||||
_ls_p = _ls_q; \
|
||||
} \
|
||||
_SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL); _RS(list); \
|
||||
if (_ls_nmerges <= 1) { \
|
||||
_ls_looping=0; \
|
||||
} \
|
||||
_ls_insize *= 2; \
|
||||
} \
|
||||
} else _tmp=NULL; /* quiet gcc unused variable warning */ \
|
||||
} while (0)
|
||||
|
||||
#define DL_SORT(list, cmp) \
|
||||
do { \
|
||||
LDECLTYPE(list) _ls_p; \
|
||||
LDECLTYPE(list) _ls_q; \
|
||||
LDECLTYPE(list) _ls_e; \
|
||||
LDECLTYPE(list) _ls_tail; \
|
||||
LDECLTYPE(list) _ls_oldhead; \
|
||||
LDECLTYPE(list) _tmp; \
|
||||
int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
|
||||
if (list) { \
|
||||
_ls_insize = 1; \
|
||||
_ls_looping = 1; \
|
||||
while (_ls_looping) { \
|
||||
_CASTASGN(_ls_p,list); \
|
||||
_CASTASGN(_ls_oldhead,list); \
|
||||
list = NULL; \
|
||||
_ls_tail = NULL; \
|
||||
_ls_nmerges = 0; \
|
||||
while (_ls_p) { \
|
||||
_ls_nmerges++; \
|
||||
_ls_q = _ls_p; \
|
||||
_ls_psize = 0; \
|
||||
for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
|
||||
_ls_psize++; \
|
||||
_SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); \
|
||||
if (!_ls_q) break; \
|
||||
} \
|
||||
_ls_qsize = _ls_insize; \
|
||||
while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
|
||||
if (_ls_psize == 0) { \
|
||||
_ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
|
||||
} else if (_ls_qsize == 0 || !_ls_q) { \
|
||||
_ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
|
||||
} else if (cmp(_ls_p,_ls_q) <= 0) { \
|
||||
_ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
|
||||
} else { \
|
||||
_ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
|
||||
} \
|
||||
if (_ls_tail) { \
|
||||
_SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \
|
||||
} else { \
|
||||
_CASTASGN(list,_ls_e); \
|
||||
} \
|
||||
_SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail); _RS(list); \
|
||||
_ls_tail = _ls_e; \
|
||||
} \
|
||||
_ls_p = _ls_q; \
|
||||
} \
|
||||
_CASTASGN(list->prev, _ls_tail); \
|
||||
_SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL); _RS(list); \
|
||||
if (_ls_nmerges <= 1) { \
|
||||
_ls_looping=0; \
|
||||
} \
|
||||
_ls_insize *= 2; \
|
||||
} \
|
||||
} else _tmp=NULL; /* quiet gcc unused variable warning */ \
|
||||
} while (0)
|
||||
|
||||
#define CDL_SORT(list, cmp) \
|
||||
do { \
|
||||
LDECLTYPE(list) _ls_p; \
|
||||
LDECLTYPE(list) _ls_q; \
|
||||
LDECLTYPE(list) _ls_e; \
|
||||
LDECLTYPE(list) _ls_tail; \
|
||||
LDECLTYPE(list) _ls_oldhead; \
|
||||
LDECLTYPE(list) _tmp; \
|
||||
LDECLTYPE(list) _tmp2; \
|
||||
int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
|
||||
if (list) { \
|
||||
_ls_insize = 1; \
|
||||
_ls_looping = 1; \
|
||||
while (_ls_looping) { \
|
||||
_CASTASGN(_ls_p,list); \
|
||||
_CASTASGN(_ls_oldhead,list); \
|
||||
list = NULL; \
|
||||
_ls_tail = NULL; \
|
||||
_ls_nmerges = 0; \
|
||||
while (_ls_p) { \
|
||||
_ls_nmerges++; \
|
||||
_ls_q = _ls_p; \
|
||||
_ls_psize = 0; \
|
||||
for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
|
||||
_ls_psize++; \
|
||||
_SV(_ls_q,list); \
|
||||
if (_NEXT(_ls_q,list) == _ls_oldhead) { \
|
||||
_ls_q = NULL; \
|
||||
} else { \
|
||||
_ls_q = _NEXT(_ls_q,list); \
|
||||
} \
|
||||
_RS(list); \
|
||||
if (!_ls_q) break; \
|
||||
} \
|
||||
_ls_qsize = _ls_insize; \
|
||||
while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
|
||||
if (_ls_psize == 0) { \
|
||||
_ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
|
||||
if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
|
||||
} else if (_ls_qsize == 0 || !_ls_q) { \
|
||||
_ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
|
||||
if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
|
||||
} else if (cmp(_ls_p,_ls_q) <= 0) { \
|
||||
_ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
|
||||
if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
|
||||
} else { \
|
||||
_ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
|
||||
if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
|
||||
} \
|
||||
if (_ls_tail) { \
|
||||
_SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \
|
||||
} else { \
|
||||
_CASTASGN(list,_ls_e); \
|
||||
} \
|
||||
_SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail); _RS(list); \
|
||||
_ls_tail = _ls_e; \
|
||||
} \
|
||||
_ls_p = _ls_q; \
|
||||
} \
|
||||
_CASTASGN(list->prev,_ls_tail); \
|
||||
_CASTASGN(_tmp2,list); \
|
||||
_SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_tmp2); _RS(list); \
|
||||
if (_ls_nmerges <= 1) { \
|
||||
_ls_looping=0; \
|
||||
} \
|
||||
_ls_insize *= 2; \
|
||||
} \
|
||||
} else _tmp=NULL; /* quiet gcc unused variable warning */ \
|
||||
} while (0)
|
||||
|
||||
/******************************************************************************
|
||||
* singly linked list macros (non-circular) *
|
||||
*****************************************************************************/
|
||||
#define LL_PREPEND(head,add) \
|
||||
do { \
|
||||
(add)->next = head; \
|
||||
head = add; \
|
||||
} while (0)
|
||||
|
||||
#define LL_APPEND(head,add) \
|
||||
do { \
|
||||
LDECLTYPE(head) _tmp; \
|
||||
(add)->next=NULL; \
|
||||
if (head) { \
|
||||
_tmp = head; \
|
||||
while (_tmp->next) { _tmp = _tmp->next; } \
|
||||
_tmp->next=(add); \
|
||||
} else { \
|
||||
(head)=(add); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define LL_DELETE(head,del) \
|
||||
do { \
|
||||
LDECLTYPE(head) _tmp; \
|
||||
if ((head) == (del)) { \
|
||||
(head)=(head)->next; \
|
||||
} else { \
|
||||
_tmp = head; \
|
||||
while (_tmp->next && (_tmp->next != (del))) { \
|
||||
_tmp = _tmp->next; \
|
||||
} \
|
||||
if (_tmp->next) { \
|
||||
_tmp->next = ((del)->next); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Here are VS2008 replacements for LL_APPEND and LL_DELETE */
|
||||
#define LL_APPEND_VS2008(head,add) \
|
||||
do { \
|
||||
if (head) { \
|
||||
(add)->next = head; /* use add->next as a temp variable */ \
|
||||
while ((add)->next->next) { (add)->next = (add)->next->next; } \
|
||||
(add)->next->next=(add); \
|
||||
} else { \
|
||||
(head)=(add); \
|
||||
} \
|
||||
(add)->next=NULL; \
|
||||
} while (0)
|
||||
|
||||
#define LL_DELETE_VS2008(head,del) \
|
||||
do { \
|
||||
if ((head) == (del)) { \
|
||||
(head)=(head)->next; \
|
||||
} else { \
|
||||
char *_tmp = (char*)(head); \
|
||||
while (head->next && (head->next != (del))) { \
|
||||
head = head->next; \
|
||||
} \
|
||||
if (head->next) { \
|
||||
head->next = ((del)->next); \
|
||||
} \
|
||||
{ \
|
||||
char **_head_alias = (char**)&(head); \
|
||||
*_head_alias = _tmp; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
#ifdef NO_DECLTYPE
|
||||
#undef LL_APPEND
|
||||
#define LL_APPEND LL_APPEND_VS2008
|
||||
#undef LL_DELETE
|
||||
#define LL_DELETE LL_DELETE_VS2008
|
||||
#endif
|
||||
/* end VS2008 replacements */
|
||||
|
||||
#define LL_FOREACH(head,el) \
|
||||
for(el=head;el;el=el->next)
|
||||
|
||||
#define LL_FOREACH_SAFE(head,el,tmp) \
|
||||
for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
|
||||
|
||||
#define LL_SEARCH_SCALAR(head,out,field,val) \
|
||||
do { \
|
||||
LL_FOREACH(head,out) { \
|
||||
if ((out)->field == (val)) break; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define LL_SEARCH(head,out,elt,cmp) \
|
||||
do { \
|
||||
LL_FOREACH(head,out) { \
|
||||
if ((cmp(out,elt))==0) break; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/******************************************************************************
|
||||
* doubly linked list macros (non-circular) *
|
||||
*****************************************************************************/
|
||||
#define DL_PREPEND(head,add) \
|
||||
do { \
|
||||
(add)->next = head; \
|
||||
if (head) { \
|
||||
(add)->prev = (head)->prev; \
|
||||
(head)->prev = (add); \
|
||||
} else { \
|
||||
(add)->prev = (add); \
|
||||
} \
|
||||
(head) = (add); \
|
||||
} while (0)
|
||||
|
||||
#define DL_APPEND(head,add) \
|
||||
do { \
|
||||
if (head) { \
|
||||
(add)->prev = (head)->prev; \
|
||||
(head)->prev->next = (add); \
|
||||
(head)->prev = (add); \
|
||||
(add)->next = NULL; \
|
||||
} else { \
|
||||
(head)=(add); \
|
||||
(head)->prev = (head); \
|
||||
(head)->next = NULL; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define DL_DELETE(head,del) \
|
||||
do { \
|
||||
if ((del)->prev == (del)) { \
|
||||
(head)=NULL; \
|
||||
} else if ((del)==(head)) { \
|
||||
(del)->next->prev = (del)->prev; \
|
||||
(head) = (del)->next; \
|
||||
} else { \
|
||||
(del)->prev->next = (del)->next; \
|
||||
if ((del)->next) { \
|
||||
(del)->next->prev = (del)->prev; \
|
||||
} else { \
|
||||
(head)->prev = (del)->prev; \
|
||||
} \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
|
||||
#define DL_FOREACH(head,el) \
|
||||
for(el=head;el;el=el->next)
|
||||
|
||||
/* this version is safe for deleting the elements during iteration */
|
||||
#define DL_FOREACH_SAFE(head,el,tmp) \
|
||||
for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
|
||||
|
||||
/* these are identical to their singly-linked list counterparts */
|
||||
#define DL_SEARCH_SCALAR LL_SEARCH_SCALAR
|
||||
#define DL_SEARCH LL_SEARCH
|
||||
|
||||
/******************************************************************************
|
||||
* circular doubly linked list macros *
|
||||
*****************************************************************************/
|
||||
#define CDL_PREPEND(head,add) \
|
||||
do { \
|
||||
if (head) { \
|
||||
(add)->prev = (head)->prev; \
|
||||
(add)->next = (head); \
|
||||
(head)->prev = (add); \
|
||||
(add)->prev->next = (add); \
|
||||
} else { \
|
||||
(add)->prev = (add); \
|
||||
(add)->next = (add); \
|
||||
} \
|
||||
(head)=(add); \
|
||||
} while (0)
|
||||
|
||||
#define CDL_DELETE(head,del) \
|
||||
do { \
|
||||
if ( ((head)==(del)) && ((head)->next == (head))) { \
|
||||
(head) = 0L; \
|
||||
} else { \
|
||||
(del)->next->prev = (del)->prev; \
|
||||
(del)->prev->next = (del)->next; \
|
||||
if ((del) == (head)) (head)=(del)->next; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define CDL_FOREACH(head,el) \
|
||||
for(el=head;el;el=(el->next==head ? 0L : el->next))
|
||||
|
||||
#define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \
|
||||
for((el)=(head), ((tmp1)=(head)?((head)->prev):NULL); \
|
||||
(el) && ((tmp2)=(el)->next, 1); \
|
||||
((el) = (((el)==(tmp1)) ? 0L : (tmp2))))
|
||||
|
||||
#define CDL_SEARCH_SCALAR(head,out,field,val) \
|
||||
do { \
|
||||
CDL_FOREACH(head,out) { \
|
||||
if ((out)->field == (val)) break; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define CDL_SEARCH(head,out,elt,cmp) \
|
||||
do { \
|
||||
CDL_FOREACH(head,out) { \
|
||||
if ((cmp(out,elt))==0) break; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#endif /* UTLIST_H */
|
||||
|
|
@ -1,429 +0,0 @@
|
|||
// Copyright 2018 Slightech Co., Ltd. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include "mynteye/logger.h"
|
||||
#include "mynteye/uvc/uvc.h"
|
||||
#include "libuvc/libuvc.h"
|
||||
|
||||
#include "mynteye/uvc/macosx/uvc_osx_internal.h"
|
||||
|
||||
// #define ENABLE_DEBUG_SPAM
|
||||
|
||||
MYNTEYE_BEGIN_NAMESPACE
|
||||
|
||||
namespace uvc {
|
||||
|
||||
static void check(const char *call, uvc_error_t status) {
|
||||
LOG_IF(FATAL, status < 0)
|
||||
<< call << "(...) returned " << uvc_strerror(status);
|
||||
}
|
||||
|
||||
#define CALL_UVC_WITHOUT_CHECK(name, ...) name(__VA_ARGS__)
|
||||
#define CALL_UVC(name, ...) check(#name, name(__VA_ARGS__))
|
||||
|
||||
struct context {
|
||||
uvc_context_t *ctx;
|
||||
|
||||
context() : ctx(nullptr) {
|
||||
VLOG(2) << __func__;
|
||||
CALL_UVC(uvc_init, &ctx, nullptr);
|
||||
}
|
||||
|
||||
~context() {
|
||||
VLOG(2) << __func__;
|
||||
if (ctx)
|
||||
uvc_exit(ctx);
|
||||
}
|
||||
};
|
||||
|
||||
/** UVC request code (A.8) */
|
||||
enum uvc_req_code {
|
||||
UVC_RC_UNDEFINED = 0x00,
|
||||
UVC_SET_CUR = 0x01,
|
||||
UVC_GET_CUR = 0x81,
|
||||
UVC_GET_MIN = 0x82,
|
||||
UVC_GET_MAX = 0x83,
|
||||
UVC_GET_RES = 0x84,
|
||||
UVC_GET_LEN = 0x85,
|
||||
UVC_GET_INFO = 0x86,
|
||||
UVC_GET_DEF = 0x87,
|
||||
UVC_REQ_TYPE_GET = 0xa1,
|
||||
UVC_REQ_TYPE_SET = 0x21
|
||||
};
|
||||
|
||||
struct device;
|
||||
|
||||
struct device {
|
||||
const std::shared_ptr<context> parent;
|
||||
|
||||
uvc_device_t *uvcdevice = nullptr;
|
||||
uvc_device_handle_t *handle = nullptr;
|
||||
/** Serial number (null if unavailable) */
|
||||
std::string serialNumber = "";
|
||||
/** Device-reported manufacturer name (or null) */
|
||||
std::string manufacturer = "";
|
||||
/** Device-reporter product name (or null) */
|
||||
std::string product = "";
|
||||
uvc_device_info_t info;
|
||||
int width, height, format, fps;
|
||||
int vid, pid;
|
||||
video_channel_callback callback = nullptr;
|
||||
static std::vector <struct device*> s_devices;
|
||||
|
||||
std::mutex _devices_mutex;
|
||||
|
||||
device(std::shared_ptr<context> parent, uvc_device_t *uvcdevice)
|
||||
: parent(parent), uvcdevice(uvcdevice) {
|
||||
VLOG(2) << __func__;
|
||||
open();
|
||||
|
||||
uvc_device_descriptor_t *desc;
|
||||
CALL_UVC(uvc_get_device_descriptor, uvcdevice, &desc);
|
||||
|
||||
serialNumber = std::string(desc->serialNumber);
|
||||
manufacturer = std::string(desc->manufacturer);
|
||||
product = std::string(desc->product);
|
||||
|
||||
vid = desc->idVendor;
|
||||
pid = desc->idProduct;
|
||||
uvc_free_device_descriptor(desc);
|
||||
std::lock_guard<std::mutex> lock(_devices_mutex);
|
||||
s_devices.push_back(this);
|
||||
}
|
||||
|
||||
~device() {
|
||||
VLOG(2) << __func__;
|
||||
if (handle)
|
||||
uvc_close(handle);
|
||||
if (uvcdevice)
|
||||
uvc_unref_device(uvcdevice);
|
||||
std::lock_guard<std::mutex> lock(_devices_mutex);
|
||||
for(unsigned long i = 0 ; i < s_devices.size() ; i++) {
|
||||
if(this == s_devices[i]) {
|
||||
s_devices.erase(s_devices.begin()+i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void open() {
|
||||
if (!handle)
|
||||
CALL_UVC(uvc_open, uvcdevice, &handle);
|
||||
}
|
||||
|
||||
void set_format(
|
||||
int width, int height, int format, int fps,
|
||||
video_channel_callback callback) {
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
this->format = format;
|
||||
this->fps = fps;
|
||||
this->callback = callback;
|
||||
}
|
||||
|
||||
static void uvc_frame_callback (struct uvc_frame *frame, void *user_ptr)
|
||||
{
|
||||
for(unsigned long i = 0 ; i < s_devices.size() ; i++) {
|
||||
if(user_ptr == (void*)s_devices[i]) {
|
||||
printf("bingo\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// int32_t get_data_usb( uvc_req_code action, int control, int unit) const {
|
||||
// unsigned char buffer[4];
|
||||
|
||||
// int status = libusb_control_transfer(handle->usb_devh,
|
||||
// UVC_REQ_TYPE_GET,
|
||||
// action,
|
||||
// control << 8,
|
||||
// unit << 8 | (1),// _interface
|
||||
// buffer,
|
||||
// sizeof(int32_t), 0);
|
||||
// MYNTEYE_UNUSED(status);
|
||||
// if (status < 0) throw std::runtime_error(
|
||||
// to_string() << "libusb_control_transfer(...) returned "
|
||||
// << libusb_error_name(status));
|
||||
|
||||
// if (status != sizeof(int32_t))
|
||||
// throw std::runtime_error("insufficient data read from USB");
|
||||
|
||||
// return DW_TO_INT(buffer);
|
||||
// }
|
||||
|
||||
// void set_data_usb( uvc_req_code action, int control, int unit, int value) const {
|
||||
// unsigned char buffer[4];
|
||||
|
||||
// INT_TO_DW(value, buffer);
|
||||
|
||||
// int status = libusb_control_transfer(handle->usb_devh,
|
||||
// UVC_REQ_TYPE_SET,
|
||||
// action,
|
||||
// control << 8,
|
||||
// unit << 8 | (1),// _interface
|
||||
// buffer,
|
||||
// sizeof(int32_t), 0);
|
||||
|
||||
// if (status < 0) throw std::runtime_error(
|
||||
// to_string() << "libusb_control_transfer(...) returned "
|
||||
// << libusb_error_name(status));
|
||||
|
||||
// if (status != sizeof(int32_t))
|
||||
// throw std::runtime_error("insufficient data writen to USB");
|
||||
// }
|
||||
};
|
||||
|
||||
std::vector <struct device*> device::s_devices;
|
||||
|
||||
std::shared_ptr<context> create_context() {
|
||||
return std::make_shared<context>();
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<device>> query_devices(
|
||||
std::shared_ptr<context> context) {
|
||||
std::vector<std::shared_ptr<device>> devices;
|
||||
|
||||
uvc_device_t **list;
|
||||
CALL_UVC(uvc_get_device_list, context->ctx, &list);
|
||||
for (auto it = list; *it; ++it) {
|
||||
try {
|
||||
auto dev = std::make_shared<device>(context, *it);
|
||||
devices.push_back(dev);
|
||||
} catch (std::runtime_error &e) {
|
||||
LOG(WARNING) << "usb:" << static_cast<int>(uvc_get_bus_number(*it)) << ':'
|
||||
<< static_cast<int>(uvc_get_device_address(*it)) << ": "
|
||||
<< e.what();
|
||||
}
|
||||
}
|
||||
uvc_free_device_list(list, 1);
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
||||
int get_vendor_id(const device &device) {
|
||||
return device.vid;
|
||||
}
|
||||
|
||||
int get_product_id(const device &device) {
|
||||
return device.pid;
|
||||
}
|
||||
|
||||
std::string get_name(const device &device) {
|
||||
return device.serialNumber + "/" + device.manufacturer + "/" + device.product;
|
||||
}
|
||||
|
||||
std::string get_video_name(const device &device) {
|
||||
return device.serialNumber + "/" + device.manufacturer + "/" + device.product;
|
||||
}
|
||||
|
||||
// class uvc_device
|
||||
// {
|
||||
// public:
|
||||
// virtual void probe_and_commit(stream_profile profile, frame_callback callback, int buffers = DEFAULT_V4L2_FRAME_BUFFERS) = 0;
|
||||
// virtual void stream_on(std::function<void(const notification& n)> error_handler = [](const notification& n){}) = 0;
|
||||
// virtual void start_callbacks() = 0;
|
||||
// virtual void stop_callbacks() = 0;
|
||||
// virtual void close(stream_profile profile) = 0;
|
||||
|
||||
// virtual void set_power_state(power_state state) = 0;
|
||||
// virtual power_state get_power_state() const = 0;
|
||||
|
||||
// virtual void init_xu(const extension_unit& xu) = 0;
|
||||
// virtual bool set_xu(const extension_unit& xu, uint8_t ctrl, const uint8_t* data, int len) = 0;
|
||||
// virtual bool get_xu(const extension_unit& xu, uint8_t ctrl, uint8_t* data, int len) const = 0;
|
||||
// virtual control_range get_xu_range(const extension_unit& xu, uint8_t ctrl, int len) const = 0;
|
||||
|
||||
// virtual bool get_pu(rs2_option opt, int32_t& value) const = 0;
|
||||
// virtual bool set_pu(rs2_option opt, int32_t value) = 0;
|
||||
// virtual control_range get_pu_range(rs2_option opt) const = 0;
|
||||
|
||||
// virtual std::vector<stream_profile> get_profiles() const = 0;
|
||||
|
||||
// virtual void lock() const = 0;
|
||||
// virtual void unlock() const = 0;
|
||||
|
||||
// virtual std::string get_device_location() const = 0;
|
||||
// virtual usb_spec get_usb_specification() const = 0;
|
||||
|
||||
// virtual ~uvc_device() = default;
|
||||
|
||||
// protected:
|
||||
// std::function<void(const notification& n)> _error_handler;
|
||||
// };
|
||||
|
||||
bool pu_control_range(
|
||||
const device &device, Option option, int32_t *min, int32_t *max,
|
||||
int32_t *def) {
|
||||
// TODO(JohnZhao)
|
||||
MYNTEYE_UNUSED(device)
|
||||
MYNTEYE_UNUSED(option)
|
||||
MYNTEYE_UNUSED(min)
|
||||
MYNTEYE_UNUSED(max)
|
||||
MYNTEYE_UNUSED(def)
|
||||
// device.uvcdevice -> set_pu(option, *def);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool pu_control_query(
|
||||
const device &device, Option option, pu_query query, int32_t *value) {
|
||||
// TODO(JohnZhao)
|
||||
MYNTEYE_UNUSED(device)
|
||||
MYNTEYE_UNUSED(option)
|
||||
MYNTEYE_UNUSED(query)
|
||||
MYNTEYE_UNUSED(value)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool xu_control_range(
|
||||
const device &device, const xu &xu, uint8_t selector, uint8_t id, int32_t *min,
|
||||
int32_t *max, int32_t *def) {
|
||||
// TODO(JohnZhao)
|
||||
MYNTEYE_UNUSED(device)
|
||||
MYNTEYE_UNUSED(xu)
|
||||
MYNTEYE_UNUSED(selector)
|
||||
MYNTEYE_UNUSED(id)
|
||||
MYNTEYE_UNUSED(min)
|
||||
MYNTEYE_UNUSED(max)
|
||||
MYNTEYE_UNUSED(def)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool xu_control_query(
|
||||
const device &device, const xu &xu, uint8_t selector, xu_query query,
|
||||
uint16_t size, uint8_t *data) {
|
||||
// TODO(JohnZhao)
|
||||
MYNTEYE_UNUSED(device)
|
||||
MYNTEYE_UNUSED(xu)
|
||||
MYNTEYE_UNUSED(selector)
|
||||
MYNTEYE_UNUSED(query)
|
||||
MYNTEYE_UNUSED(size)
|
||||
MYNTEYE_UNUSED(data)
|
||||
return false;
|
||||
}
|
||||
|
||||
void set_device_mode(
|
||||
device &device, int width, int height, int format, int fps, // NOLINT
|
||||
video_channel_callback callback) {
|
||||
device.set_format(width, height, format, fps, callback);
|
||||
}
|
||||
|
||||
void start_streaming(device &device, int num_transfer_bufs) { // NOLINT
|
||||
// MYNTEYE_UNUSED(device)
|
||||
// MYNTEYE_UNUSED(num_transfer_bufs)
|
||||
|
||||
// typedef struct uvc_stream_ctrl {
|
||||
// uint16_t bmHint;
|
||||
// uint8_t bFormatIndex;
|
||||
// uint8_t bFrameIndex;
|
||||
// uint32_t dwFrameInterval;
|
||||
// uint16_t wKeyFrameRate;
|
||||
// uint16_t wPFrameRate;
|
||||
// uint16_t wCompQuality;
|
||||
// uint16_t wCompWindowSize;
|
||||
// uint16_t wDelay;
|
||||
// uint32_t dwMaxVideoFrameSize;
|
||||
// uint32_t dwMaxPayloadTransferSize;
|
||||
// uint32_t dwClockFrequency;
|
||||
// uint8_t bmFramingInfo;
|
||||
// uint8_t bPreferredVersion;
|
||||
// uint8_t bMinVersion;
|
||||
// uint8_t bMaxVersion;
|
||||
// uint8_t bInterfaceNumber;
|
||||
// } uvc_stream_ctrl_t;
|
||||
|
||||
// uvc_error_t uvc_get_stream_ctrl_format_size(
|
||||
// uvc_device_handle_t *devh,
|
||||
// uvc_stream_ctrl_t *ctrl,
|
||||
// enum uvc_frame_format format,
|
||||
// int width, int height,
|
||||
// int fps
|
||||
// );
|
||||
|
||||
uvc_stream_ctrl_t ctrl_st = {};
|
||||
|
||||
/** Color coding of stream, transport-independent
|
||||
* @ingroup streaming
|
||||
*/
|
||||
// enum uvc_frame_format {
|
||||
// UVC_FRAME_FORMAT_UNKNOWN = 0,
|
||||
// /** Any supported format */
|
||||
// UVC_FRAME_FORMAT_ANY = 0,
|
||||
// UVC_FRAME_FORMAT_UNCOMPRESSED,
|
||||
// UVC_FRAME_FORMAT_COMPRESSED,
|
||||
// /** YUYV/YUV2/YUV422: YUV encoding with one luminance value per pixel and
|
||||
// * one UV (chrominance) pair for every two pixels.
|
||||
// */
|
||||
// UVC_FRAME_FORMAT_YUYV,
|
||||
// UVC_FRAME_FORMAT_UYVY,
|
||||
// /** 24-bit RGB */
|
||||
// UVC_FRAME_FORMAT_RGB,
|
||||
// UVC_FRAME_FORMAT_BGR,
|
||||
// /** Motion-JPEG (or JPEG) encoded images */
|
||||
// UVC_FRAME_FORMAT_MJPEG,
|
||||
// /** Greyscale images */
|
||||
// UVC_FRAME_FORMAT_GRAY8,
|
||||
// UVC_FRAME_FORMAT_GRAY16,
|
||||
// /* Raw colour mosaic images */
|
||||
// UVC_FRAME_FORMAT_BY8,
|
||||
// UVC_FRAME_FORMAT_BA81,
|
||||
// UVC_FRAME_FORMAT_SGRBG8,
|
||||
// UVC_FRAME_FORMAT_SGBRG8,
|
||||
// UVC_FRAME_FORMAT_SRGGB8,
|
||||
// UVC_FRAME_FORMAT_SBGGR8,
|
||||
// /** Number of formats understood */
|
||||
// UVC_FRAME_FORMAT_COUNT,
|
||||
// };
|
||||
CALL_UVC(uvc_get_stream_ctrl_format_size,
|
||||
device.handle,
|
||||
&ctrl_st,
|
||||
UVC_FRAME_FORMAT_ANY, // UVC_FRAME_FORMAT_YUYV, //(enum uvc_frame_format)device.format,
|
||||
device.width,
|
||||
device.height,
|
||||
device.fps);
|
||||
|
||||
/** A callback function to handle incoming assembled UVC frames
|
||||
* @ingroup streaming
|
||||
*/
|
||||
// typedef void(uvc_frame_callback_t)(struct uvc_frame *frame, void *user_ptr);
|
||||
// uvc_frame_callback_t *cb = nullptr;
|
||||
|
||||
CALL_UVC(uvc_start_streaming,
|
||||
device.handle,
|
||||
&ctrl_st,
|
||||
device::uvc_frame_callback,
|
||||
&device,
|
||||
num_transfer_bufs);
|
||||
|
||||
printf("begin\n");
|
||||
|
||||
// uvc_error_t uvc_start_streaming(
|
||||
// uvc_device_handle_t *devh,
|
||||
// uvc_stream_ctrl_t *ctrl,
|
||||
// uvc_frame_callback_t *cb,
|
||||
// void *user_ptr,
|
||||
// uint8_t flags);
|
||||
}
|
||||
|
||||
void stop_streaming(device &device) { // NOLINT
|
||||
// MYNTEYE_UNUSED(device)
|
||||
|
||||
CALL_UVC_WITHOUT_CHECK(uvc_stop_streaming, device.handle);
|
||||
}
|
||||
|
||||
} // namespace uvc
|
||||
|
||||
MYNTEYE_END_NAMESPACE
|
|
@ -168,6 +168,7 @@ struct device : public AVfoundationCamera{
|
|||
}
|
||||
}
|
||||
pause_ = true;
|
||||
teardown();
|
||||
}
|
||||
|
||||
void open() {
|
||||
|
@ -187,6 +188,7 @@ struct device : public AVfoundationCamera{
|
|||
if (!is_capturing)
|
||||
return;
|
||||
is_capturing = false;
|
||||
stopCamera();
|
||||
}
|
||||
|
||||
std::string get_name() const {
|
||||
|
@ -257,6 +259,12 @@ struct device : public AVfoundationCamera{
|
|||
}
|
||||
}
|
||||
|
||||
void teardown() {
|
||||
pause_ = true;
|
||||
stopCamera();
|
||||
closeCamera();
|
||||
}
|
||||
|
||||
// void reset_options_to_default() {
|
||||
// setCameraSetting(BRIGHTNESS, 120);
|
||||
// setCameraSetting(CONTRAST, 127);
|
||||
|
@ -310,6 +318,7 @@ MYNTEYE_API bool pu_control_range(
|
|||
MYNTEYE_UNUSED(option);
|
||||
MYNTEYE_UNUSED(min);
|
||||
MYNTEYE_UNUSED(max);
|
||||
return true;
|
||||
}
|
||||
MYNTEYE_API bool pu_control_query(
|
||||
const device &device, Option option, pu_query query, int32_t *value) {
|
||||
|
@ -317,6 +326,7 @@ MYNTEYE_API bool pu_control_query(
|
|||
MYNTEYE_UNUSED(option);
|
||||
MYNTEYE_UNUSED(query);
|
||||
MYNTEYE_UNUSED(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Access XU (Extension Unit) controls
|
||||
|
@ -326,6 +336,7 @@ MYNTEYE_API bool xu_control_range(
|
|||
int32_t * /*min*/, int32_t * /*max*/, int32_t * /*def*/) {
|
||||
// not supported on osx
|
||||
LOG(WARNING) << __func__ << " failed: this API is not supported on osx";
|
||||
return false;
|
||||
}
|
||||
MYNTEYE_API bool xu_control_query( // XU_QUERY_SET, XU_QUERY_GET
|
||||
const device &/*device*/, const xu &/*xu*/,
|
||||
|
@ -333,6 +344,7 @@ MYNTEYE_API bool xu_control_query( // XU_QUERY_SET, XU_QUERY_GET
|
|||
uint16_t /*size*/, uint8_t * /*data*/) {
|
||||
// not supported on osx
|
||||
LOG(WARNING) << __func__ << " failed: this API is not supported on osx";
|
||||
return false;
|
||||
}
|
||||
|
||||
MYNTEYE_API void set_device_mode(
|
||||
|
|
|
@ -1,326 +0,0 @@
|
|||
/** @file libuvc_internal.h
|
||||
* @brief Implementation-specific UVC constants and structures.
|
||||
* @cond include_hidden
|
||||
*/
|
||||
#ifndef UVC_OSX_INTERNAL_H
|
||||
#define UVC_OSX_INTERNAL_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <atomic>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <signal.h>
|
||||
#include "mynteye/uvc/macosx/utlist_osx.h"
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
#include <libusb-1.0/libusb.h>
|
||||
|
||||
/** Converts an unaligned four-byte little-endian integer into an int32 */
|
||||
#define DW_TO_INT(p) ((p)[0] | ((p)[1] << 8) | ((p)[2] << 16) | ((p)[3] << 24))
|
||||
/** Converts an unaligned two-byte little-endian integer into an int16 */
|
||||
#define SW_TO_SHORT(p) ((p)[0] | ((p)[1] << 8))
|
||||
/** Converts an unaligned eight-byte little-endian integer into an int64 */
|
||||
#define QW_TO_QUAD(p) ((p)[0] | ((p)[1] << 8) | ((p)[2] << 16) | ((p)[3] << 24) | \
|
||||
((p)[4] << 32) |((p)[5] << 40) |((p)[6] << 48) |((p)[7] << 56))
|
||||
|
||||
/** Converts an int16 into an unaligned two-byte little-endian integer */
|
||||
#define SHORT_TO_SW(s, p) \
|
||||
(p)[0] = (s); \
|
||||
(p)[1] = (s) >> 8;
|
||||
/** Converts an int32 into an unaligned four-byte little-endian integer */
|
||||
#define INT_TO_DW(i, p) \
|
||||
(p)[0] = (i); \
|
||||
(p)[1] = (i) >> 8; \
|
||||
(p)[2] = (i) >> 16; \
|
||||
(p)[3] = (i) >> 24;
|
||||
|
||||
/** Converts an int64 into an unaligned eight-byte little-endian integer */
|
||||
#define QUAD_TO_QW(i, p) \
|
||||
(p)[0] = (i); \
|
||||
(p)[1] = (i) >> 8; \
|
||||
(p)[2] = (i) >> 16; \
|
||||
(p)[3] = (i) >> 24; \
|
||||
(p)[4] = (i) >> 32; \
|
||||
(p)[5] = (i) >> 40; \
|
||||
(p)[6] = (i) >> 48; \
|
||||
(p)[7] = (i) >> 56; \
|
||||
|
||||
/** Selects the nth item in a doubly linked list. n=-1 selects the last item. */
|
||||
#define DL_NTH(head, out, n) \
|
||||
do { \
|
||||
int dl_nth_i = 0; \
|
||||
LDECLTYPE(head) dl_nth_p = (head); \
|
||||
if ((n) < 0) { \
|
||||
while (dl_nth_p && dl_nth_i > (n)) { \
|
||||
dl_nth_p = dl_nth_p->prev; \
|
||||
dl_nth_i--; \
|
||||
} \
|
||||
} else { \
|
||||
while (dl_nth_p && dl_nth_i < (n)) { \
|
||||
dl_nth_p = dl_nth_p->next; \
|
||||
dl_nth_i++; \
|
||||
} \
|
||||
} \
|
||||
(out) = dl_nth_p; \
|
||||
} while (0);
|
||||
|
||||
#ifdef UVC_DEBUGGING
|
||||
#include <libgen.h>
|
||||
#define UVC_DEBUG(format, ...) fprintf(stderr, "[%s:%d/%s] " format "\n", basename(__FILE__), __LINE__, __FUNCTION__, ##__VA_ARGS__)
|
||||
#define UVC_ENTER() fprintf(stderr, "[%s:%d] begin %s\n", basename(__FILE__), __LINE__, __FUNCTION__)
|
||||
#define UVC_EXIT(code) fprintf(stderr, "[%s:%d] end %s (%d)\n", basename(__FILE__), __LINE__, __FUNCTION__, code)
|
||||
#define UVC_EXIT_VOID() fprintf(stderr, "[%s:%d] end %s\n", basename(__FILE__), __LINE__, __FUNCTION__)
|
||||
#else
|
||||
#define UVC_DEBUG(format, ...)
|
||||
#define UVC_ENTER()
|
||||
#define UVC_EXIT_VOID()
|
||||
#define UVC_EXIT(code)
|
||||
#endif
|
||||
|
||||
/* http://stackoverflow.com/questions/19452971/array-size-macro-that-rejects-pointers */
|
||||
#define IS_INDEXABLE(arg) (sizeof(arg[0]))
|
||||
#define IS_ARRAY(arg) (IS_INDEXABLE(arg) && (((void *) &arg) == ((void *) arg)))
|
||||
#define ARRAYSIZE(arr) (sizeof(arr) / (IS_ARRAY(arr) ? sizeof(arr[0]) : 0))
|
||||
|
||||
/** Video interface subclass code (A.2) */
|
||||
enum uvc_int_subclass_code {
|
||||
UVC_SC_UNDEFINED = 0x00,
|
||||
UVC_SC_VIDEOCONTROL = 0x01,
|
||||
UVC_SC_VIDEOSTREAMING = 0x02,
|
||||
UVC_SC_VIDEO_INTERFACE_COLLECTION = 0x03
|
||||
};
|
||||
|
||||
/** Video interface protocol code (A.3) */
|
||||
enum uvc_int_proto_code {
|
||||
UVC_PC_PROTOCOL_UNDEFINED = 0x00
|
||||
};
|
||||
|
||||
/** VideoControl interface descriptor subtype (A.5) */
|
||||
enum uvc_vc_desc_subtype {
|
||||
UVC_VC_DESCRIPTOR_UNDEFINED = 0x00,
|
||||
UVC_VC_HEADER = 0x01,
|
||||
UVC_VC_INPUT_TERMINAL = 0x02,
|
||||
UVC_VC_OUTPUT_TERMINAL = 0x03,
|
||||
UVC_VC_SELECTOR_UNIT = 0x04,
|
||||
UVC_VC_PROCESSING_UNIT = 0x05,
|
||||
UVC_VC_EXTENSION_UNIT = 0x06
|
||||
};
|
||||
|
||||
/** UVC endpoint descriptor subtype (A.7) */
|
||||
enum uvc_ep_desc_subtype {
|
||||
UVC_EP_UNDEFINED = 0x00,
|
||||
UVC_EP_GENERAL = 0x01,
|
||||
UVC_EP_ENDPOINT = 0x02,
|
||||
UVC_EP_INTERRUPT = 0x03
|
||||
};
|
||||
|
||||
/** VideoControl interface control selector (A.9.1) */
|
||||
enum uvc_vc_ctrl_selector {
|
||||
UVC_VC_CONTROL_UNDEFINED = 0x00,
|
||||
UVC_VC_VIDEO_POWER_MODE_CONTROL = 0x01,
|
||||
UVC_VC_REQUEST_ERROR_CODE_CONTROL = 0x02
|
||||
};
|
||||
|
||||
/** Terminal control selector (A.9.2) */
|
||||
enum uvc_term_ctrl_selector {
|
||||
UVC_TE_CONTROL_UNDEFINED = 0x00
|
||||
};
|
||||
|
||||
/** Selector unit control selector (A.9.3) */
|
||||
enum uvc_su_ctrl_selector {
|
||||
UVC_SU_CONTROL_UNDEFINED = 0x00,
|
||||
UVC_SU_INPUT_SELECT_CONTROL = 0x01
|
||||
};
|
||||
|
||||
/** Extension unit control selector (A.9.6) */
|
||||
enum uvc_xu_ctrl_selector {
|
||||
UVC_XU_CONTROL_UNDEFINED = 0x00
|
||||
};
|
||||
|
||||
/** VideoStreaming interface control selector (A.9.7) */
|
||||
enum uvc_vs_ctrl_selector {
|
||||
UVC_VS_CONTROL_UNDEFINED = 0x00,
|
||||
UVC_VS_PROBE_CONTROL = 0x01,
|
||||
UVC_VS_COMMIT_CONTROL = 0x02,
|
||||
UVC_VS_STILL_PROBE_CONTROL = 0x03,
|
||||
UVC_VS_STILL_COMMIT_CONTROL = 0x04,
|
||||
UVC_VS_STILL_IMAGE_TRIGGER_CONTROL = 0x05,
|
||||
UVC_VS_STREAM_ERROR_CODE_CONTROL = 0x06,
|
||||
UVC_VS_GENERATE_KEY_FRAME_CONTROL = 0x07,
|
||||
UVC_VS_UPDATE_FRAME_SEGMENT_CONTROL = 0x08,
|
||||
UVC_VS_SYNC_DELAY_CONTROL = 0x09
|
||||
};
|
||||
|
||||
/** Status packet type (2.4.2.2) */
|
||||
enum uvc_status_type {
|
||||
UVC_STATUS_TYPE_CONTROL = 1,
|
||||
UVC_STATUS_TYPE_STREAMING = 2
|
||||
};
|
||||
|
||||
/** Payload header flags (2.4.3.3) */
|
||||
#define UVC_STREAM_EOH (1 << 7)
|
||||
#define UVC_STREAM_ERR (1 << 6)
|
||||
#define UVC_STREAM_STI (1 << 5)
|
||||
#define UVC_STREAM_RES (1 << 4)
|
||||
#define UVC_STREAM_SCR (1 << 3)
|
||||
#define UVC_STREAM_PTS (1 << 2)
|
||||
#define UVC_STREAM_EOF (1 << 1)
|
||||
#define UVC_STREAM_FID (1 << 0)
|
||||
|
||||
/** Control capabilities (4.1.2) */
|
||||
#define UVC_CONTROL_CAP_GET (1 << 0)
|
||||
#define UVC_CONTROL_CAP_SET (1 << 1)
|
||||
#define UVC_CONTROL_CAP_DISABLED (1 << 2)
|
||||
#define UVC_CONTROL_CAP_AUTOUPDATE (1 << 3)
|
||||
#define UVC_CONTROL_CAP_ASYNCHRONOUS (1 << 4)
|
||||
|
||||
struct uvc_streaming_interface;
|
||||
struct uvc_device_info;
|
||||
|
||||
/** VideoStream interface */
|
||||
typedef struct uvc_streaming_interface {
|
||||
struct uvc_device_info *parent;
|
||||
struct uvc_streaming_interface *prev, *next;
|
||||
/** Interface number */
|
||||
uint8_t bInterfaceNumber;
|
||||
/** Video formats that this interface provides */
|
||||
struct uvc_format_desc *format_descs;
|
||||
/** USB endpoint to use when communicating with this interface */
|
||||
uint8_t bEndpointAddress;
|
||||
uint8_t bTerminalLink;
|
||||
} uvc_streaming_interface_t;
|
||||
|
||||
/** VideoControl interface */
|
||||
typedef struct uvc_control_interface {
|
||||
struct uvc_device_info *parent;
|
||||
struct uvc_input_terminal *input_term_descs;
|
||||
// struct uvc_output_terminal *output_term_descs;
|
||||
struct uvc_selector_unit *selector_unit_descs;
|
||||
struct uvc_processing_unit *processing_unit_descs;
|
||||
struct uvc_extension_unit *extension_unit_descs;
|
||||
uint16_t bcdUVC;
|
||||
uint32_t dwClockFrequency;
|
||||
uint8_t bEndpointAddress;
|
||||
/** Interface number */
|
||||
uint8_t bInterfaceNumber;
|
||||
} uvc_control_interface_t;
|
||||
|
||||
struct uvc_stream_ctrl;
|
||||
|
||||
struct uvc_device {
|
||||
struct uvc_context *ctx;
|
||||
int ref;
|
||||
libusb_device *usb_dev;
|
||||
int interface;
|
||||
};
|
||||
|
||||
typedef struct uvc_device_info {
|
||||
/** Configuration descriptor for USB device */
|
||||
struct libusb_config_descriptor *config;
|
||||
/** VideoControl interface provided by device */
|
||||
uvc_control_interface_t ctrl_if;
|
||||
/** VideoStreaming interfaces on the device */
|
||||
uvc_streaming_interface_t *stream_ifs;
|
||||
/** Store the interface for multiple UVCs on a single VID/PID device (Intel RealSense, VF200, e.g) */
|
||||
int camera_number;
|
||||
} uvc_device_info_t;
|
||||
|
||||
/*
|
||||
set a high number of transfer buffers. This uses a lot of ram, but
|
||||
avoids problems with scheduling delays on slow boards causing missed
|
||||
transfers. A better approach may be to make the transfer thread FIFO
|
||||
scheduled (if we have root).
|
||||
We could/should change this to allow reduce it to, say, 5 by default
|
||||
and then allow the user to change the number of buffers as required.
|
||||
*/
|
||||
#define LIBUVC_NUM_TRANSFER_BUFS 1
|
||||
|
||||
#define LIBUVC_XFER_BUF_SIZE ( 16 * 1024 * 1024 )
|
||||
|
||||
struct uvc_stream_handle {
|
||||
struct uvc_device_handle *devh;
|
||||
struct uvc_stream_handle *prev, *next;
|
||||
struct uvc_streaming_interface *stream_if;
|
||||
|
||||
/** if true, stream is running (streaming video to host) */
|
||||
std::atomic<uint8_t> running;
|
||||
/** Current control block */
|
||||
struct uvc_stream_ctrl cur_ctrl;
|
||||
|
||||
/* listeners may only access hold*, and only when holding a
|
||||
* lock on cb_mutex (probably signaled with cb_cond) */
|
||||
uint8_t fid;
|
||||
uint32_t seq, hold_seq;
|
||||
uint32_t pts, hold_pts;
|
||||
uint32_t last_scr, hold_last_scr;
|
||||
uint8_t *metadata_buf;
|
||||
size_t metadata_bytes,metadata_size;
|
||||
size_t got_bytes, hold_bytes;
|
||||
uint8_t *outbuf, *holdbuf;
|
||||
std::mutex cb_mutex;
|
||||
std::condition_variable cb_cond;
|
||||
std::thread cb_thread;
|
||||
uint32_t last_polled_seq;
|
||||
uvc_frame_callback_t *user_cb;
|
||||
void *user_ptr;
|
||||
struct libusb_transfer *transfers[LIBUVC_NUM_TRANSFER_BUFS];
|
||||
uint8_t *transfer_bufs[LIBUVC_NUM_TRANSFER_BUFS];
|
||||
std::condition_variable transfer_cancel[LIBUVC_NUM_TRANSFER_BUFS];
|
||||
struct uvc_frame frame;
|
||||
enum uvc_frame_format frame_format;
|
||||
};
|
||||
|
||||
/** Handle on an open UVC device
|
||||
*
|
||||
* @todo move most of this into a uvc_device struct?
|
||||
*/
|
||||
struct uvc_device_handle {
|
||||
struct uvc_device *dev;
|
||||
struct uvc_device_handle *prev, *next;
|
||||
/** Underlying USB device handle */
|
||||
libusb_device_handle *usb_devh;
|
||||
struct uvc_device_info *info;
|
||||
struct libusb_transfer *status_xfer;
|
||||
uint8_t status_buf[32];
|
||||
/** Function to call when we receive status updates from the camera */
|
||||
uvc_status_callback_t *status_cb;
|
||||
void *status_user_ptr;
|
||||
/** Function to call when we receive button events from the camera */
|
||||
uvc_button_callback_t *button_cb;
|
||||
void *button_user_ptr;
|
||||
|
||||
uvc_stream_handle_t *streams;
|
||||
/** Whether the camera is an iSight that sends one header per frame */
|
||||
uint8_t is_isight;
|
||||
};
|
||||
|
||||
/** Context within which we communicate with devices */
|
||||
struct uvc_context {
|
||||
/** Underlying context for USB communication */
|
||||
struct libusb_context *usb_ctx;
|
||||
/** True iff libuvc initialized the underlying USB context */
|
||||
uint8_t own_usb_ctx;
|
||||
/** List of open devices in this context */
|
||||
uvc_device_handle_t *open_devices;
|
||||
std::thread handler_thread;
|
||||
int kill_handler_thread;
|
||||
};
|
||||
|
||||
uvc_error_t uvc_query_stream_ctrl(
|
||||
uvc_device_handle_t *devh,
|
||||
uvc_stream_ctrl_t *ctrl,
|
||||
uint8_t probe,
|
||||
enum uvc_req_code req);
|
||||
|
||||
void uvc_start_handler_thread(uvc_context_t *ctx);
|
||||
uvc_error_t uvc_claim_if(uvc_device_handle_t *devh, int idx);
|
||||
uvc_error_t uvc_release_if(uvc_device_handle_t *devh, int idx);
|
||||
|
||||
#endif // !def(UVC_OSX_INTERNAL_H)
|
||||
/** @endcond */
|
||||
|
Loading…
Reference in New Issue
Block a user