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); }