aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Nvdec.Vp9/Decoder.cs
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2020-07-12 00:07:01 -0300
committerGitHub <noreply@github.com>2020-07-12 05:07:01 +0200
commit4d02a2d2c0451b4de1f6de3bbce54c457cacebe2 (patch)
tree120fe4fb8cfa1ac1c6ef4c97d92be47e955e8c0f /Ryujinx.Graphics.Nvdec.Vp9/Decoder.cs
parent38b26cf4242999fa7d8c550993ac0940cd03d55f (diff)
New NVDEC and VIC implementation (#1384)
* Initial NVDEC and VIC implementation * Update FFmpeg.AutoGen to 4.3.0 * Add nvdec dependencies for Windows * Unify some VP9 structures * Rename VP9 structure fields * Improvements to Video API * XML docs for Common.Memory * Remove now unused or redundant overloads from MemoryAccessor * NVDEC UV surface read/write scalar paths * Add FIXME comments about hacky things/stuff that will need to be fixed in the future * Cleaned up VP9 memory allocation * Remove some debug logs * Rename some VP9 structs * Remove unused struct * No need to compile Ryujinx.Graphics.Host1x with unsafe anymore * Name AsyncWorkQueue threads to make debugging easier * Make Vp9PictureInfo a ref struct * LayoutConverter no longer needs the depth argument (broken by rebase) * Pooling of VP9 buffers, plus fix a memory leak on VP9 * Really wish VS could rename projects properly... * Address feedback * Remove using * Catch OperationCanceledException * Add licensing informations * Add THIRDPARTY.md to release too Co-authored-by: Thog <me@thog.eu>
Diffstat (limited to 'Ryujinx.Graphics.Nvdec.Vp9/Decoder.cs')
-rw-r--r--Ryujinx.Graphics.Nvdec.Vp9/Decoder.cs164
1 files changed, 164 insertions, 0 deletions
diff --git a/Ryujinx.Graphics.Nvdec.Vp9/Decoder.cs b/Ryujinx.Graphics.Nvdec.Vp9/Decoder.cs
new file mode 100644
index 00000000..df3199cf
--- /dev/null
+++ b/Ryujinx.Graphics.Nvdec.Vp9/Decoder.cs
@@ -0,0 +1,164 @@
+using Ryujinx.Common.Memory;
+using Ryujinx.Graphics.Nvdec.Vp9.Common;
+using Ryujinx.Graphics.Nvdec.Vp9.Types;
+using Ryujinx.Graphics.Video;
+using System;
+using Vp9MvRef = Ryujinx.Graphics.Video.Vp9MvRef;
+
+namespace Ryujinx.Graphics.Nvdec.Vp9
+{
+ public class Decoder : IVp9Decoder
+ {
+ public bool IsHardwareAccelerated => false;
+
+ private readonly MemoryAllocator _allocator = new MemoryAllocator();
+
+ public ISurface CreateSurface(int width, int height) => new Surface(width, height);
+
+ private static readonly byte[] LiteralToFilter = new byte[]
+ {
+ Constants.EightTapSmooth,
+ Constants.EightTap,
+ Constants.EightTapSharp,
+ Constants.Bilinear
+ };
+
+ public unsafe bool Decode(
+ ref Vp9PictureInfo pictureInfo,
+ ISurface output,
+ ReadOnlySpan<byte> bitstream,
+ ReadOnlySpan<Vp9MvRef> mvsIn,
+ Span<Vp9MvRef> mvsOut)
+ {
+ Vp9Common cm = new Vp9Common();
+
+ cm.FrameType = pictureInfo.IsKeyFrame ? FrameType.KeyFrame : FrameType.InterFrame;
+ cm.IntraOnly = pictureInfo.IntraOnly;
+
+ cm.Width = output.Width;
+ cm.Height = output.Height;
+
+ cm.UsePrevFrameMvs = pictureInfo.UsePrevInFindMvRefs;
+
+ cm.RefFrameSignBias = pictureInfo.RefFrameSignBias;
+
+ cm.BaseQindex = pictureInfo.BaseQIndex;
+ cm.YDcDeltaQ = pictureInfo.YDcDeltaQ;
+ cm.UvAcDeltaQ = pictureInfo.UvAcDeltaQ;
+ cm.UvDcDeltaQ = pictureInfo.UvDcDeltaQ;
+
+ cm.Mb.Lossless = pictureInfo.Lossless;
+
+ cm.TxMode = (TxMode)pictureInfo.TransformMode;
+
+ cm.AllowHighPrecisionMv = pictureInfo.AllowHighPrecisionMv;
+
+ cm.InterpFilter = (byte)pictureInfo.InterpFilter;
+
+ if (cm.InterpFilter != Constants.Switchable)
+ {
+ cm.InterpFilter = LiteralToFilter[cm.InterpFilter];
+ }
+
+ cm.ReferenceMode = (ReferenceMode)pictureInfo.ReferenceMode;
+
+ cm.CompFixedRef = pictureInfo.CompFixedRef;
+ cm.CompVarRef = pictureInfo.CompVarRef;
+
+ cm.Log2TileCols = pictureInfo.Log2TileCols;
+ cm.Log2TileRows = pictureInfo.Log2TileRows;
+
+ cm.Seg.Enabled = pictureInfo.SegmentEnabled;
+ cm.Seg.UpdateMap = pictureInfo.SegmentMapUpdate;
+ cm.Seg.TemporalUpdate = pictureInfo.SegmentMapTemporalUpdate;
+ cm.Seg.AbsDelta = (byte)pictureInfo.SegmentAbsDelta;
+ cm.Seg.FeatureMask = pictureInfo.SegmentFeatureEnable;
+ cm.Seg.FeatureData = pictureInfo.SegmentFeatureData;
+
+ cm.Lf.ModeRefDeltaEnabled = pictureInfo.ModeRefDeltaEnabled;
+ cm.Lf.RefDeltas = pictureInfo.RefDeltas;
+ cm.Lf.ModeDeltas = pictureInfo.ModeDeltas;
+
+ cm.Fc = new Ptr<Vp9EntropyProbs>(ref pictureInfo.Entropy);
+ cm.Counts = new Ptr<Vp9BackwardUpdates>(ref pictureInfo.BackwardUpdateCounts);
+
+ cm.FrameRefs[0].Buf = (Surface)pictureInfo.LastReference;
+ cm.FrameRefs[1].Buf = (Surface)pictureInfo.GoldenReference;
+ cm.FrameRefs[2].Buf = (Surface)pictureInfo.AltReference;
+ cm.Mb.CurBuf = (Surface)output;
+
+ cm.Mb.SetupBlockPlanes(1, 1);
+
+ cm.AllocTileWorkerData(_allocator, 1 << pictureInfo.Log2TileCols, 1 << pictureInfo.Log2TileRows);
+ cm.AllocContextBuffers(_allocator, output.Width, output.Height);
+ cm.InitContextBuffers();
+ cm.SetupSegmentationDequant();
+ cm.SetupScaleFactors();
+
+ SetMvs(ref cm, mvsIn);
+
+ fixed (byte* dataPtr = bitstream)
+ {
+ try
+ {
+ DecodeFrame.DecodeTiles(ref cm, new ArrayPtr<byte>(dataPtr, bitstream.Length));
+ }
+ catch (InternalErrorException)
+ {
+ return false;
+ }
+ }
+
+ GetMvs(ref cm, mvsOut);
+
+ cm.FreeTileWorkerData(_allocator);
+ cm.FreeContextBuffers(_allocator);
+
+ return true;
+ }
+
+ private static void SetMvs(ref Vp9Common cm, ReadOnlySpan<Vp9MvRef> mvs)
+ {
+ if (mvs.Length > cm.PrevFrameMvs.Length)
+ {
+ throw new ArgumentException($"Size mismatch, expected: {cm.PrevFrameMvs.Length}, but got: {mvs.Length}.");
+ }
+
+ for (int i = 0; i < mvs.Length; i++)
+ {
+ ref var mv = ref cm.PrevFrameMvs[i];
+
+ mv.Mv[0].Row = mvs[i].Mvs[0].Row;
+ mv.Mv[0].Col = mvs[i].Mvs[0].Col;
+ mv.Mv[1].Row = mvs[i].Mvs[1].Row;
+ mv.Mv[1].Col = mvs[i].Mvs[1].Col;
+
+ mv.RefFrame[0] = (sbyte)mvs[i].RefFrames[0];
+ mv.RefFrame[1] = (sbyte)mvs[i].RefFrames[1];
+ }
+ }
+
+ private static void GetMvs(ref Vp9Common cm, Span<Vp9MvRef> mvs)
+ {
+ if (mvs.Length > cm.CurFrameMvs.Length)
+ {
+ throw new ArgumentException($"Size mismatch, expected: {cm.CurFrameMvs.Length}, but got: {mvs.Length}.");
+ }
+
+ for (int i = 0; i < mvs.Length; i++)
+ {
+ ref var mv = ref cm.CurFrameMvs[i];
+
+ mvs[i].Mvs[0].Row = mv.Mv[0].Row;
+ mvs[i].Mvs[0].Col = mv.Mv[0].Col;
+ mvs[i].Mvs[1].Row = mv.Mv[1].Row;
+ mvs[i].Mvs[1].Col = mv.Mv[1].Col;
+
+ mvs[i].RefFrames[0] = mv.RefFrame[0];
+ mvs[i].RefFrames[1] = mv.RefFrame[1];
+ }
+ }
+
+ public void Dispose() => _allocator.Dispose();
+ }
+}