tor-browser

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

encodemb_test.cc (10754B)


      1 /*
      2 * Copyright (c) 2021, 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 <stdint.h>
     13 #include <vector>
     14 
     15 #include "gtest/gtest.h"
     16 
     17 #include "av1/encoder/block.h"
     18 #include "av1/encoder/encodemb.h"
     19 #include "av1/common/scan.h"
     20 
     21 namespace {
     22 
     23 // Reorders 'qcoeff_lexico', which is in lexicographic order (row by row), into
     24 // scan order (zigzag) in 'qcoeff_scan'.
     25 void ToScanOrder(TX_SIZE tx_size, TX_TYPE tx_type, tran_low_t *qcoeff_lexico,
     26                 tran_low_t *qcoeff_scan) {
     27  const int max_eob = av1_get_max_eob(tx_size);
     28  const SCAN_ORDER *const scan_order = get_scan(tx_size, tx_type);
     29  for (int i = 0; i < max_eob; ++i) {
     30    qcoeff_scan[i] = qcoeff_lexico[scan_order->scan[i]];
     31  }
     32 }
     33 
     34 // Reorders 'qcoeff_scan', which is in scan order (zigzag), into lexicographic
     35 // order (row by row) in 'qcoeff_lexico'.
     36 void ToLexicoOrder(TX_SIZE tx_size, TX_TYPE tx_type, tran_low_t *qcoeff_scan,
     37                   tran_low_t *qcoeff_lexico) {
     38  const int max_eob = av1_get_max_eob(tx_size);
     39  const SCAN_ORDER *const scan_order = get_scan(tx_size, tx_type);
     40  for (int i = 0; i < max_eob; ++i) {
     41    qcoeff_lexico[scan_order->scan[i]] = qcoeff_scan[i];
     42  }
     43 }
     44 
     45 // Runs coefficient dropout on 'qcoeff_scan'.
     46 void Dropout(TX_SIZE tx_size, TX_TYPE tx_type, int dropout_num_before,
     47             int dropout_num_after, tran_low_t *qcoeff_scan) {
     48  tran_low_t qcoeff[MAX_TX_SQUARE];
     49  // qcoeff_scan is assumed to be in scan order, since tests are easier to
     50  // understand this way, but av1_dropout_qcoeff expects coeffs in lexico order
     51  // so we convert to lexico then back to scan afterwards.
     52  ToLexicoOrder(tx_size, tx_type, qcoeff_scan, qcoeff);
     53 
     54  const int max_eob = av1_get_max_eob(tx_size);
     55  const int kDequantFactor = 10;
     56  tran_low_t dqcoeff[MAX_TX_SQUARE];
     57  for (int i = 0; i < max_eob; ++i) {
     58    dqcoeff[i] = qcoeff[i] * kDequantFactor;
     59  }
     60 
     61  uint16_t eob = max_eob;
     62  while (eob > 0 && qcoeff_scan[eob - 1] == 0) --eob;
     63 
     64  MACROBLOCK mb;
     65  const int kPlane = 0;
     66  const int kBlock = 0;
     67  memset(&mb, 0, sizeof(mb));
     68  uint16_t eobs[] = { eob };
     69  mb.plane[kPlane].eobs = eobs;
     70  mb.plane[kPlane].qcoeff = qcoeff;
     71  mb.plane[kPlane].dqcoeff = dqcoeff;
     72  uint8_t txb_entropy_ctx[1];
     73  mb.plane[kPlane].txb_entropy_ctx = txb_entropy_ctx;
     74 
     75  av1_dropout_qcoeff_num(&mb, kPlane, kBlock, tx_size, tx_type,
     76                         dropout_num_before, dropout_num_after);
     77 
     78  ToScanOrder(tx_size, tx_type, qcoeff, qcoeff_scan);
     79 
     80  // Check updated eob value is valid.
     81  uint16_t new_eob = max_eob;
     82  while (new_eob > 0 && qcoeff_scan[new_eob - 1] == 0) --new_eob;
     83  EXPECT_EQ(new_eob, mb.plane[kPlane].eobs[0]);
     84 
     85  // Check dqcoeff is still valid.
     86  for (int i = 0; i < max_eob; ++i) {
     87    EXPECT_EQ(qcoeff[i] * kDequantFactor, dqcoeff[i]);
     88  }
     89 }
     90 
     91 void ExpectArrayEq(tran_low_t *actual, std::vector<tran_low_t> expected) {
     92  for (size_t i = 0; i < expected.size(); ++i) {
     93    EXPECT_EQ(expected[i], actual[i]) << "Arrays differ at index " << i;
     94  }
     95 }
     96 
     97 static constexpr TX_TYPE kTxType = DCT_DCT;
     98 
     99 TEST(DropoutTest, KeepsLargeCoeffs) {
    100  const TX_SIZE tx_size = TX_8X4;
    101  const uint32_t dropout_num_before = 4;
    102  const uint32_t dropout_num_after = 6;
    103  // Large isolated coeffs should be preserved.
    104  tran_low_t qcoeff_scan[] = { 0, 0, 0, 0, 0, 0, 42, 0,    // should be kept
    105                               0, 0, 0, 0, 0, 0, 0,  0,    //
    106                               0, 0, 0, 0, 0, 0, 0,  -30,  // should be kept
    107                               0, 0, 0, 0, 0, 0, 0,  0 };
    108  Dropout(tx_size, kTxType, dropout_num_before, dropout_num_after, qcoeff_scan);
    109  ExpectArrayEq(qcoeff_scan, { 0, 0, 0, 0, 0, 0, 42, 0,    //
    110                               0, 0, 0, 0, 0, 0, 0,  0,    //
    111                               0, 0, 0, 0, 0, 0, 0,  -30,  //
    112                               0, 0, 0, 0, 0, 0, 0,  0 });
    113 }
    114 
    115 TEST(DropoutTest, RemovesSmallIsolatedCoeffs) {
    116  const TX_SIZE tx_size = TX_8X4;
    117  const uint32_t dropout_num_before = 4;
    118  const uint32_t dropout_num_after = 6;
    119  // Small isolated coeffs should be removed.
    120  tran_low_t qcoeff_scan[] = { 0, 0, 0, 0, 1,  0, 0, 0,  // should be removed
    121                               0, 0, 0, 0, 0,  0, 0, 0,  //
    122                               0, 0, 0, 0, -2, 0, 0, 0,  // should be removed
    123                               0, 0, 0, 0, 0,  0, 0, 0 };
    124  Dropout(tx_size, kTxType, dropout_num_before, dropout_num_after, qcoeff_scan);
    125  ExpectArrayEq(qcoeff_scan, { 0, 0, 0, 0, 0, 0, 0, 0,  //
    126                               0, 0, 0, 0, 0, 0, 0, 0,  //
    127                               0, 0, 0, 0, 0, 0, 0, 0,  //
    128                               0, 0, 0, 0, 0, 0, 0, 0 });
    129 }
    130 
    131 TEST(DropoutTest, KeepsSmallCoeffsAmongLargeOnes) {
    132  const TX_SIZE tx_size = TX_8X4;
    133  const uint32_t dropout_num_before = 4;
    134  const uint32_t dropout_num_after = 6;
    135  // Small coeffs that are not isolated (not enough zeros before/after should be
    136  // kept).
    137  tran_low_t qcoeff_scan[] = {
    138    1, 0,  0, 0,  -5, 0, 0, -1,  // should be kept
    139    0, 0,  0, 10, 0,  0, 2, 0,   // should be kept
    140    0, 0,  0, 0,  0,  0, 0, 0,   //
    141    0, -2, 0, 0,  0,  0, 0, 0    // should be removed
    142  };
    143  Dropout(tx_size, kTxType, dropout_num_before, dropout_num_after, qcoeff_scan);
    144  ExpectArrayEq(qcoeff_scan, { 1, 0, 0, 0,  -5, 0, 0, -1,  //
    145                               0, 0, 0, 10, 0,  0, 2, 0,   //
    146                               0, 0, 0, 0,  0,  0, 0, 0,   //
    147                               0, 0, 0, 0,  0,  0, 0, 0 });
    148 }
    149 
    150 TEST(DropoutTest, KeepsSmallCoeffsCloseToStartOrEnd) {
    151  const TX_SIZE tx_size = TX_8X4;
    152  const uint32_t dropout_num_before = 4;
    153  const uint32_t dropout_num_after = 6;
    154  // Small coeffs that are too close to the beginning or end of the block
    155  // should also be kept (not enough zeroes before/after).
    156  tran_low_t qcoeff_scan[] = { 0, 0, -1, 0,  0, 0, 0,  0,  // should be kept
    157                               0, 0, 0,  10, 0, 0, 0,  0,  // should be kept
    158                               0, 0, 0,  2,  0, 0, 0,  0,  // should be removed
    159                               0, 0, 0,  0,  0, 0, -1, 0 };  // should be kept
    160  Dropout(tx_size, kTxType, dropout_num_before, dropout_num_after, qcoeff_scan);
    161  ExpectArrayEq(qcoeff_scan, { 0, 0, -1, 0,  0, 0, 0,  0,  //
    162                               0, 0, 0,  10, 0, 0, 0,  0,  //
    163                               0, 0, 0,  0,  0, 0, 0,  0,  //
    164                               0, 0, 0,  0,  0, 0, -1, 0 });
    165 }
    166 
    167 TEST(DropoutTest, RemovesSmallClusterOfCoeffs) {
    168  const TX_SIZE tx_size = TX_8X4;
    169  const uint32_t dropout_num_before = 4;
    170  const uint32_t dropout_num_after = 6;
    171  // Small clusters (<= kDropoutContinuityMax) of small coeffs should be
    172  // removed.
    173  tran_low_t qcoeff_scan_two[] = {
    174    0, 0, 0, 0, 1, 0, 0, -1,  // should be removed
    175    0, 0, 0, 0, 0, 0, 0, 0,   //
    176    0, 0, 0, 0, 0, 0, 1, 0,   // should be removed
    177    0, 0, 0, 0, 0, 0, 0, 0
    178  };
    179  Dropout(tx_size, kTxType, dropout_num_before, dropout_num_after,
    180          qcoeff_scan_two);
    181  ExpectArrayEq(qcoeff_scan_two, { 0, 0, 0, 0, 0, 0, 0, 0,  //
    182                                   0, 0, 0, 0, 0, 0, 0, 0,  //
    183                                   0, 0, 0, 0, 0, 0, 0, 0,  //
    184                                   0, 0, 0, 0, 0, 0, 0, 0 });
    185 }
    186 
    187 TEST(DropoutTest, KeepsLargeClusterOfCoeffs) {
    188  const TX_SIZE tx_size = TX_8X4;
    189  const uint32_t dropout_num_before = 4;
    190  const uint32_t dropout_num_after = 6;
    191  // Large clusters (> kDropoutContinuityMax) of small coeffs should be kept.
    192  tran_low_t qcoeff_scan[] = { 0, 0, 0, 0, 1, 0,  1, -1,  // should be kept
    193                               0, 0, 0, 0, 0, 0,  0, 0,   //
    194                               0, 0, 0, 0, 0, -2, 0, 0,   // should be removed
    195                               0, 0, 0, 0, 0, 0,  0, 0 };
    196  Dropout(tx_size, kTxType, dropout_num_before, dropout_num_after, qcoeff_scan);
    197  ExpectArrayEq(qcoeff_scan, { 0, 0, 0, 0, 1, 0, 1, -1,  //
    198                               0, 0, 0, 0, 0, 0, 0, 0,   //
    199                               0, 0, 0, 0, 0, 0, 0, 0,   //
    200                               0, 0, 0, 0, 0, 0, 0, 0 });
    201 }
    202 
    203 TEST(DropoutTest, NumBeforeLargerThanNumAfter) {
    204  const TX_SIZE tx_size = TX_8X4;
    205  const uint32_t dropout_num_before = 4;
    206  const uint32_t dropout_num_after = 2;
    207  // The second coeff (-2) doesn't seem to meet the dropout_num_before
    208  // criteria. But since the first coeff (1) will be dropped, it will meet
    209  // the criteria and should be dropped too.
    210  tran_low_t qcoeff_scan[] = { 0,  0, 0, 0, 1, 0, 0, 0,  // should be removed
    211                               -2, 0, 0, 0, 0, 0, 0, 0,  // should be removed
    212                               0,  0, 0, 0, 0, 0, 0, 0,  //
    213                               0,  0, 0, 0, 0, 0, 0, 0 };
    214  Dropout(tx_size, kTxType, dropout_num_before, dropout_num_after, qcoeff_scan);
    215  ExpectArrayEq(qcoeff_scan, { 0, 0, 0, 0, 0, 0, 0, 0,  //
    216                               0, 0, 0, 0, 0, 0, 0, 0,  //
    217                               0, 0, 0, 0, 0, 0, 0, 0,  //
    218                               0, 0, 0, 0, 0, 0, 0, 0 });
    219 }
    220 
    221 // More complex test combining other test cases.
    222 TEST(DropoutTest, ComplexTest) {
    223  const TX_SIZE tx_size = TX_8X8;
    224  const uint32_t dropout_num_before = 4;
    225  const uint32_t dropout_num_after = 2;
    226  tran_low_t qcoeff_scan[] = { 1, 12, 0,  0,   0, 0, 1,  0,   //
    227                               0, 0,  0,  -12, 0, 0, 0,  1,   //
    228                               0, 0,  -2, 0,   1, 0, 0,  1,   //
    229                               0, 0,  0,  0,   5, 0, -1, 0,   //
    230                               0, 0,  0,  1,   0, 0, 0,  -1,  //
    231                               0, 0,  0,  0,   2, 0, 0,  0,   //
    232                               0, 1,  0,  0,   0, 5, 0,  0,   //
    233                               0, 0,  1,  1,   0, 0, 0,  -2 };
    234  Dropout(tx_size, kTxType, dropout_num_before, dropout_num_after, qcoeff_scan);
    235  ExpectArrayEq(qcoeff_scan, { 1, 12, 0,  0,   0, 0, 0,  0,  //
    236                               0, 0,  0,  -12, 0, 0, 0,  1,  //
    237                               0, 0,  -2, 0,   1, 0, 0,  1,  //
    238                               0, 0,  0,  0,   5, 0, -1, 0,  //
    239                               0, 0,  0,  0,   0, 0, 0,  0,  //
    240                               0, 0,  0,  0,   0, 0, 0,  0,  //
    241                               0, 0,  0,  0,   0, 5, 0,  0,  //
    242                               0, 0,  0,  0,   0, 0, 0,  -2 });
    243 }
    244 
    245 }  // namespace