uint32_t VP8GetValue(VP8BitReader* const br, int bits) { uint32_t v = 0; while (bits-- > 0) { v |= VP8GetBit(br, 0x80) << bits; } return v; }
// Paragraph 9.9 void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec) { VP8Proba* const proba = &dec->proba_; int t, b, c, p; for (t = 0; t < NUM_TYPES; ++t) { for (b = 0; b < NUM_BANDS; ++b) { for (c = 0; c < NUM_CTX; ++c) { for (p = 0; p < NUM_PROBAS; ++p) { if (VP8GetBit(br, CoeffsUpdateProba[t][b][c][p])) { proba->coeffs_[t][b][c][p] = VP8GetValue(br, 8); } } } } } dec->use_skip_proba_ = VP8Get(br); if (dec->use_skip_proba_) { dec->skip_p_ = VP8GetValue(br, 8); } #ifndef ONLY_KEYFRAME_CODE if (!dec->frm_hdr_.key_frame_) { int i; dec->intra_p_ = VP8GetValue(br, 8); dec->last_p_ = VP8GetValue(br, 8); dec->golden_p_ = VP8GetValue(br, 8); if (VP8Get(br)) { // update y-mode for (i = 0; i < 4; ++i) { proba->ymode_[i] = VP8GetValue(br, 8); } } if (VP8Get(br)) { // update uv-mode for (i = 0; i < 3; ++i) { proba->uvmode_[i] = VP8GetValue(br, 8); } } // update MV for (i = 0; i < 2; ++i) { int k; for (k = 0; k < NUM_MV_PROBAS; ++k) { if (VP8GetBit(br, MVUpdateProba[i][k])) { const int v = VP8GetValue(br, 7); proba->mv_[i][k] = v ? v << 1 : 1; } } } } #endif }
// Paragraph 9.9 void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec) { VP8Proba* const proba = &dec->proba_; int t, b, c, p; for (t = 0; t < NUM_TYPES; ++t) { for (b = 0; b < NUM_BANDS; ++b) { for (c = 0; c < NUM_CTX; ++c) { for (p = 0; p < NUM_PROBAS; ++p) { const int v = VP8GetBit(br, CoeffsUpdateProba[t][b][c][p]) ? VP8GetValue(br, 8) : CoeffsProba0[t][b][c][p]; proba->bands_[t][b].probas_[c][p] = v; } } } } dec->use_skip_proba_ = VP8Get(br); if (dec->use_skip_proba_) { dec->skip_p_ = VP8GetValue(br, 8); } }
void VP8ParseIntraMode(VP8BitReader* const br, VP8Decoder* const dec) { uint8_t* const top = dec->intra_t_ + 4 * dec->mb_x_; uint8_t* const left = dec->intra_l_; VP8MBData* const block = dec->mb_data_ + dec->mb_x_; block->is_i4x4_ = !VP8GetBit(br, 145); // decide for B_PRED first if (!block->is_i4x4_) { // Hardcoded 16x16 intra-mode decision tree. const int ymode = VP8GetBit(br, 156) ? (VP8GetBit(br, 128) ? TM_PRED : H_PRED) : (VP8GetBit(br, 163) ? V_PRED : DC_PRED); block->imodes_[0] = ymode; memset(top, ymode, 4 * sizeof(*top)); memset(left, ymode, 4 * sizeof(*left)); } else { uint8_t* modes = block->imodes_; int y; for (y = 0; y < 4; ++y) { int ymode = left[y]; int x; for (x = 0; x < 4; ++x) { const uint8_t* const prob = kBModesProba[top[x]][ymode]; #ifdef USE_GENERIC_TREE // Generic tree-parsing int i = kYModesIntra4[VP8GetBit(br, prob[0])]; while (i > 0) { i = kYModesIntra4[2 * i + VP8GetBit(br, prob[i])]; } ymode = -i; #else // Hardcoded tree parsing ymode = !VP8GetBit(br, prob[0]) ? B_DC_PRED : !VP8GetBit(br, prob[1]) ? B_TM_PRED : !VP8GetBit(br, prob[2]) ? B_VE_PRED : !VP8GetBit(br, prob[3]) ? (!VP8GetBit(br, prob[4]) ? B_HE_PRED : (!VP8GetBit(br, prob[5]) ? B_RD_PRED : B_VR_PRED)) : (!VP8GetBit(br, prob[6]) ? B_LD_PRED : (!VP8GetBit(br, prob[7]) ? B_VL_PRED : (!VP8GetBit(br, prob[8]) ? B_HD_PRED : B_HU_PRED))); #endif // USE_GENERIC_TREE top[x] = ymode; } memcpy(modes, top, 4 * sizeof(*top)); modes += 4; left[y] = ymode; } } // Hardcoded UVMode decision tree block->uvmode_ = !VP8GetBit(br, 142) ? DC_PRED : !VP8GetBit(br, 114) ? V_PRED : VP8GetBit(br, 183) ? TM_PRED : H_PRED; }
static void ParseIntraMode(VP8BitReader* const br, VP8Decoder* const dec, int mb_x) { uint8_t* const top = dec->intra_t_ + 4 * mb_x; uint8_t* const left = dec->intra_l_; VP8MBData* const block = dec->mb_data_ + mb_x; // Note: we don't save segment map (yet), as we don't expect // to decode more than 1 keyframe. if (dec->segment_hdr_.update_map_) { // Hardcoded tree parsing block->segment_ = !VP8GetBit(br, dec->proba_.segments_[0]) ? VP8GetBit(br, dec->proba_.segments_[1]) : 2 + VP8GetBit(br, dec->proba_.segments_[2]); } else { block->segment_ = 0; // default for intra } if (dec->use_skip_proba_) block->skip_ = VP8GetBit(br, dec->skip_p_); block->is_i4x4_ = !VP8GetBit(br, 145); // decide for B_PRED first if (!block->is_i4x4_) { // Hardcoded 16x16 intra-mode decision tree. const int ymode = VP8GetBit(br, 156) ? (VP8GetBit(br, 128) ? TM_PRED : H_PRED) : (VP8GetBit(br, 163) ? V_PRED : DC_PRED); block->imodes_[0] = ymode; memset(top, ymode, 4 * sizeof(*top)); memset(left, ymode, 4 * sizeof(*left)); } else { uint8_t* modes = block->imodes_; int y; for (y = 0; y < 4; ++y) { int ymode = left[y]; int x; for (x = 0; x < 4; ++x) { const uint8_t* const prob = kBModesProba[top[x]][ymode]; #ifdef USE_GENERIC_TREE // Generic tree-parsing int i = kYModesIntra4[VP8GetBit(br, prob[0])]; while (i > 0) { i = kYModesIntra4[2 * i + VP8GetBit(br, prob[i])]; } ymode = -i; #else // Hardcoded tree parsing ymode = !VP8GetBit(br, prob[0]) ? B_DC_PRED : !VP8GetBit(br, prob[1]) ? B_TM_PRED : !VP8GetBit(br, prob[2]) ? B_VE_PRED : !VP8GetBit(br, prob[3]) ? (!VP8GetBit(br, prob[4]) ? B_HE_PRED : (!VP8GetBit(br, prob[5]) ? B_RD_PRED : B_VR_PRED)) : (!VP8GetBit(br, prob[6]) ? B_LD_PRED : (!VP8GetBit(br, prob[7]) ? B_VL_PRED : (!VP8GetBit(br, prob[8]) ? B_HD_PRED : B_HU_PRED))); #endif // USE_GENERIC_TREE top[x] = ymode; } memcpy(modes, top, 4 * sizeof(*top)); modes += 4; left[y] = ymode; } } // Hardcoded UVMode decision tree block->uvmode_ = !VP8GetBit(br, 142) ? DC_PRED : !VP8GetBit(br, 114) ? V_PRED : VP8GetBit(br, 183) ? TM_PRED : H_PRED; }