1
0
Fork 0
forked from len0rd/rockbox

Vorbis: Apply various bugfixes from upstream Tremor.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13756 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Magnus Holmgren 2007-07-01 17:58:49 +00:00
parent 9af4289770
commit 932b20ec62
6 changed files with 290 additions and 260 deletions

View file

@ -148,7 +148,7 @@ static inline ogg_uint32_t bitreverse(register ogg_uint32_t x){
return((x>> 1)&0x55555555) | ((x<< 1)&0xaaaaaaaa); return((x>> 1)&0x55555555) | ((x<< 1)&0xaaaaaaaa);
} }
static inline long decode_packed_entry_number(codebook *book, STIN long decode_packed_entry_number(codebook *book,
oggpack_buffer *b){ oggpack_buffer *b){
int read=book->dec_maxlength; int read=book->dec_maxlength;
long lo,hi; long lo,hi;
@ -172,7 +172,11 @@ static inline long decode_packed_entry_number(codebook *book,
while(lok<0 && read>1) while(lok<0 && read>1)
lok = oggpack_look(b, --read); lok = oggpack_look(b, --read);
if(lok<0)return -1;
if(lok<0){
oggpack_adv(b,1); /* force eop */
return -1;
}
/* bisect search for the codeword in the ordered list */ /* bisect search for the codeword in the ordered list */
{ {
@ -191,7 +195,7 @@ static inline long decode_packed_entry_number(codebook *book,
} }
} }
oggpack_adv(b, read); oggpack_adv(b, read+1);
return(-1); return(-1);
} }
@ -283,67 +287,73 @@ static inline long decode_packed_block(codebook *book, oggpack_buffer *b,
/* returns the [original, not compacted] entry number or -1 on eof *********/ /* returns the [original, not compacted] entry number or -1 on eof *********/
long vorbis_book_decode(codebook *book, oggpack_buffer *b){ long vorbis_book_decode(codebook *book, oggpack_buffer *b){
long packed_entry=decode_packed_entry_number(book,b); if(book->used_entries>0){
if(packed_entry>=0) long packed_entry=decode_packed_entry_number(book,b);
return(book->dec_index[packed_entry]); if(packed_entry>=0)
return(book->dec_index[packed_entry]);
}
/* if there's no dec_index, the codebook unpacking isn't collapsed */ /* if there's no dec_index, the codebook unpacking isn't collapsed */
return(packed_entry); return(-1);
} }
/* returns 0 on OK or -1 on eof *************************************/ /* returns 0 on OK or -1 on eof *************************************/
long vorbis_book_decodevs_add(codebook *book,ogg_int32_t *a, long vorbis_book_decodevs_add(codebook *book,ogg_int32_t *a,
oggpack_buffer *b,int n,int point){ oggpack_buffer *b,int n,int point){
int step=n/book->dim; if(book->used_entries>0){
long *entry = (long *)alloca(sizeof(*entry)*step); int step=n/book->dim;
ogg_int32_t **t = (ogg_int32_t **)alloca(sizeof(*t)*step); long *entry = (long *)alloca(sizeof(*entry)*step);
int i,j,o; ogg_int32_t **t = (ogg_int32_t **)alloca(sizeof(*t)*step);
int shift=point-book->binarypoint; int i,j,o;
int shift=point-book->binarypoint;
if(shift>=0){
for (i = 0; i < step; i++) { if(shift>=0){
entry[i]=decode_packed_entry_number(book,b); for (i = 0; i < step; i++) {
if(entry[i]==-1)return(-1); entry[i]=decode_packed_entry_number(book,b);
t[i] = book->valuelist+entry[i]*book->dim; if(entry[i]==-1)return(-1);
t[i] = book->valuelist+entry[i]*book->dim;
}
for(i=0,o=0;i<book->dim;i++,o+=step)
for (j=0;j<step;j++)
a[o+j]+=t[j][i]>>shift;
}else{
for (i = 0; i < step; i++) {
entry[i]=decode_packed_entry_number(book,b);
if(entry[i]==-1)return(-1);
t[i] = book->valuelist+entry[i]*book->dim;
}
for(i=0,o=0;i<book->dim;i++,o+=step)
for (j=0;j<step;j++)
a[o+j]+=t[j][i]<<-shift;
} }
for(i=0,o=0;i<book->dim;i++,o+=step)
for (j=0;j<step;j++)
a[o+j]+=t[j][i]>>shift;
}else{
for (i = 0; i < step; i++) {
entry[i]=decode_packed_entry_number(book,b);
if(entry[i]==-1)return(-1);
t[i] = book->valuelist+entry[i]*book->dim;
}
for(i=0,o=0;i<book->dim;i++,o+=step)
for (j=0;j<step;j++)
a[o+j]+=t[j][i]<<-shift;
} }
return(0); return(0);
} }
long vorbis_book_decodev_add(codebook *book,ogg_int32_t *a, long vorbis_book_decodev_add(codebook *book,ogg_int32_t *a,
oggpack_buffer *b,int n,int point){ oggpack_buffer *b,int n,int point){
int i,j,entry; if(book->used_entries>0){
ogg_int32_t *t; int i,j,entry;
int shift=point-book->binarypoint; ogg_int32_t *t;
int shift=point-book->binarypoint;
if(shift>=0){
for(i=0;i<n;){ if(shift>=0){
entry = decode_packed_entry_number(book,b); for(i=0;i<n;){
if(entry==-1)return(-1); entry = decode_packed_entry_number(book,b);
t = book->valuelist+entry*book->dim; if(entry==-1)return(-1);
for (j=0;j<book->dim;) t = book->valuelist+entry*book->dim;
a[i++]+=t[j++]>>shift; for (j=0;j<book->dim;)
} a[i++]+=t[j++]>>shift;
}else{ }
shift = -shift; }else{
for(i=0;i<n;){ shift = -shift;
entry = decode_packed_entry_number(book,b); for(i=0;i<n;){
if(entry==-1)return(-1); entry = decode_packed_entry_number(book,b);
t = book->valuelist+entry*book->dim; if(entry==-1)return(-1);
for (j=0;j<book->dim;) t = book->valuelist+entry*book->dim;
a[i++]+=t[j++]<<shift; for (j=0;j<book->dim;)
a[i++]+=t[j++]<<shift;
}
} }
} }
return(0); return(0);
@ -351,28 +361,38 @@ long vorbis_book_decodev_add(codebook *book,ogg_int32_t *a,
long vorbis_book_decodev_set(codebook *book,ogg_int32_t *a, long vorbis_book_decodev_set(codebook *book,ogg_int32_t *a,
oggpack_buffer *b,int n,int point){ oggpack_buffer *b,int n,int point){
int i,j,entry; if(book->used_entries>0){
ogg_int32_t *t; int i,j,entry;
int shift=point-book->binarypoint; ogg_int32_t *t;
int shift=point-book->binarypoint;
if(shift>=0){
if(shift>=0){
for(i=0;i<n;){
entry = decode_packed_entry_number(book,b); for(i=0;i<n;){
if(entry==-1)return(-1); entry = decode_packed_entry_number(book,b);
t = book->valuelist+entry*book->dim; if(entry==-1)return(-1);
for (j=0;j<book->dim;){ t = book->valuelist+entry*book->dim;
a[i++]=t[j++]>>shift; for (j=0;j<book->dim;){
a[i++]=t[j++]>>shift;
}
}
}else{
shift = -shift;
for(i=0;i<n;){
entry = decode_packed_entry_number(book,b);
if(entry==-1)return(-1);
t = book->valuelist+entry*book->dim;
for (j=0;j<book->dim;){
a[i++]=t[j++]<<shift;
}
} }
} }
}else{ }else{
shift = -shift;
int i,j;
for(i=0;i<n;){ for(i=0;i<n;){
entry = decode_packed_entry_number(book,b);
if(entry==-1)return(-1);
t = book->valuelist+entry*book->dim;
for (j=0;j<book->dim;){ for (j=0;j<book->dim;){
a[i++]=t[j++]<<shift; a[i++]=0;
} }
} }
} }
@ -382,48 +402,50 @@ long vorbis_book_decodev_set(codebook *book,ogg_int32_t *a,
long vorbis_book_decodevv_add(codebook *book,ogg_int32_t **a, long vorbis_book_decodevv_add(codebook *book,ogg_int32_t **a,
long offset,int ch, long offset,int ch,
oggpack_buffer *b,int n,int point){ oggpack_buffer *b,int n,int point){
long i,j,k,chunk,read; if(book->used_entries>0){
int chptr=0; long i,j,k,chunk,read;
int shift=point-book->binarypoint; int chptr=0;
long entries[32]; int shift=point-book->binarypoint;
long entries[32];
if(shift>=0){ if(shift>=0){
for(i=offset;i<offset+n;){ for(i=offset;i<offset+n;){
chunk=32; chunk=32;
if (chunk*book->dim>(offset+n-i)*ch) if (chunk*book->dim>(offset+n-i)*ch)
chunk=((offset+n-i)*ch+book->dim-1)/book->dim; chunk=((offset+n-i)*ch+book->dim-1)/book->dim;
read = decode_packed_block(book,b,entries,chunk); read = decode_packed_block(book,b,entries,chunk);
for(k=0;k<read;k++){ for(k=0;k<read;k++){
const ogg_int32_t *t = book->valuelist+entries[k]*book->dim; const ogg_int32_t *t = book->valuelist+entries[k]*book->dim;
for (j=0;j<book->dim;j++){ for (j=0;j<book->dim;j++){
a[chptr++][i]+=t[j]>>shift; a[chptr++][i]+=t[j]>>shift;
if(chptr==ch){ if(chptr==ch){
chptr=0; chptr=0;
i++; i++;
}
} }
} }
if (read<chunk)return-1;
} }
if (read<chunk)return-1; }else{
} shift = -shift;
}else{ for(i=offset;i<offset+n;){
shift = -shift; chunk=32;
for(i=offset;i<offset+n;){ if (chunk*book->dim>(offset+n-i)*ch)
chunk=32; chunk=((offset+n-i)*ch+book->dim-1)/book->dim;
if (chunk*book->dim>(offset+n-i)*ch) read = decode_packed_block(book,b,entries,chunk);
chunk=((offset+n-i)*ch+book->dim-1)/book->dim; for(k=0;k<read;k++){
read = decode_packed_block(book,b,entries,chunk); const ogg_int32_t *t = book->valuelist+entries[k]*book->dim;
for(k=0;k<read;k++){ for (j=0;j<book->dim;j++){
const ogg_int32_t *t = book->valuelist+entries[k]*book->dim; a[chptr++][i]+=t[j]<<shift;
for (j=0;j<book->dim;j++){ if(chptr==ch){
a[chptr++][i]+=t[j]<<shift; chptr=0;
if(chptr==ch){ i++;
chptr=0; }
i++;
} }
} }
if (read<chunk)return-1;
} }
if (read<chunk)return-1;
} }
} }
return(0); return(0);

View file

@ -286,7 +286,7 @@ static const ogg_int32_t FLOOR_fromdB_LOOKUP[256] ICONST_ATTR = {
XdB(0x69f80e9a), XdB(0x70dafda8), XdB(0x78307d76), XdB(0x7fffffff), XdB(0x69f80e9a), XdB(0x70dafda8), XdB(0x78307d76), XdB(0x7fffffff),
}; };
static void render_line(int x0,register int x1,int y0,int y1,ogg_int32_t *d){ static void render_line(int n, int x0,register int x1,int y0,int y1,ogg_int32_t *d){
int dy=y1-y0; int dy=y1-y0;
register int x=x0; register int x=x0;
register int y=y0; register int y=y0;
@ -296,11 +296,13 @@ static void render_line(int x0,register int x1,int y0,int y1,ogg_int32_t *d){
register int sy=(dy<0?base-1:base+1); register int sy=(dy<0?base-1:base+1);
int err=0; int err=0;
if(n>x1)n=x1;
ady-=abs(base*adx); ady-=abs(base*adx);
d[x]= MULT31_SHIFT15(d[x],FLOOR_fromdB_LOOKUP[y]); if(x<n)
d[x]= MULT31_SHIFT15(d[x],FLOOR_fromdB_LOOKUP[y]);
while(++x<x1){ while(++x<n){
err=err+ady; err=err+ady;
if(err>=adx){ if(err>=adx){
err-=adx; err-=adx;
@ -424,7 +426,7 @@ static int floor1_inverse2(vorbis_block *vb,vorbis_look_floor *in,void *memo,
hy*=info->mult; hy*=info->mult;
hx=info->postlist[current]; hx=info->postlist[current];
render_line(lx,hx,ly,hy,out); render_line(n,lx,hx,ly,hy,out);
lx=hx; lx=hx;
ly=hy; ly=hy;

View file

@ -53,11 +53,6 @@ static void _ogg_buffer_destroy(ogg_buffer_state *bs){
bt=bs->unused_buffers; bt=bs->unused_buffers;
rt=bs->unused_references; rt=bs->unused_references;
if(!bs->outstanding){
_ogg_free(bs);
return;
}
while(bt){ while(bt){
ogg_buffer *b=bt; ogg_buffer *b=bt;
bt=b->ptr.next; bt=b->ptr.next;
@ -71,6 +66,10 @@ static void _ogg_buffer_destroy(ogg_buffer_state *bs){
_ogg_free(r); _ogg_free(r);
} }
bs->unused_references=0; bs->unused_references=0;
if(!bs->outstanding)
_ogg_free(bs);
} }
} }
@ -836,6 +835,7 @@ int ogg_stream_destroy(ogg_stream_state *os){
ogg_buffer_release(os->header_tail); ogg_buffer_release(os->header_tail);
ogg_buffer_release(os->body_tail); ogg_buffer_release(os->body_tail);
memset(os,0,sizeof(*os)); memset(os,0,sizeof(*os));
_ogg_free(os);
} }
return OGG_SUCCESS; return OGG_SUCCESS;
} }

View file

@ -97,8 +97,8 @@ void vorbis_comment_clear(vorbis_comment *vc){
if(vc->user_comments)_ogg_free(vc->user_comments); if(vc->user_comments)_ogg_free(vc->user_comments);
if(vc->comment_lengths)_ogg_free(vc->comment_lengths); if(vc->comment_lengths)_ogg_free(vc->comment_lengths);
if(vc->vendor)_ogg_free(vc->vendor); if(vc->vendor)_ogg_free(vc->vendor);
memset(vc,0,sizeof(*vc));
} }
memset(vc,0,sizeof(*vc));
} }
/* blocksize 0 is guaranteed to be short, 1 is guarantted to be long. /* blocksize 0 is guaranteed to be short, 1 is guarantted to be long.
@ -124,13 +124,16 @@ void vorbis_info_clear(vorbis_info *vi){
if(ci->mode_param[i])_ogg_free(ci->mode_param[i]); if(ci->mode_param[i])_ogg_free(ci->mode_param[i]);
for(i=0;i<ci->maps;i++) /* unpack does the range checking */ for(i=0;i<ci->maps;i++) /* unpack does the range checking */
_mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]); if(ci->map_param[i])
_mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]);
for(i=0;i<ci->floors;i++) /* unpack does the range checking */ for(i=0;i<ci->floors;i++) /* unpack does the range checking */
_floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]); if(ci->floor_param[i])
_floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]);
for(i=0;i<ci->residues;i++) /* unpack does the range checking */ for(i=0;i<ci->residues;i++) /* unpack does the range checking */
_residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]); if(ci->residue_param[i])
_residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]);
for(i=0;i<ci->books;i++){ for(i=0;i<ci->books;i++){
if(ci->book_param[i]){ if(ci->book_param[i]){

View file

@ -187,45 +187,48 @@ static int _01inverse(vorbis_block *vb,vorbis_look_residue *vl,
/* move all this setup out later */ /* move all this setup out later */
int samples_per_partition=info->grouping; int samples_per_partition=info->grouping;
int partitions_per_word=look->phrasebook->dim; int partitions_per_word=look->phrasebook->dim;
int n=info->end-info->begin; int max=vb->pcmend>>1;
int end=(info->end<max?info->end:max);
int n=end-info->begin;
if(n>0){
int partvals=n/samples_per_partition;
int partwords=(partvals+partitions_per_word-1)/partitions_per_word;
int ***partword=(int ***)alloca(ch*sizeof(*partword));
int partvals=n/samples_per_partition; for(j=0;j<ch;j++)
int partwords=(partvals+partitions_per_word-1)/partitions_per_word; partword[j]=(int **)_vorbis_block_alloc(vb,partwords*sizeof(*partword[j]));
int ***partword=(int ***)alloca(ch*sizeof(*partword));
for(s=0;s<look->stages;s++){
for(j=0;j<ch;j++)
partword[j]=(int **)_vorbis_block_alloc(vb,partwords*sizeof(*partword[j])); /* each loop decodes on partition codeword containing
partitions_pre_word partitions */
for(s=0;s<look->stages;s++){ for(i=0,l=0;i<partvals;l++){
if(s==0){
/* each loop decodes on partition codeword containing /* fetch the partition word for each channel */
partitions_pre_word partitions */ for(j=0;j<ch;j++){
for(i=0,l=0;i<partvals;l++){ int temp=vorbis_book_decode(look->phrasebook,&vb->opb);
if(s==0){ if(temp==-1)goto eopbreak;
/* fetch the partition word for each channel */ partword[j][l]=look->decodemap[temp];
for(j=0;j<ch;j++){ if(partword[j][l]==NULL)goto errout;
int temp=vorbis_book_decode(look->phrasebook,&vb->opb);
if(temp==-1)goto eopbreak;
partword[j][l]=look->decodemap[temp];
if(partword[j][l]==NULL)goto errout;
}
}
/* now we decode residual values for the partitions */
for(k=0;k<partitions_per_word && i<partvals;k++,i++)
for(j=0;j<ch;j++){
long offset=info->begin+i*samples_per_partition;
if(info->secondstages[partword[j][l][k]]&(1<<s)){
codebook *stagebook=look->partbooks[partword[j][l][k]][s];
if(stagebook){
if(decodepart(stagebook,in[j]+offset,&vb->opb,
samples_per_partition,-8)==-1)goto eopbreak;
}
} }
} }
/* now we decode residual values for the partitions */
for(k=0;k<partitions_per_word && i<partvals;k++,i++)
for(j=0;j<ch;j++){
long offset=info->begin+i*samples_per_partition;
if(info->secondstages[partword[j][l][k]]&(1<<s)){
codebook *stagebook=look->partbooks[partword[j][l][k]][s];
if(stagebook){
if(decodepart(stagebook,in[j]+offset,&vb->opb,
samples_per_partition,-8)==-1)goto eopbreak;
}
}
}
}
} }
} }
errout: errout:
eopbreak: eopbreak:
return(0); return(0);
@ -255,8 +258,6 @@ int res1_inverse(vorbis_block *vb,vorbis_look_residue *vl,
return(0); return(0);
} }
/* duplicate code here as speed is somewhat more important */ /* duplicate code here as speed is somewhat more important */
int res2_inverse(vorbis_block *vb,vorbis_look_residue *vl, int res2_inverse(vorbis_block *vb,vorbis_look_residue *vl,
ogg_int32_t **in,int *nonzero,int ch) ogg_int32_t **in,int *nonzero,int ch)
@ -270,44 +271,48 @@ int res2_inverse(vorbis_block *vb,vorbis_look_residue *vl,
/* move all this setup out later */ /* move all this setup out later */
int samples_per_partition=info->grouping; int samples_per_partition=info->grouping;
int partitions_per_word=look->phrasebook->dim; int partitions_per_word=look->phrasebook->dim;
int n=info->end-info->begin; int max=(vb->pcmend*ch)>>1;
int end=(info->end<max?info->end:max);
int n=end-info->begin;
int partvals=n/samples_per_partition; if(n>0){
int partwords=(partvals+partitions_per_word-1)/partitions_per_word;
int **partword=(int **)_vorbis_block_alloc(vb,partwords*sizeof(*partword)); int partvals=n/samples_per_partition;
int beginoff=info->begin/ch; int partwords=(partvals+partitions_per_word-1)/partitions_per_word;
int **partword=(int **)_vorbis_block_alloc(vb,partwords*sizeof(*partword));
for(i=0;i<ch;i++)if(nonzero[i])break; int beginoff=info->begin/ch;
if(i==ch)return(0); /* no nonzero vectors */
samples_per_partition/=ch;
for(s=0;s<look->stages;s++){
for(i=0,l=0;i<partvals;l++){
if(s==0){
/* fetch the partition word */
int temp=vorbis_book_decode(look->phrasebook,&vb->opb);
if(temp==-1)goto eopbreak;
partword[l]=look->decodemap[temp];
if(partword[l]==NULL)goto errout;
}
/* now we decode residual values for the partitions */
for(k=0;k<partitions_per_word && i<partvals;k++,i++)
if(info->secondstages[partword[l][k]]&(1<<s)){
codebook *stagebook=look->partbooks[partword[l][k]][s];
if(stagebook){
if(vorbis_book_decodevv_add(stagebook,in,
i*samples_per_partition+beginoff,ch,
&vb->opb,
samples_per_partition,-8)==-1)
goto eopbreak;
}
}
}
}
for(i=0;i<ch;i++)if(nonzero[i])break;
if(i==ch)return(0); /* no nonzero vectors */
samples_per_partition/=ch;
for(s=0;s<look->stages;s++){
for(i=0,l=0;i<partvals;l++){
if(s==0){
/* fetch the partition word */
int temp=vorbis_book_decode(look->phrasebook,&vb->opb);
if(temp==-1)goto eopbreak;
partword[l]=look->decodemap[temp];
if(partword[l]==NULL)goto errout;
}
/* now we decode residual values for the partitions */
for(k=0;k<partitions_per_word && i<partvals;k++,i++)
if(info->secondstages[partword[l][k]]&(1<<s)){
codebook *stagebook=look->partbooks[partword[l][k]][s];
if(stagebook){
if(vorbis_book_decodevv_add(stagebook,in,
i*samples_per_partition+beginoff,ch,
&vb->opb,
samples_per_partition,-8)==-1)
goto eopbreak;
}
}
}
}
}
errout: errout:
eopbreak: eopbreak:
return(0); return(0);

View file

@ -337,24 +337,21 @@ int vorbis_book_init_decode(codebook *c,const static_codebook *s){
c->used_entries=n; c->used_entries=n;
c->dim=s->dim; c->dim=s->dim;
c->q_min=s->q_min; if(n>0){
c->q_delta=s->q_delta; /* two different remappings go on here.
/* two different remappings go on here. First, we collapse the likely sparse codebook down only to
actually represented values/words. This collapsing needs to be
First, we collapse the likely sparse codebook down only to indexed as map-valueless books are used to encode original entry
actually represented values/words. This collapsing needs to be positions as integers.
indexed as map-valueless books are used to encode original entry
positions as integers. Second, we reorder all vectors, including the entry index above,
by sorted bitreversed codeword to allow treeless decode. */
Second, we reorder all vectors, including the entry index above,
by sorted bitreversed codeword to allow treeless decode. */
{
/* perform sort */ /* perform sort */
ogg_uint32_t *codes=_make_words(s->lengthlist,s->entries,c->used_entries); ogg_uint32_t *codes=_make_words(s->lengthlist,s->entries,c->used_entries);
ogg_uint32_t **codep=(ogg_uint32_t **)ogg_tmpmalloc(sizeof(*codep)*n); ogg_uint32_t **codep=(ogg_uint32_t **)ogg_tmpmalloc(sizeof(*codep)*n);
if(codes==NULL||codep==NULL)goto err_out; if(codes==NULL||codep==NULL)goto err_out;
for(i=0;i<n;i++){ for(i=0;i<n;i++){
@ -375,67 +372,68 @@ int vorbis_book_init_decode(codebook *c,const static_codebook *s){
for(i=0;i<n;i++) for(i=0;i<n;i++)
c->codelist[sortindex[i]]=codes[i]; c->codelist[sortindex[i]]=codes[i];
/* _ogg_free(codes); */ /* _ogg_free(codes); */
}
c->valuelist=_book_unquantize(s,n,sortindex,&c->binarypoint); c->valuelist=_book_unquantize(s,n,sortindex,&c->binarypoint);
c->dec_index=(int *)_ogg_malloc(n*sizeof(*c->dec_index)); c->dec_index=(int *)_ogg_malloc(n*sizeof(*c->dec_index));
for(n=0,i=0;i<s->entries;i++) for(n=0,i=0;i<s->entries;i++)
if(s->lengthlist[i]>0) if(s->lengthlist[i]>0)
c->dec_index[sortindex[n++]]=i; c->dec_index[sortindex[n++]]=i;
c->dec_codelengths=(char *)_ogg_malloc(n*sizeof(*c->dec_codelengths)); c->dec_codelengths=(char *)_ogg_malloc(n*sizeof(*c->dec_codelengths));
for(n=0,i=0;i<s->entries;i++) for(n=0,i=0;i<s->entries;i++)
if(s->lengthlist[i]>0) if(s->lengthlist[i]>0)
c->dec_codelengths[sortindex[n++]]=s->lengthlist[i]; c->dec_codelengths[sortindex[n++]]=s->lengthlist[i];
c->dec_firsttablen=_ilog(c->used_entries)-4; /* this is magic */ c->dec_firsttablen=_ilog(c->used_entries)-4; /* this is magic */
if(c->dec_firsttablen<5)c->dec_firsttablen=5; if(c->dec_firsttablen<5)c->dec_firsttablen=5;
if(c->dec_firsttablen>8)c->dec_firsttablen=8; if(c->dec_firsttablen>8)c->dec_firsttablen=8;
tabn=1<<c->dec_firsttablen; tabn=1<<c->dec_firsttablen;
c->dec_firsttable=(ogg_uint32_t *)_ogg_calloc(tabn,sizeof(*c->dec_firsttable)); c->dec_firsttable=(ogg_uint32_t *)_ogg_calloc(tabn,sizeof(*c->dec_firsttable));
c->dec_maxlength=0; c->dec_maxlength=0;
for(i=0;i<n;i++){ for(i=0;i<n;i++){
if(c->dec_maxlength<c->dec_codelengths[i]) if(c->dec_maxlength<c->dec_codelengths[i])
c->dec_maxlength=c->dec_codelengths[i]; c->dec_maxlength=c->dec_codelengths[i];
if(c->dec_codelengths[i]<=c->dec_firsttablen){ if(c->dec_codelengths[i]<=c->dec_firsttablen){
ogg_uint32_t orig=bitreverse(c->codelist[i]); ogg_uint32_t orig=bitreverse(c->codelist[i]);
for(j=0;j<(1<<(c->dec_firsttablen-c->dec_codelengths[i]));j++) for(j=0;j<(1<<(c->dec_firsttablen-c->dec_codelengths[i]));j++)
c->dec_firsttable[orig|(j<<c->dec_codelengths[i])]=i+1; c->dec_firsttable[orig|(j<<c->dec_codelengths[i])]=i+1;
}
} }
}
/* now fill in 'unused' entries in the firsttable with hi/lo search
/* now fill in 'unused' entries in the firsttable with hi/lo search hints for the non-direct-hits */
hints for the non-direct-hits */ {
{ ogg_uint32_t mask=0xfffffffeUL<<(31-c->dec_firsttablen);
ogg_uint32_t mask=0xfffffffeUL<<(31-c->dec_firsttablen); long lo=0,hi=0;
long lo=0,hi=0;
for(i=0;i<tabn;i++){
for(i=0;i<tabn;i++){ ogg_uint32_t word=i<<(32-c->dec_firsttablen);
ogg_uint32_t word=i<<(32-c->dec_firsttablen); if(c->dec_firsttable[bitreverse(word)]==0){
if(c->dec_firsttable[bitreverse(word)]==0){ while((lo+1)<n && c->codelist[lo+1]<=word)lo++;
while((lo+1)<n && c->codelist[lo+1]<=word)lo++; while( hi<n && word>=(c->codelist[hi]&mask))hi++;
while( hi<n && word>=(c->codelist[hi]&mask))hi++;
/* we only actually have 15 bits per hint to play with here.
/* we only actually have 15 bits per hint to play with here. In order to overflow gracefully (nothing breaks, efficiency
In order to overflow gracefully (nothing breaks, efficiency just drops), encode as the difference from the extremes. */
just drops), encode as the difference from the extremes. */ {
{ unsigned long loval=lo;
unsigned long loval=lo; unsigned long hival=n-hi;
unsigned long hival=n-hi;
if(loval>0x7fff)loval=0x7fff;
if(loval>0x7fff)loval=0x7fff; if(hival>0x7fff)hival=0x7fff;
if(hival>0x7fff)hival=0x7fff; c->dec_firsttable[bitreverse(word)]=
c->dec_firsttable[bitreverse(word)]= 0x80000000UL | (loval<<15) | hival;
0x80000000UL | (loval<<15) | hival; }
} }
} }
} }
} }
ogg_tmpmalloc_free(pos); ogg_tmpmalloc_free(pos);
return(0); return(0);
err_out: err_out: