org.jcodec.codecs.h264.decode.Intra4x4PredictionBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jcodec Show documentation
Show all versions of jcodec Show documentation
Pure Java implementation of video/audio codecs and formats
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);
}
}