diff --git a/doc/ffmpeginfo.txt b/doc/ffmpeginfo.txt index 0058b3b..f11e1e7 100644 --- a/doc/ffmpeginfo.txt +++ b/doc/ffmpeginfo.txt @@ -2,9 +2,10 @@ ffmpeg -i demo.mp4 -c copy -f flv -vcodec h264 -acodec aac demo_flv.flv ./ffmpeg -i JT1078_3.h264 -r 25 -c copy -f flv "D:\JT1078_3.flv" -ffmpeg -f dshow -i video="USB2.0 PC CAMERA" -t 60 -c copy -f h264 -vcodec h264 jt1078.264 +ffmpeg -f dshow -i video="USB2.0 PC CAMERA" -t 60 -c copy -f h264 -vcodec h264 ipc.264 ffmpeg -i demo.264 -vcodec copy -f mp4 -movflags frag_keyframe+empty_moov fragmented_demo.mp4 +ffmpeg -i ipc.264 -vcodec copy -f mp4 -movflags frag_keyframe+empty_moov ipc_fragmented_demo.mp4 chrome://media-internals/ \ No newline at end of file diff --git a/doc/video/ipc.264 b/doc/video/ipc.264 new file mode 100644 index 0000000..3052a10 Binary files /dev/null and b/doc/video/ipc.264 differ diff --git a/doc/video/ipc_fragmented_demo.mp4 b/doc/video/ipc_fragmented_demo.mp4 new file mode 100644 index 0000000..eeab519 Binary files /dev/null and b/doc/video/ipc_fragmented_demo.mp4 differ diff --git a/src/JT1078.FMp4.Test/JT1078.FMp4.Test.csproj b/src/JT1078.FMp4.Test/JT1078.FMp4.Test.csproj index 1937a79..026873a 100644 --- a/src/JT1078.FMp4.Test/JT1078.FMp4.Test.csproj +++ b/src/JT1078.FMp4.Test/JT1078.FMp4.Test.csproj @@ -22,6 +22,7 @@ + Always @@ -30,6 +31,7 @@ Always + Always @@ -38,5 +40,17 @@ Always - + + + + Always + + + Always + + + Always + + + diff --git a/src/JT1078.FMp4.Test/JT1078ToFMp4Box_Test.cs b/src/JT1078.FMp4.Test/JT1078ToFMp4Box_Test.cs new file mode 100644 index 0000000..f66523b --- /dev/null +++ b/src/JT1078.FMp4.Test/JT1078ToFMp4Box_Test.cs @@ -0,0 +1,119 @@ +using JT1078.FMp4.Enums; +using JT1078.FMp4.Samples; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace JT1078.FMp4.Test +{ + public class JT1078ToFMp4Box_Test + { + [Fact] + public void Test1() + { + //ftyp + FileTypeBox fileTypeBox = new FileTypeBox(); + fileTypeBox.MajorBrand = "isom"; + fileTypeBox.MinorVersion = "\0\0\0\u0001"; + fileTypeBox.CompatibleBrands.Add("isom"); + fileTypeBox.CompatibleBrands.Add("avc1"); + //moov + MovieBox movieBox = new MovieBox(); + movieBox.MovieHeaderBox = new MovieHeaderBox(1, 0); + movieBox.MovieHeaderBox.CreationTime = 2; + movieBox.MovieHeaderBox.ModificationTime = 3; + //var upperWordDuration = Math.floor(duration / (UINT32_MAX + 1)); + //var lowerWordDuration = Math.floor(duration % (UINT32_MAX + 1)); + //movieBox.MovieHeaderBox.Duration= + //movieBox.MovieHeaderBox.Timescale= + movieBox.TrackBox = new TrackBox(); + movieBox.TrackBox.TrackHeaderBox = new TrackHeaderBox(1, 7); + movieBox.TrackBox.TrackHeaderBox.CreationTime = 2; + movieBox.TrackBox.TrackHeaderBox.ModificationTime = 3; + movieBox.TrackBox.TrackHeaderBox.TrackID = movieBox.MovieHeaderBox.NextTrackID; + //duration = track.duration * track.timescale, + //upperWordDuration = Math.floor(duration / (UINT32_MAX + 1)), + //lowerWordDuration = Math.floor(duration % (UINT32_MAX + 1)); + //movieBox.TrackBox.TrackHeaderBox.Duration= + //movieBox.TrackBox.TrackHeaderBox.Timescale= + movieBox.TrackBox.TrackHeaderBox.TrackIsAudio = false; + //movieBox.TrackBox.TrackHeaderBox.Width= + //movieBox.TrackBox.TrackHeaderBox.Height= + movieBox.TrackBox.MediaBox = new MediaBox(); + movieBox.TrackBox.MediaBox.MediaHeaderBox = new MediaHeaderBox(); + //duration *= timescale; + //var upperWordDuration = Math.floor(duration / (UINT32_MAX + 1)); + //var lowerWordDuration = Math.floor(duration % (UINT32_MAX + 1)); + movieBox.TrackBox.MediaBox.MediaHeaderBox.CreationTime = 2; + movieBox.TrackBox.MediaBox.MediaHeaderBox.ModificationTime = 3; + //movieBox.TrackBox.MediaBox.MediaHeaderBox.Timescale= + //movieBox.TrackBox.MediaBox.MediaHeaderBox.Duration= + movieBox.TrackBox.MediaBox.HandlerBox = new HandlerBox(); + movieBox.TrackBox.MediaBox.HandlerBox.HandlerType = HandlerType.vide; + movieBox.TrackBox.MediaBox.HandlerBox.Name = "VideoHandler"; + movieBox.TrackBox.MediaBox.MediaInformationBox = new MediaInformationBox(); + movieBox.TrackBox.MediaBox.MediaInformationBox.VideoMediaHeaderBox = new VideoMediaHeaderBox(); + movieBox.TrackBox.MediaBox.MediaInformationBox.DataInformationBox = new DataInformationBox(); + movieBox.TrackBox.MediaBox.MediaInformationBox.DataInformationBox.DataReferenceBox = new DataReferenceBox(); + 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.SampleEntries = new List(); + AVC1SampleEntry avc1 = new AVC1SampleEntry(); + avc1.AVCConfigurationBox = new AVCConfigurationBox(); + //h264 + //avc1.Width= + //avc1.Height= + //avc1.AVCConfigurationBox.AVCLevelIndication + //avc1.AVCConfigurationBox.AVCProfileIndication + //avc1.AVCConfigurationBox.PPSs + //avc1.AVCConfigurationBox.SPSs + //avc1.AVCConfigurationBox.ProfileCompatibility + movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.SampleEntries.Add(avc1); + movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.TimeToSampleBox = new TimeToSampleBox(); + 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(); + trex.TrackID = movieBox.MovieHeaderBox.NextTrackID; + trex.DefaultSampleDescriptionIndex = 1; + trex.DefaultSampleDuration = 0; + trex.DefaultSampleSize = 0; + trex.DefaultSampleFlags = 1; + movieBox.MovieExtendsBox.TrackExtendsBoxs.Add(trex); + //fragment moof n + List moofs = new List(); + FragmentBox fragmentBox = new FragmentBox(); + fragmentBox.MovieFragmentBox = new MovieFragmentBox(); + fragmentBox.MovieFragmentBox.MovieFragmentHeaderBox = new MovieFragmentHeaderBox(); + //fragmentBox.MovieFragmentBox.MovieFragmentHeaderBox.SequenceNumber=SN + fragmentBox.MovieFragmentBox.TrackFragmentBox = new TrackFragmentBox(); + fragmentBox.MovieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox = new TrackFragmentHeaderBox(); + fragmentBox.MovieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.TrackID = movieBox.MovieHeaderBox.NextTrackID; + fragmentBox.MovieFragmentBox.TrackFragmentBox.SampleDependencyTypeBox = new SampleDependencyTypeBox(); + fragmentBox.MovieFragmentBox.TrackFragmentBox.SampleDependencyTypeBox.SampleDependencyTypes = new List(); + //todo:fragmentBox.MovieFragmentBox.TrackFragmentBox.SampleDependencyTypeBox.SampleDependencyTypes + fragmentBox.MovieFragmentBox.TrackFragmentBox.TrackFragmentBaseMediaDecodeTimeBox = new TrackFragmentBaseMediaDecodeTimeBox(); + //upperWordBaseMediaDecodeTime = Math.floor(baseMediaDecodeTime / (UINT32_MAX + 1)), + //lowerWordBaseMediaDecodeTime = Math.floor(baseMediaDecodeTime % (UINT32_MAX + 1)); + //fragmentBox.MovieFragmentBox.TrackFragmentBox.TrackFragmentBaseMediaDecodeTimeBox.BaseMediaDecodeTime + //trun + fragmentBox.MovieFragmentBox.TrackFragmentBox.TrackRunBox = new TrackRunBox(); + + moofs.Add(fragmentBox); + + + + + //mfra + + + } + } +} diff --git a/src/JT1078.FMp4/Boxs/FragmentBox.cs b/src/JT1078.FMp4/Boxs/FragmentBox.cs index 9f7b6c4..c2edf2a 100644 --- a/src/JT1078.FMp4/Boxs/FragmentBox.cs +++ b/src/JT1078.FMp4/Boxs/FragmentBox.cs @@ -6,6 +6,9 @@ using System.Text; namespace JT1078.FMp4 { + /// + /// + /// public class FragmentBox:IFMp4MessagePackFormatter { /// @@ -16,7 +19,10 @@ namespace JT1078.FMp4 /// mdat /// public MediaDataBox MediaDataBox { get; set; } - + /// + /// + /// + /// public void ToBuffer(ref FMp4MessagePackWriter writer) { if (MovieFragmentBox != null) diff --git a/src/JT1078.FMp4/Boxs/MediaHeaderBox.cs b/src/JT1078.FMp4/Boxs/MediaHeaderBox.cs index db67b8f..e0fd9ed 100644 --- a/src/JT1078.FMp4/Boxs/MediaHeaderBox.cs +++ b/src/JT1078.FMp4/Boxs/MediaHeaderBox.cs @@ -16,7 +16,7 @@ namespace JT1078.FMp4 /// /// /// - public MediaHeaderBox(byte version, uint flags=0) : base("mdhd", version, flags) + public MediaHeaderBox(byte version=1, uint flags=0) : base("mdhd", version, flags) { } public ulong CreationTime { get; set; } diff --git a/src/JT1078.FMp4/Boxs/MovieHeaderBox.cs b/src/JT1078.FMp4/Boxs/MovieHeaderBox.cs index e330ccc..7a73c98 100644 --- a/src/JT1078.FMp4/Boxs/MovieHeaderBox.cs +++ b/src/JT1078.FMp4/Boxs/MovieHeaderBox.cs @@ -16,7 +16,7 @@ namespace JT1078.FMp4 /// /// /// - public MovieHeaderBox(byte version, uint flags=0) : base("mvhd", version, flags) + public MovieHeaderBox(byte version=1, uint flags=0) : base("mvhd", version, flags) { } public ulong CreationTime { get; set; } diff --git a/src/JT1078.FMp4/Boxs/SampleTableBox.cs b/src/JT1078.FMp4/Boxs/SampleTableBox.cs index d46a2ab..a130d83 100644 --- a/src/JT1078.FMp4/Boxs/SampleTableBox.cs +++ b/src/JT1078.FMp4/Boxs/SampleTableBox.cs @@ -30,13 +30,14 @@ namespace JT1078.FMp4 /// public CompositionOffsetBox CompositionOffsetBox { get; set; } /// - /// stsc - /// - public SampleToChunkBox SampleToChunkBox { get; set; } - /// /// stsz /// public SampleSizeBox SampleSizeBox { get; set; } + /// + /// stsc + /// + public SampleToChunkBox SampleToChunkBox { get; set; } + //public CompactSampleSizeBox CompactSampleSizeBox { get; set; } /// /// stco diff --git a/src/JT1078.FMp4/FMp4Box.cs b/src/JT1078.FMp4/FMp4Box.cs index b910171..19b86e7 100644 --- a/src/JT1078.FMp4/FMp4Box.cs +++ b/src/JT1078.FMp4/FMp4Box.cs @@ -8,6 +8,15 @@ namespace JT1078.FMp4 { /// /// fmp4 + /// stream data + /// ftyp + /// moov + /// moof 1 + /// mdat 1 + /// ... + /// moof n + /// mdat n + /// mfra /// public class FMp4Box:IFMp4MessagePackFormatter { @@ -27,7 +36,10 @@ namespace JT1078.FMp4 /// mfra /// public MovieFragmentRandomAccessBox MovieFragmentRandomAccessBox { get; set; } - + /// + /// + /// + /// public void ToBuffer(ref FMp4MessagePackWriter writer) { FileTypeBox.ToBuffer(ref writer); diff --git a/src/JT1078.FMp4/JT1078.FMp4.xml b/src/JT1078.FMp4/JT1078.FMp4.xml index b53b130..47b5e3f 100644 --- a/src/JT1078.FMp4/JT1078.FMp4.xml +++ b/src/JT1078.FMp4/JT1078.FMp4.xml @@ -175,6 +175,11 @@ 4位*n + + + + + moof @@ -185,6 +190,12 @@ mdat + + + + + + 填充值 @@ -1045,6 +1056,15 @@ fmp4 + stream data + ftyp + moov + moof 1 + mdat 1 + ... + moof n + mdat n + mfra @@ -1067,6 +1087,12 @@ mfra + + + + + + 日期限制于2000年 @@ -1186,6 +1212,11 @@ + + + + + 盒子大小 diff --git a/src/JT1078.FMp4/Mp4Box.cs b/src/JT1078.FMp4/Mp4Box.cs index 2bedc2d..f85faff 100644 --- a/src/JT1078.FMp4/Mp4Box.cs +++ b/src/JT1078.FMp4/Mp4Box.cs @@ -6,6 +6,9 @@ using System.Text; namespace JT1078.FMp4 { + /// + /// + /// public abstract class Mp4Box { //public const string UUID = "uuid"; diff --git a/src/JT1078.FMp4/Samples/VisualSampleEntry.cs b/src/JT1078.FMp4/Samples/VisualSampleEntry.cs index 0ef485f..ba8b9e1 100644 --- a/src/JT1078.FMp4/Samples/VisualSampleEntry.cs +++ b/src/JT1078.FMp4/Samples/VisualSampleEntry.cs @@ -10,7 +10,7 @@ namespace JT1078.FMp4.Samples /// public abstract class VisualSampleEntry : SampleEntry { - const string COMPRESSORNAME = "jt1078&SmallChi(koike)&TK"; + const string COMPRESSORNAME = "jt1078&SmallChi(Koike)&TK"; /// /// VisualSampleEntry ///