| 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 |