2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
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.
18 #include "vpx_mem/vpx_mem.h"
20 /* Global event counters used for accumulating statistics across several
21 compressions, then generating context.c = initial stats. */
24 _int64 context_counters
[BLOCK_TYPES
] [COEF_BANDS
] [PREV_COEF_CONTEXTS
] [MAX_ENTROPY_TOKENS
];
26 void vp8_stuff_mb(VP8_COMP
*cpi
, MACROBLOCKD
*x
, TOKENEXTRA
**t
) ;
27 void vp8_fix_contexts(MACROBLOCKD
*x
);
29 static TOKENVALUE dct_value_tokens
[DCT_MAX_VALUE
*2];
30 const TOKENVALUE
*vp8_dct_value_tokens_ptr
;
31 static int dct_value_cost
[DCT_MAX_VALUE
*2];
32 const int *vp8_dct_value_cost_ptr
;
34 int skip_true_count
= 0;
35 int skip_false_count
= 0;
37 static void fill_value_tokens()
40 TOKENVALUE
*const t
= dct_value_tokens
+ DCT_MAX_VALUE
;
41 vp8_extra_bit_struct
*const e
= vp8_extra_bits
;
43 int i
= -DCT_MAX_VALUE
;
52 const int a
= sign
? -i
: i
;
59 while (++j
< 11 && e
[j
].base_val
<= a
) {}
62 eb
|= (a
- e
[j
].base_val
) << 1;
70 // initialize the cost for extra bits for all possible coefficient value.
73 vp8_extra_bit_struct
*p
= vp8_extra_bits
+ t
[i
].Token
;
77 const int extra
= t
[i
].Extra
;
78 const int Length
= p
->Len
;
81 cost
+= vp8_treed_cost(p
->tree
, p
->prob
, extra
>> 1, Length
);
83 cost
+= vp8_cost_bit(vp8_prob_half
, extra
& 1); /* sign */
84 dct_value_cost
[i
+ DCT_MAX_VALUE
] = cost
;
90 while (++i
< DCT_MAX_VALUE
);
92 vp8_dct_value_tokens_ptr
= dct_value_tokens
+ DCT_MAX_VALUE
;
93 vp8_dct_value_cost_ptr
= dct_value_cost
+ DCT_MAX_VALUE
;
96 static void tokenize2nd_order_b
103 int pt
; /* near block/prev token context index */
104 int c
; /* start at DC */
105 TOKENEXTRA
*t
= *tp
;/* store tokens starting here */
107 const short *qcoeff_ptr
;
110 int band
, rc
, v
, token
;
113 qcoeff_ptr
= b
->qcoeff
;
114 a
= (ENTROPY_CONTEXT
*)x
->above_context
+ 8;
115 l
= (ENTROPY_CONTEXT
*)x
->left_context
+ 8;
117 VP8_COMBINEENTROPYCONTEXTS(pt
, *a
, *l
);
119 for (c
= 0; c
< b
->eob
; c
++)
121 rc
= vp8_default_zig_zag1d
[c
];
122 band
= vp8_coef_bands
[c
];
125 t
->Extra
= vp8_dct_value_tokens_ptr
[v
].Extra
;
126 token
= vp8_dct_value_tokens_ptr
[v
].Token
;
129 t
->context_tree
= cpi
->common
.fc
.coef_probs
[1] [band
] [pt
];
131 t
->skip_eob_node
= ((pt
== 0) && (band
> 0));
133 ++cpi
->coef_counts
[1] [band
] [pt
] [token
];
135 pt
= vp8_prev_token_class
[token
];
140 band
= vp8_coef_bands
[c
];
141 t
->Token
= DCT_EOB_TOKEN
;
142 t
->context_tree
= cpi
->common
.fc
.coef_probs
[1] [band
] [pt
];
144 t
->skip_eob_node
= ((pt
== 0) && (band
> 0));
146 ++cpi
->coef_counts
[1] [band
] [pt
] [DCT_EOB_TOKEN
];
152 pt
= (c
!= 0); /* 0 <-> all coeff data is zero */
157 static void tokenize1st_order_b
161 int type
, /* which plane: 0=Y no DC, 1=Y2, 2=UV, 3=Y with DC */
167 int pt
; /* near block/prev token context index */
170 TOKENEXTRA
*t
= *tp
;/* store tokens starting here */
171 const short *qcoeff_ptr
;
179 for (block
= 0; block
< 16; block
++, b
++)
181 tmp1
= vp8_block2above
[block
];
182 tmp2
= vp8_block2left
[block
];
183 qcoeff_ptr
= b
->qcoeff
;
184 a
= (ENTROPY_CONTEXT
*)x
->above_context
+ tmp1
;
185 l
= (ENTROPY_CONTEXT
*)x
->left_context
+ tmp2
;
187 VP8_COMBINEENTROPYCONTEXTS(pt
, *a
, *l
);
191 for (; c
< b
->eob
; c
++)
193 rc
= vp8_default_zig_zag1d
[c
];
194 band
= vp8_coef_bands
[c
];
197 t
->Extra
= vp8_dct_value_tokens_ptr
[v
].Extra
;
198 token
= vp8_dct_value_tokens_ptr
[v
].Token
;
201 t
->context_tree
= cpi
->common
.fc
.coef_probs
[type
] [band
] [pt
];
203 t
->skip_eob_node
= pt
== 0 &&
204 ((band
> 0 && type
> 0) || (band
> 1 && type
== 0));
206 ++cpi
->coef_counts
[type
] [band
] [pt
] [token
];
208 pt
= vp8_prev_token_class
[token
];
213 band
= vp8_coef_bands
[c
];
214 t
->Token
= DCT_EOB_TOKEN
;
215 t
->context_tree
= cpi
->common
.fc
.coef_probs
[type
] [band
] [pt
];
217 t
->skip_eob_node
= pt
== 0 &&
218 ((band
> 0 && type
> 0) || (band
> 1 && type
== 0));
220 ++cpi
->coef_counts
[type
] [band
] [pt
] [DCT_EOB_TOKEN
];
225 pt
= (c
!= !type
); /* 0 <-> all coeff data is zero */
230 for (block
= 16; block
< 24; block
++, b
++)
232 tmp1
= vp8_block2above
[block
];
233 tmp2
= vp8_block2left
[block
];
234 qcoeff_ptr
= b
->qcoeff
;
235 a
= (ENTROPY_CONTEXT
*)x
->above_context
+ tmp1
;
236 l
= (ENTROPY_CONTEXT
*)x
->left_context
+ tmp2
;
238 VP8_COMBINEENTROPYCONTEXTS(pt
, *a
, *l
);
240 for (c
= 0; c
< b
->eob
; c
++)
242 rc
= vp8_default_zig_zag1d
[c
];
243 band
= vp8_coef_bands
[c
];
246 t
->Extra
= vp8_dct_value_tokens_ptr
[v
].Extra
;
247 token
= vp8_dct_value_tokens_ptr
[v
].Token
;
250 t
->context_tree
= cpi
->common
.fc
.coef_probs
[2] [band
] [pt
];
252 t
->skip_eob_node
= ((pt
== 0) && (band
> 0));
254 ++cpi
->coef_counts
[2] [band
] [pt
] [token
];
256 pt
= vp8_prev_token_class
[token
];
261 band
= vp8_coef_bands
[c
];
262 t
->Token
= DCT_EOB_TOKEN
;
263 t
->context_tree
= cpi
->common
.fc
.coef_probs
[2] [band
] [pt
];
265 t
->skip_eob_node
= ((pt
== 0) && (band
> 0));
267 ++cpi
->coef_counts
[2] [band
] [pt
] [DCT_EOB_TOKEN
];
272 pt
= (c
!= 0); /* 0 <-> all coeff data is zero */
279 static int mb_is_skippable(MACROBLOCKD
*x
, int has_y2_block
)
286 for (i
= 0; i
< 16; i
++)
287 skip
&= (x
->block
[i
].eob
< 2);
290 for (; i
< 24 + has_y2_block
; i
++)
291 skip
&= (!x
->block
[i
].eob
);
297 void vp8_tokenize_mb(VP8_COMP
*cpi
, MACROBLOCKD
*x
, TOKENEXTRA
**t
)
302 has_y2_block
= (x
->mode_info_context
->mbmi
.mode
!= B_PRED
303 && x
->mode_info_context
->mbmi
.mode
!= SPLITMV
);
305 x
->mode_info_context
->mbmi
.mb_skip_coeff
= mb_is_skippable(x
, has_y2_block
);
306 if (x
->mode_info_context
->mbmi
.mb_skip_coeff
)
308 cpi
->skip_true_count
++;
310 if (!cpi
->common
.mb_no_coeff_skip
)
311 vp8_stuff_mb(cpi
, x
, t
) ;
320 cpi
->skip_false_count
++;
325 tokenize2nd_order_b(x
, t
, cpi
);
330 tokenize1st_order_b(x
, t
, plane_type
, cpi
);
337 void init_context_counters(void)
339 vpx_memset(context_counters
, 0, sizeof(context_counters
));
342 void print_context_counters()
345 int type
, band
, pt
, t
;
347 FILE *const f
= fopen("context.c", "w");
349 fprintf(f
, "#include \"entropy.h\"\n");
351 fprintf(f
, "\n/* *** GENERATED FILE: DO NOT EDIT *** */\n\n");
353 fprintf(f
, "int Contexts[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS];\n\n");
355 fprintf(f
, "const int default_contexts[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS] = {");
357 # define Comma( X) (X? ",":"")
363 fprintf(f
, "%s\n { /* block Type %d */", Comma(type
), type
);
369 fprintf(f
, "%s\n { /* Coeff Band %d */", Comma(band
), band
);
375 fprintf(f
, "%s\n {", Comma(pt
));
381 const _int64 x
= context_counters
[type
] [band
] [pt
] [t
];
382 const int y
= (int) x
;
384 assert(x
== (_int64
) y
); /* no overflow handling yet */
385 fprintf(f
, "%s %d", Comma(t
), y
);
388 while (++t
< MAX_ENTROPY_TOKENS
);
392 while (++pt
< PREV_COEF_CONTEXTS
);
397 while (++band
< COEF_BANDS
);
401 while (++type
< BLOCK_TYPES
);
403 fprintf(f
, "\n};\n");
409 void vp8_tokenize_initialize()
415 static __inline
void stuff2nd_order_b
423 int pt
; /* near block/prev token context index */
424 TOKENEXTRA
*t
= *tp
; /* store tokens starting here */
425 VP8_COMBINEENTROPYCONTEXTS(pt
, *a
, *l
);
427 t
->Token
= DCT_EOB_TOKEN
;
428 t
->context_tree
= cpi
->common
.fc
.coef_probs
[1] [0] [pt
];
429 t
->skip_eob_node
= 0;
430 ++cpi
->coef_counts
[1] [0] [pt
] [DCT_EOB_TOKEN
];
439 static __inline
void stuff1st_order_b
447 int pt
; /* near block/prev token context index */
448 TOKENEXTRA
*t
= *tp
; /* store tokens starting here */
449 VP8_COMBINEENTROPYCONTEXTS(pt
, *a
, *l
);
451 t
->Token
= DCT_EOB_TOKEN
;
452 t
->context_tree
= cpi
->common
.fc
.coef_probs
[0] [1] [pt
];
453 t
->skip_eob_node
= 0;
454 ++cpi
->coef_counts
[0] [1] [pt
] [DCT_EOB_TOKEN
];
457 pt
= 0; /* 0 <-> all coeff data is zero */
462 void stuff1st_order_buv
470 int pt
; /* near block/prev token context index */
471 TOKENEXTRA
*t
= *tp
; /* store tokens starting here */
472 VP8_COMBINEENTROPYCONTEXTS(pt
, *a
, *l
);
474 t
->Token
= DCT_EOB_TOKEN
;
475 t
->context_tree
= cpi
->common
.fc
.coef_probs
[2] [0] [pt
];
476 t
->skip_eob_node
= 0;
477 ++cpi
->coef_counts
[2] [0] [pt
] [DCT_EOB_TOKEN
];
480 pt
= 0; /* 0 <-> all coeff data is zero */
485 void vp8_stuff_mb(VP8_COMP
*cpi
, MACROBLOCKD
*x
, TOKENEXTRA
**t
)
487 ENTROPY_CONTEXT
* A
= (ENTROPY_CONTEXT
*)x
->above_context
;
488 ENTROPY_CONTEXT
* L
= (ENTROPY_CONTEXT
*)x
->left_context
;
493 A
+ vp8_block2above
[24], L
+ vp8_block2left
[24], cpi
);
496 for (b
= 0; b
< 16; b
++)
498 A
+ vp8_block2above
[b
],
499 L
+ vp8_block2left
[b
], cpi
);
501 for (b
= 16; b
< 24; b
++)
502 stuff1st_order_buv(t
,
503 A
+ vp8_block2above
[b
],
504 L
+ vp8_block2left
[b
], cpi
);
507 void vp8_fix_contexts(MACROBLOCKD
*x
)
509 /* Clear entropy contexts for Y2 blocks */
510 if (x
->mode_info_context
->mbmi
.mode
!= B_PRED
&& x
->mode_info_context
->mbmi
.mode
!= SPLITMV
)
512 vpx_memset(x
->above_context
, 0, sizeof(ENTROPY_CONTEXT_PLANES
));
513 vpx_memset(x
->left_context
, 0, sizeof(ENTROPY_CONTEXT_PLANES
));
517 vpx_memset(x
->above_context
, 0, sizeof(ENTROPY_CONTEXT_PLANES
)-1);
518 vpx_memset(x
->left_context
, 0, sizeof(ENTROPY_CONTEXT_PLANES
)-1);