private void mvZero(Context context, PictureHeader ph, MPEGPred pred, int mbX, int mbY, int[][] mbPix) { if (ph.picture_coding_type == PictureHeader.PredictiveCoded) { pred.predict16x16NoMV(refFrames[0], mbX << 4, mbY << 4, ph.pictureCodingExtension == null ? PictureCodingExtension.Frame : ph.pictureCodingExtension.picture_structure, 0, mbPix); } else { int[][] pp = mbPix; if (context.lastPredB.macroblock_motion_backward == 1) { pred.predict16x16NoMV(refFrames[0], mbX << 4, mbY << 4, ph.pictureCodingExtension == null ? PictureCodingExtension.Frame : ph.pictureCodingExtension.picture_structure, 1, pp); pp = new int[][] { new int[mbPix[0].Length], new int[mbPix[1].Length], new int[mbPix[2].Length] }; } if (context.lastPredB.macroblock_motion_forward == 1) { pred.predict16x16NoMV(refFrames[1], mbX << 4, mbY << 4, ph.pictureCodingExtension == null ? PictureCodingExtension.Frame : ph.pictureCodingExtension.picture_structure, 0, pp); if (mbPix != pp) { avgPred(mbPix, pp); } } } }
public void decodeSlice(PictureHeader ph, int verticalPos, Context context, int[][] buf, BitReader ing, int vertOff, int vertStep) { int stride = context.codedWidth; resetDCPredictors(context, ph); int mbRow = verticalPos - 1; if (sh.vertical_size > 2800) { mbRow += (ing.readNBit(3) << 7); } if (sh.sequenceScalableExtension != null && sh.sequenceScalableExtension.scalable_mode == SequenceScalableExtension.DATA_PARTITIONING) { int priorityBreakpoint = ing.readNBit(7); } int qScaleCode = ing.readNBit(5); if (ing.read1Bit() == 1) { int intraSlice = ing.read1Bit(); ing.skip(7); while (ing.read1Bit() == 1) { ing.readNBit(8); } } MPEGPred pred = new MPEGPred(ph.pictureCodingExtension != null ? ph.pictureCodingExtension.f_code : new int[][] { new int[] { ph.forward_f_code, ph.forward_f_code }, new int[] { ph.backward_f_code, ph.backward_f_code } }, sh.sequenceExtension != null ? sh.sequenceExtension.chroma_format : SequenceExtension.Chroma420, ph.pictureCodingExtension != null && ph.pictureCodingExtension.top_field_first == 0 ? false : true); int[] ctx = new int[] { qScaleCode }; for (int prevAddr = mbRow * context.mbWidth - 1; ing.checkNBit(23) != 0;) { // TODO: decode skipped!!! prevAddr = decodeMacroblock(ph, context, prevAddr, ctx, buf, stride, ing, vertOff, vertStep, pred); context.mbNo++; } }
public int decodeMacroblock(PictureHeader ph, Context context, int prevAddr, int[] qScaleCode, int[][] buf, int stride, BitReader bits, int vertOff, int vertStep, MPEGPred pred) { int mbAddr = prevAddr; while (bits.checkNBit(11) == 0x8) { bits.skip(11); mbAddr += 33; } mbAddr += MPEGConst.vlcAddressIncrement.readVLC(bits) + 1; int chromaFormat = SequenceExtension.Chroma420; if (sh.sequenceExtension != null) { chromaFormat = sh.sequenceExtension.chroma_format; } for (int i = prevAddr + 1; i < mbAddr; i++) { int[][] predFwda = new int[][] { new int[256], new int[1 << (chromaFormat + 5)], new int[1 << (chromaFormat + 5)] }; int mbXa = i % context.mbWidth; int mbYa = i / context.mbWidth; if (ph.picture_coding_type == PictureHeader.PredictiveCoded) { pred.reset(); } mvZero(context, ph, pred, mbXa, mbYa, predFwda); put(predFwda, buf, stride, chromaFormat, mbXa, mbYa, context.codedWidth, context.codedHeight >> vertStep, vertOff, vertStep); } VLC vlcMBTypea = MPEGConst.vlcMBType(ph.picture_coding_type, sh.sequenceScalableExtension); nVideo.Codecs.MPEG12.MPEGConst.MBType[] mbTypeVal = MPEGConst.mbTypeVal(ph.picture_coding_type, sh.sequenceScalableExtension); nVideo.Codecs.MPEG12.MPEGConst.MBType mbType = mbTypeVal[vlcMBTypea.readVLC(bits)]; if (mbType.macroblock_intra != 1 || (mbAddr - prevAddr) > 1) { resetDCPredictors(context, ph); } int spatial_temporal_weight_code = 0; if (mbType.spatial_temporal_weight_code_flag == 1 && ph.pictureSpatialScalableExtension != null && ph.pictureSpatialScalableExtension.spatial_temporal_weight_code_table_index != 0) { spatial_temporal_weight_code = bits.readNBit(2); } int motion_type = -1; if (mbType.macroblock_motion_forward != 0 || mbType.macroblock_motion_backward != 0) { if (ph.pictureCodingExtension == null || ph.pictureCodingExtension.picture_structure == PictureCodingExtension.Frame && ph.pictureCodingExtension.frame_pred_frame_dct == 1) { motion_type = 2; } else { motion_type = bits.readNBit(2); } } int dctType = 0; if (ph.pictureCodingExtension != null && ph.pictureCodingExtension.picture_structure == PictureCodingExtension.Frame && ph.pictureCodingExtension.frame_pred_frame_dct == 0 && (mbType.macroblock_intra != 0 || mbType.macroblock_pattern != 0)) { dctType = bits.read1Bit(); } // buf[3][mbAddr] = dctType; if (mbType.macroblock_quant != 0) { qScaleCode[0] = bits.readNBit(5); } bool concealmentMv = ph.pictureCodingExtension != null && ph.pictureCodingExtension.concealment_motion_vectors != 0; int[][] predFwd = null; int mbX = mbAddr % context.mbWidth; int mbY = mbAddr / context.mbWidth; if (mbType.macroblock_intra == 1) { if (concealmentMv) { // TODO read consealment vectors } else { pred.reset(); } } else if (mbType.macroblock_motion_forward != 0) { int refIdx = ph.picture_coding_type == PictureHeader.PredictiveCoded ? 0 : 1; predFwd = new int[][] { new int[256], new int[1 << (chromaFormat + 5)], new int[1 << (chromaFormat + 5)] }; if (ph.pictureCodingExtension == null || ph.pictureCodingExtension.picture_structure == PictureCodingExtension.Frame) { pred.predictInFrame(refFrames[refIdx], mbX << 4, mbY << 4, predFwd, bits, motion_type, 0, spatial_temporal_weight_code); } else { if (ph.picture_coding_type == PictureHeader.PredictiveCoded) { pred.predictInField(refFields, mbX << 4, mbY << 4, predFwd, bits, motion_type, 0, ph.pictureCodingExtension.picture_structure - 1); } else { pred.predictInField(new Picture[] { refFrames[refIdx], refFrames[refIdx] }, mbX << 4, mbY << 4, predFwd, bits, motion_type, 0, ph.pictureCodingExtension.picture_structure - 1); } } } else if (ph.picture_coding_type == PictureHeader.PredictiveCoded) { predFwd = new int[][] { new int[256], new int[1 << (chromaFormat + 5)], new int[1 << (chromaFormat + 5)] }; pred.reset(); mvZero(context, ph, pred, mbX, mbY, predFwd); } int[][] predBack = null; if (mbType.macroblock_motion_backward != 0) { predBack = new int[][] { new int[256], new int[1 << (chromaFormat + 5)], new int[1 << (chromaFormat + 5)] }; if (ph.pictureCodingExtension == null || ph.pictureCodingExtension.picture_structure == PictureCodingExtension.Frame) { pred.predictInFrame(refFrames[0], mbX << 4, mbY << 4, predBack, bits, motion_type, 1, spatial_temporal_weight_code); } else { pred.predictInField(new Picture[] { refFrames[0], refFrames[0] }, mbX << 4, mbY << 4, predBack, bits, motion_type, 1, ph.pictureCodingExtension.picture_structure - 1); } } context.lastPredB = mbType; int[][] pp = mbType.macroblock_intra == 1 ? new int[][] { new int[256], new int[1 << (chromaFormat + 5)], new int[1 << (chromaFormat + 5)] } : buildPred(predFwd, predBack); //if (mbType.macroblock_intra != 0 && concealmentMv) //Assert.assertEquals(1, bits.read1Bit()); // Marker int cbp = mbType.macroblock_intra == 1 ? 0xfff : 0; if (mbType.macroblock_pattern != 0) { cbp = readCbPattern(bits); } VLC vlcCoeff = MPEGConst.vlcCoeff0; if (ph.pictureCodingExtension != null && mbType.macroblock_intra == 1 && ph.pictureCodingExtension.intra_vlc_format == 1) { vlcCoeff = MPEGConst.vlcCoeff1; } int[] qScaleTab = ph.pictureCodingExtension != null && ph.pictureCodingExtension.q_scale_type == 1 ? MPEGConst.qScaleTab2 : MPEGConst.qScaleTab1; int qScale = qScaleTab[qScaleCode[0]]; int intra_dc_mult = 8; if (ph.pictureCodingExtension != null) { intra_dc_mult = 8 >> ph.pictureCodingExtension.intra_dc_precision; } int blkCount = 6 + (chromaFormat == SequenceExtension.Chroma420 ? 0 : (chromaFormat == SequenceExtension.Chroma422 ? 2 : 6)); int[] block = new int[64]; // System.out.print(mbAddr + ": "); for (int i = 0, cbpMask = 1 << (blkCount - 1); i < blkCount; i++, cbpMask >>= 1) { if ((cbp & cbpMask) == 0) { continue; } int[] qmat = context.qMats[(i >= 4 ? 1 : 0) + (mbType.macroblock_intra << 1)]; if (mbType.macroblock_intra == 1) { blockIntra(bits, vlcCoeff, block, context.intra_dc_predictor, i, context.scan, sh.hasExtensions() || ph.hasExtensions() ? 12 : 8, intra_dc_mult, qScale, qmat); } else { blockInter(bits, vlcCoeff, block, context.scan, sh.hasExtensions() || ph.hasExtensions() ? 12 : 8, qScale, qmat); } mapBlock(block, pp[MPEGConst.BLOCK_TO_CC[i]], i, dctType, chromaFormat); } put(pp, buf, stride, chromaFormat, mbX, mbY, context.codedWidth, context.codedHeight >> vertStep, vertOff, vertStep); return(mbAddr); }
public MPEGPred(MPEGPred other) { this.fCode = other.fCode; this.chromaFormat = other.chromaFormat; this.topFieldFirst = other.topFieldFirst; }