public byte[] CreatePAT(JT1078Package jt1078Package, int minBufferSize = 188) { byte[] buffer = TSArrayPool.Rent(minBufferSize); try { TS_PAT_Package package = new TS_PAT_Package(); package.Header = new TS_Header(); package.Header.ContinuityCounter = 0; package.Header.AdaptationFieldControl = AdaptationFieldControl.无自适应域_仅含有效负载; package.Header.PayloadUnitStartIndicator = 1; package.Header.PID = 0; package.Programs = new List <TS_PAT_Program>(); package.Programs.Add(new TS_PAT_Program() { ProgramNumber = 0x0001, PID = 0x1000, }); TSMessagePackWriter messagePackReader = new TSMessagePackWriter(buffer); package.ToBuffer(ref messagePackReader); return(messagePackReader.FlushAndGetArray()); } finally { TSArrayPool.Return(buffer); } }
public byte[] CreatePMT(JT1078Package jt1078Package, int minBufferSize = 188) { byte[] buffer = TSArrayPool.Rent(minBufferSize); try { TS_PMT_Package package = new TS_PMT_Package(); package.Header = new TS_Header(); package.Header.ContinuityCounter = 0; package.Header.AdaptationFieldControl = AdaptationFieldControl.无自适应域_仅含有效负载; package.Header.PayloadUnitStartIndicator = 1; package.Header.PID = 4096; package.TableId = 0x02; package.Components = new List <TS_PMT_Component>(); package.Components.Add(new TS_PMT_Component { StreamType = StreamType.h264, ElementaryPID = 256, ESInfoLength = 0 }); TSMessagePackWriter messagePackReader = new TSMessagePackWriter(buffer); package.ToBuffer(ref messagePackReader); return(messagePackReader.FlushAndGetArray()); } finally { TSArrayPool.Return(buffer); } }
//private ConcurrentDictionary<string, byte> AudioCounter = new ConcurrentDictionary<string, byte>(); public byte[] CreatePAT(JT1078Package jt1078Package, int minBufferSize = 188) { byte[] buffer = TSArrayPool.Rent(minBufferSize); try { TS_PAT_Package package = new TS_PAT_Package(); package.Header = new TS_Header(); package.Header.ContinuityCounter = PATCounter.AddOrUpdate(jt1078Package.GetKey(), 0, (a, b) => { if (b > 0xf) { return(0); } else { return((byte)(b + 1)); } }); package.Header.AdaptationFieldControl = AdaptationFieldControl.无自适应域_仅含有效负载; package.Header.PayloadUnitStartIndicator = 1; package.Header.PID = 0; TSMessagePackWriter messagePackReader = new TSMessagePackWriter(buffer); package.ToBuffer(ref messagePackReader); return(messagePackReader.FlushAndGetArray()); } finally { TSArrayPool.Return(buffer); } }
/// <summary> /// 生成ts和m3u8文件 /// </summary> /// <param name="jt1078Package"></param> public void CreateTsData(JT1078Package jt1078Package) { string key = jt1078Package.GetKey(); string hlsFileDirectory = m3U8Option.HlsFileDirectory; string m3u8FileName = Path.Combine(hlsFileDirectory, key, m3U8Option.M3U8FileName); if (!File.Exists(m3u8FileName)) { File.Create(m3u8FileName); //创建m3u8文件 } var buff = TSArrayPool.Rent(jt1078Package.Bodies.Length + 1024); TSMessagePackWriter tSMessagePackWriter = new TSMessagePackWriter(buff); try { var curTsFileInfo = CreateTsFileInfo(key); if (!curTsFileInfo.IsCreateTsFile) { var pes = tSEncoder.CreatePES(jt1078Package); tSMessagePackWriter.WriteArray(pes); CreateTsFile(curTsFileInfo.FileName, key, tSMessagePackWriter.FlushAndGetArray()); curTsFileInfo.Duration = (jt1078Package.Timestamp - curTsFileInfo.TsFirst1078PackageTimeStamp) / 1000.0; //按设定的时间(默认为10秒)切分ts文件 if (curTsFileInfo.Duration > m3U8Option.TsFileMaxSecond) { var tsFileInfoQueue = ManageTsFileInfo(key, curTsFileInfo); CreateM3U8File(curTsFileInfo, tsFileInfoQueue); var newTsFileInfo = new TsFileInfo { IsCreateTsFile = true, Duration = 0, TsFileSerialNo = ++curTsFileInfo.TsFileSerialNo }; curTsFileInfoDic.TryUpdate(key, newTsFileInfo, curTsFileInfo); } } else { curTsFileInfo.IsCreateTsFile = false; curTsFileInfo.TsFirst1078PackageTimeStamp = jt1078Package.Timestamp; curTsFileInfo.FileName = $"{curTsFileInfo.TsFileSerialNo}.ts"; var sdt = tSEncoder.CreateSDT(jt1078Package); tSMessagePackWriter.WriteArray(sdt); var pat = tSEncoder.CreatePAT(jt1078Package); tSMessagePackWriter.WriteArray(pat); var pmt = tSEncoder.CreatePMT(jt1078Package); tSMessagePackWriter.WriteArray(pmt); var pes = tSEncoder.CreatePES(jt1078Package); tSMessagePackWriter.WriteArray(pes); CreateTsFile(curTsFileInfo.FileName, key, tSMessagePackWriter.FlushAndGetArray()); } } finally { TSArrayPool.Return(buff); } }
//private ConcurrentDictionary<string, byte> AudioCounter = new ConcurrentDictionary<string, byte>(); public byte[] CreateSDT(JT1078Package jt1078Package, int minBufferSize = 188) { byte[] buffer = TSArrayPool.Rent(minBufferSize); try { TS_SDT_Package package = new TS_SDT_Package(); package.Header = new TS_Header(); package.Header.PID = 0x0011; package.Header.AdaptationFieldControl = AdaptationFieldControl.无自适应域_仅含有效负载; package.Header.ContinuityCounter = 0; package.TableId = 0x42; package.TransportStreamId = 0x0001; package.VersionNumber = 0; package.CurrentNextIndicator = 0x01; package.SectionNumber = 0x00; package.LastSectionNumber = 0x00; package.OriginalNetworkId = 0xFF01; package.Services = new List <TS_SDT_Service>(); package.Services.Add(new TS_SDT_Service() { ServiceId = 0x0001, EITScheduleFlag = 0x00, EITPresentFollowingFlag = 0x00, RunningStatus = TS_SDT_Service_RunningStatus.运行, FreeCAMode = 0x00, Descriptors = new List <TS_SDT_Service_Descriptor> { new TS_SDT_Service_Descriptor { Tag = 0x48, ServiceType = TS_SDT_Service_Descriptor_ServiceType.数字电视业务, ServiceProvider = ServiceProvider, ServiceName = ServiceName } } }); TSMessagePackWriter writer = new TSMessagePackWriter(buffer); package.ToBuffer(ref writer); return(writer.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; 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); } }