Files
allwpilib/cscore/src/main/native/linux/UsbCameraImpl.hpp

182 lines
5.6 KiB
C++
Raw Normal View History

// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
2016-09-16 17:57:17 -07:00
2025-11-07 19:57:55 -05:00
#ifndef CSCORE_USBCAMERAIMPL_HPP_
#define CSCORE_USBCAMERAIMPL_HPP_
2016-09-16 17:57:17 -07:00
#include <linux/videodev2.h>
2017-08-25 17:48:06 -07:00
#include <atomic>
#include <memory>
#include <string>
#include <string_view>
2017-08-25 17:48:06 -07:00
#include <thread>
#include <utility>
#include <vector>
2025-11-07 19:57:55 -05:00
#include "SourceImpl.hpp"
#include "UsbCameraBuffer.hpp"
#include "UsbCameraProperty.hpp"
2025-11-07 19:56:21 -05:00
#include "wpi/util/SmallVector.hpp"
#include "wpi/util/condition_variable.hpp"
#include "wpi/util/mutex.hpp"
#include "wpi/util/raw_istream.hpp"
#include "wpi/util/raw_ostream.hpp"
2016-09-16 17:57:17 -07:00
namespace cs {
class Notifier;
class Telemetry;
class UsbCameraImpl : public SourceImpl {
2016-09-16 17:57:17 -07:00
public:
UsbCameraImpl(std::string_view name, wpi::Logger& logger, Notifier& notifier,
Telemetry& telemetry, std::string_view path);
~UsbCameraImpl() override;
2016-09-16 17:57:17 -07:00
void Start() override;
2016-09-16 17:57:17 -07:00
// Property functions
void SetProperty(int property, int value, CS_Status* status) override;
void SetStringProperty(int property, std::string_view value,
CS_Status* status) override;
2016-09-16 17:57:17 -07:00
// 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;
2016-09-16 17:57:17 -07:00
void SetPath(std::string_view path, CS_Status* status);
std::string GetPath() const;
// Messages passed to/from camera thread
struct Message {
2016-11-15 23:54:50 -08:00
enum Kind {
kNone = 0,
kCmdSetPath,
kCmdSetMode,
kCmdSetPixelFormat,
kCmdSetResolution,
kCmdSetFPS,
kCmdSetProperty,
kCmdSetPropertyStr,
2018-05-13 17:09:56 -07:00
kNumSinksChanged, // no response
kNumSinksEnabledChanged, // no response
// Responses
kOk,
kError
};
2017-08-25 17:48:06 -07:00
explicit Message(Kind kind_)
: kind(kind_), from(std::this_thread::get_id()) {}
2016-11-15 23:54:50 -08:00
Kind kind;
int data[4];
std::string dataStr;
std::thread::id from;
};
2016-09-16 17:57:17 -07:00
protected:
std::unique_ptr<PropertyImpl> CreateEmptyProperty(
std::string_view 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
2016-09-16 17:57:17 -07:00
void CameraThreadMain();
// Functions used by CameraThreadMain()
void DeviceDisconnect();
void DeviceConnect();
bool DeviceStreamOn();
bool DeviceStreamOff();
void DeviceProcessCommands();
void DeviceSetMode();
void DeviceSetFPS();
void DeviceCacheMode();
2016-12-22 22:08:08 -08:00
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);
CS_StatusValue DeviceCmdSetPath(std::unique_lock<wpi::mutex>& lock,
const Message& msg);
// Property helper functions
2016-12-22 22:08:08 -08:00
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};
unsigned m_capabilities = 0;
// Number of buffers to ask OS for
static constexpr int kNumBuffers = 4;
std::array<UsbCameraBuffer, kNumBuffers> m_buffers;
2016-09-16 17:57:17 -07:00
std::atomic_int m_fd;
std::atomic_int m_command_fd; // for command eventfd
2016-09-16 17:57:17 -07:00
std::atomic_bool m_active; // set to false to terminate thread
2016-09-16 17:57:17 -07:00
std::thread m_cameraThread;
// Quirks
2019-09-30 18:09:39 -04:00
bool m_lifecam_exposure{false}; // Microsoft LifeCam exposure
bool m_ps3eyecam_exposure{false}; // PS3 Eyecam exposure
bool m_ov9281_exposure{false}; // Arducam OV9281 exposure
bool m_picamera{false}; // Raspberry Pi camera
//
// 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;
// Path
std::string m_path;
2016-09-16 17:57:17 -07:00
};
} // namespace cs
2025-11-07 19:57:55 -05:00
#endif // CSCORE_USBCAMERAIMPL_HPP_