encodemb.c 42.6 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

37
38
39
// Check if one needs to use c version subtraction.
static int check_subtract_block_size(int w, int h) { return w < 4 || h < 4; }

Yaowu Xu's avatar
Yaowu Xu committed
40
void av1_subtract_plane(MACROBLOCK *x, BLOCK_SIZE bsize, int plane) {
Jingning Han's avatar
Jingning Han committed
41
42
43
  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);
44
45
  const int bw = block_size_wide[plane_bsize];
  const int bh = block_size_high[plane_bsize];
Jingning Han's avatar
Jingning Han committed
46

47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
  if (check_subtract_block_size(bw, bh)) {
#if CONFIG_AOM_HIGHBITDEPTH
    if (x->e_mbd.cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
      aom_highbd_subtract_block_c(bh, bw, p->src_diff, bw, p->src.buf,
                                  p->src.stride, pd->dst.buf, pd->dst.stride,
                                  x->e_mbd.bd);
      return;
    }
#endif  // CONFIG_AOM_HIGHBITDEPTH
    aom_subtract_block_c(bh, bw, p->src_diff, bw, p->src.buf, p->src.stride,
                         pd->dst.buf, pd->dst.stride);

    return;
  }

Yaowu Xu's avatar
Yaowu Xu committed
62
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
63
  if (x->e_mbd.cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
Yaowu Xu's avatar
Yaowu Xu committed
64
    aom_highbd_subtract_block(bh, bw, p->src_diff, bw, p->src.buf,
Jingning Han's avatar
Jingning Han committed
65
66
67
68
                              p->src.stride, pd->dst.buf, pd->dst.stride,
                              x->e_mbd.bd);
    return;
  }
Yaowu Xu's avatar
Yaowu Xu committed
69
70
#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
71
72
73
                     pd->dst.buf, pd->dst.stride);
}

Yaowu Xu's avatar
Yaowu Xu committed
74
typedef struct av1_token_state {
75
76
77
78
79
80
  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
81
} av1_token_state;
Jingning Han's avatar
Jingning Han committed
82

83
84
// These numbers are empirically obtained.
static const int plane_rd_mult[REF_TYPES][PLANE_TYPES] = {
85
  { 10, 6 }, { 8, 5 },
86
};
Jingning Han's avatar
Jingning Han committed
87

88
89
90
91
92
#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
93

Angie Chiang's avatar
Angie Chiang committed
94
95
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
96
97
98
99
  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
100
  av1_token_state tokens[MAX_TX_SQUARE + 1][2];
101
  unsigned best_index[MAX_TX_SQUARE + 1][2];
102
  uint8_t token_cache[MAX_TX_SQUARE];
Jingning Han's avatar
Jingning Han committed
103
104
105
106
  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];
107
  const PLANE_TYPE plane_type = pd->plane_type;
108
  const int default_eob = tx_size_2d[tx_size];
109
110
  const int16_t *const dequant_ptr = pd->dequant;
  const uint8_t *const band_translate = get_band_translate(tx_size);
111
  TX_TYPE tx_type = get_tx_type(plane_type, xd, block, tx_size);
112
  const SCAN_ORDER *const scan_order =
Angie Chiang's avatar
Angie Chiang committed
113
      get_scan(cm, tx_size, tx_type, is_inter_block(&xd->mi[0]->mbmi));
114
115
  const int16_t *const scan = scan_order->scan;
  const int16_t *const nb = scan_order->neighbors;
Thomas Davies's avatar
Thomas Davies committed
116
  int dqv;
117
  const int shift = get_tx_scale(tx_size);
118
119
#if CONFIG_AOM_QM
  int seg_id = xd->mi[0]->mbmi.segment_id;
120
  const qm_val_t *iqmatrix = pd->seg_iqmatrix[seg_id][!ref][tx_size];
121
#endif
122
#if CONFIG_NEW_QUANT
123
  int dq = get_dq_profile_from_ctx(mb->qindex, ctx, ref, plane_type);
124
  const dequant_val_type_nuq *dequant_val = pd->dequant_val_nuq[dq];
