// We can make our own handler.
        public Mpeg4IsoHandlerBox(ByteVector handlerType, string name, Mpeg4Box parent) : base("hdlr", 0, parent)
        {
            if (handlerType != null)
            {
                this.handlerType = handlerType.Mid(0, 4);
            }

            this.name = name;
        }
Exemplo n.º 2
0
        protected void Parse(ByteVector data)
        {
            if (data != null)
            {
                // The first thing in the comment data is the vendor ID length, followed by a
                // UTF8 string with the vendor ID.

                int pos = 0;

                int vendorLength = (int)data.Mid(0, 4).ToUInt(false);
                pos += 4;

                vendorId = data.Mid(pos, vendorLength).ToString(StringType.UTF8);
                pos     += vendorLength;

                // Next the number of fields in the comment vector.

                int commentFields = (int)data.Mid(pos, 4).ToUInt(false);
                pos += 4;

                for (int i = 0; i < commentFields; i++)
                {
                    // Each comment field is in the format "KEY=value" in a UTF8 string and has
                    // 4 buffer before the type starts that gives the length.

                    int commentLength = (int)data.Mid(pos, 4).ToUInt(false);
                    pos += 4;

                    string comment = data.Mid(pos, commentLength).ToString(StringType.UTF8);
                    pos += commentLength;

                    int commentSeparatorPosition = comment.IndexOf('=');

                    string key   = comment.Substring(0, commentSeparatorPosition);
                    string value = comment.Substring(commentSeparatorPosition + 1);

                    AddField(key, value, false);
                }
            }
            else
            {
                throw new ArgumentNullException("data");
            }
        }
Exemplo n.º 3
0
        //private void Read(ByteVector data, long stream_length, ReadStyle style)
        private void Read(ByteVector data, long streamLength)
        {
            if (data.StartsWith("MP+"))
            {
                return;
            }

            version = data[3] & 15;

            uint frames;

            if (version >= 7)
            {
                frames = data.Mid(4, 4).ToUInt(false);
                uint flags = data.Mid(8, 4).ToUInt(false);
                sampleRate = sfTable[(int)(((flags >> 17) & 1) * 2 + ((flags >> 16) & 1))];
                channels   = 2;
            }
            else
            {
                uint headerData = data.Mid(0, 4).ToUInt(false);
                bitrate    = (int)((headerData >> 23) & 0x01ff);
                version    = (int)((headerData >> 11) & 0x03ff);
                sampleRate = 44100;
                channels   = 2;
                if (version >= 5)
                {
                    frames = data.Mid(4, 4).ToUInt(false);
                }
                else
                {
                    frames = data.Mid(4, 2).ToUInt(false);
                }
            }

            uint samples = frames * 1152 - 576;

            duration = sampleRate > 0 ? TimeSpan.FromSeconds((double)samples / (double)sampleRate + 0.5) : TimeSpan.Zero;

            if (bitrate == 0)
            {
                bitrate = (int)(duration > TimeSpan.Zero ? ((streamLength * 8L) / duration.TotalSeconds) / 1000 : 0);
            }
        }
Exemplo n.º 4
0
 protected void Parse(ByteVector data)
 {
     if (data != null)
     {
         size = Id3v2SynchData.ToUInt(data.Mid(0, 4));
     }
     else
     {
         throw new ArgumentNullException("data");
     }
 }
Exemplo n.º 5
0
        protected ByteVector FieldData(ByteVector frameData)
        {
            if (frameData != null)
            {
                uint headerSize = Id3v2FrameHeader.Size(header.Version);

                uint frameDataOffset = headerSize;
                uint frameDataLength = Size;

                if (header.Compression || header.DataLengthIndicator)
                {
                    frameDataLength  = frameData.Mid((int)headerSize, 4).ToUInt();
                    frameDataLength += 4;
                }

                // FIXME: Impliment compression and encrpytion.

                /*
                 #if HAVE_ZLIB
                 * if(d->header->compression()) {
                 *        ByteVector data(frameDataLength);
                 *        uLongf uLongTmp = frameDataLength;
                 *        ::uncompress((Bytef *) data.data(),
                 *                                (uLongf *) &uLongTmp,
                 *                                (Bytef *) frameData.data() + frameDataOffset,
                 *                                size());
                 *        return data;
                 * }
                 * else
                 #endif
                 */

                return(frameData.Mid((int)frameDataOffset, (int)frameDataLength));
            }
            else
            {
                throw new ArgumentNullException("frameData");
            }
        }
