📄 vlc.java
字号:
import java.io.*;
/*
* Variable-length coding (VLC) is a statistical coding technique that
* assigns codewords to values to be encoded. Values of high frequency
* of occurrence are assigned short codewords, and those of infrequent
* occurrence are assigned long codewords. On average, the more frequent
* shorter codewords dominate such that the code string is shorter than
* the original data.
*/
public class Vlc {
public static final short NEXT1 = (short)0xdead;
public static final short NEXT2 = (short)0xbeef;
public static final short ESCAPE = 0x080b;
public static final short STUFFING = 0x0f0b;
// Store in pair value, length
private static final short[] macroblock_address_increment = {
NEXT1, NEXT2, 0x0705, 0x0605, 0x0504, 0x0504, 0x0404, 0x0404,
0x0303, 0x0303, 0x0303, 0x0303, 0x0203, 0x0203, 0x0203, 0x0203,
0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101
};
private static final short[] macroblock_address_increment2 = {
0x0d08, 0x0d08, 0x0d08, 0x0d08, 0x0d08, 0x0d08, 0x0d08, 0x0d08,
0x0c08, 0x0c08, 0x0c08, 0x0c08, 0x0c08, 0x0c08, 0x0c08, 0x0c08,
0x0b08, 0x0b08, 0x0b08, 0x0b08, 0x0b08, 0x0b08, 0x0b08, 0x0b08,
0x0a08, 0x0a08, 0x0a08, 0x0a08, 0x0a08, 0x0a08, 0x0a08, 0x0a08,
0x0907, 0x0907, 0x0907, 0x0907, 0x0907, 0x0907, 0x0907, 0x0907,
0x0907, 0x0907, 0x0907, 0x0907, 0x0907, 0x0907, 0x0907, 0x0907,
0x0807, 0x0807, 0x0807, 0x0807, 0x0807, 0x0807, 0x0807, 0x0807,
0x0807, 0x0807, 0x0807, 0x0807, 0x0807, 0x0807, 0x0807, 0x0807
};
private static final short[] macroblock_address_increment1 = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
ESCAPE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, STUFFING,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x210b, 0x200b, 0x1f0b, 0x1e0b, 0x1d0b, 0x1c0b, 0x1b0b, 0x1a0b,
0x190b, 0x180b, 0x170b, 0x160b, 0x150a, 0x150a, 0x140a, 0x140a,
0x130a, 0x130a, 0x120a, 0x120a, 0x110a, 0x110a, 0x100a, 0x100a,
0x0f08, 0x0f08, 0x0f08, 0x0f08, 0x0f08, 0x0f08, 0x0f08, 0x0f08,
0x0e08, 0x0e08, 0x0e08, 0x0e08, 0x0e08, 0x0e08, 0x0e08, 0x0e08
};
public int getMacroblockAddressIncrement(InputBitStream input) throws IOException {
int index = input.nextBits(11);
int value = macroblock_address_increment[index >> 6];
if (value == NEXT1)
value = macroblock_address_increment1[index & 0x3f];
else if (value == NEXT2)
value = macroblock_address_increment2[index & 0x3f];
input.getBits(value & 0xff);
return value >> 8;
}
private static final byte[] macroblock_type_i = {
0x00, 0x12, 0x01, 0x01
};
private static final short[] macroblock_type_p = {
0x0000, 0x1106, 0x1205, 0x1205, 0x1a05, 0x1a05, 0x0105, 0x0105,
0x0803, 0x0803, 0x0803, 0x0803, 0x0803, 0x0803, 0x0803, 0x0803,
0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202,
0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202
};
private static final short[] macroblock_type_b = {
0x0000, 0x1106, 0x1606, 0x1a06, 0x1e05, 0x1e05, 0x0105, 0x0105,
0x0804, 0x0804, 0x0804, 0x0804, 0x0a04, 0x0a04, 0x0a04, 0x0a04,
0x0403, 0x0403, 0x0403, 0x0403, 0x0403, 0x0403, 0x0403, 0x0403,
0x0603, 0x0603, 0x0603, 0x0603, 0x0603, 0x0603, 0x0603, 0x0603
};
public class MacroblockType {
public boolean mMacroblockQuant;
public boolean mMacroblockMotionForward;
public boolean mMacroblockMotionBackward;
public boolean mMacroblockPattern;
public boolean mMacroblockIntra;
}
public void getMacroblockType(int pictureType, InputBitStream input, MacroblockType macroblockType) throws IOException {
int index = 0;
int value = 0;
int length = 0;
switch (pictureType) {
case Picture.I_TYPE:
index = input.nextBits(2);
length = macroblock_type_i[index] & 0x0f;
macroblockType.mMacroblockQuant = (macroblock_type_i[index] >> 4) != 0;
macroblockType.mMacroblockMotionForward = false;
macroblockType.mMacroblockMotionBackward = false;
macroblockType.mMacroblockPattern = false;
macroblockType.mMacroblockIntra = true;
input.getBits(length);
break;
case Picture.P_TYPE:
index = input.nextBits(6);
// Handle special case: highest bit is 1
value = index < 0x20? macroblock_type_p[index] >> 8 : 0x0a;
length = index < 0x20? macroblock_type_p[index] & 0xff : 1;
macroblockType.mMacroblockQuant = (value & 0x10) != 0;
macroblockType.mMacroblockMotionForward = (value & 0x08) != 0;
macroblockType.mMacroblockMotionBackward = (value & 0x04) != 0;
macroblockType.mMacroblockPattern = (value & 0x02) != 0;
macroblockType.mMacroblockIntra = (value & 0x01) != 0;
input.getBits(length);
break;
case Picture.B_TYPE:
index = input.nextBits(6);
// Handle 2 special cases: highest bit 1
value = index < 0x20? macroblock_type_b[index] >> 8 : index < 0x30? 0x0c : 0x0e;
length = index < 0x20? macroblock_type_b[index] & 0xff : 2;
macroblockType.mMacroblockQuant = (value & 0x10) != 0;
macroblockType.mMacroblockMotionForward = (value & 0x08) != 0;
macroblockType.mMacroblockMotionBackward = (value & 0x04) != 0;
macroblockType.mMacroblockPattern = (value & 0x02) != 0;
macroblockType.mMacroblockIntra = (value & 0x01) != 0;
input.getBits(length);
break;
case Picture.D_TYPE:
break;
}
}
private static final short[] motion_vector = {
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x0000100b, 0xfffff00b, 0x00000f0b, 0xfffff10b, 0x00000e0b, 0xfffff20b, 0x00000d0b, 0xfffff30b,
0x00000c0b, 0xfffff40b, 0x00000b0b, 0xfffff50b, 0x00000a0a, 0x00000a0a, 0xfffff60a, 0xfffff60a,
0x0000090a, 0x0000090a, 0xfffff70a, 0xfffff70a, 0x0000080a, 0x0000080a, 0xfffff80a, 0xfffff80a,
0x00000708, 0x00000708, 0x00000708, 0x00000708, 0x00000708, 0x00000708, 0x00000708, 0x00000708,
0xfffff908, 0xfffff908, 0xfffff908, 0xfffff908, 0xfffff908, 0xfffff908, 0xfffff908, 0xfffff908,
0x00000608, 0x00000608, 0x00000608, 0x00000608, 0x00000608, 0x00000608, 0x00000608, 0x00000608,
0xfffffa08, 0xfffffa08, 0xfffffa08, 0xfffffa08, 0xfffffa08, 0xfffffa08, 0xfffffa08, 0xfffffa08,
0x00000508, 0x00000508, 0x00000508, 0x00000508, 0x00000508, 0x00000508, 0x00000508, 0x00000508,
0xfffffb08, 0xfffffb08, 0xfffffb08, 0xfffffb08, 0xfffffb08, 0xfffffb08, 0xfffffb08, 0xfffffb08,
0x00000407, 0x00000407, 0x00000407, 0x00000407, 0x00000407, 0x00000407, 0x00000407, 0x00000407,
0x00000407, 0x00000407, 0x00000407, 0x00000407, 0x00000407, 0x00000407, 0x00000407, 0x00000407,
0xfffffc07, 0xfffffc07, 0xfffffc07, 0xfffffc07, 0xfffffc07, 0xfffffc07, 0xfffffc07, 0xfffffc07,
0xfffffc07, 0xfffffc07, 0xfffffc07, 0xfffffc07, 0xfffffc07, 0xfffffc07, 0xfffffc07, 0xfffffc07,
};
private static final short[] motion_vector1 = {
0x00000000, 0x00000000, 0x00000305, 0xfffffd05, 0x00000204, 0x00000204, 0xfffffe04, 0xfffffe04,
0x00000103, 0x00000103, 0x00000103, 0x00000103, 0xffffff03, 0xffffff03, 0xffffff03, 0xffffff03,
0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001
};
public int getMotionVector(InputBitStream input) throws IOException {
int index = input.nextBits(11);
int value = 0;
int length = 0;
if (((index >> 7) & 0xf) == 0x0) {
value = motion_vector[index] >> 0x8;
length = motion_vector[index] & 0xff;
}
else {
index >>= 6;
value = motion_vector1[index] >> 0x8;
length = motion_vector1[index] & 0xff;
}
input.getBits(length);
return value;
}
private static final short[] coded_block_pattern = {
0x0000, 0x0000, 0x2709, 0x1b09, 0x3b09, 0x3709, 0x2f09, 0x1f09,
0x3a08, 0x3a08, 0x3608, 0x3608, 0x2e08, 0x2e08, 0x1e08, 0x1e08,
0x3908, 0x3908, 0x3508, 0x3508, 0x2d08, 0x2d08, 0x1d08, 0x1d08,
0x2608, 0x2608, 0x1a08, 0x1a08, 0x2508, 0x2508, 0x1908, 0x1908,
0x2b08, 0x2b08, 0x1708, 0x1708, 0x3308, 0x3308, 0x0f08, 0x0f08,
0x2a08, 0x2a08, 0x1608, 0x1608, 0x3208, 0x3208, 0x0e08, 0x0e08,
0x2908, 0x2908, 0x1508, 0x1508, 0x3108, 0x3108, 0x0d08, 0x0d08,
0x2308, 0x2308, 0x1308, 0x1308, 0x0b08, 0x0b08, 0x0708, 0x0708,
0x2207, 0x2207, 0x2207, 0x2207, 0x1207, 0x1207, 0x1207, 0x1207,
0x0a07, 0x0a07, 0x0a07, 0x0a07, 0x0607, 0x0607, 0x0607, 0x0607,
0x2107, 0x2107, 0x2107, 0x2107, 0x1107, 0x1107, 0x1107, 0x1107,
0x0907, 0x0907, 0x0907, 0x0907, 0x0507, 0x0507, 0x0507, 0x0507,
0x3f06, 0x3f06, 0x3f06, 0x3f06, 0x3f06, 0x3f06, 0x3f06, 0x3f06,
0x0306, 0x0306, 0x0306, 0x0306, 0x0306, 0x0306, 0x0306, 0x0306,
0x2406, 0x2406, 0x2406, 0x2406, 0x2406, 0x2406, 0x2406, 0x2406,
0x1806, 0x1806, 0x1806, 0x1806, 0x1806, 0x1806, 0x1806, 0x1806,
0x3e05, 0x3e05, 0x3e05, 0x3e05, 0x3e05, 0x3e05, 0x3e05, 0x3e05,
0x3e05, 0x3e05, 0x3e05, 0x3e05, 0x3e05, 0x3e05, 0x3e05, 0x3e05,
0x0205, 0x0205, 0x0205, 0x0205, 0x0205, 0x0205, 0x0205, 0x0205,
0x0205, 0x0205, 0x0205, 0x0205, 0x0205, 0x0205, 0x0205, 0x0205,
0x3d05, 0x3d05, 0x3d05, 0x3d05, 0x3d05, 0x3d05, 0x3d05, 0x3d05,
0x3d05, 0x3d05, 0x3d05, 0x3d05, 0x3d05, 0x3d05, 0x3d05, 0x3d05,
0x0105, 0x0105, 0x0105, 0x0105, 0x0105, 0x0105, 0x0105, 0x0105,
0x0105, 0x0105, 0x0105, 0x0105, 0x0105, 0x0105, 0x0105, 0x0105,
0x3805, 0x3805, 0x3805, 0x3805, 0x3805, 0x3805, 0x3805, 0x3805,
0x3805, 0x3805, 0x3805, 0x3805, 0x3805, 0x3805, 0x3805, 0x3805,
0x3405, 0x3405, 0x3405, 0x3405, 0x3405, 0x3405, 0x3405, 0x3405,
0x3405, 0x3405, 0x3405, 0x3405, 0x3405, 0x3405, 0x3405, 0x3405,
0x2c05, 0x2c05, 0x2c05, 0x2c05, 0x2c05, 0x2c05, 0x2c05, 0x2c05,
0x2c05, 0x2c05, 0x2c05, 0x2c05, 0x2c05, 0x2c05, 0x2c05, 0x2c05,
0x1c05, 0x1c05, 0x1c05, 0x1c05, 0x1c05, 0x1c05, 0x1c05, 0x1c05,
0x1c05, 0x1c05, 0x1c05, 0x1c05, 0x1c05, 0x1c05, 0x1c05, 0x1c05,
0x2805, 0x2805, 0x2805, 0x2805, 0x2805, 0x2805, 0x2805, 0x2805,
0x2805, 0x2805, 0x2805, 0x2805, 0x2805, 0x2805, 0x2805, 0x2805,
0x1405, 0x1405, 0x1405, 0x1405, 0x1405, 0x1405, 0x1405, 0x1405,
0x1405, 0x1405, 0x1405, 0x1405, 0x1405, 0x1405, 0x1405, 0x1405,
0x3005, 0x3005, 0x3005, 0x3005, 0x3005, 0x3005, 0x3005, 0x3005,
0x3005, 0x3005, 0x3005, 0x3005, 0x3005, 0x3005, 0x3005, 0x3005,
0x0c05, 0x0c05, 0x0c05, 0x0c05, 0x0c05, 0x0c05, 0x0c05, 0x0c05,
0x0c05, 0x0c05, 0x0c05, 0x0c05, 0x0c05, 0x0c05, 0x0c05, 0x0c05,
0x2004, 0x2004, 0x2004, 0x2004, 0x2004, 0x2004, 0x2004, 0x2004,
0x2004, 0x2004, 0x2004, 0x2004, 0x2004, 0x2004, 0x2004, 0x2004,
0x2004, 0x2004, 0x2004, 0x2004, 0x2004, 0x2004, 0x2004, 0x2004,
0x2004, 0x2004, 0x2004, 0x2004, 0x2004, 0x2004, 0x2004, 0x2004,
0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004,
0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004,
0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004,
0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004,
0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804,
0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804,
0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804,
0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804,
0x0404, 0x0404, 0x0404, 0x0404, 0x0404, 0x0404, 0x0404, 0x0404,
0x0404, 0x0404, 0x0404, 0x0404, 0x0404, 0x0404, 0x0404, 0x0404,
0x0404, 0x0404, 0x0404, 0x0404, 0x0404, 0x0404, 0x0404, 0x0404,
0x0404, 0x0404, 0x0404, 0x0404, 0x0404, 0x0404, 0x0404, 0x0404,
0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03
};
public int getCodedBlockPattern(InputBitStream input) throws IOException {
int index = input.nextBits(9);
int value = coded_block_pattern[index] >> 0x8;
int length = coded_block_pattern[index] & 0xff;
input.getBits(length);
return value;
}
/* Decoding tables for dct_dc_size_luminance */
private static final short[] dct_dc_size_luminance = {
0x12, 0x12, 0x12, 0x12, 0x22, 0x22, 0x22, 0x22,
0x03, 0x03, 0x33, 0x33, 0x43, 0x43, 0x54, 0x00
};
private static final short[] dct_dc_size_luminance1 = {
0x65, 0x65, 0x65, 0x65, 0x76, 0x76, 0x87, 0x00
};
public int decodeDCTDCSizeLuminance(InputBitStream input) throws IOException {
int index = input.nextBits(7);
int value = dct_dc_size_luminance[index >> 3];
if (value == 0)
value = dct_dc_size_luminance1[index & 0x07];
input.getBits(value & 0xf);
return value >> 4;
}
/* Decoding tables for dct_dc_size_chrominance */
private static final short[] dct_dc_size_chrominance = {
0x02, 0x02, 0x02, 0x02, 0x12, 0x12, 0x12, 0x12,
0x22, 0x22, 0x22, 0x22, 0x33, 0x33, 0x44, 0x00
};
private static final short[] dct_dc_size_chrominance1 = {
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
0x66, 0x66, 0x66, 0x66, 0x77, 0x77, 0x88, 0x00
};
public int decodeDCTDCSizeChrominance(InputBitStream input) throws IOException {
int index = input.nextBits(8);
int value = dct_dc_size_chrominance[index >> 4];
if (value == 0)
value = dct_dc_size_chrominance1[index & 0xf];
input.getBits(value & 0xf);
return value >> 4;
}
/* Decoding tables for dct_coeff_first & dct_coeff_next
*
* This were originally 15 arrays. Now they are merged to form a single array,
* and using a scale to retrieve data from the correct array of coefficients.
*/
// Total number of entries 16 * 32 = 512
// First 32 entries are not used in fact
private static final byte[][] dct_coeff = {
// 0000 0000 0000 xxxx x
{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
// 0000 0000 0001 xxxx s
{1, 18, 17}, {1, -18, 17}, {1, 17, 17}, {1, -17, 17},
{1, 16, 17}, {1, -16, 17}, {1, 15, 17}, {1, -15, 17},
{6, 3, 17}, {6, -3, 17}, {16, 2, 17}, {16, -2, 17},
{15, 2, 17}, {15, -2, 17}, {14, 2, 17}, {14, -2, 17},
{13, 2, 17}, {13, -2, 17}, {12, 2, 17}, {12, -2, 17},
{11, 2, 17}, {11, -2, 17}, {31, 1, 17}, {31, -1, 17},
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -