Ensure BitrateAllocator is updated with stream max bitrate after codec change

Bug: webrtc:341803760
Change-Id: I4453cf98fa98068aa94b3e091f03304d5cd4e6dc
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/351142
Reviewed-by: Erik Språng <sprang@webrtc.org>
Commit-Queue: Per Kjellander <perkj@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#42361}
This commit is contained in:
Per K 2024-05-21 16:31:47 +00:00 committed by WebRTC LUCI CQ
parent 316fe0b133
commit dd44334bc9
2 changed files with 64 additions and 6 deletions

View File

@ -806,13 +806,12 @@ void VideoSendStreamImpl::OnEncoderConfigurationChanged(
? experimental_min_bitrate->bps() ? experimental_min_bitrate->bps()
: std::max(streams[0].min_bitrate_bps, : std::max(streams[0].min_bitrate_bps,
GetDefaultMinVideoBitrateBps(codec_type)); GetDefaultMinVideoBitrateBps(codec_type));
encoder_max_bitrate_bps_ = 0;
double stream_bitrate_priority_sum = 0; double stream_bitrate_priority_sum = 0;
uint32_t encoder_max_bitrate_bps = 0;
for (const auto& stream : streams) { for (const auto& stream : streams) {
// We don't want to allocate more bitrate than needed to inactive streams. // We don't want to allocate more bitrate than needed to inactive streams.
if (stream.active) { if (stream.active) {
encoder_max_bitrate_bps_ += stream.max_bitrate_bps; encoder_max_bitrate_bps += stream.max_bitrate_bps;
} }
if (stream.bitrate_priority) { if (stream.bitrate_priority) {
RTC_DCHECK_GT(*stream.bitrate_priority, 0); RTC_DCHECK_GT(*stream.bitrate_priority, 0);
@ -821,9 +820,11 @@ void VideoSendStreamImpl::OnEncoderConfigurationChanged(
} }
RTC_DCHECK_GT(stream_bitrate_priority_sum, 0); RTC_DCHECK_GT(stream_bitrate_priority_sum, 0);
encoder_bitrate_priority_ = stream_bitrate_priority_sum; encoder_bitrate_priority_ = stream_bitrate_priority_sum;
encoder_max_bitrate_bps_ = if (encoder_max_bitrate_bps > 0) {
std::max(static_cast<uint32_t>(encoder_min_bitrate_bps_), encoder_max_bitrate_bps_ =
encoder_max_bitrate_bps_); std::max(static_cast<uint32_t>(encoder_min_bitrate_bps_),
encoder_max_bitrate_bps);
}
// TODO(bugs.webrtc.org/10266): Query the VideoBitrateAllocator instead. // TODO(bugs.webrtc.org/10266): Query the VideoBitrateAllocator instead.
max_padding_bitrate_ = CalculateMaxPadBitrateBps( max_padding_bitrate_ = CalculateMaxPadBitrateBps(

View File

@ -73,12 +73,15 @@ namespace {
using ::testing::_; using ::testing::_;
using ::testing::AllOf; using ::testing::AllOf;
using ::testing::AnyNumber; using ::testing::AnyNumber;
using ::testing::Eq;
using ::testing::Field; using ::testing::Field;
using ::testing::Invoke; using ::testing::Invoke;
using ::testing::Mock; using ::testing::Mock;
using ::testing::NiceMock; using ::testing::NiceMock;
using ::testing::Return; using ::testing::Return;
using ::testing::SaveArg; using ::testing::SaveArg;
using ::testing::Sequence;
using ::testing::SizeIs;
constexpr int64_t kDefaultInitialBitrateBps = 333000; constexpr int64_t kDefaultInitialBitrateBps = 333000;
const double kDefaultBitratePriority = 0.5; const double kDefaultBitratePriority = 0.5;
@ -180,6 +183,7 @@ class VideoSendStreamImplTest : public ::testing::Test {
encoder_config.content_type = content_type; encoder_config.content_type = content_type;
encoder_config.simulcast_layers.push_back(VideoStream()); encoder_config.simulcast_layers.push_back(VideoStream());
encoder_config.simulcast_layers.back().active = true; encoder_config.simulcast_layers.back().active = true;
encoder_config.simulcast_layers.back().bitrate_priority = 1.0;
return encoder_config; return encoder_config;
} }
@ -274,6 +278,59 @@ TEST_F(VideoSendStreamImplTest,
vss_impl->Stop(); vss_impl->Stop();
} }
TEST_F(VideoSendStreamImplTest,
MaxBitrateCorrectIfActiveEncodingUpdatedAfterCreation) {
VideoEncoderConfig one_active_encoding = TestVideoEncoderConfig();
ASSERT_THAT(one_active_encoding.simulcast_layers, SizeIs(1));
one_active_encoding.max_bitrate_bps = 10'000'000;
one_active_encoding.simulcast_layers[0].max_bitrate_bps = 2'000'000;
VideoEncoderConfig no_active_encodings = one_active_encoding.Copy();
no_active_encodings.simulcast_layers[0].active = false;
auto vss_impl = CreateVideoSendStreamImpl(no_active_encodings.Copy());
encoder_queue_->PostTask([&] {
static_cast<VideoStreamEncoderInterface::EncoderSink*>(vss_impl.get())
->OnEncoderConfigurationChanged(
no_active_encodings.simulcast_layers, false,
VideoEncoderConfig::ContentType::kRealtimeVideo,
/*min_transmit_bitrate_bps*/ 30000);
});
time_controller_.AdvanceTime(TimeDelta::Zero());
Sequence s;
// Expect codec max bitrate as max needed bitrate before the encoder has
// notifed about the actual send streams.
EXPECT_CALL(bitrate_allocator_,
AddObserver(vss_impl.get(),
Field(&MediaStreamAllocationConfig::max_bitrate_bps,
Eq(one_active_encoding.max_bitrate_bps))))
.InSequence(s);
// Expect the sum of active encodings as max needed bitrate after
// ->OnEncoderConfigurationChanged.
EXPECT_CALL(
bitrate_allocator_,
AddObserver(
vss_impl.get(),
Field(&MediaStreamAllocationConfig::max_bitrate_bps,
Eq(one_active_encoding.simulcast_layers[0].max_bitrate_bps))))
.InSequence(s);
vss_impl->Start();
// Enable encoding of a stream.
vss_impl->ReconfigureVideoEncoder(one_active_encoding.Copy());
encoder_queue_->PostTask([&] {
static_cast<VideoStreamEncoderInterface::EncoderSink*>(vss_impl.get())
->OnEncoderConfigurationChanged(
one_active_encoding.simulcast_layers, false,
VideoEncoderConfig::ContentType::kRealtimeVideo,
/*min_transmit_bitrate_bps*/ 30000);
});
time_controller_.AdvanceTime(TimeDelta::Zero());
EXPECT_CALL(bitrate_allocator_, RemoveObserver(vss_impl.get())).InSequence(s);
vss_impl->Stop();
}
TEST_F(VideoSendStreamImplTest, TEST_F(VideoSendStreamImplTest,
DoNotRegistersAsBitrateObserverOnStrayEncodedImage) { DoNotRegistersAsBitrateObserverOnStrayEncodedImage) {
auto vss_impl = CreateVideoSendStreamImpl(TestVideoEncoderConfig()); auto vss_impl = CreateVideoSendStreamImpl(TestVideoEncoderConfig());