123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590 |
- /********************************************************************
- * *
- * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE. *
- * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
- * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE. *
- * PLEASE READ THESE TERMS DISTRIBUTING. *
- * *
- * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-2000 *
- * by Monty <monty@xiph.org> and the XIPHOPHORUS Company *
- * http://www.xiph.org/ *
- * *
- ********************************************************************
- function: code raw [Vorbis] packets into framed OggSquish stream and
- decode Ogg streams back into raw packets
- last mod: $Id: framing.c,v 1.14.4.2 2000/04/21 16:35:39 xiphmont Exp $
- note: The CRC code is directly derived from public domain code by
- Ross Williams (ross@guest.adelaide.edu.au). See docs/framing.html
- for details.
- ********************************************************************/
- #include <stdlib.h>
- #include <string.h>
- #include "vorbis/codec.h"
- #include "misc.h"
- /* A complete description of Ogg framing exists in docs/framing.html */
- int ogg_page_version(ogg_page *og){
- return((int)(og->header[4]));
- }
- int ogg_page_continued(ogg_page *og){
- return((int)(og->header[5]&0x01));
- }
- int ogg_page_bos(ogg_page *og){
- return((int)(og->header[5]&0x02));
- }
- int ogg_page_eos(ogg_page *og){
- return((int)(og->header[5]&0x04));
- }
- int64_t ogg_page_frameno(ogg_page *og){
- unsigned char *page=og->header;
- int64_t pcmpos=page[13]&(0xff);
- pcmpos= (pcmpos<<8)|(page[12]&0xff);
- pcmpos= (pcmpos<<8)|(page[11]&0xff);
- pcmpos= (pcmpos<<8)|(page[10]&0xff);
- pcmpos= (pcmpos<<8)|(page[9]&0xff);
- pcmpos= (pcmpos<<8)|(page[8]&0xff);
- pcmpos= (pcmpos<<8)|(page[7]&0xff);
- pcmpos= (pcmpos<<8)|(page[6]&0xff);
- return(pcmpos);
- }
- int ogg_page_serialno(ogg_page *og){
- return(og->header[14] |
- (og->header[15]<<8) |
- (og->header[16]<<16) |
- (og->header[17]<<24));
- }
-
- int ogg_page_pageno(ogg_page *og){
- return(og->header[18] |
- (og->header[19]<<8) |
- (og->header[20]<<16) |
- (og->header[21]<<24));
- }
- /* helper to initialize lookup for direct-table CRC */
- static u_int32_t crc_lookup[256];
- static int crc_ready=0;
- static u_int32_t _ogg_crc_entry(unsigned long index){
- int i;
- unsigned long r;
- r = index << 24;
- for (i=0; i<8; i++)
- if (r & 0x80000000UL)
- r = (r << 1) ^ 0x04c11db7; /* The same as the ethernet generator
- polynomial, although we use an
- unreflected alg and an init/final
- of 0, not 0xffffffff */
- else
- r<<=1;
- return (r & 0xffffffffUL);
- }
- /* mind this in threaded code; sync_init and stream_init call it.
- It's thread safe only after the first time it returns */
- static void _ogg_crc_init(void){
- if(!crc_ready){
- /* initialize the crc_lookup table */
- int i;
- for (i=0;i<256;i++)
- crc_lookup[i]=_ogg_crc_entry((unsigned long)i);
- crc_ready=0;
- }
- }
- /* init the encode/decode logical stream state */
- int ogg_stream_init(ogg_stream_state *os,int serialno){
- if(os){
- memset(os,0,sizeof(ogg_stream_state));
- os->body_storage=16*1024;
- os->body_data=malloc(os->body_storage*sizeof(char));
- os->lacing_storage=1024;
- os->lacing_vals=malloc(os->lacing_storage*sizeof(int));
- os->pcm_vals=malloc(os->lacing_storage*sizeof(int64_t));
- /* initialize the crc_lookup table if not done */
- _ogg_crc_init();
- os->serialno=serialno;
- return(0);
- }
- return(-1);
- }
- /* _clear does not free os, only the non-flat storage within */
- int ogg_stream_clear(ogg_stream_state *os){
- if(os){
- if(os->body_data)free(os->body_data);
- if(os->lacing_vals)free(os->lacing_vals);
- if(os->pcm_vals)free(os->pcm_vals);
- memset(os,0,sizeof(ogg_stream_state));
- }
- return(0);
- }
- int ogg_stream_destroy(ogg_stream_state *os){
- if(os){
- ogg_stream_clear(os);
- free(os);
- }
- return(0);
- }
- /* Helpers for ogg_stream_encode; this keeps the structure and
- what's happening fairly clear */
- static void _os_body_expand(ogg_stream_state *os,int needed){
- if(os->body_storage<=os->body_fill+needed){
- os->body_storage+=(needed+1024);
- os->body_data=realloc(os->body_data,os->body_storage);
- }
- }
- static void _os_lacing_expand(ogg_stream_state *os,int needed){
- if(os->lacing_storage<=os->lacing_fill+needed){
- os->lacing_storage+=(needed+32);
- os->lacing_vals=realloc(os->lacing_vals,os->lacing_storage*sizeof(int));
- os->pcm_vals=realloc(os->pcm_vals,os->lacing_storage*sizeof(int64_t));
- }
- }
- /* checksum the page */
- /* Direct table CRC; note that this will be faster in the future if we
- perform the checksum silmultaneously with other copies */
- static void _os_checksum(ogg_page *og){
- u_int32_t crc_reg=0;
- int i;
- for(i=0;i<og->header_len;i++)
- crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->header[i]];
- for(i=0;i<og->body_len;i++)
- crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->body[i]];
-
- og->header[22]=crc_reg&0xff;
- og->header[23]=(crc_reg>>8)&0xff;
- og->header[24]=(crc_reg>>16)&0xff;
- og->header[25]=(crc_reg>>24)&0xff;
- }
- /* submit data to the internal buffer of the framing engine */
- int ogg_stream_packetin(ogg_stream_state *os,ogg_packet *op){
- int lacing_vals=op->bytes/255+1,i;
- /* make sure we have the buffer storage */
- _os_body_expand(os,op->bytes);
- _os_lacing_expand(os,lacing_vals);
- /* Copy in the submitted packet. Yes, the copy is a waste; this is
- the liability of overly clean abstraction for the time being. It
- will actually be fairly easy to eliminate the extra copy in the
- future */
- memcpy(os->body_data+os->body_fill,op->packet,op->bytes);
- os->body_fill+=op->bytes;
- /* Store lacing vals for this packet */
- for(i=0;i<lacing_vals-1;i++){
- os->lacing_vals[os->lacing_fill+i]=255;
- os->pcm_vals[os->lacing_fill+i]=os->pcmpos;
- }
- os->lacing_vals[os->lacing_fill+i]=(op->bytes)%255;
- os->pcmpos=os->pcm_vals[os->lacing_fill+i]=op->frameno;
- /* flag the first segment as the beginning of the packet */
- os->lacing_vals[os->lacing_fill]|= 0x100;
- os->lacing_fill+=lacing_vals;
- /* for the sake of completeness */
- os->packetno++;
- if(op->e_o_s)os->e_o_s=1;
- return(0);
- }
- /* This constructs pages from buffered packet segments. The pointers
- returned are to static buffers; do not free. The returned buffers are
- good only until the next call (using the same ogg_stream_state) */
- int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og){
- int i;
- if(os->body_returned){
- /* advance packet data according to the body_returned pointer. We
- had to keep it around to return a pointer into the buffer last
- call */
- os->body_fill-=os->body_returned;
- if(os->body_fill)
- memmove(os->body_data,os->body_data+os->body_returned,
- os->body_fill*sizeof(char));
- os->body_returned=0;
- }
- if((os->e_o_s&&os->lacing_fill) || /* 'were done, now flush' case */
- os->body_fill > 4096 || /* 'page nominal size' case */
- os->lacing_fill>=255 || /* 'segment table full' case */
- (os->lacing_fill&&!os->b_o_s)){ /* 'initial header page' case */
- int vals=0,bytes=0;
- int maxvals=(os->lacing_fill>255?255:os->lacing_fill);
- long acc=0;
- int64_t pcm_pos=os->pcm_vals[0];
- /* construct a page */
- /* decide how many segments to include */
- /* If this is the initial header case, the first page must only include
- the initial header packet */
- if(os->b_o_s==0){ /* 'initial header page' case */
- pcm_pos=0;
- for(vals=0;vals<maxvals;vals++){
- if((os->lacing_vals[vals]&0x0ff)<255){
- vals++;
- break;
- }
- }
- }else{
- for(vals=0;vals<maxvals;vals++){
- if(acc>4096)break;
- acc+=os->lacing_vals[vals]&0x0ff;
- pcm_pos=os->pcm_vals[vals];
- }
- }
- /* construct the header in temp storage */
- memcpy(os->header,"OggS",4);
- /* stream structure version */
- os->header[4]=0x00;
-
- /* continued packet flag? */
- os->header[5]=0x00;
- if((os->lacing_vals[0]&0x100)==0)os->header[5]|=0x01;
- /* first page flag? */
- if(os->b_o_s==0)os->header[5]|=0x02;
- /* last page flag? */
- if(os->e_o_s && os->lacing_fill==vals)os->header[5]|=0x04;
- os->b_o_s=1;
- /* 64 bits of PCM position */
- for(i=6;i<14;i++){
- os->header[i]=(pcm_pos&0xff);
- pcm_pos>>=8;
- }
- /* 32 bits of stream serial number */
- {
- long serialno=os->serialno;
- for(i=14;i<18;i++){
- os->header[i]=(serialno&0xff);
- serialno>>=8;
- }
- }
- /* 32 bits of page counter (we have both counter and page header
- because this val can roll over) */
- if(os->pageno==-1)os->pageno=0; /* because someone called
- stream_reset; this would be a
- strange thing to do in an
- encode stream, but it has
- plausible uses */
- {
- long pageno=os->pageno++;
- for(i=18;i<22;i++){
- os->header[i]=(pageno&0xff);
- pageno>>=8;
- }
- }
- /* zero for computation; filled in later */
- os->header[22]=0;
- os->header[23]=0;
- os->header[24]=0;
- os->header[25]=0;
- /* segment table */
- os->header[26]=vals&0xff;
- for(i=0;i<vals;i++)
- bytes+=os->header[i+27]=(os->lacing_vals[i]&0xff);
-
- /* advance the lacing data and set the body_returned pointer */
- os->lacing_fill-=vals;
- memmove(os->lacing_vals,os->lacing_vals+vals,os->lacing_fill*sizeof(int));
- memmove(os->pcm_vals,os->pcm_vals+vals,os->lacing_fill*sizeof(int64_t));
- os->body_returned=bytes;
- /* set pointers in the ogg_page struct */
- og->header=os->header;
- og->header_len=os->header_fill=vals+27;
- og->body=os->body_data;
- og->body_len=bytes;
- /* calculate the checksum */
- _os_checksum(og);
- return(1);
- }
- /* not enough data to construct a page and not end of stream */
- return(0);
- }
- int ogg_stream_eof(ogg_stream_state *os){
- return os->e_o_s;
- }
- /* DECODING PRIMITIVES: packet streaming layer **********************/
- /* This has two layers to place more of the multi-serialno and paging
- control in the application's hands. First, we expose a data buffer
- using ogg_decode_buffer(). The app either copies into the
- buffer, or passes it directly to read(), etc. We then call
- ogg_decode_wrote() to tell how many bytes we just added.
- Pages are returned (pointers into the buffer in ogg_sync_state)
- by ogg_decode_stream(). The page is then submitted to
- ogg_decode_page() along with the appropriate
- ogg_stream_state* (ie, matching serialno). We then get raw
- packets out calling ogg_stream_packet() with a
- ogg_stream_state. See the 'frame-prog.txt' docs for details and
- example code. */
- /* initialize the struct to a known state */
- int ogg_sync_init(ogg_sync_state *oy){
- if(oy){
- memset(oy,0,sizeof(ogg_sync_state));
- _ogg_crc_init();
- }
- return(0);
- }
- /* clear non-flat storage within */
- int ogg_sync_clear(ogg_sync_state *oy){
- if(oy){
- if(oy->data)free(oy->data);
- ogg_sync_init(oy);
- }
- return(0);
- }
- char *ogg_sync_buffer(ogg_sync_state *oy, long size){
- /* first, clear out any space that has been previously returned */
- if(oy->returned){
- oy->fill-=oy->returned;
- if(oy->fill>0)
- memmove(oy->data,oy->data+oy->returned,
- (oy->fill)*sizeof(char));
- oy->returned=0;
- }
- if(size>oy->storage-oy->fill){
- /* We need to extend the internal buffer */
- long newsize=size+oy->fill+4096; /* an extra page to be nice */
- if(oy->data)
- oy->data=realloc(oy->data,newsize);
- else
- oy->data=malloc(newsize);
- oy->storage=newsize;
- }
- /* expose a segment at least as large as requested at the fill mark */
- return((char *)oy->data+oy->fill);
- }
- int ogg_sync_wrote(ogg_sync_state *oy, long bytes){
- if(oy->fill+bytes>oy->storage)return(-1);
- oy->fill+=bytes;
- return(0);
- }
- /* 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 */
- 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(oy,og);
- if(ret>0){
- /* have a page */
- return(1);
- }
- if(ret==0){
- /* need more data */
- return(0);
- }
-
- /* head did not start a synced page... skipped some bytes */
- if(!oy->unsynced){
- oy->unsynced=1;
- return(-1);
- }
- /* loop. keep looking */
- }
- }
- /* add the incoming page to the stream state; we decompose the page
- into packet segments here as well. */
- int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){
- unsigned char *header=og->header;
- unsigned char *body=og->body;
- long bodysize=og->body_len;
- int segptr=0;
- int version=ogg_page_version(og);
- int continued=ogg_page_continued(og);
- int bos=ogg_page_bos(og);
- int eos=ogg_page_eos(og);
- int64_t pcmpos=ogg_page_frameno(og);
- int serialno=ogg_page_serialno(og);
- int pageno=ogg_page_pageno(og);
- int segments=header[26];
-
- /* clean up 'returned data' */
- {
- long lr=os->lacing_returned;
- long br=os->body_returned;
- /* body data */
- if(br){
- os->body_fill-=br;
- if(os->body_fill)
- memmove(os->body_data,os->body_data+br,os->body_fill);
- os->body_returned=0;
- }
- if(lr){
- /* segment table */
- if(os->lacing_fill-lr){
- memmove(os->lacing_vals,os->lacing_vals+lr,
- (os->lacing_fill-lr)*sizeof(int));
- memmove(os->pcm_vals,os->pcm_vals+lr,
- (os->lacing_fill-lr)*sizeof(int64_t));
- }
- os->lacing_fill-=lr;
- os->lacing_packet-=lr;
- os->lacing_returned=0;
- }
- }
- /* check the serial number */
- if(serialno!=os->serialno)return(-1);
- if(version>0)return(-1);
- _os_lacing_expand(os,segments+1);
- /* are we in sequence? */
- if(pageno!=os->pageno){
- int i;
- /* unroll previous partial packet (if any) */
- for(i=os->lacing_packet;i<os->lacing_fill;i++)
- os->body_fill-=os->lacing_vals[i]&0xff;
- os->lacing_fill=os->lacing_packet;
- /* make a note of dropped data in segment table */
- if(os->pageno!=-1){
- os->lacing_vals[os->lacing_fill++]=0x400;
- os->lacing_packet++;
- }
- /* are we a 'continued packet' page? If so, we'll need to skip
- some segments */
- if(continued){
- bos=0;
- for(;segptr<segments;segptr++){
- int val=header[27+segptr];
- body+=val;
- bodysize-=val;
- if(val<255){
- segptr++;
- break;
- }
- }
- }
- }
-
- if(bodysize){
- _os_body_expand(os,bodysize);
- memcpy(os->body_data+os->body_fill,body,bodysize);
- os->body_fill+=bodysize;
- }
- {
- int saved=-1;
- while(segptr<segments){
- int val=header[27+segptr];
- os->lacing_vals[os->lacing_fill]=val;
- os->pcm_vals[os->lacing_fill]=-1;
-
- if(bos){
- os->lacing_vals[os->lacing_fill]|=0x100;
- bos=0;
- }
-
- if(val<255)saved=os->lacing_fill;
-
- os->lacing_fill++;
- segptr++;
-
- if(val<255)os->lacing_packet=os->lacing_fill;
- }
-
- /* set the pcmpos on the last pcmval of the last full packet */
- if(saved!=-1){
- os->pcm_vals[saved]=pcmpos;
- }
- }
- if(eos){
- os->e_o_s=1;
- if(os->lacing_fill>0)
- os->lacing_vals[os->lacing_fill-1]|=0x200;
- }
- os->pageno=pageno+1;
- return(0);
- }
- /* clear things to an initial state. Good to call, eg, before seeking */
- int ogg_sync_reset(ogg_sync_state *oy){
- oy->fill=0;
- oy->returned=0;
- oy->unsynced=0;
- oy->headerbytes=0;
- oy->bodybytes=0;
- return(0);
- }
- int ogg_stream_reset(ogg_stream_state *os){
- os->body_fill=0;
- os->body_returned=0;
- os->lacing_fill=0;
- os->lacing_packet=0;
- os->lacing_returned=0;
- os->header_fill=0;
- os->e_o_s=0;
- os->b_o_s=0;
- os->pageno=-1;
- os->packetno=0;
- os->pcmpos=0;
- return(0);
- }
- int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op){
- /* The last part of decode. We have the stream broken into packet
- segments. Now we need to group them into packets (or return the
- out of sync markers) */
- int ptr=os->lacing_returned;
- if(os->lacing_packet<=ptr)return(0);
- if(os->lacing_vals[ptr]&0x400){
- /* We lost sync here; let the app know */
- os->lacing_returned++;
- /* we need to tell the codec there's a gap; it might need to
- handle previous packet dependencies. */
- os->packetno++;
- return(-1);
- }
- /* Gather the whole packet. We'll have no holes or a partial packet */
- {
- int size=os->lacing_vals[ptr]&0xff;
- int bytes=0;
- op->packet=os->body_data+os->body_returned;
- op->e_o_s=os->lacing_vals[ptr]&0x200; /* last packet of the stream? */
- op->b_o_s=os->lacing_vals[ptr]&0x100; /* first packet of the stream? */
- bytes+=size;
- while(size==255){
- int val=os->lacing_vals[++ptr];
- size=val&0xff;
- if(val&0x200)op->e_o_s=0x200;
- bytes+=size;
- }
- op->packetno=os->packetno;
- op->frameno=os->pcm_vals[ptr];
- op->bytes=bytes;
- os->body_returned+=bytes;
- os->lacing_returned=ptr+1;
- }
- os->packetno++;
- return(1);
- }
- #ifdef _V_SELFTEST
- #include <stdio.h>
- ogg_stream_state os_en, os_de;
- ogg_sync_state oy;
- void checkpacket(ogg_packet *op,int len, int no, int pos){
- long j;
- static int sequence=0;
- static int lastno=0;
- if(op->bytes!=len){
- fprintf(stderr,"incorrect packet length!\n");
- exit(1);
- }
- if(op->frameno!=pos){
- fprintf(stderr,"incorrect packet position!\n");
- exit(1);
- }
- /* packet number just follows sequence/gap; adjust the input number
- for that */
- if(no==0){
- sequence=0;
- }else{
- sequence++;
- if(no>lastno+1)
- sequence++;
- }
- lastno=no;
- if(op->packetno!=sequence){
- fprintf(stderr,"incorrect packet sequence %ld != %d\n",op->packetno,sequence);
- exit(1);
- }
- /* Test data */
- for(j=0;j<op->bytes;j++)
- if(op->packet[j]!=((j+no)&0xff)){
- fprintf(stderr,"body data mismatch at pos %ld: %x!=%lx!\n\n",
- j,op->packet[j],(j+no)&0xff);
- exit(1);
- }
- }
- void check_page(unsigned char *data,int *header,ogg_page *og){
- long j;
- /* Test data */
- for(j=0;j<og->body_len;j++)
- if(og->body[j]!=data[j]){
- fprintf(stderr,"body data mismatch at pos %ld: %x!=%x!\n\n",
- j,data[j],og->body[j]);
- exit(1);
- }
- /* Test header */
- for(j=0;j<og->header_len;j++){
- if(og->header[j]!=header[j]){
- fprintf(stderr,"header content mismatch at pos %ld:\n",j);
- for(j=0;j<header[26]+27;j++)
- fprintf(stderr," (%ld)%02x:%02x",j,header[j],og->header[j]);
- fprintf(stderr,"\n");
- exit(1);
- }
- }
- if(og->header_len!=header[26]+27){
- fprintf(stderr,"header length incorrect! (%ld!=%d)\n",
- og->header_len,header[26]+27);
- exit(1);
- }
- }
- void print_header(ogg_page *og){
- int j;
- fprintf(stderr,"\nHEADER:\n");
- fprintf(stderr," capture: %c %c %c %c version: %d flags: %x\n",
- og->header[0],og->header[1],og->header[2],og->header[3],
- (int)og->header[4],(int)og->header[5]);
- fprintf(stderr," pcmpos: %d serialno: %d pageno: %d\n",
- (og->header[9]<<24)|(og->header[8]<<16)|
- (og->header[7]<<8)|og->header[6],
- (og->header[17]<<24)|(og->header[16]<<16)|
- (og->header[15]<<8)|og->header[14],
- (og->header[21]<<24)|(og->header[20]<<16)|
- (og->header[19]<<8)|og->header[18]);
- fprintf(stderr," checksum: %02x:%02x:%02x:%02x\n segments: %d (",
- (int)og->header[22],(int)og->header[23],
- (int)og->header[24],(int)og->header[25],
- (int)og->header[26]);
- for(j=27;j<og->header_len;j++)
- fprintf(stderr,"%d ",(int)og->header[j]);
- fprintf(stderr,")\n\n");
- }
- void copy_page(ogg_page *og){
- char *temp=malloc(og->header_len);
- memcpy(temp,og->header,og->header_len);
- og->header=temp;
- temp=malloc(og->body_len);
- memcpy(temp,og->body,og->body_len);
- og->body=temp;
- }
- void error(void){
- fprintf(stderr,"error!\n");
- exit(1);
- }
- void test_pack(int *pl, int **headers){
- unsigned char *data=malloc(1024*1024); /* for scripted test cases only */
- long inptr=0;
- long outptr=0;
- long deptr=0;
- long depacket=0;
- long pcm_pos=7;
- int i,j,packets,pageno=0,pageout=0;
- int eosflag=0;
- int bosflag=0;
- ogg_stream_reset(&os_en);
- ogg_stream_reset(&os_de);
- ogg_sync_reset(&oy);
- for(packets=0;;packets++)if(pl[packets]==-1)break;
- for(i=0;i<packets;i++){
- /* construct a test packet */
- ogg_packet op;
- int len=pl[i];
-
- op.packet=data+inptr;
- op.bytes=len;
- op.e_o_s=(pl[i+1]<0?1:0);
- op.frameno=pcm_pos;
- pcm_pos+=1024;
- for(j=0;j<len;j++)data[inptr++]=i+j;
- /* submit the test packet */
- ogg_stream_packetin(&os_en,&op);
- /* retrieve any finished pages */
- {
- ogg_page og;
-
- while(ogg_stream_pageout(&os_en,&og)){
- /* We have a page. Check it carefully */
- fprintf(stderr,"%d, ",pageno);
- if(headers[pageno]==NULL){
- fprintf(stderr,"coded too many pages!\n");
- exit(1);
- }
- check_page(data+outptr,headers[pageno],&og);
- outptr+=og.body_len;
- pageno++;
- /* have a complete page; submit it to sync/decode */
- {
- ogg_page og_de;
- ogg_packet op_de;
- char *buf=ogg_sync_buffer(&oy,og.header_len+og.body_len);
- memcpy(buf,og.header,og.header_len);
- memcpy(buf+og.header_len,og.body,og.body_len);
- ogg_sync_wrote(&oy,og.header_len+og.body_len);
- while(ogg_sync_pageout(&oy,&og_de)>0){
- /* got a page. Happy happy. Verify that it's good. */
-
- check_page(data+deptr,headers[pageout],&og_de);
- deptr+=og_de.body_len;
- pageout++;
- /* submit it to deconstitution */
- ogg_stream_pagein(&os_de,&og_de);
- /* packets out? */
- while(ogg_stream_packetout(&os_de,&op_de)>0){
-
- /* verify the packet! */
- /* check data */
- if(memcmp(data+depacket,op_de.packet,op_de.bytes)){
- fprintf(stderr,"packet data mismatch in decode! pos=%ld\n",
- depacket);
- exit(1);
- }
- /* check bos flag */
- if(bosflag==0 && op_de.b_o_s==0){
- fprintf(stderr,"b_o_s flag not set on packet!\n");
- exit(1);
- }
- if(bosflag && op_de.b_o_s){
- fprintf(stderr,"b_o_s flag incorrectly set on packet!\n");
- exit(1);
- }
- bosflag=1;
- depacket+=op_de.bytes;
-
- /* check eos flag */
- if(eosflag){
- fprintf(stderr,"Multiple decoded packets with eos flag!\n");
- exit(1);
- }
- if(op_de.e_o_s)eosflag=1;
- /* check pcmpos flag */
- if(op_de.frameno!=-1){
- fprintf(stderr," pcm:%ld ",(long)op_de.frameno);
- }
- }
- }
- }
- }
- }
- }
- free(data);
- if(headers[pageno]!=NULL){
- fprintf(stderr,"did not write last page!\n");
- exit(1);
- }
- if(headers[pageout]!=NULL){
- fprintf(stderr,"did not decode last page!\n");
- exit(1);
- }
- if(inptr!=outptr){
- fprintf(stderr,"encoded page data incomplete!\n");
- exit(1);
- }
- if(inptr!=deptr){
- fprintf(stderr,"decoded page data incomplete!\n");
- exit(1);
- }
- if(inptr!=depacket){
- fprintf(stderr,"decoded packet data incomplete!\n");
- exit(1);
- }
- if(!eosflag){
- fprintf(stderr,"Never got a packet with EOS set!\n");
- exit(1);
- }
- fprintf(stderr,"ok.\n");
- }
- int main(void){
- ogg_stream_init(&os_en,0x04030201);
- ogg_stream_init(&os_de,0x04030201);
- ogg_sync_init(&oy);
- /* Exercise each code path in the framing code. Also verify that
- the checksums are working. */
- {
- /* 17 only */
- int packets[]={17, -1};
- int head1[] = {0x4f,0x67,0x67,0x53,0,0x06,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x01,0x02,0x03,0x04,0,0,0,0,
- 0x15,0xed,0xec,0x91,
- 1,
- 17};
- int *headret[]={head1,NULL};
-
- fprintf(stderr,"testing single page encoding... ");
- test_pack(packets,headret);
- }
- {
- /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
- int packets[]={17, 254, 255, 256, 500, 510, 600, -1};
- int head1[] = {0x4f,0x67,0x67,0x53,0,0x02,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x01,0x02,0x03,0x04,0,0,0,0,
- 0x59,0x10,0x6c,0x2c,
- 1,
- 17};
- int head2[] = {0x4f,0x67,0x67,0x53,0,0x04,
- 0x07,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x01,0x02,0x03,0x04,1,0,0,0,
- 0x89,0x33,0x85,0xce,
- 13,
- 254,255,0,255,1,255,245,255,255,0,
- 255,255,90};
- int *headret[]={head1,head2,NULL};
-
- fprintf(stderr,"testing basic page encoding... ");
- test_pack(packets,headret);
- }
- {
- /* nil packets; beginning,middle,end */
- int packets[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1};
- int head1[] = {0x4f,0x67,0x67,0x53,0,0x02,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x01,0x02,0x03,0x04,0,0,0,0,
- 0xff,0x7b,0x23,0x17,
- 1,
- 0};
- int head2[] = {0x4f,0x67,0x67,0x53,0,0x04,
- 0x07,0x28,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x01,0x02,0x03,0x04,1,0,0,0,
- 0x5c,0x3f,0x66,0xcb,
- 17,
- 17,254,255,0,0,255,1,0,255,245,255,255,0,
- 255,255,90,0};
- int *headret[]={head1,head2,NULL};
-
- fprintf(stderr,"testing basic nil packets... ");
- test_pack(packets,headret);
- }
- {
- /* large initial packet */
- int packets[]={4345,259,255,-1};
- int head1[] = {0x4f,0x67,0x67,0x53,0,0x02,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x01,0x02,0x03,0x04,0,0,0,0,
- 0x01,0x27,0x31,0xaa,
- 18,
- 255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,10};
- int head2[] = {0x4f,0x67,0x67,0x53,0,0x04,
- 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x01,0x02,0x03,0x04,1,0,0,0,
- 0x7f,0x4e,0x8a,0xd2,
- 4,
- 255,4,255,0};
- int *headret[]={head1,head2,NULL};
-
- fprintf(stderr,"testing initial-packet lacing > 4k... ");
- test_pack(packets,headret);
- }
- {
- /* continuing packet test */
- int packets[]={0,4345,259,255,-1};
- int head1[] = {0x4f,0x67,0x67,0x53,0,0x02,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x01,0x02,0x03,0x04,0,0,0,0,
- 0xff,0x7b,0x23,0x17,
- 1,
- 0};
- int head2[] = {0x4f,0x67,0x67,0x53,0,0x00,
- 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x01,0x02,0x03,0x04,1,0,0,0,
- 0x34,0x24,0xd5,0x29,
- 17,
- 255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255};
- int head3[] = {0x4f,0x67,0x67,0x53,0,0x05,
- 0x07,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x01,0x02,0x03,0x04,2,0,0,0,
- 0xc8,0xc3,0xcb,0xed,
- 5,
- 10,255,4,255,0};
- int *headret[]={head1,head2,head3,NULL};
-
- fprintf(stderr,"testing single packet page span... ");
- test_pack(packets,headret);
- }
- /* page with the 255 segment limit */
- {
- int packets[]={0,10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,50,-1};
- int head1[] = {0x4f,0x67,0x67,0x53,0,0x02,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x01,0x02,0x03,0x04,0,0,0,0,
- 0xff,0x7b,0x23,0x17,
- 1,
- 0};
- int head2[] = {0x4f,0x67,0x67,0x53,0,0x00,
- 0x07,0xfc,0x03,0x00,0x00,0x00,0x00,0x00,
- 0x01,0x02,0x03,0x04,1,0,0,0,
- 0xed,0x2a,0x2e,0xa7,
- 255,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10};
- int head3[] = {0x4f,0x67,0x67,0x53,0,0x04,
- 0x07,0x00,0x04,0x00,0x00,0x00,0x00,0x00,
- 0x01,0x02,0x03,0x04,2,0,0,0,
- 0x6c,0x3b,0x82,0x3d,
- 1,
- 50};
- int *headret[]={head1,head2,head3,NULL};
-
- fprintf(stderr,"testing max packet segments... ");
- test_pack(packets,headret);
- }
- {
- /* packet that overspans over an entire page */
- int packets[]={0,100,9000,259,255,-1};
- int head1[] = {0x4f,0x67,0x67,0x53,0,0x02,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x01,0x02,0x03,0x04,0,0,0,0,
- 0xff,0x7b,0x23,0x17,
- 1,
- 0};
- int head2[] = {0x4f,0x67,0x67,0x53,0,0x00,
- 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x01,0x02,0x03,0x04,1,0,0,0,
- 0x3c,0xd9,0x4d,0x3f,
- 17,
- 100,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255};
- int head3[] = {0x4f,0x67,0x67,0x53,0,0x01,
- 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x01,0x02,0x03,0x04,2,0,0,0,
- 0xbd,0xd5,0xb5,0x8b,
- 17,
- 255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255};
- int head4[] = {0x4f,0x67,0x67,0x53,0,0x05,
- 0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x01,0x02,0x03,0x04,3,0,0,0,
- 0xef,0xdd,0x88,0xde,
- 7,
- 255,255,75,255,4,255,0};
- int *headret[]={head1,head2,head3,head4,NULL};
-
- fprintf(stderr,"testing very large packets... ");
- test_pack(packets,headret);
- }
- {
- /* term only page. why not? */
- int packets[]={0,100,4080,-1};
- int head1[] = {0x4f,0x67,0x67,0x53,0,0x02,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x01,0x02,0x03,0x04,0,0,0,0,
- 0xff,0x7b,0x23,0x17,
- 1,
- 0};
- int head2[] = {0x4f,0x67,0x67,0x53,0,0x00,
- 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x01,0x02,0x03,0x04,1,0,0,0,
- 0x3c,0xd9,0x4d,0x3f,
- 17,
- 100,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255};
- int head3[] = {0x4f,0x67,0x67,0x53,0,0x05,
- 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x01,0x02,0x03,0x04,2,0,0,0,
- 0xd4,0xe0,0x60,0xe5,
- 1,0};
- int *headret[]={head1,head2,head3,NULL};
-
- fprintf(stderr,"testing zero data page (1 nil packet)... ");
- test_pack(packets,headret);
- }
- {
- /* build a bunch of pages for testing */
- unsigned char *data=malloc(1024*1024);
- int pl[]={0,100,4079,2956,2057,76,34,912,0,234,1000,1000,1000,300,-1};
- int inptr=0,i,j;
- ogg_page og[5];
-
- ogg_stream_reset(&os_en);
- for(i=0;pl[i]!=-1;i++){
- ogg_packet op;
- int len=pl[i];
-
- op.packet=data+inptr;
- op.bytes=len;
- op.e_o_s=(pl[i+1]<0?1:0);
- op.frameno=(i+1)*1000;
- for(j=0;j<len;j++)data[inptr++]=i+j;
- ogg_stream_packetin(&os_en,&op);
- }
- free(data);
- /* retrieve finished pages */
- for(i=0;i<5;i++){
- if(ogg_stream_pageout(&os_en,&og[i])==0){
- fprintf(stderr,"Too few pages output building sync tests!\n");
- exit(1);
- }
- copy_page(&og[i]);
- }
- /* Test lost pages on pagein/packetout: no rollback */
- {
- ogg_page temp;
- ogg_packet test;
- fprintf(stderr,"Testing loss of pages... ");
- ogg_sync_reset(&oy);
- ogg_stream_reset(&os_de);
- for(i=0;i<5;i++){
- memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
- og[i].header_len);
- ogg_sync_wrote(&oy,og[i].header_len);
- memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
- ogg_sync_wrote(&oy,og[i].body_len);
- }
- ogg_sync_pageout(&oy,&temp);
- ogg_stream_pagein(&os_de,&temp);
- ogg_sync_pageout(&oy,&temp);
- ogg_stream_pagein(&os_de,&temp);
- ogg_sync_pageout(&oy,&temp);
- /* skip */
- ogg_sync_pageout(&oy,&temp);
- ogg_stream_pagein(&os_de,&temp);
- /* do we get the expected results/packets? */
-
- if(ogg_stream_packetout(&os_de,&test)!=1)error();
- checkpacket(&test,0,0,0);
- if(ogg_stream_packetout(&os_de,&test)!=1)error();
- checkpacket(&test,100,1,-1);
- if(ogg_stream_packetout(&os_de,&test)!=1)error();
- checkpacket(&test,4079,2,3000);
- if(ogg_stream_packetout(&os_de,&test)!=-1){
- fprintf(stderr,"Error: loss of page did not return error\n");
- exit(1);
- }
- if(ogg_stream_packetout(&os_de,&test)!=1)error();
- checkpacket(&test,76,5,-1);
- if(ogg_stream_packetout(&os_de,&test)!=1)error();
- checkpacket(&test,34,6,-1);
- fprintf(stderr,"ok.\n");
- }
- /* Test lost pages on pagein/packetout: rollback with continuation */
- {
- ogg_page temp;
- ogg_packet test;
- fprintf(stderr,"Testing loss of pages (rollback required)... ");
- ogg_sync_reset(&oy);
- ogg_stream_reset(&os_de);
- for(i=0;i<5;i++){
- memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
- og[i].header_len);
- ogg_sync_wrote(&oy,og[i].header_len);
- memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
- ogg_sync_wrote(&oy,og[i].body_len);
- }
- ogg_sync_pageout(&oy,&temp);
- ogg_stream_pagein(&os_de,&temp);
- ogg_sync_pageout(&oy,&temp);
- ogg_stream_pagein(&os_de,&temp);
- ogg_sync_pageout(&oy,&temp);
- ogg_stream_pagein(&os_de,&temp);
- ogg_sync_pageout(&oy,&temp);
- /* skip */
- ogg_sync_pageout(&oy,&temp);
- ogg_stream_pagein(&os_de,&temp);
- /* do we get the expected results/packets? */
-
- if(ogg_stream_packetout(&os_de,&test)!=1)error();
- checkpacket(&test,0,0,0);
- if(ogg_stream_packetout(&os_de,&test)!=1)error();
- checkpacket(&test,100,1,-1);
- if(ogg_stream_packetout(&os_de,&test)!=1)error();
- checkpacket(&test,4079,2,3000);
- if(ogg_stream_packetout(&os_de,&test)!=1)error();
- checkpacket(&test,2956,3,4000);
- if(ogg_stream_packetout(&os_de,&test)!=-1){
- fprintf(stderr,"Error: loss of page did not return error\n");
- exit(1);
- }
- if(ogg_stream_packetout(&os_de,&test)!=1)error();
- checkpacket(&test,300,13,14000);
- fprintf(stderr,"ok.\n");
- }
-
- /* the rest only test sync */
- {
- ogg_page og_de;
- /* Test fractional page inputs: incomplete capture */
- fprintf(stderr,"Testing sync on partial inputs... ");
- ogg_sync_reset(&oy);
- memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
- 3);
- ogg_sync_wrote(&oy,3);
- if(ogg_sync_pageout(&oy,&og_de)>0)error();
-
- /* Test fractional page inputs: incomplete fixed header */
- memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+3,
- 20);
- ogg_sync_wrote(&oy,20);
- if(ogg_sync_pageout(&oy,&og_de)>0)error();
-
- /* Test fractional page inputs: incomplete header */
- memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+23,
- 5);
- ogg_sync_wrote(&oy,5);
- if(ogg_sync_pageout(&oy,&og_de)>0)error();
-
- /* Test fractional page inputs: incomplete body */
-
- memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+28,
- og[1].header_len-28);
- ogg_sync_wrote(&oy,og[1].header_len-28);
- if(ogg_sync_pageout(&oy,&og_de)>0)error();
-
- memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,1000);
- ogg_sync_wrote(&oy,1000);
- if(ogg_sync_pageout(&oy,&og_de)>0)error();
-
- memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body+1000,
- og[1].body_len-1000);
- ogg_sync_wrote(&oy,og[1].body_len-1000);
- if(ogg_sync_pageout(&oy,&og_de)<=0)error();
-
- fprintf(stderr,"ok.\n");
- }
- /* Test fractional page inputs: page + incomplete capture */
- {
- ogg_page og_de;
- fprintf(stderr,"Testing sync on 1+partial inputs... ");
- ogg_sync_reset(&oy);
- memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
- og[1].header_len);
- ogg_sync_wrote(&oy,og[1].header_len);
- memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
- og[1].body_len);
- ogg_sync_wrote(&oy,og[1].body_len);
- memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
- 20);
- ogg_sync_wrote(&oy,20);
- if(ogg_sync_pageout(&oy,&og_de)<=0)error();
- if(ogg_sync_pageout(&oy,&og_de)>0)error();
- memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+20,
- og[1].header_len-20);
- ogg_sync_wrote(&oy,og[1].header_len-20);
- memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
- og[1].body_len);
- ogg_sync_wrote(&oy,og[1].body_len);
- if(ogg_sync_pageout(&oy,&og_de)<=0)error();
- fprintf(stderr,"ok.\n");
- }
-
- /* Test recapture: garbage + page */
- {
- ogg_page og_de;
- fprintf(stderr,"Testing search for capture... ");
- ogg_sync_reset(&oy);
-
- /* 'garbage' */
- memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
- og[1].body_len);
- ogg_sync_wrote(&oy,og[1].body_len);
- memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
- og[1].header_len);
- ogg_sync_wrote(&oy,og[1].header_len);
- memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
- og[1].body_len);
- ogg_sync_wrote(&oy,og[1].body_len);
- memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
- 20);
- ogg_sync_wrote(&oy,20);
- if(ogg_sync_pageout(&oy,&og_de)>0)error();
- if(ogg_sync_pageout(&oy,&og_de)<=0)error();
- if(ogg_sync_pageout(&oy,&og_de)>0)error();
- memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header+20,
- og[2].header_len-20);
- ogg_sync_wrote(&oy,og[2].header_len-20);
- memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
- og[2].body_len);
- ogg_sync_wrote(&oy,og[2].body_len);
- if(ogg_sync_pageout(&oy,&og_de)<=0)error();
- fprintf(stderr,"ok.\n");
- }
- /* Test recapture: page + garbage + page */
- {
- ogg_page og_de;
- fprintf(stderr,"Testing recapture... ");
- ogg_sync_reset(&oy);
- memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
- og[1].header_len);
- ogg_sync_wrote(&oy,og[1].header_len);
- memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
- og[1].body_len);
- ogg_sync_wrote(&oy,og[1].body_len);
- memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
- og[2].header_len);
- ogg_sync_wrote(&oy,og[2].header_len);
- memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
- og[2].header_len);
- ogg_sync_wrote(&oy,og[2].header_len);
- if(ogg_sync_pageout(&oy,&og_de)<=0)error();
- memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
- og[2].body_len-5);
- ogg_sync_wrote(&oy,og[2].body_len-5);
- memcpy(ogg_sync_buffer(&oy,og[3].header_len),og[3].header,
- og[3].header_len);
- ogg_sync_wrote(&oy,og[3].header_len);
- memcpy(ogg_sync_buffer(&oy,og[3].body_len),og[3].body,
- og[3].body_len);
- ogg_sync_wrote(&oy,og[3].body_len);
- if(ogg_sync_pageout(&oy,&og_de)>0)error();
- if(ogg_sync_pageout(&oy,&og_de)<=0)error();
- fprintf(stderr,"ok.\n");
- }
- }
- return(0);
- }
- #endif
|