encodemb.c 41.2 KB
Newer Older
Jingning Han's avatar
Jingning Han committed
1
/*
Yaowu Xu's avatar
Yaowu Xu committed
2
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Jingning Han's avatar
Jingning Han committed
3
 *
Yaowu Xu's avatar
Yaowu Xu committed
4
5
6
7
8
9
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
Jingning Han's avatar
Jingning Han committed
10
11
 */

Yaowu Xu's avatar
Yaowu Xu committed
12
13
14
#include "./av1_rtcd.h"
#include "./aom_config.h"
#include "./aom_dsp_rtcd.h"
Jingning Han's avatar
Jingning Han committed
15

16
#include "aom_dsp/quantize.h"
Yaowu Xu's avatar
Yaowu Xu committed
17
#include "aom_mem/aom_mem.h"
18
#include "aom_ports/mem.h"
Jingning Han's avatar
Jingning Han committed
19

20
21
22
23
#include "av1/common/idct.h"
#include "av1/common/reconinter.h"
#include "av1/common/reconintra.h"
#include "av1/common/scan.h"
Jingning Han's avatar
Jingning Han committed
24

25
26
27
28
29
#include "av1/encoder/encodemb.h"
#include "av1/encoder/hybrid_fwd_txfm.h"
#include "av1/encoder/quantize.h"
#include "av1/encoder/rd.h"
#include "av1/encoder/tokenize.h"
Jingning Han's avatar
Jingning Han committed
30

31
32
33
34
35
36
#if CONFIG_PVQ
#include "av1/encoder/encint.h"
#include "av1/common/partition.h"
#include "av1/encoder/pvq_encoder.h"
#endif

Yaowu Xu's avatar
Yaowu Xu committed
37
void av1_subtract_plane(MACROBLOCK *x, BLOCK_SIZE bsize, int plane) {
Jingning Han's avatar
Jingning Han committed
38
39
40
  struct macroblock_plane *const p = &x->plane[plane];
  const struct macroblockd_plane *const pd = &x->e_mbd.plane[plane];
  const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
41
42
  const int bw = block_size_wide[plane_bsize];
  const int bh = block_size_high[plane_bsize];
Jingning Han's avatar
Jingning Han committed
43

Yaowu Xu's avatar
Yaowu Xu committed
44
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
45
  if (x->e_mbd.cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
Yaowu Xu's avatar
Yaowu Xu committed
46
    aom_highbd_subtract_block(bh, bw, p->src_diff, bw, p->src.buf,
Jingning Han's avatar
Jingning Han committed
47
48
49
50
                              p->src.stride, pd->dst.buf, pd->dst.stride,
                              x->e_mbd.bd);
    return;
  }
Yaowu Xu's avatar
Yaowu Xu committed
51
52
#endif  // CONFIG_AOM_HIGHBITDEPTH
  aom_subtract_block(bh, bw, p->src_diff, bw, p->src.buf, p->src.stride,
Jingning Han's avatar
Jingning Han committed
53
54
55
                     pd->dst.buf, pd->dst.stride);
}

Yaowu Xu's avatar
Yaowu Xu committed
56
typedef struct av1_token_state {
57
58
59
60
61
62
  int rate;
  int64_t error;
  int next;
  int16_t token;
  tran_low_t qc;
  tran_low_t dqc;
Yaowu Xu's avatar
Yaowu Xu committed
63
} av1_token_state;
Jingning Han's avatar
Jingning Han committed
64

65
66
// These numbers are empirically obtained.
static const int plane_rd_mult[REF_TYPES][PLANE_TYPES] = {
67
  { 10, 6 }, { 8, 5 },
68
};
Jingning Han's avatar
Jingning Han committed
69

70
71
72
73
74
#define UPDATE_RD_COST()                             \
  {                                                  \
    rd_cost0 = RDCOST(rdmult, rddiv, rate0, error0); \
    rd_cost1 = RDCOST(rdmult, rddiv, rate1, error1); \
  }
Jingning Han's avatar
Jingning Han committed
75

