[xiph-cvs] cvs commit: vorbis/lib block.c synthesis.c vorbisfile.c
Monty
xiphmont at xiph.org
Sat May 26 22:52:24 PDT 2001
xiphmont 01/05/26 22:52:23
Modified: examples Tag: monty-branch-20010404 seeking_example.c
include/vorbis Tag: monty-branch-20010404 codec.h
vorbisfile.h
lib Tag: monty-branch-20010404 block.c synthesis.c
vorbisfile.c
Log:
New seeking example/tets script (that will find both vorbisfile bugs
and bad bitstreams)
Completed vorbisfile optimizations, many seeking bugfixes.
Fixed one bug in libvorbis (vorbis_synthesis_pcmout gave an invalid
positive answer if vorbis_synthesis_blockin had not yet been called)
Monty
Revision Changes Path
No revision
No revision
1.7.4.1 +145 -12 vorbis/examples/seeking_example.c
Index: seeking_example.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis/examples/seeking_example.c,v
retrieving revision 1.7
retrieving revision 1.7.4.1
diff -u -r1.7 -r1.7.4.1
--- seeking_example.c 2001/02/26 03:50:38 1.7
+++ seeking_example.c 2001/05/27 05:52:20 1.7.4.1
@@ -11,7 +11,7 @@
********************************************************************
function: illustrate seeking, and test it too
- last mod: $Id: seeking_example.c,v 1.7 2001/02/26 03:50:38 xiphmont Exp $
+ last mod: $Id: seeking_example.c,v 1.7.4.1 2001/05/27 05:52:20 xiphmont Exp $
********************************************************************/
@@ -21,28 +21,161 @@
#include "vorbis/vorbisfile.h"
#include "../lib/misc.h"
+
+void _verify(OggVorbis_File *ov,ogg_int64_t pos,
+ ogg_int64_t val,ogg_int64_t pcmval,
+ ogg_int64_t pcmlength,
+ char *bigassbuffer){
+ int j;
+ long bread;
+ char buffer[4096];
+ int dummy;
+
+ /* verify the raw position, the pcm position and position decode */
+ if(val!=-1 && ov_raw_tell(ov)<val){
+ printf("raw position out of tolerance: requested %ld, got %ld\n",
+ (long)val,(long)ov_raw_tell(ov));
+ exit(1);
+ }
+ if(pcmval!=-1 && ov_pcm_tell(ov)>pcmval){
+ printf("pcm position out of tolerance: requested %ld, got %ld\n",
+ (long)pcmval,(long)ov_pcm_tell(ov));
+ exit(1);
+ }
+ pos=ov_pcm_tell(ov);
+ if(pos<0 || pos>pcmlength){
+ printf("pcm position out of bounds: got %ld\n",(long)pos);
+ exit(1);
+ }
+ bread=ov_read(ov,buffer,4096,1,1,1,&dummy);
+ for(j=0;j<bread;j++){
+ if(buffer[j]!=bigassbuffer[j+pos*2]){
+ printf("data position after seek doesn't match pcm position\n");
+ exit(1);
+ }
+ }
+}
+
int main(){
OggVorbis_File ov;
- int i;
+ int i,ret;
+ ogg_int64_t pcmlength;
+ char *bigassbuffer;
+ int dummy;
/* open the file/pipe on stdin */
if(ov_open(stdin,&ov,NULL,-1)<0){
printf("Could not open input as an OggVorbis file.\n\n");
exit(1);
}
-
- /* print details about each logical bitstream in the input */
+
if(ov_seekable(&ov)){
- double length=ov_time_total(&ov,-1);
- printf("testing seeking to random places in %g seconds....\n",length);
- for(i=0;i<100;i++){
- double val=(double)rand()/RAND_MAX*length;
- ov_time_seek(&ov,val);
- printf("\r\t%d [%gs]... ",i,val);
- fflush(stdout);
+
+ /* to simplify our own lives, we want to assume the whole file is
+ stereo. Verify this to avoid potentially mystifying users
+ (pissing them off is OK, just don't confuse them) */
+ for(i=0;i<ov.links;i++){
+ vorbis_info *vi=ov_info(&ov,i);
+ if(vi->channels!=2){
+ printf("Sorry; right now seeking_test can only use Vorbis files\n"
+ "that are entirely stereo.\n\n");
+ exit(1);
+ }
+ }
+
+ /* because we want to do sample-level verification that the seek
+ does what it claimed, decode the entire file into memory */
+ printf("loading....\n");
+ fflush(stdout);
+ pcmlength=ov_pcm_total(&ov,-1);
+ bigassbuffer=malloc(pcmlength*2); /* w00t */
+ i=0;
+ while(i<pcmlength*2){
+ int ret=ov_read(&ov,bigassbuffer+i,pcmlength*2-i,1,1,1,&dummy);
+ if(ret<0)continue;
+ if(ret){
+ i+=ret;
+ }else{
+ pcmlength=i/2;
+ }
+ }
+
+ /* Exercise all the real seeking cases; ov_raw_seek,
+ ov_pcm_seek_page and ov_pcm_seek. time seek is just a wrapper
+ on pcm_seek */
+ {
+ ogg_int64_t length=ov.end;
+ printf("testing raw seeking to random places in %ld bytes....\n",
+ (long)length);
+
+ for(i=0;i<1000;i++){
+ ogg_int64_t val=(double)rand()/RAND_MAX*length;
+ ogg_int64_t pos;
+ printf("\r\t%d [raw position %ld]... ",i,(long)val);
+ fflush(stdout);
+ ret=ov_raw_seek(&ov,val);
+ if(ret<0){
+ printf("seek failed: %d\n",ret);
+ exit(1);
+ }
+
+ _verify(&ov,pos,val,-1,pcmlength,bigassbuffer);
+
+ }
+ }
+
+ printf("\r");
+ {
+ ogg_int64_t length=ov.end;
+ printf("testing pcm page seeking to random places in %ld samples....\n",
+ (long)pcmlength);
+
+ for(i=0;i<1000;i++){
+ ogg_int64_t val=(double)rand()/RAND_MAX*pcmlength;
+ ogg_int64_t pos;
+ printf("\r\t%d [pcm position %ld]... ",i,(long)val);
+ fflush(stdout);
+ ret=ov_pcm_seek_page(&ov,val);
+ if(ret<0){
+ printf("seek failed: %d\n",ret);
+ exit(1);
+ }
+
+ _verify(&ov,pos,-1,val,pcmlength,bigassbuffer);
+
+ }
+ }
+
+ printf("\r");
+ {
+ ogg_int64_t length=ov.end;
+ printf("testing pcm exact seeking to random places in %ld samples....\n",
+ (long)pcmlength);
+
+ for(i=0;i<1000;i++){
+ ogg_int64_t val=(double)rand()/RAND_MAX*pcmlength;
+ ogg_int64_t pos;
+ printf("\r\t%d [pcm position %ld]... ",i,(long)val);
+ fflush(stdout);
+ ret=ov_pcm_seek(&ov,val);
+ if(ret<0){
+ printf("seek failed: %d\n",ret);
+ exit(1);
+ }
+ if(ov_pcm_tell(&ov)!=val){
+ printf("Decalred position didn't perfectly match request: %ld != %ld\n",
+ (long)val,(long)ov_pcm_tell(&ov));
+ exit(1);
+ }
+
+ _verify(&ov,pos,-1,val,pcmlength,bigassbuffer);
+
+ }
}
- printf("\r \nOK.\n\n");
+ printf("\r \nOK.\n\n");
+
+
}else{
printf("Standard input was not seekable.\n");
}
No revision
No revision
1.37.4.1 +2 -1 vorbis/include/vorbis/codec.h
Index: codec.h
===================================================================
RCS file: /usr/local/cvsroot/vorbis/include/vorbis/codec.h,v
retrieving revision 1.37
retrieving revision 1.37.4.1
diff -u -r1.37 -r1.37.4.1
--- codec.h 2001/02/26 03:50:39 1.37
+++ codec.h 2001/05/27 05:52:21 1.37.4.1
@@ -11,7 +11,7 @@
********************************************************************
function: libvorbis codec headers
- last mod: $Id: codec.h,v 1.37 2001/02/26 03:50:39 xiphmont Exp $
+ last mod: $Id: codec.h,v 1.37.4.1 2001/05/27 05:52:21 xiphmont Exp $
********************************************************************/
@@ -199,6 +199,7 @@
extern int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb);
extern int vorbis_synthesis_pcmout(vorbis_dsp_state *v,float ***pcm);
extern int vorbis_synthesis_read(vorbis_dsp_state *v,int samples);
+extern long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op);
/* Vorbis ERRORS and return codes ***********************************/
1.13.4.1 +22 -12 vorbis/include/vorbis/vorbisfile.h
Index: vorbisfile.h
===================================================================
RCS file: /usr/local/cvsroot/vorbis/include/vorbis/vorbisfile.h,v
retrieving revision 1.13
retrieving revision 1.13.4.1
diff -u -r1.13 -r1.13.4.1
--- vorbisfile.h 2001/02/26 03:50:39 1.13
+++ vorbisfile.h 2001/05/27 05:52:21 1.13.4.1
@@ -11,7 +11,7 @@
********************************************************************
function: stdio-based convenience library for opening/seeking/decoding
- last mod: $Id: vorbisfile.h,v 1.13 2001/02/26 03:50:39 xiphmont Exp $
+ last mod: $Id: vorbisfile.h,v 1.13.4.1 2001/05/27 05:52:21 xiphmont Exp $
********************************************************************/
@@ -43,27 +43,32 @@
long (*tell_func) (void *datasource);
} ov_callbacks;
+#define NOTOPEN 0
+#define PARTOPEN 1
+#define OPENED 2
+#define STREAMSET 3
+#define INITSET 4
typedef struct OggVorbis_File {
- void *datasource; /* Pointer to a FILE *, etc. */
+ void *datasource; /* Pointer to a FILE *, etc. */
int seekable;
- ogg_int64_t offset;
- ogg_int64_t end;
+ ogg_int64_t offset;
+ ogg_int64_t end;
ogg_sync_state oy;
/* If the FILE handle isn't seekable (eg, a pipe), only the current
stream appears */
int links;
- ogg_int64_t *offsets;
- ogg_int64_t *dataoffsets;
- long *serialnos;
- ogg_int64_t *pcmlengths;
- vorbis_info *vi;
- vorbis_comment *vc;
+ ogg_int64_t *offsets;
+ ogg_int64_t *dataoffsets;
+ long *serialnos;
+ ogg_int64_t *pcmlengths;
+ vorbis_info *vi;
+ vorbis_comment *vc;
/* Decoding working state local storage */
- ogg_int64_t pcm_offset;
- int decode_ready;
+ ogg_int64_t pcm_offset;
+ int ready_state;
long current_serialno;
int current_link;
@@ -83,6 +88,11 @@
extern int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes);
extern int ov_open_callbacks(void *datasource, OggVorbis_File *vf,
char *initial, long ibytes, ov_callbacks callbacks);
+
+extern int ov_test(FILE *f,OggVorbis_File *vf,char *initial,long ibytes);
+extern int ov_test_callbacks(void *datasource, OggVorbis_File *vf,
+ char *initial, long ibytes, ov_callbacks callbacks);
+extern int ov_test_open(OggVorbis_File *vf);
extern long ov_bitrate(OggVorbis_File *vf,int i);
extern long ov_bitrate_instant(OggVorbis_File *vf);
No revision
No revision
1.47.4.1 +2 -2 vorbis/lib/block.c
Index: block.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis/lib/block.c,v
retrieving revision 1.47
retrieving revision 1.47.4.1
diff -u -r1.47 -r1.47.4.1
--- block.c 2001/03/26 23:27:42 1.47
+++ block.c 2001/05/27 05:52:22 1.47.4.1
@@ -11,7 +11,7 @@
********************************************************************
function: PCM data vector blocking, windowing and dis/reassembly
- last mod: $Id: block.c,v 1.47 2001/03/26 23:27:42 xiphmont Exp $
+ last mod: $Id: block.c,v 1.47.4.1 2001/05/27 05:52:22 xiphmont Exp $
Handle windowing, overlap-add, etc of the PCM vectors. This is made
more amusing by Vorbis' current two allowed block sizes.
@@ -787,7 +787,7 @@
/* pcm==NULL indicates we just want the pending samples, no more */
int vorbis_synthesis_pcmout(vorbis_dsp_state *v,float ***pcm){
vorbis_info *vi=v->vi;
- if(v->pcm_returned<v->centerW){
+ if(v->pcm_returned>-1 && v->pcm_returned<v->centerW){
if(pcm){
int i;
for(i=0;i<vi->channels;i++)
1.21.4.1 +29 -1 vorbis/lib/synthesis.c
Index: synthesis.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis/lib/synthesis.c,v
retrieving revision 1.21
retrieving revision 1.21.4.1
diff -u -r1.21 -r1.21.4.1
--- synthesis.c 2001/02/26 03:50:43 1.21
+++ synthesis.c 2001/05/27 05:52:22 1.21.4.1
@@ -11,7 +11,7 @@
********************************************************************
function: single-block PCM synthesis
- last mod: $Id: synthesis.c,v 1.21 2001/02/26 03:50:43 xiphmont Exp $
+ last mod: $Id: synthesis.c,v 1.21.4.1 2001/05/27 05:52:22 xiphmont Exp $
********************************************************************/
@@ -70,6 +70,34 @@
type=ci->map_type[ci->mode_param[mode]->mapping];
return(_mapping_P[type]->inverse(vb,b->mode[mode]));
+}
+
+long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op){
+ codec_setup_info *ci=vi->codec_setup;
+ oggpack_buffer opb;
+ int type,mode,i;
+
+ oggpack_readinit(&opb,op->packet,op->bytes);
+
+ /* Check the packet type */
+ if(oggpack_read(&opb,1)!=0){
+ /* Oops. This is not an audio data packet */
+ return(OV_ENOTAUDIO);
+ }
+
+ {
+ int modebits=0;
+ int v=ci->modes;
+ while(v>1){
+ modebits++;
+ v>>=1;
+ }
+
+ /* read our mode and pre/post windowsize */
+ mode=oggpack_read(&opb,modebits);
+ }
+ if(mode==-1)return(OV_EBADPACKET);
+ return(ci->blocksizes[ci->mode_param[mode]->blockflag]);
}
1.44.4.1 +463 -215 vorbis/lib/vorbisfile.c
Index: vorbisfile.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis/lib/vorbisfile.c,v
retrieving revision 1.44
retrieving revision 1.44.4.1
diff -u -r1.44 -r1.44.4.1
--- vorbisfile.c 2001/03/27 07:04:51 1.44
+++ vorbisfile.c 2001/05/27 05:52:22 1.44.4.1
@@ -7,11 +7,11 @@
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 *
* by the XIPHOPHORUS Company http://www.xiph.org/ *
-
+ * *
********************************************************************
function: stdio-based convenience library for opening/seeking/decoding
- last mod: $Id: vorbisfile.c,v 1.44 2001/03/27 07:04:51 xiphmont Exp $
+ last mod: $Id: vorbisfile.c,v 1.44.4.1 2001/05/27 05:52:22 xiphmont Exp $
********************************************************************/
@@ -57,7 +57,8 @@
* grokking near the end of the file */
/* read a little more data from the file/pipe into the ogg_sync framer */
-#define CHUNKSIZE 4096
+#define CHUNKSIZE 8500 /* a shade over 8k; anyone using pages well
+ over 8k gets what they deserve */
static long _get_data(OggVorbis_File *vf){
errno=0;
if(vf->datasource){
@@ -233,6 +234,7 @@
if(serialno)*serialno=ogg_page_serialno(og_ptr);
ogg_stream_init(&vf->os,ogg_page_serialno(og_ptr));
+ vf->ready_state=STREAMSET;
/* extract the initial header from the first page and verify that the
Ogg bitstream is in fact Vorbis data */
@@ -279,24 +281,19 @@
able to open and use damaged bitstreams as well as we can. Just
watch out for missing information for links in the OggVorbis_File
struct */
-static void _prefetch_all_headers(OggVorbis_File *vf,vorbis_info *first_i,
- vorbis_comment *first_c,
- long dataoffset){
+static void _prefetch_all_headers(OggVorbis_File *vf, long dataoffset){
ogg_page og;
int i,ret;
- vf->vi=_ogg_calloc(vf->links,sizeof(vorbis_info));
- vf->vc=_ogg_calloc(vf->links,sizeof(vorbis_info));
+ vf->vi=_ogg_realloc(vf->vi,vf->links*sizeof(vorbis_info));
+ vf->vc=_ogg_realloc(vf->vc,vf->links*sizeof(vorbis_info));
vf->dataoffsets=_ogg_malloc(vf->links*sizeof(ogg_int64_t));
vf->pcmlengths=_ogg_malloc(vf->links*sizeof(ogg_int64_t));
vf->serialnos=_ogg_malloc(vf->links*sizeof(long));
for(i=0;i<vf->links;i++){
- if(first_i && first_c && i==0){
- /* we already grabbed the initial header earlier. This just
- saves the waste of grabbing it again */
- memcpy(vf->vi+i,first_i,sizeof(vorbis_info));
- memcpy(vf->vc+i,first_c,sizeof(vorbis_comment));
+ if(i==0){
+ /* we already grabbed the initial header earlier. Just set the offset */
vf->dataoffsets[i]=dataoffset;
}else{
@@ -320,7 +317,7 @@
while(1){
ret=_get_prev_page(vf,&og);
if(ret<0){
- /* this should not be possible, actually */
+ /* this should not be possible */
vorbis_info_clear(vf->vi+i);
vorbis_comment_clear(vf->vc+i);
break;
@@ -330,39 +327,32 @@
vf->pcmlengths[i]=ogg_page_granulepos(&og);
break;
}
+ vf->offset=ret;
}
}
}
}
static void _make_decode_ready(OggVorbis_File *vf){
- if(vf->decode_ready)return;
+ if(vf->ready_state!=STREAMSET)return;
if(vf->seekable){
vorbis_synthesis_init(&vf->vd,vf->vi+vf->current_link);
}else{
vorbis_synthesis_init(&vf->vd,vf->vi);
}
vorbis_block_init(&vf->vd,&vf->vb);
- vf->decode_ready=1;
+ vf->ready_state=INITSET;
return;
}
-static int _open_seekable(OggVorbis_File *vf){
- vorbis_info initial_i;
- vorbis_comment initial_c;
- long serialno,end;
- int ret;
- long dataoffset;
+static int _open_seekable2(OggVorbis_File *vf){
+ long serialno=vf->current_serialno,end;
+ long dataoffset=vf->offset;
ogg_page og;
-
- /* is this even vorbis...? */
- ret=_fetch_headers(vf,&initial_i,&initial_c,&serialno,NULL);
- dataoffset=vf->offset;
- ogg_stream_clear(&vf->os);
- if(ret<0)return(ret);
-
+
+ /* we're partially open and have a first link header state in
+ storage in vf */
/* we can seek, so set out learning all about this file */
- vf->seekable=1;
(vf->callbacks.seek_func)(vf->datasource,0,SEEK_END);
vf->offset=vf->end=(vf->callbacks.tell_func)(vf->datasource);
@@ -370,7 +360,7 @@
Most OggVorbis files will contain a single logical bitstream */
end=_get_prev_page(vf,&og);
if(end<0){
- ogg_stream_clear(&vf->os);
+ ov_clear(vf);
return(end);
}
@@ -380,7 +370,7 @@
/* Chained bitstream. Bisect-search each logical bitstream
section. Do so based on serial number only */
if(_bisect_forward_serialno(vf,0,0,end+1,serialno,0)<0){
- ogg_stream_clear(&vf->os);
+ ov_clear(vf);
return(OV_EREAD);
}
@@ -388,30 +378,15 @@
/* Only one logical bitstream */
if(_bisect_forward_serialno(vf,0,end,end+1,serialno,0)){
- ogg_stream_clear(&vf->os);
+ ov_clear(vf);
return(OV_EREAD);
}
}
- _prefetch_all_headers(vf,&initial_i,&initial_c,dataoffset);
+ /* the initial header memory is referenced by vf after; don't free it */
+ _prefetch_all_headers(vf,dataoffset);
return(ov_raw_seek(vf,0));
-
-}
-
-static int _open_nonseekable(OggVorbis_File *vf){
- int ret;
- /* we cannot seek. Set up a 'single' (current) logical bitstream entry */
- vf->links=1;
- vf->vi=_ogg_calloc(vf->links,sizeof(vorbis_info));
- vf->vc=_ogg_calloc(vf->links,sizeof(vorbis_info));
-
- /* Try to fetch the headers, maintaining all the storage */
- if((ret=_fetch_headers(vf,vf->vi,vf->vc,&vf->current_serialno,NULL))<0)
- return(ret);
- _make_decode_ready(vf);
-
- return 0;
}
/* clear out the current logical bitstream decoder */
@@ -419,7 +394,7 @@
ogg_stream_clear(&vf->os);
vorbis_dsp_clear(&vf->vd);
vorbis_block_clear(&vf->vb);
- vf->decode_ready=0;
+ vf->ready_state=OPENED;
vf->bittrack=0.f;
vf->samptrack=0.f;
@@ -445,11 +420,11 @@
/* process a packet if we can. If the machine isn't loaded,
neither is a page */
- if(vf->decode_ready){
+ if(vf->ready_state==INITSET){
ogg_packet op;
int result=ogg_stream_packetout(&vf->os,&op);
ogg_int64_t granulepos;
-
+
if(result==-1)return(OV_HOLE); /* hole in the data. */
if(result>0){
/* got a packet. process it */
@@ -499,18 +474,26 @@
}
}
}
-
- if(!readp)return(0);
- if(_get_next_page(vf,&og,-1)<0)return(OV_EOF); /* eof. leave unitialized */
- /* bitrate tracking; add the header's bytes here, the body bytes
- are done by packet above */
- vf->bittrack+=og.header_len*8;
-
- /* has our decoding just traversed a bitstream boundary? */
- if(vf->decode_ready){
- if(vf->current_serialno!=ogg_page_serialno(&og)){
- _decode_clear(vf);
+ if(vf->ready_state>=STREAMSET){
+ if(!readp)return(0);
+ if(_get_next_page(vf,&og,-1)<0)return(OV_EOF); /* eof.
+ leave unitialized */
+
+ /* bitrate tracking; add the header's bytes here, the body bytes
+ are done by packet above */
+ vf->bittrack+=og.header_len*8;
+
+ /* has our decoding just traversed a bitstream boundary? */
+ if(vf->ready_state==INITSET){
+ if(vf->current_serialno!=ogg_page_serialno(&og)){
+ _decode_clear(vf);
+
+ if(!vf->seekable){
+ vorbis_info_clear(vf->vi);
+ vorbis_comment_clear(vf->vc);
+ }
+ }
}
}
@@ -526,33 +509,37 @@
we're now nominally at the header of the next bitstream
*/
- if(!vf->decode_ready){
+ if(vf->ready_state!=INITSET){
int link;
- if(vf->seekable){
- vf->current_serialno=ogg_page_serialno(&og);
-
- /* match the serialno to bitstream section. We use this rather than
- offset positions to avoid problems near logical bitstream
- boundaries */
- for(link=0;link<vf->links;link++)
- if(vf->serialnos[link]==vf->current_serialno)break;
- if(link==vf->links)return(OV_EBADLINK); /* sign of a bogus
- stream. error out,
- leave machine
- uninitialized */
-
- vf->current_link=link;
-
- ogg_stream_init(&vf->os,vf->current_serialno);
- ogg_stream_reset(&vf->os);
-
- }else{
- /* we're streaming */
- /* fetch the three header packets, build the info struct */
-
- _fetch_headers(vf,vf->vi,vf->vc,&vf->current_serialno,&og);
- vf->current_link++;
- link=0;
+
+ if(vf->ready_state<STREAMSET){
+ if(vf->seekable){
+ vf->current_serialno=ogg_page_serialno(&og);
+
+ /* match the serialno to bitstream section. We use this rather than
+ offset positions to avoid problems near logical bitstream
+ boundaries */
+ for(link=0;link<vf->links;link++)
+ if(vf->serialnos[link]==vf->current_serialno)break;
+ if(link==vf->links)return(OV_EBADLINK); /* sign of a bogus
+ stream. error out,
+ leave machine
+ uninitialized */
+
+ vf->current_link=link;
+
+ ogg_stream_init(&vf->os,vf->current_serialno);
+ ogg_stream_reset(&vf->os);
+ vf->ready_state=STREAMSET;
+
+ }else{
+ /* we're streaming */
+ /* fetch the three header packets, build the info struct */
+
+ _fetch_headers(vf,vf->vi,vf->vc,&vf->current_serialno,&og);
+ vf->current_link++;
+ link=0;
+ }
}
_make_decode_ready(vf);
@@ -561,9 +548,65 @@
}
}
-/**********************************************************************
- * The helpers are over; it's all toplevel interface from here on out */
-
+static int _fseek64_wrap(FILE *f,ogg_int64_t off,int whence){
+ if(f==NULL)return(-1);
+ return fseek(f,(int)off,whence);
+}
+
+static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
+ long ibytes, ov_callbacks callbacks){
+ long offset=(f?callbacks.seek_func(f,0,SEEK_CUR):-1);
+ int ret;
+
+ memset(vf,0,sizeof(OggVorbis_File));
+ vf->datasource=f;
+ vf->callbacks = callbacks;
+
+ /* init the framing state */
+ ogg_sync_init(&vf->oy);
+
+ /* perhaps some data was previously read into a buffer for testing
+ against other stream types. Allow initialization from this
+ previously read data (as we may be reading from a non-seekable
+ stream) */
+ if(initial){
+ char *buffer=ogg_sync_buffer(&vf->oy,ibytes);
+ memcpy(buffer,initial,ibytes);
+ ogg_sync_wrote(&vf->oy,ibytes);
+ }
+
+ /* can we seek? Stevens suggests the seek test was portable */
+ if(offset!=-1)vf->seekable=1;
+
+ /* No seeking yet; Set up a 'single' (current) logical bitstream
+ entry for partial open */
+ vf->links=1;
+ vf->vi=_ogg_calloc(vf->links,sizeof(vorbis_info));
+ vf->vc=_ogg_calloc(vf->links,sizeof(vorbis_info));
+
+ /* Try to fetch the headers, maintaining all the storage */
+ if((ret=_fetch_headers(vf,vf->vi,vf->vc,&vf->current_serialno,NULL))<0){
+ vf->datasource=NULL;
+ ov_clear(vf);
+ }else
+ vf->ready_state=PARTOPEN;
+ return(ret);
+}
+
+static int _ov_open2(OggVorbis_File *vf){
+ vf->ready_state=OPENED;
+ if(vf->seekable){
+ int ret=_open_seekable2(vf);
+ if(ret){
+ vf->datasource=NULL;
+ ov_clear(vf);
+ }
+ return(ret);
+ }
+ return 0;
+}
+
+
/* clear out the OggVorbis_File struct */
int ov_clear(OggVorbis_File *vf){
if(vf){
@@ -594,11 +637,6 @@
return(0);
}
-static int _fseek64_wrap(FILE *f,ogg_int64_t off,int whence){
- if(f==NULL)return(-1);
- return fseek(f,(int)off,whence);
-}
-
/* inspects the OggVorbis file and finds/documents all the logical
bitstreams contained in it. Tries to be tolerant of logical
bitstream sections that are truncated/woogie.
@@ -607,6 +645,13 @@
0) OK
*/
+int ov_open_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes,
+ ov_callbacks callbacks){
+ int ret=_ov_open1(f,vf,initial,ibytes,callbacks);
+ if(ret)return ret;
+ return _ov_open2(vf);
+}
+
int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){
ov_callbacks callbacks = {
(size_t (*)(void *, size_t, size_t, void *)) fread,
@@ -618,42 +663,32 @@
return ov_open_callbacks((void *)f, vf, initial, ibytes, callbacks);
}
+/* Only partially open the vorbis file; test for Vorbisness, and load
+ the headers for the first chain. Do not seek (although test for
+ seekability). Use ov_test_open to finish opening the file, else
+ ov_clear to close/free it. Same return codes as open. */
-int ov_open_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes,
+int ov_test_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes,
ov_callbacks callbacks)
{
- long offset=(f?callbacks.seek_func(f,0,SEEK_CUR):-1);
- int ret;
-
- memset(vf,0,sizeof(OggVorbis_File));
- vf->datasource=f;
- vf->callbacks = callbacks;
-
- /* init the framing state */
- ogg_sync_init(&vf->oy);
+ return _ov_open1(f,vf,initial,ibytes,callbacks);
+}
- /* perhaps some data was previously read into a buffer for testing
- against other stream types. Allow initialization from this
- previously read data (as we may be reading from a non-seekable
- stream) */
- if(initial){
- char *buffer=ogg_sync_buffer(&vf->oy,ibytes);
- memcpy(buffer,initial,ibytes);
- ogg_sync_wrote(&vf->oy,ibytes);
- }
+int ov_test(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){
+ ov_callbacks callbacks = {
+ (size_t (*)(void *, size_t, size_t, void *)) fread,
+ (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap,
+ (int (*)(void *)) fclose,
+ (long (*)(void *)) ftell
+ };
- /* can we seek? Stevens suggests the seek test was portable */
- if(offset!=-1){
- ret=_open_seekable(vf);
- }else{
- ret=_open_nonseekable(vf);
- }
- if(ret){
- vf->datasource=NULL;
- ov_clear(vf);
- }
- return(ret);
+ return ov_test_callbacks((void *)f, vf, initial, ibytes, callbacks);
}
+
+int ov_test_open(OggVorbis_File *vf){
+ if(vf->ready_state!=PARTOPEN)return(OV_EINVAL);
+ return _ov_open2(vf);
+}
/* How many logical bitstreams in this physical bitstream? */
long ov_streams(OggVorbis_File *vf){
@@ -675,6 +710,7 @@
vorbis_info structs */
long ov_bitrate(OggVorbis_File *vf,int i){
+ if(vf->ready_state<OPENED)return(OV_EINVAL);
if(i>=vf->links)return(OV_EINVAL);
if(!vf->seekable && i!=0)return(ov_bitrate(vf,0));
if(i<0){
@@ -706,10 +742,13 @@
}
/* returns the actual bitrate since last call. returns -1 if no
- additional data to offer since last call (or at beginning of stream) */
+ additional data to offer since last call (or at beginning of stream),
+ EINVAL if stream is only partially open
+*/
long ov_bitrate_instant(OggVorbis_File *vf){
int link=(vf->seekable?vf->current_link:0);
long ret;
+ if(vf->ready_state<OPENED)return(OV_EINVAL);
if(vf->samptrack==0)return(OV_FALSE);
ret=vf->bittrack/vf->samptrack*vf->vi[link].rate+.5;
vf->bittrack=0.f;
@@ -730,9 +769,11 @@
/* returns: total raw (compressed) length of content if i==-1
raw (compressed) length of that logical bitstream for i==0 to n
- -1 if the stream is not seekable (we can't know the length)
+ OV_EINVAL if the stream is not seekable (we can't know the length)
+ or if stream is only partially open
*/
ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i){
+ if(vf->ready_state<OPENED)return(OV_EINVAL);
if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
if(i<0){
long acc=0;
@@ -745,11 +786,13 @@
}
}
-/* returns: total PCM length (samples) of content if i==-1
- PCM length (samples) of that logical bitstream for i==0 to n
- -1 if the stream is not seekable (we can't know the length)
+/* returns: total PCM length (samples) of content if i==-1 PCM length
+ (samples) of that logical bitstream for i==0 to n
+ OV_EINVAL if the stream is not seekable (we can't know the
+ length) or only partially open
*/
ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i){
+ if(vf->ready_state<OPENED)return(OV_EINVAL);
if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
if(i<0){
ogg_int64_t acc=0;
@@ -764,9 +807,11 @@
/* returns: total seconds of content if i==-1
seconds in that logical bitstream for i==0 to n
- -1 if the stream is not seekable (we can't know the length)
+ OV_EINVAL if the stream is not seekable (we can't know the
+ length) or only partially open
*/
double ov_time_total(OggVorbis_File *vf,int i){
+ if(vf->ready_state<OPENED)return(OV_EINVAL);
if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
if(i<0){
double acc=0;
@@ -780,69 +825,132 @@
}
/* seek to an offset relative to the *compressed* data. This also
- immediately sucks in and decodes pages to update the PCM cursor. It
- will cross a logical bitstream boundary, but only if it can't get
- any packets out of the tail of the bitstream we seek to (so no
- surprises).
+ scans packets to update the PCM cursor. It will cross a logical
+ bitstream boundary, but only if it can't get any packets out of the
+ tail of the bitstream we seek to (so no surprises).
returns zero on success, nonzero on failure */
int ov_raw_seek(OggVorbis_File *vf,long pos){
- int flag=0;
- if(!vf->seekable)return(OV_ENOSEEK); /* don't dump machine if we can't seek */
+ ogg_stream_state work_os;
+
+ if(vf->ready_state<OPENED)return(OV_EINVAL);
+ if(!vf->seekable)
+ return(OV_ENOSEEK); /* don't dump machine if we can't seek */
+
if(pos<0 || pos>vf->offsets[vf->links])return(OV_EINVAL);
/* clear out decoding machine state */
vf->pcm_offset=-1;
_decode_clear(vf);
- /* seek */
_seek_helper(vf,pos);
- /* we need to make sure the pcm_offset is set. We use the
- _fetch_packet helper to process one packet with readp set, then
- call it until it returns '0' with readp not set (the last packet
- from a page has the 'granulepos' field set, and that's how the
- helper updates the offset */
-
- while(!flag){
- switch(_process_packet(vf,1)){
- case 0:case OV_EOF:
- /* oh, eof. There are no packets remaining. Set the pcm offset to
- the end of file */
- vf->pcm_offset=ov_pcm_total(vf,-1);
- return(0);
- case OV_HOLE:
- break;
- case OV_EBADLINK:
- goto seek_error;
- default:
- /* all OK */
- flag=1;
- break;
- }
- }
-
- while(1){
- /* don't have to check each time through for the updated granule;
- it's always the last complete packet on a page */
- switch(_process_packet(vf,0)){
- case 0:case OV_EOF:
- /* the offset is set unless it's a bogus bitstream with no
- offset information but that's not our fault. We still run
- gracefully, we're just missing the offset */
- return(0);
- case OV_EBADLINK:
- goto seek_error;
- default:
- /* continue processing packets */
- break;
+ /* we need to make sure the pcm_offset is set, but we don't want to
+ advance the raw cursor past good packets just to get to the first
+ with a granulepos. That's not equivalent behavior to beginning
+ decoding as immediately after the seek position as possible.
+
+ So, a hack. We use two stream states; a local scratch state and
+ a the shared vf->os stream state. We use the local state to
+ scan, and the shared state as a buffer for later decode.
+
+ Unfortuantely, on the last page we still advance to last packet
+ because the granulepos on the last page is not necessarily on a
+ packet boundary, and we need to make sure the granpos is
+ correct.
+ */
+
+ {
+ ogg_page og;
+ ogg_packet op;
+ int lastblock=0;
+ int accblock=0;
+ int thisblock;
+ int eosflag;
+
+ memset(&work_os,0,sizeof(work_os));/* so that it's safe to clear
+ it later even if we don't
+ init it */
+
+ while(1){
+ if(vf->ready_state==STREAMSET){
+ /* snarf/scan a packet if we can */
+ int result=ogg_stream_packetout(&work_os,&op);
+
+ if(result>0){
+
+ if(vf->vi[vf->current_link].codec_setup)
+ thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
+ if(eosflag)
+ ogg_stream_packetout(&vf->os,NULL);
+ else
+ if(lastblock)accblock+=(lastblock+thisblock)>>2;
+
+ if(op.granulepos!=-1){
+ int i,link=vf->current_link;
+ ogg_int64_t granulepos=op.granulepos;
+
+ for(i=0;i<link;i++)
+ granulepos+=vf->pcmlengths[i];
+ vf->pcm_offset=granulepos-accblock;
+ break;
+ }
+ lastblock=thisblock;
+ continue;
+ }
+ }
+
+ if(!lastblock){
+ if(_get_next_page(vf,&og,-1)<0){
+ vf->pcm_offset=ov_pcm_total(vf,-1);
+ break;
+ }
+ }else{
+ /* huh? Bogus stream with packets but no granulepos */
+ vf->pcm_offset=-1;
+ break;
+ }
+
+ /* has our decoding just traversed a bitstream boundary? */
+ if(vf->ready_state==STREAMSET)
+ if(vf->current_serialno!=ogg_page_serialno(&og)){
+ _decode_clear(vf); /* clear out stream state */
+ ogg_stream_clear(&work_os);
+ }
+
+ if(vf->ready_state<STREAMSET){
+ int link;
+
+ vf->current_serialno=ogg_page_serialno(&og);
+ for(link=0;link<vf->links;link++)
+ if(vf->serialnos[link]==vf->current_serialno)break;
+ if(link==vf->links)goto seek_error; /* sign of a bogus stream.
+ error out, leave
+ machine uninitialized */
+ vf->current_link=link;
+
+ ogg_stream_init(&vf->os,vf->current_serialno);
+ ogg_stream_reset(&vf->os);
+ ogg_stream_init(&work_os,vf->current_serialno);
+ ogg_stream_reset(&work_os);
+ vf->ready_state=STREAMSET;
+
+ }
+
+ ogg_stream_pagein(&vf->os,&og);
+ ogg_stream_pagein(&work_os,&og);
+ eosflag=ogg_page_eos(&og);
}
}
-
+
+ ogg_stream_clear(&work_os);
+ return(0);
+
seek_error:
/* dump the machine so we're in a known state */
vf->pcm_offset=-1;
+ ogg_stream_clear(&work_os);
_decode_clear(vf);
return OV_EBADLINK;
}
@@ -858,9 +966,10 @@
long ret;
ogg_int64_t total=ov_pcm_total(vf,-1);
+ if(vf->ready_state<OPENED)return(OV_EINVAL);
if(!vf->seekable)return(OV_ENOSEEK);
if(pos<0 || pos>total)return(OV_EINVAL);
-
+
/* which bitstream section does this pcm offset occur in? */
for(link=vf->links-1;link>=0;link--){
total-=vf->pcmlengths[link];
@@ -872,46 +981,117 @@
missing pages or incorrect frame number information in the
bitstream could make our task impossible. Account for that (it
would be an error condition) */
+
+ /* new search algorithm by HB (Nicholas Vinen) */
{
ogg_int64_t target=pos-total;
long end=vf->offsets[link+1];
long begin=vf->offsets[link];
+ ogg_int64_t endtime = vf->pcmlengths[link];
+ ogg_int64_t begintime = 0;
long best=begin;
-
+
ogg_page og;
while(begin<end){
long bisect;
-
+
if(end-begin<CHUNKSIZE){
bisect=begin;
}else{
- bisect=(end+begin)/2;
+ /* take a (pretty decent) guess. */
+ bisect=begin +
+ (target-begintime)*(end-begin)/(endtime-begintime) - CHUNKSIZE;
+ if(bisect<=begin)
+ bisect=begin+1;
}
-
_seek_helper(vf,bisect);
- ret=_get_next_page(vf,&og,end-bisect);
- switch(ret){
- case OV_FALSE: case OV_EOF:
- end=bisect;
- break;
- case OV_EREAD:
- goto seek_error;
- default:
- {
+
+ while(begin<end){
+ ret=_get_next_page(vf,&og,end-bisect);
+ if(ret==OV_EREAD) goto seek_error;
+ if(ret<0){
+ if(bisect<=begin+1)
+ end=begin; /* found it */
+ else{
+ if(bisect==0)goto seek_error;
+ bisect-=CHUNKSIZE;
+ if(bisect<=begin)bisect=begin+1;
+ _seek_helper(vf,bisect);
+ }
+ }else{
ogg_int64_t granulepos=ogg_page_granulepos(&og);
if(granulepos<target){
best=ret; /* raw offset of packet with granulepos */
- begin=vf->offset; /* raw offset of next packet */
+ begin=vf->offset; /* raw offset of next page */
+ begintime=granulepos;
+
+ if(target-begin>44100)break;
+ bisect=begin; /* *not* begin + 1 */
}else{
- end=bisect;
+ if(bisect<=begin+1)
+ end=begin; /* found it */
+ else{
+ if(end==vf->offset){ /* we're pretty close - we'd be stuck in */
+ end=ret;
+ bisect-=CHUNKSIZE; /* an endless loop otherwise. */
+ if(bisect<=begin)bisect=begin+1;
+ _seek_helper(vf,bisect);
+ }else{
+ end=ret;
+ endtime=granulepos;
+ break;
+ }
+ }
}
}
}
}
- /* found our page. seek to it (call raw_seek). */
-
- if((ret=ov_raw_seek(vf,best)))goto seek_error;
+ /* found our page. seek to it, update pcm offset. Easier case than
+ raw_seek, don't keep packets preceeding granulepos. */
+ {
+ ogg_page og;
+ ogg_packet op;
+ /* clear out decoding machine state */
+ _decode_clear(vf);
+ /* seek */
+ _seek_helper(vf,best);
+
+ if(_get_next_page(vf,&og,-1)<0)return(OV_EOF); /* shouldn't happen */
+ vf->current_serialno=ogg_page_serialno(&og);
+ vf->current_link=link;
+
+ ogg_stream_init(&vf->os,vf->current_serialno);
+ ogg_stream_reset(&vf->os);
+ vf->ready_state=STREAMSET;
+ ogg_stream_pagein(&vf->os,&og);
+
+ /* pull out all but last packet; the one with granulepos */
+ while(1){
+ ret=ogg_stream_packetpeek(&vf->os,&op);
+ if(ret==0){
+ /* !!! the packet finishing this page originated on a
+ preceeding page. Keep fetching previous pages until we
+ get one with a granulepos or without the 'continued' flag
+ set. Then just use raw_seek for simplicity. */
+ while(1){
+ ret=_get_prev_page(vf,&og);
+ if(ret<0)goto seek_error;
+ if(ogg_page_granulepos(&og)>-1 ||
+ !ogg_page_continued(&og)){
+ return ov_raw_seek(vf,ret);
+ }
+ vf->offset=ret;
+ }
+ }
+ if(ret<0)goto seek_error;
+ if(op.granulepos!=-1 && !op.e_o_s){
+ vf->pcm_offset=op.granulepos+total;
+ break;
+ }else
+ ret=ogg_stream_packetout(&vf->os,NULL);
+ }
+ }
}
/* verify result */
@@ -932,11 +1112,71 @@
returns zero on success, nonzero on failure */
int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
+ int thisblock,lastblock=0,blockacc=0;
int ret=ov_pcm_seek_page(vf,pos);
if(ret<0)return(ret);
-
+
+ /* discard leading packets we don't need for the lapping of the
+ position we want; don't decode them */
+#if 0
+ while(1){
+ ogg_packet op;
+ ogg_page og;
+
+ int ret=ogg_stream_packetpeek(&vf->os,&op);
+ if(ret>0){
+ thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
+
+ if(blockacc+
+ ((lastblock+thisblock)>>2)+
+ (thisblock>>1)+vf->pcm_offset>pos)break;
+
+ ogg_stream_packetout(&vf->os,NULL);
+ /* end of logical stream case is hard, especially with exact
+ length positioning. */
+
+ if(op.granulepos>-1){
+ int i;
+ /* always believe the stream markers */
+ vf->pcm_offset=op.granulepos;
+ for(i=0;i<vf->current_link;i++)
+ vf->pcm_offset+=vf->pcmlengths[i];
+ blockacc=0;
+ }else
+ if(lastblock)blockacc+=(lastblock+thisblock)>>2;
+
+ lastblock=thisblock;
+ }else{
+ if(ret<0 && ret!=OV_HOLE)break;
+
+ /* suck in a new page */
+ if(_get_next_page(vf,&og,-1)<0)break;
+ if(vf->current_serialno!=ogg_page_serialno(&og))_decode_clear(vf);
+
+ if(vf->ready_state<STREAMSET){
+ int link;
+
+ vf->current_serialno=ogg_page_serialno(&og);
+ for(link=0;link<vf->links;link++)
+ if(vf->serialnos[link]==vf->current_serialno)break;
+ if(link==vf->links)return(OV_EBADLINK);
+ vf->current_link=link;
+
+ ogg_stream_init(&vf->os,vf->current_serialno);
+ ogg_stream_reset(&vf->os);
+ vf->ready_state=STREAMSET;
+ lastblock=0;
+ }
+ ogg_stream_pagein(&vf->os,&og);
+ }
+ }
+
+ if(lastblock)vf->pcm_offset+=blockacc;
+#endif
+
/* discard samples until we reach the desired position. Crossing a
logical bitstream boundary with abandon is OK. */
+ _make_decode_ready(vf);
while(vf->pcm_offset<pos){
float **pcm;
long target=pos-vf->pcm_offset;
@@ -947,7 +1187,7 @@
vf->pcm_offset+=samples;
if(samples<target)
- if(_process_packet(vf,1)==0)
+ if(_process_packet(vf,1)<=0)
vf->pcm_offset=ov_pcm_total(vf,-1); /* eof */
}
return 0;
@@ -962,6 +1202,7 @@
ogg_int64_t pcm_total=ov_pcm_total(vf,-1);
double time_total=ov_time_total(vf,-1);
+ if(vf->ready_state<OPENED)return(OV_EINVAL);
if(!vf->seekable)return(OV_ENOSEEK);
if(seconds<0 || seconds>time_total)return(OV_EINVAL);
@@ -988,6 +1229,7 @@
ogg_int64_t pcm_total=ov_pcm_total(vf,-1);
double time_total=ov_time_total(vf,-1);
+ if(vf->ready_state<OPENED)return(OV_EINVAL);
if(!vf->seekable)return(OV_ENOSEEK);
if(seconds<0 || seconds>time_total)return(OV_EINVAL);
@@ -1008,11 +1250,13 @@
/* tell the current stream offset cursor. Note that seek followed by
tell will likely not give the set offset due to caching */
ogg_int64_t ov_raw_tell(OggVorbis_File *vf){
+ if(vf->ready_state<OPENED)return(OV_EINVAL);
return(vf->offset);
}
/* return PCM offset (sample) of next PCM sample to be read */
ogg_int64_t ov_pcm_tell(OggVorbis_File *vf){
+ if(vf->ready_state<OPENED)return(OV_EINVAL);
return(vf->pcm_offset);
}
@@ -1024,6 +1268,7 @@
ogg_int64_t pcm_total=0;
double time_total=0.f;
+ if(vf->ready_state<OPENED)return(OV_EINVAL);
if(vf->seekable){
pcm_total=ov_pcm_total(vf,-1);
time_total=ov_time_total(vf,-1);
@@ -1050,20 +1295,17 @@
vorbis_info *ov_info(OggVorbis_File *vf,int link){
if(vf->seekable){
if(link<0)
- if(vf->decode_ready)
+ if(vf->ready_state>=STREAMSET)
return vf->vi+vf->current_link;
else
- return NULL;
+ return vf->vi;
else
if(link>=vf->links)
return NULL;
else
return vf->vi+link;
}else{
- if(vf->decode_ready)
- return vf->vi;
- else
- return NULL;
+ return vf->vi;
}
}
@@ -1071,20 +1313,17 @@
vorbis_comment *ov_comment(OggVorbis_File *vf,int link){
if(vf->seekable){
if(link<0)
- if(vf->decode_ready)
+ if(vf->ready_state>=STREAMSET)
return vf->vc+vf->current_link;
else
- return NULL;
+ return vf->vc;
else
if(link>=vf->links)
return NULL;
else
return vf->vc+link;
}else{
- if(vf->decode_ready)
- return vf->vc;
- else
- return NULL;
+ return vf->vc;
}
}
@@ -1117,7 +1356,7 @@
word) word size for output. currently 1 (byte) or
2 (16 bit short)
- return values: <0) error/hole in data (OV_HOLE)
+ return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL)
0) EOF
n) number of bytes of PCM actually returned. The
below works on a packet-by-packet basis, so the
@@ -1131,8 +1370,17 @@
int i,j;
int host_endian = host_is_big_endian();
+ if(vf->ready_state<OPENED)return(OV_EINVAL);
+ if(vf->ready_state==OPENED)return(OV_EOF); /* stream is always
+ initialized after
+ other calls (after
+ open)... unless there
+ was no page at the end
+ to initialize state
+ with. */
+
while(1){
- if(vf->decode_ready){
+ if(vf->ready_state>=STREAMSET){
float **pcm;
long samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
if(samples){
--- >8 ----
List archives: http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body. No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.
More information about the commits
mailing list