static private bool ParseReferencePictureResampling(Mpeg4Parser parser, H263PictureTypeCode pictureCodingType)
        {
            // Warping Displacement Accuracy (WDA) (2 bits)
            /*byte warpingDisplacementAccuracy = (byte)*/ parser.GetBits(2);

            FillModeH263 fillMode = FillModeH263.Invalid;

            // Warping parameters (Variable length)
            if (pictureCodingType == H263PictureTypeCode.P_Picture ||
                pictureCodingType == H263PictureTypeCode.B_Picture ||
                pictureCodingType == H263PictureTypeCode.ImprovedPBFrame)
            {
                // VLC-coded warping parameters
                // TODO


                // Fill Mode (FILL_MODE) (2 bits)
                fillMode = (FillModeH263)parser.GetBits(2);
            }
            else if (pictureCodingType == H263PictureTypeCode.EP_Picture)
            {
                // For an EP-picture, the fill-mode action is the same as that for
                // the reference layer, and the two fill-mode bits are not sent.
                // TODO
            }
            //TODO else if(pictureCodingType == H263VopType.

            // Fill Color Specification (Y_FILL, CB_EPB, CB_FILL, CR_EPB, CR_FILL) (26 bits)
            if (pictureCodingType != H263PictureTypeCode.EP_Picture && fillMode == FillModeH263.Color)
            {
                // Y_FILL
                parser.FlushBits(8);
                // CB_EPB
                bool cbepb = parser.GetBit();
                if (cbepb == false)
                {
                    return(false);
                }
                // CB_FILL
                parser.FlushBits(8);
                // CR_EPB
                bool crepb = parser.GetBit();
                if (crepb == false)
                {
                    return(false);
                }
                // CR_FILL
                parser.FlushBits(8);
            }

            //Resampling algorithm
            // TODO

            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);
        }
        /// <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);
        }
Esempio n. 4
0
        //private static bool HeaderIsShortVideo(ByteStreamDataReader dataReader, long offset)
        //{
        //    dataReader.Position = offset;
        //    byte[] bytes = new byte[3];
        //    dataReader.Read(bytes, 0, 3);
        //    return ((bytes[0] == 0x00) && (bytes[1] == 0x00) && ((bytes[2] & 0xFC) == 0x80));
        //}

        public override bool Parse(Mpeg4Parser parser)
        {
            if (InVop)
            {
                IsShortVideoHeader          = true;
                QuantPrecision              = 5;
                VideoShape                  = Shape.Rectangular;
                ResyncMarkerDisable         = true;
                DataPartitioned             = false;
                _reversible_vlc             = false;
                Interlaced                  = false;
                ComplexityEstimationDisable = true;
                Scalability                 = false;
                VopTimeIncrementResolution  = 30000;

                return(true);
            }

            if (!base.Parse(parser))
            {
                return(false);
            }

            if (StartCode < 0x120 || StartCode > 0x12F)
            {
                //mp4_Error("Error: Bad start code for VideoObjectLayerLayer");
                return(false);
            }

            // Found video_object_start_code
            parser.AddAttribute(new FormattedAttribute <Attribute, uint>(Attribute.ID, StartCode & 15));

            IsShortVideoHeader = false;
            parser.GetBit(Attribute.RandomAccessibleVol);

            /*byte typeIndication = (byte)*/ parser.GetBits(8, Attribute.TypeIndication);
            //if (typeIndication == FineGranularityScalable)
            //{
            //	TODO add branch for type indication value
            //}
            //else
            //{

            bool isIdentifier = parser.GetBit();

            uint verid = 0;

            if (isIdentifier == true)
            {
                verid = parser.GetBits(4);

                if ((verid != 1) && (verid != 2) && (verid != 4) && (verid != 5))
                {
                    var verIDAttribute = new FormattedAttribute <Attribute, string>(Attribute.VerID, string.Format(CultureInfo.CurrentCulture, "Invalid value found: {0}. It should be 1, 2, 4 or 5. Assuming '1'.", verid));
                    verIDAttribute.Valid = false;

                    //mp4_Error("Warning: invalid version number in VOL");
                    verid = 1;
                }
                else
                {
                    parser.AddAttribute(new FormattedAttribute <Attribute, uint>(Attribute.VerID, verid));
                }
                parser.GetBits(3, Attribute.Priority);
            }
            else
            {
                verid = 1;
            }

            byte   aspectRatioInfo = (byte)parser.GetBits(4);
            string aspectRatioName = Enum.IsDefined(typeof(PixelAspectRatio), aspectRatioInfo) ? Enum.GetName(typeof(PixelAspectRatio), aspectRatioInfo) : "Reserved";

            parser.AddAttribute(new FormattedAttribute <Attribute, string>(Attribute.AspectRatioInfo, string.Format(CultureInfo.CurrentCulture, "{0} ({1})", aspectRatioInfo.ToString(CultureInfo.CurrentCulture), aspectRatioName)));

            if (aspectRatioInfo == (uint)PixelAspectRatio.ExtentedPar)
            {
                parser.GetBits(8, Attribute.AspectRatioInfoParWidth);
                parser.GetBits(8, Attribute.AspectRatioInfoParHeight);
            }
            bool isVolControlParameters = parser.GetBit(Attribute.VolControlParameters);

            if (isVolControlParameters == true)
            {
                const int ChromaFormat420 = 1;

                uint chromaFormat = parser.GetBits(2, Attribute.ChromaFormat);

                if (chromaFormat != ChromaFormat420)
                {
                    //mp4_Error("Error: vol_control_parameters.chroma_format != 4:2:0");
                    return(false);
                }

                parser.GetBit(Attribute.LowDelay);

                bool vbvParameters = parser.GetBit(Attribute.VbvParameters);
                if (vbvParameters)
                {
                    uint bitRate = parser.GetBits(15);
                    bitRate <<= 15;

                    if (!parser.GetMarkerBit())
                    {
                        // Does not appear to be a mp4 VOL header
                        return(false);
                    }
                    //_VOLControlParameters.bit_rate += Utils.GetBits(15);
                    bitRate += parser.GetBits(15);
                    parser.AddAttribute(new FormattedAttribute <Attribute, uint>(Attribute.BitRate, bitRate));

                    if (!parser.GetMarkerBit())
                    {
                        // Does not appear to be a mp4 VOL header
                        return(false);
                    }
                    if (bitRate == 0)
                    {
                        //mp4_Error("Error: vbv_parameters bit_rate == 0");
                        return(false);
                    }
                    uint vbvBufferSize = parser.GetBits(15);
                    vbvBufferSize <<= 3;

                    if (!parser.GetMarkerBit())
                    {
                        // Does not appear to be a mp4 VOL header
                        return(false);
                    }
                    vbvBufferSize += parser.GetBits(3);
                    if (vbvBufferSize == 0)
                    {
                        //mp4_Error("Error: vbv_parameters vbv_buffer_size == 0");
                        return(false);
                    }
                    parser.AddAttribute(new FormattedAttribute <Attribute, uint>(Attribute.VbvBufferSize, vbvBufferSize));

                    uint vbvOccupancy = parser.GetBits(11);
                    vbvOccupancy <<= 15;

                    if (!parser.GetMarkerBit())
                    {
                        // Does not appear to be a mp4 VOL header
                        return(false);
                    }
                    vbvOccupancy += parser.GetBits(15);

                    if (!parser.GetMarkerBit())
                    {
                        // Does not appear to be a mp4 VOL header
                        return(false);
                    }
                }
            }
            const int ShapeExtNum = 13;

            this.VideoShape = (Shape)parser.GetBits(2);
            parser.AddAttribute(new FormattedAttribute <Attribute, string>(Attribute.Shape, string.Format(CultureInfo.CurrentCulture, "{0} ({1})", (int)VideoShape, Enum.GetName(typeof(Shape), (byte)this.VideoShape))));

            if (verid != 1 && VideoShape == Shape.Grayscale)
            {
                ShapeExtension = parser.GetBits(4, Attribute.ShapeExtension);
                if (ShapeExtension >= ShapeExtNum)
                {
                    //mp4_Error("Error: wrong value for video_object_layer_shape_extension");
                    return(false);
                }
            }
            else
            {
                ShapeExtension = ShapeExtNum;
                parser.AddAttribute(new FormattedAttribute <Attribute, uint>(Attribute.ShapeExtension, ShapeExtension));
            }
            if (!parser.GetMarkerBit())
            {
                // Does not appear to be a mp4 VOL header
                return(false);
            }
            VopTimeIncrementResolution = parser.GetBits(16, Attribute.VopTimeIncrementResolution);
            if (VopTimeIncrementResolution == 0)
            {
                //mp4_Error("Error: wrong value for vop_time_increment_resolution");
                return(false);
            }
            if (!parser.GetMarkerBit())
            {
                // Does not appear to be a mp4 VOL header
                return(false);
            }
            // define number bits in vop_time_increment_resolution
            uint numBits = VopTimeIncrementResolution - 1;
            uint i       = 0;

            do
            {
                numBits >>= 1;
                i++;
            } while (numBits > 0);
            VopTimeIncrementResolutionBits = (short)i;
            bool fixedVopRate = parser.GetBit(Attribute.FixedVopRate);

            if (fixedVopRate == true)
            {
                parser.GetBits((int)VopTimeIncrementResolutionBits, Attribute.FixedVopTimeIncrement);
            }
            if (VideoShape != Shape.BinaryOnly)
            {
                if (VideoShape == Shape.Rectangular)
                {
                    if (!parser.GetMarkerBit())
                    {
                        // Does not appear to be a mp4 VOL header
                        return(false);
                    }
                    Width = parser.GetBits(13, Attribute.Width);
                    if (!parser.GetMarkerBit() || Width == 0)
                    {
                        // Does not appear to be a mp4 VOL header
                        return(false);
                    }
                    Height = parser.GetBits(13, Attribute.Height);
                    if (!parser.GetMarkerBit() || Height == 0)
                    {
                        // Does not appear to be a mp4 VOL header
                        return(false);
                    }
                }
                Interlaced = parser.GetBit(Attribute.Interlaced);
                parser.GetBit(Attribute.ObmcDisable);
                SpriteEnable = parser.GetBits((short)(verid != 1 ? 2 : 1), Attribute.SpriteEnable);
                const int SpriteStatic = 1;
                const int SpriteGmc    = 2;
                if (SpriteEnable == SpriteStatic || SpriteEnable == SpriteGmc)
                {
                    if (SpriteEnable == SpriteStatic)
                    {
                        parser.GetBits(13, Attribute.SpriteWidth);
                        if (!parser.GetMarkerBit())
                        {
                            // Does not appear to be a mp4 VOL header
                            return(false);
                        }
                        parser.GetBits(13, Attribute.SpriteHeight);
                        if (!parser.GetMarkerBit())
                        {
                            // Does not appear to be a mp4 VOL header
                            return(false);
                        }
                        uint sprite_left_coordinate = parser.GetBits(13);
                        sprite_left_coordinate <<= (32 - 13);
                        sprite_left_coordinate >>= (32 - 13);
                        if ((sprite_left_coordinate & 1) > 0)
                        {
                            //mp4_Error("Error: sprite_left_coordinate must be divisible by 2");
                            return(false);
                        }
                        if (!parser.GetMarkerBit())
                        {
                            // Does not appear to be a mp4 VOL header
                            return(false);
                        }
                        uint sprite_top_coordinate = parser.GetBits(13);
                        sprite_top_coordinate <<= (32 - 13);
                        sprite_top_coordinate >>= (32 - 13);
                        if ((sprite_top_coordinate & 1) > 0)
                        {
                            //mp4_Error("Error: sprite_top_coordinate must be divisible by 2");
                            return(false);
                        }
                        if (!parser.GetMarkerBit())
                        {
                            // Does not appear to be a mp4 VOL header
                            return(false);
                        }
                    }
                    SpriteWarpingPoints = parser.GetBits(6, Attribute.SpriteWarpingPoints);
                    if (SpriteWarpingPoints > 4 ||
                        (SpriteWarpingPoints == 4 &&
                         SpriteEnable == SpriteGmc))
                    {
                        //mp4_Error("Error: bad no_of_sprite_warping_points");
                        return(false);
                    }
                    parser.GetBits(2, Attribute.SpriteWarpingAccuracy);
                    SpriteBrightnessChange = parser.GetBit(Attribute.SpriteBrightnessChange);
                    if (SpriteEnable == SpriteGmc)
                    {
                        if (SpriteBrightnessChange == true)
                        {
                            //mp4_Error("Error: sprite_brightness_change should be 0 for GMC sprites");
                            return(false);
                        }
                    }
                    if (SpriteEnable != SpriteGmc)
                    {
                        LowLatencySpriteEnabled = parser.GetBit(Attribute.LowLatencySpriteEnable);
                    }
                }
                if (verid != 1 && VideoShape != Shape.Rectangular)
                {
                    parser.GetBit(Attribute.SADctDisable);
                }
                bool not8Bit = parser.GetBit(Attribute.Not8bit);
                if (not8Bit == true)
                {
                    QuantPrecision = (short)parser.GetBits(4, Attribute.QuantPrecision);
                    if (QuantPrecision < 3 || QuantPrecision > 9)
                    {
                        //mp4_Error("Error: quant_precision must be in range [3; 9]");
                        return(false);
                    }
                    uint bits_per_pixel = parser.GetBits(4, Attribute.BitsPerPixel);
                    if (bits_per_pixel < 4 || bits_per_pixel > 12)
                    {
                        //mp4_Error("Error: bits_per_pixel must be in range [4; 12]");
                        return(false);
                    }
                }
                else
                {
                    QuantPrecision = 5;
                    parser.AddAttribute(new FormattedAttribute <Attribute, short>(Attribute.QuantPrecision, QuantPrecision));
                    parser.AddAttribute(new FormattedAttribute <Attribute, short>(Attribute.BitsPerPixel, 8));
                }
                if (VideoShape == Shape.Grayscale)
                {
                    parser.GetBit(Attribute.NoGrayQuantUpdate);
                    parser.GetBit(Attribute.CompositionMethod);
                    parser.GetBit(Attribute.LinearComposition);
                }
                bool quantType = parser.GetBit(Attribute.QuantType);
                if (quantType == true)
                {
                    bool   loadIntraQuantMat = parser.GetBit(Attribute.LoadIntraQuantMat);
                    byte[] intraQuantMat     = new byte[64];
                    if (loadIntraQuantMat == true)
                    {
                        if (ParseQuantMatrix(parser, ref intraQuantMat) != 0)
                        {
                            return(false);
                        }
                    }
                    else
                    {
                        mp4_DefaultIntraQuantMatrix.CopyTo(intraQuantMat, 0);
                    }

                    bool   loadNonintraQuantMat = parser.GetBit();
                    byte[] nonintraQuantMat     = new byte[64];
                    if (loadNonintraQuantMat == true)
                    {
                        if (ParseQuantMatrix(parser, ref nonintraQuantMat) != 0)
                        {
                            return(false);
                        }
                    }
                    else
                    {
                        mp4_DefaultNonIntraQuantMatrix.CopyTo(nonintraQuantMat, 0);
                    }
                    if (VideoShape == Shape.Grayscale)
                    {
                        int ac;
                        int index = 0;

                        ac = mp4_aux_comp_count[ShapeExtension];
                        bool[] loadIntraQuantMatGrayscale    = new bool[3];
                        bool[] loadNonintraQuantMatGrayscale = new bool[3];
                        for (index = 0; index < ac; index++)
                        {
                            loadIntraQuantMatGrayscale[index] = parser.GetBit(Attribute.LoadIntraQuantMatGrayscale);
                            if (loadIntraQuantMatGrayscale[index] == true)
                            {
                                if (ParseQuantMatrix(parser, ref _intra_quant_mat_grayscale[index]) != 1)
                                {
                                    return(false);
                                }
                            }
                            else
                            {
                                mp4_DefaultIntraQuantMatrix.CopyTo(_intra_quant_mat_grayscale[index], 0);
                            }
                            loadNonintraQuantMatGrayscale[index] = parser.GetBit(Attribute.LoadNonintraQuantMatGrayscale);
                            if (loadNonintraQuantMatGrayscale[index] == true)
                            {
                                if (ParseQuantMatrix(parser, ref _nonintra_quant_mat_grayscale[index]) != 1)
                                {
                                    return(false);
                                }
                            }
                            else
                            {
                                mp4_DefaultNonIntraQuantMatrix.CopyTo(_nonintra_quant_mat_grayscale[index], 0);
                            }
                        }
                    }
                }
                if (verid != 1)
                {
                    parser.GetBit(Attribute.QuarterSample);
                }
                ComplexityEstimationDisable = parser.GetBit();
                if (ComplexityEstimationDisable == false)
                {
                    _complexityEstimation.estimation_method = parser.GetBits(2, Attribute.EstimationMethod);
                    if (_complexityEstimation.estimation_method <= 1)
                    {
                        _complexityEstimation.shape_complexity_estimation_disable = parser.GetBit();
                        if (_complexityEstimation.shape_complexity_estimation_disable == false)
                        {
                            _complexityEstimation.opaque      = parser.GetBit(Attribute.Opaque);
                            _complexityEstimation.transparent = parser.GetBit(Attribute.Transparent);
                            _complexityEstimation.intra_cae   = parser.GetBit(Attribute.IntraCae);
                            _complexityEstimation.inter_cae   = parser.GetBit(Attribute.InterCae);
                            _complexityEstimation.no_update   = parser.GetBit(Attribute.NoUpdate);
                            _complexityEstimation.upsampling  = parser.GetBit(Attribute.Upsampling);
                        }
                        _complexityEstimation.texture_complexity_estimation_set_1_disable = parser.GetBit(Attribute.TextureComplexityEstimationSet1Disable);
                        if (_complexityEstimation.texture_complexity_estimation_set_1_disable == false)
                        {
                            _complexityEstimation.intra_blocks     = parser.GetBit(Attribute.IntraBlocks);
                            _complexityEstimation.inter_blocks     = parser.GetBit(Attribute.InterBlocks);
                            _complexityEstimation.inter4v_blocks   = parser.GetBit(Attribute.Inter4vBlocks);
                            _complexityEstimation.not_coded_blocks = parser.GetBit(Attribute.NotCodedBlocks);
                        }
                        if (!parser.GetMarkerBit())
                        {
                            // Does not appear to be a mp4 VOL header
                            return(false);
                        }
                        _complexityEstimation.texture_complexity_estimation_set_2_disable = parser.GetBit(Attribute.TextureComplexityEstimationSet2Disable);
                        if (_complexityEstimation.texture_complexity_estimation_set_2_disable == false)
                        {
                            _complexityEstimation.dct_coefs   = parser.GetBit(Attribute.DctCoefs);
                            _complexityEstimation.dct_lines   = parser.GetBit(Attribute.DctLines);
                            _complexityEstimation.vlc_symbols = parser.GetBit(Attribute.VlcSymbols);
                            _complexityEstimation.vlc_bits    = parser.GetBit(Attribute.VlcBits);
                        }
                        _complexityEstimation.motion_compensation_complexity_disable = parser.GetBit(Attribute.MotionCompensationComplexityDisable);
                        if (_complexityEstimation.motion_compensation_complexity_disable == false)
                        {
                            _complexityEstimation.apm = parser.GetBit(Attribute.Apm);
                            _complexityEstimation.npm = parser.GetBit(Attribute.Npm);
                            _complexityEstimation.interpolate_mc_q = parser.GetBit(Attribute.InterpolateMcQ);
                            _complexityEstimation.forw_back_mc_q   = parser.GetBit(Attribute.ForwBackMcQ);
                            _complexityEstimation.halfpel2         = parser.GetBit(Attribute.Halfpel2);
                            _complexityEstimation.halfpel4         = parser.GetBit(Attribute.Halfpel4);
                        }
                    }
                    if (!parser.GetMarkerBit())
                    {
                        // Does not appear to be a mp4 VOL header
                        return(false);
                    }
                    if (_complexityEstimation.estimation_method == 1)
                    {
                        // verid != 1
                        _complexityEstimation.version2_complexity_estimation_disable = parser.GetBit(Attribute.Version2ComplexityEstimationDisable);
                        if (_complexityEstimation.version2_complexity_estimation_disable == false)
                        {
                            _complexityEstimation.sadct      = parser.GetBit(Attribute.Sadct);
                            _complexityEstimation.quarterpel = parser.GetBit(Attribute.Quarterpel);
                        }
                    }
                }
                ResyncMarkerDisable = parser.GetBit(Attribute.ResyncMarkerDisable);
                DataPartitioned     = parser.GetBit(Attribute.DataPartitioned);
                //f GrayScale Shapes does not support data_part
                if (DataPartitioned == true)
                {
                    _reversible_vlc = parser.GetBit(Attribute.ReversibleVlc);
                }
                if (verid != 1)
                {
                    NewPredEnable = parser.GetBit(Attribute.NewPredEnable);
                    if (NewPredEnable == true)
                    {
                        parser.GetBits(2, Attribute.RequestedUpstreamMessageType);
                        parser.GetBit(Attribute.NewpredSegmentType);
                    }
                    ReducedResolutionVopEnable = parser.GetBit(Attribute.ReducedResolutionVopEnable);
                }
                bool scalability = parser.GetBit(Attribute.Scalability);
                if (scalability == true)
                {
                    parser.FlushBits(26);
                    EnhancementType = parser.GetBit(Attribute.EnhancementType);
                }
            }
            else
            {
                if (verid != 1)
                {
                    Scalability = parser.GetBit(Attribute.Scalability);
                    if (Scalability == true)
                    {
                        parser.FlushBits(24);
                    }
                }
                this.ResyncMarkerDisable = parser.GetBit();
            }

            //_VideoObjectLayerPlane.sprite_transmit_mode = Sprite.MP4_SPRITE_TRANSMIT_MODE_PIECE;
            return(true);
        }