Decoder.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. using Ryujinx.Common.Memory;
  2. using Ryujinx.Graphics.Nvdec.Vp9.Common;
  3. using Ryujinx.Graphics.Nvdec.Vp9.Types;
  4. using Ryujinx.Graphics.Video;
  5. using System;
  6. using Vp9MvRef = Ryujinx.Graphics.Video.Vp9MvRef;
  7. namespace Ryujinx.Graphics.Nvdec.Vp9
  8. {
  9. public class Decoder : IVp9Decoder
  10. {
  11. public bool IsHardwareAccelerated => false;
  12. private readonly MemoryAllocator _allocator = new MemoryAllocator();
  13. public ISurface CreateSurface(int width, int height) => new Surface(width, height);
  14. private static readonly byte[] LiteralToFilter = new byte[]
  15. {
  16. Constants.EightTapSmooth,
  17. Constants.EightTap,
  18. Constants.EightTapSharp,
  19. Constants.Bilinear
  20. };
  21. public unsafe bool Decode(
  22. ref Vp9PictureInfo pictureInfo,
  23. ISurface output,
  24. ReadOnlySpan<byte> bitstream,
  25. ReadOnlySpan<Vp9MvRef> mvsIn,
  26. Span<Vp9MvRef> mvsOut)
  27. {
  28. Vp9Common cm = new Vp9Common();
  29. cm.FrameType = pictureInfo.IsKeyFrame ? FrameType.KeyFrame : FrameType.InterFrame;
  30. cm.IntraOnly = pictureInfo.IntraOnly;
  31. cm.Width = output.Width;
  32. cm.Height = output.Height;
  33. cm.UsePrevFrameMvs = pictureInfo.UsePrevInFindMvRefs;
  34. cm.RefFrameSignBias = pictureInfo.RefFrameSignBias;
  35. cm.BaseQindex = pictureInfo.BaseQIndex;
  36. cm.YDcDeltaQ = pictureInfo.YDcDeltaQ;
  37. cm.UvAcDeltaQ = pictureInfo.UvAcDeltaQ;
  38. cm.UvDcDeltaQ = pictureInfo.UvDcDeltaQ;
  39. cm.Mb.Lossless = pictureInfo.Lossless;
  40. cm.TxMode = (TxMode)pictureInfo.TransformMode;
  41. cm.AllowHighPrecisionMv = pictureInfo.AllowHighPrecisionMv;
  42. cm.InterpFilter = (byte)pictureInfo.InterpFilter;
  43. if (cm.InterpFilter != Constants.Switchable)
  44. {
  45. cm.InterpFilter = LiteralToFilter[cm.InterpFilter];
  46. }
  47. cm.ReferenceMode = (ReferenceMode)pictureInfo.ReferenceMode;
  48. cm.CompFixedRef = pictureInfo.CompFixedRef;
  49. cm.CompVarRef = pictureInfo.CompVarRef;
  50. cm.Log2TileCols = pictureInfo.Log2TileCols;
  51. cm.Log2TileRows = pictureInfo.Log2TileRows;
  52. cm.Seg.Enabled = pictureInfo.SegmentEnabled;
  53. cm.Seg.UpdateMap = pictureInfo.SegmentMapUpdate;
  54. cm.Seg.TemporalUpdate = pictureInfo.SegmentMapTemporalUpdate;
  55. cm.Seg.AbsDelta = (byte)pictureInfo.SegmentAbsDelta;
  56. cm.Seg.FeatureMask = pictureInfo.SegmentFeatureEnable;
  57. cm.Seg.FeatureData = pictureInfo.SegmentFeatureData;
  58. cm.Lf.ModeRefDeltaEnabled = pictureInfo.ModeRefDeltaEnabled;
  59. cm.Lf.RefDeltas = pictureInfo.RefDeltas;
  60. cm.Lf.ModeDeltas = pictureInfo.ModeDeltas;
  61. cm.Fc = new Ptr<Vp9EntropyProbs>(ref pictureInfo.Entropy);
  62. cm.Counts = new Ptr<Vp9BackwardUpdates>(ref pictureInfo.BackwardUpdateCounts);
  63. cm.FrameRefs[0].Buf = (Surface)pictureInfo.LastReference;
  64. cm.FrameRefs[1].Buf = (Surface)pictureInfo.GoldenReference;
  65. cm.FrameRefs[2].Buf = (Surface)pictureInfo.AltReference;
  66. cm.Mb.CurBuf = (Surface)output;
  67. cm.Mb.SetupBlockPlanes(1, 1);
  68. cm.AllocTileWorkerData(_allocator, 1 << pictureInfo.Log2TileCols, 1 << pictureInfo.Log2TileRows);
  69. cm.AllocContextBuffers(_allocator, output.Width, output.Height);
  70. cm.InitContextBuffers();
  71. cm.SetupSegmentationDequant();
  72. cm.SetupScaleFactors();
  73. SetMvs(ref cm, mvsIn);
  74. fixed (byte* dataPtr = bitstream)
  75. {
  76. try
  77. {
  78. DecodeFrame.DecodeTiles(ref cm, new ArrayPtr<byte>(dataPtr, bitstream.Length));
  79. }
  80. catch (InternalErrorException)
  81. {
  82. return false;
  83. }
  84. }
  85. GetMvs(ref cm, mvsOut);
  86. cm.FreeTileWorkerData(_allocator);
  87. cm.FreeContextBuffers(_allocator);
  88. return true;
  89. }
  90. private static void SetMvs(ref Vp9Common cm, ReadOnlySpan<Vp9MvRef> mvs)
  91. {
  92. if (mvs.Length > cm.PrevFrameMvs.Length)
  93. {
  94. throw new ArgumentException($"Size mismatch, expected: {cm.PrevFrameMvs.Length}, but got: {mvs.Length}.");
  95. }
  96. for (int i = 0; i < mvs.Length; i++)
  97. {
  98. ref var mv = ref cm.PrevFrameMvs[i];
  99. mv.Mv[0].Row = mvs[i].Mvs[0].Row;
  100. mv.Mv[0].Col = mvs[i].Mvs[0].Col;
  101. mv.Mv[1].Row = mvs[i].Mvs[1].Row;
  102. mv.Mv[1].Col = mvs[i].Mvs[1].Col;
  103. mv.RefFrame[0] = (sbyte)mvs[i].RefFrames[0];
  104. mv.RefFrame[1] = (sbyte)mvs[i].RefFrames[1];
  105. }
  106. }
  107. private static void GetMvs(ref Vp9Common cm, Span<Vp9MvRef> mvs)
  108. {
  109. if (mvs.Length > cm.CurFrameMvs.Length)
  110. {
  111. throw new ArgumentException($"Size mismatch, expected: {cm.CurFrameMvs.Length}, but got: {mvs.Length}.");
  112. }
  113. for (int i = 0; i < mvs.Length; i++)
  114. {
  115. ref var mv = ref cm.CurFrameMvs[i];
  116. mvs[i].Mvs[0].Row = mv.Mv[0].Row;
  117. mvs[i].Mvs[0].Col = mv.Mv[0].Col;
  118. mvs[i].Mvs[1].Row = mv.Mv[1].Row;
  119. mvs[i].Mvs[1].Col = mv.Mv[1].Col;
  120. mvs[i].RefFrames[0] = mv.RefFrame[0];
  121. mvs[i].RefFrames[1] = mv.RefFrame[1];
  122. }
  123. }
  124. public void Dispose() => _allocator.Dispose();
  125. }
  126. }