[xiph-cvs] cvs commit: ogg/src bitwise.c buffer.c ogginternal.h stream.c

Monty xiphmont at xiph.org
Fri Mar 14 17:26:10 PST 2003



xiphmont    03/03/14 20:26:09

  Modified:    src      Tag: libogg2-zerocopy bitwise.c buffer.c
                        ogginternal.h stream.c
  Log:
  More work in progress.

Revision  Changes    Path
No                   revision

<p>No                   revision

<p>1.14.2.9  +363 -393  ogg/src/bitwise.c

Index: bitwise.c
===================================================================
RCS file: /usr/local/cvsroot/ogg/src/bitwise.c,v
retrieving revision 1.14.2.8
retrieving revision 1.14.2.9
diff -u -r1.14.2.8 -r1.14.2.9
--- bitwise.c	6 Mar 2003 23:13:36 -0000	1.14.2.8
+++ bitwise.c	15 Mar 2003 01:26:09 -0000	1.14.2.9
@@ -11,7 +11,7 @@
  ********************************************************************
 
   function: pack variable sized words into an octet stream
-  last mod: $Id: bitwise.c,v 1.14.2.8 2003/03/06 23:13:36 xiphmont Exp $
+  last mod: $Id: bitwise.c,v 1.14.2.9 2003/03/15 01:26:09 xiphmont Exp $
 
  ********************************************************************/
 
@@ -50,16 +50,16 @@
 
 static void _oggpack_extend(oggpack_buffer *b){
   if(b->head){
-    b->head->used=b->head->size;
-    b->count+=b->head->size;
-    b->head->next=ogg_buffer_alloc(b->owner,OGGPACK_CHUNKSIZE);
-    b->head=b->head->next;
+    b->head->length=b->head->buffer->size; /* only because ->begin is always
+					      zero in a write buffer */
+    b->count+=b->head->length;
+    b->head=ogg_buffer_extend(b->head,OGGPACK_CHUNKSIZE);
   }else{
     b->head=b->tail=ogg_buffer_alloc(b->owner,OGGPACK_CHUNKSIZE);
   }
 
-  b->headptr=b->head->data;
-  b->headend=b->head->size;
+  b->headptr=b->head->buffer->data;
+  b->headend=b->head->buffer->size;
 }
 
 /* Takes only up to 32 bits. */
@@ -159,32 +159,21 @@
     oggpackB_write(b,0,bits);
 }
 
