FastVideoDSEncoder/Gericom.FastVideoDS/Bitstream/BitReader.cs
2022-10-13 11:27:48 +02:00

69 lines
2.0 KiB
C#

using System;
using System.Buffers.Binary;
using System.Numerics;
namespace Gericom.FastVideoDS.Bitstream
{
public class BitReader
{
private readonly byte[] _data;
private int _offset;
public int BitsRemaining;
public uint Bits;
public BitReader(byte[] data)
{
_data = data;
Bits = (uint)(BinaryPrimitives.ReadUInt16LittleEndian(data) << 16);
BitsRemaining = 0;
_offset = 2;
}
public uint ReadUnsignedVarInt()
{
int clz = BitOperations.LeadingZeroCount(Bits); //nr zeros
Bits <<= clz; //remove the zeros
Bits += Bits; //remove the stop bit
int r9 = 32 - clz; //shift amount
uint r6 = r9 == 32 ? 0 : Bits >> r9;
r9 = 1;
r6 += (uint)(r9 << clz);
r6--;
Bits <<= clz;
BitsRemaining -= clz << 1;
if (--BitsRemaining < 0)
FillBits();
return r6;
}
public void FillBits()
{
if (_offset >= _data.Length)
return;
uint r10 = BinaryPrimitives.ReadUInt16LittleEndian(_data.AsSpan(_offset));
_offset += 2;
BitsRemaining += 0x10;
int r9 = 0x10 - BitsRemaining;
Bits |= r10 << r9;
}
private int ReadSignedVarInt()
{
int clz = BitOperations.LeadingZeroCount(Bits);
Bits <<= clz;
Bits += Bits;
int r9 = 32 - clz;
int r6 = r9 == 32 ? 0 : (int)(Bits >> r9);
r9 = 1;
r6 += r9 << clz;
if ((r6 & 1) != 0)
r6 = 1 - r6;
r6 >>= 1;
Bits <<= clz;
BitsRemaining -= clz << 1;
if (--BitsRemaining < 0)
FillBits();
return r6;
}
}
}