From a1a3a5c63e13bf97844c7039d5a6b341a14f1512 Mon Sep 17 00:00:00 2001 From: icarpis Date: Wed, 11 Jul 2018 18:04:20 +0300 Subject: [PATCH] Fixing multicamera flow via libuvc (cherry picked from commit 7aac67529d3137da3f88e645d852ce0348bd4515) # Conflicts: # src/libuvc/libuvc.cpp --- src/libuvc/device.cpp | 79 ++++++++++++------------ src/libuvc/libuvc.cpp | 136 ++++++++++++++++++++---------------------- src/libuvc/libuvc.h | 5 +- 3 files changed, 110 insertions(+), 110 deletions(-) diff --git a/src/libuvc/device.cpp b/src/libuvc/device.cpp index 9aba3d92ff..3e27628e4b 100644 --- a/src/libuvc/device.cpp +++ b/src/libuvc/device.cpp @@ -131,53 +131,56 @@ int uvc_already_open(uvc_context_t *ctx, struct libusb_device *usb_dev) { */ uvc_error_t uvc_find_device( uvc_context_t *ctx, uvc_device_t **dev, - int vid, int pid, const char *sn) { - uvc_error_t ret = UVC_SUCCESS; + int vid, int pid, const char *sn, std::function predicate) +{ + uvc_error_t ret = UVC_SUCCESS; - uvc_device_t **list; - uvc_device_t *test_dev; - int dev_idx; - int found_dev; + uvc_device_t **list; + uvc_device_t *test_dev; + int dev_idx; + int found_dev; - UVC_ENTER(); + UVC_ENTER(); - ret = uvc_get_device_list(ctx, &list); + ret = uvc_get_device_list(ctx, &list); - if (ret != UVC_SUCCESS) { - UVC_EXIT(ret); - return ret; - } - - dev_idx = 0; - found_dev = 0; - - while (!found_dev && (test_dev = list[dev_idx++]) != NULL) { - uvc_device_descriptor_t *desc; - - if (uvc_get_device_descriptor(test_dev, &desc) != UVC_SUCCESS) - continue; + if (ret != UVC_SUCCESS) { + UVC_EXIT(ret); + return ret; + } - if ((!vid || desc->idVendor == vid) - && (!pid || desc->idProduct == pid) - && (!sn || (desc->serialNumber && !strcmp(desc->serialNumber, sn)))) - found_dev = 1; + dev_idx = 0; + found_dev = 0; + + while (!found_dev && (test_dev = list[dev_idx++]) != NULL) { + uvc_device_descriptor_t *desc; + + if (uvc_get_device_descriptor(test_dev, &desc) != UVC_SUCCESS) + continue; + + if ((!vid || desc->idVendor == vid) + && (!pid || desc->idProduct == pid) + && (!sn || (desc->serialNumber && !strcmp(desc->serialNumber, sn)))) + { + if (predicate(test_dev)) + found_dev = 1; + } - uvc_free_device_descriptor(desc); - } + uvc_free_device_descriptor(desc); + } - if (found_dev) - uvc_ref_device(test_dev); + if (found_dev) uvc_ref_device(test_dev); - uvc_free_device_list(list, 1); + uvc_free_device_list(list, 1); - if (found_dev) { - *dev = test_dev; - UVC_EXIT(UVC_SUCCESS); - return UVC_SUCCESS; - } else { - UVC_EXIT(UVC_ERROR_NO_DEVICE); - return UVC_ERROR_NO_DEVICE; - } + if (found_dev) { + *dev = test_dev; + UVC_EXIT(UVC_SUCCESS); + return UVC_SUCCESS; + } else { + UVC_EXIT(UVC_ERROR_NO_DEVICE); + return UVC_ERROR_NO_DEVICE; + } } /** @brief Finds all cameras identified by vendor, product and/or serial number diff --git a/src/libuvc/libuvc.cpp b/src/libuvc/libuvc.cpp index 8cabb5383d..c5871a220c 100644 --- a/src/libuvc/libuvc.cpp +++ b/src/libuvc/libuvc.cpp @@ -189,9 +189,9 @@ namespace librealsense /* callback context send for each frame for its specific profile */ struct callback_context { - frame_callback _callback; - stream_profile _profile; - libuvc_uvc_device *_this; + frame_callback _callback; + stream_profile _profile; + libuvc_uvc_device *_this; }; /* implements uvc_device for libUVC support */ @@ -275,13 +275,12 @@ namespace librealsense } }); if (_name == "") { - throw linux_backend_exception("device is no longer connected!"); + throw linux_backend_exception("device is no longer connected!"); } - _state_change_time = 0; - _is_power_thread_alive = true; - _thread_handle = std::thread(std::bind(&libuvc_uvc_device::power_thread,this)); - + _state_change_time = 0; + _is_power_thread_alive = true; + _thread_handle = std::thread(std::bind(&libuvc_uvc_device::power_thread,this)); } ~libuvc_uvc_device() @@ -309,8 +308,7 @@ namespace librealsense if (res < 0) { uvc_close(_device_handle); uvc_unref_device(_device); - throw linux_backend_exception( - "Could not get stream format."); + throw linux_backend_exception("Could not get stream format."); } // add to the vector of profiles. @@ -322,26 +320,22 @@ namespace librealsense /* request to start streaming*/ void stream_on(std::function error_handler) override { - uvc_error_t res; - // loop over each prfile and start streaming. - for (auto i=0;i< _profiles.size(); ++i) { - callback_context *context = new callback_context(); - context->_callback = _callbacks[i]; - context->_this = this; - context->_profile = _profiles[i]; - - res = uvc_start_streaming(_device_handle, - &_stream_ctrls[i], - internal_uvc_callback, - context, - 0); - - if (res < 0) { - throw linux_backend_exception( - "fail to start streaming."); - + uvc_error_t res; + // loop over each prfile and start streaming. + for (auto i=0; i < _profiles.size(); ++i) { + callback_context *context = new callback_context(); + context->_callback = _callbacks[i]; + context->_this = this; + context->_profile = _profiles[i]; + + res = uvc_start_streaming(_device_handle, + &_stream_ctrls[i], + internal_uvc_callback, + context, + 0); + + if (res < 0) throw linux_backend_exception("fail to start streaming."); } - } } void start_callbacks() override @@ -362,58 +356,60 @@ namespace librealsense _is_capturing = false; _is_started = false; } - } void power_D0() { - uvc_error_t res; - uvc_format_t *formats; + uvc_error_t res; + uvc_format_t *formats; - res = uvc_find_device(_ctx, &_device, _info.vid, _info.pid, NULL); + res = uvc_find_device(_ctx, &_device, _info.vid, _info.pid, NULL, + [&](uvc_device_t* device){ + auto dev = (uvc_device_internal *) device; + auto usb_params = get_usb_descriptors(dev->usb_dev); + return _info.unique_id == std::get<0>(usb_params); + }); - if (res < 0) { - throw linux_backend_exception( - "Could not find the device."); - } - res = uvc_open2(_device, &_device_handle, _interface); + if (res < 0) + throw linux_backend_exception("Could not find the device."); + res = uvc_open2(_device, &_device_handle, _interface); - if (res < 0) { - uvc_unref_device(_device); - _device = NULL; - throw linux_backend_exception( - "Could not open device."); - } + if (res < 0) { + uvc_unref_device(_device); + _device = NULL; + throw linux_backend_exception("Could not open device."); + } - for(auto ct = uvc_get_input_terminals(_device_handle); - ct; ct = ct->next) { - _input_terminal = ct->bTerminalID; - } + for(auto ct = uvc_get_input_terminals(_device_handle); + ct; ct = ct->next) { + _input_terminal = ct->bTerminalID; + } - for(auto pu = uvc_get_processing_units(_device_handle); - pu; pu = pu->next) { - _processing_unit = pu->bUnitID; - } + for(auto pu = uvc_get_processing_units(_device_handle); + pu; pu = pu->next) { + _processing_unit = pu->bUnitID; + } - for(auto eu = uvc_get_extension_units(_device_handle); - eu; eu = eu->next) { - _extension_unit = eu->bUnitID; - } + for(auto eu = uvc_get_extension_units(_device_handle); + eu; eu = eu->next) { + _extension_unit = eu->bUnitID; + } - _real_state = D0; + _real_state = D0; } void power_D3() { uvc_unref_device(_device); - //uvc_stop_streaming(_device_handle); - _profiles.clear(); - uvc_close(_device_handle); - _device = NULL; - _device_handle = NULL; - _real_state = D3; - } + //uvc_stop_streaming(_device_handle); + _profiles.clear(); + uvc_close(_device_handle); + _device = NULL; + _device_handle = NULL; + _real_state = D3; + } + void set_power_state(power_state state) override { - _power_mutex.lock(); + std::lock_guard lock(_power_mutex); /* if power became on and it was originally off. open the uvc device. */ if (state == D0 && _state == D3) { @@ -422,7 +418,7 @@ namespace librealsense _state_change_time = 0; if ( _real_state == D3) { - power_D0(); + power_D0(); } } else { @@ -433,7 +429,6 @@ namespace librealsense } _state = state; - _power_mutex.unlock(); } power_state get_power_state() const override { return _state; } @@ -674,7 +669,7 @@ namespace librealsense do { std::this_thread::sleep_for(std::chrono::seconds(1)); - _power_mutex.lock(); + std::lock_guard lock(_power_mutex); if (_state_change_time != 0) { clock_t now_time = std::clock(); @@ -685,14 +680,13 @@ namespace librealsense _state_change_time = 0; if (_real_state == D0) { - power_D3(); - _real_state = D3; + power_D3(); + _real_state = D3; } } } - _power_mutex.unlock(); } while(_is_power_thread_alive); } diff --git a/src/libuvc/libuvc.h b/src/libuvc/libuvc.h index 84755c49cf..30e66d6bce 100644 --- a/src/libuvc/libuvc.h +++ b/src/libuvc/libuvc.h @@ -1,6 +1,8 @@ #ifndef LIBUVC_H #define LIBUVC_H +#include + #ifdef __cplusplus extern "C" { #endif @@ -531,7 +533,8 @@ uint8_t uvc_get_device_address(uvc_device_t *dev); uvc_error_t uvc_find_device( uvc_context_t *ctx, uvc_device_t **dev, - int vid, int pid, const char *sn); + int vid, int pid, const char *sn, + std::function predicate); uvc_error_t uvc_find_devices( uvc_context_t *ctx,