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

org.jcodec.codecs.h264.decode.Intra4x4PredictionBuilder Maven / Gradle / Ivy

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




© 2015 - 2024 Weber Informatics LLC | Privacy Policy