2 * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
4 * Use of this source code is governed by a BSD-style license and patent
5 * grant that can be found in the LICENSE file in the root of the source
6 * tree. All contributing project authors may be found in the AUTHORS
7 * file in the root of the source tree.
12 /* Arithmetic bool coder with largish probability range.
13 Timothy S Murphy 6 August 2004 */
18 #include "bool_coder.h"
22 # include "VP8cx/treewriter.h"
26 int_types::~int_types() {}
28 void bool_coder_spec::check_prec() const {
29 assert( w && (r==Up || w > 1) && w < 24 && (ebias || w < 17));
32 bool bool_coder_spec::float_init( uint Ebits, uint Mbits) {
33 uint b = (ebits = Ebits) + (mbits = Mbits);
35 assert( ebits < 6 && w + mbits < 31);
36 assert( ebits + mbits < sizeof(Index) * 8);
37 ebias = (1 << ebits) + 1 + mbits;
38 mmask = (1 << mbits) - 1;
39 max_index = ( ( half_index = 1 << b ) << 1) - 1;
49 void bool_coder_spec::cost_init()
51 static cdouble c = -(1 << 20)/log( 2.);
53 FILE *f = fopen( "costs.txt", "w");
56 assert( sizeof(int) >= 4); /* for C interface */
57 assert( max_index <= 255); /* size of Ctbl */
59 cdouble p = ( *this)( (Index) i);
60 Ctbl[i] = (uint32) ( log( p) * c);
62 f, "cost( %d -> %10.7f) = %10d = %12.5f bits\n",
63 i, p, Ctbl[i], (double) Ctbl[i] / (1<<20)
65 } while( ++i <= max_index);
69 bool_coder_spec_explicit_table::bool_coder_spec_explicit_table(
70 cuint16 tbl[256], Rounding rr, uint prec
72 : bool_coder_spec( prec, rr)
77 do { Ptbl[i] = tbl[i];} while( ++i < 256);
79 do { Ptbl[i] = i << 8;} while( ++i < 256);
84 bool_coder_spec_exponential_table::bool_coder_spec_exponential_table(
85 uint x, Rounding rr, uint prec
87 : bool_coder_spec( prec, rr)
89 assert( x > 1 && x <= 16);
92 Ptbl[0] = (uint16) pow( 2., 16. - x);
95 cdouble d = pow( .5, 1. + (1. - i/128.)*x) * 65536.;
96 uint16 v = (uint16) d;
99 Ptbl[256-i] = (uint16) ( 65536U - (Ptbl[i] = v));
104 bool_coder_spec::bool_coder_spec( FILE *fp) {
105 fscanf( fp, "%d", &w);
107 fscanf( fp, "%d", &v);
108 assert( 0 <= v && v <= 2);
110 fscanf( fp, "%d", &ebits);
111 fscanf( fp, "%d", &mbits);
112 if( float_init( ebits, mbits))
116 fscanf( fp, "%d", &v);
117 assert( 0 <=v && v <= 65535U);
123 void bool_coder_spec::dump( FILE *fp) const {
124 fprintf( fp, "%d %d %d %d\n", w, (int) r, ebits, mbits);
127 int i=0; do { fprintf( fp, "%d\n", Ptbl[i]);} while( ++i < 256);
130 vp8bc_index_t bool_coder_spec::operator()( double p) const
138 return max_index - ( *this)( 1. - p);
140 uint m = (uint) ldexp( frexp( p, &e), mbits + 2);
141 uint x = 1 << (mbits + 1);
142 assert( x <= m && m < x<<1);
143 if( (m = (m >> 1) + (m & 1)) >= x) {
149 return half_index - 1;
152 return (Index) ( (e << mbits) + (m & mmask));
155 cuint16 v = (uint16) (p * 65536.);
159 while( w = Ptbl[i], j >>= 1) {
168 cuint16 x = Ptbl[i-1];
169 if( v <= x || w - v > v - x)
171 } else if( w < v && i < 255) {
172 cuint16 x = Ptbl[i+1];
173 if( x <= v || x - v < v - w)
179 double bool_coder_spec::operator()( Index i) const {
181 return Ptbl[i]/65536.;
183 return 1. - ( *this)( (Index) (max_index - i));
184 return ldexp( (double)mantissa( i), - (int) exponent( i));
189 void bool_writer::carry() {
192 while( *--p == 255) { assert( p > Bstart); *p = 0;}
197 bool_writer::bool_writer( c_spec& s, uchar *Dest, size_t Len)
200 Bend( Len? Dest+Len : 0),
207 bool_writer::~bool_writer() { flush();}
210 extern "C" { int bc_v = 0;}
216 void bool_writer::raw( bool value, uint32 s) {
219 assert( Range >= min_range && Range <= spec.max_range());
220 assert( !is_toast && s && s < Range);
223 "Writing a %d, B %x Low %x Range %x s %x blag %d ...\n",
224 value? 1:0, B-Bstart, Low, Range, s, bit_lag
232 int ct = bit_lag; do {
237 assert( !Bend || B < Bend);
238 *B++ = (uchar) (L >> 23);
241 } while( L += L, (s += s + rinc) < min_range);
248 "...done, B %x Low %x Range %x blag %d \n",
249 B-Bstart, Low, Range, bit_lag
253 bool_writer& bool_writer::flush() {
259 if( L & (1 << (32 - b)))
266 assert( !Bend || B + 4 <= Bend);
268 *B++ = (uchar) (L >> 24);
276 bool_reader::bool_reader( c_spec& s, cuchar *src, size_t Len)
280 Bend( Len? src+Len : 0),
284 int i = 4; do { Low <<= 8; Low |= *B++;} while( --i);
288 bool bool_reader::raw( uint32 s) {
292 cuint32 S = s << shf;
294 assert( Range >= min_range && Range <= spec.max_range());
295 assert( s && s < Range && (L >> shf) < Range);
299 "Reading, B %x Low %x Range %x s %x bct %d ...\n",
300 B-Bstart, Low, Range, s, bct
306 assert( L < (s << shf));
313 assert( ~L & (1 << 31));
317 if( !Bend || B < Bend)
320 } while( (s += s + rinc) < min_range);
327 "...done, val %d B %x Low %x Range %x bct %d\n",
328 val? 1:0, B-Bstart, Low, Range, bct
338 struct NS : bool_coder_namespace {
339 static Rounding r( vp8bc_c_prec *p, Rounding rr =down_full) {
340 return p? (Rounding) p->r : rr;
344 bool_coder_spec *vp8bc_vp6spec() {
345 return new bool_coder_spec_explicit_table( 0, bool_coder_namespace::Down, 8);
347 bool_coder_spec *vp8bc_float_spec(
348 unsigned int Ebits, unsigned int Mbits, vp8bc_c_prec *p
350 return new bool_coder_spec_float( Ebits, Mbits, NS::r( p), p? p->prec : 12);
352 bool_coder_spec *vp8bc_literal_spec(
353 const unsigned short m[256], vp8bc_c_prec *p
355 return new bool_coder_spec_explicit_table( m, NS::r( p), p? p->prec : 16);
357 bool_coder_spec *vp8bc_exponential_spec( unsigned int x, vp8bc_c_prec *p)
359 return new bool_coder_spec_exponential_table( x, NS::r( p), p? p->prec : 16);
361 bool_coder_spec *vp8bc_spec_from_file( FILE *fp) {
362 return new bool_coder_spec( fp);
364 void vp8bc_destroy_spec( c_bool_coder_spec *p) { delete p;}
366 void vp8bc_spec_to_file( c_bool_coder_spec *p, FILE *fp) { p->dump( fp);}
368 vp8bc_index_t vp8bc_index( c_bool_coder_spec *p, double x) {
372 vp8bc_index_t vp8bc_index_from_counts(
373 c_bool_coder_spec *p, unsigned int L, unsigned int R
375 return ( *p)( (R += L)? (double) L/R : .5);
378 double vp8bc_probability( c_bool_coder_spec *p, vp8bc_index_t i) {
382 vp8bc_index_t vp8bc_complement( c_bool_coder_spec *p, vp8bc_index_t i) {
383 return p->complement( i);
385 unsigned int vp8bc_cost_zero( c_bool_coder_spec *p, vp8bc_index_t i) {
386 return p->cost_zero( i);
388 unsigned int vp8bc_cost_one( c_bool_coder_spec *p, vp8bc_index_t i) {
389 return p->cost_one( i);
391 unsigned int vp8bc_cost_bit( c_bool_coder_spec *p, vp8bc_index_t i, int v) {
392 return p->cost_bit( i, v);
396 extern "C" int tok_verbose;
398 # define dbg_l 1000000
400 static vp8bc_index_t dbg_i [dbg_l];
401 static char dbg_v [dbg_l];
402 static size_t dbg_w = 0, dbg_r = 0;
407 bool_writer *vp8bc_create_writer(
408 c_bool_coder_spec *p, unsigned char *D, size_t L
410 return new bool_writer( *p, D, L);
413 size_t vp8bc_destroy_writer( bool_writer *p) {
414 const size_t s = p->flush().bytes_written();
419 void vp8bc_write_bool( bool_writer *p, int v, vp8bc_index_t i)
422 // bc_v = dbg_w < 10;
423 if( bc_v = tok_verbose)
424 printf( " writing %d at prob %d\n", v? 1:0, i);
425 accum_entropy_bc( &p->Spec(), i, v);
431 dbg_v [dbg_w++] = v? 1:0;
438 void vp8bc_write_bits( bool_writer *p, unsigned int v, int n)
442 c_bool_coder_spec * const s = & p->Spec();
443 const vp8bc_index_t i = s->half_index();
446 accum_entropy_bc( s, i, (v>>m) & 1);
450 p->write_bits( n, v);
453 c_bool_coder_spec *vp8bc_writer_spec( c_bool_writer *w) { return & w->Spec();}
457 bool_reader *vp8bc_create_reader(
458 c_bool_coder_spec *p, const unsigned char *S, size_t L
460 return new bool_reader( *p, S, L);
463 void vp8bc_destroy_reader( bool_reader * p) { delete p;}
465 int vp8bc_read_bool( bool_reader *p, vp8bc_index_t i)
468 // bc_v = dbg_r < 10;
470 const int v = ( *p)( i)? 1:0;
472 printf( " reading %d at prob %d\n", v, i);
474 assert( dbg_r <= dbg_w);
475 if( i != dbg_i[dbg_r] || v != dbg_v[dbg_r]) {
477 "Position %d: INCORRECTLY READING %d prob %d, wrote %d prob %d\n",
478 dbg_r, v, i, dbg_v[dbg_r], dbg_i[dbg_r]
485 return ( *p)( i)? 1:0;
489 unsigned int vp8bc_read_bits( bool_reader *p, int n) { return p->read_bits( n);}
491 c_bool_coder_spec *vp8bc_reader_spec( c_bool_reader *r) { return & r->Spec();}