예제 #1
0
        private void ParseTag(long start, long end, List <BoxHeader> parents)
        {
            BoxHeader header;

            for (long position = start; position < end; position += header.TotalBoxSize)
            {
                header = new BoxHeader(file, position);
                if (header.BoxType == BoxType.Moov)
                {
                    ParseTag(header.HeaderSize + position, header.TotalBoxSize + position, AddParent(parents, header));
                }
                else if (header.BoxType == BoxType.Mdia || header.BoxType == BoxType.Minf || header.BoxType == BoxType.Stbl || header.BoxType == BoxType.Trak)
                {
                    ParseTag(header.HeaderSize + position, header.TotalBoxSize + position, AddParent(parents, header));
                }
                else if (header.BoxType == BoxType.Udta)
                {
                    IsoUserDataBox udtaBox = BoxFactory.CreateBox(file, header)
                                             as IsoUserDataBox;
                    List <BoxHeader> new_parents = AddParent(parents, header);
                    udtaBox.ParentTree = new_parents.ToArray();
                    udta_boxes.Add(udtaBox);
                }
                else if (header.BoxType == BoxType.Mdat)
                {
                    mdat_start = position;
                    mdat_end   = position + header.TotalBoxSize;
                }
                if (header.TotalBoxSize == 0)
                {
                    break;
                }
            }
        }
예제 #2
0
        /// <summary>
        ///    Parses boxes for a specified range, looking for tags and
        ///    properties.
        /// </summary>
        /// <param name="start">
        ///    A <see cref="long" /> value specifying the seek position
        ///    at which to start reading.
        /// </param>
        /// <param name="end">
        ///    A <see cref="long" /> value specifying the seek position
        ///    at which to stop reading.
        /// </param>
        /// <param name="handler">
        ///    A <see cref="IsoHandlerBox" /> object that applied to the
        ///    range being searched.
        /// </param>
        private void ParseTagAndProperties(long start, long end,
                                           IsoHandlerBox handler)
        {
            BoxHeader header;

            for (long position = start; position < end;
                 position += header.TotalBoxSize)
            {
                header = new BoxHeader(file, position);
                ByteVector type = header.BoxType;

                if (type == BoxType.Moov ||
                    type == BoxType.Mdia ||
                    type == BoxType.Minf ||
                    type == BoxType.Stbl ||
                    type == BoxType.Trak)
                {
                    ParseTagAndProperties(
                        header.HeaderSize + position,
                        header.TotalBoxSize + position,
                        handler);
                }
                else if (type == BoxType.Stsd)
                {
                    stsd_boxes.Add(BoxFactory.CreateBox(
                                       file, header, handler));
                }
                else if (type == BoxType.Hdlr)
                {
                    handler = BoxFactory.CreateBox(file,
                                                   header, handler) as
                              IsoHandlerBox;
                }
                else if (mvhd_box == null &&
                         type == BoxType.Mvhd)
                {
                    mvhd_box = BoxFactory.CreateBox(file,
                                                    header, handler) as
                               IsoMovieHeaderBox;
                }
                else if (udta_box == null &&
                         type == BoxType.Udta)
                {
                    udta_box = BoxFactory.CreateBox(file,
                                                    header, handler) as
                               IsoUserDataBox;
                }
                else if (type == BoxType.Mdat)
                {
                    mdat_start = position;
                    mdat_end   = position + header.TotalBoxSize;
                }

                if (header.TotalBoxSize == 0)
                {
                    break;
                }
            }
        }
예제 #3
0
        /// <summary>
        ///    Reads the file with a specified read style.
        /// </summary>
        /// <param name="propertiesStyle">
        ///    A <see cref="ReadStyle" /> value specifying at what level
        ///    of accuracy to read the media properties, or <see
        ///    cref="ReadStyle.None" /> to ignore the properties.
        /// </param>
        void Read (ReadStyle propertiesStyle)
        {
            // TODO: Support Id3v2 boxes!!!
            tag = new CombinedTag ();
            Mode = AccessMode.Read;
            try {
                var parser = new FileParser (this);

                if ((propertiesStyle & ReadStyle.Average) == 0)
                    parser.ParseTag ();
                else
                    parser.ParseTagAndProperties ();

                InvariantStartPosition = parser.MdatStartPosition;
                InvariantEndPosition = parser.MdatEndPosition;

                UdtaBoxes.AddRange (parser.UserDataBoxes);

                // Ensure our collection contains at least a single empty box
                if (UdtaBoxes.Count == 0) {
                    var dummy = new IsoUserDataBox ();
                    UdtaBoxes.Add (dummy);
                }

                // Check if a udta with ILST actually exists
                if (IsAppleTagUdtaPresent ())
                    TagTypesOnDisk |= TagTypes.Apple;   //There is an udta present with ILST info

                // Find the udta box with the Apple Tag ILST
                IsoUserDataBox udtaBox = FindAppleTagUdta ();
                if (null == udtaBox) {
                    udtaBox = new IsoUserDataBox ();
                }
                apple_tag = new AppleTag (udtaBox);
                tag.SetTags (apple_tag);

                // If we're not reading properties, we're done.
                if ((propertiesStyle & ReadStyle.Average) == 0) {
                    Mode = AccessMode.Closed;
                    return;
                }

                // Get the movie header box.
                var mvhd_box = parser.MovieHeaderBox;
                if (mvhd_box == null) {
                    Mode = AccessMode.Closed;
                    throw new CorruptFileException ("mvhd box not found.");
                }

                var audio_sample_entry = parser.AudioSampleEntry;
                var visual_sample_entry = parser.VisualSampleEntry;

                // Read the properties.
                properties = new Properties (mvhd_box.Duration, audio_sample_entry, visual_sample_entry);
            } finally {
                Mode = AccessMode.Closed;
            }
        }
예제 #4
0
 private void Read(ReadStyle propertiesStyle)
 {
     tag  = new CombinedTag();
     Mode = AccessMode.Read;
     try
     {
         FileParser parser = new FileParser(this);
         if (propertiesStyle == ReadStyle.None)
         {
             parser.ParseTag();
         }
         else
         {
             parser.ParseTagAndProperties();
         }
         InvariantStartPosition = parser.MdatStartPosition;
         InvariantEndPosition   = parser.MdatEndPosition;
         udta_boxes.AddRange(parser.UserDataBoxes);
         if (udta_boxes.Count == 0)
         {
             IsoUserDataBox dummy = new IsoUserDataBox();
             udta_boxes.Add(dummy);
         }
         if (IsAppleTagUdtaPresent())
         {
             TagTypesOnDisk |= TagTypes.Apple;
         }
         IsoUserDataBox udtaBox = FindAppleTagUdta();
         if (null == udtaBox)
         {
             udtaBox = new IsoUserDataBox();
         }
         apple_tag = new AppleTag(udtaBox);
         tag.SetTags(apple_tag);
         if (propertiesStyle == ReadStyle.None)
         {
             Mode = AccessMode.Closed;
             return;
         }
         IsoMovieHeaderBox mvhd_box = parser.MovieHeaderBox;
         if (mvhd_box == null)
         {
             Mode = AccessMode.Closed;
             throw new CorruptFileException("mvhd box not found.");
         }
         IsoAudioSampleEntry  audio_sample_entry  = parser.AudioSampleEntry;
         IsoVisualSampleEntry visual_sample_entry = parser.VisualSampleEntry;
         properties = new Properties(mvhd_box.Duration, audio_sample_entry, visual_sample_entry);
     }
     finally
     {
         Mode = AccessMode.Closed;
     }
 }
예제 #5
0
 /// <summary>
 ///    Resets all internal fields.
 /// </summary>
 private void ResetFields()
 {
     mvhd_box  = null;
     udta_box  = null;
     moov_tree = null;
     udta_tree = null;
     stco_boxes.Clear();
     stsd_boxes.Clear();
     mdat_start = -1;
     mdat_end   = -1;
 }
예제 #6
0
 private void Read(ReadStyle propertiesStyle)
 {
     this.tag = new CombinedTag();
     base.Mode = TagLib.File.AccessMode.Read;
     try
     {
         FileParser parser = new FileParser(this);
         if (propertiesStyle == ReadStyle.None)
         {
             parser.ParseTag();
         }
         else
         {
             parser.ParseTagAndProperties();
         }
         base.InvariantStartPosition = parser.MdatStartPosition;
         base.InvariantEndPosition = parser.MdatEndPosition;
         this.udta_box = parser.UserDataBox;
         if (((this.udta_box != null) && (this.udta_box.GetChild(BoxType.Meta) != null)) && (this.udta_box.GetChild(BoxType.Meta).GetChild(BoxType.Ilst) != null))
         {
             base.TagTypesOnDisk |= TagTypes.Apple;
         }
         if (this.udta_box == null)
         {
             this.udta_box = new IsoUserDataBox();
         }
         this.apple_tag = new AppleTag(this.udta_box);
         TagLib.Tag[] tags = new TagLib.Tag[] { this.apple_tag };
         this.tag.SetTags(tags);
         if (propertiesStyle == ReadStyle.None)
         {
             base.Mode = TagLib.File.AccessMode.Closed;
         }
         else
         {
             IsoMovieHeaderBox movieHeaderBox = parser.MovieHeaderBox;
             if (movieHeaderBox == null)
             {
                 base.Mode = TagLib.File.AccessMode.Closed;
                 throw new CorruptFileException("mvhd box not found.");
             }
             IsoAudioSampleEntry audioSampleEntry = parser.AudioSampleEntry;
             IsoVisualSampleEntry visualSampleEntry = parser.VisualSampleEntry;
             ICodec[] codecs = new ICodec[] { audioSampleEntry, visualSampleEntry };
             this.properties = new TagLib.Properties(movieHeaderBox.Duration, codecs);
         }
     }
     finally
     {
         base.Mode = TagLib.File.AccessMode.Closed;
     }
 }
예제 #7
0
        /// <summary>
        ///    Gets a tag of a specified type from the current instance,
        ///    optionally creating a new tag if possible.
        /// </summary>
        /// <param name="type">
        ///    A <see cref="TagLib.TagTypes" /> value indicating the
        ///    type of tag to read.
        /// </param>
        /// <param name="create">
        ///    A <see cref="bool" /> value specifying whether or not to
        ///    try and create the tag if one is not found.
        /// </param>
        /// <returns>
        ///    A <see cref="Tag" /> object containing the tag that was
        ///    found in or added to the current instance. If no
        ///    matching tag was found and none was created, <see
        ///    langword="null" /> is returned.
        /// </returns>
        /// <remarks>
        ///    At the time of this writing, only <see cref="AppleTag" />
        ///    is supported. All other tag types will be ignored.
        /// </remarks>
        public override Tag GetTag (TagTypes type, bool create)
        {
            if (type == TagTypes.Apple) {
                if (apple_tag == null && create) {
                    IsoUserDataBox udtaBox = FindAppleTagUdta ();
                    if (null == udtaBox) {
                        udtaBox = new IsoUserDataBox ();
                    }
                    apple_tag = new AppleTag (udtaBox);
                    tag.SetTags (apple_tag);
                }

                return apple_tag;
            }

            return null;
        }
예제 #8
0
 public AppleTag(IsoUserDataBox box)
 {
     if (box == null)
     {
         throw new ArgumentNullException("box");
     }
     meta_box = box.GetChild(BoxType.Meta)
                as IsoMetaBox;
     if (meta_box == null)
     {
         meta_box = new IsoMetaBox("mdir", null);
         box.AddChild(meta_box);
     }
     ilst_box = meta_box.GetChild(BoxType.Ilst)
                as AppleItemListBox;
     if (ilst_box == null)
     {
         ilst_box = new AppleItemListBox();
         meta_box.AddChild(ilst_box);
     }
 }
