Coverage Report

Created: 2024-07-27 06:05

/src/ogg/src/framing.c
Line
Count
Source (jump to first uncovered line)
1
/********************************************************************
2
 *                                                                  *
3
 * THIS FILE IS PART OF THE Ogg CONTAINER SOURCE CODE.              *
4
 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
5
 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6
 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
7
 *                                                                  *
8
 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2018             *
9
 * by the Xiph.Org Foundation http://www.xiph.org/                  *
10
 *                                                                  *
11
 ********************************************************************
12
13
 function: code raw packets into framed OggSquish stream and
14
           decode Ogg streams back into raw packets
15
16
 note: The CRC code is directly derived from public domain code by
17
 Ross Williams (ross@guest.adelaide.edu.au).  See docs/framing.html
18
 for details.
19
20
 ********************************************************************/
21
22
#ifdef HAVE_CONFIG_H
23
#include "config.h"
24
#endif
25
26
#include <stdlib.h>
27
#include <limits.h>
28
#include <string.h>
29
#include <ogg/ogg.h>
30
31
/* A complete description of Ogg framing exists in docs/framing.html */
32
33
76.7k
int ogg_page_version(const ogg_page *og){
34
76.7k
  return((int)(og->header[4]));
35
76.7k
}
36
37
76.7k
int ogg_page_continued(const ogg_page *og){
38
76.7k
  return((int)(og->header[5]&0x01));
39
76.7k
}
40
41
125k
int ogg_page_bos(const ogg_page *og){
42
125k
  return((int)(og->header[5]&0x02));
43
125k
}
44
45
76.7k
int ogg_page_eos(const ogg_page *og){
46
76.7k
  return((int)(og->header[5]&0x04));
47
76.7k
}
48
49
76.7k
ogg_int64_t ogg_page_granulepos(const ogg_page *og){
50
76.7k
  unsigned char *page=og->header;
51
76.7k
  ogg_uint64_t granulepos=page[13]&(0xff);
52
76.7k
  granulepos= (granulepos<<8)|(page[12]&0xff);
53
76.7k
  granulepos= (granulepos<<8)|(page[11]&0xff);
54
76.7k
  granulepos= (granulepos<<8)|(page[10]&0xff);
55
76.7k
  granulepos= (granulepos<<8)|(page[9]&0xff);
56
76.7k
  granulepos= (granulepos<<8)|(page[8]&0xff);
57
76.7k
  granulepos= (granulepos<<8)|(page[7]&0xff);
58
76.7k
  granulepos= (granulepos<<8)|(page[6]&0xff);
59
76.7k
  return((ogg_int64_t)granulepos);
60
76.7k
}
61
62
172k
int ogg_page_serialno(const ogg_page *og){
63
172k
  return((int)((ogg_uint32_t)og->header[14]) |
64
172k
              ((ogg_uint32_t)og->header[15]<<8) |
65
172k
              ((ogg_uint32_t)og->header[16]<<16) |
66
172k
              ((ogg_uint32_t)og->header[17]<<24));
67
172k
}
68
69
76.7k
long ogg_page_pageno(const ogg_page *og){
70
76.7k
  return((long)((ogg_uint32_t)og->header[18]) |
71
76.7k
               ((ogg_uint32_t)og->header[19]<<8) |
72
76.7k
               ((ogg_uint32_t)og->header[20]<<16) |
73
76.7k
               ((ogg_uint32_t)og->header[21]<<24));
74
76.7k
}
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
0
int ogg_page_packets(const ogg_page *og){
96
0
  int i,n=og->header[26],count=0;
97
0
  for(i=0;i<n;i++)
98
0
    if(og->header[27+i]<255)count++;
99
0
  return(count);
100
0
}
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
5.79k
int ogg_stream_init(ogg_stream_state *os,int serialno){
134
5.79k
  if(os){
135
5.79k
    memset(os,0,sizeof(*os));
136
5.79k
    os->body_storage=16*1024;
137
5.79k
    os->lacing_storage=1024;
138
139
5.79k
    os->body_data=_ogg_malloc(os->body_storage*sizeof(*os->body_data));
140
5.79k
    os->lacing_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->lacing_vals));
141
5.79k
    os->granule_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->granule_vals));
142
143
5.79k
    if(!os->body_data || !os->lacing_vals || !os->granule_vals){
144
0
      ogg_stream_clear(os);
145
0
      return -1;
146
0
    }
147
148
5.79k
    os->serialno=serialno;
149
150
5.79k
    return(0);
151
5.79k
  }
152
0
  return(-1);
153
5.79k
}
154
155
/* async/delayed error detection for the ogg_stream_state */
156
2.54M
int ogg_stream_check(ogg_stream_state *os){
157
2.54M
  if(!os || !os->body_data) return -1;
158
2.54M
  return 0;
159
2.54M
}
160
161
/* _clear does not free os, only the non-flat storage within */
162
5.79k
int ogg_stream_clear(ogg_stream_state *os){
163
5.79k
  if(os){
164
5.79k
    if(os->body_data)_ogg_free(os->body_data);
165
5.79k
    if(os->lacing_vals)_ogg_free(os->lacing_vals);
166
5.79k
    if(os->granule_vals)_ogg_free(os->granule_vals);
167
168
5.79k
    memset(os,0,sizeof(*os));
169
5.79k
  }
170
5.79k
  return(0);
171
5.79k
}
172
173
0
int ogg_stream_destroy(ogg_stream_state *os){
174
0
  if(os){
175
0
    ogg_stream_clear(os);
176
0
    _ogg_free(os);
177
0
  }
178
0
  return(0);
179
0
}
180
181
/* Helpers for ogg_stream_encode; this keeps the structure and
182
   what's happening fairly clear */
183
184
58.2k
static int _os_body_expand(ogg_stream_state *os,long needed){
185
58.2k
  if(os->body_storage-needed<=os->body_fill){
186
94
    long body_storage;
187
94
    void *ret;
188
94
    if(os->body_storage>LONG_MAX-needed){
189
0
      ogg_stream_clear(os);
190
0
      return -1;
191
0
    }
192
94
    body_storage=os->body_storage+needed;
193
94
    if(body_storage<LONG_MAX-1024)body_storage+=1024;
194
94
    ret=_ogg_realloc(os->body_data,body_storage*sizeof(*os->body_data));
195
94
    if(!ret){
196
0
      ogg_stream_clear(os);
197
0
      return -1;
198
0
    }
199
94
    os->body_storage=body_storage;
200
94
    os->body_data=ret;
201
94
  }
202
58.2k
  return 0;
203
58.2k
}
204
205
74.0k
static int _os_lacing_expand(ogg_stream_state *os,long needed){
206
74.0k
  if(os->lacing_storage-needed<=os->lacing_fill){
207
0
    long lacing_storage;
208
0
    void *ret;
209
0
    if(os->lacing_storage>LONG_MAX-needed){
210
0
      ogg_stream_clear(os);
211
0
      return -1;
212
0
    }
213
0
    lacing_storage=os->lacing_storage+needed;
214
0
    if(lacing_storage<LONG_MAX-32)lacing_storage+=32;
215
0
    ret=_ogg_realloc(os->lacing_vals,lacing_storage*sizeof(*os->lacing_vals));
216
0
    if(!ret){
217
0
      ogg_stream_clear(os);
218
0
      return -1;
219
0
    }
220
0
    os->lacing_vals=ret;
221
0
    ret=_ogg_realloc(os->granule_vals,lacing_storage*
222
0
                     sizeof(*os->granule_vals));
223
0
    if(!ret){
224
0
      ogg_stream_clear(os);
225
0
      return -1;
226
0
    }
227
0
    os->granule_vals=ret;
228
0
    os->lacing_storage=lacing_storage;
229
0
  }
230
74.0k
  return 0;
231
74.0k
}
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
147k
static ogg_uint32_t _os_update_crc(ogg_uint32_t crc, unsigned char *buffer, int size){
238
2.31M
  while (size>=8){
239
2.16M
    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
2.16M
    crc=crc_lookup[7][ crc>>24      ]^crc_lookup[6][(crc>>16)&0xFF]^
242
2.16M
        crc_lookup[5][(crc>> 8)&0xFF]^crc_lookup[4][ crc     &0xFF]^
243
2.16M
        crc_lookup[3][buffer[4]     ]^crc_lookup[2][buffer[5]     ]^
244
2.16M
        crc_lookup[1][buffer[6]     ]^crc_lookup[0][buffer[7]     ];
245
246
2.16M
    buffer+=8;
247
2.16M
    size-=8;
248
2.16M
  }
249
250
646k
  while (size--)
251
498k
    crc=(crc<<8)^crc_lookup[0][((crc >> 24)&0xff)^*buffer++];
252
147k
  return crc;
253
147k
}
254
255
73.9k
void ogg_page_checksum_set(ogg_page *og){
256
73.9k
  if(og){
257
73.9k
    ogg_uint32_t crc_reg=0;
258
259
    /* safety; needed for API behavior, but not framing code */
260
73.9k
    og->header[22]=0;
261
73.9k
    og->header[23]=0;
262
73.9k
    og->header[24]=0;
263
73.9k
    og->header[25]=0;
264
265
73.9k
    crc_reg=_os_update_crc(crc_reg,og->header,og->header_len);
266
73.9k
    crc_reg=_os_update_crc(crc_reg,og->body,og->body_len);
267
268
73.9k
    og->header[22]=(unsigned char)(crc_reg&0xff);
269
73.9k
    og->header[23]=(unsigned char)((crc_reg>>8)&0xff);
270
73.9k
    og->header[24]=(unsigned char)((crc_reg>>16)&0xff);
271
73.9k
    og->header[25]=(unsigned char)((crc_reg>>24)&0xff);
272
73.9k
  }
273
73.9k
}
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
0
                       long e_o_s, ogg_int64_t granulepos){
278
279
0
  long bytes = 0, lacing_vals;
280
0
  int i;
281
282
0
  if(ogg_stream_check(os)) return -1;
283
0
  if(!iov) return 0;
284
285
0
  for (i = 0; i < count; ++i){
286
0
    if(iov[i].iov_len>LONG_MAX) return -1;
287
0
    if(bytes>LONG_MAX-(long)iov[i].iov_len) return -1;
288
0
    bytes += (long)iov[i].iov_len;
289
0
  }
290
0
  lacing_vals=bytes/255+1;
291
292
0
  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
0
    os->body_fill-=os->body_returned;
298
0
    if(os->body_fill)
299
0
      memmove(os->body_data,os->body_data+os->body_returned,
300
0
              os->body_fill);
301
0
    os->body_returned=0;
302
0
  }
