vorbisfile.c 60.4 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-2002             *
Monty's avatar
   
Monty committed
9
 * by the XIPHOPHORUS Company 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
25
26
#include "vorbis/codec.h"
#include "vorbis/vorbisfile.h"

Monty's avatar
   
Monty committed
27
#include "os.h"
Monty's avatar
   
Monty committed
28
#include "misc.h"
Monty's avatar
 
Monty committed
29
30
31
32
33
34
35

/* 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
36
37
38
39
   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
40
41

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

/* 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
50
   picking some portion of the stream roughly in the desired area if
Ralph Giles's avatar
Ralph Giles committed
51
   we only want coarse navigation through the stream. */
Monty's avatar
   
Monty committed
52

Monty's avatar
   
Monty committed
53
54
55
56
57
58
/*************************************************************************
 * Many, many internal helpers.  The intention is not to be confusing; 
 * rampant duplication and monolithic function implementation would be 
 * 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
59
60
/* read a little more data from the file/pipe into the ogg_sync framer
*/
61
62
#define CHUNKSIZE 65536

Monty's avatar
   
Monty committed
63
static long _get_data(OggVorbis_File *vf){
Monty's avatar
   
Monty committed
64
65
66
67
68
69
70
71
72
  errno=0;
  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
73
74
75
}

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

/* 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
	      n) search for a new page beginning for n bytes

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

Monty's avatar
   
Monty committed
102
103
static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og,
				  ogg_int64_t boundary){
Monty's avatar
   
Monty committed
104
105
106
107
  if(boundary>0)boundary+=vf->offset;
  while(1){
    long more;

Monty's avatar
   
Monty committed
108
    if(boundary>0 && vf->offset>=boundary)return(OV_FALSE);
Monty's avatar
   
Monty committed
109
110
111
112
113
114
115
116
    more=ogg_sync_pageseek(&vf->oy,og);
    
    if(more<0){
      /* skipped n bytes */
      vf->offset-=more;
    }else{
      if(more==0){
	/* send more paramedics */
Monty's avatar
   
Monty committed
117
118
119
120
121
122
	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
123
124
125
      }else{
	/* got a page.  Return the offset at the page beginning,
           advance the internal offset past the page end */
Monty's avatar
   
Monty committed
126
	ogg_int64_t ret=vf->offset;
Monty's avatar
   
Monty committed
127
128
129
130
131
132
133
134
135
136
137
138
	vf->offset+=more;
	return(ret);
	
      }
    }
  }
}

/* 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
139
/* returns offset or OV_EREAD, OV_FAULT */
Monty's avatar
   
Monty committed
140
141
142
143
144
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
145
146
147

  while(offset==-1){
    begin-=CHUNKSIZE;
148
149
    if(begin<0)
      begin=0;
150
151
152
153

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

Monty's avatar
   
Monty committed
154
155
    while(vf->offset<end){
      ret=_get_next_page(vf,og,end-vf->offset);
Monty's avatar
   
Monty committed
156
157
      if(ret==OV_EREAD)return(OV_EREAD);
      if(ret<0){
Monty's avatar
   
Monty committed
158
159
160
161
162
163
164
165
	break;
      }else{
	offset=ret;
      }
    }
  }

  /* we have the offset.  Actually snork and hold the page now */
166
167
168
  ret=_seek_helper(vf,offset);
  if(ret)return(ret);

Monty's avatar
   
Monty committed
169
  ret=_get_next_page(vf,og,CHUNKSIZE);
Monty's avatar
   
Monty committed
170
  if(ret<0)
Monty's avatar
   
Monty committed
171
    /* this shouldn't be possible */
Monty's avatar
   
Monty committed
172
173
    return(OV_EFAULT);

Monty's avatar
   
Monty committed
174
175
176
  return(offset);
}

177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
static void _add_serialno(ogg_page *og,long **serialno_list, int *n){
  long s = ogg_page_serialno(og);
  (*n)++;

  if(serialno_list){
    *serialno_list = _ogg_realloc(*serialno_list, sizeof(*serialno_list)*(*n));
  }else{
    *serialno_list = _ogg_malloc(sizeof(**serialno_list));
  }
  
  (*serialno_list)[(*n)-1] = s;
}

/* returns nonzero if found */
static int _lookup_serialno(ogg_page *og, long *serialno_list, int n){
  long s = ogg_page_serialno(og);

  if(serialno_list){
    while(n--){
      if(*serialno_list == s) return 1;
      serialno_list++;
    }
  }
  return 0;
}

/* start parsing pages at current offset, remembering all serial
   numbers.  Stop logging at first non-bos page */
