Coverage Report

Created: 2025-07-11 06:15

/src/tremor/vorbisfile.c
Line
Count
Source (jump to first uncovered line)
1
/********************************************************************
2
 *                                                                  *
3
 * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE.   *
4
 *                                                                  *
5
 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
6
 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
7
 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
8
 *                                                                  *
9
 * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2014    *
10
 * BY THE Xiph.Org FOUNDATION http://www.xiph.org/                  *
11
 *                                                                  *
12
 ********************************************************************
13
14
 function: stdio-based convenience library for opening/seeking/decoding
15
 last mod: $Id$
16
17
 ********************************************************************/
18
19
#include <stdlib.h>
20
#include <stdio.h>
21
#include <errno.h>
22
#include <string.h>
23
#include <math.h>
24
25
#include "ivorbiscodec.h"
26
#include "ivorbisfile.h"
27
28
#include "os.h"
29
#include "misc.h"
30
31
/* A 'chained bitstream' is a Vorbis bitstream that contains more than
32
   one logical bitstream arranged end to end (the only form of Ogg
33
   multiplexing allowed in a Vorbis bitstream; grouping [parallel
34
   multiplexing] is not allowed in Vorbis) */
35
36
/* A Vorbis file can be played beginning to end (streamed) without
37
   worrying ahead of time about chaining (see decoder_example.c).  If
38
   we have the whole file, however, and want random access
39
   (seeking/scrubbing) or desire to know the total length/time of a
40
   file, we need to account for the possibility of chaining. */
41
42
/* We can handle things a number of ways; we can determine the entire
43
   bitstream structure right off the bat, or find pieces on demand.
44
   This example determines and caches structure for the entire
45
   bitstream, but builds a virtual decoder on the fly when moving
46
   between links in the chain. */
47
48
/* There are also different ways to implement seeking.  Enough
49
   information exists in an Ogg bitstream to seek to
50
   sample-granularity positions in the output.  Or, one can seek by
51
   picking some portion of the stream roughly in the desired area if
52
   we only want coarse navigation through the stream. */
53
54
/*************************************************************************
55
 * Many, many internal helpers.  The intention is not to be confusing;
56
 * rampant duplication and monolithic function implementation would be
57
 * harder to understand anyway.  The high level functions are last.  Begin
58
 * grokking near the end of the file */
59
60
61
/* read a little more data from the file/pipe into the ogg_sync framer */
62
9.74k
static long _get_data(OggVorbis_File *vf){
63
9.74k
  errno=0;
64
9.74k
  if(!(vf->callbacks.read_func))return(-1);
65
9.74k
  if(vf->datasource){
66
9.74k
    char *buffer=ogg_sync_buffer(&vf->oy,READSIZE);
67
9.74k
    long bytes=(vf->callbacks.read_func)(buffer,1,READSIZE,vf->datasource);
68
9.74k
    if(bytes>0)ogg_sync_wrote(&vf->oy,bytes);
69
9.74k
    if(bytes==0 && errno)return(-1);
70
9.74k
    return(bytes);
71
9.74k
  }else
72
0
    return(0);
73
9.74k
}
74
75
/* save a tiny smidge of verbosity to make the code more readable */
76
0
static int _seek_helper(OggVorbis_File *vf,ogg_int64_t offset){
77
0
  if(vf->datasource){
78
    /* only seek if the file position isn't already there */
79
0
    if(vf->offset != offset){
80
0
      if(!(vf->callbacks.seek_func)||
81
0
         (vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET) == -1)
82
0
        return OV_EREAD;
83
0
      vf->offset=offset;
84
0
      ogg_sync_reset(&vf->oy);
85
0
    }
86
0
  }else{
87
    /* shouldn't happen unless someone writes a broken callback */
88
0
    return OV_EFAULT;
89
0
  }
90
0
  return 0;
91
0
}
92
93
/* The read/seek functions track absolute position within the stream */
94
95
/* from the head of the stream, get the next page.  boundary specifies
96
   if the function is allowed to fetch more data from the stream (and
97
   how much) or only use internally buffered data.
98
99
   boundary: -1) unbounded search
100
              0) read no additional data; use cached only
101
              n) search for a new page beginning for n bytes
102
103
   return:   <0) did not find a page (OV_FALSE, OV_EOF, OV_EREAD)
104
              n) found a page at absolute offset n */
105
106
static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og,
107
36.4k
                                  ogg_int64_t boundary){
108
36.4k
  if(boundary>0)boundary+=vf->offset;
109
54.6k
  while(1){
110
54.6k
    long more;
111
112
54.6k
    if(boundary>0 && vf->offset>=boundary)return(OV_FALSE);
113
54.6k
    more=ogg_sync_pageseek(&vf->oy,og);
114
115
54.6k
    if(more<0){
116
      /* skipped n bytes */
117
11.1k
      vf->offset-=more;
118
43.4k
    }else{
119
43.4k
      if(more==0){
120
        /* send more paramedics */
121
9.74k
        if(!boundary)return(OV_FALSE);
122
9.74k
        {
123
9.74k
          long ret=_get_data(vf);
124
9.74k
          if(ret==0)return(OV_EOF);
125
7.04k
          if(ret<0)return(OV_EREAD);
126
7.04k
        }
127
33.6k
      }else{
128
        /* got a page.  Return the offset at the page beginning,
129
           advance the internal offset past the page end */
130
33.6k
        ogg_int64_t ret=vf->offset;
131
33.6k
        vf->offset+=more;
132
33.6k
        return(ret);
133
134
33.6k
      }
135
43.4k
    }
136
54.6k
  }
137
36.4k
}
138
139
/* find the latest page beginning before the passed in position. Much
140
   dirtier than the above as Ogg doesn't have any backward search
141
   linkage.  no 'readp' as it will certainly have to read. */
142
/* returns offset or OV_EREAD, OV_FAULT */
143
0
static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_int64_t begin,ogg_page *og){
144
0
  ogg_int64_t end = begin;
145
0
  ogg_int64_t ret;
146
0
  ogg_int64_t offset=-1;
147
148
0
  while(offset==-1){
149
0
    begin-=CHUNKSIZE;
150
0
    if(begin<0)
151
0
      begin=0;
152
153
0
    ret=_seek_helper(vf,begin);
154
0
    if(ret)return(ret);
155
156
0
    while(vf->offset<end){
157
0
      memset(og,0,sizeof(*og));
158
0
      ret=_get_next_page(vf,og,end-vf->offset);
159
0
      if(ret==OV_EREAD)return(OV_EREAD);
160
0
      if(ret<0){
161
0
        break;
162
0
      }else{
163
0
        offset=ret;
164
0
      }
165
0
    }
166
0
  }
167
168
  /* In a fully compliant, non-multiplexed stream, we'll still be
169
     holding the last page.  In multiplexed (or noncompliant streams),
170
     we will probably have to re-read the last page we saw */
171
0
  if(og->header_len==0){
172
0
    ret=_seek_helper(vf,offset);
173
0
    if(ret)return(ret);
174
175
0
    ret=_get_next_page(vf,og,CHUNKSIZE);
176
0
    if(ret<0)
177
      /* this shouldn't be possible */
178
0
      return(OV_EFAULT);
179
0
  }
180
181
0
  return(offset);
182
0
}
183
184
5.39k
static void _add_serialno(ogg_page *og,ogg_uint32_t **serialno_list, int *n){
185
5.39k
  ogg_uint32_t s = ogg_page_serialno(og);
186
5.39k
  (*n)++;
187
188
5.39k
  if(*serialno_list){
189
1.12k
    *serialno_list = _ogg_realloc(*serialno_list, sizeof(**serialno_list)*(*n));
190
4.27k
  }else{
191
4.27k
    *serialno_list = _ogg_malloc(sizeof(**serialno_list));
192
4.27k
  }
193
194
5.39k
  (*serialno_list)[(*n)-1] = s;
195
5.39k
}
196
197
/* returns nonzero if found */
198
5.40k
static int _lookup_serialno(ogg_uint32_t s, ogg_uint32_t *serialno_list, int n){
199
5.40k
  if(serialno_list){
200
15.4k
    while(n--){
201
14.2k
      if(*serialno_list == s) return 1;
202
14.2k
      serialno_list++;
203
14.2k
    }
204
1.12k
  }
205
5.39k
  return 0;
206
5.40k
}
207
208
5.40k
static int _lookup_page_serialno(ogg_page *og, ogg_uint32_t *serialno_list, int n){
209
5.40k
  ogg_uint32_t s = ogg_page_serialno(og);
210
5.40k
  return _lookup_serialno(s,serialno_list,n);
211
5.40k
}
212
213
/* performs the same search as _get_prev_page, but prefers pages of
214
   the specified serial number. If a page of the specified serialno is
215
   spotted during the seek-back-and-read-forward, it will return the
216
   info of last page of the matching serial number instead of the very
217
   last page.  If no page of the specified serialno is seen, it will
218
   return the info of last page and alter *serialno.  */
219
static ogg_int64_t _get_prev_page_serial(OggVorbis_File *vf, ogg_int64_t begin,
220
                                         ogg_uint32_t *serial_list, int serial_n,
221
0
                                         int *serialno, ogg_int64_t *granpos){
222
0
  ogg_page og;
223
0
  ogg_int64_t end=begin;
224
0
  ogg_int64_t ret;
225
226
0
  ogg_int64_t prefoffset=-1;
227
0
  ogg_int64_t offset=-1;
228
0
  ogg_int64_t ret_serialno=-1;
229
0
  ogg_int64_t ret_gran=-1;
230
231
0
  while(offset==-1){
232
0
    begin-=CHUNKSIZE;
233
0
    if(begin<0)
234
0
      begin=0;
235
236
0
    ret=_seek_helper(vf,begin);
237
0
    if(ret)return(ret);
238
239
0
    while(vf->offset<end){
240
0
      ret=_get_next_page(vf,&og,end-vf->offset);
241
0
      if(ret==OV_EREAD)return(OV_EREAD);
242
0
      if(ret<0){
243
0
        break;
244
0
      }else{
245
0
        ret_serialno=ogg_page_serialno(&og);
246
0
        ret_gran=ogg_page_granulepos(&og);
247
0
        offset=ret;
248
249
0
        if((ogg_uint32_t)ret_serialno == *serialno){
250
0
          prefoffset=ret;
251
0
          *granpos=ret_gran;
252
0
        }
253
254
0
        if(!_lookup_serialno((ogg_uint32_t)ret_serialno,serial_list,serial_n)){
255
          /* we fell off the end of the link, which means we seeked
256
             back too far and shouldn't have been looking in that link
257
             to begin with.  If we found the preferred serial number,
258
             forget that we saw it. */
259
0
          prefoffset=-1;
260
0
        }
261
0
      }
262
0
    }
263
0
  }
264
265
  /* we're not interested in the page... just the serialno and granpos. */
266
0
  if(prefoffset>=0)return(prefoffset);
267
268
0
  *serialno = ret_serialno;
269
0
  *granpos = ret_gran;
270
0
  return(offset);
271
272
0
}
273
274
/* uses the local ogg_stream storage in vf; this is important for
275
   non-streaming input sources */
276
static int _fetch_headers(OggVorbis_File *vf,vorbis_info *vi,vorbis_comment *vc,
277
                          ogg_uint32_t **serialno_list, int *serialno_n,
278
8.50k
                          ogg_page *og_ptr){
279
8.50k
  ogg_page og;
280
8.50k
  ogg_packet op;
281
8.50k
  int i,ret;
282
8.50k
  int allbos=0;
283
284
8.50k
  if(!og_ptr){
285
4.35k
    ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE);
286
4.35k
    if(llret==OV_EREAD)return(OV_EREAD);
287
4.35k
    if(llret<0)return(OV_ENOTVORBIS);
288
4.28k
    og_ptr=&og;
289
4.28k
  }
290
291
8.42k
  vorbis_info_init(vi);
292
8.42k
  vorbis_comment_init(vc);
293
8.42k
  vf->ready_state=OPENED;
294
295
  /* extract the serialnos of all BOS pages + the first set of vorbis
296
     headers we see in the link */
297
298
15.0k
  while(ogg_page_bos(og_ptr)){
299
14.6k
    if(serialno_list){
300
5.40k
      if(_lookup_page_serialno(og_ptr,*serialno_list,*serialno_n)){
301
        /* a dupe serialnumber in an initial header packet set == invalid stream */
302
4
        if(*serialno_list)_ogg_free(*serialno_list);
303
4
        *serialno_list=0;
304
4
        *serialno_n=0;
305
4
        ret=OV_EBADHEADER;
306
4
        goto bail_header;
307
4
      }
308
309
5.39k
      _add_serialno(og_ptr,serialno_list,serialno_n);
310
5.39k
    }
311
312
14.6k
    if(vf->ready_state<STREAMSET){
313
      /* we don't have a vorbis stream in this link yet, so begin
314
         prospective stream setup. We need a stream to get packets */
315
14.3k
      ogg_stream_reset_serialno(&vf->os,ogg_page_serialno(og_ptr));
316
14.3k
      ogg_stream_pagein(&vf->os,og_ptr);
317
318
14.3k
      if(ogg_stream_packetout(&vf->os,&op) > 0 &&
319
14.3k
         vorbis_synthesis_idheader(&op)){
320
        /* vorbis header; continue setup */
321
8.05k
        vf->ready_state=STREAMSET;
322
8.05k
        if((ret=vorbis_synthesis_headerin(vi,vc,&op))){
323
109
          ret=OV_EBADHEADER;
324
109
          goto bail_header;
325
109
        }
326
8.05k
      }
327
14.3k
    }
328
329
    /* get next page */
330
14.5k
    {
331
14.5k
      ogg_int64_t llret=_get_next_page(vf,og_ptr,CHUNKSIZE);
332
14.5k
      if(llret==OV_EREAD){
333
0
        ret=OV_EREAD;
334
0
        goto bail_header;
335
0
      }
336
14.5k
      if(llret<0){
337
406
        ret=OV_ENOTVORBIS;
338
406
        goto bail_header;
339
406
      }
340
341
      /* if this page also belongs to our vorbis stream, submit it and break */
342
14.1k
      if(vf->ready_state==STREAMSET &&
343
14.1k
         vf->os.serialno == ogg_page_serialno(og_ptr)){
344
7.52k
        ogg_stream_pagein(&vf->os,og_ptr);
345
7.52k
        break;
346
7.52k
      }
347
14.1k
    }
348
14.1k
  }
349
350
7.91k
  if(vf->ready_state!=STREAMSET){
351
15
    ret = OV_ENOTVORBIS;
352
15
    goto bail_header;
353
15
  }
354
355
7.89k
  while(1){
356
357
7.89k
    i=0;
358
16.2k
    while(i<2){ /* get a page loop */
359
360
23.6k
      while(i<2){ /* get a packet loop */
361
362
17.2k
        int result=ogg_stream_packetout(&vf->os,&op);
363
17.2k
        if(result==0)break;
364
15.0k
        if(result==-1){
365
51
          ret=OV_EBADHEADER;
366
51
          goto bail_header;
367
51
        }
368
369
15.0k
        if((ret=vorbis_synthesis_headerin(vi,vc,&op)))
370
1.36k
          goto bail_header;
371
372
13.6k
        i++;
373
13.6k
      }
374
375
9.89k
      while(i<2){
376
3.57k
        if(_get_next_page(vf,og_ptr,CHUNKSIZE)<0){
377
154
          ret=OV_EBADHEADER;
378
154
          goto bail_header;
379
154
        }
380
381
        /* if this page belongs to the correct stream, go parse it */
382
3.41k
        if(vf->os.serialno == ogg_page_serialno(og_ptr)){
383
2.07k
          ogg_stream_pagein(&vf->os,og_ptr);
384
2.07k
          break;
385
2.07k
        }
386
387
        /* if we never see the final vorbis headers before the link
388
           ends, abort */
389
1.34k
        if(ogg_page_bos(og_ptr)){
390
131
          if(allbos){
391
3
            ret = OV_EBADHEADER;
392
3
            goto bail_header;
393
3
          }else
394
128
            allbos=1;
395
131
        }
396
397
        /* otherwise, keep looking */
398
1.34k
      }
399
8.55k
    }
400
401
6.32k
    return 0;
402
7.89k
  }
403
404
2.10k
 bail_header:
405
2.10k
  vorbis_info_clear(vi);
406
2.10k
  vorbis_comment_clear(vc);
407
2.10k
  vf->ready_state=OPENED;
408
409
2.10k
  return ret;
410
7.89k
}
411
412
/* Starting from current cursor position, get initial PCM offset of
413
   next page.  Consumes the page in the process without decoding
414
   audio, however this is only called during stream parsing upon
415
   seekable open. */
416
0
static ogg_int64_t _initial_pcmoffset(OggVorbis_File *vf, vorbis_info *vi){
417
0
  ogg_page    og;
418
0
  ogg_int64_t accumulated=0;
419
0
  long        lastblock=-1;
420
0
  int         result;
421
0
  int         serialno = vf->os.serialno;
422
423
0
  while(1){
424
0
    ogg_packet op;
425
0
    if(_get_next_page(vf,&og,-1)<0)
426
0
      break; /* should not be possible unless the file is truncated/mangled */
427
428
0
    if(ogg_page_bos(&og)) break;
429
0
    if(ogg_page_serialno(&og)!=serialno) continue;
430
431
    /* count blocksizes of all frames in the page */
432
0
    ogg_stream_pagein(&vf->os,&og);
433
0
    while((result=ogg_stream_packetout(&vf->os,&op))){
434
0
      if(result>0){ /* ignore holes */
435
0
        long thisblock=vorbis_packet_blocksize(vi,&op);
436
0
        if(lastblock!=-1)
437
0
          accumulated+=(lastblock+thisblock)>>2;
438
0
        lastblock=thisblock;
439
0
      }
440
0
    }
441
442
0
    if(ogg_page_granulepos(&og)!=-1){
443
      /* pcm offset of last packet on the first audio page */
444
0
      accumulated= ogg_page_granulepos(&og)-accumulated;
445
0
      break;
446
0
    }
447
0
  }
448
449
  /* less than zero?  This is a stream with samples trimmed off
450
     the beginning, a normal occurrence; set the offset to zero */
451
0
  if(accumulated<0)accumulated=0;
452
453
0
  return accumulated;
454
0
}
455
456
/* finds each bitstream link one at a time using a bisection search
457
   (has to begin by knowing the offset of the lb's initial page).
458
   Recurses for each link so it can alloc the link storage after
459
   finding them all, then unroll and fill the cache at the same time */
