/// <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) { ulong offset = 0; while (offset < (ulong)Length) { EBMLElement element = new EBMLElement(this, offset); EBMLID ebml_id = (EBMLID)element.ID; MatroskaID matroska_id = (MatroskaID)element.ID; switch (ebml_id) { case EBMLID.EBMLHeader: ReadHeader(element); break; default: break; } switch (matroska_id) { case MatroskaID.MatroskaSegment: ReadSegment(element); break; default: break; } offset += element.Size; } }
private void ReadSegment(EBMLElement element) { ulong i = 0; while (i < element.DataSize) { EBMLElement child = new EBMLElement(this, element.DataOffset + i); MatroskaID matroska_id = (MatroskaID)child.ID; switch (matroska_id) { case MatroskaID.MatroskaTracks: ReadTracks(child); break; case MatroskaID.MatroskaSegmentInfo: ReadSegmentInfo(child); break; case MatroskaID.MatroskaTags: ReadTags(child); break; case MatroskaID.MatroskaCluster: // Get out of here when we reach the clusters for now. return; default: break; } i += child.Size; } }
/// <summary> /// Constructs a <see cref="Track" /> parsing from provided /// file data. /// Parsing will be done reading from _file at position references by /// parent element's data section. /// </summary> /// <param name="_file"><see cref="File" /> instance to read from.</param> /// <param name="element">Parent <see cref="EBMLElement" />.</param> public Track(File _file, EBMLElement element) { ulong i = 0; while (i < element.DataSize) { EBMLElement child = new EBMLElement(_file, element.DataOffset + i); MatroskaID matroska_id = (MatroskaID)child.ID; switch (matroska_id) { case MatroskaID.MatroskaTrackNumber: track_number = child.ReadUInt(); break; case MatroskaID.MatroskaTrackUID: track_uid = child.ReadUInt(); break; case MatroskaID.MatroskaCodecID: track_codec_id = child.ReadString(); break; case MatroskaID.MatroskaCodecName: track_codec_name = child.ReadString(); break; case MatroskaID.MatroskaTrackName: track_name = child.ReadString(); break; case MatroskaID.MatroskaTrackLanguage: track_language = child.ReadString(); break; case MatroskaID.MatroskaTrackFlagEnabled: track_enabled = child.ReadBool(); break; case MatroskaID.MatroskaTrackFlagDefault: track_default = child.ReadBool(); break; case MatroskaID.MatroskaCodecPrivate: codec_data = child.ReadBytes(); break; default: unknown_elems.Add(child); break; } i += child.Size; } }
private void ReadTrackEntry(EBMLElement element) { ulong i = 0; while (i < element.DataSize) { EBMLElement child = new EBMLElement(this, element.DataOffset + i); MatroskaID matroska_id = (MatroskaID)child.ID; switch (matroska_id) { case MatroskaID.MatroskaTrackType: { TrackType track_type = (TrackType)child.ReadUInt(); switch (track_type) { case TrackType.Video: { VideoTrack track = new VideoTrack(this, element); tracks.Add(track); break; } case TrackType.Audio: { AudioTrack track = new AudioTrack(this, element); tracks.Add(track); break; } case TrackType.Subtitle: { SubtitleTrack track = new SubtitleTrack(this, element); tracks.Add(track); break; } default: break; } break; } default: break; } i += child.Size; } }
private void ReadSimpleTag(EBMLElement element) { ulong i = 0; #pragma warning disable 219 // Assigned, never read string tag_name = null, tag_language = null, tag_string = null; #pragma warning restore 219 while (i < element.DataSize) { EBMLElement child = new EBMLElement(this, element.DataOffset + i); MatroskaID matroska_id = (MatroskaID)child.ID; switch (matroska_id) { case MatroskaID.MatroskaTagName: tag_name = child.ReadString(); break; case MatroskaID.MatroskaTagLanguage: tag_language = child.ReadString(); break; case MatroskaID.MatroskaTagString: tag_string = child.ReadString(); break; default: break; } i += child.Size; } if (tag_name == "AUTHOR") { tag.Performers = new string [] { tag_string }; } else if (tag_name == "TITLE") { tag.Title = tag_string; } else if (tag_name == "ALBUM") { tag.Album = tag_string; } else if (tag_name == "COMMENTS") { tag.Comment = tag_string; } }
public SubtitleTrack(File _file, EBMLElement element) : base(_file, element) { foreach (EBMLElement elem in base.UnknownElements) { MatroskaID matroska_id = (MatroskaID)elem.ID; switch (matroska_id) { default: unknown_elems.Add(elem); break; } } }
/// <summary> /// Create a new abstract <see cref="EBMLreader" /> with arbitrary attributes, /// without reading its information on the file. /// </summary> /// <param name="parent">The <see cref="EBMLreader" /> that contains the instance to be described.</param> /// <param name="position">Position in the file.</param> /// <param name="ebmlid">EBML ID of the element</param> /// <param name="size">Total size of the EBML, in bytes</param> public EBMLreader(EBMLreader parent, ulong position, MatroskaID ebmlid, ulong size = 0) { // Keep a reference to the file if (parent != null) { file = parent.file; } this.parent = parent; // Initialize attributes offset = position; data_offset = offset; ebml_id = (uint)ebmlid; ebml_size = size; }
/// <summary> /// Constructs a <see cref="SubtitleTrack" /> parsing from provided /// file data. /// Parsing will be done reading from _file at position references by /// parent element's data section. /// </summary> /// <param name="_file"><see cref="File" /> instance to read from.</param> /// <param name="element">Parent <see cref="EBMLElement" />.</param> public SubtitleTrack(File _file, EBMLElement element) : base(_file, element) { // Here we handle the unknown elements we know, and store the rest foreach (EBMLElement elem in base.UnknownElements) { MatroskaID matroska_id = (MatroskaID)elem.ID; switch (matroska_id) { default: unknown_elems.Add(elem); break; } } }
/// <summary> /// Create a UIDElement Stub /// </summary> /// <param name="type">Tag-type the UID represents</param> /// <param name="uid">UID of the element</param> public UIDElement(MatroskaID type, ulong uid) { UID = uid; if (type == MatroskaID.TagTrackUID || type == MatroskaID.TagEditionUID || type == MatroskaID.TagChapterUID || type == MatroskaID.TagAttachmentUID ) { UIDType = type; } else { UIDType = 0; } }
private void ReadTracks(EBMLElement element) { ulong i = 0; while (i < element.DataSize) { EBMLElement child = new EBMLElement(this, element.DataOffset + i); MatroskaID matroska_id = (MatroskaID)child.ID; switch (matroska_id) { case MatroskaID.MatroskaTrackEntry: ReadTrackEntry(child); break; default: break; } i += child.Size; } }
private void ReadSegmentInfo(EBMLElement element) { ulong i = 0; while (i < element.DataSize) { EBMLElement child = new EBMLElement(this, element.DataOffset + i); MatroskaID matroska_id = (MatroskaID)child.ID; switch (matroska_id) { case MatroskaID.MatroskaDuration: duration_unscaled = (UInt64)child.ReadDouble(); if (time_scale > 0) { duration = TimeSpan.FromSeconds(duration_unscaled * time_scale / 1000000000); } break; case MatroskaID.MatroskaTimeCodeScale: time_scale = child.ReadUInt(); if (duration_unscaled > 0) { duration = TimeSpan.FromSeconds(duration_unscaled * time_scale / 1000000000); } break; case MatroskaID.MatroskaTitle: title = child.ReadString(); break; default: break; } i += child.Size; } }
private bool ReadSeekHead(EBMLreader element, List <EBMLreader> segm_list) { MatroskaID ebml_id = 0; ulong ebml_position = 0; ulong i = 0; while (i < element.DataSize) { var ebml_seek = new EBMLreader(element, element.DataOffset + i); var matroska_id = ebml_seek.ID; if (matroska_id != MatroskaID.Seek) { return(false); // corrupted SeekHead } ulong j = 0; while (j < ebml_seek.DataSize) { var child = new EBMLreader(ebml_seek, ebml_seek.DataOffset + j); matroska_id = child.ID; switch (matroska_id) { case MatroskaID.SeekID: ebml_id = (MatroskaID)child.ReadULong(); break; case MatroskaID.SeekPosition: ebml_position = child.ReadULong() + element.Offset; break; } j += child.Size; } if (ebml_id > 0 && ebml_position > 0) { // Create abstract EBML representation of the segment EBML var ebml = new EBMLreader(element.Parent, ebml_position, ebml_id); // Sort the seek-entries by increasing position order int k; for (k = segm_list.Count - 1; k >= 0; k--) { if (ebml_position > segm_list[k] .Offset) { break; } } segm_list.Insert(k + 1, ebml); // Chained SeekHead recursive read if (ebml_id == MatroskaID.SeekHead) { if (!ebml.Read()) { return(false); // Corrupted } ReadSeekHead(ebml, segm_list); } } i += ebml_seek.Size; } return(true); }
/// <summary> /// Construct <see cref="EBMLelement" /> to contain data. /// </summary> /// <param name="ebmlid">EBML ID of the element to be created.</param> /// <param name="value">EBML data as an <see cref="ulong"/> value.</param> public EBMLelement(MatroskaID ebmlid, ulong value) { ID = ebmlid; SetData(value); }
/// <summary> /// Construct a <see cref="EBMLelement" /> to contain data. /// </summary> /// <param name="ebmlid">EBML ID of the element to be created.</param> /// <param name="data">EBML data of the element to be created.</param> public EBMLelement(MatroskaID ebmlid, ByteVector data) { ID = ebmlid; Data = data; }
/// <summary> /// Construct a <see cref="EBMLelement" /> to contain children elements. /// </summary> /// <param name="ebmlid">EBML ID of the element to be created.</param> public EBMLelement(MatroskaID ebmlid) { ID = ebmlid; Children = new List <EBMLelement>(); }