Example #1
0
        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());
        }
Example #2
0
        /// <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);
        }
Example #3
0
        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);
            }
        }
Example #4
0
        /// <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;
        }
Example #5
0
        /// <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);
        }