tor-browser

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

resize_test.cc (46534B)


      1 /*
      2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved.
      3 *
      4 * This source code is subject to the terms of the BSD 2 Clause License and
      5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
      6 * was not distributed with this source code in the LICENSE file, you can
      7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
      8 * Media Patent License 1.0 was not distributed with this source code in the
      9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
     10 */
     11 
     12 #include <climits>
     13 #include <vector>
     14 
     15 #include "aom/aomcx.h"
     16 #include "aom_dsp/aom_dsp_common.h"
     17 #include "av1/encoder/encoder.h"
     18 #include "gtest/gtest.h"
     19 #include "test/codec_factory.h"
     20 #include "test/encode_test_driver.h"
     21 #include "test/i420_video_source.h"
     22 #include "test/util.h"
     23 #include "test/video_source.h"
     24 #include "test/y4m_video_source.h"
     25 
     26 // Enable(1) or Disable(0) writing of the compressed bitstream.
     27 #define WRITE_COMPRESSED_STREAM 0
     28 
     29 namespace {
     30 
     31 #if WRITE_COMPRESSED_STREAM
     32 static void mem_put_le16(char *const mem, unsigned int val) {
     33  mem[0] = val;
     34  mem[1] = val >> 8;
     35 }
     36 
     37 static void mem_put_le32(char *const mem, unsigned int val) {
     38  mem[0] = val;
     39  mem[1] = val >> 8;
     40  mem[2] = val >> 16;
     41  mem[3] = val >> 24;
     42 }
     43 
     44 static void write_ivf_file_header(const aom_codec_enc_cfg_t *const cfg,
     45                                  int frame_cnt, FILE *const outfile) {
     46  char header[32];
     47 
     48  header[0] = 'D';
     49  header[1] = 'K';
     50  header[2] = 'I';
     51  header[3] = 'F';
     52  mem_put_le16(header + 4, 0);                    /* version */
     53  mem_put_le16(header + 6, 32);                   /* headersize */
     54  mem_put_le32(header + 8, AV1_FOURCC);           /* fourcc (av1) */
     55  mem_put_le16(header + 12, cfg->g_w);            /* width */
     56  mem_put_le16(header + 14, cfg->g_h);            /* height */
     57  mem_put_le32(header + 16, cfg->g_timebase.den); /* rate */
     58  mem_put_le32(header + 20, cfg->g_timebase.num); /* scale */
     59  mem_put_le32(header + 24, frame_cnt);           /* length */
     60  mem_put_le32(header + 28, 0);                   /* unused */
     61 
     62  (void)fwrite(header, 1, 32, outfile);
     63 }
     64 
     65 static void write_ivf_frame_size(FILE *const outfile, const size_t size) {
     66  char header[4];
     67  mem_put_le32(header, static_cast<unsigned int>(size));
     68  (void)fwrite(header, 1, 4, outfile);
     69 }
     70 
     71 static void write_ivf_frame_header(const aom_codec_cx_pkt_t *const pkt,
     72                                   FILE *const outfile) {
     73  char header[12];
     74  aom_codec_pts_t pts;
     75 
     76  if (pkt->kind != AOM_CODEC_CX_FRAME_PKT) return;
     77 
     78  pts = pkt->data.frame.pts;
     79  mem_put_le32(header, static_cast<unsigned int>(pkt->data.frame.sz));
     80  mem_put_le32(header + 4, pts & 0xFFFFFFFF);
     81  mem_put_le32(header + 8, pts >> 32);
     82 
     83  (void)fwrite(header, 1, 12, outfile);
     84 }
     85 #endif  // WRITE_COMPRESSED_STREAM
     86 
     87 const unsigned int kInitialWidth = 320;
     88 const unsigned int kInitialHeight = 240;
     89 
     90 struct FrameInfo {
     91  FrameInfo(aom_codec_pts_t _pts, unsigned int _w, unsigned int _h)
     92      : pts(_pts), w(_w), h(_h) {}
     93 
     94  aom_codec_pts_t pts;
     95  unsigned int w;
     96  unsigned int h;
     97 };
     98 
     99 void ScaleForFrameNumber(unsigned int frame, unsigned int initial_w,
    100                         unsigned int initial_h, int flag_codec,
    101                         bool change_start_resln,
    102                         bool random_input_one_half_only_, unsigned int *w,
    103                         unsigned int *h) {
    104  if (random_input_one_half_only_) {
    105    if (frame < 50) {
    106      *w = initial_w;
    107      *h = initial_h;
    108      return;
    109    }
    110    *w = initial_w / 2;
    111    *h = initial_h / 2;
    112    return;
    113  }
    114  if (frame < 10) {
    115    if (change_start_resln) {
    116      *w = initial_w / 4;
    117      *h = initial_h / 4;
    118    } else {
    119      *w = initial_w;
    120      *h = initial_h;
    121    }
    122    return;
    123  }
    124  if (frame < 20) {
    125    *w = initial_w * 3 / 4;
    126    *h = initial_h * 3 / 4;
    127    return;
    128  }
    129  if (frame < 30) {
    130    *w = initial_w / 2;
    131    *h = initial_h / 2;
    132    return;
    133  }
    134  if (frame < 40) {
    135    *w = initial_w;
    136    *h = initial_h;
    137    return;
    138  }
    139  if (frame < 50) {
    140    *w = initial_w * 3 / 4;
    141    *h = initial_h * 3 / 4;
    142    return;
    143  }
    144  if (frame < 60) {
    145    *w = initial_w / 2;
    146    *h = initial_h / 2;
    147    return;
    148  }
    149  if (frame < 70) {
    150    *w = initial_w;
    151    *h = initial_h;
    152    return;
    153  }
    154  if (frame < 80) {
    155    *w = initial_w * 3 / 4;
    156    *h = initial_h * 3 / 4;
    157    return;
    158  }
    159  if (frame < 90) {
    160    *w = initial_w / 2;
    161    *h = initial_h / 2;
    162    return;
    163  }
    164  if (frame < 100) {
    165    *w = initial_w * 3 / 4;
    166    *h = initial_h * 3 / 4;
    167    return;
    168  }
    169  if (frame < 110) {
    170    *w = initial_w;
    171    *h = initial_h;
    172    return;
    173  }
    174  // Go down very low
    175  if (frame < 120) {
    176    *w = initial_w / 4;
    177    *h = initial_h / 4;
    178    return;
    179  }
    180  if (flag_codec == 1) {
    181    // Cases that only works for AV1.
    182    // For AV1: Swap width and height of original.
    183    if (frame < 140) {
    184      *w = initial_h;
    185      *h = initial_w;
    186      return;
    187    }
    188  }
    189  *w = initial_w;
    190  *h = initial_h;
    191 }
    192 
    193 class ResizingVideoSource : public ::libaom_test::DummyVideoSource {
    194 public:
    195  ResizingVideoSource(int width, int height)
    196      : change_start_resln_(false), random_input_one_half_only_(false),
    197        top_width_(width), top_height_(height) {
    198    SetSize(top_width_, top_height_);
    199    limit_ = 150;
    200  }
    201  int flag_codec_;
    202  bool change_start_resln_;
    203  bool random_input_one_half_only_;
    204  // top_width_/height_ is the configured resolution when codec is created.
    205  int top_width_;
    206  int top_height_;
    207 
    208  ~ResizingVideoSource() override = default;
    209 
    210 protected:
    211  void Begin() override {
    212    frame_ = 0;
    213    unsigned int width;
    214    unsigned int height;
    215    ScaleForFrameNumber(frame_, top_width_, top_height_, flag_codec_,
    216                        change_start_resln_, random_input_one_half_only_,
    217                        &width, &height);
    218    SetSize(width, height);
    219    FillFrame();
    220  }
    221 
    222  void Next() override {
    223    ++frame_;
    224    unsigned int width;
    225    unsigned int height;
    226    ScaleForFrameNumber(frame_, top_width_, top_height_, flag_codec_,
    227                        change_start_resln_, random_input_one_half_only_,
    228                        &width, &height);
    229    SetSize(width, height);
    230    FillFrame();
    231  }
    232 
    233  void FillFrame() override {
    234    if (img_) {
    235      memset(img_->img_data, 0, raw_sz_);
    236      if (random_input_one_half_only_) {
    237        libaom_test::ACMRandom rnd(libaom_test::ACMRandom::DeterministicSeed());
    238        unsigned char *image = img_->planes[0];
    239        for (size_t i = 0; i < raw_sz_; ++i) {
    240          image[i] = rnd.Rand8();
    241        }
    242      }
    243    }
    244  }
    245 };
    246 
    247 class ResizeTest
    248    : public ::libaom_test::CodecTestWithParam<libaom_test::TestMode>,
    249      public ::libaom_test::EncoderTest {
    250 protected:
    251  ResizeTest() : EncoderTest(GET_PARAM(0)) {}
    252 
    253  ~ResizeTest() override = default;
    254 
    255  void SetUp() override { InitializeConfig(GET_PARAM(1)); }
    256 
    257  void PreEncodeFrameHook(libaom_test::VideoSource *video,
    258                          libaom_test::Encoder *encoder) override {
    259    if (video->frame() == 0) {
    260      if (GET_PARAM(1) == ::libaom_test::kRealTime) {
    261        encoder->Control(AV1E_SET_AQ_MODE, 3);
    262        encoder->Control(AOME_SET_CPUUSED, 5);
    263        encoder->Control(AV1E_SET_FRAME_PARALLEL_DECODING, 1);
    264      } else if (GET_PARAM(1) == ::libaom_test::kOnePassGood) {
    265        encoder->Control(AV1E_SET_AQ_MODE, 3);
    266        encoder->Control(AOME_SET_CPUUSED, 4);
    267        encoder->Control(AV1E_SET_ENABLE_GLOBAL_MOTION, 0);
    268        encoder->Control(AV1E_SET_ENABLE_WARPED_MOTION, 0);
    269        encoder->Control(AV1E_SET_ENABLE_RESTORATION, 0);
    270        encoder->Control(AV1E_SET_ENABLE_OBMC, 0);
    271      }
    272      if (cfg_.g_threads > 0) {
    273        encoder->Control(AV1E_SET_ROW_MT, 1);
    274        encoder->Control(AV1E_SET_TILE_COLUMNS, cfg_.g_threads >> 1);
    275        encoder->Control(AV1E_SET_TILE_ROWS, 0);
    276      }
    277    }
    278  }
    279 
    280  void DecompressedFrameHook(const aom_image_t &img,
    281                             aom_codec_pts_t pts) override {
    282    frame_info_list_.push_back(FrameInfo(pts, img.d_w, img.d_h));
    283  }
    284 
    285  std::vector<FrameInfo> frame_info_list_;
    286 };
    287 
    288 TEST_P(ResizeTest, TestExternalResizeWorks) {
    289  ResizingVideoSource video(kInitialWidth, kInitialHeight);
    290  video.flag_codec_ = 0;
    291  video.change_start_resln_ = false;
    292  cfg_.g_lag_in_frames = 0;
    293  // We use max(kInitialWidth, kInitialHeight) because during the test
    294  // the width and height of the frame are swapped
    295  cfg_.g_forced_max_frame_width = cfg_.g_forced_max_frame_height =
    296      AOMMAX(kInitialWidth, kInitialHeight);
    297  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
    298 
    299 #if CONFIG_AV1_DECODER
    300  // Check we decoded the same number of frames as we attempted to encode
    301  ASSERT_EQ(frame_info_list_.size(), video.limit());
    302 
    303  for (const auto &info : frame_info_list_) {
    304    const unsigned int frame = static_cast<unsigned>(info.pts);
    305    unsigned int expected_w;
    306    unsigned int expected_h;
    307    ScaleForFrameNumber(frame, kInitialWidth, kInitialHeight, video.flag_codec_,
    308                        video.change_start_resln_, false, &expected_w,
    309                        &expected_h);
    310    EXPECT_EQ(expected_w, info.w)
    311        << "Frame " << frame << " had unexpected width";
    312    EXPECT_EQ(expected_h, info.h)
    313        << "Frame " << frame << " had unexpected height";
    314  }
    315 #endif
    316 }
    317 
    318 TEST_P(ResizeTest, TestExternalResizeWorks4Threads) {
    319  ResizingVideoSource video(640, 480);
    320  video.flag_codec_ = 0;
    321  video.random_input_one_half_only_ = true;
    322  cfg_.g_lag_in_frames = 0;
    323  cfg_.g_forced_max_frame_width = 640;
    324  cfg_.g_forced_max_frame_height = 480;
    325  cfg_.g_threads = 4;
    326  cfg_.kf_max_dist = 40;
    327  cfg_.kf_min_dist = 40;
    328  cfg_.rc_dropframe_thresh = 0;
    329  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
    330 
    331 #if CONFIG_AV1_DECODER
    332  // Check we decoded the same number of frames as we attempted to encode
    333  ASSERT_EQ(frame_info_list_.size(), video.limit());
    334 
    335  for (const auto &info : frame_info_list_) {
    336    const unsigned int frame = static_cast<unsigned>(info.pts);
    337    unsigned int expected_w;
    338    unsigned int expected_h;
    339    ScaleForFrameNumber(frame, 640, 480, video.flag_codec_, false,
    340                        video.random_input_one_half_only_, &expected_w,
    341                        &expected_h);
    342    EXPECT_EQ(expected_w, info.w)
    343        << "Frame " << frame << " had unexpected width";
    344    EXPECT_EQ(expected_h, info.h)
    345        << "Frame " << frame << " had unexpected height";
    346  }
    347 #endif
    348 }
    349 
    350 #if !CONFIG_REALTIME_ONLY
    351 const unsigned int kStepDownFrame = 3;
    352 const unsigned int kStepUpFrame = 6;
    353 
    354 class ResizeInternalTestLarge : public ResizeTest {
    355 protected:
    356 #if WRITE_COMPRESSED_STREAM
    357  ResizeInternalTestLarge()
    358      : ResizeTest(), frame0_psnr_(0.0), outfile_(nullptr), out_frames_(0) {}
    359 #else
    360  ResizeInternalTestLarge() : ResizeTest(), frame0_psnr_(0.0) {}
    361 #endif
    362 
    363  ~ResizeInternalTestLarge() override = default;
    364 
    365  void BeginPassHook(unsigned int /*pass*/) override {
    366 #if WRITE_COMPRESSED_STREAM
    367    outfile_ = fopen("av10-2-05-resize.ivf", "wb");
    368 #endif
    369  }
    370 
    371  void EndPassHook() override {
    372 #if WRITE_COMPRESSED_STREAM
    373    if (outfile_) {
    374      if (!fseek(outfile_, 0, SEEK_SET))
    375        write_ivf_file_header(&cfg_, out_frames_, outfile_);
    376      fclose(outfile_);
    377      outfile_ = nullptr;
    378    }
    379 #endif
    380  }
    381 
    382  void PreEncodeFrameHook(libaom_test::VideoSource *video,
    383                          libaom_test::Encoder *encoder) override {
    384    if (change_config_) {
    385      int new_q = 60;
    386      if (video->frame() == 0) {
    387        struct aom_scaling_mode mode = { AOME_ONETWO, AOME_ONETWO };
    388        encoder->Control(AOME_SET_SCALEMODE, &mode);
    389      } else if (video->frame() == 1) {
    390        struct aom_scaling_mode mode = { AOME_NORMAL, AOME_NORMAL };
    391        encoder->Control(AOME_SET_SCALEMODE, &mode);
    392        cfg_.rc_min_quantizer = cfg_.rc_max_quantizer = new_q;
    393        encoder->Config(&cfg_);
    394      }
    395    } else {
    396      if (video->frame() >= kStepDownFrame && video->frame() < kStepUpFrame) {
    397        struct aom_scaling_mode mode = { AOME_FOURFIVE, AOME_THREEFIVE };
    398        encoder->Control(AOME_SET_SCALEMODE, &mode);
    399      }
    400      if (video->frame() >= kStepUpFrame) {
    401        struct aom_scaling_mode mode = { AOME_NORMAL, AOME_NORMAL };
    402        encoder->Control(AOME_SET_SCALEMODE, &mode);
    403      }
    404    }
    405  }
    406 
    407  void PSNRPktHook(const aom_codec_cx_pkt_t *pkt) override {
    408    if (frame0_psnr_ == 0.) frame0_psnr_ = pkt->data.psnr.psnr[0];
    409    EXPECT_NEAR(pkt->data.psnr.psnr[0], frame0_psnr_, 4.1);
    410  }
    411 
    412 #if WRITE_COMPRESSED_STREAM
    413  void FramePktHook(const aom_codec_cx_pkt_t *pkt) override {
    414    ++out_frames_;
    415 
    416    // Write initial file header if first frame.
    417    if (pkt->data.frame.pts == 0) write_ivf_file_header(&cfg_, 0, outfile_);
    418 
    419    // Write frame header and data.
    420    write_ivf_frame_header(pkt, outfile_);
    421    (void)fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile_);
    422  }
    423 #endif
    424 
    425  double frame0_psnr_;
    426  bool change_config_;
    427 #if WRITE_COMPRESSED_STREAM
    428  FILE *outfile_;
    429  unsigned int out_frames_;
    430 #endif
    431 };
    432 
    433 TEST_P(ResizeInternalTestLarge, TestInternalResizeWorks) {
    434  ::libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
    435                                       30, 1, 0, 10);
    436  init_flags_ = AOM_CODEC_USE_PSNR;
    437  change_config_ = false;
    438 
    439  // q picked such that initial keyframe on this clip is ~30dB PSNR
    440  cfg_.rc_min_quantizer = cfg_.rc_max_quantizer = 48;
    441 
    442  // If the number of frames being encoded is smaller than g_lag_in_frames
    443  // the encoded frame is unavailable using the current API. Comparing
    444  // frames to detect mismatch would then not be possible. Set
    445  // g_lag_in_frames = 0 to get around this.
    446  cfg_.g_lag_in_frames = 0;
    447  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
    448 
    449  for (const auto &info : frame_info_list_) {
    450    const aom_codec_pts_t pts = info.pts;
    451    if (pts >= kStepDownFrame && pts < kStepUpFrame) {
    452      ASSERT_EQ(282U, info.w) << "Frame " << pts << " had unexpected width";
    453      ASSERT_EQ(173U, info.h) << "Frame " << pts << " had unexpected height";
    454    } else {
    455      EXPECT_EQ(352U, info.w) << "Frame " << pts << " had unexpected width";
    456      EXPECT_EQ(288U, info.h) << "Frame " << pts << " had unexpected height";
    457    }
    458  }
    459 }
    460 
    461 TEST_P(ResizeInternalTestLarge, TestInternalResizeChangeConfig) {
    462  ::libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
    463                                       30, 1, 0, 10);
    464  cfg_.g_w = 352;
    465  cfg_.g_h = 288;
    466  change_config_ = true;
    467  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
    468 }
    469 
    470 AV1_INSTANTIATE_TEST_SUITE(ResizeInternalTestLarge,
    471                           ::testing::Values(::libaom_test::kOnePassGood));
    472 #endif
    473 
    474 // Parameters: test mode, speed, threads
    475 class ResizeRealtimeTest
    476    : public ::libaom_test::CodecTestWith3Params<libaom_test::TestMode, int,
    477                                                 int>,
    478      public ::libaom_test::EncoderTest {
    479 protected:
    480  ResizeRealtimeTest()
    481      : EncoderTest(GET_PARAM(0)), num_threads_(GET_PARAM(3)),
    482        set_scale_mode_(false), set_scale_mode2_(false),
    483        set_scale_mode3_(false), is_screen_(false) {}
    484  ~ResizeRealtimeTest() override = default;
    485 
    486  void PreEncodeFrameHook(libaom_test::VideoSource *video,
    487                          libaom_test::Encoder *encoder) override {
    488    if (video->frame() == 0) {
    489      encoder->Control(AV1E_SET_AQ_MODE, 3);
    490      encoder->Control(AV1E_SET_ALLOW_WARPED_MOTION, 0);
    491      encoder->Control(AV1E_SET_ENABLE_GLOBAL_MOTION, 0);
    492      encoder->Control(AV1E_SET_ENABLE_OBMC, 0);
    493      encoder->Control(AOME_SET_CPUUSED, set_cpu_used_);
    494      encoder->Control(AV1E_SET_FRAME_PARALLEL_DECODING, 1);
    495      if (cfg_.g_threads > 0) {
    496        encoder->Control(AV1E_SET_ROW_MT, 1);
    497        encoder->Control(AV1E_SET_TILE_COLUMNS, cfg_.g_threads >> 1);
    498        encoder->Control(AV1E_SET_TILE_ROWS, 0);
    499      }
    500      if (is_screen_)
    501        encoder->Control(AV1E_SET_TUNE_CONTENT, AOM_CONTENT_SCREEN);
    502    }
    503    if (set_scale_mode_) {
    504      struct aom_scaling_mode mode;
    505      if (video->frame() <= 20)
    506        mode = { AOME_ONETWO, AOME_ONETWO };
    507      else if (video->frame() <= 40)
    508        mode = { AOME_ONEFOUR, AOME_ONEFOUR };
    509      else if (video->frame() > 40)
    510        mode = { AOME_NORMAL, AOME_NORMAL };
    511      encoder->Control(AOME_SET_SCALEMODE, &mode);
    512    } else if (set_scale_mode2_) {
    513      struct aom_scaling_mode mode;
    514      if (video->frame() <= 20)
    515        mode = { AOME_ONEFOUR, AOME_ONEFOUR };
    516      else if (video->frame() <= 40)
    517        mode = { AOME_ONETWO, AOME_ONETWO };
    518      else if (video->frame() > 40)
    519        mode = { AOME_THREEFOUR, AOME_THREEFOUR };
    520      encoder->Control(AOME_SET_SCALEMODE, &mode);
    521    } else if (set_scale_mode3_) {
    522      struct aom_scaling_mode mode;
    523      if (video->frame() <= 30)
    524        mode = { AOME_ONETWO, AOME_NORMAL };
    525      else
    526        mode = { AOME_NORMAL, AOME_NORMAL };
    527      encoder->Control(AOME_SET_SCALEMODE, &mode);
    528    }
    529 
    530    if (change_bitrate_ && video->frame() == frame_change_bitrate_) {
    531      change_bitrate_ = false;
    532      cfg_.rc_target_bitrate = 500;
    533      encoder->Config(&cfg_);
    534    }
    535  }
    536 
    537  void SetUp() override {
    538    InitializeConfig(GET_PARAM(1));
    539    set_cpu_used_ = GET_PARAM(2);
    540  }
    541 
    542  void DecompressedFrameHook(const aom_image_t &img,
    543                             aom_codec_pts_t pts) override {
    544    frame_info_list_.push_back(FrameInfo(pts, img.d_w, img.d_h));
    545  }
    546 
    547  void MismatchHook(const aom_image_t *img1, const aom_image_t *img2) override {
    548    double mismatch_psnr = compute_psnr(img1, img2);
    549    mismatch_psnr_ += mismatch_psnr;
    550    ++mismatch_nframes_;
    551  }
    552 
    553  unsigned int GetMismatchFrames() { return mismatch_nframes_; }
    554 
    555  void DefaultConfig() {
    556    cfg_.rc_buf_initial_sz = 500;
    557    cfg_.rc_buf_optimal_sz = 600;
    558    cfg_.rc_buf_sz = 1000;
    559    cfg_.rc_min_quantizer = 2;
    560    cfg_.rc_max_quantizer = 56;
    561    cfg_.rc_undershoot_pct = 50;
    562    cfg_.rc_overshoot_pct = 50;
    563    cfg_.rc_end_usage = AOM_CBR;
    564    cfg_.kf_mode = AOM_KF_AUTO;
    565    cfg_.g_lag_in_frames = 0;
    566    cfg_.kf_min_dist = cfg_.kf_max_dist = 3000;
    567    // Enable dropped frames.
    568    cfg_.rc_dropframe_thresh = 1;
    569    // Disable error_resilience mode.
    570    cfg_.g_error_resilient = 0;
    571    cfg_.g_threads = num_threads_;
    572    // Run at low bitrate.
    573    cfg_.rc_target_bitrate = 200;
    574    // We use max(kInitialWidth, kInitialHeight) because during the test
    575    // the width and height of the frame are swapped
    576    cfg_.g_forced_max_frame_width = cfg_.g_forced_max_frame_height =
    577        AOMMAX(kInitialWidth, kInitialHeight);
    578    if (set_scale_mode_ || set_scale_mode2_ || set_scale_mode3_) {
    579      cfg_.rc_dropframe_thresh = 0;
    580      cfg_.g_forced_max_frame_width = 1280;
    581      cfg_.g_forced_max_frame_height = 1280;
    582    }
    583  }
    584 
    585  std::vector<FrameInfo> frame_info_list_;
    586  int set_cpu_used_;
    587  int num_threads_;
    588  bool change_bitrate_;
    589  unsigned int frame_change_bitrate_;
    590  double mismatch_psnr_;
    591  int mismatch_nframes_;
    592  bool set_scale_mode_;
    593  bool set_scale_mode2_;
    594  bool set_scale_mode3_;
    595  bool is_screen_;
    596 };
    597 
    598 // Check the AOME_SET_SCALEMODE control by downsizing to
    599 // 1/2, then 1/4, and then back up to originsal.
    600 TEST_P(ResizeRealtimeTest, TestInternalResizeSetScaleMode1) {
    601  ::libaom_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60);
    602  cfg_.g_w = 1280;
    603  cfg_.g_h = 720;
    604  set_scale_mode_ = true;
    605  set_scale_mode2_ = false;
    606  set_scale_mode3_ = false;
    607  DefaultConfig();
    608  change_bitrate_ = false;
    609  mismatch_nframes_ = 0;
    610  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
    611 #if CONFIG_AV1_DECODER
    612  // Check we decoded the same number of frames as we attempted to encode
    613  ASSERT_EQ(frame_info_list_.size(), video.limit());
    614  for (const auto &info : frame_info_list_) {
    615    const auto frame = static_cast<unsigned>(info.pts);
    616    unsigned int expected_w = 1280 >> 1;
    617    unsigned int expected_h = 720 >> 1;
    618    if (frame > 40) {
    619      expected_w = 1280;
    620      expected_h = 720;
    621    } else if (frame > 20 && frame <= 40) {
    622      expected_w = 1280 >> 2;
    623      expected_h = 720 >> 2;
    624    }
    625    EXPECT_EQ(expected_w, info.w)
    626        << "Frame " << frame << " had unexpected width";
    627    EXPECT_EQ(expected_h, info.h)
    628        << "Frame " << frame << " had unexpected height";
    629    EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
    630  }
    631 #else
    632  printf("Warning: AV1 decoder unavailable, unable to check resize count!\n");
    633 #endif
    634 }
    635 
    636 // Check the AOME_SET_SCALEMODE control by downsizing to
    637 // 1/2, then 1/4, and then back up to originsal.
    638 TEST_P(ResizeRealtimeTest, TestInternalResizeSetScaleMode1QVGA) {
    639  ::libaom_test::I420VideoSource video("desktop1.320_180.yuv", 320, 180, 30, 1,
    640                                       0, 80);
    641  cfg_.g_w = 320;
    642  cfg_.g_h = 180;
    643  set_scale_mode_ = true;
    644  set_scale_mode2_ = false;
    645  set_scale_mode3_ = false;
    646  DefaultConfig();
    647  change_bitrate_ = false;
    648  mismatch_nframes_ = 0;
    649  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
    650 #if CONFIG_AV1_DECODER
    651  // Check we decoded the same number of frames as we attempted to encode
    652  ASSERT_EQ(frame_info_list_.size(), video.limit());
    653  for (const auto &info : frame_info_list_) {
    654    const auto frame = static_cast<unsigned>(info.pts);
    655    unsigned int expected_w = 320 >> 1;
    656    unsigned int expected_h = 180 >> 1;
    657    if (frame > 40) {
    658      expected_w = 320;
    659      expected_h = 180;
    660    } else if (frame > 20 && frame <= 40) {
    661      expected_w = 320 >> 2;
    662      expected_h = 180 >> 2;
    663    }
    664    EXPECT_EQ(expected_w, info.w)
    665        << "Frame " << frame << " had unexpected width";
    666    EXPECT_EQ(expected_h, info.h)
    667        << "Frame " << frame << " had unexpected height";
    668    EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
    669  }
    670 #else
    671  printf("Warning: AV1 decoder unavailable, unable to check resize count!\n");
    672 #endif
    673 }
    674 
    675 // Check the AOME_SET_SCALEMODE control by downsizing to
    676 // 1/4, then 1/2, and then up to 3/4.
    677 TEST_P(ResizeRealtimeTest, TestInternalResizeSetScaleMode2) {
    678  ::libaom_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60);
    679  cfg_.g_w = 1280;
    680  cfg_.g_h = 720;
    681  set_scale_mode_ = false;
    682  set_scale_mode2_ = true;
    683  set_scale_mode3_ = false;
    684  DefaultConfig();
    685  change_bitrate_ = false;
    686  mismatch_nframes_ = 0;
    687  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
    688 #if CONFIG_AV1_DECODER
    689  // Check we decoded the same number of frames as we attempted to encode
    690  ASSERT_EQ(frame_info_list_.size(), video.limit());
    691  for (const auto &info : frame_info_list_) {
    692    const auto frame = static_cast<unsigned>(info.pts);
    693    unsigned int expected_w = 1280 >> 2;
    694    unsigned int expected_h = 720 >> 2;
    695    if (frame > 40) {
    696      expected_w = (3 * 1280) >> 2;
    697      expected_h = (3 * 720) >> 2;
    698    } else if (frame > 20 && frame <= 40) {
    699      expected_w = 1280 >> 1;
    700      expected_h = 720 >> 1;
    701    }
    702    EXPECT_EQ(expected_w, info.w)
    703        << "Frame " << frame << " had unexpected width";
    704    EXPECT_EQ(expected_h, info.h)
    705        << "Frame " << frame << " had unexpected height";
    706    EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
    707  }
    708 #else
    709  printf("Warning: AV1 decoder unavailable, unable to check resize count!\n");
    710 #endif
    711 }
    712 
    713 // Check the AOME_SET_SCALEMODE control by downsizing to
    714 // 1/2 horizontally only and then back up to original.
    715 TEST_P(ResizeRealtimeTest, TestInternalResizeSetScaleMode3) {
    716  ::libaom_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60);
    717  cfg_.g_w = 1280;
    718  cfg_.g_h = 720;
    719  set_scale_mode_ = false;
    720  set_scale_mode2_ = false;
    721  set_scale_mode3_ = true;
    722  DefaultConfig();
    723  change_bitrate_ = false;
    724  mismatch_nframes_ = 0;
    725  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
    726 #if CONFIG_AV1_DECODER
    727  // Check we decoded the same number of frames as we attempted to encode
    728  ASSERT_EQ(frame_info_list_.size(), video.limit());
    729  for (const auto &info : frame_info_list_) {
    730    const auto frame = static_cast<unsigned>(info.pts);
    731    unsigned int expected_w = 640;
    732    unsigned int expected_h = 720;
    733    if (frame > 30) {
    734      expected_w = 1280;
    735      expected_h = 720;
    736    }
    737    EXPECT_EQ(expected_w, info.w)
    738        << "Frame " << frame << " had unexpected width";
    739    EXPECT_EQ(expected_h, info.h)
    740        << "Frame " << frame << " had unexpected height";
    741    EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
    742  }
    743 #else
    744  printf("Warning: AV1 decoder unavailable, unable to check resize count!\n");
    745 #endif
    746 }
    747 
    748 TEST_P(ResizeRealtimeTest, TestExternalResizeWorks) {
    749  ResizingVideoSource video(kInitialWidth, kInitialHeight);
    750  video.flag_codec_ = 1;
    751  change_bitrate_ = false;
    752  set_scale_mode_ = false;
    753  set_scale_mode2_ = false;
    754  set_scale_mode3_ = false;
    755  mismatch_psnr_ = 0.0;
    756  mismatch_nframes_ = 0;
    757  DefaultConfig();
    758  // Test external resizing with start resolution equal to
    759  // 1. kInitialWidth and kInitialHeight
    760  // 2. down-scaled kInitialWidth and kInitialHeight
    761  for (int i = 0; i < 2; i++) {
    762    video.change_start_resln_ = static_cast<bool>(i);
    763 
    764    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
    765 #if CONFIG_AV1_DECODER
    766    // Check we decoded the same number of frames as we attempted to encode
    767    ASSERT_EQ(frame_info_list_.size(), video.limit());
    768    for (const auto &info : frame_info_list_) {
    769      const unsigned int frame = static_cast<unsigned>(info.pts);
    770      unsigned int expected_w;
    771      unsigned int expected_h;
    772      ScaleForFrameNumber(frame, kInitialWidth, kInitialHeight,
    773                          video.flag_codec_, video.change_start_resln_, false,
    774                          &expected_w, &expected_h);
    775      EXPECT_EQ(expected_w, info.w)
    776          << "Frame " << frame << " had unexpected width";
    777      EXPECT_EQ(expected_h, info.h)
    778          << "Frame " << frame << " had unexpected height";
    779      EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
    780    }
    781 #else
    782    printf("Warning: AV1 decoder unavailable, unable to check resize count!\n");
    783 #endif
    784    frame_info_list_.clear();
    785  }
    786 }
    787 
    788 // This tests uses 4 threads with small keyframe spacing, random input,
    789 // and uses 640x480 as initial resolution.
    790 TEST_P(ResizeRealtimeTest, TestExternalResizeWorks4Threads) {
    791  ResizingVideoSource video(640, 480);
    792  video.flag_codec_ = true;
    793  video.random_input_one_half_only_ = true;
    794  change_bitrate_ = false;
    795  set_scale_mode_ = false;
    796  set_scale_mode2_ = false;
    797  set_scale_mode3_ = false;
    798  mismatch_psnr_ = 0.0;
    799  mismatch_nframes_ = 0;
    800  DefaultConfig();
    801  cfg_.g_forced_max_frame_width = 640;
    802  cfg_.g_forced_max_frame_height = 480;
    803  cfg_.g_threads = 4;
    804  cfg_.kf_max_dist = 40;
    805  cfg_.kf_min_dist = 40;
    806  cfg_.rc_dropframe_thresh = 0;
    807  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
    808 
    809  for (const auto &info : frame_info_list_) {
    810    const unsigned int frame = static_cast<unsigned>(info.pts);
    811    unsigned int expected_w;
    812    unsigned int expected_h;
    813    ScaleForFrameNumber(frame, 640, 480, video.flag_codec_, false,
    814                        video.random_input_one_half_only_, &expected_w,
    815                        &expected_h);
    816    EXPECT_EQ(expected_w, info.w)
    817        << "Frame " << frame << " had unexpected width";
    818    EXPECT_EQ(expected_h, info.h)
    819        << "Frame " << frame << " had unexpected height";
    820    EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
    821  }
    822 }
    823 
    824 TEST_P(ResizeRealtimeTest, TestExternalResizeWorksUsePSNR) {
    825  ResizingVideoSource video(kInitialWidth, kInitialHeight);
    826  video.flag_codec_ = 1;
    827  change_bitrate_ = false;
    828  set_scale_mode_ = false;
    829  set_scale_mode2_ = false;
    830  set_scale_mode3_ = false;
    831  mismatch_psnr_ = 0.0;
    832  mismatch_nframes_ = 0;
    833  init_flags_ = AOM_CODEC_USE_PSNR;
    834  cfg_.rc_dropframe_thresh = 30;
    835  DefaultConfig();
    836  // Test external resizing with start resolution equal to
    837  // 1. kInitialWidth and kInitialHeight
    838  // 2. down-scaled kInitialWidth and kInitialHeight
    839  for (int i = 0; i < 2; i++) {
    840    video.change_start_resln_ = static_cast<bool>(i);
    841 
    842    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
    843 #if CONFIG_AV1_DECODER
    844    // Check we decoded the same number of frames as we attempted to encode
    845    ASSERT_EQ(frame_info_list_.size(), video.limit());
    846    for (const auto &info : frame_info_list_) {
    847      const unsigned int frame = static_cast<unsigned>(info.pts);
    848      unsigned int expected_w;
    849      unsigned int expected_h;
    850      ScaleForFrameNumber(frame, kInitialWidth, kInitialHeight,
    851                          video.flag_codec_, video.change_start_resln_, false,
    852                          &expected_w, &expected_h);
    853      EXPECT_EQ(expected_w, info.w)
    854          << "Frame " << frame << " had unexpected width";
    855      EXPECT_EQ(expected_h, info.h)
    856          << "Frame " << frame << " had unexpected height";
    857      EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
    858    }
    859 #else
    860    printf("Warning: AV1 decoder unavailable, unable to check resize count!\n");
    861 #endif
    862    frame_info_list_.clear();
    863  }
    864 }
    865 
    866 // Verify the dynamic resizer behavior for real time, 1 pass CBR mode.
    867 // Run at low bitrate, with resize_allowed = 1, and verify that we get
    868 // one resize down event.
    869 TEST_P(ResizeRealtimeTest, TestInternalResizeDown) {
    870  ::libaom_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
    871                                       0, 400);
    872  cfg_.g_w = 640;
    873  cfg_.g_h = 480;
    874  change_bitrate_ = false;
    875  set_scale_mode_ = false;
    876  set_scale_mode2_ = false;
    877  set_scale_mode3_ = false;
    878  mismatch_psnr_ = 0.0;
    879  mismatch_nframes_ = 0;
    880  DefaultConfig();
    881  // Disable dropped frames.
    882  cfg_.rc_dropframe_thresh = 0;
    883  // Starting bitrate low.
    884  cfg_.rc_target_bitrate = 150;
    885  cfg_.rc_resize_mode = RESIZE_DYNAMIC;
    886  cfg_.g_forced_max_frame_width = 1280;
    887  cfg_.g_forced_max_frame_height = 1280;
    888  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
    889 
    890 #if CONFIG_AV1_DECODER
    891  unsigned int last_w = cfg_.g_w;
    892  unsigned int last_h = cfg_.g_h;
    893  int resize_down_count = 0;
    894  for (const auto &info : frame_info_list_) {
    895    if (info.w != last_w || info.h != last_h) {
    896      // Verify that resize down occurs.
    897      if (info.w < last_w && info.h < last_h) {
    898        resize_down_count++;
    899      }
    900      last_w = info.w;
    901      last_h = info.h;
    902    }
    903  }
    904 
    905  // Verify that we get at lease 1 resize down event in this test.
    906  ASSERT_GE(resize_down_count, 1) << "Resizing should occur.";
    907  EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
    908 #else
    909  printf("Warning: AV1 decoder unavailable, unable to check resize count!\n");
    910 #endif
    911 }
    912 
    913 // Verify the dynamic resizer behavior for real time, 1 pass CBR mode.
    914 // Start at low target bitrate, raise the bitrate in the middle of the clip
    915 // (at frame# = frame_change_bitrate_), scaling-up should occur after bitrate
    916 // is increased.
    917 TEST_P(ResizeRealtimeTest, TestInternalResizeDownUpChangeBitRate) {
    918  ::libaom_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
    919                                       0, 400);
    920  init_flags_ = AOM_CODEC_USE_PSNR;
    921  cfg_.g_w = 640;
    922  cfg_.g_h = 480;
    923  change_bitrate_ = true;
    924  frame_change_bitrate_ = 120;
    925  set_scale_mode_ = false;
    926  set_scale_mode2_ = false;
    927  set_scale_mode3_ = false;
    928  mismatch_psnr_ = 0.0;
    929  mismatch_nframes_ = 0;
    930  DefaultConfig();
    931  // Disable dropped frames.
    932  cfg_.rc_dropframe_thresh = 0;
    933  // Starting bitrate low.
    934  cfg_.rc_target_bitrate = 150;
    935  cfg_.rc_resize_mode = RESIZE_DYNAMIC;
    936  cfg_.g_forced_max_frame_width = 1280;
    937  cfg_.g_forced_max_frame_height = 1280;
    938  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
    939 
    940 #if CONFIG_AV1_DECODER
    941  unsigned int last_w = cfg_.g_w;
    942  unsigned int last_h = cfg_.g_h;
    943  unsigned int frame_number = 0;
    944  int resize_down_count = 0;
    945  int resize_up_count = 0;
    946  for (const auto &info : frame_info_list_) {
    947    if (info.w != last_w || info.h != last_h) {
    948      if (frame_number < frame_change_bitrate_) {
    949        // Verify that resize down occurs, before bitrate is increased.
    950        ASSERT_LT(info.w, last_w);
    951        ASSERT_LT(info.h, last_h);
    952        resize_down_count++;
    953      } else {
    954        // Verify that resize up occurs, after bitrate is increased.
    955        ASSERT_GT(info.w, last_w);
    956        ASSERT_GT(info.h, last_h);
    957        resize_up_count++;
    958      }
    959      last_w = info.w;
    960      last_h = info.h;
    961    }
    962    frame_number++;
    963  }
    964 
    965  // Verify that we get at least 2 resize events in this test.
    966  ASSERT_GE(resize_up_count, 1) << "Resizing up should occur at lease once.";
    967  ASSERT_GE(resize_down_count, 1)
    968      << "Resizing down should occur at lease once.";
    969  EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
    970 #else
    971  printf("Warning: AV1 decoder unavailable, unable to check resize count!\n");
    972 #endif
    973 }
    974 
    975 // Verify the dynamic resizer behavior for real time, 1 pass CBR mode for
    976 // screen content mode. Start at low target bitrate, raise the bitrate in the
    977 // middle of the clip (at frame# = frame_change_bitrate_), scaling-up should
    978 // occur after bitrate is increased.
    979 TEST_P(ResizeRealtimeTest, TestInternalResizeDownUpChangeBitRateScreen) {
    980  ::libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
    981                                       30, 1, 0, 300);
    982  init_flags_ = AOM_CODEC_USE_PSNR;
    983  cfg_.g_w = 352;
    984  cfg_.g_h = 288;
    985  change_bitrate_ = true;
    986  frame_change_bitrate_ = 200;
    987  set_scale_mode_ = false;
    988  set_scale_mode2_ = false;
    989  set_scale_mode3_ = false;
    990  mismatch_psnr_ = 0.0;
    991  mismatch_nframes_ = 0;
    992  is_screen_ = true;
    993  DefaultConfig();
    994  // Disable dropped frames.
    995  cfg_.rc_dropframe_thresh = 0;
    996  // Starting bitrate low.
    997  cfg_.rc_target_bitrate = 30;
    998  cfg_.rc_resize_mode = RESIZE_DYNAMIC;
    999  cfg_.g_forced_max_frame_width = 1280;
   1000  cfg_.g_forced_max_frame_height = 1280;
   1001  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
   1002 
   1003 #if CONFIG_AV1_DECODER
   1004  unsigned int last_w = cfg_.g_w;
   1005  unsigned int last_h = cfg_.g_h;
   1006  unsigned int frame_number = 0;
   1007  int resize_down_count = 0;
   1008  for (const auto &info : frame_info_list_) {
   1009    if (info.w != last_w || info.h != last_h) {
   1010      if (frame_number < frame_change_bitrate_) {
   1011        // Verify that resize down occurs, before bitrate is increased.
   1012        ASSERT_LT(info.w, last_w);
   1013        ASSERT_LT(info.h, last_h);
   1014        resize_down_count++;
   1015      }
   1016      last_w = info.w;
   1017      last_h = info.h;
   1018    }
   1019    frame_number++;
   1020  }
   1021 
   1022  // Verify that we get at least 1 resize event in this test.
   1023  ASSERT_GE(resize_down_count, 1)
   1024      << "Resizing down should occur at lease once.";
   1025  EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
   1026 #else
   1027  printf("Warning: AV1 decoder unavailable, unable to check resize count!\n");
   1028 #endif
   1029 }
   1030 
   1031 class ResizeCspTest : public ResizeTest {
   1032 protected:
   1033 #if WRITE_COMPRESSED_STREAM
   1034  ResizeCspTest()
   1035      : ResizeTest(), frame0_psnr_(0.0), outfile_(nullptr), out_frames_(0) {}
   1036 #else
   1037  ResizeCspTest() : ResizeTest(), frame0_psnr_(0.0) {}
   1038 #endif
   1039 
   1040  ~ResizeCspTest() override = default;
   1041 
   1042  void BeginPassHook(unsigned int /*pass*/) override {
   1043 #if WRITE_COMPRESSED_STREAM
   1044    outfile_ = fopen("av11-2-05-cspchape.ivf", "wb");
   1045 #endif
   1046  }
   1047 
   1048  void EndPassHook() override {
   1049 #if WRITE_COMPRESSED_STREAM
   1050    if (outfile_) {
   1051      if (!fseek(outfile_, 0, SEEK_SET))
   1052        write_ivf_file_header(&cfg_, out_frames_, outfile_);
   1053      fclose(outfile_);
   1054      outfile_ = nullptr;
   1055    }
   1056 #endif
   1057  }
   1058 
   1059  void PSNRPktHook(const aom_codec_cx_pkt_t *pkt) override {
   1060    if (frame0_psnr_ == 0.) frame0_psnr_ = pkt->data.psnr.psnr[0];
   1061    EXPECT_NEAR(pkt->data.psnr.psnr[0], frame0_psnr_, 2.0);
   1062  }
   1063 
   1064 #if WRITE_COMPRESSED_STREAM
   1065  void FramePktHook(const aom_codec_cx_pkt_t *pkt) override {
   1066    ++out_frames_;
   1067 
   1068    // Write initial file header if first frame.
   1069    if (pkt->data.frame.pts == 0) write_ivf_file_header(&cfg_, 0, outfile_);
   1070 
   1071    // Write frame header and data.
   1072    write_ivf_frame_header(pkt, outfile_);
   1073    (void)fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile_);
   1074  }
   1075 #endif
   1076 
   1077  double frame0_psnr_;
   1078 #if WRITE_COMPRESSED_STREAM
   1079  FILE *outfile_;
   1080  unsigned int out_frames_;
   1081 #endif
   1082 };
   1083 
   1084 class ResizingCspVideoSource : public ::libaom_test::DummyVideoSource {
   1085 public:
   1086  explicit ResizingCspVideoSource(aom_img_fmt_t image_format) {
   1087    SetSize(kInitialWidth, kInitialHeight);
   1088    SetImageFormat(image_format);
   1089    limit_ = 30;
   1090  }
   1091 
   1092  ~ResizingCspVideoSource() override = default;
   1093 };
   1094 
   1095 #if (defined(DISABLE_TRELLISQ_SEARCH) && DISABLE_TRELLISQ_SEARCH) || \
   1096    (defined(CONFIG_MAX_DECODE_PROFILE) && CONFIG_MAX_DECODE_PROFILE < 1)
   1097 TEST_P(ResizeCspTest, DISABLED_TestResizeCspWorks) {
   1098 #else
   1099 TEST_P(ResizeCspTest, TestResizeCspWorks) {
   1100 #endif
   1101  const aom_img_fmt_t image_formats[] = { AOM_IMG_FMT_I420, AOM_IMG_FMT_I444 };
   1102  for (const aom_img_fmt_t &img_format : image_formats) {
   1103    ResizingCspVideoSource video(img_format);
   1104    init_flags_ = AOM_CODEC_USE_PSNR;
   1105    cfg_.rc_min_quantizer = cfg_.rc_max_quantizer = 48;
   1106    cfg_.g_lag_in_frames = 0;
   1107    cfg_.g_profile = (img_format == AOM_IMG_FMT_I420) ? 0 : 1;
   1108    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
   1109 
   1110 #if CONFIG_AV1_DECODER
   1111    // Check we decoded the same number of frames as we attempted to encode
   1112    ASSERT_EQ(frame_info_list_.size(), video.limit());
   1113    frame_info_list_.clear();
   1114 #endif
   1115  }
   1116 }
   1117 
   1118 #if !CONFIG_REALTIME_ONLY
   1119 // This class is used to check if there are any fatal
   1120 // failures while encoding with resize-mode > 0
   1121 class ResizeModeTestLarge
   1122    : public ::libaom_test::CodecTestWith5Params<libaom_test::TestMode, int,
   1123                                                 int, int, int>,
   1124      public ::libaom_test::EncoderTest {
   1125 protected:
   1126  ResizeModeTestLarge()
   1127      : EncoderTest(GET_PARAM(0)), encoding_mode_(GET_PARAM(1)),
   1128        resize_mode_(GET_PARAM(2)), resize_denominator_(GET_PARAM(3)),
   1129        resize_kf_denominator_(GET_PARAM(4)), cpu_used_(GET_PARAM(5)) {}
   1130  ~ResizeModeTestLarge() override = default;
   1131 
   1132  void SetUp() override {
   1133    InitializeConfig(encoding_mode_);
   1134    const aom_rational timebase = { 1, 30 };
   1135    cfg_.g_timebase = timebase;
   1136    cfg_.rc_end_usage = AOM_VBR;
   1137    cfg_.g_threads = 1;
   1138    cfg_.g_lag_in_frames = 35;
   1139    cfg_.rc_target_bitrate = 1000;
   1140    cfg_.rc_resize_mode = resize_mode_;
   1141    cfg_.rc_resize_denominator = resize_denominator_;
   1142    cfg_.rc_resize_kf_denominator = resize_kf_denominator_;
   1143    init_flags_ = AOM_CODEC_USE_PSNR;
   1144  }
   1145 
   1146  void PreEncodeFrameHook(::libaom_test::VideoSource *video,
   1147                          ::libaom_test::Encoder *encoder) override {
   1148    if (video->frame() == 0) {
   1149      encoder->Control(AOME_SET_CPUUSED, cpu_used_);
   1150      encoder->Control(AOME_SET_ENABLEAUTOALTREF, 1);
   1151    }
   1152  }
   1153 
   1154  ::libaom_test::TestMode encoding_mode_;
   1155  int resize_mode_;
   1156  int resize_denominator_;
   1157  int resize_kf_denominator_;
   1158  int cpu_used_;
   1159 };
   1160 
   1161 TEST_P(ResizeModeTestLarge, ResizeModeTest) {
   1162  ::libaom_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 30);
   1163  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
   1164 }
   1165 
   1166 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ResizeModeTestLarge);
   1167 AV1_INSTANTIATE_TEST_SUITE(ResizeModeTestLarge,
   1168                           ::testing::Values(::libaom_test::kOnePassGood,
   1169                                             ::libaom_test::kTwoPassGood),
   1170                           ::testing::Values(1, 2), ::testing::Values(8, 12),
   1171                           ::testing::Values(10, 14), ::testing::Values(3, 6));
   1172 #endif  // !CONFIG_REALTIME_ONLY
   1173 
   1174 #if CONFIG_REALTIME_ONLY
   1175 AV1_INSTANTIATE_TEST_SUITE(ResizeTest,
   1176                           ::testing::Values(::libaom_test::kRealTime));
   1177 #else
   1178 AV1_INSTANTIATE_TEST_SUITE(ResizeTest,
   1179                           ::testing::Values(::libaom_test::kRealTime,
   1180                                             ::libaom_test::kOnePassGood));
   1181 #endif
   1182 
   1183 AV1_INSTANTIATE_TEST_SUITE(ResizeRealtimeTest,
   1184                           ::testing::Values(::libaom_test::kRealTime),
   1185                           ::testing::Range(6, 10), ::testing::Values(1, 2, 4));
   1186 AV1_INSTANTIATE_TEST_SUITE(ResizeCspTest,
   1187                           ::testing::Values(::libaom_test::kRealTime));
   1188 
   1189 // A test that reproduces crbug.com/1393384. In realtime usage mode, encode
   1190 // frames of sizes 202x202, 1x202, and 202x202. ASan should report no memory
   1191 // errors.
   1192 TEST(ResizeSimpleTest, TemporarySmallerFrameSize) {
   1193  constexpr int kWidth = 202;
   1194  constexpr int kHeight = 202;
   1195  // Dummy buffer of zero samples.
   1196  constexpr size_t kBufferSize =
   1197      kWidth * kHeight + 2 * (kWidth + 1) / 2 * (kHeight + 1) / 2;
   1198  std::vector<unsigned char> buffer(kBufferSize);
   1199 
   1200  aom_image_t img;
   1201  EXPECT_EQ(&img, aom_img_wrap(&img, AOM_IMG_FMT_I420, kWidth, kHeight, 1,
   1202                               buffer.data()));
   1203  aom_image_t img2;
   1204  EXPECT_EQ(&img2, aom_img_wrap(&img2, AOM_IMG_FMT_I420, 1, kHeight, 1,
   1205                                buffer.data()));
   1206 
   1207  aom_codec_iface_t *iface = aom_codec_av1_cx();
   1208  aom_codec_enc_cfg_t cfg;
   1209  EXPECT_EQ(AOM_CODEC_OK,
   1210            aom_codec_enc_config_default(iface, &cfg, AOM_USAGE_REALTIME));
   1211  cfg.g_w = kWidth;
   1212  cfg.g_h = kHeight;
   1213  aom_codec_ctx_t enc;
   1214  EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_init(&enc, iface, &cfg, 0));
   1215  EXPECT_EQ(AOM_CODEC_OK, aom_codec_control(&enc, AOME_SET_CPUUSED, 5));
   1216 
   1217  EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, &img, 0, 1, 0));
   1218 
   1219  cfg.g_w = 1;
   1220  cfg.g_h = kHeight;
   1221  EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_config_set(&enc, &cfg));
   1222  EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, &img2, 1, 1, 0));
   1223 
   1224  cfg.g_w = kWidth;
   1225  cfg.g_h = kHeight;
   1226  EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_config_set(&enc, &cfg));
   1227  EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, &img, 2, 1, 0));
   1228 
   1229  EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, nullptr, 0, 0, 0));
   1230  EXPECT_EQ(AOM_CODEC_OK, aom_codec_destroy(&enc));
   1231 }
   1232 
   1233 // A test that reproduces crbug.com/1410766. In realtime usage mode
   1234 // for SVC with temporal layers, encode frames of sizes 600x600,
   1235 // 600x600, and 100x480. ASan should report no memory errors.
   1236 TEST(ResizeSimpleTest, SmallerFrameSizeSVC) {
   1237  constexpr int kWidth = 600;
   1238  constexpr int kHeight = 600;
   1239  // Dummy buffer of zero samples.
   1240  constexpr size_t kBufferSize =
   1241      kWidth * kHeight + 2 * (kWidth + 1) / 2 * (kHeight + 1) / 2;
   1242  std::vector<unsigned char> buffer(kBufferSize);
   1243 
   1244  aom_image_t img;
   1245  EXPECT_EQ(&img, aom_img_wrap(&img, AOM_IMG_FMT_I420, kWidth, kHeight, 1,
   1246                               buffer.data()));
   1247  aom_image_t img2;
   1248  EXPECT_EQ(&img2,
   1249            aom_img_wrap(&img2, AOM_IMG_FMT_I420, 100, 480, 1, buffer.data()));
   1250 
   1251  aom_codec_iface_t *iface = aom_codec_av1_cx();
   1252  aom_codec_enc_cfg_t cfg;
   1253  EXPECT_EQ(AOM_CODEC_OK,
   1254            aom_codec_enc_config_default(iface, &cfg, AOM_USAGE_REALTIME));
   1255  cfg.g_w = kWidth;
   1256  cfg.g_h = kHeight;
   1257  aom_codec_ctx_t enc;
   1258  EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_init(&enc, iface, &cfg, 0));
   1259  EXPECT_EQ(AOM_CODEC_OK, aom_codec_control(&enc, AOME_SET_CPUUSED, 5));
   1260 
   1261  aom_svc_params_t svc_params = {};
   1262  aom_svc_layer_id_t layer_id;
   1263  svc_params.number_spatial_layers = 1;
   1264  svc_params.framerate_factor[0] = 2;
   1265  svc_params.framerate_factor[1] = 1;
   1266  svc_params.number_temporal_layers = 2;
   1267  // Bitrate allocation L0: 60% L1: 40%
   1268  svc_params.layer_target_bitrate[0] = 60 * cfg.rc_target_bitrate / 100;
   1269  svc_params.layer_target_bitrate[1] = cfg.rc_target_bitrate;
   1270  EXPECT_EQ(AOM_CODEC_OK,
   1271            aom_codec_control(&enc, AV1E_SET_SVC_PARAMS, &svc_params));
   1272 
   1273  layer_id.spatial_layer_id = 0;
   1274  layer_id.temporal_layer_id = 0;
   1275  EXPECT_EQ(AOM_CODEC_OK,
   1276            aom_codec_control(&enc, AV1E_SET_SVC_LAYER_ID, &layer_id));
   1277  EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, &img, 0, 1, 0));
   1278 
   1279  cfg.g_w = kWidth;
   1280  cfg.g_h = kHeight;
   1281  layer_id.temporal_layer_id = 1;
   1282  EXPECT_EQ(AOM_CODEC_OK,
   1283            aom_codec_control(&enc, AV1E_SET_SVC_LAYER_ID, &layer_id));
   1284  EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_config_set(&enc, &cfg));
   1285  EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, &img, 1, 1, 0));
   1286 
   1287  cfg.g_w = 100;
   1288  cfg.g_h = 480;
   1289  layer_id.temporal_layer_id = 0;
   1290  EXPECT_EQ(AOM_CODEC_OK,
   1291            aom_codec_control(&enc, AV1E_SET_SVC_LAYER_ID, &layer_id));
   1292  EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_config_set(&enc, &cfg));
   1293  EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, &img2, 2, 1, 0));
   1294 
   1295  EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, nullptr, 0, 0, 0));
   1296  EXPECT_EQ(AOM_CODEC_OK, aom_codec_destroy(&enc));
   1297 }
   1298 
   1299 const int kUsages[] =
   1300 #if CONFIG_REALTIME_ONLY
   1301    { AOM_USAGE_REALTIME };
   1302 #else
   1303    { AOM_USAGE_GOOD_QUALITY, AOM_USAGE_REALTIME, AOM_USAGE_ALL_INTRA };
   1304 #endif
   1305 
   1306 const int kNumThreads[] = { 2, 4, 8 };
   1307 
   1308 class FrameSizeChangeTest
   1309    : public ::libaom_test::CodecTestWith3Params<int, int, int> {
   1310 protected:
   1311  FrameSizeChangeTest() {}
   1312  ~FrameSizeChangeTest() override = default;
   1313 
   1314  void DoTest(int change_thread) {
   1315    usage_ = GET_PARAM(1);
   1316    cpu_used_ = GET_PARAM(2);
   1317    threads_ = GET_PARAM(3);
   1318    constexpr int kWidth = 512;
   1319    constexpr int kHeight = 512;
   1320    constexpr int kFirstWidth = 256;
   1321    constexpr int kFirstHeight = 256;
   1322    // Buffer of zero samples.
   1323    constexpr size_t kBufferSize = 3 * kWidth * kHeight;
   1324    std::vector<unsigned char> buffer(kBufferSize,
   1325                                      static_cast<unsigned char>(0));
   1326 
   1327    aom_image_t img1;
   1328    EXPECT_EQ(&img1, aom_img_wrap(&img1, AOM_IMG_FMT_I420, kFirstWidth,
   1329                                  kFirstHeight, 1, buffer.data()));
   1330 
   1331    aom_image_t img2;
   1332    EXPECT_EQ(&img2, aom_img_wrap(&img2, AOM_IMG_FMT_I420, kWidth, kHeight, 1,
   1333                                  buffer.data()));
   1334 
   1335    aom_codec_iface_t *iface = aom_codec_av1_cx();
   1336    aom_codec_enc_cfg_t cfg;
   1337    EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_config_default(iface, &cfg, usage_));
   1338    cfg.g_threads = threads_;
   1339    cfg.g_lag_in_frames = usage_ == AOM_USAGE_ALL_INTRA ? 0 : 1;
   1340    cfg.g_w = kFirstWidth;
   1341    cfg.g_h = kFirstHeight;
   1342    cfg.g_forced_max_frame_width = kWidth;
   1343    cfg.g_forced_max_frame_height = kHeight;
   1344    aom_codec_ctx_t enc;
   1345    EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_init(&enc, iface, &cfg, 0));
   1346    EXPECT_EQ(AOM_CODEC_OK,
   1347              aom_codec_control(&enc, AOME_SET_CPUUSED, cpu_used_));
   1348 
   1349    EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, &img1, 0, 1, 0));
   1350 
   1351    if (change_thread == 1) {
   1352      cfg.g_threads = AOMMAX(1, threads_ / 2);
   1353    } else if (change_thread == 2) {
   1354      cfg.g_threads = threads_ * 2;
   1355    }
   1356    cfg.g_w = kWidth;
   1357    cfg.g_h = kHeight;
   1358    EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_config_set(&enc, &cfg));
   1359    EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, &img2, 1, 1, 0));
   1360 
   1361    EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, nullptr, 0, 0, 0));
   1362    EXPECT_EQ(AOM_CODEC_OK, aom_codec_destroy(&enc));
   1363  }
   1364 
   1365  int cpu_used_;
   1366  int threads_;
   1367  int usage_;
   1368 };
   1369 
   1370 TEST_P(FrameSizeChangeTest, FixedThreads) { DoTest(0); }
   1371 TEST_P(FrameSizeChangeTest, DecreasingThreads) { DoTest(1); }
   1372 TEST_P(FrameSizeChangeTest, IncreasingThreads) { DoTest(2); }
   1373 
   1374 AV1_INSTANTIATE_TEST_SUITE(FrameSizeChangeTest, ::testing::ValuesIn(kUsages),
   1375                           ::testing::Range(6, 7),
   1376                           ::testing::ValuesIn(kNumThreads));
   1377 
   1378 }  // namespace