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){
int read=book->dec_maxlength;
long lo,hi;
long lok = oggpack_look(b,book->dec_firsttablen);
if (lok >= 0) {
long entry = book->dec_firsttable[lok];
if(entry&0x80000000UL){
......@@ -325,24 +325,24 @@ STIN long decode_packed_entry_number(codebook *book, oggpack_buffer *b){
lo=0;
hi=book->used_entries;
}
lok = oggpack_look(b, read);
while(lok<0 && read>1)
lok = oggpack_look(b, --read);
if(lok<0)return -1;
/* bisect search for the codeword in the ordered list */
{
ogg_uint32_t testword=bitreverse((ogg_uint32_t)lok);
while(hi-lo>1){
long p=(hi-lo)>>1;
long test=book->codelist[lo+p]>testword;
lo+=p&(test-1);
hi-=p&(-test);
}
}
if(book->dec_codelengths[lo]<=read){
oggpack_adv(b, book->dec_codelengths[lo]);
return(lo);
......@@ -350,6 +350,7 @@ STIN long decode_packed_entry_number(codebook *book, oggpack_buffer *b){
}
oggpack_adv(b, read);
return(-1);
}
......@@ -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 *********/
long vorbis_book_decode(codebook *book, oggpack_buffer *b){
long packed_entry=decode_packed_entry_number(book,b);
if(packed_entry>=0)
return(book->dec_index[packed_entry]);
if(book->used_entries>0){
long packed_entry=decode_packed_entry_number(book,b);
if(packed_entry>=0)
return(book->dec_index[packed_entry]);
}
/* 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 *************************************/
long vorbis_book_decodevs_add(codebook *book,float *a,oggpack_buffer *b,int n){
int step=n/book->dim;
long *entry = alloca(sizeof(*entry)*step);
float **t = alloca(sizeof(*t)*step);
int i,j,o;
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;
if(book->used_entries>0){
int step=n/book->dim;
long *entry = alloca(sizeof(*entry)*step);
float **t = alloca(sizeof(*t)*step);
int i,j,o;
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];
}
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);
}
long vorbis_book_decodev_add(codebook *book,float *a,oggpack_buffer *b,int n){
int i,j,entry;
float *t;
if(book->used_entries>0){
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;){
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++];
a[i++]=t[j++];
}
}else{
int i,j;
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;
}
for (j=0;j<book->dim;)
a[i++]=0.f;
}
}
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);
}
long vorbis_book_decodevv_add(codebook *book,float **a,long offset,int ch,
oggpack_buffer *b,int n){
long i,j,entry;
int chptr=0;
for(i=offset/ch;i<(offset+n)/ch;){
entry = decode_packed_entry_number(book,b);
if(entry==-1)return(-1);
{
const float *t = book->valuelist+entry*book->dim;
for (j=0;j<book->dim;j++){
a[chptr++][i]+=t[j];
if(chptr==ch){
chptr=0;
i++;
if(book->used_entries>0){
for(i=offset/ch;i<(offset+n)/ch;){
entry = decode_packed_entry_number(book,b);
if(entry==-1)return(-1);
{
const float *t = book->valuelist+entry*book->dim;
for (j=0;j<book->dim;j++){
a[chptr++][i]+=t[j];
if(chptr==ch){
chptr=0;
i++;
}
}
}
}
......
......@@ -11,7 +11,7 @@
********************************************************************
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){
c->used_entries=n;
c->dim=s->dim;
/* 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
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. */
if(n>0){
/* 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
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. */
{
/* perform sort */
ogg_uint32_t *codes=_make_words(s->lengthlist,s->entries,c->used_entries);
ogg_uint32_t **codep=alloca(sizeof(*codep)*n);
if(codes==NULL)goto err_out;
for(i=0;i<n;i++){
codes[i]=bitreverse(codes[i]);
codep[i]=codes+i;
}
qsort(codep,n,sizeof(*codep),sort32a);
sortindex=alloca(n*sizeof(*sortindex));
c->codelist=_ogg_malloc(n*sizeof(*c->codelist));
/* the index is a reverse index */
......@@ -364,66 +365,66 @@ int vorbis_book_init_decode(codebook *c,const static_codebook *s){
for(i=0;i<n;i++)
c->codelist[sortindex[i]]=codes[i];
_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++){
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;
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++){
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
hints for the non-direct-hits */
{
ogg_uint32_t mask=0xfffffffeUL<<(31-c->dec_firsttablen);
long lo=0,hi=0;
for(i=0;i<tabn;i++){
ogg_uint32_t word=i<<(32-c->dec_firsttablen);
if(c->dec_firsttable[bitreverse(word)]==0){
while((lo+1)<n && c->codelist[lo+1]<=word)lo++;
while( hi<n && word>=(c->codelist[hi]&mask))hi++;
/* we only actually have 15 bits per hint to play with here.
In order to overflow gracefully (nothing breaks, efficiency
just drops), encode as the difference from the extremes. */
{
unsigned long loval=lo;
unsigned long hival=n-hi;
if(loval>0x7fff)loval=0x7fff;
if(hival>0x7fff)hival=0x7fff;
c->dec_firsttable[bitreverse(word)]=
0x80000000UL | (loval<<15) | hival;
/* now fill in 'unused' entries in the firsttable with hi/lo search
hints for the non-direct-hits */
{
ogg_uint32_t mask=0xfffffffeUL<<(31-c->dec_firsttablen);
long lo=0,hi=0;
for(i=0;i<tabn;i++){
ogg_uint32_t word=i<<(32-c->dec_firsttablen);
if(c->dec_firsttable[bitreverse(word)]==0){
while((lo+1)<n && c->codelist[lo+1]<=word)lo++;
while( hi<n && word>=(c->codelist[hi]&mask))hi++;
/* we only actually have 15 bits per hint to play with here.
In order to overflow gracefully (nothing breaks, efficiency
just drops), encode as the difference from the extremes. */
{
unsigned long loval=lo;
unsigned long hival=n-hi;
if(loval>0x7fff)loval=0x7fff;
if(hival>0x7fff)hival=0x7fff;
c->dec_firsttable[bitreverse(word)]=
0x80000000UL | (loval<<15) | hival;
}
}
}
}
}
return(0);
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