vorbisfile.c 69.8 KB
Newer Older
Monty's avatar
 
Monty committed
1
2
/********************************************************************
 *                                                                  *
Monty's avatar
   
Monty committed
3
 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
Monty's avatar
   
Monty committed
4
5
6
 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
Monty's avatar
 
Monty committed
7
 *                                                                  *
Monty's avatar
Monty committed
8
 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009             *
9
 * by the Xiph.Org Foundation http://www.xiph.org/                  *
Monty's avatar
   
Monty committed
10
 *                                                                  *
Monty's avatar
 
Monty committed
11
12
 ********************************************************************

Monty's avatar
   
Monty committed
13
 function: stdio-based convenience library for opening/seeking/decoding
Michael Smith's avatar
Michael Smith committed
14
 last mod: $Id$
Monty's avatar
 
Monty committed
15
16
17

 ********************************************************************/

Monty's avatar
   
Monty committed
18
#include <stdlib.h>
Monty's avatar
 
Monty committed
19
#include <stdio.h>
Monty's avatar
   
Monty committed
20
#include <errno.h>
Monty's avatar
   
Monty committed
21
#include <string.h>
Monty's avatar
   
Monty committed
22
#include <math.h>
23

Monty's avatar
   
Monty committed
24
#include "vorbis/codec.h"
Monty's avatar
Monty committed
25
26
27

/* we don't need or want the static callback symbols here */
#define OV_EXCLUDE_STATIC_CALLBACKS
Monty's avatar
   
Monty committed
28
29
#include "vorbis/vorbisfile.h"

Monty's avatar
   
Monty committed
30
#include "os.h"
Monty's avatar
   
Monty committed
31
#include "misc.h"
Monty's avatar
 
Monty committed
32
33
34
35
36
37
38

/* A 'chained bitstream' is a Vorbis bitstream that contains more than
   one logical bitstream arranged end to end (the only form of Ogg
   multiplexing allowed in a Vorbis bitstream; grouping [parallel
   multiplexing] is not allowed in Vorbis) */

/* A Vorbis file can be played beginning to end (streamed) without
Monty's avatar
   
Monty committed
39
40
41
42
   worrying ahead of time about chaining (see decoder_example.c).  If
   we have the whole file, however, and want random access
   (seeking/scrubbing) or desire to know the total length/time of a
   file, we need to account for the possibility of chaining. */
Monty's avatar
 
Monty committed
43
44

/* We can handle things a number of ways; we can determine the entire
Monty's avatar
   
Monty committed
45
   bitstream structure right off the bat, or find pieces on demand.
Monty's avatar
 
Monty committed
46
   This example determines and caches structure for the entire
Monty's avatar
   
Monty committed
47
   bitstream, but builds a virtual decoder on the fly when moving
Monty's avatar
   
Monty committed
48
   between links in the chain. */
Monty's avatar
 
Monty committed
49
50
51
52

/* There are also different ways to implement seeking.  Enough
   information exists in an Ogg bitstream to seek to
   sample-granularity positions in the output.  Or, one can seek by
Monty's avatar
   
Monty committed
53
   picking some portion of the stream roughly in the desired area if
Ralph Giles's avatar
Ralph Giles committed
54
   we only want coarse navigation through the stream. */
Monty's avatar
   
Monty committed
55

Monty's avatar
   
Monty committed
56
/*************************************************************************
57
58
 * Many, many internal helpers.  The intention is not to be confusing;
 * rampant duplication and monolithic function implementation would be
Monty's avatar
   
Monty committed
59
60
61
 * harder to understand anyway.  The high level functions are last.  Begin
 * grokking near the end of the file */

Ralph Giles's avatar
Ralph Giles committed
62
63
/* read a little more data from the file/pipe into the ogg_sync framer
*/
64
65
#define CHUNKSIZE 65536

Monty's avatar
   
Monty committed
66
static long _get_data(OggVorbis_File *vf){
Monty's avatar
   
Monty committed
67
  errno=0;
68
  if(!(vf->callbacks.read_func))return(-1);
Monty's avatar
   
Monty committed
69
70
71
72
73
74
75
76
  if(vf->datasource){
    char *buffer=ogg_sync_buffer(&vf->oy,CHUNKSIZE);
    long bytes=(vf->callbacks.read_func)(buffer,1,CHUNKSIZE,vf->datasource);
    if(bytes>0)ogg_sync_wrote(&vf->oy,bytes);
    if(bytes==0 && errno)return(-1);
    return(bytes);
  }else
    return(0);
Monty's avatar
   
Monty committed
77
78
79
}

/* save a tiny smidge of verbosity to make the code more readable */
80
static int _seek_helper(OggVorbis_File *vf,ogg_int64_t offset){
81
  if(vf->datasource){
82
83
    if(!(vf->callbacks.seek_func)||
       (vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET) == -1)
84
      return OV_EREAD;
Monty's avatar
   
Monty committed
85
86
87
88
    vf->offset=offset;
    ogg_sync_reset(&vf->oy);
  }else{
    /* shouldn't happen unless someone writes a broken callback */
89
    return OV_EFAULT;
Monty's avatar
   
Monty committed
90
  }
91
  return 0;
Monty's avatar
   
Monty committed
92
93
94
95
96
97
98
99
100
101
}

/* The read/seek functions track absolute position within the stream */

