int vp9_decode_block_tokens(MACROBLOCKD *xd, int plane, const scan_order *sc, int x, int y, TX_SIZE tx_size, vpx_reader *r, int seg_id) { struct macroblockd_plane *const pd = &xd->plane[plane]; const int16_t *const dequant = pd->seg_dequant[seg_id]; int eob; ENTROPY_CONTEXT *a = pd->above_context + x; ENTROPY_CONTEXT *l = pd->left_context + y; int ctx; int ctx_shift_a = 0; int ctx_shift_l = 0; switch (tx_size) { case TX_4X4: ctx = a[0] != 0; ctx += l[0] != 0; eob = decode_coefs(xd, get_plane_type(plane), pd->dqcoeff, tx_size, dequant, ctx, sc->scan, sc->neighbors, r); a[0] = l[0] = (eob > 0); break; case TX_8X8: get_ctx_shift(xd, &ctx_shift_a, &ctx_shift_l, x, y, 1 << TX_8X8); ctx = !!*(const uint16_t *)a; ctx += !!*(const uint16_t *)l; eob = decode_coefs(xd, get_plane_type(plane), pd->dqcoeff, tx_size, dequant, ctx, sc->scan, sc->neighbors, r); *(uint16_t *)a = ((eob > 0) * 0x0101) >> ctx_shift_a; *(uint16_t *)l = ((eob > 0) * 0x0101) >> ctx_shift_l; break; case TX_16X16: get_ctx_shift(xd, &ctx_shift_a, &ctx_shift_l, x, y, 1 << TX_16X16); ctx = !!*(const uint32_t *)a; ctx += !!*(const uint32_t *)l; eob = decode_coefs(xd, get_plane_type(plane), pd->dqcoeff, tx_size, dequant, ctx, sc->scan, sc->neighbors, r); *(uint32_t *)a = ((eob > 0) * 0x01010101) >> ctx_shift_a; *(uint32_t *)l = ((eob > 0) * 0x01010101) >> ctx_shift_l; break; case TX_32X32: get_ctx_shift(xd, &ctx_shift_a, &ctx_shift_l, x, y, 1 << TX_32X32); // NOTE: casting to uint64_t here is safe because the default memory // alignment is at least 8 bytes and the TX_32X32 is aligned on 8 byte // boundaries. ctx = !!*(const uint64_t *)a; ctx += !!*(const uint64_t *)l; eob = decode_coefs(xd, get_plane_type(plane), pd->dqcoeff, tx_size, dequant, ctx, sc->scan, sc->neighbors, r); *(uint64_t *)a = ((eob > 0) * 0x0101010101010101ULL) >> ctx_shift_a; *(uint64_t *)l = ((eob > 0) * 0x0101010101010101ULL) >> ctx_shift_l; break; default: assert(0 && "Invalid transform size."); eob = 0; break; } return eob; }
int vp9_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]); vp9_token_state tokens[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 = get_plane_type(plane); const int default_eob = 16 << (tx_size << 1); const int shift = (tx_size == TX_32X32); const int16_t *const dequant_ptr = pd->dequant; const uint8_t *const band_translate = get_band_translate(tx_size); const scan_order *const so = get_scan(xd, tx_size, type, block); const int16_t *const scan = so->scan; const int16_t *const nb = so->neighbors; const int dq_step[2] = { dequant_ptr[0] >> shift, dequant_ptr[1] >> shift };
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]); vp9_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 = get_plane_type(plane); 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); const scan_order *const so = get_scan(xd, tx_size, type, block); 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 int *cat6_high_cost = vp9_get_high_cost_table(xd->bd); #else const int *cat6_high_cost = vp9_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]] = vp9_pt_energy_class[vp9_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; vp9_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 = vp9_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 { vp9_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 = vp9_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 row, int col, BLOCK_SIZE plane_bsize, TX_SIZE tx_size, void *arg) { struct tokenize_b_args *const args = arg; VP9_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]; MODE_INFO *mi = xd->mi[0]; 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 = get_plane_type(plane); const tran_low_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block); const int16_t *scan, *nb; const scan_order *so; const int ref = is_inter_block(mi); 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 tx_eob = 16 << (tx_size << 1); int16_t token; EXTRABIT extra; pt = get_entropy_context(tx_size, pd->above_context + col, pd->left_context + row); so = get_scan(xd, tx_size, type, block); scan = so->scan; nb = so->neighbors; c = 0; while (c < eob) { int v = 0; v = qcoeff[scan[c]]; ++eob_branch[band[c]][pt]; while (!v) { add_token_no_extra(&t, coef_probs[band[c]][pt], ZERO_TOKEN, counts[band[c]][pt]); token_cache[scan[c]] = 0; ++c; pt = get_coef_context(nb, token_cache, c); v = qcoeff[scan[c]]; } vp9_get_token_extra(v, &token, &extra); add_token(&t, coef_probs[band[c]][pt], token, extra, counts[band[c]][pt]); token_cache[scan[c]] = vp9_pt_energy_class[token]; ++c; pt = get_coef_context(nb, token_cache, c); } if (c < tx_eob) { ++eob_branch[band[c]][pt]; add_token_no_extra(&t, coef_probs[band[c]][pt], EOB_TOKEN, counts[band[c]][pt]); } *tp = t; vp9_set_contexts(xd, pd, plane_bsize, tx_size, c > 0, col, row); }