private void GetMotionVector(MotionField motionField, MacroblockPartition mbPart)
        {
#if DEBUG
            int dmvx = 0, dmvy = 0;
#endif
            if (_arithmeticDecoder.DecodeDecision(40 + motionField.GetCtxIdxInc(_currMbAddr, mbPart, 0)) == 1)
            {
                uint dx = GetAbsMotionVectorComponent(40);                 // dx coordinate?
                motionField.UpdateComponent(_currMbAddr, mbPart, 0, dx);
#if DEBUG
                dmvx = (_arithmeticDecoder.DecodeBypass() == 1) ? -(int)dx : (int)dx; // sign?
#else
                _arithmeticDecoder.DecodeBypass();                                    // sign
#endif
            }
            if (_arithmeticDecoder.DecodeDecision(47 + motionField.GetCtxIdxInc(_currMbAddr, mbPart, 1)) == 1)
            {
                uint dy = GetAbsMotionVectorComponent(47);                 // dy coordinate?
                motionField.UpdateComponent(_currMbAddr, mbPart, 1, dy);
#if DEBUG
                dmvy = (_arithmeticDecoder.DecodeBypass() == 1) ? -(int)dy : (int)dy; // sign?
#else
                _arithmeticDecoder.DecodeBypass();                                    // sign
#endif
            }
#if DEBUG
            H264Debug.WriteLine("   dmv={0},{1}", dmvx, dmvy);
#endif
        }
Example #2
0
        internal int PredictTotalCoeff(uint mbIndex, uint subBlockIndex)
        {
            int nTop  = GetTopNumberCoeff(mbIndex, subBlockIndex);
            int nLeft = GetLeftNumberCoeff(mbIndex, subBlockIndex);

#if DEBUG
            H264Debug.WriteLine("   * (left={0}, top={1}, nzc={2})", nLeft, nTop, TotalCoeffLookup[nLeft + nTop]);
#endif
            return(TotalCoeffLookup[nLeft + nTop]);
        }
Example #3
0
        private void GetMotionVector()
        {
#if DEBUG
            int dx = _reader.GetSignedExpGolombCoded();             // dx coordinate?
            int dy = _reader.GetSignedExpGolombCoded();             // dy coordinate?
            H264Debug.WriteLine("   dmv={0},{1}", dx, dy);
#else
            _reader.GetSignedExpGolombCoded();             // dmv(x)
            _reader.GetSignedExpGolombCoded();             // dmv(y)
#endif
        }