460
static int _bisect_forward_serialno(OggVorbis_File *vf,
461
                                    ogg_int64_t begin,
462
                                    ogg_int64_t searched,
463
                                    ogg_int64_t end,
464
                                    ogg_int64_t endgran,
465
                                    int endserial,
466
                                    ogg_uint32_t *currentno_list,
467
                                    int  currentnos,
468
0
                                    long m){
469
0
  ogg_int64_t pcmoffset;
470
0
  ogg_int64_t dataoffset=searched;
471
0
  ogg_int64_t endsearched=end;
472
0
  ogg_int64_t next=end;
473
0
  ogg_int64_t searchgran=-1;
474
0
  ogg_page og;
475
0
  ogg_int64_t ret,last;
476
0
  int serialno = vf->os.serialno;
477
478
  /* invariants:
479
     we have the headers and serialnos for the link beginning at 'begin'
480
     we have the offset and granpos of the last page in the file (potentially
481
       not a page we care about)
482
  */
483
484
  /* Is the last page in our list of current serialnumbers? */
485
0
  if(_lookup_serialno(endserial,currentno_list,currentnos)){
486
487
    /* last page is in the starting serialno list, so we've bisected
488
       down to (or just started with) a single link.  Now we need to
489
       find the last vorbis page belonging to the first vorbis stream
490
       for this link. */
491
0
    searched = end;
492
0
    while(endserial != serialno){
493
0
      endserial = serialno;
494
0
      searched=_get_prev_page_serial(vf,searched,currentno_list,currentnos,&endserial,&endgran);
495
0
    }
496
497
0
    vf->links=m+1;
498
0
    if(vf->offsets)_ogg_free(vf->offsets);
499
0
    if(vf->serialnos)_ogg_free(vf->serialnos);
500
0
    if(vf->dataoffsets)_ogg_free(vf->dataoffsets);
501
502
0
    vf->offsets=_ogg_malloc((vf->links+1)*sizeof(*vf->offsets));
503
0
    vf->vi=_ogg_realloc(vf->vi,vf->links*sizeof(*vf->vi));
504
0
    vf->vc=_ogg_realloc(vf->vc,vf->links*sizeof(*vf->vc));
505
0
    vf->serialnos=_ogg_malloc(vf->links*sizeof(*vf->serialnos));
506
0
    vf->dataoffsets=_ogg_malloc(vf->links*sizeof(*vf->dataoffsets));
507
0
    vf->pcmlengths=_ogg_malloc(vf->links*2*sizeof(*vf->pcmlengths));
508
509
0
    vf->offsets[m+1]=end;
510
0
    vf->offsets[m]=begin;
511
0
    vf->pcmlengths[m*2+1]=(endgran<0?0:endgran);
512
513
0
  }else{
514
515
    /* last page is not in the starting stream's serial number list,
516
       so we have multiple links.  Find where the stream that begins
517
       our bisection ends. */
518
519
0
    ogg_uint32_t *next_serialno_list=NULL;
520
0
    int next_serialnos=0;
521
0
    vorbis_info vi;
522
0
    vorbis_comment vc;
523
0
    int testserial = serialno+1;
524
525
    /* the below guards against garbage seperating the last and
526
       first pages of two links. */
527
0
    while(searched<endsearched){
528
0
      ogg_int64_t bisect;
529
530
0
      if(endsearched-searched<CHUNKSIZE){
531
0
        bisect=searched;
532
0
      }else{
533
0
        bisect=(searched+endsearched)/2;
534
0
      }
535
536
0
      ret=_seek_helper(vf,bisect);
537
0
      if(ret)return(ret);
538
539
0
      last=_get_next_page(vf,&og,-1);
540
0
      if(last==OV_EREAD)return(OV_EREAD);
541
0
      if(last<0 || !_lookup_page_serialno(&og,currentno_list,currentnos)){
542
0
        endsearched=bisect;
543
0
        if(last>=0)next=last;
544
0
      }else{
545
0
        searched=vf->offset;
546
0
      }
547
0
    }
548
549
    /* Bisection point found */
550
    /* for the time being, fetch end PCM offset the simple way */
551
0
    searched = next;
552
0
    while(testserial != serialno){
553
0
      testserial = serialno;
554
0
      searched = _get_prev_page_serial(vf,searched,currentno_list,currentnos,&testserial,&searchgran);
555
0
    }
556
557
0
    ret=_seek_helper(vf,next);
558
0
    if(ret)return(ret);
559
560
0
    ret=_fetch_headers(vf,&vi,&vc,&next_serialno_list,&next_serialnos,NULL);
561
0
    if(ret)return(ret);
562
0
    serialno = vf->os.serialno;
563
0
    dataoffset = vf->offset;
564
565
    /* this will consume a page, however the next bisection always
566
       starts with a raw seek */
567
0
    pcmoffset = _initial_pcmoffset(vf,&vi);
568
569
0
    ret=_bisect_forward_serialno(vf,next,vf->offset,end,endgran,endserial,
570
0
                                 next_serialno_list,next_serialnos,m+1);
571
0
    if(ret)return(ret);
572
573
0
    if(next_serialno_list)_ogg_free(next_serialno_list);
574
575
0
    vf->offsets[m+1]=next;
576
0
    vf->serialnos[m+1]=serialno;
577
0
    vf->dataoffsets[m+1]=dataoffset;
578
579
0
    vf->vi[m+1]=vi;
580
0
    vf->vc[m+1]=vc;
581
582
0
    vf->pcmlengths[m*2+1]=searchgran;
583
0
    vf->pcmlengths[m*2+2]=pcmoffset;
584
0
    vf->pcmlengths[m*2+3]-=pcmoffset;
585
0
    if(vf->pcmlengths[m*2+3]<0)vf->pcmlengths[m*2+3]=0;
586
587
0
  }
588
0
  return(0);
589
0
}
590
591
6.32k
static int _make_decode_ready(OggVorbis_File *vf){
592
6.32k
  if(vf->ready_state>STREAMSET)return 0;
593
6.32k
  if(vf->ready_state<STREAMSET)return OV_EFAULT;
594
6.32k
  if(vf->seekable){
595
0
    if(vorbis_synthesis_init(&vf->vd,vf->vi+vf->current_link))
596
0
      return OV_EBADLINK;
597
6.32k
  }else{
598
6.32k
    if(vorbis_synthesis_init(&vf->vd,vf->vi))
599
111
      return OV_EBADLINK;
600
6.32k
  }
601
6.21k
  vorbis_block_init(&vf->vd,&vf->vb);
602
6.21k
  vf->ready_state=INITSET;
603
6.21k
  vf->bittrack=0;
604
6.21k
  vf->samptrack=0;
605
6.21k
  return 0;
606
6.32k
}
607
608
0
static int _open_seekable2(OggVorbis_File *vf){
609
0
  ogg_int64_t dataoffset=vf->dataoffsets[0],end,endgran=-1;
610
0
  int endserial=vf->os.serialno;
611
0
  int serialno=vf->os.serialno;
612
613
  /* we're partially open and have a first link header state in
614
     storage in vf */
615
616
  /* fetch initial PCM offset */
617
0
  ogg_int64_t pcmoffset = _initial_pcmoffset(vf,vf->vi);
618
619
  /* we can seek, so set out learning all about this file */
620
0
  if(vf->callbacks.seek_func && vf->callbacks.tell_func){
621
0
    (vf->callbacks.seek_func)(vf->datasource,0,SEEK_END);
622
0
    vf->offset=vf->end=(vf->callbacks.tell_func)(vf->datasource);
623
0
  }else{
624
0
    vf->offset=vf->end=-1;
625
0
  }
626
627
  /* If seek_func is implemented, tell_func must also be implemented */
628
0
  if(vf->end==-1) return(OV_EINVAL);
629
630
  /* Get the offset of the last page of the physical bitstream, or, if
631
     we're lucky the last vorbis page of this link as most OggVorbis
632
     files will contain a single logical bitstream */
633
0
  end=_get_prev_page_serial(vf,vf->end,vf->serialnos+2,vf->serialnos[1],&endserial,&endgran);
634
0
  if(end<0)return(end);
635
636
  /* now determine bitstream structure recursively */
637
0
  if(_bisect_forward_serialno(vf,0,dataoffset,end,endgran,endserial,
638
0
                              vf->serialnos+2,vf->serialnos[1],0)<0)return(OV_EREAD);
639
640
0
  vf->offsets[0]=0;
641
0
  vf->serialnos[0]=serialno;
642
0
  vf->dataoffsets[0]=dataoffset;
643
0
  vf->pcmlengths[0]=pcmoffset;
644
0
  vf->pcmlengths[1]-=pcmoffset;
645
0
  if(vf->pcmlengths[1]<0)vf->pcmlengths[1]=0;
646
647
0
  return(ov_raw_seek(vf,dataoffset));
648
0
}
649
650
/* clear out the current logical bitstream decoder */
651
4.14k
static void _decode_clear(OggVorbis_File *vf){
652
4.14k
  vorbis_dsp_clear(&vf->vd);
653
4.14k
  vorbis_block_clear(&vf->vb);
654
4.14k
  vf->ready_state=OPENED;
655
4.14k
}
656
657
/* fetch and process a packet.  Handles the case where we're at a
658
   bitstream boundary and dumps the decoding machine.  If the decoding
659
   machine is unloaded, it loads it.  It also keeps pcm_offset up to
660
   date (seek and read both use this.  seek uses a special hack with
661
   readp).
662
663
   return: <0) error, OV_HOLE (lost packet) or OV_EOF
664
            0) need more data (only if readp==0)
665
            1) got a packet
666
*/
667
668
static int _fetch_and_process_packet(OggVorbis_File *vf,
669
                                     ogg_packet *op_in,
670
                                     int readp,
671
43.3k
                                     int spanp){
672
43.3k
  ogg_page og;
673
674
  /* handle one packet.  Try to fetch it from current stream state */
675
  /* extract packets from page */
676
54.3k
  while(1){
677
678
54.3k
    if(vf->ready_state==STREAMSET){
679
6.32k
      int ret=_make_decode_ready(vf);
680
6.32k
      if(ret<0)return ret;
681
6.32k
    }
682
683
    /* process a packet if we can.  If the machine isn't loaded,
684
       neither is a page */
685
54.2k
    if(vf->ready_state==INITSET){
686
118k
      while(1) {
687
118k
              ogg_packet op;
688
118k
              ogg_packet *op_ptr=(op_in?op_in:&op);
689
118k
        int result=ogg_stream_packetout(&vf->os,op_ptr);
690
118k
        ogg_int64_t granulepos;
691
692
118k
        op_in=NULL;
693
118k
        if(result==-1)return(OV_HOLE); /* hole in the data. */
694
109k
        if(result>0){
695
          /* got a packet.  process it */
696
96.2k
          granulepos=op_ptr->granulepos;
697
96.2k
          if(!vorbis_synthesis(&vf->vb,op_ptr)){ /* lazy check for lazy
698
                                                    header handling.  The
699
                                                    header packets aren't
700
                                                    audio, so if/when we
701
                                                    submit them,
702
                                                    vorbis_synthesis will
703
                                                    reject them */
704
705
            /* suck in the synthesis data and track bitrate */
706
32.4k
            {
707
32.4k
              int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL);
708
              /* for proper use of libvorbis within libvorbisfile,
709
                 oldsamples will always be zero. */
710
32.4k
              if(oldsamples)return(OV_EFAULT);
711
712
32.4k
              vorbis_synthesis_blockin(&vf->vd,&vf->vb);
713
32.4k
              vf->samptrack+=vorbis_synthesis_pcmout(&vf->vd,NULL);
714
32.4k
              vf->bittrack+=op_ptr->bytes*8;
715
32.4k
            }
716
717
            /* update the pcm offset. */
718
32.4k
            if(granulepos!=-1 && !op_ptr->e_o_s){
719
5.07k
              int link=(vf->seekable?vf->current_link:0);
720
5.07k
              int i,samples;
721
722
              /* this packet has a pcm_offset on it (the last packet
723
                 completed on a page carries the offset) After processing
724
                 (above), we know the pcm position of the *last* sample
725
                 ready to be returned. Find the offset of the *first*
726
727
                 As an aside, this trick is inaccurate if we begin
728
                 reading anew right at the last page; the end-of-stream
729
                 granulepos declares the last frame in the stream, and the
730
                 last packet of the last page may be a partial frame.
731
                 So, we need a previous granulepos from an in-sequence page
732
                 to have a reference point.  Thus the !op_ptr->e_o_s clause
733
                 above */
734
735
5.07k
              if(vf->seekable && link>0)
736
0
                granulepos-=vf->pcmlengths[link*2];
737
5.07k
              if(granulepos<0)granulepos=0; /* actually, this
738
                                               shouldn't be possible
739
                                               here unless the stream
740
                                               is very broken */
741
742
5.07k
              samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
743
744
5.07k
              granulepos-=samples;
745
5.07k
              for(i=0;i<link;i++)
746
0
                granulepos+=vf->pcmlengths[i*2+1];
747
5.07k
              vf->pcm_offset=granulepos;
748
5.07k
            }
749
32.4k
            return(1);
750
32.4k
          }
751
96.2k
        }
752
13.3k
        else
753
13.3k
          break;
754
109k
      }
755
54.2k
    }
756
757
13.3k
    if(vf->ready_state>=OPENED){
758
13.3k
      ogg_int64_t ret;
759
760
13.9k
      while(1){
761
        /* the loop is not strictly necessary, but there's no sense in
762
           doing the extra checks of the larger loop for the common
763
           case in a multiplexed bistream where the page is simply
764
           part of a different logical bitstream; keep reading until
765
           we get one with the correct serialno */
766
767
13.9k
        if(!readp)return(0);
768
13.9k
        if((ret=_get_next_page(vf,&og,-1))<0){
769
2.06k
          return(OV_EOF); /* eof. leave unitialized */
770
2.06k
        }
771
772
        /* bitrate tracking; add the header's bytes here, the body bytes
773
           are done by packet above */
774
11.8k
        vf->bittrack+=og.header_len*8;
775
776
11.8k
        if(vf->ready_state==INITSET){
777
11.8k
          if(vf->current_serialno!=ogg_page_serialno(&og)){
778
779
            /* two possibilities:
780
               1) our decoding just traversed a bitstream boundary
781
               2) another stream is multiplexed into this logical section */
782
783
4.72k
            if(ogg_page_bos(&og)){
784
              /* boundary case */
785
4.14k
              if(!spanp)
786
0
                return(OV_EOF);
787
788
4.14k
              _decode_clear(vf);
789
790
4.14k
              if(!vf->seekable){
791
4.14k
                vorbis_info_clear(vf->vi);
792
4.14k
                vorbis_comment_clear(vf->vc);
793
4.14k
              }
794
4.14k
              break;
795
796
4.14k
            }else
797
571
              continue; /* possibility #2 */
798
4.72k
          }
799
11.8k
        }
800
801
7.12k
        break;
802
11.8k
      }
803
13.3k
    }
804
805
    /* Do we need to load a new machine before submitting the page? */
806
    /* This is different in the seekable and non-seekable cases.
807
808
       In the seekable case, we already have all the header
809
       information loaded and cached; we just initialize the machine
810
       with it and continue on our merry way.
811
812
       In the non-seekable (streaming) case, we'll only be at a
813
       boundary if we just left the previous logical bitstream and
814
       we're now nominally at the header of the next bitstream
815
    */
816
817
11.2k
    if(vf->ready_state!=INITSET){
818
4.14k
      int link;
819
820
4.14k
      if(vf->ready_state<STREAMSET){
821
4.14k
        if(vf->seekable){
822
0
          ogg_uint32_t serialno = ogg_page_serialno(&og);
823
824
          /* match the serialno to bitstream section.  We use this rather than
825
             offset positions to avoid problems near logical bitstream
826
             boundaries */
827
828
0
          for(link=0;link<vf->links;link++)
829
0
            if(vf->serialnos[link]==serialno)break;
830
831
0
          if(link==vf->links) continue; /* not the desired Vorbis
832
                                           bitstream section; keep
833
                                           trying */
834
835
0
          vf->current_serialno=serialno;
836
0
          vf->current_link=link;
837
838
0
          ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
839
0
          vf->ready_state=STREAMSET;
840
841
4.14k
        }else{
842
          /* we're streaming */
843
          /* fetch the three header packets, build the info struct */
844
845
4.14k
          int ret=_fetch_headers(vf,vf->vi,vf->vc,NULL,NULL,&og);
846
4.14k
          if(ret)return(ret);
847
3.91k
          vf->current_serialno=vf->os.serialno;
848
3.91k
          vf->current_link++;
849
3.91k
          link=0;
850
3.91k
        }
851
4.14k
      }
852
4.14k
    }
853
854
    /* the buffered page is the data we want, and we're ready for it;
855
       add it to the stream state */
856
11.0k
    ogg_stream_pagein(&vf->os,&og);
857
858
11.0k
  }
