From fae5e4f07feb8a9e93fb96780acaac30e09e3ddf Mon Sep 17 00:00:00 2001 From: "SmallChi(Koike)" <564952747@qq.com> Date: Wed, 14 Oct 2020 18:16:01 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=84=E8=A3=85=E6=B5=8B=E8=AF=95=E7=9B=92?= =?UTF-8?q?=E5=AD=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/JT1078.FMp4.Test/FMp4Box_Test.cs | 109 ++++++++++++++++ .../JT1078FlvEncoderContext.cs | 2 +- .../JT808HexExtensions.cs | 2 +- .../JT1078.Protocol.Benchmark.csproj | 2 - .../JT1078FlvEncoderContext.cs | 4 +- .../JT1078SerializerContext.cs | 4 +- src/JT1078.Protocol/JT1078.Protocol.csproj | 2 +- src/JT1078.Protocol/JT1078Serializer.cs | 122 ++++++++---------- src/JT1078.sln | 4 +- 9 files changed, 175 insertions(+), 76 deletions(-) create mode 100644 src/JT1078.FMp4.Test/FMp4Box_Test.cs diff --git a/src/JT1078.FMp4.Test/FMp4Box_Test.cs b/src/JT1078.FMp4.Test/FMp4Box_Test.cs new file mode 100644 index 0000000..3c74da6 --- /dev/null +++ b/src/JT1078.FMp4.Test/FMp4Box_Test.cs @@ -0,0 +1,109 @@ +using JT1078.FMp4.MessagePack; +using System; +using System.Collections.Generic; +using System.Text; +using Xunit; +using JT1078.Protocol.Extensions; + +namespace JT1078.FMp4.Test +{ + public class FMp4Box_Test + { + /// + /// 使用doc/video/fragmented_demo.mp4 + /// + [Fact(DisplayName = "ftyp")] + public void ftyp_test() + { + var MinorVersion = Encoding.ASCII.GetString(new byte[4] { 0,0,2,0}); + 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("iso6"); + fileTypeBox.CompatibleBrands.Add("mp41"); + FMp4MessagePackWriter writer = new MessagePack.FMp4MessagePackWriter(new byte[0x25]); + fileTypeBox.ToBuffer(ref writer); + var hex = writer.FlushAndGetArray().ToHexString(); + Assert.Equal("000000246674797069736f6d0000020069736f6d69736f326176633169736f366d703431".ToUpper(), hex); + } + + /// + /// 使用doc/video/fragmented_demo.mp4 + /// + [Fact(DisplayName = "moov_mvhd")] + public void moov_mvhd_test() + { + MovieHeaderBox movieHeaderBox = new MovieHeaderBox(0); + movieHeaderBox.CreationTime = 0; + movieHeaderBox.ModificationTime = 0; + movieHeaderBox.Timescale = 1000; + movieHeaderBox.Duration = 0; + movieHeaderBox.NextTrackID = 2; + FMp4MessagePackWriter writer = new MessagePack.FMp4MessagePackWriter(new byte[10240]); + movieHeaderBox.ToBuffer(ref writer); + var hex = writer.FlushAndGetArray().ToHexString(); + Assert.Equal("0000006c6d766864000000000000000000000000000003e8000000000001000001000000000000000000000000010000000000000000000000000000000100000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002".ToUpper(), hex); + } + + /// + /// 使用doc/video/fragmented_demo.mp4 + /// + [Fact(DisplayName = "trak_tkhd")] + public void trak_tkhd_test() + { + TrackHeaderBox trackHeaderBox = new TrackHeaderBox(0,3); + trackHeaderBox.CreationTime = 0; + trackHeaderBox.ModificationTime = 0; + trackHeaderBox.TrackID = 1; + trackHeaderBox.Duration = 0; + trackHeaderBox.Width = 544u; + trackHeaderBox.Height = 960u; + FMp4MessagePackWriter writer = new MessagePack.FMp4MessagePackWriter(new byte[10240]); + trackHeaderBox.ToBuffer(ref writer); + var hex = writer.FlushAndGetArray().ToHexString(); + Assert.Equal("0000005C746B68640000000300000000000000000000000100000000000000000000000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000004000000000000220000003C0".ToUpper(), hex); + } + + /// + /// 使用doc/video/fragmented_demo.mp4 + /// + [Fact(DisplayName = "trak_mdia")] + public void trak_mdia_test() + { + + + } + + /// + /// 使用doc/video/fragmented_demo.mp4 + /// + [Fact(DisplayName = "trak_mdia_mdhd")] + public void trak_mdia_mdhd_test() + { + + MediaHeaderBox mediaHeaderBox = new MediaHeaderBox(0, 0); + mediaHeaderBox.CreationTime = 0; + mediaHeaderBox.ModificationTime = 0; + mediaHeaderBox.Timescale = 0x00124f80; + mediaHeaderBox.Duration = 0; + mediaHeaderBox.Language = "und"; + FMp4MessagePackWriter writer = new MessagePack.FMp4MessagePackWriter(new byte[10240]); + mediaHeaderBox.ToBuffer(ref writer); + var hex = writer.FlushAndGetArray().ToHexString(); + //000000206d64686400000000000000000000000000124f800000000055c40000 + //00000020 + //6d646864 + //00000000 + //00000000 + //00000000 + //00124f80 + //00000000 + //55c4 + //0000 + Assert.Equal("000000206d64686400000000000000000000000000124f800000000055c40000".ToUpper(), hex); + } + } +} diff --git a/src/JT1078.Flv.Benchmark/JT1078FlvEncoderContext.cs b/src/JT1078.Flv.Benchmark/JT1078FlvEncoderContext.cs index 4d46404..9d7db77 100644 --- a/src/JT1078.Flv.Benchmark/JT1078FlvEncoderContext.cs +++ b/src/JT1078.Flv.Benchmark/JT1078FlvEncoderContext.cs @@ -69,7 +69,7 @@ namespace JT1078.Flv.Benchmark { public JT1078FlvEncoderConfig() { - Add(Job.Default.WithGcServer(false).With(CsProjCoreToolchain.NetCoreApp31).With(Platform.AnyCpu)); + AddJob(Job.Default.WithGcServer(false).WithToolchain(CsProjCoreToolchain.NetCoreApp31).WithPlatform(Platform.AnyCpu)); } } } diff --git a/src/JT1078.Flv.Benchmark/JT808HexExtensions.cs b/src/JT1078.Flv.Benchmark/JT808HexExtensions.cs index 8248bd5..622cc6e 100644 --- a/src/JT1078.Flv.Benchmark/JT808HexExtensions.cs +++ b/src/JT1078.Flv.Benchmark/JT808HexExtensions.cs @@ -6,7 +6,7 @@ namespace JT808.Protocol.Extensions /// /// ref:"www.codeproject.com/tips/447938/high-performance-csharp-byte-array-to-hex-string-t" /// - public static partial class JT808BinaryExtensions + internal static partial class JT808BinaryExtensions { public static string ToHexString(this byte[] source) { diff --git a/src/JT1078.Protocol.Benchmark/JT1078.Protocol.Benchmark.csproj b/src/JT1078.Protocol.Benchmark/JT1078.Protocol.Benchmark.csproj index d0a50e8..25db222 100644 --- a/src/JT1078.Protocol.Benchmark/JT1078.Protocol.Benchmark.csproj +++ b/src/JT1078.Protocol.Benchmark/JT1078.Protocol.Benchmark.csproj @@ -15,9 +15,7 @@ - - diff --git a/src/JT1078.Protocol.Benchmark/JT1078FlvEncoderContext.cs b/src/JT1078.Protocol.Benchmark/JT1078FlvEncoderContext.cs index a7a35f0..acf356f 100644 --- a/src/JT1078.Protocol.Benchmark/JT1078FlvEncoderContext.cs +++ b/src/JT1078.Protocol.Benchmark/JT1078FlvEncoderContext.cs @@ -7,7 +7,7 @@ using JT1078.Flv.MessagePack; using JT1078.Protocol; using JT1078.Protocol.H264; using JT1078.Protocol.MessagePack; -using JT808.Protocol.Extensions; +using JT1078.Protocol.Extensions; using System; using System.Collections.Generic; using System.IO; @@ -78,7 +78,7 @@ namespace JT1078.Flv.Benchmark { public JT1078FlvEncoderConfig() { - Add(Job.Default.WithGcServer(false).With(CsProjCoreToolchain.NetCoreApp31).With(Platform.AnyCpu)); + AddJob(Job.Default.WithGcServer(false).WithToolchain(CsProjCoreToolchain.NetCoreApp31).WithPlatform(Platform.AnyCpu)); } } } diff --git a/src/JT1078.Protocol.Benchmark/JT1078SerializerContext.cs b/src/JT1078.Protocol.Benchmark/JT1078SerializerContext.cs index c471fae..22e245f 100644 --- a/src/JT1078.Protocol.Benchmark/JT1078SerializerContext.cs +++ b/src/JT1078.Protocol.Benchmark/JT1078SerializerContext.cs @@ -3,10 +3,10 @@ using BenchmarkDotNet.Configs; using BenchmarkDotNet.Environments; using BenchmarkDotNet.Jobs; using BenchmarkDotNet.Toolchains.CsProj; -using JT808.Protocol.Extensions; using System; using System.Collections.Generic; using System.Linq; +using JT1078.Protocol.Extensions; namespace JT1078.Protocol.Benchmark { @@ -58,7 +58,7 @@ namespace JT1078.Protocol.Benchmark { public JT1078SerializerConfig() { - Add(Job.Default.WithGcServer(false).With(CsProjCoreToolchain.NetCoreApp31).With(Platform.AnyCpu)); + AddJob(Job.Default.WithGcServer(false).WithToolchain(CsProjCoreToolchain.NetCoreApp31).WithPlatform(Platform.AnyCpu)); } } } diff --git a/src/JT1078.Protocol/JT1078.Protocol.csproj b/src/JT1078.Protocol/JT1078.Protocol.csproj index 1c926b5..d2ab1c4 100644 --- a/src/JT1078.Protocol/JT1078.Protocol.csproj +++ b/src/JT1078.Protocol/JT1078.Protocol.csproj @@ -14,7 +14,7 @@ https://github.com/SmallChi/JT1078/blob/master/LICENSE https://github.com/SmallChi/JT1078/blob/master/LICENSE false - 1.0.4-preview1 + 1.0.4-preview2 false true LICENSE diff --git a/src/JT1078.Protocol/JT1078Serializer.cs b/src/JT1078.Protocol/JT1078Serializer.cs index f29d875..a5d8e54 100644 --- a/src/JT1078.Protocol/JT1078Serializer.cs +++ b/src/JT1078.Protocol/JT1078Serializer.cs @@ -115,80 +115,72 @@ namespace JT1078.Protocol return jT1078Package; } } - public static byte[] AnalyzeJsonBuffer(ReadOnlySpan bytes, JsonWriterOptions options = default, int minBufferSize = 8096) + public static byte[] AnalyzeJsonBuffer(ReadOnlySpan bytes, JsonWriterOptions options = default) { - byte[] buffer = JT1078ArrayPool.Rent(minBufferSize); - try + JT1078MessagePackReader jT1078MessagePackReader = new JT1078MessagePackReader(bytes); + using (MemoryStream memoryStream = new MemoryStream()) + using (Utf8JsonWriter writer = new Utf8JsonWriter(memoryStream, options)) { - JT1078MessagePackReader jT1078MessagePackReader = new JT1078MessagePackReader(bytes); - using (MemoryStream memoryStream = new MemoryStream()) - using (Utf8JsonWriter writer = new Utf8JsonWriter(memoryStream, options)) - { - writer.WriteStartObject(); - var header = jT1078MessagePackReader.ReadUInt32(); - writer.WriteString($"[{header}]头部", header.ReadNumber()); - var val1 = jT1078MessagePackReader.ReadByte(); - var label1 = new JT1078Label1(val1); - var labelSpan = val1.ReadBinary(); - writer.WriteStartObject($"[{labelSpan.ToString()}]object1[{val1.ReadNumber()}]"); - writer.WriteNumber($"({labelSpan.Slice(0,2).ToString()})V[固定为2]", label1.V); - writer.WriteNumber($"({labelSpan[2]})P[固定为0]", label1.P); - writer.WriteNumber($"({labelSpan[3]})X[RTP头是否需要扩展位固定为0]", label1.X); - writer.WriteNumber($"({labelSpan.Slice(4).ToString()})CC[固定为1]", label1.CC); - writer.WriteEndObject(); + writer.WriteStartObject(); + var header = jT1078MessagePackReader.ReadUInt32(); + writer.WriteNumber($"[{header.ReadNumber()}]头部", header); + var val1 = jT1078MessagePackReader.ReadByte(); + var label1 = new JT1078Label1(val1); + var labelSpan = val1.ReadBinary(); + writer.WriteStartObject($"[{labelSpan.ToString()}]object1[{val1.ReadNumber()}]"); + writer.WriteNumber($"({labelSpan.Slice(0,2).ToString()})V[固定为2]", label1.V); + writer.WriteNumber($"({labelSpan[2]})P[固定为0]", label1.P); + writer.WriteNumber($"({labelSpan[3]})X[RTP头是否需要扩展位固定为0]", label1.X); + writer.WriteNumber($"({labelSpan.Slice(4).ToString()})CC[固定为1]", label1.CC); + writer.WriteEndObject(); - var val2 = jT1078MessagePackReader.ReadByte(); - var label2 = new JT1078Label2(val2); - var label2Span = val2.ReadBinary(); - writer.WriteStartObject($"[{label2Span.ToString()}]object2[{val2.ReadNumber()}]"); - writer.WriteNumber($"({label2Span.Slice(0, 4).ToString()})M[确定是否是完整数据帧的边界]", label2.M); - writer.WriteString($"({label2Span.Slice(4).ToString()})PT[负载类型]", label2.PT.ToString()); - writer.WriteEndObject(); + var val2 = jT1078MessagePackReader.ReadByte(); + var label2 = new JT1078Label2(val2); + var label2Span = val2.ReadBinary(); + writer.WriteStartObject($"[{label2Span.ToString()}]object2[{val2.ReadNumber()}]"); + writer.WriteNumber($"({label2Span.Slice(0, 4).ToString()})M[确定是否是完整数据帧的边界]", label2.M); + writer.WriteString($"({label2Span.Slice(4).ToString()})PT[负载类型]", label2.PT.ToString()); + writer.WriteEndObject(); - var sn = jT1078MessagePackReader.ReadUInt16(); - writer.WriteNumber($"{sn.ReadNumber()}[序列号]", sn); - var sim = jT1078MessagePackReader.ReadBCD(12); - writer.WriteString($"[终端设备SIM卡号]", sim); - var logicChannelNumber = jT1078MessagePackReader.ReadByte(); - writer.WriteNumber($"{logicChannelNumber.ReadNumber()}[逻辑通道号]", logicChannelNumber); + var sn = jT1078MessagePackReader.ReadUInt16(); + writer.WriteNumber($"{sn.ReadNumber()}[序列号]", sn); + var sim = jT1078MessagePackReader.ReadBCD(12); + writer.WriteString($"[终端设备SIM卡号]", sim); + var logicChannelNumber = jT1078MessagePackReader.ReadByte(); + writer.WriteNumber($"{logicChannelNumber.ReadNumber()}[逻辑通道号]", logicChannelNumber); - var val3 = jT1078MessagePackReader.ReadByte(); - var label3 = new JT1078Label3(val3); - var label3Span = val3.ReadBinary(); - writer.WriteStartObject($"[{label3Span.ToString()}]object3[{val3.ReadNumber()}]"); - writer.WriteString($"({label3Span.Slice(0, 4).ToString()})[数据类型]", label3.DataType.ToString()); - writer.WriteString($"({label3Span.Slice(4).ToString()})[分包处理标记]", label3.SubpackageType.ToString()); - writer.WriteEndObject(); - if (label3.DataType != JT1078DataType.透传数据) - { - var timestamp = jT1078MessagePackReader.ReadUInt64(); - writer.WriteNumber($"{timestamp.ReadNumber()}[标识此RTP数据包当前帧的相对时间,单位毫秒(ms)]", timestamp); - } - if (label3.DataType != JT1078DataType.透传数据 && - label3.DataType != JT1078DataType.音频帧) - { - var lastIFrameInterval = jT1078MessagePackReader.ReadUInt16(); - writer.WriteNumber($"{lastIFrameInterval.ReadNumber()}[该帧与上一个关键帧之间的时间间隔,单位毫秒(ms)]", lastIFrameInterval); - var lastFrameInterval = jT1078MessagePackReader.ReadUInt16(); - writer.WriteNumber($"{lastFrameInterval.ReadNumber()}[该帧与上一个关键帧之间的时间间隔,单位毫秒(ms)]", lastFrameInterval); - } - var dataBodyLength = jT1078MessagePackReader.ReadUInt16(); - writer.WriteNumber($"{dataBodyLength.ReadNumber()}[数据体长度]", dataBodyLength); - var bodies = jT1078MessagePackReader.ReadRemainArray().ToArray(); - writer.WriteString("[数据体]", string.Join(" ", (bodies).Select(p => p.ToString("X2")))); - writer.WriteEndObject(); - writer.Flush(); - return memoryStream.ToArray(); + var val3 = jT1078MessagePackReader.ReadByte(); + var label3 = new JT1078Label3(val3); + var label3Span = val3.ReadBinary(); + writer.WriteStartObject($"[{label3Span.ToString()}]object3[{val3.ReadNumber()}]"); + writer.WriteString($"({label3Span.Slice(0, 4).ToString()})[数据类型]", label3.DataType.ToString()); + writer.WriteString($"({label3Span.Slice(4).ToString()})[分包处理标记]", label3.SubpackageType.ToString()); + writer.WriteEndObject(); + if (label3.DataType != JT1078DataType.透传数据) + { + var timestamp = jT1078MessagePackReader.ReadUInt64(); + writer.WriteNumber($"{timestamp.ReadNumber()}[标识此RTP数据包当前帧的相对时间,单位毫秒(ms)]", timestamp); } - } - finally - { - JT1078ArrayPool.Return(buffer); + if (label3.DataType != JT1078DataType.透传数据 && + label3.DataType != JT1078DataType.音频帧) + { + var lastIFrameInterval = jT1078MessagePackReader.ReadUInt16(); + writer.WriteNumber($"{lastIFrameInterval.ReadNumber()}[该帧与上一个关键帧之间的时间间隔,单位毫秒(ms)]", lastIFrameInterval); + var lastFrameInterval = jT1078MessagePackReader.ReadUInt16(); + writer.WriteNumber($"{lastFrameInterval.ReadNumber()}[该帧与上一个关键帧之间的时间间隔,单位毫秒(ms)]", lastFrameInterval); + } + var dataBodyLength = jT1078MessagePackReader.ReadUInt16(); + writer.WriteNumber($"{dataBodyLength.ReadNumber()}[数据体长度]", dataBodyLength); + var bodies = jT1078MessagePackReader.ReadRemainArray().ToArray(); + writer.WriteString("[数据体]", string.Join(" ", (bodies).Select(p => p.ToString("X2")))); + writer.WriteEndObject(); + writer.Flush(); + return memoryStream.ToArray(); } } - public static string Analyze(ReadOnlySpan bytes,JsonWriterOptions options = default, int minBufferSize = 8096) + public static string Analyze(ReadOnlySpan bytes,JsonWriterOptions options = default) { - string json = Encoding.UTF8.GetString(AnalyzeJsonBuffer(bytes, options, minBufferSize)); + string json = Encoding.UTF8.GetString(AnalyzeJsonBuffer(bytes, options)); return json; } } diff --git a/src/JT1078.sln b/src/JT1078.sln index 5362b6d..696d930 100644 --- a/src/JT1078.sln +++ b/src/JT1078.sln @@ -34,9 +34,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT1078.Hls", "JT1078.Hls\JT EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT1078.Hls.Test", "JT1078.Hls.Test\JT1078.Hls.Test.csproj", "{5564C20B-BFF4-4A2A-BDF2-C7427E93E993}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT1078.FMp4", "JT1078.FMp4\JT1078.FMp4.csproj", "{73F13894-0967-422C-8AC3-5EEF9189AAFC}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT1078.FMp4", "JT1078.FMp4\JT1078.FMp4.csproj", "{73F13894-0967-422C-8AC3-5EEF9189AAFC}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT1078.FMp4.Test", "JT1078.FMp4.Test\JT1078.FMp4.Test.csproj", "{56E76D56-4CCC-401F-B25D-9AB41D58A10A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT1078.FMp4.Test", "JT1078.FMp4.Test\JT1078.FMp4.Test.csproj", "{56E76D56-4CCC-401F-B25D-9AB41D58A10A}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution