static int optimize_b(MACROBLOCK *mb, int plane, int block, TX_SIZE tx_size, int ctx) { MACROBLOCKD *const xd = &mb->e_mbd; struct macroblock_plane *const p = &mb->plane[plane]; struct macroblockd_plane *const pd = &xd->plane[plane]; const int ref = is_inter_block(&xd->mi[0]->mbmi); vp10_token_state tokens[1025][2]; unsigned best_index[1025][2]; uint8_t token_cache[1024]; const tran_low_t *const coeff = BLOCK_OFFSET(mb->plane[plane].coeff, block); tran_low_t *const qcoeff = BLOCK_OFFSET(p->qcoeff, block); tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block); const int eob = p->eobs[block]; const PLANE_TYPE type = pd->plane_type; const int default_eob = 16 << (tx_size << 1); const int mul = 1 + (tx_size == TX_32X32); const int16_t *dequant_ptr = pd->dequant; const uint8_t *const band_translate = get_band_translate(tx_size); TX_TYPE tx_type = get_tx_type(type, xd, block); const scan_order *const so = get_scan(tx_size, tx_type); const int16_t *const scan = so->scan; const int16_t *const nb = so->neighbors; int next = eob, sz = 0; int64_t rdmult = mb->rdmult * plane_rd_mult[type], rddiv = mb->rddiv; int64_t rd_cost0, rd_cost1; int rate0, rate1, error0, error1; int16_t t0, t1; EXTRABIT e0; int best, band, pt, i, final_eob; #if CONFIG_VP9_HIGHBITDEPTH const int16_t *cat6_high_cost = vp10_get_high_cost_table(xd->bd); #else const int16_t *cat6_high_cost = vp10_get_high_cost_table(8); #endif assert((!type && !plane) || (type && plane)); assert(eob <= default_eob); /* Now set up a Viterbi trellis to evaluate alternative roundings. */ if (!ref) rdmult = (rdmult * 9) >> 4; /* Initialize the sentinel node of the trellis. */ tokens[eob][0].rate = 0; tokens[eob][0].error = 0; tokens[eob][0].next = default_eob; tokens[eob][0].token = EOB_TOKEN; tokens[eob][0].qc = 0; tokens[eob][1] = tokens[eob][0]; for (i = 0; i < eob; i++) token_cache[scan[i]] = vp10_pt_energy_class[vp10_get_token(qcoeff[scan[i]])]; for (i = eob; i-- > 0;) { int base_bits, d2, dx; const int rc = scan[i]; int x = qcoeff[rc]; /* Only add a trellis state for non-zero coefficients. */ if (x) { int shortcut = 0; error0 = tokens[next][0].error; error1 = tokens[next][1].error; /* Evaluate the first possibility for this state. */ rate0 = tokens[next][0].rate; rate1 = tokens[next][1].rate; vp10_get_token_extra(x, &t0, &e0); /* Consider both possible successor states. */ if (next < default_eob) { band = band_translate[i + 1]; pt = trellis_get_coeff_context(scan, nb, i, t0, token_cache); rate0 += mb->token_costs[tx_size][type][ref][band][0][pt] [tokens[next][0].token]; rate1 += mb->token_costs[tx_size][type][ref][band][0][pt] [tokens[next][1].token]; } UPDATE_RD_COST(); /* And pick the best. */ best = rd_cost1 < rd_cost0; base_bits = vp10_get_cost(t0, e0, cat6_high_cost); dx = mul * (dqcoeff[rc] - coeff[rc]); #if CONFIG_VP9_HIGHBITDEPTH if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) { dx >>= xd->bd - 8; } #endif // CONFIG_VP9_HIGHBITDEPTH d2 = dx * dx; tokens[i][0].rate = base_bits + (best ? rate1 : rate0); tokens[i][0].error = d2 + (best ? error1 : error0); tokens[i][0].next = next; tokens[i][0].token = t0; tokens[i][0].qc = x; best_index[i][0] = best; /* Evaluate the second possibility for this state. */ rate0 = tokens[next][0].rate; rate1 = tokens[next][1].rate; if ((abs(x) * dequant_ptr[rc != 0] > abs(coeff[rc]) * mul) && (abs(x) * dequant_ptr[rc != 0] < abs(coeff[rc]) * mul + dequant_ptr[rc != 0])) shortcut = 1; else shortcut = 0; if (shortcut) { sz = -(x < 0); x -= 2 * sz + 1; } /* Consider both possible successor states. */ if (!x) { /* If we reduced this coefficient to zero, check to see if * we need to move the EOB back here. */ t0 = tokens[next][0].token == EOB_TOKEN ? EOB_TOKEN : ZERO_TOKEN; t1 = tokens[next][1].token == EOB_TOKEN ? EOB_TOKEN : ZERO_TOKEN; e0 = 0; } else { vp10_get_token_extra(x, &t0, &e0); t1 = t0; } if (next < default_eob) { band = band_translate[i + 1]; if (t0 != EOB_TOKEN) { pt = trellis_get_coeff_context(scan, nb, i, t0, token_cache); rate0 += mb->token_costs[tx_size][type][ref][band][!x][pt] [tokens[next][0].token]; } if (t1 != EOB_TOKEN) { pt = trellis_get_coeff_context(scan, nb, i, t1, token_cache); rate1 += mb->token_costs[tx_size][type][ref][band][!x][pt] [tokens[next][1].token]; } } UPDATE_RD_COST(); /* And pick the best. */ best = rd_cost1 < rd_cost0; base_bits = vp10_get_cost(t0, e0, cat6_high_cost); if (shortcut) { #if CONFIG_VP9_HIGHBITDEPTH if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) { dx -= ((dequant_ptr[rc != 0] >> (xd->bd - 8)) + sz) ^ sz; } else { dx -= (dequant_ptr[rc != 0] + sz) ^ sz; } #else dx -= (dequant_ptr[rc != 0] + sz) ^ sz; #endif // CONFIG_VP9_HIGHBITDEPTH d2 = dx * dx; }
static void tokenize_b(int plane, int block, int blk_row, int blk_col, BLOCK_SIZE plane_bsize, TX_SIZE tx_size, void *arg) { struct tokenize_b_args* const args = arg; VP10_COMP *cpi = args->cpi; ThreadData *const td = args->td; MACROBLOCK *const x = &td->mb; MACROBLOCKD *const xd = &x->e_mbd; TOKENEXTRA **tp = args->tp; uint8_t token_cache[32 * 32]; struct macroblock_plane *p = &x->plane[plane]; struct macroblockd_plane *pd = &xd->plane[plane]; MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi; int pt; /* near block/prev token context index */ int c; TOKENEXTRA *t = *tp; /* store tokens starting here */ int eob = p->eobs[block]; const PLANE_TYPE type = pd->plane_type; const tran_low_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block); const int segment_id = mbmi->segment_id; const int16_t *scan, *nb; const TX_TYPE tx_type = get_tx_type(type, xd, block); const scan_order *const so = get_scan(tx_size, tx_type); const int ref = is_inter_block(mbmi); unsigned int (*const counts)[COEFF_CONTEXTS][ENTROPY_TOKENS] = td->rd_counts.coef_counts[tx_size][type][ref]; vpx_prob (*const coef_probs)[COEFF_CONTEXTS][UNCONSTRAINED_NODES] = cpi->common.fc->coef_probs[tx_size][type][ref]; unsigned int (*const eob_branch)[COEFF_CONTEXTS] = td->counts->eob_branch[tx_size][type][ref]; const uint8_t *const band = get_band_translate(tx_size); const int seg_eob = get_tx_eob(&cpi->common.seg, segment_id, tx_size); int16_t token; EXTRABIT extra; pt = get_entropy_context(tx_size, pd->above_context + blk_col, pd->left_context + blk_row); scan = so->scan; nb = so->neighbors; c = 0; while (c < eob) { int v = 0; int skip_eob = 0; v = qcoeff[scan[c]]; while (!v) { add_token_no_extra(&t, coef_probs[band[c]][pt], ZERO_TOKEN, skip_eob, counts[band[c]][pt]); eob_branch[band[c]][pt] += !skip_eob; skip_eob = 1; token_cache[scan[c]] = 0; ++c; pt = get_coef_context(nb, token_cache, c); v = qcoeff[scan[c]]; } vp10_get_token_extra(v, &token, &extra); add_token(&t, coef_probs[band[c]][pt], extra, (uint8_t)token, (uint8_t)skip_eob, counts[band[c]][pt]); eob_branch[band[c]][pt] += !skip_eob; token_cache[scan[c]] = vp10_pt_energy_class[token]; ++c; pt = get_coef_context(nb, token_cache, c); } if (c < seg_eob) { add_token_no_extra(&t, coef_probs[band[c]][pt], EOB_TOKEN, 0, counts[band[c]][pt]); ++eob_branch[band[c]][pt]; } *tp = t; vp10_set_contexts(xd, pd, plane_bsize, tx_size, c > 0, blk_col, blk_row); }