예제 #1
0
        private AudioHeader(ByteVector data, TagLib.File file, long position)
        {
            this.duration = TimeSpan.Zero;
            stream_length = 0;
            string error = GetHeaderError(data);

            if (error != null)
            {
                throw new CorruptFileException(error);
            }
            flags       = data.ToUInt();
            xing_header = XingHeader.Unknown;
            vbri_header = VBRIHeader.Unknown;
            file.Seek(position + XingHeader.XingHeaderOffset(Version, ChannelMode));
            ByteVector xing_data = file.ReadBlock(16);

            if (xing_data.Count == 16 && xing_data.StartsWith(XingHeader.FileIdentifier))
            {
                xing_header = new XingHeader(xing_data);
            }
            if (xing_header.Present)
            {
                return;
            }
            file.Seek(position + VBRIHeader.VBRIHeaderOffset());
            ByteVector vbri_data = file.ReadBlock(24);

            if (vbri_data.Count == 24 && vbri_data.StartsWith(VBRIHeader.FileIdentifier))
            {
                vbri_header = new VBRIHeader(vbri_data);
            }
        }
예제 #2
0
        protected void Read(TagLib.File file)
        {
            if (file == null)
            {
                return;
            }

            try
            {
                file.Mode = FileAccessMode.Read;
            }
            catch (TagLibException)
            {
                return;
            }

            file.Seek(tagOffset);
            header.SetData(file.ReadBlock((int)Id3v2Header.Size));

            // if the tag size is 0, then this is an invalid tag (tags must contain
            // at least one frame)

            if (header.TagSize == 0)
            {
                return;
            }

            Parse(file.ReadBlock((int)header.TagSize));
        }
예제 #3
0
        /// <summary>
        ///    Populates the current instance be reading in a tag from
        ///    a specified position in a specified file.
        /// </summary>
        /// <param name="file">
        ///    A <see cref="TagLib.File" /> object to read the tag from.
        /// </param>
        /// <param name="position">
        ///    A <see cref="long" /> value specifying the seek position
        ///    at which to read the tag.
        /// </param>
        /// <exception cref="ArgumentNullException">
        ///    <paramref name="file" /> is <see langword="null" />.
        /// </exception>
        /// <exception name="ArgumentOutOfRangeException">
        ///    <paramref name="position" /> is less than 0 or greater
        ///    than the size of the file.
        /// </exception>
        protected void Read(TagLib.File file, long position)
        {
            if (file == null)
            {
                throw new ArgumentNullException("file");
            }

            file.Mode = File.AccessMode.Read;

            if (position < 0 || position > file.Length - Footer.Size)
            {
                throw new ArgumentOutOfRangeException(
                          "position");
            }

            file.Seek(position);
            footer = new Footer(file.ReadBlock((int)Footer.Size));

            if (footer.TagSize == 0)
            {
                throw new CorruptFileException(
                          "Tag size out of bounds.");
            }

            // If we've read a header, we don't have to seek to read
            // the content. If we've read a footer, we need to move
            // back to the start of the tag.
            if ((footer.Flags & FooterFlags.IsHeader) == 0)
            {
                file.Seek(position + Footer.Size - footer.TagSize);
            }

            Parse(file.ReadBlock((int)(footer.TagSize - Footer.Size)));
        }
예제 #4
0
        /// <summary>
        ///     Searches for an audio header in a <see cref="TagLib.File" /> starting at a specified position and searching through
        ///     a specified number of bytes.
        /// </summary>
        /// <param name="header">
        ///     A <see cref="AudioHeader" /> object in which the found
        ///     header will be stored.
        /// </param>
        /// <param name="file">
        ///     A <see cref="TagLib.File" /> object to search.
        /// </param>
        /// <param name="position">
        ///     A <see cref="long" /> value specifying the seek position
        ///     in <paramref name="file" /> at which to start searching.
        /// </param>
        /// <param name="length">
        ///     A <see cref="int" /> value specifying the maximum number
        ///     of bytes to search before aborting.
        /// </param>
        /// <returns>
        ///     A <see cref="bool" /> value indicating whether or not a
        ///     header was found.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        ///     <paramref name="file" /> is <see langword="null" />.
        /// </exception>
        public static bool Find(out AudioHeader header,
                                TagLib.File file, long position,
                                int length)
        {
            if (file == null)
            {
                throw new ArgumentNullException(nameof(file));
            }

            var end = position + length;

            header = Unknown;

            file.Seek(position);

            var buffer = file.ReadBlock(3);

            if (buffer.Count < 3)
            {
                return(false);
            }

            do
            {
                file.Seek(position + 3);
                buffer = buffer.Mid(buffer.Count - 3);
                buffer.Add(file.ReadBlock(
                               (int)TagLib.File.BufferSize));

                for (var i = 0;
                     i < buffer.Count - 3 &&
                     (length < 0 || position + i < end);
                     i++)
                {
                    if (buffer[i] == 0xFF &&
                        buffer[i + 1] > 0xE0)
                    {
                        var data = buffer.Mid(i, 4);
                        if (GetHeaderError(data) == null)
                        {
                            try
                            {
                                header = new AudioHeader(
                                    data,
                                    file, position + i);

                                return(true);
                            }
                            catch (CorruptFileException)
                            {
                            }
                        }
                    }
                }

                position += TagLib.File.BufferSize;
            } while (buffer.Count > 3 && (length < 0 || position < end));

            return(false);
        }