Exemplo n.º 6
0
        protected void Parse(ByteVector data)
        {
            if (data.Count < Size)
            {
                return;
            }

            // do some sanity checking -- even in ID3v2.3.0 and less the tag size is a
            // synch-safe integer, so all buffer must be less than 128.  If this is not
            // true then this is an invalid tag.

            // note that we're doing things a little out of order here -- the size is
            // later in the bytestream than the version

            ByteVector sizeData = data.Mid(6, 4);

            if (sizeData.Count != 4)
            {
                tagSize = 0;
                TagLibDebugger.Debug("ID3v2.Header.Parse () - The tag size as read was 0 bytes!");
                return;
            }

            foreach (byte b in sizeData)
            {
                if (b >= 128)
                {
                    tagSize = 0;
                    TagLibDebugger.Debug("ID3v2.Header.Parse () - One of the size bytes in the id3v2 header was greater than the allowed 128.");
                    return;
                }
            }

            // The first three buffer, data[0..2], are the File Identifier, "ID3". (structure 3.1 "file identifier")

            // Read the version number from the fourth and fifth buffer.
            majorVersion   = data[3];             // (structure 3.1 "major version")
            revisionNumber = data[4];             // (structure 3.1 "revision number")

            // Read the flags, the first four bits of the sixth byte.
            byte flags = data[5];

            desynchronization     = ((flags >> 7) & 1) == 1;     // (structure 3.1.a)
            extendedHeader        = ((flags >> 6) & 1) == 1;     // (structure 3.1.b)
            experimentalIndicator = ((flags >> 5) & 1) == 1;     // (structure 3.1.channelMode)
            footerPresent         = ((flags >> 4) & 1) == 1;     // (structure 3.1.d)

            // Get the size from the remaining four buffer (read above)

            tagSize = Id3v2SynchData.ToUInt(sizeData);             // (structure 3.1 "size")
        }
Exemplo n.º 7
0
        private void ParseCommentsFields(ByteVector data)
        {
            if (data.Count < 5)
            {
                TagLibDebugger.Debug("A comment frame must contain at least 5 bytes.");
                return;
            }

            textEncoding = (StringType)data[0];
            language     = data.Mid(1, 3);

            int byte_align = textEncoding == StringType.Latin1 || textEncoding == StringType.UTF8 ? 1 : 2;

            ByteVectorCollection l = ByteVectorCollection.Split(data.Mid(4), TextDelimiter(textEncoding), byte_align, 2);

            if (l.Count == 2)
            {
                if (l[0].Data != null && l[0].Data.Count > 0)
                {
                    description = l[0].ToString(textEncoding);
                }
                else
                {
                    description = string.Empty;
                }

                if (l[1].Data != null && l[1].Data.Count > 0)
                {
                    text = l[1].ToString(textEncoding);
                }
                else
                {
                    text = string.Empty;
                }
            }
        }
Exemplo n.º 8
0
        public ByteVector Render()
        {
            // The size is zero because the box header was created not read.
            // Increase the sizes to account for this.
            if (size == 0)
            {
                size       = (uint)(extendedType != null ? 24 : 8);
                largeSize += size;
            }

            // Enlarge for large size if necessary. If large size is in use, the
            // header will be 16 or 32 big as opposed to 8 or 24.
            if ((size == 8 || size == 24) && largeSize > System.UInt32.MaxValue)
            {
                size      += 8;
                largeSize += 8;
            }

            // Get ready to output.
            ByteVector output = new ByteVector();

            // Add the box size and type to the output.
            output += ByteVector.FromUInt((size == 8 || size == 24) ? (uint)largeSize : 1);
            output += boxType;

            // If the box size is 16 or 32, we must have more a large header to
            // append.
            if (size == 16 || size == 32)
            {
                output += ByteVector.FromLong((long)largeSize);
            }

            // The only reason for such a big size is an extended type. Extend!!!
            if (size >= 24)
            {
                output += (extendedType != null) ? extendedType.Mid(0, 16) : new ByteVector(16);
            }

            return(output);
        }
Exemplo n.º 9
0
        protected void Parse(ByteVector data)
        {
            if (data != null)
            {
                int position = 0;

                // 11 buffer is the minimum size for an APE item
                for (uint i = 0; i < footer.ItemCount && position <= data.Count - 11; i++)
                {
                    ApeItem item = new ApeItem();
                    item.Parse(data.Mid(position));

                    SetItem(item.Key, item);

                    position += item.Size;
                }
            }
            else
            {
                throw new ArgumentNullException("data");
            }
        }
        private void ParseTextIdentifierFields(ByteVector data)
        {
            // read the string data type (the first byte of the field data)

            textEncoding = (StringType)data[0];

            // split the byte numbers into chunks based on the string type (two byte delimiter
            // for unicode encodings)

            int byteAlign = textEncoding == StringType.Latin1 || textEncoding == StringType.UTF8 ? 1 : 2;

            ByteVectorCollection list = ByteVectorCollection.Split(data.Mid(1), TextDelimiter(textEncoding), byteAlign);

            fieldList.Clear();

            // append those split values to the text and make sure that the new string'field
            // type is the same specified for this frame

            foreach (ByteVector vector in list)
            {
                fieldList.Add(vector.ToString(textEncoding));
            }
        }
