using System; using System.IO; using Matroska.Enumerations; namespace Matroska.Models; /// /// http://matroska.sourceforge.net/technical/specs/index.html#block_structure /// public class Block : IParseRawBinary { private const byte LacingBits = 0b0000110; private const byte InvisibleBit = 0b00010000; /// /// Track Number (Track Entry) /// public ulong TrackNumber { get; private set; } public byte Flags { get; private set; } /// /// Number of frames in the lace-1 (uint8) /// public int NumFrames { get; private set; } /// /// Lace-coded size of each frame of the lace, except for the last one (multiple uint8). /// *This is not used with Fixed-size lacing as it is calculated automatically from (total size of lace) / (number of frames in lace). /// public byte LaceCodedSizeOfEachFrame { get; private set; } /// /// Timecode (relative to Cluster timecode, signed int16) /// public short TimeCode { get; private set; } /// /// Invisible, the codec should decode this frame but not display it /// public bool IsInvisible { get; private set; } /// /// Lacing /// public Lacing Lacing { get; private set; } public byte[]? Data { get; private set; } public virtual void Parse(Span span) { var spanReader = new SpanReader(span); TrackNumber = spanReader.ReadVInt().Value; TimeCode = spanReader.ReadShort(true); // EBML integer datatypes are big-endian Flags = spanReader.ReadByte(); IsInvisible = (Flags & InvisibleBit) == InvisibleBit; Lacing = (Lacing)(Flags & LacingBits); if (Lacing != Lacing.No) { NumFrames = spanReader.ReadByte(); if (Lacing != Lacing.FixedSize) { LaceCodedSizeOfEachFrame = spanReader.ReadByte(); } } Data = span.Slice(spanReader.Position).ToArray(); } }