aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Nvdec/VDec/VpxRangeEncoder.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics.Nvdec/VDec/VpxRangeEncoder.cs')
-rw-r--r--Ryujinx.Graphics.Nvdec/VDec/VpxRangeEncoder.cs134
1 files changed, 134 insertions, 0 deletions
diff --git a/Ryujinx.Graphics.Nvdec/VDec/VpxRangeEncoder.cs b/Ryujinx.Graphics.Nvdec/VDec/VpxRangeEncoder.cs
new file mode 100644
index 00000000..c854c9d9
--- /dev/null
+++ b/Ryujinx.Graphics.Nvdec/VDec/VpxRangeEncoder.cs
@@ -0,0 +1,134 @@
+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)
+ {
+ _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 = _range;
+
+ uint split = 1 + (((range - 1) * (uint)probability) >> 8);
+
+ range = split;
+
+ if (bit)
+ {
+ _lowValue += split;
+ range = _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;
+
+ _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);
+ }
+ }
+ }
+} \ No newline at end of file