示例#1
0
        private 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);
            }

            offset = input.Position = input.Length;
            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));
        }
示例#2
0
        // 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);
        }
示例#3
0
        // 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;
        }
示例#4
0
        int bisect_forward_serialno(long begin, long searched, long end, int currentno, int m)
        {
            long endsearched=end;
            long next=end;
            Page page=new Page();
            int ret;

            while(searched<endsearched) {
                long bisect;
                if(endsearched-searched<CHUNKSIZE) {
                    bisect=searched;
                }
                else {
                    bisect=(searched+endsearched)/2;
                }

                seek_helper(bisect);
                ret=get_next_page(page, -1);
                if(ret==OV_EREAD) { return OV_EREAD; }
                if(ret<0 || page.serialno()!=currentno) {
                    endsearched=bisect;
                    if(ret>=0) { next=ret; }
                }
                else {
                    searched=ret+page.header_len+page.body_len;
                }
            }
            seek_helper(next);
            ret=get_next_page(page, -1);
            if(ret==OV_EREAD) { return OV_EREAD; }

            if(searched>=end || ret==-1) {
                links=m+1;
                offsets=new long[m+2];
                offsets[m+1]=searched;
            }
            else {
                ret=bisect_forward_serialno(next, offset, end, page.serialno(), m+1);
                if(ret==OV_EREAD) { return OV_EREAD; }
            }
            offsets[m]=begin;
            return 0;
        }
示例#5
0
        // fetch and process a packet.  Handles the case where we're at a
        // bitstream boundary and dumps the decoding machine.  If the decoding
        // machine is unloaded, it loads it.  It also keeps pcm_offset up to
        // date (seek and read both use this.  seek uses a special hack with
        // readp).
        //
        // return: -1) hole in the data (lost packet)
        //          0) need more date (only if readp==0)/eof
        //          1) got a packet
        int process_packet(int readp)
        {
            Page og=new Page();

            // handle one packet.  Try to fetch it from current stream state
            // extract packets from page
            while(true) {
                // process a packet if we can.  If the machine isn't loaded,
                // neither is a page
                if(decode_ready) {
                    Packet op=new Packet();
                    int result=os.packetout(op);
                    long granulepos;
                    // if(result==-1)return(-1); // hole in the data. For now, swallow
                    // and go. We'll need to add a real
                    // error code in a bit.
                    if(result>0) {
                        // got a packet.  process it
                        granulepos=op.granulepos;
                        if(vb.synthesis(op)==0) {
                            // lazy check for lazy
                            // header handling.  The
                            // header packets aren't
                            // audio, so if/when we
                            // submit them,
                            // vorbis_synthesis will
                            // reject them
                            // suck in the synthesis data and track bitrate
                            {
                                int oldsamples=vd.synthesis_pcmout(null, null);
                                vd.synthesis_blockin(vb);
                                samptrack+=vd.synthesis_pcmout(null, null)-oldsamples;
                                bittrack+=op.bytes*8;
                            }

                            // update the pcm offset.
                            if(granulepos!=-1 && op.e_o_s==0) {
                                int link=(skable?current_link:0);
                                int samples;
                                // this packet has a pcm_offset on it (the last packet
                                // completed on a page carries the offset) After processing
                                // (above), we know the pcm position of the *last* sample
                                // ready to be returned. Find the offset of the *first*
                                //
                                // As an aside, this trick is inaccurate if we begin
                                // reading anew right at the last page; the end-of-stream
                                // granulepos declares the last frame in the stream, and the
                                // last packet of the last page may be a partial frame.
                                // So, we need a previous granulepos from an in-sequence page
                                // to have a reference point.  Thus the !op.e_o_s clause above

                                samples=vd.synthesis_pcmout(null, null);
                                granulepos-=samples;
                                for(int i=0; i<link; i++) {
                                    granulepos+=pcmlengths[i];
                                }
                                pcm_offset=granulepos;
                            }
                            return(1);
                        }
                    }
                }

                if(readp==0) { return(0); }
                if(get_next_page(og,-1)<0) { return(0); } // eof. leave unitialized

                // bitrate tracking; add the header's bytes here, the body bytes
                // are done by packet above
                bittrack+=og.header_len*8;

                // has our decoding just traversed a bitstream boundary?
                if(decode_ready) {
                    if(current_serialno!=og.serialno()) {
                        decode_clear();
                    }
                }

                // Do we need to load a new machine before submitting the page?
                // This is different in the seekable and non-seekable cases.
                //
                // In the seekable case, we already have all the header
                // information loaded and cached; we just initialize the machine
                // with it and continue on our merry way.
                //
                // In the non-seekable (streaming) case, we'll only be at a
                // boundary if we just left the previous logical bitstream and
                // we're now nominally at the header of the next bitstream

                if(!decode_ready) {
                    int i;
                    if(skable) {
                        current_serialno=og.serialno();

                        // match the serialno to bitstream section.  We use this rather than
                        // offset positions to avoid problems near logical bitstream
                        // boundaries
                        for(i=0; i<links; i++) {
                            if(serialnos[i]==current_serialno) { break; }
                        }
                        if(i==links) { return(-1); } // sign of a bogus stream.  error out,
                        // leave machine uninitialized
                        current_link=i;

                        os.init(current_serialno);
                        os.reset();

                    }
                    else {
                        // we're streaming
                        // fetch the three header packets, build the info struct
                        int[] foo = new int[1];
                        int ret=fetch_headers(vi[0], vc[0], foo, og);
                        current_serialno=foo[0];
                        if(ret!=0) { return ret; }
                        current_link++;
                        i=0;
                    }
                    make_decode_ready();
                }
                os.pagein(og);
            }
        }
