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 Residual(IMacroblockType macroBlockType, int startIdx, int endIdx) { ResidualLuma(macroBlockType, startIdx, endIdx, _lumaCodedCoefficients); if (_sequenceState.IsChromaSubsampling) // Chroma format 4:2:0 or 4:2:2 { uint numSubBlocks = (4 * ChromaFormat.NumC8X8); // in 4x4 blocks if (IsChromaDcResidualPresent() && (startIdx == 0)) { for (uint iCbCr = 0; iCbCr < 2; iCbCr++) { var coeffToken = GetChromaCoeffToken(); if (coeffToken.TotalCoeff != 0) { ResidualBlockCavlc(0, (int)(numSubBlocks - 1), (int)numSubBlocks, coeffToken); } } } if (IsChromaAcResidualPresent()) { for (uint iCbCr = 0; iCbCr < 2; iCbCr++) { CodedCoefficients codedCoefficients = _chromaCodedCoefficients[iCbCr]; for (uint i = 0; i < numSubBlocks; i++) { var coeffToken = GetCoeffToken(codedCoefficients, i); if (coeffToken.TotalCoeff != 0) { ResidualBlockCavlc(Math.Max(0, (startIdx - 1)), (endIdx - 1), 15, coeffToken); } } } } else { // Clear non-zero coefficient predictions for non-coded blocks _chromaCodedCoefficients[Cb].UpdateTotalCoeff((int)_currMbAddr, 0); _chromaCodedCoefficients[Cr].UpdateTotalCoeff((int)_currMbAddr, 0); } } else if (ChromaFormat == ChromaFormat.YCbCr444) { ResidualLuma(macroBlockType, startIdx, endIdx, _chromaCodedCoefficients[0]); // Cb ResidualLuma(macroBlockType, startIdx, endIdx, _chromaCodedCoefficients[1]); // Cr } }
public CavlcSliceData(INalUnitReader reader, IState readerState) { _reader = reader; _readerState = readerState; _sliceState = reader.State.SliceState; _pictureState = _sliceState.PictureState; _sequenceState = _pictureState.SequenceState; _coeffTokenChromaDc = (ChromaFormat == ChromaFormat.YCbCr420) ? CoeffTokenChromaDc420 : CoeffTokenChromaDc422; _lumaCodedCoefficients = new CodedCoefficients(_sliceState, PicHeightInMbs, SubBlockPartition.Luma); _chromaCodedCoefficients = new CodedCoefficients[2]; _subMbTypes = new ISubMacroblockType[4]; SubBlockPartition chromaSubBlockPartition = ChromaArrayTypeSubBlockPartitions[_sequenceState.ChromaFormat.ChromaFormatIdc]; for (int i = 0; i < _chromaCodedCoefficients.Length; i++) { _chromaCodedCoefficients[i] = new CodedCoefficients(_sliceState, PicHeightInMbs, chromaSubBlockPartition); } MbToSliceGroupMap = _mbToSliceGroup.CreateMacroBlockToSliceGroupMap(_sliceState); }
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); } } } }