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