aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Nvdec/H264Decoder.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ryujinx.Graphics.Nvdec/H264Decoder.cs')
-rw-r--r--src/Ryujinx.Graphics.Nvdec/H264Decoder.cs57
1 files changed, 57 insertions, 0 deletions
diff --git a/src/Ryujinx.Graphics.Nvdec/H264Decoder.cs b/src/Ryujinx.Graphics.Nvdec/H264Decoder.cs
new file mode 100644
index 00000000..ecc7dbc7
--- /dev/null
+++ b/src/Ryujinx.Graphics.Nvdec/H264Decoder.cs
@@ -0,0 +1,57 @@
+using Ryujinx.Graphics.Nvdec.FFmpeg.H264;
+using Ryujinx.Graphics.Nvdec.Image;
+using Ryujinx.Graphics.Nvdec.Types.H264;
+using Ryujinx.Graphics.Video;
+using System;
+
+namespace Ryujinx.Graphics.Nvdec
+{
+ static class H264Decoder
+ {
+ private const int MbSizeInPixels = 16;
+
+ public static void Decode(NvdecDecoderContext context, ResourceManager rm, ref NvdecRegisters state)
+ {
+ PictureInfo pictureInfo = rm.Gmm.DeviceRead<PictureInfo>(state.SetDrvPicSetupOffset);
+ H264PictureInfo info = pictureInfo.Convert();
+
+ ReadOnlySpan<byte> bitstream = rm.Gmm.DeviceGetSpan(state.SetInBufBaseOffset, (int)pictureInfo.BitstreamSize);
+
+ int width = (int)pictureInfo.PicWidthInMbs * MbSizeInPixels;
+ int height = (int)pictureInfo.PicHeightInMbs * MbSizeInPixels;
+
+ int surfaceIndex = (int)pictureInfo.OutputSurfaceIndex;
+
+ uint lumaOffset = state.SetPictureLumaOffset[surfaceIndex];
+ uint chromaOffset = state.SetPictureChromaOffset[surfaceIndex];
+
+ Decoder decoder = context.GetH264Decoder();
+
+ ISurface outputSurface = rm.Cache.Get(decoder, 0, 0, width, height);
+
+ if (decoder.Decode(ref info, outputSurface, bitstream))
+ {
+ if (outputSurface.Field == FrameField.Progressive)
+ {
+ SurfaceWriter.Write(
+ rm.Gmm,
+ outputSurface,
+ lumaOffset + pictureInfo.LumaFrameOffset,
+ chromaOffset + pictureInfo.ChromaFrameOffset);
+ }
+ else
+ {
+ SurfaceWriter.WriteInterlaced(
+ rm.Gmm,
+ outputSurface,
+ lumaOffset + pictureInfo.LumaTopFieldOffset,
+ chromaOffset + pictureInfo.ChromaTopFieldOffset,
+ lumaOffset + pictureInfo.LumaBottomFieldOffset,
+ chromaOffset + pictureInfo.ChromaBottomFieldOffset);
+ }
+ }
+
+ rm.Cache.Put(outputSurface);
+ }
+ }
+}