예제 #5
0
 public IsoVisualSampleEntry(BoxHeader header, TagLib.File file, IsoHandlerBox handler) :
     base(header, file, handler)
 {
     file.Seek(base.DataPosition + 16);
     width  = file.ReadBlock(2).ToUShort();
     height = file.ReadBlock(2).ToUShort();
 }
        /*
         * /// <summary>
         * ///    Contains the children of the box.
         * /// </summary>
         * private BoxList children;
         */

        #endregion



        #region Constructors

        /// <summary>
        ///    Constructs and initializes a new instance of <see
        ///    cref="IsoVisualSampleEntry" /> with a provided header and
        ///    handler by reading the contents from a specified file.
        /// </summary>
        /// <param name="header">
        ///    A <see cref="BoxHeader" /> object containing the header
        ///    to use for the new instance.
        /// </param>
        /// <param name="file">
        ///    A <see cref="TagLib.File" /> object to read the contents
        ///    of the box from.
        /// </param>
        /// <param name="handler">
        ///    A <see cref="IsoHandlerBox" /> object containing the
        ///    handler that applies to the new instance.
        /// </param>
        /// <exception cref="ArgumentNullException">
        ///    <paramref name="file" /> is <see langword="null" />.
        /// </exception>
        public IsoVisualSampleEntry(BoxHeader header, TagLib.File file,
                                    IsoHandlerBox handler)
            : base(header, file, handler)
        {
            file.Seek(base.DataPosition + 16);
            width  = file.ReadBlock(2).ToUShort();
            height = file.ReadBlock(2).ToUShort();

            /*
             * TODO: What are the children anyway?
             * children = LoadChildren (file);
             */
        }
예제 #7
0
        /// <summary>
        ///    Constructs and initializes a new instance of <see
        ///    cref="AudioHeader" /> by reading its contents from a
        ///    <see cref="ByteVector" /> object and its Xing Header from
        ///    the appropriate location in the specified file.
        /// </summary>
        /// <param name="data">
        ///    A <see cref="ByteVector" /> object containing the header
        ///    to read.
        /// </param>
        /// <param name="file">
        ///    A <see cref="TagLib.File" /> object to read the Xing
        ///    header from.
        /// </param>
        /// <param name="position">
        ///    A <see cref="long" /> value indicating the position in
        ///    <paramref name="file" /> at which the header begins.
        /// </param>
        /// <exception cref="CorruptFileException">
        ///    <paramref name="data" /> is less than 4 bytes long,
        ///    does not begin with a MPEG audio synch, has a negative
        ///    bitrate, or has a sample rate of zero.
        /// </exception>
        private AudioHeader(ByteVector data, TagLib.File file,
                            long position)
        {
            this.duration = TimeSpan.Zero;
            stream_length = 0;

            string error = GetHeaderError(data);

            if (error != null)
            {
                throw new CorruptFileException(error);
            }

            flags = data.ToUInt();

            xing_header = XingHeader.Unknown;

            vbri_header = VBRIHeader.Unknown;

            // Check for a Xing header that will help us in
            // gathering information about a VBR stream.
            file.Seek(position + XingHeader.XingHeaderOffset(
                          Version, ChannelMode));

            ByteVector xing_data = file.ReadBlock(16);

            if (xing_data.Count == 16 && xing_data.StartsWith(
                    XingHeader.FileIdentifier))
            {
                xing_header = new XingHeader(xing_data);
            }

            if (xing_header.Present)
            {
                return;
            }

            // A Xing header could not be found, next chec for a
            // Fraunhofer VBRI header.
            file.Seek(position + VBRIHeader.VBRIHeaderOffset());

            // Only get the first 24 bytes of the Header.
            // We're not interested in the TOC entries.
            ByteVector vbri_data = file.ReadBlock(24);

            if (vbri_data.Count == 24 &&
                vbri_data.StartsWith(VBRIHeader.FileIdentifier))
            {
                vbri_header = new VBRIHeader(vbri_data);
            }
        }
