}
#if CONFIG_TX_SKIP
-void vp9_tx_identity_add(const tran_low_t *input, uint8_t *dest,
- int stride, int bs, int shift) {
+void vp9_tx_identity_add_rect(const tran_low_t *input, uint8_t *dest,
+ int row, int col,
+ int stride_in, int stride_out, int shift) {
int r, c, temp;
- for (r = 0; r < bs; r++)
- for (c = 0; c < bs; c++) {
- temp = dest[r * stride + c] + (input[r * bs + c] >> shift);
- dest[r * stride + c] = clip_pixel(temp);
+ for (r = 0; r < row; r++)
+ for (c = 0; c < col; c++) {
+ temp = dest[r * stride_out + c] + (input[r * stride_in + c] >> shift);
+ dest[r * stride_out + c] = clip_pixel(temp);
}
}
+
+void vp9_tx_identity_add(const tran_low_t *input, uint8_t *dest,
+ int stride, int bs, int shift) {
+ vp9_tx_identity_add_rect(input, dest, bs, bs, bs, stride, shift);
+}
#endif
#if CONFIG_TX64X64
#endif // VP9_COMMON_VP9_IDCT_H_
#if CONFIG_TX_SKIP
+void vp9_tx_identity_add_rect(const tran_low_t *input, uint8_t *dest,
+ int row, int col, int stride_in,
+ int stride_out, int shift);
void vp9_tx_identity_add(const tran_low_t *input, uint8_t *dest,
int stride, int bs, int shift);
#endif
xd->plane[i].dequant = cm->uv_dequant[q_index];
}
+#if CONFIG_TX_SKIP
+static void vp9_intra_dpcm_add(tran_low_t *dqcoeff, uint8_t *dst, int stride,
+ PREDICTION_MODE mode, int bs, int shift) {
+ int r, c, temp;
+
+ switch (mode) {
+ case H_PRED:
+ for (r = 0; r < bs; r++) {
+ temp = dst[r * stride] + (dqcoeff[r * bs] >> shift);
+ dst[r * stride] = clip_pixel(temp);
+ }
+ for (r = 0; r < bs; r++)
+ for (c = 1; c < bs; c++) {
+ temp = dst[r * stride + c - 1] +
+ (dqcoeff[r * bs + c] >> shift);
+ dst[r * stride + c] = clip_pixel(temp);
+ }
+ break;
+ case V_PRED:
+ for (c = 0; c < bs; c++) {
+ temp = dst[c] + (dqcoeff[c] >> shift);
+ dst[c] = clip_pixel(temp);
+ }
+ for (r = 1; r < bs; r++)
+ for (c = 0; c < bs; c++) {
+ temp = dst[(r - 1) * stride + c] +
+ (dqcoeff[r * bs + c] >> shift);
+ dst[r * stride + c] = clip_pixel(temp);
+ }
+ break;
+ case TM_PRED:
+ for (c = 0; c < bs; c++) {
+ temp = dst[c] + (dqcoeff[c] >> shift);
+ dst[c] = clip_pixel(temp);
+ }
+ for (r = 1; r < bs; r++) {
+ temp = dst[r * stride] + (dqcoeff[r * bs] >> shift);
+ dst[r * stride] = clip_pixel(temp);
+ }
+ for (r = 1; r < bs; r++)
+ for (c = 1; c < bs; c++) {
+ temp = dst[stride * r + c - 1] + dst[stride * (r - 1) + c] -
+ dst[stride * (r - 1) + c - 1];
+ temp = clip_pixel(temp);
+ temp = temp + (dqcoeff[r * bs + c] >> shift);
+ dst[stride * r + c] = clip_pixel(temp);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void vp9_intra_dpcm_add_nocoeff(uint8_t *dst, int stride,
+ PREDICTION_MODE mode, int bs) {
+ int r, c, temp;
+
+ switch (mode) {
+ case H_PRED:
+ for (r = 0; r < bs; r++)
+ memset(dst + r * stride + 1, dst[r * stride], bs - 1);
+ break;
+ case V_PRED:
+ for (r = 1; r < bs; r++)
+ memcpy(dst + r * stride, dst, bs * sizeof(*dst));
+ break;
+ case TM_PRED:
+ for (r = 1; r < bs; r++)
+ for (c = 1; c < bs; c++) {
+ temp = dst[stride * r + c - 1] + dst[stride * (r - 1) + c] -
+ dst[stride * (r - 1) + c - 1];
+ dst[stride * r + c] = clip_pixel(temp);
+ }
+ break;
+ default:
+ break;
+ }
+}
+#endif // CONFIG_TX_SKIP
+
static void inverse_transform_block(MACROBLOCKD* xd, int plane, int block,
TX_SIZE tx_size, uint8_t *dst, int stride,
int eob) {
#if CONFIG_TX_SKIP
MB_MODE_INFO *mbmi = &xd->mi[0].src_mi->mbmi;
int shift = mbmi->tx_skip_shift;
+ PREDICTION_MODE mode = (plane == 0) ? get_y_mode(xd->mi[0].src_mi, block):
+ mbmi->uv_mode;
#endif
if (eob > 0) {
TX_TYPE tx_type = DCT_DCT;
tx_type = get_tx_type_4x4(plane_type, xd, block);
#if CONFIG_TX_SKIP
if (mbmi->tx_skip[plane != 0]) {
- vp9_tx_identity_add(dqcoeff, dst, stride, 4, shift);
+ if (mode == V_PRED || mode == H_PRED || mode == TM_PRED)
+ vp9_intra_dpcm_add(dqcoeff, dst, stride, mode, 4, shift);
+ else
+ vp9_tx_identity_add(dqcoeff, dst, stride, 4, shift);
} else {
vp9_iht4x4_add(tx_type, dqcoeff, dst, stride, eob);
}
tx_type = get_tx_type(plane_type, xd);
#if CONFIG_TX_SKIP
if (mbmi->tx_skip[plane != 0]) {
- vp9_tx_identity_add(dqcoeff, dst, stride, 8, shift);
+ if (mode == V_PRED || mode == H_PRED || mode == TM_PRED)
+ vp9_intra_dpcm_add(dqcoeff, dst, stride, mode, 8, shift);
+ else
+ vp9_tx_identity_add(dqcoeff, dst, stride, 8, shift);
} else {
vp9_iht8x8_add(tx_type, dqcoeff, dst, stride, eob);
}
tx_type = get_tx_type(plane_type, xd);
#if CONFIG_TX_SKIP
if (mbmi->tx_skip[plane != 0]) {
- vp9_tx_identity_add(dqcoeff, dst, stride, 16, shift);
+ if (mode == V_PRED || mode == H_PRED || mode == TM_PRED)
+ vp9_intra_dpcm_add(dqcoeff, dst, stride, mode, 16, shift);
+ else
+ vp9_tx_identity_add(dqcoeff, dst, stride, 16, shift);
} else {
vp9_iht16x16_add(tx_type, dqcoeff, dst, stride, eob);
}
tx_type = DCT_DCT;
#if CONFIG_TX_SKIP
if (mbmi->tx_skip[plane != 0]) {
- vp9_tx_identity_add(dqcoeff, dst, stride, 32, shift);
+ if (mode == V_PRED || mode == H_PRED || mode == TM_PRED)
+ vp9_intra_dpcm_add(dqcoeff, dst, stride, mode, 32, shift);
+ else
+ vp9_tx_identity_add(dqcoeff, dst, stride, 32, shift);
} else {
vp9_idct32x32_add(dqcoeff, dst, stride, eob);;
}
: mi->mbmi.uv_mode;
int x, y;
uint8_t *dst;
+#if CONFIG_TX_SKIP
+ int no_coeff = 0;
+#endif
#if CONFIG_FILTERINTRA
int fbit;
if (plane == 0)
args->r);
inverse_transform_block(xd, plane, block, tx_size, dst, pd->dst.stride,
eob);
+#if CONFIG_TX_SKIP
+ no_coeff = !eob;
+#endif
+ }
+
+#if CONFIG_TX_SKIP
+ if ((mi->mbmi.skip || no_coeff) && mi->mbmi.tx_skip[plane != 0] &&
+ mode == TM_PRED && tx_size <= TX_32X32) {
+ int bs = 4 * (1 << tx_size);
+ vp9_intra_dpcm_add_nocoeff(dst, pd->dst.stride, mode, bs);
}
+#endif
+
+#if CONFIG_TX_SKIP && CONFIG_FILTERINTRA
+ if ((mi->mbmi.skip || no_coeff) && mi->mbmi.tx_skip[plane != 0] &&
+ (mode == H_PRED || mode == V_PRED) && fbit) {
+ int bs = 4 * (1 << tx_size);
+ vp9_intra_dpcm_add_nocoeff(dst, pd->dst.stride, mode, bs);
+ }
+#endif
}
struct inter_args {
xd->corrupted |= !assign_mv(cm, mbmi->mode, mbmi->mv, nearestmv,
nearestmv, nearmv, is_compound, allow_hp, r);
}
+#if CONFIG_TX_SKIP
+ mbmi->uv_mode = mbmi->mode;
+#endif
}
static void read_inter_frame_mode_info(VP9_COMMON *const cm,
#if CONFIG_SUPERTX
if (try_tx_skip) {
#else
- if (try_tx_skip && !mbmi->skip) {
+ if (try_tx_skip && (!mbmi->skip || !inter_block)) {
#endif // CONFIG_SUPERTX
if (xd->lossless) {
#if CONFIG_SUPERTX
#if CONFIG_SUPERTX
if (try_tx_skip) {
#else
- if (try_tx_skip && !skip) {
+ if (try_tx_skip && (!skip || !is_inter)) {
#endif // CONFIG_SUPERTX
if (xd->lossless) {
#if CONFIG_SUPERTX
}
#if CONFIG_TX_SKIP
-void vp9_tx_identity(const int16_t *input, tran_low_t *out, int stride,
- int bs, int shift) {
+void vp9_tx_identity_rect(const int16_t *input, tran_low_t *out,
+ int row, int col,
+ int stride_in, int stride_out, int shift) {
int r, c;
- for (r = 0; r < bs; r++)
- for (c = 0; c < bs; c++) {
- out[bs * r + c] = input[stride * r + c] << shift;
+ for (r = 0; r < row; r++)
+ for (c = 0; c < col; c++) {
+ out[stride_out * r + c] = input[stride_in * r + c] << shift;
}
}
+
+void vp9_tx_identity(const int16_t *input, tran_low_t *out, int stride,
+ int bs, int shift) {
+ vp9_tx_identity_rect(input, out, bs, bs, stride, bs, shift);
+}
#endif
#if CONFIG_TX64X64
#if CONFIG_SUPERTX
if (try_tx_skip) {
#else
- if (try_tx_skip && !(mbmi->skip || seg_skip)) {
+ if (try_tx_skip && (!(mbmi->skip || seg_skip) || !is_inter_block(mbmi))) {
#endif
++cm->counts.y_tx_skip[is_inter_block(mbmi)][mbmi->tx_skip[0]];
++cm->counts.uv_tx_skip[mbmi->tx_skip[0]][mbmi->tx_skip[1]];
}
#endif
+#if CONFIG_TX_SKIP
+static int vp9_dpcm_intra(uint8_t *src, int src_stride,
+ uint8_t *dst, int dst_stride,
+ int16_t *src_diff, int diff_stride,
+ tran_low_t *coeff, tran_low_t *qcoeff,
+ tran_low_t *dqcoeff, struct macroblock_plane *p,
+ struct macroblockd_plane *pd,
+ const scan_order *scan_order, PREDICTION_MODE mode,
+ int bs, int shift, int logsizeby32) {
+ int i, j, eob, temp;
+ vpx_memset(qcoeff, 0, bs * bs * sizeof(*qcoeff));
+ vpx_memset(dqcoeff, 0, bs * bs * sizeof(*dqcoeff));
+
+ switch (mode) {
+ case H_PRED:
+ for (i = 0 ; i < bs; i++) {
+ vp9_subtract_block_c(bs, 1, src_diff + i, diff_stride,
+ src + i, src_stride,
+ dst + i, dst_stride);
+ vp9_tx_identity_rect(src_diff + i, coeff + i, bs, 1,
+ diff_stride, bs, shift);
+ vp9_quantize_rect(coeff + i, bs, 1, p->zbin, p->round, p->quant,
+ p->quant_shift, qcoeff + i, dqcoeff + i,
+ pd->dequant, p->zbin_extra, logsizeby32, bs, i == 0);
+ vp9_tx_identity_add_rect(dqcoeff + i, dst + i, bs, 1,
+ bs, dst_stride, shift);
+ if ( i < bs - 1 && 1)
+ for (j = 0 ; j < bs; j++)
+ *(dst + j * dst_stride + i + 1) =
+ *(dst + j * dst_stride + i);
+ }
+ break;
+ case V_PRED:
+ for (i = 0 ; i < bs; i++) {
+ vp9_subtract_block_c(1, bs, src_diff + diff_stride * i,
+ diff_stride,
+ src + src_stride * i, src_stride,
+ dst + dst_stride * i, dst_stride);
+ vp9_tx_identity_rect(src_diff + diff_stride * i,
+ coeff + bs * i, 1, bs,
+ diff_stride, bs, shift);
+ vp9_quantize_rect(coeff + bs * i, 1, bs, p->zbin, p->round, p->quant,
+ p->quant_shift, qcoeff + bs * i, dqcoeff + bs * i,
+ pd->dequant, p->zbin_extra, logsizeby32, bs, i == 0);
+ vp9_tx_identity_add_rect(dqcoeff + bs * i, dst + dst_stride * i,
+ 1, bs, bs, dst_stride, shift);
+ if (i < bs - 1)
+ vpx_memcpy(dst + (i + 1) * dst_stride,
+ dst + i * dst_stride, bs * sizeof(dst[0]));
+ }
+ break;
+ case TM_PRED:
+ vp9_subtract_block_c(1, bs, src_diff, diff_stride, src, src_stride,
+ dst, dst_stride);
+ vp9_tx_identity_rect(src_diff, coeff, 1, bs, diff_stride, bs, shift);
+ vp9_quantize_rect(coeff, 1, bs, p->zbin, p->round, p->quant,
+ p->quant_shift, qcoeff, dqcoeff, pd->dequant,
+ p->zbin_extra, logsizeby32, bs, 1);
+ vp9_tx_identity_add_rect(dqcoeff, dst, 1, bs, bs, dst_stride, shift);
+
+ vp9_subtract_block_c(bs -1, 1, src_diff + diff_stride, diff_stride,
+ src + src_stride, src_stride,
+ dst + dst_stride, dst_stride);
+ vp9_tx_identity_rect(src_diff + diff_stride, coeff + bs, bs - 1, 1,
+ diff_stride, bs, shift);
+ vp9_quantize_rect(coeff + bs, bs - 1, 1, p->zbin, p->round, p->quant,
+ p->quant_shift, qcoeff + bs, dqcoeff + bs,
+ pd->dequant, p->zbin_extra, logsizeby32, bs, 0);
+ vp9_tx_identity_add_rect(dqcoeff + bs, dst + dst_stride, bs - 1, 1,
+ bs, dst_stride, shift);
+
+ for (i = 1 ; i < bs; i++) {
+ for (j = 1 ; j < bs; j++) {
+ temp = dst[(i - 1) * dst_stride + j] + dst[i * dst_stride + j - 1] -
+ dst[(i - 1) * dst_stride + j - 1];
+ temp = clip_pixel(temp);
+ dst[i * dst_stride + j] = temp;
+ vp9_subtract_block_c(1, 1, src_diff + diff_stride * i + j,
+ diff_stride, src + src_stride * i + j,
+ src_stride, dst + dst_stride * i + j,
+ dst_stride);
+ vp9_tx_identity_rect(src_diff + i * diff_stride + j,
+ coeff + bs * i + j, 1, 1, diff_stride,
+ bs, shift);
+ vp9_quantize_rect(coeff + bs * i + j, 1, 1, p->zbin, p->round,
+ p->quant, p->quant_shift, qcoeff + bs * i + j,
+ dqcoeff + bs * i + j, pd->dequant,
+ p->zbin_extra, logsizeby32, bs, 0);
+ vp9_tx_identity_add_rect(dqcoeff + bs * i + j,
+ dst + dst_stride * i + j, 1, 1, bs,
+ dst_stride, shift);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ eob = get_eob(qcoeff, bs * bs, scan_order->scan);
+ return eob;
+}
+#endif // CONFIG_TX_SKIP
+
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;
dst, dst_stride, i, j, plane);
if (!x->skip_recode) {
+ if (mode == V_PRED || mode == H_PRED || mode == TM_PRED) {
+ *eob = vp9_dpcm_intra(src, src_stride, dst, dst_stride,
+ src_diff, diff_stride,
+ coeff, qcoeff, dqcoeff, p, pd,
+ scan_order, mode, 32, shift, 0);
+ break;
+ }
+
vp9_subtract_block(32, 32, src_diff, diff_stride,
src, src_stride, dst, dst_stride);
vp9_tx_identity(src_diff, coeff, diff_stride, 32, shift);
x->skip_encode ? src_stride : dst_stride,
dst, dst_stride, i, j, plane);
if (!x->skip_recode) {
+ if (mode == V_PRED || mode == H_PRED || mode == TM_PRED) {
+ *eob = vp9_dpcm_intra(src, src_stride, dst, dst_stride,
+ src_diff, diff_stride,
+ coeff, qcoeff, dqcoeff, p, pd,
+ scan_order, mode, 16, shift, -1);
+ break;
+ }
+
vp9_subtract_block(16, 16, src_diff, diff_stride,
src, src_stride, dst, dst_stride);
vp9_tx_identity(src_diff, coeff, diff_stride, 16, shift);
x->skip_encode ? src_stride : dst_stride,
dst, dst_stride, i, j, plane);
if (!x->skip_recode) {
+ if (mode == V_PRED || mode == H_PRED || mode == TM_PRED) {
+ *eob = vp9_dpcm_intra(src, src_stride, dst, dst_stride,
+ src_diff, diff_stride,
+ coeff, qcoeff, dqcoeff, p, pd,
+ scan_order, mode, 8, shift, -1);
+ break;
+ }
+
vp9_subtract_block(8, 8, src_diff, diff_stride,
src, src_stride, dst, dst_stride);
vp9_tx_identity(src_diff, coeff, diff_stride, 8, shift);
dst, dst_stride, i, j, plane);
if (!x->skip_recode) {
+ if (mode == V_PRED || mode == H_PRED || mode == TM_PRED) {
+ *eob = vp9_dpcm_intra(src, src_stride, dst, dst_stride,
+ src_diff, diff_stride,
+ coeff, qcoeff, dqcoeff, p, pd,
+ scan_order, mode, 4, shift, -1);
+ break;
+ }
+
vp9_subtract_block(4, 4, src_diff, diff_stride,
src, src_stride, dst, dst_stride);
vp9_tx_identity(src_diff, coeff, diff_stride, 4, shift);
void vp9_encode_intra_block_plane(MACROBLOCK *x, BLOCK_SIZE bsize, int plane);
#if CONFIG_TX_SKIP
+void vp9_tx_identity_rect(const int16_t *input, tran_low_t *out,
+ int row, int col,
+ int stride_in, int stride_out, int shift);
void vp9_tx_identity(const int16_t *input, tran_low_t *out, int stride,
int bs, int shift);
#endif
*eob_ptr = eob + 1;
}
+#if CONFIG_TX_SKIP
+void vp9_quantize_rect(const tran_low_t *coeff_ptr, int row, int col,
+ const int16_t *zbin_ptr, const int16_t *round_ptr,
+ const int16_t *quant_ptr,
+ const int16_t *quant_shift_ptr,
+ tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
+ const int16_t *dequant_ptr, int zbin_oq_value,
+ int logsizeby32, int stride, int has_dc) {
+ int r, c;
+ int zbins[2] = {ROUND_POWER_OF_TWO(zbin_ptr[0] + zbin_oq_value,
+ 1 + (logsizeby32 < 0 ? -1 : logsizeby32)),
+ ROUND_POWER_OF_TWO(zbin_ptr[1] + zbin_oq_value,
+ 1 + (logsizeby32 < 0 ? -1 : logsizeby32))};
+ if (logsizeby32 < 0) {
+ logsizeby32 = -1;
+ zbins[0] = zbin_ptr[0] + zbin_oq_value;
+ zbins[1] = zbin_ptr[1] + zbin_oq_value;
+ }
+
+ for (r = 0; r < row; r++)
+ for (c = 0; c < col; c++) {
+ const int coeff = coeff_ptr[r * stride + c];
+ const int coeff_sign = (coeff >> 31);
+ int tmp;
+ int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
+ int idx = (r == 0 && c == 0 && has_dc) ? 0 : 1;
+ qcoeff_ptr[r * stride + c] = dqcoeff_ptr[r * stride + c] = 0;
+
+ if (abs_coeff >= zbins[idx]) {
+ if (logsizeby32 < 0)
+ abs_coeff += round_ptr[idx];
+ else
+ abs_coeff += ROUND_POWER_OF_TWO(round_ptr[idx], (1 + logsizeby32));
+ abs_coeff = clamp(abs_coeff, INT16_MIN, INT16_MAX);
+ tmp = ((((abs_coeff * quant_ptr[idx]) >> 16) + abs_coeff) *
+ quant_shift_ptr[idx]) >> (15 - logsizeby32);
+
+ qcoeff_ptr[r * stride + c] = (tmp ^ coeff_sign) - coeff_sign;
+ dqcoeff_ptr[r * stride + c] = qcoeff_ptr[r * stride + c] *
+ dequant_ptr[idx] /
+ (1 << (logsizeby32 + 1));
+ }
+ }
+}
+
+int get_eob(tran_low_t *qcoeff_ptr, intptr_t n_coeffs, const int16_t *scan) {
+ int i, rc, eob = -1;
+
+ for (i = (int)n_coeffs - 1; i >= 0; i--) {
+ rc = scan[i];
+ if (qcoeff_ptr[rc]) {
+ eob = i;
+ break;
+ }
+ }
+
+ eob += 1;
+ return eob;
+}
+#endif
+
#if CONFIG_VP9_HIGHBITDEPTH
void vp9_highbd_quantize_b_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
int skip_block, const int16_t *zbin_ptr,
int vp9_qindex_to_quantizer(int qindex);
+#if CONFIG_TX_SKIP
+void vp9_quantize_rect(const tran_low_t *coeff_ptr, int row, int col,
+ const int16_t *zbin_ptr, const int16_t *round_ptr,
+ const int16_t *quant_ptr, const int16_t *quant_shift_ptr,
+ tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
+ const int16_t *dequant_ptr, int zbin_oq_value,
+ int logsizeby32, int stride, int has_dc);
+
+int get_eob(tran_low_t *qcoeff_ptr, intptr_t n_coeffs, const int16_t *scan);
+#endif
+
#ifdef __cplusplus
} // extern "C"
#endif