Coverage Report

Created: 2025-07-11 06:15

/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
34.9k
int ogg_page_version(const ogg_page *og){
34
34.9k
  return((int)(og->header[4]));
35
34.9k
}
36
37
34.9k
int ogg_page_continued(const ogg_page *og){
38
34.9k
  return((int)(og->header[5]&0x01));
39
34.9k
}
40
41
56.0k
int ogg_page_bos(const ogg_page *og){
42
56.0k
  return((int)(og->header[5]&0x02));
43
56.0k
}
44
45
34.9k
int ogg_page_eos(const ogg_page *og){
46
34.9k
  return((int)(og->header[5]&0x04));
47
34.9k
}
48
49
34.9k
ogg_int64_t ogg_page_granulepos(const ogg_page *og){
50
34.9k
  unsigned char *page=og->header;
51
34.9k
  ogg_uint64_t granulepos=page[13]&(0xff);
52
34.9k
  granulepos= (granulepos<<8)|(page[12]&0xff);
53
34.9k
  granulepos= (granulepos<<8)|(page[11]&0xff);
54
34.9k
  granulepos= (granulepos<<8)|(page[10]&0xff);
55
34.9k
  granulepos= (granulepos<<8)|(page[9]&0xff);
56
34.9k
  granulepos= (granulepos<<8)|(page[8]&0xff);
57
34.9k
  granulepos= (granulepos<<8)|(page[7]&0xff);
58
34.9k
  granulepos= (granulepos<<8)|(page[6]&0xff);
59
34.9k
  return((ogg_int64_t)granulepos);
60
34.9k
}
61
62
83.6k
int ogg_page_serialno(const ogg_page *og){
63
83.6k
  return((int)((ogg_uint32_t)og->header[14]) |
64
83.6k
              ((ogg_uint32_t)og->header[15]<<8) |
65
83.6k
              ((ogg_uint32_t)og->header[16]<<16) |
66
83.6k
              ((ogg_uint32_t)og->header[17]<<24));
67
83.6k
}
68
69
34.9k
long ogg_page_pageno(const ogg_page *og){
70
34.9k
  return((long)((ogg_uint32_t)og->header[18]) |
71
34.9k
               ((ogg_uint32_t)og->header[19]<<8) |
72
34.9k
               ((ogg_uint32_t)og->header[20]<<16) |
73
34.9k
               ((ogg_uint32_t)og->header[21]<<24));
74
34.9k
}
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
4.35k
int ogg_stream_init(ogg_stream_state *os,int serialno){
134
4.35k
  if(os){
135
4.35k
    memset(os,0,sizeof(*os));
136
4.35k
    os->body_storage=16*1024;
137
4.35k
    os->lacing_storage=1024;
138
139
4.35k
    os->body_data=_ogg_malloc(os->body_storage*sizeof(*os->body_data));
140
4.35k
    os->lacing_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->lacing_vals));
141
4.35k
    os->granule_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->granule_vals));
142
143
4.35k
    if(!os->body_data || !os->lacing_vals || !os->granule_vals){
144
0
      ogg_stream_clear(os);
145
0
      return -1;
146
0
    }
147
148
4.35k
    os->serialno=serialno;
149
150
4.35k
    return(0);
151
4.35k
  }
152
0
  return(-1);
153
4.35k
}
154
155
/* async/delayed error detection for the ogg_stream_state */
156
213k
int ogg_stream_check(ogg_stream_state *os){
157
213k
  if(!os || !os->body_data) return -1;
158
213k
  return 0;
159
213k
}
160
161
/* _clear does not free os, only the non-flat storage within */
162
4.35k
int ogg_stream_clear(ogg_stream_state *os){
163
4.35k
  if(os){
164
4.35k
    if(os->body_data)_ogg_free(os->body_data);
165
4.35k
    if(os->lacing_vals)_ogg_free(os->lacing_vals);
166
4.35k
    if(os->granule_vals)_ogg_free(os->granule_vals);
167
168
4.35k
    memset(os,0,sizeof(*os));
169
4.35k
  }
170
4.35k
  return(0);
171
4.35k
}
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
28.6k
static int _os_body_expand(ogg_stream_state *os,long needed){
185
28.6k
  if(os->body_storage-needed<=os->body_fill){
186
19
    long body_storage;
187
19
    void *ret;
188
19
    if(os->body_storage>LONG_MAX-needed){
189
0
      ogg_stream_clear(os);
190
0
      return -1;
191
0
    }
192
19
    body_storage=os->body_storage+needed;
193
19
    if(body_storage<LONG_MAX-1024)body_storage+=1024;
194
19
    ret=_ogg_realloc(os->body_data,body_storage*sizeof(*os->body_data));
195
19
    if(!ret){
196
0
      ogg_stream_clear(os);
197
0
      return -1;
198
0
    }
199
19
    os->body_storage=body_storage;
200
19
    os->body_data=ret;
201
19
  }
202
28.6k
  return 0;
203
28.6k
}
204
205
34.1k
static int _os_lacing_expand(ogg_stream_state *os,long needed){
206
34.1k
  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
34.1k
  return 0;
231
34.1k
}
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
67.3k
static ogg_uint32_t _os_update_crc(ogg_uint32_t crc, unsigned char *buffer, int size){
238
449k
  while (size>=8){
239
381k
    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
381k
    crc=crc_lookup[7][ crc>>24      ]^crc_lookup[6][(crc>>16)&0xFF]^
242
381k
        crc_lookup[5][(crc>> 8)&0xFF]^crc_lookup[4][ crc     &0xFF]^
243
381k
        crc_lookup[3][buffer[4]     ]^crc_lookup[2][buffer[5]     ]^
244
381k
        crc_lookup[1][buffer[6]     ]^crc_lookup[0][buffer[7]     ];
245
246
381k
    buffer+=8;
247
381k
    size-=8;
248
381k
  }
249
250
290k
  while (size--)
251
222k
    crc=(crc<<8)^crc_lookup[0][((crc >> 24)&0xff)^*buffer++];
252
67.3k
  return crc;
253
67.3k
}
254
255
33.6k
void ogg_page_checksum_set(ogg_page *og){
256
33.6k
  if(og){
257
33.6k
    ogg_uint32_t crc_reg=0;
258
259
    /* safety; needed for API behavior, but not framing code */
260
33.6k
    og->header[22]=0;
261
33.6k
    og->header[23]=0;
262
33.6k
    og->header[24]=0;
263
33.6k
    og->header[25]=0;
264
265
33.6k
    crc_reg=_os_update_crc(crc_reg,og->header,og->header_len);
266
33.6k
    crc_reg=_os_update_crc(crc_reg,og->body,og->body_len);
267
268
33.6k
    og->header[22]=(unsigned char)(crc_reg&0xff);
269
33.6k
    og->header[23]=(unsigned char)((crc_reg>>8)&0xff);
270
33.6k
    og->header[24]=(unsigned char)((crc_reg>>16)&0xff);
271
33.6k
    og->header[25]=(unsigned char)((crc_reg>>24)&0xff);
272
33.6k
  }
273
33.6k
}
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
4.35k
int ogg_sync_init(ogg_sync_state *oy){
559
4.35k
  if(oy){
560
4.35k
    oy->storage = -1; /* used as a readiness flag */
561
4.35k
    memset(oy,0,sizeof(*oy));
562
4.35k
  }
563
4.35k
  return(0);
564
4.35k
}
565
566
/* clear non-flat storage within */
567
4.35k
int ogg_sync_clear(ogg_sync_state *oy){
568
4.35k
  if(oy){
569
4.35k
    if(oy->data)_ogg_free(oy->data);
570
4.35k
    memset(oy,0,sizeof(*oy));
571
4.35k
  }
572
4.35k
  return(0);
573
4.35k
}
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
71.4k
int ogg_sync_check(ogg_sync_state *oy){
584
71.4k
  if(oy->storage<0) return -1;
585
71.4k
  return 0;
586
71.4k
}
587
588
9.74k
char *ogg_sync_buffer(ogg_sync_state *oy, long size){
589
9.74k
  if(ogg_sync_check(oy)) return NULL;
590
591
  /* first, clear out any space that has been previously returned */
592
9.74k
  if(oy->returned){
593
4.50k
    oy->fill-=oy->returned;
594
4.50k
    if(oy->fill>0)
595
2.54k
      memmove(oy->data,oy->data+oy->returned,oy->fill);
596
4.50k
    oy->returned=0;
597
4.50k
  }
598
599
9.74k
  if(size>oy->storage-oy->fill){
600
    /* We need to extend the internal buffer */
601
4.44k
    long newsize;
602
4.44k
    void *ret;
603
604
4.44k
    if(size>INT_MAX-4096-oy->fill){
605
0
      ogg_sync_clear(oy);
606
0
      return NULL;
607
0
    }
608
4.44k
    newsize=size+oy->fill+4096; /* an extra page to be nice */
609
4.44k
    if(oy->data)
610
83
      ret=_ogg_realloc(oy->data,newsize);
611
4.35k
    else
612
4.35k
      ret=_ogg_malloc(newsize);
613
4.44k
    if(!ret){
614
0
      ogg_sync_clear(oy);
615
0
      return NULL;
616
0
    }
617
4.44k
    oy->data=ret;
618
4.44k
    oy->storage=newsize;
619
4.44k
  }
620
621
  /* expose a segment at least as large as requested at the fill mark */
622
9.74k
  return((char *)oy->data+oy->fill);
623
9.74k
}
624
625
7.04k
int ogg_sync_wrote(ogg_sync_state *oy, long bytes){
626
7.04k
  if(ogg_sync_check(oy))return -1;
627
7.04k
  if(oy->fill+bytes>oy->storage)return -1;
628
7.04k
  oy->fill+=bytes;
629
7.04k
  return(0);
630
7.04k
}
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
54.6k
long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){
643
54.6k
  unsigned char *page;
644
54.6k
  unsigned char *next;
645
54.6k
  long bytes;
646
647
54.6k
  if(ogg_sync_check(oy))return 0;
648
649
54.6k
  page=oy->data+oy->returned;
650
54.6k
  bytes=oy->fill-oy->returned;
651
652
54.6k
  if(oy->headerbytes==0){
653
52.8k
    int headerbytes,i;
654
52.8k
    if(bytes<27)return(0); /* not enough for a header */
655
656
    /* verify capture pattern */
657
45.1k
    if(memcmp(page,"OggS",4))goto sync_fail;
658
659
33.9k
    headerbytes=page[26]+27;
660
33.9k
    if(bytes<headerbytes)return(0); /* not enough for header + seg table */
661
662
    /* count up body length in the segment table */
663
664
151k
    for(i=0;i<page[26];i++)
665
118k
      oy->bodybytes+=page[27+i];
666
33.8k
    oy->headerbytes=headerbytes;
667
33.8k
  }
668
669
35.5k
  if(oy->bodybytes+oy->headerbytes>bytes)return(0);
670
671
  /* The whole test page is buffered.  Verify the checksum */
672
33.6k
  {
673
    /* Grab the checksum bytes, set the header field to zero */
674
33.6k
    char chksum[4];
675
33.6k
    ogg_page log;
676
677
33.6k
    memcpy(chksum,page+22,4);
678
33.6k
    memset(page+22,0,4);
679
680
    /* set up a temp page struct and recompute the checksum */
681
33.6k
    log.header=page;
682
33.6k
    log.header_len=oy->headerbytes;
683
33.6k
    log.body=page+oy->headerbytes;
684
33.6k
    log.body_len=oy->bodybytes;
685
33.6k
    ogg_page_checksum_set(&log);
686
687
    /* Compare */
688
33.6k
    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
32.6k
      memcpy(page+22,chksum,4);
693
694
#ifndef DISABLE_CRC
695
      /* Bad checksum. Lose sync */
696
      goto sync_fail;
697
#endif
698
32.6k
    }
699
33.6k
  }