static int _get_serialnos(OggVorbis_File *vf, long **s, int *n){
  ogg_page og;

  *s=NULL;
  *n=0;

  while(1){
    ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE);
    if(llret==OV_EOF)return(0);
    if(llret<0)return(llret);
    if(!ogg_page_bos(&og)) return 0;

    /* look for duplicate serialnos; add this one if unique */
    if(_lookup_serialno(&og,*s,*n)){
      if(*s)_ogg_free(*s);
      *s=0;
      *n=0;
      return(OV_EBADHEADER);
    }

    _add_serialno(&og,s,n);
  }
}

Monty's avatar
   
Monty committed
229
230
231
232
/* 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 */
Monty's avatar
   
Monty committed
233
static int _bisect_forward_serialno(OggVorbis_File *vf,
Monty's avatar
   
Monty committed
234
235
236
				    ogg_int64_t begin,
				    ogg_int64_t searched,
				    ogg_int64_t end,
237
238
				    long *currentno_list,
				    int  currentnos,
Monty's avatar
   
Monty committed
239
				    long m){
Monty's avatar
   
Monty committed
240
241
  ogg_int64_t endsearched=end;
  ogg_int64_t next=end;
Monty's avatar
   
Monty committed
242
  ogg_page og;
Monty's avatar
   
Monty committed
243
  ogg_int64_t ret;
Monty's avatar
   
Monty committed
244
  
Monty's avatar
   
Monty committed
245
246
247
  /* the below guards against garbage seperating the last and
     first pages of two links. */
  while(searched<endsearched){
Monty's avatar
   
Monty committed
248
    ogg_int64_t bisect;
Monty's avatar
   
Monty committed
249
250
251
252
253
254
255
    
    if(endsearched-searched<CHUNKSIZE){
      bisect=searched;
    }else{
      bisect=(searched+endsearched)/2;
    }
    
256
257
258
    ret=_seek_helper(vf,bisect);
    if(ret)return(ret);

Monty's avatar
   
Monty committed
259
    ret=_get_next_page(vf,&og,-1);
Monty's avatar
   
Monty committed
260
    if(ret==OV_EREAD)return(OV_EREAD);
261
    if(ret<0 || !_lookup_serialno(&og,currentno_list,currentnos)){
Monty's avatar
   
Monty committed
262
263
264
265
266
267
      endsearched=bisect;
      if(ret>=0)next=ret;
    }else{
      searched=ret+og.header_len+og.body_len;
    }
  }
Monty's avatar
   
Monty committed
268

269
270
271
  {
    long *next_serialno_list=NULL;
    int next_serialnos=0;
272

273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
    ret=_seek_helper(vf,next);
    if(ret)return(ret);
    ret=_get_serialnos(vf,&next_serialno_list,&next_serialnos);
    if(ret)return(ret);
    
    if(searched>=end || next_serialnos==0){
      vf->links=m+1;
      vf->offsets=_ogg_malloc((vf->links+1)*sizeof(*vf->offsets));
      vf->offsets[m+1]=searched;
    }else{
      ret=_bisect_forward_serialno(vf,next,vf->offset,
				   end,next_serialno_list,next_serialnos,m+1);
      if(ret)return(ret);
    }
    
    if(next_serialno_list)_ogg_free(next_serialno_list);
Monty's avatar
   
Monty committed
289
290
  }
  vf->offsets[m]=begin;
Monty's avatar
   
Monty committed
291
  return(0);
Monty's avatar
   
Monty committed
292
}
Monty's avatar
   
Monty committed
293

Monty's avatar
   
Monty committed
294
295
/* uses the local ogg_stream storage in vf; this is important for
   non-streaming input sources */
Monty's avatar
   
Monty committed
296
static int _fetch_headers(OggVorbis_File *vf,vorbis_info *vi,vorbis_comment *vc,
Monty's avatar
   
Monty committed
297
			  long *serialno,ogg_page *og_ptr){
Monty's avatar
   
Monty committed
298
299
  ogg_page og;
  ogg_packet op;
Monty's avatar
   
Monty committed
300
  int i,ret;
301
302
  int allbos=0;

Monty's avatar
   
Monty committed
303
  if(!og_ptr){
Monty's avatar
   
Monty committed
304
305
    ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE);
    if(llret==OV_EREAD)return(OV_EREAD);
306
    if(llret<0)return(OV_ENOTVORBIS);
Monty's avatar
   
Monty committed
307
308
309
    og_ptr=&og;
  }

Monty's avatar
   
Monty committed
310
  vorbis_info_init(vi);
Monty's avatar
   
Monty committed
311
  vorbis_comment_init(vc);
