Example #1
0
        public static float CalculateTimeScale(MovieMetadataBox moovBox, TrackBox trackBox)
        {
            MovieHeaderBox headerBox     = moovBox.MovieHeaderBox;
            ulong          moovDuration  = headerBox.Duration;
            uint           moovTimeScale = headerBox.TimeScale;

            MediaHeaderBox mdhdBox        = trackBox.MediaBox.MediaHeaderBox;
            ulong          mediaDuration  = mdhdBox.Duration;
            float          mediaTimeScale = mdhdBox.TimeScale;

            // Note that time scales may differ between moov and each media (because sampling rate can differ?)
            moovDuration  = moovDuration / moovTimeScale;
            mediaDuration = (ulong)(mediaDuration / mediaTimeScale);
            long diff = Math.Abs((long)moovDuration - (long)mediaDuration);

            if ((diff * diff) > (long)((moovDuration * moovDuration) / 100)) // must be within 1%
            {
                throw new Exception("Media Box Header inconsistent with Track Header");
            }

            // scale to 10,000,000 ticks per second
            mediaTimeScale /= TimeSpan.FromSeconds(1.0).Ticks;

            if (mediaTimeScale == 0)
            {
                throw new Exception("MP4VideoTrack: media time scale is zero");
            }

            return(mediaTimeScale);
        }
Example #2
0
        public static float CalculateTimeScale(MovieMetadataBox moovBox, TrackBox trackBox)
        {
            MovieHeaderBox headerBox = moovBox.MovieHeaderBox;
            ulong moovDuration = headerBox.Duration;
            uint moovTimeScale = headerBox.TimeScale;

            MediaHeaderBox mdhdBox = trackBox.MediaBox.MediaHeaderBox;
            ulong mediaDuration = mdhdBox.Duration;
            float mediaTimeScale = mdhdBox.TimeScale;

            // Note that time scales may differ between moov and each media (because sampling rate can differ?)
            moovDuration = moovDuration / moovTimeScale;
            mediaDuration = (ulong)(mediaDuration / mediaTimeScale);
            long diff = Math.Abs((long)moovDuration - (long)mediaDuration);
            if ((diff * diff) > (long)((moovDuration * moovDuration) / 100)) // must be within 1%
                throw new Exception("Media Box Header inconsistent with Track Header");

            // scale to 10,000,000 ticks per second
            mediaTimeScale /= TimeSpan.FromSeconds(1.0).Ticks;

            if (mediaTimeScale == 0)
                throw new Exception("MP4VideoTrack: media time scale is zero");

            return mediaTimeScale;
        }
Example #3
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;
            }
        }