303
304
  /* make sure we have the buffer storage */
305
0
  if(_os_body_expand(os,bytes) || _os_lacing_expand(os,lacing_vals))
306
0
    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
0
  for (i = 0; i < count; ++i) {
314
0
    memcpy(os->body_data+os->body_fill, iov[i].iov_base, iov[i].iov_len);
315
0
    os->body_fill += (int)iov[i].iov_len;
316
0
  }
317
318
  /* Store lacing vals for this packet */
319
0
  for(i=0;i<lacing_vals-1;i++){
320
0
    os->lacing_vals[os->lacing_fill+i]=255;
321
0
    os->granule_vals[os->lacing_fill+i]=os->granulepos;
322
0
  }
323
0
  os->lacing_vals[os->lacing_fill+i]=bytes%255;
324
0
  os->granulepos=os->granule_vals[os->lacing_fill+i]=granulepos;
325
326
  /* flag the first segment as the beginning of the packet */
327
0
  os->lacing_vals[os->lacing_fill]|= 0x100;
328
329
0
  os->lacing_fill+=lacing_vals;
330
331
  /* for the sake of completeness */
332
0
  os->packetno++;
333
334
0
  if(e_o_s)os->e_o_s=1;
335
336
0
  return(0);
337
0
}
338
339
0
int ogg_stream_packetin(ogg_stream_state *os,ogg_packet *op){
340
0
  ogg_iovec_t iov;
341
0
  iov.iov_base = op->packet;
342
0
  iov.iov_len = op->bytes;
343
0
  return ogg_stream_iovecin(os, &iov, 1, op->e_o_s, op->granulepos);
344
0
}
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
0
static int ogg_stream_flush_i(ogg_stream_state *os,ogg_page *og, int force, int nfill){
350
0
  int i;
351
0
  int vals=0;
352
0
  int maxvals;
353
0
  int bytes=0;
354
0
  long acc=0;
355
0
  ogg_int64_t granule_pos=-1;
356
357
0
  if(ogg_stream_check(os)) return(0);
358
0
  maxvals=(os->lacing_fill>255?255:os->lacing_fill);
359
0
  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
0
  if(os->b_o_s==0){  /* 'initial header page' case */
367
0
    granule_pos=0;
368
0
    for(vals=0;vals<maxvals;vals++){
369
0
      if((os->lacing_vals[vals]&0x0ff)<255){
370
0
        vals++;
371
0
        break;
372
0
      }
373
0
    }
374
0
  }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
0
    int packets_done=0;
386
0
    int packet_just_done=0;
387
0
    for(vals=0;vals<maxvals;vals++){
388
0
      if(acc>nfill && packet_just_done>=4){
389
0
        force=1;
390
0
        break;
391
0
      }
392
0
      acc+=os->lacing_vals[vals]&0x0ff;
393
0
      if((os->lacing_vals[vals]&0xff)<255){
394
0
        granule_pos=os->granule_vals[vals];
395
0
        packet_just_done=++packets_done;
396
0
      }else
397
0
        packet_just_done=0;
398
0
    }
399
0
    if(vals==255)force=1;
400
0
  }
401
402
0
  if(!force) return(0);
403
404
  /* construct the header in temp storage */
405
0
  memcpy(os->header,"OggS",4);
406
407
  /* stream structure version */
408
0
  os->header[4]=0x00;
409
410
  /* continued packet flag? */
411
0
  os->header[5]=0x00;
412
0
  if((os->lacing_vals[0]&0x100)==0)os->header[5]|=0x01;
413
  /* first page flag? */
414
0
  if(os->b_o_s==0)os->header[5]|=0x02;
415
  /* last page flag? */
416
0
  if(os->e_o_s && os->lacing_fill==vals)os->header[5]|=0x04;
417
0
  os->b_o_s=1;
418
419
  /* 64 bits of PCM position */
420
0
  for(i=6;i<14;i++){
421
0
    os->header[i]=(unsigned char)(granule_pos&0xff);
422
0
    granule_pos>>=8;
423
0
  }
424
425
  /* 32 bits of stream serial number */
426
0
  {
427
0
    long serialno=os->serialno;
428
0
    for(i=14;i<18;i++){
429
0
      os->header[i]=(unsigned char)(serialno&0xff);
430
0
      serialno>>=8;
431
0
    }
432
0
  }
433
434
  /* 32 bits of page counter (we have both counter and page header
435
     because this val can roll over) */
436
0
  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
0
  {
442
0
    long pageno=os->pageno++;
443
0
    for(i=18;i<22;i++){
444
0
      os->header[i]=(unsigned char)(pageno&0xff);
445
0
      pageno>>=8;
446
0
    }
447
0
  }
448
449
  /* zero for computation; filled in later */
450
0
  os->header[22]=0;
451
0
  os->header[23]=0;
452
0
  os->header[24]=0;
453
0
  os->header[25]=0;
454
455
  /* segment table */
456
0
  os->header[26]=(unsigned char)(vals&0xff);
457
0
  for(i=0;i<vals;i++)
458
0
    bytes+=os->header[i+27]=(unsigned char)(os->lacing_vals[i]&0xff);
459
460
  /* set pointers in the ogg_page struct */
461
0
  og->header=os->header;
462
0
  og->header_len=os->header_fill=vals+27;
463
0
  og->body=os->body_data+os->body_returned;
464
0
  og->body_len=bytes;
465
466
  /* advance the lacing data and set the body_returned pointer */
467
468
0
  os->lacing_fill-=vals;
469
0
  memmove(os->lacing_vals,os->lacing_vals+vals,os->lacing_fill*sizeof(*os->lacing_vals));
470
0
  memmove(os->granule_vals,os->granule_vals+vals,os->lacing_fill*sizeof(*os->granule_vals));
471
0
  os->body_returned+=bytes;
472
473
  /* calculate the checksum */
474
475
0
  ogg_page_checksum_set(og);
476
477
  /* done */
478
0
  return(1);