/* from the head of the stream, get the next page.  boundary specifies
   if the function is allowed to fetch more data from the stream (and
   how much) or only use internally buffered data.

   boundary: -1) unbounded search
              0) read no additional data; use cached only
102
              n) search for a new page beginning for n bytes
Monty's avatar
   
Monty committed
103

Monty's avatar
   
Monty committed
104
   return:   <0) did not find a page (OV_FALSE, OV_EOF, OV_EREAD)
Monty's avatar
   
Monty committed
105
106
              n) found a page at absolute offset n */

Monty's avatar
   
Monty committed
107
static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og,
108
                                  ogg_int64_t boundary){
Monty's avatar
   
Monty committed
109
110
111
112
  if(boundary>0)boundary+=vf->offset;
  while(1){
    long more;

Monty's avatar
   
Monty committed
113
    if(boundary>0 && vf->offset>=boundary)return(OV_FALSE);
Monty's avatar
   
Monty committed
114
    more=ogg_sync_pageseek(&vf->oy,og);
115

Monty's avatar
   
Monty committed
116
117
118
119
120
    if(more<0){
      /* skipped n bytes */
      vf->offset-=more;
    }else{
      if(more==0){
121
122
123
124
125
126
127
        /* send more paramedics */
        if(!boundary)return(OV_FALSE);
        {
          long ret=_get_data(vf);
          if(ret==0)return(OV_EOF);
          if(ret<0)return(OV_EREAD);
        }
Monty's avatar
   
Monty committed
128
      }else{
129
        /* got a page.  Return the offset at the page beginning,
Monty's avatar
   
Monty committed
130
           advance the internal offset past the page end */
131
132
133
        ogg_int64_t ret=vf->offset;
        vf->offset+=more;
        return(ret);
134

Monty's avatar
   
Monty committed
135
136
137
138
139
140
141
142
143
      }
    }
  }
}

/* find the latest page beginning before the current stream cursor
   position. Much dirtier than the above as Ogg doesn't have any
   backward search linkage.  no 'readp' as it will certainly have to
   read. */
Monty's avatar
   
Monty committed
144
/* returns offset or OV_EREAD, OV_FAULT */
Monty's avatar
   
Monty committed
145
146
147
148
149
static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_page *og){
  ogg_int64_t begin=vf->offset;
  ogg_int64_t end=begin;
  ogg_int64_t ret;
  ogg_int64_t offset=-1;
Monty's avatar
   
Monty committed
150
151
152

  while(offset==-1){
    begin-=CHUNKSIZE;
153
154
    if(begin<0)
      begin=0;
155
156
157
158

    ret=_seek_helper(vf,begin);
    if(ret)return(ret);

Monty's avatar
   
Monty committed
159
    while(vf->offset<end){
160
      memset(og,0,sizeof(*og));
Monty's avatar
   
Monty committed
161
      ret=_get_next_page(vf,og,end-vf->offset);
Monty's avatar
   
Monty committed
162
163
      if(ret==OV_EREAD)return(OV_EREAD);
      if(ret<0){
164
        break;
Monty's avatar
   
Monty committed
165
      }else{
166
        offset=ret;
Monty's avatar
   
Monty committed
167
168
169
170
      }
    }
  }

171
172
  /* In a fully compliant, non-multiplexed stream, we'll still be
     holding the last page.  In multiplexed (or noncompliant streams),
173
     we will probably have to re-read the last page we saw */
174
175
176
  if(og->header_len==0){
    ret=_seek_helper(vf,offset);
    if(ret)return(ret);
177

178
179
180
181
182
    ret=_get_next_page(vf,og,CHUNKSIZE);
    if(ret<0)
      /* this shouldn't be possible */
      return(OV_EFAULT);
  }
Monty's avatar
   
Monty committed
183

Monty's avatar
   
Monty committed
184
185
186
  return(offset);
}

187
188
189
190
static void _add_serialno(ogg_page *og,long **serialno_list, int *n){
  long s = ogg_page_serialno(og);
  (*n)++;

Monty's avatar
Monty committed
191
192
  if(*serialno_list){
    *serialno_list = _ogg_realloc(*serialno_list, sizeof(**serialno_list)*(*n));
193
194
195
  }else{
    *serialno_list = _ogg_malloc(sizeof(**serialno_list));
  }
196

197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
  (*serialno_list)[(*n)-1] = s;
}

/* returns nonzero if found */
static int _lookup_serialno(long s, long *serialno_list, int n){
  if(serialno_list){
    while(n--){
      if(*serialno_list == s) return 1;
      serialno_list++;
    }
  }
  return 0;
}

static int _lookup_page_serialno(ogg_page *og, long *serialno_list, int n){
  long s = ogg_page_serialno(og);
  return _lookup_serialno(s,serialno_list,n);
}

216
217
218
219
220
221
/* performs the same search as _get_prev_page, but prefers pages of
   the specified serial number. If a page of the specified serialno is
   spotted during the seek-back-and-read-forward, it will return the
   info of last page of the matching serial number instead of the very
   last page.  If no page of the specified serialno is seen, it will
   return the info of last page and alter *serialno.  */
