static void tokenize_b(int plane, int block, BLOCK_SIZE_TYPE plane_bsize, TX_SIZE tx_size, void *arg) { struct tokenize_b_args* const args = arg; VP9_COMP *cpi = args->cpi; MACROBLOCKD *xd = args->xd; TOKENEXTRA **tp = args->tp; struct macroblockd_plane *pd = &xd->plane[plane]; MB_MODE_INFO *mbmi = &xd->mode_info_context->mbmi; int pt; /* near block/prev token context index */ int c = 0, rc = 0; TOKENEXTRA *t = *tp; /* store tokens starting here */ const int eob = pd->eobs[block]; const PLANE_TYPE type = pd->plane_type; const int16_t *qcoeff_ptr = BLOCK_OFFSET(pd->qcoeff, block); int seg_eob; const int segment_id = mbmi->segment_id; const int16_t *scan, *nb; vp9_coeff_count *const counts = cpi->coef_counts[tx_size]; vp9_coeff_probs_model *const coef_probs = cpi->common.fc.coef_probs[tx_size]; const int ref = is_inter_block(mbmi); ENTROPY_CONTEXT above_ec, left_ec; uint8_t token_cache[1024]; const uint8_t *band_translate; ENTROPY_CONTEXT *A, *L; int aoff, loff; txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &aoff, &loff); A = pd->above_context + aoff; L = pd->left_context + loff; assert((!type && !plane) || (type && plane)); switch (tx_size) { case TX_4X4: above_ec = A[0] != 0; left_ec = L[0] != 0; seg_eob = 16; scan = get_scan_4x4(get_tx_type_4x4(type, xd, block)); band_translate = vp9_coefband_trans_4x4; break; case TX_8X8: above_ec = !!*(uint16_t *)A; left_ec = !!*(uint16_t *)L; seg_eob = 64; scan = get_scan_8x8(get_tx_type_8x8(type, xd)); band_translate = vp9_coefband_trans_8x8plus; break; case TX_16X16: above_ec = !!*(uint32_t *)A; left_ec = !!*(uint32_t *)L; seg_eob = 256; scan = get_scan_16x16(get_tx_type_16x16(type, xd)); band_translate = vp9_coefband_trans_8x8plus; break; case TX_32X32: above_ec = !!*(uint64_t *)A; left_ec = !!*(uint64_t *)L; seg_eob = 1024; scan = vp9_default_scan_32x32; band_translate = vp9_coefband_trans_8x8plus; break; default: assert(!"Invalid transform size"); } pt = combine_entropy_contexts(above_ec, left_ec); nb = vp9_get_coef_neighbors_handle(scan); if (vp9_segfeature_active(&cpi->common.seg, segment_id, SEG_LVL_SKIP)) seg_eob = 0; c = 0; do { const int band = get_coef_band(band_translate, c); int token; int v = 0; rc = scan[c]; if (c) pt = get_coef_context(nb, token_cache, c); if (c < eob) { v = qcoeff_ptr[rc]; assert(-DCT_MAX_VALUE <= v && v < DCT_MAX_VALUE); t->extra = vp9_dct_value_tokens_ptr[v].extra; token = vp9_dct_value_tokens_ptr[v].token; } else { token = DCT_EOB_TOKEN; } t->token = token; t->context_tree = coef_probs[type][ref][band][pt]; t->skip_eob_node = (c > 0) && (token_cache[scan[c - 1]] == 0); assert(vp9_coef_encodings[t->token].len - t->skip_eob_node > 0); ++counts[type][ref][band][pt][token]; if (!t->skip_eob_node) ++cpi->common.counts.eob_branch[tx_size][type][ref][band][pt]; token_cache[rc] = vp9_pt_energy_class[token]; ++t; } while (c < eob && ++c < seg_eob); *tp = t; set_contexts(xd, pd, plane_bsize, tx_size, c > 0, aoff, loff); }
static int decode_coefs(VP9_COMMON *cm, const MACROBLOCKD *xd, vp9_reader *r, int block_idx, PLANE_TYPE type, int seg_eob, int16_t *qcoeff_ptr, TX_SIZE tx_size, const int16_t *dq, int pt) { const FRAME_CONTEXT *const fc = &cm->fc; FRAME_COUNTS *const counts = &cm->counts; const int ref = is_inter_block(&xd->mi_8x8[0]->mbmi); int band, c = 0; const vp9_prob (*coef_probs)[PREV_COEF_CONTEXTS][UNCONSTRAINED_NODES] = fc->coef_probs[tx_size][type][ref]; vp9_prob coef_probs_full[COEF_BANDS][PREV_COEF_CONTEXTS][ENTROPY_NODES]; uint8_t load_map[COEF_BANDS][PREV_COEF_CONTEXTS] = { { 0 } }; const vp9_prob *prob; vp9_coeff_count_model *coef_counts = counts->coef[tx_size]; const int16_t *scan, *nb; const uint8_t *const band_translate = get_band_translate(tx_size); uint8_t token_cache[1024]; get_scan(xd, tx_size, type, block_idx, &scan, &nb); while (1) { int val; const uint8_t *cat6 = cat6_prob; if (c >= seg_eob) break; if (c) pt = get_coef_context(nb, token_cache, c); band = get_coef_band(band_translate, c); prob = coef_probs[band][pt]; if (!cm->frame_parallel_decoding_mode) ++counts->eob_branch[tx_size][type][ref][band][pt]; if (!vp9_read(r, prob[EOB_CONTEXT_NODE])) break; SKIP_START: if (c >= seg_eob) break; if (c) pt = get_coef_context(nb, token_cache, c); band = get_coef_band(band_translate, c); prob = coef_probs[band][pt]; if (!vp9_read(r, prob[ZERO_CONTEXT_NODE])) { INCREMENT_COUNT(ZERO_TOKEN); ++c; goto SKIP_START; } // ONE_CONTEXT_NODE_0_ if (!vp9_read(r, prob[ONE_CONTEXT_NODE])) { WRITE_COEF_CONTINUE(1, ONE_TOKEN); } // Load full probabilities if not already loaded if (!load_map[band][pt]) { vp9_model_to_full_probs(coef_probs[band][pt], coef_probs_full[band][pt]); load_map[band][pt] = 1; } prob = coef_probs_full[band][pt]; // LOW_VAL_CONTEXT_NODE_0_ if (!vp9_read(r, prob[LOW_VAL_CONTEXT_NODE])) { if (!vp9_read(r, prob[TWO_CONTEXT_NODE])) { WRITE_COEF_CONTINUE(2, TWO_TOKEN); } if (!vp9_read(r, prob[THREE_CONTEXT_NODE])) { WRITE_COEF_CONTINUE(3, THREE_TOKEN); } WRITE_COEF_CONTINUE(4, FOUR_TOKEN); } // HIGH_LOW_CONTEXT_NODE_0_ if (!vp9_read(r, prob[HIGH_LOW_CONTEXT_NODE])) { if (!vp9_read(r, prob[CAT_ONE_CONTEXT_NODE])) { val = CAT1_MIN_VAL; ADJUST_COEF(CAT1_PROB0, 0); WRITE_COEF_CONTINUE(val, DCT_VAL_CATEGORY1); } val = CAT2_MIN_VAL; ADJUST_COEF(CAT2_PROB1, 1); ADJUST_COEF(CAT2_PROB0, 0); WRITE_COEF_CONTINUE(val, DCT_VAL_CATEGORY2); } // CAT_THREEFOUR_CONTEXT_NODE_0_ if (!vp9_read(r, prob[CAT_THREEFOUR_CONTEXT_NODE])) { if (!vp9_read(r, prob[CAT_THREE_CONTEXT_NODE])) { val = CAT3_MIN_VAL; ADJUST_COEF(CAT3_PROB2, 2); ADJUST_COEF(CAT3_PROB1, 1); ADJUST_COEF(CAT3_PROB0, 0); WRITE_COEF_CONTINUE(val, DCT_VAL_CATEGORY3); } val = CAT4_MIN_VAL; ADJUST_COEF(CAT4_PROB3, 3); ADJUST_COEF(CAT4_PROB2, 2); ADJUST_COEF(CAT4_PROB1, 1); ADJUST_COEF(CAT4_PROB0, 0); WRITE_COEF_CONTINUE(val, DCT_VAL_CATEGORY4); } // CAT_FIVE_CONTEXT_NODE_0_: if (!vp9_read(r, prob[CAT_FIVE_CONTEXT_NODE])) { val = CAT5_MIN_VAL; ADJUST_COEF(CAT5_PROB4, 4); ADJUST_COEF(CAT5_PROB3, 3); ADJUST_COEF(CAT5_PROB2, 2); ADJUST_COEF(CAT5_PROB1, 1); ADJUST_COEF(CAT5_PROB0, 0); WRITE_COEF_CONTINUE(val, DCT_VAL_CATEGORY5); } val = 0; while (*cat6) { val = (val << 1) | vp9_read(r, *cat6++); } val += CAT6_MIN_VAL; WRITE_COEF_CONTINUE(val, DCT_VAL_CATEGORY6); } if (c < seg_eob) { if (!cm->frame_parallel_decoding_mode) ++coef_counts[type][ref][band][pt][DCT_EOB_MODEL_TOKEN]; } return c; }