update libaom to rev 76574b6c09515d6687ebfa9760319e521f5abeb3 (without moz.build and aom_ports/aom_once.h)

This commit is contained in:
Roy Tam 2019-04-19 13:08:28 +08:00
commit ef35212f8b
128 changed files with 9426 additions and 4984 deletions

View file

@ -10,4 +10,4 @@ The upstream aom git repository is:
https://aomedia.googlesource.com/aom
The git commit ID used was 5bdd95475e07ac8641114cb139105b8d734a1b60.
The git commit ID used was 76574b6c09515d6687ebfa9760319e521f5abeb3.

View file

@ -268,8 +268,7 @@ void av1_inv_txfm2d_add_8x8_c(const int32_t *input, uint16_t *output, int stride
#define av1_inv_txfm2d_add_8x8 av1_inv_txfm2d_add_8x8_c
void av1_inv_txfm_add_c(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
void av1_inv_txfm_add_neon(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
RTCD_EXTERN void (*av1_inv_txfm_add)(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
#define av1_inv_txfm_add av1_inv_txfm_add_c
void av1_round_shift_array_c(int32_t *arr, int size, int bit);
void av1_round_shift_array_neon(int32_t *arr, int size, int bit);
@ -383,8 +382,6 @@ static void setup_rtcd_internal(void)
if (flags & HAS_NEON) av1_dist_wtd_convolve_x = av1_dist_wtd_convolve_x_neon;
av1_dist_wtd_convolve_y = av1_dist_wtd_convolve_y_c;
if (flags & HAS_NEON) av1_dist_wtd_convolve_y = av1_dist_wtd_convolve_y_neon;
av1_inv_txfm_add = av1_inv_txfm_add_c;
if (flags & HAS_NEON) av1_inv_txfm_add = av1_inv_txfm_add_neon;
av1_round_shift_array = av1_round_shift_array_c;
if (flags & HAS_NEON) av1_round_shift_array = av1_round_shift_array_neon;
av1_selfguided_restoration = av1_selfguided_restoration_c;

View file

@ -214,7 +214,8 @@ void av1_highbd_dr_prediction_z1_avx2(uint16_t *dst, ptrdiff_t stride, int bw, i
RTCD_EXTERN void (*av1_highbd_dr_prediction_z1)(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_above, int dx, int dy, int bd);
void av1_highbd_dr_prediction_z2_c(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_above, int upsample_left, int dx, int dy, int bd);
#define av1_highbd_dr_prediction_z2 av1_highbd_dr_prediction_z2_c
void av1_highbd_dr_prediction_z2_avx2(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_above, int upsample_left, int dx, int dy, int bd);
RTCD_EXTERN void (*av1_highbd_dr_prediction_z2)(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_above, int upsample_left, int dx, int dy, int bd);
void av1_highbd_dr_prediction_z3_c(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_left, int dx, int dy, int bd);
void av1_highbd_dr_prediction_z3_avx2(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_left, int dx, int dy, int bd);
@ -324,6 +325,7 @@ RTCD_EXTERN void (*av1_inv_txfm2d_add_8x8)(const int32_t *input, uint16_t *outpu
void av1_inv_txfm_add_c(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
void av1_inv_txfm_add_ssse3(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
void av1_inv_txfm_add_avx2(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
RTCD_EXTERN void (*av1_inv_txfm_add)(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
void av1_round_shift_array_c(int32_t *arr, int size, int bit);
@ -526,6 +528,8 @@ static void setup_rtcd_internal(void)
if (flags & HAS_AVX2) av1_highbd_dist_wtd_convolve_y = av1_highbd_dist_wtd_convolve_y_avx2;
av1_highbd_dr_prediction_z1 = av1_highbd_dr_prediction_z1_c;
if (flags & HAS_AVX2) av1_highbd_dr_prediction_z1 = av1_highbd_dr_prediction_z1_avx2;
av1_highbd_dr_prediction_z2 = av1_highbd_dr_prediction_z2_c;
if (flags & HAS_AVX2) av1_highbd_dr_prediction_z2 = av1_highbd_dr_prediction_z2_avx2;
av1_highbd_dr_prediction_z3 = av1_highbd_dr_prediction_z3_c;
if (flags & HAS_AVX2) av1_highbd_dr_prediction_z3 = av1_highbd_dr_prediction_z3_avx2;
av1_highbd_inv_txfm_add = av1_highbd_inv_txfm_add_c;
@ -553,6 +557,7 @@ static void setup_rtcd_internal(void)
if (flags & HAS_SSE4_1) av1_inv_txfm2d_add_8x8 = av1_inv_txfm2d_add_8x8_sse4_1;
av1_inv_txfm_add = av1_inv_txfm_add_c;
if (flags & HAS_SSSE3) av1_inv_txfm_add = av1_inv_txfm_add_ssse3;
if (flags & HAS_AVX2) av1_inv_txfm_add = av1_inv_txfm_add_avx2;
av1_round_shift_array = av1_round_shift_array_c;
if (flags & HAS_SSE4_1) av1_round_shift_array = av1_round_shift_array_sse4_1;
av1_selfguided_restoration = av1_selfguided_restoration_c;

View file

@ -217,7 +217,8 @@ void av1_highbd_dr_prediction_z1_avx2(uint16_t *dst, ptrdiff_t stride, int bw, i
RTCD_EXTERN void (*av1_highbd_dr_prediction_z1)(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_above, int dx, int dy, int bd);
void av1_highbd_dr_prediction_z2_c(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_above, int upsample_left, int dx, int dy, int bd);
#define av1_highbd_dr_prediction_z2 av1_highbd_dr_prediction_z2_c
void av1_highbd_dr_prediction_z2_avx2(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_above, int upsample_left, int dx, int dy, int bd);
RTCD_EXTERN void (*av1_highbd_dr_prediction_z2)(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_above, int upsample_left, int dx, int dy, int bd);
void av1_highbd_dr_prediction_z3_c(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_left, int dx, int dy, int bd);
void av1_highbd_dr_prediction_z3_avx2(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_left, int dx, int dy, int bd);
@ -327,6 +328,7 @@ RTCD_EXTERN void (*av1_inv_txfm2d_add_8x8)(const int32_t *input, uint16_t *outpu
void av1_inv_txfm_add_c(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
void av1_inv_txfm_add_ssse3(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
void av1_inv_txfm_add_avx2(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
RTCD_EXTERN void (*av1_inv_txfm_add)(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
void av1_round_shift_array_c(int32_t *arr, int size, int bit);
@ -520,6 +522,8 @@ static void setup_rtcd_internal(void)
if (flags & HAS_AVX2) av1_highbd_dist_wtd_convolve_y = av1_highbd_dist_wtd_convolve_y_avx2;
av1_highbd_dr_prediction_z1 = av1_highbd_dr_prediction_z1_c;
if (flags & HAS_AVX2) av1_highbd_dr_prediction_z1 = av1_highbd_dr_prediction_z1_avx2;
av1_highbd_dr_prediction_z2 = av1_highbd_dr_prediction_z2_c;
if (flags & HAS_AVX2) av1_highbd_dr_prediction_z2 = av1_highbd_dr_prediction_z2_avx2;
av1_highbd_dr_prediction_z3 = av1_highbd_dr_prediction_z3_c;
if (flags & HAS_AVX2) av1_highbd_dr_prediction_z3 = av1_highbd_dr_prediction_z3_avx2;
av1_highbd_inv_txfm_add = av1_highbd_inv_txfm_add_c;
@ -547,6 +551,7 @@ static void setup_rtcd_internal(void)
if (flags & HAS_SSE4_1) av1_inv_txfm2d_add_8x8 = av1_inv_txfm2d_add_8x8_sse4_1;
av1_inv_txfm_add = av1_inv_txfm_add_c;
if (flags & HAS_SSSE3) av1_inv_txfm_add = av1_inv_txfm_add_ssse3;
if (flags & HAS_AVX2) av1_inv_txfm_add = av1_inv_txfm_add_avx2;
av1_round_shift_array = av1_round_shift_array_c;
if (flags & HAS_SSE4_1) av1_round_shift_array = av1_round_shift_array_sse4_1;
av1_selfguided_restoration = av1_selfguided_restoration_c;

View file

@ -217,7 +217,8 @@ void av1_highbd_dr_prediction_z1_avx2(uint16_t *dst, ptrdiff_t stride, int bw, i
RTCD_EXTERN void (*av1_highbd_dr_prediction_z1)(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_above, int dx, int dy, int bd);
void av1_highbd_dr_prediction_z2_c(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_above, int upsample_left, int dx, int dy, int bd);
#define av1_highbd_dr_prediction_z2 av1_highbd_dr_prediction_z2_c
void av1_highbd_dr_prediction_z2_avx2(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_above, int upsample_left, int dx, int dy, int bd);
RTCD_EXTERN void (*av1_highbd_dr_prediction_z2)(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_above, int upsample_left, int dx, int dy, int bd);
void av1_highbd_dr_prediction_z3_c(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_left, int dx, int dy, int bd);
void av1_highbd_dr_prediction_z3_avx2(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_left, int dx, int dy, int bd);
@ -327,6 +328,7 @@ RTCD_EXTERN void (*av1_inv_txfm2d_add_8x8)(const int32_t *input, uint16_t *outpu
void av1_inv_txfm_add_c(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
void av1_inv_txfm_add_ssse3(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
void av1_inv_txfm_add_avx2(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
RTCD_EXTERN void (*av1_inv_txfm_add)(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
void av1_round_shift_array_c(int32_t *arr, int size, int bit);
@ -520,6 +522,8 @@ static void setup_rtcd_internal(void)
if (flags & HAS_AVX2) av1_highbd_dist_wtd_convolve_y = av1_highbd_dist_wtd_convolve_y_avx2;
av1_highbd_dr_prediction_z1 = av1_highbd_dr_prediction_z1_c;
if (flags & HAS_AVX2) av1_highbd_dr_prediction_z1 = av1_highbd_dr_prediction_z1_avx2;
av1_highbd_dr_prediction_z2 = av1_highbd_dr_prediction_z2_c;
if (flags & HAS_AVX2) av1_highbd_dr_prediction_z2 = av1_highbd_dr_prediction_z2_avx2;
av1_highbd_dr_prediction_z3 = av1_highbd_dr_prediction_z3_c;
if (flags & HAS_AVX2) av1_highbd_dr_prediction_z3 = av1_highbd_dr_prediction_z3_avx2;
av1_highbd_inv_txfm_add = av1_highbd_inv_txfm_add_c;
@ -547,6 +551,7 @@ static void setup_rtcd_internal(void)
if (flags & HAS_SSE4_1) av1_inv_txfm2d_add_8x8 = av1_inv_txfm2d_add_8x8_sse4_1;
av1_inv_txfm_add = av1_inv_txfm_add_c;
if (flags & HAS_SSSE3) av1_inv_txfm_add = av1_inv_txfm_add_ssse3;
if (flags & HAS_AVX2) av1_inv_txfm_add = av1_inv_txfm_add_avx2;
av1_round_shift_array = av1_round_shift_array_c;
if (flags & HAS_SSE4_1) av1_round_shift_array = av1_round_shift_array_sse4_1;
av1_selfguided_restoration = av1_selfguided_restoration_c;

View file

@ -214,7 +214,8 @@ void av1_highbd_dr_prediction_z1_avx2(uint16_t *dst, ptrdiff_t stride, int bw, i
RTCD_EXTERN void (*av1_highbd_dr_prediction_z1)(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_above, int dx, int dy, int bd);
void av1_highbd_dr_prediction_z2_c(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_above, int upsample_left, int dx, int dy, int bd);
#define av1_highbd_dr_prediction_z2 av1_highbd_dr_prediction_z2_c
void av1_highbd_dr_prediction_z2_avx2(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_above, int upsample_left, int dx, int dy, int bd);
RTCD_EXTERN void (*av1_highbd_dr_prediction_z2)(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_above, int upsample_left, int dx, int dy, int bd);
void av1_highbd_dr_prediction_z3_c(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_left, int dx, int dy, int bd);
void av1_highbd_dr_prediction_z3_avx2(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_left, int dx, int dy, int bd);
@ -324,6 +325,7 @@ RTCD_EXTERN void (*av1_inv_txfm2d_add_8x8)(const int32_t *input, uint16_t *outpu
void av1_inv_txfm_add_c(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
void av1_inv_txfm_add_ssse3(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
void av1_inv_txfm_add_avx2(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
RTCD_EXTERN void (*av1_inv_txfm_add)(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
void av1_round_shift_array_c(int32_t *arr, int size, int bit);
@ -526,6 +528,8 @@ static void setup_rtcd_internal(void)
if (flags & HAS_AVX2) av1_highbd_dist_wtd_convolve_y = av1_highbd_dist_wtd_convolve_y_avx2;
av1_highbd_dr_prediction_z1 = av1_highbd_dr_prediction_z1_c;
if (flags & HAS_AVX2) av1_highbd_dr_prediction_z1 = av1_highbd_dr_prediction_z1_avx2;
av1_highbd_dr_prediction_z2 = av1_highbd_dr_prediction_z2_c;
if (flags & HAS_AVX2) av1_highbd_dr_prediction_z2 = av1_highbd_dr_prediction_z2_avx2;
av1_highbd_dr_prediction_z3 = av1_highbd_dr_prediction_z3_c;
if (flags & HAS_AVX2) av1_highbd_dr_prediction_z3 = av1_highbd_dr_prediction_z3_avx2;
av1_highbd_inv_txfm_add = av1_highbd_inv_txfm_add_c;
@ -553,6 +557,7 @@ static void setup_rtcd_internal(void)
if (flags & HAS_SSE4_1) av1_inv_txfm2d_add_8x8 = av1_inv_txfm2d_add_8x8_sse4_1;
av1_inv_txfm_add = av1_inv_txfm_add_c;
if (flags & HAS_SSSE3) av1_inv_txfm_add = av1_inv_txfm_add_ssse3;
if (flags & HAS_AVX2) av1_inv_txfm_add = av1_inv_txfm_add_avx2;
av1_round_shift_array = av1_round_shift_array_c;
if (flags & HAS_SSE4_1) av1_round_shift_array = av1_round_shift_array_sse4_1;
av1_selfguided_restoration = av1_selfguided_restoration_c;

View file

@ -214,7 +214,8 @@ void av1_highbd_dr_prediction_z1_avx2(uint16_t *dst, ptrdiff_t stride, int bw, i
RTCD_EXTERN void (*av1_highbd_dr_prediction_z1)(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_above, int dx, int dy, int bd);
void av1_highbd_dr_prediction_z2_c(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_above, int upsample_left, int dx, int dy, int bd);
#define av1_highbd_dr_prediction_z2 av1_highbd_dr_prediction_z2_c
void av1_highbd_dr_prediction_z2_avx2(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_above, int upsample_left, int dx, int dy, int bd);
RTCD_EXTERN void (*av1_highbd_dr_prediction_z2)(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_above, int upsample_left, int dx, int dy, int bd);
void av1_highbd_dr_prediction_z3_c(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_left, int dx, int dy, int bd);
void av1_highbd_dr_prediction_z3_avx2(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_left, int dx, int dy, int bd);
@ -324,6 +325,7 @@ RTCD_EXTERN void (*av1_inv_txfm2d_add_8x8)(const int32_t *input, uint16_t *outpu
void av1_inv_txfm_add_c(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
void av1_inv_txfm_add_ssse3(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
void av1_inv_txfm_add_avx2(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
RTCD_EXTERN void (*av1_inv_txfm_add)(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
void av1_round_shift_array_c(int32_t *arr, int size, int bit);
@ -526,6 +528,8 @@ static void setup_rtcd_internal(void)
if (flags & HAS_AVX2) av1_highbd_dist_wtd_convolve_y = av1_highbd_dist_wtd_convolve_y_avx2;
av1_highbd_dr_prediction_z1 = av1_highbd_dr_prediction_z1_c;
if (flags & HAS_AVX2) av1_highbd_dr_prediction_z1 = av1_highbd_dr_prediction_z1_avx2;
av1_highbd_dr_prediction_z2 = av1_highbd_dr_prediction_z2_c;
if (flags & HAS_AVX2) av1_highbd_dr_prediction_z2 = av1_highbd_dr_prediction_z2_avx2;
av1_highbd_dr_prediction_z3 = av1_highbd_dr_prediction_z3_c;
if (flags & HAS_AVX2) av1_highbd_dr_prediction_z3 = av1_highbd_dr_prediction_z3_avx2;
av1_highbd_inv_txfm_add = av1_highbd_inv_txfm_add_c;
@ -553,6 +557,7 @@ static void setup_rtcd_internal(void)
if (flags & HAS_SSE4_1) av1_inv_txfm2d_add_8x8 = av1_inv_txfm2d_add_8x8_sse4_1;
av1_inv_txfm_add = av1_inv_txfm_add_c;
if (flags & HAS_SSSE3) av1_inv_txfm_add = av1_inv_txfm_add_ssse3;
if (flags & HAS_AVX2) av1_inv_txfm_add = av1_inv_txfm_add_avx2;
av1_round_shift_array = av1_round_shift_array_c;
if (flags & HAS_SSE4_1) av1_round_shift_array = av1_round_shift_array_sse4_1;
av1_selfguided_restoration = av1_selfguided_restoration_c;

View file

@ -217,7 +217,8 @@ void av1_highbd_dr_prediction_z1_avx2(uint16_t *dst, ptrdiff_t stride, int bw, i
RTCD_EXTERN void (*av1_highbd_dr_prediction_z1)(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_above, int dx, int dy, int bd);
void av1_highbd_dr_prediction_z2_c(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_above, int upsample_left, int dx, int dy, int bd);
#define av1_highbd_dr_prediction_z2 av1_highbd_dr_prediction_z2_c
void av1_highbd_dr_prediction_z2_avx2(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_above, int upsample_left, int dx, int dy, int bd);
RTCD_EXTERN void (*av1_highbd_dr_prediction_z2)(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_above, int upsample_left, int dx, int dy, int bd);
void av1_highbd_dr_prediction_z3_c(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_left, int dx, int dy, int bd);
void av1_highbd_dr_prediction_z3_avx2(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_left, int dx, int dy, int bd);
@ -327,6 +328,7 @@ RTCD_EXTERN void (*av1_inv_txfm2d_add_8x8)(const int32_t *input, uint16_t *outpu
void av1_inv_txfm_add_c(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
void av1_inv_txfm_add_ssse3(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
void av1_inv_txfm_add_avx2(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
RTCD_EXTERN void (*av1_inv_txfm_add)(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
void av1_round_shift_array_c(int32_t *arr, int size, int bit);
@ -520,6 +522,8 @@ static void setup_rtcd_internal(void)
if (flags & HAS_AVX2) av1_highbd_dist_wtd_convolve_y = av1_highbd_dist_wtd_convolve_y_avx2;
av1_highbd_dr_prediction_z1 = av1_highbd_dr_prediction_z1_c;
if (flags & HAS_AVX2) av1_highbd_dr_prediction_z1 = av1_highbd_dr_prediction_z1_avx2;
av1_highbd_dr_prediction_z2 = av1_highbd_dr_prediction_z2_c;
if (flags & HAS_AVX2) av1_highbd_dr_prediction_z2 = av1_highbd_dr_prediction_z2_avx2;
av1_highbd_dr_prediction_z3 = av1_highbd_dr_prediction_z3_c;
if (flags & HAS_AVX2) av1_highbd_dr_prediction_z3 = av1_highbd_dr_prediction_z3_avx2;
av1_highbd_inv_txfm_add = av1_highbd_inv_txfm_add_c;
@ -547,6 +551,7 @@ static void setup_rtcd_internal(void)
if (flags & HAS_SSE4_1) av1_inv_txfm2d_add_8x8 = av1_inv_txfm2d_add_8x8_sse4_1;
av1_inv_txfm_add = av1_inv_txfm_add_c;
if (flags & HAS_SSSE3) av1_inv_txfm_add = av1_inv_txfm_add_ssse3;
if (flags & HAS_AVX2) av1_inv_txfm_add = av1_inv_txfm_add_avx2;
av1_round_shift_array = av1_round_shift_array_c;
if (flags & HAS_SSE4_1) av1_round_shift_array = av1_round_shift_array_sse4_1;
av1_selfguided_restoration = av1_selfguided_restoration_c;

View file

@ -217,7 +217,8 @@ void av1_highbd_dr_prediction_z1_avx2(uint16_t *dst, ptrdiff_t stride, int bw, i
RTCD_EXTERN void (*av1_highbd_dr_prediction_z1)(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_above, int dx, int dy, int bd);
void av1_highbd_dr_prediction_z2_c(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_above, int upsample_left, int dx, int dy, int bd);
#define av1_highbd_dr_prediction_z2 av1_highbd_dr_prediction_z2_c
void av1_highbd_dr_prediction_z2_avx2(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_above, int upsample_left, int dx, int dy, int bd);
RTCD_EXTERN void (*av1_highbd_dr_prediction_z2)(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_above, int upsample_left, int dx, int dy, int bd);
void av1_highbd_dr_prediction_z3_c(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_left, int dx, int dy, int bd);
void av1_highbd_dr_prediction_z3_avx2(uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_left, int dx, int dy, int bd);
@ -327,6 +328,7 @@ RTCD_EXTERN void (*av1_inv_txfm2d_add_8x8)(const int32_t *input, uint16_t *outpu
void av1_inv_txfm_add_c(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
void av1_inv_txfm_add_ssse3(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
void av1_inv_txfm_add_avx2(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
RTCD_EXTERN void (*av1_inv_txfm_add)(const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param);
void av1_round_shift_array_c(int32_t *arr, int size, int bit);
@ -520,6 +522,8 @@ static void setup_rtcd_internal(void)
if (flags & HAS_AVX2) av1_highbd_dist_wtd_convolve_y = av1_highbd_dist_wtd_convolve_y_avx2;
av1_highbd_dr_prediction_z1 = av1_highbd_dr_prediction_z1_c;
if (flags & HAS_AVX2) av1_highbd_dr_prediction_z1 = av1_highbd_dr_prediction_z1_avx2;
av1_highbd_dr_prediction_z2 = av1_highbd_dr_prediction_z2_c;
if (flags & HAS_AVX2) av1_highbd_dr_prediction_z2 = av1_highbd_dr_prediction_z2_avx2;
av1_highbd_dr_prediction_z3 = av1_highbd_dr_prediction_z3_c;
if (flags & HAS_AVX2) av1_highbd_dr_prediction_z3 = av1_highbd_dr_prediction_z3_avx2;
av1_highbd_inv_txfm_add = av1_highbd_inv_txfm_add_c;
@ -547,6 +551,7 @@ static void setup_rtcd_internal(void)
if (flags & HAS_SSE4_1) av1_inv_txfm2d_add_8x8 = av1_inv_txfm2d_add_8x8_sse4_1;
av1_inv_txfm_add = av1_inv_txfm_add_c;
if (flags & HAS_SSSE3) av1_inv_txfm_add = av1_inv_txfm_add_ssse3;
if (flags & HAS_AVX2) av1_inv_txfm_add = av1_inv_txfm_add_avx2;
av1_round_shift_array = av1_round_shift_array_c;
if (flags & HAS_SSE4_1) av1_round_shift_array = av1_round_shift_array_sse4_1;
av1_selfguided_restoration = av1_selfguided_restoration_c;

View file

@ -1,7 +1,7 @@
---
Language: Cpp
# BasedOnStyle: Google
# Generated with clang-format 5.0.0
# Generated with clang-format 7.0.1
AccessModifierOffset: -1
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
@ -12,7 +12,6 @@ AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: true
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: None
@ -30,6 +29,7 @@ BraceWrapping:
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
@ -39,6 +39,7 @@ BraceWrapping:
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
@ -59,7 +60,10 @@ ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^<ext/.*\.h>'
Priority: 2
- Regex: '^<.*\.h>'
Priority: 1
- Regex: '^<.*'
@ -68,6 +72,7 @@ IncludeCategories:
Priority: 3
IncludeIsMainRegex: '([-_](test|unittest))?$'
IndentCaseLabels: true
IndentPPDirectives: None
IndentWidth: 2
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
@ -77,6 +82,7 @@ MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Never
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: false
@ -85,20 +91,53 @@ PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Right
RawStringFormats:
- Language: Cpp
Delimiters:
- cc
- CC
- cpp
- Cpp
- CPP
- 'c++'
- 'C++'
CanonicalDelimiter: ''
BasedOnStyle: google
- Language: TextProto
Delimiters:
- pb
- PB
- proto
- PROTO
EnclosingFunctions:
- EqualsProto
- EquivToProto
- PARSE_PARTIAL_TEXT_PROTO
- PARSE_TEST_PROTO
- PARSE_TEXT_PROTO
- ParseTextOrDie
- ParseTextProtoOrDie
CanonicalDelimiter: ''
BasedOnStyle: google
ReflowComments: true
SortIncludes: false
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInContainerLiterals: false
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false

View file

@ -220,8 +220,8 @@ enum aome_enc_control_id {
/*!\brief Codec control function to set constrained quality level.
*
* \attention For this value to be used aom_codec_enc_cfg_t::g_usage must be
* set to #AOM_CQ.
* \attention For this value to be used aom_codec_enc_cfg_t::rc_end_usage
* must be set to #AOM_CQ.
* \note Valid range: 0..63
*/
AOME_SET_CQ_LEVEL,
@ -584,7 +584,8 @@ enum aome_enc_control_id {
*
* 0 = apply trellis quantization
* 1 = do not apply trellis quantization
* 2 = disable trellis quantization partially
* 2 = disable trellis quantization in rd search
* 3 = disable trellis quantization in estimate yrd
*
* By default, the encoder applies optimization on quantized
* coefficients.
@ -989,16 +990,23 @@ enum aome_enc_control_id {
/*!\brief Codec control function to set the delta q mode
*
* AV1 has a segment based feature that allows encoder to adaptively change
* quantization parameter for each segment within a frame to improve the
* subjective quality. the delta q mode is added on top of segment based
* feature, and allows control per 64x64 q and lf delta.This control makes
* encoder operate in one of the several DELTA_Q_modes supported.
* AV1 supports a delta q mode feature, that allows modulating q per
* superblock. This control makes encoder operate in one of several
* DELTA_Q_modes supported:
* 0: Not Supported
* 1: Use modulation to maximize objective quality
* 2: Use modulation to maximize perceptual quality
*
* By default, encoder operates with DELTAQ_Mode 0(deltaq signaling off).
*/
AV1E_SET_DELTAQ_MODE,
/*!\brief Codec control function to turn on/off loopfilter modulation
* when delta q modulation is enabled. Note AV1 only supports loopfilter
* modulation when delta q modulation is enabled as well.
*/
AV1E_SET_DELTALF_MODE,
/*!\brief Codec control function to set the single tile decoding mode to 0 or
* 1.
*
@ -1405,6 +1413,9 @@ AOM_CTRL_USE_TYPE(AV1E_SET_AQ_MODE, unsigned int)
AOM_CTRL_USE_TYPE(AV1E_SET_DELTAQ_MODE, unsigned int)
#define AOM_CTRL_AV1E_SET_DELTAQ_MODE
AOM_CTRL_USE_TYPE(AV1E_SET_DELTALF_MODE, unsigned int)
#define AOM_CTRL_AV1E_SET_DELTALF_MODE
AOM_CTRL_USE_TYPE(AV1E_SET_FRAME_PERIODIC_BOOST, unsigned int)
#define AOM_CTRL_AV1E_SET_FRAME_PERIODIC_BOOST

View file

@ -207,6 +207,7 @@ if(CONFIG_AV1_ENCODER)
"${AOM_ROOT}/aom_dsp/x86/masked_sad_intrin_avx2.c"
"${AOM_ROOT}/aom_dsp/x86/subtract_avx2.c"
"${AOM_ROOT}/aom_dsp/x86/highbd_quantize_intrin_avx2.c"
"${AOM_ROOT}/aom_dsp/x86/adaptive_quantize_avx2.c"
"${AOM_ROOT}/aom_dsp/x86/sad4d_avx2.c"
"${AOM_ROOT}/aom_dsp/x86/sad_avx2.c"
"${AOM_ROOT}/aom_dsp/x86/sad_highbd_avx2.c"

View file

@ -519,7 +519,7 @@ if (aom_config("CONFIG_AV1_ENCODER") eq "yes") {
specialize qw/aom_quantize_b sse2/, "$ssse3_x86_64", "$avx_x86_64";
add_proto qw/void aom_quantize_b_adaptive/, "const tran_low_t *coeff_ptr, intptr_t n_coeffs, 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, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan";
specialize qw/aom_quantize_b_adaptive sse2/;
specialize qw/aom_quantize_b_adaptive sse2 avx2/;
add_proto qw/void aom_quantize_b_32x32/, "const tran_low_t *coeff_ptr, intptr_t n_coeffs, 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, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan";
specialize qw/aom_quantize_b_32x32/, "$ssse3_x86_64", "$avx_x86_64";
@ -529,6 +529,9 @@ if (aom_config("CONFIG_AV1_ENCODER") eq "yes") {
add_proto qw/void aom_quantize_b_64x64/, "const tran_low_t *coeff_ptr, intptr_t n_coeffs, 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, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan";
specialize qw/aom_quantize_b_64x64 ssse3/;
add_proto qw/void aom_quantize_b_64x64_adaptive/, "const tran_low_t *coeff_ptr, intptr_t n_coeffs, 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, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan";
specialize qw/aom_quantize_b_64x64_adaptive sse2/;
} # CONFIG_AV1_ENCODER
if (aom_config("CONFIG_AV1_ENCODER") eq "yes") {

View file

@ -1078,7 +1078,7 @@ int av1_add_film_grain_run(const aom_film_grain_t *params, uint8_t *luma,
const int grain_center = 128 << (bit_depth - 8);
grain_min = 0 - grain_center;
grain_max = (256 << (bit_depth - 8)) - 1 - grain_center;
grain_max = grain_center - 1;
init_arrays(params, luma_stride, chroma_stride, &pred_pos_luma,
&pred_pos_chroma, &luma_grain_block, &cb_grain_block,

View file

@ -214,6 +214,7 @@ static void set_chroma_coefficient_fallback_soln(aom_equation_system_t *eqns) {
int aom_noise_strength_lut_init(aom_noise_strength_lut_t *lut, int num_points) {
if (!lut) return 0;
lut->num_points = 0;
lut->points = (double(*)[2])aom_malloc(num_points * sizeof(*lut->points));
if (!lut->points) return 0;
lut->num_points = num_points;
@ -426,6 +427,9 @@ int aom_flat_block_finder_init(aom_flat_block_finder_t *block_finder,
double *AtA_inv = 0;
double *A = 0;
int x = 0, y = 0, i = 0, j = 0;
block_finder->A = NULL;
block_finder->AtA_inv = NULL;
if (!equation_system_init(&eqns, kLowPolyNumParams)) {
fprintf(stderr, "Failed to init equation system for block_size=%d\n",
block_size);

View file

@ -140,7 +140,7 @@ static double calc_psnrhvs(const unsigned char *src, int _systride,
been normalized and then squared." Their CSF matrix (from PSNR-HVS)
was also constructed from the JPEG matrices. I can not find any obvious
scheme of normalizing to produce their table, but if I multiply their
CSF by 0.38857 and square the result I get their masking table.
CSF by 0.3885746225901003 and square the result I get their masking table.
I have no idea where this constant comes from, but deviating from it
too greatly hurts MOS agreement.
@ -148,11 +148,15 @@ static double calc_psnrhvs(const unsigned char *src, int _systride,
Jaakko Astola, Vladimir Lukin, "On between-coefficient contrast masking
of DCT basis functions", CD-ROM Proceedings of the Third
International Workshop on Video Processing and Quality Metrics for Consumer
Electronics VPQM-07, Scottsdale, Arizona, USA, 25-26 January, 2007, 4 p.*/
Electronics VPQM-07, Scottsdale, Arizona, USA, 25-26 January, 2007, 4 p.
Suggested in aomedia issue#2363:
0.3885746225901003 is a reciprocal of the maximum coefficient (2.573509)
of the old JPEG based matrix from the paper. Since you are not using that,
divide by actual maximum coefficient. */
for (x = 0; x < 8; x++)
for (y = 0; y < 8; y++)
mask[x][y] =
(_csf[x][y] * 0.3885746225901003) * (_csf[x][y] * 0.3885746225901003);
mask[x][y] = (_csf[x][y] / _csf[1][0]) * (_csf[x][y] / _csf[1][0]);
for (y = 0; y < _h - 7; y += _step) {
for (x = 0; x < _w - 7; x += _step) {
int i;

View file

@ -0,0 +1,244 @@
/*
* Copyright (c) 2019, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include <immintrin.h>
#include "config/aom_dsp_rtcd.h"
#include "aom/aom_integer.h"
#include "av1/encoder/av1_quantize.h"
#include "aom_dsp/x86/quantize_x86.h"
static INLINE void load_b_values_avx2(const int16_t *zbin_ptr, __m256i *zbin,
const int16_t *round_ptr, __m256i *round,
const int16_t *quant_ptr, __m256i *quant,
const int16_t *dequant_ptr,
__m256i *dequant,
const int16_t *shift_ptr,
__m256i *shift) {
*zbin = _mm256_castsi128_si256(_mm_load_si128((const __m128i *)zbin_ptr));
*zbin = _mm256_permute4x64_epi64(*zbin, 0x54);
*zbin = _mm256_sub_epi16(*zbin, _mm256_set1_epi16(1));
*round = _mm256_castsi128_si256(_mm_load_si128((const __m128i *)round_ptr));
*round = _mm256_permute4x64_epi64(*round, 0x54);
*quant = _mm256_castsi128_si256(_mm_load_si128((const __m128i *)quant_ptr));
*quant = _mm256_permute4x64_epi64(*quant, 0x54);
*dequant =
_mm256_castsi128_si256(_mm_load_si128((const __m128i *)dequant_ptr));
*dequant = _mm256_permute4x64_epi64(*dequant, 0x54);
*shift = _mm256_castsi128_si256(_mm_load_si128((const __m128i *)shift_ptr));
*shift = _mm256_permute4x64_epi64(*shift, 0x54);
}
static INLINE __m256i load_coefficients_avx2(const tran_low_t *coeff_ptr) {
const __m256i coeff1 = _mm256_load_si256((__m256i *)(coeff_ptr));
const __m256i coeff2 = _mm256_load_si256((__m256i *)(coeff_ptr + 8));
return _mm256_packs_epi32(coeff1, coeff2);
}
static INLINE void update_mask1_avx2(__m256i *cmp_mask,
const int16_t *iscan_ptr, int *is_found,
__m256i *mask) {
__m256i temp_mask = _mm256_setzero_si256();
if (_mm256_movemask_epi8(*cmp_mask)) {
__m256i iscan = _mm256_loadu_si256((const __m256i *)(iscan_ptr));
temp_mask = _mm256_and_si256(*cmp_mask, iscan);
*is_found = 1;
}
*mask = _mm256_max_epi16(temp_mask, *mask);
}
static INLINE void update_mask0_avx2(__m256i *qcoeff, __m256i *threshold,
const int16_t *iscan_ptr, int *is_found,
__m256i *mask) {
__m256i zero = _mm256_setzero_si256();
__m256i coeff[2], cmp_mask0, cmp_mask1;
coeff[0] = _mm256_unpacklo_epi16(*qcoeff, zero);
coeff[1] = _mm256_unpackhi_epi16(*qcoeff, zero);
coeff[0] = _mm256_slli_epi32(coeff[0], AOM_QM_BITS);
cmp_mask0 = _mm256_cmpgt_epi32(coeff[0], threshold[0]);
coeff[1] = _mm256_slli_epi32(coeff[1], AOM_QM_BITS);
cmp_mask1 = _mm256_cmpgt_epi32(coeff[1], threshold[1]);
cmp_mask0 =
_mm256_permute4x64_epi64(_mm256_packs_epi32(cmp_mask0, cmp_mask1), 0xd8);
update_mask1_avx2(&cmp_mask0, iscan_ptr, is_found, mask);
}
static INLINE void calculate_qcoeff_avx2(__m256i *coeff, const __m256i *round,
const __m256i *quant,
const __m256i *shift) {
__m256i tmp, qcoeff;
qcoeff = _mm256_adds_epi16(*coeff, *round);
tmp = _mm256_mulhi_epi16(qcoeff, *quant);
qcoeff = _mm256_add_epi16(tmp, qcoeff);
*coeff = _mm256_mulhi_epi16(qcoeff, *shift);
}
static INLINE __m256i calculate_dqcoeff_avx2(__m256i qcoeff, __m256i dequant) {
return _mm256_mullo_epi16(qcoeff, dequant);
}
static INLINE void store_coefficients_avx2(__m256i coeff_vals,
tran_low_t *coeff_ptr) {
__m256i coeff_sign = _mm256_srai_epi16(coeff_vals, 15);
__m256i coeff_vals_lo = _mm256_unpacklo_epi16(coeff_vals, coeff_sign);
__m256i coeff_vals_hi = _mm256_unpackhi_epi16(coeff_vals, coeff_sign);
_mm256_store_si256((__m256i *)(coeff_ptr), coeff_vals_lo);
_mm256_store_si256((__m256i *)(coeff_ptr + 8), coeff_vals_hi);
}
void aom_quantize_b_adaptive_avx2(
const tran_low_t *coeff_ptr, intptr_t n_coeffs, 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, uint16_t *eob_ptr,
const int16_t *scan, const int16_t *iscan) {
int index = 16;
int non_zero_count = 0;
int non_zero_count_prescan_add_zero = 0;
int is_found0 = 0, is_found1 = 0;
int eob = -1;
const __m256i zero = _mm256_setzero_si256();
__m256i zbin, round, quant, dequant, shift;
__m256i coeff, qcoeff;
__m256i cmp_mask, mask0 = zero, mask1 = zero;
__m128i temp_mask0, temp_mask1;
int prescan_add[2];
int thresh[2];
const qm_val_t wt = (1 << AOM_QM_BITS);
for (int i = 0; i < 2; ++i) {
prescan_add[i] = ROUND_POWER_OF_TWO(dequant_ptr[i] * EOB_FACTOR, 7);
thresh[i] = (zbin_ptr[i] * wt + prescan_add[i]) - 1;
}
__m256i threshold[2];
threshold[0] = _mm256_set1_epi32(thresh[0]);
threshold[1] = _mm256_set1_epi32(thresh[1]);
threshold[0] = _mm256_blend_epi32(threshold[0], threshold[1], 0xfe);
#if SKIP_EOB_FACTOR_ADJUST
int first = -1;
#endif
// Setup global values.
load_b_values_avx2(zbin_ptr, &zbin, round_ptr, &round, quant_ptr, &quant,
dequant_ptr, &dequant, quant_shift_ptr, &shift);
// Do DC and first 15 AC.
coeff = load_coefficients_avx2(coeff_ptr);
qcoeff = _mm256_abs_epi16(coeff);
update_mask0_avx2(&qcoeff, threshold, iscan, &is_found0, &mask0);
__m256i temp0 = _mm256_cmpgt_epi16(qcoeff, zbin);
zbin = _mm256_unpackhi_epi64(zbin, zbin);
cmp_mask = _mm256_permute4x64_epi64(temp0, 0xd8);
update_mask1_avx2(&cmp_mask, iscan, &is_found1, &mask1);
threshold[0] = threshold[1];
if (_mm256_movemask_epi8(cmp_mask) == 0) {
_mm256_store_si256((__m256i *)(qcoeff_ptr), zero);
_mm256_store_si256((__m256i *)(qcoeff_ptr + 8), zero);
_mm256_store_si256((__m256i *)(dqcoeff_ptr), zero);
_mm256_store_si256((__m256i *)(dqcoeff_ptr + 8), zero);
round = _mm256_unpackhi_epi64(round, round);
quant = _mm256_unpackhi_epi64(quant, quant);
shift = _mm256_unpackhi_epi64(shift, shift);
dequant = _mm256_unpackhi_epi64(dequant, dequant);
} else {
calculate_qcoeff_avx2(&qcoeff, &round, &quant, &shift);
round = _mm256_unpackhi_epi64(round, round);
quant = _mm256_unpackhi_epi64(quant, quant);
shift = _mm256_unpackhi_epi64(shift, shift);
// Reinsert signs
qcoeff = _mm256_sign_epi16(qcoeff, coeff);
// Mask out zbin threshold coeffs
qcoeff = _mm256_and_si256(qcoeff, temp0);
store_coefficients_avx2(qcoeff, qcoeff_ptr);
coeff = calculate_dqcoeff_avx2(qcoeff, dequant);
dequant = _mm256_unpackhi_epi64(dequant, dequant);
store_coefficients_avx2(coeff, dqcoeff_ptr);
}
// AC only loop.
while (index < n_coeffs) {
coeff = load_coefficients_avx2(coeff_ptr + index);
qcoeff = _mm256_abs_epi16(coeff);
update_mask0_avx2(&qcoeff, threshold, iscan + index, &is_found0, &mask0);
temp0 = _mm256_cmpgt_epi16(qcoeff, zbin);
cmp_mask = _mm256_permute4x64_epi64(temp0, 0xd8);
update_mask1_avx2(&cmp_mask, iscan + index, &is_found1, &mask1);
if (_mm256_movemask_epi8(cmp_mask) == 0) {
_mm256_store_si256((__m256i *)(qcoeff_ptr + index), zero);
_mm256_store_si256((__m256i *)(qcoeff_ptr + index + 8), zero);
_mm256_store_si256((__m256i *)(dqcoeff_ptr + index), zero);
_mm256_store_si256((__m256i *)(dqcoeff_ptr + index + 8), zero);
index += 16;
continue;
}
calculate_qcoeff_avx2(&qcoeff, &round, &quant, &shift);
qcoeff = _mm256_sign_epi16(qcoeff, coeff);
qcoeff = _mm256_and_si256(qcoeff, temp0);
store_coefficients_avx2(qcoeff, qcoeff_ptr + index);
coeff = calculate_dqcoeff_avx2(qcoeff, dequant);
store_coefficients_avx2(coeff, dqcoeff_ptr + index);
index += 16;
}
if (is_found0) {
temp_mask0 = _mm_max_epi16(_mm256_castsi256_si128(mask0),
_mm256_extracti128_si256(mask0, 1));
non_zero_count = calculate_non_zero_count(temp_mask0);
}
if (is_found1) {
temp_mask1 = _mm_max_epi16(_mm256_castsi256_si128(mask1),
_mm256_extracti128_si256(mask1, 1));
non_zero_count_prescan_add_zero = calculate_non_zero_count(temp_mask1);
}
for (int i = non_zero_count_prescan_add_zero - 1; i >= non_zero_count; i--) {
const int rc = scan[i];
qcoeff_ptr[rc] = 0;
dqcoeff_ptr[rc] = 0;
}
for (int i = non_zero_count - 1; i >= 0; i--) {
const int rc = scan[i];
if (qcoeff_ptr[rc]) {
eob = i;
break;
}
}
*eob_ptr = eob + 1;
#if SKIP_EOB_FACTOR_ADJUST
// TODO(Aniket): Experiment the following loop with intrinsic by combining
// with the quantization loop above
for (int i = 0; i < non_zero_count; i++) {
const int rc = scan[i];
const int qcoeff0 = qcoeff_ptr[rc];
if (qcoeff0) {
first = i;
break;
}
}
if ((*eob_ptr - 1) >= 0 && first == (*eob_ptr - 1)) {
const int rc = scan[(*eob_ptr - 1)];
if (qcoeff_ptr[rc] == 1 || qcoeff_ptr[rc] == -1) {
const int coeff0 = coeff_ptr[rc] * wt;
const int coeff_sign = (coeff0 >> 31);
const int abs_coeff = (coeff0 ^ coeff_sign) - coeff_sign;
const int factor = EOB_FACTOR + SKIP_EOB_FACTOR_ADJUST;
const int prescan_add_val =
ROUND_POWER_OF_TWO(dequant_ptr[rc != 0] * factor, 7);
if (abs_coeff <
(zbin_ptr[rc != 0] * (1 << AOM_QM_BITS) + prescan_add_val)) {
qcoeff_ptr[rc] = 0;
dqcoeff_ptr[rc] = 0;
*eob_ptr = 0;
}
}
}
#endif
}

View file

@ -22,41 +22,31 @@ void aom_quantize_b_adaptive_sse2(
const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr,
tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr,
const int16_t *scan, const int16_t *iscan) {
const __m128i zero = _mm_setzero_si128();
int index = 16;
int non_zero_count = (int)n_coeffs;
int non_zero_count = 0;
int non_zero_count_prescan_add_zero = 0;
int is_found0 = 0, is_found1 = 0;
int eob = -1;
const __m128i zero = _mm_setzero_si128();
__m128i zbin, round, quant, dequant, shift;
__m128i coeff0, coeff1, coeff0_sign, coeff1_sign;
__m128i qcoeff0, qcoeff1;
__m128i cmp_mask0, cmp_mask1;
__m128i eob = zero, eob0, prescan0, prescan1, all_zero;
const int zbins[2] = { ROUND_POWER_OF_TWO(zbin_ptr[0], 0),
ROUND_POWER_OF_TWO(zbin_ptr[1], 0) };
__m128i all_zero;
__m128i mask0 = zero, mask1 = zero;
int prescan_add[2];
for (int i = 0; i < 2; ++i)
int thresh[4];
const qm_val_t wt = (1 << AOM_QM_BITS);
for (int i = 0; i < 2; ++i) {
prescan_add[i] = ROUND_POWER_OF_TWO(dequant_ptr[i] * EOB_FACTOR, 7);
// max buffer is of size 256 as this functions calls with
// maximum n_coeffs as 256
int16_t prescan[256];
memset(prescan, -1, n_coeffs * sizeof(int16_t));
// TODO(Aniket): Experiment the following loop with intrinsic
for (int i = (int)n_coeffs - 1; i >= 0; i--) {
const int rc = scan[i];
const qm_val_t wt = 1 << AOM_QM_BITS;
const int coeff = coeff_ptr[rc] * wt;
const int coeff_sign = (coeff >> 31);
const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
const int prescan_add_val = prescan_add[rc != 0];
if (abs_coeff < (zbins[rc != 0] * (1 << AOM_QM_BITS) + prescan_add_val)) {
prescan[rc] = 0;
non_zero_count--;
} else {
break;
}
thresh[i] = (zbin_ptr[i] * wt + prescan_add[i]) - 1;
}
thresh[2] = thresh[3] = thresh[1];
__m128i threshold[2];
threshold[0] = _mm_loadu_si128((__m128i *)&thresh[0]);
threshold[1] = _mm_unpackhi_epi64(threshold[0], threshold[0]);
#if SKIP_EOB_FACTOR_ADJUST
int first = -1;
#endif
@ -74,13 +64,15 @@ void aom_quantize_b_adaptive_sse2(
qcoeff0 = invert_sign_sse2(coeff0, coeff0_sign);
qcoeff1 = invert_sign_sse2(coeff1, coeff1_sign);
prescan0 = _mm_loadu_si128((const __m128i *)prescan);
prescan1 = _mm_loadu_si128((const __m128i *)(prescan + 8));
update_mask0(&qcoeff0, &qcoeff1, threshold, iscan, &is_found0, &mask0);
cmp_mask0 = _mm_and_si128(prescan0, _mm_cmpgt_epi16(qcoeff0, zbin));
cmp_mask0 = _mm_cmpgt_epi16(qcoeff0, zbin);
zbin = _mm_unpackhi_epi64(zbin, zbin); // Switch DC to AC
cmp_mask1 = _mm_and_si128(prescan1, _mm_cmpgt_epi16(qcoeff1, zbin));
cmp_mask1 = _mm_cmpgt_epi16(qcoeff1, zbin);
update_mask1(&cmp_mask0, &cmp_mask1, iscan, &is_found1, &mask1);
threshold[0] = threshold[1];
all_zero = _mm_or_si128(cmp_mask0, cmp_mask1);
if (_mm_movemask_epi8(all_zero) == 0) {
_mm_store_si128((__m128i *)(qcoeff_ptr), zero);
@ -121,13 +113,9 @@ void aom_quantize_b_adaptive_sse2(
store_coefficients(coeff0, dqcoeff_ptr);
store_coefficients(coeff1, dqcoeff_ptr + 8);
eob = scan_for_eob(&coeff0, &coeff1, cmp_mask0, cmp_mask1, iscan, 0, zero);
}
// AC only loop.
// TODO(Aniket): Reduce the processing of coeff quatization
// based on eob logic
while (index < n_coeffs) {
coeff0 = load_coefficients(coeff_ptr + index);
coeff1 = load_coefficients(coeff_ptr + index + 8);
@ -137,11 +125,13 @@ void aom_quantize_b_adaptive_sse2(
qcoeff0 = invert_sign_sse2(coeff0, coeff0_sign);
qcoeff1 = invert_sign_sse2(coeff1, coeff1_sign);
prescan0 = _mm_loadu_si128((const __m128i *)(prescan + index));
prescan1 = _mm_loadu_si128((const __m128i *)(prescan + index + 8));
update_mask0(&qcoeff0, &qcoeff1, threshold, iscan + index, &is_found0,
&mask0);
cmp_mask0 = _mm_and_si128(prescan0, _mm_cmpgt_epi16(qcoeff0, zbin));
cmp_mask1 = _mm_and_si128(prescan1, _mm_cmpgt_epi16(qcoeff1, zbin));
cmp_mask0 = _mm_cmpgt_epi16(qcoeff0, zbin);
cmp_mask1 = _mm_cmpgt_epi16(qcoeff1, zbin);
update_mask1(&cmp_mask0, &cmp_mask1, iscan + index, &is_found1, &mask1);
all_zero = _mm_or_si128(cmp_mask0, cmp_mask1);
if (_mm_movemask_epi8(all_zero) == 0) {
@ -174,14 +164,27 @@ void aom_quantize_b_adaptive_sse2(
store_coefficients(coeff0, dqcoeff_ptr + index);
store_coefficients(coeff1, dqcoeff_ptr + index + 8);
eob0 = scan_for_eob(&coeff0, &coeff1, cmp_mask0, cmp_mask1, iscan, index,
zero);
eob = _mm_max_epi16(eob, eob0);
index += 16;
}
if (is_found0) non_zero_count = calculate_non_zero_count(mask0);
if (is_found1)
non_zero_count_prescan_add_zero = calculate_non_zero_count(mask1);
*eob_ptr = accumulate_eob(eob);
for (int i = non_zero_count_prescan_add_zero - 1; i >= non_zero_count; i--) {
const int rc = scan[i];
qcoeff_ptr[rc] = 0;
dqcoeff_ptr[rc] = 0;
}
for (int i = non_zero_count - 1; i >= 0; i--) {
const int rc = scan[i];
if (qcoeff_ptr[rc]) {
eob = i;
break;
}
}
*eob_ptr = eob + 1;
#if SKIP_EOB_FACTOR_ADJUST
// TODO(Aniket): Experiment the following loop with intrinsic by combining
// with the quantization loop above
@ -196,14 +199,14 @@ void aom_quantize_b_adaptive_sse2(
if ((*eob_ptr - 1) >= 0 && first == (*eob_ptr - 1)) {
const int rc = scan[(*eob_ptr - 1)];
if (qcoeff_ptr[rc] == 1 || qcoeff_ptr[rc] == -1) {
const qm_val_t wt = (1 << AOM_QM_BITS);
const int coeff = coeff_ptr[rc] * wt;
const int coeff_sign = (coeff >> 31);
const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
const int factor = EOB_FACTOR + SKIP_EOB_FACTOR_ADJUST;
const int prescan_add_val =
ROUND_POWER_OF_TWO(dequant_ptr[rc != 0] * factor, 7);
if (abs_coeff < (zbins[rc != 0] * (1 << AOM_QM_BITS) + prescan_add_val)) {
if (abs_coeff <
(zbin_ptr[rc != 0] * (1 << AOM_QM_BITS) + prescan_add_val)) {
qcoeff_ptr[rc] = 0;
dqcoeff_ptr[rc] = 0;
*eob_ptr = 0;
@ -220,8 +223,11 @@ void aom_quantize_b_32x32_adaptive_sse2(
tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr,
const int16_t *scan, const int16_t *iscan) {
int index = 16;
int non_zero_count = (int)n_coeffs;
const int log_scale = 1;
int non_zero_count = 0;
int non_zero_count_prescan_add_zero = 0;
int is_found0 = 0, is_found1 = 0;
int eob = -1;
const __m128i zero = _mm_setzero_si128();
const __m128i one = _mm_set1_epi16(1);
const __m128i log_scale_vec = _mm_set1_epi16(log_scale);
@ -229,34 +235,23 @@ void aom_quantize_b_32x32_adaptive_sse2(
__m128i coeff0, coeff1, coeff0_sign, coeff1_sign;
__m128i qcoeff0, qcoeff1;
__m128i cmp_mask0, cmp_mask1;
__m128i eob = zero, eob0, prescan0, prescan1, all_zero;
__m128i all_zero;
__m128i mask0 = zero, mask1 = zero;
const int zbins[2] = { ROUND_POWER_OF_TWO(zbin_ptr[0], log_scale),
ROUND_POWER_OF_TWO(zbin_ptr[1], log_scale) };
int prescan_add[2];
for (int i = 0; i < 2; ++i)
int thresh[4];
const qm_val_t wt = (1 << AOM_QM_BITS);
for (int i = 0; i < 2; ++i) {
prescan_add[i] = ROUND_POWER_OF_TWO(dequant_ptr[i] * EOB_FACTOR, 7);
// max buffer is of size 1024 as this functions calls with
// maximum n_coeffs as 1024
int16_t prescan[1024];
memset(prescan, -1, n_coeffs * sizeof(int16_t));
// TODO(Aniket): Experiment the following loop with intrinsic
for (int i = (int)n_coeffs - 1; i >= 0; i--) {
const int rc = scan[i];
const qm_val_t wt = 1 << AOM_QM_BITS;
const int coeff = coeff_ptr[rc] * wt;
const int coeff_sign = (coeff >> 31);
const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
const int prescan_add_val = prescan_add[rc != 0];
if (abs_coeff < (zbins[rc != 0] * (1 << AOM_QM_BITS) + prescan_add_val)) {
prescan[rc] = 0;
non_zero_count--;
} else {
break;
}
thresh[i] = (zbins[i] * wt + prescan_add[i]) - 1;
}
thresh[2] = thresh[3] = thresh[1];
__m128i threshold[2];
threshold[0] = _mm_loadu_si128((__m128i *)&thresh[0]);
threshold[1] = _mm_unpackhi_epi64(threshold[0], threshold[0]);
#if SKIP_EOB_FACTOR_ADJUST
int first = -1;
#endif
@ -273,6 +268,7 @@ void aom_quantize_b_32x32_adaptive_sse2(
zbin = _mm_srli_epi16(zbin, log_scale);
round = _mm_srli_epi16(round, log_scale);
zbin = _mm_sub_epi16(zbin, one);
// Do DC and first 15 AC.
coeff0 = load_coefficients(coeff_ptr);
coeff1 = load_coefficients(coeff_ptr + 8);
@ -282,13 +278,15 @@ void aom_quantize_b_32x32_adaptive_sse2(
qcoeff0 = invert_sign_sse2(coeff0, coeff0_sign);
qcoeff1 = invert_sign_sse2(coeff1, coeff1_sign);
prescan0 = _mm_loadu_si128((const __m128i *)prescan);
prescan1 = _mm_loadu_si128((const __m128i *)(prescan + 8));
update_mask0(&qcoeff0, &qcoeff1, threshold, iscan, &is_found0, &mask0);
cmp_mask0 = _mm_and_si128(prescan0, _mm_cmpgt_epi16(qcoeff0, zbin));
cmp_mask0 = _mm_cmpgt_epi16(qcoeff0, zbin);
zbin = _mm_unpackhi_epi64(zbin, zbin); // Switch DC to AC
cmp_mask1 = _mm_and_si128(prescan1, _mm_cmpgt_epi16(qcoeff1, zbin));
cmp_mask1 = _mm_cmpgt_epi16(qcoeff1, zbin);
update_mask1(&cmp_mask0, &cmp_mask1, iscan, &is_found1, &mask1);
threshold[0] = threshold[1];
all_zero = _mm_or_si128(cmp_mask0, cmp_mask1);
if (_mm_movemask_epi8(all_zero) == 0) {
_mm_store_si128((__m128i *)(qcoeff_ptr), zero);
@ -305,11 +303,9 @@ void aom_quantize_b_32x32_adaptive_sse2(
dequant = _mm_unpackhi_epi64(dequant, dequant);
} else {
calculate_qcoeff_log_scale(&qcoeff0, round, quant, &shift, &log_scale);
round = _mm_unpackhi_epi64(round, round);
quant = _mm_unpackhi_epi64(quant, quant);
shift = _mm_unpackhi_epi64(shift, shift);
calculate_qcoeff_log_scale(&qcoeff1, round, quant, &shift, &log_scale);
// Reinsert signs
@ -328,14 +324,9 @@ void aom_quantize_b_32x32_adaptive_sse2(
dequant = _mm_unpackhi_epi64(dequant, dequant);
calculate_dqcoeff_and_store_log_scale(qcoeff1, dequant, zero,
dqcoeff_ptr + 8, &log_scale);
eob =
scan_for_eob(&qcoeff0, &qcoeff1, cmp_mask0, cmp_mask1, iscan, 0, zero);
}
// AC only loop.
// TODO(Aniket): Reduce the processing of coeff quatization
// based on eob logic
while (index < n_coeffs) {
coeff0 = load_coefficients(coeff_ptr + index);
coeff1 = load_coefficients(coeff_ptr + index + 8);
@ -345,11 +336,13 @@ void aom_quantize_b_32x32_adaptive_sse2(
qcoeff0 = invert_sign_sse2(coeff0, coeff0_sign);
qcoeff1 = invert_sign_sse2(coeff1, coeff1_sign);
prescan0 = _mm_loadu_si128((const __m128i *)(prescan + index));
prescan1 = _mm_loadu_si128((const __m128i *)(prescan + index + 8));
update_mask0(&qcoeff0, &qcoeff1, threshold, iscan + index, &is_found0,
&mask0);
cmp_mask0 = _mm_and_si128(prescan0, _mm_cmpgt_epi16(qcoeff0, zbin));
cmp_mask1 = _mm_and_si128(prescan1, _mm_cmpgt_epi16(qcoeff1, zbin));
cmp_mask0 = _mm_cmpgt_epi16(qcoeff0, zbin);
cmp_mask1 = _mm_cmpgt_epi16(qcoeff1, zbin);
update_mask1(&cmp_mask0, &cmp_mask1, iscan + index, &is_found1, &mask1);
all_zero = _mm_or_si128(cmp_mask0, cmp_mask1);
if (_mm_movemask_epi8(all_zero) == 0) {
@ -380,15 +373,235 @@ void aom_quantize_b_32x32_adaptive_sse2(
dqcoeff_ptr + index, &log_scale);
calculate_dqcoeff_and_store_log_scale(qcoeff1, dequant, zero,
dqcoeff_ptr + index + 8, &log_scale);
eob0 = scan_for_eob(&qcoeff0, &qcoeff1, cmp_mask0, cmp_mask1, iscan, index,
zero);
eob = _mm_max_epi16(eob, eob0);
index += 16;
}
if (is_found0) non_zero_count = calculate_non_zero_count(mask0);
if (is_found1)
non_zero_count_prescan_add_zero = calculate_non_zero_count(mask1);
*eob_ptr = accumulate_eob(eob);
for (int i = non_zero_count_prescan_add_zero - 1; i >= non_zero_count; i--) {
const int rc = scan[i];
qcoeff_ptr[rc] = 0;
dqcoeff_ptr[rc] = 0;
}
for (int i = non_zero_count - 1; i >= 0; i--) {
const int rc = scan[i];
if (qcoeff_ptr[rc]) {
eob = i;
break;
}
}
*eob_ptr = eob + 1;
#if SKIP_EOB_FACTOR_ADJUST
// TODO(Aniket): Experiment the following loop with intrinsic by combining
// with the quantization loop above
for (int i = 0; i < non_zero_count; i++) {
const int rc = scan[i];
const int qcoeff = qcoeff_ptr[rc];
if (qcoeff) {
first = i;
break;
}
}
if ((*eob_ptr - 1) >= 0 && first == (*eob_ptr - 1)) {
const int rc = scan[(*eob_ptr - 1)];
if (qcoeff_ptr[rc] == 1 || qcoeff_ptr[rc] == -1) {
const int coeff = coeff_ptr[rc] * wt;
const int coeff_sign = (coeff >> 31);
const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
const int factor = EOB_FACTOR + SKIP_EOB_FACTOR_ADJUST;
const int prescan_add_val =
ROUND_POWER_OF_TWO(dequant_ptr[rc != 0] * factor, 7);
if (abs_coeff < (zbins[rc != 0] * (1 << AOM_QM_BITS) + prescan_add_val)) {
qcoeff_ptr[rc] = 0;
dqcoeff_ptr[rc] = 0;
*eob_ptr = 0;
}
}
}
#endif
}
void aom_quantize_b_64x64_adaptive_sse2(
const tran_low_t *coeff_ptr, intptr_t n_coeffs, 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, uint16_t *eob_ptr,
const int16_t *scan, const int16_t *iscan) {
int index = 16;
const int log_scale = 2;
int non_zero_count = 0;
int non_zero_count_prescan_add_zero = 0;
int is_found0 = 0, is_found1 = 0;
int eob = -1;
const __m128i zero = _mm_setzero_si128();
const __m128i one = _mm_set1_epi16(1);
const __m128i log_scale_vec = _mm_set1_epi16(log_scale);
__m128i zbin, round, quant, dequant, shift;
__m128i coeff0, coeff1, coeff0_sign, coeff1_sign;
__m128i qcoeff0, qcoeff1;
__m128i cmp_mask0, cmp_mask1;
__m128i all_zero;
__m128i mask0 = zero, mask1 = zero;
const int zbins[2] = { ROUND_POWER_OF_TWO(zbin_ptr[0], log_scale),
ROUND_POWER_OF_TWO(zbin_ptr[1], log_scale) };
int prescan_add[2];
int thresh[4];
const qm_val_t wt = (1 << AOM_QM_BITS);
for (int i = 0; i < 2; ++i) {
prescan_add[i] = ROUND_POWER_OF_TWO(dequant_ptr[i] * EOB_FACTOR, 7);
thresh[i] = (zbins[i] * wt + prescan_add[i]) - 1;
}
thresh[2] = thresh[3] = thresh[1];
__m128i threshold[2];
threshold[0] = _mm_loadu_si128((__m128i *)&thresh[0]);
threshold[1] = _mm_unpackhi_epi64(threshold[0], threshold[0]);
#if SKIP_EOB_FACTOR_ADJUST
int first = -1;
#endif
// Setup global values.
zbin = _mm_load_si128((const __m128i *)zbin_ptr);
round = _mm_load_si128((const __m128i *)round_ptr);
quant = _mm_load_si128((const __m128i *)quant_ptr);
dequant = _mm_load_si128((const __m128i *)dequant_ptr);
shift = _mm_load_si128((const __m128i *)quant_shift_ptr);
// Shift with rounding.
zbin = _mm_add_epi16(zbin, log_scale_vec);
round = _mm_add_epi16(round, log_scale_vec);
zbin = _mm_srli_epi16(zbin, log_scale);
round = _mm_srli_epi16(round, log_scale);
zbin = _mm_sub_epi16(zbin, one);
// Do DC and first 15 AC.
coeff0 = load_coefficients(coeff_ptr);
coeff1 = load_coefficients(coeff_ptr + 8);
coeff0_sign = _mm_srai_epi16(coeff0, 15);
coeff1_sign = _mm_srai_epi16(coeff1, 15);
qcoeff0 = invert_sign_sse2(coeff0, coeff0_sign);
qcoeff1 = invert_sign_sse2(coeff1, coeff1_sign);
update_mask0(&qcoeff0, &qcoeff1, threshold, iscan, &is_found0, &mask0);
cmp_mask0 = _mm_cmpgt_epi16(qcoeff0, zbin);
zbin = _mm_unpackhi_epi64(zbin, zbin); // Switch DC to AC
cmp_mask1 = _mm_cmpgt_epi16(qcoeff1, zbin);
update_mask1(&cmp_mask0, &cmp_mask1, iscan, &is_found1, &mask1);
threshold[0] = threshold[1];
all_zero = _mm_or_si128(cmp_mask0, cmp_mask1);
if (_mm_movemask_epi8(all_zero) == 0) {
_mm_store_si128((__m128i *)(qcoeff_ptr), zero);
_mm_store_si128((__m128i *)(qcoeff_ptr + 4), zero);
_mm_store_si128((__m128i *)(qcoeff_ptr + 8), zero);
_mm_store_si128((__m128i *)(qcoeff_ptr + 12), zero);
_mm_store_si128((__m128i *)(dqcoeff_ptr), zero);
_mm_store_si128((__m128i *)(dqcoeff_ptr + 4), zero);
_mm_store_si128((__m128i *)(dqcoeff_ptr + 8), zero);
_mm_store_si128((__m128i *)(dqcoeff_ptr + 12), zero);
round = _mm_unpackhi_epi64(round, round);
quant = _mm_unpackhi_epi64(quant, quant);
shift = _mm_unpackhi_epi64(shift, shift);
dequant = _mm_unpackhi_epi64(dequant, dequant);
} else {
calculate_qcoeff_log_scale(&qcoeff0, round, quant, &shift, &log_scale);
round = _mm_unpackhi_epi64(round, round);
quant = _mm_unpackhi_epi64(quant, quant);
shift = _mm_unpackhi_epi64(shift, shift);
calculate_qcoeff_log_scale(&qcoeff1, round, quant, &shift, &log_scale);
// Reinsert signs
qcoeff0 = invert_sign_sse2(qcoeff0, coeff0_sign);
qcoeff1 = invert_sign_sse2(qcoeff1, coeff1_sign);
// Mask out zbin threshold coeffs
qcoeff0 = _mm_and_si128(qcoeff0, cmp_mask0);
qcoeff1 = _mm_and_si128(qcoeff1, cmp_mask1);
store_coefficients(qcoeff0, qcoeff_ptr);
store_coefficients(qcoeff1, qcoeff_ptr + 8);
calculate_dqcoeff_and_store_log_scale(qcoeff0, dequant, zero, dqcoeff_ptr,
&log_scale);
dequant = _mm_unpackhi_epi64(dequant, dequant);
calculate_dqcoeff_and_store_log_scale(qcoeff1, dequant, zero,
dqcoeff_ptr + 8, &log_scale);
}
// AC only loop.
while (index < n_coeffs) {
coeff0 = load_coefficients(coeff_ptr + index);
coeff1 = load_coefficients(coeff_ptr + index + 8);
coeff0_sign = _mm_srai_epi16(coeff0, 15);
coeff1_sign = _mm_srai_epi16(coeff1, 15);
qcoeff0 = invert_sign_sse2(coeff0, coeff0_sign);
qcoeff1 = invert_sign_sse2(coeff1, coeff1_sign);
update_mask0(&qcoeff0, &qcoeff1, threshold, iscan + index, &is_found0,
&mask0);
cmp_mask0 = _mm_cmpgt_epi16(qcoeff0, zbin);
cmp_mask1 = _mm_cmpgt_epi16(qcoeff1, zbin);
update_mask1(&cmp_mask0, &cmp_mask1, iscan + index, &is_found1, &mask1);
all_zero = _mm_or_si128(cmp_mask0, cmp_mask1);
if (_mm_movemask_epi8(all_zero) == 0) {
_mm_store_si128((__m128i *)(qcoeff_ptr + index), zero);
_mm_store_si128((__m128i *)(qcoeff_ptr + index + 4), zero);
_mm_store_si128((__m128i *)(qcoeff_ptr + index + 8), zero);
_mm_store_si128((__m128i *)(qcoeff_ptr + index + 12), zero);
_mm_store_si128((__m128i *)(dqcoeff_ptr + index), zero);
_mm_store_si128((__m128i *)(dqcoeff_ptr + index + 4), zero);
_mm_store_si128((__m128i *)(dqcoeff_ptr + index + 8), zero);
_mm_store_si128((__m128i *)(dqcoeff_ptr + index + 12), zero);
index += 16;
continue;
}
calculate_qcoeff_log_scale(&qcoeff0, round, quant, &shift, &log_scale);
calculate_qcoeff_log_scale(&qcoeff1, round, quant, &shift, &log_scale);
qcoeff0 = invert_sign_sse2(qcoeff0, coeff0_sign);
qcoeff1 = invert_sign_sse2(qcoeff1, coeff1_sign);
qcoeff0 = _mm_and_si128(qcoeff0, cmp_mask0);
qcoeff1 = _mm_and_si128(qcoeff1, cmp_mask1);
store_coefficients(qcoeff0, qcoeff_ptr + index);
store_coefficients(qcoeff1, qcoeff_ptr + index + 8);
calculate_dqcoeff_and_store_log_scale(qcoeff0, dequant, zero,
dqcoeff_ptr + index, &log_scale);
calculate_dqcoeff_and_store_log_scale(qcoeff1, dequant, zero,
dqcoeff_ptr + index + 8, &log_scale);
index += 16;
}
if (is_found0) non_zero_count = calculate_non_zero_count(mask0);
if (is_found1)
non_zero_count_prescan_add_zero = calculate_non_zero_count(mask1);
for (int i = non_zero_count_prescan_add_zero - 1; i >= non_zero_count; i--) {
const int rc = scan[i];
qcoeff_ptr[rc] = 0;
dqcoeff_ptr[rc] = 0;
}
for (int i = non_zero_count - 1; i >= 0; i--) {
const int rc = scan[i];
if (qcoeff_ptr[rc]) {
eob = i;
break;
}
}
*eob_ptr = eob + 1;
#if SKIP_EOB_FACTOR_ADJUST
// TODO(Aniket): Experiment the following loop with intrinsic by combining
// with the quantization loop above
@ -403,7 +616,6 @@ void aom_quantize_b_32x32_adaptive_sse2(
if ((*eob_ptr - 1) >= 0 && first == (*eob_ptr - 1)) {
const int rc = scan[(*eob_ptr - 1)];
if (qcoeff_ptr[rc] == 1 || qcoeff_ptr[rc] == -1) {
const qm_val_t wt = (1 << AOM_QM_BITS);
const int coeff = coeff_ptr[rc] * wt;
const int coeff_sign = (coeff >> 31);
const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;

View file

@ -20,30 +20,30 @@
#include "aom_ports/emmintrin_compat.h"
// filters only for the 4_h8 convolution
DECLARE_ALIGNED(16, static const uint8_t, filt1_4_h8[16]) = {
0, 1, 1, 2, 2, 3, 3, 4, 2, 3, 3, 4, 4, 5, 5, 6
};
DECLARE_ALIGNED(16, static const uint8_t, filt1_4_h8[16]) = { 0, 1, 1, 2, 2, 3,
3, 4, 2, 3, 3, 4,
4, 5, 5, 6 };
DECLARE_ALIGNED(16, static const uint8_t, filt2_4_h8[16]) = {
4, 5, 5, 6, 6, 7, 7, 8, 6, 7, 7, 8, 8, 9, 9, 10
};
DECLARE_ALIGNED(16, static const uint8_t, filt2_4_h8[16]) = { 4, 5, 5, 6, 6, 7,
7, 8, 6, 7, 7, 8,
8, 9, 9, 10 };
// filters for 8_h8 and 16_h8
DECLARE_ALIGNED(16, static const uint8_t, filt1_global[16]) = {
0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8
};
DECLARE_ALIGNED(16, static const uint8_t,
filt1_global[16]) = { 0, 1, 1, 2, 2, 3, 3, 4,
4, 5, 5, 6, 6, 7, 7, 8 };
DECLARE_ALIGNED(16, static const uint8_t, filt2_global[16]) = {
2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10
};
DECLARE_ALIGNED(16, static const uint8_t,
filt2_global[16]) = { 2, 3, 3, 4, 4, 5, 5, 6,
6, 7, 7, 8, 8, 9, 9, 10 };
DECLARE_ALIGNED(16, static const uint8_t, filt3_global[16]) = {
4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12
};
DECLARE_ALIGNED(16, static const uint8_t,
filt3_global[16]) = { 4, 5, 5, 6, 6, 7, 7, 8,
8, 9, 9, 10, 10, 11, 11, 12 };
DECLARE_ALIGNED(16, static const uint8_t, filt4_global[16]) = {
6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14
};
DECLARE_ALIGNED(16, static const uint8_t,
filt4_global[16]) = { 6, 7, 7, 8, 8, 9, 9, 10,
10, 11, 11, 12, 12, 13, 13, 14 };
DECLARE_ALIGNED(32, static const uint8_t, filt_h4[]) = {
0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 0, 1, 1,

View file

@ -34,6 +34,31 @@ DECLARE_ALIGNED(32, static const uint8_t, filt4_d4_global_avx2[]) = {
2, 3, 4, 5, 3, 4, 5, 6, 4, 5, 6, 7, 5, 6, 7, 8,
};
DECLARE_ALIGNED(32, static const uint8_t, filt_center_global_avx2[32]) = {
3, 255, 4, 255, 5, 255, 6, 255, 7, 255, 8, 255, 9, 255, 10, 255,
3, 255, 4, 255, 5, 255, 6, 255, 7, 255, 8, 255, 9, 255, 10, 255
};
DECLARE_ALIGNED(32, static const uint8_t,
filt1_global_avx2[32]) = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5,
6, 6, 7, 7, 8, 0, 1, 1, 2, 2, 3,
3, 4, 4, 5, 5, 6, 6, 7, 7, 8 };
DECLARE_ALIGNED(32, static const uint8_t,
filt2_global_avx2[32]) = { 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
8, 8, 9, 9, 10, 2, 3, 3, 4, 4, 5,
5, 6, 6, 7, 7, 8, 8, 9, 9, 10 };
DECLARE_ALIGNED(32, static const uint8_t, filt3_global_avx2[32]) = {
4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12,
4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12
};
DECLARE_ALIGNED(32, static const uint8_t, filt4_global_avx2[32]) = {
6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14,
6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14
};
#define CONVOLVE_SR_HORIZONTAL_FILTER_8TAP \
for (i = 0; i < (im_h - 2); i += 2) { \
__m256i data = _mm256_castsi128_si256( \

File diff suppressed because it is too large Load diff

View file

@ -143,3 +143,60 @@ static INLINE void store_coefficients(__m128i coeff_vals,
_mm_store_si128((__m128i *)(coeff_ptr), coeff_vals_1);
_mm_store_si128((__m128i *)(coeff_ptr + 4), coeff_vals_2);
}
static INLINE void update_mask1(__m128i *cmp_mask0, __m128i *cmp_mask1,
const int16_t *iscan_ptr, int *is_found,
__m128i *mask) {
__m128i all_zero;
__m128i temp_mask = _mm_setzero_si128();
all_zero = _mm_or_si128(*cmp_mask0, *cmp_mask1);
if (_mm_movemask_epi8(all_zero)) {
__m128i iscan0 = _mm_load_si128((const __m128i *)(iscan_ptr));
__m128i mask0 = _mm_and_si128(*cmp_mask0, iscan0);
__m128i iscan1 = _mm_load_si128((const __m128i *)(iscan_ptr + 8));
__m128i mask1 = _mm_and_si128(*cmp_mask1, iscan1);
temp_mask = _mm_max_epi16(mask0, mask1);
*is_found = 1;
}
*mask = _mm_max_epi16(temp_mask, *mask);
}
static INLINE void update_mask0(__m128i *qcoeff0, __m128i *qcoeff1,
__m128i *threshold, const int16_t *iscan_ptr,
int *is_found, __m128i *mask) {
__m128i zero = _mm_setzero_si128();
__m128i coeff[4], cmp_mask0, cmp_mask1, cmp_mask2, cmp_mask3;
coeff[0] = _mm_unpacklo_epi16(*qcoeff0, zero);
coeff[1] = _mm_unpackhi_epi16(*qcoeff0, zero);
coeff[2] = _mm_unpacklo_epi16(*qcoeff1, zero);
coeff[3] = _mm_unpackhi_epi16(*qcoeff1, zero);
coeff[0] = _mm_slli_epi32(coeff[0], AOM_QM_BITS);
cmp_mask0 = _mm_cmpgt_epi32(coeff[0], threshold[0]);
coeff[1] = _mm_slli_epi32(coeff[1], AOM_QM_BITS);
cmp_mask1 = _mm_cmpgt_epi32(coeff[1], threshold[1]);
coeff[2] = _mm_slli_epi32(coeff[2], AOM_QM_BITS);
cmp_mask2 = _mm_cmpgt_epi32(coeff[2], threshold[1]);
coeff[3] = _mm_slli_epi32(coeff[3], AOM_QM_BITS);
cmp_mask3 = _mm_cmpgt_epi32(coeff[3], threshold[1]);
cmp_mask0 = _mm_packs_epi32(cmp_mask0, cmp_mask1);
cmp_mask1 = _mm_packs_epi32(cmp_mask2, cmp_mask3);
update_mask1(&cmp_mask0, &cmp_mask1, iscan_ptr, is_found, mask);
}
static INLINE int calculate_non_zero_count(__m128i mask) {
__m128i mask0, mask1;
int non_zero_count = 0;
mask0 = _mm_unpackhi_epi64(mask, mask);
mask1 = _mm_max_epi16(mask0, mask);
mask0 = _mm_shuffle_epi32(mask1, 1);
mask0 = _mm_max_epi16(mask0, mask1);
mask1 = _mm_srli_epi32(mask0, 16);
mask0 = _mm_max_epi16(mask0, mask1);
non_zero_count = _mm_extract_epi16(mask0, 0) + 1;
return non_zero_count;
}

View file

@ -549,8 +549,9 @@ static const arg_def_t enable_angle_delta =
"Enable intra angle delta (0: false, 1: true (default))");
static const arg_def_t disable_trellis_quant =
ARG_DEF(NULL, "disable-trellis-quant", 1,
"Disable trellis optimization of quantized coefficients (0: false ("
"default) 1: true 2: partial true)");
"Disable trellis optimization of quantized coefficients (0: false "
"1: true 2: true for rd search 3: true for estimate yrd serch "
"(default))");
static const arg_def_t enable_qm =
ARG_DEF(NULL, "enable-qm", 1,
"Enable quantisation matrices (0: false (default), 1: true)");
@ -628,9 +629,12 @@ static const arg_def_t aq_mode = ARG_DEF(
NULL, "aq-mode", 1,
"Adaptive quantization mode (0: off (default), 1: variance 2: complexity, "
"3: cyclic refresh)");
static const arg_def_t deltaq_mode = ARG_DEF(
NULL, "deltaq-mode", 1,
"Delta qindex mode (0: off (default), 1: deltaq 2: deltaq + deltalf)");
static const arg_def_t deltaq_mode =
ARG_DEF(NULL, "deltaq-mode", 1,
"Delta qindex mode (0: off (default), 1: deltaq pred efficiency, "
"2: deltaq perceptual)");
static const arg_def_t deltalf_mode = ARG_DEF(
NULL, "delta-lf-mode", 1, "Enable delta-lf-mode (0: off (default), 1: on)");
static const arg_def_t frame_periodic_boost =
ARG_DEF(NULL, "frame-boost", 1,
"Enable frame periodic boost (0: off (default), 1: on)");
@ -839,6 +843,7 @@ static const arg_def_t *av1_args[] = { &cpu_used_av1,
&error_resilient_mode,
&aq_mode,
&deltaq_mode,
&deltalf_mode,
&frame_periodic_boost,
&noise_sens,
&tune_content,
@ -938,6 +943,7 @@ static const int av1_arg_ctrl_map[] = { AOME_SET_CPUUSED,
AV1E_SET_ERROR_RESILIENT_MODE,
AV1E_SET_AQ_MODE,
AV1E_SET_DELTAQ_MODE,
AV1E_SET_DELTALF_MODE,
AV1E_SET_FRAME_PERIODIC_BOOST,
AV1E_SET_NOISE_SENSITIVITY,
AV1E_SET_TUNE_CONTENT,

View file

@ -188,6 +188,7 @@ list(APPEND AOM_AV1_ENCODER_SOURCES
"${AOM_ROOT}/av1/encoder/rd.c"
"${AOM_ROOT}/av1/encoder/rd.h"
"${AOM_ROOT}/av1/encoder/rdopt.c"
"${AOM_ROOT}/av1/encoder/nonrd_pickmode.c"
"${AOM_ROOT}/av1/encoder/rdopt.h"
"${AOM_ROOT}/av1/encoder/reconinter_enc.c"
"${AOM_ROOT}/av1/encoder/reconinter_enc.h"

View file

@ -72,6 +72,7 @@ struct av1_extracfg {
int enable_dual_filter;
AQ_MODE aq_mode;
DELTAQ_MODE deltaq_mode;
int deltalf_mode;
unsigned int frame_periodic_boost;
aom_bit_depth_t bit_depth;
aom_tune_content content;
@ -169,7 +170,7 @@ static struct av1_extracfg default_extra_cfg = {
!CONFIG_SHARP_SETTINGS, // enable_cdef
1, // enable_restoration
1, // enable_obmc
0, // disable_trellis_quant
3, // disable_trellis_quant
0, // enable_qm
DEFAULT_QM_Y, // qm_y
DEFAULT_QM_U, // qm_u
@ -186,6 +187,7 @@ static struct av1_extracfg default_extra_cfg = {
1, // enable dual filter
NO_AQ, // aq_mode
NO_DELTA_Q, // deltaq_mode
0, // delta lf mode
0, // frame_periodic_delta_q
AOM_BITS_8, // Bit depth
AOM_CONTENT_DEFAULT, // content
@ -261,6 +263,9 @@ struct aom_codec_alg_priv {
aom_codec_priv_t base;
aom_codec_enc_cfg_t cfg;
struct av1_extracfg extra_cfg;
aom_rational64_t timestamp_ratio;
aom_codec_pts_t pts_offset;
unsigned char pts_offset_initialized;
AV1EncoderConfig oxcf;
AV1_COMP *cpi;
unsigned char *cx_data;
@ -278,6 +283,23 @@ struct aom_codec_alg_priv {
BufferPool *buffer_pool;
};
static INLINE int gcd(int64_t a, int b) {
int remainder; // remainder
while (b > 0) {
remainder = (int)(a % b);
a = b;
b = remainder;
}
return (int)a;
}
static INLINE void reduce_ratio(aom_rational64_t *ratio) {
const int denom = gcd(ratio->num, ratio->den);
ratio->num /= denom;
ratio->den /= denom;
}
static aom_codec_err_t update_error_state(
aom_codec_alg_priv_t *ctx, const struct aom_internal_error_info *error) {
const aom_codec_err_t res = error->error_code;
@ -324,7 +346,8 @@ static aom_codec_err_t validate_config(aom_codec_alg_priv_t *ctx,
RANGE_CHECK_HI(cfg, rc_min_quantizer, cfg->rc_max_quantizer);
RANGE_CHECK_BOOL(extra_cfg, lossless);
RANGE_CHECK_HI(extra_cfg, aq_mode, AQ_MODE_COUNT - 1);
RANGE_CHECK_HI(extra_cfg, deltaq_mode, DELTAQ_MODE_COUNT - 1);
RANGE_CHECK_HI(extra_cfg, deltaq_mode, DELTA_Q_MODE_COUNT - 1);
RANGE_CHECK_HI(extra_cfg, deltalf_mode, 1);
RANGE_CHECK_HI(extra_cfg, frame_periodic_boost, 1);
RANGE_CHECK_HI(cfg, g_usage, 1);
RANGE_CHECK_HI(cfg, g_threads, MAX_NUM_THREADS);
@ -683,9 +706,6 @@ static aom_codec_err_t set_encoder_config(
}
}
oxcf->enable_tpl_model =
extra_cfg->enable_tpl_model && (oxcf->superres_mode == SUPERRES_NONE);
oxcf->maximum_buffer_size_ms = is_vbr ? 240000 : cfg->rc_buf_sz;
oxcf->starting_buffer_level_ms = is_vbr ? 60000 : cfg->rc_buf_initial_sz;
oxcf->optimal_buffer_level_ms = is_vbr ? 60000 : cfg->rc_buf_optimal_sz;
@ -833,8 +853,23 @@ static aom_codec_err_t set_encoder_config(
oxcf->timing_info_present = 0;
}
oxcf->enable_tpl_model =
extra_cfg->enable_tpl_model && (oxcf->superres_mode == SUPERRES_NONE);
oxcf->aq_mode = extra_cfg->aq_mode;
oxcf->deltaq_mode = extra_cfg->deltaq_mode;
// Turn on tpl model for deltaq_mode == DELTA_Q_OBJECTIVE and no
// superres. If superres is being used on the other hand, turn
// delta_q off.
if (oxcf->deltaq_mode == DELTA_Q_OBJECTIVE) {
if (oxcf->superres_mode == SUPERRES_NONE)
oxcf->enable_tpl_model = 1;
else
oxcf->deltaq_mode = NO_DELTA_Q;
}
oxcf->deltalf_mode =
(oxcf->deltaq_mode != NO_DELTA_Q) && extra_cfg->deltalf_mode;
oxcf->save_as_annexb = cfg->save_as_annexb;
@ -1507,6 +1542,13 @@ static aom_codec_err_t ctrl_set_deltaq_mode(aom_codec_alg_priv_t *ctx,
return update_extra_cfg(ctx, &extra_cfg);
}
static aom_codec_err_t ctrl_set_deltalf_mode(aom_codec_alg_priv_t *ctx,
va_list args) {
struct av1_extracfg extra_cfg = ctx->extra_cfg;
extra_cfg.deltalf_mode = CAST(AV1E_SET_DELTALF_MODE, args);
return update_extra_cfg(ctx, &extra_cfg);
}
static aom_codec_err_t ctrl_set_min_gf_interval(aom_codec_alg_priv_t *ctx,
va_list args) {
struct av1_extracfg extra_cfg = ctx->extra_cfg;
@ -1596,6 +1638,11 @@ static aom_codec_err_t encoder_init(aom_codec_ctx_t *ctx,
res = validate_config(priv, &priv->cfg, &priv->extra_cfg);
if (res == AOM_CODEC_OK) {
priv->timestamp_ratio.den = priv->cfg.g_timebase.den;
priv->timestamp_ratio.num =
(int64_t)priv->cfg.g_timebase.num * TICKS_PER_SEC;
reduce_ratio(&priv->timestamp_ratio);
set_encoder_config(&priv->oxcf, &priv->cfg, &priv->extra_cfg);
priv->oxcf.use_highbitdepth =
(ctx->init_flags & AOM_CODEC_USE_HIGHBITDEPTH) ? 1 : 0;
@ -1643,7 +1690,8 @@ static aom_codec_err_t encoder_encode(aom_codec_alg_priv_t *ctx,
const size_t kMinCompressedSize = 8192;
volatile aom_codec_err_t res = AOM_CODEC_OK;
AV1_COMP *const cpi = ctx->cpi;
const aom_rational_t *const timebase = &ctx->cfg.g_timebase;
const aom_rational64_t *const timestamp_ratio = &ctx->timestamp_ratio;
volatile aom_codec_pts_t ptsvol = pts;
if (cpi == NULL) return AOM_CODEC_INVALID_PARAM;
@ -1670,6 +1718,12 @@ static aom_codec_err_t encoder_encode(aom_codec_alg_priv_t *ctx,
av1_change_config(ctx->cpi, &ctx->oxcf);
}
if (!ctx->pts_offset_initialized) {
ctx->pts_offset = ptsvol;
ctx->pts_offset_initialized = 1;
}
ptsvol -= ctx->pts_offset;
aom_codec_pkt_list_init(&ctx->pkt_list);
volatile aom_enc_frame_flags_t flags = enc_flags;
@ -1700,9 +1754,9 @@ static aom_codec_err_t encoder_encode(aom_codec_alg_priv_t *ctx,
}
if (res == AOM_CODEC_OK) {
int64_t dst_time_stamp = timebase_units_to_ticks(timebase, pts);
int64_t dst_time_stamp = timebase_units_to_ticks(timestamp_ratio, ptsvol);
int64_t dst_end_time_stamp =
timebase_units_to_ticks(timebase, pts + duration);
timebase_units_to_ticks(timestamp_ratio, ptsvol + duration);
// Set up internal flags
if (ctx->base.init_flags & AOM_CODEC_USE_PSNR) cpi->b_calculate_psnr = 1;
@ -1751,7 +1805,7 @@ static aom_codec_err_t encoder_encode(aom_codec_alg_priv_t *ctx,
!is_frame_visible &&
-1 != av1_get_compressed_data(cpi, &lib_flags, &frame_size, cx_data,
&dst_time_stamp, &dst_end_time_stamp,
!img, timebase)) {
!img, timestamp_ratio)) {
cpi->seq_params_locked = 1;
if (frame_size) {
if (ctx->pending_cx_data == 0) ctx->pending_cx_data = cx_data;
@ -1846,7 +1900,9 @@ static aom_codec_err_t encoder_encode(aom_codec_alg_priv_t *ctx,
pkt.data.frame.partition_id = -1;
pkt.data.frame.vis_frame_size = frame_size;
pkt.data.frame.pts = ticks_to_timebase_units(timebase, dst_time_stamp);
pkt.data.frame.pts =
ticks_to_timebase_units(timestamp_ratio, dst_time_stamp) +
ctx->pts_offset;
pkt.data.frame.flags = get_frame_pkt_flags(cpi, lib_flags);
if (has_fwd_keyframe) {
// If one of the invisible frames in the packet is a keyframe, set
@ -1854,7 +1910,7 @@ static aom_codec_err_t encoder_encode(aom_codec_alg_priv_t *ctx,
pkt.data.frame.flags |= AOM_FRAME_IS_DELAYED_RANDOM_ACCESS_POINT;
}
pkt.data.frame.duration = (uint32_t)ticks_to_timebase_units(
timebase, dst_end_time_stamp - dst_time_stamp);
timestamp_ratio, dst_end_time_stamp - dst_time_stamp);
aom_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
@ -2231,6 +2287,7 @@ static aom_codec_ctrl_fn_map_t encoder_ctrl_maps[] = {
{ AV1E_SET_COEFF_COST_UPD_FREQ, ctrl_set_coeff_cost_upd_freq },
{ AV1E_SET_MODE_COST_UPD_FREQ, ctrl_set_mode_cost_upd_freq },
{ AV1E_SET_DELTAQ_MODE, ctrl_set_deltaq_mode },
{ AV1E_SET_DELTALF_MODE, ctrl_set_deltalf_mode },
{ AV1E_SET_FRAME_PERIODIC_BOOST, ctrl_set_frame_periodic_boost },
{ AV1E_SET_TUNE_CONTENT, ctrl_set_tune_content },
{ AV1E_SET_CDF_UPDATE_MODE, ctrl_set_cdf_update_mode },

View file

@ -28,9 +28,9 @@ static const SEG_LVL_FEATURES seg_lvl_lf_lut[MAX_MB_PLANE][2] = {
{ SEG_LVL_ALT_LF_V, SEG_LVL_ALT_LF_V }
};
static const int delta_lf_id_lut[MAX_MB_PLANE][2] = {
{ 0, 1 }, { 2, 2 }, { 3, 3 }
};
static const int delta_lf_id_lut[MAX_MB_PLANE][2] = { { 0, 1 },
{ 2, 2 },
{ 3, 3 } };
enum { VERT_EDGE = 0, HORZ_EDGE = 1, NUM_EDGE_DIRS } UENUM1BYTE(EDGE_DIR);
@ -2044,6 +2044,7 @@ static TX_SIZE set_lpf_parameters(
const BLOCK_SIZE bsize =
get_plane_block_size(mbmi->sb_type, plane_ptr->subsampling_x,
plane_ptr->subsampling_y);
assert(bsize < BLOCK_SIZES_ALL);
const int prediction_masks = edge_dir == VERT_EDGE
? block_size_wide[bsize] - 1
: block_size_high[bsize] - 1;

View file

@ -111,9 +111,8 @@ specialize qw/av1_highbd_convolve8_vert/, "$sse2_x86_64";
#inv txfm
add_proto qw/void av1_inv_txfm_add/, "const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param";
# TODO(http://crbug.com/aomedia/2350): avx2 is disabled due to test vector
# mismatches.
specialize qw/av1_inv_txfm_add ssse3 neon/;
# TODO(yunqing): Disable NEON version due to test vector mismatch.
specialize qw/av1_inv_txfm_add ssse3 avx2/; # neon/;
add_proto qw/void av1_highbd_inv_txfm_add/, "const tran_low_t *dqcoeff, uint8_t *dst, int stride, const TxfmParam *txfm_param";
# TODO(http://crbug.com/aomedia/2350): avx2 is disabled due to test vector
@ -164,9 +163,7 @@ add_proto qw/void av1_inv_txfm2d_add_32x8/, "const int32_t *input, uint16_t *out
add_proto qw/void av1_highbd_dr_prediction_z1/, "uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_above, int dx, int dy, int bd";
specialize qw/av1_highbd_dr_prediction_z1 avx2/;
add_proto qw/void av1_highbd_dr_prediction_z2/, "uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_above, int upsample_left, int dx, int dy, int bd";
# TODO(niva213@gmail.com): Re-enable avx2 after fixing valgrind issue
# https://crbug.com/aomedia/2316
# specialize qw/av1_highbd_dr_prediction_z2 avx2/;
specialize qw/av1_highbd_dr_prediction_z2 avx2/;
add_proto qw/void av1_highbd_dr_prediction_z3/, "uint16_t *dst, ptrdiff_t stride, int bw, int bh, const uint16_t *above, const uint16_t *left, int upsample_left, int dx, int dy, int bd";
specialize qw/av1_highbd_dr_prediction_z3 avx2/;

View file

@ -61,6 +61,8 @@ void av1_reset_skip_context(MACROBLOCKD *xd, int mi_row, int mi_col,
int i;
int nplanes;
int chroma_ref;
assert(bsize < BLOCK_SIZES_ALL);
chroma_ref =
is_chroma_reference(mi_row, mi_col, bsize, xd->plane[1].subsampling_x,
xd->plane[1].subsampling_y);

View file

@ -187,9 +187,7 @@ typedef struct RD_STATS {
int64_t rdcost;
int64_t sse;
int skip; // sse should equal to dist when skip == 1
int64_t ref_rdcost;
int zero_rate;
uint8_t invalid_rate;
#if CONFIG_RD_DEBUG
int txb_coeff_cost[MAX_MB_PLANE];
int txb_coeff_cost_map[MAX_MB_PLANE][TXB_COEFF_COST_MAP_SIZE]
@ -537,6 +535,7 @@ typedef struct macroblockd {
uint8_t ref_mv_count[MODE_CTX_REF_FRAMES];
CANDIDATE_MV ref_mv_stack[MODE_CTX_REF_FRAMES][MAX_REF_MV_STACK_SIZE];
uint16_t weight[MODE_CTX_REF_FRAMES][MAX_REF_MV_STACK_SIZE];
uint8_t is_sec_rect;
// Counts of each reference frame in the above and left neighboring blocks.
@ -786,6 +785,8 @@ static INLINE BLOCK_SIZE get_plane_block_size(BLOCK_SIZE bsize,
int subsampling_x,
int subsampling_y) {
if (bsize == BLOCK_INVALID) return BLOCK_INVALID;
assert(subsampling_x >= 0 && subsampling_x < 2);
assert(subsampling_y >= 0 && subsampling_y < 2);
return ss_size_lookup[bsize][subsampling_x][subsampling_y];
}
@ -1006,6 +1007,7 @@ static INLINE int get_vartx_max_txsize(const MACROBLOCKD *xd, BLOCK_SIZE bsize,
}
static INLINE int is_motion_variation_allowed_bsize(BLOCK_SIZE bsize) {
assert(bsize < BLOCK_SIZES_ALL);
return AOMMIN(block_size_wide[bsize], block_size_high[bsize]) >= 8;
}

View file

@ -121,6 +121,7 @@ void av1_convolve_2d_sr_c(const uint8_t *src, int src_stride, uint8_t *dst,
int16_t im_block[(MAX_SB_SIZE + MAX_FILTER_TAP - 1) * MAX_SB_SIZE];
int im_h = h + filter_params_y->taps - 1;
int im_stride = w;
assert(w <= MAX_SB_SIZE && h <= MAX_SB_SIZE);
const int fo_vert = filter_params_y->taps / 2 - 1;
const int fo_horiz = filter_params_x->taps / 2 - 1;
const int bd = 8;
@ -704,6 +705,7 @@ void av1_highbd_convolve_2d_sr_c(const uint16_t *src, int src_stride,
int16_t im_block[(MAX_SB_SIZE + MAX_FILTER_TAP - 1) * MAX_SB_SIZE];
int im_h = h + filter_params_y->taps - 1;
int im_stride = w;
assert(w <= MAX_SB_SIZE && h <= MAX_SB_SIZE);
const int fo_vert = filter_params_y->taps / 2 - 1;
const int fo_horiz = filter_params_x->taps / 2 - 1;
const int bits =

View file

@ -435,16 +435,16 @@ static const aom_cdf_prob
{ AOM_CDF3(601, 943) }, { AOM_CDF3(14969, 21398) }
};
static const aom_cdf_prob default_newmv_cdf[NEWMV_MODE_CONTEXTS][CDF_SIZE(2)] =
{ { AOM_CDF2(24035) }, { AOM_CDF2(16630) }, { AOM_CDF2(15339) },
{ AOM_CDF2(8386) }, { AOM_CDF2(12222) }, { AOM_CDF2(4676) } };
static const aom_cdf_prob default_newmv_cdf[NEWMV_MODE_CONTEXTS][CDF_SIZE(
2)] = { { AOM_CDF2(24035) }, { AOM_CDF2(16630) }, { AOM_CDF2(15339) },
{ AOM_CDF2(8386) }, { AOM_CDF2(12222) }, { AOM_CDF2(4676) } };
static const aom_cdf_prob default_zeromv_cdf[GLOBALMV_MODE_CONTEXTS][CDF_SIZE(
2)] = { { AOM_CDF2(2175) }, { AOM_CDF2(1054) } };
static const aom_cdf_prob default_refmv_cdf[REFMV_MODE_CONTEXTS][CDF_SIZE(2)] =
{ { AOM_CDF2(23974) }, { AOM_CDF2(24188) }, { AOM_CDF2(17848) },
{ AOM_CDF2(28622) }, { AOM_CDF2(24312) }, { AOM_CDF2(19923) } };
static const aom_cdf_prob default_refmv_cdf[REFMV_MODE_CONTEXTS][CDF_SIZE(
2)] = { { AOM_CDF2(23974) }, { AOM_CDF2(24188) }, { AOM_CDF2(17848) },
{ AOM_CDF2(28622) }, { AOM_CDF2(24312) }, { AOM_CDF2(19923) } };
static const aom_cdf_prob default_drl_cdf[DRL_MODE_CONTEXTS][CDF_SIZE(2)] = {
{ AOM_CDF2(13104) }, { AOM_CDF2(24560) }, { AOM_CDF2(18945) }
@ -470,11 +470,11 @@ static const aom_cdf_prob default_interintra_cdf[BLOCK_SIZE_GROUPS][CDF_SIZE(
{ AOM_CDF2(30237) } };
static const aom_cdf_prob
default_interintra_mode_cdf[BLOCK_SIZE_GROUPS][CDF_SIZE(INTERINTRA_MODES)] =
{ { AOM_CDF4(8192, 16384, 24576) },
{ AOM_CDF4(1875, 11082, 27332) },
{ AOM_CDF4(2473, 9996, 26388) },
{ AOM_CDF4(4238, 11537, 25926) } };
default_interintra_mode_cdf[BLOCK_SIZE_GROUPS][CDF_SIZE(
INTERINTRA_MODES)] = { { AOM_CDF4(8192, 16384, 24576) },
{ AOM_CDF4(1875, 11082, 27332) },
{ AOM_CDF4(2473, 9996, 26388) },
{ AOM_CDF4(4238, 11537, 25926) } };
static const aom_cdf_prob
default_wedge_interintra_cdf[BLOCK_SIZES_ALL][CDF_SIZE(2)] = {
@ -500,51 +500,51 @@ static const aom_cdf_prob default_compound_type_cdf[BLOCK_SIZES_ALL][CDF_SIZE(
{ AOM_CDF2(16384) }
};
static const aom_cdf_prob default_wedge_idx_cdf[BLOCK_SIZES_ALL][CDF_SIZE(16)] =
{ { AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432,
20480, 22528, 24576, 26624, 28672, 30720) },
{ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432,
20480, 22528, 24576, 26624, 28672, 30720) },
{ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432,
20480, 22528, 24576, 26624, 28672, 30720) },
{ AOM_CDF16(2438, 4440, 6599, 8663, 11005, 12874, 15751, 18094, 20359,
22362, 24127, 25702, 27752, 29450, 31171) },
{ AOM_CDF16(806, 3266, 6005, 6738, 7218, 7367, 7771, 14588, 16323, 17367,
18452, 19422, 22839, 26127, 29629) },
{ AOM_CDF16(2779, 3738, 4683, 7213, 7775, 8017, 8655, 14357, 17939, 21332,
24520, 27470, 29456, 30529, 31656) },
{ AOM_CDF16(1684, 3625, 5675, 7108, 9302, 11274, 14429, 17144, 19163,
20961, 22884, 24471, 26719, 28714, 30877) },
{ AOM_CDF16(1142, 3491, 6277, 7314, 8089, 8355, 9023, 13624, 15369, 16730,
18114, 19313, 22521, 26012, 29550) },
{ AOM_CDF16(2742, 4195, 5727, 8035, 8980, 9336, 10146, 14124, 17270,
20533, 23434, 25972, 27944, 29570, 31416) },
{ AOM_CDF16(1727, 3948, 6101, 7796, 9841, 12344, 15766, 18944, 20638,
22038, 23963, 25311, 26988, 28766, 31012) },
{ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432,
20480, 22528, 24576, 26624, 28672, 30720) },
{ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432,
20480, 22528, 24576, 26624, 28672, 30720) },
{ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432,
20480, 22528, 24576, 26624, 28672, 30720) },
{ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432,
20480, 22528, 24576, 26624, 28672, 30720) },
{ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432,
20480, 22528, 24576, 26624, 28672, 30720) },
{ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432,
20480, 22528, 24576, 26624, 28672, 30720) },
{ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432,
20480, 22528, 24576, 26624, 28672, 30720) },
{ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432,
20480, 22528, 24576, 26624, 28672, 30720) },
{ AOM_CDF16(154, 987, 1925, 2051, 2088, 2111, 2151, 23033, 23703, 24284,
24985, 25684, 27259, 28883, 30911) },
{ AOM_CDF16(1135, 1322, 1493, 2635, 2696, 2737, 2770, 21016, 22935, 25057,
27251, 29173, 30089, 30960, 31933) },
{ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432,
20480, 22528, 24576, 26624, 28672, 30720) },
{ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432,
20480, 22528, 24576, 26624, 28672, 30720) } };
static const aom_cdf_prob default_wedge_idx_cdf[BLOCK_SIZES_ALL][CDF_SIZE(
16)] = { { AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384,
18432, 20480, 22528, 24576, 26624, 28672, 30720) },
{ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384,
18432, 20480, 22528, 24576, 26624, 28672, 30720) },
{ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384,
18432, 20480, 22528, 24576, 26624, 28672, 30720) },
{ AOM_CDF16(2438, 4440, 6599, 8663, 11005, 12874, 15751, 18094,
20359, 22362, 24127, 25702, 27752, 29450, 31171) },
{ AOM_CDF16(806, 3266, 6005, 6738, 7218, 7367, 7771, 14588, 16323,
17367, 18452, 19422, 22839, 26127, 29629) },
{ AOM_CDF16(2779, 3738, 4683, 7213, 7775, 8017, 8655, 14357, 17939,
21332, 24520, 27470, 29456, 30529, 31656) },
{ AOM_CDF16(1684, 3625, 5675, 7108, 9302, 11274, 14429, 17144,
19163, 20961, 22884, 24471, 26719, 28714, 30877) },
{ AOM_CDF16(1142, 3491, 6277, 7314, 8089, 8355, 9023, 13624, 15369,
16730, 18114, 19313, 22521, 26012, 29550) },
{ AOM_CDF16(2742, 4195, 5727, 8035, 8980, 9336, 10146, 14124,
17270, 20533, 23434, 25972, 27944, 29570, 31416) },
{ AOM_CDF16(1727, 3948, 6101, 7796, 9841, 12344, 15766, 18944,
20638, 22038, 23963, 25311, 26988, 28766, 31012) },
{ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384,
18432, 20480, 22528, 24576, 26624, 28672, 30720) },
{ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384,
18432, 20480, 22528, 24576, 26624, 28672, 30720) },
{ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384,
18432, 20480, 22528, 24576, 26624, 28672, 30720) },
{ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384,
18432, 20480, 22528, 24576, 26624, 28672, 30720) },
{ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384,
18432, 20480, 22528, 24576, 26624, 28672, 30720) },
{ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384,
18432, 20480, 22528, 24576, 26624, 28672, 30720) },
{ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384,
18432, 20480, 22528, 24576, 26624, 28672, 30720) },
{ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384,
18432, 20480, 22528, 24576, 26624, 28672, 30720) },
{ AOM_CDF16(154, 987, 1925, 2051, 2088, 2111, 2151, 23033, 23703,
24284, 24985, 25684, 27259, 28883, 30911) },
{ AOM_CDF16(1135, 1322, 1493, 2635, 2696, 2737, 2770, 21016, 22935,
25057, 27251, 29173, 30089, 30960, 31933) },
{ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384,
18432, 20480, 22528, 24576, 26624, 28672, 30720) },
{ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384,
18432, 20480, 22528, 24576, 26624, 28672, 30720) } };
static const aom_cdf_prob default_motion_mode_cdf[BLOCK_SIZES_ALL][CDF_SIZE(
MOTION_MODES)] = { { AOM_CDF3(10923, 21845) }, { AOM_CDF3(10923, 21845) },

View file

@ -526,7 +526,9 @@ enum {
#define DELTA_Q_SMALL 3
#define DELTA_Q_PROBS (DELTA_Q_SMALL)
#define DEFAULT_DELTA_Q_RES 4
#define DEFAULT_DELTA_Q_RES_PERCEPTUAL 4
#define DEFAULT_DELTA_Q_RES_OBJECTIVE 8
#define DELTA_LF_SMALL 3
#define DELTA_LF_PROBS (DELTA_LF_SMALL)
#define DEFAULT_DELTA_LF_RES 2
@ -625,6 +627,25 @@ enum {
RESTORE_TYPES = 4,
} UENUM1BYTE(RestorationType);
// Picture prediction structures (0-12 are predefined) in scalability metadata.
enum {
SCALABILITY_L1T2 = 0,
SCALABILITY_L1T3 = 1,
SCALABILITY_L2T1 = 2,
SCALABILITY_L2T2 = 3,
SCALABILITY_L2T3 = 4,
SCALABILITY_S2T1 = 5,
SCALABILITY_S2T2 = 6,
SCALABILITY_S2T3 = 7,
SCALABILITY_L2T1h = 8,
SCALABILITY_L2T2h = 9,
SCALABILITY_L2T3h = 10,
SCALABILITY_S2T1h = 11,
SCALABILITY_S2T2h = 12,
SCALABILITY_S2T3h = 13,
SCALABILITY_SS = 14
} UENUM1BYTE(SCALABILITY_STRUCTURES);
#define SUPERRES_SCALE_BITS 3
#define SUPERRES_SCALE_DENOMINATOR_MIN (SCALE_NUMERATOR + 1)

View file

@ -277,7 +277,6 @@ static INLINE TransformationType get_wmtype(const WarpedMotionParams *gm) {
typedef struct candidate_mv {
int_mv this_mv;
int_mv comp_mv;
int weight;
} CANDIDATE_MV;
static INLINE int is_zero_mv(const MV *mv) {

View file

@ -74,8 +74,9 @@ void av1_copy_frame_mvs(const AV1_COMMON *const cm,
static void add_ref_mv_candidate(
const MB_MODE_INFO *const candidate, const MV_REFERENCE_FRAME rf[2],
uint8_t *refmv_count, uint8_t *ref_match_count, uint8_t *newmv_count,
CANDIDATE_MV *ref_mv_stack, int_mv *gm_mv_candidates,
const WarpedMotionParams *gm_params, int col, int weight) {
CANDIDATE_MV *ref_mv_stack, uint16_t *ref_mv_weight,
int_mv *gm_mv_candidates, const WarpedMotionParams *gm_params, int col,
uint16_t weight) {
if (!is_inter_block(candidate)) return; // for intrabc
int index = 0, ref;
assert(weight % 2 == 0);
@ -93,12 +94,12 @@ static void add_ref_mv_candidate(
for (index = 0; index < *refmv_count; ++index)
if (ref_mv_stack[index].this_mv.as_int == this_refmv.as_int) break;
if (index < *refmv_count) ref_mv_stack[index].weight += weight;
if (index < *refmv_count) ref_mv_weight[index] += weight;
// Add a new item to the list.
if (index == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) {
ref_mv_stack[index].this_mv = this_refmv;
ref_mv_stack[index].weight = weight;
ref_mv_weight[index] = weight;
++(*refmv_count);
}
if (have_newmv_in_inter_mode(candidate->mode)) ++*newmv_count;
@ -122,13 +123,13 @@ static void add_ref_mv_candidate(
(ref_mv_stack[index].comp_mv.as_int == this_refmv[1].as_int))
break;
if (index < *refmv_count) ref_mv_stack[index].weight += weight;
if (index < *refmv_count) ref_mv_weight[index] += weight;
// Add a new item to the list.
if (index == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) {
ref_mv_stack[index].this_mv = this_refmv[0];
ref_mv_stack[index].comp_mv = this_refmv[1];
ref_mv_stack[index].weight = weight;
ref_mv_weight[index] = weight;
++(*refmv_count);
}
if (have_newmv_in_inter_mode(candidate->mode)) ++*newmv_count;
@ -140,10 +141,10 @@ static void add_ref_mv_candidate(
static void scan_row_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
int mi_row, int mi_col,
const MV_REFERENCE_FRAME rf[2], int row_offset,
CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count,
uint8_t *ref_match_count, uint8_t *newmv_count,
int_mv *gm_mv_candidates, int max_row_offset,
int *processed_rows) {
CANDIDATE_MV *ref_mv_stack, uint16_t *ref_mv_weight,
uint8_t *refmv_count, uint8_t *ref_match_count,
uint8_t *newmv_count, int_mv *gm_mv_candidates,
int max_row_offset, int *processed_rows) {
int end_mi = AOMMIN(xd->n4_w, cm->mi_cols - mi_col);
end_mi = AOMMIN(end_mi, mi_size_wide[BLOCK_64X64]);
const int n8_w_8 = mi_size_wide[BLOCK_8X8];
@ -169,10 +170,10 @@ static void scan_row_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
else if (abs(row_offset) > 1)
len = AOMMAX(len, n8_w_8);
int weight = 2;
uint16_t weight = 2;
if (xd->n4_w >= n8_w_8 && xd->n4_w <= n4_w) {
int inc = AOMMIN(-max_row_offset + row_offset + 1,
mi_size_high[candidate_bsize]);
uint16_t inc = AOMMIN(-max_row_offset + row_offset + 1,
mi_size_high[candidate_bsize]);
// Obtain range used in weight calculation.
weight = AOMMAX(weight, inc);
// Update processed rows.
@ -180,8 +181,9 @@ static void scan_row_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
}
add_ref_mv_candidate(candidate, rf, refmv_count, ref_match_count,
newmv_count, ref_mv_stack, gm_mv_candidates,
cm->global_motion, col_offset + i, len * weight);
newmv_count, ref_mv_stack, ref_mv_weight,
gm_mv_candidates, cm->global_motion, col_offset + i,
len * weight);
i += len;
}
@ -190,10 +192,10 @@ static void scan_row_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
static void scan_col_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
int mi_row, int mi_col,
const MV_REFERENCE_FRAME rf[2], int col_offset,
CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count,
uint8_t *ref_match_count, uint8_t *newmv_count,
int_mv *gm_mv_candidates, int max_col_offset,
int *processed_cols) {
CANDIDATE_MV *ref_mv_stack, uint16_t *ref_mv_weight,
uint8_t *refmv_count, uint8_t *ref_match_count,
uint8_t *newmv_count, int_mv *gm_mv_candidates,
int max_col_offset, int *processed_cols) {
int end_mi = AOMMIN(xd->n4_h, cm->mi_rows - mi_row);
end_mi = AOMMIN(end_mi, mi_size_high[BLOCK_64X64]);
const int n8_h_8 = mi_size_high[BLOCK_8X8];
@ -229,8 +231,9 @@ static void scan_col_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
}
add_ref_mv_candidate(candidate, rf, refmv_count, ref_match_count,
newmv_count, ref_mv_stack, gm_mv_candidates,
cm->global_motion, col_offset, len * weight);
newmv_count, ref_mv_stack, ref_mv_weight,
gm_mv_candidates, cm->global_motion, col_offset,
len * weight);
i += len;
}
@ -240,8 +243,8 @@ static void scan_blk_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
const int mi_row, const int mi_col,
const MV_REFERENCE_FRAME rf[2], int row_offset,
int col_offset, CANDIDATE_MV *ref_mv_stack,
uint8_t *ref_match_count, uint8_t *newmv_count,
int_mv *gm_mv_candidates,
uint16_t *ref_mv_weight, uint8_t *ref_match_count,
uint8_t *newmv_count, int_mv *gm_mv_candidates,
uint8_t refmv_count[MODE_CTX_REF_FRAMES]) {
const TileInfo *const tile = &xd->tile;
POSITION mi_pos;
@ -255,8 +258,9 @@ static void scan_blk_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
const int len = mi_size_wide[BLOCK_8X8];
add_ref_mv_candidate(candidate, rf, refmv_count, ref_match_count,
newmv_count, ref_mv_stack, gm_mv_candidates,
cm->global_motion, mi_pos.col, 2 * len);
newmv_count, ref_mv_stack, ref_mv_weight,
gm_mv_candidates, cm->global_motion, mi_pos.col,
2 * len);
} // Analyze a single 8x8 block motion information.
}
@ -328,10 +332,11 @@ static int add_tpl_ref_mv(const AV1_COMMON *cm, const MACROBLOCKD *xd,
int blk_row, int blk_col, int_mv *gm_mv_candidates,
uint8_t refmv_count[MODE_CTX_REF_FRAMES],
CANDIDATE_MV ref_mv_stacks[][MAX_REF_MV_STACK_SIZE],
uint16_t ref_mv_weights[][MAX_REF_MV_STACK_SIZE],
int16_t *mode_context) {
POSITION mi_pos;
int idx;
const int weight_unit = 1; // mi_size_wide[BLOCK_8X8];
const uint16_t weight_unit = 1; // mi_size_wide[BLOCK_8X8];
mi_pos.row = (mi_row & 0x01) ? blk_row : blk_row + 1;
mi_pos.col = (mi_col & 0x01) ? blk_col : blk_col + 1;
@ -352,7 +357,7 @@ static int add_tpl_ref_mv(const AV1_COMMON *cm, const MACROBLOCKD *xd,
int cur_offset_0 = get_relative_dist(&cm->seq_params.order_hint_info,
cur_frame_index, frame0_index);
CANDIDATE_MV *ref_mv_stack = ref_mv_stacks[rf[0]];
uint16_t *ref_mv_weight = ref_mv_weights[rf[0]];
if (prev_frame_mvs->mfmv0.as_int != INVALID_MV) {
int_mv this_refmv;
@ -369,12 +374,12 @@ static int add_tpl_ref_mv(const AV1_COMMON *cm, const MACROBLOCKD *xd,
for (idx = 0; idx < refmv_count[rf[0]]; ++idx)
if (this_refmv.as_int == ref_mv_stack[idx].this_mv.as_int) break;
if (idx < refmv_count[rf[0]]) ref_mv_stack[idx].weight += 2 * weight_unit;
if (idx < refmv_count[rf[0]]) ref_mv_weight[idx] += 2 * weight_unit;
if (idx == refmv_count[rf[0]] &&
refmv_count[rf[0]] < MAX_REF_MV_STACK_SIZE) {
ref_mv_stack[idx].this_mv.as_int = this_refmv.as_int;
ref_mv_stack[idx].weight = 2 * weight_unit;
ref_mv_weight[idx] = 2 * weight_unit;
++(refmv_count[rf[0]]);
}
return 1;
@ -392,7 +397,7 @@ static int add_tpl_ref_mv(const AV1_COMMON *cm, const MACROBLOCKD *xd,
int cur_offset_1 = get_relative_dist(&cm->seq_params.order_hint_info,
cur_frame_index, frame1_index);
CANDIDATE_MV *ref_mv_stack = ref_mv_stacks[ref_frame];
uint16_t *ref_mv_weight = ref_mv_weights[ref_frame];
if (prev_frame_mvs->mfmv0.as_int != INVALID_MV) {
int_mv this_refmv;
int_mv comp_refmv;
@ -418,14 +423,13 @@ static int add_tpl_ref_mv(const AV1_COMMON *cm, const MACROBLOCKD *xd,
comp_refmv.as_int == ref_mv_stack[idx].comp_mv.as_int)
break;
if (idx < refmv_count[ref_frame])
ref_mv_stack[idx].weight += 2 * weight_unit;
if (idx < refmv_count[ref_frame]) ref_mv_weight[idx] += 2 * weight_unit;
if (idx == refmv_count[ref_frame] &&
refmv_count[ref_frame] < MAX_REF_MV_STACK_SIZE) {
ref_mv_stack[idx].this_mv.as_int = this_refmv.as_int;
ref_mv_stack[idx].comp_mv.as_int = comp_refmv.as_int;
ref_mv_stack[idx].weight = 2 * weight_unit;
ref_mv_weight[idx] = 2 * weight_unit;
++(refmv_count[ref_frame]);
}
return 1;
@ -462,7 +466,8 @@ static void process_compound_ref_mv_candidate(
static void process_single_ref_mv_candidate(
const MB_MODE_INFO *const candidate, const AV1_COMMON *const cm,
MV_REFERENCE_FRAME ref_frame, uint8_t refmv_count[MODE_CTX_REF_FRAMES],
CANDIDATE_MV ref_mv_stack[][MAX_REF_MV_STACK_SIZE]) {
CANDIDATE_MV ref_mv_stack[][MAX_REF_MV_STACK_SIZE],
uint16_t ref_mv_weight[][MAX_REF_MV_STACK_SIZE]) {
for (int rf_idx = 0; rf_idx < 2; ++rf_idx) {
if (candidate->ref_frame[rf_idx] > INTRA_FRAME) {
int_mv this_mv = candidate->mv[rf_idx];
@ -482,7 +487,7 @@ static void process_single_ref_mv_candidate(
// TODO(jingning): Set an arbitrary small number here. The weight
// doesn't matter as long as it is properly initialized.
ref_mv_stack[ref_frame][stack_idx].weight = 2;
ref_mv_weight[ref_frame][stack_idx] = 2;
++refmv_count[ref_frame];
}
}
@ -493,6 +498,7 @@ static void setup_ref_mv_list(
const AV1_COMMON *cm, const MACROBLOCKD *xd, MV_REFERENCE_FRAME ref_frame,
uint8_t refmv_count[MODE_CTX_REF_FRAMES],
CANDIDATE_MV ref_mv_stack[][MAX_REF_MV_STACK_SIZE],
uint16_t ref_mv_weight[][MAX_REF_MV_STACK_SIZE],
int_mv mv_ref_list[][MAX_MV_REF_CANDIDATES], int_mv *gm_mv_candidates,
int mi_row, int mi_col, int16_t *mode_context) {
const int bs = AOMMAX(xd->n4_w, xd->n4_h);
@ -536,25 +542,28 @@ static void setup_ref_mv_list(
// Scan the first above row mode info. row_offset = -1;
if (abs(max_row_offset) >= 1)
scan_row_mbmi(cm, xd, mi_row, mi_col, rf, -1, ref_mv_stack[ref_frame],
&refmv_count[ref_frame], &row_match_count, &newmv_count,
gm_mv_candidates, max_row_offset, &processed_rows);
ref_mv_weight[ref_frame], &refmv_count[ref_frame],
&row_match_count, &newmv_count, gm_mv_candidates,
max_row_offset, &processed_rows);
// Scan the first left column mode info. col_offset = -1;
if (abs(max_col_offset) >= 1)
scan_col_mbmi(cm, xd, mi_row, mi_col, rf, -1, ref_mv_stack[ref_frame],
&refmv_count[ref_frame], &col_match_count, &newmv_count,
gm_mv_candidates, max_col_offset, &processed_cols);
ref_mv_weight[ref_frame], &refmv_count[ref_frame],
&col_match_count, &newmv_count, gm_mv_candidates,
max_col_offset, &processed_cols);
// Check top-right boundary
if (has_tr)
scan_blk_mbmi(cm, xd, mi_row, mi_col, rf, -1, xd->n4_w,
ref_mv_stack[ref_frame], &row_match_count, &newmv_count,
gm_mv_candidates, &refmv_count[ref_frame]);
ref_mv_stack[ref_frame], ref_mv_weight[ref_frame],
&row_match_count, &newmv_count, gm_mv_candidates,
&refmv_count[ref_frame]);
const uint8_t nearest_match = (row_match_count > 0) + (col_match_count > 0);
const uint8_t nearest_refmv_count = refmv_count[ref_frame];
// TODO(yunqing): for comp_search, do it for all 3 cases.
for (int idx = 0; idx < nearest_refmv_count; ++idx)
ref_mv_stack[ref_frame][idx].weight += REF_CAT_LEVEL;
ref_mv_weight[ref_frame][idx] += REF_CAT_LEVEL;
if (cm->allow_ref_frame_mvs) {
int is_available = 0;
@ -584,7 +593,7 @@ static void setup_ref_mv_list(
for (int blk_col = 0; blk_col < blk_col_end; blk_col += step_w) {
int ret = add_tpl_ref_mv(cm, xd, mi_row, mi_col, ref_frame, blk_row,
blk_col, gm_mv_candidates, refmv_count,
ref_mv_stack, mode_context);
ref_mv_stack, ref_mv_weight, mode_context);
if (blk_row == 0 && blk_col == 0) is_available = ret;
}
}
@ -597,7 +606,8 @@ static void setup_ref_mv_list(
if (!check_sb_border(mi_row, mi_col, blk_row, blk_col)) continue;
add_tpl_ref_mv(cm, xd, mi_row, mi_col, ref_frame, blk_row, blk_col,
gm_mv_candidates, refmv_count, ref_mv_stack, mode_context);
gm_mv_candidates, refmv_count, ref_mv_stack, ref_mv_weight,
mode_context);
}
}
@ -605,8 +615,8 @@ static void setup_ref_mv_list(
// Scan the second outer area.
scan_blk_mbmi(cm, xd, mi_row, mi_col, rf, -1, -1, ref_mv_stack[ref_frame],
&row_match_count, &dummy_newmv_count, gm_mv_candidates,
&refmv_count[ref_frame]);
ref_mv_weight[ref_frame], &row_match_count, &dummy_newmv_count,
gm_mv_candidates, &refmv_count[ref_frame]);
for (int idx = 2; idx <= MVREF_ROW_COLS; ++idx) {
const int row_offset = -(idx << 1) + 1 + row_adj;
@ -615,16 +625,18 @@ static void setup_ref_mv_list(
if (abs(row_offset) <= abs(max_row_offset) &&
abs(row_offset) > processed_rows)
scan_row_mbmi(cm, xd, mi_row, mi_col, rf, row_offset,
ref_mv_stack[ref_frame], &refmv_count[ref_frame],
&row_match_count, &dummy_newmv_count, gm_mv_candidates,
max_row_offset, &processed_rows);
ref_mv_stack[ref_frame], ref_mv_weight[ref_frame],
&refmv_count[ref_frame], &row_match_count,
&dummy_newmv_count, gm_mv_candidates, max_row_offset,
&processed_rows);
if (abs(col_offset) <= abs(max_col_offset) &&
abs(col_offset) > processed_cols)
scan_col_mbmi(cm, xd, mi_row, mi_col, rf, col_offset,
ref_mv_stack[ref_frame], &refmv_count[ref_frame],
&col_match_count, &dummy_newmv_count, gm_mv_candidates,
max_col_offset, &processed_cols);
ref_mv_stack[ref_frame], ref_mv_weight[ref_frame],
&refmv_count[ref_frame], &col_match_count,
&dummy_newmv_count, gm_mv_candidates, max_col_offset,
&processed_cols);
}
const uint8_t ref_match_count = (row_match_count > 0) + (col_match_count > 0);
@ -661,11 +673,13 @@ static void setup_ref_mv_list(
while (len > 0) {
int nr_len = 0;
for (int idx = 1; idx < len; ++idx) {
if (ref_mv_stack[ref_frame][idx - 1].weight <
ref_mv_stack[ref_frame][idx].weight) {
if (ref_mv_weight[ref_frame][idx - 1] < ref_mv_weight[ref_frame][idx]) {
CANDIDATE_MV tmp_mv = ref_mv_stack[ref_frame][idx - 1];
uint16_t tmp_ref_mv_weight = ref_mv_weight[ref_frame][idx - 1];
ref_mv_stack[ref_frame][idx - 1] = ref_mv_stack[ref_frame][idx];
ref_mv_stack[ref_frame][idx] = tmp_mv;
ref_mv_weight[ref_frame][idx - 1] = ref_mv_weight[ref_frame][idx];
ref_mv_weight[ref_frame][idx] = tmp_ref_mv_weight;
nr_len = idx;
}
}
@ -676,11 +690,13 @@ static void setup_ref_mv_list(
while (len > nearest_refmv_count) {
int nr_len = nearest_refmv_count;
for (int idx = nearest_refmv_count + 1; idx < len; ++idx) {
if (ref_mv_stack[ref_frame][idx - 1].weight <
ref_mv_stack[ref_frame][idx].weight) {
if (ref_mv_weight[ref_frame][idx - 1] < ref_mv_weight[ref_frame][idx]) {
CANDIDATE_MV tmp_mv = ref_mv_stack[ref_frame][idx - 1];
uint16_t tmp_ref_mv_weight = ref_mv_weight[ref_frame][idx - 1];
ref_mv_stack[ref_frame][idx - 1] = ref_mv_stack[ref_frame][idx];
ref_mv_stack[ref_frame][idx] = tmp_mv;
ref_mv_weight[ref_frame][idx - 1] = ref_mv_weight[ref_frame][idx];
ref_mv_weight[ref_frame][idx] = tmp_ref_mv_weight;
nr_len = idx;
}
}
@ -745,7 +761,7 @@ static void setup_ref_mv_list(
ref_mv_stack[ref_frame][refmv_count[ref_frame]].comp_mv =
comp_list[0][1];
}
ref_mv_stack[ref_frame][refmv_count[ref_frame]].weight = 2;
ref_mv_weight[ref_frame][refmv_count[ref_frame]] = 2;
++refmv_count[ref_frame];
} else {
for (int idx = 0; idx < MAX_MV_REF_CANDIDATES; ++idx) {
@ -753,7 +769,7 @@ static void setup_ref_mv_list(
comp_list[idx][0];
ref_mv_stack[ref_frame][refmv_count[ref_frame]].comp_mv =
comp_list[idx][1];
ref_mv_stack[ref_frame][refmv_count[ref_frame]].weight = 2;
ref_mv_weight[ref_frame][refmv_count[ref_frame]] = 2;
++refmv_count[ref_frame];
}
}
@ -779,7 +795,7 @@ static void setup_ref_mv_list(
refmv_count[ref_frame] < MAX_MV_REF_CANDIDATES;) {
const MB_MODE_INFO *const candidate = xd->mi[-xd->mi_stride + idx];
process_single_ref_mv_candidate(candidate, cm, ref_frame, refmv_count,
ref_mv_stack);
ref_mv_stack, ref_mv_weight);
idx += mi_size_wide[candidate->sb_type];
}
@ -787,7 +803,7 @@ static void setup_ref_mv_list(
refmv_count[ref_frame] < MAX_MV_REF_CANDIDATES;) {
const MB_MODE_INFO *const candidate = xd->mi[idx * xd->mi_stride - 1];
process_single_ref_mv_candidate(candidate, cm, ref_frame, refmv_count,
ref_mv_stack);
ref_mv_stack, ref_mv_weight);
idx += mi_size_high[candidate->sb_type];
}
@ -813,6 +829,7 @@ void av1_find_mv_refs(const AV1_COMMON *cm, const MACROBLOCKD *xd,
MB_MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
uint8_t ref_mv_count[MODE_CTX_REF_FRAMES],
CANDIDATE_MV ref_mv_stack[][MAX_REF_MV_STACK_SIZE],
uint16_t ref_mv_weight[][MAX_REF_MV_STACK_SIZE],
int_mv mv_ref_list[][MAX_MV_REF_CANDIDATES],
int_mv *global_mvs, int mi_row, int mi_col,
int16_t *mode_context) {
@ -848,8 +865,9 @@ void av1_find_mv_refs(const AV1_COMMON *cm, const MACROBLOCKD *xd,
zeromv[0].as_int = zeromv[1].as_int = 0;
}
setup_ref_mv_list(cm, xd, ref_frame, ref_mv_count, ref_mv_stack, mv_ref_list,
zeromv, mi_row, mi_col, mode_context);
setup_ref_mv_list(cm, xd, ref_frame, ref_mv_count, ref_mv_stack,
ref_mv_weight, mv_ref_list, zeromv, mi_row, mi_col,
mode_context);
}
void av1_find_best_ref_mvs(int allow_hp, int_mv *mvlist, int_mv *nearest_mv,

View file

@ -189,18 +189,17 @@ static INLINE int16_t av1_mode_context_analyzer(
return comp_ctx;
}
static INLINE uint8_t av1_drl_ctx(const CANDIDATE_MV *ref_mv_stack,
int ref_idx) {
if (ref_mv_stack[ref_idx].weight >= REF_CAT_LEVEL &&
ref_mv_stack[ref_idx + 1].weight >= REF_CAT_LEVEL)
static INLINE uint8_t av1_drl_ctx(const uint16_t *ref_mv_weight, int ref_idx) {
if (ref_mv_weight[ref_idx] >= REF_CAT_LEVEL &&
ref_mv_weight[ref_idx + 1] >= REF_CAT_LEVEL)
return 0;
if (ref_mv_stack[ref_idx].weight >= REF_CAT_LEVEL &&
ref_mv_stack[ref_idx + 1].weight < REF_CAT_LEVEL)
if (ref_mv_weight[ref_idx] >= REF_CAT_LEVEL &&
ref_mv_weight[ref_idx + 1] < REF_CAT_LEVEL)
return 1;
if (ref_mv_stack[ref_idx].weight < REF_CAT_LEVEL &&
ref_mv_stack[ref_idx + 1].weight < REF_CAT_LEVEL)
if (ref_mv_weight[ref_idx] < REF_CAT_LEVEL &&
ref_mv_weight[ref_idx + 1] < REF_CAT_LEVEL)
return 2;
return 0;
@ -251,6 +250,7 @@ void av1_find_mv_refs(const AV1_COMMON *cm, const MACROBLOCKD *xd,
MB_MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
uint8_t ref_mv_count[MODE_CTX_REF_FRAMES],
CANDIDATE_MV ref_mv_stack[][MAX_REF_MV_STACK_SIZE],
uint16_t ref_mv_weight[][MAX_REF_MV_STACK_SIZE],
int_mv mv_ref_list[][MAX_MV_REF_CANDIDATES],
int_mv *global_mvs, int mi_row, int mi_col,
int16_t *mode_context);

View file

@ -917,6 +917,7 @@ static INLINE void update_partition_context(MACROBLOCKD *xd, int mi_row,
static INLINE int is_chroma_reference(int mi_row, int mi_col, BLOCK_SIZE bsize,
int subsampling_x, int subsampling_y) {
assert(bsize < BLOCK_SIZES_ALL);
const int bw = mi_size_wide[bsize];
const int bh = mi_size_high[bsize];
int ref_pos = ((mi_row & 0x01) || !(bh & 0x01) || !subsampling_y) &&
@ -926,6 +927,8 @@ static INLINE int is_chroma_reference(int mi_row, int mi_col, BLOCK_SIZE bsize,
static INLINE BLOCK_SIZE scale_chroma_bsize(BLOCK_SIZE bsize, int subsampling_x,
int subsampling_y) {
assert(subsampling_x >= 0 && subsampling_x < 2);
assert(subsampling_y >= 0 && subsampling_y < 2);
BLOCK_SIZE bs = bsize;
switch (bsize) {
case BLOCK_4X4:
@ -1076,6 +1079,7 @@ static INLINE int partition_cdf_length(BLOCK_SIZE bsize) {
static INLINE int max_block_wide(const MACROBLOCKD *xd, BLOCK_SIZE bsize,
int plane) {
assert(bsize < BLOCK_SIZES_ALL);
int max_blocks_wide = block_size_wide[bsize];
const struct macroblockd_plane *const pd = &xd->plane[plane];

View file

@ -182,6 +182,7 @@ int av1_get_palette_cache(const MACROBLOCKD *const xd, int plane,
uint16_t *cache);
static INLINE int av1_get_palette_bsize_ctx(BLOCK_SIZE bsize) {
assert(bsize < BLOCK_SIZES_ALL);
return num_pels_log2_lookup[bsize] - num_pels_log2_lookup[BLOCK_8X8];
}

View file

@ -1140,6 +1140,7 @@ void av1_build_interintra_predictors_sbp(const AV1_COMMON *cm, MACROBLOCKD *xd,
uint8_t *pred, int stride,
const BUFFER_SET *ctx, int plane,
BLOCK_SIZE bsize) {
assert(bsize < BLOCK_SIZES_ALL);
if (is_cur_buf_hbd(xd)) {
DECLARE_ALIGNED(16, uint16_t, intrapredictor[MAX_SB_SQUARE]);
av1_build_intra_predictors_for_interintra(

View file

@ -1015,9 +1015,9 @@ static int intra_edge_filter_strength(int bs0, int bs1, int delta, int type) {
void av1_filter_intra_edge_c(uint8_t *p, int sz, int strength) {
if (!strength) return;
const int kernel[INTRA_EDGE_FILT][INTRA_EDGE_TAPS] = {
{ 0, 4, 8, 4, 0 }, { 0, 5, 6, 5, 0 }, { 2, 4, 4, 4, 2 }
};
const int kernel[INTRA_EDGE_FILT][INTRA_EDGE_TAPS] = { { 0, 4, 8, 4, 0 },
{ 0, 5, 6, 5, 0 },
{ 2, 4, 4, 4, 2 } };
const int filt = strength - 1;
uint8_t edge[129];
@ -1048,9 +1048,9 @@ static void filter_intra_edge_corner(uint8_t *p_above, uint8_t *p_left) {
void av1_filter_intra_edge_high_c(uint16_t *p, int sz, int strength) {
if (!strength) return;
const int kernel[INTRA_EDGE_FILT][INTRA_EDGE_TAPS] = {
{ 0, 4, 8, 4, 0 }, { 0, 5, 6, 5, 0 }, { 2, 4, 4, 4, 2 }
};
const int kernel[INTRA_EDGE_FILT][INTRA_EDGE_TAPS] = { { 0, 4, 8, 4, 0 },
{ 0, 5, 6, 5, 0 },
{ 2, 4, 4, 4, 2 } };
const int filt = strength - 1;
uint16_t edge[129];

View file

@ -431,7 +431,6 @@ static int32_t get_upscale_convolve_x0(int in_length, int out_length,
return (int32_t)((uint32_t)x0 & RS_SCALE_SUBPEL_MASK);
}
#ifndef __clang_analyzer__
static void down2_symeven(const uint8_t *const input, int length,
uint8_t *output) {
// Actual filter len = 2 * filter_len_half.
@ -486,7 +485,6 @@ static void down2_symeven(const uint8_t *const input, int length,
}
}
}
#endif
static void down2_symodd(const uint8_t *const input, int length,
uint8_t *output) {
@ -852,7 +850,6 @@ static void highbd_interpolate(const uint16_t *const input, int in_length,
&interp_filters[0][0], SUBPEL_TAPS);
}
#ifndef __clang_analyzer__
static void highbd_down2_symeven(const uint16_t *const input, int length,
uint16_t *output, int bd) {
// Actual filter len = 2 * filter_len_half.
@ -960,7 +957,6 @@ static void highbd_down2_symodd(const uint16_t *const input, int length,
}
}
}
#endif
static void highbd_resize_multistep(const uint16_t *const input, int length,
uint16_t *output, int olength,

View file

@ -1146,7 +1146,7 @@ void av1_loop_restoration_copy_planes(AV1LrStruct *loop_rest_ctxt,
static const copy_fun copy_funs[3] = { aom_yv12_partial_coloc_copy_y,
aom_yv12_partial_coloc_copy_u,
aom_yv12_partial_coloc_copy_v };
assert(num_planes <= 3);
for (int plane = 0; plane < num_planes; ++plane) {
if (cm->rst_info[plane].frame_restoration_type == RESTORE_NONE) continue;
AV1PixelRect tile_rect = loop_rest_ctxt->ctxt[plane].tile_rect;

View file

@ -122,6 +122,7 @@ extern "C" {
// If WIENER_WIN_CHROMA == WIENER_WIN - 2, that implies 5x5 filters are used for
// chroma. To use 7x7 for chroma set WIENER_WIN_CHROMA to WIENER_WIN.
#define WIENER_WIN_CHROMA (WIENER_WIN - 2)
#define WIENER_WIN_REDUCED (WIENER_WIN - 2)
#define WIENER_WIN2_CHROMA ((WIENER_WIN_CHROMA) * (WIENER_WIN_CHROMA))
#define WIENER_FILT_PREC_BITS 7

View file

@ -45,11 +45,13 @@ void av1_setup_scale_factors_for_frame(struct scale_factors *sf, int other_w,
int other_h, int this_w, int this_h);
static INLINE int av1_is_valid_scale(const struct scale_factors *sf) {
assert(sf != NULL);
return sf->x_scale_fp != REF_INVALID_SCALE &&
sf->y_scale_fp != REF_INVALID_SCALE;
}
static INLINE int av1_is_scaled(const struct scale_factors *sf) {
assert(sf != NULL);
return av1_is_valid_scale(sf) &&
(sf->x_scale_fp != REF_NO_SCALE || sf->y_scale_fp != REF_NO_SCALE);
}

View file

@ -14,9 +14,9 @@
#include "av1/common/common_data.h"
#include "av1/common/scan.h"
DECLARE_ALIGNED(16, static const int16_t, default_scan_4x4[16]) = {
0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15
};
DECLARE_ALIGNED(16, static const int16_t,
default_scan_4x4[16]) = { 0, 1, 4, 8, 5, 2, 3, 6,
9, 12, 13, 10, 7, 11, 14, 15 };
DECLARE_ALIGNED(16, static const int16_t, mcol_scan_4x4[16]) = {
0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15,
@ -2376,9 +2376,9 @@ DECLARE_ALIGNED(16, static const int16_t,
990, 1021, 991, 1022, 0, 0
};
DECLARE_ALIGNED(16, static const int16_t, av1_default_iscan_4x4[16]) = {
0, 1, 5, 6, 2, 4, 7, 12, 3, 8, 11, 13, 9, 10, 14, 15
};
DECLARE_ALIGNED(16, static const int16_t,
av1_default_iscan_4x4[16]) = { 0, 1, 5, 6, 2, 4, 7, 12,
3, 8, 11, 13, 9, 10, 14, 15 };
DECLARE_ALIGNED(16, static const int16_t, av1_mcol_iscan_4x4[16]) = {
0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15,

File diff suppressed because it is too large Load diff

View file

@ -574,7 +574,6 @@ static int64_t highbd_warp_error(
CONVERT_TO_BYTEPTR(tmp), j, i, warp_w, warp_h,
WARP_ERROR_BLOCK, subsampling_x, subsampling_y, bd,
&conv_params);
gm_sumerr += highbd_frame_error(
tmp, WARP_ERROR_BLOCK, CONVERT_TO_SHORTPTR(dst8) + j + i * p_stride,
warp_w, warp_h, p_stride, bd);

View file

@ -1638,6 +1638,7 @@ static INLINE void lowbd_inv_txfm2d_add_no_identity_avx2(
assert(row_txfm != NULL);
int ud_flip, lr_flip;
get_flip_cfg(tx_type, &ud_flip, &lr_flip);
const __m256i scale0 = _mm256_set1_epi16(1 << (15 + shift[0]));
for (int i = 0; i < buf_size_nonzero_h_div16; i++) {
__m256i buf0[64];
const int32_t *input_row = input + (i << 4) * input_stride;
@ -1652,7 +1653,9 @@ static INLINE void lowbd_inv_txfm2d_add_no_identity_avx2(
round_shift_avx2(buf0, buf0, input_stride); // rect special code
}
row_txfm(buf0, buf0, cos_bit_row);
round_shift_16bit_w16_avx2(buf0, txfm_size_col, shift[0]);
for (int j = 0; j < txfm_size_col; ++j) {
buf0[j] = _mm256_mulhrs_epi16(buf0[j], scale0);
}
__m256i *buf1_cur = buf1 + (i << 4);
if (lr_flip) {
@ -1668,10 +1671,13 @@ static INLINE void lowbd_inv_txfm2d_add_no_identity_avx2(
}
}
}
const __m256i scale1 = _mm256_set1_epi16(1 << (15 + shift[1]));
for (int i = 0; i < buf_size_w_div16; i++) {
__m256i *buf1_cur = buf1 + i * txfm_size_row;
col_txfm(buf1_cur, buf1_cur, cos_bit_col);
round_shift_16bit_w16_avx2(buf1_cur, txfm_size_row, shift[1]);
for (int j = 0; j < txfm_size_row; ++j) {
buf1_cur[j] = _mm256_mulhrs_epi16(buf1_cur[j], scale1);
}
}
for (int i = 0; i < buf_size_w_div16; i++) {
lowbd_write_buffer_16xn_avx2(buf1 + i * txfm_size_row, output + 16 * i,

View file

@ -2820,8 +2820,22 @@ static void lowbd_inv_txfm2d_add_4x16_ssse3(const int32_t *input,
load_buffer_32bit_to_16bit_w4(input_cur, txfm_size_col, buf_cur,
row_one_loop);
transpose_16bit_4x8(buf_cur, buf_cur);
row_txfm(buf_cur, buf_cur, cos_bit_row);
round_shift_16bit_ssse3(buf_cur, row_one_loop, shift[0]);
if (row_txfm == iidentity4_new_ssse3) {
const __m128i scale = pair_set_epi16(NewSqrt2, 3 << (NewSqrt2Bits - 1));
const __m128i ones = _mm_set1_epi16(1);
for (int j = 0; j < 4; ++j) {
const __m128i buf_lo = _mm_unpacklo_epi16(buf_cur[j], ones);
const __m128i buf_hi = _mm_unpackhi_epi16(buf_cur[j], ones);
const __m128i buf_32_lo =
_mm_srai_epi32(_mm_madd_epi16(buf_lo, scale), (NewSqrt2Bits + 1));
const __m128i buf_32_hi =
_mm_srai_epi32(_mm_madd_epi16(buf_hi, scale), (NewSqrt2Bits + 1));
buf_cur[j] = _mm_packs_epi32(buf_32_lo, buf_32_hi);
}
} else {
row_txfm(buf_cur, buf_cur, cos_bit_row);
round_shift_16bit_ssse3(buf_cur, row_one_loop, shift[0]);
}
if (lr_flip) {
__m128i temp[8];
flip_buf_sse2(buf_cur, temp, txfm_size_col);
@ -2867,8 +2881,22 @@ static void lowbd_inv_txfm2d_add_16x4_ssse3(const int32_t *input,
txfm_size_row);
transpose_16bit_8x4(buf_cur, buf_cur);
}
row_txfm(buf, buf, cos_bit_row);
round_shift_16bit_ssse3(buf, txfm_size_col, shift[0]);
if (row_txfm == iidentity16_new_ssse3) {
const __m128i scale = pair_set_epi16(2 * NewSqrt2, 3 << (NewSqrt2Bits - 1));
const __m128i ones = _mm_set1_epi16(1);
for (int j = 0; j < 16; ++j) {
const __m128i buf_lo = _mm_unpacklo_epi16(buf[j], ones);
const __m128i buf_hi = _mm_unpackhi_epi16(buf[j], ones);
const __m128i buf_32_lo =
_mm_srai_epi32(_mm_madd_epi16(buf_lo, scale), (NewSqrt2Bits + 1));
const __m128i buf_32_hi =
_mm_srai_epi32(_mm_madd_epi16(buf_hi, scale), (NewSqrt2Bits + 1));
buf[j] = _mm_packs_epi32(buf_32_lo, buf_32_hi);
}
} else {
row_txfm(buf, buf, cos_bit_row);
round_shift_16bit_ssse3(buf, txfm_size_col, shift[0]);
}
if (lr_flip) {
__m128i temp[16];
flip_buf_sse2(buf, temp, 16);
@ -2916,22 +2944,14 @@ void av1_lowbd_inv_txfm2d_add_ssse3(const int32_t *input, uint8_t *output,
break;
}
}
void av1_inv_txfm_add_ssse3(const tran_low_t *dqcoeff, uint8_t *dst, int stride,
const TxfmParam *txfm_param) {
const TX_TYPE tx_type = txfm_param->tx_type;
if (!txfm_param->lossless) {
switch (txfm_param->tx_size) {
case TX_4X16:
case TX_16X4:
// TODO(http://crbug.com/aomedia/2350): the ssse3 versions cause test
// vector mismatches.
av1_inv_txfm_add_c(dqcoeff, dst, stride, txfm_param);
break;
default:
av1_lowbd_inv_txfm2d_add_ssse3(dqcoeff, dst, stride, tx_type,
txfm_param->tx_size, txfm_param->eob);
break;
}
const TX_TYPE tx_type = txfm_param->tx_type;
av1_lowbd_inv_txfm2d_add_ssse3(dqcoeff, dst, stride, tx_type,
txfm_param->tx_size, txfm_param->eob);
} else {
av1_inv_txfm_add_c(dqcoeff, dst, stride, txfm_param);
}

View file

@ -15,9 +15,9 @@
#include "av1/common/warped_motion.h"
static const uint8_t warp_highbd_arrange_bytes[16] = {
0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15
};
static const uint8_t warp_highbd_arrange_bytes[16] = { 0, 2, 4, 6, 8, 10,
12, 14, 1, 3, 5, 7,
9, 11, 13, 15 };
static const uint8_t highbd_shuffle_alpha0_mask0[16] = {
0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3
@ -25,12 +25,12 @@ static const uint8_t highbd_shuffle_alpha0_mask0[16] = {
static const uint8_t highbd_shuffle_alpha0_mask1[16] = {
4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7
};
static const uint8_t highbd_shuffle_alpha0_mask2[16] = {
8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11
};
static const uint8_t highbd_shuffle_alpha0_mask3[16] = {
12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15
};
static const uint8_t highbd_shuffle_alpha0_mask2[16] = { 8, 9, 10, 11, 8, 9,
10, 11, 8, 9, 10, 11,
8, 9, 10, 11 };
static const uint8_t highbd_shuffle_alpha0_mask3[16] = { 12, 13, 14, 15, 12, 13,
14, 15, 12, 13, 14, 15,
12, 13, 14, 15 };
static INLINE void highbd_prepare_horizontal_filter_coeff(int alpha, int sx,
__m128i *coeff) {

View file

@ -212,10 +212,10 @@ void av1_upsample_intra_edge_sse4_1(uint8_t *p, int sz) {
{ -1, 9, 9, -1, -1, 9, 9, -1, -1, 9, 9, -1, -1, 9, 9, -1 }
};
DECLARE_ALIGNED(16, static const int8_t, v_const[2][16]) = {
{ 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6 },
{ 4, 5, 6, 7, 5, 6, 7, 8, 6, 7, 8, 9, 7, 8, 9, 10 }
};
DECLARE_ALIGNED(
16, static const int8_t,
v_const[2][16]) = { { 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6 },
{ 4, 5, 6, 7, 5, 6, 7, 8, 6, 7, 8, 9, 7, 8, 9, 10 } };
// Extend first/last samples (upper-left p[-1], last p[sz-1])
// to support 4-tap filter

View file

@ -221,9 +221,9 @@ static const uint8_t shuffle_gamma0_mask1[16] = { 4, 5, 6, 7, 4, 5, 6, 7,
4, 5, 6, 7, 4, 5, 6, 7 };
static const uint8_t shuffle_gamma0_mask2[16] = { 8, 9, 10, 11, 8, 9, 10, 11,
8, 9, 10, 11, 8, 9, 10, 11 };
static const uint8_t shuffle_gamma0_mask3[16] = {
12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15
};
static const uint8_t shuffle_gamma0_mask3[16] = { 12, 13, 14, 15, 12, 13,
14, 15, 12, 13, 14, 15,
12, 13, 14, 15 };
static INLINE void filter_src_pixels(__m128i src, __m128i *tmp, __m128i *coeff,
const int offset_bits_horiz,

View file

@ -17,6 +17,7 @@
#include "av1/common/convolve.h"
#include "aom_dsp/aom_dsp_common.h"
#include "aom_dsp/aom_filter.h"
#include "aom_dsp/x86/convolve_avx2.h"
#include "aom_dsp/x86/synonyms.h"
#include "aom_dsp/x86/synonyms_avx2.h"
@ -25,6 +26,20 @@
// on the left.
// A row of, say, 8-bit pixels with values p0, p1, p2, ..., p30, p31 will be
// loaded and stored as [ p31 ... p17 p16 ][ p15 ... p1 p0 ].
// Exploiting the range of wiener filter coefficients,
// horizontal filtering can be done in 16 bit intermediate precision.
// The details are as follows :
// Consider the horizontal wiener filter coefficients of the following form :
// [C0, C1, C2, 2^(FILTER_BITS) -2 * (C0 + C1 + C2), C2, C1, C0]
// Subtracting 2^(FILTER_BITS) from the centre tap we get the following :
// [C0, C1, C2, -2 * (C0 + C1 + C2), C2, C1, C0]
// The sum of the product "C0 * p0 + C1 * p1 + C2 * p2 -2 * (C0 + C1 + C2) * p3
// + C2 * p4 + C1 * p5 + C0 * p6" would be in the range of signed 16 bit
// precision. Finally, after rounding the above result by round_0, we multiply
// the centre pixel by 2^(FILTER_BITS - round_0) and add it to get the
// horizontal filter output.
void av1_wiener_convolve_add_src_avx2(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x, int x_step_q4,
@ -37,224 +52,190 @@ void av1_wiener_convolve_add_src_avx2(const uint8_t *src, ptrdiff_t src_stride,
(void)x_step_q4;
(void)y_step_q4;
DECLARE_ALIGNED(32, uint16_t,
temp[(MAX_SB_SIZE + SUBPEL_TAPS - 1) * MAX_SB_SIZE]);
int intermediate_height = h + SUBPEL_TAPS - 2;
memset(temp + (intermediate_height * MAX_SB_SIZE), 0, MAX_SB_SIZE);
const int center_tap = ((SUBPEL_TAPS - 1) / 2);
DECLARE_ALIGNED(32, int16_t, im_block[(MAX_SB_SIZE + SUBPEL_TAPS) * 8]);
int im_h = h + SUBPEL_TAPS - 2;
int im_stride = 8;
memset(im_block + (im_h * im_stride), 0, MAX_SB_SIZE);
int i, j;
const int center_tap = (SUBPEL_TAPS - 1) / 2;
const uint8_t *const src_ptr = src - center_tap * src_stride - center_tap;
const __m128i zero_128 = _mm_setzero_si128();
const __m256i zero_256 = _mm256_setzero_si256();
__m256i filt[4], coeffs_h[4], coeffs_v[4], filt_center;
// Add an offset to account for the "add_src" part of the convolve function.
const __m128i offset = _mm_insert_epi16(zero_128, 1 << FILTER_BITS, 3);
assert(conv_params->round_0 > 0);
const __m256i clamp_low = zero_256;
filt[0] = _mm256_load_si256((__m256i const *)filt1_global_avx2);
filt[1] = _mm256_load_si256((__m256i const *)filt2_global_avx2);
filt[2] = _mm256_load_si256((__m256i const *)filt3_global_avx2);
filt[3] = _mm256_load_si256((__m256i const *)filt4_global_avx2);
filt_center = _mm256_load_si256((__m256i const *)filt_center_global_avx2);
const __m128i coeffs_x = _mm_loadu_si128((__m128i *)filter_x);
const __m256i filter_coeffs_x = _mm256_broadcastsi128_si256(coeffs_x);
// coeffs 0 1 0 1 0 1 0 1
coeffs_h[0] =
_mm256_shuffle_epi8(filter_coeffs_x, _mm256_set1_epi16(0x0200u));
// coeffs 2 3 2 3 2 3 2 3
coeffs_h[1] =
_mm256_shuffle_epi8(filter_coeffs_x, _mm256_set1_epi16(0x0604u));
// coeffs 4 5 4 5 4 5 4 5
coeffs_h[2] =
_mm256_shuffle_epi8(filter_coeffs_x, _mm256_set1_epi16(0x0a08u));
// coeffs 6 7 6 7 6 7 6 7
coeffs_h[3] =
_mm256_shuffle_epi8(filter_coeffs_x, _mm256_set1_epi16(0x0e0cu));
const __m256i round_const_h =
_mm256_set1_epi16((1 << (conv_params->round_0 - 1)));
const __m256i round_const_horz =
_mm256_set1_epi16((1 << (bd + FILTER_BITS - conv_params->round_0 - 1)));
const __m256i clamp_low = _mm256_setzero_si256();
const __m256i clamp_high =
_mm256_set1_epi16(WIENER_CLAMP_LIMIT(conv_params->round_0, bd) - 1);
const __m128i round_shift_h = _mm_cvtsi32_si128(conv_params->round_0);
/* Horizontal filter */
{
// coeffs [ f7 f6 f5 f4 f3 f2 f1 f0 ]
const __m128i coeffs_x = _mm_add_epi16(xx_loadu_128(filter_x), offset);
// Add an offset to account for the "add_src" part of the convolve function.
const __m128i zero_128 = _mm_setzero_si128();
const __m128i offset_0 = _mm_insert_epi16(zero_128, 1 << FILTER_BITS, 3);
const __m128i coeffs_y = _mm_add_epi16(xx_loadu_128(filter_y), offset_0);
// coeffs [ f3 f2 f3 f2 f1 f0 f1 f0 ]
const __m128i coeffs_0123 = _mm_unpacklo_epi32(coeffs_x, coeffs_x);
// coeffs [ f7 f6 f7 f6 f5 f4 f5 f4 ]
const __m128i coeffs_4567 = _mm_unpackhi_epi32(coeffs_x, coeffs_x);
const __m256i filter_coeffs_y = _mm256_broadcastsi128_si256(coeffs_y);
// coeffs [ f1 f0 f1 f0 f1 f0 f1 f0 ]
const __m128i coeffs_01_128 = _mm_unpacklo_epi64(coeffs_0123, coeffs_0123);
// coeffs [ f3 f2 f3 f2 f3 f2 f3 f2 ]
const __m128i coeffs_23_128 = _mm_unpackhi_epi64(coeffs_0123, coeffs_0123);
// coeffs [ f5 f4 f5 f4 f5 f4 f5 f4 ]
const __m128i coeffs_45_128 = _mm_unpacklo_epi64(coeffs_4567, coeffs_4567);
// coeffs [ f7 f6 f7 f6 f7 f6 f7 f6 ]
const __m128i coeffs_67_128 = _mm_unpackhi_epi64(coeffs_4567, coeffs_4567);
// coeffs 0 1 0 1 0 1 0 1
coeffs_v[0] = _mm256_shuffle_epi32(filter_coeffs_y, 0x00);
// coeffs 2 3 2 3 2 3 2 3
coeffs_v[1] = _mm256_shuffle_epi32(filter_coeffs_y, 0x55);
// coeffs 4 5 4 5 4 5 4 5
coeffs_v[2] = _mm256_shuffle_epi32(filter_coeffs_y, 0xaa);
// coeffs 6 7 6 7 6 7 6 7
coeffs_v[3] = _mm256_shuffle_epi32(filter_coeffs_y, 0xff);
// coeffs [ f1 f0 f1 f0 f1 f0 f1 f0 ][ f1 f0 f1 f0 f1 f0 f1 f0 ]
const __m256i coeffs_01 = yy_set_m128i(coeffs_01_128, coeffs_01_128);
// coeffs [ f3 f2 f3 f2 f3 f2 f3 f2 ][ f3 f2 f3 f2 f3 f2 f3 f2 ]
const __m256i coeffs_23 = yy_set_m128i(coeffs_23_128, coeffs_23_128);
// coeffs [ f5 f4 f5 f4 f5 f4 f5 f4 ][ f5 f4 f5 f4 f5 f4 f5 f4 ]
const __m256i coeffs_45 = yy_set_m128i(coeffs_45_128, coeffs_45_128);
// coeffs [ f7 f6 f7 f6 f7 f6 f7 f6 ][ f7 f6 f7 f6 f7 f6 f7 f6 ]
const __m256i coeffs_67 = yy_set_m128i(coeffs_67_128, coeffs_67_128);
const __m256i round_const_v =
_mm256_set1_epi32((1 << (conv_params->round_1 - 1)) -
(1 << (bd + conv_params->round_1 - 1)));
const __m128i round_shift_v = _mm_cvtsi32_si128(conv_params->round_1);
const __m256i round_const = _mm256_set1_epi32(
(1 << (conv_params->round_0 - 1)) + (1 << (bd + FILTER_BITS - 1)));
for (j = 0; j < w; j += 8) {
for (i = 0; i < im_h; i += 2) {
__m256i data = _mm256_castsi128_si256(
_mm_loadu_si128((__m128i *)&src_ptr[(i * src_stride) + j]));
for (int i = 0; i < intermediate_height; ++i) {
for (int j = 0; j < w; j += 16) {
const uint8_t *data_ij = src_ptr + i * src_stride + j;
// Load the next line
if (i + 1 < im_h)
data = _mm256_inserti128_si256(
data,
_mm_loadu_si128(
(__m128i *)&src_ptr[(i * src_stride) + j + src_stride]),
1);
// Load 8-bit src data
const __m128i data_0 = xx_loadu_128(data_ij + 0);
const __m128i data_1 = xx_loadu_128(data_ij + 1);
const __m128i data_2 = xx_loadu_128(data_ij + 2);
const __m128i data_3 = xx_loadu_128(data_ij + 3);
const __m128i data_4 = xx_loadu_128(data_ij + 4);
const __m128i data_5 = xx_loadu_128(data_ij + 5);
const __m128i data_6 = xx_loadu_128(data_ij + 6);
const __m128i data_7 = xx_loadu_128(data_ij + 7);
__m256i res = convolve_lowbd_x(data, coeffs_h, filt);
// (Zero-)Extend 8-bit data to 16-bit data
const __m256i src_0 = _mm256_cvtepu8_epi16(data_0);
const __m256i src_1 = _mm256_cvtepu8_epi16(data_1);
const __m256i src_2 = _mm256_cvtepu8_epi16(data_2);
const __m256i src_3 = _mm256_cvtepu8_epi16(data_3);
const __m256i src_4 = _mm256_cvtepu8_epi16(data_4);
const __m256i src_5 = _mm256_cvtepu8_epi16(data_5);
const __m256i src_6 = _mm256_cvtepu8_epi16(data_6);
const __m256i src_7 = _mm256_cvtepu8_epi16(data_7);
res =
_mm256_sra_epi16(_mm256_add_epi16(res, round_const_h), round_shift_h);
// Multiply src data by filter coeffs and sum pairs
const __m256i res_0 = _mm256_madd_epi16(src_0, coeffs_01);
const __m256i res_1 = _mm256_madd_epi16(src_1, coeffs_01);
const __m256i res_2 = _mm256_madd_epi16(src_2, coeffs_23);
const __m256i res_3 = _mm256_madd_epi16(src_3, coeffs_23);
const __m256i res_4 = _mm256_madd_epi16(src_4, coeffs_45);
const __m256i res_5 = _mm256_madd_epi16(src_5, coeffs_45);
const __m256i res_6 = _mm256_madd_epi16(src_6, coeffs_67);
const __m256i res_7 = _mm256_madd_epi16(src_7, coeffs_67);
__m256i data_0 = _mm256_shuffle_epi8(data, filt_center);
// Calculate scalar product for even- and odd-indices separately,
// increasing to 32-bit precision
const __m256i res_even_sum = _mm256_add_epi32(
_mm256_add_epi32(res_0, res_4), _mm256_add_epi32(res_2, res_6));
const __m256i res_odd_sum = _mm256_add_epi32(
_mm256_add_epi32(res_1, res_5), _mm256_add_epi32(res_3, res_7));
const __m256i res_even = _mm256_srai_epi32(
_mm256_add_epi32(res_even_sum, round_const), conv_params->round_0);
const __m256i res_odd = _mm256_srai_epi32(
_mm256_add_epi32(res_odd_sum, round_const), conv_params->round_0);
// Reduce to 16-bit precision and pack even- and odd-index results
// back into one register. The _mm256_packs_epi32 intrinsic returns
// a register with the pixels ordered as follows:
// [ 15 13 11 9 14 12 10 8 ] [ 7 5 3 1 6 4 2 0 ]
const __m256i res = _mm256_packs_epi32(res_even, res_odd);
const __m256i res_clamped =
_mm256_min_epi16(_mm256_max_epi16(res, clamp_low), clamp_high);
// Store in a temporary array
yy_storeu_256(temp + i * MAX_SB_SIZE + j, res_clamped);
}
// multiply the center pixel by 2^(FILTER_BITS - round_0) and add it to
// the result
data_0 = _mm256_slli_epi16(data_0, FILTER_BITS - conv_params->round_0);
res = _mm256_add_epi16(res, data_0);
res = _mm256_add_epi16(res, round_const_horz);
const __m256i res_clamped =
_mm256_min_epi16(_mm256_max_epi16(res, clamp_low), clamp_high);
_mm256_store_si256((__m256i *)&im_block[i * im_stride], res_clamped);
}
}
/* Vertical filter */
{
// coeffs [ g7 g6 g5 g4 g3 g2 g1 g0 ]
const __m128i coeffs_y = _mm_add_epi16(xx_loadu_128(filter_y), offset);
/* Vertical filter */
{
__m256i src_0 = _mm256_loadu_si256((__m256i *)(im_block + 0 * im_stride));
__m256i src_1 = _mm256_loadu_si256((__m256i *)(im_block + 1 * im_stride));
__m256i src_2 = _mm256_loadu_si256((__m256i *)(im_block + 2 * im_stride));
__m256i src_3 = _mm256_loadu_si256((__m256i *)(im_block + 3 * im_stride));
__m256i src_4 = _mm256_loadu_si256((__m256i *)(im_block + 4 * im_stride));
__m256i src_5 = _mm256_loadu_si256((__m256i *)(im_block + 5 * im_stride));
// coeffs [ g3 g2 g3 g2 g1 g0 g1 g0 ]
const __m128i coeffs_0123 = _mm_unpacklo_epi32(coeffs_y, coeffs_y);
// coeffs [ g7 g6 g7 g6 g5 g4 g5 g4 ]
const __m128i coeffs_4567 = _mm_unpackhi_epi32(coeffs_y, coeffs_y);
__m256i s[8];
s[0] = _mm256_unpacklo_epi16(src_0, src_1);
s[1] = _mm256_unpacklo_epi16(src_2, src_3);
s[2] = _mm256_unpacklo_epi16(src_4, src_5);
// coeffs [ g1 g0 g1 g0 g1 g0 g1 g0 ]
const __m128i coeffs_01_128 = _mm_unpacklo_epi64(coeffs_0123, coeffs_0123);
// coeffs [ g3 g2 g3 g2 g3 g2 g3 g2 ]
const __m128i coeffs_23_128 = _mm_unpackhi_epi64(coeffs_0123, coeffs_0123);
// coeffs [ g5 g4 g5 g4 g5 g4 g5 g4 ]
const __m128i coeffs_45_128 = _mm_unpacklo_epi64(coeffs_4567, coeffs_4567);
// coeffs [ g7 g6 g7 g6 g7 g6 g7 g6 ]
const __m128i coeffs_67_128 = _mm_unpackhi_epi64(coeffs_4567, coeffs_4567);
s[4] = _mm256_unpackhi_epi16(src_0, src_1);
s[5] = _mm256_unpackhi_epi16(src_2, src_3);
s[6] = _mm256_unpackhi_epi16(src_4, src_5);
// coeffs [ g1 g0 g1 g0 g1 g0 g1 g0 ][ g1 g0 g1 g0 g1 g0 g1 g0 ]
const __m256i coeffs_01 = yy_set_m128i(coeffs_01_128, coeffs_01_128);
// coeffs [ g3 g2 g3 g2 g3 g2 g3 g2 ][ g3 g2 g3 g2 g3 g2 g3 g2 ]
const __m256i coeffs_23 = yy_set_m128i(coeffs_23_128, coeffs_23_128);
// coeffs [ g5 g4 g5 g4 g5 g4 g5 g4 ][ g5 g4 g5 g4 g5 g4 g5 g4 ]
const __m256i coeffs_45 = yy_set_m128i(coeffs_45_128, coeffs_45_128);
// coeffs [ g7 g6 g7 g6 g7 g6 g7 g6 ][ g7 g6 g7 g6 g7 g6 g7 g6 ]
const __m256i coeffs_67 = yy_set_m128i(coeffs_67_128, coeffs_67_128);
for (i = 0; i < h - 1; i += 2) {
const int16_t *data = &im_block[i * im_stride];
const __m256i round_const =
_mm256_set1_epi32((1 << (conv_params->round_1 - 1)) -
(1 << (bd + conv_params->round_1 - 1)));
const __m256i s6 =
_mm256_loadu_si256((__m256i *)(data + 6 * im_stride));
const __m256i s7 =
_mm256_loadu_si256((__m256i *)(data + 7 * im_stride));
for (int i = 0; i < h; ++i) {
for (int j = 0; j < w; j += 16) {
const uint16_t *data_ij = temp + i * MAX_SB_SIZE + j;
s[3] = _mm256_unpacklo_epi16(s6, s7);
s[7] = _mm256_unpackhi_epi16(s6, s7);
// Load 16-bit data from the output of the horizontal filter in
// which the pixels are ordered as follows:
// [ 15 13 11 9 14 12 10 8 ] [ 7 5 3 1 6 4 2 0 ]
const __m256i data_0 = yy_loadu_256(data_ij + 0 * MAX_SB_SIZE);
const __m256i data_1 = yy_loadu_256(data_ij + 1 * MAX_SB_SIZE);
const __m256i data_2 = yy_loadu_256(data_ij + 2 * MAX_SB_SIZE);
const __m256i data_3 = yy_loadu_256(data_ij + 3 * MAX_SB_SIZE);
const __m256i data_4 = yy_loadu_256(data_ij + 4 * MAX_SB_SIZE);
const __m256i data_5 = yy_loadu_256(data_ij + 5 * MAX_SB_SIZE);
const __m256i data_6 = yy_loadu_256(data_ij + 6 * MAX_SB_SIZE);
const __m256i data_7 = yy_loadu_256(data_ij + 7 * MAX_SB_SIZE);
__m256i res_a = convolve(s, coeffs_v);
__m256i res_b = convolve(s + 4, coeffs_v);
// Filter the even-indices, increasing to 32-bit precision
const __m256i src_0 = _mm256_unpacklo_epi16(data_0, data_1);
const __m256i src_2 = _mm256_unpacklo_epi16(data_2, data_3);
const __m256i src_4 = _mm256_unpacklo_epi16(data_4, data_5);
const __m256i src_6 = _mm256_unpacklo_epi16(data_6, data_7);
const __m256i res_a_round = _mm256_sra_epi32(
_mm256_add_epi32(res_a, round_const_v), round_shift_v);
const __m256i res_b_round = _mm256_sra_epi32(
_mm256_add_epi32(res_b, round_const_v), round_shift_v);
const __m256i res_0 = _mm256_madd_epi16(src_0, coeffs_01);
const __m256i res_2 = _mm256_madd_epi16(src_2, coeffs_23);
const __m256i res_4 = _mm256_madd_epi16(src_4, coeffs_45);
const __m256i res_6 = _mm256_madd_epi16(src_6, coeffs_67);
/* rounding code */
// 16 bit conversion
const __m256i res_16bit = _mm256_packs_epi32(res_a_round, res_b_round);
// 8 bit conversion and saturation to uint8
const __m256i res_8b = _mm256_packus_epi16(res_16bit, res_16bit);
const __m256i res_even = _mm256_add_epi32(
_mm256_add_epi32(res_0, res_2), _mm256_add_epi32(res_4, res_6));
const __m128i res_0 = _mm256_castsi256_si128(res_8b);
const __m128i res_1 = _mm256_extracti128_si256(res_8b, 1);
// Filter the odd-indices, increasing to 32-bit precision
const __m256i src_1 = _mm256_unpackhi_epi16(data_0, data_1);
const __m256i src_3 = _mm256_unpackhi_epi16(data_2, data_3);
const __m256i src_5 = _mm256_unpackhi_epi16(data_4, data_5);
const __m256i src_7 = _mm256_unpackhi_epi16(data_6, data_7);
// Store values into the destination buffer
__m128i *const p_0 = (__m128i *)&dst[i * dst_stride + j];
__m128i *const p_1 = (__m128i *)&dst[i * dst_stride + j + dst_stride];
const __m256i res_1 = _mm256_madd_epi16(src_1, coeffs_01);
const __m256i res_3 = _mm256_madd_epi16(src_3, coeffs_23);
const __m256i res_5 = _mm256_madd_epi16(src_5, coeffs_45);
const __m256i res_7 = _mm256_madd_epi16(src_7, coeffs_67);
_mm_storel_epi64(p_0, res_0);
_mm_storel_epi64(p_1, res_1);
const __m256i res_odd = _mm256_add_epi32(
_mm256_add_epi32(res_1, res_3), _mm256_add_epi32(res_5, res_7));
s[0] = s[1];
s[1] = s[2];
s[2] = s[3];
// Pixels are currently in the following order:
// res_even order: [ 14 12 10 8 ] [ 6 4 2 0 ]
// res_odd order: [ 15 13 11 9 ] [ 7 5 3 1 ]
//
// Rearrange the pixels into the following order:
// res_lo order: [ 11 10 9 8 ] [ 3 2 1 0 ]
// res_hi order: [ 15 14 13 12 ] [ 7 6 5 4 ]
const __m256i res_lo = _mm256_unpacklo_epi32(res_even, res_odd);
const __m256i res_hi = _mm256_unpackhi_epi32(res_even, res_odd);
s[4] = s[5];
s[5] = s[6];
s[6] = s[7];
}
if (h - i) {
s[0] = _mm256_permute2x128_si256(s[0], s[4], 0x20);
s[1] = _mm256_permute2x128_si256(s[1], s[5], 0x20);
s[2] = _mm256_permute2x128_si256(s[2], s[6], 0x20);
const __m256i res_lo_round = _mm256_srai_epi32(
_mm256_add_epi32(res_lo, round_const), conv_params->round_1);
const __m256i res_hi_round = _mm256_srai_epi32(
_mm256_add_epi32(res_hi, round_const), conv_params->round_1);
const int16_t *data = &im_block[i * im_stride];
const __m128i s6_ = _mm_loadu_si128((__m128i *)(data + 6 * im_stride));
const __m128i s7_ = _mm_loadu_si128((__m128i *)(data + 7 * im_stride));
// Reduce to 16-bit precision and pack into the correct order:
// [ 15 14 13 12 11 10 9 8 ][ 7 6 5 4 3 2 1 0 ]
const __m256i res_16bit =
_mm256_packs_epi32(res_lo_round, res_hi_round);
__m128i s3 = _mm_unpacklo_epi16(s6_, s7_);
__m128i s7 = _mm_unpackhi_epi16(s6_, s7_);
// Reduce to 8-bit precision. This messes up the order:
// [ - - - - - - - - 15 14 13 12 11 10 9 8 ]
// [ - - - - - - - - 7 6 5 4 3 2 1 0 ]
const __m256i res_8bit =
_mm256_packus_epi16(res_16bit, zero_256 /* don't care value */);
s[3] = _mm256_inserti128_si256(_mm256_castsi128_si256(s3), s7, 1);
__m256i convolveres = convolve(s, coeffs_v);
// Swap the two central 32-bit values to get the order:
// [ - - - - - - - - - - - - - - - - ]
// [ 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 ]
const __m256i res_8bit2 = _mm256_permute4x64_epi64(res_8bit, 0xd8);
const __m256i res_round = _mm256_sra_epi32(
_mm256_add_epi32(convolveres, round_const_v), round_shift_v);
// Store the lower 128-bit lane in the dst array
xx_storeu_128(dst + i * dst_stride + j,
_mm256_castsi256_si128(res_8bit2));
/* rounding code */
// 16 bit conversion
__m128i reslo = _mm256_castsi256_si128(res_round);
__m128i reshi = _mm256_extracti128_si256(res_round, 1);
const __m128i res_16bit = _mm_packus_epi32(reslo, reshi);
// 8 bit conversion and saturation to uint8
const __m128i res_8b = _mm_packus_epi16(res_16bit, res_16bit);
__m128i *const p_0 = (__m128i *)&dst[i * dst_stride + j];
_mm_storel_epi64(p_0, res_8b);
}
}
}

View file

@ -1734,6 +1734,7 @@ static PARTITION_TYPE read_partition(MACROBLOCKD *xd, int mi_row, int mi_col,
static void decode_partition(AV1Decoder *const pbi, ThreadData *const td,
int mi_row, int mi_col, aom_reader *reader,
BLOCK_SIZE bsize, int parse_decode_flag) {
assert(bsize < BLOCK_SIZES_ALL);
AV1_COMMON *const cm = &pbi->common;
MACROBLOCKD *const xd = &td->xd;
const int bw = mi_size_wide[bsize];
@ -1751,9 +1752,9 @@ static void decode_partition(AV1Decoder *const pbi, ThreadData *const td,
// 01 - do parse only
// 10 - do decode only
// 11 - do parse and decode
static const block_visitor_fn_t block_visit[4] = {
NULL, parse_decode_block, decode_block, parse_decode_block
};
static const block_visitor_fn_t block_visit[4] = { NULL, parse_decode_block,
decode_block,
parse_decode_block };
if (parse_decode_flag & 1) {
const int num_planes = av1_num_planes(cm);
@ -1778,7 +1779,11 @@ static void decode_partition(AV1Decoder *const pbi, ThreadData *const td,
partition = get_partition(cm, mi_row, mi_col, bsize);
}
subsize = get_partition_subsize(bsize, partition);
if (subsize == BLOCK_INVALID) {
aom_internal_error(xd->error_info, AOM_CODEC_CORRUPT_FRAME,
"Partition is invalid for block size %dx%d",
block_size_wide[bsize], block_size_high[bsize]);
}
// Check the bitstream is conformant: if there is subsampling on the
// chroma planes, subsize must subsample to a valid block size.
const struct macroblockd_plane *const pd_u = &xd->plane[1];

View file

@ -183,7 +183,7 @@ static void read_drl_idx(FRAME_CONTEXT *ec_ctx, MACROBLOCKD *xd,
if (mbmi->mode == NEWMV || mbmi->mode == NEW_NEWMV) {
for (int idx = 0; idx < 2; ++idx) {
if (xd->ref_mv_count[ref_frame_type] > idx + 1) {
uint8_t drl_ctx = av1_drl_ctx(xd->ref_mv_stack[ref_frame_type], idx);
uint8_t drl_ctx = av1_drl_ctx(xd->weight[ref_frame_type], idx);
int drl_idx = aom_read_symbol(r, ec_ctx->drl_cdf[drl_ctx], 2, ACCT_STR);
mbmi->ref_mv_idx = idx + drl_idx;
if (!drl_idx) return;
@ -196,7 +196,7 @@ static void read_drl_idx(FRAME_CONTEXT *ec_ctx, MACROBLOCKD *xd,
// mode is factored in.
for (int idx = 1; idx < 3; ++idx) {
if (xd->ref_mv_count[ref_frame_type] > idx + 1) {
uint8_t drl_ctx = av1_drl_ctx(xd->ref_mv_stack[ref_frame_type], idx);
uint8_t drl_ctx = av1_drl_ctx(xd->weight[ref_frame_type], idx);
int drl_idx = aom_read_symbol(r, ec_ctx->drl_cdf[drl_ctx], 2, ACCT_STR);
mbmi->ref_mv_idx = idx + drl_idx - 1;
if (!drl_idx) return;
@ -680,8 +680,8 @@ static void read_intrabc_info(AV1_COMMON *const cm, MACROBLOCKD *const xd,
int_mv ref_mvs[INTRA_FRAME + 1][MAX_MV_REF_CANDIDATES];
av1_find_mv_refs(cm, xd, mbmi, INTRA_FRAME, xd->ref_mv_count,
xd->ref_mv_stack, ref_mvs, /*global_mvs=*/NULL, mi_row,
mi_col, inter_mode_ctx);
xd->ref_mv_stack, xd->weight, ref_mvs, /*global_mvs=*/NULL,
mi_row, mi_col, inter_mode_ctx);
int_mv nearestmv, nearmv;
@ -1271,7 +1271,7 @@ static void read_inter_block_mode_info(AV1Decoder *const pbi,
MV_REFERENCE_FRAME ref_frame = av1_ref_frame_type(mbmi->ref_frame);
av1_find_mv_refs(cm, xd, mbmi, ref_frame, xd->ref_mv_count, xd->ref_mv_stack,
ref_mvs, /*global_mvs=*/NULL, mi_row, mi_col,
xd->weight, ref_mvs, /*global_mvs=*/NULL, mi_row, mi_col,
inter_mode_ctx);
int mode_ctx = av1_mode_context_analyzer(inter_mode_ctx, mbmi->ref_frame);

View file

@ -336,6 +336,7 @@ void av1_read_coeffs_txb_facade(const AV1_COMMON *const cm,
struct macroblockd_plane *const pd = &xd->plane[plane];
const BLOCK_SIZE bsize = mbmi->sb_type;
assert(bsize < BLOCK_SIZES_ALL);
const BLOCK_SIZE plane_bsize =
get_plane_block_size(bsize, pd->subsampling_x, pd->subsampling_y);

View file

@ -25,25 +25,6 @@
#include "av1/decoder/decodeframe.h"
#include "av1/decoder/obu.h"
// Picture prediction structures (0-12 are predefined) in scalability metadata.
enum {
SCALABILITY_L1T2 = 0,
SCALABILITY_L1T3 = 1,
SCALABILITY_L2T1 = 2,
SCALABILITY_L2T2 = 3,
SCALABILITY_L2T3 = 4,
SCALABILITY_S2T1 = 5,
SCALABILITY_S2T2 = 6,
SCALABILITY_S2T3 = 7,
SCALABILITY_L2T1h = 8,
SCALABILITY_L2T2h = 9,
SCALABILITY_L2T3h = 10,
SCALABILITY_S2T1h = 11,
SCALABILITY_S2T2h = 12,
SCALABILITY_S2T3h = 13,
SCALABILITY_SS = 14
} UENUM1BYTE(SCALABILITY_STRUCTURES);
aom_codec_err_t aom_get_num_layers_from_operating_point_idc(
int operating_point_idc, unsigned int *number_spatial_layers,
unsigned int *number_temporal_layers) {

View file

@ -180,12 +180,12 @@ int av1_block_wavelet_energy_level(const AV1_COMP *cpi, MACROBLOCK *x,
return clamp((int)round(energy), ENERGY_MIN, ENERGY_MAX);
}
int av1_compute_deltaq_from_energy_level(const AV1_COMP *const cpi,
int block_var_level) {
int av1_compute_q_from_energy_level_deltaq_mode(const AV1_COMP *const cpi,
int block_var_level) {
int rate_level;
const AV1_COMMON *const cm = &cpi->common;
if (DELTAQ_MODULATION == 1) {
if (DELTA_Q_PERCEPTUAL_MODULATION == 1) {
ENERGY_IN_BOUNDS(block_var_level);
rate_level = SEGMENT_ID(block_var_level);
} else {
@ -198,5 +198,5 @@ int av1_compute_deltaq_from_energy_level(const AV1_COMP *const cpi,
if ((cm->base_qindex != 0) && ((cm->base_qindex + qindex_delta) == 0)) {
qindex_delta = -cm->base_qindex + 1;
}
return qindex_delta;
return cm->base_qindex + qindex_delta;
}

View file

@ -21,8 +21,8 @@ extern "C" {
void av1_vaq_frame_setup(AV1_COMP *cpi);
int av1_log_block_var(const AV1_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bs);
int av1_compute_deltaq_from_energy_level(const AV1_COMP *const cpi,
int block_var_level);
int av1_compute_q_from_energy_level_deltaq_mode(const AV1_COMP *const cpi,
int block_var_level);
int av1_block_wavelet_energy_level(const AV1_COMP *cpi, MACROBLOCK *x,
BLOCK_SIZE bs);

View file

@ -288,7 +288,7 @@ void av1_quantize_b_facade(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
eob_ptr, sc->scan, sc->iscan);
break;
case 2:
aom_quantize_b_64x64_adaptive_c(
aom_quantize_b_64x64_adaptive(
coeff_ptr, n_coeffs, p->zbin_QTX, p->round_QTX, p->quant_QTX,
p->quant_shift_QTX, qcoeff_ptr, dqcoeff_ptr, p->dequant_QTX,
eob_ptr, sc->scan, sc->iscan);

View file

@ -106,8 +106,7 @@ static void write_drl_idx(FRAME_CONTEXT *ec_ctx, const MB_MODE_INFO *mbmi,
int idx;
for (idx = 0; idx < 2; ++idx) {
if (mbmi_ext->ref_mv_count[ref_frame_type] > idx + 1) {
uint8_t drl_ctx =
av1_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], idx);
uint8_t drl_ctx = av1_drl_ctx(mbmi_ext->weight[ref_frame_type], idx);
aom_write_symbol(w, mbmi->ref_mv_idx != idx, ec_ctx->drl_cdf[drl_ctx],
2);
@ -122,8 +121,7 @@ static void write_drl_idx(FRAME_CONTEXT *ec_ctx, const MB_MODE_INFO *mbmi,
// TODO(jingning): Temporary solution to compensate the NEARESTMV offset.
for (idx = 1; idx < 3; ++idx) {
if (mbmi_ext->ref_mv_count[ref_frame_type] > idx + 1) {
uint8_t drl_ctx =
av1_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], idx);
uint8_t drl_ctx = av1_drl_ctx(mbmi_ext->weight[ref_frame_type], idx);
aom_write_symbol(w, mbmi->ref_mv_idx != (idx - 1),
ec_ctx->drl_cdf[drl_ctx], 2);
if (mbmi->ref_mv_idx == (idx - 1)) return;
@ -369,16 +367,16 @@ static void pack_txb_tokens(aom_writer *w, AV1_COMMON *cm, MACROBLOCK *const x,
blk_col)];
if (tx_size == plane_tx_size || plane) {
const CB_COEFF_BUFFER *cb_coef_buff = x->cb_coef_buff;
const int txb_offset =
x->mbmi_ext->cb_offset / (TX_SIZE_W_MIN * TX_SIZE_H_MIN);
tran_low_t *tcoeff_txb =
x->mbmi_ext->cb_coef_buff->tcoeff[plane] + x->mbmi_ext->cb_offset;
uint16_t *eob_txb = x->mbmi_ext->cb_coef_buff->eobs[plane] + txb_offset;
uint8_t *txb_skip_ctx_txb =
x->mbmi_ext->cb_coef_buff->txb_skip_ctx[plane] + txb_offset;
int *dc_sign_ctx_txb =
x->mbmi_ext->cb_coef_buff->dc_sign_ctx[plane] + txb_offset;
tran_low_t *tcoeff = BLOCK_OFFSET(tcoeff_txb, block);
const tran_low_t *tcoeff_txb =
cb_coef_buff->tcoeff[plane] + x->mbmi_ext->cb_offset;
const uint16_t *eob_txb = cb_coef_buff->eobs[plane] + txb_offset;
const uint8_t *txb_skip_ctx_txb =
cb_coef_buff->txb_skip_ctx[plane] + txb_offset;
const int *dc_sign_ctx_txb = cb_coef_buff->dc_sign_ctx[plane] + txb_offset;
const tran_low_t *tcoeff = BLOCK_OFFSET(tcoeff_txb, block);
const uint16_t eob = eob_txb[block];
TXB_CTX txb_ctx = { txb_skip_ctx_txb[block], dc_sign_ctx_txb[block] };
av1_write_coeffs_txb(cm, xd, w, blk_row, blk_col, plane, tx_size, tcoeff,
@ -1373,6 +1371,7 @@ static void write_inter_txb_coeff(AV1_COMMON *const cm, MACROBLOCK *const x,
MACROBLOCKD *const xd = &x->e_mbd;
const struct macroblockd_plane *const pd = &xd->plane[plane];
const BLOCK_SIZE bsize = mbmi->sb_type;
assert(bsize < BLOCK_SIZES_ALL);
const BLOCK_SIZE bsizec =
scale_chroma_bsize(bsize, pd->subsampling_x, pd->subsampling_y);
@ -1392,6 +1391,7 @@ static void write_inter_txb_coeff(AV1_COMMON *const cm, MACROBLOCK *const x,
int blk_row, blk_col;
assert(plane_bsize < BLOCK_SIZES_ALL);
const int num_4x4_w = block_size_wide[plane_bsize] >> tx_size_wide_log2[0];
const int num_4x4_h = block_size_high[plane_bsize] >> tx_size_high_log2[0];
@ -1498,9 +1498,9 @@ static void write_modes_b(AV1_COMP *cpi, const TileInfo *const tile,
int mi_col) {
write_mbmi_b(cpi, tile, w, mi_row, mi_col);
AV1_COMMON *cm = &cpi->common;
const AV1_COMMON *cm = &cpi->common;
MACROBLOCKD *xd = &cpi->td.mb.e_mbd;
MB_MODE_INFO *mbmi = xd->mi[0];
const MB_MODE_INFO *mbmi = xd->mi[0];
for (int plane = 0; plane < AOMMIN(2, av1_num_planes(cm)); ++plane) {
const uint8_t palette_size_plane =
mbmi->palette_mode_info.palette_size[plane];
@ -1516,10 +1516,10 @@ static void write_modes_b(AV1_COMP *cpi, const TileInfo *const tile,
}
}
BLOCK_SIZE bsize = mbmi->sb_type;
int is_inter_tx = is_inter_block(mbmi) || is_intrabc_block(mbmi);
int skip = mbmi->skip;
int segment_id = mbmi->segment_id;
const BLOCK_SIZE bsize = mbmi->sb_type;
const int is_inter_tx = is_inter_block(mbmi);
const int skip = mbmi->skip;
const int segment_id = mbmi->segment_id;
if (cm->tx_mode == TX_MODE_SELECT && block_signals_txsize(bsize) &&
!(is_inter_tx && skip) && !xd->lossless[segment_id]) {
if (is_inter_tx) { // This implies skip flag is 0.
@ -1528,17 +1528,17 @@ static void write_modes_b(AV1_COMP *cpi, const TileInfo *const tile,
const int txbw = tx_size_wide_unit[max_tx_size];
const int width = block_size_wide[bsize] >> tx_size_wide_log2[0];
const int height = block_size_high[bsize] >> tx_size_high_log2[0];
int idx, idy;
for (idy = 0; idy < height; idy += txbh)
for (idx = 0; idx < width; idx += txbw)
for (int idy = 0; idy < height; idy += txbh) {
for (int idx = 0; idx < width; idx += txbw) {
write_tx_size_vartx(xd, mbmi, max_tx_size, 0, idy, idx, w);
}
}
} else {
write_selected_tx_size(xd, w);
set_txfm_ctxs(mbmi->tx_size, xd->n4_w, xd->n4_h, 0, xd);
}
} else {
set_txfm_ctxs(mbmi->tx_size, xd->n4_w, xd->n4_h,
skip && is_inter_block(mbmi), xd);
set_txfm_ctxs(mbmi->tx_size, xd->n4_w, xd->n4_h, skip && is_inter_tx, xd);
}
write_tokens_b(cpi, tile, w, tok, tok_end, mi_row, mi_col);
@ -1587,6 +1587,7 @@ static void write_modes_sb(AV1_COMP *const cpi, const TileInfo *const tile,
int mi_col, BLOCK_SIZE bsize) {
const AV1_COMMON *const cm = &cpi->common;
MACROBLOCKD *const xd = &cpi->td.mb.e_mbd;
assert(bsize < BLOCK_SIZES_ALL);
const int hbs = mi_size_wide[bsize] / 2;
const int quarter_step = mi_size_wide[bsize] / 4;
int i;
@ -1711,6 +1712,7 @@ static void write_modes(AV1_COMP *const cpi, const TileInfo *const tile,
for (mi_col = mi_col_start; mi_col < mi_col_end;
mi_col += cm->seq_params.mib_size) {
cpi->td.mb.cb_coef_buff = av1_get_cb_coeff_buffer(cpi, mi_row, mi_col);
write_modes_sb(cpi, tile, w, &tok, tok_end, mi_row, mi_col,
cm->seq_params.sb_size);
}

View file

@ -75,8 +75,8 @@ typedef struct {
typedef struct {
// TODO(angiebird): Reduce the buffer size according to sb_type
CB_COEFF_BUFFER *cb_coef_buff;
CANDIDATE_MV ref_mv_stack[MODE_CTX_REF_FRAMES][MAX_REF_MV_STACK_SIZE];
uint16_t weight[MODE_CTX_REF_FRAMES][MAX_REF_MV_STACK_SIZE];
int_mv global_mvs[REF_FRAMES];
int cb_offset;
int16_t mode_context[MODE_CTX_REF_FRAMES];
@ -433,6 +433,8 @@ struct macroblock {
// [Saved stat index]
COMP_RD_STATS comp_rd_stats[MAX_COMP_RD_STATS];
int comp_rd_stats_idx;
CB_COEFF_BUFFER *cb_coef_buff;
};
static INLINE int is_rect_tx_allowed_bsize(BLOCK_SIZE bsize) {

View file

@ -216,7 +216,6 @@ void av1_copy_tree_context(PICK_MODE_CONTEXT *dst_ctx,
dst_ctx->mbmi_ext = src_ctx->mbmi_ext;
dst_ctx->num_4x4_blk = src_ctx->num_4x4_blk;
dst_ctx->skip = src_ctx->skip;
dst_ctx->skippable = src_ctx->skippable;
dst_ctx->best_mode_index = src_ctx->best_mode_index;
@ -227,9 +226,7 @@ void av1_copy_tree_context(PICK_MODE_CONTEXT *dst_ctx,
dst_ctx->comp_pred_diff = src_ctx->comp_pred_diff;
dst_ctx->single_pred_diff = src_ctx->single_pred_diff;
dst_ctx->rate = src_ctx->rate;
dst_ctx->dist = src_ctx->dist;
dst_ctx->rdcost = src_ctx->rdcost;
dst_ctx->rd_stats = src_ctx->rd_stats;
dst_ctx->rd_mode_is_ready = src_ctx->rd_mode_is_ready;
memcpy(dst_ctx->pred_mv, src_ctx->pred_mv, sizeof(MV) * REF_FRAMES);

View file

@ -38,8 +38,6 @@ enum {
typedef struct {
MB_MODE_INFO mic;
MB_MODE_INFO_EXT mbmi_ext;
int64_t dist;
int64_t rdcost;
uint8_t *color_index_map[2];
uint8_t *blk_skip;
@ -50,7 +48,6 @@ typedef struct {
uint8_t *txb_entropy_ctx[MAX_MB_PLANE];
int num_4x4_blk;
int skip;
// For current partition, only if all Y, U, and V transform blocks'
// coefficients are quantized to 0, skippable is set to 1.
int skippable;
@ -59,9 +56,7 @@ typedef struct {
int comp_pred_diff;
int single_pred_diff;
// TODO(jingning) Use RD_COST struct here instead. This involves a boarder
// scope of refactoring.
int rate;
RD_STATS rd_stats;
int rd_mode_is_ready; // Flag to indicate whether rd pick mode decision has
// been made.
@ -99,7 +94,15 @@ typedef struct PC_TREE {
PC_TREE_STATS pc_tree_stats;
CB_TREE_SEARCH cb_search_range;
int index;
// Simple motion search_features
MV mv_ref_fulls[REF_FRAMES];
unsigned int sms_none_feat[2];
unsigned int sms_split_feat[8];
unsigned int sms_rect_feat[8];
int sms_none_valid;
int sms_split_valid;
int sms_rect_valid;
} PC_TREE;
void av1_setup_pc_tree(struct AV1Common *cm, struct ThreadData *td);

View file

@ -947,7 +947,8 @@ static int get_refresh_frame_flags(const AV1_COMP *const cpi,
int av1_encode_strategy(AV1_COMP *const cpi, size_t *const size,
uint8_t *const dest, unsigned int *frame_flags,
int64_t *const time_stamp, int64_t *const time_end,
const aom_rational_t *const timebase, int flush) {
const aom_rational64_t *const timestamp_ratio,
int flush) {
const AV1EncoderConfig *const oxcf = &cpi->oxcf;
AV1_COMMON *const cm = &cpi->common;
@ -1027,7 +1028,7 @@ int av1_encode_strategy(AV1_COMP *const cpi, size_t *const size,
cm->seq_params.film_grain_params_present;
}
// only one operating point supported now
const int64_t pts64 = ticks_to_timebase_units(timebase, *time_stamp);
const int64_t pts64 = ticks_to_timebase_units(timestamp_ratio, *time_stamp);
if (pts64 < 0 || pts64 > UINT32_MAX) return AOM_CODEC_ERROR;
cpi->common.frame_presentation_time = (uint32_t)pts64;
}

View file

@ -29,7 +29,8 @@ extern "C" {
int av1_encode_strategy(AV1_COMP *const cpi, size_t *const size,
uint8_t *const dest, unsigned int *frame_flags,
int64_t *const time_stamp, int64_t *const time_end,
const aom_rational_t *const timebase, int flush);
const aom_rational64_t *const timestamp_ratio,
int flush);
// Set individual buffer update flags based on frame reference type.
// force_refresh_all is used when we have a KEY_FRAME or S_FRAME. It forces all

File diff suppressed because it is too large Load diff

View file

@ -20,7 +20,9 @@
extern "C" {
#endif
#define DELTAQ_MODULATION 1 // 0: variance based, 1: wavelet AC energy based
#define DELTA_Q_PERCEPTUAL_MODULATION \
1 // 0: variance based
// 1: wavelet AC energy based
struct macroblock;
struct yv12_buffer_config;

View file

@ -86,6 +86,7 @@ void av1_subtract_txb(MACROBLOCK *x, int plane, BLOCK_SIZE plane_bsize,
void av1_subtract_plane(MACROBLOCK *x, BLOCK_SIZE bsize, int plane) {
struct macroblock_plane *const p = &x->plane[plane];
const struct macroblockd_plane *const pd = &x->e_mbd.plane[plane];
assert(bsize < BLOCK_SIZES_ALL);
const BLOCK_SIZE plane_bsize =
get_plane_block_size(bsize, pd->subsampling_x, pd->subsampling_y);
const int bw = block_size_wide[plane_bsize];
@ -478,10 +479,11 @@ void av1_encode_sb(const struct AV1_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bsize,
if (x->skip) return;
assert(bsize < BLOCK_SIZES_ALL);
for (plane = 0; plane < num_planes; ++plane) {
const int subsampling_x = xd->plane[plane].subsampling_x;
const int subsampling_y = xd->plane[plane].subsampling_y;
if (!is_chroma_reference(mi_row, mi_col, bsize, subsampling_x,
subsampling_y))
continue;
@ -493,6 +495,7 @@ void av1_encode_sb(const struct AV1_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bsize,
const struct macroblockd_plane *const pd = &xd->plane[plane];
const BLOCK_SIZE plane_bsize =
get_plane_block_size(bsizec, pd->subsampling_x, pd->subsampling_y);
assert(plane_bsize < BLOCK_SIZES_ALL);
const int mi_width = block_size_wide[plane_bsize] >> tx_size_wide_log2[0];
const int mi_height = block_size_high[plane_bsize] >> tx_size_high_log2[0];
const TX_SIZE max_tx_size = get_vartx_max_txsize(xd, plane_bsize, plane);
@ -638,6 +641,7 @@ void av1_encode_intra_block_plane(const struct AV1_COMP *cpi, MACROBLOCK *x,
const MACROBLOCKD *const xd = &x->e_mbd;
ENTROPY_CONTEXT ta[MAX_MIB_SIZE] = { 0 };
ENTROPY_CONTEXT tl[MAX_MIB_SIZE] = { 0 };
assert(bsize < BLOCK_SIZES_ALL);
struct encode_b_args arg = {
cpi, x, NULL, &(xd->mi[0]->skip), ta, tl, enable_optimize_b

View file

@ -330,15 +330,13 @@ static BLOCK_SIZE select_sb_size(const AV1_COMP *const cpi) {
#endif
// When superres / resize is on, 'cm->width / height' can change between
// calls, so we don't apply this heuristic there. Also, this heuristic gives
// compression gain for speed >= 2 only.
// Things break if superblock size changes per-frame which is why this
// heuristic is set based on configured speed rather than actual
// speed-features (which may change per-frame in future)
// calls, so we don't apply this heuristic there.
// Things break if superblock size changes between the first pass and second
// pass encoding, which is why this heuristic is not configured as a
// speed-feature.
if (cpi->oxcf.superres_mode == SUPERRES_NONE &&
cpi->oxcf.resize_mode == RESIZE_NONE && cpi->oxcf.speed >= 2) {
return (cm->width >= 480 && cm->height >= 360) ? BLOCK_128X128
: BLOCK_64X64;
cpi->oxcf.resize_mode == RESIZE_NONE && cpi->oxcf.speed >= 1) {
return AOMMIN(cm->width, cm->height) > 480 ? BLOCK_128X128 : BLOCK_64X64;
}
return BLOCK_128X128;
@ -357,10 +355,11 @@ static void setup_frame(AV1_COMP *cpi) {
av1_setup_past_independence(cm);
}
if (cm->current_frame.frame_type == KEY_FRAME && cm->show_frame) {
set_sb_size(&cm->seq_params, select_sb_size(cpi));
} else if (frame_is_sframe(cm)) {
set_sb_size(&cm->seq_params, select_sb_size(cpi));
if ((cm->current_frame.frame_type == KEY_FRAME && cm->show_frame) ||
frame_is_sframe(cm)) {
if (!cpi->seq_params_locked) {
set_sb_size(&cm->seq_params, select_sb_size(cpi));
}
} else {
const RefCntBuffer *const primary_ref_buf = get_primary_ref_frame_buf(cm);
if (primary_ref_buf == NULL) {
@ -2548,19 +2547,6 @@ void av1_change_config(struct AV1_COMP *cpi, const AV1EncoderConfig *oxcf) {
}
}
static void init_level_info(AV1LevelInfo *level_info) {
memset(level_info, 0, MAX_NUM_OPERATING_POINTS * sizeof(*level_info));
for (int i = 0; i < MAX_NUM_OPERATING_POINTS; ++i) {
AV1LevelSpec *const level_spec = &level_info[i].level_spec;
level_spec->level = SEQ_LEVEL_MAX;
AV1LevelStats *const level_stats = &level_info[i].level_stats;
level_stats->min_cropped_tile_width = INT_MAX;
level_stats->min_cropped_tile_height = INT_MAX;
level_stats->tile_width_is_valid = 1;
level_stats->min_cr = 1e8;
}
}
AV1_COMP *av1_create_compressor(AV1EncoderConfig *oxcf,
BufferPool *const pool) {
unsigned int i;
@ -2622,7 +2608,7 @@ AV1_COMP *av1_create_compressor(AV1EncoderConfig *oxcf,
cpi->refresh_alt_ref_frame = 0;
init_level_info(cpi->level_info);
av1_init_level_info(cpi->level_info);
cpi->b_calculate_psnr = CONFIG_INTERNAL_STATS;
#if CONFIG_INTERNAL_STATS
@ -3522,7 +3508,7 @@ static void set_screen_content_options(AV1_COMP *cpi) {
// IntraBC would force loop filters off, so we use more strict rules that also
// requires that the block has high variance.
cm->allow_intrabc = cm->allow_screen_content_tools &&
counts_2 * blk_h * blk_w * 15 > width * height;
counts_2 * blk_h * blk_w * 12 > width * height;
}
static void set_size_independent_vars(AV1_COMP *cpi) {
@ -3568,18 +3554,30 @@ static void set_size_dependent_vars(AV1_COMP *cpi, int *q, int *bottom_index,
}
static void init_motion_estimation(AV1_COMP *cpi) {
int y_stride = cpi->scaled_source.y_stride;
int y_stride_src = (cpi->oxcf.resize_mode || cpi->oxcf.superres_mode)
? y_stride
: cpi->lookahead->buf->img.y_stride;
const int y_stride = cpi->scaled_source.y_stride;
const int y_stride_src = (cpi->oxcf.resize_mode || cpi->oxcf.superres_mode)
? y_stride
: cpi->lookahead->buf->img.y_stride;
// Update if ss_cfg is uninitialized or the current frame has a new stride
const int should_update = !cpi->ss_cfg[SS_CFG_SRC].stride ||
!cpi->ss_cfg[SS_CFG_LOOKAHEAD].stride ||
(y_stride != cpi->ss_cfg[SS_CFG_SRC].stride);
if (cpi->sf.mv.search_method == NSTEP) {
av1_init3smotion_compensation(&cpi->ss_cfg[SS_CFG_SRC], y_stride);
av1_init3smotion_compensation(&cpi->ss_cfg[SS_CFG_LOOKAHEAD], y_stride_src);
} else if (cpi->sf.mv.search_method == DIAMOND) {
if (!should_update) {
return;
}
if (cpi->sf.mv.search_method == DIAMOND) {
av1_init_dsmotion_compensation(&cpi->ss_cfg[SS_CFG_SRC], y_stride);
av1_init_dsmotion_compensation(&cpi->ss_cfg[SS_CFG_LOOKAHEAD],
y_stride_src);
} else {
// Update the offsets in search_sites as y_stride can change due to scaled
// references. This update allows NSTEP to be used on scaled references as
// long as sf.mv.search_method is not DIAMOND. Currently in the codebae,
// sf.mv.search_method is never set to DIAMOND.
av1_init3smotion_compensation(&cpi->ss_cfg[SS_CFG_SRC], y_stride);
av1_init3smotion_compensation(&cpi->ss_cfg[SS_CFG_LOOKAHEAD], y_stride_src);
}
}
@ -3838,8 +3836,9 @@ static uint8_t calculate_next_superres_scale(AV1_COMP *cpi) {
if (cpi->common.allow_screen_content_tools) break;
// Don't use for inter frames.
if (!frame_is_intra_only(&cpi->common)) break;
// Don't use for keyframes that can be used as references.
if (cpi->rc.frames_to_key != 1) break;
// Don't use for keyframes that can be used as references, except when
// using AOM_Q mode.
if (cpi->rc.frames_to_key != 1 && cpi->oxcf.rc_mode != AOM_Q) break;
// Now decide the use of superres based on 'q'.
int bottom_index, top_index;
@ -5422,7 +5421,7 @@ static void compute_internal_stats(AV1_COMP *cpi, int frame_bytes) {
int av1_get_compressed_data(AV1_COMP *cpi, unsigned int *frame_flags,
size_t *size, uint8_t *dest, int64_t *time_stamp,
int64_t *time_end, int flush,
const aom_rational_t *timebase) {
const aom_rational64_t *timestamp_ratio) {
const AV1EncoderConfig *const oxcf = &cpi->oxcf;
AV1_COMMON *const cm = &cpi->common;
@ -5458,8 +5457,9 @@ int av1_get_compressed_data(AV1_COMP *cpi, unsigned int *frame_flags,
if (assign_cur_frame_new_fb(cm) == NULL) return AOM_CODEC_ERROR;
const int result = av1_encode_strategy(cpi, size, dest, frame_flags,
time_stamp, time_end, timebase, flush);
const int result =
av1_encode_strategy(cpi, size, dest, frame_flags, time_stamp, time_end,
timestamp_ratio, flush);
if (result != AOM_CODEC_OK && result != -1) {
return AOM_CODEC_ERROR;
} else if (result == -1) {
@ -5469,14 +5469,20 @@ int av1_get_compressed_data(AV1_COMP *cpi, unsigned int *frame_flags,
#if CONFIG_INTERNAL_STATS
aom_usec_timer_mark(&cmptimer);
cpi->time_compress_data += aom_usec_timer_elapsed(&cmptimer);
#endif
#endif // CONFIG_INTERNAL_STATS
if (cpi->b_calculate_psnr) {
if (cm->show_existing_frame || (oxcf->pass != 1 && cm->show_frame)) {
generate_psnr_packet(cpi);
}
}
if (cpi->keep_level_stats && oxcf->pass != 1)
if (cpi->keep_level_stats && oxcf->pass != 1) {
// Initialize level info. at the beginning of each sequence.
if (cm->current_frame.frame_type == KEY_FRAME && cm->show_frame) {
av1_init_level_info(cpi->level_info);
}
av1_update_level_info(cpi, *size, *time_stamp, *time_end);
}
#if CONFIG_INTERNAL_STATS
if (oxcf->pass != 1) {

View file

@ -56,6 +56,13 @@
extern "C" {
#endif
// Rational number with an int64 numerator
// This structure holds a fractional value
typedef struct aom_rational64 {
int64_t num; // fraction numerator
int den; // fraction denominator
} aom_rational64_t; // alias for struct aom_rational
typedef struct {
int nmv_vec_cost[MV_JOINTS];
int nmv_costs[2][MV_VALS];
@ -110,9 +117,9 @@ enum {
} UENUM1BYTE(AQ_MODE);
enum {
NO_DELTA_Q = 0,
DELTA_Q_ONLY = 1,
DELTA_Q_LF = 2,
DELTAQ_MODE_COUNT // This should always be the last member of the enum
DELTA_Q_OBJECTIVE = 1, // Modulation to improve objective quality
DELTA_Q_PERCEPTUAL = 2, // Modulation to improve perceptual quality
DELTA_Q_MODE_COUNT // This should always be the last member of the enum
} UENUM1BYTE(DELTAQ_MODE);
enum {
@ -237,6 +244,7 @@ typedef struct AV1EncoderConfig {
int cq_level;
AQ_MODE aq_mode; // Adaptive Quantization mode
DELTAQ_MODE deltaq_mode;
int deltalf_mode;
int enable_cdef;
int enable_restoration;
int enable_obmc;
@ -1060,7 +1068,7 @@ int av1_receive_raw_frame(AV1_COMP *cpi, aom_enc_frame_flags_t frame_flags,
int av1_get_compressed_data(AV1_COMP *cpi, unsigned int *frame_flags,
size_t *size, uint8_t *dest, int64_t *time_stamp,
int64_t *time_end, int flush,
const aom_rational_t *timebase);
const aom_rational64_t *timebase);
int av1_encode(AV1_COMP *const cpi, uint8_t *const dest,
const EncodeFrameInput *const frame_input,
@ -1099,15 +1107,16 @@ int av1_convert_sect5obus_to_annexb(uint8_t *buffer, size_t *input_size);
// av1 uses 10,000,000 ticks/second as time stamp
#define TICKS_PER_SEC 10000000LL
static INLINE int64_t timebase_units_to_ticks(const aom_rational_t *timebase,
int64_t n) {
return n * TICKS_PER_SEC * timebase->num / timebase->den;
static INLINE int64_t
timebase_units_to_ticks(const aom_rational64_t *timestamp_ratio, int64_t n) {
return n * timestamp_ratio->num / timestamp_ratio->den;
}
static INLINE int64_t ticks_to_timebase_units(const aom_rational_t *timebase,
int64_t n) {
const int64_t round = TICKS_PER_SEC * timebase->num / 2 - 1;
return (n * timebase->den + round) / timebase->num / TICKS_PER_SEC;
static INLINE int64_t
ticks_to_timebase_units(const aom_rational64_t *timestamp_ratio, int64_t n) {
int64_t round = timestamp_ratio->num / 2;
if (round > 0) --round;
return (n * timestamp_ratio->den + round) / timestamp_ratio->num;
}
static INLINE int frame_is_kf_gf_arf(const AV1_COMP *cpi) {

View file

@ -73,17 +73,6 @@ void av1_alloc_txb_buf(AV1_COMP *cpi) {
void av1_free_txb_buf(AV1_COMP *cpi) { aom_free(cpi->coeff_buffer_base); }
void av1_set_coeff_buffer(const AV1_COMP *const cpi, MACROBLOCK *const x,
int mi_row, int mi_col) {
const AV1_COMMON *const cm = &cpi->common;
int mib_size_log2 = cm->seq_params.mib_size_log2;
int stride = (cm->mi_cols >> mib_size_log2) + 1;
int offset = (mi_row >> mib_size_log2) * stride + (mi_col >> mib_size_log2);
x->mbmi_ext->cb_coef_buff = &cpi->coeff_buffer_base[offset];
x->mbmi_ext->cb_offset = x->cb_offset;
assert(x->cb_offset < (1 << num_pels_log2_lookup[cm->seq_params.sb_size]));
}
static void write_golomb(aom_writer *w, int level) {
int x = level + 1;
int i = x;
@ -638,17 +627,17 @@ static void write_coeffs_txb_wrap(const AV1_COMMON *cm, MACROBLOCK *x,
aom_writer *w, int plane, int block,
int blk_row, int blk_col, TX_SIZE tx_size) {
MACROBLOCKD *xd = &x->e_mbd;
const CB_COEFF_BUFFER *cb_coef_buff = x->cb_coef_buff;
const int txb_offset =
x->mbmi_ext->cb_offset / (TX_SIZE_W_MIN * TX_SIZE_H_MIN);
tran_low_t *tcoeff_txb =
x->mbmi_ext->cb_coef_buff->tcoeff[plane] + x->mbmi_ext->cb_offset;
uint16_t *eob_txb = x->mbmi_ext->cb_coef_buff->eobs[plane] + txb_offset;
uint8_t *txb_skip_ctx_txb =
x->mbmi_ext->cb_coef_buff->txb_skip_ctx[plane] + txb_offset;
int *dc_sign_ctx_txb =
x->mbmi_ext->cb_coef_buff->dc_sign_ctx[plane] + txb_offset;
tran_low_t *tcoeff = BLOCK_OFFSET(tcoeff_txb, block);
uint16_t eob = eob_txb[block];
const tran_low_t *tcoeff_txb =
cb_coef_buff->tcoeff[plane] + x->mbmi_ext->cb_offset;
const uint16_t *eob_txb = cb_coef_buff->eobs[plane] + txb_offset;
const uint8_t *txb_skip_ctx_txb =
cb_coef_buff->txb_skip_ctx[plane] + txb_offset;
const int *dc_sign_ctx_txb = cb_coef_buff->dc_sign_ctx[plane] + txb_offset;
const tran_low_t *tcoeff = BLOCK_OFFSET(tcoeff_txb, block);
const uint16_t eob = eob_txb[block];
TXB_CTX txb_ctx = { txb_skip_ctx_txb[block], dc_sign_ctx_txb[block] };
av1_write_coeffs_txb(cm, xd, w, blk_row, blk_col, plane, tx_size, tcoeff, eob,
&txb_ctx);
@ -1690,15 +1679,15 @@ int av1_optimize_txb_new(const struct AV1_COMP *cpi, MACROBLOCK *x, int plane,
const LV_MAP_EOB_COST *txb_eob_costs =
&x->eob_costs[eob_multi_size][plane_type];
const int rshift =
(sharpness +
(cpi->oxcf.aq_mode == VARIANCE_AQ && mbmi->segment_id < 4
? 7 - mbmi->segment_id
: 2) +
(cpi->oxcf.aq_mode != VARIANCE_AQ &&
cpi->oxcf.deltaq_mode > NO_DELTA_Q && x->sb_energy_level < 0
? (3 - x->sb_energy_level)
: 0));
const int rshift = (sharpness +
(cpi->oxcf.aq_mode == VARIANCE_AQ && mbmi->segment_id < 4
? 7 - mbmi->segment_id
: 2) +
(cpi->oxcf.aq_mode != VARIANCE_AQ &&
cpi->oxcf.deltaq_mode == DELTA_Q_PERCEPTUAL &&
x->sb_energy_level < 0
? (3 - x->sb_energy_level)
: 0));
const int64_t rdmult =
(((int64_t)x->rdmult *
(plane_rd_mult[is_inter][plane_type] << (2 * (xd->bd - 8)))) +
@ -2008,11 +1997,11 @@ void av1_update_and_record_txb_context(int plane, int block, int blk_row,
2);
}
CB_COEFF_BUFFER *cb_coef_buff = x->cb_coef_buff;
const int txb_offset =
x->mbmi_ext->cb_offset / (TX_SIZE_W_MIN * TX_SIZE_H_MIN);
uint16_t *eob_txb = x->mbmi_ext->cb_coef_buff->eobs[plane] + txb_offset;
uint8_t *txb_skip_ctx_txb =
x->mbmi_ext->cb_coef_buff->txb_skip_ctx[plane] + txb_offset;
uint16_t *eob_txb = cb_coef_buff->eobs[plane] + txb_offset;
uint8_t *txb_skip_ctx_txb = cb_coef_buff->txb_skip_ctx[plane] + txb_offset;
txb_skip_ctx_txb[block] = txb_ctx.txb_skip_ctx;
eob_txb[block] = eob;
@ -2021,8 +2010,7 @@ void av1_update_and_record_txb_context(int plane, int block, int blk_row,
return;
}
tran_low_t *tcoeff_txb =
x->mbmi_ext->cb_coef_buff->tcoeff[plane] + x->mbmi_ext->cb_offset;
tran_low_t *tcoeff_txb = cb_coef_buff->tcoeff[plane] + x->mbmi_ext->cb_offset;
tran_low_t *tcoeff = BLOCK_OFFSET(tcoeff_txb, block);
const int segment_id = mbmi->segment_id;
const int seg_eob = av1_get_tx_eob(&cpi->common.seg, segment_id, tx_size);
@ -2116,8 +2104,7 @@ void av1_update_and_record_txb_context(int plane, int block, int blk_row,
#endif // CONFIG_ENTROPY_STATS
if (allow_update_cdf)
update_cdf(ec_ctx->dc_sign_cdf[plane_type][dc_sign_ctx], dc_sign, 2);
int *dc_sign_ctx_txb =
x->mbmi_ext->cb_coef_buff->dc_sign_ctx[plane] + txb_offset;
int *dc_sign_ctx_txb = cb_coef_buff->dc_sign_ctx[plane] + txb_offset;
dc_sign_ctx_txb[block] = dc_sign_ctx;
}
@ -2155,3 +2142,13 @@ void av1_update_txb_context(const AV1_COMP *cpi, ThreadData *td,
assert(0);
}
}
CB_COEFF_BUFFER *av1_get_cb_coeff_buffer(const struct AV1_COMP *cpi, int mi_row,
int mi_col) {
const AV1_COMMON *const cm = &cpi->common;
const int mib_size_log2 = cm->seq_params.mib_size_log2;
const int stride = (cm->mi_cols >> mib_size_log2) + 1;
const int offset =
(mi_row >> mib_size_log2) * stride + (mi_col >> mib_size_log2);
return cpi->coeff_buffer_base + offset;
}

View file

@ -71,15 +71,15 @@ void av1_update_and_record_txb_context(int plane, int block, int blk_row,
int blk_col, BLOCK_SIZE plane_bsize,
TX_SIZE tx_size, void *arg);
void av1_set_coeff_buffer(const AV1_COMP *const cpi, MACROBLOCK *const x,
int mi_row, int mi_col);
void hbt_destroy();
int av1_optimize_txb_new(const struct AV1_COMP *cpi, MACROBLOCK *x, int plane,
int block, TX_SIZE tx_size, TX_TYPE tx_type,
const TXB_CTX *const txb_ctx, int *rate_cost,
int sharpness, int fast_mode);
CB_COEFF_BUFFER *av1_get_cb_coeff_buffer(const struct AV1_COMP *cpi, int mi_row,
int mi_col);
// These numbers are empirically obtained.
static const int plane_rd_mult[REF_TYPES][PLANE_TYPES] = {
{ 17, 13 },

View file

@ -119,7 +119,10 @@ typedef struct {
unsigned char arf_src_offset[MAX_STATIC_GF_GROUP_LENGTH + 1];
unsigned char arf_update_idx[MAX_STATIC_GF_GROUP_LENGTH + 1];
unsigned char arf_pos_in_gf[MAX_STATIC_GF_GROUP_LENGTH + 1];
unsigned char frame_disp_idx[MAX_STATIC_GF_GROUP_LENGTH + 1];
unsigned char pyramid_level[MAX_STATIC_GF_GROUP_LENGTH + 1];
int ref_frame_disp_idx[MAX_STATIC_GF_GROUP_LENGTH + 1][REF_FRAMES];
int ref_frame_gop_idx[MAX_STATIC_GF_GROUP_LENGTH + 1][REF_FRAMES];
unsigned char pyramid_height;
unsigned char pyramid_lvl_nodes[MAX_PYRAMID_LVL];
int bit_allocation[MAX_STATIC_GF_GROUP_LENGTH + 1];

View file

@ -42,6 +42,7 @@ static void set_multi_layer_params(GF_GROUP *const gf_group, int start, int end,
gf_group->arf_src_offset[*frame_ind] = 0;
gf_group->arf_pos_in_gf[*frame_ind] = 0;
gf_group->arf_update_idx[*frame_ind] = arf_ind;
gf_group->frame_disp_idx[*frame_ind] = start;
gf_group->pyramid_level[*frame_ind] = MIN_PYRAMID_LVL;
++gf_group->pyramid_lvl_nodes[MIN_PYRAMID_LVL];
++(*frame_ind);
@ -55,6 +56,7 @@ static void set_multi_layer_params(GF_GROUP *const gf_group, int start, int end,
gf_group->arf_src_offset[*frame_ind] = m - start - 1;
gf_group->arf_pos_in_gf[*frame_ind] = 0;
gf_group->arf_update_idx[*frame_ind] = 1; // mark all internal ARF 1
gf_group->frame_disp_idx[*frame_ind] = m;
gf_group->pyramid_level[*frame_ind] = level;
++gf_group->pyramid_lvl_nodes[level];
++(*frame_ind);
@ -67,6 +69,7 @@ static void set_multi_layer_params(GF_GROUP *const gf_group, int start, int end,
gf_group->arf_src_offset[*frame_ind] = 0;
gf_group->arf_pos_in_gf[*frame_ind] = arf_pos_in_gf; // For bit allocation.
gf_group->arf_update_idx[*frame_ind] = 1;
gf_group->frame_disp_idx[*frame_ind] = m;
gf_group->pyramid_level[*frame_ind] = MIN_PYRAMID_LVL;
++(*frame_ind);
@ -101,6 +104,7 @@ static int construct_multi_layer_gf_structure(
gf_group->arf_src_offset[frame_index] = gf_interval - 1;
gf_group->arf_pos_in_gf[frame_index] = 0;
gf_group->arf_update_idx[frame_index] = 0;
gf_group->frame_disp_idx[frame_index] = gf_interval;
gf_group->pyramid_level[frame_index] = gf_group->pyramid_height;
++frame_index;
}
@ -165,6 +169,136 @@ static int get_pyramid_height(const AV1_COMP *const cpi) {
cpi->oxcf.gf_max_pyr_height);
}
#define REF_IDX(ref) ((ref)-LAST_FRAME)
static INLINE void reset_ref_frame_idx(int *ref_idx, int reset_value) {
for (int i = 0; i < REF_FRAMES; ++i) ref_idx[i] = reset_value;
}
static INLINE void set_ref_frame_disp_idx(GF_GROUP *const gf_group) {
for (int i = 0; i <= gf_group->size; ++i) {
for (int ref = 0; ref < INTER_REFS_PER_FRAME + 1; ++ref) {
int ref_gop_idx = gf_group->ref_frame_gop_idx[i][ref];
if (ref_gop_idx == -1) {
gf_group->ref_frame_disp_idx[i][ref] = -1;
} else {
gf_group->ref_frame_disp_idx[i][ref] =
gf_group->frame_disp_idx[ref_gop_idx];
}
}
}
}
static void set_gop_ref_frame_map(GF_GROUP *const gf_group) {
// Initialize the reference slots as all -1.
for (int frame_idx = 0; frame_idx <= gf_group->size; ++frame_idx)
reset_ref_frame_idx(gf_group->ref_frame_gop_idx[frame_idx], -1);
// Set the map for frames in the current gop
for (int frame_idx = 0; frame_idx < gf_group->size; ++frame_idx) {
const FRAME_UPDATE_TYPE update_type = gf_group->update_type[frame_idx];
// TODO(yuec): need to figure out how to determine
// (1) whether a KEY_FRAME has show_frame on
// (2) whether a frame with INTNL_OVERLAY_UPDATE type has
// show_existing_frame on
const int show_frame =
update_type != ARF_UPDATE && update_type != INTNL_ARF_UPDATE;
const int show_existing_frame =
update_type == OVERLAY_UPDATE || update_type == INTNL_OVERLAY_UPDATE;
int this_ref_map[INTER_REFS_PER_FRAME + 1];
memcpy(this_ref_map, gf_group->ref_frame_gop_idx[frame_idx],
sizeof(this_ref_map));
int *next_ref_map = &gf_group->ref_frame_gop_idx[frame_idx + 1][0];
switch (update_type) {
case KF_UPDATE:
if (show_frame) {
reset_ref_frame_idx(this_ref_map, frame_idx);
} else {
this_ref_map[REF_IDX(LAST3_FRAME)] = frame_idx;
this_ref_map[REF_IDX(EXTREF_FRAME)] = frame_idx;
this_ref_map[REF_IDX(ALTREF2_FRAME)] = frame_idx;
this_ref_map[REF_IDX(GOLDEN_FRAME)] = frame_idx;
this_ref_map[REF_IDX(ALTREF_FRAME)] = frame_idx;
}
break;
case LF_UPDATE: this_ref_map[REF_IDX(LAST3_FRAME)] = frame_idx; break;
case GF_UPDATE:
this_ref_map[REF_IDX(LAST3_FRAME)] = frame_idx;
this_ref_map[REF_IDX(GOLDEN_FRAME)] = frame_idx;
break;
case OVERLAY_UPDATE:
this_ref_map[REF_IDX(ALTREF_FRAME)] = frame_idx;
break;
case ARF_UPDATE: this_ref_map[REF_IDX(ALTREF_FRAME)] = frame_idx; break;
case INTNL_OVERLAY_UPDATE:
if (!show_existing_frame)
this_ref_map[REF_IDX(LAST3_FRAME)] = frame_idx;
break;
case INTNL_ARF_UPDATE:
this_ref_map[REF_IDX(EXTREF_FRAME)] = frame_idx;
break;
default: assert(0); break;
}
memcpy(next_ref_map, this_ref_map, sizeof(this_ref_map));
switch (update_type) {
case LF_UPDATE:
case GF_UPDATE:
next_ref_map[REF_IDX(LAST3_FRAME)] = this_ref_map[REF_IDX(LAST2_FRAME)];
next_ref_map[REF_IDX(LAST2_FRAME)] = this_ref_map[REF_IDX(LAST_FRAME)];
next_ref_map[REF_IDX(LAST_FRAME)] = this_ref_map[REF_IDX(LAST3_FRAME)];
break;
case INTNL_OVERLAY_UPDATE:
if (!show_existing_frame) {
next_ref_map[REF_IDX(LAST3_FRAME)] =
this_ref_map[REF_IDX(LAST2_FRAME)];
next_ref_map[REF_IDX(LAST2_FRAME)] =
this_ref_map[REF_IDX(LAST_FRAME)];
next_ref_map[REF_IDX(LAST_FRAME)] =
this_ref_map[REF_IDX(LAST3_FRAME)];
} else {
next_ref_map[REF_IDX(LAST_FRAME)] =
this_ref_map[REF_IDX(BWDREF_FRAME)];
next_ref_map[REF_IDX(LAST2_FRAME)] =
this_ref_map[REF_IDX(LAST_FRAME)];
next_ref_map[REF_IDX(LAST3_FRAME)] =
this_ref_map[REF_IDX(LAST2_FRAME)];
next_ref_map[REF_IDX(BWDREF_FRAME)] =
this_ref_map[REF_IDX(ALTREF2_FRAME)];
next_ref_map[REF_IDX(ALTREF2_FRAME)] =
this_ref_map[REF_IDX(EXTREF_FRAME)];
next_ref_map[REF_IDX(EXTREF_FRAME)] =
this_ref_map[REF_IDX(LAST3_FRAME)];
}
break;
case INTNL_ARF_UPDATE:
if (!show_existing_frame) {
next_ref_map[REF_IDX(BWDREF_FRAME)] =
this_ref_map[REF_IDX(EXTREF_FRAME)];
next_ref_map[REF_IDX(ALTREF2_FRAME)] =
this_ref_map[REF_IDX(BWDREF_FRAME)];
next_ref_map[REF_IDX(EXTREF_FRAME)] =
this_ref_map[REF_IDX(ALTREF2_FRAME)];
}
break;
case OVERLAY_UPDATE:
next_ref_map[REF_IDX(ALTREF_FRAME)] =
this_ref_map[REF_IDX(GOLDEN_FRAME)];
next_ref_map[REF_IDX(GOLDEN_FRAME)] =
this_ref_map[REF_IDX(ALTREF_FRAME)];
break;
default: break;
}
}
// Set the map in display order index by converting from gop indices in the
// above map
set_ref_frame_disp_idx(gf_group);
}
void av1_gop_setup_structure(AV1_COMP *cpi,
const EncodeFrameParams *const frame_params) {
RATE_CONTROL *const rc = &cpi->rc;
@ -186,6 +320,8 @@ void av1_gop_setup_structure(AV1_COMP *cpi,
gf_group->arf_update_idx[gf_group->size] = 0;
gf_group->arf_pos_in_gf[gf_group->size] = 0;
set_gop_ref_frame_map(gf_group);
#if CHECK_GF_PARAMETER
check_frame_params(gf_group, rc->baseline_gf_interval);
#endif

View file

@ -221,9 +221,13 @@ typedef enum {
LUMA_PIC_SIZE_TOO_LARGE,
LUMA_PIC_H_SIZE_TOO_LARGE,
LUMA_PIC_V_SIZE_TOO_LARGE,
LUMA_PIC_H_SIZE_TOO_SMALL,
LUMA_PIC_V_SIZE_TOO_SMALL,
TOO_MANY_TILE_COLUMNS,
TOO_MANY_TILES,
TILE_RATE_TOO_HIGH,
TILE_TOO_LARGE,
SUPERRES_TILE_WIDTH_TOO_LARGE,
CROPPED_TILE_WIDTH_TOO_SMALL,
CROPPED_TILE_HEIGHT_TOO_SMALL,
TILE_WIDTH_INVALID,
@ -231,6 +235,8 @@ typedef enum {
DISPLAY_RATE_TOO_HIGH,
DECODE_RATE_TOO_HIGH,
CR_TOO_SMALL,
TILE_SIZE_HEADER_RATE_TOO_HIGH,
BITRATE_TOO_HIGH,
TARGET_LEVEL_FAIL_IDS,
TARGET_LEVEL_OK,
@ -240,33 +246,91 @@ static const char *level_fail_messages[TARGET_LEVEL_FAIL_IDS] = {
"The picture size is too large.",
"The picture width is too large.",
"The picture height is too large.",
"The picture width is too small.",
"The picture height is too small.",
"Too many tile columns are used.",
"Too many tiles are used.",
"The tile rate is too high.",
"The tile size is too large.",
"The cropped tile width is less than 8",
"The cropped tile height is less than 8",
"The tile width is invalid",
"The frame header rate is too high",
"The display luma sample rate is too high",
"The decoded luma sample rate is too high",
"The compression ratio is too small",
"The superres tile width is too large.",
"The cropped tile width is less than 8.",
"The cropped tile height is less than 8.",
"The tile width is invalid.",
"The frame header rate is too high.",
"The display luma sample rate is too high.",
"The decoded luma sample rate is too high.",
"The compression ratio is too small.",
"The product of max tile size and header rate is too high.",
"The bitrate is too high.",
};
void av1_init_level_info(AV1LevelInfo *level_info) {
memset(level_info, 0, MAX_NUM_OPERATING_POINTS * sizeof(*level_info));
for (int i = 0; i < MAX_NUM_OPERATING_POINTS; ++i) {
AV1LevelSpec *const level_spec = &level_info[i].level_spec;
level_spec->level = SEQ_LEVEL_MAX;
AV1LevelStats *const level_stats = &level_info[i].level_stats;
level_stats->min_cropped_tile_width = INT_MAX;
level_stats->min_cropped_tile_height = INT_MAX;
level_stats->min_frame_width = INT_MAX;
level_stats->min_frame_height = INT_MAX;
level_stats->tile_width_is_valid = 1;
level_stats->min_cr = 1e8;
}
}
static double get_min_cr(const AV1LevelSpec *const level_spec, int tier,
int is_still_picture, int64_t decoded_sample_rate) {
if (is_still_picture) return 0.8;
if (level_spec->level < SEQ_LEVEL_4_0) tier = 0;
const double min_cr_basis = tier ? level_spec->high_cr : level_spec->main_cr;
const double speed_adj =
(double)decoded_sample_rate / level_spec->max_display_rate;
return AOMMAX(min_cr_basis * speed_adj, 0.8);
}
static void get_temporal_parallel_params(int scalability_mode_idc,
int *temporal_parallel_num,
int *temporal_parallel_denom) {
if (scalability_mode_idc < 0) {
*temporal_parallel_num = 1;
*temporal_parallel_denom = 1;
return;
}
// TODO(huisu@): handle scalability cases.
if (scalability_mode_idc == SCALABILITY_SS) {
(void)scalability_mode_idc;
} else {
(void)scalability_mode_idc;
}
}
static double get_max_bitrate(const AV1LevelSpec *const level_spec, int tier,
BITSTREAM_PROFILE profile) {
if (level_spec->level < SEQ_LEVEL_4_0) tier = 0;
const double bitrate_basis =
(tier ? level_spec->high_mbps : level_spec->main_mbps) * 1e6;
const double bitrate_profile_factor =
profile == PROFILE_0 ? 1.0 : (profile == PROFILE_1 ? 2.0 : 3.0);
return bitrate_basis * bitrate_profile_factor;
}
#define MAX_TILE_SIZE (4096 * 2304)
#define MIN_CROPPED_TILE_WIDTH 8
#define MIN_CROPPED_TILE_HEIGHT 8
#define MIN_FRAME_WIDTH 16
#define MIN_FRAME_HEIGHT 16
#define MAX_TILE_SIZE_HEADER_RATE_PRODUCT 588251136
static TARGET_LEVEL_FAIL_ID check_level_constraints(
const AV1LevelSpec *const target_level_spec,
const AV1LevelSpec *const level_spec,
const AV1LevelStats *const level_stats, int tier, int is_still_picture) {
const AV1LevelStats *const level_stats, int tier, int is_still_picture,
BITSTREAM_PROFILE profile) {
const double min_cr = get_min_cr(target_level_spec, tier, is_still_picture,
level_spec->max_decode_rate);
const double max_bitrate = get_max_bitrate(target_level_spec, tier, profile);
TARGET_LEVEL_FAIL_ID fail_id = TARGET_LEVEL_OK;
do {
@ -310,21 +374,41 @@ static TARGET_LEVEL_FAIL_ID check_level_constraints(
break;
}
if (level_stats->max_tile_size > 4096 * 2304) {
if (level_spec->max_tile_rate > target_level_spec->max_tiles * 120) {
fail_id = TILE_RATE_TOO_HIGH;
break;
}
if (level_stats->max_tile_size > MAX_TILE_SIZE) {
fail_id = TILE_TOO_LARGE;
break;
}
if (level_stats->min_cropped_tile_width < 8) {
if (level_stats->max_superres_tile_width > MAX_TILE_WIDTH) {
fail_id = SUPERRES_TILE_WIDTH_TOO_LARGE;
break;
}
if (level_stats->min_cropped_tile_width < MIN_CROPPED_TILE_WIDTH) {
fail_id = CROPPED_TILE_WIDTH_TOO_SMALL;
break;
}
if (level_stats->min_cropped_tile_height < 8) {
if (level_stats->min_cropped_tile_height < MIN_CROPPED_TILE_HEIGHT) {
fail_id = CROPPED_TILE_HEIGHT_TOO_SMALL;
break;
}
if (level_stats->min_frame_width < MIN_FRAME_WIDTH) {
fail_id = LUMA_PIC_H_SIZE_TOO_SMALL;
break;
}
if (level_stats->min_frame_height < MIN_FRAME_HEIGHT) {
fail_id = LUMA_PIC_V_SIZE_TOO_SMALL;
break;
}
if (!level_stats->tile_width_is_valid) {
fail_id = TILE_WIDTH_INVALID;
break;
@ -334,6 +418,25 @@ static TARGET_LEVEL_FAIL_ID check_level_constraints(
fail_id = CR_TOO_SMALL;
break;
}
if ((double)level_stats->max_bitrate > max_bitrate) {
fail_id = BITRATE_TOO_HIGH;
break;
}
if (target_level_spec->level > SEQ_LEVEL_5_1) {
int temporal_parallel_num;
int temporal_parallel_denom;
const int scalability_mode_idc = -1;
get_temporal_parallel_params(scalability_mode_idc, &temporal_parallel_num,
&temporal_parallel_denom);
const int val = level_stats->max_tile_size * level_spec->max_header_rate *
temporal_parallel_denom / temporal_parallel_num;
if (val > MAX_TILE_SIZE_HEADER_RATE_PRODUCT) {
fail_id = TILE_SIZE_HEADER_RATE_TOO_HIGH;
break;
}
}
} while (0);
return fail_id;
@ -349,14 +452,17 @@ static INLINE int is_in_operating_point(int operating_point,
}
static void get_tile_stats(const AV1_COMP *const cpi, int *max_tile_size,
int *max_superres_tile_width,
int *min_cropped_tile_width,
int *min_cropped_tile_height,
int *tile_width_valid) {
const AV1_COMMON *const cm = &cpi->common;
const int tile_cols = cm->tile_cols;
const int tile_rows = cm->tile_rows;
const int superres_scale_denominator = cm->superres_scale_denominator;
*max_tile_size = 0;
*max_superres_tile_width = 0;
*min_cropped_tile_width = INT_MAX;
*min_cropped_tile_height = INT_MAX;
*tile_width_valid = 1;
@ -372,6 +478,11 @@ static void get_tile_stats(const AV1_COMP *const cpi, int *max_tile_size,
const int tile_size = tile_width * tile_height;
*max_tile_size = AOMMAX(*max_tile_size, tile_size);
const int supperres_tile_width =
tile_width * superres_scale_denominator / SCALE_NUMERATOR;
*max_superres_tile_width =
AOMMAX(*max_superres_tile_width, supperres_tile_width);
const int cropped_tile_width =
cm->width - tile_info->mi_col_start * MI_SIZE;
const int cropped_tile_height =
@ -392,8 +503,9 @@ static void get_tile_stats(const AV1_COMP *const cpi, int *max_tile_size,
}
}
static int store_frame_record(int64_t ts_start, int64_t ts_end, int pic_size,
int frame_header_count, int show_frame,
static int store_frame_record(int64_t ts_start, int64_t ts_end,
size_t encoded_size, int pic_size,
int frame_header_count, int tiles, int show_frame,
int show_existing_frame,
FrameWindowBuffer *const buffer) {
if (buffer->num < FRAME_WINDOW_SIZE) {
@ -405,8 +517,10 @@ static int store_frame_record(int64_t ts_start, int64_t ts_end, int pic_size,
FrameRecord *const record = &buffer->buf[new_idx];
record->ts_start = ts_start;
record->ts_end = ts_end;
record->encoded_size_in_bytes = encoded_size;
record->pic_size = pic_size;
record->frame_header_count = frame_header_count;
record->tiles = tiles;
record->show_frame = show_frame;
record->show_existing_frame = show_existing_frame;
@ -439,12 +553,15 @@ static int count_frames(const FrameWindowBuffer *const buffer,
// Scan previously encoded frames and update level metrics accordingly.
static void scan_past_frames(const FrameWindowBuffer *const buffer,
int num_frames_to_scan,
AV1LevelSpec *const level_spec) {
AV1LevelSpec *const level_spec,
AV1LevelStats *const level_stats) {
const int num_frames_in_buffer = buffer->num;
int index = (buffer->start + num_frames_in_buffer - 1) % FRAME_WINDOW_SIZE;
int frame_headers = 0;
int tiles = 0;
int64_t display_samples = 0;
int64_t decoded_samples = 0;
size_t encoded_size_in_bytes = 0;
for (int i = 0; i < AOMMIN(num_frames_in_buffer, num_frames_to_scan); ++i) {
const FrameRecord *const record = &buffer->buf[index];
if (!record->show_existing_frame) {
@ -454,6 +571,8 @@ static void scan_past_frames(const FrameWindowBuffer *const buffer,
if (record->show_frame) {
display_samples += record->pic_size;
}
tiles += record->tiles;
encoded_size_in_bytes += record->encoded_size_in_bytes;
--index;
if (index < 0) index = FRAME_WINDOW_SIZE - 1;
}
@ -463,12 +582,16 @@ static void scan_past_frames(const FrameWindowBuffer *const buffer,
AOMMAX(level_spec->max_display_rate, display_samples);
level_spec->max_decode_rate =
AOMMAX(level_spec->max_decode_rate, decoded_samples);
level_spec->max_tile_rate = AOMMAX(level_spec->max_tile_rate, tiles);
level_stats->max_bitrate =
AOMMAX(level_stats->max_bitrate, (int)encoded_size_in_bytes * 8);
}
void av1_update_level_info(AV1_COMP *cpi, size_t size, int64_t ts_start,
int64_t ts_end) {
AV1_COMMON *const cm = &cpi->common;
const int upscaled_width = cm->superres_upscaled_width;
const int width = cm->width;
const int height = cm->height;
const int tile_cols = cm->tile_cols;
const int tile_rows = cm->tile_rows;
@ -480,8 +603,8 @@ void av1_update_level_info(AV1_COMP *cpi, size_t size, int64_t ts_start,
// Store info. of current frame into FrameWindowBuffer.
FrameWindowBuffer *const buffer = &cpi->frame_window_buffer;
store_frame_record(ts_start, ts_end, luma_pic_size, frame_header_count,
show_frame, show_existing_frame, buffer);
store_frame_record(ts_start, ts_end, size, luma_pic_size, frame_header_count,
tiles, show_frame, show_existing_frame, buffer);
// Count the number of frames encoded in the past 1 second.
const int encoded_frames_in_last_second =
show_frame ? count_frames(buffer, TICKS_PER_SEC) : 0;
@ -489,9 +612,11 @@ void av1_update_level_info(AV1_COMP *cpi, size_t size, int64_t ts_start,
int max_tile_size;
int min_cropped_tile_width;
int min_cropped_tile_height;
int max_superres_tile_width;
int tile_width_is_valid;
get_tile_stats(cpi, &max_tile_size, &min_cropped_tile_width,
&min_cropped_tile_height, &tile_width_is_valid);
get_tile_stats(cpi, &max_tile_size, &max_superres_tile_width,
&min_cropped_tile_width, &min_cropped_tile_height,
&tile_width_is_valid);
const SequenceHeader *const seq_params = &cm->seq_params;
const BITSTREAM_PROFILE profile = seq_params->profile;
@ -524,12 +649,16 @@ void av1_update_level_info(AV1_COMP *cpi, size_t size, int64_t ts_start,
level_stats->max_tile_size =
AOMMAX(level_stats->max_tile_size, max_tile_size);
level_stats->max_superres_tile_width =
AOMMAX(level_stats->max_superres_tile_width, max_superres_tile_width);
level_stats->min_cropped_tile_width =
AOMMIN(level_stats->min_cropped_tile_width, min_cropped_tile_width);
level_stats->min_cropped_tile_height =
AOMMIN(level_stats->min_cropped_tile_height, min_cropped_tile_height);
level_stats->tile_width_is_valid &= tile_width_is_valid;
level_stats->total_compressed_size += frame_compressed_size;
level_stats->min_frame_width = AOMMIN(level_stats->min_frame_width, width);
level_stats->min_frame_height =
AOMMIN(level_stats->min_frame_height, height);
if (show_frame) level_stats->total_time_encoded = total_time_encoded;
level_stats->min_cr = AOMMIN(level_stats->min_cr, compression_ratio);
@ -545,7 +674,8 @@ void av1_update_level_info(AV1_COMP *cpi, size_t size, int64_t ts_start,
level_spec->max_tiles = AOMMAX(level_spec->max_tiles, tiles);
if (show_frame) {
scan_past_frames(buffer, encoded_frames_in_last_second, level_spec);
scan_past_frames(buffer, encoded_frames_in_last_second, level_spec,
level_stats);
}
// Check whether target level is met.
@ -554,8 +684,9 @@ void av1_update_level_info(AV1_COMP *cpi, size_t size, int64_t ts_start,
const AV1LevelSpec *const target_level_spec =
av1_level_defs + target_seq_level_idx;
const int tier = seq_params->tier[i];
const TARGET_LEVEL_FAIL_ID fail_id = check_level_constraints(
target_level_spec, level_spec, level_stats, tier, is_still_picture);
const TARGET_LEVEL_FAIL_ID fail_id =
check_level_constraints(target_level_spec, level_spec, level_stats,
tier, is_still_picture, profile);
if (fail_id != TARGET_LEVEL_OK) {
const int target_level_major = 2 + (target_seq_level_idx >> 2);
const int target_level_minor = target_seq_level_idx & 3;
@ -578,6 +709,7 @@ aom_codec_err_t av1_get_seq_level_idx(const AV1_COMP *cpi, int *seq_level_idx) {
}
const int is_still_picture = seq_params->still_picture;
const BITSTREAM_PROFILE profile = seq_params->profile;
for (int op = 0; op < seq_params->operating_points_cnt_minus_1 + 1; ++op) {
seq_level_idx[op] = (int)SEQ_LEVEL_MAX;
const int tier = seq_params->tier[op];
@ -586,8 +718,9 @@ aom_codec_err_t av1_get_seq_level_idx(const AV1_COMP *cpi, int *seq_level_idx) {
const AV1LevelSpec *const level_spec = &level_info->level_spec;
for (int level = 0; level < SEQ_LEVELS; ++level) {
const AV1LevelSpec *const target_level_spec = av1_level_defs + level;
const TARGET_LEVEL_FAIL_ID fail_id = check_level_constraints(
target_level_spec, level_spec, level_stats, tier, is_still_picture);
const TARGET_LEVEL_FAIL_ID fail_id =
check_level_constraints(target_level_spec, level_spec, level_stats,
tier, is_still_picture, profile);
if (fail_id == TARGET_LEVEL_OK) {
seq_level_idx[op] = level;
break;

View file

@ -23,6 +23,7 @@ typedef struct {
int max_h_size;
int max_v_size;
int max_header_rate;
int max_tile_rate;
int max_tiles;
int max_tile_cols;
int64_t max_display_rate;
@ -36,8 +37,10 @@ typedef struct {
typedef struct {
int64_t ts_start;
int64_t ts_end;
size_t encoded_size_in_bytes;
int pic_size;
int frame_header_count;
int tiles;
int show_frame;
int show_existing_frame;
} FrameRecord;
@ -52,11 +55,14 @@ typedef struct {
// Used to keep track of AV1 Level Stats. Currently unimplemented.
typedef struct {
uint64_t total_compressed_size;
int max_bitrate; // In bps.
int max_tile_size;
int max_superres_tile_width;
int min_cropped_tile_width;
int min_cropped_tile_height;
int tile_width_is_valid;
int min_frame_width;
int min_frame_height;
double total_time_encoded;
double min_cr;
} AV1LevelStats;
@ -66,6 +72,8 @@ typedef struct {
AV1LevelSpec level_spec;
} AV1LevelInfo;
void av1_init_level_info(AV1LevelInfo *level_info);
void av1_update_level_info(struct AV1_COMP *cpi, size_t size, int64_t ts_start,
int64_t ts_end);

View file

@ -123,6 +123,7 @@ void av1_init_dsmotion_compensation(search_site_config *cfg, int stride) {
cfg->ss[0].mv.col = cfg->ss[0].mv.row = 0;
cfg->ss[0].offset = 0;
cfg->stride = stride;
for (len = MAX_FIRST_STEP; len > 0; len /= 2) {
// Generate offsets for 4 search sites per step.
@ -144,6 +145,7 @@ void av1_init3smotion_compensation(search_site_config *cfg, int stride) {
cfg->ss[0].mv.col = cfg->ss[0].mv.row = 0;
cfg->ss[0].offset = 0;
cfg->stride = stride;
for (len = MAX_FIRST_STEP; len > 0; len /= 2) {
// Generate offsets for 8 search sites per step.
@ -2017,8 +2019,8 @@ int av1_refining_search_8p_c(MACROBLOCK *x, int error_per_bit, int search_range,
MV *best_mv = &x->best_mv.as_mv;
unsigned int best_sad = INT_MAX;
int i, j;
uint8_t do_refine_search_grid[SEARCH_GRID_STRIDE_8P * SEARCH_GRID_STRIDE_8P] =
{ 0 };
uint8_t do_refine_search_grid[SEARCH_GRID_STRIDE_8P *
SEARCH_GRID_STRIDE_8P] = { 0 };
int grid_center = SEARCH_GRID_CENTER_8P;
int grid_coord = grid_center;
@ -3095,20 +3097,20 @@ void av1_simple_motion_search(AV1_COMP *const cpi, MACROBLOCK *x, int mi_row,
MV ref_mv = { 0, 0 };
const int step_param = cpi->mv_step_param;
const MvLimits tmp_mv_limits = x->mv_limits;
const SEARCH_METHODS search_methods = NSTEP;
const SEARCH_METHODS search_methods = cpi->sf.mv.search_method;
const int do_mesh_search = 0;
const int sadpb = x->sadperbit16;
int cost_list[5];
const int ref_idx = 0;
int var;
av1_setup_pre_planes(xd, ref_idx, yv12, mi_row, mi_col,
get_ref_scale_factors(cm, ref), num_planes);
set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
if (scaled_ref_frame) {
backup_yv12 = xd->plane[AOM_PLANE_Y].pre[ref_idx];
av1_setup_pre_planes(xd, ref_idx, scaled_ref_frame, mi_row, mi_col, NULL,
num_planes);
} else {
av1_setup_pre_planes(xd, ref_idx, yv12, mi_row, mi_col,
get_ref_scale_factors(cm, ref), num_planes);
}
// This overwrites the mv_limits so we will need to restore it later.
@ -3122,6 +3124,9 @@ void av1_simple_motion_search(AV1_COMP *const cpi, MACROBLOCK *x, int mi_row,
const int use_subpel_search =
var < INT_MAX && !cpi->common.cur_frame_force_integer_mv && use_subpixel;
if (scaled_ref_frame) {
xd->plane[AOM_PLANE_Y].pre[ref_idx] = backup_yv12;
}
if (use_subpel_search) {
int not_used = 0;
if (cpi->sf.use_accurate_subpel_search) {
@ -3151,7 +3156,6 @@ void av1_simple_motion_search(AV1_COMP *const cpi, MACROBLOCK *x, int mi_row,
mbmi->mv[0].as_mv = x->best_mv.as_mv;
// Get a copy of the prediction output
set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, NULL, bsize,
AOM_PLANE_Y, AOM_PLANE_Y);

View file

@ -47,6 +47,7 @@ typedef struct search_site_config {
search_site ss[8 * MAX_MVSEARCH_STEPS + 1];
int ss_count;
int searches_per_step;
int stride;
} search_site_config;
typedef struct {

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -21,109 +21,73 @@
#include "av1/encoder/partition_strategy.h"
#include "av1/encoder/rdopt.h"
// Performs a simple_motion_search with a single reference frame and extract
// the variance of residues. Here features is assumed to be a length 6 array.
// After this function is called, we will store the following in to features:
// features[0] = log(1 + dc_q**2/256)
// features[1] = log(1 + variance_of_residue)
// for i in [2, 3, 4, 5]:
// features[i] = log(1 + variance_of_residue_in_block[i]/variance_of_residue)
static void get_res_var_features(AV1_COMP *const cpi, MACROBLOCK *x, int mi_row,
int mi_col, BLOCK_SIZE bsize,
float *features) {
// TODO(chiyotsai@google.com): The data this model trained on did not also use
// SIMPLE_TRANSLATION to build the inter_predictor. Retraining and tuning the
// model with the correct data should give better performance.
assert(mi_size_wide[bsize] == mi_size_high[bsize]);
static void simple_motion_search_prune_part_features(
AV1_COMP *const cpi, MACROBLOCK *x, PC_TREE *pc_tree, int mi_row,
int mi_col, BLOCK_SIZE bsize, float *features, int features_to_get);
MACROBLOCKD *xd = &x->e_mbd;
// Perform a single motion search in Y_PLANE to make a prediction
const int use_subpixel = 0;
// Start getting the features
int f_idx = 0;
// Q_INDEX
const int dc_q = av1_dc_quant_QTX(x->qindex, 0, xd->bd) >> (xd->bd - 8);
aom_clear_system_state();
features[f_idx++] = logf(1.0f + (float)(dc_q * dc_q) / 256.0f);
// VARIANCE
unsigned int sse = 0;
unsigned int var = 0;
const MV ref_mv_full = { .row = 0, .col = 0 };
av1_simple_motion_sse_var(cpi, x, mi_row, mi_col, bsize, ref_mv_full,
use_subpixel, &sse, &var);
aom_clear_system_state();
features[f_idx++] = logf(1.0f + (float)var);
// Regional
const uint8_t *src = x->plane[0].src.buf;
const int src_stride = x->plane[0].src.stride;
const uint8_t *dst = xd->plane[0].dst.buf;
const int dst_stride = xd->plane[0].dst.stride;
const int bw = block_size_wide[bsize];
const int bh = block_size_high[bsize];
const BLOCK_SIZE subsize = get_partition_subsize(bsize, PARTITION_SPLIT);
int r_idx = 0;
for (r_idx = 0; r_idx < 4; r_idx++) {
const int x_idx = (r_idx & 1) * bw / 2;
const int y_idx = (r_idx >> 1) * bh / 2;
const int src_offset = y_idx * src_stride + x_idx;
const int dst_offset = y_idx * dst_stride + x_idx;
const unsigned int sub_var = cpi->fn_ptr[subsize].vf(
src + src_offset, src_stride, dst + dst_offset, dst_stride, &sse);
aom_clear_system_state();
const float var_ratio = (1.0f + (float)sub_var) / (4.0f + (float)var);
features[f_idx++] = var_ratio;
static INLINE int convert_bsize_to_idx(BLOCK_SIZE bsize) {
switch (bsize) {
case BLOCK_128X128: return 0;
case BLOCK_64X64: return 1;
case BLOCK_32X32: return 2;
case BLOCK_16X16: return 3;
case BLOCK_8X8: return 4;
default: assert(0 && "Invalid bsize"); return -1;
}
}
void av1_simple_motion_search_based_split(
AV1_COMP *const cpi, MACROBLOCK *x, int mi_row, int mi_col,
BLOCK_SIZE bsize, int *partition_none_allowed, int *partition_horz_allowed,
int *partition_vert_allowed, int *do_rectangular_split,
int *do_square_split) {
const NN_CONFIG *nn_config = NULL;
float split_only_thresh = 0.0f;
if (bsize == BLOCK_128X128) {
nn_config = &av1_simple_motion_search_based_split_nn_config_128;
split_only_thresh = av1_simple_motion_search_based_split_thresh_128;
} else if (bsize == BLOCK_64X64) {
nn_config = &av1_simple_motion_search_based_split_nn_config_64;
split_only_thresh = av1_simple_motion_search_based_split_thresh_64;
} else if (bsize == BLOCK_32X32) {
nn_config = &av1_simple_motion_search_based_split_nn_config_32;
split_only_thresh = av1_simple_motion_search_based_split_thresh_32;
} else if (bsize == BLOCK_16X16) {
nn_config = &av1_simple_motion_search_based_split_nn_config_16;
split_only_thresh = av1_simple_motion_search_based_split_thresh_16;
} else if (bsize == BLOCK_8X8) {
// Disable BLOCK_8X8 for now
#if !CONFIG_DISABLE_FULL_PIXEL_SPLIT_8X8
nn_config = &av1_simple_motion_search_based_split_nn_config_8;
split_only_thresh = av1_simple_motion_search_based_split_thresh_8;
#endif
} else {
assert(0 && "Unexpected block size in simple_motion_based_split");
}
if (nn_config) {
float features[6] = { 0 };
float score = 0;
get_res_var_features(cpi, x, mi_row, mi_col, bsize, features);
av1_nn_predict(features, nn_config, &score);
AV1_COMP *const cpi, MACROBLOCK *x, PC_TREE *pc_tree, int mi_row,
int mi_col, BLOCK_SIZE bsize, int *partition_none_allowed,
int *partition_horz_allowed, int *partition_vert_allowed,
int *do_rectangular_split, int *do_square_split) {
aom_clear_system_state();
if (score > split_only_thresh) {
*partition_none_allowed = 0;
*partition_horz_allowed = 0;
*partition_vert_allowed = 0;
*do_rectangular_split = 0;
}
// TODO(Venkat): Experiment to skip only rectangular/extended parititions
if (cpi->sf.simple_motion_search_split_only >= 2) {
if (score < -split_only_thresh) *do_square_split = 0;
}
const AV1_COMMON *const cm = &cpi->common;
const int is_480p_or_larger = AOMMIN(cm->width, cm->height) >= 480;
const int bsize_idx = convert_bsize_to_idx(bsize);
assert(bsize_idx >= 0 && bsize_idx <= 4 &&
"Invalid bsize in simple_motion_search_based_split");
float split_only_thresh = 100.0f, no_split_thresh = -100.0f;
const float *ml_mean = av1_simple_motion_search_split_mean[bsize_idx];
const float *ml_std = av1_simple_motion_search_split_std[bsize_idx];
const NN_CONFIG *nn_config =
av1_simple_motion_search_split_nn_config[bsize_idx];
if (is_480p_or_larger) {
split_only_thresh = av1_simple_motion_search_split_midres_thresh[bsize_idx];
no_split_thresh =
av1_simple_motion_search_split_midres_no_thresh[bsize_idx];
} else {
split_only_thresh = av1_simple_motion_search_split_lowres_thresh[bsize_idx];
no_split_thresh =
av1_simple_motion_search_split_lowres_no_thresh[bsize_idx];
}
float features[FEATURE_SIZE_SMS_SPLIT] = { 0.0f };
simple_motion_search_prune_part_features(cpi, x, pc_tree, mi_row, mi_col,
bsize, features,
FEATURE_SMS_SPLIT_MODEL_FLAG);
for (int idx = 0; idx < FEATURE_SIZE_SMS_SPLIT; idx++) {
features[idx] = (features[idx] - ml_mean[idx]) / ml_std[idx];
}
float score = 0.0f;
av1_nn_predict(features, nn_config, &score);
aom_clear_system_state();
if (score > split_only_thresh) {
*partition_none_allowed = 0;
*partition_horz_allowed = 0;
*partition_vert_allowed = 0;
*do_rectangular_split = 0;
}
if (cpi->sf.simple_motion_search_split >= 2 && score < no_split_thresh) {
*do_square_split = 0;
}
}
@ -206,71 +170,94 @@ static int simple_motion_search_get_best_ref(
// features[18] = DC q_index
static void simple_motion_search_prune_part_features(
AV1_COMP *const cpi, MACROBLOCK *x, PC_TREE *pc_tree, int mi_row,
int mi_col, BLOCK_SIZE bsize, float *features) {
int mi_col, BLOCK_SIZE bsize, float *features, int features_to_get) {
// TODO(chiyotsai@google.com): Cache the result of the motion search from the
// larger bsize.
const int w_mi = mi_size_wide[bsize];
const int h_mi = mi_size_high[bsize];
int f_idx = 0;
assert(mi_size_wide[bsize] == mi_size_high[bsize]);
assert(cpi->ref_frame_flags & av1_ref_frame_flag_list[LAST_FRAME] ||
cpi->ref_frame_flags & av1_ref_frame_flag_list[ALTREF_FRAME]);
// Setting up motion search
const int ref_list[] = { LAST_FRAME, ALTREF_FRAME };
const int num_refs = 2;
const int ref_list[] = { cpi->rc.is_src_frame_alt_ref ? ALTREF_FRAME
: LAST_FRAME };
const int num_refs = 1;
const int use_subpixel = 1;
unsigned int int_features[FEATURE_SIZE_SMS_PRUNE_PART - 1];
// Doing whole block first to update the mv
simple_motion_search_get_best_ref(
cpi, x, pc_tree, mi_row, mi_col, bsize, ref_list, num_refs, use_subpixel,
4, &int_features[f_idx], &int_features[f_idx + 1]);
f_idx += 2;
if (!pc_tree->sms_none_valid && features_to_get & FEATURE_SMS_NONE_FLAG) {
simple_motion_search_get_best_ref(cpi, x, pc_tree, mi_row, mi_col, bsize,
ref_list, num_refs, use_subpixel, 4,
&pc_tree->sms_none_feat[0],
&pc_tree->sms_none_feat[1]);
pc_tree->sms_none_valid = 1;
}
// Split subblocks
BLOCK_SIZE subsize = get_partition_subsize(bsize, PARTITION_SPLIT);
int r_idx = 0;
for (r_idx = 0; r_idx < 4; r_idx++) {
const int sub_mi_col = mi_col + (r_idx & 1) * w_mi / 2;
const int sub_mi_row = mi_row + (r_idx >> 1) * h_mi / 2;
if (!pc_tree->sms_split_valid && features_to_get & FEATURE_SMS_SPLIT_FLAG) {
const BLOCK_SIZE subsize = get_partition_subsize(bsize, PARTITION_SPLIT);
for (int r_idx = 0; r_idx < 4; r_idx++) {
const int sub_mi_col = mi_col + (r_idx & 1) * w_mi / 2;
const int sub_mi_row = mi_row + (r_idx >> 1) * h_mi / 2;
simple_motion_search_get_best_ref(
cpi, x, pc_tree, sub_mi_row, sub_mi_col, subsize, ref_list, num_refs,
use_subpixel, r_idx, &int_features[f_idx], &int_features[f_idx + 1]);
f_idx += 2;
simple_motion_search_get_best_ref(
cpi, x, pc_tree, sub_mi_row, sub_mi_col, subsize, ref_list, num_refs,
use_subpixel, r_idx, &pc_tree->sms_split_feat[2 * r_idx],
&pc_tree->sms_split_feat[2 * r_idx + 1]);
}
pc_tree->sms_split_valid = 1;
}
// Horz subblocks
subsize = get_partition_subsize(bsize, PARTITION_HORZ);
for (r_idx = 0; r_idx < 2; r_idx++) {
const int sub_mi_col = mi_col + 0;
const int sub_mi_row = mi_row + r_idx * h_mi / 2;
// Rectangular subblocks
if (!pc_tree->sms_rect_valid && features_to_get & FEATURE_SMS_RECT_FLAG) {
// Horz subblock
BLOCK_SIZE subsize = get_partition_subsize(bsize, PARTITION_HORZ);
for (int r_idx = 0; r_idx < 2; r_idx++) {
const int sub_mi_col = mi_col + 0;
const int sub_mi_row = mi_row + r_idx * h_mi / 2;
simple_motion_search_get_best_ref(
cpi, x, pc_tree, sub_mi_row, sub_mi_col, subsize, ref_list, num_refs,
use_subpixel, -1, &int_features[f_idx], &int_features[f_idx + 1]);
simple_motion_search_get_best_ref(
cpi, x, pc_tree, sub_mi_row, sub_mi_col, subsize, ref_list, num_refs,
use_subpixel, -1, &pc_tree->sms_rect_feat[2 * r_idx],
&pc_tree->sms_rect_feat[2 * r_idx + 1]);
}
f_idx += 2;
// Vert subblock
subsize = get_partition_subsize(bsize, PARTITION_VERT);
for (int r_idx = 0; r_idx < 2; r_idx++) {
const int sub_mi_col = mi_col + r_idx * w_mi / 2;
const int sub_mi_row = mi_row + 0;
simple_motion_search_get_best_ref(
cpi, x, pc_tree, sub_mi_row, sub_mi_col, subsize, ref_list, num_refs,
use_subpixel, -1, &pc_tree->sms_rect_feat[4 + 2 * r_idx],
&pc_tree->sms_rect_feat[4 + 2 * r_idx + 1]);
}
pc_tree->sms_rect_valid = 1;
}
// Vert subblock
subsize = get_partition_subsize(bsize, PARTITION_VERT);
for (r_idx = 0; r_idx < 2; r_idx++) {
const int sub_mi_col = mi_col + r_idx * w_mi / 2;
const int sub_mi_row = mi_row + 0;
simple_motion_search_get_best_ref(
cpi, x, pc_tree, sub_mi_row, sub_mi_col, subsize, ref_list, num_refs,
use_subpixel, -1, &int_features[f_idx], &int_features[f_idx + 1]);
f_idx += 2;
}
if (!features) return;
aom_clear_system_state();
for (int idx = 0; idx < f_idx; idx++) {
features[idx] = logf(1.0f + (float)int_features[idx]);
int f_idx = 0;
if (features_to_get & FEATURE_SMS_NONE_FLAG) {
for (int sub_idx = 0; sub_idx < 2; sub_idx++) {
features[f_idx++] = logf(1.0f + pc_tree->sms_none_feat[sub_idx]);
}
}
if (features_to_get & FEATURE_SMS_SPLIT_FLAG) {
for (int sub_idx = 0; sub_idx < 8; sub_idx++) {
features[f_idx++] = logf(1.0f + pc_tree->sms_split_feat[sub_idx]);
}
}
if (features_to_get & FEATURE_SMS_RECT_FLAG) {
for (int sub_idx = 0; sub_idx < 8; sub_idx++) {
features[f_idx++] = logf(1.0f + pc_tree->sms_rect_feat[sub_idx]);
}
}
const MACROBLOCKD *xd = &x->e_mbd;
@ -291,8 +278,6 @@ static void simple_motion_search_prune_part_features(
features[f_idx++] = (float)has_left;
features[f_idx++] = (float)mi_size_wide_log2[left_bsize];
features[f_idx++] = (float)mi_size_high_log2[left_bsize];
assert(f_idx == FEATURE_SIZE_SMS_PRUNE_PART);
}
void av1_simple_motion_search_prune_part(
@ -300,13 +285,13 @@ void av1_simple_motion_search_prune_part(
int mi_col, BLOCK_SIZE bsize, int *partition_none_allowed,
int *partition_horz_allowed, int *partition_vert_allowed,
int *do_square_split, int *do_rectangular_split, int *prune_horz,
int *prune_vert, float *features, int *valid) {
int *prune_vert) {
const AV1_COMMON *const cm = &cpi->common;
// Get model parameters
const NN_CONFIG *nn_config = NULL;
const float *prune_thresh = NULL, *only_thresh = NULL;
const float *ml_mean = NULL, *ml_std = NULL;
float normalized_features[FEATURE_SIZE_SMS_PRUNE_PART] = { 0.0f };
float features[FEATURE_SIZE_SMS_PRUNE_PART] = { 0.0f };
if (bsize == BLOCK_128X128) {
nn_config = &av1_simple_motion_search_prune_part_nn_config_128;
@ -353,11 +338,10 @@ void av1_simple_motion_search_prune_part(
// Get features
simple_motion_search_prune_part_features(cpi, x, pc_tree, mi_row, mi_col,
bsize, features);
*valid = 1;
bsize, features,
FEATURE_SMS_PRUNE_PART_FLAG);
for (int f_idx = 0; f_idx < FEATURE_SIZE_SMS_PRUNE_PART; f_idx++) {
normalized_features[f_idx] =
(features[f_idx] - ml_mean[f_idx]) / ml_std[f_idx];
features[f_idx] = (features[f_idx] - ml_mean[f_idx]) / ml_std[f_idx];
}
// Get probabilities
@ -367,7 +351,7 @@ void av1_simple_motion_search_prune_part(
? PARTITION_TYPES
: EXT_PARTITION_TYPES;
av1_nn_predict(normalized_features, nn_config, scores);
av1_nn_predict(features, nn_config, scores);
aom_clear_system_state();
av1_nn_softmax(scores, probs, num_classes);
@ -393,24 +377,23 @@ void av1_simple_motion_search_prune_part(
// - The frame is not intra only
// - The current bsize is > BLOCK_8X8
// - blk_row + blk_height/2 < total_rows and blk_col + blk_width/2 < total_cols
void av1_simple_motion_search_early_term_none(
AV1_COMP *const cpi, MACROBLOCK *x, PC_TREE *pc_tree, int mi_row,
int mi_col, BLOCK_SIZE bsize, const RD_STATS *none_rdc,
int *early_terminate, float *simple_motion_features,
int *simple_motion_features_are_valid) {
void av1_simple_motion_search_early_term_none(AV1_COMP *const cpi,
MACROBLOCK *x, PC_TREE *pc_tree,
int mi_row, int mi_col,
BLOCK_SIZE bsize,
const RD_STATS *none_rdc,
int *early_terminate) {
// TODO(chiyotsai@google.com): There are other features we can extract from
// PARTITION_NONE. Play with this later.
int f_idx = 0;
if (!*simple_motion_features_are_valid) {
simple_motion_search_prune_part_features(cpi, x, pc_tree, mi_row, mi_col,
bsize, simple_motion_features);
*simple_motion_features_are_valid = 1;
}
f_idx = 25;
float features[FEATURE_SIZE_SMS_TERM_NONE] = { 0.0f };
simple_motion_search_prune_part_features(cpi, x, pc_tree, mi_row, mi_col,
bsize, features,
FEATURE_SMS_PRUNE_PART_FLAG);
int f_idx = FEATURE_SIZE_SMS_PRUNE_PART;
simple_motion_features[f_idx++] = logf(1.0f + (float)none_rdc->rate);
simple_motion_features[f_idx++] = logf(1.0f + (float)none_rdc->dist);
simple_motion_features[f_idx++] = logf(1.0f + (float)none_rdc->rdcost);
features[f_idx++] = logf(1.0f + (float)none_rdc->rate);
features[f_idx++] = logf(1.0f + (float)none_rdc->dist);
features[f_idx++] = logf(1.0f + (float)none_rdc->rdcost);
assert(f_idx == FEATURE_SIZE_SMS_TERM_NONE);
@ -441,8 +424,8 @@ void av1_simple_motion_search_early_term_none(
if (ml_model) {
float score = 0.0f;
for (f_idx = 0; f_idx < FEATURE_SIZE_SMS_TERM_NONE; f_idx++) {
score += ml_model[f_idx] *
(simple_motion_features[f_idx] - ml_mean[f_idx]) / ml_std[f_idx];
score +=
ml_model[f_idx] * (features[f_idx] - ml_mean[f_idx]) / ml_std[f_idx];
}
score += ml_model[FEATURE_SIZE_SMS_TERM_NONE];
@ -720,3 +703,584 @@ BLOCK_SIZE av1_predict_max_partition(AV1_COMP *const cpi, MACROBLOCK *const x,
return (BLOCK_SIZE)((result + 2) * 3);
}
// Get the minimum partition block width and height(in log scale) under a
// PC_TREE.
static void get_min_bsize(const PC_TREE *pc_tree, int *min_bw, int *min_bh) {
if (!pc_tree) return;
const BLOCK_SIZE bsize = pc_tree->block_size;
if (bsize == BLOCK_4X4) {
*min_bw = 0;
*min_bh = 0;
return;
}
PARTITION_TYPE part_type = pc_tree->partitioning;
if (part_type == PARTITION_INVALID) return;
if (part_type == PARTITION_SPLIT) {
for (int i = 0; i < 4; ++i) {
get_min_bsize(pc_tree->split[i], min_bw, min_bh);
}
} else {
if (part_type == PARTITION_HORZ_A || part_type == PARTITION_HORZ_B ||
part_type == PARTITION_VERT_A || part_type == PARTITION_VERT_B)
part_type = PARTITION_SPLIT;
const BLOCK_SIZE subsize = get_partition_subsize(bsize, part_type);
if (subsize != BLOCK_INVALID) {
*min_bw = AOMMIN(*min_bw, mi_size_wide_log2[subsize]);
*min_bh = AOMMIN(*min_bh, mi_size_high_log2[subsize]);
}
}
}
static INLINE void add_rd_feature(int64_t rd, int64_t best_rd, float *features,
int *feature_idx) {
const int rd_valid = rd > 0 && rd < INT64_MAX;
const float rd_ratio = rd_valid ? (float)rd / best_rd : 1.0f;
features[(*feature_idx)++] = (float)rd_valid;
features[(*feature_idx)++] = rd_ratio;
}
#define FEATURES 31
void av1_ml_early_term_after_split(AV1_COMP *const cpi, MACROBLOCK *const x,
PC_TREE *const pc_tree, BLOCK_SIZE bsize,
int64_t best_rd, int64_t part_none_rd,
int64_t part_split_rd,
int64_t *split_block_rd, int mi_row,
int mi_col,
int *const terminate_partition_search) {
if (best_rd <= 0 || best_rd == INT64_MAX || *terminate_partition_search)
return;
const AV1_COMMON *const cm = &cpi->common;
const int is_480p_or_larger = AOMMIN(cm->width, cm->height) >= 480;
const NN_CONFIG *nn_config = NULL;
float thresh = -1e6;
switch (bsize) {
case BLOCK_128X128: break;
case BLOCK_64X64:
nn_config = &av1_early_term_after_split_nnconfig_64;
thresh = is_480p_or_larger ? -2.0f : -1.2f;
break;
case BLOCK_32X32:
nn_config = &av1_early_term_after_split_nnconfig_32;
thresh = is_480p_or_larger ? -2.6f : -2.3f;
break;
case BLOCK_16X16:
nn_config = &av1_early_term_after_split_nnconfig_16;
thresh = is_480p_or_larger ? -2.0f : -2.4f;
break;
case BLOCK_8X8:
nn_config = &av1_early_term_after_split_nnconfig_8;
thresh = is_480p_or_larger ? -1.0f : -1.4f;
break;
case BLOCK_4X4: break;
default:
assert(0 && "Invalid block size in av1_ml_early_term_after_split().");
break;
}
if (!nn_config) return;
// Use more conservative threshold for level 1.
if (cpi->sf.ml_early_term_after_part_split_level < 2) thresh -= 0.3f;
const MACROBLOCKD *const xd = &x->e_mbd;
const int dc_q = av1_dc_quant_QTX(x->qindex, 0, xd->bd) >> (xd->bd - 8);
const int bs = block_size_wide[bsize];
int f_idx = 0;
float features[FEATURES] = { 0.0f };
aom_clear_system_state();
features[f_idx++] = logf(1.0f + (float)dc_q / 4.0f);
features[f_idx++] = logf(1.0f + (float)best_rd / bs / bs / 1024.0f);
add_rd_feature(part_none_rd, best_rd, features, &f_idx);
add_rd_feature(part_split_rd, best_rd, features, &f_idx);
for (int i = 0; i < 4; ++i) {
add_rd_feature(split_block_rd[i], best_rd, features, &f_idx);
int min_bw = MAX_SB_SIZE_LOG2;
int min_bh = MAX_SB_SIZE_LOG2;
get_min_bsize(pc_tree->split[i], &min_bw, &min_bh);
features[f_idx++] = (float)min_bw;
features[f_idx++] = (float)min_bh;
}
simple_motion_search_prune_part_features(cpi, x, pc_tree, mi_row, mi_col,
bsize, NULL,
FEATURE_SMS_PRUNE_PART_FLAG);
features[f_idx++] = logf(1.0f + (float)pc_tree->sms_none_feat[1]);
features[f_idx++] = logf(1.0f + (float)pc_tree->sms_split_feat[1]);
features[f_idx++] = logf(1.0f + (float)pc_tree->sms_split_feat[3]);
features[f_idx++] = logf(1.0f + (float)pc_tree->sms_split_feat[5]);
features[f_idx++] = logf(1.0f + (float)pc_tree->sms_split_feat[7]);
features[f_idx++] = logf(1.0f + (float)pc_tree->sms_rect_feat[1]);
features[f_idx++] = logf(1.0f + (float)pc_tree->sms_rect_feat[3]);
features[f_idx++] = logf(1.0f + (float)pc_tree->sms_rect_feat[5]);
features[f_idx++] = logf(1.0f + (float)pc_tree->sms_rect_feat[7]);
assert(f_idx == FEATURES);
float score = 0.0f;
av1_nn_predict(features, nn_config, &score);
// Score is indicator of confidence that we should NOT terminate.
if (score < thresh) *terminate_partition_search = 1;
}
#undef FEATURES
#define FEATURE_SIZE 19
int av1_ml_prune_2pass_split_partition(const PC_TREE_STATS *pc_tree_stats,
BLOCK_SIZE bsize, int *split_score,
int *none_score) {
if (!pc_tree_stats->valid) return 0;
const float *split_weights = NULL;
const float *none_weights = NULL;
switch (bsize) {
case BLOCK_4X4: break;
case BLOCK_8X8:
split_weights = av1_2pass_split_partition_weights_8;
none_weights = av1_2pass_none_partition_weights_8;
break;
case BLOCK_16X16:
split_weights = av1_2pass_split_partition_weights_16;
none_weights = av1_2pass_none_partition_weights_16;
break;
case BLOCK_32X32:
split_weights = av1_2pass_split_partition_weights_32;
none_weights = av1_2pass_none_partition_weights_32;
break;
case BLOCK_64X64:
split_weights = av1_2pass_split_partition_weights_64;
none_weights = av1_2pass_none_partition_weights_64;
break;
case BLOCK_128X128:
split_weights = av1_2pass_split_partition_weights_128;
none_weights = av1_2pass_none_partition_weights_128;
break;
default: assert(0 && "Unexpected bsize.");
}
if (!split_weights || !none_weights) return 0;
aom_clear_system_state();
float features[FEATURE_SIZE];
int feature_index = 0;
features[feature_index++] = (float)pc_tree_stats->split;
features[feature_index++] = (float)pc_tree_stats->skip;
const int rdcost = (int)AOMMIN(INT_MAX, pc_tree_stats->rdcost);
const int rd_valid = rdcost > 0 && rdcost < 1000000000;
features[feature_index++] = (float)rd_valid;
for (int i = 0; i < 4; ++i) {
features[feature_index++] = (float)pc_tree_stats->sub_block_split[i];
features[feature_index++] = (float)pc_tree_stats->sub_block_skip[i];
const int sub_rdcost =
(int)AOMMIN(INT_MAX, pc_tree_stats->sub_block_rdcost[i]);
const int sub_rd_valid = sub_rdcost > 0 && sub_rdcost < 1000000000;
features[feature_index++] = (float)sub_rd_valid;
// Ratio between the sub-block RD and the whole-block RD.
float rd_ratio = 1.0f;
if (rd_valid && sub_rd_valid && sub_rdcost < rdcost)
rd_ratio = (float)sub_rdcost / (float)rdcost;
features[feature_index++] = rd_ratio;
}
assert(feature_index == FEATURE_SIZE);
float score_1 = split_weights[FEATURE_SIZE];
float score_2 = none_weights[FEATURE_SIZE];
for (int i = 0; i < FEATURE_SIZE; ++i) {
score_1 += features[i] * split_weights[i];
score_2 += features[i] * none_weights[i];
}
*split_score = (int)(score_1 * 100);
*none_score = (int)(score_2 * 100);
return 1;
}
#undef FEATURE_SIZE
void av1_ml_prune_rect_partition(const AV1_COMP *const cpi,
const MACROBLOCK *const x, BLOCK_SIZE bsize,
int64_t best_rd, int64_t none_rd,
int64_t *split_rd, int *const dst_prune_horz,
int *const dst_prune_vert) {
if (bsize < BLOCK_8X8 || best_rd >= 1000000000) return;
best_rd = AOMMAX(best_rd, 1);
const NN_CONFIG *nn_config = NULL;
const float prob_thresholds[5] = { 0.01f, 0.01f, 0.004f, 0.002f, 0.002f };
float cur_thresh = 0.0f;
switch (bsize) {
case BLOCK_8X8:
nn_config = &av1_rect_partition_nnconfig_8;
cur_thresh = prob_thresholds[0];
break;
case BLOCK_16X16:
nn_config = &av1_rect_partition_nnconfig_16;
cur_thresh = prob_thresholds[1];
break;
case BLOCK_32X32:
nn_config = &av1_rect_partition_nnconfig_32;
cur_thresh = prob_thresholds[2];
break;
case BLOCK_64X64:
nn_config = &av1_rect_partition_nnconfig_64;
cur_thresh = prob_thresholds[3];
break;
case BLOCK_128X128:
nn_config = &av1_rect_partition_nnconfig_128;
cur_thresh = prob_thresholds[4];
break;
default: assert(0 && "Unexpected bsize.");
}
if (!nn_config) return;
aom_clear_system_state();
// 1. Compute input features
float features[9];
// RD cost ratios
for (int i = 0; i < 5; i++) features[i] = 1.0f;
if (none_rd > 0 && none_rd < 1000000000)
features[0] = (float)none_rd / (float)best_rd;
for (int i = 0; i < 4; i++) {
if (split_rd[i] > 0 && split_rd[i] < 1000000000)
features[1 + i] = (float)split_rd[i] / (float)best_rd;
}
// Variance ratios
const MACROBLOCKD *const xd = &x->e_mbd;
int whole_block_variance;
if (is_cur_buf_hbd(xd)) {
whole_block_variance = av1_high_get_sby_perpixel_variance(
cpi, &x->plane[0].src, bsize, xd->bd);
} else {
whole_block_variance =
av1_get_sby_perpixel_variance(cpi, &x->plane[0].src, bsize);
}
whole_block_variance = AOMMAX(whole_block_variance, 1);
int split_variance[4];
const BLOCK_SIZE subsize = get_partition_subsize(bsize, PARTITION_SPLIT);
struct buf_2d buf;
buf.stride = x->plane[0].src.stride;
const int bw = block_size_wide[bsize];
for (int i = 0; i < 4; ++i) {
const int x_idx = (i & 1) * bw / 2;
const int y_idx = (i >> 1) * bw / 2;
buf.buf = x->plane[0].src.buf + x_idx + y_idx * buf.stride;
if (is_cur_buf_hbd(xd)) {
split_variance[i] =
av1_high_get_sby_perpixel_variance(cpi, &buf, subsize, xd->bd);
} else {
split_variance[i] = av1_get_sby_perpixel_variance(cpi, &buf, subsize);
}
}
for (int i = 0; i < 4; i++)
features[5 + i] = (float)split_variance[i] / (float)whole_block_variance;
// 2. Do the prediction and prune 0-2 partitions based on their probabilities
float raw_scores[3] = { 0.0f };
av1_nn_predict(features, nn_config, raw_scores);
aom_clear_system_state();
float probs[3] = { 0.0f };
av1_nn_softmax(raw_scores, probs, 3);
// probs[0] is the probability of the fact that both rectangular partitions
// are worse than current best_rd
if (probs[1] <= cur_thresh) (*dst_prune_horz) = 1;
if (probs[2] <= cur_thresh) (*dst_prune_vert) = 1;
}
// Use a ML model to predict if horz_a, horz_b, vert_a, and vert_b should be
// considered.
void av1_ml_prune_ab_partition(BLOCK_SIZE bsize, int part_ctx, int var_ctx,
int64_t best_rd, int64_t horz_rd[2],
int64_t vert_rd[2], int64_t split_rd[4],
int *const horza_partition_allowed,
int *const horzb_partition_allowed,
int *const verta_partition_allowed,
int *const vertb_partition_allowed) {
if (bsize < BLOCK_8X8 || best_rd >= 1000000000) return;
const NN_CONFIG *nn_config = NULL;
switch (bsize) {
case BLOCK_8X8: nn_config = NULL; break;
case BLOCK_16X16: nn_config = &av1_ab_partition_nnconfig_16; break;
case BLOCK_32X32: nn_config = &av1_ab_partition_nnconfig_32; break;
case BLOCK_64X64: nn_config = &av1_ab_partition_nnconfig_64; break;
case BLOCK_128X128: nn_config = &av1_ab_partition_nnconfig_128; break;
default: assert(0 && "Unexpected bsize.");
}
if (!nn_config) return;
aom_clear_system_state();
// Generate features.
float features[10];
int feature_index = 0;
features[feature_index++] = (float)part_ctx;
features[feature_index++] = (float)var_ctx;
const int rdcost = (int)AOMMIN(INT_MAX, best_rd);
int sub_block_rdcost[8] = { 0 };
int rd_index = 0;
for (int i = 0; i < 2; ++i) {
if (horz_rd[i] > 0 && horz_rd[i] < 1000000000)
sub_block_rdcost[rd_index] = (int)horz_rd[i];
++rd_index;
}
for (int i = 0; i < 2; ++i) {
if (vert_rd[i] > 0 && vert_rd[i] < 1000000000)
sub_block_rdcost[rd_index] = (int)vert_rd[i];
++rd_index;
}
for (int i = 0; i < 4; ++i) {
if (split_rd[i] > 0 && split_rd[i] < 1000000000)
sub_block_rdcost[rd_index] = (int)split_rd[i];
++rd_index;
}
for (int i = 0; i < 8; ++i) {
// Ratio between the sub-block RD and the whole-block RD.
float rd_ratio = 1.0f;
if (sub_block_rdcost[i] > 0 && sub_block_rdcost[i] < rdcost)
rd_ratio = (float)sub_block_rdcost[i] / (float)rdcost;
features[feature_index++] = rd_ratio;
}
assert(feature_index == 10);
// Calculate scores using the NN model.
float score[16] = { 0.0f };
av1_nn_predict(features, nn_config, score);
aom_clear_system_state();
int int_score[16];
int max_score = -1000;
for (int i = 0; i < 16; ++i) {
int_score[i] = (int)(100 * score[i]);
max_score = AOMMAX(int_score[i], max_score);
}
// Make decisions based on the model scores.
int thresh = max_score;
switch (bsize) {
case BLOCK_16X16: thresh -= 150; break;
case BLOCK_32X32: thresh -= 100; break;
default: break;
}
*horza_partition_allowed = 0;
*horzb_partition_allowed = 0;
*verta_partition_allowed = 0;
*vertb_partition_allowed = 0;
for (int i = 0; i < 16; ++i) {
if (int_score[i] >= thresh) {
if ((i >> 0) & 1) *horza_partition_allowed = 1;
if ((i >> 1) & 1) *horzb_partition_allowed = 1;
if ((i >> 2) & 1) *verta_partition_allowed = 1;
if ((i >> 3) & 1) *vertb_partition_allowed = 1;
}
}
}
#define FEATURES 18
#define LABELS 4
// Use a ML model to predict if horz4 and vert4 should be considered.
void av1_ml_prune_4_partition(const AV1_COMP *const cpi, MACROBLOCK *const x,
BLOCK_SIZE bsize, int part_ctx, int64_t best_rd,
int64_t horz_rd[2], int64_t vert_rd[2],
int64_t split_rd[4],
int *const partition_horz4_allowed,
int *const partition_vert4_allowed,
unsigned int pb_source_variance, int mi_row,
int mi_col) {
if (best_rd >= 1000000000) return;
const NN_CONFIG *nn_config = NULL;
switch (bsize) {
case BLOCK_16X16: nn_config = &av1_4_partition_nnconfig_16; break;
case BLOCK_32X32: nn_config = &av1_4_partition_nnconfig_32; break;
case BLOCK_64X64: nn_config = &av1_4_partition_nnconfig_64; break;
default: assert(0 && "Unexpected bsize.");
}
if (!nn_config) return;
aom_clear_system_state();
// Generate features.
float features[FEATURES];
int feature_index = 0;
features[feature_index++] = (float)part_ctx;
features[feature_index++] = (float)get_unsigned_bits(pb_source_variance);
const int rdcost = (int)AOMMIN(INT_MAX, best_rd);
int sub_block_rdcost[8] = { 0 };
int rd_index = 0;
for (int i = 0; i < 2; ++i) {
if (horz_rd[i] > 0 && horz_rd[i] < 1000000000)
sub_block_rdcost[rd_index] = (int)horz_rd[i];
++rd_index;
}
for (int i = 0; i < 2; ++i) {
if (vert_rd[i] > 0 && vert_rd[i] < 1000000000)
sub_block_rdcost[rd_index] = (int)vert_rd[i];
++rd_index;
}
for (int i = 0; i < 4; ++i) {
if (split_rd[i] > 0 && split_rd[i] < 1000000000)
sub_block_rdcost[rd_index] = (int)split_rd[i];
++rd_index;
}
for (int i = 0; i < 8; ++i) {
// Ratio between the sub-block RD and the whole-block RD.
float rd_ratio = 1.0f;
if (sub_block_rdcost[i] > 0 && sub_block_rdcost[i] < rdcost)
rd_ratio = (float)sub_block_rdcost[i] / (float)rdcost;
features[feature_index++] = rd_ratio;
}
// Get variance of the 1:4 and 4:1 sub-blocks.
unsigned int horz_4_source_var[4] = { 0 };
unsigned int vert_4_source_var[4] = { 0 };
{
BLOCK_SIZE horz_4_bs = get_partition_subsize(bsize, PARTITION_HORZ_4);
BLOCK_SIZE vert_4_bs = get_partition_subsize(bsize, PARTITION_VERT_4);
av1_setup_src_planes(x, cpi->source, mi_row, mi_col,
av1_num_planes(&cpi->common), bsize);
const int src_stride = x->plane[0].src.stride;
uint8_t *src = x->plane[0].src.buf;
const MACROBLOCKD *const xd = &x->e_mbd;
struct buf_2d horz_4_src, vert_4_src;
horz_4_src.stride = src_stride;
vert_4_src.stride = src_stride;
for (int i = 0; i < 4; ++i) {
horz_4_src.buf = src + i * block_size_high[horz_4_bs] * src_stride;
vert_4_src.buf = src + i * block_size_wide[vert_4_bs];
if (is_cur_buf_hbd(xd)) {
horz_4_source_var[i] = av1_high_get_sby_perpixel_variance(
cpi, &horz_4_src, horz_4_bs, xd->bd);
vert_4_source_var[i] = av1_high_get_sby_perpixel_variance(
cpi, &vert_4_src, vert_4_bs, xd->bd);
} else {
horz_4_source_var[i] =
av1_get_sby_perpixel_variance(cpi, &horz_4_src, horz_4_bs);
vert_4_source_var[i] =
av1_get_sby_perpixel_variance(cpi, &vert_4_src, vert_4_bs);
}
}
}
const float denom = (float)(pb_source_variance + 1);
const float low_b = 0.1f;
const float high_b = 10.0f;
for (int i = 0; i < 4; ++i) {
// Ratio between the 4:1 sub-block variance and the whole-block variance.
float var_ratio = (float)(horz_4_source_var[i] + 1) / denom;
if (var_ratio < low_b) var_ratio = low_b;
if (var_ratio > high_b) var_ratio = high_b;
features[feature_index++] = var_ratio;
}
for (int i = 0; i < 4; ++i) {
// Ratio between the 1:4 sub-block RD and the whole-block RD.
float var_ratio = (float)(vert_4_source_var[i] + 1) / denom;
if (var_ratio < low_b) var_ratio = low_b;
if (var_ratio > high_b) var_ratio = high_b;
features[feature_index++] = var_ratio;
}
assert(feature_index == FEATURES);
// Calculate scores using the NN model.
float score[LABELS] = { 0.0f };
av1_nn_predict(features, nn_config, score);
aom_clear_system_state();
int int_score[LABELS];
int max_score = -1000;
for (int i = 0; i < LABELS; ++i) {
int_score[i] = (int)(100 * score[i]);
max_score = AOMMAX(int_score[i], max_score);
}
// Make decisions based on the model scores.
int thresh = max_score;
switch (bsize) {
case BLOCK_16X16: thresh -= 500; break;
case BLOCK_32X32: thresh -= 500; break;
case BLOCK_64X64: thresh -= 200; break;
default: break;
}
*partition_horz4_allowed = 0;
*partition_vert4_allowed = 0;
for (int i = 0; i < LABELS; ++i) {
if (int_score[i] >= thresh) {
if ((i >> 0) & 1) *partition_horz4_allowed = 1;
if ((i >> 1) & 1) *partition_vert4_allowed = 1;
}
}
}
#undef FEATURES
#undef LABELS
#define FEATURES 4
int av1_ml_predict_breakout(const AV1_COMP *const cpi, BLOCK_SIZE bsize,
const MACROBLOCK *const x,
const RD_STATS *const rd_stats,
unsigned int pb_source_variance) {
const NN_CONFIG *nn_config = NULL;
int thresh = 0;
switch (bsize) {
case BLOCK_8X8:
nn_config = &av1_partition_breakout_nnconfig_8;
thresh = cpi->sf.ml_partition_search_breakout_thresh[0];
break;
case BLOCK_16X16:
nn_config = &av1_partition_breakout_nnconfig_16;
thresh = cpi->sf.ml_partition_search_breakout_thresh[1];
break;
case BLOCK_32X32:
nn_config = &av1_partition_breakout_nnconfig_32;
thresh = cpi->sf.ml_partition_search_breakout_thresh[2];
break;
case BLOCK_64X64:
nn_config = &av1_partition_breakout_nnconfig_64;
thresh = cpi->sf.ml_partition_search_breakout_thresh[3];
break;
case BLOCK_128X128:
nn_config = &av1_partition_breakout_nnconfig_128;
thresh = cpi->sf.ml_partition_search_breakout_thresh[4];
break;
default: assert(0 && "Unexpected bsize.");
}
if (!nn_config || thresh < 0) return 0;
// Generate feature values.
float features[FEATURES];
int feature_index = 0;
aom_clear_system_state();
const int num_pels_log2 = num_pels_log2_lookup[bsize];
float rate_f = (float)AOMMIN(rd_stats->rate, INT_MAX);
rate_f = ((float)x->rdmult / 128.0f / 512.0f / (float)(1 << num_pels_log2)) *
rate_f;
features[feature_index++] = rate_f;
const float dist_f =
(float)(AOMMIN(rd_stats->dist, INT_MAX) >> num_pels_log2);
features[feature_index++] = dist_f;
features[feature_index++] = (float)pb_source_variance;
const int dc_q = (int)x->plane[0].dequant_QTX[0];
features[feature_index++] = (float)(dc_q * dc_q) / 256.0f;
assert(feature_index == FEATURES);
// Calculate score using the NN model.
float score = 0.0f;
av1_nn_predict(features, nn_config, &score);
aom_clear_system_state();
// Make decision.
return (int)(score * 100) >= thresh;
}
#undef FEATURES

View file

@ -16,20 +16,31 @@
#include "av1/encoder/encodemb.h"
#include "av1/encoder/encoder.h"
#define FEATURE_SIZE_SMS_SPLIT_FAST 6
#define FEATURE_SIZE_SMS_SPLIT 17
#define FEATURE_SIZE_SMS_PRUNE_PART 25
#define FEATURE_SIZE_SMS_TERM_NONE 28
#define FEATURE_SIZE_FP_SMS_TERM_NONE 20
#define FEATURE_SIZE_MAX_MIN_PART_PRED 13
#define MAX_NUM_CLASSES_MAX_MIN_PART_PRED 4
#define FEATURE_SMS_NONE_FLAG 1
#define FEATURE_SMS_SPLIT_FLAG (1 << 1)
#define FEATURE_SMS_RECT_FLAG (1 << 2)
#define FEATURE_SMS_PRUNE_PART_FLAG \
(FEATURE_SMS_NONE_FLAG | FEATURE_SMS_SPLIT_FLAG | FEATURE_SMS_RECT_FLAG)
#define FEATURE_SMS_SPLIT_MODEL_FLAG \
(FEATURE_SMS_NONE_FLAG | FEATURE_SMS_SPLIT_FLAG)
// Performs a simple_motion_search with a single reference frame and extract
// the variance of residues. Then use the features to determine whether we want
// to go straight to splitting without trying PARTITION_NONE
void av1_simple_motion_search_based_split(
AV1_COMP *const cpi, MACROBLOCK *x, int mi_row, int mi_col,
BLOCK_SIZE bsize, int *partition_none_allowed, int *partition_horz_allowed,
int *partition_vert_allowed, int *do_rectangular_split,
int *do_square_split);
AV1_COMP *const cpi, MACROBLOCK *x, PC_TREE *pc_tree, int mi_row,
int mi_col, BLOCK_SIZE bsize, int *partition_none_allowed,
int *partition_horz_allowed, int *partition_vert_allowed,
int *do_rectangular_split, int *do_square_split);
// Performs a simple_motion_search with two reference frames and extract
// the variance of residues. Then use the features to determine whether we want
@ -39,7 +50,7 @@ void av1_simple_motion_search_prune_part(
int mi_col, BLOCK_SIZE bsize, int *partition_none_allowed,
int *partition_horz_allowed, int *partition_vert_allowed,
int *do_square_split, int *do_rectangular_split, int *prune_horz,
int *prune_vert, float *features, int *valid);
int *prune_vert);
// Early terminates PARTITION_NONE using simple_motion_search features and the
// rate, distortion, and rdcost of PARTITION_NONE. This is only called when:
@ -47,11 +58,12 @@ void av1_simple_motion_search_prune_part(
// - The frame is not intra only
// - The current bsize is > BLOCK_8X8
// - blk_row + blk_height/2 < total_rows and blk_col + blk_width/2 < total_cols
void av1_simple_motion_search_early_term_none(
AV1_COMP *const cpi, MACROBLOCK *x, PC_TREE *pc_tree, int mi_row,
int mi_col, BLOCK_SIZE bsize, const RD_STATS *none_rdc,
int *early_terminate, float *simple_motion_features,
int *simple_motion_features_are_valid);
void av1_simple_motion_search_early_term_none(AV1_COMP *const cpi,
MACROBLOCK *x, PC_TREE *pc_tree,
int mi_row, int mi_col,
BLOCK_SIZE bsize,
const RD_STATS *none_rdc,
int *early_terminate);
// Early terminates after PARTITION_NONE in firstpass of two pass partition
// search.
@ -73,6 +85,61 @@ void av1_get_max_min_partition_features(AV1_COMP *const cpi, MACROBLOCK *x,
BLOCK_SIZE av1_predict_max_partition(AV1_COMP *const cpi, MACROBLOCK *const x,
const float *features);
// Attempts an early termination after PARTITION_SPLIT.
void av1_ml_early_term_after_split(AV1_COMP *const cpi, MACROBLOCK *const x,
PC_TREE *const pc_tree, BLOCK_SIZE bsize,
int64_t best_rd, int64_t part_none_rd,
int64_t part_split_rd,
int64_t *split_block_rd, int mi_row,
int mi_col,
int *const terminate_partition_search);
// Use data from first partition pass to emit split_scores and none_scores.
// Returns 0 if the firstpass data is not valid, 1 otherwise.
// split_score indicates confidence of picking split partition;
// none_score indicates confidence of picking none partition;
int av1_ml_prune_2pass_split_partition(const PC_TREE_STATS *pc_tree_stats,
BLOCK_SIZE bsize, int *split_score,
int *none_score);
// Use the rdcost ratio and source var ratio to prune PARTITION_HORZ and
// PARTITION_VERT.
// TODO(chiyotsai@google.com): Currently this model does not use q value and has
// no information about rectangular partitions. Preliminary experiments suggest
// that we can get better performance by adding in q_index and rectangular
// sse/var from SMS. We should retrain and tune this model later.
void av1_ml_prune_rect_partition(const AV1_COMP *const cpi,
const MACROBLOCK *const x, BLOCK_SIZE bsize,
int64_t best_rd, int64_t none_rd,
int64_t *split_rd, int *const dst_prune_horz,
int *const dst_prune_vert);
// Use a ML model to predict if horz_a, horz_b, vert_a, and vert_b should be
// considered.
void av1_ml_prune_ab_partition(BLOCK_SIZE bsize, int part_ctx, int var_ctx,
int64_t best_rd, int64_t horz_rd[2],
int64_t vert_rd[2], int64_t split_rd[4],
int *const horza_partition_allowed,
int *const horzb_partition_allowed,
int *const verta_partition_allowed,
int *const vertb_partition_allowed);
// Use a ML model to predict if horz4 and vert4 should be considered.
void av1_ml_prune_4_partition(const AV1_COMP *const cpi, MACROBLOCK *const x,
BLOCK_SIZE bsize, int part_ctx, int64_t best_rd,
int64_t horz_rd[2], int64_t vert_rd[2],
int64_t split_rd[4],
int *const partition_horz4_allowed,
int *const partition_vert4_allowed,
unsigned int pb_source_variance, int mi_row,
int mi_col);
// ML-based partition search breakout after PARTITION_NONE
int av1_ml_predict_breakout(const AV1_COMP *const cpi, BLOCK_SIZE bsize,
const MACROBLOCK *const x,
const RD_STATS *const rd_stats,
unsigned int pb_source_variance);
// A simplified version of set_offsets meant to be used for
// simple_motion_search.
static INLINE void set_offsets_for_motion_search(const AV1_COMP *const cpi,
@ -116,10 +183,15 @@ static INLINE void set_offsets_for_motion_search(const AV1_COMP *const cpi,
}
static INLINE void init_simple_motion_search_mvs(PC_TREE *pc_tree) {
for (int idx = 0; idx < REF_FRAMES; idx++) {
pc_tree->mv_ref_fulls[idx].row = 0;
pc_tree->mv_ref_fulls[idx].col = 0;
}
av1_zero(pc_tree->mv_ref_fulls);
av1_zero(pc_tree->sms_none_feat);
av1_zero(pc_tree->sms_split_feat);
av1_zero(pc_tree->sms_rect_feat);
av1_zero(pc_tree->sms_none_valid);
av1_zero(pc_tree->sms_split_valid);
av1_zero(pc_tree->sms_rect_valid);
if (pc_tree->block_size >= BLOCK_8X8) {
init_simple_motion_search_mvs(pc_tree->split[0]);
init_simple_motion_search_mvs(pc_tree->split[1]);

View file

@ -57,7 +57,7 @@ static int64_t try_filter_frame(const YV12_BUFFER_CONFIG *sd,
if (plane == 0 && dir == 0) filter_level[1] = cm->lf.filter_level[1];
if (plane == 0 && dir == 1) filter_level[0] = cm->lf.filter_level[0];
// set base filters for use of get_filter_level when in DELTA_Q_LF mode
// set base filters for use of get_filter_level when in DELTA_LF mode
switch (plane) {
case 0:
cm->lf.filter_level[0] = filter_level[0];

View file

@ -1191,18 +1191,24 @@ static void search_wiener(const RestorationTileLimits *limits,
const int wiener_win =
(rsc->plane == AOM_PLANE_Y) ? WIENER_WIN : WIENER_WIN_CHROMA;
int reduced_wiener_win = wiener_win;
if (rsc->sf->reduce_wiener_window_size) {
reduced_wiener_win =
(rsc->plane == AOM_PLANE_Y) ? WIENER_WIN_REDUCED : WIENER_WIN_CHROMA;
}
int64_t M[WIENER_WIN2];
int64_t H[WIENER_WIN2 * WIENER_WIN2];
int32_t vfilter[WIENER_WIN], hfilter[WIENER_WIN];
const AV1_COMMON *const cm = rsc->cm;
if (cm->seq_params.use_highbitdepth) {
av1_compute_stats_highbd(wiener_win, rsc->dgd_buffer, rsc->src_buffer,
limits->h_start, limits->h_end, limits->v_start,
limits->v_end, rsc->dgd_stride, rsc->src_stride, M,
H, cm->seq_params.bit_depth);
av1_compute_stats_highbd(reduced_wiener_win, rsc->dgd_buffer,
rsc->src_buffer, limits->h_start, limits->h_end,
limits->v_start, limits->v_end, rsc->dgd_stride,
rsc->src_stride, M, H, cm->seq_params.bit_depth);
} else {
av1_compute_stats(wiener_win, rsc->dgd_buffer, rsc->src_buffer,
av1_compute_stats(reduced_wiener_win, rsc->dgd_buffer, rsc->src_buffer,
limits->h_start, limits->h_end, limits->v_start,
limits->v_end, rsc->dgd_stride, rsc->src_stride, M, H);
}
@ -1210,7 +1216,7 @@ static void search_wiener(const RestorationTileLimits *limits,
const MACROBLOCK *const x = rsc->x;
const int64_t bits_none = x->wiener_restore_cost[0];
if (!wiener_decompose_sep_sym(wiener_win, M, H, vfilter, hfilter)) {
if (!wiener_decompose_sep_sym(reduced_wiener_win, M, H, vfilter, hfilter)) {
rsc->bits += bits_none;
rsc->sse += rusi->sse[RESTORE_NONE];
rusi->best_rtype[RESTORE_WIENER - 1] = RESTORE_NONE;
@ -1221,13 +1227,13 @@ static void search_wiener(const RestorationTileLimits *limits,
RestorationUnitInfo rui;
memset(&rui, 0, sizeof(rui));
rui.restoration_type = RESTORE_WIENER;
finalize_sym_filter(wiener_win, vfilter, rui.wiener_info.vfilter);
finalize_sym_filter(wiener_win, hfilter, rui.wiener_info.hfilter);
finalize_sym_filter(reduced_wiener_win, vfilter, rui.wiener_info.vfilter);
finalize_sym_filter(reduced_wiener_win, hfilter, rui.wiener_info.hfilter);
// Filter score computes the value of the function x'*A*x - x'*b for the
// learned filter and compares it against identity filer. If there is no
// reduction in the function, the filter is reverted back to identity
if (compute_score(wiener_win, M, H, rui.wiener_info.vfilter,
if (compute_score(reduced_wiener_win, M, H, rui.wiener_info.vfilter,
rui.wiener_info.hfilter) > 0) {
rsc->bits += bits_none;
rsc->sse += rusi->sse[RESTORE_NONE];
@ -1238,11 +1244,11 @@ static void search_wiener(const RestorationTileLimits *limits,
aom_clear_system_state();
rusi->sse[RESTORE_WIENER] =
finer_tile_search_wiener(rsc, limits, tile_rect, &rui, wiener_win);
rusi->sse[RESTORE_WIENER] = finer_tile_search_wiener(
rsc, limits, tile_rect, &rui, reduced_wiener_win);
rusi->wiener = rui.wiener_info;
if (wiener_win != WIENER_WIN) {
if (reduced_wiener_win != WIENER_WIN) {
assert(rui.wiener_info.vfilter[0] == 0 &&
rui.wiener_info.vfilter[WIENER_WIN - 1] == 0);
assert(rui.wiener_info.hfilter[0] == 0 &&

View file

@ -43,8 +43,8 @@ static const float
-1.0533f, -0.3566f, 0.5294f, -0.4335f, 0.1626f,
};
static const float av1_pustats_rate_hiddenlayer_0_bias[HIDDEN_LAYERS_0_NODES] =
{
static const float
av1_pustats_rate_hiddenlayer_0_bias[HIDDEN_LAYERS_0_NODES] = {
10.5266f, 5.3268f, -1.0678f, 7.7411f, 8.7164f, -0.3235f,
7.3028f, 9.0874f, -6.4594f, -1.0102f, -1.1146f, 10.8419f,
};
@ -72,8 +72,8 @@ static const float
-2.7566f,
};
static const float av1_pustats_rate_hiddenlayer_1_bias[HIDDEN_LAYERS_1_NODES] =
{
static const float
av1_pustats_rate_hiddenlayer_1_bias[HIDDEN_LAYERS_1_NODES] = {
13.2435f, -8.5477f, -0.0998f, -1.5131f, -12.0187f,
6.1715f, 0.5094f, 7.6433f, -0.3992f, -1.3555f,
};
@ -124,8 +124,8 @@ static const float
-0.0806f, 0.5231f, 0.3928f, 0.4146f, 2.0956f,
};
static const float av1_pustats_dist_hiddenlayer_0_bias[HIDDEN_LAYERS_0_NODES] =
{
static const float
av1_pustats_dist_hiddenlayer_0_bias[HIDDEN_LAYERS_0_NODES] = {
1.1597f, 0.0836f, -0.7471f, -0.2439f, -0.0438f, 2.4626f,
0.f, 1.1485f, 2.7085f, -4.7897f, 1.4093f, -1.657f,
};
@ -153,8 +153,8 @@ static const float
-0.4164f,
};
static const float av1_pustats_dist_hiddenlayer_1_bias[HIDDEN_LAYERS_1_NODES] =
{
static const float
av1_pustats_dist_hiddenlayer_1_bias[HIDDEN_LAYERS_1_NODES] = {
-2.3014f, -2.4292f, 1.3317f, -3.2361f, -1.918f,
2.7149f, -2.5649f, 2.7765f, 2.9617f, 2.7684f,
};

View file

@ -265,8 +265,10 @@ static int find_rotzoom(int np, double *pts1, double *pts2, double *mat) {
}
static int find_affine(int np, double *pts1, double *pts2, double *mat) {
assert(np > 0);
const int np2 = np * 2;
double *a = (double *)aom_malloc(sizeof(*a) * (np2 * 7 + 42));
if (a == NULL) return 1;
double *b = a + np2 * 6;
double *temp = b + np2;
int i;

View file

@ -34,6 +34,8 @@
#include "av1/encoder/random.h"
#include "av1/encoder/ratectrl.h"
#define USE_UNRESTRICTED_Q_IN_CQ_MODE 0
// Max rate target for 1080P and below encodes under normal circumstances
// (1920 * 1080 / (16 * 16)) * MAX_MB_RATE bits per MB
#define MAX_MB_RATE 250
@ -1001,6 +1003,28 @@ int av1_frame_type_qdelta(const AV1_COMP *cpi, int q) {
cpi->common.seq_params.bit_depth);
}
// This unrestricted Q selection on CQ mode is useful when testing new features,
// but may lead to Q being out of range on current RC restrictions
#if USE_UNRESTRICTED_Q_IN_CQ_MODE
static int rc_pick_q_and_bounds_one_pass_cq(const AV1_COMP *cpi, int width,
int height, int *bottom_index,
int *top_index) {
const AV1_COMMON *const cm = &cpi->common;
const RATE_CONTROL *const rc = &cpi->rc;
const AV1EncoderConfig *const oxcf = &cpi->oxcf;
const int cq_level = get_active_cq_level(rc, oxcf, frame_is_intra_only(cm),
cm->superres_scale_denominator);
const int bit_depth = cm->seq_params.bit_depth;
const int q = (int)av1_convert_qindex_to_q(cq_level, bit_depth);
(void)width;
(void)height;
*top_index = q;
*bottom_index = q;
return q;
}
#endif // USE_UNRESTRICTED_Q_IN_CQ_MODE
#define STATIC_MOTION_THRESH 95
static int rc_pick_q_and_bounds_two_pass(const AV1_COMP *cpi, int width,
int height, int *bottom_index,
@ -1089,6 +1113,18 @@ static int rc_pick_q_and_bounds_two_pass(const AV1_COMP *cpi, int width,
q_val = av1_convert_qindex_to_q(active_best_quality, bit_depth);
active_best_quality +=
av1_compute_qdelta(rc, q_val, q_val * q_adj_factor, bit_depth);
// Tweak active_best_quality for AOM_Q mode when superres is on, as this
// will be used directly as 'q' later.
if (oxcf->rc_mode == AOM_Q &&
(oxcf->superres_mode == SUPERRES_QTHRESH ||
oxcf->superres_mode == SUPERRES_AUTO) &&
cm->superres_scale_denominator != SCALE_NUMERATOR) {
active_best_quality =
AOMMAX(active_best_quality -
((cm->superres_scale_denominator - SCALE_NUMERATOR) * 4),
0);
}
}
} else if (!rc->is_src_frame_alt_ref &&
(cpi->refresh_golden_frame || is_intrl_arf_boost ||
@ -1260,6 +1296,11 @@ int av1_rc_pick_q_and_bounds(AV1_COMP *cpi, int width, int height,
if (cpi->oxcf.rc_mode == AOM_CBR)
q = rc_pick_q_and_bounds_one_pass_cbr(cpi, width, height, bottom_index,
top_index);
#if USE_UNRESTRICTED_Q_IN_CQ_MODE
else if (cpi->oxcf.rc_mode == AOM_CQ)
q = rc_pick_q_and_bounds_one_pass_cq(cpi, width, height, bottom_index,
top_index);
#endif // USE_UNRESTRICTED_Q_IN_CQ_MODE
else
q = rc_pick_q_and_bounds_one_pass_vbr(cpi, width, height, bottom_index,
top_index);

View file

@ -52,20 +52,20 @@ static const uint8_t rd_thresh_block_size_factor[BLOCK_SIZES_ALL] = {
2, 3, 3, 4, 6, 6, 8, 12, 12, 16, 24, 24, 32, 48, 48, 64, 4, 4, 8, 8, 16, 16
};
static const int use_intra_ext_tx_for_txsize[EXT_TX_SETS_INTRA][EXT_TX_SIZES] =
{
{ 1, 1, 1, 1 }, // unused
{ 1, 1, 0, 0 },
{ 0, 0, 1, 0 },
};
static const int use_intra_ext_tx_for_txsize[EXT_TX_SETS_INTRA]
[EXT_TX_SIZES] = {
{ 1, 1, 1, 1 }, // unused
{ 1, 1, 0, 0 },
{ 0, 0, 1, 0 },
};
static const int use_inter_ext_tx_for_txsize[EXT_TX_SETS_INTER][EXT_TX_SIZES] =
{
{ 1, 1, 1, 1 }, // unused
{ 1, 1, 0, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 0, 1 },
};
static const int use_inter_ext_tx_for_txsize[EXT_TX_SETS_INTER]
[EXT_TX_SIZES] = {
{ 1, 1, 1, 1 }, // unused
{ 1, 1, 0, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 0, 1 },
};
static const int av1_ext_tx_set_idx_to_type[2][AOMMAX(EXT_TX_SETS_INTRA,
EXT_TX_SETS_INTER)] = {
@ -343,9 +343,9 @@ void av1_init_me_luts(void) {
static const int rd_boost_factor[16] = { 64, 32, 32, 32, 24, 16, 12, 12,
8, 8, 4, 4, 2, 2, 1, 0 };
static const int rd_frame_type_factor[FRAME_UPDATE_TYPES] = {
128, 144, 128, 128, 144, 144, 128
};
static const int rd_frame_type_factor[FRAME_UPDATE_TYPES] = { 128, 144, 128,
128, 144, 144,
128 };
int av1_compute_rd_mult_based_on_qindex(const AV1_COMP *cpi, int qindex) {
const int q = av1_dc_quant_Q3(qindex, 0, cpi->common.seq_params.bit_depth);
@ -795,9 +795,9 @@ static const double surffit_rate_params[9][4] = {
},
};
static const double surffit_dist_params[7] = {
1.475844, 4.328362, -5.680233, -0.500994, 0.554585, 4.839478, -0.695837
};
static const double surffit_dist_params[7] = { 1.475844, 4.328362, -5.680233,
-0.500994, 0.554585, 4.839478,
-0.695837 };
static void rate_surffit_model_params_lookup(BLOCK_SIZE bsize, double xm,
double *rpar) {
@ -958,6 +958,7 @@ void av1_get_entropy_contexts(BLOCK_SIZE bsize,
const struct macroblockd_plane *pd,
ENTROPY_CONTEXT t_above[MAX_MIB_SIZE],
ENTROPY_CONTEXT t_left[MAX_MIB_SIZE]) {
assert(bsize < BLOCK_SIZES_ALL);
const BLOCK_SIZE plane_bsize =
get_plane_block_size(bsize, pd->subsampling_x, pd->subsampling_y);
get_entropy_contexts_plane(plane_bsize, pd, t_above, t_left);

View file

@ -78,8 +78,8 @@ enum {
THR_GLOBALL3,
THR_GLOBALB,
THR_GLOBALA2,
THR_GLOBALA,
THR_GLOBALG,
THR_GLOBALA,
THR_COMP_NEAREST_NEARESTLA,
THR_COMP_NEAREST_NEARESTL2A,
@ -303,8 +303,6 @@ static INLINE void av1_init_rd_stats(RD_STATS *rd_stats) {
rd_stats->sse = 0;
rd_stats->skip = 1;
rd_stats->zero_rate = 0;
rd_stats->invalid_rate = 0;
rd_stats->ref_rdcost = INT64_MAX;
#if CONFIG_RD_DEBUG
// This may run into problems when monochrome video is
// encoded, as there will only be 1 plane
@ -330,8 +328,6 @@ static INLINE void av1_invalid_rd_stats(RD_STATS *rd_stats) {
rd_stats->sse = INT64_MAX;
rd_stats->skip = 0;
rd_stats->zero_rate = 0;
rd_stats->invalid_rate = 1;
rd_stats->ref_rdcost = INT64_MAX;
#if CONFIG_RD_DEBUG
// This may run into problems when monochrome video is
// encoded, as there will only be 1 plane
@ -349,20 +345,17 @@ static INLINE void av1_invalid_rd_stats(RD_STATS *rd_stats) {
static INLINE void av1_merge_rd_stats(RD_STATS *rd_stats_dst,
const RD_STATS *rd_stats_src) {
#if CONFIG_RD_DEBUG
int plane;
#endif
assert(rd_stats_dst->rate != INT_MAX && rd_stats_src->rate != INT_MAX);
rd_stats_dst->rate += rd_stats_src->rate;
if (!rd_stats_dst->zero_rate)
rd_stats_dst->zero_rate = rd_stats_src->zero_rate;
rd_stats_dst->dist += rd_stats_src->dist;
rd_stats_dst->sse += rd_stats_src->sse;
rd_stats_dst->skip &= rd_stats_src->skip;
rd_stats_dst->invalid_rate &= rd_stats_src->invalid_rate;
#if CONFIG_RD_DEBUG
// This may run into problems when monochrome video is
// encoded, as there will only be 1 plane
for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
for (int plane = 0; plane < MAX_MB_PLANE; ++plane) {
rd_stats_dst->txb_coeff_cost[plane] += rd_stats_src->txb_coeff_cost[plane];
{
// TODO(angiebird): optimize this part

View file

@ -2018,11 +2018,14 @@ static void model_rd_for_sb(const AV1_COMP *const cpi, BLOCK_SIZE bsize,
int64_t dist_sum = 0;
int64_t total_sse = 0;
assert(bsize < BLOCK_SIZES_ALL);
for (plane = plane_from; plane <= plane_to; ++plane) {
struct macroblock_plane *const p = &x->plane[plane];
struct macroblockd_plane *const pd = &xd->plane[plane];
const BLOCK_SIZE plane_bsize =
get_plane_block_size(bsize, pd->subsampling_x, pd->subsampling_y);
assert(plane_bsize < BLOCK_SIZES_ALL);
const int bw = block_size_wide[plane_bsize];
const int bh = block_size_high[plane_bsize];
int64_t sse;
@ -2187,8 +2190,13 @@ static INLINE int64_t pixel_diff_dist(const MACROBLOCK *x, int plane,
diff += ((blk_row * diff_stride + blk_col) << tx_size_wide_log2[0]);
uint64_t sse =
aom_sum_squares_2d_i16(diff, diff_stride, visible_cols, visible_rows);
if (block_mse_q8 != NULL)
*block_mse_q8 = (unsigned int)((256 * sse) / (visible_cols * visible_rows));
if (block_mse_q8 != NULL) {
if (visible_cols > 0 && visible_rows > 0)
*block_mse_q8 =
(unsigned int)((256 * sse) / (visible_cols * visible_rows));
else
*block_mse_q8 = UINT_MAX;
}
return sse;
}
@ -5181,8 +5189,6 @@ static void try_tx_block_no_split(
get_txb_ctx(plane_bsize, tx_size, 0, pta, ptl, &txb_ctx);
const int zero_blk_rate = x->coeff_costs[txs_ctx][PLANE_TYPE_Y]
.txb_skip_cost[txb_ctx.txb_skip_ctx][1];
rd_stats->ref_rdcost = ref_best_rd;
rd_stats->zero_rate = zero_blk_rate;
const int index = av1_get_txb_size_index(plane_bsize, blk_row, blk_col);
mbmi->inter_tx_size[index] = tx_size;
@ -5391,6 +5397,7 @@ static int64_t select_tx_size_and_type(const AV1_COMP *cpi, MACROBLOCK *x,
TXB_RD_INFO_NODE *rd_info_tree) {
MACROBLOCKD *const xd = &x->e_mbd;
assert(is_inter_block(xd->mi[0]));
assert(bsize < BLOCK_SIZES_ALL);
// TODO(debargha): enable this as a speed feature where the
// select_inter_block_yrd() function above will use a simplified search
@ -5410,6 +5417,7 @@ static int64_t select_tx_size_and_type(const AV1_COMP *cpi, MACROBLOCK *x,
const struct macroblockd_plane *const pd = &xd->plane[0];
const BLOCK_SIZE plane_bsize =
get_plane_block_size(bsize, pd->subsampling_x, pd->subsampling_y);
assert(plane_bsize < BLOCK_SIZES_ALL);
const int mi_width = mi_size_wide[plane_bsize];
const int mi_height = mi_size_high[plane_bsize];
ENTROPY_CONTEXT ctxa[MAX_MIB_SIZE];
@ -5519,7 +5527,6 @@ static void tx_block_yrd(const AV1_COMP *cpi, MACROBLOCK *x, int blk_row,
const int zero_blk_rate = x->coeff_costs[txs_ctx][get_plane_type(0)]
.txb_skip_cost[txb_ctx.txb_skip_ctx][1];
rd_stats->zero_rate = zero_blk_rate;
rd_stats->ref_rdcost = ref_best_rd;
tx_type_rd(cpi, x, tx_size, blk_row, blk_col, 0, block, plane_bsize,
&txb_ctx, rd_stats, ftxs_mode, ref_best_rd, NULL);
const int mi_width = block_size_wide[plane_bsize] >> tx_size_wide_log2[0];
@ -6025,12 +6032,14 @@ static void model_rd_for_sb_with_fullrdy(
int64_t rate_sum = 0;
int64_t dist_sum = 0;
int64_t total_sse = 0;
assert(bsize < BLOCK_SIZES_ALL);
for (int plane = plane_from; plane <= plane_to; ++plane) {
struct macroblock_plane *const p = &x->plane[plane];
struct macroblockd_plane *const pd = &xd->plane[plane];
const BLOCK_SIZE plane_bsize =
get_plane_block_size(bsize, pd->subsampling_x, pd->subsampling_y);
assert(plane_bsize < BLOCK_SIZES_ALL);
const int bw = block_size_wide[plane_bsize];
const int bh = block_size_high[plane_bsize];
int64_t sse;
@ -6052,7 +6061,7 @@ static void model_rd_for_sb_with_fullrdy(
if (plane == 0) {
pick_tx_size_type_yrd(cpi, x, &rd_stats, bsize, mi_row, mi_col,
INT64_MAX);
if (rd_stats.invalid_rate) {
if (rd_stats.rate == INT_MAX) {
rate = 0;
dist = sse << 4;
} else {
@ -6994,7 +7003,7 @@ static void store_coding_context(MACROBLOCK *x, PICK_MODE_CONTEXT *ctx,
// Take a snapshot of the coding context so it can be
// restored if we decide to encode this way
ctx->skip = x->skip;
ctx->rd_stats.skip = x->skip;
ctx->skippable = skippable;
ctx->best_mode_index = mode_index;
ctx->mic = *xd->mi[0];
@ -7032,8 +7041,9 @@ static void setup_buffer_ref_mvs_inter(
// Gets an initial list of candidate vectors from neighbours and orders them
av1_find_mv_refs(cm, xd, mbmi, ref_frame, mbmi_ext->ref_mv_count,
mbmi_ext->ref_mv_stack, NULL, mbmi_ext->global_mvs, mi_row,
mi_col, mbmi_ext->mode_context);
mbmi_ext->ref_mv_stack, mbmi_ext->weight, NULL,
mbmi_ext->global_mvs, mi_row, mi_col,
mbmi_ext->mode_context);
// Further refinement that is encode side only to test the top few candidates
// in full and choose the best as the center point for subsequent searches.
@ -8325,6 +8335,23 @@ static INLINE int64_t interpolation_filter_rd(
return 0;
}
static INLINE int is_pred_filter_search_allowed(
const AV1_COMP *const cpi, BLOCK_SIZE bsize, int mi_row, int mi_col,
InterpFilters af_horiz, InterpFilters af_vert, InterpFilters lf_horiz,
InterpFilters lf_vert) {
const AV1_COMMON *cm = &cpi->common;
const int bsl = mi_size_wide_log2[bsize];
int pred_filter_search =
cpi->sf.cb_pred_filter_search
? (((mi_row + mi_col) >> bsl) +
get_chessboard_index(cm->current_frame.frame_number)) &
0x1
: 0;
pred_filter_search &= ((af_horiz == lf_horiz) && (af_horiz != SWITCHABLE)) ||
((af_vert == lf_vert) && (af_vert != SWITCHABLE));
return pred_filter_search;
}
static INLINE void pred_dual_interp_filter_rd(
MACROBLOCK *const x, const AV1_COMP *const cpi,
const TileDataEnc *tile_data, BLOCK_SIZE bsize, int mi_row, int mi_col,
@ -8385,26 +8412,20 @@ static INLINE void find_best_non_dual_interp_filter(
assert(x->e_mbd.mi[0]->interp_filters == filter_sets[0]);
assert(filter_set_size == DUAL_FILTER_SET_SIZE);
if ((skip_hor & skip_ver) != cpi->default_interp_skip_flags) {
const AV1_COMMON *cm = &cpi->common;
int bsl, pred_filter_search;
int pred_filter_search;
InterpFilters af = SWITCHABLE, lf = SWITCHABLE, filter_idx = 0;
const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
bsl = mi_size_wide_log2[bsize];
pred_filter_search =
cpi->sf.cb_pred_filter_search
? (((mi_row + mi_col) >> bsl) +
get_chessboard_index(cm->current_frame.frame_number)) &
0x1
: 0;
if (above_mbmi && is_inter_block(above_mbmi)) {
af = above_mbmi->interp_filters;
}
if (left_mbmi && is_inter_block(left_mbmi)) {
lf = left_mbmi->interp_filters;
}
pred_filter_search &= ((af == lf) && (af != SWITCHABLE));
pred_filter_search = is_pred_filter_search_allowed(cpi, bsize, mi_row,
mi_col, af, af, lf, lf);
if (pred_filter_search) {
assert(af != SWITCHABLE);
filter_idx = SWITCHABLE * (af & 0xf);
// This assert tells that (filter_x == filter_y) for non-dual filter case
assert((filter_sets[filter_idx] & 0xffff) ==
@ -8781,30 +8802,23 @@ static int64_t interpolation_filter_search(
const int bw = block_size_wide[bsize];
const int bh = block_size_high[bsize];
int skip_pred;
int bsl, pred_filter_search;
int pred_filter_search = 0;
InterpFilters af_horiz = SWITCHABLE, af_vert = SWITCHABLE,
lf_horiz = SWITCHABLE, lf_vert = SWITCHABLE, filter_idx = 0;
const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
bsl = mi_size_wide_log2[bsize];
pred_filter_search =
cpi->sf.cb_pred_filter_search
? (((mi_row + mi_col) >> bsl) +
get_chessboard_index(cm->current_frame.frame_number)) &
0x1
: 0;
if (above_mbmi && is_inter_block(above_mbmi)) {
af_horiz = av1_extract_interp_filter(above_mbmi->interp_filters, 1);
af_vert = av1_extract_interp_filter(above_mbmi->interp_filters, 0);
if (!have_newmv_in_inter_mode(mbmi->mode)) {
const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
if (above_mbmi && is_inter_block(above_mbmi)) {
af_horiz = av1_extract_interp_filter(above_mbmi->interp_filters, 1);
af_vert = av1_extract_interp_filter(above_mbmi->interp_filters, 0);
}
if (left_mbmi && is_inter_block(left_mbmi)) {
lf_horiz = av1_extract_interp_filter(left_mbmi->interp_filters, 1);
lf_vert = av1_extract_interp_filter(left_mbmi->interp_filters, 0);
}
pred_filter_search = is_pred_filter_search_allowed(
cpi, bsize, mi_row, mi_col, af_horiz, af_vert, lf_horiz, lf_vert);
}
if (left_mbmi && is_inter_block(left_mbmi)) {
lf_horiz = av1_extract_interp_filter(left_mbmi->interp_filters, 1);
lf_vert = av1_extract_interp_filter(left_mbmi->interp_filters, 0);
}
pred_filter_search &= !have_newmv_in_inter_mode(mbmi->mode);
pred_filter_search &=
((af_horiz == lf_horiz) && (af_horiz != SWITCHABLE)) ||
((af_vert == lf_vert) && (af_vert != SWITCHABLE));
if (pred_filter_search) {
pred_dual_interp_filter_rd(
x, cpi, tile_data, bsize, mi_row, mi_col, orig_dst, rd,
@ -9411,7 +9425,8 @@ static int64_t motion_mode_rd(
assert(mbmi->ref_frame[1] != INTRA_FRAME);
}
if (cpi->oxcf.enable_obmc == 0 && mbmi->motion_mode == OBMC_CAUSAL)
if ((cpi->oxcf.enable_obmc == 0 || cpi->sf.use_fast_nonrd_pick_mode) &&
mbmi->motion_mode == OBMC_CAUSAL)
continue;
if (identical_obmc_mv_field_detected) {
@ -9576,20 +9591,6 @@ static int64_t motion_mode_rd(
}
}
if (cpi->sf.model_based_motion_mode_rd_breakout && do_tx_search) {
int model_rate;
int64_t model_dist;
model_rd_sb_fn[MODELRD_TYPE_MOTION_MODE_RD](
cpi, mbmi->sb_type, x, xd, 0, num_planes - 1, mi_row, mi_col,
&model_rate, &model_dist, NULL, NULL, NULL, NULL, NULL);
const int64_t est_rd =
RDCOST(x->rdmult, rd_stats->rate + model_rate, model_dist);
if ((est_rd >> 3) * 6 > ref_best_rd) {
mbmi->ref_frame[1] = ref_frame_1;
continue;
}
}
if (!do_tx_search) {
int64_t curr_sse = -1;
int est_residue_cost = 0;
@ -9725,6 +9726,7 @@ static int64_t skip_mode_rd(RD_STATS *rd_stats, const AV1_COMP *const cpi,
const AV1_COMMON *cm = &cpi->common;
const int num_planes = av1_num_planes(cm);
MACROBLOCKD *const xd = &x->e_mbd;
assert(bsize < BLOCK_SIZES_ALL);
av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, orig_dst, bsize, 0,
av1_num_planes(cm) - 1);
@ -9825,8 +9827,7 @@ static INLINE int get_drl_cost(const MB_MODE_INFO *mbmi,
if (mbmi->mode == NEWMV || mbmi->mode == NEW_NEWMV) {
for (int idx = 0; idx < 2; ++idx) {
if (mbmi_ext->ref_mv_count[ref_frame_type] > idx + 1) {
uint8_t drl_ctx =
av1_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], idx);
uint8_t drl_ctx = av1_drl_ctx(mbmi_ext->weight[ref_frame_type], idx);
cost += drl_mode_cost0[drl_ctx][mbmi->ref_mv_idx != idx];
if (mbmi->ref_mv_idx == idx) return cost;
}
@ -9837,8 +9838,7 @@ static INLINE int get_drl_cost(const MB_MODE_INFO *mbmi,
if (have_nearmv_in_inter_mode(mbmi->mode)) {
for (int idx = 1; idx < 3; ++idx) {
if (mbmi_ext->ref_mv_count[ref_frame_type] > idx + 1) {
uint8_t drl_ctx =
av1_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], idx);
uint8_t drl_ctx = av1_drl_ctx(mbmi_ext->weight[ref_frame_type], idx);
cost += drl_mode_cost0[drl_ctx][mbmi->ref_mv_idx != (idx - 1)];
if (mbmi->ref_mv_idx == (idx - 1)) return cost;
}
@ -10248,8 +10248,8 @@ static int64_t handle_inter_mode(
mbmi->ref_frame[0] == LAST3_FRAME ||
mbmi->ref_frame[1] == LAST2_FRAME ||
mbmi->ref_frame[1] == LAST3_FRAME) {
if (mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_idx + has_nearmv]
.weight < REF_CAT_LEVEL) {
if (mbmi_ext->weight[ref_frame_type][ref_mv_idx + has_nearmv] <
REF_CAT_LEVEL) {
continue;
}
}
@ -10642,8 +10642,9 @@ static int64_t rd_pick_intrabc_mode_sb(const AV1_COMP *cpi, MACROBLOCK *x,
MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
MV_REFERENCE_FRAME ref_frame = INTRA_FRAME;
av1_find_mv_refs(cm, xd, mbmi, ref_frame, mbmi_ext->ref_mv_count,
mbmi_ext->ref_mv_stack, NULL, mbmi_ext->global_mvs, mi_row,
mi_col, mbmi_ext->mode_context);
mbmi_ext->ref_mv_stack, mbmi_ext->weight, NULL,
mbmi_ext->global_mvs, mi_row, mi_col,
mbmi_ext->mode_context);
int_mv nearestmv, nearmv;
av1_find_best_ref_mvs_from_stack(0, mbmi_ext, ref_frame, &nearestmv, &nearmv,
@ -10800,7 +10801,7 @@ void av1_rd_pick_intra_mode_sb(const AV1_COMP *cpi, MACROBLOCK *x, int mi_row,
int64_t dist_y = 0, dist_uv = 0;
TX_SIZE max_uv_tx_size;
ctx->skip = 0;
ctx->rd_stats.skip = 0;
mbmi->ref_frame[0] = INTRA_FRAME;
mbmi->ref_frame[1] = NONE_FRAME;
mbmi->use_intrabc = 0;
@ -10851,7 +10852,7 @@ void av1_rd_pick_intra_mode_sb(const AV1_COMP *cpi, MACROBLOCK *x, int mi_row,
if (rd_cost->rate != INT_MAX && rd_cost->rdcost < best_rd)
best_rd = rd_cost->rdcost;
if (rd_pick_intrabc_mode_sb(cpi, x, rd_cost, bsize, best_rd) < best_rd) {
ctx->skip = x->skip;
ctx->rd_stats.skip = x->skip;
memcpy(ctx->blk_skip, x->blk_skip,
sizeof(x->blk_skip[0]) * ctx->num_4x4_blk);
assert(rd_cost->rate != INT_MAX);
@ -10958,8 +10959,9 @@ static void rd_pick_skip_mode(RD_STATS *rd_cost,
}
MB_MODE_INFO_EXT *mbmi_ext = x->mbmi_ext;
av1_find_mv_refs(cm, xd, mbmi, ref_frame_type, mbmi_ext->ref_mv_count,
mbmi_ext->ref_mv_stack, NULL, mbmi_ext->global_mvs, mi_row,
mi_col, mbmi_ext->mode_context);
mbmi_ext->ref_mv_stack, mbmi_ext->weight, NULL,
mbmi_ext->global_mvs, mi_row, mi_col,
mbmi_ext->mode_context);
}
assert(this_mode == NEAREST_NEARESTMV);
@ -11431,8 +11433,9 @@ static void set_params_rd_pick_inter_mode(
}
}
av1_find_mv_refs(cm, xd, mbmi, ref_frame, mbmi_ext->ref_mv_count,
mbmi_ext->ref_mv_stack, NULL, mbmi_ext->global_mvs, mi_row,
mi_col, mbmi_ext->mode_context);
mbmi_ext->ref_mv_stack, mbmi_ext->weight, NULL,
mbmi_ext->global_mvs, mi_row, mi_col,
mbmi_ext->mode_context);
}
av1_count_overlappable_neighbors(cm, xd, mi_row, mi_col);
@ -11472,119 +11475,6 @@ static void set_params_rd_pick_inter_mode(
x->comp_rd_stats_idx = 0;
}
// TODO(kyslov): now this is very similar to set_params_rd_pick_inter_mode
// (except that doesn't set ALTREF parameters)
// consider passing a flag to select non-rd path (similar to
// encode_sb_row)
static void set_params_nonrd_pick_inter_mode(
const AV1_COMP *cpi, MACROBLOCK *x, HandleInterModeArgs *args,
BLOCK_SIZE bsize, int mi_row, int mi_col, mode_skip_mask_t *mode_skip_mask,
int skip_ref_frame_mask, unsigned int ref_costs_single[REF_FRAMES],
unsigned int ref_costs_comp[REF_FRAMES][REF_FRAMES],
struct buf_2d yv12_mb[REF_FRAMES][MAX_MB_PLANE]) {
const AV1_COMMON *const cm = &cpi->common;
const int num_planes = av1_num_planes(cm);
MACROBLOCKD *const xd = &x->e_mbd;
MB_MODE_INFO *const mbmi = xd->mi[0];
MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
unsigned char segment_id = mbmi->segment_id;
int dst_width1[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
int dst_width2[MAX_MB_PLANE] = { MAX_SB_SIZE >> 1, MAX_SB_SIZE >> 1,
MAX_SB_SIZE >> 1 };
int dst_height1[MAX_MB_PLANE] = { MAX_SB_SIZE >> 1, MAX_SB_SIZE >> 1,
MAX_SB_SIZE >> 1 };
int dst_height2[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
for (int i = 0; i < MB_MODE_COUNT; ++i)
for (int k = 0; k < REF_FRAMES; ++k) args->single_filter[i][k] = SWITCHABLE;
if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
int len = sizeof(uint16_t);
args->above_pred_buf[0] = CONVERT_TO_BYTEPTR(x->above_pred_buf);
args->above_pred_buf[1] =
CONVERT_TO_BYTEPTR(x->above_pred_buf + (MAX_SB_SQUARE >> 1) * len);
args->above_pred_buf[2] =
CONVERT_TO_BYTEPTR(x->above_pred_buf + MAX_SB_SQUARE * len);
args->left_pred_buf[0] = CONVERT_TO_BYTEPTR(x->left_pred_buf);
args->left_pred_buf[1] =
CONVERT_TO_BYTEPTR(x->left_pred_buf + (MAX_SB_SQUARE >> 1) * len);
args->left_pred_buf[2] =
CONVERT_TO_BYTEPTR(x->left_pred_buf + MAX_SB_SQUARE * len);
} else {
args->above_pred_buf[0] = x->above_pred_buf;
args->above_pred_buf[1] = x->above_pred_buf + (MAX_SB_SQUARE >> 1);
args->above_pred_buf[2] = x->above_pred_buf + MAX_SB_SQUARE;
args->left_pred_buf[0] = x->left_pred_buf;
args->left_pred_buf[1] = x->left_pred_buf + (MAX_SB_SQUARE >> 1);
args->left_pred_buf[2] = x->left_pred_buf + MAX_SB_SQUARE;
}
av1_collect_neighbors_ref_counts(xd);
estimate_ref_frame_costs(cm, xd, x, segment_id, ref_costs_single,
ref_costs_comp);
MV_REFERENCE_FRAME ref_frame;
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
x->pred_mv_sad[ref_frame] = INT_MAX;
x->mbmi_ext->mode_context[ref_frame] = 0;
mbmi_ext->ref_mv_count[ref_frame] = UINT8_MAX;
if (cpi->ref_frame_flags & av1_ref_frame_flag_list[ref_frame]) {
if (mbmi->partition != PARTITION_NONE &&
mbmi->partition != PARTITION_SPLIT) {
if (skip_ref_frame_mask & (1 << ref_frame)) {
int skip = 1;
for (int r = ALTREF_FRAME + 1; r < MODE_CTX_REF_FRAMES; ++r) {
if (!(skip_ref_frame_mask & (1 << r))) {
const MV_REFERENCE_FRAME *rf = ref_frame_map[r - REF_FRAMES];
if (rf[0] == ref_frame || rf[1] == ref_frame) {
skip = 0;
break;
}
}
}
if (skip) continue;
}
}
assert(get_ref_frame_yv12_buf(cm, ref_frame) != NULL);
setup_buffer_ref_mvs_inter(cpi, x, ref_frame, bsize, mi_row, mi_col,
yv12_mb);
}
}
av1_count_overlappable_neighbors(cm, xd, mi_row, mi_col);
if (check_num_overlappable_neighbors(mbmi) &&
is_motion_variation_allowed_bsize(bsize)) {
av1_build_prediction_by_above_preds(cm, xd, mi_row, mi_col,
args->above_pred_buf, dst_width1,
dst_height1, args->above_pred_stride);
av1_build_prediction_by_left_preds(cm, xd, mi_row, mi_col,
args->left_pred_buf, dst_width2,
dst_height2, args->left_pred_stride);
av1_setup_dst_planes(xd->plane, bsize, &cm->cur_frame->buf, mi_row, mi_col,
0, num_planes);
calc_target_weighted_pred(
cm, x, xd, mi_row, mi_col, args->above_pred_buf[0],
args->above_pred_stride[0], args->left_pred_buf[0],
args->left_pred_stride[0]);
}
init_mode_skip_mask(mode_skip_mask, cpi, x, bsize);
if (cpi->sf.tx_type_search.fast_intra_tx_type_search)
x->use_default_intra_tx_type = 1;
else
x->use_default_intra_tx_type = 0;
if (cpi->sf.tx_type_search.fast_inter_tx_type_search)
x->use_default_inter_tx_type = 1;
else
x->use_default_inter_tx_type = 0;
if (cpi->sf.skip_repeat_interpolation_filter_search) {
x->interp_filter_stats_idx[0] = 0;
x->interp_filter_stats_idx[1] = 0;
}
}
static void search_palette_mode(const AV1_COMP *cpi, MACROBLOCK *x, int mi_row,
int mi_col, RD_STATS *rd_cost,
PICK_MODE_CONTEXT *ctx, BLOCK_SIZE bsize,
@ -13207,6 +13097,97 @@ void av1_rd_pick_inter_mode_sb(AV1_COMP *cpi, TileDataEnc *tile_data,
}
}
// TODO(kyslov): now this is very similar to set_params_rd_pick_inter_mode
// (except that doesn't set ALTREF parameters)
// consider passing a flag to select non-rd path (similar to
// encode_sb_row)
static void set_params_nonrd_pick_inter_mode(
const AV1_COMP *cpi, MACROBLOCK *x, HandleInterModeArgs *args,
BLOCK_SIZE bsize, int mi_row, int mi_col, mode_skip_mask_t *mode_skip_mask,
int skip_ref_frame_mask, unsigned int ref_costs_single[REF_FRAMES],
unsigned int ref_costs_comp[REF_FRAMES][REF_FRAMES],
struct buf_2d yv12_mb[REF_FRAMES][MAX_MB_PLANE]) {
const AV1_COMMON *const cm = &cpi->common;
MACROBLOCKD *const xd = &x->e_mbd;
MB_MODE_INFO *const mbmi = xd->mi[0];
MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
unsigned char segment_id = mbmi->segment_id;
for (int i = 0; i < MB_MODE_COUNT; ++i)
for (int k = 0; k < REF_FRAMES; ++k) args->single_filter[i][k] = SWITCHABLE;
if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
int len = sizeof(uint16_t);
args->above_pred_buf[0] = CONVERT_TO_BYTEPTR(x->above_pred_buf);
args->above_pred_buf[1] =
CONVERT_TO_BYTEPTR(x->above_pred_buf + (MAX_SB_SQUARE >> 1) * len);
args->above_pred_buf[2] =
CONVERT_TO_BYTEPTR(x->above_pred_buf + MAX_SB_SQUARE * len);
args->left_pred_buf[0] = CONVERT_TO_BYTEPTR(x->left_pred_buf);
args->left_pred_buf[1] =
CONVERT_TO_BYTEPTR(x->left_pred_buf + (MAX_SB_SQUARE >> 1) * len);
args->left_pred_buf[2] =
CONVERT_TO_BYTEPTR(x->left_pred_buf + MAX_SB_SQUARE * len);
} else {
args->above_pred_buf[0] = x->above_pred_buf;
args->above_pred_buf[1] = x->above_pred_buf + (MAX_SB_SQUARE >> 1);
args->above_pred_buf[2] = x->above_pred_buf + MAX_SB_SQUARE;
args->left_pred_buf[0] = x->left_pred_buf;
args->left_pred_buf[1] = x->left_pred_buf + (MAX_SB_SQUARE >> 1);
args->left_pred_buf[2] = x->left_pred_buf + MAX_SB_SQUARE;
}
av1_collect_neighbors_ref_counts(xd);
estimate_ref_frame_costs(cm, xd, x, segment_id, ref_costs_single,
ref_costs_comp);
MV_REFERENCE_FRAME ref_frame;
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
x->pred_mv_sad[ref_frame] = INT_MAX;
x->mbmi_ext->mode_context[ref_frame] = 0;
mbmi_ext->ref_mv_count[ref_frame] = UINT8_MAX;
if (cpi->ref_frame_flags & av1_ref_frame_flag_list[ref_frame]) {
if (mbmi->partition != PARTITION_NONE &&
mbmi->partition != PARTITION_SPLIT) {
if (skip_ref_frame_mask & (1 << ref_frame)) {
int skip = 1;
for (int r = ALTREF_FRAME + 1; r < MODE_CTX_REF_FRAMES; ++r) {
if (!(skip_ref_frame_mask & (1 << r))) {
const MV_REFERENCE_FRAME *rf = ref_frame_map[r - REF_FRAMES];
if (rf[0] == ref_frame || rf[1] == ref_frame) {
skip = 0;
break;
}
}
}
if (skip) continue;
}
}
assert(get_ref_frame_yv12_buf(cm, ref_frame) != NULL);
setup_buffer_ref_mvs_inter(cpi, x, ref_frame, bsize, mi_row, mi_col,
yv12_mb);
}
}
av1_count_overlappable_neighbors(cm, xd, mi_row, mi_col);
init_mode_skip_mask(mode_skip_mask, cpi, x, bsize);
if (cpi->sf.tx_type_search.fast_intra_tx_type_search)
x->use_default_intra_tx_type = 1;
else
x->use_default_intra_tx_type = 0;
if (cpi->sf.tx_type_search.fast_inter_tx_type_search)
x->use_default_inter_tx_type = 1;
else
x->use_default_inter_tx_type = 0;
if (cpi->sf.skip_repeat_interpolation_filter_search) {
x->interp_filter_stats_idx[0] = 0;
x->interp_filter_stats_idx[1] = 0;
}
}
// TODO(kyslov): now this is very similar to av1_rd_pick_inter_mode_sb except:
// it only checks non-compound mode and
// it doesn't check palette mode
@ -13237,10 +13218,6 @@ void av1_nonrd_pick_inter_mode_sb(AV1_COMP *cpi, TileDataEnc *tile_data,
InterModeSearchState search_state;
init_inter_mode_search_state(&search_state, cpi, tile_data, x, bsize,
best_rd_so_far);
INTERINTRA_MODE interintra_modes[REF_FRAMES] = {
INTERINTRA_MODES, INTERINTRA_MODES, INTERINTRA_MODES, INTERINTRA_MODES,
INTERINTRA_MODES, INTERINTRA_MODES, INTERINTRA_MODES, INTERINTRA_MODES
};
HandleInterModeArgs args = {
{ NULL }, { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE },
{ NULL }, { MAX_SB_SIZE >> 1, MAX_SB_SIZE >> 1, MAX_SB_SIZE >> 1 },
@ -13248,7 +13225,7 @@ void av1_nonrd_pick_inter_mode_sb(AV1_COMP *cpi, TileDataEnc *tile_data,
NULL, search_state.modelled_rd,
{ { 0 } }, INT_MAX,
INT_MAX, search_state.simple_rd,
0, interintra_modes,
0, NULL,
1, NULL
};
for (i = 0; i < REF_FRAMES; ++i) x->pred_sse[i] = INT_MAX;

View file

@ -123,6 +123,13 @@ void av1_rd_pick_inter_mode_sb(struct AV1_COMP *cpi,
struct RD_STATS *rd_cost, BLOCK_SIZE bsize,
PICK_MODE_CONTEXT *ctx, int64_t best_rd_so_far);
void av1_fast_nonrd_pick_inter_mode_sb(struct AV1_COMP *cpi,
struct TileDataEnc *tile_data,
struct macroblock *x, int mi_row,
int mi_col, struct RD_STATS *rd_cost,
BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx,
int64_t best_rd_so_far);
void av1_nonrd_pick_inter_mode_sb(struct AV1_COMP *cpi,
struct TileDataEnc *tile_data,
struct macroblock *x, int mi_row, int mi_col,

View file

@ -495,6 +495,7 @@ void av1_build_inter_predictors_for_planes_single_buf(
MACROBLOCKD *xd, BLOCK_SIZE bsize, int plane_from, int plane_to, int mi_row,
int mi_col, int ref, uint8_t *ext_dst[3], int ext_dst_stride[3],
int can_use_previous) {
assert(bsize < BLOCK_SIZES_ALL);
int plane;
const int mi_x = mi_col * MI_SIZE;
const int mi_y = mi_row * MI_SIZE;
@ -595,6 +596,7 @@ void av1_build_wedge_inter_predictor_from_buf(MACROBLOCKD *xd, BLOCK_SIZE bsize,
uint8_t *ext_dst1[3],
int ext_dst_stride1[3]) {
int plane;
assert(bsize < BLOCK_SIZES_ALL);
for (plane = plane_from; plane <= plane_to; ++plane) {
const BLOCK_SIZE plane_bsize = get_plane_block_size(
bsize, xd->plane[plane].subsampling_x, xd->plane[plane].subsampling_y);

View file

@ -151,6 +151,7 @@ static void count_segs_sb(const AV1_COMMON *cm, MACROBLOCKD *xd,
case PARTITION_SPLIT: {
const BLOCK_SIZE subsize = get_partition_subsize(bsize, PARTITION_SPLIT);
int n;
assert(subsize < BLOCK_SIZES_ALL);
for (n = 0; n < 4; n++) {
const int mi_dc = hbs * (n & 1);

View file

@ -29,9 +29,9 @@ static MESH_PATTERN
{ { 64, 16 }, { 24, 8 }, { 12, 4 }, { 7, 1 } },
{ { 64, 16 }, { 24, 8 }, { 12, 4 }, { 7, 1 } },
};
static unsigned char good_quality_max_mesh_pct[MAX_MESH_SPEED + 1] = {
50, 50, 25, 15, 5, 1
};
static unsigned char good_quality_max_mesh_pct[MAX_MESH_SPEED + 1] = { 50, 50,
25, 15,
5, 1 };
// TODO(huisu@google.com): These settings are pretty relaxed, tune them for
// each speed setting
@ -114,8 +114,11 @@ static void set_good_speed_feature_framesize_dependent(
sf->ml_partition_search_breakout_thresh[2] = 300; // BLOCK_32X32
sf->ml_partition_search_breakout_thresh[3] = 500; // BLOCK_64X64
sf->ml_partition_search_breakout_thresh[4] = -1; // BLOCK_128X128
sf->ml_early_term_after_part_split_level = 1;
}
// TODO(chiyotsai@google.com): Try to replace two pass partition search with
// other speed features.
if (is_720p_or_larger && speed >= CONFIG_2PASS_PARTITION_SEARCH_LVL_START &&
speed < CONFIG_2PASS_PARTITION_SEARCH_LVL_END) {
sf->two_pass_partition_search = 1;
@ -126,8 +129,12 @@ static void set_good_speed_feature_framesize_dependent(
sf->use_square_partition_only_threshold = BLOCK_128X128;
} else if (is_480p_or_larger) {
sf->use_square_partition_only_threshold = BLOCK_64X64;
sf->simple_motion_search_split = 2;
} else {
sf->use_square_partition_only_threshold = BLOCK_32X32;
sf->simple_motion_search_split = 1;
}
if (!is_720p_or_larger) {
@ -138,6 +145,7 @@ static void set_good_speed_feature_framesize_dependent(
sf->ml_partition_search_breakout_thresh[4] = -1; // BLOCK_128X128
sf->firstpass_simple_motion_search_early_term = 1;
sf->ml_early_term_after_part_split_level = 2;
}
}
@ -165,6 +173,7 @@ static void set_good_speed_feature_framesize_dependent(
}
if (speed >= 3) {
sf->ml_early_term_after_part_split_level = 0;
if (is_720p_or_larger) {
sf->partition_search_breakout_dist_thr = (1 << 25);
sf->partition_search_breakout_rate_thr = 200;
@ -175,6 +184,14 @@ static void set_good_speed_feature_framesize_dependent(
}
sf->use_first_partition_pass_interintra_stats =
sf->two_pass_partition_search;
// TODO(Venkat): Clean-up frame type dependency for
// simple_motion_search_split in partition search function and set the
// speed feature accordingly
// TODO(any): The models and thresholds used by simple_motion_split is
// trained and tuned on speed 1 and 2. We might get better performance if we
// readjust them for speed 3 and 4.
sf->simple_motion_search_split = cm->allow_screen_content_tools ? 1 : 2;
}
if (speed >= 4) {
@ -204,7 +221,6 @@ static void set_good_speed_features_framesize_independent(
sf->use_dist_wtd_comp_flag = DIST_WTD_COMP_SKIP_MV_SEARCH;
sf->model_based_prune_tx_search_level = 1;
sf->model_based_post_interp_filter_breakout = 1;
sf->model_based_motion_mode_rd_breakout = 1;
// TODO(debargha): Test, tweak and turn on either 1 or 2
sf->inter_mode_rd_model_estimation = 1;
@ -254,7 +270,7 @@ static void set_good_speed_features_framesize_independent(
// speed.
sf->prune_single_motion_modes_by_simple_trans = 1;
sf->simple_motion_search_split_only = 1;
sf->simple_motion_search_split = 1;
sf->simple_motion_search_early_term_none = 1;
sf->disable_wedge_search_var_thresh = 0;
@ -332,12 +348,6 @@ static void set_good_speed_features_framesize_independent(
frame_is_intra_only(&cpi->common) ? 0 : (boosted ? 1 : 2);
sf->perform_coeff_opt = is_boosted_arf2_bwd_type ? 2 : 3;
sf->prune_comp_type_by_model_rd = boosted ? 0 : 1;
// TODO(Venkat): Clean-up frame type dependency for
// simple_motion_search_split_only in partition search function and set the
// speed feature accordingly
// TODO(Venkat): Evaluate this speed feature for speed 1 & 2
sf->simple_motion_search_split_only =
cm->allow_screen_content_tools ? 1 : 2;
sf->disable_smooth_intra =
!frame_is_intra_only(&cpi->common) || (cpi->rc.frames_to_key != 1);
}
@ -347,6 +357,7 @@ static void set_good_speed_features_framesize_independent(
sf->tx_type_search.fast_intra_tx_type_search = 1;
sf->disable_loop_restoration_chroma =
(boosted || cm->allow_screen_content_tools) ? 0 : 1;
sf->reduce_wiener_window_size = !boosted;
sf->mv.subpel_search_method = SUBPEL_TREE_PRUNED;
sf->adaptive_pred_interp_filter = 0;
sf->cb_pred_filter_search = 1;
@ -433,7 +444,6 @@ static void set_rt_speed_features_framesize_independent(AV1_COMP *cpi,
sf->use_dist_wtd_comp_flag = DIST_WTD_COMP_SKIP_MV_SEARCH;
sf->model_based_prune_tx_search_level = 1;
sf->model_based_post_interp_filter_breakout = 1;
sf->model_based_motion_mode_rd_breakout = 1;
// TODO(debargha): Test, tweak and turn on either 1 or 2
sf->inter_mode_rd_model_estimation = 0;
@ -455,6 +465,9 @@ static void set_rt_speed_features_framesize_independent(AV1_COMP *cpi,
sf->cb_pred_filter_search = 0;
sf->use_nonrd_pick_mode = 0;
sf->use_real_time_ref_set = 0;
sf->use_fast_nonrd_pick_mode = 0;
sf->reuse_inter_pred_nonrd = 0;
sf->estimate_motion_for_var_based_partition = 1;
if (speed >= 1) {
sf->gm_erroradv_type = GM_ERRORADV_TR_1;
@ -593,21 +606,14 @@ static void set_rt_speed_features_framesize_independent(AV1_COMP *cpi,
sf->simple_model_rd_from_var = 1;
}
if (speed >= 7) {
sf->default_max_partition_size = BLOCK_32X32;
sf->default_min_partition_size = BLOCK_8X8;
sf->intra_y_mode_mask[TX_64X64] = INTRA_DC;
sf->intra_y_mode_mask[TX_32X32] = INTRA_DC;
sf->frame_parameter_update = 0;
sf->mv.search_method = FAST_HEX;
sf->partition_search_type = REFERENCE_PARTITION;
sf->mode_search_skip_flags |= FLAG_SKIP_INTRA_DIRMISMATCH;
}
if (speed >= 8) {
sf->mv.search_method = FAST_DIAMOND;
sf->lpf_pick = LPF_PICK_FROM_Q;
sf->mv.subpel_force_stop = QUARTER_PEL;
sf->default_max_partition_size = BLOCK_128X128;
sf->default_min_partition_size = BLOCK_8X8;
sf->frame_parameter_update = 0;
sf->mv.search_method = FAST_DIAMOND;
sf->partition_search_type = VAR_BASED_PARTITION;
sf->mode_search_skip_flags |= FLAG_SKIP_INTRA_DIRMISMATCH;
sf->use_real_time_ref_set = 1;
// Can't use LARGEST TX mode with pre-calculated partition
// and disabled TX64
@ -615,6 +621,12 @@ static void set_rt_speed_features_framesize_independent(AV1_COMP *cpi,
sf->use_nonrd_pick_mode = 1;
sf->inter_mode_rd_model_estimation = 2;
}
if (speed >= 8) {
sf->use_fast_nonrd_pick_mode = 1;
sf->mv.subpel_search_method = SUBPEL_TREE;
sf->tx_size_search_method = USE_FAST_RD;
sf->estimate_motion_for_var_based_partition = 0;
}
}
void av1_set_speed_features_framesize_dependent(AV1_COMP *cpi, int speed) {
@ -679,7 +691,6 @@ void av1_set_speed_features_framesize_independent(AV1_COMP *cpi, int speed) {
sf->tx_size_search_lgr_block = 0;
sf->model_based_prune_tx_search_level = 0;
sf->model_based_post_interp_filter_breakout = 0;
sf->model_based_motion_mode_rd_breakout = 0;
sf->reduce_inter_modes = 0;
sf->selective_ref_gm = 1;
sf->adaptive_motion_search = 0;
@ -711,6 +722,7 @@ void av1_set_speed_features_framesize_independent(AV1_COMP *cpi, int speed) {
sf->use_first_partition_pass_interintra_stats = 0;
sf->disable_wedge_search_var_thresh = 0;
sf->disable_loop_restoration_chroma = 0;
sf->reduce_wiener_window_size = 0;
sf->fast_wedge_sign_estimate = 0;
sf->prune_wedge_pred_diff_based = 0;
sf->drop_ref = 0;
@ -751,11 +763,12 @@ void av1_set_speed_features_framesize_independent(AV1_COMP *cpi, int speed) {
sf->ml_prune_rect_partition = 0;
sf->ml_prune_ab_partition = 0;
sf->ml_prune_4_partition = 0;
sf->ml_early_term_after_part_split_level = 0;
sf->fast_cdef_search = 0;
for (i = 0; i < PARTITION_BLOCK_SIZES; ++i) {
sf->ml_partition_search_breakout_thresh[i] = -1; // -1 means not enabled.
}
sf->simple_motion_search_split_only = 0;
sf->simple_motion_search_split = 0;
sf->simple_motion_search_prune_rect = 0;
sf->simple_motion_search_early_term_none = 0;
@ -774,9 +787,6 @@ void av1_set_speed_features_framesize_independent(AV1_COMP *cpi, int speed) {
// Set decoder side speed feature to use less dual sgr modes
sf->dual_sgr_penalty_level = 0;
// TODO(angiebird, debargha): Re-evaluate the impact of
// inter_mode_rd_model_estimation in conjunction with
// model_based_motion_mode_rd_breakout
sf->inter_mode_rd_model_estimation = 0;
sf->inter_mode_rd_model_estimation_adaptive = 0;

View file

@ -354,11 +354,6 @@ typedef struct SPEED_FEATURES {
// 1: use model based rd breakout
int model_based_post_interp_filter_breakout;
// Model based breakout in motion_mode_rd
// 0: no breakout
// 1: use model based rd breakout
int model_based_motion_mode_rd_breakout;
// Used if partition_search_type = FIXED_SIZE_PARTITION
BLOCK_SIZE always_this_block_size;
@ -385,6 +380,11 @@ typedef struct SPEED_FEATURES {
// Use a ML model to prune horz4 and vert4 partitions.
int ml_prune_4_partition;
// Use a ML model to adaptively terminate partition search after trying
// PARTITION_SPLIT. Can take values 0 - 2, 0 meaning not being enabled, and
// 1 - 2 increasing aggressiveness in order.
int ml_early_term_after_part_split_level;
int fast_cdef_search;
// 2-pass coding block partition search, and also use the mode decisions made
@ -648,8 +648,11 @@ typedef struct SPEED_FEATURES {
int simple_motion_search_prune_rect;
// Perform simple motion search before none_partition to decide if we
// want to split directly without trying other partition types.
int simple_motion_search_split_only;
// want to remove all partitions other than PARTITION_SPLIT. If set to 0, this
// model is disabled. If set to 1, the model attempts to perform
// PARTITION_SPLIT only. If set to 2, the model also attempts to prune
// PARTITION_SPLIT.
int simple_motion_search_split;
// Use features from simple_motion_search to terminate prediction block
// partition after PARTITION_NONE
@ -672,6 +675,9 @@ typedef struct SPEED_FEATURES {
// Disable loop restoration for Chroma plane
int disable_loop_restoration_chroma;
// Reduce the wiener filter win size for luma
int reduce_wiener_window_size;
// Flag used to control the extent of coeff R-D optimization
int perform_coeff_opt;
@ -695,6 +701,16 @@ typedef struct SPEED_FEATURES {
// inter-mode RD model for others. Only enabled when
// inter_mode_rd_model_estimation != 0
int inter_mode_rd_model_estimation_adaptive;
// Use very reduced set of inter mode checks and fast non-rd mode cost
// estimation Only enabled when use_nonrd_pick_mode is != 0
int use_fast_nonrd_pick_mode;
// Reuse inter prediction in fast non-rd mode.
int reuse_inter_pred_nonrd;
// Perform croase ME before calculating variance in variance-based partition
int estimate_motion_for_var_based_partition;
} SPEED_FEATURES;
struct AV1_COMP;

View file

@ -37,9 +37,9 @@
#define EDGE_THRESHOLD 50
#define SQRT_PI_BY_2 1.25331413732
static unsigned int index_mult[14] = {
0, 0, 0, 0, 49152, 39322, 32768, 28087, 24576, 21846, 19661, 17874, 0, 15124
};
static unsigned int index_mult[14] = { 0, 0, 0, 0, 49152,
39322, 32768, 28087, 24576, 21846,
19661, 17874, 0, 15124 };
static int64_t highbd_index_mult[14] = { 0U, 0U, 0U,
0U, 3221225472U, 2576980378U,

View file

@ -198,6 +198,8 @@ void av1_tokenize_sb_vartx(const AV1_COMP *cpi, ThreadData *td, TOKENEXTRA **t,
struct tokenize_b_args arg = { cpi, td, t, 0, allow_update_cdf };
if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return;
assert(bsize < BLOCK_SIZES_ALL);
if (mbmi->skip) {
av1_reset_skip_context(xd, mi_row, mi_col, bsize, num_planes);
return;
@ -214,6 +216,7 @@ void av1_tokenize_sb_vartx(const AV1_COMP *cpi, ThreadData *td, TOKENEXTRA **t,
scale_chroma_bsize(bsize, pd->subsampling_x, pd->subsampling_y);
const BLOCK_SIZE plane_bsize =
get_plane_block_size(bsizec, pd->subsampling_x, pd->subsampling_y);
assert(plane_bsize < BLOCK_SIZES_ALL);
const int mi_width = block_size_wide[plane_bsize] >> tx_size_wide_log2[0];
const int mi_height = block_size_high[plane_bsize] >> tx_size_high_log2[0];
const TX_SIZE max_tx_size = get_vartx_max_txsize(xd, plane_bsize, plane);

View file

@ -459,26 +459,24 @@ static void mc_flow_dispenser(AV1_COMP *cpi, GF_PICTURE *gf_picture,
}
}
static void init_gop_frames(AV1_COMP *cpi, GF_PICTURE *gf_picture,
const GF_GROUP *gf_group, int *tpl_group_frames,
const EncodeFrameInput *const frame_input) {
static void init_gop_frames_for_tpl(AV1_COMP *cpi, GF_PICTURE *gf_picture,
const GF_GROUP *gf_group,
int *tpl_group_frames,
const EncodeFrameInput *const frame_input) {
AV1_COMMON *cm = &cpi->common;
const SequenceHeader *const seq_params = &cm->seq_params;
int frame_idx = 0;
int i;
int gld_index = -1;
int alt_index = -1;
int lst_index = -1;
int extend_frame_count = 0;
int frame_gop_offset = 0;
int pframe_qindex = cpi->tpl_stats[2].base_qindex;
RefCntBuffer *frame_bufs = cm->buffer_pool->frame_bufs;
int recon_frame_index[INTER_REFS_PER_FRAME + 1] = { -1, -1, -1, -1,
-1, -1, -1, -1 };
// TODO(jingning): To be used later for gf frame type parsing.
(void)gf_group;
for (i = 0; i < FRAME_BUFFERS && frame_idx < INTER_REFS_PER_FRAME + 1; ++i) {
if (frame_bufs[i].ref_count == 0) {
alloc_frame_mvs(cm, &frame_bufs[i]);
@ -503,51 +501,48 @@ static void init_gop_frames(AV1_COMP *cpi, GF_PICTURE *gf_picture,
*tpl_group_frames = 0;
// Initialize Golden reference frame.
gf_picture[0].frame = NULL;
RefCntBuffer *ref_buf = get_ref_frame_buf(cm, GOLDEN_FRAME);
if (ref_buf) gf_picture[0].frame = &ref_buf->buf;
gf_picture[0].frame = &ref_buf->buf;
for (i = 0; i < 7; ++i) gf_picture[0].ref_frame[i] = -1;
gld_index = 0;
++*tpl_group_frames;
// Initialize ARF frame
// Initialize base layer ARF frame
gf_picture[1].frame = frame_input->source;
gf_picture[1].ref_frame[0] = gld_index;
gf_picture[1].ref_frame[1] = lst_index;
gf_picture[1].ref_frame[2] = alt_index;
// TODO(yuec) Need o figure out full AV1 reference model
for (i = 3; i < 7; ++i) gf_picture[1].ref_frame[i] = -1;
alt_index = 1;
for (i = 1; i < 7; ++i) gf_picture[1].ref_frame[i] = -1;
++*tpl_group_frames;
// Initialize P frames
for (frame_idx = 2; frame_idx < MAX_LAG_BUFFERS; ++frame_idx) {
struct lookahead_entry *buf =
av1_lookahead_peek(cpi->lookahead, frame_idx - 2);
struct lookahead_entry *buf;
frame_gop_offset = gf_group->frame_disp_idx[frame_idx];
buf = av1_lookahead_peek(cpi->lookahead, frame_gop_offset - 1);
if (buf == NULL) break;
gf_picture[frame_idx].frame = &buf->img;
gf_picture[frame_idx].ref_frame[0] = gld_index;
gf_picture[frame_idx].ref_frame[1] = lst_index;
gf_picture[frame_idx].ref_frame[2] = alt_index;
gf_picture[frame_idx].ref_frame[2] = 1;
for (i = 3; i < 7; ++i) gf_picture[frame_idx].ref_frame[i] = -1;
++*tpl_group_frames;
lst_index = frame_idx;
if (frame_idx == cpi->rc.baseline_gf_interval + 1) break;
if (frame_idx == gf_group->size) break;
}
gld_index = frame_idx;
lst_index = AOMMAX(0, frame_idx - 1);
alt_index = -1;
++frame_idx;
++frame_gop_offset;
// Extend two frames outside the current gf group.
for (; frame_idx < MAX_LAG_BUFFERS && extend_frame_count < 2; ++frame_idx) {
struct lookahead_entry *buf =
av1_lookahead_peek(cpi->lookahead, frame_idx - 2);
av1_lookahead_peek(cpi->lookahead, frame_gop_offset - 1);
if (buf == NULL) break;
@ -556,11 +551,11 @@ static void init_gop_frames(AV1_COMP *cpi, GF_PICTURE *gf_picture,
gf_picture[frame_idx].frame = &buf->img;
gf_picture[frame_idx].ref_frame[0] = gld_index;
gf_picture[frame_idx].ref_frame[1] = lst_index;
gf_picture[frame_idx].ref_frame[2] = alt_index;
for (i = 3; i < 7; ++i) gf_picture[frame_idx].ref_frame[i] = -1;
for (i = 2; i < 7; ++i) gf_picture[frame_idx].ref_frame[i] = -1;
lst_index = frame_idx;
++*tpl_group_frames;
++extend_frame_count;
++frame_gop_offset;
}
}
@ -582,7 +577,8 @@ void av1_tpl_setup_stats(AV1_COMP *cpi,
int tpl_group_frames = 0;
int frame_idx;
init_gop_frames(cpi, gf_picture, gf_group, &tpl_group_frames, frame_input);
init_gop_frames_for_tpl(cpi, gf_picture, gf_group, &tpl_group_frames,
frame_input);
init_tpl_stats(cpi);

View file

@ -227,36 +227,6 @@ static int set_vt_partitioning(AV1_COMP *cpi, MACROBLOCK *const x,
set_block_size(cpi, x, xd, mi_row, mi_col, bsize);
return 1;
}
// Check vertical split.
if (mi_row + block_height / 2 < cm->mi_rows) {
BLOCK_SIZE subsize = get_partition_subsize(bsize, PARTITION_VERT);
get_variance(&vt.part_variances->vert[0]);
get_variance(&vt.part_variances->vert[1]);
if (vt.part_variances->vert[0].variance < threshold &&
vt.part_variances->vert[1].variance < threshold &&
get_plane_block_size(subsize, xd->plane[1].subsampling_x,
xd->plane[1].subsampling_y) < BLOCK_INVALID) {
set_block_size(cpi, x, xd, mi_row, mi_col, subsize);
set_block_size(cpi, x, xd, mi_row, mi_col + block_width / 2, subsize);
return 1;
}
}
// Check horizontal split.
if (mi_col + block_width / 2 < cm->mi_cols) {
BLOCK_SIZE subsize = get_partition_subsize(bsize, PARTITION_HORZ);
get_variance(&vt.part_variances->horz[0]);
get_variance(&vt.part_variances->horz[1]);
if (vt.part_variances->horz[0].variance < threshold &&
vt.part_variances->horz[1].variance < threshold &&
get_plane_block_size(subsize, xd->plane[1].subsampling_x,
xd->plane[1].subsampling_y) < BLOCK_INVALID) {
set_block_size(cpi, x, xd, mi_row, mi_col, subsize);
set_block_size(cpi, x, xd, mi_row + block_height / 2, mi_col, subsize);
return 1;
}
}
return 0;
}
return 0;
@ -329,22 +299,15 @@ static void fill_variance_4x4avg(const uint8_t *s, int sp, const uint8_t *d,
}
}
// TODO(kyslov) Bring back threshold adjustment based on content state
static int64_t scale_part_thresh_sumdiff(int64_t threshold_base, int speed,
int width, int height,
int content_state) {
(void)width;
(void)height;
(void)content_state;
if (speed >= 8) {
if (width <= 640 && height <= 480)
return (5 * threshold_base) >> 2;
else if ((content_state == kLowSadLowSumdiff) ||
(content_state == kHighSadLowSumdiff) ||
(content_state == kLowVarHighSumdiff))
return (5 * threshold_base) >> 2;
} else if (speed == 7) {
if ((content_state == kLowSadLowSumdiff) ||
(content_state == kHighSadLowSumdiff) ||
(content_state == kLowVarHighSumdiff)) {
return (5 * threshold_base) >> 2;
}
return (5 * threshold_base) >> 2;
}
return threshold_base;
}
@ -372,7 +335,8 @@ static void set_vbp_thresholds(AV1_COMP *cpi, int64_t thresholds[], int q,
threshold_base = scale_part_thresh_sumdiff(
threshold_base, cpi->oxcf.speed, cm->width, cm->height, content_state);
thresholds[1] = threshold_base;
thresholds[0] = threshold_base;
thresholds[1] = threshold_base << 1;
thresholds[3] = threshold_base << cpi->oxcf.speed;
if (cm->width >= 1280 && cm->height >= 720)
thresholds[3] = thresholds[3] << 1;
@ -384,7 +348,6 @@ static void set_vbp_thresholds(AV1_COMP *cpi, int64_t thresholds[], int q,
thresholds[2] = (5 * threshold_base) >> 2;
} else if (cm->width < 1920 && cm->height < 1080) {
thresholds[2] = threshold_base << 1;
thresholds[3] <<= 2;
} else {
thresholds[2] = (5 * threshold_base) >> 1;
}
@ -441,22 +404,23 @@ int av1_choose_var_based_partitioning(AV1_COMP *cpi, const TileInfo *const tile,
v16x16 *vt2 = NULL;
unsigned char force_split[85];
int avg_32x32;
int max_var_32x32 = 0;
int min_var_32x32 = INT_MAX;
int max_var_32x32[4];
int min_var_32x32[4];
int var_32x32;
int var_64x64;
int min_var_64x64 = INT_MAX;
int max_var_64x64 = 0;
int avg_16x16[4];
int maxvar_16x16[4];
int minvar_16x16[4];
int avg_16x16[4][4];
int maxvar_16x16[4][4];
int minvar_16x16[4][4];
int64_t threshold_4x4avg;
int content_state = 0;
uint8_t *s;
const uint8_t *d;
int sp;
int dp;
int compute_minmax_variance = 1;
// TODO(kyslov) Bring back compute_minmax_variance with content type detection
int compute_minmax_variance = 0;
int is_key_frame = frame_is_intra_only(cm);
int pixels_wide = 128, pixels_high = 128;
assert(cm->seq_params.sb_size == BLOCK_64X64 ||
@ -512,10 +476,12 @@ int av1_choose_var_based_partitioning(AV1_COMP *cpi, const TileInfo *const tile,
mi->sb_type = cm->seq_params.sb_size;
mi->mv[0].as_int = 0;
mi->interp_filters = av1_make_interp_filters(BILINEAR, BILINEAR);
if (xd->mb_to_right_edge >= 0 && xd->mb_to_bottom_edge >= 0) {
const MV dummy_mv = { 0, 0 };
av1_int_pro_motion_estimation(cpi, x, cm->seq_params.sb_size, mi_row,
mi_col, &dummy_mv);
if (cpi->sf.estimate_motion_for_var_based_partition) {
if (xd->mb_to_right_edge >= 0 && xd->mb_to_bottom_edge >= 0) {
const MV dummy_mv = { 0, 0 };
av1_int_pro_motion_estimation(cpi, x, cm->seq_params.sb_size, mi_row,
mi_col, &dummy_mv);
}
}
// TODO(kyslov): bring the small SAD functionality back
@ -561,14 +527,16 @@ int av1_choose_var_based_partitioning(AV1_COMP *cpi, const TileInfo *const tile,
const int y64_idx = ((m >> 1) << 6);
const int m2 = m << 2;
force_split[m + 1] = 0;
max_var_32x32[m] = 0;
min_var_32x32[m] = INT_MAX;
for (i = 0; i < 4; i++) {
const int x32_idx = x64_idx + ((i & 1) << 5);
const int y32_idx = y64_idx + ((i >> 1) << 5);
const int i2 = (m2 + i) << 2;
force_split[5 + m2 + i] = 0;
avg_16x16[i] = 0;
maxvar_16x16[i] = 0;
minvar_16x16[i] = INT_MAX;
avg_16x16[m][i] = 0;
maxvar_16x16[m][i] = 0;
minvar_16x16[m][i] = INT_MAX;
for (j = 0; j < 4; j++) {
const int x16_idx = x32_idx + ((j & 1) << 4);
const int y16_idx = y32_idx + ((j >> 1) << 4);
@ -581,15 +549,15 @@ int av1_choose_var_based_partitioning(AV1_COMP *cpi, const TileInfo *const tile,
pixels_high, is_key_frame);
fill_variance_tree(&vt->split[m].split[i].split[j], BLOCK_16X16);
get_variance(&vt->split[m].split[i].split[j].part_variances.none);
avg_16x16[i] +=
avg_16x16[m][i] +=
vt->split[m].split[i].split[j].part_variances.none.variance;
if (vt->split[m].split[i].split[j].part_variances.none.variance <
minvar_16x16[i])
minvar_16x16[i] =
minvar_16x16[m][i])
minvar_16x16[m][i] =
vt->split[m].split[i].split[j].part_variances.none.variance;
if (vt->split[m].split[i].split[j].part_variances.none.variance >
maxvar_16x16[i])
maxvar_16x16[i] =
maxvar_16x16[m][i])
maxvar_16x16[m][i] =
vt->split[m].split[i].split[j].part_variances.none.variance;
if (vt->split[m].split[i].split[j].part_variances.none.variance >
thresholds[3]) {
@ -669,21 +637,22 @@ int av1_choose_var_based_partitioning(AV1_COMP *cpi, const TileInfo *const tile,
if (!force_split[5 + m2 + i]) {
get_variance(&vt->split[m].split[i].part_variances.none);
var_32x32 = vt->split[m].split[i].part_variances.none.variance;
max_var_32x32 = AOMMAX(var_32x32, max_var_32x32);
min_var_32x32 = AOMMIN(var_32x32, min_var_32x32);
max_var_32x32[m] = AOMMAX(var_32x32, max_var_32x32[m]);
min_var_32x32[m] = AOMMIN(var_32x32, min_var_32x32[m]);
if (vt->split[m].split[i].part_variances.none.variance >
thresholds[2] ||
(!is_key_frame &&
vt->split[m].split[i].part_variances.none.variance >
(thresholds[2] >> 1) &&
vt->split[m].split[i].part_variances.none.variance >
(avg_16x16[i] >> 1))) {
(avg_16x16[m][i] >> 1))) {
force_split[5 + m2 + i] = 1;
force_split[m + 1] = 1;
force_split[0] = 1;
} else if (!is_key_frame && cm->height <= 360 &&
(maxvar_16x16[i] - minvar_16x16[i]) > (thresholds[2] >> 1) &&
maxvar_16x16[i] > thresholds[2]) {
(maxvar_16x16[m][i] - minvar_16x16[m][i]) >
(thresholds[2] >> 1) &&
maxvar_16x16[m][i] > thresholds[2]) {
force_split[5 + m2 + i] = 1;
force_split[m + 1] = 1;
force_split[0] = 1;
@ -702,8 +671,8 @@ int av1_choose_var_based_partitioning(AV1_COMP *cpi, const TileInfo *const tile,
// split. Only checking this for noise level >= medium for now.
if (!is_key_frame &&
(max_var_32x32 - min_var_32x32) > 3 * (thresholds[1] >> 3) &&
max_var_32x32 > thresholds[1] >> 1)
(max_var_32x32[m] - min_var_32x32[m]) > 3 * (thresholds[1] >> 3) &&
max_var_32x32[m] > thresholds[1] >> 1)
force_split[1 + m] = 1;
}
if (is_small_sb) force_split[0] = 1;

View file

@ -17,9 +17,9 @@
#include "aom_ports/mem.h"
#include "av1/encoder/corner_match.h"
DECLARE_ALIGNED(16, static const uint8_t, byte_mask[16]) = {
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0
};
DECLARE_ALIGNED(16, static const uint8_t,
byte_mask[16]) = { 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 0, 0, 0 };
#if MATCH_SZ != 13
#error "Need to change byte_mask in corner_match_sse4.c if MATCH_SZ != 13"
#endif

Some files were not shown because too many files have changed in this diff Show more