9824230fe3
Adds ADST/DCT hybrid transform coding for Intra4x4 mode. The ADST is applied to directions in which the boundary pixels are used for prediction, while DCT applied to directions without corresponding boundary prediction. Adds enum TX_TYPE in b_mode_infor to indicate the transform type used. Make coding style consistent with google style. Fixed the commented issues. Experimental results in terms of bit-rate reduction: derf: 0.731% yt: 0.982% std-hd: 0.459% hd: 0.725% Will be looking at 8x8 transforms next. Change-Id: I46dbd7b80dbb3e8856e9c34fbc58cb3764a12fcf
382 lines
10 KiB
C
382 lines
10 KiB
C
/*
|
|
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
|
|
#include "vpx_ports/config.h"
|
|
#include "vp8/common/idct.h"
|
|
#include "quantize.h"
|
|
#include "vp8/common/reconintra.h"
|
|
#include "vp8/common/reconintra4x4.h"
|
|
#include "encodemb.h"
|
|
#include "vp8/common/invtrans.h"
|
|
#include "vp8/common/recon.h"
|
|
#include "dct.h"
|
|
#include "vp8/common/g_common.h"
|
|
#include "encodeintra.h"
|
|
|
|
|
|
#ifdef ENC_DEBUG
|
|
extern int enc_debug;
|
|
#endif
|
|
|
|
#if CONFIG_RUNTIME_CPU_DETECT
|
|
#define IF_RTCD(x) (x)
|
|
#else
|
|
#define IF_RTCD(x) NULL
|
|
#endif
|
|
|
|
#if CONFIG_HYBRIDTRANSFORM
|
|
extern void vp8_ht_quantize_b(BLOCK *b, BLOCKD *d);
|
|
#endif
|
|
|
|
int vp8_encode_intra(VP8_COMP *cpi, MACROBLOCK *x, int use_16x16_pred) {
|
|
int i;
|
|
int intra_pred_var = 0;
|
|
(void) cpi;
|
|
|
|
if (use_16x16_pred) {
|
|
x->e_mbd.mode_info_context->mbmi.mode = DC_PRED;
|
|
#if CONFIG_COMP_INTRA_PRED
|
|
x->e_mbd.mode_info_context->mbmi.second_mode = (MB_PREDICTION_MODE)(DC_PRED - 1);
|
|
#endif
|
|
x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED;
|
|
x->e_mbd.mode_info_context->mbmi.ref_frame = INTRA_FRAME;
|
|
|
|
vp8_encode_intra16x16mby(IF_RTCD(&cpi->rtcd), x);
|
|
} else {
|
|
for (i = 0; i < 16; i++) {
|
|
x->e_mbd.block[i].bmi.as_mode.first = B_DC_PRED;
|
|
vp8_encode_intra4x4block(IF_RTCD(&cpi->rtcd), x, i);
|
|
}
|
|
}
|
|
|
|
intra_pred_var = VARIANCE_INVOKE(&cpi->rtcd.variance, getmbss)(x->src_diff);
|
|
|
|
return intra_pred_var;
|
|
}
|
|
|
|
void vp8_encode_intra4x4block(const VP8_ENCODER_RTCD *rtcd,
|
|
MACROBLOCK *x, int ib) {
|
|
BLOCKD *b = &x->e_mbd.block[ib];
|
|
BLOCK *be = &x->block[ib];
|
|
|
|
#if CONFIG_HYBRIDTRANSFORM
|
|
int QIndex = x->q_index;
|
|
int active_ht = (QIndex < ACTIVE_HT);
|
|
#endif
|
|
|
|
|
|
#if CONFIG_COMP_INTRA_PRED
|
|
if (b->bmi.as_mode.second == (B_PREDICTION_MODE)(B_DC_PRED - 1)) {
|
|
#endif
|
|
RECON_INVOKE(&rtcd->common->recon, intra4x4_predict)
|
|
(b, b->bmi.as_mode.first, b->predictor);
|
|
#if CONFIG_COMP_INTRA_PRED
|
|
} else {
|
|
RECON_INVOKE(&rtcd->common->recon, comp_intra4x4_predict)
|
|
(b, b->bmi.as_mode.first, b->bmi.as_mode.second, b->predictor);
|
|
}
|
|
#endif
|
|
|
|
ENCODEMB_INVOKE(&rtcd->encodemb, subb)(be, b, 16);
|
|
|
|
#if CONFIG_HYBRIDTRANSFORM
|
|
if(active_ht) {
|
|
b->bmi.as_mode.test = b->bmi.as_mode.first;
|
|
switch(b->bmi.as_mode.first) {
|
|
// case B_DC_PRED :
|
|
case B_TM_PRED :
|
|
case B_RD_PRED :
|
|
b->bmi.as_mode.tx_type = ADST_ADST;
|
|
break;
|
|
|
|
case B_VE_PRED :
|
|
case B_VR_PRED :
|
|
b->bmi.as_mode.tx_type = ADST_DCT;
|
|
break;
|
|
|
|
case B_HE_PRED :
|
|
case B_HD_PRED :
|
|
case B_HU_PRED :
|
|
b->bmi.as_mode.tx_type = DCT_ADST;
|
|
break;
|
|
|
|
default :
|
|
b->bmi.as_mode.tx_type = DCT_DCT;
|
|
break;
|
|
}
|
|
|
|
vp8_fht4x4_c(be->src_diff, be->coeff, 32, b->bmi.as_mode.tx_type);
|
|
vp8_ht_quantize_b(be, b);
|
|
vp8_inverse_htransform_b(IF_RTCD(&rtcd->common->idct), b, 32) ;
|
|
} else {
|
|
x->vp8_short_fdct4x4(be->src_diff, be->coeff, 32) ;
|
|
x->quantize_b(be, b) ;
|
|
vp8_inverse_transform_b(IF_RTCD(&rtcd->common->idct), b, 32) ;
|
|
}
|
|
#else
|
|
x->vp8_short_fdct4x4(be->src_diff, be->coeff, 32);
|
|
x->quantize_b(be, b);
|
|
vp8_inverse_transform_b(IF_RTCD(&rtcd->common->idct), b, 32);
|
|
#endif
|
|
|
|
RECON_INVOKE(&rtcd->common->recon, recon)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
|
|
}
|
|
|
|
void vp8_encode_intra4x4mby(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *mb) {
|
|
int i;
|
|
|
|
#if 0
|
|
MACROBLOCKD *x = &mb->e_mbd;
|
|
// Intra modes requiring top-right MB reconstructed data have been disabled
|
|
vp8_intra_prediction_down_copy(x);
|
|
#endif
|
|
|
|
for (i = 0; i < 16; i++)
|
|
vp8_encode_intra4x4block(rtcd, mb, i);
|
|
return;
|
|
}
|
|
|
|
void vp8_encode_intra16x16mby(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x) {
|
|
BLOCK *b = &x->block[0];
|
|
|
|
int tx_type = x->e_mbd.mode_info_context->mbmi.txfm_size;
|
|
|
|
#if CONFIG_COMP_INTRA_PRED
|
|
if (x->e_mbd.mode_info_context->mbmi.second_mode == (MB_PREDICTION_MODE)(DC_PRED - 1))
|
|
#endif
|
|
RECON_INVOKE(&rtcd->common->recon, build_intra_predictors_mby)(&x->e_mbd);
|
|
#if CONFIG_COMP_INTRA_PRED
|
|
else
|
|
RECON_INVOKE(&rtcd->common->recon, build_comp_intra_predictors_mby)(&x->e_mbd);
|
|
#endif
|
|
|
|
ENCODEMB_INVOKE(&rtcd->encodemb, submby)(x->src_diff, *(b->base_src), x->e_mbd.predictor, b->src_stride);
|
|
|
|
if (tx_type == TX_8X8)
|
|
vp8_transform_intra_mby_8x8(x);
|
|
else
|
|
vp8_transform_intra_mby(x);
|
|
|
|
if (tx_type == TX_8X8)
|
|
vp8_quantize_mby_8x8(x);
|
|
else
|
|
vp8_quantize_mby(x);
|
|
|
|
if (x->optimize) {
|
|
if (tx_type == TX_8X8)
|
|
vp8_optimize_mby_8x8(x, rtcd);
|
|
else
|
|
vp8_optimize_mby(x, rtcd);
|
|
}
|
|
|
|
if (tx_type == TX_8X8)
|
|
vp8_inverse_transform_mby_8x8(IF_RTCD(&rtcd->common->idct), &x->e_mbd);
|
|
else
|
|
vp8_inverse_transform_mby(IF_RTCD(&rtcd->common->idct), &x->e_mbd);
|
|
|
|
#ifdef ENC_DEBUG
|
|
if (enc_debug) {
|
|
int i;
|
|
printf("Intra qcoeff:\n");
|
|
printf("%d %d:\n", x->e_mbd.mb_to_left_edge, x->e_mbd.mb_to_top_edge);
|
|
for (i = 0; i < 400; i++) {
|
|
printf("%3d ", x->e_mbd.qcoeff[i]);
|
|
if (i % 16 == 15) printf("\n");
|
|
}
|
|
printf("Intra dqcoeff:\n");
|
|
for (i = 0; i < 400; i++) {
|
|
printf("%3d ", x->e_mbd.dqcoeff[i]);
|
|
if (i % 16 == 15) printf("\n");
|
|
}
|
|
printf("Intra diff:\n");
|
|
for (i = 0; i < 400; i++) {
|
|
printf("%3d ", x->e_mbd.diff[i]);
|
|
if (i % 16 == 15) printf("\n");
|
|
}
|
|
printf("Intra predictor:\n");
|
|
for (i = 0; i < 400; i++) {
|
|
printf("%3d ", x->e_mbd.predictor[i]);
|
|
if (i % 16 == 15) printf("\n");
|
|
}
|
|
printf("eobs:\n");
|
|
for (i = 0; i < 25; i++)
|
|
printf("%d ", x->e_mbd.block[i].eob);
|
|
printf("\n");
|
|
}
|
|
#endif
|
|
|
|
RECON_INVOKE(&rtcd->common->recon, recon_mby)
|
|
(IF_RTCD(&rtcd->common->recon), &x->e_mbd);
|
|
|
|
}
|
|
|
|
void vp8_encode_intra16x16mbuv(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x) {
|
|
int tx_type = x->e_mbd.mode_info_context->mbmi.txfm_size;
|
|
#if CONFIG_COMP_INTRA_PRED
|
|
if (x->e_mbd.mode_info_context->mbmi.second_uv_mode == (MB_PREDICTION_MODE)(DC_PRED - 1)) {
|
|
#endif
|
|
RECON_INVOKE(&rtcd->common->recon, build_intra_predictors_mbuv)(&x->e_mbd);
|
|
#if CONFIG_COMP_INTRA_PRED
|
|
} else {
|
|
RECON_INVOKE(&rtcd->common->recon, build_comp_intra_predictors_mbuv)(&x->e_mbd);
|
|
}
|
|
#endif
|
|
|
|
ENCODEMB_INVOKE(&rtcd->encodemb, submbuv)(x->src_diff, x->src.u_buffer, x->src.v_buffer, x->e_mbd.predictor, x->src.uv_stride);
|
|
if (tx_type == TX_8X8)
|
|
vp8_transform_mbuv_8x8(x);
|
|
else
|
|
vp8_transform_mbuv(x);
|
|
|
|
if (tx_type == TX_8X8)
|
|
vp8_quantize_mbuv_8x8(x);
|
|
else
|
|
vp8_quantize_mbuv(x);
|
|
|
|
#ifdef ENC_DEBUG
|
|
if (enc_debug) {
|
|
int i;
|
|
printf("vp8_encode_intra16x16mbuv\n");
|
|
printf("%d %d:\n", x->e_mbd.mb_to_left_edge, x->e_mbd.mb_to_top_edge);
|
|
printf("qcoeff:\n");
|
|
for (i = 0; i < 400; i++) {
|
|
printf("%3d ", x->e_mbd.qcoeff[i]);
|
|
if (i % 16 == 15) printf("\n");
|
|
}
|
|
printf("dqcoeff:\n");
|
|
for (i = 0; i < 400; i++) {
|
|
printf("%3d ", x->e_mbd.dqcoeff[i]);
|
|
if (i % 16 == 15) printf("\n");
|
|
}
|
|
printf("diff:\n");
|
|
for (i = 0; i < 400; i++) {
|
|
printf("%3d ", x->e_mbd.diff[i]);
|
|
if (i % 16 == 15) printf("\n");
|
|
}
|
|
printf("predictor:\n");
|
|
for (i = 0; i < 400; i++) {
|
|
printf("%3d ", x->e_mbd.predictor[i]);
|
|
if (i % 16 == 15) printf("\n");
|
|
}
|
|
printf("eobs:\n");
|
|
for (i = 0; i < 25; i++)
|
|
printf("%d ", x->e_mbd.block[i].eob);
|
|
printf("\n");
|
|
}
|
|
#endif
|
|
if (x->optimize) {
|
|
if (tx_type == TX_8X8)
|
|
vp8_optimize_mbuv_8x8(x, rtcd);
|
|
else
|
|
vp8_optimize_mbuv(x, rtcd);
|
|
}
|
|
|
|
if (tx_type == TX_8X8)
|
|
vp8_inverse_transform_mbuv_8x8(IF_RTCD(&rtcd->common->idct), &x->e_mbd);
|
|
else
|
|
vp8_inverse_transform_mbuv(IF_RTCD(&rtcd->common->idct), &x->e_mbd);
|
|
|
|
vp8_recon_intra_mbuv(IF_RTCD(&rtcd->common->recon), &x->e_mbd);
|
|
}
|
|
|
|
void vp8_encode_intra8x8(const VP8_ENCODER_RTCD *rtcd,
|
|
MACROBLOCK *x, int ib) {
|
|
BLOCKD *b = &x->e_mbd.block[ib];
|
|
BLOCK *be = &x->block[ib];
|
|
const int iblock[4] = {0, 1, 4, 5};
|
|
int i;
|
|
|
|
#if CONFIG_COMP_INTRA_PRED
|
|
if (b->bmi.as_mode.second == (MB_PREDICTION_MODE)(DC_PRED - 1)) {
|
|
#endif
|
|
RECON_INVOKE(&rtcd->common->recon, intra8x8_predict)
|
|
(b, b->bmi.as_mode.first, b->predictor);
|
|
#if CONFIG_COMP_INTRA_PRED
|
|
} else {
|
|
RECON_INVOKE(&rtcd->common->recon, comp_intra8x8_predict)
|
|
(b, b->bmi.as_mode.first, b->bmi.as_mode.second, b->predictor);
|
|
}
|
|
#endif
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
b = &x->e_mbd.block[ib + iblock[i]];
|
|
be = &x->block[ib + iblock[i]];
|
|
ENCODEMB_INVOKE(&rtcd->encodemb, subb)(be, b, 16);
|
|
x->vp8_short_fdct4x4(be->src_diff, be->coeff, 32);
|
|
x->quantize_b(be, b);
|
|
vp8_inverse_transform_b(IF_RTCD(&rtcd->common->idct), b, 32);
|
|
RECON_INVOKE(&rtcd->common->recon, recon)(b->predictor,
|
|
b->diff, *(b->base_dst) + b->dst, b->dst_stride);
|
|
}
|
|
}
|
|
|
|
extern const int vp8_i8x8_block[4];
|
|
void vp8_encode_intra8x8mby(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x) {
|
|
int i, ib;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
ib = vp8_i8x8_block[i];
|
|
vp8_encode_intra8x8(rtcd, x, ib);
|
|
}
|
|
|
|
}
|
|
|
|
void vp8_encode_intra_uv4x4(const VP8_ENCODER_RTCD *rtcd,
|
|
MACROBLOCK *x, int ib,
|
|
int mode, int second) {
|
|
BLOCKD *b = &x->e_mbd.block[ib];
|
|
BLOCK *be = &x->block[ib];
|
|
|
|
#if CONFIG_COMP_INTRA_PRED
|
|
if (second == -1) {
|
|
#endif
|
|
RECON_INVOKE(&rtcd->common->recon, intra_uv4x4_predict)
|
|
(b, mode, b->predictor);
|
|
#if CONFIG_COMP_INTRA_PRED
|
|
} else {
|
|
RECON_INVOKE(&rtcd->common->recon, comp_intra_uv4x4_predict)
|
|
(b, mode, second, b->predictor);
|
|
}
|
|
#endif
|
|
|
|
ENCODEMB_INVOKE(&rtcd->encodemb, subb)(be, b, 8);
|
|
|
|
x->vp8_short_fdct4x4(be->src_diff, be->coeff, 16);
|
|
|
|
x->quantize_b(be, b);
|
|
|
|
vp8_inverse_transform_b(IF_RTCD(&rtcd->common->idct), b, 16);
|
|
|
|
RECON_INVOKE(&rtcd->common->recon, recon_uv)(b->predictor,
|
|
b->diff, *(b->base_dst) + b->dst, b->dst_stride);
|
|
}
|
|
|
|
|
|
|
|
void vp8_encode_intra8x8mbuv(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x) {
|
|
int i, ib, mode, second;
|
|
BLOCKD *b;
|
|
for (i = 0; i < 4; i++) {
|
|
ib = vp8_i8x8_block[i];
|
|
b = &x->e_mbd.block[ib];
|
|
mode = b->bmi.as_mode.first;
|
|
#if CONFIG_COMP_INTRA_PRED
|
|
second = b->bmi.as_mode.second;
|
|
#else
|
|
second = -1;
|
|
#endif
|
|
/*u */
|
|
vp8_encode_intra_uv4x4(rtcd, x, i + 16, mode, second);
|
|
/*v */
|
|
vp8_encode_intra_uv4x4(rtcd, x, i + 20, mode, second);
|
|
}
|
|
}
|