// 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; }
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"); } }
//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); } }
protected void Parse(ByteVector data) { if (data != null) { size = Id3v2SynchData.ToUInt(data.Mid(0, 4)); } else { throw new ArgumentNullException("data"); } }
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"); } }
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") }
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; } } }
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); }
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)); } }
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."); } }
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"); } }
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(); } }
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; }
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; }
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); }
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; }
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"); } }
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"); } }