Commit 0a8c9b4765 for aom
commit 0a8c9b4765b3f45503d9d63983b74a6a6b02ac08
Author: Frank Galligan <fgalligan@google.com>
Date: Sat Oct 31 09:54:05 2026 -0700
av1: Optimize PICK_MODE_CONTEXT and fwd DCT_DCT
Consolidate PICK_MODE_CONTEXT and its sub-buffers into a single 32-byte
aligned allocation, lazily allocate sub-partition contexts on demand,
inline cospi/sinpi/shift/cos_bit tables, and add DCT_DCT fast paths in
4x4, 8x8, 16x16, and 32x32 forward transforms.
Benchmarking results (incremental vs prev CL / cumulative vs baseline):
- Stock avifenc still-image (Default 1T): -1.86% / -27.36% encode time
- Stock avifenc still-image (Default 8T): -2.20% / -22.89% encode time
- 48-image multi-rate corpus (Full Suite 1T): -3.25% / -28.50% time
- Bit-exact output (1T and 8T)
TAG=agy
CONV=b929a630-a6cd-45a0-979c-1767c30178ee
Change-Id: Iac9624bee616fab3e366db9ee8c60e9b579b3402
diff --git a/av1/common/av1_txfm.h b/av1/common/av1_txfm.h
index bfe6a76a32..293b99e37d 100644
--- a/av1/common/av1_txfm.h
+++ b/av1/common/av1_txfm.h
@@ -46,11 +46,42 @@ static const int32_t NewSqrt2 = 5793;
static const int32_t NewInvSqrt2 = 2896;
static inline const int32_t *cospi_arr(int n) {
- return av1_cospi_arr_data[n - cos_bit_min];
+ static const int32_t av1_cospi_arr_data_inline[4][64] = {
+ { 1024, 1024, 1023, 1021, 1019, 1016, 1013, 1009, 1004, 999, 993, 987, 980,
+ 972, 964, 955, 946, 936, 926, 915, 903, 891, 878, 865, 851, 837,
+ 822, 807, 792, 775, 759, 742, 724, 706, 688, 669, 650, 630, 610,
+ 590, 569, 548, 526, 505, 483, 460, 438, 415, 392, 369, 345, 321,
+ 297, 273, 249, 224, 200, 175, 150, 125, 100, 75, 50, 25 },
+ { 2048, 2047, 2046, 2042, 2038, 2033, 2026, 2018, 2009, 1998, 1987,
+ 1974, 1960, 1945, 1928, 1911, 1892, 1872, 1851, 1829, 1806, 1782,
+ 1757, 1730, 1703, 1674, 1645, 1615, 1583, 1551, 1517, 1483, 1448,
+ 1412, 1375, 1338, 1299, 1260, 1220, 1179, 1138, 1096, 1053, 1009,
+ 965, 921, 876, 830, 784, 737, 690, 642, 595, 546, 498,
+ 449, 400, 350, 301, 251, 201, 151, 100, 50 },
+ { 4096, 4095, 4091, 4085, 4076, 4065, 4052, 4036, 4017, 3996, 3973,
+ 3948, 3920, 3889, 3857, 3822, 3784, 3745, 3703, 3659, 3612, 3564,
+ 3513, 3461, 3406, 3349, 3290, 3229, 3166, 3102, 3035, 2967, 2896,
+ 2824, 2751, 2675, 2598, 2520, 2440, 2359, 2276, 2191, 2106, 2019,
+ 1931, 1842, 1751, 1660, 1567, 1474, 1380, 1285, 1189, 1092, 995,
+ 897, 799, 700, 601, 501, 401, 301, 201, 101 },
+ { 8192, 8190, 8182, 8170, 8153, 8130, 8103, 8071, 8035, 7993, 7946,
+ 7895, 7839, 7779, 7713, 7643, 7568, 7489, 7405, 7317, 7225, 7128,
+ 7027, 6921, 6811, 6698, 6580, 6458, 6333, 6203, 6070, 5933, 5793,
+ 5649, 5501, 5351, 5197, 5040, 4880, 4717, 4551, 4383, 4212, 4038,
+ 3862, 3683, 3503, 3320, 3135, 2948, 2760, 2570, 2378, 2185, 1990,
+ 1795, 1598, 1401, 1202, 1003, 803, 603, 402, 201 }
+ };
+ return av1_cospi_arr_data_inline[n - cos_bit_min];
}
static inline const int32_t *sinpi_arr(int n) {
- return av1_sinpi_arr_data[n - cos_bit_min];
+ static const int32_t av1_sinpi_arr_data_inline[4][5] = {
+ { 0, 330, 621, 836, 951 },
+ { 0, 660, 1241, 1672, 1901 },
+ { 0, 1321, 2482, 3344, 3803 },
+ { 0, 2642, 4964, 6689, 7606 }
+ };
+ return av1_sinpi_arr_data_inline[n - cos_bit_min];
}
// The reduced bit-width and permuted arrays are only used in the Arm Neon
@@ -206,43 +237,13 @@ typedef struct TXFM_2D_FLIP_CFG {
} TXFM_2D_FLIP_CFG;
static inline void get_flip_cfg(TX_TYPE tx_type, int *ud_flip, int *lr_flip) {
- switch (tx_type) {
- case DCT_DCT:
- case ADST_DCT:
- case DCT_ADST:
- case ADST_ADST:
- *ud_flip = 0;
- *lr_flip = 0;
- break;
- case IDTX:
- case V_DCT:
- case H_DCT:
- case V_ADST:
- case H_ADST:
- *ud_flip = 0;
- *lr_flip = 0;
- break;
- case FLIPADST_DCT:
- case FLIPADST_ADST:
- case V_FLIPADST:
- *ud_flip = 1;
- *lr_flip = 0;
- break;
- case DCT_FLIPADST:
- case ADST_FLIPADST:
- case H_FLIPADST:
- *ud_flip = 0;
- *lr_flip = 1;
- break;
- case FLIPADST_FLIPADST:
- *ud_flip = 1;
- *lr_flip = 1;
- break;
- default:
- *ud_flip = 0;
- *lr_flip = 0;
- assert(0);
- }
+ assert((unsigned int)tx_type < TX_TYPES);
+ // ud_flip is 1 for FLIPADST_DCT (4), FLIPADST_FLIPADST (6),
+ // FLIPADST_ADST (8), V_FLIPADST (14) -> mask 0x4150.
+ // lr_flip is 1 for DCT_FLIPADST (5), FLIPADST_FLIPADST (6),
+ // ADST_FLIPADST (7), H_FLIPADST (15) -> mask 0x80E0.
+ *ud_flip = (0x4150 >> tx_type) & 1;
+ *lr_flip = (0x80E0 >> tx_type) & 1;
}
static inline void set_flip_cfg(TX_TYPE tx_type, TXFM_2D_FLIP_CFG *cfg) {
diff --git a/av1/encoder/av1_fwd_txfm1d_cfg.h b/av1/encoder/av1_fwd_txfm1d_cfg.h
index 99a3cdacfa..a57995feb5 100644
--- a/av1/encoder/av1_fwd_txfm1d_cfg.h
+++ b/av1/encoder/av1_fwd_txfm1d_cfg.h
@@ -13,7 +13,39 @@
#define AOM_AV1_ENCODER_AV1_FWD_TXFM1D_CFG_H_
#include "av1/common/enums.h"
#include "av1/encoder/av1_fwd_txfm1d.h"
-extern const int8_t *av1_fwd_txfm_shift_ls[TX_SIZES_ALL];
-extern const int8_t av1_fwd_cos_bit_col[5][5];
-extern const int8_t av1_fwd_cos_bit_row[5][5];
+
+static const int8_t av1_fwd_txfm_shift_ls[TX_SIZES_ALL][3] = {
+ { 2, 0, 0 }, // TX_4X4
+ { 2, -1, 0 }, // TX_8X8
+ { 2, -2, 0 }, // TX_16X16
+ { 2, -4, 0 }, // TX_32X32
+ { 0, -2, -2 }, // TX_64X64
+ { 2, -1, 0 }, // TX_4X8
+ { 2, -1, 0 }, // TX_8X4
+ { 2, -2, 0 }, // TX_8X16
+ { 2, -2, 0 }, // TX_16X8
+ { 2, -4, 0 }, // TX_16X32
+ { 2, -4, 0 }, // TX_32X16
+ { 0, -2, -2 }, // TX_32X64
+ { 2, -4, -2 }, // TX_64X32
+ { 2, -1, 0 }, // TX_4X16
+ { 2, -1, 0 }, // TX_16X4
+ { 2, -2, 0 }, // TX_8X32
+ { 2, -2, 0 }, // TX_32X8
+ { 0, -2, 0 }, // TX_16X64
+ { 2, -4, 0 }, // TX_64X16
+};
+
+static const int8_t av1_fwd_cos_bit_col[5][5] = { { 13, 13, 13, 0, 0 },
+ { 13, 13, 13, 12, 0 },
+ { 13, 13, 13, 12, 13 },
+ { 0, 13, 13, 12, 13 },
+ { 0, 0, 13, 12, 13 } };
+
+static const int8_t av1_fwd_cos_bit_row[5][5] = { { 13, 13, 12, 0, 0 },
+ { 13, 13, 13, 12, 0 },
+ { 13, 13, 12, 13, 12 },
+ { 0, 12, 13, 12, 11 },
+ { 0, 0, 12, 11, 10 } };
+
#endif // AOM_AV1_ENCODER_AV1_FWD_TXFM1D_CFG_H_
diff --git a/av1/encoder/av1_fwd_txfm2d.c b/av1/encoder/av1_fwd_txfm2d.c
index 0d44341db0..a0ff21baaf 100644
--- a/av1/encoder/av1_fwd_txfm2d.c
+++ b/av1/encoder/av1_fwd_txfm2d.c
@@ -317,52 +317,6 @@ void av1_fwd_txfm2d_64x16_c(const int16_t *input, int32_t *output, int stride,
}
#endif // !CONFIG_REALTIME_ONLY
-static const int8_t fwd_shift_4x4[3] = { 2, 0, 0 };
-static const int8_t fwd_shift_8x8[3] = { 2, -1, 0 };
-static const int8_t fwd_shift_16x16[3] = { 2, -2, 0 };
-static const int8_t fwd_shift_32x32[3] = { 2, -4, 0 };
-static const int8_t fwd_shift_64x64[3] = { 0, -2, -2 };
-static const int8_t fwd_shift_4x8[3] = { 2, -1, 0 };
-static const int8_t fwd_shift_8x4[3] = { 2, -1, 0 };
-static const int8_t fwd_shift_8x16[3] = { 2, -2, 0 };
-static const int8_t fwd_shift_16x8[3] = { 2, -2, 0 };
-static const int8_t fwd_shift_16x32[3] = { 2, -4, 0 };
-static const int8_t fwd_shift_32x16[3] = { 2, -4, 0 };
-static const int8_t fwd_shift_32x64[3] = { 0, -2, -2 };
-static const int8_t fwd_shift_64x32[3] = { 2, -4, -2 };
-static const int8_t fwd_shift_4x16[3] = { 2, -1, 0 };
-static const int8_t fwd_shift_16x4[3] = { 2, -1, 0 };
-static const int8_t fwd_shift_8x32[3] = { 2, -2, 0 };
-static const int8_t fwd_shift_32x8[3] = { 2, -2, 0 };
-static const int8_t fwd_shift_16x64[3] = { 0, -2, 0 };
-static const int8_t fwd_shift_64x16[3] = { 2, -4, 0 };
-
-const int8_t *av1_fwd_txfm_shift_ls[TX_SIZES_ALL] = {
- fwd_shift_4x4, fwd_shift_8x8, fwd_shift_16x16, fwd_shift_32x32,
- fwd_shift_64x64, fwd_shift_4x8, fwd_shift_8x4, fwd_shift_8x16,
- fwd_shift_16x8, fwd_shift_16x32, fwd_shift_32x16, fwd_shift_32x64,
- fwd_shift_64x32, fwd_shift_4x16, fwd_shift_16x4, fwd_shift_8x32,
- fwd_shift_32x8, fwd_shift_16x64, fwd_shift_64x16,
-};
-
-const int8_t av1_fwd_cos_bit_col[MAX_TXWH_IDX /*txw_idx*/]
- [MAX_TXWH_IDX /*txh_idx*/] = {
- { 13, 13, 13, 0, 0 },
- { 13, 13, 13, 12, 0 },
- { 13, 13, 13, 12, 13 },
- { 0, 13, 13, 12, 13 },
- { 0, 0, 13, 12, 13 }
- };
-
-const int8_t av1_fwd_cos_bit_row[MAX_TXWH_IDX /*txw_idx*/]
- [MAX_TXWH_IDX /*txh_idx*/] = {
- { 13, 13, 12, 0, 0 },
- { 13, 13, 13, 12, 0 },
- { 13, 13, 12, 13, 12 },
- { 0, 12, 13, 12, 11 },
- { 0, 0, 12, 11, 10 }
- };
-
static const int8_t fdct4_range_mult2[4] = { 0, 2, 3, 3 };
static const int8_t fdct8_range_mult2[6] = { 0, 2, 4, 5, 5, 5 };
static const int8_t fdct16_range_mult2[8] = { 0, 2, 4, 6, 7, 7, 7, 7 };
diff --git a/av1/encoder/context_tree.c b/av1/encoder/context_tree.c
index 74b82e5d89..33103844b5 100644
--- a/av1/encoder/context_tree.c
+++ b/av1/encoder/context_tree.c
@@ -65,50 +65,58 @@ void av1_free_shared_coeff_buffer(PC_TREE_SHARED_BUFFERS *shared_bufs) {
PICK_MODE_CONTEXT *av1_alloc_pmc(const struct AV1_COMP *const cpi,
BLOCK_SIZE bsize,
PC_TREE_SHARED_BUFFERS *shared_bufs) {
- PICK_MODE_CONTEXT *volatile ctx = NULL;
const AV1_COMMON *const cm = &cpi->common;
- struct aom_internal_error_info error;
-
- if (setjmp(error.jmp)) {
- av1_free_pmc(ctx, av1_num_planes(cm));
- return NULL;
- }
- error.setjmp = 1;
-
- AOM_CHECK_MEM_ERROR(&error, ctx, aom_calloc(1, sizeof(*ctx)));
- ctx->rd_mode_is_ready = 0;
-
const int num_planes = av1_num_planes(cm);
const int num_pix = block_size_wide[bsize] * block_size_high[bsize];
const int num_blk = num_pix / 16;
- AOM_CHECK_MEM_ERROR(&error, ctx->tx_type_map,
- aom_calloc(num_blk, sizeof(*ctx->tx_type_map)));
+ // Allocate PICK_MODE_CONTEXT and all sub-arrays (eobs, txb_entropy_ctx,
+ // color_index_map, tx_type_map) in a single 32-byte aligned memory block to
+ // avoid multiple aom_memalign/aom_free calls per partition context.
+ const size_t ctx_sz = (sizeof(PICK_MODE_CONTEXT) + 31) & ~(size_t)31;
+ const size_t eob_sz = (num_blk * sizeof(uint16_t) + 31) & ~(size_t)31;
+ const size_t txb_ctx_sz =
+ (num_blk * sizeof(ENTROPY_CONTEXT) + 31) & ~(size_t)31;
+ const bool use_palette = (num_pix <= MAX_PALETTE_SQUARE) &&
+ cm->features.allow_screen_content_tools;
+ const size_t pal_sz =
+ use_palette ? ((num_pix * sizeof(uint8_t) + 31) & ~(size_t)31) : 0;
+ const size_t tx_type_sz = num_blk * sizeof(uint8_t);
+
+ const size_t total_sz = ctx_sz + (size_t)num_planes * (eob_sz + txb_ctx_sz) +
+ 2 * pal_sz + tx_type_sz;
+ uint8_t *raw = (uint8_t *)aom_memalign(32, total_sz);
+ if (!raw) return NULL;
+
+ PICK_MODE_CONTEXT *ctx = (PICK_MODE_CONTEXT *)raw;
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->rd_mode_is_ready = 0;
ctx->num_4x4_blk = num_blk;
+ uint8_t *ptr = raw + ctx_sz;
for (int i = 0; i < num_planes; ++i) {
ctx->coeff[i] = shared_bufs->coeff_buf[i];
ctx->qcoeff[i] = shared_bufs->qcoeff_buf[i];
ctx->dqcoeff[i] = shared_bufs->dqcoeff_buf[i];
- AOM_CHECK_MEM_ERROR(&error, ctx->eobs[i],
- aom_memalign(32, num_blk * sizeof(*ctx->eobs[i])));
- AOM_CHECK_MEM_ERROR(
- &error, ctx->txb_entropy_ctx[i],
- aom_memalign(32, num_blk * sizeof(*ctx->txb_entropy_ctx[i])));
+ ctx->eobs[i] = (uint16_t *)ptr;
+ ptr += eob_sz;
+ ctx->txb_entropy_ctx[i] = ptr;
+ ptr += txb_ctx_sz;
}
- if (num_pix <= MAX_PALETTE_SQUARE) {
- for (int i = 0; i < 2; ++i) {
- if (cm->features.allow_screen_content_tools) {
- AOM_CHECK_MEM_ERROR(
- &error, ctx->color_index_map[i],
- aom_memalign(32, num_pix * sizeof(*ctx->color_index_map[i])));
- } else {
- ctx->color_index_map[i] = NULL;
- }
- }
+ if (use_palette) {
+ ctx->color_index_map[0] = ptr;
+ ptr += pal_sz;
+ ctx->color_index_map[1] = ptr;
+ ptr += pal_sz;
+ } else {
+ ctx->color_index_map[0] = NULL;
+ ctx->color_index_map[1] = NULL;
}
+ ctx->tx_type_map = ptr;
+ memset(ctx->tx_type_map, 0, tx_type_sz);
+
av1_invalid_rd_stats(&ctx->rd_stats);
return ctx;
@@ -120,26 +128,8 @@ void av1_reset_pmc(PICK_MODE_CONTEXT *ctx) {
}
void av1_free_pmc(PICK_MODE_CONTEXT *ctx, int num_planes) {
+ (void)num_planes;
if (ctx == NULL) return;
-
- aom_free(ctx->tx_type_map);
- for (int i = 0; i < num_planes; ++i) {
- ctx->coeff[i] = NULL;
- ctx->qcoeff[i] = NULL;
- ctx->dqcoeff[i] = NULL;
- aom_free(ctx->eobs[i]);
- ctx->eobs[i] = NULL;
- aom_free(ctx->txb_entropy_ctx[i]);
- ctx->txb_entropy_ctx[i] = NULL;
- }
-
- for (int i = 0; i < 2; ++i) {
- if (ctx->color_index_map[i]) {
- aom_free(ctx->color_index_map[i]);
- ctx->color_index_map[i] = NULL;
- }
- }
-
aom_free(ctx);
}
diff --git a/av1/encoder/partition_search.c b/av1/encoder/partition_search.c
index 132871c9c6..897be7b9ae 100644
--- a/av1/encoder/partition_search.c
+++ b/av1/encoder/partition_search.c
@@ -3595,14 +3595,12 @@ static void rectangular_partition_search(
get_partition_subsize(blk_params.bsize, partition_type);
assert(blk_params.subsize <= BLOCK_LARGEST);
av1_init_rd_stats(sum_rdc);
- for (int j = 0; j < SUB_PARTITIONS_RECT; j++) {
- if (cur_ctx[i][j][0] == NULL) {
- cur_ctx[i][j][0] =
- av1_alloc_pmc(cpi, blk_params.subsize, &td->shared_coeff_buf);
- if (!cur_ctx[i][j][0])
- aom_internal_error(x->e_mbd.error_info, AOM_CODEC_MEM_ERROR,
- "Failed to allocate PICK_MODE_CONTEXT");
- }
+ if (cur_ctx[i][0][0] == NULL) {
+ cur_ctx[i][0][0] =
+ av1_alloc_pmc(cpi, blk_params.subsize, &td->shared_coeff_buf);
+ if (!cur_ctx[i][0][0])
+ aom_internal_error(x->e_mbd.error_info, AOM_CODEC_MEM_ERROR,
+ "Failed to allocate PICK_MODE_CONTEXT");
}
sum_rdc->rate = part_search_state->partition_cost[partition_type];
sum_rdc->rdcost = RDCOST(x->rdmult, sum_rdc->rate, 0);
@@ -3624,6 +3622,13 @@ static void rectangular_partition_search(
// Evaluate second sub-partition if the first sub-partition cost
// is less than the best cost and if it is not an edge block.
if (sum_rdc->rdcost < best_rdc->rdcost && is_not_edge_block[i]) {
+ if (cur_ctx[i][1][0] == NULL) {
+ cur_ctx[i][1][0] =
+ av1_alloc_pmc(cpi, blk_params.subsize, &td->shared_coeff_buf);
+ if (!cur_ctx[i][1][0])
+ aom_internal_error(x->e_mbd.error_info, AOM_CODEC_MEM_ERROR,
+ "Failed to allocate PICK_MODE_CONTEXT");
+ }
const MB_MODE_INFO *const mbmi = &cur_ctx[i][sub_part_idx][0]->mic;
const PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
// Neither palette mode nor cfl predicted.
@@ -3922,19 +3927,16 @@ static void set_4_part_ctx_and_rdcost(
PICK_MODE_CONTEXT *cur_part_ctx[SUB_PARTITIONS_PART4],
PartitionSearchState *part_search_state, PARTITION_TYPE partition_type,
BLOCK_SIZE bsize) {
+ (void)cpi;
+ (void)td;
+ (void)cur_part_ctx;
+ (void)bsize;
// Initialize sum_rdc RD cost structure.
av1_init_rd_stats(&part_search_state->sum_rdc);
- const int subsize = get_partition_subsize(bsize, partition_type);
part_search_state->sum_rdc.rate =
part_search_state->partition_cost[partition_type];
part_search_state->sum_rdc.rdcost =
RDCOST(x->rdmult, part_search_state->sum_rdc.rate, 0);
- for (PART4_TYPES i = 0; i < SUB_PARTITIONS_PART4; ++i) {
- cur_part_ctx[i] = av1_alloc_pmc(cpi, subsize, &td->shared_coeff_buf);
- if (!cur_part_ctx[i])
- aom_internal_error(x->e_mbd.error_info, AOM_CODEC_MEM_ERROR,
- "Failed to allocate PICK_MODE_CONTEXT");
- }
}
// Partition search of HORZ4 / VERT4 partition types.
@@ -3969,6 +3971,13 @@ static void rd_pick_4partition(
for (PART4_TYPES i = 0; i < SUB_PARTITIONS_PART4; ++i) {
if (i > 0 && mi_pos[i][part4_idx] >= mi_pos_check[part4_idx]) break;
+ if (cur_part_ctx[i] == NULL) {
+ cur_part_ctx[i] =
+ av1_alloc_pmc(cpi, blk_params.subsize, &td->shared_coeff_buf);
+ if (!cur_part_ctx[i])
+ aom_internal_error(x->e_mbd.error_info, AOM_CODEC_MEM_ERROR,
+ "Failed to allocate PICK_MODE_CONTEXT");
+ }
// Sub-block evaluation of Horz4 / Vert4 partition type.
cur_part_ctx[i]->rd_mode_is_ready = 0;
if (!rd_try_subblock(
diff --git a/av1/encoder/x86/av1_fwd_txfm2d_avx2.c b/av1/encoder/x86/av1_fwd_txfm2d_avx2.c
index 9b25ae96e8..cf3c1166b7 100644
--- a/av1/encoder/x86/av1_fwd_txfm2d_avx2.c
+++ b/av1/encoder/x86/av1_fwd_txfm2d_avx2.c
@@ -20,8 +20,9 @@
#include "av1/encoder/x86/av1_fwd_txfm_sse2.h"
#include "aom_dsp/x86/txfm_common_avx2.h"
-static inline void fdct16x16_new_avx2(const __m256i *input, __m256i *output,
- int8_t cos_bit) {
+static AOM_FORCE_INLINE void fdct16x16_new_avx2(const __m256i *input,
+ __m256i *output,
+ int8_t cos_bit) {
const int32_t *cospi = cospi_arr(cos_bit);
const __m256i _r = _mm256_set1_epi32(1 << (cos_bit - 1));
@@ -113,8 +114,20 @@ static inline void fdct16x16_new_avx2(const __m256i *input, __m256i *output,
output[15] = x1[15];
}
-static inline void fdct16x32_avx2(const __m256i *input, __m256i *output,
- int8_t cos_bit) {
+static inline void fdct16x16_cb13_avx2(const __m256i *input, __m256i *output,
+ int8_t cos_bit) {
+ (void)cos_bit;
+ fdct16x16_new_avx2(input, output, 13);
+}
+
+static inline void fdct16x16_cb12_avx2(const __m256i *input, __m256i *output,
+ int8_t cos_bit) {
+ (void)cos_bit;
+ fdct16x16_new_avx2(input, output, 12);
+}
+
+static AOM_FORCE_INLINE void fdct16x32_avx2(const __m256i *input,
+ __m256i *output, int8_t cos_bit) {
const int32_t *cospi = cospi_arr(cos_bit);
const __m256i _r = _mm256_set1_epi32(1 << (cos_bit - 1));
@@ -304,6 +317,18 @@ static inline void fdct16x32_avx2(const __m256i *input, __m256i *output,
output[31] = x1[31];
}
+static inline void fdct16x32_cb12_avx2(const __m256i *input, __m256i *output,
+ int8_t cos_bit) {
+ (void)cos_bit;
+ fdct16x32_avx2(input, output, 12);
+}
+
+static inline void fdct16x32_cb13_avx2(const __m256i *input, __m256i *output,
+ int8_t cos_bit) {
+ (void)cos_bit;
+ fdct16x32_avx2(input, output, 13);
+}
+
static inline void fdct16x64_new_avx2(const __m256i *input, __m256i *output,
int8_t cos_bit) {
const int32_t *cospi = cospi_arr(cos_bit);
@@ -712,7 +737,9 @@ static inline void fdct16x64_new_avx2(const __m256i *input, __m256i *output,
}
static inline void fdct32_avx2(const __m256i *input, __m256i *output,
- int8_t cos_bit) {
+ int8_t cos_bit_arg) {
+ (void)cos_bit_arg;
+ const int8_t cos_bit = 11;
__m256i x1[32];
const int32_t *cospi = cospi_arr(cos_bit);
const __m256i _r = _mm256_set1_epi32(1 << (cos_bit - 1));
@@ -1278,8 +1305,9 @@ static inline void fdct64_new_avx2(const __m256i *input, __m256i *output,
output[63] = x1[63];
}
-static inline void fadst16x16_new_avx2(const __m256i *input, __m256i *output,
- int8_t cos_bit) {
+static AOM_FORCE_INLINE void fadst16x16_new_avx2(const __m256i *input,
+ __m256i *output,
+ int8_t cos_bit) {
const int32_t *cospi = cospi_arr(cos_bit);
const __m256i __zero = _mm256_setzero_si256();
const __m256i _r = _mm256_set1_epi32(1 << (cos_bit - 1));
@@ -1408,6 +1436,18 @@ static inline void fadst16x16_new_avx2(const __m256i *input, __m256i *output,
output[15] = x1[0];
}
+static inline void fadst16x16_cb13_avx2(const __m256i *input, __m256i *output,
+ int8_t cos_bit) {
+ (void)cos_bit;
+ fadst16x16_new_avx2(input, output, 13);
+}
+
+static inline void fadst16x16_cb12_avx2(const __m256i *input, __m256i *output,
+ int8_t cos_bit) {
+ (void)cos_bit;
+ fadst16x16_new_avx2(input, output, 12);
+}
+
static inline void fidentity16x16_new_avx2(const __m256i *input,
__m256i *output, int8_t cos_bit) {
(void)cos_bit;
@@ -1480,7 +1520,7 @@ typedef void (*transform_1d_avx2)(const __m256i *input, __m256i *output,
int8_t cos_bit);
static const transform_1d_avx2 col_txfm16x32_arr[TX_TYPES] = {
- fdct16x32_avx2, // DCT_DCT
+ fdct16x32_cb12_avx2, // DCT_DCT
NULL, // ADST_DCT
NULL, // DCT_ADST
NULL, // ADST_ADST
@@ -1490,7 +1530,7 @@ static const transform_1d_avx2 col_txfm16x32_arr[TX_TYPES] = {
NULL, // ADST_FLIPADST
NULL, // FLIPADST_ADST
fidentity16x32_avx2, // IDTX
- fdct16x32_avx2, // V_DCT
+ fdct16x32_cb12_avx2, // V_DCT
fidentity16x32_avx2, // H_DCT
NULL, // V_ADST
NULL, // H_ADST
@@ -1498,8 +1538,8 @@ static const transform_1d_avx2 col_txfm16x32_arr[TX_TYPES] = {
NULL // H_FLIPADST
};
-static const transform_1d_avx2 row_txfm16x32_arr[TX_TYPES] = {
- fdct16x32_avx2, // DCT_DCT
+static const transform_1d_avx2 row_txfm16x32_cb12_arr[TX_TYPES] = {
+ fdct16x32_cb12_avx2, // DCT_DCT
NULL, // ADST_DCT
NULL, // DCT_ADST
NULL, // ADST_ADST
@@ -1510,7 +1550,26 @@ static const transform_1d_avx2 row_txfm16x32_arr[TX_TYPES] = {
NULL, // FLIPADST_ADST
fidentity16x32_avx2, // IDTX
fidentity16x32_avx2, // V_DCT
- fdct16x32_avx2, // H_DCT
+ fdct16x32_cb12_avx2, // H_DCT
+ NULL, // V_ADST
+ NULL, // H_ADST
+ NULL, // V_FLIPADST
+ NULL // H_FLIPADST
+};
+
+static const transform_1d_avx2 row_txfm16x32_cb13_arr[TX_TYPES] = {
+ fdct16x32_cb13_avx2, // DCT_DCT
+ NULL, // ADST_DCT
+ NULL, // DCT_ADST
+ NULL, // ADST_ADST
+ NULL, // FLIPADST_DCT
+ NULL, // DCT_FLIPADST
+ NULL, // FLIPADST_FLIPADST
+ NULL, // ADST_FLIPADST
+ NULL, // FLIPADST_ADST
+ fidentity16x32_avx2, // IDTX
+ fidentity16x32_avx2, // V_DCT
+ fdct16x32_cb13_avx2, // H_DCT
NULL, // V_ADST
NULL, // H_ADST
NULL, // V_FLIPADST
@@ -1518,79 +1577,98 @@ static const transform_1d_avx2 row_txfm16x32_arr[TX_TYPES] = {
};
static const transform_1d_avx2 col_txfm16x16_arr[TX_TYPES] = {
- fdct16x16_new_avx2, // DCT_DCT
- fadst16x16_new_avx2, // ADST_DCT
- fdct16x16_new_avx2, // DCT_ADST
- fadst16x16_new_avx2, // ADST_ADST
- fadst16x16_new_avx2, // FLIPADST_DCT
- fdct16x16_new_avx2, // DCT_FLIPADST
- fadst16x16_new_avx2, // FLIPADST_FLIPADST
- fadst16x16_new_avx2, // ADST_FLIPADST
- fadst16x16_new_avx2, // FLIPADST_ADST
+ fdct16x16_cb13_avx2, // DCT_DCT
+ fadst16x16_cb13_avx2, // ADST_DCT
+ fdct16x16_cb13_avx2, // DCT_ADST
+ fadst16x16_cb13_avx2, // ADST_ADST
+ fadst16x16_cb13_avx2, // FLIPADST_DCT
+ fdct16x16_cb13_avx2, // DCT_FLIPADST
+ fadst16x16_cb13_avx2, // FLIPADST_FLIPADST
+ fadst16x16_cb13_avx2, // ADST_FLIPADST
+ fadst16x16_cb13_avx2, // FLIPADST_ADST
fidentity16x16_new_avx2, // IDTX
- fdct16x16_new_avx2, // V_DCT
+ fdct16x16_cb13_avx2, // V_DCT
fidentity16x16_new_avx2, // H_DCT
- fadst16x16_new_avx2, // V_ADST
+ fadst16x16_cb13_avx2, // V_ADST
fidentity16x16_new_avx2, // H_ADST
- fadst16x16_new_avx2, // V_FLIPADST
+ fadst16x16_cb13_avx2, // V_FLIPADST
fidentity16x16_new_avx2 // H_FLIPADST
};
-static const transform_1d_avx2 row_txfm16x16_arr[TX_TYPES] = {
- fdct16x16_new_avx2, // DCT_DCT
- fdct16x16_new_avx2, // ADST_DCT
- fadst16x16_new_avx2, // DCT_ADST
- fadst16x16_new_avx2, // ADST_ADST
- fdct16x16_new_avx2, // FLIPADST_DCT
- fadst16x16_new_avx2, // DCT_FLIPADST
- fadst16x16_new_avx2, // FLIPADST_FLIPADST
- fadst16x16_new_avx2, // ADST_FLIPADST
- fadst16x16_new_avx2, // FLIPADST_ADST
+static const transform_1d_avx2 row_txfm16x16_cb12_arr[TX_TYPES] = {
+ fdct16x16_cb12_avx2, // DCT_DCT
+ fdct16x16_cb12_avx2, // ADST_DCT
+ fadst16x16_cb12_avx2, // DCT_ADST
+ fadst16x16_cb12_avx2, // ADST_ADST
+ fdct16x16_cb12_avx2, // FLIPADST_DCT
+ fadst16x16_cb12_avx2, // DCT_FLIPADST
+ fadst16x16_cb12_avx2, // FLIPADST_FLIPADST
+ fadst16x16_cb12_avx2, // ADST_FLIPADST
+ fadst16x16_cb12_avx2, // FLIPADST_ADST
+ fidentity16x16_new_avx2, // IDTX
+ fidentity16x16_new_avx2, // V_DCT
+ fdct16x16_cb12_avx2, // H_DCT
+ fidentity16x16_new_avx2, // V_ADST
+ fadst16x16_cb12_avx2, // H_ADST
+ fidentity16x16_new_avx2, // V_FLIPADST
+ fadst16x16_cb12_avx2 // H_FLIPADST
+};
+
+static const transform_1d_avx2 row_txfm16x16_cb13_arr[TX_TYPES] = {
+ fdct16x16_cb13_avx2, // DCT_DCT
+ fdct16x16_cb13_avx2, // ADST_DCT
+ fadst16x16_cb13_avx2, // DCT_ADST
+ fadst16x16_cb13_avx2, // ADST_ADST
+ fdct16x16_cb13_avx2, // FLIPADST_DCT
+ fadst16x16_cb13_avx2, // DCT_FLIPADST
+ fadst16x16_cb13_avx2, // FLIPADST_FLIPADST
+ fadst16x16_cb13_avx2, // ADST_FLIPADST
+ fadst16x16_cb13_avx2, // FLIPADST_ADST
fidentity16x16_new_avx2, // IDTX
fidentity16x16_new_avx2, // V_DCT
- fdct16x16_new_avx2, // H_DCT
+ fdct16x16_cb13_avx2, // H_DCT
fidentity16x16_new_avx2, // V_ADST
- fadst16x16_new_avx2, // H_ADST
+ fadst16x16_cb13_avx2, // H_ADST
fidentity16x16_new_avx2, // V_FLIPADST
- fadst16x16_new_avx2 // H_FLIPADST
+ fadst16x16_cb13_avx2 // H_FLIPADST
};
static const transform_1d_sse2 col_txfm8x8_arr[TX_TYPES] = {
- fdct8x8_new_sse2, // DCT_DCT
- fadst8x8_new_sse2, // ADST_DCT
- fdct8x8_new_sse2, // DCT_ADST
- fadst8x8_new_sse2, // ADST_ADST
- fadst8x8_new_sse2, // FLIPADST_DCT
- fdct8x8_new_sse2, // DCT_FLIPADST
- fadst8x8_new_sse2, // FLIPADST_FLIPADST
- fadst8x8_new_sse2, // ADST_FLIPADST
- fadst8x8_new_sse2, // FLIPADST_ADST
+ fdct8x8_cb13_sse2, // DCT_DCT
+ fadst8x8_cb13_sse2, // ADST_DCT
+ fdct8x8_cb13_sse2, // DCT_ADST
+ fadst8x8_cb13_sse2, // ADST_ADST
+ fadst8x8_cb13_sse2, // FLIPADST_DCT
+ fdct8x8_cb13_sse2, // DCT_FLIPADST
+ fadst8x8_cb13_sse2, // FLIPADST_FLIPADST
+ fadst8x8_cb13_sse2, // ADST_FLIPADST
+ fadst8x8_cb13_sse2, // FLIPADST_ADST
fidentity8x8_new_sse2, // IDTX
- fdct8x8_new_sse2, // V_DCT
+ fdct8x8_cb13_sse2, // V_DCT
fidentity8x8_new_sse2, // H_DCT
- fadst8x8_new_sse2, // V_ADST
+ fadst8x8_cb13_sse2, // V_ADST
fidentity8x8_new_sse2, // H_ADST
- fadst8x8_new_sse2, // V_FLIPADST
+ fadst8x8_cb13_sse2, // V_FLIPADST
fidentity8x8_new_sse2, // H_FLIPADST
};
static const transform_1d_sse2 row_txfm8x8_arr[TX_TYPES] = {
- fdct8x8_new_sse2, // DCT_DCT
- fdct8x8_new_sse2, // ADST_DCT
- fadst8x8_new_sse2, // DCT_ADST
- fadst8x8_new_sse2, // ADST_ADST
- fdct8x8_new_sse2, // FLIPADST_DCT
- fadst8x8_new_sse2, // DCT_FLIPADST
- fadst8x8_new_sse2, // FLIPADST_FLIPADST
- fadst8x8_new_sse2, // ADST_FLIPADST
- fadst8x8_new_sse2, // FLIPADST_ADST
+ fdct8x8_cb13_sse2, // DCT_DCT
+ fdct8x8_cb13_sse2, // ADST_DCT
+ fadst8x8_cb13_sse2, // DCT_ADST
+ fadst8x8_cb13_sse2, // ADST_ADST
+ fdct8x8_cb13_sse2, // FLIPADST_DCT
+ fadst8x8_cb13_sse2, // DCT_FLIPADST
+ fadst8x8_cb13_sse2, // FLIPADST_FLIPADST
+ fadst8x8_cb13_sse2, // ADST_FLIPADST
+ fadst8x8_cb13_sse2, // FLIPADST_ADST
fidentity8x8_new_sse2, // IDTX
fidentity8x8_new_sse2, // V_DCT
- fdct8x8_new_sse2, // H_DCT
+ fdct8x8_cb13_sse2, // H_DCT
fidentity8x8_new_sse2, // V_ADST
- fadst8x8_new_sse2, // H_ADST
+ fadst8x8_cb13_sse2, // H_ADST
fidentity8x8_new_sse2, // V_FLIPADST
- fadst8x8_new_sse2 // H_FLIPADST
+ fadst8x8_cb13_sse2 // H_FLIPADST
};
static inline void load_buffer_and_round_shift(const int16_t *in, int stride,
@@ -1775,6 +1853,17 @@ static void av1_lowbd_fwd_txfm2d_8x8_avx2(const int16_t *input, int32_t *output,
(void)bd;
__m128i buf0[8], buf1[8], *buf;
const int8_t *shift = av1_fwd_txfm_shift_ls[TX_8X8];
+
+ // Fast path for DCT_DCT: bypass function pointer table and flip checks.
+ if (tx_type == DCT_DCT) {
+ load_buffer_and_round_shift(input, stride, buf0, shift[0]);
+ fdct8x8_new_sse2(buf0, buf0, 13);
+ transpose_round_shift_8x8(buf0, buf1, shift[1]);
+ fdct8x8_new_sse2(buf1, buf1, 13);
+ store_buffer_16bit_to_32bit_w8_avx2(buf1, output, 8, 8);
+ return;
+ }
+
const int txw_idx = get_txw_idx(TX_8X8);
const int txh_idx = get_txh_idx(TX_8X8);
const int cos_bit_col = av1_fwd_cos_bit_col[txw_idx][txh_idx];
@@ -1818,14 +1907,27 @@ static void lowbd_fwd_txfm2d_16x16_avx2(const int16_t *input, int32_t *output,
const TX_SIZE tx_size = TX_16X16;
__m256i buf0[16], buf1[16];
const int8_t *shift = av1_fwd_txfm_shift_ls[tx_size];
+ const int width = tx_size_wide[tx_size];
+ const int height = tx_size_high[tx_size];
+
+ // Fast path for DCT_DCT: inline 16x16 DCT with constant cos_bit (13, 12).
+ if (tx_type == DCT_DCT) {
+ load_buffer_16bit_to_16bit_avx2(input, stride, buf0, height);
+ round_shift_16bit_w16_avx2(buf0, height, shift[0]);
+ fdct16x16_new_avx2(buf0, buf0, 13);
+ round_shift_16bit_w16_avx2(buf0, height, shift[1]);
+ transpose_16bit_16x16_avx2(buf0, buf1);
+ fdct16x16_new_avx2(buf1, buf1, 12);
+ store_buffer_16bit_to_32bit_w16_avx2(buf1, output, height, width);
+ return;
+ }
+
const int txw_idx = get_txw_idx(tx_size);
const int txh_idx = get_txh_idx(tx_size);
const int cos_bit_col = av1_fwd_cos_bit_col[txw_idx][txh_idx];
const int cos_bit_row = av1_fwd_cos_bit_row[txw_idx][txh_idx];
- const int width = tx_size_wide[tx_size];
- const int height = tx_size_high[tx_size];
const transform_1d_avx2 col_txfm = col_txfm16x16_arr[tx_type];
- const transform_1d_avx2 row_txfm = row_txfm16x16_arr[tx_type];
+ const transform_1d_avx2 row_txfm = row_txfm16x16_cb12_arr[tx_type];
int ud_flip, lr_flip;
get_flip_cfg(tx_type, &ud_flip, &lr_flip);
@@ -1856,16 +1958,35 @@ static void lowbd_fwd_txfm2d_32x32_avx2(const int16_t *input, int32_t *output,
int stride, TX_TYPE tx_type, int bd) {
(void)bd;
const TX_SIZE tx_size = TX_32X32;
- __m256i buf0[32], buf1[128];
+ __m256i buf0[32], buf1[64];
const int8_t *shift = av1_fwd_txfm_shift_ls[tx_size];
+ const int width = tx_size_wide[tx_size];
+ const int height = tx_size_high[tx_size];
+
+ // Fast path for DCT_DCT: inline 32x32 DCT with constant cos_bit (12).
+ if (tx_type == DCT_DCT) {
+ for (int i = 0; i < 2; i++) {
+ load_buffer_16bit_to_16bit_avx2(input + 16 * i, stride, buf0, height);
+ round_shift_16bit_w16_avx2(buf0, height, shift[0]);
+ fdct16x32_avx2(buf0, buf0, 12);
+ round_shift_16bit_w16_avx2(buf0, height, shift[1]);
+ transpose_16bit_16x16_avx2(buf0 + 0 * 16, buf1 + 0 * width + 16 * i);
+ transpose_16bit_16x16_avx2(buf0 + 1 * 16, buf1 + 1 * width + 16 * i);
+ }
+ for (int i = 0; i < 2; i++) {
+ __m256i *buf = buf1 + width * i;
+ fdct16x32_avx2(buf, buf, 12);
+ store_buffer_16bit_to_32bit_w16_avx2(buf, output + i * 16, height, width);
+ }
+ return;
+ }
+
const int txw_idx = get_txw_idx(tx_size);
const int txh_idx = get_txh_idx(tx_size);
const int cos_bit_col = av1_fwd_cos_bit_col[txw_idx][txh_idx];
const int cos_bit_row = av1_fwd_cos_bit_row[txw_idx][txh_idx];
- const int width = tx_size_wide[tx_size];
- const int height = tx_size_high[tx_size];
const transform_1d_avx2 col_txfm = col_txfm16x32_arr[tx_type];
- const transform_1d_avx2 row_txfm = row_txfm16x32_arr[tx_type];
+ const transform_1d_avx2 row_txfm = row_txfm16x32_cb12_arr[tx_type];
int ud_flip, lr_flip;
get_flip_cfg(tx_type, &ud_flip, &lr_flip);
@@ -1955,7 +2076,7 @@ static void lowbd_fwd_txfm2d_16x32_avx2(const int16_t *input, int32_t *output,
const int width = tx_size_wide[tx_size];
const int height = tx_size_high[tx_size];
const transform_1d_avx2 col_txfm = col_txfm16x32_arr[tx_type];
- const transform_1d_avx2 row_txfm = row_txfm16x16_arr[tx_type];
+ const transform_1d_avx2 row_txfm = row_txfm16x16_cb13_arr[tx_type];
int ud_flip, lr_flip;
get_flip_cfg(tx_type, &ud_flip, &lr_flip);
@@ -1998,7 +2119,7 @@ static void lowbd_fwd_txfm2d_32x16_avx2(const int16_t *input, int32_t *output,
const int width = 32;
const int height = 16;
const transform_1d_avx2 col_txfm = col_txfm16x16_arr[tx_type];
- const transform_1d_avx2 row_txfm = row_txfm16x32_arr[tx_type];
+ const transform_1d_avx2 row_txfm = row_txfm16x32_cb13_arr[tx_type];
int ud_flip, lr_flip;
get_flip_cfg(tx_type, &ud_flip, &lr_flip);
@@ -2223,7 +2344,9 @@ static inline void btf_16_avx2(__m256i *w0, __m256i *w1, __m256i *in0,
}
static inline void fdct8x8_new_avx2(const __m256i *input, __m256i *output,
- int8_t cos_bit) {
+ int8_t cos_bit_arg) {
+ (void)cos_bit_arg;
+ const int8_t cos_bit = 13;
const int32_t *cospi = cospi_arr(cos_bit);
const __m256i __rounding = _mm256_set1_epi32(1 << (cos_bit - 1));
@@ -2302,7 +2425,9 @@ static inline void fdct8x8_new_avx2(const __m256i *input, __m256i *output,
}
static inline void fadst8x8_new_avx2(const __m256i *input, __m256i *output,
- int8_t cos_bit) {
+ int8_t cos_bit_arg) {
+ (void)cos_bit_arg;
+ const int8_t cos_bit = 13;
const int32_t *cospi = cospi_arr(cos_bit);
const __m256i __zero = _mm256_setzero_si256();
const __m256i __rounding = _mm256_set1_epi32(1 << (cos_bit - 1));
@@ -2429,7 +2554,9 @@ static inline void fidentity8x8_new_avx2(const __m256i *input, __m256i *output,
}
static inline void fdct8x16_new_avx2(const __m128i *input, __m128i *output,
- int8_t cos_bit) {
+ int8_t cos_bit_arg) {
+ (void)cos_bit_arg;
+ int8_t cos_bit = 13;
const int32_t *cospi = cospi_arr(cos_bit);
const __m256i __rounding_256 = _mm256_set1_epi32(1 << (cos_bit - 1));
const __m128i __rounding = _mm_set1_epi32(1 << (cos_bit - 1));
@@ -2578,7 +2705,9 @@ static inline void fdct8x16_new_avx2(const __m128i *input, __m128i *output,
}
static inline void fadst8x16_new_avx2(const __m128i *input, __m128i *output,
- int8_t cos_bit) {
+ int8_t cos_bit_arg) {
+ (void)cos_bit_arg;
+ int8_t cos_bit = 13;
const int32_t *cospi = cospi_arr(cos_bit);
const __m256i __zero = _mm256_setzero_si256();
const __m256i __rounding_256 = _mm256_set1_epi32(1 << (cos_bit - 1));
diff --git a/av1/encoder/x86/av1_fwd_txfm_sse2.c b/av1/encoder/x86/av1_fwd_txfm_sse2.c
index f6733a338d..0696e80cdf 100644
--- a/av1/encoder/x86/av1_fwd_txfm_sse2.c
+++ b/av1/encoder/x86/av1_fwd_txfm_sse2.c
@@ -17,12 +17,14 @@
static void fdct4x4_new_sse2(const __m128i *input, __m128i *output,
int8_t cos_bit) {
- const int32_t *cospi = cospi_arr(cos_bit);
+ (void)cos_bit;
+ const int8_t cb = 13;
+ const int32_t *cospi = cospi_arr(cb);
const __m128i cospi_p32_p32 = pair_set_epi16(cospi[32], cospi[32]);
const __m128i cospi_p32_m32 = pair_set_epi16(cospi[32], -cospi[32]);
const __m128i cospi_p16_p48 = pair_set_epi16(cospi[16], cospi[48]);
const __m128i cospi_p48_m16 = pair_set_epi16(cospi[48], -cospi[16]);
- const __m128i __rounding = _mm_set1_epi32(1 << (cos_bit - 1));
+ const __m128i __rounding = _mm_set1_epi32(1 << (cb - 1));
__m128i u[4], v[4];
u[0] = _mm_unpacklo_epi16(input[0], input[1]);
@@ -40,10 +42,10 @@ static void fdct4x4_new_sse2(const __m128i *input, __m128i *output,
v[1] = _mm_add_epi32(u[1], __rounding);
v[2] = _mm_add_epi32(u[2], __rounding);
v[3] = _mm_add_epi32(u[3], __rounding);
- u[0] = _mm_srai_epi32(v[0], cos_bit);
- u[1] = _mm_srai_epi32(v[1], cos_bit);
- u[2] = _mm_srai_epi32(v[2], cos_bit);
- u[3] = _mm_srai_epi32(v[3], cos_bit);
+ u[0] = _mm_srai_epi32(v[0], cb);
+ u[1] = _mm_srai_epi32(v[1], cb);
+ u[2] = _mm_srai_epi32(v[2], cb);
+ u[3] = _mm_srai_epi32(v[3], cb);
output[0] = _mm_packs_epi32(u[0], u[1]);
output[1] = _mm_packs_epi32(u[2], u[3]);
@@ -82,8 +84,10 @@ static void fdct8x4_new_sse2(const __m128i *input, __m128i *output,
static void fdct4x8_new_sse2(const __m128i *input, __m128i *output,
int8_t cos_bit) {
- const int32_t *cospi = cospi_arr(cos_bit);
- const __m128i __rounding = _mm_set1_epi32(1 << (cos_bit - 1));
+ (void)cos_bit;
+ const int8_t cb = 13;
+ const int32_t *cospi = cospi_arr(cb);
+ const __m128i __rounding = _mm_set1_epi32(1 << (cb - 1));
__m128i cospi_m32_p32 = pair_set_epi16(-cospi[32], cospi[32]);
__m128i cospi_p32_p32 = pair_set_epi16(cospi[32], cospi[32]);
@@ -113,16 +117,16 @@ static void fdct4x8_new_sse2(const __m128i *input, __m128i *output,
x2[1] = _mm_adds_epi16(x1[1], x1[2]);
x2[2] = _mm_subs_epi16(x1[1], x1[2]);
x2[4] = x1[4];
- btf_16_w4_sse2(&cospi_m32_p32, &cospi_p32_p32, __rounding, cos_bit, &x1[5],
- &x1[6], &x2[5], &x2[6]);
+ btf_16_w4_sse2(&cospi_m32_p32, &cospi_p32_p32, __rounding, cb, &x1[5], &x1[6],
+ &x2[5], &x2[6]);
x2[7] = x1[7];
// stage 3
__m128i x3[8];
- btf_16_w4_sse2(&cospi_p32_p32, &cospi_p32_m32, __rounding, cos_bit, &x2[0],
- &x2[1], &x3[0], &x3[1]);
- btf_16_w4_sse2(&cospi_p48_p16, &cospi_m16_p48, __rounding, cos_bit, &x2[2],
- &x2[3], &x3[2], &x3[3]);
+ btf_16_w4_sse2(&cospi_p32_p32, &cospi_p32_m32, __rounding, cb, &x2[0], &x2[1],
+ &x3[0], &x3[1]);
+ btf_16_w4_sse2(&cospi_p48_p16, &cospi_m16_p48, __rounding, cb, &x2[2], &x2[3],
+ &x3[2], &x3[3]);
x3[4] = _mm_adds_epi16(x2[4], x2[5]);
x3[5] = _mm_subs_epi16(x2[4], x2[5]);
x3[6] = _mm_subs_epi16(x2[7], x2[6]);
@@ -134,10 +138,10 @@ static void fdct4x8_new_sse2(const __m128i *input, __m128i *output,
x4[1] = x3[1];
x4[2] = x3[2];
x4[3] = x3[3];
- btf_16_w4_sse2(&cospi_p56_p08, &cospi_m08_p56, __rounding, cos_bit, &x3[4],
- &x3[7], &x4[4], &x4[7]);
- btf_16_w4_sse2(&cospi_p24_p40, &cospi_m40_p24, __rounding, cos_bit, &x3[5],
- &x3[6], &x4[5], &x4[6]);
+ btf_16_w4_sse2(&cospi_p56_p08, &cospi_m08_p56, __rounding, cb, &x3[4], &x3[7],
+ &x4[4], &x4[7]);
+ btf_16_w4_sse2(&cospi_p24_p40, &cospi_m40_p24, __rounding, cb, &x3[5], &x3[6],
+ &x4[5], &x4[6]);
// stage 5
output[0] = x4[0];
@@ -1353,7 +1357,9 @@ void av1_fdct8x64_new_sse2(const __m128i *input, __m128i *output,
}
static void fadst4x4_new_sse2(const __m128i *input, __m128i *output,
- int8_t cos_bit) {
+ int8_t cos_bit_arg) {
+ (void)cos_bit_arg;
+ const int8_t cos_bit = 13;
const int32_t *sinpi = sinpi_arr(cos_bit);
const __m128i sinpi_p01_p02 = pair_set_epi16(sinpi[1], sinpi[2]);
const __m128i sinpi_p04_m01 = pair_set_epi16(sinpi[4], -sinpi[1]);
@@ -1404,7 +1410,9 @@ static void fadst4x4_new_sse2(const __m128i *input, __m128i *output,
}
static void fadst4x8_new_sse2(const __m128i *input, __m128i *output,
- int8_t cos_bit) {
+ int8_t cos_bit_arg) {
+ (void)cos_bit_arg;
+ const int8_t cos_bit = 13;
const int32_t *cospi = cospi_arr(cos_bit);
const __m128i __zero = _mm_setzero_si128();
const __m128i __rounding = _mm_set1_epi32(1 << (cos_bit - 1));
@@ -1977,12 +1985,24 @@ void av1_lowbd_fwd_txfm2d_4x4_sse2(const int16_t *input, int32_t *output,
(void)bd;
__m128i buf0[4], buf1[4], *buf;
const int8_t *shift = av1_fwd_txfm_shift_ls[TX_4X4];
+ const int width = 4;
+ const int height = 4;
+
+ // Fast path for DCT_DCT: bypass function pointer table and flip checks.
+ if (tx_type == DCT_DCT) {
+ load_buffer_16bit_to_16bit_w4(input, stride, buf0, height);
+ round_shift_16bit(buf0, height, shift[0]);
+ fdct4x4_new_sse2(buf0, buf0, 13);
+ transpose_16bit_4x4(buf0, buf1);
+ fdct4x4_new_sse2(buf1, buf1, 13);
+ store_buffer_16bit_to_32bit_w4(buf1, output, height, width);
+ return;
+ }
+
const int txw_idx = get_txw_idx(TX_4X4);
const int txh_idx = get_txh_idx(TX_4X4);
const int cos_bit_col = av1_fwd_cos_bit_col[txw_idx][txh_idx];
const int cos_bit_row = av1_fwd_cos_bit_row[txw_idx][txh_idx];
- const int width = 4;
- const int height = 4;
const transform_1d_sse2 col_txfm = col_txfm4x4_arr[tx_type];
const transform_1d_sse2 row_txfm = row_txfm4x4_arr[tx_type];
int ud_flip, lr_flip;
diff --git a/av1/encoder/x86/av1_fwd_txfm_sse2.h b/av1/encoder/x86/av1_fwd_txfm_sse2.h
index 5420dc5ef3..f11d4cad3d 100644
--- a/av1/encoder/x86/av1_fwd_txfm_sse2.h
+++ b/av1/encoder/x86/av1_fwd_txfm_sse2.h
@@ -205,6 +205,18 @@ static inline void fadst8x8_new_sse2(const __m128i *input, __m128i *output,
output[6]);
}
+static inline void fdct8x8_cb13_sse2(const __m128i *input, __m128i *output,
+ int8_t cos_bit) {
+ (void)cos_bit;
+ fdct8x8_new_sse2(input, output, 13);
+}
+
+static inline void fadst8x8_cb13_sse2(const __m128i *input, __m128i *output,
+ int8_t cos_bit) {
+ (void)cos_bit;
+ fadst8x8_new_sse2(input, output, 13);
+}
+
static inline void fidentity8x16_new_sse2(const __m128i *input, __m128i *output,
int8_t cos_bit) {
(void)cos_bit;