// Appends to `samples'. // Returns nextStartTime. private static ulong ParseFragment(Fragment fragment, IList <MediaSample> samples, MediaStreamType type, ulong chunkStartTime) { // A fragment is a ``chunk'' (with a corresponding <c d=....> in its duration) in the ISM manifest file. TrackFragmentBox traf = fragment.moof.traf; if (traf.tfxd != null) { chunkStartTime = traf.tfxd.FragmentAbsoluteTime; } ulong nextStartTime = 0uL; if (traf.tfrf != null && traf.tfrf.Array.Length > 0u) { nextStartTime = traf.tfrf.Array[0].FragmentAbsoluteTime; } long sampleOffset = fragment.mdat.Start; uint defaultSampleSize = traf.tfhd.default_sample_size; uint sampleSize = defaultSampleSize; uint defaultSampleDuration = traf.tfhd.default_sample_duration; uint duration = defaultSampleDuration; ulong totalDuration = 0; uint sampleCount = traf.trun.sample_count; TrackRunBox.Element[] array = defaultSampleSize == 0u || defaultSampleDuration == 0u ? traf.trun.array : null; for (uint i = 0; i < sampleCount; ++i) { if (defaultSampleSize == 0u) { sampleSize = array[i].sample_size; } if (defaultSampleDuration == 0u) { duration = array[i].sample_duration; } // We add a few dozen MediaSample entries for a chunk. samples.Add(new MediaSample(sampleOffset, (int)sampleSize, chunkStartTime, /*isKeyFrame:*/ i == 0 || type == MediaStreamType.Audio)); chunkStartTime += (ulong)duration; totalDuration += (ulong)duration; sampleOffset += sampleSize; } return(nextStartTime != 0uL ? nextStartTime : chunkStartTime); }
/// <inheritdoc /> /// <summary> /// </summary> /// <param name="bytes"></param> /// <param name="start"></param> /// <param name="finish"></param> public MovieFragmentBox(byte[] bytes, int start, int finish) : base(Mp4Identifier.Moof) { while (start < finish) { var mp4Box = Mp4Utils.GetBox(bytes, ref start, finish); switch (mp4Box?.Mp4Identifier) { case null: continue; case Mp4Identifier.Traf: TrackFragmentBox = mp4Box as TrackFragmentBox; break; case Mp4Identifier.Mfhd: MovieFragmentHeaderBox = mp4Box as MovieFragmentHeaderBox; break; } } }