예제 #8
0
        /// <summary>
        ///    Searches for an audio header in a <see cref="TagLib.File"
        ///    /> starting at a specified position and searching through
        ///    a specified number of bytes.
        /// </summary>
        /// <param name="header">
        ///    A <see cref="AudioHeader" /> object in which the found
        ///    header will be stored.
        /// </param>
        /// <param name="file">
        ///    A <see cref="TagLib.File" /> object to search.
        /// </param>
        /// <param name="position">
        ///    A <see cref="long" /> value specifying the seek position
        ///    in <paramref name="file" /> at which to start searching.
        /// </param>
        /// <param name="length">
        ///    A <see cref="int" /> value specifying the maximum number
        ///    of bytes to search before aborting.
        /// </param>
        /// <returns>
        ///    A <see cref="bool" /> value indicating whether or not a
        ///    header was found.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        ///    <paramref name="file" /> is <see langref="null" />.
        /// </exception>
        public static bool Find(out AudioHeader header,
                                TagLib.File file, long position,
                                int length)
        {
            if (file == null)
            {
                throw new ArgumentNullException("file");
            }

            long end = position + length;

            header = AudioHeader.Unknown;

            file.Seek(position);

            ByteVector buffer = file.ReadBlock(3);

            if (buffer.Count < 3)
            {
                return(false);
            }

            do
            {
                file.Seek(position + 3);
                buffer = buffer.Mid(buffer.Count - 3);
                buffer.Add(file.ReadBlock(
                               (int)File.BufferSize));

                for (int i = 0; i < buffer.Count - 3 &&
                     (length < 0 || position + i < end); i++)
                {
                    if (buffer [i] == 0xFF &&
                        buffer [i + 1] > 0xE0)
                    {
                        try {
                            header = new AudioHeader(
                                buffer.Mid(i, 4),
                                file, position + i);
                            return(true);
                        } catch (CorruptFileException) {
                        }
                    }
                }

                position += File.BufferSize;
            } while (buffer.Count > 3 && (length < 0 || position < end));

            return(false);
        }
예제 #9
0
 public IsoAudioSampleEntry(BoxHeader header, TagLib.File file, IsoHandlerBox handler) :
     base(header, file, handler)
 {
     if (file == null)
     {
         throw new ArgumentNullException("file");
     }
     file.Seek(base.DataPosition + 8);
     channel_count = file.ReadBlock(2).ToUShort();
     sample_size   = file.ReadBlock(2).ToUShort();
     file.Seek(base.DataPosition + 16);
     sample_rate = file.ReadBlock(4).ToUInt();
     children    = LoadChildren(file);
 }
 /// <summary>
 ///    Constructs and initializes a new instance of <see
 ///    cref="AppleAdditionalInfoBox" /> with a provided header
 ///    and handler by reading the contents from a specified
 ///    file.
 /// </summary>
 /// <param name="header">
 ///    A <see cref="BoxHeader" /> object containing the header
 ///    to use for the new instance.
 /// </param>
 /// <param name="file">
 ///    A <see cref="TagLib.File" /> object to read the contents
 ///    of the box from.
 /// </param>
 /// <param name="handler">
 ///    A <see cref="IsoHandlerBox" /> object containing the
 ///    handler that applies to the new instance.
 /// </param>
 /// <exception cref="ArgumentNullException">
 ///    <paramref name="file" /> is <see langword="null" />.
 /// </exception>
 public AppleAdditionalInfoBox(BoxHeader header, TagLib.File file, IsoHandlerBox handler)
     : base(header, file, handler)
 {
     // We do not care what is in this custom data section
     // see: https://developer.apple.com/library/mac/#documentation/QuickTime/QTFF/QTFFChap2/qtff2.html
     Data = file.ReadBlock(DataSize > 0 ? DataSize : 0);
 }
예제 #11
0
        /// <summary>
        ///     Constructs and initializes a new instance of
        ///     <see
        ///         cref="VideoHeader" />
        ///     by reading it from a specified
        ///     location in a specified file.
        /// </summary>
        /// <param name="file">
        ///     A <see cref="TagLib.File" /> object to read from.
        /// </param>
        /// <param name="position">
        ///     A <see cref="long" /> value indicating the position in
        ///     <paramref name="file" /> at which the header begins.
        /// </param>
        /// <exception cref="ArgumentNullException">
        ///     <paramref name="file" /> is <see langword="null" />.
        /// </exception>
        /// <exception cref="CorruptFileException">
        ///     Insufficient data could be read for the header.
        /// </exception>
        public VideoHeader(TagLib.File file, long position)
        {
            if (file == null)
            {
                throw new ArgumentNullException(nameof(file));
            }

            file.Seek(position);
            var data = file.ReadBlock(7);

            if (data.Count < 7)
            {
                throw new CorruptFileException(
                          "Insufficient data in header.");
            }

            VideoWidth = data.Mid(0, 2)
                         .ToUShort() >> 4;

            VideoHeight = data.Mid(1, 2)
                          .ToUShort() & 0x0FFF;

            frame_rate_index = data[3] & 0x0F;
            VideoBitrate     = (int)((data.Mid(4, 3)
                                      .ToUInt() >> 6) &
                                     0x3FFFF);
        }
예제 #12
0
        /// <summary>
        ///    Looks for a tag ending at a specified position and moves
        ///    the cursor to its start position.
        /// </summary>
        /// <param name="position">
        ///    A <see cref="long" /> value reference specifying at what
        ///    position the potential tag starts. If a tag is found,
        ///    this value will be updated to the position at which the
        ///    found tag ends.
        /// </param>
        /// <returns>
        ///    A <see cref="TagLib.TagTypes" /> value specifying the
        ///    type of tag found at the specified position, or <see
        ///    cref="TagTypes.None" /> if no tag was found.
        /// </returns>
        private TagTypes ReadTagInfo(ref long position)
        {
            file.Seek(position);
            ByteVector data = file.ReadBlock(read_size);

            try {
                if (data.StartsWith(TagLib.Ape.Footer.FileIdentifier))
                {
                    TagLib.Ape.Footer footer =
                        new TagLib.Ape.Footer(data);

                    position += footer.CompleteTagSize;
                    return(TagTypes.Ape);
                }

                if (data.StartsWith(TagLib.Id3v2.Header.FileIdentifier))
                {
                    TagLib.Id3v2.Header header =
                        new TagLib.Id3v2.Header(data);

                    position += header.CompleteTagSize;
                    return(TagTypes.Id3v2);
                }
            } catch (CorruptFileException) {
            }

            return(TagTypes.None);
        }
예제 #13
0
        /// <summary>
        ///    Looks for a tag ending at a specified position and moves
        ///    the cursor to its start position.
        /// </summary>
        /// <param name="position">
        ///    A <see cref="long" /> value reference specifying at what
        ///    position the potential tag ends. If a tag is found,
        ///    this value will be updated to the position at which the
        ///    found tag starts.
        /// </param>
        /// <returns>
        ///    A <see cref="TagLib.TagTypes" /> value specifying the
        ///    type of tag found at the specified position, or <see
        ///    cref="TagTypes.None" /> if no tag was found.
        /// </returns>
        private TagTypes ReadTagInfo(ref long position)
        {
            if (position - read_size < 0)
            {
                return(TagTypes.None);
            }

            file.Seek(position - read_size);
            ByteVector data = file.ReadBlock(read_size);

            try
            {
                int offset = (int)(data.Count - TagLib.Ape.Footer.Size);
                if (data.ContainsAt(TagLib.Ape.Footer.FileIdentifier,
                                    offset))
                {
                    TagLib.Ape.Footer footer =
                        new TagLib.Ape.Footer(
                            data.Mid(offset));

                    // If the complete tag size is zero or
                    // the tag is a header, this indicates
                    // some sort of corruption.
                    if (footer.CompleteTagSize == 0 ||
                        (footer.Flags &
                         TagLib.Ape.FooterFlags.IsHeader) != 0)
                    {
                        return(TagTypes.None);
                    }

                    position -= footer.CompleteTagSize;
                    return(TagTypes.Ape);
                }

                offset = (int)(data.Count - TagLib.Id3v2.Footer.Size);
                if (data.ContainsAt(TagLib.Id3v2.Footer.FileIdentifier,
                                    offset))
                {
                    TagLib.Id3v2.Footer footer =
                        new TagLib.Id3v2.Footer(
                            data.Mid(offset));

                    position -= footer.CompleteTagSize;
                    return(TagTypes.Id3v2);
                }

                if (data.StartsWith(
                        TagLib.Id3v1.Tag.FileIdentifier))
                {
                    position -= TagLib.Id3v1.Tag.Size;
                    return(TagTypes.Id3v1);
                }
            }
            catch (CorruptFileException)
            {
            }

            return(TagTypes.None);
        }
