Decoder.cs
1 using Ryujinx.Graphics.Nvdec.FFmpeg.Native; 2 using Ryujinx.Graphics.Video; 3 using System; 4 5 namespace Ryujinx.Graphics.Nvdec.FFmpeg.H264 6 { 7 public sealed class Decoder : IH264Decoder 8 { 9 public bool IsHardwareAccelerated => false; 10 11 private const int WorkBufferSize = 0x200; 12 13 private readonly byte[] _workBuffer = new byte[WorkBufferSize]; 14 15 private FFmpegContext _context = new(AVCodecID.AV_CODEC_ID_H264); 16 17 private int _oldOutputWidth; 18 private int _oldOutputHeight; 19 20 public ISurface CreateSurface(int width, int height) 21 { 22 return new Surface(width, height); 23 } 24 25 public bool Decode(ref H264PictureInfo pictureInfo, ISurface output, ReadOnlySpan<byte> bitstream) 26 { 27 Surface outSurf = (Surface)output; 28 29 if (outSurf.RequestedWidth != _oldOutputWidth || 30 outSurf.RequestedHeight != _oldOutputHeight) 31 { 32 _context.Dispose(); 33 _context = new FFmpegContext(AVCodecID.AV_CODEC_ID_H264); 34 35 _oldOutputWidth = outSurf.RequestedWidth; 36 _oldOutputHeight = outSurf.RequestedHeight; 37 } 38 39 Span<byte> bs = Prepend(bitstream, SpsAndPpsReconstruction.Reconstruct(ref pictureInfo, _workBuffer)); 40 41 return _context.DecodeFrame(outSurf, bs) == 0; 42 } 43 44 private static byte[] Prepend(ReadOnlySpan<byte> data, ReadOnlySpan<byte> prep) 45 { 46 byte[] output = new byte[data.Length + prep.Length]; 47 48 prep.CopyTo(output); 49 data.CopyTo(new Span<byte>(output)[prep.Length..]); 50 51 return output; 52 } 53 54 public void Dispose() => _context.Dispose(); 55 } 56 }