859
43.3k
}
860
861
/* if, eg, 64 bit stdio is configured by default, this will build with
862
   fseek64 */
863
0
static int _fseek64_wrap(FILE *f,ogg_int64_t off,int whence){
864
0
  if(f==NULL)return(-1);
865
0
  return fseek(f,off,whence);
866
0
}
867
868
static int _ov_open1(void *f,OggVorbis_File *vf,const char *initial,
869
4.35k
                     long ibytes, ov_callbacks callbacks){
870
4.35k
  int offsettest=((f && callbacks.seek_func)?callbacks.seek_func(f,0,SEEK_CUR):-1);
871
4.35k
  ogg_uint32_t *serialno_list=NULL;
872
4.35k
  int serialno_list_size=0;
873
4.35k
  int ret;
874
875
4.35k
  memset(vf,0,sizeof(*vf));
876
4.35k
  vf->datasource=f;
877
4.35k
  vf->callbacks = callbacks;
878
879
  /* init the framing state */
880
4.35k
  ogg_sync_init(&vf->oy);
881
882
  /* perhaps some data was previously read into a buffer for testing
883
     against other stream types.  Allow initialization from this
884
     previously read data (especially as we may be reading from a
885
     non-seekable stream) */
886
4.35k
  if(initial){
887
0
    char *buffer=ogg_sync_buffer(&vf->oy,ibytes);
888
0
    memcpy(buffer,initial,ibytes);
889
0
    ogg_sync_wrote(&vf->oy,ibytes);
890
0
  }
891
892
  /* can we seek? Stevens suggests the seek test was portable */
893
4.35k
  if(offsettest!=-1)vf->seekable=1;
894
895
  /* No seeking yet; Set up a 'single' (current) logical bitstream
896
     entry for partial open */
897
4.35k
  vf->links=1;
898
4.35k
  vf->vi=_ogg_calloc(vf->links,sizeof(*vf->vi));
899
4.35k
  vf->vc=_ogg_calloc(vf->links,sizeof(*vf->vc));
900
4.35k
  ogg_stream_init(&vf->os,-1); /* fill in the serialno later */
901
902
  /* Fetch all BOS pages, store the vorbis header and all seen serial
903
     numbers, load subsequent vorbis setup headers */
904
4.35k
  if((ret=_fetch_headers(vf,vf->vi,vf->vc,&serialno_list,&serialno_list_size,NULL))<0){
905
1.94k
    vf->datasource=NULL;
906
1.94k
    ov_clear(vf);
907
2.40k
  }else{
908
    /* serial number list for first link needs to be held somewhere
909
       for second stage of seekable stream open; this saves having to
910
       seek/reread first link's serialnumber data then. */
911
2.40k
    vf->serialnos=_ogg_calloc(serialno_list_size+2,sizeof(*vf->serialnos));
912
2.40k
    vf->serialnos[0]=vf->current_serialno=vf->os.serialno;
913
2.40k
    vf->serialnos[1]=serialno_list_size;
914
2.40k
    memcpy(vf->serialnos+2,serialno_list,serialno_list_size*sizeof(*vf->serialnos));
915
916
2.40k
    vf->offsets=_ogg_calloc(1,sizeof(*vf->offsets));
917
2.40k
    vf->dataoffsets=_ogg_calloc(1,sizeof(*vf->dataoffsets));
918
2.40k
    vf->offsets[0]=0;
919
2.40k
    vf->dataoffsets[0]=vf->offset;
920
921
2.40k
    vf->ready_state=PARTOPEN;
922
2.40k
  }
923
4.35k
  if(serialno_list)_ogg_free(serialno_list);
924
4.35k
  return(ret);
925
4.35k
}
926
927
2.40k
static int _ov_open2(OggVorbis_File *vf){
928
2.40k
  if(vf->ready_state != PARTOPEN) return OV_EINVAL;
929
2.40k
  vf->ready_state=OPENED;
930
2.40k
  if(vf->seekable){
931
0
    int ret=_open_seekable2(vf);
932
0
    if(ret){
933
0
      vf->datasource=NULL;
934
0
      ov_clear(vf);
935
0
    }
936
0
    return(ret);
937
0
  }else
938
2.40k
    vf->ready_state=STREAMSET;
939
940
2.40k
  return 0;
941
2.40k
}
942
943
944
/* clear out the OggVorbis_File struct */
945
4.35k
int ov_clear(OggVorbis_File *vf){
946
4.35k
  if(vf){
947
4.35k
    vorbis_block_clear(&vf->vb);
948
4.35k
    vorbis_dsp_clear(&vf->vd);
949
4.35k
    ogg_stream_clear(&vf->os);
950
951
4.35k
    if(vf->vi && vf->links){
952
4.35k
      int i;
953
8.71k
      for(i=0;i<vf->links;i++){
954
4.35k
        vorbis_info_clear(vf->vi+i);
955
4.35k
        vorbis_comment_clear(vf->vc+i);
956
4.35k
      }
957
4.35k
      _ogg_free(vf->vi);
958
4.35k
      _ogg_free(vf->vc);
959
4.35k
    }
960
4.35k
    if(vf->dataoffsets)_ogg_free(vf->dataoffsets);
961
4.35k
    if(vf->pcmlengths)_ogg_free(vf->pcmlengths);
962
4.35k
    if(vf->serialnos)_ogg_free(vf->serialnos);
963
4.35k
    if(vf->offsets)_ogg_free(vf->offsets);
964
4.35k
    ogg_sync_clear(&vf->oy);
965
4.35k
    if(vf->datasource && vf->callbacks.close_func)
966
0
      (vf->callbacks.close_func)(vf->datasource);
967
4.35k
    memset(vf,0,sizeof(*vf));
968
4.35k
  }
969
#ifdef DEBUG_LEAKS
970
  _VDBG_dump();
971
#endif
972
4.35k
  return(0);
973
4.35k
}
974
975
/* inspects the OggVorbis file and finds/documents all the logical
976
   bitstreams contained in it.  Tries to be tolerant of logical
977
   bitstream sections that are truncated/woogie.
978
979
   return: -1) error
980
            0) OK
981
*/
982
983
int ov_open_callbacks(void *f,OggVorbis_File *vf,
984
4.35k
    const char *initial,long ibytes,ov_callbacks callbacks){
985
4.35k
  int ret=_ov_open1(f,vf,initial,ibytes,callbacks);
986
4.35k
  if(ret)return ret;
987
2.40k
  return _ov_open2(vf);
988
4.35k
}
989
990
0
int ov_open(FILE *f,OggVorbis_File *vf,const char *initial,long ibytes){
991
0
  ov_callbacks callbacks = {
992
0
    (size_t (*)(void *, size_t, size_t, void *))  fread,
993
0
    (int (*)(void *, ogg_int64_t, int))              _fseek64_wrap,
994
0
    (int (*)(void *))                             fclose,
995
0
    (long (*)(void *))                            ftell
996
0
  };
997
998
0
  return ov_open_callbacks((void *)f, vf, initial, ibytes, callbacks);
999
0
}
1000
1001
0
int ov_fopen(const char *path,OggVorbis_File *vf){
1002
0
  int ret;
1003
0
  FILE *f = fopen(path,"rb");
1004
0
  if(!f) return -1;
1005
1006
0
  ret = ov_open(f,vf,NULL,0);
1007
0
  if(ret) fclose(f);
1008
0
  return ret;
1009
0
}
1010
1011
1012
/* Only partially open the vorbis file; test for Vorbisness, and load
1013
   the headers for the first chain.  Do not seek (although test for
1014
   seekability).  Use ov_test_open to finish opening the file, else
1015
   ov_clear to close/free it. Same return codes as open. */
1016
1017
int ov_test_callbacks(void *f,OggVorbis_File *vf,
1018
    const char *initial,long ibytes,ov_callbacks callbacks)
1019
0
{
1020
0
  return _ov_open1(f,vf,initial,ibytes,callbacks);
1021
0
}
1022
1023
0
int ov_test(FILE *f,OggVorbis_File *vf,const char *initial,long ibytes){
1024
0
  ov_callbacks callbacks = {
1025
0
    (size_t (*)(void *, size_t, size_t, void *))  fread,
1026
0
    (int (*)(void *, ogg_int64_t, int))              _fseek64_wrap,
1027
0
    (int (*)(void *))                             fclose,
1028
0
    (long (*)(void *))                            ftell
1029
0
  };
1030
1031
0
  return ov_test_callbacks((void *)f, vf, initial, ibytes, callbacks);
1032
0
}
1033
1034
0
int ov_test_open(OggVorbis_File *vf){
1035
0
  if(vf->ready_state!=PARTOPEN)return(OV_EINVAL);
1036
0
  return _ov_open2(vf);
1037
0
}
1038
1039
/* How many logical bitstreams in this physical bitstream? */
1040
0
long ov_streams(OggVorbis_File *vf){
1041
0
  return vf->links;
1042
0
}
1043
1044
/* Is the FILE * associated with vf seekable? */
1045
0
long ov_seekable(OggVorbis_File *vf){
1046
0
  return vf->seekable;
1047
0
}
1048
1049
/* returns the bitrate for a given logical bitstream or the entire
1050
   physical bitstream.  If the file is open for random access, it will
1051
   find the *actual* average bitrate.  If the file is streaming, it
1052
   returns the nominal bitrate (if set) else the average of the
1053
   upper/lower bounds (if set) else -1 (unset).
1054
1055
   If you want the actual bitrate field settings, get them from the
1056
   vorbis_info structs */
1057
1058
0
long ov_bitrate(OggVorbis_File *vf,int i){
1059
0
  if(vf->ready_state<OPENED)return(OV_EINVAL);
1060
0
  if(i>=vf->links)return(OV_EINVAL);
1061
0
  if(!vf->seekable && i!=0)return(ov_bitrate(vf,0));
1062
0
  if(i<0){
1063
0
    ogg_int64_t bits=0;
1064
0
    int i;
1065
0
    for(i=0;i<vf->links;i++)
1066
0
      bits+=(vf->offsets[i+1]-vf->dataoffsets[i])*8;
1067
    /* This once read: return(rint(bits/ov_time_total(vf,-1)));
1068
     * gcc 3.x on x86 miscompiled this at optimisation level 2 and above,
1069
     * so this is slightly transformed to make it work.
1070
     */
1071
0
    return(bits*1000/ov_time_total(vf,-1));
1072
0
  }else{
1073
0
    if(vf->seekable){
1074
      /* return the actual bitrate */
1075
0
      return((vf->offsets[i+1]-vf->dataoffsets[i])*8000/ov_time_total(vf,i));
1076
0
    }else{
1077
      /* return nominal if set */
1078
0
      if(vf->vi[i].bitrate_nominal>0){
1079
0
        return vf->vi[i].bitrate_nominal;
1080
0
      }else{
1081
0
        if(vf->vi[i].bitrate_upper>0){
1082
0
          if(vf->vi[i].bitrate_lower>0){
1083
0
            return (vf->vi[i].bitrate_upper+vf->vi[i].bitrate_lower)/2;
1084
0
          }else{
1085
0
            return vf->vi[i].bitrate_upper;
1086
0
          }
1087
0
        }
1088
0
        return(OV_FALSE);
1089
0
      }
1090
0
    }
1091
0
  }
1092
0
}
1093
1094
/* returns the actual bitrate since last call.  returns -1 if no
1095
   additional data to offer since last call (or at beginning of stream),
1096
   EINVAL if stream is only partially open
1097
*/
1098
0
long ov_bitrate_instant(OggVorbis_File *vf){
1099
0
  int link=(vf->seekable?vf->current_link:0);
1100
0
  long ret;
1101
0
  if(vf->ready_state<OPENED)return(OV_EINVAL);
1102
0
  if(vf->samptrack==0)return(OV_FALSE);
1103
0
  ret=vf->bittrack/vf->samptrack*vf->vi[link].rate;
1104
0
  vf->bittrack=0;
1105
0
  vf->samptrack=0;
1106
0
  return(ret);
1107
0
}
1108
1109
/* Guess */
1110
0
long ov_serialnumber(OggVorbis_File *vf,int i){
1111
0
  if(i>=vf->links)return(ov_serialnumber(vf,vf->links-1));
1112
0
  if(!vf->seekable && i>=0)return(ov_serialnumber(vf,-1));
1113
0
  if(i<0){
1114
0
    return(vf->current_serialno);
1115
0
  }else{
1116
0
    return(vf->serialnos[i]);
1117
0
  }
1118
0
}
1119
1120
/* returns: total raw (compressed) length of content if i==-1
1121
            raw (compressed) length of that logical bitstream for i==0 to n
1122
            OV_EINVAL if the stream is not seekable (we can't know the length)
1123
            or if stream is only partially open
1124
*/
1125
0
ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i){
1126
0
  if(vf->ready_state<OPENED)return(OV_EINVAL);
1127
0
  if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
1128
0
  if(i<0){
1129
0
    ogg_int64_t acc=0;
1130
0
    int i;
1131
0
    for(i=0;i<vf->links;i++)
1132
0
      acc+=ov_raw_total(vf,i);
1133
0
    return(acc);
1134
0
  }else{
1135
0
    return(vf->offsets[i+1]-vf->offsets[i]);
1136
0
  }
1137
0
}
1138
1139
/* returns: total PCM length (samples) of content if i==-1 PCM length
1140
            (samples) of that logical bitstream for i==0 to n
1141
            OV_EINVAL if the stream is not seekable (we can't know the
1142
            length) or only partially open
1143
*/
1144
0
ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i){
1145
0
  if(vf->ready_state<OPENED)return(OV_EINVAL);
1146
0
  if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
1147
0
  if(i<0){
1148
0
    ogg_int64_t acc=0;
1149
0
    int i;
1150
0
    for(i=0;i<vf->links;i++)
1151
0
      acc+=ov_pcm_total(vf,i);
1152
0
    return(acc);
1153
0
  }else{
1154
0
    return(vf->pcmlengths[i*2+1]);
1155
0
  }
1156
0
}
1157
1158
/* returns: total milliseconds of content if i==-1
1159
            milliseconds in that logical bitstream for i==0 to n
1160
            OV_EINVAL if the stream is not seekable (we can't know the
1161
            length) or only partially open 
1162
*/
1163
0
ogg_int64_t ov_time_total(OggVorbis_File *vf,int i){
1164
0
  if(vf->ready_state<OPENED)return(OV_EINVAL);
1165
0
  if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
1166
0
  if(i<0){
1167
0
    ogg_int64_t acc=0;
1168
0
    int i;
1169
0
    for(i=0;i<vf->links;i++)
1170
0
      acc+=ov_time_total(vf,i);
1171
0
    return(acc);
1172
0
  }else{
1173
0
    return(((ogg_int64_t)vf->pcmlengths[i*2+1])*1000/vf->vi[i].rate);
1174
0
  }
1175
0
}
1176
1177
/* seek to an offset relative to the *compressed* data. This also
1178
   scans packets to update the PCM cursor. It will cross a logical
1179
   bitstream boundary, but only if it can't get any packets out of the
1180
   tail of the bitstream we seek to (so no surprises).
1181
1182
   returns zero on success, nonzero on failure */
1183
1184
0
int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
1185
0
  ogg_stream_state work_os;
1186
0
  int ret;
1187
1188
0
  if(vf->ready_state<OPENED)return(OV_EINVAL);
1189
0
  if(!vf->seekable)
1190
0
    return(OV_ENOSEEK); /* don't dump machine if we can't seek */
1191
1192
0
  if(pos<0 || pos>vf->end)return(OV_EINVAL);
1193
1194
  /* is the seek position outside our current link [if any]? */
1195
0
  if(vf->ready_state>=STREAMSET){
1196
0
    if(pos<vf->offsets[vf->current_link] || pos>=vf->offsets[vf->current_link+1])
1197
0
      _decode_clear(vf); /* clear out stream state */
1198
0
  }
1199
1200
  /* don't yet clear out decoding machine (if it's initialized), in
1201
     the case we're in the same link.  Restart the decode lapping, and
1202
     let _fetch_and_process_packet deal with a potential bitstream
1203
     boundary */
1204
0
  vf->pcm_offset=-1;
1205
0
  ogg_stream_reset_serialno(&vf->os,
1206
0
                            vf->current_serialno); /* must set serialno */
1207
0
  vorbis_synthesis_restart(&vf->vd);
1208
1209
0
  ret=_seek_helper(vf,pos);
1210
0
  if(ret)goto seek_error;
1211
1212
  /* we need to make sure the pcm_offset is set, but we don't want to
1213
     advance the raw cursor past good packets just to get to the first
1214
     with a granulepos.  That's not equivalent behavior to beginning
1215
     decoding as immediately after the seek position as possible.
1216
1217
     So, a hack.  We use two stream states; a local scratch state and
1218
     the shared vf->os stream state.  We use the local state to
1219
     scan, and the shared state as a buffer for later decode.
1220
1221
     Unfortuantely, on the last page we still advance to last packet
1222
     because the granulepos on the last page is not necessarily on a
1223
     packet boundary, and we need to make sure the granpos is
1224
     correct.
1225
  */
1226
1227
0
  {
1228
0
    ogg_page og;
1229
0
    ogg_packet op;
1230
0
    int lastblock=0;
1231
0
    int accblock=0;
1232
0
    int thisblock=0;
1233
0
    int lastflag=0;
1234
0
    int firstflag=0;
1235
0
    ogg_int64_t pagepos=-1;
1236
1237
0
    ogg_stream_init(&work_os,vf->current_serialno); /* get the memory ready */
1238
0
    ogg_stream_reset(&work_os); /* eliminate the spurious OV_HOLE
1239
                                   return from not necessarily
1240
                                   starting from the beginning */
1241
1242
0
    while(1){
1243
0
      if(vf->ready_state>=STREAMSET){
1244
        /* snarf/scan a packet if we can */
1245
0
        int result=ogg_stream_packetout(&work_os,&op);
1246
1247
0
        if(result>0){
1248
1249
0
          if(vf->vi[vf->current_link].codec_setup){
1250
0
            thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
1251
0
            if(thisblock<0){
1252
0
              ogg_stream_packetout(&vf->os,NULL);
1253
0
              thisblock=0;
1254
0
            }else{
1255
1256
              /* We can't get a guaranteed correct pcm position out of the
1257
                 last page in a stream because it might have a 'short'
1258
                 granpos, which can only be detected in the presence of a
1259
                 preceding page.  However, if the last page is also the first
1260
                 page, the granpos rules of a first page take precedence.  Not
1261
                 only that, but for first==last, the EOS page must be treated
1262
                 as if its a normal first page for the stream to open/play. */
1263
0
              if(lastflag && !firstflag)
1264
0
                ogg_stream_packetout(&vf->os,NULL);
1265
0
              else
1266
0
                if(lastblock)accblock+=(lastblock+thisblock)>>2;
1267
0
            }
1268
1269
0
            if(op.granulepos!=-1){
1270
0
              int i,link=vf->current_link;
1271
0
              ogg_int64_t granulepos=op.granulepos-vf->pcmlengths[link*2];
1272
0
              if(granulepos<0)granulepos=0;
1273
1274
0
              for(i=0;i<link;i++)
1275
0
                granulepos+=vf->pcmlengths[i*2+1];
1276
0
              vf->pcm_offset=granulepos-accblock;
1277
0
              if(vf->pcm_offset<0)vf->pcm_offset=0;
1278
0
              break;
1279
0
            }
1280
0
            lastblock=thisblock;
1281
0
            continue;
1282
0
          }else
1283
0
            ogg_stream_packetout(&vf->os,NULL);
1284
0
        }
1285
0
      }
1286
1287
0
      if(!lastblock){
1288
0
        pagepos=_get_next_page(vf,&og,-1);
1289
0
        if(pagepos<0){
1290
0
          vf->pcm_offset=ov_pcm_total(vf,-1);
1291
0
          break;
1292
0
        }
1293
0
      }else{
1294
        /* huh?  Bogus stream with packets but no granulepos */
1295
0
        vf->pcm_offset=-1;
1296
0
        break;
1297
0
      }
1298
1299
      /* has our decoding just traversed a bitstream boundary? */
1300
0
      if(vf->ready_state>=STREAMSET){
1301
0
        if(vf->current_serialno!=ogg_page_serialno(&og)){
1302
1303
          /* two possibilities:
1304
             1) our decoding just traversed a bitstream boundary
1305
             2) another stream is multiplexed into this logical section? */
1306
1307
0
          if(ogg_page_bos(&og)){
1308
            /* we traversed */
1309
0
            _decode_clear(vf); /* clear out stream state */
1310
0
            ogg_stream_clear(&work_os);
1311
0
          } /* else, do nothing; next loop will scoop another page */
1312
0
        }
1313
0
      }
1314
1315
0
      if(vf->ready_state<STREAMSET){
1316
0
        int link;
1317
0
        ogg_uint32_t serialno = ogg_page_serialno(&og);
1318
1319
0
        for(link=0;link<vf->links;link++)
1320
0
          if(vf->serialnos[link]==serialno)break;
1321
1322
0
        if(link==vf->links) continue; /* not the desired Vorbis
1323
                                         bitstream section; keep
1324
                                         trying */
1325
0
        vf->current_link=link;
1326
0
        vf->current_serialno=serialno;
1327
0
        ogg_stream_reset_serialno(&vf->os,serialno);
1328
0
        ogg_stream_reset_serialno(&work_os,serialno);
1329
0
        vf->ready_state=STREAMSET;
1330
0
        firstflag=(pagepos<=vf->dataoffsets[link]);
1331
0
      }
1332
1333
0
      ogg_stream_pagein(&vf->os,&og);
1334
0
      ogg_stream_pagein(&work_os,&og);
1335
0
      lastflag=ogg_page_eos(&og);
1336
1337
0
    }
1338
0
  }
1339
1340
0
  ogg_stream_clear(&work_os);
1341
0
  vf->bittrack=0;
1342
0
  vf->samptrack=0;
1343
0
  return(0);
1344
1345
0
 seek_error:
1346
  /* dump the machine so we're in a known state */
1347
0
  vf->pcm_offset=-1;
1348
0
  ogg_stream_clear(&work_os);
1349
0
  _decode_clear(vf);
1350
0
  return OV_EBADLINK;
1351
0
}
1352
1353
/* rescales the number x from the range of [0,from] to [0,to]
1354
   x is in the range [0,from]
1355
   from, to are in the range [1, 1<<62-1] */
1356
0
ogg_int64_t rescale64(ogg_int64_t x, ogg_int64_t from, ogg_int64_t to){
1357
0
  ogg_int64_t frac=0;
1358
0
  ogg_int64_t ret=0;
1359
0
  int i;
1360
0
  if(x >= from) return to;
1361
0
  if(x <= 0) return 0;
1362
1363
0
  for(i=0;i<64;i++){
1364
0
    if(x>=from){
1365
0
      frac|=1;
1366
0
      x-=from;
1367
0
    }
1368
0
    x<<=1;
1369
0
    frac<<=1;
1370
0
  }
1371
1372
0
  for(i=0;i<64;i++){
1373
0
    if(frac & 1){
1374
0
      ret+=to;
1375
0
    }
1376
0
    frac>>=1;
1377
0
    ret>>=1;
1378
0
  }
1379
1380
0
  return ret;
1381
0
}
1382
1383
/* Page granularity seek (faster than sample granularity because we
1384
   don't do the last bit of decode to find a specific sample).
1385
1386
   Seek to the last [granule marked] page preceding the specified pos
1387
   location, such that decoding past the returned point will quickly
1388
   arrive at the requested position. */
1389
0
int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
1390
0
  int link=-1;
1391
0
  ogg_int64_t result=0;
1392
0
  ogg_int64_t total=ov_pcm_total(vf,-1);
1393
1394
0
  if(vf->ready_state<OPENED)return(OV_EINVAL);
1395
0
  if(!vf->seekable)return(OV_ENOSEEK);
1396
1397
0
  if(pos<0 || pos>total)return(OV_EINVAL);
1398
1399
  /* which bitstream section does this pcm offset occur in? */
1400
0
  for(link=vf->links-1;link>=0;link--){
1401
0
    total-=vf->pcmlengths[link*2+1];
1402
0
    if(pos>=total)break;
1403
0
  }
1404
1405
  /* Search within the logical bitstream for the page with the highest
1406
     pcm_pos preceding pos.  If we're looking for a position on the
1407
     first page, bisection will halt without finding our position as
1408
     it's before the first explicit granulepos fencepost. That case is
1409
     handled separately below.
1410
1411
     There is a danger here; missing pages or incorrect frame number
1412
     information in the bitstream could make our task impossible.
1413
     Account for that (it would be an error condition) */
1414
1415
  /* new search algorithm originally by HB (Nicholas Vinen) */
