@@ -451,17 +451,36 @@ namespace JT1078.FMp4.Test | |||||
var nalus1 = h264Decoder.ParseNALU(package1); | var nalus1 = h264Decoder.ParseNALU(package1); | ||||
var moov = fMp4Encoder.EncoderMoovBox(nalus1, package1.Bodies.Length); | var moov = fMp4Encoder.EncoderMoovBox(nalus1, package1.Bodies.Length); | ||||
fileStream.Write(moov); | fileStream.Write(moov); | ||||
List<NalUnitType> filter = new List<NalUnitType>() { | |||||
NalUnitType.SPS, | |||||
NalUnitType.PPS, | |||||
NalUnitType.AUD}; | |||||
int i = 0; | |||||
foreach (var package in packages) | foreach (var package in packages) | ||||
{ | { | ||||
var otherStypBuffer = fMp4Encoder.EncoderStypBox(); | var otherStypBuffer = fMp4Encoder.EncoderStypBox(); | ||||
fileStream.Write(otherStypBuffer); | fileStream.Write(otherStypBuffer); | ||||
var otherNalus = h264Decoder.ParseNALU(package); | 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 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(otherSidxBuffer); | ||||
fileStream.Write(otherMoofBuffer); | fileStream.Write(otherMoofBuffer); | ||||
fileStream.Write(otherMdatBuffer); | fileStream.Write(otherMdatBuffer); | ||||
@@ -49,6 +49,7 @@ namespace JT1078.FMp4 | |||||
public uint DefaultSampleSize { get; set; } | public uint DefaultSampleSize { get; set; } | ||||
/// <summary> | /// <summary> | ||||
/// TFHD_FLAG_DEFAULT_FLAGS | /// TFHD_FLAG_DEFAULT_FLAGS | ||||
/// MOV_AUDIO == handler_type ? 0x02000000 : (0x00010000| 0x01000000); | |||||
/// </summary> | /// </summary> | ||||
public uint DefaultSampleFlags { get; set; } | public uint DefaultSampleFlags { get; set; } | ||||
#endregion | #endregion | ||||
@@ -108,11 +108,13 @@ namespace JT1078.FMp4 | |||||
} | } | ||||
} | } | ||||
uint IframeIntervalCache = 259960; | |||||
/// <summary> | /// <summary> | ||||
/// 编码sidx盒子 | /// 编码sidx盒子 | ||||
/// </summary> | /// </summary> | ||||
/// <returns></returns> | /// <returns></returns> | ||||
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); | byte[] buffer = FMp4ArrayPool.Rent(4096); | ||||
FMp4MessagePackWriter writer = new FMp4MessagePackWriter(buffer); | FMp4MessagePackWriter writer = new FMp4MessagePackWriter(buffer); | ||||
@@ -120,7 +122,7 @@ namespace JT1078.FMp4 | |||||
{ | { | ||||
SegmentIndexBox segmentIndexBox = new SegmentIndexBox(1); | SegmentIndexBox segmentIndexBox = new SegmentIndexBox(1); | ||||
segmentIndexBox.ReferenceID = 1; | segmentIndexBox.ReferenceID = 1; | ||||
segmentIndexBox.EarliestPresentationTime = timestamp*1000; | |||||
segmentIndexBox.EarliestPresentationTime = timestamp; | |||||
segmentIndexBox.SegmentIndexs = new List<SegmentIndexBox.SegmentIndex>() | segmentIndexBox.SegmentIndexs = new List<SegmentIndexBox.SegmentIndex>() | ||||
{ | { | ||||
new SegmentIndexBox.SegmentIndex | new SegmentIndexBox.SegmentIndex | ||||
@@ -203,7 +205,7 @@ namespace JT1078.FMp4 | |||||
avc1.AVCConfigurationBox.SPSs = new List<byte[]>() { spsNALU.RawData }; | avc1.AVCConfigurationBox.SPSs = new List<byte[]>() { spsNALU.RawData }; | ||||
movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.SampleEntries.Add(avc1); | movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.SampleEntries.Add(avc1); | ||||
movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.TimeToSampleBox = new TimeToSampleBox(); | 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.SampleToChunkBox = new SampleToChunkBox(); | ||||
movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleSizeBox = new SampleSizeBox(); | movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleSizeBox = new SampleSizeBox(); | ||||
movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.ChunkOffsetBox = new ChunkOffsetBox(); | movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.ChunkOffsetBox = new ChunkOffsetBox(); | ||||
@@ -230,7 +232,7 @@ namespace JT1078.FMp4 | |||||
/// 编码Moof盒子 | /// 编码Moof盒子 | ||||
/// </summary> | /// </summary> | ||||
/// <returns></returns> | /// <returns></returns> | ||||
public byte[] EncoderMoofBox(List<H264NALU> nalus, int naluLength,ulong timestamp,uint frameInterval, uint keyframeFlag,int moofOffset=0) | |||||
public byte[] EncoderMoofBox(List<H264NALU> nalus, int naluLength, ulong timestamp, uint frameInterval, uint IframeInterval, uint keyframeFlag) | |||||
{ | { | ||||
byte[] buffer = FMp4ArrayPool.Rent(naluLength + 4096); | byte[] buffer = FMp4ArrayPool.Rent(naluLength + 4096); | ||||
FMp4MessagePackWriter writer = new FMp4MessagePackWriter(buffer); | FMp4MessagePackWriter writer = new FMp4MessagePackWriter(buffer); | ||||
@@ -242,8 +244,9 @@ namespace JT1078.FMp4 | |||||
movieFragmentBox.TrackFragmentBox = new TrackFragmentBox(); | movieFragmentBox.TrackFragmentBox = new TrackFragmentBox(); | ||||
//0x39 写文件 | //0x39 写文件 | ||||
//0x02 分段 | //0x02 分段 | ||||
movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox = new TrackFragmentHeaderBox(0x20038); | |||||
movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox = new TrackFragmentHeaderBox(0x2003a); | |||||
movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.TrackID = 1; | movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.TrackID = 1; | ||||
movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.SampleDescriptionIndex = 1; | |||||
movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleDuration = frameInterval; | movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleDuration = frameInterval; | ||||
movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleSize = (uint)naluLength; | movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleSize = (uint)naluLength; | ||||
movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleFlags = 0x1010000; | movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleFlags = 0x1010000; | ||||
@@ -254,19 +257,21 @@ namespace JT1078.FMp4 | |||||
//0x02 分段 | //0x02 分段 | ||||
//0x205 | //0x205 | ||||
//uint flag = 0x000200 | 0x000800 | 0x000400 | 0x000100; | //uint flag = 0x000200 | 0x000800 | 0x000400 | 0x000100; | ||||
movieFragmentBox.TrackFragmentBox.TrackRunBox = new TrackRunBox(); | |||||
movieFragmentBox.TrackFragmentBox.TrackRunBox.FirstSampleFlags = 33554432; | |||||
movieFragmentBox.TrackFragmentBox.TrackRunBox.TrackRunInfos = new List<TrackRunBox.TrackRunInfo>(); | |||||
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<TrackRunBox.TrackRunInfo>(); | |||||
movieFragmentBox.TrackFragmentBox.TrackRunBox.TrackRunInfos.Add(new TrackRunBox.TrackRunInfo() | movieFragmentBox.TrackFragmentBox.TrackRunBox.TrackRunInfos.Add(new TrackRunBox.TrackRunInfo() | ||||
{ | { | ||||
SampleDuration= frameIntervalCache, | |||||
//SampleDuration= frameInterval, | |||||
SampleSize = (uint)naluLength, | SampleSize = (uint)naluLength, | ||||
SampleCompositionTimeOffset = (long)timestamp , | |||||
SampleFlags = movieFragmentBox.TrackFragmentBox.TrackRunBox.Flags | |||||
//SampleCompositionTimeOffset = frameInterval, | |||||
//SampleFlags = movieFragmentBox.TrackFragmentBox.TrackRunBox.Flags | |||||
}); | }); | ||||
movieFragmentBox.ToBuffer(ref writer); | movieFragmentBox.ToBuffer(ref writer); | ||||
var data = writer.FlushAndGetArray(); | var data = writer.FlushAndGetArray(); | ||||
@@ -399,7 +404,6 @@ namespace JT1078.FMp4 | |||||
} | } | ||||
uint sn = 1; | uint sn = 1; | ||||
uint frameIntervalCache = 0; | |||||
bool first = false; | bool first = false; | ||||
/// <summary> | /// <summary> | ||||
@@ -983,6 +983,7 @@ | |||||
<member name="P:JT1078.FMp4.TrackFragmentHeaderBox.DefaultSampleFlags"> | <member name="P:JT1078.FMp4.TrackFragmentHeaderBox.DefaultSampleFlags"> | ||||
<summary> | <summary> | ||||
TFHD_FLAG_DEFAULT_FLAGS | TFHD_FLAG_DEFAULT_FLAGS | ||||
MOV_AUDIO == handler_type ? 0x02000000 : (0x00010000| 0x01000000); | |||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="T:JT1078.FMp4.TrackFragmentRandomAccessBox"> | <member name="T:JT1078.FMp4.TrackFragmentRandomAccessBox"> | ||||
@@ -1335,7 +1336,7 @@ | |||||
</summary> | </summary> | ||||
<returns></returns> | <returns></returns> | ||||
</member> | </member> | ||||
<member name="M:JT1078.FMp4.FMp4Encoder.EncoderSidxBox(System.Int32,System.UInt64,System.UInt32)"> | |||||
<member name="M:JT1078.FMp4.FMp4Encoder.EncoderSidxBox(System.Int32,System.UInt64,System.UInt32,System.UInt32)"> | |||||
<summary> | <summary> | ||||
编码sidx盒子 | 编码sidx盒子 | ||||
</summary> | </summary> | ||||
@@ -1347,7 +1348,7 @@ | |||||
</summary> | </summary> | ||||
<returns></returns> | <returns></returns> | ||||
</member> | </member> | ||||
<member name="M:JT1078.FMp4.FMp4Encoder.EncoderMoofBox(System.Collections.Generic.List{JT1078.Protocol.H264.H264NALU},System.Int32,System.UInt64,System.UInt32,System.UInt32,System.Int32)"> | |||||
<member name="M:JT1078.FMp4.FMp4Encoder.EncoderMoofBox(System.Collections.Generic.List{JT1078.Protocol.H264.H264NALU},System.Int32,System.UInt64,System.UInt32,System.UInt32,System.UInt32)"> | |||||
<summary> | <summary> | ||||
编码Moof盒子 | 编码Moof盒子 | ||||
</summary> | </summary> | ||||
@@ -79,20 +79,19 @@ namespace JT1078.SignalR.Test.Services | |||||
//q.Enqueue(moov); | //q.Enqueue(moov); | ||||
first.Add(moov); | first.Add(moov); | ||||
q.Add(first.SelectMany(s=>s).ToArray()); | q.Add(first.SelectMany(s=>s).ToArray()); | ||||
List<NalUnitType> filter = new List<NalUnitType>() { NalUnitType.SEI,NalUnitType.SPS,NalUnitType.PPS}; | |||||
List<NalUnitType> filter = new List<NalUnitType>() { NalUnitType.SEI,NalUnitType.SPS,NalUnitType.PPS,NalUnitType.AUD}; | |||||
foreach (var package in packages) | foreach (var package in packages) | ||||
{ | { | ||||
List<byte[]> other = new List<byte[]>(); | List<byte[]> other = new List<byte[]>(); | ||||
var otherStypBuffer = fMp4Encoder.EncoderStypBox(); | |||||
other.Add(otherStypBuffer); | |||||
var otherNalus = h264Decoder.ParseNALU(package); | 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 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); | other.Add(otherMdatBuffer); | ||||
q.Add(other.SelectMany(s => s).ToArray()); | q.Add(other.SelectMany(s => s).ToArray()); | ||||
} | } | ||||