Update simulcast bitrate calculations for non-standard resolutions.

* Increase 540p bitrate to 1.2mbps from 0.9mpbs.
960x540 bitrate was by far smallest in terms of bits per pixel. This change
brings it closer to other resolutions.

* Interpolate max/target/min bitrates for non-standard resolutions based
on number of pixels.

Bug: webrtc:10965
Change-Id: If0aa56bb4c614ca09ee39d3a2b700aab2ffa1a2c
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/152828
Commit-Queue: Ilya Nikolaevskiy <ilnik@webrtc.org>
Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29195}
This commit is contained in:
Ilya Nikolaevskiy 2019-09-16 14:53:29 +02:00 committed by Commit Bot
parent 1b6a30ddcc
commit 73ceed58f8
2 changed files with 71 additions and 8 deletions

View File

@ -74,7 +74,7 @@ struct SimulcastFormat {
const SimulcastFormat kSimulcastFormats[] = {
{1920, 1080, 3, 5000, 4000, 800},
{1280, 720, 3, 2500, 2500, 600},
{960, 540, 3, 900, 900, 450},
{960, 540, 3, 1200, 1200, 350},
{640, 360, 2, 700, 500, 150},
{480, 270, 2, 450, 350, 150},
{320, 180, 1, 200, 150, 30},
@ -143,19 +143,46 @@ int NormalizeSimulcastSize(int size, size_t simulcast_layers) {
return ((size >> base2_exponent) << base2_exponent);
}
SimulcastFormat InterpolateSimulcastFormat(int width, int height) {
const int index = FindSimulcastFormatIndex(width, height);
if (index == 0)
return kSimulcastFormats[index];
const int total_pixels_up =
kSimulcastFormats[index - 1].width * kSimulcastFormats[index - 1].height;
const int total_pixels_down =
kSimulcastFormats[index].width * kSimulcastFormats[index].height;
const int total_pixels = width * height;
const float rate = (total_pixels_up - total_pixels) /
static_cast<float>(total_pixels_up - total_pixels_down);
SimulcastFormat res;
res.width = width;
res.height = height;
res.max_layers = kSimulcastFormats[index].max_layers;
res.max_bitrate_kbps =
kSimulcastFormats[index - 1].max_bitrate_kbps * (1.0 - rate) +
kSimulcastFormats[index].max_bitrate_kbps * rate;
res.target_bitrate_kbps =
kSimulcastFormats[index - 1].target_bitrate_kbps * (1.0 - rate) +
kSimulcastFormats[index].target_bitrate_kbps * rate;
res.min_bitrate_kbps =
kSimulcastFormats[index - 1].min_bitrate_kbps * (1.0 - rate) +
kSimulcastFormats[index].min_bitrate_kbps * rate;
return res;
}
int FindSimulcastMaxBitrateBps(int width, int height) {
const int format_index = FindSimulcastFormatIndex(width, height);
return kSimulcastFormats[format_index].max_bitrate_kbps * 1000;
const SimulcastFormat format = InterpolateSimulcastFormat(width, height);
return format.max_bitrate_kbps * 1000;
}
int FindSimulcastTargetBitrateBps(int width, int height) {
const int format_index = FindSimulcastFormatIndex(width, height);
return kSimulcastFormats[format_index].target_bitrate_kbps * 1000;
const SimulcastFormat format = InterpolateSimulcastFormat(width, height);
return format.target_bitrate_kbps * 1000;
}
int FindSimulcastMinBitrateBps(int width, int height) {
const int format_index = FindSimulcastFormatIndex(width, height);
return kSimulcastFormats[format_index].min_bitrate_kbps * 1000;
const SimulcastFormat format = InterpolateSimulcastFormat(width, height);
return format.min_bitrate_kbps * 1000;
}
void BoostMaxSimulcastLayer(int max_bitrate_bps,

View File

@ -262,7 +262,7 @@ TEST(SimulcastTest, GetConfigForScreenshareSimulcastWithLimitedMaxLayers) {
TEST(SimulcastTest, SimulcastScreenshareMaxBitrateAdjustedForResolution) {
constexpr int kScreenshareHighStreamMinBitrateBps = 600000;
constexpr int kScreenshareHighStreamMaxBitrateBps = 1250000;
constexpr int kMaxBitrate960_540 = 900000;
constexpr int kMaxBitrate960_540 = 1200000;
// Normal case, max bitrate not limited by resolution.
const size_t kMaxLayers = 2;
@ -291,4 +291,40 @@ TEST(SimulcastTest, SimulcastScreenshareMaxBitrateAdjustedForResolution) {
EXPECT_GE(streams[1].max_bitrate_bps, streams[1].min_bitrate_bps);
}
TEST(SimulcastTest, AveragesBitratesForNonStandardResolution) {
const size_t kMaxLayers = 3;
std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
kMaxLayers, 900, 800, kBitratePriority, kQpMax, !kScreenshare);
EXPECT_EQ(kMaxLayers, streams.size());
EXPECT_EQ(900u, streams[2].width);
EXPECT_EQ(800u, streams[2].height);
EXPECT_EQ(1850000, streams[2].max_bitrate_bps);
EXPECT_EQ(1850000, streams[2].target_bitrate_bps);
EXPECT_EQ(475000, streams[2].min_bitrate_bps);
}
TEST(SimulcastTest, BitratesForCloseToStandardResolution) {
const size_t kMaxLayers = 3;
// Resolution very close to 720p in number of pixels
const size_t kWidth = 1280;
const size_t kHeight = 716;
const std::vector<VideoStream> kExpectedNear = GetSimulcastBitrates720p();
std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
kMaxLayers, kWidth, kHeight, kBitratePriority, kQpMax, !kScreenshare);
EXPECT_EQ(kMaxLayers, streams.size());
EXPECT_EQ(kWidth, streams[2].width);
EXPECT_EQ(kHeight, streams[2].height);
for (size_t i = 0; i < streams.size(); ++i) {
EXPECT_NEAR(kExpectedNear[i].max_bitrate_bps, streams[i].max_bitrate_bps,
20000);
EXPECT_NEAR(kExpectedNear[i].target_bitrate_bps,
streams[i].target_bitrate_bps, 20000);
EXPECT_NEAR(kExpectedNear[i].min_bitrate_bps, streams[i].min_bitrate_bps,
20000);
}
}
} // namespace webrtc