video_codec_test.cc (26203B)
1 /* 2 * Copyright (c) 2022 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include <algorithm> 12 #include <cstdint> 13 #include <iterator> 14 #include <limits> 15 #include <map> 16 #include <memory> 17 #include <optional> 18 #include <string> 19 #include <tuple> 20 #include <utility> 21 #include <vector> 22 23 #include "absl/flags/flag.h" 24 #include "api/environment/environment.h" 25 #include "api/environment/environment_factory.h" 26 #include "api/test/metrics/global_metrics_logger_and_exporter.h" 27 #include "api/units/data_rate.h" 28 #include "api/units/frequency.h" 29 #include "api/video/resolution.h" 30 #include "api/video_codecs/builtin_video_decoder_factory.h" 31 #include "api/video_codecs/builtin_video_encoder_factory.h" 32 #include "api/video_codecs/scalability_mode.h" 33 #include "api/video_codecs/sdp_video_format.h" 34 #include "api/video_codecs/video_decoder_factory.h" 35 #include "api/video_codecs/video_encoder_factory.h" 36 #include "rtc_base/checks.h" 37 #if defined(WEBRTC_ANDROID) 38 #include "modules/video_coding/codecs/test/android_codec_factory_helper.h" 39 #endif 40 #include "modules/video_coding/svc/scalability_mode_util.h" 41 #include "rtc_base/logging.h" 42 #include "rtc_base/strings/string_builder.h" 43 #include "test/create_test_field_trials.h" 44 #include "test/gtest.h" 45 #include "test/test_flags.h" 46 #include "test/testsupport/file_utils.h" 47 #include "test/video_codec_tester.h" 48 49 ABSL_FLAG(std::string, 50 input_path, 51 webrtc::test::ResourcePath("FourPeople_1280x720_30", "yuv"), 52 "Path to input video file."); 53 ABSL_FLAG(int, input_width, 1280, "Input video width."); 54 ABSL_FLAG(int, input_height, 720, "Input video height."); 55 ABSL_FLAG(double, input_framerate_fps, 30, "Input video framerate, fps."); 56 ABSL_FLAG(std::string, 57 encoder, 58 "libaom-av1", 59 "Encoder: libaom-av1, libvpx-vp9, libvpx-vp8, openh264, hw-vp8, " 60 "hw-vp9, hw-av1, hw-h264, hw-h265"); 61 ABSL_FLAG(std::string, 62 decoder, 63 "dav1d", 64 "Decoder: dav1d, libvpx-vp9, libvpx-vp8, ffmpeg-h264, hw-vp8, " 65 "hw-vp9, hw-av1, hw-h264, hw-h265"); 66 ABSL_FLAG(std::string, scalability_mode, "L1T1", "Scalability mode."); 67 ABSL_FLAG(std::optional<int>, width, std::nullopt, "Encode width."); 68 ABSL_FLAG(std::optional<int>, height, std::nullopt, "Encode height."); 69 ABSL_FLAG(std::vector<std::string>, 70 bitrate_kbps, 71 {"1024"}, 72 "Encode target bitrate per layer (l0t0,l0t1,...l1t0,l1t1 and so on) " 73 "in kbps."); 74 ABSL_FLAG(std::optional<double>, 75 framerate_fps, 76 std::nullopt, 77 "Encode target frame rate of the top temporal layer in fps."); 78 ABSL_FLAG(bool, screencast, false, "Enable screen encoding mode."); 79 ABSL_FLAG(bool, frame_drop, true, "Enable frame dropping."); 80 ABSL_FLAG(int, 81 key_interval, 82 std::numeric_limits<int>::max(), 83 "Keyframe interval in frames."); 84 ABSL_FLAG(int, num_frames, 300, "Number of frames to encode and/or decode."); 85 ABSL_FLAG(std::string, test_name, "", "Test name."); 86 ABSL_FLAG(bool, dump_decoder_input, false, "Dump decoder input."); 87 ABSL_FLAG(bool, dump_decoder_output, false, "Dump decoder output."); 88 ABSL_FLAG(bool, dump_encoder_input, false, "Dump encoder input."); 89 ABSL_FLAG(bool, dump_encoder_output, false, "Dump encoder output."); 90 ABSL_FLAG(bool, write_csv, false, "Write metrics to a CSV file."); 91 92 namespace webrtc { 93 namespace test { 94 95 namespace { 96 using ::testing::Combine; 97 using ::testing::Values; 98 using VideoSourceSettings = VideoCodecTester::VideoSourceSettings; 99 using EncodingSettings = VideoCodecTester::EncodingSettings; 100 using VideoCodecStats = VideoCodecTester::VideoCodecStats; 101 using Filter = VideoCodecStats::Filter; 102 using PacingMode = VideoCodecTester::PacingSettings::PacingMode; 103 104 struct VideoInfo { 105 std::string name; 106 Resolution resolution; 107 Frequency framerate; 108 }; 109 110 VideoInfo kFourPeople_1280x720_30 = { 111 .name = "FourPeople_1280x720_30", 112 .resolution = {.width = 1280, .height = 720}, 113 .framerate = Frequency::Hertz(30)}; 114 115 constexpr Frequency k90kHz = Frequency::Hertz(90000); 116 117 VideoSourceSettings ToSourceSettings(VideoInfo video_info) { 118 return VideoSourceSettings{.file_path = ResourcePath(video_info.name, "yuv"), 119 .resolution = video_info.resolution, 120 .framerate = video_info.framerate}; 121 } 122 123 std::string CodecNameToCodecType(std::string name) { 124 if (name.find("av1") != std::string::npos) { 125 return "AV1"; 126 } 127 if (name.find("vp9") != std::string::npos) { 128 return "VP9"; 129 } 130 if (name.find("vp8") != std::string::npos) { 131 return "VP8"; 132 } 133 if (name.find("h264") != std::string::npos) { 134 return "H264"; 135 } 136 if (name.find("h265") != std::string::npos) { 137 return "H265"; 138 } 139 RTC_CHECK_NOTREACHED(); 140 } 141 142 // TODO(webrtc:14852): Make Create[Encoder,Decoder]Factory to work with codec 143 // name directly. 144 std::string CodecNameToCodecImpl(std::string name) { 145 if (name.find("hw") != std::string::npos) { 146 return "mediacodec"; 147 } 148 return "builtin"; 149 } 150 151 std::unique_ptr<VideoEncoderFactory> CreateEncoderFactory(std::string impl) { 152 if (impl == "builtin") { 153 return CreateBuiltinVideoEncoderFactory(); 154 } 155 #if defined(WEBRTC_ANDROID) 156 InitializeAndroidObjects(); 157 return CreateAndroidEncoderFactory(); 158 #else 159 return nullptr; 160 #endif 161 } 162 163 std::unique_ptr<VideoDecoderFactory> CreateDecoderFactory(std::string impl) { 164 if (impl == "builtin") { 165 return CreateBuiltinVideoDecoderFactory(); 166 } 167 #if defined(WEBRTC_ANDROID) 168 InitializeAndroidObjects(); 169 return CreateAndroidDecoderFactory(); 170 #else 171 return nullptr; 172 #endif 173 } 174 175 std::string TestName() { 176 std::string test_name = absl::GetFlag(FLAGS_test_name); 177 if (!test_name.empty()) { 178 return test_name; 179 } 180 return ::testing::UnitTest::GetInstance()->current_test_info()->name(); 181 } 182 183 std::string TestOutputPath() { 184 std::string output_path = 185 (StringBuilder() << OutputPath() << TestName()).str(); 186 std::string output_dir = DirName(output_path); 187 bool result = CreateDir(output_dir); 188 RTC_CHECK(result) << "Cannot create " << output_dir; 189 return output_path; 190 } 191 } // namespace 192 193 std::unique_ptr<VideoCodecStats> RunEncodeDecodeTest( 194 const Environment& env, 195 std::string encoder_impl, 196 std::string decoder_impl, 197 const VideoSourceSettings& source_settings, 198 const std::map<uint32_t, EncodingSettings>& encoding_settings) { 199 const SdpVideoFormat& sdp_video_format = 200 encoding_settings.begin()->second.sdp_video_format; 201 202 std::unique_ptr<VideoEncoderFactory> encoder_factory = 203 CreateEncoderFactory(encoder_impl); 204 if (!encoder_factory 205 ->QueryCodecSupport(sdp_video_format, 206 /*scalability_mode=*/std::nullopt) 207 .is_supported) { 208 RTC_LOG(LS_WARNING) << "No " << encoder_impl << " encoder for video format " 209 << sdp_video_format.ToString(); 210 return nullptr; 211 } 212 213 std::unique_ptr<VideoDecoderFactory> decoder_factory = 214 CreateDecoderFactory(decoder_impl); 215 if (!decoder_factory 216 ->QueryCodecSupport(sdp_video_format, 217 /*reference_scaling=*/false) 218 .is_supported) { 219 RTC_LOG(LS_WARNING) << "No " << decoder_impl << " decoder for video format " 220 << sdp_video_format.ToString() 221 << ". Trying built-in decoder."; 222 // TODO(ssilkin): No H264 support in ffmpeg on ARM. Consider trying HW 223 // decoder. 224 decoder_factory = CreateDecoderFactory("builtin"); 225 if (!decoder_factory 226 ->QueryCodecSupport(sdp_video_format, 227 /*reference_scaling=*/false) 228 .is_supported) { 229 RTC_LOG(LS_WARNING) << "No " << decoder_impl 230 << " decoder for video format " 231 << sdp_video_format.ToString(); 232 return nullptr; 233 } 234 } 235 236 std::string output_path = TestOutputPath(); 237 238 VideoCodecTester::EncoderSettings encoder_settings; 239 encoder_settings.pacing_settings.mode = 240 encoder_impl == "builtin" ? PacingMode::kNoPacing : PacingMode::kRealTime; 241 if (absl::GetFlag(FLAGS_dump_encoder_input)) { 242 encoder_settings.encoder_input_base_path = output_path + "_enc_input"; 243 } 244 if (absl::GetFlag(FLAGS_dump_encoder_output)) { 245 encoder_settings.encoder_output_base_path = output_path + "_enc_output"; 246 } 247 248 VideoCodecTester::DecoderSettings decoder_settings; 249 decoder_settings.pacing_settings.mode = 250 decoder_impl == "builtin" ? PacingMode::kNoPacing : PacingMode::kRealTime; 251 if (absl::GetFlag(FLAGS_dump_decoder_input)) { 252 decoder_settings.decoder_input_base_path = output_path + "_dec_input"; 253 } 254 if (absl::GetFlag(FLAGS_dump_decoder_output)) { 255 decoder_settings.decoder_output_base_path = output_path + "_dec_output"; 256 } 257 258 return VideoCodecTester::RunEncodeDecodeTest( 259 env, source_settings, encoder_factory.get(), decoder_factory.get(), 260 encoder_settings, decoder_settings, encoding_settings); 261 } 262 263 std::unique_ptr<VideoCodecStats> RunEncodeTest( 264 const Environment& env, 265 std::string encoder_impl, 266 const VideoSourceSettings& source_settings, 267 const std::map<uint32_t, EncodingSettings>& encoding_settings) { 268 const SdpVideoFormat& sdp_video_format = 269 encoding_settings.begin()->second.sdp_video_format; 270 271 std::unique_ptr<VideoEncoderFactory> encoder_factory = 272 CreateEncoderFactory(encoder_impl); 273 if (!encoder_factory 274 ->QueryCodecSupport(sdp_video_format, 275 /*scalability_mode=*/std::nullopt) 276 .is_supported) { 277 RTC_LOG(LS_WARNING) << "No encoder for video format " 278 << sdp_video_format.ToString(); 279 return nullptr; 280 } 281 282 std::string output_path = TestOutputPath(); 283 VideoCodecTester::EncoderSettings encoder_settings; 284 encoder_settings.pacing_settings.mode = 285 encoder_impl == "builtin" ? PacingMode::kNoPacing : PacingMode::kRealTime; 286 if (absl::GetFlag(FLAGS_dump_encoder_input)) { 287 encoder_settings.encoder_input_base_path = output_path + "_enc_input"; 288 } 289 if (absl::GetFlag(FLAGS_dump_encoder_output)) { 290 encoder_settings.encoder_output_base_path = output_path + "_enc_output"; 291 } 292 293 return VideoCodecTester::RunEncodeTest(env, source_settings, 294 encoder_factory.get(), 295 encoder_settings, encoding_settings); 296 } 297 298 class SpatialQualityTest : public ::testing::TestWithParam<std::tuple< 299 /*codec_type=*/std::string, 300 /*codec_impl=*/std::string, 301 VideoInfo, 302 std::tuple</*width=*/int, 303 /*height=*/int, 304 /*framerate_fps=*/double, 305 /*bitrate_kbps=*/int, 306 /*expected_min_psnr=*/double>>> { 307 public: 308 static std::string TestParamsToString( 309 const ::testing::TestParamInfo<SpatialQualityTest::ParamType>& info) { 310 auto [codec_type, codec_impl, video_info, coding_settings] = info.param; 311 auto [width, height, framerate_fps, bitrate_kbps, psnr] = coding_settings; 312 return std::string(codec_type + codec_impl + video_info.name + 313 std::to_string(width) + "x" + std::to_string(height) + 314 "p" + 315 std::to_string(static_cast<int>(1000 * framerate_fps)) + 316 "mhz" + std::to_string(bitrate_kbps) + "kbps"); 317 } 318 }; 319 320 TEST_P(SpatialQualityTest, SpatialQuality) { 321 const Environment env = CreateEnvironment(); 322 auto [codec_type, codec_impl, video_info, coding_settings] = GetParam(); 323 auto [width, height, framerate_fps, bitrate_kbps, expected_min_psnr] = 324 coding_settings; 325 int duration_s = 10; 326 int num_frames = duration_s * framerate_fps; 327 328 VideoSourceSettings source_settings = ToSourceSettings(video_info); 329 330 EncodingSettings encoding_settings = VideoCodecTester::CreateEncodingSettings( 331 env, codec_type, /*scalability_name=*/"L1T1", width, height, 332 {DataRate::KilobitsPerSec(bitrate_kbps)}, 333 Frequency::Hertz(framerate_fps)); 334 335 std::map<uint32_t, EncodingSettings> frame_settings = 336 VideoCodecTester::CreateFrameSettings(encoding_settings, num_frames); 337 338 std::unique_ptr<VideoCodecStats> stats = RunEncodeDecodeTest( 339 env, codec_impl, codec_impl, source_settings, frame_settings); 340 341 VideoCodecStats::Stream stream; 342 if (stats != nullptr) { 343 stream = stats->Aggregate(Filter{}); 344 if (absl::GetFlag(FLAGS_webrtc_quick_perf_test)) { 345 EXPECT_GE(stream.psnr.y.GetAverage(), expected_min_psnr); 346 } 347 } 348 349 stream.LogMetrics( 350 GetGlobalMetricsLogger(), 351 ::testing::UnitTest::GetInstance()->current_test_info()->name(), 352 /*prefix=*/"", 353 /*metadata=*/ 354 {{"video_name", video_info.name}, 355 {"codec_type", codec_type}, 356 {"codec_impl", codec_impl}}); 357 358 if (absl::GetFlag(FLAGS_write_csv)) { 359 stats->LogMetrics((StringBuilder() << TestOutputPath() << ".csv").str(), 360 stats->Slice(Filter{}, /*merge=*/false), /*metadata=*/ 361 {{"test_name", TestName()}}); 362 } 363 } 364 365 INSTANTIATE_TEST_SUITE_P( 366 All, 367 SpatialQualityTest, 368 Combine(Values("AV1", "VP9", "VP8", "H264", "H265"), 369 #if defined(WEBRTC_ANDROID) 370 Values("builtin", "mediacodec"), 371 #else 372 Values("builtin"), 373 #endif 374 Values(kFourPeople_1280x720_30), 375 Values(std::make_tuple(320, 180, 30, 32, 26), 376 std::make_tuple(320, 180, 30, 64, 29), 377 std::make_tuple(320, 180, 30, 128, 32), 378 std::make_tuple(320, 180, 30, 256, 36), 379 std::make_tuple(640, 360, 30, 128, 29), 380 std::make_tuple(640, 360, 30, 256, 33), 381 std::make_tuple(640, 360, 30, 384, 35), 382 std::make_tuple(640, 360, 30, 512, 36), 383 std::make_tuple(1280, 720, 30, 256, 30), 384 std::make_tuple(1280, 720, 30, 512, 34), 385 std::make_tuple(1280, 720, 30, 1024, 37), 386 std::make_tuple(1280, 720, 30, 2048, 39))), 387 SpatialQualityTest::TestParamsToString); 388 389 class BitrateAdaptationTest 390 : public ::testing::TestWithParam< 391 std::tuple</*codec_type=*/std::string, 392 /*codec_impl=*/std::string, 393 VideoInfo, 394 std::pair</*bitrate_kbps=*/int, /*bitrate_kbps=*/int>>> { 395 public: 396 static std::string TestParamsToString( 397 const ::testing::TestParamInfo<BitrateAdaptationTest::ParamType>& info) { 398 auto [codec_type, codec_impl, video_info, bitrate_kbps] = info.param; 399 return std::string(codec_type + codec_impl + video_info.name + 400 std::to_string(bitrate_kbps.first) + "kbps" + 401 std::to_string(bitrate_kbps.second) + "kbps"); 402 } 403 }; 404 405 TEST_P(BitrateAdaptationTest, BitrateAdaptation) { 406 auto [codec_type, codec_impl, video_info, bitrate_kbps] = GetParam(); 407 const Environment env = CreateEnvironment(); 408 409 int duration_s = 10; // Duration of fixed rate interval. 410 int num_frames = 411 static_cast<int>(duration_s * video_info.framerate.hertz<double>()); 412 413 VideoSourceSettings source_settings = ToSourceSettings(video_info); 414 415 EncodingSettings encoding_settings = VideoCodecTester::CreateEncodingSettings( 416 env, codec_type, /*scalability_name=*/"L1T1", 417 /*width=*/640, /*height=*/360, 418 {DataRate::KilobitsPerSec(bitrate_kbps.first)}, 419 /*framerate=*/Frequency::Hertz(30)); 420 421 EncodingSettings encoding_settings2 = 422 VideoCodecTester::CreateEncodingSettings( 423 env, codec_type, /*scalability_name=*/"L1T1", 424 /*width=*/640, /*height=*/360, 425 {DataRate::KilobitsPerSec(bitrate_kbps.second)}, 426 /*framerate=*/Frequency::Hertz(30)); 427 428 std::map<uint32_t, EncodingSettings> frame_settings = 429 VideoCodecTester::CreateFrameSettings(encoding_settings, num_frames); 430 431 uint32_t timestamp_rtp = 432 frame_settings.rbegin()->first + k90kHz / Frequency::Hertz(30); 433 std::map<uint32_t, EncodingSettings> frame_settings2 = 434 VideoCodecTester::CreateFrameSettings(encoding_settings2, num_frames, 435 timestamp_rtp); 436 437 frame_settings.merge(frame_settings2); 438 439 std::unique_ptr<VideoCodecStats> stats = 440 RunEncodeTest(env, codec_impl, source_settings, frame_settings); 441 442 VideoCodecStats::Stream stream; 443 if (stats != nullptr) { 444 stream = stats->Aggregate({.min_timestamp_rtp = timestamp_rtp}); 445 if (absl::GetFlag(FLAGS_webrtc_quick_perf_test)) { 446 EXPECT_NEAR(stream.bitrate_mismatch_pct.GetAverage(), 0, 10); 447 EXPECT_NEAR(stream.framerate_mismatch_pct.GetAverage(), 0, 10); 448 } 449 } 450 451 stream.LogMetrics( 452 GetGlobalMetricsLogger(), 453 ::testing::UnitTest::GetInstance()->current_test_info()->name(), 454 /*prefix=*/"", 455 /*metadata=*/ 456 {{"codec_type", codec_type}, 457 {"codec_impl", codec_impl}, 458 {"video_name", video_info.name}, 459 {"rate_profile", std::to_string(bitrate_kbps.first) + "," + 460 std::to_string(bitrate_kbps.second)}}); 461 462 if (absl::GetFlag(FLAGS_write_csv)) { 463 stats->LogMetrics((StringBuilder() << TestOutputPath() << ".csv").str(), 464 stats->Slice(Filter{}, /*merge=*/false), /*metadata=*/ 465 {{"test_name", TestName()}}); 466 } 467 } 468 469 INSTANTIATE_TEST_SUITE_P(All, 470 BitrateAdaptationTest, 471 Combine(Values("AV1", "VP9", "VP8", "H264", "H265"), 472 #if defined(WEBRTC_ANDROID) 473 Values("builtin", "mediacodec"), 474 #else 475 Values("builtin"), 476 #endif 477 Values(kFourPeople_1280x720_30), 478 Values(std::pair(1024, 512), 479 std::pair(512, 1024))), 480 BitrateAdaptationTest::TestParamsToString); 481 482 class FramerateAdaptationTest 483 : public ::testing::TestWithParam<std::tuple</*codec_type=*/std::string, 484 /*codec_impl=*/std::string, 485 VideoInfo, 486 std::pair<double, double>>> { 487 public: 488 static std::string TestParamsToString( 489 const ::testing::TestParamInfo<FramerateAdaptationTest::ParamType>& 490 info) { 491 auto [codec_type, codec_impl, video_info, framerate_fps] = info.param; 492 return std::string( 493 codec_type + codec_impl + video_info.name + 494 std::to_string(static_cast<int>(1000 * framerate_fps.first)) + "mhz" + 495 std::to_string(static_cast<int>(1000 * framerate_fps.second)) + "mhz"); 496 } 497 }; 498 499 TEST_P(FramerateAdaptationTest, FramerateAdaptation) { 500 auto [codec_type, codec_impl, video_info, framerate_fps] = GetParam(); 501 const Environment env = CreateEnvironment(); 502 503 int duration_s = 10; // Duration of fixed rate interval. 504 505 VideoSourceSettings source_settings = ToSourceSettings(video_info); 506 507 EncodingSettings encoding_settings = VideoCodecTester::CreateEncodingSettings( 508 env, codec_type, /*scalability_name=*/"L1T1", 509 /*width=*/640, /*height=*/360, 510 /*bitrate=*/{DataRate::KilobitsPerSec(512)}, 511 Frequency::Hertz(framerate_fps.first)); 512 513 EncodingSettings encoding_settings2 = 514 VideoCodecTester::CreateEncodingSettings( 515 env, codec_type, /*scalability_name=*/"L1T1", 516 /*width=*/640, /*height=*/360, 517 /*bitrate=*/{DataRate::KilobitsPerSec(512)}, 518 Frequency::Hertz(framerate_fps.second)); 519 520 int num_frames = static_cast<int>(duration_s * framerate_fps.first); 521 std::map<uint32_t, EncodingSettings> frame_settings = 522 VideoCodecTester::CreateFrameSettings(encoding_settings, num_frames); 523 524 uint32_t timestamp_rtp = frame_settings.rbegin()->first + 525 k90kHz / Frequency::Hertz(framerate_fps.first); 526 527 num_frames = static_cast<int>(duration_s * framerate_fps.second); 528 std::map<uint32_t, EncodingSettings> frame_settings2 = 529 VideoCodecTester::CreateFrameSettings(encoding_settings2, num_frames, 530 timestamp_rtp); 531 532 frame_settings.merge(frame_settings2); 533 534 std::unique_ptr<VideoCodecStats> stats = 535 RunEncodeTest(env, codec_impl, source_settings, frame_settings); 536 537 VideoCodecStats::Stream stream; 538 if (stats != nullptr) { 539 stream = stats->Aggregate({.min_timestamp_rtp = timestamp_rtp}); 540 if (absl::GetFlag(FLAGS_webrtc_quick_perf_test)) { 541 EXPECT_NEAR(stream.bitrate_mismatch_pct.GetAverage(), 0, 10); 542 EXPECT_NEAR(stream.framerate_mismatch_pct.GetAverage(), 0, 10); 543 } 544 } 545 546 stream.LogMetrics( 547 GetGlobalMetricsLogger(), 548 ::testing::UnitTest::GetInstance()->current_test_info()->name(), 549 /*prefix=*/"", 550 /*metadata=*/ 551 {{"codec_type", codec_type}, 552 {"codec_impl", codec_impl}, 553 {"video_name", video_info.name}, 554 {"rate_profile", std::to_string(framerate_fps.first) + "," + 555 std::to_string(framerate_fps.second)}}); 556 557 if (absl::GetFlag(FLAGS_write_csv)) { 558 stats->LogMetrics((StringBuilder() << TestOutputPath() << ".csv").str(), 559 stats->Slice(Filter{}, /*merge=*/false), /*metadata=*/ 560 {{"test_name", TestName()}}); 561 } 562 } 563 564 INSTANTIATE_TEST_SUITE_P(All, 565 FramerateAdaptationTest, 566 Combine(Values("AV1", "VP9", "VP8", "H264", "H265"), 567 #if defined(WEBRTC_ANDROID) 568 Values("builtin", "mediacodec"), 569 #else 570 Values("builtin"), 571 #endif 572 Values(kFourPeople_1280x720_30), 573 Values(std::pair(30, 15), std::pair(15, 30))), 574 FramerateAdaptationTest::TestParamsToString); 575 576 TEST(VideoCodecTest, DISABLED_EncodeDecode) { 577 const Environment env = CreateEnvironment(CreateTestFieldTrialsPtr()); 578 579 VideoSourceSettings source_settings{ 580 .file_path = absl::GetFlag(FLAGS_input_path), 581 .resolution = {.width = absl::GetFlag(FLAGS_input_width), 582 .height = absl::GetFlag(FLAGS_input_height)}, 583 .framerate = 584 Frequency::Hertz<double>(absl::GetFlag(FLAGS_input_framerate_fps))}; 585 586 std::vector<std::string> bitrate_str = absl::GetFlag(FLAGS_bitrate_kbps); 587 std::vector<DataRate> bitrate; 588 std::transform(bitrate_str.begin(), bitrate_str.end(), 589 std::back_inserter(bitrate), [](const std::string& str) { 590 return DataRate::KilobitsPerSec(std::stoi(str)); 591 }); 592 593 Frequency framerate = Frequency::Hertz<double>( 594 absl::GetFlag(FLAGS_framerate_fps) 595 .value_or(absl::GetFlag(FLAGS_input_framerate_fps))); 596 597 EncodingSettings encoding_settings = VideoCodecTester::CreateEncodingSettings( 598 env, CodecNameToCodecType(absl::GetFlag(FLAGS_encoder)), 599 absl::GetFlag(FLAGS_scalability_mode), 600 absl::GetFlag(FLAGS_width).value_or(absl::GetFlag(FLAGS_input_width)), 601 absl::GetFlag(FLAGS_height).value_or(absl::GetFlag(FLAGS_input_height)), 602 {bitrate}, framerate, absl::GetFlag(FLAGS_screencast), 603 absl::GetFlag(FLAGS_frame_drop)); 604 605 int num_frames = absl::GetFlag(FLAGS_num_frames); 606 int key_interval = absl::GetFlag(FLAGS_key_interval); 607 uint32_t timestamp_rtp = 90000; 608 std::map<uint32_t, EncodingSettings> frame_settings; 609 for (int frame_num = 0; frame_num < num_frames; ++frame_num) { 610 encoding_settings.keyframe = 611 (key_interval > 0 && (frame_num % key_interval) == 0); 612 frame_settings.emplace(timestamp_rtp, encoding_settings); 613 timestamp_rtp += k90kHz / framerate; 614 } 615 616 std::unique_ptr<VideoCodecStats> stats; 617 std::string decoder = absl::GetFlag(FLAGS_decoder); 618 if (decoder == "null") { 619 stats = 620 RunEncodeTest(env, CodecNameToCodecImpl(absl::GetFlag(FLAGS_encoder)), 621 source_settings, frame_settings); 622 } else { 623 // TODO(webrtc:14852): Pass encoder and decoder names directly, and update 624 // logged test name (implies lossing history in the chromeperf dashboard). 625 // Sync with changes in Stream::LogMetrics (see TODOs there). 626 stats = RunEncodeDecodeTest( 627 env, CodecNameToCodecImpl(absl::GetFlag(FLAGS_encoder)), 628 CodecNameToCodecImpl(decoder), source_settings, frame_settings); 629 } 630 ASSERT_NE(nullptr, stats); 631 632 // Log unsliced metrics. 633 VideoCodecStats::Stream stream = stats->Aggregate(Filter{}); 634 stream.LogMetrics(GetGlobalMetricsLogger(), TestName(), /*prefix=*/"", 635 /*metadata=*/{}); 636 637 // Log metrics sliced on spatial and temporal layer. 638 ScalabilityMode scalability_mode = 639 *ScalabilityModeFromString(absl::GetFlag(FLAGS_scalability_mode)); 640 int num_spatial_layers = ScalabilityModeToNumSpatialLayers(scalability_mode); 641 int num_temporal_layers = 642 ScalabilityModeToNumTemporalLayers(scalability_mode); 643 for (int sidx = 0; sidx < num_spatial_layers; ++sidx) { 644 for (int tidx = 0; tidx < num_temporal_layers; ++tidx) { 645 std::string metric_name_prefix = 646 (StringBuilder() << "s" << sidx << "t" << tidx << "_").str(); 647 stream = stats->Aggregate( 648 {.layer_id = {{.spatial_idx = sidx, .temporal_idx = tidx}}}); 649 stream.LogMetrics(GetGlobalMetricsLogger(), TestName(), 650 metric_name_prefix, 651 /*metadata=*/{}); 652 } 653 } 654 655 if (absl::GetFlag(FLAGS_write_csv)) { 656 stats->LogMetrics((StringBuilder() << TestOutputPath() << ".csv").str(), 657 stats->Slice(Filter{}, /*merge=*/false), /*metadata=*/ 658 {{"test_name", TestName()}}); 659 } 660 } 661 662 } // namespace test 663 664 } // namespace webrtc