// start reading at a byte boundary public virtual void Read(BitReader bitReader) { _positionInStream = bitReader.Position; Byte firstByte = bitReader.ReadByte(); Byte idc = (Byte)(firstByte >> 5); if ((idc > 0) != (NALRefIDC > 0)) // if it's not as expected, then throw exception { throw new Exception("NALU base class: unexpected Ref IDC"); } NALUnitType naluType = (NALUnitType)(firstByte & 0x1F); if (naluType != NALUType) { throw new Exception("NALU base class: unexpected NALU type"); } }
public CodedSliceBase(SequenceParameterSet sps, PictureParameterSet pps, Byte idc, NALUnitType naluType, uint size) { Nalu = new NetworkAbstractionLayerUnit(idc, naluType, size); Header = new SliceHeader(sps, pps, Nalu); Data = new SliceData(sps, pps, Header, Nalu); }
/// <summary> /// Internal method for locating next NAL unit of specific type. /// </summary> /// <param name="data"></param> /// <param name="offset"></param> /// <param name="end"></param> /// <param name="type"></param> /// <returns></returns> private int FindNALUnitStart(byte[] data, int offset, int end, NALUnitType type) { for (int i = offset; i < end - 3; i++) { if (data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1 && (data[i + 3] & 0x1F) == (byte)type) { if (i > offset && data[i - 1] == 0) i--; return i; } } return -1; }
public NetworkAbstractionLayerUnit(byte idc, NALUnitType naluType, uint size) : this(size) { NALRefIDC = idc; NALUType = naluType; }
public CodedSlicePartitionBorC(SequenceParameterSet sps, PictureParameterSet pps, byte idc, NALUnitType naluType, uint size) : base(sps, pps, (byte)0, NALUnitType.SlicePartitionA, size) { _pps = pps; }
public CodedSliceWithoutPartition(SequenceParameterSet sps, PictureParameterSet pps, Byte idc, NALUnitType naluType, uint size) : base(sps, pps, idc, naluType, size) { }
void ParseThreadProc(object buffer) { byte[] sliceBytes = buffer as byte[]; BitReader br = new BitReader(new MemoryStream(sliceBytes)); int totalSize = _totalSize; int offset = 0; int state = 0; while (totalSize > 4) { int naluLen = (int)br.GetUIntFromNBits(32); if (naluLen > totalSize) { throw new Exception("H264 parsing: wrong byte count encountered"); } if (naluLen > 0) { byte b = br.PeekByte(); byte refIDC = (byte)(b >> 5); NALUnitType naluType = (NALUnitType)(b & 0x1F); switch (state) { case 0: AccessUnitDelimiter aud = new AccessUnitDelimiter((uint)naluLen); aud.Read(br); state = 1; break; case 1: // either SEI or SPS (if it's an SEI, don't change state) if (naluType == NALUnitType.SupplementalEnhancementInfo) { SupplementatlEnhancementMessage sei = new SupplementatlEnhancementMessage(_sps, (uint)naluLen); sei.Read(br); } else if (naluType == NALUnitType.SequenceParamSet) { // replace _sps _sps = new SequenceParameterSet((uint)naluLen); _sps.Read(br); } else if (naluType == NALUnitType.PictureParamSet) { // replace _pps _pps = new PictureParameterSet((uint)naluLen); _pps.Read(br); } else if (naluType == NALUnitType.IDRSlice) { CodedSliceIDR idr = new CodedSliceIDR(_sps, _pps, (uint)naluLen); idr.Read(br); SliceType = idr.Header.SliceType; FrameNum = idr.Header.FrameNum; state = 2; // next should be zero or more redundant coded pictures } else if (naluType == NALUnitType.NonIDRSlice) { CodedSliceNonIDR nonIdr = new CodedSliceNonIDR(_sps, _pps, GetIDC(refIDC), (uint)naluLen); nonIdr.Read(br); SliceType = nonIdr.Header.SliceType; FrameNum = nonIdr.Header.FrameNum; state = 2; // next should be zero or more redundant coded pictures } else if (naluType == NALUnitType.SlicePartitionA) { CodedSlicePartitionA partA = new CodedSlicePartitionA(_sps, _pps, GetIDC(refIDC), (uint)naluLen); partA.Read(br); SliceType = partA.Header.SliceType; FrameNum = partA.Header.FrameNum; state = 2; // next should be zero or more redundant coded pictures } else if ((naluType == NALUnitType.SlicePartitionB) || (naluType == NALUnitType.SlicePartitionC)) { CodedSlicePartitionBorC partBC = new CodedSlicePartitionBorC(_sps, _pps, GetIDC(refIDC), naluType, (uint)naluLen); partBC.Read(br); // FIXME: check that SliceType and FrameNum are set at this point state = 2; // next should be zero or more redundant coded pictures } break; case 2: // either coded picture or end of sequence break; default: break; } offset += naluLen; totalSize -= (naluLen + 4); } else { naluLen = 0; // debugging break point } } if (SampleDoneEvent != null) { SampleDoneEvent(this); } }