예제 #9
0
        /// <summary>
        ///    Parses boxes for a specified range, looking for tags.
        /// </summary>
        /// <param name="start">
        ///    A <see cref="long" /> value specifying the seek position
        ///    at which to start reading.
        /// </param>
        /// <param name="end">
        ///    A <see cref="long" /> value specifying the seek position
        ///    at which to stop reading.
        /// </param>
        private void ParseTag(long start, long end)
        {
            BoxHeader header;

            for (long position = start; position < end;
                 position += header.TotalBoxSize)
            {
                header = new BoxHeader(file, position);

                if (header.BoxType == BoxType.Moov ||
                    header.BoxType == BoxType.Mdia ||
                    header.BoxType == BoxType.Minf ||
                    header.BoxType == BoxType.Stbl ||
                    header.BoxType == BoxType.Trak)
                {
                    ParseTag(header.HeaderSize + position,
                             header.TotalBoxSize + position);
                }
                else if (udta_box == null &&
                         header.BoxType == BoxType.Udta)
                {
                    udta_box = BoxFactory.CreateBox(file,
                                                    header) as IsoUserDataBox;
                }
                else if (header.BoxType == BoxType.Mdat)
                {
                    mdat_start = position;
                    mdat_end   = position + header.TotalBoxSize;
                }

                if (header.TotalBoxSize == 0)
                {
                    break;
                }
            }
        }
예제 #10
0
파일: File.cs 프로젝트: talun2075/SonosAPI
        /// <summary>
        ///    Saves the changes made in the current instance to the
        ///    file it represents.
        /// </summary>
        public override void Save()
        {
            if (udta_boxes.Count == 0)
            {
                IsoUserDataBox udtaBox = new IsoUserDataBox();
                udta_boxes.Add(udtaBox);
            }

            // Try to get into write mode.
            Mode = File.AccessMode.Write;
            try {
                FileParser parser = new FileParser(this);
                parser.ParseBoxHeaders();

                InvariantStartPosition = parser.MdatStartPosition;
                InvariantEndPosition   = parser.MdatEndPosition;

                long size_change    = 0;
                long write_position = 0;

                // To avoid rewriting udta blocks which might not have been modified,
                // the code here will work correctly if:
                // 1. There is a single udta for the entire file
                //   - OR -
                // 2. There are multiple utdtas, but only 1 of them contains the Apple ILST box.
                // We should be OK in the vast majority of cases
                IsoUserDataBox udtaBox = FindAppleTagUdta();
                if (null == udtaBox)
                {
                    udtaBox = new IsoUserDataBox();
                }
                ByteVector tag_data = udtaBox.Render();

                // If we don't have a "udta" box to overwrite...
                if (udtaBox.ParentTree == null ||
                    udtaBox.ParentTree.Length == 0)
                {
                    // Stick the box at the end of the moov box.
                    BoxHeader moov_header = parser.MoovTree [
                        parser.MoovTree.Length - 1];
                    size_change    = tag_data.Count;
                    write_position = moov_header.Position +
                                     moov_header.TotalBoxSize;
                    Insert(tag_data, write_position, 0);

                    // Overwrite the parent box sizes.
                    for (int i = parser.MoovTree.Length - 1; i >= 0;
                         i--)
                    {
                        size_change = parser.MoovTree [i
                                      ].Overwrite(this, size_change);
                    }
                }
                else
                {
                    // Overwrite the old box.
                    BoxHeader udta_header = udtaBox.ParentTree[udtaBox.ParentTree.Length - 1];
                    size_change = tag_data.Count -
                                  udta_header.TotalBoxSize;
                    write_position = udta_header.Position;
                    Insert(tag_data, write_position,
                           udta_header.TotalBoxSize);

                    // Overwrite the parent box sizes.
                    for (int i = udtaBox.ParentTree.Length - 2; i >= 0;
                         i--)
                    {
                        size_change = udtaBox.ParentTree [i
                                      ].Overwrite(this, size_change);
                    }
                }

                // If we've had a size change, we may need to adjust
                // chunk offsets.
                if (size_change != 0)
                {
                    // We may have moved the offset boxes, so we
                    // need to reread.
                    parser.ParseChunkOffsets();
                    InvariantStartPosition = parser.MdatStartPosition;
                    InvariantEndPosition   = parser.MdatEndPosition;

                    foreach (Box box in parser.ChunkOffsetBoxes)
                    {
                        IsoChunkLargeOffsetBox co64 =
                            box as IsoChunkLargeOffsetBox;

                        if (co64 != null)
                        {
                            co64.Overwrite(this,
                                           size_change,
                                           write_position);
                            continue;
                        }

                        IsoChunkOffsetBox stco =
                            box as IsoChunkOffsetBox;

                        if (stco != null)
                        {
                            stco.Overwrite(this,
                                           size_change,
                                           write_position);
                            continue;
                        }
                    }
                }

                TagTypesOnDisk = TagTypes;
            } finally {
                Mode = File.AccessMode.Closed;
            }
        }
예제 #11
0
        /// <summary>
        ///    Reads the file with a specified read style.
        /// </summary>
        /// <param name="propertiesStyle">
        ///    A <see cref="ReadStyle" /> value specifying at what level
        ///    of accuracy to read the media properties, or <see
        ///    cref="ReadStyle.None" /> to ignore the properties.
        /// </param>
        private void Read(ReadStyle propertiesStyle)
        {
            // TODO: Support Id3v2 boxes!!!
            tag = new CombinedTag ();
            Mode = AccessMode.Read;
            try {
                FileParser parser = new FileParser (this);

                if (propertiesStyle == ReadStyle.None)
                    parser.ParseTag ();
                else
                    parser.ParseTagAndProperties ();

                InvariantStartPosition = parser.MdatStartPosition;
                InvariantEndPosition = parser.MdatEndPosition;

                udta_boxes.AddRange(parser.UserDataBoxes);

                // Ensure our collection contains at least a single empty box
                if (udta_boxes.Count == 0) {
                    IsoUserDataBox dummy = new IsoUserDataBox ();
                    udta_boxes.Add(dummy);
                }

                // Check if a udta with ILST actually exists
                if (IsAppleTagUdtaPresent ())
                    TagTypesOnDisk |= TagTypes.Apple;	//There is an udta present with ILST info

                // Find the udta box with the Apple Tag ILST
                IsoUserDataBox udtaBox = FindAppleTagUdta();
                if (null == udtaBox) {
                    udtaBox = new IsoUserDataBox();
                }
                apple_tag = new AppleTag (udtaBox);
                tag.SetTags (apple_tag);

                // If we're not reading properties, we're done.
                if (propertiesStyle == ReadStyle.None) {
                    Mode = AccessMode.Closed;
                    return;
                }

                // Get the movie header box.
                IsoMovieHeaderBox mvhd_box = parser.MovieHeaderBox;
                if(mvhd_box == null) {
                    Mode = AccessMode.Closed;
                    throw new CorruptFileException (
                        "mvhd box not found.");
                }

                IsoAudioSampleEntry  audio_sample_entry =
                    parser.AudioSampleEntry;
                IsoVisualSampleEntry visual_sample_entry =
                    parser.VisualSampleEntry;

                // Read the properties.
                properties = new Properties (mvhd_box.Duration,
                    audio_sample_entry, visual_sample_entry);
            } finally {
                Mode = AccessMode.Closed;
            }
        }
