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