| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- using Ryujinx.Common.Memory;
- using Ryujinx.Graphics.Nvdec.Vp9.Common;
- using Ryujinx.Graphics.Nvdec.Vp9.Types;
- using Ryujinx.Graphics.Video;
- using System;
- using Vp9MvRef = Ryujinx.Graphics.Video.Vp9MvRef;
- namespace Ryujinx.Graphics.Nvdec.Vp9
- {
- public sealed class Decoder : IVp9Decoder
- {
- public bool IsHardwareAccelerated => false;
- private readonly MemoryAllocator _allocator = new MemoryAllocator();
- public ISurface CreateSurface(int width, int height) => new Surface(width, height);
- private static ReadOnlySpan<byte> LiteralToFilter => new byte[]
- {
- Constants.EightTapSmooth,
- Constants.EightTap,
- Constants.EightTapSharp,
- Constants.Bilinear
- };
- public unsafe bool Decode(
- ref Vp9PictureInfo pictureInfo,
- ISurface output,
- ReadOnlySpan<byte> bitstream,
- ReadOnlySpan<Vp9MvRef> mvsIn,
- Span<Vp9MvRef> mvsOut)
- {
- Vp9Common cm = new Vp9Common();
- cm.FrameType = pictureInfo.IsKeyFrame ? FrameType.KeyFrame : FrameType.InterFrame;
- cm.IntraOnly = pictureInfo.IntraOnly;
- cm.Width = output.Width;
- cm.Height = output.Height;
- cm.SubsamplingX = 1;
- cm.SubsamplingY = 1;
- cm.UsePrevFrameMvs = pictureInfo.UsePrevInFindMvRefs;
- cm.RefFrameSignBias = pictureInfo.RefFrameSignBias;
- cm.BaseQindex = pictureInfo.BaseQIndex;
- cm.YDcDeltaQ = pictureInfo.YDcDeltaQ;
- cm.UvAcDeltaQ = pictureInfo.UvAcDeltaQ;
- cm.UvDcDeltaQ = pictureInfo.UvDcDeltaQ;
- cm.Mb.Lossless = pictureInfo.Lossless;
- cm.Mb.Bd = 8;
- cm.TxMode = (TxMode)pictureInfo.TransformMode;
- cm.AllowHighPrecisionMv = pictureInfo.AllowHighPrecisionMv;
- cm.InterpFilter = (byte)pictureInfo.InterpFilter;
- if (cm.InterpFilter != Constants.Switchable)
- {
- cm.InterpFilter = LiteralToFilter[cm.InterpFilter];
- }
- cm.ReferenceMode = (ReferenceMode)pictureInfo.ReferenceMode;
- cm.CompFixedRef = pictureInfo.CompFixedRef;
- cm.CompVarRef = pictureInfo.CompVarRef;
- cm.Log2TileCols = pictureInfo.Log2TileCols;
- cm.Log2TileRows = pictureInfo.Log2TileRows;
- cm.Seg.Enabled = pictureInfo.SegmentEnabled;
- cm.Seg.UpdateMap = pictureInfo.SegmentMapUpdate;
- cm.Seg.TemporalUpdate = pictureInfo.SegmentMapTemporalUpdate;
- cm.Seg.AbsDelta = (byte)pictureInfo.SegmentAbsDelta;
- cm.Seg.FeatureMask = pictureInfo.SegmentFeatureEnable;
- cm.Seg.FeatureData = pictureInfo.SegmentFeatureData;
- cm.Lf.ModeRefDeltaEnabled = pictureInfo.ModeRefDeltaEnabled;
- cm.Lf.RefDeltas = pictureInfo.RefDeltas;
- cm.Lf.ModeDeltas = pictureInfo.ModeDeltas;
- cm.Fc = new Ptr<Vp9EntropyProbs>(ref pictureInfo.Entropy);
- cm.Counts = new Ptr<Vp9BackwardUpdates>(ref pictureInfo.BackwardUpdateCounts);
- cm.FrameRefs[0].Buf = (Surface)pictureInfo.LastReference;
- cm.FrameRefs[1].Buf = (Surface)pictureInfo.GoldenReference;
- cm.FrameRefs[2].Buf = (Surface)pictureInfo.AltReference;
- cm.Mb.CurBuf = (Surface)output;
- cm.Mb.SetupBlockPlanes(1, 1);
- int tileCols = 1 << pictureInfo.Log2TileCols;
- int tileRows = 1 << pictureInfo.Log2TileRows;
- // Video usually have only 4 columns, so more threads won't make a difference for those.
- // Try to not take all CPU cores for video decoding.
- int maxThreads = Math.Min(4, Environment.ProcessorCount / 2);
- cm.AllocTileWorkerData(_allocator, tileCols, tileRows, maxThreads);
- cm.AllocContextBuffers(_allocator, output.Width, output.Height);
- cm.InitContextBuffers();
- cm.SetupSegmentationDequant();
- cm.SetupScaleFactors();
- SetMvs(ref cm, mvsIn);
- fixed (byte* dataPtr = bitstream)
- {
- try
- {
- if (maxThreads > 1 && tileRows == 1 && tileCols > 1)
- {
- DecodeFrame.DecodeTilesMt(ref cm, new ArrayPtr<byte>(dataPtr, bitstream.Length), maxThreads);
- }
- else
- {
- DecodeFrame.DecodeTiles(ref cm, new ArrayPtr<byte>(dataPtr, bitstream.Length));
- }
- }
- catch (InternalErrorException)
- {
- return false;
- }
- }
- GetMvs(ref cm, mvsOut);
- cm.FreeTileWorkerData(_allocator);
- cm.FreeContextBuffers(_allocator);
- return true;
- }
- private static void SetMvs(ref Vp9Common cm, ReadOnlySpan<Vp9MvRef> mvs)
- {
- if (mvs.Length > cm.PrevFrameMvs.Length)
- {
- throw new ArgumentException($"Size mismatch, expected: {cm.PrevFrameMvs.Length}, but got: {mvs.Length}.");
- }
- for (int i = 0; i < mvs.Length; i++)
- {
- ref var mv = ref cm.PrevFrameMvs[i];
- mv.Mv[0].Row = mvs[i].Mvs[0].Row;
- mv.Mv[0].Col = mvs[i].Mvs[0].Col;
- mv.Mv[1].Row = mvs[i].Mvs[1].Row;
- mv.Mv[1].Col = mvs[i].Mvs[1].Col;
- mv.RefFrame[0] = (sbyte)mvs[i].RefFrames[0];
- mv.RefFrame[1] = (sbyte)mvs[i].RefFrames[1];
- }
- }
- private static void GetMvs(ref Vp9Common cm, Span<Vp9MvRef> mvs)
- {
- if (mvs.Length > cm.CurFrameMvs.Length)
- {
- throw new ArgumentException($"Size mismatch, expected: {cm.CurFrameMvs.Length}, but got: {mvs.Length}.");
- }
- for (int i = 0; i < mvs.Length; i++)
- {
- ref var mv = ref cm.CurFrameMvs[i];
- mvs[i].Mvs[0].Row = mv.Mv[0].Row;
- mvs[i].Mvs[0].Col = mv.Mv[0].Col;
- mvs[i].Mvs[1].Row = mv.Mv[1].Row;
- mvs[i].Mvs[1].Col = mv.Mv[1].Col;
- mvs[i].RefFrames[0] = mv.RefFrame[0];
- mvs[i].RefFrames[1] = mv.RefFrame[1];
- }
- }
- public void Dispose() => _allocator.Dispose();
- }
- }
|