tor-browser

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

coding_path_sync.cc (5741B)


      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 <vector>
     13 #include "gtest/gtest.h"
     14 #include "test/acm_random.h"
     15 
     16 #include "config/aom_config.h"
     17 
     18 #include "aom/aomcx.h"
     19 #include "aom/aomdx.h"
     20 #include "aom/aom_encoder.h"
     21 #include "aom/aom_decoder.h"
     22 
     23 #define NELEMENTS(x) static_cast<int>(sizeof(x) / sizeof(x[0]))
     24 
     25 using libaom_test::ACMRandom;
     26 namespace {
     27 
     28 class CompressedSource {
     29 public:
     30  explicit CompressedSource(int seed) : rnd_(seed), frame_count_(0) {
     31    aom_codec_iface_t *algo = aom_codec_av1_cx();
     32 
     33    aom_codec_enc_cfg_t cfg;
     34 #if CONFIG_REALTIME_ONLY
     35    aom_codec_enc_config_default(algo, &cfg, 1);
     36 #else
     37    aom_codec_enc_config_default(algo, &cfg, 0);
     38 #endif
     39 
     40    // force the quantizer, to reduce the sensitivity on encoding choices.
     41    // e.g, we don't want this test to break when the rate control is modified.
     42    {
     43      const int max_q = cfg.rc_max_quantizer;
     44      const int min_q = cfg.rc_min_quantizer;
     45      const int q = rnd_.PseudoUniform(max_q - min_q + 1) + min_q;
     46 
     47      cfg.rc_end_usage = AOM_Q;
     48      cfg.rc_max_quantizer = q;
     49      cfg.rc_min_quantizer = q;
     50    }
     51 
     52    // choose the picture size
     53    {
     54      width_ = rnd_.PseudoUniform(kWidth - 8) + 8;
     55      height_ = rnd_.PseudoUniform(kHeight - 8) + 8;
     56    }
     57 
     58    // choose the chroma subsampling
     59    {
     60      const aom_img_fmt_t fmts[] = {
     61        AOM_IMG_FMT_I420,
     62        AOM_IMG_FMT_I422,
     63        AOM_IMG_FMT_I444,
     64      };
     65 
     66      format_ = fmts[rnd_.PseudoUniform(NELEMENTS(fmts))];
     67    }
     68 
     69    cfg.g_w = width_;
     70    cfg.g_h = height_;
     71    cfg.g_lag_in_frames = 0;
     72    if (format_ == AOM_IMG_FMT_I420)
     73      cfg.g_profile = 0;
     74    else if (format_ == AOM_IMG_FMT_I444)
     75      cfg.g_profile = 1;
     76    else if (format_ == AOM_IMG_FMT_I422)
     77      cfg.g_profile = 2;
     78 
     79    aom_codec_enc_init(&enc_, algo, &cfg, 0);
     80  }
     81 
     82  ~CompressedSource() { aom_codec_destroy(&enc_); }
     83 
     84  const aom_codec_cx_pkt_t *ReadFrame() {
     85    uint8_t buf[kWidth * kHeight * 3] = { 0 };
     86 
     87    // render regular pattern
     88    const int period = rnd_.Rand8() % 32 + 1;
     89    const int phase = rnd_.Rand8() % period;
     90 
     91    const int val_a = rnd_.Rand8();
     92    const int val_b = rnd_.Rand8();
     93 
     94    for (int i = 0; i < (int)sizeof buf; ++i)
     95      buf[i] = (i + phase) % period < period / 2 ? val_a : val_b;
     96 
     97    aom_image_t img;
     98    aom_img_wrap(&img, format_, width_, height_, 0, buf);
     99    aom_codec_encode(&enc_, &img, frame_count_++, 1, 0);
    100 
    101    aom_codec_iter_t iter = nullptr;
    102 
    103    const aom_codec_cx_pkt_t *pkt = nullptr;
    104 
    105    do {
    106      pkt = aom_codec_get_cx_data(&enc_, &iter);
    107    } while (pkt && pkt->kind != AOM_CODEC_CX_FRAME_PKT);
    108 
    109    return pkt;
    110  }
    111 
    112 private:
    113  static const int kWidth = 128;
    114  static const int kHeight = 128;
    115 
    116  ACMRandom rnd_;
    117  aom_img_fmt_t format_;
    118  aom_codec_ctx_t enc_;
    119  int frame_count_;
    120  int width_, height_;
    121 };
    122 
    123 // lowers an aom_image_t to an easily comparable/printable form
    124 std::vector<uint16_t> Serialize(const aom_image_t *img) {
    125  std::vector<uint16_t> bytes;
    126  bytes.reserve(img->d_w * img->d_h * 3);
    127  for (int plane = 0; plane < 3; ++plane) {
    128    const int w = aom_img_plane_width(img, plane);
    129    const int h = aom_img_plane_height(img, plane);
    130 
    131    for (int r = 0; r < h; ++r) {
    132      for (int c = 0; c < w; ++c) {
    133        const unsigned char *row = img->planes[plane] + r * img->stride[plane];
    134        if (img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) {
    135          const uint16_t *row16 = reinterpret_cast<const uint16_t *>(row);
    136          bytes.push_back(row16[c]);
    137        } else {
    138          bytes.push_back(row[c]);
    139        }
    140      }
    141    }
    142  }
    143 
    144  return bytes;
    145 }
    146 
    147 class Decoder {
    148 public:
    149  explicit Decoder(int allowLowbitdepth) {
    150    aom_codec_iface_t *algo = aom_codec_av1_dx();
    151 
    152    aom_codec_dec_cfg_t cfg = aom_codec_dec_cfg_t();
    153    cfg.allow_lowbitdepth = allowLowbitdepth;
    154 
    155    aom_codec_dec_init(&dec_, algo, &cfg, 0);
    156  }
    157 
    158  ~Decoder() { aom_codec_destroy(&dec_); }
    159 
    160  std::vector<uint16_t> decode(const aom_codec_cx_pkt_t *pkt) {
    161    aom_codec_decode(&dec_, static_cast<uint8_t *>(pkt->data.frame.buf),
    162                     pkt->data.frame.sz, nullptr);
    163 
    164    aom_codec_iter_t iter = nullptr;
    165    return Serialize(aom_codec_get_frame(&dec_, &iter));
    166  }
    167 
    168 private:
    169  aom_codec_ctx_t dec_;
    170 };
    171 
    172 // Try to reveal a mismatch between LBD and HBD coding paths.
    173 TEST(CodingPathSync, SearchForHbdLbdMismatch) {
    174  const int count_tests = 10;
    175  for (int i = 0; i < count_tests; ++i) {
    176    Decoder dec_hbd(0);
    177    Decoder dec_lbd(1);
    178 
    179    CompressedSource enc(i);
    180 
    181    for (int k = 0; k < 3; ++k) {
    182      const aom_codec_cx_pkt_t *frame = enc.ReadFrame();
    183 
    184      std::vector<uint16_t> lbd_yuv = dec_lbd.decode(frame);
    185      std::vector<uint16_t> hbd_yuv = dec_hbd.decode(frame);
    186 
    187      ASSERT_EQ(lbd_yuv, hbd_yuv);
    188    }
    189  }
    190 }
    191 
    192 TEST(CodingPathSyncLarge, SearchForHbdLbdMismatchLarge) {
    193  const int count_tests = 100;
    194  const int seed = 1234;
    195  for (int i = 0; i < count_tests; ++i) {
    196    Decoder dec_hbd(0);
    197    Decoder dec_lbd(1);
    198 
    199    CompressedSource enc(seed + i);
    200 
    201    for (int k = 0; k < 5; ++k) {
    202      const aom_codec_cx_pkt_t *frame = enc.ReadFrame();
    203 
    204      std::vector<uint16_t> lbd_yuv = dec_lbd.decode(frame);
    205      std::vector<uint16_t> hbd_yuv = dec_hbd.decode(frame);
    206 
    207      ASSERT_EQ(lbd_yuv, hbd_yuv);
    208    }
    209  }
    210 }
    211 
    212 }  // namespace