xref: /aosp_15_r20/external/libvpx/vp9/encoder/vp9_encodemb.c (revision fb1b10ab9aebc7c7068eedab379b749d7e3900be)
1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker  *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3*fb1b10abSAndroid Build Coastguard Worker  *
4*fb1b10abSAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*fb1b10abSAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*fb1b10abSAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*fb1b10abSAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*fb1b10abSAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*fb1b10abSAndroid Build Coastguard Worker  */
10*fb1b10abSAndroid Build Coastguard Worker 
11*fb1b10abSAndroid Build Coastguard Worker #include "./vp9_rtcd.h"
12*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_config.h"
13*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_dsp_rtcd.h"
14*fb1b10abSAndroid Build Coastguard Worker 
15*fb1b10abSAndroid Build Coastguard Worker #include "vpx_dsp/quantize.h"
16*fb1b10abSAndroid Build Coastguard Worker #include "vpx_mem/vpx_mem.h"
17*fb1b10abSAndroid Build Coastguard Worker #include "vpx_ports/mem.h"
18*fb1b10abSAndroid Build Coastguard Worker 
19*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MISMATCH_DEBUG
20*fb1b10abSAndroid Build Coastguard Worker #include "vpx_util/vpx_debug_util.h"
21*fb1b10abSAndroid Build Coastguard Worker #endif
22*fb1b10abSAndroid Build Coastguard Worker 
23*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_idct.h"
24*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_reconinter.h"
25*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_reconintra.h"
26*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_scan.h"
27*fb1b10abSAndroid Build Coastguard Worker 
28*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_encodemb.h"
29*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_encoder.h"
30*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_rd.h"
31*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_tokenize.h"
32*fb1b10abSAndroid Build Coastguard Worker 
33*fb1b10abSAndroid Build Coastguard Worker struct optimize_ctx {
34*fb1b10abSAndroid Build Coastguard Worker   ENTROPY_CONTEXT ta[MAX_MB_PLANE][16];
35*fb1b10abSAndroid Build Coastguard Worker   ENTROPY_CONTEXT tl[MAX_MB_PLANE][16];
36*fb1b10abSAndroid Build Coastguard Worker };
37*fb1b10abSAndroid Build Coastguard Worker 
vp9_subtract_plane(MACROBLOCK * x,BLOCK_SIZE bsize,int plane)38*fb1b10abSAndroid Build Coastguard Worker void vp9_subtract_plane(MACROBLOCK *x, BLOCK_SIZE bsize, int plane) {
39*fb1b10abSAndroid Build Coastguard Worker   struct macroblock_plane *const p = &x->plane[plane];
40*fb1b10abSAndroid Build Coastguard Worker   const struct macroblockd_plane *const pd = &x->e_mbd.plane[plane];
41*fb1b10abSAndroid Build Coastguard Worker   const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
42*fb1b10abSAndroid Build Coastguard Worker   const int bw = 4 * num_4x4_blocks_wide_lookup[plane_bsize];
43*fb1b10abSAndroid Build Coastguard Worker   const int bh = 4 * num_4x4_blocks_high_lookup[plane_bsize];
44*fb1b10abSAndroid Build Coastguard Worker 
45*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
46*fb1b10abSAndroid Build Coastguard Worker   if (x->e_mbd.cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
47*fb1b10abSAndroid Build Coastguard Worker     vpx_highbd_subtract_block(bh, bw, p->src_diff, bw, p->src.buf,
48*fb1b10abSAndroid Build Coastguard Worker                               p->src.stride, pd->dst.buf, pd->dst.stride,
49*fb1b10abSAndroid Build Coastguard Worker                               x->e_mbd.bd);
50*fb1b10abSAndroid Build Coastguard Worker     return;
51*fb1b10abSAndroid Build Coastguard Worker   }
52*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
53*fb1b10abSAndroid Build Coastguard Worker   vpx_subtract_block(bh, bw, p->src_diff, bw, p->src.buf, p->src.stride,
54*fb1b10abSAndroid Build Coastguard Worker                      pd->dst.buf, pd->dst.stride);
55*fb1b10abSAndroid Build Coastguard Worker }
56*fb1b10abSAndroid Build Coastguard Worker 
57*fb1b10abSAndroid Build Coastguard Worker static const int plane_rd_mult[REF_TYPES][PLANE_TYPES] = {
58*fb1b10abSAndroid Build Coastguard Worker   { 10, 6 },
59*fb1b10abSAndroid Build Coastguard Worker   { 8, 5 },
60*fb1b10abSAndroid Build Coastguard Worker };
61*fb1b10abSAndroid Build Coastguard Worker 
62*fb1b10abSAndroid Build Coastguard Worker // 'num' can be negative, but 'shift' must be non-negative.
63*fb1b10abSAndroid Build Coastguard Worker #define RIGHT_SHIFT_POSSIBLY_NEGATIVE(num, shift) \
64*fb1b10abSAndroid Build Coastguard Worker   (((num) >= 0) ? (num) >> (shift) : -((-(num)) >> (shift)))
65*fb1b10abSAndroid Build Coastguard Worker 
vp9_optimize_b(MACROBLOCK * mb,int plane,int block,TX_SIZE tx_size,int ctx)66*fb1b10abSAndroid Build Coastguard Worker int vp9_optimize_b(MACROBLOCK *mb, int plane, int block, TX_SIZE tx_size,
67*fb1b10abSAndroid Build Coastguard Worker                    int ctx) {
68*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCKD *const xd = &mb->e_mbd;
69*fb1b10abSAndroid Build Coastguard Worker   struct macroblock_plane *const p = &mb->plane[plane];
70*fb1b10abSAndroid Build Coastguard Worker   struct macroblockd_plane *const pd = &xd->plane[plane];
71*fb1b10abSAndroid Build Coastguard Worker   const int ref = is_inter_block(xd->mi[0]);
72*fb1b10abSAndroid Build Coastguard Worker   uint8_t token_cache[1024];
73*fb1b10abSAndroid Build Coastguard Worker   const tran_low_t *const coeff = BLOCK_OFFSET(p->coeff, block);
74*fb1b10abSAndroid Build Coastguard Worker   tran_low_t *const qcoeff = BLOCK_OFFSET(p->qcoeff, block);
75*fb1b10abSAndroid Build Coastguard Worker   tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
76*fb1b10abSAndroid Build Coastguard Worker   const int eob = p->eobs[block];
77*fb1b10abSAndroid Build Coastguard Worker   const PLANE_TYPE plane_type = get_plane_type(plane);
78*fb1b10abSAndroid Build Coastguard Worker   const int default_eob = 16 << (tx_size << 1);
79*fb1b10abSAndroid Build Coastguard Worker   const int shift = (tx_size == TX_32X32);
80*fb1b10abSAndroid Build Coastguard Worker   const int16_t *const dequant_ptr = pd->dequant;
81*fb1b10abSAndroid Build Coastguard Worker   const uint8_t *const band_translate = get_band_translate(tx_size);
82*fb1b10abSAndroid Build Coastguard Worker   const ScanOrder *const so = get_scan(xd, tx_size, plane_type, block);
83*fb1b10abSAndroid Build Coastguard Worker   const int16_t *const scan = so->scan;
84*fb1b10abSAndroid Build Coastguard Worker   const int16_t *const nb = so->neighbors;
85*fb1b10abSAndroid Build Coastguard Worker   const MODE_INFO *mbmi = xd->mi[0];
86*fb1b10abSAndroid Build Coastguard Worker   const int sharpness = mb->sharpness;
87*fb1b10abSAndroid Build Coastguard Worker   const int64_t rdadj = (int64_t)mb->rdmult * plane_rd_mult[ref][plane_type];
88*fb1b10abSAndroid Build Coastguard Worker   const int64_t rdmult =
89*fb1b10abSAndroid Build Coastguard Worker       (sharpness == 0 ? rdadj >> 1
90*fb1b10abSAndroid Build Coastguard Worker                       : (rdadj * (8 - sharpness + mbmi->segment_id)) >> 4);
91*fb1b10abSAndroid Build Coastguard Worker 
92*fb1b10abSAndroid Build Coastguard Worker   const int64_t rddiv = mb->rddiv;
93*fb1b10abSAndroid Build Coastguard Worker   int64_t rd_cost0, rd_cost1;
94*fb1b10abSAndroid Build Coastguard Worker   int64_t rate0, rate1;
95*fb1b10abSAndroid Build Coastguard Worker   int16_t t0, t1;
96*fb1b10abSAndroid Build Coastguard Worker   int i, final_eob;
97*fb1b10abSAndroid Build Coastguard Worker   int count_high_values_after_eob = 0;
98*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
99*fb1b10abSAndroid Build Coastguard Worker   const uint16_t *cat6_high_cost = vp9_get_high_cost_table(xd->bd);
100*fb1b10abSAndroid Build Coastguard Worker #else
101*fb1b10abSAndroid Build Coastguard Worker   const uint16_t *cat6_high_cost = vp9_get_high_cost_table(8);
102*fb1b10abSAndroid Build Coastguard Worker #endif
103*fb1b10abSAndroid Build Coastguard Worker   unsigned int(*const token_costs)[2][COEFF_CONTEXTS][ENTROPY_TOKENS] =
104*fb1b10abSAndroid Build Coastguard Worker       mb->token_costs[tx_size][plane_type][ref];
105*fb1b10abSAndroid Build Coastguard Worker   unsigned int(*token_costs_cur)[2][COEFF_CONTEXTS][ENTROPY_TOKENS];
106*fb1b10abSAndroid Build Coastguard Worker   int64_t eob_cost0, eob_cost1;
107*fb1b10abSAndroid Build Coastguard Worker   const int ctx0 = ctx;
108*fb1b10abSAndroid Build Coastguard Worker   int64_t accu_rate = 0;
109*fb1b10abSAndroid Build Coastguard Worker   // Initialized to the worst possible error for the largest transform size.
110*fb1b10abSAndroid Build Coastguard Worker   // This ensures that it never goes negative.
111*fb1b10abSAndroid Build Coastguard Worker   int64_t accu_error = ((int64_t)1) << 50;
112*fb1b10abSAndroid Build Coastguard Worker   int64_t best_block_rd_cost = INT64_MAX;
113*fb1b10abSAndroid Build Coastguard Worker   int x_prev = 1;
114*fb1b10abSAndroid Build Coastguard Worker   tran_low_t before_best_eob_qc = 0;
115*fb1b10abSAndroid Build Coastguard Worker   tran_low_t before_best_eob_dqc = 0;
116*fb1b10abSAndroid Build Coastguard Worker 
117*fb1b10abSAndroid Build Coastguard Worker   assert((!plane_type && !plane) || (plane_type && plane));
118*fb1b10abSAndroid Build Coastguard Worker   assert(eob <= default_eob);
119*fb1b10abSAndroid Build Coastguard Worker 
120*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < eob; i++) {
121*fb1b10abSAndroid Build Coastguard Worker     const int rc = scan[i];
122*fb1b10abSAndroid Build Coastguard Worker     token_cache[rc] = vp9_pt_energy_class[vp9_get_token(qcoeff[rc])];
123*fb1b10abSAndroid Build Coastguard Worker   }
124*fb1b10abSAndroid Build Coastguard Worker   final_eob = 0;
125*fb1b10abSAndroid Build Coastguard Worker 
126*fb1b10abSAndroid Build Coastguard Worker   // Initial RD cost.
127*fb1b10abSAndroid Build Coastguard Worker   token_costs_cur = token_costs + band_translate[0];
128*fb1b10abSAndroid Build Coastguard Worker   rate0 = (*token_costs_cur)[0][ctx0][EOB_TOKEN];
129*fb1b10abSAndroid Build Coastguard Worker   best_block_rd_cost = RDCOST(rdmult, rddiv, rate0, accu_error);
130*fb1b10abSAndroid Build Coastguard Worker 
131*fb1b10abSAndroid Build Coastguard Worker   // For each token, pick one of two choices greedily:
132*fb1b10abSAndroid Build Coastguard Worker   // (i) First candidate: Keep current quantized value, OR
133*fb1b10abSAndroid Build Coastguard Worker   // (ii) Second candidate: Reduce quantized value by 1.
134*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < eob; i++) {
135*fb1b10abSAndroid Build Coastguard Worker     const int rc = scan[i];
136*fb1b10abSAndroid Build Coastguard Worker     const int x = qcoeff[rc];
137*fb1b10abSAndroid Build Coastguard Worker     const int band_cur = band_translate[i];
138*fb1b10abSAndroid Build Coastguard Worker     const int ctx_cur = (i == 0) ? ctx : get_coef_context(nb, token_cache, i);
139*fb1b10abSAndroid Build Coastguard Worker     const int token_tree_sel_cur = (x_prev == 0);
140*fb1b10abSAndroid Build Coastguard Worker     token_costs_cur = token_costs + band_cur;
141*fb1b10abSAndroid Build Coastguard Worker     if (x == 0) {  // No need to search
142*fb1b10abSAndroid Build Coastguard Worker       const int token = vp9_get_token(x);
143*fb1b10abSAndroid Build Coastguard Worker       rate0 = (*token_costs_cur)[token_tree_sel_cur][ctx_cur][token];
144*fb1b10abSAndroid Build Coastguard Worker       accu_rate += rate0;
145*fb1b10abSAndroid Build Coastguard Worker       x_prev = 0;
146*fb1b10abSAndroid Build Coastguard Worker       // Note: accu_error does not change.
147*fb1b10abSAndroid Build Coastguard Worker     } else {
148*fb1b10abSAndroid Build Coastguard Worker       const int dqv = dequant_ptr[rc != 0];
149*fb1b10abSAndroid Build Coastguard Worker       // Compute the distortion for quantizing to 0.
150*fb1b10abSAndroid Build Coastguard Worker       const int diff_for_zero_raw = (0 - coeff[rc]) * (1 << shift);
151*fb1b10abSAndroid Build Coastguard Worker       const int diff_for_zero =
152*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
153*fb1b10abSAndroid Build Coastguard Worker           (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
154*fb1b10abSAndroid Build Coastguard Worker               ? RIGHT_SHIFT_POSSIBLY_NEGATIVE(diff_for_zero_raw, xd->bd - 8)
155*fb1b10abSAndroid Build Coastguard Worker               :
156*fb1b10abSAndroid Build Coastguard Worker #endif
157*fb1b10abSAndroid Build Coastguard Worker               diff_for_zero_raw;
158*fb1b10abSAndroid Build Coastguard Worker       const int64_t distortion_for_zero =
159*fb1b10abSAndroid Build Coastguard Worker           (int64_t)diff_for_zero * diff_for_zero;
160*fb1b10abSAndroid Build Coastguard Worker 
161*fb1b10abSAndroid Build Coastguard Worker       // Compute the distortion for the first candidate
162*fb1b10abSAndroid Build Coastguard Worker       const int diff0_raw = (dqcoeff[rc] - coeff[rc]) * (1 << shift);
163*fb1b10abSAndroid Build Coastguard Worker       const int diff0 =
164*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
165*fb1b10abSAndroid Build Coastguard Worker           (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
166*fb1b10abSAndroid Build Coastguard Worker               ? RIGHT_SHIFT_POSSIBLY_NEGATIVE(diff0_raw, xd->bd - 8)
167*fb1b10abSAndroid Build Coastguard Worker               :
168*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
169*fb1b10abSAndroid Build Coastguard Worker               diff0_raw;
170*fb1b10abSAndroid Build Coastguard Worker       const int64_t distortion0 = (int64_t)diff0 * diff0;
171*fb1b10abSAndroid Build Coastguard Worker 
172*fb1b10abSAndroid Build Coastguard Worker       // Compute the distortion for the second candidate
173*fb1b10abSAndroid Build Coastguard Worker       const int sign = -(x < 0);        // -1 if x is negative and 0 otherwise.
174*fb1b10abSAndroid Build Coastguard Worker       const int x1 = x - 2 * sign - 1;  // abs(x1) = abs(x) - 1.
175*fb1b10abSAndroid Build Coastguard Worker       int64_t distortion1;
176*fb1b10abSAndroid Build Coastguard Worker       if (x1 != 0) {
177*fb1b10abSAndroid Build Coastguard Worker         const int dqv_step =
178*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
179*fb1b10abSAndroid Build Coastguard Worker             (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) ? dqv >> (xd->bd - 8)
180*fb1b10abSAndroid Build Coastguard Worker                                                           :
181*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
182*fb1b10abSAndroid Build Coastguard Worker                                                           dqv;
183*fb1b10abSAndroid Build Coastguard Worker         const int diff_step = (dqv_step + sign) ^ sign;
184*fb1b10abSAndroid Build Coastguard Worker         const int diff1 = diff0 - diff_step;
185*fb1b10abSAndroid Build Coastguard Worker         assert(dqv > 0);  // We aren't right shifting a negative number above.
186*fb1b10abSAndroid Build Coastguard Worker         distortion1 = (int64_t)diff1 * diff1;
187*fb1b10abSAndroid Build Coastguard Worker       } else {
188*fb1b10abSAndroid Build Coastguard Worker         distortion1 = distortion_for_zero;
189*fb1b10abSAndroid Build Coastguard Worker       }
190*fb1b10abSAndroid Build Coastguard Worker       {
191*fb1b10abSAndroid Build Coastguard Worker         // Calculate RDCost for current coeff for the two candidates.
192*fb1b10abSAndroid Build Coastguard Worker         const int64_t base_bits0 = vp9_get_token_cost(x, &t0, cat6_high_cost);
193*fb1b10abSAndroid Build Coastguard Worker         const int64_t base_bits1 = vp9_get_token_cost(x1, &t1, cat6_high_cost);
194*fb1b10abSAndroid Build Coastguard Worker         rate0 =
195*fb1b10abSAndroid Build Coastguard Worker             base_bits0 + (*token_costs_cur)[token_tree_sel_cur][ctx_cur][t0];
196*fb1b10abSAndroid Build Coastguard Worker         rate1 =
197*fb1b10abSAndroid Build Coastguard Worker             base_bits1 + (*token_costs_cur)[token_tree_sel_cur][ctx_cur][t1];
198*fb1b10abSAndroid Build Coastguard Worker       }
199*fb1b10abSAndroid Build Coastguard Worker       {
200*fb1b10abSAndroid Build Coastguard Worker         int rdcost_better_for_x1, eob_rdcost_better_for_x1;
201*fb1b10abSAndroid Build Coastguard Worker         int dqc0, dqc1;
202*fb1b10abSAndroid Build Coastguard Worker         int64_t best_eob_cost_cur;
203*fb1b10abSAndroid Build Coastguard Worker         int use_x1;
204*fb1b10abSAndroid Build Coastguard Worker 
205*fb1b10abSAndroid Build Coastguard Worker         // Calculate RD Cost effect on the next coeff for the two candidates.
206*fb1b10abSAndroid Build Coastguard Worker         int64_t next_bits0 = 0;
207*fb1b10abSAndroid Build Coastguard Worker         int64_t next_bits1 = 0;
208*fb1b10abSAndroid Build Coastguard Worker         int64_t next_eob_bits0 = 0;
209*fb1b10abSAndroid Build Coastguard Worker         int64_t next_eob_bits1 = 0;
210*fb1b10abSAndroid Build Coastguard Worker         if (i < default_eob - 1) {
211*fb1b10abSAndroid Build Coastguard Worker           int ctx_next, token_tree_sel_next;
212*fb1b10abSAndroid Build Coastguard Worker           const int band_next = band_translate[i + 1];
213*fb1b10abSAndroid Build Coastguard Worker           const int token_next =
214*fb1b10abSAndroid Build Coastguard Worker               (i + 1 != eob) ? vp9_get_token(qcoeff[scan[i + 1]]) : EOB_TOKEN;
215*fb1b10abSAndroid Build Coastguard Worker           unsigned int(*const token_costs_next)[2][COEFF_CONTEXTS]
216*fb1b10abSAndroid Build Coastguard Worker                                                [ENTROPY_TOKENS] =
217*fb1b10abSAndroid Build Coastguard Worker                                                    token_costs + band_next;
218*fb1b10abSAndroid Build Coastguard Worker           token_cache[rc] = vp9_pt_energy_class[t0];
219*fb1b10abSAndroid Build Coastguard Worker           ctx_next = get_coef_context(nb, token_cache, i + 1);
220*fb1b10abSAndroid Build Coastguard Worker           token_tree_sel_next = (x == 0);
221*fb1b10abSAndroid Build Coastguard Worker           next_bits0 =
222*fb1b10abSAndroid Build Coastguard Worker               (*token_costs_next)[token_tree_sel_next][ctx_next][token_next];
223*fb1b10abSAndroid Build Coastguard Worker           next_eob_bits0 =
224*fb1b10abSAndroid Build Coastguard Worker               (*token_costs_next)[token_tree_sel_next][ctx_next][EOB_TOKEN];
225*fb1b10abSAndroid Build Coastguard Worker           token_cache[rc] = vp9_pt_energy_class[t1];
226*fb1b10abSAndroid Build Coastguard Worker           ctx_next = get_coef_context(nb, token_cache, i + 1);
227*fb1b10abSAndroid Build Coastguard Worker           token_tree_sel_next = (x1 == 0);
228*fb1b10abSAndroid Build Coastguard Worker           next_bits1 =
229*fb1b10abSAndroid Build Coastguard Worker               (*token_costs_next)[token_tree_sel_next][ctx_next][token_next];
230*fb1b10abSAndroid Build Coastguard Worker           if (x1 != 0) {
231*fb1b10abSAndroid Build Coastguard Worker             next_eob_bits1 =
232*fb1b10abSAndroid Build Coastguard Worker                 (*token_costs_next)[token_tree_sel_next][ctx_next][EOB_TOKEN];
233*fb1b10abSAndroid Build Coastguard Worker           }
234*fb1b10abSAndroid Build Coastguard Worker         }
235*fb1b10abSAndroid Build Coastguard Worker 
236*fb1b10abSAndroid Build Coastguard Worker         // Compare the total RD costs for two candidates.
237*fb1b10abSAndroid Build Coastguard Worker         rd_cost0 = RDCOST(rdmult, rddiv, (rate0 + next_bits0), distortion0);
238*fb1b10abSAndroid Build Coastguard Worker         rd_cost1 = RDCOST(rdmult, rddiv, (rate1 + next_bits1), distortion1);
239*fb1b10abSAndroid Build Coastguard Worker         rdcost_better_for_x1 = (rd_cost1 < rd_cost0);
240*fb1b10abSAndroid Build Coastguard Worker         eob_cost0 = RDCOST(rdmult, rddiv, (accu_rate + rate0 + next_eob_bits0),
241*fb1b10abSAndroid Build Coastguard Worker                            (accu_error + distortion0 - distortion_for_zero));
242*fb1b10abSAndroid Build Coastguard Worker         eob_cost1 = eob_cost0;
243*fb1b10abSAndroid Build Coastguard Worker         if (x1 != 0) {
244*fb1b10abSAndroid Build Coastguard Worker           eob_cost1 =
245*fb1b10abSAndroid Build Coastguard Worker               RDCOST(rdmult, rddiv, (accu_rate + rate1 + next_eob_bits1),
246*fb1b10abSAndroid Build Coastguard Worker                      (accu_error + distortion1 - distortion_for_zero));
247*fb1b10abSAndroid Build Coastguard Worker           eob_rdcost_better_for_x1 = (eob_cost1 < eob_cost0);
248*fb1b10abSAndroid Build Coastguard Worker         } else {
249*fb1b10abSAndroid Build Coastguard Worker           eob_rdcost_better_for_x1 = 0;
250*fb1b10abSAndroid Build Coastguard Worker         }
251*fb1b10abSAndroid Build Coastguard Worker 
252*fb1b10abSAndroid Build Coastguard Worker         // Calculate the two candidate de-quantized values.
253*fb1b10abSAndroid Build Coastguard Worker         dqc0 = dqcoeff[rc];
254*fb1b10abSAndroid Build Coastguard Worker         dqc1 = 0;
255*fb1b10abSAndroid Build Coastguard Worker         if (rdcost_better_for_x1 + eob_rdcost_better_for_x1) {
256*fb1b10abSAndroid Build Coastguard Worker           if (x1 != 0) {
257*fb1b10abSAndroid Build Coastguard Worker             dqc1 = RIGHT_SHIFT_POSSIBLY_NEGATIVE(x1 * dqv, shift);
258*fb1b10abSAndroid Build Coastguard Worker           } else {
259*fb1b10abSAndroid Build Coastguard Worker             dqc1 = 0;
260*fb1b10abSAndroid Build Coastguard Worker           }
261*fb1b10abSAndroid Build Coastguard Worker         }
262*fb1b10abSAndroid Build Coastguard Worker 
263*fb1b10abSAndroid Build Coastguard Worker         // Pick and record the better quantized and de-quantized values.
264*fb1b10abSAndroid Build Coastguard Worker         if (rdcost_better_for_x1) {
265*fb1b10abSAndroid Build Coastguard Worker           qcoeff[rc] = x1;
266*fb1b10abSAndroid Build Coastguard Worker           dqcoeff[rc] = dqc1;
267*fb1b10abSAndroid Build Coastguard Worker           accu_rate += rate1;
268*fb1b10abSAndroid Build Coastguard Worker           accu_error += distortion1 - distortion_for_zero;
269*fb1b10abSAndroid Build Coastguard Worker           assert(distortion1 <= distortion_for_zero);
270*fb1b10abSAndroid Build Coastguard Worker           token_cache[rc] = vp9_pt_energy_class[t1];
271*fb1b10abSAndroid Build Coastguard Worker         } else {
272*fb1b10abSAndroid Build Coastguard Worker           accu_rate += rate0;
273*fb1b10abSAndroid Build Coastguard Worker           accu_error += distortion0 - distortion_for_zero;
274*fb1b10abSAndroid Build Coastguard Worker           assert(distortion0 <= distortion_for_zero);
275*fb1b10abSAndroid Build Coastguard Worker           token_cache[rc] = vp9_pt_energy_class[t0];
276*fb1b10abSAndroid Build Coastguard Worker         }
277*fb1b10abSAndroid Build Coastguard Worker         if (sharpness > 0 && abs(qcoeff[rc]) > 1) count_high_values_after_eob++;
278*fb1b10abSAndroid Build Coastguard Worker         assert(accu_error >= 0);
279*fb1b10abSAndroid Build Coastguard Worker         x_prev = qcoeff[rc];  // Update based on selected quantized value.
280*fb1b10abSAndroid Build Coastguard Worker 
281*fb1b10abSAndroid Build Coastguard Worker         use_x1 = (x1 != 0) && eob_rdcost_better_for_x1;
282*fb1b10abSAndroid Build Coastguard Worker         best_eob_cost_cur = use_x1 ? eob_cost1 : eob_cost0;
283*fb1b10abSAndroid Build Coastguard Worker 
284*fb1b10abSAndroid Build Coastguard Worker         // Determine whether to move the eob position to i+1
285*fb1b10abSAndroid Build Coastguard Worker         if (best_eob_cost_cur < best_block_rd_cost) {
286*fb1b10abSAndroid Build Coastguard Worker           best_block_rd_cost = best_eob_cost_cur;
287*fb1b10abSAndroid Build Coastguard Worker           final_eob = i + 1;
288*fb1b10abSAndroid Build Coastguard Worker           count_high_values_after_eob = 0;
289*fb1b10abSAndroid Build Coastguard Worker           if (use_x1) {
290*fb1b10abSAndroid Build Coastguard Worker             before_best_eob_qc = x1;
291*fb1b10abSAndroid Build Coastguard Worker             before_best_eob_dqc = dqc1;
292*fb1b10abSAndroid Build Coastguard Worker           } else {
293*fb1b10abSAndroid Build Coastguard Worker             before_best_eob_qc = x;
294*fb1b10abSAndroid Build Coastguard Worker             before_best_eob_dqc = dqc0;
295*fb1b10abSAndroid Build Coastguard Worker           }
296*fb1b10abSAndroid Build Coastguard Worker         }
297*fb1b10abSAndroid Build Coastguard Worker       }
298*fb1b10abSAndroid Build Coastguard Worker     }
299*fb1b10abSAndroid Build Coastguard Worker   }
300*fb1b10abSAndroid Build Coastguard Worker   if (count_high_values_after_eob > 0) {
301*fb1b10abSAndroid Build Coastguard Worker     final_eob = eob - 1;
302*fb1b10abSAndroid Build Coastguard Worker     for (; final_eob >= 0; final_eob--) {
303*fb1b10abSAndroid Build Coastguard Worker       const int rc = scan[final_eob];
304*fb1b10abSAndroid Build Coastguard Worker       const int x = qcoeff[rc];
305*fb1b10abSAndroid Build Coastguard Worker       if (x) {
306*fb1b10abSAndroid Build Coastguard Worker         break;
307*fb1b10abSAndroid Build Coastguard Worker       }
308*fb1b10abSAndroid Build Coastguard Worker     }
309*fb1b10abSAndroid Build Coastguard Worker     final_eob++;
310*fb1b10abSAndroid Build Coastguard Worker   } else {
311*fb1b10abSAndroid Build Coastguard Worker     assert(final_eob <= eob);
312*fb1b10abSAndroid Build Coastguard Worker     if (final_eob > 0) {
313*fb1b10abSAndroid Build Coastguard Worker       int rc;
314*fb1b10abSAndroid Build Coastguard Worker       assert(before_best_eob_qc != 0);
315*fb1b10abSAndroid Build Coastguard Worker       i = final_eob - 1;
316*fb1b10abSAndroid Build Coastguard Worker       rc = scan[i];
317*fb1b10abSAndroid Build Coastguard Worker       qcoeff[rc] = before_best_eob_qc;
318*fb1b10abSAndroid Build Coastguard Worker       dqcoeff[rc] = before_best_eob_dqc;
319*fb1b10abSAndroid Build Coastguard Worker     }
320*fb1b10abSAndroid Build Coastguard Worker     for (i = final_eob; i < eob; i++) {
321*fb1b10abSAndroid Build Coastguard Worker       int rc = scan[i];
322*fb1b10abSAndroid Build Coastguard Worker       qcoeff[rc] = 0;
323*fb1b10abSAndroid Build Coastguard Worker       dqcoeff[rc] = 0;
324*fb1b10abSAndroid Build Coastguard Worker     }
325*fb1b10abSAndroid Build Coastguard Worker   }
326*fb1b10abSAndroid Build Coastguard Worker   mb->plane[plane].eobs[block] = final_eob;
327*fb1b10abSAndroid Build Coastguard Worker   return final_eob;
328*fb1b10abSAndroid Build Coastguard Worker }
329*fb1b10abSAndroid Build Coastguard Worker #undef RIGHT_SHIFT_POSSIBLY_NEGATIVE
330*fb1b10abSAndroid Build Coastguard Worker 
fdct32x32(int rd_transform,const int16_t * src,tran_low_t * dst,int src_stride)331*fb1b10abSAndroid Build Coastguard Worker static INLINE void fdct32x32(int rd_transform, const int16_t *src,
332*fb1b10abSAndroid Build Coastguard Worker                              tran_low_t *dst, int src_stride) {
333*fb1b10abSAndroid Build Coastguard Worker   if (rd_transform)
334*fb1b10abSAndroid Build Coastguard Worker     vpx_fdct32x32_rd(src, dst, src_stride);
335*fb1b10abSAndroid Build Coastguard Worker   else
336*fb1b10abSAndroid Build Coastguard Worker     vpx_fdct32x32(src, dst, src_stride);
337*fb1b10abSAndroid Build Coastguard Worker }
338*fb1b10abSAndroid Build Coastguard Worker 
339*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
highbd_fdct32x32(int rd_transform,const int16_t * src,tran_low_t * dst,int src_stride)340*fb1b10abSAndroid Build Coastguard Worker static INLINE void highbd_fdct32x32(int rd_transform, const int16_t *src,
341*fb1b10abSAndroid Build Coastguard Worker                                     tran_low_t *dst, int src_stride) {
342*fb1b10abSAndroid Build Coastguard Worker   if (rd_transform)
343*fb1b10abSAndroid Build Coastguard Worker     vpx_highbd_fdct32x32_rd(src, dst, src_stride);
344*fb1b10abSAndroid Build Coastguard Worker   else
345*fb1b10abSAndroid Build Coastguard Worker     vpx_highbd_fdct32x32(src, dst, src_stride);
346*fb1b10abSAndroid Build Coastguard Worker }
347*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
348*fb1b10abSAndroid Build Coastguard Worker 
vp9_xform_quant_fp(MACROBLOCK * x,int plane,int block,int row,int col,BLOCK_SIZE plane_bsize,TX_SIZE tx_size)349*fb1b10abSAndroid Build Coastguard Worker void vp9_xform_quant_fp(MACROBLOCK *x, int plane, int block, int row, int col,
350*fb1b10abSAndroid Build Coastguard Worker                         BLOCK_SIZE plane_bsize, TX_SIZE tx_size) {
351*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCKD *const xd = &x->e_mbd;
352*fb1b10abSAndroid Build Coastguard Worker   const struct macroblock_plane *const p = &x->plane[plane];
353*fb1b10abSAndroid Build Coastguard Worker   const struct macroblockd_plane *const pd = &xd->plane[plane];
354*fb1b10abSAndroid Build Coastguard Worker   const ScanOrder *const scan_order = &vp9_default_scan_orders[tx_size];
355*fb1b10abSAndroid Build Coastguard Worker   tran_low_t *const coeff = BLOCK_OFFSET(p->coeff, block);
356*fb1b10abSAndroid Build Coastguard Worker   tran_low_t *const qcoeff = BLOCK_OFFSET(p->qcoeff, block);
357*fb1b10abSAndroid Build Coastguard Worker   tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
358*fb1b10abSAndroid Build Coastguard Worker   uint16_t *const eob = &p->eobs[block];
359*fb1b10abSAndroid Build Coastguard Worker   const int diff_stride = 4 * num_4x4_blocks_wide_lookup[plane_bsize];
360*fb1b10abSAndroid Build Coastguard Worker   const int16_t *src_diff;
361*fb1b10abSAndroid Build Coastguard Worker   src_diff = &p->src_diff[4 * (row * diff_stride + col)];
362*fb1b10abSAndroid Build Coastguard Worker   // skip block condition should be handled before this is called.
363*fb1b10abSAndroid Build Coastguard Worker   assert(!x->skip_block);
364*fb1b10abSAndroid Build Coastguard Worker 
365*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
366*fb1b10abSAndroid Build Coastguard Worker   if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
367*fb1b10abSAndroid Build Coastguard Worker     switch (tx_size) {
368*fb1b10abSAndroid Build Coastguard Worker       case TX_32X32:
369*fb1b10abSAndroid Build Coastguard Worker         highbd_fdct32x32(x->use_lp32x32fdct, src_diff, coeff, diff_stride);
370*fb1b10abSAndroid Build Coastguard Worker         vp9_highbd_quantize_fp_32x32(coeff, 1024, p, qcoeff, dqcoeff,
371*fb1b10abSAndroid Build Coastguard Worker                                      pd->dequant, eob, scan_order);
372*fb1b10abSAndroid Build Coastguard Worker         break;
373*fb1b10abSAndroid Build Coastguard Worker       case TX_16X16:
374*fb1b10abSAndroid Build Coastguard Worker         vpx_highbd_fdct16x16(src_diff, coeff, diff_stride);
375*fb1b10abSAndroid Build Coastguard Worker         vp9_highbd_quantize_fp(coeff, 256, p, qcoeff, dqcoeff, pd->dequant, eob,
376*fb1b10abSAndroid Build Coastguard Worker                                scan_order);
377*fb1b10abSAndroid Build Coastguard Worker         break;
378*fb1b10abSAndroid Build Coastguard Worker       case TX_8X8:
379*fb1b10abSAndroid Build Coastguard Worker         vpx_highbd_fdct8x8(src_diff, coeff, diff_stride);
380*fb1b10abSAndroid Build Coastguard Worker         vp9_highbd_quantize_fp(coeff, 64, p, qcoeff, dqcoeff, pd->dequant, eob,
381*fb1b10abSAndroid Build Coastguard Worker                                scan_order);
382*fb1b10abSAndroid Build Coastguard Worker         break;
383*fb1b10abSAndroid Build Coastguard Worker       default:
384*fb1b10abSAndroid Build Coastguard Worker         assert(tx_size == TX_4X4);
385*fb1b10abSAndroid Build Coastguard Worker         x->fwd_txfm4x4(src_diff, coeff, diff_stride);
386*fb1b10abSAndroid Build Coastguard Worker         vp9_highbd_quantize_fp(coeff, 16, p, qcoeff, dqcoeff, pd->dequant, eob,
387*fb1b10abSAndroid Build Coastguard Worker                                scan_order);
388*fb1b10abSAndroid Build Coastguard Worker         break;
389*fb1b10abSAndroid Build Coastguard Worker     }
390*fb1b10abSAndroid Build Coastguard Worker     return;
391*fb1b10abSAndroid Build Coastguard Worker   }
392*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
393*fb1b10abSAndroid Build Coastguard Worker 
394*fb1b10abSAndroid Build Coastguard Worker   switch (tx_size) {
395*fb1b10abSAndroid Build Coastguard Worker     case TX_32X32:
396*fb1b10abSAndroid Build Coastguard Worker       fdct32x32(x->use_lp32x32fdct, src_diff, coeff, diff_stride);
397*fb1b10abSAndroid Build Coastguard Worker       vp9_quantize_fp_32x32(coeff, 1024, p, qcoeff, dqcoeff, pd->dequant, eob,
398*fb1b10abSAndroid Build Coastguard Worker                             scan_order);
399*fb1b10abSAndroid Build Coastguard Worker       break;
400*fb1b10abSAndroid Build Coastguard Worker     case TX_16X16:
401*fb1b10abSAndroid Build Coastguard Worker       vpx_fdct16x16(src_diff, coeff, diff_stride);
402*fb1b10abSAndroid Build Coastguard Worker       vp9_quantize_fp(coeff, 256, p, qcoeff, dqcoeff, pd->dequant, eob,
403*fb1b10abSAndroid Build Coastguard Worker                       scan_order);
404*fb1b10abSAndroid Build Coastguard Worker       break;
405*fb1b10abSAndroid Build Coastguard Worker     case TX_8X8:
406*fb1b10abSAndroid Build Coastguard Worker       vpx_fdct8x8(src_diff, coeff, diff_stride);
407*fb1b10abSAndroid Build Coastguard Worker       vp9_quantize_fp(coeff, 64, p, qcoeff, dqcoeff, pd->dequant, eob,
408*fb1b10abSAndroid Build Coastguard Worker                       scan_order);
409*fb1b10abSAndroid Build Coastguard Worker 
410*fb1b10abSAndroid Build Coastguard Worker       break;
411*fb1b10abSAndroid Build Coastguard Worker     default:
412*fb1b10abSAndroid Build Coastguard Worker       assert(tx_size == TX_4X4);
413*fb1b10abSAndroid Build Coastguard Worker       x->fwd_txfm4x4(src_diff, coeff, diff_stride);
414*fb1b10abSAndroid Build Coastguard Worker       vp9_quantize_fp(coeff, 16, p, qcoeff, dqcoeff, pd->dequant, eob,
415*fb1b10abSAndroid Build Coastguard Worker                       scan_order);
416*fb1b10abSAndroid Build Coastguard Worker       break;
417*fb1b10abSAndroid Build Coastguard Worker   }
418*fb1b10abSAndroid Build Coastguard Worker }
419*fb1b10abSAndroid Build Coastguard Worker 
vp9_xform_quant_dc(MACROBLOCK * x,int plane,int block,int row,int col,BLOCK_SIZE plane_bsize,TX_SIZE tx_size)420*fb1b10abSAndroid Build Coastguard Worker void vp9_xform_quant_dc(MACROBLOCK *x, int plane, int block, int row, int col,
421*fb1b10abSAndroid Build Coastguard Worker                         BLOCK_SIZE plane_bsize, TX_SIZE tx_size) {
422*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCKD *const xd = &x->e_mbd;
423*fb1b10abSAndroid Build Coastguard Worker   const struct macroblock_plane *const p = &x->plane[plane];
424*fb1b10abSAndroid Build Coastguard Worker   const struct macroblockd_plane *const pd = &xd->plane[plane];
425*fb1b10abSAndroid Build Coastguard Worker   tran_low_t *const coeff = BLOCK_OFFSET(p->coeff, block);
426*fb1b10abSAndroid Build Coastguard Worker   tran_low_t *const qcoeff = BLOCK_OFFSET(p->qcoeff, block);
427*fb1b10abSAndroid Build Coastguard Worker   tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
428*fb1b10abSAndroid Build Coastguard Worker   uint16_t *const eob = &p->eobs[block];
429*fb1b10abSAndroid Build Coastguard Worker   const int diff_stride = 4 * num_4x4_blocks_wide_lookup[plane_bsize];
430*fb1b10abSAndroid Build Coastguard Worker   const int16_t *src_diff;
431*fb1b10abSAndroid Build Coastguard Worker   src_diff = &p->src_diff[4 * (row * diff_stride + col)];
432*fb1b10abSAndroid Build Coastguard Worker   // skip block condition should be handled before this is called.
433*fb1b10abSAndroid Build Coastguard Worker   assert(!x->skip_block);
434*fb1b10abSAndroid Build Coastguard Worker 
435*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
436*fb1b10abSAndroid Build Coastguard Worker   if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
437*fb1b10abSAndroid Build Coastguard Worker     switch (tx_size) {
438*fb1b10abSAndroid Build Coastguard Worker       case TX_32X32:
439*fb1b10abSAndroid Build Coastguard Worker         vpx_highbd_fdct32x32_1(src_diff, coeff, diff_stride);
440*fb1b10abSAndroid Build Coastguard Worker         vpx_highbd_quantize_dc_32x32(coeff, p->round, p->quant_fp[0], qcoeff,
441*fb1b10abSAndroid Build Coastguard Worker                                      dqcoeff, pd->dequant[0], eob);
442*fb1b10abSAndroid Build Coastguard Worker         break;
443*fb1b10abSAndroid Build Coastguard Worker       case TX_16X16:
444*fb1b10abSAndroid Build Coastguard Worker         vpx_highbd_fdct16x16_1(src_diff, coeff, diff_stride);
445*fb1b10abSAndroid Build Coastguard Worker         vpx_highbd_quantize_dc(coeff, 256, p->round, p->quant_fp[0], qcoeff,
446*fb1b10abSAndroid Build Coastguard Worker                                dqcoeff, pd->dequant[0], eob);
447*fb1b10abSAndroid Build Coastguard Worker         break;
448*fb1b10abSAndroid Build Coastguard Worker       case TX_8X8:
449*fb1b10abSAndroid Build Coastguard Worker         vpx_highbd_fdct8x8_1(src_diff, coeff, diff_stride);
450*fb1b10abSAndroid Build Coastguard Worker         vpx_highbd_quantize_dc(coeff, 64, p->round, p->quant_fp[0], qcoeff,
451*fb1b10abSAndroid Build Coastguard Worker                                dqcoeff, pd->dequant[0], eob);
452*fb1b10abSAndroid Build Coastguard Worker         break;
453*fb1b10abSAndroid Build Coastguard Worker       default:
454*fb1b10abSAndroid Build Coastguard Worker         assert(tx_size == TX_4X4);
455*fb1b10abSAndroid Build Coastguard Worker         x->fwd_txfm4x4(src_diff, coeff, diff_stride);
456*fb1b10abSAndroid Build Coastguard Worker         vpx_highbd_quantize_dc(coeff, 16, p->round, p->quant_fp[0], qcoeff,
457*fb1b10abSAndroid Build Coastguard Worker                                dqcoeff, pd->dequant[0], eob);
458*fb1b10abSAndroid Build Coastguard Worker         break;
459*fb1b10abSAndroid Build Coastguard Worker     }
460*fb1b10abSAndroid Build Coastguard Worker     return;
461*fb1b10abSAndroid Build Coastguard Worker   }
462*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
463*fb1b10abSAndroid Build Coastguard Worker 
464*fb1b10abSAndroid Build Coastguard Worker   switch (tx_size) {
465*fb1b10abSAndroid Build Coastguard Worker     case TX_32X32:
466*fb1b10abSAndroid Build Coastguard Worker       vpx_fdct32x32_1(src_diff, coeff, diff_stride);
467*fb1b10abSAndroid Build Coastguard Worker       vpx_quantize_dc_32x32(coeff, p->round, p->quant_fp[0], qcoeff, dqcoeff,
468*fb1b10abSAndroid Build Coastguard Worker                             pd->dequant[0], eob);
469*fb1b10abSAndroid Build Coastguard Worker       break;
470*fb1b10abSAndroid Build Coastguard Worker     case TX_16X16:
471*fb1b10abSAndroid Build Coastguard Worker       vpx_fdct16x16_1(src_diff, coeff, diff_stride);
472*fb1b10abSAndroid Build Coastguard Worker       vpx_quantize_dc(coeff, 256, p->round, p->quant_fp[0], qcoeff, dqcoeff,
473*fb1b10abSAndroid Build Coastguard Worker                       pd->dequant[0], eob);
474*fb1b10abSAndroid Build Coastguard Worker       break;
475*fb1b10abSAndroid Build Coastguard Worker     case TX_8X8:
476*fb1b10abSAndroid Build Coastguard Worker       vpx_fdct8x8_1(src_diff, coeff, diff_stride);
477*fb1b10abSAndroid Build Coastguard Worker       vpx_quantize_dc(coeff, 64, p->round, p->quant_fp[0], qcoeff, dqcoeff,
478*fb1b10abSAndroid Build Coastguard Worker                       pd->dequant[0], eob);
479*fb1b10abSAndroid Build Coastguard Worker       break;
480*fb1b10abSAndroid Build Coastguard Worker     default:
481*fb1b10abSAndroid Build Coastguard Worker       assert(tx_size == TX_4X4);
482*fb1b10abSAndroid Build Coastguard Worker       x->fwd_txfm4x4(src_diff, coeff, diff_stride);
483*fb1b10abSAndroid Build Coastguard Worker       vpx_quantize_dc(coeff, 16, p->round, p->quant_fp[0], qcoeff, dqcoeff,
484*fb1b10abSAndroid Build Coastguard Worker                       pd->dequant[0], eob);
485*fb1b10abSAndroid Build Coastguard Worker       break;
486*fb1b10abSAndroid Build Coastguard Worker   }
487*fb1b10abSAndroid Build Coastguard Worker }
488*fb1b10abSAndroid Build Coastguard Worker 
vp9_xform_quant(MACROBLOCK * x,int plane,int block,int row,int col,BLOCK_SIZE plane_bsize,TX_SIZE tx_size)489*fb1b10abSAndroid Build Coastguard Worker void vp9_xform_quant(MACROBLOCK *x, int plane, int block, int row, int col,
490*fb1b10abSAndroid Build Coastguard Worker                      BLOCK_SIZE plane_bsize, TX_SIZE tx_size) {
491*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCKD *const xd = &x->e_mbd;
492*fb1b10abSAndroid Build Coastguard Worker   const struct macroblock_plane *const p = &x->plane[plane];
493*fb1b10abSAndroid Build Coastguard Worker   const struct macroblockd_plane *const pd = &xd->plane[plane];
494*fb1b10abSAndroid Build Coastguard Worker   const ScanOrder *const scan_order = &vp9_default_scan_orders[tx_size];
495*fb1b10abSAndroid Build Coastguard Worker   tran_low_t *const coeff = BLOCK_OFFSET(p->coeff, block);
496*fb1b10abSAndroid Build Coastguard Worker   tran_low_t *const qcoeff = BLOCK_OFFSET(p->qcoeff, block);
497*fb1b10abSAndroid Build Coastguard Worker   tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
498*fb1b10abSAndroid Build Coastguard Worker   uint16_t *const eob = &p->eobs[block];
499*fb1b10abSAndroid Build Coastguard Worker   const int diff_stride = 4 * num_4x4_blocks_wide_lookup[plane_bsize];
500*fb1b10abSAndroid Build Coastguard Worker   const int16_t *src_diff;
501*fb1b10abSAndroid Build Coastguard Worker   src_diff = &p->src_diff[4 * (row * diff_stride + col)];
502*fb1b10abSAndroid Build Coastguard Worker   // skip block condition should be handled before this is called.
503*fb1b10abSAndroid Build Coastguard Worker   assert(!x->skip_block);
504*fb1b10abSAndroid Build Coastguard Worker 
505*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
506*fb1b10abSAndroid Build Coastguard Worker   if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
507*fb1b10abSAndroid Build Coastguard Worker     switch (tx_size) {
508*fb1b10abSAndroid Build Coastguard Worker       case TX_32X32:
509*fb1b10abSAndroid Build Coastguard Worker         highbd_fdct32x32(x->use_lp32x32fdct, src_diff, coeff, diff_stride);
510*fb1b10abSAndroid Build Coastguard Worker         vpx_highbd_quantize_b_32x32(coeff, p, qcoeff, dqcoeff, pd->dequant, eob,
511*fb1b10abSAndroid Build Coastguard Worker                                     scan_order);
512*fb1b10abSAndroid Build Coastguard Worker         break;
513*fb1b10abSAndroid Build Coastguard Worker       case TX_16X16:
514*fb1b10abSAndroid Build Coastguard Worker         vpx_highbd_fdct16x16(src_diff, coeff, diff_stride);
515*fb1b10abSAndroid Build Coastguard Worker         vpx_highbd_quantize_b(coeff, 256, p, qcoeff, dqcoeff, pd->dequant, eob,
516*fb1b10abSAndroid Build Coastguard Worker                               scan_order);
517*fb1b10abSAndroid Build Coastguard Worker         break;
518*fb1b10abSAndroid Build Coastguard Worker       case TX_8X8:
519*fb1b10abSAndroid Build Coastguard Worker         vpx_highbd_fdct8x8(src_diff, coeff, diff_stride);
520*fb1b10abSAndroid Build Coastguard Worker         vpx_highbd_quantize_b(coeff, 64, p, qcoeff, dqcoeff, pd->dequant, eob,
521*fb1b10abSAndroid Build Coastguard Worker                               scan_order);
522*fb1b10abSAndroid Build Coastguard Worker         break;
523*fb1b10abSAndroid Build Coastguard Worker       default:
524*fb1b10abSAndroid Build Coastguard Worker         assert(tx_size == TX_4X4);
525*fb1b10abSAndroid Build Coastguard Worker         x->fwd_txfm4x4(src_diff, coeff, diff_stride);
526*fb1b10abSAndroid Build Coastguard Worker         vpx_highbd_quantize_b(coeff, 16, p, qcoeff, dqcoeff, pd->dequant, eob,
527*fb1b10abSAndroid Build Coastguard Worker                               scan_order);
528*fb1b10abSAndroid Build Coastguard Worker         break;
529*fb1b10abSAndroid Build Coastguard Worker     }
530*fb1b10abSAndroid Build Coastguard Worker     return;
531*fb1b10abSAndroid Build Coastguard Worker   }
532*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
533*fb1b10abSAndroid Build Coastguard Worker 
534*fb1b10abSAndroid Build Coastguard Worker   switch (tx_size) {
535*fb1b10abSAndroid Build Coastguard Worker     case TX_32X32:
536*fb1b10abSAndroid Build Coastguard Worker       fdct32x32(x->use_lp32x32fdct, src_diff, coeff, diff_stride);
537*fb1b10abSAndroid Build Coastguard Worker       vpx_quantize_b_32x32(coeff, p, qcoeff, dqcoeff, pd->dequant, eob,
538*fb1b10abSAndroid Build Coastguard Worker                            scan_order);
539*fb1b10abSAndroid Build Coastguard Worker       break;
540*fb1b10abSAndroid Build Coastguard Worker     case TX_16X16:
541*fb1b10abSAndroid Build Coastguard Worker       vpx_fdct16x16(src_diff, coeff, diff_stride);
542*fb1b10abSAndroid Build Coastguard Worker       vpx_quantize_b(coeff, 256, p, qcoeff, dqcoeff, pd->dequant, eob,
543*fb1b10abSAndroid Build Coastguard Worker                      scan_order);
544*fb1b10abSAndroid Build Coastguard Worker       break;
545*fb1b10abSAndroid Build Coastguard Worker     case TX_8X8:
546*fb1b10abSAndroid Build Coastguard Worker       vpx_fdct8x8(src_diff, coeff, diff_stride);
547*fb1b10abSAndroid Build Coastguard Worker       vpx_quantize_b(coeff, 64, p, qcoeff, dqcoeff, pd->dequant, eob,
548*fb1b10abSAndroid Build Coastguard Worker                      scan_order);
549*fb1b10abSAndroid Build Coastguard Worker       break;
550*fb1b10abSAndroid Build Coastguard Worker     default:
551*fb1b10abSAndroid Build Coastguard Worker       assert(tx_size == TX_4X4);
552*fb1b10abSAndroid Build Coastguard Worker       x->fwd_txfm4x4(src_diff, coeff, diff_stride);
553*fb1b10abSAndroid Build Coastguard Worker       vpx_quantize_b(coeff, 16, p, qcoeff, dqcoeff, pd->dequant, eob,
554*fb1b10abSAndroid Build Coastguard Worker                      scan_order);
555*fb1b10abSAndroid Build Coastguard Worker       break;
556*fb1b10abSAndroid Build Coastguard Worker   }
557*fb1b10abSAndroid Build Coastguard Worker }
558*fb1b10abSAndroid Build Coastguard Worker 
encode_block(int plane,int block,int row,int col,BLOCK_SIZE plane_bsize,TX_SIZE tx_size,void * arg)559*fb1b10abSAndroid Build Coastguard Worker static void encode_block(int plane, int block, int row, int col,
560*fb1b10abSAndroid Build Coastguard Worker                          BLOCK_SIZE plane_bsize, TX_SIZE tx_size, void *arg) {
561*fb1b10abSAndroid Build Coastguard Worker   struct encode_b_args *const args = arg;
562*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MISMATCH_DEBUG
563*fb1b10abSAndroid Build Coastguard Worker   int mi_row = args->mi_row;
564*fb1b10abSAndroid Build Coastguard Worker   int mi_col = args->mi_col;
565*fb1b10abSAndroid Build Coastguard Worker   int output_enabled = args->output_enabled;
566*fb1b10abSAndroid Build Coastguard Worker #endif
567*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCK *const x = args->x;
568*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCKD *const xd = &x->e_mbd;
569*fb1b10abSAndroid Build Coastguard Worker   struct macroblock_plane *const p = &x->plane[plane];
570*fb1b10abSAndroid Build Coastguard Worker   struct macroblockd_plane *const pd = &xd->plane[plane];
571*fb1b10abSAndroid Build Coastguard Worker   tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
572*fb1b10abSAndroid Build Coastguard Worker   uint8_t *dst;
573*fb1b10abSAndroid Build Coastguard Worker   ENTROPY_CONTEXT *a, *l;
574*fb1b10abSAndroid Build Coastguard Worker   dst = &pd->dst.buf[4 * row * pd->dst.stride + 4 * col];
575*fb1b10abSAndroid Build Coastguard Worker   a = &args->ta[col];
576*fb1b10abSAndroid Build Coastguard Worker   l = &args->tl[row];
577*fb1b10abSAndroid Build Coastguard Worker 
578*fb1b10abSAndroid Build Coastguard Worker   // TODO(jingning): per transformed block zero forcing only enabled for
579*fb1b10abSAndroid Build Coastguard Worker   // luma component. will integrate chroma components as well.
580*fb1b10abSAndroid Build Coastguard Worker   if (x->zcoeff_blk[tx_size][block] && plane == 0) {
581*fb1b10abSAndroid Build Coastguard Worker     p->eobs[block] = 0;
582*fb1b10abSAndroid Build Coastguard Worker     *a = *l = 0;
583*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MISMATCH_DEBUG
584*fb1b10abSAndroid Build Coastguard Worker     goto encode_block_end;
585*fb1b10abSAndroid Build Coastguard Worker #else
586*fb1b10abSAndroid Build Coastguard Worker     return;
587*fb1b10abSAndroid Build Coastguard Worker #endif
588*fb1b10abSAndroid Build Coastguard Worker   }
589*fb1b10abSAndroid Build Coastguard Worker 
590*fb1b10abSAndroid Build Coastguard Worker   if (!x->skip_recode) {
591*fb1b10abSAndroid Build Coastguard Worker     if (x->quant_fp) {
592*fb1b10abSAndroid Build Coastguard Worker       // Encoding process for rtc mode
593*fb1b10abSAndroid Build Coastguard Worker       if (x->skip_txfm[0] == SKIP_TXFM_AC_DC && plane == 0) {
594*fb1b10abSAndroid Build Coastguard Worker         // skip forward transform
595*fb1b10abSAndroid Build Coastguard Worker         p->eobs[block] = 0;
596*fb1b10abSAndroid Build Coastguard Worker         *a = *l = 0;
597*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MISMATCH_DEBUG
598*fb1b10abSAndroid Build Coastguard Worker         goto encode_block_end;
599*fb1b10abSAndroid Build Coastguard Worker #else
600*fb1b10abSAndroid Build Coastguard Worker         return;
601*fb1b10abSAndroid Build Coastguard Worker #endif
602*fb1b10abSAndroid Build Coastguard Worker       } else {
603*fb1b10abSAndroid Build Coastguard Worker         vp9_xform_quant_fp(x, plane, block, row, col, plane_bsize, tx_size);
604*fb1b10abSAndroid Build Coastguard Worker       }
605*fb1b10abSAndroid Build Coastguard Worker     } else {
606*fb1b10abSAndroid Build Coastguard Worker       if (max_txsize_lookup[plane_bsize] == tx_size) {
607*fb1b10abSAndroid Build Coastguard Worker         int txfm_blk_index = (plane << 2) + (block >> (tx_size << 1));
608*fb1b10abSAndroid Build Coastguard Worker         if (x->skip_txfm[txfm_blk_index] == SKIP_TXFM_NONE) {
609*fb1b10abSAndroid Build Coastguard Worker           // full forward transform and quantization
610*fb1b10abSAndroid Build Coastguard Worker           vp9_xform_quant(x, plane, block, row, col, plane_bsize, tx_size);
611*fb1b10abSAndroid Build Coastguard Worker         } else if (x->skip_txfm[txfm_blk_index] == SKIP_TXFM_AC_ONLY) {
612*fb1b10abSAndroid Build Coastguard Worker           // fast path forward transform and quantization
613*fb1b10abSAndroid Build Coastguard Worker           vp9_xform_quant_dc(x, plane, block, row, col, plane_bsize, tx_size);
614*fb1b10abSAndroid Build Coastguard Worker         } else {
615*fb1b10abSAndroid Build Coastguard Worker           // skip forward transform
616*fb1b10abSAndroid Build Coastguard Worker           p->eobs[block] = 0;
617*fb1b10abSAndroid Build Coastguard Worker           *a = *l = 0;
618*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MISMATCH_DEBUG
619*fb1b10abSAndroid Build Coastguard Worker           goto encode_block_end;
620*fb1b10abSAndroid Build Coastguard Worker #else
621*fb1b10abSAndroid Build Coastguard Worker           return;
622*fb1b10abSAndroid Build Coastguard Worker #endif
623*fb1b10abSAndroid Build Coastguard Worker         }
624*fb1b10abSAndroid Build Coastguard Worker       } else {
625*fb1b10abSAndroid Build Coastguard Worker         vp9_xform_quant(x, plane, block, row, col, plane_bsize, tx_size);
626*fb1b10abSAndroid Build Coastguard Worker       }
627*fb1b10abSAndroid Build Coastguard Worker     }
628*fb1b10abSAndroid Build Coastguard Worker   }
629*fb1b10abSAndroid Build Coastguard Worker 
630*fb1b10abSAndroid Build Coastguard Worker   if (x->optimize && (!x->skip_recode || !x->skip_optimize)) {
631*fb1b10abSAndroid Build Coastguard Worker     const int ctx = combine_entropy_contexts(*a, *l);
632*fb1b10abSAndroid Build Coastguard Worker     *a = *l = vp9_optimize_b(x, plane, block, tx_size, ctx) > 0;
633*fb1b10abSAndroid Build Coastguard Worker   } else {
634*fb1b10abSAndroid Build Coastguard Worker     *a = *l = p->eobs[block] > 0;
635*fb1b10abSAndroid Build Coastguard Worker   }
636*fb1b10abSAndroid Build Coastguard Worker 
637*fb1b10abSAndroid Build Coastguard Worker   if (p->eobs[block]) *(args->skip) = 0;
638*fb1b10abSAndroid Build Coastguard Worker 
639*fb1b10abSAndroid Build Coastguard Worker   if (x->skip_encode || p->eobs[block] == 0) {
640*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MISMATCH_DEBUG
641*fb1b10abSAndroid Build Coastguard Worker     goto encode_block_end;
642*fb1b10abSAndroid Build Coastguard Worker #else
643*fb1b10abSAndroid Build Coastguard Worker     return;
644*fb1b10abSAndroid Build Coastguard Worker #endif
645*fb1b10abSAndroid Build Coastguard Worker   }
646*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
647*fb1b10abSAndroid Build Coastguard Worker   if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
648*fb1b10abSAndroid Build Coastguard Worker     uint16_t *const dst16 = CONVERT_TO_SHORTPTR(dst);
649*fb1b10abSAndroid Build Coastguard Worker     switch (tx_size) {
650*fb1b10abSAndroid Build Coastguard Worker       case TX_32X32:
651*fb1b10abSAndroid Build Coastguard Worker         vp9_highbd_idct32x32_add(dqcoeff, dst16, pd->dst.stride, p->eobs[block],
652*fb1b10abSAndroid Build Coastguard Worker                                  xd->bd);
653*fb1b10abSAndroid Build Coastguard Worker         break;
654*fb1b10abSAndroid Build Coastguard Worker       case TX_16X16:
655*fb1b10abSAndroid Build Coastguard Worker         vp9_highbd_idct16x16_add(dqcoeff, dst16, pd->dst.stride, p->eobs[block],
656*fb1b10abSAndroid Build Coastguard Worker                                  xd->bd);
657*fb1b10abSAndroid Build Coastguard Worker         break;
658*fb1b10abSAndroid Build Coastguard Worker       case TX_8X8:
659*fb1b10abSAndroid Build Coastguard Worker         vp9_highbd_idct8x8_add(dqcoeff, dst16, pd->dst.stride, p->eobs[block],
660*fb1b10abSAndroid Build Coastguard Worker                                xd->bd);
661*fb1b10abSAndroid Build Coastguard Worker         break;
662*fb1b10abSAndroid Build Coastguard Worker       default:
663*fb1b10abSAndroid Build Coastguard Worker         assert(tx_size == TX_4X4);
664*fb1b10abSAndroid Build Coastguard Worker         // this is like vp9_short_idct4x4 but has a special case around eob<=1
665*fb1b10abSAndroid Build Coastguard Worker         // which is significant (not just an optimization) for the lossless
666*fb1b10abSAndroid Build Coastguard Worker         // case.
667*fb1b10abSAndroid Build Coastguard Worker         x->highbd_inv_txfm_add(dqcoeff, dst16, pd->dst.stride, p->eobs[block],
668*fb1b10abSAndroid Build Coastguard Worker                                xd->bd);
669*fb1b10abSAndroid Build Coastguard Worker         break;
670*fb1b10abSAndroid Build Coastguard Worker     }
671*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MISMATCH_DEBUG
672*fb1b10abSAndroid Build Coastguard Worker     goto encode_block_end;
673*fb1b10abSAndroid Build Coastguard Worker #else
674*fb1b10abSAndroid Build Coastguard Worker     return;
675*fb1b10abSAndroid Build Coastguard Worker #endif
676*fb1b10abSAndroid Build Coastguard Worker   }
677*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
678*fb1b10abSAndroid Build Coastguard Worker 
679*fb1b10abSAndroid Build Coastguard Worker   switch (tx_size) {
680*fb1b10abSAndroid Build Coastguard Worker     case TX_32X32:
681*fb1b10abSAndroid Build Coastguard Worker       vp9_idct32x32_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
682*fb1b10abSAndroid Build Coastguard Worker       break;
683*fb1b10abSAndroid Build Coastguard Worker     case TX_16X16:
684*fb1b10abSAndroid Build Coastguard Worker       vp9_idct16x16_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
685*fb1b10abSAndroid Build Coastguard Worker       break;
686*fb1b10abSAndroid Build Coastguard Worker     case TX_8X8:
687*fb1b10abSAndroid Build Coastguard Worker       vp9_idct8x8_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
688*fb1b10abSAndroid Build Coastguard Worker       break;
689*fb1b10abSAndroid Build Coastguard Worker     default:
690*fb1b10abSAndroid Build Coastguard Worker       assert(tx_size == TX_4X4);
691*fb1b10abSAndroid Build Coastguard Worker       // this is like vp9_short_idct4x4 but has a special case around eob<=1
692*fb1b10abSAndroid Build Coastguard Worker       // which is significant (not just an optimization) for the lossless
693*fb1b10abSAndroid Build Coastguard Worker       // case.
694*fb1b10abSAndroid Build Coastguard Worker       x->inv_txfm_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
695*fb1b10abSAndroid Build Coastguard Worker       break;
696*fb1b10abSAndroid Build Coastguard Worker   }
697*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MISMATCH_DEBUG
698*fb1b10abSAndroid Build Coastguard Worker encode_block_end:
699*fb1b10abSAndroid Build Coastguard Worker   if (output_enabled) {
700*fb1b10abSAndroid Build Coastguard Worker     int pixel_c, pixel_r;
701*fb1b10abSAndroid Build Coastguard Worker     int blk_w = 1 << (tx_size + TX_UNIT_SIZE_LOG2);
702*fb1b10abSAndroid Build Coastguard Worker     int blk_h = 1 << (tx_size + TX_UNIT_SIZE_LOG2);
703*fb1b10abSAndroid Build Coastguard Worker     mi_to_pixel_loc(&pixel_c, &pixel_r, mi_col, mi_row, col, row,
704*fb1b10abSAndroid Build Coastguard Worker                     pd->subsampling_x, pd->subsampling_y);
705*fb1b10abSAndroid Build Coastguard Worker     mismatch_record_block_tx(dst, pd->dst.stride, plane, pixel_c, pixel_r,
706*fb1b10abSAndroid Build Coastguard Worker                              blk_w, blk_h,
707*fb1b10abSAndroid Build Coastguard Worker                              xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH);
708*fb1b10abSAndroid Build Coastguard Worker   }
709*fb1b10abSAndroid Build Coastguard Worker #endif
710*fb1b10abSAndroid Build Coastguard Worker }
711*fb1b10abSAndroid Build Coastguard Worker 
encode_block_pass1(int plane,int block,int row,int col,BLOCK_SIZE plane_bsize,TX_SIZE tx_size,void * arg)712*fb1b10abSAndroid Build Coastguard Worker static void encode_block_pass1(int plane, int block, int row, int col,
713*fb1b10abSAndroid Build Coastguard Worker                                BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
714*fb1b10abSAndroid Build Coastguard Worker                                void *arg) {
715*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCK *const x = (MACROBLOCK *)arg;
716*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCKD *const xd = &x->e_mbd;
717*fb1b10abSAndroid Build Coastguard Worker   struct macroblock_plane *const p = &x->plane[plane];
718*fb1b10abSAndroid Build Coastguard Worker   struct macroblockd_plane *const pd = &xd->plane[plane];
719*fb1b10abSAndroid Build Coastguard Worker   tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
720*fb1b10abSAndroid Build Coastguard Worker   uint8_t *dst;
721*fb1b10abSAndroid Build Coastguard Worker   dst = &pd->dst.buf[4 * row * pd->dst.stride + 4 * col];
722*fb1b10abSAndroid Build Coastguard Worker 
723*fb1b10abSAndroid Build Coastguard Worker   vp9_xform_quant(x, plane, block, row, col, plane_bsize, tx_size);
724*fb1b10abSAndroid Build Coastguard Worker 
725*fb1b10abSAndroid Build Coastguard Worker   if (p->eobs[block] > 0) {
726*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
727*fb1b10abSAndroid Build Coastguard Worker     if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
728*fb1b10abSAndroid Build Coastguard Worker       x->highbd_inv_txfm_add(dqcoeff, CONVERT_TO_SHORTPTR(dst), pd->dst.stride,
729*fb1b10abSAndroid Build Coastguard Worker                              p->eobs[block], xd->bd);
730*fb1b10abSAndroid Build Coastguard Worker       return;
731*fb1b10abSAndroid Build Coastguard Worker     }
732*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
733*fb1b10abSAndroid Build Coastguard Worker     x->inv_txfm_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
734*fb1b10abSAndroid Build Coastguard Worker   }
735*fb1b10abSAndroid Build Coastguard Worker }
736*fb1b10abSAndroid Build Coastguard Worker 
vp9_encode_sby_pass1(MACROBLOCK * x,BLOCK_SIZE bsize)737*fb1b10abSAndroid Build Coastguard Worker void vp9_encode_sby_pass1(MACROBLOCK *x, BLOCK_SIZE bsize) {
738*fb1b10abSAndroid Build Coastguard Worker   vp9_subtract_plane(x, bsize, 0);
739*fb1b10abSAndroid Build Coastguard Worker   vp9_foreach_transformed_block_in_plane(&x->e_mbd, bsize, 0,
740*fb1b10abSAndroid Build Coastguard Worker                                          encode_block_pass1, x);
741*fb1b10abSAndroid Build Coastguard Worker }
742*fb1b10abSAndroid Build Coastguard Worker 
vp9_encode_sb(MACROBLOCK * x,BLOCK_SIZE bsize,int mi_row,int mi_col,int output_enabled)743*fb1b10abSAndroid Build Coastguard Worker void vp9_encode_sb(MACROBLOCK *x, BLOCK_SIZE bsize, int mi_row, int mi_col,
744*fb1b10abSAndroid Build Coastguard Worker                    int output_enabled) {
745*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCKD *const xd = &x->e_mbd;
746*fb1b10abSAndroid Build Coastguard Worker   struct optimize_ctx ctx;
747*fb1b10abSAndroid Build Coastguard Worker   MODE_INFO *mi = xd->mi[0];
748*fb1b10abSAndroid Build Coastguard Worker   int plane;
749*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MISMATCH_DEBUG
750*fb1b10abSAndroid Build Coastguard Worker   struct encode_b_args arg = { x,
751*fb1b10abSAndroid Build Coastguard Worker                                1,     // enable_trellis_opt
752*fb1b10abSAndroid Build Coastguard Worker                                0.0,   // trellis_opt_thresh
753*fb1b10abSAndroid Build Coastguard Worker                                NULL,  // &sse_calc_done
754*fb1b10abSAndroid Build Coastguard Worker                                NULL,  // &sse
755*fb1b10abSAndroid Build Coastguard Worker                                NULL,  // above entropy context
756*fb1b10abSAndroid Build Coastguard Worker                                NULL,  // left entropy context
757*fb1b10abSAndroid Build Coastguard Worker                                &mi->skip, mi_row, mi_col, output_enabled };
758*fb1b10abSAndroid Build Coastguard Worker #else
759*fb1b10abSAndroid Build Coastguard Worker   struct encode_b_args arg = { x,
760*fb1b10abSAndroid Build Coastguard Worker                                1,     // enable_trellis_opt
761*fb1b10abSAndroid Build Coastguard Worker                                0.0,   // trellis_opt_thresh
762*fb1b10abSAndroid Build Coastguard Worker                                NULL,  // &sse_calc_done
763*fb1b10abSAndroid Build Coastguard Worker                                NULL,  // &sse
764*fb1b10abSAndroid Build Coastguard Worker                                NULL,  // above entropy context
765*fb1b10abSAndroid Build Coastguard Worker                                NULL,  // left entropy context
766*fb1b10abSAndroid Build Coastguard Worker                                &mi->skip };
767*fb1b10abSAndroid Build Coastguard Worker   (void)mi_row;
768*fb1b10abSAndroid Build Coastguard Worker   (void)mi_col;
769*fb1b10abSAndroid Build Coastguard Worker   (void)output_enabled;
770*fb1b10abSAndroid Build Coastguard Worker #endif
771*fb1b10abSAndroid Build Coastguard Worker 
772*fb1b10abSAndroid Build Coastguard Worker   mi->skip = 1;
773*fb1b10abSAndroid Build Coastguard Worker 
774*fb1b10abSAndroid Build Coastguard Worker   if (x->skip) return;
775*fb1b10abSAndroid Build Coastguard Worker 
776*fb1b10abSAndroid Build Coastguard Worker   for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
777*fb1b10abSAndroid Build Coastguard Worker     if (!x->skip_recode) vp9_subtract_plane(x, bsize, plane);
778*fb1b10abSAndroid Build Coastguard Worker 
779*fb1b10abSAndroid Build Coastguard Worker     if (x->optimize && (!x->skip_recode || !x->skip_optimize)) {
780*fb1b10abSAndroid Build Coastguard Worker       const struct macroblockd_plane *const pd = &xd->plane[plane];
781*fb1b10abSAndroid Build Coastguard Worker       const TX_SIZE tx_size = plane ? get_uv_tx_size(mi, pd) : mi->tx_size;
782*fb1b10abSAndroid Build Coastguard Worker       vp9_get_entropy_contexts(bsize, tx_size, pd, ctx.ta[plane],
783*fb1b10abSAndroid Build Coastguard Worker                                ctx.tl[plane]);
784*fb1b10abSAndroid Build Coastguard Worker       arg.enable_trellis_opt = 1;
785*fb1b10abSAndroid Build Coastguard Worker     } else {
786*fb1b10abSAndroid Build Coastguard Worker       arg.enable_trellis_opt = 0;
787*fb1b10abSAndroid Build Coastguard Worker     }
788*fb1b10abSAndroid Build Coastguard Worker     arg.ta = ctx.ta[plane];
789*fb1b10abSAndroid Build Coastguard Worker     arg.tl = ctx.tl[plane];
790*fb1b10abSAndroid Build Coastguard Worker 
791*fb1b10abSAndroid Build Coastguard Worker     vp9_foreach_transformed_block_in_plane(xd, bsize, plane, encode_block,
792*fb1b10abSAndroid Build Coastguard Worker                                            &arg);
793*fb1b10abSAndroid Build Coastguard Worker   }
794*fb1b10abSAndroid Build Coastguard Worker }
795*fb1b10abSAndroid Build Coastguard Worker 
vp9_encode_block_intra(int plane,int block,int row,int col,BLOCK_SIZE plane_bsize,TX_SIZE tx_size,void * arg)796*fb1b10abSAndroid Build Coastguard Worker void vp9_encode_block_intra(int plane, int block, int row, int col,
797*fb1b10abSAndroid Build Coastguard Worker                             BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
798*fb1b10abSAndroid Build Coastguard Worker                             void *arg) {
799*fb1b10abSAndroid Build Coastguard Worker   struct encode_b_args *const args = arg;
800*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCK *const x = args->x;
801*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCKD *const xd = &x->e_mbd;
802*fb1b10abSAndroid Build Coastguard Worker   MODE_INFO *mi = xd->mi[0];
803*fb1b10abSAndroid Build Coastguard Worker   struct macroblock_plane *const p = &x->plane[plane];
804*fb1b10abSAndroid Build Coastguard Worker   struct macroblockd_plane *const pd = &xd->plane[plane];
805*fb1b10abSAndroid Build Coastguard Worker   tran_low_t *coeff = BLOCK_OFFSET(p->coeff, block);
806*fb1b10abSAndroid Build Coastguard Worker   tran_low_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block);
807*fb1b10abSAndroid Build Coastguard Worker   tran_low_t *dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
808*fb1b10abSAndroid Build Coastguard Worker   const ScanOrder *scan_order;
809*fb1b10abSAndroid Build Coastguard Worker   TX_TYPE tx_type = DCT_DCT;
810*fb1b10abSAndroid Build Coastguard Worker   PREDICTION_MODE mode;
811*fb1b10abSAndroid Build Coastguard Worker   const int bwl = b_width_log2_lookup[plane_bsize];
812*fb1b10abSAndroid Build Coastguard Worker   const int diff_stride = 4 * (1 << bwl);
813*fb1b10abSAndroid Build Coastguard Worker   uint8_t *src, *dst;
814*fb1b10abSAndroid Build Coastguard Worker   int16_t *src_diff;
815*fb1b10abSAndroid Build Coastguard Worker   uint16_t *eob = &p->eobs[block];
816*fb1b10abSAndroid Build Coastguard Worker   const int src_stride = p->src.stride;
817*fb1b10abSAndroid Build Coastguard Worker   const int dst_stride = pd->dst.stride;
818*fb1b10abSAndroid Build Coastguard Worker   int enable_trellis_opt = !x->skip_recode;
819*fb1b10abSAndroid Build Coastguard Worker   ENTROPY_CONTEXT *a = NULL;
820*fb1b10abSAndroid Build Coastguard Worker   ENTROPY_CONTEXT *l = NULL;
821*fb1b10abSAndroid Build Coastguard Worker   int entropy_ctx = 0;
822*fb1b10abSAndroid Build Coastguard Worker   dst = &pd->dst.buf[4 * (row * dst_stride + col)];
823*fb1b10abSAndroid Build Coastguard Worker   src = &p->src.buf[4 * (row * src_stride + col)];
824*fb1b10abSAndroid Build Coastguard Worker   src_diff = &p->src_diff[4 * (row * diff_stride + col)];
825*fb1b10abSAndroid Build Coastguard Worker 
826*fb1b10abSAndroid Build Coastguard Worker   if (tx_size == TX_4X4) {
827*fb1b10abSAndroid Build Coastguard Worker     tx_type = get_tx_type_4x4(get_plane_type(plane), xd, block);
828*fb1b10abSAndroid Build Coastguard Worker     scan_order = &vp9_scan_orders[TX_4X4][tx_type];
829*fb1b10abSAndroid Build Coastguard Worker     mode = plane == 0 ? get_y_mode(xd->mi[0], block) : mi->uv_mode;
830*fb1b10abSAndroid Build Coastguard Worker   } else {
831*fb1b10abSAndroid Build Coastguard Worker     mode = plane == 0 ? mi->mode : mi->uv_mode;
832*fb1b10abSAndroid Build Coastguard Worker     if (tx_size == TX_32X32) {
833*fb1b10abSAndroid Build Coastguard Worker       scan_order = &vp9_default_scan_orders[TX_32X32];
834*fb1b10abSAndroid Build Coastguard Worker     } else {
835*fb1b10abSAndroid Build Coastguard Worker       tx_type = get_tx_type(get_plane_type(plane), xd);
836*fb1b10abSAndroid Build Coastguard Worker       scan_order = &vp9_scan_orders[tx_size][tx_type];
837*fb1b10abSAndroid Build Coastguard Worker     }
838*fb1b10abSAndroid Build Coastguard Worker   }
839*fb1b10abSAndroid Build Coastguard Worker 
840*fb1b10abSAndroid Build Coastguard Worker   vp9_predict_intra_block(
841*fb1b10abSAndroid Build Coastguard Worker       xd, bwl, tx_size, mode, (x->skip_encode || x->fp_src_pred) ? src : dst,
842*fb1b10abSAndroid Build Coastguard Worker       (x->skip_encode || x->fp_src_pred) ? src_stride : dst_stride, dst,
843*fb1b10abSAndroid Build Coastguard Worker       dst_stride, col, row, plane);
844*fb1b10abSAndroid Build Coastguard Worker 
845*fb1b10abSAndroid Build Coastguard Worker   // skip block condition should be handled before this is called.
846*fb1b10abSAndroid Build Coastguard Worker   assert(!x->skip_block);
847*fb1b10abSAndroid Build Coastguard Worker 
848*fb1b10abSAndroid Build Coastguard Worker   if (!x->skip_recode) {
849*fb1b10abSAndroid Build Coastguard Worker     const int tx_size_in_pixels = (1 << tx_size) << 2;
850*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
851*fb1b10abSAndroid Build Coastguard Worker     if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
852*fb1b10abSAndroid Build Coastguard Worker       vpx_highbd_subtract_block(tx_size_in_pixels, tx_size_in_pixels, src_diff,
853*fb1b10abSAndroid Build Coastguard Worker                                 diff_stride, src, src_stride, dst, dst_stride,
854*fb1b10abSAndroid Build Coastguard Worker                                 xd->bd);
855*fb1b10abSAndroid Build Coastguard Worker     } else {
856*fb1b10abSAndroid Build Coastguard Worker       vpx_subtract_block(tx_size_in_pixels, tx_size_in_pixels, src_diff,
857*fb1b10abSAndroid Build Coastguard Worker                          diff_stride, src, src_stride, dst, dst_stride);
858*fb1b10abSAndroid Build Coastguard Worker     }
859*fb1b10abSAndroid Build Coastguard Worker #else
860*fb1b10abSAndroid Build Coastguard Worker     vpx_subtract_block(tx_size_in_pixels, tx_size_in_pixels, src_diff,
861*fb1b10abSAndroid Build Coastguard Worker                        diff_stride, src, src_stride, dst, dst_stride);
862*fb1b10abSAndroid Build Coastguard Worker #endif
863*fb1b10abSAndroid Build Coastguard Worker     enable_trellis_opt = do_trellis_opt(pd, src_diff, diff_stride, row, col,
864*fb1b10abSAndroid Build Coastguard Worker                                         plane_bsize, tx_size, args);
865*fb1b10abSAndroid Build Coastguard Worker   }
866*fb1b10abSAndroid Build Coastguard Worker 
867*fb1b10abSAndroid Build Coastguard Worker   if (enable_trellis_opt) {
868*fb1b10abSAndroid Build Coastguard Worker     a = &args->ta[col];
869*fb1b10abSAndroid Build Coastguard Worker     l = &args->tl[row];
870*fb1b10abSAndroid Build Coastguard Worker     entropy_ctx = combine_entropy_contexts(*a, *l);
871*fb1b10abSAndroid Build Coastguard Worker   }
872*fb1b10abSAndroid Build Coastguard Worker 
873*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
874*fb1b10abSAndroid Build Coastguard Worker   if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
875*fb1b10abSAndroid Build Coastguard Worker     uint16_t *const dst16 = CONVERT_TO_SHORTPTR(dst);
876*fb1b10abSAndroid Build Coastguard Worker     switch (tx_size) {
877*fb1b10abSAndroid Build Coastguard Worker       case TX_32X32:
878*fb1b10abSAndroid Build Coastguard Worker         if (!x->skip_recode) {
879*fb1b10abSAndroid Build Coastguard Worker           highbd_fdct32x32(x->use_lp32x32fdct, src_diff, coeff, diff_stride);
880*fb1b10abSAndroid Build Coastguard Worker           vpx_highbd_quantize_b_32x32(coeff, p, qcoeff, dqcoeff, pd->dequant,
881*fb1b10abSAndroid Build Coastguard Worker                                       eob, scan_order);
882*fb1b10abSAndroid Build Coastguard Worker         }
883*fb1b10abSAndroid Build Coastguard Worker         if (enable_trellis_opt) {
884*fb1b10abSAndroid Build Coastguard Worker           *a = *l = vp9_optimize_b(x, plane, block, tx_size, entropy_ctx) > 0;
885*fb1b10abSAndroid Build Coastguard Worker         }
886*fb1b10abSAndroid Build Coastguard Worker         if (!x->skip_encode && *eob) {
887*fb1b10abSAndroid Build Coastguard Worker           vp9_highbd_idct32x32_add(dqcoeff, dst16, dst_stride, *eob, xd->bd);
888*fb1b10abSAndroid Build Coastguard Worker         }
889*fb1b10abSAndroid Build Coastguard Worker         break;
890*fb1b10abSAndroid Build Coastguard Worker       case TX_16X16:
891*fb1b10abSAndroid Build Coastguard Worker         if (!x->skip_recode) {
892*fb1b10abSAndroid Build Coastguard Worker           if (tx_type == DCT_DCT)
893*fb1b10abSAndroid Build Coastguard Worker             vpx_highbd_fdct16x16(src_diff, coeff, diff_stride);
894*fb1b10abSAndroid Build Coastguard Worker           else
895*fb1b10abSAndroid Build Coastguard Worker             vp9_highbd_fht16x16(src_diff, coeff, diff_stride, tx_type);
896*fb1b10abSAndroid Build Coastguard Worker           vpx_highbd_quantize_b(coeff, 256, p, qcoeff, dqcoeff, pd->dequant,
897*fb1b10abSAndroid Build Coastguard Worker                                 eob, scan_order);
898*fb1b10abSAndroid Build Coastguard Worker         }
899*fb1b10abSAndroid Build Coastguard Worker         if (enable_trellis_opt) {
900*fb1b10abSAndroid Build Coastguard Worker           *a = *l = vp9_optimize_b(x, plane, block, tx_size, entropy_ctx) > 0;
901*fb1b10abSAndroid Build Coastguard Worker         }
902*fb1b10abSAndroid Build Coastguard Worker         if (!x->skip_encode && *eob) {
903*fb1b10abSAndroid Build Coastguard Worker           vp9_highbd_iht16x16_add(tx_type, dqcoeff, dst16, dst_stride, *eob,
904*fb1b10abSAndroid Build Coastguard Worker                                   xd->bd);
905*fb1b10abSAndroid Build Coastguard Worker         }
906*fb1b10abSAndroid Build Coastguard Worker         break;
907*fb1b10abSAndroid Build Coastguard Worker       case TX_8X8:
908*fb1b10abSAndroid Build Coastguard Worker         if (!x->skip_recode) {
909*fb1b10abSAndroid Build Coastguard Worker           if (tx_type == DCT_DCT)
910*fb1b10abSAndroid Build Coastguard Worker             vpx_highbd_fdct8x8(src_diff, coeff, diff_stride);
911*fb1b10abSAndroid Build Coastguard Worker           else
912*fb1b10abSAndroid Build Coastguard Worker             vp9_highbd_fht8x8(src_diff, coeff, diff_stride, tx_type);
913*fb1b10abSAndroid Build Coastguard Worker           vpx_highbd_quantize_b(coeff, 64, p, qcoeff, dqcoeff, pd->dequant, eob,
914*fb1b10abSAndroid Build Coastguard Worker                                 scan_order);
915*fb1b10abSAndroid Build Coastguard Worker         }
916*fb1b10abSAndroid Build Coastguard Worker         if (enable_trellis_opt) {
917*fb1b10abSAndroid Build Coastguard Worker           *a = *l = vp9_optimize_b(x, plane, block, tx_size, entropy_ctx) > 0;
918*fb1b10abSAndroid Build Coastguard Worker         }
919*fb1b10abSAndroid Build Coastguard Worker         if (!x->skip_encode && *eob) {
920*fb1b10abSAndroid Build Coastguard Worker           vp9_highbd_iht8x8_add(tx_type, dqcoeff, dst16, dst_stride, *eob,
921*fb1b10abSAndroid Build Coastguard Worker                                 xd->bd);
922*fb1b10abSAndroid Build Coastguard Worker         }
923*fb1b10abSAndroid Build Coastguard Worker         break;
924*fb1b10abSAndroid Build Coastguard Worker       default:
925*fb1b10abSAndroid Build Coastguard Worker         assert(tx_size == TX_4X4);
926*fb1b10abSAndroid Build Coastguard Worker         if (!x->skip_recode) {
927*fb1b10abSAndroid Build Coastguard Worker           if (tx_type != DCT_DCT)
928*fb1b10abSAndroid Build Coastguard Worker             vp9_highbd_fht4x4(src_diff, coeff, diff_stride, tx_type);
929*fb1b10abSAndroid Build Coastguard Worker           else
930*fb1b10abSAndroid Build Coastguard Worker             x->fwd_txfm4x4(src_diff, coeff, diff_stride);
931*fb1b10abSAndroid Build Coastguard Worker           vpx_highbd_quantize_b(coeff, 16, p, qcoeff, dqcoeff, pd->dequant, eob,
932*fb1b10abSAndroid Build Coastguard Worker                                 scan_order);
933*fb1b10abSAndroid Build Coastguard Worker         }
934*fb1b10abSAndroid Build Coastguard Worker         if (enable_trellis_opt) {
935*fb1b10abSAndroid Build Coastguard Worker           *a = *l = vp9_optimize_b(x, plane, block, tx_size, entropy_ctx) > 0;
936*fb1b10abSAndroid Build Coastguard Worker         }
937*fb1b10abSAndroid Build Coastguard Worker         if (!x->skip_encode && *eob) {
938*fb1b10abSAndroid Build Coastguard Worker           if (tx_type == DCT_DCT) {
939*fb1b10abSAndroid Build Coastguard Worker             // this is like vp9_short_idct4x4 but has a special case around
940*fb1b10abSAndroid Build Coastguard Worker             // eob<=1 which is significant (not just an optimization) for the
941*fb1b10abSAndroid Build Coastguard Worker             // lossless case.
942*fb1b10abSAndroid Build Coastguard Worker             x->highbd_inv_txfm_add(dqcoeff, dst16, dst_stride, *eob, xd->bd);
943*fb1b10abSAndroid Build Coastguard Worker           } else {
944*fb1b10abSAndroid Build Coastguard Worker             vp9_highbd_iht4x4_16_add(dqcoeff, dst16, dst_stride, tx_type,
945*fb1b10abSAndroid Build Coastguard Worker                                      xd->bd);
946*fb1b10abSAndroid Build Coastguard Worker           }
947*fb1b10abSAndroid Build Coastguard Worker         }
948*fb1b10abSAndroid Build Coastguard Worker         break;
949*fb1b10abSAndroid Build Coastguard Worker     }
950*fb1b10abSAndroid Build Coastguard Worker     if (*eob) *(args->skip) = 0;
951*fb1b10abSAndroid Build Coastguard Worker     return;
952*fb1b10abSAndroid Build Coastguard Worker   }
953*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
954*fb1b10abSAndroid Build Coastguard Worker 
955*fb1b10abSAndroid Build Coastguard Worker   switch (tx_size) {
956*fb1b10abSAndroid Build Coastguard Worker     case TX_32X32:
957*fb1b10abSAndroid Build Coastguard Worker       if (!x->skip_recode) {
958*fb1b10abSAndroid Build Coastguard Worker         fdct32x32(x->use_lp32x32fdct, src_diff, coeff, diff_stride);
959*fb1b10abSAndroid Build Coastguard Worker         vpx_quantize_b_32x32(coeff, p, qcoeff, dqcoeff, pd->dequant, eob,
960*fb1b10abSAndroid Build Coastguard Worker                              scan_order);
961*fb1b10abSAndroid Build Coastguard Worker       }
962*fb1b10abSAndroid Build Coastguard Worker       if (enable_trellis_opt) {
963*fb1b10abSAndroid Build Coastguard Worker         *a = *l = vp9_optimize_b(x, plane, block, tx_size, entropy_ctx) > 0;
964*fb1b10abSAndroid Build Coastguard Worker       }
965*fb1b10abSAndroid Build Coastguard Worker       if (!x->skip_encode && *eob)
966*fb1b10abSAndroid Build Coastguard Worker         vp9_idct32x32_add(dqcoeff, dst, dst_stride, *eob);
967*fb1b10abSAndroid Build Coastguard Worker       break;
968*fb1b10abSAndroid Build Coastguard Worker     case TX_16X16:
969*fb1b10abSAndroid Build Coastguard Worker       if (!x->skip_recode) {
970*fb1b10abSAndroid Build Coastguard Worker         vp9_fht16x16(src_diff, coeff, diff_stride, tx_type);
971*fb1b10abSAndroid Build Coastguard Worker         vpx_quantize_b(coeff, 256, p, qcoeff, dqcoeff, pd->dequant, eob,
972*fb1b10abSAndroid Build Coastguard Worker                        scan_order);
973*fb1b10abSAndroid Build Coastguard Worker       }
974*fb1b10abSAndroid Build Coastguard Worker       if (enable_trellis_opt) {
975*fb1b10abSAndroid Build Coastguard Worker         *a = *l = vp9_optimize_b(x, plane, block, tx_size, entropy_ctx) > 0;
976*fb1b10abSAndroid Build Coastguard Worker       }
977*fb1b10abSAndroid Build Coastguard Worker       if (!x->skip_encode && *eob)
978*fb1b10abSAndroid Build Coastguard Worker         vp9_iht16x16_add(tx_type, dqcoeff, dst, dst_stride, *eob);
979*fb1b10abSAndroid Build Coastguard Worker       break;
980*fb1b10abSAndroid Build Coastguard Worker     case TX_8X8:
981*fb1b10abSAndroid Build Coastguard Worker       if (!x->skip_recode) {
982*fb1b10abSAndroid Build Coastguard Worker         vp9_fht8x8(src_diff, coeff, diff_stride, tx_type);
983*fb1b10abSAndroid Build Coastguard Worker         vpx_quantize_b(coeff, 64, p, qcoeff, dqcoeff, pd->dequant, eob,
984*fb1b10abSAndroid Build Coastguard Worker                        scan_order);
985*fb1b10abSAndroid Build Coastguard Worker       }
986*fb1b10abSAndroid Build Coastguard Worker       if (enable_trellis_opt) {
987*fb1b10abSAndroid Build Coastguard Worker         *a = *l = vp9_optimize_b(x, plane, block, tx_size, entropy_ctx) > 0;
988*fb1b10abSAndroid Build Coastguard Worker       }
989*fb1b10abSAndroid Build Coastguard Worker       if (!x->skip_encode && *eob)
990*fb1b10abSAndroid Build Coastguard Worker         vp9_iht8x8_add(tx_type, dqcoeff, dst, dst_stride, *eob);
991*fb1b10abSAndroid Build Coastguard Worker       break;
992*fb1b10abSAndroid Build Coastguard Worker     default:
993*fb1b10abSAndroid Build Coastguard Worker       assert(tx_size == TX_4X4);
994*fb1b10abSAndroid Build Coastguard Worker       if (!x->skip_recode) {
995*fb1b10abSAndroid Build Coastguard Worker         if (tx_type != DCT_DCT)
996*fb1b10abSAndroid Build Coastguard Worker           vp9_fht4x4(src_diff, coeff, diff_stride, tx_type);
997*fb1b10abSAndroid Build Coastguard Worker         else
998*fb1b10abSAndroid Build Coastguard Worker           x->fwd_txfm4x4(src_diff, coeff, diff_stride);
999*fb1b10abSAndroid Build Coastguard Worker         vpx_quantize_b(coeff, 16, p, qcoeff, dqcoeff, pd->dequant, eob,
1000*fb1b10abSAndroid Build Coastguard Worker                        scan_order);
1001*fb1b10abSAndroid Build Coastguard Worker       }
1002*fb1b10abSAndroid Build Coastguard Worker       if (enable_trellis_opt) {
1003*fb1b10abSAndroid Build Coastguard Worker         *a = *l = vp9_optimize_b(x, plane, block, tx_size, entropy_ctx) > 0;
1004*fb1b10abSAndroid Build Coastguard Worker       }
1005*fb1b10abSAndroid Build Coastguard Worker       if (!x->skip_encode && *eob) {
1006*fb1b10abSAndroid Build Coastguard Worker         if (tx_type == DCT_DCT)
1007*fb1b10abSAndroid Build Coastguard Worker           // this is like vp9_short_idct4x4 but has a special case around eob<=1
1008*fb1b10abSAndroid Build Coastguard Worker           // which is significant (not just an optimization) for the lossless
1009*fb1b10abSAndroid Build Coastguard Worker           // case.
1010*fb1b10abSAndroid Build Coastguard Worker           x->inv_txfm_add(dqcoeff, dst, dst_stride, *eob);
1011*fb1b10abSAndroid Build Coastguard Worker         else
1012*fb1b10abSAndroid Build Coastguard Worker           vp9_iht4x4_16_add(dqcoeff, dst, dst_stride, tx_type);
1013*fb1b10abSAndroid Build Coastguard Worker       }
1014*fb1b10abSAndroid Build Coastguard Worker       break;
1015*fb1b10abSAndroid Build Coastguard Worker   }
1016*fb1b10abSAndroid Build Coastguard Worker   if (*eob) *(args->skip) = 0;
1017*fb1b10abSAndroid Build Coastguard Worker }
1018*fb1b10abSAndroid Build Coastguard Worker 
vp9_encode_intra_block_plane(MACROBLOCK * x,BLOCK_SIZE bsize,int plane,int enable_trellis_opt)1019*fb1b10abSAndroid Build Coastguard Worker void vp9_encode_intra_block_plane(MACROBLOCK *x, BLOCK_SIZE bsize, int plane,
1020*fb1b10abSAndroid Build Coastguard Worker                                   int enable_trellis_opt) {
1021*fb1b10abSAndroid Build Coastguard Worker   const MACROBLOCKD *const xd = &x->e_mbd;
1022*fb1b10abSAndroid Build Coastguard Worker   struct optimize_ctx ctx;
1023*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MISMATCH_DEBUG
1024*fb1b10abSAndroid Build Coastguard Worker   // TODO(angiebird): make mismatch_debug support intra mode
1025*fb1b10abSAndroid Build Coastguard Worker   struct encode_b_args arg = {
1026*fb1b10abSAndroid Build Coastguard Worker     x,
1027*fb1b10abSAndroid Build Coastguard Worker     enable_trellis_opt,
1028*fb1b10abSAndroid Build Coastguard Worker     0.0,   // trellis_opt_thresh
1029*fb1b10abSAndroid Build Coastguard Worker     NULL,  // &sse_calc_done
1030*fb1b10abSAndroid Build Coastguard Worker     NULL,  // &sse
1031*fb1b10abSAndroid Build Coastguard Worker     ctx.ta[plane],
1032*fb1b10abSAndroid Build Coastguard Worker     ctx.tl[plane],
1033*fb1b10abSAndroid Build Coastguard Worker     &xd->mi[0]->skip,
1034*fb1b10abSAndroid Build Coastguard Worker     0,  // mi_row
1035*fb1b10abSAndroid Build Coastguard Worker     0,  // mi_col
1036*fb1b10abSAndroid Build Coastguard Worker     0   // output_enabled
1037*fb1b10abSAndroid Build Coastguard Worker   };
1038*fb1b10abSAndroid Build Coastguard Worker #else
1039*fb1b10abSAndroid Build Coastguard Worker   struct encode_b_args arg = { x,
1040*fb1b10abSAndroid Build Coastguard Worker                                enable_trellis_opt,
1041*fb1b10abSAndroid Build Coastguard Worker                                0.0,   // trellis_opt_thresh
1042*fb1b10abSAndroid Build Coastguard Worker                                NULL,  // &sse_calc_done
1043*fb1b10abSAndroid Build Coastguard Worker                                NULL,  // &sse
1044*fb1b10abSAndroid Build Coastguard Worker                                ctx.ta[plane],
1045*fb1b10abSAndroid Build Coastguard Worker                                ctx.tl[plane],
1046*fb1b10abSAndroid Build Coastguard Worker                                &xd->mi[0]->skip };
1047*fb1b10abSAndroid Build Coastguard Worker #endif
1048*fb1b10abSAndroid Build Coastguard Worker 
1049*fb1b10abSAndroid Build Coastguard Worker   if (enable_trellis_opt && x->optimize &&
1050*fb1b10abSAndroid Build Coastguard Worker       (!x->skip_recode || !x->skip_optimize)) {
1051*fb1b10abSAndroid Build Coastguard Worker     const struct macroblockd_plane *const pd = &xd->plane[plane];
1052*fb1b10abSAndroid Build Coastguard Worker     const TX_SIZE tx_size =
1053*fb1b10abSAndroid Build Coastguard Worker         plane ? get_uv_tx_size(xd->mi[0], pd) : xd->mi[0]->tx_size;
1054*fb1b10abSAndroid Build Coastguard Worker     vp9_get_entropy_contexts(bsize, tx_size, pd, ctx.ta[plane], ctx.tl[plane]);
1055*fb1b10abSAndroid Build Coastguard Worker   } else {
1056*fb1b10abSAndroid Build Coastguard Worker     arg.enable_trellis_opt = 0;
1057*fb1b10abSAndroid Build Coastguard Worker   }
1058*fb1b10abSAndroid Build Coastguard Worker 
1059*fb1b10abSAndroid Build Coastguard Worker   vp9_foreach_transformed_block_in_plane(xd, bsize, plane,
1060*fb1b10abSAndroid Build Coastguard Worker                                          vp9_encode_block_intra, &arg);
1061*fb1b10abSAndroid Build Coastguard Worker }
1062