-void oggpack_writebuffer(oggpack_buffer *b, ogg_buffer_reference *r){
-  /* unlike ogg_buffer_references, the oggpack write buffers do not
-     have any potential prefixed/unused ogg_buffer data */
-
-  b->head->used=b->headptr-b->head->data+(b->headbit+7)/8;
-  r->buffer=b->tail;
-  r->begin=0;
-  r->length=oggpack_bytes(b);
-  r->owner=b->owner;
+ogg_reference *oggpack_writebuffer(oggpack_buffer *b){
+  /* unlike generic ogg_buffer_references, the oggpack write buffers
+     will never have any potential prefixed/unused ogg_buffer data */
 
+  b->head->length=b->headptr-b->head->buffer->data+(b->headbit+7)/8;
+  return(b->tail);
 }
 
-void oggpackB_writebuffer(oggpack_buffer *b, ogg_buffer_reference *r){
-  oggpack_writebuffer(b,r);
+ogg_reference *oggpackB_writebuffer(oggpack_buffer *b){
+  return oggpack_writebuffer(b);
 }
 
 /* frees and deallocates the oggpack_buffer ogg_buffer usage */
 void oggpack_writeclear(oggpack_buffer *b){
-  ogg_buffer *ptr=b->tail;
-
-  while(ptr){
-    ogg_buffer *next=ptr->next;
-    ogg_buffer_release(ptr,b->owner);
-    ptr=next;
-  }
-   
+  ogg_buffer_release(b->tail);
   memset(b,0,sizeof(*b));
 }
 
@@ -192,101 +181,90 @@
   oggpack_writeclear(b);
 }
 
-void oggpack_readinit(oggpack_buffer *b,ogg_buffer_reference *r){
-  int begin=r->begin;
-  memset(b,0,sizeof(*b));
-
-  b->owner=r->owner;
-  b->head=r->buffer;
+/* mark read process as having run off the end */
+static void _adv_halt(oggpack_buffer *b){
+  b->headptr=b->head->buffer->data+b->head->begin+b->head->length;
+  b->headend=-1;
+  b->headbit=0;
+}
 
-  /* advance head ptr to beginning of reference */
-  while(begin>=b->head->used){
-    ogg_buffer *next=b->head->next;
-    begin-=b->head->used;
-    //oggbuffer_release(b->head);
-    b->head=next;
-  }
-
-  b->tail=r->buffer;  
-  b->count= -begin;
-  b->length=r->length+begin;
-  b->headptr=b->head->data+begin;
+/* spans forward, skipping as many bytes as headend is negative; if
+   headend is zero, simply finds next byte.  If we're up to the end
+   of the buffer, leaves headend at zero.  If we've read past the end,
+   halt the decode process. */
+static void _span(oggpack_buffer *b){
+  while(b->headend<1){
+    if(b->head->next){
+      b->count+=b->head->length;
+      b->head=b->head->next;
+      b->headptr=b->head->buffer->data+b->head->begin-b->headend; 
+      b->headend+=b->head->length;      
+    }else{
+      /* we've either met the end of decode, or gone past it. halt
+         only if we're past */
+      if(b->headend<0)
+	/* read has fallen off the end */
+	_adv_halt(b);
 
-  if(b->head->used>b->length){
-    b->headend=b->length-begin;
-  }else{
-    b->headend=b->head->used-begin;
+      break;
+    }
   }
 }
 
-void oggpackB_readinit(oggpack_buffer *b,ogg_buffer_reference *r){
+void oggpack_readinit(oggpack_buffer *b,ogg_reference *r){
+  memset(b,0,sizeof(*b));
+
+  b->tail=b->head=r;
+  b->count=0;
+  b->headptr=b->head->buffer->data+b->head->begin;
+  b->headend=b->head->length;
+  _span(b);
+}
+
+void oggpackB_readinit(oggpack_buffer *b,ogg_reference *r){
   oggpack_readinit(b,r);
 }
 
+#define _lookspan()   while(!end){\
+                        head=head->next;\
+                        if(!head) return -1;\
+                        ptr=head->buffer->data + head->begin;\
+                        end=head->length;\
+                      }
+
 /* Read in bits without advancing the bitptr; bits <= 32 */
 int oggpack_look(oggpack_buffer *b,int bits,unsigned long *ret){
   unsigned long m=mask[bits];
 
   bits+=b->headbit;
 
-  if(bits > b->headend<<3){
+  if(bits >= b->headend*8){
     int            end=b->headend;
     unsigned char *ptr=b->headptr;
-    ogg_buffer    *head=b->head;
-
-    /* headend's semantic usage is complex; it's a 'check carefully
-       past this point' marker.  It can mean we're either at the end
-       of a buffer fragment, or done reading. */
+    ogg_reference *head=b->head;
 
-    /* check to see if there are enough bytes left in next fragments
-       [if any] to fufill read request. */
-
-    if(bits > (b->length-b->head->used+b->headend)*8)
-      return -1;
-
-    /* At this point, we're certain we span and that there's sufficient 
-       data in the following buffer[s] to fufill the read */
-
-    while(!end){
-      ptr=b->head->next->data;
-      end=b->head->next->used; /* this value would be incorrect if we
-                                  didn't already know that we're not
-                                  going to fall off the absolute end
-                                  of the buffer */
-    }
-    *ret=*ptr++>>b->headbit;
-    if(bits>8){
-      --end;
-      while(!end){
-	head=head->next;
-	ptr=head->data;
-	end=head->used;
-      }
-      *ret|=*ptr++<<(8-b->headbit);  
-      if(bits>16){
+    if(end<0)return -1;
+    
+    if(bits){
+      _lookspan();
+      *ret=*ptr++>>b->headbit;
+      if(bits>8){
         --end;
-	while(!end){
-	  head=head->next;
-	  ptr=head->data;
-	  end=head->used;
-	}
-	*ret|=*ptr++<<(16-b->headbit);  
-	if(bits>24){
+	_lookspan();
+	*ret|=*ptr++<<(8-b->headbit);  
+	if(bits>16){
           --end;
-	  while(!end){
-	    head=head->next;
-	    ptr=head->data;
-	    end=head->used;
-	  }
-	  *ret|=*ptr++<<(24-b->headbit);  
-	  if(bits>32 && b->headbit){
+	  _lookspan();
+	  *ret|=*ptr++<<(16-b->headbit);  
+	  if(bits>24){
             --end;
-	    while(!end){
-	      head=head->next;
-	      ptr=head->data;
-	      end=head->used;
+	    _lookspan();
+	    *ret|=*ptr++<<(24-b->headbit);  
+	    if(bits>32 && b->headbit){
+	      --end;
+	      _lookspan();
+	      *ret|=*ptr<<(32-b->headbit);
             }
-	    *ret|=*ptr<<(32-b->headbit);
           }
         }
       }
@@ -319,62 +297,33 @@
 
   bits+=b->headbit;
 
-  if(bits > b->headend<<3){
+  if(bits >= b->headend<<3){
     int            end=b->headend;
     unsigned char *ptr=b->headptr;
-    ogg_buffer    *head=b->head;
-    
-    /* headend's semantic usage is complex; it's a 'check carefully
-       past this point' marker.  It can mean we're either at the end
-       of a buffer fragment, or done reading. */
-
-    /* check to see if there are enough bytes left in next fragments
-       [if any] to fufill read request. */
-
-    if(bits > (b->length-b->head->used+b->headend)*8)
-      return -1;
+    ogg_reference *head=b->head;
 
-    /* At this point, we're certain we span and that there's sufficient 
-       data in the following buffer[s] to fufill the read */
-
-    while(!end){
-      head=head->next;
-      ptr=head->data;
-      end=head->used;
-    }
-    *ret=*ptr++<<(24+b->headbit);
-    if(bits>8){
-      --end;
-      if(!end){
-	head=head->next;
-	ptr=head->data;
-	end=head->used;
-      }
-      *ret|=*ptr++<<(16+b->headbit);   
-      if(bits>16){
+    if(end<0)return -1;
+    
+    if(bits){
+      _lookspan();
+      *ret=*ptr++<<(24+b->headbit);
+      if(bits>8){
         --end;
-	if(!end){
-	  head=head->next;
-	  ptr=head->data;
-	  end=head->used;
-	}
-	*ret|=*ptr++<<(8+b->headbit);  
-	if(bits>24){
+	_lookspan();
+	*ret|=*ptr++<<(16+b->headbit);   
+	if(bits>16){
           --end;
-	  if(!end){
-	    head=head->next;
-	    ptr=head->data;
-	    end=head->used;
-	  }
-	  *ret|=*ptr++<<(b->headbit);  
-	  if(bits>32 && b->headbit){
+	  _lookspan();
+	  *ret|=*ptr++<<(8+b->headbit);  
+	  if(bits>24){
             --end;
-	    while(!end){
-	      head=head->next;
-	      ptr=head->data;
-	      end=head->used;
+	    _lookspan();
+	    *ret|=*ptr++<<(b->headbit);  
+	    if(bits>32 && b->headbit){
+	      --end;
+	      _lookspan();
+	      *ret|=*ptr>>(8-b->headbit);
             }
-	    *ret|=*ptr>>(8-b->headbit);
           }
         }
       }
@@ -401,46 +350,13 @@
 }
 
 long oggpack_look1(oggpack_buffer *b){
-  if(!b->headend) return (-1);
-  return((b->headptr[0]>>b->headbit)&1);
+  if(b->headend<1)return -1;
+  return (b->headptr[0]>>b->headbit)&1;
 }
 
 long oggpackB_look1(oggpack_buffer *b){
-  if(!b->headend) return (-1);
-  return((b->headptr[0]>>(7-b->headbit))&1);
-}
-
-static void _oggpack_adv_halt(oggpack_buffer *b){
-  /* implicit; called only when b->length<=b->head->used */
-  b->headptr=b->head->data+b->length;
-  b->headend=0;
-  b->headbit=0;
-}
-
-static void _oggpack_spanner(oggpack_buffer *b){
-  while(b->headend<1){
-    if(b->length-b->head->used>0){
-      /* on to the next fragment */
-      
-      b->count+=b->head->used;
-      b->length-=b->head->used;
-      b->head=b->head->next;
-      b->headptr=b->head->data-b->headend;
-      
-      if(b->length<b->head->used){
-	b->headend+=b->length;
-      }else{
-	b->headend+=b->head->used;
-      }
-      
-    }else{
-      
-      /* no more, bring it to a halt */
-      _oggpack_adv_halt(b);
-      break;
-
-    }
-  }
+  if(b->headend<1)return -1;
+  return (b->headptr[0]>>(7-b->headbit))&1;
 }
 
 /* limited to 32 at a time */
@@ -449,7 +365,7 @@
   b->headend-=bits/8;
   b->headbit=bits&7;
   b->headptr+=bits/8;
-  _oggpack_spanner(b);
+  _span(b);
 }
 
 void oggpackB_adv(oggpack_buffer *b,int bits){
@@ -457,61 +373,89 @@
 }
 
 void oggpack_adv1(oggpack_buffer *b){
-  if(++(b->headbit)>7){
-    b->headbit=0;
-    ++b->headptr;
-    --b->headend;  
-    _oggpack_spanner(b);
-  }
+  oggpack_adv(b,1);
 }
 
 void oggpackB_adv1(oggpack_buffer *b){
   oggpack_adv1(b);
 }
 
+/* spans forward and finds next byte.  Never halts */
+static void _span_one(oggpack_buffer *b){
+  while(b->headend<1){
+    if(b->head->next){
+      b->count+=b->head->length;
+      b->head=b->head->next;
+      b->headptr=b->head->buffer->data+b->head->begin; 
+      b->headend=b->head->length;      
+    }else
+      break;
+  }
+}
+
+static int _halt_one(oggpack_buffer *b){
+  if(b->headend<1){
+    _adv_halt(b);
+    return -1;
+  }
+  return 0;
+}
+
 /* bits <= 32 */
 int oggpack_read(oggpack_buffer *b,int bits,unsigned long *ret){
   unsigned long m=mask[bits];
 
   bits+=b->headbit;
 
-  if(bits > b->headend<<3){
+  if(bits >= b->headend<<3){
 
-    /* headend's semantic usage is complex; it's a 'check carefully
-       past this point' marker.  It can mean we're either at the end
-       of a buffer fragment, or done reading. */
-
-    /* check to see if there are enough bytes left in next fragments
-       [if any] to fufill read request. */
-
-    if(bits > (b->length-b->head->used+b->headend)*8){
-      _oggpack_adv_halt(b);
-      return -1;
-    }
-
-    if(!b->headend)_oggpack_spanner(b);
-    *ret=*b->headptr>>b->headbit;
-    if(bits>=8){
-      b->headptr++;
-      if(!--b->headend)_oggpack_spanner(b);
-      *ret|=*b->headptr<<(8-b->headbit);   
-      if(bits>=16){
-	b->headptr++;
-	if(!--b->headend)_oggpack_spanner(b);
-	*ret|=*b->headptr<<(16-b->headbit);  
-	if(bits>=24){
-	  b->headptr++;
-	  if(!--b->headend)_oggpack_spanner(b);
-	  *ret|=*b->headptr<<(24-b->headbit);  
-	  if(bits>=32){
-	    b->headptr++;
-	    if(!--b->headend)_oggpack_spanner(b);
-	    if(b->headbit)*ret|=*b->headptr<<(32-b->headbit);
+    if(b->headend<0)return(-1);
+    
+    if(bits){
+      if (_halt_one(b)) return -1;
+      *ret=*b->headptr>>b->headbit;
+      
+      if(bits>=8){
+	++b->headptr;
+	--b->headend;
+	_span_one(b);
+	if(bits>8){
+	  if (_halt_one(b)) return -1;
+	  *ret|=*b->headptr<<(8-b->headbit);   
+	  
+	  if(bits>=16){
+	    ++b->headptr;
+	    --b->headend;
+	    _span_one(b);
+	    if(bits>16){
+	      if (_halt_one(b)) return -1;
+	      *ret|=*b->headptr<<(16-b->headbit);  
+	      
+	      if(bits>=24){
+		++b->headptr;
+		--b->headend;
+		_span_one(b);
+		if(bits>24){
+		  if (_halt_one(b)) return -1;
+		  *ret|=*b->headptr<<(24-b->headbit);
+		  
+		  if(bits>=32){
+		    ++b->headptr;
+		    --b->headend;
+		    _span_one(b);
+		    if(bits>32){
+		      if (_halt_one(b)) return -1;
+		      if(b->headbit)*ret|=*b->headptr<<(32-b->headbit);
+		      
+		    }
+		  }
+		}
+	      }
+	    }
           }
         }
       }
     }
-    
   }else{
   
     *ret=b->headptr[0]>>b->headbit;
@@ -543,47 +487,57 @@
   
   bits+=b->headbit;
 
-  if(bits > b->headend<<3){
-    
-    /* headend's semantic usage is complex; it's a 'check carefully
-       past this point' marker.  It can mean we're either at the end
-       of a buffer fragment, or done reading. */
-
-    /* check to see if there are enough bytes left in next fragment
-       [if any] to fufill read request. Spanning more than one boundary
-       isn't possible so long as the ogg buffer abstraction enforces >
-       4 byte fragments, which it does. */
-
-    if(bits > (b->length-b->head->used+b->headend)*8){
-      _oggpack_adv_halt(b);
-      return -1;
-    }
-
-    if(!b->headend)_oggpack_spanner(b);
-    *ret=*b->headptr<<(24+b->headbit);
-    if(bits>=8){
-      b->headptr++;
-      if(!--b->headend)_oggpack_spanner(b);
-      *ret|=*b->headptr<<(16+b->headbit);   
-      if(bits>=16){
-	b->headptr++;
-	if(!--b->headend)_oggpack_spanner(b);
-	*ret|=*b->headptr<<(8+b->headbit);  
-	if(bits>=24){
-	  b->headptr++;
-	  if(!--b->headend)_oggpack_spanner(b);
-	  *ret|=*b->headptr<<(b->headbit);  
-	  if(bits>=32){
-	    b->headptr++;
-	    if(!--b->headend)_oggpack_spanner(b);
-	    if(b->headbit)*ret|=*b->headptr>>(8-b->headbit);
+  if(bits >= b->headend<<3){
+
+    if(b->headend<0)return(-1);
+
+    if(bits){
+      if (_halt_one(b)) return -1;
+      *ret=*b->headptr<<(24+b->headbit);
+      
+      if(bits>=8){
+	++b->headptr;
+	--b->headend;
+	_span_one(b);
+	if(bits>8){
+	  if (_halt_one(b)) return -1;
+	  *ret|=*b->headptr<<(16+b->headbit);   
+	  
+	  if(bits>=16){
+	    ++b->headptr;
+	    --b->headend;
+	    _span_one(b);
+	    if(bits>16){
+	      if (_halt_one(b)) return -1;
+	      *ret|=*b->headptr<<(8+b->headbit);  
+	      
+	      if(bits>=24){
+		++b->headptr;
+		--b->headend;
+		_span_one(b);
+		if(bits>24){
+		  if (_halt_one(b)) return -1;
+		  *ret|=*b->headptr<<(b->headbit);  
+		  
+		  if(bits>=32){
+		    ++b->headptr;
+		    --b->headend;
+		    _span_one(b);
+		    if(bits>32){
+		      if (_halt_one(b)) return -1;
+		      if(b->headbit)*ret|=*b->headptr>>(8-b->headbit);
+		      
+		    }
+		  }
+		}
+	      }
+	    }
           }
         }
       }
     }
-    
   }else{
-  
+
     *ret=b->headptr[0]<<(24+b->headbit);
     if(bits>8){
       *ret|=b->headptr[1]<<(16+b->headbit);  
@@ -607,43 +561,25 @@
 }
 
 long oggpack_read1(oggpack_buffer *b){
-  unsigned long ret;
-
-  if(!b->headend) return (-1UL);
-  ret=(b->headptr[0]>>b->headbit)&1;
-
-  if(++(b->headbit)>7){
-    b->headbit=0;
-    ++b->headptr;
-    --b->headend;  
-    if(b->headend<1)_oggpack_spanner(b);
-  }
-
-  return(ret);
+  unsigned long temp;
+  if(oggpack_read(b,1,&temp))return -1;
+  return temp;
 }
 
 long oggpackB_read1(oggpack_buffer *b){
-  unsigned long ret;
-
-  if(!b->headend) return (-1UL);
-  ret=(b->headptr[0]>>(7-b->headbit))&1;
-
-  if(++(b->headbit)>7){
-    b->headbit=0;
-    ++b->headptr;
-    --b->headend;  
-    if(b->headend<1)_oggpack_spanner(b);
-  }
-
-  return(ret);
+  unsigned long temp;
+  if(oggpackB_read(b,1,&temp))return -1;
+  return temp;
 }
 
 long oggpack_bytes(oggpack_buffer *b){
-  return(b->count+b->headptr-b->head->data+(b->headbit+7)/8);
+  return(b->count+b->headptr-b->head->buffer->data-b->head->begin+
+	 (b->headbit+7)/8);
 }
 
 long oggpack_bits(oggpack_buffer *b){
-  return((b->count+b->headptr-b->head->data)*8+b->headbit);
+  return((b->count+b->headptr-b->head->buffer->data-b->head->begin)*8+
+	 b->headbit);
 }
 
 long oggpackB_bytes(oggpack_buffer *b){
@@ -673,7 +609,7 @@
 oggpack_buffer o;
 oggpack_buffer r;
 ogg_buffer_state bs;
-ogg_buffer_reference or;
+ogg_reference *or;
 #define TESTWORDS 4096
 
 void report(char *in){
@@ -681,23 +617,22 @@
   exit(1);
 }
 
-int getbyte(ogg_buffer_reference *fb,int position){
-  ogg_buffer *b=fb->buffer;
-  while(b && position>=b->used){
-    position-=b->used;
-    b=b->next;
-    if(b==NULL){
+int getbyte(ogg_reference *or,int position){
+  while(or && position>=or->length){
+    position-=or->length;
+    or=or->next;
+    if(or==NULL){
       fprintf(stderr,"\n\tERROR: getbyte ran off end of buffer.\n");
       exit(1);
     }
   }
 
-  return(b->data[position]);
+  return(or->buffer->data[position+or->begin]);
 }
 
 void cliptest(unsigned long *b,int vals,int bits,int *comp,int compsize){
   long bytes,i,bitcount=0;
-  ogg_buffer_reference or;
+  ogg_reference *or;
 
   oggpack_writeinit(&o,&bs);
   for(i=0;i<vals;i++){
@@ -711,17 +646,17 @@
     }
   }
 
-  oggpack_writebuffer(&o,&or);
+  or=oggpack_writebuffer(&o);
   bytes=oggpack_bytes(&o);
 
   if(bytes!=compsize)report("wrong number of bytes!\n");
-  for(i=0;i<bytes;i++)if(getbyte(&or,i)!=comp[i]){
-    for(i=0;i<bytes;i++)fprintf(stderr,"%x %x\n",getbyte(&or,i),(int)comp[i]);
+  for(i=0;i<bytes;i++)if(getbyte(or,i)!=comp[i]){
+    for(i=0;i<bytes;i++)fprintf(stderr,"%x %x\n",getbyte(or,i),(int)comp[i]);
     report("wrote incorrect value!\n");
   }
 
   bitcount=0;
-  oggpack_readinit(&r,&or);
+  oggpack_readinit(&r,or);
   for(i=0;i<vals;i++){
     unsigned long test;
     int tbit=bits?bits:ilog(b[i]);
@@ -738,7 +673,9 @@
       if(oggpack_read1(&r)!=(int)(b[i]&mask[tbit]))
         report("read incorrect single bit value!\n");
     }else{
-      oggpack_read(&r,tbit,&test);
+      if(oggpack_read(&r,tbit,&test)){
+	report("premature end of data when reading!\n");
+      }
       if(test!=(b[i]&mask[tbit])){
         fprintf(stderr,"%ld) %lx %lx\n",i,(b[i]&mask[tbit]),test);
         report("read incorrect value!\n");
@@ -746,12 +683,11 @@
     }
     bitcount+=tbit;
 
-    if(bitcount!=oggpack_bits(&r)){
+    if(bitcount!=oggpack_bits(&r))
       report("wrong number of bits while reading!\n");
-    }
-    if((bitcount+7)/8!=oggpack_bytes(&r)){
+    if((bitcount+7)/8!=oggpack_bytes(&r))
       report("wrong number of bytes while reading!\n");
-    }
+
   }
   if(oggpack_bytes(&r)!=bytes)report("leftover bytes after read!\n");
   oggpack_writeclear(&o);
@@ -760,19 +696,19 @@
 
 void cliptestB(unsigned long *b,int vals,int bits,int *comp,int compsize){
   long bytes,i;
-  ogg_buffer_reference or;
+  ogg_reference *or;
 
   oggpackB_writeinit(&o,&bs);
   for(i=0;i<vals;i++)
     oggpackB_write(&o,b[i],bits?bits:ilog(b[i]));
-  oggpackB_writebuffer(&o,&or);
+  or=oggpackB_writebuffer(&o);
   bytes=oggpackB_bytes(&o);
   if(bytes!=compsize)report("wrong number of bytes!\n");
-  for(i=0;i<bytes;i++)if(getbyte(&or,i)!=comp[i]){
-    for(i=0;i<bytes;i++)fprintf(stderr,"%x %x\n",getbyte(&or,i),(int)comp[i]);
+  for(i=0;i<bytes;i++)if(getbyte(or,i)!=comp[i]){
+    for(i=0;i<bytes;i++)fprintf(stderr,"%x %x\n",getbyte(or,i),(int)comp[i]);
     report("wrote incorrect value!\n");
   }
-  oggpackB_readinit(&r,&or);
+  oggpackB_readinit(&r,or);
   for(i=0;i<vals;i++){
     unsigned long test;
     int tbit=bits?bits:ilog(b[i]);
@@ -787,7 +723,8 @@
       if(oggpackB_read1(&r)!=(int)(b[i]&mask[tbit]))
         report("read incorrect single bit value!\n");
     }else{
-      oggpackB_read(&r,tbit,&test);
+      if(oggpackB_read(&r,tbit,&test))
+	report("premature end of data when reading!\n");
       if(test!=(b[i]&mask[tbit]))
         report("read incorrect value!\n");
     }
@@ -798,12 +735,10 @@
 
 int flatten (unsigned char *flat){
   unsigned char *ptr=flat;
-  ogg_buffer *head;
-  oggpack_writebuffer(&o,&or);
-  head=or.buffer;
+  ogg_reference *head=oggpack_writebuffer(&o);
   while(head){
-    memcpy(ptr,head->data,head->used);
-    ptr+=head->used;
+    memcpy(ptr,head->buffer->data+head->begin,head->length);
+    ptr+=head->length;
     head=head->next;
   }
   return ptr-flat;
@@ -887,6 +822,15 @@
 
 }
 
+int bufferlength(ogg_reference *or){
+  int count=0;
+  while(or){
+    count+=or->length;
+    or=or->next;
+  }
+  return count;
+}
+
 int main(void){
   long bytes,i;
   static unsigned long testbuffer1[]=
@@ -954,7 +898,7 @@
 
   /* Test read/write together */
   /* Later we test against pregenerated bitstreams */
-  ogg_buffer_init(&bs,0);
+  ogg_buffer_init(&bs);
 
   fprintf(stderr,"\nSmall preclipped packing (LSb): ");
   cliptest(testbuffer1,test1size,0,one,onesize);
@@ -974,9 +918,9 @@
   oggpack_writeinit(&o,&bs);
   for(i=0;i<test2size;i++)
     oggpack_write(&o,large[i],32);
-  oggpack_writebuffer(&o,&or);
+  or=oggpack_writebuffer(&o);
   bytes=oggpack_bytes(&o);
-  oggpack_readinit(&r,&or);
+  oggpack_readinit(&r,or);
   for(i=0;i<test2size;i++){
     unsigned long test;
     if(oggpack_look(&r,32,&test)==-1)report("out of data. failed!");
@@ -1004,8 +948,8 @@
 
   fprintf(stderr,"\nTesting read past end (LSb): ");
   {
-    ogg_buffer lob={"\0\0\0\0\0\0\0\0",8,0,8,1};
-    ogg_buffer_reference lor={&lob,0,8,&bs};
+    ogg_buffer lob={"\0\0\0\0\0\0\0\0",8,0,{&bs}};
+    ogg_reference lor={&lob,0,8,0};
 
     oggpack_readinit(&r,&lor);
     for(i=0;i<64;i++){
@@ -1021,8 +965,8 @@
     }
   }
   {
-    ogg_buffer lob={"\0\0\0\0\0\0\0\0",8,0,8,1};
-    ogg_buffer_reference lor={&lob,0,8,&bs};
+    ogg_buffer lob={"\0\0\0\0\0\0\0\0",8,0,{&bs}};
+    ogg_reference lor={&lob,0,8,0};
     unsigned long test;
 
     oggpack_readinit(&r,&lor);
@@ -1069,9 +1013,9 @@
   oggpackB_writeinit(&o,&bs);
   for(i=0;i<test2size;i++)
     oggpackB_write(&o,large[i],32);
-  oggpackB_writebuffer(&o,&or);
+  or=oggpackB_writebuffer(&o);
   bytes=oggpackB_bytes(&o);
-  oggpackB_readinit(&r,&or);
+  oggpackB_readinit(&r,or);
   for(i=0;i<test2size;i++){
     unsigned long test;
     if(oggpackB_look(&r,32,&test)==-1)report("out of data. failed!");
@@ -1099,8 +1043,8 @@
 
   fprintf(stderr,"\nTesting read past end (MSb): ");
   {
-    ogg_buffer lob={"\0\0\0\0\0\0\0\0",8,0,8,1};
-    ogg_buffer_reference lor={&lob,0,8,&bs};
+    ogg_buffer lob={"\0\0\0\0\0\0\0\0",8,0,{&bs}};
+    ogg_reference lor={&lob,0,8,0};
     unsigned long test;
 
     oggpackB_readinit(&r,&lor);
@@ -1117,8 +1061,8 @@
     }
   }
   {
-    ogg_buffer lob={"\0\0\0\0\0\0\0\0",8,0,8,1};
-    ogg_buffer_reference lor={&lob,0,8,&bs};
+    ogg_buffer lob={"\0\0\0\0\0\0\0\0",8,0,{&bs}};
+    ogg_reference lor={&lob,0,8,0};
     unsigned long test;
     oggpackB_readinit(&r,&lor);
 
@@ -1145,13 +1089,13 @@
 
   /* now the scary shit: randomized testing */
 
-  for(i=0;i<1000;i++){
-    int j,count=0,count2=0,bitcount=0;
+  for(i=0;i<10000;i++){
+    int j,count2=0,bitcount=0;
     unsigned long values[TESTWORDS];
     int len[TESTWORDS];
     unsigned char flat[4*TESTWORDS]; /* max possible needed size */
 
-    fprintf(stderr,"\rRandomized testing (LSb)... (%ld)   ",1000-i);
+    fprintf(stderr,"\rRandomized testing (LSb)... (%ld)   ",10000-i);
     oggpack_writeinit(&o,&bs);
 
     /* generate a list of words and lengths */
@@ -1159,7 +1103,6 @@
     for(j=0;j<TESTWORDS;j++){
       values[j]=rand();
       len[j]=(rand()%33);
-      count+=len[j];
 
       oggpack_write(&o,values[j],len[j]);
 
@@ -1179,7 +1122,11 @@
 
     /* flatten the packbuffer out to a vector */
     count2=flatten(flat);
-    oggpackB_writeclear(&o);
+    if(count2<(bitcount+7)/8){
+      fprintf(stderr,"\nERROR: flattened write buffer incorrect length\n");
+      exit(1);
+    }
+    oggpack_writeclear(&o);
 
     /* verify against original list */
     lsbverify(values,len,flat);
@@ -1187,48 +1134,56 @@
     /* construct random-length buffer chain from flat vector; random
        byte starting offset within the length of the vector */
     {
-      ogg_buffer *obl=NULL,*ob=NULL;
+      ogg_reference *or=NULL,*orl=NULL;
       unsigned char *ptr=flat;
       
       /* build buffer chain */
       while(count2){
-	int ilen;
-	ogg_buffer *temp=_ogg_malloc(sizeof(*temp)); /* we don't bother
-                                                      freeing later;
-                                                      this is just a
-                                                      unit test */
-	if(obl)
-	  obl->next=temp;
-	else
-	  ob=temp;
+	int ilen=(rand()%32);
+	int ibegin=(rand()%32);
 
-	ilen=(rand()%32);
         if(ilen>count2)ilen=count2;
-	obl=temp;
-	obl->data=ptr;
-	obl->size=count2;
-	obl->used=ilen;
-	
+
+	if(or)
+	  orl=ogg_buffer_extend(orl,ilen+ibegin);
+	else
+	  or=orl=ogg_buffer_alloc(&bs,ilen+ibegin);
+
+	memcpy(orl->buffer->data+ibegin,ptr,ilen);
+       
+	orl->length=ilen;
+	orl->begin=ibegin;
+
         count2-=ilen;
         ptr+=ilen;
       }
-      /* build reference; choose a starting offset. */
+
+      if(bufferlength(or)!=(bitcount+7)/8){
+	fprintf(stderr,"\nERROR: buffer length incorrect after build.\n");
+	exit(1);
+      }
+
+
       {
         int begin=(rand()%TESTWORDS);
         int ilen=(rand()%(TESTWORDS-begin));
         int bitoffset,bitcount=0;
         unsigned long temp;
-	or.buffer=ob;
 
         for(j=0;j<begin;j++)
           bitcount+=len[j];
-	or.begin=bitcount/8;
-	bitoffset=bitcount%8;
+	or=ogg_buffer_pretruncate(or,bitcount/8);
+	bitoffset=bitcount%=8;
         for(;j<begin+ilen;j++)
           bitcount+=len[j];
-	or.length=((bitcount+7)/8)-or.begin;
+	ogg_buffer_posttruncate(or,((bitcount+7)/8));
 
-	oggpack_readinit(&o,&or);
+	if(bufferlength(or)!=(bitcount+7)/8){
+	  fprintf(stderr,"\nERROR: buffer length incorrect after truncate.\n");
+	  exit(1);
+	}
+	
+	oggpack_readinit(&o,or);
 
         /* verify bit count */
         if(oggpack_bits(&o)!=0){
@@ -1251,8 +1206,8 @@
           else
             ret=oggpack_read(&o,len[j],&temp);
           if(ret<0){
-	    fprintf(stderr,"\nERROR: End of stream too soon! word: %d\n",
-		    j-begin);
+	    fprintf(stderr,"\nERROR: End of stream too soon! word: %d,%d\n",
+		    j-begin,ilen);
             exit(1);
           }
           if(temp!=(values[j]&mask[len[j]])){
@@ -1280,7 +1235,7 @@
         }	
 
         /* look/adv version */
-	oggpack_readinit(&o,&or);
+	oggpack_readinit(&o,or);
         bitcount=bitoffset;
         oggpack_adv(&o,bitoffset);
 
@@ -1326,17 +1281,20 @@
         }	
 
       }
+      ogg_buffer_release(or);
     }
   }
   fprintf(stderr,"\rRandomized testing (LSb)... ok.   \n");
 
-  for(i=0;i<1000;i++){
-    int j,count=0,count2=0,bitcount=0;
+  /* cut & paste: lazy bastahd alert */
+
+  for(i=0;i<10000;i++){
+    int j,count2=0,bitcount=0;
     unsigned long values[TESTWORDS];
     int len[TESTWORDS];
     unsigned char flat[4*TESTWORDS]; /* max possible needed size */
 
-    fprintf(stderr,"\rRandomized testing (MSb)... (%ld)   ",1000-i);
+    fprintf(stderr,"\rRandomized testing (MSb)... (%ld)   ",10000-i);
     oggpackB_writeinit(&o,&bs);
 
     /* generate a list of words and lengths */
@@ -1344,7 +1302,6 @@
     for(j=0;j<TESTWORDS;j++){
       values[j]=rand();
       len[j]=(rand()%33);
-      count+=len[j];
 
       oggpackB_write(&o,values[j],len[j]);
 
@@ -1364,6 +1321,10 @@
 
     /* flatten the packbuffer out to a vector */
     count2=flatten(flat);
+    if(count2<(bitcount+7)/8){
+      fprintf(stderr,"\nERROR: flattened write buffer incorrect length\n");
+      exit(1);
+    }
     oggpackB_writeclear(&o);
 
     /* verify against original list */
@@ -1372,48 +1333,56 @@
     /* construct random-length buffer chain from flat vector; random
        byte starting offset within the length of the vector */
     {
-      ogg_buffer *obl=NULL,*ob=NULL;
+      ogg_reference *or=NULL,*orl=NULL;
       unsigned char *ptr=flat;
       
       /* build buffer chain */
       while(count2){
-	int ilen;
-	ogg_buffer *temp=_ogg_malloc(sizeof(*temp)); /* we don't bother
-                                                      freeing later;
-                                                      this is just a
-                                                      unit test */
-	if(obl)
-	  obl->next=temp;
-	else
-	  ob=temp;
+	int ilen=(rand()%32);
+	int ibegin=(rand()%32);
 
-	ilen=(rand()%32);
         if(ilen>count2)ilen=count2;
-	obl=temp;
-	obl->data=ptr;
-	obl->size=count2;
-	obl->used=ilen;
-	
+
+	if(or)
+	  orl=ogg_buffer_extend(orl,ilen+ibegin);
+	else
+	  or=orl=ogg_buffer_alloc(&bs,ilen+ibegin);
+
+	memcpy(orl->buffer->data+ibegin,ptr,ilen);
+       
+	orl->length=ilen;
+	orl->begin=ibegin;
+
         count2-=ilen;
         ptr+=ilen;
       }
-      /* build reference; choose a starting offset. */
+
+      if(bufferlength(or)!=(bitcount+7)/8){
+	fprintf(stderr,"\nERROR: buffer length incorrect after build.\n");
+	exit(1);
+      }
+
+
       {
         int begin=(rand()%TESTWORDS);
         int ilen=(rand()%(TESTWORDS-begin));
         int bitoffset,bitcount=0;
         unsigned long temp;
-	or.buffer=ob;
 
         for(j=0;j<begin;j++)
           bitcount+=len[j];
-	or.begin=bitcount/8;
-	bitoffset=bitcount%8;
+	or=ogg_buffer_pretruncate(or,bitcount/8);
+	bitoffset=bitcount%=8;
         for(;j<begin+ilen;j++)
           bitcount+=len[j];
-	or.length=((bitcount+7)/8)-or.begin;
+	ogg_buffer_posttruncate(or,((bitcount+7)/8));
 
-	oggpackB_readinit(&o,&or);
+	if(bufferlength(or)!=(bitcount+7)/8){
+	  fprintf(stderr,"\nERROR: buffer length incorrect after truncate.\n");
+	  exit(1);
+	}
+	
+	oggpackB_readinit(&o,or);
 
         /* verify bit count */
         if(oggpackB_bits(&o)!=0){
@@ -1436,8 +1405,8 @@
           else
             ret=oggpackB_read(&o,len[j],&temp);
           if(ret<0){
-	    fprintf(stderr,"\nERROR: End of stream too soon! word: %d\n",
-		    j-begin);
+	    fprintf(stderr,"\nERROR: End of stream too soon! word: %d,%d\n",
+		    j-begin,ilen);
             exit(1);
           }
           if(temp!=(values[j]&mask[len[j]])){
@@ -1465,7 +1434,7 @@
         }	
 
         /* look/adv version */
-	oggpackB_readinit(&o,&or);
+	oggpackB_readinit(&o,or);
         bitcount=bitoffset;
         oggpackB_adv(&o,bitoffset);
 
@@ -1483,7 +1452,7 @@
             exit(1);
           }
           if(temp!=(values[j]&mask[len[j]])){
-	    fprintf(stderr,"\nERROR: Incorrect read %lx != %lx, word %d, len %d\n",
+	    fprintf(stderr,"\nERROR: Incorrect look %lx != %lx, word %d, len %d\n",
                     values[j]&mask[len[j]],temp,j-begin,len[j]);
             exit(1);
           }
@@ -1493,12 +1462,12 @@
             oggpackB_adv(&o,len[j]);
           bitcount+=len[j];
           if(oggpackB_bits(&o)!=bitcount){
-	    fprintf(stderr,"\nERROR: Read bitcounter %d != %ld!\n",
+	    fprintf(stderr,"\nERROR: Look/Adv bitcounter %d != %ld!\n",
                     bitcount,oggpackB_bits(&o));
             exit(1);
           }
           if(oggpackB_bytes(&o)!=(bitcount+7)/8){
-	    fprintf(stderr,"\nERROR: Read bytecounter %d != %ld!\n",
+	    fprintf(stderr,"\nERROR: Look/Adv bytecounter %d != %ld!\n",
                     (bitcount+7)/8,oggpackB_bytes(&o));
             exit(1);
           }
@@ -1511,6 +1480,7 @@
         }	
 
       }
+      ogg_buffer_release(or);
     }
   }
   fprintf(stderr,"\rRandomized testing (MSb)... ok.   \n");

<p><p>1.1.2.6   +182 -154  ogg/src/Attic/buffer.c

Index: buffer.c
===================================================================
RCS file: /usr/local/cvsroot/ogg/src/Attic/buffer.c,v
retrieving revision 1.1.2.5
retrieving revision 1.1.2.6
diff -u -r1.1.2.5 -r1.1.2.6
--- buffer.c	6 Mar 2003 23:13:36 -0000	1.1.2.5
+++ buffer.c	15 Mar 2003 01:26:09 -0000	1.1.2.6
@@ -11,7 +11,7 @@
  ********************************************************************
 
   function: centralized fragment buffer management
-  last mod: $Id: buffer.c,v 1.1.2.5 2003/03/06 23:13:36 xiphmont Exp $
+  last mod: $Id: buffer.c,v 1.1.2.6 2003/03/15 01:26:09 xiphmont Exp $
 
  ********************************************************************/
 
@@ -22,210 +22,238 @@
 #include <stdlib.h>
 #include "ogginternal.h"
 
-/* basic, centralized Ogg memory management.
+/* basic, centralized Ogg memory management based on linked lists of
+   references to refcounted memory buffers.  References and buffers
+   are both recycled.  Buffers are passed around and consumed in
+   reference form. */
 
-   We trade in recycled, refcounted [in decode] memory blocks
-   belonging to a specific pool.
+/* management is here; actual production and consumption of data is
+   found in the rest of the libogg code */
 
-   During decode, buffers are passed around and consumed primarily in
-   reference form. Encode uses the actual ogg_buffer as there's no
-   multipath usage. */
-
-void ogg_buffer_init(ogg_buffer_state *bs,int encode_decode_flag){
+void ogg_buffer_init(ogg_buffer_state *bs){
   memset(bs,0,sizeof(*bs));
   ogg_mutex_init(&bs->mutex);
-  bs->encode_decode_flag=encode_decode_flag;
 }
 
 void ogg_buffer_clear(ogg_buffer_state *bs){
-  if(bs->outstanding==0){
-    ogg_mutex_clear(&bs->mutex);
-    
-    while(bs->unused_pool){
-      ogg_buffer *b=bs->unused_pool;
-      bs->unused_pool=b->next;
-      if(b->data)_ogg_free(b->data);
-      _ogg_free(b);
-    }
-  }
 #ifdef OGGBUFFER_DEBUG
-  else{
-    
-    fprintf(stderr,"ERROR: Freeing ogg_buffer_state with buffers outstanding.\n");
-    exit(1);
-    
-  }
+  if(bs->outstanding_buffers!=0)
+    fprintf(stderr,"WARNING: Freeing ogg_buffer_state with buffers outstanding.\n");
+  if(bs->outstanding_references!=0)
+    fprintf(stderr,"WARNING: Freeing ogg_buffer_state with buffers outstanding.\n");
 #endif
+
+  ogg_mutex_clear(&bs->mutex);
+  
+  while(bs->unused_buffers){
+    ogg_buffer *b=bs->unused_buffers;
+    bs->unused_buffers=b->ptr.next;
+    if(b->data)_ogg_free(b->data);
+    _ogg_free(b);
+  }
+  while(bs->unused_references){
+    ogg_reference *r=bs->unused_references;
+    bs->unused_references=r->next;
+    _ogg_free(r);
+  }
 }
 
-ogg_buffer *ogg_buffer_alloc(ogg_buffer_state *bs,long bytes){
-  ogg_buffer *ret;
+static ogg_buffer *_fetch_buffer(ogg_buffer_state *bs,long bytes){
+  ogg_buffer    *ob;
   ogg_mutex_lock(&bs->mutex);
-
+  
   /* do we have an unused buffer sitting in the pool? */
-  if(bs->unused_pool){
-    ret=bs->unused_pool;
-    bs->unused_pool=ret->next;
+  if(bs->unused_buffers){
+    ob=bs->unused_buffers;
+    bs->unused_buffers=ob->ptr.next;
     ogg_mutex_unlock(&bs->mutex);
 
     /* if the unused buffer is too small, grow it */
-    if(ret->size<bytes){
-      ret->data=_ogg_realloc(ret->data,bytes);
-      ret->size=bytes;
+    if(ob->size<bytes){
+      ob->data=_ogg_realloc(ob->data,bytes);
+      ob->size=bytes;
     }
   }else{
+    /* allocate a new buffer */
     ogg_mutex_unlock(&bs->mutex);
+    ob=_ogg_malloc(sizeof(*ob));
+    ob->data=_ogg_malloc(bytes);
+    ob->size=bytes;
+  }
 
-    /* allocate a new buffer */
-    ret=_ogg_malloc(sizeof(*ret));
-    ret->data=_ogg_malloc(bytes);
-    ret->size=bytes;
+  ob->ptr.owner=bs;
+  ob->refcount=1;
+  return ob;
+}
+
+static ogg_reference *_fetch_ref(ogg_buffer_state *bs){
+  ogg_reference *or;
+  ogg_mutex_lock(&bs->mutex);
+
+  /* do we have an unused reference sitting in the pool? */
+  if(bs->unused_references){
+    or=bs->unused_references;
+    bs->unused_references=or->next;
+    ogg_mutex_unlock(&bs->mutex);
+  }else{
+    /* allocate a new reference */
+    ogg_mutex_unlock(&bs->mutex);
+    or=_ogg_malloc(sizeof(*or));
   }
 
-  ret->used=0;
-  ret->next=0;
-  if(bs->encode_decode_flag)
-    ret->refbeg=1;
-  else
-    ret->refbeg=0;
+  or->begin=0;
+  or->length=0;
+  or->next=0;
 
-  return ret;
+  return or;
 }
 
-/* this will succeed only if 
-   a) the buffer is unused 
-   b) with a refcount of one, or part of an encode-side pool
+/* fetch a reference pointing to a fresh, initially continguous buffer
+   of at least [bytes] length */
+ogg_reference *ogg_buffer_alloc(ogg_buffer_state *bs,long bytes){
+  ogg_buffer    *ob=_fetch_buffer(bs,bytes);
+  ogg_reference *or=_fetch_ref(bs);
+  or->buffer=ob;
+  return or;
+}
 
-   currently used only by the sync fifo code to avoid the need
-   for a doubly-linked list */
+/* duplicate a reference (pointing to the same actual buffer memory)
+   and increment buffer refcount.  If the desired segment begins out
+   of range, NULL is returned; if the desired segment is simply zero
+   length, a zero length ref is returned.  Partial range overlap
+   returns the overlap of the ranges */
+ogg_reference *ogg_buffer_dup(ogg_reference *or,long begin,long length){
+  ogg_reference *ret=0,*head=0;
 
-int ogg_buffer_realloc(ogg_buffer_state *bs,ogg_buffer *ob,long bytes){
-  int ret=-1;
-  ogg_mutex_lock(&bs->mutex);
-  if(ob->used==0 && (ob->refbeg<=1 || bs->encode_decode_flag==0)){
-    ret=0;
-    if(bytes>ob->size){
-      ob->data=_ogg_realloc(ob->data,bytes);
-      ob->size=bytes;
-    }
+  /* walk past any preceeding fragments we don't want */
+  while(or && begin>=or->length){
+    begin-=or->length;
+    or=or->next;
   }
-  ogg_mutex_unlock(&bs->mutex);
+
+  /* duplicate the reference chain; increment refcounts */
+  while(or && length){
+    ogg_reference *temp=_fetch_ref(or->buffer->ptr.owner);
+    if(head)head->next=temp;
+    head=temp;
+    if(!ret)ret=head;
+
+    head->buffer=or->buffer;
+    
+    head->begin=or->begin+begin;
+    head->length=length;
+    if(head->begin+head->length>or->begin+or->length)
+      head->length=or->begin+or->length-head->begin;
+
+    begin=0;
+    length-=head->length;
+  }
+
+  ogg_buffer_mark(ret);
   return ret;
 }
 
-static void _ogg_buffer_release(ogg_buffer *ob,ogg_buffer_state *bs){
-  if(bs->encode_decode_flag){
-    ob->refbeg--;
-#ifdef OGGBUFFER_DEBUG
-    if(ob->refbeg<0){
-      fprintf(stderr,"ERROR: Too many release()es on ogg_buffer.\n");
-      exit(1);
+/* add a new fragment link to the end of a chain; return ptr to the new link */
+ogg_reference *ogg_buffer_extend(ogg_reference *or,long bytes){
+  if(or){
+    while(or->next){
+      or=or->next;
     }
-#endif
-  }
-  if(!bs->encode_decode_flag || !ob->refbeg==0){
-    ob->next=bs->unused_pool;
-    bs->unused_pool=ob;
+    or->next=ogg_buffer_alloc(or->buffer->ptr.owner,bytes);
+    return(or->next);
   }
+  return 0;
 }
 
-/* offered only on encode-side */
-ogg_buffer *ogg_buffer_pretruncate(ogg_buffer *ob,ogg_buffer_state *bs,
-				   int bytes){
+/* increase the refcount of the buffers to which the reference points */
+void ogg_buffer_mark(ogg_reference *or){
+  while(or){
+    ogg_buffer_state *bs=or->buffer->ptr.owner;
+    ogg_mutex_lock(&bs->mutex); /* lock now in case someone is mixing
+				   pools */
 
-  if(bs->encode_decode_flag)return NULL;
-  ogg_mutex_lock(&bs->mutex);
-  
-  while(ob && bytes>0){
-    int current=ob->used-ob->refbeg;
 #ifdef OGGBUFFER_DEBUG
-    if(current<0){
-      fprintf(stderr,"ERROR: Negative used ogg_buffer size.\n");
-      exit(1);
-    }
+    if(or->buffer->refcount==0)
+      fprintf(stderr,"WARNING: marking buffer fragment with refcount of zero!\n");
 #endif
 
-    if(current<=bytes){
-      /* now completely unused; release the buffer */
-      ogg_buffer *next=ob->next;
-      _ogg_buffer_release(ob,bs);
-      bytes-=current;
-      ob=next;
-    }else{
-      /* trim the current buffer */
-      ob->refbeg+=bytes;
-      bytes=0;
-    }
-    
+    or->buffer->refcount++;
+    ogg_mutex_unlock(&bs->mutex);
+
+    or=or->next;
+  }
+}
+
+static void _release_one(ogg_reference *or){
+  ogg_buffer *ob=or->buffer;
+  ogg_buffer_state *bs=or->buffer->ptr.owner;
+
+  ogg_mutex_lock(&bs->mutex);
+
 #ifdef OGGBUFFER_DEBUG
-    if(ob==NULL && bytes>0){
-      fprintf(stderr,"ERROR: requested pretruncate larger than ogg_buffer.\n");
-      exit(1);
-    }
+  if(ob->refcount==0)
+    fprintf(stderr,"WARNING: releasing buffer fragment with refcount of zero!\n");
 #endif
-    
+  
+  ob->refcount--;
+  if(ob->refcount==0){
+    /* release the fragment back to unused pool */
+    ob->ptr.next=bs->unused_buffers;
+    bs->unused_buffers=ob;
   }
 
-  ogg_mutex_unlock(&bs->mutex);  
-  return ob;
-}
+  or->next=bs->unused_references;
+  bs->unused_references=or;
 
-void ogg_buffer_release(ogg_buffer *ob,ogg_buffer_state *bs){
-  ogg_mutex_lock(&bs->mutex);
-  _ogg_buffer_release(ob,bs);
   ogg_mutex_unlock(&bs->mutex);
 }
 
-void ogg_reference_mark(ogg_buffer_reference *or){
-  ogg_mutex_lock(&or->owner->mutex);
-  if(or->owner->encode_decode_flag){
-    long bytes=or->begin+or->length;
-    ogg_buffer *ob=or->buffer;
-    
-    while(bytes>0){
-#ifdef OGGBUFFER_DEBUG
-      if(ob==NULL){
-	fprintf(stderr,"ERROR: ogg_reference_mark ran off the end of buffer chain.\n");
-	exit(1);
-      }
-#endif
-      
-      ob->refbeg++;
-      bytes-=ob->used;
-      ob=ob->next;
-    }
+/* release the references, decrease the refcounts of buffers to which
+   they point, release any buffers with a refcount that drops to zero */
+void ogg_buffer_release(ogg_reference *or){
+  while(or){
+    ogg_reference *next=or->next;
+    _release_one(or);
+    or=next;
   }
-  ogg_mutex_unlock(&or->owner->mutex);
 }
 
-void ogg_reference_clear(ogg_buffer_reference *or){
-  or->buffer=0;
+ogg_reference *ogg_buffer_pretruncate(ogg_reference *or,long pos){
+  /* release preceeding fragments we don't want */
+  while(or && pos>=or->length){
+    ogg_reference *next=or->next;
+    pos-=or->length;
+    _release_one(or);
+    or=next;
+  }
+  if (or) {
+    or->begin+=pos;
+    or->length-=pos;
+  }
+  return or;
 }
 
-void ogg_reference_release(ogg_buffer_reference *or){
-  if(or && or->buffer){
-    long bytes;
-    ogg_buffer *ob;
-    ogg_mutex_lock(&or->owner->mutex);
-    
-    bytes=or->begin+or->length;
-    ob=or->buffer;
-    
-    while(bytes>0){
-#ifdef OGGBUFFER_DEBUG
-      if(ob==NULL){
-	fprintf(stderr,"ERROR: ogg_reference_release ran off the end of buffer chain.\n");
-      exit(1);
-      }
-#endif
-      {
-	ogg_buffer *next=ob->next;
-	bytes-=ob->used;
-      _ogg_buffer_release(ob,or->owner);
-      ob=next;
-      }
-    }
-    
-    ogg_mutex_unlock(&or->owner->mutex);
+void ogg_buffer_posttruncate(ogg_reference *or,long pos){
+  /* walk to the point where we want to begin truncate */
+  while(or && pos>or->length){
+    pos-=or->length;
+    or=or->next;
+  }
+  if(or){
+    /* release or->next and beyond */
+    ogg_buffer_release(or->next);
+    or->next=0;
+    /* update length fencepost */
+    or->length=pos;
   }
 }
+
+/* *head is appened to the front end (head) of *tail; both continue to
+   be valid pointers, with *tail at the tail and *head at the head */
+void ogg_buffer_cat(ogg_reference *tail, ogg_reference *head){
+  while(tail->next){
+    tail=tail->next;
+  }
+  tail->next=head;
+}
+

<p><p>1.1.2.6   +50 -61    ogg/src/Attic/ogginternal.h

Index: ogginternal.h
===================================================================
RCS file: /usr/local/cvsroot/ogg/src/Attic/ogginternal.h,v
retrieving revision 1.1.2.5
retrieving revision 1.1.2.6
diff -u -r1.1.2.5 -r1.1.2.6
--- ogginternal.h	6 Mar 2003 23:13:36 -0000	1.1.2.5
+++ ogginternal.h	15 Mar 2003 01:26:09 -0000	1.1.2.6
@@ -11,7 +11,7 @@
  ********************************************************************
 
  function: internal/hidden data representation structures
- last mod: $Id: ogginternal.h,v 1.1.2.5 2003/03/06 23:13:36 xiphmont Exp $
+ last mod: $Id: ogginternal.h,v 1.1.2.6 2003/03/15 01:26:09 xiphmont Exp $
 
  ********************************************************************/
 
@@ -22,81 +22,72 @@
 #include "mutex.h"
 
 struct ogg_buffer_state{
-  ogg_buffer *unused_pool;
-  int         outstanding;
-  int         encode_decode_flag; /* (0==encode, 1==decode)*/
+  ogg_buffer    *unused_buffers;
+  int            outstanding_buffers;
+
+  ogg_reference *unused_references;
+  int            outstanding_references;
+
   ogg_mutex_t mutex;
 };
 
-typedef struct{
-  ogg_buffer           *segment;
-  int                   cursor;
-} ogg_buffer_cursor;
-
 struct ogg_buffer {
-  unsigned char     *data;
-  int                used;
-  struct ogg_buffer *next;
-  int                size;
-  int                refbeg; /* in decode, this field is used for
-				cross-abstraction refcounting and
-				memory usage tracking.  In encode,
-				each buffer fragment has a single
-				usage pathway, so this field is used
-				for pretruncation , needed by encode
-				but not decode */
+  unsigned char      *data;
+  long                size;
+  int                 refcount;
+  union {
+    ogg_buffer_state *owner;
+    ogg_buffer       *next;
+  } ptr;
+};
 
+struct ogg_reference {
+  struct ogg_buffer    *buffer;
+  long                  begin;
+  long                  length;
+  struct ogg_reference *next;
 };
 
 struct oggpack_buffer {
-  int               headbit;
-  unsigned char    *headptr;
-  long              headend;
+  int            headbit;
+  unsigned char *headptr;
+  long           headend;
 
   /* memory management */
-  ogg_buffer       *head;
-  ogg_buffer       *tail;  
-  ogg_buffer_state *owner; /* centralized mem management; buffer fragment 
-			      memory is owned and managed by the physical
-			      stream abstraction */
+  ogg_reference *head;
+  ogg_reference *tail;
 
   /* render the byte/bit counter API constant time */
-  long length; /* meaningful only in decode */
-  long count;  /* doesn't count the tail */
+  long count;              /* doesn't count the tail */
+  ogg_buffer_state *owner; /* cache preferred pool for write lazy init */
 
 };
 
-typedef struct ogg_packet_chain {
-  ogg_buffer_reference     packet;
-  ogg_int64_t              granulepos;
-
-  struct ogg_packet_chain *next;
-} ogg_packet_chain;
+typedef struct{
+  ogg_reference *segment;
+  int            cursor;
+} ogg_buffer_cursor;
 
 struct ogg_sync_state {
   /* encode/decode mem management */
-  ogg_buffer_state      bufferpool;
+  ogg_buffer_state  bufferpool;
 
   /* stream buffers */
-  ogg_buffer           *fifo_head;
-  ogg_buffer           *fifo_tail;
+  ogg_reference    *fifo_head;
+  ogg_reference    *fifo_tail;
   
-  long                  fifo_cursor;
-  long                  fifo_fill;
-  ogg_buffer_reference  returned;
+  long              fifo_cursor;
+  long              fifo_fill;
+  ogg_reference    *returned;
 
   /* stream sync management */
-  int         unsynced;
-  int         headerbytes;
-  int         bodybytes;
+  int               unsynced;
+  int               headerbytes;
+  int               bodybytes;
 
 };
 
 struct ogg_stream_state {
-  ogg_packet_chain *unused;
-  ogg_packet_chain *head;
-  ogg_packet_chain *tail;
-
 
   long              body_len;
 
@@ -122,17 +113,15 @@
 
 };
 
-extern void ogg_buffer_init(ogg_buffer_state *bs,int encode_decode_flag);
-extern void ogg_buffer_clear(ogg_buffer_state *bs);
-extern ogg_buffer *ogg_buffer_alloc(ogg_buffer_state *bs,long bytes);
-extern int ogg_buffer_realloc(ogg_buffer_state *bs,ogg_buffer *ob,long bytes);
-extern ogg_buffer *ogg_buffer_pretruncate(ogg_buffer *ob,ogg_buffer_state *bs,
-					  int bytes);
-extern void ogg_buffer_release(ogg_buffer *ob,ogg_buffer_state *bs);
-extern void ogg_reference_clear(ogg_buffer_reference *or);
-extern void ogg_reference_mark(ogg_buffer_reference *or);
-extern void ogg_reference_release(ogg_buffer_reference *or);
-
-
+extern void           ogg_buffer_init(ogg_buffer_state *bs);
+extern void           ogg_buffer_clear(ogg_buffer_state *bs);
+extern ogg_reference *ogg_buffer_alloc(ogg_buffer_state *bs,long bytes);
+extern ogg_reference *ogg_buffer_dup(ogg_reference *or,long begin,long length);
+extern ogg_reference *ogg_buffer_extend(ogg_reference *or,long bytes);
+extern void           ogg_buffer_mark(ogg_reference *or);
+extern void           ogg_buffer_release(ogg_reference *or);
+extern ogg_reference *ogg_buffer_pretruncate(ogg_reference *or,long pos);
+extern void           ogg_buffer_posttruncate(ogg_reference *or,long pos);
+extern void           ogg_buffer_cat(ogg_reference *tail, ogg_reference *head);
 
 #endif

<p><p>1.1.2.2   +2 -2      ogg/src/Attic/stream.c

Index: stream.c
===================================================================
RCS file: /usr/local/cvsroot/ogg/src/Attic/stream.c,v
retrieving revision 1.1.2.1
retrieving revision 1.1.2.2
diff -u -r1.1.2.1 -r1.1.2.2
--- stream.c	6 Mar 2003 23:13:36 -0000	1.1.2.1
+++ stream.c	15 Mar 2003 01:26:09 -0000	1.1.2.2
@@ -10,9 +10,9 @@
  *                                                                  *
  ********************************************************************
 
- function: code raw [Vorbis] packets into framed OggSquish stream and
+ function: code raw packets into framed Ogg stream and
            decode Ogg streams back into raw packets
- last mod: $Id: stream.c,v 1.1.2.1 2003/03/06 23:13:36 xiphmont Exp $
+ last mod: $Id: stream.c,v 1.1.2.2 2003/03/15 01:26:09 xiphmont Exp $
 
  ********************************************************************/
 

<p><p>--- >8 ----
List archives:  http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body.  No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.



More information about the commits mailing list