1416
1417
0
  {
1418
0
    ogg_int64_t end=vf->offsets[link+1];
1419
0
    ogg_int64_t begin=vf->dataoffsets[link];
1420
0
    ogg_int64_t begintime = vf->pcmlengths[link*2];
1421
0
    ogg_int64_t endtime = vf->pcmlengths[link*2+1]+begintime;
1422
0
    ogg_int64_t target=pos-total+begintime;
1423
0
    ogg_int64_t best=-1;
1424
0
    int         got_page=0;
1425
1426
0
    ogg_page og;
1427
1428
    /* if we have only one page, there will be no bisection.  Grab the page here */
1429
0
    if(begin==end){
1430
0
      result=_seek_helper(vf,begin);
1431
0
      if(result) goto seek_error;
1432
1433
0
      result=_get_next_page(vf,&og,1);
1434
0
      if(result<0) goto seek_error;
1435
1436
0
      got_page=1;
1437
0
    }
1438
1439
    /* bisection loop */
1440
0
    while(begin<end){
1441
0
      ogg_int64_t bisect;
1442
1443
0
      if(end-begin<CHUNKSIZE){
1444
0
        bisect=begin;
1445
0
      }else{
1446
        /* take a (pretty decent) guess. */
1447
0
        bisect=begin + rescale64(target-begintime,
1448
0
         endtime-begintime,
1449
0
         end-begin) - CHUNKSIZE;
1450
0
        if(bisect<begin+CHUNKSIZE)
1451
0
          bisect=begin;
1452
0
      }
1453
1454
0
      result=_seek_helper(vf,bisect);
1455
0
      if(result) goto seek_error;
1456
1457
      /* read loop within the bisection loop */
1458
0
      while(begin<end){
1459
0
        result=_get_next_page(vf,&og,end-vf->offset);
1460
0
        if(result==OV_EREAD) goto seek_error;
1461
0
        if(result<0){
1462
          /* there is no next page! */
1463
0
          if(bisect<=begin+1)
1464
            /* No bisection left to perform.  We've either found the
1465
               best candidate already or failed. Exit loop. */
1466
0
            end=begin;
1467
0
          else{
1468
            /* We tried to load a fraction of the last page; back up a
1469
               bit and try to get the whole last page */
1470
0
            if(bisect==0) goto seek_error;
1471
0
            bisect-=CHUNKSIZE;
1472
1473
            /* don't repeat/loop on a read we've already performed */
1474
0
            if(bisect<=begin)bisect=begin+1;
1475
1476
            /* seek and continue bisection */
1477
0
            result=_seek_helper(vf,bisect);
1478
0
            if(result) goto seek_error;
1479
0
          }
1480
0
        }else{
1481
0
          ogg_int64_t granulepos;
1482
0
          got_page=1;
1483
1484
          /* got a page. analyze it */
1485
          /* only consider pages from primary vorbis stream */
1486
0
          if(ogg_page_serialno(&og)!=vf->serialnos[link])
1487
0
            continue;
1488
1489
          /* only consider pages with the granulepos set */
1490
0
          granulepos=ogg_page_granulepos(&og);
1491
0
          if(granulepos==-1)continue;
1492
1493
0
          if(granulepos<target){
1494
            /* this page is a successful candidate! Set state */
1495
1496
0
            best=result;  /* raw offset of packet with granulepos */
1497
0
            begin=vf->offset; /* raw offset of next page */
1498
0
            begintime=granulepos;
1499
1500
            /* if we're before our target but within a short distance,
1501
               don't bisect; read forward */
1502
0
            if(target-begintime>44100)break;
1503
1504
0
            bisect=begin; /* *not* begin + 1 as above */
1505
0
          }else{
1506
1507
            /* This is one of our pages, but the granpos is
1508
               post-target; it is not a bisection return
1509
               candidate. (The only way we'd use it is if it's the
1510
               first page in the stream; we handle that case later
1511
               outside the bisection) */
1512
0
            if(bisect<=begin+1){
1513
              /* No bisection left to perform.  We've either found the
1514
                 best candidate already or failed. Exit loop. */
1515
0
              end=begin;
1516
0
            }else{
1517
0
              if(end==vf->offset){
1518
                /* bisection read to the end; use the known page
1519
                   boundary (result) to update bisection, back up a
1520
                   little bit, and try again */
1521
0
                end=result;
1522
0
                bisect-=CHUNKSIZE;
1523
0
                if(bisect<=begin)bisect=begin+1;
1524
0
                result=_seek_helper(vf,bisect);
1525
0
                if(result) goto seek_error;
1526
0
              }else{
1527
                /* Normal bisection */
1528
0
                end=bisect;
1529
0
                endtime=granulepos;
1530
0
                break;
1531
0
              }
1532
0
            }
1533
0
          }
1534
0
        }
1535
0
      }
1536
0
    }
1537
1538
    /* Out of bisection: did it 'fail?' */
1539
0
    if(best == -1){
1540
1541
      /* Check the 'looking for data in first page' special case;
1542
         bisection would 'fail' because our search target was before the
1543
         first PCM granule position fencepost. */
1544
1545
0
      if(got_page &&
1546
0
         begin == vf->dataoffsets[link] &&
1547
0
         ogg_page_serialno(&og)==vf->serialnos[link]){
1548
1549
        /* Yes, this is the beginning-of-stream case. We already have
1550
           our page, right at the beginning of PCM data.  Set state
1551
           and return. */
1552
1553
0
        vf->pcm_offset=total;
1554
1555
0
        if(link!=vf->current_link){
1556
          /* Different link; dump entire decode machine */
1557
0
          _decode_clear(vf);
1558
1559
0
          vf->current_link=link;
1560
0
          vf->current_serialno=vf->serialnos[link];
1561
0
          vf->ready_state=STREAMSET;
1562
1563
0
        }else{
1564
0
          vorbis_synthesis_restart(&vf->vd);
1565
0
        }
1566
1567
0
        ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
1568
0
        ogg_stream_pagein(&vf->os,&og);
1569
1570
0
      }else
1571
0
        goto seek_error;
1572
1573
0
    }else{
1574
1575
      /* Bisection found our page. seek to it, update pcm offset. Easier case than
1576
         raw_seek, don't keep packets preceding granulepos. */
1577
1578
0
      ogg_page og;
1579
0
      ogg_packet op;
1580
1581
      /* seek */
1582
0
      result=_seek_helper(vf,best);
1583
0
      vf->pcm_offset=-1;
1584
0
      if(result) goto seek_error;
1585
0
      result=_get_next_page(vf,&og,-1);
1586
0
      if(result<0) goto seek_error;
1587
1588
0
      if(link!=vf->current_link){
1589
        /* Different link; dump entire decode machine */
1590
0
        _decode_clear(vf);
1591
1592
0
        vf->current_link=link;
1593
0
        vf->current_serialno=vf->serialnos[link];
1594
0
        vf->ready_state=STREAMSET;
1595
1596
0
      }else{
1597
0
        vorbis_synthesis_restart(&vf->vd);
1598
0
      }
1599
1600
0
      ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
1601
0
      ogg_stream_pagein(&vf->os,&og);
1602
1603
      /* pull out all but last packet; the one with granulepos */
1604
0
      while(1){
1605
0
        result=ogg_stream_packetpeek(&vf->os,&op);
1606
0
        if(result==0){
1607
          /* No packet returned; we exited the bisection with 'best'
1608
             pointing to a page with a granule position, so the packet
1609
             finishing this page ('best') originated on a preceding
1610
             page. Keep fetching previous pages until we get one with
1611
             a granulepos or without the 'continued' flag set.  Then
1612
             just use raw_seek for simplicity. */
1613
          /* Do not rewind past the beginning of link data; if we do,
1614
             it's either a bug or a broken stream */
1615
0
          result=best;
1616
0
          while(result>vf->dataoffsets[link]){
1617
0
            result=_get_prev_page(vf,result,&og);
1618
0
            if(result<0) goto seek_error;
1619
0
            if(ogg_page_serialno(&og)==vf->current_serialno &&
1620
0
               (ogg_page_granulepos(&og)>-1 ||
1621
0
                !ogg_page_continued(&og))){
1622
0
              return ov_raw_seek(vf,result);
1623
0
            }
1624
0
          }
1625
0
        }
1626
0
        if(result<0){
1627
0
          result = OV_EBADPACKET;
1628
0
          goto seek_error;
1629
0
        }
1630
0
        if(op.granulepos!=-1){
1631
0
          vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];
1632
0
          if(vf->pcm_offset<0)vf->pcm_offset=0;
1633
0
          vf->pcm_offset+=total;
1634
0
          break;
1635
0
        }else
1636
0
          result=ogg_stream_packetout(&vf->os,NULL);
1637
0
      }
1638
0
    }
1639
0
  }
1640
1641
  /* verify result */
1642
0
  if(vf->pcm_offset>pos || pos>ov_pcm_total(vf,-1)){
1643
0
    result=OV_EFAULT;
1644
0
    goto seek_error;
1645
0
  }
1646
0
  vf->bittrack=0;
1647
0
  vf->samptrack=0;
1648
0
  return(0);
1649
1650
0
 seek_error:
1651
  /* dump machine so we're in a known state */
1652
0
  vf->pcm_offset=-1;
1653
0
  _decode_clear(vf);
1654
0
  return (int)result;
1655
0
}
1656
1657
/* seek to a sample offset relative to the decompressed pcm stream
1658
   returns zero on success, nonzero on failure */
1659
1660
0
int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
1661
0
  int thisblock,lastblock=0;
1662
0
  int ret=ov_pcm_seek_page(vf,pos);
1663
0
  if(ret<0)return(ret);
1664
0
  if((ret=_make_decode_ready(vf)))return ret;
1665
1666
  /* discard leading packets we don't need for the lapping of the
1667
     position we want; don't decode them */
1668
1669
0
  while(1){
1670
0
    ogg_packet op;
1671
0
    ogg_page og;
1672
1673
0
    int ret=ogg_stream_packetpeek(&vf->os,&op);
1674
0
    if(ret>0){
1675
0
      thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
1676
0
      if(thisblock<0){
1677
0
        ogg_stream_packetout(&vf->os,NULL);
1678
0
        continue; /* non audio packet */
1679
0
      }
1680
0
      if(lastblock)vf->pcm_offset+=(lastblock+thisblock)>>2;
1681
1682
0
      if(vf->pcm_offset+((thisblock+
1683
0
                          vorbis_info_blocksize(vf->vi,1))>>2)>=pos)break;
1684
1685
      /* remove the packet from packet queue and track its granulepos */
1686
0
      ogg_stream_packetout(&vf->os,NULL);
1687
0
      vorbis_synthesis_trackonly(&vf->vb,&op);  /* set up a vb with
1688
                                                   only tracking, no
1689
                                                   pcm_decode */
1690
0
      vorbis_synthesis_blockin(&vf->vd,&vf->vb);
1691
1692
      /* end of logical stream case is hard, especially with exact
1693
         length positioning. */
1694
1695
0
      if(op.granulepos>-1){
1696
0
        int i;
1697
        /* always believe the stream markers */
1698
0
        vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];
1699
0
        if(vf->pcm_offset<0)vf->pcm_offset=0;
1700
0
        for(i=0;i<vf->current_link;i++)
1701
0
          vf->pcm_offset+=vf->pcmlengths[i*2+1];
1702
0
      }
1703
1704
0
      lastblock=thisblock;
1705
1706
0
    }else{
1707
0
      if(ret<0 && ret!=OV_HOLE)break;
1708
1709
      /* suck in a new page */
1710
0
      if(_get_next_page(vf,&og,-1)<0)break;
1711
0
      if(ogg_page_bos(&og))_decode_clear(vf);
1712
1713
0
      if(vf->ready_state<STREAMSET){
1714
0
        ogg_uint32_t serialno=ogg_page_serialno(&og);
1715
0
        int link;
1716
1717
0
        for(link=0;link<vf->links;link++)
1718
0
          if(vf->serialnos[link]==serialno)break;
1719
0
        if(link==vf->links) continue;
1720
0
        vf->current_link=link;
1721
1722
0
        vf->ready_state=STREAMSET;
1723
0
        vf->current_serialno=ogg_page_serialno(&og);
1724
0
        ogg_stream_reset_serialno(&vf->os,serialno);
1725
0
        ret=_make_decode_ready(vf);
1726
0
        if(ret)return ret;
1727
0
        lastblock=0;
1728
0
      }
1729
1730
0
      ogg_stream_pagein(&vf->os,&og);
1731
0
    }
