/// <summary>
        /// This method looks for the beginning of an MPEG-4 header and if one is found it will parse it
        /// by calling Parser.Parse().
        /// </summary>
        override public IDataBlock DetectData(IDataReader dataReader, IDataBlockBuilder dataBlockBuilder, IScanContext context)
        {
            if (ReferenceHeaders != null)
            {
                var referenceHeaders = new Dictionary <IDataPacket, VideoObjectLayer>();
                foreach (IReferenceHeader header in ReferenceHeaders)
                {
                    IInputFile headerFile = context.CreateReferenceHeaderFile(header);
                    using (var parser = new Mpeg4Parser(new BitStreamDataReader(headerFile.CreateDataReader())))
                    {
                        Mpeg4Header root;
                        while (parser.ParseRoot(root = new Mpeg4Header(context.Detectors), parser.Length))
                        {
                            VideoObjectLayer vol = root.FindChild(Mpeg4HeaderName.VideoObjectLayer, true) as VideoObjectLayer;
                            if (vol != null)
                            {
                                referenceHeaders[headerFile.CreateDataPacket()] = vol;
                            }
                        }
                    }
                }

                context.ReferenceHeader = referenceHeaders;
            }

            return(Carve(dataReader, dataBlockBuilder, context));
        }
        /// <summary>
        /// This is a layer containing a fixed number of macroblocks in the VOP.
        /// Which macroblocks which belong to each gob can be determined by
        /// gob_number and num_macroblocks_in_gob.
        /// Remark: only used by short video
        /// </summary>
        private bool GobLayer(Mpeg4Parser parser, VideoObjectLayer VOL, ref int gob_number, ref uint rowNum, ref uint colNum, bool cpm, uint numRowsInGob, uint numGobsInVop)
        {
            //bool gob_header_empty = true;
            if (gob_number != 0)
            {
                if (parser.ShowBits(17) == GobResyncMarker)
                {
                    //gob_header_empty = false;

                    parser.FlushBits(17);

                    // Group Number (GN) (5 bits)
                    gob_number = (int)parser.GetBits(5);

                    // check gob_number is valid
                    if (gob_number > numGobsInVop)
                    {
#if DEBUG
                        Debug.WriteLineIf(_mpeg4H263DebugInfo, "H263 GOB number is invalid.", Mpeg4H263);
#endif // DEBUG
                        return(false);
                    }

                    // GOB Sub-Bitstream Indicator (GSBI) (2 bits)
                    // A fixed length codeword of 2 bits that is only present if CPM is "1" in the picture header.
                    if (cpm)
                    {
                        /*byte gobSubBitstreamIndicator = (byte)*/ parser.GetBits(2);
                    }

                    // GOB Frame ID (GFID) (2 bits)
                    // GFID shall have the same value in every GOB (or slice) header
                    // of a given picture.
                    parser.GetBits(2);

                    // Quantizer Information (GQUANT) (5 bits)
                    _quantScale = parser.GetBits(5);

                    rowNum = (uint)(gob_number * numRowsInGob);
                    colNum = 0;
                }
            }

            for (int i = 0; i < _numMacroblocksInGob; i++)
            {
                if (!HandleMacroBlock(parser, VOL, ref colNum, ref rowNum))
                {
                    if (gob_number == 0)
                    {
#if DEBUG
                        Debug.WriteLineIf(_mpeg4H263DebugInfo, "H263 GOB number is 0.", Mpeg4H263);
#endif // DEBUG
                        return(false);
                    }
                    else
                    {
                        //break;
                        return(true);
                    }
                }
            }
            if (parser.ShowBits(17) != GobResyncMarker &&
                parser.ShowNextBitsByteAligned(17) == GobResyncMarker)
            {
                while (!parser.ByteAligned)
                {
                    if (!parser.GetZeroBit())
                    {
                        return(false);
                    }
                }
            }
            gob_number++;
            return(true);
        }
        public override bool Parse(Mpeg4Parser parser)
        {
            if (!base.Parse(parser))
            {
                return(false);
            }

            VideoObjectLayer VOL = new VideoObjectLayer(Parent as Mpeg4Header, true);

            VOL.Parse(parser);

            _fcodeForward = 1;

            Attributes.Add(new FormattedAttribute <Attribute, bool>(Attribute.ShortVideoHeader, true));

            // Get the Temporal Reference (TR)
            this.TemporalReference = (byte)parser.GetBits(8, Attribute.TemporalReference);

            // Get the Type Information (PTYPE) (Variable Length)
            if (!parser.GetMarkerBit())                 // PTYPE, bit 1. First bit must always be '1',
            {                                           // in order to avoid start code emulation.
#if DEBUG
                //long offset = parser.GetDataPacket(parser._dataReader.BytePosition, 1).StartOffset;
                //string message = string.Format(CultureInfo.CurrentCulture, "Offset: 0x{0}; First bit of PTYPE is '0', it must always be '1'.", offset.ToString("X", CultureInfo.CurrentCulture));
                //Debug.WriteLineIf(_mpeg4H263DebugInfo, message, Mpeg4H263);
#endif // DEBUG
                return(false);
            }
            // The second bit must always be '0', for distinction with ITU-T Rec. H.261.
            if (!parser.GetZeroBit())             // PTYPE, bit 2
            {
#if DEBUG
                Debug.WriteLineIf(_mpeg4H263DebugInfo, "Second bit of PTYPE is '1', it must always be '0'.", Mpeg4H263);
#endif // DEBUG
                return(false);
            }
            /*bool splitScreenIndicator = */ parser.GetBit();           // PTYPE, bit 3
            /*bool documentCameraIndicator = */ parser.GetBit();        // PTYPE, bit 4
            /*bool fullPictureFreezeRelease = */ parser.GetBit();       // PTYPE, bit 5
            byte sourceFormat = (byte)parser.GetBits(3);                // PTYPE, bit 6-8
            Attributes.Add(new FormattedAttribute <Attribute, string>(Attribute.PTypeSourceFormat, Enum.GetName(typeof(PTypeSourceFormat), sourceFormat)));

            bool extendedPType = (sourceFormat == (byte)PTypeSourceFormat.ExtendedPType);
            if (sourceFormat == (byte)PTypeSourceFormat.Forbidden)
            {
#if DEBUG
                Debug.WriteLineIf(_mpeg4H263DebugInfo, "The source format has the forbidden value of '0'.", Mpeg4H263);
#endif // DEBUG
                return(false);
            }
            H263PictureTypeCode pictureCodingType    = H263PictureTypeCode.Invalid;
            bool optionalPBFramesMode                = false;
            bool optionalCustomPictureClockFrequency = false;
            bool cpm = false;

            CustomPictureFormat customPictureFormat = null;

            if (!extendedPType)
            {
                pictureCodingType = parser.GetBit() ? H263PictureTypeCode.P_Picture : H263PictureTypeCode.I_Picture;                    // PTYPE, bit 9
                _codingType       = (byte)pictureCodingType;
                Attributes.Add(new FormattedAttribute <Attribute, string>(Attribute.CodingType, Enum.GetName(typeof(H263PictureTypeCode), _codingType)));

                /*bool optionalUnrestrictedMotionVectorMode = */ parser.GetBit();    // PTYPE, bit 10
                /*bool optionalSyntaxBasedArithmeticCodingMode = */ parser.GetBit(); // PTYPE, bit 11
                /*bool optionalAdvancedPredictionMode = */ parser.GetBit();          // PTYPE, bit 12
                optionalPBFramesMode = parser.GetBit();                              // PTYPE, bit 13

                // If bit 9 is set to 0, bit 13 shall be set to 0 as well
                if (pictureCodingType == H263PictureTypeCode.I_Picture && optionalPBFramesMode)
                {
#if DEBUG
                    Debug.WriteLineIf(_mpeg4H263DebugInfo, "Bit 9 of PTYPE is '0', and bit 13 is '1', while bit 13 should be '0'.", Mpeg4H263);
#endif // DEBUG
                    return(false);
                }
            }
            else            // SourceFormat == SourceFormat.ExtendedPType
            {               // Plus PTYPE (PLUSPTYPE) (Variable Length; 12 or 30 bits)
                            // Update Full Extended PTYPE (UFEP) (3 bits)
                            // Values of UFEP other than "000" and "001" are reserved
                byte updateFullExtendedPType = (byte)parser.GetBits(3);

                //PlusPTypeSourceFormat plusPTypeSourceFormat = PlusPTypeSourceFormat.Invalid;
                bool optionalUnrestrictedMotionVector  = false;
                bool optionalSliceStructured           = false;
                bool optionalReferencePictureSelection = false;
                if (updateFullExtendedPType == 1)
                {                                           // The Optional Part of PLUSPTYPE (OPPTYPE) (18 bits)
                                                            // overwrite sourceFormat variable
                    sourceFormat = (byte)parser.GetBits(3); // bit 1-3
                    Attributes.Add(new FormattedAttribute <Attribute, string>(Attribute.PlusPTypeSourceFormat, Enum.GetName(typeof(PlusPTypeSourceFormat), (sourceFormat == 7) ? (byte)0 /* enum values 0 and 7 are both 'Reserved' */: sourceFormat)));

                    optionalCustomPictureClockFrequency = parser.GetBit();                  // bit 4 (PCF)
                    optionalUnrestrictedMotionVector    = parser.GetBit();                  // bit 5 (UMV)
                    /*bool optionalSyntaxBasedArithmeticCoding = */ parser.GetBit();        // bit 6 (SAC)
                    /*bool optionalAdvancedPrediction = */ parser.GetBit();                 // bit 7 (AP)
                    /*bool optionalAdvancedIntraCoding = */ parser.GetBit();                // bit 8 (AIC)
                    /*bool optionalDeblockingFilter = */ parser.GetBit();                   // bit 9 (DF)
                    optionalSliceStructured           = parser.GetBit();                    // bit 10 (SS)
                    optionalReferencePictureSelection = parser.GetBit();                    // bit 11 (RPS)
                    /*bool optionalIndependentSegmentDecoding = */ parser.GetBit();         // bit 12 (ISD)
                    /*bool optionalAlternativeInterVariableLengthCode = */ parser.GetBit(); // bit 13 (AIV)
                    _optionalModifiedQuantization = parser.GetBit();                        // bit 14 (MQ)

                    if (!parser.GetOneBit())                                                // bit 15 should be "1" to prevent start code emulation
                    {
#if DEBUG
                        Debug.WriteLineIf(_mpeg4H263DebugInfo, "Bit 15 of PLUSPTYPE is '0' but should be '1'.", Mpeg4H263);
#endif // DEBUG
                        return(false);
                    }

                    if (parser.GetBits(3) != 0)                         // bit 16-18 shall be equal to "0"
                    {
#if DEBUG
                        Debug.WriteLineIf(_mpeg4H263DebugInfo, "Bit 16-18 of PLUSPTYPE are != '0' but shall be equal to '0'.", Mpeg4H263);
#endif // DEBUG
                        return(false);
                    }
                }

                // The mandatory part of PLUSPTYPE (MPPTYPE) (9 bits)
                pictureCodingType = (H263PictureTypeCode)parser.GetBits(3);                 // bits 1-3
                _codingType       = (byte)pictureCodingType;
                Attributes.Add(new FormattedAttribute <Attribute, string>(Attribute.CodingType, Enum.GetName(typeof(H263PictureTypeCode), (_codingType == 7) ? (byte)6 /* enum values 6 and 7 are both 'Reserved' */: _codingType)));

                bool optionalReferencePictureResamplingMode = parser.GetBit(); // bit 4 (RPR)
                bool optionalReducedResolutionUpdateMode    = parser.GetBit(); // bit 5 (RRU)

                bool roundingType = parser.GetBit();                           // bit 6 (RTYPE)

                // bit 6 can be set to "1" only when bits 1-3 indicate P-picture, Improved PB-frame or EP-frame
                if (roundingType &&
                    !(pictureCodingType == H263PictureTypeCode.P_Picture ||
                      pictureCodingType == H263PictureTypeCode.ImprovedPBFrame ||
                      pictureCodingType == H263PictureTypeCode.EP_Picture))
                {
#if DEBUG
                    Debug.WriteLineIf(_mpeg4H263DebugInfo, "Bit 6 of PLUSPTYPE can only be set to '1' when bits 1-3 indicate P-picture, Improved PB-frame or EP-frame.", Mpeg4H263);
#endif // DEBUG
                    return(false);
                }

                // Read two reserved bits
                // Shall be equal to "0"
                if (parser.GetBits(2) != 0)                     // bit 7 and 8
                {
#if DEBUG
                    Debug.WriteLineIf(_mpeg4H263DebugInfo, "The reserved bits 7 and 8 of PLUSPTYPE are != '0', but should be '0'.", Mpeg4H263);
#endif // DEBUG
                    return(false);
                }

                // Bit 9 must be equal to "1" to prevent start code emulation
                if (!parser.GetOneBit())                        // bit 9
                {
#if DEBUG
                    Debug.WriteLineIf(_mpeg4H263DebugInfo, "Bit 9 of PLUSPTYPE is '0' but must be '1'.", Mpeg4H263);
#endif // DEBUG
                    return(false);
                }

                // If the picture type is INTRA or EI, updateFullExtendedPType shall be set to "001".
                if ((pictureCodingType == H263PictureTypeCode.I_Picture || pictureCodingType == H263PictureTypeCode.EI_Picture) &&
                    updateFullExtendedPType != 1)
                {
#if DEBUG
                    Debug.WriteLineIf(_mpeg4H263DebugInfo, "If the picture type is INTRA or EI, updateFullExtendedPType shall be set to '001'", Mpeg4H263);
#endif // DEBUG
                    return(false);
                }

                // Continuous Presence Multipoint and Video Multiplex (CPM) (1 bit)
                // CPM follows immediately after PLUSPTYPE if PLUSPTYPE is present,
                // but follows PQUANT in the picture header if PLUSPTYPE is not present.
                // - This is the case where PLUSPTYPE is present
                cpm = ReadCpmAndPsbi(parser);

                // Custom Picture Format (CPFMT) (23 bits)
                // A fixed length codeword of 23 bits that is present only if the use of a
                // custom picture format is signalled in PLUSPTYPE and UFEP is '001'
                if (sourceFormat == (int)PlusPTypeSourceFormat.CustomSourceFormat && updateFullExtendedPType == 1)
                {
                    customPictureFormat = new CustomPictureFormat(optionalReducedResolutionUpdateMode);
                    if (!customPictureFormat.Parse(parser))
                    {
                        return(false);
                    }

                    // Extended Pixel Aspect Ratio (EPAR) (16 bits)
                    if (customPictureFormat.PixelAspectRatioCode == 15 /*Extended PAR*/)
                    {
                        // The natural binary representation of the PAR width
                        byte parWidth = (byte)parser.GetBits(8);                                // bit 1-8
                        // PAR Width: "0" is forbidden.
                        if (parWidth == 0)
                        {
                            return(false);
                        }
                        // The natural binary representation of the PAR height.
                        byte parHeight = (byte)parser.GetBits(8);                               // bit 9-16
                        // PAR Height: "0" is forbidden.
                        if (parHeight == 0)
                        {
                            return(false);
                        }
                    }
                }

                // Custom Picture Clock Frequency Code (CPCFC) (8 bits)
                // A fixed length codeword of 8 bits that is present only if PLUSPTYPE is present
                // and UFEP is 001 and a custom picture clock frequency is signalled in PLUSPTYPE.
                if (updateFullExtendedPType == 1 && optionalCustomPictureClockFrequency)
                {
                    // Clock Conversion Code: "0" indicates a clock conversion factor of 1000 and
                    // "1" indicates 1001
                    /*bool clockConversionCode = */ parser.GetBit();                    // bit 1

                    // Bits 2-8
                    // Clock Divisor: "0" is forbidden. The natural binary representation of the value
                    // of the clock divisor.
                    byte clockDivisor = (byte)parser.GetBits(7);                        // bit 2-8
                    if (clockDivisor == 0)
                    {
                        return(false);
                    }
                }

                // Extended Temporal Reference (ETR) (2 bits)
                // A fixed length codeword of 2 bits which is present only if a custom picture clock frequency is in
                // use (regardless of the value of UFEP). It is the two MSBs of the 10-bit Temporal Reference (TR).
                if (optionalCustomPictureClockFrequency)
                {
                    /*byte extendedTemporalReference = (byte)*/ parser.GetBits(2);                      // bit 1-2
                }

                // Unlimited Unrestricted Motion Vectors Indicator (UUI) (Variable length)
                // A variable length codeword of 1 or 2 bits that is present only if the
                // optional Unrestricted Motion Vector mode is indicated in PLUSPTYPE and UFEP is 001.
                if (updateFullExtendedPType == 1 && optionalUnrestrictedMotionVector)
                {
                    bool unlimitedUnrestrictedMotionVectorsIndicator = parser.GetBit();

                    if (!unlimitedUnrestrictedMotionVectorsIndicator)
                    {
                        // UUI = "01" The motion vector range is not limited except by the picture size.
                        unlimitedUnrestrictedMotionVectorsIndicator = parser.GetBit();
                        if (!unlimitedUnrestrictedMotionVectorsIndicator)
                        {
                            return(false);
                        }
                    }
                    else
                    {
                        // UUI = "1" The motion vector range is limited according to Tables D.1 and D.2.
                    }
                }

                // Slice Structured Submode bits (SSS) (2 bits)
                // A fixed length codeword of 2 bits which is present only if the optional Slice Structured mode
                // (see Annex K) is indicated in PLUSPTYPE and UFEP is 001. If the Slice Structured mode is in use
                // but UFEP is not 001, the last values sent for SSS shall remain in effect.
                if (updateFullExtendedPType == 1 && optionalSliceStructured)
                {
                    // Bit 1; "0" indicates free-running slices, "1" indicates rectangular slices
                    /*bool rectangularSlices = */ parser.GetBit();
                    // Bit 2 "0" indicates sequential order, "1" indicates arbitrary order
                    /*bool arbitrarySliceOrdering = */ parser.GetBit();
                }

                if (pictureCodingType == H263PictureTypeCode.B_Picture ||
                    pictureCodingType == H263PictureTypeCode.EI_Picture ||
                    pictureCodingType == H263PictureTypeCode.EP_Picture)
                {
                    // Enhancement Layer Number (ELNUM) (4 bits)
                    // A fixed length codeword of 4 bits which is present only if the optional Temporal, SNR,
                    // and Spatial Scalability mode is in use (regardless of the value of UFEP)
                    /*byte enhancementLayerNumber = (byte)*/ parser.GetBits(4);

                    // Reference Layer Number (RLNUM) (4 bits)
                    // A fixed length codeword of 4 bits which is present only if the optional Temporal, SNR,
                    // and Spatial Scalability mode is in use (see Annex O) and UFEP is 001.
                    if (updateFullExtendedPType == 1)
                    {
                        /*byte referenceLayerNumber = (byte)*/ parser.GetBits(4);

                        // Note that for B-pictures in an enhancement layer having temporally surrounding EI- or EP-pictures
                        // which are present in the same enhancement layer, RLNUM shall be equal to ELNUM
                        //if (pictureCodingType == H263VopType.BPicture && updateFullExtendedPType != referenceLayerNumber) return false;
                    }
                }

                // Reference Picture Selection Mode Flags (RPSMF) (3 bits)
                if (updateFullExtendedPType == 1 && optionalReferencePictureSelection)
                {
                    /*byte referencePictureSelectionModeFlags = (byte)*/ parser.GetBits(3);
                }

                if (optionalReferencePictureSelection)
                {
                    // Temporal Reference for Prediction Indication (TRPI) (1 bit)
                    // A fixed length codeword of 1 bit that is present only if the optional Reference Picture Selection
                    // mode is in use (regardless of the value of UFEP).
                    bool temporalReferenceForPredictionIndication = parser.GetBit();

                    if (temporalReferenceForPredictionIndication)
                    {
                        if (pictureCodingType == H263PictureTypeCode.I_Picture || pictureCodingType == H263PictureTypeCode.EI_Picture)
                        {
                            // TRPI shall be 0 whenever the picture header indicates an I- or EI-picture.
                            return(false);
                        }

                        // Temporal Reference for Prediction (TRP) (10 bits)
                        parser.FlushBits(10);
                    }

                    // Back-Channel message Indication (BCI) (Variable length)
                    while (parser.GetBit() == true)
                    {
                        // Back-Channel Message (BCM) (Variable length)
                        // Structure: BT URF TR ELNUMI ELNUM BCPM BSBI BEPB1 GN/MBA BEPB2 RTR BSTUF

                        // Back-channel message Type (BT) (2 bits)
                        parser.FlushBits(2);

                        // Unreliable Flag (URF) (1 bit)
                        // 0: Reliable; 1: Unreliable.
                        parser.FlushBits(1);

                        // Temporal Reference (TR) (10 bits)
                        parser.FlushBits(10);

                        // Enhancement Layer Number Indication (ELNUMI) (1 bit)
                        bool enhancementLayerNumberIndication = parser.GetBit();

                        // Enhancement Layer Number (ELNUM) (4 bits)
                        if (enhancementLayerNumberIndication)
                        {
                            parser.FlushBits(4);
                        }

                        // BCPM (1 bit)
                        bool bcpm = parser.GetBit();

                        // Back-channel Sub-Bitstream Indicator (BSBI) (2 bits)
                        if (bcpm)
                        {
                            parser.FlushBits(2);
                        }

                        // Back-channel Emulation Prevention Bit 1 (BEPB1) (1 bit)
                        // A field which is present if and only if the videomux mode is in use.
                        //if(videomux mode is in use) TODO
                        //{
                        // This field is always set to "1" to prevent a start code emulation.
                        if (!parser.GetOneBit())
                        {
                            return(false);
                        }
                        //}
                    }
                    bool bit2 = parser.GetBit();
                    if (bit2 == false)
                    {
                        return(false);                                   // If bit1 == 0, bit2 must be 1.
                    }
                }

                // Reference Picture Resampling Parameters (RPRP) (Variable length)
                if (optionalReferencePictureResamplingMode)
                {
                    ParseReferencePictureResampling(parser, pictureCodingType);
                }
            }            // SourceFormat == SourceFormat.ExtendedPType

            // Quantizer Information (PQUANT) (5 bits)
            _pQuant = parser.GetBits(5);

            // Continuous Presence Multipoint and Video Multiplex (CPM) (1 bit)
            // CPM follows immediately after PLUSPTYPE if PLUSPTYPE is present,
            // but follows PQUANT in the picture header if PLUSPTYPE is not present.
            // - This is the case where PLUSPTYPE is not present.
            if (!extendedPType)
            {
                cpm = ReadCpmAndPsbi(parser);
            }

            if (optionalPBFramesMode ||                                   // PTYPE indicates "PB-frame"
                pictureCodingType == H263PictureTypeCode.ImprovedPBFrame) //PLUSPTYPE indicates "Improved PB-frame"
            {
                // Temporal Reference for B-pictures in PB-frames (TRB) (3/5 bits)
                // TRB is present if PTYPE or PLUSPTYPE indicates "PB-frame" or "Improved PB-frame"
                //
                // The codeword is the natural binary representation of the number of nontransmitted
                // pictures plus one. It is 3 bits long for standard CIF picture clock frequency and is
                // extended to 5 bits when a custom picture clock frequency is in use. The maximum number
                // of nontransmitted pictures is 6 for the standard CIF picture clock frequency and 30 when
                // a custom picture clock frequency is used.
                byte trb = (byte)parser.GetBits((short)(optionalCustomPictureClockFrequency ? 5 : 3));
                if (trb == 0)
                {
                    return(false);
                }

                // Quantization information for B-pictures in PB-frames (DBQUANT) (2 bits)
                // DBQUANT is present if PTYPE or PLUSPTYPE indicates "PB-frame" or "Improved PB-frame"
                /*byte dbQuant = (byte)*/ parser.GetBits(2);
            }

            // PEI (1 bit) and PSUPP (0/8/16 ... bits)
            for (; ;)
            {
                // Extra Insertion Information (PEI) (1 bit)
                // A bit which when set to "1" signals the presence of the following optional data field.
                bool extraInsertionInformation = parser.GetBit();                 // 1 bit (PEI)
                // If PEI is set to "1", then 9 bits follow consisting of 8 bits of data (PSUPP)
                // and then another PEI bit to indicate if a further 9 bits follow and so on.
                if (!extraInsertionInformation)
                {
                    break;
                }
                /*byte supplementalEnhancementInformation = (byte)*/ parser.GetBits(8);                // 8 bit (PSUPP)
            }

            // Group of Blocks Layer (GOB)
            // Structure: GSTUF GBSC GN GSBI GFID GQUANT Macroblock Data

            uint numGobsInVop;
            uint numRowsInGob;

            if (customPictureFormat != null)
            {
                _vopWidth            = customPictureFormat.PixelsPerLine;
                _vopHeight           = customPictureFormat.NumberOfLines;
                numGobsInVop         = customPictureFormat.GobsInVopCount;
                _numMacroblocksInGob = customPictureFormat.MacroblocksInGobCount;
                numRowsInGob         = customPictureFormat.RowsInGobCount;
            }
            else
            {
                int sourceFormatIndex = sourceFormat - 1;

                if (sourceFormatIndex < 0 || sourceFormatIndex >= MP4H263Width.Length)
                {
                    return(false);
                }

                _vopWidth            = (uint)MP4H263Width[sourceFormatIndex];
                _vopHeight           = (uint)MP4H263Height[sourceFormatIndex];
                numGobsInVop         = (uint)MP4H263GobVop[sourceFormatIndex];
                _numMacroblocksInGob = (uint)MP4H263MbGob[sourceFormatIndex];
                numRowsInGob         = (uint)MP4H263RowGob[sourceFormatIndex];
            }

            int  gob_number = 0;
            uint rowNum     = 0;
            uint colNum     = 0;

            for (int i = 0; i < numGobsInVop; i++)
            {
                if (!GobLayer(parser, VOL, ref gob_number, ref rowNum, ref colNum, cpm, numRowsInGob, numGobsInVop))
                {
                    return(false);
                }
            }

            // Stuffing (ESTUF) (Variable length)
            // A codeword of variable length consisting of less than 8 zero-bits.
            // TODO 5.1.26

            // End Of Sequence (EOS) (22 bits)
            if (parser.ShowBits(22) == ShortVideoEndMarker)
            {
                parser.FlushBits(22);
            }

            // Stuffing (PSTUF) (Variable length)
            // A codeword of variable length consisting of less than 8 zero-bits.
            while (!parser.ByteAligned)
            {
                if (!parser.GetZeroBit())
                {
                    return(false);
                }
            }

            return(true);
        }
        public override bool Parse(Mpeg4Parser parser)
        {
            if (!base.Parse(parser))
            {
                return(false);
            }

            parser.InsertReferenceHeaderBeforeStartCode();
            parser.SeenVop = true;

            // In MPEG-4 every VOP is a child of a VOL header
            VideoObjectLayer VOL  = Vol;
            uint             code = 0;

            Attributes.Add(new FormattedAttribute <Attribute, bool>(Attribute.ShortVideoHeader, false));

            _codingType = (byte)parser.GetBits(2);
            Attributes.Add(new FormattedAttribute <Attribute, string>(Attribute.CodingType, Enum.GetName(typeof(Mpeg4VopType), _codingType)));
            int moduloTimeBase = 0;

            do
            {
                code            = (parser.GetBit() == true) ? 1U : 0U;
                moduloTimeBase += (int)code;
            } while (code > 0);

            Attributes.Add(new FormattedAttribute <Attribute, int>(Attribute.ModuloTimeBase, moduloTimeBase));

            if (!parser.GetMarkerBit())
            {
                // Does not appear to be a mp4 VOP header
                return(false);
            }

            // No VOL (Video Object Layer) header was found.
            // Parsing this VOP header beyond the marker bit above is not possible
            // without the VOL.
            // There will be a VOP created anyway. Its size will be determined by the
            // location of the next header start code. When the resulting VOP is to big,
            // it will be rejected. The downside of this solution is that other streams
            // will be taken in the resulting VOP. The good news is that there is a result
            // reported without a VOL. When the detector finds a VOL anywhere else in the
            // data, the user of Defraser can use this VOL to try to repair these VOP's.
            if (VOL == null)
            {
                if (parser.TryDefaultHeaders(vol => ParseVop(parser, vol)))
                {
                    return(true);                    // VOP successfully decoded using reference header!
                }

                // Search for the next start location

                // The max distance from the current position to the next start code
                uint maxDistanceToNextStartCode = (uint)Mpeg4Detector.Configurable[Mpeg4Detector.ConfigurationKey.VopHeaderMaxUnparsedLength];
                maxDistanceToNextStartCode += (uint)Mpeg4Detector.Configurable[Mpeg4Detector.ConfigurationKey.VopHeaderMaxOtherStreamLength];

                this.Valid = false;

                return(IsNextHeaderWithinMaximumDistance(parser, maxDistanceToNextStartCode));
            }

            return(ParseVop(parser, VOL));
        }
        private bool ParseVop(Mpeg4Parser parser, VideoObjectLayer vol)
        {
            _vopWidth          = 0;
            _vopHeight         = 0;
            _intraDcVlcThr     = 0;
            _pQuant            = 0;
            _fcodeForward      = 0;
            _fcodeBackward     = 0;
            _refSelectCode     = 0;
            _quantScale        = 0;
            _macroblockNum     = 0;
            _numBitsMacroBlock = 0;

            _rvlc = vol.UseReverseDCT;

            if (vol.VopTimeIncrementResolutionBits != 0)
            {
                /*_timeIncrement = */ parser.GetBits(vol.VopTimeIncrementResolutionBits, Attribute.TimeIncrement);
            }
            else
            {
                //AddAttributes();
                return(true);
            }

            if (!parser.GetMarkerBit())
            {
                // Does not appear to be a mp4 VOP header
                return(false);
            }
            bool coded = parser.GetBit();

            if (coded == false)
            {
                //AddAttributes();
                return(true);
            }
            if (vol.NewPredEnable)
            {
                //vop_id
                //vop_id_prediction
                // if (vop_id_prediction > 0)
                // vop_id_for_prediction;
                if (!parser.GetMarkerBit())
                {
                    // Does not appear to be a mp4 VOP header
                    return(false);
                }
            }
            if (vol.VideoShape != VideoObjectLayer.Shape.BinaryOnly && (_codingType == (int)Mpeg4VopType.P_VOP ||
                                                                        (_codingType == (int)Mpeg4VopType.S_VOP && vol.SpriteEnable == VideoObjectLayer.MP4SpriteGMC)))
            {
                parser.GetBit(Attribute.RoundingType);
            }
            if (vol.ReducedResolutionVopEnable && vol.VideoShape == VideoObjectLayer.Shape.Rectangular &&
                (_codingType == (int)Mpeg4VopType.I_VOP || _codingType == (int)Mpeg4VopType.P_VOP))
            {
                parser.GetBit(Attribute.ReducedResolution);
            }

            if (vol.VideoShape != VideoObjectLayer.Shape.Rectangular)
            {
                if (!(vol.SpriteEnable == VideoObjectLayer.MP4SpriteStatic && _codingType == (int)Mpeg4VopType.I_VOP))
                {
                    _vopWidth = parser.GetBits(13, Attribute.Width);
                    if (!parser.GetMarkerBit())
                    {
                        return(false);
                    }

                    _vopHeight = parser.GetBits(13, Attribute.Height);
                    if (!parser.GetMarkerBit())
                    {
                        return(false);
                    }

                    uint vopHorizontalMcSpatialRef = parser.GetBits(13);
                    vopHorizontalMcSpatialRef <<= (32 - 13);
                    vopHorizontalMcSpatialRef >>= (32 - 13);
                    Attributes.Add(new FormattedAttribute <Attribute, uint>(Attribute.HorizontalMcSpatialRef, vopHorizontalMcSpatialRef));
                    if (!parser.GetMarkerBit())
                    {
                        return(false);
                    }
                    uint vopVerticalMcSpatialRef = parser.GetBits(13);
                    vopVerticalMcSpatialRef <<= (32 - 13);
                    vopVerticalMcSpatialRef >>= (32 - 13);
                    Attributes.Add(new FormattedAttribute <Attribute, uint>(Attribute.VerticalMcSpatialRef, vopVerticalMcSpatialRef));
                    if (!parser.GetMarkerBit())
                    {
                        return(false);
                    }
                }
                if (vol.VideoShape != VideoObjectLayer.Shape.BinaryOnly && vol.Scalability == true && vol.EnhancementType)
                {
                    /*bool backgroundComposition = */ parser.GetBit(Attribute.BackgroundComposition);
                }
                parser.GetBit(Attribute.ChangeConvRatioDisable);
                bool vopConstantAlpha = parser.GetBit(Attribute.ConstantAlpha);
                byte vopConstantAlphaValue;
                if (vopConstantAlpha == true)
                {
                    vopConstantAlphaValue = (byte)parser.GetBits(8);
                }
                else
                {
                    vopConstantAlphaValue = 255;
                }
                Attributes.Add(new FormattedAttribute <Attribute, byte>(Attribute.ConstantAlphaValue, vopConstantAlphaValue));
            }
            if (vol.VideoShape != VideoObjectLayer.Shape.BinaryOnly)
            {
                if (!vol.ComplexityEstimationDisable)
                {
                    VideoObjectLayer.mp4_ComplexityEstimation complex;
                    vol.ComplexityEstimation(out complex);
                    if (complex.estimation_method == 0)
                    {
                        if (_codingType == (int)Mpeg4VopType.I_VOP)
                        {
                            if (complex.opaque) /*complex.dcecs_opaque =*/ parser {