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-2010 *
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
15 last mod: $Id: framing.c 18758 2013-01-08 16:29:56Z tterribe $
17 note: The CRC code is directly derived from public domain code by
18 Ross Williams (ross@guest.adelaide.edu.au). See docs/framing.html
21 ********************************************************************/
28 /* A complete description of Ogg framing exists in docs/framing.html */
30 int ogg_page_version(const ogg_page *og){
31 return((int)(og->header[4]));
34 int ogg_page_continued(const ogg_page *og){
35 return((int)(og->header[5]&0x01));
38 int ogg_page_bos(const ogg_page *og){
39 return((int)(og->header[5]&0x02));
42 int ogg_page_eos(const ogg_page *og){
43 return((int)(og->header[5]&0x04));
46 ogg_int64_t ogg_page_granulepos(const ogg_page *og){
47 unsigned char *page=og->header;
48 ogg_int64_t granulepos=page[13]&(0xff);
49 granulepos= (granulepos<<8)|(page[12]&0xff);
50 granulepos= (granulepos<<8)|(page[11]&0xff);
51 granulepos= (granulepos<<8)|(page[10]&0xff);
52 granulepos= (granulepos<<8)|(page[9]&0xff);
53 granulepos= (granulepos<<8)|(page[8]&0xff);
54 granulepos= (granulepos<<8)|(page[7]&0xff);
55 granulepos= (granulepos<<8)|(page[6]&0xff);
59 int ogg_page_serialno(const ogg_page *og){
60 return(og->header[14] |
62 (og->header[16]<<16) |
63 (og->header[17]<<24));
66 long ogg_page_pageno(const ogg_page *og){
67 return(og->header[18] |
69 (og->header[20]<<16) |
70 (og->header[21]<<24));
75 /* returns the number of packets that are completed on this page (if
76 the leading packet is begun on a previous page, but ends on this
80 If a page consists of a packet begun on a previous page, and a new
81 packet begun (but not completed) on this page, the return will be:
82 ogg_page_packets(page) ==1,
83 ogg_page_continued(page) !=0
85 If a page happens to be a single packet that was begun on a
86 previous page, and spans to the next page (in the case of a three or
87 more page packet), the return will be:
88 ogg_page_packets(page) ==0,
89 ogg_page_continued(page) !=0
92 int ogg_page_packets(const ogg_page *og){
93 int i,n=og->header[26],count=0;
95 if(og->header[27+i]<255)count++;
101 /* helper to initialize lookup for direct-table CRC (illustrative; we
102 use the static init below) */
104 static ogg_uint32_t _ogg_crc_entry(unsigned long index){
110 if (r & 0x80000000UL)
111 r = (r << 1) ^ 0x04c11db7; /* The same as the ethernet generator
112 polynomial, although we use an
113 unreflected alg and an init/final
114 of 0, not 0xffffffff */
117 return (r & 0xffffffffUL);
121 static const ogg_uint32_t crc_lookup[256]={
122 0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9,
123 0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005,
124 0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61,
125 0x350c9b64,0x31cd86d3,0x3c8ea00a,0x384fbdbd,
126 0x4c11db70,0x48d0c6c7,0x4593e01e,0x4152fda9,
127 0x5f15adac,0x5bd4b01b,0x569796c2,0x52568b75,
128 0x6a1936c8,0x6ed82b7f,0x639b0da6,0x675a1011,
129 0x791d4014,0x7ddc5da3,0x709f7b7a,0x745e66cd,
130 0x9823b6e0,0x9ce2ab57,0x91a18d8e,0x95609039,
131 0x8b27c03c,0x8fe6dd8b,0x82a5fb52,0x8664e6e5,
132 0xbe2b5b58,0xbaea46ef,0xb7a96036,0xb3687d81,
133 0xad2f2d84,0xa9ee3033,0xa4ad16ea,0xa06c0b5d,
134 0xd4326d90,0xd0f37027,0xddb056fe,0xd9714b49,
135 0xc7361b4c,0xc3f706fb,0xceb42022,0xca753d95,
136 0xf23a8028,0xf6fb9d9f,0xfbb8bb46,0xff79a6f1,
137 0xe13ef6f4,0xe5ffeb43,0xe8bccd9a,0xec7dd02d,
138 0x34867077,0x30476dc0,0x3d044b19,0x39c556ae,
139 0x278206ab,0x23431b1c,0x2e003dc5,0x2ac12072,
140 0x128e9dcf,0x164f8078,0x1b0ca6a1,0x1fcdbb16,
141 0x018aeb13,0x054bf6a4,0x0808d07d,0x0cc9cdca,
142 0x7897ab07,0x7c56b6b0,0x71159069,0x75d48dde,
143 0x6b93dddb,0x6f52c06c,0x6211e6b5,0x66d0fb02,
144 0x5e9f46bf,0x5a5e5b08,0x571d7dd1,0x53dc6066,
145 0x4d9b3063,0x495a2dd4,0x44190b0d,0x40d816ba,
146 0xaca5c697,0xa864db20,0xa527fdf9,0xa1e6e04e,
147 0xbfa1b04b,0xbb60adfc,0xb6238b25,0xb2e29692,
148 0x8aad2b2f,0x8e6c3698,0x832f1041,0x87ee0df6,
149 0x99a95df3,0x9d684044,0x902b669d,0x94ea7b2a,
150 0xe0b41de7,0xe4750050,0xe9362689,0xedf73b3e,
151 0xf3b06b3b,0xf771768c,0xfa325055,0xfef34de2,
152 0xc6bcf05f,0xc27dede8,0xcf3ecb31,0xcbffd686,
153 0xd5b88683,0xd1799b34,0xdc3abded,0xd8fba05a,
154 0x690ce0ee,0x6dcdfd59,0x608edb80,0x644fc637,
155 0x7a089632,0x7ec98b85,0x738aad5c,0x774bb0eb,
156 0x4f040d56,0x4bc510e1,0x46863638,0x42472b8f,
157 0x5c007b8a,0x58c1663d,0x558240e4,0x51435d53,
158 0x251d3b9e,0x21dc2629,0x2c9f00f0,0x285e1d47,
159 0x36194d42,0x32d850f5,0x3f9b762c,0x3b5a6b9b,
160 0x0315d626,0x07d4cb91,0x0a97ed48,0x0e56f0ff,
161 0x1011a0fa,0x14d0bd4d,0x19939b94,0x1d528623,
162 0xf12f560e,0xf5ee4bb9,0xf8ad6d60,0xfc6c70d7,
163 0xe22b20d2,0xe6ea3d65,0xeba91bbc,0xef68060b,
164 0xd727bbb6,0xd3e6a601,0xdea580d8,0xda649d6f,
165 0xc423cd6a,0xc0e2d0dd,0xcda1f604,0xc960ebb3,
166 0xbd3e8d7e,0xb9ff90c9,0xb4bcb610,0xb07daba7,
167 0xae3afba2,0xaafbe615,0xa7b8c0cc,0xa379dd7b,
168 0x9b3660c6,0x9ff77d71,0x92b45ba8,0x9675461f,
169 0x8832161a,0x8cf30bad,0x81b02d74,0x857130c3,
170 0x5d8a9099,0x594b8d2e,0x5408abf7,0x50c9b640,
171 0x4e8ee645,0x4a4ffbf2,0x470cdd2b,0x43cdc09c,
172 0x7b827d21,0x7f436096,0x7200464f,0x76c15bf8,
173 0x68860bfd,0x6c47164a,0x61043093,0x65c52d24,
174 0x119b4be9,0x155a565e,0x18197087,0x1cd86d30,
175 0x029f3d35,0x065e2082,0x0b1d065b,0x0fdc1bec,
176 0x3793a651,0x3352bbe6,0x3e119d3f,0x3ad08088,
177 0x2497d08d,0x2056cd3a,0x2d15ebe3,0x29d4f654,
178 0xc5a92679,0xc1683bce,0xcc2b1d17,0xc8ea00a0,
179 0xd6ad50a5,0xd26c4d12,0xdf2f6bcb,0xdbee767c,
180 0xe3a1cbc1,0xe760d676,0xea23f0af,0xeee2ed18,
181 0xf0a5bd1d,0xf464a0aa,0xf9278673,0xfde69bc4,
182 0x89b8fd09,0x8d79e0be,0x803ac667,0x84fbdbd0,
183 0x9abc8bd5,0x9e7d9662,0x933eb0bb,0x97ffad0c,
184 0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668,
185 0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4};
187 /* init the encode/decode logical stream state */
189 int ogg_stream_init(ogg_stream_state *os,int serialno){
191 memset(os,0,sizeof(*os));
192 os->body_storage=16*1024;
193 os->lacing_storage=1024;
195 os->body_data=_ogg_malloc(os->body_storage*sizeof(*os->body_data));
196 os->lacing_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->lacing_vals));
197 os->granule_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->granule_vals));
199 if(!os->body_data || !os->lacing_vals || !os->granule_vals){
200 ogg_stream_clear(os);
204 os->serialno=serialno;
211 /* async/delayed error detection for the ogg_stream_state */
212 int ogg_stream_check(ogg_stream_state *os){
213 if(!os || !os->body_data) return -1;
217 /* _clear does not free os, only the non-flat storage within */
218 int ogg_stream_clear(ogg_stream_state *os){
220 if(os->body_data)_ogg_free(os->body_data);
221 if(os->lacing_vals)_ogg_free(os->lacing_vals);
222 if(os->granule_vals)_ogg_free(os->granule_vals);
224 memset(os,0,sizeof(*os));
229 int ogg_stream_destroy(ogg_stream_state *os){
231 ogg_stream_clear(os);
237 /* Helpers for ogg_stream_encode; this keeps the structure and
238 what's happening fairly clear */
240 static int _os_body_expand(ogg_stream_state *os,long needed){
241 if(os->body_storage-needed<=os->body_fill){
244 if(os->body_storage>LONG_MAX-needed){
245 ogg_stream_clear(os);
248 body_storage=os->body_storage+needed;
249 if(body_storage<LONG_MAX-1024)body_storage+=1024;
250 ret=_ogg_realloc(os->body_data,body_storage*sizeof(*os->body_data));
252 ogg_stream_clear(os);
255 os->body_storage=body_storage;
261 static int _os_lacing_expand(ogg_stream_state *os,long needed){
262 if(os->lacing_storage-needed<=os->lacing_fill){
265 if(os->lacing_storage>LONG_MAX-needed){
266 ogg_stream_clear(os);
269 lacing_storage=os->lacing_storage+needed;
270 if(lacing_storage<LONG_MAX-32)lacing_storage+=32;
271 ret=_ogg_realloc(os->lacing_vals,lacing_storage*sizeof(*os->lacing_vals));
273 ogg_stream_clear(os);
277 ret=_ogg_realloc(os->granule_vals,lacing_storage*
278 sizeof(*os->granule_vals));
280 ogg_stream_clear(os);
283 os->granule_vals=ret;
284 os->lacing_storage=lacing_storage;
289 /* checksum the page */
290 /* Direct table CRC; note that this will be faster in the future if we
291 perform the checksum simultaneously with other copies */
293 void ogg_page_checksum_set(ogg_page *og){
295 ogg_uint32_t crc_reg=0;
298 /* safety; needed for API behavior, but not framing code */
304 for(i=0;i<og->header_len;i++)
305 crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->header[i]];
306 for(i=0;i<og->body_len;i++)
307 crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->body[i]];
309 og->header[22]=(unsigned char)(crc_reg&0xff);
310 og->header[23]=(unsigned char)((crc_reg>>8)&0xff);
311 og->header[24]=(unsigned char)((crc_reg>>16)&0xff);
312 og->header[25]=(unsigned char)((crc_reg>>24)&0xff);
316 /* submit data to the internal buffer of the framing engine */
317 int ogg_stream_iovecin(ogg_stream_state *os, ogg_iovec_t *iov, int count,
318 long e_o_s, ogg_int64_t granulepos){
320 long bytes = 0, lacing_vals;
323 if(ogg_stream_check(os)) return -1;
326 for (i = 0; i < count; ++i){
327 if(iov[i].iov_len>LONG_MAX) return -1;
328 if(bytes>LONG_MAX-(long)iov[i].iov_len) return -1;
329 bytes += (long)iov[i].iov_len;
331 lacing_vals=bytes/255+1;
333 if(os->body_returned){
334 /* advance packet data according to the body_returned pointer. We
335 had to keep it around to return a pointer into the buffer last
338 os->body_fill-=os->body_returned;
340 memmove(os->body_data,os->body_data+os->body_returned,
345 /* make sure we have the buffer storage */
346 if(_os_body_expand(os,bytes) || _os_lacing_expand(os,lacing_vals))
349 /* Copy in the submitted packet. Yes, the copy is a waste; this is
350 the liability of overly clean abstraction for the time being. It
351 will actually be fairly easy to eliminate the extra copy in the
354 for (i = 0; i < count; ++i) {
355 memcpy(os->body_data+os->body_fill, iov[i].iov_base, iov[i].iov_len);
356 os->body_fill += (int)iov[i].iov_len;
359 /* Store lacing vals for this packet */
360 for(i=0;i<lacing_vals-1;i++){
361 os->lacing_vals[os->lacing_fill+i]=255;
362 os->granule_vals[os->lacing_fill+i]=os->granulepos;
364 os->lacing_vals[os->lacing_fill+i]=bytes%255;
365 os->granulepos=os->granule_vals[os->lacing_fill+i]=granulepos;
367 /* flag the first segment as the beginning of the packet */
368 os->lacing_vals[os->lacing_fill]|= 0x100;
370 os->lacing_fill+=lacing_vals;
372 /* for the sake of completeness */
375 if(e_o_s)os->e_o_s=1;
380 int ogg_stream_packetin(ogg_stream_state *os,ogg_packet *op){
382 iov.iov_base = op->packet;
383 iov.iov_len = op->bytes;
384 return ogg_stream_iovecin(os, &iov, 1, op->e_o_s, op->granulepos);
387 /* Conditionally flush a page; force==0 will only flush nominal-size
388 pages, force==1 forces us to flush a page regardless of page size
389 so long as there's any data available at all. */
390 static int ogg_stream_flush_i(ogg_stream_state *os,ogg_page *og, int force, int nfill){
393 int maxvals=(os->lacing_fill>255?255:os->lacing_fill);
396 ogg_int64_t granule_pos=-1;
398 if(ogg_stream_check(os)) return(0);
399 if(maxvals==0) return(0);
401 /* construct a page */
402 /* decide how many segments to include */
404 /* If this is the initial header case, the first page must only include
405 the initial header packet */
406 if(os->b_o_s==0){ /* 'initial header page' case */
408 for(vals=0;vals<maxvals;vals++){
409 if((os->lacing_vals[vals]&0x0ff)<255){
416 /* The extra packets_done, packet_just_done logic here attempts to do two things:
417 1) Don't unneccessarily span pages.
418 2) Unless necessary, don't flush pages if there are less than four packets on
419 them; this expands page size to reduce unneccessary overhead if incoming packets
421 These are not necessary behaviors, just 'always better than naive flushing'
422 without requiring an application to explicitly request a specific optimized
423 behavior. We'll want an explicit behavior setup pathway eventually as well. */
426 int packet_just_done=0;
427 for(vals=0;vals<maxvals;vals++){
428 if(acc>nfill && packet_just_done>=4){
432 acc+=os->lacing_vals[vals]&0x0ff;
433 if((os->lacing_vals[vals]&0xff)<255){
434 granule_pos=os->granule_vals[vals];
435 packet_just_done=++packets_done;
439 if(vals==255)force=1;
442 if(!force) return(0);
444 /* construct the header in temp storage */
445 memcpy(os->header,"OggS",4);
447 /* stream structure version */
450 /* continued packet flag? */
452 if((os->lacing_vals[0]&0x100)==0)os->header[5]|=0x01;
453 /* first page flag? */
454 if(os->b_o_s==0)os->header[5]|=0x02;
455 /* last page flag? */
456 if(os->e_o_s && os->lacing_fill==vals)os->header[5]|=0x04;
459 /* 64 bits of PCM position */
461 os->header[i]=(unsigned char)(granule_pos&0xff);
465 /* 32 bits of stream serial number */
467 long serialno=os->serialno;
469 os->header[i]=(unsigned char)(serialno&0xff);
474 /* 32 bits of page counter (we have both counter and page header
475 because this val can roll over) */
476 if(os->pageno==-1)os->pageno=0; /* because someone called
477 stream_reset; this would be a
478 strange thing to do in an
479 encode stream, but it has
482 long pageno=os->pageno++;
484 os->header[i]=(unsigned char)(pageno&0xff);
489 /* zero for computation; filled in later */
496 os->header[26]=(unsigned char)(vals&0xff);
498 bytes+=os->header[i+27]=(unsigned char)(os->lacing_vals[i]&0xff);
500 /* set pointers in the ogg_page struct */
501 og->header=os->header;
502 og->header_len=os->header_fill=vals+27;
503 og->body=os->body_data+os->body_returned;
506 /* advance the lacing data and set the body_returned pointer */
508 os->lacing_fill-=vals;
509 memmove(os->lacing_vals,os->lacing_vals+vals,os->lacing_fill*sizeof(*os->lacing_vals));
510 memmove(os->granule_vals,os->granule_vals+vals,os->lacing_fill*sizeof(*os->granule_vals));
511 os->body_returned+=bytes;
513 /* calculate the checksum */
515 ogg_page_checksum_set(og);
521 /* This will flush remaining packets into a page (returning nonzero),
522 even if there is not enough data to trigger a flush normally
523 (undersized page). If there are no packets or partial packets to
524 flush, ogg_stream_flush returns 0. Note that ogg_stream_flush will
525 try to flush a normal sized page like ogg_stream_pageout; a call to
526 ogg_stream_flush does not guarantee that all packets have flushed.
527 Only a return value of 0 from ogg_stream_flush indicates all packet
528 data is flushed into pages.
530 since ogg_stream_flush will flush the last page in a stream even if
531 it's undersized, you almost certainly want to use ogg_stream_pageout
532 (and *not* ogg_stream_flush) unless you specifically need to flush
533 a page regardless of size in the middle of a stream. */
535 int ogg_stream_flush(ogg_stream_state *os,ogg_page *og){
536 return ogg_stream_flush_i(os,og,1,4096);
539 /* Like the above, but an argument is provided to adjust the nominal
540 page size for applications which are smart enough to provide their
541 own delay based flushing */
543 int ogg_stream_flush_fill(ogg_stream_state *os,ogg_page *og, int nfill){
544 return ogg_stream_flush_i(os,og,1,nfill);
547 /* This constructs pages from buffered packet segments. The pointers
548 returned are to static buffers; do not free. The returned buffers are
549 good only until the next call (using the same ogg_stream_state) */
551 int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og){
553 if(ogg_stream_check(os)) return 0;
555 if((os->e_o_s&&os->lacing_fill) || /* 'were done, now flush' case */
556 (os->lacing_fill&&!os->b_o_s)) /* 'initial header page' case */
559 return(ogg_stream_flush_i(os,og,force,4096));
562 /* Like the above, but an argument is provided to adjust the nominal
563 page size for applications which are smart enough to provide their
564 own delay based flushing */
566 int ogg_stream_pageout_fill(ogg_stream_state *os, ogg_page *og, int nfill){
568 if(ogg_stream_check(os)) return 0;
570 if((os->e_o_s&&os->lacing_fill) || /* 'were done, now flush' case */
571 (os->lacing_fill&&!os->b_o_s)) /* 'initial header page' case */
574 return(ogg_stream_flush_i(os,og,force,nfill));
577 int ogg_stream_eos(ogg_stream_state *os){
578 if(ogg_stream_check(os)) return 1;
582 /* DECODING PRIMITIVES: packet streaming layer **********************/
584 /* This has two layers to place more of the multi-serialno and paging
585 control in the application's hands. First, we expose a data buffer
586 using ogg_sync_buffer(). The app either copies into the
587 buffer, or passes it directly to read(), etc. We then call
588 ogg_sync_wrote() to tell how many bytes we just added.
590 Pages are returned (pointers into the buffer in ogg_sync_state)
591 by ogg_sync_pageout(). The page is then submitted to
592 ogg_stream_pagein() along with the appropriate
593 ogg_stream_state* (ie, matching serialno). We then get raw
594 packets out calling ogg_stream_packetout() with a
597 /* initialize the struct to a known state */
598 int ogg_sync_init(ogg_sync_state *oy){
600 oy->storage = -1; /* used as a readiness flag */
601 memset(oy,0,sizeof(*oy));
606 /* clear non-flat storage within */
607 int ogg_sync_clear(ogg_sync_state *oy){
609 if(oy->data)_ogg_free(oy->data);
610 memset(oy,0,sizeof(*oy));
615 int ogg_sync_destroy(ogg_sync_state *oy){
623 int ogg_sync_check(ogg_sync_state *oy){
624 if(oy->storage<0) return -1;
628 char *ogg_sync_buffer(ogg_sync_state *oy, long size){
629 if(ogg_sync_check(oy)) return NULL;
631 /* first, clear out any space that has been previously returned */
633 oy->fill-=oy->returned;
635 memmove(oy->data,oy->data+oy->returned,oy->fill);
639 if(size>oy->storage-oy->fill){
640 /* We need to extend the internal buffer */
641 long newsize=size+oy->fill+4096; /* an extra page to be nice */
645 ret=_ogg_realloc(oy->data,newsize);
647 ret=_ogg_malloc(newsize);
656 /* expose a segment at least as large as requested at the fill mark */
657 return((char *)oy->data+oy->fill);
660 int ogg_sync_wrote(ogg_sync_state *oy, long bytes){
661 if(ogg_sync_check(oy))return -1;
662 if(oy->fill+bytes>oy->storage)return -1;
667 /* sync the stream. This is meant to be useful for finding page
670 return values for this:
672 0) page not ready; more data (no bytes skipped)
673 n) page synced at current location; page length n bytes
677 long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){
678 unsigned char *page=oy->data+oy->returned;
680 long bytes=oy->fill-oy->returned;
682 if(ogg_sync_check(oy))return 0;
684 if(oy->headerbytes==0){
686 if(bytes<27)return(0); /* not enough for a header */
688 /* verify capture pattern */
689 if(memcmp(page,"OggS",4))goto sync_fail;
691 headerbytes=page[26]+27;
692 if(bytes<headerbytes)return(0); /* not enough for header + seg table */
694 /* count up body length in the segment table */
696 for(i=0;i<page[26];i++)
697 oy->bodybytes+=page[27+i];
698 oy->headerbytes=headerbytes;
701 if(oy->bodybytes+oy->headerbytes>bytes)return(0);
703 /* The whole test page is buffered. Verify the checksum */
705 /* Grab the checksum bytes, set the header field to zero */
709 memcpy(chksum,page+22,4);
712 /* set up a temp page struct and recompute the checksum */
714 log.header_len=oy->headerbytes;
715 log.body=page+oy->headerbytes;
716 log.body_len=oy->bodybytes;
717 ogg_page_checksum_set(&log);
720 if(memcmp(chksum,page+22,4)){
721 /* D'oh. Mismatch! Corrupt page (or miscapture and not a page
723 /* replace the computed checksum with the one actually read in */
724 memcpy(page+22,chksum,4);
726 /* Bad checksum. Lose sync */
731 /* yes, have a whole page all ready to go */
733 unsigned char *page=oy->data+oy->returned;
738 og->header_len=oy->headerbytes;
739 og->body=page+oy->headerbytes;
740 og->body_len=oy->bodybytes;
744 oy->returned+=(bytes=oy->headerbytes+oy->bodybytes);
755 /* search for possible capture */
756 next=memchr(page+1,'O',bytes-1);
758 next=oy->data+oy->fill;
760 oy->returned=(int)(next-oy->data);
761 return((long)-(next-page));
764 /* sync the stream and get a page. Keep trying until we find a page.
765 Suppress 'sync errors' after reporting the first.
768 -1) recapture (hole in data)
772 Returns pointers into buffered data; invalidated by next call to
773 _stream, _clear, _init, or _buffer */
775 int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og){
777 if(ogg_sync_check(oy))return 0;
779 /* all we need to do is verify a page at the head of the stream
780 buffer. If it doesn't verify, we look for the next potential
784 long ret=ogg_sync_pageseek(oy,og);
794 /* head did not start a synced page... skipped some bytes */
800 /* loop. keep looking */
805 /* add the incoming page to the stream state; we decompose the page
806 into packet segments here as well. */
808 int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){
809 unsigned char *header=og->header;
810 unsigned char *body=og->body;
811 long bodysize=og->body_len;
814 int version=ogg_page_version(og);
815 int continued=ogg_page_continued(og);
816 int bos=ogg_page_bos(og);
817 int eos=ogg_page_eos(og);
818 ogg_int64_t granulepos=ogg_page_granulepos(og);
819 int serialno=ogg_page_serialno(og);
820 long pageno=ogg_page_pageno(og);
821 int segments=header[26];
823 if(ogg_stream_check(os)) return -1;
825 /* clean up 'returned data' */
827 long lr=os->lacing_returned;
828 long br=os->body_returned;
834 memmove(os->body_data,os->body_data+br,os->body_fill);
840 if(os->lacing_fill-lr){
841 memmove(os->lacing_vals,os->lacing_vals+lr,
842 (os->lacing_fill-lr)*sizeof(*os->lacing_vals));
843 memmove(os->granule_vals,os->granule_vals+lr,
844 (os->lacing_fill-lr)*sizeof(*os->granule_vals));
847 os->lacing_packet-=lr;
848 os->lacing_returned=0;
852 /* check the serial number */
853 if(serialno!=os->serialno)return(-1);
854 if(version>0)return(-1);
856 if(_os_lacing_expand(os,segments+1)) return -1;
858 /* are we in sequence? */
859 if(pageno!=os->pageno){
862 /* unroll previous partial packet (if any) */
863 for(i=os->lacing_packet;i<os->lacing_fill;i++)
864 os->body_fill-=os->lacing_vals[i]&0xff;
865 os->lacing_fill=os->lacing_packet;
867 /* make a note of dropped data in segment table */
869 os->lacing_vals[os->lacing_fill++]=0x400;
874 /* are we a 'continued packet' page? If so, we may need to skip
877 if(os->lacing_fill<1 ||
878 os->lacing_vals[os->lacing_fill-1]==0x400){
880 for(;segptr<segments;segptr++){
881 int val=header[27+segptr];
893 if(_os_body_expand(os,bodysize)) return -1;
894 memcpy(os->body_data+os->body_fill,body,bodysize);
895 os->body_fill+=bodysize;
900 while(segptr<segments){
901 int val=header[27+segptr];
902 os->lacing_vals[os->lacing_fill]=val;
903 os->granule_vals[os->lacing_fill]=-1;
906 os->lacing_vals[os->lacing_fill]|=0x100;
910 if(val<255)saved=os->lacing_fill;
915 if(val<255)os->lacing_packet=os->lacing_fill;
918 /* set the granulepos on the last granuleval of the last full packet */
920 os->granule_vals[saved]=granulepos;
927 if(os->lacing_fill>0)
928 os->lacing_vals[os->lacing_fill-1]|=0x200;
936 /* clear things to an initial state. Good to call, eg, before seeking */
937 int ogg_sync_reset(ogg_sync_state *oy){
938 if(ogg_sync_check(oy))return -1;
948 int ogg_stream_reset(ogg_stream_state *os){
949 if(ogg_stream_check(os)) return -1;
956 os->lacing_returned=0;
969 int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno){
970 if(ogg_stream_check(os)) return -1;
971 ogg_stream_reset(os);
972 os->serialno=serialno;
976 static int _packetout(ogg_stream_state *os,ogg_packet *op,int adv){
978 /* The last part of decode. We have the stream broken into packet
979 segments. Now we need to group them into packets (or return the
980 out of sync markers) */
982 int ptr=os->lacing_returned;
984 if(os->lacing_packet<=ptr)return(0);
986 if(os->lacing_vals[ptr]&0x400){
987 /* we need to tell the codec there's a gap; it might need to
988 handle previous packet dependencies. */
989 os->lacing_returned++;
994 if(!op && !adv)return(1); /* just using peek as an inexpensive way
995 to ask if there's a whole packet
998 /* Gather the whole packet. We'll have no holes or a partial packet */
1000 int size=os->lacing_vals[ptr]&0xff;
1002 int eos=os->lacing_vals[ptr]&0x200; /* last packet of the stream? */
1003 int bos=os->lacing_vals[ptr]&0x100; /* first packet of the stream? */
1006 int val=os->lacing_vals[++ptr];
1008 if(val&0x200)eos=0x200;
1015 op->packet=os->body_data+os->body_returned;
1016 op->packetno=os->packetno;
1017 op->granulepos=os->granule_vals[ptr];
1022 os->body_returned+=bytes;
1023 os->lacing_returned=ptr+1;
1030 int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op){
1031 if(ogg_stream_check(os)) return 0;
1032 return _packetout(os,op,1);
1035 int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op){
1036 if(ogg_stream_check(os)) return 0;
1037 return _packetout(os,op,0);
1040 void ogg_packet_clear(ogg_packet *op) {
1041 _ogg_free(op->packet);
1042 memset(op, 0, sizeof(*op));
1048 ogg_stream_state os_en, os_de;
1051 void checkpacket(ogg_packet *op,long len, int no, long pos){
1053 static int sequence=0;
1054 static int lastno=0;
1057 fprintf(stderr,"incorrect packet length (%ld != %ld)!\n",op->bytes,len);
1060 if(op->granulepos!=pos){
1061 fprintf(stderr,"incorrect packet granpos (%ld != %ld)!\n",(long)op->granulepos,pos);
1065 /* packet number just follows sequence/gap; adjust the input number
1075 if(op->packetno!=sequence){
1076 fprintf(stderr,"incorrect packet sequence %ld != %d\n",
1077 (long)(op->packetno),sequence);
1082 for(j=0;j<op->bytes;j++)
1083 if(op->packet[j]!=((j+no)&0xff)){
1084 fprintf(stderr,"body data mismatch (1) at pos %ld: %x!=%lx!\n\n",
1085 j,op->packet[j],(j+no)&0xff);
1090 void check_page(unsigned char *data,const int *header,ogg_page *og){
1093 for(j=0;j<og->body_len;j++)
1094 if(og->body[j]!=data[j]){
1095 fprintf(stderr,"body data mismatch (2) at pos %ld: %x!=%x!\n\n",
1096 j,data[j],og->body[j]);
1101 for(j=0;j<og->header_len;j++){
1102 if(og->header[j]!=header[j]){
1103 fprintf(stderr,"header content mismatch at pos %ld:\n",j);
1104 for(j=0;j<header[26]+27;j++)
1105 fprintf(stderr," (%ld)%02x:%02x",j,header[j],og->header[j]);
1106 fprintf(stderr,"\n");
1110 if(og->header_len!=header[26]+27){
1111 fprintf(stderr,"header length incorrect! (%ld!=%d)\n",
1112 og->header_len,header[26]+27);
1117 void print_header(ogg_page *og){
1119 fprintf(stderr,"\nHEADER:\n");
1120 fprintf(stderr," capture: %c %c %c %c version: %d flags: %x\n",
1121 og->header[0],og->header[1],og->header[2],og->header[3],
1122 (int)og->header[4],(int)og->header[5]);
1124 fprintf(stderr," granulepos: %d serialno: %d pageno: %ld\n",
1125 (og->header[9]<<24)|(og->header[8]<<16)|
1126 (og->header[7]<<8)|og->header[6],
1127 (og->header[17]<<24)|(og->header[16]<<16)|
1128 (og->header[15]<<8)|og->header[14],
1129 ((long)(og->header[21])<<24)|(og->header[20]<<16)|
1130 (og->header[19]<<8)|og->header[18]);
1132 fprintf(stderr," checksum: %02x:%02x:%02x:%02x\n segments: %d (",
1133 (int)og->header[22],(int)og->header[23],
1134 (int)og->header[24],(int)og->header[25],
1135 (int)og->header[26]);
1137 for(j=27;j<og->header_len;j++)
1138 fprintf(stderr,"%d ",(int)og->header[j]);
1139 fprintf(stderr,")\n\n");
1142 void copy_page(ogg_page *og){
1143 unsigned char *temp=_ogg_malloc(og->header_len);
1144 memcpy(temp,og->header,og->header_len);
1147 temp=_ogg_malloc(og->body_len);
1148 memcpy(temp,og->body,og->body_len);
1152 void free_page(ogg_page *og){
1153 _ogg_free (og->header);
1154 _ogg_free (og->body);
1158 fprintf(stderr,"error!\n");
1163 const int head1_0[] = {0x4f,0x67,0x67,0x53,0,0x06,
1164 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1165 0x01,0x02,0x03,0x04,0,0,0,0,
1166 0x15,0xed,0xec,0x91,
1170 /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
1171 const int head1_1[] = {0x4f,0x67,0x67,0x53,0,0x02,
1172 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1173 0x01,0x02,0x03,0x04,0,0,0,0,
1174 0x59,0x10,0x6c,0x2c,
1177 const int head2_1[] = {0x4f,0x67,0x67,0x53,0,0x04,
1178 0x07,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
1179 0x01,0x02,0x03,0x04,1,0,0,0,
1180 0x89,0x33,0x85,0xce,
1182 254,255,0,255,1,255,245,255,255,0,
1185 /* nil packets; beginning,middle,end */
1186 const int head1_2[] = {0x4f,0x67,0x67,0x53,0,0x02,
1187 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1188 0x01,0x02,0x03,0x04,0,0,0,0,
1189 0xff,0x7b,0x23,0x17,
1192 const int head2_2[] = {0x4f,0x67,0x67,0x53,0,0x04,
1193 0x07,0x28,0x00,0x00,0x00,0x00,0x00,0x00,
1194 0x01,0x02,0x03,0x04,1,0,0,0,
1195 0x5c,0x3f,0x66,0xcb,
1197 17,254,255,0,0,255,1,0,255,245,255,255,0,
1200 /* large initial packet */
1201 const int head1_3[] = {0x4f,0x67,0x67,0x53,0,0x02,
1202 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1203 0x01,0x02,0x03,0x04,0,0,0,0,
1204 0x01,0x27,0x31,0xaa,
1206 255,255,255,255,255,255,255,255,
1207 255,255,255,255,255,255,255,255,255,10};
1209 const int head2_3[] = {0x4f,0x67,0x67,0x53,0,0x04,
1210 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
1211 0x01,0x02,0x03,0x04,1,0,0,0,
1212 0x7f,0x4e,0x8a,0xd2,
1217 /* continuing packet test */
1218 const int head1_4[] = {0x4f,0x67,0x67,0x53,0,0x02,
1219 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1220 0x01,0x02,0x03,0x04,0,0,0,0,
1221 0xff,0x7b,0x23,0x17,
1225 const int head2_4[] = {0x4f,0x67,0x67,0x53,0,0x00,
1226 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
1227 0x01,0x02,0x03,0x04,1,0,0,0,
1228 0xf8,0x3c,0x19,0x79,
1230 255,255,255,255,255,255,255,255,
1231 255,255,255,255,255,255,255,255,
1232 255,255,255,255,255,255,255,255,
1233 255,255,255,255,255,255,255,255,
1234 255,255,255,255,255,255,255,255,
1235 255,255,255,255,255,255,255,255,
1236 255,255,255,255,255,255,255,255,
1237 255,255,255,255,255,255,255,255,
1238 255,255,255,255,255,255,255,255,
1239 255,255,255,255,255,255,255,255,
1240 255,255,255,255,255,255,255,255,
1241 255,255,255,255,255,255,255,255,
1242 255,255,255,255,255,255,255,255,
1243 255,255,255,255,255,255,255,255,
1244 255,255,255,255,255,255,255,255,
1245 255,255,255,255,255,255,255,255,
1246 255,255,255,255,255,255,255,255,
1247 255,255,255,255,255,255,255,255,
1248 255,255,255,255,255,255,255,255,
1249 255,255,255,255,255,255,255,255,
1250 255,255,255,255,255,255,255,255,
1251 255,255,255,255,255,255,255,255,
1252 255,255,255,255,255,255,255,255,
1253 255,255,255,255,255,255,255,255,
1254 255,255,255,255,255,255,255,255,
1255 255,255,255,255,255,255,255,255,
1256 255,255,255,255,255,255,255,255,
1257 255,255,255,255,255,255,255,255,
1258 255,255,255,255,255,255,255,255,
1259 255,255,255,255,255,255,255,255,
1260 255,255,255,255,255,255,255,255,
1261 255,255,255,255,255,255,255};
1263 const int head3_4[] = {0x4f,0x67,0x67,0x53,0,0x05,
1264 0x07,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,
1265 0x01,0x02,0x03,0x04,2,0,0,0,
1266 0x38,0xe6,0xb6,0x28,
1268 255,220,255,4,255,0};
1271 /* spill expansion test */
1272 const int head1_4b[] = {0x4f,0x67,0x67,0x53,0,0x02,
1273 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1274 0x01,0x02,0x03,0x04,0,0,0,0,
1275 0xff,0x7b,0x23,0x17,
1279 const int head2_4b[] = {0x4f,0x67,0x67,0x53,0,0x00,
1280 0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
1281 0x01,0x02,0x03,0x04,1,0,0,0,
1282 0xce,0x8f,0x17,0x1a,
1284 255,255,255,255,255,255,255,255,
1285 255,255,255,255,255,255,255,255,255,10,255,4,255,0,0};
1288 const int head3_4b[] = {0x4f,0x67,0x67,0x53,0,0x04,
1289 0x07,0x14,0x00,0x00,0x00,0x00,0x00,0x00,
1290 0x01,0x02,0x03,0x04,2,0,0,0,
1291 0x9b,0xb2,0x50,0xa1,
1295 /* page with the 255 segment limit */
1296 const int head1_5[] = {0x4f,0x67,0x67,0x53,0,0x02,
1297 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1298 0x01,0x02,0x03,0x04,0,0,0,0,
1299 0xff,0x7b,0x23,0x17,
1303 const int head2_5[] = {0x4f,0x67,0x67,0x53,0,0x00,
1304 0x07,0xfc,0x03,0x00,0x00,0x00,0x00,0x00,
1305 0x01,0x02,0x03,0x04,1,0,0,0,
1306 0xed,0x2a,0x2e,0xa7,
1308 10,10,10,10,10,10,10,10,
1309 10,10,10,10,10,10,10,10,
1310 10,10,10,10,10,10,10,10,
1311 10,10,10,10,10,10,10,10,
1312 10,10,10,10,10,10,10,10,
1313 10,10,10,10,10,10,10,10,
1314 10,10,10,10,10,10,10,10,
1315 10,10,10,10,10,10,10,10,
1316 10,10,10,10,10,10,10,10,
1317 10,10,10,10,10,10,10,10,
1318 10,10,10,10,10,10,10,10,
1319 10,10,10,10,10,10,10,10,
1320 10,10,10,10,10,10,10,10,
1321 10,10,10,10,10,10,10,10,
1322 10,10,10,10,10,10,10,10,
1323 10,10,10,10,10,10,10,10,
1324 10,10,10,10,10,10,10,10,
1325 10,10,10,10,10,10,10,10,
1326 10,10,10,10,10,10,10,10,
1327 10,10,10,10,10,10,10,10,
1328 10,10,10,10,10,10,10,10,
1329 10,10,10,10,10,10,10,10,
1330 10,10,10,10,10,10,10,10,
1331 10,10,10,10,10,10,10,10,
1332 10,10,10,10,10,10,10,10,
1333 10,10,10,10,10,10,10,10,
1334 10,10,10,10,10,10,10,10,
1335 10,10,10,10,10,10,10,10,
1336 10,10,10,10,10,10,10,10,
1337 10,10,10,10,10,10,10,10,
1338 10,10,10,10,10,10,10,10,
1339 10,10,10,10,10,10,10};
1341 const int head3_5[] = {0x4f,0x67,0x67,0x53,0,0x04,
1342 0x07,0x00,0x04,0x00,0x00,0x00,0x00,0x00,
1343 0x01,0x02,0x03,0x04,2,0,0,0,
1344 0x6c,0x3b,0x82,0x3d,
1349 /* packet that overspans over an entire page */
1350 const int head1_6[] = {0x4f,0x67,0x67,0x53,0,0x02,
1351 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1352 0x01,0x02,0x03,0x04,0,0,0,0,
1353 0xff,0x7b,0x23,0x17,
1357 const int head2_6[] = {0x4f,0x67,0x67,0x53,0,0x00,
1358 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
1359 0x01,0x02,0x03,0x04,1,0,0,0,
1360 0x68,0x22,0x7c,0x3d,
1363 255,255,255,255,255,255,255,255,
1364 255,255,255,255,255,255,255,255,
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};
1396 const int head3_6[] = {0x4f,0x67,0x67,0x53,0,0x01,
1397 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
1398 0x01,0x02,0x03,0x04,2,0,0,0,
1399 0xf4,0x87,0xba,0xf3,
1401 255,255,255,255,255,255,255,255,
1402 255,255,255,255,255,255,255,255,
1403 255,255,255,255,255,255,255,255,
1404 255,255,255,255,255,255,255,255,
1405 255,255,255,255,255,255,255,255,
1406 255,255,255,255,255,255,255,255,
1407 255,255,255,255,255,255,255,255,
1408 255,255,255,255,255,255,255,255,
1409 255,255,255,255,255,255,255,255,
1410 255,255,255,255,255,255,255,255,
1411 255,255,255,255,255,255,255,255,
1412 255,255,255,255,255,255,255,255,
1413 255,255,255,255,255,255,255,255,
1414 255,255,255,255,255,255,255,255,
1415 255,255,255,255,255,255,255,255,
1416 255,255,255,255,255,255,255,255,
1417 255,255,255,255,255,255,255,255,
1418 255,255,255,255,255,255,255,255,
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};
1434 const int head4_6[] = {0x4f,0x67,0x67,0x53,0,0x05,
1435 0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
1436 0x01,0x02,0x03,0x04,3,0,0,0,
1437 0xf7,0x2f,0x6c,0x60,
1441 /* packet that overspans over an entire page */
1442 const int head1_7[] = {0x4f,0x67,0x67,0x53,0,0x02,
1443 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1444 0x01,0x02,0x03,0x04,0,0,0,0,
1445 0xff,0x7b,0x23,0x17,
1449 const int head2_7[] = {0x4f,0x67,0x67,0x53,0,0x00,
1450 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
1451 0x01,0x02,0x03,0x04,1,0,0,0,
1452 0x68,0x22,0x7c,0x3d,
1455 255,255,255,255,255,255,255,255,
1456 255,255,255,255,255,255,255,255,
1457 255,255,255,255,255,255,255,255,
1458 255,255,255,255,255,255,255,255,
1459 255,255,255,255,255,255,255,255,
1460 255,255,255,255,255,255,255,255,
1461 255,255,255,255,255,255,255,255,
1462 255,255,255,255,255,255,255,255,
1463 255,255,255,255,255,255,255,255,
1464 255,255,255,255,255,255,255,255,
1465 255,255,255,255,255,255,255,255,
1466 255,255,255,255,255,255,255,255,
1467 255,255,255,255,255,255,255,255,
1468 255,255,255,255,255,255,255,255,
1469 255,255,255,255,255,255,255,255,
1470 255,255,255,255,255,255,255,255,
1471 255,255,255,255,255,255,255,255,
1472 255,255,255,255,255,255,255,255,
1473 255,255,255,255,255,255,255,255,
1474 255,255,255,255,255,255,255,255,
1475 255,255,255,255,255,255,255,255,
1476 255,255,255,255,255,255,255,255,
1477 255,255,255,255,255,255,255,255,
1478 255,255,255,255,255,255,255,255,
1479 255,255,255,255,255,255,255,255,
1480 255,255,255,255,255,255,255,255,
1481 255,255,255,255,255,255,255,255,
1482 255,255,255,255,255,255,255,255,
1483 255,255,255,255,255,255,255,255,
1484 255,255,255,255,255,255,255,255,
1485 255,255,255,255,255,255,255,255,
1486 255,255,255,255,255,255};
1488 const int head3_7[] = {0x4f,0x67,0x67,0x53,0,0x05,
1489 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
1490 0x01,0x02,0x03,0x04,2,0,0,0,
1491 0xd4,0xe0,0x60,0xe5,
1495 void test_pack(const int *pl, const int **headers, int byteskip,
1496 int pageskip, int packetskip){
1497 unsigned char *data=_ogg_malloc(1024*1024); /* for scripted test cases only */
1502 long granule_pos=7,pageno=0;
1503 int i,j,packets,pageout=pageskip;
1507 int byteskipcount=0;
1509 ogg_stream_reset(&os_en);
1510 ogg_stream_reset(&os_de);
1511 ogg_sync_reset(&oy);
1513 for(packets=0;packets<packetskip;packets++)
1514 depacket+=pl[packets];
1516 for(packets=0;;packets++)if(pl[packets]==-1)break;
1518 for(i=0;i<packets;i++){
1519 /* construct a test packet */
1523 op.packet=data+inptr;
1525 op.e_o_s=(pl[i+1]<0?1:0);
1526 op.granulepos=granule_pos;
1530 for(j=0;j<len;j++)data[inptr++]=i+j;
1532 /* submit the test packet */
1533 ogg_stream_packetin(&os_en,&op);
1535 /* retrieve any finished pages */
1539 while(ogg_stream_pageout(&os_en,&og)){
1540 /* We have a page. Check it carefully */
1542 fprintf(stderr,"%ld, ",pageno);
1544 if(headers[pageno]==NULL){
1545 fprintf(stderr,"coded too many pages!\n");
1549 check_page(data+outptr,headers[pageno],&og);
1551 outptr+=og.body_len;
1559 /* have a complete page; submit it to sync/decode */
1563 ogg_packet op_de,op_de2;
1564 char *buf=ogg_sync_buffer(&oy,og.header_len+og.body_len);
1566 byteskipcount+=og.header_len;
1567 if(byteskipcount>byteskip){
1568 memcpy(next,og.header,byteskipcount-byteskip);
1569 next+=byteskipcount-byteskip;
1570 byteskipcount=byteskip;
1573 byteskipcount+=og.body_len;
1574 if(byteskipcount>byteskip){
1575 memcpy(next,og.body,byteskipcount-byteskip);
1576 next+=byteskipcount-byteskip;
1577 byteskipcount=byteskip;
1580 ogg_sync_wrote(&oy,next-buf);
1583 int ret=ogg_sync_pageout(&oy,&og_de);
1586 /* got a page. Happy happy. Verify that it's good. */
1588 fprintf(stderr,"(%d), ",pageout);
1590 check_page(data+deptr,headers[pageout],&og_de);
1591 deptr+=og_de.body_len;
1594 /* submit it to deconstitution */
1595 ogg_stream_pagein(&os_de,&og_de);
1598 while(ogg_stream_packetpeek(&os_de,&op_de2)>0){
1599 ogg_stream_packetpeek(&os_de,NULL);
1600 ogg_stream_packetout(&os_de,&op_de); /* just catching them all */
1602 /* verify peek and out match */
1603 if(memcmp(&op_de,&op_de2,sizeof(op_de))){
1604 fprintf(stderr,"packetout != packetpeek! pos=%ld\n",
1609 /* verify the packet! */
1611 if(memcmp(data+depacket,op_de.packet,op_de.bytes)){
1612 fprintf(stderr,"packet data mismatch in decode! pos=%ld\n",
1616 /* check bos flag */
1617 if(bosflag==0 && op_de.b_o_s==0){
1618 fprintf(stderr,"b_o_s flag not set on packet!\n");
1621 if(bosflag && op_de.b_o_s){
1622 fprintf(stderr,"b_o_s flag incorrectly set on packet!\n");
1626 depacket+=op_de.bytes;
1628 /* check eos flag */
1630 fprintf(stderr,"Multiple decoded packets with eos flag!\n");
1634 if(op_de.e_o_s)eosflag=1;
1636 /* check granulepos flag */
1637 if(op_de.granulepos!=-1){
1638 fprintf(stderr," granule:%ld ",(long)op_de.granulepos);
1647 if(headers[pageno]!=NULL){
1648 fprintf(stderr,"did not write last page!\n");
1651 if(headers[pageout]!=NULL){
1652 fprintf(stderr,"did not decode last page!\n");
1656 fprintf(stderr,"encoded page data incomplete!\n");
1660 fprintf(stderr,"decoded page data incomplete!\n");
1663 if(inptr!=depacket){
1664 fprintf(stderr,"decoded packet data incomplete!\n");
1668 fprintf(stderr,"Never got a packet with EOS set!\n");
1671 fprintf(stderr,"ok.\n");
1676 ogg_stream_init(&os_en,0x04030201);
1677 ogg_stream_init(&os_de,0x04030201);
1680 /* Exercise each code path in the framing code. Also verify that
1681 the checksums are working. */
1685 const int packets[]={17, -1};
1686 const int *headret[]={head1_0,NULL};
1688 fprintf(stderr,"testing single page encoding... ");
1689 test_pack(packets,headret,0,0,0);
1693 /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
1694 const int packets[]={17, 254, 255, 256, 500, 510, 600, -1};
1695 const int *headret[]={head1_1,head2_1,NULL};
1697 fprintf(stderr,"testing basic page encoding... ");
1698 test_pack(packets,headret,0,0,0);
1702 /* nil packets; beginning,middle,end */
1703 const int packets[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1};
1704 const int *headret[]={head1_2,head2_2,NULL};
1706 fprintf(stderr,"testing basic nil packets... ");
1707 test_pack(packets,headret,0,0,0);
1711 /* large initial packet */
1712 const int packets[]={4345,259,255,-1};
1713 const int *headret[]={head1_3,head2_3,NULL};
1715 fprintf(stderr,"testing initial-packet lacing > 4k... ");
1716 test_pack(packets,headret,0,0,0);
1720 /* continuing packet test; with page spill expansion, we have to
1721 overflow the lacing table. */
1722 const int packets[]={0,65500,259,255,-1};
1723 const int *headret[]={head1_4,head2_4,head3_4,NULL};
1725 fprintf(stderr,"testing single packet page span... ");
1726 test_pack(packets,headret,0,0,0);
1730 /* spill expand packet test */
1731 const int packets[]={0,4345,259,255,0,0,-1};
1732 const int *headret[]={head1_4b,head2_4b,head3_4b,NULL};
1734 fprintf(stderr,"testing page spill expansion... ");
1735 test_pack(packets,headret,0,0,0);
1738 /* page with the 255 segment limit */
1741 const int packets[]={0,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,10,
1765 10,10,10,10,10,10,10,10,
1766 10,10,10,10,10,10,10,10,
1767 10,10,10,10,10,10,10,10,
1768 10,10,10,10,10,10,10,10,
1769 10,10,10,10,10,10,10,10,
1770 10,10,10,10,10,10,10,10,
1771 10,10,10,10,10,10,10,10,
1772 10,10,10,10,10,10,10,50,-1};
1773 const int *headret[]={head1_5,head2_5,head3_5,NULL};
1775 fprintf(stderr,"testing max packet segments... ");
1776 test_pack(packets,headret,0,0,0);
1780 /* packet that overspans over an entire page */
1781 const int packets[]={0,100,130049,259,255,-1};
1782 const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
1784 fprintf(stderr,"testing very large packets... ");
1785 test_pack(packets,headret,0,0,0);
1789 /* test for the libogg 1.1.1 resync in large continuation bug
1790 found by Josh Coalson) */
1791 const int packets[]={0,100,130049,259,255,-1};
1792 const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
1794 fprintf(stderr,"testing continuation resync in very large packets... ");
1795 test_pack(packets,headret,100,2,3);
1799 /* term only page. why not? */
1800 const int packets[]={0,100,64770,-1};
1801 const int *headret[]={head1_7,head2_7,head3_7,NULL};
1803 fprintf(stderr,"testing zero data page (1 nil packet)... ");
1804 test_pack(packets,headret,0,0,0);
1810 /* build a bunch of pages for testing */
1811 unsigned char *data=_ogg_malloc(1024*1024);
1812 int pl[]={0, 1,1,98,4079, 1,1,2954,2057, 76,34,912,0,234,1000,1000, 1000,300,-1};
1816 ogg_stream_reset(&os_en);
1818 for(i=0;pl[i]!=-1;i++){
1822 op.packet=data+inptr;
1824 op.e_o_s=(pl[i+1]<0?1:0);
1825 op.granulepos=(i+1)*1000;
1827 for(j=0;j<len;j++)data[inptr++]=i+j;
1828 ogg_stream_packetin(&os_en,&op);
1833 /* retrieve finished pages */
1835 if(ogg_stream_pageout(&os_en,&og[i])==0){
1836 fprintf(stderr,"Too few pages output building sync tests!\n");
1842 /* Test lost pages on pagein/packetout: no rollback */
1847 fprintf(stderr,"Testing loss of pages... ");
1849 ogg_sync_reset(&oy);
1850 ogg_stream_reset(&os_de);
1852 memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
1854 ogg_sync_wrote(&oy,og[i].header_len);
1855 memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
1856 ogg_sync_wrote(&oy,og[i].body_len);
1859 ogg_sync_pageout(&oy,&temp);
1860 ogg_stream_pagein(&os_de,&temp);
1861 ogg_sync_pageout(&oy,&temp);
1862 ogg_stream_pagein(&os_de,&temp);
1863 ogg_sync_pageout(&oy,&temp);
1865 ogg_sync_pageout(&oy,&temp);
1866 ogg_stream_pagein(&os_de,&temp);
1868 /* do we get the expected results/packets? */
1870 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1871 checkpacket(&test,0,0,0);
1872 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1873 checkpacket(&test,1,1,-1);
1874 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1875 checkpacket(&test,1,2,-1);
1876 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1877 checkpacket(&test,98,3,-1);
1878 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1879 checkpacket(&test,4079,4,5000);
1880 if(ogg_stream_packetout(&os_de,&test)!=-1){
1881 fprintf(stderr,"Error: loss of page did not return error\n");
1884 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1885 checkpacket(&test,76,9,-1);
1886 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1887 checkpacket(&test,34,10,-1);
1888 fprintf(stderr,"ok.\n");
1891 /* Test lost pages on pagein/packetout: rollback with continuation */
1896 fprintf(stderr,"Testing loss of pages (rollback required)... ");
1898 ogg_sync_reset(&oy);
1899 ogg_stream_reset(&os_de);
1901 memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
1903 ogg_sync_wrote(&oy,og[i].header_len);
1904 memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
1905 ogg_sync_wrote(&oy,og[i].body_len);
1908 ogg_sync_pageout(&oy,&temp);
1909 ogg_stream_pagein(&os_de,&temp);
1910 ogg_sync_pageout(&oy,&temp);
1911 ogg_stream_pagein(&os_de,&temp);
1912 ogg_sync_pageout(&oy,&temp);
1913 ogg_stream_pagein(&os_de,&temp);
1914 ogg_sync_pageout(&oy,&temp);
1916 ogg_sync_pageout(&oy,&temp);
1917 ogg_stream_pagein(&os_de,&temp);
1919 /* do we get the expected results/packets? */
1921 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1922 checkpacket(&test,0,0,0);
1923 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1924 checkpacket(&test,1,1,-1);
1925 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1926 checkpacket(&test,1,2,-1);
1927 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1928 checkpacket(&test,98,3,-1);
1929 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1930 checkpacket(&test,4079,4,5000);
1931 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1932 checkpacket(&test,1,5,-1);
1933 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1934 checkpacket(&test,1,6,-1);
1935 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1936 checkpacket(&test,2954,7,-1);
1937 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1938 checkpacket(&test,2057,8,9000);
1939 if(ogg_stream_packetout(&os_de,&test)!=-1){
1940 fprintf(stderr,"Error: loss of page did not return error\n");
1943 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1944 checkpacket(&test,300,17,18000);
1945 fprintf(stderr,"ok.\n");
1948 /* the rest only test sync */
1951 /* Test fractional page inputs: incomplete capture */
1952 fprintf(stderr,"Testing sync on partial inputs... ");
1953 ogg_sync_reset(&oy);
1954 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
1956 ogg_sync_wrote(&oy,3);
1957 if(ogg_sync_pageout(&oy,&og_de)>0)error();
1959 /* Test fractional page inputs: incomplete fixed header */
1960 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+3,
1962 ogg_sync_wrote(&oy,20);
1963 if(ogg_sync_pageout(&oy,&og_de)>0)error();
1965 /* Test fractional page inputs: incomplete header */
1966 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+23,
1968 ogg_sync_wrote(&oy,5);
1969 if(ogg_sync_pageout(&oy,&og_de)>0)error();
1971 /* Test fractional page inputs: incomplete body */
1973 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+28,
1974 og[1].header_len-28);
1975 ogg_sync_wrote(&oy,og[1].header_len-28);
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 ogg_sync_wrote(&oy,1000);
1980 if(ogg_sync_pageout(&oy,&og_de)>0)error();
1982 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body+1000,
1983 og[1].body_len-1000);
1984 ogg_sync_wrote(&oy,og[1].body_len-1000);
1985 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
1987 fprintf(stderr,"ok.\n");
1990 /* Test fractional page inputs: page + incomplete capture */
1993 fprintf(stderr,"Testing sync on 1+partial inputs... ");
1994 ogg_sync_reset(&oy);
1996 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
1998 ogg_sync_wrote(&oy,og[1].header_len);
2000 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2002 ogg_sync_wrote(&oy,og[1].body_len);
2004 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
2006 ogg_sync_wrote(&oy,20);
2007 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2008 if(ogg_sync_pageout(&oy,&og_de)>0)error();
2010 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+20,
2011 og[1].header_len-20);
2012 ogg_sync_wrote(&oy,og[1].header_len-20);
2013 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2015 ogg_sync_wrote(&oy,og[1].body_len);
2016 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2018 fprintf(stderr,"ok.\n");
2021 /* Test recapture: garbage + page */
2024 fprintf(stderr,"Testing search for capture... ");
2025 ogg_sync_reset(&oy);
2028 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2030 ogg_sync_wrote(&oy,og[1].body_len);
2032 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
2034 ogg_sync_wrote(&oy,og[1].header_len);
2036 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2038 ogg_sync_wrote(&oy,og[1].body_len);
2040 memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
2042 ogg_sync_wrote(&oy,20);
2043 if(ogg_sync_pageout(&oy,&og_de)>0)error();
2044 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2045 if(ogg_sync_pageout(&oy,&og_de)>0)error();
2047 memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header+20,
2048 og[2].header_len-20);
2049 ogg_sync_wrote(&oy,og[2].header_len-20);
2050 memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
2052 ogg_sync_wrote(&oy,og[2].body_len);
2053 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2055 fprintf(stderr,"ok.\n");
2058 /* Test recapture: page + garbage + page */
2061 fprintf(stderr,"Testing recapture... ");
2062 ogg_sync_reset(&oy);
2064 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
2066 ogg_sync_wrote(&oy,og[1].header_len);
2068 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2070 ogg_sync_wrote(&oy,og[1].body_len);
2072 memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
2074 ogg_sync_wrote(&oy,og[2].header_len);
2076 memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
2078 ogg_sync_wrote(&oy,og[2].header_len);
2080 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2082 memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
2084 ogg_sync_wrote(&oy,og[2].body_len-5);
2086 memcpy(ogg_sync_buffer(&oy,og[3].header_len),og[3].header,
2088 ogg_sync_wrote(&oy,og[3].header_len);
2090 memcpy(ogg_sync_buffer(&oy,og[3].body_len),og[3].body,
2092 ogg_sync_wrote(&oy,og[3].body_len);
2094 if(ogg_sync_pageout(&oy,&og_de)>0)error();
2095 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2097 fprintf(stderr,"ok.\n");
2100 /* Free page data that was previously copied */