479
0
}
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
0
int ogg_stream_flush(ogg_stream_state *os,ogg_page *og){
496
0
  return ogg_stream_flush_i(os,og,1,4096);
497
0
}
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
0
int ogg_stream_flush_fill(ogg_stream_state *os,ogg_page *og, int nfill){
504
0
  return ogg_stream_flush_i(os,og,1,nfill);
505
0
}
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
0
int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og){
512
0
  int force=0;
513
0
  if(ogg_stream_check(os)) return 0;
514
515
0
  if((os->e_o_s&&os->lacing_fill) ||          /* 'were done, now flush' case */
516
0
     (os->lacing_fill&&!os->b_o_s))           /* 'initial header page' case */
517
0
    force=1;
518
519
0
  return(ogg_stream_flush_i(os,og,force,4096));
520
0
}
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
0
int ogg_stream_pageout_fill(ogg_stream_state *os, ogg_page *og, int nfill){
527
0
  int force=0;
528
0
  if(ogg_stream_check(os)) return 0;
529
530
0
  if((os->e_o_s&&os->lacing_fill) ||          /* 'were done, now flush' case */
531
0
     (os->lacing_fill&&!os->b_o_s))           /* 'initial header page' case */
532
0
    force=1;
533
534
0
  return(ogg_stream_flush_i(os,og,force,nfill));
535
0
}
536
537
0
int ogg_stream_eos(ogg_stream_state *os){
538
0
  if(ogg_stream_check(os)) return 1;
539
0
  return os->e_o_s;
540
0
}
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
5.79k
int ogg_sync_init(ogg_sync_state *oy){
559
5.79k
  if(oy){
560
5.79k
    oy->storage = -1; /* used as a readiness flag */
561
5.79k
    memset(oy,0,sizeof(*oy));
562
5.79k
  }
563
5.79k
  return(0);
564
5.79k
}
565
566
/* clear non-flat storage within */
567
5.79k
int ogg_sync_clear(ogg_sync_state *oy){
568
5.79k
  if(oy){
569
5.79k
    if(oy->data)_ogg_free(oy->data);
570
5.79k
    memset(oy,0,sizeof(*oy));
571
5.79k
  }
572
5.79k
  return(0);
573
5.79k
}
574
575
0
int ogg_sync_destroy(ogg_sync_state *oy){
576
0
  if(oy){
577
0
    ogg_sync_clear(oy);
578
0
    _ogg_free(oy);
579
0
  }
580
0
  return(0);
581
0
}
582
583
737k
int ogg_sync_check(ogg_sync_state *oy){
584
737k
  if(oy->storage<0) return -1;
585
737k
  return 0;
586
737k
}
587
588
19.2k
char *ogg_sync_buffer(ogg_sync_state *oy, long size){
589
19.2k
  if(ogg_sync_check(oy)) return NULL;
590
591
  /* first, clear out any space that has been previously returned */
592
19.2k
  if(oy->returned){
593
9.88k
    oy->fill-=oy->returned;
594
9.88k
    if(oy->fill>0)
595
5.56k
      memmove(oy->data,oy->data+oy->returned,oy->fill);
596
9.88k
    oy->returned=0;
597
9.88k
  }
598
599
19.2k
  if(size>oy->storage-oy->fill){
600
    /* We need to extend the internal buffer */
601
6.30k
    long newsize;
602
6.30k
    void *ret;
603
604
6.30k
    if(size>INT_MAX-4096-oy->fill){
605
0
      ogg_sync_clear(oy);
606
0
      return NULL;
607
0
    }
608
6.30k
    newsize=size+oy->fill+4096; /* an extra page to be nice */
609
6.30k
    if(oy->data)
610
511
      ret=_ogg_realloc(oy->data,newsize);
611
5.79k
    else
612
5.79k
      ret=_ogg_malloc(newsize);
613
6.30k
    if(!ret){
614
0
      ogg_sync_clear(oy);
615
0
      return NULL;
616
0
    }
617
6.30k
    oy->data=ret;
618
6.30k
    oy->storage=newsize;
619
6.30k
  }
620
621
  /* expose a segment at least as large as requested at the fill mark */
622
19.2k
  return((char *)oy->data+oy->fill);
623
19.2k
}
624
625
15.6k
int ogg_sync_wrote(ogg_sync_state *oy, long bytes){
626
15.6k
  if(ogg_sync_check(oy))return -1;
627
15.6k
  if(oy->fill+bytes>oy->storage)return -1;
628
15.6k
  oy->fill+=bytes;
629
15.6k
  return(0);
630
15.6k
}
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
702k
long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){
643
702k
  unsigned char *page;
644
702k
  unsigned char *next;
645
702k
  long bytes;
646
647
702k
  if(ogg_sync_check(oy))return 0;
648
649
702k
  page=oy->data+oy->returned;
650
702k
  bytes=oy->fill-oy->returned;
651
652
702k
  if(oy->headerbytes==0){
653
696k
    int headerbytes,i;
654
696k
    if(bytes<27)return(0); /* not enough for a header */
655
656
    /* verify capture pattern */
657
685k
    if(memcmp(page,"OggS",4))goto sync_fail;
658
659
75.5k
    headerbytes=page[26]+27;
660
75.5k
    if(bytes<headerbytes)return(0); /* not enough for header + seg table */
661
662
    /* count up body length in the segment table */
663
664
3.17M
    for(i=0;i<page[26];i++)
665
3.09M
      oy->bodybytes+=page[27+i];
666
74.0k
    oy->headerbytes=headerbytes;
667
74.0k
  }
668
669
80.0k
  if(oy->bodybytes+oy->headerbytes>bytes)return(0);
670
671
  /* The whole test page is buffered.  Verify the checksum */
672
73.9k
  {
673
    /* Grab the checksum bytes, set the header field to zero */
674
73.9k
    char chksum[4];
675
73.9k
    ogg_page log;
676
677
73.9k
    memcpy(chksum,page+22,4);
678
73.9k
    memset(page+22,0,4);
679
680
    /* set up a temp page struct and recompute the checksum */
681
73.9k
    log.header=page;
682
73.9k
    log.header_len=oy->headerbytes;
683
73.9k
    log.body=page+oy->headerbytes;
684
73.9k
    log.body_len=oy->bodybytes;
685
73.9k
    ogg_page_checksum_set(&log);
686
687
    /* Compare */
688
73.9k
    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
73.1k
      memcpy(page+22,chksum,4);
693
694
#ifndef DISABLE_CRC
695
      /* Bad checksum. Lose sync */
696
      goto sync_fail;
697
#endif
698
73.1k
    }
699
73.9k
  }
700
701
  /* yes, have a whole page all ready to go */
702
73.9k
  {
703
73.9k
    if(og){
704
73.9k
      og->header=page;
705
73.9k
      og->header_len=oy->headerbytes;
706
73.9k
      og->body=page+oy->headerbytes;
707
73.9k
      og->body_len=oy->bodybytes;
708
73.9k
    }
709
710
73.9k
    oy->unsynced=0;
711
73.9k
    oy->returned+=(bytes=oy->headerbytes+oy->bodybytes);
712
73.9k
    oy->headerbytes=0;
713
73.9k
    oy->bodybytes=0;
714
73.9k
    return(bytes);
715
80.0k
  }
716
717
609k
 sync_fail:
718
719
609k
  oy->headerbytes=0;
720
609k
  oy->bodybytes=0;
721
722
  /* search for possible capture */
723
609k
  next=memchr(page+1,'O',bytes-1);
724
609k
  if(!next)
725
1.14k
    next=oy->data+oy->fill;
726
727
609k
  oy->returned=(int)(next-oy->data);
728
609k
  return((long)-(next-page));
729
80.0k
}
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
0
int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og){
743
744
0
  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
0
  for(;;){
751
0
    long ret=ogg_sync_pageseek(oy,og);
752
0
    if(ret>0){
753
      /* have a page */
754
0
      return(1);
755
0
    }
756
0
    if(ret==0){
757
      /* need more data */
758
0
      return(0);
759
0
    }
760
761
    /* head did not start a synced page... skipped some bytes */
762
0
    if(!oy->unsynced){
763
0
      oy->unsynced=1;
764
0
      return(-1);
765
0
    }
766
767
    /* loop. keep looking */
768
769
0
  }
770
0
}
771
772
/* add the incoming page to the stream state; we decompose the page
773
   into packet segments here as well. */