700
701
  /* yes, have a whole page all ready to go */
702
33.6k
  {
703
33.6k
    if(og){
704
33.6k
      og->header=page;
705
33.6k
      og->header_len=oy->headerbytes;
706
33.6k
      og->body=page+oy->headerbytes;
707
33.6k
      og->body_len=oy->bodybytes;
708
33.6k
    }
709
710
33.6k
    oy->unsynced=0;
711
33.6k
    oy->returned+=(bytes=oy->headerbytes+oy->bodybytes);
712
33.6k
    oy->headerbytes=0;
713
33.6k
    oy->bodybytes=0;
714
33.6k
    return(bytes);
715
35.5k
  }
716
717
11.1k
 sync_fail:
718
719
11.1k
  oy->headerbytes=0;
720
11.1k
  oy->bodybytes=0;
721
722
  /* search for possible capture */
723
11.1k
  next=memchr(page+1,'O',bytes-1);
724
11.1k
  if(!next)
725
371
    next=oy->data+oy->fill;
726
727
11.1k
  oy->returned=(int)(next-oy->data);
728
11.1k
  return((long)-(next-page));
729
35.5k
}
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
34.9k
int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){
776
34.9k
  unsigned char *header=og->header;
777
34.9k
  unsigned char *body=og->body;
778
34.9k
  long           bodysize=og->body_len;
779
34.9k
  int            segptr=0;
780
781
34.9k
  int version=ogg_page_version(og);
782
34.9k
  int continued=ogg_page_continued(og);
783
34.9k
  int bos=ogg_page_bos(og);
784
34.9k
  int eos=ogg_page_eos(og);
785
34.9k
  ogg_int64_t granulepos=ogg_page_granulepos(og);
786
34.9k
  int serialno=ogg_page_serialno(og);
787
34.9k
  long pageno=ogg_page_pageno(og);
788
34.9k
  int segments=header[26];
789
790
34.9k
  if(ogg_stream_check(os)) return -1;
791
792
  /* clean up 'returned data' */
793
34.9k
  {
794
34.9k
    long lr=os->lacing_returned;
795
34.9k
    long br=os->body_returned;
796
797
    /* body data */
798
34.9k
    if(br){
799
19.4k
      os->body_fill-=br;
800
19.4k
      if(os->body_fill)
801
2.89k
        memmove(os->body_data,os->body_data+br,os->body_fill);
802
19.4k
      os->body_returned=0;
803
19.4k
    }
804
805
34.9k
    if(lr){
806
      /* segment table */
807
20.1k
      if(os->lacing_fill-lr){
808
3.39k
        memmove(os->lacing_vals,os->lacing_vals+lr,
809
3.39k
                (os->lacing_fill-lr)*sizeof(*os->lacing_vals));
810
3.39k
        memmove(os->granule_vals,os->granule_vals+lr,
811
3.39k
                (os->lacing_fill-lr)*sizeof(*os->granule_vals));
812
3.39k
      }
813
20.1k
      os->lacing_fill-=lr;
814
20.1k
      os->lacing_packet-=lr;
815
20.1k
      os->lacing_returned=0;
816
20.1k
    }
817
34.9k
  }
818
819
  /* check the serial number */
820
34.9k
  if(serialno!=os->serialno)return(-1);
821
34.7k
  if(version>0)return(-1);
822
823
34.1k
  if(_os_lacing_expand(os,segments+1)) return -1;
824
825
  /* are we in sequence? */
826
34.1k
  if(pageno!=os->pageno){
827
22.6k
    int i;
828
829
    /* unroll previous partial packet (if any) */
830
23.0k
    for(i=os->lacing_packet;i<os->lacing_fill;i++)
831
358
      os->body_fill-=os->lacing_vals[i]&0xff;
832
22.6k
    os->lacing_fill=os->lacing_packet;
833
834
    /* make a note of dropped data in segment table */
835
22.6k
    if(os->pageno!=-1){
836
8.54k
      os->lacing_vals[os->lacing_fill++]=0x400;
837
8.54k
      os->lacing_packet++;
838
8.54k
    }
839
22.6k
  }
840
841
  /* are we a 'continued packet' page?  If so, we may need to skip
842
     some segments */
843
34.1k
  if(continued){
844
3.16k
    if(os->lacing_fill<1 ||
845
3.16k
       (os->lacing_vals[os->lacing_fill-1]&0xff)<255 ||
846
3.16k
       os->lacing_vals[os->lacing_fill-1]==0x400){
847
3.06k
      bos=0;
848
3.26k
      for(;segptr<segments;segptr++){
849
1.33k
        int val=header[27+segptr];
850
1.33k
        body+=val;
851
1.33k
        bodysize-=val;
852
1.33k
        if(val<255){
853
1.13k
          segptr++;
854
1.13k
          break;
855
1.13k
        }
856
1.33k
      }
857
3.06k
    }
858
3.16k
  }
859
860
34.1k
  if(bodysize){
861
28.6k
    if(_os_body_expand(os,bodysize)) return -1;
862
28.6k
    memcpy(os->body_data+os->body_fill,body,bodysize);
863
28.6k
    os->body_fill+=bodysize;
864
28.6k
  }
865
866
34.1k
  {
867
34.1k
    int saved=-1;
868
163k
    while(segptr<segments){
869
129k
      int val=header[27+segptr];
870
129k
      os->lacing_vals[os->lacing_fill]=val;
871
129k
      os->granule_vals[os->lacing_fill]=-1;
872
873
129k
      if(bos){
874
16.9k
        os->lacing_vals[os->lacing_fill]|=0x100;
875
16.9k
        bos=0;
876
16.9k
      }
877
878
129k
      if(val<255)saved=os->lacing_fill;
879
880
129k
      os->lacing_fill++;
881
129k
      segptr++;
882
883
129k
      if(val<255)os->lacing_packet=os->lacing_fill;
884
129k
    }
885
886
    /* set the granulepos on the last granuleval of the last full packet */
887
34.1k
    if(saved!=-1){
888
29.2k
      os->granule_vals[saved]=granulepos;
889
29.2k
    }
890
891
34.1k
  }
892
893
34.1k
  if(eos){
894
13.6k
    os->e_o_s=1;
895
13.6k
    if(os->lacing_fill>0)
896
11.5k
      os->lacing_vals[os->lacing_fill-1]|=0x200;
897
13.6k
  }
898
899
34.1k
  os->pageno=pageno+1;
900
901
34.1k
  return(0);
902
34.1k
}
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
14.3k
int ogg_stream_reset(ogg_stream_state *os){
917
14.3k
  if(ogg_stream_check(os)) return -1;
918
919
14.3k
  os->body_fill=0;
920
14.3k
  os->body_returned=0;
921
922
14.3k
  os->lacing_fill=0;
923
14.3k
  os->lacing_packet=0;
924
14.3k
  os->lacing_returned=0;
925
926
14.3k
  os->header_fill=0;
927
928
14.3k
  os->e_o_s=0;
929
14.3k
  os->b_o_s=0;
930
14.3k
  os->pageno=-1;
931
14.3k
  os->packetno=0;
932
14.3k
  os->granulepos=0;
933
934
14.3k
  return(0);
935
14.3k
}
936
937
14.3k
int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno){
938
14.3k
  if(ogg_stream_check(os)) return -1;
939
14.3k
  ogg_stream_reset(os);
940
14.3k
  os->serialno=serialno;
941
14.3k
  return(0);
942
14.3k
}
943
944
149k
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
149k
  int ptr=os->lacing_returned;
