mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-20 00:51:42 +00:00
cscore: Separate platform-specific sources (#1387)
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* 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"
|
||||
|
||||
#ifdef __linux__
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <sys/eventfd.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cerrno>
|
||||
#endif
|
||||
|
||||
#include "Log.h"
|
||||
#include "Notifier.h"
|
||||
|
||||
using namespace cs;
|
||||
|
||||
class NetworkListener::Thread : public wpi::SafeThread {
|
||||
public:
|
||||
void Main();
|
||||
|
||||
#ifdef __linux__
|
||||
int m_command_fd = -1;
|
||||
#endif
|
||||
};
|
||||
|
||||
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;
|
||||
#ifdef __linux__
|
||||
if (thr->m_command_fd >= 0) eventfd_write(thr->m_command_fd, 1);
|
||||
#endif
|
||||
}
|
||||
m_owner.Stop();
|
||||
}
|
||||
|
||||
void NetworkListener::Thread::Main() {
|
||||
#ifdef __linux__
|
||||
// Create event socket so we can be shut down
|
||||
m_command_fd = ::eventfd(0, 0);
|
||||
if (m_command_fd < 0) {
|
||||
ERROR(
|
||||
"NetworkListener: could not create eventfd: " << std::strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
// Create netlink socket
|
||||
int sd = ::socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||
if (sd < 0) {
|
||||
ERROR("NetworkListener: could not create socket: " << std::strerror(errno));
|
||||
::close(m_command_fd);
|
||||
m_command_fd = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
// Bind to netlink socket
|
||||
struct sockaddr_nl addr;
|
||||
std::memset(&addr, 0, sizeof(addr));
|
||||
addr.nl_family = AF_NETLINK;
|
||||
addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;
|
||||
if (bind(sd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) < 0) {
|
||||
ERROR("NetworkListener: could not create socket: " << std::strerror(errno));
|
||||
::close(sd);
|
||||
::close(m_command_fd);
|
||||
m_command_fd = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
char buf[4096];
|
||||
|
||||
while (m_active) {
|
||||
// select timeout
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 10;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
// select on applicable read descriptors
|
||||
fd_set readfds;
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(m_command_fd, &readfds);
|
||||
FD_SET(sd, &readfds);
|
||||
int nfds = std::max(m_command_fd, sd) + 1;
|
||||
|
||||
if (::select(nfds, &readfds, nullptr, nullptr, &tv) < 0) {
|
||||
ERROR("NetworkListener: select(): " << std::strerror(errno));
|
||||
break; // XXX: is this the right thing to do here?
|
||||
}
|
||||
|
||||
// Double-check to see if we're shutting down
|
||||
if (!m_active) break;
|
||||
|
||||
if (!FD_ISSET(sd, &readfds)) continue;
|
||||
|
||||
std::memset(&addr, 0, sizeof(addr));
|
||||
struct iovec iov = {buf, sizeof(buf)};
|
||||
struct msghdr msg = {&addr, sizeof(addr), &iov, 1, nullptr, 0, 0};
|
||||
int len = ::recvmsg(sd, &msg, 0);
|
||||
if (len < 0) {
|
||||
if (errno == EWOULDBLOCK || errno == EAGAIN) continue;
|
||||
ERROR(
|
||||
"NetworkListener: could not read netlink: " << std::strerror(errno));
|
||||
break; // XXX: is this the right thing to do here?
|
||||
}
|
||||
if (len == 0) continue; // EOF?
|
||||
for (struct nlmsghdr* nh = reinterpret_cast<struct nlmsghdr*>(buf);
|
||||
NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) {
|
||||
if (nh->nlmsg_type == NLMSG_DONE) break;
|
||||
if (nh->nlmsg_type == RTM_NEWLINK || nh->nlmsg_type == RTM_DELLINK ||
|
||||
nh->nlmsg_type == RTM_NEWADDR || nh->nlmsg_type == RTM_DELADDR) {
|
||||
Notifier::GetInstance().NotifyNetworkInterfacesChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
::close(sd);
|
||||
::close(m_command_fd);
|
||||
m_command_fd = -1;
|
||||
#endif
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* 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. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef CSCORE_USBCAMERABUFFER_H_
|
||||
#define CSCORE_USBCAMERABUFFER_H_
|
||||
|
||||
#ifdef __linux__
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace cs {
|
||||
|
||||
class UsbCameraBuffer {
|
||||
public:
|
||||
UsbCameraBuffer() noexcept : m_data{nullptr}, m_length{0} {}
|
||||
UsbCameraBuffer(UsbCameraBuffer&& other) noexcept : UsbCameraBuffer() {
|
||||
swap(*this, other);
|
||||
}
|
||||
UsbCameraBuffer& operator=(UsbCameraBuffer&& other) noexcept {
|
||||
swap(*this, other);
|
||||
return *this;
|
||||
}
|
||||
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 =
|
||||
mmap(nullptr, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
|
||||
if (m_data == MAP_FAILED) {
|
||||
m_data = nullptr;
|
||||
m_length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
~UsbCameraBuffer() {
|
||||
if (m_data) munmap(m_data, m_length);
|
||||
}
|
||||
#endif
|
||||
|
||||
friend void swap(UsbCameraBuffer& first, UsbCameraBuffer& second) noexcept {
|
||||
using std::swap;
|
||||
swap(first.m_data, second.m_data);
|
||||
swap(first.m_length, second.m_length);
|
||||
}
|
||||
|
||||
void* m_data;
|
||||
size_t m_length;
|
||||
};
|
||||
|
||||
} // namespace cs
|
||||
|
||||
#endif // CSCORE_USBCAMERABUFFER_H_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,185 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* 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. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef CSCORE_USBCAMERAIMPL_H_
|
||||
#define CSCORE_USBCAMERAIMPL_H_
|
||||
|
||||
#ifdef __linux__
|
||||
#include <linux/videodev2.h>
|
||||
#endif
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <wpi/STLExtras.h>
|
||||
#include <wpi/SmallVector.h>
|
||||
#include <wpi/Twine.h>
|
||||
#include <wpi/condition_variable.h>
|
||||
#include <wpi/mutex.h>
|
||||
#include <wpi/raw_istream.h>
|
||||
#include <wpi/raw_ostream.h>
|
||||
|
||||
#include "SourceImpl.h"
|
||||
#include "UsbCameraBuffer.h"
|
||||
#include "UsbCameraProperty.h"
|
||||
|
||||
namespace cs {
|
||||
|
||||
class UsbCameraImpl : public SourceImpl {
|
||||
public:
|
||||
UsbCameraImpl(const wpi::Twine& name, const wpi::Twine& path);
|
||||
~UsbCameraImpl() override;
|
||||
|
||||
void Start();
|
||||
|
||||
// Property functions
|
||||
void SetProperty(int property, int value, CS_Status* status) override;
|
||||
void SetStringProperty(int property, const wpi::Twine& value,
|
||||
CS_Status* status) override;
|
||||
|
||||
// Standard common camera properties
|
||||
void SetBrightness(int brightness, CS_Status* status) override;
|
||||
int GetBrightness(CS_Status* status) const override;
|
||||
void SetWhiteBalanceAuto(CS_Status* status) override;
|
||||
void SetWhiteBalanceHoldCurrent(CS_Status* status) override;
|
||||
void SetWhiteBalanceManual(int value, CS_Status* status) override;
|
||||
void SetExposureAuto(CS_Status* status) override;
|
||||
void SetExposureHoldCurrent(CS_Status* status) override;
|
||||
void SetExposureManual(int value, CS_Status* status) override;
|
||||
|
||||
bool SetVideoMode(const VideoMode& mode, CS_Status* status) override;
|
||||
bool SetPixelFormat(VideoMode::PixelFormat pixelFormat,
|
||||
CS_Status* status) override;
|
||||
bool SetResolution(int width, int height, CS_Status* status) override;
|
||||
bool SetFPS(int fps, CS_Status* status) override;
|
||||
|
||||
void NumSinksChanged() override;
|
||||
void NumSinksEnabledChanged() override;
|
||||
|
||||
std::string GetPath() { return m_path; }
|
||||
|
||||
// Messages passed to/from camera thread
|
||||
struct Message {
|
||||
enum Kind {
|
||||
kNone = 0,
|
||||
kCmdSetMode,
|
||||
kCmdSetPixelFormat,
|
||||
kCmdSetResolution,
|
||||
kCmdSetFPS,
|
||||
kCmdSetProperty,
|
||||
kCmdSetPropertyStr,
|
||||
kNumSinksChanged, // no response
|
||||
kNumSinksEnabledChanged, // no response
|
||||
// Responses
|
||||
kOk,
|
||||
kError
|
||||
};
|
||||
|
||||
explicit Message(Kind kind_)
|
||||
: kind(kind_), from(std::this_thread::get_id()) {}
|
||||
|
||||
Kind kind;
|
||||
int data[4];
|
||||
std::string dataStr;
|
||||
std::thread::id from;
|
||||
};
|
||||
|
||||
protected:
|
||||
std::unique_ptr<PropertyImpl> CreateEmptyProperty(
|
||||
const wpi::Twine& name) const override;
|
||||
|
||||
// Cache properties. Immediately successful if properties are already cached.
|
||||
// If they are not, tries to connect to the camera to do so; returns false and
|
||||
// sets status to CS_SOURCE_IS_DISCONNECTED if that too fails.
|
||||
bool CacheProperties(CS_Status* status) const override;
|
||||
|
||||
private:
|
||||
// Send a message to the camera thread and wait for a response (generic)
|
||||
CS_StatusValue SendAndWait(Message&& msg) const;
|
||||
// Send a message to the camera thread with no response
|
||||
void Send(Message&& msg) const;
|
||||
|
||||
// The camera processing thread
|
||||
void CameraThreadMain();
|
||||
|
||||
// Functions used by CameraThreadMain()
|
||||
void DeviceDisconnect();
|
||||
void DeviceConnect();
|
||||
bool DeviceStreamOn();
|
||||
bool DeviceStreamOff();
|
||||
void DeviceProcessCommands();
|
||||
void DeviceSetMode();
|
||||
void DeviceSetFPS();
|
||||
void DeviceCacheMode();
|
||||
void DeviceCacheProperty(std::unique_ptr<UsbCameraProperty> rawProp);
|
||||
void DeviceCacheProperties();
|
||||
void DeviceCacheVideoModes();
|
||||
|
||||
// Command helper functions
|
||||
CS_StatusValue DeviceProcessCommand(std::unique_lock<wpi::mutex>& lock,
|
||||
const Message& msg);
|
||||
CS_StatusValue DeviceCmdSetMode(std::unique_lock<wpi::mutex>& lock,
|
||||
const Message& msg);
|
||||
CS_StatusValue DeviceCmdSetProperty(std::unique_lock<wpi::mutex>& lock,
|
||||
const Message& msg);
|
||||
|
||||
// Property helper functions
|
||||
int RawToPercentage(const UsbCameraProperty& rawProp, int rawValue);
|
||||
int PercentageToRaw(const UsbCameraProperty& rawProp, int percentValue);
|
||||
|
||||
void SetQuirks();
|
||||
|
||||
//
|
||||
// Variables only used within camera thread
|
||||
//
|
||||
bool m_streaming;
|
||||
bool m_modeSetPixelFormat{false};
|
||||
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;
|
||||
|
||||
// Quirks
|
||||
bool m_lifecam_exposure{false}; // Microsoft LifeCam exposure
|
||||
|
||||
//
|
||||
// Variables protected by m_mutex
|
||||
//
|
||||
|
||||
// Message queues
|
||||
mutable std::vector<Message> m_commands;
|
||||
mutable std::vector<std::pair<std::thread::id, CS_StatusValue>> m_responses;
|
||||
mutable wpi::condition_variable m_responseCv;
|
||||
};
|
||||
|
||||
} // namespace cs
|
||||
|
||||
#endif // CSCORE_USBCAMERAIMPL_H_
|
||||
52
cscore/src/main/native/cpp/UsbCameraImplCommon.cpp
Normal file
52
cscore/src/main/native/cpp/UsbCameraImplCommon.cpp
Normal 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"
|
||||
@@ -1,326 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* 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 "UsbCameraProperty.h"
|
||||
|
||||
#include <wpi/STLExtras.h>
|
||||
#include <wpi/SmallString.h>
|
||||
|
||||
#include "UsbUtil.h"
|
||||
|
||||
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) ||
|
||||
(ctrl_class != V4L2_CTRL_CLASS_USER &&
|
||||
ctrl_class != V4L2_CID_PRIVATE_BASE)) {
|
||||
// Use extended control
|
||||
struct v4l2_ext_control ctrl;
|
||||
struct v4l2_ext_controls ctrls;
|
||||
std::memset(&ctrl, 0, sizeof(ctrl));
|
||||
std::memset(&ctrls, 0, sizeof(ctrls));
|
||||
ctrl.id = id;
|
||||
ctrls.ctrl_class = ctrl_class;
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &ctrl;
|
||||
int rc = DoIoctl(fd, VIDIOC_G_EXT_CTRLS, &ctrls);
|
||||
if (rc < 0) return rc;
|
||||
*value = ctrl.value;
|
||||
} else {
|
||||
// Use normal control
|
||||
struct v4l2_control ctrl;
|
||||
std::memset(&ctrl, 0, sizeof(ctrl));
|
||||
ctrl.id = id;
|
||||
int rc = DoIoctl(fd, VIDIOC_G_CTRL, &ctrl);
|
||||
if (rc < 0) return rc;
|
||||
*value = ctrl.value;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int SetIntCtrlIoctl(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) ||
|
||||
(ctrl_class != V4L2_CTRL_CLASS_USER &&
|
||||
ctrl_class != V4L2_CID_PRIVATE_BASE)) {
|
||||
// Use extended control
|
||||
struct v4l2_ext_control ctrl;
|
||||
struct v4l2_ext_controls ctrls;
|
||||
std::memset(&ctrl, 0, sizeof(ctrl));
|
||||
std::memset(&ctrls, 0, sizeof(ctrls));
|
||||
ctrl.id = id;
|
||||
if (type == V4L2_CTRL_TYPE_INTEGER64)
|
||||
ctrl.value64 = value;
|
||||
else
|
||||
ctrl.value = static_cast<__s32>(value);
|
||||
ctrls.ctrl_class = ctrl_class;
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &ctrl;
|
||||
return DoIoctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
} else {
|
||||
// Use normal control
|
||||
struct v4l2_control ctrl;
|
||||
ctrl.id = id;
|
||||
ctrl.value = static_cast<__s32>(value);
|
||||
return DoIoctl(fd, VIDIOC_S_CTRL, &ctrl);
|
||||
}
|
||||
}
|
||||
|
||||
static int GetStringCtrlIoctl(int fd, int id, int maximum, std::string* value) {
|
||||
struct v4l2_ext_control ctrl;
|
||||
struct v4l2_ext_controls ctrls;
|
||||
std::memset(&ctrl, 0, sizeof(ctrl));
|
||||
std::memset(&ctrls, 0, sizeof(ctrls));
|
||||
ctrl.id = id;
|
||||
ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(id);
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &ctrl;
|
||||
int rc = DoIoctl(fd, VIDIOC_G_EXT_CTRLS, &ctrls);
|
||||
if (rc < 0) {
|
||||
value->clear();
|
||||
return rc;
|
||||
}
|
||||
value->assign(ctrl.string, std::strlen(ctrl.string));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int SetStringCtrlIoctl(int fd, int id, int maximum,
|
||||
const wpi::Twine& value) {
|
||||
wpi::SmallString<64> strBuf, strBuf2;
|
||||
wpi::StringRef str = value.toNullTerminatedStringRef(strBuf);
|
||||
if (str.size() > static_cast<size_t>(maximum)) {
|
||||
// don't know if strBuf was used, just recopy
|
||||
strBuf2 = str.take_front(maximum);
|
||||
str = strBuf2;
|
||||
strBuf2.push_back('\0'); // null terminate
|
||||
}
|
||||
|
||||
struct v4l2_ext_control ctrl;
|
||||
struct v4l2_ext_controls ctrls;
|
||||
std::memset(&ctrl, 0, sizeof(ctrl));
|
||||
std::memset(&ctrls, 0, sizeof(ctrls));
|
||||
ctrl.id = id;
|
||||
ctrl.size = str.size();
|
||||
ctrl.string = const_cast<char*>(str.data());
|
||||
ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(id);
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &ctrl;
|
||||
return DoIoctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
}
|
||||
|
||||
// Removes non-alphanumeric characters and replaces spaces with underscores.
|
||||
// e.g. "Zoom, Absolute" -> "zoom_absolute", "Pan (Absolute)" -> "pan_absolute"
|
||||
static wpi::StringRef NormalizeName(wpi::StringRef name,
|
||||
wpi::SmallVectorImpl<char>& buf) {
|
||||
bool newWord = false;
|
||||
for (auto ch : name) {
|
||||
if (std::isalnum(ch)) {
|
||||
if (newWord) buf.push_back('_');
|
||||
newWord = false;
|
||||
buf.push_back(std::tolower(ch));
|
||||
} else if (!buf.empty()) {
|
||||
newWord = true;
|
||||
}
|
||||
}
|
||||
return wpi::StringRef(buf.data(), buf.size());
|
||||
}
|
||||
|
||||
#ifdef VIDIOC_QUERY_EXT_CTRL
|
||||
UsbCameraProperty::UsbCameraProperty(const struct v4l2_query_ext_ctrl& ctrl)
|
||||
: PropertyImpl(wpi::StringRef{}, CS_PROP_NONE, ctrl.step,
|
||||
ctrl.default_value, 0),
|
||||
id(ctrl.id & V4L2_CTRL_ID_MASK),
|
||||
type(ctrl.type) {
|
||||
hasMinimum = true;
|
||||
minimum = ctrl.minimum;
|
||||
hasMaximum = true;
|
||||
maximum = ctrl.maximum;
|
||||
|
||||
// propKind
|
||||
switch (ctrl.type) {
|
||||
case V4L2_CTRL_TYPE_INTEGER:
|
||||
case V4L2_CTRL_TYPE_INTEGER64:
|
||||
propKind = CS_PROP_INTEGER;
|
||||
break;
|
||||
case V4L2_CTRL_TYPE_BOOLEAN:
|
||||
propKind = CS_PROP_BOOLEAN;
|
||||
break;
|
||||
case V4L2_CTRL_TYPE_INTEGER_MENU:
|
||||
case V4L2_CTRL_TYPE_MENU:
|
||||
propKind = CS_PROP_ENUM;
|
||||
break;
|
||||
case V4L2_CTRL_TYPE_STRING:
|
||||
propKind = CS_PROP_STRING;
|
||||
break;
|
||||
default:
|
||||
return; // others unsupported
|
||||
}
|
||||
|
||||
// name
|
||||
size_t len = 0;
|
||||
while (len < sizeof(ctrl.name) && ctrl.name[len] != '\0') ++len;
|
||||
wpi::SmallString<64> name_buf;
|
||||
name = NormalizeName(wpi::StringRef(ctrl.name, len), name_buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
UsbCameraProperty::UsbCameraProperty(const struct v4l2_queryctrl& ctrl)
|
||||
: PropertyImpl(wpi::StringRef{}, CS_PROP_NONE, ctrl.step,
|
||||
ctrl.default_value, 0),
|
||||
id(ctrl.id & V4L2_CTRL_ID_MASK),
|
||||
type(ctrl.type) {
|
||||
hasMinimum = true;
|
||||
minimum = ctrl.minimum;
|
||||
hasMaximum = true;
|
||||
maximum = ctrl.maximum;
|
||||
|
||||
// propKind
|
||||
switch (ctrl.type) {
|
||||
case V4L2_CTRL_TYPE_INTEGER:
|
||||
case V4L2_CTRL_TYPE_INTEGER64:
|
||||
propKind = CS_PROP_INTEGER;
|
||||
break;
|
||||
case V4L2_CTRL_TYPE_BOOLEAN:
|
||||
propKind = CS_PROP_BOOLEAN;
|
||||
break;
|
||||
case V4L2_CTRL_TYPE_INTEGER_MENU:
|
||||
case V4L2_CTRL_TYPE_MENU:
|
||||
propKind = CS_PROP_ENUM;
|
||||
break;
|
||||
case V4L2_CTRL_TYPE_STRING:
|
||||
propKind = CS_PROP_STRING;
|
||||
break;
|
||||
default:
|
||||
return; // others unsupported
|
||||
}
|
||||
|
||||
// name
|
||||
size_t len = 0;
|
||||
while (len < sizeof(ctrl.name) && ctrl.name[len] != '\0') ++len;
|
||||
wpi::SmallString<64> name_buf;
|
||||
name = NormalizeName(
|
||||
wpi::StringRef(reinterpret_cast<const char*>(ctrl.name), len), name_buf);
|
||||
}
|
||||
|
||||
std::unique_ptr<UsbCameraProperty> UsbCameraProperty::DeviceQuery(int fd,
|
||||
__u32* id) {
|
||||
int rc;
|
||||
std::unique_ptr<UsbCameraProperty> prop;
|
||||
#ifdef VIDIOC_QUERY_EXT_CTRL
|
||||
v4l2_query_ext_ctrl qc_ext;
|
||||
std::memset(&qc_ext, 0, sizeof(qc_ext));
|
||||
qc_ext.id = *id;
|
||||
rc = TryIoctl(fd, VIDIOC_QUERY_EXT_CTRL, &qc_ext);
|
||||
if (rc == 0) {
|
||||
*id = qc_ext.id; // copy back
|
||||
// We don't support array types
|
||||
if (qc_ext.elems > 1 || qc_ext.nr_of_dims > 0) return nullptr;
|
||||
prop = wpi::make_unique<UsbCameraProperty>(qc_ext);
|
||||
}
|
||||
#endif
|
||||
if (!prop) {
|
||||
// Fall back to normal QUERYCTRL
|
||||
struct v4l2_queryctrl qc;
|
||||
std::memset(&qc, 0, sizeof(qc));
|
||||
qc.id = *id;
|
||||
rc = TryIoctl(fd, VIDIOC_QUERYCTRL, &qc);
|
||||
*id = qc.id; // copy back
|
||||
if (rc != 0) return nullptr;
|
||||
prop = wpi::make_unique<UsbCameraProperty>(qc);
|
||||
}
|
||||
|
||||
// Cache enum property choices
|
||||
if (prop->propKind == CS_PROP_ENUM) {
|
||||
prop->enumChoices.resize(prop->maximum + 1);
|
||||
v4l2_querymenu qmenu;
|
||||
std::memset(&qmenu, 0, sizeof(qmenu));
|
||||
qmenu.id = *id;
|
||||
for (int i = prop->minimum; i <= prop->maximum; ++i) {
|
||||
qmenu.index = static_cast<__u32>(i);
|
||||
if (TryIoctl(fd, VIDIOC_QUERYMENU, &qmenu) != 0) continue;
|
||||
prop->enumChoices[i] = reinterpret_cast<const char*>(qmenu.name);
|
||||
}
|
||||
}
|
||||
|
||||
return prop;
|
||||
}
|
||||
|
||||
bool UsbCameraProperty::DeviceGet(std::unique_lock<wpi::mutex>& lock, int fd) {
|
||||
if (fd < 0) return true;
|
||||
unsigned idCopy = id;
|
||||
int rv = 0;
|
||||
|
||||
switch (propKind) {
|
||||
case CS_PROP_BOOLEAN:
|
||||
case CS_PROP_INTEGER:
|
||||
case CS_PROP_ENUM: {
|
||||
int typeCopy = type;
|
||||
int64_t newValue = 0;
|
||||
lock.unlock();
|
||||
rv = GetIntCtrlIoctl(fd, idCopy, typeCopy, &newValue);
|
||||
lock.lock();
|
||||
if (rv >= 0) value = newValue;
|
||||
break;
|
||||
}
|
||||
case CS_PROP_STRING: {
|
||||
int maximumCopy = maximum;
|
||||
std::string newValueStr;
|
||||
lock.unlock();
|
||||
rv = GetStringCtrlIoctl(fd, idCopy, maximumCopy, &newValueStr);
|
||||
lock.lock();
|
||||
if (rv >= 0) valueStr = std::move(newValueStr);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return rv >= 0;
|
||||
}
|
||||
|
||||
bool UsbCameraProperty::DeviceSet(std::unique_lock<wpi::mutex>& lock,
|
||||
int fd) const {
|
||||
// Make a copy of the string as we're about to release the lock
|
||||
wpi::SmallString<128> valueStrCopy{valueStr};
|
||||
return DeviceSet(lock, fd, value, valueStrCopy);
|
||||
}
|
||||
|
||||
bool UsbCameraProperty::DeviceSet(std::unique_lock<wpi::mutex>& lock, int fd,
|
||||
int newValue,
|
||||
const wpi::Twine& newValueStr) const {
|
||||
if (!device || fd < 0) return true;
|
||||
unsigned idCopy = id;
|
||||
int rv = 0;
|
||||
|
||||
switch (propKind) {
|
||||
case CS_PROP_BOOLEAN:
|
||||
case CS_PROP_INTEGER:
|
||||
case CS_PROP_ENUM: {
|
||||
int typeCopy = type;
|
||||
lock.unlock();
|
||||
rv = SetIntCtrlIoctl(fd, idCopy, typeCopy, newValue);
|
||||
lock.lock();
|
||||
break;
|
||||
}
|
||||
case CS_PROP_STRING: {
|
||||
int maximumCopy = maximum;
|
||||
lock.unlock();
|
||||
rv = SetStringCtrlIoctl(fd, idCopy, maximumCopy, newValueStr);
|
||||
lock.lock();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return rv >= 0;
|
||||
}
|
||||
|
||||
#endif // __linux__
|
||||
@@ -1,82 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* 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. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef CSCORE_USBCAMERAPROPERTY_H_
|
||||
#define CSCORE_USBCAMERAPROPERTY_H_
|
||||
|
||||
#ifdef __linux__
|
||||
#include <linux/videodev2.h>
|
||||
#endif
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <wpi/mutex.h>
|
||||
|
||||
#include "PropertyImpl.h"
|
||||
|
||||
namespace cs {
|
||||
|
||||
// Property data
|
||||
class UsbCameraProperty : public PropertyImpl {
|
||||
public:
|
||||
UsbCameraProperty() = default;
|
||||
explicit UsbCameraProperty(const wpi::Twine& name_) : PropertyImpl{name_} {}
|
||||
|
||||
// Software property constructor
|
||||
UsbCameraProperty(const wpi::Twine& name_, unsigned id_,
|
||||
CS_PropertyKind kind_, int minimum_, int maximum_,
|
||||
int step_, int defaultValue_, int value_)
|
||||
: PropertyImpl(name_, kind_, minimum_, maximum_, step_, defaultValue_,
|
||||
value_),
|
||||
device{false},
|
||||
id{id_} {}
|
||||
|
||||
// Normalized property constructor
|
||||
UsbCameraProperty(const wpi::Twine& name_, int rawIndex_,
|
||||
const UsbCameraProperty& rawProp, int defaultValue_,
|
||||
int value_)
|
||||
: PropertyImpl(name_, rawProp.propKind, 1, defaultValue_, value_),
|
||||
percentage{true},
|
||||
propPair{rawIndex_},
|
||||
id{rawProp.id},
|
||||
type{rawProp.type} {
|
||||
hasMinimum = true;
|
||||
minimum = 0;
|
||||
hasMaximum = true;
|
||||
maximum = 100;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
#ifdef VIDIOC_QUERY_EXT_CTRL
|
||||
explicit UsbCameraProperty(const struct v4l2_query_ext_ctrl& ctrl);
|
||||
#endif
|
||||
explicit UsbCameraProperty(const struct v4l2_queryctrl& ctrl);
|
||||
|
||||
static std::unique_ptr<UsbCameraProperty> DeviceQuery(int fd, __u32* id);
|
||||
|
||||
bool DeviceGet(std::unique_lock<wpi::mutex>& lock, int fd);
|
||||
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};
|
||||
|
||||
// If this is a percentage (rather than raw) property
|
||||
bool percentage{false};
|
||||
|
||||
// If not 0, index of corresponding raw/percentage property
|
||||
int propPair{0};
|
||||
|
||||
unsigned id{0}; // implementation-level id
|
||||
int type{0}; // implementation type, not CS_PropertyKind!
|
||||
};
|
||||
|
||||
} // namespace cs
|
||||
|
||||
#endif // CSCORE_USBCAMERAPROPERTY_H_
|
||||
@@ -1,166 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* 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 "UsbUtil.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef __linux__
|
||||
#include <libgen.h>
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#include <wpi/Format.h>
|
||||
#include <wpi/SmallString.h>
|
||||
#include <wpi/raw_istream.h>
|
||||
#include <wpi/raw_ostream.h>
|
||||
|
||||
#include "Log.h"
|
||||
|
||||
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);
|
||||
if (fd < 0) return wpi::StringRef{};
|
||||
|
||||
wpi::raw_svector_ostream os{buf};
|
||||
wpi::raw_fd_istream is{fd, true};
|
||||
|
||||
// build vendor and product 4-char hex strings
|
||||
wpi::SmallString<16> vendorStr, productStr;
|
||||
wpi::raw_svector_ostream vendorOs{vendorStr}, productOs{productStr};
|
||||
vendorOs << wpi::format_hex_no_prefix(vendor, 4);
|
||||
productOs << wpi::format_hex_no_prefix(product, 4);
|
||||
|
||||
// scan file
|
||||
wpi::SmallString<128> lineBuf;
|
||||
bool foundVendor = false;
|
||||
for (;;) {
|
||||
auto line = is.getline(lineBuf, 4096);
|
||||
if (is.has_error()) break;
|
||||
|
||||
if (line.empty()) continue;
|
||||
|
||||
// look for vendor at start of line
|
||||
if (line.startswith(vendorStr)) {
|
||||
foundVendor = true;
|
||||
os << line.substr(5).trim() << ' ';
|
||||
continue;
|
||||
}
|
||||
|
||||
if (foundVendor) {
|
||||
// next vendor, but didn't match product?
|
||||
if (line[0] != '\t') {
|
||||
os << "Unknown";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
// look for product
|
||||
if (line.substr(1).startswith(productStr)) {
|
||||
os << line.substr(6).trim();
|
||||
return os.str();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return wpi::StringRef{};
|
||||
}
|
||||
|
||||
wpi::StringRef GetUsbNameFromId(int vendor, int product,
|
||||
wpi::SmallVectorImpl<char>& buf) {
|
||||
// try reading usb.ids
|
||||
wpi::StringRef rv = GetUsbNameFromFile(vendor, product, buf);
|
||||
if (!rv.empty()) return rv;
|
||||
|
||||
// Fall back to internal database
|
||||
wpi::raw_svector_ostream os{buf};
|
||||
switch (vendor) {
|
||||
case 0x046d:
|
||||
os << "Logitech, Inc. ";
|
||||
switch (product) {
|
||||
case 0x0802:
|
||||
os << "Webcam C200";
|
||||
break;
|
||||
case 0x0804:
|
||||
os << "Webcam C250";
|
||||
break;
|
||||
case 0x0805:
|
||||
os << "Webcam C300";
|
||||
break;
|
||||
case 0x0807:
|
||||
os << "Webcam B500";
|
||||
break;
|
||||
case 0x0808:
|
||||
os << "Webcam C600";
|
||||
break;
|
||||
case 0x0809:
|
||||
os << "Webcam Pro 9000";
|
||||
break;
|
||||
case 0x080a:
|
||||
os << "Portable Webcam C905";
|
||||
break;
|
||||
case 0x080f:
|
||||
os << "Webcam C120";
|
||||
break;
|
||||
case 0x0819:
|
||||
os << "Webcam C210";
|
||||
break;
|
||||
case 0x081b:
|
||||
os << "Webcam C310";
|
||||
break;
|
||||
case 0x081d:
|
||||
os << "HD Webcam C510";
|
||||
break;
|
||||
case 0x0821:
|
||||
os << "HD Webcam C910";
|
||||
break;
|
||||
case 0x0825:
|
||||
os << "Webcam C270";
|
||||
break;
|
||||
case 0x0826:
|
||||
os << "HD Webcam C525";
|
||||
break;
|
||||
case 0x0828:
|
||||
os << "HD Webcam B990";
|
||||
break;
|
||||
case 0x082b:
|
||||
os << "Webcam C170";
|
||||
break;
|
||||
case 0x082d:
|
||||
os << "HD Pro Webcam C920";
|
||||
break;
|
||||
case 0x0836:
|
||||
os << "B525 HD Webcam";
|
||||
break;
|
||||
case 0x0843:
|
||||
os << "Webcam C930e";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return os.str();
|
||||
}
|
||||
|
||||
int CheckedIoctl(int fd, unsigned long req, void* data, // NOLINT(runtime/int)
|
||||
const char* name, const char* file, int line, bool quiet) {
|
||||
int retval = ioctl(fd, req, data);
|
||||
if (!quiet && retval < 0) {
|
||||
wpi::SmallString<64> localfile{file};
|
||||
localfile.push_back('\0');
|
||||
ERROR("ioctl " << name << " failed at " << basename(localfile.data()) << ":"
|
||||
<< line << ": " << std::strerror(errno));
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
#endif // __linux__
|
||||
|
||||
} // namespace cs
|
||||
@@ -1,35 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* 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. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef CSCORE_USBUTIL_H_
|
||||
#define CSCORE_USBUTIL_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <wpi/SmallVector.h>
|
||||
#include <wpi/StringRef.h>
|
||||
|
||||
namespace cs {
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
wpi::StringRef GetUsbNameFromId(int vendor, int product,
|
||||
wpi::SmallVectorImpl<char>& buf);
|
||||
|
||||
int CheckedIoctl(int fd, unsigned long req, void* data, // NOLINT(runtime/int)
|
||||
const char* name, const char* file, int line, bool quiet);
|
||||
|
||||
#define DoIoctl(fd, req, data) \
|
||||
CheckedIoctl(fd, req, data, #req, __FILE__, __LINE__, false)
|
||||
#define TryIoctl(fd, req, data) \
|
||||
CheckedIoctl(fd, req, data, #req, __FILE__, __LINE__, true)
|
||||
|
||||
#endif // __linux__
|
||||
|
||||
} // namespace cs
|
||||
|
||||
#endif // CSCORE_USBUTIL_H_
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user