// The Vorbis header is in three packets; the initial small packet in // the first page that identifies basic parameters, a second packet // with bitstream comments and a third packet that holds the // codebook. public int synthesis_headerin(Comment vc, Packet op) { csBuffer opb=new csBuffer(); if(op!=null) { opb.readinit(op.packet_base, op.packet, op.bytes); // Which of the three types of header is this? // Also verify header-ness, vorbis { byte[] buffer=new byte[6]; int packtype=opb.read(8); //memset(buffer,0,6); opb.read(buffer,6); if(buffer[0]!='v' || buffer[1]!='o' || buffer[2]!='r' || buffer[3]!='b' || buffer[4]!='i' || buffer[5]!='s') { // not a vorbis header return(-1); } switch(packtype) { case 0x01: // least significant *bit* is read first if(op.b_o_s==0) { // Not the initial packet return(-1); } if(rate!=0) { // previously initialized info header return(-1); } return(unpack_info(opb)); case 0x03: // least significant *bit* is read first if(rate==0) { // um... we didn't get the initial header return(-1); } return(vc.unpack(opb)); case 0x05: // least significant *bit* is read first if(rate==0 || vc.vendor==null) { // um... we didn;t get the initial header or comments yet return(-1); } return(unpack_books(opb)); default: // Not a valid vorbis header type //return(-1); break; } } } return(-1); }
// uses the local ogg_stream storage in vf; this is important for // non-streaming input sources int fetch_headers(Info vi, Comment vc, int[] serialno, Page og_ptr) { //System.err.println("fetch_headers"); Page og=new Page(); Packet op=new Packet(); int ret; if(og_ptr==null) { ret=get_next_page(og, CHUNKSIZE); if(ret==OV_EREAD) { return OV_EREAD; } if(ret<0) { return OV_ENOTVORBIS; } og_ptr=og; } if(serialno!=null) { serialno[0]=og_ptr.serialno(); } os.init(og_ptr.serialno()); // extract the initial header from the first page and verify that the // Ogg bitstream is in fact Vorbis data vi.init(); vc.init(); int i=0; while(i<3) { os.pagein(og_ptr); while(i<3) { int result=os.packetout(op); if(result==0) { break; } if(result==-1) { Console.Error.WriteLine("Corrupt header in logical bitstream."); //goto bail_header; vi.clear(); vc.clear(); os.clear(); return -1; } if(vi.synthesis_headerin(vc, op)!=0) { Console.Error.WriteLine("Illegal header in logical bitstream."); //goto bail_header; vi.clear(); vc.clear(); os.clear(); return -1; } i++; } if(i<3) if(get_next_page(og_ptr, 1)<0) { Console.Error.WriteLine("Missing header in logical bitstream."); //goto bail_header; vi.clear(); vc.clear(); os.clear(); return -1; } } return 0; }
int open_seekable() { Info initial_i=new Info(); Comment initial_c=new Comment(); int serialno; long end; int ret; int dataoffset; Page og=new Page(); // is this even vorbis...? int[] foo=new int[1]; ret=fetch_headers(initial_i, initial_c, foo, null); serialno=foo[0]; dataoffset=(int)offset; //!! os.clear(); if(ret==-1) { return(-1); } // we can seek, so set out learning all about this file skable=true; //(callbacks.seek_func)(datasource, 0, SEEK_END); fseek(datasource, 0, SEEK_END); //offset=end=(callbacks.tell_func)(datasource); offset=ftell(datasource); end=offset; // We get the offset for the last page of the physical bitstream. // Most OggVorbis files will contain a single logical bitstream end=get_prev_page(og); // moer than one logical bitstream? if(og.serialno()!=serialno) { // Chained bitstream. Bisect-search each logical bitstream // section. Do so based on serial number only if(bisect_forward_serialno(0,0,end+1,serialno,0)<0) { clear(); return OV_EREAD; } } else { // Only one logical bitstream if(bisect_forward_serialno(0,end,end+1,serialno,0)<0) { clear(); return OV_EREAD; } } prefetch_all_headers(initial_i, initial_c, dataoffset); return(raw_seek(0)); }
// last step of the OggVorbis_File initialization; get all the // vorbis_info structs and PCM positions. Only called by the seekable // initialization (local stream storage is hacked slightly; pay // attention to how that's done) void prefetch_all_headers(Info first_i,Comment first_c, int dataoffset) { Page og=new Page(); int ret; vi=new Info[links]; vc=new Comment[links]; dataoffsets=new long[links]; pcmlengths=new long[links]; serialnos=new int[links]; for(int i=0; i<links; i++) { if(first_i!=null && first_c!=null && i==0) { // we already grabbed the initial header earlier. This just // saves the waste of grabbing it again // !!!!!!!!!!!!! vi[i]=first_i; //memcpy(vf->vi+i,first_i,sizeof(vorbis_info)); vc[i]=first_c; //memcpy(vf->vc+i,first_c,sizeof(vorbis_comment)); dataoffsets[i]=dataoffset; } else { // seek to the location of the initial header seek_helper(offsets[i]); //!!! if(fetch_headers(vi[i], vc[i], null, null)==-1) { Console.Error.WriteLine("Error opening logical bitstream #"+(i+1)+"\n"); dataoffsets[i]=-1; } else { dataoffsets[i]=offset; os.clear(); } } // get the serial number and PCM length of this link. To do this, // get the last page of the stream long end=offsets[i+1]; //!!! seek_helper(end); while(true) { ret=get_prev_page(og); if(ret==-1) { // this should not be possible Console.Error.WriteLine("Could not find last page of logical "+ "bitstream #"+(i)+"\n"); vi[i].clear(); vc[i].clear(); break; } if(og.granulepos()!=-1) { serialnos[i]=og.serialno(); pcmlengths[i]=og.granulepos(); break; } } } }
int open_nonseekable() { //System.err.println("open_nonseekable"); // we cannot seek. Set up a 'single' (current) logical bitstream entry links=1; vi=new Info[links]; vi[0]=new Info(); // ?? vc=new Comment[links]; vc[0]=new Comment(); // ?? bug? // Try to fetch the headers, maintaining all the storage int[]foo=new int[1]; if(fetch_headers(vi[0], vc[0], foo, null)==-1) { return(-1); } current_serialno=foo[0]; make_decode_ready(); return 0; }