Split CreateEncodingSettings

into CreateEncodingSettings and CreateFrameSettings. Also changed bitrate/framerate data types from int/double to DataRate/Frequency.

Bug: webrtc:42225151, b/337757868
Change-Id: I01b8b4e3d34f72250fdb8d64e4ee98ff79bbbd8b
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/349962
Reviewed-by: Åsa Persson <asapersson@webrtc.org>
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Commit-Queue: Sergey Silkin <ssilkin@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#42259}
This commit is contained in:
Sergey Silkin 2024-05-08 08:37:40 +00:00 committed by WebRTC LUCI CQ
parent 35af7ccfb0
commit 5f3fc5028f
4 changed files with 330 additions and 243 deletions

View file

@ -60,9 +60,9 @@ ABSL_FLAG(std::vector<std::string>,
{"1024"},
"Encode target bitrate per layer (l0t0,l0t1,...l1t0,l1t1 and so on) "
"in kbps.");
ABSL_FLAG(double,
ABSL_FLAG(absl::optional<double>,
framerate_fps,
30.0,
absl::nullopt,
"Encode target frame rate of the top temporal layer in fps.");
ABSL_FLAG(bool, screencast, false, "Enable screen encoding mode.");
ABSL_FLAG(bool, frame_drop, true, "Enable frame dropping.");
@ -314,13 +314,16 @@ TEST_P(SpatialQualityTest, SpatialQuality) {
VideoSourceSettings source_settings = ToSourceSettings(video_info);
std::map<uint32_t, EncodingSettings> frames_settings =
VideoCodecTester::CreateEncodingSettings(
codec_type, /*scalability_mode=*/"L1T1", width, height,
{bitrate_kbps}, framerate_fps, num_frames);
EncodingSettings encoding_settings = VideoCodecTester::CreateEncodingSettings(
codec_type, /*scalability_mode=*/"L1T1", width, height,
{DataRate::KilobitsPerSec(bitrate_kbps)},
Frequency::Hertz(framerate_fps));
std::map<uint32_t, EncodingSettings> frame_settings =
VideoCodecTester::CreateFrameSettings(encoding_settings, num_frames);
std::unique_ptr<VideoCodecStats> stats = RunEncodeDecodeTest(
env, codec_impl, codec_impl, source_settings, frames_settings);
env, codec_impl, codec_impl, source_settings, frame_settings);
VideoCodecStats::Stream stream;
if (stats != nullptr) {
@ -390,29 +393,36 @@ TEST_P(BitrateAdaptationTest, BitrateAdaptation) {
VideoSourceSettings source_settings = ToSourceSettings(video_info);
std::map<uint32_t, EncodingSettings> encoding_settings =
EncodingSettings encoding_settings = VideoCodecTester::CreateEncodingSettings(
codec_type, /*scalability_mode=*/"L1T1",
/*width=*/640, /*height=*/360,
{DataRate::KilobitsPerSec(bitrate_kbps.first)},
/*framerate=*/Frequency::Hertz(30));
EncodingSettings encoding_settings2 =
VideoCodecTester::CreateEncodingSettings(
codec_type, /*scalability_mode=*/"L1T1",
/*width=*/640, /*height=*/360, {bitrate_kbps.first},
/*framerate_fps=*/30, num_frames);
/*width=*/640, /*height=*/360,
{DataRate::KilobitsPerSec(bitrate_kbps.second)},
/*framerate=*/Frequency::Hertz(30));
uint32_t initial_timestamp_rtp =
encoding_settings.rbegin()->first + k90kHz / Frequency::Hertz(30);
std::map<uint32_t, EncodingSettings> frame_settings =
VideoCodecTester::CreateFrameSettings(encoding_settings, num_frames);
std::map<uint32_t, EncodingSettings> encoding_settings2 =
VideoCodecTester::CreateEncodingSettings(
codec_type, /*scalability_mode=*/"L1T1",
/*width=*/640, /*height=*/360, {bitrate_kbps.second},
/*framerate_fps=*/30, num_frames, initial_timestamp_rtp);
uint32_t timestamp_rtp =
frame_settings.rbegin()->first + k90kHz / Frequency::Hertz(30);
std::map<uint32_t, EncodingSettings> frame_settings2 =
VideoCodecTester::CreateFrameSettings(encoding_settings2, num_frames,
timestamp_rtp);
encoding_settings.merge(encoding_settings2);
frame_settings.merge(frame_settings2);
std::unique_ptr<VideoCodecStats> stats = RunEncodeTest(
env, codec_type, codec_impl, source_settings, encoding_settings);
env, codec_type, codec_impl, source_settings, frame_settings);
VideoCodecStats::Stream stream;
if (stats != nullptr) {
stream = stats->Aggregate({.min_timestamp_rtp = initial_timestamp_rtp});
stream = stats->Aggregate({.min_timestamp_rtp = timestamp_rtp});
if (absl::GetFlag(FLAGS_webrtc_quick_perf_test)) {
EXPECT_NEAR(stream.bitrate_mismatch_pct.GetAverage(), 0, 10);
EXPECT_NEAR(stream.framerate_mismatch_pct.GetAverage(), 0, 10);
@ -469,33 +479,39 @@ TEST_P(FramerateAdaptationTest, FramerateAdaptation) {
VideoSourceSettings source_settings = ToSourceSettings(video_info);
std::map<uint32_t, EncodingSettings> encoding_settings =
EncodingSettings encoding_settings = VideoCodecTester::CreateEncodingSettings(
codec_type, /*scalability_mode=*/"L1T1",
/*width=*/640, /*height=*/360,
/*bitrate=*/{DataRate::KilobitsPerSec(512)},
Frequency::Hertz(framerate_fps.first));
EncodingSettings encoding_settings2 =
VideoCodecTester::CreateEncodingSettings(
codec_type, /*scalability_mode=*/"L1T1",
/*width=*/640, /*height=*/360,
/*layer_bitrates_kbps=*/{512}, framerate_fps.first,
static_cast<int>(duration_s * framerate_fps.first));
/*bitrate=*/{DataRate::KilobitsPerSec(512)},
Frequency::Hertz(framerate_fps.second));
uint32_t initial_timestamp_rtp =
encoding_settings.rbegin()->first +
k90kHz / Frequency::Hertz(framerate_fps.first);
int num_frames = static_cast<int>(duration_s * framerate_fps.first);
std::map<uint32_t, EncodingSettings> frame_settings =
VideoCodecTester::CreateFrameSettings(encoding_settings, num_frames);
std::map<uint32_t, EncodingSettings> encoding_settings2 =
VideoCodecTester::CreateEncodingSettings(
codec_type, /*scalability_mode=*/"L1T1", /*width=*/640,
/*height=*/360,
/*layer_bitrates_kbps=*/{512}, framerate_fps.second,
static_cast<int>(duration_s * framerate_fps.second),
initial_timestamp_rtp);
uint32_t timestamp_rtp = frame_settings.rbegin()->first +
k90kHz / Frequency::Hertz(framerate_fps.first);
encoding_settings.merge(encoding_settings2);
num_frames = static_cast<int>(duration_s * framerate_fps.second);
std::map<uint32_t, EncodingSettings> frame_settings2 =
VideoCodecTester::CreateFrameSettings(encoding_settings2, num_frames,
timestamp_rtp);
frame_settings.merge(frame_settings2);
std::unique_ptr<VideoCodecStats> stats = RunEncodeTest(
env, codec_type, codec_impl, source_settings, encoding_settings);
env, codec_type, codec_impl, source_settings, frame_settings);
VideoCodecStats::Stream stream;
if (stats != nullptr) {
stream = stats->Aggregate({.min_timestamp_rtp = initial_timestamp_rtp});
stream = stats->Aggregate({.min_timestamp_rtp = timestamp_rtp});
if (absl::GetFlag(FLAGS_webrtc_quick_perf_test)) {
EXPECT_NEAR(stream.bitrate_mismatch_pct.GetAverage(), 0, 10);
EXPECT_NEAR(stream.framerate_mismatch_pct.GetAverage(), 0, 10);
@ -540,26 +556,27 @@ TEST(VideoCodecTest, DISABLED_EncodeDecode) {
Frequency::Hertz<double>(absl::GetFlag(FLAGS_input_framerate_fps))};
std::vector<std::string> bitrate_str = absl::GetFlag(FLAGS_bitrate_kbps);
std::vector<int> bitrate_kbps;
std::vector<DataRate> bitrate;
std::transform(bitrate_str.begin(), bitrate_str.end(),
std::back_inserter(bitrate_kbps),
[](const std::string& str) { return std::stoi(str); });
std::back_inserter(bitrate), [](const std::string& str) {
return DataRate::KilobitsPerSec(std::stoi(str));
});
VideoCodecMode content_type = absl::GetFlag(FLAGS_screencast)
? VideoCodecMode::kScreensharing
: VideoCodecMode::kRealtimeVideo;
EncodingSettings encoding_settings = VideoCodecTester::CreateEncodingSettings(
CodecNameToCodecType(absl::GetFlag(FLAGS_encoder)),
absl::GetFlag(FLAGS_scalability_mode),
absl::GetFlag(FLAGS_width).value_or(absl::GetFlag(FLAGS_input_width)),
absl::GetFlag(FLAGS_height).value_or(absl::GetFlag(FLAGS_input_height)),
{bitrate},
Frequency::Hertz<double>(
absl::GetFlag(FLAGS_framerate_fps)
.value_or(absl::GetFlag(FLAGS_input_framerate_fps))),
absl::GetFlag(FLAGS_screencast), absl::GetFlag(FLAGS_frame_drop));
std::map<uint32_t, EncodingSettings> frames_settings =
VideoCodecTester::CreateEncodingSettings(
CodecNameToCodecType(absl::GetFlag(FLAGS_encoder)),
absl::GetFlag(FLAGS_scalability_mode),
absl::GetFlag(FLAGS_width).value_or(absl::GetFlag(FLAGS_input_width)),
absl::GetFlag(FLAGS_height)
.value_or(absl::GetFlag(FLAGS_input_height)),
{bitrate_kbps}, absl::GetFlag(FLAGS_framerate_fps),
absl::GetFlag(FLAGS_num_frames),
/*first_timestamp_rtp=*/90000, content_type,
absl::GetFlag(FLAGS_frame_drop));
std::map<uint32_t, EncodingSettings> frame_settings =
VideoCodecTester::CreateFrameSettings(encoding_settings,
absl::GetFlag(FLAGS_num_frames),
/*timestamp_rtp=*/90000);
// TODO(webrtc:14852): Pass encoder and decoder names directly, and update
// logged test name (implies lossing history in the chromeperf dashboard).
@ -567,7 +584,7 @@ TEST(VideoCodecTest, DISABLED_EncodeDecode) {
std::unique_ptr<VideoCodecStats> stats = RunEncodeDecodeTest(
env, CodecNameToCodecImpl(absl::GetFlag(FLAGS_encoder)),
CodecNameToCodecImpl(absl::GetFlag(FLAGS_decoder)), source_settings,
frames_settings);
frame_settings);
ASSERT_NE(nullptr, stats);
// Log unsliced metrics.

View file

@ -1301,36 +1301,32 @@ SplitBitrateAndUpdateScalabilityMode(std::string codec_type,
ScalabilityMode scalability_mode,
int width,
int height,
std::vector<int> bitrates_kbps,
double framerate_fps,
std::vector<DataRate> layer_bitrate,
Frequency framerate,
VideoCodecMode content_type) {
int num_spatial_layers = ScalabilityModeToNumSpatialLayers(scalability_mode);
int num_temporal_layers =
ScalabilityModeToNumTemporalLayers(scalability_mode);
int num_bitrates = static_cast<int>(bitrates_kbps.size());
int num_bitrates = static_cast<int>(layer_bitrate.size());
RTC_CHECK(num_bitrates == 1 || num_bitrates == num_spatial_layers ||
num_bitrates == num_spatial_layers * num_temporal_layers);
if (num_bitrates == num_spatial_layers * num_temporal_layers) {
std::vector<DataRate> bitrates;
for (const auto& bitrate_kbps : bitrates_kbps) {
bitrates.push_back(DataRate::KilobitsPerSec(bitrate_kbps));
}
return std::make_tuple(bitrates, scalability_mode);
return std::make_tuple(layer_bitrate, scalability_mode);
}
int total_bitrate_kbps =
std::accumulate(bitrates_kbps.begin(), bitrates_kbps.end(), 0);
DataRate total_bitrate = std::accumulate(
layer_bitrate.begin(), layer_bitrate.end(), DataRate::Zero());
VideoCodec vc;
vc.codecType = PayloadStringToCodecType(codec_type);
vc.width = width;
vc.height = height;
vc.startBitrate = total_bitrate_kbps;
vc.maxBitrate = total_bitrate_kbps;
vc.startBitrate = total_bitrate.kbps();
vc.maxBitrate = total_bitrate.kbps();
vc.minBitrate = 0;
vc.maxFramerate = static_cast<uint32_t>(framerate_fps);
vc.maxFramerate = framerate.hertz();
vc.numberOfSimulcastStreams = 0;
vc.mode = content_type;
vc.SetScalabilityMode(scalability_mode);
@ -1348,8 +1344,8 @@ SplitBitrateAndUpdateScalabilityMode(std::string codec_type,
ss->height = height >> (num_spatial_layers - sidx - 1);
ss->maxFramerate = vc.maxFramerate;
ss->numberOfTemporalLayers = num_temporal_layers;
ss->maxBitrate = bitrates_kbps[sidx];
ss->targetBitrate = bitrates_kbps[sidx];
ss->maxBitrate = layer_bitrate[sidx].kbps();
ss->targetBitrate = layer_bitrate[sidx].kbps();
ss->minBitrate = 0;
ss->qpMax = 0;
ss->active = true;
@ -1363,8 +1359,8 @@ SplitBitrateAndUpdateScalabilityMode(std::string codec_type,
ss->height = height >> (num_spatial_layers - sidx - 1);
ss->maxFramerate = vc.maxFramerate;
ss->numberOfTemporalLayers = num_temporal_layers;
ss->maxBitrate = bitrates_kbps[sidx];
ss->targetBitrate = bitrates_kbps[sidx];
ss->maxBitrate = layer_bitrate[sidx].kbps();
ss->targetBitrate = layer_bitrate[sidx].kbps();
ss->minBitrate = 0;
ss->qpMax = 0;
ss->active = true;
@ -1412,7 +1408,7 @@ SplitBitrateAndUpdateScalabilityMode(std::string codec_type,
vc);
VideoBitrateAllocation bitrate_allocation =
bitrate_allocator->Allocate(VideoBitrateAllocationParameters(
1000 * total_bitrate_kbps, framerate_fps));
total_bitrate.bps(), framerate.hertz<double>()));
std::vector<DataRate> bitrates;
for (int sidx = 0; sidx < num_spatial_layers; ++sidx) {
@ -1486,22 +1482,22 @@ void VideoCodecStats::Stream::LogMetrics(
metadata);
}
// TODO(ssilkin): use Frequency and DataRate for framerate and bitrate.
std::map<uint32_t, EncodingSettings> VideoCodecTester::CreateEncodingSettings(
EncodingSettings VideoCodecTester::CreateEncodingSettings(
std::string codec_type,
std::string scalability_name,
int width,
int height,
std::vector<int> layer_bitrates_kbps,
double framerate_fps,
int num_frames,
uint32_t first_timestamp_rtp,
webrtc::VideoCodecMode content_type,
std::vector<DataRate> bitrate,
Frequency framerate,
bool screencast,
bool frame_drop) {
auto [layer_bitrates, scalability_mode] =
VideoCodecMode content_type = screencast ? VideoCodecMode::kScreensharing
: VideoCodecMode::kRealtimeVideo;
auto [adjusted_bitrate, scalability_mode] =
SplitBitrateAndUpdateScalabilityMode(
codec_type, *ScalabilityModeFromString(scalability_name), width,
height, layer_bitrates_kbps, framerate_fps, content_type);
height, bitrate, framerate, content_type);
int num_spatial_layers = ScalabilityModeToNumSpatialLayers(scalability_mode);
int num_temporal_layers =
@ -1512,14 +1508,12 @@ std::map<uint32_t, EncodingSettings> VideoCodecTester::CreateEncodingSettings(
int layer_width = width >> (num_spatial_layers - sidx - 1);
int layer_height = height >> (num_spatial_layers - sidx - 1);
for (int tidx = 0; tidx < num_temporal_layers; ++tidx) {
double layer_framerate_fps =
framerate_fps / (1 << (num_temporal_layers - tidx - 1));
layers_settings.emplace(
LayerId{.spatial_idx = sidx, .temporal_idx = tidx},
LayerSettings{
.resolution = {.width = layer_width, .height = layer_height},
.framerate = Frequency::MilliHertz(1000 * layer_framerate_fps),
.bitrate = layer_bitrates[sidx * num_temporal_layers + tidx]});
.framerate = framerate / (1 << (num_temporal_layers - tidx - 1)),
.bitrate = adjusted_bitrate[sidx * num_temporal_layers + tidx]});
}
}
@ -1534,20 +1528,25 @@ std::map<uint32_t, EncodingSettings> VideoCodecTester::CreateEncodingSettings(
.parameters;
}
std::map<uint32_t, EncodingSettings> frames_settings;
uint32_t timestamp_rtp = first_timestamp_rtp;
return EncodingSettings{.sdp_video_format = sdp_video_format,
.scalability_mode = scalability_mode,
.content_type = content_type,
.frame_drop = frame_drop,
.layers_settings = layers_settings};
}
std::map<uint32_t, EncodingSettings> VideoCodecTester::CreateFrameSettings(
const EncodingSettings& encoding_settings,
int num_frames,
uint32_t timestamp_rtp) {
std::map<uint32_t, EncodingSettings> frame_settings;
Frequency framerate =
encoding_settings.layers_settings.rbegin()->second.framerate;
for (int frame_num = 0; frame_num < num_frames; ++frame_num) {
frames_settings.emplace(
timestamp_rtp, EncodingSettings{.sdp_video_format = sdp_video_format,
.scalability_mode = scalability_mode,
.content_type = content_type,
.frame_drop = frame_drop,
.layers_settings = layers_settings});
timestamp_rtp += k90kHz / Frequency::MilliHertz(1000 * framerate_fps);
frame_settings.emplace(timestamp_rtp, encoding_settings);
timestamp_rtp += k90kHz / framerate;
}
return frames_settings;
return frame_settings;
}
std::unique_ptr<VideoCodecTester::VideoCodecStats>

View file

@ -188,19 +188,26 @@ class VideoCodecTester {
virtual absl::optional<EncodedImage> PullFrame() = 0;
};
// A helper function that creates `EncodingSettings` for `num_frames` frames,
// wraps the settings into RTP timestamp -> settings map and returns the map.
static std::map<uint32_t, EncodingSettings> CreateEncodingSettings(
std::string codec_type,
std::string scalability_name,
int width,
int height,
std::vector<int> bitrates_kbps,
double framerate_fps,
// A helper function that creates `EncodingSettings` from the given
// parameters. `bitrate` is either total, or per-spatial layer or per-spatial
// and per-temporal layer. If layer bitrates are not explicitly specified,
// then the codec-specific rate allocators used to distribute the total
// bitrate across spatial or/and temporal layers.
static EncodingSettings CreateEncodingSettings(std::string codec_type,
std::string scalability_name,
int width,
int height,
std::vector<DataRate> bitrate,
Frequency framerate,
bool screencast = false,
bool frame_drop = true);
// A helper function that creates a map of RTP timestamps to
// `EncodingSettings` for the given number of frames.
static std::map<uint32_t, EncodingSettings> CreateFrameSettings(
const EncodingSettings& encoding_settings,
int num_frames,
uint32_t first_timestamp_rtp = 90000,
VideoCodecMode content_type = VideoCodecMode::kRealtimeVideo,
bool frame_drop = true);
uint32_t first_timestamp_rtp = 90000);
// Decodes video, collects and returns decode metrics.
static std::unique_ptr<VideoCodecStats> RunDecodeTest(

View file

@ -69,8 +69,8 @@ using Stream = VideoCodecTester::VideoCodecStats::Stream;
constexpr int kWidth = 2;
constexpr int kHeight = 2;
const DataRate kTargetLayerBitrate = DataRate::BytesPerSec(100);
const Frequency kTargetFramerate = Frequency::Hertz(30);
const DataRate kBitrate = DataRate::BytesPerSec(100);
const Frequency kFramerate = Frequency::Hertz(30);
constexpr Frequency k90kHz = Frequency::Hertz(90000);
rtc::scoped_refptr<I420Buffer> CreateYuvBuffer(uint8_t y = 0,
@ -191,7 +191,7 @@ class VideoCodecTesterTest : public ::testing::Test {
VideoSourceSettings video_source_settings{
.file_path = yuv_path,
.resolution = {.width = kWidth, .height = kHeight},
.framerate = kTargetFramerate};
.framerate = kFramerate};
NiceMock<MockVideoEncoderFactory> encoder_factory;
ON_CALL(encoder_factory, Create).WillByDefault(WithoutArgs([&] {
@ -235,9 +235,9 @@ class VideoCodecTesterTest : public ::testing::Test {
LayerId{.spatial_idx = sidx, .temporal_idx = tidx},
LayerSettings{
.resolution = {.width = kWidth, .height = kHeight},
.framerate = kTargetFramerate /
(1 << (num_temporal_layers - 1 - tidx)),
.bitrate = kTargetLayerBitrate});
.framerate =
kFramerate / (1 << (num_temporal_layers - 1 - tidx)),
.bitrate = kBitrate});
}
}
encoding_settings.emplace(
@ -420,9 +420,9 @@ INSTANTIATE_TEST_SUITE_P(
DataRate::BytesPerSec(15).kbps<double>(),
.expected_encoded_framerate_fps = 2,
.expected_bitrate_mismatch_pct =
100 * (15.0 / (kTargetLayerBitrate.bytes_per_sec() * 4) - 1),
.expected_framerate_mismatch_pct =
100 * (2.0 / kTargetFramerate.hertz() - 1)},
100 * (15.0 / (kBitrate.bytes_per_sec() * 4) - 1),
.expected_framerate_mismatch_pct = 100 *
(2.0 / kFramerate.hertz() - 1)},
// L0T0
AggregationTestParameters{
.filter = {.layer_id = {{.spatial_idx = 0, .temporal_idx = 0}}},
@ -431,9 +431,9 @@ INSTANTIATE_TEST_SUITE_P(
DataRate::BytesPerSec(1).kbps<double>(),
.expected_encoded_framerate_fps = 1,
.expected_bitrate_mismatch_pct =
100 * (1.0 / kTargetLayerBitrate.bytes_per_sec() - 1),
100 * (1.0 / kBitrate.bytes_per_sec() - 1),
.expected_framerate_mismatch_pct =
100 * (1.0 / (kTargetFramerate.hertz() / 2) - 1)},
100 * (1.0 / (kFramerate.hertz() / 2) - 1)},
// L0T1
AggregationTestParameters{
.filter = {.layer_id = {{.spatial_idx = 0, .temporal_idx = 1}}},
@ -442,9 +442,9 @@ INSTANTIATE_TEST_SUITE_P(
DataRate::BytesPerSec(5).kbps<double>(),
.expected_encoded_framerate_fps = 2,
.expected_bitrate_mismatch_pct =
100 * (5.0 / (kTargetLayerBitrate.bytes_per_sec() * 2) - 1),
.expected_framerate_mismatch_pct =
100 * (2.0 / kTargetFramerate.hertz() - 1)},
100 * (5.0 / (kBitrate.bytes_per_sec() * 2) - 1),
.expected_framerate_mismatch_pct = 100 *
(2.0 / kFramerate.hertz() - 1)},
// L1T0
AggregationTestParameters{
.filter = {.layer_id = {{.spatial_idx = 1, .temporal_idx = 0}}},
@ -453,9 +453,9 @@ INSTANTIATE_TEST_SUITE_P(
DataRate::BytesPerSec(3).kbps<double>(),
.expected_encoded_framerate_fps = 1,
.expected_bitrate_mismatch_pct =
100 * (3.0 / kTargetLayerBitrate.bytes_per_sec() - 1),
100 * (3.0 / kBitrate.bytes_per_sec() - 1),
.expected_framerate_mismatch_pct =
100 * (1.0 / (kTargetFramerate.hertz() / 2) - 1)},
100 * (1.0 / (kFramerate.hertz() / 2) - 1)},
// L1T1
AggregationTestParameters{
.filter = {.layer_id = {{.spatial_idx = 1, .temporal_idx = 1}}},
@ -464,9 +464,9 @@ INSTANTIATE_TEST_SUITE_P(
DataRate::BytesPerSec(11).kbps<double>(),
.expected_encoded_framerate_fps = 2,
.expected_bitrate_mismatch_pct =
100 * (11.0 / (kTargetLayerBitrate.bytes_per_sec() * 2) - 1),
.expected_framerate_mismatch_pct =
100 * (2.0 / kTargetFramerate.hertz() - 1)}));
100 * (11.0 / (kBitrate.bytes_per_sec() * 2) - 1),
.expected_framerate_mismatch_pct = 100 * (2.0 / kFramerate.hertz() -
1)}));
TEST_F(VideoCodecTesterTest, Psnr) {
std::unique_ptr<VideoCodecStats> stats = RunEncodeDecodeTest(
@ -593,8 +593,7 @@ class VideoCodecTesterTestPacing
const int kSourceWidth = 2;
const int kSourceHeight = 2;
const int kNumFrames = 3;
const int kTargetLayerBitrateKbps = 128;
const Frequency kTargetFramerate = Frequency::Hertz(10);
const Frequency kFramerate = Frequency::Hertz(10);
void SetUp() override {
source_yuv_file_path_ = CreateYuvFile(kSourceWidth, kSourceHeight, 1);
@ -613,23 +612,23 @@ TEST_P(VideoCodecTesterTestPacing, PaceEncode) {
VideoSourceSettings video_source{
.file_path = source_yuv_file_path_,
.resolution = {.width = kSourceWidth, .height = kSourceHeight},
.framerate = kTargetFramerate};
.framerate = kFramerate};
NiceMock<MockVideoEncoderFactory> encoder_factory;
ON_CALL(encoder_factory, Create).WillByDefault(WithoutArgs([] {
return std::make_unique<NiceMock<MockVideoEncoder>>();
}));
std::map<uint32_t, EncodingSettings> encoding_settings =
VideoCodecTester::CreateEncodingSettings(
"VP8", "L1T1", kSourceWidth, kSourceHeight, {kTargetLayerBitrateKbps},
kTargetFramerate.hertz(), kNumFrames);
EncodingSettings encoding_settings = VideoCodecTester::CreateEncodingSettings(
"VP8", "L1T1", kSourceWidth, kSourceHeight, {kBitrate}, kFramerate);
std::map<uint32_t, EncodingSettings> frame_settings =
VideoCodecTester::CreateFrameSettings(encoding_settings, kNumFrames);
EncoderSettings encoder_settings;
encoder_settings.pacing_settings = pacing_settings;
std::vector<Frame> frames =
VideoCodecTester::RunEncodeTest(env, video_source, &encoder_factory,
encoder_settings, encoding_settings)
encoder_settings, frame_settings)
->Slice(/*filter=*/{}, /*merge=*/false);
ASSERT_THAT(frames, SizeIs(kNumFrames));
EXPECT_NEAR((frames[1].encode_start - frames[0].encode_start).ms(),
@ -640,7 +639,7 @@ TEST_P(VideoCodecTesterTestPacing, PaceEncode) {
TEST_P(VideoCodecTesterTestPacing, PaceDecode) {
auto [pacing_settings, expected_delta_ms] = GetParam();
MockCodedVideoSource video_source(kNumFrames, kTargetFramerate);
MockCodedVideoSource video_source(kNumFrames, kFramerate);
NiceMock<MockVideoDecoderFactory> decoder_factory;
ON_CALL(decoder_factory, Create).WillByDefault(WithoutArgs([] {
@ -678,8 +677,8 @@ INSTANTIATE_TEST_SUITE_P(
struct EncodingSettingsTestParameters {
std::string codec_type;
std::string scalability_mode;
std::vector<int> bitrate_kbps;
std::vector<int> expected_bitrate_kbps;
std::vector<DataRate> bitrate;
std::vector<DataRate> expected_bitrate;
};
class VideoCodecTesterTestEncodingSettings
@ -687,124 +686,189 @@ class VideoCodecTesterTestEncodingSettings
TEST_P(VideoCodecTesterTestEncodingSettings, CreateEncodingSettings) {
EncodingSettingsTestParameters test_params = GetParam();
std::map<uint32_t, EncodingSettings> encoding_settings =
VideoCodecTester::CreateEncodingSettings(
test_params.codec_type, test_params.scalability_mode, /*width=*/1280,
/*height=*/720, test_params.bitrate_kbps, /*framerate_fps=*/30,
/*num_frames=*/1);
ASSERT_THAT(encoding_settings, SizeIs(1));
EncodingSettings encoding_settings = VideoCodecTester::CreateEncodingSettings(
test_params.codec_type, test_params.scalability_mode, /*width=*/1280,
/*height=*/720, test_params.bitrate, kFramerate);
const std::map<LayerId, LayerSettings>& layers_settings =
encoding_settings.begin()->second.layers_settings;
std::vector<int> configured_bitrate_kbps;
std::transform(layers_settings.begin(), layers_settings.end(),
std::back_inserter(configured_bitrate_kbps),
[](const auto& layer_settings) {
return layer_settings.second.bitrate.kbps();
});
EXPECT_EQ(configured_bitrate_kbps, test_params.expected_bitrate_kbps);
encoding_settings.layers_settings;
std::vector<DataRate> configured_bitrate;
std::transform(
layers_settings.begin(), layers_settings.end(),
std::back_inserter(configured_bitrate),
[](const auto& layer_settings) { return layer_settings.second.bitrate; });
EXPECT_EQ(configured_bitrate, test_params.expected_bitrate);
}
INSTANTIATE_TEST_SUITE_P(
Vp8,
VideoCodecTesterTestEncodingSettings,
Values(EncodingSettingsTestParameters{.codec_type = "VP8",
.scalability_mode = "L1T1",
.bitrate_kbps = {1},
.expected_bitrate_kbps = {1}},
EncodingSettingsTestParameters{.codec_type = "VP8",
.scalability_mode = "L1T1",
.bitrate_kbps = {10000},
.expected_bitrate_kbps = {10000}},
EncodingSettingsTestParameters{
.codec_type = "VP8",
.scalability_mode = "L1T3",
.bitrate_kbps = {1000},
.expected_bitrate_kbps = {400, 200, 400}},
EncodingSettingsTestParameters{
.codec_type = "VP8",
.scalability_mode = "S3T3",
.bitrate_kbps = {100},
.expected_bitrate_kbps = {40, 20, 40, 0, 0, 0, 0, 0, 0}},
EncodingSettingsTestParameters{
.codec_type = "VP8",
.scalability_mode = "S3T3",
.bitrate_kbps = {10000},
.expected_bitrate_kbps = {60, 30, 60, 200, 100, 200, 1000, 500,
1000}},
EncodingSettingsTestParameters{
.codec_type = "VP8",
.scalability_mode = "S3T3",
.bitrate_kbps = {100, 200, 300, 400, 500, 600, 700, 800, 900},
.expected_bitrate_kbps = {100, 200, 300, 400, 500, 600, 700, 800,
900}}));
Values(
EncodingSettingsTestParameters{
.codec_type = "VP8",
.scalability_mode = "L1T1",
.bitrate = {DataRate::KilobitsPerSec(1)},
.expected_bitrate = {DataRate::KilobitsPerSec(1)}},
EncodingSettingsTestParameters{
.codec_type = "VP8",
.scalability_mode = "L1T1",
.bitrate = {DataRate::KilobitsPerSec(10000)},
.expected_bitrate = {DataRate::KilobitsPerSec(10000)}},
EncodingSettingsTestParameters{
.codec_type = "VP8",
.scalability_mode = "L1T3",
.bitrate = {DataRate::KilobitsPerSec(1000)},
.expected_bitrate = {DataRate::KilobitsPerSec(400),
DataRate::KilobitsPerSec(200),
DataRate::KilobitsPerSec(400)}},
EncodingSettingsTestParameters{
.codec_type = "VP8",
.scalability_mode = "S3T3",
.bitrate = {DataRate::KilobitsPerSec(100)},
.expected_bitrate =
{DataRate::KilobitsPerSec(40), DataRate::KilobitsPerSec(20),
DataRate::KilobitsPerSec(40), DataRate::KilobitsPerSec(0),
DataRate::KilobitsPerSec(0), DataRate::KilobitsPerSec(0),
DataRate::KilobitsPerSec(0), DataRate::KilobitsPerSec(0),
DataRate::KilobitsPerSec(0)}},
EncodingSettingsTestParameters{
.codec_type = "VP8",
.scalability_mode = "S3T3",
.bitrate = {DataRate::KilobitsPerSec(10000)},
.expected_bitrate =
{DataRate::KilobitsPerSec(60), DataRate::KilobitsPerSec(30),
DataRate::KilobitsPerSec(60), DataRate::KilobitsPerSec(200),
DataRate::KilobitsPerSec(100), DataRate::KilobitsPerSec(200),
DataRate::KilobitsPerSec(1000), DataRate::KilobitsPerSec(500),
DataRate::KilobitsPerSec(1000)}},
EncodingSettingsTestParameters{
.codec_type = "VP8",
.scalability_mode = "S3T3",
.bitrate =
{DataRate::KilobitsPerSec(100), DataRate::KilobitsPerSec(200),
DataRate::KilobitsPerSec(300), DataRate::KilobitsPerSec(400),
DataRate::KilobitsPerSec(500), DataRate::KilobitsPerSec(600),
DataRate::KilobitsPerSec(700), DataRate::KilobitsPerSec(800),
DataRate::KilobitsPerSec(900)},
.expected_bitrate = {
DataRate::KilobitsPerSec(100), DataRate::KilobitsPerSec(200),
DataRate::KilobitsPerSec(300), DataRate::KilobitsPerSec(400),
DataRate::KilobitsPerSec(500), DataRate::KilobitsPerSec(600),
DataRate::KilobitsPerSec(700), DataRate::KilobitsPerSec(800),
DataRate::KilobitsPerSec(900)}}));
INSTANTIATE_TEST_SUITE_P(
Vp9,
VideoCodecTesterTestEncodingSettings,
Values(EncodingSettingsTestParameters{.codec_type = "VP9",
.scalability_mode = "L1T1",
.bitrate_kbps = {1},
.expected_bitrate_kbps = {1}},
EncodingSettingsTestParameters{.codec_type = "VP9",
.scalability_mode = "L1T1",
.bitrate_kbps = {10000},
.expected_bitrate_kbps = {10000}},
EncodingSettingsTestParameters{
.codec_type = "VP9",
.scalability_mode = "L1T3",
.bitrate_kbps = {1000},
.expected_bitrate_kbps = {540, 163, 297}},
EncodingSettingsTestParameters{
.codec_type = "VP9",
.scalability_mode = "L3T3",
.bitrate_kbps = {100},
.expected_bitrate_kbps = {54, 16, 30, 0, 0, 0, 0, 0, 0}},
EncodingSettingsTestParameters{
.codec_type = "VP9",
.scalability_mode = "L3T3",
.bitrate_kbps = {10000},
.expected_bitrate_kbps = {77, 23, 42, 226, 68, 124, 823, 249,
452}},
EncodingSettingsTestParameters{
.codec_type = "VP9",
.scalability_mode = "L3T3",
.bitrate_kbps = {100, 200, 300, 400, 500, 600, 700, 800, 900},
.expected_bitrate_kbps = {100, 200, 300, 400, 500, 600, 700, 800,
900}}));
Values(
EncodingSettingsTestParameters{
.codec_type = "VP9",
.scalability_mode = "L1T1",
.bitrate = {DataRate::KilobitsPerSec(1)},
.expected_bitrate = {DataRate::KilobitsPerSec(1)}},
EncodingSettingsTestParameters{
.codec_type = "VP9",
.scalability_mode = "L1T1",
.bitrate = {DataRate::KilobitsPerSec(10000)},
.expected_bitrate = {DataRate::KilobitsPerSec(10000)}},
EncodingSettingsTestParameters{
.codec_type = "VP9",
.scalability_mode = "L1T3",
.bitrate = {DataRate::KilobitsPerSec(1000)},
.expected_bitrate = {DataRate::BitsPerSec(539811),
DataRate::BitsPerSec(163293),
DataRate::BitsPerSec(296896)}},
EncodingSettingsTestParameters{
.codec_type = "VP9",
.scalability_mode = "L3T3",
.bitrate = {DataRate::KilobitsPerSec(100)},
.expected_bitrate =
{DataRate::BitsPerSec(53981), DataRate::BitsPerSec(16329),
DataRate::BitsPerSec(29690), DataRate::BitsPerSec(0),
DataRate::BitsPerSec(0), DataRate::BitsPerSec(0),
DataRate::BitsPerSec(0), DataRate::BitsPerSec(0),
DataRate::BitsPerSec(0)}},
EncodingSettingsTestParameters{
.codec_type = "VP9",
.scalability_mode = "L3T3",
.bitrate = {DataRate::KilobitsPerSec(10000)},
.expected_bitrate =
{DataRate::BitsPerSec(76653), DataRate::BitsPerSec(23188),
DataRate::BitsPerSec(42159), DataRate::BitsPerSec(225641),
DataRate::BitsPerSec(68256), DataRate::BitsPerSec(124103),
DataRate::BitsPerSec(822672), DataRate::BitsPerSec(248858),
DataRate::BitsPerSec(452470)}},
EncodingSettingsTestParameters{
.codec_type = "VP9",
.scalability_mode = "L3T3",
.bitrate =
{DataRate::KilobitsPerSec(100), DataRate::KilobitsPerSec(200),
DataRate::KilobitsPerSec(300), DataRate::KilobitsPerSec(400),
DataRate::KilobitsPerSec(500), DataRate::KilobitsPerSec(600),
DataRate::KilobitsPerSec(700), DataRate::KilobitsPerSec(800),
DataRate::KilobitsPerSec(900)},
.expected_bitrate = {
DataRate::KilobitsPerSec(100), DataRate::KilobitsPerSec(200),
DataRate::KilobitsPerSec(300), DataRate::KilobitsPerSec(400),
DataRate::KilobitsPerSec(500), DataRate::KilobitsPerSec(600),
DataRate::KilobitsPerSec(700), DataRate::KilobitsPerSec(800),
DataRate::KilobitsPerSec(900)}}));
INSTANTIATE_TEST_SUITE_P(
Av1,
VideoCodecTesterTestEncodingSettings,
Values(EncodingSettingsTestParameters{.codec_type = "AV1",
.scalability_mode = "L1T1",
.bitrate_kbps = {1},
.expected_bitrate_kbps = {1}},
EncodingSettingsTestParameters{.codec_type = "AV1",
.scalability_mode = "L1T1",
.bitrate_kbps = {10000},
.expected_bitrate_kbps = {10000}},
EncodingSettingsTestParameters{
.codec_type = "AV1",
.scalability_mode = "L1T3",
.bitrate_kbps = {1000},
.expected_bitrate_kbps = {540, 163, 297}},
EncodingSettingsTestParameters{
.codec_type = "AV1",
.scalability_mode = "L3T3",
.bitrate_kbps = {100},
.expected_bitrate_kbps = {54, 16, 30, 0, 0, 0, 0, 0, 0}},
EncodingSettingsTestParameters{
.codec_type = "AV1",
.scalability_mode = "L3T3",
.bitrate_kbps = {10000},
.expected_bitrate_kbps = {77, 23, 42, 226, 68, 124, 823, 249,
452}},
EncodingSettingsTestParameters{
.codec_type = "AV1",
.scalability_mode = "L3T3",
.bitrate_kbps = {100, 200, 300, 400, 500, 600, 700, 800, 900},
.expected_bitrate_kbps = {100, 200, 300, 400, 500, 600, 700, 800,
900}}));
Values(
EncodingSettingsTestParameters{
.codec_type = "AV1",
.scalability_mode = "L1T1",
.bitrate = {DataRate::KilobitsPerSec(1)},
.expected_bitrate = {DataRate::KilobitsPerSec(1)}},
EncodingSettingsTestParameters{
.codec_type = "AV1",
.scalability_mode = "L1T1",
.bitrate = {DataRate::KilobitsPerSec(10000)},
.expected_bitrate = {DataRate::KilobitsPerSec(10000)}},
EncodingSettingsTestParameters{
.codec_type = "AV1",
.scalability_mode = "L1T3",
.bitrate = {DataRate::KilobitsPerSec(1000)},
.expected_bitrate = {DataRate::BitsPerSec(539811),
DataRate::BitsPerSec(163293),
DataRate::BitsPerSec(296896)}},
EncodingSettingsTestParameters{
.codec_type = "AV1",
.scalability_mode = "L3T3",
.bitrate = {DataRate::KilobitsPerSec(100)},
.expected_bitrate =
{DataRate::BitsPerSec(53981), DataRate::BitsPerSec(16329),
DataRate::BitsPerSec(29690), DataRate::BitsPerSec(0),
DataRate::BitsPerSec(0), DataRate::BitsPerSec(0),
DataRate::BitsPerSec(0), DataRate::BitsPerSec(0),
DataRate::BitsPerSec(0)}},
EncodingSettingsTestParameters{
.codec_type = "AV1",
.scalability_mode = "L3T3",
.bitrate = {DataRate::KilobitsPerSec(10000)},
.expected_bitrate =
{DataRate::BitsPerSec(76653), DataRate::BitsPerSec(23188),
DataRate::BitsPerSec(42159), DataRate::BitsPerSec(225641),
DataRate::BitsPerSec(68256), DataRate::BitsPerSec(124103),
DataRate::BitsPerSec(822672), DataRate::BitsPerSec(248858),
DataRate::BitsPerSec(452470)}},
EncodingSettingsTestParameters{
.codec_type = "AV1",
.scalability_mode = "L3T3",
.bitrate =
{DataRate::KilobitsPerSec(100), DataRate::KilobitsPerSec(200),
DataRate::KilobitsPerSec(300), DataRate::KilobitsPerSec(400),
DataRate::KilobitsPerSec(500), DataRate::KilobitsPerSec(600),
DataRate::KilobitsPerSec(700), DataRate::KilobitsPerSec(800),
DataRate::KilobitsPerSec(900)},
.expected_bitrate = {
DataRate::KilobitsPerSec(100), DataRate::KilobitsPerSec(200),
DataRate::KilobitsPerSec(300), DataRate::KilobitsPerSec(400),
DataRate::KilobitsPerSec(500), DataRate::KilobitsPerSec(600),
DataRate::KilobitsPerSec(700), DataRate::KilobitsPerSec(800),
DataRate::KilobitsPerSec(900)}}));
} // namespace test
} // namespace webrtc