Exemplo n.º 11
0
        protected void Parse(ByteVector data)
        {
            if (data != null)
            {
                int offset = 3;

                title   = stringHandler.Parse(data.Mid(offset, 30));
                offset += 30;

                artist  = stringHandler.Parse(data.Mid(offset, 30));
                offset += 30;

                album   = stringHandler.Parse(data.Mid(offset, 30));
                offset += 30;

                year    = stringHandler.Parse(data.Mid(offset, 4));
                offset += 4;

                // Check for ID3v1.1 -- Note that ID3v1 *does not* support "track zero" -- this
                // is not a bug in TagLib.  Since a zeroed byte is what we would expect to
                // indicate the end of a C-String, specifically the comment string, a value of
                // zero must be assumed to be just that.

                if (data[offset + 28] == 0 && data[offset + 29] != 0)
                {
                    // ID3v1.1 detected

                    comment = stringHandler.Parse(data.Mid(offset, 28));
                    track   = data[offset + 29];
                }
                else
                {
                    comment = stringHandler.Parse(data.Mid(offset, 30));
                }

                offset += 30;

                genre = data[offset];
            }
            else
            {
                throw new ArgumentNullException("data");
            }
        }
        //private void Read(OggVorbisFile file, ReadStyle style)
        private void Read(OggVorbisFile file)
        {
            // Get the identification header from the Ogg implementation.

            ByteVector data = file.GetPacket(0);

            int pos = 0;

            if (data.Mid(pos, 7) != vorbisCommentHeaderId)
            {
                TagLibDebugger.Debug("Vorbis.Properties.Read() -- invalid Vorbis identification header");
                return;
            }

            pos += 7;

            vorbisVersion = (int)data.Mid(pos, 4).ToUInt(false);
            pos          += 4;

            channels = data[pos];
            pos     += 1;

            sampleRate = (int)data.Mid(pos, 4).ToUInt(false);
            pos       += 4;

            bitrateMaximum = (int)data.Mid(pos, 4).ToUInt(false);
            pos           += 4;

            bitrateNominal = (int)data.Mid(pos, 4).ToUInt(false);
            pos           += 4;

            bitrateMinimum = (int)data.Mid(pos, 4).ToUInt(false);

            // TODO: Later this should be only the "fast" mode.
            bitrate = bitrateNominal;

            // Find the length of the file.  See http://wiki.xiph.org/VorbisStreamLength/
            // for my notes on the topic.

            OggPageHeader first = file.FirstPageHeader;
            OggPageHeader last  = file.LastPageHeader;

            if (first != null && last != null)
            {
                long start = first.AbsoluteGranularPosition;
                long end   = last.AbsoluteGranularPosition;

                if (start >= 0 && end >= 0 && sampleRate > 0)
                {
                    duration = TimeSpan.FromSeconds(((double)(end - start) / (double)sampleRate));
                }
                else
                {
                    TagLibDebugger.Debug("Vorbis.Properties.Read() -- Either the PCM " +
                                         "values for the start or end of this file was " +
                                         "incorrect or the sample rate is zero.");
                }
            }
            else
            {
                TagLibDebugger.Debug("Vorbis.Properties.Read() -- Could not find valid first and last Ogg pages.");
            }
        }
