Add option for the audio encoder to allocate a bitrate range.

Bug: webrtc:15834
Change-Id: I3223162e747621983dbe2704661bb87f7890b3fa
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/338221
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Commit-Queue: Jakob Ivarsson‎ <jakobi@webrtc.org>
Reviewed-by: Tomas Lundqvist <tomasl@google.com>
Cr-Commit-Position: refs/heads/main@{#41682}
diff --git a/api/audio_codecs/BUILD.gn b/api/audio_codecs/BUILD.gn
index 2719942..fc02b2d 100644
--- a/api/audio_codecs/BUILD.gn
+++ b/api/audio_codecs/BUILD.gn
@@ -42,6 +42,7 @@
     "../../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 7f5a342..7b5ee7a 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 @@
   // 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<std::pair<TimeDelta, TimeDelta>> 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<std::pair<DataRate, DataRate>> 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 2fdb5e6..59b0ea5 100644
--- a/audio/audio_send_stream.cc
+++ b/audio/audio_send_stream.cc
@@ -333,6 +333,7 @@
       return;
     }
     frame_length_range_ = encoder->GetFrameLengthRange();
+    bitrate_range_ = encoder->GetBitrateRange();
   });
 
   if (sending_) {
@@ -848,6 +849,12 @@
   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 cf55ff6..a37c8fd 100644
--- a/audio/audio_send_stream.h
+++ b/audio/audio_send_stream.h
@@ -216,6 +216,8 @@
       false;
   absl::optional<std::pair<TimeDelta, TimeDelta>> frame_length_range_
       RTC_GUARDED_BY(worker_thread_checker_);
+  absl::optional<std::pair<DataRate, DataRate>> 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 43f2fb1..60d87eb 100644
--- a/audio/audio_send_stream_unittest.cc
+++ b/audio/audio_send_stream_unittest.cc
@@ -959,5 +959,31 @@
   send_stream->Stop();
 }
 
+TEST(AudioSendStreamTest, UseEncoderBitrateRange) {
+  ConfigHelper helper(true, true, true);
+  std::pair<DataRate, DataRate> 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<AudioCodecPairId> codec_pair_id,
+                           std::unique_ptr<AudioEncoder>* 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 1f4510e..30518e8 100644
--- a/test/mock_audio_encoder.h
+++ b/test/mock_audio_encoder.h
@@ -33,6 +33,10 @@
               GetFrameLengthRange,
               (),
               (const, override));
+  MOCK_METHOD((absl::optional<std::pair<DataRate, DataRate>>),
+              GetBitrateRange,
+              (),
+              (const, override));
 
   MOCK_METHOD(void, Reset, (), (override));
   MOCK_METHOD(bool, SetFec, (bool enable), (override));