package org.jcodec.codecs.h264.decode;
import org.jcodec.codecs.h264.H264Const;
import org.jcodec.codecs.h264.decode.aso.Mapper;
import org.jcodec.codecs.h264.io.model.SliceHeader;
import org.jcodec.common.model.Picture8Bit;
/**
* A decoder for I16x16 macroblocks
*
* @author The JCodec project
*/
public class MBlockDecoderIntraNxN extends MBlockDecoderBase {
private Mapper mapper;
private Intra8x8PredictionBuilder prediction8x8Builder;
public MBlockDecoderIntraNxN(Mapper mapper, SliceHeader sh, DeblockerInput di, int poc,
DecoderState decoderState) {
super(sh, di, poc, decoderState);
this.mapper = mapper;
this.prediction8x8Builder = new Intra8x8PredictionBuilder();
}
public void decode(MBlock mBlock, Picture8Bit mb) {
int mbX = mapper.getMbX(mBlock.mbIdx);
int mbY = mapper.getMbY(mBlock.mbIdx);
int mbAddr = mapper.getAddress(mBlock.mbIdx);
boolean leftAvailable = mapper.leftAvailable(mBlock.mbIdx);
boolean topAvailable = mapper.topAvailable(mBlock.mbIdx);
boolean topLeftAvailable = mapper.topLeftAvailable(mBlock.mbIdx);
boolean topRightAvailable = mapper.topRightAvailable(mBlock.mbIdx);
if (mBlock.cbpLuma() > 0 || mBlock.cbpChroma() > 0) {
s.qp = (s.qp + mBlock.mbQPDelta + 52) % 52;
}
di.mbQps[0][mbAddr] = s.qp;
residualLuma(mBlock, leftAvailable, topAvailable, mbX, mbY);
if (!mBlock.transform8x8Used) {
for (int i = 0; i < 16; i++) {
int blkX = (i & 3) << 2;
int blkY = i & ~3;
int bi = H264Const.BLK_INV_MAP[i];
boolean trAvailable = ((bi == 0 || bi == 1 || bi == 4) && topAvailable)
|| (bi == 5 && topRightAvailable) || bi == 2 || bi == 6 || bi == 8 || bi == 9 || bi == 10
|| bi == 12 || bi == 14;
Intra4x4PredictionBuilder.predictWithMode(mBlock.lumaModes[bi], mBlock.ac[0][bi],
blkX == 0 ? leftAvailable : true, blkY == 0 ? topAvailable : true, trAvailable, s.leftRow[0],
s.topLine[0], s.topLeft[0], (mbX << 4), blkX, blkY, mb.getPlaneData(0));
}
} else {
for (int i = 0; i < 4; i++) {
int blkX = (i & 1) << 1;
int blkY = i & 2;
boolean trAvailable = (i == 0 && topAvailable) || (i == 1 && topRightAvailable) || i == 2;
boolean tlAvailable = i == 0 ? topLeftAvailable : (i == 1 ? topAvailable : (i == 2 ? leftAvailable
: true));
prediction8x8Builder.predictWithMode(mBlock.lumaModes[i], mBlock.ac[0][i],
blkX == 0 ? leftAvailable : true, blkY == 0 ? topAvailable : true, tlAvailable, trAvailable,
s.leftRow[0], s.topLine[0], s.topLeft[0], (mbX << 4), blkX << 2, blkY << 2, mb.getPlaneData(0));
}
}
decodeChroma(mBlock, mbX, mbY, leftAvailable, topAvailable, mb, s.qp);
di.mbTypes[mbAddr] = mBlock.curMbType;
di.tr8x8Used[mbAddr] = mBlock.transform8x8Used;
MBlockDecoderUtils.collectChromaPredictors(s, mb, mbX);
MBlockDecoderUtils.saveMvsIntra(di, mbX, mbY);
MBlockDecoderUtils.saveVectIntra(s, mapper.getMbX(mbAddr));
}
}