2020-12-26 14:12:05 -08:00
|
|
|
// 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-11-28 00:22:15 -08:00
|
|
|
|
2017-08-25 17:48:06 -07:00
|
|
|
#ifndef CSCORE_HTTPCAMERAIMPL_H_
|
|
|
|
|
#define CSCORE_HTTPCAMERAIMPL_H_
|
2016-11-28 00:22:15 -08:00
|
|
|
|
|
|
|
|
#include <atomic>
|
|
|
|
|
#include <functional>
|
|
|
|
|
#include <initializer_list>
|
2017-08-25 17:48:06 -07:00
|
|
|
#include <memory>
|
2022-10-15 16:33:14 -07:00
|
|
|
#include <span>
|
2017-08-25 17:48:06 -07:00
|
|
|
#include <string>
|
2021-06-06 16:13:58 -07:00
|
|
|
#include <string_view>
|
2016-11-28 00:22:15 -08:00
|
|
|
#include <thread>
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
2025-11-07 19:56:21 -05:00
|
|
|
#include "wpi/util/StringMap.hpp"
|
|
|
|
|
#include "wpi/util/condition_variable.hpp"
|
|
|
|
|
#include "wpi/util/raw_istream.hpp"
|
|
|
|
|
#include "wpi/net/HttpUtil.hpp"
|
2016-11-28 00:22:15 -08:00
|
|
|
|
2025-11-07 19:56:21 -05:00
|
|
|
#include "SourceImpl.hpp"
|
|
|
|
|
#include "wpi/cs/cscore_cpp.hpp"
|
2016-11-28 00:22:15 -08:00
|
|
|
|
|
|
|
|
namespace cs {
|
|
|
|
|
|
|
|
|
|
class HttpCameraImpl : public SourceImpl {
|
|
|
|
|
public:
|
2021-06-06 16:13:58 -07:00
|
|
|
HttpCameraImpl(std::string_view name, CS_HttpCameraKind kind,
|
2018-10-31 20:22:58 -07:00
|
|
|
wpi::Logger& logger, Notifier& notifier, Telemetry& telemetry);
|
2016-11-28 00:22:15 -08:00
|
|
|
~HttpCameraImpl() override;
|
|
|
|
|
|
2018-11-06 19:42:39 -08:00
|
|
|
void Start() override;
|
2016-11-28 00:22:15 -08:00
|
|
|
|
|
|
|
|
// Property functions
|
|
|
|
|
void SetProperty(int property, int value, CS_Status* status) override;
|
2021-06-06 16:13:58 -07:00
|
|
|
void SetStringProperty(int property, std::string_view value,
|
2016-11-28 00:22:15 -08:00
|
|
|
CS_Status* status) override;
|
|
|
|
|
|
2017-01-01 14:24:13 -08: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;
|
|
|
|
|
|
2016-11-28 00:22:15 -08:00
|
|
|
bool SetVideoMode(const VideoMode& mode, CS_Status* status) override;
|
|
|
|
|
|
|
|
|
|
void NumSinksChanged() override;
|
|
|
|
|
void NumSinksEnabledChanged() override;
|
|
|
|
|
|
|
|
|
|
CS_HttpCameraKind GetKind() const;
|
2022-10-15 16:33:14 -07:00
|
|
|
bool SetUrls(std::span<const std::string> urls, CS_Status* status);
|
2016-11-28 00:22:15 -08:00
|
|
|
std::vector<std::string> GetUrls() const;
|
|
|
|
|
|
|
|
|
|
// Property data
|
|
|
|
|
class PropertyData : public PropertyImpl {
|
|
|
|
|
public:
|
|
|
|
|
PropertyData() = default;
|
2021-06-06 16:13:58 -07:00
|
|
|
explicit PropertyData(std::string_view name_) : PropertyImpl{name_} {}
|
|
|
|
|
PropertyData(std::string_view name_, std::string_view httpParam_,
|
2016-11-28 00:22:15 -08:00
|
|
|
bool viaSettings_, CS_PropertyKind kind_, int minimum_,
|
|
|
|
|
int maximum_, int step_, int defaultValue_, int value_)
|
|
|
|
|
: PropertyImpl(name_, kind_, step_, defaultValue_, value_),
|
|
|
|
|
viaSettings(viaSettings_),
|
2021-06-06 16:13:58 -07:00
|
|
|
httpParam(httpParam_) {
|
2016-11-28 00:22:15 -08:00
|
|
|
hasMinimum = true;
|
|
|
|
|
minimum = minimum_;
|
|
|
|
|
hasMaximum = true;
|
|
|
|
|
maximum = maximum_;
|
|
|
|
|
}
|
|
|
|
|
~PropertyData() override = default;
|
|
|
|
|
|
|
|
|
|
bool viaSettings{false};
|
|
|
|
|
std::string httpParam;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
std::unique_ptr<PropertyImpl> CreateEmptyProperty(
|
2021-06-06 16:13:58 -07:00
|
|
|
std::string_view name) const override;
|
2016-11-28 00:22:15 -08:00
|
|
|
|
|
|
|
|
bool CacheProperties(CS_Status* status) const override;
|
|
|
|
|
|
2021-06-06 16:13:58 -07:00
|
|
|
void CreateProperty(std::string_view name, std::string_view httpParam,
|
2016-11-28 00:22:15 -08:00
|
|
|
bool viaSettings, CS_PropertyKind kind, int minimum,
|
|
|
|
|
int maximum, int step, int defaultValue, int value) const;
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
2021-06-06 16:13:58 -07:00
|
|
|
void CreateEnumProperty(std::string_view name, std::string_view httpParam,
|
2016-11-28 00:22:15 -08:00
|
|
|
bool viaSettings, int defaultValue, int value,
|
|
|
|
|
std::initializer_list<T> choices) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
// The camera streaming thread
|
|
|
|
|
void StreamThreadMain();
|
|
|
|
|
|
|
|
|
|
// Functions used by StreamThreadMain()
|
2017-08-25 18:10:47 -07:00
|
|
|
wpi::HttpConnection* DeviceStreamConnect(
|
2018-04-29 23:33:19 -07:00
|
|
|
wpi::SmallVectorImpl<char>& boundary);
|
2021-06-06 16:13:58 -07:00
|
|
|
void DeviceStream(wpi::raw_istream& is, std::string_view boundary);
|
2016-11-28 00:22:15 -08:00
|
|
|
bool DeviceStreamFrame(wpi::raw_istream& is, std::string& imageBuf);
|
|
|
|
|
|
|
|
|
|
// The camera settings thread
|
|
|
|
|
void SettingsThreadMain();
|
2017-08-25 18:10:47 -07:00
|
|
|
void DeviceSendSettings(wpi::HttpRequest& req);
|
2016-11-28 00:22:15 -08:00
|
|
|
|
2018-12-29 14:08:45 -08:00
|
|
|
// The monitor thread
|
|
|
|
|
void MonitorThreadMain();
|
|
|
|
|
|
2016-11-28 00:22:15 -08:00
|
|
|
std::atomic_bool m_connected{false};
|
|
|
|
|
std::atomic_bool m_active{true}; // set to false to terminate thread
|
|
|
|
|
std::thread m_streamThread;
|
|
|
|
|
std::thread m_settingsThread;
|
2018-12-29 14:08:45 -08:00
|
|
|
std::thread m_monitorThread;
|
2016-11-28 00:22:15 -08:00
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Variables protected by m_mutex
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
// The camera connections
|
2017-08-25 18:10:47 -07:00
|
|
|
std::unique_ptr<wpi::HttpConnection> m_streamConn;
|
|
|
|
|
std::unique_ptr<wpi::HttpConnection> m_settingsConn;
|
2016-11-28 00:22:15 -08:00
|
|
|
|
|
|
|
|
CS_HttpCameraKind m_kind;
|
|
|
|
|
|
2017-08-25 18:10:47 -07:00
|
|
|
std::vector<wpi::HttpLocation> m_locations;
|
2017-08-25 17:48:06 -07:00
|
|
|
size_t m_nextLocation{0};
|
2016-11-28 00:22:15 -08:00
|
|
|
int m_prefLocation{-1}; // preferred location
|
|
|
|
|
|
2018-12-29 14:08:45 -08:00
|
|
|
std::atomic_int m_frameCount{0};
|
|
|
|
|
|
2017-11-13 09:51:26 -08:00
|
|
|
wpi::condition_variable m_sinkEnabledCond;
|
2016-11-28 00:22:15 -08:00
|
|
|
|
2024-10-22 08:33:23 -06:00
|
|
|
wpi::StringMap<std::string> m_settings;
|
2017-11-13 09:51:26 -08:00
|
|
|
wpi::condition_variable m_settingsCond;
|
2016-11-28 00:22:15 -08:00
|
|
|
|
2024-10-22 08:33:23 -06:00
|
|
|
wpi::StringMap<std::string> m_streamSettings;
|
2016-11-28 00:22:15 -08:00
|
|
|
std::atomic_bool m_streamSettingsUpdated{false};
|
2018-12-29 14:08:45 -08:00
|
|
|
|
|
|
|
|
wpi::condition_variable m_monitorCond;
|
2016-11-28 00:22:15 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class AxisCameraImpl : public HttpCameraImpl {
|
|
|
|
|
public:
|
2021-06-06 16:13:58 -07:00
|
|
|
AxisCameraImpl(std::string_view name, wpi::Logger& logger, Notifier& notifier,
|
|
|
|
|
Telemetry& telemetry)
|
2018-10-31 20:22:58 -07:00
|
|
|
: HttpCameraImpl{name, CS_HTTP_AXIS, logger, notifier, telemetry} {}
|
2016-11-28 00:22:15 -08:00
|
|
|
#if 0
|
|
|
|
|
void SetProperty(int property, int value, CS_Status* status) override;
|
2021-06-06 16:13:58 -07:00
|
|
|
void SetStringProperty(int property, std::string_view value,
|
2016-11-28 00:22:15 -08:00
|
|
|
CS_Status* status) override;
|
|
|
|
|
#endif
|
|
|
|
|
protected:
|
|
|
|
|
bool CacheProperties(CS_Status* status) const override;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
} // namespace cs
|
|
|
|
|
|
2017-08-25 17:48:06 -07:00
|
|
|
#endif // CSCORE_HTTPCAMERAIMPL_H_
|