Decoder.cs 1.7 KB

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