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

net.sourceforge.jaad.aac.syntax.BitStream Maven / Gradle / Ivy

The newest version!
package net.sourceforge.jaad.aac.syntax;
import static java.lang.System.arraycopy;

import net.sourceforge.jaad.aac.AACException;

/**
 * This class is part of JAAD ( jaadec.sourceforge.net ) that is distributed
 * under the Public Domain license. Code changes provided by the JCodec project
 * are distributed under FreeBSD license. 
 *
 * @author in-somnia
 */
public class BitStream implements IBitStream {

	private static final int WORD_BITS = 32;
	private static final int WORD_BYTES = 4;
	private static final int BYTE_MASK = 0xff;
	
	public static BitStream createBitStream(byte[] data) {
        BitStream bs = new BitStream();
        bs.setData(data);
        return bs;
    }

    private byte[] buffer;
	private int pos; //offset in the buffer array
	private int cache; //current 4 bytes, that are read from the buffer
	protected int bitsCached; //remaining bits in current cache
	protected int position; //number of total bits read

	public BitStream() {
	}

	/* (non-Javadoc)
     * @see net.sourceforge.jaad.aac.syntax.IBitStream#destroy()
     */
	@Override
    public void destroy() {
		reset();
		buffer = null;
	}

	/* (non-Javadoc)
     * @see net.sourceforge.jaad.aac.syntax.IBitStream#setData(byte[])
     */
	@Override
    public final void setData(byte[] data) {
		//make the buffer size an integer number of words
		final int size = WORD_BYTES*((data.length+WORD_BYTES-1)/WORD_BYTES);
		//only reallocate if needed
		if(buffer==null||buffer.length!=size) buffer = new byte[size];
		arraycopy(data, 0, buffer, 0, data.length);
		reset();
	}

	/* (non-Javadoc)
     * @see net.sourceforge.jaad.aac.syntax.IBitStream#byteAlign()
     */
	@Override
    public void byteAlign() throws AACException {
		final int toFlush = bitsCached&7;
		if(toFlush>0) skipBits(toFlush);
	}

	/* (non-Javadoc)
     * @see net.sourceforge.jaad.aac.syntax.IBitStream#reset()
     */
	@Override
    public final void reset() {
		pos = 0;
		bitsCached = 0;
		cache = 0;
		position = 0;
	}

	/* (non-Javadoc)
     * @see net.sourceforge.jaad.aac.syntax.IBitStream#getPosition()
     */
	@Override
    public int getPosition() {
		return position;
	}

	/* (non-Javadoc)
     * @see net.sourceforge.jaad.aac.syntax.IBitStream#getBitsLeft()
     */
	@Override
    public int getBitsLeft() {
		return buffer != null ? 8*(buffer.length-pos)+bitsCached : 0;
	}

	/**
	 * Reads the next four bytes.
	 * @param peek if true, the stream pointer will not be increased
	 */
	protected int readCache(boolean peek) throws AACException {
		int i;
		if(pos>buffer.length-WORD_BYTES) throw AACException.endOfStream();
		else i = ((buffer[pos]&BYTE_MASK)<<24)
					|((buffer[pos+1]&BYTE_MASK)<<16)
					|((buffer[pos+2]&BYTE_MASK)<<8)
					|(buffer[pos+3]&BYTE_MASK);
		if(!peek) pos += WORD_BYTES;
		return i;
	}

	/* (non-Javadoc)
     * @see net.sourceforge.jaad.aac.syntax.IBitStream#readBits(int)
     */
	@Override
    public int readBits(int n) throws AACException {
		int result;
		if(bitsCached>=n) {
			bitsCached -= n;
			result = (cache>>bitsCached)&maskBits(n);
			position += n;
		}
		else {
			position += n;
			final int c = cache&maskBits(bitsCached);
			final int left = n-bitsCached;
			cache = readCache(false);
			bitsCached = WORD_BITS-left;
			result = ((cache>>bitsCached)&maskBits(left))|(c<0) {
			bitsCached--;
			i = (cache>>(bitsCached))&1;
			position++;
		}
		else {
			cache = readCache(false);
			bitsCached = WORD_BITS-1;
			position++;
			i = (cache>>bitsCached)&1;
		}
		return i;
	}

	/* (non-Javadoc)
     * @see net.sourceforge.jaad.aac.syntax.IBitStream#readBool()
     */
	@Override
    public boolean readBool() throws AACException {
		return (readBit()&0x1)!=0;
	}

	/* (non-Javadoc)
     * @see net.sourceforge.jaad.aac.syntax.IBitStream#peekBits(int)
     */
	@Override
    public int peekBits(int n) throws AACException {
		int ret;
		if(bitsCached>=n) {
			ret = (cache>>(bitsCached-n))&maskBits(n);
		}
		else {
			//old cache
			final int c = cache&maskBits(bitsCached);
			n -= bitsCached;
			//read next & combine
			ret = ((readCache(true)>>WORD_BITS-n)&maskBits(n))|(c<0) {
			ret = (cache>>(bitsCached-1))&1;
		}
		else {
			final int word = readCache(true);
			ret = (word>>WORD_BITS-1)&1;
		}
		return ret;
	}

	/* (non-Javadoc)
     * @see net.sourceforge.jaad.aac.syntax.IBitStream#skipBits(int)
     */
	@Override
    public void skipBits(int n) throws AACException {
		position += n;
		if(n<=bitsCached) {
			bitsCached -= n;
		}
		else {
			n -= bitsCached;
			while(n>=WORD_BITS) {
				n -= WORD_BITS;
				readCache(false);
			}
			if(n>0) {
				cache = readCache(false);
				bitsCached = WORD_BITS-n;
			}
			else {
				cache = 0;
				bitsCached = 0;
			}
		}
	}

	/* (non-Javadoc)
     * @see net.sourceforge.jaad.aac.syntax.IBitStream#skipBit()
     */
	@Override
    public void skipBit() throws AACException {
		position++;
		if(bitsCached>0) {
			bitsCached--;
		}
		else {
			cache = readCache(false);
			bitsCached = WORD_BITS-1;
		}
	}

	/* (non-Javadoc)
     * @see net.sourceforge.jaad.aac.syntax.IBitStream#maskBits(int)
     */
	@Override
    public int maskBits(int n) {
		int i;
		if(n==32) i = -1;
		else i = (1<




© 2015 - 2024 Weber Informatics LLC | Privacy Policy