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

com.jcraft.jogg.SyncState 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;

// DECODING PRIMITIVES: packet streaming layer

// This has two layers to place more of the multi-serialno and paging
// control in the application's hands.  First, we expose a data buffer
// using ogg_decode_buffer().  The app either copies into the
// buffer, or passes it directly to read(), etc.  We then call
// ogg_decode_wrote() to tell how many bytes we just added.
//
// Pages are returned (pointers into the buffer in ogg_sync_state)
// by ogg_decode_stream().  The page is then submitted to
// ogg_decode_page() along with the appropriate
// ogg_stream_state* (ie, matching serialno).  We then get raw
// packets out calling ogg_stream_packet() with a
// ogg_stream_state.  See the 'frame-prog.txt' docs for details and
// example code.

public class SyncState{

  public byte[] data;
  int storage;
  int fill;
  int returned;

  int unsynced;
  int headerbytes;
  int bodybytes;

  public int clear(){
    data=null;
    return (0);
  }

  public int buffer(int size){
    // first, clear out any space that has been previously returned
    if(returned!=0){
      fill-=returned;
      if(fill>0){
        System.arraycopy(data, returned, data, 0, fill);
      }
      returned=0;
    }

    if(size>storage-fill){
      // We need to extend the internal buffer
      int newsize=size+fill+4096; // an extra page to be nice
      if(data!=null){
        byte[] foo=new byte[newsize];
        System.arraycopy(data, 0, foo, 0, data.length);
        data=foo;
      }
      else{
        data=new byte[newsize];
      }
      storage=newsize;
    }

    return (fill);
  }

  public int wrote(int bytes){
    if(fill+bytes>storage)
      return (-1);
    fill+=bytes;
    return (0);
  }

  // sync the stream.  This is meant to be useful for finding page
  // boundaries.
  //
  // return values for this:
  // -n) skipped n bytes
  //  0) page not ready; more data (no bytes skipped)
  //  n) page synced at current location; page length n bytes
  private Page pageseek=new Page();
  private byte[] chksum=new byte[4];

  public int pageseek(Page og){
    int page=returned;
    int next;
    int bytes=fill-returned;

    if(headerbytes==0){
      int _headerbytes, i;
      if(bytes<27)
        return (0); // not enough for a header

      /* verify capture pattern */
      if(data[page]!='O'||data[page+1]!='g'||data[page+2]!='g'
          ||data[page+3]!='S'){
        headerbytes=0;
        bodybytes=0;

        // search for possible capture
        next=0;
        for(int ii=0; iibytes)
      return (0);

    // The whole test page is buffered.  Verify the checksum
    synchronized(chksum){
      // Grab the checksum bytes, set the header field to zero

      System.arraycopy(data, page+22, chksum, 0, 4);
      data[page+22]=0;
      data[page+23]=0;
      data[page+24]=0;
      data[page+25]=0;

      // set up a temp page struct and recompute the checksum
      Page log=pageseek;
      log.header_base=data;
      log.header=page;
      log.header_len=headerbytes;

      log.body_base=data;
      log.body=page+headerbytes;
      log.body_len=bodybytes;
      log.checksum();

      // Compare
      if(chksum[0]!=data[page+22]||chksum[1]!=data[page+23]
          ||chksum[2]!=data[page+24]||chksum[3]!=data[page+25]){
        // D'oh.  Mismatch! Corrupt page (or miscapture and not a page at all)
        // replace the computed checksum with the one actually read in
        System.arraycopy(chksum, 0, data, page+22, 4);
        // Bad checksum. Lose sync */

        headerbytes=0;
        bodybytes=0;
        // search for possible capture
        next=0;
        for(int ii=0; ii0){
        // have a page
        return (1);
      }
      if(ret==0){
        // need more data
        return (0);
      }

      // head did not start a synced page... skipped some bytes
      if(unsynced==0){
        unsynced=1;
        return (-1);
      }
      // loop. keep looking
    }
  }

  // clear things to an initial state.  Good to call, eg, before seeking
  public int reset(){
    fill=0;
    returned=0;
    unsynced=0;
    headerbytes=0;
    bodybytes=0;
    return (0);
  }

  public void init(){
  }

  public int getDataOffset(){
    return returned;
  }

  public int getBufferOffset(){
    return fill;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy