public byte[] CreatePES(JT1078Package jt1078Package, int minBufferSize = 188) { //将1078一帧的数据拆分成一小段一小段的PES包 byte[] buffer = TSArrayPool.Rent(jt1078Package.Bodies.Length + minBufferSize); TSMessagePackWriter messagePackReader = new TSMessagePackWriter(buffer); //TSHeader + Adaptation + PES1 //TSHeader + PES2 //TSHeader + Adaptation + PESN try { int totalLength = 0; TS_Package package = new TS_Package(); package.Header = new TS_Header(); //ts header 4 totalLength += 4; package.Header.PID = 256; package.Header.PackageType = PackageType.Data_Start; string key = jt1078Package.GetKey(); if (VideoCounter.TryGetValue(key, out byte counter)) { if (counter > 0xf) { counter = 0; } } else { VideoCounter.Add(key, counter); } package.Header.ContinuityCounter = counter; counter++; package.Header.PayloadUnitStartIndicator = 1; package.Header.Adaptation = new TS_AdaptationInfo(); package.Payload = new PES_Package(); package.Payload.StreamId = 0xe0; package.Payload.PESPacketLength = 0; //PESStartCode + StreamId+ Flag1 + PTS_DTS_Flag + PESPacketLength //3 + 1 + 1 + 1 + 2 totalLength += (3 + 1 + 1 + 1 + 2); package.Payload.PTS_DTS_Flag = PTS_DTS_Flags.all; long timestamp = (long)jt1078Package.Timestamp; if (jt1078Package.Label3.DataType == JT1078DataType.视频I帧) { //ts header adaptation //PCRIncluded + Timestamp //1 + 6 totalLength += (1 + 6); package.Header.Adaptation.PCRIncluded = PCRInclude.包含; package.Header.Adaptation.Timestamp = timestamp; package.Payload.DTS = timestamp * H264DefaultHZ; package.Payload.PTS = package.Payload.DTS + jt1078Package.LastIFrameInterval * H264DefaultHZ; } else if (jt1078Package.Label3.DataType == JT1078DataType.视频P帧) { //ts header adaptation //PCRIncluded //1 totalLength += 1; package.Header.Adaptation.PCRIncluded = PCRInclude.包含; package.Payload.DTS = timestamp * H264DefaultHZ; package.Payload.PTS = package.Payload.DTS + jt1078Package.LastFrameInterval * H264DefaultHZ; } //Flag1 + PTS_DTS_Flag + DTS + PTS //1 + 1 + 5 + 5 = 12 totalLength += 12; totalLength += TSConstants.FiexdESPackageHeaderLength; //根据计算剩余的长度进行是否需要填充第一包 var remainingLength = FiexdTSLength - totalLength; int index = 0; //情况1:1078的第一包不够剩余(remainingLength)字节 //情况2:1078的第一包比剩余(remainingLength)字节多 //情况3: 1078的第一包等于剩余(remainingLength)字节 //填充大小 int fullSize = jt1078Package.Bodies.Length - remainingLength; package.Payload.Payload = new ES_Package(); if (fullSize < 0) { //这个很重要,需要控制 package.Header.AdaptationFieldControl = AdaptationFieldControl.时带有自适应域和有效负载; //还差一点 fullSize = Math.Abs(fullSize); package.Header.Adaptation.FillSize = (byte)fullSize; package.Payload.Payload.NALUs = new List <byte[]>() { jt1078Package.Bodies }; package.ToBuffer(ref messagePackReader); } else if (fullSize == 0) { //这个很重要,需要控制 package.Header.AdaptationFieldControl = AdaptationFieldControl.无自适应域_仅含有效负载; //刚刚好 package.Header.Adaptation.FillSize = 0; package.Payload.Payload.NALUs = new List <byte[]>() { jt1078Package.Bodies }; package.ToBuffer(ref messagePackReader); } else { //这个很重要,需要控制 package.Header.AdaptationFieldControl = AdaptationFieldControl.时带有自适应域和有效负载; //太多了,需要拆分 package.Header.Adaptation.FillSize = 0; package.Payload.Payload.NALUs = new List <byte[]>(); ReadOnlySpan <byte> dataReader = jt1078Package.Bodies; package.Payload.Payload.NALUs.Add(dataReader.Slice(index, remainingLength).ToArray()); index += remainingLength; package.ToBuffer(ref messagePackReader); while (index != jt1078Package.Bodies.Length) { if (counter > 0xf) { counter = 0; } int segmentFullSize = jt1078Package.Bodies.Length - index; if (segmentFullSize >= FiexdSegmentPESLength) { CreateSegmentPES(ref messagePackReader, dataReader.Slice(index, FiexdSegmentPESLength).ToArray(), counter); index += FiexdSegmentPESLength; } else { var nalu = dataReader.Slice(index, segmentFullSize).ToArray(); //当等于183字节的时候 //12698D08E8DBDBCDF6C6FA19DD88490E908D687D1755BE87DF82754BE2D245270569310B3030A4904DF1883ED09A68CA1C79BC4B97642B5BC095A55E56868D05370D3BC8B7B60B4642A486B6852656C01FFADACEF4BD4320E8BE9C54D44177A433CC37493FA1D8ACD0164E92454D03B6EC0617B133AEF43B599BF85632AB9B5FF671F0DDAA07E8F279F5639BA88E3FFFFCE1D3351FAF43DF23BCEB7E3B2CAB3EABAED23B25097B7F51FF38E8D0EBAB589CEC42B0440EB8 //if (jt1078Package.Label3.DataType == JT1078DataType.视频P帧) //{ // string hex = dataReader.Slice(index, segmentFullSize).ToArray().ToHexString(); //} CreateSegmentPES(ref messagePackReader, dataReader.Slice(index, segmentFullSize).ToArray(), counter); index += segmentFullSize; } counter++; } } VideoCounter[key] = counter; return(messagePackReader.FlushAndGetArray()); } finally { TSArrayPool.Return(buffer); } }
public byte[] CreatePES(JT1078Package jt1078Package, int minBufferSize = 188) { //将1078一帧的数据拆分成一小段一小段的PES包 byte[] buffer = TSArrayPool.Rent(jt1078Package.Bodies.Length + minBufferSize); TSMessagePackWriter messagePackReader = new TSMessagePackWriter(buffer); //TSHeader + Adaptation + PES1 //TSHeader + PES2 //TSHeader + Adaptation + PESN try { int totalLength = 0; TS_Package package = new TS_Package(); package.Header = new TS_Header(); //ts header 4 totalLength += 4; package.Header.PID = 256; string key = jt1078Package.GetKey(); if (VideoCounter.TryGetValue(key, out byte counter)) { if (counter > 0xf) { counter = 0; } package.Header.ContinuityCounter = counter++; VideoCounter.TryUpdate(key, counter, counter); } else { package.Header.ContinuityCounter = counter++; VideoCounter.TryAdd(key, counter); } package.Header.PayloadUnitStartIndicator = 1; package.Header.Adaptation = new TS_AdaptationInfo(); package.Payload = new PES_Package(); package.Payload.StreamId = 0xe0; package.Payload.PESPacketLength = 0; //PESStartCode + StreamId + PESPacketLength //3 + 1 + 2 totalLength += (3 + 1 + 2); package.Payload.PTS_DTS_Flag = PTS_DTS_Flags.all; if (jt1078Package.Label3.DataType == JT1078DataType.视频I帧) { //ts header adaptation //PCRIncluded + PCR //1 + 5 totalLength += (1 + 5); package.Header.Adaptation.PCRIncluded = PCRInclude.包含; package.Header.Adaptation.PCR = jt1078Package.LastIFrameInterval; package.Payload.DTS = jt1078Package.LastIFrameInterval; package.Payload.PTS = jt1078Package.LastIFrameInterval; } else { //ts header adaptation //PCRIncluded //1 totalLength += 1; package.Header.Adaptation.PCRIncluded = PCRInclude.包含; package.Payload.DTS = jt1078Package.LastFrameInterval; package.Payload.PTS = jt1078Package.LastFrameInterval; } //Flag1 + PTS_DTS_Flag + DTS + PTS //1 + 1 + 5 + 5 totalLength += 12; //根据计算剩余的长度进行是否需要填充第一包 var remainingLength = FiexdTSLength - totalLength; int index = 0; //情况1:1078的第一包不够剩余(remainingLength)字节 //情况2:1078的第一包比剩余(remainingLength)字节多 //情况3: 1078的第一包等于剩余(remainingLength)字节 //填充大小 int fullSize = jt1078Package.Bodies.Length - remainingLength; package.Payload.Payload = new ES_Package(); if (fullSize < 0) { //这个很重要,需要控制 package.Header.AdaptationFieldControl = AdaptationFieldControl.时带有自适应域和有效负载; //还差一点 fullSize = Math.Abs(fullSize); package.Header.Adaptation.FillSize = (byte)fullSize; package.Payload.Payload.NALUs = new List <byte[]>() { jt1078Package.Bodies }; package.ToBuffer(ref messagePackReader); } else if (fullSize == 0) { //这个很重要,需要控制 package.Header.AdaptationFieldControl = AdaptationFieldControl.无自适应域_仅含有效负载; //刚刚好 package.Header.Adaptation.FillSize = 0; package.Payload.Payload.NALUs = new List <byte[]>() { jt1078Package.Bodies }; package.ToBuffer(ref messagePackReader); } else { //这个很重要,需要控制 package.Header.AdaptationFieldControl = AdaptationFieldControl.时带有自适应域和有效负载; //太多了,需要拆分 package.Header.Adaptation.FillSize = 0; package.Payload.Payload.NALUs = new List <byte[]>(); ReadOnlySpan <byte> dataReader = jt1078Package.Bodies; package.Payload.Payload.NALUs.Add(dataReader.Slice(index, remainingLength).ToArray()); index += remainingLength; package.ToBuffer(ref messagePackReader); while (index != jt1078Package.Bodies.Length) { if (counter > 0xf) { counter = 0; } int segmentFullSize = jt1078Package.Bodies.Length - index; if (segmentFullSize >= FiexdSegmentPESLength) { CreateSegmentPES(ref messagePackReader, dataReader.Slice(index, FiexdSegmentPESLength).ToArray(), counter++); } else { CreateSegmentPES(ref messagePackReader, dataReader.Slice(index, segmentFullSize).ToArray(), counter++); index += segmentFullSize; } } VideoCounter.TryUpdate(key, counter, counter); } return(messagePackReader.FlushAndGetArray()); } finally { TSArrayPool.Return(buffer); } }