Coverage Report

Created: 2025-08-03 06:35

/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.7k
int ogg_page_version(const ogg_page *og){
34
34.7k
  return((int)(og->header[4]));
35
34.7k
}
36
37
34.7k
int ogg_page_continued(const ogg_page *og){
38
34.7k
  return((int)(og->header[5]&0x01));
39
34.7k
}
40
41
49.9k
int ogg_page_bos(const ogg_page *og){
42
49.9k
  return((int)(og->header[5]&0x02));
43
49.9k
}
44
45
34.7k
int ogg_page_eos(const ogg_page *og){
46
34.7k
  return((int)(og->header[5]&0x04));
47
34.7k
}
48
49
149k
ogg_int64_t ogg_page_granulepos(const ogg_page *og){
50
149k
  unsigned char *page=og->header;
51
149k
  ogg_uint64_t granulepos=page[13]&(0xff);
52
149k
  granulepos= (granulepos<<8)|(page[12]&0xff);
53
149k
  granulepos= (granulepos<<8)|(page[11]&0xff);
54
149k
  granulepos= (granulepos<<8)|(page[10]&0xff);
55
149k
  granulepos= (granulepos<<8)|(page[9]&0xff);
56
149k
  granulepos= (granulepos<<8)|(page[8]&0xff);
57
149k
  granulepos= (granulepos<<8)|(page[7]&0xff);
58
149k
  granulepos= (granulepos<<8)|(page[6]&0xff);
59
149k
  return((ogg_int64_t)granulepos);
60
149k
}
61
62
41.5k
int ogg_page_serialno(const ogg_page *og){
63
41.5k
  return((int)((ogg_uint32_t)og->header[14]) |
64
41.5k
              ((ogg_uint32_t)og->header[15]<<8) |
65
41.5k
              ((ogg_uint32_t)og->header[16]<<16) |
66
41.5k
              ((ogg_uint32_t)og->header[17]<<24));
67
41.5k
}
68
69
34.7k
long ogg_page_pageno(const ogg_page *og){
70
34.7k
  return((long)((ogg_uint32_t)og->header[18]) |
71
34.7k
               ((ogg_uint32_t)og->header[19]<<8) |
72
34.7k
               ((ogg_uint32_t)og->header[20]<<16) |
73
34.7k
               ((ogg_uint32_t)og->header[21]<<24));
74
34.7k
}
75
76
77
78
/* returns the number of packets that are completed on this page (if
79
   the leading packet is begun on a previous page, but ends on this
80
   page, it's counted */
81
82
/* NOTE:
83
   If a page consists of a packet begun on a previous page, and a new
84
   packet begun (but not completed) on this page, the return will be:
85
     ogg_page_packets(page)   ==1,
86
     ogg_page_continued(page) !=0
87
88
   If a page happens to be a single packet that was begun on a
89
   previous page, and spans to the next page (in the case of a three or
90
   more page packet), the return will be:
91
     ogg_page_packets(page)   ==0,
92
     ogg_page_continued(page) !=0
93
*/
94
95
0
int ogg_page_packets(const ogg_page *og){
96
0
  int i,n=og->header[26],count=0;
97
0
  for(i=0;i<n;i++)
98
0
    if(og->header[27+i]<255)count++;
99
0
  return(count);
100
0
}
101
102
103
#if 0
104
/* helper to initialize lookup for direct-table CRC (illustrative; we
105
   use the static init in crctable.h) */
106
107
static void _ogg_crc_init(){
108
  int i, j;
109
  ogg_uint32_t polynomial, crc;
110
  polynomial = 0x04c11db7; /* The same as the ethernet generator
111
                              polynomial, although we use an
112
                              unreflected alg and an init/final
113
                              of 0, not 0xffffffff */
114
  for (i = 0; i <= 0xFF; i++){
115
    crc = i << 24;
116
117
    for (j = 0; j < 8; j++)
118
      crc = (crc << 1) ^ (crc & (1 << 31) ? polynomial : 0);
119
120
    crc_lookup[0][i] = crc;
121
  }
122
123
  for (i = 0; i <= 0xFF; i++)
124
    for (j = 1; j < 8; j++)
125
      crc_lookup[j][i] = crc_lookup[0][(crc_lookup[j - 1][i] >> 24) & 0xFF] ^ (crc_lookup[j - 1][i] << 8);
126
}
127
#endif
128
129
#include "crctable.h"
130
131
/* init the encode/decode logical stream state */
132
133
3.40k
int ogg_stream_init(ogg_stream_state *os,int serialno){
134
3.40k
  if(os){
135
3.40k
    memset(os,0,sizeof(*os));
136
3.40k
    os->body_storage=16*1024;
137
3.40k
    os->lacing_storage=1024;
138
139
3.40k
    os->body_data=_ogg_malloc(os->body_storage*sizeof(*os->body_data));
140
3.40k
    os->lacing_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->lacing_vals));
