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();
}
}