Example #1
0
        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)));
        }
Example #2
0
        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");
            }
        }