141
3.40k
    os->granule_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->granule_vals));
142
143
3.40k
    if(!os->body_data || !os->lacing_vals || !os->granule_vals){
144
0
      ogg_stream_clear(os);
145
0
      return -1;
146
0
    }
147
148
3.40k
    os->serialno=serialno;
149
150
3.40k
    return(0);
151
3.40k
  }
152
0
  return(-1);
153
3.40k
}
154
155
/* async/delayed error detection for the ogg_stream_state */
156
9.84M
int ogg_stream_check(ogg_stream_state *os){
157
9.84M
  if(!os || !os->body_data) return -1;
158
9.84M
  return 0;
159
9.84M
}
160
161
/* _clear does not free os, only the non-flat storage within */
162
3.40k
int ogg_stream_clear(ogg_stream_state *os){
163
3.40k
  if(os){
164
3.40k
    if(os->body_data)_ogg_free(os->body_data);
165
3.40k
    if(os->lacing_vals)_ogg_free(os->lacing_vals);
166
3.40k
    if(os->granule_vals)_ogg_free(os->granule_vals);
167
168
3.40k
    memset(os,0,sizeof(*os));
169
3.40k
  }
170
3.40k
  return(0);
171
3.40k
}
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
3.17M
static int _os_body_expand(ogg_stream_state *os,long needed){
185
3.17M
  if(os->body_storage-needed<=os->body_fill){
186
2.13k
    long body_storage;
187
2.13k
    void *ret;
188
2.13k
    if(os->body_storage>LONG_MAX-needed){
189
0
      ogg_stream_clear(os);
190
0
      return -1;
191
0
    }
192
2.13k
    body_storage=os->body_storage+needed;
193
2.13k
    if(body_storage<LONG_MAX-1024)body_storage+=1024;
194
2.13k
    ret=_ogg_realloc(os->body_data,body_storage*sizeof(*os->body_data));
195
2.13k
    if(!ret){
196
0
      ogg_stream_clear(os);
197
0
      return -1;
198
0
    }
199
2.13k
    os->body_storage=body_storage;
200
2.13k
    os->body_data=ret;
201
2.13k
  }
202
3.17M
  return 0;
203
3.17M
}
204
205
3.17M
static int _os_lacing_expand(ogg_stream_state *os,long needed){
206
3.17M
  if(os->lacing_storage-needed<=os->lacing_fill){
207
952
    long lacing_storage;
208
952
    void *ret;
209
952
    if(os->lacing_storage>LONG_MAX-needed){
210
0
      ogg_stream_clear(os);
211
0
      return -1;
212
0
    }
213
952
    lacing_storage=os->lacing_storage+needed;
214
952
    if(lacing_storage<LONG_MAX-32)lacing_storage+=32;
215
952
    ret=_ogg_realloc(os->lacing_vals,lacing_storage*sizeof(*os->lacing_vals));
216
952
    if(!ret){
217
0
      ogg_stream_clear(os);
218
0
      return -1;
219
0
    }
220
952
    os->lacing_vals=ret;
221
952
    ret=_ogg_realloc(os->granule_vals,lacing_storage*
222
952
                     sizeof(*os->granule_vals));
223
952
    if(!ret){
224
0
      ogg_stream_clear(os);
225
0
      return -1;
226
0
    }
227
952
    os->granule_vals=ret;
228
952
    os->lacing_storage=lacing_storage;
229
952
  }
230
3.17M
  return 0;
231
3.17M
}
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
301k
static ogg_uint32_t _os_update_crc(ogg_uint32_t crc, unsigned char *buffer, int size){
238
163M
  while (size>=8){
239
163M
    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
163M
    crc=crc_lookup[7][ crc>>24      ]^crc_lookup[6][(crc>>16)&0xFF]^
242
163M
        crc_lookup[5][(crc>> 8)&0xFF]^crc_lookup[4][ crc     &0xFF]^
243
163M
        crc_lookup[3][buffer[4]     ]^crc_lookup[2][buffer[5]     ]^
244
163M
        crc_lookup[1][buffer[6]     ]^crc_lookup[0][buffer[7]     ];
245
246
163M
    buffer+=8;
247
163M
    size-=8;
248
163M
  }
249
250
960k
  while (size--)
251
658k
    crc=(crc<<8)^crc_lookup[0][((crc >> 24)&0xff)^*buffer++];
252
301k
  return crc;
253
301k
}
254
255
150k
void ogg_page_checksum_set(ogg_page *og){
256
150k
  if(og){
257
150k
    ogg_uint32_t crc_reg=0;
258
259
    /* safety; needed for API behavior, but not framing code */
260
150k
    og->header[22]=0;
261
150k
    og->header[23]=0;
262
150k
    og->header[24]=0;
263
150k
    og->header[25]=0;
264
265
150k
    crc_reg=_os_update_crc(crc_reg,og->header,og->header_len);
266
150k
    crc_reg=_os_update_crc(crc_reg,og->body,og->body_len);
267
268
150k
    og->header[22]=(unsigned char)(crc_reg&0xff);
269
150k
    og->header[23]=(unsigned char)((crc_reg>>8)&0xff);
270
150k
    og->header[24]=(unsigned char)((crc_reg>>16)&0xff);
271
150k
    og->header[25]=(unsigned char)((crc_reg>>24)&0xff);
272
150k
  }
273
150k
}
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
3.15M
                       long e_o_s, ogg_int64_t granulepos){
278
279
3.15M
  long bytes = 0, lacing_vals;
280
3.15M
  int i;
281
282
3.15M
  if(ogg_stream_check(os)) return -1;
283
3.15M
  if(!iov) return 0;
284
285
6.30M
  for (i = 0; i < count; ++i){
286
3.15M
    if(iov[i].iov_len>LONG_MAX) return -1;
287
3.15M
    if(bytes>LONG_MAX-(long)iov[i].iov_len) return -1;
288
3.15M
    bytes += (long)iov[i].iov_len;
289
3.15M
  }
290
3.15M
  lacing_vals=bytes/255+1;
291
292
3.15M
  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
96.7k
    os->body_fill-=os->body_returned;
298
96.7k
    if(os->body_fill)
299
5.72k
      memmove(os->body_data,os->body_data+os->body_returned,
300
5.72k
              os->body_fill);
301
96.7k
    os->body_returned=0;
302
96.7k
  }