774
775
76.7k
int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){
776
76.7k
  unsigned char *header=og->header;
777
76.7k
  unsigned char *body=og->body;
778
76.7k
  long           bodysize=og->body_len;
779
76.7k
  int            segptr=0;
780
781
76.7k
  int version=ogg_page_version(og);
782
76.7k
  int continued=ogg_page_continued(og);
783
76.7k
  int bos=ogg_page_bos(og);
784
76.7k
  int eos=ogg_page_eos(og);
785
76.7k
  ogg_int64_t granulepos=ogg_page_granulepos(og);
786
76.7k
  int serialno=ogg_page_serialno(og);
787
76.7k
  long pageno=ogg_page_pageno(og);
788
76.7k
  int segments=header[26];
789
790
76.7k
  if(ogg_stream_check(os)) return -1;
791
792
  /* clean up 'returned data' */
793
76.7k
  {
794
76.7k
    long lr=os->lacing_returned;
795
76.7k
    long br=os->body_returned;
796
797
    /* body data */
798
76.7k
    if(br){
799
39.4k
      os->body_fill-=br;
800
39.4k
      if(os->body_fill)
801
5.58k
        memmove(os->body_data,os->body_data+br,os->body_fill);
802
39.4k
      os->body_returned=0;
803
39.4k
    }
804
805
76.7k
    if(lr){
806
      /* segment table */
807
41.2k
      if(os->lacing_fill-lr){
808
6.89k
        memmove(os->lacing_vals,os->lacing_vals+lr,
809
6.89k
                (os->lacing_fill-lr)*sizeof(*os->lacing_vals));
810
6.89k
        memmove(os->granule_vals,os->granule_vals+lr,
811
6.89k
                (os->lacing_fill-lr)*sizeof(*os->granule_vals));
812
6.89k
      }
813
41.2k
      os->lacing_fill-=lr;
814
41.2k
      os->lacing_packet-=lr;
815
41.2k
      os->lacing_returned=0;
816
41.2k
    }
817
76.7k
  }
818
819
  /* check the serial number */
820
76.7k
  if(serialno!=os->serialno)return(-1);
821
76.4k
  if(version>0)return(-1);
822
823
74.0k
  if(_os_lacing_expand(os,segments+1)) return -1;
824
825
  /* are we in sequence? */
826
74.0k
  if(pageno!=os->pageno){
827
56.1k
    int i;
828
829
    /* unroll previous partial packet (if any) */
830
58.2k
    for(i=os->lacing_packet;i<os->lacing_fill;i++)
831
2.13k
      os->body_fill-=os->lacing_vals[i]&0xff;
832
56.1k
    os->lacing_fill=os->lacing_packet;
833
834
    /* make a note of dropped data in segment table */
835
56.1k
    if(os->pageno!=-1){
836
24.2k
      os->lacing_vals[os->lacing_fill++]=0x400;
837
24.2k
      os->lacing_packet++;
838
24.2k
    }
839
56.1k
  }
840
841
  /* are we a 'continued packet' page?  If so, we may need to skip
842
     some segments */
843
74.0k
  if(continued){
844
10.0k
    if(os->lacing_fill<1 ||
845
10.0k
       (os->lacing_vals[os->lacing_fill-1]&0xff)<255 ||
846
10.0k
       os->lacing_vals[os->lacing_fill-1]==0x400){
847
8.50k
      bos=0;
848
9.83k
      for(;segptr<segments;segptr++){
849
2.58k
        int val=header[27+segptr];
850
2.58k
        body+=val;
851
2.58k
        bodysize-=val;
852
2.58k
        if(val<255){
853
1.25k
          segptr++;
854
1.25k
          break;
855
1.25k
        }
856
2.58k
      }
857
8.50k
    }
858
10.0k
  }
859
860
74.0k
  if(bodysize){
861
58.2k
    if(_os_body_expand(os,bodysize)) return -1;
862
58.2k
    memcpy(os->body_data+os->body_fill,body,bodysize);
863
58.2k
    os->body_fill+=bodysize;
864
58.2k
  }
865
866
74.0k
  {
867
74.0k
    int saved=-1;
868
2.45M
    while(segptr<segments){
869
2.38M
      int val=header[27+segptr];
870
2.38M
      os->lacing_vals[os->lacing_fill]=val;
871
2.38M
      os->granule_vals[os->lacing_fill]=-1;
872
873
2.38M
      if(bos){
874
27.0k
        os->lacing_vals[os->lacing_fill]|=0x100;
875
27.0k
        bos=0;
876
27.0k
      }
877
878
2.38M
      if(val<255)saved=os->lacing_fill;
879
880
2.38M
      os->lacing_fill++;
881
2.38M
      segptr++;
882
883
2.38M
      if(val<255)os->lacing_packet=os->lacing_fill;
884
2.38M
    }
885
886
    /* set the granulepos on the last granuleval of the last full packet */
887
74.0k
    if(saved!=-1){
888
56.3k
      os->granule_vals[saved]=granulepos;
889
56.3k
    }
890
891
74.0k
  }
892
893
74.0k
  if(eos){
894
25.1k
    os->e_o_s=1;
895
25.1k
    if(os->lacing_fill>0)
896
18.2k
      os->lacing_vals[os->lacing_fill-1]|=0x200;
897
25.1k
  }
898
899
74.0k
  os->pageno=pageno+1;
900
901
74.0k
  return(0);
902
74.0k
}
903
904
/* clear things to an initial state.  Good to call, eg, before seeking */
905
0
int ogg_sync_reset(ogg_sync_state *oy){
906
0
  if(ogg_sync_check(oy))return -1;
907
908
0
  oy->fill=0;
909
0
  oy->returned=0;
910
0
  oy->unsynced=0;
911
0
  oy->headerbytes=0;
912
0
  oy->bodybytes=0;
913
0
  return(0);
914
0
}
915
916
33.4k
int ogg_stream_reset(ogg_stream_state *os){
917
33.4k
  if(ogg_stream_check(os)) return -1;
918
919
33.4k
  os->body_fill=0;
920
33.4k
  os->body_returned=0;
921
922
33.4k
  os->lacing_fill=0;
923
33.4k
  os->lacing_packet=0;
924
33.4k
  os->lacing_returned=0;
925
926
33.4k
  os->header_fill=0;
927
928
33.4k
  os->e_o_s=0;
929
33.4k
  os->b_o_s=0;
930
33.4k
  os->pageno=-1;
931
33.4k
  os->packetno=0;
932
33.4k
  os->granulepos=0;
933
934
33.4k
  return(0);
935
33.4k
}
936
937
33.4k
int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno){
938
33.4k
  if(ogg_stream_check(os)) return -1;
939
33.4k
  ogg_stream_reset(os);
940
33.4k
  os->serialno=serialno;
941
33.4k
  return(0);
942
33.4k
}
943
944
2.39M
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
2.39M
  int ptr=os->lacing_returned;
951
952
2.39M
  if(os->lacing_packet<=ptr)return(0);
953
954
2.34M
  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
24.2k
    os->lacing_returned++;
958
24.2k
    os->packetno++;
959
24.2k
    return(-1);
960
24.2k
  }
961
962
2.32M
  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
2.32M
  {
968
2.32M
    int size=os->lacing_vals[ptr]&0xff;
969
2.32M
    long bytes=size;
970
2.32M
    int eos=os->lacing_vals[ptr]&0x200; /* last packet of the stream? */
971
2.32M
    int bos=os->lacing_vals[ptr]&0x100; /* first packet of the stream? */
972
973
2.34M
    while(size==255){
974
15.7k
      int val=os->lacing_vals[++ptr];
975
15.7k
      size=val&0xff;
976
15.7k
      if(val&0x200)eos=0x200;
977
15.7k
      bytes+=size;
978
15.7k
    }
979
980
2.32M
    if(op){
981
2.32M
      op->e_o_s=eos;
982
2.32M
      op->b_o_s=bos;
983
2.32M
      op->packet=os->body_data+os->body_returned;
984
2.32M
      op->packetno=os->packetno;
985
2.32M
      op->granulepos=os->granule_vals[ptr];
986
2.32M
      op->bytes=bytes;
987
2.32M
    }
988
989
2.32M
    if(adv){
990
2.32M
      os->body_returned+=bytes;
991
2.32M
      os->lacing_returned=ptr+1;
992
2.32M
      os->packetno++;
993
2.32M
    }
994
2.32M
  }