951
952
149k
  if(os->lacing_packet<=ptr)return(0);
953
954
129k
  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
8.51k
    os->lacing_returned++;
958
8.51k
    os->packetno++;
959
8.51k
    return(-1);
960
8.51k
  }
961
962
121k
  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
121k
  {
968
121k
    int size=os->lacing_vals[ptr]&0xff;
969
121k
    long bytes=size;
970
121k
    int eos=os->lacing_vals[ptr]&0x200; /* last packet of the stream? */
971
121k
    int bos=os->lacing_vals[ptr]&0x100; /* first packet of the stream? */
972
973
124k
    while(size==255){
974
2.70k
      int val=os->lacing_vals[++ptr];
975
2.70k
      size=val&0xff;
976
2.70k
      if(val&0x200)eos=0x200;
977
2.70k
      bytes+=size;
978
2.70k
    }
979
980
121k
    if(op){
981
121k
      op->e_o_s=eos;
982
121k
      op->b_o_s=bos;
983
121k
      op->packet=os->body_data+os->body_returned;
984
121k
      op->packetno=os->packetno;
985
121k
      op->granulepos=os->granule_vals[ptr];
986
121k
      op->bytes=bytes;
987
121k
    }
988
989
121k
    if(adv){
990
121k
      os->body_returned+=bytes;
991
121k
      os->lacing_returned=ptr+1;
992
121k
      os->packetno++;
993
121k
    }
994
121k
  }
995
121k
  return(1);
996
121k
}
997
998
149k
int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op){
999
149k
  if(ogg_stream_check(os)) return 0;
1000
149k
  return _packetout(os,op,1);
1001
149k
}
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
static int copy_page(ogg_page *og){
1111
  unsigned char *temp=_ogg_malloc(og->header_len);
1112
  if (!temp)
1113
    return -1;
1114
  memcpy(temp,og->header,og->header_len);
1115
  og->header=temp;
1116
1117
  temp=_ogg_malloc(og->body_len);
1118
  if (!temp)
1119
    return -1;
1120
  memcpy(temp,og->body,og->body_len);
1121
  og->body=temp;
1122
  return 0;
1123
}
1124
1125
static void free_page(ogg_page *og){
1126
  _ogg_free (og->header);
1127
  og->header=NULL;
1128
  _ogg_free (og->body);
1129
  og->body=NULL;
1130
}
1131
1132
void error(void){
1133
  fprintf(stderr,"error!\n");
1134
  exit(1);
1135
}
1136
1137
/* 17 only */
1138
const int head1_0[] = {0x4f,0x67,0x67,0x53,0,0x06,
1139
                       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1140
                       0x01,0x02,0x03,0x04,0,0,0,0,
1141
                       0x15,0xed,0xec,0x91,
1142
                       1,
1143
                       17};
1144
1145
/* 17, 254, 255, 256, 500, 510, 600 byte, pad */
1146
const int head1_1[] = {0x4f,0x67,0x67,0x53,0,0x02,
1147
                       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1148
                       0x01,0x02,0x03,0x04,0,0,0,0,
1149
                       0x59,0x10,0x6c,0x2c,
1150
                       1,
1151
                       17};
1152
const int head2_1[] = {0x4f,0x67,0x67,0x53,0,0x04,
1153
                       0x07,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
1154
                       0x01,0x02,0x03,0x04,1,0,0,0,
1155
                       0x89,0x33,0x85,0xce,
1156
                       13,
1157
                       254,255,0,255,1,255,245,255,255,0,
1158
                       255,255,90};
1159
1160
/* nil packets; beginning,middle,end */
1161
const int head1_2[] = {0x4f,0x67,0x67,0x53,0,0x02,
1162
                       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1163
                       0x01,0x02,0x03,0x04,0,0,0,0,
1164
                       0xff,0x7b,0x23,0x17,
1165
                       1,
1166
                       0};
1167
const int head2_2[] = {0x4f,0x67,0x67,0x53,0,0x04,
1168
                       0x07,0x28,0x00,0x00,0x00,0x00,0x00,0x00,
1169
                       0x01,0x02,0x03,0x04,1,0,0,0,
1170
                       0x5c,0x3f,0x66,0xcb,
1171
                       17,
1172
                       17,254,255,0,0,255,1,0,255,245,255,255,0,
1173
                       255,255,90,0};
