11#include <promeki/config.h>
12#if PROMEKI_ENABLE_PROAV
33PROMEKI_NAMESPACE_BEGIN
97 enum class InputOverflowPolicy {
124 FrameNumber frameIndex{0};
128 FrameCount framesRepeated{0};
132 FrameCount framesDropped{0};
145 explicit FrameSync(
const String &name);
150 FrameSync(
const FrameSync &) =
delete;
151 FrameSync &operator=(
const FrameSync &) =
delete;
152 FrameSync(FrameSync &&) =
delete;
153 FrameSync &operator=(FrameSync &&) =
delete;
156 void setName(
const String &name) { _name = name; }
159 const String &name()
const {
return _name; }
168 void setTargetFrameRate(
const FrameRate &fps);
171 const FrameRate &targetFrameRate()
const {
return _targetFrameRate; }
180 void setTargetAudioDesc(
const AudioDesc &desc);
183 const AudioDesc &targetAudioDesc()
const {
return _targetAudioDesc; }
192 void setClock(
const Clock::Ptr &clock);
195 Clock::Ptr clock()
const {
return _clock; }
207 void setInputQueueCapacity(
int capacity);
210 int inputQueueCapacity()
const {
return _queueCapacity; }
218 void setInputOverflowPolicy(InputOverflowPolicy policy);
221 InputOverflowPolicy inputOverflowPolicy()
const {
return _overflowPolicy; }
242 void reset(int64_t originNs);
255 Error pushFrame(
const Frame &frame);
265 void pushEndOfStream();
288 Result<PullResult> pullFrame(
bool blockOnEmpty =
true);
305 void clearInterrupt();
324 void resetSourceRateEstimator();
329 FrameCount framesIn()
const {
return FrameCount(_framesIn.value()); }
332 FrameCount framesOut()
const {
return FrameCount(_framesOut.value()); }
335 FrameCount framesRepeated()
const {
return FrameCount(_framesRepeated.value()); }
338 FrameCount framesDropped()
const {
return FrameCount(_framesDropped.value()); }
341 FrameCount overflowDrops()
const {
return FrameCount(_overflowDrops.value()); }
344 Duration accumulatedError()
const {
return Duration::fromNanoseconds(_accumulatedErrorNs); }
347 double currentResampleRatio()
const {
return _currentResampleRatio; }
350 double currentSourceAudioRate()
const {
return _sourceAudioRateHz; }
355 double currentSourceVideoRate()
const {
return _sourceVideoRateHz; }
360 int64_t videoTsNs = 0;
361 bool hasVideoTs =
false;
362 int64_t audioTsNs = 0;
363 bool hasAudioTs =
false;
367 void ensureInitialised();
368 void resetLocked(
bool setExplicitOrigin, int64_t originNs);
371 void selectVideo(int64_t sourceTimeNs, int64_t nextSourceTimeNs, VideoPayload::Ptr &outVideo,
372 int64_t &outRepeated, int64_t &outDropped);
373 PcmAudioPayload::Ptr produceAudio(int64_t targetSamples);
374 void updateSourceAudioRate(
const PcmAudioPayload &audio, int64_t audioTsNs);
375 void updateSourceVideoRate(int64_t videoTsNs);
378 void periodicDebugLog(int64_t nowNs);
382 FrameRate _targetFrameRate;
383 AudioDesc _targetAudioDesc;
385 SyntheticClock *_syntheticClock =
nullptr;
386 int _queueCapacity = 8;
387 InputOverflowPolicy _overflowPolicy = InputOverflowPolicy::DropOldest;
390 mutable Mutex _mutex;
394 List<QueuedFrame> _queue;
396 bool _interrupted =
false;
399 bool _started =
false;
400 bool _explicitOrigin =
false;
401 int64_t _originNs = 0;
402 int64_t _framePeriodNs = 0;
403 FrameCount _frameCount{0};
406 bool _sourceOriginValid =
false;
407 int64_t _sourceVideoOriginNs = 0;
408 int64_t _sourceAudioOriginNs = 0;
413 VideoPayload::Ptr _heldVideo;
414 int64_t _heldVideoSourceTsNs = 0;
415 bool _hasHeldVideo =
false;
426 int64_t _pendingFrameSyncDrops = 0;
427 int64_t _frameSyncRepeatIndex = 0;
430 AudioResampler::UPtr _resampler;
431 List<PcmAudioPayload::Ptr> _audioInput;
432 int64_t _audioSamplesConsumed = 0;
435 double _sourceAudioRateHz = 0.0;
436 double _sourceVideoRateHz = 0.0;
437 double _currentResampleRatio = 1.0;
438 int64_t _lastAudioTsForRateNs = 0;
439 int64_t _lastAudioTsSamples = 0;
440 int64_t _lastVideoTsForRateNs = 0;
443 int64_t _accumulatedErrorNs = 0;
444 int64_t _lastPeriodicLogNs = 0;
445 FrameCount _frameCountAtLastLog{0};
446 FrameCount _lastEmitFrameCount = FrameCount::unknown();
453 int64_t _deadlineBiasNs = 0;
456 Atomic<int64_t> _framesIn;
457 Atomic<int64_t> _framesOut;
458 Atomic<int64_t> _framesRepeated;
459 Atomic<int64_t> _framesDropped;
460 Atomic<int64_t> _overflowDrops;