All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jcodec.codecs.mpeg12.MPEGPredOct Maven / Gradle / Ivy

There is a newer version: 0.2.5
Show newest version
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;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy