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