From 617d013f95cc0767aa17f50088f5b66b7741ba65 Mon Sep 17 00:00:00 2001 From: Monty Date: Sun, 15 Sep 2002 23:48:03 +0000 Subject: Add bigendian bitpacker to libogg (that is, a packer that packs MSbit first into bit position 7, rtaher than LSb first into bit position 0, ala Vorbis I). VP3 needs it, as will other future Ogg codecs. Might as well add it now. Monty git-svn-id: http://svn.xiph.org/trunk/ogg@3911 0101bb08-14d6-0310-b084-bc0e0c8e3800 --- src/bitwise.c | 437 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 381 insertions(+), 56 deletions(-) (limited to 'src') diff --git a/src/bitwise.c b/src/bitwise.c index dae686a..0a5dc87 100644 --- a/src/bitwise.c +++ b/src/bitwise.c @@ -11,7 +11,7 @@ ******************************************************************** function: packing variable sized words into an octet stream - last mod: $Id: bitwise.c,v 1.13 2002/07/11 09:09:08 xiphmont Exp $ + last mod: $Id: bitwise.c,v 1.14 2002/09/15 23:48:03 xiphmont Exp $ ********************************************************************/ @@ -33,6 +33,9 @@ static unsigned long mask[]= 0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff, 0x3fffffff,0x7fffffff,0xffffffff }; +static unsigned int mask8B[]= +{0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe0,0xff}; + void oggpack_writeinit(oggpack_buffer *b){ memset(b,0,sizeof(*b)); b->ptr=b->buffer=_ogg_malloc(BUFFER_INCREMENT); @@ -40,13 +43,94 @@ void oggpack_writeinit(oggpack_buffer *b){ b->storage=BUFFER_INCREMENT; } +void oggpackB_writeinit(oggpack_buffer *b){ + oggpack_writeinit(b); +} + void oggpack_writetrunc(oggpack_buffer *b,long bits){ long bytes=bits>>3; bits-=bytes*8; b->ptr=b->buffer+bytes; b->endbit=bits; b->endbyte=bytes; - *b->ptr|=mask[bits]; + *b->ptr&=mask[bits]; +} + +void oggpackB_writetrunc(oggpack_buffer *b,long bits){ + long bytes=bits>>3; + bits-=bytes*8; + b->ptr=b->buffer+bytes; + b->endbit=bits; + b->endbyte=bytes; + *b->ptr&=mask8B[bits]; +} + +/* Takes only up to 32 bits. */ +void oggpack_write(oggpack_buffer *b,unsigned long value,int bits){ + if(b->endbyte+4>=b->storage){ + b->buffer=_ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT); + b->storage+=BUFFER_INCREMENT; + b->ptr=b->buffer+b->endbyte; + } + + value&=mask[bits]; + bits+=b->endbit; + + b->ptr[0]|=value<endbit; + + if(bits>=8){ + b->ptr[1]=value>>(8-b->endbit); + if(bits>=16){ + b->ptr[2]=value>>(16-b->endbit); + if(bits>=24){ + b->ptr[3]=value>>(24-b->endbit); + if(bits>=32){ + if(b->endbit) + b->ptr[4]=value>>(32-b->endbit); + else + b->ptr[4]=0; + } + } + } + } + + b->endbyte+=bits/8; + b->ptr+=bits/8; + b->endbit=bits&7; +} + +/* Takes only up to 32 bits. */ +void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits){ + if(b->endbyte+4>=b->storage){ + b->buffer=_ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT); + b->storage+=BUFFER_INCREMENT; + b->ptr=b->buffer+b->endbyte; + } + + value=(value&mask[bits])<<(32-bits); + bits+=b->endbit; + + b->ptr[0]|=value>>(24+b->endbit); + + if(bits>=8){ + b->ptr[1]=value>>(16+b->endbit); + if(bits>=16){ + b->ptr[2]=value>>(8+b->endbit); + if(bits>=24){ + b->ptr[3]=value>>(b->endbit); + if(bits>=32){ + if(b->endbit) + b->ptr[4]=value<<(8-b->endbit); + else + b->ptr[4]=0; + } + } + } + } + + b->endbyte+=bits/8; + b->ptr+=bits/8; + b->endbit=bits&7; } void oggpack_writealign(oggpack_buffer *b){ @@ -55,7 +139,18 @@ void oggpack_writealign(oggpack_buffer *b){ oggpack_write(b,0,bits); } -void oggpack_writecopy(oggpack_buffer *b,void *source,long bits){ +void oggpackB_writealign(oggpack_buffer *b){ + int bits=8-b->endbit; + if(bits<8) + oggpackB_write(b,0,bits); +} + +static void oggpack_writecopy_helper(oggpack_buffer *b, + void *source, + long bits, + void (*w)(oggpack_buffer *, + unsigned long, + int)){ unsigned char *ptr=(unsigned char *)source; long bytes=bits/8; @@ -65,7 +160,7 @@ void oggpack_writecopy(oggpack_buffer *b,void *source,long bits){ int i; /* unaligned copy. Do it the hard way. */ for(i=0;iendbyte+bytes+1>=b->storage){ @@ -81,7 +176,15 @@ void oggpack_writecopy(oggpack_buffer *b,void *source,long bits){ } if(bits) - oggpack_write(b,(long)(ptr[bytes]),bits); + w(b,(unsigned long)(ptr[bytes]),bits); +} + +void oggpack_writecopy(oggpack_buffer *b,void *source,long bits){ + oggpack_writecopy_helper(b,source,bits,oggpack_write); +} + +void oggpackB_writecopy(oggpack_buffer *b,void *source,long bits){ + oggpack_writecopy_helper(b,source,bits,oggpackB_write); } void oggpack_reset(oggpack_buffer *b){ @@ -90,49 +193,27 @@ void oggpack_reset(oggpack_buffer *b){ b->endbit=b->endbyte=0; } +void oggpackB_reset(oggpack_buffer *b){ + oggpack_reset(b); +} + void oggpack_writeclear(oggpack_buffer *b){ _ogg_free(b->buffer); memset(b,0,sizeof(*b)); } +void oggpackB_writeclear(oggpack_buffer *b){ + oggpack_writeclear(b); +} + void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes){ memset(b,0,sizeof(*b)); b->buffer=b->ptr=buf; b->storage=bytes; } -/* Takes only up to 32 bits. */ -void oggpack_write(oggpack_buffer *b,unsigned long value,int bits){ - if(b->endbyte+4>=b->storage){ - b->buffer=_ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT); - b->storage+=BUFFER_INCREMENT; - b->ptr=b->buffer+b->endbyte; - } - - value&=mask[bits]; - bits+=b->endbit; - - b->ptr[0]|=value<endbit; - - if(bits>=8){ - b->ptr[1]=value>>(8-b->endbit); - if(bits>=16){ - b->ptr[2]=value>>(16-b->endbit); - if(bits>=24){ - b->ptr[3]=value>>(24-b->endbit); - if(bits>=32){ - if(b->endbit) - b->ptr[4]=value>>(32-b->endbit); - else - b->ptr[4]=0; - } - } - } - } - - b->endbyte+=bits/8; - b->ptr+=bits/8; - b->endbit=bits&7; +void oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes){ + oggpack_readinit(b,buf,bytes); } /* Read in bits without advancing the bitptr; bits <= 32 */ @@ -162,11 +243,43 @@ long oggpack_look(oggpack_buffer *b,int bits){ return(m&ret); } +/* Read in bits without advancing the bitptr; bits <= 32 */ +long oggpackB_look(oggpack_buffer *b,int bits){ + unsigned long ret; + int m=32-bits; + + bits+=b->endbit; + + if(b->endbyte+4>=b->storage){ + /* not the main path */ + if(b->endbyte*8+bits>b->storage*8)return(-1); + } + + ret=b->ptr[0]<<(24+b->endbit); + if(bits>8){ + ret|=b->ptr[1]<<(16+b->endbit); + if(bits>16){ + ret|=b->ptr[2]<<(8+b->endbit); + if(bits>24){ + ret|=b->ptr[3]<<(b->endbit); + if(bits>32 && b->endbit) + ret|=b->ptr[4]>>(8-b->endbit); + } + } + } + return(ret>>m); +} + long oggpack_look1(oggpack_buffer *b){ if(b->endbyte>=b->storage)return(-1); return((b->ptr[0]>>b->endbit)&1); } +long oggpackB_look1(oggpack_buffer *b){ + if(b->endbyte>=b->storage)return(-1); + return((b->ptr[0]>>(7-b->endbit))&1); +} + void oggpack_adv(oggpack_buffer *b,int bits){ bits+=b->endbit; b->ptr+=bits/8; @@ -174,6 +287,10 @@ void oggpack_adv(oggpack_buffer *b,int bits){ b->endbit=bits&7; } +void oggpackB_adv(oggpack_buffer *b,int bits){ + oggpack_adv(b,bits); +} + void oggpack_adv1(oggpack_buffer *b){ if(++(b->endbit)>7){ b->endbit=0; @@ -182,6 +299,10 @@ void oggpack_adv1(oggpack_buffer *b){ } } +void oggpackB_adv1(oggpack_buffer *b){ + oggpack_adv1(b); +} + /* bits <= 32 */ long oggpack_read(oggpack_buffer *b,int bits){ unsigned long ret; @@ -218,6 +339,41 @@ long oggpack_read(oggpack_buffer *b,int bits){ return(ret); } +/* bits <= 32 */ +long oggpackB_read(oggpack_buffer *b,int bits){ + unsigned long ret; + long m=32-bits; + + bits+=b->endbit; + + if(b->endbyte+4>=b->storage){ + /* not the main path */ + ret=-1UL; + if(b->endbyte*8+bits>b->storage*8)goto overflow; + } + + ret=b->ptr[0]<<(24+b->endbit); + if(bits>8){ + ret|=b->ptr[1]<<(16+b->endbit); + if(bits>16){ + ret|=b->ptr[2]<<(8+b->endbit); + if(bits>24){ + ret|=b->ptr[3]<<(b->endbit); + if(bits>32 && b->endbit) + ret|=b->ptr[4]>>(8-b->endbit); + } + } + } + ret>>=m; + + overflow: + + b->ptr+=bits/8; + b->endbyte+=bits/8; + b->endbit=bits&7; + return(ret); +} + long oggpack_read1(oggpack_buffer *b){ unsigned long ret; @@ -240,6 +396,28 @@ long oggpack_read1(oggpack_buffer *b){ return(ret); } +long oggpackB_read1(oggpack_buffer *b){ + unsigned long ret; + + if(b->endbyte>=b->storage){ + /* not the main path */ + ret=-1UL; + goto overflow; + } + + ret=(b->ptr[0]>>(7-b->endbit))&1; + + overflow: + + b->endbit++; + if(b->endbit>7){ + b->endbit=0; + b->ptr++; + b->endbyte++; + } + return(ret); +} + long oggpack_bytes(oggpack_buffer *b){ return(b->endbyte+(b->endbit+7)/8); } @@ -248,10 +426,22 @@ long oggpack_bits(oggpack_buffer *b){ return(b->endbyte*8+b->endbit); } +long oggpackB_bytes(oggpack_buffer *b){ + return oggpack_bytes(b); +} + +long oggpackB_bits(oggpack_buffer *b){ + return oggpack_bits(b); +} + unsigned char *oggpack_get_buffer(oggpack_buffer *b){ return(b->buffer); } +unsigned char *oggpackB_get_buffer(oggpack_buffer *b){ + return oggpack_get_buffer(b); +} + /* Self test of the bitwise routines; everything else is based on them, so they damned well better be solid. */ @@ -310,6 +500,41 @@ void cliptest(unsigned long *b,int vals,int bits,int *comp,int compsize){ if(oggpack_bytes(&r)!=bytes)report("leftover bytes after read!\n"); } +void cliptestB(unsigned long *b,int vals,int bits,int *comp,int compsize){ + long bytes,i; + unsigned char *buffer; + + oggpackB_reset(&o); + for(i=0;i