aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics/VDec/VpxRangeEncoder.cs
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-12-03 00:38:47 -0200
committerGitHub <noreply@github.com>2018-12-03 00:38:47 -0200
commitc86aacde76b5f8e503e2b412385c8491ecc86b3b (patch)
tree8e4737422fba15199c1a6ce7c6345996c0e907b5 /Ryujinx.Graphics/VDec/VpxRangeEncoder.cs
parentad00fd02442cf9c0f00c4562635738042b521efa (diff)
NVDEC implementation using FFmpeg (#443)
* Initial nvdec implementation using FFmpeg * Fix swapped channels on the video decoder and the G8R8 texture format * Fix texture samplers not being set properly (regression) * Rebased * Remove unused code introduced on the rebase * Add support for RGBA8 output format on the video image composer * Correct spacing * Some fixes for rebase and other tweaks * Allow size mismatch on frame copy * Get rid of GetHostAddress calls on VDec
Diffstat (limited to 'Ryujinx.Graphics/VDec/VpxRangeEncoder.cs')
-rw-r--r--Ryujinx.Graphics/VDec/VpxRangeEncoder.cs134
1 files changed, 134 insertions, 0 deletions
diff --git a/Ryujinx.Graphics/VDec/VpxRangeEncoder.cs b/Ryujinx.Graphics/VDec/VpxRangeEncoder.cs
new file mode 100644
index 00000000..3e381d2c
--- /dev/null
+++ b/Ryujinx.Graphics/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)
+ {
+ 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);
+ }
+ }
+ }
+} \ No newline at end of file