From fc6d0d8b52c79a08e85943266a6ee235260308f8 Mon Sep 17 00:00:00 2001 From: "SmallChi(Koike)" <564952747@qq.com> Date: Sat, 10 Apr 2021 18:05:31 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=861078=E8=BD=ACfmp4=5F17=20ff=E5=8F=AF?= =?UTF-8?q?=E6=92=AD=E6=94=BE=EF=BC=8Cvlc=E5=8F=AF=E6=92=AD=E6=94=BE?= =?UTF-8?q?=EF=BC=8CMSE=E5=8F=AF=E6=92=AD=E6=94=BE=E3=80=81=E6=B5=8F?= =?UTF-8?q?=E8=A7=88=E5=99=A8=E5=8F=AF=E6=92=AD=E6=94=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/ffmpeginfo.txt | 2 +- src/JT1078.FMp4.Test/JT1078ToFMp4Box_Test.cs | 55 +++++++- src/JT1078.FMp4/FMp4Encoder.cs | 133 ++++++++++++------- src/JT1078.FMp4/JT1078.FMp4.xml | 6 + 4 files changed, 140 insertions(+), 56 deletions(-) diff --git a/doc/ffmpeginfo.txt b/doc/ffmpeginfo.txt index 9b52c27..c4fb52d 100644 --- a/doc/ffmpeginfo.txt +++ b/doc/ffmpeginfo.txt @@ -1,6 +1,6 @@ ffmpeg -i demo.mp4 -c copy -f flv -vcodec h264 -acodec aac demo_flv.flv -./ffmpeg -i JT1078_3.h264 -r 25 -c copy -f flv "D:\JT1078_3.flv" +ffmpeg -i JT1078_3.h264 -c copy -f flv JT1078_3.flv ffmpeg -f dshow -i video="USB2.0 PC CAMERA" -t 60 -c copy -f h264 -vcodec h264 ipc.264 diff --git a/src/JT1078.FMp4.Test/JT1078ToFMp4Box_Test.cs b/src/JT1078.FMp4.Test/JT1078ToFMp4Box_Test.cs index 7c56a3d..3b8e92a 100644 --- a/src/JT1078.FMp4.Test/JT1078ToFMp4Box_Test.cs +++ b/src/JT1078.FMp4.Test/JT1078ToFMp4Box_Test.cs @@ -444,20 +444,18 @@ namespace JT1078.FMp4.Test { File.Delete(filepath); } + using var fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write); var ftyp = fMp4Encoder.EncoderFtypBox(); fileStream.Write(ftyp); - List filter = new List() { - NalUnitType.SPS, - NalUnitType.PPS, - NalUnitType.AUD - }; + var iNalus = h264Decoder.ParseNALU(packages[0]); //判断第一帧是否关键帧 var moov = fMp4Encoder.EncoderMoovBox( iNalus.FirstOrDefault(f => f.NALUHeader.NalUnitType == NalUnitType.SPS), iNalus.FirstOrDefault(f => f.NALUHeader.NalUnitType == NalUnitType.PPS)); fileStream.Write(moov); + List nalus = new List(); foreach (var package in packages) { @@ -482,6 +480,53 @@ namespace JT1078.FMp4.Test } } fileStream.Close(); + } + + [Fact] + public void Test5() + { + FMp4Encoder fMp4Encoder = new FMp4Encoder(); + H264Decoder h264Decoder = new H264Decoder(); + var packages = ParseNALUTests(); + var filepath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_6.mp4"); + if (File.Exists(filepath)) + { + File.Delete(filepath); + } + using var fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write); + + var ftyp = fMp4Encoder.EncoderFtypBox(); + fileStream.Write(ftyp); + + var iNalus = h264Decoder.ParseNALU(packages[0]); + //判断第一帧是否关键帧 + var moov = fMp4Encoder.EncoderMoovBox( + iNalus.FirstOrDefault(f => f.NALUHeader.NalUnitType == NalUnitType.SPS), + iNalus.FirstOrDefault(f => f.NALUHeader.NalUnitType == NalUnitType.PPS)); + fileStream.Write(moov); + + List nalus = new List(); + foreach (var package in packages) + { + List h264NALUs = h264Decoder.ParseNALU(package); + if(package.Label3.DataType== Protocol.Enums.JT1078DataType.视频I帧) + { + if (nalus.Count > 0) + { + var otherBuffer = fMp4Encoder.EncoderOtherVideoBox(nalus); + fileStream.Write(otherBuffer); + nalus.Clear(); + } + } + nalus = nalus.Concat(h264NALUs).ToList(); + } + if (nalus.Count > 0) + { + var otherBuffer = fMp4Encoder.EncoderOtherVideoBox(nalus); + fileStream.Write(otherBuffer); + nalus.Clear(); + } + fileStream.Close(); } [Fact] diff --git a/src/JT1078.FMp4/FMp4Encoder.cs b/src/JT1078.FMp4/FMp4Encoder.cs index 28cc9dd..a92b370 100644 --- a/src/JT1078.FMp4/FMp4Encoder.cs +++ b/src/JT1078.FMp4/FMp4Encoder.cs @@ -41,21 +41,13 @@ namespace JT1078.FMp4 try { //ftyp - //FileTypeBox fileTypeBox = new FileTypeBox(); - //fileTypeBox.MajorBrand = "isom"; - //fileTypeBox.MinorVersion = "\0\0\u0002\0"; - //fileTypeBox.CompatibleBrands.Add("isom"); - //fileTypeBox.CompatibleBrands.Add("iso2"); - //fileTypeBox.CompatibleBrands.Add("avc1"); - //fileTypeBox.CompatibleBrands.Add("mp41"); - //fileTypeBox.CompatibleBrands.Add("iso5"); FileTypeBox fileTypeBox = new FileTypeBox(); - fileTypeBox.MajorBrand = "msdh"; - fileTypeBox.MinorVersion = "\0\0\0\0"; + fileTypeBox.MajorBrand = "isom"; + fileTypeBox.MinorVersion = "\0\0\u0002\0"; fileTypeBox.CompatibleBrands.Add("isom"); - fileTypeBox.CompatibleBrands.Add("mp42"); - fileTypeBox.CompatibleBrands.Add("msdh"); - fileTypeBox.CompatibleBrands.Add("msix"); + fileTypeBox.CompatibleBrands.Add("iso2"); + fileTypeBox.CompatibleBrands.Add("avc1"); + fileTypeBox.CompatibleBrands.Add("mp41"); fileTypeBox.CompatibleBrands.Add("iso5"); fileTypeBox.CompatibleBrands.Add("iso6"); fileTypeBox.ToBuffer(ref writer); @@ -152,8 +144,6 @@ namespace JT1078.FMp4 uint sn = 1; - public ulong timestampCache = 0; - /// /// 编码其他视频数据盒子 /// @@ -164,41 +154,90 @@ namespace JT1078.FMp4 FMp4MessagePackWriter writer = new FMp4MessagePackWriter(buffer); try { - SegmentTypeBox stypTypeBox = new SegmentTypeBox(); - stypTypeBox.MajorBrand = "msdh"; - stypTypeBox.MinorVersion = "\0\0\0\0"; - stypTypeBox.CompatibleBrands.Add("isom"); - stypTypeBox.CompatibleBrands.Add("mp42"); - stypTypeBox.CompatibleBrands.Add("msdh"); - stypTypeBox.CompatibleBrands.Add("msix"); - stypTypeBox.CompatibleBrands.Add("iso5"); - stypTypeBox.CompatibleBrands.Add("iso6"); - stypTypeBox.ToBuffer(ref writer); + var truns = new List(); + List rawdatas = new List(); + uint iSize = 0; + ulong lastTimestamp = 0; + for (var i=0; i 0) + { + truns.Add(new TrackRunBox.TrackRunInfo() + { + SampleSize = iSize, + }); + iSize = 0; + } + truns.Add(new TrackRunBox.TrackRunInfo() + { + SampleSize = (uint)(nalu.RawData.Length + nalu.StartCodePrefix.Length), + }); + } + if(i== (nalus.Count - 1)) + { + lastTimestamp = nalu.Timestamp; + } + } + + var movieFragmentBox = new MovieFragmentBox(); + movieFragmentBox.MovieFragmentHeaderBox = new MovieFragmentHeaderBox(); + //todo:SequenceNumber + movieFragmentBox.MovieFragmentHeaderBox.SequenceNumber = sn++; + movieFragmentBox.TrackFragmentBox = new TrackFragmentBox(); + movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox = new TrackFragmentHeaderBox(0x2003a); + movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.TrackID = 1; + movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.SampleDescriptionIndex = 1; + movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleDuration = 48000; + movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleSize = truns[0].SampleSize; + movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleFlags = 0x1010000; + movieFragmentBox.TrackFragmentBox.TrackFragmentBaseMediaDecodeTimeBox = new TrackFragmentBaseMediaDecodeTimeBox(); + movieFragmentBox.TrackFragmentBox.TrackFragmentBaseMediaDecodeTimeBox.BaseMediaDecodeTime = lastTimestamp * 1000; + + //trun + movieFragmentBox.TrackFragmentBox.TrackRunBox = new TrackRunBox(flags: 0x205); + movieFragmentBox.TrackFragmentBox.TrackRunBox.FirstSampleFlags = 33554432; + movieFragmentBox.TrackFragmentBox.TrackRunBox.TrackRunInfos = truns; + movieFragmentBox.ToBuffer(ref writer); + + var mediaDataBox = new MediaDataBox(); + mediaDataBox.Data = rawdatas; + mediaDataBox.ToBuffer(ref writer); - var firstNalu = nalus[0]; - var lastNalu = nalus[nalus.Count - 1]; - uint interval = (uint)(lastNalu.Timestamp - firstNalu.Timestamp); + var data = writer.FlushAndGetArray(); + return data; + } + finally + { + FMp4ArrayPool.Return(buffer); + } + } + + /// + /// 编码其他视频数据盒子 + /// + /// + public byte[] EncoderOtherVideoBox(List nalus,Listsamples, List sampleSizes,uint firstSize,ulong lastTimestamp) + { + byte[] buffer = FMp4ArrayPool.Rent(nalus.Sum(s => s.RawData.Length + s.StartCodePrefix.Length) + 4096); + FMp4MessagePackWriter writer = new FMp4MessagePackWriter(buffer); + try + { + var lastNalu = nalus.Last(); int iSize = nalus.Where(w => w.DataType == Protocol.Enums.JT1078DataType.视频I帧) .Sum(s => s.RawData.Length + s.StartCodePrefix.Length); - List sizes = new List(); sizes.Add(iSize); sizes = sizes.Concat(nalus.Where(w => w.DataType != Protocol.Enums.JT1078DataType.视频I帧) .Select(s => s.RawData.Length + s.StartCodePrefix.Length).ToList()) .ToList(); - SegmentIndexBox segmentIndexBox = new SegmentIndexBox(1); - segmentIndexBox.ReferenceID = 1; - segmentIndexBox.EarliestPresentationTime = timestampCache; - segmentIndexBox.SegmentIndexs = new List() - { - new SegmentIndexBox.SegmentIndex - { - SubsegmentDuration=interval - } - }; - segmentIndexBox.ToBuffer(ref writer); - - var current1 = writer.GetCurrentPosition(); var movieFragmentBox = new MovieFragmentBox(); movieFragmentBox.MovieFragmentHeaderBox = new MovieFragmentHeaderBox(); @@ -208,10 +247,10 @@ namespace JT1078.FMp4 movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.TrackID = 1; movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.SampleDescriptionIndex = 1; movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleDuration = 48000; - movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleSize = (uint)iSize; + movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleSize = firstSize; movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleFlags = 0x1010000; movieFragmentBox.TrackFragmentBox.TrackFragmentBaseMediaDecodeTimeBox = new TrackFragmentBaseMediaDecodeTimeBox(); - movieFragmentBox.TrackFragmentBox.TrackFragmentBaseMediaDecodeTimeBox.BaseMediaDecodeTime = timestampCache; + movieFragmentBox.TrackFragmentBox.TrackFragmentBaseMediaDecodeTimeBox.BaseMediaDecodeTime = lastTimestamp * 1000; //trun movieFragmentBox.TrackFragmentBox.TrackRunBox = new TrackRunBox(flags: 0x205); @@ -227,17 +266,11 @@ namespace JT1078.FMp4 } movieFragmentBox.ToBuffer(ref writer); - timestampCache += (uint)(sizes.Count * 48000); var mediaDataBox = new MediaDataBox(); mediaDataBox.Data = nalus.Select(s => s.RawData).ToList(); mediaDataBox.ToBuffer(ref writer); - var current2 = writer.GetCurrentPosition(); - foreach(var postion in segmentIndexBox.ReferencedSizePositions) - { - writer.WriteUInt32Return((uint)(current2 - current1), postion); - } var data = writer.FlushAndGetArray(); return data; } diff --git a/src/JT1078.FMp4/JT1078.FMp4.xml b/src/JT1078.FMp4/JT1078.FMp4.xml index 0189c5c..5be8d78 100644 --- a/src/JT1078.FMp4/JT1078.FMp4.xml +++ b/src/JT1078.FMp4/JT1078.FMp4.xml @@ -1338,6 +1338,12 @@ + + + 编码其他视频数据盒子 + + + unsigned int(8)