diff options
| author | Monty <xiphmont@xiph.org> | 1999-11-02 11:17:38 +0000 |
|---|---|---|
| committer | Monty <xiphmont@xiph.org> | 1999-11-02 11:17:38 +0000 |
| commit | bc58e46b73a36b79d698a2e93bd2584d9bd5f2ed (patch) | |
| tree | 31d16180c5e73599337e28ab5c4a2adee2988d61 /lib | |
| parent | 3125d16e218e49a0d17f876767fecfd30d6306d7 (diff) | |
| download | libvorbis-git-bc58e46b73a36b79d698a2e93bd2584d9bd5f2ed.tar.gz | |
First cut on chaining_example.c
Monty
svn path=/trunk/vorbis/; revision=157
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/Makefile.in | 10 | ||||
| -rw-r--r-- | lib/block.c | 5 | ||||
| -rw-r--r-- | lib/chaining_example.c | 479 | ||||
| -rw-r--r-- | lib/codec.h | 3 | ||||
| -rw-r--r-- | lib/framing.c | 187 |
5 files changed, 575 insertions, 109 deletions
diff --git a/lib/Makefile.in b/lib/Makefile.in index aeb880e3..aee6429f 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -1,6 +1,6 @@ # vorbis makefile configured for use with gcc on any platform -# $Id: Makefile.in,v 1.12 1999/10/18 09:41:07 xiphmont Exp $ +# $Id: Makefile.in,v 1.13 1999/11/02 11:17:34 xiphmont Exp $ ############################################################################### # # @@ -34,7 +34,7 @@ LFILES = framing.o mdct.o smallft.o block.o envelope.o window.o\ lsp.o lpc.o analysis.o synthesis.o psy.o info.o bitwise.o\ spectrum.o -EFILES = encoder_example.o decoder_example.o +EFILES = encoder_example.o decoder_example.o chaining_example.o all: $(MAKE) target CFLAGS="$(OPT)" @@ -48,7 +48,7 @@ analysis: profile: $(MAKE) target CFLAGS="$(PROFILE)" -target: libvorbis.a encoder_example decoder_example +target: libvorbis.a encoder_example decoder_example chaining_example selftest: $(MAKE) clean @@ -67,6 +67,10 @@ decoder_example: $(EFILES) libvorbis.a $(CC) $(CFLAGS) $(LDFLAGS) decoder_example.o libvorbis.a -o \ decoder_example -lm +chaining_example: $(EFILES) libvorbis.a + $(CC) $(CFLAGS) $(LDFLAGS) chaining_example.o libvorbis.a -o \ + chaining_example -lm + libvorbis.a: $(LFILES) $(AR) -r libvorbis.a $(LFILES) $(RANLIB) libvorbis.a diff --git a/lib/block.c b/lib/block.c index 47674ce2..ffa574e9 100644 --- a/lib/block.c +++ b/lib/block.c @@ -111,8 +111,9 @@ int vorbis_block_clear(vorbis_block *vb){ free(vb->pcm[i]); free(vb->pcm); } - if(vb->vd->analysisp) - _oggpack_writeclear(&vb->opb); + if(vb->vd) + if(vb->vd->analysisp) + _oggpack_writeclear(&vb->opb); memset(vb,0,sizeof(vorbis_block)); return(0); diff --git a/lib/chaining_example.c b/lib/chaining_example.c index 3f3f95fa..df488357 100644 --- a/lib/chaining_example.c +++ b/lib/chaining_example.c @@ -14,11 +14,13 @@ function: simple example of opening/seeking chained bitstreams author: Monty <xiphmont@mit.edu> modifications by: Monty - last modification date: Oct 29 1999 + last modification date: Nov 02 1999 ********************************************************************/ - +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> #include <stdio.h> #include <math.h> #include "codec.h" @@ -29,16 +31,16 @@ multiplexing] is not allowed in Vorbis) */ /* A Vorbis file can be played beginning to end (streamed) without - worrying ahead of time about chaining. If we have the whole file, - however, and want random access (seeking/scrubbing) or desire to - know the total length/time of a file, we need to account for the - possibility of chaining. */ + worrying ahead of time about chaining (see decoder_example.c). If + we have the whole file, however, and want random access + (seeking/scrubbing) or desire to know the total length/time of a + file, we need to account for the possibility of chaining. */ /* We can handle things a number of ways; we can determine the entire - bitstream structure right off the bat, or piece it together later. + bitstream structure right off the bat, or find pieces on demand. This example determines and caches structure for the entire - bitstream, but builds a virtual decoder on the fly when moving from - one link of the chain to another */ + bitstream, but builds a virtual decoder on the fly when moving + between links in the chain */ /* There are also different ways to implement seeking. Enough information exists in an Ogg bitstream to seek to @@ -47,43 +49,466 @@ want course navigation through the stream. */ typedef struct { + FILE *f; + int seekable; + long offset; + long end; + ogg_sync_state oy; + /* If the FILE handle isn't seekable (eg, a pipe), only the current + stream appears */ + int links; + long *offsets; + long *serialnos; + size64 *pcmlengths; + vorbis_info *vi; - - -} Vorbis_File; - -typedef struct { - ogg_sync_state oy; /* sync and verify incoming physical bitstream */ + /* Decoding working state local storage */ + int ready; ogg_stream_state os; /* take physical pages, weld into a logical stream of packets */ - ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */ - ogg_packet op; /* one raw packet of data for decode */ - - vorbis_info vi; /* struct that stores all the static vorbis bitstream - settings */ vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */ vorbis_block vb; /* local working space for packet->PCM decode */ + +} OggVorbis_File; + + +/************************************************************************* + * Many, many internal helpers. The intention is not to be confusing; + * rampant duplication and monolithic function implementation would be + * harder to understand anyway. The high level functions are last. Begin + * grokking near the end of the file */ + +/* read a little more data from the file/pipe into the ogg_sync framer */ +#define CHUNKSIZE 4096 +static long _get_data(OggVorbis_File *vf){ + char *buffer=ogg_sync_buffer(&vf->oy,4096); + long bytes=fread(buffer,1,4096,vf->f); + ogg_sync_wrote(&vf->oy,bytes); + return(bytes); +} + +/* save a tiny smidge of verbosity to make the code more readable */ +static void _seek_helper(OggVorbis_File *vf,long offset){ + fseek(vf->f,offset,SEEK_SET); + vf->offset=offset; + ogg_sync_reset(&vf->oy); +} + +/* The read/seek functions track absolute position within the stream */ + +/* from the head of the stream, get the next page. boundary specifies + if the function is allowed to fetch more data from the stream (and + how much) or only use internally buffered data. + + boundary: -1) unbounded search + 0) read no additional data; use cached only + n) search for a new page beginning for n bytes + + return: -1) did not find a page + n) found a page at absolute offset n */ + +static long _get_next_page(OggVorbis_File *vf,ogg_page *og,int boundary){ + if(boundary>0)boundary+=vf->offset; + while(1){ + long more; + + if(boundary>0 && vf->offset>=boundary)return(-1); + more=ogg_sync_pageseek(&vf->oy,og); + + if(more<0){ + /* skipped n bytes */ + vf->offset-=more; + }else{ + if(more==0){ + /* send more paramedics */ + if(!boundary)return(-1); + if(_get_data(vf)<=0)return(-1); + }else{ + /* got a page. Return the offset at the page beginning, + advance the internal offset past the page end */ + long ret=vf->offset; + vf->offset+=more; + return(ret); + + } + } + } +} + +/* find the latest page beginning before the current stream cursor + position. Much dirtier than the above as Ogg doesn't have any + backward search linkage. no 'readp' as it will certainly have to + read. */ +static long _get_prev_page(OggVorbis_File *vf,ogg_page *og){ + long begin=vf->offset; + long ret; + int offset=-1; + + while(offset==-1){ + begin-=CHUNKSIZE; + _seek_helper(vf,begin); + while(vf->offset<begin+CHUNKSIZE){ + ret=_get_next_page(vf,og,begin+CHUNKSIZE-vf->offset); + if(ret==-1){ + break; + }else{ + offset=ret; + } + } + } + + /* we have the offset. Actually snork and hold the page now */ + _seek_helper(vf,offset); + ret=_get_next_page(vf,og,CHUNKSIZE); + if(ret==-1){ + /* this shouldn't be possible */ + fprintf(stderr,"Missed page fencepost at end of logical bitstream. " + "Exiting.\n"); + exit(1); + } + return(offset); +} + +/* finds each bitstream link one at a time using a bisection search + (has to begin by knowing the offset of the lb's initial page). + Recurses for each link so it can alloc the link storage after + finding them all, then unroll and fill the cache at the same time */ +static void _bisect_forward_serialno(OggVorbis_File *vf, + long begin, + long searched, + long end, + long currentno, + long m){ + long endsearched=end; + long next=end; + ogg_page og; - char *buffer; - int bytes; - int i; - int eos=0; + /* the below guards against garbage seperating the last and + first pages of two links. */ + while(searched<endsearched){ + long bisect; + long ret; + + if(endsearched-searched<CHUNKSIZE){ + bisect=searched; + }else{ + bisect=(searched+endsearched)/2; + } + + _seek_helper(vf,bisect); + ret=_get_next_page(vf,&og,-1); + if(ret<0 || ogg_page_serialno(&og)!=currentno){ + endsearched=bisect; + if(ret>=0)next=ret; + }else{ + searched=ret+og.header_len+og.body_len; + } + } + if(searched>=end){ + vf->links=m+1; + vf->offsets=malloc((m+2)*sizeof(long)); + vf->offsets[m+1]=searched; + }else{ + _bisect_forward_serialno(vf,next,next, + end,ogg_page_serialno(&og),m+1); + } + + vf->offsets[m]=begin; +} +/* uses the local ogg_stream storage in vf; this is important for + non-streaming input sources */ +static int _fetch_headers(OggVorbis_File *vf,vorbis_info *vi,long *serialno){ + ogg_page og; + ogg_packet op; + int i,ret; + ret=_get_next_page(vf,&og,CHUNKSIZE); + if(ret==-1){ + fprintf(stderr,"Did not find initial header for bitstream.\n"); + return -1; + } + + if(serialno)*serialno=ogg_page_serialno(&og); + ogg_stream_init(&vf->os,ogg_page_serialno(&og)); + + /* extract the initial header from the first page and verify that the + Ogg bitstream is in fact Vorbis data */ + + vorbis_info_init(vi); + + i=0; + while(i<3){ + ogg_stream_pagein(&vf->os,&og); + while(i<3){ + int result=ogg_stream_packetout(&vf->os,&op); + if(result==0)break; + if(result==-1){ + fprintf(stderr,"Corrupt header in logical bitstream. " + "Exiting.\n"); + goto bail_header; + } + if(vorbis_info_headerin(vi,&op)){ + fprintf(stderr,"Illegal header in logical bitstream. " + "Exiting.\n"); + goto bail_header; + } + i++; + } + if(i<3) + if(_get_next_page(vf,&og,1)<0){ + fprintf(stderr,"Missing header in logical bitstream. " + "Exiting.\n"); + goto bail_header; + } + } + return 0; + bail_header: + vorbis_info_clear(vi); + ogg_stream_clear(&vf->os); + return -1; +} -} Vorbis_Decode; +/* last step of the OggVorbis_File initialization; get all the + vorbis_info structs and PCM positions. Only called by the seekable + initialization (local stream storage is hacked slightly; pay + attention to how that's done) */ +static void _prefetch_all_headers(OggVorbis_File *vf,vorbis_info *first){ + ogg_page og; + int i,ret; + + vf->vi=malloc(vf->links*sizeof(vorbis_info)); + vf->pcmlengths=malloc(vf->links*sizeof(size64)); + vf->serialnos=malloc(vf->links*sizeof(long)); + + for(i=0;i<vf->links;i++){ + if(first && i==0){ + /* we already grabbed the initial header earlier. This just + saves the waste of grabbing it again */ + memcpy(vf->vi+i,first,sizeof(vorbis_info)); + memset(first,0,sizeof(vorbis_info)); + }else{ + /* seek to the location of the initial header */ -int vorbis_open_file(FILE *f,Vorbis_File *vf){ + _seek_helper(vf,vf->offsets[i]); + if(_fetch_headers(vf,vf->vi+i,NULL)==-1){ + vorbis_info_clear(vf->vi+i); + fprintf(stderr,"Error opening logical bitstream #%d.\n\n",i+1); + + ogg_stream_clear(&vf->os); /* clear local storage. This is not + done in _fetch_headers, as that may + be called in a non-seekable stream + (in which case, we need to preserve + the stream local storage) */ + } + } + /* get the serial number and PCM length of this link. To do this, + get the last page of the stream */ + { + long end=vf->offsets[i+1]; + _seek_helper(vf,end); + while(1){ + ret=_get_prev_page(vf,&og); + if(ret==-1){ + /* this should not be possible */ + fprintf(stderr,"Could not find last page of logical " + "bitstream #%d\n\n",i); + vorbis_info_clear(vf->vi+i); + break; + } + if(ogg_page_frameno(&og)!=-1){ + vf->serialnos[i]=ogg_page_serialno(&og); + vf->pcmlengths[i]=ogg_page_frameno(&og); + break; + } + } + } + } } -int vorbis_clear_file(Vorbis_File *vf){ +static int _open_seekable(OggVorbis_File *vf){ + vorbis_info initial; + long serialno,end; + int ret; + ogg_page og; + + /* is this even vorbis...? */ + ret=_fetch_headers(vf,&initial,&serialno); + ogg_stream_clear(&vf->os); + if(ret==-1)return(-1); + + /* we can seek, so set out learning all about this file */ + vf->seekable=1; + fseek(vf->f,0,SEEK_END); /* Yes, I know I used lseek earlier. */ + vf->offset=vf->end=ftell(vf->f); + + /* We get the offset for the last page of the physical bitstream. + Most OggVorbis files will contain a single logical bitstream */ + end=_get_prev_page(vf,&og); + /* moer than one logical bitstream? */ + if(ogg_page_serialno(&og)!=serialno){ + /* Chained bitstream. Bisect-search each logical bitstream + section. Do so based on serial number only */ + _bisect_forward_serialno(vf,0,0,end+1,serialno,0); + }else{ + + /* Only one logical bitstream */ + _bisect_forward_serialno(vf,0,end,end+1,serialno,0); + + } + + _prefetch_all_headers(vf,&initial); + + return(0); +} + +static int _open_nonseekable(OggVorbis_File *vf){ + vorbis_info vi; + long serialno; + + /* Try to fetch the headers, maintaining all the storage */ + if(_fetch_headers(vf,&vi,&serialno)==-1)return(-1); + + /* we cannot seek. Set up a 'single' (current) logical bitstream entry */ + vf->links=1; + vf->vi=malloc(sizeof(vorbis_info)); + vf->serialnos=malloc(sizeof(long)); + + memcpy(vf->vi,&vi,sizeof(vorbis_info)); + vf->serialnos[0]=serialno; + return 0; +} + +/********************************************************************** + * The helpers are over; it's all toplevel interface from here on out */ + +/* clear out the OggVorbis_File struct */ +int ov_clear(OggVorbis_File *vf){ + if(vf){ + vorbis_block_clear(&vf->vb); + vorbis_dsp_clear(&vf->vd); + ogg_stream_clear(&vf->os); + + if(vf->vi && vf->links){ + int i; + for(i=0;i<vf->links;i++) + vorbis_info_clear(vf->vi+i); + free(vf->vi); + } + if(vf->pcmlengths)free(vf->pcmlengths); + if(vf->serialnos)free(vf->serialnos); + if(vf->offsets)free(vf->offsets); + ogg_sync_clear(&vf->oy); + if(vf->f)fclose(vf->f); + memset(vf,0,sizeof(OggVorbis_File)); + } + return(0); } +/* inspects the OggVorbis file and finds/documents all the logical + bitstreams contained in it. Tries to be tolerant of logical + bitstream sections that are truncated/woogie. */ +int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){ + long offset=lseek(fileno(f),0,SEEK_CUR); + int ret; + + memset(vf,0,sizeof(OggVorbis_File)); + vf->f=f; + + /* init the framing state */ + ogg_sync_init(&vf->oy); + + /* perhaps some data was previously read into a buffer for testing + against other stream types. Allow initialization from this + previously read data (as we may be reading from a non-seekable + stream) */ + if(initial){ + char *buffer=ogg_sync_buffer(&vf->oy,ibytes); + memcpy(buffer,initial,ibytes); + ogg_sync_wrote(&vf->oy,ibytes); + } + + /* can we seek? Stevens suggests the seek test was portable */ + if(offset!=-1){ + ret=_open_seekable(vf); + }else{ + ret=_open_nonseekable(vf); + } + if(ret){ + vf->f=NULL; + ov_clear(vf); + } + return(ret); +} + +double ov_lbtime(OggVorbis_File *vf,int i){ + if(i>=0 && i<vf->links) + return((float)(vf->pcmlengths[i])/vf->vi[i].rate); + return(0); +} + +long ov_totaltime(OggVorbis_File *vf){ + double acc=0; + int i; + for(i=0;i<vf->links;i++) + acc+=ov_lbtime(vf,i); + return(acc); +} + +/* seek to an offset relative to the *compressed* data */ +int ov_seek_stream; + + +/* seek to an offset relative to the decompressed *output* stream */ +int ov_seek_pcm; + + +int main(){ + OggVorbis_File ov; + int i; + + /* open the file/pipe on stdin */ + if(ov_open(stdin,&ov,NULL,-1)==-1){ + printf("Could not open input as an OggVorbis file.\n\n"); + exit(1); + } + + /* print details about each logical bitstream in the input */ + if(ov.seekable){ + printf("Input bitstream contained %d logical bitstream section(s).\n", + ov.links); + printf("Total bitstream playing time: %ld seconds\n\n", + (long)ov_totaltime(&ov)); + + }else{ + printf("Standard input was not seekable.\n" + "First logical bitstream information:\n\n"); + } + + for(i=0;i<ov.links;i++){ + printf("\tlogical bitstream section %d information:\n",i+1); + printf("\t\tsample rate: %ldHz\n",ov.vi[i].rate); + printf("\t\tchannels: %d\n",ov.vi[i].channels); + printf("\t\tserial number: %ld\n",ov.serialnos[i]); + printf("\t\traw length: %ldbytes\n",(ov.offsets? + ov.offsets[i+1]-ov.offsets[i]: + -1)); + printf("\t\tplay time: %lds\n\n",(long)ov_lbtime(&ov,i)); + } + + ov_clear(&ov); + return 0; +} + + + + + diff --git a/lib/codec.h b/lib/codec.h index 3815e04d..412c1e17 100644 --- a/lib/codec.h +++ b/lib/codec.h @@ -102,7 +102,7 @@ typedef struct { typedef struct vorbis_info{ int channels; - int rate; + long rate; int version; char **user_comments; @@ -329,6 +329,7 @@ extern int ogg_sync_reset(ogg_sync_state *oy); extern char *ogg_sync_buffer(ogg_sync_state *oy, long size); extern int ogg_sync_wrote(ogg_sync_state *oy, long bytes); +extern long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og); extern int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og); extern int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og); extern int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op); diff --git a/lib/framing.c b/lib/framing.c index 2cbaf66a..ce124592 100644 --- a/lib/framing.c +++ b/lib/framing.c @@ -417,9 +417,108 @@ int ogg_sync_wrote(ogg_sync_state *oy, long bytes){ return(0); } -/* sync the stream. If we had to recapture, return -1. If we - couldn't capture at all, return 0. If a page was already framed - and ready to go, return 1 and fill in the page struct. +/* sync the stream. This is meant to be useful for finding page + boundaries. + + return values for this: + -n) skipped n bytes + 0) page not ready; more data (no bytes skipped) + n) page synced at current location; page length n bytes + +*/ + +long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){ + unsigned char *page=oy->data+oy->returned; + unsigned char *next; + long bytes=oy->fill-oy->returned; + + if(oy->headerbytes==0){ + int headerbytes,i; + if(bytes<27)return(0); /* not enough for a header */ + + /* verify capture pattern */ + if(memcmp(page,"OggS",4))goto sync_fail; + + headerbytes=page[26]+27; + if(bytes<headerbytes)return(0); /* not enough for header + seg table */ + + /* count up body length in the segment table */ + + for(i=0;i<page[26];i++) + oy->bodybytes+=page[27+i]; + oy->headerbytes=headerbytes; + } + + if(oy->bodybytes+oy->headerbytes>bytes)return(0); + + /* The whole test page is buffered. Verify the checksum */ + { + /* Grab the checksum bytes, set the header field to zero */ + char chksum[4]; + ogg_page log; + + memcpy(chksum,page+22,4); + memset(page+22,0,4); + + /* set up a temp page struct and recompute the checksum */ + log.header=page; + log.header_len=oy->headerbytes; + log.body=page+oy->headerbytes; + log.body_len=oy->bodybytes; + _os_checksum(&log); + + /* Compare */ + if(memcmp(chksum,page+22,4)){ + /* D'oh. Mismatch! Corrupt page (or miscapture and not a page + at all) */ + /* replace the computed checksum with the one actually read in */ + memcpy(page+22,chksum,4); + + /* Bad checksum. Lose sync */ + goto sync_fail; + } + } + + /* yes, have a whole page all ready to go */ + { + unsigned char *page=oy->data+oy->returned; + long bytes; + + if(og){ + og->header=page; + og->header_len=oy->headerbytes; + og->body=page+oy->headerbytes; + og->body_len=oy->bodybytes; + } + + oy->unsynced=0; + oy->returned+=(bytes=oy->headerbytes+oy->bodybytes); + oy->headerbytes=0; + oy->bodybytes=0; + return(bytes); + } + + sync_fail: + + oy->headerbytes=0; + oy->bodybytes=0; + + /* search for possible capture */ + next=memchr(page+1,'O',bytes-1); + if(!next) + next=oy->data+oy->fill; + + oy->returned=next-oy->data; + return(-(next-page)); +} + +/* sync the stream and get a page. Keep trying until we find a page. + Supress 'sync errors' after reporting the first. + + return values: + -1) recapture (hole in data) + 0) need more data + 1) page returned Returns pointers into buffered data; invalidated by next call to _stream, _clear, _init, or _buffer */ @@ -431,87 +530,23 @@ int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og){ frame */ while(1){ - unsigned char *page=oy->data+oy->returned; - long bytes=oy->fill-oy->returned; - - if(oy->headerbytes==0){ - int headerbytes,i; - if(bytes<27)return(0); /* not enough for a header */ - - /* verify capture pattern */ - if(memcmp(page,"OggS",4))goto sync_fail; - - headerbytes=page[26]+27; - if(bytes<headerbytes)return(0); /* not enough for header + seg table */ - - /* count up body length in the segment table */ - - for(i=0;i<page[26];i++) - oy->bodybytes+=page[27+i]; - oy->headerbytes=headerbytes; + long ret=ogg_sync_pageseek(oy,og); + if(ret>0){ + /* have a page */ + return(1); } - - if(oy->bodybytes+oy->headerbytes>bytes)return(0); - - /* The whole test page is buffered. Verify the checksum */ - { - /* Grab the checksum bytes, set the header field to zero */ - char chksum[4]; - ogg_page log; - - memcpy(chksum,page+22,4); - memset(page+22,0,4); - - /* set up a temp page struct and recompute the checksum */ - log.header=page; - log.header_len=oy->headerbytes; - log.body=page+oy->headerbytes; - log.body_len=oy->bodybytes; - _os_checksum(&log); - - /* Compare */ - if(memcmp(chksum,page+22,4)){ - /* D'oh. Mismatch! Corrupt page (or miscapture and not a page - at all) */ - /* replace the computed checksum with the one actually read in */ - memcpy(page+22,chksum,4); - - /* Bad checksum. Lose sync */ - goto sync_fail; - } + if(ret==0){ + /* need more data */ + return(0); } - - og->header=page; - og->header_len=oy->headerbytes; - og->body=page+oy->headerbytes; - og->body_len=oy->bodybytes; - - oy->unsynced=0; - oy->returned+=oy->headerbytes+oy->bodybytes; - oy->headerbytes=0; - oy->bodybytes=0; - - return(1); - - sync_fail: - oy->headerbytes=0; - oy->bodybytes=0; - - /* search for possible capture */ - - page=memchr(page+1,'O',bytes-1); - if(page) - oy->returned=page-oy->data; - else - oy->returned=oy->fill; - + /* head did not start a synced page... skipped some bytes */ if(!oy->unsynced){ oy->unsynced=1; return(-1); } - /* loop; verifier above will take care of determining capture or not */ + /* loop. keep looking */ } } |
