diff --git a/modules/rtp_rtcp/include/rtp_rtcp_defines.h b/modules/rtp_rtcp/include/rtp_rtcp_defines.h index 414317f2f6..8cd402e227 100644 --- a/modules/rtp_rtcp/include/rtp_rtcp_defines.h +++ b/modules/rtp_rtcp/include/rtp_rtcp_defines.h @@ -55,6 +55,7 @@ enum RTPExtensionType : int { kRtpExtensionNone, kRtpExtensionTransmissionTimeOffset, kRtpExtensionAudioLevel, + kRtpExtensionInbandComfortNoise, kRtpExtensionAbsoluteSendTime, kRtpExtensionAbsoluteCaptureTime, kRtpExtensionVideoRotation, diff --git a/modules/rtp_rtcp/source/rtp_header_extension_map.cc b/modules/rtp_rtcp/source/rtp_header_extension_map.cc index dbcdff6e4e..06f2e928f9 100644 --- a/modules/rtp_rtcp/source/rtp_header_extension_map.cc +++ b/modules/rtp_rtcp/source/rtp_header_extension_map.cc @@ -49,6 +49,7 @@ constexpr ExtensionInfo kExtensions[] = { CreateExtensionInfo(), CreateExtensionInfo(), CreateExtensionInfo(), + CreateExtensionInfo(), }; // Because of kRtpExtensionNone, NumberOfExtension is 1 bigger than the actual diff --git a/modules/rtp_rtcp/source/rtp_header_extensions.cc b/modules/rtp_rtcp/source/rtp_header_extensions.cc index e1a30c145e..800226504a 100644 --- a/modules/rtp_rtcp/source/rtp_header_extensions.cc +++ b/modules/rtp_rtcp/source/rtp_header_extensions.cc @@ -855,4 +855,49 @@ constexpr const char RepairedRtpStreamId::kUri[]; constexpr RTPExtensionType RtpMid::kId; constexpr const char RtpMid::kUri[]; +// An RTP Header Extension for Inband Comfort Noise +// +// The form of the audio level extension block: +// +// 0 1 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | ID | len=0 |N| level | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// Sample Audio Level Encoding Using the One-Byte Header Format +// +// 0 1 2 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | ID | len=1 |N| level | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// Sample Audio Level Encoding Using the Two-Byte Header Format + +constexpr RTPExtensionType InbandComfortNoiseExtension::kId; +constexpr uint8_t InbandComfortNoiseExtension::kValueSizeBytes; +constexpr const char InbandComfortNoiseExtension::kUri[]; + +bool InbandComfortNoiseExtension::Parse(rtc::ArrayView data, + absl::optional* level) { + if (data.size() != kValueSizeBytes) + return false; + *level = (data[0] & 0b1000'0000) != 0 + ? absl::nullopt + : absl::make_optional(data[0] & 0b0111'1111); + return true; +} + +bool InbandComfortNoiseExtension::Write(rtc::ArrayView data, + absl::optional level) { + RTC_DCHECK_EQ(data.size(), kValueSizeBytes); + data[0] = 0b0000'0000; + if (level) { + if (*level > 127) { + return false; + } + data[0] = 0b1000'0000 | *level; + } + return true; +} + } // namespace webrtc diff --git a/modules/rtp_rtcp/source/rtp_header_extensions.h b/modules/rtp_rtcp/source/rtp_header_extensions.h index 927c9c31fb..1cf6b2eda9 100644 --- a/modules/rtp_rtcp/source/rtp_header_extensions.h +++ b/modules/rtp_rtcp/source/rtp_header_extensions.h @@ -297,5 +297,23 @@ class RtpMid : public BaseRtpStringExtension { static constexpr const char kUri[] = "urn:ietf:params:rtp-hdrext:sdes:mid"; }; +class InbandComfortNoiseExtension { + public: + using value_type = absl::optional; + + static constexpr RTPExtensionType kId = kRtpExtensionInbandComfortNoise; + static constexpr uint8_t kValueSizeBytes = 1; + static constexpr const char kUri[] = + "http://www.webrtc.org/experiments/rtp-hdrext/inband-cn"; + + static bool Parse(rtc::ArrayView data, + absl::optional* level); + static size_t ValueSize(absl::optional level) { + return kValueSizeBytes; + } + static bool Write(rtc::ArrayView data, + absl::optional level); +}; + } // namespace webrtc #endif // MODULES_RTP_RTCP_SOURCE_RTP_HEADER_EXTENSIONS_H_ diff --git a/modules/rtp_rtcp/source/rtp_packet.cc b/modules/rtp_rtcp/source/rtp_packet.cc index 557edf0915..27c940ce49 100644 --- a/modules/rtp_rtcp/source/rtp_packet.cc +++ b/modules/rtp_rtcp/source/rtp_packet.cc @@ -193,7 +193,8 @@ void RtpPacket::ZeroMutableExtensions() { case RTPExtensionType::kRtpExtensionRepairedRtpStreamId: case RTPExtensionType::kRtpExtensionRtpStreamId: case RTPExtensionType::kRtpExtensionVideoContentType: - case RTPExtensionType::kRtpExtensionVideoRotation: { + case RTPExtensionType::kRtpExtensionVideoRotation: + case RTPExtensionType::kRtpExtensionInbandComfortNoise: { // Non-mutable extension. Don't change it. break; } diff --git a/modules/rtp_rtcp/source/rtp_utility.cc b/modules/rtp_rtcp/source/rtp_utility.cc index 21d3595506..75ee052b7c 100644 --- a/modules/rtp_rtcp/source/rtp_utility.cc +++ b/modules/rtp_rtcp/source/rtp_utility.cc @@ -543,6 +543,10 @@ void RtpHeaderParser::ParseOneByteExtensionHeader( RTC_LOG(WARNING) << "RtpExtensionColorSpace unsupported by rtp header parser."; break; + case kRtpExtensionInbandComfortNoise: + RTC_LOG(WARNING) << "Inband comfort noise extension unsupported by " + "rtp header parser."; + break; case kRtpExtensionNone: case kRtpExtensionNumberOfExtensions: { RTC_NOTREACHED() << "Invalid extension type: " << type; diff --git a/test/fuzzers/rtp_packet_fuzzer.cc b/test/fuzzers/rtp_packet_fuzzer.cc index c2347cc8bd..e256eec963 100644 --- a/test/fuzzers/rtp_packet_fuzzer.cc +++ b/test/fuzzers/rtp_packet_fuzzer.cc @@ -145,6 +145,11 @@ void FuzzOneInput(const uint8_t* data, size_t size) { packet.GetExtension(&color_space); break; } + case kRtpExtensionInbandComfortNoise: { + absl::optional noise_level; + packet.GetExtension(&noise_level); + break; + } case kRtpExtensionGenericFrameDescriptor02: // This extension requires state to read and so complicated that // deserves own fuzzer.