diff --git a/.gitignore b/.gitignore index 47e7f0c..63be598 100644 --- a/.gitignore +++ b/.gitignore @@ -334,3 +334,4 @@ ASALocalRun/ /doc/tools/FlvAnalyzer.exe /doc/tools/EasyICE_2.7.0.2 /doc/tools/mp4parse +/doc/tools/mp4info.exe diff --git a/doc/video/fragmented_demo_trun.txt b/doc/video/fragmented_demo_trun.txt new file mode 100644 index 0000000..4c48896 --- /dev/null +++ b/doc/video/fragmented_demo_trun.txt @@ -0,0 +1,105 @@ +0000bb80000066ee0000a081000017ea + +0000a081000009740000a081000003970000a0820000037b0000a081000031c5 + +0000a08100000bbb0000a081000004230000a0810000052f0000a0820000349b + +0000a08100000e250000a0810000054e0000a08100000a160000a08100000e6b + +0000a08200000cf20000a08100000be20000a081000004640000a08100000df6 + +0000a081000005e80000a082000002a20000a081000002730000a0810000170b + +0000a081000005540000a081000002a10000a0820000036a0000a081000025e5 + +0000a08100000c7b0000a081000003890000a081000006ab0000a0820000310d + +0000a081000015240000a0810000071f0000a08100000b250000a08100003c7b + +0000a08200001b660000a08100000c640000a08100000f3f0000a0810000393b + +0000a081000017eb0000a082000010530000a081000010510000a0810000332e + +0000a081000016ca0000a08100000f520000a08200000e180000a08100002f6b + +0000a081000015f20000a08100000ce00000a08100000bee0000a08200002a12 + +0000a081000010820000a081000009c20000a081000009850000a08100002998 + +0000a082000010d10000a0810000084f0000a081000007870000a0810000284d + +0000a08100000d350000a0820000074f0000a081000007950000a081000026d0 + +0000a08100000dcf0000a081000007800000a0820000079f0000a0810000281d + +0000a08100000e440000a0810000080a0000a081000007ee0000a08200002860 + +0000a08100000fcb0000a081000008030000a081000009bd0000a08100002718 + +0000a08200000f7e0000a081000008a70000a081000008fc0000a081000027bc + +0000a08100000f200000a082000008d30000a081000008ef0000a081000027a6 + +0000a08100000eb60000a0810000093f0000a082000008ce0000a0810000289e + +0000a081000010c30000a08100000a280000a08100000a040000a082000026c7 + +0000a0810000105b0000a081000009150000a0810000088c0000a0810000270e + +0000a08200000ec30000a081000007db0000a081000007480000a08100002278 + +0000a08100000c270000a082000007c50000a081000006990000a08100001fbc + +0000a08100000a650000a0810000058d0000a0820000038f0000a08100002306 + +0000a08100000cb60000a0810000043a0000a081000008590000a08200002469 + +0000a0810000108a0000a081000008c90000a081000008b10000a0810000267b + +0000a082000011d40000a081000009430000a081000009bd0000a08100002664 + +0000a08100000e7e0000a082000009db0000a08100002ac40000a081000012e1 + +0000a08100000abf0000a08100000a320000a082000024fc0000a081000009a8 + +0000a0810000210d0000a0810000260b0000a08100000a790000a0820000243d + +0000a08100000b970000a081000024570000a08100000b3b0000a08100002197 + +0000a08200000a0f0000a08100001e270000a081000025c70000a08100000aef + +0000a08100001bd50000a08200001d9f0000a081000021060000a0810000208c + +0000a0810000098d0000a081000022060000a08200000e260000a08100000993 + +0000a0810000237d0000a08100000e8e0000a081000008e60000a082000007db + +0000a081000020950000a08100000c970000a081000007460000a0810000050f + +0000a08200001ddd0000a081000009390000a0810000044b0000a08100000451 + +0000a08100001b1c0000a0820000088a0000a081000003b40000a08100000384 + +0000a0810000193c0000a081000007940000a082000004670000a0810000039b + +0000a08100001a6f0000a081000008290000a081000004370000a08200000466 + +0000a08100001a8f0000a08100000aac0000a0810000042d0000a08100000438 + +0000a08200001a290000a081000009ce0000a081000004460000a0810000043a + +0000a08100001a8d0000a08200000b570000a081000004770000a08100000523 + +0000a08100001cdb0000a0810000087a0000a082000004b70000a08100000499 + +0000a08100001c750000a0810000097f0000a081000005510000a082000004f3 + +0000a08100001f0f0000a081000009790000a0810000054b0000a0810000053d + +0000a082000021e00000a08100000cc00000a081000005840000a08100000561 + +0000a081000021a20000a08200000aa60000a081000004ef0000a081000005c9 + +0000a08100001f840000a08100000d7a0000a08200000a390000a0810000064f + +0000a081000020d30000a08100000b0a \ No newline at end of file diff --git a/src/JT1078.FMp4.Test/FMP4/placeholder.txt b/src/JT1078.FMp4.Test/FMP4/placeholder.txt new file mode 100644 index 0000000..c3833e4 --- /dev/null +++ b/src/JT1078.FMp4.Test/FMP4/placeholder.txt @@ -0,0 +1 @@ +placeholder \ No newline at end of file diff --git a/src/JT1078.FMp4.Test/FMp4Box_Test.cs b/src/JT1078.FMp4.Test/FMp4Box_Test.cs index 4c1f364..dfd37b9 100644 --- a/src/JT1078.FMp4.Test/FMp4Box_Test.cs +++ b/src/JT1078.FMp4.Test/FMp4Box_Test.cs @@ -272,7 +272,25 @@ namespace JT1078.FMp4.Test //moof->tfdt movieFragmentBox.TrackFragmentBox.TrackFragmentBaseMediaDecodeTimeBox = new TrackFragmentBaseMediaDecodeTimeBox(); //todo:moof->trun + //000006987472756E00000305000000D0000006F802000000 + //00 00 06 98 + //74 72 75 6E + //00 + //00 03 05 + //00 00 00 D0 SampleCount + //00 00 06 F8 DataOffset + //02 00 00 00 FirstSampleFlags + //fragmented_demo_trun.txt TrackRunInfos movieFragmentBox.TrackFragmentBox.TrackRunBox = new TrackRunBox(0, 0x00000305); + movieFragmentBox.TrackFragmentBox.TrackRunBox.SampleCount = 0x000000D0; + movieFragmentBox.TrackFragmentBox.TrackRunBox.DataOffset = 0x000006F8; + movieFragmentBox.TrackFragmentBox.TrackRunBox.FirstSampleFlags = 0x02000000; + movieFragmentBox.TrackFragmentBox.TrackRunBox.TrackRunInfos = new List(); + var lines = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "FMP4", "fragmented_demo_trun.txt")); + var buffers = lines.Where(w => !string.IsNullOrEmpty(w)).Select(s => s.ToHexBytes()).ToList(); + List data = new List(); + //SampleDuration + //SampleSize } /// /// 使用doc/video/fragmented_demo.mp4 @@ -281,7 +299,7 @@ namespace JT1078.FMp4.Test public void mdat_test() { MediaDataBox mediaDataBox = new MediaDataBox(); - var lines = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "fragmented_demo_mdat.txt")); + var lines = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "FMP4", "fragmented_demo_mdat.txt")); var buffers = lines.Where(w => !string.IsNullOrEmpty(w)).Select(s => s.ToHexBytes()).ToList(); List data = new List(); foreach (var buffer in buffers) diff --git a/src/JT1078.FMp4.Test/JT1078.FMp4.Test.csproj b/src/JT1078.FMp4.Test/JT1078.FMp4.Test.csproj index 19109a0..1937a79 100644 --- a/src/JT1078.FMp4.Test/JT1078.FMp4.Test.csproj +++ b/src/JT1078.FMp4.Test/JT1078.FMp4.Test.csproj @@ -23,13 +23,18 @@ - - + + Always + + Always - + + Always + + Always diff --git a/src/JT1078.FMp4/Boxs/TrackHeaderBox.cs b/src/JT1078.FMp4/Boxs/TrackHeaderBox.cs index 42639e7..05e494a 100644 --- a/src/JT1078.FMp4/Boxs/TrackHeaderBox.cs +++ b/src/JT1078.FMp4/Boxs/TrackHeaderBox.cs @@ -18,7 +18,18 @@ namespace JT1078.FMp4 /// public TrackHeaderBox(byte version, uint flags) : base("tkhd", version, flags) { + } + + /// + /// tkhd + /// + /// + public TrackHeaderBox(byte version) : base("tkhd", version, (FMp4Constants.TKHD_FLAG_ENABLED | FMp4Constants.TKHD_FLAG_IN_MOVIE | FMp4Constants.TKHD_FLAG_IN_PREVIEW)) + { + + } + public ulong CreationTime { get; set; } public ulong ModificationTime { get; set; } public uint TrackID { get; set; } diff --git a/src/JT1078.FMp4/Boxs/TrackRunBox.cs b/src/JT1078.FMp4/Boxs/TrackRunBox.cs index 5ec6575..6d1c0d7 100644 --- a/src/JT1078.FMp4/Boxs/TrackRunBox.cs +++ b/src/JT1078.FMp4/Boxs/TrackRunBox.cs @@ -16,7 +16,7 @@ namespace JT1078.FMp4 /// /// /// - public TrackRunBox(byte version, uint flags) : base("trun", version, flags) + public TrackRunBox(byte version=0, uint flags= 0x000f01) : base("trun", version, flags) { } @@ -39,7 +39,52 @@ namespace JT1078.FMp4 { Start(ref writer); WriterFullBoxToBuffer(ref writer); - writer.WriteUInt32(SampleCount); + bool tmpFlag = TrackRunInfos != null && TrackRunInfos.Count > 0; + if (tmpFlag) + { + writer.WriteUInt32((uint)TrackRunInfos.Count); + } + else + { + writer.WriteUInt32(0); + } + if((Flags & FMp4Constants.TRUN_FLAG_DATA_OFFSET_PRESENT) > 0) + { + writer.WriteInt32(DataOffset); + } + if ((Flags & FMp4Constants.TRUN_FLAG_FIRST_SAMPLE_FLAGS_PRESENT) > 0) + { + writer.WriteUInt32(FirstSampleFlags); + } + if (tmpFlag) + { + foreach(var trun in TrackRunInfos) + { + if ((Flags & FMp4Constants.TRUN_FLAG_SAMPLE_DURATION_PRESENT) > 0) + { + writer.WriteUInt32(trun.SampleDuration); + } + if ((Flags & FMp4Constants.TRUN_FLAG_SAMPLE_SIZE_PRESENT) > 0) + { + writer.WriteUInt32(trun.SampleSize); + } + if ((Flags & FMp4Constants.TRUN_FLAG_SAMPLE_FLAGS_PRESENT) > 0) + { + writer.WriteUInt32(trun.SampleFlags); + } + if ((Flags & FMp4Constants.TRUN_FLAG_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT) > 0) + { + if (Version == 0) + { + writer.WriteUInt32(trun.SampleCompositionTimeOffset); + } + else + { + writer.WriteInt32(trun.SignedSampleCompositionTimeOffset); + } + } + } + } End(ref writer); } diff --git a/src/JT1078.FMp4/FMp4Constants.cs b/src/JT1078.FMp4/FMp4Constants.cs index dfb8eea..a3dc2ea 100644 --- a/src/JT1078.FMp4/FMp4Constants.cs +++ b/src/JT1078.FMp4/FMp4Constants.cs @@ -18,55 +18,67 @@ namespace JT1078.FMp4 /// public static readonly DateTime UTCBaseTime = new DateTime(1904, 1, 1); /// - /// + /// TKHD_FLAG_ENABLED + /// + public const int TKHD_FLAG_ENABLED = 0x000001; + /// + /// TKHD_FLAG_IN_MOVIE + /// + public const int TKHD_FLAG_IN_MOVIE = 0x000002; + /// + /// TKHD_FLAG_IN_PREVIEW + /// + public const int TKHD_FLAG_IN_PREVIEW = 0x000004; + /// + /// TFHD_FLAG_BASE_DATA_OFFSET /// public const int TFHD_FLAG_BASE_DATA_OFFSET = 0x00000001; /// - /// + /// TFHD_FLAG_SAMPLE_DESC /// public const int TFHD_FLAG_SAMPLE_DESCRIPTION_INDEX = 0x00000002; /// - /// + /// TFHD_FLAG_SAMPLE_DUR /// public const int TFHD_FLAG_DEFAULT_DURATION = 0x00000008; /// - /// + /// TFHD_FLAG_SAMPLE_SIZE /// public const int TFHD_FLAG_DEFAULT_SIZE = 0x00000010; /// - /// + /// TFHD_FLAG_SAMPLE_FLAGS /// public const int TFHD_FLAG_DEFAULT_FLAGS = 0x00000020; /// - /// + /// TFHD_FLAG_DUR_EMPTY /// public const int TFHD_FLAG_DURATION_IS_EMPTY = 0x00010000; /// - /// + /// TFHD_FLAG_DEFAULT_BASE_IS_MOOF /// public const int TFHD_FLAG_DEFAULT_BASE_IS_MOOF = 0x00020000; /// - /// + /// TRUN_FLAGS_DATA_OFFSET /// public const int TRUN_FLAG_DATA_OFFSET_PRESENT = 0x0001; /// - /// + /// TRUN_FLAGS_FIRST_FLAG /// public const int TRUN_FLAG_FIRST_SAMPLE_FLAGS_PRESENT = 0x0004; /// - /// + /// TRUN_FLAGS_DURATION /// public const int TRUN_FLAG_SAMPLE_DURATION_PRESENT = 0x0100; /// - /// + /// TRUN_FLAGS_SIZE /// public const int TRUN_FLAG_SAMPLE_SIZE_PRESENT = 0x0200; /// - /// + /// TRUN_FLAGS_FLAGS /// public const int TRUN_FLAG_SAMPLE_FLAGS_PRESENT = 0x0400; /// - /// + /// TRUN_FLAGS_CTS_OFFSET /// public const int TRUN_FLAG_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT = 0x0800; } diff --git a/src/JT1078.FMp4/JT1078.FMp4.xml b/src/JT1078.FMp4/JT1078.FMp4.xml index 413ac6c..b53b130 100644 --- a/src/JT1078.FMp4/JT1078.FMp4.xml +++ b/src/JT1078.FMp4/JT1078.FMp4.xml @@ -932,6 +932,12 @@ + + + tkhd + + + trun @@ -1071,69 +1077,84 @@ + + + TKHD_FLAG_ENABLED + + + + + TKHD_FLAG_IN_MOVIE + + + + + TKHD_FLAG_IN_PREVIEW + + - + TFHD_FLAG_BASE_DATA_OFFSET - + TFHD_FLAG_SAMPLE_DESC - + TFHD_FLAG_SAMPLE_DUR - + TFHD_FLAG_SAMPLE_SIZE - + TFHD_FLAG_SAMPLE_FLAGS - + TFHD_FLAG_DUR_EMPTY - + TFHD_FLAG_DEFAULT_BASE_IS_MOOF - + TRUN_FLAGS_DATA_OFFSET - + TRUN_FLAGS_FIRST_FLAG - + TRUN_FLAGS_DURATION - + TRUN_FLAGS_SIZE - + TRUN_FLAGS_FLAGS - + TRUN_FLAGS_CTS_OFFSET