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