package org.jcodec.codecs.h264.decode; import static org.jcodec.common.tools.MathUtil.clip; /** * This class is part of JCodec ( www.jcodec.org ) This software is distributed * under FreeBSD License * * Builds intra prediction for intra 4x4 coded macroblocks * * @author Jay Codec * */ public class Intra4x4PredictionBuilder { public static void predictWithMode(int mode, int[] residual, boolean leftAvailable, boolean topAvailable, boolean topRightAvailable, int[] leftRow, int[] topLine, int topLeft[], int mbOffX, int blkX, int blkY) { switch (mode) { case 0: predictVertical(residual, topAvailable, topLine, mbOffX, blkX, blkY); break; case 1: predictHorizontal(residual, leftAvailable, leftRow, mbOffX, blkX, blkY); break; case 2: predictDC(residual, leftAvailable, topAvailable, leftRow, topLine, mbOffX, blkX, blkY); break; case 3: predictDiagonalDownLeft(residual, topAvailable, topRightAvailable, topLine, mbOffX, blkX, blkY); break; case 4: predictDiagonalDownRight(residual, leftAvailable, topAvailable, leftRow, topLine, topLeft, mbOffX, blkX, blkY); break; case 5: predictVerticalRight(residual, leftAvailable, topAvailable, leftRow, topLine, topLeft, mbOffX, blkX, blkY); break; case 6: predictHorizontalDown(residual, leftAvailable, topAvailable, leftRow, topLine, topLeft, mbOffX, blkX, blkY); break; case 7: predictVerticalLeft(residual, topAvailable, topRightAvailable, topLine, mbOffX, blkX, blkY); break; case 8: predictHorizontalUp(residual, leftAvailable, leftRow, mbOffX, blkX, blkY); break; } int oo1 = mbOffX + blkX; int off1 = (blkY << 4) + blkX + 3; topLeft[blkY >> 2] = topLine[oo1 + 3]; leftRow[blkY] = residual[off1]; leftRow[blkY + 1] = residual[off1 + 16]; leftRow[blkY + 2] = residual[off1 + 32]; leftRow[blkY + 3] = residual[off1 + 48]; int off2 = (blkY << 4) + blkX + 48; topLine[oo1] = residual[off2]; topLine[oo1 + 1] = residual[off2 + 1]; topLine[oo1 + 2] = residual[off2 + 2]; topLine[oo1 + 3] = residual[off2 + 3]; } public static void predictVertical(int[] residual, boolean topAvailable, int[] topLine, int mbOffX, int blkX, int blkY) { int off = (blkY << 4) + blkX; int toff = mbOffX + blkX; for (int j = 0; j < 4; j++) { residual[off] = clip(residual[off] + topLine[toff], 0, 255); residual[off + 1] = clip(residual[off + 1] + topLine[toff + 1], 0, 255); residual[off + 2] = clip(residual[off + 2] + topLine[toff + 2], 0, 255); residual[off + 3] = clip(residual[off + 3] + topLine[toff + 3], 0, 255); off += 16; } } public static void predictHorizontal(int[] residual, boolean leftAvailable, int[] leftRow, int mbOffX, int blkX, int blkY) { int off = (blkY << 4) + blkX; for (int j = 0; j < 4; j++) { int l = leftRow[blkY + j]; residual[off] = clip(residual[off] + l, 0, 255); residual[off + 1] = clip(residual[off + 1] + l, 0, 255); residual[off + 2] = clip(residual[off + 2] + l, 0, 255); residual[off + 3] = clip(residual[off + 3] + l, 0, 255); off += 16; } } public static void predictDC(int[] residual, boolean leftAvailable, boolean topAvailable, int[] leftRow, int[] topLine, int mbOffX, int blkX, int blkY) { int val; if (leftAvailable && topAvailable) { val = (leftRow[blkY] + leftRow[blkY + 1] + leftRow[blkY + 2] + leftRow[blkY + 3] + topLine[mbOffX + blkX] + topLine[mbOffX + blkX + 1] + topLine[mbOffX + blkX + 2] + topLine[mbOffX + blkX + 3] + 4) >> 3; } else if (leftAvailable) { val = (leftRow[blkY] + leftRow[blkY + 1] + leftRow[blkY + 2] + leftRow[blkY + 3] + 2) >> 2; } else if (topAvailable) { val = (topLine[mbOffX + blkX] + topLine[mbOffX + blkX + 1] + topLine[mbOffX + blkX + 2] + topLine[mbOffX + blkX + 3] + 2) >> 2; } else { val = 128; } int off = (blkY << 4) + blkX; for (int j = 0; j < 4; j++) { residual[off] = clip(residual[off] + val, 0, 255); residual[off + 1] = clip(residual[off + 1] + val, 0, 255); residual[off + 2] = clip(residual[off + 2] + val, 0, 255); residual[off + 3] = clip(residual[off + 3] + val, 0, 255); off += 16; } } public static void predictDiagonalDownLeft(int[] residual, boolean topAvailable, boolean topRightAvailable, int[] topLine, int mbOffX, int blkX, int blkY) { int to = mbOffX + blkX; int tr0 = topLine[to+3], tr1 = topLine[to+3], tr2 = topLine[to+3], tr3 = topLine[to+3]; if(topRightAvailable) { tr0 = topLine[to+4]; tr1 = topLine[to+5]; tr2 = topLine[to+6]; tr3 = topLine[to+7]; } int c0 = ((topLine[to] + topLine[to+2] + 2*(topLine[to+1]) + 2) >> 2); int c1 = ((topLine[to+1] + topLine[to+3] + 2*(topLine[to+2]) + 2) >> 2); int c2 = ((topLine[to+2] + tr0 + 2*(topLine[to+3]) + 2) >> 2); int c3 = ((topLine[to+3] + tr1 + 2*(tr0) + 2) >> 2); int c4 = ((tr0 + tr2 + 2*(tr1) + 2) >> 2); int c5 = ((tr1 + tr3 + 2*(tr2) + 2) >> 2); int c6 = ((tr2 + 3*(tr3) + 2) >> 2); int off = (blkY << 4) + blkX; residual[off] = clip(residual[off] + c0, 0, 255); residual[off+1] = clip(residual[off+1] + c1, 0, 255); residual[off+2] = clip(residual[off+2] + c2, 0, 255); residual[off+3] = clip(residual[off+3] + c3, 0, 255); residual[off+16] = clip(residual[off+16] + c1, 0, 255); residual[off+17] = clip(residual[off+17] + c2, 0, 255); residual[off+18] = clip(residual[off+18] + c3, 0, 255); residual[off+19] = clip(residual[off+19] + c4, 0, 255); residual[off+32] = clip(residual[off+32] + c2, 0, 255); residual[off+33] = clip(residual[off+33] + c3, 0, 255); residual[off+34] = clip(residual[off+34] + c4, 0, 255); residual[off+35] = clip(residual[off+35] + c5, 0, 255); residual[off+48] = clip(residual[off+48] + c3, 0, 255); residual[off+49] = clip(residual[off+49] + c4, 0, 255); residual[off+50] = clip(residual[off+50] + c5, 0, 255); residual[off+51] = clip(residual[off+51] + c6, 0, 255); } public static void predictDiagonalDownRight(int[] residual, boolean leftAvailable, boolean topAvailable, int[] leftRow, int[] topLine, int[] topLeft, int mbOffX, int blkX, int blkY) { int off = (blkY << 4) + blkX; for (int y = 0; y < 4; y++) { for (int x = 0; x < 4; x++) { if (x > y) { int t1; if (x - y - 2 == -1) t1 = topLeft[blkY >> 2]; else t1 = topLine[mbOffX + blkX + x - y - 2]; int t2; if (x - y - 1 == -1) t2 = topLeft[blkY >> 2]; else t2 = topLine[mbOffX + blkX + x - y - 1]; int t3; if (x - y == -1) t3 = topLeft[blkY >> 2]; else t3 = topLine[mbOffX + blkX + x - y]; residual[off + x] = clip(residual[off + x] + ((t1 + 2 * t2 + t3 + 2) >> 2), 0, 255); } else if (x < y) { int l1; if (y - x - 2 == -1) l1 = topLeft[blkY >> 2]; else l1 = leftRow[blkY + y - x - 2]; int l2; if (y - x - 1 == -1) l2 = topLeft[blkY >> 2]; else l2 = leftRow[blkY + y - x - 1]; int l3; if (y - x == -1) l3 = topLeft[blkY >> 2]; else l3 = leftRow[blkY + y - x]; residual[off + x] = clip(residual[off + x] + ((l1 + 2 * l2 + l3 + 2) >> 2), 0, 255); } else residual[off + x] = clip(residual[off + x] + ((topLine[mbOffX + blkX + 0] + 2 * topLeft[blkY>>2] + leftRow[blkY] + 2) >> 2), 0, 255); } off += 16; } } public static void predictVerticalRight(int[] residual, boolean leftAvailable, boolean topAvailable, int[] leftRow, int[] topLine, int[] topLeft, int mbOffX, int blkX, int blkY) { int v1 = (topLeft[blkY >> 2] + topLine[mbOffX + blkX + 0] + 1) >> 1; int v2 = (topLine[mbOffX + blkX + 0] + topLine[mbOffX + blkX + 1] + 1) >> 1; int v3 = (topLine[mbOffX + blkX + 1] + topLine[mbOffX + blkX + 2] + 1) >> 1; int v4 = (topLine[mbOffX + blkX + 2] + topLine[mbOffX + blkX + 3] + 1) >> 1; int v5 = (leftRow[blkY] + 2 * topLeft[blkY >> 2] + topLine[mbOffX + blkX + 0] + 2) >> 2; int v6 = (topLeft[blkY >> 2] + 2 * topLine[mbOffX + blkX + 0] + topLine[mbOffX + blkX + 1] + 2) >> 2; int v7 = (topLine[mbOffX + blkX + 0] + 2 * topLine[mbOffX + blkX + 1] + topLine[mbOffX + blkX + 2] + 2) >> 2; int v8 = (topLine[mbOffX + blkX + 1] + 2 * topLine[mbOffX + blkX + 2] + topLine[mbOffX + blkX + 3] + 2) >> 2; int v9 = (topLeft[blkY >> 2] + 2 * leftRow[blkY] + leftRow[blkY + 1] + 2) >> 2; int v10 = (leftRow[blkY] + 2 * leftRow[blkY + 1] + leftRow[blkY + 2] + 2) >> 2; int off = (blkY << 4) + blkX; residual[off] = clip(residual[off] + v1, 0, 255); residual[off + 1] = clip(residual[off + 1] + v2, 0, 255); residual[off + 2] = clip(residual[off + 2] + v3, 0, 255); residual[off + 3] = clip(residual[off + 3] + v4, 0, 255); residual[off + 16] = clip(residual[off + 16] + v5, 0, 255); residual[off + 17] = clip(residual[off + 17] + v6, 0, 255); residual[off + 18] = clip(residual[off + 18] + v7, 0, 255); residual[off + 19] = clip(residual[off + 19] + v8, 0, 255); residual[off + 32] = clip(residual[off + 32] + v9, 0, 255); residual[off + 33] = clip(residual[off + 33] + v1, 0, 255); residual[off + 34] = clip(residual[off + 34] + v2, 0, 255); residual[off + 35] = clip(residual[off + 35] + v3, 0, 255); residual[off + 48] = clip(residual[off + 48] + v10, 0, 255); residual[off + 49] = clip(residual[off + 49] + v5, 0, 255); residual[off + 50] = clip(residual[off + 50] + v6, 0, 255); residual[off + 51] = clip(residual[off + 51] + v7, 0, 255); } public static void predictHorizontalDown(int[] residual, boolean leftAvailable, boolean topAvailable, int[] leftRow, int[] topLine, int[] topLeft, int mbOffX, int blkX, int blkY) { int c0 = (topLeft[blkY>>2] + leftRow[blkY] + 1) >> 1; int c1 = (leftRow[blkY] + 2 * topLeft[blkY>>2] + topLine[mbOffX + blkX + 0] + 2) >> 2; int c2 = (topLeft[blkY>>2] + 2 * topLine[mbOffX + blkX + 0] + topLine[mbOffX + blkX + 1] + 2) >> 2; int c3 = (topLine[mbOffX + blkX + 0] + 2 * topLine[mbOffX + blkX + 1] + topLine[mbOffX + blkX + 2] + 2) >> 2; int c4 = (leftRow[blkY] + leftRow[blkY + 1] + 1) >> 1; int c5 = (topLeft[blkY>>2] + 2 * leftRow[blkY] + leftRow[blkY + 1] + 2) >> 2; int c6 = (leftRow[blkY + 1] + leftRow[blkY + 2] + 1) >> 1; int c7 = (leftRow[blkY] + 2 * leftRow[blkY + 1] + leftRow[blkY + 2] + 2) >> 2; int c8 = (leftRow[blkY + 2] + leftRow[blkY + 3] + 1) >> 1; int c9 = (leftRow[blkY + 1] + 2 * leftRow[blkY + 2] + leftRow[blkY + 3] + 2) >> 2; int off = (blkY << 4) + blkX; residual[off] = clip(residual[off] + c0, 0, 255); residual[off + 1] = clip(residual[off + 1] + c1, 0, 255); residual[off + 2] = clip(residual[off + 2] + c2, 0, 255); residual[off + 3] = clip(residual[off + 3] + c3, 0, 255); residual[off + 16] = clip(residual[off + 16] + c4, 0, 255); residual[off + 17] = clip(residual[off + 17] + c5, 0, 255); residual[off + 18] = clip(residual[off + 18] + c0, 0, 255); residual[off + 19] = clip(residual[off + 19] + c1, 0, 255); residual[off + 32] = clip(residual[off + 32] + c6, 0, 255); residual[off + 33] = clip(residual[off + 33] + c7, 0, 255); residual[off + 34] = clip(residual[off + 34] + c4, 0, 255); residual[off + 35] = clip(residual[off + 35] + c5, 0, 255); residual[off + 48] = clip(residual[off + 48] + c8, 0, 255); residual[off + 49] = clip(residual[off + 49] + c9, 0, 255); residual[off + 50] = clip(residual[off + 50] + c6, 0, 255); residual[off + 51] = clip(residual[off + 51] + c7, 0, 255); } public static void predictVerticalLeft(int[] residual, boolean topAvailable, boolean topRightAvailable, int[] topLine, int mbOffX, int blkX, int blkY) { int to = mbOffX + blkX; int tr0 = topLine[to+3], tr1 = topLine[to+3], tr2 = topLine[to+3]; if(topRightAvailable) { tr0 = topLine[to+4]; tr1 = topLine[to+5]; tr2 = topLine[to+6]; } int c0 = ((topLine[to] + topLine[to+1] + 1) >> 1); int c1 = ((topLine[to+1] + topLine[to+2] + 1) >> 1); int c2 = ((topLine[to+2] + topLine[to+3] + 1) >> 1); int c3 = ((topLine[to+3] + tr0 + 1) >> 1); int c4 = ((tr0 + tr1 + 1) >> 1); int c5 = ((topLine[to] + 2*topLine[to+1] + topLine[to+2] + 2) >> 2); int c6 = ((topLine[to+1] + 2*topLine[to+2] + topLine[to+3] + 2) >> 2); int c7 = ((topLine[to+2] + 2*topLine[to+3] + tr0 + 2) >> 2); int c8 = ((topLine[to+3] + 2*tr0 + tr1 + 2) >> 2); int c9 = ((tr0 + 2*tr1 + tr2 + 2) >> 2); int off = (blkY << 4) + blkX; residual[off] = clip(residual[off] + c0, 0, 255); residual[off+1] = clip(residual[off+1] + c1, 0, 255); residual[off+2] = clip(residual[off+2] + c2, 0, 255); residual[off+3] = clip(residual[off+3] + c3, 0, 255); residual[off+16] = clip(residual[off+16] + c5, 0, 255); residual[off+17] = clip(residual[off+17] + c6, 0, 255); residual[off+18] = clip(residual[off+18] + c7, 0, 255); residual[off+19] = clip(residual[off+19] + c8, 0, 255); residual[off+32] = clip(residual[off+32] + c1, 0, 255); residual[off+33] = clip(residual[off+33] + c2, 0, 255); residual[off+34] = clip(residual[off+34] + c3, 0, 255); residual[off+35] = clip(residual[off+35] + c4, 0, 255); residual[off+48] = clip(residual[off+48] + c6, 0, 255); residual[off+49] = clip(residual[off+49] + c7, 0, 255); residual[off+50] = clip(residual[off+50] + c8, 0, 255); residual[off+51] = clip(residual[off+51] + c9, 0, 255); } public static void predictHorizontalUp(int[] residual, boolean leftAvailable, int[] leftRow, int mbOffX, int blkX, int blkY) { int c0 = ((leftRow[blkY] + leftRow[blkY+1] + 1) >> 1); int c1 = ((leftRow[blkY] + (leftRow[blkY+1] << 1) + leftRow[blkY+2] + 2) >> 2); int c2 = ((leftRow[blkY+1] + leftRow[blkY+2] + 1) >> 1); int c3 = ((leftRow[blkY+1] + (leftRow[blkY+2] << 1) + leftRow[blkY+3] + 2) >> 2); int c4 = ((leftRow[blkY+2] + leftRow[blkY+3] + 1) >> 1); int c5 = ((leftRow[blkY+2] + (leftRow[blkY+3] << 1) + leftRow[blkY+3] + 2) >> 2); int c6 = leftRow[blkY+3]; int off = (blkY << 4) + blkX; residual[off] = clip(residual[off] + c0, 0, 255); residual[off+1] = clip(residual[off+1] + c1, 0, 255); residual[off+2] = clip(residual[off+2] + c2, 0, 255); residual[off+3] = clip(residual[off+3] + c3, 0, 255); residual[off+16] = clip(residual[off+16] + c2, 0, 255); residual[off+17] = clip(residual[off+17] + c3, 0, 255); residual[off+18] = clip(residual[off+18] + c4, 0, 255); residual[off+19] = clip(residual[off+19] + c5, 0, 255); residual[off+32] = clip(residual[off+32] + c4, 0, 255); residual[off+33] = clip(residual[off+33] + c5, 0, 255); residual[off+34] = clip(residual[off+34] + c6, 0, 255); residual[off+35] = clip(residual[off+35] + c6, 0, 255); residual[off+48] = clip(residual[off+48] + c6, 0, 255); residual[off+49] = clip(residual[off+49] + c6, 0, 255); residual[off+50] = clip(residual[off+50] + c6, 0, 255); residual[off+51] = clip(residual[off+51] + c6, 0, 255); } }