예제 #12
0
        /// <summary>
        ///    Saves the changes made in the current instance to the
        ///    file it represents.
        /// </summary>
        public override void Save()
        {
            if (udta_boxes.Count == 0) {
                IsoUserDataBox udtaBox = new IsoUserDataBox ();
                udta_boxes.Add(udtaBox);
            }

            // Try to get into write mode.
            Mode = File.AccessMode.Write;
            try {
                FileParser parser = new FileParser (this);
                parser.ParseBoxHeaders ();

                InvariantStartPosition = parser.MdatStartPosition;
                InvariantEndPosition = parser.MdatEndPosition;

                long size_change = 0;
                long write_position = 0;

                // To avoid rewriting udta blocks which might not have been modified,
                // the code here will work correctly if:
                // 1. There is a single udta for the entire file
                //   - OR -
                // 2. There are multiple utdtas, but only 1 of them contains the Apple ILST box.
                // We should be OK in the vast majority of cases
                IsoUserDataBox udtaBox = FindAppleTagUdta();
                if (null == udtaBox)
                    udtaBox = new IsoUserDataBox ();
                ByteVector tag_data = udtaBox.Render ();

                // If we don't have a "udta" box to overwrite...
                if (udtaBox.ParentTree == null ||
                    udtaBox.ParentTree.Length == 0) {

                    // Stick the box at the end of the moov box.
                    BoxHeader moov_header = parser.MoovTree [
                        parser.MoovTree.Length - 1];
                    size_change = tag_data.Count;
                    write_position = moov_header.Position +
                        moov_header.TotalBoxSize;
                    Insert (tag_data, write_position, 0);

                    // Overwrite the parent box sizes.
                    for (int i = parser.MoovTree.Length - 1; i >= 0;
                        i --)
                        size_change = parser.MoovTree [i
                            ].Overwrite (this, size_change);
                } else {
                    // Overwrite the old box.
                    BoxHeader udta_header = udtaBox.ParentTree[udtaBox.ParentTree.Length - 1];
                    size_change = tag_data.Count -
                        udta_header.TotalBoxSize;
                    write_position = udta_header.Position;
                    Insert (tag_data, write_position,
                        udta_header.TotalBoxSize);

                    // Overwrite the parent box sizes.
                    for (int i = udtaBox.ParentTree.Length - 2; i >= 0;
                        i --)
                        size_change = udtaBox.ParentTree [i
                            ].Overwrite (this, size_change);
                }

                // If we've had a size change, we may need to adjust
                // chunk offsets.
                if (size_change != 0) {
                    // We may have moved the offset boxes, so we
                    // need to reread.
                    parser.ParseChunkOffsets ();
                    InvariantStartPosition = parser.MdatStartPosition;
                    InvariantEndPosition = parser.MdatEndPosition;

                    foreach (Box box in parser.ChunkOffsetBoxes) {
                        IsoChunkLargeOffsetBox co64 =
                            box as IsoChunkLargeOffsetBox;

                        if (co64 != null) {
                            co64.Overwrite (this,
                                size_change,
                                write_position);
                            continue;
                        }

                        IsoChunkOffsetBox stco =
                            box as IsoChunkOffsetBox;

                        if (stco != null) {
                            stco.Overwrite (this,
                                size_change,
                                write_position);
                            continue;
                        }
                    }
                }

                TagTypesOnDisk = TagTypes;
            } finally {
                Mode = File.AccessMode.Closed;
            }
        }
예제 #13
0
        /// <summary>
        ///    Gets a tag of a specified type from the current instance,
        ///    optionally creating a new tag if possible.
        /// </summary>
        /// <param name="type">
        ///    A <see cref="TagLib.TagTypes" /> value indicating the
        ///    type of tag to read.
        /// </param>
        /// <param name="create">
        ///    A <see cref="bool" /> value specifying whether or not to
        ///    try and create the tag if one is not found.
        /// </param>
        /// <returns>
        ///    A <see cref="Tag" /> object containing the tag that was
        ///    found in or added to the current instance. If no
        ///    matching tag was found and none was created, <see
        ///    langword="null" /> is returned.
        /// </returns>
        /// <remarks>
        ///    At the time of this writing, only <see cref="AppleTag" />
        ///    is supported. All other tag types will be ignored.
        /// </remarks>
        public override TagLib.Tag GetTag(TagTypes type, bool create)
        {
            if (type == TagTypes.Apple) {
                if (apple_tag == null && create) {
                    IsoUserDataBox udtaBox = FindAppleTagUdta();
                    if (null == udtaBox) {
                        udtaBox = new IsoUserDataBox();
                    }
                    apple_tag = new AppleTag (udtaBox);
                    tag.SetTags (apple_tag);
                }

                return apple_tag;
            }

            return null;
        }
예제 #14
0
        /// <summary>
        ///    Parses boxes for a specified range, looking for tags and
        ///    properties.
        /// </summary>
        /// <param name="start">
        ///    A <see cref="long" /> value specifying the seek position
        ///    at which to start reading.
        /// </param>
        /// <param name="end">
        ///    A <see cref="long" /> value specifying the seek position
        ///    at which to stop reading.
        /// </param>
        /// <param name="handler">
        ///    A <see cref="IsoHandlerBox" /> object that applied to the
        ///    range being searched.
        /// </param>
        private void ParseTagAndProperties(long start, long end,
                                           IsoHandlerBox handler, List <BoxHeader> parents)
        {
            BoxHeader header;

            for (long position = start; position < end;
                 position += header.TotalBoxSize)
            {
                header = new BoxHeader(file, position);
                ByteVector type = header.BoxType;

                if (type == BoxType.Moov)
                {
                    ParseTagAndProperties(header.HeaderSize + position,
                                          header.TotalBoxSize + position,
                                          handler,
                                          AddParent(parents, header));
                }
                else if (type == BoxType.Mdia ||
                         type == BoxType.Minf ||
                         type == BoxType.Stbl ||
                         type == BoxType.Trak)
                {
                    ParseTagAndProperties(
                        header.HeaderSize + position,
                        header.TotalBoxSize + position,
                        handler,
                        AddParent(parents, header));
                }
                else if (type == BoxType.Stsd)
                {
                    stsd_boxes.Add(BoxFactory.CreateBox(
                                       file, header, handler));
                }
                else if (type == BoxType.Hdlr)
                {
                    handler = BoxFactory.CreateBox(file,
                                                   header, handler) as
                              IsoHandlerBox;
                }
                else if (mvhd_box == null &&
                         type == BoxType.Mvhd)
                {
                    mvhd_box = BoxFactory.CreateBox(file,
                                                    header, handler) as
                               IsoMovieHeaderBox;
                }
                else if (type == BoxType.Udta)
                {
                    IsoUserDataBox udtaBox = BoxFactory.CreateBox(file,
                                                                  header, handler) as
                                             IsoUserDataBox;

                    // Since we can have multiple udta boxes, save the parent for each one
                    List <BoxHeader> new_parents = AddParent(
                        parents, header);
                    udtaBox.ParentTree = new_parents.ToArray();

                    udta_boxes.Add(udtaBox);
                }
                else if (type == BoxType.Mdat)
                {
                    mdat_start = position;
                    mdat_end   = position + header.TotalBoxSize;
                }

                if (header.TotalBoxSize == 0)
                {
                    break;
                }
            }
        }
예제 #15
0
 private void ParseTagAndProperties(long start, long end, IsoHandlerBox handler)
 {
     BoxHeader header;
     for (long i = start; i < end; i += header.TotalBoxSize)
     {
         header = new BoxHeader(this.file, i);
         ByteVector boxType = header.BoxType;
         if (((boxType == BoxType.Moov) || (boxType == BoxType.Mdia)) || (((boxType == BoxType.Minf) || (boxType == BoxType.Stbl)) || (boxType == BoxType.Trak)))
         {
             this.ParseTagAndProperties(header.HeaderSize + i, header.TotalBoxSize + i, handler);
         }
         else if (boxType == BoxType.Stsd)
         {
             this.stsd_boxes.Add(BoxFactory.CreateBox(this.file, header, handler));
         }
         else if (boxType == BoxType.Hdlr)
         {
             handler = BoxFactory.CreateBox(this.file, header, handler) as IsoHandlerBox;
         }
         else if ((this.mvhd_box == null) && (boxType == BoxType.Mvhd))
         {
             this.mvhd_box = BoxFactory.CreateBox(this.file, header, handler) as IsoMovieHeaderBox;
         }
         else if ((this.udta_box == null) && (boxType == BoxType.Udta))
         {
             this.udta_box = BoxFactory.CreateBox(this.file, header, handler) as IsoUserDataBox;
         }
         else if (boxType == BoxType.Mdat)
         {
             this.mdat_start = i;
             this.mdat_end = i + header.TotalBoxSize;
         }
         if (header.TotalBoxSize == 0)
         {
             break;
         }
     }
 }
예제 #16
0
 private void ResetFields()
 {
     this.mvhd_box = null;
     this.udta_box = null;
     this.moov_tree = null;
     this.udta_tree = null;
     this.stco_boxes.Clear();
     this.stsd_boxes.Clear();
     this.mdat_start = -1L;
     this.mdat_end = -1L;
 }
예제 #17
0
		/// <summary>
		///    Resets all internal fields.
		/// </summary>
		private void ResetFields ()
		{
			mvhd_box = null;
			udta_box = null;
			moov_tree = null;
			udta_tree = null;
			stco_boxes.Clear ();
			stsd_boxes.Clear ();
			mdat_start = -1;
			mdat_end = -1;
		}
예제 #18
0
 private void ParseTag(long start, long end)
 {
     BoxHeader header;
     for (long i = start; i < end; i += header.TotalBoxSize)
     {
         header = new BoxHeader(this.file, i);
         if (((header.BoxType == BoxType.Moov) || (header.BoxType == BoxType.Mdia)) || (((header.BoxType == BoxType.Minf) || (header.BoxType == BoxType.Stbl)) || (header.BoxType == BoxType.Trak)))
         {
             this.ParseTag(header.HeaderSize + i, header.TotalBoxSize + i);
         }
         else if ((this.udta_box == null) && (header.BoxType == BoxType.Udta))
         {
             this.udta_box = BoxFactory.CreateBox(this.file, header) as IsoUserDataBox;
         }
         else if (header.BoxType == BoxType.Mdat)
         {
             this.mdat_start = i;
             this.mdat_end = i + header.TotalBoxSize;
         }
         if (header.TotalBoxSize == 0)
         {
             break;
         }
     }
 }
예제 #19
0
		/// <summary>
		///    Parses boxes for a specified range, looking for tags and
		///    properties.
		/// </summary>
		/// <param name="start">
		///    A <see cref="long" /> value specifying the seek position
		///    at which to start reading.
		/// </param>
		/// <param name="end">
		///    A <see cref="long" /> value specifying the seek position
		///    at which to stop reading.
		/// </param>
		/// <param name="handler">
		///    A <see cref="IsoHandlerBox" /> object that applied to the
		///    range being searched.
		/// </param>
		private void ParseTagAndProperties (long start, long end,
		                                    IsoHandlerBox handler)
		{
			BoxHeader header;
			
			for (long position = start; position < end;
				position += header.TotalBoxSize) {
				header = new BoxHeader (file, position);
				ByteVector type = header.BoxType;
				
				if (type == BoxType.Moov ||
					type == BoxType.Mdia ||
					type == BoxType.Minf ||
					type == BoxType.Stbl ||
					type == BoxType.Trak) {
					ParseTagAndProperties (
						header.HeaderSize + position,
						header.TotalBoxSize + position,
						handler);
				} else if (type == BoxType.Stsd) {
					stsd_boxes.Add (BoxFactory.CreateBox (
						file, header, handler));
				} else if (type == BoxType.Hdlr) {
					handler = BoxFactory.CreateBox (file,
						header, handler) as
							IsoHandlerBox;
				} else if (mvhd_box == null &&
					type == BoxType.Mvhd) {
					mvhd_box = BoxFactory.CreateBox (file,
						header, handler) as
							IsoMovieHeaderBox;
				} else if (udta_box == null &&
					type == BoxType.Udta) {
					udta_box = BoxFactory.CreateBox (file,
						header, handler) as
							IsoUserDataBox;
				} else if (type == BoxType.Mdat) {
					mdat_start = position;
					mdat_end = position + header.TotalBoxSize;
				}
				
				if (header.TotalBoxSize == 0)
					break;
			}
		}
예제 #20
0
		/// <summary>
		///    Saves the changes made in the current instance to the
		///    file it represents.
		/// </summary>
		public override void Save ()
		{
			if (udta_box == null)
				udta_box = new IsoUserDataBox ();
			
			// Try to get into write mode.
			Mode = File.AccessMode.Write;
			try {
				FileParser parser = new FileParser (this);
				parser.ParseBoxHeaders ();
				
				InvariantStartPosition = parser.MdatStartPosition;
				InvariantEndPosition = parser.MdatEndPosition;
				
				long size_change = 0;
				long write_position = 0;
				
				ByteVector tag_data = udta_box.Render ();
				
				// If we don't have a "udta" box to overwrite...
				if (parser.UdtaTree == null ||
					parser.UdtaTree.Length == 0 ||
					parser.UdtaTree [parser.UdtaTree.Length - 1
					].BoxType != BoxType.Udta) {
					
					// Stick the box at the end of the moov box.
					BoxHeader moov_header = parser.MoovTree [
						parser.MoovTree.Length - 1];
					size_change = tag_data.Count;
					write_position = moov_header.Position +
						moov_header.TotalBoxSize;
					Insert (tag_data, write_position, 0);
					
					// Overwrite the parent box sizes.
					for (int i = parser.MoovTree.Length - 1; i >= 0;
						i --)
						size_change = parser.MoovTree [i
							].Overwrite (this, size_change);
				} else {
					// Overwrite the old box.
					BoxHeader udta_header = parser.UdtaTree [
						parser.UdtaTree.Length - 1];
					size_change = tag_data.Count -
						udta_header.TotalBoxSize;
					write_position = udta_header.Position;
					Insert (tag_data, write_position,
						udta_header.TotalBoxSize);
					
					// Overwrite the parent box sizes.
					for (int i = parser.UdtaTree.Length - 2; i >= 0;
						i --)
						size_change = parser.UdtaTree [i
							].Overwrite (this, size_change);
				}
				
				// If we've had a size change, we may need to adjust
				// chunk offsets.
				if (size_change != 0) {
					// We may have moved the offset boxes, so we
					// need to reread.
					parser.ParseChunkOffsets ();
					InvariantStartPosition = parser.MdatStartPosition;
					InvariantEndPosition = parser.MdatEndPosition;
					
					foreach (Box box in parser.ChunkOffsetBoxes) {
						IsoChunkLargeOffsetBox co64 = 
							box as IsoChunkLargeOffsetBox;
						
						if (co64 != null) {
							co64.Overwrite (this,
								size_change,
								write_position);
							continue;
						}
						
						IsoChunkOffsetBox stco = 
							box as IsoChunkOffsetBox;
						
						if (stco != null) {
							stco.Overwrite (this,
								size_change,
								write_position);
							continue;
						}
					}
				}
				
				TagTypesOnDisk = TagTypes;
			} finally {
				Mode = File.AccessMode.Closed;
			}
		}
예제 #21
0
        /// <summary>
        ///    Reads the file with a specified read style.
        /// </summary>
        /// <param name="propertiesStyle">
        ///    A <see cref="ReadStyle" /> value specifying at what level
        ///    of accuracy to read the media properties, or <see
        ///    cref="ReadStyle.None" /> to ignore the properties.
        /// </param>
        private void Read(ReadStyle propertiesStyle)
        {
            // TODO: Support Id3v2 boxes!!!
            tag  = new CombinedTag();
            Mode = AccessMode.Read;
            try {
                FileParser parser = new FileParser(this);

                if (propertiesStyle == ReadStyle.None)
                {
                    parser.ParseTag();
                }
                else
                {
                    parser.ParseTagAndProperties();
                }

                InvariantStartPosition = parser.MdatStartPosition;
                InvariantEndPosition   = parser.MdatEndPosition;

                udta_box = parser.UserDataBox;

                if (udta_box != null && udta_box.GetChild(BoxType.Meta)
                    != null && udta_box.GetChild(BoxType.Meta
                                                 ).GetChild(BoxType.Ilst) != null)
                {
                    TagTypesOnDisk |= TagTypes.Apple;
                }

                if (udta_box == null)
                {
                    udta_box = new IsoUserDataBox();
                }

                apple_tag = new AppleTag(udta_box);
                tag.SetTags(apple_tag);

                // If we're not reading properties, we're done.
                if (propertiesStyle == ReadStyle.None)
                {
                    Mode = AccessMode.Closed;
                    return;
                }

                // Get the movie header box.
                IsoMovieHeaderBox mvhd_box = parser.MovieHeaderBox;
                if (mvhd_box == null)
                {
                    Mode = AccessMode.Closed;
                    throw new CorruptFileException(
                              "mvhd box not found.");
                }

                IsoAudioSampleEntry audio_sample_entry =
                    parser.AudioSampleEntry;
                IsoVisualSampleEntry visual_sample_entry =
                    parser.VisualSampleEntry;

                // Read the properties.
                properties = new Properties(mvhd_box.Duration,
                                            audio_sample_entry, visual_sample_entry);
            } finally {
                Mode = AccessMode.Closed;
            }
        }
