package org.jcodec.codecs.h264.encode; import static org.jcodec.common.tools.MathUtil.clip; import org.jcodec.common.model.Picture8Bit; /** * This class is part of JCodec ( www.jcodec.org ) This software is distributed * under FreeBSD License * * @author The JCodec project */ public class MBEncoderHelper { public static final void takeSubtract(byte[] planeData, int planeWidth, int planeHeight, int x, int y, int[] coeff, byte[] pred, int blkW, int blkH) { if (x + blkW < planeWidth && y + blkH < planeHeight) takeSubtractSafe(planeData, planeWidth, planeHeight, x, y, coeff, pred, blkW, blkH); else takeSubtractUnsafe(planeData, planeWidth, planeHeight, x, y, coeff, pred, blkW, blkH); } public static final void takeSubtractSafe(byte[] planeData, int planeWidth, int planeHeight, int x, int y, int[] coeff, byte[] pred, int blkW, int blkH) { for (int i = 0, srcOff = y * planeWidth + x, dstOff = 0; i < blkH; i++, srcOff += planeWidth) { for (int j = 0, srcOff1 = srcOff; j < blkW; j += 4, dstOff += 4, srcOff1 += 4) { coeff[dstOff] = planeData[srcOff1] - pred[dstOff]; coeff[dstOff + 1] = planeData[srcOff1 + 1] - pred[dstOff + 1]; coeff[dstOff + 2] = planeData[srcOff1 + 2] - pred[dstOff + 2]; coeff[dstOff + 3] = planeData[srcOff1 + 3] - pred[dstOff + 3]; } } } public static final void take(byte[] planeData, int planeWidth, int planeHeight, int x, int y, byte[] patch, int blkW, int blkH) { if (x + blkW < planeWidth && y + blkH < planeHeight) takeSafe(planeData, planeWidth, planeHeight, x, y, patch, blkW, blkH); else takeExtendBorder(planeData, planeWidth, planeHeight, x, y, patch, blkW, blkH); } public static final void takeSafe(byte[] planeData, int planeWidth, int planeHeight, int x, int y, byte[] patch, int blkW, int blkH) { for (int i = 0, srcOff = y * planeWidth + x, dstOff = 0; i < blkH; i++, srcOff += planeWidth) { for (int j = 0, srcOff1 = srcOff; j < blkW; ++j, ++dstOff, ++srcOff1) { patch[dstOff] = planeData[srcOff1]; } } } public static final void takeExtendBorder(byte[] planeData, int planeWidth, int planeHeight, int x, int y, byte[] patch, int blkW, int blkH) { int outOff = 0; int i; for (i = y; i < Math.min(y + blkH, planeHeight); i++) { int off = i * planeWidth + Math.min(x, planeWidth); int j; for (j = x; j < Math.min(x + blkW, planeWidth); j++, outOff++, off++) { patch[outOff] = planeData[off]; } --off; for (; j < x + blkW; j++, outOff++) { patch[outOff] = planeData[off]; } } for (; i < y + blkH; i++) { int off = planeHeight * planeWidth - planeWidth + Math.min(x, planeWidth); int j; for (j = x; j < Math.min(x + blkW, planeWidth); j++, outOff++, off++) { patch[outOff] = planeData[off]; } --off; for (; j < x + blkW; j++, outOff++) { patch[outOff] = planeData[off]; } } } public static final void takeSafe2(byte[] planeData, int planeWidth, int planeHeight, int x, int y, int[] coeff, int blkW, int blkH) { for (int i = 0, srcOff = y * planeWidth + x, dstOff = 0; i < blkH; i++, srcOff += planeWidth) { for (int j = 0, srcOff1 = srcOff; j < blkW; ++j, ++dstOff, ++srcOff1) { coeff[dstOff] = planeData[srcOff1]; } } } public static final void takeSubtractUnsafe(byte[] planeData, int planeWidth, int planeHeight, int x, int y, int[] coeff, byte[] pred, int blkW, int blkH) { int outOff = 0; int i; for (i = y; i < Math.min(y + blkH, planeHeight); i++) { int off = i * planeWidth + Math.min(x, planeWidth); int j; for (j = x; j < Math.min(x + blkW, planeWidth); j++, outOff++, off++) { coeff[outOff] = planeData[off] - pred[outOff]; } --off; for (; j < x + blkW; j++, outOff++) { coeff[outOff] = planeData[off] - pred[outOff]; } } for (; i < y + blkH; i++) { int off = planeHeight * planeWidth - planeWidth + Math.min(x, planeWidth); int j; for (j = x; j < Math.min(x + blkW, planeWidth); j++, outOff++, off++) { coeff[outOff] = planeData[off] - pred[outOff]; } --off; for (; j < x + blkW; j++, outOff++) { coeff[outOff] = planeData[off] - pred[outOff]; } } } public static final void putBlk(byte[] planeData, int[] block, byte[] pred, int log2stride, int blkX, int blkY, int blkW, int blkH) { int stride = 1 << log2stride; for (int line = 0, srcOff = 0, dstOff = (blkY << log2stride) + blkX; line < blkH; line++) { int dstOff1 = dstOff; for (int row = 0; row < blkW; row += 4) { planeData[dstOff1] = (byte) clip(block[srcOff] + pred[srcOff], -128, 127); planeData[dstOff1 + 1] = (byte) clip(block[srcOff + 1] + pred[srcOff + 1], -128, 127); planeData[dstOff1 + 2] = (byte) clip(block[srcOff + 2] + pred[srcOff + 2], -128, 127); planeData[dstOff1 + 3] = (byte) clip(block[srcOff + 3] + pred[srcOff + 3], -128, 127); srcOff += 4; dstOff1 += 4; } dstOff += stride; } } public static final void putBlkPic(Picture8Bit dest, Picture8Bit src, int x, int y) { if (dest.getColor() != src.getColor()) throw new RuntimeException("Incompatible color"); for (int c = 0; c < dest.getColor().nComp; c++) { pubBlkOnePlane(dest.getPlaneData(c), dest.getPlaneWidth(c), src.getPlaneData(c), src.getPlaneWidth(c), src.getPlaneHeight(c), x >> dest.getColor().compWidth[c], y >> dest.getColor().compHeight[c]); } } private static void pubBlkOnePlane(byte[] dest, int destWidth, byte[] src, int srcWidth, int srcHeight, int x, int y) { int destOff = y * destWidth + x; int srcOff = 0; for (int i = 0; i < srcHeight; i++) { for (int j = 0; j < srcWidth; j++, ++destOff, ++srcOff) dest[destOff] = src[srcOff]; destOff += destWidth - srcWidth; } } }