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