diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2018-12-03 00:38:47 -0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-12-03 00:38:47 -0200 |
| commit | c86aacde76b5f8e503e2b412385c8491ecc86b3b (patch) | |
| tree | 8e4737422fba15199c1a6ce7c6345996c0e907b5 /Ryujinx.Graphics/VDec/VpxRangeEncoder.cs | |
| parent | ad00fd02442cf9c0f00c4562635738042b521efa (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.cs | 134 |
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 |