예제 #22
0
        /// <summary>
        ///    Saves the changes made in the current instance to the
        ///    file it represents.
        /// </summary>
        public override void Save()
        {
            if (udta_box == null)
            {
                udta_box = new IsoUserDataBox();
            }

            // Try to get into write mode.
            Mode = File.AccessMode.Write;
            try {
                FileParser parser = new FileParser(this);
                parser.ParseBoxHeaders();

                InvariantStartPosition = parser.MdatStartPosition;
                InvariantEndPosition   = parser.MdatEndPosition;

                long size_change    = 0;
                long write_position = 0;

                ByteVector tag_data = udta_box.Render();

                // If we don't have a "udta" box to overwrite...
                if (parser.UdtaTree == null ||
                    parser.UdtaTree.Length == 0 ||
                    parser.UdtaTree [parser.UdtaTree.Length - 1
                    ].BoxType != BoxType.Udta)
                {
                    // Stick the box at the end of the moov box.
                    BoxHeader moov_header = parser.MoovTree [
                        parser.MoovTree.Length - 1];
                    size_change    = tag_data.Count;
                    write_position = moov_header.Position +
                                     moov_header.TotalBoxSize;
                    Insert(tag_data, write_position, 0);

                    // Overwrite the parent box sizes.
                    for (int i = parser.MoovTree.Length - 1; i >= 0;
                         i--)
                    {
                        size_change = parser.MoovTree [i
                                      ].Overwrite(this, size_change);
                    }
                }
                else
                {
                    // Overwrite the old box.
                    BoxHeader udta_header = parser.UdtaTree [
                        parser.UdtaTree.Length - 1];
                    size_change = tag_data.Count -
                                  udta_header.TotalBoxSize;
                    write_position = udta_header.Position;
                    Insert(tag_data, write_position,
                           udta_header.TotalBoxSize);

                    // Overwrite the parent box sizes.
                    for (int i = parser.UdtaTree.Length - 2; i >= 0;
                         i--)
                    {
                        size_change = parser.UdtaTree [i
                                      ].Overwrite(this, size_change);
                    }
                }

                // If we've had a size change, we may need to adjust
                // chunk offsets.
                if (size_change != 0)
                {
                    // We may have moved the offset boxes, so we
                    // need to reread.
                    parser.ParseChunkOffsets();
                    InvariantStartPosition = parser.MdatStartPosition;
                    InvariantEndPosition   = parser.MdatEndPosition;

                    foreach (Box box in parser.ChunkOffsetBoxes)
                    {
                        IsoChunkLargeOffsetBox co64 =
                            box as IsoChunkLargeOffsetBox;

                        if (co64 != null)
                        {
                            co64.Overwrite(this,
                                           size_change,
                                           write_position);
                            continue;
                        }

                        IsoChunkOffsetBox stco =
                            box as IsoChunkOffsetBox;

                        if (stco != null)
                        {
                            stco.Overwrite(this,
                                           size_change,
                                           write_position);
                            continue;
                        }
                    }
                }

                TagTypesOnDisk = TagTypes;
            } finally {
                Mode = File.AccessMode.Closed;
            }
        }
예제 #23
0
 public override void Save()
 {
     if (udta_boxes.Count == 0)
     {
         IsoUserDataBox udtaBox = new IsoUserDataBox();
         udta_boxes.Add(udtaBox);
     }
     Mode = File.AccessMode.Write;
     try
     {
         FileParser parser = new FileParser(this);
         parser.ParseBoxHeaders();
         InvariantStartPosition = parser.MdatStartPosition;
         InvariantEndPosition   = parser.MdatEndPosition;
         long           size_change    = 0;
         long           write_position = 0;
         IsoUserDataBox udtaBox        = FindAppleTagUdta();
         if (null == udtaBox)
         {
             udtaBox = new IsoUserDataBox();
         }
         ByteVector tag_data = udtaBox.Render();
         if (udtaBox.ParentTree == null || udtaBox.ParentTree.Length == 0)
         {
             BoxHeader moov_header = parser.MoovTree[parser.MoovTree.Length - 1];
             size_change    = tag_data.Count;
             write_position = moov_header.Position + moov_header.TotalBoxSize;
             Insert(tag_data, write_position, 0);
             for (int i = parser.MoovTree.Length - 1; i >= 0; i--)
             {
                 size_change = parser.MoovTree[i].Overwrite(this, size_change);
             }
         }
         else
         {
             BoxHeader udta_header = udtaBox.ParentTree[udtaBox.ParentTree.Length - 1];
             size_change    = tag_data.Count - udta_header.TotalBoxSize;
             write_position = udta_header.Position;
             Insert(tag_data, write_position, udta_header.TotalBoxSize);
             for (int i = udtaBox.ParentTree.Length - 2; i >= 0; i--)
             {
                 size_change = udtaBox.ParentTree[i].Overwrite(this, size_change);
             }
         }
         if (size_change != 0)
         {
             parser.ParseChunkOffsets();
             InvariantStartPosition = parser.MdatStartPosition;
             InvariantEndPosition   = parser.MdatEndPosition;
             foreach (Box box in parser.ChunkOffsetBoxes)
             {
                 IsoChunkLargeOffsetBox co64 = box as IsoChunkLargeOffsetBox;
                 if (co64 != null)
                 {
                     co64.Overwrite(this, size_change, write_position);
                     continue;
                 }
                 IsoChunkOffsetBox stco = box as IsoChunkOffsetBox;
                 if (stco != null)
                 {
                     stco.Overwrite(this, size_change, write_position);
                     continue;
                 }
             }
         }
         TagTypesOnDisk = TagTypes;
     }
     finally
     {
         Mode = File.AccessMode.Closed;
     }
 }
