Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 1 | /* |
Yaowu Xu | 9c01aa1 | 2016-09-01 14:32:49 -0700 | [diff] [blame] | 2 | * Copyright (c) 2016, Alliance for Open Media. All rights reserved |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 3 | * |
Yaowu Xu | 9c01aa1 | 2016-09-01 14:32:49 -0700 | [diff] [blame] | 4 | * This source code is subject to the terms of the BSD 2 Clause License and |
| 5 | * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License |
| 6 | * was not distributed with this source code in the LICENSE file, you can |
| 7 | * obtain it at www.aomedia.org/license/software. If the Alliance for Open |
| 8 | * Media Patent License 1.0 was not distributed with this source code in the |
| 9 | * PATENTS file, you can obtain it at www.aomedia.org/license/patent. |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 10 | */ |
| 11 | |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 12 | #include "aom_dsp/quantize.h" |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 13 | #include "aom_mem/aom_mem.h" |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 14 | |
Thomas Davies | f3b5ee1 | 2017-07-18 15:16:43 +0100 | [diff] [blame] | 15 | void quantize_b_helper_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs, |
| 16 | int skip_block, const int16_t *zbin_ptr, |
| 17 | const int16_t *round_ptr, const int16_t *quant_ptr, |
| 18 | const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr, |
| 19 | tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, |
| 20 | uint16_t *eob_ptr, const int16_t *scan, |
| 21 | const int16_t *iscan, const qm_val_t *qm_ptr, |
| 22 | const qm_val_t *iqm_ptr, const int log_scale) { |
Cheng Chen | ce8275c | 2017-04-26 11:16:24 -0700 | [diff] [blame] | 23 | const int zbins[2] = { ROUND_POWER_OF_TWO(zbin_ptr[0], log_scale), |
| 24 | ROUND_POWER_OF_TWO(zbin_ptr[1], log_scale) }; |
| 25 | const int nzbins[2] = { zbins[0] * -1, zbins[1] * -1 }; |
| 26 | int i, non_zero_count = (int)n_coeffs, eob = -1; |
| 27 | (void)iscan; |
| 28 | |
| 29 | memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr)); |
| 30 | memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr)); |
| 31 | |
| 32 | if (!skip_block) { |
| 33 | // Pre-scan pass |
| 34 | for (i = (int)n_coeffs - 1; i >= 0; i--) { |
| 35 | const int rc = scan[i]; |
Thomas Davies | f3b5ee1 | 2017-07-18 15:16:43 +0100 | [diff] [blame] | 36 | const qm_val_t wt = qm_ptr != NULL ? qm_ptr[rc] : (1 << AOM_QM_BITS); |
Cheng Chen | ce8275c | 2017-04-26 11:16:24 -0700 | [diff] [blame] | 37 | const int coeff = coeff_ptr[rc] * wt; |
Cheng Chen | ce8275c | 2017-04-26 11:16:24 -0700 | [diff] [blame] | 38 | |
Hui Su | ce2e337 | 2017-08-09 15:18:05 -0700 | [diff] [blame] | 39 | if (coeff < (zbins[rc != 0] * (1 << AOM_QM_BITS)) && |
| 40 | coeff > (nzbins[rc != 0] * (1 << AOM_QM_BITS))) |
Cheng Chen | ce8275c | 2017-04-26 11:16:24 -0700 | [diff] [blame] | 41 | non_zero_count--; |
Cheng Chen | ce8275c | 2017-04-26 11:16:24 -0700 | [diff] [blame] | 42 | else |
| 43 | break; |
| 44 | } |
| 45 | |
| 46 | // Quantization pass: All coefficients with index >= zero_flag are |
| 47 | // skippable. Note: zero_flag can be zero. |
| 48 | for (i = 0; i < non_zero_count; i++) { |
| 49 | const int rc = scan[i]; |
| 50 | const int coeff = coeff_ptr[rc]; |
| 51 | const int coeff_sign = (coeff >> 31); |
| 52 | const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign; |
| 53 | int tmp32; |
| 54 | |
Thomas Davies | f3b5ee1 | 2017-07-18 15:16:43 +0100 | [diff] [blame] | 55 | const qm_val_t wt = qm_ptr != NULL ? qm_ptr[rc] : (1 << AOM_QM_BITS); |
Cheng Chen | ce8275c | 2017-04-26 11:16:24 -0700 | [diff] [blame] | 56 | if (abs_coeff * wt >= (zbins[rc != 0] << AOM_QM_BITS)) { |
Cheng Chen | ce8275c | 2017-04-26 11:16:24 -0700 | [diff] [blame] | 57 | int64_t tmp = |
| 58 | clamp(abs_coeff + ROUND_POWER_OF_TWO(round_ptr[rc != 0], log_scale), |
| 59 | INT16_MIN, INT16_MAX); |
Cheng Chen | ce8275c | 2017-04-26 11:16:24 -0700 | [diff] [blame] | 60 | tmp *= wt; |
| 61 | tmp32 = (int)(((((tmp * quant_ptr[rc != 0]) >> 16) + tmp) * |
| 62 | quant_shift_ptr[rc != 0]) >> |
| 63 | (16 - log_scale + AOM_QM_BITS)); // quantization |
Jingning Han | d18c84c | 2017-04-27 11:25:29 -0700 | [diff] [blame] | 64 | qcoeff_ptr[rc] = (tmp32 ^ coeff_sign) - coeff_sign; |
Thomas Davies | f3b5ee1 | 2017-07-18 15:16:43 +0100 | [diff] [blame] | 65 | const int iwt = iqm_ptr != NULL ? iqm_ptr[rc] : (1 << AOM_QM_BITS); |
Cheng Chen | ce8275c | 2017-04-26 11:16:24 -0700 | [diff] [blame] | 66 | const int dequant = |
Thomas Davies | f3b5ee1 | 2017-07-18 15:16:43 +0100 | [diff] [blame] | 67 | (dequant_ptr[rc != 0] * iwt + (1 << (AOM_QM_BITS - 1))) >> |
Cheng Chen | ce8275c | 2017-04-26 11:16:24 -0700 | [diff] [blame] | 68 | AOM_QM_BITS; |
| 69 | dqcoeff_ptr[rc] = qcoeff_ptr[rc] * dequant / (1 << log_scale); |
Cheng Chen | ce8275c | 2017-04-26 11:16:24 -0700 | [diff] [blame] | 70 | |
| 71 | if (tmp32) eob = i; |
| 72 | } |
| 73 | } |
| 74 | } |
| 75 | *eob_ptr = eob + 1; |
| 76 | } |
| 77 | |
Thomas Davies | f3b5ee1 | 2017-07-18 15:16:43 +0100 | [diff] [blame] | 78 | void highbd_quantize_b_helper_c( |
| 79 | const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, |
| 80 | const int16_t *zbin_ptr, const int16_t *round_ptr, const int16_t *quant_ptr, |
| 81 | const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr, |
| 82 | tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, |
| 83 | const int16_t *scan, const int16_t *iscan, const qm_val_t *qm_ptr, |
| 84 | const qm_val_t *iqm_ptr, const int log_scale) { |
| 85 | int i, eob = -1; |
| 86 | const int zbins[2] = { ROUND_POWER_OF_TWO(zbin_ptr[0], log_scale), |
| 87 | ROUND_POWER_OF_TWO(zbin_ptr[1], log_scale) }; |
| 88 | const int nzbins[2] = { zbins[0] * -1, zbins[1] * -1 }; |
| 89 | int dequant; |
Thomas Davies | f3b5ee1 | 2017-07-18 15:16:43 +0100 | [diff] [blame] | 90 | int idx_arr[4096]; |
Thomas Davies | f3b5ee1 | 2017-07-18 15:16:43 +0100 | [diff] [blame] | 91 | (void)iscan; |
| 92 | int idx = 0; |
| 93 | |
| 94 | memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr)); |
| 95 | memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr)); |
| 96 | |
| 97 | if (!skip_block) { |
| 98 | // Pre-scan pass |
| 99 | for (i = 0; i < n_coeffs; i++) { |
| 100 | const int rc = scan[i]; |
| 101 | const qm_val_t wt = qm_ptr != NULL ? qm_ptr[rc] : (1 << AOM_QM_BITS); |
| 102 | const int coeff = coeff_ptr[rc] * wt; |
| 103 | |
| 104 | // If the coefficient is out of the base ZBIN range, keep it for |
| 105 | // quantization. |
Hui Su | ce2e337 | 2017-08-09 15:18:05 -0700 | [diff] [blame] | 106 | if (coeff >= (zbins[rc != 0] * (1 << AOM_QM_BITS)) || |
| 107 | coeff <= (nzbins[rc != 0] * (1 << AOM_QM_BITS))) |
Thomas Davies | f3b5ee1 | 2017-07-18 15:16:43 +0100 | [diff] [blame] | 108 | idx_arr[idx++] = i; |
| 109 | } |
| 110 | |
| 111 | // Quantization pass: only process the coefficients selected in |
| 112 | // pre-scan pass. Note: idx can be zero. |
| 113 | for (i = 0; i < idx; i++) { |
| 114 | const int rc = scan[idx_arr[i]]; |
| 115 | const int coeff = coeff_ptr[rc]; |
| 116 | const int coeff_sign = (coeff >> 31); |
| 117 | const qm_val_t wt = qm_ptr != NULL ? qm_ptr[rc] : (1 << AOM_QM_BITS); |
| 118 | const qm_val_t iwt = iqm_ptr != NULL ? iqm_ptr[rc] : (1 << AOM_QM_BITS); |
| 119 | const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign; |
| 120 | const int64_t tmp1 = |
| 121 | abs_coeff + ROUND_POWER_OF_TWO(round_ptr[rc != 0], log_scale); |
| 122 | const int64_t tmpw = tmp1 * wt; |
| 123 | const int64_t tmp2 = ((tmpw * quant_ptr[rc != 0]) >> 16) + tmpw; |
Hui Su | b293518 | 2017-08-09 15:34:28 -0700 | [diff] [blame] | 124 | const int abs_qcoeff = (int)((tmp2 * quant_shift_ptr[rc != 0]) >> |
| 125 | (16 - log_scale + AOM_QM_BITS)); |
Thomas Davies | f3b5ee1 | 2017-07-18 15:16:43 +0100 | [diff] [blame] | 126 | qcoeff_ptr[rc] = (tran_low_t)((abs_qcoeff ^ coeff_sign) - coeff_sign); |
| 127 | dequant = (dequant_ptr[rc != 0] * iwt + (1 << (AOM_QM_BITS - 1))) >> |
| 128 | AOM_QM_BITS; |
| 129 | dqcoeff_ptr[rc] = (qcoeff_ptr[rc] * dequant) / (1 << log_scale); |
| 130 | if (abs_qcoeff) eob = idx_arr[i]; |
| 131 | } |
| 132 | } |
| 133 | *eob_ptr = eob + 1; |
| 134 | } |
| 135 | |
Thomas Davies | f3b5ee1 | 2017-07-18 15:16:43 +0100 | [diff] [blame] | 136 | /* These functions should only be called when quantisation matrices |
| 137 | are not used. */ |
Cheng Chen | ce8275c | 2017-04-26 11:16:24 -0700 | [diff] [blame] | 138 | void aom_quantize_b_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs, |
| 139 | int skip_block, const int16_t *zbin_ptr, |
| 140 | const int16_t *round_ptr, const int16_t *quant_ptr, |
| 141 | const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr, |
| 142 | tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, |
| 143 | uint16_t *eob_ptr, const int16_t *scan, |
Thomas Davies | f3b5ee1 | 2017-07-18 15:16:43 +0100 | [diff] [blame] | 144 | const int16_t *iscan) { |
Cheng Chen | ce8275c | 2017-04-26 11:16:24 -0700 | [diff] [blame] | 145 | quantize_b_helper_c(coeff_ptr, n_coeffs, skip_block, zbin_ptr, round_ptr, |
| 146 | quant_ptr, quant_shift_ptr, qcoeff_ptr, dqcoeff_ptr, |
Thomas Davies | f3b5ee1 | 2017-07-18 15:16:43 +0100 | [diff] [blame] | 147 | dequant_ptr, eob_ptr, scan, iscan, NULL, NULL, 0); |
Cheng Chen | ce8275c | 2017-04-26 11:16:24 -0700 | [diff] [blame] | 148 | } |
| 149 | |
| 150 | void aom_quantize_b_32x32_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs, |
| 151 | int skip_block, const int16_t *zbin_ptr, |
| 152 | const int16_t *round_ptr, const int16_t *quant_ptr, |
| 153 | const int16_t *quant_shift_ptr, |
| 154 | tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, |
| 155 | const int16_t *dequant_ptr, uint16_t *eob_ptr, |
Thomas Davies | f3b5ee1 | 2017-07-18 15:16:43 +0100 | [diff] [blame] | 156 | const int16_t *scan, const int16_t *iscan) { |
Cheng Chen | ce8275c | 2017-04-26 11:16:24 -0700 | [diff] [blame] | 157 | quantize_b_helper_c(coeff_ptr, n_coeffs, skip_block, zbin_ptr, round_ptr, |
| 158 | quant_ptr, quant_shift_ptr, qcoeff_ptr, dqcoeff_ptr, |
Thomas Davies | f3b5ee1 | 2017-07-18 15:16:43 +0100 | [diff] [blame] | 159 | dequant_ptr, eob_ptr, scan, iscan, NULL, NULL, 1); |
Cheng Chen | ce8275c | 2017-04-26 11:16:24 -0700 | [diff] [blame] | 160 | } |
| 161 | |
Cheng Chen | ce8275c | 2017-04-26 11:16:24 -0700 | [diff] [blame] | 162 | void aom_quantize_b_64x64_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs, |
| 163 | int skip_block, const int16_t *zbin_ptr, |
| 164 | const int16_t *round_ptr, const int16_t *quant_ptr, |
| 165 | const int16_t *quant_shift_ptr, |
| 166 | tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, |
| 167 | const int16_t *dequant_ptr, uint16_t *eob_ptr, |
Thomas Davies | f3b5ee1 | 2017-07-18 15:16:43 +0100 | [diff] [blame] | 168 | const int16_t *scan, const int16_t *iscan) { |
Cheng Chen | ce8275c | 2017-04-26 11:16:24 -0700 | [diff] [blame] | 169 | quantize_b_helper_c(coeff_ptr, n_coeffs, skip_block, zbin_ptr, round_ptr, |
| 170 | quant_ptr, quant_shift_ptr, qcoeff_ptr, dqcoeff_ptr, |
Thomas Davies | f3b5ee1 | 2017-07-18 15:16:43 +0100 | [diff] [blame] | 171 | dequant_ptr, eob_ptr, scan, iscan, NULL, NULL, 2); |
Cheng Chen | ce8275c | 2017-04-26 11:16:24 -0700 | [diff] [blame] | 172 | } |
Cheng Chen | ce8275c | 2017-04-26 11:16:24 -0700 | [diff] [blame] | 173 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 174 | void aom_highbd_quantize_b_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs, |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 175 | int skip_block, const int16_t *zbin_ptr, |
| 176 | const int16_t *round_ptr, const int16_t *quant_ptr, |
| 177 | const int16_t *quant_shift_ptr, |
| 178 | tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, |
| 179 | const int16_t *dequant_ptr, uint16_t *eob_ptr, |
| 180 | const int16_t *scan, const int16_t *iscan) { |
Thomas Davies | f3b5ee1 | 2017-07-18 15:16:43 +0100 | [diff] [blame] | 181 | highbd_quantize_b_helper_c(coeff_ptr, n_coeffs, skip_block, zbin_ptr, |
| 182 | round_ptr, quant_ptr, quant_shift_ptr, qcoeff_ptr, |
| 183 | dqcoeff_ptr, dequant_ptr, eob_ptr, scan, iscan, |
| 184 | NULL, NULL, 0); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 185 | } |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 186 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 187 | void aom_highbd_quantize_b_32x32_c( |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 188 | const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, |
| 189 | const int16_t *zbin_ptr, const int16_t *round_ptr, const int16_t *quant_ptr, |
| 190 | const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr, |
| 191 | tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, |
| 192 | const int16_t *scan, const int16_t *iscan) { |
Thomas Davies | f3b5ee1 | 2017-07-18 15:16:43 +0100 | [diff] [blame] | 193 | highbd_quantize_b_helper_c(coeff_ptr, n_coeffs, skip_block, zbin_ptr, |
| 194 | round_ptr, quant_ptr, quant_shift_ptr, qcoeff_ptr, |
| 195 | dqcoeff_ptr, dequant_ptr, eob_ptr, scan, iscan, |
| 196 | NULL, NULL, 1); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 197 | } |
Debargha Mukherjee | 0e11912 | 2016-11-04 12:10:23 -0700 | [diff] [blame] | 198 | |
Debargha Mukherjee | 0e11912 | 2016-11-04 12:10:23 -0700 | [diff] [blame] | 199 | void aom_highbd_quantize_b_64x64_c( |
| 200 | const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, |
| 201 | const int16_t *zbin_ptr, const int16_t *round_ptr, const int16_t *quant_ptr, |
| 202 | const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr, |
| 203 | tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, |
| 204 | const int16_t *scan, const int16_t *iscan) { |
Thomas Davies | f3b5ee1 | 2017-07-18 15:16:43 +0100 | [diff] [blame] | 205 | highbd_quantize_b_helper_c(coeff_ptr, n_coeffs, skip_block, zbin_ptr, |
| 206 | round_ptr, quant_ptr, quant_shift_ptr, qcoeff_ptr, |
| 207 | dqcoeff_ptr, dequant_ptr, eob_ptr, scan, iscan, |
| 208 | NULL, NULL, 2); |
Debargha Mukherjee | 0e11912 | 2016-11-04 12:10:23 -0700 | [diff] [blame] | 209 | } |