222
static ogg_int64_t _get_prev_page_serial(OggVorbis_File *vf,
223
224
                                         long *serial_list, int serial_n,
                                         int *serialno, ogg_int64_t *granpos){
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
  ogg_page og;
  ogg_int64_t begin=vf->offset;
  ogg_int64_t end=begin;
  ogg_int64_t ret;

  ogg_int64_t prefoffset=-1;
  ogg_int64_t offset=-1;
  ogg_int64_t ret_serialno;
  ogg_int64_t ret_gran;

  while(offset==-1){
    begin-=CHUNKSIZE;
    if(begin<0)
      begin=0;

    ret=_seek_helper(vf,begin);
    if(ret)return(ret);

    while(vf->offset<end){
      ret=_get_next_page(vf,&og,end-vf->offset);
      if(ret==OV_EREAD)return(OV_EREAD);
      if(ret<0){
247
        break;
248
      }else{
249
250
251
252
253
254
255
        ret_serialno=ogg_page_serialno(&og);
        ret_gran=ogg_page_granulepos(&og);
        offset=ret;

        if(ret_serialno == *serialno){
          prefoffset=ret;
          *granpos=ret_gran;
256
        }
257
258
259
260
261
262
263
264

        if(!_lookup_serialno(ret_serialno,serial_list,serial_n)){
          /* we fell off the end of the link, which means we seeked
             back too far and shouldn't have been looking in that link
             to begin with.  If we found the preferred serial number,
             forget that we saw it. */
          prefoffset=-1;
        }
265
266
267
268
269
270
271
272
273
274
275
276
277
      }
    }
  }

  /* we're not interested in the page... just the serialno and granpos. */
  if(prefoffset>=0)return(prefoffset);

  *serialno = ret_serialno;
  *granpos = ret_gran;
  return(offset);

}

Monty's avatar
   
Monty committed
278
279
/* uses the local ogg_stream storage in vf; this is important for
   non-streaming input sources */
Monty's avatar
   
Monty committed
280
static int _fetch_headers(OggVorbis_File *vf,vorbis_info *vi,vorbis_comment *vc,
281
                          long **serialno_list, int *serialno_n,
282
                          ogg_page *og_ptr){
Monty's avatar
   
Monty committed
283
284
  ogg_page og;
  ogg_packet op;
Monty's avatar
   
Monty committed
285
  int i,ret;
286
287
  int allbos=0;

Monty's avatar
   
Monty committed
288
  if(!og_ptr){
Monty's avatar
   
Monty committed
289
290
    ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE);
    if(llret==OV_EREAD)return(OV_EREAD);
291
    if(llret<0)return(OV_ENOTVORBIS);
Monty's avatar
   
Monty committed
292
293
294
    og_ptr=&og;
  }

Monty's avatar
   
Monty committed
295
  vorbis_info_init(vi);
Monty's avatar
   
Monty committed
296
  vorbis_comment_init(vc);
297
  vf->ready_state=OPENED;
298

299
300
301
302
303
  /* extract the serialnos of all BOS pages + the first set of vorbis
     headers we see in the link */

  while(ogg_page_bos(og_ptr)){
    if(serialno_list){
304
      if(_lookup_page_serialno(og_ptr,*serialno_list,*serialno_n)){
305
306
307
308
309
310
311
        /* a dupe serialnumber in an initial header packet set == invalid stream */
        if(*serialno_list)_ogg_free(*serialno_list);
        *serialno_list=0;
        *serialno_n=0;
        ret=OV_EBADHEADER;
        goto bail_header;
      }
312

313
      _add_serialno(og_ptr,serialno_list,serialno_n);
314
315
    }

316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
    if(vf->ready_state<STREAMSET){
      /* we don't have a vorbis stream in this link yet, so begin
         prospective stream setup. We need a stream to get packets */
      ogg_stream_reset_serialno(&vf->os,ogg_page_serialno(og_ptr));
      ogg_stream_pagein(&vf->os,og_ptr);

      if(ogg_stream_packetout(&vf->os,&op) > 0 &&
         vorbis_synthesis_idheader(&op)){
        /* vorbis header; continue setup */
        vf->ready_state=STREAMSET;
        if((ret=vorbis_synthesis_headerin(vi,vc,&op))){
          ret=OV_EBADHEADER;
          goto bail_header;
        }
      }
    }
332

333
334
335
336
337
338
339
340
341
342
343
    /* get next page */
    {
      ogg_int64_t llret=_get_next_page(vf,og_ptr,CHUNKSIZE);
      if(llret==OV_EREAD){
        ret=OV_EREAD;
        goto bail_header;
      }
      if(llret<0){
        ret=OV_ENOTVORBIS;
        goto bail_header;
      }
344

345
      /* if this page also belongs to our vorbis stream, submit it and break */
346
      if(vf->ready_state==STREAMSET &&
347
348
349
         vf->os.serialno == ogg_page_serialno(og_ptr)){
        ogg_stream_pagein(&vf->os,og_ptr);
        break;
350
351
      }
    }
352
  }
353

354
355
356
357
  if(vf->ready_state!=STREAMSET){
    ret = OV_ENOTVORBIS;
    goto bail_header;
  }
358

359
  while(1){
360

361
362
    i=0;
    while(i<2){ /* get a page loop */
363

364
      while(i<2){ /* get a packet loop */
365

366
367
368
369
370
371
        int result=ogg_stream_packetout(&vf->os,&op);
        if(result==0)break;
        if(result==-1){
          ret=OV_EBADHEADER;
          goto bail_header;
        }
372

373
374
        if((ret=vorbis_synthesis_headerin(vi,vc,&op)))
          goto bail_header;
375

376
377
        i++;
      }
378

379
380
381
382
383
      while(i<2){
        if(_get_next_page(vf,og_ptr,CHUNKSIZE)<0){
          ret=OV_EBADHEADER;
          goto bail_header;
        }
384

385
386
387
388
389
        /* if this page belongs to the correct stream, go parse it */
        if(vf->os.serialno == ogg_page_serialno(og_ptr)){
          ogg_stream_pagein(&vf->os,og_ptr);
          break;
        }
390

391
392
393
394
395
396
397
398
399
        /* if we never see the final vorbis headers before the link
           ends, abort */
        if(ogg_page_bos(og_ptr)){
          if(allbos){
            ret = OV_EBADHEADER;
            goto bail_header;
          }else
            allbos=1;
        }
400

401
        /* otherwise, keep looking */
Monty's avatar
   
Monty committed
402
403
      }
    }
404
405

    return 0;
Monty's avatar
   
Monty committed
406
  }
