aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Nvdec
diff options
context:
space:
mode:
authorAc_K <Acoustik666@gmail.com>2021-10-12 22:55:57 +0200
committerGitHub <noreply@github.com>2021-10-12 22:55:57 +0200
commitd1604aa762a3f669a3fecff0a30b7360399954bc (patch)
tree1996eec4b3937354aedc4d31b5b7b931ae4e321b /Ryujinx.Graphics.Nvdec
parenta7109c767bdc014327b574012794156c92174495 (diff)
nvdec: Adding Vp8 codec support (#2707)
* first try * second try * working update * Final impl * Fixes nits * Fix everything * remove leftover * Update FFmpegContext.cs * Update Surface.cs * Addresses gdkchan feedback * bool not byte * Addresses gdkchan feedback
Diffstat (limited to 'Ryujinx.Graphics.Nvdec')
-rw-r--r--Ryujinx.Graphics.Nvdec/H264Decoder.cs6
-rw-r--r--Ryujinx.Graphics.Nvdec/NvdecDecoderContext.cs20
-rw-r--r--Ryujinx.Graphics.Nvdec/NvdecDevice.cs3
-rw-r--r--Ryujinx.Graphics.Nvdec/Ryujinx.Graphics.Nvdec.csproj2
-rw-r--r--Ryujinx.Graphics.Nvdec/Types/Vp8/PictureInfo.cs75
-rw-r--r--Ryujinx.Graphics.Nvdec/Vp8Decoder.cs33
6 files changed, 129 insertions, 10 deletions
diff --git a/Ryujinx.Graphics.Nvdec/H264Decoder.cs b/Ryujinx.Graphics.Nvdec/H264Decoder.cs
index 1ee3997b..69eeb494 100644
--- a/Ryujinx.Graphics.Nvdec/H264Decoder.cs
+++ b/Ryujinx.Graphics.Nvdec/H264Decoder.cs
@@ -1,4 +1,4 @@
-using Ryujinx.Graphics.Nvdec.H264;
+using Ryujinx.Graphics.Nvdec.FFmpeg.H264;
using Ryujinx.Graphics.Nvdec.Image;
using Ryujinx.Graphics.Nvdec.Types.H264;
using Ryujinx.Graphics.Video;
@@ -10,7 +10,7 @@ namespace Ryujinx.Graphics.Nvdec
{
private const int MbSizeInPixels = 16;
- public unsafe static void Decode(NvdecDecoderContext context, ResourceManager rm, ref NvdecRegisters state)
+ public static void Decode(NvdecDecoderContext context, ResourceManager rm, ref NvdecRegisters state)
{
PictureInfo pictureInfo = rm.Gmm.DeviceRead<PictureInfo>(state.SetPictureInfoOffset);
H264PictureInfo info = pictureInfo.Convert();
@@ -25,7 +25,7 @@ namespace Ryujinx.Graphics.Nvdec
uint lumaOffset = state.SetSurfaceLumaOffset[surfaceIndex];
uint chromaOffset = state.SetSurfaceChromaOffset[surfaceIndex];
- Decoder decoder = context.GetDecoder();
+ Decoder decoder = context.GetH264Decoder();
ISurface outputSurface = rm.Cache.Get(decoder, 0, 0, width, height);
diff --git a/Ryujinx.Graphics.Nvdec/NvdecDecoderContext.cs b/Ryujinx.Graphics.Nvdec/NvdecDecoderContext.cs
index 90da0bee..54934bc5 100644
--- a/Ryujinx.Graphics.Nvdec/NvdecDecoderContext.cs
+++ b/Ryujinx.Graphics.Nvdec/NvdecDecoderContext.cs
@@ -1,21 +1,29 @@
-using Ryujinx.Graphics.Nvdec.H264;
using System;
namespace Ryujinx.Graphics.Nvdec
{
class NvdecDecoderContext : IDisposable
{
- private Decoder _decoder;
+ private FFmpeg.H264.Decoder _h264Decoder;
+ private FFmpeg.Vp8.Decoder _vp8Decoder;
- public Decoder GetDecoder()
+ public FFmpeg.H264.Decoder GetH264Decoder()
{
- return _decoder ??= new Decoder();
+ return _h264Decoder ??= new FFmpeg.H264.Decoder();
+ }
+
+ public FFmpeg.Vp8.Decoder GetVp8Decoder()
+ {
+ return _vp8Decoder ??= new FFmpeg.Vp8.Decoder();
}
public void Dispose()
{
- _decoder?.Dispose();
- _decoder = null;
+ _h264Decoder?.Dispose();
+ _h264Decoder = null;
+
+ _vp8Decoder?.Dispose();
+ _vp8Decoder = null;
}
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Nvdec/NvdecDevice.cs b/Ryujinx.Graphics.Nvdec/NvdecDevice.cs
index 5319429b..18c2fc13 100644
--- a/Ryujinx.Graphics.Nvdec/NvdecDevice.cs
+++ b/Ryujinx.Graphics.Nvdec/NvdecDevice.cs
@@ -68,6 +68,9 @@ namespace Ryujinx.Graphics.Nvdec
case CodecId.H264:
H264Decoder.Decode(_currentContext, _rm, ref _state.State);
break;
+ case CodecId.Vp8:
+ Vp8Decoder.Decode(_currentContext, _rm, ref _state.State);
+ break;
case CodecId.Vp9:
Vp9Decoder.Decode(_rm, ref _state.State);
break;
diff --git a/Ryujinx.Graphics.Nvdec/Ryujinx.Graphics.Nvdec.csproj b/Ryujinx.Graphics.Nvdec/Ryujinx.Graphics.Nvdec.csproj
index 4c20979d..095e0e59 100644
--- a/Ryujinx.Graphics.Nvdec/Ryujinx.Graphics.Nvdec.csproj
+++ b/Ryujinx.Graphics.Nvdec/Ryujinx.Graphics.Nvdec.csproj
@@ -9,7 +9,7 @@
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
<ProjectReference Include="..\Ryujinx.Graphics.Device\Ryujinx.Graphics.Device.csproj" />
<ProjectReference Include="..\Ryujinx.Graphics.Gpu\Ryujinx.Graphics.Gpu.csproj" />
- <ProjectReference Include="..\Ryujinx.Graphics.Nvdec.H264\Ryujinx.Graphics.Nvdec.H264.csproj" />
+ <ProjectReference Include="..\Ryujinx.Graphics.Nvdec.FFmpeg\Ryujinx.Graphics.Nvdec.FFmpeg.csproj" />
<ProjectReference Include="..\Ryujinx.Graphics.Nvdec.Vp9\Ryujinx.Graphics.Nvdec.Vp9.csproj" />
<ProjectReference Include="..\Ryujinx.Graphics.Texture\Ryujinx.Graphics.Texture.csproj" />
<ProjectReference Include="..\Ryujinx.Graphics.Video\Ryujinx.Graphics.Video.csproj" />
diff --git a/Ryujinx.Graphics.Nvdec/Types/Vp8/PictureInfo.cs b/Ryujinx.Graphics.Nvdec/Types/Vp8/PictureInfo.cs
new file mode 100644
index 00000000..844f2103
--- /dev/null
+++ b/Ryujinx.Graphics.Nvdec/Types/Vp8/PictureInfo.cs
@@ -0,0 +1,75 @@
+using Ryujinx.Common.Memory;
+using Ryujinx.Graphics.Video;
+
+namespace Ryujinx.Graphics.Nvdec.Types.Vp8
+{
+ struct PictureInfo
+ {
+#pragma warning disable CS0649
+ public Array13<uint> Unknown0;
+ public uint GpTimerTimeoutValue;
+ public ushort FrameWidth;
+ public ushort FrameHeight;
+ public byte KeyFrame; // 1: key frame - 0: not
+ public byte Version;
+ public byte Flags0;
+ // TileFormat : 2 // 0: TBL; 1: KBL;
+ // GobHeight : 3 // Set GOB height, 0: GOB_2, 1: GOB_4, 2: GOB_8, 3: GOB_16, 4: GOB_32 (NVDEC3 onwards)
+ // ReserverdSurfaceFormat : 3
+ public byte ErrorConcealOn; // 1: error conceal on - 0: off
+ public uint FirstPartSize; // the size of first partition (frame header and mb header partition)
+ public uint HistBufferSize; // in units of 256
+ public uint VLDBufferSize; // in units of 1
+ public Array2<uint> FrameStride; // [y_c]
+ public uint LumaTopOffset; // offset of luma top field in units of 256
+ public uint LumaBotOffset; // offset of luma bottom field in units of 256
+ public uint LumaFrameOffset; // offset of luma frame in units of 256
+ public uint ChromaTopOffset; // offset of chroma top field in units of 256
+ public uint ChromaBotOffset; // offset of chroma bottom field in units of 256
+ public uint ChromaFrameOffset; // offset of chroma frame in units of 256
+ public uint Flags1;
+ // EnableTFOutput : 1; // =1, enable dbfdma to output the display surface; if disable, then the following configure on tf is useless.
+ // Remap for VC1
+ // VC1MapYFlag : 1
+ // MapYValue : 3
+ // VC1MapUVFlag : 1
+ // MapUVValue : 3
+ // TF
+ // OutStride : 8
+ // TilingFormat : 3;
+ // OutputStructure : 1 // 0:frame, 1:field
+ // Reserved0 : 11
+ public Array2<int> OutputTop; // in units of 256
+ public Array2<int> OutputBottom; // in units of 256
+ // Histogram
+ public uint Flags2;
+ // EnableHistogram : 1 // enable histogram info collection
+ // HistogramStartX : 12 // start X of Histogram window
+ // HistogramStartY : 12 // start Y of Histogram window
+ // Reserved1 : 7
+ // HistogramEndX : 12 // end X of Histogram window
+ // HistogramEndY : 12 // end y of Histogram window
+ // Reserved2 : 8
+ // Decode picture buffer related
+ public sbyte CurrentOutputMemoryLayout;
+ public Array3<sbyte> OutputMemoryLayout; // output NV12/NV24 setting. item 0:golden - 1: altref - 2: last
+ public byte SegmentationFeatureDataUpdate;
+ public Array3<byte> Reserved3;
+ public uint ResultValue; // ucode return result
+ public Array8<uint> PartitionOffset;
+ public Array3<uint> Reserved4;
+#pragma warning restore CS0649
+
+ public Vp8PictureInfo Convert()
+ {
+ return new Vp8PictureInfo()
+ {
+ KeyFrame = KeyFrame != 0,
+ FirstPartSize = FirstPartSize,
+ Version = Version,
+ FrameWidth = FrameWidth,
+ FrameHeight = FrameHeight
+ };
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.Nvdec/Vp8Decoder.cs b/Ryujinx.Graphics.Nvdec/Vp8Decoder.cs
new file mode 100644
index 00000000..8a369984
--- /dev/null
+++ b/Ryujinx.Graphics.Nvdec/Vp8Decoder.cs
@@ -0,0 +1,33 @@
+using Ryujinx.Graphics.Nvdec.FFmpeg.Vp8;
+using Ryujinx.Graphics.Nvdec.Image;
+using Ryujinx.Graphics.Nvdec.Types.Vp8;
+using Ryujinx.Graphics.Video;
+using System;
+
+namespace Ryujinx.Graphics.Nvdec
+{
+ static class Vp8Decoder
+ {
+ public static void Decode(NvdecDecoderContext context, ResourceManager rm, ref NvdecRegisters state)
+ {
+ PictureInfo pictureInfo = rm.Gmm.DeviceRead<PictureInfo>(state.SetPictureInfoOffset);
+ ReadOnlySpan<byte> bitstream = rm.Gmm.DeviceGetSpan(state.SetBitstreamOffset, (int)pictureInfo.VLDBufferSize);
+
+ Decoder decoder = context.GetVp8Decoder();
+
+ ISurface outputSurface = rm.Cache.Get(decoder, 0, 0, pictureInfo.FrameWidth, pictureInfo.FrameHeight);
+
+ Vp8PictureInfo info = pictureInfo.Convert();
+
+ uint lumaOffset = state.SetSurfaceLumaOffset[3];
+ uint chromaOffset = state.SetSurfaceChromaOffset[3];
+
+ if (decoder.Decode(ref info, outputSurface, bitstream))
+ {
+ SurfaceWriter.Write(rm.Gmm, outputSurface, lumaOffset, chromaOffset);
+ }
+
+ rm.Cache.Put(outputSurface);
+ }
+ }
+} \ No newline at end of file