Angie Chiang's avatar
Angie Chiang committed
76
77
int av1_optimize_b(const AV1_COMMON *cm, MACROBLOCK *mb, int plane, int block,
                   TX_SIZE tx_size, int ctx) {
Jingning Han's avatar
Jingning Han committed
78
79
80
81
  MACROBLOCKD *const xd = &mb->e_mbd;
  struct macroblock_plane *const p = &mb->plane[plane];
  struct macroblockd_plane *const pd = &xd->plane[plane];
  const int ref = is_inter_block(&xd->mi[0]->mbmi);
Yaowu Xu's avatar
Yaowu Xu committed
82
  av1_token_state tokens[MAX_TX_SQUARE + 1][2];
83
  unsigned best_index[MAX_TX_SQUARE + 1][2];
84
  uint8_t token_cache[MAX_TX_SQUARE];
Jingning Han's avatar
Jingning Han committed
85
86
87
88
  const tran_low_t *const coeff = BLOCK_OFFSET(mb->plane[plane].coeff, block);
  tran_low_t *const qcoeff = BLOCK_OFFSET(p->qcoeff, block);
  tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
  const int eob = p->eobs[block];
89
  const PLANE_TYPE plane_type = pd->plane_type;
90
  const int default_eob = tx_size_2d[tx_size];
91
92
  const int16_t *const dequant_ptr = pd->dequant;
  const uint8_t *const band_translate = get_band_translate(tx_size);
93
  TX_TYPE tx_type = get_tx_type(plane_type, xd, block, tx_size);
94
  const SCAN_ORDER *const scan_order =
Angie Chiang's avatar
Angie Chiang committed
95
      get_scan(cm, tx_size, tx_type, is_inter_block(&xd->mi[0]->mbmi));
96
97
  const int16_t *const scan = scan_order->scan;
  const int16_t *const nb = scan_order->neighbors;
Thomas Davies's avatar
Thomas Davies committed
98
  int dqv;
99
  const int shift = get_tx_scale(tx_size);
100
101
#if CONFIG_AOM_QM
  int seg_id = xd->mi[0]->mbmi.segment_id;
102
  const qm_val_t *iqmatrix = pd->seg_iqmatrix[seg_id][!ref][tx_size];
103
#endif
104
#if CONFIG_NEW_QUANT
105
  int dq = get_dq_profile_from_ctx(mb->qindex, ctx, ref, plane_type);
106
  const dequant_val_type_nuq *dequant_val = pd->dequant_val_nuq[dq];
107
#elif !CONFIG_AOM_QM
108
  const int dq_step[2] = { dequant_ptr[0] >> shift, dequant_ptr[1] >> shift };
109
#endif  // CONFIG_NEW_QUANT
Jingning Han's avatar
Jingning Han committed
110
  int next = eob, sz = 0;
111
  const int64_t rdmult = (mb->rdmult * plane_rd_mult[ref][plane_type]) >> 1;
hui su's avatar
hui su committed
112
  const int64_t rddiv = mb->rddiv;
Jingning Han's avatar
Jingning Han committed
113
  int64_t rd_cost0, rd_cost1;
114
115
  int rate0, rate1;
  int64_t error0, error1;
Jingning Han's avatar
Jingning Han committed
116
  int16_t t0, t1;
117
118
  int best, band = (eob < default_eob) ? band_translate[eob]
                                       : band_translate[eob - 1];
119
  int pt, i, final_eob;
Yaowu Xu's avatar
Yaowu Xu committed
120
121
#if CONFIG_AOM_HIGHBITDEPTH
  const int *cat6_high_cost = av1_get_high_cost_table(xd->bd);
Jingning Han's avatar
Jingning Han committed
122
#else
Yaowu Xu's avatar
Yaowu Xu committed
123
  const int *cat6_high_cost = av1_get_high_cost_table(8);
Jingning Han's avatar
Jingning Han committed
124
#endif
125
  unsigned int(*token_costs)[2][COEFF_CONTEXTS][ENTROPY_TOKENS] =
126
      mb->token_costs[txsize_sqr_map[tx_size]][plane_type][ref];
127
128
  const uint16_t *band_counts = &band_count_table[tx_size][band];
  uint16_t band_left = eob - band_cum_count_table[tx_size][band] + 1;
129
130
  int shortcut = 0;
  int next_shortcut = 0;
131

132
  assert((mb->qindex == 0) ^ (xd->lossless[xd->mi[0]->mbmi.segment_id] == 0));
133

134
  token_costs += band;
Jingning Han's avatar
Jingning Han committed
135

136
  assert((!plane_type && !plane) || (plane_type && plane));
Jingning Han's avatar
Jingning Han committed
137
  assert(eob <= default_eob);
138

Jingning Han's avatar
Jingning Han committed
139
140
141
142
143
144
145
146
147
  /* Now set up a Viterbi trellis to evaluate alternative roundings. */
  /* Initialize the sentinel node of the trellis. */
  tokens[eob][0].rate = 0;
  tokens[eob][0].error = 0;
  tokens[eob][0].next = default_eob;
  tokens[eob][0].token = EOB_TOKEN;
  tokens[eob][0].qc = 0;
  tokens[eob][1] = tokens[eob][0];

148
149
  for (i = 0; i < eob; i++) {
    const int rc = scan[i];
Yaowu Xu's avatar
Yaowu Xu committed
150
    tokens[i][0].rate = av1_get_token_cost(qcoeff[rc], &t0, cat6_high_cost);
151
    tokens[i][0].token = t0;
Yaowu Xu's avatar
Yaowu Xu committed
152
    token_cache[rc] = av1_pt_energy_class[t0];
153
  }
Jingning Han's avatar
Jingning Han committed
154
155

  for (i = eob; i-- > 0;) {
156
157
    int base_bits, dx;
    int64_t d2;
Jingning Han's avatar
Jingning Han committed
158
    const int rc = scan[i];
Thomas Davies's avatar
Thomas Davies committed
159
    int x = qcoeff[rc];
160
161
#if CONFIG_AOM_QM
    int iwt = iqmatrix[rc];
Thomas Davies's avatar
Thomas Davies committed
162
163
164
165
    dqv = dequant_ptr[rc != 0];
    dqv = ((iwt * (int)dqv) + (1 << (AOM_QM_BITS - 1))) >> AOM_QM_BITS;
#else
    dqv = dequant_ptr[rc != 0];
166
#endif
167
    next_shortcut = shortcut;
168

Jingning Han's avatar
Jingning Han committed
169
    /* Only add a trellis state for non-zero coefficients. */
170
    if (UNLIKELY(x)) {
Jingning Han's avatar
Jingning Han committed
171
172
173
174
175
      error0 = tokens[next][0].error;
      error1 = tokens[next][1].error;
      /* Evaluate the first possibility for this state. */
      rate0 = tokens[next][0].rate;
      rate1 = tokens[next][1].rate;
176

177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
      if (next_shortcut) {
        /* Consider both possible successor states. */
        if (next < default_eob) {
          pt = get_coef_context(nb, token_cache, i + 1);
          rate0 += (*token_costs)[0][pt][tokens[next][0].token];
          rate1 += (*token_costs)[0][pt][tokens[next][1].token];
        }
        UPDATE_RD_COST();
        /* And pick the best. */
        best = rd_cost1 < rd_cost0;
      } else {
        if (next < default_eob) {
          pt = get_coef_context(nb, token_cache, i + 1);
          rate0 += (*token_costs)[0][pt][tokens[next][0].token];
        }
        best = 0;
Jingning Han's avatar
Jingning Han committed
193
      }
194
195

      dx = (dqcoeff[rc] - coeff[rc]) * (1 << shift);
Yaowu Xu's avatar
Yaowu Xu committed
196
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
197
198
199
      if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
        dx >>= xd->bd - 8;
      }
Yaowu Xu's avatar
Yaowu Xu committed
200
#endif  // CONFIG_AOM_HIGHBITDEPTH
201
      d2 = (int64_t)dx * dx;
202
      tokens[i][0].rate += (best ? rate1 : rate0);
Jingning Han's avatar
Jingning Han committed
203
204
205
      tokens[i][0].error = d2 + (best ? error1 : error0);
      tokens[i][0].next = next;
      tokens[i][0].qc = x;
206
      tokens[i][0].dqc = dqcoeff[rc];
Jingning Han's avatar
Jingning Han committed
207
208
209
210
211
212
      best_index[i][0] = best;

      /* Evaluate the second possibility for this state. */
      rate0 = tokens[next][0].rate;
      rate1 = tokens[next][1].rate;

213
      // The threshold of 3 is empirically obtained.
214
      if (UNLIKELY(abs(x) > 3)) {
215
216
        shortcut = 0;
      } else {
217
#if CONFIG_NEW_QUANT
Thomas Davies's avatar
Thomas Davies committed
218
        shortcut = ((av1_dequant_abscoeff_nuq(abs(x), dqv,
Yaowu Xu's avatar
Yaowu Xu committed
219
                                              dequant_val[band_translate[i]]) >
220
                     (abs(coeff[rc]) << shift)) &&
Thomas Davies's avatar
Thomas Davies committed
221
                    (av1_dequant_abscoeff_nuq(abs(x) - 1, dqv,
Yaowu Xu's avatar
Yaowu Xu committed
222
                                              dequant_val[band_translate[i]]) <
223
                     (abs(coeff[rc]) << shift)));
224
225
226
227
228
229
230
231
#else  // CONFIG_NEW_QUANT
#if CONFIG_AOM_QM
        if ((abs(x) * dequant_ptr[rc != 0] * iwt >
             ((abs(coeff[rc]) << shift) << AOM_QM_BITS)) &&
            (abs(x) * dequant_ptr[rc != 0] * iwt <
             (((abs(coeff[rc]) << shift) + dequant_ptr[rc != 0])
              << AOM_QM_BITS)))
#else
232
        if ((abs(x) * dequant_ptr[rc != 0] > (abs(coeff[rc]) << shift)) &&
233
234
            (abs(x) * dequant_ptr[rc != 0] <
             (abs(coeff[rc]) << shift) + dequant_ptr[rc != 0]))
235
#endif  // CONFIG_AOM_QM
236
237
238
          shortcut = 1;
        else
          shortcut = 0;
239
#endif  // CONFIG_NEW_QUANT
240
      }
Jingning Han's avatar
Jingning Han committed
241
242
243
244

      if (shortcut) {
        sz = -(x < 0);
        x -= 2 * sz + 1;
245
246
247
248
      } else {
        tokens[i][1] = tokens[i][0];
        best_index[i][1] = best_index[i][0];
        next = i;
249

250
        if (UNLIKELY(!(--band_left))) {
251
252
253
254
          --band_counts;
          band_left = *band_counts;
          --token_costs;
        }
255
        continue;
Jingning Han's avatar
Jingning Han committed
256
257
258
259
260
261
262
263
264
      }

      /* Consider both possible successor states. */
      if (!x) {
        /* If we reduced this coefficient to zero, check to see if
         *  we need to move the EOB back here.
         */
        t0 = tokens[next][0].token == EOB_TOKEN ? EOB_TOKEN : ZERO_TOKEN;
        t1 = tokens[next][1].token == EOB_TOKEN ? EOB_TOKEN : ZERO_TOKEN;
265
        base_bits = 0;
Jingning Han's avatar
Jingning Han committed
266
      } else {
Yaowu Xu's avatar
Yaowu Xu committed
267
        base_bits = av1_get_token_cost(x, &t0, cat6_high_cost);
Jingning Han's avatar
Jingning Han committed
268
269
        t1 = t0;
      }
270
271

      if (next_shortcut) {
272
        if (LIKELY(next < default_eob)) {
273
          if (t0 != EOB_TOKEN) {
Yaowu Xu's avatar
Yaowu Xu committed
274
            token_cache[rc] = av1_pt_energy_class[t0];
275
276
277
278
            pt = get_coef_context(nb, token_cache, i + 1);
            rate0 += (*token_costs)[!x][pt][tokens[next][0].token];
          }
          if (t1 != EOB_TOKEN) {
Yaowu Xu's avatar
Yaowu Xu committed
279
            token_cache[rc] = av1_pt_energy_class[t1];
280
281
282
283
284
285
286
287
288
289
290
            pt = get_coef_context(nb, token_cache, i + 1);
            rate1 += (*token_costs)[!x][pt][tokens[next][1].token];
          }
        }

        UPDATE_RD_COST();
        /* And pick the best. */
        best = rd_cost1 < rd_cost0;
      } else {
        // The two states in next stage are identical.
        if (next < default_eob && t0 != EOB_TOKEN) {
Yaowu Xu's avatar
Yaowu Xu committed
291
          token_cache[rc] = av1_pt_energy_class[t0];
Jingning Han's avatar
Jingning Han committed
292
          pt = get_coef_context(nb, token_cache, i + 1);
293
          rate0 += (*token_costs)[!x][pt][tokens[next][0].token];
Jingning Han's avatar
Jingning Han committed
294
        }
295
        best = 0;
Jingning Han's avatar
Jingning Han committed
296
297
      }

298
#if CONFIG_NEW_QUANT
Thomas Davies's avatar
Thomas Davies committed
299
      dx = av1_dequant_coeff_nuq(x, dqv, dequant_val[band_translate[i]]) -
300
           (coeff[rc] << shift);
Yaowu Xu's avatar
Yaowu Xu committed
301
#if CONFIG_AOM_HIGHBITDEPTH
hui su's avatar
hui su committed
302
303
304
      if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
        dx >>= xd->bd - 8;
      }
Yaowu Xu's avatar
Yaowu Xu committed
305
#endif  // CONFIG_AOM_HIGHBITDEPTH
306
#else   // CONFIG_NEW_QUANT
Yaowu Xu's avatar
Yaowu Xu committed
307
#if CONFIG_AOM_HIGHBITDEPTH
hui su's avatar
hui su committed
308
      if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
Thomas Davies's avatar
Thomas Davies committed
309
        dx -= ((dqv >> (xd->bd - 8)) + sz) ^ sz;
hui su's avatar
hui su committed
310
      } else {
Thomas Davies's avatar
Thomas Davies committed
311
        dx -= (dqv + sz) ^ sz;
hui su's avatar
hui su committed
312
313
      }
#else
Thomas Davies's avatar
Thomas Davies committed
314
      dx -= (dqv + sz) ^ sz;
Yaowu Xu's avatar
Yaowu Xu committed
315
#endif  // CONFIG_AOM_HIGHBITDEPTH
316
#endif  // CONFIG_NEW_QUANT
317
      d2 = (int64_t)dx * dx;
hui su's avatar
hui su committed
318

Jingning Han's avatar
Jingning Han committed
319
320
321
322
323
      tokens[i][1].rate = base_bits + (best ? rate1 : rate0);
      tokens[i][1].error = d2 + (best ? error1 : error0);
      tokens[i][1].next = next;
      tokens[i][1].token = best ? t1 : t0;
      tokens[i][1].qc = x;
324
325

      if (x) {
326
#if CONFIG_NEW_QUANT
Yaowu Xu's avatar
Yaowu Xu committed
327
        tokens[i][1].dqc = av1_dequant_abscoeff_nuq(
Thomas Davies's avatar
Thomas Davies committed
328
            abs(x), dqv, dequant_val[band_translate[i]]);
329
330
331
        tokens[i][1].dqc = shift ? ROUND_POWER_OF_TWO(tokens[i][1].dqc, shift)
                                 : tokens[i][1].dqc;
        if (sz) tokens[i][1].dqc = -tokens[i][1].dqc;
332
#else
333
334
335
336
// The 32x32 transform coefficient uses half quantization step size.
// Account for the rounding difference in the dequantized coefficeint
// value when the quantization index is dropped from an even number
// to an odd number.
Thomas Davies's avatar
Thomas Davies committed
337
338
339
340
341
342
343

#if CONFIG_AOM_QM
        tran_low_t offset = dqv >> shift;
#else
        tran_low_t offset = dq_step[rc != 0];
#endif
        if (shift & x) offset += (dqv & 0x01);
344
345
346
347
348

        if (sz == 0)
          tokens[i][1].dqc = dqcoeff[rc] - offset;
        else
          tokens[i][1].dqc = dqcoeff[rc] + offset;
349
#endif  // CONFIG_NEW_QUANT
350
351
352
353
      } else {
        tokens[i][1].dqc = 0;
      }

Jingning Han's avatar
Jingning Han committed
354
355
356
357
358
359
360
361
362
      best_index[i][1] = best;
      /* Finally, make this the new head of the trellis. */
      next = i;
    } else {
      /* There's no choice to make for a zero coefficient, so we don't
       *  add a new trellis node, but we do need to update the costs.
       */
      t0 = tokens[next][0].token;
      t1 = tokens[next][1].token;
363
      pt = get_coef_context(nb, token_cache, i + 1);
Jingning Han's avatar
Jingning Han committed
364
365
      /* Update the cost of each path if we're past the EOB token. */
      if (t0 != EOB_TOKEN) {
366
        tokens[next][0].rate += (*token_costs)[1][pt][t0];
Jingning Han's avatar
Jingning Han committed
367
368
369
        tokens[next][0].token = ZERO_TOKEN;
      }
      if (t1 != EOB_TOKEN) {
370
        tokens[next][1].rate += (*token_costs)[1][pt][t1];
Jingning Han's avatar
Jingning Han committed
371
372
373
        tokens[next][1].token = ZERO_TOKEN;
      }
      best_index[i][0] = best_index[i][1] = 0;
374
      shortcut = (tokens[next][0].rate != tokens[next][1].rate);
Jingning Han's avatar
Jingning Han committed
375
376
      /* Don't update next, because we didn't add a new node. */
    }
377

378
    if (UNLIKELY(!(--band_left))) {
379
380
381
382
      --band_counts;
      band_left = *band_counts;
      --token_costs;
    }
Jingning Han's avatar
Jingning Han committed
383
384
385
386
387
388
389
390
391
  }

  /* Now pick the best path through the whole trellis. */
  rate0 = tokens[next][0].rate;
  rate1 = tokens[next][1].rate;
  error0 = tokens[next][0].error;
  error1 = tokens[next][1].error;
  t0 = tokens[next][0].token;
  t1 = tokens[next][1].token;
392
393
  rate0 += (*token_costs)[0][ctx][t0];
  rate1 += (*token_costs)[0][ctx][t1];
Jingning Han's avatar
Jingning Han committed
394
395
  UPDATE_RD_COST();
  best = rd_cost1 < rd_cost0;
396

Jingning Han's avatar
Jingning Han committed
397
  final_eob = -1;
398

Jingning Han's avatar
Jingning Han committed
399
400
401
  for (i = next; i < eob; i = next) {
    const int x = tokens[i][best].qc;
    const int rc = scan[i];
402
    if (x) final_eob = i;
Jingning Han's avatar
Jingning Han committed
403
    qcoeff[rc] = x;
404
405
    dqcoeff[rc] = tokens[i][best].dqc;

Jingning Han's avatar
Jingning Han committed
406
407
408
409
410
411
    next = tokens[i][best].next;
    best = best_index[i][best];
  }
  final_eob++;

  mb->plane[plane].eobs[block] = final_eob;
412
  assert(final_eob <= default_eob);
Jingning Han's avatar
Jingning Han committed
413
414
415
  return final_eob;
}

Yaowu Xu's avatar
Yaowu Xu committed
416
#if CONFIG_AOM_HIGHBITDEPTH
Angie Chiang's avatar
Angie Chiang committed
417
418
typedef enum QUANT_FUNC {
  QUANT_FUNC_LOWBD = 0,
419
  QUANT_FUNC_HIGHBD = 1,
420
  QUANT_FUNC_TYPES = 2
Angie Chiang's avatar
Angie Chiang committed
421
422
} QUANT_FUNC;

423
424
425
static AV1_QUANT_FACADE
    quant_func_list[AV1_XFORM_QUANT_TYPES][QUANT_FUNC_TYPES] = {
      { av1_quantize_fp_facade, av1_highbd_quantize_fp_facade },
Yaowu Xu's avatar
Yaowu Xu committed
426
427
      { av1_quantize_b_facade, av1_highbd_quantize_b_facade },
      { av1_quantize_dc_facade, av1_highbd_quantize_dc_facade },
428
429
430
431
432
433
434
#if CONFIG_NEW_QUANT
      { av1_quantize_fp_nuq_facade, av1_highbd_quantize_fp_nuq_facade },
      { av1_quantize_b_nuq_facade, av1_highbd_quantize_b_nuq_facade },
      { av1_quantize_dc_nuq_facade, av1_highbd_quantize_dc_nuq_facade },
#endif  // CONFIG_NEW_QUANT
      { NULL, NULL }
    };
435

436
437
#elif !CONFIG_PVQ

Angie Chiang's avatar
Angie Chiang committed
438
439
typedef enum QUANT_FUNC {
  QUANT_FUNC_LOWBD = 0,
440
  QUANT_FUNC_TYPES = 1
Angie Chiang's avatar
Angie Chiang committed
441
} QUANT_FUNC;
Angie Chiang's avatar
Angie Chiang committed
442

