diff --git a/api/audio_codecs/BUILD.gn b/api/audio_codecs/BUILD.gn index 2719942488..fc02b2d834 100644 --- a/api/audio_codecs/BUILD.gn +++ b/api/audio_codecs/BUILD.gn @@ -42,6 +42,7 @@ rtc_library("audio_codecs_api") { "../../rtc_base:refcount", "../../rtc_base:sanitizer", "../../rtc_base/system:rtc_export", + "../units:data_rate", "../units:time_delta", ] absl_deps = [ diff --git a/api/audio_codecs/audio_encoder.h b/api/audio_codecs/audio_encoder.h index 7f5a34214f..7b5ee7a866 100644 --- a/api/audio_codecs/audio_encoder.h +++ b/api/audio_codecs/audio_encoder.h @@ -20,6 +20,7 @@ #include "absl/types/optional.h" #include "api/array_view.h" #include "api/call/bitrate_allocation.h" +#include "api/units/data_rate.h" #include "api/units/time_delta.h" #include "rtc_base/buffer.h" @@ -240,12 +241,20 @@ class AudioEncoder { // Get statistics related to audio network adaptation. virtual ANAStats GetANAStats() const; - // The range of frame lengths that are supported or nullopt if there's no sch - // information. This is used to calculated the full bitrate range, including - // overhead. + // The range of frame lengths that are supported or nullopt if there's no such + // information. This is used together with the bitrate range to calculate the + // full bitrate range, including overhead. virtual absl::optional> GetFrameLengthRange() const = 0; + // The range of payload bitrates that are supported. This is used together + // with the frame length range to calculate the full bitrate range, including + // overhead. + virtual absl::optional> GetBitrateRange() + const { + return absl::nullopt; + } + // The maximum number of audio channels supported by WebRTC encoders. static constexpr int kMaxNumberOfChannels = 24; diff --git a/audio/audio_send_stream.cc b/audio/audio_send_stream.cc index 2fdb5e63e7..59b0ea5b5e 100644 --- a/audio/audio_send_stream.cc +++ b/audio/audio_send_stream.cc @@ -333,6 +333,7 @@ void AudioSendStream::ConfigureStream( return; } frame_length_range_ = encoder->GetFrameLengthRange(); + bitrate_range_ = encoder->GetBitrateRange(); }); if (sending_) { @@ -848,6 +849,12 @@ AudioSendStream::GetMinMaxBitrateConstraints() const { if (allocation_settings_.max_bitrate) constraints.max = *allocation_settings_.max_bitrate; + // Use encoder defined bitrate range if available. + if (bitrate_range_) { + constraints.min = bitrate_range_->first; + constraints.max = bitrate_range_->second; + } + RTC_DCHECK_GE(constraints.min, DataRate::Zero()); RTC_DCHECK_GE(constraints.max, DataRate::Zero()); if (constraints.max < constraints.min) { diff --git a/audio/audio_send_stream.h b/audio/audio_send_stream.h index cf55ff6524..a37c8fd452 100644 --- a/audio/audio_send_stream.h +++ b/audio/audio_send_stream.h @@ -216,6 +216,8 @@ class AudioSendStream final : public webrtc::AudioSendStream, false; absl::optional> frame_length_range_ RTC_GUARDED_BY(worker_thread_checker_); + absl::optional> bitrate_range_ + RTC_GUARDED_BY(worker_thread_checker_); }; } // namespace internal } // namespace webrtc diff --git a/audio/audio_send_stream_unittest.cc b/audio/audio_send_stream_unittest.cc index 43f2fb14e7..60d87eb080 100644 --- a/audio/audio_send_stream_unittest.cc +++ b/audio/audio_send_stream_unittest.cc @@ -959,5 +959,31 @@ TEST(AudioSendStreamTest, OverridesPriorityBitrate) { send_stream->Stop(); } +TEST(AudioSendStreamTest, UseEncoderBitrateRange) { + ConfigHelper helper(true, true, true); + std::pair bitrate_range{DataRate::BitsPerSec(5000), + DataRate::BitsPerSec(10000)}; + EXPECT_CALL(helper.mock_encoder_factory(), MakeAudioEncoderMock(_, _, _, _)) + .WillOnce(Invoke([&](int payload_type, const SdpAudioFormat& format, + absl::optional codec_pair_id, + std::unique_ptr* return_value) { + auto mock_encoder = SetupAudioEncoderMock(payload_type, format); + EXPECT_CALL(*mock_encoder, GetBitrateRange()) + .WillRepeatedly(Return(bitrate_range)); + *return_value = std::move(mock_encoder); + })); + auto send_stream = helper.CreateAudioSendStream(); + EXPECT_CALL(*helper.bitrate_allocator(), AddObserver(send_stream.get(), _)) + .WillOnce(Invoke( + [&](BitrateAllocatorObserver*, MediaStreamAllocationConfig config) { + EXPECT_EQ(config.min_bitrate_bps, bitrate_range.first.bps()); + EXPECT_EQ(config.max_bitrate_bps, bitrate_range.second.bps()); + })); + EXPECT_CALL(*helper.channel_send(), StartSend()); + send_stream->Start(); + EXPECT_CALL(*helper.channel_send(), StopSend()); + send_stream->Stop(); +} + } // namespace test } // namespace webrtc diff --git a/test/mock_audio_encoder.h b/test/mock_audio_encoder.h index 1f4510e885..30518e8f49 100644 --- a/test/mock_audio_encoder.h +++ b/test/mock_audio_encoder.h @@ -33,6 +33,10 @@ class MockAudioEncoder : public AudioEncoder { GetFrameLengthRange, (), (const, override)); + MOCK_METHOD((absl::optional>), + GetBitrateRange, + (), + (const, override)); MOCK_METHOD(void, Reset, (), (override)); MOCK_METHOD(bool, SetFec, (bool enable), (override));