11#include <promeki/config.h>
12#if PROMEKI_ENABLE_NTV2
36PROMEKI_NAMESPACE_BEGIN
73class Ntv2MediaIO :
public DedicatedThreadMediaIO {
74 PROMEKI_OBJECT(Ntv2MediaIO, DedicatedThreadMediaIO)
77 static inline const MediaIOStats::ID StatsFramesReceived{
"Ntv2FramesReceived"};
79 static inline const MediaIOStats::ID StatsFramesDropped{
"Ntv2FramesDropped"};
81 static inline const MediaIOStats::ID StatsAudioBytesReceived{
"Ntv2AudioBytesReceived"};
83 static inline const MediaIOStats::ID StatsFramesPlayed{
"Ntv2FramesPlayed"};
88 static inline const MediaIOStats::ID StatsFramesDroppedSink{
"Ntv2FramesDroppedSink"};
96 static inline const MediaIOStats::ID StatsAncPacketsReceived{
"Ntv2AncPacketsReceived"};
101 static inline const MediaIOStats::ID StatsAncPacketsSent{
"Ntv2AncPacketsSent"};
112 static inline const MediaIOStats::ID StatsSignalLoss{
"Ntv2SignalLoss"};
118 static inline const MediaIOStats::ID StatsSignalReacquired{
"Ntv2SignalReacquired"};
120 static inline const MediaIOStats::ID StatsPacingTicksOnTime{
"Ntv2PacingTicksOnTime"};
122 static inline const MediaIOStats::ID StatsPacingTicksLate{
"Ntv2PacingTicksLate"};
124 static inline const MediaIOStats::ID StatsPacingTicksSkipped{
"Ntv2PacingTicksSkipped"};
126 static inline const MediaIOStats::ID StatsPacingReanchors{
"Ntv2PacingReanchors"};
140 static inline const MediaIOStats::ID StatsDeviceLost{
"Ntv2DeviceLost"};
143 Ntv2MediaIO(ObjectBase *parent =
nullptr);
146 ~Ntv2MediaIO()
override;
167 Error proposeInput(
const MediaDesc &offered, MediaDesc *preferred)
const override;
170 Error executeCmd(MediaIOCommandOpen &cmd)
override;
171 Error executeCmd(MediaIOCommandClose &cmd)
override;
172 Error executeCmd(MediaIOCommandRead &cmd)
override;
173 Error executeCmd(MediaIOCommandWrite &cmd)
override;
174 Error executeCmd(MediaIOCommandStats &cmd)
override;
194 Error executeCmd(MediaIOCommandSetClock &cmd)
override;
195 void cancelBlockingWork()
override;
198 Error openSource(
const MediaIO::Config &cfg,
const MediaDesc &md);
202 Error openSink(
const MediaIO::Config &cfg,
const MediaDesc &md);
224 Error routeSdiInput(
const Ntv2Routing::Config &routingCfg);
225 Error routeSdiOutput(
const Ntv2Routing::Config &routingCfg);
240 Error applySinkVpid(
const MediaIO::Config &cfg,
const ImageDesc &md);
252 void pollSourceVpid();
260 class CaptureWorker :
public Thread {
262 CaptureWorker(Ntv2MediaIO *owner) : _owner(owner) {}
265 void run()
override { _owner->captureLoop(); }
271 class PlayoutWorker :
public Thread {
273 PlayoutWorker(Ntv2MediaIO *owner) : _owner(owner) {}
276 void run()
override { _owner->playoutLoop(); }
285 Ntv2Device *_device =
nullptr;
294 int _audioSystem = 0;
298 bool _sinkMode =
false;
302 List<VideoPortRef> _reservedPorts;
308 CaptureWorker _captureWorker{
this};
309 Atomic<bool> _stopFlag{
false};
310 Atomic<bool> _readCancelled{
false};
311 static constexpr int VideoQueueDepth = 2;
312 Queue<Frame> _videoQueue;
323 PlayoutWorker _playoutWorker{
this};
324 static constexpr int WriteQueueDepth = 4;
325 Queue<Frame> _writeQueue;
332 bool _ancEnabled =
false;
337 uint16_t _f2StartLine = 0;
343 int _vbiTimeoutMs = 50;
350 int _signalPollIntervalVbi = 15;
360 bool _signalPresent =
true;
372 bool _vpidEnabled =
true;
373 int _vpidLastTransfer = 0;
374 int _vpidLastColorimetry = 0;
375 int _vpidLastRange = 0;
376 bool _vpidLastValid =
false;
379 ImageDesc _imageDesc;
380 FrameRate _frameRate;
381 AudioDesc _audioDesc;
386 Clock::Ptr _sourceClock;
395 PacingGate _paceGate;
400 Atomic<bool> _paceClockExternal{
false};
403 Atomic<int64_t> _framesReceived{0};
404 Atomic<int64_t> _framesDropped{0};
405 Atomic<int64_t> _audioBytesReceived{0};
406 Atomic<int64_t> _framesPlayed{0};
407 Atomic<int64_t> _framesDroppedSink{0};
408 Atomic<int64_t> _ancPacketsReceived{0};
409 Atomic<int64_t> _ancPacketsSent{0};
410 Atomic<int64_t> _signalLossCount{0};
411 Atomic<int64_t> _signalReacquiredCount{0};
412 Atomic<int64_t> _deviceLostCount{0};
423 Atomic<bool> _deviceLost{
false};
443class Ntv2Factory :
public MediaIOFactory {
445 Ntv2Factory() =
default;
447 String name()
const override {
return String(
"Ntv2"); }
448 String displayName()
const override {
return String(
"AJA NTV2"); }
449 String description()
const override {
450 return String(
"AJA NTV2 SDI / HDMI capture and playout via libajantv2");
453 bool canBeSource()
const override {
return true; }
454 bool canBeSink()
const override {
return true; }
456 StringList schemes()
const override {
return {String(
"ntv2")}; }
457 bool canHandlePath(
const String &path)
const override;
458 StringList enumerate()
const override;
459 Error urlToConfig(
const Url &url, Config *outConfig)
const override;
461 Config::SpecMap configSpecs()
const override;
463 MediaIO *create(
const Config &config, ObjectBase *parent =
nullptr)
const override;