125
#elif !CONFIG_AOM_QM
126
  const int dq_step[2] = { dequant_ptr[0] >> shift, dequant_ptr[1] >> shift };
127
#endif  // CONFIG_NEW_QUANT
Jingning Han's avatar
Jingning Han committed
128
  int next = eob, sz = 0;
129
  const int64_t rdmult = (mb->rdmult * plane_rd_mult[ref][plane_type]) >> 1;
hui su's avatar
hui su committed
130
  const int64_t rddiv = mb->rddiv;
Jingning Han's avatar
Jingning Han committed
131
  int64_t rd_cost0, rd_cost1;
132
133
  int rate0, rate1;
  int64_t error0, error1;
Jingning Han's avatar
Jingning Han committed
134
  int16_t t0, t1;
135
136
  int best, band = (eob < default_eob) ? band_translate[eob]
                                       : band_translate[eob - 1];
137
  int pt, i, final_eob;
Yaowu Xu's avatar
Yaowu Xu committed
138
139
#if CONFIG_AOM_HIGHBITDEPTH
  const int *cat6_high_cost = av1_get_high_cost_table(xd->bd);
Jingning Han's avatar
Jingning Han committed
140
#else
Yaowu Xu's avatar
Yaowu Xu committed
141
  const int *cat6_high_cost = av1_get_high_cost_table(8);
Jingning Han's avatar
Jingning Han committed
142
#endif
143
  unsigned int(*token_costs)[2][COEFF_CONTEXTS][ENTROPY_TOKENS] =
144
      mb->token_costs[txsize_sqr_map[tx_size]][plane_type][ref];
145
146
  const uint16_t *band_counts = &band_count_table[tx_size][band];
  uint16_t band_left = eob - band_cum_count_table[tx_size][band] + 1;
147
148
  int shortcut = 0;
  int next_shortcut = 0;
149

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

152
  token_costs += band;
Jingning Han's avatar
Jingning Han committed
153

154
  assert((!plane_type && !plane) || (plane_type && plane));
Jingning Han's avatar
Jingning Han committed
155
  assert(eob <= default_eob);
156

Jingning Han's avatar
Jingning Han committed
157
158
159
160
161
162
163
164
165
  /* 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];

166
167
  for (i = 0; i < eob; i++) {
    const int rc = scan[i];
Yaowu Xu's avatar
Yaowu Xu committed
168
    tokens[i][0].rate = av1_get_token_cost(qcoeff[rc], &t0, cat6_high_cost);
169
    tokens[i][0].token = t0;
Yaowu Xu's avatar
Yaowu Xu committed
170
    token_cache[rc] = av1_pt_energy_class[t0];
171
  }
Jingning Han's avatar
Jingning Han committed
172
173

  for (i = eob; i-- > 0;) {
174
175
    int base_bits, dx;
    int64_t d2;
Jingning Han's avatar
Jingning Han committed
176
    const int rc = scan[i];
Thomas Davies's avatar
Thomas Davies committed
177
    int x = qcoeff[rc];
178
179
#if CONFIG_AOM_QM
    int iwt = iqmatrix[rc];
Thomas Davies's avatar
Thomas Davies committed
180
181
182
183
    dqv = dequant_ptr[rc != 0];
    dqv = ((iwt * (int)dqv) + (1 << (AOM_QM_BITS - 1))) >> AOM_QM_BITS;
#else
    dqv = dequant_ptr[rc != 0];
184
#endif
185
    next_shortcut = shortcut;
186

Jingning Han's avatar
Jingning Han committed
187
    /* Only add a trellis state for non-zero coefficients. */
188
    if (UNLIKELY(x)) {
Jingning Han's avatar
Jingning Han committed
189
190
191
192
193
      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;
194

195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
      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
211
      }
212
213

      dx = (dqcoeff[rc] - coeff[rc]) * (1 << shift);
Yaowu Xu's avatar
Yaowu Xu committed
214
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
215
216
217
      if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
        dx >>= xd->bd - 8;
      }
Yaowu Xu's avatar
Yaowu Xu committed
218
#endif  // CONFIG_AOM_HIGHBITDEPTH
219
      d2 = (int64_t)dx * dx;
