private void ReadCreateSegmentInfo(EBMLreader element, EBMLelement ebml_sinfo) { ulong i = 0; while (i < element.DataSize) { var child = new EBMLreader(element, element.DataOffset + i); switch (child.ID) { case MatroskaID.Duration: duration_unscaled = child.ReadDouble(); if (time_scale > 0) { duration = TimeSpan.FromMilliseconds(duration_unscaled * time_scale / 1000000); } break; case MatroskaID.TimeCodeScale: time_scale = child.ReadULong(); if (duration_unscaled > 0) { duration = TimeSpan.FromMilliseconds(duration_unscaled * time_scale / 1000000); } break; case MatroskaID.Title: break; } i += child.Size; } }
private void ReadWriteSegment(EBMLreader element, ReadStyle propertiesStyle, bool retry = true) { // First make reference of all EBML elements at level 1 (top) in the Segment var segm_list = ReadSegments(element, retry); // Try to get it from SeekHead the first time (way faster) // Now process (read and prepare to write) the referenced elements we care about EBMLelement ebml_sinfo = null; var valid = true; foreach (var child in segm_list) { // the child here may be Abstract if it has been retrieved in the SeekHead, // so child.Read() must be used to retrieve the full EBML header switch (child.ID) { case MatroskaID.SeekHead: valid = child.Read(); break; case MatroskaID.SegmentInfo: if (valid = child.Read()) { ReadCreateSegmentInfo(child, ebml_sinfo); } break; case MatroskaID.Tracks: if ((propertiesStyle & ReadStyle.Average) != 0) { if (valid = child.Read()) { ReadTracks(child); } } break; case MatroskaID.Tags: valid = child.Read(); break; case MatroskaID.Attachments: valid = child.Read(); if (valid) { ReadAttachments(child, propertiesStyle); } break; case MatroskaID.CRC32: // We don't support it valid = child.Read(); break; } if (!valid) { break; } } // Detect invalid SeekHead if (!valid) { if (retry) { MarkAsCorrupt("Invalid Meta Seek"); // Retry it one last time ReadWriteSegment(element, propertiesStyle, false); } else { MarkAsCorrupt("Invalid EBML element Read"); } } }