Beispiel #1
0
        public MediaBox(IsochronousTrackInfo trackInfo)
            : this()
        {
            ulong scaledDuration = (ulong)TimeArithmetic.ConvertToTimeScale(trackInfo.TimeScale, trackInfo.DurationIn100NanoSecs);

            MediaHeaderBox = new MediaHeaderBox(this, scaledDuration, trackInfo.TimeScale);
            this.Size     += MediaHeaderBox.Size;
            Codec codec = null;

            if (trackInfo.GetType() == typeof(RawAudioTrackInfo))
            {
                RawAudioTrackInfo audioInfo = (RawAudioTrackInfo)trackInfo;
                codec = new Codec(CodecTypes.Audio);
                codec.PrivateCodecData = audioInfo.CodecPrivateData;
            }
            else if (trackInfo.GetType() == typeof(RawVideoTrackInfo))
            {
                RawVideoTrackInfo videoInfo = (RawVideoTrackInfo)trackInfo;
                codec = new Codec(CodecTypes.Video);
                codec.PrivateCodecData = videoInfo.CodecPrivateData;
            }
            HandlerReferenceBox = new HandlerReferenceBox(this, codec);
            this.Size          += HandlerReferenceBox.Size;
            MediaInformationBox = new MediaInformationBox(this, trackInfo);
            // MediaInformationBox.Size is indeterminate at this time; it is determined only during SampleTableBox.FinalizeBox
        }
Beispiel #2
0
        public MovieMetadataBox(List <IsochronousTrackInfo> trackInfos, float rate, float volume, uint[] matrix)
            : base(BoxTypes.Movie)
        {
            // initialize movie duration to zero, then increment it for every slice that is written
            ulong scaledDuration = (ulong)TimeArithmetic.ConvertToTimeScale(trackInfos[0].MovieTimeScale, trackInfos[0].MovieDurationIn100NanoSecs);

            MovieHeaderBox = new MovieHeaderBox(trackInfos[0].MovieTimeScale, scaledDuration, rate, volume, matrix);
            this.Size     += MovieHeaderBox.Size;
            TrackBoxes     = new TrackBox[trackInfos.Count]; // may have more than 2 tracks
            // MovieExtendsBox should only exist if this is a fragment
            if (trackInfos[0].IsFragment)
            {
                MovieExtendsBox = new MovieExtendsBox(this, trackInfos);
                this.Size      += MovieExtendsBox.Size;
            }
        }
Beispiel #3
0
        public TrackBox(IsochronousTrackInfo trackInfo)
            : this()
        {
            float height = 0.0f;
            float width  = 0.0f;

            if (trackInfo is RawVideoTrackInfo)
            {
                // set the TRACK width, which may differ from SampleDescription width and height, depending on Aspect Ratio
                RawVideoTrackInfo rvti = (RawVideoTrackInfo)trackInfo;
                height = rvti.Height;
                width  = rvti.Width * ((float)rvti.AspectRatioX / (float)rvti.AspectRatioY);
            }
            ulong scaledDuration = (ulong)TimeArithmetic.ConvertToTimeScale(trackInfo.MovieTimeScale, trackInfo.DurationIn100NanoSecs);

            TrackHeaderBox = new TrackHeaderBox((uint)trackInfo.TrackID, scaledDuration, height, width);
            // TrackHeaderBox = new TrackHeaderBox((uint)trackInfo.TrackID, (trackInfo.Duration * oneSecondTicks) / trackInfo.TimeScale, height, width);
            this.Size += TrackHeaderBox.Size;

            // skip the TrackReferenceBox for now
            //TrackReferenceBox = new TrackReferenceBox((uint)trackInfo.TrackID);
            //this.Size += TrackReferenceBox.Size;

#if EDTS_OUT
            EdtsBox = (EdtsBox)trackInfo.GetEdtsBox();
            if (EdtsBox != null)
            {
                this.Size += EdtsBox.Size;
                EdtsBox.ScaleToTarget(trackInfo.MovieTimeScale, trackInfo.TimeScale);
            }
#endif

            MediaBox = new MediaBox(trackInfo);
            // MediaBox.Size can only be determined during FinalizeBox
            // NOTE: NO Esds Box
        }
