Skip to content

Commit 3cd2829

Browse files
committed
Update with table-less version.
1 parent f9b7d9b commit 3cd2829

3 files changed

Lines changed: 41 additions & 7 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ Also, the code is very small, about 768 bytes each for reading and writing when
3838
.text 0016 (22 bytes) vpx_reader_has_error
3939
```
4040

41+
If you are on a platform that supports `__builtin_clz`, then you may want to define `VPXCODING_NOTABLE` as that will replace the table call with a `clz` and `andi` operation, which may be faster, and use less cache/RAM. If you are on a RAM constrained system, you may want to do this as well, but see the note in the header file about the manually unwound log2.
42+
4143
In my tests, depending on the application, this seems to be able to save between 1-5% over huffman trees. But, notably, there are situations where you can use this to much greater effect and simplicity than huffman trees (but not all situations).
4244

4345
## Example

bittester.c

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#define VPXCODING_READER
66
#define VPXCODING_WRITER
7+
#define VPXCODING_NOTABLE
78
#include "vpxcoding.h"
89

910
double GetAbsoluteTime()
@@ -14,9 +15,21 @@ double GetAbsoluteTime()
1415
}
1516

1617
uint8_t dummydata[1024*1024*16];
18+
uint8_t dummyprobs[1024*1024*16*8];
1719
int main( int argc, char ** argv )
1820
{
1921
int i;
22+
#if 0
23+
for( i = 0; i < 256; i++ )
24+
{
25+
printf( "%2d", VPXCODING_VPXNORM( i ) );
26+
if( ( i & 15 ) == 15 )
27+
{
28+
printf( "\n" );
29+
}
30+
}
31+
return 0;
32+
#endif
2033
for( i = 0; i < sizeof(dummydata); i++ )
2134
{
2235
//dummydata[i] = rand();
@@ -27,18 +40,18 @@ int main( int argc, char ** argv )
2740
uint8_t * bufferO = malloc(sizeof(dummydata)*20);
2841
vpx_start_encode( &w, bufferO, sizeof(dummydata)*20);
2942

30-
const int arbitrary_prob = 187;
31-
3243
double startEnc = GetAbsoluteTime();
44+
int bitno = 0;
3345
for( i = 0; i < sizeof(dummydata); i++ )
3446
{
3547
int data = dummydata[i];
3648
int bits = 8;
3749
int bit;
3850
for (bit = bits - 1; bit >= 0; bit--)
3951
{
52+
int prob = dummyprobs[bitno++] = rand()&0xff;
4053
int outbit = (data >> bit) & 1;
41-
vpx_write(&w, outbit, arbitrary_prob);
54+
vpx_write(&w, outbit, prob);
4255
}
4356
}
4457
vpx_stop_encode(&w);
@@ -56,13 +69,14 @@ int main( int argc, char ** argv )
5669
vpx_reader reader;
5770
int ret = vpx_reader_init(&reader, bufferO, w.pos, 0, 0 );
5871
double startDec = GetAbsoluteTime();
72+
bitno = 0;
5973
for( i = 0; i < sizeof(dummydata); i++ )
6074
{
6175
int bits = 8;
6276
int bit;
6377
uint8_t data = 0;
6478
for (bit = bits - 1; bit >= 0; bit--)// Arbitrary, for testing
65-
data = (data<<1) | vpx_read(&reader, arbitrary_prob);
79+
data = (data<<1) | vpx_read(&reader, dummyprobs[bitno++]);
6680
if( data != dummydata[i] )
6781
{
6882
fprintf( stderr, "Disagree at %d (%08x != %08x)\n", i, data, dummydata[i] );

vpxcoding.h

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,23 @@ extern "C" {
4444
#define VPXCODING_IMPLEMENTATION
4545
#endif
4646

47-
47+
#ifdef VPXCODING_NOTABLE
48+
VPXCODING_DECORATOR uint8_t vpx_norm( uint8_t n )
49+
{
50+
return __builtin_clz(n) & 7;
51+
#if 0
52+
// Implementation for systems w/o clz.
53+
if( n == 0 ) return 0; // I don't think this is needed
54+
int i = 7;
55+
if( n >= 16 ) { i -= 4; n >>= 4; }
56+
if( n >= 8 ) { i -= 3; n >>= 3; }
57+
if( n >= 4 ) { i -= 2; n >>= 2; }
58+
if( n >= 2 ) { i -= 1; n >>= 1; }
59+
return i;
60+
#endif
61+
}
62+
#define VPXCODING_VPXNORM(x) vpx_norm(x)
63+
#else
4864
static const uint8_t vpx_norm[256] = {
4965
0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
5066
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
@@ -64,6 +80,8 @@ static const uint8_t vpx_norm[256] = {
6480
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
6581
};
6682

83+
#define VPXCODING_VPXNORM( x ) vpx_norm[x]
84+
#endif
6785
#ifdef VPXCODING_READER
6886

6987
// This is meant to be a large, positive constant that can still be
@@ -262,7 +280,7 @@ VPXCODING_DECORATOR int vpx_read(vpx_reader *r, int prob) {
262280
}
263281

264282
{
265-
const unsigned char shift = vpx_norm[(unsigned char)range];
283+
const unsigned char shift = VPXCODING_VPXNORM((unsigned char)range);
266284
range <<= shift;
267285
value <<= shift;
268286
count -= shift;
@@ -367,7 +385,7 @@ VPXCODING_DECORATOR VPX_NO_UNSIGNED_SHIFT_CHECK void vpx_write(vpx_writer *br,
367385
range = br->range - split;
368386
}
369387

370-
shift = vpx_norm[range];
388+
shift = VPXCODING_VPXNORM(range);
371389

372390
range <<= shift;
373391
count += shift;

0 commit comments

Comments
 (0)