forked from Mirror/Ryujinx
4d02a2d2c0
* Initial NVDEC and VIC implementation * Update FFmpeg.AutoGen to 4.3.0 * Add nvdec dependencies for Windows * Unify some VP9 structures * Rename VP9 structure fields * Improvements to Video API * XML docs for Common.Memory * Remove now unused or redundant overloads from MemoryAccessor * NVDEC UV surface read/write scalar paths * Add FIXME comments about hacky things/stuff that will need to be fixed in the future * Cleaned up VP9 memory allocation * Remove some debug logs * Rename some VP9 structs * Remove unused struct * No need to compile Ryujinx.Graphics.Host1x with unsafe anymore * Name AsyncWorkQueue threads to make debugging easier * Make Vp9PictureInfo a ref struct * LayoutConverter no longer needs the depth argument (broken by rebase) * Pooling of VP9 buffers, plus fix a memory leak on VP9 * Really wish VS could rename projects properly... * Address feedback * Remove using * Catch OperationCanceledException * Add licensing informations * Add THIRDPARTY.md to release too Co-authored-by: Thog <me@thog.eu>
179 lines
6.3 KiB
C#
179 lines
6.3 KiB
C#
using Ryujinx.Common.Memory;
|
|
using Ryujinx.Graphics.Video;
|
|
|
|
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|
{
|
|
internal struct MacroBlockD
|
|
{
|
|
public Array3<MacroBlockDPlane> Plane;
|
|
public byte BmodeBlocksWl;
|
|
public byte BmodeBlocksHl;
|
|
|
|
public Ptr<Vp9BackwardUpdates> Counts;
|
|
public TileInfo Tile;
|
|
|
|
public int MiStride;
|
|
|
|
// Grid of 8x8 cells is placed over the block.
|
|
// If some of them belong to the same mbtree-block
|
|
// they will just have same mi[i][j] value
|
|
public ArrayPtr<Ptr<ModeInfo>> Mi;
|
|
public Ptr<ModeInfo> LeftMi;
|
|
public Ptr<ModeInfo> AboveMi;
|
|
|
|
public uint MaxBlocksWide;
|
|
public uint MaxBlocksHigh;
|
|
|
|
public ArrayPtr<Array3<byte>> PartitionProbs;
|
|
|
|
/* Distance of MB away from frame edges */
|
|
public int MbToLeftEdge;
|
|
public int MbToRightEdge;
|
|
public int MbToTopEdge;
|
|
public int MbToBottomEdge;
|
|
|
|
public Ptr<Vp9EntropyProbs> Fc;
|
|
|
|
/* pointers to reference frames */
|
|
public Array2<Ptr<RefBuffer>> BlockRefs;
|
|
|
|
/* pointer to current frame */
|
|
public Surface CurBuf;
|
|
|
|
public Array3<ArrayPtr<sbyte>> AboveContext;
|
|
public Array3<Array16<sbyte>> LeftContext;
|
|
|
|
public ArrayPtr<sbyte> AboveSegContext;
|
|
public Array8<sbyte> LeftSegContext;
|
|
|
|
/* Bit depth: 8, 10, 12 */
|
|
public int Bd;
|
|
|
|
public bool Lossless;
|
|
public bool Corrupted;
|
|
|
|
public Ptr<InternalErrorInfo> ErrorInfo;
|
|
|
|
public int GetPredContextSegId()
|
|
{
|
|
sbyte aboveSip = !AboveMi.IsNull ? AboveMi.Value.SegIdPredicted : (sbyte)0;
|
|
sbyte leftSip = !LeftMi.IsNull ? LeftMi.Value.SegIdPredicted : (sbyte)0;
|
|
|
|
return aboveSip + leftSip;
|
|
}
|
|
|
|
public int GetSkipContext()
|
|
{
|
|
int aboveSkip = !AboveMi.IsNull ? AboveMi.Value.Skip : 0;
|
|
int leftSkip = !LeftMi.IsNull ? LeftMi.Value.Skip : 0;
|
|
return aboveSkip + leftSkip;
|
|
}
|
|
|
|
public int GetPredContextSwitchableInterp()
|
|
{
|
|
// Note:
|
|
// The mode info data structure has a one element border above and to the
|
|
// left of the entries corresponding to real macroblocks.
|
|
// The prediction flags in these dummy entries are initialized to 0.
|
|
int leftType = !LeftMi.IsNull ? LeftMi.Value.InterpFilter : Constants.SwitchableFilters;
|
|
int aboveType = !AboveMi.IsNull ? AboveMi.Value.InterpFilter : Constants.SwitchableFilters;
|
|
|
|
if (leftType == aboveType)
|
|
{
|
|
return leftType;
|
|
}
|
|
else if (leftType == Constants.SwitchableFilters)
|
|
{
|
|
return aboveType;
|
|
}
|
|
else if (aboveType == Constants.SwitchableFilters)
|
|
{
|
|
return leftType;
|
|
}
|
|
else
|
|
{
|
|
return Constants.SwitchableFilters;
|
|
}
|
|
}
|
|
|
|
// The mode info data structure has a one element border above and to the
|
|
// left of the entries corresponding to real macroblocks.
|
|
// The prediction flags in these dummy entries are initialized to 0.
|
|
// 0 - inter/inter, inter/--, --/inter, --/--
|
|
// 1 - intra/inter, inter/intra
|
|
// 2 - intra/--, --/intra
|
|
// 3 - intra/intra
|
|
public int GetIntraInterContext()
|
|
{
|
|
if (!AboveMi.IsNull && !LeftMi.IsNull)
|
|
{ // Both edges available
|
|
bool aboveIntra = !AboveMi.Value.IsInterBlock();
|
|
bool leftIntra = !LeftMi.Value.IsInterBlock();
|
|
return leftIntra && aboveIntra ? 3 : (leftIntra || aboveIntra ? 1 : 0);
|
|
}
|
|
else if (!AboveMi.IsNull || !LeftMi.IsNull)
|
|
{ // One edge available
|
|
return 2 * (!(!AboveMi.IsNull ? AboveMi.Value : LeftMi.Value).IsInterBlock() ? 1 : 0);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// Returns a context number for the given MB prediction signal
|
|
// The mode info data structure has a one element border above and to the
|
|
// left of the entries corresponding to real blocks.
|
|
// The prediction flags in these dummy entries are initialized to 0.
|
|
public int GetTxSizeContext()
|
|
{
|
|
int maxTxSize = (int)Luts.MaxTxSizeLookup[(int)Mi[0].Value.SbType];
|
|
int aboveCtx = (!AboveMi.IsNull && AboveMi.Value.Skip == 0) ? (int)AboveMi.Value.TxSize : maxTxSize;
|
|
int leftCtx = (!LeftMi.IsNull && LeftMi.Value.Skip == 0) ? (int)LeftMi.Value.TxSize : maxTxSize;
|
|
if (LeftMi.IsNull)
|
|
{
|
|
leftCtx = aboveCtx;
|
|
}
|
|
|
|
if (AboveMi.IsNull)
|
|
{
|
|
aboveCtx = leftCtx;
|
|
}
|
|
|
|
return (aboveCtx + leftCtx) > maxTxSize ? 1 : 0;
|
|
}
|
|
|
|
public void SetupBlockPlanes(int ssX, int ssY)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < Constants.MaxMbPlane; i++)
|
|
{
|
|
Plane[i].SubsamplingX = i != 0 ? ssX : 0;
|
|
Plane[i].SubsamplingY = i != 0 ? ssY : 0;
|
|
}
|
|
}
|
|
|
|
public void SetSkipContext(int miRow, int miCol)
|
|
{
|
|
int aboveIdx = miCol * 2;
|
|
int leftIdx = (miRow * 2) & 15;
|
|
int i;
|
|
for (i = 0; i < Constants.MaxMbPlane; ++i)
|
|
{
|
|
ref MacroBlockDPlane pd = ref Plane[i];
|
|
pd.AboveContext = AboveContext[i].Slice(aboveIdx >> pd.SubsamplingX);
|
|
pd.LeftContext = new ArrayPtr<sbyte>(ref LeftContext[i][leftIdx >> pd.SubsamplingY], 16 - (leftIdx >> pd.SubsamplingY));
|
|
}
|
|
}
|
|
|
|
internal void SetMiRowCol(ref TileInfo tile, int miRow, int bh, int miCol, int bw, int miRows, int miCols)
|
|
{
|
|
MbToTopEdge = -((miRow * Constants.MiSize) * 8);
|
|
MbToBottomEdge = ((miRows - bh - miRow) * Constants.MiSize) * 8;
|
|
MbToLeftEdge = -((miCol * Constants.MiSize) * 8);
|
|
MbToRightEdge = ((miCols - bw - miCol) * Constants.MiSize) * 8;
|
|
|
|
// Are edges available for intra prediction?
|
|
AboveMi = (miRow != 0) ? Mi[-MiStride] : Ptr<ModeInfo>.Null;
|
|
LeftMi = (miCol > tile.MiColStart) ? Mi[-1] : Ptr<ModeInfo>.Null;
|
|
}
|
|
}
|
|
}
|