diff --git a/README.md b/README.md index 3f06844..3834581 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,8 @@ 2. [企业平台到政府监管的通信也就是JT809](#809Ext) 3. [设备终端上传的实时音视频流数据也就是视频服务器](#1078) 3.1 [将1078的数据(h264)编码成FLV](#1078flv) -3.2 [将1078的数据(h264)编码成HLS](#1078hls) +3.2 [将1078的数据(h264)编码成HLS](#1078hls) +3.3 [将1078的数据(h264)编码成FMp4](#1078fmp4) [![MIT Licence](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/SmallChi/JT1078/blob/master/LICENSE)[![Github Build status](https://github.com/SmallChi/JT1078/workflows/.NET%20Core/badge.svg)]() diff --git a/doc/fmp4/ISO Language Codes.txt b/doc/fmp4/ISO Language Codes.txt new file mode 100644 index 0000000..623a403 Binary files /dev/null and b/doc/fmp4/ISO Language Codes.txt differ diff --git a/doc/fmp4/ISO_IEC_14496-12_2012.pdf b/doc/fmp4/ISO_IEC_14496-12_2012.pdf new file mode 100644 index 0000000..c3ac62c Binary files /dev/null and b/doc/fmp4/ISO_IEC_14496-12_2012.pdf differ diff --git a/doc/fmp4/fmp4info.txt b/doc/fmp4/fmp4info.txt new file mode 100644 index 0000000..f8d9647 --- /dev/null +++ b/doc/fmp4/fmp4info.txt @@ -0,0 +1,19 @@ +ref https://stackoverflow.com/questions/53992918/about-fmp4-encoding-how-to-fill-the-mdat-box-wit-h264-frame?r=SearchResults + +H.264 can be in different stream formats. One is called "Annex B" the other one is MP4. In "Annex B" your NAL units are prefix with start codes 00 00 00 01 or 00 00 01. In MP4 your NAL units are prefixed with the size in bytes. + +I assume your encoder emits "Annex B". + + Remove the start code (00) 00 00 01 + + Prefix your NAL units with the size (typically 4 bytes) + + Filter out AUD/SPS/PPS NAL units from your stream + + Write you converted NAL units into the MDAT box + + Create an AVC Configuration Box ('avcC') based on your SPS, PPS and the length size + + Store your avcC box in moov->trak->mdia->minf->stbl->avc1->avcC + + While you are writing your samples into mdat - keep track of sizes, offsets and frame types to create the correct stts, stss, stsc, stsz and stco boxes. \ No newline at end of file diff --git a/doc/fmp4/img/fmp4_1.png b/doc/fmp4/img/fmp4_1.png new file mode 100644 index 0000000..9b969ff Binary files /dev/null and b/doc/fmp4/img/fmp4_1.png differ diff --git a/doc/fmp4/img/fmp4_2.png b/doc/fmp4/img/fmp4_2.png new file mode 100644 index 0000000..4dcac99 Binary files /dev/null and b/doc/fmp4/img/fmp4_2.png differ diff --git a/doc/fmp4/img/parser_pic.png b/doc/fmp4/img/parser_pic.png new file mode 100644 index 0000000..75f4e1e Binary files /dev/null and b/doc/fmp4/img/parser_pic.png differ diff --git a/doc/fmp4/img/structure_model.png b/doc/fmp4/img/structure_model.png new file mode 100644 index 0000000..9149f9e Binary files /dev/null and b/doc/fmp4/img/structure_model.png differ diff --git a/doc/fmp4/parser_manual.txt b/doc/fmp4/parser_manual.txt new file mode 100644 index 0000000..43b1a6b Binary files /dev/null and b/doc/fmp4/parser_manual.txt differ diff --git a/doc/fmp4/parser_manual_fmp4.txt b/doc/fmp4/parser_manual_fmp4.txt new file mode 100644 index 0000000..a9fa9fc Binary files /dev/null and b/doc/fmp4/parser_manual_fmp4.txt differ diff --git a/doc/tools/mp4info.exe b/doc/tools/mp4info.exe new file mode 100644 index 0000000..96da2c0 Binary files /dev/null and b/doc/tools/mp4info.exe differ diff --git a/src/JT1078.FMp4.Test/JT1078.FMp4.Test.csproj b/src/JT1078.FMp4.Test/JT1078.FMp4.Test.csproj new file mode 100644 index 0000000..dadd617 --- /dev/null +++ b/src/JT1078.FMp4.Test/JT1078.FMp4.Test.csproj @@ -0,0 +1,20 @@ + + + + netcoreapp3.1 + + false + + + + + + + + + + + + + + diff --git a/src/JT1078.FMp4.Test/UnitTest1.cs b/src/JT1078.FMp4.Test/UnitTest1.cs new file mode 100644 index 0000000..cea9638 --- /dev/null +++ b/src/JT1078.FMp4.Test/UnitTest1.cs @@ -0,0 +1,14 @@ +using System; +using Xunit; + +namespace JT1078.FMp4.Test +{ + public class UnitTest1 + { + [Fact] + public void Test1() + { + + } + } +} diff --git a/src/JT1078.FMp4/Boxs/AVCConfigurationBox.cs b/src/JT1078.FMp4/Boxs/AVCConfigurationBox.cs new file mode 100644 index 0000000..a76e449 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/AVCConfigurationBox.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class AVCConfigurationBox : Mp4Box + { + public AVCConfigurationBox() : base("avcC") + { + } + public AVCDecoderConfigurationRecord AVCDecoderConfigurationRecord { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/AVCDecoderConfigurationRecord.cs b/src/JT1078.FMp4/Boxs/AVCDecoderConfigurationRecord.cs new file mode 100644 index 0000000..daa1036 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/AVCDecoderConfigurationRecord.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + //AVCDecoderConfigurationRecord 结构的定义: + //aligned(8) class AVCDecoderConfigurationRecord + //{ + //unsigned int (8) configurationVersion = 1; + //unsigned int (8) AVCProfileIndication; + //unsigned int (8) profile_compatibility; + //unsigned int (8) AVCLevelIndication; + //bit(6) reserved = ‘111111’b; + //unsigned int (2) lengthSizeMinusOne; + //bit(3) reserved = ‘111’b; + //unsigned int (5) numOfSequenceParameterSets; + //for (i=0; i + /// + /// + public class AVCDecoderConfigurationRecord + { + public byte ConfigurationVersion { get; set; } = 1; + public byte AVCProfileIndication { get; set; } + public byte ProfileCompatibility { get; set; } + public byte AVCLevelIndication { get; set; } + public int LengthSizeMinusOne { get; set; } + public int NumOfSequenceParameterSets { get; set; } + public List SPS { get; set; } + public byte[] SPSBuffer { get; set; } + public byte NumOfPictureParameterSets { get; set; } = 1; + public List PPS { get; set; } + public byte[] PPSBuffer { get; set; } + + #region Just for non-spec-conform encoders ref:org.JT1078.FMp4.boxes.iso14496.part15.AvcDecoderConfigurationRecord + public const int LengthSizeMinusOnePaddingBits = 63; + public const int NumberOfSequenceParameterSetsPaddingBits = 7; + public const int ChromaFormatPaddingBits = 31; + public const int BitDepthLumaMinus8PaddingBits = 31; + public const int BitDepthChromaMinus8PaddingBits = 31; + #endregion + + public struct SPSInfo + { + public ushort SequenceParameterSetLength { get; set; } + public byte[] SequenceParameterSetNALUnit { get; set; } + } + + public struct PPSInfo + { + public ushort PictureParameterSetLength { get; set; } + public byte[] PictureParameterSetNALUnit { get; set; } + } + } +} diff --git a/src/JT1078.FMp4/Boxs/ChunkLargeOffsetBox.cs b/src/JT1078.FMp4/Boxs/ChunkLargeOffsetBox.cs new file mode 100644 index 0000000..7c63b0a --- /dev/null +++ b/src/JT1078.FMp4/Boxs/ChunkLargeOffsetBox.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class ChunkLargeOffsetBox : FullBox + { + public ChunkLargeOffsetBox(byte version=0, uint flags=0) : base("co64", version, flags) + { + } + public uint EntryCount { get; set; } + /// + /// length:EntryCount + /// + public List ChunkOffset { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/ChunkOffsetBox.cs b/src/JT1078.FMp4/Boxs/ChunkOffsetBox.cs new file mode 100644 index 0000000..ea8f029 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/ChunkOffsetBox.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class ChunkOffsetBox : FullBox + { + public ChunkOffsetBox( byte version=0, uint flags=0) : base("stco", version, flags) + { + } + + public uint EntryCount { get; set; } + /// + /// length:EntryCount + /// + public List ChunkOffset { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/CleanApertureBox.cs b/src/JT1078.FMp4/Boxs/CleanApertureBox.cs new file mode 100644 index 0000000..cf0f4f0 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/CleanApertureBox.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class CleanApertureBox : Mp4Box + { + public CleanApertureBox() : base("clap") + { + } + + public uint CleanApertureWidthN { get; set; } + public uint CleanApertureWidthD { get; set; } + public uint CleanApertureHeightN { get; set; } + public uint CleanApertureHeightD { get; set; } + public uint HorizOffN { get; set; } + public uint HorizOffD { get; set; } + public uint VertOffN { get; set; } + public uint VertOffD { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/ColourInformationBox.cs b/src/JT1078.FMp4/Boxs/ColourInformationBox.cs new file mode 100644 index 0000000..3507f9c --- /dev/null +++ b/src/JT1078.FMp4/Boxs/ColourInformationBox.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class ColourInformationBox : Mp4Box + { + public ColourInformationBox() : base("colr") + { + } + public string ColourType { get; set; } + public ushort ColourPrimaries { get; set; } + public ushort TransferCharacteristics { get; set; } + public ushort MatrixCoefficients { get; set; } + public bool FullRangeFlag { get; set; } + public byte Reserved { get; set; } + #warning ICC_profile????? + public byte [] ICCProfile { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/CompactSampleSizeBox.cs b/src/JT1078.FMp4/Boxs/CompactSampleSizeBox.cs new file mode 100644 index 0000000..41287e5 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/CompactSampleSizeBox.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class CompactSampleSizeBox : FullBox + { + public CompactSampleSizeBox(byte version=0, uint flags=0) : base("stz2", version, flags) + { + } + + public byte[] Reserved { get; set; } = new byte[3]; + /// + /// 4, 8 or 16 + /// + public byte FieldSize { get; set; } + + public uint SampleCount { get; set; } + + /// + /// length:SampleCount + /// DepOn:field_size=>DataType + /// + public List EntrySize { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/CompositionOffsetBox.cs b/src/JT1078.FMp4/Boxs/CompositionOffsetBox.cs new file mode 100644 index 0000000..82a94ab --- /dev/null +++ b/src/JT1078.FMp4/Boxs/CompositionOffsetBox.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class CompositionOffsetBox : FullBox + { + public CompositionOffsetBox(byte version=0, uint flags=0) : base("ctts", version, flags) + { + } + public uint EntryCount { get; set; } + + public List CompositionOffsetInfos { get; set; } + + public class CompositionOffsetInfo + { + public uint SampleCount { get; set; } + public uint SampleOffset { get; set; } + /// + /// version == 1 + /// + public int SignedSampleOffset { get; set; } + } + } +} diff --git a/src/JT1078.FMp4/Boxs/CompositionToDecodeBox.cs b/src/JT1078.FMp4/Boxs/CompositionToDecodeBox.cs new file mode 100644 index 0000000..a1d516b --- /dev/null +++ b/src/JT1078.FMp4/Boxs/CompositionToDecodeBox.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class CompositionToDecodeBox : FullBox + { + public CompositionToDecodeBox(byte version=0, uint flags=0) : base("cslg", version, flags) + { + } + + public int CompositionToDTSShift { get; set; } + public int LeastDecodeToDisplayDelta { get; set; } + public int GreatestDecodeToDisplayDelta { get; set; } + public int CompositionStartTime { get; set; } + public int CompositionEndTime { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/CopyrightBox.cs b/src/JT1078.FMp4/Boxs/CopyrightBox.cs new file mode 100644 index 0000000..86fc151 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/CopyrightBox.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class CopyrightBox : FullBox + { + public CopyrightBox(byte version=0, uint flags=0) : base("cprt", version, flags) + { + } + /// + /// 16-1 + /// + public bool Pad { get; set; } + /// + /// 16-15 + /// ISO-639-2/T language code + /// + public byte Language { get; set; } + + public string Notice { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/DataEntryBox.cs b/src/JT1078.FMp4/Boxs/DataEntryBox.cs new file mode 100644 index 0000000..325f6dc --- /dev/null +++ b/src/JT1078.FMp4/Boxs/DataEntryBox.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public abstract class DataEntryBox : FullBox + { + public DataEntryBox(string boxType, byte version, uint flags) : base(boxType, version, flags) + { + } + } +} diff --git a/src/JT1078.FMp4/Boxs/DataEntryUrlBox.cs b/src/JT1078.FMp4/Boxs/DataEntryUrlBox.cs new file mode 100644 index 0000000..bcf2754 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/DataEntryUrlBox.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class DataEntryUrlBox : DataEntryBox + { + public DataEntryUrlBox(byte version, uint flags) : base("url ", version, flags) + { + } + + public DataEntryUrlBox(uint flags) : this(0, flags) + { + } + + public string Location { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/DataEntryUrnBox.cs b/src/JT1078.FMp4/Boxs/DataEntryUrnBox.cs new file mode 100644 index 0000000..340378a --- /dev/null +++ b/src/JT1078.FMp4/Boxs/DataEntryUrnBox.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class DataEntryUrnBox : DataEntryBox + { + public DataEntryUrnBox(byte version, uint flags) : base("urn ", version, flags) + { + } + public DataEntryUrnBox(uint flags) : this(0, flags) + { + } + + public string Name { get; set; } + public string Location { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/DataInformationBox.cs b/src/JT1078.FMp4/Boxs/DataInformationBox.cs new file mode 100644 index 0000000..22a58e8 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/DataInformationBox.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class DataInformationBox : Mp4Box + { + public DataInformationBox() : base("dinf") + { + } + public DataReferenceBox DataReferenceBox { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/DataReferenceBox.cs b/src/JT1078.FMp4/Boxs/DataReferenceBox.cs new file mode 100644 index 0000000..3f41d1c --- /dev/null +++ b/src/JT1078.FMp4/Boxs/DataReferenceBox.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class DataReferenceBox : FullBox + { + public DataReferenceBox(byte version=0, uint flags=0) : base("dref", version, flags) + { + } + + public uint EntryCount { get; set; } + + /// + /// length:EntryCount + /// + public List DataEntryBoxes { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/DegradationPriorityBox.cs b/src/JT1078.FMp4/Boxs/DegradationPriorityBox.cs new file mode 100644 index 0000000..4510ea2 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/DegradationPriorityBox.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class DegradationPriorityBox : FullBox + { + public DegradationPriorityBox(byte version=0, uint flags=0) : base("stdp", version, flags) + { + } + /// + /// sample_count is taken from the sample_count in the Sample Size Box ('stsz'). + /// + public List Priorities { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/EditBox.cs b/src/JT1078.FMp4/Boxs/EditBox.cs new file mode 100644 index 0000000..d5e3203 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/EditBox.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class EditBox : Mp4Box + { + public EditBox() : base("edts") + { + } + + public List EditListBox { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/EditListBox.cs b/src/JT1078.FMp4/Boxs/EditListBox.cs new file mode 100644 index 0000000..80d070e --- /dev/null +++ b/src/JT1078.FMp4/Boxs/EditListBox.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class EditListBox : FullBox + { + public EditListBox(byte version, uint flags=0) : base("elst", version, flags) + { + } + public uint EntryCount { get; set; } + + public ulong SegmentDurationLarge { get; set; } + public long MediaTimeLarge { get; set; } + public uint SegmentDuration { get; set; } + public int MediaTime { get; set; } + public short MediaRateInteger { get; set; } + public short MediaRateFraction { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/FDItemInformationBox.cs b/src/JT1078.FMp4/Boxs/FDItemInformationBox.cs new file mode 100644 index 0000000..bb6c9f4 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/FDItemInformationBox.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class FDItemInformationBox : FullBox + { + public FDItemInformationBox(byte version, uint flags) : base("fiin", version, flags) + { + } + + public ushort EntryCount { get; set; } + /// + /// length:EntryCount + /// + public List PartitionEntries { get; set; } + public FDSessionGroupBox SessionInfo { get; set; } + public GroupIdToNameBox GroupIdToName { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/FDSessionGroupBox.cs b/src/JT1078.FMp4/Boxs/FDSessionGroupBox.cs new file mode 100644 index 0000000..c1b4c93 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/FDSessionGroupBox.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class FDSessionGroupBox : Mp4Box + { + public FDSessionGroupBox() : base("segr") + { + } + + public ushort NumSessionGroups { get; set; } + + public class FDSessionGroupInfo + { + public byte EntryCount { get; set; } + /// + /// length:EntryCount + /// + public List GroupIDs { get; set; } + public ushort NumChannelsInSessionGroup { get; set; } + /// + /// length:NumChannelsInSessionGroup + /// + public List HintTrackId{ get; set; } + } + } +} diff --git a/src/JT1078.FMp4/Boxs/FECReservoirBox.cs b/src/JT1078.FMp4/Boxs/FECReservoirBox.cs new file mode 100644 index 0000000..380d20e --- /dev/null +++ b/src/JT1078.FMp4/Boxs/FECReservoirBox.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class FECReservoirBox : FullBox + { + public FECReservoirBox(byte version=0, uint flags=0) : base("fecr", version, flags) + { + } + + public ushort EntryCount { get; set; } + + public List FECReservoirInfos { get; set; } + + public class FECReservoirInfo + { + public ushort ItemID { get; set; } + public uint SymbolCount { get; set; } + } + } +} diff --git a/src/JT1078.FMp4/Boxs/FilePartitionBox.cs b/src/JT1078.FMp4/Boxs/FilePartitionBox.cs new file mode 100644 index 0000000..9ee3068 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/FilePartitionBox.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class FilePartitionBox : FullBox + { + public FilePartitionBox(byte version=0, uint flags=0) : base("fpar", version, flags) + { + } + public ushort ItemID { get; set; } + public ushort PacketPayloadSize { get; set; } + public byte Reserved { get; set; } + public byte FECEncodingID { get; set; } + public ushort FECInstanceID { get; set; } + public ushort MaxSourceBlockLength { get; set; } + public ushort EncodingSymbolLength { get; set; } + public ushort MaxNumberOfEncodingSymbols { get; set; } + /// + /// 以null结尾 + /// + public string SchemeSpecificInfo { get; set; } + public ushort EntryCount { get; set; } + public List FilePartitionInfos { get; set; } + public class FilePartitionInfo + { + public ushort BlockCount { get; set; } + public ushort BlockSize { get; set; } + } + } +} diff --git a/src/JT1078.FMp4/Boxs/FileReservoirBox.cs b/src/JT1078.FMp4/Boxs/FileReservoirBox.cs new file mode 100644 index 0000000..9465bdf --- /dev/null +++ b/src/JT1078.FMp4/Boxs/FileReservoirBox.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class FileReservoirBox : FullBox + { + public FileReservoirBox(byte version=0, uint flags=0) : base("fire", version, flags) + { + } + public ushort EntryCount { get; set; } + + public List FileReservoirInfos { get; set; } + + public class FileReservoirInfo + { + public ushort ItemID { get; set; } + public uint SymbolCount { get; set; } + } + } +} diff --git a/src/JT1078.FMp4/Boxs/FileTypeBox.cs b/src/JT1078.FMp4/Boxs/FileTypeBox.cs new file mode 100644 index 0000000..84b5d52 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/FileTypeBox.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; +using System.Text; + +namespace JT1078.FMp4 +{ + /// + /// ftyp 盒子相当于就是该 mp4 的纲领性说明。即,告诉解码器它的基本解码版本,兼容格式。简而言之,就是用来告诉客户端,该 MP4 的使用的解码标准。通常,ftyp 都是放在 MP4 的开头。 + /// + public class FileTypeBox : Mp4Box + { + public FileTypeBox() : base("ftyp") + { + } + /// + ///因为兼容性一般可以分为推荐兼容性和默认兼容性。这里 major_brand 就相当于是推荐兼容性。通常,在 Web 中解码,一般而言都是使用 isom 这个万金油即可。如果是需要特定的格式,可以自行定义。 + /// 4位 + /// + public string MajorBrand { get; set; } + /// + /// 最低兼容版本 + /// 4位 + /// + public uint MinorVersion { get; set; } + /// + /// 和MajorBrand类似,通常是针对 MP4 中包含的额外格式,比如,AVC,AAC 等相当于的音视频解码格式。 + /// 4位*n + /// + public List CompatibleBrands { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/FragmentBox.cs b/src/JT1078.FMp4/Boxs/FragmentBox.cs new file mode 100644 index 0000000..d3c512a --- /dev/null +++ b/src/JT1078.FMp4/Boxs/FragmentBox.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class FragmentBox + { + public MovieFragmentBox MovieFragmentBox { get; set; } + public MediaDataBox MediaDataBox { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/FreeBox.cs b/src/JT1078.FMp4/Boxs/FreeBox.cs new file mode 100644 index 0000000..0ca14ac --- /dev/null +++ b/src/JT1078.FMp4/Boxs/FreeBox.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class FreeBox : FreeSpaceBox + { + public FreeBox() : base("free") + { + } + } +} diff --git a/src/JT1078.FMp4/Boxs/FreeSpaceBox.cs b/src/JT1078.FMp4/Boxs/FreeSpaceBox.cs new file mode 100644 index 0000000..11960c6 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/FreeSpaceBox.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public abstract class FreeSpaceBox: Mp4Box + { + public FreeSpaceBox(string boxType) : base(boxType) + { + } + /// + /// 填充值 + /// + public byte FillValue { get; set; } + /// + /// 填充数量 + /// + public int FillCount { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/GroupIdToNameBox.cs b/src/JT1078.FMp4/Boxs/GroupIdToNameBox.cs new file mode 100644 index 0000000..3f49b6e --- /dev/null +++ b/src/JT1078.FMp4/Boxs/GroupIdToNameBox.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class GroupIdToNameBox : FullBox + { + public GroupIdToNameBox(byte version=0, uint flags=0) : base("gitn", version, flags) + { + } + + public ushort EntryCount { get; set; } + + public List GroupIdToNameInfos { get; set; } + + public class GroupIdToNameInfo + { + public uint GroupID { get; set; } + + public string GroupName { get; set; } + } + } +} diff --git a/src/JT1078.FMp4/Boxs/HandlerBox.cs b/src/JT1078.FMp4/Boxs/HandlerBox.cs new file mode 100644 index 0000000..5f39a8e --- /dev/null +++ b/src/JT1078.FMp4/Boxs/HandlerBox.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class HandlerBox : FullBox + { + public HandlerBox(byte version=0, uint flags=0) : base("hdlr", version, flags) + { + } + + public uint PreDefined { get; set; } + public string HandlerType { get; set; } + public uint[] Reserved { get; set; } = new uint[3]; + public string Name { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/HintMediaHeaderBox.cs b/src/JT1078.FMp4/Boxs/HintMediaHeaderBox.cs new file mode 100644 index 0000000..4259366 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/HintMediaHeaderBox.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class HintMediaHeaderBox : FullBox + { + public HintMediaHeaderBox(byte version=0, uint flags=0) : base("hmhd", version, flags) + { + } + + public ushort MaxPDUSize { get; set; } + public ushort AvgPDUSize { get; set; } + public ushort MaxBitRate { get; set; } + public ushort AvgBitRate { get; set; } + public ushort Reserved { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/ItemLocationBox.cs b/src/JT1078.FMp4/Boxs/ItemLocationBox.cs new file mode 100644 index 0000000..138f8d4 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/ItemLocationBox.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class ItemLocationBox : FullBox + { + public ItemLocationBox(byte version, uint flags=0) : base("iloc", version, flags) + { + } + /// + /// 0, 4, 8 + /// + public byte OffsetSize { get; set; } + /// + /// 0, 4, 8 + /// + public byte LengthSize { get; set; } + /// + /// 0, 4, 8 + /// + public byte BaseOffsetSize { get; set; } + /// + /// version == 1 + /// + public byte IndexSize{ get; set; } + public byte Reserved { get; set; } + public ushort ItemCount { get; set; } + public List ItemLocations { get; set; } + public class ItemLocation + { + public ushort ItemID { get; set; } + /// + /// if (version == 1) 16-12 + /// + public byte Reserved { get; set; } = 12; + /// + /// if (version == 1) 16-4 + /// + public byte ConstructionMethod { get; set; } + public ushort DataReferenceIndex { get; set; } + public ulong BaseOffset { get; set; } + public ushort ExtentCount { get; set; } + public List ItemLocationExtentInfos { get; set; } + public class ItemLocationExtentInfo + { + /// + /// if ((version == 1) && (index_size > 0)) + /// + public ulong ExtentIndex { get; set; } + public ulong ExtentOffset { get; set; } + public ulong ExtentLength { get; set; } + } + } + } +} diff --git a/src/JT1078.FMp4/Boxs/ItemProtectionBox.cs b/src/JT1078.FMp4/Boxs/ItemProtectionBox.cs new file mode 100644 index 0000000..ce6925f --- /dev/null +++ b/src/JT1078.FMp4/Boxs/ItemProtectionBox.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class ItemProtectionBox : FullBox + { + public ItemProtectionBox(byte version=0, uint flags=0) : base("ipro", version, flags) + { + } + public ushort ProtectionCount { get; set; } + + + } +} diff --git a/src/JT1078.FMp4/Boxs/LevelAssignmentBox.cs b/src/JT1078.FMp4/Boxs/LevelAssignmentBox.cs new file mode 100644 index 0000000..46dc935 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/LevelAssignmentBox.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class LevelAssignmentBox : FullBox + { + public LevelAssignmentBox(byte version=0, uint flags=0) : base("leva", version, flags) + { + } + + public byte LevelCount { get; set; } + + public class LevelAssignmentInfo + { + public uint TrackId { get; set; } + /// + /// 1byte 8-1 + /// + public bool PaddingFlag { get; set; } + /// + /// 1byte 8-7 + /// + public byte AssignmentType { get; set; } + /// + /// AssignmentType == 0 || assignment_type == 1 + /// + public uint GroupingType { get; set; } + /// + /// assignment_type == 1 + /// + public uint GroupingTypeParameter { get; set; } + /// + /// assignment_type == 4 + /// + public uint SubTrackId { get; set; } + } + } +} diff --git a/src/JT1078.FMp4/Boxs/MPEG4BitRateBox.cs b/src/JT1078.FMp4/Boxs/MPEG4BitRateBox.cs new file mode 100644 index 0000000..2aae852 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/MPEG4BitRateBox.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class MPEG4BitRateBox : Mp4Box + { + public MPEG4BitRateBox() : base("btrt") + { + } + + public uint BufferSizeDB { get; set; } + public uint MaxBitRate { get; set; } + public uint AvgBitRate { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/MediaBox.cs b/src/JT1078.FMp4/Boxs/MediaBox.cs new file mode 100644 index 0000000..e4361ba --- /dev/null +++ b/src/JT1078.FMp4/Boxs/MediaBox.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class MediaBox : Mp4Box + { + public MediaBox() : base("mdia") + { + } + + public MediaHeaderBox MediaHeaderBox { get; set; } + public HandlerBox HandlerBox { get; set; } + public MediaInformationBox MediaInformationBox { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/MediaDataBox.cs b/src/JT1078.FMp4/Boxs/MediaDataBox.cs new file mode 100644 index 0000000..90f94c3 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/MediaDataBox.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class MediaDataBox : Mp4Box + { + public MediaDataBox() : base("mdat") + { + } + + public byte[] Data { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/MediaHeaderBox.cs b/src/JT1078.FMp4/Boxs/MediaHeaderBox.cs new file mode 100644 index 0000000..09147c7 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/MediaHeaderBox.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class MediaHeaderBox : FullBox + { + public MediaHeaderBox(byte version, uint flags=0) : base("mdhd", version, flags) + { + } + public uint CreationTime { get; set; } + public uint ModificationTime { get; set; } + public uint Timescale { get; set; } + public uint Duration { get; set; } = 1; + //public bool Pad { get; set; } + /// + /// ISO-639-2/T language code + /// und-undetermined + /// + public string Language { get; set; } + public ushort PreDefined { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/MediaInformationBox.cs b/src/JT1078.FMp4/Boxs/MediaInformationBox.cs new file mode 100644 index 0000000..265a529 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/MediaInformationBox.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class MediaInformationBox : Mp4Box + { + public MediaInformationBox() : base("minf") + { + } + public FullBox MediaHeaderBox { get; set; } + public DataInformationBox DataInformationBox { get; set; } + public SampleTableBox SampleTableBox { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/MetaBox.cs b/src/JT1078.FMp4/Boxs/MetaBox.cs new file mode 100644 index 0000000..85a72e8 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/MetaBox.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class MetaBox : FullBox + { + public MetaBox(string handlerType,byte version=0, uint flags=0) : base("meta", version, flags) + { + HandlerType = handlerType; + } + + public string HandlerType { get; set; } + + public HandlerBox TheHandler { get; set; } + + public DataInformationBox FileLocations { get; set; } + + public ItemLocationBox ItemLLocations { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/MovieBox.cs b/src/JT1078.FMp4/Boxs/MovieBox.cs new file mode 100644 index 0000000..9a78f7c --- /dev/null +++ b/src/JT1078.FMp4/Boxs/MovieBox.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; +using System.Text; + +namespace JT1078.FMp4 +{ + public class MovieBox : Mp4Box + { + public MovieBox() : base("moov") + { + } + public MovieHeaderBox MovieHeaderBox { get; set; } + public TrackBox TrackBox { get; set; } + public MovieExtendsBox MovieExtendsBox { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/MovieExtendsBox.cs b/src/JT1078.FMp4/Boxs/MovieExtendsBox.cs new file mode 100644 index 0000000..a674e4a --- /dev/null +++ b/src/JT1078.FMp4/Boxs/MovieExtendsBox.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class MovieExtendsBox : Mp4Box + { + public MovieExtendsBox() : base("mvex") + { + } + public MovieExtendsHeaderBox MovieExtendsHeaderBox { get; set; } + public List TrackExtendsBoxs { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/MovieExtendsHeaderBox.cs b/src/JT1078.FMp4/Boxs/MovieExtendsHeaderBox.cs new file mode 100644 index 0000000..b9dcc79 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/MovieExtendsHeaderBox.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class MovieExtendsHeaderBox : FullBox + { + public MovieExtendsHeaderBox( byte version, uint flags=0) : base("mehd", version, flags) + { + } + public uint FragmentDuration { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/MovieFragmentBox.cs b/src/JT1078.FMp4/Boxs/MovieFragmentBox.cs new file mode 100644 index 0000000..7f26a58 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/MovieFragmentBox.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class MovieFragmentBox : Mp4Box + { + public MovieFragmentBox() : base("moof") + { + } + + public MovieFragmentHeaderBox MovieFragmentHeaderBox { get; set; } + public TrackFragmentBox TrackFragmentBox { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/MovieFragmentHeaderBox.cs b/src/JT1078.FMp4/Boxs/MovieFragmentHeaderBox.cs new file mode 100644 index 0000000..960a087 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/MovieFragmentHeaderBox.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class MovieFragmentHeaderBox : FullBox + { + public MovieFragmentHeaderBox(byte version=0, uint flags=0) : base("mfhd", version, flags) + { + } + + public uint SequenceNumber { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/MovieFragmentRandomAccessBox.cs b/src/JT1078.FMp4/Boxs/MovieFragmentRandomAccessBox.cs new file mode 100644 index 0000000..a6e7a69 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/MovieFragmentRandomAccessBox.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class MovieFragmentRandomAccessBox : Mp4Box + { + public MovieFragmentRandomAccessBox() : base("mfra") + { + } + + public TrackFragmentRandomAccessBox TrackFragmentRandomAccessBox { get; set; } + + public MovieFragmentRandomAccessOffsetBox MovieFragmentRandomAccessOffsetBox { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/MovieFragmentRandomAccessOffsetBox.cs b/src/JT1078.FMp4/Boxs/MovieFragmentRandomAccessOffsetBox.cs new file mode 100644 index 0000000..c100c7e --- /dev/null +++ b/src/JT1078.FMp4/Boxs/MovieFragmentRandomAccessOffsetBox.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class MovieFragmentRandomAccessOffsetBox : FullBox + { + public MovieFragmentRandomAccessOffsetBox(byte version, uint flags=0) : base("mfro", version, flags) + { + } + + public uint MfraSize { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/MovieHeaderBox.cs b/src/JT1078.FMp4/Boxs/MovieHeaderBox.cs new file mode 100644 index 0000000..13896d7 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/MovieHeaderBox.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class MovieHeaderBox : FullBox + { + public MovieHeaderBox(byte version, uint flags=0) : base("mvhd", version, flags) + { + } + public uint CreationTime { get; set; } + public uint ModificationTime { get; set; } + public uint Timescale { get; set;} + public uint Duration { get; set; } + public int Rate { get; set; } = 0x00010000; + public short Volume { get; set; } = 0x0100; + public byte[] Reserved1 { get; set; } = new byte[2]; + public uint[] Reserved2 { get; set; } = new uint[2]; + public int[] Matrix { get; set; }=new int [9]{ 0x00010000, 0, 0, 0, 0x00010000, 0, 0, 0, 0x40000000 }; + public byte[] PreDefined { get; set; } = new byte[24]; + public uint NextTrackID { get; set; }= uint.MaxValue; + } +} diff --git a/src/JT1078.FMp4/Boxs/NullMediaHeaderBox.cs b/src/JT1078.FMp4/Boxs/NullMediaHeaderBox.cs new file mode 100644 index 0000000..b390f61 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/NullMediaHeaderBox.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class NullMediaHeaderBox : FullBox + { + public NullMediaHeaderBox(byte version=0, uint flags=0) : base("nmhd", version, flags) + { + } + } +} diff --git a/src/JT1078.FMp4/Boxs/OriginalFormatBox.cs b/src/JT1078.FMp4/Boxs/OriginalFormatBox.cs new file mode 100644 index 0000000..91ac987 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/OriginalFormatBox.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class OriginalFormatBox : Mp4Box + { + public OriginalFormatBox(string codingname) : base("frma") + { + DataFormat = codingname; + } + + public string DataFormat { get; set; } + + } +} diff --git a/src/JT1078.FMp4/Boxs/PaddingBitsBox.cs b/src/JT1078.FMp4/Boxs/PaddingBitsBox.cs new file mode 100644 index 0000000..cb50acf --- /dev/null +++ b/src/JT1078.FMp4/Boxs/PaddingBitsBox.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class PaddingBitsBox : FullBox + { + public PaddingBitsBox(byte version=0, uint flags=0) : base("padb", version, flags) + { + } + + public uint SampleCount { get; set; } + + public List PaddingBitsInfos { get; set; } + + public class PaddingBitsInfo + { + public bool Reserved1 { get; set; } + public byte Pad1 { get; set; } + public bool Reserved2 { get; set; } + public byte Pad2 { get; set; } + } + } +} diff --git a/src/JT1078.FMp4/Boxs/PartitionEntryBox.cs b/src/JT1078.FMp4/Boxs/PartitionEntryBox.cs new file mode 100644 index 0000000..05bacec --- /dev/null +++ b/src/JT1078.FMp4/Boxs/PartitionEntryBox.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class PartitionEntryBox : Mp4Box + { + public PartitionEntryBox() : base("paen") + { + } + + + } +} diff --git a/src/JT1078.FMp4/Boxs/PixelAspectRatioBox.cs b/src/JT1078.FMp4/Boxs/PixelAspectRatioBox.cs new file mode 100644 index 0000000..4278016 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/PixelAspectRatioBox.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class PixelAspectRatioBox : Mp4Box + { + public PixelAspectRatioBox() : base("pasp") + { + } + public uint HSpacing { get; set; } + public uint VSpacing { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/PrimaryItemBox.cs b/src/JT1078.FMp4/Boxs/PrimaryItemBox.cs new file mode 100644 index 0000000..4ab8fd8 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/PrimaryItemBox.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class PrimaryItemBox : FullBox + { + public PrimaryItemBox(byte version=0, uint flags=0) : base("pitm", version, flags) + { + } + + public ushort ItemID { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/ProducerReferenceTimeBox.cs b/src/JT1078.FMp4/Boxs/ProducerReferenceTimeBox.cs new file mode 100644 index 0000000..237e6d8 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/ProducerReferenceTimeBox.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class ProducerReferenceTimeBox : FullBox + { + public ProducerReferenceTimeBox(byte version, uint flags) : base("prft", version, flags) + { + } + public ushort ReferenceTrackID { get; set; } + public uint NtpTimestamp { get; set; } + /// + /// if (version==0) + /// + public uint MediaTime { get; set; } + public ulong MediaTimeLagre { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/ProgressiveDownloadInfoBox.cs b/src/JT1078.FMp4/Boxs/ProgressiveDownloadInfoBox.cs new file mode 100644 index 0000000..7c9418f --- /dev/null +++ b/src/JT1078.FMp4/Boxs/ProgressiveDownloadInfoBox.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class ProgressiveDownloadInfoBox : FullBox + { + public ProgressiveDownloadInfoBox(byte version=0, uint flags=0) : base("pdin", version, flags) + { + } + + public List ProgressiveDownloadInfos { get; set; } + + public class ProgressiveDownloadInfo + { + public ushort Rate { get; set; } + public ushort InitialDelay { get; set; } + } + } +} diff --git a/src/JT1078.FMp4/Boxs/ProtectionSchemeInfoBox.cs b/src/JT1078.FMp4/Boxs/ProtectionSchemeInfoBox.cs new file mode 100644 index 0000000..f021847 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/ProtectionSchemeInfoBox.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class ProtectionSchemeInfoBox : Mp4Box + { + public ProtectionSchemeInfoBox(string fmt) : base("sinf") + { + OriginalFormatBox = new OriginalFormatBox(fmt); + } + + public OriginalFormatBox OriginalFormatBox { get; set; } + + public SchemeTypeBox SchemeTypeBox { get; set; } + + public SchemeInformationBox SchemeInformationBox { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/RestrictedSchemeInfoBox.cs b/src/JT1078.FMp4/Boxs/RestrictedSchemeInfoBox.cs new file mode 100644 index 0000000..f660f09 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/RestrictedSchemeInfoBox.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class RestrictedSchemeInfoBox : Mp4Box + { + public RestrictedSchemeInfoBox(string fmt) : base("rinf") + { + OriginalFormatBox = new OriginalFormatBox(fmt); + } + + public OriginalFormatBox OriginalFormatBox { get; set; } + + public SchemeTypeBox SchemeTypeBox { get; set; } + + public SchemeInformationBox SchemeInformationBox { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/SampleAuxiliaryInformationOffsetsBox.cs b/src/JT1078.FMp4/Boxs/SampleAuxiliaryInformationOffsetsBox.cs new file mode 100644 index 0000000..5aeb5f9 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/SampleAuxiliaryInformationOffsetsBox.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class SampleAuxiliaryInformationOffsetsBox : FullBox + { + public SampleAuxiliaryInformationOffsetsBox(byte version, uint flags) : base("saio", version, flags) + { + } + /// + /// if (flags & 1) + /// + public uint AuxInfoType { get; set; } + /// + /// if (flags & 1) + /// + public uint AuxInfoTypeParameter { get; set; } + public uint EntryCount { get; set; } + /// + /// length:entry_count + /// + public uint[] Offset { get; set; } + /// + /// length:entry_count + /// + public ulong[] OffsetLarge { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/SampleAuxiliaryInformationSizesBox.cs b/src/JT1078.FMp4/Boxs/SampleAuxiliaryInformationSizesBox.cs new file mode 100644 index 0000000..dd808fc --- /dev/null +++ b/src/JT1078.FMp4/Boxs/SampleAuxiliaryInformationSizesBox.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class SampleAuxiliaryInformationSizesBox : FullBox + { + public SampleAuxiliaryInformationSizesBox(byte version=0, uint flags=0) : base("saiz", version, flags) + { + } + /// + /// if (flags & 1) + /// + public uint AuxInfoType { get; set; } + /// + /// if (flags & 1) + /// + public uint AuxInfoTypeParameter { get; set; } + public byte DefaultSampleInfoSize { get; set; } + public uint SampleCount { get; set; } + /// + /// default_sample_info_size==0 + /// length:sample_count + /// + public byte[] SampleInfoSize { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/SampleDependencyTypeBox.cs b/src/JT1078.FMp4/Boxs/SampleDependencyTypeBox.cs new file mode 100644 index 0000000..41ded80 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/SampleDependencyTypeBox.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class SampleDependencyTypeBox : FullBox + { + public SampleDependencyTypeBox(byte version=0, uint flags=0) : base("sdtp", version, flags) + { + } + /// + /// is taken from the sample_count in the Sample Size Box ('stsz') or Compact Sample Size Box(‘stz2’). + /// + public List SampleDependencyTypes { get; set; } + + public class SampleDependencyType + { + public byte IsLeading { get; set; } + public byte SampleDependsOn { get; set; } + public byte SampleIsDependedOn { get; set; } + public byte SampleHasRedundancy { get; set; } + public byte DegradPrio { get; set; } + public byte IsNonSync { get; set; } + public byte PaddingValue { get; set; } + } + } +} diff --git a/src/JT1078.FMp4/Boxs/SampleDescriptionBox.cs b/src/JT1078.FMp4/Boxs/SampleDescriptionBox.cs new file mode 100644 index 0000000..dcdb2fa --- /dev/null +++ b/src/JT1078.FMp4/Boxs/SampleDescriptionBox.cs @@ -0,0 +1,20 @@ +using JT1078.FMp4.Samples; +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class SampleDescriptionBox : FullBox + { + public string HandlerType { get; set; } + public SampleDescriptionBox(string handlerType,byte version=0, uint flags=0) : base("stsd", version, flags) + { + HandlerType = handlerType; + } + + public uint EntryCount { get; set; } + + public List SampleEntries { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/SampleGroupDescriptionBox.cs b/src/JT1078.FMp4/Boxs/SampleGroupDescriptionBox.cs new file mode 100644 index 0000000..2e11bac --- /dev/null +++ b/src/JT1078.FMp4/Boxs/SampleGroupDescriptionBox.cs @@ -0,0 +1,29 @@ +using JT1078.FMp4.Samples; +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class SampleGroupDescriptionBox : FullBox + { + public SampleGroupDescriptionBox(string handlerType, byte version, uint flags=0) : base("sgpd", version, flags) + { + HandlerType = handlerType; + } + + public string HandlerType { get; set; } + /// + /// if (version==1) + /// + public uint DefaultLength { get; set; } + public uint EntryCount { get; set; } + public List SampleGroupDescriptions { get; set; } + public class SampleGroupDescription + { + public uint DescriptionLength { get; set; } + + public SampleGroupDescriptionEntry SampleGroupDescriptionEntry { get; set; } + } + } +} diff --git a/src/JT1078.FMp4/Boxs/SampleSizeBox.cs b/src/JT1078.FMp4/Boxs/SampleSizeBox.cs new file mode 100644 index 0000000..6a0e5dc --- /dev/null +++ b/src/JT1078.FMp4/Boxs/SampleSizeBox.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class SampleSizeBox : FullBox + { + public SampleSizeBox(byte version=0, uint flags=0) : base("stsz", version, flags) + { + } + + public uint SampleSize { get; set; } + public uint SampleCount { get; set; } + /// + /// if (sample_size==0) + /// length:sample_count + /// + public List EntrySize { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/SampleTableBox.cs b/src/JT1078.FMp4/Boxs/SampleTableBox.cs new file mode 100644 index 0000000..dad6775 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/SampleTableBox.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class SampleTableBox : Mp4Box + { + public SampleTableBox() : base("stbl") + { + } + public SampleDescriptionBox SampleDescriptionBox { get; set; } + public TimeToSampleBox TimeToSampleBox { get; set; } + public CompositionOffsetBox CompositionOffsetBox { get; set; } + public SampleToChunkBox SampleToChunkBox { get; set; } + public SampleSizeBox SampleSizeBox { get; set; } + public CompactSampleSizeBox CompactSampleSizeBox { get; set; } + 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; } + public SampleDependencyTypeBox SampleDependencyTypeBox { get; set; } + public SampleToGroupBox SampleToGroupBox { get; set; } + public SampleGroupDescriptionBox SampleGroupDescriptionBox { get; set; } + public SubSampleInformationBox SubSampleInformationBox { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/SampleToChunkBox.cs b/src/JT1078.FMp4/Boxs/SampleToChunkBox.cs new file mode 100644 index 0000000..7d04a70 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/SampleToChunkBox.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class SampleToChunkBox : FullBox + { + public SampleToChunkBox(byte version=0, uint flags=0) : base("stsc", version, flags) + { + } + public uint EntryCount { get; set; } + public List SampleToChunkInfos { get; set; } + public class SampleToChunkInfo + { + public uint FirstChunk { get; set; } + public uint SamplesPerChunk { get; set; } + public uint SampleDescriptionIindex { get; set; } + } + } +} diff --git a/src/JT1078.FMp4/Boxs/SampleToGroupBox.cs b/src/JT1078.FMp4/Boxs/SampleToGroupBox.cs new file mode 100644 index 0000000..3329de3 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/SampleToGroupBox.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class SampleToGroupBox : FullBox + { + public SampleToGroupBox(byte version, uint flags) : base("sbgp", version, flags) + { + } + + public uint GroupingType { get; set; } + /// + /// version == 1 + /// + public uint GroupingTypeParameter { get; set; } + + public uint EntryCount { get; set; } + + public List SampleToGroupInfos { get; set; } + + public class SampleToGroupInfo + { + public uint SampleCount { get; set; } + public uint GroupDescriptionIndex { get; set; } + } + } +} diff --git a/src/JT1078.FMp4/Boxs/SchemeInformationBox.cs b/src/JT1078.FMp4/Boxs/SchemeInformationBox.cs new file mode 100644 index 0000000..6c14c1f --- /dev/null +++ b/src/JT1078.FMp4/Boxs/SchemeInformationBox.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class SchemeInformationBox : Mp4Box + { + public SchemeInformationBox() : base("schi") + { + } + + public List SchemeSpecificData { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/SchemeTypeBox.cs b/src/JT1078.FMp4/Boxs/SchemeTypeBox.cs new file mode 100644 index 0000000..d42b7f7 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/SchemeTypeBox.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class SchemeTypeBox : FullBox + { + public SchemeTypeBox(byte version, uint flags) : base("schm", version, flags) + { + } + + public SchemeTypeBox(uint flags) : this(0,flags) + { + } + + public uint SchemeType { get; set; } + + public uint SchemeVersion { get; set; } + /// + /// if (flags & 0x000001) + /// UTF-8 + /// + public string SchemeUri { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/SegmentIndexBox.cs b/src/JT1078.FMp4/Boxs/SegmentIndexBox.cs new file mode 100644 index 0000000..e8c708b --- /dev/null +++ b/src/JT1078.FMp4/Boxs/SegmentIndexBox.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class SegmentIndexBox : FullBox + { + 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; } + /// + /// if(version==0) + /// + public uint EarliestPresentationTime { get; set; } + /// + /// if (version==0) + /// + public uint FirstOffset { get; set; } + public ushort Reserved { get; set; } + public ushort ReferenceCount { get; set; } + + public List SegmentIndexs { get; set; } + + public class SegmentIndex + { + /// + /// 4byte 32 - 1 + /// + public bool ReferenceType { get; set; } + /// + /// 4byte 32 - 31 + /// + public uint ReferencedSize { get; set; } + public uint SubsegmentDuration { get; set; } + /// + /// 4byte 32 - 1 + /// + public bool StartsWithSAP { get; set; } + /// + /// 4byte 32 - 3 + /// + public byte SAPType { get; set; } + /// + /// 4byte 32 - 28 + /// + public uint SAPDeltaTime { get; set; } + } + } +} diff --git a/src/JT1078.FMp4/Boxs/ShadowSyncSampleBox.cs b/src/JT1078.FMp4/Boxs/ShadowSyncSampleBox.cs new file mode 100644 index 0000000..01f09b2 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/ShadowSyncSampleBox.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class ShadowSyncSampleBox : FullBox + { + public ShadowSyncSampleBox(byte version, uint flags) : base("stsh", version, flags) + { + } + + public uint EntryCount { get; set; } + + public List ShadowSyncSampleInfos { get; set; } + + public class ShadowSyncSampleInfo + { + public uint ShadowedSampleNumber { get; set; } + public uint SyncSampleNumber { get; set; } + } + } +} diff --git a/src/JT1078.FMp4/Boxs/SkipBox.cs b/src/JT1078.FMp4/Boxs/SkipBox.cs new file mode 100644 index 0000000..4e2f05c --- /dev/null +++ b/src/JT1078.FMp4/Boxs/SkipBox.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class SkipBox : FreeSpaceBox + { + public SkipBox() : base("skip") + { + } + } +} diff --git a/src/JT1078.FMp4/Boxs/SoundMediaHeaderBox.cs b/src/JT1078.FMp4/Boxs/SoundMediaHeaderBox.cs new file mode 100644 index 0000000..b93d81a --- /dev/null +++ b/src/JT1078.FMp4/Boxs/SoundMediaHeaderBox.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class SoundMediaHeaderBox : FullBox + { + public SoundMediaHeaderBox(byte version=0, uint flags=0) : base("smhd", version, flags) + { + } + + public ushort Balance { get; set; } + public ushort Reserved { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/StereoVideoBox.cs b/src/JT1078.FMp4/Boxs/StereoVideoBox.cs new file mode 100644 index 0000000..5cd9a4f --- /dev/null +++ b/src/JT1078.FMp4/Boxs/StereoVideoBox.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class StereoVideoBox : FullBox + { + public StereoVideoBox(byte version=0, uint flags=0) : base("stvi", version, flags) + { + } + /// + ///4btye 32 - 30 + /// + public uint Reserved { get; set; } + /// + ///4btye 32 - 2 + /// + public byte SingleViewAllowed { get; set; } + public uint StereoScheme { get; set; } + public uint Length { get; set; } + /// + /// length:Length + /// + public byte[] StereoIndicationType { get; set; } + public List AnyBox { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/SubSampleInformationBox.cs b/src/JT1078.FMp4/Boxs/SubSampleInformationBox.cs new file mode 100644 index 0000000..55bbdc8 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/SubSampleInformationBox.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class SubSampleInformationBox : FullBox + { + public SubSampleInformationBox(byte version, uint flags=0) : base("subs", version, flags) + { + } + + public uint EntryCount { get; set; } + + public List SubSampleInformations { get; set; } + + public class SubSampleInformation + { + public uint SampleDelta { get; set; } + public ushort SubsampleCount { get; set; } + + public List InnerSubSampleInformations { get; set; } + + public class InnerSubSampleInformation + { + /// + /// version == 1 + /// + public uint SubsampleSizeLarge { get; set; } + public ushort SubsampleSize { get; set; } + public byte SubsamplePriority { get; set; } + public byte Discardable { get; set; } + public uint Reserved { get; set; } + } + } + } +} diff --git a/src/JT1078.FMp4/Boxs/SubTrackBox.cs b/src/JT1078.FMp4/Boxs/SubTrackBox.cs new file mode 100644 index 0000000..d5edc82 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/SubTrackBox.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class SubTrackBox : Mp4Box + { + public SubTrackBox() : base("strk") + { + } + } +} diff --git a/src/JT1078.FMp4/Boxs/SubTrackDefinitionBox.cs b/src/JT1078.FMp4/Boxs/SubTrackDefinitionBox.cs new file mode 100644 index 0000000..584030d --- /dev/null +++ b/src/JT1078.FMp4/Boxs/SubTrackDefinitionBox.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class SubTrackDefinitionBox : Mp4Box + { + public SubTrackDefinitionBox() : base("strd") + { + } + } +} diff --git a/src/JT1078.FMp4/Boxs/SubTrackInformationBox.cs b/src/JT1078.FMp4/Boxs/SubTrackInformationBox.cs new file mode 100644 index 0000000..1fe60f8 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/SubTrackInformationBox.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class SubTrackInformationBox : FullBox + { + public SubTrackInformationBox(byte version=0, uint flags=0) : base("stri", version, flags) + { + } + + public ushort SwitchGroup { get; set; } + public ushort AlternateGroup { get; set; } + public uint SubTrackID { get; set; } + public List AttributeList { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/SubTrackSampleGroupBox.cs b/src/JT1078.FMp4/Boxs/SubTrackSampleGroupBox.cs new file mode 100644 index 0000000..769a310 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/SubTrackSampleGroupBox.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class SubTrackSampleGroupBox : FullBox + { + public SubTrackSampleGroupBox(byte version=0, uint flags=0) : base("stsg", version, flags) + { + } + public uint GroupingType { get; set; } + public ushort ItemCount { get; set; } + /// + /// length:ItemCount + /// + public List GroupDescriptionIndex { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/SubsegmentIndexBox.cs b/src/JT1078.FMp4/Boxs/SubsegmentIndexBox.cs new file mode 100644 index 0000000..3d393c8 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/SubsegmentIndexBox.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class SubsegmentIndexBox : FullBox + { + public SubsegmentIndexBox(byte version = 0, uint flags = 0) : base("ssix", version, flags) + { + } + + public uint SubSegmentCount { get; set; } + /// + /// length:SubSegmentCount + /// + public List SubsegmentIndexInfos { get; set; } + + public class SubsegmentIndexInfo + { + public uint RangesCount { get; set; } + /// + /// length:RangesCount + /// + public List SubsegmentRangeInfos { get; set; } + + public class SubsegmentRangeInfo + { + /// + /// 32 - 8 + /// + public byte Level { get; set; } + /// + /// 32 - 4 + /// + public uint RangeSize { get; set; } + } + } + } +} diff --git a/src/JT1078.FMp4/Boxs/SyncSampleBox.cs b/src/JT1078.FMp4/Boxs/SyncSampleBox.cs new file mode 100644 index 0000000..ca13df9 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/SyncSampleBox.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class SyncSampleBox : FullBox + { + public SyncSampleBox(byte version=0, uint flags=0) : base("stss", version, flags) + { + } + + public uint EntryCount { get; set; } + + public List SampleNumber { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/TimeToSampleBox.cs b/src/JT1078.FMp4/Boxs/TimeToSampleBox.cs new file mode 100644 index 0000000..d0fcc42 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/TimeToSampleBox.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class TimeToSampleBox : FullBox + { + public TimeToSampleBox(byte version = 0, uint flags = 0) : base("stts", version, flags) + { + } + + public uint EntryCount{get;set;} + + public List TimeToSampleInfos { get; set; } + + public class TimeToSampleInfo + { + public uint SampleCount { get; set; } + + public uint SampleDelta { get; set; } + } + } +} diff --git a/src/JT1078.FMp4/Boxs/TrackBox.cs b/src/JT1078.FMp4/Boxs/TrackBox.cs new file mode 100644 index 0000000..a6ff84f --- /dev/null +++ b/src/JT1078.FMp4/Boxs/TrackBox.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class TrackBox : Mp4Box + { + public TrackBox() : base("trak") + { + } + public TrackHeaderBox TrackHeaderBox { get; set; } + public TrackReferenceBox TrackReferenceBox { get; set; } + public EditBox EditBox { get; set; } + public MediaBox MediaBox { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/TrackExtendsBox.cs b/src/JT1078.FMp4/Boxs/TrackExtendsBox.cs new file mode 100644 index 0000000..2fcbbfe --- /dev/null +++ b/src/JT1078.FMp4/Boxs/TrackExtendsBox.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class TrackExtendsBox : FullBox + { + public TrackExtendsBox(byte version=0, uint flags=0) : base("trex", version, flags) + { + } + + public uint TrackID { get; set; } + public uint DefaultSampleDescriptionIndex { get; set; } + public uint DefaultSampleDuration { get; set; } + public uint DefaultSampleSize { get; set; } + public uint DefaultSampleFlags { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/TrackFragmentBaseMediaDecodeTimeBox.cs b/src/JT1078.FMp4/Boxs/TrackFragmentBaseMediaDecodeTimeBox.cs new file mode 100644 index 0000000..9aa2fe4 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/TrackFragmentBaseMediaDecodeTimeBox.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class TrackFragmentBaseMediaDecodeTimeBox : FullBox + { + public TrackFragmentBaseMediaDecodeTimeBox(byte version, uint flags=0) : base("tfdt", version, flags) + { + } + public uint BaseMediaDecodeTime { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/TrackFragmentBox.cs b/src/JT1078.FMp4/Boxs/TrackFragmentBox.cs new file mode 100644 index 0000000..a6612d9 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/TrackFragmentBox.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class TrackFragmentBox : Mp4Box + { + public TrackFragmentBox() : base("traf") + { + } + public TrackFragmentHeaderBox TrackFragmentHeaderBox { get; set; } + public SampleDependencyTypeBox SampleDependencyTypeBox { get; set; } + public TrackRunBox TrackRunBox { get; set; } + public TrackFragmentBaseMediaDecodeTimeBox TrackFragmentBaseMediaDecodeTimeBox { get; set; } + public SampleToGroupBox SampleToGroupBox { get; set; } + public SubSampleInformationBox SubSampleInformationBox { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/TrackFragmentHeaderBox.cs b/src/JT1078.FMp4/Boxs/TrackFragmentHeaderBox.cs new file mode 100644 index 0000000..69b2ca7 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/TrackFragmentHeaderBox.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class TrackFragmentHeaderBox : FullBox + { + public TrackFragmentHeaderBox(byte version, uint flags) : base("tfhd", version, flags) + { + } + public TrackFragmentHeaderBox(uint flags) : this(0, flags) + { + } + + public uint TrackID { get; set; } + + #region all the following are optional fields + public ulong BaseDataOffset { get; set; } + public uint SampleDescriptionIndex { get; set; } + public uint DefaultSampleDuration { get; set; } + public uint DefaultSampleSize { get; set; } + public uint DefaultSampleFlags { get; set; } + #endregion + } +} diff --git a/src/JT1078.FMp4/Boxs/TrackFragmentRandomAccessBox.cs b/src/JT1078.FMp4/Boxs/TrackFragmentRandomAccessBox.cs new file mode 100644 index 0000000..c0a6b5d --- /dev/null +++ b/src/JT1078.FMp4/Boxs/TrackFragmentRandomAccessBox.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class TrackFragmentRandomAccessBox : FullBox + { + public TrackFragmentRandomAccessBox(byte version, uint flags=0) : base("tfra", version, flags) + { + } + public uint TrackID { get; set; } + /// + /// 4byte 32-26 + /// + public uint Reserved { get; set; } = 26; + /// + /// 4byte 32-28 + /// + public uint LengthSizeOfTrafNum { get; set; } + /// + /// 4byte 32-30 + /// + public uint LengthSizeOfTrunNum { get; set; } + /// + /// 4byte 32-32 + /// + public uint LengthSizeOfSampleNum { get; set; } + public uint NumberOfEntry { get; set; } + public List TrackFragmentRandomAccessInfos { get; set; } + public class TrackFragmentRandomAccessInfo + { + public ulong Time { get; set; } + public ulong MoofOffset { get; set; } + public uint TrafNumber { get; set; } + public uint TrunNumber { get; set; } + public uint SampleNumber { get; set; } + } + } +} diff --git a/src/JT1078.FMp4/Boxs/TrackGroupBox.cs b/src/JT1078.FMp4/Boxs/TrackGroupBox.cs new file mode 100644 index 0000000..0101b42 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/TrackGroupBox.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class TrackGroupBox : Mp4Box + { + public TrackGroupBox() : base("trgr") + { + } + + + } +} diff --git a/src/JT1078.FMp4/Boxs/TrackGroupTypeBox.cs b/src/JT1078.FMp4/Boxs/TrackGroupTypeBox.cs new file mode 100644 index 0000000..ba6d951 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/TrackGroupTypeBox.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class TrackGroupTypeBox : FullBox + { + public TrackGroupTypeBox(string boxType, byte version=0, uint flags=0) : base(boxType, version, flags) + { + } + + public uint TrackGroupId { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/TrackHeaderBox.cs b/src/JT1078.FMp4/Boxs/TrackHeaderBox.cs new file mode 100644 index 0000000..f1db694 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/TrackHeaderBox.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class TrackHeaderBox : FullBox + { + public TrackHeaderBox(byte version, uint flags) : base("tkhd", version, flags) + { + } + public uint CreationTime { get; set; } + public uint ModificationTime { get; set; } + public uint TrackID { get; set; } + public uint Reserved1 { get; set; } + public uint Duration { get; set; } + public uint[] Reserved2 { get; set; } = new uint[2]; + public ushort Layer { get; set; } + public ushort AlternateGroup { get; set; } + public ushort Volume { get; set; } + public ushort Reserved3 { get; set; } + public int[] Matrix { get; set; } = new int[9] { 0x00010000, 0, 0, 0, 0x00010000, 0, 0, 0, 0x40000000 }; + public uint Width { get; set; } + public uint Height { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/TrackReferenceBox.cs b/src/JT1078.FMp4/Boxs/TrackReferenceBox.cs new file mode 100644 index 0000000..89ff1bf --- /dev/null +++ b/src/JT1078.FMp4/Boxs/TrackReferenceBox.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class TrackReferenceBox : Mp4Box + { + public TrackReferenceBox() : base("tref") + { + } + + } +} diff --git a/src/JT1078.FMp4/Boxs/TrackReferenceTypeBox.cs b/src/JT1078.FMp4/Boxs/TrackReferenceTypeBox.cs new file mode 100644 index 0000000..a12b99e --- /dev/null +++ b/src/JT1078.FMp4/Boxs/TrackReferenceTypeBox.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class TrackReferenceTypeBox : Mp4Box + { + public TrackReferenceTypeBox(string referenceType) : base(referenceType) + { + } + + public List TrackIDs { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/TrackRunBox.cs b/src/JT1078.FMp4/Boxs/TrackRunBox.cs new file mode 100644 index 0000000..1cc0cdc --- /dev/null +++ b/src/JT1078.FMp4/Boxs/TrackRunBox.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class TrackRunBox : FullBox + { + public TrackRunBox(byte version, uint flags) : base("trun", version, flags) + { + } + + public uint SampleCount { get; set; } + /// + /// 可选的 + /// + public int DataOffset { get; set; } + public uint FirstSampleFlags { get; set; } + /// + /// length:SampleCount + /// + public List TrackRunInfos { get; set; } + public class TrackRunInfo + { + public uint SampleDuration { get; set; } + public uint SampleSize { get; set; } + public uint SampleFlags { get; set; } + /// + /// version == 0 + /// + public uint SampleCompositionTimeOffset { get; set; } + public int SignedSampleCompositionTimeOffset { get; set; } + } + } +} diff --git a/src/JT1078.FMp4/Boxs/TrackSelectionBox.cs b/src/JT1078.FMp4/Boxs/TrackSelectionBox.cs new file mode 100644 index 0000000..eb3729b --- /dev/null +++ b/src/JT1078.FMp4/Boxs/TrackSelectionBox.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class TrackSelectionBox : FullBox + { + public TrackSelectionBox(byte version=0, uint flags=0) : base("tsel", version, flags) + { + } + + public uint SwitchGroup { get; set; } + + public List AttributeList { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/URIBox.cs b/src/JT1078.FMp4/Boxs/URIBox.cs new file mode 100644 index 0000000..7b90279 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/URIBox.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class URIBox : FullBox + { + public URIBox(byte version=0, uint flags=0) : base("uri ", version, flags) + { + } + + public string TheURI { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/URIInitBox.cs b/src/JT1078.FMp4/Boxs/URIInitBox.cs new file mode 100644 index 0000000..b1e0ed5 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/URIInitBox.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class URIInitBox : FullBox + { + public URIInitBox(byte version=0, uint flags=0) : base("uriI", version, flags) + { + } + + public byte[] UriInitializationData { get; set; } + } +} diff --git a/src/JT1078.FMp4/Boxs/UserDataBox.cs b/src/JT1078.FMp4/Boxs/UserDataBox.cs new file mode 100644 index 0000000..7abf7f9 --- /dev/null +++ b/src/JT1078.FMp4/Boxs/UserDataBox.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class UserDataBox : Mp4Box + { + public UserDataBox() : base("udta") + { + } + } +} diff --git a/src/JT1078.FMp4/Boxs/VideoMediaHeaderBox.cs b/src/JT1078.FMp4/Boxs/VideoMediaHeaderBox.cs new file mode 100644 index 0000000..f264a7b --- /dev/null +++ b/src/JT1078.FMp4/Boxs/VideoMediaHeaderBox.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class VideoMediaHeaderBox : FullBox + { + public VideoMediaHeaderBox(byte version = 0, uint flags = 1) : base("vmhd", version, flags) + { + } + + public ushort GraphicsMode { get; set; } + public ushort Red { get; set; } + public ushort Green { get; set; } + public ushort Blue { get; set; } + public ushort[] OpColor + { + get + { + return new ushort[] { + Red,Green,Blue + }; + } + } + } +} diff --git a/src/JT1078.FMp4/Buffers/FMp4BufferWriter.cs b/src/JT1078.FMp4/Buffers/FMp4BufferWriter.cs new file mode 100644 index 0000000..1318f56 --- /dev/null +++ b/src/JT1078.FMp4/Buffers/FMp4BufferWriter.cs @@ -0,0 +1,24 @@ +using System; + +namespace JT1078.FMp4.Buffers +{ + /// + /// + /// + ref partial struct FMp4BufferWriter + { + private Span _buffer; + public FMp4BufferWriter(Span buffer) + { + _buffer = buffer; + WrittenCount = 0; + } + public Span Free => _buffer.Slice(WrittenCount); + public Span Written => _buffer.Slice(0, WrittenCount); + public int WrittenCount { get; private set; } + public void Advance(int count) + { + WrittenCount += count; + } + } +} diff --git a/src/JT1078.FMp4/FMp4ArrayPool.cs b/src/JT1078.FMp4/FMp4ArrayPool.cs new file mode 100644 index 0000000..4117e2c --- /dev/null +++ b/src/JT1078.FMp4/FMp4ArrayPool.cs @@ -0,0 +1,24 @@ +using System.Buffers; + +namespace JT1078.FMp4 +{ + internal static class FMp4ArrayPool + { + private readonly static ArrayPool ArrayPool; + + static FMp4ArrayPool() + { + ArrayPool = ArrayPool.Create(); + } + + public static byte[] Rent(int minimumLength) + { + return ArrayPool.Rent(minimumLength); + } + + public static void Return(byte[] array, bool clearArray = false) + { + ArrayPool.Return(array, clearArray); + } + } +} diff --git a/src/JT1078.FMp4/FMp4Box.cs b/src/JT1078.FMp4/FMp4Box.cs new file mode 100644 index 0000000..b720925 --- /dev/null +++ b/src/JT1078.FMp4/FMp4Box.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class FMp4Box + { + public FileTypeBox FileTypeBox { get; set; } + public MovieBox MovieBox { get; set; } + public List FragmentBoxs { get; set; } + public MovieFragmentRandomAccessBox MovieFragmentRandomAccessBox { get; set; } + } +} diff --git a/src/JT1078.FMp4/FMp4Constants.cs b/src/JT1078.FMp4/FMp4Constants.cs new file mode 100644 index 0000000..b54d3ef --- /dev/null +++ b/src/JT1078.FMp4/FMp4Constants.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Text; + +[assembly: InternalsVisibleTo("JT1078.FMp4.Test")] + +namespace JT1078.FMp4 +{ + public static class FMp4Constants + { + /// + /// 日期限制于2000年 + /// + public const int DateLimitYear = 2000; + public static readonly DateTime UTCBaseTime = new DateTime(1904, 1, 1); + } +} diff --git a/src/JT1078.FMp4/FMp4Encoder.cs b/src/JT1078.FMp4/FMp4Encoder.cs new file mode 100644 index 0000000..4698461 --- /dev/null +++ b/src/JT1078.FMp4/FMp4Encoder.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public class FMp4Encoder + { + + } +} diff --git a/src/JT1078.FMp4/FullBox.cs b/src/JT1078.FMp4/FullBox.cs new file mode 100644 index 0000000..83abdb7 --- /dev/null +++ b/src/JT1078.FMp4/FullBox.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public abstract class FullBox : Mp4Box + { + public FullBox(string boxType,byte version,uint flags) : base(boxType) + { + Version = version; + Flags = flags; + } + public byte Version { get; set; } + public uint Flags { get; set; } + } +} diff --git a/src/JT1078.FMp4/Interfaces/IFMp4MessagePackFormatter.cs b/src/JT1078.FMp4/Interfaces/IFMp4MessagePackFormatter.cs new file mode 100644 index 0000000..333e695 --- /dev/null +++ b/src/JT1078.FMp4/Interfaces/IFMp4MessagePackFormatter.cs @@ -0,0 +1,10 @@ +using JT1078.FMp4.MessagePack; +using System; + +namespace JT1078.FMp4.Interfaces +{ + public interface IFMp4MessagePackFormatter + { + void ToBuffer(ref FMp4MessagePackWriter writer); + } +} diff --git a/src/JT1078.FMp4/JT1078.FMp4.csproj b/src/JT1078.FMp4/JT1078.FMp4.csproj new file mode 100644 index 0000000..27aad09 --- /dev/null +++ b/src/JT1078.FMp4/JT1078.FMp4.csproj @@ -0,0 +1,42 @@ + + + + netstandard2.0;netstandard2.1; + 8.0 + Copyright 2019. + SmallChi(Koike) + JT1078.FMp4 + JT1078.FMp4 + 基于JT1078的FMp4视频编码器 + 基于JT1078的FMp4视频编码器 + https://github.com/SmallChi/JT1078 + https://github.com/SmallChi/JT1078 + https://github.com/SmallChi/JT1078/blob/master/LICENSE + https://github.com/SmallChi/JT1078/blob/master/LICENSE + false + 1.0.0-preview1 + false + true + LICENSE + + + + JT1078.FMp4.xml + + + + JT1078.FMp4.xml + + + + True + + + + + + + + + + diff --git a/src/JT1078.FMp4/JT1078.FMp4.xml b/src/JT1078.FMp4/JT1078.FMp4.xml new file mode 100644 index 0000000..119cc17 --- /dev/null +++ b/src/JT1078.FMp4/JT1078.FMp4.xml @@ -0,0 +1,367 @@ + + + + JT1078.FMp4 + + + + + + + + + + length:EntryCount + + + + + length:EntryCount + + + + + 4, 8 or 16 + + + + + length:SampleCount + DepOn:field_size=>DataType + + + + + version == 1 + + + + + 16-1 + + + + + 16-15 + ISO-639-2/T language code + + + + + length:EntryCount + + + + + sample_count is taken from the sample_count in the Sample Size Box ('stsz'). + + + + + length:EntryCount + + + + + length:EntryCount + + + + + length:NumChannelsInSessionGroup + + + + + 以null结尾 + + + + + ftyp 盒子相当于就是该 mp4 的纲领性说明。即,告诉解码器它的基本解码版本,兼容格式。简而言之,就是用来告诉客户端,该 MP4 的使用的解码标准。通常,ftyp 都是放在 MP4 的开头。 + + + + + 因为兼容性一般可以分为推荐兼容性和默认兼容性。这里 major_brand 就相当于是推荐兼容性。通常,在 Web 中解码,一般而言都是使用 isom 这个万金油即可。如果是需要特定的格式,可以自行定义。 + 4位 + + + + + 最低兼容版本 + 4位 + + + + + 和MajorBrand类似,通常是针对 MP4 中包含的额外格式,比如,AVC,AAC 等相当于的音视频解码格式。 + 4位*n + + + + + 填充值 + + + + + 填充数量 + + + + + 0, 4, 8 + + + + + 0, 4, 8 + + + + + 0, 4, 8 + + + + + version == 1 + + + + + if (version == 1) 16-12 + + + + + if (version == 1) 16-4 + + + + + + 1byte 8-1 + + + + + 1byte 8-7 + + + + + AssignmentType == 0 || assignment_type == 1 + + + + + assignment_type == 1 + + + + + assignment_type == 4 + + + + + ISO-639-2/T language code + und-undetermined + + + + + if (version==0) + + + + + + + length:entry_count + + + + + length:entry_count + + + + + + + default_sample_info_size==0 + length:sample_count + + + + + is taken from the sample_count in the Sample Size Box ('stsz') or Compact Sample Size Box(‘stz2’). + + + + + if (version==1) + + + + + if (sample_size==0) + length:sample_count + + + + + version == 1 + + + + + + + + + + + if(version==0) + + + + + if (version==0) + + + + + 4byte 32 - 1 + + + + + 4byte 32 - 31 + + + + + 4byte 32 - 1 + + + + + 4byte 32 - 3 + + + + + 4byte 32 - 28 + + + + + 4btye 32 - 30 + + + + + 4btye 32 - 2 + + + + + length:Length + + + + + version == 1 + + + + + length:SubSegmentCount + + + + + length:RangesCount + + + + + 32 - 8 + + + + + 32 - 4 + + + + + length:ItemCount + + + + + 4byte 32-26 + + + + + 4byte 32-28 + + + + + 4byte 32-30 + + + + + 4byte 32-32 + + + + + 可选的 + + + + + length:SampleCount + + + + + version == 0 + + + + + + + + + + 日期限制于2000年 + + + + + + + + + + + + ref + + + + + + + diff --git a/src/JT1078.FMp4/MessagePack/FMp4MessagePackReader.cs b/src/JT1078.FMp4/MessagePack/FMp4MessagePackReader.cs new file mode 100644 index 0000000..05e3c55 --- /dev/null +++ b/src/JT1078.FMp4/MessagePack/FMp4MessagePackReader.cs @@ -0,0 +1,48 @@ +using System; +using System.Buffers.Binary; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4.MessagePack +{ + public ref struct FMp4MessagePackReader + { + public ReadOnlySpan Reader { get; private set; } + public ReadOnlySpan SrcBuffer { get; } + public int ReaderCount { get; private set; } + public FMp4MessagePackReader(ReadOnlySpan srcBuffer) + { + SrcBuffer = srcBuffer; + ReaderCount = 0; + Reader = srcBuffer; + } + + public ushort ReadUInt16() + { + return BinaryPrimitives.ReadUInt16BigEndian(GetReadOnlySpan(2)); + } + + /// + /// + /// + /// + /// + public string ReadIso639() + { + int bits = ReadUInt16(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 3; i++) + { + int c = (bits >> (2 - i) * 5) & 0x1f; + sb.Append((char)(c + 0x60)); + } + return sb.ToString(); + } + + private ReadOnlySpan GetReadOnlySpan(int count) + { + ReaderCount += count; + return Reader.Slice(ReaderCount - count); + } + } +} diff --git a/src/JT1078.FMp4/MessagePack/FMp4MessagePackWriter.cs b/src/JT1078.FMp4/MessagePack/FMp4MessagePackWriter.cs new file mode 100644 index 0000000..7d80f21 --- /dev/null +++ b/src/JT1078.FMp4/MessagePack/FMp4MessagePackWriter.cs @@ -0,0 +1,79 @@ +using JT1078.FMp4.Buffers; +using System; +using System.Buffers.Binary; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4.MessagePack +{ + public ref struct FMp4MessagePackWriter + { + private FMp4BufferWriter writer; + public FMp4MessagePackWriter(Span buffer) + { + this.writer = new FMp4BufferWriter(buffer); + } + public byte[] FlushAndGetArray() + { + return writer.Written.ToArray(); + } + public void WriteByte(byte value) + { + var span = writer.Free; + span[0] = value; + writer.Advance(1); + } + public void WriteUInt16(ushort value) + { + BinaryPrimitives.WriteUInt16BigEndian(writer.Free, value); + writer.Advance(2); + } + public void WriteInt32(int value) + { + BinaryPrimitives.WriteInt32BigEndian(writer.Free, value); + writer.Advance(4); + } + public void WriteUInt64(ulong value) + { + BinaryPrimitives.WriteUInt64BigEndian(writer.Free, value); + writer.Advance(8); + } + public void WriteUInt32(uint value) + { + BinaryPrimitives.WriteUInt32BigEndian(writer.Free, value); + writer.Advance(4); + } + public void WriteArray(ReadOnlySpan src) + { + src.CopyTo(writer.Free); + writer.Advance(src.Length); + } + public void Skip(int count, out int position) + { + position = writer.WrittenCount; + byte[] tmp = new byte[count]; + tmp.CopyTo(writer.Free); + writer.Advance(count); + } + public int GetCurrentPosition() + { + return writer.WrittenCount; + } + + /// + /// ref + /// + /// + /// + public void WriteIso639(string language) + { + byte[] bytes= Encoding.UTF8.GetBytes(language); + int bits = 0; + for (int i = 0; i < 3; i++) + { + bits += (bytes[i] - 0x60) << (2 - i) * 5; + } + WriteUInt16((ushort)bits); + } + } +} diff --git a/src/JT1078.FMp4/Mp4Box.cs b/src/JT1078.FMp4/Mp4Box.cs new file mode 100644 index 0000000..3d39821 --- /dev/null +++ b/src/JT1078.FMp4/Mp4Box.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4 +{ + public abstract class Mp4Box + { + public const string UUID = "uuid"; + public Mp4Box(string boxType) + { + BoxType = boxType; + } + public Mp4Box(string boxType,string extendedType) + { + BoxType = boxType; + if(boxType == UUID) + { + UserType = extendedType; + } + } + public string BoxType { get; set; } + public string UserType { get; set; } + public uint Size { get; set; } + public ulong SizeLarge{get;set;} + } +} diff --git a/src/JT1078.FMp4/Samples/AVC1SampleEntry.cs b/src/JT1078.FMp4/Samples/AVC1SampleEntry.cs new file mode 100644 index 0000000..eda3bf1 --- /dev/null +++ b/src/JT1078.FMp4/Samples/AVC1SampleEntry.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4.Samples +{ + public class AVC1SampleEntry : VisualSampleEntry + { + public AVC1SampleEntry() : base("avc1") + { + } + public AVCConfigurationBox AVCConfigurationBox { get; set; } + + public MPEG4BitRateBox MPEG4BitRateBox { get; set; } + //todo:public MPEG4ExtensionDescriptorsBox MPEG4BitRateBox { get; set; } + } +} diff --git a/src/JT1078.FMp4/Samples/AudioSampleEntry.cs b/src/JT1078.FMp4/Samples/AudioSampleEntry.cs new file mode 100644 index 0000000..a92abb9 --- /dev/null +++ b/src/JT1078.FMp4/Samples/AudioSampleEntry.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4.Samples +{ + public abstract class AudioSampleEntry : SampleEntry + { + public AudioSampleEntry(string codingname) : base(codingname) + { + } + public uint[] Reserved1 { get; set; } = new uint[2]; + public ushort ChannelCount { get; set; } = 2; + public ushort SampleSize { get; set; } = 16; + public ushort PreDefined { get; set; } = 0; + public ushort Reserved2 { get; set; } = 0; + /// + /// { default samplerate of media}<<16; + /// + public uint Samplerate{ get; set; } + } +} diff --git a/src/JT1078.FMp4/Samples/AudioSampleGroupEntry.cs b/src/JT1078.FMp4/Samples/AudioSampleGroupEntry.cs new file mode 100644 index 0000000..fed102c --- /dev/null +++ b/src/JT1078.FMp4/Samples/AudioSampleGroupEntry.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4.Samples +{ + public abstract class AudioSampleGroupEntry : SampleGroupDescriptionEntry + { + public AudioSampleGroupEntry(uint groupingType) : base(groupingType) + { + } + } +} diff --git a/src/JT1078.FMp4/Samples/HintSampleEntry.cs b/src/JT1078.FMp4/Samples/HintSampleEntry.cs new file mode 100644 index 0000000..e95303c --- /dev/null +++ b/src/JT1078.FMp4/Samples/HintSampleEntry.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4.Samples +{ + public class HintSampleEntry : SampleEntry + { + public HintSampleEntry(string protocol) : base(protocol) + { + } + public List Data { get; set; } + } +} diff --git a/src/JT1078.FMp4/Samples/HintSampleGroupEntry.cs b/src/JT1078.FMp4/Samples/HintSampleGroupEntry.cs new file mode 100644 index 0000000..1bb68e2 --- /dev/null +++ b/src/JT1078.FMp4/Samples/HintSampleGroupEntry.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4.Samples +{ + public class HintSampleGroupEntry : SampleGroupDescriptionEntry + { + public HintSampleGroupEntry(uint groupingType) : base(groupingType) + { + } + } +} diff --git a/src/JT1078.FMp4/Samples/MetaDataSampleEntry.cs b/src/JT1078.FMp4/Samples/MetaDataSampleEntry.cs new file mode 100644 index 0000000..da6917a --- /dev/null +++ b/src/JT1078.FMp4/Samples/MetaDataSampleEntry.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4.Samples +{ + public abstract class MetaDataSampleEntry : SampleEntry + { + public MetaDataSampleEntry(string codingname) : base(codingname) + { + } + } +} diff --git a/src/JT1078.FMp4/Samples/SampleEntry.cs b/src/JT1078.FMp4/Samples/SampleEntry.cs new file mode 100644 index 0000000..31ff039 --- /dev/null +++ b/src/JT1078.FMp4/Samples/SampleEntry.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4.Samples +{ + public abstract class SampleEntry : Mp4Box + { + public SampleEntry(string boxType) : base(boxType) + { + } + public byte[] Reserved { get; set; } = new byte[6]; + public ushort DataReferenceIndex { get; set; } + } +} diff --git a/src/JT1078.FMp4/Samples/SampleGroupDescriptionEntry.cs b/src/JT1078.FMp4/Samples/SampleGroupDescriptionEntry.cs new file mode 100644 index 0000000..857858f --- /dev/null +++ b/src/JT1078.FMp4/Samples/SampleGroupDescriptionEntry.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4.Samples +{ + public abstract class SampleGroupDescriptionEntry + { + public uint GroupingType { get; set; } + + public SampleGroupDescriptionEntry(uint groupingType) + { + GroupingType = groupingType; + } + } +} diff --git a/src/JT1078.FMp4/Samples/TextMetaDataSampleEntry.cs b/src/JT1078.FMp4/Samples/TextMetaDataSampleEntry.cs new file mode 100644 index 0000000..129f848 --- /dev/null +++ b/src/JT1078.FMp4/Samples/TextMetaDataSampleEntry.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4.Samples +{ + public class TextMetaDataSampleEntry : SampleEntry + { + public TextMetaDataSampleEntry() : base("mett") + { + } + public string ContentEncoding { get; set; } + public string MimeFormat { get; set; } + public MPEG4BitRateBox BitRateBox { get; set; } + } +} diff --git a/src/JT1078.FMp4/Samples/URIMetaSampleEntry.cs b/src/JT1078.FMp4/Samples/URIMetaSampleEntry.cs new file mode 100644 index 0000000..30c676d --- /dev/null +++ b/src/JT1078.FMp4/Samples/URIMetaSampleEntry.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4.Samples +{ + public class URIMetaSampleEntry : SampleEntry + { + public URIMetaSampleEntry() : base("urim") + { + } + public URIBox TheLabel { get; set; } + public URIInitBox Init { get; set; } + public MPEG4BitRateBox BitRateBox { get; set; } + } +} diff --git a/src/JT1078.FMp4/Samples/VisualSampleEntry.cs b/src/JT1078.FMp4/Samples/VisualSampleEntry.cs new file mode 100644 index 0000000..065332f --- /dev/null +++ b/src/JT1078.FMp4/Samples/VisualSampleEntry.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4.Samples +{ + public abstract class VisualSampleEntry : SampleEntry + { + public VisualSampleEntry(string boxType) : base(boxType) + { + } + + public ushort PreDefined1 { get; set; } + public ushort Reserved1 { get; set; } + public uint[] PreDefined2 { get; set; } = new uint[3]; + public ushort Width { get; set; } + public ushort Height { get; set; } + public uint HorizreSolution { get; set; }= 0x00480000; + public uint VertreSolution { get; set; }= 0x00480000; + public uint Reserved3{ get; set; } + public ushort FrameCount { get; set; } = 1; + public string CompressorName { get; set; } + public ushort Depth { get; set; } = 0x0018; + public short PreDefined3 { get; set; } = 0x1111; + public CleanApertureBox Clap { get; set; } + public PixelAspectRatioBox Pasp { get; set; } + } +} diff --git a/src/JT1078.FMp4/Samples/VisualSampleGroupEntry.cs b/src/JT1078.FMp4/Samples/VisualSampleGroupEntry.cs new file mode 100644 index 0000000..d08ff79 --- /dev/null +++ b/src/JT1078.FMp4/Samples/VisualSampleGroupEntry.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4.Samples +{ + public abstract class VisualSampleGroupEntry : SampleGroupDescriptionEntry + { + public VisualSampleGroupEntry(uint groupingType) : base(groupingType) + { + } + } +} diff --git a/src/JT1078.FMp4/Samples/XMLMetaDataSampleEntry.cs b/src/JT1078.FMp4/Samples/XMLMetaDataSampleEntry.cs new file mode 100644 index 0000000..0e0b61e --- /dev/null +++ b/src/JT1078.FMp4/Samples/XMLMetaDataSampleEntry.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.FMp4.Samples +{ + public class XMLMetaDataSampleEntry : SampleEntry + { + public XMLMetaDataSampleEntry() : base("metx") + { + } + + public string ContentEncoding { get; set; } + public string Namespace { get; set; } + public string SchemaLocation { get; set; } + public MPEG4BitRateBox BitRateBox { get; set; } + } +} diff --git a/src/JT1078.Flv/Metadata/AVCDecoderConfigurationRecord.cs b/src/JT1078.Flv/Metadata/AVCDecoderConfigurationRecord.cs index 1d85bf8..bb16677 100644 --- a/src/JT1078.Flv/Metadata/AVCDecoderConfigurationRecord.cs +++ b/src/JT1078.Flv/Metadata/AVCDecoderConfigurationRecord.cs @@ -50,7 +50,7 @@ namespace JT1078.Flv.Metadata } } - #region Just for non-spec-conform encoders ref:org.mp4parser.boxes.iso14496.part15.AvcDecoderConfigurationRecord + #region Just for non-spec-conform encoders ref:org.JT1078.FMp4.boxes.iso14496.part15.AvcDecoderConfigurationRecord public const int LengthSizeMinusOnePaddingBits = 63; public const int NumberOfSequenceParameterSetsPaddingBits = 7; public const int ChromaFormatPaddingBits = 31; diff --git a/src/JT1078.sln b/src/JT1078.sln index 731bc9d..5362b6d 100644 --- a/src/JT1078.sln +++ b/src/JT1078.sln @@ -34,6 +34,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT1078.Hls", "JT1078.Hls\JT EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT1078.Hls.Test", "JT1078.Hls.Test\JT1078.Hls.Test.csproj", "{5564C20B-BFF4-4A2A-BDF2-C7427E93E993}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT1078.FMp4", "JT1078.FMp4\JT1078.FMp4.csproj", "{73F13894-0967-422C-8AC3-5EEF9189AAFC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT1078.FMp4.Test", "JT1078.FMp4.Test\JT1078.FMp4.Test.csproj", "{56E76D56-4CCC-401F-B25D-9AB41D58A10A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -188,6 +192,30 @@ Global {5564C20B-BFF4-4A2A-BDF2-C7427E93E993}.Release|x64.Build.0 = Release|Any CPU {5564C20B-BFF4-4A2A-BDF2-C7427E93E993}.Release|x86.ActiveCfg = Release|Any CPU {5564C20B-BFF4-4A2A-BDF2-C7427E93E993}.Release|x86.Build.0 = Release|Any CPU + {73F13894-0967-422C-8AC3-5EEF9189AAFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {73F13894-0967-422C-8AC3-5EEF9189AAFC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {73F13894-0967-422C-8AC3-5EEF9189AAFC}.Debug|x64.ActiveCfg = Debug|Any CPU + {73F13894-0967-422C-8AC3-5EEF9189AAFC}.Debug|x64.Build.0 = Debug|Any CPU + {73F13894-0967-422C-8AC3-5EEF9189AAFC}.Debug|x86.ActiveCfg = Debug|Any CPU + {73F13894-0967-422C-8AC3-5EEF9189AAFC}.Debug|x86.Build.0 = Debug|Any CPU + {73F13894-0967-422C-8AC3-5EEF9189AAFC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {73F13894-0967-422C-8AC3-5EEF9189AAFC}.Release|Any CPU.Build.0 = Release|Any CPU + {73F13894-0967-422C-8AC3-5EEF9189AAFC}.Release|x64.ActiveCfg = Release|Any CPU + {73F13894-0967-422C-8AC3-5EEF9189AAFC}.Release|x64.Build.0 = Release|Any CPU + {73F13894-0967-422C-8AC3-5EEF9189AAFC}.Release|x86.ActiveCfg = Release|Any CPU + {73F13894-0967-422C-8AC3-5EEF9189AAFC}.Release|x86.Build.0 = Release|Any CPU + {56E76D56-4CCC-401F-B25D-9AB41D58A10A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {56E76D56-4CCC-401F-B25D-9AB41D58A10A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {56E76D56-4CCC-401F-B25D-9AB41D58A10A}.Debug|x64.ActiveCfg = Debug|Any CPU + {56E76D56-4CCC-401F-B25D-9AB41D58A10A}.Debug|x64.Build.0 = Debug|Any CPU + {56E76D56-4CCC-401F-B25D-9AB41D58A10A}.Debug|x86.ActiveCfg = Debug|Any CPU + {56E76D56-4CCC-401F-B25D-9AB41D58A10A}.Debug|x86.Build.0 = Debug|Any CPU + {56E76D56-4CCC-401F-B25D-9AB41D58A10A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {56E76D56-4CCC-401F-B25D-9AB41D58A10A}.Release|Any CPU.Build.0 = Release|Any CPU + {56E76D56-4CCC-401F-B25D-9AB41D58A10A}.Release|x64.ActiveCfg = Release|Any CPU + {56E76D56-4CCC-401F-B25D-9AB41D58A10A}.Release|x64.Build.0 = Release|Any CPU + {56E76D56-4CCC-401F-B25D-9AB41D58A10A}.Release|x86.ActiveCfg = Release|Any CPU + {56E76D56-4CCC-401F-B25D-9AB41D58A10A}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -198,6 +226,7 @@ Global {9ADD82F9-E0B2-4263-8573-151F673BB33F} = {0655AF84-E578-409F-AB0E-B47E0D2F6814} {D13FE092-1D11-4545-A322-9F06BCDAC0FD} = {0655AF84-E578-409F-AB0E-B47E0D2F6814} {5564C20B-BFF4-4A2A-BDF2-C7427E93E993} = {0655AF84-E578-409F-AB0E-B47E0D2F6814} + {56E76D56-4CCC-401F-B25D-9AB41D58A10A} = {0655AF84-E578-409F-AB0E-B47E0D2F6814} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {FAE1656D-226F-4B4B-8C33-615D7E632B26}