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