Configure default bitrate targets for VP9 simulcast
Bug: webrtc:15852
Change-Id: Icab74d4eafe4cfb95dace7ae0e3e5810f3052204
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/340441
Commit-Queue: Ilya Nikolaevskiy <ilnik@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#41908}
diff --git a/video/config/encoder_stream_factory.cc b/video/config/encoder_stream_factory.cc
index a4e41ad..2528a1b 100644
--- a/video/config/encoder_stream_factory.cc
+++ b/video/config/encoder_stream_factory.cc
@@ -320,7 +320,8 @@
encoder_config.number_of_streams, width, height,
encoder_config.bitrate_priority, max_qp_,
is_screenshare_ && conference_mode_,
- temporal_layers_supported, trials_);
+ temporal_layers_supported, trials_,
+ encoder_config.codec_type);
// Allow an experiment to override the minimum bitrate for the lowest
// spatial layer. The experiment's configuration has the lowest priority.
if (experimental_min_bitrate) {
diff --git a/video/config/simulcast.cc b/video/config/simulcast.cc
index 7a78ef8..2c600c8 100644
--- a/video/config/simulcast.cc
+++ b/video/config/simulcast.cc
@@ -76,7 +76,7 @@
// 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 kSimulcastFormats[] = {
+constexpr const SimulcastFormat kSimulcastFormatsVP8[] = {
{1920, 1080, 3, webrtc::DataRate::KilobitsPerSec(5000),
webrtc::DataRate::KilobitsPerSec(4000),
webrtc::DataRate::KilobitsPerSec(800)},
@@ -102,6 +102,38 @@
webrtc::DataRate::KilobitsPerSec(0),
webrtc::DataRate::KilobitsPerSec(30)}};
+// 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 kSimulcastFormatsVP9[] = {
+ {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(49)},
+ {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) {
@@ -115,10 +147,23 @@
}
std::vector<SimulcastFormat> GetSimulcastFormats(
- bool enable_lowres_bitrate_interpolation) {
+ bool enable_lowres_bitrate_interpolation,
+ webrtc::VideoCodecType codec) {
std::vector<SimulcastFormat> formats;
- formats.insert(formats.begin(), std::begin(kSimulcastFormats),
- std::end(kSimulcastFormats));
+ switch (codec) {
+ case webrtc::kVideoCodecVP8:
+ formats.insert(formats.begin(), std::begin(kSimulcastFormatsVP8),
+ std::end(kSimulcastFormatsVP8));
+ break;
+ case webrtc::kVideoCodecVP9:
+ formats.insert(formats.begin(), std::begin(kSimulcastFormatsVP9),
+ std::end(kSimulcastFormatsVP9));
+ break;
+ default:
+ formats.insert(formats.begin(), std::begin(kSimulcastFormatsVP8),
+ std::end(kSimulcastFormatsVP8));
+ break;
+ }
if (!enable_lowres_bitrate_interpolation) {
RTC_CHECK_GE(formats.size(), 2u);
SimulcastFormat& format0x0 = formats[formats.size() - 1];
@@ -153,10 +198,12 @@
int FindSimulcastFormatIndex(int width,
int height,
- bool enable_lowres_bitrate_interpolation) {
+ bool enable_lowres_bitrate_interpolation,
+ webrtc::VideoCodecType codec) {
RTC_DCHECK_GE(width, 0);
RTC_DCHECK_GE(height, 0);
- const auto formats = GetSimulcastFormats(enable_lowres_bitrate_interpolation);
+ const auto formats =
+ GetSimulcastFormats(enable_lowres_bitrate_interpolation, codec);
for (uint32_t i = 0; i < formats.size(); ++i) {
if (width * height >= formats[i].width * formats[i].height) {
return i;
@@ -186,10 +233,12 @@
int width,
int height,
absl::optional<double> max_roundup_rate,
- bool enable_lowres_bitrate_interpolation) {
- const auto formats = GetSimulcastFormats(enable_lowres_bitrate_interpolation);
+ bool enable_lowres_bitrate_interpolation,
+ webrtc::VideoCodecType codec) {
+ const auto formats =
+ GetSimulcastFormats(enable_lowres_bitrate_interpolation, codec);
const int index = FindSimulcastFormatIndex(
- width, height, enable_lowres_bitrate_interpolation);
+ width, height, enable_lowres_bitrate_interpolation, codec);
if (index == 0)
return formats[index];
const int total_pixels_up =
@@ -216,35 +265,39 @@
SimulcastFormat InterpolateSimulcastFormat(
int width,
int height,
- bool enable_lowres_bitrate_interpolation) {
+ bool enable_lowres_bitrate_interpolation,
+ webrtc::VideoCodecType codec) {
return InterpolateSimulcastFormat(width, height, absl::nullopt,
- enable_lowres_bitrate_interpolation);
+ enable_lowres_bitrate_interpolation, codec);
}
webrtc::DataRate FindSimulcastMaxBitrate(
int width,
int height,
- bool enable_lowres_bitrate_interpolation) {
+ bool enable_lowres_bitrate_interpolation,
+ webrtc::VideoCodecType codec) {
return InterpolateSimulcastFormat(width, height,
- enable_lowres_bitrate_interpolation)
+ enable_lowres_bitrate_interpolation, codec)
.max_bitrate;
}
webrtc::DataRate FindSimulcastTargetBitrate(
int width,
int height,
- bool enable_lowres_bitrate_interpolation) {
+ bool enable_lowres_bitrate_interpolation,
+ webrtc::VideoCodecType codec) {
return InterpolateSimulcastFormat(width, height,
- enable_lowres_bitrate_interpolation)
+ enable_lowres_bitrate_interpolation, codec)
.target_bitrate;
}
webrtc::DataRate FindSimulcastMinBitrate(
int width,
int height,
- bool enable_lowres_bitrate_interpolation) {
+ bool enable_lowres_bitrate_interpolation,
+ webrtc::VideoCodecType codec) {
return InterpolateSimulcastFormat(width, height,
- enable_lowres_bitrate_interpolation)
+ enable_lowres_bitrate_interpolation, codec)
.min_bitrate;
}
@@ -280,7 +333,8 @@
int height,
size_t need_layers,
size_t layer_count,
- const webrtc::FieldTrialsView& trials) {
+ const webrtc::FieldTrialsView& trials,
+ webrtc::VideoCodecType codec) {
if (!absl::StartsWith(trials.Lookup(kUseLegacySimulcastLayerLimitFieldTrial),
"Disabled")) {
// Max layers from one higher resolution in kSimulcastFormats will be used
@@ -296,7 +350,7 @@
size_t adaptive_layer_count = std::max(
need_layers,
InterpolateSimulcastFormat(width, height, max_ratio.GetOptional(),
- enable_lowres_bitrate_interpolation)
+ enable_lowres_bitrate_interpolation, codec)
.max_layers);
if (layer_count > adaptive_layer_count) {
RTC_LOG(LS_WARNING) << "Reducing simulcast layer count from "
@@ -316,7 +370,8 @@
int max_qp,
bool is_screenshare_with_conference_mode,
bool temporal_layers_supported,
- const webrtc::FieldTrialsView& trials) {
+ const webrtc::FieldTrialsView& trials,
+ webrtc::VideoCodecType codec) {
RTC_DCHECK_LE(min_layers, max_layers);
RTC_DCHECK(max_layers > 1 || is_screenshare_with_conference_mode);
@@ -331,12 +386,12 @@
// Some applications rely on the old behavior limiting the simulcast layer
// count based on the resolution automatically, which they can get through
// the WebRTC-LegacySimulcastLayerLimit field trial until they update.
- max_layers =
- LimitSimulcastLayerCount(width, height, min_layers, max_layers, trials);
+ max_layers = LimitSimulcastLayerCount(width, height, min_layers, max_layers,
+ trials, codec);
return GetNormalSimulcastLayers(max_layers, width, height, bitrate_priority,
max_qp, temporal_layers_supported,
- base_heavy_tl3_rate_alloc, trials);
+ base_heavy_tl3_rate_alloc, trials, codec);
}
}
@@ -348,7 +403,8 @@
int max_qp,
bool temporal_layers_supported,
bool base_heavy_tl3_rate_alloc,
- const webrtc::FieldTrialsView& trials) {
+ const webrtc::FieldTrialsView& trials,
+ webrtc::VideoCodecType codec) {
std::vector<webrtc::VideoStream> layers(layer_count);
const bool enable_lowres_bitrate_interpolation =
EnableLowresBitrateInterpolation(trials);
@@ -368,11 +424,11 @@
temporal_layers_supported ? num_temporal_layers : 1;
layers[s].max_bitrate_bps =
FindSimulcastMaxBitrate(width, height,
- enable_lowres_bitrate_interpolation)
+ enable_lowres_bitrate_interpolation, codec)
.bps();
layers[s].target_bitrate_bps =
FindSimulcastTargetBitrate(width, height,
- enable_lowres_bitrate_interpolation)
+ enable_lowres_bitrate_interpolation, codec)
.bps();
if (s == 0) {
// If alternative temporal rate allocation is selected, adjust the
@@ -401,7 +457,7 @@
}
layers[s].min_bitrate_bps =
FindSimulcastMinBitrate(width, height,
- enable_lowres_bitrate_interpolation)
+ enable_lowres_bitrate_interpolation, codec)
.bps();
// Ensure consistency.
diff --git a/video/config/simulcast.h b/video/config/simulcast.h
index 32af168..4bd9993 100644
--- a/video/config/simulcast.h
+++ b/video/config/simulcast.h
@@ -43,7 +43,8 @@
int max_qp,
bool is_screenshare_with_conference_mode,
bool temporal_layers_supported,
- const webrtc::FieldTrialsView& trials);
+ const webrtc::FieldTrialsView& trials,
+ webrtc::VideoCodecType codec);
// Gets the simulcast config layers for a non-screensharing case.
std::vector<webrtc::VideoStream> GetNormalSimulcastLayers(
@@ -54,7 +55,8 @@
int max_qp,
bool temporal_layers_supported,
bool base_heavy_tl3_rate_alloc,
- const webrtc::FieldTrialsView& trials);
+ const webrtc::FieldTrialsView& trials,
+ webrtc::VideoCodecType codec);
// Gets simulcast config layers for screenshare settings.
std::vector<webrtc::VideoStream> GetScreenshareLayers(
diff --git a/video/config/simulcast_unittest.cc b/video/config/simulcast_unittest.cc
index 152a0f9..8dbc003 100644
--- a/video/config/simulcast_unittest.cc
+++ b/video/config/simulcast_unittest.cc
@@ -86,7 +86,7 @@
const size_t kMaxLayers = 3;
std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
kMinLayers, kMaxLayers, 1280, 720, kBitratePriority, kQpMax,
- !kScreenshare, true, trials);
+ !kScreenshare, true, trials, webrtc::kVideoCodecVP8);
EXPECT_EQ(kMaxLayers, streams.size());
EXPECT_EQ(320u, streams[0].width);
@@ -122,7 +122,7 @@
const size_t kMaxLayers = 3;
std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
kMinLayers, kMaxLayers, 1280, 720, kBitratePriority, kQpMax,
- !kScreenshare, true, trials);
+ !kScreenshare, true, trials, webrtc::kVideoCodecVP8);
EXPECT_EQ(kExpected[0].min_bitrate_bps, streams[0].min_bitrate_bps);
EXPECT_EQ(static_cast<int>(0.4 * kExpected[0].target_bitrate_bps / 0.6),
@@ -142,7 +142,7 @@
FieldTrialBasedConfig trials;
std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
kMinLayers, kMaxLayers, 1280, 720, kBitratePriority, kQpMax,
- !kScreenshare, true, trials);
+ !kScreenshare, true, trials, webrtc::kVideoCodecVP8);
EXPECT_EQ(kMaxLayers, streams.size());
EXPECT_EQ(640u, streams[0].width);
@@ -159,7 +159,7 @@
const size_t kMaxLayers = 3;
std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
kMinLayers, kMaxLayers, 800, 600, kBitratePriority, kQpMax, !kScreenshare,
- true, trials);
+ true, trials, webrtc::kVideoCodecVP8);
EXPECT_EQ(2u, streams.size());
EXPECT_EQ(400u, streams[0].width);
@@ -176,7 +176,7 @@
const size_t kMaxLayers = 3;
std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
kMinLayers, kMaxLayers, 100, 100, kBitratePriority, kQpMax, kScreenshare,
- true, trials);
+ true, trials, webrtc::kVideoCodecVP8);
// Simulcast streams number is never decreased for screenshare,
// even for very low resolution.
@@ -191,7 +191,7 @@
const size_t kMaxLayers = 3;
std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
kMinLayers, kMaxLayers, 800, 600, kBitratePriority, kQpMax, !kScreenshare,
- true, trials);
+ true, trials, webrtc::kVideoCodecVP8);
EXPECT_EQ(kMaxLayers, streams.size());
EXPECT_EQ(200u, streams[0].width);
@@ -208,7 +208,7 @@
const size_t kMaxLayers = 2;
std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
kMinLayers, kMaxLayers, 640 + 1, 360 + 1, kBitratePriority, kQpMax,
- !kScreenshare, true, trials);
+ !kScreenshare, true, trials, webrtc::kVideoCodecVP8);
// Must be divisible by |2 ^ (num_layers - 1)|.
EXPECT_EQ(kMaxLayers, streams.size());
@@ -227,7 +227,7 @@
const size_t kMaxLayers = 2;
std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
kMinLayers, kMaxLayers, 709, 501, kBitratePriority, kQpMax, !kScreenshare,
- true, trials);
+ true, trials, webrtc::kVideoCodecVP8);
// Must be divisible by |2 ^ 2|.
EXPECT_EQ(kMaxLayers, streams.size());
@@ -246,7 +246,7 @@
const size_t kMaxLayers = 2;
std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
kMinLayers, kMaxLayers, 709, 501, kBitratePriority, kQpMax, !kScreenshare,
- true, trials);
+ true, trials, webrtc::kVideoCodecVP8);
// Must be divisible by |2 ^ 3|.
EXPECT_EQ(kMaxLayers, streams.size());
@@ -265,17 +265,17 @@
const int kMaxLayers = 3;
std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
kMinLayers, kMaxLayers, 320, 180, kBitratePriority, kQpMax, !kScreenshare,
- true, trials);
+ true, trials, webrtc::kVideoCodecVP8);
EXPECT_EQ(1u, streams.size());
streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 640, 360,
kBitratePriority, kQpMax, !kScreenshare,
- true, trials);
+ true, trials, webrtc::kVideoCodecVP8);
EXPECT_EQ(2u, streams.size());
streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 1920, 1080,
kBitratePriority, kQpMax, !kScreenshare,
- true, trials);
+ true, trials, webrtc::kVideoCodecVP8);
EXPECT_EQ(3u, streams.size());
}
@@ -288,17 +288,17 @@
const int kMaxLayers = 3;
std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
kMinLayers, kMaxLayers, 320, 180, kBitratePriority, kQpMax, !kScreenshare,
- true, trials);
+ true, trials, webrtc::kVideoCodecVP8);
EXPECT_EQ(3u, streams.size());
streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 640, 360,
kBitratePriority, kQpMax, !kScreenshare,
- true, trials);
+ true, trials, webrtc::kVideoCodecVP8);
EXPECT_EQ(3u, streams.size());
streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 1920, 1080,
kBitratePriority, kQpMax, !kScreenshare,
- true, trials);
+ true, trials, webrtc::kVideoCodecVP8);
EXPECT_EQ(3u, streams.size());
}
@@ -308,7 +308,7 @@
const size_t kMaxLayers = 3;
std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
kMinLayers, kMaxLayers, 1400, 800, kBitratePriority, kQpMax, kScreenshare,
- true, trials);
+ true, trials, webrtc::kVideoCodecVP8);
EXPECT_GT(streams.size(), 1u);
for (size_t i = 0; i < streams.size(); ++i) {
@@ -330,7 +330,7 @@
const size_t kMaxLayers = 1;
std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
kMinLayers, kMaxLayers, 1400, 800, kBitratePriority, kQpMax, kScreenshare,
- true, trials);
+ true, trials, webrtc::kVideoCodecVP8);
EXPECT_EQ(kMaxLayers, streams.size());
}
@@ -341,7 +341,7 @@
const size_t kMaxLayers = 3;
std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
kMinLayers, kMaxLayers, 900, 800, kBitratePriority, kQpMax, !kScreenshare,
- true, trials);
+ true, trials, webrtc::kVideoCodecVP8);
EXPECT_EQ(kMaxLayers, streams.size());
EXPECT_EQ(900u, streams[2].width);
@@ -362,7 +362,7 @@
std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
kMinLayers, kMaxLayers, kWidth, kHeight, kBitratePriority, kQpMax,
- !kScreenshare, true, trials);
+ !kScreenshare, true, trials, webrtc::kVideoCodecVP8);
EXPECT_EQ(kMaxLayers, streams.size());
EXPECT_EQ(kWidth, streams[2].width);
@@ -387,21 +387,21 @@
std::vector<VideoStream> streams;
streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 960, 540,
kBitratePriority, kQpMax, !kScreenshare,
- true, trials);
+ true, trials, webrtc::kVideoCodecVP8);
EXPECT_EQ(3u, streams.size());
// <960x540: 2 layers
streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 960, 539,
kBitratePriority, kQpMax, !kScreenshare,
- true, trials);
+ true, trials, webrtc::kVideoCodecVP8);
EXPECT_EQ(2u, streams.size());
streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 480, 270,
kBitratePriority, kQpMax, !kScreenshare,
- true, trials);
+ true, trials, webrtc::kVideoCodecVP8);
EXPECT_EQ(2u, streams.size());
// <480x270: 1 layer
streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 480, 269,
kBitratePriority, kQpMax, !kScreenshare,
- true, trials);
+ true, trials, webrtc::kVideoCodecVP8);
EXPECT_EQ(1u, streams.size());
}
@@ -414,29 +414,29 @@
std::vector<VideoStream> streams;
streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 960, 540,
kBitratePriority, kQpMax, !kScreenshare,
- true, trials);
+ true, trials, webrtc::kVideoCodecVP8);
EXPECT_EQ(3u, streams.size());
// Lowest cropped height where max layers from higher resolution is used.
streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 960, 512,
kBitratePriority, kQpMax, !kScreenshare,
- true, trials);
+ true, trials, webrtc::kVideoCodecVP8);
EXPECT_EQ(3u, streams.size());
streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 960, 508,
kBitratePriority, kQpMax, !kScreenshare,
- true, trials);
+ true, trials, webrtc::kVideoCodecVP8);
EXPECT_EQ(2u, streams.size());
streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 480, 270,
kBitratePriority, kQpMax, !kScreenshare,
- true, trials);
+ true, trials, webrtc::kVideoCodecVP8);
EXPECT_EQ(2u, streams.size());
// Lowest cropped height where max layers from higher resolution is used.
streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 480, 256,
kBitratePriority, kQpMax, !kScreenshare,
- true, trials);
+ true, trials, webrtc::kVideoCodecVP8);
EXPECT_EQ(2u, streams.size());
streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 480, 254,
kBitratePriority, kQpMax, !kScreenshare,
- true, trials);
+ true, trials, webrtc::kVideoCodecVP8);
EXPECT_EQ(1u, streams.size());
}
@@ -450,16 +450,16 @@
std::vector<VideoStream> streams;
streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 480, 270,
kBitratePriority, kQpMax, !kScreenshare,
- true, trials);
+ true, trials, webrtc::kVideoCodecVP8);
EXPECT_EQ(2u, streams.size());
// Lowest cropped height where max layers from higher resolution is used.
streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 480, 252,
kBitratePriority, kQpMax, !kScreenshare,
- true, trials);
+ true, trials, webrtc::kVideoCodecVP8);
EXPECT_EQ(2u, streams.size());
streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 480, 250,
kBitratePriority, kQpMax, !kScreenshare,
- true, trials);
+ true, trials, webrtc::kVideoCodecVP8);
EXPECT_EQ(1u, streams.size());
}
@@ -473,7 +473,8 @@
std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
/* min_layers = */ 1, kMaxLayers, /* width = */ 960, /* height = */ 540,
- kBitratePriority, kQpMax, !kScreenshare, true, trials);
+ kBitratePriority, kQpMax, !kScreenshare, true, trials,
+ webrtc::kVideoCodecVP8);
ASSERT_EQ(streams.size(), kMaxLayers);
EXPECT_EQ(240u, streams[0].width);
@@ -492,7 +493,8 @@
std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
/* min_layers = */ 1, /* max_layers = */ 3, /* width = */ 1,
- /* height = */ 1, kBitratePriority, kQpMax, !kScreenshare, true, trials);
+ /* height = */ 1, kBitratePriority, kQpMax, !kScreenshare, true, trials,
+ webrtc::kVideoCodecVP8);
ASSERT_TRUE(!streams.empty());
EXPECT_EQ(1u, streams[0].width);
@@ -512,7 +514,8 @@
std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
/* min_layers = */ 1, kMaxLayers, /* width = */ 960, /* height = */ 540,
- kBitratePriority, kQpMax, !kScreenshare, true, trials);
+ kBitratePriority, kQpMax, !kScreenshare, true, trials,
+ webrtc::kVideoCodecVP8);
ASSERT_EQ(streams.size(), kMaxLayers);
EXPECT_EQ(240u, streams[0].width);
@@ -522,4 +525,69 @@
EXPECT_EQ(streams[0].min_bitrate_bps, 30000);
}
+TEST(SimulcastTest, BitratesBasedOnCodec) {
+ const size_t kMaxLayers = 3;
+ FieldTrialBasedConfig trials;
+
+ std::vector<VideoStream> streams_vp8 = cricket::GetSimulcastConfig(
+ /* min_layers = */ 1, /* max_layers = */ 3, /* width = */ 1280,
+ /* height = */ 720, kBitratePriority, kQpMax, !kScreenshare, true, trials,
+ webrtc::kVideoCodecVP8);
+
+ std::vector<VideoStream> streams_vp9 = cricket::GetSimulcastConfig(
+ /* min_layers = */ 1, /* max_layers = */ 3, /* width = */ 1280,
+ /* height = */ 720, kBitratePriority, kQpMax, !kScreenshare, true, trials,
+ webrtc::kVideoCodecVP9);
+
+ ASSERT_EQ(streams_vp8.size(), kMaxLayers);
+ ASSERT_EQ(streams_vp9.size(), kMaxLayers);
+
+ EXPECT_EQ(streams_vp9[0].width, streams_vp8[0].width);
+ EXPECT_EQ(streams_vp9[0].height, streams_vp8[0].height);
+
+ EXPECT_NE(streams_vp9[0].max_bitrate_bps, streams_vp8[0].max_bitrate_bps);
+ EXPECT_NE(streams_vp9[0].target_bitrate_bps,
+ streams_vp8[0].target_bitrate_bps);
+ EXPECT_NE(streams_vp9[0].min_bitrate_bps, streams_vp8[0].min_bitrate_bps);
+
+ EXPECT_NE(streams_vp9[1].max_bitrate_bps, streams_vp8[1].max_bitrate_bps);
+ EXPECT_NE(streams_vp9[1].target_bitrate_bps,
+ streams_vp8[1].target_bitrate_bps);
+ EXPECT_NE(streams_vp9[1].min_bitrate_bps, streams_vp8[1].min_bitrate_bps);
+
+ EXPECT_NE(streams_vp9[2].max_bitrate_bps, streams_vp8[2].max_bitrate_bps);
+ EXPECT_NE(streams_vp9[2].target_bitrate_bps,
+ streams_vp8[2].target_bitrate_bps);
+ EXPECT_NE(streams_vp9[2].min_bitrate_bps, streams_vp8[2].min_bitrate_bps);
+}
+
+TEST(SimulcastTest, BitratesForVP9) {
+ const size_t kMaxLayers = 3;
+ FieldTrialBasedConfig trials;
+
+ std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
+ /* min_layers = */ 1, kMaxLayers, /* width = */ 1280, /* height = */ 720,
+ kBitratePriority, kQpMax, !kScreenshare, true, trials,
+ webrtc::kVideoCodecVP9);
+
+ ASSERT_EQ(streams.size(), 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(
+ /* min_layers = */ 1, kMaxLayers, /* width = */ 1276, /* height = */ 716,
+ kBitratePriority, kQpMax, !kScreenshare, true, trials,
+ webrtc::kVideoCodecVP9);
+
+ ASSERT_EQ(streams.size(), 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);
+}
+
} // namespace webrtc