From 67efbc13870ee87ce3df442f7c396c13481921ec Mon Sep 17 00:00:00 2001 From: Nils Wallménius Date: Mon, 6 Dec 2010 14:36:52 +0000 Subject: libtremor: Merge in upstream revision 17375. This removes tremor's internal ogg code and now uses libogg instead so a bunch of changes are just adjusting to the new api. Also brings in improvements to vorbisfile which fixes FS#10484. Disabled a lot of unused code in the libogg files and moved some small functions into the ogg.h header so they can be inlined. Some small tweaks to fix warnings. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28742 a1c6a512-1295-4272-9138-f99709370657 --- apps/codecs/libtremor/bitwise.c | 949 +++++++++++++++++++++++++++++++++------- 1 file changed, 800 insertions(+), 149 deletions(-) (limited to 'apps/codecs/libtremor/bitwise.c') diff --git a/apps/codecs/libtremor/bitwise.c b/apps/codecs/libtremor/bitwise.c index dabba468b9..050fb67c60 100644 --- a/apps/codecs/libtremor/bitwise.c +++ b/apps/codecs/libtremor/bitwise.c @@ -1,28 +1,31 @@ /******************************************************************** * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * - * * + * THIS FILE IS PART OF THE Ogg CONTAINER SOURCE CODE. * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * - * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2010 * + * by the Xiph.Org Foundation http://www.xiph.org/ * * * ******************************************************************** function: packing variable sized words into an octet stream + last mod: $Id$ ********************************************************************/ /* We're 'LSb' endian; if we write a word but read individual bits, then we'll read the lsb first */ -#include "config-tremor.h" #include +#include +#include #include "ogg.h" -const unsigned long oggpack_mask[] ICONST_ATTR = +#define BUFFER_INCREMENT 256 + +const unsigned long mask[] ICONST_ATTR = {0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f, 0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff, 0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff, @@ -31,184 +34,832 @@ const unsigned long oggpack_mask[] ICONST_ATTR = 0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff, 0x3fffffff,0x7fffffff,0xffffffff }; -void oggpack_readinit(oggpack_buffer *b,ogg_reference *r){ +#if 0 +static const unsigned int mask8B[]= +{0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff}; + +void oggpack_writeinit(oggpack_buffer *b){ memset(b,0,sizeof(*b)); + b->ptr=b->buffer=_ogg_malloc(BUFFER_INCREMENT); + b->buffer[0]='\0'; + b->storage=BUFFER_INCREMENT; +} + +void oggpackB_writeinit(oggpack_buffer *b){ + oggpack_writeinit(b); +} - b->tail=b->head=r; - b->count=0; - b->headptr=b->head->buffer->data+b->head->begin; - b->headend=b->head->length; - _span(b); +int oggpack_writecheck(oggpack_buffer *b){ + if(!b->ptr || !b->storage)return -1; + return 0; } -#define _lookspan() while(!end){\ - head=head->next;\ - if(!head) return -1;\ - ptr=head->buffer->data + head->begin;\ - end=head->length;\ - } +int oggpackB_writecheck(oggpack_buffer *b){ + return oggpack_writecheck(b); +} -/* Read in bits without advancing the bitptr; bits <= 32 */ -long oggpack_look_full(oggpack_buffer *b,int bits) ICODE_ATTR_TREMOR_NOT_MDCT; -long oggpack_look_full(oggpack_buffer *b,int bits){ - unsigned long m=oggpack_mask[bits]; - unsigned long ret=-1; - - bits+=b->headbit; - - if(bits >= b->headend<<3){ - int end=b->headend; - unsigned char *ptr=b->headptr; - ogg_reference *head=b->head; - - if(end<0)return -1; - - if(bits){ - _lookspan(); - ret=*ptr++>>b->headbit; - if(bits>8){ - --end; - _lookspan(); - ret|=*ptr++<<(8-b->headbit); - if(bits>16){ - --end; - _lookspan(); - ret|=*ptr++<<(16-b->headbit); - if(bits>24){ - --end; - _lookspan(); - ret|=*ptr++<<(24-b->headbit); - if(bits>32 && b->headbit){ - --end; - _lookspan(); - ret|=*ptr<<(32-b->headbit); - } - } +void oggpack_writetrunc(oggpack_buffer *b,long bits){ + long bytes=bits>>3; + if(b->ptr){ + bits-=bytes*8; + b->ptr=b->buffer+bytes; + b->endbit=bits; + b->endbyte=bytes; + *b->ptr&=mask[bits]; + } +} + +void oggpackB_writetrunc(oggpack_buffer *b,long bits){ + long bytes=bits>>3; + if(b->ptr){ + 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(bits<0 || bits>32) goto err; + if(b->endbyte>=b->storage-4){ + void *ret; + if(!b->ptr)return; + if(b->storage>LONG_MAX-BUFFER_INCREMENT) goto err; + ret=_ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT); + if(!ret) goto err; + b->buffer=ret; + 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]=(unsigned char)(value>>(8-b->endbit)); + if(bits>=16){ + b->ptr[2]=(unsigned char)(value>>(16-b->endbit)); + if(bits>=24){ + b->ptr[3]=(unsigned char)(value>>(24-b->endbit)); + if(bits>=32){ + if(b->endbit) + b->ptr[4]=(unsigned char)(value>>(32-b->endbit)); + else + b->ptr[4]=0; } } } + } - }else{ + b->endbyte+=bits/8; + b->ptr+=bits/8; + b->endbit=bits&7; + return; + err: + oggpack_writeclear(b); +} + +/* Takes only up to 32 bits. */ +void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits){ + if(bits<0 || bits>32) goto err; + if(b->endbyte>=b->storage-4){ + void *ret; + if(!b->ptr)return; + if(b->storage>LONG_MAX-BUFFER_INCREMENT) goto err; + ret=_ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT); + if(!ret) goto err; + b->buffer=ret; + b->storage+=BUFFER_INCREMENT; + b->ptr=b->buffer+b->endbyte; + } + + value=(value&mask[bits])<<(32-bits); + bits+=b->endbit; - /* make this a switch jump-table */ - ret=b->headptr[0]>>b->headbit; - if(bits>8){ - ret|=b->headptr[1]<<(8-b->headbit); - if(bits>16){ - ret|=b->headptr[2]<<(16-b->headbit); - if(bits>24){ - ret|=b->headptr[3]<<(24-b->headbit); - if(bits>32 && b->headbit) - ret|=b->headptr[4]<<(32-b->headbit); + b->ptr[0]|=value>>(24+b->endbit); + + if(bits>=8){ + b->ptr[1]=(unsigned char)(value>>(16+b->endbit)); + if(bits>=16){ + b->ptr[2]=(unsigned char)(value>>(8+b->endbit)); + if(bits>=24){ + b->ptr[3]=(unsigned char)(value>>(b->endbit)); + if(bits>=32){ + if(b->endbit) + b->ptr[4]=(unsigned char)(value<<(8-b->endbit)); + else + b->ptr[4]=0; } } } } - ret&=m; - return ret; + b->endbyte+=bits/8; + b->ptr+=bits/8; + b->endbit=bits&7; + return; + err: + oggpack_writeclear(b); +} + +void oggpack_writealign(oggpack_buffer *b){ + int bits=8-b->endbit; + if(bits<8) + oggpack_write(b,0,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), + int msb){ + unsigned char *ptr=(unsigned char *)source; + + long bytes=bits/8; + bits-=bytes*8; + + if(b->endbit){ + int i; + /* unaligned copy. Do it the hard way. */ + for(i=0;iendbyte+bytes+1>=b->storage){ + void *ret; + if(!b->ptr) goto err; + if(b->endbyte+bytes+BUFFER_INCREMENT>b->storage) goto err; + b->storage=b->endbyte+bytes+BUFFER_INCREMENT; + ret=_ogg_realloc(b->buffer,b->storage); + if(!ret) goto err; + b->buffer=ret; + b->ptr=b->buffer+b->endbyte; + } + + memmove(b->ptr,source,bytes); + b->ptr+=bytes; + b->endbyte+=bytes; + *b->ptr=0; + + } + if(bits){ + if(msb) + w(b,(unsigned long)(ptr[bytes]>>(8-bits)),bits); + else + w(b,(unsigned long)(ptr[bytes]),bits); + } + return; + err: + oggpack_writeclear(b); +} + +void oggpack_writecopy(oggpack_buffer *b,void *source,long bits){ + oggpack_writecopy_helper(b,source,bits,oggpack_write,0); +} + +void oggpackB_writecopy(oggpack_buffer *b,void *source,long bits){ + oggpack_writecopy_helper(b,source,bits,oggpackB_write,1); +} + +void oggpack_reset(oggpack_buffer *b){ + if(!b->ptr)return; + b->ptr=b->buffer; + b->buffer[0]=0; + b->endbit=b->endbyte=0; +} + +void oggpackB_reset(oggpack_buffer *b){ + oggpack_reset(b); +} + +void oggpack_writeclear(oggpack_buffer *b){ + if(b->buffer)_ogg_free(b->buffer); + memset(b,0,sizeof(*b)); +} + +void oggpackB_writeclear(oggpack_buffer *b){ + oggpack_writeclear(b); } +#endif +void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes){ + memset(b,0,sizeof(*b)); + b->buffer=b->ptr=buf; + b->storage=bytes; +} +#if 0 +void oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes){ + oggpack_readinit(b,buf,bytes); +} +#endif +/* Read in bits without advancing the bitptr; bits <= 32 */ +/* moved to ogg.h for inlining */ +#if 0 +long oggpack_look(oggpack_buffer *b,int bits){ + unsigned long ret; + unsigned long m; + + if(bits<0 || bits>32) return -1; + m=mask[bits]; + bits+=b->endbit; + + if(b->endbyte >= b->storage-4){ + /* not the main path */ + if(b->endbyte > b->storage-((bits+7)>>3)) return -1; + /* special case to avoid reading b->ptr[0], which might be past the end of + the buffer; also skips some useless accounting */ + else if(!bits)return(0L); + } -/* spans forward and finds next byte. Never halts */ -static void _span_one(oggpack_buffer *b){ - while(b->headend<1){ - if(b->head->next){ - b->count+=b->head->length; - b->head=b->head->next; - b->headptr=b->head->buffer->data+b->head->begin; - b->headend=b->head->length; - }else - break; + ret=b->ptr[0]>>b->endbit; + if(bits>8){ + ret|=b->ptr[1]<<(8-b->endbit); + if(bits>16){ + ret|=b->ptr[2]<<(16-b->endbit); + if(bits>24){ + ret|=b->ptr[3]<<(24-b->endbit); + if(bits>32 && b->endbit) + ret|=b->ptr[4]<<(32-b->endbit); + } + } } + return(m&ret); } +#endif + +#if 0 +/* Read in bits without advancing the bitptr; bits <= 32 */ +long oggpackB_look(oggpack_buffer *b,int bits){ + unsigned long ret; + int m=32-bits; + + if(m<0 || m>32) return -1; + bits+=b->endbit; -static int _halt_one(oggpack_buffer *b){ - if(b->headend<1){ - _adv_halt(b); - return -1; + if(b->endbyte >= b->storage-4){ + /* not the main path */ + if(b->endbyte > b->storage-((bits+7)>>3)) return -1; + /* special case to avoid reading b->ptr[0], which might be past the end of + the buffer; also skips some useless accounting */ + else if(!bits)return(0L); } - return 0; + + 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&0xffffffff)>>(m>>1))>>((m+1)>>1); +} +#endif +long oggpack_look1(oggpack_buffer *b){ + if(b->endbyte>=b->storage)return(-1); + return((b->ptr[0]>>b->endbit)&1); } +#if 0 +long oggpackB_look1(oggpack_buffer *b){ + if(b->endbyte>=b->storage)return(-1); + return((b->ptr[0]>>(7-b->endbit))&1); +} +#endif +/* moved to ogg.h for inlining +void oggpack_adv(oggpack_buffer *b,int bits){ + bits+=b->endbit; + + if(b->endbyte > b->storage-((bits+7)>>3)) goto overflow; + + b->ptr+=bits/8; + b->endbyte+=bits/8; + b->endbit=bits&7; + return; + overflow: + b->ptr=NULL; + b->endbyte=b->storage; + b->endbit=1; +} +*/ +#if 0 +void oggpackB_adv(oggpack_buffer *b,int bits){ + oggpack_adv(b,bits); +} +#endif +void oggpack_adv1(oggpack_buffer *b){ + if(++(b->endbit)>7){ + b->endbit=0; + b->ptr++; + b->endbyte++; + } +} +#if 0 +void oggpackB_adv1(oggpack_buffer *b){ + oggpack_adv1(b); +} +#endif /* bits <= 32 */ -long oggpack_read(oggpack_buffer *b,register int bits) ICODE_ATTR_TREMOR_NOT_MDCT; -long oggpack_read(oggpack_buffer *b,register int bits){ - unsigned long m=oggpack_mask[bits]; - ogg_uint32_t ret=-1; +long oggpack_read(oggpack_buffer *b,int bits) ICODE_ATTR_TREMOR_NOT_MDCT; +long oggpack_read(oggpack_buffer *b,int bits){ + long ret; + unsigned long m; - bits+=b->headbit; + if(bits<0 || bits>32) goto err; + m=mask[bits]; + bits+=b->endbit; - if(bits >= b->headend<<3){ + if(b->endbyte >= b->storage-4){ + /* not the main path */ + if(b->endbyte > b->storage-((bits+7)>>3)) goto overflow; + /* special case to avoid reading b->ptr[0], which might be past the end of + the buffer; also skips some useless accounting */ + else if(!bits)return(0L); + } - if(b->headend<0)return -1; - - if(bits){ - if (_halt_one(b)) return -1; - ret=*b->headptr>>b->headbit; - - if(bits>=8){ - ++b->headptr; - --b->headend; - _span_one(b); - if(bits>8){ - if (_halt_one(b)) return -1; - ret|=*b->headptr<<(8-b->headbit); - - if(bits>=16){ - ++b->headptr; - --b->headend; - _span_one(b); - if(bits>16){ - if (_halt_one(b)) return -1; - ret|=*b->headptr<<(16-b->headbit); - - if(bits>=24){ - ++b->headptr; - --b->headend; - _span_one(b); - if(bits>24){ - if (_halt_one(b)) return -1; - ret|=*b->headptr<<(24-b->headbit); - - if(bits>=32){ - ++b->headptr; - --b->headend; - _span_one(b); - if(bits>32){ - if (_halt_one(b)) return -1; - if(b->headbit)ret|=*b->headptr<<(32-b->headbit); - - } - } - } - } - } - } + ret=b->ptr[0]>>b->endbit; + if(bits>8){ + ret|=b->ptr[1]<<(8-b->endbit); + if(bits>16){ + ret|=b->ptr[2]<<(16-b->endbit); + if(bits>24){ + ret|=b->ptr[3]<<(24-b->endbit); + if(bits>32 && b->endbit){ + ret|=b->ptr[4]<<(32-b->endbit); } } } - }else{ + } + ret&=m; + b->ptr+=bits/8; + b->endbyte+=bits/8; + b->endbit=bits&7; + return ret; - ret=b->headptr[0]>>b->headbit; - if(bits>8){ - ret|=b->headptr[1]<<(8-b->headbit); - if(bits>16){ - ret|=b->headptr[2]<<(16-b->headbit); - if(bits>24){ - ret|=b->headptr[3]<<(24-b->headbit); - if(bits>32 && b->headbit){ - ret|=b->headptr[4]<<(32-b->headbit); - } - } + overflow: + err: + b->ptr=NULL; + b->endbyte=b->storage; + b->endbit=1; + return -1L; +} +#if 0 +/* bits <= 32 */ +long oggpackB_read(oggpack_buffer *b,int bits){ + long ret; + long m=32-bits; + + if(m<0 || m>32) goto err; + bits+=b->endbit; + + if(b->endbyte+4>=b->storage){ + /* not the main path */ + if(b->endbyte > b->storage-((bits+7)>>3)) goto overflow; + /* special case to avoid reading b->ptr[0], which might be past the end of + the buffer; also skips some useless accounting */ + else if(!bits)return(0L); + } + + 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); } } - - b->headptr+=((unsigned)bits)/8; - b->headend-=((unsigned)bits)/8; } + ret=((ret&0xffffffffUL)>>(m>>1))>>((m+1)>>1); - ret&=m; - b->headbit=bits&7; + b->ptr+=bits/8; + b->endbyte+=bits/8; + b->endbit=bits&7; return ret; + + overflow: + err: + b->ptr=NULL; + b->endbyte=b->storage; + b->endbit=1; + return -1L; } +#endif +long oggpack_read1(oggpack_buffer *b){ + long ret; + + if(b->endbyte >= b->storage) goto overflow; + ret=(b->ptr[0]>>b->endbit)&1; + + b->endbit++; + if(b->endbit>7){ + b->endbit=0; + b->ptr++; + b->endbyte++; + } + return ret; + + overflow: + b->ptr=NULL; + b->endbyte=b->storage; + b->endbit=1; + return -1L; +} +#if 0 +long oggpackB_read1(oggpack_buffer *b){ + long ret; + + if(b->endbyte >= b->storage) goto overflow; + ret=(b->ptr[0]>>(7-b->endbit))&1; + + b->endbit++; + if(b->endbit>7){ + b->endbit=0; + b->ptr++; + b->endbyte++; + } + return ret; + + overflow: + b->ptr=NULL; + b->endbyte=b->storage; + b->endbit=1; + return -1L; +} + +long oggpack_bytes(oggpack_buffer *b){ + return(b->endbyte+(b->endbit+7)/8); +} + +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); +} +#endif +/* Self test of the bitwise routines; everything else is based on + them, so they damned well better be solid. */ + +#ifdef _V_SELFTEST +#include + +static int ilog(unsigned int v){ + int ret=0; + while(v){ + ret++; + v>>=1; + } + return(ret); +} + +oggpack_buffer o; +oggpack_buffer r; + +void report(char *in){ + fprintf(stderr,"%s",in); + exit(1); +} + +void cliptest(unsigned long *b,int vals,int bits,int *comp,int compsize){ + long bytes,i; + unsigned char *buffer; + + oggpack_reset(&o); + for(i=0;i