// add the incoming page to the stream state; we decompose the page // into packet segments here as well. public int pagein(Page og) { byte[] header_base = og.header_base; int header = og.header; byte[] body_base = og.body_base; int body = og.body; int bodysize = og.body_len; int segptr = 0; int version = og.version(); int continued = og.continued(); int bos = og.bos(); int eos = og.eos(); long granulepos = og.granulepos(); int _serialno = og.serialno(); int _pageno = og.pageno(); int segments = header_base[header + 26] & 0xff; // clean up 'returned data' { int lr = lacing_returned; int br = body_returned; // body data //System.out.println("br="+br+", body_fill="+body_fill); if (br != 0) { body_fill -= br; if (body_fill != 0) { Array.Copy(body_data, br, body_data, 0, body_fill); } body_returned = 0; } //System.out.println("?? br="+br+", body_fill="+body_fill+" body_returned="+body_returned); if (lr != 0) { // segment table if ((lacing_fill - lr) != 0) { Array.Copy(lacing_vals, lr, lacing_vals, 0, lacing_fill - lr); Array.Copy(granule_vals, lr, granule_vals, 0, lacing_fill - lr); } lacing_fill -= lr; lacing_packet -= lr; lacing_returned = 0; } } // check the serial number if (_serialno != serialno) { return(-1); } if (version > 0) { return(-1); } lacing_expand(segments + 1); // are we in sequence? if (_pageno != pageno) { int i; // unroll previous partial packet (if any) for (i = lacing_packet; i < lacing_fill; i++) { body_fill -= lacing_vals[i] & 0xff; //System.out.println("??"); } lacing_fill = lacing_packet; // make a note of dropped data in segment table if (pageno != -1) { lacing_vals[lacing_fill++] = 0x400; lacing_packet++; } // are we a 'continued packet' page? If so, we'll need to skip // some segments if (continued != 0) { bos = 0; for (; segptr < segments; segptr++) { int val = (header_base[header + 27 + segptr] & 0xff); body += val; bodysize -= val; if (val < 255) { segptr++; break; } } } } //System.out.println("bodysize="+bodysize); if (bodysize != 0) { body_expand(bodysize); Array.Copy(body_base, body, body_data, body_fill, bodysize); body_fill += bodysize; } //System.out.println("bodyfill="+body_fill); { int saved = -1; while (segptr < segments) { int val = (header_base[header + 27 + segptr] & 0xff); lacing_vals[lacing_fill] = val; granule_vals[lacing_fill] = -1; if (bos != 0) { lacing_vals[lacing_fill] |= 0x100; bos = 0; } if (val < 255) { saved = lacing_fill; } lacing_fill++; segptr++; if (val < 255) { lacing_packet = lacing_fill; } } /* set the granulepos on the last pcmval of the last full packet */ if (saved != -1) { granule_vals[saved] = granulepos; } } if (eos != 0) { e_o_s = 1; if (lacing_fill > 0) { lacing_vals[lacing_fill - 1] |= 0x200; } } pageno = _pageno + 1; return(0); }
// seek to a sample offset relative to the decompressed pcm stream // returns zero on success, nonzero on failure public int pcm_seek(long pos) { int link=-1; long total=pcm_total(-1); if(!skable) { return(-1); } // don't dump machine if we can't seek if(pos<0 || pos>total) { //goto seek_error; pcm_offset=-1; decode_clear(); return -1; } // which bitstream section does this pcm offset occur in? for(link=links-1; link>=0; link--) { total-=pcmlengths[link]; if(pos>=total) { break; } } // search within the logical bitstream for the page with the highest // pcm_pos preceeding (or equal to) pos. There is a danger here; // missing pages or incorrect frame number information in the // bitstream could make our task impossible. Account for that (it // would be an error condition) { long target=pos-total; long end=offsets[link+1]; long begin=offsets[link]; int best=(int)begin; Page og=new Page(); while(begin<end) { long bisect; int ret; if(end-begin<CHUNKSIZE) { bisect=begin; } else { bisect=(end+begin)/2; } seek_helper(bisect); ret=get_next_page(og,end-bisect); if(ret==-1) { end=bisect; } else { long granulepos=og.granulepos(); if(granulepos<target) { best=ret; // raw offset of packet with granulepos begin=offset; // raw offset of next packet } else { end=bisect; } } } // found our page. seek to it (call raw_seek). if(raw_seek(best)!=0) { //goto seek_error; pcm_offset=-1; decode_clear(); return -1; } } // verify result if(pcm_offset>=pos) { //goto seek_error; pcm_offset=-1; decode_clear(); return -1; } if(pos>pcm_total(-1)) { //goto seek_error; pcm_offset=-1; decode_clear(); return -1; } // discard samples until we reach the desired position. Crossing a // logical bitstream boundary with abandon is OK. while(pcm_offset<pos) { float[][] pcm; int target=(int)(pos-pcm_offset); float[][][] _pcm=new float[1][][]; int[] _index=new int[getInfo(-1).channels]; int samples=vd.synthesis_pcmout(_pcm, _index); pcm=_pcm[0]; if(samples>target) { samples=target; } vd.synthesis_read(samples); pcm_offset+=samples; if(samples<target) if(process_packet(1)==0) { pcm_offset=pcm_total(-1); // eof } } return 0; // seek_error: // dump machine so we're in a known state //pcm_offset=-1; //decode_clear(); //return -1; }
// 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; } } } }
// add the incoming page to the stream state; we decompose the page // into packet segments here as well. public int pagein(Page og) { byte[] header_base=og.header_base; int header=og.header; byte[] body_base=og.body_base; int body=og.body; int bodysize=og.body_len; int segptr=0; int version=og.version(); int continued=og.continued(); int bos=og.bos(); int eos=og.eos(); long granulepos=og.granulepos(); int _serialno=og.serialno(); int _pageno=og.pageno(); int segments=header_base[header+26]&0xff; // clean up 'returned data' { int lr=lacing_returned; int br=body_returned; // body data //System.out.println("br="+br+", body_fill="+body_fill); if(br!=0) { body_fill-=br; if(body_fill!=0) { Array.Copy(body_data, br, body_data, 0, body_fill); } body_returned=0; } //System.out.println("?? br="+br+", body_fill="+body_fill+" body_returned="+body_returned); if(lr!=0) { // segment table if((lacing_fill-lr)!=0) { Array.Copy(lacing_vals, lr, lacing_vals, 0, lacing_fill-lr); Array.Copy(granule_vals, lr, granule_vals, 0, lacing_fill-lr); } lacing_fill-=lr; lacing_packet-=lr; lacing_returned=0; } } // check the serial number if(_serialno!=serialno)return(-1); if(version>0)return(-1); lacing_expand(segments+1); // are we in sequence? if(_pageno!=pageno) { int i; // unroll previous partial packet (if any) for(i=lacing_packet;i<lacing_fill;i++) { body_fill-=lacing_vals[i]&0xff; //System.out.println("??"); } lacing_fill=lacing_packet; // make a note of dropped data in segment table if(pageno!=-1) { lacing_vals[lacing_fill++]=0x400; lacing_packet++; } // are we a 'continued packet' page? If so, we'll need to skip // some segments if(continued!=0) { bos=0; for(;segptr<segments;segptr++) { int val=(header_base[header+27+segptr]&0xff); body+=val; bodysize-=val; if(val<255) { segptr++; break; } } } } //System.out.println("bodysize="+bodysize); if(bodysize!=0) { body_expand(bodysize); Array.Copy(body_base, body, body_data, body_fill, bodysize); body_fill+=bodysize; } //System.out.println("bodyfill="+body_fill); { int saved=-1; while(segptr<segments) { int val=(header_base[header+27+segptr]&0xff); lacing_vals[lacing_fill]=val; granule_vals[lacing_fill]=-1; if(bos!=0) { lacing_vals[lacing_fill]|=0x100; bos=0; } if(val<255)saved=lacing_fill; lacing_fill++; segptr++; if(val<255)lacing_packet=lacing_fill; } /* set the granulepos on the last pcmval of the last full packet */ if(saved!=-1) { granule_vals[saved]=granulepos; } } if(eos!=0) { e_o_s=1; if(lacing_fill>0) lacing_vals[lacing_fill-1]|=0x200; } pageno=_pageno+1; return(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) private void prefetch_all_headers(Info first_i, Comment first_c, int dataoffset) { Page og = new Page(); int ret; vis = new Info[links]; vcs = 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 // !!!!!!!!!!!!! vis[i] = first_i; //memcpy(vf->vi+i,first_i,sizeof(vorbis_info)); vcs[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(vis[i], vcs[i], null, null) == -1) { throw new Exception("Error opening logical bitstream #" + (i + 1) + "\n"); } 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 throw new Exception("Could not find last page of logical " + "bitstream #" + (i) + "\n"); } if (og.granulepos() != -1) { serialnos[i] = og.serialno(); pcmlengths[i] = og.granulepos(); break; } } } }
// seek to a sample offset relative to the decompressed pcm stream // returns zero on success, nonzero on failure private int pcm_seek(long pos) { int link = -1; long total = pcm_total(-1); if (pos < 0 || pos > total) { // goto seek_error; pcm_offset = -1; decode_clear(); return(-1); } // which bitstream section does this pcm offset occur in? for (link = links - 1; link >= 0; link--) { total -= pcmlengths[link]; if (pos >= total) { break; } } // search within the logical bitstream for the page with the highest // pcm_pos preceeding (or equal to) pos. There is a danger here; // missing pages or incorrect frame number information in the // bitstream could make our task impossible. Account for that (it // would be an error condition) { long target = pos - total; long end = offsets[link + 1]; long begin = offsets[link]; int best = (int)begin; Page og = new Page(); while (begin < end) { long bisect; int ret; if (end - begin < CHUNKSIZE) { bisect = begin; } else { bisect = (end + begin) / 2; } seek_helper(bisect); ret = get_next_page(og, end - bisect); if (ret == -1) { end = bisect; } else { long granulepos = og.granulepos(); if (granulepos < target) { best = ret; // raw offset of packet with granulepos begin = offset; // raw offset of next packet } else { end = bisect; } } } // found our page. seek to it (call raw_seek). if (raw_seek(best) != 0) { // goto seek_error; pcm_offset = -1; decode_clear(); return(-1); } } // verify result if (pcm_offset >= pos) { // goto seek_error; pcm_offset = -1; decode_clear(); return(-1); } if (pos > pcm_total(-1)) { // goto seek_error; pcm_offset = -1; decode_clear(); return(-1); } // discard samples until we reach the desired position. Crossing a // logical bitstream boundary with abandon is OK. while (pcm_offset < pos) { float[][] pcm; int target = (int)(pos - pcm_offset); float[][][] _pcm = new float[1][][]; int samples = vd.synthesis_pcmout(_pcm, _index); pcm = _pcm[0]; if (samples > target) { samples = target; } vd.synthesis_read(samples); pcm_offset += samples; if (samples < target) { if (process_packet(1) == 0) { pcm_offset = pcm_total(-1); // eof } } } return(0); // seek_error: // dump machine so we're in a known state // pcm_offset=-1; // decode_clear(); // return -1; }