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

org.jcodec.codecs.common.biari.MDecoder Maven / Gradle / Ivy

There is a newer version: 0.2.5
Show newest version
package org.jcodec.codecs.common.biari;
import java.io.IOException;
import java.nio.ByteBuffer;

/**
 * This class is part of JCodec ( www.jcodec.org ) This software is distributed
 * under FreeBSD License
 * 
 * H264 CABAC M-Coder ( decoder module )
 * 
 * @author The JCodec project
 * 
 */
public class MDecoder {

    private ByteBuffer _in;
    private int range;
    private int code;
    private int nBitsPending;
    private int[][] cm;

    public MDecoder(ByteBuffer _in, int[][] cm) {
        this._in = _in;
        this.range = 510;
        this.cm = cm;

        initCodeRegister();
    }

    /**
     * Initializes code register. Loads 9 bits from the stream into working area
     * of code register ( bits 8 - 16) leaving 7 bits in the pending area of
     * code register (bits 0 - 7)
     * 
     * @throws IOException
     */
    protected void initCodeRegister() {
        readOneByte();
        if (nBitsPending != 8)
            throw new RuntimeException("Empty stream");
        code <<= 8;
        readOneByte();
        code <<= 1;
        nBitsPending -= 9;
    }

    protected void readOneByte() {
        if (!_in.hasRemaining())
            return;
        int b = _in.get() & 0xff;
        code |= b;
        nBitsPending += 8;
    }

    /**
     * Decodes one bin from arithmetice code word
     * 
     * @param cm
     * @return
     * @throws IOException
     */
    public int decodeBin(int m) {
        int bin;

        int qIdx = (range >> 6) & 0x3;
        int rLPS = MConst.rangeLPS[qIdx][cm[0][m]];
        range -= rLPS;
        int rs8 = range << 8;

        if (code < rs8) {
            // MPS
            if (cm[0][m] < 62)
                cm[0][m]++;

            renormalize();

            bin = cm[1][m];
        } else {
            // LPS
            range = rLPS;
            code -= rs8;

            renormalize();

            bin = 1 - cm[1][m];

            if (cm[0][m] == 0)
                cm[1][m] = 1 - cm[1][m];

            cm[0][m] = MConst.transitLPS[cm[0][m]];
        }

//        System.out.println("CABAC BIT [" + m + "]: " + bin);
        return bin;
    }

    /**
     * Special decoding process for 'end of slice' flag. Uses probability state
     * 63.
     * 
     * @param cm
     * @return
     * @throws IOException
     */
    public int decodeFinalBin() {
        range -= 2;

        if (code < (range << 8)) {
            renormalize();
//            System.out.println("CABAC BIT [-2]: 0");
            return 0;
        } else {
//            System.out.println("CABAC BIT [-2]: 1");
            return 1;
        }
    }

    /**
     * Special decoding process for symbols with uniform distribution
     * 
     * @return
     * @throws IOException
     */
    public int decodeBinBypass() {
        code <<= 1;

        --nBitsPending;
        if (nBitsPending <= 0)
            readOneByte();

        int tmp = code - (range << 8);
        if (tmp < 0) {
//            System.out.println("CABAC BIT [-1]: 0");
            return 0;
        } else {
//            System.out.println("CABAC BIT [-1]: 1");
            code = tmp;
            return 1;
        }
    }

    /**
     * Shifts the current interval to either 1/2 or 0 (code = (code << 1) &
     * 0x1ffff) and scales it by 2 (range << 1).
     * 
     * Reads new byte from the input stream into code value if there are no more
     * bits pending
     * 
     * @throws IOException
     */
    private void renormalize() {
        while (range < 256) {
            range <<= 1;
            code <<= 1;
            code &= 0x1ffff;

            --nBitsPending;
            if (nBitsPending <= 0)
                readOneByte();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy