[xiph-commits] r13172 - trunk/vorbis/lib

xiphmont at svn.xiph.org xiphmont at svn.xiph.org
Thu Jun 21 22:29:52 PDT 2007


Author: xiphmont
Date: 2007-06-21 22:29:52 -0700 (Thu, 21 Jun 2007)
New Revision: 13172

Modified:
   trunk/vorbis/lib/codebook.c
   trunk/vorbis/lib/sharedbook.c
Log:
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.



Modified: trunk/vorbis/lib/codebook.c
===================================================================
--- trunk/vorbis/lib/codebook.c	2007-06-22 03:51:56 UTC (rev 13171)
+++ trunk/vorbis/lib/codebook.c	2007-06-22 05:29:52 UTC (rev 13172)
@@ -311,7 +311,7 @@
   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 @@
     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 @@
   }
   
   oggpack_adv(b, read);
+
   return(-1);
 }
 
@@ -369,104 +370,121 @@
 
 /* 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++;
+	  }
 	}
       }
     }

Modified: trunk/vorbis/lib/sharedbook.c
===================================================================
--- trunk/vorbis/lib/sharedbook.c	2007-06-22 03:51:56 UTC (rev 13171)
+++ trunk/vorbis/lib/sharedbook.c	2007-06-22 05:29:52 UTC (rev 13172)
@@ -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 @@
   c->used_entries=n;
   c->dim=s->dim;
 
-  /* two different remappings go on here.  
+  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. */
 
-     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 @@
     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:



More information about the commits mailing list