443
444
static AV1_QUANT_FACADE quant_func_list[AV1_XFORM_QUANT_TYPES]
                                       [QUANT_FUNC_TYPES] = {
clang-format's avatar
clang-format committed
445
446
447
                                         { av1_quantize_fp_facade },
                                         { av1_quantize_b_facade },
                                         { av1_quantize_dc_facade },
448
449
450
451
452
#if CONFIG_NEW_QUANT
                                         { av1_quantize_fp_nuq_facade },
                                         { av1_quantize_b_nuq_facade },
                                         { av1_quantize_dc_nuq_facade },
#endif  // CONFIG_NEW_QUANT
clang-format's avatar
clang-format committed
453
454
                                         { NULL }
                                       };
Angie Chiang's avatar
Angie Chiang committed
455
#endif
456

457
458
459
460
461
462
static FWD_TXFM_OPT fwd_txfm_opt_list[AV1_XFORM_QUANT_TYPES] = {
  FWD_TXFM_OPT_NORMAL, FWD_TXFM_OPT_NORMAL, FWD_TXFM_OPT_DC,
#if CONFIG_NEW_QUANT
  FWD_TXFM_OPT_NORMAL, FWD_TXFM_OPT_NORMAL, FWD_TXFM_OPT_DC,
#endif  // CONFIG_NEW_QUANT
  FWD_TXFM_OPT_NORMAL
463
};
464

Angie Chiang's avatar
Angie Chiang committed
465
466
void av1_xform_quant(const AV1_COMMON *cm, MACROBLOCK *x, int plane, int block,
                     int blk_row, int blk_col, BLOCK_SIZE plane_bsize,
467
468
                     TX_SIZE tx_size, int ctx,
                     AV1_XFORM_QUANT xform_quant_idx) {
Jingning Han's avatar
Jingning Han committed
469
  MACROBLOCKD *const xd = &x->e_mbd;
470
#if !CONFIG_PVQ
Jingning Han's avatar
Jingning Han committed
471
472
  const struct macroblock_plane *const p = &x->plane[plane];
  const struct macroblockd_plane *const pd = &xd->plane[plane];
473
474
475
476
#else
  struct macroblock_plane *const p = &x->plane[plane];
  struct macroblockd_plane *const pd = &xd->plane[plane];
#endif
hui su's avatar
hui su committed
477
  PLANE_TYPE plane_type = (plane == 0) ? PLANE_TYPE_Y : PLANE_TYPE_UV;
hui su's avatar
hui su committed
478
  TX_TYPE tx_type = get_tx_type(plane_type, xd, block, tx_size);
479
  const int is_inter = is_inter_block(&xd->mi[0]->mbmi);
Angie Chiang's avatar
Angie Chiang committed
480
  const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, is_inter);
Jingning Han's avatar
Jingning Han committed
481
482
483
484
  tran_low_t *const coeff = BLOCK_OFFSET(p->coeff, block);
  tran_low_t *const qcoeff = BLOCK_OFFSET(p->qcoeff, block);
  tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
  uint16_t *const eob = &p->eobs[block];
485
  const int diff_stride = block_size_wide[plane_bsize];
486
487
#if CONFIG_AOM_QM
  int seg_id = xd->mi[0]->mbmi.segment_id;
488
489
  const qm_val_t *qmatrix = pd->seg_qmatrix[seg_id][!is_inter][tx_size];
  const qm_val_t *iqmatrix = pd->seg_iqmatrix[seg_id][!is_inter][tx_size];
490
#endif
Angie Chiang's avatar
Angie Chiang committed
491
492

  FWD_TXFM_PARAM fwd_txfm_param;
493
494
495

#if !CONFIG_PVQ
  const int tx2d_size = tx_size_2d[tx_size];
496
  QUANT_PARAM qparam;
497
498
499
  const int16_t *src_diff;

  src_diff = &p->src_diff[4 * (blk_row * diff_stride + blk_col)];
500
  qparam.log_scale = get_tx_scale(tx_size);
501
502
503
504
505
506
507
508
#if CONFIG_NEW_QUANT
  qparam.tx_size = tx_size;
  qparam.dq = get_dq_profile_from_ctx(x->qindex, ctx, is_inter, plane_type);
#endif  // CONFIG_NEW_QUANT
#if CONFIG_AOM_QM
  qparam.qmatrix = qmatrix;
  qparam.iqmatrix = iqmatrix;
#endif  // CONFIG_AOM_QM
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
#else
  MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
  tran_low_t *ref_coeff = BLOCK_OFFSET(pd->pvq_ref_coeff, block);
  uint8_t *src, *dst;
  int16_t *src_int16, *pred;
  const int src_stride = p->src.stride;
  const int dst_stride = pd->dst.stride;
  int tx_blk_size;
  int i, j;
  int skip = 1;
  PVQ_INFO *pvq_info = NULL;

  (void)scan_order;
  (void)qcoeff;

  if (x->pvq_coded) {
    assert(block < MAX_PVQ_BLOCKS_IN_SB);
    pvq_info = &x->pvq[block][plane];
  }
  dst = &pd->dst.buf[4 * (blk_row * dst_stride + blk_col)];
  src = &p->src.buf[4 * (blk_row * src_stride + blk_col)];
  src_int16 = &p->src_int16[4 * (blk_row * diff_stride + blk_col)];
  pred = &pd->pred[4 * (blk_row * diff_stride + blk_col)];

  // transform block size in pixels
  tx_blk_size = tx_size_wide[tx_size];

  // copy uint8 orig and predicted block to int16 buffer
  // in order to use existing VP10 transform functions
  for (j = 0; j < tx_blk_size; j++)
    for (i = 0; i < tx_blk_size; i++) {
      src_int16[diff_stride * j + i] = src[src_stride * j + i];
      pred[diff_stride * j + i] = dst[dst_stride * j + i];
    }
#endif
544
  (void)ctx;
545
546

  fwd_txfm_param.tx_type = tx_type;
Angie Chiang's avatar
Angie Chiang committed
547
  fwd_txfm_param.tx_size = tx_size;
548
  fwd_txfm_param.fwd_txfm_opt = fwd_txfm_opt_list[xform_quant_idx];
Angie Chiang's avatar
Angie Chiang committed
549
550
551
  fwd_txfm_param.rd_transform = x->use_lp32x32fdct;
  fwd_txfm_param.lossless = xd->lossless[xd->mi[0]->mbmi.segment_id];

Yaowu Xu's avatar
Yaowu Xu committed
552
#if CONFIG_AOM_HIGHBITDEPTH
553
  fwd_txfm_param.bd = xd->bd;
Jingning Han's avatar
Jingning Han committed
554
  if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
Angie Chiang's avatar
Angie Chiang committed
555
    highbd_fwd_txfm(src_diff, coeff, diff_stride, &fwd_txfm_param);
Yaowu Xu's avatar
Yaowu Xu committed
556
    if (xform_quant_idx != AV1_XFORM_QUANT_SKIP_QUANT) {
557
      if (LIKELY(!x->skip_block)) {
558
        quant_func_list[xform_quant_idx][QUANT_FUNC_HIGHBD](
559
            coeff, tx2d_size, p, qcoeff, pd, dqcoeff, eob, scan_order, &qparam);
560
      } else {
Yaowu Xu's avatar
Yaowu Xu committed
561
        av1_quantize_skip(tx2d_size, qcoeff, dqcoeff, eob);
562
563
564
565
      }
    }
    return;
  }
Yaowu Xu's avatar
Yaowu Xu committed
566
#endif  // CONFIG_AOM_HIGHBITDEPTH
567

568
#if !CONFIG_PVQ
569
  fwd_txfm(src_diff, coeff, diff_stride, &fwd_txfm_param);
Yaowu Xu's avatar
Yaowu Xu committed
570
  if (xform_quant_idx != AV1_XFORM_QUANT_SKIP_QUANT) {
571
    if (LIKELY(!x->skip_block)) {
572
      quant_func_list[xform_quant_idx][QUANT_FUNC_LOWBD](
573
          coeff, tx2d_size, p, qcoeff, pd, dqcoeff, eob, scan_order, &qparam);
574
    } else {
Yaowu Xu's avatar
Yaowu Xu committed
575
      av1_quantize_skip(tx2d_size, qcoeff, dqcoeff, eob);
Jingning Han's avatar
Jingning Han committed
576
577
    }
  }
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
#else   // #if !CONFIG_PVQ
  fwd_txfm_param.rd_transform = 0;

  fwd_txfm(src_int16, coeff, diff_stride, &fwd_txfm_param);
  fwd_txfm(pred, ref_coeff, diff_stride, &fwd_txfm_param);

  // PVQ for inter mode block
  if (!x->skip_block)
    skip = av1_pvq_encode_helper(&x->daala_enc,
                                 coeff,        // target original vector
                                 ref_coeff,    // reference vector
                                 dqcoeff,      // de-quantized vector
                                 eob,          // End of Block marker
                                 pd->dequant,  // aom's quantizers
                                 plane,        // image plane
                                 tx_size,      // block size in log_2 - 2
                                 tx_type,
                                 &x->rate,  // rate measured
                                 x->pvq_speed,
                                 pvq_info);  // PVQ info for a block

  x->pvq_skip[plane] = skip;

  if (!skip) mbmi->skip = 0;
#endif  // #if !CONFIG_PVQ
Jingning Han's avatar
Jingning Han committed
603
604
}

605
static void encode_block(int plane, int block, int blk_row, int blk_col,
606
                         BLOCK_SIZE plane_bsize, TX_SIZE tx_size, void *arg) {
Jingning Han's avatar
Jingning Han committed
607
  struct encode_b_args *const args = arg;
Angie Chiang's avatar
Angie Chiang committed
608
  AV1_COMMON *cm = args->cm;
Jingning Han's avatar
Jingning Han committed
609
610
  MACROBLOCK *const x = args->x;
  MACROBLOCKD *const xd = &x->e_mbd;
611
  int ctx;
Jingning Han's avatar
Jingning Han committed
612
613
614
615
616
  struct macroblock_plane *const p = &x->plane[plane];
  struct macroblockd_plane *const pd = &xd->plane[plane];
  tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
  uint8_t *dst;
  ENTROPY_CONTEXT *a, *l;
Angie Chiang's avatar
Angie Chiang committed
617
  INV_TXFM_PARAM inv_txfm_param;
618
619
620
621
#if CONFIG_PVQ
  int tx_blk_size;
  int i, j;
#endif
622
623
#if CONFIG_VAR_TX
  int i;
624
  const int bwl = b_width_log2_lookup[plane_bsize];
625
#endif
626
  dst = &pd->dst.buf[4 * blk_row * pd->dst.stride + 4 * blk_col];
627
628
  a = &args->ta[blk_col];
  l = &args->tl[blk_row];
629
630
631
632
633
#if CONFIG_VAR_TX
  ctx = get_entropy_context(tx_size, a, l);
#else
  ctx = combine_entropy_contexts(*a, *l);
#endif
Jingning Han's avatar
Jingning Han committed
634

Alex Converse's avatar
Alex Converse committed
635
#if CONFIG_VAR_TX
636
  // Assert not magic number (uninitialized).
637
638
  assert(x->blk_skip[plane][(blk_row << bwl) + blk_col] != 234);

639
  if (x->blk_skip[plane][(blk_row << bwl) + blk_col] == 0) {
640
#else
641
  {
642
#endif
643
#if CONFIG_NEW_QUANT
644
645
    av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
                    ctx, AV1_XFORM_QUANT_FP_NUQ);
646
#else
Angie Chiang's avatar
Angie Chiang committed
647
    av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
648
                    ctx, AV1_XFORM_QUANT_FP);
649
#endif  // CONFIG_NEW_QUANT
Jingning Han's avatar
Jingning Han committed
650
  }
651
652
#if CONFIG_VAR_TX
  else {
653
    p->eobs[block] = 0;
654
655
  }
#endif
656
#if !CONFIG_PVQ
657
  if (p->eobs[block] && !xd->lossless[xd->mi[0]->mbmi.segment_id]) {
Angie Chiang's avatar
Angie Chiang committed
658
    *a = *l = av1_optimize_b(cm, x, plane, block, tx_size, ctx) > 0;
Jingning Han's avatar
Jingning Han committed
659
660
661
662
  } else {
    *a = *l = p->eobs[block] > 0;
  }

663
#if CONFIG_VAR_TX
664
665
666
  for (i = 0; i < tx_size_wide_unit[tx_size]; ++i) a[i] = a[0];

  for (i = 0; i < tx_size_high_unit[tx_size]; ++i) l[i] = l[0];
667
668
#endif

669
  if (p->eobs[block]) *(args->skip) = 0;
