11#include <promeki/config.h>
12#if PROMEKI_ENABLE_NETWORK
62PROMEKI_NAMESPACE_BEGIN
66class UdpSocketTransport;
386class RtpMediaIO :
public DedicatedThreadMediaIO {
387 PROMEKI_OBJECT(RtpMediaIO, DedicatedThreadMediaIO)
390 static inline const MediaIOStats::ID StatsFramesSent{
"FramesSent"};
392 static inline const MediaIOStats::ID StatsPacketsSent{
"PacketsSent"};
394 static inline const MediaIOStats::ID StatsBytesSent{
"BytesSent"};
396 static inline const MediaIOStats::ID StatsFramesReceived{
"FramesReceived"};
398 static inline const MediaIOStats::ID StatsPacketsReceived{
"PacketsReceived"};
400 static inline const MediaIOStats::ID StatsBytesReceived{
"BytesReceived"};
402 static inline const MediaIOStats::ID StatsTxVideoFrameIntervalUs{
"TxVideoFrameIntervalUs"};
404 static inline const MediaIOStats::ID StatsTxVideoSendDurationUs{
"TxVideoSendDurationUs"};
406 static inline const MediaIOStats::ID StatsRxVideoPacketIntervalUs{
"RxVideoPacketIntervalUs"};
408 static inline const MediaIOStats::ID StatsRxVideoFrameIntervalUs{
"RxVideoFrameIntervalUs"};
410 static inline const MediaIOStats::ID StatsRxVideoFrameAssembleUs{
"RxVideoFrameAssembleUs"};
422 static inline const MediaIOStats::ID StatsAudioSilencePacketsEmitted{
"AudioSilencePacketsEmitted"};
431 static inline const MediaIOStats::ID StatsAudioSilenceSamplesEmitted{
"AudioSilenceSamplesEmitted"};
444 static inline const MediaIOStats::ID StatsAudioConformanceLevel{
"AudioConformanceLevel"};
453 static inline const MediaIOStats::ID StatsAudioWireFormat{
"AudioWireFormat"};
465 static inline const MediaIOStats::ID StatsRxExtendedHighestSeq{
"RxExtendedHighestSeq"};
467 static inline const MediaIOStats::ID StatsRxPacketsExpected{
"RxPacketsExpected"};
469 static inline const MediaIOStats::ID StatsRxCumulativeLost{
"RxCumulativeLost"};
471 static inline const MediaIOStats::ID StatsRxFractionLost{
"RxFractionLost"};
473 static inline const MediaIOStats::ID StatsRxDuplicatePackets{
"RxDuplicatePackets"};
475 static inline const MediaIOStats::ID StatsRxReorderedPackets{
"RxReorderedPackets"};
477 static inline const MediaIOStats::ID StatsRxInterarrivalJitter{
"RxInterarrivalJitter"};
480 static inline const MediaIOStats::ID StatsRxSsrcChanges{
"RxSsrcChanges"};
483 static inline const MediaIOStats::ID StatsRxReorderEmittedInOrder{
"RxReorderEmittedInOrder"};
485 static inline const MediaIOStats::ID StatsRxReorderEmittedOnDeadline{
"RxReorderEmittedOnDeadline"};
487 static inline const MediaIOStats::ID StatsRxReorderDroppedOverflow{
"RxReorderDroppedOverflow"};
489 static inline const MediaIOStats::ID StatsRxReorderDroppedDuplicate{
"RxReorderDroppedDuplicate"};
492 static inline const MediaIOStats::ID StatsRxVideoQueueDepth{
"RxVideoQueueDepth"};
494 static inline const MediaIOStats::ID StatsRxAudioQueueDepth{
"RxAudioQueueDepth"};
496 static inline const MediaIOStats::ID StatsRxDataQueueDepth{
"RxDataQueueDepth"};
498 static inline const MediaIOStats::ID StatsRxReaderQueueDepth{
"RxReaderQueueDepth"};
504 static inline const MediaIOStats::ID StatsRxFramesReassembled{
"RxFramesReassembled"};
508 static inline const MediaIOStats::ID StatsRxFramesDroppedValidate{
"RxFramesDroppedValidate"};
513 static inline const MediaIOStats::ID StatsRxFramesWaitingParamSets{
"RxFramesWaitingParamSets"};
519 static inline const MediaIOStats::ID StatsRxFramesDroppedSsrcReset{
"RxFramesDroppedSsrcReset"};
524 static inline const MediaIOStats::ID StatsRxSrObserved{
"RxSrObserved"};
529 static inline const MediaIOStats::ID StatsRxLastSrAgeUs{
"RxLastSrAgeUs"};
534 static inline const MediaIOStats::ID StatsRxFirstSrLatencyUs{
"RxFirstSrLatencyUs"};
542 static inline const MediaIOParamsID ParamSdp{
"Sdp"};
545 RtpMediaIO(ObjectBase *parent =
nullptr);
548 ~RtpMediaIO()
override;
562 uint64_t objectId()
const {
return _objectId; }
577 static String buildDefaultCname(int64_t pid, uint64_t objectId,
const String &host);
597 static String pickEgressHostForCname(
const SocketAddress &destination);
633 static String formatAes67Ptime(
int packetSamples,
int sampleRateHz);
654 static int parseAes67PtimeUs(
const String &ptimeMs);
657 Error executeCmd(MediaIOCommandOpen &cmd)
override;
658 Error executeCmd(MediaIOCommandClose &cmd)
override;
659 Error executeCmd(MediaIOCommandRead &cmd)
override;
660 Error executeCmd(MediaIOCommandWrite &cmd)
override;
661 Error getParam(MediaIOParamsID
id, Variant &out)
override;
662 Error executeCmd(MediaIOCommandStats &cmd)
override;
682 Error executeCmd(MediaIOCommandSetClock &cmd)
override;
686 void cancelBlockingWork()
override;
724 class VideoPacketizerThread;
725 class AudioPacketizerThread;
726 class DataPacketizerThread;
765 Stream(Stream &&o) noexcept
766 : transport(o.transport),
767 transportSecondary(o.transportSecondary),
770 destination(std::move(o.destination)),
771 destinationSecondary(std::move(o.destinationSecondary)),
772 localAddressSecondary(std::move(o.localAddressSecondary)),
773 interfaceSecondary(std::move(o.interfaceSecondary)),
774 payloadType(o.payloadType),
775 clockRate(o.clockRate),
779 tsDelayUs(o.tsDelayUs),
780 ptpTraceable(o.ptpTraceable),
782 mediaType(std::move(o.mediaType)),
783 rtpmap(std::move(o.rtpmap)),
784 fmtp(std::move(o.fmtp)),
785 mid(std::move(o.mid)),
787 clockDomain(o.clockDomain),
788 tsRefClkMode(o.tsRefClkMode),
789 ptpGrandmaster(o.ptpGrandmaster),
790 ptpDomain(o.ptpDomain),
791 refClockLocalMac(std::move(o.refClockLocalMac)),
792 mediaClkOffset(o.mediaClkOffset),
793 mediaClkMode(o.mediaClkMode),
794 senderType(o.senderType),
795 trOffsetUs(o.trOffsetUs),
797 jxsPacketMode(o.jxsPacketMode),
798 jxsTransMode(o.jxsTransMode),
799 jxsProfile(o.jxsProfile),
800 jxsLevel(o.jxsLevel),
801 jxsSublevel(o.jxsSublevel),
802 mediaClock(std::move(o.mediaClock)) {
806 o.transport =
nullptr;
807 o.transportSecondary =
nullptr;
811 Stream(
const Stream &) =
delete;
812 Stream &operator=(
const Stream &) =
delete;
813 Stream &operator=(Stream &&) =
delete;
814 UdpSocketTransport *transport =
nullptr;
815 UdpSocketTransport *transportSecondary =
nullptr;
816 RtpSession *session =
nullptr;
817 RtpPayload *payload =
nullptr;
818 SocketAddress destination;
819 SocketAddress destinationSecondary;
820 SocketAddress localAddressSecondary;
821 String interfaceSecondary;
822 uint8_t payloadType = 0;
823 uint32_t clockRate = 90000;
828 bool ptpTraceable =
false;
829 RtpTsMode tsMode = RtpTsMode::Samp;
835 ClockDomain clockDomain;
836 RtpRefClockMode tsRefClkMode = RtpRefClockMode::None;
837 EUI64 ptpGrandmaster;
838 uint8_t ptpDomain = 0;
839 MacAddress refClockLocalMac;
840 int32_t mediaClkOffset = 0;
858 RtpMediaClkMode mediaClkMode = RtpMediaClkMode::Auto;
870 RtpSenderType senderType = RtpSenderType::Auto;
896 JxsPacketMode jxsPacketMode = JxsPacketMode::Codestream;
906 JxsTransMode jxsTransMode = JxsTransMode::SequentialOnly;
911 JxsProfile jxsProfile = JxsProfile::Unspecified;
916 JxsLevel jxsLevel = JxsLevel::Unspecified;
921 JxsSublevel jxsSublevel = JxsSublevel::Unspecified;
942 RtpMediaClock mediaClock;
959 struct WriterStream : Stream {
960 WriterStream() =
default;
961 WriterStream(WriterStream &&o) noexcept
962 : Stream(std::move(o)),
963 packetizer(o.packetizer),
965 packetsSent(o.packetsSent.value()),
966 bytesSent(o.bytesSent.value()),
967 senderOctets(o.senderOctets.value()),
968 txFrameInterval(std::move(o.txFrameInterval)),
969 txSendDuration(std::move(o.txSendDuration)),
970 txLastSendStart(o.txLastSendStart),
971 txHasLastSend(o.txHasLastSend) {
972 o.packetizer =
nullptr;
975 WriterStream(
const WriterStream &) =
delete;
976 WriterStream &operator=(
const WriterStream &) =
delete;
977 WriterStream &operator=(WriterStream &&) =
delete;
978 RtpPacketizerThread *packetizer =
nullptr;
979 RtpTxThread *tx =
nullptr;
980 Atomic<int64_t> packetsSent{0};
981 Atomic<int64_t> bytesSent{0};
982 Atomic<int64_t> senderOctets{0};
983 Histogram txFrameInterval;
984 Histogram txSendDuration;
985 TimeStamp txLastSendStart;
986 bool txHasLastSend =
false;
1005 struct ReaderStream : Stream {
1006 ReaderStream() =
default;
1007 ReaderStream(ReaderStream &&o) noexcept
1008 : Stream(std::move(o)),
1009 packetsReceived(o.packetsReceived.value()),
1010 bytesReceived(o.bytesReceived.value()),
1011 framesReceived(o.framesReceived),
1012 packetsLost(o.packetsLost.value()),
1013 readerImageDesc(std::move(o.readerImageDesc)),
1014 readerAudioDesc(std::move(o.readerAudioDesc)),
1015 reasmTimestamp(o.reasmTimestamp),
1016 reasmHasTimestamp(o.reasmHasTimestamp),
1017 reasmLastSeq(o.reasmLastSeq),
1018 reasmHaveLastSeq(o.reasmHaveLastSeq),
1019 reasmPackets(std::move(o.reasmPackets)),
1020 rxPacketInterval(std::move(o.rxPacketInterval)),
1021 rxFrameInterval(std::move(o.rxFrameInterval)),
1022 rxFrameAssembleTime(std::move(o.rxFrameAssembleTime)),
1023 rxLastPacketTime(o.rxLastPacketTime),
1024 rxLastFrameTime(o.rxLastFrameTime),
1025 rxFrameStartTime(o.rxFrameStartTime),
1026 rxHasLastPacket(o.rxHasLastPacket),
1027 rxHasLastFrame(o.rxHasLastFrame),
1028 rxHasFrameStart(o.rxHasFrameStart),
1029 streamClock(std::move(o.streamClock)),
1030 lastSrArrivedAt(o.lastSrArrivedAt),
1032 seqTracker(std::move(o.seqTracker)),
1033 reorderBuffer(std::move(o.reorderBuffer)),
1034 reorderQueue(std::move(o.reorderQueue)),
1035 depacketizer(std::move(o.depacketizer)),
1036 ssrcChanges(o.ssrcChanges.value()),
1037 framesReassembled(o.framesReassembled.value()),
1038 framesDroppedValidate(o.framesDroppedValidate.value()),
1039 framesWaitingParamSets(o.framesWaitingParamSets.value()),
1040 framesDroppedSsrcReset(o.framesDroppedSsrcReset.value()) {}
1041 ReaderStream(
const ReaderStream &) =
delete;
1042 ReaderStream &operator=(
const ReaderStream &) =
delete;
1043 ReaderStream &operator=(ReaderStream &&) =
delete;
1044 Atomic<int64_t> packetsReceived{0};
1045 Atomic<int64_t> bytesReceived{0};
1046 FrameCount framesReceived{0};
1047 Atomic<int64_t> packetsLost{0};
1048 ImageDesc readerImageDesc;
1049 AudioDesc readerAudioDesc;
1050 uint32_t reasmTimestamp = 0;
1051 bool reasmHasTimestamp =
false;
1052 uint16_t reasmLastSeq = 0;
1053 bool reasmHaveLastSeq =
false;
1054 RtpPacket::List reasmPackets;
1055 Histogram rxPacketInterval;
1056 Histogram rxFrameInterval;
1057 Histogram rxFrameAssembleTime;
1058 TimeStamp rxLastPacketTime;
1059 TimeStamp rxLastFrameTime;
1060 TimeStamp rxFrameStartTime;
1061 bool rxHasLastPacket =
false;
1062 bool rxHasLastFrame =
false;
1063 bool rxHasFrameStart =
false;
1077 RtpStreamClock streamClock;
1085 TimeStamp lastSrArrivedAt;
1101 UniquePtr<RtpSeqTracker> seqTracker;
1107 UniquePtr<RtpSeqReorderBuffer> reorderBuffer;
1116 UniquePtr<RtpPacket::Queue> reorderQueue;
1126 UniquePtr<RtpDepacketizerThread> depacketizer;
1140 Atomic<uint32_t> resetEpoch{0};
1152 Atomic<int64_t> lastPacketArrivalNs{0};
1161 bool wireSilenceEosSignaled =
false;
1173 Atomic<int64_t> ssrcChanges{0};
1184 Atomic<int64_t> framesReassembled{0};
1195 Atomic<int64_t> framesDroppedValidate{0};
1206 Atomic<int64_t> framesWaitingParamSets{0};
1215 Atomic<int64_t> framesDroppedSsrcReset{0};
1234 struct VideoStream : WriterStream {
1235 VideoStream() =
default;
1236 VideoStream(VideoStream &&o) noexcept
1237 : WriterStream(std::move(o)),
1238 imageDesc(std::move(o.imageDesc)),
1239 cachedSps(std::move(o.cachedSps)),
1240 cachedPps(std::move(o.cachedPps)),
1241 cachedVps(std::move(o.cachedVps)) {}
1242 VideoStream(
const VideoStream &) =
delete;
1243 VideoStream &operator=(
const VideoStream &) =
delete;
1244 VideoStream &operator=(VideoStream &&) =
delete;
1253 ImageDesc imageDesc;
1269 struct DataStream : WriterStream {
1270 DataStream() =
default;
1271 DataStream(DataStream &&o)
noexcept =
default;
1272 DataStream(
const DataStream &) =
delete;
1273 DataStream &operator=(
const DataStream &) =
delete;
1274 DataStream &operator=(DataStream &&) =
delete;
1281 AncTransmissionModel ancTransmissionModel =
1282 AncTransmissionModel::Unsignalled;
1288 Duration ancTrOffset;
1296 int ancTotalLines = 0;
1300 int ancVpidCode = 0;
1321 struct AudioStream : WriterStream {
1322 AudioStream() =
default;
1323 AudioStream(AudioStream &&o) noexcept
1324 : WriterStream(std::move(o)),
1325 storageDesc(std::move(o.storageDesc)),
1326 packetSamples(o.packetSamples),
1327 packetBytes(o.packetBytes),
1328 packetTimeUs(o.packetTimeUs),
1329 prerollSamples(o.prerollSamples),
1330 wireFormat(o.wireFormat),
1331 conformanceLevel(o.conformanceLevel),
1332 silencePacketsEmitted(
1333 o.silencePacketsEmitted.value()),
1334 silenceSamplesEmitted(
1335 o.silenceSamplesEmitted.value()) {}
1336 AudioStream(
const AudioStream &) =
delete;
1337 AudioStream &operator=(
const AudioStream &) =
delete;
1338 AudioStream &operator=(AudioStream &&) =
delete;
1348 AudioDesc storageDesc;
1350 size_t packetSamples = 0;
1357 size_t packetBytes = 0;
1359 int packetTimeUs = 0;
1368 size_t prerollSamples = 0;
1381 AudioWireFormat wireFormat = AudioWireFormat::L16;
1392 AudioConformanceLevel conformanceLevel = AudioConformanceLevel::None;
1401 Atomic<int64_t> silencePacketsEmitted{0};
1406 Atomic<int64_t> silenceSamplesEmitted{0};
1419 struct VideoReaderStream : ReaderStream {
1420 VideoReaderStream() =
default;
1421 VideoReaderStream(VideoReaderStream &&o) noexcept
1422 : ReaderStream(std::move(o)),
1423 payloadQueue(std::move(o.payloadQueue)) {}
1424 VideoReaderStream(
const VideoReaderStream &) =
delete;
1425 VideoReaderStream &operator=(
const VideoReaderStream &) =
delete;
1426 VideoReaderStream &operator=(VideoReaderStream &&) =
delete;
1437 UniquePtr<Queue<RxVideoFrame>> payloadQueue;
1456 struct AudioReaderStream : ReaderStream {
1457 AudioReaderStream() =
default;
1458 AudioReaderStream(AudioReaderStream &&o) noexcept
1459 : ReaderStream(std::move(o)),
1460 fifo(std::move(o.fifo)),
1461 payloadQueue(std::move(o.payloadQueue)) {}
1462 AudioReaderStream(
const AudioReaderStream &) =
delete;
1463 AudioReaderStream &operator=(
const AudioReaderStream &) =
delete;
1464 AudioReaderStream &operator=(AudioReaderStream &&) =
delete;
1478 UniquePtr<Queue<RxAudioChunk>> payloadQueue;
1494 struct DataReaderStream : ReaderStream {
1495 DataReaderStream() =
default;
1496 DataReaderStream(DataReaderStream &&o) noexcept
1497 : ReaderStream(std::move(o)),
1498 payloadQueue(std::move(o.payloadQueue)),
1499 ancPayloadQueue(std::move(o.ancPayloadQueue)) {}
1500 DataReaderStream(
const DataReaderStream &) =
delete;
1501 DataReaderStream &operator=(
const DataReaderStream &) =
delete;
1502 DataReaderStream &operator=(DataReaderStream &&) =
delete;
1508 UniquePtr<Queue<RxDataMessage>> payloadQueue;
1514 UniquePtr<Queue<RxAncFrame>> ancPayloadQueue;
1524 static constexpr size_t VideoPayloadQueueDepth = 4;
1525 static constexpr size_t AudioPayloadQueueDepth = 100;
1526 static constexpr size_t DataPayloadQueueDepth = 8;
1528 Error configureVideoStream(
const MediaIO::Config &cfg,
const MediaDesc &mediaDesc);
1529 Error configureAudioStream(
const MediaIO::Config &cfg,
const MediaDesc &mediaDesc);
1530 Error configureDataStream(
const MediaIO::Config &cfg);
1538 void applyClockReferenceConfig(
const MediaIO::Config &cfg);
1540 Error openStream(WriterStream &s,
bool enableMulticastLoopback);
1541 Error openReaderStream(ReaderStream &s,
bool enableMulticastLoopback);
1577 size_t computeStreamPacketBudget(
const ReaderStream &s)
const;
1612 Error injectParameterSets(
const uint8_t *data,
size_t size, Buffer &healed);
1628 bool paceVideoFrame();
1658 void refreshStreamClock(ReaderStream &s);
1679 TimeStamp ntpToSteady(
const NtpTime &ntp)
const;
1682 Error applySdp(
const SdpSession &sdp, MediaIO::Config &cfg, MediaDesc &mediaDesc);
1683 Error openAllReaders();
1684 void pushReaderFrame(Frame frame);
1687 Error writeSdpFile(
const String &path);
1694 void resetStreamCommon(Stream &s);
1699 void resetWriterStream(WriterStream &s);
1705 void resetReaderStream(ReaderStream &s);
1719 RtcpSchedulerContext buildRtcpSchedulerContext();
1735 List<VideoStream> _videos;
1736 List<AudioStream> _audios;
1737 List<DataStream> _datas;
1738 List<VideoReaderStream> _videoReaders;
1739 List<AudioReaderStream> _audioReaders;
1740 List<DataReaderStream> _dataReaders;
1743 SocketAddress _localAddress;
1744 String _sessionName;
1745 String _sessionOrigin;
1746 String _multicastInterface;
1747 int _multicastTTL = 0;
1748 int _recvBufferBytes = 0;
1749 int _sendBufferBytes = 0;
1754 String _rtpSourceAddress;
1755 bool _rtpDontFragment =
true;
1758 FrameRate _frameRate;
1759 FrameCount _frameCount{0};
1760 FrameCount _framesSent{0};
1763 bool _readerMode =
false;
1772 PixelFormat _videoWirePixelFormat;
1775 Queue<Frame> _readerQueue;
1776 int _readerMaxDepth = 4;
1777 int _readerJitterMs = 50;
1778 int _wireSilenceTimeoutMs = 0;
1779 bool _videoWatchdogEnabled =
false;
1780 FrameCount _readerFramesReceived{0};
1787 Atomic<bool> _readCancelled{
false};
1805 TimeStamp _readerSteadyAnchor;
1806 NtpTime _readerNtpAnchor;
1807 bool _readerHasAnchor =
false;
1814 TimeStamp _openedAt;
1821 UniquePtr<RtpAggregatorThread> _aggregator;
1829 SdpSession _sdpSession;
1846 UniquePtr<RtcpScheduler> _rtcpScheduler;
1847 bool _rtcpEnabled =
true;
1848 int _rtcpIntervalMs = 5000;
1855 static Atomic<uint64_t> _nextObjectId;
1856 uint64_t _objectId = 0;
1869 Atomic<bool> _anchorSeeded;
1883 UniquePtr<PhcClock> _phcClock;
1888 bool _phcAutoTraceable =
false;
1899 PacingGate _videoGate;
1919 String _h264SpropParameterSets;
1920 String _h265SpropVps;
1921 String _h265SpropSps;
1922 String _h265SpropPps;
1937 void refreshSdpSprop();
1944class RtpFactory :
public MediaIOFactory {
1946 RtpFactory() =
default;
1948 String name()
const override {
return String(
"Rtp"); }
1949 String displayName()
const override {
return String(
"RTP Stream"); }
1950 String description()
const override {
1951 return String(
"RTP video + audio + metadata reader / writer "
1952 "(MJPEG / JPEG XS / H.264 / H.265 / raw / L16 / JSON)");
1958 StringList extensions()
const override {
1959 return {String(
"sdp")};
1962 bool canBeSource()
const override {
return true; }
1963 bool canBeSink()
const override {
return true; }
1965 bool canHandleDevice(IODevice *device)
const override;
1966 Config::SpecMap configSpecs()
const override;
1968 MediaIO *create(
const Config &config, ObjectBase *parent =
nullptr)
const override;
1971PROMEKI_NAMESPACE_END