コード例 #1
0
        private void ResidualLuma(IMacroblockType macroBlockType, int startIdx, int endIdx, ref CodedBlockFlags codedBlockFlags, int comp)
        {
            if ((startIdx == 0) && macroBlockType.IsIntra16X16)
            {
                if (GetCodedBlockFlag(CtxBlockCatTabLuma[comp, 0], ref codedBlockFlags, 32))
                {
                    codedBlockFlags.SetCodedBlockFlag(32);

                    ResidualBlockCabac(0, 15, 16, CtxBlockCatTabLuma[comp, 0]);
                }
            }
            for (uint i8X8 = 0; i8X8 < 4; i8X8++)
            {
                if (_codedBlockPattern.IsLumaBitSet(i8X8))
                {
                    if (_mbFlags.TransformSize8X8Flag)
                    {
                        if ((ChromaFormat != ChromaFormat.YCbCr444) || GetCodedBlockFlag(CtxBlockCatTabLuma[comp, 3], ref codedBlockFlags, i8X8 + 16))
                        {
                            ResidualBlockCabac((4 * startIdx), (4 * endIdx) + 3, 64, CtxBlockCatTabLuma[comp, 3]);

                            // Update coded_block_flag prediction
                            codedBlockFlags.SetCodedBlockFlag(i8X8 + 16);
                        }
                    }
                    else
                    {
                        for (uint i4X4 = 0; i4X4 < 4; i4X4++)
                        {
                            uint ctxBlockCat = macroBlockType.IsIntra16X16 ? CtxBlockCatTabLuma[comp, 1] : CtxBlockCatTabLuma[comp, 2];
                            uint subBlkIdx   = ((i8X8 << 2) + i4X4);
                            if (GetCodedBlockFlag(ctxBlockCat, ref codedBlockFlags, subBlkIdx))
                            {
                                codedBlockFlags.SetCodedBlockFlag(subBlkIdx);

                                if (macroBlockType.IsIntra16X16)
                                {
                                    ResidualBlockCabac(Math.Max(0, (startIdx - 1)), (endIdx - 1), 15, ctxBlockCat);
                                }
                                else
                                {
                                    ResidualBlockCabac(startIdx, endIdx, 16, ctxBlockCat);
                                }
                            }
                        }
                    }
                }
            }
        }
コード例 #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 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
            }
        }
コード例 #4
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;
            }
        }
コード例 #5
0
        // 7.3.5.1 Macroblock prediction syntax
        private void MacroBlockPrediction(IMacroblockType macroBlockType)
        {
            if (macroBlockType.IsIntra4X4 || macroBlockType.IsIntra16X16)
            {
                if (macroBlockType.IsIntra4X4)
                {
                    int lumaSubBlocks = _mbFlags.TransformSize8X8Flag ? 4 : 16;
                    for (int i = 0; i < lumaSubBlocks; i++)
                    {
                        if (GetPrevIntra4X4PredModeFlag() == 0)                   // prev_intra4x4_pred_mode_flag[luma4x4BlkIdx])
                        {
                            GetRemIntra4X4PredMode();                             // rem_intra4x4_pred_mode[luma4x4BlkIdx]
                        }
                    }
                }
                if (_sequenceState.IsChromaSubsampling)
                {
                    GetIntraChromaPredMode();                     // intra_chroma_pred_mode
                }
            }
            else if (!macroBlockType.IsDirect)
            {
                uint numMbPart = macroBlockType.NumMbPart;                 // either 1 or 2
                MacroblockPartitioning macroblockPartitioning = macroBlockType.MacroblockPartitioning;

                uint referencePictureCount0 = _sliceState.ActiveReferencePictureCount0;                //defaults to _pictureState.DefaultReferencePictureCount0;
                if (HasReferencePictureIndex(referencePictureCount0))
                {
                    var referencePictureIndex = new ReferencePictureIndex(_mbStateA.RefIdxL0, _mbStateB.RefIdxL0);
                    for (uint i = 0; i < numMbPart; i++)
                    {
                        if (macroBlockType.IsList0Predicted(i))
                        {
                            uint idx = macroblockPartitioning[i].Idx;
                            if (GetReferencePicture(referencePictureCount0, referencePictureIndex.GetCtxIdxInc(idx)))                             // ref_idx_l0[ mbPartIdx ]
                            {
                                referencePictureIndex.SetNonZeroRefIdx(idx);
                            }
                        }
                    }
                    _currMbState.RefIdxL0 = referencePictureIndex.Bits;
                }

                uint referencePictureCount1 = _sliceState.ActiveReferencePictureCount1;                //defaults to _pictureState.DefaultReferencePictureCount1;
                if (HasReferencePictureIndex(referencePictureCount1))
                {
                    var referencePictureIndex = new ReferencePictureIndex(_mbStateA.RefIdxL1, _mbStateB.RefIdxL1);
                    for (uint i = 0; i < numMbPart; i++)
                    {
                        if (macroBlockType.IsList1Predicted(i))
                        {
                            uint idx = macroblockPartitioning[i].Idx;
                            if (GetReferencePicture(referencePictureCount1, referencePictureIndex.GetCtxIdxInc(idx)))                             // ref_idx_l1[ mbPartIdx ]
                            {
                                referencePictureIndex.SetNonZeroRefIdx(idx);
                            }
                        }
                    }
                    _currMbState.RefIdxL1 = referencePictureIndex.Bits;
                }

                for (uint i = 0; i < numMbPart; i++)
                {
                    if (macroBlockType.IsList0Predicted(i))
                    {
                        GetMotionVector(_motionFieldL0, macroblockPartitioning[i]);                         // mvd_l0[ i ][ 0 ][ compIdx ]
                    }
                }
                for (uint i = 0; i < numMbPart; i++)
                {
                    if (macroBlockType.IsList1Predicted(i))
                    {
                        GetMotionVector(_motionFieldL1, macroblockPartitioning[i]);                         // mvd_l1[ i ][ 0 ][ compIdx ]
                    }
                }
            }
        }