995
2.32M
  return(1);
996
2.32M
}
997
998
2.39M
int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op){
999
2.39M
  if(ogg_stream_check(os)) return 0;
1000
2.39M
  return _packetout(os,op,1);
1001
2.39M
}
1002
1003
0
int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op){
1004
0
  if(ogg_stream_check(os)) return 0;
1005
0
  return _packetout(os,op,0);
1006
0
}
1007
1008
0
void ogg_packet_clear(ogg_packet *op) {
1009
0
  _ogg_free(op->packet);
1010
0
  memset(op, 0, sizeof(*op));
1011
0
}
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
void copy_page(ogg_page *og){
1111
  unsigned char *temp=_ogg_malloc(og->header_len);
1112
  memcpy(temp,og->header,og->header_len);
1113
  og->header=temp;
1114
1115
  temp=_ogg_malloc(og->body_len);
1116
  memcpy(temp,og->body,og->body_len);
1117
  og->body=temp;
1118
}
1119
1120
void free_page(ogg_page *og){
1121
  _ogg_free (og->header);
1122
  _ogg_free (og->body);
1123
}
1124
1125
void error(void){
1126
  fprintf(stderr,"error!\n");
1127
  exit(1);
1128
}
1129
1130
/* 17 only */
1131
const int head1_0[] = {0x4f,0x67,0x67,0x53,0,0x06,
1132
                       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1133
                       0x01,0x02,0x03,0x04,0,0,0,0,
1134
                       0x15,0xed,0xec,0x91,
1135
                       1,
1136
                       17};
1137
1138
/* 17, 254, 255, 256, 500, 510, 600 byte, pad */
1139
const int head1_1[] = {0x4f,0x67,0x67,0x53,0,0x02,
1140
                       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1141
                       0x01,0x02,0x03,0x04,0,0,0,0,
1142
                       0x59,0x10,0x6c,0x2c,
1143
                       1,
1144
                       17};
1145
const int head2_1[] = {0x4f,0x67,0x67,0x53,0,0x04,
1146
                       0x07,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
1147
                       0x01,0x02,0x03,0x04,1,0,0,0,
1148
                       0x89,0x33,0x85,0xce,
1149
                       13,
1150
                       254,255,0,255,1,255,245,255,255,0,
1151
                       255,255,90};
1152
1153
/* nil packets; beginning,middle,end */
1154
const int head1_2[] = {0x4f,0x67,0x67,0x53,0,0x02,
1155
                       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1156
                       0x01,0x02,0x03,0x04,0,0,0,0,
1157
                       0xff,0x7b,0x23,0x17,
1158
                       1,
1159
                       0};
1160
const int head2_2[] = {0x4f,0x67,0x67,0x53,0,0x04,
1161
                       0x07,0x28,0x00,0x00,0x00,0x00,0x00,0x00,
1162
                       0x01,0x02,0x03,0x04,1,0,0,0,
1163
                       0x5c,0x3f,0x66,0xcb,
1164
                       17,
1165
                       17,254,255,0,0,255,1,0,255,245,255,255,0,
1166
                       255,255,90,0};
1167
1168
/* large initial packet */
1169
const int head1_3[] = {0x4f,0x67,0x67,0x53,0,0x02,
1170
                       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1171
                       0x01,0x02,0x03,0x04,0,0,0,0,
1172
                       0x01,0x27,0x31,0xaa,
1173
                       18,
1174
                       255,255,255,255,255,255,255,255,
1175
                       255,255,255,255,255,255,255,255,255,10};
1176
1177
const int head2_3[] = {0x4f,0x67,0x67,0x53,0,0x04,
1178
                       0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
1179
                       0x01,0x02,0x03,0x04,1,0,0,0,
1180
                       0x7f,0x4e,0x8a,0xd2,
1181
                       4,
1182
                       255,4,255,0};
1183
1184
1185
/* continuing packet test */
1186
const int head1_4[] = {0x4f,0x67,0x67,0x53,0,0x02,
1187
                       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1188
                       0x01,0x02,0x03,0x04,0,0,0,0,
1189
                       0xff,0x7b,0x23,0x17,
1190
                       1,
1191
                       0};
1192
1193
const int head2_4[] = {0x4f,0x67,0x67,0x53,0,0x00,
1194
                       0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
1195
                       0x01,0x02,0x03,0x04,1,0,0,0,
1196
                       0xf8,0x3c,0x19,0x79,
1197
                       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,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};
1230
1231
const int head3_4[] = {0x4f,0x67,0x67,0x53,0,0x05,
1232
                       0x07,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,
1233
                       0x01,0x02,0x03,0x04,2,0,0,0,
1234
                       0x38,0xe6,0xb6,0x28,
1235
                       6,
1236
                       255,220,255,4,255,0};
1237
1238
1239
/* spill expansion test */
1240
const int head1_4b[] = {0x4f,0x67,0x67,0x53,0,0x02,
1241
                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1242
                        0x01,0x02,0x03,0x04,0,0,0,0,
1243
                        0xff,0x7b,0x23,0x17,
1244
                        1,
1245
                        0};
1246
1247
const int head2_4b[] = {0x4f,0x67,0x67,0x53,0,0x00,
1248
                        0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
1249
                        0x01,0x02,0x03,0x04,1,0,0,0,
1250
                        0xce,0x8f,0x17,0x1a,
1251
                        23,
1252
                        255,255,255,255,255,255,255,255,
1253
                        255,255,255,255,255,255,255,255,255,10,255,4,255,0,0};
1254
1255
1256
const int head3_4b[] = {0x4f,0x67,0x67,0x53,0,0x04,
1257
                        0x07,0x14,0x00,0x00,0x00,0x00,0x00,0x00,
1258
                        0x01,0x02,0x03,0x04,2,0,0,0,
1259
                        0x9b,0xb2,0x50,0xa1,
1260
                        1,
1261
                        0};
1262
1263
/* page with the 255 segment limit */
1264
const int head1_5[] = {0x4f,0x67,0x67,0x53,0,0x02,
1265
                       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1266
                       0x01,0x02,0x03,0x04,0,0,0,0,
1267
                       0xff,0x7b,0x23,0x17,
1268
                       1,
1269
                       0};
1270
1271
const int head2_5[] = {0x4f,0x67,0x67,0x53,0,0x00,
1272
                       0x07,0xfc,0x03,0x00,0x00,0x00,0x00,0x00,
1273
                       0x01,0x02,0x03,0x04,1,0,0,0,
1274
                       0xed,0x2a,0x2e,0xa7,
1275
                       255,
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,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};
1308
1309
const int head3_5[] = {0x4f,0x67,0x67,0x53,0,0x04,
1310
                       0x07,0x00,0x04,0x00,0x00,0x00,0x00,0x00,
1311
                       0x01,0x02,0x03,0x04,2,0,0,0,
1312
                       0x6c,0x3b,0x82,0x3d,
1313
                       1,
1314
                       50};
1315
1316
1317
/* packet that overspans over an entire page */
1318
const int head1_6[] = {0x4f,0x67,0x67,0x53,0,0x02,
1319
                       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1320
                       0x01,0x02,0x03,0x04,0,0,0,0,
1321
                       0xff,0x7b,0x23,0x17,
1322
                       1,
1323
                       0};
