WPILibC++  unspecified
UsbCameraImpl.h
1 /*----------------------------------------------------------------------------*/
2 /* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
3 /* Open Source Software - may be modified and shared by FRC teams. The code */
4 /* must be accompanied by the FIRST BSD license file in the root directory of */
5 /* the project. */
6 /*----------------------------------------------------------------------------*/
7 
8 #ifndef CSCORE_USBCAMERAIMPL_H_
9 #define CSCORE_USBCAMERAIMPL_H_
10 
11 #ifdef __linux__
12 #include <linux/videodev2.h>
13 #endif
14 
15 #include <atomic>
16 #include <memory>
17 #include <string>
18 #include <thread>
19 #include <utility>
20 #include <vector>
21 
22 #include <wpi/STLExtras.h>
23 #include <wpi/SmallVector.h>
24 #include <wpi/condition_variable.h>
25 #include <wpi/mutex.h>
26 #include <wpi/raw_istream.h>
27 #include <wpi/raw_ostream.h>
28 
29 #include "SourceImpl.h"
30 #include "UsbCameraBuffer.h"
31 #include "UsbCameraProperty.h"
32 
33 namespace cs {
34 
35 class UsbCameraImpl : public SourceImpl {
36  public:
38  ~UsbCameraImpl() override;
39 
40  void Start();
41 
42  // Property functions
43  void SetProperty(int property, int value, CS_Status* status) override;
44  void SetStringProperty(int property, wpi::StringRef value,
45  CS_Status* status) override;
46 
47  // Standard common camera properties
48  void SetBrightness(int brightness, CS_Status* status) override;
49  int GetBrightness(CS_Status* status) const override;
50  void SetWhiteBalanceAuto(CS_Status* status) override;
51  void SetWhiteBalanceHoldCurrent(CS_Status* status) override;
52  void SetWhiteBalanceManual(int value, CS_Status* status) override;
53  void SetExposureAuto(CS_Status* status) override;
54  void SetExposureHoldCurrent(CS_Status* status) override;
55  void SetExposureManual(int value, CS_Status* status) override;
56 
57  bool SetVideoMode(const VideoMode& mode, CS_Status* status) override;
58  bool SetPixelFormat(VideoMode::PixelFormat pixelFormat,
59  CS_Status* status) override;
60  bool SetResolution(int width, int height, CS_Status* status) override;
61  bool SetFPS(int fps, CS_Status* status) override;
62 
63  void NumSinksChanged() override;
64  void NumSinksEnabledChanged() override;
65 
66  std::string GetPath() { return m_path; }
67 
68  // Messages passed to/from camera thread
69  struct Message {
70  enum Kind {
71  kNone = 0,
72  kCmdSetMode,
73  kCmdSetPixelFormat,
74  kCmdSetResolution,
75  kCmdSetFPS,
76  kCmdSetProperty,
77  kCmdSetPropertyStr,
78  kNumSinksChanged, // no response
79  kNumSinksEnabledChanged, // no response
80  // Responses
81  kOk,
82  kError
83  };
84 
85  explicit Message(Kind kind_)
86  : kind(kind_), from(std::this_thread::get_id()) {}
87 
88  Kind kind;
89  int data[4];
90  std::string dataStr;
91  std::thread::id from;
92  };
93 
94  protected:
95  std::unique_ptr<PropertyImpl> CreateEmptyProperty(
96  wpi::StringRef name) const override;
97 
98  // Cache properties. Immediately successful if properties are already cached.
99  // If they are not, tries to connect to the camera to do so; returns false and
100  // sets status to CS_SOURCE_IS_DISCONNECTED if that too fails.
101  bool CacheProperties(CS_Status* status) const override;
102 
103  private:
104  // Send a message to the camera thread and wait for a response (generic)
105  CS_StatusValue SendAndWait(Message&& msg) const;
106  // Send a message to the camera thread with no response
107  void Send(Message&& msg) const;
108 
109  // The camera processing thread
110  void CameraThreadMain();
111 
112  // Functions used by CameraThreadMain()
113  void DeviceDisconnect();
114  void DeviceConnect();
115  bool DeviceStreamOn();
116  bool DeviceStreamOff();
117  void DeviceProcessCommands();
118  void DeviceSetMode();
119  void DeviceSetFPS();
120  void DeviceCacheMode();
121  void DeviceCacheProperty(std::unique_ptr<UsbCameraProperty> rawProp);
122  void DeviceCacheProperties();
123  void DeviceCacheVideoModes();
124 
125  // Command helper functions
126  CS_StatusValue DeviceProcessCommand(std::unique_lock<wpi::mutex>& lock,
127  const Message& msg);
128  CS_StatusValue DeviceCmdSetMode(std::unique_lock<wpi::mutex>& lock,
129  const Message& msg);
130  CS_StatusValue DeviceCmdSetProperty(std::unique_lock<wpi::mutex>& lock,
131  const Message& msg);
132 
133  // Property helper functions
134  int RawToPercentage(const UsbCameraProperty& rawProp, int rawValue);
135  int PercentageToRaw(const UsbCameraProperty& rawProp, int percentValue);
136 
137  void SetQuirks();
138 
139  //
140  // Variables only used within camera thread
141  //
142  bool m_streaming;
143  bool m_modeSetPixelFormat{false};
144  bool m_modeSetResolution{false};
145  bool m_modeSetFPS{false};
146 #ifdef __linux__
147  unsigned m_capabilities = 0;
148 #endif
149  // Number of buffers to ask OS for
150  static constexpr int kNumBuffers = 4;
151 #ifdef __linux__
152  std::array<UsbCameraBuffer, kNumBuffers> m_buffers;
153 #endif
154 
155  //
156  // Path never changes, so not protected by mutex.
157  //
158  std::string m_path;
159 
160 #ifdef __linux__
161  std::atomic_int m_fd;
162  std::atomic_int m_command_fd; // for command eventfd
163 #endif
164 
165  std::atomic_bool m_active; // set to false to terminate thread
166  std::thread m_cameraThread;
167 
168  // Quirks
169  bool m_lifecam_exposure{false}; // Microsoft LifeCam exposure
170 
171  //
172  // Variables protected by m_mutex
173  //
174 
175  // Message queues
176  mutable std::vector<Message> m_commands;
177  mutable std::vector<std::pair<std::thread::id, CS_StatusValue>> m_responses;
178  mutable wpi::condition_variable m_responseCv;
179 };
180 
181 } // namespace cs
182 
183 #endif // CSCORE_USBCAMERAIMPL_H_
Definition: CvSourceImpl.h:19
Definition: SourceImpl.h:30
Definition: UsbCameraProperty.h:24
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
Definition: UsbCameraImpl.h:35
Definition: UsbCameraImpl.h:69
Video mode.
Definition: cscore_cpp.h:46