Add libuvc on macOS

This commit is contained in:
John Zhao 2018-03-22 12:57:35 +08:00
parent 50936ae612
commit b81299cfa1
10 changed files with 290 additions and 15 deletions

1
.gitignore vendored
View File

@ -1,6 +1,7 @@
.DS_Store .DS_Store
_build/ _build/
_install/
_output/ _output/
/doc/output/ /doc/output/

View File

@ -27,6 +27,8 @@ message(STATUS "Found glog: ${glog_VERSION}")
LIST(APPEND CMAKE_MODULE_PATH cmake) LIST(APPEND CMAKE_MODULE_PATH cmake)
include(CMakePackageConfigHelpers)
# config # config
set(MYNTEYE_NAMESPACE "mynteye") set(MYNTEYE_NAMESPACE "mynteye")
@ -41,17 +43,116 @@ configure_file(
include(cmake/Common.cmake) include(cmake/Common.cmake)
set(OUT_DIR "${PROJECT_SOURCE_DIR}/_output") set(OUT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/_output")
set_outdir( set_outdir(
"${OUT_DIR}/lib" "${OUT_DIR}/lib"
"${OUT_DIR}/lib" "${OUT_DIR}/lib"
"${OUT_DIR}/bin" "${OUT_DIR}/bin"
) )
include_directories( set(MYNTEYE_CMAKE_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/include")
include set(MYNTEYE_CMAKE_BINDIR "${CMAKE_INSTALL_PREFIX}/bin")
${CMAKE_BINARY_DIR}/include set(MYNTEYE_CMAKE_LIBDIR "${CMAKE_INSTALL_PREFIX}/lib")
) set(MYNTEYE_CMAKE_INSTALLDIR "${MYNTEYE_CMAKE_LIBDIR}/cmake/${MYNTEYE_NAME}")
## main
add_executable(main src/main.cc) add_executable(main src/main.cc)
target_link_libraries(main glog::glog) target_link_libraries(main glog::glog)
target_include_directories(main PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_BINARY_DIR}/include
)
## libmynteye
set(MYNTEYE_NAME ${PROJECT_NAME})
set(MYNTEYE_PUBLIC_H
${CMAKE_CURRENT_SOURCE_DIR}/include/mynteye/global.h
${CMAKE_CURRENT_BINARY_DIR}/include/mynteye/mynteye.h
)
if(OS_WIN)
set(UVC_SRC src/uvc/uvc-wmf.cc)
elseif(OS_MAC)
set(UVC_SRC src/uvc/uvc-libuvc.cc)
find_package(libuvc REQUIRED)
set(UVC_LIB ${libuvc_LIBRARIES})
include_directories(${libuvc_INCLUDE_DIRS})
elseif(OS_LINUX)
set(UVC_SRC src/uvc/uvc-v4l2.cc)
else()
message(FATAL_ERROR "Unsupported OS.")
endif()
set(MYNTEYE_SRCS
${UVC_SRC}
)
set(MYNTEYE_LINKLIBS
glog::glog
${UVC_LIB}
)
#message(STATUS "MYNTEYE_LINKLIBS: ${MYNTEYE_LINKLIBS}")
add_library(${MYNTEYE_NAME} SHARED ${MYNTEYE_SRCS})
target_link_libraries(${MYNTEYE_NAME} ${MYNTEYE_LINKLIBS})
if(OS_WIN)
target_compile_definitions(${MYNTEYE_NAME}
PUBLIC GLOG_NO_ABBREVIATED_SEVERITIES
)
endif()
target_include_directories(${MYNTEYE_NAME} PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>"
"$<INSTALL_INTERFACE:${MYNTEYE_CMAKE_INCLUDE_DIR}>"
)
set_target_properties(${MYNTEYE_NAME} PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
)
set_target_properties(${MYNTEYE_NAME} PROPERTIES
PUBLIC_HEADER "${MYNTEYE_PUBLIC_H}"
)
# install
#message(STATUS "MYNTEYE_CMAKE_INCLUDE_DIR: ${MYNTEYE_CMAKE_INCLUDE_DIR}")
#message(STATUS "MYNTEYE_CMAKE_BINDIR: ${MYNTEYE_CMAKE_BINDIR}")
#message(STATUS "MYNTEYE_CMAKE_LIBDIR: ${MYNTEYE_CMAKE_LIBDIR}")
#message(STATUS "MYNTEYE_CMAKE_INSTALLDIR: ${MYNTEYE_CMAKE_INSTALLDIR}")
install(TARGETS ${MYNTEYE_NAME}
EXPORT ${MYNTEYE_NAME}-targets
PUBLIC_HEADER DESTINATION ${MYNTEYE_CMAKE_INCLUDE_DIR}/${MYNTEYE_NAME}
RUNTIME DESTINATION ${MYNTEYE_CMAKE_BINDIR}
LIBRARY DESTINATION ${MYNTEYE_CMAKE_LIBDIR}
ARCHIVE DESTINATION ${MYNTEYE_CMAKE_LIBDIR}
)
configure_package_config_file(mynteye-config.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/mynteye-config.cmake
INSTALL_DESTINATION ${MYNTEYE_CMAKE_INSTALLDIR}
NO_CHECK_REQUIRED_COMPONENTS_MACRO
)
write_basic_package_version_file(mynteye-config-version.cmake
VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion
)
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/mynteye-config.cmake
${CMAKE_CURRENT_BINARY_DIR}/mynteye-config-version.cmake
DESTINATION ${MYNTEYE_CMAKE_INSTALLDIR}
)
install(EXPORT ${MYNTEYE_NAME}-targets
DESTINATION ${MYNTEYE_CMAKE_INSTALLDIR}
)

View File

@ -150,6 +150,7 @@ ifneq ($(MAKE),)
endif endif
CMAKE_OPTIONS := CMAKE_OPTIONS :=
CMAKE_OPTIONS += -DCMAKE_INSTALL_PREFIX=$(shell pwd)/_install
# CMAKE_OPTIONS += -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON # CMAKE_OPTIONS += -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON
CMAKE_OPTIONS_AFTER := CMAKE_OPTIONS_AFTER :=

View File

@ -10,6 +10,7 @@ help:
@echo " make init init project" @echo " make init init project"
@echo " make build build project" @echo " make build build project"
@echo " make test build test and run" @echo " make test build test and run"
@echo " make install install project"
@echo " make clean|cleanall clean generated or useless things" @echo " make clean|cleanall clean generated or useless things"
.PHONY: help .PHONY: help
@ -30,14 +31,6 @@ opendoc: apidoc
.PHONY: apidoc opendoc .PHONY: apidoc opendoc
# init
init:
@$(call echo,Make $@)
@$(SH) ./scripts/init.sh
.PHONY: init
# deps # deps
submodules: submodules:
@ -50,6 +43,14 @@ third_party: submodules
.PHONY: submodules third_party .PHONY: submodules third_party
# init
init: submodules
@$(call echo,Make $@)
@$(SH) ./scripts/init.sh
.PHONY: init
# build # build
build: third_party build: third_party
@ -67,12 +68,21 @@ test: submodules
.PHONY: test .PHONY: test
# install
install: build
@$(call echo,Make $@)
@cd ./_build; make install
.PHONY: install
# clean # clean
clean: clean:
@$(call echo,Make $@) @$(call echo,Make $@)
@$(call rm,./_build/) @$(call rm,./_build/)
@$(call rm,./_output/) @$(call rm,./_output/)
@$(call rm,./_install/)
@$(MAKE) cleanlog @$(MAKE) cleanlog
cleanall: clean cleanall: clean
@ -107,7 +117,7 @@ host:
.PHONY: host .PHONY: host
cpplint: cpplint: submodules
@$(call echo,Make $@) @$(call echo,Make $@)
@$(SH) ./scripts/$@.sh @$(SH) ./scripts/$@.sh

View File

@ -1,5 +1,15 @@
include(CMakeParseArguments) include(CMakeParseArguments)
if(MSVC OR MSYS OR MINGW)
set(OS_WIN TRUE)
elseif(APPLE)
set(OS_MAC TRUE)
elseif(UNIX)
set(OS_LINUX TRUE)
else()
message(FATAL_ERROR "Unsupported OS.")
endif()
# set_outdir(ARCHIVE_OUTPUT_DIRECTORY # set_outdir(ARCHIVE_OUTPUT_DIRECTORY
# LIBRARY_OUTPUT_DIRECTORY # LIBRARY_OUTPUT_DIRECTORY
# RUNTIME_OUTPUT_DIRECTORY) # RUNTIME_OUTPUT_DIRECTORY)

View File

@ -66,6 +66,8 @@
Class(const Class &) = delete; \ Class(const Class &) = delete; \
Class &operator=(const Class &) = delete; Class &operator=(const Class &) = delete;
#define UNUSED(x) (void)x;
template <typename... T> template <typename... T>
void unused(T &&...) {} void unused(T &&...) {}

3
mynteye-config.cmake.in Normal file
View File

@ -0,0 +1,3 @@
@PACKAGE_INIT@
include("${CMAKE_CURRENT_LIST_DIR}/mynteye-targets.cmake")

View File

@ -18,6 +18,16 @@ fi
_detect curl _detect curl
_detect $PYTHON _detect $PYTHON
if [ "$HOST_OS" = "Mac" ]; then
_detect_install() {
brew ls --versions "$1" > /dev/null
}
else
_detect_install() {
_detect_cmd "$1"
}
fi
_install_deps() { _install_deps() {
_cmd="$1"; shift; _deps_all=($@) _cmd="$1"; shift; _deps_all=($@)
_echo "Install cmd: $_cmd" _echo "Install cmd: $_cmd"
@ -29,7 +39,7 @@ _install_deps() {
fi fi
_deps=() _deps=()
for _dep in "${_deps_all[@]}"; do for _dep in "${_deps_all[@]}"; do
_detect_cmd $_dep || _deps+=($_dep) _detect_install $_dep || _deps+=($_dep)
done done
if [ ${#_deps[@]} -eq 0 ]; then if [ ${#_deps[@]} -eq 0 ]; then
_echo_i "All deps already exist" _echo_i "All deps already exist"
@ -62,6 +72,7 @@ elif [ "$HOST_OS" = "Mac" ]; then
# link clang-format-diff (if not compatible with Python 3, fix it by yourself) # link clang-format-diff (if not compatible with Python 3, fix it by yourself)
[ -f "/usr/local/bin/clang-format-diff" ] || \ [ -f "/usr/local/bin/clang-format-diff" ] || \
ln -s /usr/local/share/clang/clang-format-diff.py /usr/local/bin/clang-format-diff ln -s /usr/local/share/clang/clang-format-diff.py /usr/local/bin/clang-format-diff
_install_deps "brew install" libuvc
elif [ "$HOST_OS" = "Win" ]; then elif [ "$HOST_OS" = "Win" ]; then
# detect pacman on MSYS # detect pacman on MSYS
_detect pacman _detect pacman

102
src/uvc/uvc-libuvc.cc Normal file
View File

@ -0,0 +1,102 @@
#include "uvc.h" // NOLINT
#include <glog/logging.h>
#include <libuvc/libuvc.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(name, ...) check(#name, name(__VA_ARGS__))
struct context {
uvc_context_t *ctx;
context() : ctx() {
CALL_UVC(uvc_init, &ctx, nullptr);
}
~context() {
if (ctx)
uvc_exit(ctx);
}
};
struct device {
const std::shared_ptr<context> parent;
uvc_device_t *uvcdevice;
uvc_device_handle_t *handle = nullptr;
int vid, pid;
// uvc_stream_ctrl_t ctrl;
// uint8_t unit;
// video_channel_callback callback = nullptr;
device(std::shared_ptr<context> parent, uvc_device_t *uvcdevice)
: parent(parent), uvcdevice(uvcdevice) {
open();
uvc_device_descriptor_t *desc;
CALL_UVC(uvc_get_device_descriptor, uvcdevice, &desc);
vid = desc->idVendor;
pid = desc->idProduct;
uvc_free_device_descriptor(desc);
}
~device() {
if (handle)
uvc_close(handle);
if (uvcdevice)
uvc_unref_device(uvcdevice);
}
void open() {
if (!handle)
CALL_UVC(uvc_open, uvcdevice, &handle);
}
};
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;
}
} // namespace uvc
MYNTEYE_END_NAMESPACE

34
src/uvc/uvc.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef MYNTEYE_UVC_H_ // NOLINT
#define MYNTEYE_UVC_H_
#pragma once
#include <memory>
#include <vector>
#include "mynteye/mynteye.h"
#define MYNTEYE_VID 0x04B4
#define MYNTEYE_PID 0x00F9
MYNTEYE_BEGIN_NAMESPACE
namespace uvc {
struct context; // Opaque type representing access to the underlying UVC
// implementation
struct device; // Opaque type representing access to a specific UVC device
// Enumerate devices
std::shared_ptr<context> create_context();
std::vector<std::shared_ptr<device>> query_devices(
std::shared_ptr<context> context);
// Static device properties
int get_vendor_id(const device &device);
int get_product_id(const device &device);
} // namespace uvc
MYNTEYE_END_NAMESPACE
#endif // MYNTEYE_UVC_H_ NOLINT