Example #4
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);
                    }
                }
            }
        }
        private void Residual(IMacroblockType macroBlockType, int startIdx, int endIdx)
        {
            // Special case for unavailable macroblock states of intra coded blocks in inter-coded slices
            bool b1 = macroBlockType.IntraCoded && !_sliceState.IntraCoded;
            bool b2 = _mbFlags.TransformSize8X8Flag && (ChromaFormat == ChromaFormat.YCbCr444);

            if (b1 || b2)
            {
                byte unavailableCodedBlockFlags = (byte)(macroBlockType.IntraCoded ? 0xff : 0);
                if ((b1 && ((_mbStateA.Flags & 0x40) == 0x40)) || (b2 && ((_mbStateA.Flags & 0x4) == 0)))
                {
                    _mbStateA.LumaCodedBlockFlags = unavailableCodedBlockFlags;
                    _mbStateA.CrCodedBlockFlags   = unavailableCodedBlockFlags;
                    _mbStateA.CbCodedBlockFlags   = unavailableCodedBlockFlags;
                }
                if ((b1 && ((_mbStateB.Flags & 0x40) == 0x40)) || (b2 && ((_mbStateB.Flags & 0x4) == 0)))
                {
                    _mbStateB.LumaCodedBlockFlags = unavailableCodedBlockFlags;
                    _mbStateB.CrCodedBlockFlags   = unavailableCodedBlockFlags;
                    _mbStateB.CbCodedBlockFlags   = unavailableCodedBlockFlags;
                }
            }

            var codedBlockFlags = new CodedBlockFlags(_mbStateA.LumaCodedBlockFlags, _mbStateB.LumaCodedBlockFlags);

            ResidualLuma(macroBlockType, startIdx, endIdx, ref codedBlockFlags, 0);

            _currMbState.LumaCodedBlockFlags = codedBlockFlags.Flags;

            if (_sequenceState.IsChromaSubsampling)             // Chroma format 4:2:0 or 4:2:2
            {
                if (_codedBlockPattern.IsChromaDcResidualPresent)
                {
// ReSharper disable SuggestUseVarKeywordEvident
                    int numSubBlocks = (int)(4 * ChromaFormat.NumC8X8);                     // in 4x4 blocks
// ReSharper restore SuggestUseVarKeywordEvident
                    var cbCodedBlockFlags = new CodedBlockFlags(_mbStateA.CbCodedBlockFlags, _mbStateB.CbCodedBlockFlags);
                    var crCodedBlockFlags = new CodedBlockFlags(_mbStateA.CrCodedBlockFlags, _mbStateB.CrCodedBlockFlags);

                    if (GetCodedBlockFlag(3, ref cbCodedBlockFlags, 32))
                    {
                        cbCodedBlockFlags.SetCodedBlockFlag(32);

                        ResidualBlockCabac(0, (numSubBlocks - 1), numSubBlocks, 3);
                    }
                    if (GetCodedBlockFlag(3, ref crCodedBlockFlags, 32))
                    {
                        crCodedBlockFlags.SetCodedBlockFlag(32);

                        ResidualBlockCabac(0, (numSubBlocks - 1), numSubBlocks, 3);
                    }
                    if (_codedBlockPattern.IsChromaAcResidualPresent)
                    {
                        uint cbfIndex = 16U + (uint)numSubBlocks;
                        for (uint i = 0; i < numSubBlocks; i++)
                        {
                            if (GetCodedBlockFlag(4, ref cbCodedBlockFlags, cbfIndex + i))
                            {
                                cbCodedBlockFlags.SetCodedBlockFlag(cbfIndex + i);

                                ResidualBlockCabac(Math.Max(0, (startIdx - 1)), (endIdx - 1), 15, 4);
                            }
                        }
                        for (uint i = 0; i < numSubBlocks; i++)
                        {
                            if (GetCodedBlockFlag(4, ref crCodedBlockFlags, cbfIndex + i))
                            {
                                crCodedBlockFlags.SetCodedBlockFlag(cbfIndex + i);

                                ResidualBlockCabac(Math.Max(0, (startIdx - 1)), (endIdx - 1), 15, 4);
                            }
                        }
                    }

                    _currMbState.CbCodedBlockFlags = cbCodedBlockFlags.Flags;
                    _currMbState.CrCodedBlockFlags = crCodedBlockFlags.Flags;
                }
            }
            else if (ChromaFormat == ChromaFormat.YCbCr444)
            {
#if DEBUG
                H264Debug.WriteLine("  [Cb]");
#endif
                var cbCodedBlockFlags = new CodedBlockFlags(_mbStateA.CbCodedBlockFlags, _mbStateB.CbCodedBlockFlags);
                ResidualLuma(macroBlockType, startIdx, endIdx, ref cbCodedBlockFlags, 1);

                _currMbState.CbCodedBlockFlags = cbCodedBlockFlags.Flags;

#if DEBUG
                H264Debug.WriteLine("  [Cr]");
#endif
                var crCodedBlockFlags = new CodedBlockFlags(_mbStateA.CrCodedBlockFlags, _mbStateB.CrCodedBlockFlags);
                ResidualLuma(macroBlockType, startIdx, endIdx, ref crCodedBlockFlags, 2);                 // Cr

                _currMbState.CrCodedBlockFlags = crCodedBlockFlags.Flags;
            }
        }
        private void MacroBlockLayer()
        {
            IMacroblockType macroBlockType = GetMacroblockType();

#if DEBUG
            H264Debug.WriteLine("{0}: mb_type={1}", CurrentMbIndex, macroBlockType);
#endif
            if (macroBlockType.IsIPcm)
            {
                _reader.GetPcmSamples();

                InitializeCabac();

                _currMbState = MacroblockState.Pcm;
            }
            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();

                    if (HasSubMbPartSizeLessThan8X8())
                    {
                        transform8X8ModeFlagSet = true;                         // Transform 8x8 mode is not possible!
                    }
                }
                else
                {
                    if (_pictureState.Transform8X8ModeFlag && macroBlockType.IsI_NxN)
                    {
                        GetTransformSize8X8Flag();

                        transform8X8ModeFlagSet = true;
                    }

                    MacroBlockPrediction(macroBlockType);
                }

                if (macroBlockType.IsIntra16X16)
                {
                    _codedBlockPattern = new CodedBlockPattern(macroBlockType.CodedBlockPattern);
                }
                else
                {
                    GetCodedBlockPattern();

                    if (_pictureState.Transform8X8ModeFlag && !transform8X8ModeFlagSet &&
                        _codedBlockPattern.IsLumaResidualPresent &&
                        (!macroBlockType.IsDirect || _sequenceState.Direct8X8InferenceFlag))
                    {
                        GetTransformSize8X8Flag();
                    }
                }

                _currMbState.CodedBlockPattern = _codedBlockPattern.Bits;

                if (_codedBlockPattern.IsResidualPresent || macroBlockType.IsIntra16X16)
                {
                    GetMbQpDelta();                     // mb_qp_delta
                    Residual(macroBlockType, 0, 15);
                }
            }
        }
        public void Parse()
        {
            InitializeCabac();

            _currMbAddr         = _sliceState.FirstMacroBlockInSlice * (MbAffFrameFlag ? 2U : 1U);
            MbFieldDecodingFlag = _sliceState.FieldPicFlag;             // The default for non-MBAFF frames

            bool moreDataFlag  = true;
            bool prevMbSkipped = false;

            while (_readerState.Valid && moreDataFlag)
            {
                _currMbState      = new MacroblockState();
                _mbQpDeltaNotZero = 0;

                // Load macroblock states for block A (left) and B (top)
                _mbStateA = GetMacroblockState(_sliceState.GetMbAddrA(_currMbAddr));
                _mbStateB = GetMacroblockState(_sliceState.GetMbAddrB(_currMbAddr));
                _mbFlags  = new MacroblockFlags(_mbStateA.Flags, _mbStateB.Flags);

                bool mbSkipFlag = false;
                if (!_sliceState.IntraCoded)
                {
                    mbSkipFlag = GetMbSkipFlag();                     // mb_skip_flag
                }
                if (!mbSkipFlag)
                {
                    _mbFlags.SetCodedBlockFlag();

                    if (MbAffFrameFlag && (IsFirstMacroblockInPair() || prevMbSkipped))
                    {
                        MbFieldDecodingFlag = GetMbFieldDecodingFlag();                         // is field macro block
                    }

                    MacroBlockLayer();
                }
                if (MbFieldDecodingFlag && (!MbAffFrameFlag || IsLastMacroblockInPair()))
                {
                    _mbFlags.SetFieldDecodingMode();
                }

                _currMbState.Flags             = _mbFlags.Bits;
                _macroblockStates[_currMbAddr] = _currMbState;
                _prevMbQpDeltaNotZero          = _mbQpDeltaNotZero;

                if (!_sliceState.IntraCoded)
                {
                    prevMbSkipped = mbSkipFlag;
                }
                if (!MbAffFrameFlag || IsLastMacroblockInPair())
                {
                    moreDataFlag = !GetEndOfSliceFlag();
                }
                if (moreDataFlag)
                {
                    NextMbAddress();
                }
            }
#if DEBUG
            H264Debug.WriteLine(" - Terminated ({4}) at {0} of {1} ({2}), nextBits(16)={3}",
                                _reader.Position, _reader.Length, _currMbAddr, ToBitString(_reader.ShowBits(16), 16),
                                _sliceState.SliceType.ToString());
#endif
        }
Example #8
0
        private void ResidualBlockCavlc(int startIdx, int endIdx, int maxNumCoeff, CoeffToken coeffToken)
        {
            int suffixLength = ((coeffToken.TotalCoeff > 10) && (coeffToken.TrailingOnes < 3)) ? 1 : 0;

#if DEBUG
            H264Debug.Write("   - levels=");
            if (coeffToken.TrailingOnes > 0)
            {
                uint signs = _reader.GetBits(coeffToken.TrailingOnes);                 // (n) x trailing_ones_sign_flag
                for (int i = 0; i < coeffToken.TrailingOnes; i++)
                {
                    H264Debug.Write((((signs & (1 << (coeffToken.TrailingOnes - 1 - i))) == 0) ? "1," : "-1,"));
                }
            }
#else
            _reader.GetBits(coeffToken.TrailingOnes);             // (n) x trailing_ones_sign_flag
#endif

            for (int i = coeffToken.TrailingOnes; i < coeffToken.TotalCoeff; i++)
            {
                int levelCode = GetCoefficientLevelCode(suffixLength);

                // The first non-zero coefficient after 'trailing ones' must be larger than 1,
                // unless the maximum count of trailing ones, i.e. 3, was reached.
                // This will further reduce the amount of bits required to represent a
                // coefficient level.
                if ((i == coeffToken.TrailingOnes) && (i /*trailing ones*/ < 3))
                {
                    levelCode += 2;                     // 2 instead of 1, because the lowest bit is the sign bit!
                }
#if DEBUG
                H264Debug.Write("{0},", ((levelCode % 2) == 0) ? ((levelCode + 2) >> 1) : ((-levelCode - 1) >> 1));
#endif

                // Automatically adjust the suffix length if high coefficients levels are
                // encountered, to reduce the number of bits required to represent subsequent
                // high coefficient levels.
                if (suffixLength == 0)
                {
                    suffixLength = 1;
                }
                if (suffixLength < 6)
                {
                    int absLevelMinusOne = (levelCode >> 1);
                    if (absLevelMinusOne >= (3 << (suffixLength - 1)))
                    {
                        suffixLength++;
                    }
                }
            }
#if DEBUG
            H264Debug.WriteLine();
#endif

            if (coeffToken.TotalCoeff < (endIdx - startIdx + 1))
            {
                int zerosLeft = GetTotalZeros(coeffToken.TotalCoeff, maxNumCoeff);                 // total_zeros
#if DEBUG
                H264Debug.WriteLine("   - total_zeros={0}", zerosLeft);
                H264Debug.WriteLine("ShowBits(32) = {0:x8} at {1:x8}", _reader.ShowBits(32), _reader.Position);
                H264Debug.Write("   - run_before=");
#endif
                for (int i = 0; i < (coeffToken.TotalCoeff - 1) && (zerosLeft > 0); i++)
                {
#if DEBUG
                    int runBefore = _reader.GetVlc(RunBeforeTable[Math.Min(zerosLeft, 7)]);
                    zerosLeft -= runBefore;                     // run_before
                    H264Debug.Write("{0},", runBefore);
#else
                    zerosLeft -= _reader.GetVlc(RunBeforeTable[Math.Min(zerosLeft, 7)]);                     // run_before
#endif
                }
#if DEBUG
                H264Debug.WriteLine();
#endif
            }
        }
Example #9
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();
                }
            }
        }