diff --git a/api/rtp_parameters.h b/api/rtp_parameters.h index 7fe9f2bc83..3ecaaf8eeb 100644 --- a/api/rtp_parameters.h +++ b/api/rtp_parameters.h @@ -357,6 +357,11 @@ struct RTC_EXPORT RtpExtension { static constexpr char kVideoFrameTrackingIdUri[] = "http://www.webrtc.org/experiments/rtp-hdrext/video-frame-tracking-id"; + // Header extension for Mixer-to-Client audio levels per CSRC as defined in + // https://tools.ietf.org/html/rfc6465 + static constexpr char kCsrcAudioLevelsUri[] = + "urn:ietf:params:rtp-hdrext:csrc-audio-level"; + // Inclusive min and max IDs for two-byte header extensions and one-byte // header extensions, per RFC8285 Section 4.2-4.3. static constexpr int kMinId = 1; diff --git a/modules/rtp_rtcp/include/rtp_rtcp_defines.h b/modules/rtp_rtcp/include/rtp_rtcp_defines.h index d255320534..59c0f2946c 100644 --- a/modules/rtp_rtcp/include/rtp_rtcp_defines.h +++ b/modules/rtp_rtcp/include/rtp_rtcp_defines.h @@ -57,6 +57,7 @@ enum RTPExtensionType : int { kRtpExtensionNone, kRtpExtensionTransmissionTimeOffset, kRtpExtensionAudioLevel, + kRtpExtensionCsrcAudioLevel, kRtpExtensionInbandComfortNoise, kRtpExtensionAbsoluteSendTime, kRtpExtensionAbsoluteCaptureTime, diff --git a/modules/rtp_rtcp/source/rtp_header_extension_map.cc b/modules/rtp_rtcp/source/rtp_header_extension_map.cc index aebe884c0f..0b5ba474c7 100644 --- a/modules/rtp_rtcp/source/rtp_header_extension_map.cc +++ b/modules/rtp_rtcp/source/rtp_header_extension_map.cc @@ -34,6 +34,7 @@ constexpr ExtensionInfo CreateExtensionInfo() { constexpr ExtensionInfo kExtensions[] = { CreateExtensionInfo(), CreateExtensionInfo(), + CreateExtensionInfo(), CreateExtensionInfo(), CreateExtensionInfo(), CreateExtensionInfo(), diff --git a/modules/rtp_rtcp/source/rtp_header_extensions.cc b/modules/rtp_rtcp/source/rtp_header_extensions.cc index 1c3073e90d..1dd4f54759 100644 --- a/modules/rtp_rtcp/source/rtp_header_extensions.cc +++ b/modules/rtp_rtcp/source/rtp_header_extensions.cc @@ -13,6 +13,7 @@ #include #include +#include #include #include "modules/rtp_rtcp/include/rtp_cvo.h" @@ -186,6 +187,60 @@ bool AudioLevel::Write(rtc::ArrayView data, return true; } +// An RTP Header Extension for Mixer-to-Client Audio Level Indication +// +// https://tools.ietf.org/html/rfc6465 +// +// The form of the audio level extension block: +// +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | ID | len=2 |0| level 1 |0| level 2 |0| level 3 | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// Sample Audio Level Encoding Using the One-Byte Header Format +// +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | ID | len=3 |0| level 1 |0| level 2 | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// |0| level 3 | 0 (pad) | ... | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// Sample Audio Level Encoding Using the Two-Byte Header Format +constexpr RTPExtensionType CsrcAudioLevel::kId; +constexpr uint8_t CsrcAudioLevel::kMaxValueSizeBytes; +constexpr const char CsrcAudioLevel::kUri[]; + +bool CsrcAudioLevel::Parse(rtc::ArrayView data, + std::vector* csrc_audio_levels) { + if (data.size() > kRtpCsrcSize) { + return false; + } + csrc_audio_levels->resize(data.size()); + for (size_t i = 0; i < data.size(); i++) { + (*csrc_audio_levels)[i] = data[i] & 0x7F; + } + return true; +} + +size_t CsrcAudioLevel::ValueSize( + rtc::ArrayView csrc_audio_levels) { + return csrc_audio_levels.size(); +} + +bool CsrcAudioLevel::Write(rtc::ArrayView data, + rtc::ArrayView csrc_audio_levels) { + RTC_CHECK_LE(csrc_audio_levels.size(), kRtpCsrcSize); + if (csrc_audio_levels.size() != data.size()) { + return false; + } + for (size_t i = 0; i < csrc_audio_levels.size(); i++) { + data[i] = csrc_audio_levels[i] & 0x7F; + } + return true; +} + // From RFC 5450: Transmission Time Offsets in RTP Streams. // // The transmission time is signaled to the receiver in-band using the diff --git a/modules/rtp_rtcp/source/rtp_header_extensions.h b/modules/rtp_rtcp/source/rtp_header_extensions.h index f6e7a579ab..b47824afdb 100644 --- a/modules/rtp_rtcp/source/rtp_header_extensions.h +++ b/modules/rtp_rtcp/source/rtp_header_extensions.h @@ -14,6 +14,7 @@ #include #include +#include #include "api/array_view.h" #include "api/rtp_headers.h" @@ -77,6 +78,20 @@ class AudioLevel { uint8_t audio_level); }; +class CsrcAudioLevel { + public: + static constexpr RTPExtensionType kId = kRtpExtensionCsrcAudioLevel; + static constexpr uint8_t kMaxValueSizeBytes = 15; + static constexpr const char kUri[] = + "urn:ietf:params:rtp-hdrext:csrc-audio-level"; + + static bool Parse(rtc::ArrayView data, + std::vector* csrc_audio_levels); + static size_t ValueSize(rtc::ArrayView csrc_audio_levels); + static bool Write(rtc::ArrayView data, + rtc::ArrayView csrc_audio_levels); +}; + class TransmissionOffset { public: using value_type = int32_t; diff --git a/modules/rtp_rtcp/source/rtp_packet.cc b/modules/rtp_rtcp/source/rtp_packet.cc index 84769d0f4b..ce13b7d9d4 100644 --- a/modules/rtp_rtcp/source/rtp_packet.cc +++ b/modules/rtp_rtcp/source/rtp_packet.cc @@ -186,6 +186,7 @@ void RtpPacket::ZeroMutableExtensions() { break; } case RTPExtensionType::kRtpExtensionAudioLevel: + case RTPExtensionType::kRtpExtensionCsrcAudioLevel: case RTPExtensionType::kRtpExtensionAbsoluteCaptureTime: case RTPExtensionType::kRtpExtensionColorSpace: case RTPExtensionType::kRtpExtensionGenericFrameDescriptor00: diff --git a/modules/rtp_rtcp/source/rtp_sender.cc b/modules/rtp_rtcp/source/rtp_sender.cc index 8435e5f33d..80c319f4f2 100644 --- a/modules/rtp_rtcp/source/rtp_sender.cc +++ b/modules/rtp_rtcp/source/rtp_sender.cc @@ -104,6 +104,7 @@ bool IsNonVolatile(RTPExtensionType type) { switch (type) { case kRtpExtensionTransmissionTimeOffset: case kRtpExtensionAudioLevel: + case kRtpExtensionCsrcAudioLevel: case kRtpExtensionAbsoluteSendTime: case kRtpExtensionTransportSequenceNumber: case kRtpExtensionTransportSequenceNumber02: diff --git a/modules/rtp_rtcp/source/rtp_utility.cc b/modules/rtp_rtcp/source/rtp_utility.cc index a22785faca..d7df1830ce 100644 --- a/modules/rtp_rtcp/source/rtp_utility.cc +++ b/modules/rtp_rtcp/source/rtp_utility.cc @@ -364,6 +364,10 @@ void RtpHeaderParser::ParseOneByteExtensionHeader( header->extension.hasTransmissionTimeOffset = true; break; } + case kRtpExtensionCsrcAudioLevel: { + RTC_LOG(LS_WARNING) << "Csrc audio level extension not supported"; + return; + } case kRtpExtensionAudioLevel: { if (len != 0) { RTC_LOG(LS_WARNING) << "Incorrect audio level len: " << len; diff --git a/test/fuzzers/rtp_packet_fuzzer.cc b/test/fuzzers/rtp_packet_fuzzer.cc index 9e8fd6f4c1..5f649fe3d7 100644 --- a/test/fuzzers/rtp_packet_fuzzer.cc +++ b/test/fuzzers/rtp_packet_fuzzer.cc @@ -9,6 +9,7 @@ */ #include +#include #include "absl/types/optional.h" #include "modules/rtp_rtcp/include/rtp_header_extension_map.h" @@ -76,6 +77,11 @@ void FuzzOneInput(const uint8_t* data, size_t size) { uint8_t audio_level; packet.GetExtension(&voice_activity, &audio_level); break; + case kRtpExtensionCsrcAudioLevel: { + std::vector audio_levels; + packet.GetExtension(&audio_levels); + break; + } case kRtpExtensionAbsoluteSendTime: uint32_t sendtime; packet.GetExtension(&sendtime);