WPILibC++  unspecified
SourceImpl.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_SOURCEIMPL_H_
9 #define CSCORE_SOURCEIMPL_H_
10 
11 #include <atomic>
12 #include <cstddef>
13 #include <memory>
14 #include <string>
15 #include <vector>
16 
17 #include <llvm/ArrayRef.h>
18 #include <llvm/StringMap.h>
19 #include <llvm/StringRef.h>
20 #include <support/condition_variable.h>
21 #include <support/mutex.h>
22 
23 #include "Frame.h"
24 #include "Image.h"
25 #include "PropertyImpl.h"
26 #include "cscore_cpp.h"
27 
28 namespace cs {
29 
30 class SourceImpl {
31  friend class Frame;
32 
33  public:
34  explicit SourceImpl(llvm::StringRef name);
35  virtual ~SourceImpl();
36  SourceImpl(const SourceImpl& oth) = delete;
37  SourceImpl& operator=(const SourceImpl& oth) = delete;
38 
39  llvm::StringRef GetName() const { return m_name; }
40 
41  void SetDescription(llvm::StringRef description);
42  llvm::StringRef GetDescription(llvm::SmallVectorImpl<char>& buf) const;
43 
44  void SetConnected(bool connected);
45  bool IsConnected() const { return m_connected; }
46 
47  // Functions to keep track of the overall number of sinks connected to this
48  // source. Primarily used by sinks to determine if other sinks are using
49  // the same source.
50  int GetNumSinks() const { return m_numSinks; }
51  void AddSink() {
52  ++m_numSinks;
53  NumSinksChanged();
54  }
55  void RemoveSink() {
56  --m_numSinks;
57  NumSinksChanged();
58  }
59 
60  // Functions to keep track of the number of sinks connected to this source
61  // that are "enabled", in other words, listening for new images. Primarily
62  // used by sources to determine whether they should actually bother trying
63  // to get source frames.
64  int GetNumSinksEnabled() const { return m_numSinksEnabled; }
65 
66  void EnableSink() {
67  ++m_numSinksEnabled;
68  NumSinksEnabledChanged();
69  }
70 
71  void DisableSink() {
72  --m_numSinksEnabled;
73  NumSinksEnabledChanged();
74  }
75 
76  // Gets the current frame time (without waiting for a new one).
77  uint64_t GetCurFrameTime();
78 
79  // Gets the current frame (without waiting for a new one).
80  Frame GetCurFrame();
81 
82  // Blocking function that waits for the next frame and returns it.
83  Frame GetNextFrame();
84 
85  // Blocking function that waits for the next frame and returns it (with
86  // timeout in seconds). If timeout expires, returns empty frame.
87  Frame GetNextFrame(double timeout);
88 
89  // Force a wakeup of all GetNextFrame() callers by sending an empty frame.
90  void Wakeup();
91 
92  // Property functions
93  int GetPropertyIndex(llvm::StringRef name) const;
94  llvm::ArrayRef<int> EnumerateProperties(llvm::SmallVectorImpl<int>& vec,
95  CS_Status* status) const;
96  CS_PropertyKind GetPropertyKind(int property) const;
97  llvm::StringRef GetPropertyName(int property,
99  CS_Status* status) const;
100  int GetProperty(int property, CS_Status* status) const;
101  virtual void SetProperty(int property, int value, CS_Status* status) = 0;
102  int GetPropertyMin(int property, CS_Status* status) const;
103  int GetPropertyMax(int property, CS_Status* status) const;
104  int GetPropertyStep(int property, CS_Status* status) const;
105  int GetPropertyDefault(int property, CS_Status* status) const;
106  llvm::StringRef GetStringProperty(int property,
108  CS_Status* status) const;
109  virtual void SetStringProperty(int property, llvm::StringRef value,
110  CS_Status* status) = 0;
111  std::vector<std::string> GetEnumPropertyChoices(int property,
112  CS_Status* status) const;
113 
114  // Standard common camera properties
115  virtual void SetBrightness(int brightness, CS_Status* status) = 0;
116  virtual int GetBrightness(CS_Status* status) const = 0;
117  virtual void SetWhiteBalanceAuto(CS_Status* status) = 0;
118  virtual void SetWhiteBalanceHoldCurrent(CS_Status* status) = 0;
119  virtual void SetWhiteBalanceManual(int value, CS_Status* status) = 0;
120  virtual void SetExposureAuto(CS_Status* status) = 0;
121  virtual void SetExposureHoldCurrent(CS_Status* status) = 0;
122  virtual void SetExposureManual(int value, CS_Status* status) = 0;
123 
124  // Video mode functions
125  VideoMode GetVideoMode(CS_Status* status) const;
126  virtual bool SetVideoMode(const VideoMode& mode, CS_Status* status) = 0;
127 
128  // These have default implementations but can be overridden for custom
129  // or optimized behavior.
130  virtual bool SetPixelFormat(VideoMode::PixelFormat pixelFormat,
131  CS_Status* status);
132  virtual bool SetResolution(int width, int height, CS_Status* status);
133  virtual bool SetFPS(int fps, CS_Status* status);
134 
135  std::vector<VideoMode> EnumerateVideoModes(CS_Status* status) const;
136 
137  std::unique_ptr<Image> AllocImage(VideoMode::PixelFormat pixelFormat,
138  int width, int height, size_t size);
139 
140  protected:
141  void PutFrame(VideoMode::PixelFormat pixelFormat, int width, int height,
142  llvm::StringRef data, Frame::Time time);
143  void PutFrame(std::unique_ptr<Image> image, Frame::Time time);
144  void PutError(llvm::StringRef msg, Frame::Time time);
145 
146  // Notification functions for corresponding atomics
147  virtual void NumSinksChanged() = 0;
148  virtual void NumSinksEnabledChanged() = 0;
149 
150  std::atomic_int m_numSinks{0};
151  std::atomic_int m_numSinksEnabled{0};
152 
153  protected:
154  // Get a property; must be called with m_mutex held.
155  PropertyImpl* GetProperty(int property) {
156  if (property <= 0 || static_cast<size_t>(property) > m_propertyData.size())
157  return nullptr;
158  return m_propertyData[property - 1].get();
159  }
160  const PropertyImpl* GetProperty(int property) const {
161  if (property <= 0 || static_cast<size_t>(property) > m_propertyData.size())
162  return nullptr;
163  return m_propertyData[property - 1].get();
164  }
165 
166  // Create an "empty" property. This is called by GetPropertyIndex to create
167  // properties that don't exist (as GetPropertyIndex can't fail).
168  // Note: called with m_mutex held.
169  virtual std::unique_ptr<PropertyImpl> CreateEmptyProperty(
170  llvm::StringRef name) const = 0;
171 
172  // Cache properties. Implementations must return false and set status to
173  // CS_SOURCE_IS_DISCONNECTED if not possible to cache.
174  virtual bool CacheProperties(CS_Status* status) const = 0;
175 
176  void NotifyPropertyCreated(int propIndex, PropertyImpl& prop);
177 
178  // Update property value; must be called with m_mutex held.
179  void UpdatePropertyValue(int property, bool setString, int value,
180  llvm::StringRef valueStr);
181 
182  // Cached properties and video modes (protected with m_mutex)
183  mutable std::vector<std::unique_ptr<PropertyImpl>> m_propertyData;
184  mutable llvm::StringMap<int> m_properties;
185  mutable std::vector<VideoMode> m_videoModes;
186  // Current video mode
187  mutable VideoMode m_mode;
188  // Whether CacheProperties() has been successful at least once (and thus
189  // should not be called again)
190  mutable std::atomic_bool m_properties_cached{false};
191 
192  mutable wpi::mutex m_mutex;
193 
194  private:
195  void ReleaseImage(std::unique_ptr<Image> image);
196  std::unique_ptr<Frame::Impl> AllocFrameImpl();
197  void ReleaseFrameImpl(std::unique_ptr<Frame::Impl> data);
198 
199  std::string m_name;
200  std::string m_description;
201 
202  wpi::mutex m_frameMutex;
203  wpi::condition_variable m_frameCv;
204 
205  bool m_destroyFrames{false};
206 
207  // Pool of frames/images to reduce malloc traffic.
208  wpi::mutex m_poolMutex;
209  std::vector<std::unique_ptr<Frame::Impl>> m_framesAvail;
210  std::vector<std::unique_ptr<Image>> m_imagesAvail;
211 
212  std::atomic_bool m_connected{false};
213 
214  // Most recent frame (returned to callers of GetNextFrame)
215  // Access protected by m_frameMutex.
216  // MUST be located below m_poolMutex as the Frame destructor calls back
217  // into SourceImpl::ReleaseImage, which locks m_poolMutex.
218  Frame m_frame;
219 };
220 
221 } // namespace cs
222 
223 #endif // CSCORE_SOURCEIMPL_H_
Definition: SinkImpl.h:19
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: ArrayRef.h:32
Definition: SourceImpl.h:30
Definition: PropertyImpl.h:21
bool IsConnected(NT_Inst inst)
Return whether or not the instance is connected to another node.
Definition: ntcore_cpp.cpp:904
Definition: Frame.h:27
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:42
Video mode.
Definition: cscore_cpp.h:46