void vp9_inverse_transform_mby_8x8(MACROBLOCKD *xd) { int i; BLOCKD *blockd = xd->block; int has_2nd_order = get_2nd_order_usage(xd); if (has_2nd_order) { // do 2nd order transform on the dc block vp9_short_ihaar2x2(blockd[24].dqcoeff, blockd[24].diff, 8); recon_dcblock_8x8(xd); // need to change for 8x8 } for (i = 0; i < 9; i += 8) { TX_TYPE tx_type = get_tx_type_8x8(xd, &xd->block[i]); if (tx_type != DCT_DCT) { vp9_ihtllm(xd->block[i].dqcoeff, xd->block[i].diff, 32, tx_type, 8, xd->block[i].eob); } else { vp9_inverse_transform_b_8x8(&blockd[i].dqcoeff[0], &blockd[i].diff[0], 32); } } for (i = 2; i < 11; i += 8) { TX_TYPE tx_type = get_tx_type_8x8(xd, &xd->block[i]); if (tx_type != DCT_DCT) { vp9_ihtllm(xd->block[i + 2].dqcoeff, xd->block[i].diff, 32, tx_type, 8, xd->block[i + 2].eob); } else { vp9_inverse_transform_b_8x8(&blockd[i + 2].dqcoeff[0], &blockd[i].diff[0], 32); } } }
static void decode_block(int plane, int block, BLOCK_SIZE_TYPE bsize, int ss_txfrm_size, void *arg) { MACROBLOCKD* const xd = arg; struct macroblockd_plane *pd = &xd->plane[plane]; int16_t* const qcoeff = BLOCK_OFFSET(pd->qcoeff, block, 16); const int stride = pd->dst.stride; const int raster_block = txfrm_block_to_raster_block(xd, bsize, plane, block, ss_txfrm_size); uint8_t* const dst = raster_block_offset_uint8(xd, bsize, plane, raster_block, pd->dst.buf, stride); TX_TYPE tx_type; switch (ss_txfrm_size / 2) { case TX_4X4: tx_type = plane == 0 ? get_tx_type_4x4(xd, raster_block) : DCT_DCT; if (tx_type == DCT_DCT) xd->itxm_add(qcoeff, dst, stride, pd->eobs[block]); else vp9_iht_add_c(tx_type, qcoeff, dst, stride, pd->eobs[block]); break; case TX_8X8: tx_type = plane == 0 ? get_tx_type_8x8(xd, raster_block) : DCT_DCT; vp9_iht_add_8x8_c(tx_type, qcoeff, dst, stride, pd->eobs[block]); break; case TX_16X16: tx_type = plane == 0 ? get_tx_type_16x16(xd, raster_block) : DCT_DCT; vp9_iht_add_16x16_c(tx_type, qcoeff, dst, stride, pd->eobs[block]); break; case TX_32X32: vp9_idct_add_32x32(qcoeff, dst, stride, pd->eobs[block]); break; } }
void vp9_encode_intra8x8(MACROBLOCK *x, int ib) { MACROBLOCKD *xd = &x->e_mbd; BLOCKD *b = &xd->block[ib]; BLOCK *be = &x->block[ib]; const int iblock[4] = {0, 1, 4, 5}; int i; TX_TYPE tx_type; #if CONFIG_COMP_INTRA_PRED if (b->bmi.as_mode.second == (MB_PREDICTION_MODE)(DC_PRED - 1)) { #endif vp9_intra8x8_predict(b, b->bmi.as_mode.first, b->predictor); #if CONFIG_COMP_INTRA_PRED } else { vp9_comp_intra8x8_predict(b, b->bmi.as_mode.first, b->bmi.as_mode.second, b->predictor); } #endif // generate residual blocks vp9_subtract_4b_c(be, b, 16); if (xd->mode_info_context->mbmi.txfm_size == TX_8X8) { int idx = (ib & 0x02) ? (ib + 2) : ib; tx_type = get_tx_type_8x8(xd, &xd->block[ib]); if (tx_type != DCT_DCT) { vp9_fht(be->src_diff, 32, (x->block + idx)->coeff, tx_type, 8); x->quantize_b_8x8(x->block + idx, xd->block + idx); vp9_ihtllm(xd->block[idx].dqcoeff, xd->block[ib].diff, 32, tx_type, 8, xd->block[idx].eob); } else { x->vp9_short_fdct8x8(be->src_diff, (x->block + idx)->coeff, 32); x->quantize_b_8x8(x->block + idx, xd->block + idx); vp9_short_idct8x8(xd->block[idx].dqcoeff, xd->block[ib].diff, 32); } } else { for (i = 0; i < 4; i++) { b = &xd->block[ib + iblock[i]]; be = &x->block[ib + iblock[i]]; tx_type = get_tx_type_4x4(xd, b); if (tx_type != DCT_DCT) { vp9_fht_c(be->src_diff, 32, be->coeff, tx_type, 4); vp9_ht_quantize_b_4x4(be, b, tx_type); vp9_ihtllm(b->dqcoeff, b->diff, 32, tx_type, 4, b->eob); } else { x->vp9_short_fdct4x4(be->src_diff, be->coeff, 32); x->quantize_b_4x4(be, b); vp9_inverse_transform_b_4x4(xd, ib + iblock[i], 32); } } } // reconstruct submacroblock for (i = 0; i < 4; i++) { b = &xd->block[ib + iblock[i]]; vp9_recon_b_c(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride); } }
void vp9_transform_mby_8x8(MACROBLOCK *x) { int i; MACROBLOCKD *xd = &x->e_mbd; TX_TYPE tx_type; int has_2nd_order = get_2nd_order_usage(xd); for (i = 0; i < 9; i += 8) { BLOCK *b = &x->block[i]; tx_type = get_tx_type_8x8(xd, &xd->block[i]); if (tx_type != DCT_DCT) { assert(has_2nd_order == 0); vp9_fht_c(b->src_diff, 32, b->coeff, tx_type, 8); } else { x->vp9_short_fdct8x8(&x->block[i].src_diff[0], &x->block[i].coeff[0], 32); } } for (i = 2; i < 11; i += 8) { BLOCK *b = &x->block[i]; tx_type = get_tx_type_8x8(xd, &xd->block[i]); if (tx_type != DCT_DCT) { assert(has_2nd_order == 0); vp9_fht_c(b->src_diff, 32, (b + 2)->coeff, tx_type, 8); } else { x->vp9_short_fdct8x8(&x->block[i].src_diff[0], &x->block[i + 2].coeff[0], 32); } } if (has_2nd_order) { // build dc block from 2x2 y dc values build_dcblock_8x8(x); // do 2nd order transform on the dc block x->short_fhaar2x2(&x->block[24].src_diff[0], &x->block[24].coeff[0], 8); } else { vpx_memset(x->block[24].coeff, 0, 16 * sizeof(x->block[24].coeff[0])); } }
static void inverse_transform_block(MACROBLOCKD* xd, int plane, int block, BLOCK_SIZE plane_bsize, TX_SIZE tx_size) { struct macroblockd_plane *const pd = &xd->plane[plane]; int16_t* const qcoeff = BLOCK_OFFSET(pd->qcoeff, block); const int stride = pd->dst.stride; const int eob = pd->eobs[block]; if (eob > 0) { TX_TYPE tx_type; const int raster_block = txfrm_block_to_raster_block(plane_bsize, tx_size, block); uint8_t* const dst = raster_block_offset_uint8(plane_bsize, raster_block, pd->dst.buf, stride); switch (tx_size) { case TX_4X4: tx_type = get_tx_type_4x4(pd->plane_type, xd, raster_block); if (tx_type == DCT_DCT) xd->itxm_add(qcoeff, dst, stride, eob); else vp9_iht4x4_add(tx_type, qcoeff, dst, stride, eob); break; case TX_8X8: tx_type = get_tx_type_8x8(pd->plane_type, xd); vp9_iht8x8_add(tx_type, qcoeff, dst, stride, eob); break; case TX_16X16: tx_type = get_tx_type_16x16(pd->plane_type, xd); vp9_iht16x16_add(tx_type, qcoeff, dst, stride, eob); break; case TX_32X32: tx_type = DCT_DCT; vp9_idct32x32_add(qcoeff, dst, stride, eob); break; default: assert(!"Invalid transform size"); } if (eob == 1) { vpx_memset(qcoeff, 0, 2 * sizeof(qcoeff[0])); } else { if (tx_type == DCT_DCT && tx_size <= TX_16X16 && eob <= 10) vpx_memset(qcoeff, 0, 4 * (4 << tx_size) * sizeof(qcoeff[0])); else vpx_memset(qcoeff, 0, (16 << (tx_size << 1)) * sizeof(qcoeff[0])); } } }
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 void encode_block_intra(int plane, int block, BLOCK_SIZE plane_bsize, TX_SIZE tx_size, void *arg) { struct encode_b_args* const args = arg; MACROBLOCK *const x = args->x; MACROBLOCKD *const xd = &x->e_mbd; MB_MODE_INFO *mbmi = &xd->mi_8x8[0]->mbmi; struct macroblock_plane *const p = &x->plane[plane]; struct macroblockd_plane *const pd = &xd->plane[plane]; int16_t *coeff = BLOCK_OFFSET(p->coeff, block); int16_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block); int16_t *dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block); const scan_order *scan_order; TX_TYPE tx_type; MB_PREDICTION_MODE mode; const int bwl = b_width_log2(plane_bsize); const int diff_stride = 4 * (1 << bwl); uint8_t *src, *dst; int16_t *src_diff; uint16_t *eob = &p->eobs[block]; const int src_stride = p->src.stride; const int dst_stride = pd->dst.stride; int i, j; txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &i, &j); dst = &pd->dst.buf[4 * (j * dst_stride + i)]; src = &p->src.buf[4 * (j * src_stride + i)]; src_diff = &p->src_diff[4 * (j * diff_stride + i)]; // if (x->optimize) // optimize_b(plane, block, plane_bsize, tx_size, x, args->ctx); switch (tx_size) { case TX_32X32: scan_order = &vp9_default_scan_orders[TX_32X32]; mode = plane == 0 ? mbmi->mode : mbmi->uv_mode; vp9_predict_intra_block(xd, block >> 6, bwl, TX_32X32, mode, x->skip_encode ? src : dst, x->skip_encode ? src_stride : dst_stride, dst, dst_stride, i, j, plane); if (!x->skip_recode) { vp9_subtract_block(32, 32, src_diff, diff_stride, src, src_stride, dst, dst_stride); fdct32x32(x->use_lp32x32fdct, src_diff, coeff, diff_stride); vp9_quantize_b_32x32(coeff, 1024, x->skip_block, p->zbin, p->round, p->quant, p->quant_shift, qcoeff, dqcoeff, pd->dequant, p->zbin_extra, eob, scan_order->scan, scan_order->iscan); } if (!x->skip_encode && *eob) vp9_idct32x32_add(dqcoeff, dst, dst_stride, *eob); break; case TX_16X16: tx_type = get_tx_type_16x16(pd->plane_type, xd); scan_order = &vp9_scan_orders[TX_16X16][tx_type]; mode = plane == 0 ? mbmi->mode : mbmi->uv_mode; vp9_predict_intra_block(xd, block >> 4, bwl, TX_16X16, mode, x->skip_encode ? src : dst, x->skip_encode ? src_stride : dst_stride, dst, dst_stride, i, j, plane); if (!x->skip_recode) { vp9_subtract_block(16, 16, src_diff, diff_stride, src, src_stride, dst, dst_stride); vp9_fht16x16(src_diff, coeff, diff_stride, tx_type); vp9_quantize_b(coeff, 256, x->skip_block, p->zbin, p->round, p->quant, p->quant_shift, qcoeff, dqcoeff, pd->dequant, p->zbin_extra, eob, scan_order->scan, scan_order->iscan); } if (!x->skip_encode && *eob) vp9_iht16x16_add(tx_type, dqcoeff, dst, dst_stride, *eob); break; case TX_8X8: tx_type = get_tx_type_8x8(pd->plane_type, xd); scan_order = &vp9_scan_orders[TX_8X8][tx_type]; mode = plane == 0 ? mbmi->mode : mbmi->uv_mode; vp9_predict_intra_block(xd, block >> 2, bwl, TX_8X8, mode, x->skip_encode ? src : dst, x->skip_encode ? src_stride : dst_stride, dst, dst_stride, i, j, plane); if (!x->skip_recode) { vp9_subtract_block(8, 8, src_diff, diff_stride, src, src_stride, dst, dst_stride); vp9_fht8x8(src_diff, coeff, diff_stride, tx_type); vp9_quantize_b(coeff, 64, x->skip_block, p->zbin, p->round, p->quant, p->quant_shift, qcoeff, dqcoeff, pd->dequant, p->zbin_extra, eob, scan_order->scan, scan_order->iscan); } if (!x->skip_encode && *eob) vp9_iht8x8_add(tx_type, dqcoeff, dst, dst_stride, *eob); break; case TX_4X4: tx_type = get_tx_type_4x4(pd->plane_type, xd, block); scan_order = &vp9_scan_orders[TX_4X4][tx_type]; mode = plane == 0 ? get_y_mode(xd->mi_8x8[0], block) : mbmi->uv_mode; vp9_predict_intra_block(xd, block, bwl, TX_4X4, mode, x->skip_encode ? src : dst, x->skip_encode ? src_stride : dst_stride, dst, dst_stride, i, j, plane); if (!x->skip_recode) { vp9_subtract_block(4, 4, src_diff, diff_stride, src, src_stride, dst, dst_stride); if (tx_type != DCT_DCT) vp9_fht4x4(src_diff, coeff, diff_stride, tx_type); else x->fwd_txm4x4(src_diff, coeff, diff_stride); vp9_quantize_b(coeff, 16, x->skip_block, p->zbin, p->round, p->quant, p->quant_shift, qcoeff, dqcoeff, pd->dequant, p->zbin_extra, eob, scan_order->scan, scan_order->iscan); } if (!x->skip_encode && *eob) { if (tx_type == DCT_DCT) // this is like vp9_short_idct4x4 but has a special case around eob<=1 // which is significant (not just an optimization) for the lossless // case. xd->itxm_add(dqcoeff, dst, dst_stride, *eob); else vp9_iht4x4_16_add(dqcoeff, dst, dst_stride, tx_type); } break; default: assert(0); } if (*eob) *(args->skip) = 0; }