226 vf->offsets[m+1]=searched; |
218 vf->offsets[m+1]=searched; |
227 }else{ |
219 }else{ |
228 ret=_bisect_forward_serialno(vf,next,vf->offset, |
220 ret=_bisect_forward_serialno(vf,next,vf->offset, |
229 end,ogg_page_serialno(&og),m+1); |
221 end,ogg_page_serialno(&og),m+1); |
230 ogg_page_release(&og); |
222 ogg_page_release(&og); |
231 if(ret==OV_EREAD)return OV_EREAD; |
223 if(ret==OV_EREAD)return(OV_EREAD); |
232 } |
224 } |
233 |
225 |
234 vf->offsets[m]=begin; |
226 vf->offsets[m]=begin; |
235 vf->serialnos[m]=currentno; |
227 vf->serialnos[m]=currentno; |
236 return 0; |
228 return(0); |
237 } |
|
238 |
|
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 } |
229 } |
253 |
230 |
254 /* uses the local ogg_stream storage in vf; this is important for |
231 /* uses the local ogg_stream storage in vf; this is important for |
255 non-streaming input sources */ |
232 non-streaming input sources */ |
256 /* consumes the page that's passed in (if any) */ |
233 /* consumes the page that's passed in (if any) */ |
257 /* state is LINKSET upon successful return */ |
|
258 |
234 |
259 static int _fetch_headers(OggVorbis_File *vf, |
235 static int _fetch_headers(OggVorbis_File *vf, |
260 vorbis_info *vi, |
236 vorbis_info *vi, |
261 vorbis_comment *vc, |
237 vorbis_comment *vc, |
262 ogg_uint32_t *serialno, |
238 ogg_uint32_t *serialno, |
263 ogg_page *og_ptr){ |
239 ogg_page *og_ptr){ |
264 ogg_page og={0,0,0,0}; |
240 ogg_page og={0,0,0,0}; |
265 ogg_packet op={0,0,0,0,0,0}; |
241 ogg_packet op={0,0,0,0,0,0}; |
266 int i,ret; |
242 int i,ret; |
267 |
243 |
268 if(vf->ready_state>OPENED)_decode_clear(vf); |
|
269 |
|
270 if(!og_ptr){ |
244 if(!og_ptr){ |
271 ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE); |
245 ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE); |
272 if(llret==OV_EREAD)return OV_EREAD; |
246 if(llret==OV_EREAD)return(OV_EREAD); |
273 if(llret<0)return OV_ENOTVORBIS; |
247 if(llret<0)return OV_ENOTVORBIS; |
274 og_ptr=&og; |
248 og_ptr=&og; |
275 } |
249 } |
276 |
250 |
277 ogg_stream_reset_serialno(vf->os,ogg_page_serialno(og_ptr)); |
251 ogg_stream_reset_serialno(vf->os,ogg_page_serialno(og_ptr)); |
278 if(serialno)*serialno=vf->os->serialno; |
252 if(serialno)*serialno=vf->os->serialno; |
|
253 vf->ready_state=STREAMSET; |
279 |
254 |
280 /* extract the initial header from the first page and verify that the |
255 /* extract the initial header from the first page and verify that the |
281 Ogg bitstream is in fact Vorbis data */ |
256 Ogg bitstream is in fact Vorbis data */ |
282 |
257 |
283 vorbis_info_init(vi); |
258 vorbis_info_init(vi); |
318 vf->ready_state=OPENED; |
292 vf->ready_state=OPENED; |
319 |
293 |
320 return ret; |
294 return ret; |
321 } |
295 } |
322 |
296 |
323 /* we no longer preload all vorbis_info (and the associated |
297 /* last step of the OggVorbis_File initialization; get all the |
324 codec_setup) structs. Call this to seek and fetch the info from |
298 vorbis_info structs and PCM positions. Only called by the seekable |
325 the bitstream, if needed */ |
299 initialization (local stream storage is hacked slightly; pay |
326 static int _set_link_number(OggVorbis_File *vf,int link){ |
300 attention to how that's done) */ |
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 |
|
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 |
301 |
353 /* this is void and does not propogate errors up because we want to be |
302 /* 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 |
303 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 |
304 watch out for missing information for links in the OggVorbis_File |
356 struct */ |
305 struct */ |
357 static void _prefetch_all_offsets(OggVorbis_File *vf, ogg_int64_t dataoffset){ |
306 static void _prefetch_all_headers(OggVorbis_File *vf, ogg_int64_t dataoffset){ |
358 ogg_page og={0,0,0,0}; |
307 ogg_page og={0,0,0,0}; |
359 int i; |
308 int i; |
360 ogg_int64_t ret; |
309 ogg_int64_t ret; |
361 |
310 |
|
311 vf->vi=_ogg_realloc(vf->vi,vf->links*sizeof(*vf->vi)); |
|
312 vf->vc=_ogg_realloc(vf->vc,vf->links*sizeof(*vf->vc)); |
362 vf->dataoffsets=_ogg_malloc(vf->links*sizeof(*vf->dataoffsets)); |
313 vf->dataoffsets=_ogg_malloc(vf->links*sizeof(*vf->dataoffsets)); |
363 vf->pcmlengths=_ogg_malloc(vf->links*2*sizeof(*vf->pcmlengths)); |
314 vf->pcmlengths=_ogg_malloc(vf->links*2*sizeof(*vf->pcmlengths)); |
364 |
315 |
365 for(i=0;i<vf->links;i++){ |
316 for(i=0;i<vf->links;i++){ |
366 if(i==0){ |
317 if(i==0){ |
491 vf->offset=vf->end=(vf->callbacks.tell_func)(vf->datasource); |
432 vf->offset=vf->end=(vf->callbacks.tell_func)(vf->datasource); |
492 |
433 |
493 /* We get the offset for the last page of the physical bitstream. |
434 /* We get the offset for the last page of the physical bitstream. |
494 Most OggVorbis files will contain a single logical bitstream */ |
435 Most OggVorbis files will contain a single logical bitstream */ |
495 end=_get_prev_page(vf,&og); |
436 end=_get_prev_page(vf,&og); |
496 if(end<0)return end; |
437 if(end<0)return(end); |
497 |
438 |
498 /* more than one logical bitstream? */ |
439 /* more than one logical bitstream? */ |
499 tempserialno=ogg_page_serialno(&og); |
440 tempserialno=ogg_page_serialno(&og); |
500 ogg_page_release(&og); |
441 ogg_page_release(&og); |
501 |
442 |
502 if(tempserialno!=serialno){ |
443 if(tempserialno!=serialno){ |
503 |
444 |
504 /* Chained bitstream. Bisect-search each logical bitstream |
445 /* Chained bitstream. Bisect-search each logical bitstream |
505 section. Do so based on serial number only */ |
446 section. Do so based on serial number only */ |
506 if(_bisect_forward_serialno(vf,0,0,end+1,serialno,0)<0)return OV_EREAD; |
447 if(_bisect_forward_serialno(vf,0,0,end+1,serialno,0)<0)return(OV_EREAD); |
507 |
448 |
508 }else{ |
449 }else{ |
509 |
450 |
510 /* Only one logical bitstream */ |
451 /* Only one logical bitstream */ |
511 if(_bisect_forward_serialno(vf,0,end,end+1,serialno,0))return OV_EREAD; |
452 if(_bisect_forward_serialno(vf,0,end,end+1,serialno,0))return(OV_EREAD); |
512 |
453 |
513 } |
454 } |
514 |
455 |
515 /* the initial header memory is referenced by vf after; don't free it */ |
456 /* the initial header memory is referenced by vf after; don't free it */ |
516 _prefetch_all_offsets(vf,dataoffset); |
457 _prefetch_all_headers(vf,dataoffset); |
517 return ov_raw_seek(vf,0); |
458 return(ov_raw_seek(vf,0)); |
|
459 } |
|
460 |
|
461 /* clear out the current logical bitstream decoder */ |
|
462 static void _decode_clear(OggVorbis_File *vf){ |
|
463 vorbis_dsp_clear(&vf->vd); |
|
464 vorbis_block_clear(&vf->vb); |
|
465 vf->ready_state=OPENED; |
518 } |
466 } |
519 |
467 |
520 /* fetch and process a packet. Handles the case where we're at a |
468 /* fetch and process a packet. Handles the case where we're at a |
521 bitstream boundary and dumps the decoding machine. If the decoding |
469 bitstream boundary and dumps the decoding machine. If the decoding |
522 machine is unloaded, it loads it. It also keeps pcm_offset up to |
470 machine is unloaded, it loads it. It also keeps pcm_offset up to |
660 if(link==vf->links){ |
625 if(link==vf->links){ |
661 ret=OV_EBADLINK; /* sign of a bogus stream. error out, |
626 ret=OV_EBADLINK; /* sign of a bogus stream. error out, |
662 leave machine uninitialized */ |
627 leave machine uninitialized */ |
663 goto cleanup; |
628 goto cleanup; |
664 } |
629 } |
665 |
630 |
666 vf->current_link=link; |
631 vf->current_link=link; |
667 ret=_fetch_headers(vf,&vf->vi,&vf->vc,&vf->current_serialno,&og); |
632 |
668 if(ret) goto cleanup; |
633 ogg_stream_reset_serialno(vf->os,vf->current_serialno); |
|
634 vf->ready_state=STREAMSET; |
669 |
635 |
670 }else{ |
636 }else{ |
671 /* we're streaming */ |
637 /* we're streaming */ |
672 /* fetch the three header packets, build the info struct */ |
638 /* fetch the three header packets, build the info struct */ |
673 |
639 |
674 int ret=_fetch_headers(vf,&vf->vi,&vf->vc,&vf->current_serialno,&og); |
640 int ret=_fetch_headers(vf,vf->vi,vf->vc,&vf->current_serialno,&og); |
675 if(ret) goto cleanup; |
641 if(ret) goto cleanup; |
676 vf->current_link++; |
642 vf->current_link++; |
|
643 link=0; |
677 } |
644 } |
678 } |
645 } |
679 |
646 |
680 if(_make_decode_ready(vf)) return OV_EBADLINK; |
647 _make_decode_ready(vf); |
681 } |
648 } |
682 ogg_stream_pagein(vf->os,&og); |
649 ogg_stream_pagein(vf->os,&og); |
683 } |
650 } |
684 cleanup: |
651 cleanup: |
685 ogg_packet_release(&op); |
652 ogg_packet_release(&op); |
688 } |
655 } |
689 |
656 |
690 /* if, eg, 64 bit stdio is configured by default, this will build with |
657 /* if, eg, 64 bit stdio is configured by default, this will build with |
691 fseek64 */ |
658 fseek64 */ |
692 static int _fseek64_wrap(FILE *f,ogg_int64_t off,int whence){ |
659 static int _fseek64_wrap(FILE *f,ogg_int64_t off,int whence){ |
693 if(f==NULL)return -1; |
660 if(f==NULL)return(-1); |
694 return fseek(f,off,whence); |
661 return fseek(f,off,whence); |
695 } |
662 } |
696 |
663 |
697 static int _ov_open1(void *f,OggVorbis_File *vf,char *initial, |
664 static int _ov_open1(void *f,OggVorbis_File *vf,char *initial, |
698 long ibytes, ov_callbacks callbacks){ |
665 long ibytes, ov_callbacks callbacks){ |
699 int offsettest=(f?callbacks.seek_func(f,0,SEEK_CUR):-1); |
666 int offsettest=(f?callbacks.seek_func(f,0,SEEK_CUR):-1); |
700 int ret; |
667 int ret; |
701 |
668 |
702 memset(vf,0,sizeof(*vf)); |
669 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; |
670 vf->datasource=f; |
709 vf->callbacks = callbacks; |
671 vf->callbacks = callbacks; |
710 |
672 |
711 /* init the framing state */ |
673 /* init the framing state */ |
712 vf->oy=ogg_sync_create(); |
674 vf->oy=ogg_sync_create(); |
745 int ret=_open_seekable2(vf); |
709 int ret=_open_seekable2(vf); |
746 if(ret){ |
710 if(ret){ |
747 vf->datasource=NULL; |
711 vf->datasource=NULL; |
748 ov_clear(vf); |
712 ov_clear(vf); |
749 } |
713 } |
750 return ret; |
714 return(ret); |
751 } |
715 } |
752 return 0; |
716 return 0; |
753 } |
717 } |
754 |
718 |
755 |
719 |
756 /* clear out the OggVorbis_File struct */ |
720 /* clear out the OggVorbis_File struct */ |
757 int ov_clear(OggVorbis_File *vf){ |
721 int ov_clear(OggVorbis_File *vf){ |
758 if(vf){ |
722 if(vf){ |
759 vorbis_dsp_destroy(vf->vd); |
723 vorbis_block_clear(&vf->vb); |
760 vf->vd=0; |
724 vorbis_dsp_clear(&vf->vd); |
761 ogg_stream_destroy(vf->os); |
725 ogg_stream_destroy(vf->os); |
762 vorbis_info_clear(&vf->vi); |
726 |
763 vorbis_comment_clear(&vf->vc); |
727 if(vf->vi && vf->links){ |
|
728 int i; |
|
729 for(i=0;i<vf->links;i++){ |
|
730 vorbis_info_clear(vf->vi+i); |
|
731 vorbis_comment_clear(vf->vc+i); |
|
732 } |
|
733 _ogg_free(vf->vi); |
|
734 _ogg_free(vf->vc); |
|
735 } |
764 if(vf->dataoffsets)_ogg_free(vf->dataoffsets); |
736 if(vf->dataoffsets)_ogg_free(vf->dataoffsets); |
765 if(vf->pcmlengths)_ogg_free(vf->pcmlengths); |
737 if(vf->pcmlengths)_ogg_free(vf->pcmlengths); |
766 if(vf->serialnos)_ogg_free(vf->serialnos); |
738 if(vf->serialnos)_ogg_free(vf->serialnos); |
767 if(vf->offsets)_ogg_free(vf->offsets); |
739 if(vf->offsets)_ogg_free(vf->offsets); |
768 ogg_sync_destroy(vf->oy); |
740 ogg_sync_destroy(vf->oy); |
769 |
741 |
770 if(vf->datasource)(vf->callbacks.close_func)(vf->datasource); |
742 if(vf->datasource && vf->callbacks.close_func) |
|
743 (vf->callbacks.close_func)(vf->datasource); |
771 memset(vf,0,sizeof(*vf)); |
744 memset(vf,0,sizeof(*vf)); |
772 } |
745 } |
773 #ifdef DEBUG_LEAKS |
746 #ifdef DEBUG_LEAKS |
774 _VDBG_dump(); |
747 _VDBG_dump(); |
775 #endif |
748 #endif |
776 return 0; |
749 return(0); |
777 } |
750 } |
778 |
751 |
779 /* inspects the OggVorbis file and finds/documents all the logical |
752 /* inspects the OggVorbis file and finds/documents all the logical |
780 bitstreams contained in it. Tries to be tolerant of logical |
753 bitstreams contained in it. Tries to be tolerant of logical |
781 bitstream sections that are truncated/woogie. |
754 bitstream sections that are truncated/woogie. |
847 |
820 |
848 If you want the actual bitrate field settings, get them from the |
821 If you want the actual bitrate field settings, get them from the |
849 vorbis_info structs */ |
822 vorbis_info structs */ |
850 |
823 |
851 long ov_bitrate(OggVorbis_File *vf,int i){ |
824 long ov_bitrate(OggVorbis_File *vf,int i){ |
852 if(vf->ready_state<OPENED)return OV_EINVAL; |
825 if(vf->ready_state<OPENED)return(OV_EINVAL); |
853 if(i>=vf->links)return OV_EINVAL; |
826 if(i>=vf->links)return(OV_EINVAL); |
854 if(!vf->seekable && i!=0)return ov_bitrate(vf,0); |
827 if(!vf->seekable && i!=0)return(ov_bitrate(vf,0)); |
855 if(i<0){ |
828 if(i<0){ |
856 ogg_int64_t bits=0; |
829 ogg_int64_t bits=0; |
857 int i; |
830 int i; |
858 for(i=0;i<vf->links;i++) |
831 for(i=0;i<vf->links;i++) |
859 bits+=(vf->offsets[i+1]-vf->dataoffsets[i])*8; |
832 bits+=(vf->offsets[i+1]-vf->dataoffsets[i])*8; |
860 /* This once read: return(rint(bits/ov_time_total(vf,-1))); |
833 /* 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, |
834 * gcc 3.x on x86 miscompiled this at optimisation level 2 and above, |
862 * so this is slightly transformed to make it work. |
835 * so this is slightly transformed to make it work. |
863 */ |
836 */ |
864 return bits*1000/ov_time_total(vf,-1); |
837 return(bits*1000/ov_time_total(vf,-1)); |
865 }else{ |
838 }else{ |
866 if(vf->seekable){ |
839 if(vf->seekable){ |
867 /* return the actual bitrate */ |
840 /* return the actual bitrate */ |
868 return (vf->offsets[i+1]-vf->dataoffsets[i])*8000/ov_time_total(vf,i); |
841 return((vf->offsets[i+1]-vf->dataoffsets[i])*8000/ov_time_total(vf,i)); |
869 }else{ |
842 }else{ |
870 /* return nominal if set */ |
843 /* return nominal if set */ |
871 if(vf->vi.bitrate_nominal>0){ |
844 if(vf->vi[i].bitrate_nominal>0){ |
872 return vf->vi.bitrate_nominal; |
845 return vf->vi[i].bitrate_nominal; |
873 }else{ |
846 }else{ |
874 if(vf->vi.bitrate_upper>0){ |
847 if(vf->vi[i].bitrate_upper>0){ |
875 if(vf->vi.bitrate_lower>0){ |
848 if(vf->vi[i].bitrate_lower>0){ |
876 return (vf->vi.bitrate_upper+vf->vi.bitrate_lower)/2; |
849 return (vf->vi[i].bitrate_upper+vf->vi[i].bitrate_lower)/2; |
877 }else{ |
850 }else{ |
878 return vf->vi.bitrate_upper; |
851 return vf->vi[i].bitrate_upper; |
879 } |
852 } |
880 } |
853 } |
881 return OV_FALSE; |
854 return(OV_FALSE); |
882 } |
855 } |
883 } |
856 } |
884 } |
857 } |
885 } |
858 } |
886 |
859 |
887 /* returns the actual bitrate since last call. returns -1 if no |
860 /* returns the actual bitrate since last call. returns -1 if no |
888 additional data to offer since last call (or at beginning of stream), |
861 additional data to offer since last call (or at beginning of stream), |
889 EINVAL if stream is only partially open |
862 EINVAL if stream is only partially open |
890 */ |
863 */ |
891 long ov_bitrate_instant(OggVorbis_File *vf){ |
864 long ov_bitrate_instant(OggVorbis_File *vf){ |
|
865 int link=(vf->seekable?vf->current_link:0); |
892 long ret; |
866 long ret; |
893 if(vf->ready_state<OPENED)return OV_EINVAL; |
867 if(vf->ready_state<OPENED)return(OV_EINVAL); |
894 if(vf->samptrack==0)return OV_FALSE; |
868 if(vf->samptrack==0)return(OV_FALSE); |
895 ret=vf->bittrack/vf->samptrack*vf->vi.rate; |
869 ret=vf->bittrack/vf->samptrack*vf->vi[link].rate; |
896 vf->bittrack=0; |
870 vf->bittrack=0; |
897 vf->samptrack=0; |
871 vf->samptrack=0; |
898 return ret; |
872 return(ret); |
899 } |
873 } |
900 |
874 |
901 /* Guess */ |
875 /* Guess */ |
902 long ov_serialnumber(OggVorbis_File *vf,int i){ |
876 long ov_serialnumber(OggVorbis_File *vf,int i){ |
903 if(i>=vf->links)return ov_serialnumber(vf,vf->links-1); |
877 if(i>=vf->links)return(ov_serialnumber(vf,vf->links-1)); |
904 if(!vf->seekable && i>=0)return ov_serialnumber(vf,-1); |
878 if(!vf->seekable && i>=0)return(ov_serialnumber(vf,-1)); |
905 if(i<0){ |
879 if(i<0){ |
906 return vf->current_serialno; |
880 return(vf->current_serialno); |
907 }else{ |
881 }else{ |
908 return vf->serialnos[i]; |
882 return(vf->serialnos[i]); |
909 } |
883 } |
910 } |
884 } |
911 |
885 |
912 /* returns: total raw (compressed) length of content if i==-1 |
886 /* returns: total raw (compressed) length of content if i==-1 |
913 raw (compressed) length of that logical bitstream for i==0 to n |
887 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) |
888 OV_EINVAL if the stream is not seekable (we can't know the length) |
915 or if stream is only partially open |
889 or if stream is only partially open |
916 */ |
890 */ |
917 ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i){ |
891 ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i){ |
918 if(vf->ready_state<OPENED)return OV_EINVAL; |
892 if(vf->ready_state<OPENED)return(OV_EINVAL); |
919 if(!vf->seekable || i>=vf->links)return OV_EINVAL; |
893 if(!vf->seekable || i>=vf->links)return(OV_EINVAL); |
920 if(i<0){ |
894 if(i<0){ |
921 ogg_int64_t acc=0; |
895 ogg_int64_t acc=0; |
922 int i; |
896 int i; |
923 for(i=0;i<vf->links;i++) |
897 for(i=0;i<vf->links;i++) |
924 acc+=ov_raw_total(vf,i); |
898 acc+=ov_raw_total(vf,i); |
925 return acc; |
899 return(acc); |
926 }else{ |
900 }else{ |
927 return vf->offsets[i+1]-vf->offsets[i]; |
901 return(vf->offsets[i+1]-vf->offsets[i]); |
928 } |
902 } |
929 } |
903 } |
930 |
904 |
931 /* returns: total PCM length (samples) of content if i==-1 PCM length |
905 /* returns: total PCM length (samples) of content if i==-1 PCM length |
932 (samples) of that logical bitstream for i==0 to n |
906 (samples) of that logical bitstream for i==0 to n |
933 OV_EINVAL if the stream is not seekable (we can't know the |
907 OV_EINVAL if the stream is not seekable (we can't know the |
934 length) or only partially open |
908 length) or only partially open |
935 */ |
909 */ |
936 ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i){ |
910 ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i){ |
937 if(vf->ready_state<OPENED)return OV_EINVAL; |
911 if(vf->ready_state<OPENED)return(OV_EINVAL); |
938 if(!vf->seekable || i>=vf->links)return OV_EINVAL; |
912 if(!vf->seekable || i>=vf->links)return(OV_EINVAL); |
939 if(i<0){ |
913 if(i<0){ |
940 ogg_int64_t acc=0; |
914 ogg_int64_t acc=0; |
941 int i; |
915 int i; |
942 for(i=0;i<vf->links;i++) |
916 for(i=0;i<vf->links;i++) |
943 acc+=ov_pcm_total(vf,i); |
917 acc+=ov_pcm_total(vf,i); |
944 return acc; |
918 return(acc); |
945 }else{ |
919 }else{ |
946 return vf->pcmlengths[i*2+1]; |
920 return(vf->pcmlengths[i*2+1]); |
947 } |
921 } |
948 } |
922 } |
949 |
923 |
950 /* returns: total milliseconds of content if i==-1 |
924 /* returns: total milliseconds of content if i==-1 |
951 milliseconds in that logical bitstream for i==0 to n |
925 milliseconds in that logical bitstream for i==0 to n |
952 OV_EINVAL if the stream is not seekable (we can't know the |
926 OV_EINVAL if the stream is not seekable (we can't know the |
953 length) or only partially open |
927 length) or only partially open |
954 */ |
928 */ |
955 ogg_int64_t ov_time_total(OggVorbis_File *vf,int i){ |
929 ogg_int64_t ov_time_total(OggVorbis_File *vf,int i){ |
956 if(vf->ready_state<OPENED)return OV_EINVAL; |
930 if(vf->ready_state<OPENED)return(OV_EINVAL); |
957 if(!vf->seekable || i>=vf->links)return OV_EINVAL; |
931 if(!vf->seekable || i>=vf->links)return(OV_EINVAL); |
958 if(i<0){ |
932 if(i<0){ |
959 ogg_int64_t acc=0; |
933 ogg_int64_t acc=0; |
960 int i; |
934 int i; |
961 for(i=0;i<vf->links;i++) |
935 for(i=0;i<vf->links;i++) |
962 acc+=ov_time_total(vf,i); |
936 acc+=ov_time_total(vf,i); |
963 return acc; |
937 return(acc); |
964 }else{ |
938 }else{ |
965 return ((ogg_int64_t)vf->pcmlengths[i*2+1])*1000/vf->vi.rate; |
939 return(((ogg_int64_t)vf->pcmlengths[i*2+1])*1000/vf->vi[i].rate); |
966 } |
940 } |
967 } |
941 } |
968 |
942 |
969 /* seek to an offset relative to the *compressed* data. This also |
943 /* seek to an offset relative to the *compressed* data. This also |
970 scans packets to update the PCM cursor. It will cross a logical |
944 scans packets to update the PCM cursor. It will cross a logical |
976 int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){ |
950 int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){ |
977 ogg_stream_state *work_os=NULL; |
951 ogg_stream_state *work_os=NULL; |
978 ogg_page og={0,0,0,0}; |
952 ogg_page og={0,0,0,0}; |
979 ogg_packet op={0,0,0,0,0,0}; |
953 ogg_packet op={0,0,0,0,0,0}; |
980 |
954 |
981 if(vf->ready_state<OPENED)return OV_EINVAL; |
955 if(vf->ready_state<OPENED)return(OV_EINVAL); |
982 if(!vf->seekable) |
956 if(!vf->seekable) |
983 return OV_ENOSEEK; /* don't dump machine if we can't seek */ |
957 return(OV_ENOSEEK); /* don't dump machine if we can't seek */ |
984 |
958 |
985 if(pos<0 || pos>vf->end)return OV_EINVAL; |
959 if(pos<0 || pos>vf->end)return(OV_EINVAL); |
986 |
960 |
987 /* don't yet clear out decoding machine (if it's initialized), in |
961 /* 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 |
962 the case we're in the same link. Restart the decode lapping, and |
989 let _fetch_and_process_packet deal with a potential bitstream |
963 let _fetch_and_process_packet deal with a potential bitstream |
990 boundary */ |
964 boundary */ |
991 vf->pcm_offset=-1; |
965 vf->pcm_offset=-1; |
992 ogg_stream_reset_serialno(vf->os, |
966 ogg_stream_reset_serialno(vf->os, |
993 vf->current_serialno); /* must set serialno */ |
967 vf->current_serialno); /* must set serialno */ |
994 vorbis_dsp_restart(vf->vd); |
968 vorbis_synthesis_restart(&vf->vd); |
995 |
969 |
996 _seek_helper(vf,pos); |
970 _seek_helper(vf,pos); |
997 |
971 |
998 /* we need to make sure the pcm_offset is set, but we don't want to |
972 /* 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 |
973 advance the raw cursor past good packets just to get to the first |
1132 ogg_int64_t result=0; |
1103 ogg_int64_t result=0; |
1133 ogg_int64_t total=ov_pcm_total(vf,-1); |
1104 ogg_int64_t total=ov_pcm_total(vf,-1); |
1134 ogg_page og={0,0,0,0}; |
1105 ogg_page og={0,0,0,0}; |
1135 ogg_packet op={0,0,0,0,0,0}; |
1106 ogg_packet op={0,0,0,0,0,0}; |
1136 |
1107 |
1137 if(vf->ready_state<OPENED)return OV_EINVAL; |
1108 if(vf->ready_state<OPENED)return(OV_EINVAL); |
1138 if(!vf->seekable)return OV_ENOSEEK; |
1109 if(!vf->seekable)return(OV_ENOSEEK); |
1139 if(pos<0 || pos>total)return OV_EINVAL; |
1110 if(pos<0 || pos>total)return(OV_EINVAL); |
1140 |
1111 |
1141 /* which bitstream section does this pcm offset occur in? */ |
1112 /* which bitstream section does this pcm offset occur in? */ |
1142 for(link=vf->links-1;link>=0;link--){ |
1113 for(link=vf->links-1;link>=0;link--){ |
1143 total-=vf->pcmlengths[link*2+1]; |
1114 total-=vf->pcmlengths[link*2+1]; |
1144 if(pos>=total)break; |
1115 if(pos>=total)break; |
1145 } |
1116 } |
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 |
1117 |
1157 /* search within the logical bitstream for the page with the highest |
1118 /* search within the logical bitstream for the page with the highest |
1158 pcm_pos preceeding (or equal to) pos. There is a danger here; |
1119 pcm_pos preceeding (or equal to) pos. There is a danger here; |
1159 missing pages or incorrect frame number information in the |
1120 missing pages or incorrect frame number information in the |
1160 bitstream could make our task impossible. Account for that (it |
1121 bitstream could make our task impossible. Account for that (it |
1306 int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){ |
1280 int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){ |
1307 ogg_packet op={0,0,0,0,0,0}; |
1281 ogg_packet op={0,0,0,0,0,0}; |
1308 ogg_page og={0,0,0,0}; |
1282 ogg_page og={0,0,0,0}; |
1309 int thisblock,lastblock=0; |
1283 int thisblock,lastblock=0; |
1310 int ret=ov_pcm_seek_page(vf,pos); |
1284 int ret=ov_pcm_seek_page(vf,pos); |
1311 if(ret<0)return ret; |
1285 if(ret<0)return(ret); |
1312 if(_make_decode_ready(vf))return OV_EBADLINK; |
1286 _make_decode_ready(vf); |
1313 |
1287 |
1314 /* discard leading packets we don't need for the lapping of the |
1288 /* discard leading packets we don't need for the lapping of the |
1315 position we want; don't decode them */ |
1289 position we want; don't decode them */ |
1316 |
1290 |
1317 while(1){ |
1291 while(1){ |
1318 |
1292 |
1319 int ret=ogg_stream_packetpeek(vf->os,&op); |
1293 int ret=ogg_stream_packetpeek(vf->os,&op); |
1320 if(ret>0){ |
1294 if(ret>0){ |
1321 thisblock=vorbis_packet_blocksize(&vf->vi,&op); |
1295 thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op); |
1322 if(thisblock<0){ |
1296 if(thisblock<0){ |
1323 ogg_stream_packetout(vf->os,NULL); |
1297 ogg_stream_packetout(vf->os,NULL); |
1324 continue; /* non audio packet */ |
1298 continue; /* non audio packet */ |
1325 } |
1299 } |
1326 if(lastblock)vf->pcm_offset+=(lastblock+thisblock)>>2; |
1300 if(lastblock)vf->pcm_offset+=(lastblock+thisblock)>>2; |
1327 |
1301 |
1328 if(vf->pcm_offset+((thisblock+ |
1302 if(vf->pcm_offset+((thisblock+ |
1329 vorbis_info_blocksize(&vf->vi,1))>>2)>=pos)break; |
1303 vorbis_info_blocksize(vf->vi,1))>>2)>=pos)break; |
1330 |
1304 |
1331 /* remove the packet from packet queue and track its granulepos */ |
1305 /* remove the packet from packet queue and track its granulepos */ |
1332 ogg_stream_packetout(vf->os,NULL); |
1306 ogg_stream_packetout(vf->os,NULL); |
1333 vorbis_dsp_synthesis(vf->vd,&op,0); /* set up a vb with |
1307 vorbis_synthesis(&vf->vb,&op,0); /* set up a vb with |
1334 only tracking, no |
1308 only tracking, no |
1335 pcm_decode */ |
1309 pcm_decode */ |
|
1310 vorbis_synthesis_blockin(&vf->vd,&vf->vb); |
1336 |
1311 |
1337 /* end of logical stream case is hard, especially with exact |
1312 /* end of logical stream case is hard, especially with exact |
1338 length positioning. */ |
1313 length positioning. */ |
1339 |
1314 |
1340 if(op.granulepos>-1){ |
1315 if(op.granulepos>-1){ |
1354 /* suck in a new page */ |
1329 /* suck in a new page */ |
1355 if(_get_next_page(vf,&og,-1)<0)break; |
1330 if(_get_next_page(vf,&og,-1)<0)break; |
1356 if(vf->current_serialno!=ogg_page_serialno(&og))_decode_clear(vf); |
1331 if(vf->current_serialno!=ogg_page_serialno(&og))_decode_clear(vf); |
1357 |
1332 |
1358 if(vf->ready_state<STREAMSET){ |
1333 if(vf->ready_state<STREAMSET){ |
1359 int link,ret; |
1334 int link; |
1360 |
1335 |
1361 vf->current_serialno=ogg_page_serialno(&og); |
1336 vf->current_serialno=ogg_page_serialno(&og); |
1362 for(link=0;link<vf->links;link++) |
1337 for(link=0;link<vf->links;link++) |
1363 if(vf->serialnos[link]==vf->current_serialno)break; |
1338 if(vf->serialnos[link]==vf->current_serialno)break; |
1364 if(link==vf->links){ |
1339 if(link==vf->links){ |
1365 ogg_page_release(&og); |
1340 ogg_page_release(&og); |
1366 ogg_packet_release(&op); |
1341 ogg_packet_release(&op); |
1367 return OV_EBADLINK; |
1342 return(OV_EBADLINK); |
1368 } |
1343 } |
1369 |
|
1370 |
|
1371 vf->current_link=link; |
1344 vf->current_link=link; |
1372 ret=_fetch_headers(vf,&vf->vi,&vf->vc,&vf->current_serialno,&og); |
1345 |
1373 if(ret) return ret; |
1346 ogg_stream_reset_serialno(vf->os,vf->current_serialno); |
1374 if(_make_decode_ready(vf))return OV_EBADLINK; |
1347 vf->ready_state=STREAMSET; |
|
1348 _make_decode_ready(vf); |
1375 lastblock=0; |
1349 lastblock=0; |
1376 } |
1350 } |
1377 |
1351 |
1378 ogg_stream_pagein(vf->os,&og); |
1352 ogg_stream_pagein(vf->os,&og); |
1379 } |
1353 } |
1408 |
1382 |
1409 int link=-1; |
1383 int link=-1; |
1410 ogg_int64_t pcm_total=ov_pcm_total(vf,-1); |
1384 ogg_int64_t pcm_total=ov_pcm_total(vf,-1); |
1411 ogg_int64_t time_total=ov_time_total(vf,-1); |
1385 ogg_int64_t time_total=ov_time_total(vf,-1); |
1412 |
1386 |
1413 if(vf->ready_state<OPENED)return OV_EINVAL; |
1387 if(vf->ready_state<OPENED)return(OV_EINVAL); |
1414 if(!vf->seekable)return OV_ENOSEEK; |
1388 if(!vf->seekable)return(OV_ENOSEEK); |
1415 if(milliseconds<0 || milliseconds>time_total)return OV_EINVAL; |
1389 if(milliseconds<0 || milliseconds>time_total)return(OV_EINVAL); |
1416 |
1390 |
1417 /* which bitstream section does this time offset occur in? */ |
1391 /* which bitstream section does this time offset occur in? */ |
1418 for(link=vf->links-1;link>=0;link--){ |
1392 for(link=vf->links-1;link>=0;link--){ |
1419 pcm_total-=vf->pcmlengths[link*2+1]; |
1393 pcm_total-=vf->pcmlengths[link*2+1]; |
1420 time_total-=ov_time_total(vf,link); |
1394 time_total-=ov_time_total(vf,link); |
1421 if(milliseconds>=time_total)break; |
1395 if(milliseconds>=time_total)break; |
1422 } |
1396 } |
1423 |
1397 |
1424 /* enough information to convert time offset to pcm offset */ |
1398 /* enough information to convert time offset to pcm offset */ |
1425 { |
1399 { |
1426 int ret=_set_link_number(vf,link); |
1400 ogg_int64_t target=pcm_total+(milliseconds-time_total)*vf->vi[link].rate/1000; |
1427 if(ret)return ret; |
1401 return(ov_pcm_seek(vf,target)); |
1428 return |
|
1429 ov_pcm_seek(vf,pcm_total+(milliseconds-time_total)* |
|
1430 vf->vi.rate/1000); |
|
1431 } |
1402 } |
1432 } |
1403 } |
1433 |
1404 |
1434 /* page-granularity version of ov_time_seek |
1405 /* page-granularity version of ov_time_seek |
1435 returns zero on success, nonzero on failure */ |
1406 returns zero on success, nonzero on failure */ |
1438 |
1409 |
1439 int link=-1; |
1410 int link=-1; |
1440 ogg_int64_t pcm_total=ov_pcm_total(vf,-1); |
1411 ogg_int64_t pcm_total=ov_pcm_total(vf,-1); |
1441 ogg_int64_t time_total=ov_time_total(vf,-1); |
1412 ogg_int64_t time_total=ov_time_total(vf,-1); |
1442 |
1413 |
1443 if(vf->ready_state<OPENED)return OV_EINVAL; |
1414 if(vf->ready_state<OPENED)return(OV_EINVAL); |
1444 if(!vf->seekable)return OV_ENOSEEK; |
1415 if(!vf->seekable)return(OV_ENOSEEK); |
1445 if(milliseconds<0 || milliseconds>time_total)return OV_EINVAL; |
1416 if(milliseconds<0 || milliseconds>time_total)return(OV_EINVAL); |
1446 |
1417 |
1447 /* which bitstream section does this time offset occur in? */ |
1418 /* which bitstream section does this time offset occur in? */ |
1448 for(link=vf->links-1;link>=0;link--){ |
1419 for(link=vf->links-1;link>=0;link--){ |
1449 pcm_total-=vf->pcmlengths[link*2+1]; |
1420 pcm_total-=vf->pcmlengths[link*2+1]; |
1450 time_total-=ov_time_total(vf,link); |
1421 time_total-=ov_time_total(vf,link); |
1451 if(milliseconds>=time_total)break; |
1422 if(milliseconds>=time_total)break; |
1452 } |
1423 } |
1453 |
1424 |
1454 /* enough information to convert time offset to pcm offset */ |
1425 /* enough information to convert time offset to pcm offset */ |
1455 { |
1426 { |
1456 int ret=_set_link_number(vf,link); |
1427 ogg_int64_t target=pcm_total+(milliseconds-time_total)*vf->vi[link].rate/1000; |
1457 if(ret)return ret; |
1428 return(ov_pcm_seek_page(vf,target)); |
1458 return |
|
1459 ov_pcm_seek_page(vf,pcm_total+(milliseconds-time_total)* |
|
1460 vf->vi.rate/1000); |
|
1461 } |
1429 } |
1462 } |
1430 } |
1463 |
1431 |
1464 /* tell the current stream offset cursor. Note that seek followed by |
1432 /* tell the current stream offset cursor. Note that seek followed by |
1465 tell will likely not give the set offset due to caching */ |
1433 tell will likely not give the set offset due to caching */ |
1466 ogg_int64_t ov_raw_tell(OggVorbis_File *vf){ |
1434 ogg_int64_t ov_raw_tell(OggVorbis_File *vf){ |
1467 if(vf->ready_state<OPENED)return OV_EINVAL; |
1435 if(vf->ready_state<OPENED)return(OV_EINVAL); |
1468 return vf->offset; |
1436 return(vf->offset); |
1469 } |
1437 } |
1470 |
1438 |
1471 /* return PCM offset (sample) of next PCM sample to be read */ |
1439 /* return PCM offset (sample) of next PCM sample to be read */ |
1472 ogg_int64_t ov_pcm_tell(OggVorbis_File *vf){ |
1440 ogg_int64_t ov_pcm_tell(OggVorbis_File *vf){ |
1473 if(vf->ready_state<OPENED)return OV_EINVAL; |
1441 if(vf->ready_state<OPENED)return(OV_EINVAL); |
1474 return vf->pcm_offset; |
1442 return(vf->pcm_offset); |
1475 } |
1443 } |
1476 |
1444 |
1477 /* return time offset (milliseconds) of next PCM sample to be read */ |
1445 /* return time offset (milliseconds) of next PCM sample to be read */ |
1478 ogg_int64_t ov_time_tell(OggVorbis_File *vf){ |
1446 ogg_int64_t ov_time_tell(OggVorbis_File *vf){ |
1479 int link=0; |
1447 int link=0; |
1480 ogg_int64_t pcm_total=0; |
1448 ogg_int64_t pcm_total=0; |
1481 ogg_int64_t time_total=0; |
1449 ogg_int64_t time_total=0; |
1482 |
1450 |
1483 if(vf->ready_state<OPENED)return OV_EINVAL; |
1451 if(vf->ready_state<OPENED)return(OV_EINVAL); |
1484 if(vf->seekable){ |
1452 if(vf->seekable){ |
1485 pcm_total=ov_pcm_total(vf,-1); |
1453 pcm_total=ov_pcm_total(vf,-1); |
1486 time_total=ov_time_total(vf,-1); |
1454 time_total=ov_time_total(vf,-1); |
1487 |
1455 |
1488 /* which bitstream section does this time offset occur in? */ |
1456 /* which bitstream section does this time offset occur in? */ |
1552 return length is not related to the 'length' passed |
1532 return length is not related to the 'length' passed |
1553 in, just guaranteed to fit. |
1533 in, just guaranteed to fit. |
1554 |
1534 |
1555 *section) set to the logical bitstream number */ |
1535 *section) set to the logical bitstream number */ |
1556 |
1536 |
1557 long ov_read(OggVorbis_File *vf,void *buffer,int bytes_req,int *bitstream){ |
1537 long ov_read(OggVorbis_File *vf,char *buffer,int bytes_req,int *bitstream){ |
1558 |
1538 int i,j; |
|
1539 |
|
1540 ogg_int32_t **pcm; |
1559 long samples; |
1541 long samples; |
1560 long channels; |
1542 |
1561 |
1543 if(vf->ready_state<OPENED)return(OV_EINVAL); |
1562 if(vf->ready_state<OPENED)return OV_EINVAL; |
|
1563 |
1544 |
1564 while(1){ |
1545 while(1){ |
1565 if(vf->ready_state==INITSET){ |
1546 if(vf->ready_state==INITSET){ |
1566 channels=vf->vi.channels; |
1547 samples=vorbis_synthesis_pcmout(&vf->vd,&pcm); |
1567 samples=vorbis_dsp_pcmout(vf->vd,buffer,(bytes_req>>1)/channels); |
1548 if(samples)break; |
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 } |
1549 } |
1578 |
1550 |
1579 /* suck in another packet */ |
1551 /* suck in another packet */ |
1580 { |
1552 { |
1581 int ret=_fetch_and_process_packet(vf,1,1); |
1553 int ret=_fetch_and_process_packet(vf,1,1); |
1582 if(ret==OV_EOF) |
1554 if(ret==OV_EOF) |
1583 return 0; |
1555 return(0); |
1584 if(ret<=0) |
1556 if(ret<=0) |
1585 return ret; |
1557 return(ret); |
1586 } |
1558 } |
1587 |
1559 |
1588 } |
1560 } |
1589 } |
1561 |
|
1562 if(samples>0){ |
|
1563 |
|
1564 /* yay! proceed to pack data into the byte buffer */ |
|
1565 |
|
1566 long channels=ov_info(vf,-1)->channels; |
|
1567 |
|
1568 if(samples>(bytes_req/(2*channels))) |
|
1569 samples=bytes_req/(2*channels); |
|
1570 |
|
1571 for(i=0;i<channels;i++) { /* It's faster in this order */ |
|
1572 ogg_int32_t *src=pcm[i]; |
|
1573 short *dest=((short *)buffer)+i; |
|
1574 for(j=0;j<samples;j++) { |
|
1575 *dest=CLIP_TO_15(src[j]>>9); |
|
1576 dest+=channels; |
|
1577 } |
|
1578 } |
|
1579 |
|
1580 vorbis_synthesis_read(&vf->vd,samples); |
|
1581 vf->pcm_offset+=samples; |
|
1582 if(bitstream)*bitstream=vf->current_link; |
|
1583 return(samples*2*channels); |
|
1584 }else{ |
|
1585 return(samples); |
|
1586 } |
|
1587 } |