diff --git a/src/JT1078.FMp4.Test/FMp4Box_Test.cs b/src/JT1078.FMp4.Test/FMp4Box_Test.cs index 1655bd6..1844585 100644 --- a/src/JT1078.FMp4.Test/FMp4Box_Test.cs +++ b/src/JT1078.FMp4.Test/FMp4Box_Test.cs @@ -172,7 +172,7 @@ namespace JT1078.FMp4.Test //stbl SampleTableBox sampleTableBox = new SampleTableBox(); //stbl->stsd - SampleDescriptionBox sampleDescriptionBox = new SampleDescriptionBox(HandlerType.none); + SampleDescriptionBox sampleDescriptionBox = new SampleDescriptionBox(); //stbl->stsd->avc1 AVC1SampleEntry aVC1SampleEntry = new AVC1SampleEntry(); aVC1SampleEntry.Width = 0x0220; diff --git a/src/JT1078.FMp4.Test/JT1078ToFMp4Box_Test.cs b/src/JT1078.FMp4.Test/JT1078ToFMp4Box_Test.cs index fcf2ca6..b88ba25 100644 --- a/src/JT1078.FMp4.Test/JT1078ToFMp4Box_Test.cs +++ b/src/JT1078.FMp4.Test/JT1078ToFMp4Box_Test.cs @@ -71,7 +71,7 @@ namespace JT1078.FMp4.Test movieBox.TrackBox.MediaBox.MediaInformationBox.DataInformationBox.DataReferenceBox.DataEntryBoxes = new List(); movieBox.TrackBox.MediaBox.MediaInformationBox.DataInformationBox.DataReferenceBox.DataEntryBoxes.Add(new DataEntryUrlBox(1)); movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox = new SampleTableBox(); - movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox = new SampleDescriptionBox(movieBox.TrackBox.MediaBox.HandlerBox.HandlerType); + movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox = new SampleDescriptionBox(); movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.SampleEntries = new List(); AVC1SampleEntry avc1 = new AVC1SampleEntry(); avc1.AVCConfigurationBox = new AVCConfigurationBox(); @@ -224,7 +224,7 @@ namespace JT1078.FMp4.Test movieBox.TrackBox.MediaBox.MediaInformationBox.DataInformationBox.DataReferenceBox.DataEntryBoxes = new List(); movieBox.TrackBox.MediaBox.MediaInformationBox.DataInformationBox.DataReferenceBox.DataEntryBoxes.Add(new DataEntryUrlBox(1)); movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox = new SampleTableBox(); - movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox = new SampleDescriptionBox(movieBox.TrackBox.MediaBox.HandlerBox.HandlerType); + movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox = new SampleDescriptionBox(); movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.SampleEntries = new List(); AVC1SampleEntry avc1 = new AVC1SampleEntry(); avc1.AVCConfigurationBox = new AVCConfigurationBox(); @@ -373,7 +373,7 @@ namespace JT1078.FMp4.Test movieBox.TrackBox.MediaBox.MediaInformationBox.DataInformationBox.DataReferenceBox.DataEntryBoxes = new List(); movieBox.TrackBox.MediaBox.MediaInformationBox.DataInformationBox.DataReferenceBox.DataEntryBoxes.Add(new DataEntryUrlBox(1)); movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox = new SampleTableBox(); - movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox = new SampleDescriptionBox(movieBox.TrackBox.MediaBox.HandlerBox.HandlerType); + movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox = new SampleDescriptionBox(); movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.SampleEntries = new List(); AVC1SampleEntry avc1 = new AVC1SampleEntry(); avc1.AVCConfigurationBox = new AVCConfigurationBox(); @@ -453,12 +453,17 @@ namespace JT1078.FMp4.Test fileStream.Write(moov); foreach (var package in packages) { + var otherStypBuffer = fMp4Encoder.EncoderStypBox(); + fileStream.Write(otherStypBuffer); + var otherSidxBuffer = fMp4Encoder.EncoderSidxBox(package.Timestamp, package.LastIFrameInterval); + fileStream.Write(otherSidxBuffer); var otherNalus = h264Decoder.ParseNALU(package); var flag = package.Label3.DataType == Protocol.Enums.JT1078DataType.视频I帧 ? 1u : 0u; var otherMoofBuffer = fMp4Encoder.EncoderMoofBox(otherNalus, package.Bodies.Length, package.Timestamp, package.LastIFrameInterval, flag); var otherMdatBuffer = fMp4Encoder.EncoderMdatBox(otherNalus, package.Bodies.Length); fileStream.Write(otherMoofBuffer); fileStream.Write(otherMdatBuffer); + } fileStream.Close(); } diff --git a/src/JT1078.FMp4/Boxs/SampleDescriptionBox.cs b/src/JT1078.FMp4/Boxs/SampleDescriptionBox.cs index de595aa..9cd37cc 100644 --- a/src/JT1078.FMp4/Boxs/SampleDescriptionBox.cs +++ b/src/JT1078.FMp4/Boxs/SampleDescriptionBox.cs @@ -16,15 +16,13 @@ namespace JT1078.FMp4 /// /// stsd /// - /// /// /// - public SampleDescriptionBox(HandlerType handlerType,byte version=0, uint flags=0) : base("stsd", version, flags) + public SampleDescriptionBox(byte version=0, uint flags=0) : base("stsd", version, flags) { - HandlerType = handlerType; + } - public HandlerType HandlerType { get; set; } - public uint EntryCount { get; set; } + private uint EntryCount { get; set; } public List SampleEntries { get; set; } public void ToBuffer(ref FMp4MessagePackWriter writer) { diff --git a/src/JT1078.FMp4/Boxs/SampleTableBox.cs b/src/JT1078.FMp4/Boxs/SampleTableBox.cs index a130d83..ffb5e46 100644 --- a/src/JT1078.FMp4/Boxs/SampleTableBox.cs +++ b/src/JT1078.FMp4/Boxs/SampleTableBox.cs @@ -26,6 +26,10 @@ namespace JT1078.FMp4 /// public TimeToSampleBox TimeToSampleBox { get; set; } /// + /// stss + /// + public SyncSampleBox SyncSampleBox { get; set; } + /// /// ctts /// public CompositionOffsetBox CompositionOffsetBox { get; set; } @@ -44,7 +48,6 @@ namespace JT1078.FMp4 /// public ChunkOffsetBox ChunkOffsetBox { get; set; } //public ChunkLargeOffsetBox ChunkLargeOffsetBox { get; set; } - //public SyncSampleBox SyncSampleBox { get; set; } //public ShadowSyncSampleBox ShadowSyncSampleBox { get; set; } //public PaddingBitsBox PaddingBitsBox { get; set; } //public DegradationPriorityBox DegradationPriorityBox { get; set; } @@ -58,6 +61,10 @@ namespace JT1078.FMp4 Start(ref writer); SampleDescriptionBox.ToBuffer(ref writer); TimeToSampleBox.ToBuffer(ref writer); + if (SyncSampleBox != null) + { + SyncSampleBox.ToBuffer(ref writer); + } if(CompositionOffsetBox!=null) CompositionOffsetBox.ToBuffer(ref writer); SampleToChunkBox.ToBuffer(ref writer); diff --git a/src/JT1078.FMp4/Boxs/SegmentIndexBox.cs b/src/JT1078.FMp4/Boxs/SegmentIndexBox.cs index e8c708b..04d8825 100644 --- a/src/JT1078.FMp4/Boxs/SegmentIndexBox.cs +++ b/src/JT1078.FMp4/Boxs/SegmentIndexBox.cs @@ -1,58 +1,123 @@ -using System; +using JT1078.FMp4.Interfaces; +using JT1078.FMp4.MessagePack; +using System; using System.Collections.Generic; using System.Text; namespace JT1078.FMp4 { - public class SegmentIndexBox : FullBox + /// + /// sidx + /// + public class SegmentIndexBox : FullBox,IFMp4MessagePackFormatter { + /// + /// sidx + /// + /// + /// public SegmentIndexBox(byte version, uint flags=0) : base("sidx", version, flags) { } - - public uint ReferenceID { get; set; } - public string Timescale { get; set; } /// /// /// - public ulong EarliestPresentationTimeLarge { get; set; } - public ulong FirstOffsetLarge { get; set; } + public uint ReferenceID { get; set; } = 1; + /// + /// + /// + public uint Timescale { get; set; } = 1000; /// - /// if(version==0) + /// if(version==0) + /// version==0 32 bit + /// version>0 64 bit /// - public uint EarliestPresentationTime { get; set; } + public ulong EarliestPresentationTime { get; set; } /// - /// if (version==0) + /// + /// + public ulong FirstOffset { get; set; } = 0; + private ushort Reserved { get; set; } + //private ushort ReferenceCount { get; set; } + /// + /// /// - public uint FirstOffset { get; set; } - public ushort Reserved { get; set; } - public ushort ReferenceCount { get; set; } - public List SegmentIndexs { get; set; } + public void ToBuffer(ref FMp4MessagePackWriter writer) + { + Start(ref writer); + WriterFullBoxToBuffer(ref writer); + writer.WriteUInt32(ReferenceID); + writer.WriteUInt32(Timescale); + if (Version == 0) + { + writer.WriteUInt32((uint)EarliestPresentationTime); + writer.WriteUInt32((uint)FirstOffset); + } + else + { + writer.WriteUInt64(EarliestPresentationTime); + writer.WriteUInt64(FirstOffset); + } + writer.WriteUInt16(Reserved); + if(SegmentIndexs!=null && SegmentIndexs.Count > 0) + { + writer.WriteUInt16((ushort)SegmentIndexs.Count); + foreach(var si in SegmentIndexs) + { + if (si.ReferenceType) + { + writer.WriteUInt32(si.ReferencedSize | 0x80000000); + } + else + { + writer.WriteUInt32(si.ReferencedSize); + } + writer.WriteUInt32(si.SubsegmentDuration); + if (si.StartsWithSAP) + { + writer.WriteUInt32((si.SAPDeltaTime | 0x80000000 | (uint)(si.SAPType << 28 & 0x70000000))); + } + else + { + writer.WriteUInt32((si.SAPDeltaTime | (uint)((si.SAPType <<28) & 0x70000000))); + } + } + } + else + { + writer.WriteUInt16(0); + } + End(ref writer); + } + public class SegmentIndex { /// /// 4byte 32 - 1 /// - public bool ReferenceType { get; set; } + public bool ReferenceType { get; set; } = false; /// /// 4byte 32 - 31 /// - public uint ReferencedSize { get; set; } + public uint ReferencedSize { get; set; } = 0; + /// + /// + /// public uint SubsegmentDuration { get; set; } /// /// 4byte 32 - 1 /// - public bool StartsWithSAP { get; set; } + public bool StartsWithSAP { get; set; } = true; /// /// 4byte 32 - 3 /// - public byte SAPType { get; set; } + public byte SAPType { get; set; } = 1; /// /// 4byte 32 - 28 /// - public uint SAPDeltaTime { get; set; } + public uint SAPDeltaTime { get; set; } = 0; } } } diff --git a/src/JT1078.FMp4/Boxs/SyncSampleBox.cs b/src/JT1078.FMp4/Boxs/SyncSampleBox.cs index ca13df9..0f92c4c 100644 --- a/src/JT1078.FMp4/Boxs/SyncSampleBox.cs +++ b/src/JT1078.FMp4/Boxs/SyncSampleBox.cs @@ -1,17 +1,46 @@ -using System; +using JT1078.FMp4.Interfaces; +using JT1078.FMp4.MessagePack; +using System; using System.Collections.Generic; using System.Text; namespace JT1078.FMp4 { - public class SyncSampleBox : FullBox + /// + /// stss + /// + public class SyncSampleBox : FullBox, IFMp4MessagePackFormatter { + /// + /// stss + /// + /// + /// public SyncSampleBox(byte version=0, uint flags=0) : base("stss", version, flags) { } - public uint EntryCount { get; set; } + //private uint EntryCount { get; set; } - public List SampleNumber { get; set; } + public List SampleNumbers { get; set; } + + public void ToBuffer(ref FMp4MessagePackWriter writer) + { + Start(ref writer); + WriterFullBoxToBuffer(ref writer); + if(SampleNumbers!=null && SampleNumbers.Count > 0) + { + writer.WriteUInt32((uint)SampleNumbers.Count); + foreach(var item in SampleNumbers) + { + writer.WriteUInt32(item); + } + } + else + { + writer.WriteUInt32(0); + } + End(ref writer); + } } } diff --git a/src/JT1078.FMp4/Boxs/TrackRunBox.cs b/src/JT1078.FMp4/Boxs/TrackRunBox.cs index d572d42..12741bf 100644 --- a/src/JT1078.FMp4/Boxs/TrackRunBox.cs +++ b/src/JT1078.FMp4/Boxs/TrackRunBox.cs @@ -13,13 +13,26 @@ namespace JT1078.FMp4 { /// /// trun + /// 201 205 1 + /// 201 0010 0000 0001 + /// 205 0010 0000 0101 + /// 1 0000 0000 0001 + /// tr_flags 是用来表示下列 sample 相关的标识符是否应用到每个字段中: + /// 0x000001-0000 0000 0001: data-offset-present,只应用 data-offset + /// 0x000004-0000 0000 0100: 只对第一个 sample 应用对应的 flags。剩余 sample flags 就不管了。 + /// 0x000100-0001 0000 0000: 这个比较重要,表示每个 sample 都有自己的 duration,否则使用默认的 + /// 0x000200-0010 0000 0000: 每个 sample 有自己的 sample_size,否则使用默认的。 + /// 0x000400-0100 0000 0000: 对每个 sample 使用自己的 flags。否则,使用默认的。 + /// 0x000800-1000 0000 0000: 每个 sample 都有自己的 cts 值 /// /// /// public TrackRunBox(byte version=0, uint flags= 0x000f01) : base("trun", version, flags) { } - + /// + /// + /// public uint SampleCount { get; set; } /// /// 可选的 diff --git a/src/JT1078.FMp4/FMp4Encoder.cs b/src/JT1078.FMp4/FMp4Encoder.cs index ffe69b1..31274b5 100644 --- a/src/JT1078.FMp4/FMp4Encoder.cs +++ b/src/JT1078.FMp4/FMp4Encoder.cs @@ -18,9 +18,11 @@ namespace JT1078.FMp4 /// stream data /// ftyp /// moov + /// styp 1 /// moof 1 /// mdat 1 /// ... + /// styp n /// moof n /// mdat n /// mfra @@ -37,6 +39,10 @@ namespace JT1078.FMp4 h264Decoder = new H264Decoder(); } + /// + /// styp + /// + /// public byte[] EncoderStypBox() { byte[] buffer = FMp4ArrayPool.Rent(4096); @@ -50,7 +56,7 @@ namespace JT1078.FMp4 stypTypeBox.CompatibleBrands.Add("isom"); stypTypeBox.CompatibleBrands.Add("mp42"); stypTypeBox.CompatibleBrands.Add("msdh"); - stypTypeBox.CompatibleBrands.Add("nsix"); + stypTypeBox.CompatibleBrands.Add("msix"); stypTypeBox.CompatibleBrands.Add("iso5"); stypTypeBox.CompatibleBrands.Add("iso6"); stypTypeBox.ToBuffer(ref writer); @@ -74,23 +80,23 @@ 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 = "iso5"; + //fileTypeBox.MajorBrand = "isom"; //fileTypeBox.MinorVersion = "\0\0\u0002\0"; - //fileTypeBox.CompatibleBrands.Add("iso5"); - //fileTypeBox.CompatibleBrands.Add("iso6"); + //fileTypeBox.CompatibleBrands.Add("isom"); + //fileTypeBox.CompatibleBrands.Add("iso2"); + //fileTypeBox.CompatibleBrands.Add("avc1"); //fileTypeBox.CompatibleBrands.Add("mp41"); - //fileTypeBox.ToBuffer(ref writer); - + //fileTypeBox.CompatibleBrands.Add("iso5"); + FileTypeBox fileTypeBox = new FileTypeBox(); + fileTypeBox.MajorBrand = "msdh"; + fileTypeBox.MinorVersion = "\0\0\0\0"; + fileTypeBox.CompatibleBrands.Add("isom"); + fileTypeBox.CompatibleBrands.Add("mp42"); + fileTypeBox.CompatibleBrands.Add("msdh"); + fileTypeBox.CompatibleBrands.Add("msix"); + fileTypeBox.CompatibleBrands.Add("iso5"); + fileTypeBox.CompatibleBrands.Add("iso6"); fileTypeBox.ToBuffer(ref writer); var data = writer.FlushAndGetArray(); return data; @@ -101,6 +107,36 @@ namespace JT1078.FMp4 } } + /// + /// 编码sidx盒子 + /// + /// + public byte[] EncoderSidxBox(ulong timestamp, uint frameInterval) + { + byte[] buffer = FMp4ArrayPool.Rent(4096); + FMp4MessagePackWriter writer = new FMp4MessagePackWriter(buffer); + try + { + SegmentIndexBox segmentIndexBox = new SegmentIndexBox(1); + segmentIndexBox.ReferenceID = 1; + segmentIndexBox.EarliestPresentationTime = timestamp; + segmentIndexBox.SegmentIndexs = new List() + { + new SegmentIndexBox.SegmentIndex + { + SubsegmentDuration=frameInterval + } + }; + segmentIndexBox.ToBuffer(ref writer); + var data = writer.FlushAndGetArray(); + return data; + } + finally + { + FMp4ArrayPool.Return(buffer); + } + } + /// /// 编码moov盒子 /// @@ -151,7 +187,7 @@ namespace JT1078.FMp4 movieBox.TrackBox.MediaBox.MediaInformationBox.DataInformationBox.DataReferenceBox.DataEntryBoxes = new List(); movieBox.TrackBox.MediaBox.MediaInformationBox.DataInformationBox.DataReferenceBox.DataEntryBoxes.Add(new DataEntryUrlBox(1)); movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox = new SampleTableBox(); - movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox = new SampleDescriptionBox(movieBox.TrackBox.MediaBox.HandlerBox.HandlerType); + movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox = new SampleDescriptionBox(); movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.SampleEntries = new List(); AVC1SampleEntry avc1 = new AVC1SampleEntry(); avc1.AVCConfigurationBox = new AVCConfigurationBox(); @@ -164,37 +200,11 @@ namespace JT1078.FMp4 avc1.AVCConfigurationBox.PPSs = new List() { ppsNALU.RawData }; avc1.AVCConfigurationBox.SPSs = new List() { spsNALU.RawData }; movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.SampleEntries.Add(avc1); - movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.TimeToSampleBox = new TimeToSampleBox() { - //TimeToSampleInfos=new List - //{ - // new TimeToSampleBox.TimeToSampleInfo - // { - // SampleCount=0, - // SampleDelta=0 - // } - //} - }; - movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleToChunkBox = new SampleToChunkBox() { - //SampleToChunkInfos=new List() - //{ - // new SampleToChunkBox.SampleToChunkInfo - // { - - // } - //} - }; - movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleSizeBox = new SampleSizeBox() { - //EntrySize = new List() - //{ - // 0 - //} - }; - movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.ChunkOffsetBox = new ChunkOffsetBox() { - //ChunkOffset=new List() - //{ - // 0 - //} - }; + movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.TimeToSampleBox = new TimeToSampleBox(); + movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SyncSampleBox = new SyncSampleBox(); + movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleToChunkBox = new SampleToChunkBox(); + movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleSizeBox = new SampleSizeBox(); + movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.ChunkOffsetBox = new ChunkOffsetBox(); movieBox.MovieExtendsBox = new MovieExtendsBox(); movieBox.MovieExtendsBox.TrackExtendsBoxs = new List(); TrackExtendsBox trex = new TrackExtendsBox(); @@ -214,7 +224,6 @@ namespace JT1078.FMp4 } } - /// /// 编码Moof盒子 /// @@ -237,49 +246,27 @@ namespace JT1078.FMp4 movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleSize = (uint)naluLength; movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleFlags = 0x1010000; movieFragmentBox.TrackFragmentBox.TrackFragmentBaseMediaDecodeTimeBox = new TrackFragmentBaseMediaDecodeTimeBox(); - //movieFragmentBox.TrackFragmentBox.SampleDependencyTypeBox = new SampleDependencyTypeBox() - //{ - // SampleDependencyTypes = new List() - //}; //trun //0x39 写文件 //0x02 分段 //uint flag = 0x000200 | 0x000800 | 0x000400 | 0x000100; uint flag = 4u; - - //var sdtp = new SampleDependencyTypeBox.SampleDependencyType(); - //if (keyframeFlag==1) - //{ - // sdtp.SampleDependsOn = 2; - // sdtp.SampleIsDependedOn = 1; - //} - //else - //{ - // sdtp.SampleDependsOn = 1; - // sdtp.SampleIsDependedOn = 0; - //} - if (!first) { //sdtp.IsLeading = 1; //flag = 4u; movieFragmentBox.TrackFragmentBox.TrackFragmentBaseMediaDecodeTimeBox.BaseMediaDecodeTime = 0; - movieFragmentBox.TrackFragmentBox.TrackRunBox = new TrackRunBox(flags: 0x205); + movieFragmentBox.TrackFragmentBox.TrackRunBox = new TrackRunBox(flags: 5); first = true; } else { //flag = 0x000400; - movieFragmentBox.TrackFragmentBox.TrackFragmentBaseMediaDecodeTimeBox.BaseMediaDecodeTime = BaseMediaDecodeTime; - movieFragmentBox.TrackFragmentBox.TrackRunBox = new TrackRunBox(flags: 0x205); - BaseMediaDecodeTime += BaseMediaDecodeTime; + movieFragmentBox.TrackFragmentBox.TrackFragmentBaseMediaDecodeTimeBox.BaseMediaDecodeTime = timestamp*1000; + movieFragmentBox.TrackFragmentBox.TrackRunBox = new TrackRunBox(flags: 5); } - //movieFragmentBox.TrackFragmentBox.SampleDependencyTypeBox.SampleDependencyTypes.Add(sdtp); - movieFragmentBox.TrackFragmentBox.TrackRunBox.FirstSampleFlags = 33554432; movieFragmentBox.TrackFragmentBox.TrackRunBox.TrackRunInfos = new List(); - - //movieFragmentBox.TrackFragmentBox.TrackRunBox.TrackRunInfos.Add(new TrackRunBox.TrackRunInfo()); movieFragmentBox.TrackFragmentBox.TrackRunBox.TrackRunInfos.Add(new TrackRunBox.TrackRunInfo() { SampleDuration= frameInterval, @@ -287,7 +274,6 @@ namespace JT1078.FMp4 SampleCompositionTimeOffset = frameInterval, SampleFlags = flag }); - movieFragmentBox.ToBuffer(ref writer); var data = writer.FlushAndGetArray(); return data; @@ -381,7 +367,7 @@ namespace JT1078.FMp4 movieBox.TrackBox.MediaBox.MediaInformationBox.DataInformationBox.DataReferenceBox.DataEntryBoxes = new List(); movieBox.TrackBox.MediaBox.MediaInformationBox.DataInformationBox.DataReferenceBox.DataEntryBoxes.Add(new DataEntryUrlBox(1)); movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox = new SampleTableBox(); - movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox = new SampleDescriptionBox(movieBox.TrackBox.MediaBox.HandlerBox.HandlerType); + movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox = new SampleDescriptionBox(); movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.SampleEntries = new List(); AVC1SampleEntry avc1 = new AVC1SampleEntry(); avc1.AVCConfigurationBox = new AVCConfigurationBox(); @@ -422,8 +408,6 @@ namespace JT1078.FMp4 bool first = false; - ulong BaseMediaDecodeTime = 2160000; - /// /// 编码其他视频数据盒子 /// diff --git a/src/JT1078.FMp4/JT1078.FMp4.xml b/src/JT1078.FMp4/JT1078.FMp4.xml index f26948c..2c0acee 100644 --- a/src/JT1078.FMp4/JT1078.FMp4.xml +++ b/src/JT1078.FMp4/JT1078.FMp4.xml @@ -571,11 +571,10 @@ stsd - + stsd - @@ -622,6 +621,11 @@ stts + + + stss + + ctts @@ -672,19 +676,43 @@ - + + + sidx + + + + + sidx + + + + + + + + + + - if(version==0) + if(version==0) + version==0 32 bit + version>0 64 bit - if (version==0) + + + + + + @@ -697,6 +725,11 @@ 4byte 32 - 31 + + + + + 4byte 32 - 1 @@ -798,6 +831,18 @@ length:ItemCount + + + stss + + + + + stss + + + + stts @@ -1006,10 +1051,26 @@ trun + 201 205 1 + 201 0010 0000 0001 + 205 0010 0000 0101 + 1 0000 0000 0001 + tr_flags 是用来表示下列 sample 相关的标识符是否应用到每个字段中: + 0x000001-0000 0000 0001: data-offset-present,只应用 data-offset + 0x000004-0000 0000 0100: 只对第一个 sample 应用对应的 flags。剩余 sample flags 就不管了。 + 0x000100-0001 0000 0000: 这个比较重要,表示每个 sample 都有自己的 duration,否则使用默认的 + 0x000200-0010 0000 0000: 每个 sample 有自己的 sample_size,否则使用默认的。 + 0x000400-0100 0000 0000: 对每个 sample 使用自己的 flags。否则,使用默认的。 + 0x000800-1000 0000 0000: 每个 sample 都有自己的 cts 值 + + + + + 可选的 @@ -1241,9 +1302,11 @@ stream data ftyp moov + styp 1 moof 1 mdat 1 ... + styp n moof n mdat n mfra @@ -1255,12 +1318,24 @@ + + + styp + + + 编码ftyp盒子 + + + 编码sidx盒子 + + + 编码moov盒子