package org.jcodec.codecs.mjpeg;
import org.jcodec.common.io.BitReader;
import org.jcodec.common.io.VLC;
import java.nio.ByteBuffer;
/**
* This class is part of JCodec ( www.jcodec.org ) This software is distributed
* under FreeBSD License
*
* Class for convenient reading JPEG entropy coded bit stream
*
* @author The JCodec project
*
*/
public class JPEGBitStream {
private VLC[] huff;
private BitReader _in;
private int[] dcPredictor;
private int lumaLen;
public JPEGBitStream(ByteBuffer b, VLC[] huff, int lumaLen) {
this.dcPredictor = new int[3];
this._in = BitReader.createBitReader(b);
this.huff = huff;
this.lumaLen = lumaLen;
}
public void readMCU(int[][] buf) {
int blk = 0;
for (int i = 0; i < lumaLen; i++, blk++) {
dcPredictor[0] = buf[blk][0] = readDCValue(dcPredictor[0], huff[0]);
readACValues(buf[blk], huff[2]);
}
dcPredictor[1] = buf[blk][0] = readDCValue(dcPredictor[1], huff[1]);
readACValues(buf[blk], huff[3]);
++blk;
dcPredictor[2] = buf[blk][0] = readDCValue(dcPredictor[2], huff[1]);
readACValues(buf[blk], huff[3]);
++blk;
}
public int readDCValue(int prevDC, VLC table) {
int code = table.readVLC(_in);
return code != 0 ? toValue(_in.readNBit(code), code) + prevDC : prevDC;
}
public void readACValues(int[] target, VLC table) {
int code;
int curOff = 1;
do {
code = table.readVLC(_in);
if (code == 0xF0) {
curOff += 16;
} else if (code > 0) {
int rle = code >> 4;
curOff += rle;
int len = code & 0xf;
target[curOff] = toValue(_in.readNBit(len), len);
curOff++;
}
} while (code != 0 && curOff < 64);
}
public final int toValue(int raw, int length) {
return (length >= 1 && raw < (1 << length - 1)) ? -(1 << length) + 1 + raw : raw;
}
}