package org.jcodec.codecs.mpeg12;
import org.jcodec.common.tools.MathUtil;
/**
* This class is part of JCodec ( www.jcodec.org ) This software is distributed
* under FreeBSD License
*
* MPEG 1/2 decoder interframe motion compensation routines
*
* @author The JCodec project
*
*/
public class MPEGPredQuad extends MPEGPred {
public MPEGPredQuad(MPEGPred other) {
super(other);
}
@Override
public void predictPlane(int[] ref, int refX, int refY, int refW, int refH, int refVertStep, int refVertOff,
int[] tgt, int tgtY, int tgtW, int tgtH, int tgtVertStep) {
int rx = refX >> 2, ry = refY >> 2;
boolean safe = rx >= 0 && ry >= 0 && rx + tgtW < refW && (ry + tgtH << refVertStep) < refH;
if ((refX & 0x3) == 0) {
if ((refY & 0x3) == 0) {
if (safe)
predictEvenEvenSafe(ref, rx, ry, refW, refH, refVertStep, refVertOff, tgt, tgtY, tgtW, tgtH,
tgtVertStep);
else
predictEvenEvenUnSafe(ref, rx, ry, refW, refH, refVertStep, refVertOff, tgt, tgtY, tgtW, tgtH,
tgtVertStep);
} else {
if (safe)
predictOddEvenSafe(ref, rx, ry, refY - (ry << 2), refW, refH, refVertStep, refVertOff, tgt,
tgtY, tgtW, tgtH, tgtVertStep);
else
predictOddEvenUnSafe(ref, rx, ry, refY - (ry << 2), refW, refH, refVertStep, refVertOff, tgt,
tgtY, tgtW, tgtH, tgtVertStep);
}
} else if ((refY & 0x3) == 0) {
if (safe)
predictEvenOddSafe(ref, rx, refX - (rx << 2), ry, refW, refH, refVertStep, refVertOff, tgt, tgtY,
tgtW, tgtH, tgtVertStep);
else
predictEvenOddUnSafe(ref, rx, refX - (rx << 2), ry, refW, refH, refVertStep, refVertOff, tgt, tgtY,
tgtW, tgtH, tgtVertStep);
} else {
if (safe)
predictOddOddSafe(ref, rx, refX - (rx << 2), ry, refY - (ry << 2), refW, refH, refVertStep,
refVertOff, tgt, tgtY, tgtW, tgtH, tgtVertStep);
else
predictOddOddUnSafe(ref, rx, refX - (rx << 2), ry, refY - (ry << 2), refW, refH, refVertStep,
refVertOff, tgt, tgtY, tgtW, tgtH, tgtVertStep);
}
}
private void predictOddOddUnSafe(int[] ref, int rx, int ix, int ry, int iy, int refW, int refH,
int refVertStep, int refVertOff, int[] tgt, int tgtY, int tgtW, int tgtH, int tgtVertStep) {
int tgtOff = tgtW * tgtY, jump = tgtVertStep * tgtW;
for (int j = 0; j < tgtH; j++) {
int y1 = ((j + ry) << refVertStep) + refVertOff;
int y2 = ((j + ry + 1) << refVertStep) + refVertOff;
for (int i = 0; i < tgtW; i++) {
int ptX = i + rx;
tgt[tgtOff++] = getPix4(ref, refW, refH, ptX, y1, ptX + 1, y1, ptX, y2, ptX + 1, y2, refVertStep,
refVertOff, ix, iy);
}
tgtOff += jump;
}
}
protected int getPix4(int[] ref, int refW, int refH, int x1, int y1, int x2, int y2, int x3, int y3, int x4,
int y4, int refVertStep, int refVertOff, int ix, int iy) {
int lastLine = refH - (1 << refVertStep) + refVertOff;
x1 = MathUtil.clip(x1, 0, refW - 1);
y1 = MathUtil.clip(y1, 0, lastLine);
x2 = MathUtil.clip(x2, 0, refW - 1);
y2 = MathUtil.clip(y2, 0, lastLine);
x3 = MathUtil.clip(x3, 0, refW - 1);
y3 = MathUtil.clip(y3, 0, lastLine);
x4 = MathUtil.clip(x4, 0, refW - 1);
y4 = MathUtil.clip(y4, 0, lastLine);
int nix = 4 - ix, niy = 4 - iy;
return (ref[y1 * refW + x1] * nix * niy + ref[y2 * refW + x2] * ix * niy + ref[y3 * refW + x3] * nix * iy
+ ref[y4 * refW + x4] * ix * iy + 8) >> 4;
}
private void predictOddOddSafe(int[] ref, int rx, int ix, int ry, int iy, int refW, int refH, int refVertStep,
int refVertOff, int[] tgt, int tgtY, int tgtW, int tgtH, int tgtVertStep) {
int offRef = ((ry << refVertStep) + refVertOff) * refW + rx, offTgt = tgtW * tgtY, lfRef = (refW << refVertStep)
- tgtW, lfTgt = tgtVertStep * tgtW, stride = refW << refVertStep;
int nix = 4 - ix, niy = 4 - iy;
for (int i = 0; i < tgtH; i++) {
for (int j = 0; j < tgtW; j++) {
tgt[offTgt++] = (ref[offRef] * nix * niy + ref[offRef + 1] * ix * niy + ref[offRef + stride] * nix
* iy + ref[offRef + stride + 1] * ix * iy + 8) >> 4;
++offRef;
}
offRef += lfRef;
offTgt += lfTgt;
}
}
protected int getPix2(int[] ref, int refW, int refH, int x1, int y1, int x2, int y2, int refVertStep,
int refVertOff, int i) {
int ni = 4 - i;
x1 = MathUtil.clip(x1, 0, refW - 1);
int lastLine = refH - (1 << refVertStep) + refVertOff;
y1 = MathUtil.clip(y1, 0, lastLine);
x2 = MathUtil.clip(x2, 0, refW - 1);
y2 = MathUtil.clip(y2, 0, lastLine);
return (ref[y1 * refW + x1] * ni + ref[y2 * refW + x2] * i + 2) >> 2;
}
private void predictEvenOddUnSafe(int[] ref, int rx, int ix, int ry, int refW, int refH, int refVertStep,
int refVertOff, int[] tgt, int tgtY, int tgtW, int tgtH, int tgtVertStep) {
int tgtOff = tgtW * tgtY, jump = tgtVertStep * tgtW;
for (int j = 0; j < tgtH; j++) {
int y = ((j + ry) << refVertStep) + refVertOff;
for (int i = 0; i < tgtW; i++) {
tgt[tgtOff++] = getPix2(ref, refW, refH, i + rx, y, i + rx + 1, y, refVertStep, refVertOff, ix);
}
tgtOff += jump;
}
}
private void predictEvenOddSafe(int[] ref, int rx, int ix, int ry, int refW, int refH, int refVertStep,
int refVertOff, int[] tgt, int tgtY, int tgtW, int tgtH, int tgtVertStep) {
int offRef = ((ry << refVertStep) + refVertOff) * refW + rx, offTgt = tgtW * tgtY, lfRef = (refW << refVertStep)
- tgtW, lfTgt = tgtVertStep * tgtW;
int nix = 4 - ix;
for (int i = 0; i < tgtH; i++) {
for (int j = 0; j < tgtW; j++) {
tgt[offTgt++] = (ref[offRef] * nix + ref[offRef + 1] * ix + 2) >> 2;
++offRef;
}
offRef += lfRef;
offTgt += lfTgt;
}
}
private void predictOddEvenUnSafe(int[] ref, int rx, int ry, int iy, int refW, int refH, int refVertStep,
int refVertOff, int[] tgt, int tgtY, int tgtW, int tgtH, int tgtVertStep) {
int tgtOff = tgtW * tgtY, jump = tgtVertStep * tgtW;
for (int j = 0; j < tgtH; j++) {
int y1 = ((j + ry) << refVertStep) + refVertOff;
int y2 = ((j + ry + 1) << refVertStep) + refVertOff;
for (int i = 0; i < tgtW; i++) {
tgt[tgtOff++] = getPix2(ref, refW, refH, i + rx, y1, i + rx, y2, refVertStep, refVertOff, iy);
}
tgtOff += jump;
}
}
private void predictOddEvenSafe(int[] ref, int rx, int ry, int iy, int refW, int refH, int refVertStep,
int refVertOff, int[] tgt, int tgtY, int tgtW, int tgtH, int tgtVertStep) {
int offRef = ((ry << refVertStep) + refVertOff) * refW + rx, offTgt = tgtW * tgtY, lfRef = (refW << refVertStep)
- tgtW, lfTgt = tgtVertStep * tgtW, stride = refW << refVertStep;
int niy = 4 - iy;
for (int i = 0; i < tgtH; i++) {
for (int j = 0; j < tgtW; j++) {
tgt[offTgt++] = (ref[offRef] * niy + ref[offRef + stride] * iy + 2) >> 2;
++offRef;
}
offRef += lfRef;
offTgt += lfTgt;
}
}
}