1732
0
  }
1733
1734
0
  vf->bittrack=0;
1735
0
  vf->samptrack=0;
1736
  /* discard samples until we reach the desired position. Crossing a
1737
     logical bitstream boundary with abandon is OK. */
1738
0
  while(vf->pcm_offset<pos){
1739
0
    ogg_int64_t target=pos-vf->pcm_offset;
1740
0
    long samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
1741
1742
0
    if(samples>target)samples=target;
1743
0
    vorbis_synthesis_read(&vf->vd,samples);
1744
0
    vf->pcm_offset+=samples;
1745
1746
0
    if(samples<target)
1747
0
      if(_fetch_and_process_packet(vf,NULL,1,1)<=0)
1748
0
        vf->pcm_offset=ov_pcm_total(vf,-1); /* eof */
1749
0
  }
1750
0
  return 0;
1751
0
}
1752
1753
/* seek to a playback time relative to the decompressed pcm stream
1754
   returns zero on success, nonzero on failure */
1755
0
int ov_time_seek(OggVorbis_File *vf,ogg_int64_t milliseconds){
1756
  /* translate time to PCM position and call ov_pcm_seek */
1757
1758
0
  int link=-1;
1759
0
  ogg_int64_t pcm_total=0;
1760
0
  ogg_int64_t time_total=0;
1761
1762
0
  if(vf->ready_state<OPENED)return(OV_EINVAL);
1763
0
  if(!vf->seekable)return(OV_ENOSEEK);
1764
0
  if(milliseconds<0)return(OV_EINVAL);
1765
1766
  /* which bitstream section does this time offset occur in? */
1767
0
  for(link=0;link<vf->links;link++){
1768
0
    ogg_int64_t addsec = ov_time_total(vf,link);
1769
0
    if(milliseconds<time_total+addsec)break;
1770
0
    time_total+=addsec;
1771
0
    pcm_total+=vf->pcmlengths[link*2+1];
1772
0
  }
1773
1774
0
  if(link==vf->links)return(OV_EINVAL);
1775
1776
  /* enough information to convert time offset to pcm offset */
1777
0
  {
1778
0
    ogg_int64_t target=pcm_total+(milliseconds-time_total)*vf->vi[link].rate/1000;
1779
0
    return(ov_pcm_seek(vf,target));
1780
0
  }
1781
0
}
1782
1783
/* page-granularity version of ov_time_seek 
1784
   returns zero on success, nonzero on failure */
1785
0
int ov_time_seek_page(OggVorbis_File *vf,ogg_int64_t milliseconds){
1786
  /* translate time to PCM position and call ov_pcm_seek */
1787
1788
0
  int link=-1;
1789
0
  ogg_int64_t pcm_total=0;
1790
0
  ogg_int64_t time_total=0;
1791
1792
0
  if(vf->ready_state<OPENED)return(OV_EINVAL);
1793
0
  if(!vf->seekable)return(OV_ENOSEEK);
1794
0
  if(milliseconds<0)return(OV_EINVAL);
1795
1796
  /* which bitstream section does this time offset occur in? */
1797
0
  for(link=0;link<vf->links;link++){
1798
0
    ogg_int64_t addsec = ov_time_total(vf,link);
1799
0
    if(milliseconds<time_total+addsec)break;
1800
0
    time_total+=addsec;
1801
0
    pcm_total+=vf->pcmlengths[link*2+1];
1802
0
  }
1803
1804
0
  if(link==vf->links)return(OV_EINVAL);
1805
1806
  /* enough information to convert time offset to pcm offset */
1807
0
  {
1808
0
    ogg_int64_t target=pcm_total+(milliseconds-time_total)*vf->vi[link].rate/1000;
1809
0
    return(ov_pcm_seek_page(vf,target));
1810
0
  }
1811
0
}
1812
1813
/* tell the current stream offset cursor.  Note that seek followed by
1814
   tell will likely not give the set offset due to caching */
1815
0
ogg_int64_t ov_raw_tell(OggVorbis_File *vf){
1816
0
  if(vf->ready_state<OPENED)return(OV_EINVAL);
1817
0
  return(vf->offset);
1818
0
}
1819
1820
/* return PCM offset (sample) of next PCM sample to be read */
1821
0
ogg_int64_t ov_pcm_tell(OggVorbis_File *vf){
1822
0
  if(vf->ready_state<OPENED)return(OV_EINVAL);
1823
0
  return(vf->pcm_offset);
1824
0
}
1825
1826
/* return time offset (milliseconds) of next PCM sample to be read */
1827
0
ogg_int64_t ov_time_tell(OggVorbis_File *vf){
1828
0
  int link=0;
1829
0
  ogg_int64_t pcm_total=0;
1830
0
  ogg_int64_t time_total=0;
1831
1832
0
  if(vf->ready_state<OPENED)return(OV_EINVAL);
1833
0
  if(vf->seekable){
1834
0
    pcm_total=ov_pcm_total(vf,-1);
1835
0
    time_total=ov_time_total(vf,-1);
1836
1837
    /* which bitstream section does this time offset occur in? */
1838
0
    for(link=vf->links-1;link>=0;link--){
1839
0
      pcm_total-=vf->pcmlengths[link*2+1];
1840
0
      time_total-=ov_time_total(vf,link);
1841
0
      if(vf->pcm_offset>=pcm_total)break;
1842
0
    }
1843
0
  }
1844
1845
0
  return(time_total+(1000*vf->pcm_offset-pcm_total)/vf->vi[link].rate);
1846
0
}
1847
1848
/*  link:   -1) return the vorbis_info struct for the bitstream section
1849
                currently being decoded
1850
           0-n) to request information for a specific bitstream section
1851
1852
    In the case of a non-seekable bitstream, any call returns the
1853
    current bitstream.  NULL in the case that the machine is not
1854
    initialized */
1855
1856
1.41M
vorbis_info *ov_info(OggVorbis_File *vf,int link){
1857
1.41M
  if(vf->seekable){
1858
0
    if(link<0)
1859
0
      if(vf->ready_state>=STREAMSET)
1860
0
        return vf->vi+vf->current_link;
1861
0
      else
1862
0
      return vf->vi;
1863
0
    else
1864
0
      if(link>=vf->links)
1865
0
        return NULL;
1866
0
      else
1867
0
        return vf->vi+link;
1868
1.41M
  }else{
1869
1.41M
    return vf->vi;
1870
1.41M
  }
1871
1.41M
}
1872
1873
/* grr, strong typing, grr, no templates/inheritence, grr */
1874
0
vorbis_comment *ov_comment(OggVorbis_File *vf,int link){
1875
0
  if(vf->seekable){
1876
0
    if(link<0)
1877
0
      if(vf->ready_state>=STREAMSET)
1878
0
        return vf->vc+vf->current_link;
1879
0
      else
1880
0
        return vf->vc;
1881
0
    else
1882
0
      if(link>=vf->links)
1883
0
        return NULL;
1884
0
      else
1885
0
        return vf->vc+link;
1886
0
  }else{
1887
0
    return vf->vc;
1888
0
  }
1889
0
}
1890
1891
/* up to this point, everything could more or less hide the multiple
1892
   logical bitstream nature of chaining from the toplevel application
1893
   if the toplevel application didn't particularly care.  However, at
1894
   the point that we actually read audio back, the multiple-section
1895
   nature must surface: Multiple bitstream sections do not necessarily
1896
   have to have the same number of channels or sampling rate.
1897
1898
   ov_read returns the sequential logical bitstream number currently
1899
   being decoded along with the PCM data in order that the toplevel
1900
   application can take action on channel/sample rate changes.  This
1901
   number will be incremented even for streamed (non-seekable) streams
1902
   (for seekable streams, it represents the actual logical bitstream
1903
   index within the physical bitstream.  Note that the accessor
1904
   functions above are aware of this dichotomy).
1905
1906
   input values: buffer) a buffer to hold packed PCM data for return
1907
                 bytes_req) the byte length requested to be placed into buffer
1908
1909
   return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL)
1910
                   0) EOF
1911
                   n) number of bytes of PCM actually returned.  The
1912
                   below works on a packet-by-packet basis, so the
1913
                   return length is not related to the 'length' passed
1914
                   in, just guaranteed to fit.
1915
1916
            *section) set to the logical bitstream number */
1917
1918
1.42M
long ov_read(OggVorbis_File *vf,char *buffer,int bytes_req,int *bitstream){
1919
1.42M
  int i,j;
1920
1921
1.42M
  ogg_int32_t **pcm;
1922
1.42M
  long samples;
1923
1924
1.42M
  if(vf->ready_state<OPENED)return(OV_EINVAL);
1925
1926
1.45M
  while(1){
1927
1.45M
    if(vf->ready_state==INITSET){
1928
1.45M
      samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
1929
1.45M
      if(samples)break;
1930
1.45M
    }
1931
1932
    /* suck in another packet */
1933
43.3k
    {
1934
43.3k
      int ret=_fetch_and_process_packet(vf,NULL,1,1);
1935
43.3k
      if(ret==OV_EOF)
1936
2.06k
        return(0);
1937
41.2k
      if(ret<=0)
1938
8.81k
        return(ret);
1939
41.2k
    }
1940
1941
41.2k
  }
1942
1943
1.41M
  if(samples>0){
1944
1945
    /* yay! proceed to pack data into the byte buffer */
1946
1947
1.41M
    long channels=ov_info(vf,-1)->channels;
1948
1949
1.41M
    if(samples>(bytes_req/(2*channels)))
1950
1.38M
      samples=bytes_req/(2*channels);
1951
1952
313M
    for(i=0;i<channels;i++) { /* It's faster in this order */
1953
312M
      ogg_int32_t *src=pcm[i];
1954
312M
      short *dest=((short *)buffer)+i;
1955
3.07G
      for(j=0;j<samples;j++) {
1956
2.76G
        *dest=CLIP_TO_15(src[j]>>9);
1957
2.76G
        dest+=channels;
1958
2.76G
      }
1959
312M
    }
1960
1961
1.41M
    vorbis_synthesis_read(&vf->vd,samples);
1962
1.41M
    vf->pcm_offset+=samples;
1963
1.41M
    if(bitstream)*bitstream=vf->current_link;
1964
1.41M
    return(samples*2*channels);
1965
1.41M
  }else{
1966
0
    return(samples);
1967
0
  }
1968
1.41M
}