From 798e45187873d45b9251e56b9ff3345909af958e Mon Sep 17 00:00:00 2001 From: Dan Tan Date: Thu, 18 Jan 2024 11:13:32 -0800 Subject: [PATCH] Adds WebRTC-AV1-OverridePriorityBitrate to change bit rate allocation between audio and video MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: webrtc:15763 Change-Id: If53cb2750756e40a226097638f2a3c96e154e83d Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/333984 Commit-Queue: Dan Tan Reviewed-by: Sergey Silkin Reviewed-by: Erik Språng Cr-Commit-Position: refs/heads/main@{#41586} --- experiments/field_trials.py | 3 + video/video_send_stream_impl.cc | 17 +++++- video/video_send_stream_impl.h | 2 + video/video_send_stream_impl_unittest.cc | 77 +++++++++++++++++++++++- 4 files changed, 97 insertions(+), 2 deletions(-) diff --git a/experiments/field_trials.py b/experiments/field_trials.py index 82761a2659..4aa9bcbe4b 100755 --- a/experiments/field_trials.py +++ b/experiments/field_trials.py @@ -50,6 +50,9 @@ ACTIVE_FIELD_TRIALS: FrozenSet[FieldTrial] = frozenset([ FieldTrial('WebRTC-Audio-OpusSetSignalVoiceWithDtx', 'webrtc:4559', date(2024, 4, 1)), + FieldTrial('WebRTC-AV1-OverridePriorityBitrate', + 'webrtc:15763', + date(2024, 4, 1)), FieldTrial('WebRTC-Av1-GetEncoderInfoOverride', 'webrtc:14931', date(2024, 4, 1)), diff --git a/video/video_send_stream_impl.cc b/video/video_send_stream_impl.cc index 91790afded..23dbb7177f 100644 --- a/video/video_send_stream_impl.cc +++ b/video/video_send_stream_impl.cc @@ -224,6 +224,19 @@ absl::optional GetConfiguredPacingFactor( default_pacing_config.pacing_factor); } +int GetEncoderPriorityBitrate(std::string codec_name, + const FieldTrialsView& field_trials) { + int priority_bitrate = 0; + if (PayloadStringToCodecType(codec_name) == VideoCodecType::kVideoCodecAV1) { + webrtc::FieldTrialParameter av1_priority_bitrate("bitrate", 0); + webrtc::ParseFieldTrial( + {&av1_priority_bitrate}, + field_trials.Lookup("WebRTC-AV1-OverridePriorityBitrate")); + priority_bitrate = av1_priority_bitrate; + } + return priority_bitrate; +} + uint32_t GetInitialEncoderMaxBitrate(int initial_encoder_max_bitrate) { if (initial_encoder_max_bitrate > 0) return rtc::dchecked_cast(initial_encoder_max_bitrate); @@ -432,6 +445,8 @@ VideoSendStreamImpl::VideoSendStreamImpl( GetInitialEncoderMaxBitrate(encoder_config.max_bitrate_bps)), encoder_target_rate_bps_(0), encoder_bitrate_priority_(encoder_config.bitrate_priority), + encoder_av1_priority_bitrate_override_bps_( + GetEncoderPriorityBitrate(config_.rtp.payload_name, field_trials)), configured_pacing_factor_(GetConfiguredPacingFactor(config_, content_type_, pacing_config_, @@ -757,7 +772,7 @@ MediaStreamAllocationConfig VideoSendStreamImpl::GetAllocationConfig() const { static_cast(encoder_min_bitrate_bps_), encoder_max_bitrate_bps_, static_cast(disable_padding_ ? 0 : max_padding_bitrate_), - /* priority_bitrate */ 0, + encoder_av1_priority_bitrate_override_bps_, !config_.suspend_below_min_bitrate, encoder_bitrate_priority_}; } diff --git a/video/video_send_stream_impl.h b/video/video_send_stream_impl.h index 89fb9db93b..758e12c095 100644 --- a/video/video_send_stream_impl.h +++ b/video/video_send_stream_impl.h @@ -218,6 +218,8 @@ class VideoSendStreamImpl : public webrtc::VideoSendStream, uint32_t encoder_max_bitrate_bps_ RTC_GUARDED_BY(thread_checker_); uint32_t encoder_target_rate_bps_ RTC_GUARDED_BY(thread_checker_); double encoder_bitrate_priority_ RTC_GUARDED_BY(thread_checker_); + const int encoder_av1_priority_bitrate_override_bps_ + RTC_GUARDED_BY(thread_checker_); ScopedTaskSafety worker_queue_safety_; diff --git a/video/video_send_stream_impl_unittest.cc b/video/video_send_stream_impl_unittest.cc index 9d003dcc03..ba492ae66f 100644 --- a/video/video_send_stream_impl_unittest.cc +++ b/video/video_send_stream_impl_unittest.cc @@ -175,7 +175,8 @@ class VideoSendStreamImplTest : public ::testing::Test { std::unique_ptr CreateVideoSendStreamImpl( int initial_encoder_max_bitrate, double initial_encoder_bitrate_priority, - VideoEncoderConfig::ContentType content_type) { + VideoEncoderConfig::ContentType content_type, + absl::optional codec = std::nullopt) { EXPECT_CALL(bitrate_allocator_, GetStartBitrate(_)) .WillOnce(Return(123000)); @@ -183,6 +184,9 @@ class VideoSendStreamImplTest : public ::testing::Test { encoder_config.max_bitrate_bps = initial_encoder_max_bitrate; encoder_config.bitrate_priority = initial_encoder_bitrate_priority; encoder_config.content_type = content_type; + if (codec) { + config_.rtp.payload_name = *codec; + } std::map suspended_ssrcs; std::map suspended_payload_states; @@ -190,6 +194,7 @@ class VideoSendStreamImplTest : public ::testing::Test { std::unique_ptr> video_stream_encoder = std::make_unique>(); video_stream_encoder_ = video_stream_encoder.get(); + auto ret = std::make_unique( time_controller_.GetClock(), /*num_cpu_cores=*/1, time_controller_.GetTaskQueueFactory(), @@ -714,6 +719,76 @@ TEST_F(VideoSendStreamImplTest, ForwardsVideoBitrateAllocationAfterTimeout) { vss_impl->Stop(); } +TEST_F(VideoSendStreamImplTest, PriorityBitrateConfigInactiveByDefault) { + auto vss_impl = CreateVideoSendStreamImpl( + kDefaultInitialBitrateBps, kDefaultBitratePriority, + VideoEncoderConfig::ContentType::kRealtimeVideo); + EXPECT_CALL( + bitrate_allocator_, + AddObserver( + vss_impl.get(), + Field(&MediaStreamAllocationConfig::priority_bitrate_bps, 0))); + vss_impl->StartPerRtpStream({true}); + EXPECT_CALL(bitrate_allocator_, RemoveObserver(vss_impl.get())).Times(1); + vss_impl->Stop(); +} + +TEST_F(VideoSendStreamImplTest, PriorityBitrateConfigAffectsAV1) { + test::ScopedFieldTrials override_priority_bitrate( + "WebRTC-AV1-OverridePriorityBitrate/bitrate:20000/"); + auto vss_impl = CreateVideoSendStreamImpl( + kDefaultInitialBitrateBps, kDefaultBitratePriority, + VideoEncoderConfig::ContentType::kRealtimeVideo, "AV1"); + EXPECT_CALL( + bitrate_allocator_, + AddObserver( + vss_impl.get(), + Field(&MediaStreamAllocationConfig::priority_bitrate_bps, 20000))); + vss_impl->StartPerRtpStream({true}); + EXPECT_CALL(bitrate_allocator_, RemoveObserver(vss_impl.get())).Times(1); + vss_impl->Stop(); +} + +TEST_F(VideoSendStreamImplTest, + PriorityBitrateConfigSurvivesConfigurationChange) { + VideoStream qvga_stream; + qvga_stream.width = 320; + qvga_stream.height = 180; + qvga_stream.max_framerate = 30; + qvga_stream.min_bitrate_bps = 30000; + qvga_stream.target_bitrate_bps = 150000; + qvga_stream.max_bitrate_bps = 200000; + qvga_stream.max_qp = 56; + qvga_stream.bitrate_priority = 1; + + int min_transmit_bitrate_bps = 30000; + + test::ScopedFieldTrials override_priority_bitrate( + "WebRTC-AV1-OverridePriorityBitrate/bitrate:20000/"); + auto vss_impl = CreateVideoSendStreamImpl( + kDefaultInitialBitrateBps, kDefaultBitratePriority, + VideoEncoderConfig::ContentType::kRealtimeVideo, "AV1"); + EXPECT_CALL( + bitrate_allocator_, + AddObserver( + vss_impl.get(), + Field(&MediaStreamAllocationConfig::priority_bitrate_bps, 20000))) + .Times(2); + vss_impl->StartPerRtpStream({true}); + + encoder_queue_->PostTask([&] { + static_cast(vss_impl.get()) + ->OnEncoderConfigurationChanged( + std::vector{qvga_stream}, false, + VideoEncoderConfig::ContentType::kRealtimeVideo, + min_transmit_bitrate_bps); + }); + time_controller_.AdvanceTime(TimeDelta::Zero()); + + EXPECT_CALL(bitrate_allocator_, RemoveObserver(vss_impl.get())).Times(1); + vss_impl->Stop(); +} + TEST_F(VideoSendStreamImplTest, CallsVideoStreamEncoderOnBitrateUpdate) { const bool kSuspend = false; config_.suspend_below_min_bitrate = kSuspend;