| OLD | NEW | 
|---|
|  | (Empty) | 
| 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 |  | 
| 12 |  | 
| 13 /* Arithmetic bool coder with largish probability range. |  | 
| 14    Timothy S Murphy  6 August 2004 */ |  | 
| 15 |  | 
| 16 #include <assert.h> |  | 
| 17 #include <math.h> |  | 
| 18 |  | 
| 19 #include "bool_coder.h" |  | 
| 20 |  | 
| 21 #if tim_vp8 |  | 
| 22     extern "C" { |  | 
| 23 #       include "VP8cx/treewriter.h" |  | 
| 24     } |  | 
| 25 #endif |  | 
| 26 |  | 
| 27 int_types::~int_types() {} |  | 
| 28 |  | 
| 29 void bool_coder_spec::check_prec() const { |  | 
| 30     assert( w  &&  (r==Up || w > 1)  &&  w < 24  &&  (ebias || w < 17)); |  | 
| 31 } |  | 
| 32 |  | 
| 33 bool bool_coder_spec::float_init( uint Ebits, uint Mbits) { |  | 
| 34     uint b = (ebits = Ebits) + (mbits = Mbits); |  | 
| 35     if( b) { |  | 
| 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; |  | 
| 41     } else { |  | 
| 42         ebias = 0; |  | 
| 43         max_index = 255; |  | 
| 44         half_index = 128; |  | 
| 45     } |  | 
| 46     check_prec(); |  | 
| 47     return b? 1:0; |  | 
| 48 } |  | 
| 49 |  | 
| 50 void bool_coder_spec::cost_init() |  | 
| 51 { |  | 
| 52     static cdouble c = -(1 << 20)/log( 2.); |  | 
| 53 |  | 
| 54     FILE *f = fopen( "costs.txt", "w"); |  | 
| 55     assert( f); |  | 
| 56 |  | 
| 57     assert( sizeof(int) >= 4);  /* for C interface */ |  | 
| 58     assert( max_index <= 255);   /* size of Ctbl */ |  | 
| 59     uint i = 0;  do { |  | 
| 60         cdouble p = ( *this)( (Index) i); |  | 
| 61         Ctbl[i] = (uint32) ( log( p) * c); |  | 
| 62         fprintf( |  | 
| 63             f, "cost( %d -> %10.7f) = %10d = %12.5f bits\n", |  | 
| 64             i, p, Ctbl[i], (double) Ctbl[i] / (1<<20) |  | 
| 65         ); |  | 
| 66     } while( ++i <= max_index); |  | 
| 67     fclose( f); |  | 
| 68 } |  | 
| 69 |  | 
| 70 bool_coder_spec_explicit_table::bool_coder_spec_explicit_table( |  | 
| 71     cuint16 tbl[256], Rounding rr, uint prec |  | 
| 72 ) |  | 
| 73   : bool_coder_spec( prec, rr) |  | 
| 74 { |  | 
| 75     check_prec(); |  | 
| 76     uint i = 0; |  | 
| 77     if( tbl) |  | 
| 78         do { Ptbl[i] = tbl[i];}  while( ++i < 256); |  | 
| 79     else |  | 
| 80         do { Ptbl[i] = i << 8;}  while( ++i < 256); |  | 
| 81     cost_init(); |  | 
| 82 } |  | 
| 83 |  | 
| 84 |  | 
| 85 bool_coder_spec_exponential_table::bool_coder_spec_exponential_table( |  | 
| 86     uint x, Rounding rr, uint prec |  | 
| 87 ) |  | 
| 88   : bool_coder_spec( prec, rr) |  | 
| 89 { |  | 
| 90     assert( x > 1  &&  x <= 16); |  | 
| 91     check_prec(); |  | 
| 92     Ptbl[128] = 32768u; |  | 
| 93     Ptbl[0] = (uint16) pow( 2., 16. - x); |  | 
| 94     --x; |  | 
| 95     int i=1;  do { |  | 
| 96         cdouble d = pow( .5, 1. + (1. - i/128.)*x) * 65536.; |  | 
| 97         uint16 v = (uint16) d; |  | 
| 98         if( v < i) |  | 
| 99             v = i; |  | 
| 100         Ptbl[256-i] = (uint16) ( 65536U - (Ptbl[i] = v)); |  | 
| 101     } while( ++i < 128); |  | 
| 102     cost_init(); |  | 
| 103 } |  | 
| 104 |  | 
| 105 bool_coder_spec::bool_coder_spec( FILE *fp) { |  | 
| 106     fscanf( fp, "%d", &w); |  | 
| 107     int v; |  | 
| 108     fscanf( fp, "%d", &v); |  | 
| 109     assert( 0 <= v  &&  v <= 2); |  | 
| 110     r = (Rounding) v; |  | 
| 111     fscanf( fp, "%d", &ebits); |  | 
| 112     fscanf( fp, "%d", &mbits); |  | 
| 113     if( float_init( ebits, mbits)) |  | 
| 114         return; |  | 
| 115     int i=0;  do { |  | 
| 116         uint v; |  | 
| 117         fscanf( fp, "%d", &v); |  | 
| 118         assert( 0 <=v  &&  v <= 65535U); |  | 
| 119         Ptbl[i] = v; |  | 
| 120     } while( ++i < 256); |  | 
| 121     cost_init(); |  | 
| 122 } |  | 
| 123 |  | 
| 124 void bool_coder_spec::dump( FILE *fp) const { |  | 
| 125     fprintf( fp, "%d %d %d %d\n", w, (int) r, ebits, mbits); |  | 
| 126     if( ebits  ||  mbits) |  | 
| 127         return; |  | 
| 128     int i=0;  do { fprintf( fp, "%d\n", Ptbl[i]);}  while( ++i < 256); |  | 
| 129 } |  | 
| 130 |  | 
| 131 vp8bc_index_t bool_coder_spec::operator()( double p) const |  | 
| 132 { |  | 
| 133     if( p <= 0.) |  | 
| 134         return 0; |  | 
| 135     if( p >= 1.) |  | 
| 136         return max_index; |  | 
| 137     if( ebias) { |  | 
| 138         if( p > .5) |  | 
| 139             return max_index - ( *this)( 1. - p); |  | 
| 140         int e; |  | 
| 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) { |  | 
| 145             m = x >> 1; |  | 
| 146             ++e; |  | 
| 147         } |  | 
| 148         int y = 1 << ebits; |  | 
| 149         if( (e += y) >= y) |  | 
| 150             return half_index - 1; |  | 
| 151         if( e < 0) |  | 
| 152             return 0; |  | 
| 153         return (Index) ( (e << mbits) + (m & mmask)); |  | 
| 154     } |  | 
| 155 |  | 
| 156     cuint16 v = (uint16) (p * 65536.); |  | 
| 157     int i = 128; |  | 
| 158     int j = 128; |  | 
| 159     uint16 w; |  | 
| 160     while( w = Ptbl[i], j >>= 1) { |  | 
| 161         if( w < v) |  | 
| 162             i += j; |  | 
| 163         else if( w == v) |  | 
| 164             return (uchar) i; |  | 
| 165         else |  | 
| 166             i -= j; |  | 
| 167     } |  | 
| 168     if( w > v) { |  | 
| 169         cuint16 x = Ptbl[i-1]; |  | 
| 170         if( v <= x  ||  w - v > v - x) |  | 
| 171             --i; |  | 
| 172     } else if( w < v  &&  i < 255) { |  | 
| 173         cuint16 x = Ptbl[i+1]; |  | 
| 174         if( x <= v  ||  x - v < v - w) |  | 
| 175             ++i; |  | 
| 176     } |  | 
| 177     return (Index) i; |  | 
| 178 } |  | 
| 179 |  | 
| 180 double bool_coder_spec::operator()( Index i) const { |  | 
| 181     if( !ebias) |  | 
| 182         return Ptbl[i]/65536.; |  | 
| 183     if( i >= half_index) |  | 
| 184         return 1. - ( *this)( (Index) (max_index - i)); |  | 
| 185     return ldexp( (double)mantissa( i), - (int) exponent( i)); |  | 
| 186 } |  | 
| 187 |  | 
| 188 |  | 
| 189 |  | 
| 190 void bool_writer::carry() { |  | 
| 191     uchar *p = B; |  | 
| 192     assert( p > Bstart); |  | 
| 193     while( *--p == 255) { assert( p > Bstart);  *p = 0;} |  | 
| 194     ++*p; |  | 
| 195 } |  | 
| 196 |  | 
| 197 |  | 
| 198 bool_writer::bool_writer( c_spec& s, uchar *Dest, size_t Len) |  | 
| 199   : bool_coder( s), |  | 
| 200     Bstart( Dest), |  | 
| 201     Bend( Len? Dest+Len : 0), |  | 
| 202     B( Dest) |  | 
| 203 { |  | 
| 204     assert( Dest); |  | 
| 205     reset(); |  | 
| 206 } |  | 
| 207 |  | 
| 208 bool_writer::~bool_writer() { flush();} |  | 
| 209 |  | 
| 210 #if 1 |  | 
| 211     extern "C" { int bc_v = 0;} |  | 
| 212 #else |  | 
| 213 #   define bc_v 0 |  | 
| 214 #endif |  | 
| 215 |  | 
| 216 |  | 
| 217 void bool_writer::raw( bool value, uint32 s) { |  | 
| 218     uint32 L = Low; |  | 
| 219 |  | 
| 220     assert( Range >= min_range  &&  Range <= spec.max_range()); |  | 
| 221     assert( !is_toast  &&  s  &&  s < Range); |  | 
| 222 |  | 
| 223     if( bc_v) printf( |  | 
| 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 |  | 
| 226     ); |  | 
| 227     if( value) { |  | 
| 228         L += s; |  | 
| 229         s = Range - s; |  | 
| 230     } else |  | 
| 231         s -= rinc; |  | 
| 232     if( s < min_range) { |  | 
| 233         int ct = bit_lag;  do { |  | 
| 234             if( !--ct) { |  | 
| 235                 ct = 8; |  | 
| 236                 if( L & (1 << 31)) |  | 
| 237                     carry(); |  | 
| 238                 assert( !Bend  ||  B < Bend); |  | 
| 239                 *B++ = (uchar) (L >> 23); |  | 
| 240                 L &= (1<<23) - 1; |  | 
| 241             } |  | 
| 242         } while( L += L, (s += s + rinc) < min_range); |  | 
| 243         bit_lag = ct; |  | 
| 244     } |  | 
| 245     Low = L; |  | 
| 246     Range = s; |  | 
| 247     if( bc_v) |  | 
| 248         printf( |  | 
| 249             "...done, B %x  Low %x  Range %x  blag %d \n", |  | 
| 250                 B-Bstart, Low, Range, bit_lag |  | 
| 251         ); |  | 
| 252 } |  | 
| 253 |  | 
| 254 bool_writer& bool_writer::flush() { |  | 
| 255     if( is_toast) |  | 
| 256         return *this; |  | 
| 257     int b = bit_lag; |  | 
| 258     uint32 L = Low; |  | 
| 259     assert( b); |  | 
| 260     if( L & (1 << (32 - b))) |  | 
| 261         carry(); |  | 
| 262     L <<= b & 7; |  | 
| 263     b >>= 3; |  | 
| 264     while( --b >= 0) |  | 
| 265         L <<= 8; |  | 
| 266     b = 4; |  | 
| 267     assert( !Bend  ||  B + 4 <= Bend); |  | 
| 268     do { |  | 
| 269         *B++ = (uchar) (L >> 24); |  | 
| 270         L <<= 8; |  | 
| 271     } while( --b); |  | 
| 272     is_toast = 1; |  | 
| 273     return *this; |  | 
| 274 } |  | 
| 275 |  | 
| 276 |  | 
| 277 bool_reader::bool_reader( c_spec& s, cuchar *src, size_t Len) |  | 
| 278   : bool_coder( s), |  | 
| 279     Bstart( src), |  | 
| 280     B( src), |  | 
| 281     Bend( Len? src+Len : 0), |  | 
| 282     shf( 32 - s.w), |  | 
| 283     bct( 8) |  | 
| 284 { |  | 
| 285     int i = 4;  do { Low <<= 8;  Low |= *B++;}  while( --i); |  | 
| 286 } |  | 
| 287 |  | 
| 288 |  | 
| 289 bool bool_reader::raw( uint32 s) { |  | 
| 290 |  | 
| 291     bool val = 0; |  | 
| 292     uint32 L = Low; |  | 
| 293     cuint32 S = s << shf; |  | 
| 294 |  | 
| 295     assert( Range >= min_range  &&  Range <= spec.max_range()); |  | 
| 296     assert( s  &&  s < Range  &&  (L >> shf) < Range); |  | 
| 297 |  | 
| 298     if( bc_v) |  | 
| 299         printf( |  | 
| 300             "Reading, B %x  Low %x  Range %x  s %x  bct %d ...\n", |  | 
| 301             B-Bstart, Low, Range, s, bct |  | 
| 302         ); |  | 
| 303 |  | 
| 304     if( L >= S) { |  | 
| 305         L -= S; |  | 
| 306         s = Range - s; |  | 
| 307         assert( L < (s << shf)); |  | 
| 308         val = 1; |  | 
| 309     } else |  | 
| 310         s -= rinc; |  | 
| 311     if( s < min_range) { |  | 
| 312         int ct = bct; |  | 
| 313         do { |  | 
| 314             assert( ~L & (1 << 31)); |  | 
| 315             L += L; |  | 
| 316             if( !--ct) { |  | 
| 317                 ct = 8; |  | 
| 318                 if( !Bend  ||  B < Bend) |  | 
| 319                     L |= *B++; |  | 
| 320             } |  | 
| 321         } while( (s += s + rinc) < min_range); |  | 
| 322         bct = ct; |  | 
| 323     } |  | 
| 324     Low = L; |  | 
| 325     Range = s; |  | 
| 326     if( bc_v) |  | 
| 327         printf( |  | 
| 328             "...done, val %d  B %x  Low %x  Range %x  bct %d\n", |  | 
| 329             val? 1:0, B-Bstart, Low, Range, bct |  | 
| 330         ); |  | 
| 331     return val; |  | 
| 332 } |  | 
| 333 |  | 
| 334 |  | 
| 335 /* C interfaces */ |  | 
| 336 |  | 
| 337 // spec interface |  | 
| 338 |  | 
| 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; |  | 
| 342     } |  | 
| 343 }; |  | 
| 344 |  | 
| 345 bool_coder_spec *vp8bc_vp6spec() { |  | 
| 346     return new bool_coder_spec_explicit_table( 0, bool_coder_namespace::Down, 8)
     ; |  | 
| 347 } |  | 
| 348 bool_coder_spec *vp8bc_float_spec( |  | 
| 349     unsigned int Ebits, unsigned int Mbits, vp8bc_c_prec *p |  | 
| 350 ) { |  | 
| 351     return new bool_coder_spec_float( Ebits, Mbits, NS::r( p), p? p->prec : 12); |  | 
| 352 } |  | 
| 353 bool_coder_spec *vp8bc_literal_spec( |  | 
| 354     const unsigned short m[256], vp8bc_c_prec *p |  | 
| 355 ) { |  | 
| 356     return new bool_coder_spec_explicit_table( m, NS::r( p), p? p->prec : 16); |  | 
| 357 } |  | 
| 358 bool_coder_spec *vp8bc_exponential_spec( unsigned int x, vp8bc_c_prec *p) |  | 
| 359 { |  | 
| 360     return new bool_coder_spec_exponential_table( x, NS::r( p), p? p->prec : 16)
     ; |  | 
| 361 } |  | 
| 362 bool_coder_spec *vp8bc_spec_from_file( FILE *fp) { |  | 
| 363     return new bool_coder_spec( fp); |  | 
| 364 } |  | 
| 365 void vp8bc_destroy_spec( c_bool_coder_spec *p) { delete p;} |  | 
| 366 |  | 
| 367 void vp8bc_spec_to_file( c_bool_coder_spec *p, FILE *fp) { p->dump( fp);} |  | 
| 368 |  | 
| 369 vp8bc_index_t vp8bc_index( c_bool_coder_spec *p, double x) { |  | 
| 370     return ( *p)( x); |  | 
| 371 } |  | 
| 372 |  | 
| 373 vp8bc_index_t vp8bc_index_from_counts( |  | 
| 374     c_bool_coder_spec *p, unsigned int L, unsigned int R |  | 
| 375 ) { |  | 
| 376     return ( *p)( (R += L)? (double) L/R : .5); |  | 
| 377 } |  | 
| 378 |  | 
| 379 double vp8bc_probability( c_bool_coder_spec *p, vp8bc_index_t i) { |  | 
| 380     return ( *p)( i); |  | 
| 381 } |  | 
| 382 |  | 
| 383 vp8bc_index_t vp8bc_complement( c_bool_coder_spec *p, vp8bc_index_t i) { |  | 
| 384     return p->complement( i); |  | 
| 385 } |  | 
| 386 unsigned int vp8bc_cost_zero( c_bool_coder_spec *p, vp8bc_index_t i) { |  | 
| 387     return p->cost_zero( i); |  | 
| 388 } |  | 
| 389 unsigned int vp8bc_cost_one( c_bool_coder_spec *p, vp8bc_index_t i) { |  | 
| 390     return p->cost_one( i); |  | 
| 391 } |  | 
| 392 unsigned int vp8bc_cost_bit( c_bool_coder_spec *p, vp8bc_index_t i, int v) { |  | 
| 393     return p->cost_bit( i, v); |  | 
| 394 } |  | 
| 395 |  | 
| 396 #if tim_vp8 |  | 
| 397     extern "C" int tok_verbose; |  | 
| 398 |  | 
| 399 #   define dbg_l 1000000 |  | 
| 400 |  | 
| 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; |  | 
| 404 #endif |  | 
| 405 |  | 
| 406 // writer interface |  | 
| 407 |  | 
| 408 bool_writer *vp8bc_create_writer( |  | 
| 409     c_bool_coder_spec *p, unsigned char *D, size_t L |  | 
| 410 ) { |  | 
| 411     return new bool_writer( *p, D, L); |  | 
| 412 } |  | 
| 413 |  | 
| 414 size_t vp8bc_destroy_writer( bool_writer *p) { |  | 
| 415     const size_t s = p->flush().bytes_written(); |  | 
| 416     delete p; |  | 
| 417     return s; |  | 
| 418 } |  | 
| 419 |  | 
| 420 void vp8bc_write_bool( bool_writer *p, int v, vp8bc_index_t i) |  | 
| 421 { |  | 
| 422 #   if tim_vp8 |  | 
| 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); |  | 
| 427 |  | 
| 428         ( *p)( i, (bool) v); |  | 
| 429 |  | 
| 430         if( dbg_w < dbg_l) { |  | 
| 431             dbg_i [dbg_w] = i; |  | 
| 432             dbg_v [dbg_w++] = v? 1:0; |  | 
| 433         } |  | 
| 434 #   else |  | 
| 435         ( *p)( i, (bool) v); |  | 
| 436 #   endif |  | 
| 437 } |  | 
| 438 |  | 
| 439 void vp8bc_write_bits( bool_writer *p, unsigned int v, int n) |  | 
| 440 { |  | 
| 441 #   if tim_vp8 |  | 
| 442         { |  | 
| 443             c_bool_coder_spec * const s = & p->Spec(); |  | 
| 444             const vp8bc_index_t i = s->half_index(); |  | 
| 445             int m = n; |  | 
| 446             while( --m >= 0) |  | 
| 447                 accum_entropy_bc( s, i, (v>>m) & 1); |  | 
| 448         } |  | 
| 449 #   endif |  | 
| 450 |  | 
| 451     p->write_bits( n, v); |  | 
| 452 } |  | 
| 453 |  | 
| 454 c_bool_coder_spec *vp8bc_writer_spec( c_bool_writer *w) { return & w->Spec();} |  | 
| 455 |  | 
| 456 // reader interface |  | 
| 457 |  | 
| 458 bool_reader *vp8bc_create_reader( |  | 
| 459     c_bool_coder_spec *p, const unsigned char *S, size_t L |  | 
| 460 ) { |  | 
| 461     return new bool_reader( *p, S, L); |  | 
| 462 } |  | 
| 463 |  | 
| 464 void vp8bc_destroy_reader( bool_reader * p) { delete p;} |  | 
| 465 |  | 
| 466 int vp8bc_read_bool( bool_reader *p, vp8bc_index_t i) |  | 
| 467 { |  | 
| 468 #   if tim_vp8 |  | 
| 469         // bc_v = dbg_r < 10; |  | 
| 470         bc_v = tok_verbose; |  | 
| 471         const int v = ( *p)( i)? 1:0; |  | 
| 472         if( tok_verbose) |  | 
| 473             printf( " reading %d at prob %d\n", v, i); |  | 
| 474         if( dbg_r < dbg_l) { |  | 
| 475             assert( dbg_r <= dbg_w); |  | 
| 476             if( i != dbg_i[dbg_r]  ||  v != dbg_v[dbg_r]) { |  | 
| 477                 printf( |  | 
| 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] |  | 
| 480                 ); |  | 
| 481             } |  | 
| 482             ++dbg_r; |  | 
| 483         } |  | 
| 484         return v; |  | 
| 485 #   else |  | 
| 486         return ( *p)( i)? 1:0; |  | 
| 487 #   endif |  | 
| 488 } |  | 
| 489 |  | 
| 490 unsigned int vp8bc_read_bits( bool_reader *p, int n) { return p->read_bits( n);} |  | 
| 491 |  | 
| 492 c_bool_coder_spec *vp8bc_reader_spec( c_bool_reader *r) { return & r->Spec();} |  | 
| 493 |  | 
| 494 #undef bc_v |  | 
| OLD | NEW | 
|---|