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));