1174
1175
/* large initial packet */
1176
const int head1_3[] = {0x4f,0x67,0x67,0x53,0,0x02,
1177
                       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1178
                       0x01,0x02,0x03,0x04,0,0,0,0,
1179
                       0x01,0x27,0x31,0xaa,
1180
                       18,
1181
                       255,255,255,255,255,255,255,255,
1182
                       255,255,255,255,255,255,255,255,255,10};
1183
1184
const int head2_3[] = {0x4f,0x67,0x67,0x53,0,0x04,
1185
                       0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
1186
                       0x01,0x02,0x03,0x04,1,0,0,0,
1187
                       0x7f,0x4e,0x8a,0xd2,
1188
                       4,
1189
                       255,4,255,0};
1190
1191
1192
/* continuing packet test */
1193
const int head1_4[] = {0x4f,0x67,0x67,0x53,0,0x02,
1194
                       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1195
                       0x01,0x02,0x03,0x04,0,0,0,0,
1196
                       0xff,0x7b,0x23,0x17,
1197
                       1,
1198
                       0};
1199
1200
const int head2_4[] = {0x4f,0x67,0x67,0x53,0,0x00,
1201
                       0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
1202
                       0x01,0x02,0x03,0x04,1,0,0,0,
1203
                       0xf8,0x3c,0x19,0x79,
1204
                       255,
1205
                       255,255,255,255,255,255,255,255,
1206
                       255,255,255,255,255,255,255,255,
1207
                       255,255,255,255,255,255,255,255,
1208
                       255,255,255,255,255,255,255,255,
1209
                       255,255,255,255,255,255,255,255,
1210
                       255,255,255,255,255,255,255,255,
1211
                       255,255,255,255,255,255,255,255,
1212
                       255,255,255,255,255,255,255,255,
1213
                       255,255,255,255,255,255,255,255,
1214
                       255,255,255,255,255,255,255,255,
1215
                       255,255,255,255,255,255,255,255,
1216
                       255,255,255,255,255,255,255,255,
1217
                       255,255,255,255,255,255,255,255,
1218
                       255,255,255,255,255,255,255,255,
1219
                       255,255,255,255,255,255,255,255,
1220
                       255,255,255,255,255,255,255,255,
1221
                       255,255,255,255,255,255,255,255,
1222
                       255,255,255,255,255,255,255,255,
1223
                       255,255,255,255,255,255,255,255,
1224
                       255,255,255,255,255,255,255,255,
1225
                       255,255,255,255,255,255,255,255,
1226
                       255,255,255,255,255,255,255,255,
1227
                       255,255,255,255,255,255,255,255,
1228
                       255,255,255,255,255,255,255,255,
1229
                       255,255,255,255,255,255,255,255,
1230
                       255,255,255,255,255,255,255,255,
1231
                       255,255,255,255,255,255,255,255,
1232
                       255,255,255,255,255,255,255,255,
1233
                       255,255,255,255,255,255,255,255,
1234
                       255,255,255,255,255,255,255,255,
1235
                       255,255,255,255,255,255,255,255,
1236
                       255,255,255,255,255,255,255};
1237
1238
const int head3_4[] = {0x4f,0x67,0x67,0x53,0,0x05,
1239
                       0x07,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,
1240
                       0x01,0x02,0x03,0x04,2,0,0,0,
1241
                       0x38,0xe6,0xb6,0x28,
1242
                       6,
1243
                       255,220,255,4,255,0};
1244
1245
1246
/* spill expansion test */
1247
const int head1_4b[] = {0x4f,0x67,0x67,0x53,0,0x02,
1248
                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1249
                        0x01,0x02,0x03,0x04,0,0,0,0,
1250
                        0xff,0x7b,0x23,0x17,
1251
                        1,
1252
                        0};
1253
1254
const int head2_4b[] = {0x4f,0x67,0x67,0x53,0,0x00,
1255
                        0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
1256
                        0x01,0x02,0x03,0x04,1,0,0,0,
1257
                        0xce,0x8f,0x17,0x1a,
1258
                        23,
1259
                        255,255,255,255,255,255,255,255,
1260
                        255,255,255,255,255,255,255,255,255,10,255,4,255,0,0};
1261
1262
1263
const int head3_4b[] = {0x4f,0x67,0x67,0x53,0,0x04,
1264
                        0x07,0x14,0x00,0x00,0x00,0x00,0x00,0x00,
1265
                        0x01,0x02,0x03,0x04,2,0,0,0,
1266
                        0x9b,0xb2,0x50,0xa1,
1267
                        1,
1268
                        0};
1269
1270
/* page with the 255 segment limit */
1271
const int head1_5[] = {0x4f,0x67,0x67,0x53,0,0x02,
1272
                       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1273
                       0x01,0x02,0x03,0x04,0,0,0,0,
1274
                       0xff,0x7b,0x23,0x17,
1275
                       1,
1276
                       0};
1277
1278
const int head2_5[] = {0x4f,0x67,0x67,0x53,0,0x00,
1279
                       0x07,0xfc,0x03,0x00,0x00,0x00,0x00,0x00,
1280
                       0x01,0x02,0x03,0x04,1,0,0,0,
1281
                       0xed,0x2a,0x2e,0xa7,
1282
                       255,
1283
                       10,10,10,10,10,10,10,10,
1284
                       10,10,10,10,10,10,10,10,
1285
                       10,10,10,10,10,10,10,10,
1286
                       10,10,10,10,10,10,10,10,
1287
                       10,10,10,10,10,10,10,10,
1288
                       10,10,10,10,10,10,10,10,
1289
                       10,10,10,10,10,10,10,10,
1290
                       10,10,10,10,10,10,10,10,
1291
                       10,10,10,10,10,10,10,10,
1292
                       10,10,10,10,10,10,10,10,
1293
                       10,10,10,10,10,10,10,10,
1294
                       10,10,10,10,10,10,10,10,
1295
                       10,10,10,10,10,10,10,10,
1296
                       10,10,10,10,10,10,10,10,
1297
                       10,10,10,10,10,10,10,10,
1298
                       10,10,10,10,10,10,10,10,
1299
                       10,10,10,10,10,10,10,10,
1300
                       10,10,10,10,10,10,10,10,
1301
                       10,10,10,10,10,10,10,10,
1302
                       10,10,10,10,10,10,10,10,
1303
                       10,10,10,10,10,10,10,10,
1304
                       10,10,10,10,10,10,10,10,
1305
                       10,10,10,10,10,10,10,10,
1306
                       10,10,10,10,10,10,10,10,
1307
                       10,10,10,10,10,10,10,10,
1308
                       10,10,10,10,10,10,10,10,
1309
                       10,10,10,10,10,10,10,10,
1310
                       10,10,10,10,10,10,10,10,
1311
                       10,10,10,10,10,10,10,10,
1312
                       10,10,10,10,10,10,10,10,
1313
                       10,10,10,10,10,10,10,10,
1314
                       10,10,10,10,10,10,10};
1315
1316
const int head3_5[] = {0x4f,0x67,0x67,0x53,0,0x04,
1317
                       0x07,0x00,0x04,0x00,0x00,0x00,0x00,0x00,
1318
                       0x01,0x02,0x03,0x04,2,0,0,0,
1319
                       0x6c,0x3b,0x82,0x3d,
1320
                       1,
1321
                       50};
1322
1323
1324
/* packet that overspans over an entire page */
1325
const int head1_6[] = {0x4f,0x67,0x67,0x53,0,0x02,
1326
                       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1327
                       0x01,0x02,0x03,0x04,0,0,0,0,
1328
                       0xff,0x7b,0x23,0x17,
1329
                       1,
1330
                       0};