220
      tokens[i][0].rate += (best ? rate1 : rate0);
Jingning Han's avatar
Jingning Han committed
221
222
223
      tokens[i][0].error = d2 + (best ? error1 : error0);
      tokens[i][0].next = next;
      tokens[i][0].qc = x;
224
      tokens[i][0].dqc = dqcoeff[rc];
Jingning Han's avatar
Jingning Han committed
225
226
227
228
229
230
      best_index[i][0] = best;

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

231
      // The threshold of 3 is empirically obtained.
232
      if (UNLIKELY(abs(x) > 3)) {
233
234
        shortcut = 0;
      } else {
235
#if CONFIG_NEW_QUANT
Thomas Davies's avatar
Thomas Davies committed
236
        shortcut = ((av1_dequant_abscoeff_nuq(abs(x), dqv,
Yaowu Xu's avatar
Yaowu Xu committed
237
                                              dequant_val[band_translate[i]]) >
238
                     (abs(coeff[rc]) << shift)) &&
Thomas Davies's avatar
Thomas Davies committed
239
                    (av1_dequant_abscoeff_nuq(abs(x) - 1, dqv,
Yaowu Xu's avatar
Yaowu Xu committed
240
                                              dequant_val[band_translate[i]]) <
241
                     (abs(coeff[rc]) << shift)));
242
243
244
245
246
247
248
249
#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
250
        if ((abs(x) * dequant_ptr[rc != 0] > (abs(coeff[rc]) << shift)) &&
251
252
            (abs(x) * dequant_ptr[rc != 0] <
             (abs(coeff[rc]) << shift) + dequant_ptr[rc != 0]))
253
#endif  // CONFIG_AOM_QM
254
255
256
          shortcut = 1;
        else
          shortcut = 0;
257
#endif  // CONFIG_NEW_QUANT
258
      }
