H264Decoder.cs
1 using Ryujinx.Graphics.Nvdec.FFmpeg.H264; 2 using Ryujinx.Graphics.Nvdec.Image; 3 using Ryujinx.Graphics.Nvdec.Types.H264; 4 using Ryujinx.Graphics.Video; 5 using System; 6 7 namespace Ryujinx.Graphics.Nvdec 8 { 9 static class H264Decoder 10 { 11 private const int MbSizeInPixels = 16; 12 13 public static void Decode(NvdecDecoderContext context, ResourceManager rm, ref NvdecRegisters state) 14 { 15 PictureInfo pictureInfo = rm.MemoryManager.DeviceRead<PictureInfo>(state.SetDrvPicSetupOffset); 16 H264PictureInfo info = pictureInfo.Convert(); 17 18 ReadOnlySpan<byte> bitstream = rm.MemoryManager.DeviceGetSpan(state.SetInBufBaseOffset, (int)pictureInfo.BitstreamSize); 19 20 int width = (int)pictureInfo.PicWidthInMbs * MbSizeInPixels; 21 int height = (int)pictureInfo.PicHeightInMbs * MbSizeInPixels; 22 23 int surfaceIndex = (int)pictureInfo.OutputSurfaceIndex; 24 25 uint lumaOffset = state.SetPictureLumaOffset[surfaceIndex]; 26 uint chromaOffset = state.SetPictureChromaOffset[surfaceIndex]; 27 28 Decoder decoder = context.GetH264Decoder(); 29 30 ISurface outputSurface = rm.Cache.Get(decoder, 0, 0, width, height); 31 32 if (decoder.Decode(ref info, outputSurface, bitstream)) 33 { 34 if (outputSurface.Field == FrameField.Progressive) 35 { 36 SurfaceWriter.Write( 37 rm.MemoryManager, 38 outputSurface, 39 lumaOffset + pictureInfo.LumaFrameOffset, 40 chromaOffset + pictureInfo.ChromaFrameOffset); 41 } 42 else 43 { 44 SurfaceWriter.WriteInterlaced( 45 rm.MemoryManager, 46 outputSurface, 47 lumaOffset + pictureInfo.LumaTopFieldOffset, 48 chromaOffset + pictureInfo.ChromaTopFieldOffset, 49 lumaOffset + pictureInfo.LumaBottomFieldOffset, 50 chromaOffset + pictureInfo.ChromaBottomFieldOffset); 51 } 52 } 53 54 rm.Cache.Put(outputSurface); 55 } 56 } 57 }