Commit 708c1ec5 authored by Lester Lu's avatar Lester Lu

Inter and intra LGTs

Here we have an LGT to replace ADST for intra residual blocks, and
another LGT to replace ADST for inter residual blocks. The changes
are only applied to transform length 4 and 8, and only for the
lowbitdepth path.

lowres: -0.18%

Change-Id: Iadc1e02b53e3756b44f74ca648cfa8b0e8ca7af4
parent 7651b739
......@@ -247,33 +247,7 @@ void aom_idct8x8_1_add_c(const tran_low_t *input, uint8_t *dest, int stride) {
}
}
#if CONFIG_LGT
void aom_ilgt4_c(const tran_low_t *input, tran_low_t *output) {
if (!(input[0] | input[1] | input[2] | input[3])) {
output[0] = output[1] = output[2] = output[3] = 0;
return;
}
tran_high_t s[4] = { 0 };
for (int i = 0; i < 4; ++i)
for (int j = 0; j < 4; ++j) s[j] += lgtbasis4[i][j] * input[i];
for (int i = 0; i < 4; ++i) output[i] = WRAPLOW(dct_const_round_shift(s[i]));
}
void aom_ilgt8_c(const tran_low_t *input, tran_low_t *output) {
tran_high_t s[8] = { 0 };
for (int i = 0; i < 8; ++i)
for (int j = 0; j < 8; ++j) s[j] += lgtbasis8[i][j] * input[i];
for (int i = 0; i < 8; ++i) output[i] = WRAPLOW(dct_const_round_shift(s[i]));
}
#endif // CONFIG_LGT
void aom_iadst4_c(const tran_low_t *input, tran_low_t *output) {
#if CONFIG_LGT
aom_ilgt4_c(input, output);
#else
tran_high_t s0, s1, s2, s3, s4, s5, s6, s7;
tran_low_t x0 = input[0];
......@@ -308,13 +282,9 @@ void aom_iadst4_c(const tran_low_t *input, tran_low_t *output) {
output[1] = WRAPLOW(dct_const_round_shift(s1 + s3));
output[2] = WRAPLOW(dct_const_round_shift(s2));
output[3] = WRAPLOW(dct_const_round_shift(s0 + s1 - s3));
#endif // CONFIG_LGT
}
void aom_iadst8_c(const tran_low_t *input, tran_low_t *output) {
#if CONFIG_LGT
aom_ilgt8_c(input, output);
#else
int s0, s1, s2, s3, s4, s5, s6, s7;
tran_high_t x0 = input[7];
......@@ -389,7 +359,6 @@ void aom_iadst8_c(const tran_low_t *input, tran_low_t *output) {
output[5] = WRAPLOW(-x7);
output[6] = WRAPLOW(x5);
output[7] = WRAPLOW(-x1);
#endif // CONFIG_LGT
}
void aom_idct8x8_12_add_c(const tran_low_t *input, uint8_t *dest, int stride) {
......
......@@ -52,11 +52,6 @@ static INLINE tran_high_t check_range(tran_high_t input, int bd) {
#define WRAPLOW(x) ((int32_t)check_range(x, 8))
#define HIGHBD_WRAPLOW(x, bd) ((int32_t)check_range((x), bd))
#if CONFIG_LGT
void aom_ilgt4_c(const tran_low_t *input, tran_low_t *output);
void aom_ilgt8_c(const tran_low_t *input, tran_low_t *output);
#endif
void aom_idct4_c(const tran_low_t *input, tran_low_t *output);
void aom_idct8_c(const tran_low_t *input, tran_low_t *output);
void aom_idct16_c(const tran_low_t *input, tran_low_t *output);
......
......@@ -73,22 +73,48 @@ static INLINE tran_high_t fdct_round_shift(tran_high_t input) {
}
#if CONFIG_LGT
// LGT4--a modified ADST4
// LGT4 name: lgt4_160
// Self loops: 1.600, 0.000, 0.000, 0.000
// The Line Graph Transforms (LGTs) matrices are written as follows.
// Each 2D array is 16384 times an LGT matrix, which is the matrix of
// eigenvectors of the graph Laplacian matrices for the line graph.
// LGT4 name: lgt4_140
// Self loops: 1.400, 0.000, 0.000, 0.000
// Edges: 1.000, 1.000, 1.000
static const tran_high_t lgt4_140[4][4] = {
{ 4206, 9518, 13524, 15674 },
{ 11552, 14833, 1560, -13453 },
{ 15391, -1906, -14393, 9445 },
{ 12201, -14921, 12016, -4581 },
};
// LGT4 name: lgt4_170
// Self loops: 1.700, 0.000, 0.000, 0.000
// Edges: 1.000, 1.000, 1.000
static const tran_high_t lgtbasis4[4][4] = {
{ 3809, 9358, 13567, 15834 },
{ 10673, 15348, 2189, -13513 },
{ 15057, -157, -14961, 9290 },
{ 13481, -14619, 11144, -4151 },
static const tran_high_t lgt4_170[4][4] = {
{ 3636, 9287, 13584, 15902 },
{ 10255, 15563, 2470, -13543 },
{ 14786, 711, -15249, 9231 },
{ 14138, -14420, 10663, -3920 },
};
// LGT8 name: lgt8_150
// Self loops: 1.500, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000
// Edges: 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000
static const tran_high_t lgt8_150[8][8] = {
{ 2075, 5110, 7958, 10511, 12677, 14376, 15544, 16140 },
{ 6114, 13307, 16196, 13845, 7015, -2084, -10509, -15534 },
{ 9816, 16163, 8717, -6168, -15790, -11936, 2104, 14348 },
{ 12928, 12326, -7340, -15653, 242, 15763, 6905, -12632 },
{ 15124, 3038, -16033, 1758, 15507, -6397, -13593, 10463 },
{ 15895, -7947, -7947, 15895, -7947, -7947, 15895, -7947 },
{ 14325, -15057, 9030, 1050, -10659, 15483, -13358, 5236 },
{ 9054, -12580, 14714, -15220, 14043, -11312, 7330, -2537 },
};
// LGT8--a modified ADST8
// LGT8 name: lgt8_170
// Self loops: 1.700, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000
// Edges: 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000
static const tran_high_t lgtbasis8[8][8] = {
static const tran_high_t lgt8_170[8][8] = {
{ 1858, 4947, 7850, 10458, 12672, 14411, 15607, 16217 },
{ 5494, 13022, 16256, 14129, 7343, -1864, -10456, -15601 },
{ 8887, 16266, 9500, -5529, -15749, -12273, 1876, 14394 },
......
......@@ -1077,6 +1077,18 @@ static INLINE int av1_raster_order_to_block_index(TX_SIZE tx_size,
return (tx_size == TX_4X4) ? raster_order : (raster_order > 0) ? 2 : 0;
}
#if CONFIG_DPCM_INTRA || CONFIG_LGT
static INLINE PREDICTION_MODE get_prediction_mode(const MODE_INFO *mi,
int plane, TX_SIZE tx_size,
int block_idx) {
const MB_MODE_INFO *const mbmi = &mi->mbmi;
if (is_inter_block(mbmi)) return mbmi->mode;
int block_raster_idx = av1_block_index_to_raster_order(tx_size, block_idx);
return (plane == 0) ? get_y_mode(mi, block_raster_idx) : mbmi->uv_mode;
}
#endif
static INLINE TX_TYPE get_default_tx_type(PLANE_TYPE plane_type,
const MACROBLOCKD *xd, int block_idx,
TX_SIZE tx_size) {
......
This diff is collapsed.
......@@ -33,6 +33,12 @@ typedef struct fwd_txfm_param {
TX_SIZE tx_size;
int lossless;
int bd;
#if CONFIG_LGT
int is_inter;
int stride;
PREDICTION_MODE mode;
uint8_t *dst;
#endif
} FWD_TXFM_PARAM;
typedef struct inv_txfm_param {
......@@ -44,6 +50,12 @@ typedef struct inv_txfm_param {
int eob;
int lossless;
int bd;
#if CONFIG_LGT
int is_inter;
int stride;
PREDICTION_MODE mode;
uint8_t *dst;
#endif
} INV_TXFM_PARAM;
typedef void (*transform_1d)(const tran_low_t *, tran_low_t *);
......@@ -71,9 +83,12 @@ void av1_idct4x4_add(const tran_low_t *input, uint8_t *dest, int stride,
void av1_inv_txfm_add(const tran_low_t *input, uint8_t *dest, int stride,
INV_TXFM_PARAM *inv_txfm_param);
void av1_inverse_transform_block(const MACROBLOCKD *xd,
const tran_low_t *dqcoeff, TX_TYPE tx_type,
TX_SIZE tx_size, uint8_t *dst, int stride,
int eob);
const tran_low_t *dqcoeff,
#if CONFIG_LGT
PREDICTION_MODE mode,
#endif
TX_TYPE tx_type, TX_SIZE tx_size, uint8_t *dst,
int stride, int eob);
void av1_inverse_transform_block_facade(MACROBLOCKD *xd, int plane, int block,
int blk_row, int blk_col, int eob);
......
......@@ -354,12 +354,19 @@ static void read_mv_probs(nmv_context *ctx, int allow_hp, aom_reader *r) {
}
static void inverse_transform_block(MACROBLOCKD *xd, int plane,
#if CONFIG_LGT
PREDICTION_MODE mode,
#endif
const TX_TYPE tx_type,
const TX_SIZE tx_size, uint8_t *dst,
int stride, int16_t scan_line, int eob) {
struct macroblockd_plane *const pd = &xd->plane[plane];
tran_low_t *const dqcoeff = pd->dqcoeff;
av1_inverse_transform_block(xd, dqcoeff, tx_type, tx_size, dst, stride, eob);
av1_inverse_transform_block(xd, dqcoeff,
#if CONFIG_LGT
mode,
#endif
tx_type, tx_size, dst, stride, eob);
memset(dqcoeff, 0, (scan_line + 1) * sizeof(dqcoeff[0]));
}
......@@ -508,6 +515,11 @@ static int av1_pvq_decode_helper2(AV1_COMMON *cm, MACROBLOCKD *const xd,
fwd_txfm_param.tx_type = tx_type;
fwd_txfm_param.tx_size = tx_size;
fwd_txfm_param.lossless = xd->lossless[seg_id];
#if CONFIG_LGT
fwd_txfm_param.is_inter = is_inter_block(mbmi);
fwd_txfm_param.dst = dst;
fwd_txfm_param.mode = get_prediction_mode(xd->mi[0], plane, tx_size, block);
#endif
#if CONFIG_HIGHBITDEPTH
if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
......@@ -525,7 +537,11 @@ static int av1_pvq_decode_helper2(AV1_COMMON *cm, MACROBLOCKD *const xd,
eob = av1_pvq_decode_helper(xd, pvq_ref_coeff, dqcoeff, quant, plane,
tx_size, tx_type, xdec, ac_dc_coded);
inverse_transform_block(xd, plane, tx_type, tx_size, dst, pd->dst.stride,
inverse_transform_block(xd, plane,
#if CONFIG_LGT
fwd_txfm_param.mode,
#endif
tx_type, tx_size, dst, pd->dst.stride,
max_scan_line, eob);
}
......@@ -709,27 +725,30 @@ static void predict_and_reconstruct_intra_block(
if (eob) {
uint8_t *dst =
&pd->dst.buf[(row * pd->dst.stride + col) << tx_size_wide_log2[0]];
#if CONFIG_DPCM_INTRA || CONFIG_LGT
const PREDICTION_MODE mode =
get_prediction_mode(xd->mi[0], plane, tx_size, block_idx);
#if CONFIG_DPCM_INTRA
const int block_raster_idx =
av1_block_index_to_raster_order(tx_size, block_idx);
const PREDICTION_MODE mode = (plane == 0)
? get_y_mode(xd->mi[0], block_raster_idx)
: mbmi->uv_mode;
if (av1_use_dpcm_intra(plane, mode, tx_type, mbmi)) {
inverse_transform_block_dpcm(xd, plane, mode, tx_size, tx_type, dst,
pd->dst.stride, max_scan_line);
} else {
#endif // CONFIG_DPCM_INTRA
inverse_transform_block(xd, plane, tx_type, tx_size, dst,
pd->dst.stride, max_scan_line, eob);
#endif // CONFIG_DPCM_INTRA || CONFIG_LGT
inverse_transform_block(xd, plane,
#if CONFIG_LGT
mode,
#endif
tx_type, tx_size, dst, pd->dst.stride,
max_scan_line, eob);
#if CONFIG_DPCM_INTRA
}
#endif // CONFIG_DPCM_INTRA
}
#else
#else // !CONFIG_PVQ
TX_TYPE tx_type = get_tx_type(plane_type, xd, block_idx, tx_size);
av1_pvq_decode_helper2(cm, xd, mbmi, plane, row, col, tx_size, tx_type);
#endif
#endif // !CONFIG_PVQ
}
#if CONFIG_CFL
if (plane == AOM_PLANE_Y) {
......@@ -785,7 +804,11 @@ static void decode_reconstruct_tx(AV1_COMMON *cm, MACROBLOCKD *const xd,
cm, xd, plane, sc, blk_col, blk_row, plane_tx_size, tx_type,
&max_scan_line, r, mbmi->segment_id);
#endif // CONFIG_LV_MAP
inverse_transform_block(xd, plane, tx_type, plane_tx_size,
inverse_transform_block(xd, plane,
#if CONFIG_LGT
mbmi->mode,
#endif
tx_type, plane_tx_size,
&pd->dst.buf[(blk_row * pd->dst.stride + blk_col)
<< tx_size_wide_log2[0]],
pd->dst.stride, max_scan_line, eob);
......@@ -850,7 +873,11 @@ static int reconstruct_inter_block(AV1_COMMON *cm, MACROBLOCKD *const xd,
uint8_t *dst =
&pd->dst.buf[(row * pd->dst.stride + col) << tx_size_wide_log2[0]];
if (eob)
inverse_transform_block(xd, plane, tx_type, tx_size, dst, pd->dst.stride,
inverse_transform_block(xd, plane,
#if CONFIG_LGT
xd->mi[0]->mbmi.mode,
#endif
tx_type, tx_size, dst, pd->dst.stride,
max_scan_line, eob);
#else
TX_TYPE tx_type = get_tx_type(plane_type, xd, block_idx, tx_size);
......
This diff is collapsed.
......@@ -534,14 +534,16 @@ void av1_xform_quant(const AV1_COMMON *cm, MACROBLOCK *x, int plane, int block,
FWD_TXFM_PARAM fwd_txfm_param;
#if CONFIG_PVQ || CONFIG_DAALA_DIST
#if CONFIG_PVQ || CONFIG_DAALA_DIST || CONFIG_LGT
uint8_t *dst;
int16_t *pred;
const int dst_stride = pd->dst.stride;
#if CONFIG_PVQ || CONFIG_DAALA_DIST
int16_t *pred;
const int txw = tx_size_wide[tx_size];
const int txh = tx_size_high[tx_size];
int i, j;
#endif
#endif
#if !CONFIG_PVQ
const int tx2d_size = tx_size_2d[tx_size];
......@@ -595,8 +597,9 @@ void av1_xform_quant(const AV1_COMMON *cm, MACROBLOCK *x, int plane, int block,
#endif // CONFIG_HIGHBITDEPTH
#endif
#if CONFIG_PVQ || CONFIG_DAALA_DIST
#if CONFIG_PVQ || CONFIG_DAALA_DIST || CONFIG_LGT
dst = &pd->dst.buf[(blk_row * dst_stride + blk_col) << tx_size_wide_log2[0]];
#if CONFIG_PVQ || CONFIG_DAALA_DIST
pred = &pd->pred[(blk_row * diff_stride + blk_col) << tx_size_wide_log2[0]];
// copy uint8 orig and predicted block to int16 buffer
......@@ -615,13 +618,20 @@ void av1_xform_quant(const AV1_COMMON *cm, MACROBLOCK *x, int plane, int block,
#if CONFIG_HIGHBITDEPTH
}
#endif // CONFIG_HIGHBITDEPTH
#endif
#endif // CONFIG_PVQ || CONFIG_DAALA_DIST
#endif // CONFIG_PVQ || CONFIG_DAALA_DIST || CONFIG_LGT
(void)ctx;
fwd_txfm_param.tx_type = tx_type;
fwd_txfm_param.tx_size = tx_size;
fwd_txfm_param.lossless = xd->lossless[mbmi->segment_id];
#if CONFIG_LGT
fwd_txfm_param.is_inter = is_inter_block(mbmi);
fwd_txfm_param.dst = dst;
fwd_txfm_param.stride = dst_stride;
fwd_txfm_param.mode = get_prediction_mode(xd->mi[0], plane, tx_size, block);
#endif
#if !CONFIG_PVQ
fwd_txfm_param.bd = xd->bd;
......@@ -743,8 +753,14 @@ static void encode_block(int plane, int block, int blk_row, int blk_col,
if (x->pvq_skip[plane]) return;
#endif
TX_TYPE tx_type = get_tx_type(pd->plane_type, xd, block, tx_size);
#if CONFIG_LGT
PREDICTION_MODE mode = get_prediction_mode(xd->mi[0], plane, tx_size, block);
av1_inverse_transform_block(xd, dqcoeff, mode, tx_type, tx_size, dst,
pd->dst.stride, p->eobs[block]);
#else
av1_inverse_transform_block(xd, dqcoeff, tx_type, tx_size, dst,
pd->dst.stride, p->eobs[block]);
#endif
}
#if CONFIG_VAR_TX
......@@ -1362,11 +1378,11 @@ void av1_encode_block_intra(int plane, int block, int blk_row, int blk_col,
av1_predict_intra_block_facade(xd, plane, block, blk_col, blk_row, tx_size);
#endif
#if CONFIG_DPCM_INTRA || CONFIG_LGT
const PREDICTION_MODE mode =
get_prediction_mode(xd->mi[0], plane, tx_size, block);
#if CONFIG_DPCM_INTRA
const int block_raster_idx = av1_block_index_to_raster_order(tx_size, block);
const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
const PREDICTION_MODE mode =
(plane == 0) ? get_y_mode(xd->mi[0], block_raster_idx) : mbmi->uv_mode;
if (av1_use_dpcm_intra(plane, mode, tx_type, mbmi)) {
av1_encode_block_intra_dpcm(cm, x, mode, plane, block, blk_row, blk_col,
plane_bsize, tx_size, tx_type, args->ta,
......@@ -1374,6 +1390,7 @@ void av1_encode_block_intra(int plane, int block, int blk_row, int blk_col,
return;
}
#endif // CONFIG_DPCM_INTRA
#endif // CONFIG_DPCM_INTRA || CONFIG_LGT
av1_subtract_txb(x, plane, plane_bsize, blk_col, blk_row, tx_size);
......@@ -1395,8 +1412,11 @@ void av1_encode_block_intra(int plane, int block, int blk_row, int blk_col,
if (x->pvq_skip[plane]) return;
#endif // CONFIG_PVQ
av1_inverse_transform_block(xd, dqcoeff, tx_type, tx_size, dst, dst_stride,
*eob);
av1_inverse_transform_block(xd, dqcoeff,
#if CONFIG_LGT
mode,
#endif
tx_type, tx_size, dst, dst_stride, *eob);
#if !CONFIG_PVQ
if (*eob) *(args->skip) = 0;
#else
......
......@@ -1694,8 +1694,11 @@ void av1_dist_block(const AV1_COMP *cpi, MACROBLOCK *x, int plane,
const PLANE_TYPE plane_type = get_plane_type(plane);
TX_TYPE tx_type = get_tx_type(plane_type, xd, block, tx_size);
av1_inverse_transform_block(xd, dqcoeff, tx_type, tx_size, recon,
MAX_TX_SIZE, eob);
av1_inverse_transform_block(xd, dqcoeff,
#if CONFIG_LGT
xd->mi[0]->mbmi.mode,
#endif
tx_type, tx_size, recon, MAX_TX_SIZE, eob);
#if CONFIG_DAALA_DIST
if (plane == 0 && (bsw < 8 || bsh < 8)) {
......@@ -3102,6 +3105,9 @@ static int64_t rd_pick_intra_sub_8x8_y_subblock_mode(
if (!skip)
#endif
av1_inverse_transform_block(xd, BLOCK_OFFSET(pd->dqcoeff, block),
#if CONFIG_LGT
mode,
#endif
DCT_DCT, tx_size, dst, dst_stride,
p->eobs[block]);
} else {
......@@ -3151,6 +3157,9 @@ static int64_t rd_pick_intra_sub_8x8_y_subblock_mode(
if (!skip)
#endif
av1_inverse_transform_block(xd, BLOCK_OFFSET(pd->dqcoeff, block),
#if CONFIG_LGT
mode,
#endif
tx_type, tx_size, dst, dst_stride,
p->eobs[block]);
cpi->fn_ptr[sub_bsize].vf(src, src_stride, dst, dst_stride, &tmp);
......@@ -3334,6 +3343,9 @@ static int64_t rd_pick_intra_sub_8x8_y_subblock_mode(
if (!skip)
#endif // CONFIG_PVQ
av1_inverse_transform_block(xd, BLOCK_OFFSET(pd->dqcoeff, block),
#if CONFIG_LGT
mode,
#endif
tx_type, tx_size, dst, dst_stride,
p->eobs[block]);
unsigned int tmp;
......@@ -3349,6 +3361,9 @@ static int64_t rd_pick_intra_sub_8x8_y_subblock_mode(
if (!skip)
#endif // CONFIG_PVQ
av1_inverse_transform_block(xd, BLOCK_OFFSET(pd->dqcoeff, block),
#if CONFIG_LGT
mode,
#endif
DCT_DCT, tx_size, dst, dst_stride,
p->eobs[block]);
}
......@@ -4254,8 +4269,14 @@ void av1_tx_block_rd_b(const AV1_COMP *cpi, MACROBLOCK *x, TX_SIZE tx_size,
rd_stats->sse += tmp * 16;
const int eob = p->eobs[block];
#if CONFIG_LGT
PREDICTION_MODE mode = get_prediction_mode(xd->mi[0], plane, tx_size, block);
av1_inverse_transform_block(xd, dqcoeff, mode, tx_type, tx_size, rec_buffer,
MAX_TX_SIZE, eob);
#else
av1_inverse_transform_block(xd, dqcoeff, tx_type, tx_size, rec_buffer,
MAX_TX_SIZE, eob);
#endif
if (eob > 0) {
#if CONFIG_DAALA_DIST
if (plane == 0 && (bw < 8 && bh < 8)) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment