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.Intra4x4PredictionBuilder; import org.jcodec.common.tools.MathUtil; import org.junit.Test; import java.util.Arrays; public class Intra4x4PredictionBuilderTest { private static int[] emptyResidual = new int[16]; private static int[] testResidual = new int[16]; static { for (int i = 0; i < 16; i++) { testResidual[i] = 16 * i - 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[] idxMap = { 0, 1, 2, 3, 16, 17, 18, 19, 32, 33, 34, 35, 48, 49, 50, 51 }; int off = (blkY << 4) + blkX; for (int i = 0; i < 16; i++) { result[idxMap[i] + off] = is[i]; } return result; } @Test public void testDC() throws Exception { byte[] pred = new byte[256]; byte[] top = toByteArrayShifted(1, 2, 3, 4, 5, 6, 7, 8); byte[] left = toByteArrayShifted(9, 10, 11, 12); Intra4x4PredictionBuilder.predictDC(emptyResidual, true, true, left, top, 0, 0, 0, pred); assertArrayEquals(inMB(toByteArrayShifted(7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7), 0, 0), pred); for (int blkY = 0; blkY < 16; blkY += 4) { for (int blkX = 0; blkX < 16; blkX += 4) { Arrays.fill(pred, (byte) 0); Intra4x4PredictionBuilder.predictDC(testResidual, true, true, padLeft(left, blkY), padLeft(top, blkX), 0, blkX, blkY, pred); assertArrayEquals( "@[" + blkX + ", " + blkY + "]", inMB(addResidual(toByteArrayShifted(7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7), 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); Intra4x4PredictionBuilder.predictVertical(emptyResidual, true, top, 0, 0, 0, pred); assertArrayEquals(inMB(toByteArrayShifted(1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4), 0, 0), pred); for (int blkY = 0; blkY < 16; blkY += 4) { for (int blkX = 0; blkX < 16; blkX += 4) { Arrays.fill(pred, (byte) 0); Intra4x4PredictionBuilder.predictVertical(testResidual, true, padLeft(top, blkX), 0, blkX, blkY, pred); assertArrayEquals( "@[" + blkX + ", " + blkY + "]", inMB(addResidual(toByteArrayShifted(1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4), testResidual), blkX, blkY), pred); } } } @Test public void testHorizontal() throws Exception { byte[] pred = new byte[256]; // byte[] top = toByteArrayShifted( 1, 2, 3, 4, 5, 6, 7, 8 }; byte[] left = toByteArrayShifted(9, 10, 11, 12); Intra4x4PredictionBuilder.predictHorizontal(emptyResidual, true, left, 0, 0, 0, pred); assertArrayEquals(inMB(toByteArrayShifted(9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12), 0, 0), pred); for (int blkY = 0; blkY < 16; blkY += 4) { for (int blkX = 0; blkX < 16; blkX += 4) { Arrays.fill(pred, (byte) 0); Intra4x4PredictionBuilder.predictHorizontal(testResidual, true, padLeft(left, blkY), 0, blkX, blkY, pred); assertArrayEquals( "@[" + blkX + ", " + blkY + "]", inMB(addResidual( toByteArrayShifted(9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12), testResidual), blkX, blkY), pred); } } } @Test public void testDiagonalDownLeft() throws Exception { byte[] pred = new byte[256]; byte[] top = toByteArrayShifted(209, 212, 218, 222, 216, 219, 225, 229); Intra4x4PredictionBuilder.predictDiagonalDownLeft(emptyResidual, true, true, top, 0, 0, 0, pred); assertArrayEquals( inMB(toByteArrayShifted(213, 218, 220, 218, 218, 220, 218, 220, 220, 218, 220, 225, 218, 220, 225, 228), 0, 0), pred); for (int blkY = 0; blkY < 16; blkY += 4) { for (int blkX = 0; blkX < 16; blkX += 4) { Arrays.fill(pred, (byte) 0); Intra4x4PredictionBuilder.predictDiagonalDownLeft(testResidual, true, true, padLeft(top, blkX), 0, blkX, blkY, pred); assertArrayEquals( "@[" + blkX + ", " + blkY + "]", inMB(addResidual( toByteArrayShifted(213, 218, 220, 218, 218, 220, 218, 220, 220, 218, 220, 225, 218, 220, 225, 228), testResidual), blkX, blkY), pred); } } } @Test public void testDiagonalDownRight() throws Exception { byte[] pred = new byte[256]; byte[] top = toByteArrayShifted(183, 196, 170, 131, 0, 0, 0, 0); byte[] left = toByteArrayShifted(207, 207, 207, 207); byte[] tl = toByteArrayShifted(196, 0, 0, 0); Intra4x4PredictionBuilder.predictDiagonalDownRight(emptyResidual, true, true, left, top, tl, 0, 0, 0, pred); assertArrayEquals( inMB(toByteArrayShifted(196, 190, 186, 167, 204, 196, 190, 186, 207, 204, 196, 190, 207, 207, 204, 196), 0, 0), pred); for (int blkY = 0; blkY < 16; blkY += 4) { for (int blkX = 0; blkX < 16; blkX += 4) { Arrays.fill(pred, (byte) 0); Intra4x4PredictionBuilder.predictDiagonalDownRight(testResidual, true, true, padLeft(left, blkY), padLeft(top, blkX), padLeft(tl, blkY >> 2), 0, blkX, blkY, pred); assertArrayEquals( "@[" + blkX + ", " + blkY + "]", inMB(addResidual( toByteArrayShifted(196, 190, 186, 167, 204, 196, 190, 186, 207, 204, 196, 190, 207, 207, 204, 196), testResidual), blkX, blkY), pred); } } } @Test public void testDiagonalDownRight1() throws Exception { byte[] pred = new byte[256]; byte[] top = toByteArrayShifted(236, 236, 236, 236, 0, 0, 0, 0); byte[] left = toByteArrayShifted(233, 233, 233, 233); byte[] tl = toByteArrayShifted(226, 0, 0, 0); Intra4x4PredictionBuilder.predictDiagonalDownRight(emptyResidual, true, true, left, top, tl, 0, 0, 0, pred); assertArrayEquals( inMB(toByteArrayShifted(230, 234, 236, 236, 231, 230, 234, 236, 233, 231, 230, 234, 233, 233, 231, 230), 0, 0), pred); for (int blkY = 0; blkY < 16; blkY += 4) { for (int blkX = 0; blkX < 16; blkX += 4) { Arrays.fill(pred, (byte) 0); Intra4x4PredictionBuilder.predictDiagonalDownRight(testResidual, true, true, padLeft(left, blkY), padLeft(top, blkX), padLeft(tl, blkY >> 2), 0, blkX, blkY, pred); assertArrayEquals( "@[" + blkX + ", " + blkY + "]", inMB(addResidual( toByteArrayShifted(230, 234, 236, 236, 231, 230, 234, 236, 233, 231, 230, 234, 233, 233, 231, 230), testResidual), blkX, blkY), pred); } } } @Test public void testVerticalRight() throws Exception { byte[] pred = new byte[256]; byte[] top = toByteArrayShifted(207, 201, 197, 175, 0, 0, 0, 0); byte[] left = toByteArrayShifted(208, 176, 129, 122); byte[] tl = toByteArrayShifted(206, 0, 0, 0); Intra4x4PredictionBuilder.predictVerticalRight(emptyResidual, true, true, left, top, tl, 0, 0, 0, pred); assertArrayEquals( inMB(toByteArrayShifted(207, 204, 199, 186, 207, 205, 202, 193, 200, 207, 204, 199, 172, 207, 205, 202), 0, 0), pred); for (int blkY = 0; blkY < 16; blkY += 4) { for (int blkX = 0; blkX < 16; blkX += 4) { Arrays.fill(pred, (byte) 0); Intra4x4PredictionBuilder.predictVerticalRight(testResidual, true, true, padLeft(left, blkY), padLeft(top, blkX), padLeft(tl, blkY >> 2), 0, blkX, blkY, pred); assertArrayEquals( "@[" + blkX + ", " + blkY + "]", inMB(addResidual( toByteArrayShifted(207, 204, 199, 186, 207, 205, 202, 193, 200, 207, 204, 199, 172, 207, 205, 202), testResidual), blkX, blkY), pred); } } } @Test public void testHorizontalDown() throws Exception { byte[] pred = new byte[256]; byte[] top = toByteArrayShifted(209, 157, 114, 118); byte[] left = toByteArrayShifted(197, 198, 202, 205); byte[] tl = toByteArrayShifted(204, 0, 0, 0); Intra4x4PredictionBuilder.predictHorizontalDown(emptyResidual, true, true, left, top, tl, 0, 0, 0, pred); assertArrayEquals( inMB(toByteArrayShifted(201, 204, 195, 159, 198, 199, 201, 204, 200, 199, 198, 199, 204, 202, 200, 199), 0, 0), pred); for (int blkY = 0; blkY < 16; blkY += 4) { for (int blkX = 0; blkX < 16; blkX += 4) { Arrays.fill(pred, (byte) 0); Intra4x4PredictionBuilder.predictHorizontalDown(testResidual, true, true, padLeft(left, blkY), padLeft(top, blkX), padLeft(tl, blkY >> 2), 0, blkX, blkY, pred); assertArrayEquals( "@[" + blkX + ", " + blkY + "]", inMB(addResidual( toByteArrayShifted(201, 204, 195, 159, 198, 199, 201, 204, 200, 199, 198, 199, 204, 202, 200, 199), testResidual), blkX, blkY), pred); } } } @Test public void testVerticalLeft() throws Exception { byte[] pred = new byte[256]; byte[] top = toByteArrayShifted(215, 201, 173, 159, 137, 141, 150, 155); Intra4x4PredictionBuilder.predictVerticalLeft(emptyResidual, true, true, top, 0, 0, 0, pred); assertArrayEquals( inMB(toByteArrayShifted(208, 187, 166, 148, 198, 177, 157, 144, 187, 166, 148, 139, 177, 157, 144, 142), 0, 0), pred); for (int blkY = 0; blkY < 16; blkY += 4) { for (int blkX = 0; blkX < 16; blkX += 4) { Arrays.fill(pred, (byte) 0); Intra4x4PredictionBuilder.predictVerticalLeft(testResidual, true, true, padLeft(top, blkX), 0, blkX, blkY, pred); assertArrayEquals( "@[" + blkX + ", " + blkY + "]", inMB(addResidual( toByteArrayShifted(208, 187, 166, 148, 198, 177, 157, 144, 187, 166, 148, 139, 177, 157, 144, 142), testResidual), blkX, blkY), pred); } } } @Test public void testHorizontalUp() throws Exception { byte[] pred = new byte[256]; byte[] left = toByteArrayShifted(175, 180, 216, 221); Intra4x4PredictionBuilder.predictHorizontalUp(emptyResidual, true, left, 0, 0, 0, pred); assertArrayEquals( inMB(toByteArrayShifted(178, 188, 198, 208, 198, 208, 219, 220, 219, 220, 221, 221, 221, 221, 221, 221), 0, 0), pred); for (int blkY = 0; blkY < 16; blkY += 4) { for (int blkX = 0; blkX < 16; blkX += 4) { Arrays.fill(pred, (byte) 0); Intra4x4PredictionBuilder.predictHorizontalUp(testResidual, true, padLeft(left, blkY), 0, blkX, blkY, pred); assertArrayEquals( "@[" + blkX + ", " + blkY + "]", inMB(addResidual( toByteArrayShifted(178, 188, 198, 208, 198, 208, 219, 220, 219, 220, 221, 221, 221, 221, 221, 221), testResidual), blkX, blkY), pred); } } } }