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