package org.jcodec.codecs.h264;
import static org.jcodec.common.ArrayUtil.padLeft;
import static org.jcodec.common.ArrayUtil.toByteArrayShifted;
import static org.junit.Assert.assertArrayEquals;
import org.jcodec.codecs.h264.decode.Intra8x8PredictionBuilder;
import org.jcodec.common.tools.MathUtil;
import org.junit.Test;
import java.util.Arrays;
public class Intra8x8PredictionBuilderTest {
private static int[] testResidual = new int[64];
private static int[] emptyResidual = new int[64];
static {
for (int i = 0; i < 64; i++) {
testResidual[i] = (i << 2) - 128;
}
}
private byte[] addResidual(byte[] pred, int[] residual) {
byte[] result = new byte[pred.length];
for (int i = 0; i < pred.length; i++)
result[i] = (byte) MathUtil.clip(pred[i] + residual[i], -128, 127);
return result;
}
private byte[] inMB(byte[] is, int blkX, int blkY) {
byte[] result = new byte[256];
int off = (blkY << 4) + blkX;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++)
result[off + (i << 4) + j] = is[(i << 3) + j];
}
return result;
}
@Test
public void testDC() throws Exception {
byte[] pred = new byte[256];
byte[] top = toByteArrayShifted(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 64, 65, 66, 67, 68, 69, 70,
71);
byte[] left = toByteArrayShifted(16, 17, 18, 19, 20, 21, 22, 23);
byte[] topLeft = toByteArrayShifted(24);
byte[] expected = new byte[64];
Arrays.fill(expected, (byte) (13 - 128));
new Intra8x8PredictionBuilder().predictDC(emptyResidual, true, true, true, true, topLeft, left, top, 0, 0, 0,
pred);
assertArrayEquals(inMB(expected, 0, 0), pred);
for (int blkY = 0; blkY < 16; blkY += 8) {
for (int blkX = 0; blkX < 16; blkX += 8) {
Arrays.fill(pred, (byte) 0);
new Intra8x8PredictionBuilder().predictDC(testResidual, true, true, true, true,
padLeft(topLeft, blkY >> 2), padLeft(left, blkY), padLeft(top, blkX), 0, blkX, blkY, pred);
assertArrayEquals(inMB(addResidual(expected, testResidual), blkX, blkY), pred);
}
}
}
@Test
public void testVertical() throws Exception {
byte[] pred = new byte[256];
byte[] top = toByteArrayShifted(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 64, 65, 66, 67, 68, 69, 70,
71);
byte[] topLeft = toByteArrayShifted(24, 0, 0, 0);
byte[] expected = toByteArrayShifted(7, 2, 3, 4, 5, 6, 7, 8, 7, 2, 3, 4, 5, 6, 7, 8, 7, 2, 3, 4, 5, 6, 7, 8, 7,
2, 3, 4, 5, 6, 7, 8, 7, 2, 3, 4, 5, 6, 7, 8, 7, 2, 3, 4, 5, 6, 7, 8, 7, 2, 3, 4, 5, 6, 7, 8, 7, 2, 3,
4, 5, 6, 7, 8);
new Intra8x8PredictionBuilder().predictVertical(emptyResidual, true, true, topLeft, top, 0, 0, 0, pred);
assertArrayEquals(inMB(expected, 0, 0), pred);
for (int blkY = 0; blkY < 16; blkY += 8) {
for (int blkX = 0; blkX < 16; blkX += 8) {
Arrays.fill(pred, (byte) 0);
new Intra8x8PredictionBuilder().predictVertical(testResidual, true, true, padLeft(topLeft, blkY >> 2),
padLeft(top, blkX), 0, blkX, blkY, pred);
assertArrayEquals(inMB(addResidual(expected, testResidual), blkX, blkY), pred);
}
}
}
@Test
public void testHorizontal() throws Exception {
byte[] pred = new byte[256];
byte[] left = toByteArrayShifted(16, 17, 18, 19, 20, 21, 22, 23);
byte[] topLeft = toByteArrayShifted(24, 0, 0, 0);
byte[] expected = toByteArrayShifted(18, 18, 18, 18, 18, 18, 18, 18, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18,
18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21,
21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23);
new Intra8x8PredictionBuilder().predictHorizontal(emptyResidual, true, topLeft, left, 0, 0, 0, pred);
assertArrayEquals(inMB(expected, 0, 0), pred);
for (int blkY = 0; blkY < 16; blkY += 8) {
for (int blkX = 0; blkX < 16; blkX += 8) {
Arrays.fill(pred, (byte) 0);
new Intra8x8PredictionBuilder().predictHorizontal(testResidual, true, padLeft(topLeft, blkY >> 2),
padLeft(left, blkY), 0, blkX, blkY, pred);
assertArrayEquals(inMB(addResidual(expected, testResidual), blkX, blkY), pred);
}
}
}
@Test
public void testDiagonalDownLeft() throws Exception {
byte[] pred = new byte[256];
byte[] top = toByteArrayShifted(10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160);
byte[] topLeft = toByteArrayShifted(170, 180, 190, 200);
byte[] expected = toByteArrayShifted(31, 30, 40, 50, 60, 70, 80, 90, 30, 40, 50, 60, 70, 80, 90, 100, 40, 50,
60, 70, 80, 90, 100, 110, 50, 60, 70, 80, 90, 100, 110, 120, 60, 70, 80, 90, 100, 110, 120, 130, 70,
80, 90, 100, 110, 120, 130, 140, 80, 90, 100, 110, 120, 130, 140, 150, 90, 100, 110, 120, 130, 140,
150, 156);
new Intra8x8PredictionBuilder().predictDiagonalDownLeft(emptyResidual, true, true, true, topLeft, top, 0, 0, 0,
pred);
assertArrayEquals(inMB(expected, 0, 0), pred);
for (int blkY = 0; blkY < 16; blkY += 8) {
for (int blkX = 0; blkX < 16; blkX += 8) {
Arrays.fill(pred, (byte) 0);
new Intra8x8PredictionBuilder().predictDiagonalDownLeft(testResidual, true, true, true,
padLeft(topLeft, blkY >> 2), padLeft(top, blkX), 0, blkX, blkY, pred);
assertArrayEquals(inMB(addResidual(expected, testResidual), blkX, blkY), pred);
}
}
}
@Test
public void testDiagonalDownRight() throws Exception {
byte[] pred = new byte[256];
byte[] top = toByteArrayShifted(10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160);
byte[] left = toByteArrayShifted(210, 215, 220, 225, 230, 235, 240, 245);
byte[] tl = toByteArrayShifted(170, 180, 190, 200);
byte[] expected = toByteArrayShifted(134, 67, 31, 30, 40, 50, 60, 70, 189, 134, 67, 31, 30, 40, 50, 60, 213,
189, 134, 67, 31, 30, 40, 50, 220, 213, 189, 134, 67, 31, 30, 40, 225, 220, 213, 189, 134, 67, 31, 30,
230, 225, 220, 213, 189, 134, 67, 31, 235, 230, 225, 220, 213, 189, 134, 67, 240, 235, 230, 225, 220,
213, 189, 134);
new Intra8x8PredictionBuilder().predictDiagonalDownRight(emptyResidual, true, tl, left, top, 0, 0, 0, pred);
assertArrayEquals(inMB(expected, 0, 0), pred);
for (int blkY = 0; blkY < 16; blkY += 8) {
for (int blkX = 0; blkX < 16; blkX += 8) {
Arrays.fill(pred, (byte) 0);
new Intra8x8PredictionBuilder().predictDiagonalDownRight(testResidual, true, padLeft(tl, blkY >> 2),
padLeft(left, blkY), padLeft(top, blkX), 0, blkX, blkY, pred);
assertArrayEquals(inMB(addResidual(expected, testResidual), blkX, blkY), pred);
}
}
}
@Test
public void testVerticalRight() throws Exception {
byte[] pred = new byte[256];
byte[] top = toByteArrayShifted(10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160);
byte[] left = toByteArrayShifted(210, 215, 220, 225, 230, 235, 240, 245);
byte[] tl = toByteArrayShifted(170, 180, 190, 200);
byte[] expected = toByteArrayShifted(97, 37, 25, 35, 45, 55, 65, 75, 134, 67, 31, 30, 40, 50, 60, 70, 189, 97,
37, 25, 35, 45, 55, 65, 213, 134, 67, 31, 30, 40, 50, 60, 220, 189, 97, 37, 25, 35, 45, 55, 225, 213,
134, 67, 31, 30, 40, 50, 230, 220, 189, 97, 37, 25, 35, 45, 235, 225, 213, 134, 67, 31, 30, 40);
new Intra8x8PredictionBuilder().predictVerticalRight(emptyResidual, true, tl, left, top, 0, 0, 0, pred);
assertArrayEquals(inMB(expected, 0, 0), pred);
for (int blkY = 0; blkY < 16; blkY += 8) {
for (int blkX = 0; blkX < 16; blkX += 8) {
Arrays.fill(pred, (byte) 0);
new Intra8x8PredictionBuilder().predictVerticalRight(testResidual, true, padLeft(tl, blkY >> 2),
padLeft(left, blkY), padLeft(top, blkX), 0, blkX, blkY, pred);
assertArrayEquals(inMB(addResidual(expected, testResidual), blkX, blkY), pred);
}
}
}
@Test
public void testHorizontalDown() throws Exception {
byte[] pred = new byte[256];
byte[] top = toByteArrayShifted(10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160);
byte[] left = toByteArrayShifted(210, 215, 220, 225, 230, 235, 240, 245);
byte[] tl = toByteArrayShifted(170, 180, 190, 200);
byte[] expected = toByteArrayShifted(171, 134, 67, 31, 30, 40, 50, 60, 208, 189, 171, 134, 67, 31, 30, 40, 218,
213, 208, 189, 171, 134, 67, 31, 223, 220, 218, 213, 208, 189, 171, 134, 228, 225, 223, 220, 218, 213,
208, 189, 233, 230, 228, 225, 223, 220, 218, 213, 238, 235, 233, 230, 228, 225, 223, 220, 242, 240,
238, 235, 233, 230, 228, 225);
new Intra8x8PredictionBuilder().predictHorizontalDown(emptyResidual, true, tl, left, top, 0, 0, 0, pred);
assertArrayEquals(inMB(expected, 0, 0), pred);
for (int blkY = 0; blkY < 16; blkY += 8) {
for (int blkX = 0; blkX < 16; blkX += 8) {
Arrays.fill(pred, (byte) 0);
new Intra8x8PredictionBuilder().predictHorizontalDown(testResidual, true, padLeft(tl, blkY >> 2),
padLeft(left, blkY), padLeft(top, blkX), 0, blkX, blkY, pred);
assertArrayEquals(inMB(addResidual(expected, testResidual), blkX, blkY), pred);
}
}
}
@Test
public void testVerticalLeft() throws Exception {
byte[] pred = new byte[256];
byte[] top = toByteArrayShifted(10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160);
byte[] tl = toByteArrayShifted(170, 180, 190, 200);
byte[] expected = toByteArrayShifted(37, 25, 35, 45, 55, 65, 75, 85, 31, 30, 40, 50, 60, 70, 80, 90, 25, 35,
45, 55, 65, 75, 85, 95, 30, 40, 50, 60, 70, 80, 90, 100, 35, 45, 55, 65, 75, 85, 95, 105, 40, 50, 60,
70, 80, 90, 100, 110, 45, 55, 65, 75, 85, 95, 105, 115, 50, 60, 70, 80, 90, 100, 110, 120);
new Intra8x8PredictionBuilder().predictVerticalLeft(emptyResidual, true, true, tl, top, 0, 0, 0, pred);
assertArrayEquals(inMB(expected, 0, 0), pred);
for (int blkY = 0; blkY < 16; blkY += 8) {
for (int blkX = 0; blkX < 16; blkX += 8) {
Arrays.fill(pred, (byte) 0);
new Intra8x8PredictionBuilder().predictVerticalLeft(testResidual, true, true, padLeft(tl, blkY >> 2),
padLeft(top, blkX), 0, blkX, blkY, pred);
assertArrayEquals(inMB(addResidual(expected, testResidual), blkX, blkY), pred);
}
}
}
@Test
public void testHorizontalUp() throws Exception {
byte[] pred = new byte[256];
byte[] left = toByteArrayShifted(210, 215, 220, 225, 230, 235, 240, 245);
byte[] tl = toByteArrayShifted(170, 180, 190, 200);
byte[] expected = toByteArrayShifted(208, 213, 218, 220, 223, 225, 228, 230, 218, 220, 223, 225, 228, 230, 233,
235, 223, 225, 228, 230, 233, 235, 238, 240, 228, 230, 233, 235, 238, 240, 242, 243, 233, 235, 238,
240, 242, 243, 244, 244, 238, 240, 242, 243, 244, 244, 244, 244, 242, 243, 244, 244, 244, 244, 244,
244, 244, 244, 244, 244, 244, 244, 244, 244);
new Intra8x8PredictionBuilder().predictHorizontalUp(emptyResidual, true, tl, left, 0, 0, 0, pred);
assertArrayEquals(inMB(expected, 0, 0), pred);
for (int blkY = 0; blkY < 16; blkY += 8) {
for (int blkX = 0; blkX < 16; blkX += 8) {
Arrays.fill(pred, (byte) 0);
new Intra8x8PredictionBuilder().predictHorizontalUp(testResidual, true, padLeft(tl, blkY >> 2),
padLeft(left, blkY), 0, blkX, blkY, pred);
assertArrayEquals(inMB(addResidual(expected, testResidual), blkX, blkY), pred);
}
}
}
}