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
807 MediaIORequest sendParams(const String &name, const MediaIOParams &params = MediaIOParams());
808
835 MediaIORequest stats();
836
866 MediaIOAllocator::Ptr allocator() const;
867
880 void setAllocator(MediaIOAllocator::Ptr a);
881
883 PROMEKI_SIGNAL(errorOccurred, Error);
884
895 PROMEKI_SIGNAL(descriptorChanged);
896
908 PROMEKI_SIGNAL(closed, Error);
909
932 PROMEKI_SIGNAL(commandCompleted, MediaIOCommand::Ptr);
933
934 protected:
956 virtual void submit(MediaIOCommand::Ptr cmd) = 0;
957
975 void completeCommand(MediaIOCommand::Ptr cmd);
976
977 // ---- Port containers (populated by subclass executeCmd
978 // hooks via @ref CommandMediaIO::addPortGroup etc.) ----
979 //
980 // Lives on @ref MediaIO so cached-state queries
981 // (@ref source, @ref sink, @ref portGroup) are part of
982 // the abstract interface, but mutated only by the
983 // command-handling subclasses through friend access.
984
985 List<MediaIOSource *> _sources;
986 List<MediaIOSink *> _sinks;
987 List<MediaIOPortGroup *> _portGroups;
988
989 private:
990 friend class CommandMediaIO;
991 friend class MediaIOPort;
992 friend class MediaIOSink;
993 friend class MediaIOSource;
994 friend class MediaIOPortGroup;
995 friend class MediaIOReadCache;
996
1007 void resetClosedState();
1008
1021 static int64_t frameByteSize(const Frame &frame);
1022
1042 void populateStandardStats(MediaIOStats &stats) const;
1043
1044 Config _config;
1045 // Allocator policy for buffers vended on behalf of
1046 // this MediaIO. Default-initialised lazily through
1047 // allocator() to MediaIOAllocator::defaultAllocator(),
1048 // so a freshly-constructed MediaIO that never installs
1049 // an override transparently routes through the
1050 // process-wide default.
1051 MediaIOAllocator::Ptr _allocator;
1052 // _open / _closing are read from arbitrary threads
1053 // (e.g. the EventLoop thread in
1054 // @ref MediaIOReadCache::submitOneLocked) while the
1055 // worker strand writes them through
1056 // @ref completeCommand and @ref resetClosedState.
1057 // Atomic loads / stores keep those reads safe without
1058 // forcing isOpen() / isClosing() through the strand.
1059 Atomic<bool> _open;
1060 Atomic<bool> _closing;
1061
1062
1063 // Container-level cached state, written from
1064 // @ref completeCommand on whatever thread the strategy
1065 // chose, read by the user thread. Per-port cached state
1066 // (current frame, step, frame count, canSeek) lives on
1067 // @ref MediaIOPortGroup; per-port format shapes live on
1068 // @ref MediaIOSource / @ref MediaIOSink.
1069 MediaDesc _mediaDesc;
1070 AudioDesc _audioDesc;
1071 Metadata _metadata;
1072 FrameRate _frameRate;
1073 TimeStamp _originTime;
1074 SeekMode _defaultSeekMode = SeekExact;
1075
1076 // Pre-open settings. Backends consume these on the open
1077 // command (cmd.pendingMediaDesc / pendingAudioDesc /
1078 // pendingMetadata) so the planner / pipeline can hand
1079 // upstream shape to a sink or transform before its ports
1080 // exist.
1081 MediaDesc _pendingMediaDesc;
1082 AudioDesc _pendingAudioDesc;
1083 Metadata _pendingMetadata;
1084 List<int> _pendingVideoTracks;
1085 List<int> _pendingAudioTracks;
1086};
1087
1088PROMEKI_NAMESPACE_END
1089
1090#endif // PROMEKI_ENABLE_PROAV