1331
1332
const int head2_6[] = {0x4f,0x67,0x67,0x53,0,0x00,
1333
                       0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
1334
                       0x01,0x02,0x03,0x04,1,0,0,0,
1335
                       0x68,0x22,0x7c,0x3d,
1336
                       255,
1337
                       100,
1338
                       255,255,255,255,255,255,255,255,
1339
                       255,255,255,255,255,255,255,255,
1340
                       255,255,255,255,255,255,255,255,
1341
                       255,255,255,255,255,255,255,255,
1342
                       255,255,255,255,255,255,255,255,
1343
                       255,255,255,255,255,255,255,255,
1344
                       255,255,255,255,255,255,255,255,
1345
                       255,255,255,255,255,255,255,255,
1346
                       255,255,255,255,255,255,255,255,
1347
                       255,255,255,255,255,255,255,255,
1348
                       255,255,255,255,255,255,255,255,
1349
                       255,255,255,255,255,255,255,255,
1350
                       255,255,255,255,255,255,255,255,
1351
                       255,255,255,255,255,255,255,255,
1352
                       255,255,255,255,255,255,255,255,
1353
                       255,255,255,255,255,255,255,255,
1354
                       255,255,255,255,255,255,255,255,
1355
                       255,255,255,255,255,255,255,255,
1356
                       255,255,255,255,255,255,255,255,
1357
                       255,255,255,255,255,255,255,255,
1358
                       255,255,255,255,255,255,255,255,
1359
                       255,255,255,255,255,255,255,255,
1360
                       255,255,255,255,255,255,255,255,
1361
                       255,255,255,255,255,255,255,255,
1362
                       255,255,255,255,255,255,255,255,
1363
                       255,255,255,255,255,255,255,255,
1364
                       255,255,255,255,255,255,255,255,
1365
                       255,255,255,255,255,255,255,255,
1366
                       255,255,255,255,255,255,255,255,
1367
                       255,255,255,255,255,255,255,255,
1368
                       255,255,255,255,255,255,255,255,
1369
                       255,255,255,255,255,255};
1370
1371
const int head3_6[] = {0x4f,0x67,0x67,0x53,0,0x01,
1372
                       0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
1373
                       0x01,0x02,0x03,0x04,2,0,0,0,
1374
                       0xf4,0x87,0xba,0xf3,
1375
                       255,
1376
                       255,255,255,255,255,255,255,255,
1377
                       255,255,255,255,255,255,255,255,
1378
                       255,255,255,255,255,255,255,255,
1379
                       255,255,255,255,255,255,255,255,
1380
                       255,255,255,255,255,255,255,255,
1381
                       255,255,255,255,255,255,255,255,
1382
                       255,255,255,255,255,255,255,255,
1383
                       255,255,255,255,255,255,255,255,
1384
                       255,255,255,255,255,255,255,255,
1385
                       255,255,255,255,255,255,255,255,
1386
                       255,255,255,255,255,255,255,255,
1387
                       255,255,255,255,255,255,255,255,
1388
                       255,255,255,255,255,255,255,255,
1389
                       255,255,255,255,255,255,255,255,
1390
                       255,255,255,255,255,255,255,255,
1391
                       255,255,255,255,255,255,255,255,
1392
                       255,255,255,255,255,255,255,255,
1393
                       255,255,255,255,255,255,255,255,
1394
                       255,255,255,255,255,255,255,255,
1395
                       255,255,255,255,255,255,255,255,
1396
                       255,255,255,255,255,255,255,255,
1397
                       255,255,255,255,255,255,255,255,
1398
                       255,255,255,255,255,255,255,255,
1399
                       255,255,255,255,255,255,255,255,
1400
                       255,255,255,255,255,255,255,255,
1401
                       255,255,255,255,255,255,255,255,
1402
                       255,255,255,255,255,255,255,255,
1403
                       255,255,255,255,255,255,255,255,
1404
                       255,255,255,255,255,255,255,255,
1405
                       255,255,255,255,255,255,255,255,
1406
                       255,255,255,255,255,255,255,255,
1407
                       255,255,255,255,255,255,255};
1408
1409
const int head4_6[] = {0x4f,0x67,0x67,0x53,0,0x05,
1410
                       0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
1411
                       0x01,0x02,0x03,0x04,3,0,0,0,
1412
                       0xf7,0x2f,0x6c,0x60,
1413
                       5,
1414
                       254,255,4,255,0};
1415
1416
/* packet that overspans over an entire page */
1417
const int head1_7[] = {0x4f,0x67,0x67,0x53,0,0x02,
1418
                       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1419
                       0x01,0x02,0x03,0x04,0,0,0,0,
1420
                       0xff,0x7b,0x23,0x17,
1421
                       1,
1422
                       0};
1423
1424
const int head2_7[] = {0x4f,0x67,0x67,0x53,0,0x00,
1425
                       0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
1426
                       0x01,0x02,0x03,0x04,1,0,0,0,
1427
                       0x68,0x22,0x7c,0x3d,
1428
                       255,
1429
                       100,
1430
                       255,255,255,255,255,255,255,255,
1431
                       255,255,255,255,255,255,255,255,
1432
                       255,255,255,255,255,255,255,255,
1433
                       255,255,255,255,255,255,255,255,
1434
                       255,255,255,255,255,255,255,255,
1435
                       255,255,255,255,255,255,255,255,
1436
                       255,255,255,255,255,255,255,255,
1437
                       255,255,255,255,255,255,255,255,
1438
                       255,255,255,255,255,255,255,255,
1439
                       255,255,255,255,255,255,255,255,
1440
                       255,255,255,255,255,255,255,255,
1441
                       255,255,255,255,255,255,255,255,
1442
                       255,255,255,255,255,255,255,255,
1443
                       255,255,255,255,255,255,255,255,
1444
                       255,255,255,255,255,255,255,255,
1445
                       255,255,255,255,255,255,255,255,
1446
                       255,255,255,255,255,255,255,255,
1447
                       255,255,255,255,255,255,255,255,
1448
                       255,255,255,255,255,255,255,255,
1449
                       255,255,255,255,255,255,255,255,
1450
                       255,255,255,255,255,255,255,255,
1451
                       255,255,255,255,255,255,255,255,
1452
                       255,255,255,255,255,255,255,255,
1453
                       255,255,255,255,255,255,255,255,
1454
                       255,255,255,255,255,255,255,255,
1455
                       255,255,255,255,255,255,255,255,
1456
                       255,255,255,255,255,255,255,255,
1457
                       255,255,255,255,255,255,255,255,
1458
                       255,255,255,255,255,255,255,255,
1459
                       255,255,255,255,255,255,255,255,
1460
                       255,255,255,255,255,255,255,255,
1461
                       255,255,255,255,255,255};
1462
1463
const int head3_7[] = {0x4f,0x67,0x67,0x53,0,0x05,
1464
                       0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
1465
                       0x01,0x02,0x03,0x04,2,0,0,0,
1466
                       0xd4,0xe0,0x60,0xe5,
1467
                       1,
1468
                       0};
