1 /********************************************************************
3 * THIS FILE IS PART OF THE Ogg CONTAINER SOURCE CODE. *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
8 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2018 *
9 * by the Xiph.Org Foundation http://www.xiph.org/ *
11 ********************************************************************
13 function: code raw packets into framed OggSquish stream and
14 decode Ogg streams back into raw packets
16 note: The CRC code is directly derived from public domain code by
17 Ross Williams (ross@guest.adelaide.edu.au). See docs/framing.html
20 ********************************************************************/
31 /* A complete description of Ogg framing exists in docs/framing.html */
33 int ogg_page_version(const ogg_page *og){
34 return((int)(og->header[4]));
37 int ogg_page_continued(const ogg_page *og){
38 return((int)(og->header[5]&0x01));
41 int ogg_page_bos(const ogg_page *og){
42 return((int)(og->header[5]&0x02));
45 int ogg_page_eos(const ogg_page *og){
46 return((int)(og->header[5]&0x04));
49 ogg_int64_t ogg_page_granulepos(const ogg_page *og){
50 unsigned char *page=og->header;
51 ogg_uint64_t granulepos=page[13]&(0xff);
52 granulepos= (granulepos<<8)|(page[12]&0xff);
53 granulepos= (granulepos<<8)|(page[11]&0xff);
54 granulepos= (granulepos<<8)|(page[10]&0xff);
55 granulepos= (granulepos<<8)|(page[9]&0xff);
56 granulepos= (granulepos<<8)|(page[8]&0xff);
57 granulepos= (granulepos<<8)|(page[7]&0xff);
58 granulepos= (granulepos<<8)|(page[6]&0xff);
59 return((ogg_int64_t)granulepos);
62 int ogg_page_serialno(const ogg_page *og){
63 return((int)((ogg_uint32_t)og->header[14]) |
64 ((ogg_uint32_t)og->header[15]<<8) |
65 ((ogg_uint32_t)og->header[16]<<16) |
66 ((ogg_uint32_t)og->header[17]<<24));
69 long ogg_page_pageno(const ogg_page *og){
70 return((long)((ogg_uint32_t)og->header[18]) |
71 ((ogg_uint32_t)og->header[19]<<8) |
72 ((ogg_uint32_t)og->header[20]<<16) |
73 ((ogg_uint32_t)og->header[21]<<24));
78 /* returns the number of packets that are completed on this page (if
79 the leading packet is begun on a previous page, but ends on this
83 If a page consists of a packet begun on a previous page, and a new
84 packet begun (but not completed) on this page, the return will be:
85 ogg_page_packets(page) ==1,
86 ogg_page_continued(page) !=0
88 If a page happens to be a single packet that was begun on a
89 previous page, and spans to the next page (in the case of a three or
90 more page packet), the return will be:
91 ogg_page_packets(page) ==0,
92 ogg_page_continued(page) !=0
95 int ogg_page_packets(const ogg_page *og){
96 int i,n=og->header[26],count=0;
98 if(og->header[27+i]<255)count++;
104 /* helper to initialize lookup for direct-table CRC (illustrative; we
105 use the static init in crctable.h) */
107 static void _ogg_crc_init(){
109 ogg_uint32_t polynomial, crc;
110 polynomial = 0x04c11db7; /* The same as the ethernet generator
111 polynomial, although we use an
112 unreflected alg and an init/final
113 of 0, not 0xffffffff */
114 for (i = 0; i <= 0xFF; i++){
117 for (j = 0; j < 8; j++)
118 crc = (crc << 1) ^ (crc & (1 << 31) ? polynomial : 0);
120 crc_lookup[0][i] = crc;
123 for (i = 0; i <= 0xFF; i++)
124 for (j = 1; j < 8; j++)
125 crc_lookup[j][i] = crc_lookup[0][(crc_lookup[j - 1][i] >> 24) & 0xFF] ^ (crc_lookup[j - 1][i] << 8);
129 #include "crctable.h"
131 /* init the encode/decode logical stream state */
133 int ogg_stream_init(ogg_stream_state *os,int serialno){
135 memset(os,0,sizeof(*os));
136 os->body_storage=16*1024;
137 os->lacing_storage=1024;
139 os->body_data=_ogg_malloc(os->body_storage*sizeof(*os->body_data));
140 os->lacing_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->lacing_vals));
141 os->granule_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->granule_vals));
143 if(!os->body_data || !os->lacing_vals || !os->granule_vals){
144 ogg_stream_clear(os);
148 os->serialno=serialno;
155 /* async/delayed error detection for the ogg_stream_state */
156 int ogg_stream_check(ogg_stream_state *os){
157 if(!os || !os->body_data) return -1;
161 /* _clear does not free os, only the non-flat storage within */
162 int ogg_stream_clear(ogg_stream_state *os){
164 if(os->body_data)_ogg_free(os->body_data);
165 if(os->lacing_vals)_ogg_free(os->lacing_vals);
166 if(os->granule_vals)_ogg_free(os->granule_vals);
168 memset(os,0,sizeof(*os));
173 int ogg_stream_destroy(ogg_stream_state *os){
175 ogg_stream_clear(os);
181 /* Helpers for ogg_stream_encode; this keeps the structure and
182 what's happening fairly clear */
184 static int _os_body_expand(ogg_stream_state *os,long needed){
185 if(os->body_storage-needed<=os->body_fill){
188 if(os->body_storage>LONG_MAX-needed){
189 ogg_stream_clear(os);
192 body_storage=os->body_storage+needed;
193 if(body_storage<LONG_MAX-1024)body_storage+=1024;
194 ret=_ogg_realloc(os->body_data,body_storage*sizeof(*os->body_data));
196 ogg_stream_clear(os);
199 os->body_storage=body_storage;
205 static int _os_lacing_expand(ogg_stream_state *os,long needed){
206 if(os->lacing_storage-needed<=os->lacing_fill){
209 if(os->lacing_storage>LONG_MAX-needed){
210 ogg_stream_clear(os);
213 lacing_storage=os->lacing_storage+needed;
214 if(lacing_storage<LONG_MAX-32)lacing_storage+=32;
215 ret=_ogg_realloc(os->lacing_vals,lacing_storage*sizeof(*os->lacing_vals));
217 ogg_stream_clear(os);
221 ret=_ogg_realloc(os->granule_vals,lacing_storage*
222 sizeof(*os->granule_vals));
224 ogg_stream_clear(os);
227 os->granule_vals=ret;
228 os->lacing_storage=lacing_storage;
233 /* checksum the page */
234 /* Direct table CRC; note that this will be faster in the future if we
235 perform the checksum simultaneously with other copies */
237 static ogg_uint32_t _os_update_crc(ogg_uint32_t crc, unsigned char *buffer, int size){
239 crc^=((ogg_uint32_t)buffer[0]<<24)|((ogg_uint32_t)buffer[1]<<16)|((ogg_uint32_t)buffer[2]<<8)|((ogg_uint32_t)buffer[3]);
241 crc=crc_lookup[7][ crc>>24 ]^crc_lookup[6][(crc>>16)&0xFF]^
242 crc_lookup[5][(crc>> 8)&0xFF]^crc_lookup[4][ crc &0xFF]^
243 crc_lookup[3][buffer[4] ]^crc_lookup[2][buffer[5] ]^
244 crc_lookup[1][buffer[6] ]^crc_lookup[0][buffer[7] ];
251 crc=(crc<<8)^crc_lookup[0][((crc >> 24)&0xff)^*buffer++];
255 void ogg_page_checksum_set(ogg_page *og){
257 ogg_uint32_t crc_reg=0;
259 /* safety; needed for API behavior, but not framing code */
265 crc_reg=_os_update_crc(crc_reg,og->header,og->header_len);
266 crc_reg=_os_update_crc(crc_reg,og->body,og->body_len);
268 og->header[22]=(unsigned char)(crc_reg&0xff);
269 og->header[23]=(unsigned char)((crc_reg>>8)&0xff);
270 og->header[24]=(unsigned char)((crc_reg>>16)&0xff);
271 og->header[25]=(unsigned char)((crc_reg>>24)&0xff);
275 /* submit data to the internal buffer of the framing engine */
276 int ogg_stream_iovecin(ogg_stream_state *os, ogg_iovec_t *iov, int count,
277 long e_o_s, ogg_int64_t granulepos){
279 long bytes = 0, lacing_vals;
282 if(ogg_stream_check(os)) return -1;
285 for (i = 0; i < count; ++i){
286 if(iov[i].iov_len>LONG_MAX) return -1;
287 if(bytes>LONG_MAX-(long)iov[i].iov_len) return -1;
288 bytes += (long)iov[i].iov_len;
290 lacing_vals=bytes/255+1;
292 if(os->body_returned){
293 /* advance packet data according to the body_returned pointer. We
294 had to keep it around to return a pointer into the buffer last
297 os->body_fill-=os->body_returned;
299 memmove(os->body_data,os->body_data+os->body_returned,
304 /* make sure we have the buffer storage */
305 if(_os_body_expand(os,bytes) || _os_lacing_expand(os,lacing_vals))
308 /* Copy in the submitted packet. Yes, the copy is a waste; this is
309 the liability of overly clean abstraction for the time being. It
310 will actually be fairly easy to eliminate the extra copy in the
313 for (i = 0; i < count; ++i) {
314 memcpy(os->body_data+os->body_fill, iov[i].iov_base, iov[i].iov_len);
315 os->body_fill += (int)iov[i].iov_len;
318 /* Store lacing vals for this packet */
319 for(i=0;i<lacing_vals-1;i++){
320 os->lacing_vals[os->lacing_fill+i]=255;
321 os->granule_vals[os->lacing_fill+i]=os->granulepos;
323 os->lacing_vals[os->lacing_fill+i]=bytes%255;
324 os->granulepos=os->granule_vals[os->lacing_fill+i]=granulepos;
326 /* flag the first segment as the beginning of the packet */
327 os->lacing_vals[os->lacing_fill]|= 0x100;
329 os->lacing_fill+=lacing_vals;
331 /* for the sake of completeness */
334 if(e_o_s)os->e_o_s=1;
339 int ogg_stream_packetin(ogg_stream_state *os,ogg_packet *op){
341 iov.iov_base = op->packet;
342 iov.iov_len = op->bytes;
343 return ogg_stream_iovecin(os, &iov, 1, op->e_o_s, op->granulepos);
346 /* Conditionally flush a page; force==0 will only flush nominal-size
347 pages, force==1 forces us to flush a page regardless of page size
348 so long as there's any data available at all. */
349 static int ogg_stream_flush_i(ogg_stream_state *os,ogg_page *og, int force, int nfill){
352 int maxvals=(os->lacing_fill>255?255:os->lacing_fill);
355 ogg_int64_t granule_pos=-1;
357 if(ogg_stream_check(os)) return(0);
358 if(maxvals==0) return(0);
360 /* construct a page */
361 /* decide how many segments to include */
363 /* If this is the initial header case, the first page must only include
364 the initial header packet */
365 if(os->b_o_s==0){ /* 'initial header page' case */
367 for(vals=0;vals<maxvals;vals++){
368 if((os->lacing_vals[vals]&0x0ff)<255){
375 /* The extra packets_done, packet_just_done logic here attempts to do two things:
376 1) Don't unnecessarily span pages.
377 2) Unless necessary, don't flush pages if there are less than four packets on
378 them; this expands page size to reduce unnecessary overhead if incoming packets
380 These are not necessary behaviors, just 'always better than naive flushing'
381 without requiring an application to explicitly request a specific optimized
382 behavior. We'll want an explicit behavior setup pathway eventually as well. */
385 int packet_just_done=0;
386 for(vals=0;vals<maxvals;vals++){
387 if(acc>nfill && packet_just_done>=4){
391 acc+=os->lacing_vals[vals]&0x0ff;
392 if((os->lacing_vals[vals]&0xff)<255){
393 granule_pos=os->granule_vals[vals];
394 packet_just_done=++packets_done;
398 if(vals==255)force=1;
401 if(!force) return(0);
403 /* construct the header in temp storage */
404 memcpy(os->header,"OggS",4);
406 /* stream structure version */
409 /* continued packet flag? */
411 if((os->lacing_vals[0]&0x100)==0)os->header[5]|=0x01;
412 /* first page flag? */
413 if(os->b_o_s==0)os->header[5]|=0x02;
414 /* last page flag? */
415 if(os->e_o_s && os->lacing_fill==vals)os->header[5]|=0x04;
418 /* 64 bits of PCM position */
420 os->header[i]=(unsigned char)(granule_pos&0xff);
424 /* 32 bits of stream serial number */
426 long serialno=os->serialno;
428 os->header[i]=(unsigned char)(serialno&0xff);
433 /* 32 bits of page counter (we have both counter and page header
434 because this val can roll over) */
435 if(os->pageno==-1)os->pageno=0; /* because someone called
436 stream_reset; this would be a
437 strange thing to do in an
438 encode stream, but it has
441 long pageno=os->pageno++;
443 os->header[i]=(unsigned char)(pageno&0xff);
448 /* zero for computation; filled in later */
455 os->header[26]=(unsigned char)(vals&0xff);
457 bytes+=os->header[i+27]=(unsigned char)(os->lacing_vals[i]&0xff);
459 /* set pointers in the ogg_page struct */
460 og->header=os->header;
461 og->header_len=os->header_fill=vals+27;
462 og->body=os->body_data+os->body_returned;
465 /* advance the lacing data and set the body_returned pointer */
467 os->lacing_fill-=vals;
468 memmove(os->lacing_vals,os->lacing_vals+vals,os->lacing_fill*sizeof(*os->lacing_vals));
469 memmove(os->granule_vals,os->granule_vals+vals,os->lacing_fill*sizeof(*os->granule_vals));
470 os->body_returned+=bytes;
472 /* calculate the checksum */
474 ogg_page_checksum_set(og);
480 /* This will flush remaining packets into a page (returning nonzero),
481 even if there is not enough data to trigger a flush normally
482 (undersized page). If there are no packets or partial packets to
483 flush, ogg_stream_flush returns 0. Note that ogg_stream_flush will
484 try to flush a normal sized page like ogg_stream_pageout; a call to
485 ogg_stream_flush does not guarantee that all packets have flushed.
486 Only a return value of 0 from ogg_stream_flush indicates all packet
487 data is flushed into pages.
489 since ogg_stream_flush will flush the last page in a stream even if
490 it's undersized, you almost certainly want to use ogg_stream_pageout
491 (and *not* ogg_stream_flush) unless you specifically need to flush
492 a page regardless of size in the middle of a stream. */
494 int ogg_stream_flush(ogg_stream_state *os,ogg_page *og){
495 return ogg_stream_flush_i(os,og,1,4096);
498 /* Like the above, but an argument is provided to adjust the nominal
499 page size for applications which are smart enough to provide their
500 own delay based flushing */
502 int ogg_stream_flush_fill(ogg_stream_state *os,ogg_page *og, int nfill){
503 return ogg_stream_flush_i(os,og,1,nfill);
506 /* This constructs pages from buffered packet segments. The pointers
507 returned are to static buffers; do not free. The returned buffers are
508 good only until the next call (using the same ogg_stream_state) */
510 int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og){
512 if(ogg_stream_check(os)) return 0;
514 if((os->e_o_s&&os->lacing_fill) || /* 'were done, now flush' case */
515 (os->lacing_fill&&!os->b_o_s)) /* 'initial header page' case */
518 return(ogg_stream_flush_i(os,og,force,4096));
521 /* Like the above, but an argument is provided to adjust the nominal
522 page size for applications which are smart enough to provide their
523 own delay based flushing */
525 int ogg_stream_pageout_fill(ogg_stream_state *os, ogg_page *og, int nfill){
527 if(ogg_stream_check(os)) return 0;
529 if((os->e_o_s&&os->lacing_fill) || /* 'were done, now flush' case */
530 (os->lacing_fill&&!os->b_o_s)) /* 'initial header page' case */
533 return(ogg_stream_flush_i(os,og,force,nfill));
536 int ogg_stream_eos(ogg_stream_state *os){
537 if(ogg_stream_check(os)) return 1;
541 /* DECODING PRIMITIVES: packet streaming layer **********************/
543 /* This has two layers to place more of the multi-serialno and paging
544 control in the application's hands. First, we expose a data buffer
545 using ogg_sync_buffer(). The app either copies into the
546 buffer, or passes it directly to read(), etc. We then call
547 ogg_sync_wrote() to tell how many bytes we just added.
549 Pages are returned (pointers into the buffer in ogg_sync_state)
550 by ogg_sync_pageout(). The page is then submitted to
551 ogg_stream_pagein() along with the appropriate
552 ogg_stream_state* (ie, matching serialno). We then get raw
553 packets out calling ogg_stream_packetout() with a
556 /* initialize the struct to a known state */
557 int ogg_sync_init(ogg_sync_state *oy){
559 oy->storage = -1; /* used as a readiness flag */
560 memset(oy,0,sizeof(*oy));
565 /* clear non-flat storage within */
566 int ogg_sync_clear(ogg_sync_state *oy){
568 if(oy->data)_ogg_free(oy->data);
569 memset(oy,0,sizeof(*oy));
574 int ogg_sync_destroy(ogg_sync_state *oy){
582 int ogg_sync_check(ogg_sync_state *oy){
583 if(oy->storage<0) return -1;
587 char *ogg_sync_buffer(ogg_sync_state *oy, long size){
588 if(ogg_sync_check(oy)) return NULL;
590 /* first, clear out any space that has been previously returned */
592 oy->fill-=oy->returned;
594 memmove(oy->data,oy->data+oy->returned,oy->fill);
598 if(size>oy->storage-oy->fill){
599 /* We need to extend the internal buffer */
603 if(size>INT_MAX-4096-oy->fill){
607 newsize=size+oy->fill+4096; /* an extra page to be nice */
609 ret=_ogg_realloc(oy->data,newsize);
611 ret=_ogg_malloc(newsize);
620 /* expose a segment at least as large as requested at the fill mark */
621 return((char *)oy->data+oy->fill);
624 int ogg_sync_wrote(ogg_sync_state *oy, long bytes){
625 if(ogg_sync_check(oy))return -1;
626 if(oy->fill+bytes>oy->storage)return -1;
631 /* sync the stream. This is meant to be useful for finding page
634 return values for this:
636 0) page not ready; more data (no bytes skipped)
637 n) page synced at current location; page length n bytes
641 long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){
642 unsigned char *page=oy->data+oy->returned;
644 long bytes=oy->fill-oy->returned;
646 if(ogg_sync_check(oy))return 0;
648 if(oy->headerbytes==0){
650 if(bytes<27)return(0); /* not enough for a header */
652 /* verify capture pattern */
653 if(memcmp(page,"OggS",4))goto sync_fail;
655 headerbytes=page[26]+27;
656 if(bytes<headerbytes)return(0); /* not enough for header + seg table */
658 /* count up body length in the segment table */
660 for(i=0;i<page[26];i++)
661 oy->bodybytes+=page[27+i];
662 oy->headerbytes=headerbytes;
665 if(oy->bodybytes+oy->headerbytes>bytes)return(0);
667 /* The whole test page is buffered. Verify the checksum */
669 /* Grab the checksum bytes, set the header field to zero */
673 memcpy(chksum,page+22,4);
676 /* set up a temp page struct and recompute the checksum */
678 log.header_len=oy->headerbytes;
679 log.body=page+oy->headerbytes;
680 log.body_len=oy->bodybytes;
681 ogg_page_checksum_set(&log);
684 if(memcmp(chksum,page+22,4)){
685 /* D'oh. Mismatch! Corrupt page (or miscapture and not a page
687 /* replace the computed checksum with the one actually read in */
688 memcpy(page+22,chksum,4);
691 /* Bad checksum. Lose sync */
697 /* yes, have a whole page all ready to go */
701 og->header_len=oy->headerbytes;
702 og->body=page+oy->headerbytes;
703 og->body_len=oy->bodybytes;
707 oy->returned+=(bytes=oy->headerbytes+oy->bodybytes);
718 /* search for possible capture */
719 next=memchr(page+1,'O',bytes-1);
721 next=oy->data+oy->fill;
723 oy->returned=(int)(next-oy->data);
724 return((long)-(next-page));
727 /* sync the stream and get a page. Keep trying until we find a page.
728 Suppress 'sync errors' after reporting the first.
731 -1) recapture (hole in data)
735 Returns pointers into buffered data; invalidated by next call to
736 _stream, _clear, _init, or _buffer */
738 int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og){
740 if(ogg_sync_check(oy))return 0;
742 /* all we need to do is verify a page at the head of the stream
743 buffer. If it doesn't verify, we look for the next potential
747 long ret=ogg_sync_pageseek(oy,og);
757 /* head did not start a synced page... skipped some bytes */
763 /* loop. keep looking */
768 /* add the incoming page to the stream state; we decompose the page
769 into packet segments here as well. */
771 int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){
772 unsigned char *header=og->header;
773 unsigned char *body=og->body;
774 long bodysize=og->body_len;
777 int version=ogg_page_version(og);
778 int continued=ogg_page_continued(og);
779 int bos=ogg_page_bos(og);
780 int eos=ogg_page_eos(og);
781 ogg_int64_t granulepos=ogg_page_granulepos(og);
782 int serialno=ogg_page_serialno(og);
783 long pageno=ogg_page_pageno(og);
784 int segments=header[26];
786 if(ogg_stream_check(os)) return -1;
788 /* clean up 'returned data' */
790 long lr=os->lacing_returned;
791 long br=os->body_returned;
797 memmove(os->body_data,os->body_data+br,os->body_fill);
803 if(os->lacing_fill-lr){
804 memmove(os->lacing_vals,os->lacing_vals+lr,
805 (os->lacing_fill-lr)*sizeof(*os->lacing_vals));
806 memmove(os->granule_vals,os->granule_vals+lr,
807 (os->lacing_fill-lr)*sizeof(*os->granule_vals));
810 os->lacing_packet-=lr;
811 os->lacing_returned=0;
815 /* check the serial number */
816 if(serialno!=os->serialno)return(-1);
817 if(version>0)return(-1);
819 if(_os_lacing_expand(os,segments+1)) return -1;
821 /* are we in sequence? */
822 if(pageno!=os->pageno){
825 /* unroll previous partial packet (if any) */
826 for(i=os->lacing_packet;i<os->lacing_fill;i++)
827 os->body_fill-=os->lacing_vals[i]&0xff;
828 os->lacing_fill=os->lacing_packet;
830 /* make a note of dropped data in segment table */
832 os->lacing_vals[os->lacing_fill++]=0x400;
837 /* are we a 'continued packet' page? If so, we may need to skip
840 if(os->lacing_fill<1 ||
841 (os->lacing_vals[os->lacing_fill-1]&0xff)<255 ||
842 os->lacing_vals[os->lacing_fill-1]==0x400){
844 for(;segptr<segments;segptr++){
845 int val=header[27+segptr];
857 if(_os_body_expand(os,bodysize)) return -1;
858 memcpy(os->body_data+os->body_fill,body,bodysize);
859 os->body_fill+=bodysize;
864 while(segptr<segments){
865 int val=header[27+segptr];
866 os->lacing_vals[os->lacing_fill]=val;
867 os->granule_vals[os->lacing_fill]=-1;
870 os->lacing_vals[os->lacing_fill]|=0x100;
874 if(val<255)saved=os->lacing_fill;
879 if(val<255)os->lacing_packet=os->lacing_fill;
882 /* set the granulepos on the last granuleval of the last full packet */
884 os->granule_vals[saved]=granulepos;
891 if(os->lacing_fill>0)
892 os->lacing_vals[os->lacing_fill-1]|=0x200;
900 /* clear things to an initial state. Good to call, eg, before seeking */
901 int ogg_sync_reset(ogg_sync_state *oy){
902 if(ogg_sync_check(oy))return -1;
912 int ogg_stream_reset(ogg_stream_state *os){
913 if(ogg_stream_check(os)) return -1;
920 os->lacing_returned=0;
933 int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno){
934 if(ogg_stream_check(os)) return -1;
935 ogg_stream_reset(os);
936 os->serialno=serialno;
940 static int _packetout(ogg_stream_state *os,ogg_packet *op,int adv){
942 /* The last part of decode. We have the stream broken into packet
943 segments. Now we need to group them into packets (or return the
944 out of sync markers) */
946 int ptr=os->lacing_returned;
948 if(os->lacing_packet<=ptr)return(0);
950 if(os->lacing_vals[ptr]&0x400){
951 /* we need to tell the codec there's a gap; it might need to
952 handle previous packet dependencies. */
953 os->lacing_returned++;
958 if(!op && !adv)return(1); /* just using peek as an inexpensive way
959 to ask if there's a whole packet
962 /* Gather the whole packet. We'll have no holes or a partial packet */
964 int size=os->lacing_vals[ptr]&0xff;
966 int eos=os->lacing_vals[ptr]&0x200; /* last packet of the stream? */
967 int bos=os->lacing_vals[ptr]&0x100; /* first packet of the stream? */
970 int val=os->lacing_vals[++ptr];
972 if(val&0x200)eos=0x200;
979 op->packet=os->body_data+os->body_returned;
980 op->packetno=os->packetno;
981 op->granulepos=os->granule_vals[ptr];
986 os->body_returned+=bytes;
987 os->lacing_returned=ptr+1;
994 int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op){
995 if(ogg_stream_check(os)) return 0;
996 return _packetout(os,op,1);
999 int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op){
1000 if(ogg_stream_check(os)) return 0;
1001 return _packetout(os,op,0);
1004 void ogg_packet_clear(ogg_packet *op) {
1005 _ogg_free(op->packet);
1006 memset(op, 0, sizeof(*op));
1012 ogg_stream_state os_en, os_de;
1015 void checkpacket(ogg_packet *op,long len, int no, long pos){
1017 static int sequence=0;
1018 static int lastno=0;
1021 fprintf(stderr,"incorrect packet length (%ld != %ld)!\n",op->bytes,len);
1024 if(op->granulepos!=pos){
1025 fprintf(stderr,"incorrect packet granpos (%ld != %ld)!\n",(long)op->granulepos,pos);
1029 /* packet number just follows sequence/gap; adjust the input number
1039 if(op->packetno!=sequence){
1040 fprintf(stderr,"incorrect packet sequence %ld != %d\n",
1041 (long)(op->packetno),sequence);
1046 for(j=0;j<op->bytes;j++)
1047 if(op->packet[j]!=((j+no)&0xff)){
1048 fprintf(stderr,"body data mismatch (1) at pos %ld: %x!=%lx!\n\n",
1049 j,op->packet[j],(j+no)&0xff);
1054 void check_page(unsigned char *data,const int *header,ogg_page *og){
1057 for(j=0;j<og->body_len;j++)
1058 if(og->body[j]!=data[j]){
1059 fprintf(stderr,"body data mismatch (2) at pos %ld: %x!=%x!\n\n",
1060 j,data[j],og->body[j]);
1065 for(j=0;j<og->header_len;j++){
1066 if(og->header[j]!=header[j]){
1067 fprintf(stderr,"header content mismatch at pos %ld:\n",j);
1068 for(j=0;j<header[26]+27;j++)
1069 fprintf(stderr," (%ld)%02x:%02x",j,header[j],og->header[j]);
1070 fprintf(stderr,"\n");
1074 if(og->header_len!=header[26]+27){
1075 fprintf(stderr,"header length incorrect! (%ld!=%d)\n",
1076 og->header_len,header[26]+27);
1081 void print_header(ogg_page *og){
1083 fprintf(stderr,"\nHEADER:\n");
1084 fprintf(stderr," capture: %c %c %c %c version: %d flags: %x\n",
1085 og->header[0],og->header[1],og->header[2],og->header[3],
1086 (int)og->header[4],(int)og->header[5]);
1088 fprintf(stderr," granulepos: %d serialno: %d pageno: %ld\n",
1089 (og->header[9]<<24)|(og->header[8]<<16)|
1090 (og->header[7]<<8)|og->header[6],
1091 (og->header[17]<<24)|(og->header[16]<<16)|
1092 (og->header[15]<<8)|og->header[14],
1093 ((long)(og->header[21])<<24)|(og->header[20]<<16)|
1094 (og->header[19]<<8)|og->header[18]);
1096 fprintf(stderr," checksum: %02x:%02x:%02x:%02x\n segments: %d (",
1097 (int)og->header[22],(int)og->header[23],
1098 (int)og->header[24],(int)og->header[25],
1099 (int)og->header[26]);
1101 for(j=27;j<og->header_len;j++)
1102 fprintf(stderr,"%d ",(int)og->header[j]);
1103 fprintf(stderr,")\n\n");
1106 void copy_page(ogg_page *og){
1107 unsigned char *temp=_ogg_malloc(og->header_len);
1108 memcpy(temp,og->header,og->header_len);
1111 temp=_ogg_malloc(og->body_len);
1112 memcpy(temp,og->body,og->body_len);
1116 void free_page(ogg_page *og){
1117 _ogg_free (og->header);
1118 _ogg_free (og->body);
1122 fprintf(stderr,"error!\n");
1127 const int head1_0[] = {0x4f,0x67,0x67,0x53,0,0x06,
1128 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1129 0x01,0x02,0x03,0x04,0,0,0,0,
1130 0x15,0xed,0xec,0x91,
1134 /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
1135 const int head1_1[] = {0x4f,0x67,0x67,0x53,0,0x02,
1136 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1137 0x01,0x02,0x03,0x04,0,0,0,0,
1138 0x59,0x10,0x6c,0x2c,
1141 const int head2_1[] = {0x4f,0x67,0x67,0x53,0,0x04,
1142 0x07,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
1143 0x01,0x02,0x03,0x04,1,0,0,0,
1144 0x89,0x33,0x85,0xce,
1146 254,255,0,255,1,255,245,255,255,0,
1149 /* nil packets; beginning,middle,end */
1150 const int head1_2[] = {0x4f,0x67,0x67,0x53,0,0x02,
1151 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1152 0x01,0x02,0x03,0x04,0,0,0,0,
1153 0xff,0x7b,0x23,0x17,
1156 const int head2_2[] = {0x4f,0x67,0x67,0x53,0,0x04,
1157 0x07,0x28,0x00,0x00,0x00,0x00,0x00,0x00,
1158 0x01,0x02,0x03,0x04,1,0,0,0,
1159 0x5c,0x3f,0x66,0xcb,
1161 17,254,255,0,0,255,1,0,255,245,255,255,0,
1164 /* large initial packet */
1165 const int head1_3[] = {0x4f,0x67,0x67,0x53,0,0x02,
1166 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1167 0x01,0x02,0x03,0x04,0,0,0,0,
1168 0x01,0x27,0x31,0xaa,
1170 255,255,255,255,255,255,255,255,
1171 255,255,255,255,255,255,255,255,255,10};
1173 const int head2_3[] = {0x4f,0x67,0x67,0x53,0,0x04,
1174 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
1175 0x01,0x02,0x03,0x04,1,0,0,0,
1176 0x7f,0x4e,0x8a,0xd2,
1181 /* continuing packet test */
1182 const int head1_4[] = {0x4f,0x67,0x67,0x53,0,0x02,
1183 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1184 0x01,0x02,0x03,0x04,0,0,0,0,
1185 0xff,0x7b,0x23,0x17,
1189 const int head2_4[] = {0x4f,0x67,0x67,0x53,0,0x00,
1190 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
1191 0x01,0x02,0x03,0x04,1,0,0,0,
1192 0xf8,0x3c,0x19,0x79,
1194 255,255,255,255,255,255,255,255,
1195 255,255,255,255,255,255,255,255,
1196 255,255,255,255,255,255,255,255,
1197 255,255,255,255,255,255,255,255,
1198 255,255,255,255,255,255,255,255,
1199 255,255,255,255,255,255,255,255,
1200 255,255,255,255,255,255,255,255,
1201 255,255,255,255,255,255,255,255,
1202 255,255,255,255,255,255,255,255,
1203 255,255,255,255,255,255,255,255,
1204 255,255,255,255,255,255,255,255,
1205 255,255,255,255,255,255,255,255,
1206 255,255,255,255,255,255,255,255,
1207 255,255,255,255,255,255,255,255,
1208 255,255,255,255,255,255,255,255,
1209 255,255,255,255,255,255,255,255,
1210 255,255,255,255,255,255,255,255,
1211 255,255,255,255,255,255,255,255,
1212 255,255,255,255,255,255,255,255,
1213 255,255,255,255,255,255,255,255,
1214 255,255,255,255,255,255,255,255,
1215 255,255,255,255,255,255,255,255,
1216 255,255,255,255,255,255,255,255,
1217 255,255,255,255,255,255,255,255,
1218 255,255,255,255,255,255,255,255,
1219 255,255,255,255,255,255,255,255,
1220 255,255,255,255,255,255,255,255,
1221 255,255,255,255,255,255,255,255,
1222 255,255,255,255,255,255,255,255,
1223 255,255,255,255,255,255,255,255,
1224 255,255,255,255,255,255,255,255,
1225 255,255,255,255,255,255,255};
1227 const int head3_4[] = {0x4f,0x67,0x67,0x53,0,0x05,
1228 0x07,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,
1229 0x01,0x02,0x03,0x04,2,0,0,0,
1230 0x38,0xe6,0xb6,0x28,
1232 255,220,255,4,255,0};
1235 /* spill expansion test */
1236 const int head1_4b[] = {0x4f,0x67,0x67,0x53,0,0x02,
1237 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1238 0x01,0x02,0x03,0x04,0,0,0,0,
1239 0xff,0x7b,0x23,0x17,
1243 const int head2_4b[] = {0x4f,0x67,0x67,0x53,0,0x00,
1244 0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
1245 0x01,0x02,0x03,0x04,1,0,0,0,
1246 0xce,0x8f,0x17,0x1a,
1248 255,255,255,255,255,255,255,255,
1249 255,255,255,255,255,255,255,255,255,10,255,4,255,0,0};
1252 const int head3_4b[] = {0x4f,0x67,0x67,0x53,0,0x04,
1253 0x07,0x14,0x00,0x00,0x00,0x00,0x00,0x00,
1254 0x01,0x02,0x03,0x04,2,0,0,0,
1255 0x9b,0xb2,0x50,0xa1,
1259 /* page with the 255 segment limit */
1260 const int head1_5[] = {0x4f,0x67,0x67,0x53,0,0x02,
1261 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1262 0x01,0x02,0x03,0x04,0,0,0,0,
1263 0xff,0x7b,0x23,0x17,
1267 const int head2_5[] = {0x4f,0x67,0x67,0x53,0,0x00,
1268 0x07,0xfc,0x03,0x00,0x00,0x00,0x00,0x00,
1269 0x01,0x02,0x03,0x04,1,0,0,0,
1270 0xed,0x2a,0x2e,0xa7,
1272 10,10,10,10,10,10,10,10,
1273 10,10,10,10,10,10,10,10,
1274 10,10,10,10,10,10,10,10,
1275 10,10,10,10,10,10,10,10,
1276 10,10,10,10,10,10,10,10,
1277 10,10,10,10,10,10,10,10,
1278 10,10,10,10,10,10,10,10,
1279 10,10,10,10,10,10,10,10,
1280 10,10,10,10,10,10,10,10,
1281 10,10,10,10,10,10,10,10,
1282 10,10,10,10,10,10,10,10,
1283 10,10,10,10,10,10,10,10,
1284 10,10,10,10,10,10,10,10,
1285 10,10,10,10,10,10,10,10,
1286 10,10,10,10,10,10,10,10,
1287 10,10,10,10,10,10,10,10,
1288 10,10,10,10,10,10,10,10,
1289 10,10,10,10,10,10,10,10,
1290 10,10,10,10,10,10,10,10,
1291 10,10,10,10,10,10,10,10,
1292 10,10,10,10,10,10,10,10,
1293 10,10,10,10,10,10,10,10,
1294 10,10,10,10,10,10,10,10,
1295 10,10,10,10,10,10,10,10,
1296 10,10,10,10,10,10,10,10,
1297 10,10,10,10,10,10,10,10,
1298 10,10,10,10,10,10,10,10,
1299 10,10,10,10,10,10,10,10,
1300 10,10,10,10,10,10,10,10,
1301 10,10,10,10,10,10,10,10,
1302 10,10,10,10,10,10,10,10,
1303 10,10,10,10,10,10,10};
1305 const int head3_5[] = {0x4f,0x67,0x67,0x53,0,0x04,
1306 0x07,0x00,0x04,0x00,0x00,0x00,0x00,0x00,
1307 0x01,0x02,0x03,0x04,2,0,0,0,
1308 0x6c,0x3b,0x82,0x3d,
1313 /* packet that overspans over an entire page */
1314 const int head1_6[] = {0x4f,0x67,0x67,0x53,0,0x02,
1315 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1316 0x01,0x02,0x03,0x04,0,0,0,0,
1317 0xff,0x7b,0x23,0x17,
1321 const int head2_6[] = {0x4f,0x67,0x67,0x53,0,0x00,
1322 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
1323 0x01,0x02,0x03,0x04,1,0,0,0,
1324 0x68,0x22,0x7c,0x3d,
1327 255,255,255,255,255,255,255,255,
1328 255,255,255,255,255,255,255,255,
1329 255,255,255,255,255,255,255,255,
1330 255,255,255,255,255,255,255,255,
1331 255,255,255,255,255,255,255,255,
1332 255,255,255,255,255,255,255,255,
1333 255,255,255,255,255,255,255,255,
1334 255,255,255,255,255,255,255,255,
1335 255,255,255,255,255,255,255,255,
1336 255,255,255,255,255,255,255,255,
1337 255,255,255,255,255,255,255,255,
1338 255,255,255,255,255,255,255,255,
1339 255,255,255,255,255,255,255,255,
1340 255,255,255,255,255,255,255,255,
1341 255,255,255,255,255,255,255,255,
1342 255,255,255,255,255,255,255,255,
1343 255,255,255,255,255,255,255,255,
1344 255,255,255,255,255,255,255,255,
1345 255,255,255,255,255,255,255,255,
1346 255,255,255,255,255,255,255,255,
1347 255,255,255,255,255,255,255,255,
1348 255,255,255,255,255,255,255,255,
1349 255,255,255,255,255,255,255,255,
1350 255,255,255,255,255,255,255,255,
1351 255,255,255,255,255,255,255,255,
1352 255,255,255,255,255,255,255,255,
1353 255,255,255,255,255,255,255,255,
1354 255,255,255,255,255,255,255,255,
1355 255,255,255,255,255,255,255,255,
1356 255,255,255,255,255,255,255,255,
1357 255,255,255,255,255,255,255,255,
1358 255,255,255,255,255,255};
1360 const int head3_6[] = {0x4f,0x67,0x67,0x53,0,0x01,
1361 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
1362 0x01,0x02,0x03,0x04,2,0,0,0,
1363 0xf4,0x87,0xba,0xf3,
1365 255,255,255,255,255,255,255,255,
1366 255,255,255,255,255,255,255,255,
1367 255,255,255,255,255,255,255,255,
1368 255,255,255,255,255,255,255,255,
1369 255,255,255,255,255,255,255,255,
1370 255,255,255,255,255,255,255,255,
1371 255,255,255,255,255,255,255,255,
1372 255,255,255,255,255,255,255,255,
1373 255,255,255,255,255,255,255,255,
1374 255,255,255,255,255,255,255,255,
1375 255,255,255,255,255,255,255,255,
1376 255,255,255,255,255,255,255,255,
1377 255,255,255,255,255,255,255,255,
1378 255,255,255,255,255,255,255,255,
1379 255,255,255,255,255,255,255,255,
1380 255,255,255,255,255,255,255,255,
1381 255,255,255,255,255,255,255,255,
1382 255,255,255,255,255,255,255,255,
1383 255,255,255,255,255,255,255,255,
1384 255,255,255,255,255,255,255,255,
1385 255,255,255,255,255,255,255,255,
1386 255,255,255,255,255,255,255,255,
1387 255,255,255,255,255,255,255,255,
1388 255,255,255,255,255,255,255,255,
1389 255,255,255,255,255,255,255,255,
1390 255,255,255,255,255,255,255,255,
1391 255,255,255,255,255,255,255,255,
1392 255,255,255,255,255,255,255,255,
1393 255,255,255,255,255,255,255,255,
1394 255,255,255,255,255,255,255,255,
1395 255,255,255,255,255,255,255,255,
1396 255,255,255,255,255,255,255};
1398 const int head4_6[] = {0x4f,0x67,0x67,0x53,0,0x05,
1399 0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
1400 0x01,0x02,0x03,0x04,3,0,0,0,
1401 0xf7,0x2f,0x6c,0x60,
1405 /* packet that overspans over an entire page */
1406 const int head1_7[] = {0x4f,0x67,0x67,0x53,0,0x02,
1407 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1408 0x01,0x02,0x03,0x04,0,0,0,0,
1409 0xff,0x7b,0x23,0x17,
1413 const int head2_7[] = {0x4f,0x67,0x67,0x53,0,0x00,
1414 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
1415 0x01,0x02,0x03,0x04,1,0,0,0,
1416 0x68,0x22,0x7c,0x3d,
1419 255,255,255,255,255,255,255,255,
1420 255,255,255,255,255,255,255,255,
1421 255,255,255,255,255,255,255,255,
1422 255,255,255,255,255,255,255,255,
1423 255,255,255,255,255,255,255,255,
1424 255,255,255,255,255,255,255,255,
1425 255,255,255,255,255,255,255,255,
1426 255,255,255,255,255,255,255,255,
1427 255,255,255,255,255,255,255,255,
1428 255,255,255,255,255,255,255,255,
1429 255,255,255,255,255,255,255,255,
1430 255,255,255,255,255,255,255,255,
1431 255,255,255,255,255,255,255,255,
1432 255,255,255,255,255,255,255,255,
1433 255,255,255,255,255,255,255,255,
1434 255,255,255,255,255,255,255,255,
1435 255,255,255,255,255,255,255,255,
1436 255,255,255,255,255,255,255,255,
1437 255,255,255,255,255,255,255,255,
1438 255,255,255,255,255,255,255,255,
1439 255,255,255,255,255,255,255,255,
1440 255,255,255,255,255,255,255,255,
1441 255,255,255,255,255,255,255,255,
1442 255,255,255,255,255,255,255,255,
1443 255,255,255,255,255,255,255,255,
1444 255,255,255,255,255,255,255,255,
1445 255,255,255,255,255,255,255,255,
1446 255,255,255,255,255,255,255,255,
1447 255,255,255,255,255,255,255,255,
1448 255,255,255,255,255,255,255,255,
1449 255,255,255,255,255,255,255,255,
1450 255,255,255,255,255,255};
1452 const int head3_7[] = {0x4f,0x67,0x67,0x53,0,0x05,
1453 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
1454 0x01,0x02,0x03,0x04,2,0,0,0,
1455 0xd4,0xe0,0x60,0xe5,
1459 int compare_packet(const ogg_packet *op1, const ogg_packet *op2){
1460 if(op1->packet!=op2->packet){
1461 fprintf(stderr,"op1->packet != op2->packet\n");
1464 if(op1->bytes!=op2->bytes){
1465 fprintf(stderr,"op1->bytes != op2->bytes\n");
1468 if(op1->b_o_s!=op2->b_o_s){
1469 fprintf(stderr,"op1->b_o_s != op2->b_o_s\n");
1472 if(op1->e_o_s!=op2->e_o_s){
1473 fprintf(stderr,"op1->e_o_s != op2->e_o_s\n");
1476 if(op1->granulepos!=op2->granulepos){
1477 fprintf(stderr,"op1->granulepos != op2->granulepos\n");
1480 if(op1->packetno!=op2->packetno){
1481 fprintf(stderr,"op1->packetno != op2->packetno\n");
1487 void test_pack(const int *pl, const int **headers, int byteskip,
1488 int pageskip, int packetskip){
1489 unsigned char *data=_ogg_malloc(1024*1024); /* for scripted test cases only */
1494 long granule_pos=7,pageno=0;
1495 int i,j,packets,pageout=pageskip;
1499 int byteskipcount=0;
1501 ogg_stream_reset(&os_en);
1502 ogg_stream_reset(&os_de);
1503 ogg_sync_reset(&oy);
1505 for(packets=0;packets<packetskip;packets++)
1506 depacket+=pl[packets];
1508 for(packets=0;;packets++)if(pl[packets]==-1)break;
1510 for(i=0;i<packets;i++){
1511 /* construct a test packet */
1515 op.packet=data+inptr;
1517 op.e_o_s=(pl[i+1]<0?1:0);
1518 op.granulepos=granule_pos;
1522 for(j=0;j<len;j++)data[inptr++]=i+j;
1524 /* submit the test packet */
1525 ogg_stream_packetin(&os_en,&op);
1527 /* retrieve any finished pages */
1531 while(ogg_stream_pageout(&os_en,&og)){
1532 /* We have a page. Check it carefully */
1534 fprintf(stderr,"%ld, ",pageno);
1536 if(headers[pageno]==NULL){
1537 fprintf(stderr,"coded too many pages!\n");
1541 check_page(data+outptr,headers[pageno],&og);
1543 outptr+=og.body_len;
1551 /* have a complete page; submit it to sync/decode */
1555 ogg_packet op_de,op_de2;
1556 char *buf=ogg_sync_buffer(&oy,og.header_len+og.body_len);
1558 byteskipcount+=og.header_len;
1559 if(byteskipcount>byteskip){
1560 memcpy(next,og.header,byteskipcount-byteskip);
1561 next+=byteskipcount-byteskip;
1562 byteskipcount=byteskip;
1565 byteskipcount+=og.body_len;
1566 if(byteskipcount>byteskip){
1567 memcpy(next,og.body,byteskipcount-byteskip);
1568 next+=byteskipcount-byteskip;
1569 byteskipcount=byteskip;
1572 ogg_sync_wrote(&oy,(long)(next-buf));
1575 int ret=ogg_sync_pageout(&oy,&og_de);
1578 /* got a page. Happy happy. Verify that it's good. */
1580 fprintf(stderr,"(%d), ",pageout);
1582 check_page(data+deptr,headers[pageout],&og_de);
1583 deptr+=og_de.body_len;
1586 /* submit it to deconstitution */
1587 ogg_stream_pagein(&os_de,&og_de);
1590 while(ogg_stream_packetpeek(&os_de,&op_de2)>0){
1591 ogg_stream_packetpeek(&os_de,NULL);
1592 ogg_stream_packetout(&os_de,&op_de); /* just catching them all */
1594 /* verify peek and out match */
1595 if(compare_packet(&op_de,&op_de2)){
1596 fprintf(stderr,"packetout != packetpeek! pos=%ld\n",
1601 /* verify the packet! */
1603 if(memcmp(data+depacket,op_de.packet,op_de.bytes)){
1604 fprintf(stderr,"packet data mismatch in decode! pos=%ld\n",
1608 /* check bos flag */
1609 if(bosflag==0 && op_de.b_o_s==0){
1610 fprintf(stderr,"b_o_s flag not set on packet!\n");
1613 if(bosflag && op_de.b_o_s){
1614 fprintf(stderr,"b_o_s flag incorrectly set on packet!\n");
1618 depacket+=op_de.bytes;
1620 /* check eos flag */
1622 fprintf(stderr,"Multiple decoded packets with eos flag!\n");
1626 if(op_de.e_o_s)eosflag=1;
1628 /* check granulepos flag */
1629 if(op_de.granulepos!=-1){
1630 fprintf(stderr," granule:%ld ",(long)op_de.granulepos);
1639 if(headers[pageno]!=NULL){
1640 fprintf(stderr,"did not write last page!\n");
1643 if(headers[pageout]!=NULL){
1644 fprintf(stderr,"did not decode last page!\n");
1648 fprintf(stderr,"encoded page data incomplete!\n");
1652 fprintf(stderr,"decoded page data incomplete!\n");
1655 if(inptr!=depacket){
1656 fprintf(stderr,"decoded packet data incomplete!\n");
1660 fprintf(stderr,"Never got a packet with EOS set!\n");
1663 fprintf(stderr,"ok.\n");
1668 ogg_stream_init(&os_en,0x04030201);
1669 ogg_stream_init(&os_de,0x04030201);
1672 /* Exercise each code path in the framing code. Also verify that
1673 the checksums are working. */
1677 const int packets[]={17, -1};
1678 const int *headret[]={head1_0,NULL};
1680 fprintf(stderr,"testing single page encoding... ");
1681 test_pack(packets,headret,0,0,0);
1685 /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
1686 const int packets[]={17, 254, 255, 256, 500, 510, 600, -1};
1687 const int *headret[]={head1_1,head2_1,NULL};
1689 fprintf(stderr,"testing basic page encoding... ");
1690 test_pack(packets,headret,0,0,0);
1694 /* nil packets; beginning,middle,end */
1695 const int packets[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1};
1696 const int *headret[]={head1_2,head2_2,NULL};
1698 fprintf(stderr,"testing basic nil packets... ");
1699 test_pack(packets,headret,0,0,0);
1703 /* large initial packet */
1704 const int packets[]={4345,259,255,-1};
1705 const int *headret[]={head1_3,head2_3,NULL};
1707 fprintf(stderr,"testing initial-packet lacing > 4k... ");
1708 test_pack(packets,headret,0,0,0);
1712 /* continuing packet test; with page spill expansion, we have to
1713 overflow the lacing table. */
1714 const int packets[]={0,65500,259,255,-1};
1715 const int *headret[]={head1_4,head2_4,head3_4,NULL};
1717 fprintf(stderr,"testing single packet page span... ");
1718 test_pack(packets,headret,0,0,0);
1722 /* spill expand packet test */
1723 const int packets[]={0,4345,259,255,0,0,-1};
1724 const int *headret[]={head1_4b,head2_4b,head3_4b,NULL};
1726 fprintf(stderr,"testing page spill expansion... ");
1727 test_pack(packets,headret,0,0,0);
1730 /* page with the 255 segment limit */
1733 const int packets[]={0,10,10,10,10,10,10,10,10,
1734 10,10,10,10,10,10,10,10,
1735 10,10,10,10,10,10,10,10,
1736 10,10,10,10,10,10,10,10,
1737 10,10,10,10,10,10,10,10,
1738 10,10,10,10,10,10,10,10,
1739 10,10,10,10,10,10,10,10,
1740 10,10,10,10,10,10,10,10,
1741 10,10,10,10,10,10,10,10,
1742 10,10,10,10,10,10,10,10,
1743 10,10,10,10,10,10,10,10,
1744 10,10,10,10,10,10,10,10,
1745 10,10,10,10,10,10,10,10,
1746 10,10,10,10,10,10,10,10,
1747 10,10,10,10,10,10,10,10,
1748 10,10,10,10,10,10,10,10,
1749 10,10,10,10,10,10,10,10,
1750 10,10,10,10,10,10,10,10,
1751 10,10,10,10,10,10,10,10,
1752 10,10,10,10,10,10,10,10,
1753 10,10,10,10,10,10,10,10,
1754 10,10,10,10,10,10,10,10,
1755 10,10,10,10,10,10,10,10,
1756 10,10,10,10,10,10,10,10,
1757 10,10,10,10,10,10,10,10,
1758 10,10,10,10,10,10,10,10,
1759 10,10,10,10,10,10,10,10,
1760 10,10,10,10,10,10,10,10,
1761 10,10,10,10,10,10,10,10,
1762 10,10,10,10,10,10,10,10,
1763 10,10,10,10,10,10,10,10,
1764 10,10,10,10,10,10,10,50,-1};
1765 const int *headret[]={head1_5,head2_5,head3_5,NULL};
1767 fprintf(stderr,"testing max packet segments... ");
1768 test_pack(packets,headret,0,0,0);
1772 /* packet that overspans over an entire page */
1773 const int packets[]={0,100,130049,259,255,-1};
1774 const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
1776 fprintf(stderr,"testing very large packets... ");
1777 test_pack(packets,headret,0,0,0);
1782 /* test for the libogg 1.1.1 resync in large continuation bug
1783 found by Josh Coalson) */
1784 const int packets[]={0,100,130049,259,255,-1};
1785 const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
1787 fprintf(stderr,"testing continuation resync in very large packets... ");
1788 test_pack(packets,headret,100,2,3);
1791 fprintf(stderr,"Skipping continuation resync test due to --disable-crc\n");
1795 /* term only page. why not? */
1796 const int packets[]={0,100,64770,-1};
1797 const int *headret[]={head1_7,head2_7,head3_7,NULL};
1799 fprintf(stderr,"testing zero data page (1 nil packet)... ");
1800 test_pack(packets,headret,0,0,0);
1806 /* build a bunch of pages for testing */
1807 unsigned char *data=_ogg_malloc(1024*1024);
1808 int pl[]={0, 1,1,98,4079, 1,1,2954,2057, 76,34,912,0,234,1000,1000, 1000,300,-1};
1812 ogg_stream_reset(&os_en);
1814 for(i=0;pl[i]!=-1;i++){
1818 op.packet=data+inptr;
1820 op.e_o_s=(pl[i+1]<0?1:0);
1821 op.granulepos=(i+1)*1000;
1823 for(j=0;j<len;j++)data[inptr++]=i+j;
1824 ogg_stream_packetin(&os_en,&op);
1829 /* retrieve finished pages */
1831 if(ogg_stream_pageout(&os_en,&og[i])==0){
1832 fprintf(stderr,"Too few pages output building sync tests!\n");
1838 /* Test lost pages on pagein/packetout: no rollback */
1843 fprintf(stderr,"Testing loss of pages... ");
1845 ogg_sync_reset(&oy);
1846 ogg_stream_reset(&os_de);
1848 memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
1850 ogg_sync_wrote(&oy,og[i].header_len);
1851 memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
1852 ogg_sync_wrote(&oy,og[i].body_len);
1855 ogg_sync_pageout(&oy,&temp);
1856 ogg_stream_pagein(&os_de,&temp);
1857 ogg_sync_pageout(&oy,&temp);
1858 ogg_stream_pagein(&os_de,&temp);
1859 ogg_sync_pageout(&oy,&temp);
1861 ogg_sync_pageout(&oy,&temp);
1862 ogg_stream_pagein(&os_de,&temp);
1864 /* do we get the expected results/packets? */
1866 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1867 checkpacket(&test,0,0,0);
1868 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1869 checkpacket(&test,1,1,-1);
1870 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1871 checkpacket(&test,1,2,-1);
1872 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1873 checkpacket(&test,98,3,-1);
1874 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1875 checkpacket(&test,4079,4,5000);
1876 if(ogg_stream_packetout(&os_de,&test)!=-1){
1877 fprintf(stderr,"Error: loss of page did not return error\n");
1880 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1881 checkpacket(&test,76,9,-1);
1882 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1883 checkpacket(&test,34,10,-1);
1884 fprintf(stderr,"ok.\n");
1887 /* Test lost pages on pagein/packetout: rollback with continuation */
1892 fprintf(stderr,"Testing loss of pages (rollback required)... ");
1894 ogg_sync_reset(&oy);
1895 ogg_stream_reset(&os_de);
1897 memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
1899 ogg_sync_wrote(&oy,og[i].header_len);
1900 memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
1901 ogg_sync_wrote(&oy,og[i].body_len);
1904 ogg_sync_pageout(&oy,&temp);
1905 ogg_stream_pagein(&os_de,&temp);
1906 ogg_sync_pageout(&oy,&temp);
1907 ogg_stream_pagein(&os_de,&temp);
1908 ogg_sync_pageout(&oy,&temp);
1909 ogg_stream_pagein(&os_de,&temp);
1910 ogg_sync_pageout(&oy,&temp);
1912 ogg_sync_pageout(&oy,&temp);
1913 ogg_stream_pagein(&os_de,&temp);
1915 /* do we get the expected results/packets? */
1917 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1918 checkpacket(&test,0,0,0);
1919 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1920 checkpacket(&test,1,1,-1);
1921 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1922 checkpacket(&test,1,2,-1);
1923 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1924 checkpacket(&test,98,3,-1);
1925 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1926 checkpacket(&test,4079,4,5000);
1927 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1928 checkpacket(&test,1,5,-1);
1929 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1930 checkpacket(&test,1,6,-1);
1931 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1932 checkpacket(&test,2954,7,-1);
1933 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1934 checkpacket(&test,2057,8,9000);
1935 if(ogg_stream_packetout(&os_de,&test)!=-1){
1936 fprintf(stderr,"Error: loss of page did not return error\n");
1939 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1940 checkpacket(&test,300,17,18000);
1941 fprintf(stderr,"ok.\n");
1944 /* the rest only test sync */
1947 /* Test fractional page inputs: incomplete capture */
1948 fprintf(stderr,"Testing sync on partial inputs... ");
1949 ogg_sync_reset(&oy);
1950 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
1952 ogg_sync_wrote(&oy,3);
1953 if(ogg_sync_pageout(&oy,&og_de)>0)error();
1955 /* Test fractional page inputs: incomplete fixed header */
1956 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+3,
1958 ogg_sync_wrote(&oy,20);
1959 if(ogg_sync_pageout(&oy,&og_de)>0)error();
1961 /* Test fractional page inputs: incomplete header */
1962 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+23,
1964 ogg_sync_wrote(&oy,5);
1965 if(ogg_sync_pageout(&oy,&og_de)>0)error();
1967 /* Test fractional page inputs: incomplete body */
1969 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+28,
1970 og[1].header_len-28);
1971 ogg_sync_wrote(&oy,og[1].header_len-28);
1972 if(ogg_sync_pageout(&oy,&og_de)>0)error();
1974 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,1000);
1975 ogg_sync_wrote(&oy,1000);
1976 if(ogg_sync_pageout(&oy,&og_de)>0)error();
1978 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body+1000,
1979 og[1].body_len-1000);
1980 ogg_sync_wrote(&oy,og[1].body_len-1000);
1981 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
1983 fprintf(stderr,"ok.\n");
1986 /* Test fractional page inputs: page + incomplete capture */
1989 fprintf(stderr,"Testing sync on 1+partial inputs... ");
1990 ogg_sync_reset(&oy);
1992 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
1994 ogg_sync_wrote(&oy,og[1].header_len);
1996 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
1998 ogg_sync_wrote(&oy,og[1].body_len);
2000 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
2002 ogg_sync_wrote(&oy,20);
2003 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2004 if(ogg_sync_pageout(&oy,&og_de)>0)error();
2006 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+20,
2007 og[1].header_len-20);
2008 ogg_sync_wrote(&oy,og[1].header_len-20);
2009 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2011 ogg_sync_wrote(&oy,og[1].body_len);
2012 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2014 fprintf(stderr,"ok.\n");
2017 /* Test recapture: garbage + page */
2020 fprintf(stderr,"Testing search for capture... ");
2021 ogg_sync_reset(&oy);
2024 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2026 ogg_sync_wrote(&oy,og[1].body_len);
2028 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
2030 ogg_sync_wrote(&oy,og[1].header_len);
2032 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2034 ogg_sync_wrote(&oy,og[1].body_len);
2036 memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
2038 ogg_sync_wrote(&oy,20);
2039 if(ogg_sync_pageout(&oy,&og_de)>0)error();
2040 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2041 if(ogg_sync_pageout(&oy,&og_de)>0)error();
2043 memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header+20,
2044 og[2].header_len-20);
2045 ogg_sync_wrote(&oy,og[2].header_len-20);
2046 memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
2048 ogg_sync_wrote(&oy,og[2].body_len);
2049 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2051 fprintf(stderr,"ok.\n");
2055 /* Test recapture: page + garbage + page */
2058 fprintf(stderr,"Testing recapture... ");
2059 ogg_sync_reset(&oy);
2061 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
2063 ogg_sync_wrote(&oy,og[1].header_len);
2065 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2067 ogg_sync_wrote(&oy,og[1].body_len);
2069 memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
2071 ogg_sync_wrote(&oy,og[2].header_len);
2073 memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
2075 ogg_sync_wrote(&oy,og[2].header_len);
2077 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2079 memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
2081 ogg_sync_wrote(&oy,og[2].body_len-5);
2083 memcpy(ogg_sync_buffer(&oy,og[3].header_len),og[3].header,
2085 ogg_sync_wrote(&oy,og[3].header_len);
2087 memcpy(ogg_sync_buffer(&oy,og[3].body_len),og[3].body,
2089 ogg_sync_wrote(&oy,og[3].body_len);
2091 if(ogg_sync_pageout(&oy,&og_de)>0)error();
2092 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2094 fprintf(stderr,"ok.\n");
2097 fprintf(stderr,"Skipping recapture test due to --disable-crc\n");
2100 /* Free page data that was previously copied */
2107 ogg_sync_clear(&oy);
2108 ogg_stream_clear(&os_en);
2109 ogg_stream_clear(&os_de);