1324
1325
const int head2_6[] = {0x4f,0x67,0x67,0x53,0,0x00,
1326
                       0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
1327
                       0x01,0x02,0x03,0x04,1,0,0,0,
1328
                       0x68,0x22,0x7c,0x3d,
1329
                       255,
1330
                       100,
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,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};
1363
1364
const int head3_6[] = {0x4f,0x67,0x67,0x53,0,0x01,
1365
                       0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
1366
                       0x01,0x02,0x03,0x04,2,0,0,0,
1367
                       0xf4,0x87,0xba,0xf3,
1368
                       255,
1369
                       255,255,255,255,255,255,255,255,
1370
                       255,255,255,255,255,255,255,255,
1371
                       255,255,255,255,255,255,255,255,
1372
                       255,255,255,255,255,255,255,255,
1373
                       255,255,255,255,255,255,255,255,
1374
                       255,255,255,255,255,255,255,255,
1375
                       255,255,255,255,255,255,255,255,
1376
                       255,255,255,255,255,255,255,255,
1377
                       255,255,255,255,255,255,255,255,
1378
                       255,255,255,255,255,255,255,255,
1379
                       255,255,255,255,255,255,255,255,
1380
                       255,255,255,255,255,255,255,255,
1381
                       255,255,255,255,255,255,255,255,
1382
                       255,255,255,255,255,255,255,255,
1383
                       255,255,255,255,255,255,255,255,
1384
                       255,255,255,255,255,255,255,255,
1385
                       255,255,255,255,255,255,255,255,
1386
                       255,255,255,255,255,255,255,255,
1387
                       255,255,255,255,255,255,255,255,
1388
                       255,255,255,255,255,255,255,255,
1389
                       255,255,255,255,255,255,255,255,
1390
                       255,255,255,255,255,255,255,255,
1391
                       255,255,255,255,255,255,255,255,
1392
                       255,255,255,255,255,255,255,255,
1393
                       255,255,255,255,255,255,255,255,
1394
                       255,255,255,255,255,255,255,255,
1395
                       255,255,255,255,255,255,255,255,
1396
                       255,255,255,255,255,255,255,255,
1397
                       255,255,255,255,255,255,255,255,
1398
                       255,255,255,255,255,255,255,255,
1399
                       255,255,255,255,255,255,255,255,
1400
                       255,255,255,255,255,255,255};
1401
1402
const int head4_6[] = {0x4f,0x67,0x67,0x53,0,0x05,
1403
                       0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
1404
                       0x01,0x02,0x03,0x04,3,0,0,0,
1405
                       0xf7,0x2f,0x6c,0x60,
1406
                       5,
1407
                       254,255,4,255,0};
1408
1409
/* packet that overspans over an entire page */
1410
const int head1_7[] = {0x4f,0x67,0x67,0x53,0,0x02,
1411
                       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1412
                       0x01,0x02,0x03,0x04,0,0,0,0,
1413
                       0xff,0x7b,0x23,0x17,
1414
                       1,
1415
                       0};
1416
1417
const int head2_7[] = {0x4f,0x67,0x67,0x53,0,0x00,
1418
                       0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
1419
                       0x01,0x02,0x03,0x04,1,0,0,0,
1420
                       0x68,0x22,0x7c,0x3d,
1421
                       255,
1422
                       100,
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,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};
1455
1456
const int head3_7[] = {0x4f,0x67,0x67,0x53,0,0x05,
1457
                       0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
1458
                       0x01,0x02,0x03,0x04,2,0,0,0,
1459
                       0xd4,0xe0,0x60,0xe5,
1460
                       1,
1461
                       0};