コード例 #6
0
        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);
                }
            }
        }
コード例 #7
0
        private void SubMacroBlockPrediction(IMacroblockType macroBlockType)
        {
            if (_sliceState.SliceType == SliceType.B)
            {
                for (uint mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
                {
                    uint subMbType = _reader.GetExpGolombCoded(12);                     // sub_mb_type[mbPartIdx]
                    _subMbTypes[mbPartIdx] = SubMacroblockType.GetSubMbTypeB(subMbType);
                }
            }
            else             // P or Sp
            {
                for (uint mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
                {
                    uint subMbType = _reader.GetExpGolombCoded(3);                     // sub_mb_type[mbPartIdx]
                    _subMbTypes[mbPartIdx] = SubMacroblockType.GetSubMbTypeP(subMbType);
                }
            }

            uint referencePictureCount0 = _sliceState.ActiveReferencePictureCount0;            //defaults to _pictureState.DefaultReferencePictureCount0;

            if (HasReferencePictureIndex(referencePictureCount0) && !macroBlockType.IsP8X8Ref0)
            {
                for (uint mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
                {
                    if (_subMbTypes[mbPartIdx].List0Predicted)
                    {
                        GetReferencePicture(referencePictureCount0);
                    }
                }
            }

            uint referencePictureCount1 = _sliceState.ActiveReferencePictureCount1;            //defaults to _pictureState.DefaultReferencePictureCount1;

            if (HasReferencePictureIndex(referencePictureCount1))
            {
                for (uint mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
                {
                    if (_subMbTypes[mbPartIdx].List1Predicted)
                    {
                        GetReferencePicture(referencePictureCount1);
                    }
                }
            }

            for (uint mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
            {
                ISubMacroblockType subMbType = _subMbTypes[mbPartIdx];
                if (subMbType.List0Predicted)
                {
                    for (uint subMbPartIdx = 0; subMbPartIdx < subMbType.NumSubMbPart; subMbPartIdx++)
                    {
                        GetMotionVector();                         // mvd_l0[ i ][ j ][ compIdx ]
                    }
                }
            }
            for (uint mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
            {
                ISubMacroblockType subMbType = _subMbTypes[mbPartIdx];
                if (subMbType.List1Predicted)
                {
                    for (uint subMbPartIdx = 0; subMbPartIdx < subMbType.NumSubMbPart; subMbPartIdx++)
                    {
                        GetMotionVector();                         // mvd_l1[ i ][ j ][ compIdx ]
                    }
                }
            }
        }
コード例 #8
0
        // 7.3.5.1 Macroblock prediction syntax
        private void MacroBlockPrediction(IMacroblockType macroBlockType, bool transformSize8X8Flag)
        {
            if (macroBlockType.IsIntra4X4 || macroBlockType.IsIntra16X16)
            {
                if (macroBlockType.IsIntra4X4)
                {
                    uint lumaSubBlocks = transformSize8X8Flag ? 4U : 16U;
                    for (uint i = 0; i < lumaSubBlocks; i++)
                    {
                        if (!_reader.GetBit())                         // prev_intra4x4_pred_mode_flag[luma4x4BlkIdx])
                        {
                            _reader.GetBits(3);                        // rem_intra4x4_pred_mode[luma4x4BlkIdx]
                        }
                    }
                }
                if (_sequenceState.IsChromaSubsampling)
                {
                    _reader.GetExpGolombCoded();                     // intra_chroma_pred_mode
                }
            }
            else if (!macroBlockType.IsDirect)
            {
                uint numMbPart = macroBlockType.NumMbPart;                              // either 1 or 2

                uint referencePictureCount0 = _sliceState.ActiveReferencePictureCount0; //defaults to _pictureState.DefaultReferencePictureCount0;
                if (HasReferencePictureIndex(referencePictureCount0))
                {
                    for (uint i = 0; i < numMbPart; i++)
                    {
                        if (macroBlockType.IsList0Predicted(i))
                        {
                            GetReferencePicture(referencePictureCount0);                             // ref_idx_l0[ mbPartIdx ]
                        }
                    }
                }

                uint referencePictureCount1 = _sliceState.ActiveReferencePictureCount1;                //defaults to _pictureState.DefaultReferencePictureCount1;
                if (HasReferencePictureIndex(referencePictureCount1))
                {
                    for (uint i = 0; i < numMbPart; i++)
                    {
                        if (macroBlockType.IsList1Predicted(i))
                        {
                            GetReferencePicture(referencePictureCount1);                             // ref_idx_l1[ mbPartIdx ]
                        }
                    }
                }

                for (uint i = 0; i < numMbPart; i++)
                {
                    if (macroBlockType.IsList0Predicted(i))
                    {
                        GetMotionVector();                         // mvd_l0[ i ][ 0 ][ compIdx ]
                    }
                }
                for (uint i = 0; i < numMbPart; i++)
                {
                    if (macroBlockType.IsList1Predicted(i))
                    {
                        GetMotionVector();                         // mvd_l1[ i ][ 0 ][ compIdx ]
                    }
                }
            }
        }
コード例 #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();
                }
            }
        }