/*
* BitStream variable length code management table.
* Copyright (c) 2003 Jonathan Hueber.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* See Credits file and Readme for details
*/
package net.sourceforge.jffmpeg.codecs.utils;
/**
* This class manages the Variable length codes
*/
public class VLCTable {
/**
* Constructor
*/
protected VLCTable() {
}
/**
* This is the list of vlcCodes in {value, bitlength} pairs
*/
protected long[][] vlcCodes;
/**
* This are the fast lookup tables (0-0x1ff ranges)
*/
protected int[] codeLength = new int[ 0x1000 ];
protected int[] codeValue = new int[ 0x1000 ];
protected VLCTable[] nextLevel = new VLCTable[ 0x1000 ];
/**
* Getters for highspeed table
*/
public final int getCodeLength( int i ) {
return codeLength[ i ];
}
/**
* Getters for highspeed table
*/
public final int getCodeValue( int i ) {
return codeValue[ i ];
}
/**
* Getters for highspeed table
*/
public final VLCTable getNextLevel( int i ) {
return nextLevel[ i ];
}
/**
* Create indexed lookup tables
*/
protected void createHighSpeedTable() {
for ( int value = 0; value < vlcCodes.length; value++ ) {
int code = (int)vlcCodes[value][0];
int length = (int)vlcCodes[value][1];
if ( length == 0 ) continue; // Skip this value
writeTable( value, code, length );
}
}
/**
* Write this value into the index table
*/
protected void writeTable( int value, int code, int length ) {
if (length < 13) {
int top12Bits = code << (12 - length);
int range = ((code + 1) << (12 - length));
for ( int j = top12Bits; j < range; j++ ) {
codeLength[ j ] = length;
codeValue[ j ] = value;
}
} else {
int top12Bits = code >> (length - 12);
int remainingBits = code & ~(0xffff << (length - 12));
codeLength[ top12Bits ] = -1;
if (nextLevel[ top12Bits ] == null) nextLevel[ top12Bits ] = new VLCTable();
nextLevel[ top12Bits ].writeTable( value, remainingBits, length - 12 );
}
}
/**
* Returns decoded VLC or -1 if there is match
* Throws an exception if the numberOfBits is too great
*/
public int decode( int value, int numberOfBits ) throws FFMpegException {
boolean exception = true;
for (int i = 0; i < vlcCodes.length; i++ ) {
exception &= (vlcCodes[i][1] < numberOfBits);
if ( vlcCodes[i][1] == numberOfBits && vlcCodes[i][0] == value ) {
return i;
}
}
if (exception) throw new FFMpegException( "Illegal VLC code" );
return -1;
}
}