blob: b4624a4e9f3130ccadd9f3674d1e144a6b490695 [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
122#define UPDATE_RD_COST() \
123 { \
124 rd_cost0 = RDCOST(rdmult, rddiv, rate0, error0); \
125 rd_cost1 = RDCOST(rdmult, rddiv, rate1, error1); \
126 }
127
Yaowu Xu42350322017-05-05 11:12:19 -0700128static INLINE unsigned int get_token_bit_costs(
129 unsigned int token_costs[2][COEFF_CONTEXTS][ENTROPY_TOKENS], int skip_eob,
130 int ctx, int token) {
Thomas Daviesed8e2d22017-01-04 16:42:09 +0000131 (void)skip_eob;
132 return token_costs[token == ZERO_TOKEN || token == EOB_TOKEN][ctx][token];
Thomas Daviesed8e2d22017-01-04 16:42:09 +0000133}
134
Angie Chiang1c96e822017-05-31 14:40:55 -0700135#if !CONFIG_LV_MAP
Dake He97f56642017-03-29 16:46:51 -0700136
Angie Chiang7dec6c42017-05-03 17:58:17 -0700137typedef struct av1_token_state_greedy {
Dake He97f56642017-03-29 16:46:51 -0700138 int16_t token;
139 tran_low_t qc;
140 tran_low_t dqc;
Angie Chiang7dec6c42017-05-03 17:58:17 -0700141} av1_token_state_greedy;
Dake He97f56642017-03-29 16:46:51 -0700142
Angie Chiang7dec6c42017-05-03 17:58:17 -0700143static int optimize_b_greedy(const AV1_COMMON *cm, MACROBLOCK *mb, int plane,
144 int block, TX_SIZE tx_size, int ctx) {
Dake He97f56642017-03-29 16:46:51 -0700145 MACROBLOCKD *const xd = &mb->e_mbd;
146 struct macroblock_plane *const p = &mb->plane[plane];
147 struct macroblockd_plane *const pd = &xd->plane[plane];
148 const int ref = is_inter_block(&xd->mi[0]->mbmi);
Angie Chiang7dec6c42017-05-03 17:58:17 -0700149 av1_token_state_greedy tokens[MAX_TX_SQUARE + 1][2];
Dake He97f56642017-03-29 16:46:51 -0700150 uint8_t token_cache[MAX_TX_SQUARE];
151 const tran_low_t *const coeff = BLOCK_OFFSET(p->coeff, block);
152 tran_low_t *const qcoeff = BLOCK_OFFSET(p->qcoeff, block);
153 tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
154 const int eob = p->eobs[block];
155 const PLANE_TYPE plane_type = pd->plane_type;
156 const int16_t *const dequant_ptr = pd->dequant;
157 const uint8_t *const band_translate = get_band_translate(tx_size);
158 TX_TYPE tx_type = get_tx_type(plane_type, xd, block, tx_size);
159 const SCAN_ORDER *const scan_order =
160 get_scan(cm, tx_size, tx_type, is_inter_block(&xd->mi[0]->mbmi));
161 const int16_t *const scan = scan_order->scan;
162 const int16_t *const nb = scan_order->neighbors;
163 int dqv;
Jingning Hanff705452017-04-27 11:32:15 -0700164 const int shift = av1_get_tx_scale(tx_size);
Dake He97f56642017-03-29 16:46:51 -0700165#if CONFIG_AOM_QM
166 int seg_id = xd->mi[0]->mbmi.segment_id;
167 const qm_val_t *iqmatrix = pd->seg_iqmatrix[seg_id][!ref][tx_size];
168#endif
169#if CONFIG_NEW_QUANT
170 int dq = get_dq_profile_from_ctx(mb->qindex, ctx, ref, plane_type);
171 const dequant_val_type_nuq *dequant_val = pd->dequant_val_nuq[dq];
Dake He97f56642017-03-29 16:46:51 -0700172#endif // CONFIG_NEW_QUANT
173 int sz = 0;
174 const int64_t rddiv = mb->rddiv;
175 int64_t rd_cost0, rd_cost1;
176 int16_t t0, t1;
177 int i, final_eob;
Dake He97f56642017-03-29 16:46:51 -0700178 const int cat6_bits = av1_get_cat6_extrabits_size(tx_size, xd->bd);
Dake He97f56642017-03-29 16:46:51 -0700179 unsigned int(*token_costs)[2][COEFF_CONTEXTS][ENTROPY_TOKENS] =
180 mb->token_costs[txsize_sqr_map[tx_size]][plane_type][ref];
181 const int default_eob = tx_size_2d[tx_size];
182
Angie Chiang7dec6c42017-05-03 17:58:17 -0700183 assert(mb->qindex > 0);
Dake He97f56642017-03-29 16:46:51 -0700184
185 assert((!plane_type && !plane) || (plane_type && plane));
186 assert(eob <= default_eob);
187
188 int64_t rdmult = (mb->rdmult * plane_rd_mult[ref][plane_type]) >> 1;
Dake He97f56642017-03-29 16:46:51 -0700189
190 int64_t rate0, rate1;
191 for (i = 0; i < eob; i++) {
192 const int rc = scan[i];
193 int x = qcoeff[rc];
194 t0 = av1_get_token(x);
195
196 tokens[i][0].qc = x;
197 tokens[i][0].token = t0;
198 tokens[i][0].dqc = dqcoeff[rc];
199
200 token_cache[rc] = av1_pt_energy_class[t0];
201 }
202 tokens[eob][0].token = EOB_TOKEN;
203 tokens[eob][0].qc = 0;
204 tokens[eob][0].dqc = 0;
205 tokens[eob][1] = tokens[eob][0];
206
207 unsigned int(*token_costs_ptr)[2][COEFF_CONTEXTS][ENTROPY_TOKENS] =
208 token_costs;
209
210 final_eob = 0;
211
212 int64_t eob_cost0, eob_cost1;
213
214 const int ctx0 = ctx;
215 /* Record the r-d cost */
216 int64_t accu_rate = 0;
217 int64_t accu_error = 0;
218
219 rate0 = get_token_bit_costs(*(token_costs_ptr + band_translate[0]), 0, ctx0,
220 EOB_TOKEN);
221 int64_t best_block_rd_cost = RDCOST(rdmult, rddiv, rate0, accu_error);
222
223 // int64_t best_block_rd_cost_all0 = best_block_rd_cost;
224
225 int x_prev = 1;
226
227 for (i = 0; i < eob; i++) {
228 const int rc = scan[i];
229 int x = qcoeff[rc];
230 sz = -(x < 0);
231
232 int band_cur = band_translate[i];
233 int ctx_cur = (i == 0) ? ctx : get_coef_context(nb, token_cache, i);
234 int token_tree_sel_cur = (x_prev == 0);
235
236 if (x == 0) {
237 // no need to search when x == 0
238 rate0 =
239 get_token_bit_costs(*(token_costs_ptr + band_cur), token_tree_sel_cur,
240 ctx_cur, tokens[i][0].token);
241 accu_rate += rate0;
242 x_prev = 0;
243 // accu_error does not change when x==0
244 } else {
245 /* Computing distortion
246 */
247 // compute the distortion for the first candidate
248 // and the distortion for quantizing to 0.
Jingning Han32d26bc2017-06-11 07:50:39 -0700249 int dx0 = abs(coeff[rc]) * (1 << shift);
Dake He97f56642017-03-29 16:46:51 -0700250#if CONFIG_HIGHBITDEPTH
251 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
252 dx0 >>= xd->bd - 8;
253 }
254#endif
255 int64_t d0 = (int64_t)dx0 * dx0;
256
257 int x_a = x - 2 * sz - 1;
258 int64_t d2, d2_a;
259
260 int dx;
261
262#if CONFIG_AOM_QM
263 int iwt = iqmatrix[rc];
264 dqv = dequant_ptr[rc != 0];
265 dqv = ((iwt * (int)dqv) + (1 << (AOM_QM_BITS - 1))) >> AOM_QM_BITS;
266#else
267 dqv = dequant_ptr[rc != 0];
268#endif
269
270 dx = (dqcoeff[rc] - coeff[rc]) * (1 << shift);
271#if CONFIG_HIGHBITDEPTH
272 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
Jingning Han32d26bc2017-06-11 07:50:39 -0700273 int dx_sign = dx < 0 ? 1 : 0;
274 dx = abs(dx) >> (xd->bd - 8);
275 if (dx_sign) dx = -dx;
Dake He97f56642017-03-29 16:46:51 -0700276 }
277#endif // CONFIG_HIGHBITDEPTH
278 d2 = (int64_t)dx * dx;
279
280 /* compute the distortion for the second candidate
281 * x_a = x - 2 * sz + 1;
282 */
283 if (x_a != 0) {
284#if CONFIG_NEW_QUANT
285 dx = av1_dequant_coeff_nuq(x, dqv, dequant_val[band_translate[i]]) -
286 (coeff[rc] << shift);
287#if CONFIG_HIGHBITDEPTH
288 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
289 dx >>= xd->bd - 8;
290 }
291#endif // CONFIG_HIGHBITDEPTH
292#else // CONFIG_NEW_QUANT
293#if CONFIG_HIGHBITDEPTH
294 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
295 dx -= ((dqv >> (xd->bd - 8)) + sz) ^ sz;
296 } else {
297 dx -= (dqv + sz) ^ sz;
298 }
299#else
300 dx -= (dqv + sz) ^ sz;
301#endif // CONFIG_HIGHBITDEPTH
302#endif // CONFIG_NEW_QUANT
303 d2_a = (int64_t)dx * dx;
304 } else {
305 d2_a = d0;
306 }
307 /* Computing rates and r-d cost
308 */
309
310 int best_x, best_eob_x;
311 int64_t base_bits, next_bits0, next_bits1;
312 int64_t next_eob_bits0, next_eob_bits1;
313
314 // rate cost of x
315 base_bits = av1_get_token_cost(x, &t0, cat6_bits);
316 rate0 = base_bits + get_token_bit_costs(*(token_costs_ptr + band_cur),
317 token_tree_sel_cur, ctx_cur, t0);
318
319 base_bits = av1_get_token_cost(x_a, &t1, cat6_bits);
320 rate1 = base_bits + get_token_bit_costs(*(token_costs_ptr + band_cur),
321 token_tree_sel_cur, ctx_cur, t1);
322
323 next_bits0 = 0;
324 next_bits1 = 0;
325 next_eob_bits0 = 0;
326 next_eob_bits1 = 0;
327
328 if (i < default_eob - 1) {
329 int ctx_next, token_tree_sel_next;
330 int band_next = band_translate[i + 1];
331
332 token_cache[rc] = av1_pt_energy_class[t0];
333 ctx_next = get_coef_context(nb, token_cache, i + 1);
334 token_tree_sel_next = (x == 0);
335
336 next_bits0 = get_token_bit_costs(*(token_costs_ptr + band_next),
337 token_tree_sel_next, ctx_next,
338 tokens[i + 1][0].token);
339 next_eob_bits0 =
340 get_token_bit_costs(*(token_costs_ptr + band_next),
341 token_tree_sel_next, ctx_next, EOB_TOKEN);
342
343 token_cache[rc] = av1_pt_energy_class[t1];
344 ctx_next = get_coef_context(nb, token_cache, i + 1);
345 token_tree_sel_next = (x_a == 0);
346
347 next_bits1 = get_token_bit_costs(*(token_costs_ptr + band_next),
348 token_tree_sel_next, ctx_next,
349 tokens[i + 1][0].token);
350
351 if (x_a != 0) {
352 next_eob_bits1 =
353 get_token_bit_costs(*(token_costs_ptr + band_next),
354 token_tree_sel_next, ctx_next, EOB_TOKEN);
355 }
356 }
357
358 rd_cost0 = RDCOST(rdmult, rddiv, (rate0 + next_bits0), d2);
359 rd_cost1 = RDCOST(rdmult, rddiv, (rate1 + next_bits1), d2_a);
360
361 best_x = (rd_cost1 < rd_cost0);
362
363 eob_cost0 = RDCOST(rdmult, rddiv, (accu_rate + rate0 + next_eob_bits0),
364 (accu_error + d2 - d0));
365 eob_cost1 = eob_cost0;
366 if (x_a != 0) {
367 eob_cost1 = RDCOST(rdmult, rddiv, (accu_rate + rate1 + next_eob_bits1),
368 (accu_error + d2_a - d0));
369 best_eob_x = (eob_cost1 < eob_cost0);
370 } else {
371 best_eob_x = 0;
372 }
373
374 int dqc, dqc_a = 0;
375
376 dqc = dqcoeff[rc];
377 if (best_x + best_eob_x) {
378 if (x_a != 0) {
379#if CONFIG_NEW_QUANT
380 dqc_a = av1_dequant_abscoeff_nuq(abs(x_a), dqv,
381 dequant_val[band_translate[i]]);
382 dqc_a = shift ? ROUND_POWER_OF_TWO(dqc_a, shift) : dqc_a;
383 if (sz) dqc_a = -dqc_a;
384#else
David Barkerc747a782017-05-24 12:46:08 +0100385 if (x_a < 0)
386 dqc_a = -((-x_a * dqv) >> shift);
Dake He97f56642017-03-29 16:46:51 -0700387 else
David Barkerc747a782017-05-24 12:46:08 +0100388 dqc_a = (x_a * dqv) >> shift;
Dake He97f56642017-03-29 16:46:51 -0700389#endif // CONFIG_NEW_QUANT
390 } else {
391 dqc_a = 0;
392 } // if (x_a != 0)
393 }
394
395 // record the better quantized value
396 if (best_x) {
397 qcoeff[rc] = x_a;
398 dqcoeff[rc] = dqc_a;
399
400 accu_rate += rate1;
401 accu_error += d2_a - d0;
402 assert(d2_a <= d0);
403
404 token_cache[rc] = av1_pt_energy_class[t1];
405 } else {
406 accu_rate += rate0;
407 accu_error += d2 - d0;
408 assert(d2 <= d0);
409
410 token_cache[rc] = av1_pt_energy_class[t0];
411 }
412
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}
455
Angie Chiang1c96e822017-05-31 14:40:55 -0700456#endif // !CONFIG_LV_MAP
Dake He97f56642017-03-29 16:46:51 -0700457
Angie Chiang7dec6c42017-05-03 17:58:17 -0700458int av1_optimize_b(const AV1_COMMON *cm, MACROBLOCK *mb, int plane, int block,
Angie Chiang3511c372017-05-31 12:47:07 -0700459 BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
460 const ENTROPY_CONTEXT *a, const ENTROPY_CONTEXT *l) {
Angie Chiang7dec6c42017-05-03 17:58:17 -0700461 MACROBLOCKD *const xd = &mb->e_mbd;
462 struct macroblock_plane *const p = &mb->plane[plane];
463 const int eob = p->eobs[block];
464 assert((mb->qindex == 0) ^ (xd->lossless[xd->mi[0]->mbmi.segment_id] == 0));
465 if (eob == 0) return eob;
466 if (xd->lossless[xd->mi[0]->mbmi.segment_id]) return eob;
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
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200491#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700492typedef enum QUANT_FUNC {
493 QUANT_FUNC_LOWBD = 0,
494 QUANT_FUNC_HIGHBD = 1,
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800495 QUANT_FUNC_TYPES = 2
Yaowu Xuc27fc142016-08-22 16:08:15 -0700496} QUANT_FUNC;
497
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800498static AV1_QUANT_FACADE
499 quant_func_list[AV1_XFORM_QUANT_TYPES][QUANT_FUNC_TYPES] = {
Angie Chiang6a71ad12017-04-03 11:19:00 -0700500#if !CONFIG_NEW_QUANT
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800501 { av1_quantize_fp_facade, av1_highbd_quantize_fp_facade },
Yaowu Xuf883b422016-08-30 14:01:10 -0700502 { av1_quantize_b_facade, av1_highbd_quantize_b_facade },
503 { av1_quantize_dc_facade, av1_highbd_quantize_dc_facade },
Angie Chiang6a71ad12017-04-03 11:19:00 -0700504#else // !CONFIG_NEW_QUANT
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800505 { av1_quantize_fp_nuq_facade, av1_highbd_quantize_fp_nuq_facade },
506 { av1_quantize_b_nuq_facade, av1_highbd_quantize_b_nuq_facade },
507 { av1_quantize_dc_nuq_facade, av1_highbd_quantize_dc_nuq_facade },
Angie Chiang6a71ad12017-04-03 11:19:00 -0700508#endif // !CONFIG_NEW_QUANT
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800509 { NULL, NULL }
510 };
Yaowu Xuc27fc142016-08-22 16:08:15 -0700511
Thomas Daede6ff6af62017-02-03 16:29:24 -0800512#else
Yaowu Xu02d4c3b2016-11-07 10:45:56 -0800513
Yaowu Xuc27fc142016-08-22 16:08:15 -0700514typedef enum QUANT_FUNC {
515 QUANT_FUNC_LOWBD = 0,
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800516 QUANT_FUNC_TYPES = 1
Yaowu Xuc27fc142016-08-22 16:08:15 -0700517} QUANT_FUNC;
518
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800519static AV1_QUANT_FACADE quant_func_list[AV1_XFORM_QUANT_TYPES]
520 [QUANT_FUNC_TYPES] = {
Angie Chiang6a71ad12017-04-03 11:19:00 -0700521#if !CONFIG_NEW_QUANT
clang-format67948d32016-09-07 22:40:40 -0700522 { av1_quantize_fp_facade },
523 { av1_quantize_b_facade },
524 { av1_quantize_dc_facade },
Angie Chiang6a71ad12017-04-03 11:19:00 -0700525#else // !CONFIG_NEW_QUANT
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800526 { av1_quantize_fp_nuq_facade },
527 { av1_quantize_b_nuq_facade },
528 { av1_quantize_dc_nuq_facade },
Angie Chiang6a71ad12017-04-03 11:19:00 -0700529#endif // !CONFIG_NEW_QUANT
clang-format67948d32016-09-07 22:40:40 -0700530 { NULL }
531 };
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200532#endif // CONFIG_HIGHBITDEPTH
Thomas Daede6ff6af62017-02-03 16:29:24 -0800533#endif // CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -0700534
Angie Chiangff6d8902016-10-21 11:02:09 -0700535void av1_xform_quant(const AV1_COMMON *cm, MACROBLOCK *x, int plane, int block,
536 int blk_row, int blk_col, BLOCK_SIZE plane_bsize,
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800537 TX_SIZE tx_size, int ctx,
538 AV1_XFORM_QUANT xform_quant_idx) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700539 MACROBLOCKD *const xd = &x->e_mbd;
Luc Trudeaub6e94d92017-03-13 15:46:15 -0400540 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Yushin Cho7a428ba2017-01-12 16:28:49 -0800541#if !(CONFIG_PVQ || CONFIG_DAALA_DIST)
Yaowu Xuc27fc142016-08-22 16:08:15 -0700542 const struct macroblock_plane *const p = &x->plane[plane];
543 const struct macroblockd_plane *const pd = &xd->plane[plane];
Yushin Cho77bba8d2016-11-04 16:36:56 -0700544#else
545 struct macroblock_plane *const p = &x->plane[plane];
546 struct macroblockd_plane *const pd = &xd->plane[plane];
547#endif
Luc Trudeau005feb62017-02-22 13:34:01 -0500548 PLANE_TYPE plane_type = get_plane_type(plane);
Angie Chiang752ccce2017-04-09 13:41:13 -0700549 TX_TYPE tx_type = get_tx_type(plane_type, xd, block, tx_size);
Luc Trudeaub6e94d92017-03-13 15:46:15 -0400550 const int is_inter = is_inter_block(mbmi);
Angie Chiangff6d8902016-10-21 11:02:09 -0700551 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, is_inter);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700552 tran_low_t *const coeff = BLOCK_OFFSET(p->coeff, block);
553 tran_low_t *const qcoeff = BLOCK_OFFSET(p->qcoeff, block);
554 tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
555 uint16_t *const eob = &p->eobs[block];
Jingning Hanae5cfde2016-11-30 12:01:44 -0800556 const int diff_stride = block_size_wide[plane_bsize];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700557#if CONFIG_AOM_QM
Luc Trudeaub6e94d92017-03-13 15:46:15 -0400558 int seg_id = mbmi->segment_id;
Debargha Mukherjee3c42c092016-09-29 09:17:36 -0700559 const qm_val_t *qmatrix = pd->seg_qmatrix[seg_id][!is_inter][tx_size];
560 const qm_val_t *iqmatrix = pd->seg_iqmatrix[seg_id][!is_inter][tx_size];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700561#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -0700562
563 FWD_TXFM_PARAM fwd_txfm_param;
Yushin Cho77bba8d2016-11-04 16:36:56 -0700564
Yushin Cho7a428ba2017-01-12 16:28:49 -0800565#if CONFIG_PVQ || CONFIG_DAALA_DIST
566 uint8_t *dst;
567 int16_t *pred;
568 const int dst_stride = pd->dst.stride;
569 int tx_blk_size;
570 int i, j;
571#endif
572
Yushin Cho77bba8d2016-11-04 16:36:56 -0700573#if !CONFIG_PVQ
574 const int tx2d_size = tx_size_2d[tx_size];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700575 QUANT_PARAM qparam;
Yushin Cho77bba8d2016-11-04 16:36:56 -0700576 const int16_t *src_diff;
577
Jingning Han81492262016-12-05 15:48:47 -0800578 src_diff =
579 &p->src_diff[(blk_row * diff_stride + blk_col) << tx_size_wide_log2[0]];
Jingning Hanff705452017-04-27 11:32:15 -0700580 qparam.log_scale = av1_get_tx_scale(tx_size);
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800581#if CONFIG_NEW_QUANT
582 qparam.tx_size = tx_size;
583 qparam.dq = get_dq_profile_from_ctx(x->qindex, ctx, is_inter, plane_type);
584#endif // CONFIG_NEW_QUANT
585#if CONFIG_AOM_QM
586 qparam.qmatrix = qmatrix;
587 qparam.iqmatrix = iqmatrix;
588#endif // CONFIG_AOM_QM
Yushin Cho77bba8d2016-11-04 16:36:56 -0700589#else
Yushin Cho77bba8d2016-11-04 16:36:56 -0700590 tran_low_t *ref_coeff = BLOCK_OFFSET(pd->pvq_ref_coeff, block);
Yushin Cho77bba8d2016-11-04 16:36:56 -0700591 int skip = 1;
592 PVQ_INFO *pvq_info = NULL;
Yushin Cho7a428ba2017-01-12 16:28:49 -0800593 uint8_t *src;
594 int16_t *src_int16;
595 const int src_stride = p->src.stride;
Yushin Cho77bba8d2016-11-04 16:36:56 -0700596
Yushin Cho6341f5c2017-03-24 14:36:28 -0700597 (void)ctx;
Yushin Cho77bba8d2016-11-04 16:36:56 -0700598 (void)scan_order;
599 (void)qcoeff;
600
601 if (x->pvq_coded) {
602 assert(block < MAX_PVQ_BLOCKS_IN_SB);
603 pvq_info = &x->pvq[block][plane];
604 }
Jingning Han81492262016-12-05 15:48:47 -0800605 src = &p->src.buf[(blk_row * src_stride + blk_col) << tx_size_wide_log2[0]];
606 src_int16 =
607 &p->src_int16[(blk_row * diff_stride + blk_col) << tx_size_wide_log2[0]];
Yushin Cho7a428ba2017-01-12 16:28:49 -0800608
609 // transform block size in pixels
610 tx_blk_size = tx_size_wide[tx_size];
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200611#if CONFIG_HIGHBITDEPTH
Thomas Daede6ff6af62017-02-03 16:29:24 -0800612 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
613 for (j = 0; j < tx_blk_size; j++)
614 for (i = 0; i < tx_blk_size; i++)
615 src_int16[diff_stride * j + i] =
616 CONVERT_TO_SHORTPTR(src)[src_stride * j + i];
617 } else {
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200618#endif // CONFIG_HIGHBITDEPTH
Thomas Daede6ff6af62017-02-03 16:29:24 -0800619 for (j = 0; j < tx_blk_size; j++)
620 for (i = 0; i < tx_blk_size; i++)
621 src_int16[diff_stride * j + i] = src[src_stride * j + i];
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200622#if CONFIG_HIGHBITDEPTH
Thomas Daede6ff6af62017-02-03 16:29:24 -0800623 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200624#endif // CONFIG_HIGHBITDEPTH
Yushin Cho7a428ba2017-01-12 16:28:49 -0800625#endif
626
627#if CONFIG_PVQ || CONFIG_DAALA_DIST
628 dst = &pd->dst.buf[(blk_row * dst_stride + blk_col) << tx_size_wide_log2[0]];
Jingning Han81492262016-12-05 15:48:47 -0800629 pred = &pd->pred[(blk_row * diff_stride + blk_col) << tx_size_wide_log2[0]];
Yushin Cho77bba8d2016-11-04 16:36:56 -0700630
631 // transform block size in pixels
632 tx_blk_size = tx_size_wide[tx_size];
633
Thomas Daede6ff6af62017-02-03 16:29:24 -0800634// copy uint8 orig and predicted block to int16 buffer
635// in order to use existing VP10 transform functions
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200636#if CONFIG_HIGHBITDEPTH
Thomas Daede6ff6af62017-02-03 16:29:24 -0800637 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
638 for (j = 0; j < tx_blk_size; j++)
639 for (i = 0; i < tx_blk_size; i++)
640 pred[diff_stride * j + i] =
641 CONVERT_TO_SHORTPTR(dst)[dst_stride * j + i];
642 } else {
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200643#endif // CONFIG_HIGHBITDEPTH
Thomas Daede6ff6af62017-02-03 16:29:24 -0800644 for (j = 0; j < tx_blk_size; j++)
645 for (i = 0; i < tx_blk_size; i++)
646 pred[diff_stride * j + i] = dst[dst_stride * j + i];
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200647#if CONFIG_HIGHBITDEPTH
Thomas Daede6ff6af62017-02-03 16:29:24 -0800648 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200649#endif // CONFIG_HIGHBITDEPTH
Yushin Cho77bba8d2016-11-04 16:36:56 -0700650#endif
Yushin Cho7a428ba2017-01-12 16:28:49 -0800651
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800652 (void)ctx;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700653
654 fwd_txfm_param.tx_type = tx_type;
655 fwd_txfm_param.tx_size = tx_size;
Luc Trudeaub6e94d92017-03-13 15:46:15 -0400656 fwd_txfm_param.lossless = xd->lossless[mbmi->segment_id];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700657
Thomas Daede6ff6af62017-02-03 16:29:24 -0800658#if !CONFIG_PVQ
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200659#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700660 fwd_txfm_param.bd = xd->bd;
661 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
hui suf11fb882017-03-27 14:56:33 -0700662 av1_highbd_fwd_txfm(src_diff, coeff, diff_stride, &fwd_txfm_param);
Yaowu Xuf883b422016-08-30 14:01:10 -0700663 if (xform_quant_idx != AV1_XFORM_QUANT_SKIP_QUANT) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700664 if (LIKELY(!x->skip_block)) {
665 quant_func_list[xform_quant_idx][QUANT_FUNC_HIGHBD](
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800666 coeff, tx2d_size, p, qcoeff, pd, dqcoeff, eob, scan_order, &qparam);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700667 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -0700668 av1_quantize_skip(tx2d_size, qcoeff, dqcoeff, eob);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700669 }
670 }
Angie Chiang74e23072017-03-24 14:54:23 -0700671#if CONFIG_LV_MAP
672 p->txb_entropy_ctx[block] =
673 (uint8_t)av1_get_txb_entropy_context(qcoeff, scan_order, *eob);
674#endif // CONFIG_LV_MAP
Yaowu Xuc27fc142016-08-22 16:08:15 -0700675 return;
676 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200677#endif // CONFIG_HIGHBITDEPTH
hui suf11fb882017-03-27 14:56:33 -0700678 av1_fwd_txfm(src_diff, coeff, diff_stride, &fwd_txfm_param);
Yaowu Xuf883b422016-08-30 14:01:10 -0700679 if (xform_quant_idx != AV1_XFORM_QUANT_SKIP_QUANT) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700680 if (LIKELY(!x->skip_block)) {
681 quant_func_list[xform_quant_idx][QUANT_FUNC_LOWBD](
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800682 coeff, tx2d_size, p, qcoeff, pd, dqcoeff, eob, scan_order, &qparam);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700683 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -0700684 av1_quantize_skip(tx2d_size, qcoeff, dqcoeff, eob);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700685 }
686 }
Angie Chiang74e23072017-03-24 14:54:23 -0700687#if CONFIG_LV_MAP
688 p->txb_entropy_ctx[block] =
689 (uint8_t)av1_get_txb_entropy_context(qcoeff, scan_order, *eob);
690#endif // CONFIG_LV_MAP
691#else // #if !CONFIG_PVQ
Angie Chiang2cc057c2017-01-03 18:31:47 -0800692 (void)xform_quant_idx;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200693#if CONFIG_HIGHBITDEPTH
Thomas Daede6ff6af62017-02-03 16:29:24 -0800694 fwd_txfm_param.bd = xd->bd;
695 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
hui suf11fb882017-03-27 14:56:33 -0700696 av1_highbd_fwd_txfm(src_int16, coeff, diff_stride, &fwd_txfm_param);
697 av1_highbd_fwd_txfm(pred, ref_coeff, diff_stride, &fwd_txfm_param);
Thomas Daede6ff6af62017-02-03 16:29:24 -0800698 } else {
699#endif
hui suf11fb882017-03-27 14:56:33 -0700700 av1_fwd_txfm(src_int16, coeff, diff_stride, &fwd_txfm_param);
701 av1_fwd_txfm(pred, ref_coeff, diff_stride, &fwd_txfm_param);
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200702#if CONFIG_HIGHBITDEPTH
Thomas Daede6ff6af62017-02-03 16:29:24 -0800703 }
704#endif
Yushin Cho77bba8d2016-11-04 16:36:56 -0700705
706 // PVQ for inter mode block
ltrudeau472f63f2017-01-12 15:22:32 -0500707 if (!x->skip_block) {
ltrudeaue1c09292017-01-20 15:42:13 -0500708 PVQ_SKIP_TYPE ac_dc_coded =
Thomas Daede6ff6af62017-02-03 16:29:24 -0800709 av1_pvq_encode_helper(x,
ltrudeaue1c09292017-01-20 15:42:13 -0500710 coeff, // target original vector
711 ref_coeff, // reference vector
712 dqcoeff, // de-quantized vector
713 eob, // End of Block marker
714 pd->dequant, // aom's quantizers
715 plane, // image plane
716 tx_size, // block size in log_2 - 2
717 tx_type,
718 &x->rate, // rate measured
719 x->pvq_speed,
720 pvq_info); // PVQ info for a block
721 skip = ac_dc_coded == PVQ_SKIP;
ltrudeau472f63f2017-01-12 15:22:32 -0500722 }
Yushin Cho77bba8d2016-11-04 16:36:56 -0700723 x->pvq_skip[plane] = skip;
724
725 if (!skip) mbmi->skip = 0;
726#endif // #if !CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -0700727}
728
Yaowu Xuc27fc142016-08-22 16:08:15 -0700729static void encode_block(int plane, int block, int blk_row, int blk_col,
730 BLOCK_SIZE plane_bsize, TX_SIZE tx_size, void *arg) {
731 struct encode_b_args *const args = arg;
Angie Chiangff6d8902016-10-21 11:02:09 -0700732 AV1_COMMON *cm = args->cm;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700733 MACROBLOCK *const x = args->x;
734 MACROBLOCKD *const xd = &x->e_mbd;
735 int ctx;
736 struct macroblock_plane *const p = &x->plane[plane];
737 struct macroblockd_plane *const pd = &xd->plane[plane];
738 tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
739 uint8_t *dst;
Yushin Cho6341f5c2017-03-24 14:36:28 -0700740#if !CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -0700741 ENTROPY_CONTEXT *a, *l;
Yushin Cho6341f5c2017-03-24 14:36:28 -0700742#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -0700743#if CONFIG_VAR_TX
Jingning Han9ca05b72017-01-03 14:41:36 -0800744 int bw = block_size_wide[plane_bsize] >> tx_size_wide_log2[0];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700745#endif
Jingning Han81492262016-12-05 15:48:47 -0800746 dst = &pd->dst
747 .buf[(blk_row * pd->dst.stride + blk_col) << tx_size_wide_log2[0]];
Yushin Cho6341f5c2017-03-24 14:36:28 -0700748
749#if !CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -0700750 a = &args->ta[blk_col];
751 l = &args->tl[blk_row];
752#if CONFIG_VAR_TX
753 ctx = get_entropy_context(tx_size, a, l);
754#else
755 ctx = combine_entropy_contexts(*a, *l);
756#endif
Yushin Cho6341f5c2017-03-24 14:36:28 -0700757#else
758 ctx = 0;
759#endif // CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -0700760
761#if CONFIG_VAR_TX
Yue Chena1e48dc2016-08-29 17:29:33 -0700762 // Assert not magic number (uninitialized).
Jingning Han9ca05b72017-01-03 14:41:36 -0800763 assert(x->blk_skip[plane][blk_row * bw + blk_col] != 234);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700764
Jingning Han9ca05b72017-01-03 14:41:36 -0800765 if (x->blk_skip[plane][blk_row * bw + blk_col] == 0) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700766#else
767 {
768#endif
Angie Chiangff6d8902016-10-21 11:02:09 -0700769 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800770 ctx, AV1_XFORM_QUANT_FP);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700771 }
772#if CONFIG_VAR_TX
773 else {
774 p->eobs[block] = 0;
775 }
776#endif
Yushin Cho6341f5c2017-03-24 14:36:28 -0700777
Yushin Cho77bba8d2016-11-04 16:36:56 -0700778#if !CONFIG_PVQ
Angie Chiang3511c372017-05-31 12:47:07 -0700779 av1_optimize_b(cm, x, plane, block, plane_bsize, tx_size, a, l);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700780
Angie Chiangdb0c7d42017-03-23 16:05:37 -0700781 av1_set_txb_context(x, plane, block, tx_size, a, l);
782
Yaowu Xuc27fc142016-08-22 16:08:15 -0700783 if (p->eobs[block]) *(args->skip) = 0;
784
785 if (p->eobs[block] == 0) return;
Yushin Cho77bba8d2016-11-04 16:36:56 -0700786#else
787 (void)ctx;
Yushin Cho77bba8d2016-11-04 16:36:56 -0700788 if (!x->pvq_skip[plane]) *(args->skip) = 0;
789
790 if (x->pvq_skip[plane]) return;
Yushin Cho77bba8d2016-11-04 16:36:56 -0700791#endif
Angie Chiang752ccce2017-04-09 13:41:13 -0700792 TX_TYPE tx_type = get_tx_type(pd->plane_type, xd, block, tx_size);
Angie Chiang44d7e662017-04-06 11:07:53 -0700793 av1_inverse_transform_block(xd, dqcoeff, tx_type, tx_size, dst,
794 pd->dst.stride, p->eobs[block]);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700795}
796
797#if CONFIG_VAR_TX
798static void encode_block_inter(int plane, int block, int blk_row, int blk_col,
799 BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
800 void *arg) {
801 struct encode_b_args *const args = arg;
802 MACROBLOCK *const x = args->x;
803 MACROBLOCKD *const xd = &x->e_mbd;
804 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
805 const BLOCK_SIZE bsize = txsize_to_bsize[tx_size];
806 const struct macroblockd_plane *const pd = &xd->plane[plane];
807 const int tx_row = blk_row >> (1 - pd->subsampling_y);
808 const int tx_col = blk_col >> (1 - pd->subsampling_x);
809 TX_SIZE plane_tx_size;
Jingning Hanf65b8702016-10-31 12:13:20 -0700810 const int max_blocks_high = max_block_high(xd, plane_bsize, plane);
811 const int max_blocks_wide = max_block_wide(xd, plane_bsize, plane);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700812
813 if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
814
Debargha Mukherjee2f123402016-08-30 17:43:38 -0700815 plane_tx_size =
816 plane ? uv_txsize_lookup[bsize][mbmi->inter_tx_size[tx_row][tx_col]][0][0]
817 : mbmi->inter_tx_size[tx_row][tx_col];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700818
819 if (tx_size == plane_tx_size) {
820 encode_block(plane, block, blk_row, blk_col, plane_bsize, tx_size, arg);
821 } else {
Alex Conversee16b2662017-05-24 14:00:00 -0700822 assert(tx_size < TX_SIZES_ALL);
Jingning Hana9336322016-11-02 15:45:07 -0700823 const TX_SIZE sub_txs = sub_tx_size_map[tx_size];
Alex Conversee16b2662017-05-24 14:00:00 -0700824 assert(sub_txs < tx_size);
Jingning Hana9336322016-11-02 15:45:07 -0700825 // This is the square transform block partition entry point.
826 int bsl = tx_size_wide_unit[sub_txs];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700827 int i;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700828 assert(bsl > 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700829
830 for (i = 0; i < 4; ++i) {
Jingning Hande953b92016-10-25 12:35:43 -0700831 const int offsetr = blk_row + ((i >> 1) * bsl);
832 const int offsetc = blk_col + ((i & 0x01) * bsl);
Jingning Hande953b92016-10-25 12:35:43 -0700833 int step = tx_size_wide_unit[sub_txs] * tx_size_high_unit[sub_txs];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700834
835 if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide) continue;
836
Jingning Han98d6a1f2016-11-03 12:47:47 -0700837 encode_block_inter(plane, block, offsetr, offsetc, plane_bsize, sub_txs,
838 arg);
839 block += step;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700840 }
841 }
842}
843#endif
844
Angie Chiangff6d8902016-10-21 11:02:09 -0700845typedef struct encode_block_pass1_args {
846 AV1_COMMON *cm;
847 MACROBLOCK *x;
848} encode_block_pass1_args;
849
Yaowu Xuc27fc142016-08-22 16:08:15 -0700850static void encode_block_pass1(int plane, int block, int blk_row, int blk_col,
851 BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
852 void *arg) {
Angie Chiangff6d8902016-10-21 11:02:09 -0700853 encode_block_pass1_args *args = (encode_block_pass1_args *)arg;
854 AV1_COMMON *cm = args->cm;
855 MACROBLOCK *const x = args->x;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700856 MACROBLOCKD *const xd = &x->e_mbd;
857 struct macroblock_plane *const p = &x->plane[plane];
858 struct macroblockd_plane *const pd = &xd->plane[plane];
859 tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
860 uint8_t *dst;
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800861 int ctx = 0;
Jingning Han81492262016-12-05 15:48:47 -0800862 dst = &pd->dst
863 .buf[(blk_row * pd->dst.stride + blk_col) << tx_size_wide_log2[0]];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700864
Angie Chiangff6d8902016-10-21 11:02:09 -0700865 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
Debargha Mukherjeef0305582016-11-24 09:55:34 -0800866 ctx, AV1_XFORM_QUANT_B);
Yushin Cho77bba8d2016-11-04 16:36:56 -0700867#if !CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -0700868 if (p->eobs[block] > 0) {
Yushin Cho77bba8d2016-11-04 16:36:56 -0700869#else
870 if (!x->pvq_skip[plane]) {
Yushin Cho77bba8d2016-11-04 16:36:56 -0700871 {
872 int tx_blk_size;
873 int i, j;
874 // transform block size in pixels
875 tx_blk_size = tx_size_wide[tx_size];
876
Thomas Daede6ff6af62017-02-03 16:29:24 -0800877// Since av1 does not have separate function which does inverse transform
878// but av1_inv_txfm_add_*x*() also does addition of predicted image to
879// inverse transformed image,
880// pass blank dummy image to av1_inv_txfm_add_*x*(), i.e. set dst as zeros
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200881#if CONFIG_HIGHBITDEPTH
Thomas Daede6ff6af62017-02-03 16:29:24 -0800882 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
883 for (j = 0; j < tx_blk_size; j++)
884 for (i = 0; i < tx_blk_size; i++)
885 CONVERT_TO_SHORTPTR(dst)[j * pd->dst.stride + i] = 0;
886 } else {
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200887#endif // CONFIG_HIGHBITDEPTH
Thomas Daede6ff6af62017-02-03 16:29:24 -0800888 for (j = 0; j < tx_blk_size; j++)
889 for (i = 0; i < tx_blk_size; i++) dst[j * pd->dst.stride + i] = 0;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200890#if CONFIG_HIGHBITDEPTH
Thomas Daede6ff6af62017-02-03 16:29:24 -0800891 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200892#endif // CONFIG_HIGHBITDEPTH
Yushin Cho77bba8d2016-11-04 16:36:56 -0700893 }
Jingning Handf072642016-11-08 16:43:38 -0800894#endif // !CONFIG_PVQ
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200895#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700896 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
897 if (xd->lossless[xd->mi[0]->mbmi.segment_id]) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700898 av1_highbd_iwht4x4_add(dqcoeff, dst, pd->dst.stride, p->eobs[block],
899 xd->bd);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700900 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -0700901 av1_highbd_idct4x4_add(dqcoeff, dst, pd->dst.stride, p->eobs[block],
902 xd->bd);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700903 }
904 return;
905 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200906#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700907 if (xd->lossless[xd->mi[0]->mbmi.segment_id]) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700908 av1_iwht4x4_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700909 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -0700910 av1_idct4x4_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700911 }
912 }
913}
914
Angie Chiangff6d8902016-10-21 11:02:09 -0700915void av1_encode_sby_pass1(AV1_COMMON *cm, MACROBLOCK *x, BLOCK_SIZE bsize) {
916 encode_block_pass1_args args = { cm, x };
Yaowu Xuf883b422016-08-30 14:01:10 -0700917 av1_subtract_plane(x, bsize, 0);
918 av1_foreach_transformed_block_in_plane(&x->e_mbd, bsize, 0,
Angie Chiangff6d8902016-10-21 11:02:09 -0700919 encode_block_pass1, &args);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700920}
921
Yaowu Xu1e4e5b92017-05-05 11:06:42 -0700922void av1_encode_sb(AV1_COMMON *cm, MACROBLOCK *x, BLOCK_SIZE bsize, int mi_row,
923 int mi_col) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700924 MACROBLOCKD *const xd = &x->e_mbd;
925 struct optimize_ctx ctx;
926 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Angie Chiangff6d8902016-10-21 11:02:09 -0700927 struct encode_b_args arg = { cm, x, &ctx, &mbmi->skip, NULL, NULL, 1 };
Yaowu Xuc27fc142016-08-22 16:08:15 -0700928 int plane;
929
930 mbmi->skip = 1;
931
932 if (x->skip) return;
933
934 for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
Jingning Han31b6a4f2017-02-23 11:05:53 -0800935#if CONFIG_CB4X4 && !CONFIG_CHROMA_2X2
Jingning Han2d2dac22017-04-11 09:41:10 -0700936 const int subsampling_x = xd->plane[plane].subsampling_x;
937 const int subsampling_y = xd->plane[plane].subsampling_y;
938
939 if (!is_chroma_reference(mi_row, mi_col, bsize, subsampling_x,
940 subsampling_y))
Jingning Hanea576f32017-02-21 23:05:09 -0800941 continue;
Jingning Han2d2dac22017-04-11 09:41:10 -0700942
943 bsize = scale_chroma_bsize(bsize, subsampling_x, subsampling_y);
Jingning Hanea576f32017-02-21 23:05:09 -0800944#else
945 (void)mi_row;
946 (void)mi_col;
947#endif
948
Yaowu Xuc27fc142016-08-22 16:08:15 -0700949#if CONFIG_VAR_TX
950 // TODO(jingning): Clean this up.
951 const struct macroblockd_plane *const pd = &xd->plane[plane];
952 const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
Jingning Hande953b92016-10-25 12:35:43 -0700953 const int mi_width = block_size_wide[plane_bsize] >> tx_size_wide_log2[0];
954 const int mi_height = block_size_high[plane_bsize] >> tx_size_wide_log2[0];
Sarah Parker106b3cb2017-04-21 12:13:37 -0700955 const TX_SIZE max_tx_size = get_vartx_max_txsize(mbmi, plane_bsize);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700956 const BLOCK_SIZE txb_size = txsize_to_bsize[max_tx_size];
Jingning Hande953b92016-10-25 12:35:43 -0700957 const int bw = block_size_wide[txb_size] >> tx_size_wide_log2[0];
958 const int bh = block_size_high[txb_size] >> tx_size_wide_log2[0];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700959 int idx, idy;
960 int block = 0;
Jingning Hande953b92016-10-25 12:35:43 -0700961 int step = tx_size_wide_unit[max_tx_size] * tx_size_high_unit[max_tx_size];
Jingning Han581d1692017-01-05 16:03:54 -0800962 av1_get_entropy_contexts(bsize, 0, pd, ctx.ta[plane], ctx.tl[plane]);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700963#else
964 const struct macroblockd_plane *const pd = &xd->plane[plane];
Angie Chiang7fcfee42017-02-24 15:51:03 -0800965 const TX_SIZE tx_size = get_tx_size(plane, xd);
Yaowu Xuf883b422016-08-30 14:01:10 -0700966 av1_get_entropy_contexts(bsize, tx_size, pd, ctx.ta[plane], ctx.tl[plane]);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700967#endif
Jingning Hanea576f32017-02-21 23:05:09 -0800968
Yushin Cho77bba8d2016-11-04 16:36:56 -0700969#if !CONFIG_PVQ
Yaowu Xuf883b422016-08-30 14:01:10 -0700970 av1_subtract_plane(x, bsize, plane);
Yushin Cho77bba8d2016-11-04 16:36:56 -0700971#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -0700972 arg.ta = ctx.ta[plane];
973 arg.tl = ctx.tl[plane];
974
975#if CONFIG_VAR_TX
Jingning Hanfe45b212016-11-22 10:30:23 -0800976 for (idy = 0; idy < mi_height; idy += bh) {
977 for (idx = 0; idx < mi_width; idx += bw) {
978 encode_block_inter(plane, block, idy, idx, plane_bsize, max_tx_size,
979 &arg);
980 block += step;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700981 }
Yaowu Xuc27fc142016-08-22 16:08:15 -0700982 }
Yaowu Xuc27fc142016-08-22 16:08:15 -0700983#else
Yaowu Xuf883b422016-08-30 14:01:10 -0700984 av1_foreach_transformed_block_in_plane(xd, bsize, plane, encode_block,
985 &arg);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700986#endif
987 }
988}
989
990#if CONFIG_SUPERTX
Angie Chiangff6d8902016-10-21 11:02:09 -0700991void av1_encode_sb_supertx(AV1_COMMON *cm, MACROBLOCK *x, BLOCK_SIZE bsize) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700992 MACROBLOCKD *const xd = &x->e_mbd;
993 struct optimize_ctx ctx;
994 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Angie Chiangff6d8902016-10-21 11:02:09 -0700995 struct encode_b_args arg = { cm, x, &ctx, &mbmi->skip, NULL, NULL, 1 };
Yaowu Xuc27fc142016-08-22 16:08:15 -0700996 int plane;
997
998 mbmi->skip = 1;
999 if (x->skip) return;
1000
1001 for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
1002 const struct macroblockd_plane *const pd = &xd->plane[plane];
1003#if CONFIG_VAR_TX
1004 const TX_SIZE tx_size = TX_4X4;
1005#else
Angie Chiang7fcfee42017-02-24 15:51:03 -08001006 const TX_SIZE tx_size = get_tx_size(plane, xd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001007#endif
Yaowu Xuf883b422016-08-30 14:01:10 -07001008 av1_subtract_plane(x, bsize, plane);
1009 av1_get_entropy_contexts(bsize, tx_size, pd, ctx.ta[plane], ctx.tl[plane]);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001010 arg.ta = ctx.ta[plane];
1011 arg.tl = ctx.tl[plane];
Yaowu Xuf883b422016-08-30 14:01:10 -07001012 av1_foreach_transformed_block_in_plane(xd, bsize, plane, encode_block,
1013 &arg);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001014 }
1015}
1016#endif // CONFIG_SUPERTX
1017
Yushin Cho6341f5c2017-03-24 14:36:28 -07001018#if !CONFIG_PVQ
Angie Chiangdb0c7d42017-03-23 16:05:37 -07001019void av1_set_txb_context(MACROBLOCK *x, int plane, int block, TX_SIZE tx_size,
Angie Chiang36aca332017-03-23 14:16:24 -07001020 ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l) {
Angie Chiang36aca332017-03-23 14:16:24 -07001021 (void)tx_size;
Angie Chiang36aca332017-03-23 14:16:24 -07001022 struct macroblock_plane *p = &x->plane[plane];
Yushin Cho6341f5c2017-03-24 14:36:28 -07001023
Angie Chiang74e23072017-03-24 14:54:23 -07001024#if !CONFIG_LV_MAP
Angie Chiang36aca332017-03-23 14:16:24 -07001025 *a = *l = p->eobs[block] > 0;
Angie Chiang74e23072017-03-24 14:54:23 -07001026#else // !CONFIG_LV_MAP
1027 *a = *l = p->txb_entropy_ctx[block];
1028#endif // !CONFIG_LV_MAP
Angie Chiangdb0c7d42017-03-23 16:05:37 -07001029
1030#if CONFIG_VAR_TX || CONFIG_LV_MAP
1031 int i;
1032 for (i = 0; i < tx_size_wide_unit[tx_size]; ++i) a[i] = a[0];
1033
1034 for (i = 0; i < tx_size_high_unit[tx_size]; ++i) l[i] = l[0];
1035#endif
Angie Chiang36aca332017-03-23 14:16:24 -07001036}
Yushin Cho6341f5c2017-03-24 14:36:28 -07001037#endif
Angie Chiang36aca332017-03-23 14:16:24 -07001038
1039static void encode_block_intra_and_set_context(int plane, int block,
1040 int blk_row, int blk_col,
1041 BLOCK_SIZE plane_bsize,
1042 TX_SIZE tx_size, void *arg) {
1043 av1_encode_block_intra(plane, block, blk_row, blk_col, plane_bsize, tx_size,
1044 arg);
Yushin Cho6341f5c2017-03-24 14:36:28 -07001045#if !CONFIG_PVQ
Angie Chiang36aca332017-03-23 14:16:24 -07001046 struct encode_b_args *const args = arg;
1047 MACROBLOCK *x = args->x;
1048 ENTROPY_CONTEXT *a = &args->ta[blk_col];
1049 ENTROPY_CONTEXT *l = &args->tl[blk_row];
Angie Chiangdb0c7d42017-03-23 16:05:37 -07001050 av1_set_txb_context(x, plane, block, tx_size, a, l);
Yushin Cho6341f5c2017-03-24 14:36:28 -07001051#endif
Angie Chiang36aca332017-03-23 14:16:24 -07001052}
1053
hui sub8a6fd62017-05-10 10:57:57 -07001054#if CONFIG_DPCM_INTRA
1055static int get_eob(const tran_low_t *qcoeff, intptr_t n_coeffs,
1056 const int16_t *scan) {
1057 int eob = -1;
1058 for (int i = (int)n_coeffs - 1; i >= 0; i--) {
1059 const int rc = scan[i];
1060 if (qcoeff[rc]) {
1061 eob = i;
1062 break;
1063 }
1064 }
1065 return eob + 1;
1066}
1067
1068static void quantize_scaler(int coeff, int16_t zbin, int16_t round_value,
1069 int16_t quant, int16_t quant_shift, int16_t dequant,
1070 int log_scale, tran_low_t *const qcoeff,
1071 tran_low_t *const dqcoeff) {
1072 zbin = ROUND_POWER_OF_TWO(zbin, log_scale);
1073 round_value = ROUND_POWER_OF_TWO(round_value, log_scale);
1074 const int coeff_sign = (coeff >> 31);
1075 const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
1076 if (abs_coeff >= zbin) {
1077 int tmp = clamp(abs_coeff + round_value, INT16_MIN, INT16_MAX);
1078 tmp = ((((tmp * quant) >> 16) + tmp) * quant_shift) >> (16 - log_scale);
1079 *qcoeff = (tmp ^ coeff_sign) - coeff_sign;
1080 *dqcoeff = (*qcoeff * dequant) / (1 << log_scale);
1081 }
1082}
1083
Sarah Parker31c66502017-05-19 16:51:07 -07001084#if CONFIG_HIGHBITDEPTH
1085typedef void (*hbd_dpcm_fwd_tx_func)(const int16_t *input, int stride,
1086 TX_TYPE_1D tx_type, tran_low_t *output,
1087 int dir);
1088
1089static hbd_dpcm_fwd_tx_func get_hbd_dpcm_fwd_tx_func(int tx_length) {
1090 switch (tx_length) {
1091 case 4: return av1_hbd_dpcm_ft4_c;
1092 case 8: return av1_hbd_dpcm_ft8_c;
1093 case 16: return av1_hbd_dpcm_ft16_c;
1094 case 32:
1095 return av1_hbd_dpcm_ft32_c;
1096 // TODO(huisu): add support for TX_64X64.
1097 default: assert(0); return NULL;
1098 }
1099}
1100#endif // CONFIG_HIGHBITDEPTH
1101
hui sub8a6fd62017-05-10 10:57:57 -07001102typedef void (*dpcm_fwd_tx_func)(const int16_t *input, int stride,
1103 TX_TYPE_1D tx_type, tran_low_t *output);
1104
1105static dpcm_fwd_tx_func get_dpcm_fwd_tx_func(int tx_length) {
1106 switch (tx_length) {
1107 case 4: return av1_dpcm_ft4_c;
1108 case 8: return av1_dpcm_ft8_c;
1109 case 16: return av1_dpcm_ft16_c;
1110 case 32:
1111 return av1_dpcm_ft32_c;
1112 // TODO(huisu): add support for TX_64X64.
1113 default: assert(0); return NULL;
1114 }
1115}
1116
1117static void process_block_dpcm_vert(TX_SIZE tx_size, TX_TYPE_1D tx_type_1d,
1118 struct macroblockd_plane *const pd,
1119 struct macroblock_plane *const p,
1120 uint8_t *src, int src_stride, uint8_t *dst,
1121 int dst_stride, int16_t *src_diff,
1122 int diff_stride, tran_low_t *coeff,
1123 tran_low_t *qcoeff, tran_low_t *dqcoeff) {
1124 const int tx1d_width = tx_size_wide[tx_size];
1125 dpcm_fwd_tx_func forward_tx = get_dpcm_fwd_tx_func(tx1d_width);
1126 dpcm_inv_txfm_add_func inverse_tx =
1127 av1_get_dpcm_inv_txfm_add_func(tx1d_width);
1128 const int tx1d_height = tx_size_high[tx_size];
1129 const int log_scale = av1_get_tx_scale(tx_size);
1130 int q_idx = 0;
1131 for (int r = 0; r < tx1d_height; ++r) {
1132 // Update prediction.
1133 if (r > 0) memcpy(dst, dst - dst_stride, tx1d_width * sizeof(dst[0]));
1134 // Subtraction.
1135 for (int c = 0; c < tx1d_width; ++c) src_diff[c] = src[c] - dst[c];
1136 // Forward transform.
1137 forward_tx(src_diff, 1, tx_type_1d, coeff);
1138 // Quantization.
1139 for (int c = 0; c < tx1d_width; ++c) {
1140 quantize_scaler(coeff[c], p->zbin[q_idx], p->round[q_idx],
1141 p->quant[q_idx], p->quant_shift[q_idx],
1142 pd->dequant[q_idx], log_scale, &qcoeff[c], &dqcoeff[c]);
1143 q_idx = 1;
1144 }
1145 // Inverse transform.
1146 inverse_tx(dqcoeff, 1, tx_type_1d, dst);
1147 // Move to the next row.
1148 coeff += tx1d_width;
1149 qcoeff += tx1d_width;
1150 dqcoeff += tx1d_width;
1151 src_diff += diff_stride;
1152 dst += dst_stride;
1153 src += src_stride;
1154 }
1155}
1156
1157static void process_block_dpcm_horz(TX_SIZE tx_size, TX_TYPE_1D tx_type_1d,
1158 struct macroblockd_plane *const pd,
1159 struct macroblock_plane *const p,
1160 uint8_t *src, int src_stride, uint8_t *dst,
1161 int dst_stride, int16_t *src_diff,
1162 int diff_stride, tran_low_t *coeff,
1163 tran_low_t *qcoeff, tran_low_t *dqcoeff) {
1164 const int tx1d_height = tx_size_high[tx_size];
1165 dpcm_fwd_tx_func forward_tx = get_dpcm_fwd_tx_func(tx1d_height);
1166 dpcm_inv_txfm_add_func inverse_tx =
1167 av1_get_dpcm_inv_txfm_add_func(tx1d_height);
1168 const int tx1d_width = tx_size_wide[tx_size];
1169 const int log_scale = av1_get_tx_scale(tx_size);
1170 int q_idx = 0;
1171 for (int c = 0; c < tx1d_width; ++c) {
1172 for (int r = 0; r < tx1d_height; ++r) {
1173 // Update prediction.
1174 if (c > 0) dst[r * dst_stride] = dst[r * dst_stride - 1];
1175 // Subtraction.
1176 src_diff[r * diff_stride] = src[r * src_stride] - dst[r * dst_stride];
1177 }
1178 // Forward transform.
1179 tran_low_t tx_buff[64];
1180 forward_tx(src_diff, diff_stride, tx_type_1d, tx_buff);
1181 for (int r = 0; r < tx1d_height; ++r) coeff[r * tx1d_width] = tx_buff[r];
1182 // Quantization.
1183 for (int r = 0; r < tx1d_height; ++r) {
1184 quantize_scaler(coeff[r * tx1d_width], p->zbin[q_idx], p->round[q_idx],
1185 p->quant[q_idx], p->quant_shift[q_idx],
1186 pd->dequant[q_idx], log_scale, &qcoeff[r * tx1d_width],
1187 &dqcoeff[r * tx1d_width]);
1188 q_idx = 1;
1189 }
1190 // Inverse transform.
1191 for (int r = 0; r < tx1d_height; ++r) tx_buff[r] = dqcoeff[r * tx1d_width];
1192 inverse_tx(tx_buff, dst_stride, tx_type_1d, dst);
1193 // Move to the next column.
1194 ++coeff, ++qcoeff, ++dqcoeff, ++src_diff, ++dst, ++src;
1195 }
1196}
1197
1198#if CONFIG_HIGHBITDEPTH
1199static void hbd_process_block_dpcm_vert(
1200 TX_SIZE tx_size, TX_TYPE_1D tx_type_1d, int bd,
1201 struct macroblockd_plane *const pd, struct macroblock_plane *const p,
1202 uint8_t *src8, int src_stride, uint8_t *dst8, int dst_stride,
1203 int16_t *src_diff, int diff_stride, tran_low_t *coeff, tran_low_t *qcoeff,
1204 tran_low_t *dqcoeff) {
1205 const int tx1d_width = tx_size_wide[tx_size];
Sarah Parker31c66502017-05-19 16:51:07 -07001206 hbd_dpcm_fwd_tx_func forward_tx = get_hbd_dpcm_fwd_tx_func(tx1d_width);
hui sub8a6fd62017-05-10 10:57:57 -07001207 hbd_dpcm_inv_txfm_add_func inverse_tx =
1208 av1_get_hbd_dpcm_inv_txfm_add_func(tx1d_width);
1209 uint16_t *src = CONVERT_TO_SHORTPTR(src8);
1210 uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
1211 const int tx1d_height = tx_size_high[tx_size];
1212 const int log_scale = av1_get_tx_scale(tx_size);
1213 int q_idx = 0;
1214 for (int r = 0; r < tx1d_height; ++r) {
1215 // Update prediction.
1216 if (r > 0) memcpy(dst, dst - dst_stride, tx1d_width * sizeof(dst[0]));
1217 // Subtraction.
1218 for (int c = 0; c < tx1d_width; ++c) src_diff[c] = src[c] - dst[c];
1219 // Forward transform.
Sarah Parker31c66502017-05-19 16:51:07 -07001220 forward_tx(src_diff, 1, tx_type_1d, coeff, 1);
hui sub8a6fd62017-05-10 10:57:57 -07001221 // Quantization.
1222 for (int c = 0; c < tx1d_width; ++c) {
1223 quantize_scaler(coeff[c], p->zbin[q_idx], p->round[q_idx],
1224 p->quant[q_idx], p->quant_shift[q_idx],
1225 pd->dequant[q_idx], log_scale, &qcoeff[c], &dqcoeff[c]);
1226 q_idx = 1;
1227 }
1228 // Inverse transform.
Sarah Parker31c66502017-05-19 16:51:07 -07001229 inverse_tx(dqcoeff, 1, tx_type_1d, bd, dst, 1);
hui sub8a6fd62017-05-10 10:57:57 -07001230 // Move to the next row.
1231 coeff += tx1d_width;
1232 qcoeff += tx1d_width;
1233 dqcoeff += tx1d_width;
1234 src_diff += diff_stride;
1235 dst += dst_stride;
1236 src += src_stride;
1237 }
1238}
1239
1240static void hbd_process_block_dpcm_horz(
1241 TX_SIZE tx_size, TX_TYPE_1D tx_type_1d, int bd,
1242 struct macroblockd_plane *const pd, struct macroblock_plane *const p,
1243 uint8_t *src8, int src_stride, uint8_t *dst8, int dst_stride,
1244 int16_t *src_diff, int diff_stride, tran_low_t *coeff, tran_low_t *qcoeff,
1245 tran_low_t *dqcoeff) {
1246 const int tx1d_height = tx_size_high[tx_size];
Sarah Parker31c66502017-05-19 16:51:07 -07001247 hbd_dpcm_fwd_tx_func forward_tx = get_hbd_dpcm_fwd_tx_func(tx1d_height);
hui sub8a6fd62017-05-10 10:57:57 -07001248 hbd_dpcm_inv_txfm_add_func inverse_tx =
1249 av1_get_hbd_dpcm_inv_txfm_add_func(tx1d_height);
1250 uint16_t *src = CONVERT_TO_SHORTPTR(src8);
1251 uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
1252 const int tx1d_width = tx_size_wide[tx_size];
1253 const int log_scale = av1_get_tx_scale(tx_size);
1254 int q_idx = 0;
1255 for (int c = 0; c < tx1d_width; ++c) {
1256 for (int r = 0; r < tx1d_height; ++r) {
1257 // Update prediction.
1258 if (c > 0) dst[r * dst_stride] = dst[r * dst_stride - 1];
1259 // Subtraction.
1260 src_diff[r * diff_stride] = src[r * src_stride] - dst[r * dst_stride];
1261 }
1262 // Forward transform.
1263 tran_low_t tx_buff[64];
Sarah Parker31c66502017-05-19 16:51:07 -07001264 forward_tx(src_diff, diff_stride, tx_type_1d, tx_buff, 0);
hui sub8a6fd62017-05-10 10:57:57 -07001265 for (int r = 0; r < tx1d_height; ++r) coeff[r * tx1d_width] = tx_buff[r];
1266 // Quantization.
1267 for (int r = 0; r < tx1d_height; ++r) {
1268 quantize_scaler(coeff[r * tx1d_width], p->zbin[q_idx], p->round[q_idx],
1269 p->quant[q_idx], p->quant_shift[q_idx],
1270 pd->dequant[q_idx], log_scale, &qcoeff[r * tx1d_width],
1271 &dqcoeff[r * tx1d_width]);
1272 q_idx = 1;
1273 }
1274 // Inverse transform.
1275 for (int r = 0; r < tx1d_height; ++r) tx_buff[r] = dqcoeff[r * tx1d_width];
Sarah Parker31c66502017-05-19 16:51:07 -07001276 inverse_tx(tx_buff, dst_stride, tx_type_1d, bd, dst, 0);
hui sub8a6fd62017-05-10 10:57:57 -07001277 // Move to the next column.
1278 ++coeff, ++qcoeff, ++dqcoeff, ++src_diff, ++dst, ++src;
1279 }
1280}
1281#endif // CONFIG_HIGHBITDEPTH
1282
1283void av1_encode_block_intra_dpcm(const AV1_COMMON *cm, MACROBLOCK *x,
1284 PREDICTION_MODE mode, int plane, int block,
1285 int blk_row, int blk_col,
1286 BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
1287 TX_TYPE tx_type, ENTROPY_CONTEXT *ta,
1288 ENTROPY_CONTEXT *tl, int8_t *skip) {
1289 MACROBLOCKD *const xd = &x->e_mbd;
1290 struct macroblock_plane *const p = &x->plane[plane];
1291 struct macroblockd_plane *const pd = &xd->plane[plane];
1292 tran_low_t *dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
1293 const int diff_stride = block_size_wide[plane_bsize];
1294 const int src_stride = p->src.stride;
1295 const int dst_stride = pd->dst.stride;
1296 const int tx1d_width = tx_size_wide[tx_size];
1297 const int tx1d_height = tx_size_high[tx_size];
1298 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, 0);
1299 tran_low_t *coeff = BLOCK_OFFSET(p->coeff, block);
1300 tran_low_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block);
1301 uint8_t *dst =
1302 &pd->dst.buf[(blk_row * dst_stride + blk_col) << tx_size_wide_log2[0]];
1303 uint8_t *src =
1304 &p->src.buf[(blk_row * src_stride + blk_col) << tx_size_wide_log2[0]];
1305 int16_t *src_diff =
1306 &p->src_diff[(blk_row * diff_stride + blk_col) << tx_size_wide_log2[0]];
1307 uint16_t *eob = &p->eobs[block];
1308 *eob = 0;
1309 memset(qcoeff, 0, tx1d_height * tx1d_width * sizeof(*qcoeff));
1310 memset(dqcoeff, 0, tx1d_height * tx1d_width * sizeof(*dqcoeff));
1311
1312 if (LIKELY(!x->skip_block)) {
1313 TX_TYPE_1D tx_type_1d = DCT_1D;
1314 switch (tx_type) {
1315 case IDTX: tx_type_1d = IDTX_1D; break;
1316 case V_DCT:
1317 assert(mode == H_PRED);
1318 tx_type_1d = DCT_1D;
1319 break;
1320 case H_DCT:
1321 assert(mode == V_PRED);
1322 tx_type_1d = DCT_1D;
1323 break;
1324 default: assert(0);
1325 }
1326 switch (mode) {
1327 case V_PRED:
1328#if CONFIG_HIGHBITDEPTH
1329 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
1330 hbd_process_block_dpcm_vert(tx_size, tx_type_1d, xd->bd, pd, p, src,
1331 src_stride, dst, dst_stride, src_diff,
1332 diff_stride, coeff, qcoeff, dqcoeff);
1333 } else {
1334#endif // CONFIG_HIGHBITDEPTH
1335 process_block_dpcm_vert(tx_size, tx_type_1d, pd, p, src, src_stride,
1336 dst, dst_stride, src_diff, diff_stride, coeff,
1337 qcoeff, dqcoeff);
1338#if CONFIG_HIGHBITDEPTH
1339 }
1340#endif // CONFIG_HIGHBITDEPTH
1341 break;
1342 case H_PRED:
1343#if CONFIG_HIGHBITDEPTH
1344 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
1345 hbd_process_block_dpcm_horz(tx_size, tx_type_1d, xd->bd, pd, p, src,
1346 src_stride, dst, dst_stride, src_diff,
1347 diff_stride, coeff, qcoeff, dqcoeff);
1348 } else {
1349#endif // CONFIG_HIGHBITDEPTH
1350 process_block_dpcm_horz(tx_size, tx_type_1d, pd, p, src, src_stride,
1351 dst, dst_stride, src_diff, diff_stride, coeff,
1352 qcoeff, dqcoeff);
1353#if CONFIG_HIGHBITDEPTH
1354 }
1355#endif // CONFIG_HIGHBITDEPTH
1356 break;
1357 default: assert(0);
1358 }
1359 *eob = get_eob(qcoeff, tx1d_height * tx1d_width, scan_order->scan);
1360 }
1361
1362 ta[blk_col] = tl[blk_row] = *eob > 0;
1363 if (*eob) *skip = 0;
1364}
1365#endif // CONFIG_DPCM_INTRA
1366
Yaowu Xuf883b422016-08-30 14:01:10 -07001367void av1_encode_block_intra(int plane, int block, int blk_row, int blk_col,
1368 BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
1369 void *arg) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07001370 struct encode_b_args *const args = arg;
Angie Chiangff6d8902016-10-21 11:02:09 -07001371 AV1_COMMON *cm = args->cm;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001372 MACROBLOCK *const x = args->x;
1373 MACROBLOCKD *const xd = &x->e_mbd;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001374 struct macroblock_plane *const p = &x->plane[plane];
1375 struct macroblockd_plane *const pd = &xd->plane[plane];
1376 tran_low_t *dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
Luc Trudeau005feb62017-02-22 13:34:01 -05001377 PLANE_TYPE plane_type = get_plane_type(plane);
Angie Chiang752ccce2017-04-09 13:41:13 -07001378 const TX_TYPE tx_type = get_tx_type(plane_type, xd, block, tx_size);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001379 uint16_t *eob = &p->eobs[block];
Yaowu Xuc27fc142016-08-22 16:08:15 -07001380 const int dst_stride = pd->dst.stride;
Angie Chiangf87e43f2017-04-02 16:51:19 -07001381 uint8_t *dst =
1382 &pd->dst.buf[(blk_row * dst_stride + blk_col) << tx_size_wide_log2[0]];
Luc Trudeauf5334002017-04-25 12:21:26 -04001383#if CONFIG_CFL
Luc Trudeaue8dfbcf2017-05-12 09:57:50 -04001384
1385#if CONFIG_EC_ADAPT
1386 FRAME_CONTEXT *const ec_ctx = xd->tile_ctx;
1387#else
1388 FRAME_CONTEXT *const ec_ctx = cm->fc;
1389#endif // CONFIG_EC_ADAPT
1390
1391 av1_predict_intra_block_encoder_facade(x, ec_ctx, plane, block, blk_col,
1392 blk_row, tx_size, plane_bsize);
Luc Trudeauf5334002017-04-25 12:21:26 -04001393#else
Angie Chiang752ccce2017-04-09 13:41:13 -07001394 av1_predict_intra_block_facade(xd, plane, block, blk_col, blk_row, tx_size);
Luc Trudeauf5334002017-04-25 12:21:26 -04001395#endif
hui sub8a6fd62017-05-10 10:57:57 -07001396
1397#if CONFIG_DPCM_INTRA
1398 const int block_raster_idx = av1_block_index_to_raster_order(tx_size, block);
1399 const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
1400 const PREDICTION_MODE mode =
1401 (plane == 0) ? get_y_mode(xd->mi[0], block_raster_idx) : mbmi->uv_mode;
1402 if (av1_use_dpcm_intra(plane, mode, tx_type, mbmi)) {
1403 av1_encode_block_intra_dpcm(cm, x, mode, plane, block, blk_row, blk_col,
1404 plane_bsize, tx_size, tx_type, args->ta,
1405 args->tl, args->skip);
1406 return;
1407 }
1408#endif // CONFIG_DPCM_INTRA
1409
Angie Chiangf87e43f2017-04-02 16:51:19 -07001410 av1_subtract_txb(x, plane, plane_bsize, blk_col, blk_row, tx_size);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001411
Angie Chiang36aca332017-03-23 14:16:24 -07001412 const ENTROPY_CONTEXT *a = &args->ta[blk_col];
1413 const ENTROPY_CONTEXT *l = &args->tl[blk_row];
Angie Chiang57605532017-04-03 11:51:15 -07001414 int ctx = combine_entropy_contexts(*a, *l);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001415 if (args->enable_optimize_b) {
Angie Chiangff6d8902016-10-21 11:02:09 -07001416 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
Debargha Mukherjeef0305582016-11-24 09:55:34 -08001417 ctx, AV1_XFORM_QUANT_FP);
Angie Chiang3511c372017-05-31 12:47:07 -07001418 av1_optimize_b(cm, x, plane, block, plane_bsize, tx_size, a, l);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001419 } else {
Debargha Mukherjeef0305582016-11-24 09:55:34 -08001420 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
1421 ctx, AV1_XFORM_QUANT_B);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001422 }
1423
Angie Chiang57605532017-04-03 11:51:15 -07001424#if CONFIG_PVQ
Yushin Cho3827fdd2016-11-09 15:50:23 -08001425 // *(args->skip) == mbmi->skip
1426 if (!x->pvq_skip[plane]) *(args->skip) = 0;
1427
1428 if (x->pvq_skip[plane]) return;
Angie Chiang50910f62017-04-03 12:31:34 -07001429#endif // CONFIG_PVQ
Angie Chiangd92d4bf2017-04-02 17:49:18 -07001430 av1_inverse_transform_block(xd, dqcoeff, tx_type, tx_size, dst, dst_stride,
1431 *eob);
Yushin Cho77bba8d2016-11-04 16:36:56 -07001432#if !CONFIG_PVQ
1433 if (*eob) *(args->skip) = 0;
1434#else
1435// Note : *(args->skip) == mbmi->skip
1436#endif
Luc Trudeaue3980282017-04-25 23:17:21 -04001437#if CONFIG_CFL
Luc Trudeauf5334002017-04-25 12:21:26 -04001438 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Luc Trudeaue3980282017-04-25 23:17:21 -04001439 if (plane == AOM_PLANE_Y && x->cfl_store_y) {
1440 cfl_store(xd->cfl, dst, dst_stride, blk_row, blk_col, tx_size);
1441 }
Luc Trudeauf5334002017-04-25 12:21:26 -04001442
1443 if (mbmi->uv_mode == DC_PRED) {
1444 // TODO(ltrudeau) find a cleaner way to detect last transform block
1445 if (plane == AOM_PLANE_U) {
1446 xd->cfl->num_tx_blk[CFL_PRED_U] =
1447 (blk_row == 0 && blk_col == 0) ? 1
1448 : xd->cfl->num_tx_blk[CFL_PRED_U] + 1;
1449 }
1450
1451 if (plane == AOM_PLANE_V) {
1452 xd->cfl->num_tx_blk[CFL_PRED_V] =
1453 (blk_row == 0 && blk_col == 0) ? 1
1454 : xd->cfl->num_tx_blk[CFL_PRED_V] + 1;
1455
1456 if (mbmi->skip &&
1457 xd->cfl->num_tx_blk[CFL_PRED_U] == xd->cfl->num_tx_blk[CFL_PRED_V]) {
1458 assert(plane_bsize != BLOCK_INVALID);
1459 const int block_width = block_size_wide[plane_bsize];
1460 const int block_height = block_size_high[plane_bsize];
1461
1462 // if SKIP is chosen at the block level, and ind != 0, we must change
1463 // the prediction
Luc Trudeaua9bd85f2017-05-11 14:37:56 -04001464 if (mbmi->cfl_alpha_idx != 0) {
Luc Trudeauf5334002017-04-25 12:21:26 -04001465 const struct macroblockd_plane *const pd_cb = &xd->plane[AOM_PLANE_U];
1466 uint8_t *const dst_cb = pd_cb->dst.buf;
1467 const int dst_stride_cb = pd_cb->dst.stride;
1468 uint8_t *const dst_cr = pd->dst.buf;
1469 const int dst_stride_cr = pd->dst.stride;
1470 for (int j = 0; j < block_height; j++) {
1471 for (int i = 0; i < block_width; i++) {
1472 dst_cb[dst_stride_cb * j + i] =
1473 (uint8_t)(xd->cfl->dc_pred[CFL_PRED_U] + 0.5);
1474 dst_cr[dst_stride_cr * j + i] =
1475 (uint8_t)(xd->cfl->dc_pred[CFL_PRED_V] + 0.5);
1476 }
1477 }
Luc Trudeaua9bd85f2017-05-11 14:37:56 -04001478 mbmi->cfl_alpha_idx = 0;
Luc Trudeauf5334002017-04-25 12:21:26 -04001479 mbmi->cfl_alpha_signs[CFL_PRED_U] = CFL_SIGN_POS;
1480 mbmi->cfl_alpha_signs[CFL_PRED_V] = CFL_SIGN_POS;
1481 }
1482 }
1483 }
1484 }
Luc Trudeaue3980282017-04-25 23:17:21 -04001485#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07001486}
1487
Luc Trudeauf5334002017-04-25 12:21:26 -04001488#if CONFIG_CFL
David Michael Barrd3b01b82017-04-27 19:58:52 +09001489static int cfl_alpha_dist(const uint8_t *y_pix, int y_stride, double y_avg,
1490 const uint8_t *src, int src_stride, int blk_width,
1491 int blk_height, double dc_pred, double alpha,
1492 int *dist_neg_out) {
1493 const double dc_pred_bias = dc_pred + 0.5;
1494 int dist = 0;
1495 int diff;
Luc Trudeauf5334002017-04-25 12:21:26 -04001496
David Michael Barrd3b01b82017-04-27 19:58:52 +09001497 if (alpha == 0.0) {
1498 const int dc_pred_i = (int)dc_pred_bias;
1499 for (int j = 0; j < blk_height; j++) {
1500 for (int i = 0; i < blk_width; i++) {
1501 diff = src[i] - dc_pred_i;
1502 dist += diff * diff;
1503 }
1504 src += src_stride;
1505 }
1506
1507 if (dist_neg_out) *dist_neg_out = dist;
1508
1509 return dist;
1510 }
1511
1512 int dist_neg = 0;
1513 for (int j = 0; j < blk_height; j++) {
1514 for (int i = 0; i < blk_width; i++) {
1515 const double scaled_luma = alpha * (y_pix[i] - y_avg);
1516 const int uv = src[i];
1517 diff = uv - (int)(scaled_luma + dc_pred_bias);
1518 dist += diff * diff;
1519 diff = uv + (int)(scaled_luma - dc_pred_bias);
1520 dist_neg += diff * diff;
1521 }
1522 y_pix += y_stride;
1523 src += src_stride;
1524 }
1525
1526 if (dist_neg_out) *dist_neg_out = dist_neg;
1527
1528 return dist;
1529}
1530
1531static int cfl_compute_alpha_ind(MACROBLOCK *const x, const CFL_CTX *const cfl,
Luc Trudeau060e1eb2017-05-12 14:47:11 -04001532 BLOCK_SIZE bsize,
1533 CFL_SIGN_TYPE signs_out[CFL_SIGNS]) {
David Michael Barrd3b01b82017-04-27 19:58:52 +09001534 const struct macroblock_plane *const p_u = &x->plane[AOM_PLANE_U];
1535 const struct macroblock_plane *const p_v = &x->plane[AOM_PLANE_V];
1536 const uint8_t *const src_u = p_u->src.buf;
1537 const uint8_t *const src_v = p_v->src.buf;
1538 const int src_stride_u = p_u->src.stride;
1539 const int src_stride_v = p_v->src.stride;
1540 const int block_width = block_size_wide[bsize];
1541 const int block_height = block_size_high[bsize];
1542 const double dc_pred_u = cfl->dc_pred[CFL_PRED_U];
1543 const double dc_pred_v = cfl->dc_pred[CFL_PRED_V];
1544
1545 // Temporary pixel buffer used to store the CfL prediction when we compute the
1546 // alpha index.
1547 uint8_t tmp_pix[MAX_SB_SQUARE];
1548 // Load CfL Prediction over the entire block
1549 const double y_avg =
Luc Trudeau30596fb2017-05-08 11:35:25 -04001550 cfl_load(cfl, tmp_pix, MAX_SB_SIZE, 0, 0, block_width, block_height);
David Michael Barrd3b01b82017-04-27 19:58:52 +09001551
David Michael Barr84a44db2017-05-16 23:31:09 +09001552 int sse[CFL_PRED_PLANES][CFL_MAGS_SIZE];
1553 sse[CFL_PRED_U][0] =
1554 cfl_alpha_dist(tmp_pix, MAX_SB_SIZE, y_avg, src_u, src_stride_u,
1555 block_width, block_height, dc_pred_u, 0, NULL);
1556 sse[CFL_PRED_V][0] =
1557 cfl_alpha_dist(tmp_pix, MAX_SB_SIZE, y_avg, src_v, src_stride_v,
1558 block_width, block_height, dc_pred_v, 0, NULL);
1559 for (int m = 1; m < CFL_MAGS_SIZE; m += 2) {
1560 assert(cfl_alpha_mags[m + 1] == -cfl_alpha_mags[m]);
1561 sse[CFL_PRED_U][m] = cfl_alpha_dist(
1562 tmp_pix, MAX_SB_SIZE, y_avg, src_u, src_stride_u, block_width,
1563 block_height, dc_pred_u, cfl_alpha_mags[m], &sse[CFL_PRED_U][m + 1]);
1564 sse[CFL_PRED_V][m] = cfl_alpha_dist(
1565 tmp_pix, MAX_SB_SIZE, y_avg, src_v, src_stride_v, block_width,
1566 block_height, dc_pred_v, cfl_alpha_mags[m], &sse[CFL_PRED_V][m + 1]);
1567 }
1568
David Michael Barrd3b01b82017-04-27 19:58:52 +09001569 int dist;
1570 int64_t cost;
1571 int64_t best_cost;
1572
1573 // Compute least squares parameter of the entire block
1574 // IMPORTANT: We assume that the first code is 0,0
1575 int ind = 0;
Luc Trudeau060e1eb2017-05-12 14:47:11 -04001576 signs_out[CFL_PRED_U] = CFL_SIGN_POS;
1577 signs_out[CFL_PRED_V] = CFL_SIGN_POS;
David Michael Barrd3b01b82017-04-27 19:58:52 +09001578
David Michael Barr84a44db2017-05-16 23:31:09 +09001579 dist = sse[CFL_PRED_U][0] + sse[CFL_PRED_V][0];
David Michael Barrd3b01b82017-04-27 19:58:52 +09001580 dist *= 16;
Luc Trudeau1a474302017-05-12 10:21:31 -04001581 best_cost = RDCOST(x->rdmult, x->rddiv, cfl->costs[0], dist);
David Michael Barrd3b01b82017-04-27 19:58:52 +09001582
1583 for (int c = 1; c < CFL_ALPHABET_SIZE; c++) {
David Michael Barr84a44db2017-05-16 23:31:09 +09001584 const int idx_u = cfl_alpha_codes[c][CFL_PRED_U];
1585 const int idx_v = cfl_alpha_codes[c][CFL_PRED_V];
1586 for (CFL_SIGN_TYPE sign_u = idx_u == 0; sign_u < CFL_SIGNS; sign_u++) {
1587 for (CFL_SIGN_TYPE sign_v = idx_v == 0; sign_v < CFL_SIGNS; sign_v++) {
1588 dist = sse[CFL_PRED_U][idx_u + (sign_u == CFL_SIGN_NEG)] +
1589 sse[CFL_PRED_V][idx_v + (sign_v == CFL_SIGN_NEG)];
David Michael Barrd3b01b82017-04-27 19:58:52 +09001590 dist *= 16;
Luc Trudeau1a474302017-05-12 10:21:31 -04001591 cost = RDCOST(x->rdmult, x->rddiv, cfl->costs[c], dist);
David Michael Barrd3b01b82017-04-27 19:58:52 +09001592 if (cost < best_cost) {
1593 best_cost = cost;
1594 ind = c;
Luc Trudeau060e1eb2017-05-12 14:47:11 -04001595 signs_out[CFL_PRED_U] = sign_u;
1596 signs_out[CFL_PRED_V] = sign_v;
David Michael Barrd3b01b82017-04-27 19:58:52 +09001597 }
1598 }
1599 }
1600 }
1601
1602 return ind;
1603}
1604
Luc Trudeau1a474302017-05-12 10:21:31 -04001605static inline void cfl_update_costs(CFL_CTX *cfl, FRAME_CONTEXT *ec_ctx) {
1606 assert(ec_ctx->cfl_alpha_cdf[CFL_ALPHABET_SIZE - 1] ==
1607 AOM_ICDF(CDF_PROB_TOP));
1608 const int prob_den = CDF_PROB_TOP;
1609
1610 int prob_num = AOM_ICDF(ec_ctx->cfl_alpha_cdf[0]);
1611 cfl->costs[0] = av1_cost_zero(get_prob(prob_num, prob_den));
1612
1613 for (int c = 1; c < CFL_ALPHABET_SIZE; c++) {
David Michael Barr84a44db2017-05-16 23:31:09 +09001614 int sign_bit_cost = (cfl_alpha_codes[c][CFL_PRED_U] != 0) +
1615 (cfl_alpha_codes[c][CFL_PRED_V] != 0);
Luc Trudeau1a474302017-05-12 10:21:31 -04001616 prob_num = AOM_ICDF(ec_ctx->cfl_alpha_cdf[c]) -
1617 AOM_ICDF(ec_ctx->cfl_alpha_cdf[c - 1]);
1618 cfl->costs[c] = av1_cost_zero(get_prob(prob_num, prob_den)) +
1619 av1_cost_literal(sign_bit_cost);
1620 }
1621}
1622
Luc Trudeaue8dfbcf2017-05-12 09:57:50 -04001623void av1_predict_intra_block_encoder_facade(MACROBLOCK *x,
1624 FRAME_CONTEXT *ec_ctx, int plane,
David Michael Barrd3b01b82017-04-27 19:58:52 +09001625 int block_idx, int blk_col,
1626 int blk_row, TX_SIZE tx_size,
1627 BLOCK_SIZE plane_bsize) {
1628 MACROBLOCKD *const xd = &x->e_mbd;
1629 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
David Michael Barrd3b01b82017-04-27 19:58:52 +09001630 if (plane != AOM_PLANE_Y && mbmi->uv_mode == DC_PRED) {
1631 if (blk_col == 0 && blk_row == 0 && plane == AOM_PLANE_U) {
David Michael Barrd3b01b82017-04-27 19:58:52 +09001632 CFL_CTX *const cfl = xd->cfl;
Luc Trudeau1a474302017-05-12 10:21:31 -04001633 cfl_update_costs(cfl, ec_ctx);
David Michael Barrd3b01b82017-04-27 19:58:52 +09001634 cfl_dc_pred(xd, plane_bsize, tx_size);
Luc Trudeau1a474302017-05-12 10:21:31 -04001635 mbmi->cfl_alpha_idx =
1636 cfl_compute_alpha_ind(x, cfl, plane_bsize, mbmi->cfl_alpha_signs);
David Michael Barrd3b01b82017-04-27 19:58:52 +09001637 }
1638 }
Luc Trudeauf5334002017-04-25 12:21:26 -04001639 av1_predict_intra_block_facade(xd, plane, block_idx, blk_col, blk_row,
1640 tx_size);
1641}
1642#endif
1643
Angie Chiangff6d8902016-10-21 11:02:09 -07001644void av1_encode_intra_block_plane(AV1_COMMON *cm, MACROBLOCK *x,
1645 BLOCK_SIZE bsize, int plane,
Yaowu Xu1e4e5b92017-05-05 11:06:42 -07001646 int enable_optimize_b, int mi_row,
1647 int mi_col) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07001648 const MACROBLOCKD *const xd = &x->e_mbd;
Guillaume Martrese50d9dd2016-12-18 18:26:47 +01001649 ENTROPY_CONTEXT ta[2 * MAX_MIB_SIZE] = { 0 };
1650 ENTROPY_CONTEXT tl[2 * MAX_MIB_SIZE] = { 0 };
Yaowu Xuc27fc142016-08-22 16:08:15 -07001651
Angie Chiangff6d8902016-10-21 11:02:09 -07001652 struct encode_b_args arg = {
1653 cm, x, NULL, &xd->mi[0]->mbmi.skip, ta, tl, enable_optimize_b
1654 };
Jingning Han18c53c82017-02-17 14:49:57 -08001655
1656#if CONFIG_CB4X4
Jingning Hand3a64432017-04-06 17:04:17 -07001657 if (!is_chroma_reference(mi_row, mi_col, bsize,
1658 xd->plane[plane].subsampling_x,
1659 xd->plane[plane].subsampling_y))
Jingning Han18c53c82017-02-17 14:49:57 -08001660 return;
1661#else
1662 (void)mi_row;
1663 (void)mi_col;
1664#endif
1665
Yaowu Xuc27fc142016-08-22 16:08:15 -07001666 if (enable_optimize_b) {
1667 const struct macroblockd_plane *const pd = &xd->plane[plane];
Angie Chiang7fcfee42017-02-24 15:51:03 -08001668 const TX_SIZE tx_size = get_tx_size(plane, xd);
Yaowu Xuf883b422016-08-30 14:01:10 -07001669 av1_get_entropy_contexts(bsize, tx_size, pd, ta, tl);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001670 }
Angie Chiang36aca332017-03-23 14:16:24 -07001671 av1_foreach_transformed_block_in_plane(
1672 xd, bsize, plane, encode_block_intra_and_set_context, &arg);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001673}
Yushin Cho77bba8d2016-11-04 16:36:56 -07001674
1675#if CONFIG_PVQ
Thomas Daede6ff6af62017-02-03 16:29:24 -08001676PVQ_SKIP_TYPE av1_pvq_encode_helper(MACROBLOCK *x, tran_low_t *const coeff,
1677 tran_low_t *ref_coeff,
1678 tran_low_t *const dqcoeff, uint16_t *eob,
1679 const int16_t *quant, int plane,
1680 int tx_size, TX_TYPE tx_type, int *rate,
1681 int speed, PVQ_INFO *pvq_info) {
Yushin Cho77bba8d2016-11-04 16:36:56 -07001682 const int tx_blk_size = tx_size_wide[tx_size];
Thomas Daede6ff6af62017-02-03 16:29:24 -08001683 daala_enc_ctx *daala_enc = &x->daala_enc;
ltrudeaue1c09292017-01-20 15:42:13 -05001684 PVQ_SKIP_TYPE ac_dc_coded;
Jingning Hanff705452017-04-27 11:32:15 -07001685 int coeff_shift = 3 - av1_get_tx_scale(tx_size);
Thomas Daede6ff6af62017-02-03 16:29:24 -08001686 int hbd_downshift = 0;
Timothy B. Terriberrye93acb22017-02-06 13:55:53 -08001687 int rounding_mask;
Yushin Cho70669122016-12-08 09:53:14 -10001688 int pvq_dc_quant;
1689 int use_activity_masking = daala_enc->use_activity_masking;
Yushin Cho77bba8d2016-11-04 16:36:56 -07001690 int tell;
1691 int has_dc_skip = 1;
1692 int i;
1693 int off = od_qm_offset(tx_size, plane ? 1 : 0);
Yushin Cho70669122016-12-08 09:53:14 -10001694
Thomas Daede1dbda1b2017-02-06 16:06:29 -08001695 DECLARE_ALIGNED(16, tran_low_t, coeff_pvq[OD_TXSIZE_MAX * OD_TXSIZE_MAX]);
1696 DECLARE_ALIGNED(16, tran_low_t, ref_coeff_pvq[OD_TXSIZE_MAX * OD_TXSIZE_MAX]);
1697 DECLARE_ALIGNED(16, tran_low_t, dqcoeff_pvq[OD_TXSIZE_MAX * OD_TXSIZE_MAX]);
Yushin Cho77bba8d2016-11-04 16:36:56 -07001698
Yushin Cho48f84db2016-11-07 21:20:17 -08001699 DECLARE_ALIGNED(16, int32_t, in_int32[OD_TXSIZE_MAX * OD_TXSIZE_MAX]);
1700 DECLARE_ALIGNED(16, int32_t, ref_int32[OD_TXSIZE_MAX * OD_TXSIZE_MAX]);
1701 DECLARE_ALIGNED(16, int32_t, out_int32[OD_TXSIZE_MAX * OD_TXSIZE_MAX]);
Yushin Cho77bba8d2016-11-04 16:36:56 -07001702
Thomas Daede6ff6af62017-02-03 16:29:24 -08001703 hbd_downshift = x->e_mbd.bd - 8;
Thomas Daede6ff6af62017-02-03 16:29:24 -08001704
1705 assert(OD_COEFF_SHIFT >= 4);
Yushin Cho70669122016-12-08 09:53:14 -10001706 // DC quantizer for PVQ
1707 if (use_activity_masking)
clang-format55ce9e02017-02-15 22:27:12 -08001708 pvq_dc_quant =
Thomas Daede6ff6af62017-02-03 16:29:24 -08001709 OD_MAXI(1, (quant[0] << (OD_COEFF_SHIFT - 3) >> hbd_downshift) *
clang-format55ce9e02017-02-15 22:27:12 -08001710 daala_enc->state
1711 .pvq_qm_q4[plane][od_qm_get_index(tx_size, 0)] >>
1712 4);
Yushin Cho70669122016-12-08 09:53:14 -10001713 else
Thomas Daede6ff6af62017-02-03 16:29:24 -08001714 pvq_dc_quant =
1715 OD_MAXI(1, quant[0] << (OD_COEFF_SHIFT - 3) >> hbd_downshift);
Yushin Cho70669122016-12-08 09:53:14 -10001716
Yushin Cho77bba8d2016-11-04 16:36:56 -07001717 *eob = 0;
1718
Nathan E. Egge476c63c2017-05-18 18:35:16 -04001719#if !CONFIG_ANS
Nathan E. Egge6675be02016-12-21 13:02:43 -05001720 tell = od_ec_enc_tell_frac(&daala_enc->w.ec);
1721#else
Nathan E. Egge476c63c2017-05-18 18:35:16 -04001722#error "CONFIG_PVQ currently requires !CONFIG_ANS."
Nathan E. Egge6675be02016-12-21 13:02:43 -05001723#endif
Yushin Cho77bba8d2016-11-04 16:36:56 -07001724
1725 // Change coefficient ordering for pvq encoding.
1726 od_raster_to_coding_order(coeff_pvq, tx_blk_size, tx_type, coeff,
1727 tx_blk_size);
1728 od_raster_to_coding_order(ref_coeff_pvq, tx_blk_size, tx_type, ref_coeff,
1729 tx_blk_size);
1730
1731 // copy int16 inputs to int32
1732 for (i = 0; i < tx_blk_size * tx_blk_size; i++) {
Timothy B. Terriberry4e6a8f32017-02-24 11:00:59 -08001733 ref_int32[i] =
Thomas Daede6ff6af62017-02-03 16:29:24 -08001734 AOM_SIGNED_SHL(ref_coeff_pvq[i], OD_COEFF_SHIFT - coeff_shift) >>
1735 hbd_downshift;
1736 in_int32[i] = AOM_SIGNED_SHL(coeff_pvq[i], OD_COEFF_SHIFT - coeff_shift) >>
1737 hbd_downshift;
Yushin Cho77bba8d2016-11-04 16:36:56 -07001738 }
1739
Yushin Cho77bba8d2016-11-04 16:36:56 -07001740 if (abs(in_int32[0] - ref_int32[0]) < pvq_dc_quant * 141 / 256) { /* 0.55 */
1741 out_int32[0] = 0;
1742 } else {
1743 out_int32[0] = OD_DIV_R0(in_int32[0] - ref_int32[0], pvq_dc_quant);
1744 }
1745
Thomas Daede6ff6af62017-02-03 16:29:24 -08001746 ac_dc_coded =
1747 od_pvq_encode(daala_enc, ref_int32, in_int32, out_int32,
1748 OD_MAXI(1, quant[0] << (OD_COEFF_SHIFT - 3) >>
1749 hbd_downshift), // scale/quantizer
1750 OD_MAXI(1, quant[1] << (OD_COEFF_SHIFT - 3) >>
1751 hbd_downshift), // scale/quantizer
1752 plane,
1753 tx_size, OD_PVQ_BETA[use_activity_masking][plane][tx_size],
Yushin Cho31b980a2017-03-23 10:28:09 -07001754 0, // is_keyframe,
Thomas Daede6ff6af62017-02-03 16:29:24 -08001755 daala_enc->state.qm + off, daala_enc->state.qm_inv + off,
1756 speed, // speed
1757 pvq_info);
Yushin Cho77bba8d2016-11-04 16:36:56 -07001758
1759 // Encode residue of DC coeff, if required.
1760 if (!has_dc_skip || out_int32[0]) {
Yushin Choc49ef3a2017-03-13 17:27:25 -07001761 generic_encode(&daala_enc->w, &daala_enc->state.adapt->model_dc[plane],
Timothy B. Terriberry44bb6d02017-04-07 15:44:14 -07001762 abs(out_int32[0]) - has_dc_skip,
Yushin Choc49ef3a2017-03-13 17:27:25 -07001763 &daala_enc->state.adapt->ex_dc[plane][tx_size][0], 2);
Yushin Cho77bba8d2016-11-04 16:36:56 -07001764 }
1765 if (out_int32[0]) {
Nathan E. Egge6675be02016-12-21 13:02:43 -05001766 aom_write_bit(&daala_enc->w, out_int32[0] < 0);
Yushin Cho77bba8d2016-11-04 16:36:56 -07001767 }
1768
1769 // need to save quantized residue of DC coeff
1770 // so that final pvq bitstream writing can know whether DC is coded.
1771 if (pvq_info) pvq_info->dq_dc_residue = out_int32[0];
1772
1773 out_int32[0] = out_int32[0] * pvq_dc_quant;
1774 out_int32[0] += ref_int32[0];
1775
1776 // copy int32 result back to int16
Timothy B. Terriberrye93acb22017-02-06 13:55:53 -08001777 assert(OD_COEFF_SHIFT > coeff_shift);
1778 rounding_mask = (1 << (OD_COEFF_SHIFT - coeff_shift - 1)) - 1;
1779 for (i = 0; i < tx_blk_size * tx_blk_size; i++) {
Thomas Daede6ff6af62017-02-03 16:29:24 -08001780 out_int32[i] = AOM_SIGNED_SHL(out_int32[i], hbd_downshift);
Timothy B. Terriberrye93acb22017-02-06 13:55:53 -08001781 dqcoeff_pvq[i] = (out_int32[i] + (out_int32[i] < 0) + rounding_mask) >>
1782 (OD_COEFF_SHIFT - coeff_shift);
1783 }
Yushin Cho77bba8d2016-11-04 16:36:56 -07001784
1785 // Back to original coefficient order
1786 od_coding_order_to_raster(dqcoeff, tx_blk_size, tx_type, dqcoeff_pvq,
1787 tx_blk_size);
1788
1789 *eob = tx_blk_size * tx_blk_size;
1790
Nathan E. Egge476c63c2017-05-18 18:35:16 -04001791#if !CONFIG_ANS
Nathan E. Egge6675be02016-12-21 13:02:43 -05001792 *rate = (od_ec_enc_tell_frac(&daala_enc->w.ec) - tell)
Yushin Cho77bba8d2016-11-04 16:36:56 -07001793 << (AV1_PROB_COST_SHIFT - OD_BITRES);
Nathan E. Egge6675be02016-12-21 13:02:43 -05001794#else
Nathan E. Egge476c63c2017-05-18 18:35:16 -04001795#error "CONFIG_PVQ currently requires !CONFIG_ANS."
Nathan E. Egge6675be02016-12-21 13:02:43 -05001796#endif
Yushin Cho77bba8d2016-11-04 16:36:56 -07001797 assert(*rate >= 0);
Yushin Cho5c207292017-02-16 15:01:33 -08001798
ltrudeau472f63f2017-01-12 15:22:32 -05001799 return ac_dc_coded;
Yushin Cho77bba8d2016-11-04 16:36:56 -07001800}
1801
Timothy B. Terriberry44bb6d02017-04-07 15:44:14 -07001802void av1_store_pvq_enc_info(PVQ_INFO *pvq_info, int *qg, int *theta, int *k,
1803 od_coeff *y, int nb_bands, const int *off,
1804 int *size, int skip_rest, int skip_dir,
Yushin Cho77bba8d2016-11-04 16:36:56 -07001805 int bs) { // block size in log_2 -2
1806 int i;
1807 const int tx_blk_size = tx_size_wide[bs];
1808
1809 for (i = 0; i < nb_bands; i++) {
1810 pvq_info->qg[i] = qg[i];
1811 pvq_info->theta[i] = theta[i];
Yushin Cho77bba8d2016-11-04 16:36:56 -07001812 pvq_info->k[i] = k[i];
1813 pvq_info->off[i] = off[i];
1814 pvq_info->size[i] = size[i];
1815 }
1816
1817 memcpy(pvq_info->y, y, tx_blk_size * tx_blk_size * sizeof(od_coeff));
1818
1819 pvq_info->nb_bands = nb_bands;
1820 pvq_info->skip_rest = skip_rest;
1821 pvq_info->skip_dir = skip_dir;
1822 pvq_info->bs = bs;
1823}
1824#endif