cscore: Separate platform-specific sources (#1387)

This commit is contained in:
Peter Johnson
2018-10-23 22:59:47 -07:00
committed by GitHub
parent 349e273ecc
commit 8ff81f5a2a
22 changed files with 333 additions and 180 deletions

View File

@@ -19,6 +19,9 @@ licenseUpdateExclude {
includeGuardRoots {
cscore/src/main/native/cpp/
cscore/src/main/native/include/
cscore/src/main/native/linux/
cscore/src/main/native/osx/
cscore/src/main/native/windows/
cscore/src/main/test/native/cpp/
}

View File

@@ -54,10 +54,29 @@ endif()
file(GLOB
cscore_native_src src/main/native/cpp/*.cpp)
file(GLOB cscore_linux_src src/main/native/linux/*.cpp)
file(GLOB cscore_osx_src src/main/native/osx/*.cpp)
file(GLOB cscore_windows_src src/main/native/windows/*.cpp)
add_library(cscore ${cscore_native_src} ${cscore_jni_src})
if(NOT MSVC)
if (APPLE)
target_sources(cscore PRIVATE ${cscore_osx_src})
else()
target_sources(cscore PRIVATE ${cscore_linux_src})
endif()
target_compile_options(cscore PRIVATE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE)
else()
target_sources(cscore PRIVATE ${cscore_windows_src})
target_compile_options(cscore PUBLIC -DNOMINMAX)
target_compile_options(cscore PRIVATE -D_CRT_SECURE_NO_WARNINGS)
endif()
target_include_directories(cscore PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/main/native/include>
$<INSTALL_INTERFACE:${include_dest}/cscore>)
target_include_directories(cscore PRIVATE src/main/native/cpp)
target_link_libraries(cscore PUBLIC wpiutil ${OpenCV_LIBS})
set_property(TARGET cscore PROPERTY FOLDER "libraries")

View File

@@ -31,6 +31,39 @@ ext {
srcDirs 'src/main/native/include'
}
}
cscoreMacCpp(CppSourceSet) {
source {
srcDirs 'src/main/native/osx'
include '**/*.cpp'
}
exportedHeaders {
srcDirs 'src/main/native/include', 'src/main/native/cpp'
}
}
}
} else if (it.targetPlatform.operatingSystem.name == 'linux') {
it.sources {
cscoreLinuxCpp(CppSourceSet) {
source {
srcDirs 'src/main/native/linux'
include '**/*.cpp'
}
exportedHeaders {
srcDirs 'src/main/native/include', 'src/main/native/cpp'
}
}
}
} else if (it.targetPlatform.operatingSystem.name == 'windows') {
it.sources {
cscoreWindowsCpp(CppSourceSet) {
source {
srcDirs 'src/main/native/windows'
include '**/*.cpp'
}
exportedHeaders {
srcDirs 'src/main/native/include', 'src/main/native/cpp'
}
}
}
}
}

View File

@@ -53,15 +53,6 @@ void HttpCameraImpl::Start() {
m_settingsThread = std::thread(&HttpCameraImpl::SettingsThreadMain, this);
}
#ifdef __linux__
static inline void DoFdSet(int fd, fd_set* set, int* nfds) {
if (fd >= 0) {
FD_SET(fd, set);
if ((fd + 1) > *nfds) *nfds = fd + 1;
}
}
#endif
void HttpCameraImpl::StreamThreadMain() {
while (m_active) {
SetConnected(false);

View File

@@ -0,0 +1,52 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include "cscore_c.h" // NOLINT(build/include_order)
#include "c_util.h"
#include "cscore_cpp.h"
using namespace cs;
extern "C" {
CS_Source CS_CreateUsbCameraDev(const char* name, int dev, CS_Status* status) {
return cs::CreateUsbCameraDev(name, dev, status);
}
CS_Source CS_CreateUsbCameraPath(const char* name, const char* path,
CS_Status* status) {
return cs::CreateUsbCameraPath(name, path, status);
}
char* CS_GetUsbCameraPath(CS_Source source, CS_Status* status) {
return ConvertToC(cs::GetUsbCameraPath(source, status));
}
CS_UsbCameraInfo* CS_EnumerateUsbCameras(int* count, CS_Status* status) {
auto cameras = cs::EnumerateUsbCameras(status);
CS_UsbCameraInfo* out = static_cast<CS_UsbCameraInfo*>(
wpi::CheckedMalloc(cameras.size() * sizeof(CS_UsbCameraInfo)));
*count = cameras.size();
for (size_t i = 0; i < cameras.size(); ++i) {
out[i].dev = cameras[i].dev;
out[i].path = ConvertToC(cameras[i].path);
out[i].name = ConvertToC(cameras[i].name);
}
return out;
}
void CS_FreeEnumeratedUsbCameras(CS_UsbCameraInfo* cameras, int count) {
if (!cameras) return;
for (int i = 0; i < count; ++i) {
std::free(cameras[i].path);
std::free(cameras[i].name);
}
std::free(cameras);
}
} // extern "C"

View File

@@ -7,13 +7,6 @@
#include "cscore_cpp.h"
#if defined(__linux__)
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <sys/types.h>
#include <unistd.h>
#endif
#include <wpi/SmallString.h>
#include "Handle.h"
@@ -693,39 +686,4 @@ wpi::ArrayRef<CS_Sink> EnumerateSinkHandles(wpi::SmallVectorImpl<CS_Sink>& vec,
return Sinks::GetInstance().GetAll(vec);
}
std::string GetHostname() {
#ifdef __linux__
char name[256];
if (::gethostname(name, sizeof(name)) != 0) return "";
name[255] = '\0'; // Per POSIX, may not be null terminated if too long
return name;
#else
return ""; // TODO
#endif
}
std::vector<std::string> GetNetworkInterfaces() {
#ifdef __linux__
struct ifaddrs* ifa;
if (::getifaddrs(&ifa) != 0) return std::vector<std::string>{};
std::vector<std::string> rv;
char buf[256];
for (struct ifaddrs* i = ifa; i; i = i->ifa_next) {
if (!i->ifa_addr) continue; // no address
if (i->ifa_addr->sa_family != AF_INET) continue; // only return IPv4
struct sockaddr_in* addr_in = reinterpret_cast<sockaddr_in*>(i->ifa_addr);
const char* addr =
::inet_ntop(addr_in->sin_family, &addr_in->sin_addr, buf, sizeof(buf));
if (!addr) continue; // error converting address
rv.emplace_back(addr);
}
::freeifaddrs(ifa);
return rv;
#else
return std::vector<std::string>{}; // TODO
#endif
}
} // namespace cs

View File

@@ -181,7 +181,6 @@ static inline bool CheckStatus(JNIEnv* env, CS_Status status) {
return status == CS_OK;
}
#ifdef __linux__
static jobject MakeJObject(JNIEnv* env, const cs::UsbCameraInfo& info) {
static jmethodID constructor = env->GetMethodID(
usbCameraInfoCls, "<init>", "(ILjava/lang/String;Ljava/lang/String;)V");
@@ -190,7 +189,6 @@ static jobject MakeJObject(JNIEnv* env, const cs::UsbCameraInfo& info) {
return env->NewObject(usbCameraInfoCls, constructor,
static_cast<jint>(info.dev), path.obj(), name.obj());
}
#endif
static jobject MakeJObject(JNIEnv* env, const cs::VideoMode& videoMode) {
static jmethodID constructor =
@@ -406,10 +404,6 @@ JNIEXPORT jint JNICALL
Java_edu_wpi_cscore_CameraServerJNI_createUsbCameraDev
(JNIEnv* env, jclass, jstring name, jint dev)
{
#ifndef __linux__
unsupportedEx.Throw(env, "USB is not supported yet");
return 0;
#else
if (!name) {
nullPointerEx.Throw(env, "name cannot be null");
return 0;
@@ -418,7 +412,6 @@ Java_edu_wpi_cscore_CameraServerJNI_createUsbCameraDev
auto val = cs::CreateUsbCameraDev(JStringRef{env, name}.str(), dev, &status);
CheckStatus(env, status);
return val;
#endif
}
/*
@@ -430,10 +423,6 @@ JNIEXPORT jint JNICALL
Java_edu_wpi_cscore_CameraServerJNI_createUsbCameraPath
(JNIEnv* env, jclass, jstring name, jstring path)
{
#ifndef __linux__
unsupportedEx.Throw(env, "USB is not supported yet");
return 0;
#else
if (!name) {
nullPointerEx.Throw(env, "name cannot be null");
return 0;
@@ -447,7 +436,6 @@ Java_edu_wpi_cscore_CameraServerJNI_createUsbCameraPath
JStringRef{env, path}.str(), &status);
CheckStatus(env, status);
return val;
#endif
}
/*
@@ -949,15 +937,10 @@ JNIEXPORT jstring JNICALL
Java_edu_wpi_cscore_CameraServerJNI_getUsbCameraPath
(JNIEnv* env, jclass, jint source)
{
#ifndef __linux__
unsupportedEx.Throw(env, "USB is not supported yet");
return 0;
#else
CS_Status status = 0;
auto str = cs::GetUsbCameraPath(source, &status);
if (!CheckStatus(env, status)) return nullptr;
return MakeJString(env, str);
#endif
}
/*
@@ -1582,10 +1565,6 @@ JNIEXPORT jobjectArray JNICALL
Java_edu_wpi_cscore_CameraServerJNI_enumerateUsbCameras
(JNIEnv* env, jclass)
{
#ifndef __linux__
unsupportedEx.Throw(env, "USB is not supported yet");
return 0;
#else
CS_Status status = 0;
auto arr = cs::EnumerateUsbCameras(&status);
if (!CheckStatus(env, status)) return nullptr;
@@ -1597,7 +1576,6 @@ Java_edu_wpi_cscore_CameraServerJNI_enumerateUsbCameras
env->SetObjectArrayElement(jarr, i, jelem);
}
return jarr;
#endif
}
/*

View File

@@ -0,0 +1,44 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include "cscore_cpp.h" // NOLINT(build/include_order)
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <sys/types.h>
#include <unistd.h>
namespace cs {
std::string GetHostname() {
char name[256];
if (::gethostname(name, sizeof(name)) != 0) return "";
name[255] = '\0'; // Per POSIX, may not be null terminated if too long
return name;
}
std::vector<std::string> GetNetworkInterfaces() {
struct ifaddrs* ifa;
if (::getifaddrs(&ifa) != 0) return std::vector<std::string>{};
std::vector<std::string> rv;
char buf[256];
for (struct ifaddrs* i = ifa; i; i = i->ifa_next) {
if (!i->ifa_addr) continue; // no address
if (i->ifa_addr->sa_family != AF_INET) continue; // only return IPv4
struct sockaddr_in* addr_in = reinterpret_cast<sockaddr_in*>(i->ifa_addr);
const char* addr =
::inet_ntop(addr_in->sin_family, &addr_in->sin_addr, buf, sizeof(buf));
if (!addr) continue; // error converting address
rv.emplace_back(addr);
}
::freeifaddrs(ifa);
return rv;
}
} // namespace cs

View File

@@ -8,9 +8,7 @@
#ifndef CSCORE_USBCAMERABUFFER_H_
#define CSCORE_USBCAMERABUFFER_H_
#ifdef __linux__
#include <sys/mman.h>
#endif
#include <utility>
@@ -29,7 +27,6 @@ class UsbCameraBuffer {
UsbCameraBuffer(const UsbCameraBuffer&) = delete;
UsbCameraBuffer& operator=(const UsbCameraBuffer&) = delete;
#ifdef __linux__
UsbCameraBuffer(int fd, size_t length, off_t offset) noexcept
: m_length{length} {
m_data =
@@ -43,7 +40,6 @@ class UsbCameraBuffer {
~UsbCameraBuffer() {
if (m_data) munmap(m_data, m_length);
}
#endif
friend void swap(UsbCameraBuffer& first, UsbCameraBuffer& second) noexcept {
using std::swap;

View File

@@ -7,7 +7,6 @@
#include "UsbCameraImpl.h"
#ifdef __linux__
#include <dirent.h>
#include <fcntl.h>
#include <libgen.h>
@@ -22,8 +21,6 @@
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#elif defined(_WIN32)
#endif
#include <algorithm>
@@ -38,13 +35,10 @@
#include "Notifier.h"
#include "Telemetry.h"
#include "UsbUtil.h"
#include "c_util.h"
#include "cscore_cpp.h"
using namespace cs;
#ifdef __linux__
static constexpr char const* kPropWbAuto = "white_balance_temperature_auto";
static constexpr char const* kPropWbValue = "white_balance_temperature";
static constexpr char const* kPropExAuto = "exposure_auto";
@@ -1320,73 +1314,3 @@ std::vector<UsbCameraInfo> EnumerateUsbCameras(CS_Status* status) {
}
} // namespace cs
extern "C" {
CS_Source CS_CreateUsbCameraDev(const char* name, int dev, CS_Status* status) {
return cs::CreateUsbCameraDev(name, dev, status);
}
CS_Source CS_CreateUsbCameraPath(const char* name, const char* path,
CS_Status* status) {
return cs::CreateUsbCameraPath(name, path, status);
}
char* CS_GetUsbCameraPath(CS_Source source, CS_Status* status) {
return ConvertToC(cs::GetUsbCameraPath(source, status));
}
CS_UsbCameraInfo* CS_EnumerateUsbCameras(int* count, CS_Status* status) {
auto cameras = cs::EnumerateUsbCameras(status);
CS_UsbCameraInfo* out = static_cast<CS_UsbCameraInfo*>(
wpi::CheckedMalloc(cameras.size() * sizeof(CS_UsbCameraInfo)));
*count = cameras.size();
for (size_t i = 0; i < cameras.size(); ++i) {
out[i].dev = cameras[i].dev;
out[i].path = ConvertToC(cameras[i].path);
out[i].name = ConvertToC(cameras[i].name);
}
return out;
}
void CS_FreeEnumeratedUsbCameras(CS_UsbCameraInfo* cameras, int count) {
if (!cameras) return;
for (int i = 0; i < count; ++i) {
std::free(cameras[i].path);
std::free(cameras[i].name);
}
std::free(cameras);
}
} // extern "C"
#else
extern "C" {
CS_Source CS_CreateUsbCameraDev(const char* name, int dev, CS_Status* status) {
*status = CS_INVALID_HANDLE;
return 0;
}
CS_Source CS_CreateUsbCameraPath(const char* name, const char* path,
CS_Status* status) {
*status = CS_INVALID_HANDLE;
return 0;
}
char* CS_GetUsbCameraPath(CS_Source source, CS_Status* status) {
*status = CS_INVALID_HANDLE;
return nullptr;
}
CS_UsbCameraInfo* CS_EnumerateUsbCameras(int* count, CS_Status* status) {
*status = CS_INVALID_HANDLE;
return nullptr;
}
void CS_FreeEnumeratedUsbCameras(CS_UsbCameraInfo* cameras, int count) {}
} // extern "C"
#endif // __linux__

View File

@@ -8,9 +8,7 @@
#ifndef CSCORE_USBCAMERAIMPL_H_
#define CSCORE_USBCAMERAIMPL_H_
#ifdef __linux__
#include <linux/videodev2.h>
#endif
#include <atomic>
#include <memory>
@@ -145,24 +143,18 @@ class UsbCameraImpl : public SourceImpl {
bool m_modeSetResolution{false};
bool m_modeSetFPS{false};
int m_connectVerbose{1};
#ifdef __linux__
unsigned m_capabilities = 0;
#endif
// Number of buffers to ask OS for
static constexpr int kNumBuffers = 4;
#ifdef __linux__
std::array<UsbCameraBuffer, kNumBuffers> m_buffers;
#endif
//
// Path never changes, so not protected by mutex.
//
std::string m_path;
#ifdef __linux__
std::atomic_int m_fd;
std::atomic_int m_command_fd; // for command eventfd
#endif
std::atomic_bool m_active; // set to false to terminate thread
std::thread m_cameraThread;

View File

@@ -14,8 +14,6 @@
using namespace cs;
#ifdef __linux__
static int GetIntCtrlIoctl(int fd, unsigned id, int type, int64_t* value) {
unsigned ctrl_class = V4L2_CTRL_ID2CLASS(id);
if (type == V4L2_CTRL_TYPE_INTEGER64 || V4L2_CTRL_DRIVER_PRIV(id) ||
@@ -322,5 +320,3 @@ bool UsbCameraProperty::DeviceSet(std::unique_lock<wpi::mutex>& lock, int fd,
return rv >= 0;
}
#endif // __linux__

View File

@@ -8,9 +8,7 @@
#ifndef CSCORE_USBCAMERAPROPERTY_H_
#define CSCORE_USBCAMERAPROPERTY_H_
#ifdef __linux__
#include <linux/videodev2.h>
#endif
#include <memory>
@@ -50,7 +48,6 @@ class UsbCameraProperty : public PropertyImpl {
maximum = 100;
}
#ifdef __linux__
#ifdef VIDIOC_QUERY_EXT_CTRL
explicit UsbCameraProperty(const struct v4l2_query_ext_ctrl& ctrl);
#endif
@@ -62,7 +59,6 @@ class UsbCameraProperty : public PropertyImpl {
bool DeviceSet(std::unique_lock<wpi::mutex>& lock, int fd) const;
bool DeviceSet(std::unique_lock<wpi::mutex>& lock, int fd, int newValue,
const wpi::Twine& newValueStr) const;
#endif
// If this is a device (rather than software) property
bool device{true};

View File

@@ -8,11 +8,8 @@
#include "UsbUtil.h"
#include <fcntl.h>
#ifdef __linux__
#include <libgen.h>
#include <sys/ioctl.h>
#endif
#include <wpi/Format.h>
#include <wpi/SmallString.h>
@@ -23,8 +20,6 @@
namespace cs {
#ifdef __linux__
static wpi::StringRef GetUsbNameFromFile(int vendor, int product,
wpi::SmallVectorImpl<char>& buf) {
int fd = open("/var/lib/usbutils/usb.ids", O_RDONLY);
@@ -161,6 +156,4 @@ int CheckedIoctl(int fd, unsigned long req, void* data, // NOLINT(runtime/int)
return retval;
}
#endif // __linux__
} // namespace cs

View File

@@ -15,8 +15,6 @@
namespace cs {
#ifdef __linux__
wpi::StringRef GetUsbNameFromId(int vendor, int product,
wpi::SmallVectorImpl<char>& buf);
@@ -28,8 +26,6 @@ int CheckedIoctl(int fd, unsigned long req, void* data, // NOLINT(runtime/int)
#define TryIoctl(fd, req, data) \
CheckedIoctl(fd, req, data, #req, __FILE__, __LINE__, true)
#endif // __linux__
} // namespace cs
#endif // CSCORE_USBUTIL_H_

View File

@@ -0,0 +1,37 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2015-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include "NetworkListener.h"
#include "Log.h"
#include "Notifier.h"
using namespace cs;
class NetworkListener::Thread : public wpi::SafeThread {
public:
void Main();
};
NetworkListener::~NetworkListener() { Stop(); }
void NetworkListener::Start() {
auto thr = m_owner.GetThread();
if (!thr) m_owner.Start();
}
void NetworkListener::Stop() {
// Wake up thread
if (auto thr = m_owner.GetThread()) {
thr->m_active = false;
}
m_owner.Stop();
}
void NetworkListener::Thread::Main() {
// TODO
}

View File

@@ -0,0 +1,20 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include "cscore_cpp.h"
namespace cs {
std::string GetHostname() {
return ""; // TODO
}
std::vector<std::string> GetNetworkInterfaces() {
return std::vector<std::string>{}; // TODO
}
} // namespace cs

View File

@@ -0,0 +1,34 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include "cscore_cpp.h"
namespace cs {
CS_Source CreateUsbCameraDev(const wpi::Twine& name, int dev,
CS_Status* status) {
*status = CS_INVALID_HANDLE;
return 0;
}
CS_Source CreateUsbCameraPath(const wpi::Twine& name, const wpi::Twine& path,
CS_Status* status) {
*status = CS_INVALID_HANDLE;
return 0;
}
std::string GetUsbCameraPath(CS_Source source, CS_Status* status) {
*status = CS_INVALID_HANDLE;
return std::string{};
}
std::vector<UsbCameraInfo> EnumerateUsbCameras(CS_Status* status) {
*status = CS_INVALID_HANDLE;
return std::vector<UsbCameraInfo>{};
}
} // namespace cs

View File

@@ -0,0 +1,37 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2015-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include "NetworkListener.h"
#include "Log.h"
#include "Notifier.h"
using namespace cs;
class NetworkListener::Thread : public wpi::SafeThread {
public:
void Main();
};
NetworkListener::~NetworkListener() { Stop(); }
void NetworkListener::Start() {
auto thr = m_owner.GetThread();
if (!thr) m_owner.Start();
}
void NetworkListener::Stop() {
// Wake up thread
if (auto thr = m_owner.GetThread()) {
thr->m_active = false;
}
m_owner.Stop();
}
void NetworkListener::Thread::Main() {
// TODO
}

View File

@@ -0,0 +1,20 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include "cscore_cpp.h"
namespace cs {
std::string GetHostname() {
return ""; // TODO
}
std::vector<std::string> GetNetworkInterfaces() {
return std::vector<std::string>{}; // TODO
}
} // namespace cs

View File

@@ -0,0 +1,34 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include "cscore_cpp.h"
namespace cs {
CS_Source CreateUsbCameraDev(const wpi::Twine& name, int dev,
CS_Status* status) {
*status = CS_INVALID_HANDLE;
return 0;
}
CS_Source CreateUsbCameraPath(const wpi::Twine& name, const wpi::Twine& path,
CS_Status* status) {
*status = CS_INVALID_HANDLE;
return 0;
}
std::string GetUsbCameraPath(CS_Source source, CS_Status* status) {
*status = CS_INVALID_HANDLE;
return std::string{};
}
std::vector<UsbCameraInfo> EnumerateUsbCameras(CS_Status* status) {
*status = CS_INVALID_HANDLE;
return std::vector<UsbCameraInfo>{};
}
} // namespace cs