1469
1470
int compare_packet(const ogg_packet *op1, const ogg_packet *op2){
1471
  if(op1->packet!=op2->packet){
1472
    fprintf(stderr,"op1->packet != op2->packet\n");
1473
    return(1);
1474
  }
1475
  if(op1->bytes!=op2->bytes){
1476
    fprintf(stderr,"op1->bytes != op2->bytes\n");
1477
    return(1);
1478
  }
1479
  if(op1->b_o_s!=op2->b_o_s){
1480
    fprintf(stderr,"op1->b_o_s != op2->b_o_s\n");
1481
    return(1);
1482
  }
1483
  if(op1->e_o_s!=op2->e_o_s){
1484
    fprintf(stderr,"op1->e_o_s != op2->e_o_s\n");
1485
    return(1);
1486
  }
1487
  if(op1->granulepos!=op2->granulepos){
1488
    fprintf(stderr,"op1->granulepos != op2->granulepos\n");
1489
    return(1);
1490
  }
1491
  if(op1->packetno!=op2->packetno){
1492
    fprintf(stderr,"op1->packetno != op2->packetno\n");
1493
    return(1);
1494
  }
1495
  return(0);
1496
}
1497
1498
void test_pack(const int *pl, const int **headers, int byteskip,
1499
               int pageskip, int packetskip){
1500
  unsigned char *data=_ogg_malloc(1024*1024); /* for scripted test cases only */
1501
  long inptr=0;
1502
  long outptr=0;
1503
  long deptr=0;
1504
  long depacket=0;
1505
  long granule_pos=7,pageno=0;
1506
  int i,j,packets,pageout=pageskip;
1507
  int eosflag=0;
1508
  int bosflag=0;
1509
1510
  int byteskipcount=0;
1511
1512
  if (!data) {
1513
    fprintf(stderr,"unable to allocate required data buffer!\n");
1514
    exit(1);
1515
  }
1516
1517
  ogg_stream_reset(&os_en);
1518
  ogg_stream_reset(&os_de);
1519
  ogg_sync_reset(&oy);
1520
1521
  for(packets=0;packets<packetskip;packets++)
1522
    depacket+=pl[packets];
1523
1524
  for(packets=0;;packets++)if(pl[packets]==-1)break;
1525
1526
  for(i=0;i<packets;i++){
1527
    /* construct a test packet */
1528
    ogg_packet op;
1529
    int len=pl[i];
1530
1531
    op.packet=data+inptr;
1532
    op.bytes=len;
1533
    op.e_o_s=(pl[i+1]<0?1:0);
1534
    op.granulepos=granule_pos;
1535
1536
    granule_pos+=1024;
1537
1538
    for(j=0;j<len;j++)data[inptr++]=i+j;
1539
1540
    /* submit the test packet */
1541
    ogg_stream_packetin(&os_en,&op);
1542
1543
    /* retrieve any finished pages */
1544
    {
1545
      ogg_page og;
1546
1547
      while(ogg_stream_pageout(&os_en,&og)){
1548
        /* We have a page.  Check it carefully */
1549
1550
        fprintf(stderr,"%ld, ",pageno);
1551
1552
        if(headers[pageno]==NULL){
1553
          fprintf(stderr,"coded too many pages!\n");
1554
          exit(1);
1555
        }
1556
1557
        check_page(data+outptr,headers[pageno],&og);
1558
1559
        outptr+=og.body_len;
1560
        pageno++;
1561
        if(pageskip){
1562
          bosflag=1;
1563
          pageskip--;
1564
          deptr+=og.body_len;
1565
        }
1566
1567
        /* have a complete page; submit it to sync/decode */
1568
1569
        {
1570
          ogg_page og_de;
1571
          ogg_packet op_de,op_de2;
1572
          char *buf=ogg_sync_buffer(&oy,og.header_len+og.body_len);
1573
          char *next=buf;
1574
          byteskipcount+=og.header_len;
1575
          if(byteskipcount>byteskip){
1576
            memcpy(next,og.header,byteskipcount-byteskip);
1577
            next+=byteskipcount-byteskip;
1578
            byteskipcount=byteskip;
1579
          }
1580
1581
          byteskipcount+=og.body_len;
1582
          if(byteskipcount>byteskip){
1583
            memcpy(next,og.body,byteskipcount-byteskip);
1584
            next+=byteskipcount-byteskip;
1585
            byteskipcount=byteskip;
1586
          }
1587
1588
          ogg_sync_wrote(&oy,(long)(next-buf));
1589
1590
          while(1){
1591
            int ret=ogg_sync_pageout(&oy,&og_de);
1592
            if(ret==0)break;
1593
            if(ret<0)continue;
1594
            /* got a page.  Happy happy.  Verify that it's good. */
1595
1596
            fprintf(stderr,"(%d), ",pageout);
1597
1598
            check_page(data+deptr,headers[pageout],&og_de);
1599
            deptr+=og_de.body_len;
1600
            pageout++;
1601
1602
            /* submit it to deconstitution */
1603
            ogg_stream_pagein(&os_de,&og_de);
1604
1605
            /* packets out? */
1606
            while(ogg_stream_packetpeek(&os_de,&op_de2)>0){
1607
              ogg_stream_packetpeek(&os_de,NULL);
1608
              ogg_stream_packetout(&os_de,&op_de); /* just catching them all */
1609
1610
              /* verify peek and out match */
1611
              if(compare_packet(&op_de,&op_de2)){
1612
                fprintf(stderr,"packetout != packetpeek! pos=%ld\n",
1613
                        depacket);
1614
                exit(1);
1615
              }
1616
1617
              /* verify the packet! */
1618
              /* check data */
1619
              if(memcmp(data+depacket,op_de.packet,op_de.bytes)){
1620
                fprintf(stderr,"packet data mismatch in decode! pos=%ld\n",
1621
                        depacket);
1622
                exit(1);
1623
              }
1624
              /* check bos flag */
1625
              if(bosflag==0 && op_de.b_o_s==0){
1626
                fprintf(stderr,"b_o_s flag not set on packet!\n");
1627
                exit(1);
1628
              }
1629
              if(bosflag && op_de.b_o_s){
1630
                fprintf(stderr,"b_o_s flag incorrectly set on packet!\n");
1631
                exit(1);
1632
              }
1633
              bosflag=1;
1634
              depacket+=op_de.bytes;
1635
1636
              /* check eos flag */
1637
              if(eosflag){
1638
                fprintf(stderr,"Multiple decoded packets with eos flag!\n");
1639
                exit(1);
1640
              }
1641
1642
              if(op_de.e_o_s)eosflag=1;
1643
1644
              /* check granulepos flag */
1645
              if(op_de.granulepos!=-1){
1646
                fprintf(stderr," granule:%ld ",(long)op_de.granulepos);
1647
              }
1648
            }
1649
          }
1650
        }
1651
      }
1652
    }
1653
  }
1654
  _ogg_free(data);
1655
  if(headers[pageno]!=NULL){
1656
    fprintf(stderr,"did not write last page!\n");
1657
    exit(1);
1658
  }
1659
  if(headers[pageout]!=NULL){
1660
    fprintf(stderr,"did not decode last page!\n");
1661
    exit(1);
1662
  }
1663
  if(inptr!=outptr){
1664
    fprintf(stderr,"encoded page data incomplete!\n");
1665
    exit(1);
1666
  }
1667
  if(inptr!=deptr){
1668
    fprintf(stderr,"decoded page data incomplete!\n");
1669
    exit(1);
1670
  }
1671
  if(inptr!=depacket){
1672
    fprintf(stderr,"decoded packet data incomplete!\n");
1673
    exit(1);
1674
  }
1675
  if(!eosflag){
1676
    fprintf(stderr,"Never got a packet with EOS set!\n");
1677
    exit(1);
1678
  }
1679
  fprintf(stderr,"ok.\n");
1680
}
1681
1682
int main(void){
1683
1684
  ogg_stream_init(&os_en,0x04030201);
1685
  ogg_stream_init(&os_de,0x04030201);
1686
  ogg_sync_init(&oy);
1687
1688
  /* Exercise each code path in the framing code.  Also verify that
1689
     the checksums are working.  */
1690
1691
  {
1692
    /* 17 only */
1693
    const int packets[]={17, -1};
1694
    const int *headret[]={head1_0,NULL};
1695
1696
    fprintf(stderr,"testing single page encoding... ");
1697
    test_pack(packets,headret,0,0,0);
1698
  }
1699
1700
  {
1701
    /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
1702
    const int packets[]={17, 254, 255, 256, 500, 510, 600, -1};
1703
    const int *headret[]={head1_1,head2_1,NULL};
1704
1705
    fprintf(stderr,"testing basic page encoding... ");
1706
    test_pack(packets,headret,0,0,0);
1707
  }
1708
1709
  {
1710
    /* nil packets; beginning,middle,end */
1711
    const int packets[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1};
1712
    const int *headret[]={head1_2,head2_2,NULL};
1713
1714
    fprintf(stderr,"testing basic nil packets... ");
1715
    test_pack(packets,headret,0,0,0);
1716
  }
1717
1718
  {
1719
    /* large initial packet */
1720
    const int packets[]={4345,259,255,-1};
1721
    const int *headret[]={head1_3,head2_3,NULL};
1722
1723
    fprintf(stderr,"testing initial-packet lacing > 4k... ");
1724
    test_pack(packets,headret,0,0,0);
1725
  }
1726
1727
  {
1728
    /* continuing packet test; with page spill expansion, we have to
1729
       overflow the lacing table. */
1730
    const int packets[]={0,65500,259,255,-1};
1731
    const int *headret[]={head1_4,head2_4,head3_4,NULL};
1732
1733
    fprintf(stderr,"testing single packet page span... ");
1734
    test_pack(packets,headret,0,0,0);
1735
  }
1736
1737
  {
1738
    /* spill expand packet test */
1739
    const int packets[]={0,4345,259,255,0,0,-1};
1740
    const int *headret[]={head1_4b,head2_4b,head3_4b,NULL};
1741
1742
    fprintf(stderr,"testing page spill expansion... ");
1743
    test_pack(packets,headret,0,0,0);
1744
  }
1745
1746
  /* page with the 255 segment limit */
1747
  {
1748
1749
    const int packets[]={0,10,10,10,10,10,10,10,10,
1750
                   10,10,10,10,10,10,10,10,
1751
                   10,10,10,10,10,10,10,10,
1752
                   10,10,10,10,10,10,10,10,
1753
                   10,10,10,10,10,10,10,10,
1754
                   10,10,10,10,10,10,10,10,
1755
                   10,10,10,10,10,10,10,10,
1756
                   10,10,10,10,10,10,10,10,
1757
                   10,10,10,10,10,10,10,10,
1758
                   10,10,10,10,10,10,10,10,
1759
                   10,10,10,10,10,10,10,10,
1760
                   10,10,10,10,10,10,10,10,
1761
                   10,10,10,10,10,10,10,10,
1762
                   10,10,10,10,10,10,10,10,
1763
                   10,10,10,10,10,10,10,10,
1764
                   10,10,10,10,10,10,10,10,
1765
                   10,10,10,10,10,10,10,10,
1766
                   10,10,10,10,10,10,10,10,
1767
                   10,10,10,10,10,10,10,10,
1768
                   10,10,10,10,10,10,10,10,
1769
                   10,10,10,10,10,10,10,10,
1770
                   10,10,10,10,10,10,10,10,
1771
                   10,10,10,10,10,10,10,10,
1772
                   10,10,10,10,10,10,10,10,
1773
                   10,10,10,10,10,10,10,10,
1774
                   10,10,10,10,10,10,10,10,
1775
                   10,10,10,10,10,10,10,10,
1776
                   10,10,10,10,10,10,10,10,
1777
                   10,10,10,10,10,10,10,10,
1778
                   10,10,10,10,10,10,10,10,
1779
                   10,10,10,10,10,10,10,10,
1780
                   10,10,10,10,10,10,10,50,-1};
1781
    const int *headret[]={head1_5,head2_5,head3_5,NULL};
1782
1783
    fprintf(stderr,"testing max packet segments... ");
1784
    test_pack(packets,headret,0,0,0);
1785
  }
1786
1787
  {
1788
    /* packet that overspans over an entire page */
1789
    const int packets[]={0,100,130049,259,255,-1};
1790
    const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
1791
1792
    fprintf(stderr,"testing very large packets... ");
1793
    test_pack(packets,headret,0,0,0);
1794
  }
1795
1796
#ifndef DISABLE_CRC
1797
  {
1798
    /* test for the libogg 1.1.1 resync in large continuation bug
1799
       found by Josh Coalson)  */
1800
    const int packets[]={0,100,130049,259,255,-1};
1801
    const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
1802
1803
    fprintf(stderr,"testing continuation resync in very large packets... ");
1804
    test_pack(packets,headret,100,2,3);
1805
  }
1806
#else
1807
    fprintf(stderr,"Skipping continuation resync test due to --disable-crc\n");
1808
#endif
1809
1810
  {
1811
    /* term only page.  why not? */
1812
    const int packets[]={0,100,64770,-1};
1813
    const int *headret[]={head1_7,head2_7,head3_7,NULL};
1814
1815
    fprintf(stderr,"testing zero data page (1 nil packet)... ");
1816
    test_pack(packets,headret,0,0,0);
1817
  }
1818
1819
1820
1821
  {
1822
    /* build a bunch of pages for testing */
1823
    unsigned char *data=_ogg_malloc(1024*1024);
1824
    int pl[]={0, 1,1,98,4079, 1,1,2954,2057, 76,34,912,0,234,1000,1000, 1000,300,-1};
1825
    int inptr=0,i,j;
1826
    ogg_page og[5];
1827
1828
    if (!data) {
1829
      fprintf(stderr,"unable to allocate required packet data buffer!\n");
1830
      exit(1);
1831
    }
1832
1833
    ogg_stream_reset(&os_en);
1834
1835
    for(i=0;pl[i]!=-1;i++){
1836
      ogg_packet op;
1837
      int len=pl[i];
1838
1839
      op.packet=data+inptr;
1840
      op.bytes=len;
1841
      op.e_o_s=(pl[i+1]<0?1:0);
1842
      op.granulepos=(i+1)*1000;
1843
1844
      for(j=0;j<len;j++)data[inptr++]=i+j;
1845
      ogg_stream_packetin(&os_en,&op);
1846
    }
1847
1848
    _ogg_free(data);
1849
1850
    /* retrieve finished pages */
1851
    for(i=0;i<5;i++){
1852
      if(ogg_stream_pageout(&os_en,&og[i])==0){
1853
        fprintf(stderr,"Too few pages output building sync tests!\n");
1854
        exit(1);
1855
      }
1856
      if (-1 == copy_page(&og[i])) {
1857
        fprintf(stderr,"unable to copy page building sync tests!\n");
1858
        exit(1);
1859
      }
1860
    }
1861
1862
    /* Test lost pages on pagein/packetout: no rollback */
1863
    {
1864
      ogg_page temp;
1865
      ogg_packet test;
1866
1867
      fprintf(stderr,"Testing loss of pages... ");
1868
1869
      ogg_sync_reset(&oy);
1870
      ogg_stream_reset(&os_de);
1871
      for(i=0;i<5;i++){
1872
        memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
1873
               og[i].header_len);
1874
        ogg_sync_wrote(&oy,og[i].header_len);
1875
        memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
1876
        ogg_sync_wrote(&oy,og[i].body_len);
1877
      }
1878
1879
      ogg_sync_pageout(&oy,&temp);
1880
      ogg_stream_pagein(&os_de,&temp);
1881
      ogg_sync_pageout(&oy,&temp);
1882
      ogg_stream_pagein(&os_de,&temp);
1883
      ogg_sync_pageout(&oy,&temp);
1884
      /* skip */
1885
      ogg_sync_pageout(&oy,&temp);
1886
      ogg_stream_pagein(&os_de,&temp);
1887
1888
      /* do we get the expected results/packets? */
1889
1890
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1891
      checkpacket(&test,0,0,0);
1892
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1893
      checkpacket(&test,1,1,-1);
1894
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1895
      checkpacket(&test,1,2,-1);
1896
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1897
      checkpacket(&test,98,3,-1);
1898
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1899
      checkpacket(&test,4079,4,5000);
1900
      if(ogg_stream_packetout(&os_de,&test)!=-1){
1901
        fprintf(stderr,"Error: loss of page did not return error\n");
1902
        exit(1);
1903
      }
1904
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1905
      checkpacket(&test,76,9,-1);
1906
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1907
      checkpacket(&test,34,10,-1);
1908
      fprintf(stderr,"ok.\n");
1909
    }
1910
1911
    /* Test lost pages on pagein/packetout: rollback with continuation */
1912
    {
1913
      ogg_page temp;
1914
      ogg_packet test;
1915
1916
      fprintf(stderr,"Testing loss of pages (rollback required)... ");
1917
1918
      ogg_sync_reset(&oy);
1919
      ogg_stream_reset(&os_de);
1920
      for(i=0;i<5;i++){
1921
        memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
1922
               og[i].header_len);
1923
        ogg_sync_wrote(&oy,og[i].header_len);
1924
        memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
1925
        ogg_sync_wrote(&oy,og[i].body_len);
1926
      }
1927
1928
      ogg_sync_pageout(&oy,&temp);
1929
      ogg_stream_pagein(&os_de,&temp);
1930
      ogg_sync_pageout(&oy,&temp);
1931
      ogg_stream_pagein(&os_de,&temp);
1932
      ogg_sync_pageout(&oy,&temp);
1933
      ogg_stream_pagein(&os_de,&temp);
1934
      ogg_sync_pageout(&oy,&temp);
1935
      /* skip */
1936
      ogg_sync_pageout(&oy,&temp);
1937
      ogg_stream_pagein(&os_de,&temp);
1938
1939
      /* do we get the expected results/packets? */
1940
1941
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1942
      checkpacket(&test,0,0,0);
1943
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1944
      checkpacket(&test,1,1,-1);
1945
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1946
      checkpacket(&test,1,2,-1);
1947
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1948
      checkpacket(&test,98,3,-1);
1949
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1950
      checkpacket(&test,4079,4,5000);
1951
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1952
      checkpacket(&test,1,5,-1);
1953
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1954
      checkpacket(&test,1,6,-1);
1955
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1956
      checkpacket(&test,2954,7,-1);
1957
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1958
      checkpacket(&test,2057,8,9000);
1959
      if(ogg_stream_packetout(&os_de,&test)!=-1){
1960
        fprintf(stderr,"Error: loss of page did not return error\n");
1961
        exit(1);
1962
      }
1963
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1964
      checkpacket(&test,300,17,18000);
1965
      fprintf(stderr,"ok.\n");
1966
    }
