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

de.jarnbjo.ogg.OggPage Maven / Gradle / Ivy

The newest version!
/*
 * $ProjectName$
 * $ProjectRevision$
 * -----------------------------------------------------------
 * $Id: OggPage.java,v 1.3 2003/04/10 19:48:22 jarnbjo Exp $
 * -----------------------------------------------------------
 *
 * $Author: jarnbjo $
 *
 * Description:
 *
 * Copyright 2002-2003 Tor-Einar Jarnbjo
 * -----------------------------------------------------------
 *
 * Change History
 * -----------------------------------------------------------
 * $Log: OggPage.java,v $
 * Revision 1.3  2003/04/10 19:48:22  jarnbjo
 * no message
 *
 * Revision 1.2  2003/03/31 00:23:04  jarnbjo
 * no message
 *
 * Revision 1.1  2003/03/03 21:02:20  jarnbjo
 * no message
 *
 */

package de.jarnbjo.ogg;

import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;

import de.jarnbjo.util.io.BitInputStream;
import de.jarnbjo.util.io.ByteArrayBitInputStream;

/**
 * 

An instance of this class represents an ogg page read from an ogg file * or network stream. It has no public constructor, but instances can be * created by the create methods, supplying a JMF stream or * a RandomAccessFile * which is positioned at the beginning of an Ogg page.

* *

Furtheron, the class provides methods for accessing the raw page data, * as well as data attributes like segmenting information, sequence number, * stream serial number, chechsum and wether this page is the beginning or * end of a logical bitstream (BOS, EOS) and if the page data starts with a * continued packet or a fresh data packet.

*/ public class OggPage { private int version; private boolean continued, bos, eos; private long absoluteGranulePosition; private int streamSerialNumber, pageSequenceNumber, pageCheckSum; private int[] segmentOffsets; private int[] segmentLengths; private int totalLength; private byte[] header, segmentTable, data; protected OggPage() { } private OggPage( int version, boolean continued, boolean bos, boolean eos, long absoluteGranulePosition, int streamSerialNumber, int pageSequenceNumber, int pageCheckSum, int[] segmentOffsets, int[] segmentLengths, int totalLength, byte[] header, byte[] segmentTable, byte[] data) { this.version=version; this.continued=continued; this.bos=bos; this.eos=eos; this.absoluteGranulePosition=absoluteGranulePosition; this.streamSerialNumber=streamSerialNumber; this.pageSequenceNumber=pageSequenceNumber; this.pageCheckSum=pageCheckSum; this.segmentOffsets=segmentOffsets; this.segmentLengths=segmentLengths; this.totalLength=totalLength; this.header=header; this.segmentTable=segmentTable; this.data=data; } /** * this method equals to create(RandomAccessFile source, false) * * @see #create(RandomAccessFile, boolean) */ public static OggPage create(RandomAccessFile source) throws IOException, EndOfOggStreamException, OggFormatException { return create(source, false); } /** * This method is called to read data from the current position in the * specified RandomAccessFile and create a new OggPage instance based on the data * read. If the parameter skipData is set to true, * the actual page segments (page data) is skipped and not read into * memory. This mode is useful when scanning through an ogg file to build * a seek table. * * @param source the source from which the ogg page is generated * @param skipData if set to true, the actual page data is not read into memory * @return an ogg page created by reading data from the specified source, starting at the current position * @throws OggFormatException if the data read from the specified source is not matching the specification for an ogg page * @throws EndOfOggStreamException if it is not possible to read an entire ogg page from the specified source * @throws IOException if some other I/O error is detected when reading from the source * * @see #create(RandomAccessFile) */ public static OggPage create(RandomAccessFile source, boolean skipData) throws IOException, EndOfOggStreamException, OggFormatException { return create((Object)source, skipData); } /** * this method equals to create(InputStream source, false) * * @see #create(InputStream, boolean) */ public static OggPage create(InputStream source) throws IOException, EndOfOggStreamException, OggFormatException { return create(source, false); } /** * This method is called to read data from the current position in the * specified InpuStream and create a new OggPage instance based on the data * read. If the parameter skipData is set to true, * the actual page segments (page data) is skipped and not read into * memory. This mode is useful when scanning through an ogg file to build * a seek table. * * @param source the source from which the ogg page is generated * @param skipData if set to true, the actual page data is not read into memory * @return an ogg page created by reading data from the specified source, starting at the current position * @throws OggFormatException if the data read from the specified source is not matching the specification for an ogg page * @throws EndOfOggStreamException if it is not possible to read an entire ogg page from the specified source * @throws IOException if some other I/O error is detected when reading from the source * * @see #create(InputStream) */ public static OggPage create(InputStream source, boolean skipData) throws IOException, EndOfOggStreamException, OggFormatException { return create((Object)source, skipData); } /** * this method equals to create(byte[] source, false) * * @see #create(byte[], boolean) */ public static OggPage create(byte[] source) throws IOException, EndOfOggStreamException, OggFormatException { return create(source, false); } /** * This method is called to * create a new OggPage instance based on the specified byte array. * * @param source the source from which the ogg page is generated * @param skipData if set to true, the actual page data is not read into memory * @return an ogg page created by reading data from the specified source, starting at the current position * @throws OggFormatException if the data read from the specified source is not matching the specification for an ogg page * @throws EndOfOggStreamException if it is not possible to read an entire ogg page from the specified source * @throws IOException if some other I/O error is detected when reading from the source * * @see #create(byte[]) */ public static OggPage create(byte[] source, boolean skipData) throws IOException, EndOfOggStreamException, OggFormatException { return create((Object)source, skipData); } private static OggPage create(Object source, boolean skipData) throws IOException, EndOfOggStreamException, OggFormatException { try { int sourceOffset=27; byte[] header=new byte[27]; if(source instanceof RandomAccessFile) { RandomAccessFile raf=(RandomAccessFile)source; if(raf.getFilePointer()==raf.length()) { return null; } raf.readFully(header); } else if(source instanceof InputStream) { readFully((InputStream)source, header); } else if(source instanceof byte[]) { System.arraycopy((byte[])source, 0, header, 0, 27); } BitInputStream bdSource=new ByteArrayBitInputStream(header); int capture=bdSource.getInt(32); if(capture!=0x5367674f) { //throw new FormatException("Ogg page does not start with 'OggS' (0x4f676753)"); /* ** This condition is IMHO an error, but older Ogg files often contain ** pages with a different capture than OggS. I am not sure how to ** manage these pages, but the decoder seems to work properly, if ** the incorrect capture is simply ignored. */ String cs=Integer.toHexString(capture); while(cs.length()<8) { cs="0"+cs; } cs=cs.substring(6, 8)+cs.substring(4, 6)+cs.substring(2, 4)+cs.substring(0, 2); char c1=(char)(Integer.valueOf(cs.substring(0, 2), 16).intValue()); char c2=(char)(Integer.valueOf(cs.substring(2, 4), 16).intValue()); char c3=(char)(Integer.valueOf(cs.substring(4, 6), 16).intValue()); char c4=(char)(Integer.valueOf(cs.substring(6, 8), 16).intValue()); System.out.println("Ogg packet header is 0x"+cs+" ("+c1+c2+c3+c4+"), should be 0x4f676753 (OggS)"); } int version=bdSource.getInt(8); byte tmp=(byte)bdSource.getInt(8); boolean bf1=(tmp&1)!=0; boolean bos=(tmp&2)!=0; boolean eos=(tmp&4)!=0; long absoluteGranulePosition=bdSource.getLong(64); int streamSerialNumber=bdSource.getInt(32); int pageSequenceNumber=bdSource.getInt(32); int pageCheckSum=bdSource.getInt(32); int pageSegments=bdSource.getInt(8); //System.out.println("OggPage: "+streamSerialNumber+" / "+absoluteGranulePosition+" / "+pageSequenceNumber); int[] segmentOffsets=new int[pageSegments]; int[] segmentLengths=new int[pageSegments]; int totalLength=0; byte[] segmentTable=new byte[pageSegments]; byte[] tmpBuf=new byte[1]; for(int i=0; itrue
if this page begins with a continued packet */ public boolean isContinued() { return continued; } /** * @return true if this page begins with a fresh packet */ public boolean isFresh() { return !continued; } /** * @return true if this page is the beginning of a logical stream */ public boolean isBos() { return bos; } /** * @return true if this page is the end of a logical stream */ public boolean isEos() { return eos; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy