blob: a7e49e99f3039675cb4880537e9c9749c4b94205 [file] [log] [blame]
Yaowu Xuc27fc142016-08-22 16:08:15 -07001/*
Yaowu Xu2ab7ff02016-09-02 12:04:54 -07002 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Yaowu Xuc27fc142016-08-22 16:08:15 -07003 *
Yaowu Xu2ab7ff02016-09-02 12:04:54 -07004 * 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 Xuc27fc142016-08-22 16:08:15 -070010 */
11
Yaowu Xuf883b422016-08-30 14:01:10 -070012#include "./av1_rtcd.h"
13#include "./aom_config.h"
14#include "./aom_dsp_rtcd.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070015
Nathan E. Egge6675be02016-12-21 13:02:43 -050016#include "aom_dsp/bitwriter.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070017#include "aom_dsp/quantize.h"
Yaowu Xuf883b422016-08-30 14:01:10 -070018#include "aom_mem/aom_mem.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070019#include "aom_ports/mem.h"
20
21#include "av1/common/idct.h"
22#include "av1/common/reconinter.h"
23#include "av1/common/reconintra.h"
24#include "av1/common/scan.h"
25
Tom Finegan17ce8b12017-02-08 12:46:31 -080026#include "av1/encoder/av1_quantize.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070027#include "av1/encoder/encodemb.h"
28#include "av1/encoder/hybrid_fwd_txfm.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070029#include "av1/encoder/rd.h"
30#include "av1/encoder/tokenize.h"
31
Yushin Cho77bba8d2016-11-04 16:36:56 -070032#if CONFIG_PVQ
33#include "av1/encoder/encint.h"
34#include "av1/common/partition.h"
35#include "av1/encoder/pvq_encoder.h"
36#endif
37
Jingning Hane325abd2016-12-01 09:35:10 -080038// Check if one needs to use c version subtraction.
39static int check_subtract_block_size(int w, int h) { return w < 4 || h < 4; }
40
Yaowu Xuf883b422016-08-30 14:01:10 -070041void av1_subtract_plane(MACROBLOCK *x, BLOCK_SIZE bsize, int plane) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070042 struct macroblock_plane *const p = &x->plane[plane];
43 const struct macroblockd_plane *const pd = &x->e_mbd.plane[plane];
44 const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
Jingning Hanae5cfde2016-11-30 12:01:44 -080045 const int bw = block_size_wide[plane_bsize];
46 const int bh = block_size_high[plane_bsize];
Yaowu Xuc27fc142016-08-22 16:08:15 -070047
Jingning Hane325abd2016-12-01 09:35:10 -080048 if (check_subtract_block_size(bw, bh)) {
49#if CONFIG_AOM_HIGHBITDEPTH
50 if (x->e_mbd.cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
51 aom_highbd_subtract_block_c(bh, bw, p->src_diff, bw, p->src.buf,
52 p->src.stride, pd->dst.buf, pd->dst.stride,
53 x->e_mbd.bd);
54 return;
55 }
56#endif // CONFIG_AOM_HIGHBITDEPTH
57 aom_subtract_block_c(bh, bw, p->src_diff, bw, p->src.buf, p->src.stride,
58 pd->dst.buf, pd->dst.stride);
59
60 return;
61 }
62
Yaowu Xuf883b422016-08-30 14:01:10 -070063#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -070064 if (x->e_mbd.cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
Yaowu Xuf883b422016-08-30 14:01:10 -070065 aom_highbd_subtract_block(bh, bw, p->src_diff, bw, p->src.buf,
Yaowu Xuc27fc142016-08-22 16:08:15 -070066 p->src.stride, pd->dst.buf, pd->dst.stride,
67 x->e_mbd.bd);
68 return;
69 }
Yaowu Xuf883b422016-08-30 14:01:10 -070070#endif // CONFIG_AOM_HIGHBITDEPTH
71 aom_subtract_block(bh, bw, p->src_diff, bw, p->src.buf, p->src.stride,
Yaowu Xuc27fc142016-08-22 16:08:15 -070072 pd->dst.buf, pd->dst.stride);
73}
74
Yaowu Xuf883b422016-08-30 14:01:10 -070075typedef struct av1_token_state {
Yaowu Xuc27fc142016-08-22 16:08:15 -070076 int rate;
77 int64_t error;
78 int next;
79 int16_t token;
80 tran_low_t qc;
81 tran_low_t dqc;
Yaowu Xuf883b422016-08-30 14:01:10 -070082} av1_token_state;
Yaowu Xuc27fc142016-08-22 16:08:15 -070083
84// These numbers are empirically obtained.
85static const int plane_rd_mult[REF_TYPES][PLANE_TYPES] = {
86 { 10, 6 }, { 8, 5 },
87};
88
89#define UPDATE_RD_COST() \
90 { \
91 rd_cost0 = RDCOST(rdmult, rddiv, rate0, error0); \
92 rd_cost1 = RDCOST(rdmult, rddiv, rate1, error1); \
93 }
94
Thomas Daviesed8e2d22017-01-04 16:42:09 +000095static inline int64_t get_token_bit_costs(
96 unsigned int token_costs[2][COEFF_CONTEXTS][ENTROPY_TOKENS], int skip_eob,
97 int ctx, int token) {
98#if CONFIG_NEW_TOKENSET
99 (void)skip_eob;
100 return token_costs[token == ZERO_TOKEN || token == EOB_TOKEN][ctx][token];
101#else
102 return token_costs[skip_eob][ctx][token];
103#endif
104}
105
Angie Chiangff6d8902016-10-21 11:02:09 -0700106int av1_optimize_b(const AV1_COMMON *cm, MACROBLOCK *mb, int plane, int block,
107 TX_SIZE tx_size, int ctx) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700108 MACROBLOCKD *const xd = &mb->e_mbd;
109 struct macroblock_plane *const p = &mb->plane[plane];
110 struct macroblockd_plane *const pd = &xd->plane[plane];
111 const int ref = is_inter_block(&xd->mi[0]->mbmi);
Yaowu Xuf883b422016-08-30 14:01:10 -0700112 av1_token_state tokens[MAX_TX_SQUARE + 1][2];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700113 unsigned best_index[MAX_TX_SQUARE + 1][2];
114 uint8_t token_cache[MAX_TX_SQUARE];
Urvang Joshifeb925f2016-12-05 10:37:29 -0800115 const tran_low_t *const coeff = BLOCK_OFFSET(p->coeff, block);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700116 tran_low_t *const qcoeff = BLOCK_OFFSET(p->qcoeff, block);
117 tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
118 const int eob = p->eobs[block];
Debargha Mukherjee3c42c092016-09-29 09:17:36 -0700119 const PLANE_TYPE plane_type = pd->plane_type;
Jingning Hande953b92016-10-25 12:35:43 -0700120 const int default_eob = tx_size_2d[tx_size];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700121 const int16_t *const dequant_ptr = pd->dequant;
122 const uint8_t *const band_translate = get_band_translate(tx_size);
Urvang Joshifeb925f2016-12-05 10:37:29 -0800123 const int block_raster_idx = av1_block_index_to_raster_order(tx_size, block);
124 TX_TYPE tx_type = get_tx_type(plane_type, xd, block_raster_idx, tx_size);
Urvang Joshi03f6fdc2016-10-14 15:53:39 -0700125 const SCAN_ORDER *const scan_order =
Angie Chiangff6d8902016-10-21 11:02:09 -0700126 get_scan(cm, tx_size, tx_type, is_inter_block(&xd->mi[0]->mbmi));
Urvang Joshi03f6fdc2016-10-14 15:53:39 -0700127 const int16_t *const scan = scan_order->scan;
128 const int16_t *const nb = scan_order->neighbors;
Thomas Daviese0f8c552016-11-15 17:28:03 +0000129 int dqv;
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800130 const int shift = get_tx_scale(tx_size);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700131#if CONFIG_AOM_QM
132 int seg_id = xd->mi[0]->mbmi.segment_id;
Debargha Mukherjee3c42c092016-09-29 09:17:36 -0700133 const qm_val_t *iqmatrix = pd->seg_iqmatrix[seg_id][!ref][tx_size];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700134#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -0700135#if CONFIG_NEW_QUANT
David Barkerd7d78c82016-10-24 10:55:35 +0100136 int dq = get_dq_profile_from_ctx(mb->qindex, ctx, ref, plane_type);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700137 const dequant_val_type_nuq *dequant_val = pd->dequant_val_nuq[dq];
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800138#elif !CONFIG_AOM_QM
Yaowu Xuc27fc142016-08-22 16:08:15 -0700139 const int dq_step[2] = { dequant_ptr[0] >> shift, dequant_ptr[1] >> shift };
140#endif // CONFIG_NEW_QUANT
141 int next = eob, sz = 0;
Debargha Mukherjee3c42c092016-09-29 09:17:36 -0700142 const int64_t rdmult = (mb->rdmult * plane_rd_mult[ref][plane_type]) >> 1;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700143 const int64_t rddiv = mb->rddiv;
144 int64_t rd_cost0, rd_cost1;
145 int rate0, rate1;
146 int64_t error0, error1;
147 int16_t t0, t1;
148 int best, band = (eob < default_eob) ? band_translate[eob]
149 : band_translate[eob - 1];
150 int pt, i, final_eob;
Yaowu Xuf883b422016-08-30 14:01:10 -0700151#if CONFIG_AOM_HIGHBITDEPTH
152 const int *cat6_high_cost = av1_get_high_cost_table(xd->bd);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700153#else
Yaowu Xuf883b422016-08-30 14:01:10 -0700154 const int *cat6_high_cost = av1_get_high_cost_table(8);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700155#endif
156 unsigned int(*token_costs)[2][COEFF_CONTEXTS][ENTROPY_TOKENS] =
Debargha Mukherjee3c42c092016-09-29 09:17:36 -0700157 mb->token_costs[txsize_sqr_map[tx_size]][plane_type][ref];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700158 const uint16_t *band_counts = &band_count_table[tx_size][band];
159 uint16_t band_left = eob - band_cum_count_table[tx_size][band] + 1;
160 int shortcut = 0;
161 int next_shortcut = 0;
162
David Barkerd7d78c82016-10-24 10:55:35 +0100163 assert((mb->qindex == 0) ^ (xd->lossless[xd->mi[0]->mbmi.segment_id] == 0));
Debargha Mukherjee3c42c092016-09-29 09:17:36 -0700164
Yaowu Xuc27fc142016-08-22 16:08:15 -0700165 token_costs += band;
166
Debargha Mukherjee3c42c092016-09-29 09:17:36 -0700167 assert((!plane_type && !plane) || (plane_type && plane));
Yaowu Xuc27fc142016-08-22 16:08:15 -0700168 assert(eob <= default_eob);
169
170 /* Now set up a Viterbi trellis to evaluate alternative roundings. */
171 /* Initialize the sentinel node of the trellis. */
172 tokens[eob][0].rate = 0;
173 tokens[eob][0].error = 0;
174 tokens[eob][0].next = default_eob;
175 tokens[eob][0].token = EOB_TOKEN;
176 tokens[eob][0].qc = 0;
177 tokens[eob][1] = tokens[eob][0];
178
179 for (i = 0; i < eob; i++) {
180 const int rc = scan[i];
Yaowu Xuf883b422016-08-30 14:01:10 -0700181 tokens[i][0].rate = av1_get_token_cost(qcoeff[rc], &t0, cat6_high_cost);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700182 tokens[i][0].token = t0;
Yaowu Xuf883b422016-08-30 14:01:10 -0700183 token_cache[rc] = av1_pt_energy_class[t0];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700184 }
185
186 for (i = eob; i-- > 0;) {
187 int base_bits, dx;
188 int64_t d2;
189 const int rc = scan[i];
Thomas Daviese0f8c552016-11-15 17:28:03 +0000190 int x = qcoeff[rc];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700191#if CONFIG_AOM_QM
192 int iwt = iqmatrix[rc];
Thomas Daviese0f8c552016-11-15 17:28:03 +0000193 dqv = dequant_ptr[rc != 0];
194 dqv = ((iwt * (int)dqv) + (1 << (AOM_QM_BITS - 1))) >> AOM_QM_BITS;
195#else
196 dqv = dequant_ptr[rc != 0];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700197#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -0700198 next_shortcut = shortcut;
199
200 /* Only add a trellis state for non-zero coefficients. */
201 if (UNLIKELY(x)) {
202 error0 = tokens[next][0].error;
203 error1 = tokens[next][1].error;
204 /* Evaluate the first possibility for this state. */
205 rate0 = tokens[next][0].rate;
206 rate1 = tokens[next][1].rate;
207
208 if (next_shortcut) {
209 /* Consider both possible successor states. */
210 if (next < default_eob) {
211 pt = get_coef_context(nb, token_cache, i + 1);
Thomas Daviesed8e2d22017-01-04 16:42:09 +0000212 rate0 +=
213 get_token_bit_costs(*token_costs, 0, pt, tokens[next][0].token);
214 rate1 +=
215 get_token_bit_costs(*token_costs, 0, pt, tokens[next][1].token);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700216 }
217 UPDATE_RD_COST();
218 /* And pick the best. */
219 best = rd_cost1 < rd_cost0;
220 } else {
221 if (next < default_eob) {
222 pt = get_coef_context(nb, token_cache, i + 1);
Thomas Daviesed8e2d22017-01-04 16:42:09 +0000223 rate0 +=
224 get_token_bit_costs(*token_costs, 0, pt, tokens[next][0].token);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700225 }
226 best = 0;
227 }
228
229 dx = (dqcoeff[rc] - coeff[rc]) * (1 << shift);
Yaowu Xuf883b422016-08-30 14:01:10 -0700230#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700231 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
232 dx >>= xd->bd - 8;
233 }
Yaowu Xuf883b422016-08-30 14:01:10 -0700234#endif // CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700235 d2 = (int64_t)dx * dx;
236 tokens[i][0].rate += (best ? rate1 : rate0);
237 tokens[i][0].error = d2 + (best ? error1 : error0);
238 tokens[i][0].next = next;
239 tokens[i][0].qc = x;
240 tokens[i][0].dqc = dqcoeff[rc];
241 best_index[i][0] = best;
242
243 /* Evaluate the second possibility for this state. */
244 rate0 = tokens[next][0].rate;
245 rate1 = tokens[next][1].rate;
246
247 // The threshold of 3 is empirically obtained.
248 if (UNLIKELY(abs(x) > 3)) {
249 shortcut = 0;
250 } else {
251#if CONFIG_NEW_QUANT
Thomas Daviese0f8c552016-11-15 17:28:03 +0000252 shortcut = ((av1_dequant_abscoeff_nuq(abs(x), dqv,
Yaowu Xuf883b422016-08-30 14:01:10 -0700253 dequant_val[band_translate[i]]) >
Yaowu Xuc27fc142016-08-22 16:08:15 -0700254 (abs(coeff[rc]) << shift)) &&
Thomas Daviese0f8c552016-11-15 17:28:03 +0000255 (av1_dequant_abscoeff_nuq(abs(x) - 1, dqv,
Yaowu Xuf883b422016-08-30 14:01:10 -0700256 dequant_val[band_translate[i]]) <
Yaowu Xuc27fc142016-08-22 16:08:15 -0700257 (abs(coeff[rc]) << shift)));
258#else // CONFIG_NEW_QUANT
259#if CONFIG_AOM_QM
260 if ((abs(x) * dequant_ptr[rc != 0] * iwt >
261 ((abs(coeff[rc]) << shift) << AOM_QM_BITS)) &&
262 (abs(x) * dequant_ptr[rc != 0] * iwt <
263 (((abs(coeff[rc]) << shift) + dequant_ptr[rc != 0])
264 << AOM_QM_BITS)))
265#else
266 if ((abs(x) * dequant_ptr[rc != 0] > (abs(coeff[rc]) << shift)) &&
267 (abs(x) * dequant_ptr[rc != 0] <
268 (abs(coeff[rc]) << shift) + dequant_ptr[rc != 0]))
269#endif // CONFIG_AOM_QM
270 shortcut = 1;
271 else
272 shortcut = 0;
273#endif // CONFIG_NEW_QUANT
274 }
275
276 if (shortcut) {
277 sz = -(x < 0);
278 x -= 2 * sz + 1;
279 } else {
280 tokens[i][1] = tokens[i][0];
281 best_index[i][1] = best_index[i][0];
282 next = i;
283
284 if (UNLIKELY(!(--band_left))) {
285 --band_counts;
286 band_left = *band_counts;
287 --token_costs;
288 }
289 continue;
290 }
291
292 /* Consider both possible successor states. */
293 if (!x) {
294 /* If we reduced this coefficient to zero, check to see if
295 * we need to move the EOB back here.
296 */
297 t0 = tokens[next][0].token == EOB_TOKEN ? EOB_TOKEN : ZERO_TOKEN;
298 t1 = tokens[next][1].token == EOB_TOKEN ? EOB_TOKEN : ZERO_TOKEN;
299 base_bits = 0;
300 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -0700301 base_bits = av1_get_token_cost(x, &t0, cat6_high_cost);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700302 t1 = t0;
303 }
304
305 if (next_shortcut) {
306 if (LIKELY(next < default_eob)) {
307 if (t0 != EOB_TOKEN) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700308 token_cache[rc] = av1_pt_energy_class[t0];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700309 pt = get_coef_context(nb, token_cache, i + 1);
Thomas Daviesed8e2d22017-01-04 16:42:09 +0000310 rate0 += get_token_bit_costs(*token_costs, !x, pt,
311 tokens[next][0].token);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700312 }
313 if (t1 != EOB_TOKEN) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700314 token_cache[rc] = av1_pt_energy_class[t1];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700315 pt = get_coef_context(nb, token_cache, i + 1);
Thomas Daviesed8e2d22017-01-04 16:42:09 +0000316 rate1 += get_token_bit_costs(*token_costs, !x, pt,
317 tokens[next][1].token);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700318 }
319 }
320
321 UPDATE_RD_COST();
322 /* And pick the best. */
323 best = rd_cost1 < rd_cost0;
324 } else {
325 // The two states in next stage are identical.
326 if (next < default_eob && t0 != EOB_TOKEN) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700327 token_cache[rc] = av1_pt_energy_class[t0];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700328 pt = get_coef_context(nb, token_cache, i + 1);
Thomas Daviesed8e2d22017-01-04 16:42:09 +0000329 rate0 +=
330 get_token_bit_costs(*token_costs, !x, pt, tokens[next][0].token);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700331 }
332 best = 0;
333 }
334
335#if CONFIG_NEW_QUANT
Thomas Daviese0f8c552016-11-15 17:28:03 +0000336 dx = av1_dequant_coeff_nuq(x, dqv, dequant_val[band_translate[i]]) -
Yaowu Xuc27fc142016-08-22 16:08:15 -0700337 (coeff[rc] << shift);
Yaowu Xuf883b422016-08-30 14:01:10 -0700338#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700339 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
340 dx >>= xd->bd - 8;
341 }
Yaowu Xuf883b422016-08-30 14:01:10 -0700342#endif // CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700343#else // CONFIG_NEW_QUANT
Yaowu Xuf883b422016-08-30 14:01:10 -0700344#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700345 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
Thomas Daviese0f8c552016-11-15 17:28:03 +0000346 dx -= ((dqv >> (xd->bd - 8)) + sz) ^ sz;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700347 } else {
Thomas Daviese0f8c552016-11-15 17:28:03 +0000348 dx -= (dqv + sz) ^ sz;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700349 }
350#else
Thomas Daviese0f8c552016-11-15 17:28:03 +0000351 dx -= (dqv + sz) ^ sz;
Yaowu Xuf883b422016-08-30 14:01:10 -0700352#endif // CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700353#endif // CONFIG_NEW_QUANT
354 d2 = (int64_t)dx * dx;
355
356 tokens[i][1].rate = base_bits + (best ? rate1 : rate0);
357 tokens[i][1].error = d2 + (best ? error1 : error0);
358 tokens[i][1].next = next;
359 tokens[i][1].token = best ? t1 : t0;
360 tokens[i][1].qc = x;
361
362 if (x) {
363#if CONFIG_NEW_QUANT
Yaowu Xuf883b422016-08-30 14:01:10 -0700364 tokens[i][1].dqc = av1_dequant_abscoeff_nuq(
Thomas Daviese0f8c552016-11-15 17:28:03 +0000365 abs(x), dqv, dequant_val[band_translate[i]]);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700366 tokens[i][1].dqc = shift ? ROUND_POWER_OF_TWO(tokens[i][1].dqc, shift)
367 : tokens[i][1].dqc;
368 if (sz) tokens[i][1].dqc = -tokens[i][1].dqc;
369#else
Debargha Mukherjeeb98a7022016-11-15 16:07:12 -0800370// The 32x32 transform coefficient uses half quantization step size.
371// Account for the rounding difference in the dequantized coefficeint
372// value when the quantization index is dropped from an even number
373// to an odd number.
Thomas Daviese0f8c552016-11-15 17:28:03 +0000374
375#if CONFIG_AOM_QM
376 tran_low_t offset = dqv >> shift;
377#else
378 tran_low_t offset = dq_step[rc != 0];
379#endif
380 if (shift & x) offset += (dqv & 0x01);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700381
382 if (sz == 0)
383 tokens[i][1].dqc = dqcoeff[rc] - offset;
384 else
385 tokens[i][1].dqc = dqcoeff[rc] + offset;
386#endif // CONFIG_NEW_QUANT
387 } else {
388 tokens[i][1].dqc = 0;
389 }
390
391 best_index[i][1] = best;
392 /* Finally, make this the new head of the trellis. */
393 next = i;
394 } else {
395 /* There's no choice to make for a zero coefficient, so we don't
396 * add a new trellis node, but we do need to update the costs.
397 */
398 t0 = tokens[next][0].token;
399 t1 = tokens[next][1].token;
400 pt = get_coef_context(nb, token_cache, i + 1);
401 /* Update the cost of each path if we're past the EOB token. */
402 if (t0 != EOB_TOKEN) {
Thomas Daviesed8e2d22017-01-04 16:42:09 +0000403 tokens[next][0].rate += get_token_bit_costs(*token_costs, 1, pt, t0);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700404 tokens[next][0].token = ZERO_TOKEN;
405 }
406 if (t1 != EOB_TOKEN) {
Thomas Daviesed8e2d22017-01-04 16:42:09 +0000407 tokens[next][1].rate += get_token_bit_costs(*token_costs, 1, pt, t1);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700408 tokens[next][1].token = ZERO_TOKEN;
409 }
410 best_index[i][0] = best_index[i][1] = 0;
411 shortcut = (tokens[next][0].rate != tokens[next][1].rate);
412 /* Don't update next, because we didn't add a new node. */
413 }
414
415 if (UNLIKELY(!(--band_left))) {
416 --band_counts;
417 band_left = *band_counts;
418 --token_costs;
419 }
420 }
421
422 /* Now pick the best path through the whole trellis. */
423 rate0 = tokens[next][0].rate;
424 rate1 = tokens[next][1].rate;
425 error0 = tokens[next][0].error;
426 error1 = tokens[next][1].error;
427 t0 = tokens[next][0].token;
428 t1 = tokens[next][1].token;
Thomas Daviesed8e2d22017-01-04 16:42:09 +0000429 rate0 += get_token_bit_costs(*token_costs, 0, ctx, t0);
430 rate1 += get_token_bit_costs(*token_costs, 0, ctx, t1);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700431 UPDATE_RD_COST();
432 best = rd_cost1 < rd_cost0;
433
434 final_eob = -1;
435
436 for (i = next; i < eob; i = next) {
437 const int x = tokens[i][best].qc;
438 const int rc = scan[i];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700439 if (x) final_eob = i;
440 qcoeff[rc] = x;
441 dqcoeff[rc] = tokens[i][best].dqc;
442
443 next = tokens[i][best].next;
444 best = best_index[i][best];
445 }
446 final_eob++;
447
448 mb->plane[plane].eobs[block] = final_eob;
449 assert(final_eob <= default_eob);
450 return final_eob;
451}
452
Yaowu Xuf883b422016-08-30 14:01:10 -0700453#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700454typedef enum QUANT_FUNC {
455 QUANT_FUNC_LOWBD = 0,
456 QUANT_FUNC_HIGHBD = 1,
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800457 QUANT_FUNC_TYPES = 2
Yaowu Xuc27fc142016-08-22 16:08:15 -0700458} QUANT_FUNC;
459
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800460static AV1_QUANT_FACADE
461 quant_func_list[AV1_XFORM_QUANT_TYPES][QUANT_FUNC_TYPES] = {
462 { av1_quantize_fp_facade, av1_highbd_quantize_fp_facade },
Yaowu Xuf883b422016-08-30 14:01:10 -0700463 { av1_quantize_b_facade, av1_highbd_quantize_b_facade },
464 { av1_quantize_dc_facade, av1_highbd_quantize_dc_facade },
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800465#if CONFIG_NEW_QUANT
466 { av1_quantize_fp_nuq_facade, av1_highbd_quantize_fp_nuq_facade },
467 { av1_quantize_b_nuq_facade, av1_highbd_quantize_b_nuq_facade },
468 { av1_quantize_dc_nuq_facade, av1_highbd_quantize_dc_nuq_facade },
469#endif // CONFIG_NEW_QUANT
470 { NULL, NULL }
471 };
Yaowu Xuc27fc142016-08-22 16:08:15 -0700472
Yaowu Xu02d4c3b2016-11-07 10:45:56 -0800473#elif !CONFIG_PVQ
474
Yaowu Xuc27fc142016-08-22 16:08:15 -0700475typedef enum QUANT_FUNC {
476 QUANT_FUNC_LOWBD = 0,
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800477 QUANT_FUNC_TYPES = 1
Yaowu Xuc27fc142016-08-22 16:08:15 -0700478} QUANT_FUNC;
479
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800480static AV1_QUANT_FACADE quant_func_list[AV1_XFORM_QUANT_TYPES]
481 [QUANT_FUNC_TYPES] = {
clang-format67948d32016-09-07 22:40:40 -0700482 { av1_quantize_fp_facade },
483 { av1_quantize_b_facade },
484 { av1_quantize_dc_facade },
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800485#if CONFIG_NEW_QUANT
486 { av1_quantize_fp_nuq_facade },
487 { av1_quantize_b_nuq_facade },
488 { av1_quantize_dc_nuq_facade },
489#endif // CONFIG_NEW_QUANT
clang-format67948d32016-09-07 22:40:40 -0700490 { NULL }
491 };
Yaowu Xuc27fc142016-08-22 16:08:15 -0700492#endif
493
Angie Chiangff6d8902016-10-21 11:02:09 -0700494void av1_xform_quant(const AV1_COMMON *cm, MACROBLOCK *x, int plane, int block,
495 int blk_row, int blk_col, BLOCK_SIZE plane_bsize,
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800496 TX_SIZE tx_size, int ctx,
497 AV1_XFORM_QUANT xform_quant_idx) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700498 MACROBLOCKD *const xd = &x->e_mbd;
Yushin Cho7a428ba2017-01-12 16:28:49 -0800499#if !(CONFIG_PVQ || CONFIG_DAALA_DIST)
Yaowu Xuc27fc142016-08-22 16:08:15 -0700500 const struct macroblock_plane *const p = &x->plane[plane];
501 const struct macroblockd_plane *const pd = &xd->plane[plane];
Yushin Cho77bba8d2016-11-04 16:36:56 -0700502#else
503 struct macroblock_plane *const p = &x->plane[plane];
504 struct macroblockd_plane *const pd = &xd->plane[plane];
505#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -0700506 PLANE_TYPE plane_type = (plane == 0) ? PLANE_TYPE_Y : PLANE_TYPE_UV;
Urvang Joshifeb925f2016-12-05 10:37:29 -0800507 const int block_raster_idx = av1_block_index_to_raster_order(tx_size, block);
508 TX_TYPE tx_type = get_tx_type(plane_type, xd, block_raster_idx, tx_size);
Debargha Mukherjee3c42c092016-09-29 09:17:36 -0700509 const int is_inter = is_inter_block(&xd->mi[0]->mbmi);
Angie Chiangff6d8902016-10-21 11:02:09 -0700510 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, is_inter);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700511 tran_low_t *const coeff = BLOCK_OFFSET(p->coeff, block);
512 tran_low_t *const qcoeff = BLOCK_OFFSET(p->qcoeff, block);
513 tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
514 uint16_t *const eob = &p->eobs[block];
Jingning Hanae5cfde2016-11-30 12:01:44 -0800515 const int diff_stride = block_size_wide[plane_bsize];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700516#if CONFIG_AOM_QM
517 int seg_id = xd->mi[0]->mbmi.segment_id;
Debargha Mukherjee3c42c092016-09-29 09:17:36 -0700518 const qm_val_t *qmatrix = pd->seg_qmatrix[seg_id][!is_inter][tx_size];
519 const qm_val_t *iqmatrix = pd->seg_iqmatrix[seg_id][!is_inter][tx_size];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700520#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -0700521
522 FWD_TXFM_PARAM fwd_txfm_param;
Yushin Cho77bba8d2016-11-04 16:36:56 -0700523
Yushin Cho7a428ba2017-01-12 16:28:49 -0800524#if CONFIG_PVQ || CONFIG_DAALA_DIST
525 uint8_t *dst;
526 int16_t *pred;
527 const int dst_stride = pd->dst.stride;
528 int tx_blk_size;
529 int i, j;
530#endif
531
Yushin Cho77bba8d2016-11-04 16:36:56 -0700532#if !CONFIG_PVQ
533 const int tx2d_size = tx_size_2d[tx_size];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700534 QUANT_PARAM qparam;
Yushin Cho77bba8d2016-11-04 16:36:56 -0700535 const int16_t *src_diff;
536
Jingning Han81492262016-12-05 15:48:47 -0800537 src_diff =
538 &p->src_diff[(blk_row * diff_stride + blk_col) << tx_size_wide_log2[0]];
Debargha Mukherjee0e119122016-11-04 12:10:23 -0700539 qparam.log_scale = get_tx_scale(tx_size);
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800540#if CONFIG_NEW_QUANT
541 qparam.tx_size = tx_size;
542 qparam.dq = get_dq_profile_from_ctx(x->qindex, ctx, is_inter, plane_type);
543#endif // CONFIG_NEW_QUANT
544#if CONFIG_AOM_QM
545 qparam.qmatrix = qmatrix;
546 qparam.iqmatrix = iqmatrix;
547#endif // CONFIG_AOM_QM
Yushin Cho77bba8d2016-11-04 16:36:56 -0700548#else
549 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
550 tran_low_t *ref_coeff = BLOCK_OFFSET(pd->pvq_ref_coeff, block);
Yushin Cho77bba8d2016-11-04 16:36:56 -0700551 int skip = 1;
552 PVQ_INFO *pvq_info = NULL;
Yushin Cho7a428ba2017-01-12 16:28:49 -0800553 uint8_t *src;
554 int16_t *src_int16;
555 const int src_stride = p->src.stride;
Yushin Cho77bba8d2016-11-04 16:36:56 -0700556
557 (void)scan_order;
558 (void)qcoeff;
559
560 if (x->pvq_coded) {
561 assert(block < MAX_PVQ_BLOCKS_IN_SB);
562 pvq_info = &x->pvq[block][plane];
563 }
Jingning Han81492262016-12-05 15:48:47 -0800564 src = &p->src.buf[(blk_row * src_stride + blk_col) << tx_size_wide_log2[0]];
565 src_int16 =
566 &p->src_int16[(blk_row * diff_stride + blk_col) << tx_size_wide_log2[0]];
Yushin Cho7a428ba2017-01-12 16:28:49 -0800567
568 // transform block size in pixels
569 tx_blk_size = tx_size_wide[tx_size];
570
571 for (j = 0; j < tx_blk_size; j++)
572 for (i = 0; i < tx_blk_size; i++)
573 src_int16[diff_stride * j + i] = src[src_stride * j + i];
574#endif
575
576#if CONFIG_PVQ || CONFIG_DAALA_DIST
577 dst = &pd->dst.buf[(blk_row * dst_stride + blk_col) << tx_size_wide_log2[0]];
Jingning Han81492262016-12-05 15:48:47 -0800578 pred = &pd->pred[(blk_row * diff_stride + blk_col) << tx_size_wide_log2[0]];
Yushin Cho77bba8d2016-11-04 16:36:56 -0700579
580 // transform block size in pixels
581 tx_blk_size = tx_size_wide[tx_size];
582
583 // copy uint8 orig and predicted block to int16 buffer
584 // in order to use existing VP10 transform functions
585 for (j = 0; j < tx_blk_size; j++)
586 for (i = 0; i < tx_blk_size; i++) {
Yushin Cho77bba8d2016-11-04 16:36:56 -0700587 pred[diff_stride * j + i] = dst[dst_stride * j + i];
588 }
589#endif
Yushin Cho7a428ba2017-01-12 16:28:49 -0800590
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800591 (void)ctx;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700592
593 fwd_txfm_param.tx_type = tx_type;
594 fwd_txfm_param.tx_size = tx_size;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700595 fwd_txfm_param.lossless = xd->lossless[xd->mi[0]->mbmi.segment_id];
596
Yaowu Xuf883b422016-08-30 14:01:10 -0700597#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700598 fwd_txfm_param.bd = xd->bd;
599 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
600 highbd_fwd_txfm(src_diff, coeff, diff_stride, &fwd_txfm_param);
Yaowu Xuf883b422016-08-30 14:01:10 -0700601 if (xform_quant_idx != AV1_XFORM_QUANT_SKIP_QUANT) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700602 if (LIKELY(!x->skip_block)) {
603 quant_func_list[xform_quant_idx][QUANT_FUNC_HIGHBD](
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800604 coeff, tx2d_size, p, qcoeff, pd, dqcoeff, eob, scan_order, &qparam);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700605 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -0700606 av1_quantize_skip(tx2d_size, qcoeff, dqcoeff, eob);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700607 }
608 }
609 return;
610 }
Yaowu Xuf883b422016-08-30 14:01:10 -0700611#endif // CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700612
Yushin Cho77bba8d2016-11-04 16:36:56 -0700613#if !CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -0700614 fwd_txfm(src_diff, coeff, diff_stride, &fwd_txfm_param);
Yaowu Xuf883b422016-08-30 14:01:10 -0700615 if (xform_quant_idx != AV1_XFORM_QUANT_SKIP_QUANT) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700616 if (LIKELY(!x->skip_block)) {
617 quant_func_list[xform_quant_idx][QUANT_FUNC_LOWBD](
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800618 coeff, tx2d_size, p, qcoeff, pd, dqcoeff, eob, scan_order, &qparam);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700619 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -0700620 av1_quantize_skip(tx2d_size, qcoeff, dqcoeff, eob);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700621 }
622 }
Yushin Cho77bba8d2016-11-04 16:36:56 -0700623#else // #if !CONFIG_PVQ
Yushin Cho77bba8d2016-11-04 16:36:56 -0700624
Angie Chiang2cc057c2017-01-03 18:31:47 -0800625 (void)xform_quant_idx;
Yushin Cho77bba8d2016-11-04 16:36:56 -0700626 fwd_txfm(src_int16, coeff, diff_stride, &fwd_txfm_param);
627 fwd_txfm(pred, ref_coeff, diff_stride, &fwd_txfm_param);
628
629 // PVQ for inter mode block
ltrudeau472f63f2017-01-12 15:22:32 -0500630 if (!x->skip_block) {
ltrudeaue1c09292017-01-20 15:42:13 -0500631 PVQ_SKIP_TYPE ac_dc_coded =
632 av1_pvq_encode_helper(&x->daala_enc,
633 coeff, // target original vector
634 ref_coeff, // reference vector
635 dqcoeff, // de-quantized vector
636 eob, // End of Block marker
637 pd->dequant, // aom's quantizers
638 plane, // image plane
639 tx_size, // block size in log_2 - 2
640 tx_type,
641 &x->rate, // rate measured
642 x->pvq_speed,
643 pvq_info); // PVQ info for a block
644 skip = ac_dc_coded == PVQ_SKIP;
ltrudeau472f63f2017-01-12 15:22:32 -0500645 }
Yushin Cho77bba8d2016-11-04 16:36:56 -0700646 x->pvq_skip[plane] = skip;
647
648 if (!skip) mbmi->skip = 0;
649#endif // #if !CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -0700650}
651
Yaowu Xuc27fc142016-08-22 16:08:15 -0700652static void encode_block(int plane, int block, int blk_row, int blk_col,
653 BLOCK_SIZE plane_bsize, TX_SIZE tx_size, void *arg) {
654 struct encode_b_args *const args = arg;
Angie Chiangff6d8902016-10-21 11:02:09 -0700655 AV1_COMMON *cm = args->cm;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700656 MACROBLOCK *const x = args->x;
657 MACROBLOCKD *const xd = &x->e_mbd;
658 int ctx;
659 struct macroblock_plane *const p = &x->plane[plane];
660 struct macroblockd_plane *const pd = &xd->plane[plane];
661 tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
662 uint8_t *dst;
663 ENTROPY_CONTEXT *a, *l;
664 INV_TXFM_PARAM inv_txfm_param;
Urvang Joshifeb925f2016-12-05 10:37:29 -0800665 const int block_raster_idx = av1_block_index_to_raster_order(tx_size, block);
Yushin Cho77bba8d2016-11-04 16:36:56 -0700666#if CONFIG_PVQ
Urvang Joshifeb925f2016-12-05 10:37:29 -0800667 int tx_width_pixels, tx_height_pixels;
Yushin Cho77bba8d2016-11-04 16:36:56 -0700668 int i, j;
669#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -0700670#if CONFIG_VAR_TX
671 int i;
Jingning Han9ca05b72017-01-03 14:41:36 -0800672 int bw = block_size_wide[plane_bsize] >> tx_size_wide_log2[0];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700673#endif
Jingning Han81492262016-12-05 15:48:47 -0800674 dst = &pd->dst
675 .buf[(blk_row * pd->dst.stride + blk_col) << tx_size_wide_log2[0]];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700676 a = &args->ta[blk_col];
677 l = &args->tl[blk_row];
678#if CONFIG_VAR_TX
679 ctx = get_entropy_context(tx_size, a, l);
680#else
681 ctx = combine_entropy_contexts(*a, *l);
682#endif
683
684#if CONFIG_VAR_TX
Yue Chena1e48dc2016-08-29 17:29:33 -0700685 // Assert not magic number (uninitialized).
Jingning Han9ca05b72017-01-03 14:41:36 -0800686 assert(x->blk_skip[plane][blk_row * bw + blk_col] != 234);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700687
Jingning Han9ca05b72017-01-03 14:41:36 -0800688 if (x->blk_skip[plane][blk_row * bw + blk_col] == 0) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700689#else
690 {
691#endif
692#if CONFIG_NEW_QUANT
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800693 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
694 ctx, AV1_XFORM_QUANT_FP_NUQ);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700695#else
Angie Chiangff6d8902016-10-21 11:02:09 -0700696 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800697 ctx, AV1_XFORM_QUANT_FP);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700698#endif // CONFIG_NEW_QUANT
699 }
700#if CONFIG_VAR_TX
701 else {
702 p->eobs[block] = 0;
703 }
704#endif
Yushin Cho77bba8d2016-11-04 16:36:56 -0700705#if !CONFIG_PVQ
Jingning Handb4c9ba2016-11-30 10:00:25 -0800706 if (p->eobs[block] && !xd->lossless[xd->mi[0]->mbmi.segment_id]) {
Angie Chiangff6d8902016-10-21 11:02:09 -0700707 *a = *l = av1_optimize_b(cm, x, plane, block, tx_size, ctx) > 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700708 } else {
709 *a = *l = p->eobs[block] > 0;
710 }
711
712#if CONFIG_VAR_TX
Jingning Hande953b92016-10-25 12:35:43 -0700713 for (i = 0; i < tx_size_wide_unit[tx_size]; ++i) a[i] = a[0];
714
715 for (i = 0; i < tx_size_high_unit[tx_size]; ++i) l[i] = l[0];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700716#endif
717
718 if (p->eobs[block]) *(args->skip) = 0;
719
720 if (p->eobs[block] == 0) return;
Yushin Cho77bba8d2016-11-04 16:36:56 -0700721#else
722 (void)ctx;
723 *a = *l = !x->pvq_skip[plane];
724
725 if (!x->pvq_skip[plane]) *(args->skip) = 0;
726
727 if (x->pvq_skip[plane]) return;
728
729 // transform block size in pixels
Urvang Joshifeb925f2016-12-05 10:37:29 -0800730 tx_width_pixels = tx_size_wide[tx_size];
731 tx_height_pixels = tx_size_high[tx_size];
Yushin Cho77bba8d2016-11-04 16:36:56 -0700732
733 // Since av1 does not have separate function which does inverse transform
734 // but av1_inv_txfm_add_*x*() also does addition of predicted image to
735 // inverse transformed image,
736 // pass blank dummy image to av1_inv_txfm_add_*x*(), i.e. set dst as zeros
Urvang Joshifeb925f2016-12-05 10:37:29 -0800737 for (j = 0; j < tx_height_pixels; j++)
738 for (i = 0; i < tx_width_pixels; i++) dst[j * pd->dst.stride + i] = 0;
Yushin Cho77bba8d2016-11-04 16:36:56 -0700739#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -0700740
741 // inverse transform parameters
Urvang Joshifeb925f2016-12-05 10:37:29 -0800742 inv_txfm_param.tx_type =
743 get_tx_type(pd->plane_type, xd, block_raster_idx, tx_size);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700744 inv_txfm_param.tx_size = tx_size;
745 inv_txfm_param.eob = p->eobs[block];
746 inv_txfm_param.lossless = xd->lossless[xd->mi[0]->mbmi.segment_id];
747
Yaowu Xuf883b422016-08-30 14:01:10 -0700748#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700749 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
750 inv_txfm_param.bd = xd->bd;
751 highbd_inv_txfm_add(dqcoeff, dst, pd->dst.stride, &inv_txfm_param);
752 return;
753 }
Yaowu Xuf883b422016-08-30 14:01:10 -0700754#endif // CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700755 inv_txfm_add(dqcoeff, dst, pd->dst.stride, &inv_txfm_param);
756}
757
758#if CONFIG_VAR_TX
759static void encode_block_inter(int plane, int block, int blk_row, int blk_col,
760 BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
761 void *arg) {
762 struct encode_b_args *const args = arg;
763 MACROBLOCK *const x = args->x;
764 MACROBLOCKD *const xd = &x->e_mbd;
765 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
766 const BLOCK_SIZE bsize = txsize_to_bsize[tx_size];
767 const struct macroblockd_plane *const pd = &xd->plane[plane];
768 const int tx_row = blk_row >> (1 - pd->subsampling_y);
769 const int tx_col = blk_col >> (1 - pd->subsampling_x);
770 TX_SIZE plane_tx_size;
Jingning Hanf65b8702016-10-31 12:13:20 -0700771 const int max_blocks_high = max_block_high(xd, plane_bsize, plane);
772 const int max_blocks_wide = max_block_wide(xd, plane_bsize, plane);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700773
774 if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
775
Debargha Mukherjee2f123402016-08-30 17:43:38 -0700776 plane_tx_size =
777 plane ? uv_txsize_lookup[bsize][mbmi->inter_tx_size[tx_row][tx_col]][0][0]
778 : mbmi->inter_tx_size[tx_row][tx_col];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700779
780 if (tx_size == plane_tx_size) {
781 encode_block(plane, block, blk_row, blk_col, plane_bsize, tx_size, arg);
782 } else {
Jingning Hana9336322016-11-02 15:45:07 -0700783 const TX_SIZE sub_txs = sub_tx_size_map[tx_size];
784 // This is the square transform block partition entry point.
785 int bsl = tx_size_wide_unit[sub_txs];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700786 int i;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700787 assert(bsl > 0);
Jingning Hand3fada82016-11-22 10:46:55 -0800788 assert(tx_size < TX_SIZES_ALL);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700789
790 for (i = 0; i < 4; ++i) {
Jingning Hande953b92016-10-25 12:35:43 -0700791 const int offsetr = blk_row + ((i >> 1) * bsl);
792 const int offsetc = blk_col + ((i & 0x01) * bsl);
Jingning Hande953b92016-10-25 12:35:43 -0700793 int step = tx_size_wide_unit[sub_txs] * tx_size_high_unit[sub_txs];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700794
795 if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide) continue;
796
Jingning Han98d6a1f2016-11-03 12:47:47 -0700797 encode_block_inter(plane, block, offsetr, offsetc, plane_bsize, sub_txs,
798 arg);
799 block += step;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700800 }
801 }
802}
803#endif
804
Angie Chiangff6d8902016-10-21 11:02:09 -0700805typedef struct encode_block_pass1_args {
806 AV1_COMMON *cm;
807 MACROBLOCK *x;
808} encode_block_pass1_args;
809
Yaowu Xuc27fc142016-08-22 16:08:15 -0700810static void encode_block_pass1(int plane, int block, int blk_row, int blk_col,
811 BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
812 void *arg) {
Angie Chiangff6d8902016-10-21 11:02:09 -0700813 encode_block_pass1_args *args = (encode_block_pass1_args *)arg;
814 AV1_COMMON *cm = args->cm;
815 MACROBLOCK *const x = args->x;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700816 MACROBLOCKD *const xd = &x->e_mbd;
817 struct macroblock_plane *const p = &x->plane[plane];
818 struct macroblockd_plane *const pd = &xd->plane[plane];
819 tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
820 uint8_t *dst;
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800821 int ctx = 0;
Jingning Han81492262016-12-05 15:48:47 -0800822 dst = &pd->dst
823 .buf[(blk_row * pd->dst.stride + blk_col) << tx_size_wide_log2[0]];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700824
825#if CONFIG_NEW_QUANT
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800826 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
827 ctx, AV1_XFORM_QUANT_B_NUQ);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700828#else
Angie Chiangff6d8902016-10-21 11:02:09 -0700829 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800830 ctx, AV1_XFORM_QUANT_B);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700831#endif // CONFIG_NEW_QUANT
Yushin Cho77bba8d2016-11-04 16:36:56 -0700832#if !CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -0700833 if (p->eobs[block] > 0) {
Yushin Cho77bba8d2016-11-04 16:36:56 -0700834#else
835 if (!x->pvq_skip[plane]) {
Yushin Cho77bba8d2016-11-04 16:36:56 -0700836 {
837 int tx_blk_size;
838 int i, j;
839 // transform block size in pixels
840 tx_blk_size = tx_size_wide[tx_size];
841
842 // Since av1 does not have separate function which does inverse transform
843 // but av1_inv_txfm_add_*x*() also does addition of predicted image to
844 // inverse transformed image,
845 // pass blank dummy image to av1_inv_txfm_add_*x*(), i.e. set dst as zeros
846 for (j = 0; j < tx_blk_size; j++)
847 for (i = 0; i < tx_blk_size; i++) dst[j * pd->dst.stride + i] = 0;
848 }
Jingning Handf072642016-11-08 16:43:38 -0800849#endif // !CONFIG_PVQ
Yaowu Xuf883b422016-08-30 14:01:10 -0700850#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700851 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
852 if (xd->lossless[xd->mi[0]->mbmi.segment_id]) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700853 av1_highbd_iwht4x4_add(dqcoeff, dst, pd->dst.stride, p->eobs[block],
854 xd->bd);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700855 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -0700856 av1_highbd_idct4x4_add(dqcoeff, dst, pd->dst.stride, p->eobs[block],
857 xd->bd);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700858 }
859 return;
860 }
Jingning Hane38d63c2016-11-08 12:05:29 -0800861#endif // CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700862 if (xd->lossless[xd->mi[0]->mbmi.segment_id]) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700863 av1_iwht4x4_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700864 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -0700865 av1_idct4x4_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700866 }
867 }
868}
869
Angie Chiangff6d8902016-10-21 11:02:09 -0700870void av1_encode_sby_pass1(AV1_COMMON *cm, MACROBLOCK *x, BLOCK_SIZE bsize) {
871 encode_block_pass1_args args = { cm, x };
Yaowu Xuf883b422016-08-30 14:01:10 -0700872 av1_subtract_plane(x, bsize, 0);
873 av1_foreach_transformed_block_in_plane(&x->e_mbd, bsize, 0,
Angie Chiangff6d8902016-10-21 11:02:09 -0700874 encode_block_pass1, &args);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700875}
876
Jingning Han18c53c82017-02-17 14:49:57 -0800877void av1_encode_sb(AV1_COMMON *cm, MACROBLOCK *x, BLOCK_SIZE bsize,
878 const int mi_row, const int mi_col) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700879 MACROBLOCKD *const xd = &x->e_mbd;
880 struct optimize_ctx ctx;
881 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Angie Chiangff6d8902016-10-21 11:02:09 -0700882 struct encode_b_args arg = { cm, x, &ctx, &mbmi->skip, NULL, NULL, 1 };
Yaowu Xuc27fc142016-08-22 16:08:15 -0700883 int plane;
884
885 mbmi->skip = 1;
886
887 if (x->skip) return;
888
889 for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
890#if CONFIG_VAR_TX
891 // TODO(jingning): Clean this up.
892 const struct macroblockd_plane *const pd = &xd->plane[plane];
893 const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
Jingning Hande953b92016-10-25 12:35:43 -0700894 const int mi_width = block_size_wide[plane_bsize] >> tx_size_wide_log2[0];
895 const int mi_height = block_size_high[plane_bsize] >> tx_size_wide_log2[0];
Jingning Han70e5f3f2016-11-09 17:03:07 -0800896 const TX_SIZE max_tx_size = max_txsize_rect_lookup[plane_bsize];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700897 const BLOCK_SIZE txb_size = txsize_to_bsize[max_tx_size];
Jingning Hande953b92016-10-25 12:35:43 -0700898 const int bw = block_size_wide[txb_size] >> tx_size_wide_log2[0];
899 const int bh = block_size_high[txb_size] >> tx_size_wide_log2[0];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700900 int idx, idy;
901 int block = 0;
Jingning Hande953b92016-10-25 12:35:43 -0700902 int step = tx_size_wide_unit[max_tx_size] * tx_size_high_unit[max_tx_size];
Jingning Han581d1692017-01-05 16:03:54 -0800903 av1_get_entropy_contexts(bsize, 0, pd, ctx.ta[plane], ctx.tl[plane]);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700904#else
905 const struct macroblockd_plane *const pd = &xd->plane[plane];
906 const TX_SIZE tx_size = plane ? get_uv_tx_size(mbmi, pd) : mbmi->tx_size;
Yaowu Xuf883b422016-08-30 14:01:10 -0700907 av1_get_entropy_contexts(bsize, tx_size, pd, ctx.ta[plane], ctx.tl[plane]);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700908#endif
Yushin Cho77bba8d2016-11-04 16:36:56 -0700909#if !CONFIG_PVQ
Yaowu Xuf883b422016-08-30 14:01:10 -0700910 av1_subtract_plane(x, bsize, plane);
Yushin Cho77bba8d2016-11-04 16:36:56 -0700911#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -0700912 arg.ta = ctx.ta[plane];
913 arg.tl = ctx.tl[plane];
914
Jingning Han18c53c82017-02-17 14:49:57 -0800915#if CONFIG_CB4X4
916 if (bsize < BLOCK_8X8 && plane && !is_chroma_reference(mi_row, mi_col))
917 continue;
918#else
919 (void)mi_row;
920 (void)mi_col;
921#endif
922
Yaowu Xuc27fc142016-08-22 16:08:15 -0700923#if CONFIG_VAR_TX
Jingning Hanfe45b212016-11-22 10:30:23 -0800924 for (idy = 0; idy < mi_height; idy += bh) {
925 for (idx = 0; idx < mi_width; idx += bw) {
926 encode_block_inter(plane, block, idy, idx, plane_bsize, max_tx_size,
927 &arg);
928 block += step;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700929 }
Yaowu Xuc27fc142016-08-22 16:08:15 -0700930 }
Yaowu Xuc27fc142016-08-22 16:08:15 -0700931#else
Yaowu Xuf883b422016-08-30 14:01:10 -0700932 av1_foreach_transformed_block_in_plane(xd, bsize, plane, encode_block,
933 &arg);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700934#endif
935 }
936}
937
938#if CONFIG_SUPERTX
Angie Chiangff6d8902016-10-21 11:02:09 -0700939void av1_encode_sb_supertx(AV1_COMMON *cm, MACROBLOCK *x, BLOCK_SIZE bsize) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700940 MACROBLOCKD *const xd = &x->e_mbd;
941 struct optimize_ctx ctx;
942 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Angie Chiangff6d8902016-10-21 11:02:09 -0700943 struct encode_b_args arg = { cm, x, &ctx, &mbmi->skip, NULL, NULL, 1 };
Yaowu Xuc27fc142016-08-22 16:08:15 -0700944 int plane;
945
946 mbmi->skip = 1;
947 if (x->skip) return;
948
949 for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
950 const struct macroblockd_plane *const pd = &xd->plane[plane];
951#if CONFIG_VAR_TX
952 const TX_SIZE tx_size = TX_4X4;
953#else
954 const TX_SIZE tx_size = plane ? get_uv_tx_size(mbmi, pd) : mbmi->tx_size;
955#endif
Yaowu Xuf883b422016-08-30 14:01:10 -0700956 av1_subtract_plane(x, bsize, plane);
957 av1_get_entropy_contexts(bsize, tx_size, pd, ctx.ta[plane], ctx.tl[plane]);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700958 arg.ta = ctx.ta[plane];
959 arg.tl = ctx.tl[plane];
Yaowu Xuf883b422016-08-30 14:01:10 -0700960 av1_foreach_transformed_block_in_plane(xd, bsize, plane, encode_block,
961 &arg);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700962 }
963}
964#endif // CONFIG_SUPERTX
965
Yaowu Xuf883b422016-08-30 14:01:10 -0700966void av1_encode_block_intra(int plane, int block, int blk_row, int blk_col,
967 BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
968 void *arg) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700969 struct encode_b_args *const args = arg;
Angie Chiangff6d8902016-10-21 11:02:09 -0700970 AV1_COMMON *cm = args->cm;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700971 MACROBLOCK *const x = args->x;
972 MACROBLOCKD *const xd = &x->e_mbd;
973 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
974 struct macroblock_plane *const p = &x->plane[plane];
975 struct macroblockd_plane *const pd = &xd->plane[plane];
976 tran_low_t *dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
977 PLANE_TYPE plane_type = (plane == 0) ? PLANE_TYPE_Y : PLANE_TYPE_UV;
Urvang Joshifeb925f2016-12-05 10:37:29 -0800978 const int block_raster_idx = av1_block_index_to_raster_order(tx_size, block);
979 const TX_TYPE tx_type =
980 get_tx_type(plane_type, xd, block_raster_idx, tx_size);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700981 PREDICTION_MODE mode;
Jingning Han62a2b9e2016-10-24 10:32:37 -0700982 const int diff_stride = block_size_wide[plane_bsize];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700983 uint8_t *src, *dst;
984 int16_t *src_diff;
985 uint16_t *eob = &p->eobs[block];
986 const int src_stride = p->src.stride;
987 const int dst_stride = pd->dst.stride;
Jingning Han62a2b9e2016-10-24 10:32:37 -0700988 const int tx1d_width = tx_size_wide[tx_size];
989 const int tx1d_height = tx_size_high[tx_size];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700990 ENTROPY_CONTEXT *a = NULL, *l = NULL;
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800991 int ctx = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700992 INV_TXFM_PARAM inv_txfm_param;
Yushin Cho3827fdd2016-11-09 15:50:23 -0800993#if CONFIG_PVQ
Yushin Cho77bba8d2016-11-04 16:36:56 -0700994 int tx_blk_size;
995 int i, j;
Yushin Cho77bba8d2016-11-04 16:36:56 -0700996#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -0700997
Jingning Han81492262016-12-05 15:48:47 -0800998 dst = &pd->dst.buf[(blk_row * dst_stride + blk_col) << tx_size_wide_log2[0]];
999 src = &p->src.buf[(blk_row * src_stride + blk_col) << tx_size_wide_log2[0]];
1000 src_diff =
1001 &p->src_diff[(blk_row * diff_stride + blk_col) << tx_size_wide_log2[0]];
Urvang Joshifeb925f2016-12-05 10:37:29 -08001002 mode = (plane == 0) ? get_y_mode(xd->mi[0], block_raster_idx) : mbmi->uv_mode;
David Barker839467f2017-01-19 11:06:15 +00001003 av1_predict_intra_block(xd, pd->width, pd->height, txsize_to_bsize[tx_size],
1004 mode, dst, dst_stride, dst, dst_stride, blk_col,
1005 blk_row, plane);
Jingning Hane325abd2016-12-01 09:35:10 -08001006
1007 if (check_subtract_block_size(tx1d_width, tx1d_height)) {
Yaowu Xuf883b422016-08-30 14:01:10 -07001008#if CONFIG_AOM_HIGHBITDEPTH
Jingning Hane325abd2016-12-01 09:35:10 -08001009 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
1010 aom_highbd_subtract_block_c(tx1d_height, tx1d_width, src_diff,
1011 diff_stride, src, src_stride, dst, dst_stride,
1012 xd->bd);
1013 } else {
1014 aom_subtract_block_c(tx1d_height, tx1d_width, src_diff, diff_stride, src,
1015 src_stride, dst, dst_stride);
1016 }
1017#else
1018 aom_subtract_block_c(tx1d_height, tx1d_width, src_diff, diff_stride, src,
1019 src_stride, dst, dst_stride);
1020#endif // CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07001021 } else {
Jingning Hane325abd2016-12-01 09:35:10 -08001022#if CONFIG_AOM_HIGHBITDEPTH
1023 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
1024 aom_highbd_subtract_block(tx1d_height, tx1d_width, src_diff, diff_stride,
1025 src, src_stride, dst, dst_stride, xd->bd);
1026 } else {
1027 aom_subtract_block(tx1d_height, tx1d_width, src_diff, diff_stride, src,
1028 src_stride, dst, dst_stride);
1029 }
1030#else
Yaowu Xuf883b422016-08-30 14:01:10 -07001031 aom_subtract_block(tx1d_height, tx1d_width, src_diff, diff_stride, src,
Yaowu Xuc27fc142016-08-22 16:08:15 -07001032 src_stride, dst, dst_stride);
Yaowu Xuf883b422016-08-30 14:01:10 -07001033#endif // CONFIG_AOM_HIGHBITDEPTH
Jingning Hane325abd2016-12-01 09:35:10 -08001034 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07001035
1036 a = &args->ta[blk_col];
1037 l = &args->tl[blk_row];
Yushin Cho3827fdd2016-11-09 15:50:23 -08001038#if !CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -07001039 ctx = combine_entropy_contexts(*a, *l);
1040
1041 if (args->enable_optimize_b) {
1042#if CONFIG_NEW_QUANT
Debargha Mukherjeef0305582016-11-24 09:55:34 -08001043 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
1044 ctx, AV1_XFORM_QUANT_FP_NUQ);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001045#else // CONFIG_NEW_QUANT
Angie Chiangff6d8902016-10-21 11:02:09 -07001046 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
Debargha Mukherjeef0305582016-11-24 09:55:34 -08001047 ctx, AV1_XFORM_QUANT_FP);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001048#endif // CONFIG_NEW_QUANT
1049 if (p->eobs[block]) {
Angie Chiangff6d8902016-10-21 11:02:09 -07001050 *a = *l = av1_optimize_b(cm, x, plane, block, tx_size, ctx) > 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001051 } else {
1052 *a = *l = 0;
1053 }
1054 } else {
Debargha Mukherjeef0305582016-11-24 09:55:34 -08001055#if CONFIG_NEW_QUANT
Angie Chiangff6d8902016-10-21 11:02:09 -07001056 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
Debargha Mukherjeef0305582016-11-24 09:55:34 -08001057 ctx, AV1_XFORM_QUANT_B_NUQ);
1058#else // CONFIG_NEW_QUANT
1059 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
1060 ctx, AV1_XFORM_QUANT_B);
1061#endif // CONFIG_NEW_QUANT
Yaowu Xuc27fc142016-08-22 16:08:15 -07001062 *a = *l = p->eobs[block] > 0;
1063 }
1064
1065 if (*eob) {
1066 // inverse transform
1067 inv_txfm_param.tx_type = tx_type;
1068 inv_txfm_param.tx_size = tx_size;
1069 inv_txfm_param.eob = *eob;
1070 inv_txfm_param.lossless = xd->lossless[mbmi->segment_id];
Yaowu Xuf883b422016-08-30 14:01:10 -07001071#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07001072 inv_txfm_param.bd = xd->bd;
1073 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
1074 highbd_inv_txfm_add(dqcoeff, dst, dst_stride, &inv_txfm_param);
1075 } else {
1076 inv_txfm_add(dqcoeff, dst, dst_stride, &inv_txfm_param);
1077 }
1078#else
1079 inv_txfm_add(dqcoeff, dst, dst_stride, &inv_txfm_param);
Yaowu Xuf883b422016-08-30 14:01:10 -07001080#endif // CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07001081
1082 *(args->skip) = 0;
1083 }
Yaowu Xu859a5272016-11-10 15:32:21 -08001084#else // #if !CONFIG_PVQ
Yushin Cho3827fdd2016-11-09 15:50:23 -08001085
Debargha Mukherjeef0305582016-11-24 09:55:34 -08001086#if CONFIG_NEW_QUANT
Yushin Cho3827fdd2016-11-09 15:50:23 -08001087 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
Debargha Mukherjeef0305582016-11-24 09:55:34 -08001088 ctx, AV1_XFORM_QUANT_FP_NUQ);
1089#else
1090 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
1091 ctx, AV1_XFORM_QUANT_FP);
1092#endif // CONFIG_NEW_QUANT
Yushin Cho3827fdd2016-11-09 15:50:23 -08001093
1094 *a = *l = !x->pvq_skip[plane];
1095
1096 // *(args->skip) == mbmi->skip
1097 if (!x->pvq_skip[plane]) *(args->skip) = 0;
1098
1099 if (x->pvq_skip[plane]) return;
1100
Yushin Cho77bba8d2016-11-04 16:36:56 -07001101 // transform block size in pixels
1102 tx_blk_size = tx_size_wide[tx_size];
1103
Yushin Cho77bba8d2016-11-04 16:36:56 -07001104 // Since av1 does not have separate function which does inverse transform
1105 // but av1_inv_txfm_add_*x*() also does addition of predicted image to
1106 // inverse transformed image,
1107 // pass blank dummy image to av1_inv_txfm_add_*x*(), i.e. set dst as zeros
1108
Yushin Cho3827fdd2016-11-09 15:50:23 -08001109 for (j = 0; j < tx_blk_size; j++)
1110 for (i = 0; i < tx_blk_size; i++) dst[j * dst_stride + i] = 0;
Yushin Cho77bba8d2016-11-04 16:36:56 -07001111
Yushin Cho3827fdd2016-11-09 15:50:23 -08001112 inv_txfm_param.tx_type = tx_type;
1113 inv_txfm_param.tx_size = tx_size;
1114 inv_txfm_param.eob = *eob;
1115 inv_txfm_param.lossless = xd->lossless[mbmi->segment_id];
1116#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xu859a5272016-11-10 15:32:21 -08001117#error
Yushin Cho3827fdd2016-11-09 15:50:23 -08001118
1119#else
1120 inv_txfm_add(dqcoeff, dst, dst_stride, &inv_txfm_param);
1121#endif
Yushin Cho77bba8d2016-11-04 16:36:56 -07001122#endif // #if !CONFIG_PVQ
1123
1124#if !CONFIG_PVQ
1125 if (*eob) *(args->skip) = 0;
1126#else
1127// Note : *(args->skip) == mbmi->skip
1128#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07001129}
1130
Angie Chiangff6d8902016-10-21 11:02:09 -07001131void av1_encode_intra_block_plane(AV1_COMMON *cm, MACROBLOCK *x,
1132 BLOCK_SIZE bsize, int plane,
Jingning Han18c53c82017-02-17 14:49:57 -08001133 int enable_optimize_b, const int mi_row,
1134 const int mi_col) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07001135 const MACROBLOCKD *const xd = &x->e_mbd;
Guillaume Martrese50d9dd2016-12-18 18:26:47 +01001136 ENTROPY_CONTEXT ta[2 * MAX_MIB_SIZE] = { 0 };
1137 ENTROPY_CONTEXT tl[2 * MAX_MIB_SIZE] = { 0 };
Yaowu Xuc27fc142016-08-22 16:08:15 -07001138
Angie Chiangff6d8902016-10-21 11:02:09 -07001139 struct encode_b_args arg = {
1140 cm, x, NULL, &xd->mi[0]->mbmi.skip, ta, tl, enable_optimize_b
1141 };
Jingning Han18c53c82017-02-17 14:49:57 -08001142
1143#if CONFIG_CB4X4
1144 if (bsize < BLOCK_8X8 && plane && !is_chroma_reference(mi_row, mi_col))
1145 return;
1146#else
1147 (void)mi_row;
1148 (void)mi_col;
1149#endif
1150
Yaowu Xuc27fc142016-08-22 16:08:15 -07001151 if (enable_optimize_b) {
1152 const struct macroblockd_plane *const pd = &xd->plane[plane];
1153 const TX_SIZE tx_size =
1154 plane ? get_uv_tx_size(&xd->mi[0]->mbmi, pd) : xd->mi[0]->mbmi.tx_size;
Yaowu Xuf883b422016-08-30 14:01:10 -07001155 av1_get_entropy_contexts(bsize, tx_size, pd, ta, tl);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001156 }
Yaowu Xuf883b422016-08-30 14:01:10 -07001157 av1_foreach_transformed_block_in_plane(xd, bsize, plane,
1158 av1_encode_block_intra, &arg);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001159}
Yushin Cho77bba8d2016-11-04 16:36:56 -07001160
1161#if CONFIG_PVQ
ltrudeaue1c09292017-01-20 15:42:13 -05001162PVQ_SKIP_TYPE av1_pvq_encode_helper(
1163 daala_enc_ctx *daala_enc, tran_low_t *const coeff, tran_low_t *ref_coeff,
1164 tran_low_t *const dqcoeff, uint16_t *eob, const int16_t *quant, int plane,
1165 int tx_size, TX_TYPE tx_type, int *rate, int speed, PVQ_INFO *pvq_info) {
Yushin Cho77bba8d2016-11-04 16:36:56 -07001166 const int tx_blk_size = tx_size_wide[tx_size];
ltrudeaue1c09292017-01-20 15:42:13 -05001167 PVQ_SKIP_TYPE ac_dc_coded;
Timothy B. Terriberrye93acb22017-02-06 13:55:53 -08001168 /*TODO(tterribe): Handle CONFIG_AOM_HIGHBITDEPTH.*/
1169 int coeff_shift = 3 - get_tx_scale(tx_size);
1170 int rounding_mask;
Yushin Cho70669122016-12-08 09:53:14 -10001171 int pvq_dc_quant;
1172 int use_activity_masking = daala_enc->use_activity_masking;
Yushin Cho77bba8d2016-11-04 16:36:56 -07001173 int tell;
1174 int has_dc_skip = 1;
1175 int i;
1176 int off = od_qm_offset(tx_size, plane ? 1 : 0);
Yushin Cho70669122016-12-08 09:53:14 -10001177
Thomas Daede1dbda1b2017-02-06 16:06:29 -08001178 DECLARE_ALIGNED(16, tran_low_t, coeff_pvq[OD_TXSIZE_MAX * OD_TXSIZE_MAX]);
1179 DECLARE_ALIGNED(16, tran_low_t, ref_coeff_pvq[OD_TXSIZE_MAX * OD_TXSIZE_MAX]);
1180 DECLARE_ALIGNED(16, tran_low_t, dqcoeff_pvq[OD_TXSIZE_MAX * OD_TXSIZE_MAX]);
Yushin Cho77bba8d2016-11-04 16:36:56 -07001181
Yushin Cho48f84db2016-11-07 21:20:17 -08001182 DECLARE_ALIGNED(16, int32_t, in_int32[OD_TXSIZE_MAX * OD_TXSIZE_MAX]);
1183 DECLARE_ALIGNED(16, int32_t, ref_int32[OD_TXSIZE_MAX * OD_TXSIZE_MAX]);
1184 DECLARE_ALIGNED(16, int32_t, out_int32[OD_TXSIZE_MAX * OD_TXSIZE_MAX]);
Yushin Cho77bba8d2016-11-04 16:36:56 -07001185
Timothy B. Terriberrye93acb22017-02-06 13:55:53 -08001186 assert(OD_COEFF_SHIFT >= 3);
Yushin Cho70669122016-12-08 09:53:14 -10001187 // DC quantizer for PVQ
1188 if (use_activity_masking)
clang-format55ce9e02017-02-15 22:27:12 -08001189 pvq_dc_quant =
1190 OD_MAXI(1, (quant[0] << (OD_COEFF_SHIFT - 3)) *
1191 daala_enc->state
1192 .pvq_qm_q4[plane][od_qm_get_index(tx_size, 0)] >>
1193 4);
Yushin Cho70669122016-12-08 09:53:14 -10001194 else
Timothy B. Terriberrye93acb22017-02-06 13:55:53 -08001195 pvq_dc_quant = OD_MAXI(1, quant[0] << (OD_COEFF_SHIFT - 3));
Yushin Cho70669122016-12-08 09:53:14 -10001196
Yushin Cho77bba8d2016-11-04 16:36:56 -07001197 *eob = 0;
1198
Nathan E. Egge6675be02016-12-21 13:02:43 -05001199#if CONFIG_DAALA_EC
1200 tell = od_ec_enc_tell_frac(&daala_enc->w.ec);
1201#else
1202#error "CONFIG_PVQ currently requires CONFIG_DAALA_EC."
1203#endif
Yushin Cho77bba8d2016-11-04 16:36:56 -07001204
1205 // Change coefficient ordering for pvq encoding.
1206 od_raster_to_coding_order(coeff_pvq, tx_blk_size, tx_type, coeff,
1207 tx_blk_size);
1208 od_raster_to_coding_order(ref_coeff_pvq, tx_blk_size, tx_type, ref_coeff,
1209 tx_blk_size);
1210
1211 // copy int16 inputs to int32
1212 for (i = 0; i < tx_blk_size * tx_blk_size; i++) {
Timothy B. Terriberrye93acb22017-02-06 13:55:53 -08001213 ref_int32[i] = ref_coeff_pvq[i] << (OD_COEFF_SHIFT - coeff_shift);
1214 in_int32[i] = coeff_pvq[i] << (OD_COEFF_SHIFT - coeff_shift);
Yushin Cho77bba8d2016-11-04 16:36:56 -07001215 }
1216
Yushin Cho77bba8d2016-11-04 16:36:56 -07001217 if (abs(in_int32[0] - ref_int32[0]) < pvq_dc_quant * 141 / 256) { /* 0.55 */
1218 out_int32[0] = 0;
1219 } else {
1220 out_int32[0] = OD_DIV_R0(in_int32[0] - ref_int32[0], pvq_dc_quant);
1221 }
1222
ltrudeau472f63f2017-01-12 15:22:32 -05001223 ac_dc_coded = od_pvq_encode(
1224 daala_enc, ref_int32, in_int32, out_int32,
Timothy B. Terriberrye93acb22017-02-06 13:55:53 -08001225 quant[0] << (OD_COEFF_SHIFT - 3), // scale/quantizer
1226 quant[1] << (OD_COEFF_SHIFT - 3), // scale/quantizer
ltrudeau472f63f2017-01-12 15:22:32 -05001227 plane, tx_size, OD_PVQ_BETA[use_activity_masking][plane][tx_size],
1228 OD_ROBUST_STREAM,
1229 0, // is_keyframe,
1230 0, 0, 0, // q_scaling, bx, by,
1231 daala_enc->state.qm + off, daala_enc->state.qm_inv + off,
1232 speed, // speed
1233 pvq_info);
Yushin Cho77bba8d2016-11-04 16:36:56 -07001234
1235 // Encode residue of DC coeff, if required.
1236 if (!has_dc_skip || out_int32[0]) {
Nathan E. Egge760c27f2016-12-22 12:30:00 -05001237 generic_encode(&daala_enc->w, &daala_enc->state.adapt.model_dc[plane],
Yushin Cho77bba8d2016-11-04 16:36:56 -07001238 abs(out_int32[0]) - has_dc_skip, -1,
1239 &daala_enc->state.adapt.ex_dc[plane][tx_size][0], 2);
1240 }
1241 if (out_int32[0]) {
Nathan E. Egge6675be02016-12-21 13:02:43 -05001242 aom_write_bit(&daala_enc->w, out_int32[0] < 0);
Yushin Cho77bba8d2016-11-04 16:36:56 -07001243 }
1244
1245 // need to save quantized residue of DC coeff
1246 // so that final pvq bitstream writing can know whether DC is coded.
1247 if (pvq_info) pvq_info->dq_dc_residue = out_int32[0];
1248
1249 out_int32[0] = out_int32[0] * pvq_dc_quant;
1250 out_int32[0] += ref_int32[0];
1251
1252 // copy int32 result back to int16
Timothy B. Terriberrye93acb22017-02-06 13:55:53 -08001253 assert(OD_COEFF_SHIFT > coeff_shift);
1254 rounding_mask = (1 << (OD_COEFF_SHIFT - coeff_shift - 1)) - 1;
1255 for (i = 0; i < tx_blk_size * tx_blk_size; i++) {
1256 dqcoeff_pvq[i] = (out_int32[i] + (out_int32[i] < 0) + rounding_mask) >>
1257 (OD_COEFF_SHIFT - coeff_shift);
1258 }
Yushin Cho77bba8d2016-11-04 16:36:56 -07001259
1260 // Back to original coefficient order
1261 od_coding_order_to_raster(dqcoeff, tx_blk_size, tx_type, dqcoeff_pvq,
1262 tx_blk_size);
1263
1264 *eob = tx_blk_size * tx_blk_size;
1265
Nathan E. Egge6675be02016-12-21 13:02:43 -05001266#if CONFIG_DAALA_EC
1267 *rate = (od_ec_enc_tell_frac(&daala_enc->w.ec) - tell)
Yushin Cho77bba8d2016-11-04 16:36:56 -07001268 << (AV1_PROB_COST_SHIFT - OD_BITRES);
Nathan E. Egge6675be02016-12-21 13:02:43 -05001269#else
1270#error "CONFIG_PVQ currently requires CONFIG_DAALA_EC."
1271#endif
Yushin Cho77bba8d2016-11-04 16:36:56 -07001272 assert(*rate >= 0);
Yushin Cho5c207292017-02-16 15:01:33 -08001273
ltrudeau472f63f2017-01-12 15:22:32 -05001274 return ac_dc_coded;
Yushin Cho77bba8d2016-11-04 16:36:56 -07001275}
1276
1277void av1_store_pvq_enc_info(PVQ_INFO *pvq_info, int *qg, int *theta,
1278 int *max_theta, int *k, od_coeff *y, int nb_bands,
1279 const int *off, int *size, int skip_rest,
1280 int skip_dir,
1281 int bs) { // block size in log_2 -2
1282 int i;
1283 const int tx_blk_size = tx_size_wide[bs];
1284
1285 for (i = 0; i < nb_bands; i++) {
1286 pvq_info->qg[i] = qg[i];
1287 pvq_info->theta[i] = theta[i];
1288 pvq_info->max_theta[i] = max_theta[i];
1289 pvq_info->k[i] = k[i];
1290 pvq_info->off[i] = off[i];
1291 pvq_info->size[i] = size[i];
1292 }
1293
1294 memcpy(pvq_info->y, y, tx_blk_size * tx_blk_size * sizeof(od_coeff));
1295
1296 pvq_info->nb_bands = nb_bands;
1297 pvq_info->skip_rest = skip_rest;
1298 pvq_info->skip_dir = skip_dir;
1299 pvq_info->bs = bs;
1300}
1301#endif