public void ParseNALUTest2() { JT1078Package Package = null; var lines = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078.txt")); int mergeBodyLength = 0; foreach (var line in lines) { var data = line.Split(','); var bytes = data[5].ToHexBytes(); JT1078Package package = JT1078Serializer.Deserialize(bytes); mergeBodyLength += package.DataBodyLength; Package = JT1078Serializer.Merge(package); } Flv.H264.H264Decoder decoder = new Flv.H264.H264Decoder(); var nalus = decoder.ParseNALU(Package); Assert.Equal(4, nalus.Count); //SPS -> 7 var spsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == 7); Assert.NotNull(spsNALU); spsNALU.RawData = decoder.DiscardEmulationPreventionBytes(spsNALU.RawData); //"Z00AFJWoWCWQ" var spsRawDataHex = JsonConvert.SerializeObject(spsNALU.RawData); ExpGolombReader h264GolombReader = new ExpGolombReader(spsNALU.RawData); //(77, 20, 0, 352, 288) var spsInfo = h264GolombReader.ReadSPS(); Assert.Equal(77, spsInfo.profileIdc); Assert.Equal(20, spsInfo.levelIdc); Assert.Equal(0u, spsInfo.profileCompat); Assert.Equal(288, spsInfo.height); Assert.Equal(352, spsInfo.width); //PPS -> 8 var ppsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == 8); Assert.NotNull(ppsNALU); //IDR -> 5 关键帧 var idrNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == 5); Assert.NotNull(idrNALU); //SEI -> 6 var seiNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == 6); Assert.NotNull(seiNALU); }
public byte[] CreateFlvFrame(List <H264NALU> nALUs, int minimumLength = 10240) { byte[] buffer = FlvArrayPool.Rent(minimumLength); try { FlvMessagePackWriter flvMessagePackWriter = new FlvMessagePackWriter(buffer); int currentMarkPosition = 0; int nextMarkPosition = 0; H264NALU?sps = null, pps = null; foreach (var naln in nALUs) { string key = naln.GetKey(); if (!FrameInitDict.ContainsKey(key)) { if (naln.NALUHeader.NalUnitType == 7) { naln.RawData = H264Decoder.DiscardEmulationPreventionBytes(naln.RawData); sps = naln; } else if (naln.NALUHeader.NalUnitType == 8) { pps = naln; } if (sps != null && pps != null) { flvMessagePackWriter.WriteArray(CreateFlvFirstFrame(sps, pps)); FrameInitDict.TryAdd(key, true); } else { continue; } } if (PreviousTagSizeDict.TryGetValue(key, out uint previousTagSize)) { currentMarkPosition = flvMessagePackWriter.GetCurrentPosition(); CreateVideoTagOtherFrame(ref flvMessagePackWriter, previousTagSize, naln); nextMarkPosition = flvMessagePackWriter.GetCurrentPosition(); uint tmpPreviousTagSize = (uint)(nextMarkPosition - currentMarkPosition - PreviousTagSizeFixedLength); PreviousTagSizeDict.TryUpdate(key, tmpPreviousTagSize, previousTagSize); } } return(flvMessagePackWriter.FlushAndGetArray()); } finally { FlvArrayPool.Return(buffer); } }
public byte[] CreateFlvFrame(List <H264NALU> nALUs, int minimumLength = 65535) { byte[] buffer = FlvArrayPool.Rent(minimumLength); try { FlvMessagePackWriter flvMessagePackWriter = new FlvMessagePackWriter(buffer); int currentMarkPosition = 0; int nextMarkPosition = 0; H264NALU sps = null, pps = null; SPSInfo spsInfo = new SPSInfo(); foreach (var naln in nALUs) { string key = naln.GetKey(); if (sps != null && pps != null) { if (VideoSPSDict.TryGetValue(key, out var spsInfoCache)) { if (spsInfoCache.height != spsInfo.height && spsInfoCache.width != spsInfo.width) { if (FlvFrameInfoDict.TryGetValue(key, out FlvFrameInfo flvFrameInfo)) { CreateFlvKeyFrame(ref flvMessagePackWriter, key, sps.RawData, pps.RawData, spsInfo, flvFrameInfo.PreviousTagSize); FlvFirstFrameCache.TryRemove(key, out _); FlvFirstFrameCache.TryAdd(key, flvMessagePackWriter.FlushAndGetArray()); VideoSPSDict.TryUpdate(key, spsInfo, spsInfo); flvFrameInfo.LastFrameInterval = 0; FlvFrameInfoDict.TryUpdate(key, flvFrameInfo, flvFrameInfo); } } sps = null; pps = null; } else { CreateFlvKeyFrame(ref flvMessagePackWriter, key, sps.RawData, pps.RawData, spsInfo, 0); FlvFirstFrameCache.TryAdd(key, flvMessagePackWriter.FlushAndGetArray()); VideoSPSDict.TryAdd(key, spsInfo); sps = null; pps = null; } } //7 8 6 5 1 1 1 1 7 8 6 5 1 1 1 1 1 7 8 6 5 1 1 1 1 1 switch (naln.NALUHeader.NalUnitType) { case 5: // IDR case 1: // I/P/B if (FlvFrameInfoDict.TryGetValue(key, out FlvFrameInfo flvFrameInfo)) { currentMarkPosition = flvMessagePackWriter.GetCurrentPosition(); CreateVideoTagOtherFrame(ref flvMessagePackWriter, flvFrameInfo, naln); nextMarkPosition = flvMessagePackWriter.GetCurrentPosition(); uint tmpPreviousTagSize = (uint)(nextMarkPosition - currentMarkPosition - PreviousTagSizeFixedLength); flvFrameInfo.PreviousTagSize = tmpPreviousTagSize; flvFrameInfo.LastFrameInterval += naln.LastFrameInterval; FlvFrameInfoDict.TryUpdate(key, flvFrameInfo, flvFrameInfo); } break; case 7: // sps sps = naln; var rawData = H264Decoder.DiscardEmulationPreventionBytes(naln.RawData); ExpGolombReader h264GolombReader = new ExpGolombReader(rawData); spsInfo = h264GolombReader.ReadSPS(); break; case 8: // pps pps = naln; break; case 6: //SEI break; default: break; } } return(flvMessagePackWriter.FlushAndGetArray()); } finally { FlvArrayPool.Return(buffer); } }