예제 #14
0
        /// <summary>
        ///    Constructs and initializes a new instance of <see
        ///    cref="BoxHeader" /> by reading it from a specified seek
        ///    position in a specified file.
        /// </summary>
        /// <param name="file">
        ///    A <see cref="TagLib.File" /> object to read the new
        ///    instance from.
        /// </param>
        /// <param name="position">
        ///    A <see cref="long" /> value specifiying the seek position
        ///    in <paramref name="file" /> at which to start reading.
        /// </param>
        /// <exception cref="ArgumentNullException">
        ///    <paramref name="file" /> is <see langword="null" />.
        /// </exception>
        /// <exception cref="CorruptFileException">
        ///    There isn't enough data in the file to read the complete
        ///    header.
        /// </exception>
        public BoxHeader(TagLib.File file, long position)
        {
            if (file == null)
            {
                throw new ArgumentNullException("file");
            }

            this.box       = null;
            this.from_disk = true;
            this.position  = position;
            file.Seek(position);

            ByteVector data   = file.ReadBlock(32);
            int        offset = 0;

            if (data.Count < 8 + offset)
            {
                throw new CorruptFileException(
                          "Not enough data in box header.");
            }

            header_size = 8;
            box_size    = data.Mid(offset, 4).ToUInt();
            box_type    = data.Mid(offset + 4, 4);

            // If the size is 1, that just tells us we have a
            // massive ULONG size waiting for us in the next 8
            // bytes.
            if (box_size == 1)
            {
                if (data.Count < 8 + offset)
                {
                    throw new CorruptFileException(
                              "Not enough data in box header.");
                }

                header_size += 8;
                box_size     = data.Mid(offset, 8).ToULong();
                offset      += 8;
            }

            // UUID has a special header with 16 extra bytes.
            if (box_type == Mpeg4.BoxType.Uuid)
            {
                if (data.Count < 16 + offset)
                {
                    throw new CorruptFileException(
                              "Not enough data in box header.");
                }

                header_size  += 16;
                extended_type = data.Mid(offset, 16);
            }
            else
            {
                extended_type = null;
            }
        }
예제 #15
0
        /// <summary>
        ///    Constructs and initializes a new instance of <see
        ///    cref="UnknownBox" /> with a provided header and handler
        ///    by reading the contents from a specified file.
        /// </summary>
        /// <param name="header">
        ///    A <see cref="BoxHeader" /> object containing the header
        ///    to use for the new instance.
        /// </param>
        /// <param name="file">
        ///    A <see cref="TagLib.File" /> object to read the contents
        ///    of the box from.
        /// </param>
        /// <param name="handler">
        ///    A <see cref="IsoHandlerBox" /> object containing the
        ///    handler that applies to the new instance.
        /// </param>
        /// <exception cref="ArgumentNullException">
        ///    <paramref name="file" /> is <see langword="null" />.
        /// </exception>
        public UnknownBox(BoxHeader header, TagLib.File file, IsoHandlerBox handler) : base(header, handler)
        {
            if (file == null)
            {
                throw new ArgumentNullException(nameof(file));
            }

            data = file.ReadBlock(DataSize > 0 ? DataSize : 0);
        }
예제 #16
0
 public IsoSampleDescriptionBox(BoxHeader header, TagLib.File file, IsoHandlerBox handler) :
     base(header, file, handler)
 {
     if (file == null)
     {
         throw new ArgumentNullException("file");
     }
     entry_count = file.ReadBlock(4).ToUInt();
     children    = LoadChildren(file);
 }