Monty's avatar
   
Monty committed
407

Monty's avatar
   
Monty committed
408
409
 bail_header:
  vorbis_info_clear(vi);
Monty's avatar
   
Monty committed
410
  vorbis_comment_clear(vc);
Monty's avatar
   
Monty committed
411
412
  vf->ready_state=OPENED;

Monty's avatar
   
Monty committed
413
  return ret;
Monty's avatar
   
Monty committed
414
}
Monty's avatar
   
Monty committed
415

416
417
418
419
420
421
422
423
424
425
/* Starting from current cursor position, get initial PCM offset of
   next page.  Consumes the page in the process without decoding
   audio, however this is only called during stream parsing upon
   seekable open. */
static ogg_int64_t _initial_pcmoffset(OggVorbis_File *vf, vorbis_info *vi){
  ogg_page    og;
  ogg_int64_t accumulated=0;
  long        lastblock=-1;
  int         result;
  int         serialno = vf->os.serialno;
Monty's avatar
   
Monty committed
426

427
428
429
430
  while(1){
    ogg_packet op;
    if(_get_next_page(vf,&og,-1)<0)
      break; /* should not be possible unless the file is truncated/mangled */
431

432
433
    if(ogg_page_bos(&og)) break;
    if(ogg_page_serialno(&og)!=serialno) continue;
434

435
436
437
438
    /* count blocksizes of all frames in the page */
    ogg_stream_pagein(&vf->os,&og);
    while((result=ogg_stream_packetout(&vf->os,&op))){
      if(result>0){ /* ignore holes */
439
440
441
442
        long thisblock=vorbis_packet_blocksize(vi,&op);
        if(lastblock!=-1)
          accumulated+=(lastblock+thisblock)>>2;
        lastblock=thisblock;
443
444
      }
    }
445

446
447
448
449
450
451
    if(ogg_page_granulepos(&og)!=-1){
      /* pcm offset of last packet on the first audio page */
      accumulated= ogg_page_granulepos(&og)-accumulated;
      break;
    }
  }
452

453
454
455
  /* less than zero?  This is a stream with samples trimmed off
     the beginning, a normal occurrence; set the offset to zero */
  if(accumulated<0)accumulated=0;
456

457
458
  return accumulated;
}
Monty's avatar
   
Monty committed
459

460
461
462
463
464
/* finds each bitstream link one at a time using a bisection search
   (has to begin by knowing the offset of the lb's initial page).
   Recurses for each link so it can alloc the link storage after
   finding them all, then unroll and fill the cache at the same time */
static int _bisect_forward_serialno(OggVorbis_File *vf,
465
466
467
468
469
470
471
472
                                    ogg_int64_t begin,
                                    ogg_int64_t searched,
                                    ogg_int64_t end,
                                    ogg_int64_t endgran,
                                    int endserial,
                                    long *currentno_list,
                                    int  currentnos,
                                    long m){
473
474
475
476
477
478
479
480
481
  ogg_int64_t pcmoffset;
  ogg_int64_t dataoffset=searched;
  ogg_int64_t endsearched=end;
  ogg_int64_t next=end;
  ogg_int64_t searchgran=-1;
  ogg_page og;
  ogg_int64_t ret,last;
  int serialno = vf->os.serialno;

482
  /* invariants:
483
     we have the headers and serialnos for the link beginning at 'begin'
484
     we have the offset and granpos of the last page in the file (potentially
485
486
487
488
489
490
491
492
493
494
       not a page we care about)
  */

  /* Is the last page in our list of current serialnumbers? */
  if(_lookup_serialno(endserial,currentno_list,currentnos)){

    /* last page is in the starting serialno list, so we've bisected
       down to (or just started with) a single link.  Now we need to
       find the last vorbis page belonging to the first vorbis stream
       for this link. */
495

496
497
    while(endserial != serialno){
      endserial = serialno;
498
      vf->offset=_get_prev_page_serial(vf,currentno_list,currentnos,&endserial,&endgran);
499
    }
Monty's avatar
   
Monty committed
500

501
502
503
504
    vf->links=m+1;
    if(vf->offsets)_ogg_free(vf->offsets);
    if(vf->serialnos)_ogg_free(vf->serialnos);
    if(vf->dataoffsets)_ogg_free(vf->dataoffsets);
Monty's avatar
   
Monty committed
505

506
507
508
509
510
511
512
513
514
    vf->offsets=_ogg_malloc((vf->links+1)*sizeof(*vf->offsets));
    vf->vi=_ogg_realloc(vf->vi,vf->links*sizeof(*vf->vi));
    vf->vc=_ogg_realloc(vf->vc,vf->links*sizeof(*vf->vc));
    vf->serialnos=_ogg_malloc(vf->links*sizeof(*vf->serialnos));
    vf->dataoffsets=_ogg_malloc(vf->links*sizeof(*vf->dataoffsets));
    vf->pcmlengths=_ogg_malloc(vf->links*2*sizeof(*vf->pcmlengths));

    vf->offsets[m+1]=end;
    vf->offsets[m]=begin;
515
    vf->pcmlengths[m*2+1]=endgran;
516
517

  }else{
518

519
520
521
522
523
524
525
526
527
    long *next_serialno_list=NULL;
    int next_serialnos=0;
    vorbis_info vi;
    vorbis_comment vc;

    /* the below guards against garbage seperating the last and
       first pages of two links. */
    while(searched<endsearched){
      ogg_int64_t bisect;
528

529
      if(endsearched-searched<CHUNKSIZE){
530
        bisect=searched;
Monty's avatar
   
Monty committed
531
      }else{
532
        bisect=(searched+endsearched)/2;
Monty's avatar
   
Monty committed
533
      }
534

535
536
      ret=_seek_helper(vf,bisect);
      if(ret)return(ret);
Monty's avatar
   
Monty committed
537

538
539
540
      last=_get_next_page(vf,&og,-1);
      if(last==OV_EREAD)return(OV_EREAD);
      if(last<0 || !_lookup_page_serialno(&og,currentno_list,currentnos)){
541
542
        endsearched=bisect;
        if(last>=0)next=last;
543
      }else{
544
        searched=last+og.header_len+og.body_len;
545
546
      }
    }
Monty's avatar
   
Monty committed
547

548
    /* Bisection point found */
Monty's avatar
   
Monty committed
549

550
551
552
553
554
    /* for the time being, fetch end PCM offset the simple way */
    {
      int testserial = serialno+1;
      vf->offset = next;
      while(testserial != serialno){
555
556
        testserial = serialno;
        vf->offset=_get_prev_page_serial(vf,currentno_list,currentnos,&testserial,&searchgran);
557
558
      }
    }
Monty's avatar
   
Monty committed
559

560
561
562
563
    if(vf->offset!=next){
      ret=_seek_helper(vf,next);
      if(ret)return(ret);
    }
Monty's avatar
   
Monty committed
564

565
566
567
568
    ret=_fetch_headers(vf,&vi,&vc,&next_serialno_list,&next_serialnos,NULL);
    if(ret)return(ret);
    serialno = vf->os.serialno;
    dataoffset = vf->offset;
569

570
571
572
    /* this will consume a page, however the next bistection always
       starts with a raw seek */
    pcmoffset = _initial_pcmoffset(vf,&vi);
Monty's avatar
   
Monty committed
573

574
    ret=_bisect_forward_serialno(vf,next,vf->offset,end,endgran,endserial,
575
                                 next_serialno_list,next_serialnos,m+1);
576
    if(ret)return(ret);
577

578
    if(next_serialno_list)_ogg_free(next_serialno_list);
579

580
581
582
    vf->offsets[m+1]=next;
    vf->serialnos[m+1]=serialno;
    vf->dataoffsets[m+1]=dataoffset;
Monty's avatar
   
Monty committed
583

584
585
    vf->vi[m+1]=vi;
    vf->vc[m+1]=vc;
Monty's avatar
   
Monty committed
586

587
588
589
    vf->pcmlengths[m*2+1]=searchgran;
    vf->pcmlengths[m*2+2]=pcmoffset;
    vf->pcmlengths[m*2+3]-=pcmoffset;
Monty's avatar
   
Monty committed
590

Monty's avatar
   
Monty committed
591
  }
592
  return(0);
Monty's avatar
   
Monty committed
593
594
}

Monty's avatar
   
Monty committed
595
static int _make_decode_ready(OggVorbis_File *vf){
Monty's avatar
   
Monty committed
596
597
  if(vf->ready_state>STREAMSET)return 0;
  if(vf->ready_state<STREAMSET)return OV_EFAULT;
Monty's avatar
   
Monty committed
598
  if(vf->seekable){
Monty's avatar
   
Monty committed
599
600
    if(vorbis_synthesis_init(&vf->vd,vf->vi+vf->current_link))
      return OV_EBADLINK;
Monty's avatar
   
Monty committed
601
  }else{
Monty's avatar
   
Monty committed
602
603
    if(vorbis_synthesis_init(&vf->vd,vf->vi))
      return OV_EBADLINK;
604
  }
Monty's avatar
   
Monty committed
605
  vorbis_block_init(&vf->vd,&vf->vb);
Monty's avatar
   
Monty committed
606
  vf->ready_state=INITSET;
Monty's avatar
   
Monty committed
607
608
  vf->bittrack=0.f;
  vf->samptrack=0.f;
Monty's avatar
   
Monty committed
609
  return 0;
Monty's avatar
   
Monty committed
610
611
}

Monty's avatar
   
