org.jcodec.codecs.mpeg12.MPEGPredOct 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.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, octal interpolation
*
* @author The JCodec project
*
*/
public class MPEGPredOct extends MPEGPred {
// Max block size is 16x16
private int[] tmp;
// TODO: this really implements interpolation for QUAD downsampling, add another linear step for OCT.
// This is also to be complient with MPEG spec which uses linear interpolation.
private static final int[][] COEFF = {
{ 0, 0, 128, 0, 0, 0 },
{ 0, -6, 123, 12, -1, 0 },
{ 2, -11, 108, 36, -8, 1 },
{ 0, -9, 93, 50, -6, 0 },
{ 3, -16, 77, 77, -16, 3 },
{ 0, -6, 50, 93, -9, 0 },
{ 1, -8, 36, 108, -11, 2 },
{ 0, -1, 12, 123, -6, 0 }
};
public MPEGPredOct(MPEGPred other) {
super(other.fCode, other.chromaFormat, other.topFieldFirst);
this.tmp = new int[16 * 21];
}
@Override
public void predictPlane(byte[] 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 >> 3, ry = refY >> 3;
tgtW >>= 3;
tgtH >>= 3;
boolean safe = rx >= 2 && ry >= 2 && rx + tgtW + 3 < refW && ((ry + tgtH + 3) << refVertStep) < refH;
if ((refX & 0x7) == 0) {
if ((refY & 0x7) == 0) {
if (safe)
predictFullXFullYSafe(ref, rx, ry, refW, refH, refVertStep, refVertOff, tgt, tgtY, tgtW, tgtH,
tgtVertStep);
else
predictFullXFullYUnSafe(ref, rx, ry, refW, refH, refVertStep, refVertOff, tgt, tgtY, tgtW, tgtH,
tgtVertStep);
} else {
if (safe)
predictFullXSubYSafe(ref, rx, ry, refY & 0x7, refW, refH, refVertStep, refVertOff, tgt, tgtY, tgtW,
tgtH, tgtVertStep);
else
predictFullXSubYUnSafe(ref, rx, ry, refY & 0x7, refW, refH, refVertStep, refVertOff, tgt, tgtY,
tgtW, tgtH, tgtVertStep);
}
} else if ((refY & 0x7) == 0) {
if (safe)
predictSubXFullYSafe(ref, rx, refX & 0x7, ry, refW, refH, refVertStep, refVertOff, tgt, tgtY, tgtW,
tgtH, tgtVertStep);
else
predictSubXFullYUnSafe(ref, rx, refX & 0x7, ry, refW, refH, refVertStep, refVertOff, tgt, tgtY, tgtW,
tgtH, tgtVertStep);
} else {
if (safe)
predictSubXSubYSafe(ref, rx, refX & 0x7, ry, refY & 0x7, refW, refH, refVertStep, refVertOff, tgt,
tgtY, tgtW, tgtH, tgtVertStep);
else
predictSubXSubYUnSafe(ref, rx, refX & 0x7, ry, refY & 0x7, refW, refH, refVertStep, refVertOff, tgt,
tgtY, tgtW, tgtH, tgtVertStep);
}
}
protected int getPix6(byte[] ref, int refW, int refH, int x, int y, int refVertStep, int refVertOff, int[] coeff) {
int lastLine = refH - (1 << refVertStep) + refVertOff;
int x0 = MathUtil.clip(x - 2, 0, refW - 1);
int x1 = MathUtil.clip(x - 1, 0, refW - 1);
int x2 = MathUtil.clip(x, 0, refW - 1);
int x3 = MathUtil.clip(x + 1, 0, refW - 1);
int x4 = MathUtil.clip(x + 2, 0, refW - 1);
int x5 = MathUtil.clip(x + 3, 0, refW - 1);
int off = MathUtil.clip(y, refVertOff, lastLine) * refW;
return ref[off + x0] * coeff[0] + ref[off + x1] * coeff[1] + ref[off + x2] * coeff[2] + ref[off + x3]
* coeff[3] + ref[off + x4] * coeff[4] + ref[off + x5] * coeff[5] + 16384;
}
protected int getPix6Vert(byte[] ref, int refW, int refH, int x, int y, int refVertStep, int refVertOff, int[] coeff) {
int lastLine = refH - (1 << refVertStep) + refVertOff;
int y0 = MathUtil.clip(y - (2 << refVertStep), refVertOff, lastLine);
int y1 = MathUtil.clip(y - (1 << refVertStep), refVertOff, lastLine);
int y2 = MathUtil.clip(y, 0, lastLine);
int y3 = MathUtil.clip(y + (1 << refVertStep), refVertOff, lastLine);
int y4 = MathUtil.clip(y + (2 << refVertStep), refVertOff, lastLine);
int y5 = MathUtil.clip(y + (3 << refVertStep), refVertOff, lastLine);
x = MathUtil.clip(x, 0, refW - 1);
return ref[y0 * refW + x] * coeff[0] + ref[y1 * refW + x] * coeff[1] + ref[y2 * refW + x] * coeff[2]
+ ref[y3 * refW + x] * coeff[3] + ref[y4 * refW + x] * coeff[4] + ref[y5 * refW + x] * coeff[5] + 16384;
}
private void predictSubXSubYUnSafe(byte[] 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 offTgt = tgtW * tgtY;
int dblTgtW = tgtW << 1;
int tripleTgtW = dblTgtW + tgtW;
int lfTgt = tgtVertStep * tgtW;
int[] coeff = COEFF[ix];
for (int i = -2, offTmp = 0; i < tgtH + 3; i++) {
int y = ((i + ry) << refVertStep) + refVertOff;
for (int j = 0; j < tgtW; j++, ++offTmp) {
tmp[offTmp] = getPix6(ref, refW, refH, j + rx, y, refVertStep, refVertOff, coeff);
}
}
coeff = COEFF[iy];
for (int i = 0, offTmp = dblTgtW; i < tgtH; i++) {
for (int j = 0; j < tgtW; j++, ++offTmp, ++offTgt) {
tgt[offTgt] = (tmp[offTmp - dblTgtW] * coeff[0] + tmp[offTmp - tgtW] * coeff[1] + tmp[offTmp]
* coeff[2] + tmp[offTmp + tgtW] * coeff[3] + tmp[offTmp + dblTgtW] * coeff[4]
+ tmp[offTmp + tripleTgtW] * coeff[5] + 8192) >> 14;
}
offTgt += lfTgt;
}
}
private void predictSubXSubYSafe(byte[] 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[] coeff = COEFF[ix];
int offRef = (((ry - 2) << refVertStep) + refVertOff) * refW + rx;
int offTgt = tgtW * tgtY;
int lfRef = (refW << refVertStep) - tgtW;
int lfTgt = tgtVertStep * tgtW;
int dblTgtW = tgtW << 1;
int tripleTgtW = dblTgtW + tgtW;
for (int i = 0, offTmp = 0; i < tgtH + 5; i++) {
for (int j = 0; j < tgtW; j++, ++offTmp, ++offRef) {
tmp[offTmp] = ref[offRef - 2] * coeff[0] + ref[offRef - 1] * coeff[1] + ref[offRef] * coeff[2]
+ ref[offRef + 1] * coeff[3] + ref[offRef + 2] * coeff[4] + ref[offRef + 3] * coeff[5];
}
offRef += lfRef;
}
coeff = COEFF[iy];
for (int i = 0, offTmp = dblTgtW; i < tgtH; i++) {
for (int j = 0; j < tgtW; j++, ++offTmp, ++offTgt) {
tgt[offTgt] = ((tmp[offTmp - dblTgtW] * coeff[0] + tmp[offTmp - tgtW] * coeff[1] + tmp[offTmp]
* coeff[2] + tmp[offTmp + tgtW] * coeff[3] + tmp[offTmp + dblTgtW] * coeff[4]
+ tmp[offTmp + tripleTgtW] * coeff[5] + 8192) >> 14) + 128;
}
offTgt += lfTgt;
}
}
private void predictSubXFullYUnSafe(byte[] 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[] coeff = COEFF[ix];
int tgtOff = tgtW * tgtY;
int lfTgt = tgtVertStep * tgtW;
for (int i = 0; i < tgtH; i++) {
int y = ((i + ry) << refVertStep) + refVertOff;
for (int j = 0; j < tgtW; j++) {
tgt[tgtOff++] = (getPix6(ref, refW, refH, j + rx, y, refVertStep, refVertOff, coeff) + 64) >> 7;
}
tgtOff += lfTgt;
}
}
private void predictSubXFullYSafe(byte[] 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[] coeff = COEFF[ix];
int offRef = ((ry << refVertStep) + refVertOff) * refW + rx;
int offTgt = tgtW * tgtY;
int lfRef = (refW << refVertStep) - tgtW;
int lfTgt = tgtVertStep * tgtW;
for (int i = 0; i < tgtH; i++) {
for (int j = 0; j < tgtW; j++, ++offRef) {
tgt[offTgt++] = ((ref[offRef - 2] * coeff[0] + ref[offRef - 1] * coeff[1] + ref[offRef] * coeff[2]
+ ref[offRef + 1] * coeff[3] + ref[offRef + 2] * coeff[4] + ref[offRef + 3] * coeff[5] + 64) >> 7) + 128;
}
offRef += lfRef;
offTgt += lfTgt;
}
}
private void predictFullXSubYUnSafe(byte[] 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[] coeff = COEFF[iy];
int tgtOff = tgtW * tgtY;
int lfTgt = tgtVertStep * tgtW;
for (int i = 0; i < tgtH; i++) {
int y = ((i + ry) << refVertStep) + refVertOff;
for (int j = 0; j < tgtW; j++) {
tgt[tgtOff++] = (getPix6Vert(ref, refW, refH, j + rx, y, refVertStep, refVertOff, coeff) + 64) >> 7;
}
tgtOff += lfTgt;
}
}
private void predictFullXSubYSafe(byte[] 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[] coeff = COEFF[iy];
int offTgt = tgtW * tgtY;
int offRef = ((ry << refVertStep) + refVertOff) * refW + rx;
int singleRefW = refW << refVertStep;
int dblRefW = refW << (1 + refVertStep);
int tripleRefW = dblRefW + singleRefW;
int lfTgt = tgtVertStep * tgtW;
int lfRef = (refW << refVertStep) - tgtW;
for (int i = 0; i < tgtH; i++) {
for (int j = 0; j < tgtW; ++j, ++offTgt, ++offRef) {
tgt[offTgt] = ((ref[offRef - dblRefW] * coeff[0] + ref[offRef - singleRefW] * coeff[1] + ref[offRef]
* coeff[2] + ref[offRef + singleRefW] * coeff[3] + ref[offRef + dblRefW] * coeff[4]
+ ref[offRef + tripleRefW] * coeff[5] + 64) >> 7) + 128;
}
offRef += lfRef;
offTgt += lfTgt;
}
}
}