예제 #17
0
        /// <summary>
        ///    Loads the data of the current instance from a specified
        ///    file using the internal data position and size.
        /// </summary>
        /// <param name="file">
        ///    The <see cref="TagLib.File" /> from which the current
        ///    instance was read and from which to read the data.
        /// </param>
        /// <returns>
        ///    A <see cref="ByteVector" /> object containing the data
        ///    read from the file.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        ///    <paramref name="file" /> is <see langref="null" />.
        /// </exception>
        protected ByteVector LoadData(TagLib.File file)
        {
            if (file == null)
            {
                throw new ArgumentNullException("file");
            }

            file.Seek(DataPosition);
            return(file.ReadBlock(DataSize));
        }
예제 #18
0
        protected ListTag(TagLib.File file, long position, int length)
        {
            if (file == null)
            {
                throw new System.ArgumentNullException("file");
            }

            file.Seek(position);
            fields = new List(file.ReadBlock(length));
        }
예제 #19
0
 public IsoSampleEntry(BoxHeader header, TagLib.File file, IsoHandlerBox handler) :
     base(header, handler)
 {
     if (file == null)
     {
         throw new ArgumentNullException("file");
     }
     file.Seek(base.DataPosition + 6);
     data_reference_index = file.ReadBlock(2).ToUShort();
 }
예제 #20
0
        public IsoChunkLargeOffsetBox(BoxHeader header, TagLib.File file, IsoHandlerBox handler) :
            base(header, file, handler)
        {
            ByteVector box_data = file.ReadBlock(DataSize);

            offsets = new ulong[(int)box_data.Mid(0, 4).ToUInt()];
            for (int i = 0; i < offsets.Length; i++)
            {
                offsets[i] = box_data.Mid(4 + i * 8, 8).ToULong();
            }
        }
예제 #21
0
        protected FullBox(BoxHeader header, TagLib.File file, IsoHandlerBox handler) :
            base(header, handler)
        {
            if (file == null)
            {
                throw new ArgumentNullException("file");
            }
            file.Seek(base.DataPosition);
            ByteVector header_data = file.ReadBlock(4);

            version = header_data[0];
            flags   = header_data.Mid(1, 3).ToUInt();
        }
예제 #22
0
 protected void Read(TagLib.File file, long position)
 {
     if (file == null)
     {
         throw new ArgumentNullException("file");
     }
     file.Mode = File.AccessMode.Read;
     if (position < 0 || position > file.Length - Footer.Size)
     {
         throw new ArgumentOutOfRangeException("position");
     }
     file.Seek(position);
     footer = new Footer(file.ReadBlock((int)Footer.Size));
     if (footer.TagSize == 0)
     {
         throw new CorruptFileException("Tag size out of bounds.");
     }
     if ((footer.Flags & FooterFlags.IsHeader) == 0)
     {
         file.Seek(position + Footer.Size - footer.TagSize);
     }
     Parse(file.ReadBlock((int)(footer.TagSize - Footer.Size)));
 }
예제 #23
0
        public BoxHeader(TagLib.File file, long position)
        {
            if (file == null)
            {
                throw new ArgumentNullException("file");
            }
            this.box       = null;
            this.from_disk = true;
            this.position  = position;
            file.Seek(position);
            ByteVector data   = file.ReadBlock(32);
            int        offset = 0;

            if (data.Count < 8 + offset)
            {
                throw new CorruptFileException("Not enough data in box header.");
            }
            header_size = 8;
            box_size    = data.Mid(offset, 4).ToUInt();
            box_type    = data.Mid(offset + 4, 4);
            if (box_size == 1)
            {
                if (data.Count < 8 + offset)
                {
                    throw new CorruptFileException("Not enough data in box header.");
                }
                header_size += 8;
                box_size     = data.Mid(offset, 8).ToULong();
                offset      += 8;
            }
            if (box_type == Mpeg4.BoxType.Uuid)
            {
                if (data.Count < 16 + offset)
                {
                    throw new CorruptFileException("Not enough data in box header.");
                }
                header_size  += 16;
                extended_type = data.Mid(offset, 16);
            }
            else
            {
                extended_type = null;
            }
            if (box_size > (ulong)(file.Length - position))
            {
                throw new CorruptFileException("Box header specified a size of {0} bytes but only {1} bytes left in the file");
            }
        }
