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

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

There is a newer version: 0.2.5
Show newest version
package org.jcodec.codecs.mpeg12;

import static org.jcodec.codecs.mpeg12.MPEGConst.BLOCK_TO_CC;
import static org.jcodec.codecs.mpeg12.MPEGConst.SQUEEZE_X;
import static org.jcodec.codecs.mpeg12.MPEGConst.SQUEEZE_Y;
import static org.jcodec.codecs.mpeg12.MPEGConst.vlcCoeff0;
import static org.jcodec.codecs.mpeg12.MPEGConst.vlcDCSizeChroma;
import static org.jcodec.codecs.mpeg12.MPEGConst.vlcDCSizeLuma;
import static org.jcodec.codecs.mpeg12.bitstream.SequenceExtension.Chroma420;

import java.util.Arrays;

import org.jcodec.codecs.mpeg12.bitstream.PictureHeader;
import org.jcodec.codecs.mpeg12.bitstream.SequenceHeader;
import org.jcodec.common.dct.IDCT4x4;
import org.jcodec.common.io.BitReader;
import org.jcodec.common.io.VLC;

/**
 * This class is part of JCodec ( www.jcodec.org ) This software is distributed
 * under FreeBSD License
 * 
 * MPEG 1/2 Decoder, downscaled 4x4
 * 
 * @author The JCodec project
 * 
 */
public class Mpeg2Thumb4x4 extends MPEGDecoder {
    private MPEGPred localPred;
    private MPEGPred oldPred;

    protected void blockIntra(BitReader bits, VLC vlcCoeff, int[] block, int[] intra_dc_predictor, int blkIdx,
            int[] scan, int escSize, int intra_dc_mult, int qScale, int[] qmat) {
        int cc = BLOCK_TO_CC[blkIdx];
        int size = (cc == 0 ? vlcDCSizeLuma : vlcDCSizeChroma).readVLC(bits);
        int delta = (size != 0) ? mpegSigned(bits, size) : 0;
        intra_dc_predictor[cc] = intra_dc_predictor[cc] + delta;
        Arrays.fill(block, 1, 16, 0);
        block[0] = intra_dc_predictor[cc] * intra_dc_mult;

        int idx, readVLC = 0;
        for (idx = 0; idx < 19 + (scan == scan4x4[1] ? 7 : 0);) {
            readVLC = vlcCoeff.readVLC(bits);
            int level;

            if (readVLC == MPEGConst.CODE_END) {
                break;
            } else if (readVLC == MPEGConst.CODE_ESCAPE) {
                idx += bits.readNBit(6) + 1;
                level = twosSigned(bits, escSize) * qScale * qmat[idx];
                level = level >= 0 ? (level >> 4) : -(-level >> 4);
            } else {
                idx += (readVLC >> 6) + 1;
                level = toSigned(((readVLC & 0x3f) * qScale * qmat[idx]) >> 4, bits.read1Bit());
            }
            block[scan[idx]] = level;
        }
        if (readVLC != MPEGConst.CODE_END)
            finishOff(bits, idx, vlcCoeff, escSize);
        IDCT4x4.idct(block, 0);
    }

    private void finishOff(BitReader bits, int idx, VLC vlcCoeff, int escSize) {
        for (; idx < 64;) {
            int readVLC = vlcCoeff.readVLC(bits);

            if (readVLC == MPEGConst.CODE_END) {
                break;
            } else if (readVLC == MPEGConst.CODE_ESCAPE) {
                idx += bits.readNBit(6) + 1;
                bits.readNBit(escSize);
            } else {
                bits.read1Bit();
            }
        }
    }

    protected void blockInter(BitReader bits, VLC vlcCoeff, int[] block, int[] scan, int escSize, int qScale, int[] qmat) {
        Arrays.fill(block, 1, 16, 0);

        int idx = -1;
        if (vlcCoeff == vlcCoeff0 && bits.checkNBit(1) == 1) {
            bits.read1Bit();
            block[0] = toSigned(quantInter(1, qScale * qmat[0]), bits.read1Bit());
            idx++;
        } else {
            block[0] = 0;
        }

        int readVLC = 0;
        for (; idx < 19 + (scan == scan4x4[1] ? 7 : 0);) {
            readVLC = vlcCoeff.readVLC(bits);
            int ac;
            if (readVLC == MPEGConst.CODE_END) {
                break;
            } else if (readVLC == MPEGConst.CODE_ESCAPE) {
                idx += bits.readNBit(6) + 1;
                ac = quantInterSigned(twosSigned(bits, escSize), qScale * qmat[idx]);
            } else {
                idx += (readVLC >> 6) + 1;
                ac = toSigned(quantInter(readVLC & 0x3f, qScale * qmat[idx]), bits.read1Bit());
            }
            block[scan[idx]] = ac;
        }
        if (readVLC != MPEGConst.CODE_END)
            finishOff(bits, idx, vlcCoeff, escSize);
        IDCT4x4.idct(block, 0);
    }

    @Override
    public int decodeMacroblock(PictureHeader ph, Context context, int prevAddr, int[] qScaleCode, int[][] buf,
            int stride, BitReader bits, int vertOff, int vertStep, MPEGPred pred) {
        if (localPred == null || oldPred != pred) {
            localPred = new MPEGPredQuad(pred);
            oldPred = pred;
        }

        return super.decodeMacroblock(ph, context, prevAddr, qScaleCode, buf, stride, bits, vertOff, vertStep,
                localPred);
    }

    public static int[] BLOCK_POS_X = new int[] { 0, 4, 0, 4, 0, 0, 0, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0, 4, 0, 4, 0, 0, 0,
            0, 4, 4, 4, 4 };
    public static int[] BLOCK_POS_Y = new int[] { 0, 0, 4, 4, 0, 0, 4, 4, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1,
            1, 0, 0, 1, 1 };

    protected void mapBlock(int[] block, int[] out, int blkIdx, int dctType, int chromaFormat) {
        int stepVert = chromaFormat == Chroma420 && (blkIdx == 4 || blkIdx == 5) ? 0 : dctType;
        int log2stride = blkIdx < 4 ? 3 : 3 - SQUEEZE_X[chromaFormat];

        int blkIdxExt = blkIdx + (dctType << 4);
        int x = BLOCK_POS_X[blkIdxExt];
        int y = BLOCK_POS_Y[blkIdxExt];
        int off = (y << log2stride) + x, stride = 1 << (log2stride + stepVert);

        for (int i = 0; i < 16; i += 4, off += stride) {
            out[off] += block[i];
            out[off + 1] += block[i + 1];
            out[off + 2] += block[i + 2];
            out[off + 3] += block[i + 3];
        }
    }

    protected void put(int[][] mbPix, int[][] buf, int stride, int chromaFormat, int mbX, int mbY, int width,
            int height, int vertOff, int vertStep) {

        int chromaStride = (stride + (1 << SQUEEZE_X[chromaFormat]) - 1) >> SQUEEZE_X[chromaFormat];
        int chromaMBW = 3 - SQUEEZE_X[chromaFormat];
        int chromaMBH = 3 - SQUEEZE_Y[chromaFormat];

        putSub(buf[0], (mbY << 3) * (stride << vertStep) + vertOff * stride + (mbX << 3), stride << vertStep, mbPix[0],
                3, 3);
        putSub(buf[1], (mbY << chromaMBH) * (chromaStride << vertStep) + vertOff * chromaStride + (mbX << chromaMBW),
                chromaStride << vertStep, mbPix[1], chromaMBW, chromaMBH);
        putSub(buf[2], (mbY << chromaMBH) * (chromaStride << vertStep) + vertOff * chromaStride + (mbX << chromaMBW),
                chromaStride << vertStep, mbPix[2], chromaMBW, chromaMBH);
    }

    private final void putSub(int[] big, int off, int stride, int[] block, int mbW, int mbH) {
        int blOff = 0;

        if (mbW == 2) {
            for (int i = 0; i < (1 << mbH); i++) {
                big[off] = clip(block[blOff]);
                big[off + 1] = clip(block[blOff + 1]);
                big[off + 2] = clip(block[blOff + 2]);
                big[off + 3] = clip(block[blOff + 3]);

                blOff += 4;
                off += stride;
            }
        } else {
            for (int i = 0; i < (1 << mbH); i++) {
                big[off] = clip(block[blOff]);
                big[off + 1] = clip(block[blOff + 1]);
                big[off + 2] = clip(block[blOff + 2]);
                big[off + 3] = clip(block[blOff + 3]);
                big[off + 4] = clip(block[blOff + 4]);
                big[off + 5] = clip(block[blOff + 5]);
                big[off + 6] = clip(block[blOff + 6]);
                big[off + 7] = clip(block[blOff + 7]);

                blOff += 8;
                off += stride;
            }
        }
    }

    public static int[][] scan4x4 = new int[][] {
            new int[] { 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 16, 13, 10, 7, 16, 16, 16, 11, 14, 16, 16, 16, 16, 16, 15, 16,
                    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
                    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 },
            new int[] { 0, 4, 8, 12, 1, 5, 2, 6, 9, 13, 16, 16, 16, 16, 16, 16, 16, 16, 14, 10, 3, 7, 16, 16, 11, 15,
                    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
                    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 } };

    protected Context initContext(SequenceHeader sh, PictureHeader ph) {
        Context context = super.initContext(sh, ph);
        context.codedWidth >>= 1;
        context.codedHeight >>= 1;
        context.picWidth >>= 1;
        context.picHeight >>= 1;

        context.scan = scan4x4[ph.pictureCodingExtension == null ? 0 : ph.pictureCodingExtension.alternate_scan];

        return context;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy