134 lines
3.6 KiB
C#
134 lines
3.6 KiB
C#
|
using System.IO;
|
||
|
|
||
|
namespace Ryujinx.Graphics.VDec
|
||
|
{
|
||
|
class VpxRangeEncoder
|
||
|
{
|
||
|
private const int HalfProbability = 128;
|
||
|
|
||
|
private static readonly int[] NormLut = new int[]
|
||
|
{
|
||
|
0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
|
||
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||
|
};
|
||
|
|
||
|
private Stream BaseStream;
|
||
|
|
||
|
private uint LowValue;
|
||
|
private uint Range;
|
||
|
private int Count;
|
||
|
|
||
|
public VpxRangeEncoder(Stream BaseStream)
|
||
|
{
|
||
|
this.BaseStream = BaseStream;
|
||
|
|
||
|
Range = 0xff;
|
||
|
Count = -24;
|
||
|
|
||
|
Write(false);
|
||
|
}
|
||
|
|
||
|
public void WriteByte(byte Value)
|
||
|
{
|
||
|
Write(Value, 8);
|
||
|
}
|
||
|
|
||
|
public void Write(int Value, int ValueSize)
|
||
|
{
|
||
|
for (int Bit = ValueSize - 1; Bit >= 0; Bit--)
|
||
|
{
|
||
|
Write(((Value >> Bit) & 1) != 0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void Write(bool Bit)
|
||
|
{
|
||
|
Write(Bit, HalfProbability);
|
||
|
}
|
||
|
|
||
|
public void Write(bool Bit, int Probability)
|
||
|
{
|
||
|
uint Range = this.Range;
|
||
|
|
||
|
uint Split = 1 + (((Range - 1) * (uint)Probability) >> 8);
|
||
|
|
||
|
Range = Split;
|
||
|
|
||
|
if (Bit)
|
||
|
{
|
||
|
LowValue += Split;
|
||
|
Range = this.Range - Split;
|
||
|
}
|
||
|
|
||
|
int Shift = NormLut[Range];
|
||
|
|
||
|
Range <<= Shift;
|
||
|
Count += Shift;
|
||
|
|
||
|
if (Count >= 0)
|
||
|
{
|
||
|
int Offset = Shift - Count;
|
||
|
|
||
|
if (((LowValue << (Offset - 1)) >> 31) != 0)
|
||
|
{
|
||
|
long CurrentPos = BaseStream.Position;
|
||
|
|
||
|
BaseStream.Seek(-1, SeekOrigin.Current);
|
||
|
|
||
|
while (BaseStream.Position >= 0 && PeekByte() == 0xff)
|
||
|
{
|
||
|
BaseStream.WriteByte(0);
|
||
|
|
||
|
BaseStream.Seek(-2, SeekOrigin.Current);
|
||
|
}
|
||
|
|
||
|
BaseStream.WriteByte((byte)(PeekByte() + 1));
|
||
|
|
||
|
BaseStream.Seek(CurrentPos, SeekOrigin.Begin);
|
||
|
}
|
||
|
|
||
|
BaseStream.WriteByte((byte)(LowValue >> (24 - Offset)));
|
||
|
|
||
|
LowValue <<= Offset;
|
||
|
Shift = Count;
|
||
|
LowValue &= 0xffffff;
|
||
|
Count -= 8;
|
||
|
}
|
||
|
|
||
|
LowValue <<= Shift;
|
||
|
|
||
|
this.Range = Range;
|
||
|
}
|
||
|
|
||
|
private byte PeekByte()
|
||
|
{
|
||
|
byte Value = (byte)BaseStream.ReadByte();
|
||
|
|
||
|
BaseStream.Seek(-1, SeekOrigin.Current);
|
||
|
|
||
|
return Value;
|
||
|
}
|
||
|
|
||
|
public void End()
|
||
|
{
|
||
|
for (int Index = 0; Index < 32; Index++)
|
||
|
{
|
||
|
Write(false);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|