@@ -8,6 +8,7 @@ | |||||
3.1 [将1078的数据(h264)编码成FLV](#1078flv) | 3.1 [将1078的数据(h264)编码成FLV](#1078flv) | ||||
3.2 [将1078的数据(h264)编码成HLS](#1078hls) | 3.2 [将1078的数据(h264)编码成HLS](#1078hls) | ||||
3.3 [将1078的数据(h264)编码成FMp4](#1078fmp4) | 3.3 [将1078的数据(h264)编码成FMp4](#1078fmp4) | ||||
4. ***====音频部分暂未实现====*** | |||||
[](https://github.com/SmallChi/JT1078/blob/master/LICENSE)[]() | [](https://github.com/SmallChi/JT1078/blob/master/LICENSE)[]() | ||||
@@ -18,6 +19,7 @@ | |||||
| Install-Package JT1078 |  |  | | | Install-Package JT1078 |  |  | | ||||
| Install-Package JT1078.Flv |  |  | | | Install-Package JT1078.Flv |  |  | | ||||
| Install-Package JT1078.Hls |  |  | | | Install-Package JT1078.Hls |  |  | | ||||
| Install-Package JT1078.FMp4 |  |  | | |||||
| Install-Package JT808.Protocol.Extensions.JT1078 |  |  | | | Install-Package JT808.Protocol.Extensions.JT1078 |  |  | | ||||
| Install-Package JT809.Protocol.Extensions.JT1078 |  |  | | | Install-Package JT809.Protocol.Extensions.JT1078 |  |  | | ||||
@@ -180,7 +182,13 @@ Platform=AnyCpu Server=False Toolchain=.NET Core 3.1 | |||||
3. 掌握TS编码; | 3. 掌握TS编码; | ||||
4. 掌握Hls编码; | 4. 掌握Hls编码; | ||||
> 音频暂未实现 | |||||
## <span id="1078fmp4">基于JT1078的FMp4视频编码器</span> | |||||
### 前提条件 | |||||
1. 掌握JT078解码; | |||||
2. 了解H264解码; | |||||
3. 掌握FMp4编码; | |||||
### 使用BenchmarkDotNet性能测试报告(只是玩玩,不能当真) | ### 使用BenchmarkDotNet性能测试报告(只是玩玩,不能当真) | ||||
@@ -6,8 +6,16 @@ using System.Text; | |||||
namespace JT1078.FMp4 | namespace JT1078.FMp4 | ||||
{ | { | ||||
/// <summary> | |||||
/// stco | |||||
/// </summary> | |||||
public class ChunkOffsetBox : FullBox, IFMp4MessagePackFormatter | public class ChunkOffsetBox : FullBox, IFMp4MessagePackFormatter | ||||
{ | { | ||||
/// <summary> | |||||
/// stco | |||||
/// </summary> | |||||
/// <param name="version"></param> | |||||
/// <param name="flags"></param> | |||||
public ChunkOffsetBox( byte version=0, uint flags=0) : base("stco", version, flags) | 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) | 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); | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -6,8 +6,16 @@ using System.Text; | |||||
namespace JT1078.FMp4 | namespace JT1078.FMp4 | ||||
{ | { | ||||
/// <summary> | |||||
/// ctts | |||||
/// </summary> | |||||
public class CompositionOffsetBox : FullBox, IFMp4MessagePackFormatter | public class CompositionOffsetBox : FullBox, IFMp4MessagePackFormatter | ||||
{ | { | ||||
/// <summary> | |||||
/// ctts | |||||
/// </summary> | |||||
/// <param name="version"></param> | |||||
/// <param name="flags"></param> | |||||
public CompositionOffsetBox(byte version=0, uint flags=0) : base("ctts", version, flags) | 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) | 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 | public class CompositionOffsetInfo | ||||
@@ -1,4 +1,6 @@ | |||||
using System; | |||||
using JT1078.FMp4.Interfaces; | |||||
using JT1078.FMp4.MessagePack; | |||||
using System; | |||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Text; | using System.Text; | ||||
@@ -7,7 +9,7 @@ namespace JT1078.FMp4 | |||||
/// <summary> | /// <summary> | ||||
/// mdia | /// mdia | ||||
/// </summary> | /// </summary> | ||||
public class MediaBox : Mp4Box | |||||
public class MediaBox : Mp4Box, IFMp4MessagePackFormatter | |||||
{ | { | ||||
/// <summary> | /// <summary> | ||||
/// mdia | /// mdia | ||||
@@ -27,5 +29,14 @@ namespace JT1078.FMp4 | |||||
/// minf | /// minf | ||||
/// </summary> | /// </summary> | ||||
public MediaInformationBox MediaInformationBox { get; set; } | 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); | |||||
} | |||||
} | } | ||||
} | } |
@@ -27,7 +27,7 @@ namespace JT1078.FMp4 | |||||
/// </summary> | /// </summary> | ||||
public TrackBox TrackBox { get; set; } | public TrackBox TrackBox { get; set; } | ||||
/// <summary> | /// <summary> | ||||
/// trak | |||||
/// mvex | |||||
/// </summary> | /// </summary> | ||||
public MovieExtendsBox MovieExtendsBox { get; set; } | public MovieExtendsBox MovieExtendsBox { get; set; } | ||||
@@ -35,7 +35,8 @@ namespace JT1078.FMp4 | |||||
{ | { | ||||
Start(ref writer); | Start(ref writer); | ||||
MovieHeaderBox.ToBuffer(ref writer); | MovieHeaderBox.ToBuffer(ref writer); | ||||
TrackBox.ToBuffer(ref writer); | |||||
MovieExtendsBox.ToBuffer(ref writer); | |||||
End(ref writer); | End(ref writer); | ||||
} | } | ||||
} | } | ||||
@@ -1,4 +1,6 @@ | |||||
using System; | |||||
using JT1078.FMp4.Interfaces; | |||||
using JT1078.FMp4.MessagePack; | |||||
using System; | |||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Text; | using System.Text; | ||||
@@ -7,7 +9,7 @@ namespace JT1078.FMp4 | |||||
/// <summary> | /// <summary> | ||||
/// mvex | /// mvex | ||||
/// </summary> | /// </summary> | ||||
public class MovieExtendsBox : Mp4Box | |||||
public class MovieExtendsBox : Mp4Box, IFMp4MessagePackFormatter | |||||
{ | { | ||||
/// <summary> | /// <summary> | ||||
/// mvex | /// mvex | ||||
@@ -17,5 +19,22 @@ namespace JT1078.FMp4 | |||||
} | } | ||||
public MovieExtendsHeaderBox MovieExtendsHeaderBox { get; set; } | public MovieExtendsHeaderBox MovieExtendsHeaderBox { get; set; } | ||||
public List<TrackExtendsBox> TrackExtendsBoxs { get; set; } | public List<TrackExtendsBox> 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); | |||||
} | |||||
} | } | ||||
} | } |
@@ -1,14 +1,33 @@ | |||||
using System; | |||||
using JT1078.FMp4.Interfaces; | |||||
using JT1078.FMp4.MessagePack; | |||||
using System; | |||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Text; | using System.Text; | ||||
namespace JT1078.FMp4 | namespace JT1078.FMp4 | ||||
{ | { | ||||
public class MovieExtendsHeaderBox : FullBox | |||||
/// <summary> | |||||
/// mehd | |||||
/// </summary> | |||||
public class MovieExtendsHeaderBox : FullBox, IFMp4MessagePackFormatter | |||||
{ | { | ||||
/// <summary> | |||||
/// mehd | |||||
/// </summary> | |||||
/// <param name="version"></param> | |||||
/// <param name="flags"></param> | |||||
public MovieExtendsHeaderBox( byte version, uint flags=0) : base("mehd", version, flags) | public MovieExtendsHeaderBox( byte version, uint flags=0) : base("mehd", version, flags) | ||||
{ | { | ||||
} | } | ||||
public uint FragmentDuration { get; set; } | public uint FragmentDuration { get; set; } | ||||
public void ToBuffer(ref FMp4MessagePackWriter writer) | |||||
{ | |||||
Start(ref writer); | |||||
WriterFullBoxToBuffer(ref writer); | |||||
writer.WriteUInt32(FragmentDuration); | |||||
End(ref writer); | |||||
} | |||||
} | } | ||||
} | } |
@@ -32,7 +32,8 @@ namespace JT1078.FMp4 | |||||
WriterFullBoxToBuffer(ref writer); | WriterFullBoxToBuffer(ref writer); | ||||
if(SampleEntries!=null && SampleEntries.Count > 0) | 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); | item.ToBuffer(ref writer); | ||||
} | } | ||||
@@ -6,8 +6,16 @@ using System.Text; | |||||
namespace JT1078.FMp4 | namespace JT1078.FMp4 | ||||
{ | { | ||||
/// <summary> | |||||
/// stsc | |||||
/// </summary> | |||||
public class SampleToChunkBox : FullBox, IFMp4MessagePackFormatter | public class SampleToChunkBox : FullBox, IFMp4MessagePackFormatter | ||||
{ | { | ||||
/// <summary> | |||||
/// stsc | |||||
/// </summary> | |||||
/// <param name="version"></param> | |||||
/// <param name="flags"></param> | |||||
public SampleToChunkBox(byte version=0, uint flags=0) : base("stsc", version, flags) | 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) | 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 | public class SampleToChunkInfo | ||||
@@ -6,8 +6,16 @@ using System.Text; | |||||
namespace JT1078.FMp4 | namespace JT1078.FMp4 | ||||
{ | { | ||||
/// <summary> | |||||
/// stts | |||||
/// </summary> | |||||
public class TimeToSampleBox : FullBox, IFMp4MessagePackFormatter | public class TimeToSampleBox : FullBox, IFMp4MessagePackFormatter | ||||
{ | { | ||||
/// <summary> | |||||
/// stts | |||||
/// </summary> | |||||
/// <param name="version"></param> | |||||
/// <param name="flags"></param> | |||||
public TimeToSampleBox(byte version = 0, uint flags = 0) : base("stts", version, flags) | 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) | 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 | public class TimeToSampleInfo | ||||
@@ -1,4 +1,6 @@ | |||||
using System; | |||||
using JT1078.FMp4.Interfaces; | |||||
using JT1078.FMp4.MessagePack; | |||||
using System; | |||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Text; | using System.Text; | ||||
@@ -7,7 +9,7 @@ namespace JT1078.FMp4 | |||||
/// <summary> | /// <summary> | ||||
/// trak | /// trak | ||||
/// </summary> | /// </summary> | ||||
public class TrackBox : Mp4Box | |||||
public class TrackBox : Mp4Box, IFMp4MessagePackFormatter | |||||
{ | { | ||||
/// <summary> | /// <summary> | ||||
/// trak | /// trak | ||||
@@ -25,5 +27,13 @@ namespace JT1078.FMp4 | |||||
/// mdia | /// mdia | ||||
/// </summary> | /// </summary> | ||||
public MediaBox MediaBox { get; set; } | 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); | |||||
} | |||||
} | } | ||||
} | } |
@@ -1,10 +1,12 @@ | |||||
using System; | |||||
using JT1078.FMp4.Interfaces; | |||||
using JT1078.FMp4.MessagePack; | |||||
using System; | |||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Text; | using System.Text; | ||||
namespace JT1078.FMp4 | namespace JT1078.FMp4 | ||||
{ | { | ||||
public class TrackExtendsBox : FullBox | |||||
public class TrackExtendsBox : FullBox, IFMp4MessagePackFormatter | |||||
{ | { | ||||
public TrackExtendsBox(byte version=0, uint flags=0) : base("trex", version, flags) | 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 DefaultSampleDuration { get; set; } | ||||
public uint DefaultSampleSize { get; set; } | public uint DefaultSampleSize { get; set; } | ||||
public uint DefaultSampleFlags { 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); | |||||
} | |||||
} | } | ||||
} | } |
@@ -747,7 +747,7 @@ | |||||
</summary> | </summary> | ||||
<param name="writer"></param> | <param name="writer"></param> | ||||
</member> | </member> | ||||
<!-- Badly formed XML comment ignored for member "P:JT1078.FMp4.Samples.AudioSampleEntry.Samplerate" --> | |||||
<!-- Badly formed XML comment ignored for member "P:JT1078.FMp4.Samples.AudioSampleEntry.SampleRate" --> | |||||
<member name="T:JT1078.FMp4.Samples.AVC1SampleEntry"> | <member name="T:JT1078.FMp4.Samples.AVC1SampleEntry"> | ||||
<summary> | <summary> | ||||
avc1 | avc1 | ||||
@@ -1,4 +1,5 @@ | |||||
using System; | |||||
using JT1078.FMp4.MessagePack; | |||||
using System; | |||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Text; | using System.Text; | ||||
@@ -15,8 +16,22 @@ namespace JT1078.FMp4.Samples | |||||
public ushort PreDefined { get; set; } = 0; | public ushort PreDefined { get; set; } = 0; | ||||
public ushort Reserved2 { get; set; } = 0; | public ushort Reserved2 { get; set; } = 0; | ||||
/// <summary> | /// <summary> | ||||
/// { default samplerate of media}<<16; | |||||
/// | |||||
/// default samplerate of media << 16; | |||||
/// </summary> | /// </summary> | ||||
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); | |||||
} | |||||
} | } | ||||
} | } |