internal bool Parse(Mpeg4Parser parser) { PixelAspectRatioCode = (byte)parser.GetBits(4); // bit 1-4 if (PixelAspectRatioCode == 0 /*Forbidden*/) { return(false); } ushort pictureWidthIndication = (ushort)parser.GetBits(9); // bit 5-13 PixelsPerLine = (pictureWidthIndication + 1U) * 4U; if (!parser.GetOneBit()) { return(false); // Bit 14 equal to "1" to prevent start code emulation; } ushort pictureHeightIndication = (ushort)parser.GetBits(9); // bit 15-23 NumberOfLines = pictureHeightIndication * 4U; uint k = K; const int macroblockLength = 16 * 16; GobsInVopCount = NumberOfLines / (16U * k); MacroblocksInGobCount = (PixelsPerLine * NumberOfLines) / (GobsInVopCount * macroblockLength); RowsInGobCount = k; return(true); }
public override bool Parse(Mpeg4Parser parser) { if (!base.Parse(parser)) { return(false); } uint hour = parser.GetBits(5); uint minute = parser.GetBits(6); bool markerBit = parser.GetMarkerBit(); var markerBitAttribute = new FormattedAttribute <Attribute, bool>(Attribute.MarkerBit, markerBit); if (markerBit == false) { markerBitAttribute.Valid = false; } Attributes.Add(markerBitAttribute); uint seconds = parser.GetBits(6); long timeCode = seconds + minute * 60 + hour * 3600; Attributes.Add(new FormattedAttribute <Attribute, long>(Attribute.TimeCode, timeCode)); Attributes.Add(new FormattedAttribute <Attribute, string>(Attribute.Time, string.Format(CultureInfo.InvariantCulture, "{0}:{1}:{2}", hour.ToString("D2", CultureInfo.InvariantCulture), minute.ToString("D2", CultureInfo.InvariantCulture), seconds.ToString("D2", CultureInfo.InvariantCulture)))); /*bool closedGov = */ parser.GetBit(Attribute.ClosedGov); /*bool brokenLink = */ parser.GetBit(Attribute.BrokenLink); return(true); }
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); } bool isIdentifier = parser.GetBit(Attribute.Identifier); if (isIdentifier) { byte versionID = (byte)parser.GetBits(4); var versionIDAttribute = new FormattedAttribute <Attribute, uint>(Attribute.VersionID, versionID); byte[] validVersionIDs = new byte[] { 1, 2, 4, 5 }; if (!validVersionIDs.Contains(versionID)) { versionIDAttribute.Valid = false; } parser.AddAttribute(versionIDAttribute); parser.GetBits(3, Attribute.Priority); } else { VersionId = 1; } uint type = parser.GetBits(4, Attribute.Type); if (type > (uint)ObjectType.Mesh_3D) { return(false); } if (type == (uint)ObjectType.Video || type == (uint)ObjectType.Texture) { // Parse video signal type bool isVideoSignalType = parser.GetBit(Attribute.VideoSignalType); if (isVideoSignalType) { byte videoFormat = (byte)parser.GetBits(3); parser.AddAttribute(new FormattedAttribute <Attribute, string>(Attribute.VideoFormat, string.Format(CultureInfo.CurrentCulture, "{0} ({1})", videoFormat.ToString(CultureInfo.CurrentCulture), Enum.GetName(typeof(VideoFormat), videoFormat)))); parser.GetBit(Attribute.VideoRange); bool colourDescription = parser.GetBit(Attribute.ColourDescription); if (colourDescription) { parser.GetBits(8, Attribute.ColourPrimaries); parser.GetBits(8, Attribute.TransferCharacteristics); parser.GetBits(8, Attribute.MatrixCoefficients); } } } return(true); }
/// <summary> /// Read Continuous Presence Multipoint and Video Multiplex (CPM) and /// Picture Sub-Bitstream Indicator (PSBI) (when CPM is 1) /// </summary> /// <param name="dataInfo"></param> /// <returns>The value of CMP</returns> static private bool ReadCpmAndPsbi(Mpeg4Parser parser) { // Continuous Presence Multipoint and Video Multiplex (CPM) (1 bit) bool cpm = parser.GetBit(); if (cpm) { // Picture Sub-Bitstream Indicator (PSBI) (2 bits) /*byte psbi = (byte)*/ parser.GetBits(2); } return(cpm); }
public override bool Parse(Mpeg4Parser parser) { if (!base.Parse(parser)) { return(false); } if (!parser.Parse(new UserDataAttribute())) { this.Valid = false; } return(this.Valid); }
public override bool Parse(Mpeg4Parser parser) { if (!base.Parse(parser)) { return(false); } int stuffingByteNumber = 0; while (parser.ShowBits(8) == StuffingByteValue) { stuffingByteNumber++; parser.GetByte(); } Attributes.Add(new FormattedAttribute <Attribute, int>(Attribute.StuffingByteNumber, stuffingByteNumber)); return(true); }
public override bool Parse(Mpeg4Parser parser) { if (!base.Parse(parser)) { return(false); } if (Length < 5) { return(false); } uint extensionType = parser.GetBits(4); if (extensionType < 2 || extensionType > 13 || (extensionType >= 8 && extensionType <= 10)) { return(false); } parser.AddAttribute(new FormattedAttribute <Attribute, uint>(Attribute.ExtensionCode, extensionType)); return(true); }
public static int ParseQuantMatrix(Mpeg4Parser parser, ref byte [] quantMatrix) { byte code = 0; int i; for (i = 0; i < 64; i++) { code = (byte)parser.GetBits(8); if (code == 0) { break; } quantMatrix[mp4_ClassicalZigzag[i]] = code; } if (i >= 1) { code = quantMatrix[mp4_ClassicalZigzag[i - 1]]; } for (; i < 64; i++) { quantMatrix[mp4_ClassicalZigzag[i]] = code; } return(1); }
/// <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); }
//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); }
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 {