libpromeki 1.0.0-alpha
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
mediaioportconnection.h
Go to the documentation of this file.
1
8#pragma once
9
10
11#include <promeki/config.h>
12#if PROMEKI_ENABLE_PROAV
13#include <functional>
14
15#include <promeki/function.h>
16#include <promeki/atomic.h>
17#include <promeki/error.h>
18#include <promeki/frame.h>
19#include <promeki/framecount.h>
20#include <promeki/list.h>
22#include <promeki/namespace.h>
23#include <promeki/objectbase.h>
24
25PROMEKI_NAMESPACE_BEGIN
26
27class MediaIOSource;
28class MediaIOSink;
29
109class MediaIOPortConnection : public ObjectBase {
110 PROMEKI_OBJECT(MediaIOPortConnection, ObjectBase)
111 public:
126 MediaIOPortConnection(MediaIOSource *source, MediaIOSink *sink, ObjectBase *parent = nullptr);
127
139 explicit MediaIOPortConnection(MediaIOSource *source, ObjectBase *parent = nullptr);
140
142 ~MediaIOPortConnection() override;
143
145 MediaIOSource *source() const { return _source; }
146
153 MediaIOSink *sink() const;
154
156 List<MediaIOSink *> sinks() const;
157
159 int sinkCount() const { return static_cast<int>(_sinks.size()); }
160
162 bool isRunning() const { return _running; }
163
184 Error addSink(MediaIOSink *sink, FrameCount frameLimit = FrameCount());
185
200 Error start();
201
210 void stop();
211
212 // ---- Stats ----
213
221 int64_t framesTransferred() const { return _framesTransferred.value(); }
222
231 int64_t framesWritten(MediaIOSink *sink) const;
232
234 bool upstreamDone() const { return _upstreamDone; }
235
242 bool sinkStopped(MediaIOSink *sink) const;
243
245 bool allSinksDone() const { return _allSinksDoneEmitted; }
246
247 // ---- Per-sink gate (capture transport) ----
248
272 void setSinkGate(MediaIOSink *sink, bool open);
273
282 bool sinkGate(MediaIOSink *sink) const;
283
294 using FrameInspector = Function<void(const Frame &)>;
295
307 void setFrameInspector(FrameInspector cb);
308
310 bool hasFrameInspector() const { return static_cast<bool>(_frameInspector); }
311
312 // ---- Signals ----
313
321 PROMEKI_SIGNAL(sinkGateChanged, MediaIOSink *, bool);
322
333 PROMEKI_SIGNAL(upstreamDone);
334
347 PROMEKI_SIGNAL(errorOccurred, Error);
348
358 PROMEKI_SIGNAL(sinkLimitReached, MediaIOSink *);
359
373 PROMEKI_SIGNAL(sinkError, MediaIOSink *, Error);
374
385 PROMEKI_SIGNAL(allSinksDone);
386
388 PROMEKI_SIGNAL(stopped);
389
390 private:
391 struct SinkState {
392 MediaIOSink *sink = nullptr;
393 FrameCount frameLimit;
394 int64_t framesWritten = 0;
395 bool doneByLimit = false;
396 bool stopped = false;
398 bool gateOpen = true;
408 bool pendingForceKeyframe = false;
409 };
410
411 void pump();
412 void onSinkWriteError(MediaIOSink *sink, Error err);
413 SinkState *findSinkState(MediaIOSink *sink);
414 const SinkState *findSinkState(MediaIOSink *sink) const;
415 void maybeEmitAllSinksDone();
416 bool everyActiveSinkAcceptsWrite() const;
417
418 void schedulePump();
419
420 MediaIOSource *_source = nullptr;
421 List<SinkState> _sinks;
422 FrameInspector _frameInspector;
423 // The pump holds the most recent in-flight read
424 // request across iterations. When @ref readFrame
425 // returns a request whose payload has not yet
426 // arrived (cache miss) the pump stashes it here and
427 // returns; the next pump invocation (kicked by
428 // @c frameReady) re-checks and consumes when ready,
429 // so no prefetched frame is ever discarded.
430 MediaIORequest _pendingRead;
431 bool _running = false;
432 bool _upstreamDone = false;
433 bool _allSinksDoneEmitted = false;
434 Atomic<int64_t> _framesTransferred{0};
435 // Signal-coalescer: at most one pump is queued on
436 // the loop at a time. Many signals (frameReady +
437 // per-sink frameWanted + per-cmd .then()) can fire
438 // simultaneously from the strand worker; without
439 // this flag they each post a pump callable and the
440 // EventLoop's @c processEvents drains them faster
441 // than @c pumpUntil can break out to check its
442 // predicate. The flag flips to true on the first
443 // post and is cleared inside pump itself.
444 Atomic<bool> _pumpScheduled{false};
445};
446
447PROMEKI_NAMESPACE_END
448
449#endif // PROMEKI_ENABLE_PROAV