312
313
314
315

  /* extract the first set of vorbis headers we see in the headerset */

  while(1){
Monty's avatar
   
Monty committed
316
  
317
318
319
320
321
322
323
324
325
    /* if we're past the ID headers, we won't be finding a Vorbis
       stream in this link */
    if(!ogg_page_bos(og_ptr)){
      ret = OV_ENOTVORBIS;
      goto bail_header;
    }

    /* prospective stream setup; we need a stream to get packets */
    ogg_stream_reset_serialno(&vf->os,ogg_page_serialno(og_ptr));
Monty's avatar
   
Monty committed
326
    ogg_stream_pagein(&vf->os,og_ptr);
327

328
329
    if(ogg_stream_packetout(&vf->os,&op) > 0 &&
       vorbis_synthesis_idheader(&op)){
330
331
332
333
334
335
336

      /* continue Vorbis header load; past this point, any error will
	 render this link useless (we won't continue looking for more
	 Vorbis streams */
      if(serialno)*serialno=vf->os.serialno;
      vf->ready_state=STREAMSET;
      if((ret=vorbis_synthesis_headerin(vi,vc,&op)))
Monty's avatar
   
Monty committed
337
	goto bail_header;
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380

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

	  int result=ogg_stream_packetout(&vf->os,&op);
	  if(result==0)break;
	  if(result==-1){
	    ret=OV_EBADHEADER;
	    goto bail_header;
	  }
	
	  if((ret=vorbis_synthesis_headerin(vi,vc,&op)))
	    goto bail_header;

	  i++;
	}

	while(i<2){
	  if(_get_next_page(vf,og_ptr,CHUNKSIZE)<0){
	    ret=OV_EBADHEADER;
	    goto bail_header;
	  }

	  /* 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;
	  }

	  /* 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;
	  }

	  /* otherwise, keep looking */
	}
Monty's avatar
   
Monty committed
381
      }
382
383

      return 0; 
Monty's avatar
   
Monty committed
384
    }
385
386
387
388
389
390
391

    /* this wasn't vorbis, get next page, try again */
    {
      ogg_int64_t llret=_get_next_page(vf,og_ptr,CHUNKSIZE);
      if(llret==OV_EREAD)return(OV_EREAD);
      if(llret<0)return(OV_ENOTVORBIS);
    } 
Monty's avatar
   
Monty committed
392
  }
Monty's avatar
   
Monty committed
393

Monty's avatar
   
Monty committed
394
395
 bail_header:
  vorbis_info_clear(vi);
Monty's avatar
   
Monty committed
396
  vorbis_comment_clear(vc);
Monty's avatar
   
Monty committed
397
398
  vf->ready_state=OPENED;

Monty's avatar
   
Monty committed
399
  return ret;
Monty's avatar
   
Monty committed
400
}
Monty's avatar
   
Monty committed
401

Monty's avatar
   
Monty committed
402
403
404
405
/* last step of the OggVorbis_File initialization; get all the
   vorbis_info structs and PCM positions.  Only called by the seekable
   initialization (local stream storage is hacked slightly; pay
   attention to how that's done) */
Monty's avatar
   
Monty committed
406
407
408
409
410

/* this is void and does not propogate errors up because we want to be
   able to open and use damaged bitstreams as well as we can.  Just
   watch out for missing information for links in the OggVorbis_File
   struct */
Monty's avatar
   
