package org.jcodec.common.io;
import java.io.IOException;
import java.io.InputStream;
import java.lang.IllegalArgumentException;
/**
* This class is part of JCodec ( www.jcodec.org ) This software is distributed
* under FreeBSD License
*
* A dummy implementation of H264 RBSP reading
*
* @author The JCodec project
*
*/
public class DummyBitstreamReader {
private InputStream is;
private int curByte;
private int nextByte;
private int secondByte;
int nBit;
protected static int bitsRead;
public DummyBitstreamReader(InputStream is) throws IOException {
this.is = is;
curByte = is.read();
nextByte = is.read();
secondByte = is.read();
// println("\n-> " + curByte);
}
int cnt = 0;
/*
* (non-Javadoc)
*
* @see ua.org.jplayer.javcodec.h264.RBSPInputStream#read1Bit()
*/
public int read1Bit() throws IOException {
return read1BitInt();
}
public int read1BitInt() throws IOException {
if (nBit == 8) {
advance();
if (curByte == -1) {
return -1;
}
}
int res = (curByte >> (7 - nBit)) & 1;
nBit++;
// debugBits.append(res == 0 ? '0' : '1');
++bitsRead;
return res;
}
/*
* (non-Javadoc)
*
* @see ua.org.jplayer.javcodec.h264.RBSPInputStream#readNBit(int)
*/
public int readNBit(int n) throws IOException {
if (n > 32)
throw new IllegalArgumentException("Can not read more then 32 bit");
int val = 0;
for (int i = 0; i < n; i++) {
val <<= 1;
val |= read1BitInt();
}
return val;
}
private final void advance1() throws IOException {
curByte = nextByte;
nextByte = secondByte;
secondByte = is.read();
}
private final void advance() throws IOException {
advance1();
nBit = 0;
// println("\n-> " + curByte);
}
/*
* (non-Javadoc)
*
* @see ua.org.jplayer.javcodec.h264.RBSPInputStream#readByte()
*/
public int readByte() throws IOException {
if (nBit > 0) {
advance();
}
int res = curByte;
advance();
return res;
}
/*
* (non-Javadoc)
*
* @see ua.org.jplayer.javcodec.h264.RBSPInputStream#moreRBSPData()
*/
public boolean moreRBSPData() throws IOException {
if (nBit == 8) {
advance();
}
int tail = 1 << (8 - nBit - 1);
int mask = ((tail << 1) - 1);
boolean hasTail = (curByte & mask) == tail;
return !(curByte == -1 || (nextByte == -1 && hasTail));
}
public long getBitPosition() {
return (bitsRead * 8 + (nBit % 8));
}
public boolean moreData() throws IOException {
if (nBit == 8)
advance();
if (curByte == -1)
return false;
if (nextByte == -1 || (nextByte == 0 && secondByte == -1)) {
int mask = (1 << (8 - nBit)) - 1;
return (curByte & mask) != 0;
}
return true;
}
/*
* (non-Javadoc)
*
* @see ua.org.jplayer.javcodec.h264.RBSPInputStream#readRemainingByte()
*/
public long readRemainingByte() throws IOException {
return readNBit(8 - nBit);
}
/*
* (non-Javadoc)
*
* @see ua.org.jplayer.javcodec.h264.RBSPInputStream#next_bits(int)
*/
public int peakNextBits(int n) throws IOException {
if (n > 8)
throw new IllegalArgumentException("N should be less then 8");
if (nBit == 8) {
advance();
if (curByte == -1) {
return -1;
}
}
int[] bits = new int[16 - nBit];
int cnt = 0;
for (int i = nBit; i < 8; i++) {
bits[cnt++] = (curByte >> (7 - i)) & 0x1;
}
for (int i = 0; i < 8; i++) {
bits[cnt++] = (nextByte >> (7 - i)) & 0x1;
}
int result = 0;
for (int i = 0; i < n; i++) {
result <<= 1;
result |= bits[i];
}
return result;
}
/*
* (non-Javadoc)
*
* @see ua.org.jplayer.javcodec.h264.RBSPInputStream#byte_aligned()
*/
public boolean isByteAligned() {
return (nBit % 8) == 0;
}
/*
* (non-Javadoc)
*
* @see ua.org.jplayer.javcodec.h264.RBSPInputStream#close()
*/
public void close() throws IOException {
is.close();
}
public int getCurBit() {
return nBit;
}
public final int skip(int bits) throws IOException {
nBit += bits;
int was = nBit;
while (nBit >= 8 && curByte != -1) {
advance1();
nBit -= 8;
}
return was - nBit;
}
public int align() throws IOException {
int n = (8 - nBit) & 0x7;
skip((8 - nBit) & 0x7);
return n;
}
public int checkNBit(int n) throws IOException {
return peakNextBits(n);
}
public int curBit() {
return nBit;
}
public boolean lastByte() throws IOException {
return nextByte == -1 && secondByte == -1;
}
}