11#include <promeki/config.h>
12#if PROMEKI_ENABLE_NETWORK
31PROMEKI_NAMESPACE_BEGIN
117class RtmpMediaIO :
public DedicatedThreadMediaIO {
118 PROMEKI_OBJECT(RtmpMediaIO, DedicatedThreadMediaIO)
123 static inline const MediaIOStats::ID StatsFramesSent{
"FramesSent"};
125 static inline const MediaIOStats::ID StatsFramesReceived{
"FramesReceived"};
127 static inline const MediaIOStats::ID StatsVideoMessagesSent{
"VideoMessagesSent"};
129 static inline const MediaIOStats::ID StatsAudioMessagesSent{
"AudioMessagesSent"};
131 static inline const MediaIOStats::ID StatsVideoMessagesReceived{
"VideoMessagesReceived"};
133 static inline const MediaIOStats::ID StatsAudioMessagesReceived{
"AudioMessagesReceived"};
135 static inline const MediaIOStats::ID StatsBytesSent{
"BytesSent"};
137 static inline const MediaIOStats::ID StatsBytesReceived{
"BytesReceived"};
139 static inline const MediaIOStats::ID StatsSendQueueDepth{
"SendQueueDepth"};
141 static inline const MediaIOStats::ID StatsReadQueueDepth{
"ReadQueueDepth"};
143 static inline const MediaIOStats::ID StatsSendQueueOverflows{
"SendQueueOverflows"};
145 static inline const MediaIOStats::ID StatsConnectDurationMs{
"ConnectDurationMs"};
147 static inline const MediaIOStats::ID StatsHandshakeDurationMs{
"HandshakeDurationMs"};
149 static inline const MediaIOStats::ID StatsVideoFramesDroppedPreIdr{
"VideoFramesDroppedPreIdr"};
152 static inline const MediaIOStats::ID StatsPacingTicksOnTime{
"PacingTicksOnTime"};
154 static inline const MediaIOStats::ID StatsPacingTicksLate{
"PacingTicksLate"};
156 static inline const MediaIOStats::ID StatsPacingTicksSkipped{
"PacingTicksSkipped"};
158 static inline const MediaIOStats::ID StatsPacingReanchors{
"PacingReanchors"};
160 static inline const MediaIOStats::ID StatsPacingClockKind{
"PacingClockKind"};
163 explicit RtmpMediaIO(ObjectBase *parent =
nullptr);
166 ~RtmpMediaIO()
override;
175 uint64_t objectId()
const {
return _objectId; }
196 Error proposeInput(
const MediaDesc &offered, MediaDesc *preferred)
const override;
199 Error executeCmd(MediaIOCommandOpen &cmd)
override;
200 Error executeCmd(MediaIOCommandClose &cmd)
override;
201 Error executeCmd(MediaIOCommandRead &cmd)
override;
202 Error executeCmd(MediaIOCommandWrite &cmd)
override;
203 Error executeCmd(MediaIOCommandStats &cmd)
override;
223 Error executeCmd(MediaIOCommandSetClock &cmd)
override;
227 void cancelBlockingWork()
override;
230 class PacketizerThread;
231 class DepacketizerThread;
237 RtmpConnectOptions buildConnectOptions(
const MediaIO::Config &cfg)
const;
240 static bool hasVideoEssence(
const Frame &frame);
243 static bool hasAudioEssence(
const Frame &frame);
256 bool paceVideoFrame();
269 void armVideoPaceGate();
272 String paceClockKind()
const;
287 void onClientDisconnected(Error reason);
293 UniquePtr<RtmpClient> _client;
296 UniquePtr<PacketizerThread> _packetizer;
297 UniquePtr<DepacketizerThread> _depacketizer;
301 Queue<Frame> _readerQueue;
305 Atomic<bool> _readCancelled{
false};
317 Atomic<bool> _clientDisconnected{
false};
318 Atomic<int> _disconnectErrorCode{0};
322 ImageDesc _imageDesc;
323 AudioDesc _audioDesc;
326 bool _readerMode =
false;
327 bool _dropUntilKeyframe =
true;
328 bool _repeatParameterSets =
true;
329 bool _enhancedRtmp =
true;
330 bool _emitAnnexB =
false;
331 bool _dataEnabled =
true;
332 int _sendQueueDepth = 64;
333 int _readQueueDepth = 64;
338 FrameCount _frameCount{0};
339 FrameCount _framesSent{0};
344 Atomic<int64_t> _readerFramesReceived{0};
345 Atomic<int64_t> _videoFramesDroppedPreIdr{0};
346 Atomic<int64_t> _sendQueueOverflows{0};
352 RtmpVideoPacing _videoPacingMode{RtmpVideoPacing::Internal};
353 PacingGate _videoPaceGate;
354 FrameRate _frameRate;
355 int _paceSkipThresholdMs = 0;
356 int _paceReanchorThresholdMs = 0;
357 bool _paceClockIsExternal =
false;
361 int64_t _connectDurationMs = 0;
362 int64_t _handshakeDurationMs = 0;
366 static Atomic<uint64_t> _nextObjectId;
367 uint64_t _objectId = 0;
374class RtmpFactory :
public MediaIOFactory {
376 RtmpFactory() =
default;
378 String name()
const override {
return String(
"Rtmp"); }
379 String displayName()
const override {
return String(
"RTMP Stream"); }
380 String description()
const override {
381 return String(
"RTMP / RTMPS publisher and subscriber "
382 "(H.264 + HEVC video, AAC audio)");
384 StringList schemes()
const override {
385 return StringList{String(
"rtmp"), String(
"rtmps")};
388 bool canBeSource()
const override {
return true; }
389 bool canBeSink()
const override {
return true; }
391 Config::SpecMap configSpecs()
const override;
392 Error urlToConfig(
const Url &url, Config *outConfig)
const override;
393 MediaIO *create(
const Config &config, ObjectBase *parent =
nullptr)
const override;