tor-browser

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

encode_small_width_height_test.cc (9108B)


      1 /*
      2 * Copyright (c) 2020, 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 // Tests for https://crbug.com/aomedia/2777.
     13 //
     14 // Encode images with a small width (<= two AV1 superblocks) or a small height
     15 // (<= one AV1 superblock) with multiple threads. aom_codec_encode() should
     16 // not crash.
     17 
     18 #include <memory>
     19 
     20 #include "aom/aomcx.h"
     21 #include "aom/aom_encoder.h"
     22 #include "config/aom_config.h"
     23 #include "gtest/gtest.h"
     24 
     25 namespace {
     26 
     27 // Dummy buffer of zero samples.
     28 constexpr unsigned char kBuffer[2 * (256 * 512 + 2 * 128 * 256)] = { 0 };
     29 #if CONFIG_REALTIME_ONLY
     30 const int kUsage = 1;
     31 #else
     32 const int kUsage = 0;
     33 #endif
     34 
     35 void EncodeSmallWidthMultiThreaded(aom_img_fmt fmt, aom_codec_flags_t flag) {
     36  // The image has only one tile and the tile is two AV1 superblocks wide.
     37  // For speed >= 1, superblock size is 64x64 (see av1_select_sb_size()).
     38  constexpr int kWidth = 128;
     39  constexpr int kHeight = 512;
     40 
     41  aom_image_t img;
     42  EXPECT_EQ(&img, aom_img_wrap(&img, fmt, kWidth, kHeight, 1,
     43                               const_cast<unsigned char *>(kBuffer)));
     44 
     45  aom_codec_iface_t *iface = aom_codec_av1_cx();
     46  aom_codec_enc_cfg_t cfg;
     47  EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_config_default(iface, &cfg, kUsage));
     48  cfg.g_threads = 2;
     49  cfg.g_w = kWidth;
     50  cfg.g_h = kHeight;
     51  aom_codec_ctx_t enc;
     52  EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_init(&enc, iface, &cfg, flag));
     53  EXPECT_EQ(AOM_CODEC_OK, aom_codec_control(&enc, AOME_SET_CPUUSED, 5));
     54  EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, &img, 0, 1, 0));
     55  EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, nullptr, 0, 0, 0));
     56  EXPECT_EQ(AOM_CODEC_OK, aom_codec_destroy(&enc));
     57 }
     58 
     59 TEST(EncodeSmallWidthHeight, SmallWidthMultiThreaded) {
     60  EncodeSmallWidthMultiThreaded(AOM_IMG_FMT_I420, 0);
     61 }
     62 
     63 #if CONFIG_AV1_HIGHBITDEPTH
     64 TEST(HighbdEncodeSmallWidthHeight, SmallWidthMultiThreaded) {
     65  EncodeSmallWidthMultiThreaded(AOM_IMG_FMT_I42016, AOM_CODEC_USE_HIGHBITDEPTH);
     66 }
     67 #endif  // CONFIG_AV1_HIGHBITDEPTH
     68 
     69 #if !CONFIG_REALTIME_ONLY
     70 void EncodeSmallWidthMultiThreadedSpeed0(aom_img_fmt fmt,
     71                                         aom_codec_flags_t flag) {
     72  // The image has only one tile and the tile is two AV1 superblocks wide.
     73  // For speed 0, superblock size is 128x128 (see av1_select_sb_size()).
     74  constexpr int kWidth = 256;
     75  constexpr int kHeight = 512;
     76 
     77  aom_image_t img;
     78  EXPECT_EQ(&img, aom_img_wrap(&img, fmt, kWidth, kHeight, 1,
     79                               const_cast<unsigned char *>(kBuffer)));
     80 
     81  aom_codec_iface_t *iface = aom_codec_av1_cx();
     82  aom_codec_enc_cfg_t cfg;
     83  EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_config_default(iface, &cfg, 0));
     84  cfg.g_threads = 2;
     85  cfg.g_w = kWidth;
     86  cfg.g_h = kHeight;
     87  aom_codec_ctx_t enc;
     88  EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_init(&enc, iface, &cfg, flag));
     89  EXPECT_EQ(AOM_CODEC_OK, aom_codec_control(&enc, AOME_SET_CPUUSED, 0));
     90  EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, &img, 0, 1, 0));
     91  EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, nullptr, 0, 0, 0));
     92  EXPECT_EQ(AOM_CODEC_OK, aom_codec_destroy(&enc));
     93 }
     94 
     95 TEST(EncodeSmallWidthHeight, SmallWidthMultiThreadedSpeed0) {
     96  EncodeSmallWidthMultiThreadedSpeed0(AOM_IMG_FMT_I420, 0);
     97 }
     98 
     99 #if CONFIG_AV1_HIGHBITDEPTH
    100 TEST(HighbdEncodeSmallWidthHeight, SmallWidthMultiThreadedSpeed0) {
    101  EncodeSmallWidthMultiThreadedSpeed0(AOM_IMG_FMT_I42016,
    102                                      AOM_CODEC_USE_HIGHBITDEPTH);
    103 }
    104 #endif  // CONFIG_AV1_HIGHBITDEPTH
    105 
    106 #endif
    107 
    108 void EncodeSmallHeightMultiThreaded(aom_img_fmt fmt, aom_codec_flags_t flag) {
    109  // The image has only one tile and the tile is one AV1 superblock tall.
    110  // For speed >= 1, superblock size is 64x64 (see av1_select_sb_size()).
    111  constexpr int kWidth = 512;
    112  constexpr int kHeight = 64;
    113 
    114  aom_image_t img;
    115  EXPECT_EQ(&img, aom_img_wrap(&img, fmt, kWidth, kHeight, 1,
    116                               const_cast<unsigned char *>(kBuffer)));
    117 
    118  aom_codec_iface_t *iface = aom_codec_av1_cx();
    119  aom_codec_enc_cfg_t cfg;
    120  EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_config_default(iface, &cfg, kUsage));
    121  cfg.g_threads = 2;
    122  cfg.g_w = kWidth;
    123  cfg.g_h = kHeight;
    124  aom_codec_ctx_t enc;
    125  EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_init(&enc, iface, &cfg, flag));
    126  EXPECT_EQ(AOM_CODEC_OK, aom_codec_control(&enc, AOME_SET_CPUUSED, 5));
    127  EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, &img, 0, 1, 0));
    128  EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, nullptr, 0, 0, 0));
    129  EXPECT_EQ(AOM_CODEC_OK, aom_codec_destroy(&enc));
    130 }
    131 
    132 TEST(EncodeSmallWidthHeight, SmallHeightMultiThreaded) {
    133  EncodeSmallHeightMultiThreaded(AOM_IMG_FMT_I420, 0);
    134 }
    135 
    136 #if CONFIG_AV1_HIGHBITDEPTH
    137 TEST(HighbdEncodeSmallWidthHeight, SmallHeightMultiThreaded) {
    138  EncodeSmallHeightMultiThreaded(AOM_IMG_FMT_I42016,
    139                                 AOM_CODEC_USE_HIGHBITDEPTH);
    140 }
    141 #endif  // CONFIG_AV1_HIGHBITDEPTH
    142 
    143 #if !CONFIG_REALTIME_ONLY
    144 void EncodeSmallHeightMultiThreadedSpeed0(aom_img_fmt fmt,
    145                                          aom_codec_flags_t flag) {
    146  // The image has only one tile and the tile is one AV1 superblock tall.
    147  // For speed 0, superblock size is 128x128 (see av1_select_sb_size()).
    148  constexpr int kWidth = 512;
    149  constexpr int kHeight = 128;
    150 
    151  aom_image_t img;
    152  EXPECT_EQ(&img, aom_img_wrap(&img, fmt, kWidth, kHeight, 1,
    153                               const_cast<unsigned char *>(kBuffer)));
    154 
    155  aom_codec_iface_t *iface = aom_codec_av1_cx();
    156  aom_codec_enc_cfg_t cfg;
    157  EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_config_default(iface, &cfg, 0));
    158  cfg.g_threads = 2;
    159  cfg.g_w = kWidth;
    160  cfg.g_h = kHeight;
    161  aom_codec_ctx_t enc;
    162  EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_init(&enc, iface, &cfg, flag));
    163  EXPECT_EQ(AOM_CODEC_OK, aom_codec_control(&enc, AOME_SET_CPUUSED, 0));
    164  EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, &img, 0, 1, 0));
    165  EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, nullptr, 0, 0, 0));
    166  EXPECT_EQ(AOM_CODEC_OK, aom_codec_destroy(&enc));
    167 }
    168 
    169 TEST(EncodeSmallWidthHeight, SmallHeightMultiThreadedSpeed0) {
    170  EncodeSmallHeightMultiThreadedSpeed0(AOM_IMG_FMT_I420, 0);
    171 }
    172 
    173 #if CONFIG_AV1_HIGHBITDEPTH
    174 TEST(HighbdEncodeSmallWidthHeight, SmallHeightMultiThreadedSpeed0) {
    175  EncodeSmallHeightMultiThreadedSpeed0(AOM_IMG_FMT_I42016,
    176                                       AOM_CODEC_USE_HIGHBITDEPTH);
    177 }
    178 #endif  // CONFIG_AV1_HIGHBITDEPTH
    179 #endif
    180 
    181 // A reproducer test for aomedia:3113. The test should complete without any
    182 // memory errors.
    183 void Encode1x1(aom_img_fmt fmt, int bitdepth, aom_codec_flags_t flags) {
    184  constexpr int kWidth = 1;
    185  constexpr int kHeight = 1;
    186 
    187  // This test cannot use aom_img_alloc() or aom_img_wrap() because they call
    188  // align_image_dimension() to align img.w and img.h to the next even number
    189  // (2). In this test it is important to set img.w and img.h to 1. Therefore we
    190  // set up img manually.
    191  aom_image_t img;
    192  memset(&img, 0, sizeof(img));
    193  img.fmt = fmt;
    194  img.bit_depth = bitdepth;
    195  img.w = kWidth;
    196  img.h = kHeight;
    197  img.d_w = kWidth;
    198  img.d_h = kHeight;
    199  img.x_chroma_shift = 1;
    200  img.y_chroma_shift = 1;
    201  img.bps = 12;
    202  const int y_stride = kWidth;
    203  const int uv_stride = (kWidth + 1) >> 1;
    204  int y_height = kHeight;
    205  int uv_height = (kHeight + 1) >> 1;
    206  if (bitdepth > 8) {
    207    y_height <<= 1;
    208    uv_height <<= 1;
    209  }
    210  img.stride[AOM_PLANE_Y] = y_stride;
    211  img.stride[AOM_PLANE_U] = img.stride[AOM_PLANE_V] = uv_stride;
    212  std::unique_ptr<unsigned char[]> y_plane(
    213      new unsigned char[y_height * y_stride]());
    214  ASSERT_NE(y_plane, nullptr);
    215  std::unique_ptr<unsigned char[]> u_plane(
    216      new unsigned char[uv_height * uv_stride]());
    217  ASSERT_NE(u_plane, nullptr);
    218  std::unique_ptr<unsigned char[]> v_plane(
    219      new unsigned char[uv_height * uv_stride]());
    220  ASSERT_NE(v_plane, nullptr);
    221  img.planes[AOM_PLANE_Y] = y_plane.get();
    222  img.planes[AOM_PLANE_U] = u_plane.get();
    223  img.planes[AOM_PLANE_V] = v_plane.get();
    224 
    225  aom_codec_iface_t *iface = aom_codec_av1_cx();
    226  aom_codec_enc_cfg_t cfg;
    227  EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_config_default(iface, &cfg, kUsage));
    228  cfg.g_w = kWidth;
    229  cfg.g_h = kHeight;
    230  aom_codec_ctx_t enc;
    231  EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_init(&enc, iface, &cfg, flags));
    232  EXPECT_EQ(AOM_CODEC_OK, aom_codec_control(&enc, AOME_SET_CPUUSED, 5));
    233  EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, &img, 0, 1, 0));
    234  EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, nullptr, 0, 0, 0));
    235  EXPECT_EQ(AOM_CODEC_OK, aom_codec_destroy(&enc));
    236 }
    237 
    238 TEST(EncodeSmallWidthHeight, 1x1) { Encode1x1(AOM_IMG_FMT_I420, 8, 0); }
    239 
    240 #if CONFIG_AV1_HIGHBITDEPTH
    241 TEST(HighbdEncodeSmallWidthHeight, 1x1) {
    242  Encode1x1(AOM_IMG_FMT_I42016, 12, AOM_CODEC_USE_HIGHBITDEPTH);
    243 }
    244 #endif  // CONFIG_AV1_HIGHBITDEPTH
    245 
    246 }  // namespace