Beispiel #4
0
        private uint SampleCountInLastBatch = 0; // last batch sample count for this trak box (this is independent of the other trak box)

        /// <summary>
        /// InitSampleTableBoxFromStreamLocations
        /// Initialize the boxes that point to where the payload bits are, without writing them out to final destination file yet.
        /// Major change (06/06/2012): favor creating new chunks over accumulating slices in a chunk.
        /// We take it to the extreme here, like VLC does it: we create a new chunk for every slice/sample.
        /// What this does is make the stsc box small, but the stco box very large. The advantage is that
        /// every slice now has an offset into mdat (and the slice crawler can't possibly go out of sync).
        /// </summary>
        /// <param name="streamLocations">List of StreamDataBlockInfo extracted from source stream, possibly using InitSampleStreamFromSampleTableBox above.</param>
        public void InitSampleTableBoxFromStreamLocations(List <StreamDataBlockInfo> streamLocations, ref ulong currMdatOffset)
        {
            // if this is the first call, create temp files
            if (SttsCountsWriter == null)
            {
                CreateTempFiles();
            }

            if (CompositionTimeToSample == null && (CTTSOut) && (streamLocations.Any(d => (d.CTS > 0UL) || (d.SliceType == SliceType.BFrame))))
            {
                CompositionTimeToSample = new CompositionTimeToSample(this);
            }

            if (streamLocations.Count == 0)
            {
                throw new Exception("InitSampleTableBoxFromStreamLocations: SampleStreamLocations list empty.");
            }
            bool needNewChunk = true;

            foreach (StreamDataBlockInfo sample in streamLocations)
            {
                uint scaledDuration = (uint)TimeArithmetic.ConvertToTimeScale(parent.parent.MediaHeaderBox.TimeScale, sample.SliceDuration);
                if (LastDuration == 0)
                {
                    sampleCountInStts = 1;
                }
                else if (LastDuration == scaledDuration)
                {
                    sampleCountInStts++;
                }
                else
                {
                    WriteToSttsTempFile();
                    sampleCountInStts = 1; // this one for which duration is different counts as one
                }
                LastDuration = scaledDuration;
                //TimeTicks += sample.SliceDuration;
                if (sample.SliceType == SliceType.IFrame)
                {
                    SyncSampleMapWriter.Write(SampleIndex); // if the SyncSampleMapStream has zero length when all is done, then its box should be null
                    CurrSyncSampleMapCount++;
                }
                // compute CTTS from TimeStamp and CTS
                if (CompositionTimeToSample != null)
                {
                    // CTS = Composition Time of the Sample, so these values are ever-increasing
                    // CTTS = Composition Time relative to Time of the Sample, so these are really either 0 or some multiple of the typical sample duration

                    // CTTS values for an i-frame, for example, is always zero, as its composition time relative to the sample:
                    // CTTS-iframe = SampleTime - CTS = Always 0

                    if (sample.SliceType == SliceType.IFrame)
                    {
                        // relative time for an iframe is always 0
                        CompositionTimeToSample.AddEntry(0);
                        LastSynchTime = 0;
                    }
                    else
                    {
                        //if (sample.TimeStampNew.HasValue) {
                        //  // relative time for a d-frame is always 0
                        //  uint TimeFromLastSample = (uint)TimeArithmetic.ConvertToTimeScale(parent.parent.MediaHeaderBox.TimeScale, sample.SliceDuration);
                        //  CompositionTimeToSample.AddEntry((uint)TimeFromLastSample);
                        //} else {
                        //  // this means we are a b-frame
                        //  CompositionTimeToSample.AddEntry((uint)uint.MaxValue);
                        //}


                        if (!sample.TimeStampNew.HasValue || sample.SliceType == SliceType.BFrame)
                        {
                            // this means we are a b-frame
                            uint TimeFromLastSample = (uint)TimeArithmetic.ConvertToTimeScale(parent.parent.MediaHeaderBox.TimeScale, sample.SliceDuration);
                            // we get further from a sync time for each consecutive b-frame we have
                            // as you can see above if we encounter an i or d frame we snap back to a delta of 0
                            LastSynchTime += TimeFromLastSample;
                            CompositionTimeToSample.AddEntry((uint)LastSynchTime);
                        }
                        else if (sample.TimeStampNew.HasValue)
                        {
                            // relative time for a d-frame is always 0
                            CompositionTimeToSample.AddEntry(0);
                            LastSynchTime = 0;
                        }
                    }
                }

                // determine which chunk to put this sample in
                SampleSizeWriter.Write((uint)sample.SliceSize);
                SampleToChunkBox.SetFileOffsetForChunk(SampleIndex, (uint)sample.SliceSize, 1u /* (uint)streamLocations.Count */, needNewChunk, ref currMdatOffset);
                needNewChunk = true; // always create a new chunk, thereby having only a single slice in every chunk (as in VLC output)
                SampleIndex++;
            }

            // set last count
            SampleCountInLastBatch = (uint)streamLocations.Count;
        }