1 /********************************************************************
2  *                                                                  *
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.       *
7  *                                                                  *
8  * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2010             *
9  * by the Xiph.Org Foundation http://www.xiph.org/                  *
10  *                                                                  *
11  ********************************************************************
12 
13  function: code raw packets into framed OggSquish stream and
14            decode Ogg streams back into raw packets
15  last mod: $Id$
16 
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
19  for details.
20 
21  ********************************************************************/
22 
23 #include <stdlib.h>
24 #include <limits.h>
25 #include <string.h>
26 #include <ogg/ogg.h>
27 
28 /* A complete description of Ogg framing exists in docs/framing.html */
29 
ogg_page_version(const ogg_page * og)30 int ogg_page_version(const ogg_page *og){
31   return((int)(og->header[4]));
32 }
33 
ogg_page_continued(const ogg_page * og)34 int ogg_page_continued(const ogg_page *og){
35   return((int)(og->header[5]&0x01));
36 }
37 
ogg_page_bos(const ogg_page * og)38 int ogg_page_bos(const ogg_page *og){
39   return((int)(og->header[5]&0x02));
40 }
41 
ogg_page_eos(const ogg_page * og)42 int ogg_page_eos(const ogg_page *og){
43   return((int)(og->header[5]&0x04));
44 }
45 
ogg_page_granulepos(const ogg_page * og)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);
56   return(granulepos);
57 }
58 
ogg_page_serialno(const ogg_page * og)59 int ogg_page_serialno(const ogg_page *og){
60   return(og->header[14] |
61          (og->header[15]<<8) |
62          (og->header[16]<<16) |
63          (og->header[17]<<24));
64 }
65 
ogg_page_pageno(const ogg_page * og)66 long ogg_page_pageno(const ogg_page *og){
67   return(og->header[18] |
68          (og->header[19]<<8) |
69          (og->header[20]<<16) |
70          (og->header[21]<<24));
71 }
72 
73 
74 
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
77    page, it's counted */
78 
79 /* NOTE:
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
84 
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
90 */
91 
ogg_page_packets(const ogg_page * og)92 int ogg_page_packets(const ogg_page *og){
93   int i,n=og->header[26],count=0;
94   for(i=0;i<n;i++)
95     if(og->header[27+i]<255)count++;
96   return(count);
97 }
98 
99 
100 #if 0
101 /* helper to initialize lookup for direct-table CRC (illustrative; we
102    use the static init below) */
103 
104 static ogg_uint32_t _ogg_crc_entry(unsigned long index){
105   int           i;
106   unsigned long r;
107 
108   r = index << 24;
109   for (i=0; i<8; i++)
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 */
115     else
116        r<<=1;
117  return (r & 0xffffffffUL);
118 }
119 #endif
120 
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};
186 
187 /* init the encode/decode logical stream state */
188 
ogg_stream_init(ogg_stream_state * os,int serialno)189 int ogg_stream_init(ogg_stream_state *os,int serialno){
190   if(os){
191     memset(os,0,sizeof(*os));
192     os->body_storage=16*1024;
193     os->lacing_storage=1024;
194 
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));
198 
199     if(!os->body_data || !os->lacing_vals || !os->granule_vals){
200       ogg_stream_clear(os);
201       return -1;
202     }
203 
204     os->serialno=serialno;
205 
206     return(0);
207   }
208   return(-1);
209 }
210 
211 /* async/delayed error detection for the ogg_stream_state */
ogg_stream_check(ogg_stream_state * os)212 int ogg_stream_check(ogg_stream_state *os){
213   if(!os || !os->body_data) return -1;
214   return 0;
215 }
216 
217 /* _clear does not free os, only the non-flat storage within */
ogg_stream_clear(ogg_stream_state * os)218 int ogg_stream_clear(ogg_stream_state *os){
219   if(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);
223 
224     memset(os,0,sizeof(*os));
225   }
226   return(0);
227 }
228 
ogg_stream_destroy(ogg_stream_state * os)229 int ogg_stream_destroy(ogg_stream_state *os){
230   if(os){
231     ogg_stream_clear(os);
232     _ogg_free(os);
233   }
234   return(0);
235 }
236 
237 /* Helpers for ogg_stream_encode; this keeps the structure and
238    what's happening fairly clear */
239 
_os_body_expand(ogg_stream_state * os,long needed)240 static int _os_body_expand(ogg_stream_state *os,long needed){
241   if(os->body_storage-needed<=os->body_fill){
242     long body_storage;
243     void *ret;
244     if(os->body_storage>LONG_MAX-needed){
245       ogg_stream_clear(os);
246       return -1;
247     }
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));
251     if(!ret){
252       ogg_stream_clear(os);
253       return -1;
254     }
255     os->body_storage=body_storage;
256     os->body_data=ret;
257   }
258   return 0;
259 }
260 
_os_lacing_expand(ogg_stream_state * os,long needed)261 static int _os_lacing_expand(ogg_stream_state *os,long needed){
262   if(os->lacing_storage-needed<=os->lacing_fill){
263     long lacing_storage;
264     void *ret;
265     if(os->lacing_storage>LONG_MAX-needed){
266       ogg_stream_clear(os);
267       return -1;
268     }
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));
272     if(!ret){
273       ogg_stream_clear(os);
274       return -1;
275     }
276     os->lacing_vals=ret;
277     ret=_ogg_realloc(os->granule_vals,lacing_storage*
278                      sizeof(*os->granule_vals));
279     if(!ret){
280       ogg_stream_clear(os);
281       return -1;
282     }
283     os->granule_vals=ret;
284     os->lacing_storage=lacing_storage;
285   }
286   return 0;
287 }
288 
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 */
292 
ogg_page_checksum_set(ogg_page * og)293 void ogg_page_checksum_set(ogg_page *og){
294   if(og){
295 #ifndef FUZZING
296     ogg_uint32_t crc_reg=0;
297     int i;
298 #endif
299 
300     /* safety; needed for API behavior, but not framing code */
301     og->header[22]=0;
302     og->header[23]=0;
303     og->header[24]=0;
304     og->header[25]=0;
305 
306 #ifndef FUZZING
307     for(i=0;i<og->header_len;i++)
308       crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->header[i]];
309     for(i=0;i<og->body_len;i++)
310       crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->body[i]];
311 
312     og->header[22]=(unsigned char)(crc_reg&0xff);
313     og->header[23]=(unsigned char)((crc_reg>>8)&0xff);
314     og->header[24]=(unsigned char)((crc_reg>>16)&0xff);
315     og->header[25]=(unsigned char)((crc_reg>>24)&0xff);
316 #endif
317   }
318 }
319 
320 /* submit data to the internal buffer of the framing engine */
ogg_stream_iovecin(ogg_stream_state * os,ogg_iovec_t * iov,int count,long e_o_s,ogg_int64_t granulepos)321 int ogg_stream_iovecin(ogg_stream_state *os, ogg_iovec_t *iov, int count,
322                        long e_o_s, ogg_int64_t granulepos){
323 
324   long bytes = 0, lacing_vals;
325   int i;
326 
327   if(ogg_stream_check(os)) return -1;
328   if(!iov) return 0;
329 
330   for (i = 0; i < count; ++i){
331     if(iov[i].iov_len>LONG_MAX) return -1;
332     if(bytes>LONG_MAX-(long)iov[i].iov_len) return -1;
333     bytes += (long)iov[i].iov_len;
334   }
335   lacing_vals=bytes/255+1;
336 
337   if(os->body_returned){
338     /* advance packet data according to the body_returned pointer. We
339        had to keep it around to return a pointer into the buffer last
340        call */
341 
342     os->body_fill-=os->body_returned;
343     if(os->body_fill)
344       memmove(os->body_data,os->body_data+os->body_returned,
345               os->body_fill);
346     os->body_returned=0;
347   }
348 
349   /* make sure we have the buffer storage */
350   if(_os_body_expand(os,bytes) || _os_lacing_expand(os,lacing_vals))
351     return -1;
352 
353   /* Copy in the submitted packet.  Yes, the copy is a waste; this is
354      the liability of overly clean abstraction for the time being.  It
355      will actually be fairly easy to eliminate the extra copy in the
356      future */
357 
358   for (i = 0; i < count; ++i) {
359     memcpy(os->body_data+os->body_fill, iov[i].iov_base, iov[i].iov_len);
360     os->body_fill += (int)iov[i].iov_len;
361   }
362 
363   /* Store lacing vals for this packet */
364   for(i=0;i<lacing_vals-1;i++){
365     os->lacing_vals[os->lacing_fill+i]=255;
366     os->granule_vals[os->lacing_fill+i]=os->granulepos;
367   }
368   os->lacing_vals[os->lacing_fill+i]=bytes%255;
369   os->granulepos=os->granule_vals[os->lacing_fill+i]=granulepos;
370 
371   /* flag the first segment as the beginning of the packet */
372   os->lacing_vals[os->lacing_fill]|= 0x100;
373 
374   os->lacing_fill+=lacing_vals;
375 
376   /* for the sake of completeness */
377   os->packetno++;
378 
379   if(e_o_s)os->e_o_s=1;
380 
381   return(0);
382 }
383 
ogg_stream_packetin(ogg_stream_state * os,ogg_packet * op)384 int ogg_stream_packetin(ogg_stream_state *os,ogg_packet *op){
385   ogg_iovec_t iov;
386   iov.iov_base = op->packet;
387   iov.iov_len = op->bytes;
388   return ogg_stream_iovecin(os, &iov, 1, op->e_o_s, op->granulepos);
389 }
390 
391 /* Conditionally flush a page; force==0 will only flush nominal-size
392    pages, force==1 forces us to flush a page regardless of page size
393    so long as there's any data available at all. */
ogg_stream_flush_i(ogg_stream_state * os,ogg_page * og,int force,int nfill)394 static int ogg_stream_flush_i(ogg_stream_state *os,ogg_page *og, int force, int nfill){
395   int i;
396   int vals=0;
397   int maxvals=(os->lacing_fill>255?255:os->lacing_fill);
398   int bytes=0;
399   long acc=0;
400   ogg_int64_t granule_pos=-1;
401 
402   if(ogg_stream_check(os)) return(0);
403   if(maxvals==0) return(0);
404 
405   /* construct a page */
406   /* decide how many segments to include */
407 
408   /* If this is the initial header case, the first page must only include
409      the initial header packet */
410   if(os->b_o_s==0){  /* 'initial header page' case */
411     granule_pos=0;
412     for(vals=0;vals<maxvals;vals++){
413       if((os->lacing_vals[vals]&0x0ff)<255){
414         vals++;
415         break;
416       }
417     }
418   }else{
419 
420     /* The extra packets_done, packet_just_done logic here attempts to do two things:
421        1) Don't unneccessarily span pages.
422        2) Unless necessary, don't flush pages if there are less than four packets on
423           them; this expands page size to reduce unneccessary overhead if incoming packets
424           are large.
425        These are not necessary behaviors, just 'always better than naive flushing'
426        without requiring an application to explicitly request a specific optimized
427        behavior. We'll want an explicit behavior setup pathway eventually as well. */
428 
429     int packets_done=0;
430     int packet_just_done=0;
431     for(vals=0;vals<maxvals;vals++){
432       if(acc>nfill && packet_just_done>=4){
433         force=1;
434         break;
435       }
436       acc+=os->lacing_vals[vals]&0x0ff;
437       if((os->lacing_vals[vals]&0xff)<255){
438         granule_pos=os->granule_vals[vals];
439         packet_just_done=++packets_done;
440       }else
441         packet_just_done=0;
442     }
443     if(vals==255)force=1;
444   }
445 
446   if(!force) return(0);
447 
448   /* construct the header in temp storage */
449   memcpy(os->header,"OggS",4);
450 
451   /* stream structure version */
452   os->header[4]=0x00;
453 
454   /* continued packet flag? */
455   os->header[5]=0x00;
456   if((os->lacing_vals[0]&0x100)==0)os->header[5]|=0x01;
457   /* first page flag? */
458   if(os->b_o_s==0)os->header[5]|=0x02;
459   /* last page flag? */
460   if(os->e_o_s && os->lacing_fill==vals)os->header[5]|=0x04;
461   os->b_o_s=1;
462 
463   /* 64 bits of PCM position */
464   for(i=6;i<14;i++){
465     os->header[i]=(unsigned char)(granule_pos&0xff);
466     granule_pos>>=8;
467   }
468 
469   /* 32 bits of stream serial number */
470   {
471     long serialno=os->serialno;
472     for(i=14;i<18;i++){
473       os->header[i]=(unsigned char)(serialno&0xff);
474       serialno>>=8;
475     }
476   }
477 
478   /* 32 bits of page counter (we have both counter and page header
479      because this val can roll over) */
480   if(os->pageno==-1)os->pageno=0; /* because someone called
481                                      stream_reset; this would be a
482                                      strange thing to do in an
483                                      encode stream, but it has
484                                      plausible uses */
485   {
486     long pageno=os->pageno++;
487     for(i=18;i<22;i++){
488       os->header[i]=(unsigned char)(pageno&0xff);
489       pageno>>=8;
490     }
491   }
492 
493   /* zero for computation; filled in later */
494   os->header[22]=0;
495   os->header[23]=0;
496   os->header[24]=0;
497   os->header[25]=0;
498 
499   /* segment table */
500   os->header[26]=(unsigned char)(vals&0xff);
501   for(i=0;i<vals;i++)
502     bytes+=os->header[i+27]=(unsigned char)(os->lacing_vals[i]&0xff);
503 
504   /* set pointers in the ogg_page struct */
505   og->header=os->header;
506   og->header_len=os->header_fill=vals+27;
507   og->body=os->body_data+os->body_returned;
508   og->body_len=bytes;
509 
510   /* advance the lacing data and set the body_returned pointer */
511 
512   os->lacing_fill-=vals;
513   memmove(os->lacing_vals,os->lacing_vals+vals,os->lacing_fill*sizeof(*os->lacing_vals));
514   memmove(os->granule_vals,os->granule_vals+vals,os->lacing_fill*sizeof(*os->granule_vals));
515   os->body_returned+=bytes;
516 
517   /* calculate the checksum */
518 
519   ogg_page_checksum_set(og);
520 
521   /* done */
522   return(1);
523 }
524 
525 /* This will flush remaining packets into a page (returning nonzero),
526    even if there is not enough data to trigger a flush normally
527    (undersized page). If there are no packets or partial packets to
528    flush, ogg_stream_flush returns 0.  Note that ogg_stream_flush will
529    try to flush a normal sized page like ogg_stream_pageout; a call to
530    ogg_stream_flush does not guarantee that all packets have flushed.
531    Only a return value of 0 from ogg_stream_flush indicates all packet
532    data is flushed into pages.
533 
534    since ogg_stream_flush will flush the last page in a stream even if
535    it's undersized, you almost certainly want to use ogg_stream_pageout
536    (and *not* ogg_stream_flush) unless you specifically need to flush
537    a page regardless of size in the middle of a stream. */
538 
ogg_stream_flush(ogg_stream_state * os,ogg_page * og)539 int ogg_stream_flush(ogg_stream_state *os,ogg_page *og){
540   return ogg_stream_flush_i(os,og,1,4096);
541 }
542 
543 /* Like the above, but an argument is provided to adjust the nominal
544    page size for applications which are smart enough to provide their
545    own delay based flushing */
546 
ogg_stream_flush_fill(ogg_stream_state * os,ogg_page * og,int nfill)547 int ogg_stream_flush_fill(ogg_stream_state *os,ogg_page *og, int nfill){
548   return ogg_stream_flush_i(os,og,1,nfill);
549 }
550 
551 /* This constructs pages from buffered packet segments.  The pointers
552 returned are to static buffers; do not free. The returned buffers are
553 good only until the next call (using the same ogg_stream_state) */
554 
ogg_stream_pageout(ogg_stream_state * os,ogg_page * og)555 int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og){
556   int force=0;
557   if(ogg_stream_check(os)) return 0;
558 
559   if((os->e_o_s&&os->lacing_fill) ||          /* 'were done, now flush' case */
560      (os->lacing_fill&&!os->b_o_s))           /* 'initial header page' case */
561     force=1;
562 
563   return(ogg_stream_flush_i(os,og,force,4096));
564 }
565 
566 /* Like the above, but an argument is provided to adjust the nominal
567 page size for applications which are smart enough to provide their
568 own delay based flushing */
569 
ogg_stream_pageout_fill(ogg_stream_state * os,ogg_page * og,int nfill)570 int ogg_stream_pageout_fill(ogg_stream_state *os, ogg_page *og, int nfill){
571   int force=0;
572   if(ogg_stream_check(os)) return 0;
573 
574   if((os->e_o_s&&os->lacing_fill) ||          /* 'were done, now flush' case */
575      (os->lacing_fill&&!os->b_o_s))           /* 'initial header page' case */
576     force=1;
577 
578   return(ogg_stream_flush_i(os,og,force,nfill));
579 }
580 
ogg_stream_eos(ogg_stream_state * os)581 int ogg_stream_eos(ogg_stream_state *os){
582   if(ogg_stream_check(os)) return 1;
583   return os->e_o_s;
584 }
585 
586 /* DECODING PRIMITIVES: packet streaming layer **********************/
587 
588 /* This has two layers to place more of the multi-serialno and paging
589    control in the application's hands.  First, we expose a data buffer
590    using ogg_sync_buffer().  The app either copies into the
591    buffer, or passes it directly to read(), etc.  We then call
592    ogg_sync_wrote() to tell how many bytes we just added.
593 
594    Pages are returned (pointers into the buffer in ogg_sync_state)
595    by ogg_sync_pageout().  The page is then submitted to
596    ogg_stream_pagein() along with the appropriate
597    ogg_stream_state* (ie, matching serialno).  We then get raw
598    packets out calling ogg_stream_packetout() with a
599    ogg_stream_state. */
600 
601 /* initialize the struct to a known state */
ogg_sync_init(ogg_sync_state * oy)602 int ogg_sync_init(ogg_sync_state *oy){
603   if(oy){
604     oy->storage = -1; /* used as a readiness flag */
605     memset(oy,0,sizeof(*oy));
606   }
607   return(0);
608 }
609 
610 /* clear non-flat storage within */
ogg_sync_clear(ogg_sync_state * oy)611 int ogg_sync_clear(ogg_sync_state *oy){
612   if(oy){
613     if(oy->data)_ogg_free(oy->data);
614     memset(oy,0,sizeof(*oy));
615   }
616   return(0);
617 }
618 
ogg_sync_destroy(ogg_sync_state * oy)619 int ogg_sync_destroy(ogg_sync_state *oy){
620   if(oy){
621     ogg_sync_clear(oy);
622     _ogg_free(oy);
623   }
624   return(0);
625 }
626 
ogg_sync_check(ogg_sync_state * oy)627 int ogg_sync_check(ogg_sync_state *oy){
628   if(oy->storage<0) return -1;
629   return 0;
630 }
631 
ogg_sync_buffer(ogg_sync_state * oy,long size)632 char *ogg_sync_buffer(ogg_sync_state *oy, long size){
633   if(ogg_sync_check(oy)) return NULL;
634 
635   /* first, clear out any space that has been previously returned */
636   if(oy->returned){
637     oy->fill-=oy->returned;
638     if(oy->fill>0)
639       memmove(oy->data,oy->data+oy->returned,oy->fill);
640     oy->returned=0;
641   }
642 
643   if(size>oy->storage-oy->fill){
644     /* We need to extend the internal buffer */
645     long newsize=size+oy->fill+4096; /* an extra page to be nice */
646     void *ret;
647 
648     if(oy->data)
649       ret=_ogg_realloc(oy->data,newsize);
650     else
651       ret=_ogg_malloc(newsize);
652     if(!ret){
653       ogg_sync_clear(oy);
654       return NULL;
655     }
656     oy->data=ret;
657     oy->storage=newsize;
658   }
659 
660   /* expose a segment at least as large as requested at the fill mark */
661   return((char *)oy->data+oy->fill);
662 }
663 
ogg_sync_wrote(ogg_sync_state * oy,long bytes)664 int ogg_sync_wrote(ogg_sync_state *oy, long bytes){
665   if(ogg_sync_check(oy))return -1;
666   if(oy->fill+bytes>oy->storage)return -1;
667   oy->fill+=bytes;
668   return(0);
669 }
670 
671 /* sync the stream.  This is meant to be useful for finding page
672    boundaries.
673 
674    return values for this:
675   -n) skipped n bytes
676    0) page not ready; more data (no bytes skipped)
677    n) page synced at current location; page length n bytes
678 
679 */
680 
ogg_sync_pageseek(ogg_sync_state * oy,ogg_page * og)681 long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){
682   unsigned char *page=oy->data+oy->returned;
683   unsigned char *next;
684   long bytes=oy->fill-oy->returned;
685 
686   if(ogg_sync_check(oy))return 0;
687 
688   if(oy->headerbytes==0){
689     int headerbytes,i;
690     if(bytes<27)return(0); /* not enough for a header */
691 
692     /* verify capture pattern */
693     if(memcmp(page,"OggS",4))goto sync_fail;
694 
695     headerbytes=page[26]+27;
696     if(bytes<headerbytes)return(0); /* not enough for header + seg table */
697 
698     /* count up body length in the segment table */
699 
700     for(i=0;i<page[26];i++)
701       oy->bodybytes+=page[27+i];
702     oy->headerbytes=headerbytes;
703   }
704 
705   if(oy->bodybytes+oy->headerbytes>bytes)return(0);
706 
707   /* The whole test page is buffered.  Verify the checksum */
708   {
709     /* Grab the checksum bytes, set the header field to zero */
710     char chksum[4];
711     ogg_page log;
712 
713     memcpy(chksum,page+22,4);
714     memset(page+22,0,4);
715 
716     /* set up a temp page struct and recompute the checksum */
717     log.header=page;
718     log.header_len=oy->headerbytes;
719     log.body=page+oy->headerbytes;
720     log.body_len=oy->bodybytes;
721     ogg_page_checksum_set(&log);
722 
723     /* Compare */
724     if(memcmp(chksum,page+22,4)){
725       /* D'oh.  Mismatch! Corrupt page (or miscapture and not a page
726          at all) */
727       /* replace the computed checksum with the one actually read in */
728       memcpy(page+22,chksum,4);
729 
730       /* Bad checksum. Lose sync */
731       goto sync_fail;
732     }
733   }
734 
735   /* yes, have a whole page all ready to go */
736   {
737     unsigned char *page=oy->data+oy->returned;
738     long bytes;
739 
740     if(og){
741       og->header=page;
742       og->header_len=oy->headerbytes;
743       og->body=page+oy->headerbytes;
744       og->body_len=oy->bodybytes;
745     }
746 
747     oy->unsynced=0;
748     oy->returned+=(bytes=oy->headerbytes+oy->bodybytes);
749     oy->headerbytes=0;
750     oy->bodybytes=0;
751     return(bytes);
752   }
753 
754  sync_fail:
755 
756   oy->headerbytes=0;
757   oy->bodybytes=0;
758 
759   /* search for possible capture */
760   next=memchr(page+1,'O',bytes-1);
761   if(!next)
762     next=oy->data+oy->fill;
763 
764   oy->returned=(int)(next-oy->data);
765   return((long)-(next-page));
766 }
767 
768 /* sync the stream and get a page.  Keep trying until we find a page.
769    Suppress 'sync errors' after reporting the first.
770 
771    return values:
772    -1) recapture (hole in data)
773     0) need more data
774     1) page returned
775 
776    Returns pointers into buffered data; invalidated by next call to
777    _stream, _clear, _init, or _buffer */
778 
ogg_sync_pageout(ogg_sync_state * oy,ogg_page * og)779 int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og){
780 
781   if(ogg_sync_check(oy))return 0;
782 
783   /* all we need to do is verify a page at the head of the stream
784      buffer.  If it doesn't verify, we look for the next potential
785      frame */
786 
787   for(;;){
788     long ret=ogg_sync_pageseek(oy,og);
789     if(ret>0){
790       /* have a page */
791       return(1);
792     }
793     if(ret==0){
794       /* need more data */
795       return(0);
796     }
797 
798     /* head did not start a synced page... skipped some bytes */
799     if(!oy->unsynced){
800       oy->unsynced=1;
801       return(-1);
802     }
803 
804     /* loop. keep looking */
805 
806   }
807 }
808 
809 /* add the incoming page to the stream state; we decompose the page
810    into packet segments here as well. */
811 
ogg_stream_pagein(ogg_stream_state * os,ogg_page * og)812 int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){
813   unsigned char *header=og->header;
814   unsigned char *body=og->body;
815   long           bodysize=og->body_len;
816   int            segptr=0;
817 
818   int version=ogg_page_version(og);
819   int continued=ogg_page_continued(og);
820   int bos=ogg_page_bos(og);
821   int eos=ogg_page_eos(og);
822   ogg_int64_t granulepos=ogg_page_granulepos(og);
823   int serialno=ogg_page_serialno(og);
824   long pageno=ogg_page_pageno(og);
825   int segments=header[26];
826 
827   if(ogg_stream_check(os)) return -1;
828 
829   /* clean up 'returned data' */
830   {
831     long lr=os->lacing_returned;
832     long br=os->body_returned;
833 
834     /* body data */
835     if(br){
836       os->body_fill-=br;
837       if(os->body_fill)
838         memmove(os->body_data,os->body_data+br,os->body_fill);
839       os->body_returned=0;
840     }
841 
842     if(lr){
843       /* segment table */
844       if(os->lacing_fill-lr){
845         memmove(os->lacing_vals,os->lacing_vals+lr,
846                 (os->lacing_fill-lr)*sizeof(*os->lacing_vals));
847         memmove(os->granule_vals,os->granule_vals+lr,
848                 (os->lacing_fill-lr)*sizeof(*os->granule_vals));
849       }
850       os->lacing_fill-=lr;
851       os->lacing_packet-=lr;
852       os->lacing_returned=0;
853     }
854   }
855 
856   /* check the serial number */
857   if(serialno!=os->serialno)return(-1);
858   if(version>0)return(-1);
859 
860   if(_os_lacing_expand(os,segments+1)) return -1;
861 
862   /* are we in sequence? */
863   if(pageno!=os->pageno){
864     int i;
865 
866     /* unroll previous partial packet (if any) */
867     for(i=os->lacing_packet;i<os->lacing_fill;i++)
868       os->body_fill-=os->lacing_vals[i]&0xff;
869     os->lacing_fill=os->lacing_packet;
870 
871     /* make a note of dropped data in segment table */
872     if(os->pageno!=-1){
873       os->lacing_vals[os->lacing_fill++]=0x400;
874       os->lacing_packet++;
875     }
876   }
877 
878   /* are we a 'continued packet' page?  If so, we may need to skip
879      some segments */
880   if(continued){
881     if(os->lacing_fill<1 ||
882        (os->lacing_vals[os->lacing_fill-1]&0xff)<255 ||
883        os->lacing_vals[os->lacing_fill-1]==0x400){
884       bos=0;
885       for(;segptr<segments;segptr++){
886         int val=header[27+segptr];
887         body+=val;
888         bodysize-=val;
889         if(val<255){
890           segptr++;
891           break;
892         }
893       }
894     }
895   }
896 
897   if(bodysize){
898     if(_os_body_expand(os,bodysize)) return -1;
899     memcpy(os->body_data+os->body_fill,body,bodysize);
900     os->body_fill+=bodysize;
901   }
902 
903   {
904     int saved=-1;
905     while(segptr<segments){
906       int val=header[27+segptr];
907       os->lacing_vals[os->lacing_fill]=val;
908       os->granule_vals[os->lacing_fill]=-1;
909 
910       if(bos){
911         os->lacing_vals[os->lacing_fill]|=0x100;
912         bos=0;
913       }
914 
915       if(val<255)saved=os->lacing_fill;
916 
917       os->lacing_fill++;
918       segptr++;
919 
920       if(val<255)os->lacing_packet=os->lacing_fill;
921     }
922 
923     /* set the granulepos on the last granuleval of the last full packet */
924     if(saved!=-1){
925       os->granule_vals[saved]=granulepos;
926     }
927 
928   }
929 
930   if(eos){
931     os->e_o_s=1;
932     if(os->lacing_fill>0)
933       os->lacing_vals[os->lacing_fill-1]|=0x200;
934   }
935 
936   os->pageno=pageno+1;
937 
938   return(0);
939 }
940 
941 /* clear things to an initial state.  Good to call, eg, before seeking */
ogg_sync_reset(ogg_sync_state * oy)942 int ogg_sync_reset(ogg_sync_state *oy){
943   if(ogg_sync_check(oy))return -1;
944 
945   oy->fill=0;
946   oy->returned=0;
947   oy->unsynced=0;
948   oy->headerbytes=0;
949   oy->bodybytes=0;
950   return(0);
951 }
952 
ogg_stream_reset(ogg_stream_state * os)953 int ogg_stream_reset(ogg_stream_state *os){
954   if(ogg_stream_check(os)) return -1;
955 
956   os->body_fill=0;
957   os->body_returned=0;
958 
959   os->lacing_fill=0;
960   os->lacing_packet=0;
961   os->lacing_returned=0;
962 
963   os->header_fill=0;
964 
965   os->e_o_s=0;
966   os->b_o_s=0;
967   os->pageno=-1;
968   os->packetno=0;
969   os->granulepos=0;
970 
971   return(0);
972 }
973 
ogg_stream_reset_serialno(ogg_stream_state * os,int serialno)974 int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno){
975   if(ogg_stream_check(os)) return -1;
976   ogg_stream_reset(os);
977   os->serialno=serialno;
978   return(0);
979 }
980 
_packetout(ogg_stream_state * os,ogg_packet * op,int adv)981 static int _packetout(ogg_stream_state *os,ogg_packet *op,int adv){
982 
983   /* The last part of decode. We have the stream broken into packet
984      segments.  Now we need to group them into packets (or return the
985      out of sync markers) */
986 
987   int ptr=os->lacing_returned;
988 
989   if(os->lacing_packet<=ptr)return(0);
990 
991   if(os->lacing_vals[ptr]&0x400){
992     /* we need to tell the codec there's a gap; it might need to
993        handle previous packet dependencies. */
994     os->lacing_returned++;
995     os->packetno++;
996     return(-1);
997   }
998 
999   if(!op && !adv)return(1); /* just using peek as an inexpensive way
1000                                to ask if there's a whole packet
1001                                waiting */
1002 
1003   /* Gather the whole packet. We'll have no holes or a partial packet */
1004   {
1005     int size=os->lacing_vals[ptr]&0xff;
1006     long bytes=size;
1007     int eos=os->lacing_vals[ptr]&0x200; /* last packet of the stream? */
1008     int bos=os->lacing_vals[ptr]&0x100; /* first packet of the stream? */
1009 
1010     while(size==255){
1011       int val=os->lacing_vals[++ptr];
1012       size=val&0xff;
1013       if(val&0x200)eos=0x200;
1014       bytes+=size;
1015     }
1016 
1017     if(op){
1018       op->e_o_s=eos;
1019       op->b_o_s=bos;
1020       op->packet=os->body_data+os->body_returned;
1021       op->packetno=os->packetno;
1022       op->granulepos=os->granule_vals[ptr];
1023       op->bytes=bytes;
1024     }
1025 
1026     if(adv){
1027       os->body_returned+=bytes;
1028       os->lacing_returned=ptr+1;
1029       os->packetno++;
1030     }
1031   }
1032   return(1);
1033 }
1034 
ogg_stream_packetout(ogg_stream_state * os,ogg_packet * op)1035 int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op){
1036   if(ogg_stream_check(os)) return 0;
1037   return _packetout(os,op,1);
1038 }
1039 
ogg_stream_packetpeek(ogg_stream_state * os,ogg_packet * op)1040 int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op){
1041   if(ogg_stream_check(os)) return 0;
1042   return _packetout(os,op,0);
1043 }
1044 
ogg_packet_clear(ogg_packet * op)1045 void ogg_packet_clear(ogg_packet *op) {
1046   _ogg_free(op->packet);
1047   memset(op, 0, sizeof(*op));
1048 }
1049 
1050 #ifdef _V_SELFTEST
1051 #include <stdio.h>
1052 
1053 ogg_stream_state os_en, os_de;
1054 ogg_sync_state oy;
1055 
checkpacket(ogg_packet * op,long len,int no,long pos)1056 void checkpacket(ogg_packet *op,long len, int no, long pos){
1057   long j;
1058   static int sequence=0;
1059   static int lastno=0;
1060 
1061   if(op->bytes!=len){
1062     fprintf(stderr,"incorrect packet length (%ld != %ld)!\n",op->bytes,len);
1063     exit(1);
1064   }
1065   if(op->granulepos!=pos){
1066     fprintf(stderr,"incorrect packet granpos (%ld != %ld)!\n",(long)op->granulepos,pos);
1067     exit(1);
1068   }
1069 
1070   /* packet number just follows sequence/gap; adjust the input number
1071      for that */
1072   if(no==0){
1073     sequence=0;
1074   }else{
1075     sequence++;
1076     if(no>lastno+1)
1077       sequence++;
1078   }
1079   lastno=no;
1080   if(op->packetno!=sequence){
1081     fprintf(stderr,"incorrect packet sequence %ld != %d\n",
1082             (long)(op->packetno),sequence);
1083     exit(1);
1084   }
1085 
1086   /* Test data */
1087   for(j=0;j<op->bytes;j++)
1088     if(op->packet[j]!=((j+no)&0xff)){
1089       fprintf(stderr,"body data mismatch (1) at pos %ld: %x!=%lx!\n\n",
1090               j,op->packet[j],(j+no)&0xff);
1091       exit(1);
1092     }
1093 }
1094 
check_page(unsigned char * data,const int * header,ogg_page * og)1095 void check_page(unsigned char *data,const int *header,ogg_page *og){
1096   long j;
1097   /* Test data */
1098   for(j=0;j<og->body_len;j++)
1099     if(og->body[j]!=data[j]){
1100       fprintf(stderr,"body data mismatch (2) at pos %ld: %x!=%x!\n\n",
1101               j,data[j],og->body[j]);
1102       exit(1);
1103     }
1104 
1105   /* Test header */
1106   for(j=0;j<og->header_len;j++){
1107     if(og->header[j]!=header[j]){
1108       fprintf(stderr,"header content mismatch at pos %ld:\n",j);
1109       for(j=0;j<header[26]+27;j++)
1110         fprintf(stderr," (%ld)%02x:%02x",j,header[j],og->header[j]);
1111       fprintf(stderr,"\n");
1112       exit(1);
1113     }
1114   }
1115   if(og->header_len!=header[26]+27){
1116     fprintf(stderr,"header length incorrect! (%ld!=%d)\n",
1117             og->header_len,header[26]+27);
1118     exit(1);
1119   }
1120 }
1121 
print_header(ogg_page * og)1122 void print_header(ogg_page *og){
1123   int j;
1124   fprintf(stderr,"\nHEADER:\n");
1125   fprintf(stderr,"  capture: %c %c %c %c  version: %d  flags: %x\n",
1126           og->header[0],og->header[1],og->header[2],og->header[3],
1127           (int)og->header[4],(int)og->header[5]);
1128 
1129   fprintf(stderr,"  granulepos: %d  serialno: %d  pageno: %ld\n",
1130           (og->header[9]<<24)|(og->header[8]<<16)|
1131           (og->header[7]<<8)|og->header[6],
1132           (og->header[17]<<24)|(og->header[16]<<16)|
1133           (og->header[15]<<8)|og->header[14],
1134           ((long)(og->header[21])<<24)|(og->header[20]<<16)|
1135           (og->header[19]<<8)|og->header[18]);
1136 
1137   fprintf(stderr,"  checksum: %02x:%02x:%02x:%02x\n  segments: %d (",
1138           (int)og->header[22],(int)og->header[23],
1139           (int)og->header[24],(int)og->header[25],
1140           (int)og->header[26]);
1141 
1142   for(j=27;j<og->header_len;j++)
1143     fprintf(stderr,"%d ",(int)og->header[j]);
1144   fprintf(stderr,")\n\n");
1145 }
1146 
copy_page(ogg_page * og)1147 void copy_page(ogg_page *og){
1148   unsigned char *temp=_ogg_malloc(og->header_len);
1149   memcpy(temp,og->header,og->header_len);
1150   og->header=temp;
1151 
1152   temp=_ogg_malloc(og->body_len);
1153   memcpy(temp,og->body,og->body_len);
1154   og->body=temp;
1155 }
1156 
free_page(ogg_page * og)1157 void free_page(ogg_page *og){
1158   _ogg_free (og->header);
1159   _ogg_free (og->body);
1160 }
1161 
error(void)1162 void error(void){
1163   fprintf(stderr,"error!\n");
1164   exit(1);
1165 }
1166 
1167 /* 17 only */
1168 const int head1_0[] = {0x4f,0x67,0x67,0x53,0,0x06,
1169                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1170                        0x01,0x02,0x03,0x04,0,0,0,0,
1171                        0x15,0xed,0xec,0x91,
1172                        1,
1173                        17};
1174 
1175 /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
1176 const int head1_1[] = {0x4f,0x67,0x67,0x53,0,0x02,
1177                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1178                        0x01,0x02,0x03,0x04,0,0,0,0,
1179                        0x59,0x10,0x6c,0x2c,
1180                        1,
1181                        17};
1182 const int head2_1[] = {0x4f,0x67,0x67,0x53,0,0x04,
1183                        0x07,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
1184                        0x01,0x02,0x03,0x04,1,0,0,0,
1185                        0x89,0x33,0x85,0xce,
1186                        13,
1187                        254,255,0,255,1,255,245,255,255,0,
1188                        255,255,90};
1189 
1190 /* nil packets; beginning,middle,end */
1191 const int head1_2[] = {0x4f,0x67,0x67,0x53,0,0x02,
1192                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1193                        0x01,0x02,0x03,0x04,0,0,0,0,
1194                        0xff,0x7b,0x23,0x17,
1195                        1,
1196                        0};
1197 const int head2_2[] = {0x4f,0x67,0x67,0x53,0,0x04,
1198                        0x07,0x28,0x00,0x00,0x00,0x00,0x00,0x00,
1199                        0x01,0x02,0x03,0x04,1,0,0,0,
1200                        0x5c,0x3f,0x66,0xcb,
1201                        17,
1202                        17,254,255,0,0,255,1,0,255,245,255,255,0,
1203                        255,255,90,0};
1204 
1205 /* large initial packet */
1206 const int head1_3[] = {0x4f,0x67,0x67,0x53,0,0x02,
1207                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1208                        0x01,0x02,0x03,0x04,0,0,0,0,
1209                        0x01,0x27,0x31,0xaa,
1210                        18,
1211                        255,255,255,255,255,255,255,255,
1212                        255,255,255,255,255,255,255,255,255,10};
1213 
1214 const int head2_3[] = {0x4f,0x67,0x67,0x53,0,0x04,
1215                        0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
1216                        0x01,0x02,0x03,0x04,1,0,0,0,
1217                        0x7f,0x4e,0x8a,0xd2,
1218                        4,
1219                        255,4,255,0};
1220 
1221 
1222 /* continuing packet test */
1223 const int head1_4[] = {0x4f,0x67,0x67,0x53,0,0x02,
1224                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1225                        0x01,0x02,0x03,0x04,0,0,0,0,
1226                        0xff,0x7b,0x23,0x17,
1227                        1,
1228                        0};
1229 
1230 const int head2_4[] = {0x4f,0x67,0x67,0x53,0,0x00,
1231                        0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
1232                        0x01,0x02,0x03,0x04,1,0,0,0,
1233                        0xf8,0x3c,0x19,0x79,
1234                        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,255,
1262                        255,255,255,255,255,255,255,255,
1263                        255,255,255,255,255,255,255,255,
1264                        255,255,255,255,255,255,255,255,
1265                        255,255,255,255,255,255,255,255,
1266                        255,255,255,255,255,255,255};
1267 
1268 const int head3_4[] = {0x4f,0x67,0x67,0x53,0,0x05,
1269                        0x07,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,
1270                        0x01,0x02,0x03,0x04,2,0,0,0,
1271                        0x38,0xe6,0xb6,0x28,
1272                        6,
1273                        255,220,255,4,255,0};
1274 
1275 
1276 /* spill expansion test */
1277 const int head1_4b[] = {0x4f,0x67,0x67,0x53,0,0x02,
1278                         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1279                         0x01,0x02,0x03,0x04,0,0,0,0,
1280                         0xff,0x7b,0x23,0x17,
1281                         1,
1282                         0};
1283 
1284 const int head2_4b[] = {0x4f,0x67,0x67,0x53,0,0x00,
1285                         0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
1286                         0x01,0x02,0x03,0x04,1,0,0,0,
1287                         0xce,0x8f,0x17,0x1a,
1288                         23,
1289                         255,255,255,255,255,255,255,255,
1290                         255,255,255,255,255,255,255,255,255,10,255,4,255,0,0};
1291 
1292 
1293 const int head3_4b[] = {0x4f,0x67,0x67,0x53,0,0x04,
1294                         0x07,0x14,0x00,0x00,0x00,0x00,0x00,0x00,
1295                         0x01,0x02,0x03,0x04,2,0,0,0,
1296                         0x9b,0xb2,0x50,0xa1,
1297                         1,
1298                         0};
1299 
1300 /* page with the 255 segment limit */
1301 const int head1_5[] = {0x4f,0x67,0x67,0x53,0,0x02,
1302                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1303                        0x01,0x02,0x03,0x04,0,0,0,0,
1304                        0xff,0x7b,0x23,0x17,
1305                        1,
1306                        0};
1307 
1308 const int head2_5[] = {0x4f,0x67,0x67,0x53,0,0x00,
1309                        0x07,0xfc,0x03,0x00,0x00,0x00,0x00,0x00,
1310                        0x01,0x02,0x03,0x04,1,0,0,0,
1311                        0xed,0x2a,0x2e,0xa7,
1312                        255,
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,10,
1340                        10,10,10,10,10,10,10,10,
1341                        10,10,10,10,10,10,10,10,
1342                        10,10,10,10,10,10,10,10,
1343                        10,10,10,10,10,10,10,10,
1344                        10,10,10,10,10,10,10};
1345 
1346 const int head3_5[] = {0x4f,0x67,0x67,0x53,0,0x04,
1347                        0x07,0x00,0x04,0x00,0x00,0x00,0x00,0x00,
1348                        0x01,0x02,0x03,0x04,2,0,0,0,
1349                        0x6c,0x3b,0x82,0x3d,
1350                        1,
1351                        50};
1352 
1353 
1354 /* packet that overspans over an entire page */
1355 const int head1_6[] = {0x4f,0x67,0x67,0x53,0,0x02,
1356                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1357                        0x01,0x02,0x03,0x04,0,0,0,0,
1358                        0xff,0x7b,0x23,0x17,
1359                        1,
1360                        0};
1361 
1362 const int head2_6[] = {0x4f,0x67,0x67,0x53,0,0x00,
1363                        0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
1364                        0x01,0x02,0x03,0x04,1,0,0,0,
1365                        0x68,0x22,0x7c,0x3d,
1366                        255,
1367                        100,
1368                        255,255,255,255,255,255,255,255,
1369                        255,255,255,255,255,255,255,255,
1370                        255,255,255,255,255,255,255,255,
1371                        255,255,255,255,255,255,255,255,
1372                        255,255,255,255,255,255,255,255,
1373                        255,255,255,255,255,255,255,255,
1374                        255,255,255,255,255,255,255,255,
1375                        255,255,255,255,255,255,255,255,
1376                        255,255,255,255,255,255,255,255,
1377                        255,255,255,255,255,255,255,255,
1378                        255,255,255,255,255,255,255,255,
1379                        255,255,255,255,255,255,255,255,
1380                        255,255,255,255,255,255,255,255,
1381                        255,255,255,255,255,255,255,255,
1382                        255,255,255,255,255,255,255,255,
1383                        255,255,255,255,255,255,255,255,
1384                        255,255,255,255,255,255,255,255,
1385                        255,255,255,255,255,255,255,255,
1386                        255,255,255,255,255,255,255,255,
1387                        255,255,255,255,255,255,255,255,
1388                        255,255,255,255,255,255,255,255,
1389                        255,255,255,255,255,255,255,255,
1390                        255,255,255,255,255,255,255,255,
1391                        255,255,255,255,255,255,255,255,
1392                        255,255,255,255,255,255,255,255,
1393                        255,255,255,255,255,255,255,255,
1394                        255,255,255,255,255,255,255,255,
1395                        255,255,255,255,255,255,255,255,
1396                        255,255,255,255,255,255,255,255,
1397                        255,255,255,255,255,255,255,255,
1398                        255,255,255,255,255,255,255,255,
1399                        255,255,255,255,255,255};
1400 
1401 const int head3_6[] = {0x4f,0x67,0x67,0x53,0,0x01,
1402                        0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
1403                        0x01,0x02,0x03,0x04,2,0,0,0,
1404                        0xf4,0x87,0xba,0xf3,
1405                        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,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};
1438 
1439 const int head4_6[] = {0x4f,0x67,0x67,0x53,0,0x05,
1440                        0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
1441                        0x01,0x02,0x03,0x04,3,0,0,0,
1442                        0xf7,0x2f,0x6c,0x60,
1443                        5,
1444                        254,255,4,255,0};
1445 
1446 /* packet that overspans over an entire page */
1447 const int head1_7[] = {0x4f,0x67,0x67,0x53,0,0x02,
1448                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1449                        0x01,0x02,0x03,0x04,0,0,0,0,
1450                        0xff,0x7b,0x23,0x17,
1451                        1,
1452                        0};
1453 
1454 const int head2_7[] = {0x4f,0x67,0x67,0x53,0,0x00,
1455                        0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
1456                        0x01,0x02,0x03,0x04,1,0,0,0,
1457                        0x68,0x22,0x7c,0x3d,
1458                        255,
1459                        100,
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,255,255,
1487                        255,255,255,255,255,255,255,255,
1488                        255,255,255,255,255,255,255,255,
1489                        255,255,255,255,255,255,255,255,
1490                        255,255,255,255,255,255,255,255,
1491                        255,255,255,255,255,255};
1492 
1493 const int head3_7[] = {0x4f,0x67,0x67,0x53,0,0x05,
1494                        0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
1495                        0x01,0x02,0x03,0x04,2,0,0,0,
1496                        0xd4,0xe0,0x60,0xe5,
1497                        1,
1498                        0};
1499 
compare_packet(const ogg_packet * op1,const ogg_packet * op2)1500 int compare_packet(const ogg_packet *op1, const ogg_packet *op2){
1501   if(op1->packet!=op2->packet){
1502     fprintf(stderr,"op1->packet != op2->packet\n");
1503     return(1);
1504   }
1505   if(op1->bytes!=op2->bytes){
1506     fprintf(stderr,"op1->bytes != op2->bytes\n");
1507     return(1);
1508   }
1509   if(op1->b_o_s!=op2->b_o_s){
1510     fprintf(stderr,"op1->b_o_s != op2->b_o_s\n");
1511     return(1);
1512   }
1513   if(op1->e_o_s!=op2->e_o_s){
1514     fprintf(stderr,"op1->e_o_s != op2->e_o_s\n");
1515     return(1);
1516   }
1517   if(op1->granulepos!=op2->granulepos){
1518     fprintf(stderr,"op1->granulepos != op2->granulepos\n");
1519     return(1);
1520   }
1521   if(op1->packetno!=op2->packetno){
1522     fprintf(stderr,"op1->packetno != op2->packetno\n");
1523     return(1);
1524   }
1525   return(0);
1526 }
1527 
test_pack(const int * pl,const int ** headers,int byteskip,int pageskip,int packetskip)1528 void test_pack(const int *pl, const int **headers, int byteskip,
1529                int pageskip, int packetskip){
1530   unsigned char *data=_ogg_malloc(1024*1024); /* for scripted test cases only */
1531   long inptr=0;
1532   long outptr=0;
1533   long deptr=0;
1534   long depacket=0;
1535   long granule_pos=7,pageno=0;
1536   int i,j,packets,pageout=pageskip;
1537   int eosflag=0;
1538   int bosflag=0;
1539 
1540   int byteskipcount=0;
1541 
1542   ogg_stream_reset(&os_en);
1543   ogg_stream_reset(&os_de);
1544   ogg_sync_reset(&oy);
1545 
1546   for(packets=0;packets<packetskip;packets++)
1547     depacket+=pl[packets];
1548 
1549   for(packets=0;;packets++)if(pl[packets]==-1)break;
1550 
1551   for(i=0;i<packets;i++){
1552     /* construct a test packet */
1553     ogg_packet op;
1554     int len=pl[i];
1555 
1556     op.packet=data+inptr;
1557     op.bytes=len;
1558     op.e_o_s=(pl[i+1]<0?1:0);
1559     op.granulepos=granule_pos;
1560 
1561     granule_pos+=1024;
1562 
1563     for(j=0;j<len;j++)data[inptr++]=i+j;
1564 
1565     /* submit the test packet */
1566     ogg_stream_packetin(&os_en,&op);
1567 
1568     /* retrieve any finished pages */
1569     {
1570       ogg_page og;
1571 
1572       while(ogg_stream_pageout(&os_en,&og)){
1573         /* We have a page.  Check it carefully */
1574 
1575         fprintf(stderr,"%ld, ",pageno);
1576 
1577         if(headers[pageno]==NULL){
1578           fprintf(stderr,"coded too many pages!\n");
1579           exit(1);
1580         }
1581 
1582         check_page(data+outptr,headers[pageno],&og);
1583 
1584         outptr+=og.body_len;
1585         pageno++;
1586         if(pageskip){
1587           bosflag=1;
1588           pageskip--;
1589           deptr+=og.body_len;
1590         }
1591 
1592         /* have a complete page; submit it to sync/decode */
1593 
1594         {
1595           ogg_page og_de;
1596           ogg_packet op_de,op_de2;
1597           char *buf=ogg_sync_buffer(&oy,og.header_len+og.body_len);
1598           char *next=buf;
1599           byteskipcount+=og.header_len;
1600           if(byteskipcount>byteskip){
1601             memcpy(next,og.header,byteskipcount-byteskip);
1602             next+=byteskipcount-byteskip;
1603             byteskipcount=byteskip;
1604           }
1605 
1606           byteskipcount+=og.body_len;
1607           if(byteskipcount>byteskip){
1608             memcpy(next,og.body,byteskipcount-byteskip);
1609             next+=byteskipcount-byteskip;
1610             byteskipcount=byteskip;
1611           }
1612 
1613           ogg_sync_wrote(&oy,next-buf);
1614 
1615           while(1){
1616             int ret=ogg_sync_pageout(&oy,&og_de);
1617             if(ret==0)break;
1618             if(ret<0)continue;
1619             /* got a page.  Happy happy.  Verify that it's good. */
1620 
1621             fprintf(stderr,"(%d), ",pageout);
1622 
1623             check_page(data+deptr,headers[pageout],&og_de);
1624             deptr+=og_de.body_len;
1625             pageout++;
1626 
1627             /* submit it to deconstitution */
1628             ogg_stream_pagein(&os_de,&og_de);
1629 
1630             /* packets out? */
1631             while(ogg_stream_packetpeek(&os_de,&op_de2)>0){
1632               ogg_stream_packetpeek(&os_de,NULL);
1633               ogg_stream_packetout(&os_de,&op_de); /* just catching them all */
1634 
1635               /* verify peek and out match */
1636               if(compare_packet(&op_de,&op_de2)){
1637                 fprintf(stderr,"packetout != packetpeek! pos=%ld\n",
1638                         depacket);
1639                 exit(1);
1640               }
1641 
1642               /* verify the packet! */
1643               /* check data */
1644               if(memcmp(data+depacket,op_de.packet,op_de.bytes)){
1645                 fprintf(stderr,"packet data mismatch in decode! pos=%ld\n",
1646                         depacket);
1647                 exit(1);
1648               }
1649               /* check bos flag */
1650               if(bosflag==0 && op_de.b_o_s==0){
1651                 fprintf(stderr,"b_o_s flag not set on packet!\n");
1652                 exit(1);
1653               }
1654               if(bosflag && op_de.b_o_s){
1655                 fprintf(stderr,"b_o_s flag incorrectly set on packet!\n");
1656                 exit(1);
1657               }
1658               bosflag=1;
1659               depacket+=op_de.bytes;
1660 
1661               /* check eos flag */
1662               if(eosflag){
1663                 fprintf(stderr,"Multiple decoded packets with eos flag!\n");
1664                 exit(1);
1665               }
1666 
1667               if(op_de.e_o_s)eosflag=1;
1668 
1669               /* check granulepos flag */
1670               if(op_de.granulepos!=-1){
1671                 fprintf(stderr," granule:%ld ",(long)op_de.granulepos);
1672               }
1673             }
1674           }
1675         }
1676       }
1677     }
1678   }
1679   _ogg_free(data);
1680   if(headers[pageno]!=NULL){
1681     fprintf(stderr,"did not write last page!\n");
1682     exit(1);
1683   }
1684   if(headers[pageout]!=NULL){
1685     fprintf(stderr,"did not decode last page!\n");
1686     exit(1);
1687   }
1688   if(inptr!=outptr){
1689     fprintf(stderr,"encoded page data incomplete!\n");
1690     exit(1);
1691   }
1692   if(inptr!=deptr){
1693     fprintf(stderr,"decoded page data incomplete!\n");
1694     exit(1);
1695   }
1696   if(inptr!=depacket){
1697     fprintf(stderr,"decoded packet data incomplete!\n");
1698     exit(1);
1699   }
1700   if(!eosflag){
1701     fprintf(stderr,"Never got a packet with EOS set!\n");
1702     exit(1);
1703   }
1704   fprintf(stderr,"ok.\n");
1705 }
1706 
main(void)1707 int main(void){
1708 
1709   ogg_stream_init(&os_en,0x04030201);
1710   ogg_stream_init(&os_de,0x04030201);
1711   ogg_sync_init(&oy);
1712 
1713   /* Exercise each code path in the framing code.  Also verify that
1714      the checksums are working.  */
1715 
1716   {
1717     /* 17 only */
1718     const int packets[]={17, -1};
1719     const int *headret[]={head1_0,NULL};
1720 
1721     fprintf(stderr,"testing single page encoding... ");
1722     test_pack(packets,headret,0,0,0);
1723   }
1724 
1725   {
1726     /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
1727     const int packets[]={17, 254, 255, 256, 500, 510, 600, -1};
1728     const int *headret[]={head1_1,head2_1,NULL};
1729 
1730     fprintf(stderr,"testing basic page encoding... ");
1731     test_pack(packets,headret,0,0,0);
1732   }
1733 
1734   {
1735     /* nil packets; beginning,middle,end */
1736     const int packets[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1};
1737     const int *headret[]={head1_2,head2_2,NULL};
1738 
1739     fprintf(stderr,"testing basic nil packets... ");
1740     test_pack(packets,headret,0,0,0);
1741   }
1742 
1743   {
1744     /* large initial packet */
1745     const int packets[]={4345,259,255,-1};
1746     const int *headret[]={head1_3,head2_3,NULL};
1747 
1748     fprintf(stderr,"testing initial-packet lacing > 4k... ");
1749     test_pack(packets,headret,0,0,0);
1750   }
1751 
1752   {
1753     /* continuing packet test; with page spill expansion, we have to
1754        overflow the lacing table. */
1755     const int packets[]={0,65500,259,255,-1};
1756     const int *headret[]={head1_4,head2_4,head3_4,NULL};
1757 
1758     fprintf(stderr,"testing single packet page span... ");
1759     test_pack(packets,headret,0,0,0);
1760   }
1761 
1762   {
1763     /* spill expand packet test */
1764     const int packets[]={0,4345,259,255,0,0,-1};
1765     const int *headret[]={head1_4b,head2_4b,head3_4b,NULL};
1766 
1767     fprintf(stderr,"testing page spill expansion... ");
1768     test_pack(packets,headret,0,0,0);
1769   }
1770 
1771   /* page with the 255 segment limit */
1772   {
1773 
1774     const int packets[]={0,10,10,10,10,10,10,10,10,
1775                    10,10,10,10,10,10,10,10,
1776                    10,10,10,10,10,10,10,10,
1777                    10,10,10,10,10,10,10,10,
1778                    10,10,10,10,10,10,10,10,
1779                    10,10,10,10,10,10,10,10,
1780                    10,10,10,10,10,10,10,10,
1781                    10,10,10,10,10,10,10,10,
1782                    10,10,10,10,10,10,10,10,
1783                    10,10,10,10,10,10,10,10,
1784                    10,10,10,10,10,10,10,10,
1785                    10,10,10,10,10,10,10,10,
1786                    10,10,10,10,10,10,10,10,
1787                    10,10,10,10,10,10,10,10,
1788                    10,10,10,10,10,10,10,10,
1789                    10,10,10,10,10,10,10,10,
1790                    10,10,10,10,10,10,10,10,
1791                    10,10,10,10,10,10,10,10,
1792                    10,10,10,10,10,10,10,10,
1793                    10,10,10,10,10,10,10,10,
1794                    10,10,10,10,10,10,10,10,
1795                    10,10,10,10,10,10,10,10,
1796                    10,10,10,10,10,10,10,10,
1797                    10,10,10,10,10,10,10,10,
1798                    10,10,10,10,10,10,10,10,
1799                    10,10,10,10,10,10,10,10,
1800                    10,10,10,10,10,10,10,10,
1801                    10,10,10,10,10,10,10,10,
1802                    10,10,10,10,10,10,10,10,
1803                    10,10,10,10,10,10,10,10,
1804                    10,10,10,10,10,10,10,10,
1805                    10,10,10,10,10,10,10,50,-1};
1806     const int *headret[]={head1_5,head2_5,head3_5,NULL};
1807 
1808     fprintf(stderr,"testing max packet segments... ");
1809     test_pack(packets,headret,0,0,0);
1810   }
1811 
1812   {
1813     /* packet that overspans over an entire page */
1814     const int packets[]={0,100,130049,259,255,-1};
1815     const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
1816 
1817     fprintf(stderr,"testing very large packets... ");
1818     test_pack(packets,headret,0,0,0);
1819   }
1820 
1821   {
1822     /* test for the libogg 1.1.1 resync in large continuation bug
1823        found by Josh Coalson)  */
1824     const int packets[]={0,100,130049,259,255,-1};
1825     const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
1826 
1827     fprintf(stderr,"testing continuation resync in very large packets... ");
1828     test_pack(packets,headret,100,2,3);
1829   }
1830 
1831   {
1832     /* term only page.  why not? */
1833     const int packets[]={0,100,64770,-1};
1834     const int *headret[]={head1_7,head2_7,head3_7,NULL};
1835 
1836     fprintf(stderr,"testing zero data page (1 nil packet)... ");
1837     test_pack(packets,headret,0,0,0);
1838   }
1839 
1840 
1841 
1842   {
1843     /* build a bunch of pages for testing */
1844     unsigned char *data=_ogg_malloc(1024*1024);
1845     int pl[]={0, 1,1,98,4079, 1,1,2954,2057, 76,34,912,0,234,1000,1000, 1000,300,-1};
1846     int inptr=0,i,j;
1847     ogg_page og[5];
1848 
1849     ogg_stream_reset(&os_en);
1850 
1851     for(i=0;pl[i]!=-1;i++){
1852       ogg_packet op;
1853       int len=pl[i];
1854 
1855       op.packet=data+inptr;
1856       op.bytes=len;
1857       op.e_o_s=(pl[i+1]<0?1:0);
1858       op.granulepos=(i+1)*1000;
1859 
1860       for(j=0;j<len;j++)data[inptr++]=i+j;
1861       ogg_stream_packetin(&os_en,&op);
1862     }
1863 
1864     _ogg_free(data);
1865 
1866     /* retrieve finished pages */
1867     for(i=0;i<5;i++){
1868       if(ogg_stream_pageout(&os_en,&og[i])==0){
1869         fprintf(stderr,"Too few pages output building sync tests!\n");
1870         exit(1);
1871       }
1872       copy_page(&og[i]);
1873     }
1874 
1875     /* Test lost pages on pagein/packetout: no rollback */
1876     {
1877       ogg_page temp;
1878       ogg_packet test;
1879 
1880       fprintf(stderr,"Testing loss of pages... ");
1881 
1882       ogg_sync_reset(&oy);
1883       ogg_stream_reset(&os_de);
1884       for(i=0;i<5;i++){
1885         memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
1886                og[i].header_len);
1887         ogg_sync_wrote(&oy,og[i].header_len);
1888         memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
1889         ogg_sync_wrote(&oy,og[i].body_len);
1890       }
1891 
1892       ogg_sync_pageout(&oy,&temp);
1893       ogg_stream_pagein(&os_de,&temp);
1894       ogg_sync_pageout(&oy,&temp);
1895       ogg_stream_pagein(&os_de,&temp);
1896       ogg_sync_pageout(&oy,&temp);
1897       /* skip */
1898       ogg_sync_pageout(&oy,&temp);
1899       ogg_stream_pagein(&os_de,&temp);
1900 
1901       /* do we get the expected results/packets? */
1902 
1903       if(ogg_stream_packetout(&os_de,&test)!=1)error();
1904       checkpacket(&test,0,0,0);
1905       if(ogg_stream_packetout(&os_de,&test)!=1)error();
1906       checkpacket(&test,1,1,-1);
1907       if(ogg_stream_packetout(&os_de,&test)!=1)error();
1908       checkpacket(&test,1,2,-1);
1909       if(ogg_stream_packetout(&os_de,&test)!=1)error();
1910       checkpacket(&test,98,3,-1);
1911       if(ogg_stream_packetout(&os_de,&test)!=1)error();
1912       checkpacket(&test,4079,4,5000);
1913       if(ogg_stream_packetout(&os_de,&test)!=-1){
1914         fprintf(stderr,"Error: loss of page did not return error\n");
1915         exit(1);
1916       }
1917       if(ogg_stream_packetout(&os_de,&test)!=1)error();
1918       checkpacket(&test,76,9,-1);
1919       if(ogg_stream_packetout(&os_de,&test)!=1)error();
1920       checkpacket(&test,34,10,-1);
1921       fprintf(stderr,"ok.\n");
1922     }
1923 
1924     /* Test lost pages on pagein/packetout: rollback with continuation */
1925     {
1926       ogg_page temp;
1927       ogg_packet test;
1928 
1929       fprintf(stderr,"Testing loss of pages (rollback required)... ");
1930 
1931       ogg_sync_reset(&oy);
1932       ogg_stream_reset(&os_de);
1933       for(i=0;i<5;i++){
1934         memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
1935                og[i].header_len);
1936         ogg_sync_wrote(&oy,og[i].header_len);
1937         memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
1938         ogg_sync_wrote(&oy,og[i].body_len);
1939       }
1940 
1941       ogg_sync_pageout(&oy,&temp);
1942       ogg_stream_pagein(&os_de,&temp);
1943       ogg_sync_pageout(&oy,&temp);
1944       ogg_stream_pagein(&os_de,&temp);
1945       ogg_sync_pageout(&oy,&temp);
1946       ogg_stream_pagein(&os_de,&temp);
1947       ogg_sync_pageout(&oy,&temp);
1948       /* skip */
1949       ogg_sync_pageout(&oy,&temp);
1950       ogg_stream_pagein(&os_de,&temp);
1951 
1952       /* do we get the expected results/packets? */
1953 
1954       if(ogg_stream_packetout(&os_de,&test)!=1)error();
1955       checkpacket(&test,0,0,0);
1956       if(ogg_stream_packetout(&os_de,&test)!=1)error();
1957       checkpacket(&test,1,1,-1);
1958       if(ogg_stream_packetout(&os_de,&test)!=1)error();
1959       checkpacket(&test,1,2,-1);
1960       if(ogg_stream_packetout(&os_de,&test)!=1)error();
1961       checkpacket(&test,98,3,-1);
1962       if(ogg_stream_packetout(&os_de,&test)!=1)error();
1963       checkpacket(&test,4079,4,5000);
1964       if(ogg_stream_packetout(&os_de,&test)!=1)error();
1965       checkpacket(&test,1,5,-1);
1966       if(ogg_stream_packetout(&os_de,&test)!=1)error();
1967       checkpacket(&test,1,6,-1);
1968       if(ogg_stream_packetout(&os_de,&test)!=1)error();
1969       checkpacket(&test,2954,7,-1);
1970       if(ogg_stream_packetout(&os_de,&test)!=1)error();
1971       checkpacket(&test,2057,8,9000);
1972       if(ogg_stream_packetout(&os_de,&test)!=-1){
1973         fprintf(stderr,"Error: loss of page did not return error\n");
1974         exit(1);
1975       }
1976       if(ogg_stream_packetout(&os_de,&test)!=1)error();
1977       checkpacket(&test,300,17,18000);
1978       fprintf(stderr,"ok.\n");
1979     }
1980 
1981     /* the rest only test sync */
1982     {
1983       ogg_page og_de;
1984       /* Test fractional page inputs: incomplete capture */
1985       fprintf(stderr,"Testing sync on partial inputs... ");
1986       ogg_sync_reset(&oy);
1987       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
1988              3);
1989       ogg_sync_wrote(&oy,3);
1990       if(ogg_sync_pageout(&oy,&og_de)>0)error();
1991 
1992       /* Test fractional page inputs: incomplete fixed header */
1993       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+3,
1994              20);
1995       ogg_sync_wrote(&oy,20);
1996       if(ogg_sync_pageout(&oy,&og_de)>0)error();
1997 
1998       /* Test fractional page inputs: incomplete header */
1999       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+23,
2000              5);
2001       ogg_sync_wrote(&oy,5);
2002       if(ogg_sync_pageout(&oy,&og_de)>0)error();
2003 
2004       /* Test fractional page inputs: incomplete body */
2005 
2006       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+28,
2007              og[1].header_len-28);
2008       ogg_sync_wrote(&oy,og[1].header_len-28);
2009       if(ogg_sync_pageout(&oy,&og_de)>0)error();
2010 
2011       memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,1000);
2012       ogg_sync_wrote(&oy,1000);
2013       if(ogg_sync_pageout(&oy,&og_de)>0)error();
2014 
2015       memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body+1000,
2016              og[1].body_len-1000);
2017       ogg_sync_wrote(&oy,og[1].body_len-1000);
2018       if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2019 
2020       fprintf(stderr,"ok.\n");
2021     }
2022 
2023     /* Test fractional page inputs: page + incomplete capture */
2024     {
2025       ogg_page og_de;
2026       fprintf(stderr,"Testing sync on 1+partial inputs... ");
2027       ogg_sync_reset(&oy);
2028 
2029       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
2030              og[1].header_len);
2031       ogg_sync_wrote(&oy,og[1].header_len);
2032 
2033       memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2034              og[1].body_len);
2035       ogg_sync_wrote(&oy,og[1].body_len);
2036 
2037       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
2038              20);
2039       ogg_sync_wrote(&oy,20);
2040       if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2041       if(ogg_sync_pageout(&oy,&og_de)>0)error();
2042 
2043       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+20,
2044              og[1].header_len-20);
2045       ogg_sync_wrote(&oy,og[1].header_len-20);
2046       memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2047              og[1].body_len);
2048       ogg_sync_wrote(&oy,og[1].body_len);
2049       if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2050 
2051       fprintf(stderr,"ok.\n");
2052     }
2053 
2054     /* Test recapture: garbage + page */
2055     {
2056       ogg_page og_de;
2057       fprintf(stderr,"Testing search for capture... ");
2058       ogg_sync_reset(&oy);
2059 
2060       /* 'garbage' */
2061       memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2062              og[1].body_len);
2063       ogg_sync_wrote(&oy,og[1].body_len);
2064 
2065       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
2066              og[1].header_len);
2067       ogg_sync_wrote(&oy,og[1].header_len);
2068 
2069       memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2070              og[1].body_len);
2071       ogg_sync_wrote(&oy,og[1].body_len);
2072 
2073       memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
2074              20);
2075       ogg_sync_wrote(&oy,20);
2076       if(ogg_sync_pageout(&oy,&og_de)>0)error();
2077       if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2078       if(ogg_sync_pageout(&oy,&og_de)>0)error();
2079 
2080       memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header+20,
2081              og[2].header_len-20);
2082       ogg_sync_wrote(&oy,og[2].header_len-20);
2083       memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
2084              og[2].body_len);
2085       ogg_sync_wrote(&oy,og[2].body_len);
2086       if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2087 
2088       fprintf(stderr,"ok.\n");
2089     }
2090 
2091     /* Test recapture: page + garbage + page */
2092     {
2093       ogg_page og_de;
2094       fprintf(stderr,"Testing recapture... ");
2095       ogg_sync_reset(&oy);
2096 
2097       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
2098              og[1].header_len);
2099       ogg_sync_wrote(&oy,og[1].header_len);
2100 
2101       memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2102              og[1].body_len);
2103       ogg_sync_wrote(&oy,og[1].body_len);
2104 
2105       memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
2106              og[2].header_len);
2107       ogg_sync_wrote(&oy,og[2].header_len);
2108 
2109       memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
2110              og[2].header_len);
2111       ogg_sync_wrote(&oy,og[2].header_len);
2112 
2113       if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2114 
2115       memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
2116              og[2].body_len-5);
2117       ogg_sync_wrote(&oy,og[2].body_len-5);
2118 
2119       memcpy(ogg_sync_buffer(&oy,og[3].header_len),og[3].header,
2120              og[3].header_len);
2121       ogg_sync_wrote(&oy,og[3].header_len);
2122 
2123       memcpy(ogg_sync_buffer(&oy,og[3].body_len),og[3].body,
2124              og[3].body_len);
2125       ogg_sync_wrote(&oy,og[3].body_len);
2126 
2127       if(ogg_sync_pageout(&oy,&og_de)>0)error();
2128       if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2129 
2130       fprintf(stderr,"ok.\n");
2131     }
2132 
2133     /* Free page data that was previously copied */
2134     {
2135       for(i=0;i<5;i++){
2136         free_page(&og[i]);
2137       }
2138     }
2139   }
2140 
2141   return(0);
2142 }
2143 
2144 #endif
2145