Coverage Report

Created: 2023-03-20 06:50

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