Exemple #1
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");
            }
        }
Exemple #2
0
        static void unpackEbmlFromBuffer(int lacedBlocksCount, ReadOnlySpan <byte> buffer, ref LacedFrames laced)
        {
            // The count is stored in 1 byte, the absolute max.limit is 256, totally fine for the stack.
            Span <int> sizes             = stackalloc int[lacedBlocksCount];
            int        lacingHeaderBytes = 1;      // The 1 byte is lacedBlocksCount we have already consumed from that buffer
            int        cb;
            int        prevSize = checked ((int)buffer.parseUint4(lacingHeaderBytes, out cb));

            lacingHeaderBytes += cb;
            sizes[0]           = prevSize;
            int combinedSize = prevSize;

            for (int i = 1; i < lacedBlocksCount - 1; i++)
            {
                int difference = checked ((int)buffer.parseUint4(lacingHeaderBytes, out cb));
                lacingHeaderBytes += cb;
                prevSize          += rangeShiftSignedInt(difference, cb);

                sizes[i]      = prevSize;
                combinedSize += prevSize;
            }
            // The size of the last frame is deduced from the total size of the Block.
            sizes[lacedBlocksCount - 1] = buffer.Length - lacingHeaderBytes - combinedSize;

            int pos = lacingHeaderBytes;

            for (int i = 0; i < lacedBlocksCount; i++)
            {
                laced.add(pos, sizes[i]);
                pos += sizes[i];
            }
        }
Exemple #3
0
        static void unpackEbmlFromStream(int lacedBlocksCount, Stream stream, int blobSize, ref LacedFrames laced)
        {
            Span <int> sizes             = stackalloc int[lacedBlocksCount];
            int        lacingHeaderBytes = 1;      // The 1 byte is lacedBlocksCount we have already read
            int        cb;
            int        prevSize = checked ((int)stream.readUint4(out cb));

            lacingHeaderBytes += cb;
            sizes[0]           = prevSize;
            int combinedSize = prevSize;

            for (int i = 1; i < lacedBlocksCount - 1; i++)
            {
                int difference = checked ((int)stream.readUint4(out cb));
                lacingHeaderBytes += cb;
                prevSize          += rangeShiftSignedInt(difference, cb);

                sizes[i]      = prevSize;
                combinedSize += prevSize;
            }
            // The size of the last frame is deduced from the total size of the Block.
            sizes[lacedBlocksCount - 1] = blobSize - lacingHeaderBytes - combinedSize;

            int pos = lacingHeaderBytes;

            for (int i = 0; i < lacedBlocksCount; i++)
            {
                laced.add(pos, sizes[i]);
                pos += sizes[i];
            }
        }