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