Skip to content

Commit

Permalink
Fixing multicamera flow via libuvc
Browse files Browse the repository at this point in the history
  • Loading branch information
icarpis committed Jul 11, 2018
1 parent 2c48112 commit 7aac675
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 112 deletions.
79 changes: 41 additions & 38 deletions src/libuvc/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<bool(uvc_device_t*)> 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
Expand Down
142 changes: 69 additions & 73 deletions src/libuvc/libuvc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,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 */
Expand Down Expand Up @@ -270,8 +270,9 @@ namespace librealsense
throw linux_backend_exception("fail to initialize libuvc");
}

bool found = false;
// search the device in device list.
foreach_uvc_device(_ctx, [&info, this](const uvc_device_info& i, const std::string& name)
foreach_uvc_device(_ctx, [&info, &found, this](const uvc_device_info& i, const std::string& name)
{
if (i == info)
{
Expand All @@ -280,16 +281,16 @@ namespace librealsense
_device_path = i.device_path;
_interface = i.mi;
_device_usb_spec = i.conn_spec;
found = true;
}
});
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()
Expand Down Expand Up @@ -321,8 +322,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.
Expand All @@ -334,26 +334,22 @@ namespace librealsense
/* request to start streaming*/
void stream_on(std::function<void(const notification& n)> 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
Expand All @@ -374,57 +370,59 @@ 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_stop_streaming(_device_handle);
_profiles.clear();
uvc_close(_device_handle);
uvc_unref_device(_device);
_device = NULL;
_device_handle = NULL;
_real_state = D3;
}
//uvc_stop_streaming(_device_handle);
_profiles.clear();
uvc_close(_device_handle);
uvc_unref_device(_device);
_device = NULL;
_device_handle = NULL;
_real_state = D3;
}

void set_power_state(power_state state) override {
_power_mutex.lock();
std::lock_guard<std::mutex> lock(_power_mutex);

/* if power became on and it was originally off. open the uvc device. */
if (state == D0 && _state == D3) {
Expand All @@ -433,7 +431,7 @@ namespace librealsense
_state_change_time = 0;

if ( _real_state == D3) {
power_D0();
power_D0();
}
}
else {
Expand All @@ -444,7 +442,6 @@ namespace librealsense
}

_state = state;
_power_mutex.unlock();

}
power_state get_power_state() const override { return _state; }
Expand Down Expand Up @@ -693,7 +690,7 @@ namespace librealsense
do {
std::this_thread::sleep_for(std::chrono::seconds(1));

_power_mutex.lock();
std::lock_guard<std::mutex> lock(_power_mutex);

if (_state_change_time != 0) {
clock_t now_time = std::clock();
Expand All @@ -704,14 +701,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);
}

Expand Down
5 changes: 4 additions & 1 deletion src/libuvc/libuvc.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#ifndef LIBUVC_H
#define LIBUVC_H

#include <functional>

#ifdef __cplusplus
extern "C" {
#endif
Expand Down Expand Up @@ -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<bool(uvc_device_t *)> predicate);

uvc_error_t uvc_find_devices(
uvc_context_t *ctx,
Expand Down

0 comments on commit 7aac675

Please sign in to comment.