More fixes to handle the null-entry codebook case. It appears the
authorMonty <xiphmont@xiph.org>
Fri, 22 Jun 2007 05:29:52 +0000 (05:29 +0000)
committerMonty <xiphmont@xiph.org>
Fri, 22 Jun 2007 05:29:52 +0000 (05:29 +0000)
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

lib/codebook.c
lib/sharedbook.c

index e689756..e47a8ec 100644 (file)
@@ -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++;
+         }
        }
       }
     }
index 11c02f6..c5f1988 100644 (file)
@@ -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: