From f54707cd715e030c8162c476ab70691437fffbf9 Mon Sep 17 00:00:00 2001 From: Qiu Jianlin Date: Thu, 14 Nov 2024 19:36:37 +0800 Subject: [PATCH] Reuse VP9 simulcast stream limits for H.265. H.265 should have limits probably between VP9 and AV1, instead of using VP8 tables. For now we reuse VP9 tables but eventually we may create table for H.265. Bug: chromium:41480904 Change-Id: I6dc2ec629142ee06f1c82a2df30d753ec1353496 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/368240 Reviewed-by: Ilya Nikolaevskiy Reviewed-by: Sergey Silkin Commit-Queue: Jianlin Qiu Cr-Commit-Position: refs/heads/main@{#43404} --- video/config/simulcast.cc | 38 ++++++++++++++++++++++++++++++ video/config/simulcast_unittest.cc | 29 +++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/video/config/simulcast.cc b/video/config/simulcast.cc index 08246acffd..06a3bedb7d 100644 --- a/video/config/simulcast.cc +++ b/video/config/simulcast.cc @@ -137,6 +137,40 @@ constexpr const SimulcastFormat kSimulcastFormatsVP9[] = { webrtc::DataRate::KilobitsPerSec(0), webrtc::DataRate::KilobitsPerSec(30)}}; +// TODO(crbugs.com/41480904): For now this table is just a copy from VP9, and +// needs to be tuned for H.265. +// These tables describe from which resolution we can use how many simulcast +// layers at what bitrates (maximum, target, and minimum). +// Important!! Keep this table from high resolution to low resolution. +constexpr const SimulcastFormat kSimulcastFormatsH265[] = { + {1920, 1080, 3, webrtc::DataRate::KilobitsPerSec(3367), + webrtc::DataRate::KilobitsPerSec(3367), + webrtc::DataRate::KilobitsPerSec(769)}, + {1280, 720, 3, webrtc::DataRate::KilobitsPerSec(1524), + webrtc::DataRate::KilobitsPerSec(1524), + webrtc::DataRate::KilobitsPerSec(481)}, + {960, 540, 3, webrtc::DataRate::KilobitsPerSec(879), + webrtc::DataRate::KilobitsPerSec(879), + webrtc::DataRate::KilobitsPerSec(337)}, + {640, 360, 2, webrtc::DataRate::KilobitsPerSec(420), + webrtc::DataRate::KilobitsPerSec(420), + webrtc::DataRate::KilobitsPerSec(193)}, + {480, 270, 2, webrtc::DataRate::KilobitsPerSec(257), + webrtc::DataRate::KilobitsPerSec(257), + webrtc::DataRate::KilobitsPerSec(121)}, + {320, 180, 1, webrtc::DataRate::KilobitsPerSec(142), + webrtc::DataRate::KilobitsPerSec(142), + webrtc::DataRate::KilobitsPerSec(30)}, + {240, 135, 1, webrtc::DataRate::KilobitsPerSec(101), + webrtc::DataRate::KilobitsPerSec(101), + webrtc::DataRate::KilobitsPerSec(30)}, + // As the resolution goes down, interpolate the target and max bitrates down + // towards zero. The min bitrate is still limited at 30 kbps and the target + // and the max will be capped from below accordingly. + {0, 0, 1, webrtc::DataRate::KilobitsPerSec(0), + webrtc::DataRate::KilobitsPerSec(0), + webrtc::DataRate::KilobitsPerSec(30)}}; + constexpr webrtc::DataRate Interpolate(const webrtc::DataRate& a, const webrtc::DataRate& b, float rate) { @@ -162,6 +196,10 @@ std::vector GetSimulcastFormats( formats.insert(formats.begin(), std::begin(kSimulcastFormatsVP9), std::end(kSimulcastFormatsVP9)); break; + case webrtc::kVideoCodecH265: + formats.insert(formats.begin(), std::begin(kSimulcastFormatsH265), + std::end(kSimulcastFormatsH265)); + break; default: formats.insert(formats.begin(), std::begin(kSimulcastFormatsVP8), std::end(kSimulcastFormatsVP8)); diff --git a/video/config/simulcast_unittest.cc b/video/config/simulcast_unittest.cc index 3dd4417374..6e000a4641 100644 --- a/video/config/simulcast_unittest.cc +++ b/video/config/simulcast_unittest.cc @@ -413,4 +413,33 @@ TEST(SimulcastTest, BitratesForVP9) { EXPECT_NEAR(streams[2].min_bitrate_bps, 481000, 20000); } +#ifdef RTC_ENABLE_H265 +TEST(SimulcastTest, BitratesForH265) { + ExplicitKeyValueConfig trials(""); + + const size_t kMaxLayers = 3; + std::vector streams = cricket::GetSimulcastConfig( + CreateResolutions(/*max_width=*/1280, /*max_height=*/720, kMaxLayers), + !kScreenshare, true, trials, webrtc::kVideoCodecH265); + + ASSERT_THAT(streams, SizeIs(kMaxLayers)); + EXPECT_EQ(1280u, streams[2].width); + EXPECT_EQ(720u, streams[2].height); + EXPECT_EQ(streams[2].max_bitrate_bps, 1524000); + EXPECT_EQ(streams[2].target_bitrate_bps, 1524000); + EXPECT_EQ(streams[2].min_bitrate_bps, 481000); + + streams = cricket::GetSimulcastConfig( + CreateResolutions(/*max_width=*/1276, /*max_height=*/716, kMaxLayers), + !kScreenshare, true, trials, webrtc::kVideoCodecH265); + + ASSERT_THAT(streams, SizeIs(kMaxLayers)); + EXPECT_EQ(1276u, streams[2].width); + EXPECT_EQ(716u, streams[2].height); + EXPECT_NEAR(streams[2].max_bitrate_bps, 1524000, 20000); + EXPECT_NEAR(streams[2].target_bitrate_bps, 1524000, 20000); + EXPECT_NEAR(streams[2].min_bitrate_bps, 481000, 20000); +} +#endif + } // namespace webrtc