public EltH264Nalu(CommonH264Nalu nalu) : base(nalu) { m_eNaluType = nalu.getNaluType(); m_LayerId = nalu.getLayerId(); m_PictureId = nalu.getPictureId(); m_SliceId = nalu.getSliceId(); }
public EltH264Nalu(CommonH264Nalu nalu) : base(nalu) { m_eNaluType = nalu.getNaluType(); m_LayerId = nalu.getLayerId(); m_PictureId = nalu.getPictureId(); m_SliceId = nalu.getSliceId(); }
public static NalUnitTypeDescriptor GetNalUnitType(NalUnitType nalUnitType) { var type = (int)nalUnitType; if (type < Types.Length) return Types[type]; return null; }
public static NalUnitTypeDescriptor GetNalUnitType(NalUnitType nalUnitType) { int index = (int)nalUnitType; if (index < NalUnitTypes.Types.Length) { return(NalUnitTypes.Types[index]); } return((NalUnitTypeDescriptor)null); }
/// <summary> /// Processes the given NAL Unit bytes. /// </summary> /// <param name="nalUnitBytes"></param> /// <returns>A potentially modified set of bytes for the NAL Unit.</returns> public byte[] ProcessNalUnit(byte[] nalUnitBytes) { NalUnitType nalUnitType = DetermineNalUnitType(nalUnitBytes); if (nalUnitType == NalUnitType.NAL_SPS) { nalUnitBytes = ProcessSequenceParameterSetNalUnit(nalUnitBytes); } return(nalUnitBytes); }
public void ParseHeader(IReaderState readerState) { bool firstHeader = (_state.NalUnitType == NalUnitType.Invalid); uint maxGapAfterNalUnit = GetMaxGapAfterNalUnit(_state.NalUnitType); long startPosition = _reader.Position; long maxNalUnitStartPosition = Math.Min(_reader.Length, (startPosition + maxGapAfterNalUnit)); NalUnitType previousNalUnitType = _state.NalUnitType; while (_dataReader.State == DataReaderState.Ready) { if (!firstHeader) { while (true) { if ((FindNalUnit(false) == null) || (_reader.Position >= maxNalUnitStartPosition) || (_dataReader.State != DataReaderState.Ready)) { _reader.Position = startPosition; readerState.Invalidate(); return; } var nextNalUnitType = (NalUnitType)(GetNalUnitByte() & 0x1f); if ((_reader.Position - startPosition) <= GetMaxGapBetweenNalUnits(previousNalUnitType, nextNalUnitType)) { break; } _reader.Position++; } } long nalUnitStartPosition = _reader.Position; readerState.Parse(_streamParser, _reader); if (readerState.Valid) { return; // Result is valid } if (firstHeader || (nalUnitStartPosition >= (maxNalUnitStartPosition - 1))) { return; // Done scanning for a valid result } readerState.Recover(); _reader.Position = (nalUnitStartPosition + 1); } // Nothing was found, so the result is invalid readerState.Invalidate(); }
private static bool CanParseNalUnitType(ISliceState sliceState, NalUnitType nalUnitType) { if (!IsSlice(nalUnitType)) { return(true); } if (sliceState == null) { return(false); // Slice with no picture parameter set available } // FIXME: certain CAVLC and CABAC files do not work, e.g. separate colour plane YCrCb 4:4:4 files return(true); // H.264 slice that can be parsed }
private uint GetMaxGapBetweenNalUnits(NalUnitType previousNalUnitType, NalUnitType nextNalUnitType) { if (previousNalUnitType == NalUnitType.Invalid) { return(0U); } if (previousNalUnitType == NalUnitType.SequenceParameterSet) { return((nextNalUnitType == NalUnitType.PictureParameterSet) ? _maxGapBetweenPpsAndSps : _maxGapBetweenNalUnits); } if (previousNalUnitType == NalUnitType.PictureParameterSet) { return((nextNalUnitType == NalUnitType.CodedSliceOfAnIdrPicture || nextNalUnitType == NalUnitType.CodedSliceOfANonIdrPicture) ? _maxGapBetweenPpsAndSlice : _maxGapBetweenNalUnits); } return(_maxGapBetweenNalUnits); }
private uint GetMaxGapAfterNalUnit(NalUnitType nalUnitType) { if (nalUnitType == NalUnitType.Invalid) { return(0); } if (nalUnitType == NalUnitType.SequenceParameterSet) { return(Math.Max(_maxGapBetweenPpsAndSps, _maxGapBetweenNalUnits)); } if (nalUnitType == NalUnitType.PictureParameterSet) { return(Math.Max(_maxGapBetweenPpsAndSlice, _maxGapBetweenNalUnits)); } return(_maxGapBetweenNalUnits); }
private void ParseData() { byte[] frameData = RawData; int frameSize = frameData.Length; // I know how my H.264 data source's NALUs looks like so I know start code index is always 0. // if you don't know where it starts, you can use a for loop similar to how I find the 2nd and 3rd start codes int startCodeIndex = 0; int secondStartCodeIndex = 0; int thirdStartCodeIndex = 0; int _spsSize = 0; int _ppsSize = 0; long blockLength = 0; _isParsed = true; NalUnitType type = (NalUnitType)(frameData[startCodeIndex + 4] & 0x1F); NalUnitTypes.Add(type); // NALU type 7 is the SPS parameter NALU if (type == NalUnitType.SEQUENCE_PARAMETER_SET) { // find where the second PPS start code begins, (the 0x00 00 00 01 code) // from which we also get the length of the first SPS code for (int i = startCodeIndex + 4; i < startCodeIndex + 40; i++) { if (frameData[i] == 0x00 && frameData[i + 1] == 0x00 && frameData[i + 2] == 0x00 && frameData[i + 3] == 0x01) { secondStartCodeIndex = i; _spsSize = secondStartCodeIndex; // includes the header in the size break; } } // find what the second NALU type is type = (NalUnitType)(frameData[secondStartCodeIndex + 4] & 0x1F); NalUnitTypes.Add(type); } // type 8 is the PPS parameter NALU if (type == NalUnitType.PICTURE_PARAMETER_SET) { // find where the NALU after this one starts so we know how long the PPS parameter is for (int i = _spsSize + 8; i < _spsSize + 50; i++) { if (frameData[i] == 0x00 && frameData[i + 1] == 0x00 && frameData[i + 2] == 0x00 && frameData[i + 3] == 0x01) { thirdStartCodeIndex = i; _ppsSize = thirdStartCodeIndex - _spsSize; break; } } if (_ppsSize < 4 || _spsSize < 4) { throw new InvalidDataException("Couldnt determine PPS/SPS size"); } // allocate enough data to fit the SPS and PPS parameters into our data objects. // NOTE: buffers won't contain NAL start-code (00 00 00 01) _ppsData = new byte[_ppsSize - 4]; _spsData = new byte[_spsSize - 4]; // copy in the actual sps and pps values, again ignoring the 4 byte header Array.Copy(frameData, 4, _spsData, 0, _spsSize - 4); Array.Copy(frameData, _spsSize + 4, _ppsData, 0, _ppsSize - 4); // now lets handle the IDR frame that (should) come after the parameter sets // I say "should" because that's how I expect my H264 stream to work, YMMV type = (NalUnitType)(frameData[thirdStartCodeIndex + 4] & 0x1F); NalUnitTypes.Add(type); } // NALU type 1 is non-IDR (or PFrame) picture // NALU type 5 is an IDR frame NALU. The SPS and PPS NALUs should always be followed by an IDR (or IFrame) NALU, as far as I know if (type == NalUnitType.P_FRAME || type == NalUnitType.I_FRAME) { // P-Frame (1): non-IDR frames do not have an offset due to SPS and PSS // I-Frame (5): find the offset, or where the SPS and PPS NALUs end and the IDR frame NALU begins int offset = type == NalUnitType.I_FRAME ? _spsSize + _ppsSize : 0; blockLength = frameSize - offset; // copy in the actual frame data, again ignoring the 4 byte header _frameData = new byte[blockLength - 4]; Array.Copy(frameData, offset + 4, _frameData, 0, blockLength - 4); } }
private static bool IsSlice(NalUnitType nalUnitType) { return((nalUnitType == NalUnitType.CodedSliceOfANonIdrPicture) || (nalUnitType == NalUnitType.CodedSliceOfAnIdrPicture)); }
public NalUnitType getNaluType() { NalUnitType ret = (NalUnitType)commonWRAPPINVOKE.CommonH264Nalu_getNaluType(swigCPtr); return(ret); }
public NalUnitTypeDescriptor(NalUnitType type, string name, string description) { this._type = type; this._name = name; this._description = description; }