Monty committed
411
static void _prefetch_all_headers(OggVorbis_File *vf, ogg_int64_t dataoffset){
Monty's avatar
   
Monty committed
412
  ogg_page og;
Monty's avatar
   
Monty committed
413
414
  int i;
  ogg_int64_t ret;
415

416
417
  vf->vi=_ogg_realloc(vf->vi,vf->links*sizeof(*vf->vi));
  vf->vc=_ogg_realloc(vf->vc,vf->links*sizeof(*vf->vc));
418
  vf->serialnos=_ogg_malloc(vf->links*sizeof(*vf->serialnos));
419
  vf->dataoffsets=_ogg_malloc(vf->links*sizeof(*vf->dataoffsets));
Monty's avatar
   
Monty committed
420
  vf->pcmlengths=_ogg_malloc(vf->links*2*sizeof(*vf->pcmlengths));
Monty's avatar
   
Monty committed
421
422
  
  for(i=0;i<vf->links;i++){
Monty's avatar
   
Monty committed
423
424
    if(i==0){
      /* we already grabbed the initial header earlier.  Just set the offset */
425
      vf->serialnos[i]=vf->current_serialno;
Monty's avatar
   
Monty committed
426
      vf->dataoffsets[i]=dataoffset;
427
428
429
      ret=_seek_helper(vf,dataoffset);
      if(ret)
	vf->dataoffsets[i]=-1;
Monty's avatar
   
Monty committed
430

Monty's avatar
   
Monty committed
431
    }else{
Monty's avatar
   
Monty committed
432

Monty's avatar
   
Monty committed
433
      /* seek to the location of the initial header */
Monty's avatar
   
Monty committed
434

435
436
437
      ret=_seek_helper(vf,vf->offsets[i]);
      if(ret){
	vf->dataoffsets[i]=-1;
Monty's avatar
   
Monty committed
438
      }else{
439
	if(_fetch_headers(vf,vf->vi+i,vf->vc+i,vf->serialnos+i,NULL)<0){
440
441
442
443
	  vf->dataoffsets[i]=-1;
	}else{
	  vf->dataoffsets[i]=vf->offset;
	}
Monty's avatar
   
Monty committed
444
      }
Monty's avatar
   
Monty committed
445
    }
Monty's avatar
   
Monty committed
446

Monty's avatar
   
Monty committed
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
    /* fetch beginning PCM offset */

    if(vf->dataoffsets[i]!=-1){
      ogg_int64_t accumulated=0;
      long        lastblock=-1;
      int         result;

      ogg_stream_reset_serialno(&vf->os,vf->serialnos[i]);

      while(1){
	ogg_packet op;

	ret=_get_next_page(vf,&og,-1);
	if(ret<0)
	  /* this should not be possible unless the file is
             truncated/mangled */
	  break;
       
465
466
	if(ogg_page_bos(&og)) break;

Monty's avatar
   
Monty committed
467
	if(ogg_page_serialno(&og)!=vf->serialnos[i])
468
	  continue;
Monty's avatar
   
Monty committed
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
	
	/* 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 */
	    long thisblock=vorbis_packet_blocksize(vf->vi+i,&op);
	    if(lastblock!=-1)
	      accumulated+=(lastblock+thisblock)>>2;
	    lastblock=thisblock;
	  }
	}

	if(ogg_page_granulepos(&og)!=-1){
	  /* pcm offset of last packet on the first audio page */
	  accumulated= ogg_page_granulepos(&og)-accumulated;
	  break;
	}
      }

      /* 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;

      vf->pcmlengths[i*2]=accumulated;
    }

    /* get the PCM length of this link. To do this,
Monty's avatar
   
Monty committed
496
497
       get the last page of the stream */
    {
Monty's avatar
   
Monty committed
498
      ogg_int64_t end=vf->offsets[i+1];
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
      ret=_seek_helper(vf,end);
      if(ret){
	/* this should not be possible */
	vorbis_info_clear(vf->vi+i);
	vorbis_comment_clear(vf->vc+i);
      }else{
	
	while(1){
	  ret=_get_prev_page(vf,&og);
	  if(ret<0){
	    /* this should not be possible */
	    vorbis_info_clear(vf->vi+i);
	    vorbis_comment_clear(vf->vc+i);
	    break;
	  }
514
515
516
	  if(ogg_page_serialno(&og)!=vf->serialnos[i])
	    continue;

517
518
519
520
521
	  if(ogg_page_granulepos(&og)!=-1){
	    vf->pcmlengths[i*2+1]=ogg_page_granulepos(&og)-vf->pcmlengths[i*2];
	    break;
	  }
	  vf->offset=ret;
Monty's avatar
   
Monty committed
522
523
524
525
	}
      }
    }
  }
Monty's avatar
   
Monty committed
526
527
}

Monty's avatar
   
Monty committed
528
static int _make_decode_ready(OggVorbis_File *vf){
Monty's avatar
   
Monty committed
529
530
  if(vf->ready_state>STREAMSET)return 0;
  if(vf->ready_state<STREAMSET)return OV_EFAULT;
Monty's avatar
   
Monty committed
531
  if(vf->seekable){
Monty's avatar
   
Monty committed
532
533
    if(vorbis_synthesis_init(&vf->vd,vf->vi+vf->current_link))
      return OV_EBADLINK;
Monty's avatar
   
Monty committed
534
  }else{
Monty's avatar
   
Monty committed
535
536
    if(vorbis_synthesis_init(&vf->vd,vf->vi))
      return OV_EBADLINK;
Monty's avatar
   
Monty committed
537
  }    
Monty's avatar
   
Monty committed
538
  vorbis_block_init(&vf->vd,&vf->vb);
Monty's avatar
   
Monty committed
539
  vf->ready_state=INITSET;
Monty's avatar
   
Monty committed
540
541
  vf->bittrack=0.f;
  vf->samptrack=0.f;
Monty's avatar
   
Monty committed
542
  return 0;
Monty's avatar
   
Monty committed
543
544
}

Monty's avatar
   
Monty committed
545
static int _open_seekable2(OggVorbis_File *vf){
546
547
548
549
  ogg_int64_t dataoffset=vf->offset,end;
  long *serialno_list=NULL;
  int serialnos=0;
  int ret;
550
  ogg_page og;
Monty's avatar
   
Monty committed
551
552
553

  /* we're partially open and have a first link header state in
     storage in vf */
Monty's avatar
   
Monty committed
554
  /* we can seek, so set out learning all about this file */
Michael Smith's avatar
   
Michael Smith committed
555
556
  (vf->callbacks.seek_func)(vf->datasource,0,SEEK_END);
  vf->offset=vf->end=(vf->callbacks.tell_func)(vf->datasource);
557
558
559
560

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

561
562
563
564
565
  /* We get the offset for the last page of the physical bitstream.
     Most OggVorbis files will contain a single logical bitstream */
  end=_get_prev_page(vf,&og);
  if(end<0)return(end);

566
  /* back to beginning, learn all serialnos of first link */
567
  ret=_seek_helper(vf,0);
568
569
570
  if(ret)return(ret);
  ret=_get_serialnos(vf,&serialno_list,&serialnos);
  if(ret)return(ret);
Monty's avatar
   
Monty committed
571

572
573
574
  /* now determine bitstream structure recursively */
  if(_bisect_forward_serialno(vf,0,0,end+1,serialno_list,serialnos,0)<0)return(OV_EREAD);  
  if(serialno_list)_ogg_free(serialno_list);
Monty's avatar
   
Monty committed
575

Monty's avatar
   
Monty committed
576
577
  /* the initial header memory is referenced by vf after; don't free it */
  _prefetch_all_headers(vf,dataoffset);
Monty's avatar
   
Monty committed
578
  return(ov_raw_seek(vf,0));
Monty's avatar
   
Monty committed
579
}
Monty's avatar
   
Monty committed
580
581
582
583
584

/* clear out the current logical bitstream decoder */ 
static void _decode_clear(OggVorbis_File *vf){
  vorbis_dsp_clear(&vf->vd);
  vorbis_block_clear(&vf->vb);
Monty's avatar
   
Monty committed
585
  vf->ready_state=OPENED;
Monty's avatar
   
Monty committed
586
587
588
589
590
591
592
593
}

/* 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
   readp). 

Monty's avatar
   
Monty committed
594
595
   return: <0) error, OV_HOLE (lost packet) or OV_EOF
            0) need more data (only if readp==0)
Monty's avatar
   
Monty committed
596
597
598
	    1) got a packet 
*/

Monty's avatar
   
Monty committed
599
600
static int _fetch_and_process_packet(OggVorbis_File *vf,
				     ogg_packet *op_in,
Monty's avatar
   
Monty committed
601
602
				     int readp,
				     int spanp){
Monty's avatar
   
Monty committed
603
604
605
606
607
608
609
610
  ogg_page og;

  /* handle one packet.  Try to fetch it from current stream state */
  /* extract packets from page */
  while(1){
    
    /* process a packet if we can.  If the machine isn't loaded,
       neither is a page */
Monty's avatar
   
Monty committed
611
    if(vf->ready_state==INITSET){
612
613
      while(1) {
      	ogg_packet op;
Monty's avatar
   
Monty committed
614
615
      	ogg_packet *op_ptr=(op_in?op_in:&op);
	int result=ogg_stream_packetout(&vf->os,op_ptr);
616
617
	ogg_int64_t granulepos;

Monty's avatar
   
Monty committed
618
	op_in=NULL;
619
620
621
	if(result==-1)return(OV_HOLE); /* hole in the data. */
	if(result>0){
	  /* got a packet.  process it */
Monty's avatar
   
Monty committed
622
623
624
625
626
627
628
629
	  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 */
630
631
632
633

	    /* suck in the synthesis data and track bitrate */
	    {
	      int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL);
Monty's avatar
   
Monty committed
634
635
636
637
	      /* for proper use of libvorbis within libvorbisfile,
                 oldsamples will always be zero. */
	      if(oldsamples)return(OV_EFAULT);
	      
638
639
	      vorbis_synthesis_blockin(&vf->vd,&vf->vb);
	      vf->samptrack+=vorbis_synthesis_pcmout(&vf->vd,NULL)-oldsamples;
Monty's avatar
   
Monty committed
640
	      vf->bittrack+=op_ptr->bytes*8;
641
	    }
Monty's avatar
   
Monty committed
642
	  
643
	    /* update the pcm offset. */
Monty's avatar
   
Monty committed
644
	    if(granulepos!=-1 && !op_ptr->e_o_s){
645
646
	      int link=(vf->seekable?vf->current_link:0);
	      int i,samples;
Monty's avatar
   
Monty committed
647
	    
648
649
650
651
652
653
654
655
656
657
	      /* 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
Monty's avatar
   
Monty committed
658
	         to have a reference point.  Thus the !op_ptr->e_o_s clause
659
	         above */
Monty's avatar
   
Monty committed
660
661
662

	      if(vf->seekable && link>0)
		granulepos-=vf->pcmlengths[link*2];
Monty's avatar
   
Monty committed
663
664
665
666
667
	      if(granulepos<0)granulepos=0; /* actually, this
					       shouldn't be possible
					       here unless the stream
					       is very broken */

668
	      samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
Monty's avatar
   
Monty committed
669
	    
670
671
	      granulepos-=samples;
	      for(i=0;i<link;i++)
Monty's avatar
   
Monty committed
672
	        granulepos+=vf->pcmlengths[i*2+1];
673
674
675
	      vf->pcm_offset=granulepos;
	    }
	    return(1);
Monty's avatar
   
Monty committed
676
	  }
Monty's avatar
   
Monty committed
677
	}
678
679
	else 
	  break;
Monty's avatar
   
Monty committed
680
681
682
      }
    }

