11#include <promeki/config.h>
12#if PROMEKI_ENABLE_NETWORK
32PROMEKI_NAMESPACE_BEGIN
118class RtmpMediaIO :
public DedicatedThreadMediaIO {
119 PROMEKI_OBJECT(RtmpMediaIO, DedicatedThreadMediaIO)
124 static inline const MediaIOStats::ID StatsFramesSent{
"FramesSent"};
126 static inline const MediaIOStats::ID StatsFramesReceived{
"FramesReceived"};
128 static inline const MediaIOStats::ID StatsVideoMessagesSent{
"VideoMessagesSent"};
130 static inline const MediaIOStats::ID StatsAudioMessagesSent{
"AudioMessagesSent"};
132 static inline const MediaIOStats::ID StatsVideoMessagesReceived{
"VideoMessagesReceived"};
134 static inline const MediaIOStats::ID StatsAudioMessagesReceived{
"AudioMessagesReceived"};
136 static inline const MediaIOStats::ID StatsBytesSent{
"BytesSent"};
138 static inline const MediaIOStats::ID StatsBytesReceived{
"BytesReceived"};
140 static inline const MediaIOStats::ID StatsSendQueueDepth{
"SendQueueDepth"};
142 static inline const MediaIOStats::ID StatsReadQueueDepth{
"ReadQueueDepth"};
144 static inline const MediaIOStats::ID StatsSendQueueOverflows{
"SendQueueOverflows"};
146 static inline const MediaIOStats::ID StatsConnectDurationMs{
"ConnectDurationMs"};
148 static inline const MediaIOStats::ID StatsHandshakeDurationMs{
"HandshakeDurationMs"};
150 static inline const MediaIOStats::ID StatsVideoFramesDroppedPreIdr{
"VideoFramesDroppedPreIdr"};
153 static inline const MediaIOStats::ID StatsPacingTicksOnTime{
"PacingTicksOnTime"};
155 static inline const MediaIOStats::ID StatsPacingTicksLate{
"PacingTicksLate"};
157 static inline const MediaIOStats::ID StatsPacingTicksSkipped{
"PacingTicksSkipped"};
159 static inline const MediaIOStats::ID StatsPacingReanchors{
"PacingReanchors"};
161 static inline const MediaIOStats::ID StatsPacingClockKind{
"PacingClockKind"};
164 explicit RtmpMediaIO(ObjectBase *parent =
nullptr);
167 ~RtmpMediaIO()
override;
176 uint64_t objectId()
const {
return _objectId; }
197 Error proposeInput(
const MediaDesc &offered, MediaDesc *preferred)
const override;
200 Error executeCmd(MediaIOCommandOpen &cmd)
override;
201 Error executeCmd(MediaIOCommandClose &cmd)
override;
202 Error executeCmd(MediaIOCommandRead &cmd)
override;
203 Error executeCmd(MediaIOCommandWrite &cmd)
override;
204 Error executeCmd(MediaIOCommandStats &cmd)
override;
224 Error executeCmd(MediaIOCommandSetClock &cmd)
override;
228 void cancelBlockingWork()
override;
231 class PacketizerThread;
232 class DepacketizerThread;
238 RtmpConnectOptions buildConnectOptions(
const MediaIO::Config &cfg)
const;
241 static bool hasVideoEssence(
const Frame &frame);
244 static bool hasAudioEssence(
const Frame &frame);
257 bool paceVideoFrame();
270 void armVideoPaceGate();
273 String paceClockKind()
const;
288 void onClientDisconnected(Error reason);
294 UniquePtr<RtmpClient> _client;
297 UniquePtr<PacketizerThread> _packetizer;
298 UniquePtr<DepacketizerThread> _depacketizer;
302 Queue<Frame> _readerQueue;
306 Atomic<bool> _readCancelled{
false};
318 Atomic<bool> _clientDisconnected{
false};
319 Atomic<int> _disconnectErrorCode{0};
323 ImageDesc _imageDesc;
324 AudioDesc _audioDesc;
327 bool _readerMode =
false;
328 bool _dropUntilKeyframe =
true;
329 bool _repeatParameterSets =
true;
330 bool _enhancedRtmp =
true;
331 bool _emitAnnexB =
false;
332 bool _dataEnabled =
true;
333 int _sendQueueDepth = 64;
334 int _readQueueDepth = 64;
339 FrameCount _frameCount{0};
340 FrameCount _framesSent{0};
345 Atomic<int64_t> _readerFramesReceived{0};
346 Atomic<int64_t> _videoFramesDroppedPreIdr{0};
347 Atomic<int64_t> _sendQueueOverflows{0};
353 RtmpVideoPacing _videoPacingMode{RtmpVideoPacing::Internal};
354 PacingGate _videoPaceGate;
355 FrameRate _frameRate;
356 int _paceSkipThresholdMs = 0;
357 int _paceReanchorThresholdMs = 0;
358 bool _paceClockIsExternal =
false;
362 int64_t _connectDurationMs = 0;
363 int64_t _handshakeDurationMs = 0;
367 static Atomic<uint64_t> _nextObjectId;
368 uint64_t _objectId = 0;
375class RtmpFactory :
public MediaIOFactory {
377 RtmpFactory() =
default;
379 String name()
const override {
return String(
"Rtmp"); }
380 String displayName()
const override {
return String(
"RTMP Stream"); }
381 String description()
const override {
382 return String(
"RTMP / RTMPS publisher and subscriber "
383 "(H.264 + HEVC video, AAC audio)");
385 StringList schemes()
const override {
386 return StringList{String(
"rtmp"), String(
"rtmps")};
389 bool canBeSource()
const override {
return true; }
390 bool canBeSink()
const override {
return true; }
392 Config::SpecMap configSpecs()
const override;
393 Error urlToConfig(
const Url &url, Config *outConfig)
const override;
394 MediaIO *create(
const Config &config, ObjectBase *parent =
nullptr)
const override;