diff --git a/README.md b/README.md index 3834581..874f202 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ 3.1 [将1078的数据(h264)编码成FLV](#1078flv) 3.2 [将1078的数据(h264)编码成HLS](#1078hls) 3.3 [将1078的数据(h264)编码成FMp4](#1078fmp4) +4. ***====音频部分暂未实现====*** [![MIT Licence](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/SmallChi/JT1078/blob/master/LICENSE)[![Github Build status](https://github.com/SmallChi/JT1078/workflows/.NET%20Core/badge.svg)]() @@ -18,6 +19,7 @@ | Install-Package JT1078 | ![JT1078](https://img.shields.io/nuget/v/JT1078.svg) | ![JT1078](https://img.shields.io/nuget/dt/JT1078.svg) | | Install-Package JT1078.Flv | ![JT1078.Flv](https://img.shields.io/nuget/v/JT1078.Flv.svg) | ![JT1078.Flv](https://img.shields.io/nuget/dt/JT1078.Flv.svg) | | Install-Package JT1078.Hls | ![JT1078.Hls](https://img.shields.io/nuget/v/JT1078.Hls.svg) | ![JT1078.Hls](https://img.shields.io/nuget/dt/JT1078.Hls.svg) | +| Install-Package JT1078.FMp4 | ![JT1078.FMp4](https://img.shields.io/nuget/v/JT1078.FMp4.svg) | ![JT1078.FMp4](https://img.shields.io/nuget/dt/JT1078.FMp4.svg) | | Install-Package JT808.Protocol.Extensions.JT1078 | ![JT808.Protocol.Extensions.JT1078](https://img.shields.io/nuget/v/JT808.Protocol.Extensions.JT1078.svg) | ![JT808](https://img.shields.io/nuget/dt/JT808.Protocol.Extensions.JT1078.svg) | | Install-Package JT809.Protocol.Extensions.JT1078 | ![JT809.Protocol.Extensions.JT1078](https://img.shields.io/nuget/v/JT809.Protocol.Extensions.JT1078.svg) | ![JT809](https://img.shields.io/nuget/dt/JT809.Protocol.Extensions.JT1078.svg) | @@ -180,7 +182,13 @@ Platform=AnyCpu Server=False Toolchain=.NET Core 3.1 3. 掌握TS编码; 4. 掌握Hls编码; -> 音频暂未实现 +## 基于JT1078的FMp4视频编码器 + +### 前提条件 + +1. 掌握JT078解码; +2. 了解H264解码; +3. 掌握FMp4编码; ### 使用BenchmarkDotNet性能测试报告(只是玩玩,不能当真) diff --git a/src/JT1078.FMp4/Boxs/ChunkOffsetBox.cs b/src/JT1078.FMp4/Boxs/ChunkOffsetBox.cs index f8c0b97..cddea67 100644 --- a/src/JT1078.FMp4/Boxs/ChunkOffsetBox.cs +++ b/src/JT1078.FMp4/Boxs/ChunkOffsetBox.cs @@ -6,8 +6,16 @@ using System.Text; namespace JT1078.FMp4 { + /// + /// stco + /// public class ChunkOffsetBox : FullBox, IFMp4MessagePackFormatter { + /// + /// stco + /// + /// + /// public ChunkOffsetBox( byte version=0, uint flags=0) : base("stco", version, flags) { } @@ -20,7 +28,21 @@ namespace JT1078.FMp4 public void ToBuffer(ref FMp4MessagePackWriter writer) { - throw new NotImplementedException(); + Start(ref writer); + WriterFullBoxToBuffer(ref writer); + if(ChunkOffset!=null && ChunkOffset.Count > 0) + { + writer.WriteUInt32((uint)ChunkOffset.Count); + foreach(var item in ChunkOffset) + { + writer.WriteUInt32(item); + } + } + else + { + writer.WriteUInt32(0); + } + End(ref writer); } } } diff --git a/src/JT1078.FMp4/Boxs/CompositionOffsetBox.cs b/src/JT1078.FMp4/Boxs/CompositionOffsetBox.cs index 57700a6..1b49433 100644 --- a/src/JT1078.FMp4/Boxs/CompositionOffsetBox.cs +++ b/src/JT1078.FMp4/Boxs/CompositionOffsetBox.cs @@ -6,8 +6,16 @@ using System.Text; namespace JT1078.FMp4 { + /// + /// ctts + /// public class CompositionOffsetBox : FullBox, IFMp4MessagePackFormatter { + /// + /// ctts + /// + /// + /// public CompositionOffsetBox(byte version=0, uint flags=0) : base("ctts", version, flags) { } @@ -17,7 +25,30 @@ namespace JT1078.FMp4 public void ToBuffer(ref FMp4MessagePackWriter writer) { - throw new NotImplementedException(); + Start(ref writer); + WriterFullBoxToBuffer(ref writer); + if(CompositionOffsetInfos!=null && CompositionOffsetInfos.Count > 0) + { + writer.WriteUInt32((uint)CompositionOffsetInfos.Count); + foreach(var item in CompositionOffsetInfos) + { + if (Version == 0) + { + writer.WriteUInt32(item.SampleCount); + writer.WriteUInt32(item.SampleOffset); + } + else + { + writer.WriteUInt32(item.SampleCount); + writer.WriteInt32(item.SignedSampleOffset); + } + } + } + else + { + writer.WriteUInt32(0); + } + End(ref writer); } public class CompositionOffsetInfo diff --git a/src/JT1078.FMp4/Boxs/MediaBox.cs b/src/JT1078.FMp4/Boxs/MediaBox.cs index eff4e13..cf456c0 100644 --- a/src/JT1078.FMp4/Boxs/MediaBox.cs +++ b/src/JT1078.FMp4/Boxs/MediaBox.cs @@ -1,4 +1,6 @@ -using System; +using JT1078.FMp4.Interfaces; +using JT1078.FMp4.MessagePack; +using System; using System.Collections.Generic; using System.Text; @@ -7,7 +9,7 @@ namespace JT1078.FMp4 /// /// mdia /// - public class MediaBox : Mp4Box + public class MediaBox : Mp4Box, IFMp4MessagePackFormatter { /// /// mdia @@ -27,5 +29,14 @@ namespace JT1078.FMp4 /// minf /// public MediaInformationBox MediaInformationBox { get; set; } + + public void ToBuffer(ref FMp4MessagePackWriter writer) + { + Start(ref writer); + MediaHeaderBox.ToBuffer(ref writer); + HandlerBox.ToBuffer(ref writer); + MediaInformationBox.ToBuffer(ref writer); + End(ref writer); + } } } diff --git a/src/JT1078.FMp4/Boxs/MovieBox.cs b/src/JT1078.FMp4/Boxs/MovieBox.cs index eace22e..d8530d2 100644 --- a/src/JT1078.FMp4/Boxs/MovieBox.cs +++ b/src/JT1078.FMp4/Boxs/MovieBox.cs @@ -27,7 +27,7 @@ namespace JT1078.FMp4 /// public TrackBox TrackBox { get; set; } /// - /// trak + /// mvex /// public MovieExtendsBox MovieExtendsBox { get; set; } @@ -35,7 +35,8 @@ namespace JT1078.FMp4 { Start(ref writer); MovieHeaderBox.ToBuffer(ref writer); - + TrackBox.ToBuffer(ref writer); + MovieExtendsBox.ToBuffer(ref writer); End(ref writer); } } diff --git a/src/JT1078.FMp4/Boxs/MovieExtendsBox.cs b/src/JT1078.FMp4/Boxs/MovieExtendsBox.cs index d7f966d..ceeb636 100644 --- a/src/JT1078.FMp4/Boxs/MovieExtendsBox.cs +++ b/src/JT1078.FMp4/Boxs/MovieExtendsBox.cs @@ -1,4 +1,6 @@ -using System; +using JT1078.FMp4.Interfaces; +using JT1078.FMp4.MessagePack; +using System; using System.Collections.Generic; using System.Text; @@ -7,7 +9,7 @@ namespace JT1078.FMp4 /// /// mvex /// - public class MovieExtendsBox : Mp4Box + public class MovieExtendsBox : Mp4Box, IFMp4MessagePackFormatter { /// /// mvex @@ -17,5 +19,22 @@ namespace JT1078.FMp4 } public MovieExtendsHeaderBox MovieExtendsHeaderBox { get; set; } public List TrackExtendsBoxs { get; set; } + + public void ToBuffer(ref FMp4MessagePackWriter writer) + { + Start(ref writer); + if (MovieExtendsHeaderBox != null) + { + MovieExtendsHeaderBox.ToBuffer(ref writer); + } + if (TrackExtendsBoxs != null) + { + foreach(var item in TrackExtendsBoxs) + { + item.ToBuffer(ref writer); + } + } + End(ref writer); + } } } diff --git a/src/JT1078.FMp4/Boxs/MovieExtendsHeaderBox.cs b/src/JT1078.FMp4/Boxs/MovieExtendsHeaderBox.cs index b9dcc79..4c4ea6e 100644 --- a/src/JT1078.FMp4/Boxs/MovieExtendsHeaderBox.cs +++ b/src/JT1078.FMp4/Boxs/MovieExtendsHeaderBox.cs @@ -1,14 +1,33 @@ -using System; +using JT1078.FMp4.Interfaces; +using JT1078.FMp4.MessagePack; +using System; using System.Collections.Generic; using System.Text; namespace JT1078.FMp4 { - public class MovieExtendsHeaderBox : FullBox + /// + /// mehd + /// + public class MovieExtendsHeaderBox : FullBox, IFMp4MessagePackFormatter { + /// + /// mehd + /// + /// + /// public MovieExtendsHeaderBox( byte version, uint flags=0) : base("mehd", version, flags) { } + public uint FragmentDuration { get; set; } + + public void ToBuffer(ref FMp4MessagePackWriter writer) + { + Start(ref writer); + WriterFullBoxToBuffer(ref writer); + writer.WriteUInt32(FragmentDuration); + End(ref writer); + } } } diff --git a/src/JT1078.FMp4/Boxs/SampleDescriptionBox.cs b/src/JT1078.FMp4/Boxs/SampleDescriptionBox.cs index e320b16..de595aa 100644 --- a/src/JT1078.FMp4/Boxs/SampleDescriptionBox.cs +++ b/src/JT1078.FMp4/Boxs/SampleDescriptionBox.cs @@ -32,7 +32,8 @@ namespace JT1078.FMp4 WriterFullBoxToBuffer(ref writer); if(SampleEntries!=null && SampleEntries.Count > 0) { - foreach(var item in SampleEntries) + writer.WriteUInt32((uint)SampleEntries.Count); + foreach (var item in SampleEntries) { item.ToBuffer(ref writer); } diff --git a/src/JT1078.FMp4/Boxs/SampleToChunkBox.cs b/src/JT1078.FMp4/Boxs/SampleToChunkBox.cs index f93c996..ae4b69b 100644 --- a/src/JT1078.FMp4/Boxs/SampleToChunkBox.cs +++ b/src/JT1078.FMp4/Boxs/SampleToChunkBox.cs @@ -6,8 +6,16 @@ using System.Text; namespace JT1078.FMp4 { + /// + /// stsc + /// public class SampleToChunkBox : FullBox, IFMp4MessagePackFormatter { + /// + /// stsc + /// + /// + /// public SampleToChunkBox(byte version=0, uint flags=0) : base("stsc", version, flags) { } @@ -16,7 +24,23 @@ namespace JT1078.FMp4 public void ToBuffer(ref FMp4MessagePackWriter writer) { - throw new NotImplementedException(); + Start(ref writer); + WriterFullBoxToBuffer(ref writer); + if(SampleToChunkInfos!=null && SampleToChunkInfos.Count > 0) + { + writer.WriteUInt32((uint)SampleToChunkInfos.Count); + foreach(var item in SampleToChunkInfos) + { + writer.WriteUInt32(item.FirstChunk); + writer.WriteUInt32(item.SamplesPerChunk); + writer.WriteUInt32(item.SampleDescriptionIindex); + } + } + else + { + writer.WriteUInt32(0); + } + End(ref writer); } public class SampleToChunkInfo diff --git a/src/JT1078.FMp4/Boxs/TimeToSampleBox.cs b/src/JT1078.FMp4/Boxs/TimeToSampleBox.cs index 82afa45..ea8d545 100644 --- a/src/JT1078.FMp4/Boxs/TimeToSampleBox.cs +++ b/src/JT1078.FMp4/Boxs/TimeToSampleBox.cs @@ -6,8 +6,16 @@ using System.Text; namespace JT1078.FMp4 { + /// + /// stts + /// public class TimeToSampleBox : FullBox, IFMp4MessagePackFormatter { + /// + /// stts + /// + /// + /// public TimeToSampleBox(byte version = 0, uint flags = 0) : base("stts", version, flags) { } @@ -18,7 +26,22 @@ namespace JT1078.FMp4 public void ToBuffer(ref FMp4MessagePackWriter writer) { - throw new NotImplementedException(); + Start(ref writer); + WriterFullBoxToBuffer(ref writer); + if(TimeToSampleInfos!=null && TimeToSampleInfos.Count > 0) + { + writer.WriteUInt32((uint)TimeToSampleInfos.Count); + foreach (var item in TimeToSampleInfos) + { + writer.WriteUInt32(item.SampleCount); + writer.WriteUInt32(item.SampleDelta); + } + } + else + { + writer.WriteUInt32(0); + } + End(ref writer); } public class TimeToSampleInfo diff --git a/src/JT1078.FMp4/Boxs/TrackBox.cs b/src/JT1078.FMp4/Boxs/TrackBox.cs index 4c08eae..6464972 100644 --- a/src/JT1078.FMp4/Boxs/TrackBox.cs +++ b/src/JT1078.FMp4/Boxs/TrackBox.cs @@ -1,4 +1,6 @@ -using System; +using JT1078.FMp4.Interfaces; +using JT1078.FMp4.MessagePack; +using System; using System.Collections.Generic; using System.Text; @@ -7,7 +9,7 @@ namespace JT1078.FMp4 /// /// trak /// - public class TrackBox : Mp4Box + public class TrackBox : Mp4Box, IFMp4MessagePackFormatter { /// /// trak @@ -25,5 +27,13 @@ namespace JT1078.FMp4 /// mdia /// public MediaBox MediaBox { get; set; } + + public void ToBuffer(ref FMp4MessagePackWriter writer) + { + Start(ref writer); + TrackHeaderBox.ToBuffer(ref writer); + MediaBox.ToBuffer(ref writer); + End(ref writer); + } } } diff --git a/src/JT1078.FMp4/Boxs/TrackExtendsBox.cs b/src/JT1078.FMp4/Boxs/TrackExtendsBox.cs index 2fcbbfe..6fc6017 100644 --- a/src/JT1078.FMp4/Boxs/TrackExtendsBox.cs +++ b/src/JT1078.FMp4/Boxs/TrackExtendsBox.cs @@ -1,10 +1,12 @@ -using System; +using JT1078.FMp4.Interfaces; +using JT1078.FMp4.MessagePack; +using System; using System.Collections.Generic; using System.Text; namespace JT1078.FMp4 { - public class TrackExtendsBox : FullBox + public class TrackExtendsBox : FullBox, IFMp4MessagePackFormatter { public TrackExtendsBox(byte version=0, uint flags=0) : base("trex", version, flags) { @@ -15,5 +17,17 @@ namespace JT1078.FMp4 public uint DefaultSampleDuration { get; set; } public uint DefaultSampleSize { get; set; } public uint DefaultSampleFlags { get; set; } + + public void ToBuffer(ref FMp4MessagePackWriter writer) + { + Start(ref writer); + WriterFullBoxToBuffer(ref writer); + writer.WriteUInt32(TrackID); + writer.WriteUInt32(DefaultSampleDescriptionIndex); + writer.WriteUInt32(DefaultSampleDuration); + writer.WriteUInt32(DefaultSampleSize); + writer.WriteUInt32(DefaultSampleFlags); + End(ref writer); + } } } diff --git a/src/JT1078.FMp4/JT1078.FMp4.xml b/src/JT1078.FMp4/JT1078.FMp4.xml index b947e02..bb40784 100644 --- a/src/JT1078.FMp4/JT1078.FMp4.xml +++ b/src/JT1078.FMp4/JT1078.FMp4.xml @@ -747,7 +747,7 @@ - + avc1 diff --git a/src/JT1078.FMp4/Samples/AudioSampleEntry.cs b/src/JT1078.FMp4/Samples/AudioSampleEntry.cs index a92abb9..9be46b0 100644 --- a/src/JT1078.FMp4/Samples/AudioSampleEntry.cs +++ b/src/JT1078.FMp4/Samples/AudioSampleEntry.cs @@ -1,4 +1,5 @@ -using System; +using JT1078.FMp4.MessagePack; +using System; using System.Collections.Generic; using System.Text; @@ -15,8 +16,22 @@ namespace JT1078.FMp4.Samples public ushort PreDefined { get; set; } = 0; public ushort Reserved2 { get; set; } = 0; /// - /// { default samplerate of media}<<16; + /// + /// default samplerate of media << 16; /// - public uint Samplerate{ get; set; } + public uint SampleRate{ get; set; } + + protected void WriterAudioSampleEntryToBuffer(ref FMp4MessagePackWriter writer) + { + foreach(var item in Reserved1) + { + writer.WriteUInt32(item); + } + writer.WriteUInt16(ChannelCount); + writer.WriteUInt16(SampleSize); + writer.WriteUInt16(PreDefined); + writer.WriteUInt16(Reserved2); + writer.WriteUInt32(SampleRate<<16); + } } }