303
304
  /* make sure we have the buffer storage */
305
3.15M
  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
6.30M
  for (i = 0; i < count; ++i) {
314
3.15M
    memcpy(os->body_data+os->body_fill, iov[i].iov_base, iov[i].iov_len);
315
3.15M
    os->body_fill += (int)iov[i].iov_len;
316
3.15M
  }
317
318
  /* Store lacing vals for this packet */
319
7.58M
  for(i=0;i<lacing_vals-1;i++){
320
4.43M
    os->lacing_vals[os->lacing_fill+i]=255;
321
4.43M
    os->granule_vals[os->lacing_fill+i]=os->granulepos;
322
4.43M
  }
323
3.15M
  os->lacing_vals[os->lacing_fill+i]=bytes%255;
324
3.15M
  os->granulepos=os->granule_vals[os->lacing_fill+i]=granulepos;
325
326
  /* flag the first segment as the beginning of the packet */
327
3.15M
  os->lacing_vals[os->lacing_fill]|= 0x100;
328
329
3.15M
  os->lacing_fill+=lacing_vals;
330
331
  /* for the sake of completeness */
332
3.15M
  os->packetno++;
333
334
3.15M
  if(e_o_s)os->e_o_s=1;
335
336
3.15M
  return(0);
337
3.15M
}
338
339
3.15M
int ogg_stream_packetin(ogg_stream_state *os,ogg_packet *op){
340
3.15M
  ogg_iovec_t iov;
341
3.15M
  iov.iov_base = op->packet;
342
3.15M
  iov.iov_len = op->bytes;
343
3.15M
  return ogg_stream_iovecin(os, &iov, 1, op->e_o_s, op->granulepos);
344
3.15M
}
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
3.26M
static int ogg_stream_flush_i(ogg_stream_state *os,ogg_page *og, int force, int nfill){
350
3.26M
  int i;
351
3.26M
  int vals=0;
352
3.26M
  int maxvals;
353
3.26M
  int bytes=0;
354
3.26M
  long acc=0;
355
3.26M
  ogg_int64_t granule_pos=-1;
356
357
3.26M
  if(ogg_stream_check(os)) return(0);
358
3.26M
  maxvals=(os->lacing_fill>255?255:os->lacing_fill);
359
3.26M
  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
3.17M
  if(os->b_o_s==0){  /* 'initial header page' case */
367
1.81k
    granule_pos=0;
368
1.81k
    for(vals=0;vals<maxvals;vals++){
369
1.81k
      if((os->lacing_vals[vals]&0x0ff)<255){
370
1.81k
        vals++;
371
1.81k
        break;
372
1.81k
      }
373
1.81k
    }
374
3.17M
  }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
3.17M
    int packets_done=0;
386
3.17M
    int packet_just_done=0;
387
387M
    for(vals=0;vals<maxvals;vals++){
388
384M
      if(acc>nfill && packet_just_done>=4){
389
5.37k
        force=1;
390
5.37k
        break;
391
5.37k
      }
392
384M
      acc+=os->lacing_vals[vals]&0x0ff;
393
384M
      if((os->lacing_vals[vals]&0xff)<255){
394
379M
        granule_pos=os->granule_vals[vals];
395
379M
        packet_just_done=++packets_done;
396
379M
      }else
397
4.68M
        packet_just_done=0;
398
384M
    }
399
3.17M
    if(vals==255)force=1;
400
3.17M
  }
