Index: apps/codecs/libtremor/codebook.c =================================================================== --- apps/codecs/libtremor/codebook.c (revision 20567) +++ apps/codecs/libtremor/codebook.c (working copy) @@ -199,78 +199,6 @@ return(-1); } -static long decode_packed_block(codebook *book, oggpack_buffer *b, - long *buf, int n){ - long *bufptr = buf; - long *bufend = buf + n; - - while (bufptrheadend > 8) { - ogg_uint32_t *ptr; - unsigned long bit, bitend; - unsigned long adr; - ogg_uint32_t cache = 0; - int cachesize = 0; - - adr = (unsigned long)b->headptr; - bit = (adr&3)*8+b->headbit; - ptr = (ogg_uint32_t *)(adr&~3); - bitend = ((adr&3)+b->headend)*8; - while (bufptrdec_maxlength)) { - if (bit-cachesize+32>=bitend) - break; - bit-=cachesize; - cache=letoh32(ptr[bit>>5]) >> (bit&31); - if (bit&31) - cache|=letoh32(ptr[(bit>>5)+1]) << (32-(bit&31)); - cachesize=32; - bit+=32; - } - - entry=book->dec_firsttable[cache&((1<dec_firsttablen)-1)]; - if(UNLIKELY(entry&0x80000000UL)){ - lo=(entry>>15)&0x7fff; - hi=book->used_entries-(entry&0x7fff); - { - ogg_uint32_t testword=bitreverse((ogg_uint32_t)cache); - - while(LIKELY(hi-lo>1)){ - long p=(hi-lo)>>1; - if (book->codelist[lo+p]>testword) - hi-=p; - else - lo+=p; - } - entry=lo; - } - }else - entry--; - - *bufptr++=entry; - { - int l=book->dec_codelengths[entry]; - cachesize-=l; - cache>>=l; - } - } - - adr=(unsigned long)b->headptr; - bit-=(adr&3)*8+cachesize; - b->headend-=(bit/8); - b->headptr+=bit/8; - b->headbit=bit%8; - } else { - long r = decode_packed_entry_number(book, b); - if (r == -1) return bufptr-buf; - *bufptr++ = r; - } - } - return n; -} - - /* Decode side is specced and easier, because we don't need to find matches using different criteria; we simply read and map. There are two things we need to do 'depending': @@ -399,76 +327,24 @@ return(0); } -static long vorbis_book_decodevv_add_2ch_even(codebook *book,ogg_int32_t **a, - long offset,oggpack_buffer *b, - int n,int point){ - long i,k,chunk,read; - int shift=point-book->binarypoint; - long entries[32]; - ogg_int32_t *p0 = &(a[0][offset]); - ogg_int32_t *p1 = &(a[1][offset]); - - if(shift>=0){ - - for(i=0;idim>(n-i)*2) - chunk=((n-i)*2+book->dim-1)/book->dim; - read = decode_packed_block(book,b,entries,chunk); - for(k=0;kvaluelist+entries[k]*book->dim; - const ogg_int32_t *u = t+book->dim; - do{ - *p0++ += *t++>>shift; - *p1++ += *t++>>shift; - }while(tdim/2; - } - }else{ - shift = -shift; - for(i=0;idim>(n-i)*2) - chunk=((n-i)*2+book->dim-1)/book->dim; - read = decode_packed_block(book,b,entries,chunk); - for(k=0;kvaluelist+entries[k]*book->dim; - const ogg_int32_t *u = t+book->dim; - do{ - *p0++ += *t++<dim/2; - } - } - return(0); -} - long vorbis_book_decodevv_add(codebook *book,ogg_int32_t **a, long offset,int ch, oggpack_buffer *b,int n,int point){ if(LIKELY(book->used_entries>0)){ - long i,j,k,chunk,read; + long i,j,entry; int chptr=0; int shift=point-book->binarypoint; - long entries[32]; - if (!(book->dim&1) && ch==2) - return vorbis_book_decodevv_add_2ch_even(book,a,offset,b,n,point); +// if (!(book->dim&1) && ch==2) +// return vorbis_book_decodevv_add_2ch_even(book,a,offset,b,n,point); if(shift>=0){ for(i=offset;idim>(offset+n-i)*ch) - chunk=((offset+n-i)*ch+book->dim-1)/book->dim; - read = decode_packed_block(book,b,entries,chunk); - for(k=0;kvaluelist+entries[k]*book->dim; + entry = decode_packed_entry_number(book,b); + if(entry==-1)return(-1); + { + const ogg_int32_t *t = book->valuelist+entry*book->dim; for (j=0;jdim;j++){ a[chptr++][i]+=t[j]>>shift; if(chptr==ch){ @@ -477,17 +353,14 @@ } } } - if (readdim>(offset+n-i)*ch) - chunk=((offset+n-i)*ch+book->dim-1)/book->dim; - read = decode_packed_block(book,b,entries,chunk); - for(k=0;kvaluelist+entries[k]*book->dim; + entry = decode_packed_entry_number(book,b); + if(entry==-1)return(-1); + { + const ogg_int32_t *t = book->valuelist+entry*book->dim; for (j=0;jdim;j++){ a[chptr++][i]+=t[j]< +#include +#include "misc.h" #include "ogg.h" -const unsigned long oggpack_mask[] ICONST_ATTR = +#include + + +#if !defined(ARM_LITTLE_ENDIAN) || defined(_V_BIT_TEST) +static unsigned long mask[]= {0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f, 0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff, 0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff, @@ -30,8 +35,134 @@ 0x000fffff,0x001fffff,0x003fffff,0x007fffff,0x00ffffff, 0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff, 0x3fffffff,0x7fffffff,0xffffffff }; +#endif +#ifdef ARM_LITTLE_ENDIAN + +#ifdef DEBUGGING_BITWISE +extern void oggpack_readinitARM(oggpack_buffer *b,ogg_reference *r); + void oggpack_readinit(oggpack_buffer *b,ogg_reference *r){ + oggpack_readinitARM(b,r); + //fprintf(stderr, "Init: buffer=(%d,%x,%d,%d) %08x%08x\n", + // b->bitsLeftInSegment, b->ptr, b->bitsLeftInWord, b->count, + // b->ptr[1], b->ptr[0]); + //fflush(stderr); +} + +extern long oggpack_lookARM(oggpack_buffer *b,int bits); + +long oggpack_look(oggpack_buffer *b,int bits){ + long l; + + //fprintf(stderr, "PreLook: buffer=(%x,%x,%x) %08x%08x (%d bits)\n", + // b->bitsLeftInSegment, b->ptr, b->bitsLeftInWord, + // b->ptr[1], b->ptr[0], bits); + //fflush(stderr); + l = oggpack_lookARM(b,bits); + //fprintf(stderr, "Look: buffer=(%d,%x,%d,%d) %08x%08x (%d bits) (result=%x)\n", + // b->bitsLeftInSegment, b->ptr, b->bitsLeftInWord, b->count, + // b->ptr[1], b->ptr[0], bits, l); + //fflush(stderr); + + return l; +} + +extern void oggpack_advARM(oggpack_buffer *b,int bits); + +void oggpack_adv(oggpack_buffer *b,int bits){ + //fprintf(stderr, "Adv before: buffer=(%x,%x,%x) %08x%08x (%d bits)\n", + // b->bitsLeftInSegment, b->ptr, b->bitsLeftInWord, + // b->ptr[1], b->ptr[0],bits); + //fflush(stderr); + oggpack_advARM(b,bits); + //fprintf(stderr, "Adv: buffer=(%d,%x,%d,%d) %08x%08x\n", + // b->bitsLeftInSegment, b->ptr, b->bitsLeftInWord, b->count, + // b->ptr[1], b->ptr[0]); + //fflush(stderr); +} + +extern long oggpack_readARM(oggpack_buffer *b,int bits); + +/* bits <= 32 */ +long oggpack_read(oggpack_buffer *b,int bits){ + long l; + + //fprintf(stderr, "PreRead: buffer=(%d,%x,%d,%d) %08x%08x (%d bits)\n", + // b->bitsLeftInSegment, b->ptr, b->bitsLeftInWord, b->count, + // b->ptr[1], b->ptr[0], bits); + //fflush(stderr); + l = oggpack_readARM(b,bits); + //fprintf(stderr, "Read: buffer=(%d,%x,%d,%d) %08x%08x (%d bits) (result=%x)\n", + // b->bitsLeftInSegment, b->ptr, b->bitsLeftInWord, b->count, + // b->ptr[1], b->ptr[0], bits, l); + //fflush(stderr); + + return l; +} +#endif + +int oggpack_eop(oggpack_buffer *b){ + int ret; + if(b->bitsLeftInSegment<0)ret= -1; + else ret = 0; + //fprintf(stderr, "EOP %d\n", ret); + //fflush(stderr); + return ret; +} + +long oggpack_bytes(oggpack_buffer *b){ + long ret; + if(b->bitsLeftInSegment<0) ret = b->count+b->head->length; + else ret = b->count + b->head->length - (b->bitsLeftInSegment)/8; + //fprintf(stderr, "count=%d length=%d bitsLeftInSegment=%d\n", + // b->count, b->head->length, b->bitsLeftInSegment); + //fflush(stderr); + return ret; +} + +long oggpack_bits(oggpack_buffer *b){ + long ret; + if(b->bitsLeftInSegment<0) ret=(b->count+b->head->length)*8; + else ret = b->count*8 + b->head->length*8 - b->bitsLeftInSegment; + //fprintf(stderr, "count=%d length=%d bitsLeftInSegment=%d\n", + // b->count, b->head->length, b->bitsLeftInSegment); + //fflush(stderr); + return ret; +} + +#else + +/* spans forward, skipping as many bytes as headend is negative; if + headend is zero, simply finds next byte. If we're up to the end + of the buffer, leaves headend at zero. If we've read past the end, + halt the decode process. */ + +static void _span(oggpack_buffer *b){ + while(b->headend-(b->headbit>>3)<1){ + b->headend-=b->headbit>>3; + b->headbit&=0x7; + + if(b->head->next){ + b->count+=b->head->length; + b->head=b->head->next; + + if(b->headend+b->head->length>0) + b->headptr=b->head->buffer->data+b->head->begin-b->headend; + + b->headend+=b->head->length; + }else{ + /* we've either met the end of decode, or gone past it. halt + only if we're past */ + if(b->headend*8headbit) + /* read has fallen off the end */ + b->headend=-1; + break; + } + } +} + +void oggpack_readinit(oggpack_buffer *b,ogg_reference *r){ memset(b,0,sizeof(*b)); b->tail=b->head=r; @@ -39,6 +170,13 @@ b->headptr=b->head->buffer->data+b->head->begin; b->headend=b->head->length; _span(b); + + //fprintf(stderr, + // "Init: buffer=(%d,%x,%d,%d) %02x%02x%02x%02x%02x%02x%02x%02x\n", + // b->headbit, b->headptr, b->headend, b->count, + // b->headptr[7], b->headptr[6], b->headptr[5], b->headptr[4], + // b->headptr[3], b->headptr[2], b->headptr[1], b->headptr[0]); + //fflush(stderr); } #define _lookspan() while(!end){\ @@ -49,10 +187,10 @@ } /* 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; +long oggpack_look(oggpack_buffer *b,int bits){ + unsigned long m=mask[bits]; + unsigned long ret; + int BITS = bits; bits+=b->headbit; @@ -62,22 +200,22 @@ 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); + ret|=*ptr++<<(8-b->headbit); if(bits>16){ --end; _lookspan(); - ret|=*ptr++<<(16-b->headbit); + ret|=*ptr++<<(16-b->headbit); if(bits>24){ --end; _lookspan(); - ret|=*ptr++<<(24-b->headbit); + ret|=*ptr++<<(24-b->headbit); if(bits>32 && b->headbit){ --end; _lookspan(); @@ -93,11 +231,11 @@ /* make this a switch jump-table */ ret=b->headptr[0]>>b->headbit; if(bits>8){ - ret|=b->headptr[1]<<(8-b->headbit); + ret|=b->headptr[1]<<(8-b->headbit); if(bits>16){ - ret|=b->headptr[2]<<(16-b->headbit); + ret|=b->headptr[2]<<(16-b->headbit); if(bits>24){ - ret|=b->headptr[3]<<(24-b->headbit); + ret|=b->headptr[3]<<(24-b->headbit); if(bits>32 && b->headbit) ret|=b->headptr[4]<<(32-b->headbit); } @@ -106,109 +244,600 @@ } ret&=m; + //fprintf(stderr, + // "Look: buffer=(%d,%x,%d,%d) %02x%02x%02x%02x%02x%02x%02x%02x (%d bits) return=%x\n", + // b->headbit, b->headptr, b->headend, b->count, + // b->headptr[7], b->headptr[6], b->headptr[5], b->headptr[4], + // b->headptr[3], b->headptr[2], b->headptr[1], b->headptr[0], + // BITS, ret); + //fflush(stderr); return ret; } -/* 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; +/* limited to 32 at a time */ +void oggpack_adv(oggpack_buffer *b,int bits){ + int BITS=bits; + bits+=b->headbit; + b->headbit=bits&7; + b->headend-=(bits>>3); + b->headptr+=(bits>>3); + if(b->headend<1)_span(b); + //fprintf(stderr, "Adv: buffer=(%d,%x,%d,%d) %02x%02x%02x%02x%02x%02x%02x%02x (%d bits)\n", + // b->headbit, b->headptr, b->headend,b->count, + // b->headptr[7], b->headptr[6], b->headptr[5], b->headptr[4], + // b->headptr[3], b->headptr[2], b->headptr[1], b->headptr[0], + // BITS); + //fflush(stderr); +} + +int oggpack_eop(oggpack_buffer *b){ + int ret; + if(b->headend<0)ret= -1; + else ret = 0; + //fprintf(stderr, "EOP %d\n", ret); + //fflush(stderr); + return ret; +} + +long oggpack_bytes(oggpack_buffer *b){ + long ret; + if(b->headend<0) ret = b->count+b->head->length; + ret = b->count + b->head->length-b->headend + (b->headbit+7)/8; + //fprintf(stderr, "Bytes: buffer=(%d,%x,%d,%d) %02x%02x%02x%02x%02x%02x%02x%02x (%d bytes)\n", + // b->headbit, b->headptr, b->headend, b->count, + // b->headptr[7], b->headptr[6], b->headptr[5], b->headptr[4], + // b->headptr[3], b->headptr[2], b->headptr[1], b->headptr[0], + // ret); + //fflush(stderr); + return ret; +} + +long oggpack_bits(oggpack_buffer *b){ + long ret; + if(b->headend<0) ret = (b->count+b->head->length)*8; + else ret = (b->count + b->head->length-b->headend)*8 + b->headbit; + //fprintf(stderr, "Bits: buffer=(%x,%x,%x) %02x%02x%02x%02x%02x%02x%02x%02x (%d bits)\n", + // b->headbit, b->headptr, b->headend, + // b->headptr[7], b->headptr[6], b->headptr[5], b->headptr[4], + // b->headptr[3], b->headptr[2], b->headptr[1], b->headptr[0], + // ret); + //fflush(stderr); + return ret; +} + +/* bits <= 32 */ +long oggpack_read(oggpack_buffer *b,int bits){ + long ret=oggpack_look(b,bits); + oggpack_adv(b,bits); + return(ret); +} + +#endif + +/* Self test of the bitwise routines; everything else is based on + them, so they damned well better be solid. */ + +#ifdef _V_BIT_TEST +#include +#include +#include +#include "framing.c" + +static int ilog(unsigned long v){ + int ret=0; + while(v){ + ret++; + v>>=1; } + return(ret); } -static int _halt_one(oggpack_buffer *b){ - if(b->headend<1){ - _adv_halt(b); - return -1; +oggpack_buffer r; +oggpack_buffer o; +ogg_buffer_state *bs; +ogg_reference *or; +#define TESTWORDS 256 + +void report(char *in){ + fprintf(stderr,"%s",in); + exit(1); +} + +int getbyte(ogg_reference *or,int position){ + while(or && position>=or->length){ + position-=or->length; + or=or->next; + if(or==NULL){ + fprintf(stderr,"\n\tERROR: getbyte ran off end of buffer.\n"); + exit(1); + } } + + if((position+or->begin)&1) + return (or->buffer->data[(position+or->begin)>>1])&0xff; + else + return (or->buffer->data[(position+or->begin)>>1]>>8)&0xff; +} + +void cliptest(unsigned long *b,int vals,int bits,int *comp,int compsize){ + long i,bitcount=0; + ogg_reference *or=ogg_buffer_alloc(bs,64); + for(i=0;ibuffer->data[i]= comp[i]; + or->length=i; + + oggpack_readinit(&r,or); + for(i=0;i7) + report("\nERROR: too many bits reported left over.\n"); + + /* does reading to exactly byte alignment *not* trip EOF? */ + if(oggpack_read(&o,leftover)==-1) + report("\nERROR: read to but not past exact end tripped EOF.\n"); + if(oggpack_bits(&o)!=count*8) + report("\nERROR: read to but not past exact end reported bad bitcount.\n"); + + /* does EOF trip properly after a single additional bit? */ + if(oggpack_read(&o,1)!=-1) + report("\nERROR: read past exact end did not trip EOF.\n"); + if(oggpack_bits(&o)!=count*8) + report("\nERROR: read past exact end reported bad bitcount.\n"); + + /* does EOF stay set over additional bit reads? */ + for(i=0;i<=32;i++){ + if(oggpack_read(&o,i)!=-1) + report("\nERROR: EOF did not stay set on stream.\n"); + if(oggpack_bits(&o)!=count*8) + report("\nERROR: read past exact end reported bad bitcount.\n"); + } +} + +void _end_verify2(int count){ + int i; + + /* are the proper number of bits left over? */ + int leftover=count*8-oggpack_bits(&o); + if(leftover>7) + report("\nERROR: too many bits reported left over.\n"); + + /* does reading to exactly byte alignment *not* trip EOF? */ + oggpack_adv(&o,leftover); +#ifdef ARM_LITTLE_ENDIAN + if(o.bitsLeftInSegment!=0) +#else + if(o.headend!=0) +#endif + report("\nERROR: read to but not past exact end tripped EOF.\n"); + if(oggpack_bits(&o)!=count*8) + report("\nERROR: read to but not past exact end reported bad bitcount.\n"); + + /* does EOF trip properly after a single additional bit? */ + oggpack_adv(&o,1); +#ifdef ARM_LITTLE_ENDIAN + if(o.bitsLeftInSegment>=0) +#else + if(o.headend>=0) +#endif + report("\nERROR: read past exact end did not trip EOF.\n"); + if(oggpack_bits(&o)!=count*8) + report("\nERROR: read past exact end reported bad bitcount.\n"); + + /* does EOF stay set over additional bit reads? */ + for(i=0;i<=32;i++){ + oggpack_adv(&o,i); +#ifdef ARM_LITTLE_ENDIAN + if(o.bitsLeftInSegment>=0) +#else + if(o.headend>=0) +#endif + report("\nERROR: EOF did not stay set on stream.\n"); + if(oggpack_bits(&o)!=count*8) + report("\nERROR: read past exact end reported bad bitcount.\n"); + } +} + +long ogg_buffer_length(ogg_reference *or){ + int count=0; + while(or){ + count+=or->length; + or=or->next; + } + return count; +} + +ogg_reference *ogg_buffer_extend(ogg_reference *or,long bytes){ + if(or){ + while(or->next){ + or=or->next; + } + or->next=ogg_buffer_alloc(or->buffer->ptr.owner,bytes); + return(or->next); + } return 0; } -/* 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; +void ogg_buffer_posttruncate(ogg_reference *or,long pos){ + /* walk to the point where we want to begin truncate */ + while(or && pos>or->length){ + pos-=or->length; + or=or->next; + } + if(or){ + ogg_buffer_release(or->next); + or->next=0; + or->length=pos; + } +} - bits+=b->headbit; +int main(void){ + long i; + static unsigned long testbuffer1[]= + {18,12,103948,4325,543,76,432,52,3,65,4,56,32,42,34,21,1,23,32,546,456,7, + 567,56,8,8,55,3,52,342,341,4,265,7,67,86,2199,21,7,1,5,1,4}; + int test1size=43; - if(bits >= b->headend<<3){ + static unsigned long testbuffer2[]= + {216531625L,1237861823,56732452,131,3212421,12325343,34547562,12313212, + 1233432,534,5,346435231,14436467,7869299,76326614,167548585, + 85525151,0,12321,1,349528352}; + int test2size=21; - 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); - - } - } - } - } - } - } - } + static unsigned long testbuffer3[]= + {1,0,14,0,1,0,12,0,1,0,0,0,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,1,1,1,1,1,0,0,1, + 0,1,30,1,1,1,0,0,1,0,0,0,12,0,11,0,1,0,0,1}; + int test3size=56; + + static unsigned long large[]= + {2136531625L,2137861823,56732452,131,3212421,12325343,34547562,12313212, + 1233432,534,5,2146435231,14436467,7869299,76326614,167548585, + 85525151,0,12321,1,2146528352}; + + int onesize=33; + static int one[33]={146,25,44,151,195,15,153,176,233,131,196,65,85,172,47,40, + 34,242,223,136,35,222,211,86,171,50,225,135,214,75,172, + 223,4}; + + int twosize=6; + static int two[6]={61,255,255,251,231,29}; + + int threesize=54; + static int three[54]={169,2,232,252,91,132,156,36,89,13,123,176,144,32,254, + 142,224,85,59,121,144,79,124,23,67,90,90,216,79,23,83, + 58,135,196,61,55,129,183,54,101,100,170,37,127,126,10, + 100,52,4,14,18,86,77,1}; + + int foursize=38; + static int four[38]={18,6,163,252,97,194,104,131,32,1,7,82,137,42,129,11,72, + 132,60,220,112,8,196,109,64,179,86,9,137,195,208,122,169, + 28,2,133,0,1}; + + int fivesize=45; + static int five[45]={169,2,126,139,144,172,30,4,80,72,240,59,130,218,73,62, + 241,24,210,44,4,20,0,248,116,49,135,100,110,130,181,169, + 84,75,159,2,1,0,132,192,8,0,0,18,22}; + + int sixsize=7; + static int six[7]={17,177,170,242,169,19,148}; + + /* Test read/write together */ + /* Later we test against pregenerated bitstreams */ + bs=ogg_buffer_create(); + + fprintf(stderr,"\nSmall preclipped packing (LSb): "); + cliptest(testbuffer1,test1size,0,one,onesize); + fprintf(stderr,"ok."); + + fprintf(stderr,"\nNull bit call (LSb): "); + cliptest(testbuffer3,test3size,0,two,twosize); + fprintf(stderr,"ok."); + + fprintf(stderr,"\nLarge preclipped packing (LSb): "); + cliptest(testbuffer2,test2size,0,three,threesize); + fprintf(stderr,"ok."); + + fprintf(stderr,"\n32 bit preclipped packing (LSb): "); + + or=ogg_buffer_alloc(bs,128); + for(i=0;ibuffer->data[i*4] = large[i]&0xff; + or->buffer->data[i*4+1] = (large[i]>>8)&0xff; + or->buffer->data[i*4+2] = (large[i]>>16)&0xff; + or->buffer->data[i*4+3] = (large[i]>>24)&0xff; + } + or->length=test2size*4; + oggpack_readinit(&r,or); + for(i=0;iheadptr[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); + oggpack_readinit(&r,&lor); + if((test=oggpack_read(&r,30))==0xffffffffUL || + (test=oggpack_read(&r,16))==0xffffffffUL){ + fprintf(stderr,"failed 2; got -1 prematurely.\n"); + exit(1); + } + + if((test=oggpack_look(&r,18))==0xffffffffUL){ + fprintf(stderr,"failed 3; got -1 prematurely.\n"); + exit(1); + } + if((test=oggpack_look(&r,19))!=0xffffffffUL){ + fprintf(stderr,"failed; read past end without -1.\n"); + exit(1); + } + if((test=oggpack_look(&r,32))!=0xffffffffUL){ + fprintf(stderr,"failed; read past end without -1.\n"); + exit(1); + } + } + fprintf(stderr,"ok.\n"); + + /* now the scary shit: randomized testing */ + + for(i=0;i<10000;i++){ + long j,count=0,count2=0,bitcount=0; + unsigned long values[TESTWORDS]; + int len[TESTWORDS]; + unsigned char flat[4*TESTWORDS]; /* max possible needed size */ + + memset(flat,0,sizeof(flat)); + fprintf(stderr,"\rRandomized testing (LSb)... (%ld) ",10000-i); + + /* generate a list of words and lengths */ + /* write the required number of bits out to packbuffer */ + { + long word=0; + long bit=0; + int k; + + for(j=0;j>k)&0x1)<7){ + bit=0; + word++; + } + } + } + } + count2=(bitcount+7)>>3; + + /* construct random-length buffer chain from flat vector; random + byte starting offset within the length of the vector */ + { + ogg_reference *or=NULL,*orl=NULL; + long pos=0; + + /* build buffer chain */ + while(count2){ + int ilen=(rand()%32),k; + int ibegin=(rand()%32); + + + if(ilen>count2)ilen=count2; + + if(or) + orl=ogg_buffer_extend(orl,64); + else + or=orl=ogg_buffer_alloc(bs,64); + + orl->length=ilen; + orl->begin=ibegin; + + for(k=0;kbuffer->data[ibegin++]= flat[pos++]; + + count2-=ilen; + } + + if(ogg_buffer_length(or)!=(bitcount+7)/8){ + fprintf(stderr,"\nERROR: buffer length incorrect after build.\n"); + exit(1); + } + + + { + int begin=0; //=(rand()%TESTWORDS); + int ilen=(rand()%(TESTWORDS-begin)); + int bitoffset,bitcount=0; + unsigned long temp; + + for(j=0;jheadptr+=((unsigned)bits)/8; - b->headend-=((unsigned)bits)/8; } + fprintf(stderr,"\rRandomized testing (LSb)... ok. \n"); - ret&=m; - b->headbit=bits&7; - return ret; + return(0); } +#ifdef _WIN32_WCE +int WinMain(void){ + return main(); +} +#endif + +#endif Index: apps/codecs/libtremor/ogg.h =================================================================== --- apps/codecs/libtremor/ogg.h (revision 20567) +++ apps/codecs/libtremor/ogg.h (working copy) @@ -23,6 +23,10 @@ #include "os_types.h" +#ifndef ONLY_C +#define ARM_LITTLE_ENDIAN +#endif + typedef struct ogg_buffer_state{ struct ogg_buffer *unused_buffers; struct ogg_reference *unused_references; @@ -34,7 +38,7 @@ unsigned char *data; long size; int refcount; - + union { ogg_buffer_state *owner; struct ogg_buffer *next; @@ -50,10 +54,15 @@ } ogg_reference; typedef struct oggpack_buffer { +#ifdef ARM_LITTLE_ENDIAN + int bitsLeftInSegment; + ogg_uint32_t *ptr; + long bitsLeftInWord; +#else int headbit; unsigned char *headptr; long headend; - +#endif /* ARM_LITTLE_ENDIAN */ /* memory management */ ogg_reference *head; ogg_reference *tail; @@ -115,7 +124,7 @@ int clearflag; int laceptr; ogg_uint32_t body_fill_next; - + } ogg_stream_state; typedef struct { @@ -141,74 +150,13 @@ /* Ogg BITSTREAM PRIMITIVES: bitstream ************************/ extern void oggpack_readinit(oggpack_buffer *b,ogg_reference *r); -extern long oggpack_look_full(oggpack_buffer *b,int bits); -extern long oggpack_read(oggpack_buffer *b,register int bits); +extern long oggpack_look(oggpack_buffer *b,int bits); +extern void oggpack_adv(oggpack_buffer *b,int bits); +extern long oggpack_read(oggpack_buffer *b,int bits); +extern long oggpack_bytes(oggpack_buffer *b); +extern long oggpack_bits(oggpack_buffer *b); +extern int oggpack_eop(oggpack_buffer *b); -/* Inline a few, often called functions */ - -/* mark read process as having run off the end */ -static inline void _adv_halt(oggpack_buffer *b){ - b->headptr=b->head->buffer->data+b->head->begin+b->head->length; - b->headend=-1; - b->headbit=0; -} - -/* spans forward, skipping as many bytes as headend is negative; if - headend is zero, simply finds next byte. If we're up to the end - of the buffer, leaves headend at zero. If we've read past the end, - halt the decode process. */ -static inline void _span(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->headend+=b->head->length; - }else{ - /* we've either met the end of decode, or gone past it. halt - only if we're past */ - if(b->headend<0 || b->headbit) - /* read has fallen off the end */ - _adv_halt(b); - - break; - } - } -} - -/* limited to 32 at a time */ -static inline void oggpack_adv(oggpack_buffer *b,int bits){ - bits+=b->headbit; - b->headbit=bits&7; - b->headptr+=bits/8; - if((b->headend-=((unsigned)bits)/8)<1)_span(b); -} - -static inline long oggpack_look(oggpack_buffer *b, int bits){ - if(bits+b->headbit < b->headend<<3){ - extern const unsigned long oggpack_mask[]; - unsigned long m=oggpack_mask[bits]; - unsigned long ret=-1; - - bits+=b->headbit; - 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); - } - } - } - return ret&m; - }else{ - return oggpack_look_full(b, bits); - } -} - /* Ogg BITSTREAM PRIMITIVES: decoding **************************/ extern ogg_sync_state *ogg_sync_create(void); @@ -218,6 +166,7 @@ extern unsigned char *ogg_sync_bufferin(ogg_sync_state *oy, long size); extern int ogg_sync_wrote(ogg_sync_state *oy, long bytes); extern long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og); +extern int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og); extern int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og); extern int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op); extern int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op); @@ -239,6 +188,7 @@ extern ogg_int64_t ogg_page_granulepos(ogg_page *og); extern ogg_uint32_t ogg_page_serialno(ogg_page *og); extern ogg_uint32_t ogg_page_pageno(ogg_page *og); +extern int ogg_page_packets(ogg_page *og); extern int ogg_page_getbuffer(ogg_page *og, unsigned char **buffer); extern int ogg_packet_release(ogg_packet *op); Index: apps/codecs/libtremor/libtremor.make =================================================================== --- apps/codecs/libtremor/libtremor.make (revision 20567) +++ apps/codecs/libtremor/libtremor.make (working copy) @@ -17,12 +17,6 @@ $(SILENT)$(shell rm -f $@) $(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null -$(CODECDIR)/libtremor/%.o: $(ROOTDIR)/apps/codecs/libtremor/%.c - $(SILENT)mkdir -p $(dir $@) - $(call PRINTS,CC $(subst $(ROOTDIR)/,,$<))$(CC) \ - -I$(APPSDIR)/codecs/libtremor \ - $(CODECFLAGS) $(CFLAGS) -c $< -o $@ - TREMORFLAGS = -I$(APPSDIR)/codecs/libtremor $(filter-out -O%,$(CODECFLAGS)) # Tremor is slightly faster on coldfire with -O3 @@ -32,6 +26,9 @@ TREMORFLAGS += -O2 endif +$(CODECDIR)/libtremor/bitwiseARM.o: $(ROOTDIR)/apps/codecs/libtremor/bitwiseARM.S + $(CC) $(TREMORFLAGS) -c $< -o $@ + $(CODECDIR)/libtremor/%.o: $(ROOTDIR)/apps/codecs/libtremor/%.c $(SILENT)mkdir -p $(dir $@) $(call PRINTS,CC $(subst $(ROOTDIR)/,,$<))$(CC) $(TREMORFLAGS) -c $< -o $@