Source code

Revision control

Other Tools

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