Commit 32939197 authored by Monty's avatar Monty

More fixes to handle the null-entry codebook case. It appears the

failure to handle this case affects more of the code than thought;
many of the old low-bitrate crash cases trace back to this problem.

This also affects tremor.  These changes are not yet thoroughly
tested.


svn path=/trunk/vorbis/; revision=13172
parent a527fa59
...@@ -311,7 +311,7 @@ STIN long decode_packed_entry_number(codebook *book, oggpack_buffer *b){ ...@@ -311,7 +311,7 @@ STIN long decode_packed_entry_number(codebook *book, oggpack_buffer *b){
int read=book->dec_maxlength; int read=book->dec_maxlength;
long lo,hi; long lo,hi;
long lok = oggpack_look(b,book->dec_firsttablen); long lok = oggpack_look(b,book->dec_firsttablen);
if (lok >= 0) { if (lok >= 0) {
long entry = book->dec_firsttable[lok]; long entry = book->dec_firsttable[lok];
if(entry&0x80000000UL){ if(entry&0x80000000UL){
...@@ -325,24 +325,24 @@ STIN long decode_packed_entry_number(codebook *book, oggpack_buffer *b){ ...@@ -325,24 +325,24 @@ STIN long decode_packed_entry_number(codebook *book, oggpack_buffer *b){
lo=0; lo=0;
hi=book->used_entries; hi=book->used_entries;
} }
lok = oggpack_look(b, read); lok = oggpack_look(b, read);
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)return -1;
/* bisect search for the codeword in the ordered list */ /* bisect search for the codeword in the ordered list */
{ {
ogg_uint32_t testword=bitreverse((ogg_uint32_t)lok); ogg_uint32_t testword=bitreverse((ogg_uint32_t)lok);
while(hi-lo>1){ while(hi-lo>1){
long p=(hi-lo)>>1; long p=(hi-lo)>>1;
long test=book->codelist[lo+p]>testword; long test=book->codelist[lo+p]>testword;
lo+=p&(test-1); lo+=p&(test-1);
hi-=p&(-test); hi-=p&(-test);
} }
if(book->dec_codelengths[lo]<=read){ if(book->dec_codelengths[lo]<=read){
oggpack_adv(b, book->dec_codelengths[lo]); oggpack_adv(b, book->dec_codelengths[lo]);
return(lo); return(lo);
...@@ -350,6 +350,7 @@ STIN long decode_packed_entry_number(codebook *book, oggpack_buffer *b){ ...@@ -350,6 +350,7 @@ STIN long decode_packed_entry_number(codebook *book, oggpack_buffer *b){
} }
oggpack_adv(b, read); oggpack_adv(b, read);
return(-1); return(-1);
} }
...@@ -369,104 +370,121 @@ STIN long decode_packed_entry_number(codebook *book, oggpack_buffer *b){ ...@@ -369,104 +370,121 @@ STIN long decode_packed_entry_number(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,float *a,oggpack_buffer *b,int n){ long vorbis_book_decodevs_add(codebook *book,float *a,oggpack_buffer *b,int n){
int step=n/book->dim; if(book->used_entries>0){
long *entry = alloca(sizeof(*entry)*step); int step=n/book->dim;
float **t = alloca(sizeof(*t)*step); long *entry = alloca(sizeof(*entry)*step);
int i,j,o; float **t = alloca(sizeof(*t)*step);
int i,j,o;
for (i = 0; i < step; i++) {
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];
} }
for(i=0,o=0;i<book->dim;i++,o+=step)
for (j=0;j<step;j++)
a[o+j]+=t[j][i];
return(0); return(0);
} }
long vorbis_book_decodev_add(codebook *book,float *a,oggpack_buffer *b,int n){ long vorbis_book_decodev_add(codebook *book,float *a,oggpack_buffer *b,int n){
int i,j,entry; if(book->used_entries>0){
float *t; int i,j,entry;
float *t;
if(book->dim>8){
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++];
}
}else{
for(i=0;i<n;){
entry = decode_packed_entry_number(book,b);
if(entry==-1)return(-1);
t = book->valuelist+entry*book->dim;
j=0;
switch((int)book->dim){
case 8:
a[i++]+=t[j++];
case 7:
a[i++]+=t[j++];
case 6:
a[i++]+=t[j++];
case 5:
a[i++]+=t[j++];
case 4:
a[i++]+=t[j++];
case 3:
a[i++]+=t[j++];
case 2:
a[i++]+=t[j++];
case 1:
a[i++]+=t[j++];
case 0:
break;
}
}
}
}
return(0);
}
if(book->dim>8){ long vorbis_book_decodev_set(codebook *book,float *a,oggpack_buffer *b,int n){
if(book->used_entries>0){
int i,j,entry;
float *t;
for(i=0;i<n;){ for(i=0;i<n;){
entry = decode_packed_entry_number(book,b); entry = decode_packed_entry_number(book,b);
if(entry==-1)return(-1); if(entry==-1)return(-1);
t = book->valuelist+entry*book->dim; t = book->valuelist+entry*book->dim;
for (j=0;j<book->dim;) for (j=0;j<book->dim;)
a[i++]+=t[j++]; a[i++]=t[j++];
} }
}else{ }else{
int i,j;
for(i=0;i<n;){ for(i=0;i<n;){
entry = decode_packed_entry_number(book,b); for (j=0;j<book->dim;)
if(entry==-1)return(-1); a[i++]=0.f;
t = book->valuelist+entry*book->dim;
j=0;
switch((int)book->dim){
case 8:
a[i++]+=t[j++];
case 7:
a[i++]+=t[j++];
case 6:
a[i++]+=t[j++];
case 5:
a[i++]+=t[j++];
case 4:
a[i++]+=t[j++];
case 3:
a[i++]+=t[j++];
case 2:
a[i++]+=t[j++];
case 1:
a[i++]+=t[j++];
case 0:
break;
}
} }
}
return(0);
}
long vorbis_book_decodev_set(codebook *book,float *a,oggpack_buffer *b,int n){
int i,j,entry;
float *t;
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++];
} }
return(0); return(0);
} }
long vorbis_book_decodevv_add(codebook *book,float **a,long offset,int ch, long vorbis_book_decodevv_add(codebook *book,float **a,long offset,int ch,
oggpack_buffer *b,int n){ oggpack_buffer *b,int n){
long i,j,entry; long i,j,entry;
int chptr=0; int chptr=0;
if(book->used_entries>0){
for(i=offset/ch;i<(offset+n)/ch;){ for(i=offset/ch;i<(offset+n)/ch;){
entry = decode_packed_entry_number(book,b); entry = decode_packed_entry_number(book,b);
if(entry==-1)return(-1); if(entry==-1)return(-1);
{ {
const float *t = book->valuelist+entry*book->dim; const float *t = book->valuelist+entry*book->dim;
for (j=0;j<book->dim;j++){ for (j=0;j<book->dim;j++){
a[chptr++][i]+=t[j]; a[chptr++][i]+=t[j];
if(chptr==ch){ if(chptr==ch){
chptr=0; chptr=0;
i++; i++;
}
} }
} }
} }
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
******************************************************************** ********************************************************************
function: basic shared codebook operations function: basic shared codebook operations
last mod: $Id: sharedbook.c,v 1.29 2002/10/11 07:44:28 xiphmont Exp $ last mod: $Id$
********************************************************************/ ********************************************************************/
...@@ -329,30 +329,31 @@ int vorbis_book_init_decode(codebook *c,const static_codebook *s){ ...@@ -329,30 +329,31 @@ 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;
/* two different remappings go on here. if(n>0){
First, we collapse the likely sparse codebook down only to /* two different remappings go on here.
actually represented values/words. This collapsing needs to be
indexed as map-valueless books are used to encode original entry First, we collapse the likely sparse codebook down only to
positions as integers. actually represented values/words. This collapsing needs to be
indexed as map-valueless books are used to encode original entry
Second, we reorder all vectors, including the entry index above, positions as integers.
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=alloca(sizeof(*codep)*n); ogg_uint32_t **codep=alloca(sizeof(*codep)*n);
if(codes==NULL)goto err_out; if(codes==NULL)goto err_out;
for(i=0;i<n;i++){ for(i=0;i<n;i++){
codes[i]=bitreverse(codes[i]); codes[i]=bitreverse(codes[i]);
codep[i]=codes+i; codep[i]=codes+i;
} }
qsort(codep,n,sizeof(*codep),sort32a); qsort(codep,n,sizeof(*codep),sort32a);
sortindex=alloca(n*sizeof(*sortindex)); sortindex=alloca(n*sizeof(*sortindex));
c->codelist=_ogg_malloc(n*sizeof(*c->codelist)); c->codelist=_ogg_malloc(n*sizeof(*c->codelist));
/* the index is a reverse index */ /* the index is a reverse index */
...@@ -364,66 +365,66 @@ int vorbis_book_init_decode(codebook *c,const static_codebook *s){ ...@@ -364,66 +365,66 @@ 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->dec_index=_ogg_malloc(n*sizeof(*c->dec_index));
for(n=0,i=0;i<s->entries;i++)
if(s->lengthlist[i]>0)
c->dec_index[sortindex[n++]]=i;
c->dec_codelengths=_ogg_malloc(n*sizeof(*c->dec_codelengths));
for(n=0,i=0;i<s->entries;i++)
if(s->lengthlist[i]>0)
c->dec_codelengths[sortindex[n++]]=s->lengthlist[i];
c->dec_firsttablen=_ilog(c->used_entries)-4; /* this is magic */
if(c->dec_firsttablen<5)c->dec_firsttablen=5;
if(c->dec_firsttablen>8)c->dec_firsttablen=8;
tabn=1<<c->dec_firsttablen;
c->dec_firsttable=_ogg_calloc(tabn,sizeof(*c->dec_firsttable));
c->dec_maxlength=0;
for(i=0;i<n;i++){ c->valuelist=_book_unquantize(s,n,sortindex);
if(c->dec_maxlength<c->dec_codelengths[i]) c->dec_index=_ogg_malloc(n*sizeof(*c->dec_index));
c->dec_maxlength=c->dec_codelengths[i];
if(c->dec_codelengths[i]<=c->dec_firsttablen){ for(n=0,i=0;i<s->entries;i++)
ogg_uint32_t orig=bitreverse(c->codelist[i]); if(s->lengthlist[i]>0)
for(j=0;j<(1<<(c->dec_firsttablen-c->dec_codelengths[i]));j++) c->dec_index[sortindex[n++]]=i;
c->dec_firsttable[orig|(j<<c->dec_codelengths[i])]=i+1;
c->dec_codelengths=_ogg_malloc(n*sizeof(*c->dec_codelengths));
for(n=0,i=0;i<s->entries;i++)
if(s->lengthlist[i]>0)
c->dec_codelengths[sortindex[n++]]=s->lengthlist[i];
c->dec_firsttablen=_ilog(c->used_entries)-4; /* this is magic */
if(c->dec_firsttablen<5)c->dec_firsttablen=5;
if(c->dec_firsttablen>8)c->dec_firsttablen=8;
tabn=1<<c->dec_firsttablen;
c->dec_firsttable=_ogg_calloc(tabn,sizeof(*c->dec_firsttable));
c->dec_maxlength=0;
for(i=0;i<n;i++){
if(c->dec_maxlength<c->dec_codelengths[i])
c->dec_maxlength=c->dec_codelengths[i];
if(c->dec_codelengths[i]<=c->dec_firsttablen){
ogg_uint32_t orig=bitreverse(c->codelist[i]);
for(j=0;j<(1<<(c->dec_firsttablen-c->dec_codelengths[i]));j++)
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; }
} }
} }
} }
} }
return(0); return(0);
err_out: err_out:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment