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 17039 2010-03-26 00:34:54Z xiphmont $
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 ********************************************************************/
27 /* A complete description of Ogg framing exists in docs/framing.html */
29 int ogg_page_version(const ogg_page *og){
30 return((int)(og->header[4]));
33 int ogg_page_continued(const ogg_page *og){
34 return((int)(og->header[5]&0x01));
37 int ogg_page_bos(const ogg_page *og){
38 return((int)(og->header[5]&0x02));
41 int ogg_page_eos(const ogg_page *og){
42 return((int)(og->header[5]&0x04));
45 ogg_int64_t ogg_page_granulepos(const ogg_page *og){
46 unsigned char *page=og->header;
47 ogg_int64_t granulepos=page[13]&(0xff);
48 granulepos= (granulepos<<8)|(page[12]&0xff);
49 granulepos= (granulepos<<8)|(page[11]&0xff);
50 granulepos= (granulepos<<8)|(page[10]&0xff);
51 granulepos= (granulepos<<8)|(page[9]&0xff);
52 granulepos= (granulepos<<8)|(page[8]&0xff);
53 granulepos= (granulepos<<8)|(page[7]&0xff);
54 granulepos= (granulepos<<8)|(page[6]&0xff);
58 int ogg_page_serialno(const ogg_page *og){
59 return(og->header[14] |
61 (og->header[16]<<16) |
62 (og->header[17]<<24));
65 long ogg_page_pageno(const ogg_page *og){
66 return(og->header[18] |
68 (og->header[20]<<16) |
69 (og->header[21]<<24));
74 /* returns the number of packets that are completed on this page (if
75 the leading packet is begun on a previous page, but ends on this
79 If a page consists of a packet begun on a previous page, and a new
80 packet begun (but not completed) on this page, the return will be:
81 ogg_page_packets(page) ==1,
82 ogg_page_continued(page) !=0
84 If a page happens to be a single packet that was begun on a
85 previous page, and spans to the next page (in the case of a three or
86 more page packet), the return will be:
87 ogg_page_packets(page) ==0,
88 ogg_page_continued(page) !=0
91 int ogg_page_packets(const ogg_page *og){
92 int i,n=og->header[26],count=0;
94 if(og->header[27+i]<255)count++;
100 /* helper to initialize lookup for direct-table CRC (illustrative; we
101 use the static init below) */
103 static ogg_uint32_t _ogg_crc_entry(unsigned long index){
109 if (r & 0x80000000UL)
110 r = (r << 1) ^ 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 */
116 return (r & 0xffffffffUL);
120 static const ogg_uint32_t crc_lookup[256]={
121 0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9,
122 0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005,
123 0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61,
124 0x350c9b64,0x31cd86d3,0x3c8ea00a,0x384fbdbd,
125 0x4c11db70,0x48d0c6c7,0x4593e01e,0x4152fda9,
126 0x5f15adac,0x5bd4b01b,0x569796c2,0x52568b75,
127 0x6a1936c8,0x6ed82b7f,0x639b0da6,0x675a1011,
128 0x791d4014,0x7ddc5da3,0x709f7b7a,0x745e66cd,
129 0x9823b6e0,0x9ce2ab57,0x91a18d8e,0x95609039,
130 0x8b27c03c,0x8fe6dd8b,0x82a5fb52,0x8664e6e5,
131 0xbe2b5b58,0xbaea46ef,0xb7a96036,0xb3687d81,
132 0xad2f2d84,0xa9ee3033,0xa4ad16ea,0xa06c0b5d,
133 0xd4326d90,0xd0f37027,0xddb056fe,0xd9714b49,
134 0xc7361b4c,0xc3f706fb,0xceb42022,0xca753d95,
135 0xf23a8028,0xf6fb9d9f,0xfbb8bb46,0xff79a6f1,
136 0xe13ef6f4,0xe5ffeb43,0xe8bccd9a,0xec7dd02d,
137 0x34867077,0x30476dc0,0x3d044b19,0x39c556ae,
138 0x278206ab,0x23431b1c,0x2e003dc5,0x2ac12072,
139 0x128e9dcf,0x164f8078,0x1b0ca6a1,0x1fcdbb16,
140 0x018aeb13,0x054bf6a4,0x0808d07d,0x0cc9cdca,
141 0x7897ab07,0x7c56b6b0,0x71159069,0x75d48dde,
142 0x6b93dddb,0x6f52c06c,0x6211e6b5,0x66d0fb02,
143 0x5e9f46bf,0x5a5e5b08,0x571d7dd1,0x53dc6066,
144 0x4d9b3063,0x495a2dd4,0x44190b0d,0x40d816ba,
145 0xaca5c697,0xa864db20,0xa527fdf9,0xa1e6e04e,
146 0xbfa1b04b,0xbb60adfc,0xb6238b25,0xb2e29692,
147 0x8aad2b2f,0x8e6c3698,0x832f1041,0x87ee0df6,
148 0x99a95df3,0x9d684044,0x902b669d,0x94ea7b2a,
149 0xe0b41de7,0xe4750050,0xe9362689,0xedf73b3e,
150 0xf3b06b3b,0xf771768c,0xfa325055,0xfef34de2,
151 0xc6bcf05f,0xc27dede8,0xcf3ecb31,0xcbffd686,
152 0xd5b88683,0xd1799b34,0xdc3abded,0xd8fba05a,
153 0x690ce0ee,0x6dcdfd59,0x608edb80,0x644fc637,
154 0x7a089632,0x7ec98b85,0x738aad5c,0x774bb0eb,
155 0x4f040d56,0x4bc510e1,0x46863638,0x42472b8f,
156 0x5c007b8a,0x58c1663d,0x558240e4,0x51435d53,
157 0x251d3b9e,0x21dc2629,0x2c9f00f0,0x285e1d47,
158 0x36194d42,0x32d850f5,0x3f9b762c,0x3b5a6b9b,
159 0x0315d626,0x07d4cb91,0x0a97ed48,0x0e56f0ff,
160 0x1011a0fa,0x14d0bd4d,0x19939b94,0x1d528623,
161 0xf12f560e,0xf5ee4bb9,0xf8ad6d60,0xfc6c70d7,
162 0xe22b20d2,0xe6ea3d65,0xeba91bbc,0xef68060b,
163 0xd727bbb6,0xd3e6a601,0xdea580d8,0xda649d6f,
164 0xc423cd6a,0xc0e2d0dd,0xcda1f604,0xc960ebb3,
165 0xbd3e8d7e,0xb9ff90c9,0xb4bcb610,0xb07daba7,
166 0xae3afba2,0xaafbe615,0xa7b8c0cc,0xa379dd7b,
167 0x9b3660c6,0x9ff77d71,0x92b45ba8,0x9675461f,
168 0x8832161a,0x8cf30bad,0x81b02d74,0x857130c3,
169 0x5d8a9099,0x594b8d2e,0x5408abf7,0x50c9b640,
170 0x4e8ee645,0x4a4ffbf2,0x470cdd2b,0x43cdc09c,
171 0x7b827d21,0x7f436096,0x7200464f,0x76c15bf8,
172 0x68860bfd,0x6c47164a,0x61043093,0x65c52d24,
173 0x119b4be9,0x155a565e,0x18197087,0x1cd86d30,
174 0x029f3d35,0x065e2082,0x0b1d065b,0x0fdc1bec,
175 0x3793a651,0x3352bbe6,0x3e119d3f,0x3ad08088,
176 0x2497d08d,0x2056cd3a,0x2d15ebe3,0x29d4f654,
177 0xc5a92679,0xc1683bce,0xcc2b1d17,0xc8ea00a0,
178 0xd6ad50a5,0xd26c4d12,0xdf2f6bcb,0xdbee767c,
179 0xe3a1cbc1,0xe760d676,0xea23f0af,0xeee2ed18,
180 0xf0a5bd1d,0xf464a0aa,0xf9278673,0xfde69bc4,
181 0x89b8fd09,0x8d79e0be,0x803ac667,0x84fbdbd0,
182 0x9abc8bd5,0x9e7d9662,0x933eb0bb,0x97ffad0c,
183 0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668,
184 0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4};
186 /* init the encode/decode logical stream state */
188 int ogg_stream_init(ogg_stream_state *os,int serialno){
190 memset(os,0,sizeof(*os));
191 os->body_storage=16*1024;
192 os->lacing_storage=1024;
194 os->body_data=_ogg_malloc(os->body_storage*sizeof(*os->body_data));
195 os->lacing_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->lacing_vals));
196 os->granule_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->granule_vals));
198 if(!os->body_data || !os->lacing_vals || !os->granule_vals){
199 ogg_stream_clear(os);
203 os->serialno=serialno;
210 /* async/delayed error detection for the ogg_stream_state */
211 int ogg_stream_check(ogg_stream_state *os){
212 if(!os || !os->body_data) return -1;
216 /* _clear does not free os, only the non-flat storage within */
217 int ogg_stream_clear(ogg_stream_state *os){
219 if(os->body_data)_ogg_free(os->body_data);
220 if(os->lacing_vals)_ogg_free(os->lacing_vals);
221 if(os->granule_vals)_ogg_free(os->granule_vals);
223 memset(os,0,sizeof(*os));
228 int ogg_stream_destroy(ogg_stream_state *os){
230 ogg_stream_clear(os);
236 /* Helpers for ogg_stream_encode; this keeps the structure and
237 what's happening fairly clear */
239 static int _os_body_expand(ogg_stream_state *os,int needed){
240 if(os->body_storage<=os->body_fill+needed){
242 ret=_ogg_realloc(os->body_data,(os->body_storage+needed+1024)*
243 sizeof(*os->body_data));
245 ogg_stream_clear(os);
248 os->body_storage+=(needed+1024);
254 static int _os_lacing_expand(ogg_stream_state *os,int needed){
255 if(os->lacing_storage<=os->lacing_fill+needed){
257 ret=_ogg_realloc(os->lacing_vals,(os->lacing_storage+needed+32)*
258 sizeof(*os->lacing_vals));
260 ogg_stream_clear(os);
264 ret=_ogg_realloc(os->granule_vals,(os->lacing_storage+needed+32)*
265 sizeof(*os->granule_vals));
267 ogg_stream_clear(os);
270 os->granule_vals=ret;
271 os->lacing_storage+=(needed+32);
276 /* checksum the page */
277 /* Direct table CRC; note that this will be faster in the future if we
278 perform the checksum silmultaneously with other copies */
280 void ogg_page_checksum_set(ogg_page *og){
282 ogg_uint32_t crc_reg=0;
285 /* safety; needed for API behavior, but not framing code */
291 for(i=0;i<og->header_len;i++)
292 crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->header[i]];
293 for(i=0;i<og->body_len;i++)
294 crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->body[i]];
296 og->header[22]=(unsigned char)(crc_reg&0xff);
297 og->header[23]=(unsigned char)((crc_reg>>8)&0xff);
298 og->header[24]=(unsigned char)((crc_reg>>16)&0xff);
299 og->header[25]=(unsigned char)((crc_reg>>24)&0xff);
303 /* submit data to the internal buffer of the framing engine */
304 int ogg_stream_iovecin(ogg_stream_state *os, ogg_iovec_t *iov, int count,
305 long e_o_s, ogg_int64_t granulepos){
307 int bytes = 0, lacing_vals, i;
309 if(ogg_stream_check(os)) return -1;
312 for (i = 0; i < count; ++i) bytes += (int)iov[i].iov_len;
313 lacing_vals=bytes/255+1;
315 if(os->body_returned){
316 /* advance packet data according to the body_returned pointer. We
317 had to keep it around to return a pointer into the buffer last
320 os->body_fill-=os->body_returned;
322 memmove(os->body_data,os->body_data+os->body_returned,
327 /* make sure we have the buffer storage */
328 if(_os_body_expand(os,bytes) || _os_lacing_expand(os,lacing_vals))
331 /* Copy in the submitted packet. Yes, the copy is a waste; this is
332 the liability of overly clean abstraction for the time being. It
333 will actually be fairly easy to eliminate the extra copy in the
336 for (i = 0; i < count; ++i) {
337 memcpy(os->body_data+os->body_fill, iov[i].iov_base, iov[i].iov_len);
338 os->body_fill += (int)iov[i].iov_len;
341 /* Store lacing vals for this packet */
342 for(i=0;i<lacing_vals-1;i++){
343 os->lacing_vals[os->lacing_fill+i]=255;
344 os->granule_vals[os->lacing_fill+i]=os->granulepos;
346 os->lacing_vals[os->lacing_fill+i]=bytes%255;
347 os->granulepos=os->granule_vals[os->lacing_fill+i]=granulepos;
349 /* flag the first segment as the beginning of the packet */
350 os->lacing_vals[os->lacing_fill]|= 0x100;
352 os->lacing_fill+=lacing_vals;
354 /* for the sake of completeness */
357 if(e_o_s)os->e_o_s=1;
362 int ogg_stream_packetin(ogg_stream_state *os,ogg_packet *op){
364 iov.iov_base = op->packet;
365 iov.iov_len = op->bytes;
366 return ogg_stream_iovecin(os, &iov, 1, op->e_o_s, op->granulepos);
369 /* Conditionally flush a page; force==0 will only flush nominal-size
370 pages, force==1 forces us to flush a page regardless of page size
371 so long as there's any data available at all. */
372 static int ogg_stream_flush_i(ogg_stream_state *os,ogg_page *og, int force){
375 int maxvals=(os->lacing_fill>255?255:os->lacing_fill);
378 ogg_int64_t granule_pos=-1;
380 if(ogg_stream_check(os)) return(0);
381 if(maxvals==0) return(0);
383 /* construct a page */
384 /* decide how many segments to include */
386 /* If this is the initial header case, the first page must only include
387 the initial header packet */
388 if(os->b_o_s==0){ /* 'initial header page' case */
390 for(vals=0;vals<maxvals;vals++){
391 if((os->lacing_vals[vals]&0x0ff)<255){
398 /* The extra packets_done, packet_just_done logic here attempts to do two things:
399 1) Don't unneccessarily span pages.
400 2) Unless necessary, don't flush pages if there are less than four packets on
401 them; this expands page size to reduce unneccessary overhead if incoming packets
403 These are not necessary behaviors, just 'always better than naive flushing'
404 without requiring an application to explicitly request a specific optimized
405 behavior. We'll want an explicit behavior setup pathway eventually as well. */
408 int packet_just_done=0;
409 for(vals=0;vals<maxvals;vals++){
410 if(acc>4096 && packet_just_done>=4){
414 acc+=os->lacing_vals[vals]&0x0ff;
415 if((os->lacing_vals[vals]&0xff)<255){
416 granule_pos=os->granule_vals[vals];
417 packet_just_done=++packets_done;
421 if(vals==255)force=1;
424 if(!force) return(0);
426 /* construct the header in temp storage */
427 memcpy(os->header,"OggS",4);
429 /* stream structure version */
432 /* continued packet flag? */
434 if((os->lacing_vals[0]&0x100)==0)os->header[5]|=0x01;
435 /* first page flag? */
436 if(os->b_o_s==0)os->header[5]|=0x02;
437 /* last page flag? */
438 if(os->e_o_s && os->lacing_fill==vals)os->header[5]|=0x04;
441 /* 64 bits of PCM position */
443 os->header[i]=(unsigned char)(granule_pos&0xff);
447 /* 32 bits of stream serial number */
449 long serialno=os->serialno;
451 os->header[i]=(unsigned char)(serialno&0xff);
456 /* 32 bits of page counter (we have both counter and page header
457 because this val can roll over) */
458 if(os->pageno==-1)os->pageno=0; /* because someone called
459 stream_reset; this would be a
460 strange thing to do in an
461 encode stream, but it has
464 long pageno=os->pageno++;
466 os->header[i]=(unsigned char)(pageno&0xff);
471 /* zero for computation; filled in later */
478 os->header[26]=(unsigned char)(vals&0xff);
480 bytes+=os->header[i+27]=(unsigned char)(os->lacing_vals[i]&0xff);
482 /* set pointers in the ogg_page struct */
483 og->header=os->header;
484 og->header_len=os->header_fill=vals+27;
485 og->body=os->body_data+os->body_returned;
488 /* advance the lacing data and set the body_returned pointer */
490 os->lacing_fill-=vals;
491 memmove(os->lacing_vals,os->lacing_vals+vals,os->lacing_fill*sizeof(*os->lacing_vals));
492 memmove(os->granule_vals,os->granule_vals+vals,os->lacing_fill*sizeof(*os->granule_vals));
493 os->body_returned+=bytes;
495 /* calculate the checksum */
497 ogg_page_checksum_set(og);
503 /* This will flush remaining packets into a page (returning nonzero),
504 even if there is not enough data to trigger a flush normally
505 (undersized page). If there are no packets or partial packets to
506 flush, ogg_stream_flush returns 0. Note that ogg_stream_flush will
507 try to flush a normal sized page like ogg_stream_pageout; a call to
508 ogg_stream_flush does not guarantee that all packets have flushed.
509 Only a return value of 0 from ogg_stream_flush indicates all packet
510 data is flushed into pages.
512 since ogg_stream_flush will flush the last page in a stream even if
513 it's undersized, you almost certainly want to use ogg_stream_pageout
514 (and *not* ogg_stream_flush) unless you specifically need to flush
515 an page regardless of size in the middle of a stream. */
517 int ogg_stream_flush(ogg_stream_state *os,ogg_page *og){
518 return ogg_stream_flush_i(os,og,1);
521 /* This constructs pages from buffered packet segments. The pointers
522 returned are to static buffers; do not free. The returned buffers are
523 good only until the next call (using the same ogg_stream_state) */
525 int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og){
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));
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 */
600 long newsize=size+oy->fill+4096; /* an extra page to be nice */
604 ret=_ogg_realloc(oy->data,newsize);
606 ret=_ogg_malloc(newsize);
615 /* expose a segment at least as large as requested at the fill mark */
616 return((char *)oy->data+oy->fill);
619 int ogg_sync_wrote(ogg_sync_state *oy, long bytes){
620 if(ogg_sync_check(oy))return -1;
621 if(oy->fill+bytes>oy->storage)return -1;
626 /* sync the stream. This is meant to be useful for finding page
629 return values for this:
631 0) page not ready; more data (no bytes skipped)
632 n) page synced at current location; page length n bytes
636 long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){
637 unsigned char *page=oy->data+oy->returned;
639 long bytes=oy->fill-oy->returned;
641 if(ogg_sync_check(oy))return 0;
643 if(oy->headerbytes==0){
645 if(bytes<27)return(0); /* not enough for a header */
647 /* verify capture pattern */
648 if(memcmp(page,"OggS",4))goto sync_fail;
650 headerbytes=page[26]+27;
651 if(bytes<headerbytes)return(0); /* not enough for header + seg table */
653 /* count up body length in the segment table */
655 for(i=0;i<page[26];i++)
656 oy->bodybytes+=page[27+i];
657 oy->headerbytes=headerbytes;
660 if(oy->bodybytes+oy->headerbytes>bytes)return(0);
662 /* The whole test page is buffered. Verify the checksum */
664 /* Grab the checksum bytes, set the header field to zero */
668 memcpy(chksum,page+22,4);
671 /* set up a temp page struct and recompute the checksum */
673 log.header_len=oy->headerbytes;
674 log.body=page+oy->headerbytes;
675 log.body_len=oy->bodybytes;
676 ogg_page_checksum_set(&log);
679 if(memcmp(chksum,page+22,4)){
680 /* D'oh. Mismatch! Corrupt page (or miscapture and not a page
682 /* replace the computed checksum with the one actually read in */
683 memcpy(page+22,chksum,4);
685 /* Bad checksum. Lose sync */
690 /* yes, have a whole page all ready to go */
692 unsigned char *page=oy->data+oy->returned;
697 og->header_len=oy->headerbytes;
698 og->body=page+oy->headerbytes;
699 og->body_len=oy->bodybytes;
703 oy->returned+=(bytes=oy->headerbytes+oy->bodybytes);
714 /* search for possible capture */
715 next=memchr(page+1,'O',bytes-1);
717 next=oy->data+oy->fill;
719 oy->returned=(int)(next-oy->data);
720 return((long)-(next-page));
723 /* sync the stream and get a page. Keep trying until we find a page.
724 Supress 'sync errors' after reporting the first.
727 -1) recapture (hole in data)
731 Returns pointers into buffered data; invalidated by next call to
732 _stream, _clear, _init, or _buffer */
734 int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og){
736 if(ogg_sync_check(oy))return 0;
738 /* all we need to do is verify a page at the head of the stream
739 buffer. If it doesn't verify, we look for the next potential
743 long ret=ogg_sync_pageseek(oy,og);
753 /* head did not start a synced page... skipped some bytes */
759 /* loop. keep looking */
764 /* add the incoming page to the stream state; we decompose the page
765 into packet segments here as well. */
767 int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){
768 unsigned char *header=og->header;
769 unsigned char *body=og->body;
770 long bodysize=og->body_len;
773 int version=ogg_page_version(og);
774 int continued=ogg_page_continued(og);
775 int bos=ogg_page_bos(og);
776 int eos=ogg_page_eos(og);
777 ogg_int64_t granulepos=ogg_page_granulepos(og);
778 int serialno=ogg_page_serialno(og);
779 long pageno=ogg_page_pageno(og);
780 int segments=header[26];
782 if(ogg_stream_check(os)) return -1;
784 /* clean up 'returned data' */
786 long lr=os->lacing_returned;
787 long br=os->body_returned;
793 memmove(os->body_data,os->body_data+br,os->body_fill);
799 if(os->lacing_fill-lr){
800 memmove(os->lacing_vals,os->lacing_vals+lr,
801 (os->lacing_fill-lr)*sizeof(*os->lacing_vals));
802 memmove(os->granule_vals,os->granule_vals+lr,
803 (os->lacing_fill-lr)*sizeof(*os->granule_vals));
806 os->lacing_packet-=lr;
807 os->lacing_returned=0;
811 /* check the serial number */
812 if(serialno!=os->serialno)return(-1);
813 if(version>0)return(-1);
815 if(_os_lacing_expand(os,segments+1)) return -1;
817 /* are we in sequence? */
818 if(pageno!=os->pageno){
821 /* unroll previous partial packet (if any) */
822 for(i=os->lacing_packet;i<os->lacing_fill;i++)
823 os->body_fill-=os->lacing_vals[i]&0xff;
824 os->lacing_fill=os->lacing_packet;
826 /* make a note of dropped data in segment table */
828 os->lacing_vals[os->lacing_fill++]=0x400;
833 /* are we a 'continued packet' page? If so, we may need to skip
836 if(os->lacing_fill<1 ||
837 os->lacing_vals[os->lacing_fill-1]==0x400){
839 for(;segptr<segments;segptr++){
840 int val=header[27+segptr];
852 if(_os_body_expand(os,bodysize)) return -1;
853 memcpy(os->body_data+os->body_fill,body,bodysize);
854 os->body_fill+=bodysize;
859 while(segptr<segments){
860 int val=header[27+segptr];
861 os->lacing_vals[os->lacing_fill]=val;
862 os->granule_vals[os->lacing_fill]=-1;
865 os->lacing_vals[os->lacing_fill]|=0x100;
869 if(val<255)saved=os->lacing_fill;
874 if(val<255)os->lacing_packet=os->lacing_fill;
877 /* set the granulepos on the last granuleval of the last full packet */
879 os->granule_vals[saved]=granulepos;
886 if(os->lacing_fill>0)
887 os->lacing_vals[os->lacing_fill-1]|=0x200;
895 /* clear things to an initial state. Good to call, eg, before seeking */
896 int ogg_sync_reset(ogg_sync_state *oy){
897 if(ogg_sync_check(oy))return -1;
907 int ogg_stream_reset(ogg_stream_state *os){
908 if(ogg_stream_check(os)) return -1;
915 os->lacing_returned=0;
928 int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno){
929 if(ogg_stream_check(os)) return -1;
930 ogg_stream_reset(os);
931 os->serialno=serialno;
935 static int _packetout(ogg_stream_state *os,ogg_packet *op,int adv){
937 /* The last part of decode. We have the stream broken into packet
938 segments. Now we need to group them into packets (or return the
939 out of sync markers) */
941 int ptr=os->lacing_returned;
943 if(os->lacing_packet<=ptr)return(0);
945 if(os->lacing_vals[ptr]&0x400){
946 /* we need to tell the codec there's a gap; it might need to
947 handle previous packet dependencies. */
948 os->lacing_returned++;
953 if(!op && !adv)return(1); /* just using peek as an inexpensive way
954 to ask if there's a whole packet
957 /* Gather the whole packet. We'll have no holes or a partial packet */
959 int size=os->lacing_vals[ptr]&0xff;
961 int eos=os->lacing_vals[ptr]&0x200; /* last packet of the stream? */
962 int bos=os->lacing_vals[ptr]&0x100; /* first packet of the stream? */
965 int val=os->lacing_vals[++ptr];
967 if(val&0x200)eos=0x200;
974 op->packet=os->body_data+os->body_returned;
975 op->packetno=os->packetno;
976 op->granulepos=os->granule_vals[ptr];
981 os->body_returned+=bytes;
982 os->lacing_returned=ptr+1;
989 int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op){
990 if(ogg_stream_check(os)) return 0;
991 return _packetout(os,op,1);
994 int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op){
995 if(ogg_stream_check(os)) return 0;
996 return _packetout(os,op,0);
999 void ogg_packet_clear(ogg_packet *op) {
1000 _ogg_free(op->packet);
1001 memset(op, 0, sizeof(*op));
1007 ogg_stream_state os_en, os_de;
1010 void checkpacket(ogg_packet *op,int len, int no, int pos){
1012 static int sequence=0;
1013 static int lastno=0;
1016 fprintf(stderr,"incorrect packet length (%d != %d)!\n",op->bytes,len);
1019 if(op->granulepos!=pos){
1020 fprintf(stderr,"incorrect packet granpos (%ld != %ld)!\n",(long)op->granulepos,pos);
1024 /* packet number just follows sequence/gap; adjust the input number
1034 if(op->packetno!=sequence){
1035 fprintf(stderr,"incorrect packet sequence %ld != %d\n",
1036 (long)(op->packetno),sequence);
1041 for(j=0;j<op->bytes;j++)
1042 if(op->packet[j]!=((j+no)&0xff)){
1043 fprintf(stderr,"body data mismatch (1) at pos %ld: %x!=%lx!\n\n",
1044 j,op->packet[j],(j+no)&0xff);
1049 void check_page(unsigned char *data,const int *header,ogg_page *og){
1052 for(j=0;j<og->body_len;j++)
1053 if(og->body[j]!=data[j]){
1054 fprintf(stderr,"body data mismatch (2) at pos %ld: %x!=%x!\n\n",
1055 j,data[j],og->body[j]);
1060 for(j=0;j<og->header_len;j++){
1061 if(og->header[j]!=header[j]){
1062 fprintf(stderr,"header content mismatch at pos %ld:\n",j);
1063 for(j=0;j<header[26]+27;j++)
1064 fprintf(stderr," (%ld)%02x:%02x",j,header[j],og->header[j]);
1065 fprintf(stderr,"\n");
1069 if(og->header_len!=header[26]+27){
1070 fprintf(stderr,"header length incorrect! (%ld!=%d)\n",
1071 og->header_len,header[26]+27);
1076 void print_header(ogg_page *og){
1078 fprintf(stderr,"\nHEADER:\n");
1079 fprintf(stderr," capture: %c %c %c %c version: %d flags: %x\n",
1080 og->header[0],og->header[1],og->header[2],og->header[3],
1081 (int)og->header[4],(int)og->header[5]);
1083 fprintf(stderr," granulepos: %d serialno: %d pageno: %ld\n",
1084 (og->header[9]<<24)|(og->header[8]<<16)|
1085 (og->header[7]<<8)|og->header[6],
1086 (og->header[17]<<24)|(og->header[16]<<16)|
1087 (og->header[15]<<8)|og->header[14],
1088 ((long)(og->header[21])<<24)|(og->header[20]<<16)|
1089 (og->header[19]<<8)|og->header[18]);
1091 fprintf(stderr," checksum: %02x:%02x:%02x:%02x\n segments: %d (",
1092 (int)og->header[22],(int)og->header[23],
1093 (int)og->header[24],(int)og->header[25],
1094 (int)og->header[26]);
1096 for(j=27;j<og->header_len;j++)
1097 fprintf(stderr,"%d ",(int)og->header[j]);
1098 fprintf(stderr,")\n\n");
1101 void copy_page(ogg_page *og){
1102 unsigned char *temp=_ogg_malloc(og->header_len);
1103 memcpy(temp,og->header,og->header_len);
1106 temp=_ogg_malloc(og->body_len);
1107 memcpy(temp,og->body,og->body_len);
1111 void free_page(ogg_page *og){
1112 _ogg_free (og->header);
1113 _ogg_free (og->body);
1117 fprintf(stderr,"error!\n");
1122 const int head1_0[] = {0x4f,0x67,0x67,0x53,0,0x06,
1123 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1124 0x01,0x02,0x03,0x04,0,0,0,0,
1125 0x15,0xed,0xec,0x91,
1129 /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
1130 const int head1_1[] = {0x4f,0x67,0x67,0x53,0,0x02,
1131 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1132 0x01,0x02,0x03,0x04,0,0,0,0,
1133 0x59,0x10,0x6c,0x2c,
1136 const int head2_1[] = {0x4f,0x67,0x67,0x53,0,0x04,
1137 0x07,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
1138 0x01,0x02,0x03,0x04,1,0,0,0,
1139 0x89,0x33,0x85,0xce,
1141 254,255,0,255,1,255,245,255,255,0,
1144 /* nil packets; beginning,middle,end */
1145 const int head1_2[] = {0x4f,0x67,0x67,0x53,0,0x02,
1146 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1147 0x01,0x02,0x03,0x04,0,0,0,0,
1148 0xff,0x7b,0x23,0x17,
1151 const int head2_2[] = {0x4f,0x67,0x67,0x53,0,0x04,
1152 0x07,0x28,0x00,0x00,0x00,0x00,0x00,0x00,
1153 0x01,0x02,0x03,0x04,1,0,0,0,
1154 0x5c,0x3f,0x66,0xcb,
1156 17,254,255,0,0,255,1,0,255,245,255,255,0,
1159 /* large initial packet */
1160 const int head1_3[] = {0x4f,0x67,0x67,0x53,0,0x02,
1161 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1162 0x01,0x02,0x03,0x04,0,0,0,0,
1163 0x01,0x27,0x31,0xaa,
1165 255,255,255,255,255,255,255,255,
1166 255,255,255,255,255,255,255,255,255,10};
1168 const int head2_3[] = {0x4f,0x67,0x67,0x53,0,0x04,
1169 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
1170 0x01,0x02,0x03,0x04,1,0,0,0,
1171 0x7f,0x4e,0x8a,0xd2,
1176 /* continuing packet test */
1177 const int head1_4[] = {0x4f,0x67,0x67,0x53,0,0x02,
1178 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1179 0x01,0x02,0x03,0x04,0,0,0,0,
1180 0xff,0x7b,0x23,0x17,
1184 const int head2_4[] = {0x4f,0x67,0x67,0x53,0,0x00,
1185 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
1186 0x01,0x02,0x03,0x04,1,0,0,0,
1187 0xf8,0x3c,0x19,0x79,
1189 255,255,255,255,255,255,255,255,
1190 255,255,255,255,255,255,255,255,
1191 255,255,255,255,255,255,255,255,
1192 255,255,255,255,255,255,255,255,
1193 255,255,255,255,255,255,255,255,
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};
1222 const int head3_4[] = {0x4f,0x67,0x67,0x53,0,0x05,
1223 0x07,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,
1224 0x01,0x02,0x03,0x04,2,0,0,0,
1225 0x38,0xe6,0xb6,0x28,
1227 255,220,255,4,255,0};
1230 /* spill expansion test */
1231 const int head1_4b[] = {0x4f,0x67,0x67,0x53,0,0x02,
1232 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1233 0x01,0x02,0x03,0x04,0,0,0,0,
1234 0xff,0x7b,0x23,0x17,
1238 const int head2_4b[] = {0x4f,0x67,0x67,0x53,0,0x00,
1239 0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
1240 0x01,0x02,0x03,0x04,1,0,0,0,
1241 0xce,0x8f,0x17,0x1a,
1243 255,255,255,255,255,255,255,255,
1244 255,255,255,255,255,255,255,255,255,10,255,4,255,0,0};
1247 const int head3_4b[] = {0x4f,0x67,0x67,0x53,0,0x04,
1248 0x07,0x14,0x00,0x00,0x00,0x00,0x00,0x00,
1249 0x01,0x02,0x03,0x04,2,0,0,0,
1250 0x9b,0xb2,0x50,0xa1,
1254 /* page with the 255 segment limit */
1255 const int head1_5[] = {0x4f,0x67,0x67,0x53,0,0x02,
1256 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1257 0x01,0x02,0x03,0x04,0,0,0,0,
1258 0xff,0x7b,0x23,0x17,
1262 const int head2_5[] = {0x4f,0x67,0x67,0x53,0,0x00,
1263 0x07,0xfc,0x03,0x00,0x00,0x00,0x00,0x00,
1264 0x01,0x02,0x03,0x04,1,0,0,0,
1265 0xed,0x2a,0x2e,0xa7,
1267 10,10,10,10,10,10,10,10,
1268 10,10,10,10,10,10,10,10,
1269 10,10,10,10,10,10,10,10,
1270 10,10,10,10,10,10,10,10,
1271 10,10,10,10,10,10,10,10,
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};
1300 const int head3_5[] = {0x4f,0x67,0x67,0x53,0,0x04,
1301 0x07,0x00,0x04,0x00,0x00,0x00,0x00,0x00,
1302 0x01,0x02,0x03,0x04,2,0,0,0,
1303 0x6c,0x3b,0x82,0x3d,
1308 /* packet that overspans over an entire page */
1309 const int head1_6[] = {0x4f,0x67,0x67,0x53,0,0x02,
1310 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1311 0x01,0x02,0x03,0x04,0,0,0,0,
1312 0xff,0x7b,0x23,0x17,
1316 const int head2_6[] = {0x4f,0x67,0x67,0x53,0,0x00,
1317 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
1318 0x01,0x02,0x03,0x04,1,0,0,0,
1319 0x68,0x22,0x7c,0x3d,
1322 255,255,255,255,255,255,255,255,
1323 255,255,255,255,255,255,255,255,
1324 255,255,255,255,255,255,255,255,
1325 255,255,255,255,255,255,255,255,
1326 255,255,255,255,255,255,255,255,
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};
1355 const int head3_6[] = {0x4f,0x67,0x67,0x53,0,0x01,
1356 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
1357 0x01,0x02,0x03,0x04,2,0,0,0,
1358 0xf4,0x87,0xba,0xf3,
1360 255,255,255,255,255,255,255,255,
1361 255,255,255,255,255,255,255,255,
1362 255,255,255,255,255,255,255,255,
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};
1393 const int head4_6[] = {0x4f,0x67,0x67,0x53,0,0x05,
1394 0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
1395 0x01,0x02,0x03,0x04,3,0,0,0,
1396 0xf7,0x2f,0x6c,0x60,
1400 /* packet that overspans over an entire page */
1401 const int head1_7[] = {0x4f,0x67,0x67,0x53,0,0x02,
1402 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1403 0x01,0x02,0x03,0x04,0,0,0,0,
1404 0xff,0x7b,0x23,0x17,
1408 const int head2_7[] = {0x4f,0x67,0x67,0x53,0,0x00,
1409 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
1410 0x01,0x02,0x03,0x04,1,0,0,0,
1411 0x68,0x22,0x7c,0x3d,
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,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};
1447 const int head3_7[] = {0x4f,0x67,0x67,0x53,0,0x05,
1448 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
1449 0x01,0x02,0x03,0x04,2,0,0,0,
1450 0xd4,0xe0,0x60,0xe5,
1454 void test_pack(const int *pl, const int **headers, int byteskip,
1455 int pageskip, int packetskip){
1456 unsigned char *data=_ogg_malloc(1024*1024); /* for scripted test cases only */
1461 long granule_pos=7,pageno=0;
1462 int i,j,packets,pageout=pageskip;
1466 int byteskipcount=0;
1468 ogg_stream_reset(&os_en);
1469 ogg_stream_reset(&os_de);
1470 ogg_sync_reset(&oy);
1472 for(packets=0;packets<packetskip;packets++)
1473 depacket+=pl[packets];
1475 for(packets=0;;packets++)if(pl[packets]==-1)break;
1477 for(i=0;i<packets;i++){
1478 /* construct a test packet */
1482 op.packet=data+inptr;
1484 op.e_o_s=(pl[i+1]<0?1:0);
1485 op.granulepos=granule_pos;
1489 for(j=0;j<len;j++)data[inptr++]=i+j;
1491 /* submit the test packet */
1492 ogg_stream_packetin(&os_en,&op);
1494 /* retrieve any finished pages */
1498 while(ogg_stream_pageout(&os_en,&og)){
1499 /* We have a page. Check it carefully */
1501 fprintf(stderr,"%ld, ",pageno);
1503 if(headers[pageno]==NULL){
1504 fprintf(stderr,"coded too many pages!\n");
1508 check_page(data+outptr,headers[pageno],&og);
1510 outptr+=og.body_len;
1518 /* have a complete page; submit it to sync/decode */
1522 ogg_packet op_de,op_de2;
1523 char *buf=ogg_sync_buffer(&oy,og.header_len+og.body_len);
1525 byteskipcount+=og.header_len;
1526 if(byteskipcount>byteskip){
1527 memcpy(next,og.header,byteskipcount-byteskip);
1528 next+=byteskipcount-byteskip;
1529 byteskipcount=byteskip;
1532 byteskipcount+=og.body_len;
1533 if(byteskipcount>byteskip){
1534 memcpy(next,og.body,byteskipcount-byteskip);
1535 next+=byteskipcount-byteskip;
1536 byteskipcount=byteskip;
1539 ogg_sync_wrote(&oy,next-buf);
1542 int ret=ogg_sync_pageout(&oy,&og_de);
1545 /* got a page. Happy happy. Verify that it's good. */
1547 fprintf(stderr,"(%ld), ",pageout);
1549 check_page(data+deptr,headers[pageout],&og_de);
1550 deptr+=og_de.body_len;
1553 /* submit it to deconstitution */
1554 ogg_stream_pagein(&os_de,&og_de);
1557 while(ogg_stream_packetpeek(&os_de,&op_de2)>0){
1558 ogg_stream_packetpeek(&os_de,NULL);
1559 ogg_stream_packetout(&os_de,&op_de); /* just catching them all */
1561 /* verify peek and out match */
1562 if(memcmp(&op_de,&op_de2,sizeof(op_de))){
1563 fprintf(stderr,"packetout != packetpeek! pos=%ld\n",
1568 /* verify the packet! */
1570 if(memcmp(data+depacket,op_de.packet,op_de.bytes)){
1571 fprintf(stderr,"packet data mismatch in decode! pos=%ld\n",
1575 /* check bos flag */
1576 if(bosflag==0 && op_de.b_o_s==0){
1577 fprintf(stderr,"b_o_s flag not set on packet!\n");
1580 if(bosflag && op_de.b_o_s){
1581 fprintf(stderr,"b_o_s flag incorrectly set on packet!\n");
1585 depacket+=op_de.bytes;
1587 /* check eos flag */
1589 fprintf(stderr,"Multiple decoded packets with eos flag!\n");
1593 if(op_de.e_o_s)eosflag=1;
1595 /* check granulepos flag */
1596 if(op_de.granulepos!=-1){
1597 fprintf(stderr," granule:%ld ",(long)op_de.granulepos);
1606 if(headers[pageno]!=NULL){
1607 fprintf(stderr,"did not write last page!\n");
1610 if(headers[pageout]!=NULL){
1611 fprintf(stderr,"did not decode last page!\n");
1615 fprintf(stderr,"encoded page data incomplete!\n");
1619 fprintf(stderr,"decoded page data incomplete!\n");
1622 if(inptr!=depacket){
1623 fprintf(stderr,"decoded packet data incomplete!\n");
1627 fprintf(stderr,"Never got a packet with EOS set!\n");
1630 fprintf(stderr,"ok.\n");
1635 ogg_stream_init(&os_en,0x04030201);
1636 ogg_stream_init(&os_de,0x04030201);
1639 /* Exercise each code path in the framing code. Also verify that
1640 the checksums are working. */
1644 const int packets[]={17, -1};
1645 const int *headret[]={head1_0,NULL};
1647 fprintf(stderr,"testing single page encoding... ");
1648 test_pack(packets,headret,0,0,0);
1652 /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
1653 const int packets[]={17, 254, 255, 256, 500, 510, 600, -1};
1654 const int *headret[]={head1_1,head2_1,NULL};
1656 fprintf(stderr,"testing basic page encoding... ");
1657 test_pack(packets,headret,0,0,0);
1661 /* nil packets; beginning,middle,end */
1662 const int packets[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1};
1663 const int *headret[]={head1_2,head2_2,NULL};
1665 fprintf(stderr,"testing basic nil packets... ");
1666 test_pack(packets,headret,0,0,0);
1670 /* large initial packet */
1671 const int packets[]={4345,259,255,-1};
1672 const int *headret[]={head1_3,head2_3,NULL};
1674 fprintf(stderr,"testing initial-packet lacing > 4k... ");
1675 test_pack(packets,headret,0,0,0);
1679 /* continuing packet test; with page spill expansion, we have to
1680 overflow the lacing table. */
1681 const int packets[]={0,65500,259,255,-1};
1682 const int *headret[]={head1_4,head2_4,head3_4,NULL};
1684 fprintf(stderr,"testing single packet page span... ");
1685 test_pack(packets,headret,0,0,0);
1689 /* spill expand packet test */
1690 const int packets[]={0,4345,259,255,0,0,-1};
1691 const int *headret[]={head1_4b,head2_4b,head3_4b,NULL};
1693 fprintf(stderr,"testing page spill expansion... ");
1694 test_pack(packets,headret,0,0,0);
1697 /* page with the 255 segment limit */
1700 const int packets[]={0,10,10,10,10,10,10,10,10,
1701 10,10,10,10,10,10,10,10,
1702 10,10,10,10,10,10,10,10,
1703 10,10,10,10,10,10,10,10,
1704 10,10,10,10,10,10,10,10,
1705 10,10,10,10,10,10,10,10,
1706 10,10,10,10,10,10,10,10,
1707 10,10,10,10,10,10,10,10,
1708 10,10,10,10,10,10,10,10,
1709 10,10,10,10,10,10,10,10,
1710 10,10,10,10,10,10,10,10,
1711 10,10,10,10,10,10,10,10,
1712 10,10,10,10,10,10,10,10,
1713 10,10,10,10,10,10,10,10,
1714 10,10,10,10,10,10,10,10,
1715 10,10,10,10,10,10,10,10,
1716 10,10,10,10,10,10,10,10,
1717 10,10,10,10,10,10,10,10,
1718 10,10,10,10,10,10,10,10,
1719 10,10,10,10,10,10,10,10,
1720 10,10,10,10,10,10,10,10,
1721 10,10,10,10,10,10,10,10,
1722 10,10,10,10,10,10,10,10,
1723 10,10,10,10,10,10,10,10,
1724 10,10,10,10,10,10,10,10,
1725 10,10,10,10,10,10,10,10,
1726 10,10,10,10,10,10,10,10,
1727 10,10,10,10,10,10,10,10,
1728 10,10,10,10,10,10,10,10,
1729 10,10,10,10,10,10,10,10,
1730 10,10,10,10,10,10,10,10,
1731 10,10,10,10,10,10,10,50,-1};
1732 const int *headret[]={head1_5,head2_5,head3_5,NULL};
1734 fprintf(stderr,"testing max packet segments... ");
1735 test_pack(packets,headret,0,0,0);
1739 /* packet that overspans over an entire page */
1740 const int packets[]={0,100,130049,259,255,-1};
1741 const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
1743 fprintf(stderr,"testing very large packets... ");
1744 test_pack(packets,headret,0,0,0);
1748 /* test for the libogg 1.1.1 resync in large continuation bug
1749 found by Josh Coalson) */
1750 const int packets[]={0,100,130049,259,255,-1};
1751 const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
1753 fprintf(stderr,"testing continuation resync in very large packets... ");
1754 test_pack(packets,headret,100,2,3);
1758 /* term only page. why not? */
1759 const int packets[]={0,100,64770,-1};
1760 const int *headret[]={head1_7,head2_7,head3_7,NULL};
1762 fprintf(stderr,"testing zero data page (1 nil packet)... ");
1763 test_pack(packets,headret,0,0,0);
1769 /* build a bunch of pages for testing */
1770 unsigned char *data=_ogg_malloc(1024*1024);
1771 int pl[]={0, 1,1,98,4079, 1,1,2954,2057, 76,34,912,0,234,1000,1000, 1000,300,-1};
1775 ogg_stream_reset(&os_en);
1777 for(i=0;pl[i]!=-1;i++){
1781 op.packet=data+inptr;
1783 op.e_o_s=(pl[i+1]<0?1:0);
1784 op.granulepos=(i+1)*1000;
1786 for(j=0;j<len;j++)data[inptr++]=i+j;
1787 ogg_stream_packetin(&os_en,&op);
1792 /* retrieve finished pages */
1794 if(ogg_stream_pageout(&os_en,&og[i])==0){
1795 fprintf(stderr,"Too few pages output building sync tests!\n");
1801 /* Test lost pages on pagein/packetout: no rollback */
1806 fprintf(stderr,"Testing loss of pages... ");
1808 ogg_sync_reset(&oy);
1809 ogg_stream_reset(&os_de);
1811 memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
1813 ogg_sync_wrote(&oy,og[i].header_len);
1814 memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
1815 ogg_sync_wrote(&oy,og[i].body_len);
1818 ogg_sync_pageout(&oy,&temp);
1819 ogg_stream_pagein(&os_de,&temp);
1820 ogg_sync_pageout(&oy,&temp);
1821 ogg_stream_pagein(&os_de,&temp);
1822 ogg_sync_pageout(&oy,&temp);
1824 ogg_sync_pageout(&oy,&temp);
1825 ogg_stream_pagein(&os_de,&temp);
1827 /* do we get the expected results/packets? */
1829 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1830 checkpacket(&test,0,0,0);
1831 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1832 checkpacket(&test,1,1,-1);
1833 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1834 checkpacket(&test,1,2,-1);
1835 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1836 checkpacket(&test,98,3,-1);
1837 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1838 checkpacket(&test,4079,4,5000);
1839 if(ogg_stream_packetout(&os_de,&test)!=-1){
1840 fprintf(stderr,"Error: loss of page did not return error\n");
1843 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1844 checkpacket(&test,76,9,-1);
1845 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1846 checkpacket(&test,34,10,-1);
1847 fprintf(stderr,"ok.\n");
1850 /* Test lost pages on pagein/packetout: rollback with continuation */
1855 fprintf(stderr,"Testing loss of pages (rollback required)... ");
1857 ogg_sync_reset(&oy);
1858 ogg_stream_reset(&os_de);
1860 memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
1862 ogg_sync_wrote(&oy,og[i].header_len);
1863 memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
1864 ogg_sync_wrote(&oy,og[i].body_len);
1867 ogg_sync_pageout(&oy,&temp);
1868 ogg_stream_pagein(&os_de,&temp);
1869 ogg_sync_pageout(&oy,&temp);
1870 ogg_stream_pagein(&os_de,&temp);
1871 ogg_sync_pageout(&oy,&temp);
1872 ogg_stream_pagein(&os_de,&temp);
1873 ogg_sync_pageout(&oy,&temp);
1875 ogg_sync_pageout(&oy,&temp);
1876 ogg_stream_pagein(&os_de,&temp);
1878 /* do we get the expected results/packets? */
1880 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1881 checkpacket(&test,0,0,0);
1882 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1883 checkpacket(&test,1,1,-1);
1884 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1885 checkpacket(&test,1,2,-1);
1886 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1887 checkpacket(&test,98,3,-1);
1888 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1889 checkpacket(&test,4079,4,5000);
1890 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1891 checkpacket(&test,1,5,-1);
1892 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1893 checkpacket(&test,1,6,-1);
1894 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1895 checkpacket(&test,2954,7,-1);
1896 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1897 checkpacket(&test,2057,8,9000);
1898 if(ogg_stream_packetout(&os_de,&test)!=-1){
1899 fprintf(stderr,"Error: loss of page did not return error\n");
1902 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1903 checkpacket(&test,300,17,18000);
1904 fprintf(stderr,"ok.\n");
1907 /* the rest only test sync */
1910 /* Test fractional page inputs: incomplete capture */
1911 fprintf(stderr,"Testing sync on partial inputs... ");
1912 ogg_sync_reset(&oy);
1913 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
1915 ogg_sync_wrote(&oy,3);
1916 if(ogg_sync_pageout(&oy,&og_de)>0)error();
1918 /* Test fractional page inputs: incomplete fixed header */
1919 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+3,
1921 ogg_sync_wrote(&oy,20);
1922 if(ogg_sync_pageout(&oy,&og_de)>0)error();
1924 /* Test fractional page inputs: incomplete header */
1925 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+23,
1927 ogg_sync_wrote(&oy,5);
1928 if(ogg_sync_pageout(&oy,&og_de)>0)error();
1930 /* Test fractional page inputs: incomplete body */
1932 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+28,
1933 og[1].header_len-28);
1934 ogg_sync_wrote(&oy,og[1].header_len-28);
1935 if(ogg_sync_pageout(&oy,&og_de)>0)error();
1937 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,1000);
1938 ogg_sync_wrote(&oy,1000);
1939 if(ogg_sync_pageout(&oy,&og_de)>0)error();
1941 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body+1000,
1942 og[1].body_len-1000);
1943 ogg_sync_wrote(&oy,og[1].body_len-1000);
1944 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
1946 fprintf(stderr,"ok.\n");
1949 /* Test fractional page inputs: page + incomplete capture */
1952 fprintf(stderr,"Testing sync on 1+partial inputs... ");
1953 ogg_sync_reset(&oy);
1955 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
1957 ogg_sync_wrote(&oy,og[1].header_len);
1959 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
1961 ogg_sync_wrote(&oy,og[1].body_len);
1963 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
1965 ogg_sync_wrote(&oy,20);
1966 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
1967 if(ogg_sync_pageout(&oy,&og_de)>0)error();
1969 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+20,
1970 og[1].header_len-20);
1971 ogg_sync_wrote(&oy,og[1].header_len-20);
1972 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
1974 ogg_sync_wrote(&oy,og[1].body_len);
1975 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
1977 fprintf(stderr,"ok.\n");
1980 /* Test recapture: garbage + page */
1983 fprintf(stderr,"Testing search for capture... ");
1984 ogg_sync_reset(&oy);
1987 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
1989 ogg_sync_wrote(&oy,og[1].body_len);
1991 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
1993 ogg_sync_wrote(&oy,og[1].header_len);
1995 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
1997 ogg_sync_wrote(&oy,og[1].body_len);
1999 memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
2001 ogg_sync_wrote(&oy,20);
2002 if(ogg_sync_pageout(&oy,&og_de)>0)error();
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[2].header_len),og[2].header+20,
2007 og[2].header_len-20);
2008 ogg_sync_wrote(&oy,og[2].header_len-20);
2009 memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
2011 ogg_sync_wrote(&oy,og[2].body_len);
2012 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2014 fprintf(stderr,"ok.\n");
2017 /* Test recapture: page + garbage + page */
2020 fprintf(stderr,"Testing recapture... ");
2021 ogg_sync_reset(&oy);
2023 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
2025 ogg_sync_wrote(&oy,og[1].header_len);
2027 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2029 ogg_sync_wrote(&oy,og[1].body_len);
2031 memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
2033 ogg_sync_wrote(&oy,og[2].header_len);
2035 memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
2037 ogg_sync_wrote(&oy,og[2].header_len);
2039 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2041 memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
2043 ogg_sync_wrote(&oy,og[2].body_len-5);
2045 memcpy(ogg_sync_buffer(&oy,og[3].header_len),og[3].header,
2047 ogg_sync_wrote(&oy,og[3].header_len);
2049 memcpy(ogg_sync_buffer(&oy,og[3].body_len),og[3].body,
2051 ogg_sync_wrote(&oy,og[3].body_len);
2053 if(ogg_sync_pageout(&oy,&og_de)>0)error();
2054 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2056 fprintf(stderr,"ok.\n");
2059 /* Free page data that was previously copied */