/// <summary> /// Reads the file with a specified read style. /// </summary> /// <param name="propertiesStyle"> /// A <see cref="ReadStyle" /> value specifying at what level /// of accuracy to read the media properties, or <see /// cref="ReadStyle.None" /> to ignore the properties. /// </param> private void Read(ReadStyle propertiesStyle) { long end; Dictionary <uint, Bitstream> streams = ReadStreams(null, out end); List <ICodec> codecs = new List <ICodec> (); InvariantStartPosition = end; InvariantEndPosition = Length; foreach (uint id in streams.Keys) { tag.AddComment(id, streams [id].Codec.CommentData); codecs.Add(streams [id].Codec); } if (propertiesStyle == ReadStyle.None) { return; } PageHeader last_header = LastPageHeader; TimeSpan duration = streams [last_header .StreamSerialNumber].GetDuration( last_header.AbsoluteGranularPosition); properties = new Properties(duration, codecs); }
public Page(ByteVectorCollection packets, PageHeader header) : this(header) { if (packets == null) { throw new ArgumentNullException("packets"); } this.packets = new ByteVectorCollection(packets); List<int> list = new List<int>(); IEnumerator<ByteVector> enumerator = packets.GetEnumerator(); try { while (enumerator.MoveNext()) { ByteVector current = enumerator.Current; list.Add(current.Count); } } finally { if (enumerator == null) { } enumerator.Dispose(); } header.PacketSizes = list.ToArray(); }
public bool Equals(PageHeader other) { return(_packet_sizes == other._packet_sizes && _version == other._version && _flags == other._flags && _absolute_granular_position == other._absolute_granular_position && _stream_serial_number == other._stream_serial_number && _page_sequence_number == other._page_sequence_number && _size == other._size && _data_size == other._data_size); }
public static void OverwriteSequenceNumbers(File file, long position, IDictionary <uint, int> shiftTable) { bool done = true; foreach (KeyValuePair <uint, int> pair in shiftTable) { if (pair.Value != 0) { done = false; break; } } if (done) { return; } while (position < file.Length) { PageHeader header = new PageHeader(file, position); int size = (int)(header.Size + header.DataSize); if (shiftTable.ContainsKey(header.StreamSerialNumber) && shiftTable [header.StreamSerialNumber] != 0) { file.Seek(position); ByteVector page_data = file.ReadBlock(size); ByteVector new_data = ByteVector.FromUInt( (uint)(header.PageSequenceNumber + shiftTable [header.StreamSerialNumber]), false); for (int i = 18; i < 22; i++) { page_data [i] = new_data [i - 18]; } for (int i = 22; i < 26; i++) { page_data [i] = 0; } new_data.Add(ByteVector.FromUInt( page_data.Checksum, false)); file.Seek(position + 18); file.WriteBlock(new_data); } position += size; } }
/// <summary> /// Checks whether or not the current instance is equal to /// another instance of <see cref="PageHeader" />. /// </summary> /// <param name="other"> /// A <see cref="PageHeader" /> object to compare to the /// current instance. /// </param> /// <returns> /// A <see cref="bool" /> value indicating whether or not the /// current instance is equal to <paramref name="other" />. /// </returns> /// <seealso cref="M:System.IEquatable`1.Equals" /> public bool Equals(PageHeader other) { return(packet_sizes == other.packet_sizes && version == other.version && Flags == other.Flags && absolute_granular_position == other.absolute_granular_position && StreamSerialNumber == other.StreamSerialNumber && PageSequenceNumber == other.PageSequenceNumber && Size == other.Size && DataSize == other.DataSize); }
/// <summary> /// Checks whether or not the current instance is equal to /// another instance of <see cref="PageHeader" />. /// </summary> /// <param name="other"> /// A <see cref="PageHeader" /> object to compare to the /// current instance. /// </param> /// <returns> /// A <see cref="bool" /> value indicating whether or not the /// current instance is equal to <paramref name="other" />. /// </returns> /// <seealso cref="M:System.IEquatable`1.Equals" /> public bool Equals(PageHeader other) { return(packet_sizes == other.packet_sizes && version == other.version && flags == other.flags && absolute_granular_position == other.absolute_granular_position && stream_serial_number == other.stream_serial_number && page_sequence_number == other.page_sequence_number && size == other.size && data_size == other.data_size); }
public PageHeader(PageHeader original, uint offset, PageFlags flags) { this.version = original.version; this.flags = flags; this.absolute_granular_position = original.absolute_granular_position; this.stream_serial_number = original.stream_serial_number; this.page_sequence_number = original.page_sequence_number + offset; this.size = original.size; this.data_size = original.data_size; this.packet_sizes = new List<int>(); if ((this.page_sequence_number == 0) && (((byte) (flags & PageFlags.FirstPacketContinued)) == 0)) { this.flags = (PageFlags) ((byte) (this.flags | PageFlags.FirstPageOfStream)); } }
public PageHeader(PageHeader original, uint offset, PageFlags flags) { version = original.version; this.flags = flags; absolute_granular_position = original.absolute_granular_position; stream_serial_number = original.stream_serial_number; page_sequence_number = original.page_sequence_number + offset; size = original.size; data_size = original.data_size; packet_sizes = new List <int>(); if (page_sequence_number == 0 && (flags & PageFlags.FirstPacketContinued) == 0) { this.flags |= PageFlags.FirstPageOfStream; } }
public Page(ByteVectorCollection packets, PageHeader header) : this(header) { if (packets == null) { throw new ArgumentNullException("packets"); } this.packets = new ByteVectorCollection(packets); List <int> packet_sizes = new List <int>(); foreach (ByteVector v in packets) { packet_sizes.Add(v.Count); } header.PacketSizes = packet_sizes.ToArray(); }
public Page (ByteVectorCollection packets, PageHeader header) : this (header) { if (packets == null) throw new ArgumentNullException ("packets"); this.packets = packets; List<int> packet_sizes = new List<int> (); // Build a page from the list of packets. foreach (ByteVector v in packets) packet_sizes.Add (v.Count); header.PacketSizes = packet_sizes.ToArray (); }
/// <summary> /// Constructs and initializes a new instance of <see /// cref="PageHeader" /> by copying the values from another /// instance, offsetting the page number and applying new /// flags. /// </summary> /// <param name="original"> /// A <see cref="PageHeader"/> object to copy the values /// from. /// </param> /// <param name="offset"> /// A <see cref="uint"/> value specifying how much to offset /// the page sequence number in the new instance. /// </param> /// <param name="flags"> /// A <see cref="PageFlags"/> value specifying the flags to /// use in the new instance. /// </param> public PageHeader(PageHeader original, uint offset, PageFlags flags) { version = original.version; Flags = flags; absolute_granular_position = original.absolute_granular_position; StreamSerialNumber = original.StreamSerialNumber; PageSequenceNumber = original.PageSequenceNumber + offset; Size = original.Size; DataSize = original.DataSize; packet_sizes = new List <int> (); if (PageSequenceNumber == 0 && (flags & PageFlags.FirstPacketContinued) == 0) { Flags |= PageFlags.FirstPageOfStream; } }
public PageHeader(PageHeader original, uint offset, PageFlags flags) { _version = original._version; _flags = flags; _absolute_granular_position = original._absolute_granular_position; _stream_serial_number = original._stream_serial_number; _page_sequence_number = original._page_sequence_number + offset; _size = original._size; _data_size = original._data_size; _packet_sizes = new List <int> (); if (_page_sequence_number == 0 && (flags & PageFlags.FirstPacketContinued) == 0) { _flags |= PageFlags.FirstPageOfStream; } }
/// <summary> /// Repaginates the pages passed into the current instance to /// handle changes made to the Xiph comment. /// </summary> /// <param name="change"> /// A <see cref="int" /> value reference containing the /// the difference between the number of pages returned and /// the number of pages that were added to the class. /// </param> /// <returns> /// A <see cref="T:Page[]" /> containing the new page /// collection. /// </returns> public Page [] Paginate(out int change) { // Ogg Pagination: Welcome to sucksville! // If you don't understand this, you're not alone. // It is confusing as Hell. // TODO: Document this method, in the mean time, there // is always http://xiph.org/ogg/doc/framing.html if (pages_read == 0) { change = 0; return(new Page [0]); } int count = pages_read; ByteVectorCollection packets = new ByteVectorCollection( this.packets); PageHeader first_header = (PageHeader)first_page_header; List <Page> pages = new List <Page> (); uint index = 0; bool bos = first_header.PageSequenceNumber == 0; if (bos) { pages.Add(new Page(new ByteVectorCollection(packets [0]), first_header)); index++; packets.RemoveAt(0); count--; } int lacing_per_page = 0xfc; if (count > 0) { int total_lacing_bytes = 0; for (int i = 0; i < packets.Count; i++) { total_lacing_bytes += GetLacingValueLength( packets, i); } lacing_per_page = Math.Min(total_lacing_bytes / count + 1, lacing_per_page); } int lacing_bytes_used = 0; ByteVectorCollection page_packets = new ByteVectorCollection(); bool first_packet_continued = false; while (packets.Count > 0) { int packet_bytes = GetLacingValueLength(packets, 0); int remaining = lacing_per_page - lacing_bytes_used; bool whole_packet = packet_bytes <= remaining; if (whole_packet) { page_packets.Add(packets [0]); lacing_bytes_used += packet_bytes; packets.RemoveAt(0); } else { page_packets.Add(packets [0].Mid(0, remaining * 0xff)); packets [0] = packets [0].Mid(remaining * 0xff); lacing_bytes_used += remaining; } if (lacing_bytes_used == lacing_per_page) { pages.Add(new Page(page_packets, new PageHeader(first_header, index, first_packet_continued ? PageFlags.FirstPacketContinued : PageFlags.None))); page_packets = new ByteVectorCollection(); lacing_bytes_used = 0; index++; count--; first_packet_continued = !whole_packet; } } if (page_packets.Count > 0) { pages.Add(new Page(page_packets, new PageHeader( first_header.StreamSerialNumber, index, first_packet_continued ? PageFlags.FirstPacketContinued : PageFlags.None))); index++; count--; } change = -count; return(pages.ToArray()); }
public static void OverwriteSequenceNumbers (File file, long position, IDictionary<uint, int> shiftTable) { bool done = true; foreach (KeyValuePair<uint, int> pair in shiftTable) if (pair.Value != 0) { done = false; break; } if (done) return; while (position < file.Length) { PageHeader header = new PageHeader (file, position); int size = (int) (header.Size + header.DataSize); if (shiftTable.ContainsKey (header.StreamSerialNumber) && shiftTable [header.StreamSerialNumber] != 0) { file.Seek (position); ByteVector page_data = file.ReadBlock (size); ByteVector new_data = ByteVector.FromUInt ( (uint)(header.PageSequenceNumber + shiftTable [header.StreamSerialNumber]), false); for (int i = 18; i < 22; i ++) page_data [i] = new_data [i - 18]; for (int i = 22; i < 26; i++) page_data [i] = 0; new_data.Add (ByteVector.FromUInt ( page_data.Checksum, false)); file.Seek (position + 18); file.WriteBlock (new_data); } position += size; } }
protected Page (PageHeader header) { this.header = header; packets = new ByteVectorCollection (); }
protected Page(PageHeader header) { this.header = header; packets = new ByteVectorCollection(); }
public static void OverwriteSequenceNumbers(TagLib.Ogg.File file, long position, IDictionary<uint, int> shiftTable) { if (file == null) { throw new ArgumentNullException("file"); } if (shiftTable == null) { throw new ArgumentNullException("shiftTable"); } bool flag = true; IEnumerator<KeyValuePair<uint, int>> enumerator = shiftTable.GetEnumerator(); try { while (enumerator.MoveNext()) { KeyValuePair<uint, int> current = enumerator.Current; if (current.Value != 0) { flag = false; goto Label_0065; } } } finally { if (enumerator == null) { } enumerator.Dispose(); } Label_0065: if (flag) { return; } while (position < (file.Length - 0x1bL)) { PageHeader header = new PageHeader(file, position); int length = (int) (header.Size + header.DataSize); if (shiftTable.ContainsKey(header.StreamSerialNumber) && (shiftTable[header.StreamSerialNumber] != 0)) { file.Seek(position); ByteVector vector = file.ReadBlock(length); ByteVector data = ByteVector.FromUInt(header.PageSequenceNumber + ((uint) ((long) shiftTable[header.StreamSerialNumber])), false); for (int i = 0x12; i < 0x16; i++) { vector[i] = data[i - 0x12]; } for (int j = 0x16; j < 0x1a; j++) { vector[j] = 0; } data.Add(ByteVector.FromUInt(vector.Checksum, false)); file.Seek(position + 0x12L); file.WriteBlock(data); } position += length; } }
/// <summary> /// Checks whether or not the current instance is equal to /// another instance of <see cref="PageHeader" />. /// </summary> /// <param name="other"> /// A <see cref="PageHeader" /> object to compare to the /// current instance. /// </param> /// <returns> /// A <see cref="bool" /> value indicating whether or not the /// current instance is equal to <paramref name="other" />. /// </returns> /// <seealso cref="M:System.IEquatable`1.Equals" /> public bool Equals(PageHeader other) { return packet_sizes == other.packet_sizes && version == other.version && flags == other.flags && absolute_granular_position == other.absolute_granular_position && stream_serial_number == other.stream_serial_number && page_sequence_number == other.page_sequence_number && size == other.size && data_size == other.data_size; }
/// <summary> /// Constructs and initializes a new instance of <see /// cref="PageHeader" /> by copying the values from another /// instance, offsetting the page number and applying new /// flags. /// </summary> /// <param name="original"> /// A <see cref="PageHeader"/> object to copy the values /// from. /// </param> /// <param name="offset"> /// A <see cref="uint"/> value specifying how much to offset /// the page sequence number in the new instance. /// </param> /// <param name="flags"> /// A <see cref="PageFlags"/> value specifying the flags to /// use in the new instance. /// </param> public PageHeader(PageHeader original, uint offset, PageFlags flags) { version = original.version; this.flags = flags; absolute_granular_position = original.absolute_granular_position; stream_serial_number = original.stream_serial_number; page_sequence_number = original.page_sequence_number + offset; size = original.size; data_size = original.data_size; packet_sizes = new List<int> (); if (page_sequence_number == 0 && (flags & PageFlags.FirstPacketContinued) == 0) this.flags |= PageFlags.FirstPageOfStream; }
/// <summary> /// Overwrites all page headers in a file starting at a /// specified position, shifting the page sequence numbers /// a set amount. /// </summary> /// <param name="file"> /// A <see cref="File" /> object containing the file to /// update. /// </param> /// <param name="position"> /// A <see cref="long" /> value specify at what position to /// start updating. /// </param> /// <param name="shiftTable"> /// A <see cref="T:System.Collections.Generic.IDictionary`2" /// /> object where the key is the serial number of the /// stream to update and the value is the amount to offset /// the page sequence numbers in the stream. /// </param> /// <exception cref="ArgumentNullException"> /// <paramref name="file" /> or <paramref name="shiftTable" /// /> is <see langword="null" />. /// </exception> /// <remarks> /// When the number of pages in a stream changes, all /// subsequent pages in the stream need to have their page /// sequence number update in order to remain valid. /// Additionally, when the page sequence number changes, the /// page needs to have its checksum recomputed. This makes /// for a costly recalculation if large comment data is /// added. /// </remarks> public static void OverwriteSequenceNumbers (File file, long position, IDictionary<uint, int> shiftTable) { if (file == null) throw new ArgumentNullException ("file"); if (shiftTable == null) throw new ArgumentNullException ("shiftTable"); // Check to see if there are no changes to be made. bool done = true; foreach (KeyValuePair<uint, int> pair in shiftTable) if (pair.Value != 0) { done = false; break; } // If the file is fine, quit. if (done) return; while (position < file.Length - 27) { PageHeader header = new PageHeader (file, position); int size = (int) (header.Size + header.DataSize); if (shiftTable.ContainsKey (header.StreamSerialNumber) && shiftTable [header.StreamSerialNumber] != 0) { file.Seek (position); ByteVector page_data = file.ReadBlock (size); ByteVector new_data = ByteVector.FromUInt ( (uint)(header.PageSequenceNumber + shiftTable [header.StreamSerialNumber]), false); for (int i = 18; i < 22; i ++) page_data [i] = new_data [i - 18]; for (int i = 22; i < 26; i++) page_data [i] = 0; new_data.Add (ByteVector.FromUInt ( page_data.Checksum, false)); file.Seek (position + 18); file.WriteBlock (new_data); } position += size; } }
public bool Equals(PageHeader other) { return (((((this.packet_sizes == other.packet_sizes) && (this.version == other.version)) && ((this.flags == other.flags) && (this.absolute_granular_position == other.absolute_granular_position))) && (((this.stream_serial_number == other.stream_serial_number) && (this.page_sequence_number == other.page_sequence_number)) && (this.size == other.size))) && (this.data_size == other.data_size)); }
/// <summary> /// Overwrites all page headers in a file starting at a /// specified position, shifting the page sequence numbers /// a set amount. /// </summary> /// <param name="file"> /// A <see cref="File" /> object containing the file to /// update. /// </param> /// <param name="position"> /// A <see cref="long" /> value specify at what position to /// start updating. /// </param> /// <param name="shiftTable"> /// A <see cref="T:System.Collections.Generic.IDictionary`2" /// /> object where the key is the serial number of the /// stream to update and the value is the amount to offset /// the page sequence numbers in the stream. /// </param> /// <exception cref="ArgumentNullException"> /// <paramref name="file" /> or <paramref name="shiftTable" /// /> is <see langword="null" />. /// </exception> /// <remarks> /// When the number of pages in a stream changes, all /// subsequent pages in the stream need to have their page /// sequence number update in order to remain valid. /// Additionally, when the page sequence number changes, the /// page needs to have its checksum recomputed. This makes /// for a costly recalculation if large comment data is /// added. /// </remarks> public static void OverwriteSequenceNumbers(File file, long position, IDictionary <uint, int> shiftTable) { if (file == null) { throw new ArgumentNullException("file"); } if (shiftTable == null) { throw new ArgumentNullException("shiftTable"); } // Check to see if there are no changes to be made. bool done = true; foreach (KeyValuePair <uint, int> pair in shiftTable) { if (pair.Value != 0) { done = false; break; } } // If the file is fine, quit. if (done) { return; } while (position < file.Length - 27) { PageHeader header = new PageHeader(file, position); int size = (int)(header.Size + header.DataSize); if (shiftTable.ContainsKey(header.StreamSerialNumber) && shiftTable [header.StreamSerialNumber] != 0) { file.Seek(position); ByteVector page_data = file.ReadBlock(size); ByteVector new_data = ByteVector.FromUInt( (uint)(header.PageSequenceNumber + shiftTable [header.StreamSerialNumber]), false); for (int i = 18; i < 22; i++) { page_data [i] = new_data [i - 18]; } for (int i = 22; i < 26; i++) { page_data [i] = 0; } new_data.Add(ByteVector.FromUInt( page_data.Checksum, false)); file.Seek(position + 18); file.WriteBlock(new_data); } position += size; } }
public Page[] Paginate(out int change) { if (pages_read == 0) { change = 0; return(new Page[0]); } int count = pages_read; ByteVectorCollection packets = new ByteVectorCollection(this.packets); PageHeader first_header = (PageHeader)first_page_header; List <Page> pages = new List <Page>(); uint index = 0; bool bos = first_header.PageSequenceNumber == 0; if (bos) { pages.Add(new Page(new ByteVectorCollection(packets[0]), first_header)); index++; packets.RemoveAt(0); count--; } int lacing_per_page = 0xfc; if (count > 0) { int total_lacing_bytes = 0; for (int i = 0; i < packets.Count; i++) { total_lacing_bytes += GetLacingValueLength(packets, i); } lacing_per_page = Math.Min(total_lacing_bytes / count + 1, lacing_per_page); } int lacing_bytes_used = 0; ByteVectorCollection page_packets = new ByteVectorCollection(); bool first_packet_continued = false; while (packets.Count > 0) { int packet_bytes = GetLacingValueLength(packets, 0); int remaining = lacing_per_page - lacing_bytes_used; bool whole_packet = packet_bytes <= remaining; if (whole_packet) { page_packets.Add(packets[0]); lacing_bytes_used += packet_bytes; packets.RemoveAt(0); } else { page_packets.Add(packets[0].Mid(0, remaining * 0xff)); packets[0] = packets[0].Mid(remaining * 0xff); lacing_bytes_used += remaining; } if (lacing_bytes_used == lacing_per_page) { pages.Add(new Page(page_packets, new PageHeader(first_header, index, first_packet_continued?PageFlags.FirstPacketContinued:PageFlags.None))); page_packets = new ByteVectorCollection(); lacing_bytes_used = 0; index++; count--; first_packet_continued = !whole_packet; } } if (page_packets.Count > 0) { pages.Add(new Page(page_packets, new PageHeader(first_header.StreamSerialNumber, index, first_packet_continued?PageFlags.FirstPacketContinued:PageFlags.None))); index++; count--; } change = -count; return(pages.ToArray()); }