1462
1463
int compare_packet(const ogg_packet *op1, const ogg_packet *op2){
1464
  if(op1->packet!=op2->packet){
1465
    fprintf(stderr,"op1->packet != op2->packet\n");
1466
    return(1);
1467
  }
1468
  if(op1->bytes!=op2->bytes){
1469
    fprintf(stderr,"op1->bytes != op2->bytes\n");
1470
    return(1);
1471
  }
1472
  if(op1->b_o_s!=op2->b_o_s){
1473
    fprintf(stderr,"op1->b_o_s != op2->b_o_s\n");
1474
    return(1);
1475
  }
1476
  if(op1->e_o_s!=op2->e_o_s){
1477
    fprintf(stderr,"op1->e_o_s != op2->e_o_s\n");
1478
    return(1);
1479
  }
1480
  if(op1->granulepos!=op2->granulepos){
1481
    fprintf(stderr,"op1->granulepos != op2->granulepos\n");
1482
    return(1);
1483
  }
1484
  if(op1->packetno!=op2->packetno){
1485
    fprintf(stderr,"op1->packetno != op2->packetno\n");
1486
    return(1);
1487
  }
1488
  return(0);
1489
}
1490
1491
void test_pack(const int *pl, const int **headers, int byteskip,
1492
               int pageskip, int packetskip){
1493
  unsigned char *data=_ogg_malloc(1024*1024); /* for scripted test cases only */
1494
  long inptr=0;
1495
  long outptr=0;
1496
  long deptr=0;
1497
  long depacket=0;
1498
  long granule_pos=7,pageno=0;
1499
  int i,j,packets,pageout=pageskip;
1500
  int eosflag=0;
1501
  int bosflag=0;
1502
1503
  int byteskipcount=0;
1504
1505
  ogg_stream_reset(&os_en);
1506
  ogg_stream_reset(&os_de);
1507
  ogg_sync_reset(&oy);
1508
1509
  for(packets=0;packets<packetskip;packets++)
1510
    depacket+=pl[packets];
1511
1512
  for(packets=0;;packets++)if(pl[packets]==-1)break;
1513
1514
  for(i=0;i<packets;i++){
1515
    /* construct a test packet */
1516
    ogg_packet op;
1517
    int len=pl[i];
1518
1519
    op.packet=data+inptr;
1520
    op.bytes=len;
1521
    op.e_o_s=(pl[i+1]<0?1:0);
1522
    op.granulepos=granule_pos;
1523
1524
    granule_pos+=1024;
1525
1526
    for(j=0;j<len;j++)data[inptr++]=i+j;
1527
1528
    /* submit the test packet */
1529
    ogg_stream_packetin(&os_en,&op);
1530
1531
    /* retrieve any finished pages */
1532
    {
1533
      ogg_page og;
1534
1535
      while(ogg_stream_pageout(&os_en,&og)){
1536
        /* We have a page.  Check it carefully */
1537
1538
        fprintf(stderr,"%ld, ",pageno);
1539
1540
        if(headers[pageno]==NULL){
1541
          fprintf(stderr,"coded too many pages!\n");
1542
          exit(1);
1543
        }
1544
1545
        check_page(data+outptr,headers[pageno],&og);
1546
1547
        outptr+=og.body_len;
1548
        pageno++;
1549
        if(pageskip){
1550
          bosflag=1;
1551
          pageskip--;
1552
          deptr+=og.body_len;
1553
        }
1554
1555
        /* have a complete page; submit it to sync/decode */
1556
1557
        {
1558
          ogg_page og_de;
1559
          ogg_packet op_de,op_de2;
1560
          char *buf=ogg_sync_buffer(&oy,og.header_len+og.body_len);
1561
          char *next=buf;
1562
          byteskipcount+=og.header_len;
1563
          if(byteskipcount>byteskip){
1564
            memcpy(next,og.header,byteskipcount-byteskip);
1565
            next+=byteskipcount-byteskip;
1566
            byteskipcount=byteskip;
1567
          }
1568
1569
          byteskipcount+=og.body_len;
1570
          if(byteskipcount>byteskip){
1571
            memcpy(next,og.body,byteskipcount-byteskip);
1572
            next+=byteskipcount-byteskip;
1573
            byteskipcount=byteskip;
1574
          }
1575
1576
          ogg_sync_wrote(&oy,(long)(next-buf));
1577
1578
          while(1){
1579
            int ret=ogg_sync_pageout(&oy,&og_de);
1580
            if(ret==0)break;
1581
            if(ret<0)continue;
1582
            /* got a page.  Happy happy.  Verify that it's good. */
1583
1584
            fprintf(stderr,"(%d), ",pageout);
1585
1586
            check_page(data+deptr,headers[pageout],&og_de);
1587
            deptr+=og_de.body_len;
1588
            pageout++;
1589
1590
            /* submit it to deconstitution */
1591
            ogg_stream_pagein(&os_de,&og_de);
1592
1593
            /* packets out? */
1594
            while(ogg_stream_packetpeek(&os_de,&op_de2)>0){
1595
              ogg_stream_packetpeek(&os_de,NULL);
1596
              ogg_stream_packetout(&os_de,&op_de); /* just catching them all */
1597
1598
              /* verify peek and out match */
1599
              if(compare_packet(&op_de,&op_de2)){
1600
                fprintf(stderr,"packetout != packetpeek! pos=%ld\n",
1601
                        depacket);
1602
                exit(1);
1603
              }
1604
1605
              /* verify the packet! */
1606
              /* check data */
1607
              if(memcmp(data+depacket,op_de.packet,op_de.bytes)){
1608
                fprintf(stderr,"packet data mismatch in decode! pos=%ld\n",
1609
                        depacket);
1610
                exit(1);
1611
              }
1612
              /* check bos flag */
1613
              if(bosflag==0 && op_de.b_o_s==0){
1614
                fprintf(stderr,"b_o_s flag not set on packet!\n");
1615
                exit(1);
1616
              }
1617
              if(bosflag && op_de.b_o_s){
1618
                fprintf(stderr,"b_o_s flag incorrectly set on packet!\n");
1619
                exit(1);
1620
              }
1621
              bosflag=1;
1622
              depacket+=op_de.bytes;
1623
1624
              /* check eos flag */
1625
              if(eosflag){
1626
                fprintf(stderr,"Multiple decoded packets with eos flag!\n");
1627
                exit(1);
1628
              }
1629
1630
              if(op_de.e_o_s)eosflag=1;
1631
1632
              /* check granulepos flag */
1633
              if(op_de.granulepos!=-1){
1634
                fprintf(stderr," granule:%ld ",(long)op_de.granulepos);
1635
              }
1636
            }
1637
          }
1638
        }
1639
      }
1640
    }
1641
  }
1642
  _ogg_free(data);
1643
  if(headers[pageno]!=NULL){
1644
    fprintf(stderr,"did not write last page!\n");
1645
    exit(1);
1646
  }
1647
  if(headers[pageout]!=NULL){
1648
    fprintf(stderr,"did not decode last page!\n");
1649
    exit(1);
1650
  }
1651
  if(inptr!=outptr){
1652
    fprintf(stderr,"encoded page data incomplete!\n");
1653
    exit(1);
1654
  }
1655
  if(inptr!=deptr){
1656
    fprintf(stderr,"decoded page data incomplete!\n");
1657
    exit(1);
1658
  }
1659
  if(inptr!=depacket){
1660
    fprintf(stderr,"decoded packet data incomplete!\n");
1661
    exit(1);
1662
  }
1663
  if(!eosflag){
1664
    fprintf(stderr,"Never got a packet with EOS set!\n");
1665
    exit(1);
1666
  }
1667
  fprintf(stderr,"ok.\n");
1668
}
1669
1670
int main(void){
1671
1672
  ogg_stream_init(&os_en,0x04030201);
1673
  ogg_stream_init(&os_de,0x04030201);
1674
  ogg_sync_init(&oy);
1675
1676
  /* Exercise each code path in the framing code.  Also verify that
1677
     the checksums are working.  */
1678
1679
  {
1680
    /* 17 only */
1681
    const int packets[]={17, -1};
1682
    const int *headret[]={head1_0,NULL};
1683
1684
    fprintf(stderr,"testing single page encoding... ");
1685
    test_pack(packets,headret,0,0,0);
1686
  }
1687
1688
  {
1689
    /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
1690
    const int packets[]={17, 254, 255, 256, 500, 510, 600, -1};
1691
    const int *headret[]={head1_1,head2_1,NULL};
1692
1693
    fprintf(stderr,"testing basic page encoding... ");
1694
    test_pack(packets,headret,0,0,0);
1695
  }
1696
1697
  {
1698
    /* nil packets; beginning,middle,end */
1699
    const int packets[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1};
1700
    const int *headret[]={head1_2,head2_2,NULL};
1701
1702
    fprintf(stderr,"testing basic nil packets... ");
1703
    test_pack(packets,headret,0,0,0);
1704
  }
1705
1706
  {
1707
    /* large initial packet */
1708
    const int packets[]={4345,259,255,-1};
1709
    const int *headret[]={head1_3,head2_3,NULL};
1710
1711
    fprintf(stderr,"testing initial-packet lacing > 4k... ");
1712
    test_pack(packets,headret,0,0,0);
1713
  }
1714
1715
  {
1716
    /* continuing packet test; with page spill expansion, we have to
1717
       overflow the lacing table. */
1718
    const int packets[]={0,65500,259,255,-1};
1719
    const int *headret[]={head1_4,head2_4,head3_4,NULL};
1720
1721
    fprintf(stderr,"testing single packet page span... ");
1722
    test_pack(packets,headret,0,0,0);
1723
  }
1724
1725
  {
1726
    /* spill expand packet test */
1727
    const int packets[]={0,4345,259,255,0,0,-1};
1728
    const int *headret[]={head1_4b,head2_4b,head3_4b,NULL};
1729
1730
    fprintf(stderr,"testing page spill expansion... ");
1731
    test_pack(packets,headret,0,0,0);
1732
  }
1733
1734
  /* page with the 255 segment limit */
1735
  {
1736
1737
    const int packets[]={0,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,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,50,-1};
1769
    const int *headret[]={head1_5,head2_5,head3_5,NULL};
1770
1771
    fprintf(stderr,"testing max packet segments... ");
1772
    test_pack(packets,headret,0,0,0);
1773
  }
1774
1775
  {
1776
    /* packet that overspans over an entire page */
1777
    const int packets[]={0,100,130049,259,255,-1};
1778
    const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
1779
1780
    fprintf(stderr,"testing very large packets... ");
1781
    test_pack(packets,headret,0,0,0);
1782
  }
1783
1784
#ifndef DISABLE_CRC
1785
  {
1786
    /* test for the libogg 1.1.1 resync in large continuation bug
1787
       found by Josh Coalson)  */
1788
    const int packets[]={0,100,130049,259,255,-1};
1789
    const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
1790
1791
    fprintf(stderr,"testing continuation resync in very large packets... ");
1792
    test_pack(packets,headret,100,2,3);
1793
  }
1794
#else
1795
    fprintf(stderr,"Skipping continuation resync test due to --disable-crc\n");
1796
#endif
1797
1798
  {
1799
    /* term only page.  why not? */
1800
    const int packets[]={0,100,64770,-1};
1801
    const int *headret[]={head1_7,head2_7,head3_7,NULL};
1802
1803
    fprintf(stderr,"testing zero data page (1 nil packet)... ");
1804
    test_pack(packets,headret,0,0,0);
1805
  }
1806
1807
1808
1809
  {
1810
    /* build a bunch of pages for testing */
1811
    unsigned char *data=_ogg_malloc(1024*1024);
1812
    int pl[]={0, 1,1,98,4079, 1,1,2954,2057, 76,34,912,0,234,1000,1000, 1000,300,-1};
1813
    int inptr=0,i,j;
1814
    ogg_page og[5];
1815
1816
    ogg_stream_reset(&os_en);
1817
1818
    for(i=0;pl[i]!=-1;i++){
1819
      ogg_packet op;
1820
      int len=pl[i];
1821
1822
      op.packet=data+inptr;
1823
      op.bytes=len;
1824
      op.e_o_s=(pl[i+1]<0?1:0);
1825
      op.granulepos=(i+1)*1000;
1826
1827
      for(j=0;j<len;j++)data[inptr++]=i+j;
1828
      ogg_stream_packetin(&os_en,&op);
1829
    }
1830
1831
    _ogg_free(data);
1832
1833
    /* retrieve finished pages */
1834
    for(i=0;i<5;i++){
1835
      if(ogg_stream_pageout(&os_en,&og[i])==0){
1836
        fprintf(stderr,"Too few pages output building sync tests!\n");
1837
        exit(1);
1838
      }
1839
      copy_page(&og[i]);
1840
    }
1841
1842
    /* Test lost pages on pagein/packetout: no rollback */
1843
    {
1844
      ogg_page temp;
1845
      ogg_packet test;
1846
1847
      fprintf(stderr,"Testing loss of pages... ");
1848
1849
      ogg_sync_reset(&oy);
1850
      ogg_stream_reset(&os_de);
1851
      for(i=0;i<5;i++){
1852
        memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
1853
               og[i].header_len);
1854
        ogg_sync_wrote(&oy,og[i].header_len);
1855
        memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
1856
        ogg_sync_wrote(&oy,og[i].body_len);
1857
      }
1858
1859
      ogg_sync_pageout(&oy,&temp);
1860
      ogg_stream_pagein(&os_de,&temp);
1861
      ogg_sync_pageout(&oy,&temp);
1862
      ogg_stream_pagein(&os_de,&temp);
1863
      ogg_sync_pageout(&oy,&temp);
1864
      /* skip */
1865
      ogg_sync_pageout(&oy,&temp);
1866
      ogg_stream_pagein(&os_de,&temp);
1867
1868
      /* do we get the expected results/packets? */
1869
1870
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1871
      checkpacket(&test,0,0,0);
1872
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1873
      checkpacket(&test,1,1,-1);
1874
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1875
      checkpacket(&test,1,2,-1);
1876
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1877
      checkpacket(&test,98,3,-1);
1878
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1879
      checkpacket(&test,4079,4,5000);
1880
      if(ogg_stream_packetout(&os_de,&test)!=-1){
1881
        fprintf(stderr,"Error: loss of page did not return error\n");
1882
        exit(1);
1883
      }
1884
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1885
      checkpacket(&test,76,9,-1);
1886
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1887
      checkpacket(&test,34,10,-1);
1888
      fprintf(stderr,"ok.\n");
1889
    }
1890
1891
    /* Test lost pages on pagein/packetout: rollback with continuation */
1892
    {
1893
      ogg_page temp;
1894
      ogg_packet test;
1895
1896
      fprintf(stderr,"Testing loss of pages (rollback required)... ");
1897
1898
      ogg_sync_reset(&oy);
1899
      ogg_stream_reset(&os_de);
1900
      for(i=0;i<5;i++){
1901
        memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
1902
               og[i].header_len);
1903
        ogg_sync_wrote(&oy,og[i].header_len);
1904
        memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
1905
        ogg_sync_wrote(&oy,og[i].body_len);
1906
      }
1907
1908
      ogg_sync_pageout(&oy,&temp);
1909
      ogg_stream_pagein(&os_de,&temp);
1910
      ogg_sync_pageout(&oy,&temp);
1911
      ogg_stream_pagein(&os_de,&temp);
1912
      ogg_sync_pageout(&oy,&temp);
1913
      ogg_stream_pagein(&os_de,&temp);
1914
      ogg_sync_pageout(&oy,&temp);
1915
      /* skip */
1916
      ogg_sync_pageout(&oy,&temp);
1917
      ogg_stream_pagein(&os_de,&temp);
1918
1919
      /* do we get the expected results/packets? */
1920
1921
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1922
      checkpacket(&test,0,0,0);
1923
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1924
      checkpacket(&test,1,1,-1);
1925
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1926
      checkpacket(&test,1,2,-1);
1927
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1928
      checkpacket(&test,98,3,-1);
1929
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1930
      checkpacket(&test,4079,4,5000);
1931
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1932
      checkpacket(&test,1,5,-1);
1933
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1934
      checkpacket(&test,1,6,-1);
1935
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1936
      checkpacket(&test,2954,7,-1);
1937
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1938
      checkpacket(&test,2057,8,9000);
1939
      if(ogg_stream_packetout(&os_de,&test)!=-1){
1940
        fprintf(stderr,"Error: loss of page did not return error\n");
1941
        exit(1);
1942
      }
1943
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1944
      checkpacket(&test,300,17,18000);
1945
      fprintf(stderr,"ok.\n");
1946
    }
1947
1948
    /* the rest only test sync */
1949
    {
1950
      ogg_page og_de;
1951
      /* Test fractional page inputs: incomplete capture */
1952
      fprintf(stderr,"Testing sync on partial inputs... ");
1953
      ogg_sync_reset(&oy);
1954
      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
1955
             3);
1956
      ogg_sync_wrote(&oy,3);
1957
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
1958
1959
      /* Test fractional page inputs: incomplete fixed header */
1960
      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+3,
1961
             20);
1962
      ogg_sync_wrote(&oy,20);
1963
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
1964
1965
      /* Test fractional page inputs: incomplete header */
1966
      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+23,
1967
             5);
1968
      ogg_sync_wrote(&oy,5);
1969
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
1970
1971
      /* Test fractional page inputs: incomplete body */
1972
1973
      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+28,
1974
             og[1].header_len-28);
1975
      ogg_sync_wrote(&oy,og[1].header_len-28);
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
      ogg_sync_wrote(&oy,1000);
1980
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
1981
1982
      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body+1000,
1983
             og[1].body_len-1000);
1984
      ogg_sync_wrote(&oy,og[1].body_len-1000);
1985
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();
1986
1987
      fprintf(stderr,"ok.\n");
1988
    }
1989
1990
    /* Test fractional page inputs: page + incomplete capture */
1991
    {
1992
      ogg_page og_de;
1993
      fprintf(stderr,"Testing sync on 1+partial inputs... ");
1994
      ogg_sync_reset(&oy);
1995
1996
      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
1997
             og[1].header_len);
1998
      ogg_sync_wrote(&oy,og[1].header_len);
1999
2000
      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2001
             og[1].body_len);
2002
      ogg_sync_wrote(&oy,og[1].body_len);
2003
2004
      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
2005
             20);
2006
      ogg_sync_wrote(&oy,20);
2007
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2008
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
2009
2010
      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+20,
2011
             og[1].header_len-20);
2012
      ogg_sync_wrote(&oy,og[1].header_len-20);
2013
      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2014
             og[1].body_len);
2015
      ogg_sync_wrote(&oy,og[1].body_len);
2016
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2017
2018
      fprintf(stderr,"ok.\n");
2019
    }
2020
2021
    /* Test recapture: garbage + page */
2022
    {
2023
      ogg_page og_de;
2024
      fprintf(stderr,"Testing search for capture... ");
2025
      ogg_sync_reset(&oy);
2026
2027
      /* 'garbage' */
2028
      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2029
             og[1].body_len);
2030
      ogg_sync_wrote(&oy,og[1].body_len);
2031
2032
      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
2033
             og[1].header_len);
2034
      ogg_sync_wrote(&oy,og[1].header_len);
2035
2036
      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2037
             og[1].body_len);
2038
      ogg_sync_wrote(&oy,og[1].body_len);
2039
2040
      memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
2041
             20);
2042
      ogg_sync_wrote(&oy,20);
2043
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
2044
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2045
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
2046
2047
      memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header+20,
2048
             og[2].header_len-20);
2049
      ogg_sync_wrote(&oy,og[2].header_len-20);
2050
      memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
2051
             og[2].body_len);
2052
      ogg_sync_wrote(&oy,og[2].body_len);
2053
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2054
2055
      fprintf(stderr,"ok.\n");
2056
    }
2057
2058
#ifndef DISABLE_CRC
2059
    /* Test recapture: page + garbage + page */
2060
    {
2061
      ogg_page og_de;
2062
      fprintf(stderr,"Testing recapture... ");
2063
      ogg_sync_reset(&oy);
2064
2065
      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
2066
             og[1].header_len);
2067
      ogg_sync_wrote(&oy,og[1].header_len);
2068
2069
      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2070
             og[1].body_len);
2071
      ogg_sync_wrote(&oy,og[1].body_len);
2072
2073
      memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
2074
             og[2].header_len);
2075
      ogg_sync_wrote(&oy,og[2].header_len);
2076
2077
      memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
2078
             og[2].header_len);
2079
      ogg_sync_wrote(&oy,og[2].header_len);
2080
2081
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2082
2083
      memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
2084
             og[2].body_len-5);
2085
      ogg_sync_wrote(&oy,og[2].body_len-5);
2086
2087
      memcpy(ogg_sync_buffer(&oy,og[3].header_len),og[3].header,
2088
             og[3].header_len);
2089
      ogg_sync_wrote(&oy,og[3].header_len);
2090
2091
      memcpy(ogg_sync_buffer(&oy,og[3].body_len),og[3].body,
2092
             og[3].body_len);
2093
      ogg_sync_wrote(&oy,og[3].body_len);
2094
2095
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
2096
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2097
2098
      fprintf(stderr,"ok.\n");
2099
    }
2100
#else
2101
    fprintf(stderr,"Skipping recapture test due to --disable-crc\n");
2102
#endif
2103
2104
    /* Free page data that was previously copied */
2105
    {
2106
      for(i=0;i<5;i++){
2107
        free_page(&og[i]);
2108
      }
2109
    }
2110
  }
2111
  ogg_sync_clear(&oy);
2112
  ogg_stream_clear(&os_en);
2113
  ogg_stream_clear(&os_de);
2114
2115
  return(0);
2116
}
2117
2118
#endif