From 1ad51fe73c2e05e66e92c8168dc4314f3be46757 Mon Sep 17 00:00:00 2001 From: Qiu Jianlin Date: Sat, 8 Feb 2025 10:12:04 +0800 Subject: [PATCH] Use similar bitrate allocations as VP9 for H.265 simulcast streams. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that there is not requirement of base-heavy for H.265 simulcast, it should follow VP9 on simulcast bitrate allocations per stream. Bug: chromium:392060821 Change-Id: I245def7f27022a943a31e96a51552db7505b7546 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/376620 Reviewed-by: Erik Språng Reviewed-by: Henrik Boström Commit-Queue: Henrik Boström Cr-Commit-Position: refs/heads/main@{#43865} --- video/config/simulcast.cc | 2 +- video/config/simulcast_unittest.cc | 45 ++++++++++++++++++++++++++++++ video/video_stream_encoder.cc | 3 ++ 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/video/config/simulcast.cc b/video/config/simulcast.cc index 4391d973f6..0893b4ca90 100644 --- a/video/config/simulcast.cc +++ b/video/config/simulcast.cc @@ -320,7 +320,7 @@ std::vector GetNormalSimulcastLayers( // Base heavy allocation increases TL0 bitrate from 40% to 60%. rate_factor = 0.4 / 0.6; } - } else { + } else if (num_temporal_layers > 3) { rate_factor = webrtc::SimulcastRateAllocator::GetTemporalRateAllocation( 3, 0, /*base_heavy_tl3_rate_alloc=*/false) / diff --git a/video/config/simulcast_unittest.cc b/video/config/simulcast_unittest.cc index f538cd7de7..cc9386c7a7 100644 --- a/video/config/simulcast_unittest.cc +++ b/video/config/simulcast_unittest.cc @@ -22,6 +22,7 @@ using ::testing::SizeIs; constexpr bool kScreenshare = true; constexpr int kDefaultTemporalLayers = 3; // Value from simulcast.cc. +constexpr int kDefaultH265TemporalLayers = 1; // Value from simulcast.cc. // Values from kSimulcastConfigs in simulcast.cc. const std::vector GetSimulcastBitrates720p() { @@ -38,6 +39,21 @@ const std::vector GetSimulcastBitrates720p() { return streams; } +// Values from kSimulcastFormatsH265 in simulcast.cc +const std::vector GetH265SimulcastBitrates720p() { + std::vector streams(3); + streams[0].min_bitrate_bps = 30'000; + streams[0].target_bitrate_bps = 142'000; + streams[0].max_bitrate_bps = 142'000; + streams[1].min_bitrate_bps = 193'000; + streams[1].target_bitrate_bps = 420'000; + streams[1].max_bitrate_bps = 420'000; + streams[2].min_bitrate_bps = 481'000; + streams[2].target_bitrate_bps = 1'524'000; + streams[2].max_bitrate_bps = 1'524'000; + return streams; +} + // Creates a vector of resolutions scaled down with 1/2 factor ordered from low // to high. std::vector CreateResolutions(int max_width, @@ -121,6 +137,35 @@ TEST(SimulcastTest, GetConfig) { } } +TEST(SimulcastTest, GetConfigH265) { + const ExplicitKeyValueConfig trials(""); + const std::vector kExpected = GetH265SimulcastBitrates720p(); + + const size_t kMaxLayers = 3; + std::vector streams = cricket::GetSimulcastConfig( + CreateResolutions(1280, 720, kMaxLayers), !kScreenshare, true, trials, + webrtc::kVideoCodecH265); + + ASSERT_THAT(streams, SizeIs(kMaxLayers)); + EXPECT_EQ(320u, streams[0].width); + EXPECT_EQ(180u, streams[0].height); + EXPECT_EQ(640u, streams[1].width); + EXPECT_EQ(360u, streams[1].height); + EXPECT_EQ(1280u, streams[2].width); + EXPECT_EQ(720u, streams[2].height); + + for (size_t i = 0; i < streams.size(); ++i) { + EXPECT_EQ(size_t{kDefaultH265TemporalLayers}, + streams[i].num_temporal_layers); + EXPECT_EQ(cricket::kDefaultVideoMaxFramerate, streams[i].max_framerate); + EXPECT_EQ(-1, streams[i].max_qp); + EXPECT_EQ(kExpected[i].min_bitrate_bps, streams[i].min_bitrate_bps); + EXPECT_EQ(kExpected[i].target_bitrate_bps, streams[i].target_bitrate_bps); + EXPECT_EQ(kExpected[i].max_bitrate_bps, streams[i].max_bitrate_bps); + EXPECT_TRUE(streams[i].active); + } +} + TEST(SimulcastTest, GetConfigWithBaseHeavyVP8TL3RateAllocation) { ExplicitKeyValueConfig trials( "WebRTC-UseBaseHeavyVP8TL3RateAllocation/Enabled/"); diff --git a/video/video_stream_encoder.cc b/video/video_stream_encoder.cc index a7e24400fb..5f5c3a9e43 100644 --- a/video/video_stream_encoder.cc +++ b/video/video_stream_encoder.cc @@ -92,6 +92,9 @@ int GetNumSpatialLayers(const VideoCodec& codec) { } else if (codec.codecType == kVideoCodecAV1 && codec.GetScalabilityMode().has_value()) { return ScalabilityModeToNumSpatialLayers(*(codec.GetScalabilityMode())); + } else if (codec.codecType == kVideoCodecH265) { + // No spatial scalability support for H.265. + return 1; } else { return 0; }