401
402
3.17M
  if(!force) return(0);
403
404
  /* construct the header in temp storage */
405
115k
  memcpy(os->header,"OggS",4);
406
407
  /* stream structure version */
408
115k
  os->header[4]=0x00;
409
410
  /* continued packet flag? */
411
115k
  os->header[5]=0x00;
412
115k
  if((os->lacing_vals[0]&0x100)==0)os->header[5]|=0x01;
413
  /* first page flag? */
414
115k
  if(os->b_o_s==0)os->header[5]|=0x02;
415
  /* last page flag? */
416
115k
  if(os->e_o_s && os->lacing_fill==vals)os->header[5]|=0x04;
417
115k
  os->b_o_s=1;
418
419
  /* 64 bits of PCM position */
420
1.03M
  for(i=6;i<14;i++){
421
921k
    os->header[i]=(unsigned char)(granule_pos&0xff);
422
921k
    granule_pos>>=8;
423
921k
  }
424
425
  /* 32 bits of stream serial number */
426
115k
  {
427
115k
    long serialno=os->serialno;
428
575k
    for(i=14;i<18;i++){
429
460k
      os->header[i]=(unsigned char)(serialno&0xff);
430
460k
      serialno>>=8;
431
460k
    }
432
115k
  }
433
434
  /* 32 bits of page counter (we have both counter and page header
435
     because this val can roll over) */
436
115k
  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
115k
  {
442
115k
    long pageno=os->pageno++;
443
575k
    for(i=18;i<22;i++){
444
460k
      os->header[i]=(unsigned char)(pageno&0xff);
445
460k
      pageno>>=8;
446
460k
    }
447
115k
  }
448
449
  /* zero for computation; filled in later */
450
115k
  os->header[22]=0;
451
115k
  os->header[23]=0;
452
115k
  os->header[24]=0;
453
115k
  os->header[25]=0;
454
455
  /* segment table */
456
115k
  os->header[26]=(unsigned char)(vals&0xff);
457
7.70M
  for(i=0;i<vals;i++)
458
7.58M
    bytes+=os->header[i+27]=(unsigned char)(os->lacing_vals[i]&0xff);
459
460
  /* set pointers in the ogg_page struct */
461
115k
  og->header=os->header;
462
115k
  og->header_len=os->header_fill=vals+27;
463
115k
  og->body=os->body_data+os->body_returned;
464
115k
  og->body_len=bytes;
465
466
  /* advance the lacing data and set the body_returned pointer */
467
468
115k
  os->lacing_fill-=vals;
469
115k
  memmove(os->lacing_vals,os->lacing_vals+vals,os->lacing_fill*sizeof(*os->lacing_vals));
470
115k
  memmove(os->granule_vals,os->granule_vals+vals,os->lacing_fill*sizeof(*os->granule_vals));
471
115k
  os->body_returned+=bytes;
472
473
  /* calculate the checksum */
474
475
115k
  ogg_page_checksum_set(og);
476
477
  /* done */
478
115k
  return(1);
479
3.17M
}
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
180k
int ogg_stream_flush(ogg_stream_state *os,ogg_page *og){
496
180k
  return ogg_stream_flush_i(os,og,1,4096);
497
180k
}
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
3.08M
int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og){
512
3.08M
  int force=0;
513
3.08M
  if(ogg_stream_check(os)) return 0;
514
515
3.08M
  if((os->e_o_s&&os->lacing_fill) ||          /* 'were done, now flush' case */
516
3.08M
     (os->lacing_fill&&!os->b_o_s))           /* 'initial header page' case */
517
1.15k
    force=1;
518
519
3.08M
  return(ogg_stream_flush_i(os,og,force,4096));
520
3.08M
}
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
1.57k
int ogg_sync_init(ogg_sync_state *oy){
559
1.57k
  if(oy){
560
1.57k
    oy->storage = -1; /* used as a readiness flag */
561
1.57k
    memset(oy,0,sizeof(*oy));
562
1.57k
  }
563
1.57k
  return(0);
564
1.57k
}
565
566
/* clear non-flat storage within */
567
1.57k
int ogg_sync_clear(ogg_sync_state *oy){
568
1.57k
  if(oy){
569
1.57k
    if(oy->data)_ogg_free(oy->data);
570
1.57k
    memset(oy,0,sizeof(*oy));
571
1.57k
  }
572
1.57k
  return(0);
573
1.57k
}
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
361k
int ogg_sync_check(ogg_sync_state *oy){
584
361k
  if(oy->storage<0) return -1;
585
361k
  return 0;
586
361k
}
587
588
23.8k
char *ogg_sync_buffer(ogg_sync_state *oy, long size){
589
23.8k
  if(ogg_sync_check(oy)) return NULL;
590
591
  /* first, clear out any space that has been previously returned */
592
23.8k
  if(oy->returned){
593
9.20k
    oy->fill-=oy->returned;
594
9.20k
    if(oy->fill>0)
595
4.05k
      memmove(oy->data,oy->data+oy->returned,oy->fill);
596
9.20k
    oy->returned=0;
597
9.20k
  }
598
599
23.8k
  if(size>oy->storage-oy->fill){
600
    /* We need to extend the internal buffer */
601
3.47k
    long newsize;
602
3.47k
    void *ret;
603
604
3.47k
    if(size>INT_MAX-4096-oy->fill){
605
0
      ogg_sync_clear(oy);
606
0
      return NULL;
607
0
    }
608
3.47k
    newsize=size+oy->fill+4096; /* an extra page to be nice */
609
3.47k
    if(oy->data)
610
1.90k
      ret=_ogg_realloc(oy->data,newsize);
611
1.57k
    else
612
1.57k
      ret=_ogg_malloc(newsize);
613
3.47k
    if(!ret){
614
0
      ogg_sync_clear(oy);
615
0
      return NULL;
616
0
    }
617
3.47k
    oy->data=ret;
618
3.47k
    oy->storage=newsize;
619
3.47k
  }
620
621
  /* expose a segment at least as large as requested at the fill mark */
622
23.8k
  return((char *)oy->data+oy->fill);
623
23.8k
}
624
625
23.3k
int ogg_sync_wrote(ogg_sync_state *oy, long bytes){
626
23.3k
  if(ogg_sync_check(oy))return -1;
627
23.3k
  if(oy->fill+bytes>oy->storage)return -1;
628
23.3k
  oy->fill+=bytes;
629
23.3k
  return(0);
630
23.3k
}
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
217k
long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){
643
217k
  unsigned char *page;
644
217k
  unsigned char *next;
645
217k
  long bytes;
646
647
217k
  if(ogg_sync_check(oy))return 0;
648
649
217k
  page=oy->data+oy->returned;
650
217k
  bytes=oy->fill-oy->returned;
651
652
217k
  if(oy->headerbytes==0){
653
204k
    int headerbytes,i;
654
204k
    if(bytes<27)return(0); /* not enough for a header */
655
656
    /* verify capture pattern */
657
194k
    if(memcmp(page,"OggS",4))goto sync_fail;
658
659
35.2k
    headerbytes=page[26]+27;
660
35.2k
    if(bytes<headerbytes)return(0); /* not enough for header + seg table */
661
662
    /* count up body length in the segment table */
663
664
776k
    for(i=0;i<page[26];i++)
665
741k
      oy->bodybytes+=page[27+i];
666
34.9k
    oy->headerbytes=headerbytes;
667
34.9k
  }
668
669
48.2k
  if(oy->bodybytes+oy->headerbytes>bytes)return(0);
670
671
  /* The whole test page is buffered.  Verify the checksum */
672
34.7k
  {
673
    /* Grab the checksum bytes, set the header field to zero */
674
34.7k
    char chksum[4];
675
34.7k
    ogg_page log;
676
677
34.7k
    memcpy(chksum,page+22,4);
678
34.7k
    memset(page+22,0,4);
679
680
    /* set up a temp page struct and recompute the checksum */
681
34.7k
    log.header=page;
682
34.7k
    log.header_len=oy->headerbytes;
683
34.7k
    log.body=page+oy->headerbytes;
684
34.7k
    log.body_len=oy->bodybytes;
685
34.7k
    ogg_page_checksum_set(&log);
686
687
    /* Compare */
688
34.7k
    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
31.8k
      memcpy(page+22,chksum,4);
693
694
#ifndef DISABLE_CRC
695
      /* Bad checksum. Lose sync */
696
      goto sync_fail;
697
#endif
698
31.8k
    }
699
34.7k
  }
700
701
  /* yes, have a whole page all ready to go */
702
34.7k
  {
703
34.7k
    if(og){
704
34.7k
      og->header=page;
705
34.7k
      og->header_len=oy->headerbytes;
706
34.7k
      og->body=page+oy->headerbytes;
707
34.7k
      og->body_len=oy->bodybytes;
708
34.7k
    }
709
710
34.7k
    oy->unsynced=0;
711
34.7k
    oy->returned+=(bytes=oy->headerbytes+oy->bodybytes);
712
34.7k
    oy->headerbytes=0;
713
34.7k
    oy->bodybytes=0;
714
34.7k
    return(bytes);
715
48.2k
  }
716
717
159k
 sync_fail:
718
719
159k
  oy->headerbytes=0;
720
159k
  oy->bodybytes=0;
721
722
  /* search for possible capture */
723
159k
  next=memchr(page+1,'O',bytes-1);
724
159k
  if(!next)
725
5.08k
    next=oy->data+oy->fill;
726
727
159k
  oy->returned=(int)(next-oy->data);
728
159k
  return((long)-(next-page));
729
48.2k
}
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
91.1k
int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og){
743
744
91.1k
  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
217k
  for(;;){
751
217k
    long ret=ogg_sync_pageseek(oy,og);
752
217k
    if(ret>0){
753
      /* have a page */
754
34.7k
      return(1);
755
34.7k
    }
756
182k
    if(ret==0){
757
      /* need more data */
758
23.8k
      return(0);
759
23.8k
    }
760
761
    /* head did not start a synced page... skipped some bytes */
762
159k
    if(!oy->unsynced){
763
32.5k
      oy->unsynced=1;
764
32.5k
      return(-1);
765
32.5k
    }
766
767
    /* loop. keep looking */
768
769
159k
  }
770
91.1k
}
771
772
/* add the incoming page to the stream state; we decompose the page
773
   into packet segments here as well. */
774
775
34.7k
int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){
776
34.7k
  unsigned char *header=og->header;
777
34.7k
  unsigned char *body=og->body;
778
34.7k
  long           bodysize=og->body_len;
779
34.7k
  int            segptr=0;
780
781
34.7k
  int version=ogg_page_version(og);
782
34.7k
  int continued=ogg_page_continued(og);
783
34.7k
  int bos=ogg_page_bos(og);
784
34.7k
  int eos=ogg_page_eos(og);
785
34.7k
  ogg_int64_t granulepos=ogg_page_granulepos(og);
786
34.7k
  int serialno=ogg_page_serialno(og);
787
34.7k
  long pageno=ogg_page_pageno(og);
788
34.7k
  int segments=header[26];
789
790
34.7k
  if(ogg_stream_check(os)) return -1;
791
792
  /* clean up 'returned data' */
793
34.7k
  {
794
34.7k
    long lr=os->lacing_returned;
795
34.7k
    long br=os->body_returned;
796
797
    /* body data */
798
34.7k
    if(br){
799
19.1k
      os->body_fill-=br;
800
19.1k
      if(os->body_fill)
801
614
        memmove(os->body_data,os->body_data+br,os->body_fill);
802
19.1k
      os->body_returned=0;
803
19.1k
    }
804
805
34.7k
    if(lr){
806
      /* segment table */
807
21.7k
      if(os->lacing_fill-lr){
808
862
        memmove(os->lacing_vals,os->lacing_vals+lr,
809
862
                (os->lacing_fill-lr)*sizeof(*os->lacing_vals));
810
862
        memmove(os->granule_vals,os->granule_vals+lr,
811
862
                (os->lacing_fill-lr)*sizeof(*os->granule_vals));
812
862
      }
813
21.7k
      os->lacing_fill-=lr;
814
21.7k
      os->lacing_packet-=lr;
815
21.7k
      os->lacing_returned=0;
816
21.7k
    }
817
34.7k
  }
818
819
  /* check the serial number */
820
34.7k
  if(serialno!=os->serialno)return(-1);
821
27.0k
  if(version>0)return(-1);
822
823
26.3k
  if(_os_lacing_expand(os,segments+1)) return -1;
824
825
  /* are we in sequence? */
826
26.3k
  if(pageno!=os->pageno){
827
23.7k
    int i;
828
829
    /* unroll previous partial packet (if any) */
830
25.6k
    for(i=os->lacing_packet;i<os->lacing_fill;i++)
831
1.88k
      os->body_fill-=os->lacing_vals[i]&0xff;
832
23.7k
    os->lacing_fill=os->lacing_packet;
833
834
    /* make a note of dropped data in segment table */
835
23.7k
    if(os->pageno!=-1){
836
19.6k
      os->lacing_vals[os->lacing_fill++]=0x400;
837
19.6k
      os->lacing_packet++;
838
19.6k
    }
839
23.7k
  }
840
841
  /* are we a 'continued packet' page?  If so, we may need to skip
842
     some segments */
843
26.3k
  if(continued){
844
11.0k
    if(os->lacing_fill<1 ||
845
11.0k
       (os->lacing_vals[os->lacing_fill-1]&0xff)<255 ||
846
11.0k
       os->lacing_vals[os->lacing_fill-1]==0x400){
847
9.63k
      bos=0;
848
10.2k
      for(;segptr<segments;segptr++){
849
8.42k
        int val=header[27+segptr];
850
8.42k
        body+=val;
851
8.42k
        bodysize-=val;
852
8.42k
        if(val<255){
853
7.85k
          segptr++;
854
7.85k
          break;
855
7.85k
        }
856
8.42k
      }
857
9.63k
    }
858
11.0k
  }
859
860
26.3k
  if(bodysize){
861
23.1k
    if(_os_body_expand(os,bodysize)) return -1;
862
23.1k
    memcpy(os->body_data+os->body_fill,body,bodysize);
863
23.1k
    os->body_fill+=bodysize;
864
23.1k
  }
865
866
26.3k
  {
867
26.3k
    int saved=-1;
868
701k
    while(segptr<segments){
869
675k
      int val=header[27+segptr];
870
675k
      os->lacing_vals[os->lacing_fill]=val;
871
675k
      os->granule_vals[os->lacing_fill]=-1;
872
873
675k
      if(bos){
874
12.9k
        os->lacing_vals[os->lacing_fill]|=0x100;
875
12.9k
        bos=0;
876
12.9k
      }
877
878
675k
      if(val<255)saved=os->lacing_fill;
879
880
675k
      os->lacing_fill++;
881
675k
      segptr++;
882
883
675k
      if(val<255)os->lacing_packet=os->lacing_fill;
884
675k
    }
885
886
    /* set the granulepos on the last granuleval of the last full packet */
887
26.3k
    if(saved!=-1){
888
21.6k
      os->granule_vals[saved]=granulepos;
889
21.6k
    }
890
891
26.3k
  }
892
893
26.3k
  if(eos){
894
8.24k
    os->e_o_s=1;
895
8.24k
    if(os->lacing_fill>0)
896
7.75k
      os->lacing_vals[os->lacing_fill-1]|=0x200;
897
8.24k
  }
898
899
26.3k
  os->pageno=pageno+1;
900
901
26.3k
  return(0);
902
26.3k
}
903
904
/* clear things to an initial state.  Good to call, eg, before seeking */
905
5.42k
int ogg_sync_reset(ogg_sync_state *oy){
906
5.42k
  if(ogg_sync_check(oy))return -1;
907
908
5.42k
  oy->fill=0;
909
5.42k
  oy->returned=0;
910
5.42k
  oy->unsynced=0;
911
5.42k
  oy->headerbytes=0;
912
5.42k
  oy->bodybytes=0;
913
5.42k
  return(0);
914
5.42k
}
915
916
7.28k
int ogg_stream_reset(ogg_stream_state *os){
917
7.28k
  if(ogg_stream_check(os)) return -1;
918
919
7.28k
  os->body_fill=0;
920
7.28k
  os->body_returned=0;
921
922
7.28k
  os->lacing_fill=0;
923
7.28k
  os->lacing_packet=0;
924
7.28k
  os->lacing_returned=0;
925
926
7.28k
  os->header_fill=0;
927
928
7.28k
  os->e_o_s=0;
929
7.28k
  os->b_o_s=0;
930
7.28k
  os->pageno=-1;
931
7.28k
  os->packetno=0;
932
7.28k
  os->granulepos=0;
933
934
7.28k
  return(0);
935
7.28k
}
936
937
1.86k
int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno){
938
1.86k
  if(ogg_stream_check(os)) return -1;
939
1.86k
  ogg_stream_reset(os);
940
1.86k
  os->serialno=serialno;
941
1.86k
  return(0);
942
1.86k
}
943
944
302k
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
302k
  int ptr=os->lacing_returned;
