![]() System : Linux absol.cf 5.4.0-198-generic #218-Ubuntu SMP Fri Sep 27 20:18:53 UTC 2024 x86_64 User : www-data ( 33) PHP Version : 7.4.33 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, Directory : /proc/thread-self/root/usr/local/lib/node_modules/mediasoup/worker/include/RTC/ |
Upload File : |
#ifndef MS_RTC_RTP_PACKET_HPP #define MS_RTC_RTP_PACKET_HPP #include "common.hpp" #include "Utils.hpp" #include "RTC/Codecs/PayloadDescriptorHandler.hpp" #include <json.hpp> #include <map> #include <string> #include <vector> using json = nlohmann::json; namespace RTC { // Max RTP length. constexpr size_t RtpBufferSize{ 65536u }; // Max MTU size. constexpr size_t MtuSize{ 1500u }; // MID header extension max length (just used when setting/updating MID // extension). constexpr uint8_t MidMaxLength{ 8u }; class RtpPacket { public: /* Struct for RTP header. */ struct Header { #if defined(MS_LITTLE_ENDIAN) uint8_t csrcCount : 4; uint8_t extension : 1; uint8_t padding : 1; uint8_t version : 2; uint8_t payloadType : 7; uint8_t marker : 1; #elif defined(MS_BIG_ENDIAN) uint8_t version : 2; uint8_t padding : 1; uint8_t extension : 1; uint8_t csrcCount : 4; uint8_t marker : 1; uint8_t payloadType : 7; #endif uint16_t sequenceNumber; uint32_t timestamp; uint32_t ssrc; }; private: /* Struct for RTP header extension. */ struct HeaderExtension { uint16_t id; uint16_t length; // Size of value in multiples of 4 bytes. uint8_t value[1]; }; private: /* Struct for One-Byte extension. */ struct OneByteExtension { #if defined(MS_LITTLE_ENDIAN) uint8_t len : 4; uint8_t id : 4; #elif defined(MS_BIG_ENDIAN) uint8_t id : 4; uint8_t len : 4; #endif uint8_t value[1]; }; private: /* Struct for Two-Bytes extension. */ struct TwoBytesExtension { uint8_t id : 8; uint8_t len : 8; uint8_t value[1]; }; public: /* Struct for replacing and setting header extensions. */ struct GenericExtension { GenericExtension(uint8_t id, uint8_t len, uint8_t* value) : id(id), len(len), value(value){}; uint8_t id : 8; uint8_t len : 8; uint8_t* value; }; public: /* Struct with frame-marking information. */ struct FrameMarking { #if defined(MS_LITTLE_ENDIAN) uint8_t tid : 3; uint8_t base : 1; uint8_t discardable : 1; uint8_t independent : 1; uint8_t end : 1; uint8_t start : 1; #elif defined(MS_BIG_ENDIAN) uint8_t start : 1; uint8_t end : 1; uint8_t independent : 1; uint8_t discardable : 1; uint8_t base : 1; uint8_t tid : 3; #endif uint8_t lid; uint8_t tl0picidx; }; public: static bool IsRtp(const uint8_t* data, size_t len) { // NOTE: RtcpPacket::IsRtcp() must always be called before this method. auto header = const_cast<Header*>(reinterpret_cast<const Header*>(data)); // clang-format off return ( (len >= sizeof(Header)) && // DOC: https://tools.ietf.org/html/draft-ietf-avtcore-rfc5764-mux-fixes (data[0] > 127 && data[0] < 192) && // RTP Version must be 2. (header->version == 2) ); // clang-format on } static RtpPacket* Parse(const uint8_t* data, size_t len); private: RtpPacket( Header* header, HeaderExtension* headerExtension, const uint8_t* payload, size_t payloadLength, uint8_t payloadPadding, size_t size); public: ~RtpPacket(); void Dump() const; void FillJson(json& jsonObject) const; const uint8_t* GetData() const { return (const uint8_t*)this->header; } size_t GetSize() const { return this->size; } uint8_t GetPayloadType() const { return this->header->payloadType; } void SetPayloadType(uint8_t payloadType) { this->header->payloadType = payloadType; } bool HasMarker() const { return this->header->marker; } void SetMarker(bool marker) { this->header->marker = marker; } void SetPayloadPaddingFlag(bool flag) { this->header->padding = flag; } uint16_t GetSequenceNumber() const { return uint16_t{ ntohs(this->header->sequenceNumber) }; } void SetSequenceNumber(uint16_t seq) { this->header->sequenceNumber = uint16_t{ htons(seq) }; } uint32_t GetTimestamp() const { return uint32_t{ ntohl(this->header->timestamp) }; } void SetTimestamp(uint32_t timestamp) { this->header->timestamp = uint32_t{ htonl(timestamp) }; } uint32_t GetSsrc() const { return uint32_t{ ntohl(this->header->ssrc) }; } void SetSsrc(uint32_t ssrc) { this->header->ssrc = uint32_t{ htonl(ssrc) }; } bool HasHeaderExtension() const { return (this->headerExtension ? true : false); } // After calling this method, all the extension ids are reset to 0. void SetExtensions(uint8_t type, const std::vector<GenericExtension>& extensions); uint16_t GetHeaderExtensionId() const { if (!this->headerExtension) return 0u; return uint16_t{ ntohs(this->headerExtension->id) }; } size_t GetHeaderExtensionLength() const { if (!this->headerExtension) return 0u; return static_cast<size_t>(ntohs(this->headerExtension->length) * 4); } uint8_t* GetHeaderExtensionValue() const { if (!this->headerExtension) return nullptr; return this->headerExtension->value; } bool HasOneByteExtensions() const { return GetHeaderExtensionId() == 0xBEDE; } bool HasTwoBytesExtensions() const { return (GetHeaderExtensionId() & 0b1111111111110000) == 0b0001000000000000; } void SetMidExtensionId(uint8_t id) { this->midExtensionId = id; } void SetRidExtensionId(uint8_t id) { this->ridExtensionId = id; } void SetRepairedRidExtensionId(uint8_t id) { this->rridExtensionId = id; } void SetAbsSendTimeExtensionId(uint8_t id) { this->absSendTimeExtensionId = id; } void SetTransportWideCc01ExtensionId(uint8_t id) { this->transportWideCc01ExtensionId = id; } // NOTE: Remove once RFC. void SetFrameMarking07ExtensionId(uint8_t id) { this->frameMarking07ExtensionId = id; } void SetFrameMarkingExtensionId(uint8_t id) { this->frameMarkingExtensionId = id; } void SetSsrcAudioLevelExtensionId(uint8_t id) { this->ssrcAudioLevelExtensionId = id; } void SetVideoOrientationExtensionId(uint8_t id) { this->videoOrientationExtensionId = id; } bool ReadMid(std::string& mid) const { uint8_t extenLen; uint8_t* extenValue = GetExtension(this->midExtensionId, extenLen); if (!extenValue || extenLen == 0u) return false; mid.assign(reinterpret_cast<const char*>(extenValue), static_cast<size_t>(extenLen)); return true; } bool UpdateMid(const std::string& mid); bool ReadRid(std::string& rid) const { // First try with the RID id then with the Repaired RID id. uint8_t extenLen; uint8_t* extenValue = GetExtension(this->ridExtensionId, extenLen); if (extenValue && extenLen > 0u) { rid.assign(reinterpret_cast<const char*>(extenValue), static_cast<size_t>(extenLen)); return true; } extenValue = GetExtension(this->rridExtensionId, extenLen); if (extenValue && extenLen > 0u) { rid.assign(reinterpret_cast<const char*>(extenValue), static_cast<size_t>(extenLen)); return true; } return false; } bool ReadAbsSendTime(uint32_t& absSendtime) const { uint8_t extenLen; uint8_t* extenValue = GetExtension(this->absSendTimeExtensionId, extenLen); if (!extenValue || extenLen != 3u) return false; absSendtime = Utils::Byte::Get3Bytes(extenValue, 0); return true; } bool UpdateAbsSendTime(uint64_t ms) { uint8_t extenLen; uint8_t* extenValue = GetExtension(this->absSendTimeExtensionId, extenLen); if (!extenValue || extenLen != 3u) return false; auto absSendTime = Utils::Time::TimeMsToAbsSendTime(ms); Utils::Byte::Set3Bytes(extenValue, 0, absSendTime); return true; } bool ReadTransportWideCc01(uint16_t& wideSeqNumber) const { uint8_t extenLen; uint8_t* extenValue = GetExtension(this->transportWideCc01ExtensionId, extenLen); if (!extenValue || extenLen != 2u) return false; wideSeqNumber = Utils::Byte::Get2Bytes(extenValue, 0); return true; } bool UpdateTransportWideCc01(uint16_t wideSeqNumber) { uint8_t extenLen; uint8_t* extenValue = GetExtension(this->transportWideCc01ExtensionId, extenLen); if (!extenValue || extenLen != 2u) return false; Utils::Byte::Set2Bytes(extenValue, 0, wideSeqNumber); return true; } bool ReadFrameMarking(RtpPacket::FrameMarking** frameMarking, uint8_t& length) const { uint8_t extenLen; uint8_t* extenValue = GetExtension(this->frameMarkingExtensionId, extenLen); // NOTE: Remove this once framemarking draft becomes RFC. if (!extenValue) extenValue = GetExtension(this->frameMarking07ExtensionId, extenLen); if (!extenValue || extenLen > 3u) return false; *frameMarking = reinterpret_cast<RtpPacket::FrameMarking*>(extenValue); length = extenLen; return true; } bool ReadSsrcAudioLevel(uint8_t& volume, bool& voice) const { uint8_t extenLen; uint8_t* extenValue = GetExtension(this->ssrcAudioLevelExtensionId, extenLen); if (!extenValue || extenLen != 1u) return false; volume = Utils::Byte::Get1Byte(extenValue, 0); voice = (volume & (1 << 7)) ? true : false; volume &= ~(1 << 7); return true; } bool ReadVideoOrientation(bool& camera, bool& flip, uint16_t& rotation) const { uint8_t extenLen; uint8_t* extenValue = GetExtension(this->videoOrientationExtensionId, extenLen); if (!extenValue || extenLen != 1u) return false; uint8_t cvoByte = Utils::Byte::Get1Byte(extenValue, 0); uint8_t cameraValue = ((cvoByte & 0b00001000) >> 3); uint8_t flipValue = ((cvoByte & 0b00000100) >> 2); uint8_t rotationValue = (cvoByte & 0b00000011); camera = cameraValue ? true : false; flip = flipValue ? true : false; // Using counter clockwise values. switch (rotationValue) { case 3: rotation = 270; break; case 2: rotation = 180; break; case 1: rotation = 90; break; default: rotation = 0; } return true; } bool HasExtension(uint8_t id) const { if (id == 0u) { return false; } else if (HasOneByteExtensions()) { auto it = this->mapOneByteExtensions.find(id); return it != this->mapOneByteExtensions.end(); } else if (HasTwoBytesExtensions()) { auto it = this->mapTwoBytesExtensions.find(id); if (it == this->mapTwoBytesExtensions.end()) return false; auto* extension = it->second; // In Two-Byte extensions value length may be zero. If so, return false. if (extension->len == 0u) return false; return true; } else { return false; } } uint8_t* GetExtension(uint8_t id, uint8_t& len) const { len = 0u; if (id == 0u) { return nullptr; } else if (HasOneByteExtensions()) { auto it = this->mapOneByteExtensions.find(id); if (it == this->mapOneByteExtensions.end()) return nullptr; auto* extension = it->second; // In One-Byte extensions value length 0 means 1. len = extension->len + 1; return extension->value; } else if (HasTwoBytesExtensions()) { auto it = this->mapTwoBytesExtensions.find(id); if (it == this->mapTwoBytesExtensions.end()) return nullptr; auto* extension = it->second; len = extension->len; // In Two-Byte extensions value length may be zero. If so, return nullptr. if (extension->len == 0u) return nullptr; return extension->value; } else { return nullptr; } } bool SetExtensionLength(uint8_t id, uint8_t len); uint8_t* GetPayload() const { return this->payloadLength != 0u ? this->payload : nullptr; } size_t GetPayloadLength() const { return this->payloadLength; } void SetPayloadLength(size_t length); uint8_t GetPayloadPadding() const { return this->payloadPadding; } uint8_t GetSpatialLayer() const { if (!this->payloadDescriptorHandler) return 0u; return this->payloadDescriptorHandler->GetSpatialLayer(); } uint8_t GetTemporalLayer() const { if (!this->payloadDescriptorHandler) return 0u; return this->payloadDescriptorHandler->GetTemporalLayer(); } bool IsKeyFrame() const { if (!this->payloadDescriptorHandler) return false; return this->payloadDescriptorHandler->IsKeyFrame(); } RtpPacket* Clone(const uint8_t* buffer) const; void RtxEncode(uint8_t payloadType, uint32_t ssrc, uint16_t seq); bool RtxDecode(uint8_t payloadType, uint32_t ssrc); void SetPayloadDescriptorHandler(RTC::Codecs::PayloadDescriptorHandler* payloadDescriptorHandler) { this->payloadDescriptorHandler.reset(payloadDescriptorHandler); } bool ProcessPayload(RTC::Codecs::EncodingContext* context); void RestorePayload(); void ShiftPayload(size_t payloadOffset, size_t shift, bool expand = true); private: void ParseExtensions(); private: // Passed by argument. Header* header{ nullptr }; uint8_t* csrcList{ nullptr }; HeaderExtension* headerExtension{ nullptr }; std::map<uint8_t, OneByteExtension*> mapOneByteExtensions; std::map<uint8_t, TwoBytesExtension*> mapTwoBytesExtensions; uint8_t midExtensionId{ 0u }; uint8_t ridExtensionId{ 0u }; uint8_t rridExtensionId{ 0u }; uint8_t absSendTimeExtensionId{ 0u }; uint8_t transportWideCc01ExtensionId{ 0u }; uint8_t frameMarking07ExtensionId{ 0u }; // NOTE: Remove once RFC. uint8_t frameMarkingExtensionId{ 0u }; uint8_t ssrcAudioLevelExtensionId{ 0u }; uint8_t videoOrientationExtensionId{ 0u }; uint8_t* payload{ nullptr }; size_t payloadLength{ 0u }; uint8_t payloadPadding{ 0u }; size_t size{ 0u }; // Full size of the packet in bytes. // Codecs std::unique_ptr<Codecs::PayloadDescriptorHandler> payloadDescriptorHandler; }; } // namespace RTC #endif