Example #4
0
        /// <summary>
        /// FinalizeStream
        /// 1. Write out ftyp
        /// 2. Finalize stbl box in each trak box (call mmb.FinalizeBox)
        /// 3. Calculate size of ftyp + moov + header of mdat boxes
        /// 4. Fix fileoffsets in stbl chunk boxes (NOTE: interleaving means we should have more than one chunk)
        /// 5. Write out all of moov box
        /// 6. Create and write out mdat header only, with correct byte count
        /// 7. Read from mdat sample file and write to destination mdat
        /// </summary>
        public override void FinalizeStream()
        {
            // step 0
            // flush all remaining slices
            if (this.CachingEnabled)
            {
                foreach (GenericMediaTrack track in this.MediaTracks)
                {
                    if ((track.SampleStreamLocations != null) && (track.SampleStreamLocations.Count > 0))
                    {
                        ulong _currMDatOffset = CurrMDatOffset;
                        track.TrackFormat.PrepareSampleWriting(track.SampleStreamLocations, ref _currMDatOffset);
                        CurrMDatOffset = _currMDatOffset;
                        this.WriteSamples(track.SampleStreamLocations.Cast <Slice>(), track.Codec.CodecType);
                    }
                }
            }
            // set duration of movie (must be set to duration of longest track)
            TrackBox trkBox = this.mmb.TrackBoxes.FirstOrDefault(box => box.MediaBox.HandlerReferenceBox.HandlerType.Equals("vide"));
            decimal  vDuration;

            if (trkBox == null)
            {
                vDuration = 0;
            }
            else
            {
                vDuration = (decimal)trkBox.MediaBox.MediaHeaderBox.Duration / trkBox.MediaBox.MediaHeaderBox.TimeScale;
            }

            trkBox = this.mmb.TrackBoxes.FirstOrDefault(box => box.MediaBox.HandlerReferenceBox.HandlerType.Equals("soun"));
            decimal aDuration;

            if (trkBox == null)
            {
                aDuration = 0;
            }
            else
            {
                aDuration = (decimal)trkBox.MediaBox.MediaHeaderBox.Duration / trkBox.MediaBox.MediaHeaderBox.TimeScale;
            }

            if (vDuration < aDuration)
            {
                this.mmb.MovieHeaderBox.Duration = (ulong)(aDuration * this.mmb.MovieHeaderBox.TimeScale);
            }
            else
            {
                this.mmb.MovieHeaderBox.Duration = (ulong)(vDuration * this.mmb.MovieHeaderBox.TimeScale);
            }

            // step 1
            this.ftb.Write(m_writer);

            // step 2
            this.mmb.FinalizeBox();

            // step 3
            int headerSize = (int)(this.ftb.Size + this.mmb.Size);

            // step 4
            foreach (TrackBox tbox in this.mmb.TrackBoxes)
            {
                tbox.MediaBox.MediaInformationBox.SampleTableBox.ChunkOffSetBox.Fixup(headerSize);
            }

            // step 5
            this.mmb.Write(m_writer);

            // step 6
            this.MediaDataBoxList = new List <MediaDataBox>(); // there is only one mdat for non-fragmented streams.
            MediaDataBox mdat = new MediaDataBox();

            // because the mdat is the last box in the file, we can set its size to 0
            // if mdat is too large, set its size filed to zero:
            // this gets WMP to work, but VLC and QT doesn't like it.
            mdat.Size += (ulong)tempMdat.Length;
            if (mdat.Size > uint.MaxValue)
            {
                mdat.Size = 0UL; // += (ulong)tempMdat.Length;
            }
            this.MediaDataBoxList.Add(mdat);

            // step 7
            tempMdat.Position = 0L;
            mdat.Write(m_writer, tempMdat);

            // close file
            Close();
        }
Example #5
0
 public MediaBox(TrackBox inParent)
     : base(BoxTypes.Media)
 {
     parent = inParent;
 }
Example #6
0
        public override void Read(BoxReader reader)
        {
            long testpos = reader.BaseStream.Position;

            using (new SizeChecker(this, reader)) {
                base.Read(reader);
                MovieHeaderBox.Read(reader);

                // Don't assume any order in the boxes within this after the header.
                // (The order depends on the brand.)
                int        tbcount = 0;
                TrackBox[] tmpTBs  = new TrackBox[10];
                while (reader.BaseStream.Position < (long)(this.Size + this.Offset))
                {
                    long pos = reader.BaseStream.Position;

                    Box tmpBox = new Box(BoxTypes.Any);
                    tmpBox.Read(reader);

                    reader.BaseStream.Position = pos;

                    if (tmpBox.Type == BoxTypes.Track)
                    {
                        TrackBox tb = new TrackBox(this, MovieHeaderBox.TimeScale);
                        tb.Read(reader);
                        tmpTBs[tbcount] = tb;
                        tbcount++;
                    }

                    else if (tmpBox.Type == BoxTypes.MovieExtends)
                    {
                        MovieExtendsBox = new MovieExtendsBox(this);
                        MovieExtendsBox.Read(reader);
                    }

                    else if (tmpBox.Type == BoxTypes.ObjectDescriptor) // iods
                    {
                        _objectDescriptor = new ObjectDescriptorBox();
                        _objectDescriptor.Read(reader);
                    }

                    else if (tmpBox.Type == BoxTypes.UserData) // udta
                    {
                        _userData = new UserDataBox();
                        _userData.Read(reader);
                    }

                    // some cases below for things we currently ignore, thus we skip over them...
                    else
                    {
                        byte[] buffer = new byte[tmpBox.Size];
                        reader.Read(buffer, 0, (int)tmpBox.Size);
                        //reader.BaseStream.Position = (long)(tmpBox.Size + tmpBox.Offset); // ignore for now
                        Debug.WriteLine(string.Format("Unknown box type {0} in MovieMetadataBox (this), skipped", tmpBox.Type.ToString()));
                    }
                }

                TrackBoxes = new TrackBox[tbcount];
                for (int i = 0; i < tbcount; i++)
                {
                    TrackBoxes[i] = tmpTBs[i];
                }
            }
        }