Monty committed
612
static int _open_seekable2(OggVorbis_File *vf){
613
614
615
  ogg_int64_t dataoffset=vf->dataoffsets[0],end,endgran=-1;
  int endserial=vf->os.serialno;
  int serialno=vf->os.serialno;
Monty's avatar
   
Monty committed
616
617
618

  /* we're partially open and have a first link header state in
     storage in vf */
619
620
621
622

  /* fetch initial PCM offset */
  ogg_int64_t pcmoffset = _initial_pcmoffset(vf,vf->vi);

Monty's avatar
   
Monty committed
623
  /* we can seek, so set out learning all about this file */
624
  if(vf->callbacks.seek_func && vf->callbacks.tell_func){
625
626
627
628
629
    (vf->callbacks.seek_func)(vf->datasource,0,SEEK_END);
    vf->offset=vf->end=(vf->callbacks.tell_func)(vf->datasource);
  }else{
    vf->offset=vf->end=-1;
  }
630
631
632
633

  /* If seek_func is implemented, tell_func must also be implemented */
  if(vf->end==-1) return(OV_EINVAL);

634
635
636
  /* Get the offset of the last page of the physical bitstream, or, if
     we're lucky the last vorbis page of this link as most OggVorbis
     files will contain a single logical bitstream */
637
  end=_get_prev_page_serial(vf,vf->serialnos+2,vf->serialnos[1],&endserial,&endgran);
638
639
  if(end<0)return(end);

640
  /* now determine bitstream structure recursively */
641
  if(_bisect_forward_serialno(vf,0,dataoffset,vf->offset,endgran,endserial,
642
                              vf->serialnos+2,vf->serialnos[1],0)<0)return(OV_EREAD);
643
644
645
646
647
648

  vf->offsets[0]=0;
  vf->serialnos[0]=serialno;
  vf->dataoffsets[0]=dataoffset;
  vf->pcmlengths[0]=pcmoffset;
  vf->pcmlengths[1]-=pcmoffset;
Monty's avatar
   
Monty committed
649

650
  return(ov_raw_seek(vf,dataoffset));
Monty's avatar
   
Monty committed
651
}
Monty's avatar
   
Monty committed
652

653
/* clear out the current logical bitstream decoder */
Monty's avatar
   
Monty committed
654
655
656
static void _decode_clear(OggVorbis_File *vf){
  vorbis_dsp_clear(&vf->vd);
  vorbis_block_clear(&vf->vb);
Monty's avatar
   
Monty committed
657
  vf->ready_state=OPENED;
Monty's avatar
   
Monty committed
658
659
660
661
662
663
}

/* fetch and process a packet.  Handles the case where we're at a
   bitstream boundary and dumps the decoding machine.  If the decoding
   machine is unloaded, it loads it.  It also keeps pcm_offset up to
   date (seek and read both use this.  seek uses a special hack with
664
   readp).
Monty's avatar
   
Monty committed
665

Monty's avatar
   
Monty committed
666
667
   return: <0) error, OV_HOLE (lost packet) or OV_EOF
            0) need more data (only if readp==0)
668
            1) got a packet
Monty's avatar
   
Monty committed
669
670
*/

Monty's avatar
   
