libpromeki 1.0.0-alpha
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
mediaio.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 <promeki/namespace.h>
14#include <promeki/objectbase.h>
15#include <promeki/atomic.h>
16#include <promeki/string.h>
17#include <promeki/error.h>
18#include <promeki/list.h>
19#include <promeki/uniqueptr.h>
20#include <promeki/frame.h>
21#include <promeki/mediadesc.h>
22#include <promeki/audiodesc.h>
23#include <promeki/metadata.h>
24#include <promeki/framerate.h>
25#include <promeki/framecount.h>
26#include <promeki/mediaconfig.h>
27#include <promeki/url.h>
32
33PROMEKI_NAMESPACE_BEGIN
34
35class IODevice;
36class Clock;
37class MediaIODescription;
38class MediaIOFactory;
39class MediaIOPort;
40class MediaIOSink;
41class MediaIOSource;
42class MediaIOPortGroup;
43
44// MediaIORequest is forward-declared so MediaIO can return it from public
45// methods without pulling in the full mediaiorequest.h here. Callers that
46// consume the returned request (.wait(), .then()) include mediaiorequest.h
47// themselves.
48class MediaIORequest;
49
50// ============================================================================
51// MediaIO controller class
52// ============================================================================
53
113class MediaIO : public ObjectBase {
114 PROMEKI_OBJECT(MediaIO, ObjectBase)
115 public:
117 using UPtr = UniquePtr<MediaIO>;
118
120 using SeekMode = MediaIOSeekMode;
121
122 static constexpr SeekMode SeekDefault = MediaIO_SeekDefault;
123 static constexpr SeekMode SeekExact = MediaIO_SeekExact;
124 static constexpr SeekMode SeekNearestKeyframe = MediaIO_SeekNearestKeyframe;
125 static constexpr SeekMode SeekKeyframeBefore = MediaIO_SeekKeyframeBefore;
126 static constexpr SeekMode SeekKeyframeAfter = MediaIO_SeekKeyframeAfter;
127
129 using Config = MediaConfig;
130
132 using ConfigID = MediaConfigID;
133
135 static constexpr FrameCount FrameCountUnknown = FrameCount::unknown();
136
138 static constexpr FrameCount FrameCountInfinite = FrameCount::infinity();
139
140
147 static MediaIO *create(const Config &config, ObjectBase *parent = nullptr);
148
166 static MediaIO *createForFileRead(const String &filename, ObjectBase *parent = nullptr);
167
182 static MediaIO *createForFileWrite(const String &filename, ObjectBase *parent = nullptr);
183
199 static MediaIO *createFromUrl(const Url &url, ObjectBase *parent = nullptr);
200
209 static MediaIO *createFromUrl(const String &url, ObjectBase *parent = nullptr);
210
275 static Error applyQueryToConfig(const Url &url, const Config::SpecMap &specs, Config *outConfig);
276
313 static MediaDesc applyOutputOverrides(const MediaDesc &input, const MediaConfig &config);
314
334 static PixelFormat defaultUncompressedPixelFormat(const PixelFormat &source);
335
340 MediaIO(ObjectBase *parent = nullptr);
341
345 ~MediaIO() override;
346
348 const Config &config() const { return _config; }
349
350 // ---- Ports (multi-port surface) ----
351
363 MediaIOSource *source(int N) const;
364
366 int sourceCount() const;
367
379 MediaIOSink *sink(int N) const;
380
382 int sinkCount() const;
383
397 MediaIOPortGroup *portGroup(int N) const;
398
400 int portGroupCount() const;
401
409 bool isSource() const { return sourceCount() > 0; }
410
418 bool isSink() const { return sinkCount() > 0; }
419
420 // ---- Per-instance identifier ----
421
435 String name() const { return _config.getAs<String>(MediaConfig::Name, String()); }
436
447 void setName(const String &val) { _config.set(MediaConfig::Name, val); }
448
450 bool isOpen() const { return _open.value(); }
451
461 SeekMode defaultSeekMode() const { return _defaultSeekMode; }
462
477 Error setPendingMediaDesc(const MediaDesc &desc);
478
480 const MediaDesc &pendingMediaDesc() const { return _pendingMediaDesc; }
481
483 Error setPendingAudioDesc(const AudioDesc &desc);
484
486 const AudioDesc &pendingAudioDesc() const { return _pendingAudioDesc; }
487
489 Error setPendingMetadata(const Metadata &meta);
490
492 const Metadata &pendingMetadata() const { return _pendingMetadata; }
493
504 Error setVideoTracks(const List<int> &tracks);
505
516 Error setAudioTracks(const List<int> &tracks);
517
545 MediaIORequest open();
546
578 MediaIORequest close();
579
587 bool isClosing() const { return _closing.value(); }
588
589 // ---- Cached descriptor accessors ----
590
597 const MediaDesc &mediaDesc() const { return _mediaDesc; }
598
604 const FrameRate &frameRate() const { return _frameRate; }
605
611 const AudioDesc &audioDesc() const { return _audioDesc; }
612
618 const Metadata &metadata() const { return _metadata; }
619
620 // ---- Introspection / negotiation ----
621
650 virtual Error describe(MediaIODescription *out) const;
651
665 virtual Error proposeInput(const MediaDesc &offered, MediaDesc *preferred) const;
666
695 virtual Error proposeOutput(const MediaDesc &requested, MediaDesc *achievable,
696 MediaConfig *configDelta = nullptr) const;
697
711 virtual bool isIdle() const { return true; }
712
723 virtual void cancelBlockingWork() {}
724
737 virtual void cancelPendingWork() {}
738
751 virtual int pendingInternalWrites() const { return 0; }
752
777 virtual void setIngestPaused(bool paused) { (void)paused; }
778
780 void setConfig(const Config &config) { _config = config; }
781
816 MediaIORequest sendParams(const MediaIOParams &block);
817
844 MediaIORequest stats();
845
875 MediaIOAllocator::Ptr allocator() const;
876
889 void setAllocator(MediaIOAllocator::Ptr a);
890
892 PROMEKI_SIGNAL(errorOccurred, Error);
893
904 PROMEKI_SIGNAL(descriptorChanged);
905
917 PROMEKI_SIGNAL(closed, Error);
918
941 PROMEKI_SIGNAL(commandCompleted, MediaIOCommand::Ptr);
942
943 protected:
965 virtual void submit(MediaIOCommand::Ptr cmd) = 0;
966
984 void completeCommand(MediaIOCommand::Ptr cmd);
985
986 // ---- Port containers (populated by subclass executeCmd
987 // hooks via @ref CommandMediaIO::addPortGroup etc.) ----
988 //
989 // Lives on @ref MediaIO so cached-state queries
990 // (@ref source, @ref sink, @ref portGroup) are part of
991 // the abstract interface, but mutated only by the
992 // command-handling subclasses through friend access.
993
994 List<MediaIOSource *> _sources;
995 List<MediaIOSink *> _sinks;
996 List<MediaIOPortGroup *> _portGroups;
997
998 private:
999 friend class CommandMediaIO;
1000 friend class MediaIOPort;
1001 friend class MediaIOSink;
1002 friend class MediaIOSource;
1003 friend class MediaIOPortGroup;
1004 friend class MediaIOReadCache;
1005
1016 void resetClosedState();
1017
1030 static int64_t frameByteSize(const Frame &frame);
1031
1051 void populateStandardStats(MediaIOStats &stats) const;
1052
1053 Config _config;
1054 // Allocator policy for buffers vended on behalf of
1055 // this MediaIO. Default-initialised lazily through
1056 // allocator() to MediaIOAllocator::defaultAllocator(),
1057 // so a freshly-constructed MediaIO that never installs
1058 // an override transparently routes through the
1059 // process-wide default.
1060 MediaIOAllocator::Ptr _allocator;
1061 // _open / _closing are read from arbitrary threads
1062 // (e.g. the EventLoop thread in
1063 // @ref MediaIOReadCache::submitOneLocked) while the
1064 // worker strand writes them through
1065 // @ref completeCommand and @ref resetClosedState.
1066 // Atomic loads / stores keep those reads safe without
1067 // forcing isOpen() / isClosing() through the strand.
1068 Atomic<bool> _open;
1069 Atomic<bool> _closing;
1070
1071
1072 // Container-level cached state, written from
1073 // @ref completeCommand on whatever thread the strategy
1074 // chose, read by the user thread. Per-port cached state
1075 // (current frame, step, frame count, canSeek) lives on
1076 // @ref MediaIOPortGroup; per-port format shapes live on
1077 // @ref MediaIOSource / @ref MediaIOSink.
1078 MediaDesc _mediaDesc;
1079 AudioDesc _audioDesc;
1080 Metadata _metadata;
1081 FrameRate _frameRate;
1082 TimeStamp _originTime;
1083 SeekMode _defaultSeekMode = SeekExact;
1084
1085 // Pre-open settings. Backends consume these on the open
1086 // command (cmd.pendingMediaDesc / pendingAudioDesc /
1087 // pendingMetadata) so the planner / pipeline can hand
1088 // upstream shape to a sink or transform before its ports
1089 // exist.
1090 MediaDesc _pendingMediaDesc;
1091 AudioDesc _pendingAudioDesc;
1092 Metadata _pendingMetadata;
1093 List<int> _pendingVideoTracks;
1094 List<int> _pendingAudioTracks;
1095};
1096
1097PROMEKI_NAMESPACE_END
1098
1099#endif // PROMEKI_ENABLE_PROAV