package org.jcodec.codecs.h264;
import static org.junit.Assert.assertArrayEquals;
import org.jcodec.codecs.common.biari.MDecoder;
import org.jcodec.codecs.common.biari.MEncoder;
import org.jcodec.codecs.h264.decode.CoeffTransformer;
import org.jcodec.codecs.h264.io.CABAC;
import org.jcodec.codecs.h264.io.CAVLC;
import org.jcodec.codecs.h264.io.model.PictureParameterSet;
import org.jcodec.codecs.h264.io.model.SeqParameterSet;
import org.jcodec.codecs.util.BinUtil;
import org.jcodec.common.io.BitReader;
import org.jcodec.common.io.VLC;
import org.junit.Test;
import java.io.IOException;
import java.nio.ByteBuffer;
public class ResidualBlockTest {
@Test
public void testLuma1CAVLC() throws Exception {
// 0000100 5,3
String code = "0000100 01110010111101101";
int[] coeffs = { 0, 3, 0, 1, -1, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
testResidualCAVLC(code, H264Const.CoeffToken[0], coeffs);
}
@Test
public void testLuma2CAVLC() throws Exception {
// 0000000110 5,1
String code = "0000000110 10001001000010111001100";
int[] coeffs = { -2, 4, 3, -3, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
testResidualCAVLC(code, H264Const.CoeffToken[0], coeffs);
}
@Test
public void testLuma3CAVLC() throws Exception {
// 00011 3,3
String code = "00011 10001110010";
int[] coeffs = { 0, 0, 0, 1, 0, 1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0 };
testResidualCAVLC(code, H264Const.CoeffToken[0], coeffs);
}
@Test
public void testChromaAC3CAVLC() throws Exception {
// 000000100 7,3
String code = "000000100 000 1 010 0011 10 101 00";
int[] coeffs = { 1, -3, 2, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 };
testResidualCAVLC(code, H264Const.CoeffToken[0], coeffs);
}
private int[] zigzag(int[] src, int[] tab) {
int[] result = new int[src.length];
for (int i = 0; i < src.length; i++)
result[tab[i]] = src[i];
return result;
}
private void testResidualCAVLC(String code, VLC coeffTokenTab, int[] expected) throws IOException {
BitReader reader = BitReader.createBitReader(ByteBuffer.wrap(BinUtil.binaryStringToBytes(code)));
CAVLC cavlc = new CAVLC(new SeqParameterSet(), new PictureParameterSet(), 4, 4);
int[] actual = new int[expected.length];
cavlc.readCoeffs(reader, coeffTokenTab, H264Const.totalZeros16, actual, 0, 16, CoeffTransformer.zigzag4x4);
assertArrayEquals(zigzag(expected, CoeffTransformer.zigzag4x4), actual);
}
@Test
public void testLumaCABAC() {
int bits[] = { 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1,
1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1 };
int m[] = { 134, 195, 135, 196, 136, 197, 137, 198, 138, 199, 139, 200, 140, 201, 141, 202, 142, 203, 143, 144,
145, 206, 146, 207, 248, -1, 249, -1, 250, -1, 251, -1, 251, 252, -1, 247, 253, 253, -1, 247, 254, -1,
247, -1, 247, -1, 247, 255, 255, 255, -1, 247, 256, -1 };
int coeffs[] = { -2, -1, 1, 0, 4, 2, -1, 0, -3, -1, 1, 0, 2, 1, 0, 0 };
int[] actual = new int[16];
MDecoder decoder = new MockMDecoder(bits, m);
new CABAC(1).readCoeffs(decoder, CABAC.BlockType.LUMA_16, actual, 0, 16, new int[] { 0, 4, 1, 2, 5, 8, 12, 9,
6, 3, 7, 10, 13, 14, 11, 15 }, H264Const.identityMapping16, H264Const.identityMapping16);
assertArrayEquals(coeffs, actual);
MEncoder encoder = new MockMEncoder(bits, m);
new CABAC(1).writeCoeffs(encoder, CABAC.BlockType.LUMA_16, actual, 0, 16, new int[] { 0, 4, 1, 2, 5, 8, 12, 9,
6, 3, 7, 10, 13, 14, 11, 15 });
}
@Test
public void testChromaDCCABAC() {
int bits[] = { 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1 };
int m[] = { 149, 210, 150, 211, 151, 212, 258, 262, 262, -1, 257, 263, 263, 263, 263, 263, 263, -1, 257, 264,
-1, 257, 265, 265, 265, 265, -1 };
int coeffs[] = { -5, 2, 7, -3 };
int[] actual = new int[4];
MDecoder decoder = new MockMDecoder(bits, m);
new CABAC(1).readCoeffs(decoder, CABAC.BlockType.CHROMA_DC, actual, 0, 4, new int[] { 0, 1, 2, 3 }, H264Const.identityMapping16, H264Const.identityMapping16);
assertArrayEquals(coeffs, actual);
MEncoder encoder = new MockMEncoder(bits, m);
new CABAC(1).writeCoeffs(encoder, CABAC.BlockType.CHROMA_DC, actual, 0, 4, new int[] { 0, 1, 2, 3 });
}
@Test
public void testAC15CABAC() {
int bits[] = { 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1,
0, 0 };
int m[] = { 152, 213, 153, 154, 155, 216, 156, 157, 158, 219, 159, 220, 160, 161, 162, 223, 163, 224, 164, 225,
267, -1, 268, -1, 269, -1, 270, -1, 270, -1, 270, -1, 270, -1 };
int coeffs[] = { 0, 0, 0, 0, 1, -1, 1, 0, 0, -1, 1, 0, 0, -1, -1, 0 };
int[] actual = new int[16];
MDecoder decoder = new MockMDecoder(bits, m);
new CABAC(1).readCoeffs(decoder, CABAC.BlockType.CHROMA_AC, actual, 1, 15, new int[] { 0, 4, 1, 2, 5, 8, 12, 9,
6, 3, 7, 10, 13, 14, 11, 15 }, H264Const.identityMapping16, H264Const.identityMapping16);
assertArrayEquals(coeffs, actual);
MEncoder encoder = new MockMEncoder(bits, m);
new CABAC(1).writeCoeffs(encoder, CABAC.BlockType.CHROMA_AC, actual, 1, 15, new int[] { 0, 4, 1, 2, 5, 8, 12,
9, 6, 3, 7, 10, 13, 14, 11, 15 });
}
@Test
public void testLumaDCCabac() {
int[] coeffs = new int[] { 46, -10, -5, -27, -18, -4, 7, 9, 19, -3, -37, 14, -17, -15, -43, -28 };
int bits[] = { 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1,
1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
int m[] = { 105, 166, 106, 167, 107, 168, 108, 169, 109, 170, 110, 171, 111, 172, 112, 173, 113, 174, 114, 175,
115, 176, 116, 177, 117, 178, 118, 179, 119, 180, 228, 232, 232, 232, 232, 232, 232, 232, 232, 232,
232, 232, 232, 232, -1, -1, -1, -1, -1, -1, -1, -1, 227, 233, 233, 233, 233, 233, 233, 233, 233, 233,
233, 233, 233, 233, -1, 227, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, 227, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235,
-1, -1, 227, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, 227, 236, 236, 236, 236, 236, 236, 236, 236, -1, 227, 236, 236, 236, 236, 236, 236,
236, 236, 236, 236, 236, 236, 236, -1, -1, -1, -1, -1, -1, -1, -1, 227, 236, 236, 236, 236, 236, 236,
-1, 227, 236, 236, -1, 227, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, -1, -1,
-1, -1, 227, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, -1, -1, -1, -1, -1, -1,
227, 236, 236, 236, -1, 227, 236, 236, 236, 236, -1, 227, 236, 236, 236, 236, 236, 236, 236, 236, 236,
-1, 227, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, -1, -1, -1, -1, -1, -1, 227,
236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1 };
int[] actual = new int[16];
MDecoder decoder = new MockMDecoder(bits, m);
new CABAC(1).readCoeffs(decoder, CABAC.BlockType.LUMA_16_DC, actual, 0, 16, new int[] { 0, 4, 1, 2, 5, 8, 12,
9, 6, 3, 7, 10, 13, 14, 11, 15 }, H264Const.identityMapping16, H264Const.identityMapping16);
assertArrayEquals(coeffs, actual);
MEncoder encoder = new MockMEncoder(bits, m);
new CABAC(1).writeCoeffs(encoder, CABAC.BlockType.LUMA_16_DC, actual, 0, 16, new int[] { 0, 4, 1, 2, 5, 8, 12,
9, 6, 3, 7, 10, 13, 14, 11, 15 });
}
}