Jingning Han's avatar
Jingning Han committed
670

671
  if (p->eobs[block] == 0) return;
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
#else
  (void)ctx;
  *a = *l = !x->pvq_skip[plane];

  if (!x->pvq_skip[plane]) *(args->skip) = 0;

  if (x->pvq_skip[plane]) return;

  // transform block size in pixels
  tx_blk_size = tx_size_wide[tx_size];

  // Since av1 does not have separate function which does inverse transform
  // but av1_inv_txfm_add_*x*() also does addition of predicted image to
  // inverse transformed image,
  // pass blank dummy image to av1_inv_txfm_add_*x*(), i.e. set dst as zeros
  for (j = 0; j < tx_blk_size; j++)
    for (i = 0; i < tx_blk_size; i++) dst[j * pd->dst.stride + i] = 0;
#endif
Angie Chiang's avatar
Angie Chiang committed
690
691
692
693
694
695
696

  // inverse transform parameters
  inv_txfm_param.tx_type = get_tx_type(pd->plane_type, xd, block, tx_size);
  inv_txfm_param.tx_size = tx_size;
  inv_txfm_param.eob = p->eobs[block];
  inv_txfm_param.lossless = xd->lossless[xd->mi[0]->mbmi.segment_id];

Yaowu Xu's avatar
Yaowu Xu committed
697
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
698
  if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
Angie Chiang's avatar
Angie Chiang committed
699
700
    inv_txfm_param.bd = xd->bd;
    highbd_inv_txfm_add(dqcoeff, dst, pd->dst.stride, &inv_txfm_param);
Jingning Han's avatar
Jingning Han committed
701
702
    return;
  }
Yaowu Xu's avatar
Yaowu Xu committed
703
#endif  // CONFIG_AOM_HIGHBITDEPTH
Angie Chiang's avatar
Angie Chiang committed
704
  inv_txfm_add(dqcoeff, dst, pd->dst.stride, &inv_txfm_param);
Jingning Han's avatar
Jingning Han committed
705
706
}

707
708
709
710
711
712
713
714
#if CONFIG_VAR_TX
static void encode_block_inter(int plane, int block, int blk_row, int blk_col,
                               BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
                               void *arg) {
  struct encode_b_args *const args = arg;
  MACROBLOCK *const x = args->x;
  MACROBLOCKD *const xd = &x->e_mbd;
  MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
715
  const BLOCK_SIZE bsize = txsize_to_bsize[tx_size];
716
  const struct macroblockd_plane *const pd = &xd->plane[plane];
717
718
  const int tx_row = blk_row >> (1 - pd->subsampling_y);
  const int tx_col = blk_col >> (1 - pd->subsampling_x);
Debargha Mukherjee's avatar
Debargha Mukherjee committed
719
  TX_SIZE plane_tx_size;
720
721
  const int max_blocks_high = max_block_high(xd, plane_bsize, plane);
  const int max_blocks_wide = max_block_wide(xd, plane_bsize, plane);
722

723
  if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
724

725
726
727
  plane_tx_size =
      plane ? uv_txsize_lookup[bsize][mbmi->inter_tx_size[tx_row][tx_col]][0][0]
            : mbmi->inter_tx_size[tx_row][tx_col];
Debargha Mukherjee's avatar
Debargha Mukherjee committed
728

729
  if (tx_size == plane_tx_size) {
730
    encode_block(plane, block, blk_row, blk_col, plane_bsize, tx_size, arg);
731
  } else {
732
733
734
    const TX_SIZE sub_txs = sub_tx_size_map[tx_size];
    // This is the square transform block partition entry point.
    int bsl = tx_size_wide_unit[sub_txs];
735
736
    int i;
    assert(bsl > 0);
737
    assert(tx_size < TX_SIZES_ALL);
738

739
    for (i = 0; i < 4; ++i) {
740
741
742
      const int offsetr = blk_row + ((i >> 1) * bsl);
      const int offsetc = blk_col + ((i & 0x01) * bsl);
      int step = tx_size_wide_unit[sub_txs] * tx_size_high_unit[sub_txs];
743

744
      if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide) continue;
745

746
747
748
      encode_block_inter(plane, block, offsetr, offsetc, plane_bsize, sub_txs,
                         arg);
      block += step;
749
750
751
752
753
    }
  }
}
#endif

Angie Chiang's avatar
Angie Chiang committed
754
755
756
757
758
typedef struct encode_block_pass1_args {
  AV1_COMMON *cm;
  MACROBLOCK *x;
} encode_block_pass1_args;

759
static void encode_block_pass1(int plane, int block, int blk_row, int blk_col,
760
761
                               BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
                               void *arg) {
Angie Chiang's avatar
Angie Chiang committed
762
763
764
  encode_block_pass1_args *args = (encode_block_pass1_args *)arg;
  AV1_COMMON *cm = args->cm;
  MACROBLOCK *const x = args->x;
Jingning Han's avatar
Jingning Han committed
765
766
767
768
769
  MACROBLOCKD *const xd = &x->e_mbd;
  struct macroblock_plane *const p = &x->plane[plane];
  struct macroblockd_plane *const pd = &xd->plane[plane];
  tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
  uint8_t *dst;
770
  int ctx = 0;
771
  dst = &pd->dst.buf[4 * blk_row * pd->dst.stride + 4 * blk_col];
Jingning Han's avatar
Jingning Han committed
772

773
#if CONFIG_NEW_QUANT
774
775
  av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
                  ctx, AV1_XFORM_QUANT_B_NUQ);
776
#else
Angie Chiang's avatar
Angie Chiang committed
777
  av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
778
                  ctx, AV1_XFORM_QUANT_B);
779
#endif  // CONFIG_NEW_QUANT
780
#if !CONFIG_PVQ
Jingning Han's avatar
Jingning Han committed
781
  if (p->eobs[block] > 0) {
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
#else
  if (!x->pvq_skip[plane]) {
    {
      int tx_blk_size;
      int i, j;
      // transform block size in pixels
      tx_blk_size = tx_size_wide[tx_size];

      // Since av1 does not have separate function which does inverse transform
      // but av1_inv_txfm_add_*x*() also does addition of predicted image to
      // inverse transformed image,
      // pass blank dummy image to av1_inv_txfm_add_*x*(), i.e. set dst as zeros
      for (j = 0; j < tx_blk_size; j++)
        for (i = 0; i < tx_blk_size; i++) dst[j * pd->dst.stride + i] = 0;
    }
Jingning Han's avatar
Jingning Han committed
797
#endif  // !CONFIG_PVQ
Yaowu Xu's avatar
Yaowu Xu committed
798
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
799
    if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
Yaowu Xu's avatar
Yaowu Xu committed
800
      if (xd->lossless[xd->mi[0]->mbmi.segment_id]) {
Yaowu Xu's avatar
Yaowu Xu committed
801
802
        av1_highbd_iwht4x4_add(dqcoeff, dst, pd->dst.stride, p->eobs[block],
                               xd->bd);
803
      } else {
Yaowu Xu's avatar
Yaowu Xu committed
804
805
        av1_highbd_idct4x4_add(dqcoeff, dst, pd->dst.stride, p->eobs[block],
                               xd->bd);
806
807
      }
      return;
Jingning Han's avatar
Jingning Han committed
808
    }
809
#endif  //  CONFIG_AOM_HIGHBITDEPTH
Yaowu Xu's avatar
Yaowu Xu committed
810
    if (xd->lossless[xd->mi[0]->mbmi.segment_id]) {
Yaowu Xu's avatar
Yaowu Xu committed
811
      av1_iwht4x4_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
812
    } else {
Yaowu Xu's avatar
Yaowu Xu committed
813
      av1_idct4x4_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
814
    }
Jingning Han's avatar
Jingning Han committed
815
816
817
  }
}

Angie Chiang's avatar
Angie Chiang committed
818
819
void av1_encode_sby_pass1(AV1_COMMON *cm, MACROBLOCK *x, BLOCK_SIZE bsize) {
  encode_block_pass1_args args = { cm, x };
Yaowu Xu's avatar
Yaowu Xu committed
820
821
  av1_subtract_plane(x, bsize, 0);
  av1_foreach_transformed_block_in_plane(&x->e_mbd, bsize, 0,
Angie Chiang's avatar
Angie Chiang committed
822
                                         encode_block_pass1, &args);
Jingning Han's avatar
Jingning Han committed
823
824
}

Angie Chiang's avatar
Angie Chiang committed
825
void av1_encode_sb(AV1_COMMON *cm, MACROBLOCK *x, BLOCK_SIZE bsize) {
Jingning Han's avatar
Jingning Han committed
826
827
828
  MACROBLOCKD *const xd = &x->e_mbd;
  struct optimize_ctx ctx;
  MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Angie Chiang's avatar
Angie Chiang committed
829
  struct encode_b_args arg = { cm, x, &ctx, &mbmi->skip, NULL, NULL, 1 };
Jingning Han's avatar
Jingning Han committed
830
831
832
833
  int plane;

  mbmi->skip = 1;

834
  if (x->skip) return;
Jingning Han's avatar
Jingning Han committed
835
836

  for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
837
838
839
840
#if CONFIG_VAR_TX
    // TODO(jingning): Clean this up.
    const struct macroblockd_plane *const pd = &xd->plane[plane];
    const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
841
842
    const int mi_width = block_size_wide[plane_bsize] >> tx_size_wide_log2[0];
    const int mi_height = block_size_high[plane_bsize] >> tx_size_wide_log2[0];
843
    const TX_SIZE max_tx_size = max_txsize_rect_lookup[plane_bsize];
844
    const BLOCK_SIZE txb_size = txsize_to_bsize[max_tx_size];
845
846
    const int bw = block_size_wide[txb_size] >> tx_size_wide_log2[0];
    const int bh = block_size_high[txb_size] >> tx_size_wide_log2[0];
847
848
    int idx, idy;
    int block = 0;
849
    int step = tx_size_wide_unit[max_tx_size] * tx_size_high_unit[max_tx_size];
Yaowu Xu's avatar
Yaowu Xu committed
850
    av1_get_entropy_contexts(bsize, TX_4X4, pd, ctx.ta[plane], ctx.tl[plane]);
851
#else
852
    const struct macroblockd_plane *const pd = &xd->plane[plane];
853
    const TX_SIZE tx_size = plane ? get_uv_tx_size(mbmi, pd) : mbmi->tx_size;
Yaowu Xu's avatar
Yaowu Xu committed
854
    av1_get_entropy_contexts(bsize, tx_size, pd, ctx.ta[plane], ctx.tl[plane]);
855
#endif
856
#if !CONFIG_PVQ
Yaowu Xu's avatar
Yaowu Xu committed
857
    av1_subtract_plane(x, bsize, plane);
858
#endif
859
860
    arg.ta = ctx.ta[plane];
    arg.tl = ctx.tl[plane];
861

862
#if CONFIG_VAR_TX
863
864
865
866
867
    for (idy = 0; idy < mi_height; idy += bh) {
      for (idx = 0; idx < mi_width; idx += bw) {
        encode_block_inter(plane, block, idy, idx, plane_bsize, max_tx_size,
                           &arg);
        block += step;
868
869
870
      }
    }
#else
Yaowu Xu's avatar
Yaowu Xu committed
871
872
    av1_foreach_transformed_block_in_plane(xd, bsize, plane, encode_block,
                                           &arg);
873
#endif
Jingning Han's avatar
Jingning Han committed
874
875
876
  }
}

877
#if CONFIG_SUPERTX
Angie Chiang's avatar
Angie Chiang committed
878
void av1_encode_sb_supertx(AV1_COMMON *cm, MACROBLOCK *x, BLOCK_SIZE bsize) {
879
880
881
  MACROBLOCKD *const xd = &x->e_mbd;
  struct optimize_ctx ctx;
  MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Angie Chiang's avatar
Angie Chiang committed
882
  struct encode_b_args arg = { cm, x, &ctx, &mbmi->skip, NULL, NULL, 1 };
883
884
885
  int plane;

  mbmi->skip = 1;
886
  if (x->skip) return;
887
888

  for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
889
    const struct macroblockd_plane *const pd = &xd->plane[plane];
890
891
892
#if CONFIG_VAR_TX
    const TX_SIZE tx_size = TX_4X4;
#else
893
    const TX_SIZE tx_size = plane ? get_uv_tx_size(mbmi, pd) : mbmi->tx_size;
894
#endif
Yaowu Xu's avatar
Yaowu Xu committed
895
896
    av1_subtract_plane(x, bsize, plane);
    av1_get_entropy_contexts(bsize, tx_size, pd, ctx.ta[plane], ctx.tl[plane]);