/// <summary> /// This method looks for the beginning of an MPEG-4 header and if one is found it will parse it /// by calling Parser.Parse(). /// </summary> override public IDataBlock DetectData(IDataReader dataReader, IDataBlockBuilder dataBlockBuilder, IScanContext context) { if (ReferenceHeaders != null) { var referenceHeaders = new Dictionary <IDataPacket, VideoObjectLayer>(); foreach (IReferenceHeader header in ReferenceHeaders) { IInputFile headerFile = context.CreateReferenceHeaderFile(header); using (var parser = new Mpeg4Parser(new BitStreamDataReader(headerFile.CreateDataReader()))) { Mpeg4Header root; while (parser.ParseRoot(root = new Mpeg4Header(context.Detectors), parser.Length)) { VideoObjectLayer vol = root.FindChild(Mpeg4HeaderName.VideoObjectLayer, true) as VideoObjectLayer; if (vol != null) { referenceHeaders[headerFile.CreateDataPacket()] = vol; } } } } context.ReferenceHeader = referenceHeaders; } return(Carve(dataReader, dataBlockBuilder, context)); }
/// <summary> /// This is a layer containing a fixed number of macroblocks in the VOP. /// Which macroblocks which belong to each gob can be determined by /// gob_number and num_macroblocks_in_gob. /// Remark: only used by short video /// </summary> private bool GobLayer(Mpeg4Parser parser, VideoObjectLayer VOL, ref int gob_number, ref uint rowNum, ref uint colNum, bool cpm, uint numRowsInGob, uint numGobsInVop) { //bool gob_header_empty = true; if (gob_number != 0) { if (parser.ShowBits(17) == GobResyncMarker) { //gob_header_empty = false; parser.FlushBits(17); // Group Number (GN) (5 bits) gob_number = (int)parser.GetBits(5); // check gob_number is valid if (gob_number > numGobsInVop) { #if DEBUG Debug.WriteLineIf(_mpeg4H263DebugInfo, "H263 GOB number is invalid.", Mpeg4H263); #endif // DEBUG return(false); } // GOB Sub-Bitstream Indicator (GSBI) (2 bits) // A fixed length codeword of 2 bits that is only present if CPM is "1" in the picture header. if (cpm) { /*byte gobSubBitstreamIndicator = (byte)*/ parser.GetBits(2); } // GOB Frame ID (GFID) (2 bits) // GFID shall have the same value in every GOB (or slice) header // of a given picture. parser.GetBits(2); // Quantizer Information (GQUANT) (5 bits) _quantScale = parser.GetBits(5); rowNum = (uint)(gob_number * numRowsInGob); colNum = 0; } } for (int i = 0; i < _numMacroblocksInGob; i++) { if (!HandleMacroBlock(parser, VOL, ref colNum, ref rowNum)) { if (gob_number == 0) { #if DEBUG Debug.WriteLineIf(_mpeg4H263DebugInfo, "H263 GOB number is 0.", Mpeg4H263); #endif // DEBUG return(false); } else { //break; return(true); } } } if (parser.ShowBits(17) != GobResyncMarker && parser.ShowNextBitsByteAligned(17) == GobResyncMarker) { while (!parser.ByteAligned) { if (!parser.GetZeroBit()) { return(false); } } } gob_number++; return(true); }
public override bool Parse(Mpeg4Parser parser) { if (!base.Parse(parser)) { return(false); } VideoObjectLayer VOL = new VideoObjectLayer(Parent as Mpeg4Header, true); VOL.Parse(parser); _fcodeForward = 1; Attributes.Add(new FormattedAttribute <Attribute, bool>(Attribute.ShortVideoHeader, true)); // Get the Temporal Reference (TR) this.TemporalReference = (byte)parser.GetBits(8, Attribute.TemporalReference); // Get the Type Information (PTYPE) (Variable Length) if (!parser.GetMarkerBit()) // PTYPE, bit 1. First bit must always be '1', { // in order to avoid start code emulation. #if DEBUG //long offset = parser.GetDataPacket(parser._dataReader.BytePosition, 1).StartOffset; //string message = string.Format(CultureInfo.CurrentCulture, "Offset: 0x{0}; First bit of PTYPE is '0', it must always be '1'.", offset.ToString("X", CultureInfo.CurrentCulture)); //Debug.WriteLineIf(_mpeg4H263DebugInfo, message, Mpeg4H263); #endif // DEBUG return(false); } // The second bit must always be '0', for distinction with ITU-T Rec. H.261. if (!parser.GetZeroBit()) // PTYPE, bit 2 { #if DEBUG Debug.WriteLineIf(_mpeg4H263DebugInfo, "Second bit of PTYPE is '1', it must always be '0'.", Mpeg4H263); #endif // DEBUG return(false); } /*bool splitScreenIndicator = */ parser.GetBit(); // PTYPE, bit 3 /*bool documentCameraIndicator = */ parser.GetBit(); // PTYPE, bit 4 /*bool fullPictureFreezeRelease = */ parser.GetBit(); // PTYPE, bit 5 byte sourceFormat = (byte)parser.GetBits(3); // PTYPE, bit 6-8 Attributes.Add(new FormattedAttribute <Attribute, string>(Attribute.PTypeSourceFormat, Enum.GetName(typeof(PTypeSourceFormat), sourceFormat))); bool extendedPType = (sourceFormat == (byte)PTypeSourceFormat.ExtendedPType); if (sourceFormat == (byte)PTypeSourceFormat.Forbidden) { #if DEBUG Debug.WriteLineIf(_mpeg4H263DebugInfo, "The source format has the forbidden value of '0'.", Mpeg4H263); #endif // DEBUG return(false); } H263PictureTypeCode pictureCodingType = H263PictureTypeCode.Invalid; bool optionalPBFramesMode = false; bool optionalCustomPictureClockFrequency = false; bool cpm = false; CustomPictureFormat customPictureFormat = null; if (!extendedPType) { pictureCodingType = parser.GetBit() ? H263PictureTypeCode.P_Picture : H263PictureTypeCode.I_Picture; // PTYPE, bit 9 _codingType = (byte)pictureCodingType; Attributes.Add(new FormattedAttribute <Attribute, string>(Attribute.CodingType, Enum.GetName(typeof(H263PictureTypeCode), _codingType))); /*bool optionalUnrestrictedMotionVectorMode = */ parser.GetBit(); // PTYPE, bit 10 /*bool optionalSyntaxBasedArithmeticCodingMode = */ parser.GetBit(); // PTYPE, bit 11 /*bool optionalAdvancedPredictionMode = */ parser.GetBit(); // PTYPE, bit 12 optionalPBFramesMode = parser.GetBit(); // PTYPE, bit 13 // If bit 9 is set to 0, bit 13 shall be set to 0 as well if (pictureCodingType == H263PictureTypeCode.I_Picture && optionalPBFramesMode) { #if DEBUG Debug.WriteLineIf(_mpeg4H263DebugInfo, "Bit 9 of PTYPE is '0', and bit 13 is '1', while bit 13 should be '0'.", Mpeg4H263); #endif // DEBUG return(false); } } else // SourceFormat == SourceFormat.ExtendedPType { // Plus PTYPE (PLUSPTYPE) (Variable Length; 12 or 30 bits) // Update Full Extended PTYPE (UFEP) (3 bits) // Values of UFEP other than "000" and "001" are reserved byte updateFullExtendedPType = (byte)parser.GetBits(3); //PlusPTypeSourceFormat plusPTypeSourceFormat = PlusPTypeSourceFormat.Invalid; bool optionalUnrestrictedMotionVector = false; bool optionalSliceStructured = false; bool optionalReferencePictureSelection = false; if (updateFullExtendedPType == 1) { // The Optional Part of PLUSPTYPE (OPPTYPE) (18 bits) // overwrite sourceFormat variable sourceFormat = (byte)parser.GetBits(3); // bit 1-3 Attributes.Add(new FormattedAttribute <Attribute, string>(Attribute.PlusPTypeSourceFormat, Enum.GetName(typeof(PlusPTypeSourceFormat), (sourceFormat == 7) ? (byte)0 /* enum values 0 and 7 are both 'Reserved' */: sourceFormat))); optionalCustomPictureClockFrequency = parser.GetBit(); // bit 4 (PCF) optionalUnrestrictedMotionVector = parser.GetBit(); // bit 5 (UMV) /*bool optionalSyntaxBasedArithmeticCoding = */ parser.GetBit(); // bit 6 (SAC) /*bool optionalAdvancedPrediction = */ parser.GetBit(); // bit 7 (AP) /*bool optionalAdvancedIntraCoding = */ parser.GetBit(); // bit 8 (AIC) /*bool optionalDeblockingFilter = */ parser.GetBit(); // bit 9 (DF) optionalSliceStructured = parser.GetBit(); // bit 10 (SS) optionalReferencePictureSelection = parser.GetBit(); // bit 11 (RPS) /*bool optionalIndependentSegmentDecoding = */ parser.GetBit(); // bit 12 (ISD) /*bool optionalAlternativeInterVariableLengthCode = */ parser.GetBit(); // bit 13 (AIV) _optionalModifiedQuantization = parser.GetBit(); // bit 14 (MQ) if (!parser.GetOneBit()) // bit 15 should be "1" to prevent start code emulation { #if DEBUG Debug.WriteLineIf(_mpeg4H263DebugInfo, "Bit 15 of PLUSPTYPE is '0' but should be '1'.", Mpeg4H263); #endif // DEBUG return(false); } if (parser.GetBits(3) != 0) // bit 16-18 shall be equal to "0" { #if DEBUG Debug.WriteLineIf(_mpeg4H263DebugInfo, "Bit 16-18 of PLUSPTYPE are != '0' but shall be equal to '0'.", Mpeg4H263); #endif // DEBUG return(false); } } // The mandatory part of PLUSPTYPE (MPPTYPE) (9 bits) pictureCodingType = (H263PictureTypeCode)parser.GetBits(3); // bits 1-3 _codingType = (byte)pictureCodingType; Attributes.Add(new FormattedAttribute <Attribute, string>(Attribute.CodingType, Enum.GetName(typeof(H263PictureTypeCode), (_codingType == 7) ? (byte)6 /* enum values 6 and 7 are both 'Reserved' */: _codingType))); bool optionalReferencePictureResamplingMode = parser.GetBit(); // bit 4 (RPR) bool optionalReducedResolutionUpdateMode = parser.GetBit(); // bit 5 (RRU) bool roundingType = parser.GetBit(); // bit 6 (RTYPE) // bit 6 can be set to "1" only when bits 1-3 indicate P-picture, Improved PB-frame or EP-frame if (roundingType && !(pictureCodingType == H263PictureTypeCode.P_Picture || pictureCodingType == H263PictureTypeCode.ImprovedPBFrame || pictureCodingType == H263PictureTypeCode.EP_Picture)) { #if DEBUG Debug.WriteLineIf(_mpeg4H263DebugInfo, "Bit 6 of PLUSPTYPE can only be set to '1' when bits 1-3 indicate P-picture, Improved PB-frame or EP-frame.", Mpeg4H263); #endif // DEBUG return(false); } // Read two reserved bits // Shall be equal to "0" if (parser.GetBits(2) != 0) // bit 7 and 8 { #if DEBUG Debug.WriteLineIf(_mpeg4H263DebugInfo, "The reserved bits 7 and 8 of PLUSPTYPE are != '0', but should be '0'.", Mpeg4H263); #endif // DEBUG return(false); } // Bit 9 must be equal to "1" to prevent start code emulation if (!parser.GetOneBit()) // bit 9 { #if DEBUG Debug.WriteLineIf(_mpeg4H263DebugInfo, "Bit 9 of PLUSPTYPE is '0' but must be '1'.", Mpeg4H263); #endif // DEBUG return(false); } // If the picture type is INTRA or EI, updateFullExtendedPType shall be set to "001". if ((pictureCodingType == H263PictureTypeCode.I_Picture || pictureCodingType == H263PictureTypeCode.EI_Picture) && updateFullExtendedPType != 1) { #if DEBUG Debug.WriteLineIf(_mpeg4H263DebugInfo, "If the picture type is INTRA or EI, updateFullExtendedPType shall be set to '001'", Mpeg4H263); #endif // DEBUG return(false); } // Continuous Presence Multipoint and Video Multiplex (CPM) (1 bit) // CPM follows immediately after PLUSPTYPE if PLUSPTYPE is present, // but follows PQUANT in the picture header if PLUSPTYPE is not present. // - This is the case where PLUSPTYPE is present cpm = ReadCpmAndPsbi(parser); // Custom Picture Format (CPFMT) (23 bits) // A fixed length codeword of 23 bits that is present only if the use of a // custom picture format is signalled in PLUSPTYPE and UFEP is '001' if (sourceFormat == (int)PlusPTypeSourceFormat.CustomSourceFormat && updateFullExtendedPType == 1) { customPictureFormat = new CustomPictureFormat(optionalReducedResolutionUpdateMode); if (!customPictureFormat.Parse(parser)) { return(false); } // Extended Pixel Aspect Ratio (EPAR) (16 bits) if (customPictureFormat.PixelAspectRatioCode == 15 /*Extended PAR*/) { // The natural binary representation of the PAR width byte parWidth = (byte)parser.GetBits(8); // bit 1-8 // PAR Width: "0" is forbidden. if (parWidth == 0) { return(false); } // The natural binary representation of the PAR height. byte parHeight = (byte)parser.GetBits(8); // bit 9-16 // PAR Height: "0" is forbidden. if (parHeight == 0) { return(false); } } } // Custom Picture Clock Frequency Code (CPCFC) (8 bits) // A fixed length codeword of 8 bits that is present only if PLUSPTYPE is present // and UFEP is 001 and a custom picture clock frequency is signalled in PLUSPTYPE. if (updateFullExtendedPType == 1 && optionalCustomPictureClockFrequency) { // Clock Conversion Code: "0" indicates a clock conversion factor of 1000 and // "1" indicates 1001 /*bool clockConversionCode = */ parser.GetBit(); // bit 1 // Bits 2-8 // Clock Divisor: "0" is forbidden. The natural binary representation of the value // of the clock divisor. byte clockDivisor = (byte)parser.GetBits(7); // bit 2-8 if (clockDivisor == 0) { return(false); } } // Extended Temporal Reference (ETR) (2 bits) // A fixed length codeword of 2 bits which is present only if a custom picture clock frequency is in // use (regardless of the value of UFEP). It is the two MSBs of the 10-bit Temporal Reference (TR). if (optionalCustomPictureClockFrequency) { /*byte extendedTemporalReference = (byte)*/ parser.GetBits(2); // bit 1-2 } // Unlimited Unrestricted Motion Vectors Indicator (UUI) (Variable length) // A variable length codeword of 1 or 2 bits that is present only if the // optional Unrestricted Motion Vector mode is indicated in PLUSPTYPE and UFEP is 001. if (updateFullExtendedPType == 1 && optionalUnrestrictedMotionVector) { bool unlimitedUnrestrictedMotionVectorsIndicator = parser.GetBit(); if (!unlimitedUnrestrictedMotionVectorsIndicator) { // UUI = "01" The motion vector range is not limited except by the picture size. unlimitedUnrestrictedMotionVectorsIndicator = parser.GetBit(); if (!unlimitedUnrestrictedMotionVectorsIndicator) { return(false); } } else { // UUI = "1" The motion vector range is limited according to Tables D.1 and D.2. } } // Slice Structured Submode bits (SSS) (2 bits) // A fixed length codeword of 2 bits which is present only if the optional Slice Structured mode // (see Annex K) is indicated in PLUSPTYPE and UFEP is 001. If the Slice Structured mode is in use // but UFEP is not 001, the last values sent for SSS shall remain in effect. if (updateFullExtendedPType == 1 && optionalSliceStructured) { // Bit 1; "0" indicates free-running slices, "1" indicates rectangular slices /*bool rectangularSlices = */ parser.GetBit(); // Bit 2 "0" indicates sequential order, "1" indicates arbitrary order /*bool arbitrarySliceOrdering = */ parser.GetBit(); } if (pictureCodingType == H263PictureTypeCode.B_Picture || pictureCodingType == H263PictureTypeCode.EI_Picture || pictureCodingType == H263PictureTypeCode.EP_Picture) { // Enhancement Layer Number (ELNUM) (4 bits) // A fixed length codeword of 4 bits which is present only if the optional Temporal, SNR, // and Spatial Scalability mode is in use (regardless of the value of UFEP) /*byte enhancementLayerNumber = (byte)*/ parser.GetBits(4); // Reference Layer Number (RLNUM) (4 bits) // A fixed length codeword of 4 bits which is present only if the optional Temporal, SNR, // and Spatial Scalability mode is in use (see Annex O) and UFEP is 001. if (updateFullExtendedPType == 1) { /*byte referenceLayerNumber = (byte)*/ parser.GetBits(4); // Note that for B-pictures in an enhancement layer having temporally surrounding EI- or EP-pictures // which are present in the same enhancement layer, RLNUM shall be equal to ELNUM //if (pictureCodingType == H263VopType.BPicture && updateFullExtendedPType != referenceLayerNumber) return false; } } // Reference Picture Selection Mode Flags (RPSMF) (3 bits) if (updateFullExtendedPType == 1 && optionalReferencePictureSelection) { /*byte referencePictureSelectionModeFlags = (byte)*/ parser.GetBits(3); } if (optionalReferencePictureSelection) { // Temporal Reference for Prediction Indication (TRPI) (1 bit) // A fixed length codeword of 1 bit that is present only if the optional Reference Picture Selection // mode is in use (regardless of the value of UFEP). bool temporalReferenceForPredictionIndication = parser.GetBit(); if (temporalReferenceForPredictionIndication) { if (pictureCodingType == H263PictureTypeCode.I_Picture || pictureCodingType == H263PictureTypeCode.EI_Picture) { // TRPI shall be 0 whenever the picture header indicates an I- or EI-picture. return(false); } // Temporal Reference for Prediction (TRP) (10 bits) parser.FlushBits(10); } // Back-Channel message Indication (BCI) (Variable length) while (parser.GetBit() == true) { // Back-Channel Message (BCM) (Variable length) // Structure: BT URF TR ELNUMI ELNUM BCPM BSBI BEPB1 GN/MBA BEPB2 RTR BSTUF // Back-channel message Type (BT) (2 bits) parser.FlushBits(2); // Unreliable Flag (URF) (1 bit) // 0: Reliable; 1: Unreliable. parser.FlushBits(1); // Temporal Reference (TR) (10 bits) parser.FlushBits(10); // Enhancement Layer Number Indication (ELNUMI) (1 bit) bool enhancementLayerNumberIndication = parser.GetBit(); // Enhancement Layer Number (ELNUM) (4 bits) if (enhancementLayerNumberIndication) { parser.FlushBits(4); } // BCPM (1 bit) bool bcpm = parser.GetBit(); // Back-channel Sub-Bitstream Indicator (BSBI) (2 bits) if (bcpm) { parser.FlushBits(2); } // Back-channel Emulation Prevention Bit 1 (BEPB1) (1 bit) // A field which is present if and only if the videomux mode is in use. //if(videomux mode is in use) TODO //{ // This field is always set to "1" to prevent a start code emulation. if (!parser.GetOneBit()) { return(false); } //} } bool bit2 = parser.GetBit(); if (bit2 == false) { return(false); // If bit1 == 0, bit2 must be 1. } } // Reference Picture Resampling Parameters (RPRP) (Variable length) if (optionalReferencePictureResamplingMode) { ParseReferencePictureResampling(parser, pictureCodingType); } } // SourceFormat == SourceFormat.ExtendedPType // Quantizer Information (PQUANT) (5 bits) _pQuant = parser.GetBits(5); // Continuous Presence Multipoint and Video Multiplex (CPM) (1 bit) // CPM follows immediately after PLUSPTYPE if PLUSPTYPE is present, // but follows PQUANT in the picture header if PLUSPTYPE is not present. // - This is the case where PLUSPTYPE is not present. if (!extendedPType) { cpm = ReadCpmAndPsbi(parser); } if (optionalPBFramesMode || // PTYPE indicates "PB-frame" pictureCodingType == H263PictureTypeCode.ImprovedPBFrame) //PLUSPTYPE indicates "Improved PB-frame" { // Temporal Reference for B-pictures in PB-frames (TRB) (3/5 bits) // TRB is present if PTYPE or PLUSPTYPE indicates "PB-frame" or "Improved PB-frame" // // The codeword is the natural binary representation of the number of nontransmitted // pictures plus one. It is 3 bits long for standard CIF picture clock frequency and is // extended to 5 bits when a custom picture clock frequency is in use. The maximum number // of nontransmitted pictures is 6 for the standard CIF picture clock frequency and 30 when // a custom picture clock frequency is used. byte trb = (byte)parser.GetBits((short)(optionalCustomPictureClockFrequency ? 5 : 3)); if (trb == 0) { return(false); } // Quantization information for B-pictures in PB-frames (DBQUANT) (2 bits) // DBQUANT is present if PTYPE or PLUSPTYPE indicates "PB-frame" or "Improved PB-frame" /*byte dbQuant = (byte)*/ parser.GetBits(2); } // PEI (1 bit) and PSUPP (0/8/16 ... bits) for (; ;) { // Extra Insertion Information (PEI) (1 bit) // A bit which when set to "1" signals the presence of the following optional data field. bool extraInsertionInformation = parser.GetBit(); // 1 bit (PEI) // If PEI is set to "1", then 9 bits follow consisting of 8 bits of data (PSUPP) // and then another PEI bit to indicate if a further 9 bits follow and so on. if (!extraInsertionInformation) { break; } /*byte supplementalEnhancementInformation = (byte)*/ parser.GetBits(8); // 8 bit (PSUPP) } // Group of Blocks Layer (GOB) // Structure: GSTUF GBSC GN GSBI GFID GQUANT Macroblock Data uint numGobsInVop; uint numRowsInGob; if (customPictureFormat != null) { _vopWidth = customPictureFormat.PixelsPerLine; _vopHeight = customPictureFormat.NumberOfLines; numGobsInVop = customPictureFormat.GobsInVopCount; _numMacroblocksInGob = customPictureFormat.MacroblocksInGobCount; numRowsInGob = customPictureFormat.RowsInGobCount; } else { int sourceFormatIndex = sourceFormat - 1; if (sourceFormatIndex < 0 || sourceFormatIndex >= MP4H263Width.Length) { return(false); } _vopWidth = (uint)MP4H263Width[sourceFormatIndex]; _vopHeight = (uint)MP4H263Height[sourceFormatIndex]; numGobsInVop = (uint)MP4H263GobVop[sourceFormatIndex]; _numMacroblocksInGob = (uint)MP4H263MbGob[sourceFormatIndex]; numRowsInGob = (uint)MP4H263RowGob[sourceFormatIndex]; } int gob_number = 0; uint rowNum = 0; uint colNum = 0; for (int i = 0; i < numGobsInVop; i++) { if (!GobLayer(parser, VOL, ref gob_number, ref rowNum, ref colNum, cpm, numRowsInGob, numGobsInVop)) { return(false); } } // Stuffing (ESTUF) (Variable length) // A codeword of variable length consisting of less than 8 zero-bits. // TODO 5.1.26 // End Of Sequence (EOS) (22 bits) if (parser.ShowBits(22) == ShortVideoEndMarker) { parser.FlushBits(22); } // Stuffing (PSTUF) (Variable length) // A codeword of variable length consisting of less than 8 zero-bits. while (!parser.ByteAligned) { if (!parser.GetZeroBit()) { return(false); } } return(true); }
public override bool Parse(Mpeg4Parser parser) { if (!base.Parse(parser)) { return(false); } parser.InsertReferenceHeaderBeforeStartCode(); parser.SeenVop = true; // In MPEG-4 every VOP is a child of a VOL header VideoObjectLayer VOL = Vol; uint code = 0; Attributes.Add(new FormattedAttribute <Attribute, bool>(Attribute.ShortVideoHeader, false)); _codingType = (byte)parser.GetBits(2); Attributes.Add(new FormattedAttribute <Attribute, string>(Attribute.CodingType, Enum.GetName(typeof(Mpeg4VopType), _codingType))); int moduloTimeBase = 0; do { code = (parser.GetBit() == true) ? 1U : 0U; moduloTimeBase += (int)code; } while (code > 0); Attributes.Add(new FormattedAttribute <Attribute, int>(Attribute.ModuloTimeBase, moduloTimeBase)); if (!parser.GetMarkerBit()) { // Does not appear to be a mp4 VOP header return(false); } // No VOL (Video Object Layer) header was found. // Parsing this VOP header beyond the marker bit above is not possible // without the VOL. // There will be a VOP created anyway. Its size will be determined by the // location of the next header start code. When the resulting VOP is to big, // it will be rejected. The downside of this solution is that other streams // will be taken in the resulting VOP. The good news is that there is a result // reported without a VOL. When the detector finds a VOL anywhere else in the // data, the user of Defraser can use this VOL to try to repair these VOP's. if (VOL == null) { if (parser.TryDefaultHeaders(vol => ParseVop(parser, vol))) { return(true); // VOP successfully decoded using reference header! } // Search for the next start location // The max distance from the current position to the next start code uint maxDistanceToNextStartCode = (uint)Mpeg4Detector.Configurable[Mpeg4Detector.ConfigurationKey.VopHeaderMaxUnparsedLength]; maxDistanceToNextStartCode += (uint)Mpeg4Detector.Configurable[Mpeg4Detector.ConfigurationKey.VopHeaderMaxOtherStreamLength]; this.Valid = false; return(IsNextHeaderWithinMaximumDistance(parser, maxDistanceToNextStartCode)); } return(ParseVop(parser, VOL)); }
private bool ParseVop(Mpeg4Parser parser, VideoObjectLayer vol) { _vopWidth = 0; _vopHeight = 0; _intraDcVlcThr = 0; _pQuant = 0; _fcodeForward = 0; _fcodeBackward = 0; _refSelectCode = 0; _quantScale = 0; _macroblockNum = 0; _numBitsMacroBlock = 0; _rvlc = vol.UseReverseDCT; if (vol.VopTimeIncrementResolutionBits != 0) { /*_timeIncrement = */ parser.GetBits(vol.VopTimeIncrementResolutionBits, Attribute.TimeIncrement); } else { //AddAttributes(); return(true); } if (!parser.GetMarkerBit()) { // Does not appear to be a mp4 VOP header return(false); } bool coded = parser.GetBit(); if (coded == false) { //AddAttributes(); return(true); } if (vol.NewPredEnable) { //vop_id //vop_id_prediction // if (vop_id_prediction > 0) // vop_id_for_prediction; if (!parser.GetMarkerBit()) { // Does not appear to be a mp4 VOP header return(false); } } if (vol.VideoShape != VideoObjectLayer.Shape.BinaryOnly && (_codingType == (int)Mpeg4VopType.P_VOP || (_codingType == (int)Mpeg4VopType.S_VOP && vol.SpriteEnable == VideoObjectLayer.MP4SpriteGMC))) { parser.GetBit(Attribute.RoundingType); } if (vol.ReducedResolutionVopEnable && vol.VideoShape == VideoObjectLayer.Shape.Rectangular && (_codingType == (int)Mpeg4VopType.I_VOP || _codingType == (int)Mpeg4VopType.P_VOP)) { parser.GetBit(Attribute.ReducedResolution); } if (vol.VideoShape != VideoObjectLayer.Shape.Rectangular) { if (!(vol.SpriteEnable == VideoObjectLayer.MP4SpriteStatic && _codingType == (int)Mpeg4VopType.I_VOP)) { _vopWidth = parser.GetBits(13, Attribute.Width); if (!parser.GetMarkerBit()) { return(false); } _vopHeight = parser.GetBits(13, Attribute.Height); if (!parser.GetMarkerBit()) { return(false); } uint vopHorizontalMcSpatialRef = parser.GetBits(13); vopHorizontalMcSpatialRef <<= (32 - 13); vopHorizontalMcSpatialRef >>= (32 - 13); Attributes.Add(new FormattedAttribute <Attribute, uint>(Attribute.HorizontalMcSpatialRef, vopHorizontalMcSpatialRef)); if (!parser.GetMarkerBit()) { return(false); } uint vopVerticalMcSpatialRef = parser.GetBits(13); vopVerticalMcSpatialRef <<= (32 - 13); vopVerticalMcSpatialRef >>= (32 - 13); Attributes.Add(new FormattedAttribute <Attribute, uint>(Attribute.VerticalMcSpatialRef, vopVerticalMcSpatialRef)); if (!parser.GetMarkerBit()) { return(false); } } if (vol.VideoShape != VideoObjectLayer.Shape.BinaryOnly && vol.Scalability == true && vol.EnhancementType) { /*bool backgroundComposition = */ parser.GetBit(Attribute.BackgroundComposition); } parser.GetBit(Attribute.ChangeConvRatioDisable); bool vopConstantAlpha = parser.GetBit(Attribute.ConstantAlpha); byte vopConstantAlphaValue; if (vopConstantAlpha == true) { vopConstantAlphaValue = (byte)parser.GetBits(8); } else { vopConstantAlphaValue = 255; } Attributes.Add(new FormattedAttribute <Attribute, byte>(Attribute.ConstantAlphaValue, vopConstantAlphaValue)); } if (vol.VideoShape != VideoObjectLayer.Shape.BinaryOnly) { if (!vol.ComplexityEstimationDisable) { VideoObjectLayer.mp4_ComplexityEstimation complex; vol.ComplexityEstimation(out complex); if (complex.estimation_method == 0) { if (_codingType == (int)Mpeg4VopType.I_VOP) { if (complex.opaque) /*complex.dcecs_opaque =*/ parser {