Jingning Han's avatar
Jingning Han committed
259
260
261
262

      if (shortcut) {
        sz = -(x < 0);
        x -= 2 * sz + 1;
263
264
265
266
      } else {
        tokens[i][1] = tokens[i][0];
        best_index[i][1] = best_index[i][0];
        next = i;
267

268
        if (UNLIKELY(!(--band_left))) {
269
270
271
272
          --band_counts;
          band_left = *band_counts;
          --token_costs;
        }
273
        continue;
Jingning Han's avatar
Jingning Han committed
274
275
276
277
278
279
280
281
282
      }

      /* 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;
283
        base_bits = 0;
Jingning Han's avatar
Jingning Han committed
284
      } else {
Yaowu Xu's avatar
Yaowu Xu committed
285
        base_bits = av1_get_token_cost(x, &t0, cat6_high_cost);
Jingning Han's avatar
Jingning Han committed
286
287
        t1 = t0;
      }
288
289

      if (next_shortcut) {
290
        if (LIKELY(next < default_eob)) {
291
          if (t0 != EOB_TOKEN) {
Yaowu Xu's avatar
Yaowu Xu committed
292
            token_cache[rc] = av1_pt_energy_class[t0];
293
294
295
296
            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
297
            token_cache[rc] = av1_pt_energy_class[t1];
298
299
300
301
302
303
304
305
306
307
308
            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
309
          token_cache[rc] = av1_pt_energy_class[t0];
Jingning Han's avatar
Jingning Han committed
310
          pt = get_coef_context(nb, token_cache, i + 1);
311
          rate0 += (*token_costs)[!x][pt][tokens[next][0].token];
Jingning Han's avatar
Jingning Han committed
312
        }
313
        best = 0;
Jingning Han's avatar
Jingning Han committed
314
315
      }

316
#if CONFIG_NEW_QUANT
Thomas Davies's avatar
Thomas Davies committed
317
      dx = av1_dequant_coeff_nuq(x, dqv, dequant_val[band_translate[i]]) -
318
           (coeff[rc] << shift);
Yaowu Xu's avatar
Yaowu Xu committed
319
#if CONFIG_AOM_HIGHBITDEPTH
hui su's avatar
hui su committed
320
321
322
      if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
        dx >>= xd->bd - 8;
      }
Yaowu Xu's avatar
Yaowu Xu committed
323
#endif  // CONFIG_AOM_HIGHBITDEPTH
324
#else   // CONFIG_NEW_QUANT
Yaowu Xu's avatar
Yaowu Xu committed
325
#if CONFIG_AOM_HIGHBITDEPTH
hui su's avatar
hui su committed
326
      if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
Thomas Davies's avatar
Thomas Davies committed
327
        dx -= ((dqv >> (xd->bd - 8)) + sz) ^ sz;
hui su's avatar
hui su committed
328
      } else {
Thomas Davies's avatar
Thomas Davies committed
329
        dx -= (dqv + sz) ^ sz;
hui su's avatar
hui su committed
330
331
      }
#else
Thomas Davies's avatar
Thomas Davies committed
332
      dx -= (dqv + sz) ^ sz;
Yaowu Xu's avatar
Yaowu Xu committed
333
#endif  // CONFIG_AOM_HIGHBITDEPTH
334
#endif  // CONFIG_NEW_QUANT
335
      d2 = (int64_t)dx * dx;
hui su's avatar
hui su committed
336

Jingning Han's avatar
Jingning Han committed
337
338
339
340
341
      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;
342
343

      if (x) {
344
#if CONFIG_NEW_QUANT
Yaowu Xu's avatar
Yaowu Xu committed
345
        tokens[i][1].dqc = av1_dequant_abscoeff_nuq(
Thomas Davies's avatar
Thomas Davies committed
346
            abs(x), dqv, dequant_val[band_translate[i]]);
347
348
349
        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;
350
#else
351
352
353
354
// 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
355
356
357
358
359
360
361

#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);
362
363
364
365
366

        if (sz == 0)
          tokens[i][1].dqc = dqcoeff[rc] - offset;
        else
          tokens[i][1].dqc = dqcoeff[rc] + offset;
367
#endif  // CONFIG_NEW_QUANT
368
369
370
371
      } else {
        tokens[i][1].dqc = 0;
      }

Jingning Han's avatar
Jingning Han committed
372
373
374
375
376
377
378
379
380
      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;
381
      pt = get_coef_context(nb, token_cache, i + 1);
Jingning Han's avatar
Jingning Han committed
382
383
      /* Update the cost of each path if we're past the EOB token. */
      if (t0 != EOB_TOKEN) {
384
        tokens[next][0].rate += (*token_costs)[1][pt][t0];
Jingning Han's avatar
Jingning Han committed
385
386
387
        tokens[next][0].token = ZERO_TOKEN;
      }
      if (t1 != EOB_TOKEN) {
388
        tokens[next][1].rate += (*token_costs)[1][pt][t1];
Jingning Han's avatar
Jingning Han committed
389
390
391
        tokens[next][1].token = ZERO_TOKEN;
      }
      best_index[i][0] = best_index[i][1] = 0;
392
      shortcut = (tokens[next][0].rate != tokens[next][1].rate);
Jingning Han's avatar
Jingning Han committed
393
394
      /* Don't update next, because we didn't add a new node. */
    }
395

396
    if (UNLIKELY(!(--band_left))) {
397
398
399
400
      --band_counts;
      band_left = *band_counts;
      --token_costs;
    }
Jingning Han's avatar
Jingning Han committed
401
402
403
404
405
406
407
408
409
  }

  /* 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;
410
411
  rate0 += (*token_costs)[0][ctx][t0];
  rate1 += (*token_costs)[0][ctx][t1];
Jingning Han's avatar
Jingning Han committed
412
413
  UPDATE_RD_COST();
  best = rd_cost1 < rd_cost0;
414

Jingning Han's avatar
Jingning Han committed
415
  final_eob = -1;
416

Jingning Han's avatar
Jingning Han committed
417
418
419
  for (i = next; i < eob; i = next) {
    const int x = tokens[i][best].qc;
    const int rc = scan[i];
420
    if (x) final_eob = i;
Jingning Han's avatar
Jingning Han committed
421
    qcoeff[rc] = x;
422
423
    dqcoeff[rc] = tokens[i][best].dqc;

Jingning Han's avatar
Jingning Han committed
424
425
426
427
428
429
    next = tokens[i][best].next;
    best = best_index[i][best];
  }
  final_eob++;

  mb->plane[plane].eobs[block] = final_eob;
430
  assert(final_eob <= default_eob);
Jingning Han's avatar
Jingning Han committed
431
432
433
  return final_eob;
}

Yaowu Xu's avatar
Yaowu Xu committed
434
#if CONFIG_AOM_HIGHBITDEPTH
Angie Chiang's avatar
Angie Chiang committed
435
436
typedef enum QUANT_FUNC {
  QUANT_FUNC_LOWBD = 0,
437
  QUANT_FUNC_HIGHBD = 1,
438
  QUANT_FUNC_TYPES = 2
Angie Chiang's avatar
Angie Chiang committed
439
440
} QUANT_FUNC;

441
442
443
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
444
445
      { av1_quantize_b_facade, av1_highbd_quantize_b_facade },
      { av1_quantize_dc_facade, av1_highbd_quantize_dc_facade },
446
447
448
449
450
451
452
#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 }
    };
453

454
455
#elif !CONFIG_PVQ

Angie Chiang's avatar
Angie Chiang committed
456
457
typedef enum QUANT_FUNC {
  QUANT_FUNC_LOWBD = 0,
458
  QUANT_FUNC_TYPES = 1
Angie Chiang's avatar
Angie Chiang committed
459
} QUANT_FUNC;
Angie Chiang's avatar
Angie Chiang committed
460

461
462
static AV1_QUANT_FACADE quant_func_list[AV1_XFORM_QUANT_TYPES]
                                       [QUANT_FUNC_TYPES] = {
clang-format's avatar
clang-format committed
463
464
465
                                         { av1_quantize_fp_facade },
                                         { av1_quantize_b_facade },
                                         { av1_quantize_dc_facade },
466
467
468
469
470
#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
471
472
                                         { NULL }
                                       };
Angie Chiang's avatar
Angie Chiang committed
473
#endif
474

475
476
477
478
479
480
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
481
};
482

Angie Chiang's avatar
Angie Chiang committed
483
484
void av1_xform_quant(const AV1_COMMON *cm, MACROBLOCK *x, int plane, int block,
                     int blk_row, int blk_col, BLOCK_SIZE plane_bsize,
485
486
                     TX_SIZE tx_size, int ctx,
                     AV1_XFORM_QUANT xform_quant_idx) {
Jingning Han's avatar
Jingning Han committed
487
  MACROBLOCKD *const xd = &x->e_mbd;
488
#if !CONFIG_PVQ
Jingning Han's avatar
Jingning Han committed
489
490
  const struct macroblock_plane *const p = &x->plane[plane];
  const struct macroblockd_plane *const pd = &xd->plane[plane];
491
492
493
494
#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
495
  PLANE_TYPE plane_type = (plane == 0) ? PLANE_TYPE_Y : PLANE_TYPE_UV;
hui su's avatar
hui su committed
496
  TX_TYPE tx_type = get_tx_type(plane_type, xd, block, tx_size);
497
  const int is_inter = is_inter_block(&xd->mi[0]->mbmi);
Angie Chiang's avatar
Angie Chiang committed
498
  const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, is_inter);
Jingning Han's avatar
Jingning Han committed
499
500
501
502
  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];
503
  const int diff_stride = block_size_wide[plane_bsize];
504
505
#if CONFIG_AOM_QM
  int seg_id = xd->mi[0]->mbmi.segment_id;
506
507
  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];
508
#endif
Angie Chiang's avatar
Angie Chiang committed
509
510

  FWD_TXFM_PARAM fwd_txfm_param;
511
512
513

#if !CONFIG_PVQ
  const int tx2d_size = tx_size_2d[tx_size];
514
  QUANT_PARAM qparam;
515
516
517
  const int16_t *src_diff;

  src_diff = &p->src_diff[4 * (blk_row * diff_stride + blk_col)];
518
  qparam.log_scale = get_tx_scale(tx_size);
519
520
521
522
523
524
525
526
#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
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
#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
562
  (void)ctx;
563
564

  fwd_txfm_param.tx_type = tx_type;
Angie Chiang's avatar
Angie Chiang committed
565
  fwd_txfm_param.tx_size = tx_size;
566
  fwd_txfm_param.fwd_txfm_opt = fwd_txfm_opt_list[xform_quant_idx];
Angie Chiang's avatar
Angie Chiang committed
567
568
569
  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
570
#if CONFIG_AOM_HIGHBITDEPTH
571
  fwd_txfm_param.bd = xd->bd;
Jingning Han's avatar
Jingning Han committed
572
  if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
Angie Chiang's avatar
Angie Chiang committed
573
    highbd_fwd_txfm(src_diff, coeff, diff_stride, &fwd_txfm_param);
Yaowu Xu's avatar
Yaowu Xu committed
574
    if (xform_quant_idx != AV1_XFORM_QUANT_SKIP_QUANT) {
575
      if (LIKELY(!x->skip_block)) {
576
        quant_func_list[xform_quant_idx][QUANT_FUNC_HIGHBD](
577
            coeff, tx2d_size, p, qcoeff, pd, dqcoeff, eob, scan_order, &qparam);
578
      } else {
Yaowu Xu's avatar
Yaowu Xu committed
579
        av1_quantize_skip(tx2d_size, qcoeff, dqcoeff, eob);
580
581
582
583
      }
    }
    return;
  }
Yaowu Xu's avatar
Yaowu Xu committed
584
#endif  // CONFIG_AOM_HIGHBITDEPTH
585

586
#if !CONFIG_PVQ
587
  fwd_txfm(src_diff, coeff, diff_stride, &fwd_txfm_param);
Yaowu Xu's avatar
Yaowu Xu committed
588
  if (xform_quant_idx != AV1_XFORM_QUANT_SKIP_QUANT) {
589
    if (LIKELY(!x->skip_block)) {
590
      quant_func_list[xform_quant_idx][QUANT_FUNC_LOWBD](
591
          coeff, tx2d_size, p, qcoeff, pd, dqcoeff, eob, scan_order, &qparam);
592
    } else {
Yaowu Xu's avatar
Yaowu Xu committed
593
      av1_quantize_skip(tx2d_size, qcoeff, dqcoeff, eob);
Jingning Han's avatar
Jingning Han committed
594
595
    }
  }
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
#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
621
622
}

623
static void encode_block(int plane, int block, int blk_row, int blk_col,
624
                         BLOCK_SIZE plane_bsize, TX_SIZE tx_size, void *arg) {
Jingning Han's avatar
Jingning Han committed
625
  struct encode_b_args *const args = arg;
Angie Chiang's avatar
Angie Chiang committed
626
  AV1_COMMON *cm = args->cm;
Jingning Han's avatar
Jingning Han committed
627
628
  MACROBLOCK *const x = args->x;
  MACROBLOCKD *const xd = &x->e_mbd;
629
  int ctx;
Jingning Han's avatar
Jingning Han committed
630
631
632
633
634
  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
635
  INV_TXFM_PARAM inv_txfm_param;
636
637
638
639
#if CONFIG_PVQ
  int tx_blk_size;
  int i, j;
#endif
640
641
#if CONFIG_VAR_TX
  int i;
642
  const int bwl = b_width_log2_lookup[plane_bsize];
643
#endif
644
  dst = &pd->dst.buf[4 * blk_row * pd->dst.stride + 4 * blk_col];
645
646
  a = &args->ta[blk_col];
  l = &args->tl[blk_row];
647
648
649
650
651
#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
652

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

657
  if (x->blk_skip[plane][(blk_row << bwl) + blk_col] == 0) {
658
#else
659
  {
660
#endif
661
#if CONFIG_NEW_QUANT
662
663
    av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
                    ctx, AV1_XFORM_QUANT_FP_NUQ);
664
#else
Angie Chiang's avatar
Angie Chiang committed
665
    av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
666
                    ctx, AV1_XFORM_QUANT_FP);
667
#endif  // CONFIG_NEW_QUANT
Jingning Han's avatar
Jingning Han committed
668
  }
669
670
#if CONFIG_VAR_TX
  else {
671
    p->eobs[block] = 0;
672
673
  }
#endif
674
#if !CONFIG_PVQ
675
  if (p->eobs[block] && !xd->lossless[xd->mi[0]->mbmi.segment_id]) {
Angie Chiang's avatar
Angie Chiang committed
676
    *a = *l = av1_optimize_b(cm, x, plane, block, tx_size, ctx) > 0;
Jingning Han's avatar
Jingning Han committed
677
678
679
680
  } else {
    *a = *l = p->eobs[block] > 0;
  }

681
#if CONFIG_VAR_TX
682
683
684
  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];
685
686
#endif

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

689
  if (p->eobs[block] == 0) return;
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
#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
708
709
710
711
712
713
714

  // 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
715
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
716
  if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
Angie Chiang's avatar
Angie Chiang committed
717
718
    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
719
720
    return;
  }
Yaowu Xu's avatar
Yaowu Xu committed
721
#endif  // CONFIG_AOM_HIGHBITDEPTH
Angie Chiang's avatar
Angie Chiang committed
722
  inv_txfm_add(dqcoeff, dst, pd->dst.stride, &inv_txfm_param);
Jingning Han's avatar
Jingning Han committed
723
724
}

725
726
727
728
729
730
731
732
#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;
733
  const BLOCK_SIZE bsize = txsize_to_bsize[tx_size];
734
  const struct macroblockd_plane *const pd = &xd->plane[plane];
735
736
  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
737
  TX_SIZE plane_tx_size;
738
739
  const int max_blocks_high = max_block_high(xd, plane_bsize, plane);
  const int max_blocks_wide = max_block_wide(xd, plane_bsize, plane);
740

741
  if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
742

743
744
745
  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
746

747
  if (tx_size == plane_tx_size) {
748
    encode_block(plane, block, blk_row, blk_col, plane_bsize, tx_size, arg);
749
  } else {
750
751
752
    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];
753
754
    int i;
    assert(bsl > 0);
755
    assert(tx_size < TX_SIZES_ALL);
756

757
    for (i = 0; i < 4; ++i) {
758
759
760
      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];
761

762
      if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide) continue;
763

764
765
766
      encode_block_inter(plane, block, offsetr, offsetc, plane_bsize, sub_txs,
                         arg);
      block += step;
767
768
769
770
771
    }
  }
}
#endif

Angie Chiang's avatar
Angie Chiang committed
772
773
774
775
776
typedef struct encode_block_pass1_args {
  AV1_COMMON *cm;
  MACROBLOCK *x;
} encode_block_pass1_args;

777
static void encode_block_pass1(int plane, int block, int blk_row, int blk_col,
778
779
                               BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
                               void *arg) {
Angie Chiang's avatar
Angie Chiang committed
780
781
782
  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
783
784
785
786
787
  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;
788
  int ctx = 0;
789
  dst = &pd->dst.buf[4 * blk_row * pd->dst.stride + 4 * blk_col];
Jingning Han's avatar
Jingning Han committed
790

791
#if CONFIG_NEW_QUANT
792
793
  av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
                  ctx, AV1_XFORM_QUANT_B_NUQ);
794
#else
Angie Chiang's avatar
Angie Chiang committed
795
  av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
796
                  ctx, AV1_XFORM_QUANT_B);
797
#endif  // CONFIG_NEW_QUANT
798
#if !CONFIG_PVQ
Jingning Han's avatar
Jingning Han committed
799
  if (p->eobs[block] > 0) {
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
#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
815
#endif  // !CONFIG_PVQ
Yaowu Xu's avatar
Yaowu Xu committed
816
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
817
    if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
Yaowu Xu's avatar
Yaowu Xu committed
818
      if (xd->lossless[xd->mi[0]->mbmi.segment_id]) {
Yaowu Xu's avatar
Yaowu Xu committed
819
820
        av1_highbd_iwht4x4_add(dqcoeff, dst, pd->dst.stride, p->eobs[block],
                               xd->bd);
821
      } else {
Yaowu Xu's avatar
Yaowu Xu committed
822
823
        av1_highbd_idct4x4_add(dqcoeff, dst, pd->dst.stride, p->eobs[block],
                               xd->bd);
824
825
      }
      return;
Jingning Han's avatar
Jingning Han committed
826
    }
827
#endif  //  CONFIG_AOM_HIGHBITDEPTH
Yaowu Xu's avatar
Yaowu Xu committed
828
    if (xd->lossless[xd->mi[0]->mbmi.segment_id]) {
Yaowu Xu's avatar
Yaowu Xu committed
829
      av1_iwht4x4_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
830
    } else {
Yaowu Xu's avatar
Yaowu Xu committed
831
      av1_idct4x4_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
832
    }
Jingning Han's avatar
Jingning Han committed
833
834
835
  }
}

Angie Chiang's avatar
Angie Chiang committed
836
837
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
838
839
  av1_subtract_plane(x, bsize, 0);
  av1_foreach_transformed_block_in_plane(&x->e_mbd, bsize, 0,
Angie Chiang's avatar
Angie Chiang committed
840
                                         encode_block_pass1, &args);
Jingning Han's avatar
Jingning Han committed
841
842
}

Angie Chiang's avatar
Angie Chiang committed
843
void av1_encode_sb(AV1_COMMON *cm, MACROBLOCK *x, BLOCK_SIZE bsize) {
Jingning Han's avatar
Jingning Han committed
844
845
846
  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
847
  struct encode_b_args arg = { cm, x, &ctx, &mbmi->skip, NULL, NULL, 1 };
Jingning Han's avatar
Jingning Han committed
848
849
850
851
  int plane;

  mbmi->skip = 1;

852
  if (x->skip) return;
Jingning Han's avatar
Jingning Han committed
853
854

  for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
855
856
857
858
#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);
859
860
    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];
861
    const TX_SIZE max_tx_size = max_txsize_rect_lookup[plane_bsize];
862
    const BLOCK_SIZE txb_size = txsize_to_bsize[max_tx_size];
863
864
    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];
865
866
    int idx, idy;
    int block = 0;
867
    int step = tx_size_wide_unit[max_tx_size] * tx_size_high_unit[max_tx_size];
Yaowu Xu's avatar
Yaowu Xu committed
868
    av1_get_entropy_contexts(bsize, TX_4X4, pd, ctx.ta[plane], ctx.tl[plane]);
869
#else
870
    const struct macroblockd_plane *const pd = &xd->plane[plane];
871
    const TX_SIZE tx_size = plane ? get_uv_tx_size(mbmi, pd) : mbmi->tx_size;
Yaowu Xu's avatar
Yaowu Xu committed
872
    av1_get_entropy_contexts(bsize, tx_size, pd, ctx.ta[plane], ctx.tl[plane]);
873
#endif
874
#if !CONFIG_PVQ
Yaowu Xu's avatar
Yaowu Xu committed
875
    av1_subtract_plane(x, bsize, plane);
876
#endif
877
878
    arg.ta = ctx.ta[plane];
    arg.tl = ctx.tl[plane];
879

880
#if CONFIG_VAR_TX
881
882
883
884
885
    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;
886
887
888
      }
    }
#else
Yaowu Xu's avatar
Yaowu Xu committed
889
890
    av1_foreach_transformed_block_in_plane(xd, bsize, plane, encode_block,
                                           &arg);
891
#endif
Jingning Han's avatar
Jingning Han committed
892
893
894
  }
}

895
#if CONFIG_SUPERTX
Angie Chiang's avatar
Angie Chiang committed
896
void av1_encode_sb_supertx(AV1_COMMON *cm, MACROBLOCK *x, BLOCK_SIZE bsize) {
897
898
899
  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
900
  struct encode_b_args arg = { cm, x, &ctx, &mbmi->skip, NULL, NULL, 1 };
901
902
903
  int plane;

  mbmi->skip = 1;
904
  if (x->skip) return;
905
906

  for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
907
<