예제 #1
0
        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);
        }
예제 #2
0
        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);
                    }
                }
            }
        }
예제 #3
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();
                }
            }
        }