예제 #24
0
 public List(TagLib.File file, long position, int length)
 {
     if (file == null)
     {
         throw new ArgumentNullException("file");
     }
     if (length < 0)
     {
         throw new ArgumentOutOfRangeException("length");
     }
     if (position < 0 || position > file.Length - length)
     {
         throw new ArgumentOutOfRangeException("position");
     }
     file.Seek(position);
     Parse(file.ReadBlock(length));
 }
예제 #25
0
        /// <summary>
        ///     Constructs and initializes a new instance of
        ///     <see
        ///         cref="IsoChunkOffsetBox" />
        ///     with a provided header and
        ///     handler by reading the contents from a specified file.
        /// </summary>
        /// <param name="header">
        ///     A <see cref="BoxHeader" /> object containing the header
        ///     to use for the new instance.
        /// </param>
        /// <param name="file">
        ///     A <see cref="TagLib.File" /> object to read the contents
        ///     of the box from.
        /// </param>
        /// <param name="handler">
        ///     A <see cref="IsoHandlerBox" /> object containing the
        ///     handler that applies to the new instance.
        /// </param>
        public IsoChunkOffsetBox(BoxHeader header, TagLib.File file,
                                 IsoHandlerBox handler)
            : base(header, file, handler)
        {
            var box_data = file.ReadBlock(DataSize);

            Offsets = new uint [(int)
                                box_data.Mid(0, 4)
                                .ToUInt()];

            for (var i = 0; i < Offsets.Length; i++)
            {
                Offsets[i] = box_data.Mid(4 + i * 4,
                                          4)
                             .ToUInt();
            }
        }
예제 #26
0
        public AppleElementaryStreamDescriptor(BoxHeader header, TagLib.File file, IsoHandlerBox handler) :
            base(header, file, handler)
        {
            int        offset   = 0;
            ByteVector box_data = file.ReadBlock(DataSize);

            decoder_config = new ByteVector();
            if (box_data[offset++] == 3)
            {
                if (ReadLength(box_data, ref offset) < 20)
                {
                    throw new CorruptFileException("Insufficient data present.");
                }
                es_id           = box_data.Mid(offset, 2).ToUShort();
                offset         += 2;
                stream_priority = box_data[offset++];
            }
            else
            {
                es_id   = box_data.Mid(offset, 2).ToUShort();
                offset += 2;
            }
            if (box_data[offset++] != 4)
            {
                throw new CorruptFileException("Could not identify decoder configuration descriptor.");
            }
            if (ReadLength(box_data, ref offset) < 15)
            {
                throw new CorruptFileException("Could not read data. Too small.");
            }
            object_type_id  = box_data[offset++];
            stream_type     = box_data[offset++];
            buffer_size_db  = box_data.Mid(offset, 3).ToUInt();
            offset         += 3;
            max_bitrate     = box_data.Mid(offset, 4).ToUInt();
            offset         += 4;
            average_bitrate = box_data.Mid(offset, 4).ToUInt();
            offset         += 4;
            if (box_data[offset++] != 5)
            {
                throw new CorruptFileException("Could not identify decoder specific descriptor.");
            }
            uint length = ReadLength(box_data, ref offset);

            decoder_config = box_data.Mid(offset, (int)length);
        }
예제 #27
0
 /// <summary>
 /// get the sha1 of media file data (not including tag info)
 /// </summary>
 /// <param name="file"></param>
 /// <returns></returns>
 public static byte[] MediaSHA1(TagLib.File file)
 {
     try
     {
         int len = (int)file.InvariantEndPosition - (int)file.InvariantStartPosition;
         file.Seek(file.InvariantStartPosition);
         //
         TagLib.ByteVector vector = file.ReadBlock(len);
         //
         byte[] data = vector.Data;
         return(Utility.CryptoFunctions.SHA1(data));
     }
     catch (OutOfMemoryException e)
     {
         Trace.WriteLine("OutOfMemoryException - " + file, Utility.Logger.Level.Error.ToString());
         return(null);
     }
 }
예제 #28
0
        public IsoHandlerBox(BoxHeader header, TagLib.File file, IsoHandlerBox handler) :
            base(header, file, handler)
        {
            if (file == null)
            {
                throw new System.ArgumentNullException("file");
            }
            file.Seek(DataPosition + 4);
            ByteVector box_data = file.ReadBlock(DataSize - 4);

            handler_type = box_data.Mid(0, 4);
            int end = box_data.Find((byte)0, 16);

            if (end < 16)
            {
                end = box_data.Count;
            }
            name = box_data.ToString(StringType.UTF8, 16, end - 16);
        }
예제 #29
0
        public IsoHandlerBox(BoxHeader header, TagLib.File file,
                             IsoHandlerBox handler)
            : base(header, file, handler)
        {
            if (file == null)
            {
                throw new ArgumentNullException("file");
            }

            file.Seek(DataPosition + 4);
            var box_data = file.ReadBlock(DataSize - 4);

            HandlerType = box_data.Mid(0, 4);

            var end = box_data.Find((byte)0, 16);

            if (end < 16)
            {
                end = box_data.Count;
            }
            Name = end > 16 ? box_data.ToString(StringType.UTF8, 16, end - 16) : string.Empty;
        }
예제 #30
0
        /// <summary>
        ///     Searches for an audio header in a <see cref="TagLib.File" /> starting at a specified position and searching through
        ///     a specified number of bytes.
        /// </summary>
        /// <param name="header">
        ///     A <see cref="AudioHeader" /> object in which the found
        ///     header will be stored.
        /// </param>
        /// <param name="file">
        ///     A <see cref="TagLib.File" /> object to search.
        /// </param>
        /// <param name="position">
        ///     A <see cref="long" /> value specifying the seek position
        ///     in <paramref name="file" /> at which to start searching.
        /// </param>
        /// <param name="length">
        ///     A <see cref="int" /> value specifying the maximum number
        ///     of bytes to search before aborting.
        /// </param>
        /// <returns>
        ///     A <see cref="bool" /> value indicating whether or not a
        ///     header was found.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        ///     <paramref name="file" /> is <see langword="null" />.
        /// </exception>
        public static bool Find(out AudioHeader header,
                                TagLib.File file, long position, int length)
        {
            if (file == null)
            {
                throw new ArgumentNullException(nameof(file));
            }

            var end = position + length;

            header = Unknown;

            file.Seek(position);

            var buffer = file.ReadBlock(3);

            if (buffer.Count < 3)
            {
                return(false);
            }

            do
            {
                file.Seek(position + 3);
                buffer = buffer.Mid(buffer.Count - 3);
                buffer.Add(file.ReadBlock(
                               (int)TagLib.File.BufferSize));

                for (var i = 0;
                     i < buffer.Count - 3 &&
                     (length < 0 || position + i < end);
                     i++)
                {
                    if (buffer[i] == 0xFF &&
                        buffer[i + 1] >= 0xF0)                        // 0xFFF
                    {
                        try
                        {
                            var bits = new BitStream(buffer.Mid(i, 7)
                                                     .Data);

                            // 12 bits sync header
                            bits.ReadInt32(12);

                            // 1 bit mpeg 2/4
                            bits.ReadInt32(1);

                            // 2 bits layer
                            bits.ReadInt32(2);

                            // 1 bit protection absent
                            bits.ReadInt32(1);

                            // 2 bits profile object type
                            bits.ReadInt32(2);

                            // 4 bits sampling frequency index
                            var samplerateindex = bits.ReadInt32(4);
                            if (samplerateindex >= sample_rates.Length)
                            {
                                return(false);
                            }

                            long samplerate = sample_rates[samplerateindex];

                            // 1 bit private bit
                            bits.ReadInt32(1);

                            // 3 bits channel configuration
                            var channelconfigindex = bits.ReadInt32(3);
                            if (channelconfigindex >= channels.Length)
                            {
                                return(false);
                            }

                            // 4 copyright bits
                            bits.ReadInt32(4);

                            // 13 bits frame length
                            long framelength = bits.ReadInt32(13);                             // double check framelength
                            if (framelength < 7)
                            {
                                return(false);
                            }

                            // 11 bits buffer fullness
                            bits.ReadInt32(11);

                            // 2 bits number of raw data blocks in frame
                            var numberofframes = bits.ReadInt32(2) + 1;

                            long numberofsamples = numberofframes * 1024;
                            var  bitrate         = framelength * 8 * samplerate / numberofsamples;

                            header = new AudioHeader(channels[channelconfigindex],
                                                     (int)bitrate,
                                                     (int)samplerate,
                                                     (int)numberofsamples,
                                                     numberofframes);

                            return(true);
                        }
                        catch (CorruptFileException)
                        {
                        }
                    }
                }

                position += TagLib.File.BufferSize;
            } while (buffer.Count > 3 && (length < 0 || position < end));

            return(false);
        }