1967
1968
    /* the rest only test sync */
1969
    {
1970
      ogg_page og_de;
1971
      /* Test fractional page inputs: incomplete capture */
1972
      fprintf(stderr,"Testing sync on partial inputs... ");
1973
      ogg_sync_reset(&oy);
1974
      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
1975
             3);
1976
      ogg_sync_wrote(&oy,3);
1977
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
1978
1979
      /* Test fractional page inputs: incomplete fixed header */
1980
      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+3,
1981
             20);
1982
      ogg_sync_wrote(&oy,20);
1983
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
1984
1985
      /* Test fractional page inputs: incomplete header */
1986
      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+23,
1987
             5);
1988
      ogg_sync_wrote(&oy,5);
1989
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
1990
1991
      /* Test fractional page inputs: incomplete body */
1992
1993
      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+28,
1994
             og[1].header_len-28);
1995
      ogg_sync_wrote(&oy,og[1].header_len-28);
1996
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
1997
1998
      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,1000);
1999
      ogg_sync_wrote(&oy,1000);
2000
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
2001
2002
      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body+1000,
2003
             og[1].body_len-1000);
2004
      ogg_sync_wrote(&oy,og[1].body_len-1000);
2005
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2006
2007
      fprintf(stderr,"ok.\n");
2008
    }
2009
2010
    /* Test fractional page inputs: page + incomplete capture */
2011
    {
2012
      ogg_page og_de;
2013
      fprintf(stderr,"Testing sync on 1+partial inputs... ");
2014
      ogg_sync_reset(&oy);
2015
2016
      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
2017
             og[1].header_len);
2018
      ogg_sync_wrote(&oy,og[1].header_len);
2019
2020
      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2021
             og[1].body_len);
2022
      ogg_sync_wrote(&oy,og[1].body_len);
2023
2024
      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
2025
             20);
2026
      ogg_sync_wrote(&oy,20);
2027
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2028
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
2029
2030
      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+20,
2031
             og[1].header_len-20);
2032
      ogg_sync_wrote(&oy,og[1].header_len-20);
2033
      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2034
             og[1].body_len);
2035
      ogg_sync_wrote(&oy,og[1].body_len);
2036
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2037
2038
      fprintf(stderr,"ok.\n");
2039
    }
2040
2041
    /* Test recapture: garbage + page */
2042
    {
2043
      ogg_page og_de;
2044
      fprintf(stderr,"Testing search for capture... ");
2045
      ogg_sync_reset(&oy);
2046
2047
      /* 'garbage' */
2048
      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2049
             og[1].body_len);
2050
      ogg_sync_wrote(&oy,og[1].body_len);
2051
2052
      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
2053
             og[1].header_len);
2054
      ogg_sync_wrote(&oy,og[1].header_len);
2055
2056
      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2057
             og[1].body_len);
2058
      ogg_sync_wrote(&oy,og[1].body_len);
2059
2060
      memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
2061
             20);
2062
      ogg_sync_wrote(&oy,20);
2063
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
2064
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2065
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
2066
2067
      memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header+20,
2068
             og[2].header_len-20);
2069
      ogg_sync_wrote(&oy,og[2].header_len-20);
2070
      memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
2071
             og[2].body_len);
2072
      ogg_sync_wrote(&oy,og[2].body_len);
2073
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2074
2075
      fprintf(stderr,"ok.\n");
2076
    }
2077
2078
#ifndef DISABLE_CRC
2079
    /* Test recapture: page + garbage + page */
2080
    {
2081
      ogg_page og_de;
2082
      fprintf(stderr,"Testing recapture... ");
2083
      ogg_sync_reset(&oy);
2084
2085
      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
2086
             og[1].header_len);
2087
      ogg_sync_wrote(&oy,og[1].header_len);
2088
2089
      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2090
             og[1].body_len);
2091
      ogg_sync_wrote(&oy,og[1].body_len);
2092
2093
      memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
2094
             og[2].header_len);
2095
      ogg_sync_wrote(&oy,og[2].header_len);
2096
2097
      memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
2098
             og[2].header_len);
2099
      ogg_sync_wrote(&oy,og[2].header_len);
2100
2101
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2102
2103
      memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
2104
             og[2].body_len-5);
2105
      ogg_sync_wrote(&oy,og[2].body_len-5);
2106
2107
      memcpy(ogg_sync_buffer(&oy,og[3].header_len),og[3].header,
2108
             og[3].header_len);
2109
      ogg_sync_wrote(&oy,og[3].header_len);
2110
2111
      memcpy(ogg_sync_buffer(&oy,og[3].body_len),og[3].body,
2112
             og[3].body_len);
2113
      ogg_sync_wrote(&oy,og[3].body_len);
2114
2115
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
2116
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2117
2118
      fprintf(stderr,"ok.\n");
2119
    }
2120
#else
2121
    fprintf(stderr,"Skipping recapture test due to --disable-crc\n");
2122
#endif
2123
2124
    /* Free page data that was previously copied */
2125
    {
2126
      for(i=0;i<5;i++){
2127
        free_page(&og[i]);
2128
      }
2129
    }
2130
  }
2131
  ogg_sync_clear(&oy);
2132
  ogg_stream_clear(&os_en);
2133
  ogg_stream_clear(&os_de);
2134
2135
  return(0);
2136
}
2137
2138
#endif