/* JOrbis * Copyright (C) 2000 ymnk, JCraft,Inc. * * Written by: 2000 ymnk * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jogg; public class StreamState{ byte[] body_data; /* bytes from packet bodies */ int body_storage; /* storage elements allocated */ int body_fill; /* elements stored; fill mark */ private int body_returned; /* elements of fill returned */ int[] lacing_vals; /* The values that will go to the segment table */ long[] granule_vals; /* pcm_pos values for headers. Not compact this way, but it is simple coupled to the lacing fifo */ int lacing_storage; int lacing_fill; int lacing_packet; int lacing_returned; byte[] header=new byte[282]; /* working space for header encode */ int header_fill; public int e_o_s; /* set when we have buffered the last packet in the logical bitstream */ int b_o_s; /* set after we've written the initial page of a logical bitstream */ int serialno; int pageno; long packetno; /* sequence number for decode; the framing knows where there's a hole in the data, but we need coupling so that the codec (which is in a seperate abstraction layer) also knows about the gap */ long granulepos; public StreamState(){ init(); } StreamState(int serialno){ this(); init(serialno); } void init(){ body_storage=16*1024; body_data=new byte[body_storage]; lacing_storage=1024; lacing_vals=new int[lacing_storage]; granule_vals=new long[lacing_storage]; } public void init(int serialno){ if(body_data==null){ init(); } else{ for(int i=0; i255?255:lacing_fill); int bytes=0; int acc=0; long granule_pos=granule_vals[0]; if(maxvals==0)return(0); /* construct a page */ /* decide how many segments to include */ /* If this is the initial header case, the first page must only include the initial header packet */ if(b_o_s==0){ /* 'initial header page' case */ granule_pos=0; for(vals=0;vals4096)break; acc+=(lacing_vals[vals]&0x0ff); granule_pos=granule_vals[vals]; } } /* construct the header in temp storage */ System.arraycopy("OggS".getBytes(), 0, header, 0, 4); /* stream structure version */ header[4]=0x00; /* continued packet flag? */ header[5]=0x00; if((lacing_vals[0]&0x100)==0)header[5]|=0x01; /* first page flag? */ if(b_o_s==0) header[5]|=0x02; /* last page flag? */ if(e_o_s!=0 && lacing_fill==vals) header[5]|=0x04; b_o_s=1; /* 64 bits of PCM position */ for(i=6;i<14;i++){ header[i]=(byte)granule_pos; granule_pos>>>=8; } /* 32 bits of stream serial number */ { int _serialno=serialno; for(i=14;i<18;i++){ header[i]=(byte)_serialno; _serialno>>>=8; } } /* 32 bits of page counter (we have both counter and page header because this val can roll over) */ if(pageno==-1)pageno=0; /* because someone called stream_reset; this would be a strange thing to do in an encode stream, but it has plausible uses */ { int _pageno=pageno++; for(i=18;i<22;i++){ header[i]=(byte)_pageno; _pageno>>>=8; } } /* zero for computation; filled in later */ header[22]=0; header[23]=0; header[24]=0; header[25]=0; /* segment table */ header[26]=(byte)vals; for(i=0;i>>=8; // } // // /* 32 bits of stream serial number */ // { // int serialn=serialno; // for(int i=14;i<18;i++){ // header[i]=(byte)serialn; // serialn>>>=8; // } // } // // ///* 32 bits of page counter (we have both counter and page header // because this val can roll over) */ // if(pageno==-1)pageno=0; /* because someone called // stream_reset; this would be a // strange thing to do in an // encode stream, but it has // plausible uses */ // { // int pagen=pageno++; // for(int i=18;i<22;i++){ // header[i]=(byte)pagen; // pagen>>>=8; // } // } // // /* zero for computation; filled in later */ // header[22]=0; // header[23]=0; // header[24]=0; // header[25]=0; // // /* segment table */ // header[26]=(byte)vals; // for(int i=0;i 4096 || /* 'page nominal size' case */ lacing_fill>=255 || /* 'segment table full' case */ (lacing_fill!=0&&b_o_s==0)){ /* 'initial header page' case */ return flush(og); } return 0; } public int eof(){ return e_o_s; } public int reset(){ body_fill=0; body_returned=0; lacing_fill=0; lacing_packet=0; lacing_returned=0; header_fill=0; e_o_s=0; b_o_s=0; pageno=-1; packetno=0; granulepos=0; return(0); } }