package org.jcodec.codecs.h264.decode;
import static java.lang.System.arraycopy;
import static org.jcodec.common.ArrayUtil.shiftLeft1;
import static org.jcodec.common.tools.MathUtil.clip;
import org.jcodec.common.logging.Logger;
import org.jcodec.common.model.Picture8Bit;
public class MBlockDecoderUtils {
private static boolean debug;
public static final int[] NULL_VECTOR = new int[] { 0, 0, -1 };
public static void debugPrint(Object... arguments) {
if (debug && arguments.length > 0) {
if (arguments.length == 1) {
Logger.debug(""+arguments[0]);
} else {
String fmt = (String)arguments[0];
shiftLeft1(arguments);
Logger.debug(String.format(fmt, arguments));
}
}
}
static void collectPredictors(DecoderState sharedState, Picture8Bit outMB, int mbX) {
sharedState.topLeft[0][0] = sharedState.topLine[0][(mbX << 4) + 15];
sharedState.topLeft[0][1] = outMB.getPlaneData(0)[63];
sharedState.topLeft[0][2] = outMB.getPlaneData(0)[127];
sharedState.topLeft[0][3] = outMB.getPlaneData(0)[191];
arraycopy(outMB.getPlaneData(0), 240, sharedState.topLine[0], mbX << 4, 16);
copyCol(outMB.getPlaneData(0), 16, 15, 16, sharedState.leftRow[0]);
collectChromaPredictors(sharedState, outMB, mbX);
}
static void collectChromaPredictors(DecoderState sharedState, Picture8Bit outMB, int mbX) {
sharedState.topLeft[1][0] = sharedState.topLine[1][(mbX << 3) + 7];
sharedState.topLeft[2][0] = sharedState.topLine[2][(mbX << 3) + 7];
arraycopy(outMB.getPlaneData(1), 56, sharedState.topLine[1], mbX << 3, 8);
arraycopy(outMB.getPlaneData(2), 56, sharedState.topLine[2], mbX << 3, 8);
copyCol(outMB.getPlaneData(1), 8, 7, 8, sharedState.leftRow[1]);
copyCol(outMB.getPlaneData(2), 8, 7, 8, sharedState.leftRow[2]);
}
private static void copyCol(byte[] planeData, int n, int off, int stride, byte[] out) {
for (int i = 0; i < n; i++, off += stride) {
out[i] = planeData[off];
}
}
static void saveMvsIntra(DeblockerInput di, int mbX, int mbY) {
for (int j = 0, blkOffY = mbY << 2, blkInd = 0; j < 4; j++, blkOffY++) {
for (int i = 0, blkOffX = mbX << 2; i < 4; i++, blkOffX++, blkInd++) {
di.mvs[0][blkOffY][blkOffX] = NULL_VECTOR;
di.mvs[1][blkOffY][blkOffX] = NULL_VECTOR;
}
}
}
static void mergeResidual(Picture8Bit mb, int[][][] residual, int[][] blockLUT, int[][] posLUT) {
for (int comp = 0; comp < 3; comp++) {
byte[] to = mb.getPlaneData(comp);
for (int i = 0; i < to.length; i++) {
to[i] = (byte) clip(to[i] + residual[comp][blockLUT[comp][i]][posLUT[comp][i]], -128, 127);
}
}
}
static void saveVect(int[][] mv, int from, int to, int x, int y, int r) {
for (int i = from; i < to; i++) {
mv[i][0] = x;
mv[i][1] = y;
mv[i][2] = r;
}
}
public static int calcMVPredictionMedian(int[] a, int[] b, int[] c, int[] d, boolean aAvb, boolean bAvb,
boolean cAvb, boolean dAvb, int ref, int comp) {
if (!cAvb) {
c = d;
cAvb = dAvb;
}
if (aAvb && !bAvb && !cAvb) {
b = c = a;
bAvb = cAvb = aAvb;
}
a = aAvb ? a : NULL_VECTOR;
b = bAvb ? b : NULL_VECTOR;
c = cAvb ? c : NULL_VECTOR;
if (a[2] == ref && b[2] != ref && c[2] != ref)
return a[comp];
else if (b[2] == ref && a[2] != ref && c[2] != ref)
return b[comp];
else if (c[2] == ref && a[2] != ref && b[2] != ref)
return c[comp];
return a[comp] + b[comp] + c[comp] - min(a[comp], b[comp], c[comp]) - max(a[comp], b[comp], c[comp]);
}
public static int max(int x, int x2, int x3) {
return x > x2 ? (x > x3 ? x : x3) : (x2 > x3 ? x2 : x3);
}
public static int min(int x, int x2, int x3) {
return x < x2 ? (x < x3 ? x : x3) : (x2 < x3 ? x2 : x3);
}
static void copyVect(int[] to, int[] from) {
to[0] = from[0];
to[1] = from[1];
to[2] = from[2];
}
static void saveMvs(DeblockerInput di, int[][][] x, int mbX, int mbY) {
for (int j = 0, blkOffY = mbY << 2, blkInd = 0; j < 4; j++, blkOffY++) {
for (int i = 0, blkOffX = mbX << 2; i < 4; i++, blkOffX++, blkInd++) {
di.mvs[0][blkOffY][blkOffX] = x[0][blkInd];
di.mvs[1][blkOffY][blkOffX] = x[1][blkInd];
}
}
}
static void savePrediction8x8(DecoderState sharedState, int mbX, int[][] x, int list) {
copyVect(sharedState.mvTopLeft[list], sharedState.mvTop[list][(mbX << 2) + 3]);
copyVect(sharedState.mvLeft[list][0], x[3]);
copyVect(sharedState.mvLeft[list][1], x[7]);
copyVect(sharedState.mvLeft[list][2], x[11]);
copyVect(sharedState.mvLeft[list][3], x[15]);
copyVect(sharedState.mvTop[list][mbX << 2], x[12]);
copyVect(sharedState.mvTop[list][(mbX << 2) + 1], x[13]);
copyVect(sharedState.mvTop[list][(mbX << 2) + 2], x[14]);
copyVect(sharedState.mvTop[list][(mbX << 2) + 3], x[15]);
}
public static void saveVectIntra(DecoderState sharedState, int mbX) {
int xx = mbX << 2;
copyVect(sharedState.mvTopLeft[0], sharedState.mvTop[0][xx + 3]);
copyVect(sharedState.mvTopLeft[1], sharedState.mvTop[1][xx + 3]);
saveVect(sharedState.mvTop[0], xx, xx + 4, 0, 0, -1);
saveVect(sharedState.mvLeft[0], 0, 4, 0, 0, -1);
saveVect(sharedState.mvTop[1], xx, xx + 4, 0, 0, -1);
saveVect(sharedState.mvLeft[1], 0, 4, 0, 0, -1);
}
}