xref: /aosp_15_r20/external/libvpx/vp8/encoder/tokenize.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 <math.h>
12*fb1b10abSAndroid Build Coastguard Worker #include <stdio.h>
13*fb1b10abSAndroid Build Coastguard Worker #include <string.h>
14*fb1b10abSAndroid Build Coastguard Worker #include <assert.h>
15*fb1b10abSAndroid Build Coastguard Worker #include "onyx_int.h"
16*fb1b10abSAndroid Build Coastguard Worker #include "tokenize.h"
17*fb1b10abSAndroid Build Coastguard Worker #include "vpx_mem/vpx_mem.h"
18*fb1b10abSAndroid Build Coastguard Worker 
19*fb1b10abSAndroid Build Coastguard Worker /* Global event counters used for accumulating statistics across several
20*fb1b10abSAndroid Build Coastguard Worker    compressions, then generating context.c = initial stats. */
21*fb1b10abSAndroid Build Coastguard Worker 
22*fb1b10abSAndroid Build Coastguard Worker void vp8_stuff_mb(VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t);
23*fb1b10abSAndroid Build Coastguard Worker void vp8_fix_contexts(MACROBLOCKD *x);
24*fb1b10abSAndroid Build Coastguard Worker 
25*fb1b10abSAndroid Build Coastguard Worker #include "dct_value_tokens.h"
26*fb1b10abSAndroid Build Coastguard Worker #include "dct_value_cost.h"
27*fb1b10abSAndroid Build Coastguard Worker 
28*fb1b10abSAndroid Build Coastguard Worker const TOKENVALUE *const vp8_dct_value_tokens_ptr =
29*fb1b10abSAndroid Build Coastguard Worker     dct_value_tokens + DCT_MAX_VALUE;
30*fb1b10abSAndroid Build Coastguard Worker const short *const vp8_dct_value_cost_ptr = dct_value_cost + DCT_MAX_VALUE;
31*fb1b10abSAndroid Build Coastguard Worker 
32*fb1b10abSAndroid Build Coastguard Worker #if 0
33*fb1b10abSAndroid Build Coastguard Worker int skip_true_count = 0;
34*fb1b10abSAndroid Build Coastguard Worker int skip_false_count = 0;
35*fb1b10abSAndroid Build Coastguard Worker #endif
36*fb1b10abSAndroid Build Coastguard Worker 
37*fb1b10abSAndroid Build Coastguard Worker /* function used to generate dct_value_tokens and dct_value_cost tables */
38*fb1b10abSAndroid Build Coastguard Worker /*
39*fb1b10abSAndroid Build Coastguard Worker static void fill_value_tokens()
40*fb1b10abSAndroid Build Coastguard Worker {
41*fb1b10abSAndroid Build Coastguard Worker 
42*fb1b10abSAndroid Build Coastguard Worker     TOKENVALUE *t = dct_value_tokens + DCT_MAX_VALUE;
43*fb1b10abSAndroid Build Coastguard Worker     const vp8_extra_bit_struct *e = vp8_extra_bits;
44*fb1b10abSAndroid Build Coastguard Worker 
45*fb1b10abSAndroid Build Coastguard Worker     int i = -DCT_MAX_VALUE;
46*fb1b10abSAndroid Build Coastguard Worker     int sign = 1;
47*fb1b10abSAndroid Build Coastguard Worker 
48*fb1b10abSAndroid Build Coastguard Worker     do
49*fb1b10abSAndroid Build Coastguard Worker     {
50*fb1b10abSAndroid Build Coastguard Worker         if (!i)
51*fb1b10abSAndroid Build Coastguard Worker             sign = 0;
52*fb1b10abSAndroid Build Coastguard Worker 
53*fb1b10abSAndroid Build Coastguard Worker         {
54*fb1b10abSAndroid Build Coastguard Worker             const int a = sign ? -i : i;
55*fb1b10abSAndroid Build Coastguard Worker             int eb = sign;
56*fb1b10abSAndroid Build Coastguard Worker 
57*fb1b10abSAndroid Build Coastguard Worker             if (a > 4)
58*fb1b10abSAndroid Build Coastguard Worker             {
59*fb1b10abSAndroid Build Coastguard Worker                 int j = 4;
60*fb1b10abSAndroid Build Coastguard Worker 
61*fb1b10abSAndroid Build Coastguard Worker                 while (++j < 11  &&  e[j].base_val <= a) {}
62*fb1b10abSAndroid Build Coastguard Worker 
63*fb1b10abSAndroid Build Coastguard Worker                 t[i].Token = --j;
64*fb1b10abSAndroid Build Coastguard Worker                 eb |= (a - e[j].base_val) << 1;
65*fb1b10abSAndroid Build Coastguard Worker             }
66*fb1b10abSAndroid Build Coastguard Worker             else
67*fb1b10abSAndroid Build Coastguard Worker                 t[i].Token = a;
68*fb1b10abSAndroid Build Coastguard Worker 
69*fb1b10abSAndroid Build Coastguard Worker             t[i].Extra = eb;
70*fb1b10abSAndroid Build Coastguard Worker         }
71*fb1b10abSAndroid Build Coastguard Worker 
72*fb1b10abSAndroid Build Coastguard Worker         // initialize the cost for extra bits for all possible coefficient
73*fb1b10abSAndroid Build Coastguard Worker value.
74*fb1b10abSAndroid Build Coastguard Worker         {
75*fb1b10abSAndroid Build Coastguard Worker             int cost = 0;
76*fb1b10abSAndroid Build Coastguard Worker             const vp8_extra_bit_struct *p = vp8_extra_bits + t[i].Token;
77*fb1b10abSAndroid Build Coastguard Worker 
78*fb1b10abSAndroid Build Coastguard Worker             if (p->base_val)
79*fb1b10abSAndroid Build Coastguard Worker             {
80*fb1b10abSAndroid Build Coastguard Worker                 const int extra = t[i].Extra;
81*fb1b10abSAndroid Build Coastguard Worker                 const int Length = p->Len;
82*fb1b10abSAndroid Build Coastguard Worker 
83*fb1b10abSAndroid Build Coastguard Worker                 if (Length)
84*fb1b10abSAndroid Build Coastguard Worker                     cost += vp8_treed_cost(p->tree, p->prob, extra >> 1,
85*fb1b10abSAndroid Build Coastguard Worker Length);
86*fb1b10abSAndroid Build Coastguard Worker 
87*fb1b10abSAndroid Build Coastguard Worker                 cost += vp8_cost_bit(vp8_prob_half, extra & 1); // sign
88*fb1b10abSAndroid Build Coastguard Worker                 dct_value_cost[i + DCT_MAX_VALUE] = cost;
89*fb1b10abSAndroid Build Coastguard Worker             }
90*fb1b10abSAndroid Build Coastguard Worker 
91*fb1b10abSAndroid Build Coastguard Worker         }
92*fb1b10abSAndroid Build Coastguard Worker 
93*fb1b10abSAndroid Build Coastguard Worker     }
94*fb1b10abSAndroid Build Coastguard Worker     while (++i < DCT_MAX_VALUE);
95*fb1b10abSAndroid Build Coastguard Worker 
96*fb1b10abSAndroid Build Coastguard Worker     vp8_dct_value_tokens_ptr = dct_value_tokens + DCT_MAX_VALUE;
97*fb1b10abSAndroid Build Coastguard Worker     vp8_dct_value_cost_ptr   = dct_value_cost + DCT_MAX_VALUE;
98*fb1b10abSAndroid Build Coastguard Worker }
99*fb1b10abSAndroid Build Coastguard Worker */
100*fb1b10abSAndroid Build Coastguard Worker 
tokenize2nd_order_b(MACROBLOCK * x,TOKENEXTRA ** tp,VP8_COMP * cpi)101*fb1b10abSAndroid Build Coastguard Worker static void tokenize2nd_order_b(MACROBLOCK *x, TOKENEXTRA **tp, VP8_COMP *cpi) {
102*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCKD *xd = &x->e_mbd;
103*fb1b10abSAndroid Build Coastguard Worker   int pt;              /* near block/prev token context index */
104*fb1b10abSAndroid Build Coastguard Worker   int c;               /* start at DC */
105*fb1b10abSAndroid Build Coastguard Worker   TOKENEXTRA *t = *tp; /* store tokens starting here */
106*fb1b10abSAndroid Build Coastguard Worker   const BLOCKD *b;
107*fb1b10abSAndroid Build Coastguard Worker   const short *qcoeff_ptr;
108*fb1b10abSAndroid Build Coastguard Worker   ENTROPY_CONTEXT *a;
109*fb1b10abSAndroid Build Coastguard Worker   ENTROPY_CONTEXT *l;
110*fb1b10abSAndroid Build Coastguard Worker   int band, rc, v, token;
111*fb1b10abSAndroid Build Coastguard Worker   int eob;
112*fb1b10abSAndroid Build Coastguard Worker 
113*fb1b10abSAndroid Build Coastguard Worker   b = xd->block + 24;
114*fb1b10abSAndroid Build Coastguard Worker   qcoeff_ptr = b->qcoeff;
115*fb1b10abSAndroid Build Coastguard Worker   a = (ENTROPY_CONTEXT *)xd->above_context + 8;
116*fb1b10abSAndroid Build Coastguard Worker   l = (ENTROPY_CONTEXT *)xd->left_context + 8;
117*fb1b10abSAndroid Build Coastguard Worker   eob = xd->eobs[24];
118*fb1b10abSAndroid Build Coastguard Worker   VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
119*fb1b10abSAndroid Build Coastguard Worker 
120*fb1b10abSAndroid Build Coastguard Worker   if (!eob) {
121*fb1b10abSAndroid Build Coastguard Worker     /* c = band for this case */
122*fb1b10abSAndroid Build Coastguard Worker     t->Token = DCT_EOB_TOKEN;
123*fb1b10abSAndroid Build Coastguard Worker     t->context_tree = cpi->common.fc.coef_probs[1][0][pt];
124*fb1b10abSAndroid Build Coastguard Worker     t->skip_eob_node = 0;
125*fb1b10abSAndroid Build Coastguard Worker 
126*fb1b10abSAndroid Build Coastguard Worker     ++x->coef_counts[1][0][pt][DCT_EOB_TOKEN];
127*fb1b10abSAndroid Build Coastguard Worker     t++;
128*fb1b10abSAndroid Build Coastguard Worker     *tp = t;
129*fb1b10abSAndroid Build Coastguard Worker     *a = *l = 0;
130*fb1b10abSAndroid Build Coastguard Worker     return;
131*fb1b10abSAndroid Build Coastguard Worker   }
132*fb1b10abSAndroid Build Coastguard Worker 
133*fb1b10abSAndroid Build Coastguard Worker   v = qcoeff_ptr[0];
134*fb1b10abSAndroid Build Coastguard Worker   t->Extra = vp8_dct_value_tokens_ptr[v].Extra;
135*fb1b10abSAndroid Build Coastguard Worker   token = vp8_dct_value_tokens_ptr[v].Token;
136*fb1b10abSAndroid Build Coastguard Worker   t->Token = token;
137*fb1b10abSAndroid Build Coastguard Worker 
138*fb1b10abSAndroid Build Coastguard Worker   t->context_tree = cpi->common.fc.coef_probs[1][0][pt];
139*fb1b10abSAndroid Build Coastguard Worker   t->skip_eob_node = 0;
140*fb1b10abSAndroid Build Coastguard Worker   ++x->coef_counts[1][0][pt][token];
141*fb1b10abSAndroid Build Coastguard Worker   pt = vp8_prev_token_class[token];
142*fb1b10abSAndroid Build Coastguard Worker   t++;
143*fb1b10abSAndroid Build Coastguard Worker   c = 1;
144*fb1b10abSAndroid Build Coastguard Worker 
145*fb1b10abSAndroid Build Coastguard Worker   for (; c < eob; ++c) {
146*fb1b10abSAndroid Build Coastguard Worker     rc = vp8_default_zig_zag1d[c];
147*fb1b10abSAndroid Build Coastguard Worker     band = vp8_coef_bands[c];
148*fb1b10abSAndroid Build Coastguard Worker     v = qcoeff_ptr[rc];
149*fb1b10abSAndroid Build Coastguard Worker 
150*fb1b10abSAndroid Build Coastguard Worker     t->Extra = vp8_dct_value_tokens_ptr[v].Extra;
151*fb1b10abSAndroid Build Coastguard Worker     token = vp8_dct_value_tokens_ptr[v].Token;
152*fb1b10abSAndroid Build Coastguard Worker 
153*fb1b10abSAndroid Build Coastguard Worker     t->Token = token;
154*fb1b10abSAndroid Build Coastguard Worker     t->context_tree = cpi->common.fc.coef_probs[1][band][pt];
155*fb1b10abSAndroid Build Coastguard Worker 
156*fb1b10abSAndroid Build Coastguard Worker     t->skip_eob_node = ((pt == 0));
157*fb1b10abSAndroid Build Coastguard Worker 
158*fb1b10abSAndroid Build Coastguard Worker     ++x->coef_counts[1][band][pt][token];
159*fb1b10abSAndroid Build Coastguard Worker 
160*fb1b10abSAndroid Build Coastguard Worker     pt = vp8_prev_token_class[token];
161*fb1b10abSAndroid Build Coastguard Worker     t++;
162*fb1b10abSAndroid Build Coastguard Worker   }
163*fb1b10abSAndroid Build Coastguard Worker   if (c < 16) {
164*fb1b10abSAndroid Build Coastguard Worker     band = vp8_coef_bands[c];
165*fb1b10abSAndroid Build Coastguard Worker     t->Token = DCT_EOB_TOKEN;
166*fb1b10abSAndroid Build Coastguard Worker     t->context_tree = cpi->common.fc.coef_probs[1][band][pt];
167*fb1b10abSAndroid Build Coastguard Worker 
168*fb1b10abSAndroid Build Coastguard Worker     t->skip_eob_node = 0;
169*fb1b10abSAndroid Build Coastguard Worker 
170*fb1b10abSAndroid Build Coastguard Worker     ++x->coef_counts[1][band][pt][DCT_EOB_TOKEN];
171*fb1b10abSAndroid Build Coastguard Worker 
172*fb1b10abSAndroid Build Coastguard Worker     t++;
173*fb1b10abSAndroid Build Coastguard Worker   }
174*fb1b10abSAndroid Build Coastguard Worker 
175*fb1b10abSAndroid Build Coastguard Worker   *tp = t;
176*fb1b10abSAndroid Build Coastguard Worker   *a = *l = 1;
177*fb1b10abSAndroid Build Coastguard Worker }
178*fb1b10abSAndroid Build Coastguard Worker 
tokenize1st_order_b(MACROBLOCK * x,TOKENEXTRA ** tp,int type,VP8_COMP * cpi)179*fb1b10abSAndroid Build Coastguard Worker static void tokenize1st_order_b(
180*fb1b10abSAndroid Build Coastguard Worker     MACROBLOCK *x, TOKENEXTRA **tp,
181*fb1b10abSAndroid Build Coastguard Worker     int type, /* which plane: 0=Y no DC, 1=Y2, 2=UV, 3=Y with DC */
182*fb1b10abSAndroid Build Coastguard Worker     VP8_COMP *cpi) {
183*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCKD *xd = &x->e_mbd;
184*fb1b10abSAndroid Build Coastguard Worker   unsigned int block;
185*fb1b10abSAndroid Build Coastguard Worker   const BLOCKD *b;
186*fb1b10abSAndroid Build Coastguard Worker   int pt; /* near block/prev token context index */
187*fb1b10abSAndroid Build Coastguard Worker   int c;
188*fb1b10abSAndroid Build Coastguard Worker   int token;
189*fb1b10abSAndroid Build Coastguard Worker   TOKENEXTRA *t = *tp; /* store tokens starting here */
190*fb1b10abSAndroid Build Coastguard Worker   const short *qcoeff_ptr;
191*fb1b10abSAndroid Build Coastguard Worker   ENTROPY_CONTEXT *a;
192*fb1b10abSAndroid Build Coastguard Worker   ENTROPY_CONTEXT *l;
193*fb1b10abSAndroid Build Coastguard Worker   int band, rc, v;
194*fb1b10abSAndroid Build Coastguard Worker   int tmp1, tmp2;
195*fb1b10abSAndroid Build Coastguard Worker 
196*fb1b10abSAndroid Build Coastguard Worker   b = xd->block;
197*fb1b10abSAndroid Build Coastguard Worker   /* Luma */
198*fb1b10abSAndroid Build Coastguard Worker   for (block = 0; block < 16; block++, b++) {
199*fb1b10abSAndroid Build Coastguard Worker     const int eob = *b->eob;
200*fb1b10abSAndroid Build Coastguard Worker     tmp1 = vp8_block2above[block];
201*fb1b10abSAndroid Build Coastguard Worker     tmp2 = vp8_block2left[block];
202*fb1b10abSAndroid Build Coastguard Worker     qcoeff_ptr = b->qcoeff;
203*fb1b10abSAndroid Build Coastguard Worker     a = (ENTROPY_CONTEXT *)xd->above_context + tmp1;
204*fb1b10abSAndroid Build Coastguard Worker     l = (ENTROPY_CONTEXT *)xd->left_context + tmp2;
205*fb1b10abSAndroid Build Coastguard Worker 
206*fb1b10abSAndroid Build Coastguard Worker     VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
207*fb1b10abSAndroid Build Coastguard Worker 
208*fb1b10abSAndroid Build Coastguard Worker     c = type ? 0 : 1;
209*fb1b10abSAndroid Build Coastguard Worker 
210*fb1b10abSAndroid Build Coastguard Worker     if (c >= eob) {
211*fb1b10abSAndroid Build Coastguard Worker       /* c = band for this case */
212*fb1b10abSAndroid Build Coastguard Worker       t->Token = DCT_EOB_TOKEN;
213*fb1b10abSAndroid Build Coastguard Worker       t->context_tree = cpi->common.fc.coef_probs[type][c][pt];
214*fb1b10abSAndroid Build Coastguard Worker       t->skip_eob_node = 0;
215*fb1b10abSAndroid Build Coastguard Worker 
216*fb1b10abSAndroid Build Coastguard Worker       ++x->coef_counts[type][c][pt][DCT_EOB_TOKEN];
217*fb1b10abSAndroid Build Coastguard Worker       t++;
218*fb1b10abSAndroid Build Coastguard Worker       *tp = t;
219*fb1b10abSAndroid Build Coastguard Worker       *a = *l = 0;
220*fb1b10abSAndroid Build Coastguard Worker       continue;
221*fb1b10abSAndroid Build Coastguard Worker     }
222*fb1b10abSAndroid Build Coastguard Worker 
223*fb1b10abSAndroid Build Coastguard Worker     v = qcoeff_ptr[c];
224*fb1b10abSAndroid Build Coastguard Worker 
225*fb1b10abSAndroid Build Coastguard Worker     t->Extra = vp8_dct_value_tokens_ptr[v].Extra;
226*fb1b10abSAndroid Build Coastguard Worker     token = vp8_dct_value_tokens_ptr[v].Token;
227*fb1b10abSAndroid Build Coastguard Worker     t->Token = token;
228*fb1b10abSAndroid Build Coastguard Worker 
229*fb1b10abSAndroid Build Coastguard Worker     t->context_tree = cpi->common.fc.coef_probs[type][c][pt];
230*fb1b10abSAndroid Build Coastguard Worker     t->skip_eob_node = 0;
231*fb1b10abSAndroid Build Coastguard Worker     ++x->coef_counts[type][c][pt][token];
232*fb1b10abSAndroid Build Coastguard Worker     pt = vp8_prev_token_class[token];
233*fb1b10abSAndroid Build Coastguard Worker     t++;
234*fb1b10abSAndroid Build Coastguard Worker     c++;
235*fb1b10abSAndroid Build Coastguard Worker 
236*fb1b10abSAndroid Build Coastguard Worker     assert(eob <= 16);
237*fb1b10abSAndroid Build Coastguard Worker     for (; c < eob; ++c) {
238*fb1b10abSAndroid Build Coastguard Worker       rc = vp8_default_zig_zag1d[c];
239*fb1b10abSAndroid Build Coastguard Worker       band = vp8_coef_bands[c];
240*fb1b10abSAndroid Build Coastguard Worker       v = qcoeff_ptr[rc];
241*fb1b10abSAndroid Build Coastguard Worker 
242*fb1b10abSAndroid Build Coastguard Worker       t->Extra = vp8_dct_value_tokens_ptr[v].Extra;
243*fb1b10abSAndroid Build Coastguard Worker       token = vp8_dct_value_tokens_ptr[v].Token;
244*fb1b10abSAndroid Build Coastguard Worker 
245*fb1b10abSAndroid Build Coastguard Worker       t->Token = token;
246*fb1b10abSAndroid Build Coastguard Worker       t->context_tree = cpi->common.fc.coef_probs[type][band][pt];
247*fb1b10abSAndroid Build Coastguard Worker 
248*fb1b10abSAndroid Build Coastguard Worker       t->skip_eob_node = (pt == 0);
249*fb1b10abSAndroid Build Coastguard Worker       ++x->coef_counts[type][band][pt][token];
250*fb1b10abSAndroid Build Coastguard Worker 
251*fb1b10abSAndroid Build Coastguard Worker       pt = vp8_prev_token_class[token];
252*fb1b10abSAndroid Build Coastguard Worker       t++;
253*fb1b10abSAndroid Build Coastguard Worker     }
254*fb1b10abSAndroid Build Coastguard Worker     if (c < 16) {
255*fb1b10abSAndroid Build Coastguard Worker       band = vp8_coef_bands[c];
256*fb1b10abSAndroid Build Coastguard Worker       t->Token = DCT_EOB_TOKEN;
257*fb1b10abSAndroid Build Coastguard Worker       t->context_tree = cpi->common.fc.coef_probs[type][band][pt];
258*fb1b10abSAndroid Build Coastguard Worker 
259*fb1b10abSAndroid Build Coastguard Worker       t->skip_eob_node = 0;
260*fb1b10abSAndroid Build Coastguard Worker       ++x->coef_counts[type][band][pt][DCT_EOB_TOKEN];
261*fb1b10abSAndroid Build Coastguard Worker 
262*fb1b10abSAndroid Build Coastguard Worker       t++;
263*fb1b10abSAndroid Build Coastguard Worker     }
264*fb1b10abSAndroid Build Coastguard Worker     *tp = t;
265*fb1b10abSAndroid Build Coastguard Worker     *a = *l = 1;
266*fb1b10abSAndroid Build Coastguard Worker   }
267*fb1b10abSAndroid Build Coastguard Worker 
268*fb1b10abSAndroid Build Coastguard Worker   /* Chroma */
269*fb1b10abSAndroid Build Coastguard Worker   for (block = 16; block < 24; block++, b++) {
270*fb1b10abSAndroid Build Coastguard Worker     const int eob = *b->eob;
271*fb1b10abSAndroid Build Coastguard Worker     tmp1 = vp8_block2above[block];
272*fb1b10abSAndroid Build Coastguard Worker     tmp2 = vp8_block2left[block];
273*fb1b10abSAndroid Build Coastguard Worker     qcoeff_ptr = b->qcoeff;
274*fb1b10abSAndroid Build Coastguard Worker     a = (ENTROPY_CONTEXT *)xd->above_context + tmp1;
275*fb1b10abSAndroid Build Coastguard Worker     l = (ENTROPY_CONTEXT *)xd->left_context + tmp2;
276*fb1b10abSAndroid Build Coastguard Worker 
277*fb1b10abSAndroid Build Coastguard Worker     VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
278*fb1b10abSAndroid Build Coastguard Worker 
279*fb1b10abSAndroid Build Coastguard Worker     if (!eob) {
280*fb1b10abSAndroid Build Coastguard Worker       /* c = band for this case */
281*fb1b10abSAndroid Build Coastguard Worker       t->Token = DCT_EOB_TOKEN;
282*fb1b10abSAndroid Build Coastguard Worker       t->context_tree = cpi->common.fc.coef_probs[2][0][pt];
283*fb1b10abSAndroid Build Coastguard Worker       t->skip_eob_node = 0;
284*fb1b10abSAndroid Build Coastguard Worker 
285*fb1b10abSAndroid Build Coastguard Worker       ++x->coef_counts[2][0][pt][DCT_EOB_TOKEN];
286*fb1b10abSAndroid Build Coastguard Worker       t++;
287*fb1b10abSAndroid Build Coastguard Worker       *tp = t;
288*fb1b10abSAndroid Build Coastguard Worker       *a = *l = 0;
289*fb1b10abSAndroid Build Coastguard Worker       continue;
290*fb1b10abSAndroid Build Coastguard Worker     }
291*fb1b10abSAndroid Build Coastguard Worker 
292*fb1b10abSAndroid Build Coastguard Worker     v = qcoeff_ptr[0];
293*fb1b10abSAndroid Build Coastguard Worker 
294*fb1b10abSAndroid Build Coastguard Worker     t->Extra = vp8_dct_value_tokens_ptr[v].Extra;
295*fb1b10abSAndroid Build Coastguard Worker     token = vp8_dct_value_tokens_ptr[v].Token;
296*fb1b10abSAndroid Build Coastguard Worker     t->Token = token;
297*fb1b10abSAndroid Build Coastguard Worker 
298*fb1b10abSAndroid Build Coastguard Worker     t->context_tree = cpi->common.fc.coef_probs[2][0][pt];
299*fb1b10abSAndroid Build Coastguard Worker     t->skip_eob_node = 0;
300*fb1b10abSAndroid Build Coastguard Worker     ++x->coef_counts[2][0][pt][token];
301*fb1b10abSAndroid Build Coastguard Worker     pt = vp8_prev_token_class[token];
302*fb1b10abSAndroid Build Coastguard Worker     t++;
303*fb1b10abSAndroid Build Coastguard Worker     c = 1;
304*fb1b10abSAndroid Build Coastguard Worker 
305*fb1b10abSAndroid Build Coastguard Worker     assert(eob <= 16);
306*fb1b10abSAndroid Build Coastguard Worker     for (; c < eob; ++c) {
307*fb1b10abSAndroid Build Coastguard Worker       rc = vp8_default_zig_zag1d[c];
308*fb1b10abSAndroid Build Coastguard Worker       band = vp8_coef_bands[c];
309*fb1b10abSAndroid Build Coastguard Worker       v = qcoeff_ptr[rc];
310*fb1b10abSAndroid Build Coastguard Worker 
311*fb1b10abSAndroid Build Coastguard Worker       t->Extra = vp8_dct_value_tokens_ptr[v].Extra;
312*fb1b10abSAndroid Build Coastguard Worker       token = vp8_dct_value_tokens_ptr[v].Token;
313*fb1b10abSAndroid Build Coastguard Worker 
314*fb1b10abSAndroid Build Coastguard Worker       t->Token = token;
315*fb1b10abSAndroid Build Coastguard Worker       t->context_tree = cpi->common.fc.coef_probs[2][band][pt];
316*fb1b10abSAndroid Build Coastguard Worker 
317*fb1b10abSAndroid Build Coastguard Worker       t->skip_eob_node = (pt == 0);
318*fb1b10abSAndroid Build Coastguard Worker 
319*fb1b10abSAndroid Build Coastguard Worker       ++x->coef_counts[2][band][pt][token];
320*fb1b10abSAndroid Build Coastguard Worker 
321*fb1b10abSAndroid Build Coastguard Worker       pt = vp8_prev_token_class[token];
322*fb1b10abSAndroid Build Coastguard Worker       t++;
323*fb1b10abSAndroid Build Coastguard Worker     }
324*fb1b10abSAndroid Build Coastguard Worker     if (c < 16) {
325*fb1b10abSAndroid Build Coastguard Worker       band = vp8_coef_bands[c];
326*fb1b10abSAndroid Build Coastguard Worker       t->Token = DCT_EOB_TOKEN;
327*fb1b10abSAndroid Build Coastguard Worker       t->context_tree = cpi->common.fc.coef_probs[2][band][pt];
328*fb1b10abSAndroid Build Coastguard Worker 
329*fb1b10abSAndroid Build Coastguard Worker       t->skip_eob_node = 0;
330*fb1b10abSAndroid Build Coastguard Worker 
331*fb1b10abSAndroid Build Coastguard Worker       ++x->coef_counts[2][band][pt][DCT_EOB_TOKEN];
332*fb1b10abSAndroid Build Coastguard Worker 
333*fb1b10abSAndroid Build Coastguard Worker       t++;
334*fb1b10abSAndroid Build Coastguard Worker     }
335*fb1b10abSAndroid Build Coastguard Worker     *tp = t;
336*fb1b10abSAndroid Build Coastguard Worker     *a = *l = 1;
337*fb1b10abSAndroid Build Coastguard Worker   }
338*fb1b10abSAndroid Build Coastguard Worker }
339*fb1b10abSAndroid Build Coastguard Worker 
mb_is_skippable(MACROBLOCKD * x,int has_y2_block)340*fb1b10abSAndroid Build Coastguard Worker static int mb_is_skippable(MACROBLOCKD *x, int has_y2_block) {
341*fb1b10abSAndroid Build Coastguard Worker   int skip = 1;
342*fb1b10abSAndroid Build Coastguard Worker   int i = 0;
343*fb1b10abSAndroid Build Coastguard Worker 
344*fb1b10abSAndroid Build Coastguard Worker   if (has_y2_block) {
345*fb1b10abSAndroid Build Coastguard Worker     for (i = 0; i < 16; ++i) skip &= (x->eobs[i] < 2);
346*fb1b10abSAndroid Build Coastguard Worker   }
347*fb1b10abSAndroid Build Coastguard Worker 
348*fb1b10abSAndroid Build Coastguard Worker   for (; i < 24 + has_y2_block; ++i) skip &= (!x->eobs[i]);
349*fb1b10abSAndroid Build Coastguard Worker 
350*fb1b10abSAndroid Build Coastguard Worker   return skip;
351*fb1b10abSAndroid Build Coastguard Worker }
352*fb1b10abSAndroid Build Coastguard Worker 
vp8_tokenize_mb(VP8_COMP * cpi,MACROBLOCK * x,TOKENEXTRA ** t)353*fb1b10abSAndroid Build Coastguard Worker void vp8_tokenize_mb(VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t) {
354*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCKD *xd = &x->e_mbd;
355*fb1b10abSAndroid Build Coastguard Worker   int plane_type;
356*fb1b10abSAndroid Build Coastguard Worker   int has_y2_block;
357*fb1b10abSAndroid Build Coastguard Worker 
358*fb1b10abSAndroid Build Coastguard Worker   has_y2_block = (xd->mode_info_context->mbmi.mode != B_PRED &&
359*fb1b10abSAndroid Build Coastguard Worker                   xd->mode_info_context->mbmi.mode != SPLITMV);
360*fb1b10abSAndroid Build Coastguard Worker 
361*fb1b10abSAndroid Build Coastguard Worker   xd->mode_info_context->mbmi.mb_skip_coeff = mb_is_skippable(xd, has_y2_block);
362*fb1b10abSAndroid Build Coastguard Worker   if (xd->mode_info_context->mbmi.mb_skip_coeff) {
363*fb1b10abSAndroid Build Coastguard Worker     if (!cpi->common.mb_no_coeff_skip) {
364*fb1b10abSAndroid Build Coastguard Worker       vp8_stuff_mb(cpi, x, t);
365*fb1b10abSAndroid Build Coastguard Worker     } else {
366*fb1b10abSAndroid Build Coastguard Worker       vp8_fix_contexts(xd);
367*fb1b10abSAndroid Build Coastguard Worker       x->skip_true_count++;
368*fb1b10abSAndroid Build Coastguard Worker     }
369*fb1b10abSAndroid Build Coastguard Worker 
370*fb1b10abSAndroid Build Coastguard Worker     return;
371*fb1b10abSAndroid Build Coastguard Worker   }
372*fb1b10abSAndroid Build Coastguard Worker 
373*fb1b10abSAndroid Build Coastguard Worker   plane_type = 3;
374*fb1b10abSAndroid Build Coastguard Worker   if (has_y2_block) {
375*fb1b10abSAndroid Build Coastguard Worker     tokenize2nd_order_b(x, t, cpi);
376*fb1b10abSAndroid Build Coastguard Worker     plane_type = 0;
377*fb1b10abSAndroid Build Coastguard Worker   }
378*fb1b10abSAndroid Build Coastguard Worker 
379*fb1b10abSAndroid Build Coastguard Worker   tokenize1st_order_b(x, t, plane_type, cpi);
380*fb1b10abSAndroid Build Coastguard Worker }
381*fb1b10abSAndroid Build Coastguard Worker 
stuff2nd_order_b(TOKENEXTRA ** tp,ENTROPY_CONTEXT * a,ENTROPY_CONTEXT * l,VP8_COMP * cpi,MACROBLOCK * x)382*fb1b10abSAndroid Build Coastguard Worker static void stuff2nd_order_b(TOKENEXTRA **tp, ENTROPY_CONTEXT *a,
383*fb1b10abSAndroid Build Coastguard Worker                              ENTROPY_CONTEXT *l, VP8_COMP *cpi, MACROBLOCK *x) {
384*fb1b10abSAndroid Build Coastguard Worker   int pt;              /* near block/prev token context index */
385*fb1b10abSAndroid Build Coastguard Worker   TOKENEXTRA *t = *tp; /* store tokens starting here */
386*fb1b10abSAndroid Build Coastguard Worker   VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
387*fb1b10abSAndroid Build Coastguard Worker 
388*fb1b10abSAndroid Build Coastguard Worker   t->Token = DCT_EOB_TOKEN;
389*fb1b10abSAndroid Build Coastguard Worker   t->context_tree = cpi->common.fc.coef_probs[1][0][pt];
390*fb1b10abSAndroid Build Coastguard Worker   t->skip_eob_node = 0;
391*fb1b10abSAndroid Build Coastguard Worker   ++x->coef_counts[1][0][pt][DCT_EOB_TOKEN];
392*fb1b10abSAndroid Build Coastguard Worker   ++t;
393*fb1b10abSAndroid Build Coastguard Worker 
394*fb1b10abSAndroid Build Coastguard Worker   *tp = t;
395*fb1b10abSAndroid Build Coastguard Worker   pt = 0;
396*fb1b10abSAndroid Build Coastguard Worker   *a = *l = pt;
397*fb1b10abSAndroid Build Coastguard Worker }
398*fb1b10abSAndroid Build Coastguard Worker 
stuff1st_order_b(TOKENEXTRA ** tp,ENTROPY_CONTEXT * a,ENTROPY_CONTEXT * l,int type,VP8_COMP * cpi,MACROBLOCK * x)399*fb1b10abSAndroid Build Coastguard Worker static void stuff1st_order_b(TOKENEXTRA **tp, ENTROPY_CONTEXT *a,
400*fb1b10abSAndroid Build Coastguard Worker                              ENTROPY_CONTEXT *l, int type, VP8_COMP *cpi,
401*fb1b10abSAndroid Build Coastguard Worker                              MACROBLOCK *x) {
402*fb1b10abSAndroid Build Coastguard Worker   int pt; /* near block/prev token context index */
403*fb1b10abSAndroid Build Coastguard Worker   int band;
404*fb1b10abSAndroid Build Coastguard Worker   TOKENEXTRA *t = *tp; /* store tokens starting here */
405*fb1b10abSAndroid Build Coastguard Worker   VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
406*fb1b10abSAndroid Build Coastguard Worker   band = type ? 0 : 1;
407*fb1b10abSAndroid Build Coastguard Worker   t->Token = DCT_EOB_TOKEN;
408*fb1b10abSAndroid Build Coastguard Worker   t->context_tree = cpi->common.fc.coef_probs[type][band][pt];
409*fb1b10abSAndroid Build Coastguard Worker   t->skip_eob_node = 0;
410*fb1b10abSAndroid Build Coastguard Worker   ++x->coef_counts[type][band][pt][DCT_EOB_TOKEN];
411*fb1b10abSAndroid Build Coastguard Worker   ++t;
412*fb1b10abSAndroid Build Coastguard Worker   *tp = t;
413*fb1b10abSAndroid Build Coastguard Worker   pt = 0; /* 0 <-> all coeff data is zero */
414*fb1b10abSAndroid Build Coastguard Worker   *a = *l = pt;
415*fb1b10abSAndroid Build Coastguard Worker }
416*fb1b10abSAndroid Build Coastguard Worker 
stuff1st_order_buv(TOKENEXTRA ** tp,ENTROPY_CONTEXT * a,ENTROPY_CONTEXT * l,VP8_COMP * cpi,MACROBLOCK * x)417*fb1b10abSAndroid Build Coastguard Worker static void stuff1st_order_buv(TOKENEXTRA **tp, ENTROPY_CONTEXT *a,
418*fb1b10abSAndroid Build Coastguard Worker                                ENTROPY_CONTEXT *l, VP8_COMP *cpi,
419*fb1b10abSAndroid Build Coastguard Worker                                MACROBLOCK *x) {
420*fb1b10abSAndroid Build Coastguard Worker   int pt;              /* near block/prev token context index */
421*fb1b10abSAndroid Build Coastguard Worker   TOKENEXTRA *t = *tp; /* store tokens starting here */
422*fb1b10abSAndroid Build Coastguard Worker   VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
423*fb1b10abSAndroid Build Coastguard Worker 
424*fb1b10abSAndroid Build Coastguard Worker   t->Token = DCT_EOB_TOKEN;
425*fb1b10abSAndroid Build Coastguard Worker   t->context_tree = cpi->common.fc.coef_probs[2][0][pt];
426*fb1b10abSAndroid Build Coastguard Worker   t->skip_eob_node = 0;
427*fb1b10abSAndroid Build Coastguard Worker   ++x->coef_counts[2][0][pt][DCT_EOB_TOKEN];
428*fb1b10abSAndroid Build Coastguard Worker   ++t;
429*fb1b10abSAndroid Build Coastguard Worker   *tp = t;
430*fb1b10abSAndroid Build Coastguard Worker   pt = 0; /* 0 <-> all coeff data is zero */
431*fb1b10abSAndroid Build Coastguard Worker   *a = *l = pt;
432*fb1b10abSAndroid Build Coastguard Worker }
433*fb1b10abSAndroid Build Coastguard Worker 
vp8_stuff_mb(VP8_COMP * cpi,MACROBLOCK * x,TOKENEXTRA ** t)434*fb1b10abSAndroid Build Coastguard Worker void vp8_stuff_mb(VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t) {
435*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCKD *xd = &x->e_mbd;
436*fb1b10abSAndroid Build Coastguard Worker   ENTROPY_CONTEXT *A = (ENTROPY_CONTEXT *)xd->above_context;
437*fb1b10abSAndroid Build Coastguard Worker   ENTROPY_CONTEXT *L = (ENTROPY_CONTEXT *)xd->left_context;
438*fb1b10abSAndroid Build Coastguard Worker   int plane_type;
439*fb1b10abSAndroid Build Coastguard Worker   int b;
440*fb1b10abSAndroid Build Coastguard Worker   plane_type = 3;
441*fb1b10abSAndroid Build Coastguard Worker   if ((xd->mode_info_context->mbmi.mode != B_PRED &&
442*fb1b10abSAndroid Build Coastguard Worker        xd->mode_info_context->mbmi.mode != SPLITMV)) {
443*fb1b10abSAndroid Build Coastguard Worker     stuff2nd_order_b(t, A + vp8_block2above[24], L + vp8_block2left[24], cpi,
444*fb1b10abSAndroid Build Coastguard Worker                      x);
445*fb1b10abSAndroid Build Coastguard Worker     plane_type = 0;
446*fb1b10abSAndroid Build Coastguard Worker   }
447*fb1b10abSAndroid Build Coastguard Worker 
448*fb1b10abSAndroid Build Coastguard Worker   for (b = 0; b < 16; ++b) {
449*fb1b10abSAndroid Build Coastguard Worker     stuff1st_order_b(t, A + vp8_block2above[b], L + vp8_block2left[b],
450*fb1b10abSAndroid Build Coastguard Worker                      plane_type, cpi, x);
451*fb1b10abSAndroid Build Coastguard Worker   }
452*fb1b10abSAndroid Build Coastguard Worker 
453*fb1b10abSAndroid Build Coastguard Worker   for (b = 16; b < 24; ++b) {
454*fb1b10abSAndroid Build Coastguard Worker     stuff1st_order_buv(t, A + vp8_block2above[b], L + vp8_block2left[b], cpi,
455*fb1b10abSAndroid Build Coastguard Worker                        x);
456*fb1b10abSAndroid Build Coastguard Worker   }
457*fb1b10abSAndroid Build Coastguard Worker }
vp8_fix_contexts(MACROBLOCKD * x)458*fb1b10abSAndroid Build Coastguard Worker void vp8_fix_contexts(MACROBLOCKD *x) {
459*fb1b10abSAndroid Build Coastguard Worker   /* Clear entropy contexts for Y2 blocks */
460*fb1b10abSAndroid Build Coastguard Worker   if (x->mode_info_context->mbmi.mode != B_PRED &&
461*fb1b10abSAndroid Build Coastguard Worker       x->mode_info_context->mbmi.mode != SPLITMV) {
462*fb1b10abSAndroid Build Coastguard Worker     memset(x->above_context, 0, sizeof(ENTROPY_CONTEXT_PLANES));
463*fb1b10abSAndroid Build Coastguard Worker     memset(x->left_context, 0, sizeof(ENTROPY_CONTEXT_PLANES));
464*fb1b10abSAndroid Build Coastguard Worker   } else {
465*fb1b10abSAndroid Build Coastguard Worker     memset(x->above_context, 0, sizeof(ENTROPY_CONTEXT_PLANES) - 1);
466*fb1b10abSAndroid Build Coastguard Worker     memset(x->left_context, 0, sizeof(ENTROPY_CONTEXT_PLANES) - 1);
467*fb1b10abSAndroid Build Coastguard Worker   }
468*fb1b10abSAndroid Build Coastguard Worker }
469