tor-browser

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

avif_progressive_test.cc (14300B)


      1 /*
      2 * Copyright (c) 2023, 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 <cstddef>
     13 #include <vector>
     14 
     15 #include "aom/aomcx.h"
     16 #include "aom/aom_codec.h"
     17 #include "aom/aom_encoder.h"
     18 #include "aom/aom_image.h"
     19 #include "gtest/gtest.h"
     20 
     21 namespace {
     22 
     23 // This test emulates how libavif calls libaom functions to encode a
     24 // progressive AVIF image in libavif's ProgressiveTest.QualityChange test.
     25 TEST(AVIFProgressiveTest, QualityChange) {
     26  constexpr int kWidth = 256;
     27  constexpr int kHeight = 256;
     28  // A buffer of neutral gray samples.
     29  constexpr size_t kBufferSize = 3 * kWidth * kHeight;
     30  std::vector<unsigned char> buffer(kBufferSize,
     31                                    static_cast<unsigned char>(128));
     32 
     33  aom_image_t img;
     34  EXPECT_EQ(&img, aom_img_wrap(&img, AOM_IMG_FMT_I444, kWidth, kHeight, 1,
     35                               buffer.data()));
     36  img.cp = AOM_CICP_CP_UNSPECIFIED;
     37  img.tc = AOM_CICP_TC_UNSPECIFIED;
     38  img.mc = AOM_CICP_MC_UNSPECIFIED;
     39  img.range = AOM_CR_FULL_RANGE;
     40 
     41  aom_codec_iface_t *iface = aom_codec_av1_cx();
     42  aom_codec_enc_cfg_t cfg;
     43  EXPECT_EQ(AOM_CODEC_OK,
     44            aom_codec_enc_config_default(iface, &cfg, AOM_USAGE_GOOD_QUALITY));
     45  cfg.g_profile = 1;
     46  cfg.g_w = kWidth;
     47  cfg.g_h = kHeight;
     48  cfg.g_bit_depth = AOM_BITS_8;
     49  cfg.g_input_bit_depth = 8;
     50  cfg.g_lag_in_frames = 0;
     51  cfg.rc_end_usage = AOM_Q;
     52  cfg.rc_min_quantizer = 50;
     53  cfg.rc_max_quantizer = 50;
     54  aom_codec_ctx_t enc;
     55  EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_init(&enc, iface, &cfg, 0));
     56  EXPECT_EQ(AOM_CODEC_OK, aom_codec_control(&enc, AOME_SET_CQ_LEVEL, 50));
     57  EXPECT_EQ(AOM_CODEC_OK,
     58            aom_codec_control(&enc, AOME_SET_NUMBER_SPATIAL_LAYERS, 2));
     59  EXPECT_EQ(AOM_CODEC_OK, aom_codec_control(&enc, AOME_SET_CPUUSED, 6));
     60  EXPECT_EQ(AOM_CODEC_OK,
     61            aom_codec_control(&enc, AV1E_SET_COLOR_RANGE, AOM_CR_FULL_RANGE));
     62  EXPECT_EQ(AOM_CODEC_OK,
     63            aom_codec_control(&enc, AOME_SET_TUNING, AOM_TUNE_SSIM));
     64 
     65  // First frame (layer 0)
     66  EXPECT_EQ(AOM_CODEC_OK,
     67            aom_codec_control(&enc, AOME_SET_SPATIAL_LAYER_ID, 0));
     68  EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, &img, 0, 1, 0));
     69  aom_codec_iter_t iter = nullptr;
     70  const aom_codec_cx_pkt_t *pkt = aom_codec_get_cx_data(&enc, &iter);
     71  ASSERT_NE(pkt, nullptr);
     72  EXPECT_EQ(pkt->kind, AOM_CODEC_CX_FRAME_PKT);
     73  // pkt->data.frame.flags is 0x1f0011.
     74  EXPECT_EQ(pkt->data.frame.flags & AOM_FRAME_IS_KEY, AOM_FRAME_IS_KEY);
     75  pkt = aom_codec_get_cx_data(&enc, &iter);
     76  EXPECT_EQ(pkt, nullptr);
     77 
     78  // Second frame (layer 1)
     79  cfg.rc_min_quantizer = 0;
     80  cfg.rc_max_quantizer = 0;
     81  EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_config_set(&enc, &cfg));
     82  EXPECT_EQ(AOM_CODEC_OK, aom_codec_control(&enc, AOME_SET_CQ_LEVEL, 0));
     83  EXPECT_EQ(AOM_CODEC_OK, aom_codec_control(&enc, AV1E_SET_LOSSLESS, 1));
     84  EXPECT_EQ(AOM_CODEC_OK,
     85            aom_codec_control(&enc, AOME_SET_SPATIAL_LAYER_ID, 1));
     86  aom_enc_frame_flags_t encode_flags =
     87      AOM_EFLAG_NO_REF_GF | AOM_EFLAG_NO_REF_ARF | AOM_EFLAG_NO_REF_BWD |
     88      AOM_EFLAG_NO_REF_ARF2 | AOM_EFLAG_NO_UPD_GF | AOM_EFLAG_NO_UPD_ARF;
     89  EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, &img, 0, 1, encode_flags));
     90  iter = nullptr;
     91  pkt = aom_codec_get_cx_data(&enc, &iter);
     92  ASSERT_NE(pkt, nullptr);
     93  EXPECT_EQ(pkt->kind, AOM_CODEC_CX_FRAME_PKT);
     94  // pkt->data.frame.flags is 0.
     95  EXPECT_EQ(pkt->data.frame.flags & AOM_FRAME_IS_KEY, 0u);
     96  pkt = aom_codec_get_cx_data(&enc, &iter);
     97  EXPECT_EQ(pkt, nullptr);
     98 
     99  // Flush encoder
    100  EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, nullptr, 0, 1, 0));
    101  iter = nullptr;
    102  pkt = aom_codec_get_cx_data(&enc, &iter);
    103  EXPECT_EQ(pkt, nullptr);
    104 
    105  EXPECT_EQ(AOM_CODEC_OK, aom_codec_destroy(&enc));
    106 }
    107 
    108 // This test emulates how libavif calls libaom functions to encode a
    109 // progressive AVIF image in libavif's ProgressiveTest.DimensionChange test.
    110 TEST(AVIFProgressiveTest, DimensionChange) {
    111  constexpr int kWidth = 256;
    112  constexpr int kHeight = 256;
    113  // A buffer of neutral gray samples.
    114  constexpr size_t kBufferSize = 3 * kWidth * kHeight;
    115  std::vector<unsigned char> buffer(kBufferSize,
    116                                    static_cast<unsigned char>(128));
    117 
    118  aom_image_t img;
    119  EXPECT_EQ(&img, aom_img_wrap(&img, AOM_IMG_FMT_I444, kWidth, kHeight, 1,
    120                               buffer.data()));
    121  img.cp = AOM_CICP_CP_UNSPECIFIED;
    122  img.tc = AOM_CICP_TC_UNSPECIFIED;
    123  img.mc = AOM_CICP_MC_UNSPECIFIED;
    124  img.range = AOM_CR_FULL_RANGE;
    125 
    126  aom_codec_iface_t *iface = aom_codec_av1_cx();
    127  aom_codec_enc_cfg_t cfg;
    128  EXPECT_EQ(AOM_CODEC_OK,
    129            aom_codec_enc_config_default(iface, &cfg, AOM_USAGE_GOOD_QUALITY));
    130  cfg.g_profile = 1;
    131  cfg.g_w = kWidth;
    132  cfg.g_h = kHeight;
    133  cfg.g_bit_depth = AOM_BITS_8;
    134  cfg.g_input_bit_depth = 8;
    135  cfg.g_lag_in_frames = 0;
    136  cfg.rc_end_usage = AOM_Q;
    137  cfg.rc_min_quantizer = 0;
    138  cfg.rc_max_quantizer = 0;
    139  aom_codec_ctx_t enc;
    140  EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_init(&enc, iface, &cfg, 0));
    141  EXPECT_EQ(AOM_CODEC_OK, aom_codec_control(&enc, AOME_SET_CQ_LEVEL, 0));
    142  EXPECT_EQ(AOM_CODEC_OK, aom_codec_control(&enc, AV1E_SET_LOSSLESS, 1));
    143  EXPECT_EQ(AOM_CODEC_OK,
    144            aom_codec_control(&enc, AOME_SET_NUMBER_SPATIAL_LAYERS, 2));
    145  EXPECT_EQ(AOM_CODEC_OK, aom_codec_control(&enc, AOME_SET_CPUUSED, 6));
    146  EXPECT_EQ(AOM_CODEC_OK,
    147            aom_codec_control(&enc, AV1E_SET_COLOR_RANGE, AOM_CR_FULL_RANGE));
    148  EXPECT_EQ(AOM_CODEC_OK,
    149            aom_codec_control(&enc, AOME_SET_TUNING, AOM_TUNE_SSIM));
    150 
    151  // First frame (layer 0)
    152  EXPECT_EQ(AOM_CODEC_OK,
    153            aom_codec_control(&enc, AOME_SET_SPATIAL_LAYER_ID, 0));
    154  const aom_scaling_mode_t scaling_mode = { AOME_ONETWO, AOME_ONETWO };
    155  EXPECT_EQ(AOM_CODEC_OK,
    156            aom_codec_control(&enc, AOME_SET_SCALEMODE, &scaling_mode));
    157  EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, &img, 0, 1, 0));
    158  aom_codec_iter_t iter = nullptr;
    159  const aom_codec_cx_pkt_t *pkt = aom_codec_get_cx_data(&enc, &iter);
    160  ASSERT_NE(pkt, nullptr);
    161  EXPECT_EQ(pkt->kind, AOM_CODEC_CX_FRAME_PKT);
    162  // pkt->data.frame.flags is 0x1f0011.
    163  EXPECT_EQ(pkt->data.frame.flags & AOM_FRAME_IS_KEY, AOM_FRAME_IS_KEY);
    164  pkt = aom_codec_get_cx_data(&enc, &iter);
    165  EXPECT_EQ(pkt, nullptr);
    166 
    167  // Second frame (layer 1)
    168  EXPECT_EQ(AOM_CODEC_OK,
    169            aom_codec_control(&enc, AOME_SET_SPATIAL_LAYER_ID, 1));
    170  aom_enc_frame_flags_t encode_flags =
    171      AOM_EFLAG_NO_REF_GF | AOM_EFLAG_NO_REF_ARF | AOM_EFLAG_NO_REF_BWD |
    172      AOM_EFLAG_NO_REF_ARF2 | AOM_EFLAG_NO_UPD_GF | AOM_EFLAG_NO_UPD_ARF;
    173  EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, &img, 0, 1, encode_flags));
    174  iter = nullptr;
    175  pkt = aom_codec_get_cx_data(&enc, &iter);
    176  ASSERT_NE(pkt, nullptr);
    177  EXPECT_EQ(pkt->kind, AOM_CODEC_CX_FRAME_PKT);
    178  // pkt->data.frame.flags is 0.
    179  EXPECT_EQ(pkt->data.frame.flags & AOM_FRAME_IS_KEY, 0u);
    180  pkt = aom_codec_get_cx_data(&enc, &iter);
    181  EXPECT_EQ(pkt, nullptr);
    182 
    183  // Flush encoder
    184  EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, nullptr, 0, 1, 0));
    185  iter = nullptr;
    186  pkt = aom_codec_get_cx_data(&enc, &iter);
    187  EXPECT_EQ(pkt, nullptr);
    188 
    189  EXPECT_EQ(AOM_CODEC_OK, aom_codec_destroy(&enc));
    190 }
    191 
    192 // This test reproduces bug aomedia:3382. Certain parameters such as width,
    193 // height, g_threads, usage, etc. were carefully chosen based on the
    194 // complicated logic of av1_select_sb_size() to cause an inconsistent sb_size.
    195 TEST(AVIFProgressiveTest, DimensionChangeBigImageMultiThread) {
    196  constexpr int kWidth = 1920;
    197  constexpr int kHeight = 1080;
    198  // A buffer of neutral gray samples.
    199  constexpr size_t kBufferSize = 2 * kWidth * kHeight;
    200  std::vector<unsigned char> buffer(kBufferSize,
    201                                    static_cast<unsigned char>(128));
    202 
    203  aom_image_t img;
    204  EXPECT_EQ(&img, aom_img_wrap(&img, AOM_IMG_FMT_I420, kWidth, kHeight, 1,
    205                               buffer.data()));
    206  img.cp = AOM_CICP_CP_UNSPECIFIED;
    207  img.tc = AOM_CICP_TC_UNSPECIFIED;
    208  img.mc = AOM_CICP_MC_UNSPECIFIED;
    209  img.range = AOM_CR_FULL_RANGE;
    210 
    211  aom_codec_iface_t *iface = aom_codec_av1_cx();
    212  aom_codec_enc_cfg_t cfg;
    213  EXPECT_EQ(AOM_CODEC_OK,
    214            aom_codec_enc_config_default(iface, &cfg, AOM_USAGE_GOOD_QUALITY));
    215  cfg.g_profile = 0;
    216  cfg.g_w = img.w;
    217  cfg.g_h = img.h;
    218  cfg.g_bit_depth = AOM_BITS_8;
    219  cfg.g_input_bit_depth = 8;
    220  cfg.g_lag_in_frames = 0;
    221  cfg.g_threads = 2;  // MultiThread
    222  cfg.rc_end_usage = AOM_Q;
    223  cfg.rc_min_quantizer = 0;
    224  cfg.rc_max_quantizer = 63;
    225  aom_codec_ctx_t enc;
    226  EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_init(&enc, iface, &cfg, 0));
    227  EXPECT_EQ(AOM_CODEC_OK, aom_codec_control(&enc, AOME_SET_CQ_LEVEL, 31));
    228  EXPECT_EQ(AOM_CODEC_OK, aom_codec_control(&enc, AOME_SET_CPUUSED, 6));
    229  EXPECT_EQ(AOM_CODEC_OK,
    230            aom_codec_control(&enc, AV1E_SET_ROW_MT, 1));  // MultiThread
    231  EXPECT_EQ(AOM_CODEC_OK,
    232            aom_codec_control(&enc, AV1E_SET_COLOR_RANGE, AOM_CR_FULL_RANGE));
    233  EXPECT_EQ(AOM_CODEC_OK,
    234            aom_codec_control(&enc, AOME_SET_TUNING, AOM_TUNE_SSIM));
    235  EXPECT_EQ(AOM_CODEC_OK,
    236            aom_codec_control(&enc, AOME_SET_NUMBER_SPATIAL_LAYERS, 2));
    237 
    238  // First frame (layer 0)
    239  EXPECT_EQ(AOM_CODEC_OK,
    240            aom_codec_control(&enc, AOME_SET_SPATIAL_LAYER_ID, 0));
    241  const aom_scaling_mode_t scaling_mode = { AOME_ONETWO, AOME_ONETWO };
    242  EXPECT_EQ(AOM_CODEC_OK,
    243            aom_codec_control(&enc, AOME_SET_SCALEMODE, &scaling_mode));
    244  EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, &img, 0, 1, 0));
    245  aom_codec_iter_t iter = nullptr;
    246  const aom_codec_cx_pkt_t *pkt = aom_codec_get_cx_data(&enc, &iter);
    247  ASSERT_NE(pkt, nullptr);
    248  EXPECT_EQ(pkt->kind, AOM_CODEC_CX_FRAME_PKT);
    249  // pkt->data.frame.flags is 0x1f0011.
    250  EXPECT_EQ(pkt->data.frame.flags & AOM_FRAME_IS_KEY, AOM_FRAME_IS_KEY);
    251  pkt = aom_codec_get_cx_data(&enc, &iter);
    252  EXPECT_EQ(pkt, nullptr);
    253 
    254  // Second frame (layer 1)
    255  EXPECT_EQ(AOM_CODEC_OK,
    256            aom_codec_control(&enc, AOME_SET_SPATIAL_LAYER_ID, 1));
    257  aom_enc_frame_flags_t encode_flags =
    258      AOM_EFLAG_NO_REF_GF | AOM_EFLAG_NO_REF_ARF | AOM_EFLAG_NO_REF_BWD |
    259      AOM_EFLAG_NO_REF_ARF2 | AOM_EFLAG_NO_UPD_GF | AOM_EFLAG_NO_UPD_ARF;
    260  EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, &img, 0, 1, encode_flags));
    261  iter = nullptr;
    262  pkt = aom_codec_get_cx_data(&enc, &iter);
    263  ASSERT_NE(pkt, nullptr);
    264  EXPECT_EQ(pkt->kind, AOM_CODEC_CX_FRAME_PKT);
    265  // pkt->data.frame.flags is 0.
    266  EXPECT_EQ(pkt->data.frame.flags & AOM_FRAME_IS_KEY, 0u);
    267  pkt = aom_codec_get_cx_data(&enc, &iter);
    268  EXPECT_EQ(pkt, nullptr);
    269 
    270  // Flush encoder
    271  EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, nullptr, 0, 1, 0));
    272  iter = nullptr;
    273  pkt = aom_codec_get_cx_data(&enc, &iter);
    274  EXPECT_EQ(pkt, nullptr);
    275 
    276  EXPECT_EQ(AOM_CODEC_OK, aom_codec_destroy(&enc));
    277 }
    278 
    279 // A variant of the previous test, without the spatial layers.
    280 TEST(AVIFProgressiveTest, DimensionChangeBigImageMultiThread2) {
    281  constexpr int kWidth = 1920;
    282  constexpr int kHeight = 1080;
    283  // A buffer of neutral gray samples.
    284  constexpr size_t kBufferSize = 2 * kWidth * kHeight;
    285  std::vector<unsigned char> buffer(kBufferSize,
    286                                    static_cast<unsigned char>(128));
    287 
    288  aom_image_t img;
    289  EXPECT_EQ(&img, aom_img_wrap(&img, AOM_IMG_FMT_I420, kWidth, kHeight, 1,
    290                               buffer.data()));
    291  img.cp = AOM_CICP_CP_UNSPECIFIED;
    292  img.tc = AOM_CICP_TC_UNSPECIFIED;
    293  img.mc = AOM_CICP_MC_UNSPECIFIED;
    294  img.range = AOM_CR_FULL_RANGE;
    295 
    296  aom_codec_iface_t *iface = aom_codec_av1_cx();
    297  aom_codec_enc_cfg_t cfg;
    298  EXPECT_EQ(AOM_CODEC_OK,
    299            aom_codec_enc_config_default(iface, &cfg, AOM_USAGE_GOOD_QUALITY));
    300  cfg.g_profile = 0;
    301  cfg.g_w = img.w;
    302  cfg.g_h = img.h;
    303  cfg.g_bit_depth = AOM_BITS_8;
    304  cfg.g_input_bit_depth = 8;
    305  cfg.g_lag_in_frames = 0;
    306  cfg.g_threads = 2;  // MultiThread
    307  cfg.rc_end_usage = AOM_Q;
    308  cfg.rc_min_quantizer = 0;
    309  cfg.rc_max_quantizer = 63;
    310  aom_codec_ctx_t enc;
    311  EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_init(&enc, iface, &cfg, 0));
    312  EXPECT_EQ(AOM_CODEC_OK, aom_codec_control(&enc, AOME_SET_CQ_LEVEL, 31));
    313  EXPECT_EQ(AOM_CODEC_OK, aom_codec_control(&enc, AOME_SET_CPUUSED, 6));
    314  EXPECT_EQ(AOM_CODEC_OK,
    315            aom_codec_control(&enc, AV1E_SET_ROW_MT, 1));  // MultiThread
    316  EXPECT_EQ(AOM_CODEC_OK,
    317            aom_codec_control(&enc, AV1E_SET_COLOR_RANGE, AOM_CR_FULL_RANGE));
    318  EXPECT_EQ(AOM_CODEC_OK,
    319            aom_codec_control(&enc, AOME_SET_TUNING, AOM_TUNE_SSIM));
    320 
    321  // First frame
    322  const aom_scaling_mode_t scaling_mode = { AOME_ONETWO, AOME_ONETWO };
    323  EXPECT_EQ(AOM_CODEC_OK,
    324            aom_codec_control(&enc, AOME_SET_SCALEMODE, &scaling_mode));
    325  EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, &img, 0, 1, 0));
    326  aom_codec_iter_t iter = nullptr;
    327  const aom_codec_cx_pkt_t *pkt = aom_codec_get_cx_data(&enc, &iter);
    328  ASSERT_NE(pkt, nullptr);
    329  EXPECT_EQ(pkt->kind, AOM_CODEC_CX_FRAME_PKT);
    330  // pkt->data.frame.flags is 0x1f0011.
    331  EXPECT_EQ(pkt->data.frame.flags & AOM_FRAME_IS_KEY, AOM_FRAME_IS_KEY);
    332  pkt = aom_codec_get_cx_data(&enc, &iter);
    333  EXPECT_EQ(pkt, nullptr);
    334 
    335  // Second frame
    336  aom_enc_frame_flags_t encode_flags =
    337      AOM_EFLAG_NO_REF_GF | AOM_EFLAG_NO_REF_ARF | AOM_EFLAG_NO_REF_BWD |
    338      AOM_EFLAG_NO_REF_ARF2 | AOM_EFLAG_NO_UPD_GF | AOM_EFLAG_NO_UPD_ARF;
    339  EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, &img, 0, 1, encode_flags));
    340  iter = nullptr;
    341  pkt = aom_codec_get_cx_data(&enc, &iter);
    342  ASSERT_NE(pkt, nullptr);
    343  EXPECT_EQ(pkt->kind, AOM_CODEC_CX_FRAME_PKT);
    344  // pkt->data.frame.flags is 0.
    345  EXPECT_EQ(pkt->data.frame.flags & AOM_FRAME_IS_KEY, 0u);
    346  pkt = aom_codec_get_cx_data(&enc, &iter);
    347  EXPECT_EQ(pkt, nullptr);
    348 
    349  // Flush encoder
    350  EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, nullptr, 0, 1, 0));
    351  iter = nullptr;
    352  pkt = aom_codec_get_cx_data(&enc, &iter);
    353  EXPECT_EQ(pkt, nullptr);
    354 
    355  EXPECT_EQ(AOM_CODEC_OK, aom_codec_destroy(&enc));
    356 }
    357 
    358 }  // namespace