tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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