libpromeki 1.0.0-alpha
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
ntv2device.h
Go to the documentation of this file.
1
8#pragma once
9
10
11#include <promeki/config.h>
12#if PROMEKI_ENABLE_NTV2
13
14#include <promeki/atomic.h>
15#include <promeki/clock.h>
16#include <promeki/error.h>
17#include <promeki/list.h>
18#include <promeki/map.h>
19#include <promeki/mutex.h>
20#include <promeki/namespace.h>
23#include <promeki/string.h>
24#include <promeki/uniqueptr.h>
26
27class CNTV2Card;
28
29PROMEKI_NAMESPACE_BEGIN
30
31class Ntv2DeviceRegistry;
32class Ntv2MediaIO;
33
73class Ntv2Device {
74 public:
84 CNTV2Card &card();
85
87 Mutex &mutex() { return _mutex; }
88
90 const Ntv2Capabilities &caps() const { return _caps; }
91
95 const String &displayName() const { return _displayName; }
96
103 const String &serial() const { return _serial; }
104
113 const String &key() const { return _key; }
114
116 int deviceIndex() const { return _deviceIndex; }
117
118 // ---- Reservations ----
119
130 Error reserveChannel(int channel, Ntv2MediaIO *owner);
131
138 Error releaseChannel(int channel, Ntv2MediaIO *owner);
139
148 Error reservePorts(const SdiSignalConfig::PortList &ports, Ntv2MediaIO *owner);
149
156 void releasePortsOwnedBy(Ntv2MediaIO *owner);
157
166 Error reserveAudioSystem(int sysIndex, Ntv2MediaIO *owner);
167
169 Error releaseAudioSystem(int sysIndex, Ntv2MediaIO *owner);
170
171 // ---- Reference clock ----
172
183 Error setReference(const VideoReferenceConfig &ref, Ntv2MediaIO *requester);
184
185 // ---- Sample clock ----
186
203 Clock::Ptr sampleClock();
204
205 // ---- Static helpers ----
206
216 static int resolveDeviceIndex(const String &locator);
217
218 // Destructor is public so the registry's UniquePtr can
219 // delete the device; construction stays restricted via
220 // the private default constructor + friend declaration.
221 ~Ntv2Device();
222
223 private:
224 friend class Ntv2DeviceRegistry;
225 friend struct Ntv2DeviceTestAccess;
226
227 // Constructed only through the registry.
228 Ntv2Device();
229
230 Ntv2Device(const Ntv2Device &) = delete;
231 Ntv2Device &operator=(const Ntv2Device &) = delete;
232
233 Error initialize(int deviceIndex, const String &locator, bool retailServices,
234 bool multiFormat);
235 void shutdown(bool retailServices);
236
237 // Returns the first audio system (1-based) currently
238 // reserved by any channel, or 0 when none. No longer
239 // load-bearing for the device clock (which reads the
240 // shared FPGA counter); retained for code paths that
241 // still want to know whether any audio is in flight.
242 int firstReservedAudioSystem() const;
243
244 UniquePtr<CNTV2Card> _card;
245 Ntv2Capabilities _caps;
246 mutable Mutex _mutex;
247
248 String _key;
249 String _displayName;
250 String _serial;
251 int _deviceIndex = -1;
252
253 // Reservation tables. Channels and audio systems use
254 // sparse Map<int, Ntv2MediaIO*> rather than arrays so
255 // the unused range stays cheap.
256 Map<int, Ntv2MediaIO *> _channelOwners;
257 Map<int, Ntv2MediaIO *> _audioSystemOwners;
258
259 // Ports: (kindValue * 100 + index) → owner. Encoded as
260 // int so the same Map shape works for SDI + HDMI without
261 // a custom key type.
262 Map<int, Ntv2MediaIO *> _portOwners;
263
264 // Reference clock state — used for the warn-on-conflict
265 // path. Both fields default to "unset" so the very
266 // first request applies without a spurious warning.
267 bool _refSet = false;
268 int _currentReferenceRaw = 0; // AJA NTV2ReferenceSource as int
269 Ntv2MediaIO *_refOwner = nullptr;
270
271 // Lazily constructed shared clock — see sampleClock().
272 Clock::Ptr _sampleClock;
273};
274
290class Ntv2DeviceRegistry {
291 public:
293 static Ntv2DeviceRegistry &instance();
294
317 Error acquire(int deviceIndex, const String &locator, bool retailServices,
318 bool multiFormat, Ntv2Device **outDevice);
319
326 void release(Ntv2Device *device);
327
335 List<Ntv2Device *> liveDevices() const;
336
337 private:
338 Ntv2DeviceRegistry() = default;
339 ~Ntv2DeviceRegistry();
340
341 Ntv2DeviceRegistry(const Ntv2DeviceRegistry &) = delete;
342 Ntv2DeviceRegistry &operator=(const Ntv2DeviceRegistry &) = delete;
343
344 struct Entry {
345 UniquePtr<Ntv2Device> device;
346 int refCount = 0;
347 bool retailServices = false;
348 };
349
350 mutable Mutex _mutex;
351 Map<String, Entry> _entries;
352};
353
368struct Ntv2DeviceTestAccess {
378 static UniquePtr<Ntv2Device> create(int deviceIndex, const String &displayName,
379 const Ntv2Capabilities &caps);
380
382 static size_t channelOwnerCount(const Ntv2Device &dev);
383
385 static const Ntv2MediaIO *channelOwner(const Ntv2Device &dev, int channel);
386
388 static size_t portOwnerCount(const Ntv2Device &dev);
389
391 static size_t audioSystemOwnerCount(const Ntv2Device &dev);
392
394 static const Ntv2MediaIO *audioSystemOwner(const Ntv2Device &dev, int sysIndex);
395
397 static bool referenceSet(const Ntv2Device &dev);
398
400 static int currentReferenceRaw(const Ntv2Device &dev);
401
403 static const Ntv2MediaIO *referenceOwner(const Ntv2Device &dev);
404};
405
406PROMEKI_NAMESPACE_END
407
408#endif // PROMEKI_ENABLE_NTV2