[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