951
952
302k
  if(os->lacing_packet<=ptr)return(0);
953
954
282k
  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
19.6k
    os->lacing_returned++;
958
19.6k
    os->packetno++;
959
19.6k
    return(-1);
960
19.6k
  }
961
962
262k
  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
262k
  {
968
262k
    int size=os->lacing_vals[ptr]&0xff;
969
262k
    long bytes=size;
970
262k
    int eos=os->lacing_vals[ptr]&0x200; /* last packet of the stream? */
971
262k
    int bos=os->lacing_vals[ptr]&0x100; /* first packet of the stream? */
972
973
652k
    while(size==255){
974
389k
      int val=os->lacing_vals[++ptr];
975
389k
      size=val&0xff;
976
389k
      if(val&0x200)eos=0x200;
977
389k
      bytes+=size;
978
389k
    }
979
980
262k
    if(op){
981
262k
      op->e_o_s=eos;
982
262k
      op->b_o_s=bos;
983
262k
      op->packet=os->body_data+os->body_returned;
984
262k
      op->packetno=os->packetno;
985
262k
      op->granulepos=os->granule_vals[ptr];
986
262k
      op->bytes=bytes;
987
262k
    }
988
989
262k
    if(adv){
990
262k
      os->body_returned+=bytes;
991
262k
      os->lacing_returned=ptr+1;
992
262k
      os->packetno++;
993
262k
    }
994
262k
  }
995
262k
  return(1);
996
262k
}
997
998
302k
int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op){
999
302k
  if(ogg_stream_check(os)) return 0;
1000
302k
  return _packetout(os,op,1);
1001
302k
}
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