예제 #24
0
 public override void Save()
 {
     if (this.udta_box == null)
     {
         this.udta_box = new IsoUserDataBox();
     }
     base.Mode = TagLib.File.AccessMode.Write;
     try
     {
         FileParser parser = new FileParser(this);
         parser.ParseBoxHeaders();
         base.InvariantStartPosition = parser.MdatStartPosition;
         base.InvariantEndPosition = parser.MdatEndPosition;
         long sizeChange = 0L;
         long start = 0L;
         ByteVector data = this.udta_box.Render();
         if (((parser.UdtaTree == null) || (parser.UdtaTree.Length == 0)) || (parser.UdtaTree[parser.UdtaTree.Length - 1].BoxType != BoxType.Udta))
         {
             BoxHeader header = parser.MoovTree[parser.MoovTree.Length - 1];
             sizeChange = data.Count;
             start = header.Position + header.TotalBoxSize;
             base.Insert(data, start, 0L);
             for (int i = parser.MoovTree.Length - 1; i >= 0; i--)
             {
                 sizeChange = parser.MoovTree[i].Overwrite(this, sizeChange);
             }
         }
         else
         {
             BoxHeader header2 = parser.UdtaTree[parser.UdtaTree.Length - 1];
             sizeChange = data.Count - header2.TotalBoxSize;
             start = header2.Position;
             base.Insert(data, start, header2.TotalBoxSize);
             for (int j = parser.UdtaTree.Length - 2; j >= 0; j--)
             {
                 sizeChange = parser.UdtaTree[j].Overwrite(this, sizeChange);
             }
         }
         if (sizeChange != 0)
         {
             parser.ParseChunkOffsets();
             base.InvariantStartPosition = parser.MdatStartPosition;
             base.InvariantEndPosition = parser.MdatEndPosition;
             foreach (Box box in parser.ChunkOffsetBoxes)
             {
                 IsoChunkLargeOffsetBox box2 = box as IsoChunkLargeOffsetBox;
                 if (box2 != null)
                 {
                     box2.Overwrite(this, sizeChange, start);
                 }
                 else
                 {
                     IsoChunkOffsetBox box3 = box as IsoChunkOffsetBox;
                     if (box3 != null)
                     {
                         box3.Overwrite(this, sizeChange, start);
                     }
                 }
             }
         }
         base.TagTypesOnDisk = base.TagTypes;
     }
     finally
     {
         base.Mode = TagLib.File.AccessMode.Closed;
     }
 }
예제 #25
0
		/// <summary>
		///    Reads the file with a specified read style.
		/// </summary>
		/// <param name="propertiesStyle">
		///    A <see cref="ReadStyle" /> value specifying at what level
		///    of accuracy to read the media properties, or <see
		///    cref="ReadStyle.None" /> to ignore the properties.
		/// </param>
		private void Read (ReadStyle propertiesStyle)
		{
			// TODO: Support Id3v2 boxes!!!
			tag = new CombinedTag ();
			Mode = AccessMode.Read;
			try {
				FileParser parser = new FileParser (this);
				
				if (propertiesStyle == ReadStyle.None)
					parser.ParseTag ();
				else
					parser.ParseTagAndProperties ();
				
				InvariantStartPosition = parser.MdatStartPosition;
				InvariantEndPosition = parser.MdatEndPosition;
				
				udta_box = parser.UserDataBox;
				
				if (udta_box != null && udta_box.GetChild (BoxType.Meta)
					!= null && udta_box.GetChild (BoxType.Meta
					).GetChild (BoxType.Ilst) != null)
					TagTypesOnDisk |= TagTypes.Apple;
				
				if (udta_box == null)
					udta_box = new IsoUserDataBox ();
				
				apple_tag = new AppleTag (udta_box);
				tag.SetTags (apple_tag);
				
				// If we're not reading properties, we're done.
				if (propertiesStyle == ReadStyle.None) {
					Mode = AccessMode.Closed;
					return;
				}
				
				// Get the movie header box.
				IsoMovieHeaderBox mvhd_box = parser.MovieHeaderBox;
				if(mvhd_box == null) {
					Mode = AccessMode.Closed;
					throw new CorruptFileException (
						"mvhd box not found.");
				}
				
				IsoAudioSampleEntry  audio_sample_entry =
					parser.AudioSampleEntry;
				IsoVisualSampleEntry visual_sample_entry =
					parser.VisualSampleEntry;
				
				// Read the properties.
				properties = new Properties (mvhd_box.Duration,
					audio_sample_entry, visual_sample_entry);
			} finally {
				Mode = AccessMode.Closed;
			}
		}
예제 #26
0
		/// <summary>
		///    Parses boxes for a specified range, looking for tags.
		/// </summary>
		/// <param name="start">
		///    A <see cref="long" /> value specifying the seek position
		///    at which to start reading.
		/// </param>
		/// <param name="end">
		///    A <see cref="long" /> value specifying the seek position
		///    at which to stop reading.
		/// </param>
		private void ParseTag (long start, long end)
		{
			BoxHeader header;
			
			for (long position = start; position < end;
				position += header.TotalBoxSize) {
				header = new BoxHeader (file, position);
				
				if (header.BoxType == BoxType.Moov ||
					header.BoxType == BoxType.Mdia ||
					header.BoxType == BoxType.Minf ||
					header.BoxType == BoxType.Stbl ||
					header.BoxType == BoxType.Trak) {
					ParseTag (header.HeaderSize + position,
						header.TotalBoxSize + position);
				} else if (udta_box == null &&
					header.BoxType == BoxType.Udta) {
					udta_box = BoxFactory.CreateBox (file,
					header) as IsoUserDataBox;
				} else if (header.BoxType == BoxType.Mdat) {
					mdat_start = position;
					mdat_end = position + header.TotalBoxSize;
				}
				
				if (header.TotalBoxSize == 0)
					break;
			}
		}