blob: e0f4516c6c97869979844fd9870c3e5356e01f56 [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"
Angie Chiang74e23072017-03-24 14:54:23 -070028#if CONFIG_LV_MAP
29#include "av1/encoder/encodetxb.h"
30#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -070031#include "av1/encoder/hybrid_fwd_txfm.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070032#include "av1/encoder/rd.h"
33#include "av1/encoder/tokenize.h"
34
Yushin Cho77bba8d2016-11-04 16:36:56 -070035#if CONFIG_PVQ
36#include "av1/encoder/encint.h"
37#include "av1/common/partition.h"
38#include "av1/encoder/pvq_encoder.h"
39#endif
40
Luc Trudeaue3980282017-04-25 23:17:21 -040041#if CONFIG_CFL
42#include "av1/common/cfl.h"
43#endif
44
Jingning Hane325abd2016-12-01 09:35:10 -080045// Check if one needs to use c version subtraction.
46static int check_subtract_block_size(int w, int h) { return w < 4 || h < 4; }
47
Angie Chiang19407b52017-04-02 15:27:57 -070048static void subtract_block(const MACROBLOCKD *xd, int rows, int cols,
49 int16_t *diff, ptrdiff_t diff_stride,
50 const uint8_t *src8, ptrdiff_t src_stride,
51 const uint8_t *pred8, ptrdiff_t pred_stride) {
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020052#if !CONFIG_HIGHBITDEPTH
Angie Chiang19407b52017-04-02 15:27:57 -070053 (void)xd;
54#endif
55
56 if (check_subtract_block_size(rows, cols)) {
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020057#if CONFIG_HIGHBITDEPTH
Angie Chiang19407b52017-04-02 15:27:57 -070058 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
59 aom_highbd_subtract_block_c(rows, cols, diff, diff_stride, src8,
60 src_stride, pred8, pred_stride, xd->bd);
61 return;
62 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020063#endif // CONFIG_HIGHBITDEPTH
Angie Chiang19407b52017-04-02 15:27:57 -070064 aom_subtract_block_c(rows, cols, diff, diff_stride, src8, src_stride, pred8,
65 pred_stride);
66
67 return;
68 }
69
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020070#if CONFIG_HIGHBITDEPTH
Angie Chiang19407b52017-04-02 15:27:57 -070071 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
72 aom_highbd_subtract_block(rows, cols, diff, diff_stride, src8, src_stride,
73 pred8, pred_stride, xd->bd);
74 return;
75 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020076#endif // CONFIG_HIGHBITDEPTH
Angie Chiang19407b52017-04-02 15:27:57 -070077 aom_subtract_block(rows, cols, diff, diff_stride, src8, src_stride, pred8,
78 pred_stride);
79}
80
Angie Chiangf87e43f2017-04-02 16:51:19 -070081void av1_subtract_txb(MACROBLOCK *x, int plane, BLOCK_SIZE plane_bsize,
82 int blk_col, int blk_row, TX_SIZE tx_size) {
83 MACROBLOCKD *const xd = &x->e_mbd;
84 struct macroblock_plane *const p = &x->plane[plane];
85 const struct macroblockd_plane *const pd = &x->e_mbd.plane[plane];
86 const int diff_stride = block_size_wide[plane_bsize];
87 const int src_stride = p->src.stride;
88 const int dst_stride = pd->dst.stride;
89 const int tx1d_width = tx_size_wide[tx_size];
90 const int tx1d_height = tx_size_high[tx_size];
91 uint8_t *dst =
92 &pd->dst.buf[(blk_row * dst_stride + blk_col) << tx_size_wide_log2[0]];
93 uint8_t *src =
94 &p->src.buf[(blk_row * src_stride + blk_col) << tx_size_wide_log2[0]];
95 int16_t *src_diff =
96 &p->src_diff[(blk_row * diff_stride + blk_col) << tx_size_wide_log2[0]];
97 subtract_block(xd, tx1d_height, tx1d_width, src_diff, diff_stride, src,
98 src_stride, dst, dst_stride);
99}
100
Yaowu Xuf883b422016-08-30 14:01:10 -0700101void av1_subtract_plane(MACROBLOCK *x, BLOCK_SIZE bsize, int plane) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700102 struct macroblock_plane *const p = &x->plane[plane];
103 const struct macroblockd_plane *const pd = &x->e_mbd.plane[plane];
104 const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
Jingning Hanae5cfde2016-11-30 12:01:44 -0800105 const int bw = block_size_wide[plane_bsize];
106 const int bh = block_size_high[plane_bsize];
Angie Chiang19407b52017-04-02 15:27:57 -0700107 const MACROBLOCKD *xd = &x->e_mbd;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700108
Angie Chiang19407b52017-04-02 15:27:57 -0700109 subtract_block(xd, bh, bw, p->src_diff, bw, p->src.buf, p->src.stride,
110 pd->dst.buf, pd->dst.stride);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700111}
112
Yaowu Xuc27fc142016-08-22 16:08:15 -0700113// These numbers are empirically obtained.
114static const int plane_rd_mult[REF_TYPES][PLANE_TYPES] = {
Thomas Davies10525752017-03-06 12:10:46 +0000115#if CONFIG_EC_ADAPT
116 { 10, 7 }, { 8, 5 },
117#else
Angie Chiangebcdb252017-05-05 18:15:10 -0700118 { 10, 6 }, { 8, 6 },
Thomas Davies10525752017-03-06 12:10:46 +0000119#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -0700120};
121
Yaowu Xu42350322017-05-05 11:12:19 -0700122static INLINE unsigned int get_token_bit_costs(
123 unsigned int token_costs[2][COEFF_CONTEXTS][ENTROPY_TOKENS], int skip_eob,
124 int ctx, int token) {
Thomas Daviesed8e2d22017-01-04 16:42:09 +0000125 (void)skip_eob;
126 return token_costs[token == ZERO_TOKEN || token == EOB_TOKEN][ctx][token];
Thomas Daviesed8e2d22017-01-04 16:42:09 +0000127}
128
Angie Chiang1c96e822017-05-31 14:40:55 -0700129#if !CONFIG_LV_MAP
Dake He97f56642017-03-29 16:46:51 -0700130
Angie Chiang7dec6c42017-05-03 17:58:17 -0700131typedef struct av1_token_state_greedy {
Dake He97f56642017-03-29 16:46:51 -0700132 int16_t token;
133 tran_low_t qc;
134 tran_low_t dqc;
Angie Chiang7dec6c42017-05-03 17:58:17 -0700135} av1_token_state_greedy;
Dake He97f56642017-03-29 16:46:51 -0700136
Angie Chiang7dec6c42017-05-03 17:58:17 -0700137static int optimize_b_greedy(const AV1_COMMON *cm, MACROBLOCK *mb, int plane,
138 int block, TX_SIZE tx_size, int ctx) {
Dake He97f56642017-03-29 16:46:51 -0700139 MACROBLOCKD *const xd = &mb->e_mbd;
140 struct macroblock_plane *const p = &mb->plane[plane];
141 struct macroblockd_plane *const pd = &xd->plane[plane];
142 const int ref = is_inter_block(&xd->mi[0]->mbmi);
Angie Chiang7dec6c42017-05-03 17:58:17 -0700143 av1_token_state_greedy tokens[MAX_TX_SQUARE + 1][2];
Dake He97f56642017-03-29 16:46:51 -0700144 uint8_t token_cache[MAX_TX_SQUARE];
145 const tran_low_t *const coeff = BLOCK_OFFSET(p->coeff, block);
146 tran_low_t *const qcoeff = BLOCK_OFFSET(p->qcoeff, block);
147 tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
148 const int eob = p->eobs[block];
149 const PLANE_TYPE plane_type = pd->plane_type;
150 const int16_t *const dequant_ptr = pd->dequant;
151 const uint8_t *const band_translate = get_band_translate(tx_size);
152 TX_TYPE tx_type = get_tx_type(plane_type, xd, block, tx_size);
153 const SCAN_ORDER *const scan_order =
Angie Chiangbd99b382017-06-20 15:11:16 -0700154 get_scan(cm, tx_size, tx_type, &xd->mi[0]->mbmi);
Dake He97f56642017-03-29 16:46:51 -0700155 const int16_t *const scan = scan_order->scan;
156 const int16_t *const nb = scan_order->neighbors;
157 int dqv;
Jingning Hanff705452017-04-27 11:32:15 -0700158 const int shift = av1_get_tx_scale(tx_size);
Dake He97f56642017-03-29 16:46:51 -0700159#if CONFIG_AOM_QM
160 int seg_id = xd->mi[0]->mbmi.segment_id;
Thomas Daviesbe44e512017-06-07 11:41:07 +0100161 // Use a flat matrix (i.e. no weighting) for 1D and Identity transforms
162 const qm_val_t *iqmatrix =
163 IS_2D_TRANSFORM(tx_type)
164 ? pd->seg_iqmatrix[seg_id][!ref][tx_size]
165 : cm->giqmatrix[NUM_QM_LEVELS - 1][0][0][tx_size];
Dake He97f56642017-03-29 16:46:51 -0700166#endif
167#if CONFIG_NEW_QUANT
168 int dq = get_dq_profile_from_ctx(mb->qindex, ctx, ref, plane_type);
169 const dequant_val_type_nuq *dequant_val = pd->dequant_val_nuq[dq];
Dake He97f56642017-03-29 16:46:51 -0700170#endif // CONFIG_NEW_QUANT
171 int sz = 0;
Dake He97f56642017-03-29 16:46:51 -0700172 int64_t rd_cost0, rd_cost1;
173 int16_t t0, t1;
174 int i, final_eob;
Dake He97f56642017-03-29 16:46:51 -0700175 const int cat6_bits = av1_get_cat6_extrabits_size(tx_size, xd->bd);
Dake He97f56642017-03-29 16:46:51 -0700176 unsigned int(*token_costs)[2][COEFF_CONTEXTS][ENTROPY_TOKENS] =
177 mb->token_costs[txsize_sqr_map[tx_size]][plane_type][ref];
178 const int default_eob = tx_size_2d[tx_size];
179
Angie Chiang7dec6c42017-05-03 17:58:17 -0700180 assert(mb->qindex > 0);
Dake He97f56642017-03-29 16:46:51 -0700181
182 assert((!plane_type && !plane) || (plane_type && plane));
183 assert(eob <= default_eob);
184
185 int64_t rdmult = (mb->rdmult * plane_rd_mult[ref][plane_type]) >> 1;
Dake He97f56642017-03-29 16:46:51 -0700186
187 int64_t rate0, rate1;
188 for (i = 0; i < eob; i++) {
189 const int rc = scan[i];
190 int x = qcoeff[rc];
191 t0 = av1_get_token(x);
192
193 tokens[i][0].qc = x;
194 tokens[i][0].token = t0;
195 tokens[i][0].dqc = dqcoeff[rc];
196
197 token_cache[rc] = av1_pt_energy_class[t0];
198 }
199 tokens[eob][0].token = EOB_TOKEN;
200 tokens[eob][0].qc = 0;
201 tokens[eob][0].dqc = 0;
202 tokens[eob][1] = tokens[eob][0];
203
204 unsigned int(*token_costs_ptr)[2][COEFF_CONTEXTS][ENTROPY_TOKENS] =
205 token_costs;
206
207 final_eob = 0;
208
209 int64_t eob_cost0, eob_cost1;
210
211 const int ctx0 = ctx;
212 /* Record the r-d cost */
213 int64_t accu_rate = 0;
Urvang Joshi6eb35eb2017-06-14 13:28:56 -0700214 // Initialized to the worst possible error for the largest transform size.
215 // This ensures that it never goes negative.
216 int64_t accu_error = ((int64_t)1) << 50;
Dake He97f56642017-03-29 16:46:51 -0700217
218 rate0 = get_token_bit_costs(*(token_costs_ptr + band_translate[0]), 0, ctx0,
219 EOB_TOKEN);
Urvang Joshi70006e42017-06-14 16:08:55 -0700220 int64_t best_block_rd_cost = RDCOST(rdmult, rate0, accu_error);
Dake He97f56642017-03-29 16:46:51 -0700221
222 // int64_t best_block_rd_cost_all0 = best_block_rd_cost;
223
224 int x_prev = 1;
225
226 for (i = 0; i < eob; i++) {
227 const int rc = scan[i];
228 int x = qcoeff[rc];
229 sz = -(x < 0);
230
231 int band_cur = band_translate[i];
232 int ctx_cur = (i == 0) ? ctx : get_coef_context(nb, token_cache, i);
233 int token_tree_sel_cur = (x_prev == 0);
234
235 if (x == 0) {
236 // no need to search when x == 0
237 rate0 =
238 get_token_bit_costs(*(token_costs_ptr + band_cur), token_tree_sel_cur,
239 ctx_cur, tokens[i][0].token);
240 accu_rate += rate0;
241 x_prev = 0;
242 // accu_error does not change when x==0
243 } else {
244 /* Computing distortion
245 */
246 // compute the distortion for the first candidate
247 // and the distortion for quantizing to 0.
Jingning Han32d26bc2017-06-11 07:50:39 -0700248 int dx0 = abs(coeff[rc]) * (1 << shift);
Dake He97f56642017-03-29 16:46:51 -0700249#if CONFIG_HIGHBITDEPTH
250 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
251 dx0 >>= xd->bd - 8;
252 }
253#endif
254 int64_t d0 = (int64_t)dx0 * dx0;
255
256 int x_a = x - 2 * sz - 1;
257 int64_t d2, d2_a;
258
259 int dx;
260
261#if CONFIG_AOM_QM
262 int iwt = iqmatrix[rc];
263 dqv = dequant_ptr[rc != 0];
264 dqv = ((iwt * (int)dqv) + (1 << (AOM_QM_BITS - 1))) >> AOM_QM_BITS;
265#else
266 dqv = dequant_ptr[rc != 0];
267#endif
268
269 dx = (dqcoeff[rc] - coeff[rc]) * (1 << shift);
270#if CONFIG_HIGHBITDEPTH
271 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
Jingning Han32d26bc2017-06-11 07:50:39 -0700272 int dx_sign = dx < 0 ? 1 : 0;
273 dx = abs(dx) >> (xd->bd - 8);
274 if (dx_sign) dx = -dx;
Dake He97f56642017-03-29 16:46:51 -0700275 }
276#endif // CONFIG_HIGHBITDEPTH
277 d2 = (int64_t)dx * dx;
278
279 /* compute the distortion for the second candidate
280 * x_a = x - 2 * sz + 1;
281 */
282 if (x_a != 0) {
283#if CONFIG_NEW_QUANT
284 dx = av1_dequant_coeff_nuq(x, dqv, dequant_val[band_translate[i]]) -
285 (coeff[rc] << shift);
286#if CONFIG_HIGHBITDEPTH
287 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
288 dx >>= xd->bd - 8;
289 }
290#endif // CONFIG_HIGHBITDEPTH
291#else // CONFIG_NEW_QUANT
292#if CONFIG_HIGHBITDEPTH
293 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
294 dx -= ((dqv >> (xd->bd - 8)) + sz) ^ sz;
295 } else {
296 dx -= (dqv + sz) ^ sz;
297 }
298#else
299 dx -= (dqv + sz) ^ sz;
300#endif // CONFIG_HIGHBITDEPTH
301#endif // CONFIG_NEW_QUANT
302 d2_a = (int64_t)dx * dx;
303 } else {
304 d2_a = d0;
305 }
306 /* Computing rates and r-d cost
307 */
308
309 int best_x, best_eob_x;
310 int64_t base_bits, next_bits0, next_bits1;
311 int64_t next_eob_bits0, next_eob_bits1;
312
313 // rate cost of x
314 base_bits = av1_get_token_cost(x, &t0, cat6_bits);
315 rate0 = base_bits + get_token_bit_costs(*(token_costs_ptr + band_cur),
316 token_tree_sel_cur, ctx_cur, t0);
317
318 base_bits = av1_get_token_cost(x_a, &t1, cat6_bits);
319 rate1 = base_bits + get_token_bit_costs(*(token_costs_ptr + band_cur),
320 token_tree_sel_cur, ctx_cur, t1);
321
322 next_bits0 = 0;
323 next_bits1 = 0;
324 next_eob_bits0 = 0;
325 next_eob_bits1 = 0;
326
327 if (i < default_eob - 1) {
328 int ctx_next, token_tree_sel_next;
329 int band_next = band_translate[i + 1];
330
331 token_cache[rc] = av1_pt_energy_class[t0];
332 ctx_next = get_coef_context(nb, token_cache, i + 1);
333 token_tree_sel_next = (x == 0);
334
335 next_bits0 = get_token_bit_costs(*(token_costs_ptr + band_next),
336 token_tree_sel_next, ctx_next,
337 tokens[i + 1][0].token);
338 next_eob_bits0 =
339 get_token_bit_costs(*(token_costs_ptr + band_next),
340 token_tree_sel_next, ctx_next, EOB_TOKEN);
341
342 token_cache[rc] = av1_pt_energy_class[t1];
343 ctx_next = get_coef_context(nb, token_cache, i + 1);
344 token_tree_sel_next = (x_a == 0);
345
346 next_bits1 = get_token_bit_costs(*(token_costs_ptr + band_next),
347 token_tree_sel_next, ctx_next,
348 tokens[i + 1][0].token);
349
350 if (x_a != 0) {
351 next_eob_bits1 =
352 get_token_bit_costs(*(token_costs_ptr + band_next),
353 token_tree_sel_next, ctx_next, EOB_TOKEN);
354 }
355 }
356
Urvang Joshi70006e42017-06-14 16:08:55 -0700357 rd_cost0 = RDCOST(rdmult, (rate0 + next_bits0), d2);
358 rd_cost1 = RDCOST(rdmult, (rate1 + next_bits1), d2_a);
Dake He97f56642017-03-29 16:46:51 -0700359
360 best_x = (rd_cost1 < rd_cost0);
361
Urvang Joshi70006e42017-06-14 16:08:55 -0700362 eob_cost0 = RDCOST(rdmult, (accu_rate + rate0 + next_eob_bits0),
Dake He97f56642017-03-29 16:46:51 -0700363 (accu_error + d2 - d0));
364 eob_cost1 = eob_cost0;
365 if (x_a != 0) {
Urvang Joshi70006e42017-06-14 16:08:55 -0700366 eob_cost1 = RDCOST(rdmult, (accu_rate + rate1 + next_eob_bits1),
Dake He97f56642017-03-29 16:46:51 -0700367 (accu_error + d2_a - d0));
368 best_eob_x = (eob_cost1 < eob_cost0);
369 } else {
370 best_eob_x = 0;
371 }
372
373 int dqc, dqc_a = 0;
374
375 dqc = dqcoeff[rc];
376 if (best_x + best_eob_x) {
377 if (x_a != 0) {
378#if CONFIG_NEW_QUANT
379 dqc_a = av1_dequant_abscoeff_nuq(abs(x_a), dqv,
380 dequant_val[band_translate[i]]);
381 dqc_a = shift ? ROUND_POWER_OF_TWO(dqc_a, shift) : dqc_a;
382 if (sz) dqc_a = -dqc_a;
383#else
David Barkerc747a782017-05-24 12:46:08 +0100384 if (x_a < 0)
385 dqc_a = -((-x_a * dqv) >> shift);
Dake He97f56642017-03-29 16:46:51 -0700386 else
David Barkerc747a782017-05-24 12:46:08 +0100387 dqc_a = (x_a * dqv) >> shift;
Dake He97f56642017-03-29 16:46:51 -0700388#endif // CONFIG_NEW_QUANT
389 } else {
390 dqc_a = 0;
391 } // if (x_a != 0)
392 }
393
394 // record the better quantized value
395 if (best_x) {
396 qcoeff[rc] = x_a;
397 dqcoeff[rc] = dqc_a;
398
399 accu_rate += rate1;
400 accu_error += d2_a - d0;
401 assert(d2_a <= d0);
402
403 token_cache[rc] = av1_pt_energy_class[t1];
404 } else {
405 accu_rate += rate0;
406 accu_error += d2 - d0;
407 assert(d2 <= d0);
408
409 token_cache[rc] = av1_pt_energy_class[t0];
410 }
Urvang Joshi6eb35eb2017-06-14 13:28:56 -0700411 assert(accu_error >= 0);
Dake He97f56642017-03-29 16:46:51 -0700412
413 x_prev = qcoeff[rc];
414
415 // determine whether to move the eob position to i+1
416 int64_t best_eob_cost_i = eob_cost0;
417
418 tokens[i][1].token = t0;
419 tokens[i][1].qc = x;
420 tokens[i][1].dqc = dqc;
421
422 if ((x_a != 0) && (best_eob_x)) {
423 best_eob_cost_i = eob_cost1;
424
425 tokens[i][1].token = t1;
426 tokens[i][1].qc = x_a;
427 tokens[i][1].dqc = dqc_a;
428 }
429
430 if (best_eob_cost_i < best_block_rd_cost) {
431 best_block_rd_cost = best_eob_cost_i;
432 final_eob = i + 1;
433 }
434 } // if (x==0)
435 } // for (i)
436
437 assert(final_eob <= eob);
438 if (final_eob > 0) {
439 assert(tokens[final_eob - 1][1].qc != 0);
440 i = final_eob - 1;
441 int rc = scan[i];
442 qcoeff[rc] = tokens[i][1].qc;
443 dqcoeff[rc] = tokens[i][1].dqc;
444 }
445
446 for (i = final_eob; i < eob; i++) {
447 int rc = scan[i];
448 qcoeff[rc] = 0;
449 dqcoeff[rc] = 0;
450 }
451
452 mb->plane[plane].eobs[block] = final_eob;
453 return final_eob;
Dake He97f56642017-03-29 16:46:51 -0700454}
Angie Chiang1c96e822017-05-31 14:40:55 -0700455#endif // !CONFIG_LV_MAP
Dake He97f56642017-03-29 16:46:51 -0700456
Angie Chiang7dec6c42017-05-03 17:58:17 -0700457int av1_optimize_b(const AV1_COMMON *cm, MACROBLOCK *mb, int plane, int block,
Angie Chiang3511c372017-05-31 12:47:07 -0700458 BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
459 const ENTROPY_CONTEXT *a, const ENTROPY_CONTEXT *l) {
Angie Chiang7dec6c42017-05-03 17:58:17 -0700460 MACROBLOCKD *const xd = &mb->e_mbd;
461 struct macroblock_plane *const p = &mb->plane[plane];
462 const int eob = p->eobs[block];
463 assert((mb->qindex == 0) ^ (xd->lossless[xd->mi[0]->mbmi.segment_id] == 0));
464 if (eob == 0) return eob;
465 if (xd->lossless[xd->mi[0]->mbmi.segment_id]) return eob;
Jingning Hanaba246d2017-06-14 12:00:16 -0700466
Angie Chiang1c96e822017-05-31 14:40:55 -0700467#if CONFIG_PVQ
468 (void)cm;
469 (void)tx_size;
470 (void)a;
471 (void)l;
472 return eob;
473#endif
Angie Chiang3511c372017-05-31 12:47:07 -0700474
Angie Chiang1c96e822017-05-31 14:40:55 -0700475#if !CONFIG_LV_MAP
476 (void)plane_bsize;
Angie Chiang3511c372017-05-31 12:47:07 -0700477#if CONFIG_VAR_TX
478 int ctx = get_entropy_context(tx_size, a, l);
479#else
480 int ctx = combine_entropy_contexts(*a, *l);
Urvang Joshi09302f52017-06-08 14:24:59 -0700481#endif // CONFIG_VAR_TX
Angie Chiang7dec6c42017-05-03 17:58:17 -0700482 return optimize_b_greedy(cm, mb, plane, block, tx_size, ctx);
Angie Chiang1c96e822017-05-31 14:40:55 -0700483#else // !CONFIG_LV_MAP
484 TXB_CTX txb_ctx;
485 get_txb_ctx(plane_bsize, tx_size, plane, a, l, &txb_ctx);
486 return av1_optimize_txb(cm, mb, plane, block, tx_size, &txb_ctx);
487#endif // !CONFIG_LV_MAP
Angie Chiang7dec6c42017-05-03 17:58:17 -0700488}
489
Thomas Daede6ff6af62017-02-03 16:29:24 -0800490#if !CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -0700491typedef enum QUANT_FUNC {
492 QUANT_FUNC_LOWBD = 0,
493 QUANT_FUNC_HIGHBD = 1,
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800494 QUANT_FUNC_TYPES = 2
Yaowu Xuc27fc142016-08-22 16:08:15 -0700495} QUANT_FUNC;
496
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800497static AV1_QUANT_FACADE
498 quant_func_list[AV1_XFORM_QUANT_TYPES][QUANT_FUNC_TYPES] = {
Angie Chiang6a71ad12017-04-03 11:19:00 -0700499#if !CONFIG_NEW_QUANT
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800500 { av1_quantize_fp_facade, av1_highbd_quantize_fp_facade },
Yaowu Xuf883b422016-08-30 14:01:10 -0700501 { av1_quantize_b_facade, av1_highbd_quantize_b_facade },
502 { av1_quantize_dc_facade, av1_highbd_quantize_dc_facade },
Angie Chiang6a71ad12017-04-03 11:19:00 -0700503#else // !CONFIG_NEW_QUANT
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800504 { av1_quantize_fp_nuq_facade, av1_highbd_quantize_fp_nuq_facade },
505 { av1_quantize_b_nuq_facade, av1_highbd_quantize_b_nuq_facade },
506 { av1_quantize_dc_nuq_facade, av1_highbd_quantize_dc_nuq_facade },
Angie Chiang6a71ad12017-04-03 11:19:00 -0700507#endif // !CONFIG_NEW_QUANT
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800508 { NULL, NULL }
509 };
Yi Luo0f4195c2017-06-27 16:07:28 -0700510#endif // !CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -0700511
Yi Luo0f4195c2017-06-27 16:07:28 -0700512typedef void (*fwdTxfmFunc)(const int16_t *diff, tran_low_t *coeff, int stride,
513 FWD_TXFM_PARAM *param);
514static const fwdTxfmFunc fwd_txfm_func[2] = { av1_fwd_txfm,
515 av1_highbd_fwd_txfm };
Yaowu Xuc27fc142016-08-22 16:08:15 -0700516
Angie Chiangff6d8902016-10-21 11:02:09 -0700517void av1_xform_quant(const AV1_COMMON *cm, MACROBLOCK *x, int plane, int block,
518 int blk_row, int blk_col, BLOCK_SIZE plane_bsize,
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800519 TX_SIZE tx_size, int ctx,
520 AV1_XFORM_QUANT xform_quant_idx) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700521 MACROBLOCKD *const xd = &x->e_mbd;
Luc Trudeaub6e94d92017-03-13 15:46:15 -0400522 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Yushin Cho7a428ba2017-01-12 16:28:49 -0800523#if !(CONFIG_PVQ || CONFIG_DAALA_DIST)
Yaowu Xuc27fc142016-08-22 16:08:15 -0700524 const struct macroblock_plane *const p = &x->plane[plane];
525 const struct macroblockd_plane *const pd = &xd->plane[plane];
Yushin Cho77bba8d2016-11-04 16:36:56 -0700526#else
527 struct macroblock_plane *const p = &x->plane[plane];
528 struct macroblockd_plane *const pd = &xd->plane[plane];
529#endif
Luc Trudeau005feb62017-02-22 13:34:01 -0500530 PLANE_TYPE plane_type = get_plane_type(plane);
Angie Chiang752ccce2017-04-09 13:41:13 -0700531 TX_TYPE tx_type = get_tx_type(plane_type, xd, block, tx_size);
Angie Chiangbd99b382017-06-20 15:11:16 -0700532
533#if CONFIG_AOM_QM || CONFIG_NEW_QUANT
Luc Trudeaub6e94d92017-03-13 15:46:15 -0400534 const int is_inter = is_inter_block(mbmi);
Angie Chiangbd99b382017-06-20 15:11:16 -0700535#endif
536
537 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700538 tran_low_t *const coeff = BLOCK_OFFSET(p->coeff, block);
539 tran_low_t *const qcoeff = BLOCK_OFFSET(p->qcoeff, block);
540 tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
541 uint16_t *const eob = &p->eobs[block];
Jingning Hanae5cfde2016-11-30 12:01:44 -0800542 const int diff_stride = block_size_wide[plane_bsize];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700543#if CONFIG_AOM_QM
Luc Trudeaub6e94d92017-03-13 15:46:15 -0400544 int seg_id = mbmi->segment_id;
Thomas Daviesbe44e512017-06-07 11:41:07 +0100545 // Use a flat matrix (i.e. no weighting) for 1D and Identity transforms
546 const qm_val_t *qmatrix =
547 IS_2D_TRANSFORM(tx_type) ? pd->seg_qmatrix[seg_id][!is_inter][tx_size]
548 : cm->gqmatrix[NUM_QM_LEVELS - 1][0][0][tx_size];
549 const qm_val_t *iqmatrix =
550 IS_2D_TRANSFORM(tx_type)
551 ? pd->seg_iqmatrix[seg_id][!is_inter][tx_size]
552 : cm->giqmatrix[NUM_QM_LEVELS - 1][0][0][tx_size];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700553#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -0700554
555 FWD_TXFM_PARAM fwd_txfm_param;
Yushin Cho77bba8d2016-11-04 16:36:56 -0700556
Yushin Cho7a428ba2017-01-12 16:28:49 -0800557#if CONFIG_PVQ || CONFIG_DAALA_DIST
558 uint8_t *dst;
559 int16_t *pred;
560 const int dst_stride = pd->dst.stride;
Yushin Cho1c602b32017-06-07 17:57:14 -0700561 const int txw = tx_size_wide[tx_size];
562 const int txh = tx_size_high[tx_size];
Yushin Cho7a428ba2017-01-12 16:28:49 -0800563 int i, j;
564#endif
565
Yushin Cho77bba8d2016-11-04 16:36:56 -0700566#if !CONFIG_PVQ
567 const int tx2d_size = tx_size_2d[tx_size];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700568 QUANT_PARAM qparam;
Yushin Cho77bba8d2016-11-04 16:36:56 -0700569 const int16_t *src_diff;
570
Jingning Han81492262016-12-05 15:48:47 -0800571 src_diff =
572 &p->src_diff[(blk_row * diff_stride + blk_col) << tx_size_wide_log2[0]];
Jingning Hanff705452017-04-27 11:32:15 -0700573 qparam.log_scale = av1_get_tx_scale(tx_size);
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800574#if CONFIG_NEW_QUANT
575 qparam.tx_size = tx_size;
576 qparam.dq = get_dq_profile_from_ctx(x->qindex, ctx, is_inter, plane_type);
577#endif // CONFIG_NEW_QUANT
578#if CONFIG_AOM_QM
579 qparam.qmatrix = qmatrix;
580 qparam.iqmatrix = iqmatrix;
581#endif // CONFIG_AOM_QM
Yushin Cho77bba8d2016-11-04 16:36:56 -0700582#else
Yushin Cho77bba8d2016-11-04 16:36:56 -0700583 tran_low_t *ref_coeff = BLOCK_OFFSET(pd->pvq_ref_coeff, block);
Yushin Cho77bba8d2016-11-04 16:36:56 -0700584 int skip = 1;
585 PVQ_INFO *pvq_info = NULL;
Yushin Cho7a428ba2017-01-12 16:28:49 -0800586 uint8_t *src;
587 int16_t *src_int16;
588 const int src_stride = p->src.stride;
Yushin Cho77bba8d2016-11-04 16:36:56 -0700589
Yushin Cho6341f5c2017-03-24 14:36:28 -0700590 (void)ctx;
Yushin Cho77bba8d2016-11-04 16:36:56 -0700591 (void)scan_order;
592 (void)qcoeff;
593
594 if (x->pvq_coded) {
595 assert(block < MAX_PVQ_BLOCKS_IN_SB);
596 pvq_info = &x->pvq[block][plane];
597 }
Jingning Han81492262016-12-05 15:48:47 -0800598 src = &p->src.buf[(blk_row * src_stride + blk_col) << tx_size_wide_log2[0]];
599 src_int16 =
600 &p->src_int16[(blk_row * diff_stride + blk_col) << tx_size_wide_log2[0]];
Yushin Cho7a428ba2017-01-12 16:28:49 -0800601
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200602#if CONFIG_HIGHBITDEPTH
Thomas Daede6ff6af62017-02-03 16:29:24 -0800603 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
Yushin Cho1c602b32017-06-07 17:57:14 -0700604 for (j = 0; j < txh; j++)
605 for (i = 0; i < txw; i++)
Thomas Daede6ff6af62017-02-03 16:29:24 -0800606 src_int16[diff_stride * j + i] =
607 CONVERT_TO_SHORTPTR(src)[src_stride * j + i];
608 } else {
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200609#endif // CONFIG_HIGHBITDEPTH
Yushin Cho1c602b32017-06-07 17:57:14 -0700610 for (j = 0; j < txh; j++)
611 for (i = 0; i < txw; i++)
Thomas Daede6ff6af62017-02-03 16:29:24 -0800612 src_int16[diff_stride * j + i] = src[src_stride * j + i];
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200613#if CONFIG_HIGHBITDEPTH
Thomas Daede6ff6af62017-02-03 16:29:24 -0800614 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200615#endif // CONFIG_HIGHBITDEPTH
Yushin Cho7a428ba2017-01-12 16:28:49 -0800616#endif
617
618#if CONFIG_PVQ || CONFIG_DAALA_DIST
619 dst = &pd->dst.buf[(blk_row * dst_stride + blk_col) << tx_size_wide_log2[0]];
Jingning Han81492262016-12-05 15:48:47 -0800620 pred = &pd->pred[(blk_row * diff_stride + blk_col) << tx_size_wide_log2[0]];
Yushin Cho77bba8d2016-11-04 16:36:56 -0700621
Thomas Daede6ff6af62017-02-03 16:29:24 -0800622// copy uint8 orig and predicted block to int16 buffer
623// in order to use existing VP10 transform functions
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200624#if CONFIG_HIGHBITDEPTH
Thomas Daede6ff6af62017-02-03 16:29:24 -0800625 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
Yushin Cho1c602b32017-06-07 17:57:14 -0700626 for (j = 0; j < txh; j++)
627 for (i = 0; i < txw; i++)
Thomas Daede6ff6af62017-02-03 16:29:24 -0800628 pred[diff_stride * j + i] =
629 CONVERT_TO_SHORTPTR(dst)[dst_stride * j + i];
630 } else {
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200631#endif // CONFIG_HIGHBITDEPTH
Yushin Cho1c602b32017-06-07 17:57:14 -0700632 for (j = 0; j < txh; j++)
633 for (i = 0; i < txw; i++)
Thomas Daede6ff6af62017-02-03 16:29:24 -0800634 pred[diff_stride * j + i] = dst[dst_stride * j + i];
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200635#if CONFIG_HIGHBITDEPTH
Thomas Daede6ff6af62017-02-03 16:29:24 -0800636 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200637#endif // CONFIG_HIGHBITDEPTH
Yushin Cho77bba8d2016-11-04 16:36:56 -0700638#endif
Yushin Cho7a428ba2017-01-12 16:28:49 -0800639
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800640 (void)ctx;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700641
642 fwd_txfm_param.tx_type = tx_type;
643 fwd_txfm_param.tx_size = tx_size;
Luc Trudeaub6e94d92017-03-13 15:46:15 -0400644 fwd_txfm_param.lossless = xd->lossless[mbmi->segment_id];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700645
Thomas Daede6ff6af62017-02-03 16:29:24 -0800646#if !CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -0700647 fwd_txfm_param.bd = xd->bd;
Yi Luo0f4195c2017-06-27 16:07:28 -0700648 const int is_hbd = get_bitdepth_data_path_index(xd);
649 fwd_txfm_func[is_hbd](src_diff, coeff, diff_stride, &fwd_txfm_param);
650
Yaowu Xuf883b422016-08-30 14:01:10 -0700651 if (xform_quant_idx != AV1_XFORM_QUANT_SKIP_QUANT) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700652 if (LIKELY(!x->skip_block)) {
Yi Luo0f4195c2017-06-27 16:07:28 -0700653 quant_func_list[xform_quant_idx][is_hbd](
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800654 coeff, tx2d_size, p, qcoeff, pd, dqcoeff, eob, scan_order, &qparam);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700655 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -0700656 av1_quantize_skip(tx2d_size, qcoeff, dqcoeff, eob);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700657 }
658 }
Angie Chiang74e23072017-03-24 14:54:23 -0700659#if CONFIG_LV_MAP
660 p->txb_entropy_ctx[block] =
661 (uint8_t)av1_get_txb_entropy_context(qcoeff, scan_order, *eob);
662#endif // CONFIG_LV_MAP
Yi Luo0f4195c2017-06-27 16:07:28 -0700663 return;
664#else // CONFIG_PVQ
Angie Chiang2cc057c2017-01-03 18:31:47 -0800665 (void)xform_quant_idx;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200666#if CONFIG_HIGHBITDEPTH
Thomas Daede6ff6af62017-02-03 16:29:24 -0800667 fwd_txfm_param.bd = xd->bd;
668 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
hui suf11fb882017-03-27 14:56:33 -0700669 av1_highbd_fwd_txfm(src_int16, coeff, diff_stride, &fwd_txfm_param);
670 av1_highbd_fwd_txfm(pred, ref_coeff, diff_stride, &fwd_txfm_param);
Thomas Daede6ff6af62017-02-03 16:29:24 -0800671 } else {
672#endif
hui suf11fb882017-03-27 14:56:33 -0700673 av1_fwd_txfm(src_int16, coeff, diff_stride, &fwd_txfm_param);
674 av1_fwd_txfm(pred, ref_coeff, diff_stride, &fwd_txfm_param);
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200675#if CONFIG_HIGHBITDEPTH
Thomas Daede6ff6af62017-02-03 16:29:24 -0800676 }
677#endif
Yushin Cho77bba8d2016-11-04 16:36:56 -0700678
679 // PVQ for inter mode block
ltrudeau472f63f2017-01-12 15:22:32 -0500680 if (!x->skip_block) {
ltrudeaue1c09292017-01-20 15:42:13 -0500681 PVQ_SKIP_TYPE ac_dc_coded =
Thomas Daede6ff6af62017-02-03 16:29:24 -0800682 av1_pvq_encode_helper(x,
ltrudeaue1c09292017-01-20 15:42:13 -0500683 coeff, // target original vector
684 ref_coeff, // reference vector
685 dqcoeff, // de-quantized vector
686 eob, // End of Block marker
687 pd->dequant, // aom's quantizers
688 plane, // image plane
689 tx_size, // block size in log_2 - 2
690 tx_type,
691 &x->rate, // rate measured
692 x->pvq_speed,
693 pvq_info); // PVQ info for a block
694 skip = ac_dc_coded == PVQ_SKIP;
ltrudeau472f63f2017-01-12 15:22:32 -0500695 }
Yushin Cho77bba8d2016-11-04 16:36:56 -0700696 x->pvq_skip[plane] = skip;
697
698 if (!skip) mbmi->skip = 0;
699#endif // #if !CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -0700700}
701
Yaowu Xuc27fc142016-08-22 16:08:15 -0700702static void encode_block(int plane, int block, int blk_row, int blk_col,
703 BLOCK_SIZE plane_bsize, TX_SIZE tx_size, void *arg) {
704 struct encode_b_args *const args = arg;
Angie Chiangff6d8902016-10-21 11:02:09 -0700705 AV1_COMMON *cm = args->cm;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700706 MACROBLOCK *const x = args->x;
707 MACROBLOCKD *const xd = &x->e_mbd;
708 int ctx;
709 struct macroblock_plane *const p = &x->plane[plane];
710 struct macroblockd_plane *const pd = &xd->plane[plane];
711 tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
712 uint8_t *dst;
Yushin Cho6341f5c2017-03-24 14:36:28 -0700713#if !CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -0700714 ENTROPY_CONTEXT *a, *l;
Yushin Cho6341f5c2017-03-24 14:36:28 -0700715#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -0700716#if CONFIG_VAR_TX
Jingning Han9ca05b72017-01-03 14:41:36 -0800717 int bw = block_size_wide[plane_bsize] >> tx_size_wide_log2[0];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700718#endif
Jingning Han81492262016-12-05 15:48:47 -0800719 dst = &pd->dst
720 .buf[(blk_row * pd->dst.stride + blk_col) << tx_size_wide_log2[0]];
Yushin Cho6341f5c2017-03-24 14:36:28 -0700721
722#if !CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -0700723 a = &args->ta[blk_col];
724 l = &args->tl[blk_row];
725#if CONFIG_VAR_TX
726 ctx = get_entropy_context(tx_size, a, l);
727#else
728 ctx = combine_entropy_contexts(*a, *l);
729#endif
Yushin Cho6341f5c2017-03-24 14:36:28 -0700730#else
731 ctx = 0;
732#endif // CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -0700733
734#if CONFIG_VAR_TX
Yue Chena1e48dc2016-08-29 17:29:33 -0700735 // Assert not magic number (uninitialized).
Jingning Han9ca05b72017-01-03 14:41:36 -0800736 assert(x->blk_skip[plane][blk_row * bw + blk_col] != 234);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700737
Jingning Han9ca05b72017-01-03 14:41:36 -0800738 if (x->blk_skip[plane][blk_row * bw + blk_col] == 0) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700739#else
740 {
741#endif
Angie Chiangff6d8902016-10-21 11:02:09 -0700742 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800743 ctx, AV1_XFORM_QUANT_FP);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700744 }
745#if CONFIG_VAR_TX
746 else {
747 p->eobs[block] = 0;
748 }
749#endif
Yushin Cho6341f5c2017-03-24 14:36:28 -0700750
Yushin Cho77bba8d2016-11-04 16:36:56 -0700751#if !CONFIG_PVQ
Angie Chiang3511c372017-05-31 12:47:07 -0700752 av1_optimize_b(cm, x, plane, block, plane_bsize, tx_size, a, l);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700753
Angie Chiangdb0c7d42017-03-23 16:05:37 -0700754 av1_set_txb_context(x, plane, block, tx_size, a, l);
755
Yaowu Xuc27fc142016-08-22 16:08:15 -0700756 if (p->eobs[block]) *(args->skip) = 0;
757
758 if (p->eobs[block] == 0) return;
Yushin Cho77bba8d2016-11-04 16:36:56 -0700759#else
760 (void)ctx;
Yushin Cho77bba8d2016-11-04 16:36:56 -0700761 if (!x->pvq_skip[plane]) *(args->skip) = 0;
762
763 if (x->pvq_skip[plane]) return;
Yushin Cho77bba8d2016-11-04 16:36:56 -0700764#endif
Angie Chiang752ccce2017-04-09 13:41:13 -0700765 TX_TYPE tx_type = get_tx_type(pd->plane_type, xd, block, tx_size);
Angie Chiang44d7e662017-04-06 11:07:53 -0700766 av1_inverse_transform_block(xd, dqcoeff, tx_type, tx_size, dst,
767 pd->dst.stride, p->eobs[block]);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700768}
769
770#if CONFIG_VAR_TX
771static void encode_block_inter(int plane, int block, int blk_row, int blk_col,
772 BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
773 void *arg) {
774 struct encode_b_args *const args = arg;
775 MACROBLOCK *const x = args->x;
776 MACROBLOCKD *const xd = &x->e_mbd;
777 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
778 const BLOCK_SIZE bsize = txsize_to_bsize[tx_size];
779 const struct macroblockd_plane *const pd = &xd->plane[plane];
780 const int tx_row = blk_row >> (1 - pd->subsampling_y);
781 const int tx_col = blk_col >> (1 - pd->subsampling_x);
782 TX_SIZE plane_tx_size;
Jingning Hanf65b8702016-10-31 12:13:20 -0700783 const int max_blocks_high = max_block_high(xd, plane_bsize, plane);
784 const int max_blocks_wide = max_block_wide(xd, plane_bsize, plane);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700785
786 if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
787
Debargha Mukherjee2f123402016-08-30 17:43:38 -0700788 plane_tx_size =
789 plane ? uv_txsize_lookup[bsize][mbmi->inter_tx_size[tx_row][tx_col]][0][0]
790 : mbmi->inter_tx_size[tx_row][tx_col];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700791
792 if (tx_size == plane_tx_size) {
793 encode_block(plane, block, blk_row, blk_col, plane_bsize, tx_size, arg);
794 } else {
Alex Conversee16b2662017-05-24 14:00:00 -0700795 assert(tx_size < TX_SIZES_ALL);
Jingning Hana9336322016-11-02 15:45:07 -0700796 const TX_SIZE sub_txs = sub_tx_size_map[tx_size];
Alex Conversee16b2662017-05-24 14:00:00 -0700797 assert(sub_txs < tx_size);
Jingning Hana9336322016-11-02 15:45:07 -0700798 // This is the square transform block partition entry point.
799 int bsl = tx_size_wide_unit[sub_txs];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700800 int i;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700801 assert(bsl > 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700802
803 for (i = 0; i < 4; ++i) {
Jingning Hande953b92016-10-25 12:35:43 -0700804 const int offsetr = blk_row + ((i >> 1) * bsl);
805 const int offsetc = blk_col + ((i & 0x01) * bsl);
Jingning Hande953b92016-10-25 12:35:43 -0700806 int step = tx_size_wide_unit[sub_txs] * tx_size_high_unit[sub_txs];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700807
808 if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide) continue;
809
Jingning Han98d6a1f2016-11-03 12:47:47 -0700810 encode_block_inter(plane, block, offsetr, offsetc, plane_bsize, sub_txs,
811 arg);
812 block += step;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700813 }
814 }
815}
816#endif
817
Angie Chiangff6d8902016-10-21 11:02:09 -0700818typedef struct encode_block_pass1_args {
819 AV1_COMMON *cm;
820 MACROBLOCK *x;
821} encode_block_pass1_args;
822
Yaowu Xuc27fc142016-08-22 16:08:15 -0700823static void encode_block_pass1(int plane, int block, int blk_row, int blk_col,
824 BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
825 void *arg) {
Angie Chiangff6d8902016-10-21 11:02:09 -0700826 encode_block_pass1_args *args = (encode_block_pass1_args *)arg;
827 AV1_COMMON *cm = args->cm;
828 MACROBLOCK *const x = args->x;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700829 MACROBLOCKD *const xd = &x->e_mbd;
830 struct macroblock_plane *const p = &x->plane[plane];
831 struct macroblockd_plane *const pd = &xd->plane[plane];
832 tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
833 uint8_t *dst;
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800834 int ctx = 0;
Jingning Han81492262016-12-05 15:48:47 -0800835 dst = &pd->dst
836 .buf[(blk_row * pd->dst.stride + blk_col) << tx_size_wide_log2[0]];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700837
Angie Chiangff6d8902016-10-21 11:02:09 -0700838 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800839 ctx, AV1_XFORM_QUANT_B);
Yushin Cho77bba8d2016-11-04 16:36:56 -0700840#if !CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -0700841 if (p->eobs[block] > 0) {
Yushin Cho77bba8d2016-11-04 16:36:56 -0700842#else
843 if (!x->pvq_skip[plane]) {
Yushin Cho77bba8d2016-11-04 16:36:56 -0700844 {
845 int tx_blk_size;
846 int i, j;
847 // transform block size in pixels
848 tx_blk_size = tx_size_wide[tx_size];
849
Thomas Daede6ff6af62017-02-03 16:29:24 -0800850// Since av1 does not have separate function which does inverse transform
851// but av1_inv_txfm_add_*x*() also does addition of predicted image to
852// inverse transformed image,
853// pass blank dummy image to av1_inv_txfm_add_*x*(), i.e. set dst as zeros
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200854#if CONFIG_HIGHBITDEPTH
Thomas Daede6ff6af62017-02-03 16:29:24 -0800855 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
856 for (j = 0; j < tx_blk_size; j++)
857 for (i = 0; i < tx_blk_size; i++)
858 CONVERT_TO_SHORTPTR(dst)[j * pd->dst.stride + i] = 0;
859 } else {
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200860#endif // CONFIG_HIGHBITDEPTH
Thomas Daede6ff6af62017-02-03 16:29:24 -0800861 for (j = 0; j < tx_blk_size; j++)
862 for (i = 0; i < tx_blk_size; i++) dst[j * pd->dst.stride + i] = 0;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200863#if CONFIG_HIGHBITDEPTH
Thomas Daede6ff6af62017-02-03 16:29:24 -0800864 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200865#endif // CONFIG_HIGHBITDEPTH
Yushin Cho77bba8d2016-11-04 16:36:56 -0700866 }
Jingning Handf072642016-11-08 16:43:38 -0800867#endif // !CONFIG_PVQ
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200868#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700869 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
Frederic Barbier05b45e62017-06-26 09:57:40 +0200870 av1_highbd_inv_txfm_add_4x4(dqcoeff, dst, pd->dst.stride, p->eobs[block],
871 xd->bd, DCT_DCT,
872 xd->lossless[xd->mi[0]->mbmi.segment_id]);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700873 return;
874 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200875#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700876 if (xd->lossless[xd->mi[0]->mbmi.segment_id]) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700877 av1_iwht4x4_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700878 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -0700879 av1_idct4x4_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700880 }
881 }
882}
883
Angie Chiangff6d8902016-10-21 11:02:09 -0700884void av1_encode_sby_pass1(AV1_COMMON *cm, MACROBLOCK *x, BLOCK_SIZE bsize) {
885 encode_block_pass1_args args = { cm, x };
Yaowu Xuf883b422016-08-30 14:01:10 -0700886 av1_subtract_plane(x, bsize, 0);
887 av1_foreach_transformed_block_in_plane(&x->e_mbd, bsize, 0,
Angie Chiangff6d8902016-10-21 11:02:09 -0700888 encode_block_pass1, &args);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700889}
890
Yaowu Xu1e4e5b92017-05-05 11:06:42 -0700891void av1_encode_sb(AV1_COMMON *cm, MACROBLOCK *x, BLOCK_SIZE bsize, int mi_row,
892 int mi_col) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700893 MACROBLOCKD *const xd = &x->e_mbd;
894 struct optimize_ctx ctx;
895 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Angie Chiangff6d8902016-10-21 11:02:09 -0700896 struct encode_b_args arg = { cm, x, &ctx, &mbmi->skip, NULL, NULL, 1 };
Yaowu Xuc27fc142016-08-22 16:08:15 -0700897 int plane;
898
899 mbmi->skip = 1;
900
901 if (x->skip) return;
902
903 for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
Jingning Han31b6a4f2017-02-23 11:05:53 -0800904#if CONFIG_CB4X4 && !CONFIG_CHROMA_2X2
Jingning Han2d2dac22017-04-11 09:41:10 -0700905 const int subsampling_x = xd->plane[plane].subsampling_x;
906 const int subsampling_y = xd->plane[plane].subsampling_y;
907
908 if (!is_chroma_reference(mi_row, mi_col, bsize, subsampling_x,
909 subsampling_y))
Jingning Hanea576f32017-02-21 23:05:09 -0800910 continue;
Jingning Han2d2dac22017-04-11 09:41:10 -0700911
912 bsize = scale_chroma_bsize(bsize, subsampling_x, subsampling_y);
Jingning Hanea576f32017-02-21 23:05:09 -0800913#else
914 (void)mi_row;
915 (void)mi_col;
916#endif
917
Yaowu Xuc27fc142016-08-22 16:08:15 -0700918#if CONFIG_VAR_TX
919 // TODO(jingning): Clean this up.
920 const struct macroblockd_plane *const pd = &xd->plane[plane];
921 const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
Jingning Hande953b92016-10-25 12:35:43 -0700922 const int mi_width = block_size_wide[plane_bsize] >> tx_size_wide_log2[0];
923 const int mi_height = block_size_high[plane_bsize] >> tx_size_wide_log2[0];
Sarah Parker106b3cb2017-04-21 12:13:37 -0700924 const TX_SIZE max_tx_size = get_vartx_max_txsize(mbmi, plane_bsize);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700925 const BLOCK_SIZE txb_size = txsize_to_bsize[max_tx_size];
Jingning Hande953b92016-10-25 12:35:43 -0700926 const int bw = block_size_wide[txb_size] >> tx_size_wide_log2[0];
927 const int bh = block_size_high[txb_size] >> tx_size_wide_log2[0];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700928 int idx, idy;
929 int block = 0;
Jingning Hande953b92016-10-25 12:35:43 -0700930 int step = tx_size_wide_unit[max_tx_size] * tx_size_high_unit[max_tx_size];
Jingning Han581d1692017-01-05 16:03:54 -0800931 av1_get_entropy_contexts(bsize, 0, pd, ctx.ta[plane], ctx.tl[plane]);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700932#else
933 const struct macroblockd_plane *const pd = &xd->plane[plane];
Angie Chiang7fcfee42017-02-24 15:51:03 -0800934 const TX_SIZE tx_size = get_tx_size(plane, xd);
Yaowu Xuf883b422016-08-30 14:01:10 -0700935 av1_get_entropy_contexts(bsize, tx_size, pd, ctx.ta[plane], ctx.tl[plane]);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700936#endif
Jingning Hanea576f32017-02-21 23:05:09 -0800937
Yushin Cho77bba8d2016-11-04 16:36:56 -0700938#if !CONFIG_PVQ
Yaowu Xuf883b422016-08-30 14:01:10 -0700939 av1_subtract_plane(x, bsize, plane);
Yushin Cho77bba8d2016-11-04 16:36:56 -0700940#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -0700941 arg.ta = ctx.ta[plane];
942 arg.tl = ctx.tl[plane];
943
944#if CONFIG_VAR_TX
Jingning Hanfe45b212016-11-22 10:30:23 -0800945 for (idy = 0; idy < mi_height; idy += bh) {
946 for (idx = 0; idx < mi_width; idx += bw) {
947 encode_block_inter(plane, block, idy, idx, plane_bsize, max_tx_size,
948 &arg);
949 block += step;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700950 }
Yaowu Xuc27fc142016-08-22 16:08:15 -0700951 }
Yaowu Xuc27fc142016-08-22 16:08:15 -0700952#else
Yaowu Xuf883b422016-08-30 14:01:10 -0700953 av1_foreach_transformed_block_in_plane(xd, bsize, plane, encode_block,
954 &arg);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700955#endif
956 }
957}
958
959#if CONFIG_SUPERTX
Angie Chiangff6d8902016-10-21 11:02:09 -0700960void av1_encode_sb_supertx(AV1_COMMON *cm, MACROBLOCK *x, BLOCK_SIZE bsize) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700961 MACROBLOCKD *const xd = &x->e_mbd;
962 struct optimize_ctx ctx;
963 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Angie Chiangff6d8902016-10-21 11:02:09 -0700964 struct encode_b_args arg = { cm, x, &ctx, &mbmi->skip, NULL, NULL, 1 };
Yaowu Xuc27fc142016-08-22 16:08:15 -0700965 int plane;
966
967 mbmi->skip = 1;
968 if (x->skip) return;
969
970 for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
971 const struct macroblockd_plane *const pd = &xd->plane[plane];
972#if CONFIG_VAR_TX
973 const TX_SIZE tx_size = TX_4X4;
974#else
Angie Chiang7fcfee42017-02-24 15:51:03 -0800975 const TX_SIZE tx_size = get_tx_size(plane, xd);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700976#endif
Yaowu Xuf883b422016-08-30 14:01:10 -0700977 av1_subtract_plane(x, bsize, plane);
978 av1_get_entropy_contexts(bsize, tx_size, pd, ctx.ta[plane], ctx.tl[plane]);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700979 arg.ta = ctx.ta[plane];
980 arg.tl = ctx.tl[plane];
Yaowu Xuf883b422016-08-30 14:01:10 -0700981 av1_foreach_transformed_block_in_plane(xd, bsize, plane, encode_block,
982 &arg);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700983 }
984}
985#endif // CONFIG_SUPERTX
986
Yushin Cho6341f5c2017-03-24 14:36:28 -0700987#if !CONFIG_PVQ
Angie Chiangdb0c7d42017-03-23 16:05:37 -0700988void av1_set_txb_context(MACROBLOCK *x, int plane, int block, TX_SIZE tx_size,
Angie Chiang36aca332017-03-23 14:16:24 -0700989 ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l) {
Angie Chiang36aca332017-03-23 14:16:24 -0700990 (void)tx_size;
Angie Chiang36aca332017-03-23 14:16:24 -0700991 struct macroblock_plane *p = &x->plane[plane];
Yushin Cho6341f5c2017-03-24 14:36:28 -0700992
Angie Chiang74e23072017-03-24 14:54:23 -0700993#if !CONFIG_LV_MAP
Angie Chiang36aca332017-03-23 14:16:24 -0700994 *a = *l = p->eobs[block] > 0;
Angie Chiang74e23072017-03-24 14:54:23 -0700995#else // !CONFIG_LV_MAP
996 *a = *l = p->txb_entropy_ctx[block];
997#endif // !CONFIG_LV_MAP
Angie Chiangdb0c7d42017-03-23 16:05:37 -0700998
999#if CONFIG_VAR_TX || CONFIG_LV_MAP
1000 int i;
1001 for (i = 0; i < tx_size_wide_unit[tx_size]; ++i) a[i] = a[0];
1002
1003 for (i = 0; i < tx_size_high_unit[tx_size]; ++i) l[i] = l[0];
1004#endif
Angie Chiang36aca332017-03-23 14:16:24 -07001005}
Yushin Cho6341f5c2017-03-24 14:36:28 -07001006#endif
Angie Chiang36aca332017-03-23 14:16:24 -07001007
1008static void encode_block_intra_and_set_context(int plane, int block,
1009 int blk_row, int blk_col,
1010 BLOCK_SIZE plane_bsize,
1011 TX_SIZE tx_size, void *arg) {
1012 av1_encode_block_intra(plane, block, blk_row, blk_col, plane_bsize, tx_size,
1013 arg);
Yushin Cho6341f5c2017-03-24 14:36:28 -07001014#if !CONFIG_PVQ
Angie Chiang36aca332017-03-23 14:16:24 -07001015 struct encode_b_args *const args = arg;
1016 MACROBLOCK *x = args->x;
1017 ENTROPY_CONTEXT *a = &args->ta[blk_col];
1018 ENTROPY_CONTEXT *l = &args->tl[blk_row];
Angie Chiangdb0c7d42017-03-23 16:05:37 -07001019 av1_set_txb_context(x, plane, block, tx_size, a, l);
Yushin Cho6341f5c2017-03-24 14:36:28 -07001020#endif
Angie Chiang36aca332017-03-23 14:16:24 -07001021}
1022
hui sub8a6fd62017-05-10 10:57:57 -07001023#if CONFIG_DPCM_INTRA
1024static int get_eob(const tran_low_t *qcoeff, intptr_t n_coeffs,
1025 const int16_t *scan) {
1026 int eob = -1;
1027 for (int i = (int)n_coeffs - 1; i >= 0; i--) {
1028 const int rc = scan[i];
1029 if (qcoeff[rc]) {
1030 eob = i;
1031 break;
1032 }
1033 }
1034 return eob + 1;
1035}
1036
1037static void quantize_scaler(int coeff, int16_t zbin, int16_t round_value,
1038 int16_t quant, int16_t quant_shift, int16_t dequant,
1039 int log_scale, tran_low_t *const qcoeff,
1040 tran_low_t *const dqcoeff) {
1041 zbin = ROUND_POWER_OF_TWO(zbin, log_scale);
1042 round_value = ROUND_POWER_OF_TWO(round_value, log_scale);
1043 const int coeff_sign = (coeff >> 31);
1044 const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
1045 if (abs_coeff >= zbin) {
1046 int tmp = clamp(abs_coeff + round_value, INT16_MIN, INT16_MAX);
1047 tmp = ((((tmp * quant) >> 16) + tmp) * quant_shift) >> (16 - log_scale);
1048 *qcoeff = (tmp ^ coeff_sign) - coeff_sign;
1049 *dqcoeff = (*qcoeff * dequant) / (1 << log_scale);
1050 }
1051}
1052
Sarah Parker31c66502017-05-19 16:51:07 -07001053#if CONFIG_HIGHBITDEPTH
1054typedef void (*hbd_dpcm_fwd_tx_func)(const int16_t *input, int stride,
1055 TX_TYPE_1D tx_type, tran_low_t *output,
1056 int dir);
1057
1058static hbd_dpcm_fwd_tx_func get_hbd_dpcm_fwd_tx_func(int tx_length) {
1059 switch (tx_length) {
1060 case 4: return av1_hbd_dpcm_ft4_c;
1061 case 8: return av1_hbd_dpcm_ft8_c;
1062 case 16: return av1_hbd_dpcm_ft16_c;
1063 case 32:
1064 return av1_hbd_dpcm_ft32_c;
1065 // TODO(huisu): add support for TX_64X64.
1066 default: assert(0); return NULL;
1067 }
1068}
1069#endif // CONFIG_HIGHBITDEPTH
1070
hui sub8a6fd62017-05-10 10:57:57 -07001071typedef void (*dpcm_fwd_tx_func)(const int16_t *input, int stride,
1072 TX_TYPE_1D tx_type, tran_low_t *output);
1073
1074static dpcm_fwd_tx_func get_dpcm_fwd_tx_func(int tx_length) {
1075 switch (tx_length) {
1076 case 4: return av1_dpcm_ft4_c;
1077 case 8: return av1_dpcm_ft8_c;
1078 case 16: return av1_dpcm_ft16_c;
1079 case 32:
1080 return av1_dpcm_ft32_c;
1081 // TODO(huisu): add support for TX_64X64.
1082 default: assert(0); return NULL;
1083 }
1084}
1085
1086static void process_block_dpcm_vert(TX_SIZE tx_size, TX_TYPE_1D tx_type_1d,
1087 struct macroblockd_plane *const pd,
1088 struct macroblock_plane *const p,
1089 uint8_t *src, int src_stride, uint8_t *dst,
1090 int dst_stride, int16_t *src_diff,
1091 int diff_stride, tran_low_t *coeff,
1092 tran_low_t *qcoeff, tran_low_t *dqcoeff) {
1093 const int tx1d_width = tx_size_wide[tx_size];
1094 dpcm_fwd_tx_func forward_tx = get_dpcm_fwd_tx_func(tx1d_width);
1095 dpcm_inv_txfm_add_func inverse_tx =
1096 av1_get_dpcm_inv_txfm_add_func(tx1d_width);
1097 const int tx1d_height = tx_size_high[tx_size];
1098 const int log_scale = av1_get_tx_scale(tx_size);
1099 int q_idx = 0;
1100 for (int r = 0; r < tx1d_height; ++r) {
1101 // Update prediction.
1102 if (r > 0) memcpy(dst, dst - dst_stride, tx1d_width * sizeof(dst[0]));
1103 // Subtraction.
1104 for (int c = 0; c < tx1d_width; ++c) src_diff[c] = src[c] - dst[c];
1105 // Forward transform.
1106 forward_tx(src_diff, 1, tx_type_1d, coeff);
1107 // Quantization.
1108 for (int c = 0; c < tx1d_width; ++c) {
1109 quantize_scaler(coeff[c], p->zbin[q_idx], p->round[q_idx],
1110 p->quant[q_idx], p->quant_shift[q_idx],
1111 pd->dequant[q_idx], log_scale, &qcoeff[c], &dqcoeff[c]);
1112 q_idx = 1;
1113 }
1114 // Inverse transform.
1115 inverse_tx(dqcoeff, 1, tx_type_1d, dst);
1116 // Move to the next row.
1117 coeff += tx1d_width;
1118 qcoeff += tx1d_width;
1119 dqcoeff += tx1d_width;
1120 src_diff += diff_stride;
1121 dst += dst_stride;
1122 src += src_stride;
1123 }
1124}
1125
1126static void process_block_dpcm_horz(TX_SIZE tx_size, TX_TYPE_1D tx_type_1d,
1127 struct macroblockd_plane *const pd,
1128 struct macroblock_plane *const p,
1129 uint8_t *src, int src_stride, uint8_t *dst,
1130 int dst_stride, int16_t *src_diff,
1131 int diff_stride, tran_low_t *coeff,
1132 tran_low_t *qcoeff, tran_low_t *dqcoeff) {
1133 const int tx1d_height = tx_size_high[tx_size];
1134 dpcm_fwd_tx_func forward_tx = get_dpcm_fwd_tx_func(tx1d_height);
1135 dpcm_inv_txfm_add_func inverse_tx =
1136 av1_get_dpcm_inv_txfm_add_func(tx1d_height);
1137 const int tx1d_width = tx_size_wide[tx_size];
1138 const int log_scale = av1_get_tx_scale(tx_size);
1139 int q_idx = 0;
1140 for (int c = 0; c < tx1d_width; ++c) {
1141 for (int r = 0; r < tx1d_height; ++r) {
1142 // Update prediction.
1143 if (c > 0) dst[r * dst_stride] = dst[r * dst_stride - 1];
1144 // Subtraction.
1145 src_diff[r * diff_stride] = src[r * src_stride] - dst[r * dst_stride];
1146 }
1147 // Forward transform.
1148 tran_low_t tx_buff[64];
1149 forward_tx(src_diff, diff_stride, tx_type_1d, tx_buff);
1150 for (int r = 0; r < tx1d_height; ++r) coeff[r * tx1d_width] = tx_buff[r];
1151 // Quantization.
1152 for (int r = 0; r < tx1d_height; ++r) {
1153 quantize_scaler(coeff[r * tx1d_width], p->zbin[q_idx], p->round[q_idx],
1154 p->quant[q_idx], p->quant_shift[q_idx],
1155 pd->dequant[q_idx], log_scale, &qcoeff[r * tx1d_width],
1156 &dqcoeff[r * tx1d_width]);
1157 q_idx = 1;
1158 }
1159 // Inverse transform.
1160 for (int r = 0; r < tx1d_height; ++r) tx_buff[r] = dqcoeff[r * tx1d_width];
1161 inverse_tx(tx_buff, dst_stride, tx_type_1d, dst);
1162 // Move to the next column.
1163 ++coeff, ++qcoeff, ++dqcoeff, ++src_diff, ++dst, ++src;
1164 }
1165}
1166
1167#if CONFIG_HIGHBITDEPTH
1168static void hbd_process_block_dpcm_vert(
1169 TX_SIZE tx_size, TX_TYPE_1D tx_type_1d, int bd,
1170 struct macroblockd_plane *const pd, struct macroblock_plane *const p,
1171 uint8_t *src8, int src_stride, uint8_t *dst8, int dst_stride,
1172 int16_t *src_diff, int diff_stride, tran_low_t *coeff, tran_low_t *qcoeff,
1173 tran_low_t *dqcoeff) {
1174 const int tx1d_width = tx_size_wide[tx_size];
Sarah Parker31c66502017-05-19 16:51:07 -07001175 hbd_dpcm_fwd_tx_func forward_tx = get_hbd_dpcm_fwd_tx_func(tx1d_width);
hui sub8a6fd62017-05-10 10:57:57 -07001176 hbd_dpcm_inv_txfm_add_func inverse_tx =
1177 av1_get_hbd_dpcm_inv_txfm_add_func(tx1d_width);
1178 uint16_t *src = CONVERT_TO_SHORTPTR(src8);
1179 uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
1180 const int tx1d_height = tx_size_high[tx_size];
1181 const int log_scale = av1_get_tx_scale(tx_size);
1182 int q_idx = 0;
1183 for (int r = 0; r < tx1d_height; ++r) {
1184 // Update prediction.
1185 if (r > 0) memcpy(dst, dst - dst_stride, tx1d_width * sizeof(dst[0]));
1186 // Subtraction.
1187 for (int c = 0; c < tx1d_width; ++c) src_diff[c] = src[c] - dst[c];
1188 // Forward transform.
Sarah Parker31c66502017-05-19 16:51:07 -07001189 forward_tx(src_diff, 1, tx_type_1d, coeff, 1);
hui sub8a6fd62017-05-10 10:57:57 -07001190 // Quantization.
1191 for (int c = 0; c < tx1d_width; ++c) {
1192 quantize_scaler(coeff[c], p->zbin[q_idx], p->round[q_idx],
1193 p->quant[q_idx], p->quant_shift[q_idx],
1194 pd->dequant[q_idx], log_scale, &qcoeff[c], &dqcoeff[c]);
1195 q_idx = 1;
1196 }
1197 // Inverse transform.
Sarah Parker31c66502017-05-19 16:51:07 -07001198 inverse_tx(dqcoeff, 1, tx_type_1d, bd, dst, 1);
hui sub8a6fd62017-05-10 10:57:57 -07001199 // Move to the next row.
1200 coeff += tx1d_width;
1201 qcoeff += tx1d_width;
1202 dqcoeff += tx1d_width;
1203 src_diff += diff_stride;
1204 dst += dst_stride;
1205 src += src_stride;
1206 }
1207}
1208
1209static void hbd_process_block_dpcm_horz(
1210 TX_SIZE tx_size, TX_TYPE_1D tx_type_1d, int bd,
1211 struct macroblockd_plane *const pd, struct macroblock_plane *const p,
1212 uint8_t *src8, int src_stride, uint8_t *dst8, int dst_stride,
1213 int16_t *src_diff, int diff_stride, tran_low_t *coeff, tran_low_t *qcoeff,
1214 tran_low_t *dqcoeff) {
1215 const int tx1d_height = tx_size_high[tx_size];
Sarah Parker31c66502017-05-19 16:51:07 -07001216 hbd_dpcm_fwd_tx_func forward_tx = get_hbd_dpcm_fwd_tx_func(tx1d_height);
hui sub8a6fd62017-05-10 10:57:57 -07001217 hbd_dpcm_inv_txfm_add_func inverse_tx =
1218 av1_get_hbd_dpcm_inv_txfm_add_func(tx1d_height);
1219 uint16_t *src = CONVERT_TO_SHORTPTR(src8);
1220 uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
1221 const int tx1d_width = tx_size_wide[tx_size];
1222 const int log_scale = av1_get_tx_scale(tx_size);
1223 int q_idx = 0;
1224 for (int c = 0; c < tx1d_width; ++c) {
1225 for (int r = 0; r < tx1d_height; ++r) {
1226 // Update prediction.
1227 if (c > 0) dst[r * dst_stride] = dst[r * dst_stride - 1];
1228 // Subtraction.
1229 src_diff[r * diff_stride] = src[r * src_stride] - dst[r * dst_stride];
1230 }
1231 // Forward transform.
1232 tran_low_t tx_buff[64];
Sarah Parker31c66502017-05-19 16:51:07 -07001233 forward_tx(src_diff, diff_stride, tx_type_1d, tx_buff, 0);
hui sub8a6fd62017-05-10 10:57:57 -07001234 for (int r = 0; r < tx1d_height; ++r) coeff[r * tx1d_width] = tx_buff[r];
1235 // Quantization.
1236 for (int r = 0; r < tx1d_height; ++r) {
1237 quantize_scaler(coeff[r * tx1d_width], p->zbin[q_idx], p->round[q_idx],
1238 p->quant[q_idx], p->quant_shift[q_idx],
1239 pd->dequant[q_idx], log_scale, &qcoeff[r * tx1d_width],
1240 &dqcoeff[r * tx1d_width]);
1241 q_idx = 1;
1242 }
1243 // Inverse transform.
1244 for (int r = 0; r < tx1d_height; ++r) tx_buff[r] = dqcoeff[r * tx1d_width];
Sarah Parker31c66502017-05-19 16:51:07 -07001245 inverse_tx(tx_buff, dst_stride, tx_type_1d, bd, dst, 0);
hui sub8a6fd62017-05-10 10:57:57 -07001246 // Move to the next column.
1247 ++coeff, ++qcoeff, ++dqcoeff, ++src_diff, ++dst, ++src;
1248 }
1249}
1250#endif // CONFIG_HIGHBITDEPTH
1251
1252void av1_encode_block_intra_dpcm(const AV1_COMMON *cm, MACROBLOCK *x,
1253 PREDICTION_MODE mode, int plane, int block,
1254 int blk_row, int blk_col,
1255 BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
1256 TX_TYPE tx_type, ENTROPY_CONTEXT *ta,
1257 ENTROPY_CONTEXT *tl, int8_t *skip) {
1258 MACROBLOCKD *const xd = &x->e_mbd;
1259 struct macroblock_plane *const p = &x->plane[plane];
1260 struct macroblockd_plane *const pd = &xd->plane[plane];
1261 tran_low_t *dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
1262 const int diff_stride = block_size_wide[plane_bsize];
1263 const int src_stride = p->src.stride;
1264 const int dst_stride = pd->dst.stride;
1265 const int tx1d_width = tx_size_wide[tx_size];
1266 const int tx1d_height = tx_size_high[tx_size];
Angie Chiangbd99b382017-06-20 15:11:16 -07001267 const SCAN_ORDER *const scan_order =
1268 get_scan(cm, tx_size, tx_type, &xd->mi[0]->mbmi);
hui sub8a6fd62017-05-10 10:57:57 -07001269 tran_low_t *coeff = BLOCK_OFFSET(p->coeff, block);
1270 tran_low_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block);
1271 uint8_t *dst =
1272 &pd->dst.buf[(blk_row * dst_stride + blk_col) << tx_size_wide_log2[0]];
1273 uint8_t *src =
1274 &p->src.buf[(blk_row * src_stride + blk_col) << tx_size_wide_log2[0]];
1275 int16_t *src_diff =
1276 &p->src_diff[(blk_row * diff_stride + blk_col) << tx_size_wide_log2[0]];
1277 uint16_t *eob = &p->eobs[block];
1278 *eob = 0;
1279 memset(qcoeff, 0, tx1d_height * tx1d_width * sizeof(*qcoeff));
1280 memset(dqcoeff, 0, tx1d_height * tx1d_width * sizeof(*dqcoeff));
1281
1282 if (LIKELY(!x->skip_block)) {
1283 TX_TYPE_1D tx_type_1d = DCT_1D;
1284 switch (tx_type) {
1285 case IDTX: tx_type_1d = IDTX_1D; break;
1286 case V_DCT:
1287 assert(mode == H_PRED);
1288 tx_type_1d = DCT_1D;
1289 break;
1290 case H_DCT:
1291 assert(mode == V_PRED);
1292 tx_type_1d = DCT_1D;
1293 break;
1294 default: assert(0);
1295 }
1296 switch (mode) {
1297 case V_PRED:
1298#if CONFIG_HIGHBITDEPTH
1299 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
1300 hbd_process_block_dpcm_vert(tx_size, tx_type_1d, xd->bd, pd, p, src,
1301 src_stride, dst, dst_stride, src_diff,
1302 diff_stride, coeff, qcoeff, dqcoeff);
1303 } else {
1304#endif // CONFIG_HIGHBITDEPTH
1305 process_block_dpcm_vert(tx_size, tx_type_1d, pd, p, src, src_stride,
1306 dst, dst_stride, src_diff, diff_stride, coeff,
1307 qcoeff, dqcoeff);
1308#if CONFIG_HIGHBITDEPTH
1309 }
1310#endif // CONFIG_HIGHBITDEPTH
1311 break;
1312 case H_PRED:
1313#if CONFIG_HIGHBITDEPTH
1314 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
1315 hbd_process_block_dpcm_horz(tx_size, tx_type_1d, xd->bd, pd, p, src,
1316 src_stride, dst, dst_stride, src_diff,
1317 diff_stride, coeff, qcoeff, dqcoeff);
1318 } else {
1319#endif // CONFIG_HIGHBITDEPTH
1320 process_block_dpcm_horz(tx_size, tx_type_1d, pd, p, src, src_stride,
1321 dst, dst_stride, src_diff, diff_stride, coeff,
1322 qcoeff, dqcoeff);
1323#if CONFIG_HIGHBITDEPTH
1324 }
1325#endif // CONFIG_HIGHBITDEPTH
1326 break;
1327 default: assert(0);
1328 }
1329 *eob = get_eob(qcoeff, tx1d_height * tx1d_width, scan_order->scan);
1330 }
1331
1332 ta[blk_col] = tl[blk_row] = *eob > 0;
1333 if (*eob) *skip = 0;
1334}
1335#endif // CONFIG_DPCM_INTRA
1336
Yaowu Xuf883b422016-08-30 14:01:10 -07001337void av1_encode_block_intra(int plane, int block, int blk_row, int blk_col,
1338 BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
1339 void *arg) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07001340 struct encode_b_args *const args = arg;
Angie Chiangff6d8902016-10-21 11:02:09 -07001341 AV1_COMMON *cm = args->cm;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001342 MACROBLOCK *const x = args->x;
1343 MACROBLOCKD *const xd = &x->e_mbd;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001344 struct macroblock_plane *const p = &x->plane[plane];
1345 struct macroblockd_plane *const pd = &xd->plane[plane];
1346 tran_low_t *dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
Luc Trudeau005feb62017-02-22 13:34:01 -05001347 PLANE_TYPE plane_type = get_plane_type(plane);
Angie Chiang752ccce2017-04-09 13:41:13 -07001348 const TX_TYPE tx_type = get_tx_type(plane_type, xd, block, tx_size);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001349 uint16_t *eob = &p->eobs[block];
Yaowu Xuc27fc142016-08-22 16:08:15 -07001350 const int dst_stride = pd->dst.stride;
Angie Chiangf87e43f2017-04-02 16:51:19 -07001351 uint8_t *dst =
1352 &pd->dst.buf[(blk_row * dst_stride + blk_col) << tx_size_wide_log2[0]];
Luc Trudeauf5334002017-04-25 12:21:26 -04001353#if CONFIG_CFL
Luc Trudeaue8dfbcf2017-05-12 09:57:50 -04001354
1355#if CONFIG_EC_ADAPT
1356 FRAME_CONTEXT *const ec_ctx = xd->tile_ctx;
1357#else
1358 FRAME_CONTEXT *const ec_ctx = cm->fc;
1359#endif // CONFIG_EC_ADAPT
1360
Luc Trudeau3dc55e02017-06-22 14:03:47 -04001361#if CONFIG_DEBUG
1362 const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
1363// av1_predict_intra_block_facade does not pass plane_bsize, we need to validate
1364// that we will get the same value of plane_bsize on the other side.
1365#if CONFIG_CHROMA_SUB8X8
1366 const BLOCK_SIZE plane_bsize_val =
1367 AOMMAX(BLOCK_4X4, get_plane_block_size(mbmi->sb_type, &xd->plane[plane]));
1368#else
1369 const BLOCK_SIZE plane_bsize_val =
1370 get_plane_block_size(mbmi->sb_type, &xd->plane[plane]);
1371#endif // CONFIG_CHROMA_SUB8X8
1372 assert(plane_bsize == plane_bsize_val);
1373#endif // CONFIG_DEBUG
1374
Luc Trudeaue8dfbcf2017-05-12 09:57:50 -04001375 av1_predict_intra_block_encoder_facade(x, ec_ctx, plane, block, blk_col,
Luc Trudeau3dc55e02017-06-22 14:03:47 -04001376 blk_row, tx_size);
Luc Trudeauf5334002017-04-25 12:21:26 -04001377#else
Angie Chiang752ccce2017-04-09 13:41:13 -07001378 av1_predict_intra_block_facade(xd, plane, block, blk_col, blk_row, tx_size);
Luc Trudeauf5334002017-04-25 12:21:26 -04001379#endif
hui sub8a6fd62017-05-10 10:57:57 -07001380
1381#if CONFIG_DPCM_INTRA
1382 const int block_raster_idx = av1_block_index_to_raster_order(tx_size, block);
1383 const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
1384 const PREDICTION_MODE mode =
1385 (plane == 0) ? get_y_mode(xd->mi[0], block_raster_idx) : mbmi->uv_mode;
1386 if (av1_use_dpcm_intra(plane, mode, tx_type, mbmi)) {
1387 av1_encode_block_intra_dpcm(cm, x, mode, plane, block, blk_row, blk_col,
1388 plane_bsize, tx_size, tx_type, args->ta,
1389 args->tl, args->skip);
1390 return;
1391 }
1392#endif // CONFIG_DPCM_INTRA
1393
Angie Chiangf87e43f2017-04-02 16:51:19 -07001394 av1_subtract_txb(x, plane, plane_bsize, blk_col, blk_row, tx_size);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001395
Angie Chiang36aca332017-03-23 14:16:24 -07001396 const ENTROPY_CONTEXT *a = &args->ta[blk_col];
1397 const ENTROPY_CONTEXT *l = &args->tl[blk_row];
Angie Chiang57605532017-04-03 11:51:15 -07001398 int ctx = combine_entropy_contexts(*a, *l);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001399 if (args->enable_optimize_b) {
Angie Chiangff6d8902016-10-21 11:02:09 -07001400 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
Debargha Mukherjeef0305582016-11-24 09:55:34 -08001401 ctx, AV1_XFORM_QUANT_FP);
Angie Chiang3511c372017-05-31 12:47:07 -07001402 av1_optimize_b(cm, x, plane, block, plane_bsize, tx_size, a, l);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001403 } else {
Debargha Mukherjeef0305582016-11-24 09:55:34 -08001404 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
1405 ctx, AV1_XFORM_QUANT_B);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001406 }
1407
Angie Chiang57605532017-04-03 11:51:15 -07001408#if CONFIG_PVQ
Yushin Cho3827fdd2016-11-09 15:50:23 -08001409 // *(args->skip) == mbmi->skip
1410 if (!x->pvq_skip[plane]) *(args->skip) = 0;
1411
1412 if (x->pvq_skip[plane]) return;
Angie Chiang50910f62017-04-03 12:31:34 -07001413#endif // CONFIG_PVQ
Angie Chiangd92d4bf2017-04-02 17:49:18 -07001414 av1_inverse_transform_block(xd, dqcoeff, tx_type, tx_size, dst, dst_stride,
1415 *eob);
Yushin Cho77bba8d2016-11-04 16:36:56 -07001416#if !CONFIG_PVQ
1417 if (*eob) *(args->skip) = 0;
1418#else
1419// Note : *(args->skip) == mbmi->skip
1420#endif
Luc Trudeaue3980282017-04-25 23:17:21 -04001421#if CONFIG_CFL
1422 if (plane == AOM_PLANE_Y && x->cfl_store_y) {
Luc Trudeau780d2492017-06-15 22:26:41 -04001423 // TODO (ltrudeau) Store sub-8x8 inter blocks when bottom right block is
1424 // intra predicted.
1425 cfl_store(xd->cfl, dst, dst_stride, blk_row, blk_col, tx_size, plane_bsize);
Luc Trudeaue3980282017-04-25 23:17:21 -04001426 }
1427#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07001428}
1429
Luc Trudeauf5334002017-04-25 12:21:26 -04001430#if CONFIG_CFL
Luc Trudeau3dc55e02017-06-22 14:03:47 -04001431static int cfl_alpha_dist(const uint8_t *y_pix, int y_stride,
1432 const double y_average, const uint8_t *src,
1433 int src_stride, int width, int height,
1434 TX_SIZE tx_size, double dc_pred, double alpha,
1435 int *dist_neg_out) {
David Michael Barrd3b01b82017-04-27 19:58:52 +09001436 const double dc_pred_bias = dc_pred + 0.5;
1437 int dist = 0;
1438 int diff;
Luc Trudeauf5334002017-04-25 12:21:26 -04001439
David Michael Barrd3b01b82017-04-27 19:58:52 +09001440 if (alpha == 0.0) {
1441 const int dc_pred_i = (int)dc_pred_bias;
Luc Trudeau8fb4c9e2017-06-12 16:23:16 -04001442 for (int j = 0; j < height; j++) {
1443 for (int i = 0; i < width; i++) {
David Michael Barrd3b01b82017-04-27 19:58:52 +09001444 diff = src[i] - dc_pred_i;
1445 dist += diff * diff;
1446 }
1447 src += src_stride;
1448 }
1449
1450 if (dist_neg_out) *dist_neg_out = dist;
1451
1452 return dist;
1453 }
1454
1455 int dist_neg = 0;
Luc Trudeau8fb4c9e2017-06-12 16:23:16 -04001456 const int tx_height = tx_size_high[tx_size];
1457 const int tx_width = tx_size_wide[tx_size];
Luc Trudeau3dc55e02017-06-22 14:03:47 -04001458 const int y_block_row_off = y_stride * tx_height;
1459 const int src_block_row_off = src_stride * tx_height;
Luc Trudeau8fb4c9e2017-06-12 16:23:16 -04001460 const uint8_t *t_y_pix;
1461 const uint8_t *t_src;
1462 for (int b_j = 0; b_j < height; b_j += tx_height) {
1463 const int h = b_j + tx_height;
1464 for (int b_i = 0; b_i < width; b_i += tx_width) {
1465 const int w = b_i + tx_width;
1466 t_y_pix = y_pix;
1467 t_src = src;
1468 for (int t_j = b_j; t_j < h; t_j++) {
1469 for (int t_i = b_i; t_i < w; t_i++) {
Luc Trudeau3dc55e02017-06-22 14:03:47 -04001470 const double scaled_luma = alpha * (t_y_pix[t_i] - y_average);
Luc Trudeau8fb4c9e2017-06-12 16:23:16 -04001471 const int uv = t_src[t_i];
1472 diff = uv - (int)(scaled_luma + dc_pred_bias);
1473 dist += diff * diff;
1474 diff = uv + (int)(scaled_luma - dc_pred_bias);
1475 dist_neg += diff * diff;
1476 }
1477 t_y_pix += y_stride;
1478 t_src += src_stride;
1479 }
David Michael Barrd3b01b82017-04-27 19:58:52 +09001480 }
Luc Trudeau3dc55e02017-06-22 14:03:47 -04001481 y_pix += y_block_row_off;
1482 src += src_block_row_off;
David Michael Barrd3b01b82017-04-27 19:58:52 +09001483 }
1484
1485 if (dist_neg_out) *dist_neg_out = dist_neg;
1486
1487 return dist;
1488}
1489
Luc Trudeau1a474302017-05-12 10:21:31 -04001490static inline void cfl_update_costs(CFL_CTX *cfl, FRAME_CONTEXT *ec_ctx) {
1491 assert(ec_ctx->cfl_alpha_cdf[CFL_ALPHABET_SIZE - 1] ==
1492 AOM_ICDF(CDF_PROB_TOP));
1493 const int prob_den = CDF_PROB_TOP;
1494
1495 int prob_num = AOM_ICDF(ec_ctx->cfl_alpha_cdf[0]);
1496 cfl->costs[0] = av1_cost_zero(get_prob(prob_num, prob_den));
1497
1498 for (int c = 1; c < CFL_ALPHABET_SIZE; c++) {
David Michael Barr84a44db2017-05-16 23:31:09 +09001499 int sign_bit_cost = (cfl_alpha_codes[c][CFL_PRED_U] != 0) +
1500 (cfl_alpha_codes[c][CFL_PRED_V] != 0);
Luc Trudeau1a474302017-05-12 10:21:31 -04001501 prob_num = AOM_ICDF(ec_ctx->cfl_alpha_cdf[c]) -
1502 AOM_ICDF(ec_ctx->cfl_alpha_cdf[c - 1]);
1503 cfl->costs[c] = av1_cost_zero(get_prob(prob_num, prob_den)) +
1504 av1_cost_literal(sign_bit_cost);
1505 }
1506}
1507
Luc Trudeau3dc55e02017-06-22 14:03:47 -04001508static void cfl_compute_alpha_ind(MACROBLOCK *const x, FRAME_CONTEXT *ec_ctx,
1509 TX_SIZE tx_size) {
1510 const struct macroblock_plane *const p_u = &x->plane[AOM_PLANE_U];
1511 const struct macroblock_plane *const p_v = &x->plane[AOM_PLANE_V];
1512 const uint8_t *const src_u = p_u->src.buf;
1513 const uint8_t *const src_v = p_v->src.buf;
1514 const int src_stride_u = p_u->src.stride;
1515 const int src_stride_v = p_v->src.stride;
1516
1517 MACROBLOCKD *const xd = &x->e_mbd;
1518 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
1519
1520 CFL_CTX *const cfl = xd->cfl;
1521 cfl_compute_parameters(xd, tx_size);
1522 const int width = cfl->uv_width;
1523 const int height = cfl->uv_height;
1524 const double dc_pred_u = cfl->dc_pred[CFL_PRED_U];
1525 const double dc_pred_v = cfl->dc_pred[CFL_PRED_V];
1526 const double y_average = cfl->y_average;
1527 const uint8_t *y_pix = cfl->y_down_pix;
1528
1529 CFL_SIGN_TYPE *signs = mbmi->cfl_alpha_signs;
1530
1531 cfl_update_costs(cfl, ec_ctx);
1532
1533 int sse[CFL_PRED_PLANES][CFL_MAGS_SIZE];
1534 sse[CFL_PRED_U][0] =
1535 cfl_alpha_dist(y_pix, MAX_SB_SIZE, y_average, src_u, src_stride_u, width,
1536 height, tx_size, dc_pred_u, 0, NULL);
1537 sse[CFL_PRED_V][0] =
1538 cfl_alpha_dist(y_pix, MAX_SB_SIZE, y_average, src_v, src_stride_v, width,
1539 height, tx_size, dc_pred_v, 0, NULL);
1540 for (int m = 1; m < CFL_MAGS_SIZE; m += 2) {
1541 assert(cfl_alpha_mags[m + 1] == -cfl_alpha_mags[m]);
1542 sse[CFL_PRED_U][m] = cfl_alpha_dist(
1543 y_pix, MAX_SB_SIZE, y_average, src_u, src_stride_u, width, height,
1544 tx_size, dc_pred_u, cfl_alpha_mags[m], &sse[CFL_PRED_U][m + 1]);
1545 sse[CFL_PRED_V][m] = cfl_alpha_dist(
1546 y_pix, MAX_SB_SIZE, y_average, src_v, src_stride_v, width, height,
1547 tx_size, dc_pred_v, cfl_alpha_mags[m], &sse[CFL_PRED_V][m + 1]);
1548 }
1549
1550 int dist;
1551 int64_t cost;
1552 int64_t best_cost;
1553
1554 // Compute least squares parameter of the entire block
1555 // IMPORTANT: We assume that the first code is 0,0
1556 int ind = 0;
1557 signs[CFL_PRED_U] = CFL_SIGN_POS;
1558 signs[CFL_PRED_V] = CFL_SIGN_POS;
1559
1560 dist = sse[CFL_PRED_U][0] + sse[CFL_PRED_V][0];
1561 dist *= 16;
1562 best_cost = RDCOST(x->rdmult, cfl->costs[0], dist);
1563
1564 for (int c = 1; c < CFL_ALPHABET_SIZE; c++) {
1565 const int idx_u = cfl_alpha_codes[c][CFL_PRED_U];
1566 const int idx_v = cfl_alpha_codes[c][CFL_PRED_V];
1567 for (CFL_SIGN_TYPE sign_u = idx_u == 0; sign_u < CFL_SIGNS; sign_u++) {
1568 for (CFL_SIGN_TYPE sign_v = idx_v == 0; sign_v < CFL_SIGNS; sign_v++) {
1569 dist = sse[CFL_PRED_U][idx_u + (sign_u == CFL_SIGN_NEG)] +
1570 sse[CFL_PRED_V][idx_v + (sign_v == CFL_SIGN_NEG)];
1571 dist *= 16;
1572 cost = RDCOST(x->rdmult, cfl->costs[c], dist);
1573 if (cost < best_cost) {
1574 best_cost = cost;
1575 ind = c;
1576 signs[CFL_PRED_U] = sign_u;
1577 signs[CFL_PRED_V] = sign_v;
1578 }
1579 }
1580 }
1581 }
1582
1583 mbmi->cfl_alpha_idx = ind;
1584}
1585
Luc Trudeaue8dfbcf2017-05-12 09:57:50 -04001586void av1_predict_intra_block_encoder_facade(MACROBLOCK *x,
1587 FRAME_CONTEXT *ec_ctx, int plane,
David Michael Barrd3b01b82017-04-27 19:58:52 +09001588 int block_idx, int blk_col,
Luc Trudeau3dc55e02017-06-22 14:03:47 -04001589 int blk_row, TX_SIZE tx_size) {
David Michael Barrd3b01b82017-04-27 19:58:52 +09001590 MACROBLOCKD *const xd = &x->e_mbd;
1591 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
David Michael Barrd3b01b82017-04-27 19:58:52 +09001592 if (plane != AOM_PLANE_Y && mbmi->uv_mode == DC_PRED) {
1593 if (blk_col == 0 && blk_row == 0 && plane == AOM_PLANE_U) {
Luc Trudeau3dc55e02017-06-22 14:03:47 -04001594 cfl_compute_alpha_ind(x, ec_ctx, tx_size);
David Michael Barrd3b01b82017-04-27 19:58:52 +09001595 }
1596 }
Luc Trudeauf5334002017-04-25 12:21:26 -04001597 av1_predict_intra_block_facade(xd, plane, block_idx, blk_col, blk_row,
1598 tx_size);
1599}
1600#endif
1601
Angie Chiangff6d8902016-10-21 11:02:09 -07001602void av1_encode_intra_block_plane(AV1_COMMON *cm, MACROBLOCK *x,
1603 BLOCK_SIZE bsize, int plane,
Yaowu Xu1e4e5b92017-05-05 11:06:42 -07001604 int enable_optimize_b, int mi_row,
1605 int mi_col) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07001606 const MACROBLOCKD *const xd = &x->e_mbd;
Guillaume Martrese50d9dd2016-12-18 18:26:47 +01001607 ENTROPY_CONTEXT ta[2 * MAX_MIB_SIZE] = { 0 };
1608 ENTROPY_CONTEXT tl[2 * MAX_MIB_SIZE] = { 0 };
Yaowu Xuc27fc142016-08-22 16:08:15 -07001609
Angie Chiangff6d8902016-10-21 11:02:09 -07001610 struct encode_b_args arg = {
1611 cm, x, NULL, &xd->mi[0]->mbmi.skip, ta, tl, enable_optimize_b
1612 };
Jingning Han18c53c82017-02-17 14:49:57 -08001613
1614#if CONFIG_CB4X4
Jingning Hand3a64432017-04-06 17:04:17 -07001615 if (!is_chroma_reference(mi_row, mi_col, bsize,
1616 xd->plane[plane].subsampling_x,
1617 xd->plane[plane].subsampling_y))
Jingning Han18c53c82017-02-17 14:49:57 -08001618 return;
1619#else
1620 (void)mi_row;
1621 (void)mi_col;
1622#endif
1623
Yaowu Xuc27fc142016-08-22 16:08:15 -07001624 if (enable_optimize_b) {
1625 const struct macroblockd_plane *const pd = &xd->plane[plane];
Angie Chiang7fcfee42017-02-24 15:51:03 -08001626 const TX_SIZE tx_size = get_tx_size(plane, xd);
Yaowu Xuf883b422016-08-30 14:01:10 -07001627 av1_get_entropy_contexts(bsize, tx_size, pd, ta, tl);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001628 }
Angie Chiang36aca332017-03-23 14:16:24 -07001629 av1_foreach_transformed_block_in_plane(
1630 xd, bsize, plane, encode_block_intra_and_set_context, &arg);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001631}
Yushin Cho77bba8d2016-11-04 16:36:56 -07001632
1633#if CONFIG_PVQ
Thomas Daede6ff6af62017-02-03 16:29:24 -08001634PVQ_SKIP_TYPE av1_pvq_encode_helper(MACROBLOCK *x, tran_low_t *const coeff,
1635 tran_low_t *ref_coeff,
1636 tran_low_t *const dqcoeff, uint16_t *eob,
1637 const int16_t *quant, int plane,
1638 int tx_size, TX_TYPE tx_type, int *rate,
1639 int speed, PVQ_INFO *pvq_info) {
Yushin Cho77bba8d2016-11-04 16:36:56 -07001640 const int tx_blk_size = tx_size_wide[tx_size];
Thomas Daede6ff6af62017-02-03 16:29:24 -08001641 daala_enc_ctx *daala_enc = &x->daala_enc;
ltrudeaue1c09292017-01-20 15:42:13 -05001642 PVQ_SKIP_TYPE ac_dc_coded;
Jingning Hanff705452017-04-27 11:32:15 -07001643 int coeff_shift = 3 - av1_get_tx_scale(tx_size);
Thomas Daede6ff6af62017-02-03 16:29:24 -08001644 int hbd_downshift = 0;
Timothy B. Terriberrye93acb22017-02-06 13:55:53 -08001645 int rounding_mask;
Yushin Cho70669122016-12-08 09:53:14 -10001646 int pvq_dc_quant;
1647 int use_activity_masking = daala_enc->use_activity_masking;
Yushin Cho77bba8d2016-11-04 16:36:56 -07001648 int tell;
1649 int has_dc_skip = 1;
1650 int i;
1651 int off = od_qm_offset(tx_size, plane ? 1 : 0);
Yushin Cho70669122016-12-08 09:53:14 -10001652
Thomas Daede1dbda1b2017-02-06 16:06:29 -08001653 DECLARE_ALIGNED(16, tran_low_t, coeff_pvq[OD_TXSIZE_MAX * OD_TXSIZE_MAX]);
1654 DECLARE_ALIGNED(16, tran_low_t, ref_coeff_pvq[OD_TXSIZE_MAX * OD_TXSIZE_MAX]);
1655 DECLARE_ALIGNED(16, tran_low_t, dqcoeff_pvq[OD_TXSIZE_MAX * OD_TXSIZE_MAX]);
Yushin Cho77bba8d2016-11-04 16:36:56 -07001656
Yushin Cho48f84db2016-11-07 21:20:17 -08001657 DECLARE_ALIGNED(16, int32_t, in_int32[OD_TXSIZE_MAX * OD_TXSIZE_MAX]);
1658 DECLARE_ALIGNED(16, int32_t, ref_int32[OD_TXSIZE_MAX * OD_TXSIZE_MAX]);
1659 DECLARE_ALIGNED(16, int32_t, out_int32[OD_TXSIZE_MAX * OD_TXSIZE_MAX]);
Yushin Cho77bba8d2016-11-04 16:36:56 -07001660
Thomas Daede6ff6af62017-02-03 16:29:24 -08001661 hbd_downshift = x->e_mbd.bd - 8;
Thomas Daede6ff6af62017-02-03 16:29:24 -08001662
1663 assert(OD_COEFF_SHIFT >= 4);
Yushin Cho70669122016-12-08 09:53:14 -10001664 // DC quantizer for PVQ
1665 if (use_activity_masking)
clang-format55ce9e02017-02-15 22:27:12 -08001666 pvq_dc_quant =
Thomas Daede6ff6af62017-02-03 16:29:24 -08001667 OD_MAXI(1, (quant[0] << (OD_COEFF_SHIFT - 3) >> hbd_downshift) *
clang-format55ce9e02017-02-15 22:27:12 -08001668 daala_enc->state
1669 .pvq_qm_q4[plane][od_qm_get_index(tx_size, 0)] >>
1670 4);
Yushin Cho70669122016-12-08 09:53:14 -10001671 else
Thomas Daede6ff6af62017-02-03 16:29:24 -08001672 pvq_dc_quant =
1673 OD_MAXI(1, quant[0] << (OD_COEFF_SHIFT - 3) >> hbd_downshift);
Yushin Cho70669122016-12-08 09:53:14 -10001674
Yushin Cho77bba8d2016-11-04 16:36:56 -07001675 *eob = 0;
1676
Nathan E. Egge476c63c2017-05-18 18:35:16 -04001677#if !CONFIG_ANS
Nathan E. Egge6675be02016-12-21 13:02:43 -05001678 tell = od_ec_enc_tell_frac(&daala_enc->w.ec);
1679#else
Nathan E. Egge476c63c2017-05-18 18:35:16 -04001680#error "CONFIG_PVQ currently requires !CONFIG_ANS."
Nathan E. Egge6675be02016-12-21 13:02:43 -05001681#endif
Yushin Cho77bba8d2016-11-04 16:36:56 -07001682
1683 // Change coefficient ordering for pvq encoding.
1684 od_raster_to_coding_order(coeff_pvq, tx_blk_size, tx_type, coeff,
1685 tx_blk_size);
1686 od_raster_to_coding_order(ref_coeff_pvq, tx_blk_size, tx_type, ref_coeff,
1687 tx_blk_size);
1688
1689 // copy int16 inputs to int32
1690 for (i = 0; i < tx_blk_size * tx_blk_size; i++) {
Timothy B. Terriberry4e6a8f32017-02-24 11:00:59 -08001691 ref_int32[i] =
Thomas Daede6ff6af62017-02-03 16:29:24 -08001692 AOM_SIGNED_SHL(ref_coeff_pvq[i], OD_COEFF_SHIFT - coeff_shift) >>
1693 hbd_downshift;
1694 in_int32[i] = AOM_SIGNED_SHL(coeff_pvq[i], OD_COEFF_SHIFT - coeff_shift) >>
1695 hbd_downshift;
Yushin Cho77bba8d2016-11-04 16:36:56 -07001696 }
1697
Yushin Cho77bba8d2016-11-04 16:36:56 -07001698 if (abs(in_int32[0] - ref_int32[0]) < pvq_dc_quant * 141 / 256) { /* 0.55 */
1699 out_int32[0] = 0;
1700 } else {
1701 out_int32[0] = OD_DIV_R0(in_int32[0] - ref_int32[0], pvq_dc_quant);
1702 }
1703
Thomas Daede6ff6af62017-02-03 16:29:24 -08001704 ac_dc_coded =
1705 od_pvq_encode(daala_enc, ref_int32, in_int32, out_int32,
1706 OD_MAXI(1, quant[0] << (OD_COEFF_SHIFT - 3) >>
1707 hbd_downshift), // scale/quantizer
1708 OD_MAXI(1, quant[1] << (OD_COEFF_SHIFT - 3) >>
1709 hbd_downshift), // scale/quantizer
1710 plane,
1711 tx_size, OD_PVQ_BETA[use_activity_masking][plane][tx_size],
Yushin Cho31b980a2017-03-23 10:28:09 -07001712 0, // is_keyframe,
Thomas Daede6ff6af62017-02-03 16:29:24 -08001713 daala_enc->state.qm + off, daala_enc->state.qm_inv + off,
1714 speed, // speed
1715 pvq_info);
Yushin Cho77bba8d2016-11-04 16:36:56 -07001716
1717 // Encode residue of DC coeff, if required.
1718 if (!has_dc_skip || out_int32[0]) {
Yushin Choc49ef3a2017-03-13 17:27:25 -07001719 generic_encode(&daala_enc->w, &daala_enc->state.adapt->model_dc[plane],
Timothy B. Terriberry44bb6d02017-04-07 15:44:14 -07001720 abs(out_int32[0]) - has_dc_skip,
Yushin Choc49ef3a2017-03-13 17:27:25 -07001721 &daala_enc->state.adapt->ex_dc[plane][tx_size][0], 2);
Yushin Cho77bba8d2016-11-04 16:36:56 -07001722 }
1723 if (out_int32[0]) {
Nathan E. Egge6675be02016-12-21 13:02:43 -05001724 aom_write_bit(&daala_enc->w, out_int32[0] < 0);
Yushin Cho77bba8d2016-11-04 16:36:56 -07001725 }
1726
1727 // need to save quantized residue of DC coeff
1728 // so that final pvq bitstream writing can know whether DC is coded.
1729 if (pvq_info) pvq_info->dq_dc_residue = out_int32[0];
1730
1731 out_int32[0] = out_int32[0] * pvq_dc_quant;
1732 out_int32[0] += ref_int32[0];
1733
1734 // copy int32 result back to int16
Timothy B. Terriberrye93acb22017-02-06 13:55:53 -08001735 assert(OD_COEFF_SHIFT > coeff_shift);
1736 rounding_mask = (1 << (OD_COEFF_SHIFT - coeff_shift - 1)) - 1;
1737 for (i = 0; i < tx_blk_size * tx_blk_size; i++) {
Thomas Daede6ff6af62017-02-03 16:29:24 -08001738 out_int32[i] = AOM_SIGNED_SHL(out_int32[i], hbd_downshift);
Timothy B. Terriberrye93acb22017-02-06 13:55:53 -08001739 dqcoeff_pvq[i] = (out_int32[i] + (out_int32[i] < 0) + rounding_mask) >>
1740 (OD_COEFF_SHIFT - coeff_shift);
1741 }
Yushin Cho77bba8d2016-11-04 16:36:56 -07001742
1743 // Back to original coefficient order
1744 od_coding_order_to_raster(dqcoeff, tx_blk_size, tx_type, dqcoeff_pvq,
1745 tx_blk_size);
1746
1747 *eob = tx_blk_size * tx_blk_size;
1748
Nathan E. Egge476c63c2017-05-18 18:35:16 -04001749#if !CONFIG_ANS
Nathan E. Egge6675be02016-12-21 13:02:43 -05001750 *rate = (od_ec_enc_tell_frac(&daala_enc->w.ec) - tell)
Yushin Cho77bba8d2016-11-04 16:36:56 -07001751 << (AV1_PROB_COST_SHIFT - OD_BITRES);
Nathan E. Egge6675be02016-12-21 13:02:43 -05001752#else
Nathan E. Egge476c63c2017-05-18 18:35:16 -04001753#error "CONFIG_PVQ currently requires !CONFIG_ANS."
Nathan E. Egge6675be02016-12-21 13:02:43 -05001754#endif
Yushin Cho77bba8d2016-11-04 16:36:56 -07001755 assert(*rate >= 0);
Yushin Cho5c207292017-02-16 15:01:33 -08001756
ltrudeau472f63f2017-01-12 15:22:32 -05001757 return ac_dc_coded;
Yushin Cho77bba8d2016-11-04 16:36:56 -07001758}
1759
Timothy B. Terriberry44bb6d02017-04-07 15:44:14 -07001760void av1_store_pvq_enc_info(PVQ_INFO *pvq_info, int *qg, int *theta, int *k,
1761 od_coeff *y, int nb_bands, const int *off,
1762 int *size, int skip_rest, int skip_dir,
Yushin Cho77bba8d2016-11-04 16:36:56 -07001763 int bs) { // block size in log_2 -2
1764 int i;
1765 const int tx_blk_size = tx_size_wide[bs];
1766
1767 for (i = 0; i < nb_bands; i++) {
1768 pvq_info->qg[i] = qg[i];
1769 pvq_info->theta[i] = theta[i];
Yushin Cho77bba8d2016-11-04 16:36:56 -07001770 pvq_info->k[i] = k[i];
1771 pvq_info->off[i] = off[i];
1772 pvq_info->size[i] = size[i];
1773 }
1774
1775 memcpy(pvq_info->y, y, tx_blk_size * tx_blk_size * sizeof(od_coeff));
1776
1777 pvq_info->nb_bands = nb_bands;
1778 pvq_info->skip_rest = skip_rest;
1779 pvq_info->skip_dir = skip_dir;
1780 pvq_info->bs = bs;
1781}
1782#endif