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