void InitializeSampleCountsInChunk(int trackIndex) { SampleCountsInChunk[trackIndex] = new List <uint>(); SampleCountsInChunk[trackIndex].Clear(); TrackBox[] tracks = this.mmb.TrackBoxes; SampleTableBox sampleTable = tracks[trackIndex].MediaBox.MediaInformationBox.SampleTableBox; SampleToChunkBox stsc = sampleTable.SampleToChunkBox; uint totalChunks = sampleTable.ChunkOffSetBox.EntryCount; int chunkEntryIndex; uint samplesPerChunk; for (chunkEntryIndex = 0; chunkEntryIndex < (stsc.EntryCount - 1); chunkEntryIndex++) { for (uint chunkCount = stsc.ChunkEntries[chunkEntryIndex].firstChunk; chunkCount < stsc.ChunkEntries[chunkEntryIndex + 1].firstChunk; chunkCount++) { samplesPerChunk = stsc.ChunkEntries[chunkEntryIndex].samplesPerChunk; SampleCountsInChunk[trackIndex].Add(samplesPerChunk); } } uint remainingChunkCount = (uint)sampleTable.ChunkOffSetBox.ChunkOffsets.Length - stsc.ChunkEntries[chunkEntryIndex].firstChunk + 1; samplesPerChunk = stsc.ChunkEntries[chunkEntryIndex].samplesPerChunk; for (; remainingChunkCount > 0; remainingChunkCount--) { SampleCountsInChunk[trackIndex].Add(samplesPerChunk); } }
public override string ToString() { StringBuilder xml = new StringBuilder(); xml.Append(base.ToString()); if (SoundMediaHeaderBox != null) { xml.Append(SoundMediaHeaderBox.ToString()); } if (VideoMediaHeaderBox != null) { xml.Append(VideoMediaHeaderBox.ToString()); } if (DataInformationBox != null) { xml.Append(DataInformationBox.ToString()); } if (SampleTableBox != null) { xml.Append(SampleTableBox.ToString()); } if (NullMediaHeaderBox != null) { xml.Append(NullMediaHeaderBox.ToString()); } xml.Append("</box>"); return(xml.ToString()); }
public SampleSizeBox(SampleTableBox inParent) : base(BoxTypes.SampleSize) { parent = inParent; sampleCount = 0; sampleSize = 0; this.Size += 8UL; // default sample size plus sample count }
/// <summary> /// Read - read a MediaInformationBox /// We go in a loop with an if-else statement, so ordering of sub-boxes does not matter. /// </summary> /// <param name="reader"></param> public override void Read(BoxReader reader) { using (new SizeChecker(this, reader)) { base.Read(reader); while (reader.BaseStream.Position < (long)(this.Size + this.Offset)) { long pos = reader.BaseStream.Position; Box test = new Box(BoxTypes.Any); test.Read(reader); reader.BaseStream.Seek(pos, System.IO.SeekOrigin.Begin); pos = reader.BaseStream.Position; if (test.Type == BoxTypes.SoundMediaHeader) { this.SoundMediaHeaderBox = new SoundMediaHeaderBox(); SoundMediaHeaderBox.Read(reader); } else if (test.Type == BoxTypes.VideoMediaHeader) { this.VideoMediaHeaderBox = new VideoMediaHeaderBox(); VideoMediaHeaderBox.Read(reader); } else if (test.Type == BoxTypes.DataInformation) { this.DataInformationBox = new DataInformationBox(); DataInformationBox.Read(reader); } else if (test.Type == BoxTypes.SampleTable) { this.SampleTableBox = new SampleTableBox(this); SampleTableBox.Read(reader); } else if (test.Type == BoxTypes.NullMediaHeader) { this.NullMediaHeaderBox = new NullMediaHeaderBox(); NullMediaHeaderBox.Read(reader); } else { test.Read(reader); Debug.WriteLine(string.Format("Unknown box type {0} in MediaInformationBox (minf)", test.Type.ToString())); } } } }
public MediaInformationBox(MediaBox inParent, IsochronousTrackInfo trackInfo) : this(inParent) { if (trackInfo.GetType() == typeof(RawAudioTrackInfo)) { SoundMediaHeaderBox = new SoundMediaHeaderBox(); this.Size += SoundMediaHeaderBox.Size; } else if (trackInfo.GetType() == typeof(RawVideoTrackInfo)) { VideoMediaHeaderBox = new VideoMediaHeaderBox(); this.Size += VideoMediaHeaderBox.Size; } DataInformationBox = new DataInformationBox(); this.Size += DataInformationBox.Size; SampleTableBox = new SampleTableBox(this, trackInfo); // Size for SampleTableBox is determined only during SampleTableBox.FinalizeBox }
/// <summary> /// Write - write out MediaInforationBox with the following order of sub-boxes: /// SoundMediaHeaderBox or VideoMediaHeaderBox /// DataInformationBox /// SampleTableBox /// </summary> /// <param name="writer"></param> public override void Write(BoxWriter writer) { using (new SizeCalculator(this, writer)) { base.Write(writer); if (SoundMediaHeaderBox != null) { SoundMediaHeaderBox.Write(writer); } if (VideoMediaHeaderBox != null) { VideoMediaHeaderBox.Write(writer); } DataInformationBox.Write(writer); if (SampleTableBox != null) { SampleTableBox.Write(writer); } } }
public override List <StreamDataBlockInfo> PrepareSampleReading(UInt64 inStartSampleTime, UInt64 inEndSampleTime, ref ulong lastEnd) { //lastEnd = 0UL; string trackType = this.TrackBox.MediaBox.HandlerReferenceBox.Name; // FIXME: use this to set SampleType below SampleTableBox stb = this.TrackBox.MediaBox.MediaInformationBox.SampleTableBox; // if we are missing any of three box types, then we can't continue if ((stb.SampleSizeBox == null) || (stb.SampleToChunkBox == null) || (stb.ChunkOffSetBox == null)) { throw new Exception("MP4 Track is non-standard (missing Sample Size, Sample to Chunk, or Chunk Offset)"); } // either ctts or stts must be present also because we index on time if (stb.DecodingTimeToSampleBox == null) { throw new Exception("MP4 Track is missing Decoding Time To Sample box"); } //float scale = (float)(TimeScale) / TimeSpan.FromSeconds(1.0).Ticks; return(stb.InitSampleStreamFromSampleTableBox(this.TrackBox.EdtsBox, TimeScale, inStartSampleTime, inEndSampleTime, ref lastEnd)); }
public override void PrepareSampleWriting(List <StreamDataBlockInfo> streamLocations, ref ulong currMdatOffset) { SampleTableBox stb = this.TrackBox.MediaBox.MediaInformationBox.SampleTableBox; stb.InitSampleTableBoxFromStreamLocations(streamLocations, ref currMdatOffset); }
public ChunkOffSetBox(SampleTableBox inParent) : base(BoxTypes.ChunkOffset) { parent = inParent; this.Size += 4UL; // entryCount }
public DecodingTimeToSampleBox(SampleTableBox inParent) : base(BoxTypes.TimeToSample) { parent = inParent; this.Size += 4UL; // EntryCount }
public SampleToChunkBox(SampleTableBox inParent) : base(BoxTypes.SampleToChunk) { parent = inParent; this.Size += 4UL; // EntryCount }
public SampleDescriptionsBox(SampleTableBox inParent) : base(BoxTypes.SampleDescription) { parent = inParent; }
public CompositionTimeToSample(SampleTableBox inParent) : base(BoxTypes.CompositionOffset) { parent = inParent; this.Size += 4UL; // +EntryCount * 8; }
public void FinalizeBox() { SampleTableBox.FinalizeBox(); this.Size += SampleTableBox.Size; }
public SampleDescriptionsBox(SampleTableBox inParent, IsochronousTrackInfo trackInfo) : this(inParent) { EntryCount = 1; // FIXME: assume only one sample entry Entries = new SampleEntry[EntryCount]; this.Size += 4UL; BoxType btype; if (trackInfo is RawAudioTrackInfo) { RawAudioTrackInfo rati = (RawAudioTrackInfo)trackInfo; switch (rati.PayloadType) { case AudioPayloadType.aac: case AudioPayloadType.mp4a: btype = BoxTypes.Mp4a; break; case AudioPayloadType.wma: btype = BoxTypes.Wma; break; case AudioPayloadType.samr: // 3gp audio btype = BoxTypes.Samr; break; default: throw new Exception(string.Format("Unknown audio track payload type: {0}", rati.PayloadType)); } //btype = (rati.PayloadType == AudioPayloadType.wma) ? BoxTypes.Wma : ((rati.PayloadType == AudioPayloadType.mp4a) ? BoxTypes.Mp4a : BoxTypes.AudioSampleEntry); Entries[0] = new AudioSampleEntry(btype, (RawAudioTrackInfo)trackInfo); this.Size += Entries[0].Size; } else if (trackInfo is RawVideoTrackInfo) { RawVideoTrackInfo rvti = (RawVideoTrackInfo)trackInfo; switch (rvti.PayloadType) { case VideoPayloadType.vc1: btype = BoxTypes.Vc1; break; case VideoPayloadType.mp4v: btype = BoxTypes.Mp4v; break; case VideoPayloadType.mjpeg: btype = BoxTypes.VisualSampleEntry; // FIXME: this is not correct break; case VideoPayloadType.jpeg: btype = BoxTypes.VisualSampleEntry; // FIXME: this is not correct break; case VideoPayloadType.avc1: btype = BoxTypes.Avc1; break; default: btype = BoxTypes.Any; break; } Entries[0] = new VisualSampleEntry(btype, (RawVideoTrackInfo)trackInfo); this.Size += Entries[0].Size; } else //Entries[0] = new UnknownEntry(BoxTypes.UnknownSampleEntry); throw new Exception("unknown track type"); // error out instead of constructing an unknwon entry }