Home | History | Annotate | Download | only in vda
      1 // Copyright 2016 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 // Note: ported from Chromium commit head: 2de6929
      5 
      6 #include "vp9_compressed_header_parser.h"
      7 
      8 #include "base/logging.h"
      9 
     10 namespace media {
     11 
     12 namespace {
     13 
     14 // 6.3.6 Inv recenter noneg syntax, inv_recenter_nonneg().
     15 int InvRecenterNonneg(int v, int m) {
     16   DCHECK_LE(m, kVp9MaxProb / 2);
     17   if (v > 2 * m)
     18     return v;
     19 
     20   if (v & 1)
     21     return m - ((v + 1) >> 1);
     22   return m + (v >> 1);
     23 }
     24 
     25 // 6.3.5 Inv remap prob syntax, inv_remap_prob().
     26 Vp9Prob InvRemapProb(uint8_t delta_prob, uint8_t prob) {
     27   static uint8_t inv_map_table[kVp9MaxProb] = {
     28       7,   20,  33,  46,  59,  72,  85,  98,  111, 124, 137, 150, 163, 176,
     29       189, 202, 215, 228, 241, 254, 1,   2,   3,   4,   5,   6,   8,   9,
     30       10,  11,  12,  13,  14,  15,  16,  17,  18,  19,  21,  22,  23,  24,
     31       25,  26,  27,  28,  29,  30,  31,  32,  34,  35,  36,  37,  38,  39,
     32       40,  41,  42,  43,  44,  45,  47,  48,  49,  50,  51,  52,  53,  54,
     33       55,  56,  57,  58,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,
     34       70,  71,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,
     35       86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  99,  100,
     36       101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 112, 113, 114, 115,
     37       116, 117, 118, 119, 120, 121, 122, 123, 125, 126, 127, 128, 129, 130,
     38       131, 132, 133, 134, 135, 136, 138, 139, 140, 141, 142, 143, 144, 145,
     39       146, 147, 148, 149, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160,
     40       161, 162, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
     41       177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 190, 191,
     42       192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 203, 204, 205, 206,
     43       207, 208, 209, 210, 211, 212, 213, 214, 216, 217, 218, 219, 220, 221,
     44       222, 223, 224, 225, 226, 227, 229, 230, 231, 232, 233, 234, 235, 236,
     45       237, 238, 239, 240, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251,
     46       252, 253, 253};
     47   uint8_t m = prob;
     48   uint8_t v = delta_prob;
     49   DCHECK_GE(m, 1);
     50   DCHECK_LE(m, kVp9MaxProb);
     51   DCHECK_LT(v, arraysize(inv_map_table));
     52   v = inv_map_table[v];
     53   m--;
     54   if ((m << 1) <= kVp9MaxProb) {
     55     return 1 + InvRecenterNonneg(v, m);
     56   } else {
     57     return kVp9MaxProb - InvRecenterNonneg(v, kVp9MaxProb - 1 - m);
     58   }
     59 }
     60 
     61 }  // namespace
     62 
     63 Vp9CompressedHeaderParser::Vp9CompressedHeaderParser() = default;
     64 
     65 // 6.3.1 Tx mode syntax
     66 void Vp9CompressedHeaderParser::ReadTxMode(Vp9FrameHeader* fhdr) {
     67   int tx_mode;
     68   if (fhdr->quant_params.IsLossless()) {
     69     tx_mode = Vp9CompressedHeader::ONLY_4X4;
     70   } else {
     71     tx_mode = reader_.ReadLiteral(2);
     72     if (tx_mode == Vp9CompressedHeader::ALLOW_32X32)
     73       tx_mode += reader_.ReadLiteral(1);
     74   }
     75   fhdr->compressed_header.tx_mode =
     76       static_cast<Vp9CompressedHeader::Vp9TxMode>(tx_mode);
     77 }
     78 
     79 // 6.3.4 Decode term subexp syntax
     80 uint8_t Vp9CompressedHeaderParser::DecodeTermSubexp() {
     81   if (reader_.ReadLiteral(1) == 0)
     82     return reader_.ReadLiteral(4);
     83   if (reader_.ReadLiteral(1) == 0)
     84     return reader_.ReadLiteral(4) + 16;
     85   if (reader_.ReadLiteral(1) == 0)
     86     return reader_.ReadLiteral(5) + 32;
     87   uint8_t v = reader_.ReadLiteral(7);
     88   if (v < 65)
     89     return v + 64;
     90   return (v << 1) - 1 + reader_.ReadLiteral(1);
     91 }
     92 
     93 // 6.3.3 Diff update prob syntax
     94 void Vp9CompressedHeaderParser::DiffUpdateProb(Vp9Prob* prob) {
     95   const Vp9Prob kUpdateProb = 252;
     96   if (reader_.ReadBool(kUpdateProb)) {
     97     uint8_t delta_prob = DecodeTermSubexp();
     98     *prob = InvRemapProb(delta_prob, *prob);
     99   }
    100 }
    101 
    102 // Helper function to DiffUpdateProb an array of probs.
    103 template <int N>
    104 void Vp9CompressedHeaderParser::DiffUpdateProbArray(Vp9Prob (&prob_array)[N]) {
    105   for (auto& x : prob_array) {
    106     DiffUpdateProb(&x);
    107   }
    108 }
    109 
    110 // 6.3.2 Tx mode probs syntax
    111 void Vp9CompressedHeaderParser::ReadTxModeProbs(
    112     Vp9FrameContext* frame_context) {
    113   for (auto& a : frame_context->tx_probs_8x8) {
    114     DiffUpdateProbArray(a);
    115   }
    116   for (auto& a : frame_context->tx_probs_16x16) {
    117     DiffUpdateProbArray(a);
    118   }
    119   for (auto& a : frame_context->tx_probs_32x32) {
    120     DiffUpdateProbArray(a);
    121   }
    122 }
    123 
    124 // 6.3.7 Coef probs syntax
    125 void Vp9CompressedHeaderParser::ReadCoefProbs(Vp9FrameHeader* fhdr) {
    126   const int tx_mode_to_biggest_tx_size[Vp9CompressedHeader::TX_MODES] = {
    127       0, 1, 2, 3, 3,
    128   };
    129   const int max_tx_size =
    130       tx_mode_to_biggest_tx_size[fhdr->compressed_header.tx_mode];
    131   for (int tx_size = 0; tx_size <= max_tx_size; tx_size++) {
    132     if (reader_.ReadLiteral(1) == 0)
    133       continue;
    134 
    135     for (auto& ai : fhdr->frame_context.coef_probs[tx_size]) {
    136       for (auto& aj : ai) {
    137         for (auto& ak : aj) {
    138           int max_l = (ak == aj[0]) ? 3 : 6;
    139           for (int l = 0; l < max_l; l++) {
    140             DiffUpdateProbArray(ak[l]);
    141           }
    142         }
    143       }
    144     }
    145   }
    146 }
    147 
    148 // 6.3.8 Skip probs syntax
    149 void Vp9CompressedHeaderParser::ReadSkipProb(Vp9FrameContext* frame_context) {
    150   DiffUpdateProbArray(frame_context->skip_prob);
    151 }
    152 
    153 // 6.3.9 Inter mode probs syntax
    154 void Vp9CompressedHeaderParser::ReadInterModeProbs(
    155     Vp9FrameContext* frame_context) {
    156   for (auto& a : frame_context->inter_mode_probs)
    157     DiffUpdateProbArray(a);
    158 }
    159 
    160 // 6.3.10 Interp filter probs syntax
    161 void Vp9CompressedHeaderParser::ReadInterpFilterProbs(
    162     Vp9FrameContext* frame_context) {
    163   for (auto& a : frame_context->interp_filter_probs)
    164     DiffUpdateProbArray(a);
    165 }
    166 
    167 // 6.3.11 Intra inter probs syntax
    168 void Vp9CompressedHeaderParser::ReadIsInterProbs(
    169     Vp9FrameContext* frame_context) {
    170   DiffUpdateProbArray(frame_context->is_inter_prob);
    171 }
    172 
    173 // 6.3.12 Frame reference mode syntax
    174 void Vp9CompressedHeaderParser::ReadFrameReferenceMode(Vp9FrameHeader* fhdr) {
    175   bool compound_reference_allowed = false;
    176   for (int i = VP9_FRAME_LAST + 1; i < VP9_FRAME_MAX; i++)
    177     if (fhdr->ref_frame_sign_bias[i] != fhdr->ref_frame_sign_bias[1])
    178       compound_reference_allowed = true;
    179 
    180   if (compound_reference_allowed && reader_.ReadLiteral(1)) {
    181     fhdr->compressed_header.reference_mode =
    182         reader_.ReadLiteral(1) ? REFERENCE_MODE_SELECT : COMPOUND_REFERENCE;
    183   } else {
    184     fhdr->compressed_header.reference_mode = SINGLE_REFERENCE;
    185   }
    186 }
    187 
    188 // 6.3.13 Frame reference mode probs syntax
    189 void Vp9CompressedHeaderParser::ReadFrameReferenceModeProbs(
    190     Vp9FrameHeader* fhdr) {
    191   Vp9FrameContext* frame_context = &fhdr->frame_context;
    192   if (fhdr->compressed_header.reference_mode == REFERENCE_MODE_SELECT)
    193     DiffUpdateProbArray(frame_context->comp_mode_prob);
    194 
    195   if (fhdr->compressed_header.reference_mode != COMPOUND_REFERENCE)
    196     for (auto& a : frame_context->single_ref_prob)
    197       DiffUpdateProbArray(a);
    198 
    199   if (fhdr->compressed_header.reference_mode != SINGLE_REFERENCE)
    200     DiffUpdateProbArray(frame_context->comp_ref_prob);
    201 }
    202 
    203 // 6.3.14 Y mode probs syntax
    204 void Vp9CompressedHeaderParser::ReadYModeProbs(Vp9FrameContext* frame_context) {
    205   for (auto& a : frame_context->y_mode_probs)
    206     DiffUpdateProbArray(a);
    207 }
    208 
    209 // 6.3.15 Partition probs syntax
    210 void Vp9CompressedHeaderParser::ReadPartitionProbs(
    211     Vp9FrameContext* frame_context) {
    212   for (auto& a : frame_context->partition_probs)
    213     DiffUpdateProbArray(a);
    214 }
    215 
    216 // 6.3.16 MV probs syntax
    217 void Vp9CompressedHeaderParser::ReadMvProbs(bool allow_high_precision_mv,
    218                                             Vp9FrameContext* frame_context) {
    219   UpdateMvProbArray(frame_context->mv_joint_probs);
    220 
    221   for (int i = 0; i < 2; i++) {
    222     UpdateMvProb(&frame_context->mv_sign_prob[i]);
    223     UpdateMvProbArray(frame_context->mv_class_probs[i]);
    224     UpdateMvProb(&frame_context->mv_class0_bit_prob[i]);
    225     UpdateMvProbArray(frame_context->mv_bits_prob[i]);
    226   }
    227 
    228   for (int i = 0; i < 2; i++) {
    229     for (auto& a : frame_context->mv_class0_fr_probs[i])
    230       UpdateMvProbArray(a);
    231     UpdateMvProbArray(frame_context->mv_fr_probs[i]);
    232   }
    233 
    234   if (allow_high_precision_mv) {
    235     for (int i = 0; i < 2; i++) {
    236       UpdateMvProb(&frame_context->mv_class0_hp_prob[i]);
    237       UpdateMvProb(&frame_context->mv_hp_prob[i]);
    238     }
    239   }
    240 }
    241 
    242 // 6.3.17 Update mv prob syntax
    243 void Vp9CompressedHeaderParser::UpdateMvProb(Vp9Prob* prob) {
    244   if (reader_.ReadBool(252))
    245     *prob = reader_.ReadLiteral(7) << 1 | 1;
    246 }
    247 
    248 // Helper function to UpdateMvProb an array of probs.
    249 template <int N>
    250 void Vp9CompressedHeaderParser::UpdateMvProbArray(Vp9Prob (&prob_array)[N]) {
    251   for (auto& x : prob_array) {
    252     UpdateMvProb(&x);
    253   }
    254 }
    255 
    256 // 6.3 Compressed header syntax
    257 bool Vp9CompressedHeaderParser::Parse(const uint8_t* stream,
    258                                       off_t frame_size,
    259                                       Vp9FrameHeader* fhdr) {
    260   DVLOG(2) << "Vp9CompressedHeaderParser::Parse";
    261   if (!reader_.Initialize(stream, frame_size))
    262     return false;
    263 
    264   ReadTxMode(fhdr);
    265   if (fhdr->compressed_header.tx_mode == Vp9CompressedHeader::TX_MODE_SELECT)
    266     ReadTxModeProbs(&fhdr->frame_context);
    267 
    268   ReadCoefProbs(fhdr);
    269   ReadSkipProb(&fhdr->frame_context);
    270 
    271   if (!fhdr->IsIntra()) {
    272     ReadInterModeProbs(&fhdr->frame_context);
    273     if (fhdr->interpolation_filter == SWITCHABLE)
    274       ReadInterpFilterProbs(&fhdr->frame_context);
    275     ReadIsInterProbs(&fhdr->frame_context);
    276     ReadFrameReferenceMode(fhdr);
    277     ReadFrameReferenceModeProbs(fhdr);
    278     ReadYModeProbs(&fhdr->frame_context);
    279     ReadPartitionProbs(&fhdr->frame_context);
    280     ReadMvProbs(fhdr->allow_high_precision_mv, &fhdr->frame_context);
    281   }
    282 
    283   if (!reader_.IsValid()) {
    284     DVLOG(1) << "parser reads beyond the end of buffer";
    285     return false;
    286   }
    287   if (!reader_.ConsumePaddingBits()) {
    288     DVLOG(1) << "padding bits are not zero";
    289     return false;
    290   }
    291   return true;
    292 }
    293 
    294 }  // namespace media
    295