diff --git a/webrtc/media/engine/webrtcvoiceengine.cc b/webrtc/media/engine/webrtcvoiceengine.cc index 9871d3a21f..2ae25140b4 100644 --- a/webrtc/media/engine/webrtcvoiceengine.cc +++ b/webrtc/media/engine/webrtcvoiceengine.cc @@ -405,6 +405,24 @@ class WebRtcVoiceCodecs final { return 0; } + static rtc::ArrayView GetPacketSizesMs( + const webrtc::CodecInst& codec) { + for (size_t i = 0; i < arraysize(kCodecPrefs); ++i) { + if (IsCodec(codec, kCodecPrefs[i].name)) { + size_t num_packet_sizes = kMaxNumPacketSize; + for (int index = 0; index < kMaxNumPacketSize; index++) { + if (kCodecPrefs[i].packet_sizes_ms[index] == 0) { + num_packet_sizes = index; + break; + } + } + return rtc::ArrayView(kCodecPrefs[i].packet_sizes_ms, + num_packet_sizes); + } + } + return rtc::ArrayView(); + } + // If the AudioCodec param kCodecParamPTime is set, then we will set it to // codec pacsize if it's valid, or we will pick the next smallest value we // support. @@ -1445,8 +1463,40 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream "Enabled") { // TODO(mflodman): Keep testing this and set proper values. // Note: This is an early experiment currently only supported by Opus. - config_.min_bitrate_bps = kOpusMinBitrateBps; - config_.max_bitrate_bps = kOpusBitrateFbBps; + if (webrtc::field_trial::FindFullName( + "WebRTC-SendSideBwe-WithOverhead") == "Enabled") { + auto packet_sizes_ms = WebRtcVoiceCodecs::GetPacketSizesMs( + config_.send_codec_spec.codec_inst); + if (!packet_sizes_ms.empty()) { + int max_packet_size_ms = + *std::max_element(packet_sizes_ms.begin(), packet_sizes_ms.end()); + int min_packet_size_ms = + *std::min_element(packet_sizes_ms.begin(), packet_sizes_ms.end()); + + // Audio network adaptor will just use 20ms and 60ms frame lengths. + // The adaptor will only be active for the Opus encoder. + if (config_.audio_network_adaptor_config && + IsCodec(config_.send_codec_spec.codec_inst, kOpusCodecName)) { + max_packet_size_ms = 60; + min_packet_size_ms = 20; + } + + // OverheadPerPacket = Ipv4(20B) + UDP(8B) + SRTP(10B) + RTP(12) + constexpr int kOverheadPerPacket = 20 + 8 + 10 + 12; + + int min_overhead_bps = + kOverheadPerPacket * 8 * 1000 / max_packet_size_ms; + + int max_overhead_bps = + kOverheadPerPacket * 8 * 1000 / min_packet_size_ms; + + config_.min_bitrate_bps = kOpusMinBitrateBps + min_overhead_bps; + config_.max_bitrate_bps = kOpusBitrateFbBps + max_overhead_bps; + } + } else { + config_.min_bitrate_bps = kOpusMinBitrateBps; + config_.max_bitrate_bps = kOpusBitrateFbBps; + } } stream_ = call_->CreateAudioSendStream(config_); RTC_CHECK(stream_); diff --git a/webrtc/media/engine/webrtcvoiceengine_unittest.cc b/webrtc/media/engine/webrtcvoiceengine_unittest.cc index 0cfbeab42b..8ad5d97ce3 100644 --- a/webrtc/media/engine/webrtcvoiceengine_unittest.cc +++ b/webrtc/media/engine/webrtcvoiceengine_unittest.cc @@ -2548,6 +2548,50 @@ TEST_F(WebRtcVoiceEngineTestFake, AudioNetworkAdaptorNotGetOverridden) { GetAudioNetworkAdaptorConfig(kSsrc1)); } +class WebRtcVoiceEngineWithSendSideBweWithOverheadTest + : public WebRtcVoiceEngineTestFake { + public: + WebRtcVoiceEngineWithSendSideBweWithOverheadTest() + : WebRtcVoiceEngineTestFake( + "WebRTC-Audio-SendSideBwe/Enabled/WebRTC-SendSideBwe-WithOverhead/" + "Enabled/") {} +}; + +TEST_F(WebRtcVoiceEngineWithSendSideBweWithOverheadTest, MinAndMaxBitrate) { + EXPECT_TRUE(SetupSendStream()); + cricket::AudioSendParameters parameters; + parameters.codecs.push_back(kOpusCodec); + SetSendParameters(parameters); + const int initial_num = call_.GetNumCreatedSendStreams(); + EXPECT_EQ(initial_num, call_.GetNumCreatedSendStreams()); + + // OverheadPerPacket = Ipv4(20B) + UDP(8B) + SRTP(10B) + RTP(12) + constexpr int kOverheadPerPacket = 20 + 8 + 10 + 12; + constexpr int kMinOverheadBps = kOverheadPerPacket * 8 * 1000 / 60; + constexpr int kMaxOverheadBps = kOverheadPerPacket * 8 * 1000 / 10; + + constexpr int kOpusMinBitrateBps = 6000; + EXPECT_EQ(kOpusMinBitrateBps + kMinOverheadBps, + GetSendStreamConfig(kSsrc1).min_bitrate_bps); + constexpr int kOpusBitrateFbBps = 32000; + EXPECT_EQ(kOpusBitrateFbBps + kMaxOverheadBps, + GetSendStreamConfig(kSsrc1).max_bitrate_bps); + + parameters.options.audio_network_adaptor = rtc::Optional(true); + parameters.options.audio_network_adaptor_config = + rtc::Optional("1234"); + SetSendParameters(parameters); + + constexpr int kMinOverheadWithAnaBps = kOverheadPerPacket * 8 * 1000 / 60; + constexpr int kMaxOverheadWithAnaBps = kOverheadPerPacket * 8 * 1000 / 20; + + EXPECT_EQ(kOpusMinBitrateBps + kMinOverheadWithAnaBps, + GetSendStreamConfig(kSsrc1).min_bitrate_bps); + + EXPECT_EQ(kOpusBitrateFbBps + kMaxOverheadWithAnaBps, + GetSendStreamConfig(kSsrc1).max_bitrate_bps); +} + // Test that we can set the outgoing SSRC properly. // SSRC is set in SetupSendStream() by calling AddSendStream. TEST_F(WebRtcVoiceEngineTestFake, SetSendSsrc) {