• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-2003    *
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: vorbisfile.c,v 1.6.2.5 2003/11/20 06:16:17 xiphmont Exp $
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 "codec_internal.h"
26 #include "ivorbisfile.h"
27 
28 #include "os.h"
29 #include "misc.h"
30 
31 #define  NOTOPEN   0
32 #define  PARTOPEN  1
33 #define  OPENED    2
34 #define  STREAMSET 3 /* serialno and link set, but not to current link */
35 #define  LINKSET   4 /* serialno and link set to current link */
36 #define  INITSET   5
37 
38 /* A 'chained bitstream' is a Vorbis bitstream that contains more than
39    one logical bitstream arranged end to end (the only form of Ogg
40    multiplexing allowed in a Vorbis bitstream; grouping [parallel
41    multiplexing] is not allowed in Vorbis) */
42 
43 /* A Vorbis file can be played beginning to end (streamed) without
44    worrying ahead of time about chaining (see decoder_example.c).  If
45    we have the whole file, however, and want random access
46    (seeking/scrubbing) or desire to know the total length/time of a
47    file, we need to account for the possibility of chaining. */
48 
49 /* We can handle things a number of ways; we can determine the entire
50    bitstream structure right off the bat, or find pieces on demand.
51    This example determines and caches structure for the entire
52    bitstream, but builds a virtual decoder on the fly when moving
53    between links in the chain. */
54 
55 /* There are also different ways to implement seeking.  Enough
56    information exists in an Ogg bitstream to seek to
57    sample-granularity positions in the output.  Or, one can seek by
58    picking some portion of the stream roughly in the desired area if
59    we only want coarse navigation through the stream. */
60 
61 /*************************************************************************
62  * Many, many internal helpers.  The intention is not to be confusing;
63  * rampant duplication and monolithic function implementation would be
64  * harder to understand anyway.  The high level functions are last.  Begin
65  * grokking near the end of the file */
66 
67 
68 /* read a little more data from the file/pipe into the ogg_sync framer */
_get_data(OggVorbis_File * vf)69 static long _get_data(OggVorbis_File *vf){
70   errno=0;
71   if(vf->datasource){
72     unsigned char *buffer=ogg_sync_bufferin(vf->oy,CHUNKSIZE);
73     long bytes=(vf->callbacks.read_func)(buffer,1,CHUNKSIZE,vf->datasource);
74     if(bytes>0)ogg_sync_wrote(vf->oy,bytes);
75     if(bytes==0 && errno)return -1;
76     return bytes;
77   }else
78     return 0;
79 }
80 
81 /* save a tiny smidge of verbosity to make the code more readable */
_seek_helper(OggVorbis_File * vf,ogg_int64_t offset)82 static void _seek_helper(OggVorbis_File *vf,ogg_int64_t offset){
83   if(vf->datasource){
84     (vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET);
85     vf->offset=offset;
86     ogg_sync_reset(vf->oy);
87   }else{
88     /* shouldn't happen unless someone writes a broken callback */
89     return;
90   }
91 }
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               produces a refcounted page */
107 
_get_next_page(OggVorbis_File * vf,ogg_page * og,ogg_int64_t boundary)108 static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og,
109 				  ogg_int64_t boundary){
110   if(boundary>0)boundary+=vf->offset;
111   while(1){
112     long more;
113 
114     if(boundary>0 && vf->offset>=boundary)return OV_FALSE;
115     more=ogg_sync_pageseek(vf->oy,og);
116 
117     if(more<0){
118       /* skipped n bytes */
119       vf->offset-=more;
120     }else{
121       if(more==0){
122 	/* send more paramedics */
123 	if(!boundary)return OV_FALSE;
124 	{
125 	  long ret=_get_data(vf);
126 	  if(ret==0)return OV_EOF;
127 	  if(ret<0)return OV_EREAD;
128 	}
129       }else{
130 	/* got a page.  Return the offset at the page beginning,
131            advance the internal offset past the page end */
132 	ogg_int64_t ret=vf->offset;
133 	vf->offset+=more;
134 	return ret;
135 
136       }
137     }
138   }
139 }
140 
141 /* find the latest page beginning before the current stream cursor
142    position. Much dirtier than the above as Ogg doesn't have any
143    backward search linkage.  no 'readp' as it will certainly have to
144    read. */
145 /* returns offset or OV_EREAD, OV_FAULT and produces a refcounted page */
146 
_get_prev_page(OggVorbis_File * vf,ogg_page * og)147 static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_page *og){
148   ogg_int64_t begin=vf->offset;
149   ogg_int64_t end=begin;
150   ogg_int64_t ret;
151   ogg_int64_t offset=-1;
152 
153   while(offset==-1){
154     begin-=CHUNKSIZE;
155     if(begin<0)
156       begin=0;
157     _seek_helper(vf,begin);
158     while(vf->offset<end){
159       ret=_get_next_page(vf,og,end-vf->offset);
160       if(ret==OV_EREAD)return OV_EREAD;
161       if(ret<0){
162 	break;
163       }else{
164 	offset=ret;
165       }
166     }
167   }
168 
169   /* we have the offset.  Actually snork and hold the page now */
170   _seek_helper(vf,offset);
171   ret=_get_next_page(vf,og,CHUNKSIZE);
172   if(ret<0)
173     /* this shouldn't be possible */
174     return OV_EFAULT;
175 
176   return offset;
177 }
178 
179 /* finds each bitstream link one at a time using a bisection search
180    (has to begin by knowing the offset of the lb's initial page).
181    Recurses for each link so it can alloc the link storage after
182    finding them all, then unroll and fill the cache at the same time */
_bisect_forward_serialno(OggVorbis_File * vf,ogg_int64_t begin,ogg_int64_t searched,ogg_int64_t end,ogg_uint32_t currentno,long m)183 static int _bisect_forward_serialno(OggVorbis_File *vf,
184 				    ogg_int64_t begin,
185 				    ogg_int64_t searched,
186 				    ogg_int64_t end,
187 				    ogg_uint32_t currentno,
188 				    long m){
189   ogg_int64_t endsearched=end;
190   ogg_int64_t next=end;
191   ogg_page og={0,0,0,0};
192   ogg_int64_t ret;
193 
194   /* the below guards against garbage seperating the last and
195      first pages of two links. */
196   while(searched<endsearched){
197     ogg_int64_t bisect;
198 
199     if(endsearched-searched<CHUNKSIZE){
200       bisect=searched;
201     }else{
202       bisect=(searched+endsearched)/2;
203     }
204 
205     _seek_helper(vf,bisect);
206     ret=_get_next_page(vf,&og,-1);
207     if(ret==OV_EREAD)return OV_EREAD;
208     if(ret<0 || ogg_page_serialno(&og)!=currentno){
209       endsearched=bisect;
210       if(ret>=0)next=ret;
211     }else{
212       searched=ret+og.header_len+og.body_len;
213     }
214     ogg_page_release(&og);
215   }
216 
217   _seek_helper(vf,next);
218   ret=_get_next_page(vf,&og,-1);
219   if(ret==OV_EREAD)return OV_EREAD;
220 
221   if(searched>=end || ret<0){
222     ogg_page_release(&og);
223     vf->links=m+1;
224     vf->offsets=_ogg_malloc((vf->links+1)*sizeof(*vf->offsets));
225     vf->serialnos=_ogg_malloc(vf->links*sizeof(*vf->serialnos));
226     vf->offsets[m+1]=searched;
227   }else{
228     ret=_bisect_forward_serialno(vf,next,vf->offset,
229 				 end,ogg_page_serialno(&og),m+1);
230     ogg_page_release(&og);
231     if(ret==OV_EREAD)return OV_EREAD;
232   }
233 
234   vf->offsets[m]=begin;
235   vf->serialnos[m]=currentno;
236   return 0;
237 }
238 
_decode_clear(OggVorbis_File * vf)239 static int _decode_clear(OggVorbis_File *vf){
240   if(vf->ready_state==INITSET){
241     vorbis_dsp_destroy(vf->vd);
242     vf->vd=0;
243     vf->ready_state=STREAMSET;
244   }
245 
246   if(vf->ready_state>=STREAMSET){
247     vorbis_info_clear(&vf->vi);
248     vorbis_comment_clear(&vf->vc);
249     vf->ready_state=OPENED;
250   }
251   return 0;
252 }
253 
254 /* uses the local ogg_stream storage in vf; this is important for
255    non-streaming input sources */
256 /* consumes the page that's passed in (if any) */
257 /* state is LINKSET upon successful return */
258 
_fetch_headers(OggVorbis_File * vf,vorbis_info * vi,vorbis_comment * vc,ogg_uint32_t * serialno,ogg_page * og_ptr)259 static int _fetch_headers(OggVorbis_File *vf,
260 			  vorbis_info *vi,
261 			  vorbis_comment *vc,
262 			  ogg_uint32_t *serialno,
263 			  ogg_page *og_ptr){
264   ogg_page og={0,0,0,0};
265   ogg_packet op={0,0,0,0,0,0};
266   int i,ret;
267 
268   if(vf->ready_state>OPENED)_decode_clear(vf);
269 
270   if(!og_ptr){
271     ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE);
272     if(llret==OV_EREAD)return OV_EREAD;
273     if(llret<0)return OV_ENOTVORBIS;
274     og_ptr=&og;
275   }
276 
277   ogg_stream_reset_serialno(vf->os,ogg_page_serialno(og_ptr));
278   if(serialno)*serialno=vf->os->serialno;
279 
280   /* extract the initial header from the first page and verify that the
281      Ogg bitstream is in fact Vorbis data */
282 
283   vorbis_info_init(vi);
284   vorbis_comment_init(vc);
285 
286   i=0;
287   while(i<3){
288     ogg_stream_pagein(vf->os,og_ptr);
289     while(i<3){
290       int result=ogg_stream_packetout(vf->os,&op);
291       if(result==0)break;
292       if(result==-1){
293 	ret=OV_EBADHEADER;
294 	goto bail_header;
295       }
296       if((ret=vorbis_dsp_headerin(vi,vc,&op))){
297 	goto bail_header;
298       }
299       i++;
300     }
301     if(i<3)
302       if(_get_next_page(vf,og_ptr,CHUNKSIZE)<0){
303 	ret=OV_EBADHEADER;
304 	goto bail_header;
305       }
306   }
307 
308   ogg_packet_release(&op);
309   ogg_page_release(&og);
310   vf->ready_state=LINKSET;
311   return 0;
312 
313  bail_header:
314   ogg_packet_release(&op);
315   ogg_page_release(&og);
316   vorbis_info_clear(vi);
317   vorbis_comment_clear(vc);
318   vf->ready_state=OPENED;
319 
320   return ret;
321 }
322 
323 /* we no longer preload all vorbis_info (and the associated
324    codec_setup) structs.  Call this to seek and fetch the info from
325    the bitstream, if needed */
_set_link_number(OggVorbis_File * vf,int link)326 static int _set_link_number(OggVorbis_File *vf,int link){
327   if(link != vf->current_link) _decode_clear(vf);
328   if(vf->ready_state<STREAMSET){
329     _seek_helper(vf,vf->offsets[link]);
330     ogg_stream_reset_serialno(vf->os,vf->serialnos[link]);
331     vf->current_serialno=vf->serialnos[link];
332     vf->current_link=link;
333     return _fetch_headers(vf,&vf->vi,&vf->vc,&vf->current_serialno,NULL);
334   }
335   return 0;
336 }
337 
_set_link_number_preserve_pos(OggVorbis_File * vf,int link)338 static int _set_link_number_preserve_pos(OggVorbis_File *vf,int link){
339   ogg_int64_t pos=vf->offset;
340   int ret=_set_link_number(vf,link);
341   if(ret)return ret;
342   _seek_helper(vf,pos);
343   if(pos<vf->offsets[link] || pos>=vf->offsets[link+1])
344     vf->ready_state=STREAMSET;
345   return 0;
346 }
347 
348 /* last step of the OggVorbis_File initialization; get all the offset
349    positions.  Only called by the seekable initialization (local
350    stream storage is hacked slightly; pay attention to how that's
351    done) */
352 
353 /* this is void and does not propogate errors up because we want to be
354    able to open and use damaged bitstreams as well as we can.  Just
355    watch out for missing information for links in the OggVorbis_File
356    struct */
_prefetch_all_offsets(OggVorbis_File * vf,ogg_int64_t dataoffset)357 static void _prefetch_all_offsets(OggVorbis_File *vf, ogg_int64_t dataoffset){
358   ogg_page og={0,0,0,0};
359   int i;
360   ogg_int64_t ret;
361 
362   vf->dataoffsets=_ogg_malloc(vf->links*sizeof(*vf->dataoffsets));
363   vf->pcmlengths=_ogg_malloc(vf->links*2*sizeof(*vf->pcmlengths));
364 
365   for(i=0;i<vf->links;i++){
366     if(i==0){
367       /* we already grabbed the initial header earlier.  Just set the offset */
368       vf->dataoffsets[i]=dataoffset;
369       _seek_helper(vf,dataoffset);
370 
371     }else{
372 
373       /* seek to the location of the initial header */
374 
375       _seek_helper(vf,vf->offsets[i]);
376       if(_fetch_headers(vf,&vf->vi,&vf->vc,NULL,NULL)<0){
377     	vf->dataoffsets[i]=-1;
378       }else{
379 	vf->dataoffsets[i]=vf->offset;
380       }
381     }
382 
383     /* fetch beginning PCM offset */
384 
385     if(vf->dataoffsets[i]!=-1){
386       ogg_int64_t accumulated=0,pos;
387       long        lastblock=-1;
388       int         result;
389 
390       ogg_stream_reset_serialno(vf->os,vf->serialnos[i]);
391 
392       while(1){
393 	ogg_packet op={0,0,0,0,0,0};
394 
395 	ret=_get_next_page(vf,&og,-1);
396 	if(ret<0)
397 	  /* this should not be possible unless the file is
398              truncated/mangled */
399 	  break;
400 
401 	if(ogg_page_serialno(&og)!=vf->serialnos[i])
402 	  break;
403 
404 	pos=ogg_page_granulepos(&og);
405 
406 	/* count blocksizes of all frames in the page */
407 	ogg_stream_pagein(vf->os,&og);
408 	while((result=ogg_stream_packetout(vf->os,&op))){
409 	  if(result>0){ /* ignore holes */
410 	    long thisblock=vorbis_packet_blocksize(&vf->vi,&op);
411 	    if(lastblock!=-1)
412 	      accumulated+=(lastblock+thisblock)>>2;
413 	    lastblock=thisblock;
414 	  }
415 	}
416 	ogg_packet_release(&op);
417 
418 	if(pos!=-1){
419 	  /* pcm offset of last packet on the first audio page */
420 	  accumulated= pos-accumulated;
421 	  break;
422 	}
423       }
424 
425       /* less than zero?  This is a stream with samples trimmed off
426          the beginning, a normal occurrence; set the offset to zero */
427       if(accumulated<0)accumulated=0;
428 
429       vf->pcmlengths[i*2]=accumulated;
430     }
431 
432     /* get the PCM length of this link. To do this,
433        get the last page of the stream */
434     {
435       ogg_int64_t end=vf->offsets[i+1];
436       _seek_helper(vf,end);
437 
438       while(1){
439 	ret=_get_prev_page(vf,&og);
440 	if(ret<0){
441 	  /* this should not be possible */
442 	  vorbis_info_clear(&vf->vi);
443 	  vorbis_comment_clear(&vf->vc);
444 	  break;
445 	}
446 	if(ogg_page_granulepos(&og)!=-1){
447 	  vf->pcmlengths[i*2+1]=ogg_page_granulepos(&og)-vf->pcmlengths[i*2];
448 	  break;
449 	}
450 	vf->offset=ret;
451       }
452     }
453   }
454   ogg_page_release(&og);
455 }
456 
_make_decode_ready(OggVorbis_File * vf)457 static int _make_decode_ready(OggVorbis_File *vf){
458   int i;
459   switch(vf->ready_state){
460   case OPENED:
461   case STREAMSET:
462     for(i=0;i<vf->links;i++)
463       if(vf->offsets[i+1]>=vf->offset)break;
464     if(i==vf->links)return -1;
465     i=_set_link_number_preserve_pos(vf,i);
466     if(i)return i;
467     /* fall through */
468   case LINKSET:
469     vf->vd=vorbis_dsp_create(&vf->vi);
470     vf->ready_state=INITSET;
471     vf->bittrack=0;
472     vf->samptrack=0;
473   case INITSET:
474     return 0;
475   default:
476     return -1;
477   }
478 
479 }
480 
_open_seekable2(OggVorbis_File * vf)481 static int _open_seekable2(OggVorbis_File *vf){
482   ogg_uint32_t serialno=vf->current_serialno;
483   ogg_uint32_t tempserialno;
484   ogg_int64_t dataoffset=vf->offset, end;
485   ogg_page og={0,0,0,0};
486 
487   /* we're partially open and have a first link header state in
488      storage in vf */
489   /* we can seek, so set out learning all about this file */
490   (vf->callbacks.seek_func)(vf->datasource,0,SEEK_END);
491   vf->offset=vf->end=(vf->callbacks.tell_func)(vf->datasource);
492 
493   /* We get the offset for the last page of the physical bitstream.
494      Most OggVorbis files will contain a single logical bitstream */
495   end=_get_prev_page(vf,&og);
496   if(end<0)return end;
497 
498   /* more than one logical bitstream? */
499   tempserialno=ogg_page_serialno(&og);
500   ogg_page_release(&og);
501 
502   if(tempserialno!=serialno){
503 
504     /* Chained bitstream. Bisect-search each logical bitstream
505        section.  Do so based on serial number only */
506     if(_bisect_forward_serialno(vf,0,0,end+1,serialno,0)<0)return OV_EREAD;
507 
508   }else{
509 
510     /* Only one logical bitstream */
511     if(_bisect_forward_serialno(vf,0,end,end+1,serialno,0))return OV_EREAD;
512 
513   }
514 
515   /* the initial header memory is referenced by vf after; don't free it */
516   _prefetch_all_offsets(vf,dataoffset);
517   return ov_raw_seek(vf,0);
518 }
519 
520 /* fetch and process a packet.  Handles the case where we're at a
521    bitstream boundary and dumps the decoding machine.  If the decoding
522    machine is unloaded, it loads it.  It also keeps pcm_offset up to
523    date (seek and read both use this.  seek uses a special hack with
524    readp).
525 
526    return: <0) error, OV_HOLE (lost packet) or OV_EOF
527             0) need more data (only if readp==0)
528 	    1) got a packet
529 */
530 
_fetch_and_process_packet(OggVorbis_File * vf,int readp,int spanp)531 static int _fetch_and_process_packet(OggVorbis_File *vf,
532 				     int readp,
533 				     int spanp){
534   ogg_page og={0,0,0,0};
535   ogg_packet op={0,0,0,0,0,0};
536   int ret=0;
537 
538   /* handle one packet.  Try to fetch it from current stream state */
539   /* extract packets from page */
540   while(1){
541 
542     /* process a packet if we can.  If the machine isn't loaded,
543        neither is a page */
544     if(vf->ready_state==INITSET){
545       while(1) {
546 	int result=ogg_stream_packetout(vf->os,&op);
547 	ogg_int64_t granulepos;
548 
549 	if(result<0){
550 	  ret=OV_HOLE; /* hole in the data. */
551 	  goto cleanup;
552 	}
553 	if(result>0){
554 	  /* got a packet.  process it */
555 	  granulepos=op.granulepos;
556 	  if(!vorbis_dsp_synthesis(vf->vd,&op,1)){ /* lazy check for lazy
557 						      header handling.  The
558 						      header packets aren't
559 						      audio, so if/when we
560 						      submit them,
561 						      vorbis_synthesis will
562 						      reject them */
563 
564 	    vf->samptrack+=vorbis_dsp_pcmout(vf->vd,NULL,0);
565 	    vf->bittrack+=op.bytes*8;
566 
567 	    /* update the pcm offset. */
568 	    if(granulepos!=-1 && !op.e_o_s){
569 	      int link=(vf->seekable?vf->current_link:0);
570 	      int i,samples;
571 
572 	      /* this packet has a pcm_offset on it (the last packet
573 	         completed on a page carries the offset) After processing
574 	         (above), we know the pcm position of the *last* sample
575 	         ready to be returned. Find the offset of the *first*
576 
577 	         As an aside, this trick is inaccurate if we begin
578 	         reading anew right at the last page; the end-of-stream
579 	         granulepos declares the last frame in the stream, and the
580 	         last packet of the last page may be a partial frame.
581 	         So, we need a previous granulepos from an in-sequence page
582 	         to have a reference point.  Thus the !op.e_o_s clause
583 	         above */
584 
585 	      if(vf->seekable && link>0)
586 		granulepos-=vf->pcmlengths[link*2];
587 	      if(granulepos<0)granulepos=0; /* actually, this
588 					       shouldn't be possible
589 					       here unless the stream
590 					       is very broken */
591 
592 	      samples=vorbis_dsp_pcmout(vf->vd,NULL,0);
593 
594 	      granulepos-=samples;
595 	      for(i=0;i<link;i++)
596 	        granulepos+=vf->pcmlengths[i*2+1];
597 	      vf->pcm_offset=granulepos;
598 	    }
599 	    ret=1;
600 	    goto cleanup;
601 	  }
602 	}
603 	else
604 	  break;
605       }
606     }
607 
608     if(vf->ready_state>=OPENED){
609       int ret;
610       if(!readp){
611 	ret=0;
612 	goto cleanup;
613       }
614       if((ret=_get_next_page(vf,&og,-1))<0){
615 	ret=OV_EOF; /* eof. leave unitialized */
616 	goto cleanup;
617       }
618 
619 	/* bitrate tracking; add the header's bytes here, the body bytes
620 	   are done by packet above */
621       vf->bittrack+=og.header_len*8;
622 
623       /* has our decoding just traversed a bitstream boundary? */
624       if(vf->ready_state==INITSET){
625 	if(vf->current_serialno!=ogg_page_serialno(&og)){
626 	  if(!spanp){
627 	    ret=OV_EOF;
628 	    goto cleanup;
629 	  }
630 
631 	  _decode_clear(vf);
632 	}
633       }
634     }
635 
636     /* Do we need to load a new machine before submitting the page? */
637     /* This is different in the seekable and non-seekable cases.
638 
639        In the seekable case, we already have all the header
640        information loaded and cached; we just initialize the machine
641        with it and continue on our merry way.
642 
643        In the non-seekable (streaming) case, we'll only be at a
644        boundary if we just left the previous logical bitstream and
645        we're now nominally at the header of the next bitstream
646     */
647 
648     if(vf->ready_state!=INITSET){
649       int link,ret;
650 
651       if(vf->ready_state<STREAMSET){
652 	if(vf->seekable){
653 	  vf->current_serialno=ogg_page_serialno(&og);
654 
655 	  /* match the serialno to bitstream section.  We use this rather than
656 	     offset positions to avoid problems near logical bitstream
657 	     boundaries */
658 	  for(link=0;link<vf->links;link++)
659 	    if(vf->serialnos[link]==vf->current_serialno)break;
660 	  if(link==vf->links){
661 	    ret=OV_EBADLINK; /* sign of a bogus stream.  error out,
662 				leave machine uninitialized */
663 	    goto cleanup;
664 	  }
665 
666 	  vf->current_link=link;
667 	  ret=_fetch_headers(vf,&vf->vi,&vf->vc,&vf->current_serialno,&og);
668 	  if(ret) goto cleanup;
669 
670 	}else{
671 	  /* we're streaming */
672 	  /* fetch the three header packets, build the info struct */
673 
674 	  int ret=_fetch_headers(vf,&vf->vi,&vf->vc,&vf->current_serialno,&og);
675 	  if(ret) goto cleanup;
676 	  vf->current_link++;
677 	}
678       }
679 
680       if(_make_decode_ready(vf)) return OV_EBADLINK;
681     }
682     ogg_stream_pagein(vf->os,&og);
683   }
684  cleanup:
685   ogg_packet_release(&op);
686   ogg_page_release(&og);
687   return ret;
688 }
689 
690 /* if, eg, 64 bit stdio is configured by default, this will build with
691    fseek64 */
_fseek64_wrap(FILE * f,ogg_int64_t off,int whence)692 static int _fseek64_wrap(FILE *f,ogg_int64_t off,int whence){
693   if(f==NULL)return -1;
694   return fseek(f,off,whence);
695 }
696 
_ov_open1(void * f,OggVorbis_File * vf,char * initial,long ibytes,ov_callbacks callbacks)697 static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
698 		     long ibytes, ov_callbacks callbacks){
699   int offsettest=(f?callbacks.seek_func(f,0,SEEK_CUR):-1);
700   int ret;
701 
702   memset(vf,0,sizeof(*vf));
703 
704   /* Tremor assumes in multiple places that right shift of a signed
705      integer is an arithmetic shift */
706   if( (-1>>1) != -1) return OV_EIMPL;
707 
708   vf->datasource=f;
709   vf->callbacks = callbacks;
710 
711   /* init the framing state */
712   vf->oy=ogg_sync_create();
713 
714   /* perhaps some data was previously read into a buffer for testing
715      against other stream types.  Allow initialization from this
716      previously read data (as we may be reading from a non-seekable
717      stream) */
718   if(initial){
719     unsigned char *buffer=ogg_sync_bufferin(vf->oy,ibytes);
720     memcpy(buffer,initial,ibytes);
721     ogg_sync_wrote(vf->oy,ibytes);
722   }
723 
724   /* can we seek? Stevens suggests the seek test was portable */
725   if(offsettest!=-1)vf->seekable=1;
726 
727   /* No seeking yet; Set up a 'single' (current) logical bitstream
728      entry for partial open */
729   vf->links=1;
730   vf->os=ogg_stream_create(-1); /* fill in the serialno later */
731 
732   /* Try to fetch the headers, maintaining all the storage */
733   if((ret=_fetch_headers(vf,&vf->vi,&vf->vc,&vf->current_serialno,NULL))<0){
734     vf->datasource=NULL;
735     ov_clear(vf);
736   }else if(vf->ready_state < PARTOPEN)
737     vf->ready_state=PARTOPEN;
738   return ret;
739 }
740 
_ov_open2(OggVorbis_File * vf)741 static int _ov_open2(OggVorbis_File *vf){
742   if(vf->ready_state < OPENED)
743     vf->ready_state=OPENED;
744   if(vf->seekable){
745     int ret=_open_seekable2(vf);
746     if(ret){
747       vf->datasource=NULL;
748       ov_clear(vf);
749     }
750     return ret;
751   }
752   return 0;
753 }
754 
755 
756 /* clear out the OggVorbis_File struct */
ov_clear(OggVorbis_File * vf)757 int ov_clear(OggVorbis_File *vf){
758   if(vf){
759     vorbis_dsp_destroy(vf->vd);
760     vf->vd=0;
761     ogg_stream_destroy(vf->os);
762     vorbis_info_clear(&vf->vi);
763     vorbis_comment_clear(&vf->vc);
764     if(vf->dataoffsets)_ogg_free(vf->dataoffsets);
765     if(vf->pcmlengths)_ogg_free(vf->pcmlengths);
766     if(vf->serialnos)_ogg_free(vf->serialnos);
767     if(vf->offsets)_ogg_free(vf->offsets);
768     ogg_sync_destroy(vf->oy);
769 
770     if(vf->datasource)(vf->callbacks.close_func)(vf->datasource);
771     memset(vf,0,sizeof(*vf));
772   }
773 #ifdef DEBUG_LEAKS
774   _VDBG_dump();
775 #endif
776   return 0;
777 }
778 
779 /* inspects the OggVorbis file and finds/documents all the logical
780    bitstreams contained in it.  Tries to be tolerant of logical
781    bitstream sections that are truncated/woogie.
782 
783    return: -1) error
784             0) OK
785 */
786 
ov_open_callbacks(void * f,OggVorbis_File * vf,char * initial,long ibytes,ov_callbacks callbacks)787 int ov_open_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes,
788     ov_callbacks callbacks){
789   int ret=_ov_open1(f,vf,initial,ibytes,callbacks);
790   if(ret)return ret;
791   return _ov_open2(vf);
792 }
793 
ov_open(FILE * f,OggVorbis_File * vf,char * initial,long ibytes)794 int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){
795   ov_callbacks callbacks = {
796     (size_t (*)(void *, size_t, size_t, void *))  fread,
797     (int (*)(void *, ogg_int64_t, int))              _fseek64_wrap,
798     (int (*)(void *))                             fclose,
799     (long (*)(void *))                            ftell
800   };
801 
802   return ov_open_callbacks((void *)f, vf, initial, ibytes, callbacks);
803 }
804 
805 /* Only partially open the vorbis file; test for Vorbisness, and load
806    the headers for the first chain.  Do not seek (although test for
807    seekability).  Use ov_test_open to finish opening the file, else
808    ov_clear to close/free it. Same return codes as open. */
809 
ov_test_callbacks(void * f,OggVorbis_File * vf,char * initial,long ibytes,ov_callbacks callbacks)810 int ov_test_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes,
811     ov_callbacks callbacks)
812 {
813   return _ov_open1(f,vf,initial,ibytes,callbacks);
814 }
815 
ov_test(FILE * f,OggVorbis_File * vf,char * initial,long ibytes)816 int ov_test(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){
817   ov_callbacks callbacks = {
818     (size_t (*)(void *, size_t, size_t, void *))  fread,
819     (int (*)(void *, ogg_int64_t, int))              _fseek64_wrap,
820     (int (*)(void *))                             fclose,
821     (long (*)(void *))                            ftell
822   };
823 
824   return ov_test_callbacks((void *)f, vf, initial, ibytes, callbacks);
825 }
826 
ov_test_open(OggVorbis_File * vf)827 int ov_test_open(OggVorbis_File *vf){
828   if(vf->ready_state!=PARTOPEN)return OV_EINVAL;
829   return _ov_open2(vf);
830 }
831 
832 /* How many logical bitstreams in this physical bitstream? */
ov_streams(OggVorbis_File * vf)833 long ov_streams(OggVorbis_File *vf){
834   return vf->links;
835 }
836 
837 /* Is the FILE * associated with vf seekable? */
ov_seekable(OggVorbis_File * vf)838 long ov_seekable(OggVorbis_File *vf){
839   return vf->seekable;
840 }
841 
842 /* returns the bitrate for a given logical bitstream or the entire
843    physical bitstream.  If the file is open for random access, it will
844    find the *actual* average bitrate.  If the file is streaming, it
845    returns the nominal bitrate (if set) else the average of the
846    upper/lower bounds (if set) else -1 (unset).
847 
848    If you want the actual bitrate field settings, get them from the
849    vorbis_info structs */
850 
ov_bitrate(OggVorbis_File * vf,int i)851 long ov_bitrate(OggVorbis_File *vf,int i){
852   if(vf->ready_state<OPENED)return OV_EINVAL;
853   if(i>=vf->links)return OV_EINVAL;
854   if(!vf->seekable && i!=0)return ov_bitrate(vf,0);
855   if(i<0){
856     ogg_int64_t bits=0;
857     int i;
858     for(i=0;i<vf->links;i++)
859       bits+=(vf->offsets[i+1]-vf->dataoffsets[i])*8;
860     /* This once read: return(rint(bits/ov_time_total(vf,-1)));
861      * gcc 3.x on x86 miscompiled this at optimisation level 2 and above,
862      * so this is slightly transformed to make it work.
863      */
864     return bits*1000/ov_time_total(vf,-1);
865   }else{
866     if(vf->seekable){
867       /* return the actual bitrate */
868       return (vf->offsets[i+1]-vf->dataoffsets[i])*8000/ov_time_total(vf,i);
869     }else{
870       /* return nominal if set */
871       if(vf->vi.bitrate_nominal>0){
872 	return vf->vi.bitrate_nominal;
873       }else{
874 	if(vf->vi.bitrate_upper>0){
875 	  if(vf->vi.bitrate_lower>0){
876 	    return (vf->vi.bitrate_upper+vf->vi.bitrate_lower)/2;
877 	  }else{
878 	    return vf->vi.bitrate_upper;
879 	  }
880 	}
881 	return OV_FALSE;
882       }
883     }
884   }
885 }
886 
887 /* returns the actual bitrate since last call.  returns -1 if no
888    additional data to offer since last call (or at beginning of stream),
889    EINVAL if stream is only partially open
890 */
ov_bitrate_instant(OggVorbis_File * vf)891 long ov_bitrate_instant(OggVorbis_File *vf){
892   long ret;
893   if(vf->ready_state<OPENED)return OV_EINVAL;
894   if(vf->samptrack==0)return OV_FALSE;
895   ret=vf->bittrack/vf->samptrack*vf->vi.rate;
896   vf->bittrack=0;
897   vf->samptrack=0;
898   return ret;
899 }
900 
901 /* Guess */
ov_serialnumber(OggVorbis_File * vf,int i)902 long ov_serialnumber(OggVorbis_File *vf,int i){
903   if(i>=vf->links)return ov_serialnumber(vf,vf->links-1);
904   if(!vf->seekable && i>=0)return ov_serialnumber(vf,-1);
905   if(i<0){
906     return vf->current_serialno;
907   }else{
908     return vf->serialnos[i];
909   }
910 }
911 
912 /* returns: total raw (compressed) length of content if i==-1
913             raw (compressed) length of that logical bitstream for i==0 to n
914 	    OV_EINVAL if the stream is not seekable (we can't know the length)
915 	    or if stream is only partially open
916 */
ov_raw_total(OggVorbis_File * vf,int i)917 ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i){
918   if(vf->ready_state<OPENED)return OV_EINVAL;
919   if(!vf->seekable || i>=vf->links)return OV_EINVAL;
920   if(i<0){
921     ogg_int64_t acc=0;
922     int i;
923     for(i=0;i<vf->links;i++)
924       acc+=ov_raw_total(vf,i);
925     return acc;
926   }else{
927     return vf->offsets[i+1]-vf->offsets[i];
928   }
929 }
930 
931 /* returns: total PCM length (samples) of content if i==-1 PCM length
932 	    (samples) of that logical bitstream for i==0 to n
933 	    OV_EINVAL if the stream is not seekable (we can't know the
934 	    length) or only partially open
935 */
ov_pcm_total(OggVorbis_File * vf,int i)936 ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i){
937   if(vf->ready_state<OPENED)return OV_EINVAL;
938   if(!vf->seekable || i>=vf->links)return OV_EINVAL;
939   if(i<0){
940     ogg_int64_t acc=0;
941     int i;
942     for(i=0;i<vf->links;i++)
943       acc+=ov_pcm_total(vf,i);
944     return acc;
945   }else{
946     return vf->pcmlengths[i*2+1];
947   }
948 }
949 
950 /* returns: total milliseconds of content if i==-1
951             milliseconds in that logical bitstream for i==0 to n
952 	    OV_EINVAL if the stream is not seekable (we can't know the
953 	    length) or only partially open
954 */
ov_time_total(OggVorbis_File * vf,int i)955 ogg_int64_t ov_time_total(OggVorbis_File *vf,int i){
956   if(vf->ready_state<OPENED)return OV_EINVAL;
957   if(!vf->seekable || i>=vf->links)return OV_EINVAL;
958   if(i<0){
959     ogg_int64_t acc=0;
960     int i;
961     for(i=0;i<vf->links;i++)
962       acc+=ov_time_total(vf,i);
963     return acc;
964   }else{
965     return ((ogg_int64_t)vf->pcmlengths[i*2+1])*1000/vf->vi.rate;
966   }
967 }
968 
969 /* seek to an offset relative to the *compressed* data. This also
970    scans packets to update the PCM cursor. It will cross a logical
971    bitstream boundary, but only if it can't get any packets out of the
972    tail of the bitstream we seek to (so no surprises).
973 
974    returns zero on success, nonzero on failure */
975 
ov_raw_seek(OggVorbis_File * vf,ogg_int64_t pos)976 int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
977   ogg_stream_state *work_os=NULL;
978   ogg_page og={0,0,0,0};
979   ogg_packet op={0,0,0,0,0,0};
980 
981   if(vf->ready_state<OPENED)return OV_EINVAL;
982   if(!vf->seekable)
983     return OV_ENOSEEK; /* don't dump machine if we can't seek */
984 
985   if(pos<0 || pos>vf->end)return OV_EINVAL;
986 
987   /* don't yet clear out decoding machine (if it's initialized), in
988      the case we're in the same link.  Restart the decode lapping, and
989      let _fetch_and_process_packet deal with a potential bitstream
990      boundary */
991   vf->pcm_offset=-1;
992   ogg_stream_reset_serialno(vf->os,
993 			    vf->current_serialno); /* must set serialno */
994   vorbis_dsp_restart(vf->vd);
995 
996   _seek_helper(vf,pos);
997 
998   /* we need to make sure the pcm_offset is set, but we don't want to
999      advance the raw cursor past good packets just to get to the first
1000      with a granulepos.  That's not equivalent behavior to beginning
1001      decoding as immediately after the seek position as possible.
1002 
1003      So, a hack.  We use two stream states; a local scratch state and
1004      the shared vf->os stream state.  We use the local state to
1005      scan, and the shared state as a buffer for later decode.
1006 
1007      Unfortuantely, on the last page we still advance to last packet
1008      because the granulepos on the last page is not necessarily on a
1009      packet boundary, and we need to make sure the granpos is
1010      correct.
1011   */
1012 
1013   {
1014     int lastblock=0;
1015     int accblock=0;
1016     int thisblock;
1017     int eosflag;
1018 
1019     work_os=ogg_stream_create(vf->current_serialno); /* get the memory ready */
1020     while(1){
1021       if(vf->ready_state>=STREAMSET){
1022 	/* snarf/scan a packet if we can */
1023 	int result=ogg_stream_packetout(work_os,&op);
1024 
1025 	if(result>0){
1026 
1027 	  if(vf->vi.codec_setup){
1028 	    thisblock=vorbis_packet_blocksize(&vf->vi,&op);
1029 	    if(thisblock<0){
1030 	      ogg_stream_packetout(vf->os,NULL);
1031 	      thisblock=0;
1032 	    }else{
1033 
1034 	      if(eosflag)
1035 		ogg_stream_packetout(vf->os,NULL);
1036 	      else
1037 		if(lastblock)accblock+=(lastblock+thisblock)>>2;
1038 	    }
1039 
1040 	    if(op.granulepos!=-1){
1041 	      int i,link=vf->current_link;
1042 	      ogg_int64_t granulepos=op.granulepos-vf->pcmlengths[link*2];
1043 	      if(granulepos<0)granulepos=0;
1044 
1045 	      for(i=0;i<link;i++)
1046 		granulepos+=vf->pcmlengths[i*2+1];
1047 	      vf->pcm_offset=granulepos-accblock;
1048 	      break;
1049 	    }
1050 	    lastblock=thisblock;
1051 	    continue;
1052 	  }else
1053 	    ogg_stream_packetout(vf->os,NULL);
1054 	}
1055       }
1056 
1057       if(!lastblock){
1058 	if(_get_next_page(vf,&og,-1)<0){
1059 	  vf->pcm_offset=ov_pcm_total(vf,-1);
1060 	  break;
1061 	}
1062       }else{
1063 	/* huh?  Bogus stream with packets but no granulepos */
1064 	vf->pcm_offset=-1;
1065 	break;
1066       }
1067 
1068       /* did we just grab a page from other than current link? */
1069       if(vf->ready_state>=STREAMSET)
1070 	if(vf->current_serialno!=ogg_page_serialno(&og)){
1071 	  _decode_clear(vf); /* clear out stream state */
1072 	  ogg_stream_destroy(work_os);
1073 	}
1074 
1075       if(vf->ready_state<STREAMSET){
1076 	int link;
1077 
1078 	vf->current_serialno=ogg_page_serialno(&og);
1079 	for(link=0;link<vf->links;link++)
1080 	  if(vf->serialnos[link]==vf->current_serialno)break;
1081 	if(link==vf->links)
1082 	  goto seek_error; /* sign of a bogus stream.  error out,
1083 			      leave machine uninitialized */
1084 
1085 	/* need to initialize machine to this link */
1086 	{
1087 	  int ret=_set_link_number_preserve_pos(vf,link);
1088 	  if(ret) goto seek_error;
1089 	}
1090 	ogg_stream_reset_serialno(vf->os,vf->current_serialno);
1091 	ogg_stream_reset_serialno(work_os,vf->current_serialno);
1092 
1093 
1094       }
1095 
1096       {
1097 	ogg_page dup;
1098 	ogg_page_dup(&dup,&og);
1099 	eosflag=ogg_page_eos(&og);
1100 	ogg_stream_pagein(vf->os,&og);
1101 	ogg_stream_pagein(work_os,&dup);
1102       }
1103     }
1104   }
1105 
1106   ogg_packet_release(&op);
1107   ogg_page_release(&og);
1108   ogg_stream_destroy(work_os);
1109   vf->bittrack=0;
1110   vf->samptrack=0;
1111   return 0;
1112 
1113  seek_error:
1114   ogg_packet_release(&op);
1115   ogg_page_release(&og);
1116 
1117   /* dump the machine so we're in a known state */
1118   vf->pcm_offset=-1;
1119   ogg_stream_destroy(work_os);
1120   _decode_clear(vf);
1121   return OV_EBADLINK;
1122 }
1123 
1124 /* Page granularity seek (faster than sample granularity because we
1125    don't do the last bit of decode to find a specific sample).
1126 
1127    Seek to the last [granule marked] page preceeding the specified pos
1128    location, such that decoding past the returned point will quickly
1129    arrive at the requested position. */
ov_pcm_seek_page(OggVorbis_File * vf,ogg_int64_t pos)1130 int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
1131   int link=-1;
1132   ogg_int64_t result=0;
1133   ogg_int64_t total=ov_pcm_total(vf,-1);
1134   ogg_page og={0,0,0,0};
1135   ogg_packet op={0,0,0,0,0,0};
1136 
1137   if(vf->ready_state<OPENED)return OV_EINVAL;
1138   if(!vf->seekable)return OV_ENOSEEK;
1139   if(pos<0 || pos>total)return OV_EINVAL;
1140 
1141   /* which bitstream section does this pcm offset occur in? */
1142   for(link=vf->links-1;link>=0;link--){
1143     total-=vf->pcmlengths[link*2+1];
1144     if(pos>=total)break;
1145   }
1146 
1147 
1148   if(link!=vf->current_link){
1149     int ret=_set_link_number(vf,link);
1150     if(ret) goto seek_error;
1151   }else{
1152     vorbis_dsp_restart(vf->vd);
1153   }
1154 
1155   ogg_stream_reset_serialno(vf->os,vf->serialnos[link]);
1156 
1157   /* search within the logical bitstream for the page with the highest
1158      pcm_pos preceeding (or equal to) pos.  There is a danger here;
1159      missing pages or incorrect frame number information in the
1160      bitstream could make our task impossible.  Account for that (it
1161      would be an error condition) */
1162 
1163   /* new search algorithm by HB (Nicholas Vinen) */
1164   {
1165     ogg_int64_t end=vf->offsets[link+1];
1166     ogg_int64_t begin=vf->offsets[link];
1167     ogg_int64_t begintime = vf->pcmlengths[link*2];
1168     ogg_int64_t endtime = vf->pcmlengths[link*2+1]+begintime;
1169     ogg_int64_t target=pos-total+begintime;
1170     ogg_int64_t best=begin;
1171 
1172     while(begin<end){
1173       ogg_int64_t bisect;
1174 
1175       if(end-begin<CHUNKSIZE){
1176 	bisect=begin;
1177       }else{
1178 	/* take a (pretty decent) guess. */
1179 	bisect=begin +
1180 	  (target-begintime)*(end-begin)/(endtime-begintime) - CHUNKSIZE;
1181 	if(bisect<=begin)
1182 	  bisect=begin+1;
1183       }
1184 
1185       _seek_helper(vf,bisect);
1186 
1187       while(begin<end){
1188 	result=_get_next_page(vf,&og,end-vf->offset);
1189 	if(result==OV_EREAD) goto seek_error;
1190 	if(result<0){
1191 	  if(bisect<=begin+1)
1192 	    end=begin; /* found it */
1193 	  else{
1194 	    if(bisect==0) goto seek_error;
1195 	    bisect-=CHUNKSIZE;
1196 	    if(bisect<=begin)bisect=begin+1;
1197 	    _seek_helper(vf,bisect);
1198 	  }
1199 	}else{
1200 	  ogg_int64_t granulepos=ogg_page_granulepos(&og);
1201 	  if(granulepos==-1)continue;
1202 	  if(granulepos<target){
1203 	    best=result;  /* raw offset of packet with granulepos */
1204 	    begin=vf->offset; /* raw offset of next page */
1205 	    begintime=granulepos;
1206 
1207 	    if(target-begintime>44100)break;
1208 	    bisect=begin; /* *not* begin + 1 */
1209 	  }else{
1210 	    if(bisect<=begin+1)
1211 	      end=begin;  /* found it */
1212 	    else{
1213 	      if(end==vf->offset){ /* we're pretty close - we'd be stuck in */
1214 		end=result;
1215 		bisect-=CHUNKSIZE; /* an endless loop otherwise. */
1216 		if(bisect<=begin)bisect=begin+1;
1217 		_seek_helper(vf,bisect);
1218 	      }else{
1219 		end=result;
1220 		endtime=granulepos;
1221 		break;
1222 	      }
1223 	    }
1224 	  }
1225 	}
1226       }
1227     }
1228 
1229     /* found our page. seek to it, update pcm offset. Easier case than
1230        raw_seek, don't keep packets preceeding granulepos. */
1231     {
1232 
1233       /* seek */
1234       _seek_helper(vf,best);
1235       vf->pcm_offset=-1;
1236 
1237       if(_get_next_page(vf,&og,-1)<0){
1238 	ogg_page_release(&og);
1239 	return OV_EOF; /* shouldn't happen */
1240       }
1241 
1242       ogg_stream_pagein(vf->os,&og);
1243 
1244       /* pull out all but last packet; the one with granulepos */
1245       while(1){
1246 	result=ogg_stream_packetpeek(vf->os,&op);
1247 	if(result==0){
1248 	  /* !!! the packet finishing this page originated on a
1249              preceeding page. Keep fetching previous pages until we
1250              get one with a granulepos or without the 'continued' flag
1251              set.  Then just use raw_seek for simplicity. */
1252 
1253 	  _seek_helper(vf,best);
1254 
1255 	  while(1){
1256 	    result=_get_prev_page(vf,&og);
1257 	    if(result<0) goto seek_error;
1258 	    if(ogg_page_granulepos(&og)>-1 ||
1259 	       !ogg_page_continued(&og)){
1260 	      return ov_raw_seek(vf,result);
1261 	    }
1262 	    vf->offset=result;
1263 	  }
1264 	}
1265 	if(result<0){
1266 	  result = OV_EBADPACKET;
1267 	  goto seek_error;
1268 	}
1269 	if(op.granulepos!=-1){
1270 	  vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];
1271 	  if(vf->pcm_offset<0)vf->pcm_offset=0;
1272 	  vf->pcm_offset+=total;
1273 	  break;
1274 	}else
1275 	  result=ogg_stream_packetout(vf->os,NULL);
1276       }
1277     }
1278   }
1279 
1280   /* verify result */
1281   if(vf->pcm_offset>pos || pos>ov_pcm_total(vf,-1)){
1282     result=OV_EFAULT;
1283     goto seek_error;
1284   }
1285   vf->bittrack=0;
1286   vf->samptrack=0;
1287 
1288   ogg_page_release(&og);
1289   ogg_packet_release(&op);
1290   return 0;
1291 
1292  seek_error:
1293 
1294   ogg_page_release(&og);
1295   ogg_packet_release(&op);
1296 
1297   /* dump machine so we're in a known state */
1298   vf->pcm_offset=-1;
1299   _decode_clear(vf);
1300   return (int)result;
1301 }
1302 
1303 /* seek to a sample offset relative to the decompressed pcm stream
1304    returns zero on success, nonzero on failure */
1305 
ov_pcm_seek(OggVorbis_File * vf,ogg_int64_t pos)1306 int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
1307   ogg_packet op={0,0,0,0,0,0};
1308   ogg_page og={0,0,0,0};
1309   int thisblock,lastblock=0;
1310   int ret=ov_pcm_seek_page(vf,pos);
1311   if(ret<0)return ret;
1312   if(_make_decode_ready(vf))return OV_EBADLINK;
1313 
1314   /* discard leading packets we don't need for the lapping of the
1315      position we want; don't decode them */
1316 
1317   while(1){
1318 
1319     int ret=ogg_stream_packetpeek(vf->os,&op);
1320     if(ret>0){
1321       thisblock=vorbis_packet_blocksize(&vf->vi,&op);
1322       if(thisblock<0){
1323 	ogg_stream_packetout(vf->os,NULL);
1324 	continue; /* non audio packet */
1325       }
1326       if(lastblock)vf->pcm_offset+=(lastblock+thisblock)>>2;
1327 
1328       if(vf->pcm_offset+((thisblock+
1329 			  vorbis_info_blocksize(&vf->vi,1))>>2)>=pos)break;
1330 
1331       /* remove the packet from packet queue and track its granulepos */
1332       ogg_stream_packetout(vf->os,NULL);
1333       vorbis_dsp_synthesis(vf->vd,&op,0);  /* set up a vb with
1334 					      only tracking, no
1335 					      pcm_decode */
1336 
1337       /* end of logical stream case is hard, especially with exact
1338 	 length positioning. */
1339 
1340       if(op.granulepos>-1){
1341 	int i;
1342 	/* always believe the stream markers */
1343 	vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];
1344 	if(vf->pcm_offset<0)vf->pcm_offset=0;
1345 	for(i=0;i<vf->current_link;i++)
1346 	  vf->pcm_offset+=vf->pcmlengths[i*2+1];
1347       }
1348 
1349       lastblock=thisblock;
1350 
1351     }else{
1352       if(ret<0 && ret!=OV_HOLE)break;
1353 
1354       /* suck in a new page */
1355       if(_get_next_page(vf,&og,-1)<0)break;
1356       if(vf->current_serialno!=ogg_page_serialno(&og))_decode_clear(vf);
1357 
1358       if(vf->ready_state<STREAMSET){
1359 	int link,ret;
1360 
1361 	vf->current_serialno=ogg_page_serialno(&og);
1362 	for(link=0;link<vf->links;link++)
1363 	  if(vf->serialnos[link]==vf->current_serialno)break;
1364 	if(link==vf->links){
1365 	  ogg_page_release(&og);
1366 	  ogg_packet_release(&op);
1367 	  return OV_EBADLINK;
1368 	}
1369 
1370 
1371 	vf->current_link=link;
1372 	ret=_fetch_headers(vf,&vf->vi,&vf->vc,&vf->current_serialno,&og);
1373 	if(ret) return ret;
1374 	if(_make_decode_ready(vf))return OV_EBADLINK;
1375 	lastblock=0;
1376       }
1377 
1378       ogg_stream_pagein(vf->os,&og);
1379     }
1380   }
1381 
1382   vf->bittrack=0;
1383   vf->samptrack=0;
1384   /* discard samples until we reach the desired position. Crossing a
1385      logical bitstream boundary with abandon is OK. */
1386   while(vf->pcm_offset<pos){
1387     ogg_int64_t target=pos-vf->pcm_offset;
1388     long samples=vorbis_dsp_pcmout(vf->vd,NULL,0);
1389 
1390     if(samples>target)samples=target;
1391     vorbis_dsp_read(vf->vd,samples);
1392     vf->pcm_offset+=samples;
1393 
1394     if(samples<target)
1395       if(_fetch_and_process_packet(vf,1,1)<=0)
1396 	vf->pcm_offset=ov_pcm_total(vf,-1); /* eof */
1397   }
1398 
1399   ogg_page_release(&og);
1400   ogg_packet_release(&op);
1401   return 0;
1402 }
1403 
1404 /* seek to a playback time relative to the decompressed pcm stream
1405    returns zero on success, nonzero on failure */
ov_time_seek(OggVorbis_File * vf,ogg_int64_t milliseconds)1406 int ov_time_seek(OggVorbis_File *vf,ogg_int64_t milliseconds){
1407   /* translate time to PCM position and call ov_pcm_seek */
1408 
1409   int link=-1;
1410   ogg_int64_t pcm_total=ov_pcm_total(vf,-1);
1411   ogg_int64_t time_total=ov_time_total(vf,-1);
1412 
1413   if(vf->ready_state<OPENED)return OV_EINVAL;
1414   if(!vf->seekable)return OV_ENOSEEK;
1415   if(milliseconds<0 || milliseconds>time_total)return OV_EINVAL;
1416 
1417   /* which bitstream section does this time offset occur in? */
1418   for(link=vf->links-1;link>=0;link--){
1419     pcm_total-=vf->pcmlengths[link*2+1];
1420     time_total-=ov_time_total(vf,link);
1421     if(milliseconds>=time_total)break;
1422   }
1423 
1424   /* enough information to convert time offset to pcm offset */
1425   {
1426     int ret=_set_link_number(vf,link);
1427     if(ret)return ret;
1428     return
1429       ov_pcm_seek(vf,pcm_total+(milliseconds-time_total)*
1430 		  vf->vi.rate/1000);
1431   }
1432 }
1433 
1434 /* page-granularity version of ov_time_seek
1435    returns zero on success, nonzero on failure */
ov_time_seek_page(OggVorbis_File * vf,ogg_int64_t milliseconds)1436 int ov_time_seek_page(OggVorbis_File *vf,ogg_int64_t milliseconds){
1437   /* translate time to PCM position and call ov_pcm_seek */
1438 
1439   int link=-1;
1440   ogg_int64_t pcm_total=ov_pcm_total(vf,-1);
1441   ogg_int64_t time_total=ov_time_total(vf,-1);
1442 
1443   if(vf->ready_state<OPENED)return OV_EINVAL;
1444   if(!vf->seekable)return OV_ENOSEEK;
1445   if(milliseconds<0 || milliseconds>time_total)return OV_EINVAL;
1446 
1447   /* which bitstream section does this time offset occur in? */
1448   for(link=vf->links-1;link>=0;link--){
1449     pcm_total-=vf->pcmlengths[link*2+1];
1450     time_total-=ov_time_total(vf,link);
1451     if(milliseconds>=time_total)break;
1452   }
1453 
1454   /* enough information to convert time offset to pcm offset */
1455   {
1456     int ret=_set_link_number(vf,link);
1457     if(ret)return ret;
1458     return
1459       ov_pcm_seek_page(vf,pcm_total+(milliseconds-time_total)*
1460 		       vf->vi.rate/1000);
1461   }
1462 }
1463 
1464 /* tell the current stream offset cursor.  Note that seek followed by
1465    tell will likely not give the set offset due to caching */
ov_raw_tell(OggVorbis_File * vf)1466 ogg_int64_t ov_raw_tell(OggVorbis_File *vf){
1467   if(vf->ready_state<OPENED)return OV_EINVAL;
1468   return vf->offset;
1469 }
1470 
1471 /* return PCM offset (sample) of next PCM sample to be read */
ov_pcm_tell(OggVorbis_File * vf)1472 ogg_int64_t ov_pcm_tell(OggVorbis_File *vf){
1473   if(vf->ready_state<OPENED)return OV_EINVAL;
1474   return vf->pcm_offset;
1475 }
1476 
1477 /* return time offset (milliseconds) of next PCM sample to be read */
ov_time_tell(OggVorbis_File * vf)1478 ogg_int64_t ov_time_tell(OggVorbis_File *vf){
1479   int link=0;
1480   ogg_int64_t pcm_total=0;
1481   ogg_int64_t time_total=0;
1482 
1483   if(vf->ready_state<OPENED)return OV_EINVAL;
1484   if(vf->seekable){
1485     pcm_total=ov_pcm_total(vf,-1);
1486     time_total=ov_time_total(vf,-1);
1487 
1488     /* which bitstream section does this time offset occur in? */
1489     for(link=vf->links-1;link>=0;link--){
1490       pcm_total-=vf->pcmlengths[link*2+1];
1491       time_total-=ov_time_total(vf,link);
1492       if(vf->pcm_offset>=pcm_total)break;
1493     }
1494   }
1495 
1496   return time_total+(1000*vf->pcm_offset-pcm_total)/vf->vi.rate;
1497 }
1498 
1499 /*  link:   -1) return the vorbis_info struct for the bitstream section
1500                 currently being decoded
1501            0-n) to request information for a specific bitstream section
1502 
1503     In the case of a non-seekable bitstream, any call returns the
1504     current bitstream.  NULL in the case that the machine is not
1505     initialized */
1506 
ov_info(OggVorbis_File * vf,int link)1507 vorbis_info *ov_info(OggVorbis_File *vf,int link){
1508   if(vf->seekable){
1509     if(link>=vf->links)return NULL;
1510     if(link>=0){
1511       int ret=_set_link_number_preserve_pos(vf,link);
1512       if(ret)return NULL;
1513     }
1514   }
1515   return &vf->vi;
1516 }
1517 
1518 /* grr, strong typing, grr, no templates/inheritence, grr */
ov_comment(OggVorbis_File * vf,int link)1519 vorbis_comment *ov_comment(OggVorbis_File *vf,int link){
1520   if(vf->seekable){
1521     if(link>=vf->links)return NULL;
1522     if(link>=0){
1523       int ret=_set_link_number_preserve_pos(vf,link);
1524       if(ret)return NULL;
1525     }
1526   }
1527   return &vf->vc;
1528 }
1529 
1530 /* up to this point, everything could more or less hide the multiple
1531    logical bitstream nature of chaining from the toplevel application
1532    if the toplevel application didn't particularly care.  However, at
1533    the point that we actually read audio back, the multiple-section
1534    nature must surface: Multiple bitstream sections do not necessarily
1535    have to have the same number of channels or sampling rate.
1536 
1537    ov_read returns the sequential logical bitstream number currently
1538    being decoded along with the PCM data in order that the toplevel
1539    application can take action on channel/sample rate changes.  This
1540    number will be incremented even for streamed (non-seekable) streams
1541    (for seekable streams, it represents the actual logical bitstream
1542    index within the physical bitstream.  Note that the accessor
1543    functions above are aware of this dichotomy).
1544 
1545    input values: buffer) a buffer to hold packed PCM data for return
1546 		 length) the byte length requested to be placed into buffer
1547 
1548    return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL)
1549                    0) EOF
1550 		   n) number of bytes of PCM actually returned.  The
1551 		   below works on a packet-by-packet basis, so the
1552 		   return length is not related to the 'length' passed
1553 		   in, just guaranteed to fit.
1554 
1555 	    *section) set to the logical bitstream number */
1556 
ov_read(OggVorbis_File * vf,void * buffer,int bytes_req,int * bitstream)1557 long ov_read(OggVorbis_File *vf,void *buffer,int bytes_req,int *bitstream){
1558 
1559   long samples;
1560   long channels;
1561 
1562   if(vf->ready_state<OPENED)return OV_EINVAL;
1563 
1564   while(1){
1565     if(vf->ready_state==INITSET){
1566       channels=vf->vi.channels;
1567       samples=vorbis_dsp_pcmout(vf->vd,buffer,(bytes_req>>1)/channels);
1568       if(samples){
1569 	if(samples>0){
1570 	  vorbis_dsp_read(vf->vd,samples);
1571 	  vf->pcm_offset+=samples;
1572 	  if(bitstream)*bitstream=vf->current_link;
1573 	  return samples*2*channels;
1574 	}
1575 	return samples;
1576       }
1577     }
1578 
1579     /* suck in another packet */
1580     {
1581       int ret=_fetch_and_process_packet(vf,1,1);
1582       if(ret==OV_EOF)
1583 	return 0;
1584       if(ret<=0)
1585 	return ret;
1586     }
1587 
1588   }
1589 }
1590