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.
13 /* Arithmetic bool coder with largish probability range.
14 Timothy S Murphy 6 August 2004 */
19 #include "bool_coder.h"
23 # include "VP8cx/treewriter.h"
27 int_types::~int_types() {}
29 void bool_coder_spec::check_prec() const {
30 assert( w
&& (r
==Up
|| w
> 1) && w
< 24 && (ebias
|| w
< 17));
33 bool bool_coder_spec::float_init( uint Ebits
, uint Mbits
) {
34 uint b
= (ebits
= Ebits
) + (mbits
= Mbits
);
36 assert( ebits
< 6 && w
+ mbits
< 31);
37 assert( ebits
+ mbits
< sizeof(Index
) * 8);
38 ebias
= (1 << ebits
) + 1 + mbits
;
39 mmask
= (1 << mbits
) - 1;
40 max_index
= ( ( half_index
= 1 << b
) << 1) - 1;
50 void bool_coder_spec::cost_init()
52 static cdouble c
= -(1 << 20)/log( 2.);
54 FILE *f
= fopen( "costs.txt", "w");
57 assert( sizeof(int) >= 4); /* for C interface */
58 assert( max_index
<= 255); /* size of Ctbl */
60 cdouble p
= ( *this)( (Index
) i
);
61 Ctbl
[i
] = (uint32
) ( log( p
) * c
);
63 f
, "cost( %d -> %10.7f) = %10d = %12.5f bits\n",
64 i
, p
, Ctbl
[i
], (double) Ctbl
[i
] / (1<<20)
66 } while( ++i
<= max_index
);
70 bool_coder_spec_explicit_table::bool_coder_spec_explicit_table(
71 cuint16 tbl
[256], Rounding rr
, uint prec
73 : bool_coder_spec( prec
, rr
)
78 do { Ptbl
[i
] = tbl
[i
];} while( ++i
< 256);
80 do { Ptbl
[i
] = i
<< 8;} while( ++i
< 256);
85 bool_coder_spec_exponential_table::bool_coder_spec_exponential_table(
86 uint x
, Rounding rr
, uint prec
88 : bool_coder_spec( prec
, rr
)
90 assert( x
> 1 && x
<= 16);
93 Ptbl
[0] = (uint16
) pow( 2., 16. - x
);
96 cdouble d
= pow( .5, 1. + (1. - i
/128.)*x
) * 65536.;
97 uint16 v
= (uint16
) d
;
100 Ptbl
[256-i
] = (uint16
) ( 65536U - (Ptbl
[i
] = v
));
105 bool_coder_spec::bool_coder_spec( FILE *fp
) {
106 fscanf( fp
, "%d", &w
);
108 fscanf( fp
, "%d", &v
);
109 assert( 0 <= v
&& v
<= 2);
111 fscanf( fp
, "%d", &ebits
);
112 fscanf( fp
, "%d", &mbits
);
113 if( float_init( ebits
, mbits
))
117 fscanf( fp
, "%d", &v
);
118 assert( 0 <=v
&& v
<= 65535U);
124 void bool_coder_spec::dump( FILE *fp
) const {
125 fprintf( fp
, "%d %d %d %d\n", w
, (int) r
, ebits
, mbits
);
128 int i
=0; do { fprintf( fp
, "%d\n", Ptbl
[i
]);} while( ++i
< 256);
131 vp8bc_index_t
bool_coder_spec::operator()( double p
) const
139 return max_index
- ( *this)( 1. - p
);
141 uint m
= (uint
) ldexp( frexp( p
, &e
), mbits
+ 2);
142 uint x
= 1 << (mbits
+ 1);
143 assert( x
<= m
&& m
< x
<<1);
144 if( (m
= (m
>> 1) + (m
& 1)) >= x
) {
150 return half_index
- 1;
153 return (Index
) ( (e
<< mbits
) + (m
& mmask
));
156 cuint16 v
= (uint16
) (p
* 65536.);
160 while( w
= Ptbl
[i
], j
>>= 1) {
169 cuint16 x
= Ptbl
[i
-1];
170 if( v
<= x
|| w
- v
> v
- x
)
172 } else if( w
< v
&& i
< 255) {
173 cuint16 x
= Ptbl
[i
+1];
174 if( x
<= v
|| x
- v
< v
- w
)
180 double bool_coder_spec::operator()( Index i
) const {
182 return Ptbl
[i
]/65536.;
184 return 1. - ( *this)( (Index
) (max_index
- i
));
185 return ldexp( (double)mantissa( i
), - (int) exponent( i
));
190 void bool_writer::carry() {
193 while( *--p
== 255) { assert( p
> Bstart
); *p
= 0;}
198 bool_writer::bool_writer( c_spec
& s
, uchar
*Dest
, size_t Len
)
201 Bend( Len
? Dest
+Len
: 0),
208 bool_writer::~bool_writer() { flush();}
211 extern "C" { int bc_v
= 0;}
217 void bool_writer::raw( bool value
, uint32 s
) {
220 assert( Range
>= min_range
&& Range
<= spec
.max_range());
221 assert( !is_toast
&& s
&& s
< Range
);
224 "Writing a %d, B %x Low %x Range %x s %x blag %d ...\n",
225 value
? 1:0, B
-Bstart
, Low
, Range
, s
, bit_lag
233 int ct
= bit_lag
; do {
238 assert( !Bend
|| B
< Bend
);
239 *B
++ = (uchar
) (L
>> 23);
242 } while( L
+= L
, (s
+= s
+ rinc
) < min_range
);
249 "...done, B %x Low %x Range %x blag %d \n",
250 B
-Bstart
, Low
, Range
, bit_lag
254 bool_writer
& bool_writer::flush() {
260 if( L
& (1 << (32 - b
)))
267 assert( !Bend
|| B
+ 4 <= Bend
);
269 *B
++ = (uchar
) (L
>> 24);
277 bool_reader::bool_reader( c_spec
& s
, cuchar
*src
, size_t Len
)
281 Bend( Len
? src
+Len
: 0),
285 int i
= 4; do { Low
<<= 8; Low
|= *B
++;} while( --i
);
289 bool bool_reader::raw( uint32 s
) {
293 cuint32 S
= s
<< shf
;
295 assert( Range
>= min_range
&& Range
<= spec
.max_range());
296 assert( s
&& s
< Range
&& (L
>> shf
) < Range
);
300 "Reading, B %x Low %x Range %x s %x bct %d ...\n",
301 B
-Bstart
, Low
, Range
, s
, bct
307 assert( L
< (s
<< shf
));
314 assert( ~L
& (1 << 31));
318 if( !Bend
|| B
< Bend
)
321 } while( (s
+= s
+ rinc
) < min_range
);
328 "...done, val %d B %x Low %x Range %x bct %d\n",
329 val
? 1:0, B
-Bstart
, Low
, Range
, bct
339 struct NS
: bool_coder_namespace
{
340 static Rounding
r( vp8bc_c_prec
*p
, Rounding rr
=down_full
) {
341 return p
? (Rounding
) p
->r
: rr
;
345 bool_coder_spec
*vp8bc_vp6spec() {
346 return new bool_coder_spec_explicit_table( 0, bool_coder_namespace::Down
, 8);
348 bool_coder_spec
*vp8bc_float_spec(
349 unsigned int Ebits
, unsigned int Mbits
, vp8bc_c_prec
*p
351 return new bool_coder_spec_float( Ebits
, Mbits
, NS::r( p
), p
? p
->prec
: 12);
353 bool_coder_spec
*vp8bc_literal_spec(
354 const unsigned short m
[256], vp8bc_c_prec
*p
356 return new bool_coder_spec_explicit_table( m
, NS::r( p
), p
? p
->prec
: 16);
358 bool_coder_spec
*vp8bc_exponential_spec( unsigned int x
, vp8bc_c_prec
*p
)
360 return new bool_coder_spec_exponential_table( x
, NS::r( p
), p
? p
->prec
: 16);
362 bool_coder_spec
*vp8bc_spec_from_file( FILE *fp
) {
363 return new bool_coder_spec( fp
);
365 void vp8bc_destroy_spec( c_bool_coder_spec
*p
) { delete p
;}
367 void vp8bc_spec_to_file( c_bool_coder_spec
*p
, FILE *fp
) { p
->dump( fp
);}
369 vp8bc_index_t
vp8bc_index( c_bool_coder_spec
*p
, double x
) {
373 vp8bc_index_t
vp8bc_index_from_counts(
374 c_bool_coder_spec
*p
, unsigned int L
, unsigned int R
376 return ( *p
)( (R
+= L
)? (double) L
/R
: .5);
379 double vp8bc_probability( c_bool_coder_spec
*p
, vp8bc_index_t i
) {
383 vp8bc_index_t
vp8bc_complement( c_bool_coder_spec
*p
, vp8bc_index_t i
) {
384 return p
->complement( i
);
386 unsigned int vp8bc_cost_zero( c_bool_coder_spec
*p
, vp8bc_index_t i
) {
387 return p
->cost_zero( i
);
389 unsigned int vp8bc_cost_one( c_bool_coder_spec
*p
, vp8bc_index_t i
) {
390 return p
->cost_one( i
);
392 unsigned int vp8bc_cost_bit( c_bool_coder_spec
*p
, vp8bc_index_t i
, int v
) {
393 return p
->cost_bit( i
, v
);
397 extern "C" int tok_verbose
;
399 # define dbg_l 1000000
401 static vp8bc_index_t dbg_i
[dbg_l
];
402 static char dbg_v
[dbg_l
];
403 static size_t dbg_w
= 0, dbg_r
= 0;
408 bool_writer
*vp8bc_create_writer(
409 c_bool_coder_spec
*p
, unsigned char *D
, size_t L
411 return new bool_writer( *p
, D
, L
);
414 size_t vp8bc_destroy_writer( bool_writer
*p
) {
415 const size_t s
= p
->flush().bytes_written();
420 void vp8bc_write_bool( bool_writer
*p
, int v
, vp8bc_index_t i
)
423 // bc_v = dbg_w < 10;
424 if( bc_v
= tok_verbose
)
425 printf( " writing %d at prob %d\n", v
? 1:0, i
);
426 accum_entropy_bc( &p
->Spec(), i
, v
);
432 dbg_v
[dbg_w
++] = v
? 1:0;
439 void vp8bc_write_bits( bool_writer
*p
, unsigned int v
, int n
)
443 c_bool_coder_spec
* const s
= & p
->Spec();
444 const vp8bc_index_t i
= s
->half_index();
447 accum_entropy_bc( s
, i
, (v
>>m
) & 1);
451 p
->write_bits( n
, v
);
454 c_bool_coder_spec
*vp8bc_writer_spec( c_bool_writer
*w
) { return & w
->Spec();}
458 bool_reader
*vp8bc_create_reader(
459 c_bool_coder_spec
*p
, const unsigned char *S
, size_t L
461 return new bool_reader( *p
, S
, L
);
464 void vp8bc_destroy_reader( bool_reader
* p
) { delete p
;}
466 int vp8bc_read_bool( bool_reader
*p
, vp8bc_index_t i
)
469 // bc_v = dbg_r < 10;
471 const int v
= ( *p
)( i
)? 1:0;
473 printf( " reading %d at prob %d\n", v
, i
);
475 assert( dbg_r
<= dbg_w
);
476 if( i
!= dbg_i
[dbg_r
] || v
!= dbg_v
[dbg_r
]) {
478 "Position %d: INCORRECTLY READING %d prob %d, wrote %d prob %d\n",
479 dbg_r
, v
, i
, dbg_v
[dbg_r
], dbg_i
[dbg_r
]
486 return ( *p
)( i
)? 1:0;
490 unsigned int vp8bc_read_bits( bool_reader
*p
, int n
) { return p
->read_bits( n
);}
492 c_bool_coder_spec
*vp8bc_reader_spec( c_bool_reader
*r
) { return & r
->Spec();}