Decoder.cs 1.6 KB

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