Use similar bitrate allocations as VP9 for H.265 simulcast streams.

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 <sprang@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#43865}
This commit is contained in:
Qiu Jianlin 2025-02-08 10:12:04 +08:00 committed by WebRTC LUCI CQ
parent be32f038a0
commit 1ad51fe73c
3 changed files with 49 additions and 1 deletions

View File

@ -320,7 +320,7 @@ std::vector<webrtc::VideoStream> 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) /

View File

@ -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<VideoStream> GetSimulcastBitrates720p() {
@ -38,6 +39,21 @@ const std::vector<VideoStream> GetSimulcastBitrates720p() {
return streams;
}
// Values from kSimulcastFormatsH265 in simulcast.cc
const std::vector<VideoStream> GetH265SimulcastBitrates720p() {
std::vector<VideoStream> 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<Resolution> CreateResolutions(int max_width,
@ -121,6 +137,35 @@ TEST(SimulcastTest, GetConfig) {
}
}
TEST(SimulcastTest, GetConfigH265) {
const ExplicitKeyValueConfig trials("");
const std::vector<VideoStream> kExpected = GetH265SimulcastBitrates720p();
const size_t kMaxLayers = 3;
std::vector<VideoStream> 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/");

View File

@ -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;
}