[xiph-cvs] cvs commit: ogg/src stream.c bitwise.c buffer.c ogginternal.h sync.c
Monty
xiphmont at xiph.org
Thu Mar 6 15:13:36 PST 2003
xiphmont 03/03/06 18:13:36
Modified: src Tag: libogg2-zerocopy bitwise.c buffer.c
ogginternal.h sync.c
Added: src Tag: libogg2-zerocopy stream.c
Log:
Incremental of new unit tests, fixes, etc.
Revision Changes Path
No revision
<p>No revision
<p>1.14.2.8 +2 -3 ogg/src/bitwise.c
Index: bitwise.c
===================================================================
RCS file: /usr/local/cvsroot/ogg/src/bitwise.c,v
retrieving revision 1.14.2.7
retrieving revision 1.14.2.8
diff -u -r1.14.2.7 -r1.14.2.8
--- bitwise.c 10 Feb 2003 18:05:46 -0000 1.14.2.7
+++ bitwise.c 6 Mar 2003 23:13:36 -0000 1.14.2.8
@@ -11,7 +11,7 @@
********************************************************************
function: pack variable sized words into an octet stream
- last mod: $Id: bitwise.c,v 1.14.2.7 2003/02/10 18:05:46 xiphmont Exp $
+ last mod: $Id: bitwise.c,v 1.14.2.8 2003/03/06 23:13:36 xiphmont Exp $
********************************************************************/
@@ -413,7 +413,6 @@
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->length=0;
b->headend=0;
b->headbit=0;
}
@@ -955,7 +954,7 @@
/* Test read/write together */
/* Later we test against pregenerated bitstreams */
- ogg_buffer_init(&bs);
+ ogg_buffer_init(&bs,0);
fprintf(stderr,"\nSmall preclipped packing (LSb): ");
cliptest(testbuffer1,test1size,0,one,onesize);
<p><p>1.1.2.5 +119 -44 ogg/src/Attic/buffer.c
Index: buffer.c
===================================================================
RCS file: /usr/local/cvsroot/ogg/src/Attic/buffer.c,v
retrieving revision 1.1.2.4
retrieving revision 1.1.2.5
diff -u -r1.1.2.4 -r1.1.2.5
--- buffer.c 10 Feb 2003 18:05:46 -0000 1.1.2.4
+++ buffer.c 6 Mar 2003 23:13:36 -0000 1.1.2.5
@@ -11,7 +11,7 @@
********************************************************************
function: centralized fragment buffer management
- last mod: $Id: buffer.c,v 1.1.2.4 2003/02/10 18:05:46 xiphmont Exp $
+ last mod: $Id: buffer.c,v 1.1.2.5 2003/03/06 23:13:36 xiphmont Exp $
********************************************************************/
@@ -24,14 +24,17 @@
/* basic, centralized Ogg memory management.
- We trade in recycled, refcounted memory blocks belonging to a
- specific pool.
+ We trade in recycled, refcounted [in decode] memory blocks
+ belonging to a specific pool.
- Buffers are passed around and consumed primarily in reference form. */
+ 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){
+void ogg_buffer_init(ogg_buffer_state *bs,int encode_decode_flag){
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){
@@ -81,22 +84,90 @@
ret->used=0;
ret->next=0;
- ret->refcount=1;
+ if(bs->encode_decode_flag)
+ ret->refbeg=1;
+ else
+ ret->refbeg=0;
+
+ return ret;
+}
+
+/* this will succeed only if
+ a) the buffer is unused
+ b) with a refcount of one, or part of an encode-side pool
+
+ currently used only by the sync fifo code to avoid the need
+ for a doubly-linked list */
+
+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;
+ }
+ }
+ ogg_mutex_unlock(&bs->mutex);
return ret;
}
static void _ogg_buffer_release(ogg_buffer *ob,ogg_buffer_state *bs){
- ob->refcount--;
- if(ob->refcount==0){
+ 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);
+ }
+#endif
+ }
+ if(!bs->encode_decode_flag || !ob->refbeg==0){
ob->next=bs->unused_pool;
bs->unused_pool=ob;
}
+}
+
+/* offered only on encode-side */
+ogg_buffer *ogg_buffer_pretruncate(ogg_buffer *ob,ogg_buffer_state *bs,
+ int bytes){
+
+ 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(ob->refcount<0){
- fprintf(stderr,"ERROR: Too many release()es on ogg_buffer.\n");
- exit(1);
- }
+ if(current<0){
+ fprintf(stderr,"ERROR: Negative used ogg_buffer size.\n");
+ exit(1);
+ }
+#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;
+ }
+
+#ifdef OGGBUFFER_DEBUG
+ if(ob==NULL && bytes>0){
+ fprintf(stderr,"ERROR: requested pretruncate larger than ogg_buffer.\n");
+ exit(1);
+ }
#endif
+
+ }
+
+ ogg_mutex_unlock(&bs->mutex);
+ return ob;
}
void ogg_buffer_release(ogg_buffer *ob,ogg_buffer_state *bs){
@@ -106,51 +177,55 @@
}
void ogg_reference_mark(ogg_buffer_reference *or){
- long bytes;
- ogg_buffer *ob;
ogg_mutex_lock(&or->owner->mutex);
-
- bytes=or->begin+or->length;
- ob=or->buffer;
-
- while(bytes>0){
+ 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);
- }
+ if(ob==NULL){
+ fprintf(stderr,"ERROR: ogg_reference_mark ran off the end of buffer chain.\n");
+ exit(1);
+ }
#endif
-
- ob->refcount++;
- bytes-=ob->used;
- ob=ob->next;
+
+ ob->refbeg++;
+ bytes-=ob->used;
+ ob=ob->next;
+ }
}
-
ogg_mutex_unlock(&or->owner->mutex);
}
-void ogg_reference_release(ogg_buffer_reference *or){
- long bytes;
- ogg_buffer *ob;
- ogg_mutex_lock(&or->owner->mutex);
-
- bytes=or->begin+or->length;
- ob=or->buffer;
+void ogg_reference_clear(ogg_buffer_reference *or){
+ or->buffer=0;
+}
- while(bytes>0){
+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");
+ 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 *next=ob->next;
+ bytes-=ob->used;
_ogg_buffer_release(ob,or->owner);
ob=next;
+ }
}
+
+ ogg_mutex_unlock(&or->owner->mutex);
}
-
- ogg_mutex_unlock(&or->owner->mutex);
}
<p><p>1.1.2.5 +19 -6 ogg/src/Attic/ogginternal.h
Index: ogginternal.h
===================================================================
RCS file: /usr/local/cvsroot/ogg/src/Attic/ogginternal.h,v
retrieving revision 1.1.2.4
retrieving revision 1.1.2.5
diff -u -r1.1.2.4 -r1.1.2.5
--- ogginternal.h 10 Feb 2003 18:05:46 -0000 1.1.2.4
+++ ogginternal.h 6 Mar 2003 23:13:36 -0000 1.1.2.5
@@ -11,19 +11,20 @@
********************************************************************
function: internal/hidden data representation structures
- last mod: $Id: ogginternal.h,v 1.1.2.4 2003/02/10 18:05:46 xiphmont Exp $
+ last mod: $Id: ogginternal.h,v 1.1.2.5 2003/03/06 23:13:36 xiphmont Exp $
********************************************************************/
#ifndef _OGGI_H
#define _OGGI_H
-#include <ogg/ogg.h>
+#include <ogg2/ogg.h>
#include "mutex.h"
struct ogg_buffer_state{
ogg_buffer *unused_pool;
int outstanding;
+ int encode_decode_flag; /* (0==encode, 1==decode)*/
ogg_mutex_t mutex;
};
@@ -37,7 +38,14 @@
int used;
struct ogg_buffer *next;
int size;
- int refcount;
+ 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 */
+
};
struct oggpack_buffer {
@@ -67,14 +75,15 @@
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;
long fifo_cursor;
- ogg_buffer_reference *returned;
+ long fifo_fill;
+ ogg_buffer_reference returned;
/* stream sync management */
int unsynced;
@@ -113,10 +122,14 @@
};
-extern void ogg_buffer_init(ogg_buffer_state *bs);
+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);
<p><p>1.1.2.2 +372 -338 ogg/src/Attic/sync.c
Index: sync.c
===================================================================
RCS file: /usr/local/cvsroot/ogg/src/Attic/sync.c,v
retrieving revision 1.1.2.1
retrieving revision 1.1.2.2
diff -u -r1.1.2.1 -r1.1.2.2
--- sync.c 31 Dec 2002 01:18:02 -0000 1.1.2.1
+++ sync.c 6 Mar 2003 23:13:36 -0000 1.1.2.2
@@ -1,4 +1,4 @@
-/********************************************************************
+ /********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
@@ -12,7 +12,7 @@
function: decode stream sync and memory management foundation code;
takes in raw data, spits out packets
- last mod: $Id: sync.c,v 1.1.2.1 2002/12/31 01:18:02 xiphmont Exp $
+ last mod: $Id: sync.c,v 1.1.2.2 2003/03/06 23:13:36 xiphmont Exp $
note: The CRC code is directly derived from public domain code by
Ross Williams (ross at guest.adelaide.edu.au). See docs/framing.html
@@ -27,53 +27,66 @@
/* A complete description of Ogg framing exists in docs/framing.html */
-/* Below we have decode stream buffer and memory management which is
+/* Below we have stream buffer and memory management which is
handled by physical stream and centralized in the ogg_sync_state
- structure. Encode side buffer management is done by logical stream
- in the ogg_stream_state structure */
+ structure. */
-static void _fc_seek(fragmented_cursor *fc,
- fragmented_reference *fb,
+/* called only on decode side; refbeg is a refcounter */
+static void _obc_seek(ogg_buffer_cursor *obc,
+ ogg_buffer *fb,
int position){
- fc->segment=fb;
- fc->cursor=position;
- while(fc->segment && fc->cursor>=fc->segment->used){
- fc->cursor-=fc->segment->used;
- fc->segment=fc->segment->next;
+ obc->segment=fb;
+ obc->cursor=position;
+ while(obc->segment && obc->cursor>=obc->segment->used){
+ obc->cursor-=obc->segment->used;
+ obc->segment=obc->segment->next;
}
}
-static int _fc_get(fragmented_cursor *fc){
- if(!fc->segment)return -1;
- if(fc->cursor>=fc->segment->used){
- fc->cursor=0;
- fc->segment=fc->segment->next;
- if(!fc->segment)return -1;
+static void _obc_seekr(ogg_buffer_cursor *obc,
+ ogg_buffer_reference *fb,
+ int position){
+ _obc_seek(obc,fb->buffer,position+fb->begin);
+}
+
+static void _obc_span(ogg_buffer_cursor *obc){
+ if(obc->segment){
+ obc->segment=obc->segment->next;
+ obc->cursor=0;
+ }
+}
+
+static int _obc_get(ogg_buffer_cursor *obc){
+ if(!obc->segment)return -1;
+ if(obc->cursor>=obc->segment->used){
+ obc->cursor=0;
+ obc->segment=obc->segment->next;
+ if(!obc->segment)return -1;
}
- return(fc->segment->data[fc->cursor++]);
+ return(obc->segment->data[obc->cursor++]);
}
-static void _fc_set(fragmented_cursor *fc,unsigned char val){
- if(!fc->segment)return;
- if(fc->cursor>=fc->segment->used){
- fc->cursor=0;
- fc->segment=fc->segment->next;
- if(!fc->segment)return;
+static void _obc_set(ogg_buffer_cursor *obc,unsigned char val){
+ if(!obc->segment)return;
+ if(obc->cursor>=obc->segment->used){
+ obc->cursor=0;
+ obc->segment=obc->segment->next;
+ if(!obc->segment)return;
}
- fc->segment->data[fc->cursor++]=val;
+ obc->segment->data[obc->cursor++]=val;
}
-static ogg_int64_t _fc_get_int64(fragmented_cursor *fc){
+static ogg_int64_t _obc_get_int64(ogg_buffer_cursor *obc){
ogg_int64_t ret;
unsigned char y[7];
- y[0]=_fc_get(fc);
- y[1]=_fc_get(fc);
- y[2]=_fc_get(fc);
- y[3]=_fc_get(fc);
- y[4]=_fc_get(fc);
- y[5]=_fc_get(fc);
- y[6]=_fc_get(fc);
- ret =_fc_get(fc);
+ y[0]=_obc_get(obc);
+ y[1]=_obc_get(obc);
+ y[2]=_obc_get(obc);
+ y[3]=_obc_get(obc);
+ y[4]=_obc_get(obc);
+ y[5]=_obc_get(obc);
+ y[6]=_obc_get(obc);
+ ret =_obc_get(obc);
ret =(ret<<8)|y[6];
ret =(ret<<8)|y[5];
@@ -86,13 +99,13 @@
return(ret);
}
-static ogg_uint32_t _fc_get_uint32(fragmented_cursor *fc){
+static ogg_uint32_t _obc_get_uint32(ogg_buffer_cursor *obc){
ogg_uint32_t ret;
unsigned char y[3];
- y[0]=_fc_get(fc);
- y[1]=_fc_get(fc);
- y[2]=_fc_get(fc);
- ret =_fc_get(fc);
+ y[0]=_obc_get(obc);
+ y[1]=_obc_get(obc);
+ y[2]=_obc_get(obc);
+ ret =_obc_get(obc);
ret =(ret<<8)|y[2];
ret =(ret<<8)|y[1];
ret =(ret<<8)|y[0];
@@ -100,137 +113,46 @@
return(ret);
}
-/* if there is a head fragment with sufficient space for the expose,
- return it
- if the head fragment doesn't have enough space or no head fragment:
- if there is no unused_fifo fragment, allocate one and return it
- if the unused_fifo fragment is large enough for the expose, return it
- else realloc the fragment in the unused_fifo buffer (the only graceful
- failback if the app is calling for exposes with varying sizes)
-*/
-
-static unsigned char *_sync_expose_fifo(_ogg_sync_state *oy,long size){
- if(!oy->fifo_head ||
- oy->fifo_head->size-oy->fifo_head->used<size){
-
- /* need to add to the fifo */
-
- fragmented_buffer *new;
- if(!oy->unused_fifo){
- oy->unused_fifo=_ogg_malloc(sizeof(*oy->unused_fifo));
- oy->unused_fifo->data=_ogg_malloc(size);
- oy->unused_fifo->size=size;
- oy->unused_fifo->used=0;
- }
- if(oy->unused_fifo->size<size){
- oy->unused_fifo->data=_ogg_realloc(oy->unused_fifo->data,size);
- oy->unused_fifo->size=size;
- }
-
- new=oy->unused_fifo;
- oy->unused_fifo=new->next;
- new->next=0;
- oy->fifo_head->next=new;
- oy->fifo_head=new;
- if(!oy->fifo_tail){
- oy->fifo_tail=new;
- oy->fifo_returned=new;
- oy->fifo_returned_pos=0;
- }
-
- return new->data;
- }
-
- return oy->fifo_head->data+oy->fifo_head->used;
-
-}
-
-static int _sync_wrote_fifo(_ogg_sync_state *oy,long size){
- if(oy->fifo_head->size-oy->fifo_head->used<size)
- size=oy->fifo_head->size-oy->fifo_head->used;
- oy->fifo_head->used+=size;
- oy->fifo_fill+=size;
- return 0;
-}
-
-/* marks for release fifo memory up to the passed in ptr which must be
- a valid location somewhere in the fragment buffer data (clearing up
- to the point), or if it is not in a valid data area, clearing the
- whole fifo. The reason we mark but do not yet release is that a
- page read can be immediately followed by handing that page to a
- logical stream, in which case the memory is once again locked
- in-buffer */
-
-static void _sync_mark_fifo(_ogg_sync_state *oy,long bytes){
-
- oy->fifo_returned_pos+=bytes;
- oy->fifo_fill-=bytes;
-
- while(oy->fifo_returned_pos>=oy->fifo_returned->used){
- oy->fifo_returned_pos-=oy->fifo_returned->used;
- oy->fifo_returned=oy->fifo_returned->next;
- }
-}
-
-/* release up to previously marked point, taking into account
- higher-layer buffer locking */
-static void _sync_release_fifo(_ogg_sync_state *oy){
-
- while(oy->fifo_tail!=oy->fifo_returned){
- fragmented_buffer *next=oy->fifo_tail->next;
-
- oy->fifo_tail->used=0;
- oy->fifo_tail->next=oy->unused_fifo;
- oy->unused_fifo=oy->fifo_tail;
-
- oy->fifo_tail=next;
- if(!oy->fifo_tail){
- oy->fifo_head=NULL;
- return;
- }
- }
-}
-
int ogg_page_version(ogg_page *og){
- fragmented_cursor fc;
- _fc_seek(&fc,&og->header,4);
- return(_fc_get(&fc));
+ ogg_buffer_cursor obc;
+ _obc_seekr(&obc,&og->header,4);
+ return(_obc_get(&obc));
}
int ogg_page_continued(ogg_page *og){
- fragmented_cursor fc;
- _fc_seek(&fc,&og->header,5);
- return(_fc_get(&fc)&0x01);
+ ogg_buffer_cursor obc;
+ _obc_seekr(&obc,&og->header,5);
+ return(_obc_get(&obc)&0x01);
}
int ogg_page_bos(ogg_page *og){
- fragmented_cursor fc;
- _fc_seek(&fc,&og->header,5);
- return(_fc_get(&fc)&0x02);
+ ogg_buffer_cursor obc;
+ _obc_seekr(&obc,&og->header,5);
+ return(_obc_get(&obc)&0x02);
}
int ogg_page_eos(ogg_page *og){
- fragmented_cursor fc;
- _fc_seek(&fc,&og->header,5);
- return(_fc_get(&fc)&0x04);
+ ogg_buffer_cursor obc;
+ _obc_seekr(&obc,&og->header,5);
+ return(_obc_get(&obc)&0x04);
}
ogg_int64_t ogg_page_granulepos(ogg_page *og){
- fragmented_cursor fc;
- _fc_seek(&fc,&og->header,6);
- return _fc_get_int64(&fc);
+ ogg_buffer_cursor obc;
+ _obc_seekr(&obc,&og->header,6);
+ return _obc_get_int64(&obc);
}
ogg_uint32_t ogg_page_serialno(ogg_page *og){
- fragmented_cursor fc;
- _fc_seek(&fc,&og->header,14);
- return _fc_get_uint32(&fc);
+ ogg_buffer_cursor obc;
+ _obc_seekr(&obc,&og->header,14);
+ return _obc_get_uint32(&obc);
}
ogg_uint32_t ogg_page_pageno(ogg_page *og){
- fragmented_cursor fc;
- _fc_seek(&fc,&og->header,18);
- return _fc_get_uint32(&fc);
+ ogg_buffer_cursor obc;
+ _obc_seekr(&obc,&og->header,18);
+ return _obc_get_uint32(&obc);
}
@@ -255,12 +177,12 @@
int i;
int n;
int count=0;
- fragmented_cursor fc;
- _fc_seek(&fc,&og->header,26);
+ ogg_buffer_cursor obc;
+ _obc_seekr(&obc,&og->header,26);
- n=_fc_get(&fc);
+ n=_obc_get(&obc);
for(i=0;i<n;i++)
- if(_fc_get(&fc)<255)count++;
+ if(_obc_get(&obc)<255)count++;
return(count);
}
@@ -340,7 +262,7 @@
higher layers (eg, OggFile). First, we expose a data buffer using
ogg_sync_buffer(). The app either copies into the buffer, or
passes it directly to read(), etc. We then call ogg_sync_wrote()
- to tell how many bytes we just added.
+ to tell how many bytes we just added.
Efficiency note: request the same buffer size each time if at all
possible.
@@ -348,60 +270,68 @@
Pages are returned (pointers into the buffer in ogg_sync_state)
by ogg_sync_pageout(). */
-/* initialize the struct to a known state */
+ogg_sync_state *ogg_sync_decode_create(void){
+ ogg_sync_state *oy=_ogg_calloc(1,sizeof(*oy));
+ memset(oy,0,sizeof(*oy));
+ ogg_buffer_init(&oy->bufferpool,1);
+ return oy;
+}
-/* why the double indirects?
- allows us to clear the pointer on clear/destroy
- holds more compatability with libogg1 interface */
-
-int ogg_sync_init(ogg_sync_state *oyi){
- if(oyi){
- _ogg_sync_state *oy=_ogg_calloc(1,sizeof(_ogg_sync_state));
- *oyi=(ogg_sync_state)oy;
+int ogg_sync_destroy(ogg_sync_state *oy){
+ if(oy){
+ ogg_sync_reset(oy);
+ ogg_buffer_clear(&oy->bufferpool);
memset(oy,0,sizeof(*oy));
+ _ogg_free(oy);
}
- return(0);
+ return 0;
}
-/* clear non-flat storage within */
-int ogg_sync_clear(ogg_sync_state *oyi){
- if(oyi){
- _ogg_sync_state *oy=(_ogg_sync_state *)*oyi;
- if(oy){
- fragmented_buffer *p=oy->unused_fifo;
- while(p){
- fragmented_buffer *next=p->next;
- if(p->data)_ogg_free(p->data);
- _ogg_free(p);
- p=next;
- }
-
- p=oy->fifo_tail;
- while(p){
- fragmented_buffer *next=p->next;
- if(p->data)_ogg_free(p->data);
- _ogg_free(p);
- p=next;
- }
-
- _ogg_free(oy);
- *oyi=0;
- }
+unsigned char *ogg_sync_bufferin(ogg_sync_state *oy, long bytes){
+ /* release the 'held' reference (if any) previously returned by the
+ sync */
+ ogg_reference_release(&oy->returned);
+ ogg_reference_clear(&oy->returned);
+
+ /* [allocate and] expose a buffer for data submission.
+
+ If there is no head fragment
+ allocate one and expose it
+ else
+ if the current head fragment has sufficient unused space
+ expose it
+ else
+ if the current head fragment is unused
+ resize and expose it
+ else
+ allocate new fragment and expose it
+ */
+ if(!oy->fifo_head){
+ oy->fifo_head=oy->fifo_tail=ogg_buffer_alloc(&oy->bufferpool,bytes);
+ return oy->fifo_head->data;
+ }
+
+ if(oy->fifo_head->size-oy->fifo_head->used<bytes)
+ return oy->fifo_head->data+oy->fifo_head->used;
+ if(!oy->fifo_head->used){
+ ogg_buffer_realloc(&oy->bufferpool,oy->fifo_head,bytes);
+ return oy->fifo_head->data;
}
- return(0);
-}
-
-unsigned char *ogg_sync_buffer(ogg_sync_state *oyi, long bytes){
- _ogg_sync_state *oy=(_ogg_sync_state *)*oyi;
- /* this is the API point where fragments marked to be cleared from
- the fifo and not claimed by the stream layer are released */
- _sync_release_fifo(oy);
- return _sync_expose_fifo(oy,bytes);
+
+ {
+ ogg_buffer *new=ogg_buffer_alloc(&oy->bufferpool,bytes);
+ oy->fifo_head->next=new;
+ oy->fifo_head=new;
+ }
+ return oy->fifo_head->data;
}
-int ogg_sync_wrote(ogg_sync_state *oyi, long bytes){
- _ogg_sync_state *oy=(_ogg_sync_state *)*oyi;
- return _sync_wrote_fifo(oy,bytes);
+int ogg_sync_wrote(ogg_sync_state *oy, long bytes){
+ if(!oy->fifo_head)return -1;
+ if(oy->fifo_head->size-oy->fifo_head->used<bytes)return -1;
+ oy->fifo_head->used+=bytes;
+ oy->fifo_fill+=bytes;
+ return 0;
}
/* sync the stream. This is meant to be useful for finding page
@@ -414,146 +344,184 @@
*/
-long ogg_sync_pageseek(ogg_sync_state *oyi,ogg_page *og){
- _ogg_sync_state *oy=(_ogg_sync_state *)*oyi;
- fragmented_cursor page;
- ogg_page temppage;
- long bytes;
+long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){
+ ogg_buffer_cursor page;
+ long bytes,ret=0;
+
+ ogg_reference_release(&oy->returned);
+ ogg_reference_clear(&oy->returned);
bytes=oy->fifo_fill;
if(oy->headerbytes==0){
- if(bytes<27)goto out_more; /* not enough for even a minimal header */
+ if(bytes<27)goto sync_out; /* not enough for even a minimal header */
/* verify capture pattern */
- _fc_seek(&page,(fragmented_reference *)&oy->fifo_returned,
- oy->fifo_returned_pos);
- if(_fc_get(&page)!=(int)'O' ||
- _fc_get(&page)!=(int)'g' ||
- _fc_get(&page)!=(int)'g' ||
- _fc_get(&page)!=(int)'S' ) goto sync_fail;
-
- _fc_seek(&page,(fragmented_reference *)&oy->fifo_returned,
- oy->fifo_returned_pos+26);
- oy->headerbytes=_fc_get(&page)+27;
+ _obc_seek(&page,oy->fifo_tail,
+ oy->fifo_cursor);
+ if(_obc_get(&page)!=(int)'O' ||
+ _obc_get(&page)!=(int)'g' ||
+ _obc_get(&page)!=(int)'g' ||
+ _obc_get(&page)!=(int)'S' ) goto sync_fail;
+
+ _obc_seek(&page,oy->fifo_tail,
+ oy->fifo_cursor+26);
+ oy->headerbytes=_obc_get(&page)+27;
}
- if(bytes<oy->headerbytes)goto out_more; /* not enough for header +
+ if(bytes<oy->headerbytes)goto sync_out; /* not enough for header +
seg table */
if(oy->bodybytes==0){
int i;
/* count up body length in the segment table */
- _fc_seek(&page,(fragmented_reference *)&oy->fifo_returned,
- oy->fifo_returned_pos+27);
+ _obc_seek(&page,oy->fifo_tail,
+ oy->fifo_cursor+27);
for(i=0;i<oy->headerbytes-27;i++)
- oy->bodybytes+=_fc_get(&page);
+ oy->bodybytes+=_obc_get(&page);
}
- if(oy->bodybytes+oy->headerbytes>bytes)goto out_more;
+ if(oy->bodybytes+oy->headerbytes>bytes)goto sync_out;
/* The whole test page is buffered. Set up the page struct and
verify the checksum */
{
/* Grab the checksum bytes */
unsigned char chksum[4];
- _fc_seek(&page,(fragmented_reference *)&oy->fifo_returned,
- oy->fifo_returned_pos+22);
- chksum[0]=_fc_get(&page);
- chksum[1]=_fc_get(&page);
- chksum[2]=_fc_get(&page);
- chksum[3]=_fc_get(&page);
+ _obc_seek(&page,oy->fifo_tail,
+ oy->fifo_cursor+22);
+ chksum[0]=_obc_get(&page);
+ chksum[1]=_obc_get(&page);
+ chksum[2]=_obc_get(&page);
+ chksum[3]=_obc_get(&page);
/* set up page struct and recompute the checksum */
{
- fragmented_buffer *fb=oy->fifo_returned;
- int pos=oy->fifo_returned_pos;
- if(!og)og=&temppage;
-
- og->header.data =fb->data+pos;
- og->header.used =fb->used-pos;
- og->header.next =(fragmented_reference *)fb->next;
- og->header_len=oy->headerbytes;
-
- pos+=oy->headerbytes;
- while(pos>=fb->used){
- pos-=fb->used;
- fb=fb->next;
+ ogg_buffer_reference *fb=&oy->returned;
+
+ /* set up return reference */
+ fb->buffer=oy->fifo_tail;
+ fb->begin=oy->fifo_cursor;
+ fb->length=oy->headerbytes+oy->bodybytes;
+ fb->owner=&oy->bufferpool;
+ while(fb->begin>=fb->buffer->used){
+ fb->begin-=fb->buffer->used;
+ fb->buffer=fb->buffer->next;
}
- og->body.data =fb->data+pos;
- og->body.used =fb->used-pos;
- og->body.next =(fragmented_reference *)fb->next;
- og->body_len=oy->bodybytes;
- }
+ if(og){
+ /* set up page output */
+ og->header.buffer=fb->buffer;
+ og->header.begin=fb->begin;
+ og->header.length=oy->headerbytes;
+ og->header.owner=&oy->bufferpool;
+ og->body.buffer=fb->buffer;
+ og->body.begin=fb->begin+oy->headerbytes;
+ og->body.length=oy->bodybytes;
+ og->body.owner=&oy->bufferpool;
+ while(og->body.begin>=og->body.buffer->used){
+ og->body.begin-=og->body.buffer->used;
+ og->body.buffer=og->body.buffer->next;
+ }
+ }
+ }
ogg_page_checksum_set(og);
/* Compare checksums */
- _fc_seek(&page,(fragmented_reference *)&oy->fifo_returned,
- oy->fifo_returned_pos+22);
- if(chksum[0]!=_fc_get(&page) ||
- chksum[1]!=_fc_get(&page) ||
- chksum[2]!=_fc_get(&page) ||
- chksum[3]!=_fc_get(&page)){
+ _obc_seekr(&page,&oy->returned,
+ oy->fifo_cursor+22);
+ if(chksum[0]!=_obc_get(&page) ||
+ chksum[1]!=_obc_get(&page) ||
+ chksum[2]!=_obc_get(&page) ||
+ chksum[3]!=_obc_get(&page)){
+
/* D'oh. Mismatch! Corrupt page (or miscapture and not a page
at all). replace the computed checksum with the one actually
read in */
- _fc_seek(&page,(fragmented_reference *)&oy->fifo_returned,
- oy->fifo_returned_pos+22);
- _fc_set(&page,chksum[0]);
- _fc_set(&page,chksum[1]);
- _fc_set(&page,chksum[2]);
- _fc_set(&page,chksum[3]);
+
+ _obc_seekr(&page,&oy->returned,
+ oy->fifo_cursor+22);
+ _obc_set(&page,chksum[0]);
+ _obc_set(&page,chksum[1]);
+ _obc_set(&page,chksum[2]);
+ _obc_set(&page,chksum[3]);
- /* Bad checksum. Lose sync */
+ /* Bad checksum. Lose sync. */
goto sync_fail;
}
}
/* yes, have a whole page all ready to go */
{
- long bytes=oy->headerbytes+oy->bodybytes;
-
+ ret=oy->headerbytes+oy->bodybytes;
oy->unsynced=0;
oy->headerbytes=0;
oy->bodybytes=0;
-
- /* chase the return position forward */
- _sync_mark_fifo(oy,bytes);
-
- return(bytes);
+
+ ogg_reference_mark(&oy->returned); /* claim the memory range for now */
+ oy->fifo_cursor+=ret; /* advance the cursor past the page */
+
+ /* release any unneded fragments */
+ while(oy->fifo_tail && oy->fifo_cursor>=oy->fifo_tail->used){
+ ogg_buffer *temp=oy->fifo_tail;
+
+ oy->fifo_tail=temp->next;
+ if(!oy->fifo_tail)oy->fifo_head=0;
+ oy->fifo_cursor-=temp->used;
+
+ ogg_buffer_release(temp,&oy->bufferpool);
+ }
+ goto sync_adv;
}
sync_fail:
{
- long count=0;
oy->headerbytes=0;
oy->bodybytes=0;
-
+ ogg_reference_clear(&oy->returned); /* ...if any; would happen on
+ CRC fail */
+
+ _obc_seek(&page,oy->fifo_tail,oy->fifo_cursor+1);
+ ret--;
+
/* search forward through fragments for possible capture */
- while(oy->fifo_returned){
- unsigned char *next=memchr(oy->fifo_returned->data+
- oy->fifo_returned_pos,
+ while(page.segment){
+ /* invariant: fifo_cursor points to a position in fifo_tail */
+ unsigned char *next=memchr(page.segment->data+
+ page.cursor,
'O',
- oy->fifo_returned->used-
- oy->fifo_returned_pos);
+ page.segment->used-
+ page.cursor);
if(next){
- long bytes=next-oy->fifo_returned->data-oy->fifo_returned_pos;
- count+=bytes;
- oy->fifo_returned_pos+=bytes;
+ /* possible capture in this segment */
+ long bytes=next-page.segment->data-page.cursor;
+ page.cursor+=bytes;
+ ret-=bytes;
break;
}else{
- oy->fifo_returned_pos=0;
- oy->fifo_returned=oy->fifo_returned->next;
+ /* no capture. advance to next segment */
+ ret-=page.segment->used-page.cursor;
+ _obc_span(&page);
}
}
- return(-count);
+ oy->fifo_cursor-=ret;
}
- out_more:
- return(0);
+ sync_adv:
+ while(oy->fifo_tail && oy->fifo_cursor>=oy->fifo_tail->used){
+ ogg_buffer *temp=oy->fifo_tail;
+
+ oy->fifo_tail=temp->next;
+ if(!oy->fifo_tail)oy->fifo_head=0;
+ oy->fifo_cursor-=temp->used;
+
+ ogg_buffer_release(temp,&oy->bufferpool);
+ }
+
+ sync_out:
+ return(ret);
}
/* sync the stream and get a page. Keep trying until we find a page.
@@ -567,15 +535,14 @@
Returns pointers into buffered data; invalidated by next call to
_stream, _clear, _init, or _buffer */
-int ogg_sync_pageout(ogg_sync_state *oyi, ogg_page *og){
- _ogg_sync_state *oy=(_ogg_sync_state *)*oyi;
+int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og){
/* all we need to do is verify a page at the head of the stream
buffer. If it doesn't verify, we look for the next potential
frame */
while(1){
- long ret=ogg_sync_pageseek(oyi,og);
+ long ret=ogg_sync_pageseek(oy,og);
if(ret>0){
/* have a page */
return(1);
@@ -597,11 +564,17 @@
}
/* clear things to an initial state. Good to call, eg, before seeking */
-int ogg_sync_reset(ogg_sync_state *oyi){
- _ogg_sync_state *oy=(_ogg_sync_state *)*oyi;
- oy->fifo_returned=0;
- oy->fifo_returned_pos=0;
- _sync_release_fifo(oy);
+int ogg_sync_reset(ogg_sync_state *oy){
+ ogg_buffer *p=oy->fifo_tail;
+ ogg_buffer_state *bs=&oy->bufferpool;
+ while(p){
+ ogg_buffer *next=p->next;
+ ogg_buffer_release(p,bs);
+ p=next;
+ }
+ ogg_reference_release(&oy->returned);
+ ogg_reference_clear(&oy->returned);
+ oy->fifo_cursor=0;
oy->unsynced=0;
oy->headerbytes=0;
@@ -613,76 +586,137 @@
void ogg_page_checksum_set(ogg_page *og){
if(og){
- fragmented_cursor fc;
- fragmented_reference *fb;
+ ogg_buffer_cursor obc;
+ ogg_buffer_reference *fb;
+ ogg_buffer *buf;
ogg_uint32_t crc_reg=0;
int i,j;
+ int begin;
/* safety; needed for API behavior, but not framing code */
- _fc_seek(&fc,&og->header,22);
- _fc_set(&fc,0);
- _fc_set(&fc,0);
- _fc_set(&fc,0);
- _fc_set(&fc,0);
+ _obc_seekr(&obc,&og->header,22);
+ _obc_set(&obc,0);
+ _obc_set(&obc,0);
+ _obc_set(&obc,0);
+ _obc_set(&obc,0);
- i=og->header_len;
fb=&og->header;
+ i=fb->length;
+ buf=fb->buffer;
while(i){
- for(j=0;j<i && j<fb->used;j++)
- crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^fb->data[j]];
- i-=j;
- fb=fb->next;
+ begin=(fb->owner->encode_decode_flag?0:buf->refbeg);
+ for(j=begin;
+ j-begin<i && j<buf->used;
+ j++)
+ crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^buf->data[j]];
+ i-=j-begin;
+ buf=buf->next;
}
- i=og->body_len;
+
fb=&og->body;
+ i=fb->length;
+ buf=fb->buffer;
while(i){
- for(j=0;j<i && j<fb->used;j++)
- crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^fb->data[j]];
- i-=j;
- fb=fb->next;
+ begin=(fb->owner->encode_decode_flag?0:buf->refbeg);
+ for(j=begin;
+ j-begin<i && j<buf->used;
+ j++)
+ crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^buf->data[j]];
+ i-=j-begin;
+ buf=buf->next;
}
- _fc_seek(&fc,&og->header,22);
- _fc_set(&fc,crc_reg);
- _fc_set(&fc,crc_reg>>8);
- _fc_set(&fc,crc_reg>>16);
- _fc_set(&fc,crc_reg>>24);
+ _obc_seekr(&obc,&og->header,22);
+ _obc_set(&obc,crc_reg);
+ _obc_set(&obc,crc_reg>>8);
+ _obc_set(&obc,crc_reg>>16);
+ _obc_set(&obc,crc_reg>>24);
}
}
/* ENCODING PRIMITIVES: raw stream and page layer *******************/
-/* The encode sync layer is only a convenience; it eliminates the need
- to parse the fragmented buffer data structure */
+/* On encode side, the sync layer provides centralized memory
+ management, buffering, and and abstraction to deal with fragmented
+ linked buffers as an iteration over flat char buffers.
+ ogg_sync_destroy is as in decode. */
+
+ogg_sync_state *ogg_sync_encode_create(void){
+ ogg_sync_state *oy=_ogg_calloc(1,sizeof(*oy));
+ memset(oy,0,sizeof(*oy));
+ ogg_buffer_init(&oy->bufferpool,0);
+ return oy;
+}
+
+static void _ogg_sync_addref(ogg_sync_state *oy,ogg_buffer_reference *fb){
+ /* trim fragments off reference up to beginning */
+ while(fb->begin>=fb->buffer->used){
+ ogg_buffer *next=fb->buffer->next;
+ fb->begin-=fb->buffer->used-fb->buffer->refbeg;
+ ogg_buffer_release(fb->buffer,&oy->bufferpool);
+ fb->buffer=next;
+ }
+ /* pretruncate buffer if needed */
+ fb->buffer=ogg_buffer_pretruncate(fb->buffer,&oy->bufferpool,fb->begin);
+ /* add fragments to sync chain */
+ while(fb->length){
+ ogg_buffer *now=fb->buffer;
+ ogg_buffer *next=now->next;
+ fb->buffer=next;
+ now->next=0;
+
+ if(!oy->fifo_tail)oy->fifo_tail=now;
+ if(oy->fifo_head)oy->fifo_head->next=now;
+ oy->fifo_head=now;
+
+ if(fb->length<=now->used-now->refbeg){
+ now->used=fb->length+now->refbeg;
+ break;
+ }
+ fb->length-=now->used-now->refbeg;
+ }
+ /* release unused fragments at end of buffer */
+ while(fb->buffer){
+ ogg_buffer *next=fb->buffer->next;
+ ogg_buffer_release(fb->buffer,&oy->bufferpool);
+ fb->buffer=next;
+ }
+ memcpy(fb,0,sizeof(*fb));
+}
-extern int ogg_page_getbuffer(ogg_page *og, unsigned char **buffer){
- int bytes;
+extern int ogg_sync_pagein(ogg_sync_state *oy,ogg_page *og){
+ /* free up returned */
+ ogg_reference_release(&oy->returned);
+ ogg_reference_clear(&oy->returned);
- if(og->header_len){
- bytes=og->header.used;
- if(bytes>og->header_len)bytes=og->header_len;
- *buffer=og->header.data;
- og->header_len-=bytes;
+ /* buffer new */
+ _ogg_sync_addref(oy,&og->header);
+ _ogg_sync_addref(oy,&og->body);
+ return(0);
+}
- og->header.data=og->header.next->data;
- og->header.used=og->header.next->used;
- og->header.next=og->header.next->next;
+extern long ogg_sync_bufferout(ogg_sync_state *oy, unsigned char **buffer){
- return(bytes);
+ /* free up returned */
+ ogg_reference_release(&oy->returned);
+ ogg_reference_clear(&oy->returned);
+
+ /* return next fragment */
+ if(!oy->fifo_tail){
+ *buffer=0;
+ return 0;
}
-
- if(og->body_len){
- bytes=og->body.used;
- if(bytes>og->body_len)bytes=og->body_len;
- *buffer=og->body.data;
- og->body_len-=bytes;
-
- og->body.data=og->body.next->data;
- og->body.used=og->body.next->used;
- og->body.next=og->body.next->next;
- return(bytes);
+ {
+ ogg_buffer *ret=oy->fifo_tail;
+ oy->fifo_tail=ret->next;
+ if(!oy->fifo_tail)oy->fifo_head=0;
+ ret->next=0;
+ oy->returned.buffer=ret;
+ oy->returned.begin=0;
+ oy->returned.length=ret->used-ret->refbeg;
+ *buffer=ret->data+ret->refbeg;
+ return ret->used-ret->refbeg;
}
- return(0);
}
<p><p>No revision
<p>No revision
<p>1.1.2.1 +1317 -0 ogg/src/Attic/stream.c
<p><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