public CabacSliceData(INalUnitReader reader, IState readerState)
        {
            _reader        = reader;
            _readerState   = readerState;
            _sliceState    = reader.State.SliceState;
            _pictureState  = _sliceState.PictureState;
            _sequenceState = _pictureState.SequenceState;
            _unavailableMacroblockState = _sliceState.IntraCoded
                                                        ? MacroblockState.UnavailableIntraCoded
                                                        : MacroblockState.UnavailableInterCoded;
            _macroblockStates  = new MacroblockState[PicSizeInMbs];
            _motionFieldL0     = IsList0Predicted ? new MotionField(_sliceState) : null;
            _motionFieldL1     = IsList1Predicted ? new MotionField(_sliceState) : null;
            _subMbTypes        = new ISubMacroblockType[4];
            _arithmeticDecoder = new ArithmeticDecoder(reader);

            for (int i = 0; i < _macroblockStates.Length; i++)
            {
                _macroblockStates[i] = _unavailableMacroblockState;
            }

            MbToSliceGroupMap = _mbToSliceGroup.CreateMacroBlockToSliceGroupMap(_sliceState);
        }
        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
        }