public override string ToString() { StringBuilder xml = new StringBuilder(); xml.Append(base.ToString()); xml.Append(TrackFragmentHeaderBox.ToString()); xml.Append(TrackFragmentRunBox.ToString()); xml.Append(IndependentAndDisposableSamplesBox.ToString()); xml.Append("</box>"); return(xml.ToString()); }
/// <summary> /// AddSampleStream /// This is the inverse of GetSampleStream above. /// Given a list of samples, assemble the TrackFragmentBox for this fragment. /// </summary> /// <param name="streamLocations"></param> /// <param name="trackTimeScale"></param> /// <param name="currMdatOffset"></param> public void AddSampleStream(List <StreamDataBlockInfo> streamLocations, uint trackTimeScale, ref ulong currMdatOffset) { // the time scale for every ISMV video fragment is 10,000,000 this._timeScale = trackTimeScale; _currentOffsetInBytes = 0UL; TrackFragmentBox tfrag = this.MovieFragmentBox.TrackFragmentBox; TrackFragmentHeaderBox tfhd = tfrag.TrackFragmentHeaderBox; // now we know the file offset to the data bits, so this is where we set the base data offset tfhd.BaseDataOffset = currMdatOffset; uint defaultSampleDuration = tfhd.DefaultSampleDuration; uint defaultSampleSize = 0; // tfhd.DefaultSampleSize; <-- don't use default sample size uint defaultSampleFlags = tfhd.DefaultSampleFlags; TrackFragmentRunBox fragRunBox = tfrag.TrackFragmentRunBox; IndependentAndDisposableSamplesBox stdpBox = tfrag.IndependentAndDisposableSamplesBox; uint trackID = tfhd.TrackId; uint trunFlags = fragRunBox.Flags; if (((trunFlags & (uint)TrackFragmentRunBoxFlags.SampleDurationPresent) == 0) != (defaultSampleDuration > 0)) { throw new Exception("Fragment: Trun flag sample duration present inconsistent with TrackFragmentHeaderBox data"); } if (((trunFlags & (uint)TrackFragmentRunBoxFlags.SampleSizePresent) == 0) != (defaultSampleSize > 0)) { throw new Exception("Fragment: Trun flag sample size present inconsistent with TrackFragmentHeaderBox data"); } if (((trunFlags & (uint)TrackFragmentRunBoxFlags.SampleFlagsPresent) == 0) != (defaultSampleFlags != 0)) { throw new Exception("Fragment: Trun flag sample flags present inconsistent with TrackFragmentHeaderBox data"); } foreach (StreamDataBlockInfo data in streamLocations) { if ((defaultSampleSize > 0) && (data.SliceSize != defaultSampleSize)) { throw new Exception("Samples do not have the same size in input stream when they're supposed to"); } fragRunBox.AddOneSample(data, trackTimeScale, defaultSampleSize, defaultSampleFlags, ref currMdatOffset); stdpBox.AddOneSample(data); } // after we write all the data bits, we should know the size of the mdata box if (currMdatOffset < tfhd.BaseDataOffset) { throw new Exception("Fragment: fragment mdat box size calculation error"); } this.MediaDataBox.Size += (ulong)(currMdatOffset - tfhd.BaseDataOffset); }
private void CollectSampleInfoStream() { this._currentOffsetInBytes = 0UL; this._listOfSampleInfo = new List <StreamDataBlockInfo>(); List <TrackFragmentRunSample> samples = MovieFragmentBox.TrackFragmentBox.TrackFragmentRunBox.Samples; TrackFragmentHeaderBox tfhd = MovieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox; if (tfhd.BaseDataOffset > 0L) { this._baseDataOffset = tfhd.BaseDataOffset; } StreamDataBlockInfo sampleInfo; while (null != (sampleInfo = GetOneSample(samples, tfhd))) { _listOfSampleInfo.Add(sampleInfo); } }
/// <summary> /// GetOneSample /// Get one frame or sample from the moof structures. There is no stss in a fragment, so we need to determine /// whether a frame is an IFrame or not by examining the IndependentAndDisposableSamplesBox. /// </summary> /// <param name="samples"></param> /// <param name="tfhd"></param> /// <returns></returns> private StreamDataBlockInfo GetOneSample(List<TrackFragmentRunSample> samples, TrackFragmentHeaderBox tfhd) { if (_currentFrame == samples.Count + _startIndex) return null; uint fixedFrameSizeInBytes = tfhd.DefaultSampleSize; if (fixedFrameSizeInBytes == 0) { fixedFrameSizeInBytes = samples[_currentFrame - _startIndex].SampleSize; } if (fixedFrameSizeInBytes == 0) // if it's still zero, then we have a problem throw new Exception("Sample size zero"); // is there enough data left to read the next frame? if (this._baseDataOffset + _currentOffsetInBytes + fixedFrameSizeInBytes > (ulong)_reader.BaseStream.Length) return null; // currently DRM is not yet supported in this GetFrame routine, unlike the FragmentedMp4ParserImplementation // if ((this.m_drmIVOffsets != null) && (this.m_numDrmIVs > this.m_frameIndex)) // { // length = this.m_drmIVSizes[this.m_frameIndex]; // destinationArray = new byte[length]; // Array.Copy(this.m_headerBuffer, this.m_drmIVOffsets[this.m_frameIndex], destinationArray, 0, length); // } uint fixedDuration = tfhd.DefaultSampleDuration; if (samples[_currentFrame - _startIndex].SampleDuration != 0) { fixedDuration = samples[_currentFrame - _startIndex].SampleDuration; } if (_timeScale > 0) // time scale is 1 for ODS assets { // scale time fixedDuration = (uint)TimeArithmetic.ConvertToStandardUnit(_timeScale, fixedDuration); } StreamDataBlockInfo oneFrameData = new StreamDataBlockInfo(); //RawFrameData ans = new RawFrameData(CurrentTime, currentOffsetInBytes, fixedFrameSizeInBytes, fixedDuration, destinationArray); oneFrameData.SliceDuration = fixedDuration; oneFrameData.SliceSize = (int)fixedFrameSizeInBytes; oneFrameData.StreamOffset = this._baseDataOffset + _currentOffsetInBytes; GetSliceTypeAndFrameNum(oneFrameData); // for ISM, TimeStampNew will always have a value oneFrameData.TimeStampNew = (ulong)_currentTime; oneFrameData.index = _currentFrame; _currentOffsetInBytes += fixedFrameSizeInBytes; _currentTime += fixedDuration; _currentFrame++; return oneFrameData; }
/// <summary> /// GetOneSample /// Get one frame or sample from the moof structures. There is no stss in a fragment, so we need to determine /// whether a frame is an IFrame or not by examining the IndependentAndDisposableSamplesBox. /// </summary> /// <param name="samples"></param> /// <param name="tfhd"></param> /// <returns></returns> private StreamDataBlockInfo GetOneSample(List <TrackFragmentRunSample> samples, TrackFragmentHeaderBox tfhd) { if (_currentFrame == samples.Count + _startIndex) { return(null); } uint fixedFrameSizeInBytes = tfhd.DefaultSampleSize; if (fixedFrameSizeInBytes == 0) { fixedFrameSizeInBytes = samples[_currentFrame - _startIndex].SampleSize; } if (fixedFrameSizeInBytes == 0) // if it's still zero, then we have a problem { throw new Exception("Sample size zero"); } // is there enough data left to read the next frame? if (this._baseDataOffset + _currentOffsetInBytes + fixedFrameSizeInBytes > (ulong)_reader.BaseStream.Length) { return(null); } // currently DRM is not yet supported in this GetFrame routine, unlike the FragmentedMp4ParserImplementation // if ((this.m_drmIVOffsets != null) && (this.m_numDrmIVs > this.m_frameIndex)) // { // length = this.m_drmIVSizes[this.m_frameIndex]; // destinationArray = new byte[length]; // Array.Copy(this.m_headerBuffer, this.m_drmIVOffsets[this.m_frameIndex], destinationArray, 0, length); // } uint fixedDuration = tfhd.DefaultSampleDuration; if (samples[_currentFrame - _startIndex].SampleDuration != 0) { fixedDuration = samples[_currentFrame - _startIndex].SampleDuration; } if (_timeScale > 0) // time scale is 1 for ODS assets { // scale time fixedDuration = (uint)TimeArithmetic.ConvertToStandardUnit(_timeScale, fixedDuration); } StreamDataBlockInfo oneFrameData = new StreamDataBlockInfo(); //RawFrameData ans = new RawFrameData(CurrentTime, currentOffsetInBytes, fixedFrameSizeInBytes, fixedDuration, destinationArray); oneFrameData.SliceDuration = fixedDuration; oneFrameData.SliceSize = (int)fixedFrameSizeInBytes; oneFrameData.StreamOffset = this._baseDataOffset + _currentOffsetInBytes; GetSliceTypeAndFrameNum(oneFrameData); // for ISM, TimeStampNew will always have a value oneFrameData.TimeStampNew = (ulong)_currentTime; oneFrameData.index = _currentFrame; _currentOffsetInBytes += fixedFrameSizeInBytes; _currentTime += fixedDuration; _currentFrame++; return(oneFrameData); }