Monty's avatar
   
Monty committed
683
    if(vf->ready_state>=OPENED){
Michael Smith's avatar
Michael Smith committed
684
      ogg_int64_t ret;
685
686
687
688
689
690
691
692
693
694
695
696
      
      while(1){ 
	/* 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 */
	
	if(!readp)return(0);
	if((ret=_get_next_page(vf,&og,-1))<0){
	  return(OV_EOF); /* eof. leave unitialized */
	}
Monty's avatar
   
Monty committed
697
698
699

	/* bitrate tracking; add the header's bytes here, the body bytes
	   are done by packet above */
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
	vf->bittrack+=og.header_len*8;
	
	if(vf->ready_state==INITSET){
	  if(vf->current_serialno!=ogg_page_serialno(&og)){
	    
	    /* two possibilities: 
	       1) our decoding just traversed a bitstream boundary
	       2) another stream is multiplexed into this logical section? */
	    
	    if(ogg_page_bos(&og)){
	      /* boundary case */
	      if(!spanp)
		return(OV_EOF);
	      
	      _decode_clear(vf);
	      
	      if(!vf->seekable){
		vorbis_info_clear(vf->vi);
		vorbis_comment_clear(vf->vc);
	      }
	      break;

	    }else
	      continue; /* possibility #2 */
Monty's avatar
   
Monty committed
724
725
	  }
	}
726
727

	break;
Monty's avatar
   
Monty committed
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
      }
    }

    /* Do we need to load a new machine before submitting the page? */
    /* This is different in the seekable and non-seekable cases.  

       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
    */

Monty's avatar
   
Monty committed
743
    if(vf->ready_state!=INITSET){ 
Monty's avatar
   
Monty committed
744
      int link;
Monty's avatar
   
Monty committed
745
746
747

      if(vf->ready_state<STREAMSET){
	if(vf->seekable){
748
749
	  long serialno = ogg_page_serialno(&og);

Monty's avatar
   
Monty committed
750
751
752
	  /* match the serialno to bitstream section.  We use this rather than
	     offset positions to avoid problems near logical bitstream
	     boundaries */
753

Monty's avatar
   
Monty committed
754
	  for(link=0;link<vf->links;link++)
755
756
757
758
759
760
761
	    if(vf->serialnos[link]==serialno)break;

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

	  vf->current_serialno=serialno;
Monty's avatar
   
Monty committed
762
763
	  vf->current_link=link;
	  
Monty's avatar
   
Monty committed
764
	  ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
Monty's avatar
   
Monty committed
765
766
767
768
769
770
	  vf->ready_state=STREAMSET;
	  
	}else{
	  /* we're streaming */
	  /* fetch the three header packets, build the info struct */
	  
Monty's avatar
   
Monty committed
771
772
	  int ret=_fetch_headers(vf,vf->vi,vf->vc,&vf->current_serialno,&og);
	  if(ret)return(ret);
Monty's avatar
   
Monty committed
773
774
775
	  vf->current_link++;
	  link=0;
	}
Monty's avatar
   
Monty committed
776
777
      }
      
Monty's avatar
   
Monty committed
778
779
780
781
      {
	int ret=_make_decode_ready(vf);
	if(ret<0)return ret;
      }
Monty's avatar
   
Monty committed
782
    }
783
784
785

    /* 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
786
    ogg_stream_pagein(&vf->os,&og);
787

Monty's avatar
   
Monty committed
788
789
790
  }
}

Monty's avatar
   
Monty committed
791
792
/* if, eg, 64 bit stdio is configured by default, this will build with
   fseek64 */
Monty's avatar
   
