All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jcraft.jogg.StreamState Maven / Gradle / Ivy

The newest version!
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/* 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; i0)
      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; i0)
        lacing_vals[lacing_fill-1]|=0x200;
    }

    pageno=_pageno+1;
    return (0);
  }

  /* This will flush remaining packets into a page (returning nonzero),
     even if there is not enough data to trigger a flush normally
     (undersized page). If there are no packets or partial packets to
     flush, ogg_stream_flush returns 0.  Note that ogg_stream_flush will
     try to flush a normal sized page like ogg_stream_pageout; a call to
     ogg_stream_flush does not gurantee that all packets have flushed.
     Only a return value of 0 from ogg_stream_flush indicates all packet
     data is flushed into pages.

     ogg_stream_page will flush the last page in a stream even if it's
     undersized; you almost certainly want to use ogg_stream_pageout
     (and *not* ogg_stream_flush) unless you need to flush an undersized
     page in the middle of a stream for some reason. */

  public int flush(Page og){

    int i;
    int vals=0;
    int maxvals=(lacing_fill>255 ? 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; i4096|| /* '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);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy