blob: a76443ad6ea693ffdf1967ccf3803cdec53535c9 [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
26#include "av1/encoder/encodemb.h"
27#include "av1/encoder/hybrid_fwd_txfm.h"
28#include "av1/encoder/quantize.h"
29#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
Angie Chiangff6d8902016-10-21 11:02:09 -070095int av1_optimize_b(const AV1_COMMON *cm, MACROBLOCK *mb, int plane, int block,
96 TX_SIZE tx_size, int ctx) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070097 MACROBLOCKD *const xd = &mb->e_mbd;
98 struct macroblock_plane *const p = &mb->plane[plane];
99 struct macroblockd_plane *const pd = &xd->plane[plane];
100 const int ref = is_inter_block(&xd->mi[0]->mbmi);
Yaowu Xuf883b422016-08-30 14:01:10 -0700101 av1_token_state tokens[MAX_TX_SQUARE + 1][2];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700102 unsigned best_index[MAX_TX_SQUARE + 1][2];
103 uint8_t token_cache[MAX_TX_SQUARE];
104 const tran_low_t *const coeff = BLOCK_OFFSET(mb->plane[plane].coeff, block);
105 tran_low_t *const qcoeff = BLOCK_OFFSET(p->qcoeff, block);
106 tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
107 const int eob = p->eobs[block];
Debargha Mukherjee3c42c092016-09-29 09:17:36 -0700108 const PLANE_TYPE plane_type = pd->plane_type;
Jingning Hande953b92016-10-25 12:35:43 -0700109 const int default_eob = tx_size_2d[tx_size];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700110 const int16_t *const dequant_ptr = pd->dequant;
111 const uint8_t *const band_translate = get_band_translate(tx_size);
Debargha Mukherjee3c42c092016-09-29 09:17:36 -0700112 TX_TYPE tx_type = get_tx_type(plane_type, xd, block, tx_size);
Urvang Joshi03f6fdc2016-10-14 15:53:39 -0700113 const SCAN_ORDER *const scan_order =
Angie Chiangff6d8902016-10-21 11:02:09 -0700114 get_scan(cm, tx_size, tx_type, is_inter_block(&xd->mi[0]->mbmi));
Urvang Joshi03f6fdc2016-10-14 15:53:39 -0700115 const int16_t *const scan = scan_order->scan;
116 const int16_t *const nb = scan_order->neighbors;
Thomas Daviese0f8c552016-11-15 17:28:03 +0000117 int dqv;
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800118 const int shift = get_tx_scale(tx_size);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700119#if CONFIG_AOM_QM
120 int seg_id = xd->mi[0]->mbmi.segment_id;
Debargha Mukherjee3c42c092016-09-29 09:17:36 -0700121 const qm_val_t *iqmatrix = pd->seg_iqmatrix[seg_id][!ref][tx_size];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700122#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -0700123#if CONFIG_NEW_QUANT
David Barkerd7d78c82016-10-24 10:55:35 +0100124 int dq = get_dq_profile_from_ctx(mb->qindex, ctx, ref, plane_type);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700125 const dequant_val_type_nuq *dequant_val = pd->dequant_val_nuq[dq];
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800126#elif !CONFIG_AOM_QM
Yaowu Xuc27fc142016-08-22 16:08:15 -0700127 const int dq_step[2] = { dequant_ptr[0] >> shift, dequant_ptr[1] >> shift };
128#endif // CONFIG_NEW_QUANT
129 int next = eob, sz = 0;
Debargha Mukherjee3c42c092016-09-29 09:17:36 -0700130 const int64_t rdmult = (mb->rdmult * plane_rd_mult[ref][plane_type]) >> 1;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700131 const int64_t rddiv = mb->rddiv;
132 int64_t rd_cost0, rd_cost1;
133 int rate0, rate1;
134 int64_t error0, error1;
135 int16_t t0, t1;
136 int best, band = (eob < default_eob) ? band_translate[eob]
137 : band_translate[eob - 1];
138 int pt, i, final_eob;
Yaowu Xuf883b422016-08-30 14:01:10 -0700139#if CONFIG_AOM_HIGHBITDEPTH
140 const int *cat6_high_cost = av1_get_high_cost_table(xd->bd);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700141#else
Yaowu Xuf883b422016-08-30 14:01:10 -0700142 const int *cat6_high_cost = av1_get_high_cost_table(8);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700143#endif
144 unsigned int(*token_costs)[2][COEFF_CONTEXTS][ENTROPY_TOKENS] =
Debargha Mukherjee3c42c092016-09-29 09:17:36 -0700145 mb->token_costs[txsize_sqr_map[tx_size]][plane_type][ref];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700146 const uint16_t *band_counts = &band_count_table[tx_size][band];
147 uint16_t band_left = eob - band_cum_count_table[tx_size][band] + 1;
148 int shortcut = 0;
149 int next_shortcut = 0;
150
David Barkerd7d78c82016-10-24 10:55:35 +0100151 assert((mb->qindex == 0) ^ (xd->lossless[xd->mi[0]->mbmi.segment_id] == 0));
Debargha Mukherjee3c42c092016-09-29 09:17:36 -0700152
Yaowu Xuc27fc142016-08-22 16:08:15 -0700153 token_costs += band;
154
Debargha Mukherjee3c42c092016-09-29 09:17:36 -0700155 assert((!plane_type && !plane) || (plane_type && plane));
Yaowu Xuc27fc142016-08-22 16:08:15 -0700156 assert(eob <= default_eob);
157
158 /* Now set up a Viterbi trellis to evaluate alternative roundings. */
159 /* Initialize the sentinel node of the trellis. */
160 tokens[eob][0].rate = 0;
161 tokens[eob][0].error = 0;
162 tokens[eob][0].next = default_eob;
163 tokens[eob][0].token = EOB_TOKEN;
164 tokens[eob][0].qc = 0;
165 tokens[eob][1] = tokens[eob][0];
166
167 for (i = 0; i < eob; i++) {
168 const int rc = scan[i];
Yaowu Xuf883b422016-08-30 14:01:10 -0700169 tokens[i][0].rate = av1_get_token_cost(qcoeff[rc], &t0, cat6_high_cost);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700170 tokens[i][0].token = t0;
Yaowu Xuf883b422016-08-30 14:01:10 -0700171 token_cache[rc] = av1_pt_energy_class[t0];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700172 }
173
174 for (i = eob; i-- > 0;) {
175 int base_bits, dx;
176 int64_t d2;
177 const int rc = scan[i];
Thomas Daviese0f8c552016-11-15 17:28:03 +0000178 int x = qcoeff[rc];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700179#if CONFIG_AOM_QM
180 int iwt = iqmatrix[rc];
Thomas Daviese0f8c552016-11-15 17:28:03 +0000181 dqv = dequant_ptr[rc != 0];
182 dqv = ((iwt * (int)dqv) + (1 << (AOM_QM_BITS - 1))) >> AOM_QM_BITS;
183#else
184 dqv = dequant_ptr[rc != 0];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700185#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -0700186 next_shortcut = shortcut;
187
188 /* Only add a trellis state for non-zero coefficients. */
189 if (UNLIKELY(x)) {
190 error0 = tokens[next][0].error;
191 error1 = tokens[next][1].error;
192 /* Evaluate the first possibility for this state. */
193 rate0 = tokens[next][0].rate;
194 rate1 = tokens[next][1].rate;
195
196 if (next_shortcut) {
197 /* Consider both possible successor states. */
198 if (next < default_eob) {
199 pt = get_coef_context(nb, token_cache, i + 1);
200 rate0 += (*token_costs)[0][pt][tokens[next][0].token];
201 rate1 += (*token_costs)[0][pt][tokens[next][1].token];
202 }
203 UPDATE_RD_COST();
204 /* And pick the best. */
205 best = rd_cost1 < rd_cost0;
206 } else {
207 if (next < default_eob) {
208 pt = get_coef_context(nb, token_cache, i + 1);
209 rate0 += (*token_costs)[0][pt][tokens[next][0].token];
210 }
211 best = 0;
212 }
213
214 dx = (dqcoeff[rc] - coeff[rc]) * (1 << shift);
Yaowu Xuf883b422016-08-30 14:01:10 -0700215#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700216 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
217 dx >>= xd->bd - 8;
218 }
Yaowu Xuf883b422016-08-30 14:01:10 -0700219#endif // CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700220 d2 = (int64_t)dx * dx;
221 tokens[i][0].rate += (best ? rate1 : rate0);
222 tokens[i][0].error = d2 + (best ? error1 : error0);
223 tokens[i][0].next = next;
224 tokens[i][0].qc = x;
225 tokens[i][0].dqc = dqcoeff[rc];
226 best_index[i][0] = best;
227
228 /* Evaluate the second possibility for this state. */
229 rate0 = tokens[next][0].rate;
230 rate1 = tokens[next][1].rate;
231
232 // The threshold of 3 is empirically obtained.
233 if (UNLIKELY(abs(x) > 3)) {
234 shortcut = 0;
235 } else {
236#if CONFIG_NEW_QUANT
Thomas Daviese0f8c552016-11-15 17:28:03 +0000237 shortcut = ((av1_dequant_abscoeff_nuq(abs(x), dqv,
Yaowu Xuf883b422016-08-30 14:01:10 -0700238 dequant_val[band_translate[i]]) >
Yaowu Xuc27fc142016-08-22 16:08:15 -0700239 (abs(coeff[rc]) << shift)) &&
Thomas Daviese0f8c552016-11-15 17:28:03 +0000240 (av1_dequant_abscoeff_nuq(abs(x) - 1, dqv,
Yaowu Xuf883b422016-08-30 14:01:10 -0700241 dequant_val[band_translate[i]]) <
Yaowu Xuc27fc142016-08-22 16:08:15 -0700242 (abs(coeff[rc]) << shift)));
243#else // CONFIG_NEW_QUANT
244#if CONFIG_AOM_QM
245 if ((abs(x) * dequant_ptr[rc != 0] * iwt >
246 ((abs(coeff[rc]) << shift) << AOM_QM_BITS)) &&
247 (abs(x) * dequant_ptr[rc != 0] * iwt <
248 (((abs(coeff[rc]) << shift) + dequant_ptr[rc != 0])
249 << AOM_QM_BITS)))
250#else
251 if ((abs(x) * dequant_ptr[rc != 0] > (abs(coeff[rc]) << shift)) &&
252 (abs(x) * dequant_ptr[rc != 0] <
253 (abs(coeff[rc]) << shift) + dequant_ptr[rc != 0]))
254#endif // CONFIG_AOM_QM
255 shortcut = 1;
256 else
257 shortcut = 0;
258#endif // CONFIG_NEW_QUANT
259 }
260
261 if (shortcut) {
262 sz = -(x < 0);
263 x -= 2 * sz + 1;
264 } else {
265 tokens[i][1] = tokens[i][0];
266 best_index[i][1] = best_index[i][0];
267 next = i;
268
269 if (UNLIKELY(!(--band_left))) {
270 --band_counts;
271 band_left = *band_counts;
272 --token_costs;
273 }
274 continue;
275 }
276
277 /* Consider both possible successor states. */
278 if (!x) {
279 /* If we reduced this coefficient to zero, check to see if
280 * we need to move the EOB back here.
281 */
282 t0 = tokens[next][0].token == EOB_TOKEN ? EOB_TOKEN : ZERO_TOKEN;
283 t1 = tokens[next][1].token == EOB_TOKEN ? EOB_TOKEN : ZERO_TOKEN;
284 base_bits = 0;
285 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -0700286 base_bits = av1_get_token_cost(x, &t0, cat6_high_cost);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700287 t1 = t0;
288 }
289
290 if (next_shortcut) {
291 if (LIKELY(next < default_eob)) {
292 if (t0 != EOB_TOKEN) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700293 token_cache[rc] = av1_pt_energy_class[t0];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700294 pt = get_coef_context(nb, token_cache, i + 1);
295 rate0 += (*token_costs)[!x][pt][tokens[next][0].token];
296 }
297 if (t1 != EOB_TOKEN) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700298 token_cache[rc] = av1_pt_energy_class[t1];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700299 pt = get_coef_context(nb, token_cache, i + 1);
300 rate1 += (*token_costs)[!x][pt][tokens[next][1].token];
301 }
302 }
303
304 UPDATE_RD_COST();
305 /* And pick the best. */
306 best = rd_cost1 < rd_cost0;
307 } else {
308 // The two states in next stage are identical.
309 if (next < default_eob && t0 != EOB_TOKEN) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700310 token_cache[rc] = av1_pt_energy_class[t0];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700311 pt = get_coef_context(nb, token_cache, i + 1);
312 rate0 += (*token_costs)[!x][pt][tokens[next][0].token];
313 }
314 best = 0;
315 }
316
317#if CONFIG_NEW_QUANT
Thomas Daviese0f8c552016-11-15 17:28:03 +0000318 dx = av1_dequant_coeff_nuq(x, dqv, dequant_val[band_translate[i]]) -
Yaowu Xuc27fc142016-08-22 16:08:15 -0700319 (coeff[rc] << shift);
Yaowu Xuf883b422016-08-30 14:01:10 -0700320#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700321 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
322 dx >>= xd->bd - 8;
323 }
Yaowu Xuf883b422016-08-30 14:01:10 -0700324#endif // CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700325#else // CONFIG_NEW_QUANT
Yaowu Xuf883b422016-08-30 14:01:10 -0700326#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700327 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
Thomas Daviese0f8c552016-11-15 17:28:03 +0000328 dx -= ((dqv >> (xd->bd - 8)) + sz) ^ sz;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700329 } else {
Thomas Daviese0f8c552016-11-15 17:28:03 +0000330 dx -= (dqv + sz) ^ sz;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700331 }
332#else
Thomas Daviese0f8c552016-11-15 17:28:03 +0000333 dx -= (dqv + sz) ^ sz;
Yaowu Xuf883b422016-08-30 14:01:10 -0700334#endif // CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700335#endif // CONFIG_NEW_QUANT
336 d2 = (int64_t)dx * dx;
337
338 tokens[i][1].rate = base_bits + (best ? rate1 : rate0);
339 tokens[i][1].error = d2 + (best ? error1 : error0);
340 tokens[i][1].next = next;
341 tokens[i][1].token = best ? t1 : t0;
342 tokens[i][1].qc = x;
343
344 if (x) {
345#if CONFIG_NEW_QUANT
Yaowu Xuf883b422016-08-30 14:01:10 -0700346 tokens[i][1].dqc = av1_dequant_abscoeff_nuq(
Thomas Daviese0f8c552016-11-15 17:28:03 +0000347 abs(x), dqv, dequant_val[band_translate[i]]);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700348 tokens[i][1].dqc = shift ? ROUND_POWER_OF_TWO(tokens[i][1].dqc, shift)
349 : tokens[i][1].dqc;
350 if (sz) tokens[i][1].dqc = -tokens[i][1].dqc;
351#else
Debargha Mukherjeeb98a7022016-11-15 16:07:12 -0800352// The 32x32 transform coefficient uses half quantization step size.
353// Account for the rounding difference in the dequantized coefficeint
354// value when the quantization index is dropped from an even number
355// to an odd number.
Thomas Daviese0f8c552016-11-15 17:28:03 +0000356
357#if CONFIG_AOM_QM
358 tran_low_t offset = dqv >> shift;
359#else
360 tran_low_t offset = dq_step[rc != 0];
361#endif
362 if (shift & x) offset += (dqv & 0x01);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700363
364 if (sz == 0)
365 tokens[i][1].dqc = dqcoeff[rc] - offset;
366 else
367 tokens[i][1].dqc = dqcoeff[rc] + offset;
368#endif // CONFIG_NEW_QUANT
369 } else {
370 tokens[i][1].dqc = 0;
371 }
372
373 best_index[i][1] = best;
374 /* Finally, make this the new head of the trellis. */
375 next = i;
376 } else {
377 /* There's no choice to make for a zero coefficient, so we don't
378 * add a new trellis node, but we do need to update the costs.
379 */
380 t0 = tokens[next][0].token;
381 t1 = tokens[next][1].token;
382 pt = get_coef_context(nb, token_cache, i + 1);
383 /* Update the cost of each path if we're past the EOB token. */
384 if (t0 != EOB_TOKEN) {
385 tokens[next][0].rate += (*token_costs)[1][pt][t0];
386 tokens[next][0].token = ZERO_TOKEN;
387 }
388 if (t1 != EOB_TOKEN) {
389 tokens[next][1].rate += (*token_costs)[1][pt][t1];
390 tokens[next][1].token = ZERO_TOKEN;
391 }
392 best_index[i][0] = best_index[i][1] = 0;
393 shortcut = (tokens[next][0].rate != tokens[next][1].rate);
394 /* Don't update next, because we didn't add a new node. */
395 }
396
397 if (UNLIKELY(!(--band_left))) {
398 --band_counts;
399 band_left = *band_counts;
400 --token_costs;
401 }
402 }
403
404 /* Now pick the best path through the whole trellis. */
405 rate0 = tokens[next][0].rate;
406 rate1 = tokens[next][1].rate;
407 error0 = tokens[next][0].error;
408 error1 = tokens[next][1].error;
409 t0 = tokens[next][0].token;
410 t1 = tokens[next][1].token;
411 rate0 += (*token_costs)[0][ctx][t0];
412 rate1 += (*token_costs)[0][ctx][t1];
413 UPDATE_RD_COST();
414 best = rd_cost1 < rd_cost0;
415
416 final_eob = -1;
417
418 for (i = next; i < eob; i = next) {
419 const int x = tokens[i][best].qc;
420 const int rc = scan[i];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700421 if (x) final_eob = i;
422 qcoeff[rc] = x;
423 dqcoeff[rc] = tokens[i][best].dqc;
424
425 next = tokens[i][best].next;
426 best = best_index[i][best];
427 }
428 final_eob++;
429
430 mb->plane[plane].eobs[block] = final_eob;
431 assert(final_eob <= default_eob);
432 return final_eob;
433}
434
Yaowu Xuf883b422016-08-30 14:01:10 -0700435#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700436typedef enum QUANT_FUNC {
437 QUANT_FUNC_LOWBD = 0,
438 QUANT_FUNC_HIGHBD = 1,
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800439 QUANT_FUNC_TYPES = 2
Yaowu Xuc27fc142016-08-22 16:08:15 -0700440} QUANT_FUNC;
441
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800442static AV1_QUANT_FACADE
443 quant_func_list[AV1_XFORM_QUANT_TYPES][QUANT_FUNC_TYPES] = {
444 { av1_quantize_fp_facade, av1_highbd_quantize_fp_facade },
Yaowu Xuf883b422016-08-30 14:01:10 -0700445 { av1_quantize_b_facade, av1_highbd_quantize_b_facade },
446 { av1_quantize_dc_facade, av1_highbd_quantize_dc_facade },
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800447#if CONFIG_NEW_QUANT
448 { av1_quantize_fp_nuq_facade, av1_highbd_quantize_fp_nuq_facade },
449 { av1_quantize_b_nuq_facade, av1_highbd_quantize_b_nuq_facade },
450 { av1_quantize_dc_nuq_facade, av1_highbd_quantize_dc_nuq_facade },
451#endif // CONFIG_NEW_QUANT
452 { NULL, NULL }
453 };
Yaowu Xuc27fc142016-08-22 16:08:15 -0700454
Yaowu Xu02d4c3b2016-11-07 10:45:56 -0800455#elif !CONFIG_PVQ
456
Yaowu Xuc27fc142016-08-22 16:08:15 -0700457typedef enum QUANT_FUNC {
458 QUANT_FUNC_LOWBD = 0,
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800459 QUANT_FUNC_TYPES = 1
Yaowu Xuc27fc142016-08-22 16:08:15 -0700460} QUANT_FUNC;
461
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800462static AV1_QUANT_FACADE quant_func_list[AV1_XFORM_QUANT_TYPES]
463 [QUANT_FUNC_TYPES] = {
clang-format67948d32016-09-07 22:40:40 -0700464 { av1_quantize_fp_facade },
465 { av1_quantize_b_facade },
466 { av1_quantize_dc_facade },
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800467#if CONFIG_NEW_QUANT
468 { av1_quantize_fp_nuq_facade },
469 { av1_quantize_b_nuq_facade },
470 { av1_quantize_dc_nuq_facade },
471#endif // CONFIG_NEW_QUANT
clang-format67948d32016-09-07 22:40:40 -0700472 { NULL }
473 };
Yaowu Xuc27fc142016-08-22 16:08:15 -0700474#endif
475
Angie Chiangff6d8902016-10-21 11:02:09 -0700476void av1_xform_quant(const AV1_COMMON *cm, MACROBLOCK *x, int plane, int block,
477 int blk_row, int blk_col, BLOCK_SIZE plane_bsize,
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800478 TX_SIZE tx_size, int ctx,
479 AV1_XFORM_QUANT xform_quant_idx) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700480 MACROBLOCKD *const xd = &x->e_mbd;
Yushin Cho77bba8d2016-11-04 16:36:56 -0700481#if !CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -0700482 const struct macroblock_plane *const p = &x->plane[plane];
483 const struct macroblockd_plane *const pd = &xd->plane[plane];
Yushin Cho77bba8d2016-11-04 16:36:56 -0700484#else
485 struct macroblock_plane *const p = &x->plane[plane];
486 struct macroblockd_plane *const pd = &xd->plane[plane];
487#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -0700488 PLANE_TYPE plane_type = (plane == 0) ? PLANE_TYPE_Y : PLANE_TYPE_UV;
489 TX_TYPE tx_type = get_tx_type(plane_type, xd, block, tx_size);
Debargha Mukherjee3c42c092016-09-29 09:17:36 -0700490 const int is_inter = is_inter_block(&xd->mi[0]->mbmi);
Angie Chiangff6d8902016-10-21 11:02:09 -0700491 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, is_inter);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700492 tran_low_t *const coeff = BLOCK_OFFSET(p->coeff, block);
493 tran_low_t *const qcoeff = BLOCK_OFFSET(p->qcoeff, block);
494 tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
495 uint16_t *const eob = &p->eobs[block];
Jingning Hanae5cfde2016-11-30 12:01:44 -0800496 const int diff_stride = block_size_wide[plane_bsize];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700497#if CONFIG_AOM_QM
498 int seg_id = xd->mi[0]->mbmi.segment_id;
Debargha Mukherjee3c42c092016-09-29 09:17:36 -0700499 const qm_val_t *qmatrix = pd->seg_qmatrix[seg_id][!is_inter][tx_size];
500 const qm_val_t *iqmatrix = pd->seg_iqmatrix[seg_id][!is_inter][tx_size];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700501#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -0700502
503 FWD_TXFM_PARAM fwd_txfm_param;
Yushin Cho77bba8d2016-11-04 16:36:56 -0700504
505#if !CONFIG_PVQ
506 const int tx2d_size = tx_size_2d[tx_size];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700507 QUANT_PARAM qparam;
Yushin Cho77bba8d2016-11-04 16:36:56 -0700508 const int16_t *src_diff;
509
Jingning Han81492262016-12-05 15:48:47 -0800510 src_diff =
511 &p->src_diff[(blk_row * diff_stride + blk_col) << tx_size_wide_log2[0]];
Debargha Mukherjee0e119122016-11-04 12:10:23 -0700512 qparam.log_scale = get_tx_scale(tx_size);
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800513#if CONFIG_NEW_QUANT
514 qparam.tx_size = tx_size;
515 qparam.dq = get_dq_profile_from_ctx(x->qindex, ctx, is_inter, plane_type);
516#endif // CONFIG_NEW_QUANT
517#if CONFIG_AOM_QM
518 qparam.qmatrix = qmatrix;
519 qparam.iqmatrix = iqmatrix;
520#endif // CONFIG_AOM_QM
Yushin Cho77bba8d2016-11-04 16:36:56 -0700521#else
522 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
523 tran_low_t *ref_coeff = BLOCK_OFFSET(pd->pvq_ref_coeff, block);
524 uint8_t *src, *dst;
525 int16_t *src_int16, *pred;
526 const int src_stride = p->src.stride;
527 const int dst_stride = pd->dst.stride;
528 int tx_blk_size;
529 int i, j;
530 int skip = 1;
531 PVQ_INFO *pvq_info = NULL;
532
533 (void)scan_order;
534 (void)qcoeff;
535
536 if (x->pvq_coded) {
537 assert(block < MAX_PVQ_BLOCKS_IN_SB);
538 pvq_info = &x->pvq[block][plane];
539 }
Jingning Han81492262016-12-05 15:48:47 -0800540 dst = &pd->dst.buf[(blk_row * dst_stride + blk_col) << tx_size_wide_log2[0]];
541 src = &p->src.buf[(blk_row * src_stride + blk_col) << tx_size_wide_log2[0]];
542 src_int16 =
543 &p->src_int16[(blk_row * diff_stride + blk_col) << tx_size_wide_log2[0]];
544 pred = &pd->pred[(blk_row * diff_stride + blk_col) << tx_size_wide_log2[0]];
Yushin Cho77bba8d2016-11-04 16:36:56 -0700545
546 // transform block size in pixels
547 tx_blk_size = tx_size_wide[tx_size];
548
549 // copy uint8 orig and predicted block to int16 buffer
550 // in order to use existing VP10 transform functions
551 for (j = 0; j < tx_blk_size; j++)
552 for (i = 0; i < tx_blk_size; i++) {
553 src_int16[diff_stride * j + i] = src[src_stride * j + i];
554 pred[diff_stride * j + i] = dst[dst_stride * j + i];
555 }
556#endif
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800557 (void)ctx;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700558
559 fwd_txfm_param.tx_type = tx_type;
560 fwd_txfm_param.tx_size = tx_size;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700561 fwd_txfm_param.lossless = xd->lossless[xd->mi[0]->mbmi.segment_id];
562
Yaowu Xuf883b422016-08-30 14:01:10 -0700563#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700564 fwd_txfm_param.bd = xd->bd;
565 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
566 highbd_fwd_txfm(src_diff, coeff, diff_stride, &fwd_txfm_param);
Yaowu Xuf883b422016-08-30 14:01:10 -0700567 if (xform_quant_idx != AV1_XFORM_QUANT_SKIP_QUANT) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700568 if (LIKELY(!x->skip_block)) {
569 quant_func_list[xform_quant_idx][QUANT_FUNC_HIGHBD](
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800570 coeff, tx2d_size, p, qcoeff, pd, dqcoeff, eob, scan_order, &qparam);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700571 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -0700572 av1_quantize_skip(tx2d_size, qcoeff, dqcoeff, eob);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700573 }
574 }
575 return;
576 }
Yaowu Xuf883b422016-08-30 14:01:10 -0700577#endif // CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700578
Yushin Cho77bba8d2016-11-04 16:36:56 -0700579#if !CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -0700580 fwd_txfm(src_diff, coeff, diff_stride, &fwd_txfm_param);
Yaowu Xuf883b422016-08-30 14:01:10 -0700581 if (xform_quant_idx != AV1_XFORM_QUANT_SKIP_QUANT) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700582 if (LIKELY(!x->skip_block)) {
583 quant_func_list[xform_quant_idx][QUANT_FUNC_LOWBD](
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800584 coeff, tx2d_size, p, qcoeff, pd, dqcoeff, eob, scan_order, &qparam);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700585 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -0700586 av1_quantize_skip(tx2d_size, qcoeff, dqcoeff, eob);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700587 }
588 }
Yushin Cho77bba8d2016-11-04 16:36:56 -0700589#else // #if !CONFIG_PVQ
Yushin Cho77bba8d2016-11-04 16:36:56 -0700590
Angie Chiang2cc057c2017-01-03 18:31:47 -0800591 (void)xform_quant_idx;
Yushin Cho77bba8d2016-11-04 16:36:56 -0700592 fwd_txfm(src_int16, coeff, diff_stride, &fwd_txfm_param);
593 fwd_txfm(pred, ref_coeff, diff_stride, &fwd_txfm_param);
594
595 // PVQ for inter mode block
596 if (!x->skip_block)
597 skip = av1_pvq_encode_helper(&x->daala_enc,
598 coeff, // target original vector
599 ref_coeff, // reference vector
600 dqcoeff, // de-quantized vector
601 eob, // End of Block marker
602 pd->dequant, // aom's quantizers
603 plane, // image plane
604 tx_size, // block size in log_2 - 2
605 tx_type,
606 &x->rate, // rate measured
607 x->pvq_speed,
608 pvq_info); // PVQ info for a block
609
610 x->pvq_skip[plane] = skip;
611
612 if (!skip) mbmi->skip = 0;
613#endif // #if !CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -0700614}
615
Yaowu Xuc27fc142016-08-22 16:08:15 -0700616static void encode_block(int plane, int block, int blk_row, int blk_col,
617 BLOCK_SIZE plane_bsize, TX_SIZE tx_size, void *arg) {
618 struct encode_b_args *const args = arg;
Angie Chiangff6d8902016-10-21 11:02:09 -0700619 AV1_COMMON *cm = args->cm;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700620 MACROBLOCK *const x = args->x;
621 MACROBLOCKD *const xd = &x->e_mbd;
622 int ctx;
623 struct macroblock_plane *const p = &x->plane[plane];
624 struct macroblockd_plane *const pd = &xd->plane[plane];
625 tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
626 uint8_t *dst;
627 ENTROPY_CONTEXT *a, *l;
628 INV_TXFM_PARAM inv_txfm_param;
Yushin Cho77bba8d2016-11-04 16:36:56 -0700629#if CONFIG_PVQ
630 int tx_blk_size;
631 int i, j;
632#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -0700633#if CONFIG_VAR_TX
634 int i;
635 const int bwl = b_width_log2_lookup[plane_bsize];
636#endif
Jingning Han81492262016-12-05 15:48:47 -0800637 dst = &pd->dst
638 .buf[(blk_row * pd->dst.stride + blk_col) << tx_size_wide_log2[0]];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700639 a = &args->ta[blk_col];
640 l = &args->tl[blk_row];
641#if CONFIG_VAR_TX
642 ctx = get_entropy_context(tx_size, a, l);
643#else
644 ctx = combine_entropy_contexts(*a, *l);
645#endif
646
647#if CONFIG_VAR_TX
Yue Chena1e48dc2016-08-29 17:29:33 -0700648 // Assert not magic number (uninitialized).
Yaowu Xuc27fc142016-08-22 16:08:15 -0700649 assert(x->blk_skip[plane][(blk_row << bwl) + blk_col] != 234);
650
651 if (x->blk_skip[plane][(blk_row << bwl) + blk_col] == 0) {
652#else
653 {
654#endif
655#if CONFIG_NEW_QUANT
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800656 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
657 ctx, AV1_XFORM_QUANT_FP_NUQ);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700658#else
Angie Chiangff6d8902016-10-21 11:02:09 -0700659 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800660 ctx, AV1_XFORM_QUANT_FP);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700661#endif // CONFIG_NEW_QUANT
662 }
663#if CONFIG_VAR_TX
664 else {
665 p->eobs[block] = 0;
666 }
667#endif
Yushin Cho77bba8d2016-11-04 16:36:56 -0700668#if !CONFIG_PVQ
Jingning Handb4c9ba2016-11-30 10:00:25 -0800669 if (p->eobs[block] && !xd->lossless[xd->mi[0]->mbmi.segment_id]) {
Angie Chiangff6d8902016-10-21 11:02:09 -0700670 *a = *l = av1_optimize_b(cm, x, plane, block, tx_size, ctx) > 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700671 } else {
672 *a = *l = p->eobs[block] > 0;
673 }
674
675#if CONFIG_VAR_TX
Jingning Hande953b92016-10-25 12:35:43 -0700676 for (i = 0; i < tx_size_wide_unit[tx_size]; ++i) a[i] = a[0];
677
678 for (i = 0; i < tx_size_high_unit[tx_size]; ++i) l[i] = l[0];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700679#endif
680
681 if (p->eobs[block]) *(args->skip) = 0;
682
683 if (p->eobs[block] == 0) return;
Yushin Cho77bba8d2016-11-04 16:36:56 -0700684#else
685 (void)ctx;
686 *a = *l = !x->pvq_skip[plane];
687
688 if (!x->pvq_skip[plane]) *(args->skip) = 0;
689
690 if (x->pvq_skip[plane]) return;
691
692 // transform block size in pixels
693 tx_blk_size = tx_size_wide[tx_size];
694
695 // Since av1 does not have separate function which does inverse transform
696 // but av1_inv_txfm_add_*x*() also does addition of predicted image to
697 // inverse transformed image,
698 // pass blank dummy image to av1_inv_txfm_add_*x*(), i.e. set dst as zeros
699 for (j = 0; j < tx_blk_size; j++)
700 for (i = 0; i < tx_blk_size; i++) dst[j * pd->dst.stride + i] = 0;
701#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -0700702
703 // inverse transform parameters
704 inv_txfm_param.tx_type = get_tx_type(pd->plane_type, xd, block, tx_size);
705 inv_txfm_param.tx_size = tx_size;
706 inv_txfm_param.eob = p->eobs[block];
707 inv_txfm_param.lossless = xd->lossless[xd->mi[0]->mbmi.segment_id];
708
Yaowu Xuf883b422016-08-30 14:01:10 -0700709#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700710 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
711 inv_txfm_param.bd = xd->bd;
712 highbd_inv_txfm_add(dqcoeff, dst, pd->dst.stride, &inv_txfm_param);
713 return;
714 }
Yaowu Xuf883b422016-08-30 14:01:10 -0700715#endif // CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700716 inv_txfm_add(dqcoeff, dst, pd->dst.stride, &inv_txfm_param);
717}
718
719#if CONFIG_VAR_TX
720static void encode_block_inter(int plane, int block, int blk_row, int blk_col,
721 BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
722 void *arg) {
723 struct encode_b_args *const args = arg;
724 MACROBLOCK *const x = args->x;
725 MACROBLOCKD *const xd = &x->e_mbd;
726 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
727 const BLOCK_SIZE bsize = txsize_to_bsize[tx_size];
728 const struct macroblockd_plane *const pd = &xd->plane[plane];
729 const int tx_row = blk_row >> (1 - pd->subsampling_y);
730 const int tx_col = blk_col >> (1 - pd->subsampling_x);
731 TX_SIZE plane_tx_size;
Jingning Hanf65b8702016-10-31 12:13:20 -0700732 const int max_blocks_high = max_block_high(xd, plane_bsize, plane);
733 const int max_blocks_wide = max_block_wide(xd, plane_bsize, plane);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700734
735 if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
736
Debargha Mukherjee2f123402016-08-30 17:43:38 -0700737 plane_tx_size =
738 plane ? uv_txsize_lookup[bsize][mbmi->inter_tx_size[tx_row][tx_col]][0][0]
739 : mbmi->inter_tx_size[tx_row][tx_col];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700740
741 if (tx_size == plane_tx_size) {
742 encode_block(plane, block, blk_row, blk_col, plane_bsize, tx_size, arg);
743 } else {
Jingning Hana9336322016-11-02 15:45:07 -0700744 const TX_SIZE sub_txs = sub_tx_size_map[tx_size];
745 // This is the square transform block partition entry point.
746 int bsl = tx_size_wide_unit[sub_txs];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700747 int i;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700748 assert(bsl > 0);
Jingning Hand3fada82016-11-22 10:46:55 -0800749 assert(tx_size < TX_SIZES_ALL);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700750
751 for (i = 0; i < 4; ++i) {
Jingning Hande953b92016-10-25 12:35:43 -0700752 const int offsetr = blk_row + ((i >> 1) * bsl);
753 const int offsetc = blk_col + ((i & 0x01) * bsl);
Jingning Hande953b92016-10-25 12:35:43 -0700754 int step = tx_size_wide_unit[sub_txs] * tx_size_high_unit[sub_txs];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700755
756 if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide) continue;
757
Jingning Han98d6a1f2016-11-03 12:47:47 -0700758 encode_block_inter(plane, block, offsetr, offsetc, plane_bsize, sub_txs,
759 arg);
760 block += step;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700761 }
762 }
763}
764#endif
765
Angie Chiangff6d8902016-10-21 11:02:09 -0700766typedef struct encode_block_pass1_args {
767 AV1_COMMON *cm;
768 MACROBLOCK *x;
769} encode_block_pass1_args;
770
Yaowu Xuc27fc142016-08-22 16:08:15 -0700771static void encode_block_pass1(int plane, int block, int blk_row, int blk_col,
772 BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
773 void *arg) {
Angie Chiangff6d8902016-10-21 11:02:09 -0700774 encode_block_pass1_args *args = (encode_block_pass1_args *)arg;
775 AV1_COMMON *cm = args->cm;
776 MACROBLOCK *const x = args->x;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700777 MACROBLOCKD *const xd = &x->e_mbd;
778 struct macroblock_plane *const p = &x->plane[plane];
779 struct macroblockd_plane *const pd = &xd->plane[plane];
780 tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
781 uint8_t *dst;
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800782 int ctx = 0;
Jingning Han81492262016-12-05 15:48:47 -0800783 dst = &pd->dst
784 .buf[(blk_row * pd->dst.stride + blk_col) << tx_size_wide_log2[0]];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700785
786#if CONFIG_NEW_QUANT
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800787 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
788 ctx, AV1_XFORM_QUANT_B_NUQ);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700789#else
Angie Chiangff6d8902016-10-21 11:02:09 -0700790 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800791 ctx, AV1_XFORM_QUANT_B);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700792#endif // CONFIG_NEW_QUANT
Yushin Cho77bba8d2016-11-04 16:36:56 -0700793#if !CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -0700794 if (p->eobs[block] > 0) {
Yushin Cho77bba8d2016-11-04 16:36:56 -0700795#else
796 if (!x->pvq_skip[plane]) {
Yushin Cho77bba8d2016-11-04 16:36:56 -0700797 {
798 int tx_blk_size;
799 int i, j;
800 // transform block size in pixels
801 tx_blk_size = tx_size_wide[tx_size];
802
803 // Since av1 does not have separate function which does inverse transform
804 // but av1_inv_txfm_add_*x*() also does addition of predicted image to
805 // inverse transformed image,
806 // pass blank dummy image to av1_inv_txfm_add_*x*(), i.e. set dst as zeros
807 for (j = 0; j < tx_blk_size; j++)
808 for (i = 0; i < tx_blk_size; i++) dst[j * pd->dst.stride + i] = 0;
809 }
Jingning Handf072642016-11-08 16:43:38 -0800810#endif // !CONFIG_PVQ
Yaowu Xuf883b422016-08-30 14:01:10 -0700811#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700812 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
813 if (xd->lossless[xd->mi[0]->mbmi.segment_id]) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700814 av1_highbd_iwht4x4_add(dqcoeff, dst, pd->dst.stride, p->eobs[block],
815 xd->bd);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700816 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -0700817 av1_highbd_idct4x4_add(dqcoeff, dst, pd->dst.stride, p->eobs[block],
818 xd->bd);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700819 }
820 return;
821 }
Jingning Hane38d63c2016-11-08 12:05:29 -0800822#endif // CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700823 if (xd->lossless[xd->mi[0]->mbmi.segment_id]) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700824 av1_iwht4x4_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700825 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -0700826 av1_idct4x4_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700827 }
828 }
829}
830
Angie Chiangff6d8902016-10-21 11:02:09 -0700831void av1_encode_sby_pass1(AV1_COMMON *cm, MACROBLOCK *x, BLOCK_SIZE bsize) {
832 encode_block_pass1_args args = { cm, x };
Yaowu Xuf883b422016-08-30 14:01:10 -0700833 av1_subtract_plane(x, bsize, 0);
834 av1_foreach_transformed_block_in_plane(&x->e_mbd, bsize, 0,
Angie Chiangff6d8902016-10-21 11:02:09 -0700835 encode_block_pass1, &args);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700836}
837
Angie Chiangff6d8902016-10-21 11:02:09 -0700838void av1_encode_sb(AV1_COMMON *cm, MACROBLOCK *x, BLOCK_SIZE bsize) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700839 MACROBLOCKD *const xd = &x->e_mbd;
840 struct optimize_ctx ctx;
841 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Angie Chiangff6d8902016-10-21 11:02:09 -0700842 struct encode_b_args arg = { cm, x, &ctx, &mbmi->skip, NULL, NULL, 1 };
Yaowu Xuc27fc142016-08-22 16:08:15 -0700843 int plane;
844
845 mbmi->skip = 1;
846
847 if (x->skip) return;
848
849 for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
850#if CONFIG_VAR_TX
851 // TODO(jingning): Clean this up.
852 const struct macroblockd_plane *const pd = &xd->plane[plane];
853 const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
Jingning Hande953b92016-10-25 12:35:43 -0700854 const int mi_width = block_size_wide[plane_bsize] >> tx_size_wide_log2[0];
855 const int mi_height = block_size_high[plane_bsize] >> tx_size_wide_log2[0];
Jingning Han70e5f3f2016-11-09 17:03:07 -0800856 const TX_SIZE max_tx_size = max_txsize_rect_lookup[plane_bsize];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700857 const BLOCK_SIZE txb_size = txsize_to_bsize[max_tx_size];
Jingning Hande953b92016-10-25 12:35:43 -0700858 const int bw = block_size_wide[txb_size] >> tx_size_wide_log2[0];
859 const int bh = block_size_high[txb_size] >> tx_size_wide_log2[0];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700860 int idx, idy;
861 int block = 0;
Jingning Hande953b92016-10-25 12:35:43 -0700862 int step = tx_size_wide_unit[max_tx_size] * tx_size_high_unit[max_tx_size];
Yaowu Xuf883b422016-08-30 14:01:10 -0700863 av1_get_entropy_contexts(bsize, TX_4X4, pd, ctx.ta[plane], ctx.tl[plane]);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700864#else
865 const struct macroblockd_plane *const pd = &xd->plane[plane];
866 const TX_SIZE tx_size = plane ? get_uv_tx_size(mbmi, pd) : mbmi->tx_size;
Yaowu Xuf883b422016-08-30 14:01:10 -0700867 av1_get_entropy_contexts(bsize, tx_size, pd, ctx.ta[plane], ctx.tl[plane]);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700868#endif
Yushin Cho77bba8d2016-11-04 16:36:56 -0700869#if !CONFIG_PVQ
Yaowu Xuf883b422016-08-30 14:01:10 -0700870 av1_subtract_plane(x, bsize, plane);
Yushin Cho77bba8d2016-11-04 16:36:56 -0700871#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -0700872 arg.ta = ctx.ta[plane];
873 arg.tl = ctx.tl[plane];
874
875#if CONFIG_VAR_TX
Jingning Hanfe45b212016-11-22 10:30:23 -0800876 for (idy = 0; idy < mi_height; idy += bh) {
877 for (idx = 0; idx < mi_width; idx += bw) {
878 encode_block_inter(plane, block, idy, idx, plane_bsize, max_tx_size,
879 &arg);
880 block += step;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700881 }
Yaowu Xuc27fc142016-08-22 16:08:15 -0700882 }
Yaowu Xuc27fc142016-08-22 16:08:15 -0700883#else
Yaowu Xuf883b422016-08-30 14:01:10 -0700884 av1_foreach_transformed_block_in_plane(xd, bsize, plane, encode_block,
885 &arg);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700886#endif
887 }
888}
889
890#if CONFIG_SUPERTX
Angie Chiangff6d8902016-10-21 11:02:09 -0700891void av1_encode_sb_supertx(AV1_COMMON *cm, MACROBLOCK *x, BLOCK_SIZE bsize) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700892 MACROBLOCKD *const xd = &x->e_mbd;
893 struct optimize_ctx ctx;
894 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Angie Chiangff6d8902016-10-21 11:02:09 -0700895 struct encode_b_args arg = { cm, x, &ctx, &mbmi->skip, NULL, NULL, 1 };
Yaowu Xuc27fc142016-08-22 16:08:15 -0700896 int plane;
897
898 mbmi->skip = 1;
899 if (x->skip) return;
900
901 for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
902 const struct macroblockd_plane *const pd = &xd->plane[plane];
903#if CONFIG_VAR_TX
904 const TX_SIZE tx_size = TX_4X4;
905#else
906 const TX_SIZE tx_size = plane ? get_uv_tx_size(mbmi, pd) : mbmi->tx_size;
907#endif
Yaowu Xuf883b422016-08-30 14:01:10 -0700908 av1_subtract_plane(x, bsize, plane);
909 av1_get_entropy_contexts(bsize, tx_size, pd, ctx.ta[plane], ctx.tl[plane]);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700910 arg.ta = ctx.ta[plane];
911 arg.tl = ctx.tl[plane];
Yaowu Xuf883b422016-08-30 14:01:10 -0700912 av1_foreach_transformed_block_in_plane(xd, bsize, plane, encode_block,
913 &arg);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700914 }
915}
916#endif // CONFIG_SUPERTX
917
Yaowu Xuf883b422016-08-30 14:01:10 -0700918void av1_encode_block_intra(int plane, int block, int blk_row, int blk_col,
919 BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
920 void *arg) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700921 struct encode_b_args *const args = arg;
Angie Chiangff6d8902016-10-21 11:02:09 -0700922 AV1_COMMON *cm = args->cm;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700923 MACROBLOCK *const x = args->x;
924 MACROBLOCKD *const xd = &x->e_mbd;
925 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
926 struct macroblock_plane *const p = &x->plane[plane];
927 struct macroblockd_plane *const pd = &xd->plane[plane];
928 tran_low_t *dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
929 PLANE_TYPE plane_type = (plane == 0) ? PLANE_TYPE_Y : PLANE_TYPE_UV;
930 const TX_TYPE tx_type = get_tx_type(plane_type, xd, block, tx_size);
931 PREDICTION_MODE mode;
Jingning Han62a2b9e2016-10-24 10:32:37 -0700932 const int diff_stride = block_size_wide[plane_bsize];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700933 uint8_t *src, *dst;
934 int16_t *src_diff;
935 uint16_t *eob = &p->eobs[block];
936 const int src_stride = p->src.stride;
937 const int dst_stride = pd->dst.stride;
Jingning Han62a2b9e2016-10-24 10:32:37 -0700938 const int tx1d_width = tx_size_wide[tx_size];
939 const int tx1d_height = tx_size_high[tx_size];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700940 ENTROPY_CONTEXT *a = NULL, *l = NULL;
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800941 int ctx = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700942 INV_TXFM_PARAM inv_txfm_param;
Yushin Cho3827fdd2016-11-09 15:50:23 -0800943#if CONFIG_PVQ
Yushin Cho77bba8d2016-11-04 16:36:56 -0700944 int tx_blk_size;
945 int i, j;
Yushin Cho77bba8d2016-11-04 16:36:56 -0700946#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -0700947
948 assert(tx1d_width == tx1d_height);
949
Jingning Han81492262016-12-05 15:48:47 -0800950 dst = &pd->dst.buf[(blk_row * dst_stride + blk_col) << tx_size_wide_log2[0]];
951 src = &p->src.buf[(blk_row * src_stride + blk_col) << tx_size_wide_log2[0]];
952 src_diff =
953 &p->src_diff[(blk_row * diff_stride + blk_col) << tx_size_wide_log2[0]];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700954 mode = plane == 0 ? get_y_mode(xd->mi[0], block) : mbmi->uv_mode;
Jingning Hanc4c99da2016-10-24 10:27:28 -0700955 av1_predict_intra_block(xd, pd->width, pd->height, tx_size, mode, dst,
956 dst_stride, dst, dst_stride, blk_col, blk_row, plane);
Jingning Hane325abd2016-12-01 09:35:10 -0800957
958 if (check_subtract_block_size(tx1d_width, tx1d_height)) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700959#if CONFIG_AOM_HIGHBITDEPTH
Jingning Hane325abd2016-12-01 09:35:10 -0800960 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
961 aom_highbd_subtract_block_c(tx1d_height, tx1d_width, src_diff,
962 diff_stride, src, src_stride, dst, dst_stride,
963 xd->bd);
964 } else {
965 aom_subtract_block_c(tx1d_height, tx1d_width, src_diff, diff_stride, src,
966 src_stride, dst, dst_stride);
967 }
968#else
969 aom_subtract_block_c(tx1d_height, tx1d_width, src_diff, diff_stride, src,
970 src_stride, dst, dst_stride);
971#endif // CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700972 } else {
Jingning Hane325abd2016-12-01 09:35:10 -0800973#if CONFIG_AOM_HIGHBITDEPTH
974 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
975 aom_highbd_subtract_block(tx1d_height, tx1d_width, src_diff, diff_stride,
976 src, src_stride, dst, dst_stride, xd->bd);
977 } else {
978 aom_subtract_block(tx1d_height, tx1d_width, src_diff, diff_stride, src,
979 src_stride, dst, dst_stride);
980 }
981#else
Yaowu Xuf883b422016-08-30 14:01:10 -0700982 aom_subtract_block(tx1d_height, tx1d_width, src_diff, diff_stride, src,
Yaowu Xuc27fc142016-08-22 16:08:15 -0700983 src_stride, dst, dst_stride);
Yaowu Xuf883b422016-08-30 14:01:10 -0700984#endif // CONFIG_AOM_HIGHBITDEPTH
Jingning Hane325abd2016-12-01 09:35:10 -0800985 }
Yaowu Xuc27fc142016-08-22 16:08:15 -0700986
987 a = &args->ta[blk_col];
988 l = &args->tl[blk_row];
Yushin Cho3827fdd2016-11-09 15:50:23 -0800989#if !CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -0700990 ctx = combine_entropy_contexts(*a, *l);
991
992 if (args->enable_optimize_b) {
993#if CONFIG_NEW_QUANT
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800994 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
995 ctx, AV1_XFORM_QUANT_FP_NUQ);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700996#else // CONFIG_NEW_QUANT
Angie Chiangff6d8902016-10-21 11:02:09 -0700997 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800998 ctx, AV1_XFORM_QUANT_FP);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700999#endif // CONFIG_NEW_QUANT
1000 if (p->eobs[block]) {
Angie Chiangff6d8902016-10-21 11:02:09 -07001001 *a = *l = av1_optimize_b(cm, x, plane, block, tx_size, ctx) > 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001002 } else {
1003 *a = *l = 0;
1004 }
1005 } else {
Debargha Mukherjeef0305582016-11-24 09:55:34 -08001006#if CONFIG_NEW_QUANT
Angie Chiangff6d8902016-10-21 11:02:09 -07001007 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
Debargha Mukherjeef0305582016-11-24 09:55:34 -08001008 ctx, AV1_XFORM_QUANT_B_NUQ);
1009#else // CONFIG_NEW_QUANT
1010 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
1011 ctx, AV1_XFORM_QUANT_B);
1012#endif // CONFIG_NEW_QUANT
Yaowu Xuc27fc142016-08-22 16:08:15 -07001013 *a = *l = p->eobs[block] > 0;
1014 }
1015
1016 if (*eob) {
1017 // inverse transform
1018 inv_txfm_param.tx_type = tx_type;
1019 inv_txfm_param.tx_size = tx_size;
1020 inv_txfm_param.eob = *eob;
1021 inv_txfm_param.lossless = xd->lossless[mbmi->segment_id];
Yaowu Xuf883b422016-08-30 14:01:10 -07001022#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07001023 inv_txfm_param.bd = xd->bd;
1024 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
1025 highbd_inv_txfm_add(dqcoeff, dst, dst_stride, &inv_txfm_param);
1026 } else {
1027 inv_txfm_add(dqcoeff, dst, dst_stride, &inv_txfm_param);
1028 }
1029#else
1030 inv_txfm_add(dqcoeff, dst, dst_stride, &inv_txfm_param);
Yaowu Xuf883b422016-08-30 14:01:10 -07001031#endif // CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07001032
1033 *(args->skip) = 0;
1034 }
Yaowu Xu859a5272016-11-10 15:32:21 -08001035#else // #if !CONFIG_PVQ
Yushin Cho3827fdd2016-11-09 15:50:23 -08001036
Debargha Mukherjeef0305582016-11-24 09:55:34 -08001037#if CONFIG_NEW_QUANT
Yushin Cho3827fdd2016-11-09 15:50:23 -08001038 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
Debargha Mukherjeef0305582016-11-24 09:55:34 -08001039 ctx, AV1_XFORM_QUANT_FP_NUQ);
1040#else
1041 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
1042 ctx, AV1_XFORM_QUANT_FP);
1043#endif // CONFIG_NEW_QUANT
Yushin Cho3827fdd2016-11-09 15:50:23 -08001044
1045 *a = *l = !x->pvq_skip[plane];
1046
1047 // *(args->skip) == mbmi->skip
1048 if (!x->pvq_skip[plane]) *(args->skip) = 0;
1049
1050 if (x->pvq_skip[plane]) return;
1051
Yushin Cho77bba8d2016-11-04 16:36:56 -07001052 // transform block size in pixels
1053 tx_blk_size = tx_size_wide[tx_size];
1054
Yushin Cho77bba8d2016-11-04 16:36:56 -07001055 // Since av1 does not have separate function which does inverse transform
1056 // but av1_inv_txfm_add_*x*() also does addition of predicted image to
1057 // inverse transformed image,
1058 // pass blank dummy image to av1_inv_txfm_add_*x*(), i.e. set dst as zeros
1059
Yushin Cho3827fdd2016-11-09 15:50:23 -08001060 for (j = 0; j < tx_blk_size; j++)
1061 for (i = 0; i < tx_blk_size; i++) dst[j * dst_stride + i] = 0;
Yushin Cho77bba8d2016-11-04 16:36:56 -07001062
Yushin Cho3827fdd2016-11-09 15:50:23 -08001063 inv_txfm_param.tx_type = tx_type;
1064 inv_txfm_param.tx_size = tx_size;
1065 inv_txfm_param.eob = *eob;
1066 inv_txfm_param.lossless = xd->lossless[mbmi->segment_id];
1067#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xu859a5272016-11-10 15:32:21 -08001068#error
Yushin Cho3827fdd2016-11-09 15:50:23 -08001069
1070#else
1071 inv_txfm_add(dqcoeff, dst, dst_stride, &inv_txfm_param);
1072#endif
Yushin Cho77bba8d2016-11-04 16:36:56 -07001073#endif // #if !CONFIG_PVQ
1074
1075#if !CONFIG_PVQ
1076 if (*eob) *(args->skip) = 0;
1077#else
1078// Note : *(args->skip) == mbmi->skip
1079#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07001080}
1081
Angie Chiangff6d8902016-10-21 11:02:09 -07001082void av1_encode_intra_block_plane(AV1_COMMON *cm, MACROBLOCK *x,
1083 BLOCK_SIZE bsize, int plane,
Yaowu Xuf883b422016-08-30 14:01:10 -07001084 int enable_optimize_b) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07001085 const MACROBLOCKD *const xd = &x->e_mbd;
Guillaume Martrese50d9dd2016-12-18 18:26:47 +01001086 ENTROPY_CONTEXT ta[2 * MAX_MIB_SIZE] = { 0 };
1087 ENTROPY_CONTEXT tl[2 * MAX_MIB_SIZE] = { 0 };
Yaowu Xuc27fc142016-08-22 16:08:15 -07001088
Angie Chiangff6d8902016-10-21 11:02:09 -07001089 struct encode_b_args arg = {
1090 cm, x, NULL, &xd->mi[0]->mbmi.skip, ta, tl, enable_optimize_b
1091 };
Yaowu Xuc27fc142016-08-22 16:08:15 -07001092 if (enable_optimize_b) {
1093 const struct macroblockd_plane *const pd = &xd->plane[plane];
1094 const TX_SIZE tx_size =
1095 plane ? get_uv_tx_size(&xd->mi[0]->mbmi, pd) : xd->mi[0]->mbmi.tx_size;
Yaowu Xuf883b422016-08-30 14:01:10 -07001096 av1_get_entropy_contexts(bsize, tx_size, pd, ta, tl);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001097 }
Yaowu Xuf883b422016-08-30 14:01:10 -07001098 av1_foreach_transformed_block_in_plane(xd, bsize, plane,
1099 av1_encode_block_intra, &arg);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001100}
Yushin Cho77bba8d2016-11-04 16:36:56 -07001101
1102#if CONFIG_PVQ
1103int av1_pvq_encode_helper(daala_enc_ctx *daala_enc, tran_low_t *const coeff,
1104 tran_low_t *ref_coeff, tran_low_t *const dqcoeff,
1105 uint16_t *eob, const int16_t *quant, int plane,
1106 int tx_size, TX_TYPE tx_type, int *rate, int speed,
1107 PVQ_INFO *pvq_info) {
1108 const int tx_blk_size = tx_size_wide[tx_size];
1109 int skip;
Debargha Mukherjee153e1f82016-11-17 09:59:14 -08001110 int quant_shift = get_tx_scale(tx_size);
Yushin Cho70669122016-12-08 09:53:14 -10001111 int pvq_dc_quant;
1112 int use_activity_masking = daala_enc->use_activity_masking;
Yushin Cho77bba8d2016-11-04 16:36:56 -07001113 int tell;
1114 int has_dc_skip = 1;
1115 int i;
1116 int off = od_qm_offset(tx_size, plane ? 1 : 0);
1117#if PVQ_CHROMA_RD
1118 double save_pvq_lambda;
1119#endif
Yushin Cho70669122016-12-08 09:53:14 -10001120
Yushin Cho48f84db2016-11-07 21:20:17 -08001121 DECLARE_ALIGNED(16, int16_t, coeff_pvq[OD_TXSIZE_MAX * OD_TXSIZE_MAX]);
1122 DECLARE_ALIGNED(16, int16_t, ref_coeff_pvq[OD_TXSIZE_MAX * OD_TXSIZE_MAX]);
1123 DECLARE_ALIGNED(16, int16_t, dqcoeff_pvq[OD_TXSIZE_MAX * OD_TXSIZE_MAX]);
Yushin Cho77bba8d2016-11-04 16:36:56 -07001124
Yushin Cho48f84db2016-11-07 21:20:17 -08001125 DECLARE_ALIGNED(16, int32_t, in_int32[OD_TXSIZE_MAX * OD_TXSIZE_MAX]);
1126 DECLARE_ALIGNED(16, int32_t, ref_int32[OD_TXSIZE_MAX * OD_TXSIZE_MAX]);
1127 DECLARE_ALIGNED(16, int32_t, out_int32[OD_TXSIZE_MAX * OD_TXSIZE_MAX]);
Yushin Cho77bba8d2016-11-04 16:36:56 -07001128
Yushin Cho70669122016-12-08 09:53:14 -10001129 // DC quantizer for PVQ
1130 if (use_activity_masking)
1131 pvq_dc_quant = OD_MAXI(
1132 1, (quant[0] >> quant_shift) *
1133 daala_enc->state.pvq_qm_q4[plane]
1134 [od_qm_get_index(tx_size, 0)] >>
1135 4);
1136 else
1137 pvq_dc_quant = OD_MAXI(1, quant[0] >> quant_shift);
1138
Yushin Cho77bba8d2016-11-04 16:36:56 -07001139 *eob = 0;
1140
Nathan E. Egge6675be02016-12-21 13:02:43 -05001141#if CONFIG_DAALA_EC
1142 tell = od_ec_enc_tell_frac(&daala_enc->w.ec);
1143#else
1144#error "CONFIG_PVQ currently requires CONFIG_DAALA_EC."
1145#endif
Yushin Cho77bba8d2016-11-04 16:36:56 -07001146
1147 // Change coefficient ordering for pvq encoding.
1148 od_raster_to_coding_order(coeff_pvq, tx_blk_size, tx_type, coeff,
1149 tx_blk_size);
1150 od_raster_to_coding_order(ref_coeff_pvq, tx_blk_size, tx_type, ref_coeff,
1151 tx_blk_size);
1152
1153 // copy int16 inputs to int32
1154 for (i = 0; i < tx_blk_size * tx_blk_size; i++) {
1155 ref_int32[i] = ref_coeff_pvq[i];
1156 in_int32[i] = coeff_pvq[i];
1157 }
1158
1159#if PVQ_CHROMA_RD
1160 if (plane != 0) {
1161 save_pvq_lambda = daala_enc->pvq_norm_lambda;
1162 daala_enc->pvq_norm_lambda *= 0.8;
1163 }
1164#endif
1165 if (abs(in_int32[0] - ref_int32[0]) < pvq_dc_quant * 141 / 256) { /* 0.55 */
1166 out_int32[0] = 0;
1167 } else {
1168 out_int32[0] = OD_DIV_R0(in_int32[0] - ref_int32[0], pvq_dc_quant);
1169 }
1170
Yushin Cho70669122016-12-08 09:53:14 -10001171 skip = od_pvq_encode(daala_enc, ref_int32, in_int32, out_int32,
1172 (int)quant[0] >> quant_shift, // scale/quantizer
1173 (int)quant[1] >> quant_shift, // scale/quantizer
1174 plane, tx_size,
1175 OD_PVQ_BETA[use_activity_masking][plane][tx_size],
1176 OD_ROBUST_STREAM,
1177 0, // is_keyframe,
1178 0, 0, 0, // q_scaling, bx, by,
1179 daala_enc->state.qm + off, daala_enc->state.qm_inv + off,
1180 speed, // speed
1181 pvq_info);
Yushin Cho77bba8d2016-11-04 16:36:56 -07001182
1183 if (skip && pvq_info) assert(pvq_info->ac_dc_coded == 0);
1184
1185 if (!skip && pvq_info) assert(pvq_info->ac_dc_coded > 0);
1186
1187 // Encode residue of DC coeff, if required.
1188 if (!has_dc_skip || out_int32[0]) {
Nathan E. Egge6675be02016-12-21 13:02:43 -05001189#if CONFIG_DAALA_EC
1190 generic_encode(&daala_enc->w.ec, &daala_enc->state.adapt.model_dc[plane],
Yushin Cho77bba8d2016-11-04 16:36:56 -07001191 abs(out_int32[0]) - has_dc_skip, -1,
1192 &daala_enc->state.adapt.ex_dc[plane][tx_size][0], 2);
Nathan E. Egge6675be02016-12-21 13:02:43 -05001193#else
1194#error "CONFIG_PVQ currently requires CONFIG_DAALA_EC."
1195#endif
Yushin Cho77bba8d2016-11-04 16:36:56 -07001196 }
1197 if (out_int32[0]) {
Nathan E. Egge6675be02016-12-21 13:02:43 -05001198 aom_write_bit(&daala_enc->w, out_int32[0] < 0);
Yushin Cho77bba8d2016-11-04 16:36:56 -07001199 skip = 0;
1200 }
1201
1202 // need to save quantized residue of DC coeff
1203 // so that final pvq bitstream writing can know whether DC is coded.
1204 if (pvq_info) pvq_info->dq_dc_residue = out_int32[0];
1205
1206 out_int32[0] = out_int32[0] * pvq_dc_quant;
1207 out_int32[0] += ref_int32[0];
1208
1209 // copy int32 result back to int16
1210 for (i = 0; i < tx_blk_size * tx_blk_size; i++) dqcoeff_pvq[i] = out_int32[i];
1211
1212 // Back to original coefficient order
1213 od_coding_order_to_raster(dqcoeff, tx_blk_size, tx_type, dqcoeff_pvq,
1214 tx_blk_size);
1215
1216 *eob = tx_blk_size * tx_blk_size;
1217
Nathan E. Egge6675be02016-12-21 13:02:43 -05001218#if CONFIG_DAALA_EC
1219 *rate = (od_ec_enc_tell_frac(&daala_enc->w.ec) - tell)
Yushin Cho77bba8d2016-11-04 16:36:56 -07001220 << (AV1_PROB_COST_SHIFT - OD_BITRES);
Nathan E. Egge6675be02016-12-21 13:02:43 -05001221#else
1222#error "CONFIG_PVQ currently requires CONFIG_DAALA_EC."
1223#endif
Yushin Cho77bba8d2016-11-04 16:36:56 -07001224 assert(*rate >= 0);
1225#if PVQ_CHROMA_RD
1226 if (plane != 0) daala_enc->pvq_norm_lambda = save_pvq_lambda;
1227#endif
1228 return skip;
1229}
1230
1231void av1_store_pvq_enc_info(PVQ_INFO *pvq_info, int *qg, int *theta,
1232 int *max_theta, int *k, od_coeff *y, int nb_bands,
1233 const int *off, int *size, int skip_rest,
1234 int skip_dir,
1235 int bs) { // block size in log_2 -2
1236 int i;
1237 const int tx_blk_size = tx_size_wide[bs];
1238
1239 for (i = 0; i < nb_bands; i++) {
1240 pvq_info->qg[i] = qg[i];
1241 pvq_info->theta[i] = theta[i];
1242 pvq_info->max_theta[i] = max_theta[i];
1243 pvq_info->k[i] = k[i];
1244 pvq_info->off[i] = off[i];
1245 pvq_info->size[i] = size[i];
1246 }
1247
1248 memcpy(pvq_info->y, y, tx_blk_size * tx_blk_size * sizeof(od_coeff));
1249
1250 pvq_info->nb_bands = nb_bands;
1251 pvq_info->skip_rest = skip_rest;
1252 pvq_info->skip_dir = skip_dir;
1253 pvq_info->bs = bs;
1254}
1255#endif