Monty committed
671
static int _fetch_and_process_packet(OggVorbis_File *vf,
672
673
674
                                     ogg_packet *op_in,
                                     int readp,
                                     int spanp){
Monty's avatar
   
Monty committed
675
676
677
678
679
  ogg_page og;

  /* handle one packet.  Try to fetch it from current stream state */
  /* extract packets from page */
  while(1){
680

681
682
683
684
685
686
687
    if(vf->ready_state==STREAMSET){
      int ret=_make_decode_ready(vf);
      if(ret<0)return ret;
    }

    /* process a packet if we can. */

Monty's avatar
   
Monty committed
688
    if(vf->ready_state==INITSET){
689
      while(1) {
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
              ogg_packet op;
              ogg_packet *op_ptr=(op_in?op_in:&op);
        int result=ogg_stream_packetout(&vf->os,op_ptr);
        ogg_int64_t granulepos;

        op_in=NULL;
        if(result==-1)return(OV_HOLE); /* hole in the data. */
        if(result>0){
          /* got a packet.  process it */
          granulepos=op_ptr->granulepos;
          if(!vorbis_synthesis(&vf->vb,op_ptr)){ /* lazy check for lazy
                                                    header handling.  The
                                                    header packets aren't
                                                    audio, so if/when we
                                                    submit them,
                                                    vorbis_synthesis will
                                                    reject them */

            /* suck in the synthesis data and track bitrate */
            {
              int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL);
              /* for proper use of libvorbis within libvorbisfile,
Monty's avatar
   
Monty committed
712
                 oldsamples will always be zero. */
713
              if(oldsamples)return(OV_EFAULT);
714

715
716
717
718
              vorbis_synthesis_blockin(&vf->vd,&vf->vb);
              vf->samptrack+=vorbis_synthesis_pcmout(&vf->vd,NULL)-oldsamples;
              vf->bittrack+=op_ptr->bytes*8;
            }
719

720
721
722
723
            /* update the pcm offset. */
            if(granulepos!=-1 && !op_ptr->e_o_s){
              int link=(vf->seekable?vf->current_link:0);
              int i,samples;
724

725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
              /* this packet has a pcm_offset on it (the last packet
                 completed on a page carries the offset) After processing
                 (above), we know the pcm position of the *last* sample
                 ready to be returned. Find the offset of the *first*

                 As an aside, this trick is inaccurate if we begin
                 reading anew right at the last page; the end-of-stream
                 granulepos declares the last frame in the stream, and the
                 last packet of the last page may be a partial frame.
                 So, we need a previous granulepos from an in-sequence page
                 to have a reference point.  Thus the !op_ptr->e_o_s clause
                 above */

              if(vf->seekable && link>0)
                granulepos-=vf->pcmlengths[link*2];
              if(granulepos<0)granulepos=0; /* actually, this
                                               shouldn't be possible
                                               here unless the stream
                                               is very broken */

              samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
746

747
748
749
750
751
752
753
754
              granulepos-=samples;
              for(i=0;i<link;i++)
                granulepos+=vf->pcmlengths[i*2+1];
              vf->pcm_offset=granulepos;
            }
            return(1);
          }
        }
755
        else
756
          break;
Monty's avatar
   
Monty committed
757
758
759
      }
    }

Monty's avatar
   
Monty committed
760
    if(vf->ready_state>=OPENED){
Michael Smith's avatar
Michael Smith committed
761
      ogg_int64_t ret;
762
763

      while(1){
764
765
766
767
768
        /* the loop is not strictly necessary, but there's no sense in
           doing the extra checks of the larger loop for the common
           case in a multiplexed bistream where the page is simply
           part of a different logical bitstream; keep reading until
           we get one with the correct serialno */
769

770
771
772
773
774
775
776
777
        if(!readp)return(0);
        if((ret=_get_next_page(vf,&og,-1))<0){
          return(OV_EOF); /* eof. leave unitialized */
        }

        /* bitrate tracking; add the header's bytes here, the body bytes
           are done by packet above */
        vf->bittrack+=og.header_len*8;
778

779
780
        if(vf->ready_state==INITSET){
          if(vf->current_serialno!=ogg_page_serialno(&og)){
781
782

            /* two possibilities:
783
784
               1) our decoding just traversed a bitstream boundary
               2) another stream is multiplexed into this logical section */
785

786
787
788
789
            if(ogg_page_bos(&og)){
              /* boundary case */
              if(!spanp)
                return(OV_EOF);
790

791
              _decode_clear(vf);
792

793
794
795
796
797
798
799
800
801
802
803
804
              if(!vf->seekable){
                vorbis_info_clear(vf->vi);
                vorbis_comment_clear(vf->vc);
              }
              break;

            }else
              continue; /* possibility #2 */
          }
        }

        break;
Monty's avatar
   
Monty committed
805
806
807
808
      }
    }

    /* Do we need to load a new machine before submitting the page? */
809
    /* This is different in the seekable and non-seekable cases.
Monty's avatar
   
Monty committed
810
811
812
813
814
815
816
817
818
819

       In the seekable case, we already have all the header
       information loaded and cached; we just initialize the machine
       with it and continue on our merry way.

       In the non-seekable (streaming) case, we'll only be at a
       boundary if we just left the previous logical bitstream and
       we're now nominally at the header of the next bitstream
    */

820
    if(vf->ready_state!=INITSET){
Monty's avatar
   
Monty committed
821
      int link;
Monty's avatar
   
Monty committed
822
823

      if(vf->ready_state<STREAMSET){
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
        if(vf->seekable){
          long serialno = ogg_page_serialno(&og);

          /* match the serialno to bitstream section.  We use this rather than
             offset positions to avoid problems near logical bitstream
             boundaries */

          for(link=0;link<vf->links;link++)
            if(vf->serialnos[link]==serialno)break;

          if(link==vf->links) continue; /* not the desired Vorbis
                                           bitstream section; keep
                                           trying */

          vf->current_serialno=serialno;
          vf->current_link=link;
840

841
842
          ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
          vf->ready_state=STREAMSET;
843

844
845
846
        }else{
          /* we're streaming */
          /* fetch the three header packets, build the info struct */
847

848
849
850
851
852
853
          int ret=_fetch_headers(vf,vf->vi,vf->vc,NULL,NULL,&og);
          if(ret)return(ret);
          vf->current_serialno=vf->os.serialno;
          vf->current_link++;
          link=0;
        }
Monty's avatar
   
Monty committed
854
855
      }
    }
856
857
858

    /* the buffered page is the data we want, and we're ready for it;
       add it to the stream state */
Monty's avatar
   
Monty committed
859
    ogg_stream_pagein(&vf->os,&og);
860

Monty's avatar
   
Monty committed
861
862
863
  }
}

Monty's avatar
   
Monty committed
864
865
/* if, eg, 64 bit stdio is configured by default, this will build with
   fseek64 */
Monty's avatar
   
Monty committed
866
867
static int _fseek64_wrap(FILE *f,ogg_int64_t off,int whence){
  if(f==NULL)return(-1);
Monty's avatar
   
Monty committed
868
  return fseek(f,off,whence);
Monty's avatar
   
Monty committed
869
870
871
}

