| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331 |
- using Ryujinx.Common.Memory;
- using Ryujinx.Graphics.Nvdec.Vp9.Common;
- using Ryujinx.Graphics.Video;
- namespace Ryujinx.Graphics.Nvdec.Vp9.Types
- {
- internal struct Vp9Common
- {
- public MacroBlockD Mb;
- public ArrayPtr<TileWorkerData> TileWorkerData;
- public InternalErrorInfo Error;
- public int Width;
- public int Height;
- public int SubsamplingX;
- public int SubsamplingY;
- public ArrayPtr<MvRef> PrevFrameMvs;
- public ArrayPtr<MvRef> CurFrameMvs;
- public Array3<RefBuffer> FrameRefs;
- public FrameType FrameType;
- // Flag signaling that the frame is encoded using only Intra modes.
- public bool IntraOnly;
- public bool AllowHighPrecisionMv;
- // MBs, MbRows/Cols is in 16-pixel units; MiRows/Cols is in
- // ModeInfo (8-pixel) units.
- public int MBs;
- public int MbRows, MiRows;
- public int MbCols, MiCols;
- public int MiStride;
- /* Profile settings */
- public TxMode TxMode;
- public int BaseQindex;
- public int YDcDeltaQ;
- public int UvDcDeltaQ;
- public int UvAcDeltaQ;
- public Array8<Array2<short>> YDequant;
- public Array8<Array2<short>> UvDequant;
- /* We allocate a ModeInfo struct for each macroblock, together with
- an extra row on top and column on the left to simplify prediction. */
- public ArrayPtr<ModeInfo> Mip; /* Base of allocated array */
- public ArrayPtr<ModeInfo> Mi; /* Corresponds to upper left visible macroblock */
- public ArrayPtr<Ptr<ModeInfo>> MiGridBase;
- public ArrayPtr<Ptr<ModeInfo>> MiGridVisible;
- // Whether to use previous frame's motion vectors for prediction.
- public bool UsePrevFrameMvs;
- // Persistent mb segment id map used in prediction.
- public int SegMapIdx;
- public int PrevSegMapIdx;
- public Array2<ArrayPtr<byte>> SegMapArray;
- public ArrayPtr<byte> LastFrameSegMap;
- public ArrayPtr<byte> CurrentFrameSegMap;
- public byte InterpFilter;
- public LoopFilterInfoN LfInfo;
- public Array4<sbyte> RefFrameSignBias; /* Two state 0, 1 */
- public LoopFilter Lf;
- public Segmentation Seg;
- // Context probabilities for reference frame prediction
- public sbyte CompFixedRef;
- public Array2<sbyte> CompVarRef;
- public ReferenceMode ReferenceMode;
- public Ptr<Vp9EntropyProbs> Fc;
- public Ptr<Vp9BackwardUpdates> Counts;
- public int Log2TileCols, Log2TileRows;
- public ArrayPtr<sbyte> AboveSegContext;
- public ArrayPtr<sbyte> AboveContext;
- public bool FrameIsIntraOnly()
- {
- return FrameType == FrameType.KeyFrame || IntraOnly;
- }
- public bool CompoundReferenceAllowed()
- {
- int i;
- for (i = 1; i < Constants.RefsPerFrame; ++i)
- {
- if (RefFrameSignBias[i + 1] != RefFrameSignBias[1])
- {
- return true;
- }
- }
- return false;
- }
- private static int CalcMiSize(int len)
- {
- // Len is in mi units.
- return len + Constants.MiBlockSize;
- }
- public void SetMbMi(int width, int height)
- {
- int alignedWidth = BitUtils.AlignPowerOfTwo(width, Constants.MiSizeLog2);
- int alignedHeight = BitUtils.AlignPowerOfTwo(height, Constants.MiSizeLog2);
- MiCols = alignedWidth >> Constants.MiSizeLog2;
- MiRows = alignedHeight >> Constants.MiSizeLog2;
- MiStride = CalcMiSize(MiCols);
- MbCols = (MiCols + 1) >> 1;
- MbRows = (MiRows + 1) >> 1;
- MBs = MbRows * MbCols;
- }
- public void AllocTileWorkerData(MemoryAllocator allocator, int tileCols, int tileRows, int maxThreads)
- {
- TileWorkerData = allocator.Allocate<TileWorkerData>(tileCols * tileRows + (maxThreads > 1 ? maxThreads : 0));
- }
- public void FreeTileWorkerData(MemoryAllocator allocator)
- {
- allocator.Free(TileWorkerData);
- }
- private void AllocSegMap(MemoryAllocator allocator, int segMapSize)
- {
- int i;
- for (i = 0; i < Constants.NumPingPongBuffers; ++i)
- {
- SegMapArray[i] = allocator.Allocate<byte>(segMapSize);
- }
- // Init the index.
- SegMapIdx = 0;
- PrevSegMapIdx = 1;
- CurrentFrameSegMap = SegMapArray[SegMapIdx];
- LastFrameSegMap = SegMapArray[PrevSegMapIdx];
- }
- private void FreeSegMap(MemoryAllocator allocator)
- {
- int i;
- for (i = 0; i < Constants.NumPingPongBuffers; ++i)
- {
- allocator.Free(SegMapArray[i]);
- SegMapArray[i] = ArrayPtr<byte>.Null;
- }
- CurrentFrameSegMap = ArrayPtr<byte>.Null;
- LastFrameSegMap = ArrayPtr<byte>.Null;
- }
- private void DecAllocMi(MemoryAllocator allocator, int miSize)
- {
- Mip = allocator.Allocate<ModeInfo>(miSize);
- MiGridBase = allocator.Allocate<Ptr<ModeInfo>>(miSize);
- }
- private void DecFreeMi(MemoryAllocator allocator)
- {
- allocator.Free(Mip);
- Mip = ArrayPtr<ModeInfo>.Null;
- allocator.Free(MiGridBase);
- MiGridBase = ArrayPtr<Ptr<ModeInfo>>.Null;
- }
- public void FreeContextBuffers(MemoryAllocator allocator)
- {
- DecFreeMi(allocator);
- FreeSegMap(allocator);
- allocator.Free(AboveContext);
- AboveContext = ArrayPtr<sbyte>.Null;
- allocator.Free(AboveSegContext);
- AboveSegContext = ArrayPtr<sbyte>.Null;
- allocator.Free(Lf.Lfm);
- Lf.Lfm = ArrayPtr<LoopFilterMask>.Null;
- allocator.Free(CurFrameMvs);
- CurFrameMvs = ArrayPtr<MvRef>.Null;
- if (UsePrevFrameMvs)
- {
- allocator.Free(PrevFrameMvs);
- PrevFrameMvs = ArrayPtr<MvRef>.Null;
- }
- }
- private void AllocLoopFilter(MemoryAllocator allocator)
- {
- // Each lfm holds bit masks for all the 8x8 blocks in a 64x64 region. The
- // stride and rows are rounded up / truncated to a multiple of 8.
- Lf.LfmStride = (MiCols + (Constants.MiBlockSize - 1)) >> 3;
- Lf.Lfm = allocator.Allocate<LoopFilterMask>(((MiRows + (Constants.MiBlockSize - 1)) >> 3) * Lf.LfmStride);
- }
- public void AllocContextBuffers(MemoryAllocator allocator, int width, int height)
- {
- SetMbMi(width, height);
- int newMiSize = MiStride * CalcMiSize(MiRows);
- if (newMiSize != 0)
- {
- DecAllocMi(allocator, newMiSize);
- }
- if (MiRows * MiCols != 0)
- {
- // Create the segmentation map structure and set to 0.
- AllocSegMap(allocator, MiRows * MiCols);
- }
- if (MiCols != 0)
- {
- AboveContext = allocator.Allocate<sbyte>(2 * TileInfo.MiColsAlignedToSb(MiCols) * Constants.MaxMbPlane);
- AboveSegContext = allocator.Allocate<sbyte>(TileInfo.MiColsAlignedToSb(MiCols));
- }
- AllocLoopFilter(allocator);
- CurFrameMvs = allocator.Allocate<MvRef>(MiRows * MiCols);
- // Using the same size as the current frame is fine here,
- // as this is never true when we have a resolution change.
- if (UsePrevFrameMvs)
- {
- PrevFrameMvs = allocator.Allocate<MvRef>(MiRows * MiCols);
- }
- }
- private unsafe void DecSetupMi()
- {
- Mi = Mip.Slice(MiStride + 1);
- MiGridVisible = MiGridBase.Slice(MiStride + 1);
- MemoryUtil.Fill(MiGridBase.ToPointer(), Ptr<ModeInfo>.Null, MiStride * (MiRows + 1));
- }
- public unsafe void InitContextBuffers()
- {
- DecSetupMi();
- if (!LastFrameSegMap.IsNull)
- {
- MemoryUtil.Fill(LastFrameSegMap.ToPointer(), (byte)0, MiRows * MiCols);
- }
- }
- private void SetPartitionProbs(ref MacroBlockD xd)
- {
- xd.PartitionProbs = FrameIsIntraOnly()
- ? new ArrayPtr<Array3<byte>>(ref Fc.Value.KfPartitionProb[0], 16)
- : new ArrayPtr<Array3<byte>>(ref Fc.Value.PartitionProb[0], 16);
- }
- internal void InitMacroBlockD(ref MacroBlockD xd, ArrayPtr<int> dqcoeff)
- {
- int i;
- for (i = 0; i < Constants.MaxMbPlane; ++i)
- {
- xd.Plane[i].DqCoeff = dqcoeff;
- xd.AboveContext[i] = AboveContext.Slice(i * 2 * TileInfo.MiColsAlignedToSb(MiCols));
- if (i == 0)
- {
- MemoryUtil.Copy(ref xd.Plane[i].SegDequant, ref YDequant);
- }
- else
- {
- MemoryUtil.Copy(ref xd.Plane[i].SegDequant, ref UvDequant);
- }
- xd.Fc = new Ptr<Vp9EntropyProbs>(ref Fc.Value);
- }
- xd.AboveSegContext = AboveSegContext;
- xd.MiStride = MiStride;
- xd.ErrorInfo = new Ptr<InternalErrorInfo>(ref Error);
- SetPartitionProbs(ref xd);
- }
- public void SetupSegmentationDequant()
- {
- const BitDepth bitDepth = BitDepth.Bits8; // TODO: Configurable
- // Build y/uv dequant values based on segmentation.
- if (Seg.Enabled)
- {
- int i;
- for (i = 0; i < Constants.MaxSegments; ++i)
- {
- int qIndex = QuantCommon.GetQIndex(ref Seg, i, BaseQindex);
- YDequant[i][0] = QuantCommon.DcQuant(qIndex, YDcDeltaQ, bitDepth);
- YDequant[i][1] = QuantCommon.AcQuant(qIndex, 0, bitDepth);
- UvDequant[i][0] = QuantCommon.DcQuant(qIndex, UvDcDeltaQ, bitDepth);
- UvDequant[i][1] = QuantCommon.AcQuant(qIndex, UvAcDeltaQ, bitDepth);
- }
- }
- else
- {
- int qIndex = BaseQindex;
- // When segmentation is disabled, only the first value is used. The
- // remaining are don't cares.
- YDequant[0][0] = QuantCommon.DcQuant(qIndex, YDcDeltaQ, bitDepth);
- YDequant[0][1] = QuantCommon.AcQuant(qIndex, 0, bitDepth);
- UvDequant[0][0] = QuantCommon.DcQuant(qIndex, UvDcDeltaQ, bitDepth);
- UvDequant[0][1] = QuantCommon.AcQuant(qIndex, UvAcDeltaQ, bitDepth);
- }
- }
- public void SetupScaleFactors()
- {
- for (int i = 0; i < Constants.RefsPerFrame; ++i)
- {
- ref RefBuffer refBuf = ref FrameRefs[i];
- refBuf.Sf.SetupScaleFactorsForFrame(refBuf.Buf.Width, refBuf.Buf.Height, Width, Height);
- }
- }
- }
- }
|