Exemplo n.º 13
0
        protected void Parse(ByteVector data)
        {
            if (data != null)
            {
                try
                {
                    int frameDataPosition = 0;
                    int frameDataLength   = data.Count;

                    // check for extended header

                    if (header.ExtendedHeader)
                    {
                        if (ExtendedHeader == null)
                        {
                            extendedHeader = new Id3v2ExtendedHeader();
                        }

                        ExtendedHeader.SetData(data);

                        if (ExtendedHeader.Size <= data.Count)
                        {
                            frameDataPosition += (int)ExtendedHeader.Size;
                            frameDataLength   -= (int)ExtendedHeader.Size;
                        }
                    }

                    // check for footer -- we don'type actually need to parse it, as it *must*
                    // contain the same data as the header, but we do need to account for its
                    // size.

                    if (header.FooterPresent && Id3v2Footer.Size <= frameDataLength)
                    {
                        frameDataLength -= (int)Id3v2Footer.Size;
                    }

                    // parse frames

                    // Make sure that there is at least enough room in the remaining frame data for
                    // a frame header.

                    while (frameDataPosition < frameDataLength - Id3v2FrameHeader.Size(header.MajorVersion))
                    {
                        // If the next data is position is 0, assume that we've hit the padding
                        // portion of the frame data.
                        if (data[frameDataPosition] == 0)
                        {
                            if (header.FooterPresent)
                            {
                                TagLibDebugger.Debug("Padding *and* a footer found.  This is not allowed by the spec.");
                            }

                            return;
                        }

                        Id3v2Frame frame = Id3v2FrameFactory.CreateFrame(data.Mid(frameDataPosition), header.MajorVersion);

                        if (frame == null)
                        {
                            return;
                        }

                        // Checks to make sure that frame parsed correctly.
                        if (frame.Size < 0)
                        {
                            return;
                        }

                        frameDataPosition += (int)(frame.Size + Id3v2FrameHeader.Size(header.MajorVersion));
                        // Only add frames with content so we don'type send out just we got in.
                        if (frame.Size > 0)
                        {
                            AddFrame(frame);
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw new ApplicationException("There was an error parsing this ID3 tag", ex);
                }
            }
            else
            {
                throw new ArgumentNullException("data");
            }
        }
Exemplo n.º 14
0
        public Mpeg4IsoMovieHeaderBox(Mpeg4BoxHeader header, Mpeg4Box parent) : base(header, parent)
        {
            // Size depends on version.
            boxSize = Version == 1 ? 108 : 96;

            // Get everything.
            File.Seek(base.DataPosition);
            ByteVector data = File.ReadBlock(boxSize);
            int        pos  = 0;

            // Read version one (large integers).
            if (Version == 1)
            {
                if (data.Count >= pos + 8)
                {
                    creationTime = (ulong)data.Mid(pos, 8).ToLong();
                }
                pos += 8;

                if (data.Count >= pos + 8)
                {
                    modificationTime = (ulong)data.Mid(pos, 8).ToLong();
                }
                pos += 8;

                if (data.Count >= pos + 4)
                {
                    timescale = data.Mid(pos, 4).ToUInt();
                }
                pos += 4;

                if (data.Count >= pos + 8)
                {
                    duration = (ulong)data.Mid(pos, 8).ToLong();
                }
                pos += 8;
            }
            // Read version zero (normal integers).
            else
            {
                if (data.Count >= pos + 4)
                {
                    creationTime = data.Mid(pos, 4).ToUInt();
                }
                pos += 4;

                if (data.Count >= pos + 4)
                {
                    modificationTime = data.Mid(pos, 4).ToUInt();
                }
                pos += 4;

                if (data.Count >= pos + 4)
                {
                    timescale = data.Mid(pos, 4).ToUInt();
                }
                pos += 4;

                if (data.Count >= pos + 4)
                {
                    duration = (ulong)data.Mid(pos, 4).ToUInt();
                }
                pos += 4;
            }

            // Get rate
            if (data.Count >= pos + 4)
            {
                rate = data.Mid(pos, 4).ToUInt();
            }
            pos += 4;

            // Get volume
            if (data.Count >= pos + 2)
            {
                volume = (ushort)data.Mid(pos, 2).ToShort();
            }
            pos += 2;

            // reserved
            pos += 2;

            // reserved
            pos += 8;

            // video transformation matrix
            pos += 36;

            // pre-defined
            pos += 24;

            // Get next track ID
            if (data.Count >= pos + 4)
            {
                nextTrackId = (ushort)data.Mid(pos, 4).ToUInt();
            }
        }
Exemplo n.º 15
0
        private void Scan()
        {
            // Scan the metadata pages

            if (scanned || !IsValid)
            {
                return;
            }

            uint ipacket  = 0;
            long overhead = 0;

            ByteVector metadata_header = GetPacket(ipacket++);

            if (metadata_header == null)
            {
                return;
            }

            ByteVector header;

            if (!metadata_header.StartsWith("fLaC"))
            {
                // FLAC 1.1.2+
                if (metadata_header.Mid(1, 4) != "FLAC")
                {
                    return;
                }

                if (metadata_header[5] != 1)
                {
                    return;                     // not version 1
                }
                metadata_header = metadata_header.Mid(13);
            }
            else
            {
                // FLAC 1.1.0 & 1.1.1
                metadata_header = GetPacket(ipacket++);

                if (metadata_header == null)
                {
                    return;
                }
            }

            header = metadata_header.Mid(0, 4);
            // Header format (from spec):
            // <1> Last-metadata-block flag
            // <7> BLOCK_TYPE
            //    0 : STREAMINFO
            //    1 : PADDING
            //    ..
            //    4 : VORBIS_COMMENT
            //    ..
            // <24> Length of metadata to follow

            byte block_type = (byte)(header[0] & 0x7f);
            bool last_block = (header[0] & 0x80) != 0;
            uint length     = header.Mid(1, 3).ToUInt();

            overhead += length;

            // Sanity: First block should be the stream_info metadata

            if (block_type != 0)
            {
                TagLibDebugger.Debug("Ogg.Flac.File.Scan() -- Invalid Ogg/FLAC stream");
                return;
            }

            stream_info_data = metadata_header.Mid(4, (int)length);

            // Search through the remaining metadata

            while (!last_block)
            {
                metadata_header = GetPacket(ipacket++);

                if (metadata_header == null)
                {
                    return;
                }

                header     = metadata_header.Mid(0, 4);
                block_type = (byte)(header[0] & 0x7f);
                last_block = (header[0] & 0x80) != 0;
                length     = header.Mid(1, 3).ToUInt();
                overhead  += length;

                if (block_type == 4)
                {
                    xiph_comment_data = metadata_header.Mid(4, (int)length);
                    has_xiph_comment  = true;
                    comment_packet    = ipacket;
                }
                else if (block_type > 5)
                {
                    TagLibDebugger.Debug("Ogg.Flac.File.Scan() -- Unknown metadata block");
                }
            }

            // End of metadata, now comes the datastream
            stream_start  = overhead;
            stream_length = Length - stream_start;

            scanned = true;
        }
Exemplo n.º 16
0
        public override void Save()
        {
            if (IsReadOnly)
            {
                throw new ReadOnlyException();
            }

            Mode = FileAccessMode.Write;

            long flac_data_begin;
            long flac_data_end;

            // Update ID3 tags
            if (id3v2_tag != null)
            {
                ByteVector id3v2_tag_data = id3v2_tag.Render();

                long id3v2_location = FindId3v2();
                if (id3v2_location >= 0)
                {
                    int id3v2_size = 0;

                    Seek(id3v2_location);
                    Id3v2Header header = new Id3v2Header(ReadBlock((int)Id3v2Header.Size));

                    if (header.TagSize == 0)
                    {
                        TagLibDebugger.Debug("Flac.File.Save() -- Id3v2 header is broken. Ignoring.");
                    }
                    else
                    {
                        id3v2_size = (int)header.CompleteTagSize;
                    }

                    Insert(id3v2_tag_data, id3v2_location, id3v2_size);
                    System.Console.WriteLine("ID3v2: " + id3v2_size + " " + id3v2_tag_data.Count);
                    flac_data_begin = id3v2_location + id3v2_tag_data.Count;
                }
                else
                {
                    Insert(id3v2_tag_data, 0, 0);
                    flac_data_begin = id3v2_tag_data.Count;
                }
            }
            else
            {
                flac_data_begin = 0;
            }

            if (id3v1_tag != null)
            {
                long id3v1_location = FindId3v1();

                if (id3v1_location >= 0)
                {
                    Seek(id3v1_location);
                }
                else
                {
                    Seek(0, System.IO.SeekOrigin.End);
                }

                flac_data_end = Tell;
                WriteBlock(id3v1_tag.Render());
            }
            else
            {
                flac_data_end = Length;
            }


            // Create new vorbis comments is they don'type exist.
            FindTag(TagTypes.Xiph, true);

            xiph_comment_data = comment.Render(false);

            ByteVector v = ByteVector.FromUInt((uint)xiph_comment_data.Count);

            // Set the type of the comment to be a Xiph / Vorbis comment
            // (See scan() for comments on header-format)
            v[0] = 4;
            v.Add(xiph_comment_data);


            // If file already have comment => find and update it
            //                       if not => insert one

            scanned = false;

            if (Scan(flac_data_begin, flac_data_end) != null)
            {
                long next_page_offset = flac_start;
                Seek(next_page_offset);
                ByteVector header = ReadBlock(4);
                uint       length = header.Mid(1, 3).ToUInt();

                next_page_offset += length + 4;

                // Search through the remaining metadata

                byte block_type = (byte)(header[0] & 0x7f);
                bool last_block = (header[0] & 0x80) != 0;

                while (!last_block)
                {
                    Seek(next_page_offset);

                    header     = ReadBlock(4);
                    block_type = (byte)(header[0] & 0x7f);
                    last_block = (header[0] & 0x80) != 0;
                    length     = header.Mid(1, 3).ToUInt();

                    // Type is vorbiscomment
                    if (block_type == 4)
                    {
                        long next_keep = (last_block ? 0 : FindPaddingBreak(next_page_offset + length + 4,
                                                                            next_page_offset + XiphCommentData.Count + 8,
                                                                            ref last_block));
                        uint padding_length;
                        if (next_keep != 0)
                        {
                            // There is space for comment and padding blocks without rewriting the whole file.
                            // Note this can not overflow.
                            padding_length = (uint)(next_keep - (next_page_offset + XiphCommentData.Count + 8));
                        }
                        else
                        {
                            // Not enough space, so we will have to rewrite the whole file following this block
                            padding_length = (uint)XiphCommentData.Count;
                            if (padding_length < 4096)
                            {
                                padding_length = 4096;
                            }
                            next_keep = next_page_offset + length + 4;
                        }

                        ByteVector padding = ByteVector.FromUInt(padding_length);
                        padding[0] = 1;
                        if (last_block)
                        {
                            padding[0] = (byte)(padding[0] | 0x80);
                        }
                        padding.Resize((int)(padding_length + 4));

                        Insert(v + padding, next_page_offset, next_keep - next_page_offset);
                        //System.Console.WriteLine ("OGG: " + (next_keep - next_page_offset) + " " + (vector.Count + padding.Count));

                        break;
                    }

                    next_page_offset += length + 4;
                }
            }
            else
            {
                long next_page_offset = flac_start;

                Seek(next_page_offset);

                ByteVector header     = ReadBlock(4);
                bool       last_block = (header[0] & 0x80) != 0;
                uint       length     = header.Mid(1, 3).ToUInt();

                // If last block was last, make this one last

                if (last_block)
                {
                    // Copy the bottom seven bits into the new value

                    ByteVector h = (byte)(header[0] & 0x7F);
                    Insert(h, next_page_offset, 1);

                    // Set the last bit
                    v[0] = (byte)(v[0] | 0x80);
                }

                Insert(v, next_page_offset + length + 4, 0);
            }

            Mode = FileAccessMode.Closed;
        }
Exemplo n.º 17
0
        private ByteVector Scan(long begin, long end)
        {
            ByteVector xiph_comment_data = null;

            // Scan the metadata pages

            if (scanned || !IsValid)
            {
                return(null);
            }

            long next_page_offset;
            long file_size = Length;

            next_page_offset = Find("fLaC", begin);

            if (next_page_offset < 0)
            {
                TagLibDebugger.Debug("Flac.File.Scan () -- FLAC stream not found");
                SetValid(false);
                return(null);
            }

            next_page_offset += 4;
            flac_start        = next_page_offset;

            Seek(next_page_offset);

            ByteVector header = ReadBlock(4);

            // Header format (from spec):
            // <1> Last-metadata-block flag
            // <7> BLOCK_TYPE
            //	0 : STREAMINFO
            //    1 : PADDING
            //    ..
            //    4 : VORBIS_COMMENT
            //    ..
            // <24> Length of metadata to follow

            byte block_type = (byte)(header[0] & 0x7f);
            bool last_block = (header[0] & 0x80) != 0;
            uint length     = header.Mid(1, 3).ToUInt();

            // First block should be the stream_info metadata
            if (block_type != 0)
            {
                TagLibDebugger.Debug("Flac.File.Scan() -- invalid FLAC stream");
                SetValid(false);
                return(null);
            }
            stream_info_data  = ReadBlock((int)length);
            next_page_offset += length + 4;

            // Search through the remaining metadata

            while (!last_block)
            {
                header     = ReadBlock(4);
                block_type = (byte)(header[0] & 0x7f);
                last_block = (header[0] & 0x80) != 0;
                length     = header.Mid(1, 3).ToUInt();

                // Found the vorbis-comment
                if (block_type == 4)
                {
                    xiph_comment_data = ReadBlock((int)length);
                }

                next_page_offset += length + 4;
                if (next_page_offset >= file_size)
                {
                    TagLibDebugger.Debug("Flac.File.Scan() -- FLAC stream corrupted");
                    SetValid(false);
                    return(null);
                }
                Seek(next_page_offset);
            }

            // End of metadata, now comes the datastream
            stream_start  = next_page_offset;
            stream_length = end - stream_start;

            scanned = true;

            return(xiph_comment_data);
        }
Exemplo n.º 18
0
        private void Read(OggFile file, long file_offset)
        {
            file.Seek(file_offset);

            // An Ogg page header is at least 27 buffer, so we'll go ahead and read that
            // much and then get the rest when we're ready for it.

            ByteVector data = file.ReadBlock(27);

            // Sanity check -- make sure that we were in fact able to read as much data as
            // we asked for and that the page begins with "OggS".

            if (data.Count != 27 || !data.StartsWith("OggS"))
            {
                TagLibDebugger.Debug("Ogg.PageHeader.Read() -- error reading page header");
                return;
            }

            byte flags = data[5];

            firstPacketContinued = (flags & 1) != 0;
            firstPageOfStream    = ((flags >> 1) & 1) != 0;
            lastPageOfStream     = ((flags >> 2) & 1) != 0;

            absoluteGranularPosition = data.Mid(6, 8).ToLong(false);
            streamSerialNumber       = data.Mid(14, 4).ToUInt(false);
            pageSequenceNumber       = (int)data.Mid(18, 4).ToUInt(false);

            // Byte number 27 is the number of page segments, which is the only variable
            // length portion of the page header.  After reading the number of page
            // segments we'll then read in the coresponding data for this count.

            int pageSegmentCount = data[26];

            ByteVector page_segments = file.ReadBlock(pageSegmentCount);

            // Another sanity check.

            if (pageSegmentCount < 1 || page_segments.Count != pageSegmentCount)
            {
                return;
            }

            // The base size of an Ogg page 27 buffer plus the number of lacing values.

            size = 27 + pageSegmentCount;

            int packetSize = 0;

            for (int i = 0; i < pageSegmentCount; i++)
            {
                dataSize   += page_segments[i];
                packetSize += page_segments[i];

                if (page_segments[i] < 255)
                {
                    packetSizes.Add(packetSize);
                    packetSize = 0;
                }
            }

            if (packetSize > 0)
            {
                packetSizes.Add(packetSize);
                lastPacketCompleted = false;
            }
            else
            {
                lastPacketCompleted = true;
            }

            isValid = true;
        }
Exemplo n.º 19
0
        public void SetData(ByteVector data, uint version)
        {
            if (data != null)
            {
                this.version = version;

                if (version < 3)
                {
                    // ID3v2.2

                    if (data.Count < 3)
                    {
                        TagLibDebugger.Debug("You must at least specify a frame ID.");
                        return;
                    }

                    // Set the frame ID -- the first three buffer

                    frameId = data.Mid(0, 3);

                    // If the full header information was not passed in, do not continue to the
                    // steps to parse the frame size and flags.

                    if (data.Count < 6)
                    {
                        frameSize = 0;
                        return;
                    }

                    frameSize = data.Mid(3, 3).ToUInt();
                }
                else if (version == 3)
                {
                    // ID3v2.3

                    if (data.Count < 4)
                    {
                        TagLibDebugger.Debug("You must at least specify a frame ID.");
                        return;
                    }

                    // Set the frame ID -- the first four buffer

                    frameId = data.Mid(0, 4);

                    // If the full header information was not passed in, do not continue to the
                    // steps to parse the frame size and flags.

                    if (data.Count < 10)
                    {
                        frameSize = 0;
                        return;
                    }

                    // Set the size -- the frame size is the four buffer starting at byte four in
                    // the frame header (structure 4)

                    frameSize = data.Mid(4, 4).ToUInt();

                    // read the first byte of flags
                    tagAlterPreservation  = ((data[8] >> 7) & 1) == 1;        // (structure 3.3.1.a)
                    fileAlterPreservation = ((data[8] >> 6) & 1) == 1;        // (structure 3.3.1.b)
                    readOnly = ((data[8] >> 5) & 1) == 1;                     // (structure 3.3.1.channelMode)

                    // read the second byte of flags
                    compression      = ((data[9] >> 7) & 1) == 1;               // (structure 3.3.1.index)
                    encryption       = ((data[9] >> 6) & 1) == 1;               // (structure 3.3.1.j)
                    groupingIdentity = ((data[9] >> 5) & 1) == 1;               // (structure 3.3.1.k)
                }
                else
                {
                    // ID3v2.4

                    if (data.Count < 4)
                    {
                        TagLibDebugger.Debug("You must at least specify a frame ID.");
                        return;
                    }

                    // Set the frame ID -- the first four buffer

                    frameId = data.Mid(0, 4);

                    // If the full header information was not passed in, do not continue to the
                    // steps to parse the frame size and flags.

                    if (data.Count < 10)
                    {
                        frameSize = 0;
                        return;
                    }

                    // Set the size -- the frame size is the four buffer starting at byte four in
                    // the frame header (structure 4)

                    frameSize = Id3v2SynchData.ToUInt(data.Mid(4, 4));

                    // read the first byte of flags
                    tagAlterPreservation  = ((data[8] >> 6) & 1) == 1;        // (structure 4.1.1.a)
                    fileAlterPreservation = ((data[8] >> 5) & 1) == 1;        // (structure 4.1.1.b)
                    readOnly = ((data[8] >> 4) & 1) == 1;                     // (structure 4.1.1.channelMode)

                    // read the second byte of flags
                    groupingIdentity    = ((data[9] >> 6) & 1) == 1;            // (structure 4.1.2.header)
                    compression         = ((data[9] >> 3) & 1) == 1;            // (structure 4.1.2.k)
                    encryption          = ((data[9] >> 2) & 1) == 1;            // (structure 4.1.2.m)
                    desynchronization   = ((data[9] >> 1) & 1) == 1;            // (structure 4.1.2.n)
                    dataLengthIndicator = (data[9] & 1) == 1;                   // (structure 4.1.2.position)
                }
            }
            else
            {
                throw new ArgumentNullException("data");
            }
        }
Exemplo n.º 20
0
        public Mpeg4AppleElementaryStreamDescriptor(Mpeg4BoxHeader header, Mpeg4Box parent) : base(header, parent)
        {
            //WARNING: this was changed from accessing the Data property directy to instead
            // use LoadBoxData which returns a reference to the underlying data.  This change
            // was required to avoid accessing the virtual methods that the Data property uses
            // Everything should still work but if it doesn't then this change is the culprit...

            decoderConfiguration = new ByteVector();

            uint length;

            // This box contains a ton of information.
            int offset = 0;

            // This is a safe alternative to the Data property
            // it will be a reference to the same underlying structure and so should work identically to Data
            ByteVector boxData = LoadBoxData();

            // Elementary Stream Descriptor Tag
            if (boxData[offset++] == 3)
            {
                // We have a descriptor tag. Check that it'field at least 20 long.
                if ((length = ReadLength(boxData, offset)) < 20)
                {
                    TagLibDebugger.Debug("TagLib.Mpeg4.AppleElementaryStreamDescriptor () - Could not read data. Too small.");
                    return;
                }
                offset += 4;

                streamId = boxData.Mid(offset, 2).ToShort();
                offset  += 2;

                streamPriority = boxData[offset++];
            }
            else
            {
                // The tag wasn'type found, so the next two byte are the ID, and
                // after that, business as usual.
                streamId = boxData.Mid(offset, 2).ToShort();
                offset  += 2;
            }

            // Verify that the next data is the Decoder Configuration Descriptor
            // Tag and escape if it won'type work out.
            if (boxData[offset++] != 4)
            {
                TagLibDebugger.Debug("TagLib.Mpeg4.AppleElementaryStreamDescriptor () - Could not identify decoder configuration descriptor.");
                return;
            }

            // Check that it'field at least 15 long.
            if ((length = ReadLength(boxData, offset)) < 15)
            {
                TagLibDebugger.Debug("TagLib.Mpeg4.AppleElementaryStreamDescriptor () - Could not read data. Too small.");
                return;
            }
            offset += 4;

            // Read a lot of good info.
            objectTypeId   = boxData[offset++];
            streamType     = boxData[offset++];
            bufferSize     = boxData.Mid(offset, 3).ToUInt();
            offset        += 3;
            maximumBitrate = boxData.Mid(offset, 4).ToUInt();
            offset        += 4;
            averageBitrate = boxData.Mid(offset, 4).ToUInt();
            offset        += 4;

            // Verify that the next data is the Decoder Specific Descriptor
            // Tag and escape if it won'type work out.
            if (boxData[offset++] != 5)
            {
                TagLibDebugger.Debug("TagLib.Mpeg4.AppleElementaryStreamDescriptor () - Could not identify decoder specific descriptor.");
                return;
            }

            // The rest of the info is decoder specific.
            length  = ReadLength(boxData, offset);
            offset += 4;
            decoderConfiguration = boxData.Mid(offset, (int)length);
        }
        private void ParseAttachedPictureFields(ByteVector data)
        {
            if (data != null)
            {
                if (data.Count < 5)
                {
                    TagLibDebugger.Debug("A picture frame must contain at least 5 bytes.");
                    return;
                }

                int pos = 0;

                textEncoding = (StringType)data[pos];
                pos         += 1;

                int offset;

                if (Header.Version > 2)
                {
                    offset = data.Find(TextDelimiter(StringType.Latin1), pos);

                    if (offset < pos)
                    {
                        return;
                    }

                    mimeType = data.Mid(pos, offset - pos).ToString(StringType.Latin1);
                    pos      = offset + 1;
                }
                else
                {
                    ByteVector ext = data.Mid(pos, 3);
                    if (ext == "JPG")
                    {
                        mimeType = "image/jpeg";
                    }
                    else if (ext == "PNG")
                    {
                        mimeType = "image/png";
                    }
                    else
                    {
                        mimeType = "image/unknown";
                    }

                    pos += 3;
                }

                type = (PictureType)data[pos];
                pos += 1;

                offset = data.Find(TextDelimiter(textEncoding), pos);

                if (offset < pos)
                {
                    return;
                }

                description = data.Mid(pos, offset - pos).ToString(textEncoding);
                pos         = offset + 1;

                this.data = data.Mid(pos);
            }
            else
            {
                throw new ArgumentNullException("data");
            }
        }