Blob(long len, Stream stream) { if (len < 0) { throw new ArgumentOutOfRangeException(); } long startPosition = stream.Position; trackNumber = checked ((byte)stream.readUint4()); Span <byte> buffer = stackalloc byte[3]; stream.read(buffer); timestamp = BinaryPrimitives.ReadInt16BigEndian(buffer); flags = (eBlockFlags)buffer[2]; long currentPosition = stream.Position; position = currentPosition; length = checked ((int)(len - (currentPosition - startPosition))); }
public static void unpackFrames(this Stream stream, ref Blob blob, ref LacedFrames laced) { eBlockFlags lacing = blob.lacing; if (lacing == eBlockFlags.NoLacing) { // laced.frames?.Clear(); laced.lacing = eLacingResult.NoLacing; return; } stream.Seek(blob.position, SeekOrigin.Begin); int lacingHeader; if (blob.length <= maxBuffer) { if (null != laced.buffer) { if (laced.buffer.Length < blob.length) { laced.buffer = new byte[blob.length]; } } else { laced.buffer = new byte[blob.length]; } stream.read(laced.buffer.AsSpan().Slice(0, blob.length)); lacingHeader = laced.buffer[0]; laced.lacing = eLacingResult.Buffered; } else { lacingHeader = stream.ReadByte(); if (lacingHeader < 0) { throw new EndOfStreamException(); } laced.lacing = eLacingResult.Large; } int lacedBlocksCount = lacingHeader + 1; laced.initialize(lacedBlocksCount); switch (lacing) { case eBlockFlags.FixedSize: int cbPayload = blob.length - 1; if (0 != cbPayload % lacedBlocksCount) { throw new ArgumentException($"Error in the MKV file, blob header specifies fixed size lacing with { lacedBlocksCount } laced frames, yet the block payload size { cbPayload } ain’t divisible"); } int cbFrame = cbPayload / lacedBlocksCount; for (int i = 0; i < lacedBlocksCount; i++) { laced.add(1 + cbFrame * i, cbFrame); } return; case eBlockFlags.EBML: if (laced.lacing == eLacingResult.Buffered) { unpackEbmlFromBuffer(lacedBlocksCount, laced.buffer.AsSpan().Slice(0, blob.length), ref laced); } else { unpackEbmlFromStream(lacedBlocksCount, stream, blob.length, ref laced); } break; default: throw new NotImplementedException($"{ lacing } lacing is not implemented"); } }