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