From b5e599b544991312e6a3a1d2b7a505ea38d333d1 Mon Sep 17 00:00:00 2001 From: "SmallChi(Koike)" <564952747@qq.com> Date: Wed, 31 Mar 2021 18:57:00 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=861078=E8=BD=ACfmp4=5F12?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/JT1078.FMp4.Test/JT1078ToFMp4Box_Test.cs | 27 +++++++++++++--- .../Boxs/TrackFragmentHeaderBox.cs | 1 + src/JT1078.FMp4/FMp4Encoder.cs | 32 +++++++++++-------- src/JT1078.FMp4/JT1078.FMp4.xml | 5 +-- .../Services/ToWebSocketService.cs | 17 +++++----- 5 files changed, 53 insertions(+), 29 deletions(-) diff --git a/src/JT1078.FMp4.Test/JT1078ToFMp4Box_Test.cs b/src/JT1078.FMp4.Test/JT1078ToFMp4Box_Test.cs index f8ccb42..b71a4bb 100644 --- a/src/JT1078.FMp4.Test/JT1078ToFMp4Box_Test.cs +++ b/src/JT1078.FMp4.Test/JT1078ToFMp4Box_Test.cs @@ -451,17 +451,36 @@ namespace JT1078.FMp4.Test var nalus1 = h264Decoder.ParseNALU(package1); var moov = fMp4Encoder.EncoderMoovBox(nalus1, package1.Bodies.Length); fileStream.Write(moov); + List filter = new List() { + NalUnitType.SPS, + NalUnitType.PPS, + NalUnitType.AUD}; + int i = 0; foreach (var package in packages) { var otherStypBuffer = fMp4Encoder.EncoderStypBox(); fileStream.Write(otherStypBuffer); var otherNalus = h264Decoder.ParseNALU(package); - var flag = package.Label3.DataType == Protocol.Enums.JT1078DataType.视频I帧 ? 1u : 0u; + //var filterOtherNalus = otherNalus.Where(w => !filter.Contains(w.NALUHeader.NalUnitType)).ToList(); + //if (filterOtherNalus.Count <= 0) + //{ + // continue; + //} + //int length = filterOtherNalus.Sum(s => s.RawData.Length); + foreach(var nalu in otherNalus) + { + //H264 NALU slice first_mb_in_slice + if ((nalu.RawData[1] & 0x80) == 0x80) + { - var otherMoofBuffer = fMp4Encoder.EncoderMoofBox(otherNalus, package.Bodies.Length, package.Timestamp, package.LastIFrameInterval, flag); + } + } + var flag = package.Label3.DataType == Protocol.Enums.JT1078DataType.视频I帧 ? 1u : 0u; + var otherMoofBuffer = fMp4Encoder.EncoderMoofBox(otherNalus, package.Bodies.Length, package.Timestamp, package.LastFrameInterval, package.LastIFrameInterval, flag); var otherMdatBuffer = fMp4Encoder.EncoderMdatBox(otherNalus, package.Bodies.Length); - var otherSidxBuffer = fMp4Encoder.EncoderSidxBox(otherMoofBuffer.Length + otherMdatBuffer.Length, package.Timestamp, package.LastIFrameInterval); - + //var otherMoofBuffer = fMp4Encoder.EncoderMoofBox(filterOtherNalus, length, package.Timestamp, package.LastFrameInterval, package.LastIFrameInterval, flag); + //var otherMdatBuffer = fMp4Encoder.EncoderMdatBox(filterOtherNalus, length); + var otherSidxBuffer = fMp4Encoder.EncoderSidxBox(otherMoofBuffer.Length + otherMdatBuffer.Length, package.Timestamp, package.LastIFrameInterval, package.LastFrameInterval); fileStream.Write(otherSidxBuffer); fileStream.Write(otherMoofBuffer); fileStream.Write(otherMdatBuffer); diff --git a/src/JT1078.FMp4/Boxs/TrackFragmentHeaderBox.cs b/src/JT1078.FMp4/Boxs/TrackFragmentHeaderBox.cs index 290d8ed..ebb721d 100644 --- a/src/JT1078.FMp4/Boxs/TrackFragmentHeaderBox.cs +++ b/src/JT1078.FMp4/Boxs/TrackFragmentHeaderBox.cs @@ -49,6 +49,7 @@ namespace JT1078.FMp4 public uint DefaultSampleSize { get; set; } /// /// TFHD_FLAG_DEFAULT_FLAGS + /// MOV_AUDIO == handler_type ? 0x02000000 : (0x00010000| 0x01000000); /// public uint DefaultSampleFlags { get; set; } #endregion diff --git a/src/JT1078.FMp4/FMp4Encoder.cs b/src/JT1078.FMp4/FMp4Encoder.cs index 2eaa5be..23c3dbe 100644 --- a/src/JT1078.FMp4/FMp4Encoder.cs +++ b/src/JT1078.FMp4/FMp4Encoder.cs @@ -108,11 +108,13 @@ namespace JT1078.FMp4 } } + uint IframeIntervalCache = 259960; + /// /// 编码sidx盒子 /// /// - public byte[] EncoderSidxBox(int moofAndMdatLength, ulong timestamp, uint frameInterval) + public byte[] EncoderSidxBox(int moofAndMdatLength, ulong timestamp, uint IframeInterval, uint frameInterval) { byte[] buffer = FMp4ArrayPool.Rent(4096); FMp4MessagePackWriter writer = new FMp4MessagePackWriter(buffer); @@ -120,7 +122,7 @@ namespace JT1078.FMp4 { SegmentIndexBox segmentIndexBox = new SegmentIndexBox(1); segmentIndexBox.ReferenceID = 1; - segmentIndexBox.EarliestPresentationTime = timestamp*1000; + segmentIndexBox.EarliestPresentationTime = timestamp; segmentIndexBox.SegmentIndexs = new List() { new SegmentIndexBox.SegmentIndex @@ -203,7 +205,7 @@ namespace JT1078.FMp4 avc1.AVCConfigurationBox.SPSs = new List() { spsNALU.RawData }; movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.SampleEntries.Add(avc1); movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.TimeToSampleBox = new TimeToSampleBox(); - movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SyncSampleBox = new SyncSampleBox(); + movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SyncSampleBox = new SyncSampleBox(); movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleToChunkBox = new SampleToChunkBox(); movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleSizeBox = new SampleSizeBox(); movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.ChunkOffsetBox = new ChunkOffsetBox(); @@ -230,7 +232,7 @@ namespace JT1078.FMp4 /// 编码Moof盒子 /// /// - public byte[] EncoderMoofBox(List nalus, int naluLength,ulong timestamp,uint frameInterval, uint keyframeFlag,int moofOffset=0) + public byte[] EncoderMoofBox(List nalus, int naluLength, ulong timestamp, uint frameInterval, uint IframeInterval, uint keyframeFlag) { byte[] buffer = FMp4ArrayPool.Rent(naluLength + 4096); FMp4MessagePackWriter writer = new FMp4MessagePackWriter(buffer); @@ -242,8 +244,9 @@ namespace JT1078.FMp4 movieFragmentBox.TrackFragmentBox = new TrackFragmentBox(); //0x39 写文件 //0x02 分段 - movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox = new TrackFragmentHeaderBox(0x20038); + movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox = new TrackFragmentHeaderBox(0x2003a); movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.TrackID = 1; + movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.SampleDescriptionIndex = 1; movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleDuration = frameInterval; movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleSize = (uint)naluLength; movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleFlags = 0x1010000; @@ -254,19 +257,21 @@ namespace JT1078.FMp4 //0x02 分段 //0x205 //uint flag = 0x000200 | 0x000800 | 0x000400 | 0x000100; - movieFragmentBox.TrackFragmentBox.TrackRunBox = new TrackRunBox(); - movieFragmentBox.TrackFragmentBox.TrackRunBox.FirstSampleFlags = 33554432; - movieFragmentBox.TrackFragmentBox.TrackRunBox.TrackRunInfos = new List(); - if (frameIntervalCache == 0) + uint flag = 0x0001; + if (keyframeFlag == 1) { - frameIntervalCache += frameInterval; + flag |= 0x0004; } + //flag |= 0x000200; + movieFragmentBox.TrackFragmentBox.TrackRunBox = new TrackRunBox(flags: flag); + movieFragmentBox.TrackFragmentBox.TrackRunBox.FirstSampleFlags = 33554432; + movieFragmentBox.TrackFragmentBox.TrackRunBox.TrackRunInfos = new List(); movieFragmentBox.TrackFragmentBox.TrackRunBox.TrackRunInfos.Add(new TrackRunBox.TrackRunInfo() { - SampleDuration= frameIntervalCache, + //SampleDuration= frameInterval, SampleSize = (uint)naluLength, - SampleCompositionTimeOffset = (long)timestamp , - SampleFlags = movieFragmentBox.TrackFragmentBox.TrackRunBox.Flags + //SampleCompositionTimeOffset = frameInterval, + //SampleFlags = movieFragmentBox.TrackFragmentBox.TrackRunBox.Flags }); movieFragmentBox.ToBuffer(ref writer); var data = writer.FlushAndGetArray(); @@ -399,7 +404,6 @@ namespace JT1078.FMp4 } uint sn = 1; - uint frameIntervalCache = 0; bool first = false; /// diff --git a/src/JT1078.FMp4/JT1078.FMp4.xml b/src/JT1078.FMp4/JT1078.FMp4.xml index 0448ef6..3844fe2 100644 --- a/src/JT1078.FMp4/JT1078.FMp4.xml +++ b/src/JT1078.FMp4/JT1078.FMp4.xml @@ -983,6 +983,7 @@ TFHD_FLAG_DEFAULT_FLAGS + MOV_AUDIO == handler_type ? 0x02000000 : (0x00010000| 0x01000000); @@ -1335,7 +1336,7 @@ - + 编码sidx盒子 @@ -1347,7 +1348,7 @@ - + 编码Moof盒子 diff --git a/src/JT1078.SignalR.Test/Services/ToWebSocketService.cs b/src/JT1078.SignalR.Test/Services/ToWebSocketService.cs index 85bb897..0f0b0c3 100644 --- a/src/JT1078.SignalR.Test/Services/ToWebSocketService.cs +++ b/src/JT1078.SignalR.Test/Services/ToWebSocketService.cs @@ -79,20 +79,19 @@ namespace JT1078.SignalR.Test.Services //q.Enqueue(moov); first.Add(moov); q.Add(first.SelectMany(s=>s).ToArray()); - List filter = new List() { NalUnitType.SEI,NalUnitType.SPS,NalUnitType.PPS}; + List filter = new List() { NalUnitType.SEI,NalUnitType.SPS,NalUnitType.PPS,NalUnitType.AUD}; foreach (var package in packages) { List other = new List(); + var otherStypBuffer = fMp4Encoder.EncoderStypBox(); + other.Add(otherStypBuffer); var otherNalus = h264Decoder.ParseNALU(package); - var filterNalus = otherNalus.Where(w => !filter.Contains(w.NALUHeader.NalUnitType)).ToList(); var flag = package.Label3.DataType == Protocol.Enums.JT1078DataType.视频I帧 ? 1u : 0u; - var len = filterNalus.Sum(s => s.RawData.Length); - var len1 = otherNalus.Sum(s => s.RawData.Length); - var moofBuffer = fMp4Encoder.EncoderMoofBox(filterNalus, len, package.Timestamp, package.LastIFrameInterval, flag); - //q.Enqueue(moofBuffer); - other.Add(moofBuffer); - var otherMdatBuffer = fMp4Encoder.EncoderMdatBox(filterNalus, len); - //q.Enqueue(otherMdatBuffer); + var otherMoofBuffer = fMp4Encoder.EncoderMoofBox(otherNalus, package.Bodies.Length, package.Timestamp, package.LastFrameInterval, package.LastIFrameInterval, flag); + var otherMdatBuffer = fMp4Encoder.EncoderMdatBox(otherNalus, package.Bodies.Length); + var otherSidxBuffer = fMp4Encoder.EncoderSidxBox(otherMoofBuffer.Length + otherMdatBuffer.Length, package.Timestamp, package.LastIFrameInterval, package.LastFrameInterval); + other.Add(otherSidxBuffer); + other.Add(otherMoofBuffer); other.Add(otherMdatBuffer); q.Add(other.SelectMany(s => s).ToArray()); }