示例#6
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;
                    }
                }
            }
        }
示例#7
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));
 }
示例#8
0
		// 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);
		}
示例#9
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;
                    }
                }
            }
        }
示例#10
0
        // uses the local ogg_stream storage in vf; this is important for
        // non-streaming input sources
        private 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)
                    {
                        throw new Exception("Corrupt header in logical bitstream.");
                    }
                    if (vi.synthesis_headerin(vc, op) != 0)
                    {
                        throw new Exception("Illegal header in logical bitstream.");
                    }
                    i++;
                }
                if (i < 3)
                {
                    if (get_next_page(og_ptr, 1) < 0)
                    {
                        throw new Exception("Missing header in logical bitstream.");
                    }
                }
            }
            return(0);
        }
示例#11
0
        // fetch and process a packet. Handles the case where we're at a
        // bitstream boundary and dumps the decoding machine. If the decoding
        // machine is unloaded, it loads it. It also keeps pcm_offset up to
        // date (seek and read both use this. seek uses a special hack with
        // readp).
        //
        // return: -1) hole in the data (lost packet)
        // 0) need more date (only if readp==0)/eof
        // 1) got a packet

        private int process_packet(int readp)
        {
            Page og = new Page();

            // handle one packet. Try to fetch it from current stream state
            // extract packets from page
            while (true)
            {
                // process a packet if we can. If the machine isn't loaded,
                // neither is a page
                if (decode_ready)
                {
                    Packet op     = new Packet();
                    int    result = os.packetout(op);
                    long   granulepos;
                    // if(result==-1)return(-1); // hole in the data. For now, swallow
                    // and go. We'll need to add a real
                    // error code in a bit.
                    if (result > 0)
                    {
                        // got a packet. process it
                        granulepos = op.granulepos;
                        if (vb.synthesis(op) == 0)
                        {
                            // lazy check for lazy
                            // header handling. The
                            // header packets aren't
                            // audio, so if/when we
                            // submit them,
                            // vorbis_synthesis will
                            // reject them
                            // suck in the synthesis data and track bitrate
                            {
                                int oldsamples = vd.synthesis_pcmout(null, null);
                                vd.synthesis_blockin(vb);
                                samptrack += vd.synthesis_pcmout(null, null) - oldsamples;
                                bittrack  += op.bytes * 8;
                            }

                            // update the pcm offset.
                            if (granulepos != -1 && op.e_o_s == 0)
                            {
                                int link = current_link;
                                int samples;
                                // this packet has a pcm_offset on it (the last packet
                                // completed on a page carries the offset) After processing
                                // (above), we know the pcm position of the *last* sample
                                // ready to be returned. Find the offset of the *first*
                                //
                                // As an aside, this trick is inaccurate if we begin
                                // reading anew right at the last page; the end-of-stream
                                // granulepos declares the last frame in the stream, and the
                                // last packet of the last page may be a partial frame.
                                // So, we need a previous granulepos from an in-sequence page
                                // to have a reference point. Thus the !op.e_o_s clause above

                                samples     = vd.synthesis_pcmout(null, null);
                                granulepos -= samples;
                                for (int i = 0; i < link; i++)
                                {
                                    granulepos += pcmlengths[i];
                                }
                                pcm_offset = granulepos;
                            }
                            return(1);
                        }
                    }
                }

                if (readp == 0)
                {
                    return(0);
                }
                if (get_next_page(og, -1) < 0)
                {
                    return(0);
                }                                              // eof. leave unitialized

                // bitrate tracking; add the header's bytes here, the body bytes
                // are done by packet above
                bittrack += og.header_len * 8;

                // has our decoding just traversed a bitstream boundary?
                if (decode_ready)
                {
                    if (current_serialno != og.serialno())
                    {
                        decode_clear();
                    }
                }

                // Do we need to load a new machine before submitting the page?
                // This is different in the seekable and non-seekable cases.
                //
                // In the seekable case, we already have all the header
                // information loaded and cached; we just initialize the machine
                // with it and continue on our merry way.
                //
                // In the non-seekable (streaming) case, we'll only be at a
                // boundary if we just left the previous logical bitstream and
                // we're now nominally at the header of the next bitstream

                if (!decode_ready)
                {
                    int i;
                    current_serialno = og.serialno();

                    // match the serialno to bitstream section. We use this rather than
                    // offset positions to avoid problems near logical bitstream
                    // boundaries
                    for (i = 0; i < links; i++)
                    {
                        if (serialnos[i] == current_serialno)
                        {
                            break;
                        }
                    }
                    if (i == links)
                    {
                        return(-1);
                    }                                // sign of a bogus stream. error out,
                    // leave machine uninitialized
                    current_link = i;

                    os.init(current_serialno);
                    os.reset();

                    make_decode_ready();
                }
                os.pagein(og);
            }
        }