static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
872
                     long ibytes, ov_callbacks callbacks){
873
  int offsettest=((f && callbacks.seek_func)?callbacks.seek_func(f,0,SEEK_CUR):-1);
874
875
  long *serialno_list=NULL;
  int serialno_list_size=0;
Monty's avatar
   
Monty committed
876
  int ret;
877

878
  memset(vf,0,sizeof(*vf));
Monty's avatar
   
Monty committed
879
880
881
882
883
884
885
886
  vf->datasource=f;
  vf->callbacks = callbacks;

  /* init the framing state */
  ogg_sync_init(&vf->oy);

  /* perhaps some data was previously read into a buffer for testing
     against other stream types.  Allow initialization from this
887
888
     previously read data (especially as we may be reading from a
     non-seekable stream) */
Monty's avatar
   
Monty committed
889
890
891
892
893
894
895
  if(initial){
    char *buffer=ogg_sync_buffer(&vf->oy,ibytes);
    memcpy(buffer,initial,ibytes);
    ogg_sync_wrote(&vf->oy,ibytes);
  }

  /* can we seek? Stevens suggests the seek test was portable */
Monty's avatar
   
Monty committed
896
  if(offsettest!=-1)vf->seekable=1;
Monty's avatar
   
Monty committed
897
898
899
900

  /* No seeking yet; Set up a 'single' (current) logical bitstream
     entry for partial open */
  vf->links=1;
901
902
  vf->vi=_ogg_calloc(vf->links,sizeof(*vf->vi));
  vf->vc=_ogg_calloc(vf->links,sizeof(*vf->vc));
Monty's avatar
   
Monty committed
903
904
  ogg_stream_init(&vf->os,-1); /* fill in the serialno later */

905
906
  /* Fetch all BOS pages, store the vorbis header and all seen serial
     numbers, load subsequent vorbis setup headers */
907
  if((ret=_fetch_headers(vf,vf->vi,vf->vc,&serialno_list,&serialno_list_size,NULL))<0){
Monty's avatar
   
Monty committed
908
909
    vf->datasource=NULL;
    ov_clear(vf);
910
911
912
913
914
915
916
917
  }else{
    /* serial number list for first link needs to be held somewhere
       for second stage of seekable stream open; this saves having to
       seek/reread first link's serialnumber data then. */
    vf->serialnos=_ogg_calloc(serialno_list_size+2,sizeof(*vf->serialnos));
    vf->serialnos[0]=vf->current_serialno;
    vf->serialnos[1]=serialno_list_size;
    memcpy(vf->serialnos+2,serialno_list,serialno_list_size*sizeof(*vf->serialnos));
918

919
920
921
922
    vf->offsets=_ogg_calloc(1,sizeof(*vf->offsets));
    vf->dataoffsets=_ogg_calloc(1,sizeof(*vf->dataoffsets));
    vf->offsets[0]=0;
    vf->dataoffsets[0]=vf->offset;
923
    vf->current_serialno=vf->os.serialno;
924

Monty's avatar
   
Monty committed
925
    vf->ready_state=PARTOPEN;
926
927
  }
  if(serialno_list)_ogg_free(serialno_list);
Monty's avatar
   
Monty committed
928
929
930
931
  return(ret);
}

static int _ov_open2(OggVorbis_File *vf){
Monty's avatar
   
Monty committed
932
933
  if(vf->ready_state != PARTOPEN) return OV_EINVAL;
  vf->ready_state=OPENED;
Monty's avatar
   
Monty committed
934
935
936
937
938
939
940
  if(vf->seekable){
    int ret=_open_seekable2(vf);
    if(ret){
      vf->datasource=NULL;
      ov_clear(vf);
    }
    return(ret);
Monty's avatar
   
Monty committed
941
942
943
  }else
    vf->ready_state=STREAMSET;

Monty's avatar
   
Monty committed
944
945
946
947
  return 0;
}


Monty's avatar
   
Monty committed
948
949
950
951
952
953
/* clear out the OggVorbis_File struct */
int ov_clear(OggVorbis_File *vf){
  if(vf){
    vorbis_block_clear(&vf->vb);
    vorbis_dsp_clear(&vf->vd);
    ogg_stream_clear(&vf->os);
954

Monty's avatar
   
Monty committed
955
956
    if(vf->vi && vf->links){
      int i;
Monty's avatar
   
Monty committed
957
      for(i=0;i<vf->links;i++){
958
959
        vorbis_info_clear(vf->vi+i);
        vorbis_comment_clear(vf->vc+i);
Monty's avatar
   
Monty committed
960
      }
Monty's avatar
   
Monty committed
961
962
      _ogg_free(vf->vi);
      _ogg_free(vf->vc);
Monty's avatar
   
Monty committed
963
    }
Monty's avatar
   
Monty committed
964
965
966
967
    if(vf->dataoffsets)_ogg_free(vf->dataoffsets);
    if(vf->pcmlengths)_ogg_free(vf->pcmlengths);
    if(vf->serialnos)_ogg_free(vf->serialnos);
    if(vf->offsets)_ogg_free(vf->offsets);
Monty's avatar
   
Monty committed
968
    ogg_sync_clear(&vf->oy);
969
970
    if(vf->datasource && vf->callbacks.close_func)
      (vf->callbacks.close_func)(vf->datasource);
971
    memset(vf,0,sizeof(*vf));
Monty's avatar
   
Monty committed
972
  }
Monty's avatar
   
Monty committed
973
#ifdef DEBUG_LEAKS
Monty's avatar
   
Monty committed
974
  _VDBG_dump();
Monty's avatar
   
Monty committed
975
#endif
Monty's avatar
   
Monty committed
976
  return(0);
Monty's avatar
   
Monty committed
977
}
Monty's avatar
 
Monty committed
978

Monty's avatar
   
Monty committed
979
980
/* inspects the OggVorbis file and finds/documents all the logical
   bitstreams contained in it.  Tries to be tolerant of logical
981
   bitstream sections that are truncated/woogie.
Monty's avatar
   
Monty committed
982
983
984
985
986

   return: -1) error
            0) OK
*/

Monty's avatar
   
Monty committed
987
988
989
990
991
992
993
int ov_open_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes,
    ov_callbacks callbacks){
  int ret=_ov_open1(f,vf,initial,ibytes,callbacks);
  if(ret)return ret;
  return _ov_open2(vf);
}

Monty's avatar
   
Monty committed
994
int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){
Michael Smith's avatar
   
Michael Smith committed
995
  ov_callbacks callbacks = {
Michael Smith's avatar
   
Michael Smith committed
996
    (size_t (*)(void *, size_t, size_t, void *))  fread,
Monty's avatar
   
Monty committed
997
    (int (*)(void *, ogg_int64_t, int))              _fseek64_wrap,
Michael Smith's avatar
   
Michael Smith committed
998
999
1000
    (int (*)(void *))                             fclose,
    (long (*)(void *))                            ftell
  };
For faster browsing, not all history is shown. View entire blame