Example #7
0
 public void AddTrackBox(TrackBox tbox)
 {
     TrackBoxes[MovieHeaderBox.NextTrackID - 1] = tbox;
     tbox.TrackHeaderBox.TrackID = MovieHeaderBox.NextTrackID;
     MovieHeaderBox.NextTrackID++;
 }
Example #8
0
        public override void Read(BoxReader reader)
        {
            long testpos = reader.BaseStream.Position;
              using (new SizeChecker(this, reader)) {
            base.Read(reader);
            MovieHeaderBox.Read(reader);

            // Don't assume any order in the boxes within this after the header.
            // (The order depends on the brand.)
            int tbcount = 0;
            TrackBox[] tmpTBs = new TrackBox[10];
            while (reader.BaseStream.Position < (long)(this.Size + this.Offset)) {
              long pos = reader.BaseStream.Position;

              Box tmpBox = new Box(BoxTypes.Any);
              tmpBox.Read(reader);

              reader.BaseStream.Position = pos;

              if (tmpBox.Type == BoxTypes.Track)
              {
              TrackBox tb = new TrackBox(this, MovieHeaderBox.TimeScale);
              tb.Read(reader);
              tmpTBs[tbcount] = tb;
              tbcount++;
              }

              else if (tmpBox.Type == BoxTypes.MovieExtends)
              {
              MovieExtendsBox = new MovieExtendsBox(this);
              MovieExtendsBox.Read(reader);
              }

              else if (tmpBox.Type == BoxTypes.ObjectDescriptor) // iods
              {
            _objectDescriptor = new ObjectDescriptorBox();
            _objectDescriptor.Read(reader);
              }

              else if (tmpBox.Type == BoxTypes.UserData) // udta
              {
            _userData = new UserDataBox();
            _userData.Read(reader);
              }

              // some cases below for things we currently ignore, thus we skip over them...
              else
              {
            byte[] buffer = new byte[tmpBox.Size];
            reader.Read(buffer, 0, (int)tmpBox.Size);
            //reader.BaseStream.Position = (long)(tmpBox.Size + tmpBox.Offset); // ignore for now
            Debug.WriteLine(string.Format("Unknown box type {0} in MovieMetadataBox (this), skipped", tmpBox.Type.ToString()));
              }
            }

            TrackBoxes = new TrackBox[tbcount];
            for (int i = 0; i < tbcount; i++)
            {
            TrackBoxes[i] = tmpTBs[i];
            }

              }
        }
Example #9
0
 public void AddTrackBox(TrackBox tbox)
 {
     TrackBoxes[MovieHeaderBox.NextTrackID - 1] = tbox;
       tbox.TrackHeaderBox.TrackID = MovieHeaderBox.NextTrackID;
       MovieHeaderBox.NextTrackID++;
 }
Example #10
0
 public MediaBox(TrackBox inParent)
     : base(BoxTypes.Media)
 {
     parent = inParent;
 }