示例#12
0
        private int bisect_forward_serialno(long begin, long searched, long end, int currentno, int m)
        {
            long endsearched = end;
            long next        = end;
            Page page        = new Page();
            int  ret;

            while (searched < endsearched)
            {
                long bisect;
                if (endsearched - searched < CHUNKSIZE)
                {
                    bisect = searched;
                }
                else
                {
                    bisect = (searched + endsearched) / 2;
                }

                seek_helper(bisect);
                ret = get_next_page(page, -1);
                if (ret == OV_EREAD)
                {
                    return(OV_EREAD);
                }
                if (ret < 0 || page.serialno() != currentno)
                {
                    endsearched = bisect;
                    if (ret >= 0)
                    {
                        next = ret;
                    }
                }
                else
                {
                    searched = ret + page.header_len + page.body_len;
                }
            }
            seek_helper(next);
            ret = get_next_page(page, -1);
            if (ret == OV_EREAD)
            {
                return(OV_EREAD);
            }

            if (searched >= end || ret == -1)
            {
                links          = m + 1;
                offsets        = new long[m + 2];
                offsets[m + 1] = searched;
            }
            else
            {
                ret = bisect_forward_serialno(next, offset, end, page.serialno(), m + 1);
                if (ret == OV_EREAD)
                {
                    return(OV_EREAD);
                }
            }
            offsets[m] = begin;
            return(0);
        }