private CoeffToken GetCoeffToken(CodedCoefficients codedCoefficients, uint subBlockIndex) { var nC = codedCoefficients.PredictTotalCoeff(_currMbAddr, subBlockIndex); var coeffToken = _reader.GetVlc(LookupCoeffTokenVlcTable(nC)); if (coeffToken.TotalCoeff == 255 /*invalid*/) { _readerState.Invalidate(); return(new CoeffToken(0, 0)); } codedCoefficients.UpdateTotalCoeff((int)_currMbAddr, subBlockIndex, coeffToken.TotalCoeff); return(coeffToken); }
private void ResidualLuma(IMacroblockType macroBlockType, int startIdx, int endIdx, CodedCoefficients codedCoefficients) { if ((startIdx == 0) && macroBlockType.IsIntra16X16) { var coeffTokenDc = GetCoeffToken(codedCoefficients, 0); #if DEBUG H264Debug.WriteLine(" coeff_token( luma dc )={0}", coeffTokenDc); #endif if (coeffTokenDc.TotalCoeff != 0) { ResidualBlockCavlc(0, 15, 16, coeffTokenDc); } } for (uint i8X8 = 0; i8X8 < 4; i8X8++) { if (IsLumaBitSet(i8X8)) { for (uint i4X4 = 0; i4X4 < 4; i4X4++) { uint subBlkIdx = ((i8X8 << 2) + i4X4); var coeffToken = GetCoeffToken(codedCoefficients, subBlkIdx); #if DEBUG H264Debug.WriteLine(" coeff_token={0}", coeffToken); #endif if (coeffToken.TotalCoeff != 0) { if (macroBlockType.IsIntra16X16) { ResidualBlockCavlc(Math.Max(0, (startIdx - 1)), (endIdx - 1), 15, coeffToken); } else { ResidualBlockCavlc(startIdx, endIdx, 16, coeffToken); } } } } else { // Clear non-zero coefficient predictions for non-coded blocks for (uint i4X4 = 0; i4X4 < 4; i4X4++) { codedCoefficients.UpdateTotalCoeff((int)_currMbAddr, (4 * i8X8) + i4X4, 0); } } } }
private void MacroBlockLayer() { //page 76 IMacroblockType macroBlockType = GetMacroBlockType(); #if DEBUG H264Debug.WriteLine("{0}: mb_type={1}", CurrentMbIndex, macroBlockType); H264Debug.WriteLine("ShowBits(32) = {0:x8} at {1:x8}", _reader.ShowBits(32), _reader.Position); #endif if (macroBlockType.IsIPcm) { _reader.GetPcmSamples(); _lumaCodedCoefficients.UpdateTotalCoeff((int)_currMbAddr, 16); _chromaCodedCoefficients[Cb].UpdateTotalCoeff((int)_currMbAddr, 16); _chromaCodedCoefficients[Cr].UpdateTotalCoeff((int)_currMbAddr, 16); } else { bool transform8X8ModeFlagSet = false; if (macroBlockType.NumMbPart == 4) { // Note: Only inter-coded blocks can have mb parts, in particular, // we are not currently decoding an intra-coded block! SubMacroBlockPrediction(macroBlockType); if (HasSubMbPartSizeLessThan8X8()) { transform8X8ModeFlagSet = true; // Transform 8x8 mode is not possible! } } else { bool transformSize8X8Flag = false; if (_pictureState.Transform8X8ModeFlag && macroBlockType.IsI_NxN) { transformSize8X8Flag = _reader.GetBit(); transform8X8ModeFlagSet = true; } MacroBlockPrediction(macroBlockType, transformSize8X8Flag); } if (macroBlockType.IsIntra16X16) { _codedBlockPattern = macroBlockType.CodedBlockPattern; } else { GetCodedBlockPattern(macroBlockType.IntraCoded); if (_pictureState.Transform8X8ModeFlag && !transform8X8ModeFlagSet && ((_codedBlockPattern & 15) /*luma*/ != 0) && (!macroBlockType.IsDirect || _sequenceState.Direct8X8InferenceFlag)) { _reader.GetBit(); // transform_size_8x8_flag } } if ((_codedBlockPattern != 0) || macroBlockType.IsIntra16X16) { _reader.GetSignedExpGolombCoded(_sequenceState.MinMbQpDelta, _sequenceState.MaxMbQpDelta); // mb_qp_delta Residual(macroBlockType, 0, 15); } else { UpdateSkippedMacroblockPrediction(); } } }