Monty committed
793
794
static int _fseek64_wrap(FILE *f,ogg_int64_t off,int whence){
  if(f==NULL)return(-1);
Monty's avatar
   
Monty committed
795
  return fseek(f,off,whence);
Monty's avatar
   
Monty committed
796
797
798
799
}

static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
		     long ibytes, ov_callbacks callbacks){
Monty's avatar
   
Monty committed
800
  int offsettest=(f?callbacks.seek_func(f,0,SEEK_CUR):-1);
Monty's avatar
   
Monty committed
801
  int ret;
802
  
803
  memset(vf,0,sizeof(*vf));
Monty's avatar
   
Monty committed
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
  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
     previously read data (as we may be reading from a non-seekable
     stream) */
  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
821
  if(offsettest!=-1)vf->seekable=1;
Monty's avatar
   
Monty committed
822
823
824
825

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

Monty's avatar
   
Monty committed
830
831
832
833
  /* Try to fetch the headers, maintaining all the storage */
  if((ret=_fetch_headers(vf,vf->vi,vf->vc,&vf->current_serialno,NULL))<0){
    vf->datasource=NULL;
    ov_clear(vf);
Monty's avatar
   
Monty committed
834
  }else 
Monty's avatar
   
Monty committed
835
836
837
838
839
    vf->ready_state=PARTOPEN;
  return(ret);
}

static int _ov_open2(OggVorbis_File *vf){
Monty's avatar
   
Monty committed
840
841
  if(vf->ready_state != PARTOPEN) return OV_EINVAL;
  vf->ready_state=OPENED;
Monty's avatar
   
Monty committed
842
843
844
845
846
847
848
  if(vf->seekable){
    int ret=_open_seekable2(vf);
    if(ret){
      vf->datasource=NULL;
      ov_clear(vf);
    }
    return(ret);
Monty's avatar
   
Monty committed
849
850
851
  }else
    vf->ready_state=STREAMSET;

Monty's avatar
   
Monty committed
852
853
854
855
  return 0;
}


Monty's avatar
   
Monty committed
856
857
858
859
860
861
862
863
864
/* 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);
    
    if(vf->vi && vf->links){
      int i;
Monty's avatar
   
Monty committed
865
      for(i=0;i<vf->links;i++){
Monty's avatar
   
Monty committed
866
	vorbis_info_clear(vf->vi+i);
Monty's avatar
   
Monty committed
867
868
	vorbis_comment_clear(vf->vc+i);
      }
Monty's avatar
   
Monty committed
869
870
      _ogg_free(vf->vi);
      _ogg_free(vf->vc);
Monty's avatar
   
Monty committed
871
    }
Monty's avatar
   
Monty committed
872
873
874
875
    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
876
    ogg_sync_clear(&vf->oy);
Michael Smith's avatar
   
Michael Smith committed
877
    if(vf->datasource)(vf->callbacks.close_func)(vf->datasource);
878
    memset(vf,0,sizeof(*vf));
Monty's avatar
   
Monty committed
879
  }
Monty's avatar
   
Monty committed
880
#ifdef DEBUG_LEAKS
Monty's avatar
   
Monty committed
881
  _VDBG_dump();
Monty's avatar
   
Monty committed
882
#endif
Monty's avatar
   
Monty committed
883
  return(0);
Monty's avatar
   
Monty committed
884
}
Monty's avatar
 
Monty committed
885

Monty's avatar
   
Monty committed
886
887
/* inspects the OggVorbis file and finds/documents all the logical
   bitstreams contained in it.  Tries to be tolerant of logical
Monty's avatar
   
Monty committed
888
889
890
891
892
893
   bitstream sections that are truncated/woogie. 

   return: -1) error
            0) OK
*/

Monty's avatar
   
Monty committed
894
895
896
897
898
899
900
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
901
int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){
Michael Smith's avatar
   
Michael Smith committed
902
  ov_callbacks callbacks = {
Michael Smith's avatar
   
Michael Smith committed
903
    (size_t (*)(void *, size_t, size_t, void *))  fread,
Monty's avatar
   
Monty committed
904
    (int (*)(void *, ogg_int64_t, int))              _fseek64_wrap,
Michael Smith's avatar
   
Michael Smith committed
905
906
907
    (int (*)(void *))                             fclose,
    (long (*)(void *))                            ftell
  };
Michael Smith's avatar
   
Michael Smith committed
908
909
910

  return ov_open_callbacks((void *)f, vf, initial, ibytes, callbacks);
}
Monty's avatar
   
Monty committed
911
912
913
914
915
916
917
918
919
920
921
922
923
924
 
/* cheap hack for game usage where downsampling is desirable; there's
   no need for SRC as we can just do it cheaply in libvorbis. */
 
int ov_halfrate(OggVorbis_File *vf,int flag){
  int i;
  if(vf->vi==NULL)return OV_EINVAL;
  if(!vf->seekable)return OV_EINVAL;
  if(vf->ready_state>=STREAMSET)
    _decode_clear(vf); /* clear out stream state; later on libvorbis
                          will be able to swap this on the fly, but
                          for now dumping the decode machine is needed
                          to reinit the MDCT lookups.  1.1 libvorbis
                          is planned to be able to switch on the fly */
Michael Smith's avatar
   
Michael Smith committed
925
  
Monty's avatar
   
Monty committed
926
927
928
929
930
931
932
933
934
935
936
937
938
939
  for(i=0;i<vf->links;i++){
    if(vorbis_synthesis_halfrate(vf->vi+i,flag)){
      ov_halfrate(vf,0);
      return OV_EINVAL;
    }
  }
  return 0;
}

int ov_halfrate_p(OggVorbis_File *vf){
  if(vf->vi==NULL)return OV_EINVAL;
  return vorbis_synthesis_halfrate_p(vf->vi);
}

Monty's avatar
   
Monty committed
940
941
942
943
/* Only partially open the vorbis file; test for Vorbisness, and load
   the headers for the first chain.  Do not seek (although test for
   seekability).  Use ov_test_open to finish opening the file, else
   ov_clear to close/free it. Same return codes as open. */
Michael Smith's avatar
   
Michael Smith committed
944

Monty's avatar
   
Monty committed
945
int ov_test_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes,
Michael Smith's avatar
   
Michael Smith committed
946
947
    ov_callbacks callbacks)
{
Monty's avatar
   
Monty committed
948
949
  return _ov_open1(f,vf,initial,ibytes,callbacks);
}
Monty's avatar
   
Monty committed
950

Monty's avatar
   
Monty committed
951
952
953
954
955
956
957
int ov_test(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){
  ov_callbacks callbacks = {
    (size_t (*)(void *, size_t, size_t, void *))  fread,
    (int (*)(void *, ogg_int64_t, int))              _fseek64_wrap,
    (int (*)(void *))                             fclose,
    (long (*)(void *))                            ftell
  };
Monty's avatar
   
Monty committed
958

Monty's avatar
   
Monty committed
959
960
961
962
963
964
  return ov_test_callbacks((void *)f, vf, initial, ibytes, callbacks);
}
  
int ov_test_open(OggVorbis_File *vf){
  if(vf->ready_state!=PARTOPEN)return(OV_EINVAL);
  return _ov_open2(vf);
Monty's avatar
   
Monty committed
965
966
}

Monty's avatar
   
Monty committed
967
/* How many logical bitstreams in this physical bitstream? */
Monty's avatar
   
Monty committed
968
969
long ov_streams(OggVorbis_File *vf){
  return vf->links;
Monty's avatar
   
Monty committed
970
971
}

Monty's avatar
   
Monty committed
972
/* Is the FILE * associated with vf seekable? */
Monty's avatar
   
Monty committed
973
974
long ov_seekable(OggVorbis_File *vf){
  return vf->seekable;
Monty's avatar
   
Monty committed
975
976
}

Monty's avatar
   
Monty committed
977
978
979
980
981
982
983
984
985
986
/* returns the bitrate for a given logical bitstream or the entire
   physical bitstream.  If the file is open for random access, it will
   find the *actual* average bitrate.  If the file is streaming, it
   returns the nominal bitrate (if set) else the average of the
   upper/lower bounds (if set) else -1 (unset).

   If you want the actual bitrate field settings, get them from the
   vorbis_info structs */

long ov_bitrate(OggVorbis_File *vf,int i){
Monty's avatar
   
Monty committed
987
  if(vf->ready_state<OPENED)return(OV_EINVAL);
Monty's avatar
   
Monty committed
988
  if(i>=vf->links)return(OV_EINVAL);
Monty's avatar
   
Monty committed
989
  if(!vf->seekable && i!=0)return(ov_bitrate(vf,0));
Monty's avatar
   
Monty committed
990
  if(i<0){
Monty's avatar
   
Monty committed
991
    ogg_int64_t bits=0;
Monty's avatar
   
Monty committed
992
    int i;
993
    float br;
Monty's avatar
   
Monty committed
994
    for(i=0;i<vf->links;i++)
Monty's avatar
   
Monty committed
995
      bits+=(vf->offsets[i+1]-vf->dataoffsets[i])*8;
996
997
998
999
1000
    /* This once read: return(rint(bits/ov_time_total(vf,-1)));
     * gcc 3.x on x86 miscompiled this at optimisation level 2 and above,
     * so this is slightly transformed to make it work.
     */
    br = bits/ov_time_total(vf,-1);
For faster browsing, not all history is shown. View entire blame