mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2025-01-15 15:10:33 +00:00
Implement VP9 loop filtering
This commit is contained in:
parent
a73a5d7e85
commit
34a583e045
79 changed files with 10926 additions and 2595 deletions
|
@ -2,8 +2,13 @@
|
||||||
{
|
{
|
||||||
internal enum BitDepth
|
internal enum BitDepth
|
||||||
{
|
{
|
||||||
Bits8 = 8, /**< 8 bits */
|
// 8 bits
|
||||||
Bits10 = 10, /**< 10 bits */
|
Bits8 = 8,
|
||||||
Bits12 = 12, /**< 12 bits */
|
|
||||||
|
// 10 bits
|
||||||
|
Bits10 = 10,
|
||||||
|
|
||||||
|
// 12 bits
|
||||||
|
Bits12 = 12
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,26 +3,26 @@
|
||||||
internal enum CodecErr
|
internal enum CodecErr
|
||||||
{
|
{
|
||||||
/*!\brief Operation completed without error */
|
/*!\brief Operation completed without error */
|
||||||
CodecOk,
|
Ok,
|
||||||
|
|
||||||
/*!\brief Unspecified error */
|
/*!\brief Unspecified error */
|
||||||
CodecError,
|
Error,
|
||||||
|
|
||||||
/*!\brief Memory operation failed */
|
/*!\brief Memory operation failed */
|
||||||
CodecMemError,
|
MemError,
|
||||||
|
|
||||||
/*!\brief ABI version mismatch */
|
/*!\brief ABI version mismatch */
|
||||||
CodecAbiMismatch,
|
AbiMismatch,
|
||||||
|
|
||||||
/*!\brief Algorithm does not have required capability */
|
/*!\brief Algorithm does not have required capability */
|
||||||
CodecIncapable,
|
Incapable,
|
||||||
|
|
||||||
/*!\brief The given bitstream is not supported.
|
/*!\brief The given bitstream is not supported.
|
||||||
*
|
*
|
||||||
* The bitstream was unable to be parsed at the highest level. The decoder
|
* The bitstream was unable to be parsed at the highest level. The decoder
|
||||||
* is unable to proceed. This error \ref SHOULD be treated as fatal to the
|
* is unable to proceed. This error \ref SHOULD be treated as fatal to the
|
||||||
* stream. */
|
* stream. */
|
||||||
CodecUnsupBitstream,
|
UnsupBitstream,
|
||||||
|
|
||||||
/*!\brief Encoded bitstream uses an unsupported feature
|
/*!\brief Encoded bitstream uses an unsupported feature
|
||||||
*
|
*
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
* pictures from being properly decoded. This error \ref MAY be treated as
|
* pictures from being properly decoded. This error \ref MAY be treated as
|
||||||
* fatal to the stream or \ref MAY be treated as fatal to the current GOP.
|
* fatal to the stream or \ref MAY be treated as fatal to the current GOP.
|
||||||
*/
|
*/
|
||||||
CodecUnsupFeature,
|
UnsupFeature,
|
||||||
|
|
||||||
/*!\brief The coded data for this stream is corrupt or incomplete
|
/*!\brief The coded data for this stream is corrupt or incomplete
|
||||||
*
|
*
|
||||||
|
@ -41,16 +41,16 @@
|
||||||
* stream or \ref MAY be treated as fatal to the current GOP. If decoding
|
* stream or \ref MAY be treated as fatal to the current GOP. If decoding
|
||||||
* is continued for the current GOP, artifacts may be present.
|
* is continued for the current GOP, artifacts may be present.
|
||||||
*/
|
*/
|
||||||
CodecCorruptFrame,
|
CorruptFrame,
|
||||||
|
|
||||||
/*!\brief An application-supplied parameter is not valid.
|
/*!\brief An application-supplied parameter is not valid.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
CodecInvalidParam,
|
InvalidParam,
|
||||||
|
|
||||||
/*!\brief An iterator reached the end of list.
|
/*!\brief An iterator reached the end of list.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
CodecListEnd
|
ListEnd
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -10,7 +10,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static byte ClipPixel(int val)
|
public static byte ClipPixel(int val)
|
||||||
{
|
{
|
||||||
return (byte)((val > 255) ? 255 : (val < 0) ? 0 : val);
|
return (byte)(val > 255 ? 255 : val < 0 ? 0 : val);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
|
||||||
public bool InUse;
|
public bool InUse;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PoolItem[] _pool = new PoolItem[PoolEntries];
|
private readonly PoolItem[] _pool = new PoolItem[PoolEntries];
|
||||||
|
|
||||||
public ArrayPtr<T> Allocate<T>(int length) where T : unmanaged
|
public ArrayPtr<T> Allocate<T>(int length) where T : unmanaged
|
||||||
{
|
{
|
||||||
|
@ -51,6 +51,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
|
||||||
{
|
{
|
||||||
Marshal.FreeHGlobal(item.Pointer);
|
Marshal.FreeHGlobal(item.Pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
item.Pointer = ptr;
|
item.Pointer = ptr;
|
||||||
item.Length = lengthInBytes;
|
item.Length = lengthInBytes;
|
||||||
break;
|
break;
|
||||||
|
@ -58,7 +59,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ArrayPtr<T>(ptr, length);
|
ArrayPtr<T> allocation = new ArrayPtr<T>(ptr, length);
|
||||||
|
|
||||||
|
allocation.AsSpan().Fill(default);
|
||||||
|
|
||||||
|
return allocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe void Free<T>(ArrayPtr<T> arr) where T : unmanaged
|
public unsafe void Free<T>(ArrayPtr<T> arr) where T : unmanaged
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
namespace Ryujinx.Graphics.Nvdec.Vp9
|
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
internal static class Constants
|
internal static class Constants
|
||||||
{
|
{
|
||||||
public const int Vp9InterpExtend = 4;
|
public const int InterpExtend = 4;
|
||||||
|
|
||||||
public const int MaxMbPlane = 3;
|
public const int MaxMbPlane = 3;
|
||||||
|
|
||||||
|
@ -25,6 +27,7 @@
|
||||||
/* Segment Feature Masks */
|
/* Segment Feature Masks */
|
||||||
public const int MaxMvRefCandidates = 2;
|
public const int MaxMvRefCandidates = 2;
|
||||||
|
|
||||||
|
public const int IntraInterContexts = 4;
|
||||||
public const int CompInterContexts = 5;
|
public const int CompInterContexts = 5;
|
||||||
public const int RefContexts = 5;
|
public const int RefContexts = 5;
|
||||||
|
|
||||||
|
@ -32,12 +35,26 @@
|
||||||
public const int EightTapSmooth = 1;
|
public const int EightTapSmooth = 1;
|
||||||
public const int EightTapSharp = 2;
|
public const int EightTapSharp = 2;
|
||||||
public const int SwitchableFilters = 3; /* Number of switchable filters */
|
public const int SwitchableFilters = 3; /* Number of switchable filters */
|
||||||
|
|
||||||
public const int Bilinear = 3;
|
public const int Bilinear = 3;
|
||||||
public const int Switchable = 4; /* should be the last one */
|
|
||||||
|
// The codec can operate in four possible inter prediction filter mode:
|
||||||
|
// 8-tap, 8-tap-smooth, 8-tap-sharp, and switching between the three.
|
||||||
|
public const int SwitchableFilterContexts = SwitchableFilters + 1;
|
||||||
|
public const int Switchable = 4; /* Should be the last one */
|
||||||
|
|
||||||
// Frame
|
// Frame
|
||||||
public const int RefsPerFrame = 3;
|
public const int RefsPerFrame = 3;
|
||||||
|
|
||||||
|
public const int RefFramesLog2 = 3;
|
||||||
|
public const int RefFrames = 1 << RefFramesLog2;
|
||||||
|
|
||||||
|
// 1 scratch frame for the new frame, 3 for scaled references on the encoder.
|
||||||
|
public const int FrameBuffers = RefFrames + 4;
|
||||||
|
|
||||||
|
public const int FrameContextsLog2 = 2;
|
||||||
|
public const int FrameContexts = 1 << FrameContextsLog2;
|
||||||
|
|
||||||
public const int NumPingPongBuffers = 2;
|
public const int NumPingPongBuffers = 2;
|
||||||
|
|
||||||
public const int Class0Bits = 1; /* bits at integer precision for class 0 */
|
public const int Class0Bits = 1; /* bits at integer precision for class 0 */
|
||||||
|
@ -65,5 +82,19 @@
|
||||||
|
|
||||||
public const int SegmentAbsData = 1;
|
public const int SegmentAbsData = 1;
|
||||||
public const int MaxSegments = 8;
|
public const int MaxSegments = 8;
|
||||||
|
|
||||||
|
public const int PartitionTypes = (int)PartitionType.PartitionTypes;
|
||||||
|
|
||||||
|
public const int PartitionPlOffset = 4; // Number of probability models per block size
|
||||||
|
public const int PartitionContexts = 4 * PartitionPlOffset;
|
||||||
|
|
||||||
|
public const int PlaneTypes = (int)PlaneType.PlaneTypes;
|
||||||
|
|
||||||
|
public const int IntraModes = (int)PredictionMode.TmPred + 1;
|
||||||
|
|
||||||
|
public const int InterModes = 1 + (int)PredictionMode.NewMv - (int)PredictionMode.NearestMv;
|
||||||
|
|
||||||
|
public const int SkipContexts = 3;
|
||||||
|
public const int InterModeContexts = 7;
|
||||||
}
|
}
|
||||||
}
|
}
|
47
src/Ryujinx.Graphics.Nvdec.Vp9/DSubExp.cs
Normal file
47
src/Ryujinx.Graphics.Nvdec.Vp9/DSubExp.cs
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
{
|
||||||
|
internal static class DSubExp
|
||||||
|
{
|
||||||
|
public static int InvRecenterNonneg(int v, int m)
|
||||||
|
{
|
||||||
|
if (v > 2 * m)
|
||||||
|
{
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (v & 1) != 0 ? m - ((v + 1) >> 1) : m + (v >> 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly byte[] InvMapTable =
|
||||||
|
{
|
||||||
|
7, 20, 33, 46, 59, 72, 85, 98, 111, 124, 137, 150, 163, 176, 189, 202, 215, 228, 241, 254, 1, 2, 3, 4,
|
||||||
|
5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 34,
|
||||||
|
35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60, 61, 62,
|
||||||
|
63, 64, 65, 66, 67, 68, 69, 70, 71, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 86, 87, 88, 89, 90,
|
||||||
|
91, 92, 93, 94, 95, 96, 97, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 112, 113, 114,
|
||||||
|
115, 116, 117, 118, 119, 120, 121, 122, 123, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136,
|
||||||
|
138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 151, 152, 153, 154, 155, 156, 157, 158, 159,
|
||||||
|
160, 161, 162, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 177, 178, 179, 180, 181, 182,
|
||||||
|
183, 184, 185, 186, 187, 188, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 203, 204, 205,
|
||||||
|
206, 207, 208, 209, 210, 211, 212, 213, 214, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227,
|
||||||
|
229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 242, 243, 244, 245, 246, 247, 248, 249, 250,
|
||||||
|
251, 252, 253, 253
|
||||||
|
};
|
||||||
|
|
||||||
|
public static int InvRemapProb(int v, int m)
|
||||||
|
{
|
||||||
|
Debug.Assert(v < InvMapTable.Length / sizeof(byte));
|
||||||
|
|
||||||
|
v = InvMapTable[v];
|
||||||
|
m--;
|
||||||
|
if (m << 1 <= Prob.MaxProb)
|
||||||
|
{
|
||||||
|
return 1 + InvRecenterNonneg(v, m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Prob.MaxProb - InvRecenterNonneg(v, Prob.MaxProb - 1 - m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load diff
|
@ -5,18 +5,16 @@ using Ryujinx.Graphics.Video;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using Mv = Ryujinx.Graphics.Nvdec.Vp9.Types.Mv;
|
|
||||||
using MvRef = Ryujinx.Graphics.Nvdec.Vp9.Types.MvRef;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Nvdec.Vp9
|
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
internal static class DecodeMv
|
internal static class DecodeMv
|
||||||
{
|
{
|
||||||
private const int MvrefNeighbours = 8;
|
private const int RefNeighbours = 8;
|
||||||
|
|
||||||
private static PredictionMode ReadIntraMode(ref Reader r, ReadOnlySpan<byte> p)
|
private static PredictionMode ReadIntraMode(ref Reader r, ReadOnlySpan<byte> p)
|
||||||
{
|
{
|
||||||
return (PredictionMode)r.ReadTree(Luts.Vp9IntraModeTree, p);
|
return (PredictionMode)r.ReadTree(Luts.IntraModeTree, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PredictionMode ReadIntraModeY(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, int sizeGroup)
|
private static PredictionMode ReadIntraModeY(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, int sizeGroup)
|
||||||
|
@ -43,7 +41,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
|
||||||
private static PredictionMode ReadInterMode(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, int ctx)
|
private static PredictionMode ReadInterMode(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, int ctx)
|
||||||
{
|
{
|
||||||
int mode = r.ReadTree(Luts.Vp9InterModeTree, cm.Fc.Value.InterModeProb[ctx].AsSpan());
|
int mode = r.ReadTree(Luts.InterModeTree, cm.Fc.Value.InterModeProb[ctx].AsSpan());
|
||||||
if (!xd.Counts.IsNull)
|
if (!xd.Counts.IsNull)
|
||||||
{
|
{
|
||||||
++xd.Counts.Value.InterMode[ctx][mode];
|
++xd.Counts.Value.InterMode[ctx][mode];
|
||||||
|
@ -54,7 +52,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
|
||||||
private static int ReadSegmentId(ref Reader r, ref Array7<byte> segTreeProbs)
|
private static int ReadSegmentId(ref Reader r, ref Array7<byte> segTreeProbs)
|
||||||
{
|
{
|
||||||
return r.ReadTree(Luts.Vp9SegmentTree, segTreeProbs.AsSpan());
|
return r.ReadTree(Luts.SegmentTree, segTreeProbs.AsSpan());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ReadOnlySpan<byte> GetTxProbs(ref Vp9EntropyProbs fc, TxSize maxTxSize, int ctx)
|
private static ReadOnlySpan<byte> GetTxProbs(ref Vp9EntropyProbs fc, TxSize maxTxSize, int ctx)
|
||||||
|
@ -64,7 +62,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
case TxSize.Tx8x8: return fc.Tx8x8Prob[ctx].AsSpan();
|
case TxSize.Tx8x8: return fc.Tx8x8Prob[ctx].AsSpan();
|
||||||
case TxSize.Tx16x16: return fc.Tx16x16Prob[ctx].AsSpan();
|
case TxSize.Tx16x16: return fc.Tx16x16Prob[ctx].AsSpan();
|
||||||
case TxSize.Tx32x32: return fc.Tx32x32Prob[ctx].AsSpan();
|
case TxSize.Tx32x32: return fc.Tx32x32Prob[ctx].AsSpan();
|
||||||
default: Debug.Assert(false, "Invalid maxTxSize."); return ReadOnlySpan<byte>.Empty;
|
default:
|
||||||
|
Debug.Assert(false, "Invalid maxTxSize.");
|
||||||
|
return ReadOnlySpan<byte>.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +75,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
case TxSize.Tx8x8: return counts.Tx8x8[ctx].AsSpan();
|
case TxSize.Tx8x8: return counts.Tx8x8[ctx].AsSpan();
|
||||||
case TxSize.Tx16x16: return counts.Tx16x16[ctx].AsSpan();
|
case TxSize.Tx16x16: return counts.Tx16x16[ctx].AsSpan();
|
||||||
case TxSize.Tx32x32: return counts.Tx32x32[ctx].AsSpan();
|
case TxSize.Tx32x32: return counts.Tx32x32[ctx].AsSpan();
|
||||||
default: Debug.Assert(false, "Invalid maxTxSize."); return Span<uint>.Empty;
|
default:
|
||||||
|
Debug.Assert(false, "Invalid maxTxSize.");
|
||||||
|
return Span<uint>.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,21 +112,20 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
return ReadSelectedTxSize(ref cm, ref xd, maxTxSize, ref r);
|
return ReadSelectedTxSize(ref cm, ref xd, maxTxSize, ref r);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
return (TxSize)Math.Min((int)maxTxSize, (int)Luts.TxModeToBiggestTxSize[(int)txMode]);
|
return (TxSize)Math.Min((int)maxTxSize, (int)Luts.TxModeToBiggestTxSize[(int)txMode]);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static int DecGetSegmentId(ref Vp9Common cm, ArrayPtr<byte> segmentIds, int miOffset, int xMis, int yMis)
|
private static int DecGetSegmentId(ref Vp9Common cm, ArrayPtr<byte> segmentIds, int miOffset, int xMis,
|
||||||
|
int yMis)
|
||||||
{
|
{
|
||||||
int x, y, segmentId = int.MaxValue;
|
int segmentId = int.MaxValue;
|
||||||
|
|
||||||
for (y = 0; y < yMis; y++)
|
for (int y = 0; y < yMis; y++)
|
||||||
{
|
{
|
||||||
for (x = 0; x < xMis; x++)
|
for (int x = 0; x < xMis; x++)
|
||||||
{
|
{
|
||||||
segmentId = Math.Min(segmentId, segmentIds[miOffset + y * cm.MiCols + x]);
|
segmentId = Math.Min(segmentId, segmentIds[miOffset + (y * cm.MiCols) + x]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,15 +135,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
|
||||||
private static void SetSegmentId(ref Vp9Common cm, int miOffset, int xMis, int yMis, int segmentId)
|
private static void SetSegmentId(ref Vp9Common cm, int miOffset, int xMis, int yMis, int segmentId)
|
||||||
{
|
{
|
||||||
int x, y;
|
|
||||||
|
|
||||||
Debug.Assert(segmentId >= 0 && segmentId < Constants.MaxSegments);
|
Debug.Assert(segmentId >= 0 && segmentId < Constants.MaxSegments);
|
||||||
|
|
||||||
for (y = 0; y < yMis; y++)
|
for (int y = 0; y < yMis; y++)
|
||||||
{
|
{
|
||||||
for (x = 0; x < xMis; x++)
|
for (int x = 0; x < xMis; x++)
|
||||||
{
|
{
|
||||||
cm.CurrentFrameSegMap[miOffset + y * cm.MiCols + x] = (byte)segmentId;
|
cm.CurrentFrameSegMap[miOffset + (y * cm.MiCols) + x] = (byte)segmentId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,13 +154,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
int xMis,
|
int xMis,
|
||||||
int yMis)
|
int yMis)
|
||||||
{
|
{
|
||||||
int x, y;
|
for (int y = 0; y < yMis; y++)
|
||||||
|
|
||||||
for (y = 0; y < yMis; y++)
|
|
||||||
{
|
{
|
||||||
for (x = 0; x < xMis; x++)
|
for (int x = 0; x < xMis; x++)
|
||||||
{
|
{
|
||||||
currentSegmentIds[miOffset + y * cm.MiCols + x] = (byte)(!lastSegmentIds.IsNull ? lastSegmentIds[miOffset + y * cm.MiCols + x] : 0);
|
currentSegmentIds[miOffset + (y * cm.MiCols) + x] = (byte)(!lastSegmentIds.IsNull
|
||||||
|
? lastSegmentIds[miOffset + (y * cm.MiCols) + x]
|
||||||
|
: 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -199,7 +198,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
ref Segmentation seg = ref cm.Seg;
|
ref Segmentation seg = ref cm.Seg;
|
||||||
ref ModeInfo mi = ref xd.Mi[0].Value;
|
ref ModeInfo mi = ref xd.Mi[0].Value;
|
||||||
int predictedSegmentId, segmentId;
|
int predictedSegmentId, segmentId;
|
||||||
int miOffset = miRow * cm.MiCols + miCol;
|
int miOffset = (miRow * cm.MiCols) + miCol;
|
||||||
|
|
||||||
if (!seg.Enabled)
|
if (!seg.Enabled)
|
||||||
{
|
{
|
||||||
|
@ -220,24 +219,26 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
byte predProb = Segmentation.GetPredProbSegId(ref cm.Fc.Value.SegPredProb, ref xd);
|
byte predProb = Segmentation.GetPredProbSegId(ref cm.Fc.Value.SegPredProb, ref xd);
|
||||||
mi.SegIdPredicted = (sbyte)r.Read(predProb);
|
mi.SegIdPredicted = (sbyte)r.Read(predProb);
|
||||||
segmentId = mi.SegIdPredicted != 0 ? predictedSegmentId : ReadSegmentId(ref r, ref cm.Fc.Value.SegTreeProb);
|
segmentId = mi.SegIdPredicted != 0
|
||||||
|
? predictedSegmentId
|
||||||
|
: ReadSegmentId(ref r, ref cm.Fc.Value.SegTreeProb);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
segmentId = ReadSegmentId(ref r, ref cm.Fc.Value.SegTreeProb);
|
segmentId = ReadSegmentId(ref r, ref cm.Fc.Value.SegTreeProb);
|
||||||
}
|
}
|
||||||
|
|
||||||
SetSegmentId(ref cm, miOffset, xMis, yMis, segmentId);
|
SetSegmentId(ref cm, miOffset, xMis, yMis, segmentId);
|
||||||
return segmentId;
|
return segmentId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int ReadSkip(ref Vp9Common cm, ref MacroBlockD xd, int segmentId, ref Reader r)
|
private static int ReadSkip(ref Vp9Common cm, ref MacroBlockD xd, int segmentId, ref Reader r)
|
||||||
{
|
{
|
||||||
if (cm.Seg.IsSegFeatureActive(segmentId, SegLvlFeatures.SegLvlSkip) != 0)
|
if (cm.Seg.IsSegFeatureActive(segmentId, SegLvlFeatures.Skip) != 0)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
int ctx = xd.GetSkipContext();
|
int ctx = xd.GetSkipContext();
|
||||||
int skip = r.Read(cm.Fc.Value.SkipProb[ctx]);
|
int skip = r.Read(cm.Fc.Value.SkipProb[ctx]);
|
||||||
if (!xd.Counts.IsNull)
|
if (!xd.Counts.IsNull)
|
||||||
|
@ -247,14 +248,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
|
||||||
return skip;
|
return skip;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static int ReadMvComponent(ref Reader r, ref Vp9EntropyProbs fc, int mvcomp, bool usehp)
|
private static int ReadComponent(ref Reader r, ref Vp9EntropyProbs fc, int mvcomp, bool usehp)
|
||||||
{
|
{
|
||||||
int mag, d, fr, hp;
|
int mag, d, fr, hp;
|
||||||
bool sign = r.Read(fc.Sign[mvcomp]) != 0;
|
bool sign = r.Read(fc.Sign[mvcomp]) != 0;
|
||||||
MvClassType mvClass = (MvClassType)r.ReadTree(Luts.Vp9MvClassTree, fc.Classes[mvcomp].AsSpan());
|
MvClassType mvClass = (MvClassType)r.ReadTree(Luts.MvClassTree, fc.Classes[mvcomp].AsSpan());
|
||||||
bool class0 = mvClass == MvClassType.MvClass0;
|
bool class0 = mvClass == MvClassType.Class0;
|
||||||
|
|
||||||
// Integer part
|
// Integer part
|
||||||
if (class0)
|
if (class0)
|
||||||
|
@ -264,11 +264,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
int n = (int)mvClass + Constants.Class0Bits - 1; // Number of bits
|
int n = (int)mvClass + Constants.Class0Bits - 1; // Number of bits
|
||||||
|
|
||||||
d = 0;
|
d = 0;
|
||||||
for (i = 0; i < n; ++i)
|
for (int i = 0; i < n; ++i)
|
||||||
{
|
{
|
||||||
d |= r.Read(fc.Bits[mvcomp][i]) << i;
|
d |= r.Read(fc.Bits[mvcomp][i]) << i;
|
||||||
}
|
}
|
||||||
|
@ -277,7 +276,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fractional part
|
// Fractional part
|
||||||
fr = r.ReadTree(Luts.Vp9MvFPTree, class0 ? fc.Class0Fp[mvcomp][d].AsSpan() : fc.Fp[mvcomp].AsSpan());
|
fr = r.ReadTree(Luts.MvFPTree, class0 ? fc.Class0Fp[mvcomp][d].AsSpan() : fc.Fp[mvcomp].AsSpan());
|
||||||
|
|
||||||
// High precision part (if hp is not used, the default value of the hp is 1)
|
// High precision part (if hp is not used, the default value of the hp is 1)
|
||||||
hp = usehp ? r.Read(class0 ? fc.Class0Hp[mvcomp] : fc.Hp[mvcomp]) : 1;
|
hp = usehp ? r.Read(class0 ? fc.Class0Hp[mvcomp] : fc.Hp[mvcomp]) : 1;
|
||||||
|
@ -287,29 +286,29 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
return sign ? -mag : mag;
|
return sign ? -mag : mag;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ReadMv(
|
private static void Read(
|
||||||
ref Reader r,
|
ref Reader r,
|
||||||
ref Mv mv,
|
ref Mv mv,
|
||||||
ref Mv refr,
|
ref Mv refr,
|
||||||
ref Vp9EntropyProbs fc,
|
ref Vp9EntropyProbs fc,
|
||||||
Ptr<Vp9BackwardUpdates> counts,
|
Ptr<Vp9BackwardUpdates> counts,
|
||||||
bool allowHP)
|
bool allowHp)
|
||||||
{
|
{
|
||||||
MvJointType jointType = (MvJointType)r.ReadTree(Luts.Vp9MvJointTree, fc.Joints.AsSpan());
|
MvJointType jointType = (MvJointType)r.ReadTree(Luts.MvJointTree, fc.Joints.AsSpan());
|
||||||
bool useHP = allowHP && refr.UseMvHp();
|
bool useHp = allowHp && refr.UseHp();
|
||||||
Mv diff = new Mv();
|
Mv diff = new();
|
||||||
|
|
||||||
if (Mv.MvJointVertical(jointType))
|
if (Mv.JointVertical(jointType))
|
||||||
{
|
{
|
||||||
diff.Row = (short)ReadMvComponent(ref r, ref fc, 0, useHP);
|
diff.Row = (short)ReadComponent(ref r, ref fc, 0, useHp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Mv.MvJointHorizontal(jointType))
|
if (Mv.JointHorizontal(jointType))
|
||||||
{
|
{
|
||||||
diff.Col = (short)ReadMvComponent(ref r, ref fc, 1, useHP);
|
diff.Col = (short)ReadComponent(ref r, ref fc, 1, useHp);
|
||||||
}
|
}
|
||||||
|
|
||||||
diff.IncMv(counts);
|
diff.Inc(counts);
|
||||||
|
|
||||||
mv.Row = (short)(refr.Row + diff.Row);
|
mv.Row = (short)(refr.Row + diff.Row);
|
||||||
mv.Col = (short)(refr.Col + diff.Col);
|
mv.Col = (short)(refr.Col + diff.Col);
|
||||||
|
@ -317,7 +316,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
|
||||||
private static ReferenceMode ReadBlockReferenceMode(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r)
|
private static ReferenceMode ReadBlockReferenceMode(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r)
|
||||||
{
|
{
|
||||||
if (cm.ReferenceMode == ReferenceMode.ReferenceModeSelect)
|
if (cm.ReferenceMode == ReferenceMode.Select)
|
||||||
{
|
{
|
||||||
int ctx = PredCommon.GetReferenceModeContext(ref cm, ref xd);
|
int ctx = PredCommon.GetReferenceModeContext(ref cm, ref xd);
|
||||||
ReferenceMode mode = (ReferenceMode)r.Read(cm.Fc.Value.CompInterProb[ctx]);
|
ReferenceMode mode = (ReferenceMode)r.Read(cm.Fc.Value.CompInterProb[ctx]);
|
||||||
|
@ -328,11 +327,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
|
||||||
return mode; // SingleReference or CompoundReference
|
return mode; // SingleReference or CompoundReference
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
return cm.ReferenceMode;
|
return cm.ReferenceMode;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Read the referncence frame
|
// Read the referncence frame
|
||||||
private static void ReadRefFrames(
|
private static void ReadRefFrames(
|
||||||
|
@ -344,15 +341,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
ref Vp9EntropyProbs fc = ref cm.Fc.Value;
|
ref Vp9EntropyProbs fc = ref cm.Fc.Value;
|
||||||
|
|
||||||
if (cm.Seg.IsSegFeatureActive(segmentId, SegLvlFeatures.SegLvlRefFrame) != 0)
|
if (cm.Seg.IsSegFeatureActive(segmentId, SegLvlFeatures.RefFrame) != 0)
|
||||||
{
|
{
|
||||||
refFrame[0] = (sbyte)cm.Seg.GetSegData(segmentId, SegLvlFeatures.SegLvlRefFrame);
|
refFrame[0] = (sbyte)cm.Seg.GetSegData(segmentId, SegLvlFeatures.RefFrame);
|
||||||
refFrame[1] = Constants.None;
|
refFrame[1] = Constants.None;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ReferenceMode mode = ReadBlockReferenceMode(ref cm, ref xd, ref r);
|
ReferenceMode mode = ReadBlockReferenceMode(ref cm, ref xd, ref r);
|
||||||
if (mode == ReferenceMode.CompoundReference)
|
if (mode == ReferenceMode.Compound)
|
||||||
{
|
{
|
||||||
int idx = cm.RefFrameSignBias[cm.CompFixedRef];
|
int idx = cm.RefFrameSignBias[cm.CompFixedRef];
|
||||||
int ctx = PredCommon.GetPredContextCompRefP(ref cm, ref xd);
|
int ctx = PredCommon.GetPredContextCompRefP(ref cm, ref xd);
|
||||||
|
@ -365,7 +362,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
refFrame[idx] = cm.CompFixedRef;
|
refFrame[idx] = cm.CompFixedRef;
|
||||||
refFrame[idx == 0 ? 1 : 0] = cm.CompVarRef[bit];
|
refFrame[idx == 0 ? 1 : 0] = cm.CompVarRef[bit];
|
||||||
}
|
}
|
||||||
else if (mode == ReferenceMode.SingleReference)
|
else if (mode == ReferenceMode.Single)
|
||||||
{
|
{
|
||||||
int ctx0 = PredCommon.GetPredContextSingleRefP1(ref xd);
|
int ctx0 = PredCommon.GetPredContextSingleRefP1(ref xd);
|
||||||
int bit0 = r.Read(fc.SingleRefProb[ctx0][0]);
|
int bit0 = r.Read(fc.SingleRefProb[ctx0][0]);
|
||||||
|
@ -402,7 +399,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
private static byte ReadSwitchableInterpFilter(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r)
|
private static byte ReadSwitchableInterpFilter(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r)
|
||||||
{
|
{
|
||||||
int ctx = xd.GetPredContextSwitchableInterp();
|
int ctx = xd.GetPredContextSwitchableInterp();
|
||||||
byte type = (byte)r.ReadTree(Luts.Vp9SwitchableInterpTree, cm.Fc.Value.SwitchableInterpProb[ctx].AsSpan());
|
byte type = (byte)r.ReadTree(Luts.SwitchableInterpTree, cm.Fc.Value.SwitchableInterpProb[ctx].AsSpan());
|
||||||
if (!xd.Counts.IsNull)
|
if (!xd.Counts.IsNull)
|
||||||
{
|
{
|
||||||
++xd.Counts.Value.SwitchableInterp[ctx][type];
|
++xd.Counts.Value.SwitchableInterp[ctx][type];
|
||||||
|
@ -414,12 +411,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
private static void ReadIntraBlockModeInfo(ref Vp9Common cm, ref MacroBlockD xd, ref ModeInfo mi, ref Reader r)
|
private static void ReadIntraBlockModeInfo(ref Vp9Common cm, ref MacroBlockD xd, ref ModeInfo mi, ref Reader r)
|
||||||
{
|
{
|
||||||
BlockSize bsize = mi.SbType;
|
BlockSize bsize = mi.SbType;
|
||||||
int i;
|
|
||||||
|
|
||||||
switch (bsize)
|
switch (bsize)
|
||||||
{
|
{
|
||||||
case BlockSize.Block4x4:
|
case BlockSize.Block4x4:
|
||||||
for (i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
mi.Bmi[i].Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0);
|
mi.Bmi[i].Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0);
|
||||||
}
|
}
|
||||||
|
@ -434,7 +431,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
mi.Bmi[0].Mode = mi.Bmi[1].Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0);
|
mi.Bmi[0].Mode = mi.Bmi[1].Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0);
|
||||||
mi.Bmi[2].Mode = mi.Bmi[3].Mode = mi.Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0);
|
mi.Bmi[2].Mode = mi.Bmi[3].Mode = mi.Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0);
|
||||||
break;
|
break;
|
||||||
default: mi.Mode = ReadIntraModeY(ref cm, ref xd, ref r, Luts.SizeGroupLookup[(int)bsize]); break;
|
default:
|
||||||
|
mi.Mode = ReadIntraModeY(ref cm, ref xd, ref r, Luts.SizeGroupLookup[(int)bsize]);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
mi.UvMode = ReadIntraModeUv(ref cm, ref xd, ref r, (byte)mi.Mode);
|
mi.UvMode = ReadIntraModeUv(ref cm, ref xd, ref r, (byte)mi.Mode);
|
||||||
|
@ -447,27 +446,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
mi.RefFrame[1] = Constants.None;
|
mi.RefFrame[1] = Constants.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsMvValid(ref Mv mv)
|
private static void CopyPair(ref Array2<Mv> dst, ref Array2<Mv> src)
|
||||||
{
|
|
||||||
return mv.Row > Constants.MvLow &&
|
|
||||||
mv.Row < Constants.MvUpp &&
|
|
||||||
mv.Col > Constants.MvLow &&
|
|
||||||
mv.Col < Constants.MvUpp;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void CopyMvPair(ref Array2<Mv> dst, ref Array2<Mv> src)
|
|
||||||
{
|
{
|
||||||
dst[0] = src[0];
|
dst[0] = src[0];
|
||||||
dst[1] = src[1];
|
dst[1] = src[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ZeroMvPair(ref Array2<Mv> dst)
|
private static void ZeroPair(ref Array2<Mv> dst)
|
||||||
{
|
{
|
||||||
dst[0] = new Mv();
|
dst[0] = new Mv();
|
||||||
dst[1] = new Mv();
|
dst[1] = new Mv();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool AssignMv(
|
private static bool Assign(
|
||||||
ref Vp9Common cm,
|
ref Vp9Common cm,
|
||||||
ref MacroBlockD xd,
|
ref MacroBlockD xd,
|
||||||
PredictionMode mode,
|
PredictionMode mode,
|
||||||
|
@ -475,47 +466,47 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
ref Array2<Mv> refMv,
|
ref Array2<Mv> refMv,
|
||||||
ref Array2<Mv> nearNearestMv,
|
ref Array2<Mv> nearNearestMv,
|
||||||
int isCompound,
|
int isCompound,
|
||||||
bool allowHP,
|
bool allowHp,
|
||||||
ref Reader r)
|
ref Reader r)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
|
|
||||||
switch (mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
case PredictionMode.NewMv:
|
case PredictionMode.NewMv:
|
||||||
{
|
{
|
||||||
for (i = 0; i < 1 + isCompound; ++i)
|
for (int i = 0; i < 1 + isCompound; ++i)
|
||||||
{
|
{
|
||||||
ReadMv(ref r, ref mv[i], ref refMv[i], ref cm.Fc.Value, xd.Counts, allowHP);
|
Read(ref r, ref mv[i], ref refMv[i], ref cm.Fc.Value, xd.Counts, allowHp);
|
||||||
ret = ret && IsMvValid(ref mv[i]);
|
ret = ret && mv[i].IsValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PredictionMode.NearMv:
|
case PredictionMode.NearMv:
|
||||||
case PredictionMode.NearestMv:
|
case PredictionMode.NearestMv:
|
||||||
{
|
{
|
||||||
CopyMvPair(ref mv, ref nearNearestMv);
|
CopyPair(ref mv, ref nearNearestMv);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PredictionMode.ZeroMv:
|
case PredictionMode.ZeroMv:
|
||||||
{
|
{
|
||||||
ZeroMvPair(ref mv);
|
ZeroPair(ref mv);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: return false;
|
default: return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool ReadIsInterBlock(ref Vp9Common cm, ref MacroBlockD xd, int segmentId, ref Reader r)
|
private static bool ReadIsInterBlock(ref Vp9Common cm, ref MacroBlockD xd, int segmentId, ref Reader r)
|
||||||
{
|
{
|
||||||
if (cm.Seg.IsSegFeatureActive(segmentId, SegLvlFeatures.SegLvlRefFrame) != 0)
|
if (cm.Seg.IsSegFeatureActive(segmentId, SegLvlFeatures.RefFrame) != 0)
|
||||||
{
|
{
|
||||||
return cm.Seg.GetSegData(segmentId, SegLvlFeatures.SegLvlRefFrame) != Constants.IntraFrame;
|
return cm.Seg.GetSegData(segmentId, SegLvlFeatures.RefFrame) != Constants.IntraFrame;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
int ctx = xd.GetIntraInterContext();
|
int ctx = xd.GetIntraInterContext();
|
||||||
bool isInter = r.Read(cm.Fc.Value.IntraInterProb[ctx]) != 0;
|
bool isInter = r.Read(cm.Fc.Value.IntraInterProb[ctx]) != 0;
|
||||||
if (!xd.Counts.IsNull)
|
if (!xd.Counts.IsNull)
|
||||||
|
@ -525,34 +516,31 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
|
||||||
return isInter;
|
return isInter;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static void DecFindBestRefMvs(bool allowHP, Span<Mv> mvlist, ref Mv bestMv, int refmvCount)
|
private static void DecFindBestRefs(bool allowHp, Span<Mv> mvlist, ref Mv bestMv, int refmvCount)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
|
|
||||||
// Make sure all the candidates are properly clamped etc
|
// Make sure all the candidates are properly clamped etc
|
||||||
for (i = 0; i < refmvCount; ++i)
|
for (int i = 0; i < refmvCount; ++i)
|
||||||
{
|
{
|
||||||
mvlist[i].LowerMvPrecision(allowHP);
|
mvlist[i].LowerPrecision(allowHp);
|
||||||
bestMv = mvlist[i];
|
bestMv = mvlist[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool AddMvRefListEb(Mv mv, ref int refMvCount, Span<Mv> mvRefList, bool earlyBreak)
|
private static bool AddRefListEb(Mv mv, ref int refCount, Span<Mv> mvRefList, bool earlyBreak)
|
||||||
{
|
{
|
||||||
if (refMvCount != 0)
|
if (refCount != 0)
|
||||||
{
|
{
|
||||||
if (Unsafe.As<Mv, int>(ref mv) != Unsafe.As<Mv, int>(ref mvRefList[0]))
|
if (Unsafe.As<Mv, int>(ref mv) != Unsafe.As<Mv, int>(ref mvRefList[0]))
|
||||||
{
|
{
|
||||||
mvRefList[refMvCount] = mv;
|
mvRefList[refCount] = mv;
|
||||||
refMvCount++;
|
refCount++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mvRefList[refMvCount++] = mv;
|
mvRefList[refCount++] = mv;
|
||||||
if (earlyBreak)
|
if (earlyBreak)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
@ -562,19 +550,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Performs mv sign inversion if indicated by the reference frame combination.
|
private static bool IsDiffRefFrameAddEb(
|
||||||
private static Mv ScaleMv(ref ModeInfo mi, int refr, sbyte thisRefFrame, ref Array4<sbyte> refSignBias)
|
|
||||||
{
|
|
||||||
Mv mv = mi.Mv[refr];
|
|
||||||
if (refSignBias[mi.RefFrame[refr]] != refSignBias[thisRefFrame])
|
|
||||||
{
|
|
||||||
mv.Row *= -1;
|
|
||||||
mv.Col *= -1;
|
|
||||||
}
|
|
||||||
return mv;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsDiffRefFrameAddMvEb(
|
|
||||||
ref ModeInfo mbmi,
|
ref ModeInfo mbmi,
|
||||||
sbyte refFrame,
|
sbyte refFrame,
|
||||||
ref Array4<sbyte> refSignBias,
|
ref Array4<sbyte> refSignBias,
|
||||||
|
@ -586,26 +562,30 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
if (mbmi.RefFrame[0] != refFrame)
|
if (mbmi.RefFrame[0] != refFrame)
|
||||||
{
|
{
|
||||||
if (AddMvRefListEb(ScaleMv(ref mbmi, 0, refFrame, ref refSignBias), ref refmvCount, mvRefList, earlyBreak))
|
if (AddRefListEb(mbmi.ScaleMv(0, refFrame, ref refSignBias), ref refmvCount, mvRefList,
|
||||||
{
|
earlyBreak))
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mbmi.HasSecondRef() && mbmi.RefFrame[1] != refFrame && Unsafe.As<Mv, int>(ref mbmi.Mv[1]) != Unsafe.As<Mv, int>(ref mbmi.Mv[0]))
|
|
||||||
{
|
|
||||||
if (AddMvRefListEb(ScaleMv(ref mbmi, 1, refFrame, ref refSignBias), ref refmvCount, mvRefList, earlyBreak))
|
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mbmi.HasSecondRef() && mbmi.RefFrame[1] != refFrame &&
|
||||||
|
Unsafe.As<Mv, int>(ref mbmi.Mv[1]) != Unsafe.As<Mv, int>(ref mbmi.Mv[0]))
|
||||||
|
{
|
||||||
|
if (AddRefListEb(mbmi.ScaleMv(1, refFrame, ref refSignBias), ref refmvCount, mvRefList,
|
||||||
|
earlyBreak))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function searches the neighborhood of a given MB/SB
|
// This function searches the neighborhood of a given MB/SB
|
||||||
// to try and find candidate reference vectors.
|
// to try and find candidate reference vectors.
|
||||||
private static unsafe int DecFindMvRefs(
|
private static int DecFindRefs(
|
||||||
ref Vp9Common cm,
|
ref Vp9Common cm,
|
||||||
ref MacroBlockD xd,
|
ref MacroBlockD xd,
|
||||||
PredictionMode mode,
|
PredictionMode mode,
|
||||||
|
@ -615,12 +595,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
int miRow,
|
int miRow,
|
||||||
int miCol,
|
int miCol,
|
||||||
int block,
|
int block,
|
||||||
int isSub8X8)
|
int isSub8x8)
|
||||||
{
|
{
|
||||||
ref Array4<sbyte> refSignBias = ref cm.RefFrameSignBias;
|
ref Array4<sbyte> refSignBias = ref cm.RefFrameSignBias;
|
||||||
int i, refmvCount = 0;
|
int i, refmvCount = 0;
|
||||||
bool differentRefFound = false;
|
bool differentRefFound = false;
|
||||||
Ptr<MvRef> prevFrameMvs = cm.UsePrevFrameMvs ? new Ptr<MvRef>(ref cm.PrevFrameMvs[miRow * cm.MiCols + miCol]) : Ptr<MvRef>.Null;
|
Ptr<MvRef> prevFrameMvs = cm.UsePrevFrameMvs
|
||||||
|
? new Ptr<MvRef>(ref cm.PrevFrameMvs[(miRow * cm.MiCols) + miCol])
|
||||||
|
: Ptr<MvRef>.Null;
|
||||||
ref TileInfo tile = ref xd.Tile;
|
ref TileInfo tile = ref xd.Tile;
|
||||||
// If mode is nearestmv or newmv (uses nearestmv as a reference) then stop
|
// If mode is nearestmv or newmv (uses nearestmv as a reference) then stop
|
||||||
// searching after the first mv is found.
|
// searching after the first mv is found.
|
||||||
|
@ -630,7 +612,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
mvRefList.Slice(0, Constants.MaxMvRefCandidates).Fill(new Mv());
|
mvRefList.Slice(0, Constants.MaxMvRefCandidates).Fill(new Mv());
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
if (isSub8X8 != 0)
|
if (isSub8x8 != 0)
|
||||||
{
|
{
|
||||||
// If the size < 8x8 we get the mv from the bmi substructure for the
|
// If the size < 8x8 we get the mv from the bmi substructure for the
|
||||||
// nearest two blocks.
|
// nearest two blocks.
|
||||||
|
@ -639,19 +621,21 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
ref Position mvRef = ref mvRefSearch[i];
|
ref Position mvRef = ref mvRefSearch[i];
|
||||||
if (tile.IsInside(miCol, miRow, cm.MiRows, ref mvRef))
|
if (tile.IsInside(miCol, miRow, cm.MiRows, ref mvRef))
|
||||||
{
|
{
|
||||||
ref ModeInfo candidateMi = ref xd.Mi[mvRef.Col + mvRef.Row * xd.MiStride].Value;
|
ref ModeInfo candidateMi = ref xd.Mi[mvRef.Col + (mvRef.Row * xd.MiStride)].Value;
|
||||||
differentRefFound = true;
|
differentRefFound = true;
|
||||||
|
|
||||||
if (candidateMi.RefFrame[0] == refFrame)
|
if (candidateMi.RefFrame[0] == refFrame)
|
||||||
{
|
{
|
||||||
if (AddMvRefListEb(candidateMi.GetSubBlockMv(0, mvRef.Col, block), ref refmvCount, mvRefList, earlyBreak))
|
if (AddRefListEb(candidateMi.GetSubBlockMv(0, mvRef.Col, block), ref refmvCount,
|
||||||
|
mvRefList, earlyBreak))
|
||||||
{
|
{
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (candidateMi.RefFrame[1] == refFrame)
|
else if (candidateMi.RefFrame[1] == refFrame)
|
||||||
{
|
{
|
||||||
if (AddMvRefListEb(candidateMi.GetSubBlockMv(1, mvRef.Col, block), ref refmvCount, mvRefList, earlyBreak))
|
if (AddRefListEb(candidateMi.GetSubBlockMv(1, mvRef.Col, block), ref refmvCount,
|
||||||
|
mvRefList, earlyBreak))
|
||||||
{
|
{
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
|
@ -663,24 +647,24 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
// Check the rest of the neighbors in much the same way
|
// Check the rest of the neighbors in much the same way
|
||||||
// as before except we don't need to keep track of sub blocks or
|
// as before except we don't need to keep track of sub blocks or
|
||||||
// mode counts.
|
// mode counts.
|
||||||
for (; i < MvrefNeighbours; ++i)
|
for (; i < RefNeighbours; ++i)
|
||||||
{
|
{
|
||||||
ref Position mvRef = ref mvRefSearch[i];
|
ref Position mvRef = ref mvRefSearch[i];
|
||||||
if (tile.IsInside(miCol, miRow, cm.MiRows, ref mvRef))
|
if (tile.IsInside(miCol, miRow, cm.MiRows, ref mvRef))
|
||||||
{
|
{
|
||||||
ref ModeInfo candidate = ref xd.Mi[mvRef.Col + mvRef.Row * xd.MiStride].Value;
|
ref ModeInfo candidate = ref xd.Mi[mvRef.Col + (mvRef.Row * xd.MiStride)].Value;
|
||||||
differentRefFound = true;
|
differentRefFound = true;
|
||||||
|
|
||||||
if (candidate.RefFrame[0] == refFrame)
|
if (candidate.RefFrame[0] == refFrame)
|
||||||
{
|
{
|
||||||
if (AddMvRefListEb(candidate.Mv[0], ref refmvCount, mvRefList, earlyBreak))
|
if (AddRefListEb(candidate.Mv[0], ref refmvCount, mvRefList, earlyBreak))
|
||||||
{
|
{
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (candidate.RefFrame[1] == refFrame)
|
else if (candidate.RefFrame[1] == refFrame)
|
||||||
{
|
{
|
||||||
if (AddMvRefListEb(candidate.Mv[1], ref refmvCount, mvRefList, earlyBreak))
|
if (AddRefListEb(candidate.Mv[1], ref refmvCount, mvRefList, earlyBreak))
|
||||||
{
|
{
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
|
@ -693,14 +677,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
if (prevFrameMvs.Value.RefFrame[0] == refFrame)
|
if (prevFrameMvs.Value.RefFrame[0] == refFrame)
|
||||||
{
|
{
|
||||||
if (AddMvRefListEb(prevFrameMvs.Value.Mv[0], ref refmvCount, mvRefList, earlyBreak))
|
if (AddRefListEb(prevFrameMvs.Value.Mv[0], ref refmvCount, mvRefList, earlyBreak))
|
||||||
{
|
{
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (prevFrameMvs.Value.RefFrame[1] == refFrame)
|
else if (prevFrameMvs.Value.RefFrame[1] == refFrame)
|
||||||
{
|
{
|
||||||
if (AddMvRefListEb(prevFrameMvs.Value.Mv[1], ref refmvCount, mvRefList, earlyBreak))
|
if (AddRefListEb(prevFrameMvs.Value.Mv[1], ref refmvCount, mvRefList, earlyBreak))
|
||||||
{
|
{
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
|
@ -712,15 +696,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
// different reference frames.
|
// different reference frames.
|
||||||
if (differentRefFound)
|
if (differentRefFound)
|
||||||
{
|
{
|
||||||
for (i = 0; i < MvrefNeighbours; ++i)
|
for (i = 0; i < RefNeighbours; ++i)
|
||||||
{
|
{
|
||||||
ref Position mvRef = ref mvRefSearch[i];
|
ref Position mvRef = ref mvRefSearch[i];
|
||||||
if (tile.IsInside(miCol, miRow, cm.MiRows, ref mvRef))
|
if (tile.IsInside(miCol, miRow, cm.MiRows, ref mvRef))
|
||||||
{
|
{
|
||||||
ref ModeInfo candidate = ref xd.Mi[mvRef.Col + mvRef.Row * xd.MiStride].Value;
|
ref ModeInfo candidate = ref xd.Mi[mvRef.Col + (mvRef.Row * xd.MiStride)].Value;
|
||||||
|
|
||||||
// If the candidate is Intra we don't want to consider its mv.
|
// If the candidate is Intra we don't want to consider its mv.
|
||||||
if (IsDiffRefFrameAddMvEb(ref candidate, refFrame, ref refSignBias, ref refmvCount, mvRefList, earlyBreak))
|
if (IsDiffRefFrameAddEb(ref candidate, refFrame, ref refSignBias, ref refmvCount, mvRefList,
|
||||||
|
earlyBreak))
|
||||||
{
|
{
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
|
@ -739,7 +724,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
mv.Row *= -1;
|
mv.Row *= -1;
|
||||||
mv.Col *= -1;
|
mv.Col *= -1;
|
||||||
}
|
}
|
||||||
if (AddMvRefListEb(mv, ref refmvCount, mvRefList, earlyBreak))
|
|
||||||
|
if (AddRefListEb(mv, ref refmvCount, mvRefList, earlyBreak))
|
||||||
{
|
{
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
|
@ -747,7 +733,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
|
||||||
if (prevFrameMvs.Value.RefFrame[1] > Constants.IntraFrame &&
|
if (prevFrameMvs.Value.RefFrame[1] > Constants.IntraFrame &&
|
||||||
prevFrameMvs.Value.RefFrame[1] != refFrame &&
|
prevFrameMvs.Value.RefFrame[1] != refFrame &&
|
||||||
Unsafe.As<Mv, int>(ref prevFrameMvs.Value.Mv[1]) != Unsafe.As<Mv, int>(ref prevFrameMvs.Value.Mv[0]))
|
Unsafe.As<Mv, int>(ref prevFrameMvs.Value.Mv[1]) !=
|
||||||
|
Unsafe.As<Mv, int>(ref prevFrameMvs.Value.Mv[0]))
|
||||||
{
|
{
|
||||||
Mv mv = prevFrameMvs.Value.Mv[1];
|
Mv mv = prevFrameMvs.Value.Mv[1];
|
||||||
if (refSignBias[prevFrameMvs.Value.RefFrame[1]] != refSignBias[refFrame])
|
if (refSignBias[prevFrameMvs.Value.RefFrame[1]] != refSignBias[refFrame])
|
||||||
|
@ -755,7 +742,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
mv.Row *= -1;
|
mv.Row *= -1;
|
||||||
mv.Col *= -1;
|
mv.Col *= -1;
|
||||||
}
|
}
|
||||||
if (AddMvRefListEb(mv, ref refmvCount, mvRefList, earlyBreak))
|
|
||||||
|
if (AddRefListEb(mv, ref refmvCount, mvRefList, earlyBreak))
|
||||||
{
|
{
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
|
@ -776,13 +764,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
// Clamp vectors
|
// Clamp vectors
|
||||||
for (i = 0; i < refmvCount; ++i)
|
for (i = 0; i < refmvCount; ++i)
|
||||||
{
|
{
|
||||||
mvRefList[i].ClampMvRef(ref xd);
|
mvRefList[i].ClampRef(ref xd);
|
||||||
}
|
}
|
||||||
|
|
||||||
return refmvCount;
|
return refmvCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AppendSub8x8MvsForIdx(
|
private static void AppendSub8x8ForIdx(
|
||||||
ref Vp9Common cm,
|
ref Vp9Common cm,
|
||||||
ref MacroBlockD xd,
|
ref MacroBlockD xd,
|
||||||
Span<Position> mvRefSearch,
|
Span<Position> mvRefSearch,
|
||||||
|
@ -796,16 +784,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
Span<Mv> mvList = stackalloc Mv[Constants.MaxMvRefCandidates];
|
Span<Mv> mvList = stackalloc Mv[Constants.MaxMvRefCandidates];
|
||||||
ref ModeInfo mi = ref xd.Mi[0].Value;
|
ref ModeInfo mi = ref xd.Mi[0].Value;
|
||||||
ref Array4<BModeInfo> bmi = ref mi.Bmi;
|
ref Array4<BModeInfo> bmi = ref mi.Bmi;
|
||||||
int n;
|
|
||||||
int refmvCount;
|
int refmvCount;
|
||||||
|
|
||||||
Debug.Assert(Constants.MaxMvRefCandidates == 2);
|
Debug.Assert(Constants.MaxMvRefCandidates == 2);
|
||||||
|
|
||||||
refmvCount = DecFindMvRefs(ref cm, ref xd, bMode, mi.RefFrame[refr], mvRefSearch, mvList, miRow, miCol, block, 1);
|
refmvCount = DecFindRefs(ref cm, ref xd, bMode, mi.RefFrame[refr], mvRefSearch, mvList, miRow, miCol,
|
||||||
|
block, 1);
|
||||||
|
|
||||||
switch (block)
|
switch (block)
|
||||||
{
|
{
|
||||||
case 0: bestSub8x8 = mvList[refmvCount - 1]; break;
|
case 0:
|
||||||
|
bestSub8x8 = mvList[refmvCount - 1];
|
||||||
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
case 2:
|
case 2:
|
||||||
if (bMode == PredictionMode.NearestMv)
|
if (bMode == PredictionMode.NearestMv)
|
||||||
|
@ -815,7 +805,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bestSub8x8 = new Mv();
|
bestSub8x8 = new Mv();
|
||||||
for (n = 0; n < refmvCount; ++n)
|
for (int n = 0; n < refmvCount; ++n)
|
||||||
{
|
{
|
||||||
if (Unsafe.As<Mv, int>(ref bmi[0].Mv[refr]) != Unsafe.As<Mv, int>(ref mvList[n]))
|
if (Unsafe.As<Mv, int>(ref bmi[0].Mv[refr]) != Unsafe.As<Mv, int>(ref mvList[n]))
|
||||||
{
|
{
|
||||||
|
@ -824,6 +814,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if (bMode == PredictionMode.NearestMv)
|
if (bMode == PredictionMode.NearestMv)
|
||||||
|
@ -838,7 +829,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
candidates[2] = mvList[0];
|
candidates[2] = mvList[0];
|
||||||
candidates[3] = mvList[1];
|
candidates[3] = mvList[1];
|
||||||
bestSub8x8 = new Mv();
|
bestSub8x8 = new Mv();
|
||||||
for (n = 0; n < 2 + Constants.MaxMvRefCandidates; ++n)
|
for (int n = 0; n < 2 + Constants.MaxMvRefCandidates; ++n)
|
||||||
{
|
{
|
||||||
if (Unsafe.As<Mv, int>(ref bmi[2].Mv[refr]) != Unsafe.As<Mv, int>(ref candidates[n]))
|
if (Unsafe.As<Mv, int>(ref bmi[2].Mv[refr]) != Unsafe.As<Mv, int>(ref candidates[n]))
|
||||||
{
|
{
|
||||||
|
@ -847,24 +838,27 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Debug.Assert(false, "Invalid block index.");
|
||||||
break;
|
break;
|
||||||
default: Debug.Assert(false, "Invalid block index."); break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte GetModeContext(ref Vp9Common cm, ref MacroBlockD xd, Span<Position> mvRefSearch, int miRow, int miCol)
|
private static byte GetModeContext(ref Vp9Common cm, ref MacroBlockD xd, Span<Position> mvRefSearch, int miRow,
|
||||||
|
int miCol)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
int contextCounter = 0;
|
int contextCounter = 0;
|
||||||
ref TileInfo tile = ref xd.Tile;
|
ref TileInfo tile = ref xd.Tile;
|
||||||
|
|
||||||
// Get mode count from nearest 2 blocks
|
// Get mode count from nearest 2 blocks
|
||||||
for (i = 0; i < 2; ++i)
|
for (int i = 0; i < 2; ++i)
|
||||||
{
|
{
|
||||||
ref Position mvRef = ref mvRefSearch[i];
|
ref Position mvRef = ref mvRefSearch[i];
|
||||||
if (tile.IsInside(miCol, miRow, cm.MiRows, ref mvRef))
|
if (tile.IsInside(miCol, miRow, cm.MiRows, ref mvRef))
|
||||||
{
|
{
|
||||||
ref ModeInfo candidate = ref xd.Mi[mvRef.Col + mvRef.Row * xd.MiStride].Value;
|
ref ModeInfo candidate = ref xd.Mi[mvRef.Col + (mvRef.Row * xd.MiStride)].Value;
|
||||||
// Keep counts for entropy encoding.
|
// Keep counts for entropy encoding.
|
||||||
contextCounter += Luts.Mode2Counter[(int)candidate.Mode];
|
contextCounter += Luts.Mode2Counter[(int)candidate.Mode];
|
||||||
}
|
}
|
||||||
|
@ -882,8 +876,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
ref Reader r)
|
ref Reader r)
|
||||||
{
|
{
|
||||||
BlockSize bsize = mi.SbType;
|
BlockSize bsize = mi.SbType;
|
||||||
bool allowHP = cm.AllowHighPrecisionMv;
|
bool allowHp = cm.AllowHighPrecisionMv;
|
||||||
Array2<Mv> bestRefMvs = new Array2<Mv>();
|
Array2<Mv> bestRefMvs = new();
|
||||||
int refr, isCompound;
|
int refr, isCompound;
|
||||||
byte interModeCtx;
|
byte interModeCtx;
|
||||||
Span<Position> mvRefSearch = Luts.MvRefBlocks[(int)bsize];
|
Span<Position> mvRefSearch = Luts.MvRefBlocks[(int)bsize];
|
||||||
|
@ -892,12 +886,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
isCompound = mi.HasSecondRef() ? 1 : 0;
|
isCompound = mi.HasSecondRef() ? 1 : 0;
|
||||||
interModeCtx = GetModeContext(ref cm, ref xd, mvRefSearch, miRow, miCol);
|
interModeCtx = GetModeContext(ref cm, ref xd, mvRefSearch, miRow, miCol);
|
||||||
|
|
||||||
if (cm.Seg.IsSegFeatureActive(mi.SegmentId, SegLvlFeatures.SegLvlSkip) != 0)
|
if (cm.Seg.IsSegFeatureActive(mi.SegmentId, SegLvlFeatures.Skip) != 0)
|
||||||
{
|
{
|
||||||
mi.Mode = PredictionMode.ZeroMv;
|
mi.Mode = PredictionMode.ZeroMv;
|
||||||
if (bsize < BlockSize.Block8x8)
|
if (bsize < BlockSize.Block8x8)
|
||||||
{
|
{
|
||||||
xd.ErrorInfo.Value.InternalError(CodecErr.CodecUnsupBitstream, "Invalid usage of segement feature on small blocks");
|
xd.ErrorInfo.Value.InternalError(CodecErr.UnsupBitstream,
|
||||||
|
"Invalid usage of segement feature on small blocks");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -925,53 +920,58 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
sbyte frame = mi.RefFrame[refr];
|
sbyte frame = mi.RefFrame[refr];
|
||||||
int refmvCount;
|
int refmvCount;
|
||||||
|
|
||||||
refmvCount = DecFindMvRefs(ref cm, ref xd, mi.Mode, frame, mvRefSearch, tmpMvs, miRow, miCol, -1, 0);
|
refmvCount = DecFindRefs(ref cm, ref xd, mi.Mode, frame, mvRefSearch, tmpMvs, miRow, miCol,
|
||||||
|
-1, 0);
|
||||||
|
|
||||||
DecFindBestRefMvs(allowHP, tmpMvs, ref bestRefMvs[refr], refmvCount);
|
DecFindBestRefs(allowHp, tmpMvs, ref bestRefMvs[refr], refmvCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mi.InterpFilter = (cm.InterpFilter == Constants.Switchable) ? ReadSwitchableInterpFilter(ref cm, ref xd, ref r) : cm.InterpFilter;
|
mi.InterpFilter = cm.InterpFilter == Constants.Switchable
|
||||||
|
? ReadSwitchableInterpFilter(ref cm, ref xd, ref r)
|
||||||
|
: cm.InterpFilter;
|
||||||
|
|
||||||
if (bsize < BlockSize.Block8x8)
|
if (bsize < BlockSize.Block8x8)
|
||||||
{
|
{
|
||||||
int num4X4W = 1 << xd.BmodeBlocksWl;
|
int num4x4W = 1 << xd.BmodeBlocksWl;
|
||||||
int num4X4H = 1 << xd.BmodeBlocksHl;
|
int num4x4H = 1 << xd.BmodeBlocksHl;
|
||||||
int idx, idy;
|
int idx, idy;
|
||||||
PredictionMode bMode = 0;
|
PredictionMode bMode = 0;
|
||||||
Array2<Mv> bestSub8x8 = new Array2<Mv>();
|
Array2<Mv> bestSub8x8 = new();
|
||||||
const uint invalidMv = 0x80008000;
|
const uint invalidMv = 0x80008000;
|
||||||
// Initialize the 2nd element as even though it won't be used meaningfully
|
// Initialize the 2nd element as even though it won't be used meaningfully
|
||||||
// if isCompound is false.
|
// if isCompound is false.
|
||||||
Unsafe.As<Mv, uint>(ref bestSub8x8[1]) = invalidMv;
|
Unsafe.As<Mv, uint>(ref bestSub8x8[1]) = invalidMv;
|
||||||
for (idy = 0; idy < 2; idy += num4X4H)
|
for (idy = 0; idy < 2; idy += num4x4H)
|
||||||
{
|
{
|
||||||
for (idx = 0; idx < 2; idx += num4X4W)
|
for (idx = 0; idx < 2; idx += num4x4W)
|
||||||
{
|
{
|
||||||
int j = idy * 2 + idx;
|
int j = (idy * 2) + idx;
|
||||||
bMode = ReadInterMode(ref cm, ref xd, ref r, interModeCtx);
|
bMode = ReadInterMode(ref cm, ref xd, ref r, interModeCtx);
|
||||||
|
|
||||||
if (bMode == PredictionMode.NearestMv || bMode == PredictionMode.NearMv)
|
if (bMode == PredictionMode.NearestMv || bMode == PredictionMode.NearMv)
|
||||||
{
|
{
|
||||||
for (refr = 0; refr < 1 + isCompound; ++refr)
|
for (refr = 0; refr < 1 + isCompound; ++refr)
|
||||||
{
|
{
|
||||||
AppendSub8x8MvsForIdx(ref cm, ref xd, mvRefSearch, bMode, j, refr, miRow, miCol, ref bestSub8x8[refr]);
|
AppendSub8x8ForIdx(ref cm, ref xd, mvRefSearch, bMode, j, refr, miRow, miCol,
|
||||||
|
ref bestSub8x8[refr]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!AssignMv(ref cm, ref xd, bMode, ref mi.Bmi[j].Mv, ref bestRefMvs, ref bestSub8x8, isCompound, allowHP, ref r))
|
if (!Assign(ref cm, ref xd, bMode, ref mi.Bmi[j].Mv, ref bestRefMvs, ref bestSub8x8,
|
||||||
|
isCompound, allowHp, ref r))
|
||||||
{
|
{
|
||||||
xd.Corrupted |= true;
|
xd.Corrupted |= true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num4X4H == 2)
|
if (num4x4H == 2)
|
||||||
{
|
{
|
||||||
mi.Bmi[j + 2] = mi.Bmi[j];
|
mi.Bmi[j + 2] = mi.Bmi[j];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num4X4W == 2)
|
if (num4x4W == 2)
|
||||||
{
|
{
|
||||||
mi.Bmi[j + 1] = mi.Bmi[j];
|
mi.Bmi[j + 1] = mi.Bmi[j];
|
||||||
}
|
}
|
||||||
|
@ -980,11 +980,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
|
||||||
mi.Mode = bMode;
|
mi.Mode = bMode;
|
||||||
|
|
||||||
CopyMvPair(ref mi.Mv, ref mi.Bmi[3].Mv);
|
CopyPair(ref mi.Mv, ref mi.Bmi[3].Mv);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xd.Corrupted |= !AssignMv(ref cm, ref xd, mi.Mode, ref mi.Mv, ref bestRefMvs, ref bestRefMvs, isCompound, allowHP, ref r);
|
xd.Corrupted |= !Assign(ref cm, ref xd, mi.Mode, ref mi.Mv, ref bestRefMvs, ref bestRefMvs,
|
||||||
|
isCompound, allowHp, ref r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1026,12 +1027,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
|
||||||
return leftMi.Value.GetYMode(b + 1);
|
return leftMi.Value.GetYMode(b + 1);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.Assert(b == 1 || b == 3);
|
Debug.Assert(b == 1 || b == 3);
|
||||||
return curMi.Value.Bmi[b - 1].Mode;
|
return curMi.Value.Bmi[b - 1].Mode;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static PredictionMode AboveBlockMode(Ptr<ModeInfo> curMi, Ptr<ModeInfo> aboveMi, int b)
|
private static PredictionMode AboveBlockMode(Ptr<ModeInfo> curMi, Ptr<ModeInfo> aboveMi, int b)
|
||||||
{
|
{
|
||||||
|
@ -1044,12 +1043,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
|
||||||
return aboveMi.Value.GetYMode(b + 2);
|
return aboveMi.Value.GetYMode(b + 2);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.Assert(b == 2 || b == 3);
|
Debug.Assert(b == 2 || b == 3);
|
||||||
return curMi.Value.Bmi[b - 2].Mode;
|
return curMi.Value.Bmi[b - 2].Mode;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static ReadOnlySpan<byte> GetYModeProbs(
|
private static ReadOnlySpan<byte> GetYModeProbs(
|
||||||
ref Vp9EntropyProbs fc,
|
ref Vp9EntropyProbs fc,
|
||||||
|
@ -1076,8 +1073,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
Ptr<ModeInfo> aboveMi = xd.AboveMi;
|
Ptr<ModeInfo> aboveMi = xd.AboveMi;
|
||||||
Ptr<ModeInfo> leftMi = xd.LeftMi;
|
Ptr<ModeInfo> leftMi = xd.LeftMi;
|
||||||
BlockSize bsize = mi.Value.SbType;
|
BlockSize bsize = mi.Value.SbType;
|
||||||
int i;
|
|
||||||
int miOffset = miRow * cm.MiCols + miCol;
|
int miOffset = (miRow * cm.MiCols) + miCol;
|
||||||
|
|
||||||
mi.Value.SegmentId = (sbyte)ReadIntraSegmentId(ref cm, miOffset, xMis, yMis, ref r);
|
mi.Value.SegmentId = (sbyte)ReadIntraSegmentId(ref cm, miOffset, xMis, yMis, ref r);
|
||||||
mi.Value.Skip = (sbyte)ReadSkip(ref cm, ref xd, mi.Value.SegmentId, ref r);
|
mi.Value.Skip = (sbyte)ReadSkip(ref cm, ref xd, mi.Value.SegmentId, ref r);
|
||||||
|
@ -1088,7 +1085,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
switch (bsize)
|
switch (bsize)
|
||||||
{
|
{
|
||||||
case BlockSize.Block4x4:
|
case BlockSize.Block4x4:
|
||||||
for (i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
mi.Value.Bmi[i].Mode =
|
mi.Value.Bmi[i].Mode =
|
||||||
ReadIntraMode(ref r, GetYModeProbs(ref cm.Fc.Value, mi, aboveMi, leftMi, i));
|
ReadIntraMode(ref r, GetYModeProbs(ref cm.Fc.Value, mi, aboveMi, leftMi, i));
|
||||||
|
@ -1133,8 +1130,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
ref Reader r = ref twd.BitReader;
|
ref Reader r = ref twd.BitReader;
|
||||||
ref MacroBlockD xd = ref twd.Xd;
|
ref MacroBlockD xd = ref twd.Xd;
|
||||||
ref ModeInfo mi = ref xd.Mi[0].Value;
|
ref ModeInfo mi = ref xd.Mi[0].Value;
|
||||||
ArrayPtr<MvRef> frameMvs = cm.CurFrameMvs.Slice(miRow * cm.MiCols + miCol);
|
ArrayPtr<MvRef> frameMvs = cm.CurFrameMvs.Slice((miRow * cm.MiCols) + miCol);
|
||||||
int w, h;
|
|
||||||
|
|
||||||
if (cm.FrameIsIntraOnly())
|
if (cm.FrameIsIntraOnly())
|
||||||
{
|
{
|
||||||
|
@ -1144,14 +1140,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
ReadInterFrameModeInfo(ref cm, ref xd, miRow, miCol, ref r, xMis, yMis);
|
ReadInterFrameModeInfo(ref cm, ref xd, miRow, miCol, ref r, xMis, yMis);
|
||||||
|
|
||||||
for (h = 0; h < yMis; ++h)
|
for (int h = 0; h < yMis; ++h)
|
||||||
{
|
{
|
||||||
for (w = 0; w < xMis; ++w)
|
for (int w = 0; w < xMis; ++w)
|
||||||
{
|
{
|
||||||
ref MvRef mv = ref frameMvs[w];
|
ref MvRef mv = ref frameMvs[w];
|
||||||
CopyRefFramePair(ref mv.RefFrame, ref mi.RefFrame);
|
CopyRefFramePair(ref mv.RefFrame, ref mi.RefFrame);
|
||||||
CopyMvPair(ref mv.Mv, ref mi.Mv);
|
CopyPair(ref mv.Mv, ref mi.Mv);
|
||||||
}
|
}
|
||||||
|
|
||||||
frameMvs = frameMvs.Slice(cm.MiCols);
|
frameMvs = frameMvs.Slice(cm.MiCols);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ using Ryujinx.Graphics.Nvdec.Vp9.Common;
|
||||||
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
||||||
using Ryujinx.Graphics.Video;
|
using Ryujinx.Graphics.Video;
|
||||||
using System;
|
using System;
|
||||||
using Vp9MvRef = Ryujinx.Graphics.Video.Vp9MvRef;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Nvdec.Vp9
|
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
|
@ -11,16 +10,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
public bool IsHardwareAccelerated => false;
|
public bool IsHardwareAccelerated => false;
|
||||||
|
|
||||||
private readonly MemoryAllocator _allocator = new MemoryAllocator();
|
private readonly MemoryAllocator _allocator = new();
|
||||||
|
|
||||||
public ISurface CreateSurface(int width, int height) => new Surface(width, height);
|
public ISurface CreateSurface(int width, int height)
|
||||||
|
{
|
||||||
|
return new Surface(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
private static ReadOnlySpan<byte> LiteralToFilter => new byte[]
|
private static ReadOnlySpan<byte> LiteralToFilter => new byte[]
|
||||||
{
|
{
|
||||||
Constants.EightTapSmooth,
|
Constants.EightTapSmooth, Constants.EightTap, Constants.EightTapSharp, Constants.Bilinear
|
||||||
Constants.EightTap,
|
|
||||||
Constants.EightTapSharp,
|
|
||||||
Constants.Bilinear
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public unsafe bool Decode(
|
public unsafe bool Decode(
|
||||||
|
@ -30,7 +29,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
ReadOnlySpan<Vp9MvRef> mvsIn,
|
ReadOnlySpan<Vp9MvRef> mvsIn,
|
||||||
Span<Vp9MvRef> mvsOut)
|
Span<Vp9MvRef> mvsOut)
|
||||||
{
|
{
|
||||||
Vp9Common cm = new Vp9Common();
|
Vp9Common cm = new();
|
||||||
|
|
||||||
cm.FrameType = pictureInfo.IsKeyFrame ? FrameType.KeyFrame : FrameType.InterFrame;
|
cm.FrameType = pictureInfo.IsKeyFrame ? FrameType.KeyFrame : FrameType.InterFrame;
|
||||||
cm.IntraOnly = pictureInfo.IntraOnly;
|
cm.IntraOnly = pictureInfo.IntraOnly;
|
||||||
|
@ -68,6 +67,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
cm.CompFixedRef = pictureInfo.CompFixedRef;
|
cm.CompFixedRef = pictureInfo.CompFixedRef;
|
||||||
cm.CompVarRef = pictureInfo.CompVarRef;
|
cm.CompVarRef = pictureInfo.CompVarRef;
|
||||||
|
|
||||||
|
cm.BitDepth = BitDepth.Bits8;
|
||||||
|
|
||||||
cm.Log2TileCols = pictureInfo.Log2TileCols;
|
cm.Log2TileCols = pictureInfo.Log2TileCols;
|
||||||
cm.Log2TileRows = pictureInfo.Log2TileRows;
|
cm.Log2TileRows = pictureInfo.Log2TileRows;
|
||||||
|
|
||||||
|
@ -78,6 +79,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
cm.Seg.FeatureMask = pictureInfo.SegmentFeatureEnable;
|
cm.Seg.FeatureMask = pictureInfo.SegmentFeatureEnable;
|
||||||
cm.Seg.FeatureData = pictureInfo.SegmentFeatureData;
|
cm.Seg.FeatureData = pictureInfo.SegmentFeatureData;
|
||||||
|
|
||||||
|
cm.Lf.FilterLevel = pictureInfo.LoopFilterLevel;
|
||||||
|
cm.Lf.SharpnessLevel = pictureInfo.LoopFilterSharpnessLevel;
|
||||||
cm.Lf.ModeRefDeltaEnabled = pictureInfo.ModeRefDeltaEnabled;
|
cm.Lf.ModeRefDeltaEnabled = pictureInfo.ModeRefDeltaEnabled;
|
||||||
cm.Lf.RefDeltas = pictureInfo.RefDeltas;
|
cm.Lf.RefDeltas = pictureInfo.RefDeltas;
|
||||||
cm.Lf.ModeDeltas = pictureInfo.ModeDeltas;
|
cm.Lf.ModeDeltas = pictureInfo.ModeDeltas;
|
||||||
|
@ -105,7 +108,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
cm.SetupSegmentationDequant();
|
cm.SetupSegmentationDequant();
|
||||||
cm.SetupScaleFactors();
|
cm.SetupScaleFactors();
|
||||||
|
|
||||||
SetMvs(ref cm, mvsIn);
|
cm.SetMvs(mvsIn);
|
||||||
|
|
||||||
fixed (byte* dataPtr = bitstream)
|
fixed (byte* dataPtr = bitstream)
|
||||||
{
|
{
|
||||||
|
@ -114,10 +117,27 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
if (maxThreads > 1 && tileRows == 1 && tileCols > 1)
|
if (maxThreads > 1 && tileRows == 1 && tileCols > 1)
|
||||||
{
|
{
|
||||||
DecodeFrame.DecodeTilesMt(ref cm, new ArrayPtr<byte>(dataPtr, bitstream.Length), maxThreads);
|
DecodeFrame.DecodeTilesMt(ref cm, new ArrayPtr<byte>(dataPtr, bitstream.Length), maxThreads);
|
||||||
|
|
||||||
|
LoopFilter.LoopFilterFrameMt(
|
||||||
|
ref cm.Mb.CurBuf,
|
||||||
|
ref cm,
|
||||||
|
ref cm.Mb,
|
||||||
|
cm.Lf.FilterLevel,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
maxThreads);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DecodeFrame.DecodeTiles(ref cm, new ArrayPtr<byte>(dataPtr, bitstream.Length));
|
DecodeFrame.DecodeTiles(ref cm, new ArrayPtr<byte>(dataPtr, bitstream.Length));
|
||||||
|
|
||||||
|
LoopFilter.LoopFilterFrame(
|
||||||
|
ref cm.Mb.CurBuf,
|
||||||
|
ref cm,
|
||||||
|
ref cm.Mb,
|
||||||
|
cm.Lf.FilterLevel,
|
||||||
|
false,
|
||||||
|
false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (InternalErrorException)
|
catch (InternalErrorException)
|
||||||
|
@ -126,7 +146,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GetMvs(ref cm, mvsOut);
|
cm.GetMvs(mvsOut);
|
||||||
|
|
||||||
cm.FreeTileWorkerData(_allocator);
|
cm.FreeTileWorkerData(_allocator);
|
||||||
cm.FreeContextBuffers(_allocator);
|
cm.FreeContextBuffers(_allocator);
|
||||||
|
@ -134,48 +154,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SetMvs(ref Vp9Common cm, ReadOnlySpan<Vp9MvRef> mvs)
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (mvs.Length > cm.PrevFrameMvs.Length)
|
_allocator.Dispose();
|
||||||
{
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -19,24 +19,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
const int maxNeighbors = 2;
|
const int maxNeighbors = 2;
|
||||||
|
|
||||||
return (1 + tokenCache[neighbors[maxNeighbors * c + 0]] + tokenCache[neighbors[maxNeighbors * c + 1]]) >> 1;
|
return (1 + tokenCache[neighbors[(maxNeighbors * c) + 0]] +
|
||||||
}
|
tokenCache[neighbors[(maxNeighbors * c) + 1]]) >> 1;
|
||||||
|
|
||||||
private static int ReadCoeff(
|
|
||||||
ref Reader r,
|
|
||||||
ReadOnlySpan<byte> probs,
|
|
||||||
int n,
|
|
||||||
ref ulong value,
|
|
||||||
ref int count,
|
|
||||||
ref uint range)
|
|
||||||
{
|
|
||||||
int i, val = 0;
|
|
||||||
for (i = 0; i < n; ++i)
|
|
||||||
{
|
|
||||||
val = (val << 1) | r.ReadBool(probs[i], ref value, ref count, ref range);
|
|
||||||
}
|
|
||||||
|
|
||||||
return val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int DecodeCoefs(
|
private static int DecodeCoefs(
|
||||||
|
@ -57,14 +41,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
int band, c = 0;
|
int band, c = 0;
|
||||||
ref Array6<Array6<Array3<byte>>> coefProbs = ref fc.CoefProbs[(int)txSize][(int)type][refr];
|
ref Array6<Array6<Array3<byte>>> coefProbs = ref fc.CoefProbs[(int)txSize][(int)type][refr];
|
||||||
Span<byte> tokenCache = stackalloc byte[32 * 32];
|
Span<byte> tokenCache = stackalloc byte[32 * 32];
|
||||||
ReadOnlySpan<byte> bandTranslate = Luts.get_band_translate(txSize);
|
ReadOnlySpan<byte> bandTranslate = Luts.GetBandTranslate(txSize);
|
||||||
int dqShift = (txSize == TxSize.Tx32x32) ? 1 : 0;
|
int dqShift = txSize == TxSize.Tx32x32 ? 1 : 0;
|
||||||
int v;
|
int v;
|
||||||
short dqv = dq[0];
|
short dqv = dq[0];
|
||||||
ReadOnlySpan<byte> cat6Prob = (xd.Bd == 12)
|
ReadOnlySpan<byte> cat6Prob = xd.Bd == 12
|
||||||
? Luts.Vp9Cat6ProbHigh12
|
? Luts.Cat6ProbHigh12
|
||||||
: (xd.Bd == 10) ? Luts.Vp9Cat6ProbHigh12.Slice(2) : Luts.Vp9Cat6Prob;
|
: xd.Bd == 10
|
||||||
int cat6Bits = (xd.Bd == 12) ? 18 : (xd.Bd == 10) ? 16 : 14;
|
? Luts.Cat6ProbHigh12.Slice(2)
|
||||||
|
: Luts.Cat6Prob;
|
||||||
|
int cat6Bits = xd.Bd == 12 ? 18 : xd.Bd == 10 ? 16 : 14;
|
||||||
// Keep value, range, and count as locals. The compiler produces better
|
// Keep value, range, and count as locals. The compiler produces better
|
||||||
// results with the locals than using r directly.
|
// results with the locals than using r directly.
|
||||||
ulong value = r.Value;
|
ulong value = r.Value;
|
||||||
|
@ -109,6 +95,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
r.Count = count;
|
r.Count = count;
|
||||||
return c; // Zero tokens at the end (no eob token)
|
return c; // Zero tokens at the end (no eob token)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = GetCoefContext(nb, tokenCache, c);
|
ctx = GetCoefContext(nb, tokenCache, c);
|
||||||
band = bandTranslate[0];
|
band = bandTranslate[0];
|
||||||
bandTranslate = bandTranslate.Slice(1);
|
bandTranslate = bandTranslate.Slice(1);
|
||||||
|
@ -117,7 +104,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
|
||||||
if (r.ReadBool(prob[OneContextNode], ref value, ref count, ref range) != 0)
|
if (r.ReadBool(prob[OneContextNode], ref value, ref count, ref range) != 0)
|
||||||
{
|
{
|
||||||
ReadOnlySpan<byte> p = Luts.Vp9Pareto8Full[prob[Constants.PivotNode] - 1];
|
ReadOnlySpan<byte> p = Luts.Pareto8Full[prob[Constants.PivotNode] - 1];
|
||||||
if (!xd.Counts.IsNull)
|
if (!xd.Counts.IsNull)
|
||||||
{
|
{
|
||||||
++counts.Coef[(int)txSize][(int)type][refr][band][ctx][Constants.TwoToken];
|
++counts.Coef[(int)txSize][(int)type][refr][band][ctx][Constants.TwoToken];
|
||||||
|
@ -132,20 +119,24 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
if (r.ReadBool(p[7], ref value, ref count, ref range) != 0)
|
if (r.ReadBool(p[7], ref value, ref count, ref range) != 0)
|
||||||
{
|
{
|
||||||
val = Constants.Cat6MinVal + ReadCoeff(ref r, cat6Prob, cat6Bits, ref value, ref count, ref range);
|
val = Constants.Cat6MinVal + r.ReadCoeff(cat6Prob, cat6Bits, ref value,
|
||||||
|
ref count, ref range);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
val = Constants.Cat5MinVal + ReadCoeff(ref r, Luts.Vp9Cat5Prob, 5, ref value, ref count, ref range);
|
val = Constants.Cat5MinVal + r.ReadCoeff(Luts.Cat5Prob, 5, ref value,
|
||||||
|
ref count, ref range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (r.ReadBool(p[6], ref value, ref count, ref range) != 0)
|
else if (r.ReadBool(p[6], ref value, ref count, ref range) != 0)
|
||||||
{
|
{
|
||||||
val = Constants.Cat4MinVal + ReadCoeff(ref r, Luts.Vp9Cat4Prob, 4, ref value, ref count, ref range);
|
val = Constants.Cat4MinVal + r.ReadCoeff(Luts.Cat4Prob, 4, ref value, ref count,
|
||||||
|
ref range);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
val = Constants.Cat3MinVal + ReadCoeff(ref r, Luts.Vp9Cat3Prob, 3, ref value, ref count, ref range);
|
val = Constants.Cat3MinVal + r.ReadCoeff(Luts.Cat3Prob, 3, ref value, ref count,
|
||||||
|
ref range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -153,13 +144,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
tokenCache[scan[c]] = 4;
|
tokenCache[scan[c]] = 4;
|
||||||
if (r.ReadBool(p[4], ref value, ref count, ref range) != 0)
|
if (r.ReadBool(p[4], ref value, ref count, ref range) != 0)
|
||||||
{
|
{
|
||||||
val = Constants.Cat2MinVal + ReadCoeff(ref r, Luts.Vp9Cat2Prob, 2, ref value, ref count, ref range);
|
val = Constants.Cat2MinVal + r.ReadCoeff(Luts.Cat2Prob, 2, ref value, ref count,
|
||||||
|
ref range);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
val = Constants.Cat1MinVal + ReadCoeff(ref r, Luts.Vp9Cat1Prob, 1, ref value, ref count, ref range);
|
val = Constants.Cat1MinVal + r.ReadCoeff(Luts.Cat1Prob, 1, ref value, ref count,
|
||||||
|
ref range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Val may use 18-bits
|
// Val may use 18-bits
|
||||||
v = (int)(((long)val * dqv) >> dqShift);
|
v = (int)(((long)val * dqv) >> dqShift);
|
||||||
}
|
}
|
||||||
|
@ -187,7 +181,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
tokenCache[scan[c]] = 1;
|
tokenCache[scan[c]] = 1;
|
||||||
v = dqv >> dqShift;
|
v = dqv >> dqShift;
|
||||||
}
|
}
|
||||||
dqcoeff[scan[c]] = (int)HighbdCheckRange(r.ReadBool(128, ref value, ref count, ref range) != 0 ? -v : v, xd.Bd);
|
|
||||||
|
dqcoeff[scan[c]] = (int)HighbdCheckRange(r.ReadBool(128, ref value, ref count, ref range) != 0 ? -v : v,
|
||||||
|
xd.Bd);
|
||||||
++c;
|
++c;
|
||||||
ctx = GetCoefContext(nb, tokenCache, c);
|
ctx = GetCoefContext(nb, tokenCache, c);
|
||||||
dqv = dq[1];
|
dqv = dq[1];
|
||||||
|
@ -199,7 +195,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GetCtxShift(ref MacroBlockD xd, ref int ctxShiftA, ref int ctxShiftL, int x, int y, uint txSizeInBlocks)
|
private static void GetCtxShift(ref MacroBlockD xd, ref int ctxShiftA, ref int ctxShiftL, int x, int y,
|
||||||
|
uint txSizeInBlocks)
|
||||||
{
|
{
|
||||||
if (xd.MaxBlocksWide != 0)
|
if (xd.MaxBlocksWide != 0)
|
||||||
{
|
{
|
||||||
|
@ -208,6 +205,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
ctxShiftA = (int)(txSizeInBlocks - (xd.MaxBlocksWide - x)) * 8;
|
ctxShiftA = (int)(txSizeInBlocks - (xd.MaxBlocksWide - x)) * 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xd.MaxBlocksHigh != 0)
|
if (xd.MaxBlocksHigh != 0)
|
||||||
{
|
{
|
||||||
if (txSizeInBlocks + y > xd.MaxBlocksHigh)
|
if (txSizeInBlocks + y > xd.MaxBlocksHigh)
|
||||||
|
|
|
@ -75,17 +75,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
Vector128<int> zero = Vector128<int>.Zero;
|
Vector128<int> zero = Vector128<int>.Zero;
|
||||||
Vector128<int> const64 = Vector128.Create(64);
|
Vector128<int> const64 = Vector128.Create(64);
|
||||||
|
|
||||||
ulong x, y;
|
src -= (SubpelTaps / 2) - 1;
|
||||||
src -= SubpelTaps / 2 - 1;
|
|
||||||
|
|
||||||
fixed (Array8<short>* xFilter = xFilters)
|
fixed (Array8<short>* xFilter = xFilters)
|
||||||
{
|
{
|
||||||
Vector128<short> vfilter = Sse2.LoadVector128((short*)xFilter + (uint)(x0Q4 & SubpelMask) * 8);
|
Vector128<short> vfilter = Sse2.LoadVector128((short*)xFilter + ((uint)(x0Q4 & SubpelMask) * 8));
|
||||||
|
|
||||||
for (y = 0; y < (uint)h; ++y)
|
for (ulong y = 0; y < (uint)h; ++y)
|
||||||
{
|
{
|
||||||
ulong srcOffset = (uint)x0Q4 >> SubpelBits;
|
ulong srcOffset = (uint)x0Q4 >> SubpelBits;
|
||||||
for (x = 0; x < (uint)w; x += 4)
|
for (ulong x = 0; x < (uint)w; x += 4)
|
||||||
{
|
{
|
||||||
Vector128<short> vsrc0 = Sse41.ConvertToVector128Int16(&src[srcOffset + x]);
|
Vector128<short> vsrc0 = Sse41.ConvertToVector128Int16(&src[srcOffset + x]);
|
||||||
Vector128<short> vsrc1 = Sse41.ConvertToVector128Int16(&src[srcOffset + x + 1]);
|
Vector128<short> vsrc1 = Sse41.ConvertToVector128Int16(&src[srcOffset + x + 1]);
|
||||||
|
@ -94,8 +93,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
|
|
||||||
Vector128<int> sum0123 = MultiplyAddAdjacent(vsrc0, vsrc1, vsrc2, vsrc3, vfilter, zero);
|
Vector128<int> sum0123 = MultiplyAddAdjacent(vsrc0, vsrc1, vsrc2, vsrc3, vfilter, zero);
|
||||||
|
|
||||||
Sse.StoreScalar((float*)&dst[x], PackUnsignedSaturate(RoundShift(sum0123, const64), zero).AsSingle());
|
Sse.StoreScalar((float*)&dst[x],
|
||||||
|
PackUnsignedSaturate(RoundShift(sum0123, const64), zero).AsSingle());
|
||||||
}
|
}
|
||||||
|
|
||||||
src += srcStride;
|
src += srcStride;
|
||||||
dst += dstStride;
|
dst += dstStride;
|
||||||
}
|
}
|
||||||
|
@ -120,18 +121,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int x, y;
|
src -= (SubpelTaps / 2) - 1;
|
||||||
src -= SubpelTaps / 2 - 1;
|
|
||||||
|
|
||||||
for (y = 0; y < h; ++y)
|
for (int y = 0; y < h; ++y)
|
||||||
{
|
{
|
||||||
int xQ4 = x0Q4;
|
int xQ4 = x0Q4;
|
||||||
for (x = 0; x < w; ++x)
|
for (int x = 0; x < w; ++x)
|
||||||
{
|
{
|
||||||
byte* srcX = &src[xQ4 >> SubpelBits];
|
byte* srcX = &src[xQ4 >> SubpelBits];
|
||||||
ref Array8<short> xFilter = ref xFilters[xQ4 & SubpelMask];
|
ref Array8<short> xFilter = ref xFilters[xQ4 & SubpelMask];
|
||||||
int k, sum = 0;
|
int sum = 0;
|
||||||
for (k = 0; k < SubpelTaps; ++k)
|
for (int k = 0; k < SubpelTaps; ++k)
|
||||||
{
|
{
|
||||||
sum += srcX[k] * xFilter[k];
|
sum += srcX[k] * xFilter[k];
|
||||||
}
|
}
|
||||||
|
@ -139,6 +139,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
dst[x] = BitUtils.ClipPixel(BitUtils.RoundPowerOfTwo(sum, FilterBits));
|
dst[x] = BitUtils.ClipPixel(BitUtils.RoundPowerOfTwo(sum, FilterBits));
|
||||||
xQ4 += xStepQ4;
|
xQ4 += xStepQ4;
|
||||||
}
|
}
|
||||||
|
|
||||||
src += srcStride;
|
src += srcStride;
|
||||||
dst += dstStride;
|
dst += dstStride;
|
||||||
}
|
}
|
||||||
|
@ -155,25 +156,26 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
int w,
|
int w,
|
||||||
int h)
|
int h)
|
||||||
{
|
{
|
||||||
int x, y;
|
src -= (SubpelTaps / 2) - 1;
|
||||||
src -= SubpelTaps / 2 - 1;
|
|
||||||
|
|
||||||
for (y = 0; y < h; ++y)
|
for (int y = 0; y < h; ++y)
|
||||||
{
|
{
|
||||||
int xQ4 = x0Q4;
|
int xQ4 = x0Q4;
|
||||||
for (x = 0; x < w; ++x)
|
for (int x = 0; x < w; ++x)
|
||||||
{
|
{
|
||||||
byte* srcX = &src[xQ4 >> SubpelBits];
|
byte* srcX = &src[xQ4 >> SubpelBits];
|
||||||
ref Array8<short> xFilter = ref xFilters[xQ4 & SubpelMask];
|
ref Array8<short> xFilter = ref xFilters[xQ4 & SubpelMask];
|
||||||
int k, sum = 0;
|
int sum = 0;
|
||||||
for (k = 0; k < SubpelTaps; ++k)
|
for (int k = 0; k < SubpelTaps; ++k)
|
||||||
{
|
{
|
||||||
sum += srcX[k] * xFilter[k];
|
sum += srcX[k] * xFilter[k];
|
||||||
}
|
}
|
||||||
|
|
||||||
dst[x] = (byte)BitUtils.RoundPowerOfTwo(dst[x] + BitUtils.ClipPixel(BitUtils.RoundPowerOfTwo(sum, FilterBits)), 1);
|
dst[x] = (byte)BitUtils.RoundPowerOfTwo(
|
||||||
|
dst[x] + BitUtils.ClipPixel(BitUtils.RoundPowerOfTwo(sum, FilterBits)), 1);
|
||||||
xQ4 += xStepQ4;
|
xQ4 += xStepQ4;
|
||||||
}
|
}
|
||||||
|
|
||||||
src += srcStride;
|
src += srcStride;
|
||||||
dst += dstStride;
|
dst += dstStride;
|
||||||
}
|
}
|
||||||
|
@ -202,18 +204,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
srcStride * 6,
|
srcStride * 6,
|
||||||
srcStride * 7);
|
srcStride * 7);
|
||||||
|
|
||||||
ulong x, y;
|
src -= srcStride * ((SubpelTaps / 2) - 1);
|
||||||
src -= srcStride * (SubpelTaps / 2 - 1);
|
|
||||||
|
|
||||||
fixed (Array8<short>* yFilter = yFilters)
|
fixed (Array8<short>* yFilter = yFilters)
|
||||||
{
|
{
|
||||||
Vector128<short> vfilter = Sse2.LoadVector128((short*)yFilter + (uint)(y0Q4 & SubpelMask) * 8);
|
Vector128<short> vfilter = Sse2.LoadVector128((short*)yFilter + ((uint)(y0Q4 & SubpelMask) * 8));
|
||||||
|
|
||||||
ulong srcBaseY = (uint)y0Q4 >> SubpelBits;
|
ulong srcBaseY = (uint)y0Q4 >> SubpelBits;
|
||||||
for (y = 0; y < (uint)h; ++y)
|
for (ulong y = 0; y < (uint)h; ++y)
|
||||||
{
|
{
|
||||||
ulong srcOffset = (srcBaseY + y) * (uint)srcStride;
|
ulong srcOffset = (srcBaseY + y) * (uint)srcStride;
|
||||||
for (x = 0; x < (uint)w; x += 4)
|
for (ulong x = 0; x < (uint)w; x += 4)
|
||||||
{
|
{
|
||||||
Vector256<int> vsrc = Avx2.GatherVector256((uint*)&src[srcOffset + x], indices, 1).AsInt32();
|
Vector256<int> vsrc = Avx2.GatherVector256((uint*)&src[srcOffset + x], indices, 1).AsInt32();
|
||||||
|
|
||||||
|
@ -239,8 +240,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
|
|
||||||
Vector128<int> sum0123 = MultiplyAddAdjacent(vsrc0, vsrc1, vsrc2, vsrc3, vfilter, zero);
|
Vector128<int> sum0123 = MultiplyAddAdjacent(vsrc0, vsrc1, vsrc2, vsrc3, vfilter, zero);
|
||||||
|
|
||||||
Sse.StoreScalar((float*)&dst[x], PackUnsignedSaturate(RoundShift(sum0123, const64), zero).AsSingle());
|
Sse.StoreScalar((float*)&dst[x],
|
||||||
|
PackUnsignedSaturate(RoundShift(sum0123, const64), zero).AsSingle());
|
||||||
}
|
}
|
||||||
|
|
||||||
dst += dstStride;
|
dst += dstStride;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -264,18 +267,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int x, y;
|
src -= srcStride * ((SubpelTaps / 2) - 1);
|
||||||
src -= srcStride * (SubpelTaps / 2 - 1);
|
|
||||||
|
|
||||||
for (x = 0; x < w; ++x)
|
for (int x = 0; x < w; ++x)
|
||||||
{
|
{
|
||||||
int yQ4 = y0Q4;
|
int yQ4 = y0Q4;
|
||||||
for (y = 0; y < h; ++y)
|
for (int y = 0; y < h; ++y)
|
||||||
{
|
{
|
||||||
byte* srcY = &src[(yQ4 >> SubpelBits) * srcStride];
|
byte* srcY = &src[(yQ4 >> SubpelBits) * srcStride];
|
||||||
ref Array8<short> yFilter = ref yFilters[yQ4 & SubpelMask];
|
ref Array8<short> yFilter = ref yFilters[yQ4 & SubpelMask];
|
||||||
int k, sum = 0;
|
int sum = 0;
|
||||||
for (k = 0; k < SubpelTaps; ++k)
|
for (int k = 0; k < SubpelTaps; ++k)
|
||||||
{
|
{
|
||||||
sum += srcY[k * srcStride] * yFilter[k];
|
sum += srcY[k * srcStride] * yFilter[k];
|
||||||
}
|
}
|
||||||
|
@ -283,6 +285,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
dst[y * dstStride] = BitUtils.ClipPixel(BitUtils.RoundPowerOfTwo(sum, FilterBits));
|
dst[y * dstStride] = BitUtils.ClipPixel(BitUtils.RoundPowerOfTwo(sum, FilterBits));
|
||||||
yQ4 += yStepQ4;
|
yQ4 += yStepQ4;
|
||||||
}
|
}
|
||||||
|
|
||||||
++src;
|
++src;
|
||||||
++dst;
|
++dst;
|
||||||
}
|
}
|
||||||
|
@ -299,18 +302,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
int w,
|
int w,
|
||||||
int h)
|
int h)
|
||||||
{
|
{
|
||||||
int x, y;
|
src -= srcStride * ((SubpelTaps / 2) - 1);
|
||||||
src -= srcStride * (SubpelTaps / 2 - 1);
|
|
||||||
|
|
||||||
for (x = 0; x < w; ++x)
|
for (int x = 0; x < w; ++x)
|
||||||
{
|
{
|
||||||
int yQ4 = y0Q4;
|
int yQ4 = y0Q4;
|
||||||
for (y = 0; y < h; ++y)
|
for (int y = 0; y < h; ++y)
|
||||||
{
|
{
|
||||||
byte* srcY = &src[(yQ4 >> SubpelBits) * srcStride];
|
byte* srcY = &src[(yQ4 >> SubpelBits) * srcStride];
|
||||||
ref Array8<short> yFilter = ref yFilters[yQ4 & SubpelMask];
|
ref Array8<short> yFilter = ref yFilters[yQ4 & SubpelMask];
|
||||||
int k, sum = 0;
|
int sum = 0;
|
||||||
for (k = 0; k < SubpelTaps; ++k)
|
for (int k = 0; k < SubpelTaps; ++k)
|
||||||
{
|
{
|
||||||
sum += srcY[k * srcStride] * yFilter[k];
|
sum += srcY[k * srcStride] * yFilter[k];
|
||||||
}
|
}
|
||||||
|
@ -319,6 +321,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
dst[y * dstStride] + BitUtils.ClipPixel(BitUtils.RoundPowerOfTwo(sum, FilterBits)), 1);
|
dst[y * dstStride] + BitUtils.ClipPixel(BitUtils.RoundPowerOfTwo(sum, FilterBits)), 1);
|
||||||
yQ4 += yStepQ4;
|
yQ4 += yStepQ4;
|
||||||
}
|
}
|
||||||
|
|
||||||
++src;
|
++src;
|
||||||
++dst;
|
++dst;
|
||||||
}
|
}
|
||||||
|
@ -418,15 +421,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
// ==> yStepQ4 = 64. Since w and h are at most 16, the temp buffer is still
|
// ==> yStepQ4 = 64. Since w and h are at most 16, the temp buffer is still
|
||||||
// big enough.
|
// big enough.
|
||||||
byte* temp = stackalloc byte[64 * 135];
|
byte* temp = stackalloc byte[64 * 135];
|
||||||
int intermediateHeight = (((h - 1) * yStepQ4 + y0Q4) >> SubpelBits) + SubpelTaps;
|
int intermediateHeight = ((((h - 1) * yStepQ4) + y0Q4) >> SubpelBits) + SubpelTaps;
|
||||||
|
|
||||||
Debug.Assert(w <= 64);
|
Debug.Assert(w <= 64);
|
||||||
Debug.Assert(h <= 64);
|
Debug.Assert(h <= 64);
|
||||||
Debug.Assert(yStepQ4 <= 32 || (yStepQ4 <= 64 && h <= 32));
|
Debug.Assert(yStepQ4 <= 32 || (yStepQ4 <= 64 && h <= 32));
|
||||||
Debug.Assert(xStepQ4 <= 64);
|
Debug.Assert(xStepQ4 <= 64);
|
||||||
|
|
||||||
ConvolveHoriz(src - srcStride * (SubpelTaps / 2 - 1), srcStride, temp, 64, filter, x0Q4, xStepQ4, w, intermediateHeight);
|
ConvolveHoriz(src - (srcStride * ((SubpelTaps / 2) - 1)), srcStride, temp, 64, filter, x0Q4, xStepQ4, w,
|
||||||
ConvolveVert(temp + 64 * (SubpelTaps / 2 - 1), 64, dst, dstStride, filter, y0Q4, yStepQ4, w, h);
|
intermediateHeight);
|
||||||
|
ConvolveVert(temp + (64 * ((SubpelTaps / 2) - 1)), 64, dst, dstStride, filter, y0Q4, yStepQ4, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void Convolve8Avg(
|
public static unsafe void Convolve8Avg(
|
||||||
|
@ -487,11 +491,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
int w,
|
int w,
|
||||||
int h)
|
int h)
|
||||||
{
|
{
|
||||||
int x, y;
|
for (int y = 0; y < h; ++y)
|
||||||
|
|
||||||
for (y = 0; y < h; ++y)
|
|
||||||
{
|
{
|
||||||
for (x = 0; x < w; ++x)
|
for (int x = 0; x < w; ++x)
|
||||||
{
|
{
|
||||||
dst[x] = (byte)BitUtils.RoundPowerOfTwo(dst[x] + src[x], 1);
|
dst[x] = (byte)BitUtils.RoundPowerOfTwo(dst[x] + src[x], 1);
|
||||||
}
|
}
|
||||||
|
@ -609,18 +611,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
int h,
|
int h,
|
||||||
int bd)
|
int bd)
|
||||||
{
|
{
|
||||||
int x, y;
|
src -= (SubpelTaps / 2) - 1;
|
||||||
src -= SubpelTaps / 2 - 1;
|
|
||||||
|
|
||||||
for (y = 0; y < h; ++y)
|
for (int y = 0; y < h; ++y)
|
||||||
{
|
{
|
||||||
int xQ4 = x0Q4;
|
int xQ4 = x0Q4;
|
||||||
for (x = 0; x < w; ++x)
|
for (int x = 0; x < w; ++x)
|
||||||
{
|
{
|
||||||
ushort* srcX = &src[xQ4 >> SubpelBits];
|
ushort* srcX = &src[xQ4 >> SubpelBits];
|
||||||
ref Array8<short> xFilter = ref xFilters[xQ4 & SubpelMask];
|
ref Array8<short> xFilter = ref xFilters[xQ4 & SubpelMask];
|
||||||
int k, sum = 0;
|
int sum = 0;
|
||||||
for (k = 0; k < SubpelTaps; ++k)
|
for (int k = 0; k < SubpelTaps; ++k)
|
||||||
{
|
{
|
||||||
sum += srcX[k] * xFilter[k];
|
sum += srcX[k] * xFilter[k];
|
||||||
}
|
}
|
||||||
|
@ -628,6 +629,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
dst[x] = BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd);
|
dst[x] = BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd);
|
||||||
xQ4 += xStepQ4;
|
xQ4 += xStepQ4;
|
||||||
}
|
}
|
||||||
|
|
||||||
src += srcStride;
|
src += srcStride;
|
||||||
dst += dstStride;
|
dst += dstStride;
|
||||||
}
|
}
|
||||||
|
@ -645,25 +647,26 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
int h,
|
int h,
|
||||||
int bd)
|
int bd)
|
||||||
{
|
{
|
||||||
int x, y;
|
src -= (SubpelTaps / 2) - 1;
|
||||||
src -= SubpelTaps / 2 - 1;
|
|
||||||
|
|
||||||
for (y = 0; y < h; ++y)
|
for (int y = 0; y < h; ++y)
|
||||||
{
|
{
|
||||||
int xQ4 = x0Q4;
|
int xQ4 = x0Q4;
|
||||||
for (x = 0; x < w; ++x)
|
for (int x = 0; x < w; ++x)
|
||||||
{
|
{
|
||||||
ushort* srcX = &src[xQ4 >> SubpelBits];
|
ushort* srcX = &src[xQ4 >> SubpelBits];
|
||||||
ref Array8<short> xFilter = ref xFilters[xQ4 & SubpelMask];
|
ref Array8<short> xFilter = ref xFilters[xQ4 & SubpelMask];
|
||||||
int k, sum = 0;
|
int sum = 0;
|
||||||
for (k = 0; k < SubpelTaps; ++k)
|
for (int k = 0; k < SubpelTaps; ++k)
|
||||||
{
|
{
|
||||||
sum += srcX[k] * xFilter[k];
|
sum += srcX[k] * xFilter[k];
|
||||||
}
|
}
|
||||||
|
|
||||||
dst[x] = (ushort)BitUtils.RoundPowerOfTwo(dst[x] + BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd), 1);
|
dst[x] = (ushort)BitUtils.RoundPowerOfTwo(
|
||||||
|
dst[x] + BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd), 1);
|
||||||
xQ4 += xStepQ4;
|
xQ4 += xStepQ4;
|
||||||
}
|
}
|
||||||
|
|
||||||
src += srcStride;
|
src += srcStride;
|
||||||
dst += dstStride;
|
dst += dstStride;
|
||||||
}
|
}
|
||||||
|
@ -681,18 +684,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
int h,
|
int h,
|
||||||
int bd)
|
int bd)
|
||||||
{
|
{
|
||||||
int x, y;
|
src -= srcStride * ((SubpelTaps / 2) - 1);
|
||||||
src -= srcStride * (SubpelTaps / 2 - 1);
|
|
||||||
|
|
||||||
for (x = 0; x < w; ++x)
|
for (int x = 0; x < w; ++x)
|
||||||
{
|
{
|
||||||
int yQ4 = y0Q4;
|
int yQ4 = y0Q4;
|
||||||
for (y = 0; y < h; ++y)
|
for (int y = 0; y < h; ++y)
|
||||||
{
|
{
|
||||||
ushort* srcY = &src[(yQ4 >> SubpelBits) * srcStride];
|
ushort* srcY = &src[(yQ4 >> SubpelBits) * srcStride];
|
||||||
ref Array8<short> yFilter = ref yFilters[yQ4 & SubpelMask];
|
ref Array8<short> yFilter = ref yFilters[yQ4 & SubpelMask];
|
||||||
int k, sum = 0;
|
int sum = 0;
|
||||||
for (k = 0; k < SubpelTaps; ++k)
|
for (int k = 0; k < SubpelTaps; ++k)
|
||||||
{
|
{
|
||||||
sum += srcY[k * srcStride] * yFilter[k];
|
sum += srcY[k * srcStride] * yFilter[k];
|
||||||
}
|
}
|
||||||
|
@ -700,6 +702,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
dst[y * dstStride] = BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd);
|
dst[y * dstStride] = BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd);
|
||||||
yQ4 += yStepQ4;
|
yQ4 += yStepQ4;
|
||||||
}
|
}
|
||||||
|
|
||||||
++src;
|
++src;
|
||||||
++dst;
|
++dst;
|
||||||
}
|
}
|
||||||
|
@ -717,26 +720,27 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
int h,
|
int h,
|
||||||
int bd)
|
int bd)
|
||||||
{
|
{
|
||||||
int x, y;
|
src -= srcStride * ((SubpelTaps / 2) - 1);
|
||||||
src -= srcStride * (SubpelTaps / 2 - 1);
|
|
||||||
|
|
||||||
for (x = 0; x < w; ++x)
|
for (int x = 0; x < w; ++x)
|
||||||
{
|
{
|
||||||
int yQ4 = y0Q4;
|
int yQ4 = y0Q4;
|
||||||
for (y = 0; y < h; ++y)
|
for (int y = 0; y < h; ++y)
|
||||||
{
|
{
|
||||||
ushort* srcY = &src[(yQ4 >> SubpelBits) * srcStride];
|
ushort* srcY = &src[(yQ4 >> SubpelBits) * srcStride];
|
||||||
ref Array8<short> yFilter = ref yFilters[yQ4 & SubpelMask];
|
ref Array8<short> yFilter = ref yFilters[yQ4 & SubpelMask];
|
||||||
int k, sum = 0;
|
int sum = 0;
|
||||||
for (k = 0; k < SubpelTaps; ++k)
|
for (int k = 0; k < SubpelTaps; ++k)
|
||||||
{
|
{
|
||||||
sum += srcY[k * srcStride] * yFilter[k];
|
sum += srcY[k * srcStride] * yFilter[k];
|
||||||
}
|
}
|
||||||
|
|
||||||
dst[y * dstStride] = (ushort)BitUtils.RoundPowerOfTwo(
|
dst[y * dstStride] = (ushort)BitUtils.RoundPowerOfTwo(
|
||||||
dst[y * dstStride] + BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd), 1);
|
dst[y * dstStride] + BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd),
|
||||||
|
1);
|
||||||
yQ4 += yStepQ4;
|
yQ4 += yStepQ4;
|
||||||
}
|
}
|
||||||
|
|
||||||
++src;
|
++src;
|
||||||
++dst;
|
++dst;
|
||||||
}
|
}
|
||||||
|
@ -769,15 +773,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
// --Require an additional SubpelTaps rows for the 8-tap filter tails.
|
// --Require an additional SubpelTaps rows for the 8-tap filter tails.
|
||||||
// --((64 - 1) * 32 + 15) >> 4 + 8 = 135.
|
// --((64 - 1) * 32 + 15) >> 4 + 8 = 135.
|
||||||
ushort* temp = stackalloc ushort[64 * 135];
|
ushort* temp = stackalloc ushort[64 * 135];
|
||||||
int intermediateHeight = (((h - 1) * yStepQ4 + y0Q4) >> SubpelBits) + SubpelTaps;
|
int intermediateHeight = ((((h - 1) * yStepQ4) + y0Q4) >> SubpelBits) + SubpelTaps;
|
||||||
|
|
||||||
Debug.Assert(w <= 64);
|
Debug.Assert(w <= 64);
|
||||||
Debug.Assert(h <= 64);
|
Debug.Assert(h <= 64);
|
||||||
Debug.Assert(yStepQ4 <= 32);
|
Debug.Assert(yStepQ4 <= 32);
|
||||||
Debug.Assert(xStepQ4 <= 32);
|
Debug.Assert(xStepQ4 <= 32);
|
||||||
|
|
||||||
HighbdConvolveHoriz(src - srcStride * (SubpelTaps / 2 - 1), srcStride, temp, 64, filter, x0Q4, xStepQ4, w, intermediateHeight, bd);
|
HighbdConvolveHoriz(src - (srcStride * ((SubpelTaps / 2) - 1)), srcStride, temp, 64, filter, x0Q4, xStepQ4,
|
||||||
HighbdConvolveVert(temp + 64 * (SubpelTaps / 2 - 1), 64, dst, dstStride, filter, y0Q4, yStepQ4, w, h, bd);
|
w, intermediateHeight, bd);
|
||||||
|
HighbdConvolveVert(temp + (64 * ((SubpelTaps / 2) - 1)), 64, dst, dstStride, filter, y0Q4, yStepQ4, w, h,
|
||||||
|
bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void HighbdConvolve8Horiz(
|
public static unsafe void HighbdConvolve8Horiz(
|
||||||
|
@ -926,11 +932,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
int h,
|
int h,
|
||||||
int bd)
|
int bd)
|
||||||
{
|
{
|
||||||
int x, y;
|
for (int y = 0; y < h; ++y)
|
||||||
|
|
||||||
for (y = 0; y < h; ++y)
|
|
||||||
{
|
{
|
||||||
for (x = 0; x < w; ++x)
|
for (int x = 0; x < w; ++x)
|
||||||
{
|
{
|
||||||
dst[x] = (ushort)BitUtils.RoundPowerOfTwo(dst[x] + src[x], 1);
|
dst[x] = (ushort)BitUtils.RoundPowerOfTwo(dst[x] + src[x], 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,22 +6,22 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
{
|
{
|
||||||
private static unsafe ref byte Dst(byte* dst, int stride, int x, int y)
|
private static unsafe ref byte Dst(byte* dst, int stride, int x, int y)
|
||||||
{
|
{
|
||||||
return ref dst[x + y * stride];
|
return ref dst[x + (y * stride)];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe ref ushort Dst(ushort* dst, int stride, int x, int y)
|
private static unsafe ref ushort Dst(ushort* dst, int stride, int x, int y)
|
||||||
{
|
{
|
||||||
return ref dst[x + y * stride];
|
return ref dst[x + (y * stride)];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte Avg3(byte a, byte b, byte c)
|
private static byte Avg3(byte a, byte b, byte c)
|
||||||
{
|
{
|
||||||
return (byte)((a + 2 * b + c + 2) >> 2);
|
return (byte)((a + (2 * b) + c + 2) >> 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ushort Avg3(ushort a, ushort b, ushort c)
|
private static ushort Avg3(ushort a, ushort b, ushort c)
|
||||||
{
|
{
|
||||||
return (ushort)((a + 2 * b + c + 2) >> 2);
|
return (ushort)((a + (2 * b) + c + 2) >> 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte Avg2(byte a, byte b)
|
private static byte Avg2(byte a, byte b)
|
||||||
|
@ -51,9 +51,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
|
|
||||||
private static unsafe void D207Predictor(byte* dst, int stride, int bs, byte* above, byte* left)
|
private static unsafe void D207Predictor(byte* dst, int stride, int bs, byte* above, byte* left)
|
||||||
{
|
{
|
||||||
int r, c;
|
|
||||||
// First column
|
// First column
|
||||||
for (r = 0; r < bs - 1; ++r)
|
for (int r = 0; r < bs - 1; ++r)
|
||||||
{
|
{
|
||||||
dst[r * stride] = Avg2(left[r], left[r + 1]);
|
dst[r * stride] = Avg2(left[r], left[r + 1]);
|
||||||
}
|
}
|
||||||
|
@ -62,7 +61,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
dst++;
|
dst++;
|
||||||
|
|
||||||
// Second column
|
// Second column
|
||||||
for (r = 0; r < bs - 2; ++r)
|
for (int r = 0; r < bs - 2; ++r)
|
||||||
{
|
{
|
||||||
dst[r * stride] = Avg3(left[r], left[r + 1], left[r + 2]);
|
dst[r * stride] = Avg3(left[r], left[r + 1], left[r + 2]);
|
||||||
}
|
}
|
||||||
|
@ -72,16 +71,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
dst++;
|
dst++;
|
||||||
|
|
||||||
// Rest of last row
|
// Rest of last row
|
||||||
for (c = 0; c < bs - 2; ++c)
|
for (int c = 0; c < bs - 2; ++c)
|
||||||
{
|
{
|
||||||
dst[(bs - 1) * stride + c] = left[bs - 1];
|
dst[((bs - 1) * stride) + c] = left[bs - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (r = bs - 2; r >= 0; --r)
|
for (int r = bs - 2; r >= 0; --r)
|
||||||
{
|
{
|
||||||
for (c = 0; c < bs - 2; ++c)
|
for (int c = 0; c < bs - 2; ++c)
|
||||||
{
|
{
|
||||||
dst[r * stride + c] = dst[(r + 1) * stride + c - 2];
|
dst[(r * stride) + c] = dst[((r + 1) * stride) + c - 2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,19 +102,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
|
|
||||||
private static unsafe void D63Predictor(byte* dst, int stride, int bs, byte* above, byte* left)
|
private static unsafe void D63Predictor(byte* dst, int stride, int bs, byte* above, byte* left)
|
||||||
{
|
{
|
||||||
int r, c;
|
for (int c = 0; c < bs; ++c)
|
||||||
int size;
|
|
||||||
for (c = 0; c < bs; ++c)
|
|
||||||
{
|
{
|
||||||
dst[c] = Avg2(above[c], above[c + 1]);
|
dst[c] = Avg2(above[c], above[c + 1]);
|
||||||
dst[stride + c] = Avg3(above[c], above[c + 1], above[c + 2]);
|
dst[stride + c] = Avg3(above[c], above[c + 1], above[c + 2]);
|
||||||
}
|
}
|
||||||
for (r = 2, size = bs - 2; r < bs; r += 2, --size)
|
|
||||||
|
for (int r = 2, size = bs - 2; r < bs; r += 2, --size)
|
||||||
{
|
{
|
||||||
MemoryUtil.Copy(dst + (r + 0) * stride, dst + (r >> 1), size);
|
MemoryUtil.Copy(dst + ((r + 0) * stride), dst + (r >> 1), size);
|
||||||
MemoryUtil.Fill(dst + (r + 0) * stride + size, above[bs - 1], bs - size);
|
MemoryUtil.Fill(dst + ((r + 0) * stride) + size, above[bs - 1], bs - size);
|
||||||
MemoryUtil.Copy(dst + (r + 1) * stride, dst + stride + (r >> 1), size);
|
MemoryUtil.Copy(dst + ((r + 1) * stride), dst + stride + (r >> 1), size);
|
||||||
MemoryUtil.Fill(dst + (r + 1) * stride + size, above[bs - 1], bs - size);
|
MemoryUtil.Fill(dst + ((r + 1) * stride) + size, above[bs - 1], bs - size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,15 +136,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
{
|
{
|
||||||
byte aboveRight = above[bs - 1];
|
byte aboveRight = above[bs - 1];
|
||||||
byte* dstRow0 = dst;
|
byte* dstRow0 = dst;
|
||||||
int x, size;
|
|
||||||
|
|
||||||
for (x = 0; x < bs - 1; ++x)
|
for (int x = 0; x < bs - 1; ++x)
|
||||||
{
|
{
|
||||||
dst[x] = Avg3(above[x], above[x + 1], above[x + 2]);
|
dst[x] = Avg3(above[x], above[x + 1], above[x + 2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
dst[bs - 1] = aboveRight;
|
dst[bs - 1] = aboveRight;
|
||||||
dst += stride;
|
dst += stride;
|
||||||
for (x = 1, size = bs - 2; x < bs; ++x, --size)
|
for (int x = 1, size = bs - 2; x < bs; ++x, --size)
|
||||||
{
|
{
|
||||||
MemoryUtil.Copy(dst, dstRow0 + x, size);
|
MemoryUtil.Copy(dst, dstRow0 + x, size);
|
||||||
MemoryUtil.Fill(dst + size, aboveRight, x + 1);
|
MemoryUtil.Fill(dst + size, aboveRight, x + 1);
|
||||||
|
@ -171,10 +169,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
|
|
||||||
private static unsafe void D117Predictor(byte* dst, int stride, int bs, byte* above, byte* left)
|
private static unsafe void D117Predictor(byte* dst, int stride, int bs, byte* above, byte* left)
|
||||||
{
|
{
|
||||||
int r, c;
|
|
||||||
|
|
||||||
// First row
|
// First row
|
||||||
for (c = 0; c < bs; c++)
|
for (int c = 0; c < bs; c++)
|
||||||
{
|
{
|
||||||
dst[c] = Avg2(above[c - 1], above[c]);
|
dst[c] = Avg2(above[c - 1], above[c]);
|
||||||
}
|
}
|
||||||
|
@ -183,7 +179,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
|
|
||||||
// Second row
|
// Second row
|
||||||
dst[0] = Avg3(left[0], above[-1], above[0]);
|
dst[0] = Avg3(left[0], above[-1], above[0]);
|
||||||
for (c = 1; c < bs; c++)
|
for (int c = 1; c < bs; c++)
|
||||||
{
|
{
|
||||||
dst[c] = Avg3(above[c - 2], above[c - 1], above[c]);
|
dst[c] = Avg3(above[c - 2], above[c - 1], above[c]);
|
||||||
}
|
}
|
||||||
|
@ -192,17 +188,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
|
|
||||||
// The rest of first col
|
// The rest of first col
|
||||||
dst[0] = Avg3(above[-1], left[0], left[1]);
|
dst[0] = Avg3(above[-1], left[0], left[1]);
|
||||||
for (r = 3; r < bs; ++r)
|
for (int r = 3; r < bs; ++r)
|
||||||
{
|
{
|
||||||
dst[(r - 2) * stride] = Avg3(left[r - 3], left[r - 2], left[r - 1]);
|
dst[(r - 2) * stride] = Avg3(left[r - 3], left[r - 2], left[r - 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The rest of the block
|
// The rest of the block
|
||||||
for (r = 2; r < bs; ++r)
|
for (int r = 2; r < bs; ++r)
|
||||||
{
|
{
|
||||||
for (c = 1; c < bs; c++)
|
for (int c = 1; c < bs; c++)
|
||||||
{
|
{
|
||||||
dst[c] = dst[-2 * stride + c - 1];
|
dst[c] = dst[(-2 * stride) + c - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
dst += stride;
|
dst += stride;
|
||||||
|
@ -226,26 +222,26 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
|
|
||||||
private static unsafe void D135Predictor(byte* dst, int stride, int bs, byte* above, byte* left)
|
private static unsafe void D135Predictor(byte* dst, int stride, int bs, byte* above, byte* left)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
byte* border = stackalloc byte[32 + 32 - 1]; // outer border from bottom-left to top-right
|
byte* border = stackalloc byte[32 + 32 - 1]; // outer border from bottom-left to top-right
|
||||||
|
|
||||||
// Dst(dst, stride, bs, bs - 2)[0], i.e., border starting at bottom-left
|
// Dst(dst, stride, bs, bs - 2)[0], i.e., border starting at bottom-left
|
||||||
for (i = 0; i < bs - 2; ++i)
|
for (int i = 0; i < bs - 2; ++i)
|
||||||
{
|
{
|
||||||
border[i] = Avg3(left[bs - 3 - i], left[bs - 2 - i], left[bs - 1 - i]);
|
border[i] = Avg3(left[bs - 3 - i], left[bs - 2 - i], left[bs - 1 - i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
border[bs - 2] = Avg3(above[-1], left[0], left[1]);
|
border[bs - 2] = Avg3(above[-1], left[0], left[1]);
|
||||||
border[bs - 1] = Avg3(left[0], above[-1], above[0]);
|
border[bs - 1] = Avg3(left[0], above[-1], above[0]);
|
||||||
border[bs - 0] = Avg3(above[-1], above[0], above[1]);
|
border[bs - 0] = Avg3(above[-1], above[0], above[1]);
|
||||||
// dst[0][2, size), i.e., remaining top border ascending
|
// dst[0][2, size), i.e., remaining top border ascending
|
||||||
for (i = 0; i < bs - 2; ++i)
|
for (int i = 0; i < bs - 2; ++i)
|
||||||
{
|
{
|
||||||
border[bs + 1 + i] = Avg3(above[i], above[i + 1], above[i + 2]);
|
border[bs + 1 + i] = Avg3(above[i], above[i + 1], above[i + 2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < bs; ++i)
|
for (int i = 0; i < bs; ++i)
|
||||||
{
|
{
|
||||||
MemoryUtil.Copy(dst + i * stride, border + bs - 1 - i, bs);
|
MemoryUtil.Copy(dst + (i * stride), border + bs - 1 - i, bs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,9 +262,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
|
|
||||||
private static unsafe void D153Predictor(byte* dst, int stride, int bs, byte* above, byte* left)
|
private static unsafe void D153Predictor(byte* dst, int stride, int bs, byte* above, byte* left)
|
||||||
{
|
{
|
||||||
int r, c;
|
|
||||||
dst[0] = Avg2(above[-1], left[0]);
|
dst[0] = Avg2(above[-1], left[0]);
|
||||||
for (r = 1; r < bs; r++)
|
for (int r = 1; r < bs; r++)
|
||||||
{
|
{
|
||||||
dst[r * stride] = Avg2(left[r - 1], left[r]);
|
dst[r * stride] = Avg2(left[r - 1], left[r]);
|
||||||
}
|
}
|
||||||
|
@ -277,23 +272,23 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
|
|
||||||
dst[0] = Avg3(left[0], above[-1], above[0]);
|
dst[0] = Avg3(left[0], above[-1], above[0]);
|
||||||
dst[stride] = Avg3(above[-1], left[0], left[1]);
|
dst[stride] = Avg3(above[-1], left[0], left[1]);
|
||||||
for (r = 2; r < bs; r++)
|
for (int r = 2; r < bs; r++)
|
||||||
{
|
{
|
||||||
dst[r * stride] = Avg3(left[r - 2], left[r - 1], left[r]);
|
dst[r * stride] = Avg3(left[r - 2], left[r - 1], left[r]);
|
||||||
}
|
}
|
||||||
|
|
||||||
dst++;
|
dst++;
|
||||||
|
|
||||||
for (c = 0; c < bs - 2; c++)
|
for (int c = 0; c < bs - 2; c++)
|
||||||
{
|
{
|
||||||
dst[c] = Avg3(above[c - 1], above[c], above[c + 1]);
|
dst[c] = Avg3(above[c - 1], above[c], above[c + 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
dst += stride;
|
dst += stride;
|
||||||
|
|
||||||
for (r = 1; r < bs; ++r)
|
for (int r = 1; r < bs; ++r)
|
||||||
{
|
{
|
||||||
for (c = 0; c < bs - 2; c++)
|
for (int c = 0; c < bs - 2; c++)
|
||||||
{
|
{
|
||||||
dst[c] = dst[-stride + c - 2];
|
dst[c] = dst[-stride + c - 2];
|
||||||
}
|
}
|
||||||
|
@ -324,9 +319,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
|
|
||||||
private static unsafe void VPredictor(byte* dst, int stride, int bs, byte* above, byte* left)
|
private static unsafe void VPredictor(byte* dst, int stride, int bs, byte* above, byte* left)
|
||||||
{
|
{
|
||||||
int r;
|
for (int r = 0; r < bs; r++)
|
||||||
|
|
||||||
for (r = 0; r < bs; r++)
|
|
||||||
{
|
{
|
||||||
MemoryUtil.Copy(dst, above, bs);
|
MemoryUtil.Copy(dst, above, bs);
|
||||||
dst += stride;
|
dst += stride;
|
||||||
|
@ -355,43 +348,40 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
|
|
||||||
private static unsafe void HPredictor(byte* dst, int stride, int bs, byte* above, byte* left)
|
private static unsafe void HPredictor(byte* dst, int stride, int bs, byte* above, byte* left)
|
||||||
{
|
{
|
||||||
int r;
|
for (int r = 0; r < bs; r++)
|
||||||
|
|
||||||
for (r = 0; r < bs; r++)
|
|
||||||
{
|
{
|
||||||
MemoryUtil.Fill(dst, left[r], bs);
|
MemoryUtil.Fill(dst, left[r], bs);
|
||||||
dst += stride;
|
dst += stride;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void TMPredictor4x4(byte* dst, int stride, byte* above, byte* left)
|
public static unsafe void TmPredictor4x4(byte* dst, int stride, byte* above, byte* left)
|
||||||
{
|
{
|
||||||
TMPredictor(dst, stride, 4, above, left);
|
TmPredictor(dst, stride, 4, above, left);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void TMPredictor8x8(byte* dst, int stride, byte* above, byte* left)
|
public static unsafe void TmPredictor8x8(byte* dst, int stride, byte* above, byte* left)
|
||||||
{
|
{
|
||||||
TMPredictor(dst, stride, 8, above, left);
|
TmPredictor(dst, stride, 8, above, left);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void TMPredictor16x16(byte* dst, int stride, byte* above, byte* left)
|
public static unsafe void TmPredictor16x16(byte* dst, int stride, byte* above, byte* left)
|
||||||
{
|
{
|
||||||
TMPredictor(dst, stride, 16, above, left);
|
TmPredictor(dst, stride, 16, above, left);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void TMPredictor32x32(byte* dst, int stride, byte* above, byte* left)
|
public static unsafe void TmPredictor32x32(byte* dst, int stride, byte* above, byte* left)
|
||||||
{
|
{
|
||||||
TMPredictor(dst, stride, 32, above, left);
|
TmPredictor(dst, stride, 32, above, left);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe void TMPredictor(byte* dst, int stride, int bs, byte* above, byte* left)
|
private static unsafe void TmPredictor(byte* dst, int stride, int bs, byte* above, byte* left)
|
||||||
{
|
{
|
||||||
int r, c;
|
|
||||||
int yTopLeft = above[-1];
|
int yTopLeft = above[-1];
|
||||||
|
|
||||||
for (r = 0; r < bs; r++)
|
for (int r = 0; r < bs; r++)
|
||||||
{
|
{
|
||||||
for (c = 0; c < bs; c++)
|
for (int c = 0; c < bs; c++)
|
||||||
{
|
{
|
||||||
dst[c] = BitUtils.ClipPixel(left[r] + above[c] - yTopLeft);
|
dst[c] = BitUtils.ClipPixel(left[r] + above[c] - yTopLeft);
|
||||||
}
|
}
|
||||||
|
@ -422,9 +412,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
|
|
||||||
private static unsafe void Dc128Predictor(byte* dst, int stride, int bs, byte* above, byte* left)
|
private static unsafe void Dc128Predictor(byte* dst, int stride, int bs, byte* above, byte* left)
|
||||||
{
|
{
|
||||||
int r;
|
for (int r = 0; r < bs; r++)
|
||||||
|
|
||||||
for (r = 0; r < bs; r++)
|
|
||||||
{
|
{
|
||||||
MemoryUtil.Fill(dst, (byte)128, bs);
|
MemoryUtil.Fill(dst, (byte)128, bs);
|
||||||
dst += stride;
|
dst += stride;
|
||||||
|
@ -453,16 +441,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
|
|
||||||
private static unsafe void DcLeftPredictor(byte* dst, int stride, int bs, byte* above, byte* left)
|
private static unsafe void DcLeftPredictor(byte* dst, int stride, int bs, byte* above, byte* left)
|
||||||
{
|
{
|
||||||
int i, r, expectedDc, sum = 0;
|
int expectedDc, sum = 0;
|
||||||
|
|
||||||
for (i = 0; i < bs; i++)
|
for (int i = 0; i < bs; i++)
|
||||||
{
|
{
|
||||||
sum += left[i];
|
sum += left[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedDc = (sum + (bs >> 1)) / bs;
|
expectedDc = (sum + (bs >> 1)) / bs;
|
||||||
|
|
||||||
for (r = 0; r < bs; r++)
|
for (int r = 0; r < bs; r++)
|
||||||
{
|
{
|
||||||
MemoryUtil.Fill(dst, (byte)expectedDc, bs);
|
MemoryUtil.Fill(dst, (byte)expectedDc, bs);
|
||||||
dst += stride;
|
dst += stride;
|
||||||
|
@ -491,16 +479,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
|
|
||||||
private static unsafe void DcTopPredictor(byte* dst, int stride, int bs, byte* above, byte* left)
|
private static unsafe void DcTopPredictor(byte* dst, int stride, int bs, byte* above, byte* left)
|
||||||
{
|
{
|
||||||
int i, r, expectedDc, sum = 0;
|
int expectedDc, sum = 0;
|
||||||
|
|
||||||
for (i = 0; i < bs; i++)
|
for (int i = 0; i < bs; i++)
|
||||||
{
|
{
|
||||||
sum += above[i];
|
sum += above[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedDc = (sum + (bs >> 1)) / bs;
|
expectedDc = (sum + (bs >> 1)) / bs;
|
||||||
|
|
||||||
for (r = 0; r < bs; r++)
|
for (int r = 0; r < bs; r++)
|
||||||
{
|
{
|
||||||
MemoryUtil.Fill(dst, (byte)expectedDc, bs);
|
MemoryUtil.Fill(dst, (byte)expectedDc, bs);
|
||||||
dst += stride;
|
dst += stride;
|
||||||
|
@ -529,10 +517,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
|
|
||||||
private static unsafe void DcPredictor(byte* dst, int stride, int bs, byte* above, byte* left)
|
private static unsafe void DcPredictor(byte* dst, int stride, int bs, byte* above, byte* left)
|
||||||
{
|
{
|
||||||
int i, r, expectedDc, sum = 0;
|
int expectedDc, sum = 0;
|
||||||
int count = 2 * bs;
|
int count = 2 * bs;
|
||||||
|
|
||||||
for (i = 0; i < bs; i++)
|
for (int i = 0; i < bs; i++)
|
||||||
{
|
{
|
||||||
sum += above[i];
|
sum += above[i];
|
||||||
sum += left[i];
|
sum += left[i];
|
||||||
|
@ -540,7 +528,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
|
|
||||||
expectedDc = (sum + (count >> 1)) / count;
|
expectedDc = (sum + (count >> 1)) / count;
|
||||||
|
|
||||||
for (r = 0; r < bs; r++)
|
for (int r = 0; r < bs; r++)
|
||||||
{
|
{
|
||||||
MemoryUtil.Fill(dst, (byte)expectedDc, bs);
|
MemoryUtil.Fill(dst, (byte)expectedDc, bs);
|
||||||
dst += stride;
|
dst += stride;
|
||||||
|
@ -555,10 +543,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
byte k = left[2];
|
byte k = left[2];
|
||||||
byte l = left[3];
|
byte l = left[3];
|
||||||
|
|
||||||
MemoryUtil.Fill(dst + stride * 0, Avg3(h, I, j), 4);
|
MemoryUtil.Fill(dst + (stride * 0), Avg3(h, I, j), 4);
|
||||||
MemoryUtil.Fill(dst + stride * 1, Avg3(I, j, k), 4);
|
MemoryUtil.Fill(dst + (stride * 1), Avg3(I, j, k), 4);
|
||||||
MemoryUtil.Fill(dst + stride * 2, Avg3(j, k, l), 4);
|
MemoryUtil.Fill(dst + (stride * 2), Avg3(j, k, l), 4);
|
||||||
MemoryUtil.Fill(dst + stride * 3, Avg3(k, l, l), 4);
|
MemoryUtil.Fill(dst + (stride * 3), Avg3(k, l, l), 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void VePredictor4x4(byte* dst, int stride, byte* above, byte* left)
|
public static unsafe void VePredictor4x4(byte* dst, int stride, byte* above, byte* left)
|
||||||
|
@ -574,9 +562,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
dst[1] = Avg3(I, j, k);
|
dst[1] = Avg3(I, j, k);
|
||||||
dst[2] = Avg3(j, k, l);
|
dst[2] = Avg3(j, k, l);
|
||||||
dst[3] = Avg3(k, l, m);
|
dst[3] = Avg3(k, l, m);
|
||||||
MemoryUtil.Copy(dst + stride * 1, dst, 4);
|
MemoryUtil.Copy(dst + (stride * 1), dst, 4);
|
||||||
MemoryUtil.Copy(dst + stride * 2, dst, 4);
|
MemoryUtil.Copy(dst + (stride * 2), dst, 4);
|
||||||
MemoryUtil.Copy(dst + stride * 3, dst, 4);
|
MemoryUtil.Copy(dst + (stride * 3), dst, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void D207Predictor4x4(byte* dst, int stride, byte* above, byte* left)
|
public static unsafe void D207Predictor4x4(byte* dst, int stride, byte* above, byte* left)
|
||||||
|
@ -591,7 +579,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
Dst(dst, stride, 1, 0) = Avg3(I, j, k);
|
Dst(dst, stride, 1, 0) = Avg3(I, j, k);
|
||||||
Dst(dst, stride, 3, 0) = Dst(dst, stride, 1, 1) = Avg3(j, k, l);
|
Dst(dst, stride, 3, 0) = Dst(dst, stride, 1, 1) = Avg3(j, k, l);
|
||||||
Dst(dst, stride, 3, 1) = Dst(dst, stride, 1, 2) = Avg3(k, l, l);
|
Dst(dst, stride, 3, 1) = Dst(dst, stride, 1, 2) = Avg3(k, l, l);
|
||||||
Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 0, 3) = Dst(dst, stride, 1, 3) = Dst(dst, stride, 2, 3) = Dst(dst, stride, 3, 3) = l;
|
Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 0, 3) =
|
||||||
|
Dst(dst, stride, 1, 3) = Dst(dst, stride, 2, 3) = Dst(dst, stride, 3, 3) = l;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void D63Predictor4x4(byte* dst, int stride, byte* above, byte* left)
|
public static unsafe void D63Predictor4x4(byte* dst, int stride, byte* above, byte* left)
|
||||||
|
@ -616,7 +605,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
Dst(dst, stride, 3, 3) = Avg3(e, f, g); // Differs from vp8
|
Dst(dst, stride, 3, 3) = Avg3(e, f, g); // Differs from vp8
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void D63ePredictor4x4(byte* dst, int stride, byte* above, byte* left)
|
public static unsafe void D63EPredictor4x4(byte* dst, int stride, byte* above, byte* left)
|
||||||
{
|
{
|
||||||
byte a = above[0];
|
byte a = above[0];
|
||||||
byte b = above[1];
|
byte b = above[1];
|
||||||
|
@ -652,13 +641,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
Dst(dst, stride, 0, 0) = Avg3(a, b, c);
|
Dst(dst, stride, 0, 0) = Avg3(a, b, c);
|
||||||
Dst(dst, stride, 1, 0) = Dst(dst, stride, 0, 1) = Avg3(b, c, d);
|
Dst(dst, stride, 1, 0) = Dst(dst, stride, 0, 1) = Avg3(b, c, d);
|
||||||
Dst(dst, stride, 2, 0) = Dst(dst, stride, 1, 1) = Dst(dst, stride, 0, 2) = Avg3(c, d, e);
|
Dst(dst, stride, 2, 0) = Dst(dst, stride, 1, 1) = Dst(dst, stride, 0, 2) = Avg3(c, d, e);
|
||||||
Dst(dst, stride, 3, 0) = Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 2) = Dst(dst, stride, 0, 3) = Avg3(d, e, f);
|
Dst(dst, stride, 3, 0) =
|
||||||
|
Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 2) = Dst(dst, stride, 0, 3) = Avg3(d, e, f);
|
||||||
Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 1, 3) = Avg3(e, f, g);
|
Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 1, 3) = Avg3(e, f, g);
|
||||||
Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 3) = Avg3(f, g, h);
|
Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 3) = Avg3(f, g, h);
|
||||||
Dst(dst, stride, 3, 3) = h; // differs from vp8
|
Dst(dst, stride, 3, 3) = h; // differs from vp8
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void D45ePredictor4x4(byte* dst, int stride, byte* above, byte* left)
|
public static unsafe void D45EPredictor4x4(byte* dst, int stride, byte* above, byte* left)
|
||||||
{
|
{
|
||||||
byte a = above[0];
|
byte a = above[0];
|
||||||
byte b = above[1];
|
byte b = above[1];
|
||||||
|
@ -671,7 +661,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
Dst(dst, stride, 0, 0) = Avg3(a, b, c);
|
Dst(dst, stride, 0, 0) = Avg3(a, b, c);
|
||||||
Dst(dst, stride, 1, 0) = Dst(dst, stride, 0, 1) = Avg3(b, c, d);
|
Dst(dst, stride, 1, 0) = Dst(dst, stride, 0, 1) = Avg3(b, c, d);
|
||||||
Dst(dst, stride, 2, 0) = Dst(dst, stride, 1, 1) = Dst(dst, stride, 0, 2) = Avg3(c, d, e);
|
Dst(dst, stride, 2, 0) = Dst(dst, stride, 1, 1) = Dst(dst, stride, 0, 2) = Avg3(c, d, e);
|
||||||
Dst(dst, stride, 3, 0) = Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 2) = Dst(dst, stride, 0, 3) = Avg3(d, e, f);
|
Dst(dst, stride, 3, 0) =
|
||||||
|
Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 2) = Dst(dst, stride, 0, 3) = Avg3(d, e, f);
|
||||||
Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 1, 3) = Avg3(e, f, g);
|
Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 1, 3) = Avg3(e, f, g);
|
||||||
Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 3) = Avg3(f, g, h);
|
Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 3) = Avg3(f, g, h);
|
||||||
Dst(dst, stride, 3, 3) = Avg3(g, h, h);
|
Dst(dst, stride, 3, 3) = Avg3(g, h, h);
|
||||||
|
@ -714,7 +705,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
Dst(dst, stride, 0, 3) = Avg3(j, k, l);
|
Dst(dst, stride, 0, 3) = Avg3(j, k, l);
|
||||||
Dst(dst, stride, 1, 3) = Dst(dst, stride, 0, 2) = Avg3(I, j, k);
|
Dst(dst, stride, 1, 3) = Dst(dst, stride, 0, 2) = Avg3(I, j, k);
|
||||||
Dst(dst, stride, 2, 3) = Dst(dst, stride, 1, 2) = Dst(dst, stride, 0, 1) = Avg3(x, I, j);
|
Dst(dst, stride, 2, 3) = Dst(dst, stride, 1, 2) = Dst(dst, stride, 0, 1) = Avg3(x, I, j);
|
||||||
Dst(dst, stride, 3, 3) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 1, 1) = Dst(dst, stride, 0, 0) = Avg3(a, x, I);
|
Dst(dst, stride, 3, 3) =
|
||||||
|
Dst(dst, stride, 2, 2) = Dst(dst, stride, 1, 1) = Dst(dst, stride, 0, 0) = Avg3(a, x, I);
|
||||||
Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 0) = Avg3(b, a, x);
|
Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 0) = Avg3(b, a, x);
|
||||||
Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 0) = Avg3(c, b, a);
|
Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 0) = Avg3(c, b, a);
|
||||||
Dst(dst, stride, 3, 0) = Avg3(d, c, b);
|
Dst(dst, stride, 3, 0) = Avg3(d, c, b);
|
||||||
|
@ -758,38 +750,39 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
HighbdD207Predictor(dst, stride, 32, above, left, bd);
|
HighbdD207Predictor(dst, stride, 32, above, left, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe void HighbdD207Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, int bd)
|
private static unsafe void HighbdD207Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left,
|
||||||
|
int bd)
|
||||||
{
|
{
|
||||||
int r, c;
|
|
||||||
|
|
||||||
// First column.
|
// First column.
|
||||||
for (r = 0; r < bs - 1; ++r)
|
for (int r = 0; r < bs - 1; ++r)
|
||||||
{
|
{
|
||||||
dst[r * stride] = Avg2(left[r], left[r + 1]);
|
dst[r * stride] = Avg2(left[r], left[r + 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
dst[(bs - 1) * stride] = left[bs - 1];
|
dst[(bs - 1) * stride] = left[bs - 1];
|
||||||
dst++;
|
dst++;
|
||||||
|
|
||||||
// Second column.
|
// Second column.
|
||||||
for (r = 0; r < bs - 2; ++r)
|
for (int r = 0; r < bs - 2; ++r)
|
||||||
{
|
{
|
||||||
dst[r * stride] = Avg3(left[r], left[r + 1], left[r + 2]);
|
dst[r * stride] = Avg3(left[r], left[r + 1], left[r + 2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
dst[(bs - 2) * stride] = Avg3(left[bs - 2], left[bs - 1], left[bs - 1]);
|
dst[(bs - 2) * stride] = Avg3(left[bs - 2], left[bs - 1], left[bs - 1]);
|
||||||
dst[(bs - 1) * stride] = left[bs - 1];
|
dst[(bs - 1) * stride] = left[bs - 1];
|
||||||
dst++;
|
dst++;
|
||||||
|
|
||||||
// Rest of last row.
|
// Rest of last row.
|
||||||
for (c = 0; c < bs - 2; ++c)
|
for (int c = 0; c < bs - 2; ++c)
|
||||||
{
|
{
|
||||||
dst[(bs - 1) * stride + c] = left[bs - 1];
|
dst[((bs - 1) * stride) + c] = left[bs - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (r = bs - 2; r >= 0; --r)
|
for (int r = bs - 2; r >= 0; --r)
|
||||||
{
|
{
|
||||||
for (c = 0; c < bs - 2; ++c)
|
for (int c = 0; c < bs - 2; ++c)
|
||||||
{
|
{
|
||||||
dst[r * stride + c] = dst[(r + 1) * stride + c - 2];
|
dst[(r * stride) + c] = dst[((r + 1) * stride) + c - 2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -809,21 +802,21 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
HighbdD63Predictor(dst, stride, 32, above, left, bd);
|
HighbdD63Predictor(dst, stride, 32, above, left, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe void HighbdD63Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, int bd)
|
private static unsafe void HighbdD63Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left,
|
||||||
|
int bd)
|
||||||
{
|
{
|
||||||
int r, c;
|
for (int c = 0; c < bs; ++c)
|
||||||
int size;
|
|
||||||
for (c = 0; c < bs; ++c)
|
|
||||||
{
|
{
|
||||||
dst[c] = Avg2(above[c], above[c + 1]);
|
dst[c] = Avg2(above[c], above[c + 1]);
|
||||||
dst[stride + c] = Avg3(above[c], above[c + 1], above[c + 2]);
|
dst[stride + c] = Avg3(above[c], above[c + 1], above[c + 2]);
|
||||||
}
|
}
|
||||||
for (r = 2, size = bs - 2; r < bs; r += 2, --size)
|
|
||||||
|
for (int r = 2, size = bs - 2; r < bs; r += 2, --size)
|
||||||
{
|
{
|
||||||
MemoryUtil.Copy(dst + (r + 0) * stride, dst + (r >> 1), size);
|
MemoryUtil.Copy(dst + ((r + 0) * stride), dst + (r >> 1), size);
|
||||||
MemoryUtil.Fill(dst + (r + 0) * stride + size, above[bs - 1], bs - size);
|
MemoryUtil.Fill(dst + ((r + 0) * stride) + size, above[bs - 1], bs - size);
|
||||||
MemoryUtil.Copy(dst + (r + 1) * stride, dst + stride + (r >> 1), size);
|
MemoryUtil.Copy(dst + ((r + 1) * stride), dst + stride + (r >> 1), size);
|
||||||
MemoryUtil.Fill(dst + (r + 1) * stride + size, above[bs - 1], bs - size);
|
MemoryUtil.Fill(dst + ((r + 1) * stride) + size, above[bs - 1], bs - size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -842,19 +835,20 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
HighbdD45Predictor(dst, stride, 32, above, left, bd);
|
HighbdD45Predictor(dst, stride, 32, above, left, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe void HighbdD45Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, int bd)
|
private static unsafe void HighbdD45Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left,
|
||||||
|
int bd)
|
||||||
{
|
{
|
||||||
ushort aboveRight = above[bs - 1];
|
ushort aboveRight = above[bs - 1];
|
||||||
ushort* dstRow0 = dst;
|
ushort* dstRow0 = dst;
|
||||||
int x, size;
|
|
||||||
|
|
||||||
for (x = 0; x < bs - 1; ++x)
|
for (int x = 0; x < bs - 1; ++x)
|
||||||
{
|
{
|
||||||
dst[x] = Avg3(above[x], above[x + 1], above[x + 2]);
|
dst[x] = Avg3(above[x], above[x + 1], above[x + 2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
dst[bs - 1] = aboveRight;
|
dst[bs - 1] = aboveRight;
|
||||||
dst += stride;
|
dst += stride;
|
||||||
for (x = 1, size = bs - 2; x < bs; ++x, --size)
|
for (int x = 1, size = bs - 2; x < bs; ++x, --size)
|
||||||
{
|
{
|
||||||
MemoryUtil.Copy(dst, dstRow0 + x, size);
|
MemoryUtil.Copy(dst, dstRow0 + x, size);
|
||||||
MemoryUtil.Fill(dst + size, aboveRight, x + 1);
|
MemoryUtil.Fill(dst + size, aboveRight, x + 1);
|
||||||
|
@ -877,12 +871,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
HighbdD117Predictor(dst, stride, 32, above, left, bd);
|
HighbdD117Predictor(dst, stride, 32, above, left, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe void HighbdD117Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, int bd)
|
private static unsafe void HighbdD117Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left,
|
||||||
|
int bd)
|
||||||
{
|
{
|
||||||
int r, c;
|
|
||||||
|
|
||||||
// First row
|
// First row
|
||||||
for (c = 0; c < bs; c++)
|
for (int c = 0; c < bs; c++)
|
||||||
{
|
{
|
||||||
dst[c] = Avg2(above[c - 1], above[c]);
|
dst[c] = Avg2(above[c - 1], above[c]);
|
||||||
}
|
}
|
||||||
|
@ -891,7 +884,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
|
|
||||||
// Second row
|
// Second row
|
||||||
dst[0] = Avg3(left[0], above[-1], above[0]);
|
dst[0] = Avg3(left[0], above[-1], above[0]);
|
||||||
for (c = 1; c < bs; c++)
|
for (int c = 1; c < bs; c++)
|
||||||
{
|
{
|
||||||
dst[c] = Avg3(above[c - 2], above[c - 1], above[c]);
|
dst[c] = Avg3(above[c - 2], above[c - 1], above[c]);
|
||||||
}
|
}
|
||||||
|
@ -900,17 +893,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
|
|
||||||
// The rest of first col
|
// The rest of first col
|
||||||
dst[0] = Avg3(above[-1], left[0], left[1]);
|
dst[0] = Avg3(above[-1], left[0], left[1]);
|
||||||
for (r = 3; r < bs; ++r)
|
for (int r = 3; r < bs; ++r)
|
||||||
{
|
{
|
||||||
dst[(r - 2) * stride] = Avg3(left[r - 3], left[r - 2], left[r - 1]);
|
dst[(r - 2) * stride] = Avg3(left[r - 3], left[r - 2], left[r - 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The rest of the block
|
// The rest of the block
|
||||||
for (r = 2; r < bs; ++r)
|
for (int r = 2; r < bs; ++r)
|
||||||
{
|
{
|
||||||
for (c = 1; c < bs; c++)
|
for (int c = 1; c < bs; c++)
|
||||||
{
|
{
|
||||||
dst[c] = dst[-2 * stride + c - 1];
|
dst[c] = dst[(-2 * stride) + c - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
dst += stride;
|
dst += stride;
|
||||||
|
@ -932,28 +925,29 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
HighbdD135Predictor(dst, stride, 32, above, left, bd);
|
HighbdD135Predictor(dst, stride, 32, above, left, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe void HighbdD135Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, int bd)
|
private static unsafe void HighbdD135Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left,
|
||||||
|
int bd)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
ushort* border = stackalloc ushort[32 + 32 - 1]; // Outer border from bottom-left to top-right
|
ushort* border = stackalloc ushort[32 + 32 - 1]; // Outer border from bottom-left to top-right
|
||||||
|
|
||||||
// Dst(dst, stride, bs, bs - 2)[0], i.e., border starting at bottom-left
|
// Dst(dst, stride, bs, bs - 2)[0], i.e., border starting at bottom-left
|
||||||
for (i = 0; i < bs - 2; ++i)
|
for (int i = 0; i < bs - 2; ++i)
|
||||||
{
|
{
|
||||||
border[i] = Avg3(left[bs - 3 - i], left[bs - 2 - i], left[bs - 1 - i]);
|
border[i] = Avg3(left[bs - 3 - i], left[bs - 2 - i], left[bs - 1 - i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
border[bs - 2] = Avg3(above[-1], left[0], left[1]);
|
border[bs - 2] = Avg3(above[-1], left[0], left[1]);
|
||||||
border[bs - 1] = Avg3(left[0], above[-1], above[0]);
|
border[bs - 1] = Avg3(left[0], above[-1], above[0]);
|
||||||
border[bs - 0] = Avg3(above[-1], above[0], above[1]);
|
border[bs - 0] = Avg3(above[-1], above[0], above[1]);
|
||||||
// dst[0][2, size), i.e., remaining top border ascending
|
// dst[0][2, size), i.e., remaining top border ascending
|
||||||
for (i = 0; i < bs - 2; ++i)
|
for (int i = 0; i < bs - 2; ++i)
|
||||||
{
|
{
|
||||||
border[bs + 1 + i] = Avg3(above[i], above[i + 1], above[i + 2]);
|
border[bs + 1 + i] = Avg3(above[i], above[i + 1], above[i + 2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < bs; ++i)
|
for (int i = 0; i < bs; ++i)
|
||||||
{
|
{
|
||||||
MemoryUtil.Copy(dst + i * stride, border + bs - 1 - i, bs);
|
MemoryUtil.Copy(dst + (i * stride), border + bs - 1 - i, bs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -972,11 +966,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
HighbdD153Predictor(dst, stride, 32, above, left, bd);
|
HighbdD153Predictor(dst, stride, 32, above, left, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe void HighbdD153Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, int bd)
|
private static unsafe void HighbdD153Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left,
|
||||||
|
int bd)
|
||||||
{
|
{
|
||||||
int r, c;
|
|
||||||
dst[0] = Avg2(above[-1], left[0]);
|
dst[0] = Avg2(above[-1], left[0]);
|
||||||
for (r = 1; r < bs; r++)
|
for (int r = 1; r < bs; r++)
|
||||||
{
|
{
|
||||||
dst[r * stride] = Avg2(left[r - 1], left[r]);
|
dst[r * stride] = Avg2(left[r - 1], left[r]);
|
||||||
}
|
}
|
||||||
|
@ -985,23 +979,23 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
|
|
||||||
dst[0] = Avg3(left[0], above[-1], above[0]);
|
dst[0] = Avg3(left[0], above[-1], above[0]);
|
||||||
dst[stride] = Avg3(above[-1], left[0], left[1]);
|
dst[stride] = Avg3(above[-1], left[0], left[1]);
|
||||||
for (r = 2; r < bs; r++)
|
for (int r = 2; r < bs; r++)
|
||||||
{
|
{
|
||||||
dst[r * stride] = Avg3(left[r - 2], left[r - 1], left[r]);
|
dst[r * stride] = Avg3(left[r - 2], left[r - 1], left[r]);
|
||||||
}
|
}
|
||||||
|
|
||||||
dst++;
|
dst++;
|
||||||
|
|
||||||
for (c = 0; c < bs - 2; c++)
|
for (int c = 0; c < bs - 2; c++)
|
||||||
{
|
{
|
||||||
dst[c] = Avg3(above[c - 1], above[c], above[c + 1]);
|
dst[c] = Avg3(above[c - 1], above[c], above[c + 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
dst += stride;
|
dst += stride;
|
||||||
|
|
||||||
for (r = 1; r < bs; ++r)
|
for (int r = 1; r < bs; ++r)
|
||||||
{
|
{
|
||||||
for (c = 0; c < bs - 2; c++)
|
for (int c = 0; c < bs - 2; c++)
|
||||||
{
|
{
|
||||||
dst[c] = dst[-stride + c - 2];
|
dst[c] = dst[-stride + c - 2];
|
||||||
}
|
}
|
||||||
|
@ -1030,10 +1024,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
HighbdVPredictor(dst, stride, 32, above, left, bd);
|
HighbdVPredictor(dst, stride, 32, above, left, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe void HighbdVPredictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, int bd)
|
private static unsafe void HighbdVPredictor(ushort* dst, int stride, int bs, ushort* above, ushort* left,
|
||||||
|
int bd)
|
||||||
{
|
{
|
||||||
int r;
|
for (int r = 0; r < bs; r++)
|
||||||
for (r = 0; r < bs; r++)
|
|
||||||
{
|
{
|
||||||
MemoryUtil.Copy(dst, above, bs);
|
MemoryUtil.Copy(dst, above, bs);
|
||||||
dst += stride;
|
dst += stride;
|
||||||
|
@ -1060,44 +1054,44 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
HighbdHPredictor(dst, stride, 32, above, left, bd);
|
HighbdHPredictor(dst, stride, 32, above, left, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe void HighbdHPredictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, int bd)
|
private static unsafe void HighbdHPredictor(ushort* dst, int stride, int bs, ushort* above, ushort* left,
|
||||||
|
int bd)
|
||||||
{
|
{
|
||||||
int r;
|
for (int r = 0; r < bs; r++)
|
||||||
for (r = 0; r < bs; r++)
|
|
||||||
{
|
{
|
||||||
MemoryUtil.Fill(dst, left[r], bs);
|
MemoryUtil.Fill(dst, left[r], bs);
|
||||||
dst += stride;
|
dst += stride;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void HighbdTMPredictor4x4(ushort* dst, int stride, ushort* above, ushort* left, int bd)
|
public static unsafe void HighbdTmPredictor4x4(ushort* dst, int stride, ushort* above, ushort* left, int bd)
|
||||||
{
|
{
|
||||||
HighbdTMPredictor(dst, stride, 4, above, left, bd);
|
HighbdTmPredictor(dst, stride, 4, above, left, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void HighbdTMPredictor8x8(ushort* dst, int stride, ushort* above, ushort* left, int bd)
|
public static unsafe void HighbdTmPredictor8x8(ushort* dst, int stride, ushort* above, ushort* left, int bd)
|
||||||
{
|
{
|
||||||
HighbdTMPredictor(dst, stride, 8, above, left, bd);
|
HighbdTmPredictor(dst, stride, 8, above, left, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void HighbdTMPredictor16x16(ushort* dst, int stride, ushort* above, ushort* left, int bd)
|
public static unsafe void HighbdTmPredictor16x16(ushort* dst, int stride, ushort* above, ushort* left, int bd)
|
||||||
{
|
{
|
||||||
HighbdTMPredictor(dst, stride, 16, above, left, bd);
|
HighbdTmPredictor(dst, stride, 16, above, left, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void HighbdTMPredictor32x32(ushort* dst, int stride, ushort* above, ushort* left, int bd)
|
public static unsafe void HighbdTmPredictor32x32(ushort* dst, int stride, ushort* above, ushort* left, int bd)
|
||||||
{
|
{
|
||||||
HighbdTMPredictor(dst, stride, 32, above, left, bd);
|
HighbdTmPredictor(dst, stride, 32, above, left, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe void HighbdTMPredictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, int bd)
|
private static unsafe void HighbdTmPredictor(ushort* dst, int stride, int bs, ushort* above, ushort* left,
|
||||||
|
int bd)
|
||||||
{
|
{
|
||||||
int r, c;
|
|
||||||
int yTopLeft = above[-1];
|
int yTopLeft = above[-1];
|
||||||
|
|
||||||
for (r = 0; r < bs; r++)
|
for (int r = 0; r < bs; r++)
|
||||||
{
|
{
|
||||||
for (c = 0; c < bs; c++)
|
for (int c = 0; c < bs; c++)
|
||||||
{
|
{
|
||||||
dst[c] = BitUtils.ClipPixelHighbd(left[r] + above[c] - yTopLeft, bd);
|
dst[c] = BitUtils.ClipPixelHighbd(left[r] + above[c] - yTopLeft, bd);
|
||||||
}
|
}
|
||||||
|
@ -1116,21 +1110,22 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
HighbdDc128Predictor(dst, stride, 8, above, left, bd);
|
HighbdDc128Predictor(dst, stride, 8, above, left, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void HighbdDc128Predictor16x16(ushort* dst, int stride, ushort* above, ushort* left, int bd)
|
public static unsafe void HighbdDc128Predictor16x16(ushort* dst, int stride, ushort* above, ushort* left,
|
||||||
|
int bd)
|
||||||
{
|
{
|
||||||
HighbdDc128Predictor(dst, stride, 16, above, left, bd);
|
HighbdDc128Predictor(dst, stride, 16, above, left, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void HighbdDc128Predictor32x32(ushort* dst, int stride, ushort* above, ushort* left, int bd)
|
public static unsafe void HighbdDc128Predictor32x32(ushort* dst, int stride, ushort* above, ushort* left,
|
||||||
|
int bd)
|
||||||
{
|
{
|
||||||
HighbdDc128Predictor(dst, stride, 32, above, left, bd);
|
HighbdDc128Predictor(dst, stride, 32, above, left, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe void HighbdDc128Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, int bd)
|
private static unsafe void HighbdDc128Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left,
|
||||||
|
int bd)
|
||||||
{
|
{
|
||||||
int r;
|
for (int r = 0; r < bs; r++)
|
||||||
|
|
||||||
for (r = 0; r < bs; r++)
|
|
||||||
{
|
{
|
||||||
MemoryUtil.Fill(dst, (ushort)(128 << (bd - 8)), bs);
|
MemoryUtil.Fill(dst, (ushort)(128 << (bd - 8)), bs);
|
||||||
dst += stride;
|
dst += stride;
|
||||||
|
@ -1147,28 +1142,31 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
HighbdDcLeftPredictor(dst, stride, 8, above, left, bd);
|
HighbdDcLeftPredictor(dst, stride, 8, above, left, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void HighbdDcLeftPredictor16x16(ushort* dst, int stride, ushort* above, ushort* left, int bd)
|
public static unsafe void HighbdDcLeftPredictor16x16(ushort* dst, int stride, ushort* above, ushort* left,
|
||||||
|
int bd)
|
||||||
{
|
{
|
||||||
HighbdDcLeftPredictor(dst, stride, 16, above, left, bd);
|
HighbdDcLeftPredictor(dst, stride, 16, above, left, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void HighbdDcLeftPredictor32x32(ushort* dst, int stride, ushort* above, ushort* left, int bd)
|
public static unsafe void HighbdDcLeftPredictor32x32(ushort* dst, int stride, ushort* above, ushort* left,
|
||||||
|
int bd)
|
||||||
{
|
{
|
||||||
HighbdDcLeftPredictor(dst, stride, 32, above, left, bd);
|
HighbdDcLeftPredictor(dst, stride, 32, above, left, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe void HighbdDcLeftPredictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, int bd)
|
private static unsafe void HighbdDcLeftPredictor(ushort* dst, int stride, int bs, ushort* above, ushort* left,
|
||||||
|
int bd)
|
||||||
{
|
{
|
||||||
int i, r, expectedDc, sum = 0;
|
int expectedDc, sum = 0;
|
||||||
|
|
||||||
for (i = 0; i < bs; i++)
|
for (int i = 0; i < bs; i++)
|
||||||
{
|
{
|
||||||
sum += left[i];
|
sum += left[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedDc = (sum + (bs >> 1)) / bs;
|
expectedDc = (sum + (bs >> 1)) / bs;
|
||||||
|
|
||||||
for (r = 0; r < bs; r++)
|
for (int r = 0; r < bs; r++)
|
||||||
{
|
{
|
||||||
MemoryUtil.Fill(dst, (ushort)expectedDc, bs);
|
MemoryUtil.Fill(dst, (ushort)expectedDc, bs);
|
||||||
dst += stride;
|
dst += stride;
|
||||||
|
@ -1185,28 +1183,31 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
HighbdDcTopPredictor(dst, stride, 8, above, left, bd);
|
HighbdDcTopPredictor(dst, stride, 8, above, left, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void HighbdDcTopPredictor16x16(ushort* dst, int stride, ushort* above, ushort* left, int bd)
|
public static unsafe void HighbdDcTopPredictor16x16(ushort* dst, int stride, ushort* above, ushort* left,
|
||||||
|
int bd)
|
||||||
{
|
{
|
||||||
HighbdDcTopPredictor(dst, stride, 16, above, left, bd);
|
HighbdDcTopPredictor(dst, stride, 16, above, left, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void HighbdDcTopPredictor32x32(ushort* dst, int stride, ushort* above, ushort* left, int bd)
|
public static unsafe void HighbdDcTopPredictor32x32(ushort* dst, int stride, ushort* above, ushort* left,
|
||||||
|
int bd)
|
||||||
{
|
{
|
||||||
HighbdDcTopPredictor(dst, stride, 32, above, left, bd);
|
HighbdDcTopPredictor(dst, stride, 32, above, left, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe void HighbdDcTopPredictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, int bd)
|
private static unsafe void HighbdDcTopPredictor(ushort* dst, int stride, int bs, ushort* above, ushort* left,
|
||||||
|
int bd)
|
||||||
{
|
{
|
||||||
int i, r, expectedDc, sum = 0;
|
int expectedDc, sum = 0;
|
||||||
|
|
||||||
for (i = 0; i < bs; i++)
|
for (int i = 0; i < bs; i++)
|
||||||
{
|
{
|
||||||
sum += above[i];
|
sum += above[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedDc = (sum + (bs >> 1)) / bs;
|
expectedDc = (sum + (bs >> 1)) / bs;
|
||||||
|
|
||||||
for (r = 0; r < bs; r++)
|
for (int r = 0; r < bs; r++)
|
||||||
{
|
{
|
||||||
MemoryUtil.Fill(dst, (ushort)expectedDc, bs);
|
MemoryUtil.Fill(dst, (ushort)expectedDc, bs);
|
||||||
dst += stride;
|
dst += stride;
|
||||||
|
@ -1233,12 +1234,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
HighbdDcPredictor(dst, stride, 32, above, left, bd);
|
HighbdDcPredictor(dst, stride, 32, above, left, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe void HighbdDcPredictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, int bd)
|
private static unsafe void HighbdDcPredictor(ushort* dst, int stride, int bs, ushort* above, ushort* left,
|
||||||
|
int bd)
|
||||||
{
|
{
|
||||||
int i, r, expectedDc, sum = 0;
|
int expectedDc, sum = 0;
|
||||||
int count = 2 * bs;
|
int count = 2 * bs;
|
||||||
|
|
||||||
for (i = 0; i < bs; i++)
|
for (int i = 0; i < bs; i++)
|
||||||
{
|
{
|
||||||
sum += above[i];
|
sum += above[i];
|
||||||
sum += left[i];
|
sum += left[i];
|
||||||
|
@ -1246,7 +1248,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
|
|
||||||
expectedDc = (sum + (count >> 1)) / count;
|
expectedDc = (sum + (count >> 1)) / count;
|
||||||
|
|
||||||
for (r = 0; r < bs; r++)
|
for (int r = 0; r < bs; r++)
|
||||||
{
|
{
|
||||||
MemoryUtil.Fill(dst, (ushort)expectedDc, bs);
|
MemoryUtil.Fill(dst, (ushort)expectedDc, bs);
|
||||||
dst += stride;
|
dst += stride;
|
||||||
|
@ -1265,7 +1267,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
Dst(dst, stride, 1, 0) = Avg3(I, j, k);
|
Dst(dst, stride, 1, 0) = Avg3(I, j, k);
|
||||||
Dst(dst, stride, 3, 0) = Dst(dst, stride, 1, 1) = Avg3(j, k, l);
|
Dst(dst, stride, 3, 0) = Dst(dst, stride, 1, 1) = Avg3(j, k, l);
|
||||||
Dst(dst, stride, 3, 1) = Dst(dst, stride, 1, 2) = Avg3(k, l, l);
|
Dst(dst, stride, 3, 1) = Dst(dst, stride, 1, 2) = Avg3(k, l, l);
|
||||||
Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 0, 3) = Dst(dst, stride, 1, 3) = Dst(dst, stride, 2, 3) = Dst(dst, stride, 3, 3) = l;
|
Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 0, 3) =
|
||||||
|
Dst(dst, stride, 1, 3) = Dst(dst, stride, 2, 3) = Dst(dst, stride, 3, 3) = l;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void HighbdD63Predictor4x4(ushort* dst, int stride, ushort* above, ushort* left, int bd)
|
public static unsafe void HighbdD63Predictor4x4(ushort* dst, int stride, ushort* above, ushort* left, int bd)
|
||||||
|
@ -1303,7 +1306,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
Dst(dst, stride, 0, 0) = Avg3(a, b, c);
|
Dst(dst, stride, 0, 0) = Avg3(a, b, c);
|
||||||
Dst(dst, stride, 1, 0) = Dst(dst, stride, 0, 1) = Avg3(b, c, d);
|
Dst(dst, stride, 1, 0) = Dst(dst, stride, 0, 1) = Avg3(b, c, d);
|
||||||
Dst(dst, stride, 2, 0) = Dst(dst, stride, 1, 1) = Dst(dst, stride, 0, 2) = Avg3(c, d, e);
|
Dst(dst, stride, 2, 0) = Dst(dst, stride, 1, 1) = Dst(dst, stride, 0, 2) = Avg3(c, d, e);
|
||||||
Dst(dst, stride, 3, 0) = Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 2) = Dst(dst, stride, 0, 3) = Avg3(d, e, f);
|
Dst(dst, stride, 3, 0) =
|
||||||
|
Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 2) = Dst(dst, stride, 0, 3) = Avg3(d, e, f);
|
||||||
Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 1, 3) = Avg3(e, f, g);
|
Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 1, 3) = Avg3(e, f, g);
|
||||||
Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 3) = Avg3(f, g, h);
|
Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 3) = Avg3(f, g, h);
|
||||||
Dst(dst, stride, 3, 3) = h; // Differs from vp8
|
Dst(dst, stride, 3, 3) = h; // Differs from vp8
|
||||||
|
@ -1346,7 +1350,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
Dst(dst, stride, 0, 3) = Avg3(j, k, l);
|
Dst(dst, stride, 0, 3) = Avg3(j, k, l);
|
||||||
Dst(dst, stride, 1, 3) = Dst(dst, stride, 0, 2) = Avg3(I, j, k);
|
Dst(dst, stride, 1, 3) = Dst(dst, stride, 0, 2) = Avg3(I, j, k);
|
||||||
Dst(dst, stride, 2, 3) = Dst(dst, stride, 1, 2) = Dst(dst, stride, 0, 1) = Avg3(x, I, j);
|
Dst(dst, stride, 2, 3) = Dst(dst, stride, 1, 2) = Dst(dst, stride, 0, 1) = Avg3(x, I, j);
|
||||||
Dst(dst, stride, 3, 3) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 1, 1) = Dst(dst, stride, 0, 0) = Avg3(a, x, I);
|
Dst(dst, stride, 3, 3) =
|
||||||
|
Dst(dst, stride, 2, 2) = Dst(dst, stride, 1, 1) = Dst(dst, stride, 0, 0) = Avg3(a, x, I);
|
||||||
Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 0) = Avg3(b, a, x);
|
Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 0) = Avg3(b, a, x);
|
||||||
Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 0) = Avg3(c, b, a);
|
Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 0) = Avg3(c, b, a);
|
||||||
Dst(dst, stride, 3, 0) = Avg3(d, c, b);
|
Dst(dst, stride, 3, 0) = Avg3(d, c, b);
|
||||||
|
|
File diff suppressed because it is too large
Load diff
229
src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterAuto.cs
Normal file
229
src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterAuto.cs
Normal file
|
@ -0,0 +1,229 @@
|
||||||
|
using Ryujinx.Common.Memory;
|
||||||
|
using System;
|
||||||
|
using System.Runtime.Intrinsics.X86;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
|
{
|
||||||
|
internal class LoopFilterAuto
|
||||||
|
{
|
||||||
|
public static void LpfHorizontal4(
|
||||||
|
ArrayPtr<byte> s,
|
||||||
|
int pitch,
|
||||||
|
ReadOnlySpan<byte> blimit,
|
||||||
|
ReadOnlySpan<byte> limit,
|
||||||
|
ReadOnlySpan<byte> thresh)
|
||||||
|
{
|
||||||
|
if (Sse2.IsSupported)
|
||||||
|
{
|
||||||
|
LoopFilterSse2.LpfHorizontal4(s, pitch, blimit, limit, thresh);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LoopFilterScalar.LpfHorizontal4(s, pitch, blimit[0], limit[0], thresh[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LpfHorizontal4Dual(
|
||||||
|
ArrayPtr<byte> s,
|
||||||
|
int pitch,
|
||||||
|
ReadOnlySpan<byte> blimit0,
|
||||||
|
ReadOnlySpan<byte> limit0,
|
||||||
|
ReadOnlySpan<byte> thresh0,
|
||||||
|
ReadOnlySpan<byte> blimit1,
|
||||||
|
ReadOnlySpan<byte> limit1,
|
||||||
|
ReadOnlySpan<byte> thresh1)
|
||||||
|
{
|
||||||
|
if (Sse2.IsSupported)
|
||||||
|
{
|
||||||
|
LoopFilterSse2.LpfHorizontal4Dual(s, pitch, blimit0, limit0, thresh0, blimit1, limit1, thresh1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LoopFilterScalar.LpfHorizontal4Dual(s, pitch, blimit0[0], limit0[0], thresh0[0], blimit1[0], limit1[0],
|
||||||
|
thresh1[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LpfHorizontal8(
|
||||||
|
ArrayPtr<byte> s,
|
||||||
|
int pitch,
|
||||||
|
ReadOnlySpan<byte> blimit,
|
||||||
|
ReadOnlySpan<byte> limit,
|
||||||
|
ReadOnlySpan<byte> thresh)
|
||||||
|
{
|
||||||
|
if (Sse2.IsSupported)
|
||||||
|
{
|
||||||
|
LoopFilterSse2.LpfHorizontal8(s, pitch, blimit, limit, thresh);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LoopFilterScalar.LpfHorizontal8(s, pitch, blimit[0], limit[0], thresh[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LpfHorizontal8Dual(
|
||||||
|
ArrayPtr<byte> s,
|
||||||
|
int pitch,
|
||||||
|
ReadOnlySpan<byte> blimit0,
|
||||||
|
ReadOnlySpan<byte> limit0,
|
||||||
|
ReadOnlySpan<byte> thresh0,
|
||||||
|
ReadOnlySpan<byte> blimit1,
|
||||||
|
ReadOnlySpan<byte> limit1,
|
||||||
|
ReadOnlySpan<byte> thresh1)
|
||||||
|
{
|
||||||
|
if (Sse2.IsSupported)
|
||||||
|
{
|
||||||
|
LoopFilterSse2.LpfHorizontal8Dual(s, pitch, blimit0, limit0, thresh0, blimit1, limit1, thresh1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LoopFilterScalar.LpfHorizontal8Dual(s, pitch, blimit0[0], limit0[0], thresh0[0], blimit1[0], limit1[0],
|
||||||
|
thresh1[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LpfHorizontal16(
|
||||||
|
ArrayPtr<byte> s,
|
||||||
|
int pitch,
|
||||||
|
ReadOnlySpan<byte> blimit,
|
||||||
|
ReadOnlySpan<byte> limit,
|
||||||
|
ReadOnlySpan<byte> thresh)
|
||||||
|
{
|
||||||
|
if (Sse2.IsSupported)
|
||||||
|
{
|
||||||
|
LoopFilterSse2.LpfHorizontal16(s, pitch, blimit, limit, thresh);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LoopFilterScalar.LpfHorizontal16(s, pitch, blimit[0], limit[0], thresh[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LpfHorizontal16Dual(
|
||||||
|
ArrayPtr<byte> s,
|
||||||
|
int pitch,
|
||||||
|
ReadOnlySpan<byte> blimit,
|
||||||
|
ReadOnlySpan<byte> limit,
|
||||||
|
ReadOnlySpan<byte> thresh)
|
||||||
|
{
|
||||||
|
if (Sse2.IsSupported)
|
||||||
|
{
|
||||||
|
LoopFilterSse2.LpfHorizontal16Dual(s, pitch, blimit, limit, thresh);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LoopFilterScalar.LpfHorizontal16Dual(s, pitch, blimit[0], limit[0], thresh[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LpfVertical4(
|
||||||
|
ArrayPtr<byte> s,
|
||||||
|
int pitch,
|
||||||
|
ReadOnlySpan<byte> blimit,
|
||||||
|
ReadOnlySpan<byte> limit,
|
||||||
|
ReadOnlySpan<byte> thresh)
|
||||||
|
{
|
||||||
|
if (Sse2.IsSupported)
|
||||||
|
{
|
||||||
|
LoopFilterSse2.LpfVertical4(s, pitch, blimit, limit, thresh);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LoopFilterScalar.LpfVertical4(s, pitch, blimit[0], limit[0], thresh[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LpfVertical4Dual(
|
||||||
|
ArrayPtr<byte> s,
|
||||||
|
int pitch,
|
||||||
|
ReadOnlySpan<byte> blimit0,
|
||||||
|
ReadOnlySpan<byte> limit0,
|
||||||
|
ReadOnlySpan<byte> thresh0,
|
||||||
|
ReadOnlySpan<byte> blimit1,
|
||||||
|
ReadOnlySpan<byte> limit1,
|
||||||
|
ReadOnlySpan<byte> thresh1)
|
||||||
|
{
|
||||||
|
if (Sse2.IsSupported)
|
||||||
|
{
|
||||||
|
LoopFilterSse2.LpfVertical4Dual(s, pitch, blimit0, limit0, thresh0, blimit1, limit1, thresh1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LoopFilterScalar.LpfVertical4Dual(s, pitch, blimit0[0], limit0[0], thresh0[0], blimit1[0], limit1[0],
|
||||||
|
thresh1[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LpfVertical8(
|
||||||
|
ArrayPtr<byte> s,
|
||||||
|
int pitch,
|
||||||
|
ReadOnlySpan<byte> blimit,
|
||||||
|
ReadOnlySpan<byte> limit,
|
||||||
|
ReadOnlySpan<byte> thresh)
|
||||||
|
{
|
||||||
|
if (Sse2.IsSupported)
|
||||||
|
{
|
||||||
|
LoopFilterSse2.LpfVertical8(s, pitch, blimit, limit, thresh);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LoopFilterScalar.LpfVertical8(s, pitch, blimit[0], limit[0], thresh[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LpfVertical8Dual(
|
||||||
|
ArrayPtr<byte> s,
|
||||||
|
int pitch,
|
||||||
|
ReadOnlySpan<byte> blimit0,
|
||||||
|
ReadOnlySpan<byte> limit0,
|
||||||
|
ReadOnlySpan<byte> thresh0,
|
||||||
|
ReadOnlySpan<byte> blimit1,
|
||||||
|
ReadOnlySpan<byte> limit1,
|
||||||
|
ReadOnlySpan<byte> thresh1)
|
||||||
|
{
|
||||||
|
if (Sse2.IsSupported)
|
||||||
|
{
|
||||||
|
LoopFilterSse2.LpfVertical8Dual(s, pitch, blimit0, limit0, thresh0, blimit1, limit1, thresh1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LoopFilterScalar.LpfVertical8Dual(s, pitch, blimit0[0], limit0[0], thresh0[0], blimit1[0], limit1[0],
|
||||||
|
thresh1[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LpfVertical16(
|
||||||
|
ArrayPtr<byte> s,
|
||||||
|
int pitch,
|
||||||
|
ReadOnlySpan<byte> blimit,
|
||||||
|
ReadOnlySpan<byte> limit,
|
||||||
|
ReadOnlySpan<byte> thresh)
|
||||||
|
{
|
||||||
|
if (Sse2.IsSupported)
|
||||||
|
{
|
||||||
|
LoopFilterSse2.LpfVertical16(s, pitch, blimit, limit, thresh);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LoopFilterScalar.LpfVertical16(s, pitch, blimit[0], limit[0], thresh[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LpfVertical16Dual(
|
||||||
|
ArrayPtr<byte> s,
|
||||||
|
int pitch,
|
||||||
|
ReadOnlySpan<byte> blimit,
|
||||||
|
ReadOnlySpan<byte> limit,
|
||||||
|
ReadOnlySpan<byte> thresh)
|
||||||
|
{
|
||||||
|
if (Sse2.IsSupported)
|
||||||
|
{
|
||||||
|
LoopFilterSse2.LpfVertical16Dual(s, pitch, blimit, limit, thresh);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LoopFilterScalar.LpfVertical16Dual(s, pitch, blimit[0], limit[0], thresh[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1093
src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterScalar.cs
Normal file
1093
src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterScalar.cs
Normal file
File diff suppressed because it is too large
Load diff
1837
src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterSse2.cs
Normal file
1837
src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterSse2.cs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -12,7 +12,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
{
|
{
|
||||||
Debug.Assert(den != 0);
|
Debug.Assert(den != 0);
|
||||||
{
|
{
|
||||||
int p = (int)(((ulong)num * 256 + (den >> 1)) / den);
|
int p = (int)((((ulong)num * 256) + (den >> 1)) / den);
|
||||||
// (p > 255) ? 255 : (p < 1) ? 1 : p;
|
// (p > 255) ? 255 : (p < 1) ? 1 : p;
|
||||||
int clippedProb = p | ((255 - p) >> 23) | (p == 0 ? 1 : 0);
|
int clippedProb = p | ((255 - p) >> 23) | (p == 0 ? 1 : 0);
|
||||||
return (byte)clippedProb;
|
return (byte)clippedProb;
|
||||||
|
@ -22,14 +22,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
/* This function assumes prob1 and prob2 are already within [1,255] range. */
|
/* This function assumes prob1 and prob2 are already within [1,255] range. */
|
||||||
public static byte WeightedProb(int prob1, int prob2, int factor)
|
public static byte WeightedProb(int prob1, int prob2, int factor)
|
||||||
{
|
{
|
||||||
return (byte)BitUtils.RoundPowerOfTwo(prob1 * (256 - factor) + prob2 * factor, 8);
|
return (byte)BitUtils.RoundPowerOfTwo((prob1 * (256 - factor)) + (prob2 * factor), 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
// MODE_MV_MAX_UPDATE_FACTOR (128) * count / MODE_MV_COUNT_SAT;
|
// MODE_MV_MAX_UPDATE_FACTOR (128) * count / MODE_MV_COUNT_SAT;
|
||||||
private static readonly uint[] CountToUpdateFactor = new uint[]
|
private static readonly uint[] CountToUpdateFactor =
|
||||||
{
|
{
|
||||||
0, 6, 12, 19, 25, 32, 38, 44, 51, 57, 64,
|
0, 6, 12, 19, 25, 32, 38, 44, 51, 57, 64, 70, 76, 83, 89, 96, 102, 108, 115, 121, 128
|
||||||
70, 76, 83, 89, 96, 102, 108, 115, 121, 128
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private const int ModeMvCountSat = 20;
|
private const int ModeMvCountSat = 20;
|
||||||
|
@ -41,14 +40,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
{
|
{
|
||||||
return preProb;
|
return preProb;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
uint count = Math.Min(den, ModeMvCountSat);
|
uint count = Math.Min(den, ModeMvCountSat);
|
||||||
uint factor = CountToUpdateFactor[(int)count];
|
uint factor = CountToUpdateFactor[(int)count];
|
||||||
byte prob = GetProb(ct0, den);
|
byte prob = GetProb(ct0, den);
|
||||||
return WeightedProb(preProb, prob, (int)factor);
|
return WeightedProb(preProb, prob, (int)factor);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static uint TreeMergeProbsImpl(
|
private static uint TreeMergeProbsImpl(
|
||||||
uint i,
|
uint i,
|
||||||
|
@ -58,14 +55,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
Span<byte> probs)
|
Span<byte> probs)
|
||||||
{
|
{
|
||||||
int l = tree[i];
|
int l = tree[i];
|
||||||
uint leftCount = (l <= 0) ? counts[-l] : TreeMergeProbsImpl((uint)l, tree, preProbs, counts, probs);
|
uint leftCount = l <= 0 ? counts[-l] : TreeMergeProbsImpl((uint)l, tree, preProbs, counts, probs);
|
||||||
int r = tree[i + 1];
|
int r = tree[i + 1];
|
||||||
uint rightCount = (r <= 0) ? counts[-r] : TreeMergeProbsImpl((uint)r, tree, preProbs, counts, probs);
|
uint rightCount = r <= 0 ? counts[-r] : TreeMergeProbsImpl((uint)r, tree, preProbs, counts, probs);
|
||||||
probs[(int)(i >> 1)] = ModeMvMergeProbs(preProbs[(int)(i >> 1)], leftCount, rightCount);
|
probs[(int)(i >> 1)] = ModeMvMergeProbs(preProbs[(int)(i >> 1)], leftCount, rightCount);
|
||||||
return leftCount + rightCount;
|
return leftCount + rightCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void TreeMergeProbs(sbyte[] tree, ReadOnlySpan<byte> preProbs, ReadOnlySpan<uint> counts, Span<byte> probs)
|
public static void TreeMergeProbs(sbyte[] tree, ReadOnlySpan<byte> preProbs, ReadOnlySpan<uint> counts,
|
||||||
|
Span<byte> probs)
|
||||||
{
|
{
|
||||||
TreeMergeProbsImpl(0, tree, preProbs, counts, probs);
|
TreeMergeProbsImpl(0, tree, preProbs, counts, probs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
|
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
||||||
using System;
|
using System;
|
||||||
using System.Buffers.Binary;
|
using System.Buffers.Binary;
|
||||||
|
|
||||||
|
@ -6,19 +7,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
{
|
{
|
||||||
internal struct Reader
|
internal struct Reader
|
||||||
{
|
{
|
||||||
private static readonly byte[] Norm = new byte[]
|
private static readonly byte[] Norm =
|
||||||
{
|
{
|
||||||
0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2,
|
||||||
3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1,
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private const int BdValueSize = sizeof(ulong) * 8;
|
private const int BdValueSize = sizeof(ulong) * 8;
|
||||||
|
|
||||||
// This is meant to be a large, positive constant that can still be efficiently
|
// This is meant to be a large, positive constant that can still be efficiently
|
||||||
|
@ -37,8 +37,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
_buffer = new ArrayPtr<byte>(ref buffer[0], size);
|
_buffer = new ArrayPtr<byte>(ref buffer[0], size);
|
||||||
Value = 0;
|
Value = 0;
|
||||||
Count = -8;
|
Count = -8;
|
||||||
|
@ -46,7 +45,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
Fill();
|
Fill();
|
||||||
return ReadBit() != 0; // Marker bit
|
return ReadBit() != 0; // Marker bit
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void Fill()
|
private void Fill()
|
||||||
{
|
{
|
||||||
|
@ -124,7 +122,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
ulong bigsplit;
|
ulong bigsplit;
|
||||||
int count;
|
int count;
|
||||||
uint range;
|
uint range;
|
||||||
uint split = (Range * (uint)prob + (256 - (uint)prob)) >> 8;
|
uint split = ((Range * (uint)prob) + (256 - (uint)prob)) >> 8;
|
||||||
|
|
||||||
if (Count < 0)
|
if (Count < 0)
|
||||||
{
|
{
|
||||||
|
@ -181,7 +179,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
|
|
||||||
while ((i = tree[i + Read(probs[i >> 1])]) > 0)
|
while ((i = tree[i + Read(probs[i >> 1])]) > 0)
|
||||||
{
|
{
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return -i;
|
return -i;
|
||||||
|
@ -189,7 +186,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
|
|
||||||
public int ReadBool(int prob, ref ulong value, ref int count, ref uint range)
|
public int ReadBool(int prob, ref ulong value, ref int count, ref uint range)
|
||||||
{
|
{
|
||||||
uint split = (range * (uint)prob + (256 - (uint)prob)) >> 8;
|
uint split = ((range * (uint)prob) + (256 - (uint)prob)) >> 8;
|
||||||
ulong bigsplit = (ulong)split << (BdValueSize - 8);
|
ulong bigsplit = (ulong)split << (BdValueSize - 8);
|
||||||
|
|
||||||
if (count < 0)
|
if (count < 0)
|
||||||
|
@ -213,6 +210,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
range = split;
|
range = split;
|
||||||
{
|
{
|
||||||
int shift = Norm[range];
|
int shift = Norm[range];
|
||||||
|
@ -231,7 +229,82 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
Count -= 8;
|
Count -= 8;
|
||||||
_buffer = _buffer.Slice(-1);
|
_buffer = _buffer.Slice(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return _buffer;
|
return _buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int DecodeUniform()
|
||||||
|
{
|
||||||
|
const int l = 8;
|
||||||
|
const int m = (1 << l) - 191;
|
||||||
|
int v = ReadLiteral(l - 1);
|
||||||
|
return v < m ? v : (v << 1) - m + ReadBit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int DecodeTermSubexp()
|
||||||
|
{
|
||||||
|
if (ReadBit() == 0)
|
||||||
|
{
|
||||||
|
return ReadLiteral(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ReadBit() == 0)
|
||||||
|
{
|
||||||
|
return ReadLiteral(4) + 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ReadBit() == 0)
|
||||||
|
{
|
||||||
|
return ReadLiteral(5) + 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DecodeUniform() + 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TxMode ReadTxMode()
|
||||||
|
{
|
||||||
|
TxMode txMode = (TxMode)ReadLiteral(2);
|
||||||
|
if (txMode == TxMode.Allow32x32)
|
||||||
|
{
|
||||||
|
txMode += ReadBit();
|
||||||
|
}
|
||||||
|
|
||||||
|
return txMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ReadCoeff(
|
||||||
|
ReadOnlySpan<byte> probs,
|
||||||
|
int n,
|
||||||
|
ref ulong value,
|
||||||
|
ref int count,
|
||||||
|
ref uint range)
|
||||||
|
{
|
||||||
|
int val = 0;
|
||||||
|
for (int i = 0; i < n; ++i)
|
||||||
|
{
|
||||||
|
val = (val << 1) | ReadBool(probs[i], ref value, ref count, ref range);
|
||||||
|
}
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DiffUpdateProb(ref byte p)
|
||||||
|
{
|
||||||
|
if (Read(Entropy.DiffUpdateProb) != 0)
|
||||||
|
{
|
||||||
|
p = (byte)DSubExp.InvRemapProb(DecodeTermSubexp(), p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateMvProbs(Span<byte> p, int n)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < n; ++i)
|
||||||
|
{
|
||||||
|
if (Read(EntropyMv.UpdateProb) != 0)
|
||||||
|
{
|
||||||
|
p[i] = (byte)((ReadLiteral(7) << 1) | 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -13,42 +13,42 @@
|
||||||
// for (int i = 1; i < 32; ++i)
|
// for (int i = 1; i < 32; ++i)
|
||||||
// Console.WriteLine("public const short CosPi{0}_64 = {1};", i, MathF.Round(16384 * MathF.Cos(i * MathF.PI / 64)));
|
// Console.WriteLine("public const short CosPi{0}_64 = {1};", i, MathF.Round(16384 * MathF.Cos(i * MathF.PI / 64)));
|
||||||
// Note: sin(k * Pi / 64) = cos((32 - k) * Pi / 64)
|
// Note: sin(k * Pi / 64) = cos((32 - k) * Pi / 64)
|
||||||
public const short CosPi1_64 = 16364;
|
public const short CosPi164 = 16364;
|
||||||
public const short CosPi2_64 = 16305;
|
public const short CosPi264 = 16305;
|
||||||
public const short CosPi3_64 = 16207;
|
public const short CosPi364 = 16207;
|
||||||
public const short CosPi4_64 = 16069;
|
public const short CosPi464 = 16069;
|
||||||
public const short CosPi5_64 = 15893;
|
public const short CosPi564 = 15893;
|
||||||
public const short CosPi6_64 = 15679;
|
public const short CosPi664 = 15679;
|
||||||
public const short CosPi7_64 = 15426;
|
public const short CosPi764 = 15426;
|
||||||
public const short CosPi8_64 = 15137;
|
public const short CosPi864 = 15137;
|
||||||
public const short CosPi9_64 = 14811;
|
public const short CosPi964 = 14811;
|
||||||
public const short CosPi10_64 = 14449;
|
public const short CosPi1064 = 14449;
|
||||||
public const short CosPi11_64 = 14053;
|
public const short CosPi1164 = 14053;
|
||||||
public const short CosPi12_64 = 13623;
|
public const short CosPi1264 = 13623;
|
||||||
public const short CosPi13_64 = 13160;
|
public const short CosPi1364 = 13160;
|
||||||
public const short CosPi14_64 = 12665;
|
public const short CosPi1464 = 12665;
|
||||||
public const short CosPi15_64 = 12140;
|
public const short CosPi1564 = 12140;
|
||||||
public const short CosPi16_64 = 11585;
|
public const short CosPi1664 = 11585;
|
||||||
public const short CosPi17_64 = 11003;
|
public const short CosPi1764 = 11003;
|
||||||
public const short CosPi18_64 = 10394;
|
public const short CosPi1864 = 10394;
|
||||||
public const short CosPi19_64 = 9760;
|
public const short CosPi1964 = 9760;
|
||||||
public const short CosPi20_64 = 9102;
|
public const short CosPi2064 = 9102;
|
||||||
public const short CosPi21_64 = 8423;
|
public const short CosPi2164 = 8423;
|
||||||
public const short CosPi22_64 = 7723;
|
public const short CosPi2264 = 7723;
|
||||||
public const short CosPi23_64 = 7005;
|
public const short CosPi2364 = 7005;
|
||||||
public const short CosPi24_64 = 6270;
|
public const short CosPi2464 = 6270;
|
||||||
public const short CosPi25_64 = 5520;
|
public const short CosPi2564 = 5520;
|
||||||
public const short CosPi26_64 = 4756;
|
public const short CosPi2664 = 4756;
|
||||||
public const short CosPi27_64 = 3981;
|
public const short CosPi2764 = 3981;
|
||||||
public const short CosPi28_64 = 3196;
|
public const short CosPi2864 = 3196;
|
||||||
public const short CosPi29_64 = 2404;
|
public const short CosPi2964 = 2404;
|
||||||
public const short CosPi30_64 = 1606;
|
public const short CosPi3064 = 1606;
|
||||||
public const short CosPi31_64 = 804;
|
public const short CosPi3164 = 804;
|
||||||
|
|
||||||
// 16384 * sqrt(2) * sin(kPi / 9) * 2 / 3
|
// 16384 * sqrt(2) * sin(kPi / 9) * 2 / 3
|
||||||
public const short SinPi1_9 = 5283;
|
public const short SinPi19 = 5283;
|
||||||
public const short SinPi2_9 = 9929;
|
public const short SinPi29 = 9929;
|
||||||
public const short SinPi3_9 = 13377;
|
public const short SinPi39 = 13377;
|
||||||
public const short SinPi4_9 = 15212;
|
public const short SinPi49 = 15212;
|
||||||
}
|
}
|
||||||
}
|
}
|
623
src/Ryujinx.Graphics.Nvdec.Vp9/Entropy.cs
Normal file
623
src/Ryujinx.Graphics.Nvdec.Vp9/Entropy.cs
Normal file
|
@ -0,0 +1,623 @@
|
||||||
|
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
||||||
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
{
|
||||||
|
internal static class Entropy
|
||||||
|
{
|
||||||
|
public const int DiffUpdateProb = 252;
|
||||||
|
|
||||||
|
// Coefficient token alphabet
|
||||||
|
public const int ZeroToken = 0; // 0 Extra Bits 0+0
|
||||||
|
public const int OneToken = 1; // 1 Extra Bits 0+1
|
||||||
|
public const int TwoToken = 2; // 2 Extra Bits 0+1
|
||||||
|
public const int ThreeToken = 3; // 3 Extra Bits 0+1
|
||||||
|
public const int FourToken = 4; // 4 Extra Bits 0+1
|
||||||
|
public const int Category1Token = 5; // 5-6 Extra Bits 1+1
|
||||||
|
public const int Category2Token = 6; // 7-10 Extra Bits 2+1
|
||||||
|
public const int Category3Token = 7; // 11-18 Extra Bits 3+1
|
||||||
|
public const int Category4Token = 8; // 19-34 Extra Bits 4+1
|
||||||
|
public const int Category5Token = 9; // 35-66 Extra Bits 5+1
|
||||||
|
public const int Category6Token = 10; // 67+ Extra Bits 14+1
|
||||||
|
public const int EobToken = 11; // EOB Extra Bits 0+0
|
||||||
|
|
||||||
|
public const int EntropyTokens = 12;
|
||||||
|
|
||||||
|
public const int RefTypes = 2; // intra=0, inter=1
|
||||||
|
|
||||||
|
/* Middle dimension reflects the coefficient position within the transform. */
|
||||||
|
public const int CoefBands = 6;
|
||||||
|
|
||||||
|
/* Inside dimension is measure of nearby complexity, that reflects the energy
|
||||||
|
of nearby coefficients are nonzero. For the first coefficient (DC, unless
|
||||||
|
block type is 0), we look at the (already encoded) blocks above and to the
|
||||||
|
left of the current block. The context index is then the number (0,1,or 2)
|
||||||
|
of these blocks having nonzero coefficients.
|
||||||
|
After decoding a coefficient, the measure is determined by the size of the
|
||||||
|
most recently decoded coefficient.
|
||||||
|
Note that the intuitive meaning of this measure changes as coefficients
|
||||||
|
are decoded, e.g., prior to the first token, a zero means that my neighbors
|
||||||
|
are empty while, after the first token, because of the use of end-of-block,
|
||||||
|
a zero means we just decoded a zero and hence guarantees that a non-zero
|
||||||
|
coefficient will appear later in this block. However, this shift
|
||||||
|
in meaning is perfectly OK because our context depends also on the
|
||||||
|
coefficient band (and since zigzag positions 0, 1, and 2 are in
|
||||||
|
distinct bands). */
|
||||||
|
|
||||||
|
public const int CoeffContexts = 6;
|
||||||
|
|
||||||
|
public static int BAND_COEFF_CONTEXTS(int band)
|
||||||
|
{
|
||||||
|
return band == 0 ? 3 : CoeffContexts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public const int UnconstrainedNodes = 3;
|
||||||
|
|
||||||
|
public const int PivotNode = 2;
|
||||||
|
|
||||||
|
public const int Cat1MinVal = 5;
|
||||||
|
public const int Cat2MinVal = 7;
|
||||||
|
public const int Cat3MinVal = 11;
|
||||||
|
public const int Cat4MinVal = 19;
|
||||||
|
public const int Cat5MinVal = 35;
|
||||||
|
public const int Cat6MinVal = 67;
|
||||||
|
|
||||||
|
public static readonly byte[] Cat1Prob = { 159 };
|
||||||
|
public static readonly byte[] Cat2Prob = { 165, 145 };
|
||||||
|
public static readonly byte[] Cat3Prob = { 173, 148, 140 };
|
||||||
|
public static readonly byte[] Cat4Prob = { 176, 155, 140, 135 };
|
||||||
|
public static readonly byte[] Cat5Prob = { 180, 157, 141, 134, 130 };
|
||||||
|
|
||||||
|
public static readonly byte[] Cat6Prob =
|
||||||
|
{
|
||||||
|
254, 254, 254, 252, 249, 243, 230, 196, 177, 153, 140, 133, 130, 129
|
||||||
|
};
|
||||||
|
|
||||||
|
public static readonly byte[] Cat6ProbHigh12 =
|
||||||
|
{
|
||||||
|
255, 255, 255, 255, 254, 254, 54, 252, 249, 243, 230, 196, 177, 153, 140, 133, 130, 129
|
||||||
|
};
|
||||||
|
|
||||||
|
public const int EobModelToken = 3;
|
||||||
|
|
||||||
|
private static readonly byte[] CoefbandTrans8x8Plus =
|
||||||
|
{
|
||||||
|
0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5,
|
||||||
|
// beyond MAXBAND_INDEX+1 all values are filled as 5
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly byte[] CoefbandTrans4x4 = { 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5 };
|
||||||
|
|
||||||
|
public static readonly byte[][] Pareto8Full =
|
||||||
|
{
|
||||||
|
new byte[] { 3, 86, 128, 6, 86, 23, 88, 29 }, new byte[] { 6, 86, 128, 11, 87, 42, 91, 52 },
|
||||||
|
new byte[] { 9, 86, 129, 17, 88, 61, 94, 76 }, new byte[] { 12, 86, 129, 22, 88, 77, 97, 93 },
|
||||||
|
new byte[] { 15, 87, 129, 28, 89, 93, 100, 110 }, new byte[] { 17, 87, 129, 33, 90, 105, 103, 123 },
|
||||||
|
new byte[] { 20, 88, 130, 38, 91, 118, 106, 136 }, new byte[] { 23, 88, 130, 43, 91, 128, 108, 146 },
|
||||||
|
new byte[] { 26, 89, 131, 48, 92, 139, 111, 156 }, new byte[] { 28, 89, 131, 53, 93, 147, 114, 163 },
|
||||||
|
new byte[] { 31, 90, 131, 58, 94, 156, 117, 171 }, new byte[] { 34, 90, 131, 62, 94, 163, 119, 177 },
|
||||||
|
new byte[] { 37, 90, 132, 66, 95, 171, 122, 184 }, new byte[] { 39, 90, 132, 70, 96, 177, 124, 189 },
|
||||||
|
new byte[] { 42, 91, 132, 75, 97, 183, 127, 194 }, new byte[] { 44, 91, 132, 79, 97, 188, 129, 198 },
|
||||||
|
new byte[] { 47, 92, 133, 83, 98, 193, 132, 202 }, new byte[] { 49, 92, 133, 86, 99, 197, 134, 205 },
|
||||||
|
new byte[] { 52, 93, 133, 90, 100, 201, 137, 208 }, new byte[] { 54, 93, 133, 94, 100, 204, 139, 211 },
|
||||||
|
new byte[] { 57, 94, 134, 98, 101, 208, 142, 214 }, new byte[] { 59, 94, 134, 101, 102, 211, 144, 216 },
|
||||||
|
new byte[] { 62, 94, 135, 105, 103, 214, 146, 218 },
|
||||||
|
new byte[] { 64, 94, 135, 108, 103, 216, 148, 220 },
|
||||||
|
new byte[] { 66, 95, 135, 111, 104, 219, 151, 222 },
|
||||||
|
new byte[] { 68, 95, 135, 114, 105, 221, 153, 223 },
|
||||||
|
new byte[] { 71, 96, 136, 117, 106, 224, 155, 225 },
|
||||||
|
new byte[] { 73, 96, 136, 120, 106, 225, 157, 226 },
|
||||||
|
new byte[] { 76, 97, 136, 123, 107, 227, 159, 228 },
|
||||||
|
new byte[] { 78, 97, 136, 126, 108, 229, 160, 229 },
|
||||||
|
new byte[] { 80, 98, 137, 129, 109, 231, 162, 231 },
|
||||||
|
new byte[] { 82, 98, 137, 131, 109, 232, 164, 232 },
|
||||||
|
new byte[] { 84, 98, 138, 134, 110, 234, 166, 233 },
|
||||||
|
new byte[] { 86, 98, 138, 137, 111, 235, 168, 234 },
|
||||||
|
new byte[] { 89, 99, 138, 140, 112, 236, 170, 235 },
|
||||||
|
new byte[] { 91, 99, 138, 142, 112, 237, 171, 235 },
|
||||||
|
new byte[] { 93, 100, 139, 145, 113, 238, 173, 236 },
|
||||||
|
new byte[] { 95, 100, 139, 147, 114, 239, 174, 237 },
|
||||||
|
new byte[] { 97, 101, 140, 149, 115, 240, 176, 238 },
|
||||||
|
new byte[] { 99, 101, 140, 151, 115, 241, 177, 238 },
|
||||||
|
new byte[] { 101, 102, 140, 154, 116, 242, 179, 239 },
|
||||||
|
new byte[] { 103, 102, 140, 156, 117, 242, 180, 239 },
|
||||||
|
new byte[] { 105, 103, 141, 158, 118, 243, 182, 240 },
|
||||||
|
new byte[] { 107, 103, 141, 160, 118, 243, 183, 240 },
|
||||||
|
new byte[] { 109, 104, 141, 162, 119, 244, 185, 241 },
|
||||||
|
new byte[] { 111, 104, 141, 164, 119, 244, 186, 241 },
|
||||||
|
new byte[] { 113, 104, 142, 166, 120, 245, 187, 242 },
|
||||||
|
new byte[] { 114, 104, 142, 168, 121, 245, 188, 242 },
|
||||||
|
new byte[] { 116, 105, 143, 170, 122, 246, 190, 243 },
|
||||||
|
new byte[] { 118, 105, 143, 171, 122, 246, 191, 243 },
|
||||||
|
new byte[] { 120, 106, 143, 173, 123, 247, 192, 244 },
|
||||||
|
new byte[] { 121, 106, 143, 175, 124, 247, 193, 244 },
|
||||||
|
new byte[] { 123, 107, 144, 177, 125, 248, 195, 244 },
|
||||||
|
new byte[] { 125, 107, 144, 178, 125, 248, 196, 244 },
|
||||||
|
new byte[] { 127, 108, 145, 180, 126, 249, 197, 245 },
|
||||||
|
new byte[] { 128, 108, 145, 181, 127, 249, 198, 245 },
|
||||||
|
new byte[] { 130, 109, 145, 183, 128, 249, 199, 245 },
|
||||||
|
new byte[] { 132, 109, 145, 184, 128, 249, 200, 245 },
|
||||||
|
new byte[] { 134, 110, 146, 186, 129, 250, 201, 246 },
|
||||||
|
new byte[] { 135, 110, 146, 187, 130, 250, 202, 246 },
|
||||||
|
new byte[] { 137, 111, 147, 189, 131, 251, 203, 246 },
|
||||||
|
new byte[] { 138, 111, 147, 190, 131, 251, 204, 246 },
|
||||||
|
new byte[] { 140, 112, 147, 192, 132, 251, 205, 247 },
|
||||||
|
new byte[] { 141, 112, 147, 193, 132, 251, 206, 247 },
|
||||||
|
new byte[] { 143, 113, 148, 194, 133, 251, 207, 247 },
|
||||||
|
new byte[] { 144, 113, 148, 195, 134, 251, 207, 247 },
|
||||||
|
new byte[] { 146, 114, 149, 197, 135, 252, 208, 248 },
|
||||||
|
new byte[] { 147, 114, 149, 198, 135, 252, 209, 248 },
|
||||||
|
new byte[] { 149, 115, 149, 199, 136, 252, 210, 248 },
|
||||||
|
new byte[] { 150, 115, 149, 200, 137, 252, 210, 248 },
|
||||||
|
new byte[] { 152, 115, 150, 201, 138, 252, 211, 248 },
|
||||||
|
new byte[] { 153, 115, 150, 202, 138, 252, 212, 248 },
|
||||||
|
new byte[] { 155, 116, 151, 204, 139, 253, 213, 249 },
|
||||||
|
new byte[] { 156, 116, 151, 205, 139, 253, 213, 249 },
|
||||||
|
new byte[] { 158, 117, 151, 206, 140, 253, 214, 249 },
|
||||||
|
new byte[] { 159, 117, 151, 207, 141, 253, 215, 249 },
|
||||||
|
new byte[] { 161, 118, 152, 208, 142, 253, 216, 249 },
|
||||||
|
new byte[] { 162, 118, 152, 209, 142, 253, 216, 249 },
|
||||||
|
new byte[] { 163, 119, 153, 210, 143, 253, 217, 249 },
|
||||||
|
new byte[] { 164, 119, 153, 211, 143, 253, 217, 249 },
|
||||||
|
new byte[] { 166, 120, 153, 212, 144, 254, 218, 250 },
|
||||||
|
new byte[] { 167, 120, 153, 212, 145, 254, 219, 250 },
|
||||||
|
new byte[] { 168, 121, 154, 213, 146, 254, 220, 250 },
|
||||||
|
new byte[] { 169, 121, 154, 214, 146, 254, 220, 250 },
|
||||||
|
new byte[] { 171, 122, 155, 215, 147, 254, 221, 250 },
|
||||||
|
new byte[] { 172, 122, 155, 216, 147, 254, 221, 250 },
|
||||||
|
new byte[] { 173, 123, 155, 217, 148, 254, 222, 250 },
|
||||||
|
new byte[] { 174, 123, 155, 217, 149, 254, 222, 250 },
|
||||||
|
new byte[] { 176, 124, 156, 218, 150, 254, 223, 250 },
|
||||||
|
new byte[] { 177, 124, 156, 219, 150, 254, 223, 250 },
|
||||||
|
new byte[] { 178, 125, 157, 220, 151, 254, 224, 251 },
|
||||||
|
new byte[] { 179, 125, 157, 220, 151, 254, 224, 251 },
|
||||||
|
new byte[] { 180, 126, 157, 221, 152, 254, 225, 251 },
|
||||||
|
new byte[] { 181, 126, 157, 221, 152, 254, 225, 251 },
|
||||||
|
new byte[] { 183, 127, 158, 222, 153, 254, 226, 251 },
|
||||||
|
new byte[] { 184, 127, 158, 223, 154, 254, 226, 251 },
|
||||||
|
new byte[] { 185, 128, 159, 224, 155, 255, 227, 251 },
|
||||||
|
new byte[] { 186, 128, 159, 224, 155, 255, 227, 251 },
|
||||||
|
new byte[] { 187, 129, 160, 225, 156, 255, 228, 251 },
|
||||||
|
new byte[] { 188, 130, 160, 225, 156, 255, 228, 251 },
|
||||||
|
new byte[] { 189, 131, 160, 226, 157, 255, 228, 251 },
|
||||||
|
new byte[] { 190, 131, 160, 226, 158, 255, 228, 251 },
|
||||||
|
new byte[] { 191, 132, 161, 227, 159, 255, 229, 251 },
|
||||||
|
new byte[] { 192, 132, 161, 227, 159, 255, 229, 251 },
|
||||||
|
new byte[] { 193, 133, 162, 228, 160, 255, 230, 252 },
|
||||||
|
new byte[] { 194, 133, 162, 229, 160, 255, 230, 252 },
|
||||||
|
new byte[] { 195, 134, 163, 230, 161, 255, 231, 252 },
|
||||||
|
new byte[] { 196, 134, 163, 230, 161, 255, 231, 252 },
|
||||||
|
new byte[] { 197, 135, 163, 231, 162, 255, 231, 252 },
|
||||||
|
new byte[] { 198, 135, 163, 231, 162, 255, 231, 252 },
|
||||||
|
new byte[] { 199, 136, 164, 232, 163, 255, 232, 252 },
|
||||||
|
new byte[] { 200, 136, 164, 232, 164, 255, 232, 252 },
|
||||||
|
new byte[] { 201, 137, 165, 233, 165, 255, 233, 252 },
|
||||||
|
new byte[] { 201, 137, 165, 233, 165, 255, 233, 252 },
|
||||||
|
new byte[] { 202, 138, 166, 233, 166, 255, 233, 252 },
|
||||||
|
new byte[] { 203, 138, 166, 233, 166, 255, 233, 252 },
|
||||||
|
new byte[] { 204, 139, 166, 234, 167, 255, 234, 252 },
|
||||||
|
new byte[] { 205, 139, 166, 234, 167, 255, 234, 252 },
|
||||||
|
new byte[] { 206, 140, 167, 235, 168, 255, 235, 252 },
|
||||||
|
new byte[] { 206, 140, 167, 235, 168, 255, 235, 252 },
|
||||||
|
new byte[] { 207, 141, 168, 236, 169, 255, 235, 252 },
|
||||||
|
new byte[] { 208, 141, 168, 236, 170, 255, 235, 252 },
|
||||||
|
new byte[] { 209, 142, 169, 237, 171, 255, 236, 252 },
|
||||||
|
new byte[] { 209, 143, 169, 237, 171, 255, 236, 252 },
|
||||||
|
new byte[] { 210, 144, 169, 237, 172, 255, 236, 252 },
|
||||||
|
new byte[] { 211, 144, 169, 237, 172, 255, 236, 252 },
|
||||||
|
new byte[] { 212, 145, 170, 238, 173, 255, 237, 252 },
|
||||||
|
new byte[] { 213, 145, 170, 238, 173, 255, 237, 252 },
|
||||||
|
new byte[] { 214, 146, 171, 239, 174, 255, 237, 253 },
|
||||||
|
new byte[] { 214, 146, 171, 239, 174, 255, 237, 253 },
|
||||||
|
new byte[] { 215, 147, 172, 240, 175, 255, 238, 253 },
|
||||||
|
new byte[] { 215, 147, 172, 240, 175, 255, 238, 253 },
|
||||||
|
new byte[] { 216, 148, 173, 240, 176, 255, 238, 253 },
|
||||||
|
new byte[] { 217, 148, 173, 240, 176, 255, 238, 253 },
|
||||||
|
new byte[] { 218, 149, 173, 241, 177, 255, 239, 253 },
|
||||||
|
new byte[] { 218, 149, 173, 241, 178, 255, 239, 253 },
|
||||||
|
new byte[] { 219, 150, 174, 241, 179, 255, 239, 253 },
|
||||||
|
new byte[] { 219, 151, 174, 241, 179, 255, 239, 253 },
|
||||||
|
new byte[] { 220, 152, 175, 242, 180, 255, 240, 253 },
|
||||||
|
new byte[] { 221, 152, 175, 242, 180, 255, 240, 253 },
|
||||||
|
new byte[] { 222, 153, 176, 242, 181, 255, 240, 253 },
|
||||||
|
new byte[] { 222, 153, 176, 242, 181, 255, 240, 253 },
|
||||||
|
new byte[] { 223, 154, 177, 243, 182, 255, 240, 253 },
|
||||||
|
new byte[] { 223, 154, 177, 243, 182, 255, 240, 253 },
|
||||||
|
new byte[] { 224, 155, 178, 244, 183, 255, 241, 253 },
|
||||||
|
new byte[] { 224, 155, 178, 244, 183, 255, 241, 253 },
|
||||||
|
new byte[] { 225, 156, 178, 244, 184, 255, 241, 253 },
|
||||||
|
new byte[] { 225, 157, 178, 244, 184, 255, 241, 253 },
|
||||||
|
new byte[] { 226, 158, 179, 244, 185, 255, 242, 253 },
|
||||||
|
new byte[] { 227, 158, 179, 244, 185, 255, 242, 253 },
|
||||||
|
new byte[] { 228, 159, 180, 245, 186, 255, 242, 253 },
|
||||||
|
new byte[] { 228, 159, 180, 245, 186, 255, 242, 253 },
|
||||||
|
new byte[] { 229, 160, 181, 245, 187, 255, 242, 253 },
|
||||||
|
new byte[] { 229, 160, 181, 245, 187, 255, 242, 253 },
|
||||||
|
new byte[] { 230, 161, 182, 246, 188, 255, 243, 253 },
|
||||||
|
new byte[] { 230, 162, 182, 246, 188, 255, 243, 253 },
|
||||||
|
new byte[] { 231, 163, 183, 246, 189, 255, 243, 253 },
|
||||||
|
new byte[] { 231, 163, 183, 246, 189, 255, 243, 253 },
|
||||||
|
new byte[] { 232, 164, 184, 247, 190, 255, 243, 253 },
|
||||||
|
new byte[] { 232, 164, 184, 247, 190, 255, 243, 253 },
|
||||||
|
new byte[] { 233, 165, 185, 247, 191, 255, 244, 253 },
|
||||||
|
new byte[] { 233, 165, 185, 247, 191, 255, 244, 253 },
|
||||||
|
new byte[] { 234, 166, 185, 247, 192, 255, 244, 253 },
|
||||||
|
new byte[] { 234, 167, 185, 247, 192, 255, 244, 253 },
|
||||||
|
new byte[] { 235, 168, 186, 248, 193, 255, 244, 253 },
|
||||||
|
new byte[] { 235, 168, 186, 248, 193, 255, 244, 253 },
|
||||||
|
new byte[] { 236, 169, 187, 248, 194, 255, 244, 253 },
|
||||||
|
new byte[] { 236, 169, 187, 248, 194, 255, 244, 253 },
|
||||||
|
new byte[] { 236, 170, 188, 248, 195, 255, 245, 253 },
|
||||||
|
new byte[] { 236, 170, 188, 248, 195, 255, 245, 253 },
|
||||||
|
new byte[] { 237, 171, 189, 249, 196, 255, 245, 254 },
|
||||||
|
new byte[] { 237, 172, 189, 249, 196, 255, 245, 254 },
|
||||||
|
new byte[] { 238, 173, 190, 249, 197, 255, 245, 254 },
|
||||||
|
new byte[] { 238, 173, 190, 249, 197, 255, 245, 254 },
|
||||||
|
new byte[] { 239, 174, 191, 249, 198, 255, 245, 254 },
|
||||||
|
new byte[] { 239, 174, 191, 249, 198, 255, 245, 254 },
|
||||||
|
new byte[] { 240, 175, 192, 249, 199, 255, 246, 254 },
|
||||||
|
new byte[] { 240, 176, 192, 249, 199, 255, 246, 254 },
|
||||||
|
new byte[] { 240, 177, 193, 250, 200, 255, 246, 254 },
|
||||||
|
new byte[] { 240, 177, 193, 250, 200, 255, 246, 254 },
|
||||||
|
new byte[] { 241, 178, 194, 250, 201, 255, 246, 254 },
|
||||||
|
new byte[] { 241, 178, 194, 250, 201, 255, 246, 254 },
|
||||||
|
new byte[] { 242, 179, 195, 250, 202, 255, 246, 254 },
|
||||||
|
new byte[] { 242, 180, 195, 250, 202, 255, 246, 254 },
|
||||||
|
new byte[] { 242, 181, 196, 250, 203, 255, 247, 254 },
|
||||||
|
new byte[] { 242, 181, 196, 250, 203, 255, 247, 254 },
|
||||||
|
new byte[] { 243, 182, 197, 251, 204, 255, 247, 254 },
|
||||||
|
new byte[] { 243, 183, 197, 251, 204, 255, 247, 254 },
|
||||||
|
new byte[] { 244, 184, 198, 251, 205, 255, 247, 254 },
|
||||||
|
new byte[] { 244, 184, 198, 251, 205, 255, 247, 254 },
|
||||||
|
new byte[] { 244, 185, 199, 251, 206, 255, 247, 254 },
|
||||||
|
new byte[] { 244, 185, 199, 251, 206, 255, 247, 254 },
|
||||||
|
new byte[] { 245, 186, 200, 251, 207, 255, 247, 254 },
|
||||||
|
new byte[] { 245, 187, 200, 251, 207, 255, 247, 254 },
|
||||||
|
new byte[] { 246, 188, 201, 252, 207, 255, 248, 254 },
|
||||||
|
new byte[] { 246, 188, 201, 252, 207, 255, 248, 254 },
|
||||||
|
new byte[] { 246, 189, 202, 252, 208, 255, 248, 254 },
|
||||||
|
new byte[] { 246, 190, 202, 252, 208, 255, 248, 254 },
|
||||||
|
new byte[] { 247, 191, 203, 252, 209, 255, 248, 254 },
|
||||||
|
new byte[] { 247, 191, 203, 252, 209, 255, 248, 254 },
|
||||||
|
new byte[] { 247, 192, 204, 252, 210, 255, 248, 254 },
|
||||||
|
new byte[] { 247, 193, 204, 252, 210, 255, 248, 254 },
|
||||||
|
new byte[] { 248, 194, 205, 252, 211, 255, 248, 254 },
|
||||||
|
new byte[] { 248, 194, 205, 252, 211, 255, 248, 254 },
|
||||||
|
new byte[] { 248, 195, 206, 252, 212, 255, 249, 254 },
|
||||||
|
new byte[] { 248, 196, 206, 252, 212, 255, 249, 254 },
|
||||||
|
new byte[] { 249, 197, 207, 253, 213, 255, 249, 254 },
|
||||||
|
new byte[] { 249, 197, 207, 253, 213, 255, 249, 254 },
|
||||||
|
new byte[] { 249, 198, 208, 253, 214, 255, 249, 254 },
|
||||||
|
new byte[] { 249, 199, 209, 253, 214, 255, 249, 254 },
|
||||||
|
new byte[] { 250, 200, 210, 253, 215, 255, 249, 254 },
|
||||||
|
new byte[] { 250, 200, 210, 253, 215, 255, 249, 254 },
|
||||||
|
new byte[] { 250, 201, 211, 253, 215, 255, 249, 254 },
|
||||||
|
new byte[] { 250, 202, 211, 253, 215, 255, 249, 254 },
|
||||||
|
new byte[] { 250, 203, 212, 253, 216, 255, 249, 254 },
|
||||||
|
new byte[] { 250, 203, 212, 253, 216, 255, 249, 254 },
|
||||||
|
new byte[] { 251, 204, 213, 253, 217, 255, 250, 254 },
|
||||||
|
new byte[] { 251, 205, 213, 253, 217, 255, 250, 254 },
|
||||||
|
new byte[] { 251, 206, 214, 254, 218, 255, 250, 254 },
|
||||||
|
new byte[] { 251, 206, 215, 254, 218, 255, 250, 254 },
|
||||||
|
new byte[] { 252, 207, 216, 254, 219, 255, 250, 254 },
|
||||||
|
new byte[] { 252, 208, 216, 254, 219, 255, 250, 254 },
|
||||||
|
new byte[] { 252, 209, 217, 254, 220, 255, 250, 254 },
|
||||||
|
new byte[] { 252, 210, 217, 254, 220, 255, 250, 254 },
|
||||||
|
new byte[] { 252, 211, 218, 254, 221, 255, 250, 254 },
|
||||||
|
new byte[] { 252, 212, 218, 254, 221, 255, 250, 254 },
|
||||||
|
new byte[] { 253, 213, 219, 254, 222, 255, 250, 254 },
|
||||||
|
new byte[] { 253, 213, 220, 254, 222, 255, 250, 254 },
|
||||||
|
new byte[] { 253, 214, 221, 254, 223, 255, 250, 254 },
|
||||||
|
new byte[] { 253, 215, 221, 254, 223, 255, 250, 254 },
|
||||||
|
new byte[] { 253, 216, 222, 254, 224, 255, 251, 254 },
|
||||||
|
new byte[] { 253, 217, 223, 254, 224, 255, 251, 254 },
|
||||||
|
new byte[] { 253, 218, 224, 254, 225, 255, 251, 254 },
|
||||||
|
new byte[] { 253, 219, 224, 254, 225, 255, 251, 254 },
|
||||||
|
new byte[] { 254, 220, 225, 254, 225, 255, 251, 254 },
|
||||||
|
new byte[] { 254, 221, 226, 254, 225, 255, 251, 254 },
|
||||||
|
new byte[] { 254, 222, 227, 255, 226, 255, 251, 254 },
|
||||||
|
new byte[] { 254, 223, 227, 255, 226, 255, 251, 254 },
|
||||||
|
new byte[] { 254, 224, 228, 255, 227, 255, 251, 254 },
|
||||||
|
new byte[] { 254, 225, 229, 255, 227, 255, 251, 254 },
|
||||||
|
new byte[] { 254, 226, 230, 255, 228, 255, 251, 254 },
|
||||||
|
new byte[] { 254, 227, 230, 255, 229, 255, 251, 254 },
|
||||||
|
new byte[] { 255, 228, 231, 255, 230, 255, 251, 254 },
|
||||||
|
new byte[] { 255, 229, 232, 255, 230, 255, 251, 254 },
|
||||||
|
new byte[] { 255, 230, 233, 255, 231, 255, 252, 254 },
|
||||||
|
new byte[] { 255, 231, 234, 255, 231, 255, 252, 254 },
|
||||||
|
new byte[] { 255, 232, 235, 255, 232, 255, 252, 254 },
|
||||||
|
new byte[] { 255, 233, 236, 255, 232, 255, 252, 254 },
|
||||||
|
new byte[] { 255, 235, 237, 255, 233, 255, 252, 254 },
|
||||||
|
new byte[] { 255, 236, 238, 255, 234, 255, 252, 254 },
|
||||||
|
new byte[] { 255, 238, 240, 255, 235, 255, 252, 255 },
|
||||||
|
new byte[] { 255, 239, 241, 255, 235, 255, 252, 254 },
|
||||||
|
new byte[] { 255, 241, 243, 255, 236, 255, 252, 254 },
|
||||||
|
new byte[] { 255, 243, 245, 255, 237, 255, 252, 254 },
|
||||||
|
new byte[] { 255, 246, 247, 255, 239, 255, 253, 255 }
|
||||||
|
};
|
||||||
|
|
||||||
|
internal static readonly byte[] DefaultCoefProbs4x4 =
|
||||||
|
{
|
||||||
|
// Y plane
|
||||||
|
// Intra
|
||||||
|
// Band 0
|
||||||
|
195, 29, 183, 84, 49, 136, 8, 42, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
// Band 1
|
||||||
|
31, 107, 169, 35, 99, 159, 17, 82, 140, 8, 66, 114, 2, 44, 76, 1, 19, 32,
|
||||||
|
// Band 2
|
||||||
|
40, 132, 201, 29, 114, 187, 13, 91, 157, 7, 75, 127, 3, 58, 95, 1, 28, 47,
|
||||||
|
// Band 3
|
||||||
|
69, 142, 221, 42, 122, 201, 15, 91, 159, 6, 67, 121, 1, 42, 77, 1, 17, 31,
|
||||||
|
// Band 4
|
||||||
|
102, 148, 228, 67, 117, 204, 17, 82, 154, 6, 59, 114, 2, 39, 75, 1, 15, 29,
|
||||||
|
// Band 5
|
||||||
|
156, 57, 233, 119, 57, 212, 58, 48, 163, 29, 40, 124, 12, 30, 81, 3, 12, 31,
|
||||||
|
// Inter
|
||||||
|
// Band 0
|
||||||
|
191, 107, 226, 124, 117, 204, 25, 99, 155, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
// Band 1
|
||||||
|
29, 148, 210, 37, 126, 194, 8, 93, 157, 2, 68, 118, 1, 39, 69, 1, 17, 33,
|
||||||
|
// Band 2
|
||||||
|
41, 151, 213, 27, 123, 193, 3, 82, 144, 1, 58, 105, 1, 32, 60, 1, 13, 26,
|
||||||
|
// Band 3
|
||||||
|
59, 159, 220, 23, 126, 198, 4, 88, 151, 1, 66, 114, 1, 38, 71, 1, 18, 34,
|
||||||
|
// Band 4
|
||||||
|
114, 136, 232, 51, 114, 207, 11, 83, 155, 3, 56, 105, 1, 33, 65, 1, 17, 34,
|
||||||
|
// Band 5
|
||||||
|
149, 65, 234, 121, 57, 215, 61, 49, 166, 28, 36, 114, 12, 25, 76, 3, 16, 42,
|
||||||
|
// UV plane
|
||||||
|
// Intra
|
||||||
|
// Band 0
|
||||||
|
214, 49, 220, 132, 63, 188, 42, 65, 137, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
// Band 1
|
||||||
|
85, 137, 221, 104, 131, 216, 49, 111, 192, 21, 87, 155, 2, 49, 87, 1, 16, 28,
|
||||||
|
// Band 2
|
||||||
|
89, 163, 230, 90, 137, 220, 29, 100, 183, 10, 70, 135, 2, 42, 81, 1, 17, 33,
|
||||||
|
// Band 3
|
||||||
|
108, 167, 237, 55, 133, 222, 15, 97, 179, 4, 72, 135, 1, 45, 85, 1, 19, 38,
|
||||||
|
// Band 4
|
||||||
|
124, 146, 240, 66, 124, 224, 17, 88, 175, 4, 58, 122, 1, 36, 75, 1, 18, 37,
|
||||||
|
// Band 5
|
||||||
|
141, 79, 241, 126, 70, 227, 66, 58, 182, 30, 44, 136, 12, 34, 96, 2, 20, 47,
|
||||||
|
// Inter
|
||||||
|
// Band 0
|
||||||
|
229, 99, 249, 143, 111, 235, 46, 109, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
// Band 1
|
||||||
|
82, 158, 236, 94, 146, 224, 25, 117, 191, 9, 87, 149, 3, 56, 99, 1, 33, 57,
|
||||||
|
// Band 2
|
||||||
|
83, 167, 237, 68, 145, 222, 10, 103, 177, 2, 72, 131, 1, 41, 79, 1, 20, 39,
|
||||||
|
// Band 3
|
||||||
|
99, 167, 239, 47, 141, 224, 10, 104, 178, 2, 73, 133, 1, 44, 85, 1, 22, 47,
|
||||||
|
// Band 4
|
||||||
|
127, 145, 243, 71, 129, 228, 17, 93, 177, 3, 61, 124, 1, 41, 84, 1, 21, 52,
|
||||||
|
// Band 5
|
||||||
|
157, 78, 244, 140, 72, 231, 69, 58, 184, 31, 44, 137, 14, 38, 105, 8, 23, 61
|
||||||
|
};
|
||||||
|
|
||||||
|
internal static readonly byte[] DefaultCoefProbs8x8 =
|
||||||
|
{
|
||||||
|
// Y plane
|
||||||
|
// Intra
|
||||||
|
// Band 0
|
||||||
|
125, 34, 187, 52, 41, 133, 6, 31, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
// Band 1
|
||||||
|
37, 109, 153, 51, 102, 147, 23, 87, 128, 8, 67, 101, 1, 41, 63, 1, 19, 29,
|
||||||
|
// Band 2
|
||||||
|
31, 154, 185, 17, 127, 175, 6, 96, 145, 2, 73, 114, 1, 51, 82, 1, 28, 45,
|
||||||
|
// Band 3
|
||||||
|
23, 163, 200, 10, 131, 185, 2, 93, 148, 1, 67, 111, 1, 41, 69, 1, 14, 24,
|
||||||
|
// Band 4
|
||||||
|
29, 176, 217, 12, 145, 201, 3, 101, 156, 1, 69, 111, 1, 39, 63, 1, 14, 23,
|
||||||
|
// Band 5
|
||||||
|
57, 192, 233, 25, 154, 215, 6, 109, 167, 3, 78, 118, 1, 48, 69, 1, 21, 29,
|
||||||
|
// Inter
|
||||||
|
// Band 0
|
||||||
|
202, 105, 245, 108, 106, 216, 18, 90, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
// Band 1
|
||||||
|
33, 172, 219, 64, 149, 206, 14, 117, 177, 5, 90, 141, 2, 61, 95, 1, 37, 57,
|
||||||
|
// Band 2
|
||||||
|
33, 179, 220, 11, 140, 198, 1, 89, 148, 1, 60, 104, 1, 33, 57, 1, 12, 21,
|
||||||
|
// Band 3
|
||||||
|
30, 181, 221, 8, 141, 198, 1, 87, 145, 1, 58, 100, 1, 31, 55, 1, 12, 20,
|
||||||
|
// Band 4
|
||||||
|
32, 186, 224, 7, 142, 198, 1, 86, 143, 1, 58, 100, 1, 31, 55, 1, 12, 22,
|
||||||
|
// Band 5
|
||||||
|
57, 192, 227, 20, 143, 204, 3, 96, 154, 1, 68, 112, 1, 42, 69, 1, 19, 32,
|
||||||
|
// UV plane
|
||||||
|
// Intra
|
||||||
|
// Band 0
|
||||||
|
212, 35, 215, 113, 47, 169, 29, 48, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
// Band 1
|
||||||
|
74, 129, 203, 106, 120, 203, 49, 107, 178, 19, 84, 144, 4, 50, 84, 1, 15, 25,
|
||||||
|
// Band 2
|
||||||
|
71, 172, 217, 44, 141, 209, 15, 102, 173, 6, 76, 133, 2, 51, 89, 1, 24, 42,
|
||||||
|
// Band 3
|
||||||
|
64, 185, 231, 31, 148, 216, 8, 103, 175, 3, 74, 131, 1, 46, 81, 1, 18, 30,
|
||||||
|
// Band 4
|
||||||
|
65, 196, 235, 25, 157, 221, 5, 105, 174, 1, 67, 120, 1, 38, 69, 1, 15, 30,
|
||||||
|
// Band 5
|
||||||
|
65, 204, 238, 30, 156, 224, 7, 107, 177, 2, 70, 124, 1, 42, 73, 1, 18, 34,
|
||||||
|
// Inter
|
||||||
|
// Band 0
|
||||||
|
225, 86, 251, 144, 104, 235, 42, 99, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
// Band 1
|
||||||
|
85, 175, 239, 112, 165, 229, 29, 136, 200, 12, 103, 162, 6, 77, 123, 2, 53, 84,
|
||||||
|
// Band 2
|
||||||
|
75, 183, 239, 30, 155, 221, 3, 106, 171, 1, 74, 128, 1, 44, 76, 1, 17, 28,
|
||||||
|
// Band 3
|
||||||
|
73, 185, 240, 27, 159, 222, 2, 107, 172, 1, 75, 127, 1, 42, 73, 1, 17, 29,
|
||||||
|
// Band 4
|
||||||
|
62, 190, 238, 21, 159, 222, 2, 107, 172, 1, 72, 122, 1, 40, 71, 1, 18, 32,
|
||||||
|
// Band 5
|
||||||
|
61, 199, 240, 27, 161, 226, 4, 113, 180, 1, 76, 129, 1, 46, 80, 1, 23, 41
|
||||||
|
};
|
||||||
|
|
||||||
|
internal static readonly byte[] DefaultCoefProbs16x16 =
|
||||||
|
{
|
||||||
|
// Y plane
|
||||||
|
// Intra
|
||||||
|
// Band 0
|
||||||
|
7, 27, 153, 5, 30, 95, 1, 16, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
// Band 1
|
||||||
|
50, 75, 127, 57, 75, 124, 27, 67, 108, 10, 54, 86, 1, 33, 52, 1, 12, 18,
|
||||||
|
// Band 2
|
||||||
|
43, 125, 151, 26, 108, 148, 7, 83, 122, 2, 59, 89, 1, 38, 60, 1, 17, 27,
|
||||||
|
// Band 3
|
||||||
|
23, 144, 163, 13, 112, 154, 2, 75, 117, 1, 50, 81, 1, 31, 51, 1, 14, 23,
|
||||||
|
// Band 4
|
||||||
|
18, 162, 185, 6, 123, 171, 1, 78, 125, 1, 51, 86, 1, 31, 54, 1, 14, 23,
|
||||||
|
// Band 5
|
||||||
|
15, 199, 227, 3, 150, 204, 1, 91, 146, 1, 55, 95, 1, 30, 53, 1, 11, 20,
|
||||||
|
// Inter
|
||||||
|
// Band 0
|
||||||
|
19, 55, 240, 19, 59, 196, 3, 52, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
// Band 1
|
||||||
|
41, 166, 207, 104, 153, 199, 31, 123, 181, 14, 101, 152, 5, 72, 106, 1, 36, 52,
|
||||||
|
// Band 2
|
||||||
|
35, 176, 211, 12, 131, 190, 2, 88, 144, 1, 60, 101, 1, 36, 60, 1, 16, 28,
|
||||||
|
// Band 3
|
||||||
|
28, 183, 213, 8, 134, 191, 1, 86, 142, 1, 56, 96, 1, 30, 53, 1, 12, 20,
|
||||||
|
// Band 4
|
||||||
|
20, 190, 215, 4, 135, 192, 1, 84, 139, 1, 53, 91, 1, 28, 49, 1, 11, 20,
|
||||||
|
// Band 5
|
||||||
|
13, 196, 216, 2, 137, 192, 1, 86, 143, 1, 57, 99, 1, 32, 56, 1, 13, 24,
|
||||||
|
// UV plane
|
||||||
|
// Intra
|
||||||
|
// Band 0
|
||||||
|
211, 29, 217, 96, 47, 156, 22, 43, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
// Band 1
|
||||||
|
78, 120, 193, 111, 116, 186, 46, 102, 164, 15, 80, 128, 2, 49, 76, 1, 18, 28,
|
||||||
|
// Band 2
|
||||||
|
71, 161, 203, 42, 132, 192, 10, 98, 150, 3, 69, 109, 1, 44, 70, 1, 18, 29,
|
||||||
|
// Band 3
|
||||||
|
57, 186, 211, 30, 140, 196, 4, 93, 146, 1, 62, 102, 1, 38, 65, 1, 16, 27,
|
||||||
|
// Band 4
|
||||||
|
47, 199, 217, 14, 145, 196, 1, 88, 142, 1, 57, 98, 1, 36, 62, 1, 15, 26,
|
||||||
|
// Band 5
|
||||||
|
26, 219, 229, 5, 155, 207, 1, 94, 151, 1, 60, 104, 1, 36, 62, 1, 16, 28,
|
||||||
|
// Inter
|
||||||
|
// Band 0
|
||||||
|
233, 29, 248, 146, 47, 220, 43, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
// Band 1
|
||||||
|
100, 163, 232, 179, 161, 222, 63, 142, 204, 37, 113, 174, 26, 89, 137, 18, 68, 97,
|
||||||
|
// Band 2
|
||||||
|
85, 181, 230, 32, 146, 209, 7, 100, 164, 3, 71, 121, 1, 45, 77, 1, 18, 30,
|
||||||
|
// Band 3
|
||||||
|
65, 187, 230, 20, 148, 207, 2, 97, 159, 1, 68, 116, 1, 40, 70, 1, 14, 29,
|
||||||
|
// Band 4
|
||||||
|
40, 194, 227, 8, 147, 204, 1, 94, 155, 1, 65, 112, 1, 39, 66, 1, 14, 26,
|
||||||
|
// Band 5
|
||||||
|
16, 208, 228, 3, 151, 207, 1, 98, 160, 1, 67, 117, 1, 41, 74, 1, 17, 31
|
||||||
|
};
|
||||||
|
|
||||||
|
internal static readonly byte[] DefaultCoefProbs32x32 =
|
||||||
|
{
|
||||||
|
// Y plane
|
||||||
|
// Intra
|
||||||
|
// Band 0
|
||||||
|
17, 38, 140, 7, 34, 80, 1, 17, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
// Band 1
|
||||||
|
37, 75, 128, 41, 76, 128, 26, 66, 116, 12, 52, 94, 2, 32, 55, 1, 10, 16,
|
||||||
|
// Band 2
|
||||||
|
50, 127, 154, 37, 109, 152, 16, 82, 121, 5, 59, 85, 1, 35, 54, 1, 13, 20,
|
||||||
|
// Band 3
|
||||||
|
40, 142, 167, 17, 110, 157, 2, 71, 112, 1, 44, 72, 1, 27, 45, 1, 11, 17,
|
||||||
|
// Band 4
|
||||||
|
30, 175, 188, 9, 124, 169, 1, 74, 116, 1, 48, 78, 1, 30, 49, 1, 11, 18,
|
||||||
|
// Band 5
|
||||||
|
10, 222, 223, 2, 150, 194, 1, 83, 128, 1, 48, 79, 1, 27, 45, 1, 11, 17,
|
||||||
|
// Inter
|
||||||
|
// Band 0
|
||||||
|
36, 41, 235, 29, 36, 193, 10, 27, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
// Band 1
|
||||||
|
85, 165, 222, 177, 162, 215, 110, 135, 195, 57, 113, 168, 23, 83, 120, 10, 49, 61,
|
||||||
|
// Band 2
|
||||||
|
85, 190, 223, 36, 139, 200, 5, 90, 146, 1, 60, 103, 1, 38, 65, 1, 18, 30,
|
||||||
|
// Band 3
|
||||||
|
72, 202, 223, 23, 141, 199, 2, 86, 140, 1, 56, 97, 1, 36, 61, 1, 16, 27,
|
||||||
|
// Band 4
|
||||||
|
55, 218, 225, 13, 145, 200, 1, 86, 141, 1, 57, 99, 1, 35, 61, 1, 13, 22,
|
||||||
|
// Band 5
|
||||||
|
15, 235, 212, 1, 132, 184, 1, 84, 139, 1, 57, 97, 1, 34, 56, 1, 14, 23,
|
||||||
|
// UV plane
|
||||||
|
// Intra
|
||||||
|
// Band 0
|
||||||
|
181, 21, 201, 61, 37, 123, 10, 38, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
// Band 1
|
||||||
|
47, 106, 172, 95, 104, 173, 42, 93, 159, 18, 77, 131, 4, 50, 81, 1, 17, 23,
|
||||||
|
// Band 2
|
||||||
|
62, 147, 199, 44, 130, 189, 28, 102, 154, 18, 75, 115, 2, 44, 65, 1, 12, 19,
|
||||||
|
// Band 3
|
||||||
|
55, 153, 210, 24, 130, 194, 3, 93, 146, 1, 61, 97, 1, 31, 50, 1, 10, 16,
|
||||||
|
// Band 4
|
||||||
|
49, 186, 223, 17, 148, 204, 1, 96, 142, 1, 53, 83, 1, 26, 44, 1, 11, 17,
|
||||||
|
// Band 5
|
||||||
|
13, 217, 212, 2, 136, 180, 1, 78, 124, 1, 50, 83, 1, 29, 49, 1, 14, 23,
|
||||||
|
// Inter
|
||||||
|
// Band 0
|
||||||
|
197, 13, 247, 82, 17, 222, 25, 17, 162, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
// Band 1
|
||||||
|
126, 186, 247, 234, 191, 243, 176, 177, 234, 104, 158, 220, 66, 128, 186, 55, 90, 137,
|
||||||
|
// Band 2
|
||||||
|
111, 197, 242, 46, 158, 219, 9, 104, 171, 2, 65, 125, 1, 44, 80, 1, 17, 91,
|
||||||
|
// Band 3
|
||||||
|
104, 208, 245, 39, 168, 224, 3, 109, 162, 1, 79, 124, 1, 50, 102, 1, 43, 102,
|
||||||
|
// Band 4
|
||||||
|
84, 220, 246, 31, 177, 231, 2, 115, 180, 1, 79, 134, 1, 55, 77, 1, 60, 79,
|
||||||
|
// Band 5
|
||||||
|
43, 243, 240, 8, 180, 217, 1, 115, 166, 1, 84, 121, 1, 51, 67, 1, 16, 6
|
||||||
|
};
|
||||||
|
|
||||||
|
public static byte[] GetBandTranslate(int txSize)
|
||||||
|
{
|
||||||
|
return txSize == (int)TxSize.Tx4x4 ? CoefbandTrans4x4 : CoefbandTrans8x8Plus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CopyProbs<T>(ref T dest, ReadOnlySpan<byte> probs) where T : unmanaged
|
||||||
|
{
|
||||||
|
if (Unsafe.SizeOf<T>() != probs.Length)
|
||||||
|
{
|
||||||
|
throw new Exception("size mismatch expected: " + probs.Length + " got: " + Unsafe.SizeOf<T>());
|
||||||
|
}
|
||||||
|
|
||||||
|
probs.CopyTo(MemoryMarshal.Cast<T, byte>(MemoryMarshal.CreateSpan(ref dest, 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
internal const int CoefCountSat = 24;
|
||||||
|
internal const int CoefMaxUpdateFactor = 112;
|
||||||
|
internal const int CoefCountSatKey = 24;
|
||||||
|
internal const int CoefMaxUpdateFactorKey = 112;
|
||||||
|
internal const int CoefCountSatAfterKey = 24;
|
||||||
|
internal const int CoefMaxUpdateFactorAfterKey = 128;
|
||||||
|
}
|
||||||
|
}
|
400
src/Ryujinx.Graphics.Nvdec.Vp9/EntropyMode.cs
Normal file
400
src/Ryujinx.Graphics.Nvdec.Vp9/EntropyMode.cs
Normal file
|
@ -0,0 +1,400 @@
|
||||||
|
using Ryujinx.Common.Memory;
|
||||||
|
using Ryujinx.Graphics.Nvdec.Vp9.Common;
|
||||||
|
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
||||||
|
using Ryujinx.Graphics.Video;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
{
|
||||||
|
internal class EntropyMode
|
||||||
|
{
|
||||||
|
public const int BlockSizeGroups = 4;
|
||||||
|
|
||||||
|
public const int TxSizeContexts = 2;
|
||||||
|
|
||||||
|
public static readonly byte[][][] KfYModeProb =
|
||||||
|
{
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
// above = dc
|
||||||
|
new byte[] { 137, 30, 42, 148, 151, 207, 70, 52, 91 }, // left = dc
|
||||||
|
new byte[] { 92, 45, 102, 136, 116, 180, 74, 90, 100 }, // left = v
|
||||||
|
new byte[] { 73, 32, 19, 187, 222, 215, 46, 34, 100 }, // left = h
|
||||||
|
new byte[] { 91, 30, 32, 116, 121, 186, 93, 86, 94 }, // left = d45
|
||||||
|
new byte[] { 72, 35, 36, 149, 68, 206, 68, 63, 105 }, // left = d135
|
||||||
|
new byte[] { 73, 31, 28, 138, 57, 124, 55, 122, 151 }, // left = d117
|
||||||
|
new byte[] { 67, 23, 21, 140, 126, 197, 40, 37, 171 }, // left = d153
|
||||||
|
new byte[] { 86, 27, 28, 128, 154, 212, 45, 43, 53 }, // left = d207
|
||||||
|
new byte[] { 74, 32, 27, 107, 86, 160, 63, 134, 102 }, // left = d63
|
||||||
|
new byte[] { 59, 67, 44, 140, 161, 202, 78, 67, 119 } // left = tm
|
||||||
|
},
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
// above = v
|
||||||
|
new byte[] { 63, 36, 126, 146, 123, 158, 60, 90, 96 }, // left = dc
|
||||||
|
new byte[] { 43, 46, 168, 134, 107, 128, 69, 142, 92 }, // left = v
|
||||||
|
new byte[] { 44, 29, 68, 159, 201, 177, 50, 57, 77 }, // left = h
|
||||||
|
new byte[] { 58, 38, 76, 114, 97, 172, 78, 133, 92 }, // left = d45
|
||||||
|
new byte[] { 46, 41, 76, 140, 63, 184, 69, 112, 57 }, // left = d135
|
||||||
|
new byte[] { 38, 32, 85, 140, 46, 112, 54, 151, 133 }, // left = d117
|
||||||
|
new byte[] { 39, 27, 61, 131, 110, 175, 44, 75, 136 }, // left = d153
|
||||||
|
new byte[] { 52, 30, 74, 113, 130, 175, 51, 64, 58 }, // left = d207
|
||||||
|
new byte[] { 47, 35, 80, 100, 74, 143, 64, 163, 74 }, // left = d63
|
||||||
|
new byte[] { 36, 61, 116, 114, 128, 162, 80, 125, 82 } // left = tm
|
||||||
|
},
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
// above = h
|
||||||
|
new byte[] { 82, 26, 26, 171, 208, 204, 44, 32, 105 }, // left = dc
|
||||||
|
new byte[] { 55, 44, 68, 166, 179, 192, 57, 57, 108 }, // left = v
|
||||||
|
new byte[] { 42, 26, 11, 199, 241, 228, 23, 15, 85 }, // left = h
|
||||||
|
new byte[] { 68, 42, 19, 131, 160, 199, 55, 52, 83 }, // left = d45
|
||||||
|
new byte[] { 58, 50, 25, 139, 115, 232, 39, 52, 118 }, // left = d135
|
||||||
|
new byte[] { 50, 35, 33, 153, 104, 162, 64, 59, 131 }, // left = d117
|
||||||
|
new byte[] { 44, 24, 16, 150, 177, 202, 33, 19, 156 }, // left = d153
|
||||||
|
new byte[] { 55, 27, 12, 153, 203, 218, 26, 27, 49 }, // left = d207
|
||||||
|
new byte[] { 53, 49, 21, 110, 116, 168, 59, 80, 76 }, // left = d63
|
||||||
|
new byte[] { 38, 72, 19, 168, 203, 212, 50, 50, 107 } // left = tm
|
||||||
|
},
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
// above = d45
|
||||||
|
new byte[] { 103, 26, 36, 129, 132, 201, 83, 80, 93 }, // left = dc
|
||||||
|
new byte[] { 59, 38, 83, 112, 103, 162, 98, 136, 90 }, // left = v
|
||||||
|
new byte[] { 62, 30, 23, 158, 200, 207, 59, 57, 50 }, // left = h
|
||||||
|
new byte[] { 67, 30, 29, 84, 86, 191, 102, 91, 59 }, // left = d45
|
||||||
|
new byte[] { 60, 32, 33, 112, 71, 220, 64, 89, 104 }, // left = d135
|
||||||
|
new byte[] { 53, 26, 34, 130, 56, 149, 84, 120, 103 }, // left = d117
|
||||||
|
new byte[] { 53, 21, 23, 133, 109, 210, 56, 77, 172 }, // left = d153
|
||||||
|
new byte[] { 77, 19, 29, 112, 142, 228, 55, 66, 36 }, // left = d207
|
||||||
|
new byte[] { 61, 29, 29, 93, 97, 165, 83, 175, 162 }, // left = d63
|
||||||
|
new byte[] { 47, 47, 43, 114, 137, 181, 100, 99, 95 } // left = tm
|
||||||
|
},
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
// above = d135
|
||||||
|
new byte[] { 69, 23, 29, 128, 83, 199, 46, 44, 101 }, // left = dc
|
||||||
|
new byte[] { 53, 40, 55, 139, 69, 183, 61, 80, 110 }, // left = v
|
||||||
|
new byte[] { 40, 29, 19, 161, 180, 207, 43, 24, 91 }, // left = h
|
||||||
|
new byte[] { 60, 34, 19, 105, 61, 198, 53, 64, 89 }, // left = d45
|
||||||
|
new byte[] { 52, 31, 22, 158, 40, 209, 58, 62, 89 }, // left = d135
|
||||||
|
new byte[] { 44, 31, 29, 147, 46, 158, 56, 102, 198 }, // left = d117
|
||||||
|
new byte[] { 35, 19, 12, 135, 87, 209, 41, 45, 167 }, // left = d153
|
||||||
|
new byte[] { 55, 25, 21, 118, 95, 215, 38, 39, 66 }, // left = d207
|
||||||
|
new byte[] { 51, 38, 25, 113, 58, 164, 70, 93, 97 }, // left = d63
|
||||||
|
new byte[] { 47, 54, 34, 146, 108, 203, 72, 103, 151 } // left = tm
|
||||||
|
},
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
// above = d117
|
||||||
|
new byte[] { 64, 19, 37, 156, 66, 138, 49, 95, 133 }, // left = dc
|
||||||
|
new byte[] { 46, 27, 80, 150, 55, 124, 55, 121, 135 }, // left = v
|
||||||
|
new byte[] { 36, 23, 27, 165, 149, 166, 54, 64, 118 }, // left = h
|
||||||
|
new byte[] { 53, 21, 36, 131, 63, 163, 60, 109, 81 }, // left = d45
|
||||||
|
new byte[] { 40, 26, 35, 154, 40, 185, 51, 97, 123 }, // left = d135
|
||||||
|
new byte[] { 35, 19, 34, 179, 19, 97, 48, 129, 124 }, // left = d117
|
||||||
|
new byte[] { 36, 20, 26, 136, 62, 164, 33, 77, 154 }, // left = d153
|
||||||
|
new byte[] { 45, 18, 32, 130, 90, 157, 40, 79, 91 }, // left = d207
|
||||||
|
new byte[] { 45, 26, 28, 129, 45, 129, 49, 147, 123 }, // left = d63
|
||||||
|
new byte[] { 38, 44, 51, 136, 74, 162, 57, 97, 121 } // left = tm
|
||||||
|
},
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
// above = d153
|
||||||
|
new byte[] { 75, 17, 22, 136, 138, 185, 32, 34, 166 }, // left = dc
|
||||||
|
new byte[] { 56, 39, 58, 133, 117, 173, 48, 53, 187 }, // left = v
|
||||||
|
new byte[] { 35, 21, 12, 161, 212, 207, 20, 23, 145 }, // left = h
|
||||||
|
new byte[] { 56, 29, 19, 117, 109, 181, 55, 68, 112 }, // left = d45
|
||||||
|
new byte[] { 47, 29, 17, 153, 64, 220, 59, 51, 114 }, // left = d135
|
||||||
|
new byte[] { 46, 16, 24, 136, 76, 147, 41, 64, 172 }, // left = d117
|
||||||
|
new byte[] { 34, 17, 11, 108, 152, 187, 13, 15, 209 }, // left = d153
|
||||||
|
new byte[] { 51, 24, 14, 115, 133, 209, 32, 26, 104 }, // left = d207
|
||||||
|
new byte[] { 55, 30, 18, 122, 79, 179, 44, 88, 116 }, // left = d63
|
||||||
|
new byte[] { 37, 49, 25, 129, 168, 164, 41, 54, 148 } // left = tm
|
||||||
|
},
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
// above = d207
|
||||||
|
new byte[] { 82, 22, 32, 127, 143, 213, 39, 41, 70 }, // left = dc
|
||||||
|
new byte[] { 62, 44, 61, 123, 105, 189, 48, 57, 64 }, // left = v
|
||||||
|
new byte[] { 47, 25, 17, 175, 222, 220, 24, 30, 86 }, // left = h
|
||||||
|
new byte[] { 68, 36, 17, 106, 102, 206, 59, 74, 74 }, // left = d45
|
||||||
|
new byte[] { 57, 39, 23, 151, 68, 216, 55, 63, 58 }, // left = d135
|
||||||
|
new byte[] { 49, 30, 35, 141, 70, 168, 82, 40, 115 }, // left = d117
|
||||||
|
new byte[] { 51, 25, 15, 136, 129, 202, 38, 35, 139 }, // left = d153
|
||||||
|
new byte[] { 68, 26, 16, 111, 141, 215, 29, 28, 28 }, // left = d207
|
||||||
|
new byte[] { 59, 39, 19, 114, 75, 180, 77, 104, 42 }, // left = d63
|
||||||
|
new byte[] { 40, 61, 26, 126, 152, 206, 61, 59, 93 } // left = tm
|
||||||
|
},
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
// above = d63
|
||||||
|
new byte[] { 78, 23, 39, 111, 117, 170, 74, 124, 94 }, // left = dc
|
||||||
|
new byte[] { 48, 34, 86, 101, 92, 146, 78, 179, 134 }, // left = v
|
||||||
|
new byte[] { 47, 22, 24, 138, 187, 178, 68, 69, 59 }, // left = h
|
||||||
|
new byte[] { 56, 25, 33, 105, 112, 187, 95, 177, 129 }, // left = d45
|
||||||
|
new byte[] { 48, 31, 27, 114, 63, 183, 82, 116, 56 }, // left = d135
|
||||||
|
new byte[] { 43, 28, 37, 121, 63, 123, 61, 192, 169 }, // left = d117
|
||||||
|
new byte[] { 42, 17, 24, 109, 97, 177, 56, 76, 122 }, // left = d153
|
||||||
|
new byte[] { 58, 18, 28, 105, 139, 182, 70, 92, 63 }, // left = d207
|
||||||
|
new byte[] { 46, 23, 32, 74, 86, 150, 67, 183, 88 }, // left = d63
|
||||||
|
new byte[] { 36, 38, 48, 92, 122, 165, 88, 137, 91 } // left = tm
|
||||||
|
},
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
// above = tm
|
||||||
|
new byte[] { 65, 70, 60, 155, 159, 199, 61, 60, 81 }, // left = dc
|
||||||
|
new byte[] { 44, 78, 115, 132, 119, 173, 71, 112, 93 }, // left = v
|
||||||
|
new byte[] { 39, 38, 21, 184, 227, 206, 42, 32, 64 }, // left = h
|
||||||
|
new byte[] { 58, 47, 36, 124, 137, 193, 80, 82, 78 }, // left = d45
|
||||||
|
new byte[] { 49, 50, 35, 144, 95, 205, 63, 78, 59 }, // left = d135
|
||||||
|
new byte[] { 41, 53, 52, 148, 71, 142, 65, 128, 51 }, // left = d117
|
||||||
|
new byte[] { 40, 36, 28, 143, 143, 202, 40, 55, 137 }, // left = d153
|
||||||
|
new byte[] { 52, 34, 29, 129, 183, 227, 42, 35, 43 }, // left = d207
|
||||||
|
new byte[] { 42, 44, 44, 104, 105, 164, 64, 130, 80 }, // left = d63
|
||||||
|
new byte[] { 43, 81, 53, 140, 169, 204, 68, 84, 72 } // left = tm
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static readonly byte[][] KfUvModeProb =
|
||||||
|
{
|
||||||
|
new byte[] { 144, 11, 54, 157, 195, 130, 46, 58, 108 }, // y = dc
|
||||||
|
new byte[] { 118, 15, 123, 148, 131, 101, 44, 93, 131 }, // y = v
|
||||||
|
new byte[] { 113, 12, 23, 188, 226, 142, 26, 32, 125 }, // y = h
|
||||||
|
new byte[] { 120, 11, 50, 123, 163, 135, 64, 77, 103 }, // y = d45
|
||||||
|
new byte[] { 113, 9, 36, 155, 111, 157, 32, 44, 161 }, // y = d135
|
||||||
|
new byte[] { 116, 9, 55, 176, 76, 96, 37, 61, 149 }, // y = d117
|
||||||
|
new byte[] { 115, 9, 28, 141, 161, 167, 21, 25, 193 }, // y = d153
|
||||||
|
new byte[] { 120, 12, 32, 145, 195, 142, 32, 38, 86 }, // y = d207
|
||||||
|
new byte[] { 116, 12, 64, 120, 140, 125, 49, 115, 121 }, // y = d63
|
||||||
|
new byte[] { 102, 19, 66, 162, 182, 122, 35, 59, 128 } // y = tm
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly byte[] DefaultIfYProbs =
|
||||||
|
{
|
||||||
|
65, 32, 18, 144, 162, 194, 41, 51, 98, // block_size < 8x8
|
||||||
|
132, 68, 18, 165, 217, 196, 45, 40, 78, // block_size < 16x16
|
||||||
|
173, 80, 19, 176, 240, 193, 64, 35, 46, // block_size < 32x32
|
||||||
|
221, 135, 38, 194, 248, 121, 96, 85, 29 // block_size >= 32x32
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly byte[] DefaultIfUvProbs =
|
||||||
|
{
|
||||||
|
120, 7, 76, 176, 208, 126, 28, 54, 103, // y = dc
|
||||||
|
48, 12, 154, 155, 139, 90, 34, 117, 119, // y = v
|
||||||
|
67, 6, 25, 204, 243, 158, 13, 21, 96, // y = h
|
||||||
|
97, 5, 44, 131, 176, 139, 48, 68, 97, // y = d45
|
||||||
|
83, 5, 42, 156, 111, 152, 26, 49, 152, // y = d135
|
||||||
|
80, 5, 58, 178, 74, 83, 33, 62, 145, // y = d117
|
||||||
|
86, 5, 32, 154, 192, 168, 14, 22, 163, // y = d153
|
||||||
|
85, 5, 32, 156, 216, 148, 19, 29, 73, // y = d207
|
||||||
|
77, 7, 64, 116, 132, 122, 37, 126, 120, // y = d63
|
||||||
|
101, 21, 107, 181, 192, 103, 19, 67, 125 // y = tm
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly byte[] DefaultPartitionProbs =
|
||||||
|
{
|
||||||
|
// 8x8 . 4x4
|
||||||
|
199, 122, 141, // a/l both not split
|
||||||
|
147, 63, 159, // a split, l not split
|
||||||
|
148, 133, 118, // l split, a not split
|
||||||
|
121, 104, 114, // a/l both split
|
||||||
|
// 16x16 . 8x8
|
||||||
|
174, 73, 87, // a/l both not split
|
||||||
|
92, 41, 83, // a split, l not split
|
||||||
|
82, 99, 50, // l split, a not split
|
||||||
|
53, 39, 39, // a/l both split
|
||||||
|
// 32x32 . 16x16
|
||||||
|
177, 58, 59, // a/l both not split
|
||||||
|
68, 26, 63, // a split, l not split
|
||||||
|
52, 79, 25, // l split, a not split
|
||||||
|
17, 14, 12, // a/l both split
|
||||||
|
// 64x64 . 32x32
|
||||||
|
222, 34, 30, // a/l both not split
|
||||||
|
72, 16, 44, // a split, l not split
|
||||||
|
58, 32, 12, // l split, a not split
|
||||||
|
10, 7, 6 // a/l both split
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly byte[] DefaultInterModeProbs =
|
||||||
|
{
|
||||||
|
2, 173, 34, // 0 = both zero mv
|
||||||
|
7, 145, 85, // 1 = one zero mv + one a predicted mv
|
||||||
|
7, 166, 63, // 2 = two predicted mvs
|
||||||
|
7, 94, 66, // 3 = one predicted/zero and one new mv
|
||||||
|
8, 64, 46, // 4 = two new mvs
|
||||||
|
17, 81, 31, // 5 = one intra neighbour + x
|
||||||
|
25, 29, 30 // 6 = two intra neighbours
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Array indices are identical to previously-existing INTRAMODECONTEXTNODES. */
|
||||||
|
public static readonly sbyte[] IntraModeTree =
|
||||||
|
{
|
||||||
|
-(int)PredictionMode.DcPred, 2, /* 0 = DC_NODE */ -(int)PredictionMode.TmPred, 4, /* 1 = TM_NODE */
|
||||||
|
-(int)PredictionMode.VPred, 6, /* 2 = V_NODE */ 8, 12, /* 3 = COM_NODE */ -(int)PredictionMode.HPred,
|
||||||
|
10, /* 4 = H_NODE */ -(int)PredictionMode.D135Pred, -(int)PredictionMode.D117Pred, /* 5 = D135_NODE */
|
||||||
|
-(int)PredictionMode.D45Pred, 14, /* 6 = D45_NODE */ -(int)PredictionMode.D63Pred,
|
||||||
|
16, /* 7 = D63_NODE */ -(int)PredictionMode.D153Pred, -(int)PredictionMode.D207Pred /* 8 = D153_NODE */
|
||||||
|
};
|
||||||
|
|
||||||
|
public static readonly sbyte[] InterModeTree =
|
||||||
|
{
|
||||||
|
-((int)PredictionMode.ZeroMv - (int)PredictionMode.NearestMv), 2,
|
||||||
|
-((int)PredictionMode.NearestMv - (int)PredictionMode.NearestMv), 4,
|
||||||
|
-((int)PredictionMode.NearMv - (int)PredictionMode.NearestMv),
|
||||||
|
-((int)PredictionMode.NewMv - (int)PredictionMode.NearestMv)
|
||||||
|
};
|
||||||
|
|
||||||
|
public static readonly sbyte[] PartitionTree =
|
||||||
|
{
|
||||||
|
-(sbyte)PartitionType.PartitionNone, 2, -(sbyte)PartitionType.PartitionHorz, 4,
|
||||||
|
-(sbyte)PartitionType.PartitionVert, -(sbyte)PartitionType.PartitionSplit
|
||||||
|
};
|
||||||
|
|
||||||
|
public static readonly sbyte[] SwitchableInterpTree =
|
||||||
|
{
|
||||||
|
-Constants.EightTap, 2, -Constants.EightTapSmooth, -Constants.EightTapSharp
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly byte[] DefaultIntraInterP = { 9, 102, 187, 225 };
|
||||||
|
private static readonly byte[] DefaultCompInterP = { 239, 183, 119, 96, 41 };
|
||||||
|
private static readonly byte[] DefaultCompRefP = { 50, 126, 123, 221, 226 };
|
||||||
|
private static readonly byte[] DefaultSingleRefP = { 33, 16, 77, 74, 142, 142, 172, 170, 238, 247 };
|
||||||
|
private static readonly byte[] DefaultTxProbs = { 3, 136, 37, 5, 52, 13, 20, 152, 15, 101, 100, 66 };
|
||||||
|
|
||||||
|
static EntropyMode()
|
||||||
|
{
|
||||||
|
byte[][] KfPartitionProbs =
|
||||||
|
{
|
||||||
|
// 8x8 . 4x4
|
||||||
|
new byte[] { 158, 97, 94 }, // a/l both not split
|
||||||
|
new byte[] { 93, 24, 99 }, // a split, l not split
|
||||||
|
new byte[] { 85, 119, 44 }, // l split, a not split
|
||||||
|
new byte[] { 62, 59, 67 }, // a/l both split
|
||||||
|
|
||||||
|
// 16x16 . 8x8
|
||||||
|
new byte[] { 149, 53, 53 }, // a/l both not split
|
||||||
|
new byte[] { 94, 20, 48 }, // a split, l not split
|
||||||
|
new byte[] { 83, 53, 24 }, // l split, a not split
|
||||||
|
new byte[] { 52, 18, 18 }, // a/l both split
|
||||||
|
|
||||||
|
// 32x32 . 16x16
|
||||||
|
new byte[] { 150, 40, 39 }, // a/l both not split
|
||||||
|
new byte[] { 78, 12, 26 }, // a split, l not split
|
||||||
|
new byte[] { 67, 33, 11 }, // l split, a not split
|
||||||
|
new byte[] { 24, 7, 5 }, // a/l both split
|
||||||
|
|
||||||
|
// 64x64 . 32x32
|
||||||
|
new byte[] { 174, 35, 49 }, // a/l both not split
|
||||||
|
new byte[] { 68, 11, 27 }, // a split, l not split
|
||||||
|
new byte[] { 57, 15, 9 }, // l split, a not split
|
||||||
|
new byte[] { 12, 3, 3 } // a/l both split
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly byte[] DefaultSkipProbs = { 192, 128, 64 };
|
||||||
|
|
||||||
|
private static readonly byte[] DefaultSwitchableInterpProb = { 235, 162, 36, 255, 34, 3, 149, 144 };
|
||||||
|
|
||||||
|
private static void InitModeProbs(ref Vp9EntropyProbs fc)
|
||||||
|
{
|
||||||
|
Entropy.CopyProbs(ref fc.UvModeProb, DefaultIfUvProbs);
|
||||||
|
Entropy.CopyProbs(ref fc.YModeProb, DefaultIfYProbs);
|
||||||
|
Entropy.CopyProbs(ref fc.SwitchableInterpProb, DefaultSwitchableInterpProb);
|
||||||
|
Entropy.CopyProbs(ref fc.PartitionProb, DefaultPartitionProbs);
|
||||||
|
Entropy.CopyProbs(ref fc.IntraInterProb, DefaultIntraInterP);
|
||||||
|
Entropy.CopyProbs(ref fc.CompInterProb, DefaultCompInterP);
|
||||||
|
Entropy.CopyProbs(ref fc.CompRefProb, DefaultCompRefP);
|
||||||
|
Entropy.CopyProbs(ref fc.SingleRefProb, DefaultSingleRefP);
|
||||||
|
Entropy.CopyProbs(ref fc.Tx32x32Prob, DefaultTxProbs.AsSpan().Slice(0, 6));
|
||||||
|
Entropy.CopyProbs(ref fc.Tx16x16Prob, DefaultTxProbs.AsSpan().Slice(6, 4));
|
||||||
|
Entropy.CopyProbs(ref fc.Tx8x8Prob, DefaultTxProbs.AsSpan().Slice(10, 2));
|
||||||
|
Entropy.CopyProbs(ref fc.SkipProb, DefaultSkipProbs);
|
||||||
|
Entropy.CopyProbs(ref fc.InterModeProb, DefaultInterModeProbs);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void TxCountsToBranchCounts32x32(ReadOnlySpan<uint> txCount32x32P,
|
||||||
|
ref Array3<Array2<uint>> ct32x32P)
|
||||||
|
{
|
||||||
|
ct32x32P[0][0] = txCount32x32P[(int)TxSize.Tx4x4];
|
||||||
|
ct32x32P[0][1] = txCount32x32P[(int)TxSize.Tx8x8] + txCount32x32P[(int)TxSize.Tx16x16] +
|
||||||
|
txCount32x32P[(int)TxSize.Tx32x32];
|
||||||
|
ct32x32P[1][0] = txCount32x32P[(int)TxSize.Tx8x8];
|
||||||
|
ct32x32P[1][1] = txCount32x32P[(int)TxSize.Tx16x16] + txCount32x32P[(int)TxSize.Tx32x32];
|
||||||
|
ct32x32P[2][0] = txCount32x32P[(int)TxSize.Tx16x16];
|
||||||
|
ct32x32P[2][1] = txCount32x32P[(int)TxSize.Tx32x32];
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void TxCountsToBranchCounts16x16(ReadOnlySpan<uint> txCount16x16P,
|
||||||
|
ref Array2<Array2<uint>> ct16x16P)
|
||||||
|
{
|
||||||
|
ct16x16P[0][0] = txCount16x16P[(int)TxSize.Tx4x4];
|
||||||
|
ct16x16P[0][1] = txCount16x16P[(int)TxSize.Tx8x8] + txCount16x16P[(int)TxSize.Tx16x16];
|
||||||
|
ct16x16P[1][0] = txCount16x16P[(int)TxSize.Tx8x8];
|
||||||
|
ct16x16P[1][1] = txCount16x16P[(int)TxSize.Tx16x16];
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void TxCountsToBranchCounts8x8(ReadOnlySpan<uint> txCount8x8P,
|
||||||
|
ref Array1<Array2<uint>> ct8x8P)
|
||||||
|
{
|
||||||
|
ct8x8P[0][0] = txCount8x8P[(int)TxSize.Tx4x4];
|
||||||
|
ct8x8P[0][1] = txCount8x8P[(int)TxSize.Tx8x8];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static unsafe void SetupPastIndependence(ref Vp9Common cm)
|
||||||
|
{
|
||||||
|
// Reset the segment feature data to the default stats:
|
||||||
|
// Features disabled, 0, with delta coding (Default state).
|
||||||
|
ref Types.LoopFilter lf = ref cm.Lf;
|
||||||
|
|
||||||
|
cm.Seg.ClearAllSegFeatures();
|
||||||
|
cm.Seg.AbsDelta = Segmentation.SegmentDeltadata;
|
||||||
|
|
||||||
|
if (!cm.LastFrameSegMap.IsNull)
|
||||||
|
{
|
||||||
|
MemoryUtil.Fill(cm.LastFrameSegMap.ToPointer(), (byte)0, cm.MiRows * cm.MiCols);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cm.CurrentFrameSegMap.IsNull)
|
||||||
|
{
|
||||||
|
MemoryUtil.Fill(cm.CurrentFrameSegMap.ToPointer(), (byte)0, cm.MiRows * cm.MiCols);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the mode ref deltas for loop filter
|
||||||
|
lf.LastRefDeltas = new Array4<sbyte>();
|
||||||
|
lf.LastModeDeltas = new Array2<sbyte>();
|
||||||
|
lf.SetDefaultLfDeltas();
|
||||||
|
|
||||||
|
// To force update of the sharpness
|
||||||
|
lf.LastSharpnessLevel = -1;
|
||||||
|
|
||||||
|
cm.DefaultCoefProbs();
|
||||||
|
InitModeProbs(ref cm.Fc.Value);
|
||||||
|
cm.InitMvProbs();
|
||||||
|
|
||||||
|
if (cm.FrameType == FrameType.KeyFrame || cm.ErrorResilientMode != 0 || cm.ResetFrameContext == 3)
|
||||||
|
{
|
||||||
|
// Reset all frame contexts.
|
||||||
|
for (int i = 0; i < Constants.FrameContexts; ++i)
|
||||||
|
{
|
||||||
|
cm.FrameContexts[i] = cm.Fc.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (cm.ResetFrameContext == 2)
|
||||||
|
{
|
||||||
|
// Reset only the frame context specified in the frame header.
|
||||||
|
cm.FrameContexts[(int)cm.FrameContextIdx] = cm.Fc.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// prev_mip will only be allocated in encoder.
|
||||||
|
if (cm.FrameIsIntraOnly() && !cm.PrevMip.IsNull)
|
||||||
|
{
|
||||||
|
cm.PrevMi.Value = new ModeInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
cm.RefFrameSignBias = new Array4<sbyte>();
|
||||||
|
|
||||||
|
cm.FrameContextIdx = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
165
src/Ryujinx.Graphics.Nvdec.Vp9/EntropyMv.cs
Normal file
165
src/Ryujinx.Graphics.Nvdec.Vp9/EntropyMv.cs
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
using Ryujinx.Common.Memory;
|
||||||
|
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
||||||
|
using Ryujinx.Graphics.Video;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
{
|
||||||
|
internal static class EntropyMv
|
||||||
|
{
|
||||||
|
public const int UpdateProb = 252;
|
||||||
|
|
||||||
|
/* Symbols for coding which components are zero jointly */
|
||||||
|
public const int Joints = 4;
|
||||||
|
|
||||||
|
|
||||||
|
public static readonly sbyte[] JointTree =
|
||||||
|
{
|
||||||
|
-(sbyte)MvJointType.Zero, 2, -(sbyte)MvJointType.Hnzvz, 4,
|
||||||
|
-(sbyte)MvJointType.Hzvnz, -(sbyte)MvJointType.Hnzvnz
|
||||||
|
};
|
||||||
|
|
||||||
|
public static readonly sbyte[] ClassTree =
|
||||||
|
{
|
||||||
|
-(sbyte)MvClassType.Class0, 2, -(sbyte)MvClassType.Class1, 4, 6, 8, -(sbyte)MvClassType.Class2,
|
||||||
|
-(sbyte)MvClassType.Class3, 10, 12, -(sbyte)MvClassType.Class4, -(sbyte)MvClassType.Class5,
|
||||||
|
-(sbyte)MvClassType.Class6, 14, 16, 18, -(sbyte)MvClassType.Class7, -(sbyte)MvClassType.Class8,
|
||||||
|
-(sbyte)MvClassType.Class9, -(sbyte)MvClassType.Class10
|
||||||
|
};
|
||||||
|
|
||||||
|
public static readonly sbyte[] Class0Tree = { -0, -1 };
|
||||||
|
|
||||||
|
public static readonly sbyte[] FpTree = { -0, 2, -1, 4, -2, -3 };
|
||||||
|
|
||||||
|
private static bool JointVertical(MvJointType type)
|
||||||
|
{
|
||||||
|
return type == MvJointType.Hzvnz || type == MvJointType.Hnzvnz;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool JointHorizontal(MvJointType type)
|
||||||
|
{
|
||||||
|
return type == MvJointType.Hnzvz || type == MvJointType.Hnzvnz;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly byte[] LogInBase2 =
|
||||||
|
{
|
||||||
|
0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6,
|
||||||
|
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||||
|
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||||
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||||
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||||
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||||
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 10
|
||||||
|
};
|
||||||
|
|
||||||
|
private static int ClassBase(MvClassType c)
|
||||||
|
{
|
||||||
|
return c != 0 ? Class0Size << ((int)c + 2) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MvClassType GetClass(int z, Ptr<int> offset)
|
||||||
|
{
|
||||||
|
MvClassType c = z >= Class0Size * 4096
|
||||||
|
? MvClassType.Class10
|
||||||
|
: (MvClassType)LogInBase2[z >> 3];
|
||||||
|
if (!offset.IsNull)
|
||||||
|
{
|
||||||
|
offset.Value = z - ClassBase(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void IncComponent(int v, ref Vp9BackwardUpdates compCounts, int compIndex, int incr, int usehp)
|
||||||
|
{
|
||||||
|
int s, z, c, o = 0, d, e, f;
|
||||||
|
Debug.Assert(v != 0); /* should not be zero */
|
||||||
|
s = v < 0 ? 1 : 0;
|
||||||
|
compCounts.Sign[compIndex][s] += (uint)incr;
|
||||||
|
z = (s != 0 ? -v : v) - 1; /* magnitude - 1 */
|
||||||
|
|
||||||
|
c = (int)GetClass(z, new Ptr<int>(ref o));
|
||||||
|
compCounts.Classes[compIndex][c] += (uint)incr;
|
||||||
|
|
||||||
|
d = o >> 3; /* int mv data */
|
||||||
|
f = (o >> 1) & 3; /* fractional pel mv data */
|
||||||
|
e = o & 1; /* high precision mv data */
|
||||||
|
|
||||||
|
if (c == (int)MvClassType.Class0)
|
||||||
|
{
|
||||||
|
compCounts.Class0[compIndex][d] += (uint)incr;
|
||||||
|
compCounts.Class0Fp[compIndex][d][f] += (uint)incr;
|
||||||
|
compCounts.Class0Hp[compIndex][e] += (uint)(usehp * incr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int b = c + Class0Bits - 1; // number of bits
|
||||||
|
for (int i = 0; i < b; ++i)
|
||||||
|
{
|
||||||
|
compCounts.Bits[compIndex][i][(d >> i) & 1] += (uint)incr;
|
||||||
|
}
|
||||||
|
|
||||||
|
compCounts.Fp[compIndex][f] += (uint)incr;
|
||||||
|
compCounts.Hp[compIndex][e] += (uint)(usehp * incr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Inc(ref Mv mv, Ptr<Vp9BackwardUpdates> counts)
|
||||||
|
{
|
||||||
|
if (!counts.IsNull)
|
||||||
|
{
|
||||||
|
MvJointType j = mv.GetJoint();
|
||||||
|
++counts.Value.Joints[(int)j];
|
||||||
|
|
||||||
|
if (JointVertical(j))
|
||||||
|
{
|
||||||
|
IncComponent(mv.Row, ref counts.Value, 0, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (JointHorizontal(j))
|
||||||
|
{
|
||||||
|
IncComponent(mv.Col, ref counts.Value, 1, 1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Symbols for coding magnitude class of nonzero components */
|
||||||
|
public const int Classes = 11;
|
||||||
|
|
||||||
|
public const int Class0Bits = 1; /* bits at integer precision for class 0 */
|
||||||
|
public const int Class0Size = 1 << Class0Bits;
|
||||||
|
public const int OffsetBits = Classes + Class0Bits - 2;
|
||||||
|
public const int FpSize = 4;
|
||||||
|
|
||||||
|
public const int MaxBits = Classes + Class0Bits + 2;
|
||||||
|
public const int Max = (1 << MaxBits) - 1;
|
||||||
|
public const int Vals = (Max << 1) + 1;
|
||||||
|
|
||||||
|
public const int InUseBits = 14;
|
||||||
|
public const int Upp = (1 << InUseBits) - 1;
|
||||||
|
public const int Low = -(1 << InUseBits);
|
||||||
|
}
|
||||||
|
}
|
79
src/Ryujinx.Graphics.Nvdec.Vp9/FrameBuffers.cs
Normal file
79
src/Ryujinx.Graphics.Nvdec.Vp9/FrameBuffers.cs
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
using Ryujinx.Common.Memory;
|
||||||
|
using Ryujinx.Graphics.Nvdec.Vp9.Common;
|
||||||
|
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
{
|
||||||
|
internal struct InternalFrameBuffer
|
||||||
|
{
|
||||||
|
public ArrayPtr<byte> Data;
|
||||||
|
public bool InUse;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal struct InternalFrameBufferList
|
||||||
|
{
|
||||||
|
public ArrayPtr<InternalFrameBuffer> IntFb;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static class FrameBuffers
|
||||||
|
{
|
||||||
|
public static int GetFrameBuffer(MemoryAllocator allocator, Ptr<InternalFrameBufferList> cbPriv, ulong minSize,
|
||||||
|
ref VpxCodecFrameBuffer fb)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
Ptr<InternalFrameBufferList> intFbList = cbPriv;
|
||||||
|
if (intFbList.IsNull)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find a free frame buffer.
|
||||||
|
for (i = 0; i < intFbList.Value.IntFb.Length; ++i)
|
||||||
|
{
|
||||||
|
if (!intFbList.Value.IntFb[i].InUse)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == intFbList.Value.IntFb.Length)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ulong)intFbList.Value.IntFb[i].Data.Length < minSize)
|
||||||
|
{
|
||||||
|
if (!intFbList.Value.IntFb[i].Data.IsNull)
|
||||||
|
{
|
||||||
|
allocator.Free(intFbList.Value.IntFb[i].Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The data must be zeroed to fix a valgrind error from the C loop filter
|
||||||
|
// due to access uninitialized memory in frame border. It could be
|
||||||
|
// skipped if border were totally removed.
|
||||||
|
intFbList.Value.IntFb[i].Data = allocator.Allocate<byte>((int)minSize);
|
||||||
|
if (intFbList.Value.IntFb[i].Data.IsNull)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fb.Data = intFbList.Value.IntFb[i].Data;
|
||||||
|
intFbList.Value.IntFb[i].InUse = true;
|
||||||
|
|
||||||
|
// Set the frame buffer's private data to point at the internal frame buffer.
|
||||||
|
fb.Priv = new Ptr<InternalFrameBuffer>(ref intFbList.Value.IntFb[i]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int ReleaseFrameBuffer(Ptr<InternalFrameBufferList> cbPriv, ref VpxCodecFrameBuffer fb)
|
||||||
|
{
|
||||||
|
if (!fb.Priv.IsNull)
|
||||||
|
{
|
||||||
|
fb.Priv.Value.InUse = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,11 +8,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
internal static class Idct
|
internal static class Idct
|
||||||
{
|
{
|
||||||
private delegate void Transform1D(ReadOnlySpan<int> input, Span<int> output);
|
private delegate void Transform1D(ReadOnlySpan<int> input, Span<int> output);
|
||||||
|
|
||||||
private delegate void HighbdTransform1D(ReadOnlySpan<int> input, Span<int> output, int bd);
|
private delegate void HighbdTransform1D(ReadOnlySpan<int> input, Span<int> output, int bd);
|
||||||
|
|
||||||
private struct Transform2D
|
private struct Transform2D
|
||||||
{
|
{
|
||||||
public Transform1D Cols, Rows; // Vertical and horizontal
|
public readonly Transform1D Cols; // Vertical and horizontal
|
||||||
|
public readonly Transform1D Rows; // Vertical and horizontal
|
||||||
|
|
||||||
public Transform2D(Transform1D cols, Transform1D rows)
|
public Transform2D(Transform1D cols, Transform1D rows)
|
||||||
{
|
{
|
||||||
|
@ -23,7 +25,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
|
||||||
private struct HighbdTransform2D
|
private struct HighbdTransform2D
|
||||||
{
|
{
|
||||||
public HighbdTransform1D Cols, Rows; // Vertical and horizontal
|
public readonly HighbdTransform1D Cols; // Vertical and horizontal
|
||||||
|
public readonly HighbdTransform1D Rows; // Vertical and horizontal
|
||||||
|
|
||||||
public HighbdTransform2D(HighbdTransform1D cols, HighbdTransform1D rows)
|
public HighbdTransform2D(HighbdTransform1D cols, HighbdTransform1D rows)
|
||||||
{
|
{
|
||||||
|
@ -32,24 +35,23 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Transform2D[] Iht4 = new Transform2D[]
|
private static readonly Transform2D[] Iht4 =
|
||||||
{
|
{
|
||||||
new Transform2D(Idct4, Idct4), // DCT_DCT = 0
|
new(Idct4, Idct4), // DCT_DCT = 0
|
||||||
new Transform2D(Iadst4, Idct4), // ADST_DCT = 1
|
new(Iadst4, Idct4), // ADST_DCT = 1
|
||||||
new Transform2D(Idct4, Iadst4), // DCT_ADST = 2
|
new(Idct4, Iadst4), // DCT_ADST = 2
|
||||||
new Transform2D(Iadst4, Iadst4) // ADST_ADST = 3
|
new(Iadst4, Iadst4) // ADST_ADST = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
public static void Iht4x416Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType)
|
public static void Iht4x416Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType)
|
||||||
{
|
{
|
||||||
int i, j;
|
|
||||||
Span<int> output = stackalloc int[4 * 4];
|
Span<int> output = stackalloc int[4 * 4];
|
||||||
Span<int> outptr = output;
|
Span<int> outptr = output;
|
||||||
Span<int> tempIn = stackalloc int[4];
|
Span<int> tempIn = stackalloc int[4];
|
||||||
Span<int> tempOut = stackalloc int[4];
|
Span<int> tempOut = stackalloc int[4];
|
||||||
|
|
||||||
// Inverse transform row vectors
|
// Inverse transform row vectors
|
||||||
for (i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
Iht4[txType].Rows(input, outptr);
|
Iht4[txType].Rows(input, outptr);
|
||||||
input = input.Slice(4);
|
input = input.Slice(4);
|
||||||
|
@ -57,32 +59,32 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inverse transform column vectors
|
// Inverse transform column vectors
|
||||||
for (i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
for (j = 0; j < 4; ++j)
|
for (int j = 0; j < 4; ++j)
|
||||||
{
|
{
|
||||||
tempIn[j] = output[j * 4 + i];
|
tempIn[j] = output[(j * 4) + i];
|
||||||
}
|
}
|
||||||
|
|
||||||
Iht4[txType].Cols(tempIn, tempOut);
|
Iht4[txType].Cols(tempIn, tempOut);
|
||||||
for (j = 0; j < 4; ++j)
|
for (int j = 0; j < 4; ++j)
|
||||||
{
|
{
|
||||||
dest[j * stride + i] = ClipPixelAdd(dest[j * stride + i], BitUtils.RoundPowerOfTwo(tempOut[j], 4));
|
dest[(j * stride) + i] =
|
||||||
|
ClipPixelAdd(dest[(j * stride) + i], BitUtils.RoundPowerOfTwo(tempOut[j], 4));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Transform2D[] Iht8 = new Transform2D[]
|
private static readonly Transform2D[] Iht8 =
|
||||||
{
|
{
|
||||||
new Transform2D(Idct8, Idct8), // DCT_DCT = 0
|
new(Idct8, Idct8), // DCT_DCT = 0
|
||||||
new Transform2D(Iadst8, Idct8), // ADST_DCT = 1
|
new(Iadst8, Idct8), // ADST_DCT = 1
|
||||||
new Transform2D(Idct8, Iadst8), // DCT_ADST = 2
|
new(Idct8, Iadst8), // DCT_ADST = 2
|
||||||
new Transform2D(Iadst8, Iadst8) // ADST_ADST = 3
|
new(Iadst8, Iadst8) // ADST_ADST = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
public static void Iht8x864Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType)
|
public static void Iht8x864Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType)
|
||||||
{
|
{
|
||||||
int i, j;
|
|
||||||
Span<int> output = stackalloc int[8 * 8];
|
Span<int> output = stackalloc int[8 * 8];
|
||||||
Span<int> outptr = output;
|
Span<int> outptr = output;
|
||||||
Span<int> tempIn = stackalloc int[8];
|
Span<int> tempIn = stackalloc int[8];
|
||||||
|
@ -90,7 +92,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
Transform2D ht = Iht8[txType];
|
Transform2D ht = Iht8[txType];
|
||||||
|
|
||||||
// Inverse transform row vectors
|
// Inverse transform row vectors
|
||||||
for (i = 0; i < 8; ++i)
|
for (int i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
ht.Rows(input, outptr);
|
ht.Rows(input, outptr);
|
||||||
input = input.Slice(8);
|
input = input.Slice(8);
|
||||||
|
@ -98,32 +100,32 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inverse transform column vectors
|
// Inverse transform column vectors
|
||||||
for (i = 0; i < 8; ++i)
|
for (int i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
for (j = 0; j < 8; ++j)
|
for (int j = 0; j < 8; ++j)
|
||||||
{
|
{
|
||||||
tempIn[j] = output[j * 8 + i];
|
tempIn[j] = output[(j * 8) + i];
|
||||||
}
|
}
|
||||||
|
|
||||||
ht.Cols(tempIn, tempOut);
|
ht.Cols(tempIn, tempOut);
|
||||||
for (j = 0; j < 8; ++j)
|
for (int j = 0; j < 8; ++j)
|
||||||
{
|
{
|
||||||
dest[j * stride + i] = ClipPixelAdd(dest[j * stride + i], BitUtils.RoundPowerOfTwo(tempOut[j], 5));
|
dest[(j * stride) + i] =
|
||||||
|
ClipPixelAdd(dest[(j * stride) + i], BitUtils.RoundPowerOfTwo(tempOut[j], 5));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Transform2D[] Iht16 = new Transform2D[]
|
private static readonly Transform2D[] Iht16 =
|
||||||
{
|
{
|
||||||
new Transform2D(Idct16, Idct16), // DCT_DCT = 0
|
new(Idct16, Idct16), // DCT_DCT = 0
|
||||||
new Transform2D(Iadst16, Idct16), // ADST_DCT = 1
|
new(Iadst16, Idct16), // ADST_DCT = 1
|
||||||
new Transform2D(Idct16, Iadst16), // DCT_ADST = 2
|
new(Idct16, Iadst16), // DCT_ADST = 2
|
||||||
new Transform2D(Iadst16, Iadst16) // ADST_ADST = 3
|
new(Iadst16, Iadst16) // ADST_ADST = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
public static void Iht16x16256Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType)
|
public static void Iht16x16256Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType)
|
||||||
{
|
{
|
||||||
int i, j;
|
|
||||||
Span<int> output = stackalloc int[16 * 16];
|
Span<int> output = stackalloc int[16 * 16];
|
||||||
Span<int> outptr = output;
|
Span<int> outptr = output;
|
||||||
Span<int> tempIn = stackalloc int[16];
|
Span<int> tempIn = stackalloc int[16];
|
||||||
|
@ -131,7 +133,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
Transform2D ht = Iht16[txType];
|
Transform2D ht = Iht16[txType];
|
||||||
|
|
||||||
// Rows
|
// Rows
|
||||||
for (i = 0; i < 16; ++i)
|
for (int i = 0; i < 16; ++i)
|
||||||
{
|
{
|
||||||
ht.Rows(input, outptr);
|
ht.Rows(input, outptr);
|
||||||
input = input.Slice(16);
|
input = input.Slice(16);
|
||||||
|
@ -139,17 +141,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
|
|
||||||
// Columns
|
// Columns
|
||||||
for (i = 0; i < 16; ++i)
|
for (int i = 0; i < 16; ++i)
|
||||||
{
|
{
|
||||||
for (j = 0; j < 16; ++j)
|
for (int j = 0; j < 16; ++j)
|
||||||
{
|
{
|
||||||
tempIn[j] = output[j * 16 + i];
|
tempIn[j] = output[(j * 16) + i];
|
||||||
}
|
}
|
||||||
|
|
||||||
ht.Cols(tempIn, tempOut);
|
ht.Cols(tempIn, tempOut);
|
||||||
for (j = 0; j < 16; ++j)
|
for (int j = 0; j < 16; ++j)
|
||||||
{
|
{
|
||||||
dest[j * stride + i] = ClipPixelAdd(dest[j * stride + i], BitUtils.RoundPowerOfTwo(tempOut[j], 6));
|
dest[(j * stride) + i] =
|
||||||
|
ClipPixelAdd(dest[(j * stride) + i], BitUtils.RoundPowerOfTwo(tempOut[j], 6));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -283,24 +286,23 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly HighbdTransform2D[] HighbdIht4 = new HighbdTransform2D[]
|
private static readonly HighbdTransform2D[] HighbdIht4 =
|
||||||
{
|
{
|
||||||
new HighbdTransform2D(HighbdIdct4, HighbdIdct4), // DCT_DCT = 0
|
new(HighbdIdct4, HighbdIdct4), // DCT_DCT = 0
|
||||||
new HighbdTransform2D(HighbdIadst4, HighbdIdct4), // ADST_DCT = 1
|
new(HighbdIadst4, HighbdIdct4), // ADST_DCT = 1
|
||||||
new HighbdTransform2D(HighbdIdct4, HighbdIadst4), // DCT_ADST = 2
|
new(HighbdIdct4, HighbdIadst4), // DCT_ADST = 2
|
||||||
new HighbdTransform2D(HighbdIadst4, HighbdIadst4) // ADST_ADST = 3
|
new(HighbdIadst4, HighbdIadst4) // ADST_ADST = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
public static void HighbdIht4x416Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd)
|
public static void HighbdIht4x416Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd)
|
||||||
{
|
{
|
||||||
int i, j;
|
|
||||||
Span<int> output = stackalloc int[4 * 4];
|
Span<int> output = stackalloc int[4 * 4];
|
||||||
Span<int> outptr = output;
|
Span<int> outptr = output;
|
||||||
Span<int> tempIn = stackalloc int[4];
|
Span<int> tempIn = stackalloc int[4];
|
||||||
Span<int> tempOut = stackalloc int[4];
|
Span<int> tempOut = stackalloc int[4];
|
||||||
|
|
||||||
// Inverse transform row vectors.
|
// Inverse transform row vectors.
|
||||||
for (i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
HighbdIht4[txType].Rows(input, outptr, bd);
|
HighbdIht4[txType].Rows(input, outptr, bd);
|
||||||
input = input.Slice(4);
|
input = input.Slice(4);
|
||||||
|
@ -308,32 +310,32 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inverse transform column vectors.
|
// Inverse transform column vectors.
|
||||||
for (i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
for (j = 0; j < 4; ++j)
|
for (int j = 0; j < 4; ++j)
|
||||||
{
|
{
|
||||||
tempIn[j] = output[j * 4 + i];
|
tempIn[j] = output[(j * 4) + i];
|
||||||
}
|
}
|
||||||
|
|
||||||
HighbdIht4[txType].Cols(tempIn, tempOut, bd);
|
HighbdIht4[txType].Cols(tempIn, tempOut, bd);
|
||||||
for (j = 0; j < 4; ++j)
|
for (int j = 0; j < 4; ++j)
|
||||||
{
|
{
|
||||||
dest[j * stride + i] = HighbdClipPixelAdd(dest[j * stride + i], BitUtils.RoundPowerOfTwo(tempOut[j], 4), bd);
|
dest[(j * stride) + i] = HighbdClipPixelAdd(dest[(j * stride) + i],
|
||||||
|
BitUtils.RoundPowerOfTwo(tempOut[j], 4), bd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly HighbdTransform2D[] HighIht8 = new HighbdTransform2D[]
|
private static readonly HighbdTransform2D[] HighIht8 =
|
||||||
{
|
{
|
||||||
new HighbdTransform2D(HighbdIdct8, HighbdIdct8), // DCT_DCT = 0
|
new(HighbdIdct8, HighbdIdct8), // DCT_DCT = 0
|
||||||
new HighbdTransform2D(HighbdIadst8, HighbdIdct8), // ADST_DCT = 1
|
new(HighbdIadst8, HighbdIdct8), // ADST_DCT = 1
|
||||||
new HighbdTransform2D(HighbdIdct8, HighbdIadst8), // DCT_ADST = 2
|
new(HighbdIdct8, HighbdIadst8), // DCT_ADST = 2
|
||||||
new HighbdTransform2D(HighbdIadst8, HighbdIadst8) // ADST_ADST = 3
|
new(HighbdIadst8, HighbdIadst8) // ADST_ADST = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
public static void HighbdIht8x864Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd)
|
public static void HighbdIht8x864Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd)
|
||||||
{
|
{
|
||||||
int i, j;
|
|
||||||
Span<int> output = stackalloc int[8 * 8];
|
Span<int> output = stackalloc int[8 * 8];
|
||||||
Span<int> outptr = output;
|
Span<int> outptr = output;
|
||||||
Span<int> tempIn = stackalloc int[8];
|
Span<int> tempIn = stackalloc int[8];
|
||||||
|
@ -341,7 +343,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
HighbdTransform2D ht = HighIht8[txType];
|
HighbdTransform2D ht = HighIht8[txType];
|
||||||
|
|
||||||
// Inverse transform row vectors.
|
// Inverse transform row vectors.
|
||||||
for (i = 0; i < 8; ++i)
|
for (int i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
ht.Rows(input, outptr, bd);
|
ht.Rows(input, outptr, bd);
|
||||||
input = input.Slice(8);
|
input = input.Slice(8);
|
||||||
|
@ -349,32 +351,33 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inverse transform column vectors.
|
// Inverse transform column vectors.
|
||||||
for (i = 0; i < 8; ++i)
|
for (int i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
for (j = 0; j < 8; ++j)
|
for (int j = 0; j < 8; ++j)
|
||||||
{
|
{
|
||||||
tempIn[j] = output[j * 8 + i];
|
tempIn[j] = output[(j * 8) + i];
|
||||||
}
|
}
|
||||||
|
|
||||||
ht.Cols(tempIn, tempOut, bd);
|
ht.Cols(tempIn, tempOut, bd);
|
||||||
for (j = 0; j < 8; ++j)
|
for (int j = 0; j < 8; ++j)
|
||||||
{
|
{
|
||||||
dest[j * stride + i] = HighbdClipPixelAdd(dest[j * stride + i], BitUtils.RoundPowerOfTwo(tempOut[j], 5), bd);
|
dest[(j * stride) + i] = HighbdClipPixelAdd(dest[(j * stride) + i],
|
||||||
|
BitUtils.RoundPowerOfTwo(tempOut[j], 5), bd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly HighbdTransform2D[] HighIht16 = new HighbdTransform2D[]
|
private static readonly HighbdTransform2D[] HighIht16 =
|
||||||
{
|
{
|
||||||
new HighbdTransform2D(HighbdIdct16, HighbdIdct16), // DCT_DCT = 0
|
new(HighbdIdct16, HighbdIdct16), // DCT_DCT = 0
|
||||||
new HighbdTransform2D(HighbdIadst16, HighbdIdct16), // ADST_DCT = 1
|
new(HighbdIadst16, HighbdIdct16), // ADST_DCT = 1
|
||||||
new HighbdTransform2D(HighbdIdct16, HighbdIadst16), // DCT_ADST = 2
|
new(HighbdIdct16, HighbdIadst16), // DCT_ADST = 2
|
||||||
new HighbdTransform2D(HighbdIadst16, HighbdIadst16) // ADST_ADST = 3
|
new(HighbdIadst16, HighbdIadst16) // ADST_ADST = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
public static void HighbdIht16x16256Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd)
|
public static void HighbdIht16x16256Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType,
|
||||||
|
int bd)
|
||||||
{
|
{
|
||||||
int i, j;
|
|
||||||
Span<int> output = stackalloc int[16 * 16];
|
Span<int> output = stackalloc int[16 * 16];
|
||||||
Span<int> outptr = output;
|
Span<int> outptr = output;
|
||||||
Span<int> tempIn = stackalloc int[16];
|
Span<int> tempIn = stackalloc int[16];
|
||||||
|
@ -382,7 +385,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
HighbdTransform2D ht = HighIht16[txType];
|
HighbdTransform2D ht = HighIht16[txType];
|
||||||
|
|
||||||
// Rows
|
// Rows
|
||||||
for (i = 0; i < 16; ++i)
|
for (int i = 0; i < 16; ++i)
|
||||||
{
|
{
|
||||||
ht.Rows(input, outptr, bd);
|
ht.Rows(input, outptr, bd);
|
||||||
input = input.Slice(16);
|
input = input.Slice(16);
|
||||||
|
@ -390,17 +393,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
|
|
||||||
// Columns
|
// Columns
|
||||||
for (i = 0; i < 16; ++i)
|
for (int i = 0; i < 16; ++i)
|
||||||
{
|
{
|
||||||
for (j = 0; j < 16; ++j)
|
for (int j = 0; j < 16; ++j)
|
||||||
{
|
{
|
||||||
tempIn[j] = output[j * 16 + i];
|
tempIn[j] = output[(j * 16) + i];
|
||||||
}
|
}
|
||||||
|
|
||||||
ht.Cols(tempIn, tempOut, bd);
|
ht.Cols(tempIn, tempOut, bd);
|
||||||
for (j = 0; j < 16; ++j)
|
for (int j = 0; j < 16; ++j)
|
||||||
{
|
{
|
||||||
dest[j * stride + i] = HighbdClipPixelAdd(dest[j * stride + i], BitUtils.RoundPowerOfTwo(tempOut[j], 6), bd);
|
dest[(j * stride) + i] = HighbdClipPixelAdd(dest[(j * stride) + i],
|
||||||
|
BitUtils.RoundPowerOfTwo(tempOut[j], 6), bd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -440,7 +444,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
// DC only DCT coefficient
|
// DC only DCT coefficient
|
||||||
if (eob == 1)
|
if (eob == 1)
|
||||||
{
|
{
|
||||||
vpx_Highbdidct8x8_1_add_c(input, dest, stride, bd);
|
VpxHighbdidct8x81AddC(input, dest, stride, bd);
|
||||||
}
|
}
|
||||||
else if (eob <= 12)
|
else if (eob <= 12)
|
||||||
{
|
{
|
||||||
|
@ -497,7 +501,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iht
|
// Iht
|
||||||
public static void HighbdIht4x4Add(TxType txType, ReadOnlySpan<int> input, Span<ushort> dest, int stride, int eob, int bd)
|
public static void HighbdIht4x4Add(TxType txType, ReadOnlySpan<int> input, Span<ushort> dest, int stride,
|
||||||
|
int eob, int bd)
|
||||||
{
|
{
|
||||||
if (txType == TxType.DctDct)
|
if (txType == TxType.DctDct)
|
||||||
{
|
{
|
||||||
|
@ -509,7 +514,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void HighbdIht8x8Add(TxType txType, ReadOnlySpan<int> input, Span<ushort> dest, int stride, int eob, int bd)
|
public static void HighbdIht8x8Add(TxType txType, ReadOnlySpan<int> input, Span<ushort> dest, int stride,
|
||||||
|
int eob, int bd)
|
||||||
{
|
{
|
||||||
if (txType == TxType.DctDct)
|
if (txType == TxType.DctDct)
|
||||||
{
|
{
|
||||||
|
@ -521,7 +527,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void HighbdIht16x16Add(TxType txType, ReadOnlySpan<int> input, Span<ushort> dest, int stride, int eob, int bd)
|
public static void HighbdIht16x16Add(TxType txType, ReadOnlySpan<int> input, Span<ushort> dest, int stride,
|
||||||
|
int eob, int bd)
|
||||||
{
|
{
|
||||||
if (txType == TxType.DctDct)
|
if (txType == TxType.DctDct)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Nvdec.Vp9
|
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
class InternalErrorException : Exception
|
internal class InternalErrorException : Exception
|
||||||
{
|
{
|
||||||
public InternalErrorException(string message) : base(message)
|
public InternalErrorException(string message) : base(message)
|
||||||
{
|
{
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -84,7 +84,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
},
|
},
|
||||||
new TxSize[][][]
|
new TxSize[][][]
|
||||||
{
|
{
|
||||||
// BLOCK_4X8
|
// BLOCK_4x8
|
||||||
new TxSize[][] { new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 }, new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 } },
|
new TxSize[][] { new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 }, new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 } },
|
||||||
new TxSize[][] { new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 }, new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 } },
|
new TxSize[][] { new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 }, new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 } },
|
||||||
new TxSize[][] { new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 }, new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 } },
|
new TxSize[][] { new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 }, new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 } },
|
||||||
|
@ -92,7 +92,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
},
|
},
|
||||||
new TxSize[][][]
|
new TxSize[][][]
|
||||||
{
|
{
|
||||||
// BLOCK_8X4
|
// BLOCK_8x4
|
||||||
new TxSize[][] { new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 }, new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 } },
|
new TxSize[][] { new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 }, new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 } },
|
||||||
new TxSize[][] { new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 }, new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 } },
|
new TxSize[][] { new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 }, new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 } },
|
||||||
new TxSize[][] { new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 }, new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 } },
|
new TxSize[][] { new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 }, new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 } },
|
||||||
|
@ -108,7 +108,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
},
|
},
|
||||||
new TxSize[][][]
|
new TxSize[][][]
|
||||||
{
|
{
|
||||||
// BLOCK_8X16
|
// BLOCK_8x16
|
||||||
new TxSize[][] { new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 }, new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 } },
|
new TxSize[][] { new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 }, new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 } },
|
||||||
new TxSize[][] { new TxSize[] { TxSize.Tx8x8, TxSize.Tx8x8 }, new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 } },
|
new TxSize[][] { new TxSize[] { TxSize.Tx8x8, TxSize.Tx8x8 }, new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 } },
|
||||||
new TxSize[][] { new TxSize[] { TxSize.Tx8x8, TxSize.Tx8x8 }, new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 } },
|
new TxSize[][] { new TxSize[] { TxSize.Tx8x8, TxSize.Tx8x8 }, new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 } },
|
||||||
|
@ -116,7 +116,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
},
|
},
|
||||||
new TxSize[][][]
|
new TxSize[][][]
|
||||||
{
|
{
|
||||||
// BLOCK_16X8
|
// BLOCK_16x8
|
||||||
new TxSize[][] { new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 }, new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 } },
|
new TxSize[][] { new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 }, new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 } },
|
||||||
new TxSize[][] { new TxSize[] { TxSize.Tx8x8, TxSize.Tx4x4 }, new TxSize[] { TxSize.Tx8x8, TxSize.Tx4x4 } },
|
new TxSize[][] { new TxSize[] { TxSize.Tx8x8, TxSize.Tx4x4 }, new TxSize[] { TxSize.Tx8x8, TxSize.Tx4x4 } },
|
||||||
new TxSize[][] { new TxSize[] { TxSize.Tx8x8, TxSize.Tx4x4 }, new TxSize[] { TxSize.Tx8x8, TxSize.Tx8x8 } },
|
new TxSize[][] { new TxSize[] { TxSize.Tx8x8, TxSize.Tx4x4 }, new TxSize[] { TxSize.Tx8x8, TxSize.Tx8x8 } },
|
||||||
|
@ -132,7 +132,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
},
|
},
|
||||||
new TxSize[][][]
|
new TxSize[][][]
|
||||||
{
|
{
|
||||||
// BLOCK_16X32
|
// BLOCK_16x32
|
||||||
new TxSize[][] { new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 }, new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 } },
|
new TxSize[][] { new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 }, new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 } },
|
||||||
new TxSize[][] { new TxSize[] { TxSize.Tx8x8, TxSize.Tx8x8 }, new TxSize[] { TxSize.Tx8x8, TxSize.Tx8x8 } },
|
new TxSize[][] { new TxSize[] { TxSize.Tx8x8, TxSize.Tx8x8 }, new TxSize[] { TxSize.Tx8x8, TxSize.Tx8x8 } },
|
||||||
new TxSize[][] { new TxSize[] { TxSize.Tx16x16, TxSize.Tx16x16 }, new TxSize[] { TxSize.Tx8x8, TxSize.Tx8x8 } },
|
new TxSize[][] { new TxSize[] { TxSize.Tx16x16, TxSize.Tx16x16 }, new TxSize[] { TxSize.Tx8x8, TxSize.Tx8x8 } },
|
||||||
|
@ -140,7 +140,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
},
|
},
|
||||||
new TxSize[][][]
|
new TxSize[][][]
|
||||||
{
|
{
|
||||||
// BLOCK_32X16
|
// BLOCK_32x16
|
||||||
new TxSize[][] { new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 }, new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 } },
|
new TxSize[][] { new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 }, new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 } },
|
||||||
new TxSize[][] { new TxSize[] { TxSize.Tx8x8, TxSize.Tx8x8 }, new TxSize[] { TxSize.Tx8x8, TxSize.Tx8x8 } },
|
new TxSize[][] { new TxSize[] { TxSize.Tx8x8, TxSize.Tx8x8 }, new TxSize[] { TxSize.Tx8x8, TxSize.Tx8x8 } },
|
||||||
new TxSize[][] { new TxSize[] { TxSize.Tx16x16, TxSize.Tx8x8 }, new TxSize[] { TxSize.Tx16x16, TxSize.Tx8x8 } },
|
new TxSize[][] { new TxSize[] { TxSize.Tx16x16, TxSize.Tx8x8 }, new TxSize[] { TxSize.Tx16x16, TxSize.Tx8x8 } },
|
||||||
|
@ -156,7 +156,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
},
|
},
|
||||||
new TxSize[][][]
|
new TxSize[][][]
|
||||||
{
|
{
|
||||||
// BLOCK_32X64
|
// BLOCK_32x64
|
||||||
new TxSize[][] { new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 }, new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 } },
|
new TxSize[][] { new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 }, new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 } },
|
||||||
new TxSize[][] { new TxSize[] { TxSize.Tx8x8, TxSize.Tx8x8 }, new TxSize[] { TxSize.Tx8x8, TxSize.Tx8x8 } },
|
new TxSize[][] { new TxSize[] { TxSize.Tx8x8, TxSize.Tx8x8 }, new TxSize[] { TxSize.Tx8x8, TxSize.Tx8x8 } },
|
||||||
new TxSize[][] { new TxSize[] { TxSize.Tx16x16, TxSize.Tx16x16 }, new TxSize[] { TxSize.Tx16x16, TxSize.Tx16x16 } },
|
new TxSize[][] { new TxSize[] { TxSize.Tx16x16, TxSize.Tx16x16 }, new TxSize[] { TxSize.Tx16x16, TxSize.Tx16x16 } },
|
||||||
|
@ -164,7 +164,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
},
|
},
|
||||||
new TxSize[][][]
|
new TxSize[][][]
|
||||||
{
|
{
|
||||||
// BLOCK_64X32
|
// BLOCK_64x32
|
||||||
new TxSize[][] { new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 }, new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 } },
|
new TxSize[][] { new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 }, new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 } },
|
||||||
new TxSize[][] { new TxSize[] { TxSize.Tx8x8, TxSize.Tx8x8 }, new TxSize[] { TxSize.Tx8x8, TxSize.Tx8x8 } },
|
new TxSize[][] { new TxSize[] { TxSize.Tx8x8, TxSize.Tx8x8 }, new TxSize[] { TxSize.Tx8x8, TxSize.Tx8x8 } },
|
||||||
new TxSize[][] { new TxSize[] { TxSize.Tx16x16, TxSize.Tx16x16 }, new TxSize[] { TxSize.Tx16x16, TxSize.Tx16x16 } },
|
new TxSize[][] { new TxSize[] { TxSize.Tx16x16, TxSize.Tx16x16 }, new TxSize[] { TxSize.Tx16x16, TxSize.Tx16x16 } },
|
||||||
|
@ -172,7 +172,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
},
|
},
|
||||||
new TxSize[][][]
|
new TxSize[][][]
|
||||||
{
|
{
|
||||||
// BLOCK_64X64
|
// BLOCK_64x64
|
||||||
new TxSize[][] { new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 }, new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 } },
|
new TxSize[][] { new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 }, new TxSize[] { TxSize.Tx4x4, TxSize.Tx4x4 } },
|
||||||
new TxSize[][] { new TxSize[] { TxSize.Tx8x8, TxSize.Tx8x8 }, new TxSize[] { TxSize.Tx8x8, TxSize.Tx8x8 } },
|
new TxSize[][] { new TxSize[] { TxSize.Tx8x8, TxSize.Tx8x8 }, new TxSize[] { TxSize.Tx8x8, TxSize.Tx8x8 } },
|
||||||
new TxSize[][] { new TxSize[] { TxSize.Tx16x16, TxSize.Tx16x16 }, new TxSize[] { TxSize.Tx16x16, TxSize.Tx16x16 } },
|
new TxSize[][] { new TxSize[] { TxSize.Tx16x16, TxSize.Tx16x16 }, new TxSize[] { TxSize.Tx16x16, TxSize.Tx16x16 } },
|
||||||
|
@ -198,18 +198,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
public static readonly PartitionContextPair[] PartitionContextLookup = new PartitionContextPair[]
|
public static readonly PartitionContextPair[] PartitionContextLookup = new PartitionContextPair[]
|
||||||
{
|
{
|
||||||
new PartitionContextPair(15, 15), // 4X4 - {0b1111, 0b1111}
|
new PartitionContextPair(15, 15), // 4X4 - {0b1111, 0b1111}
|
||||||
new PartitionContextPair(15, 14), // 4X8 - {0b1111, 0b1110}
|
new PartitionContextPair(15, 14), // 4x8 - {0b1111, 0b1110}
|
||||||
new PartitionContextPair(14, 15), // 8X4 - {0b1110, 0b1111}
|
new PartitionContextPair(14, 15), // 8x4 - {0b1110, 0b1111}
|
||||||
new PartitionContextPair(14, 14), // 8X8 - {0b1110, 0b1110}
|
new PartitionContextPair(14, 14), // 8X8 - {0b1110, 0b1110}
|
||||||
new PartitionContextPair(14, 12), // 8X16 - {0b1110, 0b1100}
|
new PartitionContextPair(14, 12), // 8x16 - {0b1110, 0b1100}
|
||||||
new PartitionContextPair(12, 14), // 16X8 - {0b1100, 0b1110}
|
new PartitionContextPair(12, 14), // 16x8 - {0b1100, 0b1110}
|
||||||
new PartitionContextPair(12, 12), // 16X16 - {0b1100, 0b1100}
|
new PartitionContextPair(12, 12), // 16X16 - {0b1100, 0b1100}
|
||||||
new PartitionContextPair(12, 8), // 16X32 - {0b1100, 0b1000}
|
new PartitionContextPair(12, 8), // 16x32 - {0b1100, 0b1000}
|
||||||
new PartitionContextPair(8, 12), // 32X16 - {0b1000, 0b1100}
|
new PartitionContextPair(8, 12), // 32x16 - {0b1000, 0b1100}
|
||||||
new PartitionContextPair(8, 8), // 32X32 - {0b1000, 0b1000}
|
new PartitionContextPair(8, 8), // 32X32 - {0b1000, 0b1000}
|
||||||
new PartitionContextPair(8, 0), // 32X64 - {0b1000, 0b0000}
|
new PartitionContextPair(8, 0), // 32x64 - {0b1000, 0b0000}
|
||||||
new PartitionContextPair(0, 8), // 64X32 - {0b0000, 0b1000}
|
new PartitionContextPair(0, 8), // 64x32 - {0b0000, 0b1000}
|
||||||
new PartitionContextPair(0, 0), // 64X64 - {0b0000, 0b0000}
|
new PartitionContextPair(0, 0), // 64x64 - {0b0000, 0b0000}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Filter
|
// Filter
|
||||||
|
@ -281,7 +281,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly Array8<short>[][] Vp9FilterKernels = new Array8<short>[][]
|
public static readonly Array8<short>[][] FilterKernels = new Array8<short>[][]
|
||||||
{
|
{
|
||||||
SubPelFilters8, SubPelFilters8Lp, SubPelFilters8S, BilinearFilters
|
SubPelFilters8, SubPelFilters8Lp, SubPelFilters8S, BilinearFilters
|
||||||
};
|
};
|
||||||
|
@ -797,22 +797,22 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
959, 990, 991, 1022, 0, 0,
|
959, 990, 991, 1022, 0, 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly short[] Vp9DefaultIscan4X4 = new short[]
|
private static readonly short[] DefaultIscan4X4 = new short[]
|
||||||
{
|
{
|
||||||
0, 2, 5, 8, 1, 3, 9, 12, 4, 7, 11, 14, 6, 10, 13, 15,
|
0, 2, 5, 8, 1, 3, 9, 12, 4, 7, 11, 14, 6, 10, 13, 15,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly short[] Vp9ColIscan4X4 = new short[]
|
private static readonly short[] ColIscan4X4 = new short[]
|
||||||
{
|
{
|
||||||
0, 3, 7, 11, 1, 5, 9, 12, 2, 6, 10, 14, 4, 8, 13, 15,
|
0, 3, 7, 11, 1, 5, 9, 12, 2, 6, 10, 14, 4, 8, 13, 15,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly short[] Vp9RowIscan4X4 = new short[]
|
private static readonly short[] RowIscan4X4 = new short[]
|
||||||
{
|
{
|
||||||
0, 1, 3, 5, 2, 4, 6, 9, 7, 8, 11, 13, 10, 12, 14, 15,
|
0, 1, 3, 5, 2, 4, 6, 9, 7, 8, 11, 13, 10, 12, 14, 15,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly short[] Vp9ColIscan8X8 = new short[]
|
private static readonly short[] ColIscan8X8 = new short[]
|
||||||
{
|
{
|
||||||
0, 3, 8, 15, 22, 32, 40, 47, 1, 5, 11, 18, 26, 34, 44, 51,
|
0, 3, 8, 15, 22, 32, 40, 47, 1, 5, 11, 18, 26, 34, 44, 51,
|
||||||
2, 7, 13, 20, 28, 38, 46, 54, 4, 10, 16, 24, 31, 41, 50, 56,
|
2, 7, 13, 20, 28, 38, 46, 54, 4, 10, 16, 24, 31, 41, 50, 56,
|
||||||
|
@ -820,7 +820,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
14, 23, 30, 37, 45, 53, 59, 62, 19, 29, 36, 42, 49, 57, 61, 63,
|
14, 23, 30, 37, 45, 53, 59, 62, 19, 29, 36, 42, 49, 57, 61, 63,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly short[] Vp9RowIscan8X8 = new short[]
|
private static readonly short[] RowIscan8X8 = new short[]
|
||||||
{
|
{
|
||||||
0, 1, 2, 5, 8, 12, 19, 24, 3, 4, 7, 10, 15, 20, 30, 39,
|
0, 1, 2, 5, 8, 12, 19, 24, 3, 4, 7, 10, 15, 20, 30, 39,
|
||||||
6, 9, 13, 16, 21, 27, 37, 46, 11, 14, 17, 23, 28, 34, 44, 52,
|
6, 9, 13, 16, 21, 27, 37, 46, 11, 14, 17, 23, 28, 34, 44, 52,
|
||||||
|
@ -828,7 +828,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
32, 36, 42, 47, 51, 54, 60, 61, 40, 45, 48, 53, 56, 58, 62, 63,
|
32, 36, 42, 47, 51, 54, 60, 61, 40, 45, 48, 53, 56, 58, 62, 63,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly short[] Vp9DefaultIscan8X8 = new short[]
|
private static readonly short[] DefaultIscan8X8 = new short[]
|
||||||
{
|
{
|
||||||
0, 2, 5, 9, 14, 22, 31, 37, 1, 4, 8, 13, 19, 26, 38, 44,
|
0, 2, 5, 9, 14, 22, 31, 37, 1, 4, 8, 13, 19, 26, 38, 44,
|
||||||
3, 6, 10, 17, 24, 30, 42, 49, 7, 11, 15, 21, 29, 36, 47, 53,
|
3, 6, 10, 17, 24, 30, 42, 49, 7, 11, 15, 21, 29, 36, 47, 53,
|
||||||
|
@ -836,7 +836,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
25, 32, 39, 45, 50, 55, 59, 62, 33, 40, 46, 51, 54, 58, 61, 63,
|
25, 32, 39, 45, 50, 55, 59, 62, 33, 40, 46, 51, 54, 58, 61, 63,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly short[] Vp9ColIscan16X16 = new short[]
|
private static readonly short[] ColIscan16X16 = new short[]
|
||||||
{
|
{
|
||||||
0, 4, 11, 20, 31, 43, 59, 75, 85, 109, 130, 150, 165, 181, 195, 198,
|
0, 4, 11, 20, 31, 43, 59, 75, 85, 109, 130, 150, 165, 181, 195, 198,
|
||||||
1, 6, 14, 23, 34, 47, 64, 81, 95, 114, 135, 153, 171, 188, 201, 212,
|
1, 6, 14, 23, 34, 47, 64, 81, 95, 114, 135, 153, 171, 188, 201, 212,
|
||||||
|
@ -856,7 +856,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
65, 88, 107, 124, 139, 152, 163, 177, 185, 199, 221, 234, 243, 248, 252, 255,
|
65, 88, 107, 124, 139, 152, 163, 177, 185, 199, 221, 234, 243, 248, 252, 255,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly short[] Vp9RowIscan16X16 = new short[]
|
private static readonly short[] RowIscan16X16 = new short[]
|
||||||
{
|
{
|
||||||
0, 1, 2, 4, 6, 9, 12, 17, 22, 29, 36, 43, 54, 64, 76,
|
0, 1, 2, 4, 6, 9, 12, 17, 22, 29, 36, 43, 54, 64, 76,
|
||||||
86, 3, 5, 7, 11, 15, 19, 25, 32, 38, 48, 59, 68, 84, 99,
|
86, 3, 5, 7, 11, 15, 19, 25, 32, 38, 48, 59, 68, 84, 99,
|
||||||
|
@ -878,7 +878,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
255,
|
255,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly short[] Vp9DefaultIscan16X16 = new short[]
|
private static readonly short[] DefaultIscan16X16 = new short[]
|
||||||
{
|
{
|
||||||
0, 2, 5, 9, 17, 24, 36, 44, 55, 72, 88, 104, 128, 143, 166,
|
0, 2, 5, 9, 17, 24, 36, 44, 55, 72, 88, 104, 128, 143, 166,
|
||||||
179, 1, 4, 8, 13, 20, 30, 40, 54, 66, 79, 96, 113, 141, 154,
|
179, 1, 4, 8, 13, 20, 30, 40, 54, 66, 79, 96, 113, 141, 154,
|
||||||
|
@ -900,7 +900,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
255,
|
255,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly short[] Vp9DefaultIscan32X32 = new short[]
|
private static readonly short[] DefaultIscan32X32 = new short[]
|
||||||
{
|
{
|
||||||
0, 2, 5, 10, 17, 25, 38, 47, 62, 83, 101, 121, 145,
|
0, 2, 5, 10, 17, 25, 38, 47, 62, 83, 101, 121, 145,
|
||||||
170, 193, 204, 210, 219, 229, 233, 245, 257, 275, 299, 342, 356,
|
170, 193, 204, 210, 219, 229, 233, 245, 257, 275, 299, 342, 356,
|
||||||
|
@ -997,94 +997,94 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly ScanOrder[] Vp9DefaultScanOrders = new ScanOrder[]
|
public static readonly ScanOrder[] DefaultScanOrders = new ScanOrder[]
|
||||||
{
|
{
|
||||||
new ScanOrder(DefaultScan4X4, Vp9DefaultIscan4X4, DefaultScan4X4Neighbors),
|
new ScanOrder(DefaultScan4X4, DefaultIscan4X4, DefaultScan4X4Neighbors),
|
||||||
new ScanOrder(DefaultScan8X8, Vp9DefaultIscan8X8, DefaultScan8X8Neighbors),
|
new ScanOrder(DefaultScan8X8, DefaultIscan8X8, DefaultScan8X8Neighbors),
|
||||||
new ScanOrder(DefaultScan16X16, Vp9DefaultIscan16X16, DefaultScan16X16Neighbors),
|
new ScanOrder(DefaultScan16X16, DefaultIscan16X16, DefaultScan16X16Neighbors),
|
||||||
new ScanOrder(DefaultScan32X32, Vp9DefaultIscan32X32, DefaultScan32X32Neighbors)
|
new ScanOrder(DefaultScan32X32, DefaultIscan32X32, DefaultScan32X32Neighbors)
|
||||||
};
|
};
|
||||||
|
|
||||||
public static readonly ScanOrder[][] Vp9ScanOrders = new ScanOrder[][]
|
public static readonly ScanOrder[][] ScanOrders = new ScanOrder[][]
|
||||||
{
|
{
|
||||||
new ScanOrder[]
|
new ScanOrder[]
|
||||||
{ // TX_4X4
|
{ // TX_4X4
|
||||||
new ScanOrder(DefaultScan4X4, Vp9DefaultIscan4X4, DefaultScan4X4Neighbors),
|
new ScanOrder(DefaultScan4X4, DefaultIscan4X4, DefaultScan4X4Neighbors),
|
||||||
new ScanOrder(RowScan4X4, Vp9RowIscan4X4, RowScan4X4Neighbors),
|
new ScanOrder(RowScan4X4, RowIscan4X4, RowScan4X4Neighbors),
|
||||||
new ScanOrder(ColScan4X4, Vp9ColIscan4X4, ColScan4X4Neighbors),
|
new ScanOrder(ColScan4X4, ColIscan4X4, ColScan4X4Neighbors),
|
||||||
new ScanOrder(DefaultScan4X4, Vp9DefaultIscan4X4, DefaultScan4X4Neighbors)
|
new ScanOrder(DefaultScan4X4, DefaultIscan4X4, DefaultScan4X4Neighbors)
|
||||||
},
|
},
|
||||||
new ScanOrder[]
|
new ScanOrder[]
|
||||||
{ // TX_8X8
|
{ // TX_8X8
|
||||||
new ScanOrder(DefaultScan8X8, Vp9DefaultIscan8X8, DefaultScan8X8Neighbors),
|
new ScanOrder(DefaultScan8X8, DefaultIscan8X8, DefaultScan8X8Neighbors),
|
||||||
new ScanOrder(RowScan8X8, Vp9RowIscan8X8, RowScan8X8Neighbors),
|
new ScanOrder(RowScan8X8, RowIscan8X8, RowScan8X8Neighbors),
|
||||||
new ScanOrder(ColScan8X8, Vp9ColIscan8X8, ColScan8X8Neighbors),
|
new ScanOrder(ColScan8X8, ColIscan8X8, ColScan8X8Neighbors),
|
||||||
new ScanOrder(DefaultScan8X8, Vp9DefaultIscan8X8, DefaultScan8X8Neighbors)
|
new ScanOrder(DefaultScan8X8, DefaultIscan8X8, DefaultScan8X8Neighbors)
|
||||||
},
|
},
|
||||||
new ScanOrder[]
|
new ScanOrder[]
|
||||||
{ // TX_16X16
|
{ // TX_16X16
|
||||||
new ScanOrder(DefaultScan16X16, Vp9DefaultIscan16X16, DefaultScan16X16Neighbors),
|
new ScanOrder(DefaultScan16X16, DefaultIscan16X16, DefaultScan16X16Neighbors),
|
||||||
new ScanOrder(RowScan16X16, Vp9RowIscan16X16, RowScan16X16Neighbors),
|
new ScanOrder(RowScan16X16, RowIscan16X16, RowScan16X16Neighbors),
|
||||||
new ScanOrder(ColScan16X16, Vp9ColIscan16X16, ColScan16X16Neighbors),
|
new ScanOrder(ColScan16X16, ColIscan16X16, ColScan16X16Neighbors),
|
||||||
new ScanOrder(DefaultScan16X16, Vp9DefaultIscan16X16, DefaultScan16X16Neighbors)
|
new ScanOrder(DefaultScan16X16, DefaultIscan16X16, DefaultScan16X16Neighbors)
|
||||||
},
|
},
|
||||||
new ScanOrder[]
|
new ScanOrder[]
|
||||||
{ // TX_32X32
|
{ // TX_32X32
|
||||||
new ScanOrder(DefaultScan32X32, Vp9DefaultIscan32X32, DefaultScan32X32Neighbors),
|
new ScanOrder(DefaultScan32X32, DefaultIscan32X32, DefaultScan32X32Neighbors),
|
||||||
new ScanOrder(DefaultScan32X32, Vp9DefaultIscan32X32, DefaultScan32X32Neighbors),
|
new ScanOrder(DefaultScan32X32, DefaultIscan32X32, DefaultScan32X32Neighbors),
|
||||||
new ScanOrder(DefaultScan32X32, Vp9DefaultIscan32X32, DefaultScan32X32Neighbors),
|
new ScanOrder(DefaultScan32X32, DefaultIscan32X32, DefaultScan32X32Neighbors),
|
||||||
new ScanOrder(DefaultScan32X32, Vp9DefaultIscan32X32, DefaultScan32X32Neighbors)
|
new ScanOrder(DefaultScan32X32, DefaultIscan32X32, DefaultScan32X32Neighbors)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Entropy MV
|
// Entropy MV
|
||||||
|
|
||||||
public static readonly sbyte[] Vp9MvJointTree = new sbyte[]
|
public static readonly sbyte[] MvJointTree = new sbyte[]
|
||||||
{
|
{
|
||||||
-(sbyte)MvJointType.MvJointZero, 2, -(sbyte)MvJointType.MvJointHnzvz, 4, -(sbyte)MvJointType.MvJointHzvnz, -(sbyte)MvJointType.MvJointHnzvnz
|
-(sbyte)MvJointType.Zero, 2, -(sbyte)MvJointType.Hnzvz, 4, -(sbyte)MvJointType.Hzvnz, -(sbyte)MvJointType.Hnzvnz
|
||||||
};
|
};
|
||||||
|
|
||||||
public static readonly sbyte[] Vp9MvClassTree = new sbyte[]
|
public static readonly sbyte[] MvClassTree = new sbyte[]
|
||||||
{
|
{
|
||||||
-(sbyte)MvClassType.MvClass0,
|
-(sbyte)MvClassType.Class0,
|
||||||
2,
|
2,
|
||||||
-(sbyte)MvClassType.MvClass1,
|
-(sbyte)MvClassType.Class1,
|
||||||
4,
|
4,
|
||||||
6,
|
6,
|
||||||
8,
|
8,
|
||||||
-(sbyte)MvClassType.MvClass2,
|
-(sbyte)MvClassType.Class2,
|
||||||
-(sbyte)MvClassType.MvClass3,
|
-(sbyte)MvClassType.Class3,
|
||||||
10,
|
10,
|
||||||
12,
|
12,
|
||||||
-(sbyte)MvClassType.MvClass4,
|
-(sbyte)MvClassType.Class4,
|
||||||
-(sbyte)MvClassType.MvClass5,
|
-(sbyte)MvClassType.Class5,
|
||||||
-(sbyte)MvClassType.MvClass6,
|
-(sbyte)MvClassType.Class6,
|
||||||
14,
|
14,
|
||||||
16,
|
16,
|
||||||
18,
|
18,
|
||||||
-(sbyte)MvClassType.MvClass7,
|
-(sbyte)MvClassType.Class7,
|
||||||
-(sbyte)MvClassType.MvClass8,
|
-(sbyte)MvClassType.Class8,
|
||||||
-(sbyte)MvClassType.MvClass9,
|
-(sbyte)MvClassType.Class9,
|
||||||
-(sbyte)MvClassType.MvClass10,
|
-(sbyte)MvClassType.Class10
|
||||||
};
|
};
|
||||||
|
|
||||||
public static ReadOnlySpan<sbyte> Vp9MvFPTree => new sbyte[] { -0, 2, -1, 4, -2, -3 };
|
public static ReadOnlySpan<sbyte> MvFPTree => new sbyte[] { -0, 2, -1, 4, -2, -3 };
|
||||||
|
|
||||||
// Entropy
|
// Entropy
|
||||||
|
|
||||||
public static ReadOnlySpan<byte> Vp9Cat1Prob => new byte[] { 159 };
|
public static ReadOnlySpan<byte> Cat1Prob => new byte[] { 159 };
|
||||||
public static ReadOnlySpan<byte> Vp9Cat2Prob => new byte[] { 165, 145 };
|
public static ReadOnlySpan<byte> Cat2Prob => new byte[] { 165, 145 };
|
||||||
public static ReadOnlySpan<byte> Vp9Cat3Prob => new byte[] { 173, 148, 140 };
|
public static ReadOnlySpan<byte> Cat3Prob => new byte[] { 173, 148, 140 };
|
||||||
public static ReadOnlySpan<byte> Vp9Cat4Prob => new byte[] { 176, 155, 140, 135 };
|
public static ReadOnlySpan<byte> Cat4Prob => new byte[] { 176, 155, 140, 135 };
|
||||||
public static ReadOnlySpan<byte> Vp9Cat5Prob => new byte[] { 180, 157, 141, 134, 130 };
|
public static ReadOnlySpan<byte> Cat5Prob => new byte[] { 180, 157, 141, 134, 130 };
|
||||||
public static ReadOnlySpan<byte> Vp9Cat6Prob => new byte[] { 254, 254, 254, 252, 249, 243, 230, 196, 177, 153, 140, 133, 130, 129 };
|
public static ReadOnlySpan<byte> Cat6Prob => new byte[] { 254, 254, 254, 252, 249, 243, 230, 196, 177, 153, 140, 133, 130, 129 };
|
||||||
|
|
||||||
public static ReadOnlySpan<byte> Vp9Cat6ProbHigh12 => new byte[]
|
public static ReadOnlySpan<byte> Cat6ProbHigh12 => new byte[]
|
||||||
{
|
{
|
||||||
255, 255, 255, 255, 254, 254, 54, 252, 249, 243, 230, 196, 177, 153, 140, 133, 130, 129
|
255, 255, 255, 255, 254, 254, 54, 252, 249, 243, 230, 196, 177, 153, 140, 133, 130, 129
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly byte[] Vp9CoefbandTrans8X8Plus = new byte[]
|
private static readonly byte[] CoefbandTrans8X8Plus = new byte[]
|
||||||
{
|
{
|
||||||
0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5,
|
0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5,
|
||||||
// Beyond MAXBAND_INDEX+1 all values are filled as 5
|
// Beyond MAXBAND_INDEX+1 all values are filled as 5
|
||||||
|
@ -1129,17 +1129,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static ReadOnlySpan<byte> Vp9CoefbandTrans4X4 => new byte[]
|
private static ReadOnlySpan<byte> CoefbandTrans4X4 => new byte[]
|
||||||
{
|
{
|
||||||
0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5,
|
0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
public static ReadOnlySpan<byte> get_band_translate(TxSize txSize)
|
public static ReadOnlySpan<byte> GetBandTranslate(TxSize txSize)
|
||||||
{
|
{
|
||||||
return txSize == TxSize.Tx4x4 ? Vp9CoefbandTrans4X4 : Vp9CoefbandTrans8X8Plus;
|
return txSize == TxSize.Tx4x4 ? CoefbandTrans4X4 : CoefbandTrans8X8Plus;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly byte[][] Vp9Pareto8Full = new byte[][]
|
public static readonly byte[][] Pareto8Full = new byte[][]
|
||||||
{
|
{
|
||||||
new byte[] { 3, 86, 128, 6, 86, 23, 88, 29 },
|
new byte[] { 3, 86, 128, 6, 86, 23, 88, 29 },
|
||||||
new byte[] { 6, 86, 128, 11, 87, 42, 91, 52 },
|
new byte[] { 6, 86, 128, 11, 87, 42, 91, 52 },
|
||||||
|
@ -1399,7 +1399,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Array indices are identical to previously-existing INTRAMODECONTEXTNODES. */
|
/* Array indices are identical to previously-existing INTRAMODECONTEXTNODES. */
|
||||||
public static readonly sbyte[] Vp9IntraModeTree = new sbyte[]
|
public static readonly sbyte[] IntraModeTree = new sbyte[]
|
||||||
{
|
{
|
||||||
-(sbyte)PredictionMode.DcPred, 2, /* 0 = DC_NODE */
|
-(sbyte)PredictionMode.DcPred, 2, /* 0 = DC_NODE */
|
||||||
-(sbyte)PredictionMode.TmPred, 4, /* 1 = TM_NODE */
|
-(sbyte)PredictionMode.TmPred, 4, /* 1 = TM_NODE */
|
||||||
|
@ -1412,7 +1412,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
-(sbyte)PredictionMode.D153Pred, -(sbyte)PredictionMode.D207Pred /* 8 = D153_NODE */
|
-(sbyte)PredictionMode.D153Pred, -(sbyte)PredictionMode.D207Pred /* 8 = D153_NODE */
|
||||||
};
|
};
|
||||||
|
|
||||||
public static readonly sbyte[] Vp9InterModeTree = new sbyte[]
|
public static readonly sbyte[] InterModeTree = new sbyte[]
|
||||||
{
|
{
|
||||||
-((sbyte)PredictionMode.ZeroMv - (sbyte)PredictionMode. NearestMv), 2,
|
-((sbyte)PredictionMode.ZeroMv - (sbyte)PredictionMode. NearestMv), 2,
|
||||||
-((sbyte)PredictionMode.NearestMv - (sbyte)PredictionMode.NearestMv), 4,
|
-((sbyte)PredictionMode.NearestMv - (sbyte)PredictionMode.NearestMv), 4,
|
||||||
|
@ -1420,17 +1420,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
-((sbyte)PredictionMode.NewMv - (sbyte)PredictionMode.NearestMv)
|
-((sbyte)PredictionMode.NewMv - (sbyte)PredictionMode.NearestMv)
|
||||||
};
|
};
|
||||||
|
|
||||||
public static readonly sbyte[] Vp9PartitionTree = new sbyte[]
|
public static readonly sbyte[] PartitionTree = new sbyte[]
|
||||||
{
|
{
|
||||||
-(sbyte)PartitionType.PartitionNone, 2, -(sbyte)PartitionType.PartitionHorz, 4, -(sbyte)PartitionType.PartitionVert, -(sbyte)PartitionType.PartitionSplit
|
-(sbyte)PartitionType.PartitionNone, 2, -(sbyte)PartitionType.PartitionHorz, 4, -(sbyte)PartitionType.PartitionVert, -(sbyte)PartitionType.PartitionSplit
|
||||||
};
|
};
|
||||||
|
|
||||||
public static readonly sbyte[] Vp9SwitchableInterpTree = new sbyte[]
|
public static readonly sbyte[] SwitchableInterpTree = new sbyte[]
|
||||||
{
|
{
|
||||||
-Constants.EightTap, 2, -Constants.EightTapSmooth, -Constants.EightTapSharp
|
-Constants.EightTap, 2, -Constants.EightTapSmooth, -Constants.EightTapSharp
|
||||||
};
|
};
|
||||||
|
|
||||||
public static readonly sbyte[] Vp9SegmentTree = new sbyte[]
|
public static readonly sbyte[] SegmentTree = new sbyte[]
|
||||||
{
|
{
|
||||||
2, 4, 6, 8, 10, 12, 0, -1, -2, -3, -4, -5, -6, -7
|
2, 4, 6, 8, 10, 12, 0, -1, -2, -3, -4, -5, -6, -7
|
||||||
};
|
};
|
||||||
|
@ -1497,7 +1497,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
new Position( -2, -1 ),
|
new Position( -2, -1 ),
|
||||||
new Position( -1, -2 ),
|
new Position( -1, -2 ),
|
||||||
new Position( -2, -2 ) },
|
new Position( -2, -2 ) },
|
||||||
// 4X8
|
// 4x8
|
||||||
new Position[] { new Position( -1, 0 ),
|
new Position[] { new Position( -1, 0 ),
|
||||||
new Position( 0, -1 ),
|
new Position( 0, -1 ),
|
||||||
new Position( -1, -1 ),
|
new Position( -1, -1 ),
|
||||||
|
@ -1506,7 +1506,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
new Position( -2, -1 ),
|
new Position( -2, -1 ),
|
||||||
new Position( -1, -2 ),
|
new Position( -1, -2 ),
|
||||||
new Position( -2, -2 ) },
|
new Position( -2, -2 ) },
|
||||||
// 8X4
|
// 8x4
|
||||||
new Position[] { new Position( -1, 0 ),
|
new Position[] { new Position( -1, 0 ),
|
||||||
new Position( 0, -1 ),
|
new Position( 0, -1 ),
|
||||||
new Position( -1, -1 ),
|
new Position( -1, -1 ),
|
||||||
|
@ -1524,7 +1524,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
new Position( -2, -1 ),
|
new Position( -2, -1 ),
|
||||||
new Position( -1, -2 ),
|
new Position( -1, -2 ),
|
||||||
new Position( -2, -2 ) },
|
new Position( -2, -2 ) },
|
||||||
// 8X16
|
// 8x16
|
||||||
new Position[] { new Position( 0, -1 ),
|
new Position[] { new Position( 0, -1 ),
|
||||||
new Position( -1, 0 ),
|
new Position( -1, 0 ),
|
||||||
new Position( 1, -1 ),
|
new Position( 1, -1 ),
|
||||||
|
@ -1533,7 +1533,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
new Position( -2, 0 ),
|
new Position( -2, 0 ),
|
||||||
new Position( -2, -1 ),
|
new Position( -2, -1 ),
|
||||||
new Position( -1, -2 ) },
|
new Position( -1, -2 ) },
|
||||||
// 16X8
|
// 16x8
|
||||||
new Position[] { new Position( -1, 0 ),
|
new Position[] { new Position( -1, 0 ),
|
||||||
new Position( 0, -1 ),
|
new Position( 0, -1 ),
|
||||||
new Position( -1, 1 ),
|
new Position( -1, 1 ),
|
||||||
|
@ -1551,7 +1551,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
new Position( -3, 0 ),
|
new Position( -3, 0 ),
|
||||||
new Position( 0, -3 ),
|
new Position( 0, -3 ),
|
||||||
new Position( -3, -3 ) },
|
new Position( -3, -3 ) },
|
||||||
// 16X32
|
// 16x32
|
||||||
new Position[] { new Position( 0, -1 ),
|
new Position[] { new Position( 0, -1 ),
|
||||||
new Position( -1, 0 ),
|
new Position( -1, 0 ),
|
||||||
new Position( 2, -1 ),
|
new Position( 2, -1 ),
|
||||||
|
@ -1560,7 +1560,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
new Position( 0, -3 ),
|
new Position( 0, -3 ),
|
||||||
new Position( -3, 0 ),
|
new Position( -3, 0 ),
|
||||||
new Position( -3, -3 ) },
|
new Position( -3, -3 ) },
|
||||||
// 32X16
|
// 32x16
|
||||||
new Position[] { new Position( -1, 0 ),
|
new Position[] { new Position( -1, 0 ),
|
||||||
new Position( 0, -1 ),
|
new Position( 0, -1 ),
|
||||||
new Position( -1, 2 ),
|
new Position( -1, 2 ),
|
||||||
|
@ -1578,7 +1578,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
new Position( -3, 0 ),
|
new Position( -3, 0 ),
|
||||||
new Position( 0, -3 ),
|
new Position( 0, -3 ),
|
||||||
new Position( -3, -3 ) },
|
new Position( -3, -3 ) },
|
||||||
// 32X64
|
// 32x64
|
||||||
new Position[] { new Position( 0, -1 ),
|
new Position[] { new Position( 0, -1 ),
|
||||||
new Position( -1, 0 ),
|
new Position( -1, 0 ),
|
||||||
new Position( 4, -1 ),
|
new Position( 4, -1 ),
|
||||||
|
@ -1587,7 +1587,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
new Position( 0, -3 ),
|
new Position( 0, -3 ),
|
||||||
new Position( -3, 0 ),
|
new Position( -3, 0 ),
|
||||||
new Position( 2, -1 ) },
|
new Position( 2, -1 ) },
|
||||||
// 64X32
|
// 64x32
|
||||||
new Position[] { new Position( -1, 0 ),
|
new Position[] { new Position( -1, 0 ),
|
||||||
new Position( 0, -1 ),
|
new Position( 0, -1 ),
|
||||||
new Position( -1, 4 ),
|
new Position( -1, 4 ),
|
||||||
|
@ -1596,7 +1596,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
new Position( -3, 0 ),
|
new Position( -3, 0 ),
|
||||||
new Position( 0, -3 ),
|
new Position( 0, -3 ),
|
||||||
new Position( -1, 2 ) },
|
new Position( -1, 2 ) },
|
||||||
// 64X64
|
// 64x64
|
||||||
new Position[] { new Position( -1, 3 ),
|
new Position[] { new Position( -1, 3 ),
|
||||||
new Position( 3, -1 ),
|
new Position( 3, -1 ),
|
||||||
new Position( -1, 4 ),
|
new Position( -1, 4 ),
|
||||||
|
|
|
@ -13,7 +13,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
// left of the entries corresponding to real macroblocks.
|
// left of the entries corresponding to real macroblocks.
|
||||||
// The prediction flags in these dummy entries are initialized to 0.
|
// The prediction flags in these dummy entries are initialized to 0.
|
||||||
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
|
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
|
||||||
{ // both edges available
|
{
|
||||||
|
// both edges available
|
||||||
if (!xd.AboveMi.Value.HasSecondRef() && !xd.LeftMi.Value.HasSecondRef())
|
if (!xd.AboveMi.Value.HasSecondRef() && !xd.LeftMi.Value.HasSecondRef())
|
||||||
{
|
{
|
||||||
// Neither edge uses comp pred (0/1)
|
// Neither edge uses comp pred (0/1)
|
||||||
|
@ -23,12 +24,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
else if (!xd.AboveMi.Value.HasSecondRef())
|
else if (!xd.AboveMi.Value.HasSecondRef())
|
||||||
{
|
{
|
||||||
// One of two edges uses comp pred (2/3)
|
// One of two edges uses comp pred (2/3)
|
||||||
ctx = 2 + (xd.AboveMi.Value.RefFrame[0] == cm.CompFixedRef || !xd.AboveMi.Value.IsInterBlock() ? 1 : 0);
|
ctx = 2 + (xd.AboveMi.Value.RefFrame[0] == cm.CompFixedRef || !xd.AboveMi.Value.IsInterBlock()
|
||||||
|
? 1
|
||||||
|
: 0);
|
||||||
}
|
}
|
||||||
else if (!xd.LeftMi.Value.HasSecondRef())
|
else if (!xd.LeftMi.Value.HasSecondRef())
|
||||||
{
|
{
|
||||||
// One of two edges uses comp pred (2/3)
|
// One of two edges uses comp pred (2/3)
|
||||||
ctx = 2 + (xd.LeftMi.Value.RefFrame[0] == cm.CompFixedRef || !xd.LeftMi.Value.IsInterBlock() ? 1 : 0);
|
ctx = 2 +
|
||||||
|
(xd.LeftMi.Value.RefFrame[0] == cm.CompFixedRef || !xd.LeftMi.Value.IsInterBlock() ? 1 : 0);
|
||||||
}
|
}
|
||||||
else // Both edges use comp pred (4)
|
else // Both edges use comp pred (4)
|
||||||
{
|
{
|
||||||
|
@ -36,7 +40,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
|
else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
|
||||||
{ // One edge available
|
{
|
||||||
|
// One edge available
|
||||||
ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
|
ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
|
||||||
|
|
||||||
if (!edgeMi.HasSecondRef())
|
if (!edgeMi.HasSecondRef())
|
||||||
|
@ -51,9 +56,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // No edges available (1)
|
{
|
||||||
|
// No edges available (1)
|
||||||
ctx = 1;
|
ctx = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Assert(ctx >= 0 && ctx < Constants.CompInterContexts);
|
Debug.Assert(ctx >= 0 && ctx < Constants.CompInterContexts);
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
@ -70,29 +77,33 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
int varRefIdx = fixRefIdx == 0 ? 1 : 0;
|
int varRefIdx = fixRefIdx == 0 ? 1 : 0;
|
||||||
|
|
||||||
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
|
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
|
||||||
{ // Both edges available
|
{
|
||||||
|
// Both edges available
|
||||||
bool aboveIntra = !xd.AboveMi.Value.IsInterBlock();
|
bool aboveIntra = !xd.AboveMi.Value.IsInterBlock();
|
||||||
bool leftIntra = !xd.LeftMi.Value.IsInterBlock();
|
bool leftIntra = !xd.LeftMi.Value.IsInterBlock();
|
||||||
|
|
||||||
if (aboveIntra && leftIntra)
|
if (aboveIntra && leftIntra)
|
||||||
{ // Intra/Intra (2)
|
{
|
||||||
|
// Intra/Intra (2)
|
||||||
predContext = 2;
|
predContext = 2;
|
||||||
}
|
}
|
||||||
else if (aboveIntra || leftIntra)
|
else if (aboveIntra || leftIntra)
|
||||||
{ // Intra/Inter
|
{
|
||||||
|
// Intra/Inter
|
||||||
ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value;
|
ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value;
|
||||||
|
|
||||||
if (!edgeMi.HasSecondRef()) // single pred (1/3)
|
if (!edgeMi.HasSecondRef()) // single pred (1/3)
|
||||||
{
|
{
|
||||||
predContext = 1 + 2 * (edgeMi.RefFrame[0] != cm.CompVarRef[1] ? 1 : 0);
|
predContext = 1 + (2 * (edgeMi.RefFrame[0] != cm.CompVarRef[1] ? 1 : 0));
|
||||||
}
|
}
|
||||||
else // Comp pred (1/3)
|
else // Comp pred (1/3)
|
||||||
{
|
{
|
||||||
predContext = 1 + 2 * (edgeMi.RefFrame[varRefIdx] != cm.CompVarRef[1] ? 1 : 0);
|
predContext = 1 + (2 * (edgeMi.RefFrame[varRefIdx] != cm.CompVarRef[1] ? 1 : 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // Inter/Inter
|
{
|
||||||
|
// Inter/Inter
|
||||||
bool lSg = !xd.LeftMi.Value.HasSecondRef();
|
bool lSg = !xd.LeftMi.Value.HasSecondRef();
|
||||||
bool aSg = !xd.AboveMi.Value.HasSecondRef();
|
bool aSg = !xd.AboveMi.Value.HasSecondRef();
|
||||||
sbyte vrfa = aSg ? xd.AboveMi.Value.RefFrame[0] : xd.AboveMi.Value.RefFrame[varRefIdx];
|
sbyte vrfa = aSg ? xd.AboveMi.Value.RefFrame[0] : xd.AboveMi.Value.RefFrame[varRefIdx];
|
||||||
|
@ -103,7 +114,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
predContext = 0;
|
predContext = 0;
|
||||||
}
|
}
|
||||||
else if (lSg && aSg)
|
else if (lSg && aSg)
|
||||||
{ // Single/Single
|
{
|
||||||
|
// Single/Single
|
||||||
if ((vrfa == cm.CompFixedRef && vrfl == cm.CompVarRef[0]) ||
|
if ((vrfa == cm.CompFixedRef && vrfl == cm.CompVarRef[0]) ||
|
||||||
(vrfl == cm.CompFixedRef && vrfa == cm.CompVarRef[0]))
|
(vrfl == cm.CompFixedRef && vrfa == cm.CompVarRef[0]))
|
||||||
{
|
{
|
||||||
|
@ -119,7 +131,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (lSg || aSg)
|
else if (lSg || aSg)
|
||||||
{ // Single/Comp
|
{
|
||||||
|
// Single/Comp
|
||||||
sbyte vrfc = lSg ? vrfa : vrfl;
|
sbyte vrfc = lSg ? vrfa : vrfl;
|
||||||
sbyte rfs = aSg ? vrfa : vrfl;
|
sbyte rfs = aSg ? vrfa : vrfl;
|
||||||
if (vrfc == cm.CompVarRef[1] && rfs != cm.CompVarRef[1])
|
if (vrfc == cm.CompVarRef[1] && rfs != cm.CompVarRef[1])
|
||||||
|
@ -136,7 +149,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (vrfa == vrfl)
|
else if (vrfa == vrfl)
|
||||||
{ // Comp/Comp
|
{
|
||||||
|
// Comp/Comp
|
||||||
predContext = 4;
|
predContext = 4;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -146,7 +160,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
|
else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
|
||||||
{ // One edge available
|
{
|
||||||
|
// One edge available
|
||||||
ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
|
ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
|
||||||
|
|
||||||
if (!edgeMi.IsInterBlock())
|
if (!edgeMi.IsInterBlock())
|
||||||
|
@ -166,9 +181,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // No edges available (2)
|
{
|
||||||
|
// No edges available (2)
|
||||||
predContext = 2;
|
predContext = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
|
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
|
||||||
return predContext;
|
return predContext;
|
||||||
}
|
}
|
||||||
|
@ -181,16 +198,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
// left of the entries corresponding to real macroblocks.
|
// left of the entries corresponding to real macroblocks.
|
||||||
// The prediction flags in these dummy entries are initialized to 0.
|
// The prediction flags in these dummy entries are initialized to 0.
|
||||||
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
|
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
|
||||||
{ // Both edges available
|
{
|
||||||
|
// Both edges available
|
||||||
bool aboveIntra = !xd.AboveMi.Value.IsInterBlock();
|
bool aboveIntra = !xd.AboveMi.Value.IsInterBlock();
|
||||||
bool leftIntra = !xd.LeftMi.Value.IsInterBlock();
|
bool leftIntra = !xd.LeftMi.Value.IsInterBlock();
|
||||||
|
|
||||||
if (aboveIntra && leftIntra)
|
if (aboveIntra && leftIntra)
|
||||||
{ // Intra/Intra
|
{
|
||||||
|
// Intra/Intra
|
||||||
predContext = 2;
|
predContext = 2;
|
||||||
}
|
}
|
||||||
else if (aboveIntra || leftIntra)
|
else if (aboveIntra || leftIntra)
|
||||||
{ // Intra/Inter or Inter/Intra
|
{
|
||||||
|
// Intra/Inter or Inter/Intra
|
||||||
ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value;
|
ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value;
|
||||||
if (!edgeMi.HasSecondRef())
|
if (!edgeMi.HasSecondRef())
|
||||||
{
|
{
|
||||||
|
@ -199,11 +219,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
predContext = 1 + (edgeMi.RefFrame[0] == Constants.LastFrame ||
|
predContext = 1 + (edgeMi.RefFrame[0] == Constants.LastFrame ||
|
||||||
edgeMi.RefFrame[1] == Constants.LastFrame ? 1 : 0);
|
edgeMi.RefFrame[1] == Constants.LastFrame
|
||||||
|
? 1
|
||||||
|
: 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // Inter/Inter
|
{
|
||||||
|
// Inter/Inter
|
||||||
bool aboveHasSecond = xd.AboveMi.Value.HasSecondRef();
|
bool aboveHasSecond = xd.AboveMi.Value.HasSecondRef();
|
||||||
bool leftHasSecond = xd.LeftMi.Value.HasSecondRef();
|
bool leftHasSecond = xd.LeftMi.Value.HasSecondRef();
|
||||||
sbyte above0 = xd.AboveMi.Value.RefFrame[0];
|
sbyte above0 = xd.AboveMi.Value.RefFrame[0];
|
||||||
|
@ -214,7 +237,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
if (aboveHasSecond && leftHasSecond)
|
if (aboveHasSecond && leftHasSecond)
|
||||||
{
|
{
|
||||||
predContext = 1 + (above0 == Constants.LastFrame || above1 == Constants.LastFrame ||
|
predContext = 1 + (above0 == Constants.LastFrame || above1 == Constants.LastFrame ||
|
||||||
left0 == Constants.LastFrame || left1 == Constants.LastFrame ? 1 : 0);
|
left0 == Constants.LastFrame || left1 == Constants.LastFrame
|
||||||
|
? 1
|
||||||
|
: 0);
|
||||||
}
|
}
|
||||||
else if (aboveHasSecond || leftHasSecond)
|
else if (aboveHasSecond || leftHasSecond)
|
||||||
{
|
{
|
||||||
|
@ -228,24 +253,28 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
predContext = (crf1 == Constants.LastFrame || crf2 == Constants.LastFrame ? 1 : 0);
|
predContext = crf1 == Constants.LastFrame || crf2 == Constants.LastFrame ? 1 : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
predContext = 2 * (above0 == Constants.LastFrame ? 1 : 0) + 2 * (left0 == Constants.LastFrame ? 1 : 0);
|
predContext = (2 * (above0 == Constants.LastFrame ? 1 : 0)) +
|
||||||
|
(2 * (left0 == Constants.LastFrame ? 1 : 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
|
else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
|
||||||
{ // One edge available
|
{
|
||||||
|
// One edge available
|
||||||
ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
|
ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
|
||||||
if (!edgeMi.IsInterBlock())
|
if (!edgeMi.IsInterBlock())
|
||||||
{ // Intra
|
{
|
||||||
|
// Intra
|
||||||
predContext = 2;
|
predContext = 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // Inter
|
{
|
||||||
|
// Inter
|
||||||
if (!edgeMi.HasSecondRef())
|
if (!edgeMi.HasSecondRef())
|
||||||
{
|
{
|
||||||
predContext = 4 * (edgeMi.RefFrame[0] == Constants.LastFrame ? 1 : 0);
|
predContext = 4 * (edgeMi.RefFrame[0] == Constants.LastFrame ? 1 : 0);
|
||||||
|
@ -253,14 +282,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
predContext = 1 + (edgeMi.RefFrame[0] == Constants.LastFrame ||
|
predContext = 1 + (edgeMi.RefFrame[0] == Constants.LastFrame ||
|
||||||
edgeMi.RefFrame[1] == Constants.LastFrame ? 1 : 0);
|
edgeMi.RefFrame[1] == Constants.LastFrame
|
||||||
|
? 1
|
||||||
|
: 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // No edges available
|
{
|
||||||
|
// No edges available
|
||||||
predContext = 2;
|
predContext = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
|
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
|
||||||
return predContext;
|
return predContext;
|
||||||
}
|
}
|
||||||
|
@ -274,16 +307,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
// left of the entries corresponding to real macroblocks.
|
// left of the entries corresponding to real macroblocks.
|
||||||
// The prediction flags in these dummy entries are initialized to 0.
|
// The prediction flags in these dummy entries are initialized to 0.
|
||||||
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
|
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
|
||||||
{ // Both edges available
|
{
|
||||||
|
// Both edges available
|
||||||
bool aboveIntra = !xd.AboveMi.Value.IsInterBlock();
|
bool aboveIntra = !xd.AboveMi.Value.IsInterBlock();
|
||||||
bool leftIntra = !xd.LeftMi.Value.IsInterBlock();
|
bool leftIntra = !xd.LeftMi.Value.IsInterBlock();
|
||||||
|
|
||||||
if (aboveIntra && leftIntra)
|
if (aboveIntra && leftIntra)
|
||||||
{ // Intra/Intra
|
{
|
||||||
|
// Intra/Intra
|
||||||
predContext = 2;
|
predContext = 2;
|
||||||
}
|
}
|
||||||
else if (aboveIntra || leftIntra)
|
else if (aboveIntra || leftIntra)
|
||||||
{ // Intra/Inter or Inter/Intra
|
{
|
||||||
|
// Intra/Inter or Inter/Intra
|
||||||
ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value;
|
ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value;
|
||||||
if (!edgeMi.HasSecondRef())
|
if (!edgeMi.HasSecondRef())
|
||||||
{
|
{
|
||||||
|
@ -298,12 +334,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
predContext = 1 + 2 * (edgeMi.RefFrame[0] == Constants.GoldenFrame ||
|
predContext = 1 + (2 * (edgeMi.RefFrame[0] == Constants.GoldenFrame ||
|
||||||
edgeMi.RefFrame[1] == Constants.GoldenFrame ? 1 : 0);
|
edgeMi.RefFrame[1] == Constants.GoldenFrame
|
||||||
|
? 1
|
||||||
|
: 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // Inter/Inter
|
{
|
||||||
|
// Inter/Inter
|
||||||
bool aboveHasSecond = xd.AboveMi.Value.HasSecondRef();
|
bool aboveHasSecond = xd.AboveMi.Value.HasSecondRef();
|
||||||
bool leftHasSecond = xd.LeftMi.Value.HasSecondRef();
|
bool leftHasSecond = xd.LeftMi.Value.HasSecondRef();
|
||||||
sbyte above0 = xd.AboveMi.Value.RefFrame[0];
|
sbyte above0 = xd.AboveMi.Value.RefFrame[0];
|
||||||
|
@ -316,7 +355,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
if (above0 == left0 && above1 == left1)
|
if (above0 == left0 && above1 == left1)
|
||||||
{
|
{
|
||||||
predContext = 3 * (above0 == Constants.GoldenFrame || above1 == Constants.GoldenFrame ||
|
predContext = 3 * (above0 == Constants.GoldenFrame || above1 == Constants.GoldenFrame ||
|
||||||
left0 == Constants.GoldenFrame || left1 == Constants.GoldenFrame ? 1 : 0);
|
left0 == Constants.GoldenFrame || left1 == Constants.GoldenFrame
|
||||||
|
? 1
|
||||||
|
: 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -339,7 +380,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
predContext = 1 + 2 * (crf1 == Constants.GoldenFrame || crf2 == Constants.GoldenFrame ? 1 : 0);
|
predContext =
|
||||||
|
1 + (2 * (crf1 == Constants.GoldenFrame || crf2 == Constants.GoldenFrame ? 1 : 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -350,18 +392,20 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
else if (above0 == Constants.LastFrame || left0 == Constants.LastFrame)
|
else if (above0 == Constants.LastFrame || left0 == Constants.LastFrame)
|
||||||
{
|
{
|
||||||
sbyte edge0 = (above0 == Constants.LastFrame) ? left0 : above0;
|
sbyte edge0 = above0 == Constants.LastFrame ? left0 : above0;
|
||||||
predContext = 4 * (edge0 == Constants.GoldenFrame ? 1 : 0);
|
predContext = 4 * (edge0 == Constants.GoldenFrame ? 1 : 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
predContext = 2 * (above0 == Constants.GoldenFrame ? 1 : 0) + 2 * (left0 == Constants.GoldenFrame ? 1 : 0);
|
predContext = (2 * (above0 == Constants.GoldenFrame ? 1 : 0)) +
|
||||||
|
(2 * (left0 == Constants.GoldenFrame ? 1 : 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
|
else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
|
||||||
{ // One edge available
|
{
|
||||||
|
// One edge available
|
||||||
ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
|
ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
|
||||||
|
|
||||||
if (!edgeMi.IsInterBlock() || (edgeMi.RefFrame[0] == Constants.LastFrame && !edgeMi.HasSecondRef()))
|
if (!edgeMi.IsInterBlock() || (edgeMi.RefFrame[0] == Constants.LastFrame && !edgeMi.HasSecondRef()))
|
||||||
|
@ -375,13 +419,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
predContext = 3 * (edgeMi.RefFrame[0] == Constants.GoldenFrame ||
|
predContext = 3 * (edgeMi.RefFrame[0] == Constants.GoldenFrame ||
|
||||||
edgeMi.RefFrame[1] == Constants.GoldenFrame ? 1 : 0);
|
edgeMi.RefFrame[1] == Constants.GoldenFrame
|
||||||
|
? 1
|
||||||
|
: 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // No edges available (2)
|
{
|
||||||
|
// No edges available (2)
|
||||||
predContext = 2;
|
predContext = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
|
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
|
||||||
return predContext;
|
return predContext;
|
||||||
}
|
}
|
||||||
|
|
94
src/Ryujinx.Graphics.Nvdec.Vp9/Prob.cs
Normal file
94
src/Ryujinx.Graphics.Nvdec.Vp9/Prob.cs
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
using Ryujinx.Common.Memory;
|
||||||
|
using Ryujinx.Graphics.Nvdec.Vp9.Common;
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
{
|
||||||
|
public static class Prob
|
||||||
|
{
|
||||||
|
public const int MaxProb = 255;
|
||||||
|
|
||||||
|
private static byte GetProb(uint num, uint den)
|
||||||
|
{
|
||||||
|
Debug.Assert(den != 0);
|
||||||
|
{
|
||||||
|
int p = (int)((((ulong)num * 256) + (den >> 1)) / den);
|
||||||
|
// (p > 255) ? 255 : (p < 1) ? 1 : p;
|
||||||
|
int clippedProb = p | ((255 - p) >> 23) | (p == 0 ? 1 : 0);
|
||||||
|
return (byte)clippedProb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte GetBinaryProb(uint n0, uint n1)
|
||||||
|
{
|
||||||
|
uint den = n0 + n1;
|
||||||
|
if (den == 0)
|
||||||
|
{
|
||||||
|
return 128;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetProb(n0, den);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This function assumes prob1 and prob2 are already within [1,255] range. */
|
||||||
|
public static byte WeightedProb(int prob1, int prob2, int factor)
|
||||||
|
{
|
||||||
|
return (byte)BitUtils.RoundPowerOfTwo((prob1 * (256 - factor)) + (prob2 * factor), 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte MergeProbs(byte preProb, ref Array2<uint> ct, uint countSat, uint maxUpdateFactor)
|
||||||
|
{
|
||||||
|
byte prob = GetBinaryProb(ct[0], ct[1]);
|
||||||
|
uint count = Math.Min(ct[0] + ct[1], countSat);
|
||||||
|
uint factor = maxUpdateFactor * count / countSat;
|
||||||
|
return WeightedProb(preProb, prob, (int)factor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MODE_MV_MAX_UPDATE_FACTOR (128) * count / MODE_MV_COUNT_SAT;
|
||||||
|
private static readonly uint[] CountToUpdateFactor =
|
||||||
|
{
|
||||||
|
0, 6, 12, 19, 25, 32, 38, 44, 51, 57, 64, 70, 76, 83, 89, 96, 102, 108, 115, 121, 128
|
||||||
|
};
|
||||||
|
|
||||||
|
private const int ModeMvCountSat = 20;
|
||||||
|
|
||||||
|
public static byte ModeMvMergeProbs(byte preProb, ref Array2<uint> ct)
|
||||||
|
{
|
||||||
|
uint den = ct[0] + ct[1];
|
||||||
|
if (den == 0)
|
||||||
|
{
|
||||||
|
return preProb;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint count = Math.Min(den, ModeMvCountSat);
|
||||||
|
uint factor = CountToUpdateFactor[(int)count];
|
||||||
|
byte prob = GetProb(ct[0], den);
|
||||||
|
return WeightedProb(preProb, prob, (int)factor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static uint TreeMergeProbsImpl(
|
||||||
|
uint i,
|
||||||
|
sbyte[] tree,
|
||||||
|
ReadOnlySpan<byte> preProbs,
|
||||||
|
ReadOnlySpan<uint> counts,
|
||||||
|
Span<byte> probs)
|
||||||
|
{
|
||||||
|
int l = tree[i];
|
||||||
|
uint leftCount = l <= 0 ? counts[-l] : TreeMergeProbsImpl((uint)l, tree, preProbs, counts, probs);
|
||||||
|
int r = tree[i + 1];
|
||||||
|
uint rightCount = r <= 0 ? counts[-r] : TreeMergeProbsImpl((uint)r, tree, preProbs, counts, probs);
|
||||||
|
Array2<uint> ct = new();
|
||||||
|
ct[0] = leftCount;
|
||||||
|
ct[1] = rightCount;
|
||||||
|
probs[(int)(i >> 1)] = ModeMvMergeProbs(preProbs[(int)(i >> 1)], ref ct);
|
||||||
|
return leftCount + rightCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void VpxTreeMergeProbs(sbyte[] tree, ReadOnlySpan<byte> preProbs, ReadOnlySpan<uint> counts,
|
||||||
|
Span<byte> probs)
|
||||||
|
{
|
||||||
|
TreeMergeProbsImpl(0, tree, preProbs, counts, probs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,163 +1,116 @@
|
||||||
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
using System;
|
||||||
using System;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Nvdec.Vp9
|
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
internal static class QuantCommon
|
internal static class QuantCommon
|
||||||
{
|
{
|
||||||
public const int MinQ = 0;
|
|
||||||
public const int MaxQ = 255;
|
public const int MaxQ = 255;
|
||||||
|
public const int QindexBits = 8;
|
||||||
|
|
||||||
private static readonly short[] DcQlookup = new short[]
|
private static readonly short[] DcQlookup =
|
||||||
{
|
{
|
||||||
4, 8, 8, 9, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18,
|
4, 8, 8, 9, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 23, 24, 25, 26, 26, 27, 28, 29,
|
||||||
19, 19, 20, 21, 22, 23, 24, 25, 26, 26, 27, 28, 29, 30,
|
30, 31, 32, 32, 33, 34, 35, 36, 37, 38, 38, 39, 40, 41, 42, 43, 43, 44, 45, 46, 47, 48, 48, 49, 50, 51,
|
||||||
31, 32, 32, 33, 34, 35, 36, 37, 38, 38, 39, 40, 41, 42,
|
52, 53, 53, 54, 55, 56, 57, 57, 58, 59, 60, 61, 62, 62, 63, 64, 65, 66, 66, 67, 68, 69, 70, 70, 71, 72,
|
||||||
43, 43, 44, 45, 46, 47, 48, 48, 49, 50, 51, 52, 53, 53,
|
73, 74, 74, 75, 76, 77, 78, 78, 79, 80, 81, 81, 82, 83, 84, 85, 85, 87, 88, 90, 92, 93, 95, 96, 98, 99,
|
||||||
54, 55, 56, 57, 57, 58, 59, 60, 61, 62, 62, 63, 64, 65,
|
101, 102, 104, 105, 107, 108, 110, 111, 113, 114, 116, 117, 118, 120, 121, 123, 125, 127, 129, 131, 134,
|
||||||
66, 66, 67, 68, 69, 70, 70, 71, 72, 73, 74, 74, 75, 76,
|
136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 161, 164, 166, 169, 172, 174, 177, 180, 182,
|
||||||
77, 78, 78, 79, 80, 81, 81, 82, 83, 84, 85, 85, 87, 88,
|
185, 187, 190, 192, 195, 199, 202, 205, 208, 211, 214, 217, 220, 223, 226, 230, 233, 237, 240, 243, 247,
|
||||||
90, 92, 93, 95, 96, 98, 99, 101, 102, 104, 105, 107, 108, 110,
|
250, 253, 257, 261, 265, 269, 272, 276, 280, 284, 288, 292, 296, 300, 304, 309, 313, 317, 322, 326, 330,
|
||||||
111, 113, 114, 116, 117, 118, 120, 121, 123, 125, 127, 129, 131, 134,
|
335, 340, 344, 349, 354, 359, 364, 369, 374, 379, 384, 389, 395, 400, 406, 411, 417, 423, 429, 435, 441,
|
||||||
136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 161, 164,
|
447, 454, 461, 467, 475, 482, 489, 497, 505, 513, 522, 530, 539, 549, 559, 569, 579, 590, 602, 614, 626,
|
||||||
166, 169, 172, 174, 177, 180, 182, 185, 187, 190, 192, 195, 199, 202,
|
640, 654, 668, 684, 700, 717, 736, 755, 775, 796, 819, 843, 869, 896, 925, 955, 988, 1022, 1058, 1098,
|
||||||
205, 208, 211, 214, 217, 220, 223, 226, 230, 233, 237, 240, 243, 247,
|
1139, 1184, 1232, 1282, 1336
|
||||||
250, 253, 257, 261, 265, 269, 272, 276, 280, 284, 288, 292, 296, 300,
|
|
||||||
304, 309, 313, 317, 322, 326, 330, 335, 340, 344, 349, 354, 359, 364,
|
|
||||||
369, 374, 379, 384, 389, 395, 400, 406, 411, 417, 423, 429, 435, 441,
|
|
||||||
447, 454, 461, 467, 475, 482, 489, 497, 505, 513, 522, 530, 539, 549,
|
|
||||||
559, 569, 579, 590, 602, 614, 626, 640, 654, 668, 684, 700, 717, 736,
|
|
||||||
755, 775, 796, 819, 843, 869, 896, 925, 955, 988, 1022, 1058, 1098, 1139,
|
|
||||||
1184, 1232, 1282, 1336,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly short[] DcQlookup10 = new short[]
|
private static readonly short[] DcQlookup10 =
|
||||||
{
|
{
|
||||||
4, 9, 10, 13, 15, 17, 20, 22, 25, 28, 31, 34, 37,
|
4, 9, 10, 13, 15, 17, 20, 22, 25, 28, 31, 34, 37, 40, 43, 47, 50, 53, 57, 60, 64, 68, 71, 75, 78, 82,
|
||||||
40, 43, 47, 50, 53, 57, 60, 64, 68, 71, 75, 78, 82,
|
86, 90, 93, 97, 101, 105, 109, 113, 116, 120, 124, 128, 132, 136, 140, 143, 147, 151, 155, 159, 163,
|
||||||
86, 90, 93, 97, 101, 105, 109, 113, 116, 120, 124, 128, 132,
|
166, 170, 174, 178, 182, 185, 189, 193, 197, 200, 204, 208, 212, 215, 219, 223, 226, 230, 233, 237, 241,
|
||||||
136, 140, 143, 147, 151, 155, 159, 163, 166, 170, 174, 178, 182,
|
244, 248, 251, 255, 259, 262, 266, 269, 273, 276, 280, 283, 287, 290, 293, 297, 300, 304, 307, 310, 314,
|
||||||
185, 189, 193, 197, 200, 204, 208, 212, 215, 219, 223, 226, 230,
|
317, 321, 324, 327, 331, 334, 337, 343, 350, 356, 362, 369, 375, 381, 387, 394, 400, 406, 412, 418, 424,
|
||||||
233, 237, 241, 244, 248, 251, 255, 259, 262, 266, 269, 273, 276,
|
430, 436, 442, 448, 454, 460, 466, 472, 478, 484, 490, 499, 507, 516, 525, 533, 542, 550, 559, 567, 576,
|
||||||
280, 283, 287, 290, 293, 297, 300, 304, 307, 310, 314, 317, 321,
|
584, 592, 601, 609, 617, 625, 634, 644, 655, 666, 676, 687, 698, 708, 718, 729, 739, 749, 759, 770, 782,
|
||||||
324, 327, 331, 334, 337, 343, 350, 356, 362, 369, 375, 381, 387,
|
795, 807, 819, 831, 844, 856, 868, 880, 891, 906, 920, 933, 947, 961, 975, 988, 1001, 1015, 1030, 1045,
|
||||||
394, 400, 406, 412, 418, 424, 430, 436, 442, 448, 454, 460, 466,
|
1061, 1076, 1090, 1105, 1120, 1137, 1153, 1170, 1186, 1202, 1218, 1236, 1253, 1271, 1288, 1306, 1323,
|
||||||
472, 478, 484, 490, 499, 507, 516, 525, 533, 542, 550, 559, 567,
|
1342, 1361, 1379, 1398, 1416, 1436, 1456, 1476, 1496, 1516, 1537, 1559, 1580, 1601, 1624, 1647, 1670,
|
||||||
576, 584, 592, 601, 609, 617, 625, 634, 644, 655, 666, 676, 687,
|
1692, 1717, 1741, 1766, 1791, 1817, 1844, 1871, 1900, 1929, 1958, 1990, 2021, 2054, 2088, 2123, 2159,
|
||||||
698, 708, 718, 729, 739, 749, 759, 770, 782, 795, 807, 819, 831,
|
2197, 2236, 2276, 2319, 2363, 2410, 2458, 2508, 2561, 2616, 2675, 2737, 2802, 2871, 2944, 3020, 3102,
|
||||||
844, 856, 868, 880, 891, 906, 920, 933, 947, 961, 975, 988, 1001,
|
3188, 3280, 3375, 3478, 3586, 3702, 3823, 3953, 4089, 4236, 4394, 4559, 4737, 4929, 5130, 5347
|
||||||
1015, 1030, 1045, 1061, 1076, 1090, 1105, 1120, 1137, 1153, 1170, 1186, 1202,
|
|
||||||
1218, 1236, 1253, 1271, 1288, 1306, 1323, 1342, 1361, 1379, 1398, 1416, 1436,
|
|
||||||
1456, 1476, 1496, 1516, 1537, 1559, 1580, 1601, 1624, 1647, 1670, 1692, 1717,
|
|
||||||
1741, 1766, 1791, 1817, 1844, 1871, 1900, 1929, 1958, 1990, 2021, 2054, 2088,
|
|
||||||
2123, 2159, 2197, 2236, 2276, 2319, 2363, 2410, 2458, 2508, 2561, 2616, 2675,
|
|
||||||
2737, 2802, 2871, 2944, 3020, 3102, 3188, 3280, 3375, 3478, 3586, 3702, 3823,
|
|
||||||
3953, 4089, 4236, 4394, 4559, 4737, 4929, 5130, 5347,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly short[] DcQlookup12 = new short[]
|
private static readonly short[] DcQlookup12 =
|
||||||
{
|
{
|
||||||
4, 12, 18, 25, 33, 41, 50, 60, 70, 80, 91,
|
4, 12, 18, 25, 33, 41, 50, 60, 70, 80, 91, 103, 115, 127, 140, 153, 166, 180, 194, 208, 222, 237, 251,
|
||||||
103, 115, 127, 140, 153, 166, 180, 194, 208, 222, 237,
|
266, 281, 296, 312, 327, 343, 358, 374, 390, 405, 421, 437, 453, 469, 484, 500, 516, 532, 548, 564, 580,
|
||||||
251, 266, 281, 296, 312, 327, 343, 358, 374, 390, 405,
|
596, 611, 627, 643, 659, 674, 690, 706, 721, 737, 752, 768, 783, 798, 814, 829, 844, 859, 874, 889, 904,
|
||||||
421, 437, 453, 469, 484, 500, 516, 532, 548, 564, 580,
|
919, 934, 949, 964, 978, 993, 1008, 1022, 1037, 1051, 1065, 1080, 1094, 1108, 1122, 1136, 1151, 1165,
|
||||||
596, 611, 627, 643, 659, 674, 690, 706, 721, 737, 752,
|
1179, 1192, 1206, 1220, 1234, 1248, 1261, 1275, 1288, 1302, 1315, 1329, 1342, 1368, 1393, 1419, 1444,
|
||||||
768, 783, 798, 814, 829, 844, 859, 874, 889, 904, 919,
|
1469, 1494, 1519, 1544, 1569, 1594, 1618, 1643, 1668, 1692, 1717, 1741, 1765, 1789, 1814, 1838, 1862,
|
||||||
934, 949, 964, 978, 993, 1008, 1022, 1037, 1051, 1065, 1080,
|
1885, 1909, 1933, 1957, 1992, 2027, 2061, 2096, 2130, 2165, 2199, 2233, 2267, 2300, 2334, 2367, 2400,
|
||||||
1094, 1108, 1122, 1136, 1151, 1165, 1179, 1192, 1206, 1220, 1234,
|
2434, 2467, 2499, 2532, 2575, 2618, 2661, 2704, 2746, 2788, 2830, 2872, 2913, 2954, 2995, 3036, 3076,
|
||||||
1248, 1261, 1275, 1288, 1302, 1315, 1329, 1342, 1368, 1393, 1419,
|
3127, 3177, 3226, 3275, 3324, 3373, 3421, 3469, 3517, 3565, 3621, 3677, 3733, 3788, 3843, 3897, 3951,
|
||||||
1444, 1469, 1494, 1519, 1544, 1569, 1594, 1618, 1643, 1668, 1692,
|
4005, 4058, 4119, 4181, 4241, 4301, 4361, 4420, 4479, 4546, 4612, 4677, 4742, 4807, 4871, 4942, 5013,
|
||||||
1717, 1741, 1765, 1789, 1814, 1838, 1862, 1885, 1909, 1933, 1957,
|
5083, 5153, 5222, 5291, 5367, 5442, 5517, 5591, 5665, 5745, 5825, 5905, 5984, 6063, 6149, 6234, 6319,
|
||||||
1992, 2027, 2061, 2096, 2130, 2165, 2199, 2233, 2267, 2300, 2334,
|
6404, 6495, 6587, 6678, 6769, 6867, 6966, 7064, 7163, 7269, 7376, 7483, 7599, 7715, 7832, 7958, 8085,
|
||||||
2367, 2400, 2434, 2467, 2499, 2532, 2575, 2618, 2661, 2704, 2746,
|
8214, 8352, 8492, 8635, 8788, 8945, 9104, 9275, 9450, 9639, 9832, 10031, 10245, 10465, 10702, 10946,
|
||||||
2788, 2830, 2872, 2913, 2954, 2995, 3036, 3076, 3127, 3177, 3226,
|
11210, 11482, 11776, 12081, 12409, 12750, 13118, 13501, 13913, 14343, 14807, 15290, 15812, 16356, 16943,
|
||||||
3275, 3324, 3373, 3421, 3469, 3517, 3565, 3621, 3677, 3733, 3788,
|
17575, 18237, 18949, 19718, 20521, 21387
|
||||||
3843, 3897, 3951, 4005, 4058, 4119, 4181, 4241, 4301, 4361, 4420,
|
|
||||||
4479, 4546, 4612, 4677, 4742, 4807, 4871, 4942, 5013, 5083, 5153,
|
|
||||||
5222, 5291, 5367, 5442, 5517, 5591, 5665, 5745, 5825, 5905, 5984,
|
|
||||||
6063, 6149, 6234, 6319, 6404, 6495, 6587, 6678, 6769, 6867, 6966,
|
|
||||||
7064, 7163, 7269, 7376, 7483, 7599, 7715, 7832, 7958, 8085, 8214,
|
|
||||||
8352, 8492, 8635, 8788, 8945, 9104, 9275, 9450, 9639, 9832, 10031,
|
|
||||||
10245, 10465, 10702, 10946, 11210, 11482, 11776, 12081, 12409, 12750, 13118,
|
|
||||||
13501, 13913, 14343, 14807, 15290, 15812, 16356, 16943, 17575, 18237, 18949,
|
|
||||||
19718, 20521, 21387,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly short[] AcQlookup = new short[]
|
private static readonly short[] AcQlookup =
|
||||||
{
|
{
|
||||||
4, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
|
4, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
|
||||||
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
|
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
|
||||||
33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
|
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
|
||||||
46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
|
86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 104, 106, 108, 110, 112, 114,
|
||||||
59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
|
116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 155, 158,
|
||||||
72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
|
161, 164, 167, 170, 173, 176, 179, 182, 185, 188, 191, 194, 197, 200, 203, 207, 211, 215, 219, 223, 227,
|
||||||
85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
|
231, 235, 239, 243, 247, 251, 255, 260, 265, 270, 275, 280, 285, 290, 295, 300, 305, 311, 317, 323, 329,
|
||||||
98, 99, 100, 101, 102, 104, 106, 108, 110, 112, 114, 116, 118,
|
335, 341, 347, 353, 359, 366, 373, 380, 387, 394, 401, 408, 416, 424, 432, 440, 448, 456, 465, 474, 483,
|
||||||
120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144,
|
492, 501, 510, 520, 530, 540, 550, 560, 571, 582, 593, 604, 615, 627, 639, 651, 663, 676, 689, 702, 715,
|
||||||
146, 148, 150, 152, 155, 158, 161, 164, 167, 170, 173, 176, 179,
|
729, 743, 757, 771, 786, 801, 816, 832, 848, 864, 881, 898, 915, 933, 951, 969, 988, 1007, 1026, 1046,
|
||||||
182, 185, 188, 191, 194, 197, 200, 203, 207, 211, 215, 219, 223,
|
1066, 1087, 1108, 1129, 1151, 1173, 1196, 1219, 1243, 1267, 1292, 1317, 1343, 1369, 1396, 1423, 1451,
|
||||||
227, 231, 235, 239, 243, 247, 251, 255, 260, 265, 270, 275, 280,
|
1479, 1508, 1537, 1567, 1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828
|
||||||
285, 290, 295, 300, 305, 311, 317, 323, 329, 335, 341, 347, 353,
|
|
||||||
359, 366, 373, 380, 387, 394, 401, 408, 416, 424, 432, 440, 448,
|
|
||||||
456, 465, 474, 483, 492, 501, 510, 520, 530, 540, 550, 560, 571,
|
|
||||||
582, 593, 604, 615, 627, 639, 651, 663, 676, 689, 702, 715, 729,
|
|
||||||
743, 757, 771, 786, 801, 816, 832, 848, 864, 881, 898, 915, 933,
|
|
||||||
951, 969, 988, 1007, 1026, 1046, 1066, 1087, 1108, 1129, 1151, 1173, 1196,
|
|
||||||
1219, 1243, 1267, 1292, 1317, 1343, 1369, 1396, 1423, 1451, 1479, 1508, 1537,
|
|
||||||
1567, 1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly short[] AcQlookup10 = new short[]
|
private static readonly short[] AcQlookup10 =
|
||||||
{
|
{
|
||||||
4, 9, 11, 13, 16, 18, 21, 24, 27, 30, 33, 37, 40,
|
4, 9, 11, 13, 16, 18, 21, 24, 27, 30, 33, 37, 40, 44, 48, 51, 55, 59, 63, 67, 71, 75, 79, 83, 88, 92,
|
||||||
44, 48, 51, 55, 59, 63, 67, 71, 75, 79, 83, 88, 92,
|
96, 100, 105, 109, 114, 118, 122, 127, 131, 136, 140, 145, 149, 154, 158, 163, 168, 172, 177, 181, 186,
|
||||||
96, 100, 105, 109, 114, 118, 122, 127, 131, 136, 140, 145, 149,
|
190, 195, 199, 204, 208, 213, 217, 222, 226, 231, 235, 240, 244, 249, 253, 258, 262, 267, 271, 275, 280,
|
||||||
154, 158, 163, 168, 172, 177, 181, 186, 190, 195, 199, 204, 208,
|
284, 289, 293, 297, 302, 306, 311, 315, 319, 324, 328, 332, 337, 341, 345, 349, 354, 358, 362, 367, 371,
|
||||||
213, 217, 222, 226, 231, 235, 240, 244, 249, 253, 258, 262, 267,
|
375, 379, 384, 388, 392, 396, 401, 409, 417, 425, 433, 441, 449, 458, 466, 474, 482, 490, 498, 506, 514,
|
||||||
271, 275, 280, 284, 289, 293, 297, 302, 306, 311, 315, 319, 324,
|
523, 531, 539, 547, 555, 563, 571, 579, 588, 596, 604, 616, 628, 640, 652, 664, 676, 688, 700, 713, 725,
|
||||||
328, 332, 337, 341, 345, 349, 354, 358, 362, 367, 371, 375, 379,
|
737, 749, 761, 773, 785, 797, 809, 825, 841, 857, 873, 889, 905, 922, 938, 954, 970, 986, 1002, 1018,
|
||||||
384, 388, 392, 396, 401, 409, 417, 425, 433, 441, 449, 458, 466,
|
1038, 1058, 1078, 1098, 1118, 1138, 1158, 1178, 1198, 1218, 1242, 1266, 1290, 1314, 1338, 1362, 1386,
|
||||||
474, 482, 490, 498, 506, 514, 523, 531, 539, 547, 555, 563, 571,
|
1411, 1435, 1463, 1491, 1519, 1547, 1575, 1603, 1631, 1663, 1695, 1727, 1759, 1791, 1823, 1859, 1895,
|
||||||
579, 588, 596, 604, 616, 628, 640, 652, 664, 676, 688, 700, 713,
|
1931, 1967, 2003, 2039, 2079, 2119, 2159, 2199, 2239, 2283, 2327, 2371, 2415, 2459, 2507, 2555, 2603,
|
||||||
725, 737, 749, 761, 773, 785, 797, 809, 825, 841, 857, 873, 889,
|
2651, 2703, 2755, 2807, 2859, 2915, 2971, 3027, 3083, 3143, 3203, 3263, 3327, 3391, 3455, 3523, 3591,
|
||||||
905, 922, 938, 954, 970, 986, 1002, 1018, 1038, 1058, 1078, 1098, 1118,
|
3659, 3731, 3803, 3876, 3952, 4028, 4104, 4184, 4264, 4348, 4432, 4516, 4604, 4692, 4784, 4876, 4972,
|
||||||
1138, 1158, 1178, 1198, 1218, 1242, 1266, 1290, 1314, 1338, 1362, 1386, 1411,
|
5068, 5168, 5268, 5372, 5476, 5584, 5692, 5804, 5916, 6032, 6148, 6268, 6388, 6512, 6640, 6768, 6900,
|
||||||
1435, 1463, 1491, 1519, 1547, 1575, 1603, 1631, 1663, 1695, 1727, 1759, 1791,
|
7036, 7172, 7312
|
||||||
1823, 1859, 1895, 1931, 1967, 2003, 2039, 2079, 2119, 2159, 2199, 2239, 2283,
|
|
||||||
2327, 2371, 2415, 2459, 2507, 2555, 2603, 2651, 2703, 2755, 2807, 2859, 2915,
|
|
||||||
2971, 3027, 3083, 3143, 3203, 3263, 3327, 3391, 3455, 3523, 3591, 3659, 3731,
|
|
||||||
3803, 3876, 3952, 4028, 4104, 4184, 4264, 4348, 4432, 4516, 4604, 4692, 4784,
|
|
||||||
4876, 4972, 5068, 5168, 5268, 5372, 5476, 5584, 5692, 5804, 5916, 6032, 6148,
|
|
||||||
6268, 6388, 6512, 6640, 6768, 6900, 7036, 7172, 7312,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly short[] AcQlookup12 = new short[]
|
private static readonly short[] AcQlookup12 =
|
||||||
{
|
{
|
||||||
4, 13, 19, 27, 35, 44, 54, 64, 75, 87, 99,
|
4, 13, 19, 27, 35, 44, 54, 64, 75, 87, 99, 112, 126, 139, 154, 168, 183, 199, 214, 230, 247, 263, 280,
|
||||||
112, 126, 139, 154, 168, 183, 199, 214, 230, 247, 263,
|
297, 314, 331, 349, 366, 384, 402, 420, 438, 456, 475, 493, 511, 530, 548, 567, 586, 604, 623, 642, 660,
|
||||||
280, 297, 314, 331, 349, 366, 384, 402, 420, 438, 456,
|
679, 698, 716, 735, 753, 772, 791, 809, 828, 846, 865, 884, 902, 920, 939, 957, 976, 994, 1012, 1030,
|
||||||
475, 493, 511, 530, 548, 567, 586, 604, 623, 642, 660,
|
1049, 1067, 1085, 1103, 1121, 1139, 1157, 1175, 1193, 1211, 1229, 1246, 1264, 1282, 1299, 1317, 1335,
|
||||||
679, 698, 716, 735, 753, 772, 791, 809, 828, 846, 865,
|
1352, 1370, 1387, 1405, 1422, 1440, 1457, 1474, 1491, 1509, 1526, 1543, 1560, 1577, 1595, 1627, 1660,
|
||||||
884, 902, 920, 939, 957, 976, 994, 1012, 1030, 1049, 1067,
|
1693, 1725, 1758, 1791, 1824, 1856, 1889, 1922, 1954, 1987, 2020, 2052, 2085, 2118, 2150, 2183, 2216,
|
||||||
1085, 1103, 1121, 1139, 1157, 1175, 1193, 1211, 1229, 1246, 1264,
|
2248, 2281, 2313, 2346, 2378, 2411, 2459, 2508, 2556, 2605, 2653, 2701, 2750, 2798, 2847, 2895, 2943,
|
||||||
1282, 1299, 1317, 1335, 1352, 1370, 1387, 1405, 1422, 1440, 1457,
|
2992, 3040, 3088, 3137, 3185, 3234, 3298, 3362, 3426, 3491, 3555, 3619, 3684, 3748, 3812, 3876, 3941,
|
||||||
1474, 1491, 1509, 1526, 1543, 1560, 1577, 1595, 1627, 1660, 1693,
|
4005, 4069, 4149, 4230, 4310, 4390, 4470, 4550, 4631, 4711, 4791, 4871, 4967, 5064, 5160, 5256, 5352,
|
||||||
1725, 1758, 1791, 1824, 1856, 1889, 1922, 1954, 1987, 2020, 2052,
|
5448, 5544, 5641, 5737, 5849, 5961, 6073, 6185, 6297, 6410, 6522, 6650, 6778, 6906, 7034, 7162, 7290,
|
||||||
2085, 2118, 2150, 2183, 2216, 2248, 2281, 2313, 2346, 2378, 2411,
|
7435, 7579, 7723, 7867, 8011, 8155, 8315, 8475, 8635, 8795, 8956, 9132, 9308, 9484, 9660, 9836, 10028,
|
||||||
2459, 2508, 2556, 2605, 2653, 2701, 2750, 2798, 2847, 2895, 2943,
|
10220, 10412, 10604, 10812, 11020, 11228, 11437, 11661, 11885, 12109, 12333, 12573, 12813, 13053, 13309,
|
||||||
2992, 3040, 3088, 3137, 3185, 3234, 3298, 3362, 3426, 3491, 3555,
|
13565, 13821, 14093, 14365, 14637, 14925, 15213, 15502, 15806, 16110, 16414, 16734, 17054, 17390, 17726,
|
||||||
3619, 3684, 3748, 3812, 3876, 3941, 4005, 4069, 4149, 4230, 4310,
|
18062, 18414, 18766, 19134, 19502, 19886, 20270, 20670, 21070, 21486, 21902, 22334, 22766, 23214, 23662,
|
||||||
4390, 4470, 4550, 4631, 4711, 4791, 4871, 4967, 5064, 5160, 5256,
|
24126, 24590, 25070, 25551, 26047, 26559, 27071, 27599, 28143, 28687, 29247
|
||||||
5352, 5448, 5544, 5641, 5737, 5849, 5961, 6073, 6185, 6297, 6410,
|
|
||||||
6522, 6650, 6778, 6906, 7034, 7162, 7290, 7435, 7579, 7723, 7867,
|
|
||||||
8011, 8155, 8315, 8475, 8635, 8795, 8956, 9132, 9308, 9484, 9660,
|
|
||||||
9836, 10028, 10220, 10412, 10604, 10812, 11020, 11228, 11437, 11661, 11885,
|
|
||||||
12109, 12333, 12573, 12813, 13053, 13309, 13565, 13821, 14093, 14365, 14637,
|
|
||||||
14925, 15213, 15502, 15806, 16110, 16414, 16734, 17054, 17390, 17726, 18062,
|
|
||||||
18414, 18766, 19134, 19502, 19886, 20270, 20670, 21070, 21486, 21902, 22334,
|
|
||||||
22766, 23214, 23662, 24126, 24590, 25070, 25551, 26047, 26559, 27071, 27599,
|
|
||||||
28143, 28687, 29247,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public static short DcQuant(int qindex, int delta, BitDepth bitDepth)
|
public static short DcQuant(int qindex, int delta, BitDepth bitDepth)
|
||||||
|
@ -168,7 +121,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
case BitDepth.Bits10: return DcQlookup10[Math.Clamp(qindex + delta, 0, MaxQ)];
|
case BitDepth.Bits10: return DcQlookup10[Math.Clamp(qindex + delta, 0, MaxQ)];
|
||||||
case BitDepth.Bits12: return DcQlookup12[Math.Clamp(qindex + delta, 0, MaxQ)];
|
case BitDepth.Bits12: return DcQlookup12[Math.Clamp(qindex + delta, 0, MaxQ)];
|
||||||
default:
|
default:
|
||||||
Debug.Assert(false, "bit_depth should be VPX_BITS_8, VPX_BITS_10 or VPX_BITS_12");
|
Debug.Assert(false, "bitDepth should be Bits8, Bits10 or Bits12");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -181,23 +134,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
case BitDepth.Bits10: return AcQlookup10[Math.Clamp(qindex + delta, 0, MaxQ)];
|
case BitDepth.Bits10: return AcQlookup10[Math.Clamp(qindex + delta, 0, MaxQ)];
|
||||||
case BitDepth.Bits12: return AcQlookup12[Math.Clamp(qindex + delta, 0, MaxQ)];
|
case BitDepth.Bits12: return AcQlookup12[Math.Clamp(qindex + delta, 0, MaxQ)];
|
||||||
default:
|
default:
|
||||||
Debug.Assert(false, "bit_depth should be VPX_BITS_8, VPX_BITS_10 or VPX_BITS_12");
|
Debug.Assert(false, "bitDepth should be Bits8, Bits10 or Bits12");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int GetQIndex(ref Segmentation seg, int segmentId, int baseQIndex)
|
|
||||||
{
|
|
||||||
if (seg.IsSegFeatureActive(segmentId, SegLvlFeatures.SegLvlAltQ) != 0)
|
|
||||||
{
|
|
||||||
int data = seg.GetSegData(segmentId, SegLvlFeatures.SegLvlAltQ);
|
|
||||||
int segQIndex = seg.AbsDelta == Constants.SegmentAbsData ? data : baseQIndex + data;
|
|
||||||
return Math.Clamp(segQIndex, 0, MaxQ);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return baseQIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
96
src/Ryujinx.Graphics.Nvdec.Vp9/ReadBitBuffer.cs
Normal file
96
src/Ryujinx.Graphics.Nvdec.Vp9/ReadBitBuffer.cs
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
{
|
||||||
|
public ref struct ReadBitBuffer
|
||||||
|
{
|
||||||
|
public ReadOnlySpan<byte> BitBuffer;
|
||||||
|
public ulong BitOffset;
|
||||||
|
public object ErrorHandlerData;
|
||||||
|
|
||||||
|
private static int GetMsb(uint n)
|
||||||
|
{
|
||||||
|
Debug.Assert(n != 0);
|
||||||
|
return 31 ^ BitOperations.LeadingZeroCount(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int GetUnsignedBits(uint numValues)
|
||||||
|
{
|
||||||
|
return numValues > 0 ? GetMsb(numValues) + 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int DecodeUnsignedMax(int max)
|
||||||
|
{
|
||||||
|
int data = ReadLiteral(GetUnsignedBits((uint)max));
|
||||||
|
return data > max ? max : data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ulong BytesRead()
|
||||||
|
{
|
||||||
|
return (BitOffset + 7) >> 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ReadBit()
|
||||||
|
{
|
||||||
|
ulong off = BitOffset;
|
||||||
|
ulong p = off >> 3;
|
||||||
|
int q = 7 - (int)(off & 0x7);
|
||||||
|
if (p < (ulong)BitBuffer.Length)
|
||||||
|
{
|
||||||
|
int bit = (BitBuffer[(int)p] >> q) & 1;
|
||||||
|
BitOffset = off + 1;
|
||||||
|
return bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ReadLiteral(int bits)
|
||||||
|
{
|
||||||
|
int value = 0, bit;
|
||||||
|
for (bit = bits - 1; bit >= 0; bit--)
|
||||||
|
{
|
||||||
|
value |= ReadBit() << bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ReadSignedLiteral(int bits)
|
||||||
|
{
|
||||||
|
int value = ReadLiteral(bits);
|
||||||
|
return ReadBit() != 0 ? -value : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ReadInvSignedLiteral(int bits)
|
||||||
|
{
|
||||||
|
return ReadSignedLiteral(bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ReadDeltaQ()
|
||||||
|
{
|
||||||
|
return ReadBit() != 0 ? ReadSignedLiteral(4) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReadFrameSize(out int width, out int height)
|
||||||
|
{
|
||||||
|
width = ReadLiteral(16) + 1;
|
||||||
|
height = ReadLiteral(16) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BitstreamProfile ReadProfile()
|
||||||
|
{
|
||||||
|
int profile = ReadBit();
|
||||||
|
profile |= ReadBit() << 1;
|
||||||
|
if (profile > 2)
|
||||||
|
{
|
||||||
|
profile += ReadBit();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (BitstreamProfile)profile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -77,67 +77,38 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
bd);
|
bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int RoundMvCompQ4(int value)
|
public static int RoundMvCompQ4(int value)
|
||||||
{
|
{
|
||||||
return (value < 0 ? value - 2 : value + 2) / 4;
|
return (value < 0 ? value - 2 : value + 2) / 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Mv MiMvPredQ4(ref ModeInfo mi, int idx)
|
public static int RoundMvCompQ2(int value)
|
||||||
{
|
|
||||||
Mv res = new Mv()
|
|
||||||
{
|
|
||||||
Row = (short)RoundMvCompQ4(
|
|
||||||
mi.Bmi[0].Mv[idx].Row + mi.Bmi[1].Mv[idx].Row +
|
|
||||||
mi.Bmi[2].Mv[idx].Row + mi.Bmi[3].Mv[idx].Row),
|
|
||||||
Col = (short)RoundMvCompQ4(
|
|
||||||
mi.Bmi[0].Mv[idx].Col + mi.Bmi[1].Mv[idx].Col +
|
|
||||||
mi.Bmi[2].Mv[idx].Col + mi.Bmi[3].Mv[idx].Col)
|
|
||||||
};
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int RoundMvCompQ2(int value)
|
|
||||||
{
|
{
|
||||||
return (value < 0 ? value - 1 : value + 1) / 2;
|
return (value < 0 ? value - 1 : value + 1) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Mv MiMvPredQ2(ref ModeInfo mi, int idx, int block0, int block1)
|
|
||||||
{
|
|
||||||
Mv res = new Mv()
|
|
||||||
{
|
|
||||||
Row = (short)RoundMvCompQ2(
|
|
||||||
mi.Bmi[block0].Mv[idx].Row +
|
|
||||||
mi.Bmi[block1].Mv[idx].Row),
|
|
||||||
Col = (short)RoundMvCompQ2(
|
|
||||||
mi.Bmi[block0].Mv[idx].Col +
|
|
||||||
mi.Bmi[block1].Mv[idx].Col)
|
|
||||||
};
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Mv ClampMvToUmvBorderSb(ref MacroBlockD xd, ref Mv srcMv, int bw, int bh, int ssX, int ssY)
|
public static Mv ClampMvToUmvBorderSb(ref MacroBlockD xd, ref Mv srcMv, int bw, int bh, int ssX, int ssY)
|
||||||
{
|
{
|
||||||
// If the MV points so far into the UMV border that no visible pixels
|
// If the MV points so far into the UMV border that no visible pixels
|
||||||
// are used for reconstruction, the subpel part of the MV can be
|
// are used for reconstruction, the subpel part of the MV can be
|
||||||
// discarded and the MV limited to 16 pixels with equivalent results.
|
// discarded and the MV limited to 16 pixels with equivalent results.
|
||||||
int spelLeft = (Constants.Vp9InterpExtend + bw) << SubpelBits;
|
int spelLeft = (Constants.InterpExtend + bw) << SubpelBits;
|
||||||
int spelRight = spelLeft - SubpelShifts;
|
int spelRight = spelLeft - SubpelShifts;
|
||||||
int spelTop = (Constants.Vp9InterpExtend + bh) << SubpelBits;
|
int spelTop = (Constants.InterpExtend + bh) << SubpelBits;
|
||||||
int spelBottom = spelTop - SubpelShifts;
|
int spelBottom = spelTop - SubpelShifts;
|
||||||
Mv clampedMv = new Mv()
|
Mv clampedMv = new()
|
||||||
{
|
{
|
||||||
Row = (short)(srcMv.Row * (1 << (1 - ssY))),
|
Row = (short)(srcMv.Row * (1 << (1 - ssY))), Col = (short)(srcMv.Col * (1 << (1 - ssX)))
|
||||||
Col = (short)(srcMv.Col * (1 << (1 - ssX)))
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Debug.Assert(ssX <= 1);
|
Debug.Assert(ssX <= 1);
|
||||||
Debug.Assert(ssY <= 1);
|
Debug.Assert(ssY <= 1);
|
||||||
|
|
||||||
clampedMv.ClampMv(
|
clampedMv.Clamp(
|
||||||
xd.MbToLeftEdge * (1 << (1 - ssX)) - spelLeft,
|
(xd.MbToLeftEdge * (1 << (1 - ssX))) - spelLeft,
|
||||||
xd.MbToRightEdge * (1 << (1 - ssX)) + spelRight,
|
(xd.MbToRightEdge * (1 << (1 - ssX))) + spelRight,
|
||||||
xd.MbToTopEdge * (1 << (1 - ssY)) - spelTop,
|
(xd.MbToTopEdge * (1 << (1 - ssY))) - spelTop,
|
||||||
xd.MbToBottomEdge * (1 << (1 - ssY)) + spelBottom);
|
(xd.MbToBottomEdge * (1 << (1 - ssY))) + spelBottom);
|
||||||
|
|
||||||
return clampedMv;
|
return clampedMv;
|
||||||
}
|
}
|
||||||
|
@ -145,15 +116,26 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
public static Mv AverageSplitMvs(ref MacroBlockDPlane pd, ref ModeInfo mi, int refr, int block)
|
public static Mv AverageSplitMvs(ref MacroBlockDPlane pd, ref ModeInfo mi, int refr, int block)
|
||||||
{
|
{
|
||||||
int ssIdx = ((pd.SubsamplingX > 0 ? 1 : 0) << 1) | (pd.SubsamplingY > 0 ? 1 : 0);
|
int ssIdx = ((pd.SubsamplingX > 0 ? 1 : 0) << 1) | (pd.SubsamplingY > 0 ? 1 : 0);
|
||||||
Mv res = new Mv();
|
Mv res = new();
|
||||||
switch (ssIdx)
|
switch (ssIdx)
|
||||||
{
|
{
|
||||||
case 0: res = mi.Bmi[block].Mv[refr]; break;
|
case 0:
|
||||||
case 1: res = MiMvPredQ2(ref mi, refr, block, block + 2); break;
|
res = mi.Bmi[block].Mv[refr];
|
||||||
case 2: res = MiMvPredQ2(ref mi, refr, block, block + 1); break;
|
break;
|
||||||
case 3: res = MiMvPredQ4(ref mi, refr); break;
|
case 1:
|
||||||
default: Debug.Assert(ssIdx <= 3 && ssIdx >= 0); break;
|
res = mi.MvPredQ2(refr, block, block + 2);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
res = mi.MvPredQ2(refr, block, block + 1);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
res = mi.MvPredQ4(refr);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Debug.Assert(ssIdx <= 3 && ssIdx >= 0);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +143,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
int x = !sf.IsNull ? sf.Value.ScaleValueX(xOffset) : xOffset;
|
int x = !sf.IsNull ? sf.Value.ScaleValueX(xOffset) : xOffset;
|
||||||
int y = !sf.IsNull ? sf.Value.ScaleValueY(yOffset) : yOffset;
|
int y = !sf.IsNull ? sf.Value.ScaleValueY(yOffset) : yOffset;
|
||||||
return y * stride + x;
|
return (y * stride) + x;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SetupPredPlanes(
|
private static void SetupPredPlanes(
|
||||||
|
@ -194,12 +176,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
strides[0] = src.Stride;
|
strides[0] = src.Stride;
|
||||||
strides[1] = src.UvStride;
|
strides[1] = src.UvStride;
|
||||||
strides[2] = src.UvStride;
|
strides[2] = src.UvStride;
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < Constants.MaxMbPlane; ++i)
|
for (int i = 0; i < Constants.MaxMbPlane; ++i)
|
||||||
{
|
{
|
||||||
ref MacroBlockDPlane pd = ref planes[i];
|
ref MacroBlockDPlane pd = ref planes[i];
|
||||||
SetupPredPlanes(ref pd.Dst, buffers[i], strides[i], miRow, miCol, Ptr<ScaleFactors>.Null, pd.SubsamplingX, pd.SubsamplingY);
|
SetupPredPlanes(ref pd.Dst, buffers[i], strides[i], miRow, miCol, Ptr<ScaleFactors>.Null,
|
||||||
|
pd.SubsamplingX, pd.SubsamplingY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,12 +203,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
strides[0] = src.Stride;
|
strides[0] = src.Stride;
|
||||||
strides[1] = src.UvStride;
|
strides[1] = src.UvStride;
|
||||||
strides[2] = src.UvStride;
|
strides[2] = src.UvStride;
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < Constants.MaxMbPlane; ++i)
|
for (int i = 0; i < Constants.MaxMbPlane; ++i)
|
||||||
{
|
{
|
||||||
ref MacroBlockDPlane pd = ref xd.Plane[i];
|
ref MacroBlockDPlane pd = ref xd.Plane[i];
|
||||||
SetupPredPlanes(ref pd.Pre[idx], buffers[i], strides[i], miRow, miCol, sf, pd.SubsamplingX, pd.SubsamplingY);
|
SetupPredPlanes(ref pd.Pre[idx], buffers[i], strides[i], miRow, miCol, sf, pd.SubsamplingX,
|
||||||
|
pd.SubsamplingY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
internal static class ReconIntra
|
internal static class ReconIntra
|
||||||
{
|
{
|
||||||
public static readonly TxType[] IntraModeToTxTypeLookup = new TxType[]
|
public static readonly TxType[] IntraModeToTxTypeLookup =
|
||||||
{
|
{
|
||||||
TxType.DctDct, // DC
|
TxType.DctDct, // DC
|
||||||
TxType.AdstDct, // V
|
TxType.AdstDct, // V
|
||||||
|
@ -36,232 +36,120 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
NeedLeft | NeedAbove, // D153
|
NeedLeft | NeedAbove, // D153
|
||||||
NeedLeft, // D207
|
NeedLeft, // D207
|
||||||
NeedAboveRight, // D63
|
NeedAboveRight, // D63
|
||||||
NeedLeft | NeedAbove, // TM
|
NeedLeft | NeedAbove // TM
|
||||||
};
|
};
|
||||||
|
|
||||||
private unsafe delegate void IntraPredFn(byte* dst, int stride, byte* above, byte* left);
|
private unsafe delegate void IntraPredFn(byte* dst, int stride, byte* above, byte* left);
|
||||||
|
|
||||||
private static unsafe IntraPredFn[][] _pred = new IntraPredFn[][]
|
private static readonly unsafe IntraPredFn[][] Pred =
|
||||||
{
|
{
|
||||||
new IntraPredFn[]
|
new IntraPredFn[] { null, null, null, null },
|
||||||
{
|
new IntraPredFn[] { VPredictor4x4, VPredictor8x8, VPredictor16x16, VPredictor32x32 },
|
||||||
null,
|
new IntraPredFn[] { HPredictor4x4, HPredictor8x8, HPredictor16x16, HPredictor32x32 },
|
||||||
null,
|
new IntraPredFn[] { D45Predictor4x4, D45Predictor8x8, D45Predictor16x16, D45Predictor32x32 },
|
||||||
null,
|
new IntraPredFn[] { D135Predictor4x4, D135Predictor8x8, D135Predictor16x16, D135Predictor32x32 },
|
||||||
null
|
new IntraPredFn[] { D117Predictor4x4, D117Predictor8x8, D117Predictor16x16, D117Predictor32x32 },
|
||||||
},
|
new IntraPredFn[] { D153Predictor4x4, D153Predictor8x8, D153Predictor16x16, D153Predictor32x32 },
|
||||||
new IntraPredFn[]
|
new IntraPredFn[] { D207Predictor4x4, D207Predictor8x8, D207Predictor16x16, D207Predictor32x32 },
|
||||||
{
|
new IntraPredFn[] { D63Predictor4x4, D63Predictor8x8, D63Predictor16x16, D63Predictor32x32 },
|
||||||
VPredictor4x4,
|
new IntraPredFn[] { TmPredictor4x4, TmPredictor8x8, TmPredictor16x16, TmPredictor32x32 }
|
||||||
VPredictor8x8,
|
|
||||||
VPredictor16x16,
|
|
||||||
VPredictor32x32
|
|
||||||
},
|
|
||||||
new IntraPredFn[]
|
|
||||||
{
|
|
||||||
HPredictor4x4,
|
|
||||||
HPredictor8x8,
|
|
||||||
HPredictor16x16,
|
|
||||||
HPredictor32x32
|
|
||||||
},
|
|
||||||
new IntraPredFn[]
|
|
||||||
{
|
|
||||||
D45Predictor4x4,
|
|
||||||
D45Predictor8x8,
|
|
||||||
D45Predictor16x16,
|
|
||||||
D45Predictor32x32
|
|
||||||
},
|
|
||||||
new IntraPredFn[]
|
|
||||||
{
|
|
||||||
D135Predictor4x4,
|
|
||||||
D135Predictor8x8,
|
|
||||||
D135Predictor16x16,
|
|
||||||
D135Predictor32x32
|
|
||||||
},
|
|
||||||
new IntraPredFn[]
|
|
||||||
{
|
|
||||||
D117Predictor4x4,
|
|
||||||
D117Predictor8x8,
|
|
||||||
D117Predictor16x16,
|
|
||||||
D117Predictor32x32
|
|
||||||
},
|
|
||||||
new IntraPredFn[]
|
|
||||||
{
|
|
||||||
D153Predictor4x4,
|
|
||||||
D153Predictor8x8,
|
|
||||||
D153Predictor16x16,
|
|
||||||
D153Predictor32x32
|
|
||||||
},
|
|
||||||
new IntraPredFn[]
|
|
||||||
{
|
|
||||||
D207Predictor4x4,
|
|
||||||
D207Predictor8x8,
|
|
||||||
D207Predictor16x16,
|
|
||||||
D207Predictor32x32
|
|
||||||
},
|
|
||||||
new IntraPredFn[]
|
|
||||||
{
|
|
||||||
D63Predictor4x4,
|
|
||||||
D63Predictor8x8,
|
|
||||||
D63Predictor16x16,
|
|
||||||
D63Predictor32x32
|
|
||||||
},
|
|
||||||
new IntraPredFn[]
|
|
||||||
{
|
|
||||||
TMPredictor4x4,
|
|
||||||
TMPredictor8x8,
|
|
||||||
TMPredictor16x16,
|
|
||||||
TMPredictor32x32
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private static unsafe IntraPredFn[][][] _dcPred = new IntraPredFn[][][]
|
private static readonly unsafe IntraPredFn[][][] DcPred =
|
||||||
{
|
{
|
||||||
new IntraPredFn[][]
|
new[]
|
||||||
{
|
{
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
Dc128Predictor4x4,
|
Dc128Predictor4x4, Dc128Predictor8x8, Dc128Predictor16x16, Dc128Predictor32x32
|
||||||
Dc128Predictor8x8,
|
|
||||||
Dc128Predictor16x16,
|
|
||||||
Dc128Predictor32x32
|
|
||||||
},
|
},
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
DcTopPredictor4x4,
|
DcTopPredictor4x4, DcTopPredictor8x8, DcTopPredictor16x16, DcTopPredictor32x32
|
||||||
DcTopPredictor8x8,
|
|
||||||
DcTopPredictor16x16,
|
|
||||||
DcTopPredictor32x32
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new IntraPredFn[][]
|
new[]
|
||||||
{
|
{
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
DcLeftPredictor4x4,
|
DcLeftPredictor4x4, DcLeftPredictor8x8, DcLeftPredictor16x16, DcLeftPredictor32x32
|
||||||
DcLeftPredictor8x8,
|
|
||||||
DcLeftPredictor16x16,
|
|
||||||
DcLeftPredictor32x32
|
|
||||||
},
|
},
|
||||||
new IntraPredFn[]
|
new IntraPredFn[] { DcPredictor4x4, DcPredictor8x8, DcPredictor16x16, DcPredictor32x32 }
|
||||||
{
|
|
||||||
DcPredictor4x4,
|
|
||||||
DcPredictor8x8,
|
|
||||||
DcPredictor16x16,
|
|
||||||
DcPredictor32x32
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private unsafe delegate void IntraHighPredFn(ushort* dst, int stride, ushort* above, ushort* left, int bd);
|
private unsafe delegate void IntraHighPredFn(ushort* dst, int stride, ushort* above, ushort* left, int bd);
|
||||||
|
|
||||||
private static unsafe IntraHighPredFn[][] _predHigh = new IntraHighPredFn[][]
|
private static readonly unsafe IntraHighPredFn[][] PredHigh =
|
||||||
{
|
{
|
||||||
|
new IntraHighPredFn[] { null, null, null, null },
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
null,
|
HighbdVPredictor4x4, HighbdVPredictor8x8, HighbdVPredictor16x16, HighbdVPredictor32x32
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null
|
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdVPredictor4x4,
|
HighbdHPredictor4x4, HighbdHPredictor8x8, HighbdHPredictor16x16, HighbdHPredictor32x32
|
||||||
HighbdVPredictor8x8,
|
|
||||||
HighbdVPredictor16x16,
|
|
||||||
HighbdVPredictor32x32
|
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdHPredictor4x4,
|
HighbdD45Predictor4x4, HighbdD45Predictor8x8, HighbdD45Predictor16x16, HighbdD45Predictor32x32
|
||||||
HighbdHPredictor8x8,
|
|
||||||
HighbdHPredictor16x16,
|
|
||||||
HighbdHPredictor32x32
|
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdD45Predictor4x4,
|
HighbdD135Predictor4x4, HighbdD135Predictor8x8, HighbdD135Predictor16x16,
|
||||||
HighbdD45Predictor8x8,
|
|
||||||
HighbdD45Predictor16x16,
|
|
||||||
HighbdD45Predictor32x32
|
|
||||||
},
|
|
||||||
new IntraHighPredFn[]
|
|
||||||
{
|
|
||||||
HighbdD135Predictor4x4,
|
|
||||||
HighbdD135Predictor8x8,
|
|
||||||
HighbdD135Predictor16x16,
|
|
||||||
HighbdD135Predictor32x32
|
HighbdD135Predictor32x32
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdD117Predictor4x4,
|
HighbdD117Predictor4x4, HighbdD117Predictor8x8, HighbdD117Predictor16x16,
|
||||||
HighbdD117Predictor8x8,
|
|
||||||
HighbdD117Predictor16x16,
|
|
||||||
HighbdD117Predictor32x32
|
HighbdD117Predictor32x32
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdD153Predictor4x4,
|
HighbdD153Predictor4x4, HighbdD153Predictor8x8, HighbdD153Predictor16x16,
|
||||||
HighbdD153Predictor8x8,
|
|
||||||
HighbdD153Predictor16x16,
|
|
||||||
HighbdD153Predictor32x32
|
HighbdD153Predictor32x32
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdD207Predictor4x4,
|
HighbdD207Predictor4x4, HighbdD207Predictor8x8, HighbdD207Predictor16x16,
|
||||||
HighbdD207Predictor8x8,
|
|
||||||
HighbdD207Predictor16x16,
|
|
||||||
HighbdD207Predictor32x32
|
HighbdD207Predictor32x32
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdD63Predictor4x4,
|
HighbdD63Predictor4x4, HighbdD63Predictor8x8, HighbdD63Predictor16x16, HighbdD63Predictor32x32
|
||||||
HighbdD63Predictor8x8,
|
|
||||||
HighbdD63Predictor16x16,
|
|
||||||
HighbdD63Predictor32x32
|
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdTMPredictor4x4,
|
HighbdTmPredictor4x4, HighbdTmPredictor8x8, HighbdTmPredictor16x16, HighbdTmPredictor32x32
|
||||||
HighbdTMPredictor8x8,
|
|
||||||
HighbdTMPredictor16x16,
|
|
||||||
HighbdTMPredictor32x32
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static unsafe IntraHighPredFn[][][] _dcPredHigh = new IntraHighPredFn[][][]
|
private static readonly unsafe IntraHighPredFn[][][] DcPredHigh =
|
||||||
{
|
{
|
||||||
new IntraHighPredFn[][]
|
new[]
|
||||||
{
|
{
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdDc128Predictor4x4,
|
HighbdDc128Predictor4x4, HighbdDc128Predictor8x8, HighbdDc128Predictor16x16,
|
||||||
HighbdDc128Predictor8x8,
|
|
||||||
HighbdDc128Predictor16x16,
|
|
||||||
HighbdDc128Predictor32x32
|
HighbdDc128Predictor32x32
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdDcTopPredictor4x4,
|
HighbdDcTopPredictor4x4, HighbdDcTopPredictor8x8, HighbdDcTopPredictor16x16,
|
||||||
HighbdDcTopPredictor8x8,
|
|
||||||
HighbdDcTopPredictor16x16,
|
|
||||||
HighbdDcTopPredictor32x32
|
HighbdDcTopPredictor32x32
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[][]
|
new[]
|
||||||
{
|
{
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdDcLeftPredictor4x4,
|
HighbdDcLeftPredictor4x4, HighbdDcLeftPredictor8x8, HighbdDcLeftPredictor16x16,
|
||||||
HighbdDcLeftPredictor8x8,
|
|
||||||
HighbdDcLeftPredictor16x16,
|
|
||||||
HighbdDcLeftPredictor32x32
|
HighbdDcLeftPredictor32x32
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdDcPredictor4x4,
|
HighbdDcPredictor4x4, HighbdDcPredictor8x8, HighbdDcPredictor16x16,
|
||||||
HighbdDcPredictor8x8,
|
|
||||||
HighbdDcPredictor16x16,
|
|
||||||
HighbdDcPredictor32x32
|
HighbdDcPredictor32x32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -332,7 +220,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
for (i = 0; i < bs; ++i)
|
for (i = 0; i < bs; ++i)
|
||||||
{
|
{
|
||||||
leftCol[i] = refr[i * refStride - 1];
|
leftCol[i] = refr[(i * refStride) - 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -340,12 +228,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
int extendBottom = frameHeight - y0;
|
int extendBottom = frameHeight - y0;
|
||||||
for (i = 0; i < extendBottom; ++i)
|
for (i = 0; i < extendBottom; ++i)
|
||||||
{
|
{
|
||||||
leftCol[i] = refr[i * refStride - 1];
|
leftCol[i] = refr[(i * refStride) - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; i < bs; ++i)
|
for (; i < bs; ++i)
|
||||||
{
|
{
|
||||||
leftCol[i] = refr[(extendBottom - 1) * refStride - 1];
|
leftCol[i] = refr[((extendBottom - 1) * refStride) - 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -354,7 +242,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
/* faster path if the block does not need extension */
|
/* faster path if the block does not need extension */
|
||||||
for (i = 0; i < bs; ++i)
|
for (i = 0; i < bs; ++i)
|
||||||
{
|
{
|
||||||
leftCol[i] = refr[i * refStride - 1];
|
leftCol[i] = refr[(i * refStride) - 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -396,6 +284,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
MemoryUtil.Copy(aboveRow, aboveRef, bs);
|
MemoryUtil.Copy(aboveRow, aboveRef, bs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (ushort)(baseVal + 1);
|
aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (ushort)(baseVal + 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -414,7 +303,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
if (xd.MbToRightEdge < 0)
|
if (xd.MbToRightEdge < 0)
|
||||||
{
|
{
|
||||||
/* slower path if the block needs border extension */
|
/* slower path if the block needs border extension */
|
||||||
if (x0 + 2 * bs <= frameWidth)
|
if (x0 + (2 * bs) <= frameWidth)
|
||||||
{
|
{
|
||||||
if (rightAvailable != 0 && bs == 4)
|
if (rightAvailable != 0 && bs == 4)
|
||||||
{
|
{
|
||||||
|
@ -432,7 +321,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
if (rightAvailable != 0 && bs == 4)
|
if (rightAvailable != 0 && bs == 4)
|
||||||
{
|
{
|
||||||
MemoryUtil.Copy(aboveRow, aboveRef, r);
|
MemoryUtil.Copy(aboveRow, aboveRef, r);
|
||||||
MemoryUtil.Fill(aboveRow + r, aboveRow[r - 1], x0 + 2 * bs - frameWidth);
|
MemoryUtil.Fill(aboveRow + r, aboveRow[r - 1], x0 + (2 * bs) - frameWidth);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -444,8 +333,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
int r = frameWidth - x0;
|
int r = frameWidth - x0;
|
||||||
MemoryUtil.Copy(aboveRow, aboveRef, r);
|
MemoryUtil.Copy(aboveRow, aboveRef, r);
|
||||||
MemoryUtil.Fill(aboveRow + r, aboveRow[r - 1], x0 + 2 * bs - frameWidth);
|
MemoryUtil.Fill(aboveRow + r, aboveRow[r - 1], x0 + (2 * bs) - frameWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (ushort)(baseVal + 1);
|
aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (ushort)(baseVal + 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -481,11 +371,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
// Predict
|
// Predict
|
||||||
if (mode == PredictionMode.DcPred)
|
if (mode == PredictionMode.DcPred)
|
||||||
{
|
{
|
||||||
_dcPredHigh[leftAvailable][upAvailable][(int)txSize](dst, dstStride, constAboveRow, leftCol, xd.Bd);
|
DcPredHigh[leftAvailable][upAvailable][(int)txSize](dst, dstStride, constAboveRow, leftCol, xd.Bd);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_predHigh[(int)mode][(int)txSize](dst, dstStride, constAboveRow, leftCol, xd.Bd);
|
PredHigh[(int)mode][(int)txSize](dst, dstStride, constAboveRow, leftCol, xd.Bd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -549,7 +439,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
for (i = 0; i < bs; ++i)
|
for (i = 0; i < bs; ++i)
|
||||||
{
|
{
|
||||||
leftCol[i] = refr[i * refStride - 1];
|
leftCol[i] = refr[(i * refStride) - 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -557,12 +447,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
int extendBottom = frameHeight - y0;
|
int extendBottom = frameHeight - y0;
|
||||||
for (i = 0; i < extendBottom; ++i)
|
for (i = 0; i < extendBottom; ++i)
|
||||||
{
|
{
|
||||||
leftCol[i] = refr[i * refStride - 1];
|
leftCol[i] = refr[(i * refStride) - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; i < bs; ++i)
|
for (; i < bs; ++i)
|
||||||
{
|
{
|
||||||
leftCol[i] = refr[(extendBottom - 1) * refStride - 1];
|
leftCol[i] = refr[((extendBottom - 1) * refStride) - 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -571,7 +461,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
/* Faster path if the block does not need extension */
|
/* Faster path if the block does not need extension */
|
||||||
for (i = 0; i < bs; ++i)
|
for (i = 0; i < bs; ++i)
|
||||||
{
|
{
|
||||||
leftCol[i] = refr[i * refStride - 1];
|
leftCol[i] = refr[(i * refStride) - 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -613,6 +503,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
MemoryUtil.Copy(aboveRow, aboveRef, bs);
|
MemoryUtil.Copy(aboveRow, aboveRef, bs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (byte)129;
|
aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (byte)129;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -631,7 +522,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
if (xd.MbToRightEdge < 0)
|
if (xd.MbToRightEdge < 0)
|
||||||
{
|
{
|
||||||
/* Slower path if the block needs border extension */
|
/* Slower path if the block needs border extension */
|
||||||
if (x0 + 2 * bs <= frameWidth)
|
if (x0 + (2 * bs) <= frameWidth)
|
||||||
{
|
{
|
||||||
if (rightAvailable != 0 && bs == 4)
|
if (rightAvailable != 0 && bs == 4)
|
||||||
{
|
{
|
||||||
|
@ -649,7 +540,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
if (rightAvailable != 0 && bs == 4)
|
if (rightAvailable != 0 && bs == 4)
|
||||||
{
|
{
|
||||||
MemoryUtil.Copy(aboveRow, aboveRef, r);
|
MemoryUtil.Copy(aboveRow, aboveRef, r);
|
||||||
MemoryUtil.Fill(aboveRow + r, aboveRow[r - 1], x0 + 2 * bs - frameWidth);
|
MemoryUtil.Fill(aboveRow + r, aboveRow[r - 1], x0 + (2 * bs) - frameWidth);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -661,7 +552,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
int r = frameWidth - x0;
|
int r = frameWidth - x0;
|
||||||
MemoryUtil.Copy(aboveRow, aboveRef, r);
|
MemoryUtil.Copy(aboveRow, aboveRef, r);
|
||||||
MemoryUtil.Fill(aboveRow + r, aboveRow[r - 1], x0 + 2 * bs - frameWidth);
|
MemoryUtil.Fill(aboveRow + r, aboveRow[r - 1], x0 + (2 * bs) - frameWidth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -684,6 +575,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (byte)129;
|
aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (byte)129;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -696,11 +588,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
// Predict
|
// Predict
|
||||||
if (mode == PredictionMode.DcPred)
|
if (mode == PredictionMode.DcPred)
|
||||||
{
|
{
|
||||||
_dcPred[leftAvailable][upAvailable][(int)txSize](dst, dstStride, constAboveRow, leftCol);
|
DcPred[leftAvailable][upAvailable][(int)txSize](dst, dstStride, constAboveRow, leftCol);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_pred[(int)mode][(int)txSize](dst, dstStride, constAboveRow, leftCol);
|
Pred[(int)mode][(int)txSize](dst, dstStride, constAboveRow, leftCol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -721,7 +613,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
int txw = 1 << (int)txSize;
|
int txw = 1 << (int)txSize;
|
||||||
int haveTop = loff != 0 || !xd.AboveMi.IsNull ? 1 : 0;
|
int haveTop = loff != 0 || !xd.AboveMi.IsNull ? 1 : 0;
|
||||||
int haveLeft = aoff != 0 || !xd.LeftMi.IsNull ? 1 : 0;
|
int haveLeft = aoff != 0 || !xd.LeftMi.IsNull ? 1 : 0;
|
||||||
int haveRight = (aoff + txw) < bw ? 1 : 0;
|
int haveRight = aoff + txw < bw ? 1 : 0;
|
||||||
int x = aoff * 4;
|
int x = aoff * 4;
|
||||||
int y = loff * 4;
|
int y = loff * 4;
|
||||||
|
|
||||||
|
@ -743,6 +635,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
plane);
|
plane);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BuildIntraPredictors(
|
BuildIntraPredictors(
|
||||||
ref xd,
|
ref xd,
|
||||||
refr,
|
refr,
|
||||||
|
|
|
@ -12,9 +12,20 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
public int BufEnd;
|
public int BufEnd;
|
||||||
public Reader BitReader;
|
public Reader BitReader;
|
||||||
public Vp9BackwardUpdates Counts;
|
public Vp9BackwardUpdates Counts;
|
||||||
|
|
||||||
public MacroBlockD Xd;
|
public MacroBlockD Xd;
|
||||||
|
|
||||||
/* dqcoeff are shared by all the planes. So planes must be decoded serially */
|
/* dqcoeff are shared by all the planes. So planes must be decoded serially */
|
||||||
public Array32<Array32<int>> Dqcoeff;
|
public Array32<Array32<int>> Dqcoeff;
|
||||||
public InternalErrorInfo ErrorInfo;
|
public InternalErrorInfo ErrorInfo;
|
||||||
|
|
||||||
|
public int DecPartitionPlaneContext(int miRow, int miCol, int bsl)
|
||||||
|
{
|
||||||
|
ref sbyte aboveCtx = ref Xd.AboveSegContext[miCol];
|
||||||
|
ref sbyte leftCtx = ref Xd.LeftSegContext[miRow & Constants.MiMask];
|
||||||
|
int above = (aboveCtx >> bsl) & 1, left = (leftCtx >> bsl) & 1;
|
||||||
|
|
||||||
|
return (left * 2) + above + (bsl * Constants.PartitionPloffset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
11
src/Ryujinx.Graphics.Nvdec.Vp9/Types/BitstreamProfile.cs
Normal file
11
src/Ryujinx.Graphics.Nvdec.Vp9/Types/BitstreamProfile.cs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
|
{
|
||||||
|
public enum BitstreamProfile
|
||||||
|
{
|
||||||
|
Profile0,
|
||||||
|
Profile1,
|
||||||
|
Profile2,
|
||||||
|
Profile3,
|
||||||
|
MaxProfiles
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,20 +2,20 @@
|
||||||
{
|
{
|
||||||
internal enum BlockSize
|
internal enum BlockSize
|
||||||
{
|
{
|
||||||
Block4x4 = 0,
|
Block4x4,
|
||||||
Block4x8 = 1,
|
Block4x8,
|
||||||
Block8x4 = 2,
|
Block8x4,
|
||||||
Block8x8 = 3,
|
Block8x8,
|
||||||
Block8x16 = 4,
|
Block8x16,
|
||||||
Block16x8 = 5,
|
Block16x8,
|
||||||
Block16x16 = 6,
|
Block16x16,
|
||||||
Block16x32 = 7,
|
Block16x32,
|
||||||
Block32x16 = 8,
|
Block32x16,
|
||||||
Block32x32 = 9,
|
Block32x32,
|
||||||
Block32x64 = 10,
|
Block32x64,
|
||||||
Block64x32 = 11,
|
Block64x32,
|
||||||
Block64x64 = 12,
|
Block64x64,
|
||||||
BlockSizes = 13,
|
BlockSizes,
|
||||||
BlockInvalid = BlockSizes
|
BlockInvalid = BlockSizes
|
||||||
}
|
}
|
||||||
}
|
}
|
18
src/Ryujinx.Graphics.Nvdec.Vp9/Types/BufferPool.cs
Normal file
18
src/Ryujinx.Graphics.Nvdec.Vp9/Types/BufferPool.cs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
using Ryujinx.Common.Memory;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
|
{
|
||||||
|
internal struct BufferPool
|
||||||
|
{
|
||||||
|
// Private data associated with the frame buffer callbacks.
|
||||||
|
public Ptr<InternalFrameBufferList> CbPriv;
|
||||||
|
|
||||||
|
// vpx_get_frame_buffer_cb_fn_t get_fb_cb;
|
||||||
|
// vpx_release_frame_buffer_cb_fn_t release_fb_cb;
|
||||||
|
|
||||||
|
public Array12<RefCntBuffer> FrameBufs;
|
||||||
|
|
||||||
|
// Frame buffers allocated internally by the codec.
|
||||||
|
public InternalFrameBufferList IntFrameBuffers;
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,5 +23,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
|
|
||||||
public ArrayPtr<LoopFilterMask> Lfm;
|
public ArrayPtr<LoopFilterMask> Lfm;
|
||||||
public int LfmStride;
|
public int LfmStride;
|
||||||
|
|
||||||
|
public void SetDefaultLfDeltas()
|
||||||
|
{
|
||||||
|
ModeRefDeltaEnabled = true;
|
||||||
|
ModeRefDeltaUpdate = true;
|
||||||
|
|
||||||
|
RefDeltas[Constants.IntraFrame] = 1;
|
||||||
|
RefDeltas[Constants.LastFrame] = 0;
|
||||||
|
RefDeltas[Constants.GoldenFrame] = -1;
|
||||||
|
RefDeltas[Constants.AltRefFrame] = -1;
|
||||||
|
ModeDeltas[0] = 0;
|
||||||
|
ModeDeltas[1] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
|
using Ryujinx.Graphics.Nvdec.Vp9.Common;
|
||||||
using Ryujinx.Graphics.Video;
|
using Ryujinx.Graphics.Video;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
|
@ -82,19 +83,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
{
|
{
|
||||||
return leftType;
|
return leftType;
|
||||||
}
|
}
|
||||||
else if (leftType == Constants.SwitchableFilters)
|
|
||||||
|
if (leftType == Constants.SwitchableFilters)
|
||||||
{
|
{
|
||||||
return aboveType;
|
return aboveType;
|
||||||
}
|
}
|
||||||
else if (aboveType == Constants.SwitchableFilters)
|
|
||||||
|
if (aboveType == Constants.SwitchableFilters)
|
||||||
{
|
{
|
||||||
return leftType;
|
return leftType;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
return Constants.SwitchableFilters;
|
return Constants.SwitchableFilters;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// The mode info data structure has a one element border above and to the
|
// The mode info data structure has a one element border above and to the
|
||||||
// left of the entries corresponding to real macroblocks.
|
// left of the entries corresponding to real macroblocks.
|
||||||
|
@ -106,15 +107,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
public int GetIntraInterContext()
|
public int GetIntraInterContext()
|
||||||
{
|
{
|
||||||
if (!AboveMi.IsNull && !LeftMi.IsNull)
|
if (!AboveMi.IsNull && !LeftMi.IsNull)
|
||||||
{ // Both edges available
|
{
|
||||||
|
// Both edges available
|
||||||
bool aboveIntra = !AboveMi.Value.IsInterBlock();
|
bool aboveIntra = !AboveMi.Value.IsInterBlock();
|
||||||
bool leftIntra = !LeftMi.Value.IsInterBlock();
|
bool leftIntra = !LeftMi.Value.IsInterBlock();
|
||||||
return leftIntra && aboveIntra ? 3 : (leftIntra || aboveIntra ? 1 : 0);
|
return leftIntra && aboveIntra ? 3 : leftIntra || aboveIntra ? 1 : 0;
|
||||||
}
|
}
|
||||||
else if (!AboveMi.IsNull || !LeftMi.IsNull)
|
|
||||||
{ // One edge available
|
if (!AboveMi.IsNull || !LeftMi.IsNull)
|
||||||
|
{
|
||||||
|
// One edge available
|
||||||
return 2 * (!(!AboveMi.IsNull ? AboveMi.Value : LeftMi.Value).IsInterBlock() ? 1 : 0);
|
return 2 * (!(!AboveMi.IsNull ? AboveMi.Value : LeftMi.Value).IsInterBlock() ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,8 +130,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
public int GetTxSizeContext()
|
public int GetTxSizeContext()
|
||||||
{
|
{
|
||||||
int maxTxSize = (int)Luts.MaxTxSizeLookup[(int)Mi[0].Value.SbType];
|
int maxTxSize = (int)Luts.MaxTxSizeLookup[(int)Mi[0].Value.SbType];
|
||||||
int aboveCtx = (!AboveMi.IsNull && AboveMi.Value.Skip == 0) ? (int)AboveMi.Value.TxSize : maxTxSize;
|
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;
|
int leftCtx = !LeftMi.IsNull && LeftMi.Value.Skip == 0 ? (int)LeftMi.Value.TxSize : maxTxSize;
|
||||||
if (LeftMi.IsNull)
|
if (LeftMi.IsNull)
|
||||||
{
|
{
|
||||||
leftCtx = aboveCtx;
|
leftCtx = aboveCtx;
|
||||||
|
@ -137,14 +142,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
aboveCtx = leftCtx;
|
aboveCtx = leftCtx;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (aboveCtx + leftCtx) > maxTxSize ? 1 : 0;
|
return aboveCtx + leftCtx > maxTxSize ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetupBlockPlanes(int ssX, int ssY)
|
public void SetupBlockPlanes(int ssX, int ssY)
|
||||||
{
|
{
|
||||||
int i;
|
for (int i = 0; i < Constants.MaxMbPlane; i++)
|
||||||
|
|
||||||
for (i = 0; i < Constants.MaxMbPlane; i++)
|
|
||||||
{
|
{
|
||||||
Plane[i].SubsamplingX = i != 0 ? ssX : 0;
|
Plane[i].SubsamplingX = i != 0 ? ssX : 0;
|
||||||
Plane[i].SubsamplingY = i != 0 ? ssY : 0;
|
Plane[i].SubsamplingY = i != 0 ? ssY : 0;
|
||||||
|
@ -155,25 +158,36 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
{
|
{
|
||||||
int aboveIdx = miCol * 2;
|
int aboveIdx = miCol * 2;
|
||||||
int leftIdx = (miRow * 2) & 15;
|
int leftIdx = (miRow * 2) & 15;
|
||||||
int i;
|
|
||||||
for (i = 0; i < Constants.MaxMbPlane; ++i)
|
for (int i = 0; i < Constants.MaxMbPlane; ++i)
|
||||||
{
|
{
|
||||||
ref MacroBlockDPlane pd = ref Plane[i];
|
ref MacroBlockDPlane pd = ref Plane[i];
|
||||||
pd.AboveContext = AboveContext[i].Slice(aboveIdx >> pd.SubsamplingX);
|
pd.AboveContext = AboveContext[i].Slice(aboveIdx >> pd.SubsamplingX);
|
||||||
pd.LeftContext = new ArrayPtr<sbyte>(ref LeftContext[i][leftIdx >> pd.SubsamplingY], 16 - (leftIdx >> pd.SubsamplingY));
|
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)
|
internal void SetMiRowCol(ref TileInfo tile, int miRow, int bh, int miCol, int bw, int miRows, int miCols)
|
||||||
{
|
{
|
||||||
MbToTopEdge = -((miRow * Constants.MiSize) * 8);
|
MbToTopEdge = -(miRow * Constants.MiSize * 8);
|
||||||
MbToBottomEdge = ((miRows - bh - miRow) * Constants.MiSize) * 8;
|
MbToBottomEdge = (miRows - bh - miRow) * Constants.MiSize * 8;
|
||||||
MbToLeftEdge = -((miCol * Constants.MiSize) * 8);
|
MbToLeftEdge = -(miCol * Constants.MiSize * 8);
|
||||||
MbToRightEdge = ((miCols - bw - miCol) * Constants.MiSize) * 8;
|
MbToRightEdge = (miCols - bw - miCol) * Constants.MiSize * 8;
|
||||||
|
|
||||||
// Are edges available for intra prediction?
|
// Are edges available for intra prediction?
|
||||||
AboveMi = (miRow != 0) ? Mi[-MiStride] : Ptr<ModeInfo>.Null;
|
AboveMi = miRow != 0 ? Mi[-MiStride] : Ptr<ModeInfo>.Null;
|
||||||
LeftMi = (miCol > tile.MiColStart) ? Mi[-1] : Ptr<ModeInfo>.Null;
|
LeftMi = miCol > tile.MiColStart ? Mi[-1] : Ptr<ModeInfo>.Null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe void DecResetSkipContext()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Constants.MaxMbPlane; i++)
|
||||||
|
{
|
||||||
|
ref MacroBlockDPlane pd = ref Plane[i];
|
||||||
|
MemoryUtil.Fill(pd.AboveContext.ToPointer(), (sbyte)0, pd.N4W);
|
||||||
|
MemoryUtil.Fill(pd.LeftContext.ToPointer(), (sbyte)0, pd.N4H);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -15,6 +15,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
|
|
||||||
// Number of 4x4s in current block
|
// Number of 4x4s in current block
|
||||||
public ushort N4W, N4H;
|
public ushort N4W, N4H;
|
||||||
|
|
||||||
// Log2 of N4W, N4H
|
// Log2 of N4W, N4H
|
||||||
public byte N4Wl, N4Hl;
|
public byte N4Wl, N4Hl;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,9 +49,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
return RefFrame[1] > Constants.IntraFrame;
|
return RefFrame[1] > Constants.IntraFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly int[][] IdxNColumnToSubblock = new int[][]
|
private static readonly int[][] IdxNColumnToSubblock =
|
||||||
{
|
{
|
||||||
new int[] { 1, 2 }, new int[] { 1, 3 }, new int[] { 3, 2 }, new int[] { 3, 3 }
|
new[] { 1, 2 }, new[] { 1, 3 }, new[] { 3, 2 }, new[] { 3, 3 }
|
||||||
};
|
};
|
||||||
|
|
||||||
// This function returns either the appropriate sub block or block's mv
|
// This function returns either the appropriate sub block or block's mv
|
||||||
|
@ -62,5 +62,46 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
? Bmi[IdxNColumnToSubblock[blockIdx][searchCol == 0 ? 1 : 0]].Mv[whichMv]
|
? Bmi[IdxNColumnToSubblock[blockIdx][searchCol == 0 ? 1 : 0]].Mv[whichMv]
|
||||||
: Mv[whichMv];
|
: Mv[whichMv];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Mv MvPredQ4(int idx)
|
||||||
|
{
|
||||||
|
Mv res = new()
|
||||||
|
{
|
||||||
|
Row = (short)ReconInter.RoundMvCompQ4(
|
||||||
|
Bmi[0].Mv[idx].Row + Bmi[1].Mv[idx].Row +
|
||||||
|
Bmi[2].Mv[idx].Row + Bmi[3].Mv[idx].Row),
|
||||||
|
Col = (short)ReconInter.RoundMvCompQ4(
|
||||||
|
Bmi[0].Mv[idx].Col + Bmi[1].Mv[idx].Col +
|
||||||
|
Bmi[2].Mv[idx].Col + Bmi[3].Mv[idx].Col)
|
||||||
|
};
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mv MvPredQ2(int idx, int block0, int block1)
|
||||||
|
{
|
||||||
|
Mv res = new()
|
||||||
|
{
|
||||||
|
Row = (short)ReconInter.RoundMvCompQ2(
|
||||||
|
Bmi[block0].Mv[idx].Row +
|
||||||
|
Bmi[block1].Mv[idx].Row),
|
||||||
|
Col = (short)ReconInter.RoundMvCompQ2(
|
||||||
|
Bmi[block0].Mv[idx].Col +
|
||||||
|
Bmi[block1].Mv[idx].Col)
|
||||||
|
};
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Performs mv sign inversion if indicated by the reference frame combination.
|
||||||
|
public Mv ScaleMv(int refr, sbyte thisRefFrame, ref Array4<sbyte> refSignBias)
|
||||||
|
{
|
||||||
|
Mv mv = Mv[refr];
|
||||||
|
if (refSignBias[RefFrame[refr]] != refSignBias[thisRefFrame])
|
||||||
|
{
|
||||||
|
mv.Row *= -1;
|
||||||
|
mv.Col *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mv;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -12,96 +12,86 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
|
|
||||||
private static ReadOnlySpan<byte> LogInBase2 => new byte[]
|
private static ReadOnlySpan<byte> LogInBase2 => new byte[]
|
||||||
{
|
{
|
||||||
0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5,
|
||||||
4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6,
|
||||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7,
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8,
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9,
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 10
|
||||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
|
||||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
|
||||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
|
||||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
|
||||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
|
||||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
|
||||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
|
||||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
|
||||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
|
||||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public bool UseMvHp()
|
public bool UseHp()
|
||||||
{
|
{
|
||||||
const int kMvRefThresh = 64; // Threshold for use of high-precision 1/8 mv
|
const int kMvRefThresh = 64; // Threshold for use of high-precision 1/8 mv
|
||||||
return Math.Abs(Row) < kMvRefThresh && Math.Abs(Col) < kMvRefThresh;
|
return Math.Abs(Row) < kMvRefThresh && Math.Abs(Col) < kMvRefThresh;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool MvJointVertical(MvJointType type)
|
public static bool JointVertical(MvJointType type)
|
||||||
{
|
{
|
||||||
return type == MvJointType.MvJointHzvnz || type == MvJointType.MvJointHnzvnz;
|
return type == MvJointType.Hzvnz || type == MvJointType.Hnzvnz;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool MvJointHorizontal(MvJointType type)
|
public static bool JointHorizontal(MvJointType type)
|
||||||
{
|
{
|
||||||
return type == MvJointType.MvJointHnzvz || type == MvJointType.MvJointHnzvnz;
|
return type == MvJointType.Hnzvz || type == MvJointType.Hnzvnz;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int MvClassBase(MvClassType c)
|
private static int ClassBase(MvClassType c)
|
||||||
{
|
{
|
||||||
return c != 0 ? Constants.Class0Size << ((int)c + 2) : 0;
|
return c != 0 ? Constants.Class0Size << ((int)c + 2) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MvClassType GetMvClass(int z, Ptr<int> offset)
|
private static MvClassType GetClass(int z, Ptr<int> offset)
|
||||||
{
|
{
|
||||||
MvClassType c = (z >= Constants.Class0Size * 4096) ? MvClassType.MvClass10 : (MvClassType)LogInBase2[z >> 3];
|
MvClassType c = z >= Constants.Class0Size * 4096 ? MvClassType.Class10 : (MvClassType)LogInBase2[z >> 3];
|
||||||
if (!offset.IsNull)
|
if (!offset.IsNull)
|
||||||
{
|
{
|
||||||
offset.Value = z - MvClassBase(c);
|
offset.Value = z - ClassBase(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void IncMvComponent(int v, ref Vp9BackwardUpdates counts, int comp, int incr, int usehp)
|
private static void IncComponent(int v, ref Vp9BackwardUpdates counts, int comp, int incr, int usehp)
|
||||||
{
|
{
|
||||||
int s, z, c, o = 0, d, e, f;
|
int o = 0;
|
||||||
Debug.Assert(v != 0); /* Should not be zero */
|
Debug.Assert(v != 0); /* Should not be zero */
|
||||||
s = v < 0 ? 1 : 0;
|
int s = v < 0 ? 1 : 0;
|
||||||
counts.Sign[comp][s] += (uint)incr;
|
counts.Sign[comp][s] += (uint)incr;
|
||||||
z = (s != 0 ? -v : v) - 1; /* Magnitude - 1 */
|
int z = (s != 0 ? -v : v) - 1 /* Magnitude - 1 */;
|
||||||
|
|
||||||
c = (int)GetMvClass(z, new Ptr<int>(ref o));
|
int c = (int)GetClass(z, new Ptr<int>(ref o));
|
||||||
counts.Classes[comp][c] += (uint)incr;
|
counts.Classes[comp][c] += (uint)incr;
|
||||||
|
|
||||||
d = (o >> 3); /* Int mv data */
|
int d = o >> 3 /* Int mv data */;
|
||||||
f = (o >> 1) & 3; /* Fractional pel mv data */
|
int f = (o >> 1) & 3 /* Fractional pel mv data */;
|
||||||
e = (o & 1); /* High precision mv data */
|
int e = o & 1 /* High precision mv data */;
|
||||||
|
|
||||||
if (c == (int)MvClassType.MvClass0)
|
if (c == (int)MvClassType.Class0)
|
||||||
{
|
{
|
||||||
counts.Class0[comp][d] += (uint)incr;
|
counts.Class0[comp][d] += (uint)incr;
|
||||||
counts.Class0Fp[comp][d][f] += (uint)incr;
|
counts.Class0Fp[comp][d][f] += (uint)incr;
|
||||||
|
@ -109,11 +99,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
int b = c + Constants.Class0Bits - 1; // Number of bits
|
int b = c + Constants.Class0Bits - 1; // Number of bits
|
||||||
for (i = 0; i < b; ++i)
|
for (int i = 0; i < b; ++i)
|
||||||
{
|
{
|
||||||
counts.Bits[comp][i][((d >> i) & 1)] += (uint)incr;
|
counts.Bits[comp][i][(d >> i) & 1] += (uint)incr;
|
||||||
}
|
}
|
||||||
|
|
||||||
counts.Fp[comp][f] += (uint)incr;
|
counts.Fp[comp][f] += (uint)incr;
|
||||||
|
@ -121,58 +110,56 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private MvJointType GetMvJoint()
|
public MvJointType GetJoint()
|
||||||
{
|
{
|
||||||
if (Row == 0)
|
if (Row == 0)
|
||||||
{
|
{
|
||||||
return Col == 0 ? MvJointType.MvJointZero : MvJointType.MvJointHnzvz;
|
return Col == 0 ? MvJointType.Zero : MvJointType.Hnzvz;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return Col == 0 ? MvJointType.MvJointHzvnz : MvJointType.MvJointHnzvnz;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void IncMv(Ptr<Vp9BackwardUpdates> counts)
|
return Col == 0 ? MvJointType.Hzvnz : MvJointType.Hnzvnz;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Inc(Ptr<Vp9BackwardUpdates> counts)
|
||||||
{
|
{
|
||||||
if (!counts.IsNull)
|
if (!counts.IsNull)
|
||||||
{
|
{
|
||||||
MvJointType j = GetMvJoint();
|
MvJointType j = GetJoint();
|
||||||
++counts.Value.Joints[(int)j];
|
++counts.Value.Joints[(int)j];
|
||||||
|
|
||||||
if (MvJointVertical(j))
|
if (JointVertical(j))
|
||||||
{
|
{
|
||||||
IncMvComponent(Row, ref counts.Value, 0, 1, 1);
|
IncComponent(Row, ref counts.Value, 0, 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MvJointHorizontal(j))
|
if (JointHorizontal(j))
|
||||||
{
|
{
|
||||||
IncMvComponent(Col, ref counts.Value, 1, 1, 1);
|
IncComponent(Col, ref counts.Value, 1, 1, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClampMv(int minCol, int maxCol, int minRow, int maxRow)
|
public void Clamp(int minCol, int maxCol, int minRow, int maxRow)
|
||||||
{
|
{
|
||||||
Col = (short)Math.Clamp(Col, minCol, maxCol);
|
Col = (short)Math.Clamp(Col, minCol, maxCol);
|
||||||
Row = (short)Math.Clamp(Row, minRow, maxRow);
|
Row = (short)Math.Clamp(Row, minRow, maxRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
private const int MvBorder = (16 << 3); // Allow 16 pels in 1/8th pel units
|
private const int Border = 16 << 3; // Allow 16 pels in 1/8th pel units
|
||||||
|
|
||||||
public void ClampMvRef(ref MacroBlockD xd)
|
public void ClampRef(ref MacroBlockD xd)
|
||||||
{
|
{
|
||||||
ClampMv(
|
Clamp(
|
||||||
xd.MbToLeftEdge - MvBorder,
|
xd.MbToLeftEdge - Border,
|
||||||
xd.MbToRightEdge + MvBorder,
|
xd.MbToRightEdge + Border,
|
||||||
xd.MbToTopEdge - MvBorder,
|
xd.MbToTopEdge - Border,
|
||||||
xd.MbToBottomEdge + MvBorder);
|
xd.MbToBottomEdge + Border);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LowerMvPrecision(bool allowHP)
|
public void LowerPrecision(bool allowHp)
|
||||||
{
|
{
|
||||||
bool useHP = allowHP && UseMvHp();
|
bool useHp = allowHp && UseHp();
|
||||||
if (!useHP)
|
if (!useHp)
|
||||||
{
|
{
|
||||||
if ((Row & 1) != 0)
|
if ((Row & 1) != 0)
|
||||||
{
|
{
|
||||||
|
@ -185,5 +172,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsValid()
|
||||||
|
{
|
||||||
|
return Row is > Constants.MvLow and < Constants.MvUpp &&
|
||||||
|
Col is > Constants.MvLow and < Constants.MvUpp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,16 +2,16 @@
|
||||||
{
|
{
|
||||||
internal enum MvClassType
|
internal enum MvClassType
|
||||||
{
|
{
|
||||||
MvClass0 = 0, /* (0, 2] integer pel */
|
Class0, /* (0, 2] integer pel */
|
||||||
MvClass1 = 1, /* (2, 4] integer pel */
|
Class1, /* (2, 4] integer pel */
|
||||||
MvClass2 = 2, /* (4, 8] integer pel */
|
Class2, /* (4, 8] integer pel */
|
||||||
MvClass3 = 3, /* (8, 16] integer pel */
|
Class3, /* (8, 16] integer pel */
|
||||||
MvClass4 = 4, /* (16, 32] integer pel */
|
Class4, /* (16, 32] integer pel */
|
||||||
MvClass5 = 5, /* (32, 64] integer pel */
|
Class5, /* (32, 64] integer pel */
|
||||||
MvClass6 = 6, /* (64, 128] integer pel */
|
Class6, /* (64, 128] integer pel */
|
||||||
MvClass7 = 7, /* (128, 256] integer pel */
|
Class7, /* (128, 256] integer pel */
|
||||||
MvClass8 = 8, /* (256, 512] integer pel */
|
Class8, /* (256, 512] integer pel */
|
||||||
MvClass9 = 9, /* (512, 1024] integer pel */
|
Class9, /* (512, 1024] integer pel */
|
||||||
MvClass10 = 10, /* (1024,2048] integer pel */
|
Class10 /* (1024,2048] integer pel */
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,9 +2,9 @@
|
||||||
{
|
{
|
||||||
internal enum MvJointType
|
internal enum MvJointType
|
||||||
{
|
{
|
||||||
MvJointZero = 0, /* Zero vector */
|
Zero, /* Zero vector */
|
||||||
MvJointHnzvz = 1, /* Vert zero, hor nonzero */
|
Hnzvz, /* Vert zero, hor nonzero */
|
||||||
MvJointHzvnz = 2, /* Hor zero, vert nonzero */
|
Hzvnz, /* Hor zero, vert nonzero */
|
||||||
MvJointHnzvnz = 3, /* Both components nonzero */
|
Hnzvnz /* Both components nonzero */
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,8 +2,8 @@
|
||||||
{
|
{
|
||||||
internal enum PlaneType
|
internal enum PlaneType
|
||||||
{
|
{
|
||||||
Y = 0,
|
Y,
|
||||||
Uv = 1,
|
Uv,
|
||||||
PlaneTypes
|
PlaneTypes
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,20 +2,20 @@
|
||||||
{
|
{
|
||||||
internal enum PredictionMode
|
internal enum PredictionMode
|
||||||
{
|
{
|
||||||
DcPred = 0, // Average of above and left pixels
|
DcPred, // Average of above and left pixels
|
||||||
VPred = 1, // Vertical
|
VPred, // Vertical
|
||||||
HPred = 2, // Horizontal
|
HPred, // Horizontal
|
||||||
D45Pred = 3, // Directional 45 deg = round(arctan(1 / 1) * 180 / pi)
|
D45Pred, // Directional 45 deg = round(arctan(1 / 1) * 180 / pi)
|
||||||
D135Pred = 4, // Directional 135 deg = 180 - 45
|
D135Pred, // Directional 135 deg = 180 - 45
|
||||||
D117Pred = 5, // Directional 117 deg = 180 - 63
|
D117Pred, // Directional 117 deg = 180 - 63
|
||||||
D153Pred = 6, // Directional 153 deg = 180 - 27
|
D153Pred, // Directional 153 deg = 180 - 27
|
||||||
D207Pred = 7, // Directional 207 deg = 180 + 27
|
D207Pred, // Directional 207 deg = 180 + 27
|
||||||
D63Pred = 8, // Directional 63 deg = round(arctan(2 / 1) * 180 / pi)
|
D63Pred, // Directional 63 deg = round(arctan(2 / 1) * 180 / pi)
|
||||||
TmPred = 9, // True-motion
|
TmPred, // True-motion
|
||||||
NearestMv = 10,
|
NearestMv,
|
||||||
NearMv = 11,
|
NearMv,
|
||||||
ZeroMv = 12,
|
ZeroMv,
|
||||||
NewMv = 13,
|
NewMv,
|
||||||
MbModeCount = 14
|
MbModeCount
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,6 +2,9 @@
|
||||||
{
|
{
|
||||||
internal struct RefBuffer
|
internal struct RefBuffer
|
||||||
{
|
{
|
||||||
|
public const int InvalidIdx = -1; // Invalid buffer index.
|
||||||
|
|
||||||
|
public int Idx;
|
||||||
public Surface Buf;
|
public Surface Buf;
|
||||||
public ScaleFactors Sf;
|
public ScaleFactors Sf;
|
||||||
}
|
}
|
||||||
|
|
12
src/Ryujinx.Graphics.Nvdec.Vp9/Types/RefCntBuffer.cs
Normal file
12
src/Ryujinx.Graphics.Nvdec.Vp9/Types/RefCntBuffer.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
|
{
|
||||||
|
internal struct RefCntBuffer
|
||||||
|
{
|
||||||
|
public int RefCount;
|
||||||
|
public int MiRows;
|
||||||
|
public int MiCols;
|
||||||
|
public byte Released;
|
||||||
|
public VpxCodecFrameBuffer RawFrameBuffer;
|
||||||
|
public Surface Buf;
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,9 +2,9 @@
|
||||||
{
|
{
|
||||||
internal enum ReferenceMode
|
internal enum ReferenceMode
|
||||||
{
|
{
|
||||||
SingleReference = 0,
|
Single,
|
||||||
CompoundReference = 1,
|
Compound,
|
||||||
ReferenceModeSelect = 2,
|
Select,
|
||||||
ReferenceModes = 3
|
ReferenceModes
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
internal struct ScaleFactors
|
internal struct ScaleFactors
|
||||||
{
|
{
|
||||||
private const int RefScaleShift = 14;
|
private const int RefScaleShift = 14;
|
||||||
private const int RefNoScale = (1 << RefScaleShift);
|
private const int RefNoScale = 1 << RefScaleShift;
|
||||||
private const int RefInvalidScale = -1;
|
private const int RefInvalidScale = -1;
|
||||||
|
|
||||||
private unsafe delegate void ConvolveFn(
|
private unsafe delegate void ConvolveFn(
|
||||||
|
@ -38,248 +38,99 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
int h,
|
int h,
|
||||||
int bd);
|
int bd);
|
||||||
|
|
||||||
private static readonly unsafe ConvolveFn[][][] PredictX16Y16 = new ConvolveFn[][][]
|
private static readonly unsafe ConvolveFn[][][] PredictX16Y16 =
|
||||||
{
|
{
|
||||||
new ConvolveFn[][]
|
new[]
|
||||||
{
|
{
|
||||||
new ConvolveFn[]
|
new ConvolveFn[] { ConvolveCopy, ConvolveAvg },
|
||||||
{
|
new ConvolveFn[] { Convolve8Vert, Convolve8AvgVert }
|
||||||
ConvolveCopy,
|
|
||||||
ConvolveAvg
|
|
||||||
},
|
},
|
||||||
new ConvolveFn[]
|
new[]
|
||||||
{
|
{
|
||||||
Convolve8Vert,
|
new ConvolveFn[] { Convolve8Horiz, Convolve8AvgHoriz },
|
||||||
Convolve8AvgVert
|
new ConvolveFn[] { Convolve8, Convolve8Avg }
|
||||||
}
|
|
||||||
},
|
|
||||||
new ConvolveFn[][]
|
|
||||||
{
|
|
||||||
new ConvolveFn[]
|
|
||||||
{
|
|
||||||
Convolve8Horiz,
|
|
||||||
Convolve8AvgHoriz
|
|
||||||
},
|
|
||||||
new ConvolveFn[]
|
|
||||||
{
|
|
||||||
Convolve8,
|
|
||||||
Convolve8Avg
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly unsafe ConvolveFn[][][] PredictX16 = new ConvolveFn[][][]
|
private static readonly unsafe ConvolveFn[][][] PredictX16 =
|
||||||
{
|
{
|
||||||
new ConvolveFn[][]
|
new[]
|
||||||
{
|
{
|
||||||
new ConvolveFn[]
|
new ConvolveFn[] { ScaledVert, ScaledAvgVert }, new ConvolveFn[] { ScaledVert, ScaledAvgVert }
|
||||||
{
|
|
||||||
ScaledVert,
|
|
||||||
ScaledAvgVert
|
|
||||||
},
|
},
|
||||||
new ConvolveFn[]
|
new[] { new ConvolveFn[] { Scaled2D, ScaledAvg2D }, new ConvolveFn[] { Scaled2D, ScaledAvg2D } }
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly unsafe ConvolveFn[][][] PredictY16 =
|
||||||
{
|
{
|
||||||
ScaledVert,
|
new[] { new ConvolveFn[] { ScaledHoriz, ScaledAvgHoriz }, new ConvolveFn[] { Scaled2D, ScaledAvg2D } },
|
||||||
ScaledAvgVert
|
new[] { new ConvolveFn[] { ScaledHoriz, ScaledAvgHoriz }, new ConvolveFn[] { Scaled2D, ScaledAvg2D } }
|
||||||
}
|
};
|
||||||
|
|
||||||
|
private static readonly unsafe ConvolveFn[][][] Predict =
|
||||||
|
{
|
||||||
|
new[] { new ConvolveFn[] { Scaled2D, ScaledAvg2D }, new ConvolveFn[] { Scaled2D, ScaledAvg2D } },
|
||||||
|
new[] { new ConvolveFn[] { Scaled2D, ScaledAvg2D }, new ConvolveFn[] { Scaled2D, ScaledAvg2D } }
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly unsafe HighbdConvolveFn[][][] HighbdPredictX16Y16 =
|
||||||
|
{
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new HighbdConvolveFn[] { HighbdConvolveCopy, HighbdConvolveAvg },
|
||||||
|
new HighbdConvolveFn[] { HighbdConvolve8Vert, HighbdConvolve8AvgVert }
|
||||||
},
|
},
|
||||||
new ConvolveFn[][]
|
new[]
|
||||||
{
|
{
|
||||||
new ConvolveFn[]
|
new HighbdConvolveFn[] { HighbdConvolve8Horiz, HighbdConvolve8AvgHoriz },
|
||||||
{
|
new HighbdConvolveFn[] { HighbdConvolve8, HighbdConvolve8Avg }
|
||||||
Scaled2D,
|
|
||||||
ScaledAvg2D
|
|
||||||
},
|
|
||||||
new ConvolveFn[]
|
|
||||||
{
|
|
||||||
Scaled2D,
|
|
||||||
ScaledAvg2D
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly unsafe ConvolveFn[][][] PredictY16 = new ConvolveFn[][][]
|
private static readonly unsafe HighbdConvolveFn[][][] HighbdPredictX16 =
|
||||||
{
|
{
|
||||||
new ConvolveFn[][]
|
new[]
|
||||||
{
|
{
|
||||||
new ConvolveFn[]
|
new HighbdConvolveFn[] { HighbdConvolve8Vert, HighbdConvolve8AvgVert },
|
||||||
{
|
new HighbdConvolveFn[] { HighbdConvolve8Vert, HighbdConvolve8AvgVert }
|
||||||
ScaledHoriz,
|
|
||||||
ScaledAvgHoriz
|
|
||||||
},
|
},
|
||||||
new ConvolveFn[]
|
new[]
|
||||||
{
|
{
|
||||||
Scaled2D,
|
new HighbdConvolveFn[] { HighbdConvolve8, HighbdConvolve8Avg },
|
||||||
ScaledAvg2D
|
new HighbdConvolveFn[] { HighbdConvolve8, HighbdConvolve8Avg }
|
||||||
}
|
|
||||||
},
|
|
||||||
new ConvolveFn[][]
|
|
||||||
{
|
|
||||||
new ConvolveFn[]
|
|
||||||
{
|
|
||||||
ScaledHoriz,
|
|
||||||
ScaledAvgHoriz
|
|
||||||
},
|
|
||||||
new ConvolveFn[]
|
|
||||||
{
|
|
||||||
Scaled2D,
|
|
||||||
ScaledAvg2D
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly unsafe ConvolveFn[][][] Predict = new ConvolveFn[][][]
|
private static readonly unsafe HighbdConvolveFn[][][] HighbdPredictY16 =
|
||||||
{
|
{
|
||||||
new ConvolveFn[][]
|
new[]
|
||||||
{
|
{
|
||||||
new ConvolveFn[]
|
new HighbdConvolveFn[] { HighbdConvolve8Horiz, HighbdConvolve8AvgHoriz },
|
||||||
{
|
new HighbdConvolveFn[] { HighbdConvolve8, HighbdConvolve8Avg }
|
||||||
Scaled2D,
|
|
||||||
ScaledAvg2D
|
|
||||||
},
|
},
|
||||||
new ConvolveFn[]
|
new[]
|
||||||
{
|
{
|
||||||
Scaled2D,
|
new HighbdConvolveFn[] { HighbdConvolve8Horiz, HighbdConvolve8AvgHoriz },
|
||||||
ScaledAvg2D
|
new HighbdConvolveFn[] { HighbdConvolve8, HighbdConvolve8Avg }
|
||||||
}
|
|
||||||
},
|
|
||||||
new ConvolveFn[][]
|
|
||||||
{
|
|
||||||
new ConvolveFn[]
|
|
||||||
{
|
|
||||||
Scaled2D,
|
|
||||||
ScaledAvg2D
|
|
||||||
},
|
|
||||||
new ConvolveFn[]
|
|
||||||
{
|
|
||||||
Scaled2D,
|
|
||||||
ScaledAvg2D
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly unsafe HighbdConvolveFn[][][] HighbdPredictX16Y16 = new HighbdConvolveFn[][][]
|
private static readonly unsafe HighbdConvolveFn[][][] HighbdPredict =
|
||||||
{
|
{
|
||||||
new HighbdConvolveFn[][]
|
new[]
|
||||||
{
|
{
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[] { HighbdConvolve8, HighbdConvolve8Avg },
|
||||||
{
|
new HighbdConvolveFn[] { HighbdConvolve8, HighbdConvolve8Avg }
|
||||||
HighbdConvolveCopy,
|
|
||||||
HighbdConvolveAvg
|
|
||||||
},
|
},
|
||||||
new HighbdConvolveFn[]
|
new[]
|
||||||
{
|
{
|
||||||
HighbdConvolve8Vert,
|
new HighbdConvolveFn[] { HighbdConvolve8, HighbdConvolve8Avg },
|
||||||
HighbdConvolve8AvgVert
|
new HighbdConvolveFn[] { HighbdConvolve8, HighbdConvolve8Avg }
|
||||||
}
|
|
||||||
},
|
|
||||||
new HighbdConvolveFn[][]
|
|
||||||
{
|
|
||||||
new HighbdConvolveFn[]
|
|
||||||
{
|
|
||||||
HighbdConvolve8Horiz,
|
|
||||||
HighbdConvolve8AvgHoriz
|
|
||||||
},
|
|
||||||
new HighbdConvolveFn[]
|
|
||||||
{
|
|
||||||
HighbdConvolve8,
|
|
||||||
HighbdConvolve8Avg
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly unsafe HighbdConvolveFn[][][] HighbdPredictX16 = new HighbdConvolveFn[][][]
|
public int XScaleFp; // Horizontal fixed point scale factor
|
||||||
{
|
public int YScaleFp; // Vertical fixed point scale factor
|
||||||
new HighbdConvolveFn[][]
|
|
||||||
{
|
|
||||||
new HighbdConvolveFn[]
|
|
||||||
{
|
|
||||||
HighbdConvolve8Vert,
|
|
||||||
HighbdConvolve8AvgVert
|
|
||||||
},
|
|
||||||
new HighbdConvolveFn[]
|
|
||||||
{
|
|
||||||
HighbdConvolve8Vert,
|
|
||||||
HighbdConvolve8AvgVert
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new HighbdConvolveFn[][]
|
|
||||||
{
|
|
||||||
new HighbdConvolveFn[]
|
|
||||||
{
|
|
||||||
HighbdConvolve8,
|
|
||||||
HighbdConvolve8Avg
|
|
||||||
},
|
|
||||||
new HighbdConvolveFn[]
|
|
||||||
{
|
|
||||||
HighbdConvolve8,
|
|
||||||
HighbdConvolve8Avg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly unsafe HighbdConvolveFn[][][] HighbdPredictY16 = new HighbdConvolveFn[][][]
|
|
||||||
{
|
|
||||||
new HighbdConvolveFn[][]
|
|
||||||
{
|
|
||||||
new HighbdConvolveFn[]
|
|
||||||
{
|
|
||||||
HighbdConvolve8Horiz,
|
|
||||||
HighbdConvolve8AvgHoriz
|
|
||||||
},
|
|
||||||
new HighbdConvolveFn[]
|
|
||||||
{
|
|
||||||
HighbdConvolve8,
|
|
||||||
HighbdConvolve8Avg
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new HighbdConvolveFn[][]
|
|
||||||
{
|
|
||||||
new HighbdConvolveFn[]
|
|
||||||
{
|
|
||||||
HighbdConvolve8Horiz,
|
|
||||||
HighbdConvolve8AvgHoriz
|
|
||||||
},
|
|
||||||
new HighbdConvolveFn[]
|
|
||||||
{
|
|
||||||
HighbdConvolve8,
|
|
||||||
HighbdConvolve8Avg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly unsafe HighbdConvolveFn[][][] HighbdPredict = new HighbdConvolveFn[][][]
|
|
||||||
{
|
|
||||||
new HighbdConvolveFn[][]
|
|
||||||
{
|
|
||||||
new HighbdConvolveFn[]
|
|
||||||
{
|
|
||||||
HighbdConvolve8,
|
|
||||||
HighbdConvolve8Avg
|
|
||||||
},
|
|
||||||
new HighbdConvolveFn[]
|
|
||||||
{
|
|
||||||
HighbdConvolve8,
|
|
||||||
HighbdConvolve8Avg
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new HighbdConvolveFn[][]
|
|
||||||
{
|
|
||||||
new HighbdConvolveFn[]
|
|
||||||
{
|
|
||||||
HighbdConvolve8,
|
|
||||||
HighbdConvolve8Avg
|
|
||||||
},
|
|
||||||
new HighbdConvolveFn[]
|
|
||||||
{
|
|
||||||
HighbdConvolve8,
|
|
||||||
HighbdConvolve8Avg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public int XScaleFP; // Horizontal fixed point scale factor
|
|
||||||
public int YScaleFP; // Vertical fixed point scale factor
|
|
||||||
public int XStepQ4;
|
public int XStepQ4;
|
||||||
public int YStepQ4;
|
public int YStepQ4;
|
||||||
|
|
||||||
|
@ -315,12 +166,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
if (YStepQ4 == 16)
|
if (YStepQ4 == 16)
|
||||||
{
|
{
|
||||||
// No scaling in either direction.
|
// No scaling in either direction.
|
||||||
PredictX16Y16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
|
PredictX16Y16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w,
|
||||||
|
h);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// No scaling in x direction. Must always scale in the y direction.
|
// No scaling in x direction. Must always scale in the y direction.
|
||||||
PredictX16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
|
PredictX16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w,
|
||||||
|
h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -328,7 +181,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
if (YStepQ4 == 16)
|
if (YStepQ4 == 16)
|
||||||
{
|
{
|
||||||
// No scaling in the y direction. Must always scale in the x direction.
|
// No scaling in the y direction. Must always scale in the x direction.
|
||||||
PredictY16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
|
PredictY16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w,
|
||||||
|
h);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -361,12 +215,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
if (YStepQ4 == 16)
|
if (YStepQ4 == 16)
|
||||||
{
|
{
|
||||||
// No scaling in either direction.
|
// No scaling in either direction.
|
||||||
HighbdPredictX16Y16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
|
HighbdPredictX16Y16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY,
|
||||||
|
ys, w, h, bd);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// No scaling in x direction. Must always scale in the y direction.
|
// No scaling in x direction. Must always scale in the y direction.
|
||||||
HighbdPredictX16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
|
HighbdPredictX16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys,
|
||||||
|
w, h, bd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -374,24 +230,26 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
if (YStepQ4 == 16)
|
if (YStepQ4 == 16)
|
||||||
{
|
{
|
||||||
// No scaling in the y direction. Must always scale in the x direction.
|
// No scaling in the y direction. Must always scale in the x direction.
|
||||||
HighbdPredictY16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
|
HighbdPredictY16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys,
|
||||||
|
w, h, bd);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Must always scale in both directions.
|
// Must always scale in both directions.
|
||||||
HighbdPredict[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
|
HighbdPredict[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w,
|
||||||
|
h, bd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int ScaledX(int val)
|
private int ScaledX(int val)
|
||||||
{
|
{
|
||||||
return (int)((long)val * XScaleFP >> RefScaleShift);
|
return (int)(((long)val * XScaleFp) >> RefScaleShift);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int ScaledY(int val)
|
private int ScaledY(int val)
|
||||||
{
|
{
|
||||||
return (int)((long)val * YScaleFP >> RefScaleShift);
|
return (int)(((long)val * YScaleFp) >> RefScaleShift);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int GetFixedPointScaleFactor(int otherSize, int thisSize)
|
private static int GetFixedPointScaleFactor(int otherSize, int thisSize)
|
||||||
|
@ -407,22 +265,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
{
|
{
|
||||||
int xOffQ4 = ScaledX(x << SubpelBits) & SubpelMask;
|
int xOffQ4 = ScaledX(x << SubpelBits) & SubpelMask;
|
||||||
int yOffQ4 = ScaledY(y << SubpelBits) & SubpelMask;
|
int yOffQ4 = ScaledY(y << SubpelBits) & SubpelMask;
|
||||||
Mv32 res = new Mv32()
|
Mv32 res = new() { Row = ScaledY(mv.Row) + yOffQ4, Col = ScaledX(mv.Col) + xOffQ4 };
|
||||||
{
|
|
||||||
Row = ScaledY(mv.Row) + yOffQ4,
|
|
||||||
Col = ScaledX(mv.Col) + xOffQ4
|
|
||||||
};
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsValidScale()
|
public bool IsValidScale()
|
||||||
{
|
{
|
||||||
return XScaleFP != RefInvalidScale && YScaleFP != RefInvalidScale;
|
return XScaleFp != RefInvalidScale && YScaleFp != RefInvalidScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsScaled()
|
public bool IsScaled()
|
||||||
{
|
{
|
||||||
return IsValidScale() && (XScaleFP != RefNoScale || YScaleFP != RefNoScale);
|
return IsValidScale() && (XScaleFp != RefNoScale || YScaleFp != RefNoScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool ValidRefFrameSize(int refWidth, int refHeight, int thisWidth, int thisHeight)
|
public static bool ValidRefFrameSize(int refWidth, int refHeight, int thisWidth, int thisHeight)
|
||||||
|
@ -437,13 +291,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
{
|
{
|
||||||
if (!ValidRefFrameSize(otherW, otherH, thisW, thisH))
|
if (!ValidRefFrameSize(otherW, otherH, thisW, thisH))
|
||||||
{
|
{
|
||||||
XScaleFP = RefInvalidScale;
|
XScaleFp = RefInvalidScale;
|
||||||
YScaleFP = RefInvalidScale;
|
YScaleFp = RefInvalidScale;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
XScaleFP = GetFixedPointScaleFactor(otherW, thisW);
|
XScaleFp = GetFixedPointScaleFactor(otherW, thisW);
|
||||||
YScaleFP = GetFixedPointScaleFactor(otherH, thisH);
|
YScaleFp = GetFixedPointScaleFactor(otherH, thisH);
|
||||||
XStepQ4 = ScaledX(16);
|
XStepQ4 = ScaledX(16);
|
||||||
YStepQ4 = ScaledY(16);
|
YStepQ4 = ScaledY(16);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
{
|
{
|
||||||
internal enum SegLvlFeatures
|
internal enum SegLvlFeatures
|
||||||
{
|
{
|
||||||
SegLvlAltQ = 0, // Use alternate Quantizer ....
|
AltQ, // Use alternate Quantizer ....
|
||||||
SegLvlAltLf = 1, // Use alternate loop filter value...
|
AltLf, // Use alternate loop filter value...
|
||||||
SegLvlRefFrame = 2, // Optional Segment reference frame
|
RefFrame, // Optional Segment reference frame
|
||||||
SegLvlSkip = 3, // Optional Segment (0,0) + skip mode
|
Skip, // Optional Segment (0,0) + skip mode
|
||||||
SegLvlMax = 4 // Number of features supported
|
Max // Number of features supported
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,6 @@
|
||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
|
using Ryujinx.Graphics.Video;
|
||||||
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
@ -6,8 +8,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
{
|
{
|
||||||
internal struct Segmentation
|
internal struct Segmentation
|
||||||
{
|
{
|
||||||
private static readonly int[] SegFeatureDataSigned = new int[] { 1, 1, 0, 0 };
|
public const int SegmentDeltadata = 0;
|
||||||
private static readonly int[] SegFeatureDataMax = new int[] { QuantCommon.MaxQ, Vp9.LoopFilter.MaxLoopFilter, 3, 0 };
|
public const int SegmentAbsdata = 1;
|
||||||
|
|
||||||
|
public const int MaxSegments = 8;
|
||||||
|
public const int SegTreeProbs = MaxSegments - 1;
|
||||||
|
|
||||||
|
public const int PredictionProbs = 3;
|
||||||
|
|
||||||
|
private static readonly int[] SegFeatureDataSigned = { 1, 1, 0, 0 };
|
||||||
|
private static readonly int[] SegFeatureDataMax = { QuantCommon.MaxQ, Vp9.LoopFilter.MaxLoopFilter, 3, 0 };
|
||||||
|
|
||||||
public bool Enabled;
|
public bool Enabled;
|
||||||
public bool UpdateMap;
|
public bool UpdateMap;
|
||||||
|
@ -26,8 +36,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
|
|
||||||
public void ClearAllSegFeatures()
|
public void ClearAllSegFeatures()
|
||||||
{
|
{
|
||||||
MemoryMarshal.CreateSpan(ref FeatureData[0][0], 8 * 4).Fill(0);
|
MemoryMarshal.CreateSpan(ref FeatureData[0][0], 8 * 4).Clear();
|
||||||
MemoryMarshal.CreateSpan(ref FeatureMask[0], 8).Fill(0);
|
MemoryMarshal.CreateSpan(ref FeatureMask[0], 8).Clear();
|
||||||
AqAvOffset = 0;
|
AqAvOffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,5 +77,88 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
{
|
{
|
||||||
return FeatureData[segmentId][(int)featureId];
|
return FeatureData[segmentId][(int)featureId];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int GetQIndex(int segmentId, int baseQIndex)
|
||||||
|
{
|
||||||
|
if (IsSegFeatureActive(segmentId, SegLvlFeatures.AltQ) != 0)
|
||||||
|
{
|
||||||
|
int data = GetSegData(segmentId, SegLvlFeatures.AltQ);
|
||||||
|
int segQIndex = AbsDelta == Constants.SegmentAbsData ? data : baseQIndex + data;
|
||||||
|
return Math.Clamp(segQIndex, 0, QuantCommon.MaxQ);
|
||||||
|
}
|
||||||
|
|
||||||
|
return baseQIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetupSegmentation(ref Vp9EntropyProbs fc, ref ReadBitBuffer rb)
|
||||||
|
{
|
||||||
|
UpdateMap = false;
|
||||||
|
UpdateData = 0;
|
||||||
|
|
||||||
|
Enabled = rb.ReadBit() != 0;
|
||||||
|
if (!Enabled)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Segmentation map update
|
||||||
|
UpdateMap = rb.ReadBit() != 0;
|
||||||
|
if (UpdateMap)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < SegTreeProbs; i++)
|
||||||
|
{
|
||||||
|
fc.SegTreeProb[i] = rb.ReadBit() != 0
|
||||||
|
? (byte)rb.ReadLiteral(8)
|
||||||
|
: (byte)Prob.MaxProb;
|
||||||
|
}
|
||||||
|
|
||||||
|
TemporalUpdate = rb.ReadBit() != 0;
|
||||||
|
if (TemporalUpdate)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < PredictionProbs; i++)
|
||||||
|
{
|
||||||
|
fc.SegPredProb[i] = rb.ReadBit() != 0
|
||||||
|
? (byte)rb.ReadLiteral(8)
|
||||||
|
: (byte)Prob.MaxProb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < PredictionProbs; i++)
|
||||||
|
{
|
||||||
|
fc.SegPredProb[i] = Prob.MaxProb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Segmentation data update
|
||||||
|
UpdateData = (byte)rb.ReadBit();
|
||||||
|
if (UpdateData != 0)
|
||||||
|
{
|
||||||
|
AbsDelta = (byte)rb.ReadBit();
|
||||||
|
|
||||||
|
ClearAllSegFeatures();
|
||||||
|
|
||||||
|
for (int i = 0; i < Constants.MaxSegments; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < (int)SegLvlFeatures.Max; j++)
|
||||||
|
{
|
||||||
|
int data = 0;
|
||||||
|
int featureEnabled = rb.ReadBit();
|
||||||
|
if (featureEnabled != 0)
|
||||||
|
{
|
||||||
|
EnableSegFeature(i, (SegLvlFeatures)j);
|
||||||
|
data = rb.DecodeUnsignedMax(FeatureDataMax((SegLvlFeatures)j));
|
||||||
|
if (IsSegFeatureSigned((SegLvlFeatures)j) != 0)
|
||||||
|
{
|
||||||
|
data = rb.ReadBit() != 0 ? -data : data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SetSegData(i, (SegLvlFeatures)j, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,33 +1,66 @@
|
||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
|
using Ryujinx.Graphics.Nvdec.Vp9.Common;
|
||||||
using Ryujinx.Graphics.Video;
|
using Ryujinx.Graphics.Video;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
{
|
{
|
||||||
|
internal delegate int VpxGetFrameBufferCbFnT(MemoryAllocator allocator, Ptr<InternalFrameBufferList> cbPriv,
|
||||||
|
ulong minSize, ref VpxCodecFrameBuffer fb);
|
||||||
|
|
||||||
internal struct Surface : ISurface
|
internal struct Surface : ISurface
|
||||||
{
|
{
|
||||||
|
public const int Innerborderinpixels = 96;
|
||||||
|
public const int InterpExtend = 4;
|
||||||
|
public const int EncBorderInPixels = 160;
|
||||||
|
public const int DecBorderInPixels = 32;
|
||||||
|
|
||||||
|
public const int Yv12FlagHighbitdepth = 8;
|
||||||
|
|
||||||
public ArrayPtr<byte> YBuffer;
|
public ArrayPtr<byte> YBuffer;
|
||||||
public ArrayPtr<byte> UBuffer;
|
public ArrayPtr<byte> UBuffer;
|
||||||
public ArrayPtr<byte> VBuffer;
|
public ArrayPtr<byte> VBuffer;
|
||||||
|
|
||||||
public unsafe Plane YPlane => new Plane((IntPtr)YBuffer.ToPointer(), YBuffer.Length);
|
public unsafe Plane YPlane => new((IntPtr)YBuffer.ToPointer(), YBuffer.Length);
|
||||||
public unsafe Plane UPlane => new Plane((IntPtr)UBuffer.ToPointer(), UBuffer.Length);
|
public unsafe Plane UPlane => new((IntPtr)UBuffer.ToPointer(), UBuffer.Length);
|
||||||
public unsafe Plane VPlane => new Plane((IntPtr)VBuffer.ToPointer(), VBuffer.Length);
|
public unsafe Plane VPlane => new((IntPtr)VBuffer.ToPointer(), VBuffer.Length);
|
||||||
|
|
||||||
public FrameField Field => FrameField.Progressive;
|
public FrameField Field => FrameField.Progressive;
|
||||||
|
|
||||||
public int Width { get; }
|
public int Width { get; private set; }
|
||||||
public int Height { get; }
|
public int Height { get; private set; }
|
||||||
public int AlignedWidth { get; }
|
public int AlignedWidth { get; private set; }
|
||||||
public int AlignedHeight { get; }
|
public int AlignedHeight { get; private set; }
|
||||||
public int Stride { get; }
|
public int Stride { get; private set; }
|
||||||
public int UvWidth { get; }
|
public int UvWidth { get; private set; }
|
||||||
public int UvHeight { get; }
|
public int UvHeight { get; private set; }
|
||||||
public int UvAlignedWidth { get; }
|
public int UvAlignedWidth { get; private set; }
|
||||||
public int UvAlignedHeight { get; }
|
public int UvAlignedHeight { get; private set; }
|
||||||
public int UvStride { get; }
|
public int UvStride { get; private set; }
|
||||||
public bool HighBd => false;
|
public bool HighBd { get; private set; }
|
||||||
|
|
||||||
|
public int FrameSize { get; private set; }
|
||||||
|
public int Border { get; private set; }
|
||||||
|
|
||||||
|
public int YCropWidth => Width;
|
||||||
|
public int YCropHeight => Height;
|
||||||
|
public int UvCropWidth => UvWidth;
|
||||||
|
public int UvCropHeight => UvHeight;
|
||||||
|
|
||||||
|
public ArrayPtr<byte> BufferAlloc;
|
||||||
|
public int BufferAllocSz;
|
||||||
|
public int SubsamplingX;
|
||||||
|
public int SubsamplingY;
|
||||||
|
public uint BitDepth;
|
||||||
|
public VpxColorSpace ColorSpace;
|
||||||
|
public VpxColorRange ColorRange;
|
||||||
|
public int RenderWidth;
|
||||||
|
public int RenderHeight;
|
||||||
|
|
||||||
|
public int Corrupted;
|
||||||
|
public int Flags;
|
||||||
|
|
||||||
private readonly IntPtr _pointer;
|
private readonly IntPtr _pointer;
|
||||||
|
|
||||||
|
@ -40,16 +73,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
|
|
||||||
int alignedWidth = (width + 7) & ~7;
|
int alignedWidth = (width + 7) & ~7;
|
||||||
int alignedHeight = (height + 7) & ~7;
|
int alignedHeight = (height + 7) & ~7;
|
||||||
int yStride = ((alignedWidth + 2 * border) + 31) & ~31;
|
int yStride = (alignedWidth + (2 * border) + 31) & ~31;
|
||||||
int yplaneSize = (alignedHeight + 2 * border) * yStride;
|
int yplaneSize = (alignedHeight + (2 * border)) * yStride;
|
||||||
int uvWidth = alignedWidth >> ssX;
|
int uvWidth = alignedWidth >> ssX;
|
||||||
int uvHeight = alignedHeight >> ssY;
|
int uvHeight = alignedHeight >> ssY;
|
||||||
int uvStride = yStride >> ssX;
|
int uvStride = yStride >> ssX;
|
||||||
int uvBorderW = border >> ssX;
|
int uvBorderW = border >> ssX;
|
||||||
int uvBorderH = border >> ssY;
|
int uvBorderH = border >> ssY;
|
||||||
int uvplaneSize = (uvHeight + 2 * uvBorderH) * uvStride;
|
int uvplaneSize = (uvHeight + (2 * uvBorderH)) * uvStride;
|
||||||
|
|
||||||
int frameSize = (highbd ? 2 : 1) * (yplaneSize + 2 * uvplaneSize);
|
int frameSize = (highbd ? 2 : 1) * (yplaneSize + (2 * uvplaneSize));
|
||||||
|
|
||||||
IntPtr pointer = Marshal.AllocHGlobal(frameSize);
|
IntPtr pointer = Marshal.AllocHGlobal(frameSize);
|
||||||
_pointer = pointer;
|
_pointer = pointer;
|
||||||
|
@ -74,6 +107,131 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
VBuffer = NewPlane(yplaneSize + uvplaneSize, uvplaneSize, (uvBorderH * uvStride) + uvBorderW);
|
VBuffer = NewPlane(yplaneSize + uvplaneSize, uvplaneSize, (uvBorderH * uvStride) + uvBorderW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public unsafe int ReallocFrameBuffer(
|
||||||
|
MemoryAllocator allocator,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
int ssX,
|
||||||
|
int ssY,
|
||||||
|
bool useHighbitdepth,
|
||||||
|
int border,
|
||||||
|
int byteAlignment,
|
||||||
|
Ptr<VpxCodecFrameBuffer> fb,
|
||||||
|
VpxGetFrameBufferCbFnT cb,
|
||||||
|
Ptr<InternalFrameBufferList> cbPriv)
|
||||||
|
{
|
||||||
|
int byteAlign = byteAlignment == 0 ? 1 : byteAlignment; // TODO: Is it safe to ignore the alignment?
|
||||||
|
int alignedWidth = (width + 7) & ~7;
|
||||||
|
int alignedHeight = (height + 7) & ~7;
|
||||||
|
int yStride = (alignedWidth + (2 * border) + 31) & ~31;
|
||||||
|
ulong yplaneSize =
|
||||||
|
((ulong)(alignedHeight + (2 * border)) * (ulong)yStride) + (ulong)byteAlignment;
|
||||||
|
int uvWidth = alignedWidth >> ssX;
|
||||||
|
int uvHeight = alignedHeight >> ssY;
|
||||||
|
int uvStride = yStride >> ssX;
|
||||||
|
int uvBorderW = border >> ssX;
|
||||||
|
int uvBorderH = border >> ssY;
|
||||||
|
ulong uvplaneSize =
|
||||||
|
((ulong)(uvHeight + (2 * uvBorderH)) * (ulong)uvStride) + (ulong)byteAlignment;
|
||||||
|
|
||||||
|
ulong frameSize = (ulong)(1 + (useHighbitdepth ? 1 : 0)) * (yplaneSize + (2 * uvplaneSize));
|
||||||
|
|
||||||
|
ArrayPtr<byte> buf = ArrayPtr<byte>.Null;
|
||||||
|
|
||||||
|
// frame_size is stored in buffer_alloc_sz, which is an int. If it won't
|
||||||
|
// fit, fail early.
|
||||||
|
if (frameSize > int.MaxValue)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cb != null)
|
||||||
|
{
|
||||||
|
const int alignAddrExtraSize = 31;
|
||||||
|
ulong externalFrameSize = frameSize + alignAddrExtraSize;
|
||||||
|
|
||||||
|
Debug.Assert(!fb.IsNull);
|
||||||
|
|
||||||
|
// Allocation to hold larger frame, or first allocation.
|
||||||
|
if (cb(allocator, cbPriv, externalFrameSize, ref fb.Value) < 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fb.Value.Data.IsNull || (ulong)fb.Value.Data.Length < externalFrameSize)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferAlloc = fb.Value.Data;
|
||||||
|
}
|
||||||
|
else if (frameSize > (ulong)BufferAllocSz)
|
||||||
|
{
|
||||||
|
// Allocation to hold larger frame, or first allocation.
|
||||||
|
allocator.Free(BufferAlloc);
|
||||||
|
BufferAlloc = ArrayPtr<byte>.Null;
|
||||||
|
|
||||||
|
BufferAlloc = allocator.Allocate<byte>((int)frameSize);
|
||||||
|
if (BufferAlloc.IsNull)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferAllocSz = (int)frameSize;
|
||||||
|
|
||||||
|
// This memset is needed for fixing valgrind error from C loop filter
|
||||||
|
// due to access uninitialized memory in frame border. It could be
|
||||||
|
// removed if border is totally removed.
|
||||||
|
MemoryUtil.Fill(BufferAlloc.ToPointer(), (byte)0, BufferAllocSz);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only support allocating buffers that have a border that's a multiple
|
||||||
|
* of 32. The border restriction is required to get 16-byte alignment of
|
||||||
|
* the start of the chroma rows without introducing an arbitrary gap
|
||||||
|
* between planes, which would break the semantics of things like
|
||||||
|
* vpx_img_set_rect(). */
|
||||||
|
if ((border & 0x1f) != 0)
|
||||||
|
{
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
Width = width;
|
||||||
|
Height = height;
|
||||||
|
AlignedWidth = alignedWidth;
|
||||||
|
AlignedHeight = alignedHeight;
|
||||||
|
Stride = yStride;
|
||||||
|
|
||||||
|
UvWidth = (width + ssX) >> ssX;
|
||||||
|
UvHeight = (height + ssY) >> ssY;
|
||||||
|
UvAlignedWidth = uvWidth;
|
||||||
|
UvAlignedHeight = uvHeight;
|
||||||
|
UvStride = uvStride;
|
||||||
|
|
||||||
|
Border = border;
|
||||||
|
FrameSize = (int)frameSize;
|
||||||
|
SubsamplingX = ssX;
|
||||||
|
SubsamplingY = ssY;
|
||||||
|
|
||||||
|
buf = BufferAlloc;
|
||||||
|
if (useHighbitdepth)
|
||||||
|
{
|
||||||
|
// Store uint16 addresses when using 16bit framebuffers
|
||||||
|
buf = BufferAlloc;
|
||||||
|
Flags = Yv12FlagHighbitdepth;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Flags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
YBuffer = buf.Slice((border * yStride) + border);
|
||||||
|
UBuffer = buf.Slice((int)yplaneSize + (uvBorderH * uvStride) + uvBorderW);
|
||||||
|
VBuffer = buf.Slice((int)yplaneSize + (int)uvplaneSize + (uvBorderH * uvStride) + uvBorderW);
|
||||||
|
|
||||||
|
Corrupted = 0; /* assume not corrupted by errors */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Marshal.FreeHGlobal(_pointer);
|
Marshal.FreeHGlobal(_pointer);
|
||||||
|
|
|
@ -55,7 +55,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
private static int GetMinLog2TileCols(int sb64Cols)
|
private static int GetMinLog2TileCols(int sb64Cols)
|
||||||
{
|
{
|
||||||
int minLog2 = 0;
|
int minLog2 = 0;
|
||||||
while ((MaxTileWidthB64 << minLog2) < sb64Cols)
|
while (MaxTileWidthB64 << minLog2 < sb64Cols)
|
||||||
{
|
{
|
||||||
++minLog2;
|
++minLog2;
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
private static int GetMaxLog2TileCols(int sb64Cols)
|
private static int GetMaxLog2TileCols(int sb64Cols)
|
||||||
{
|
{
|
||||||
int maxLog2 = 1;
|
int maxLog2 = 1;
|
||||||
while ((sb64Cols >> maxLog2) >= MinTileWidthB64)
|
while (sb64Cols >> maxLog2 >= MinTileWidthB64)
|
||||||
{
|
{
|
||||||
++maxLog2;
|
++maxLog2;
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
return maxLog2 - 1;
|
return maxLog2 - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void GetTileNBits(int miCols, ref int minLog2TileCols, ref int maxLog2TileCols)
|
public static void GetTileNBits(int miCols, out int minLog2TileCols, out int maxLog2TileCols)
|
||||||
{
|
{
|
||||||
int sb64Cols = MiColsAlignedToSb(miCols) >> Constants.MiBlockSizeLog2;
|
int sb64Cols = MiColsAlignedToSb(miCols) >> Constants.MiBlockSizeLog2;
|
||||||
minLog2TileCols = GetMinLog2TileCols(sb64Cols);
|
minLog2TileCols = GetMinLog2TileCols(sb64Cols);
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
{
|
{
|
||||||
public enum TxMode
|
public enum TxMode
|
||||||
{
|
{
|
||||||
Only4X4 = 0, // Only 4x4 transform used
|
Only4x4, // Only 4x4 transform used
|
||||||
Allow8X8 = 1, // Allow block transform size up to 8x8
|
Allow8x8, // Allow block transform size up to 8x8
|
||||||
Allow16X16 = 2, // Allow block transform size up to 16x16
|
Allow16x16, // Allow block transform size up to 16x16
|
||||||
Allow32X32 = 3, // Allow block transform size up to 32x32
|
Allow32x32, // Allow block transform size up to 32x32
|
||||||
TxModeSelect = 4, // Transform specified for each block
|
TxModeSelect, // Transform specified for each block
|
||||||
TxModes = 5
|
TxModes
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,10 +2,10 @@
|
||||||
{
|
{
|
||||||
public enum TxSize
|
public enum TxSize
|
||||||
{
|
{
|
||||||
Tx4x4 = 0, // 4x4 transform
|
Tx4x4, // 4x4 transform
|
||||||
Tx8x8 = 1, // 8x8 transform
|
Tx8x8, // 8x8 transform
|
||||||
Tx16x16 = 2, // 16x16 transform
|
Tx16x16, // 16x16 transform
|
||||||
Tx32x32 = 3, // 32x32 transform
|
Tx32x32, // 32x32 transform
|
||||||
TxSizes = 4
|
TxSizes
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,10 +2,10 @@
|
||||||
{
|
{
|
||||||
internal enum TxType
|
internal enum TxType
|
||||||
{
|
{
|
||||||
DctDct = 0, // DCT in both horizontal and vertical
|
DctDct, // DCT in both horizontal and vertical
|
||||||
AdstDct = 1, // ADST in vertical, DCT in horizontal
|
AdstDct, // ADST in vertical, DCT in horizontal
|
||||||
DctAdst = 2, // DCT in vertical, ADST in horizontal
|
DctAdst, // DCT in vertical, ADST in horizontal
|
||||||
AdstAdst = 3, // ADST in both directions
|
AdstAdst, // ADST in both directions
|
||||||
TxTypes = 4
|
TxTypes
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
using Ryujinx.Graphics.Nvdec.Vp9.Common;
|
using Ryujinx.Graphics.Nvdec.Vp9.Common;
|
||||||
|
using Ryujinx.Graphics.Nvdec.Vp9.Dsp;
|
||||||
using Ryujinx.Graphics.Video;
|
using Ryujinx.Graphics.Video;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
{
|
{
|
||||||
|
@ -9,27 +11,62 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
public MacroBlockD Mb;
|
public MacroBlockD Mb;
|
||||||
|
|
||||||
public ArrayPtr<TileWorkerData> TileWorkerData;
|
public ArrayPtr<TileWorkerData> TileWorkerData;
|
||||||
|
public int TotalTiles;
|
||||||
|
|
||||||
public InternalErrorInfo Error;
|
public InternalErrorInfo Error;
|
||||||
|
|
||||||
|
public VpxColorSpace ColorSpace;
|
||||||
|
public VpxColorRange ColorRange;
|
||||||
|
|
||||||
public int Width;
|
public int Width;
|
||||||
public int Height;
|
public int Height;
|
||||||
|
|
||||||
|
public int RenderWidth;
|
||||||
|
public int RenderHeight;
|
||||||
|
|
||||||
|
public int LastWidth;
|
||||||
|
public int LastHeight;
|
||||||
|
|
||||||
public int SubsamplingX;
|
public int SubsamplingX;
|
||||||
public int SubsamplingY;
|
public int SubsamplingY;
|
||||||
|
|
||||||
|
public bool UseHighBitDepth;
|
||||||
|
|
||||||
public ArrayPtr<MvRef> PrevFrameMvs;
|
public ArrayPtr<MvRef> PrevFrameMvs;
|
||||||
public ArrayPtr<MvRef> CurFrameMvs;
|
public ArrayPtr<MvRef> CurFrameMvs;
|
||||||
|
|
||||||
|
public Ptr<Surface> FrameToShow;
|
||||||
|
public Ptr<RefCntBuffer> PrevFrame;
|
||||||
|
|
||||||
|
public Ptr<RefCntBuffer> CurFrame;
|
||||||
|
|
||||||
|
public Array8<int> RefFrameMap; /* maps fb_idx to reference slot */
|
||||||
|
|
||||||
|
// Prepare ref_frame_map for the next frame.
|
||||||
|
// Only used in frame parallel decode.
|
||||||
|
public Array8<int> NextRefFrameMap;
|
||||||
|
|
||||||
public Array3<RefBuffer> FrameRefs;
|
public Array3<RefBuffer> FrameRefs;
|
||||||
|
|
||||||
|
public int NewFbIdx;
|
||||||
|
|
||||||
|
public int CurShowFrameFbIdx;
|
||||||
|
|
||||||
|
public FrameType LastFrameType;
|
||||||
public FrameType FrameType;
|
public FrameType FrameType;
|
||||||
|
|
||||||
|
public int ShowFrame;
|
||||||
|
public int LastShowFrame;
|
||||||
|
public int ShowExistingFrame;
|
||||||
|
|
||||||
// Flag signaling that the frame is encoded using only Intra modes.
|
// Flag signaling that the frame is encoded using only Intra modes.
|
||||||
public bool IntraOnly;
|
public bool IntraOnly;
|
||||||
|
public bool LastIntraOnly;
|
||||||
|
|
||||||
public bool AllowHighPrecisionMv;
|
public bool AllowHighPrecisionMv;
|
||||||
|
|
||||||
|
public int ResetFrameContext;
|
||||||
|
|
||||||
// MBs, MbRows/Cols is in 16-pixel units; MiRows/Cols is in
|
// MBs, MbRows/Cols is in 16-pixel units; MiRows/Cols is in
|
||||||
// ModeInfo (8-pixel) units.
|
// ModeInfo (8-pixel) units.
|
||||||
public int MBs;
|
public int MBs;
|
||||||
|
@ -49,9 +86,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
|
|
||||||
/* We allocate a ModeInfo struct for each macroblock, together with
|
/* We allocate a ModeInfo struct for each macroblock, together with
|
||||||
an extra row on top and column on the left to simplify prediction. */
|
an extra row on top and column on the left to simplify prediction. */
|
||||||
|
public int MiAllocSize;
|
||||||
public ArrayPtr<ModeInfo> Mip; /* Base of allocated array */
|
public ArrayPtr<ModeInfo> Mip; /* Base of allocated array */
|
||||||
public ArrayPtr<ModeInfo> Mi; /* Corresponds to upper left visible macroblock */
|
public ArrayPtr<ModeInfo> Mi; /* Corresponds to upper left visible macroblock */
|
||||||
|
|
||||||
|
// prev_mip and prev_mi will only be allocated in VP9 encoder.
|
||||||
|
public Ptr<ModeInfo> PrevMip; /* MODE_INFO array 'mip' from last decoded frame */
|
||||||
|
public Ptr<ModeInfo> PrevMi; /* 'mi' from last frame (points into prev_mip) */
|
||||||
|
|
||||||
public ArrayPtr<Ptr<ModeInfo>> MiGridBase;
|
public ArrayPtr<Ptr<ModeInfo>> MiGridBase;
|
||||||
public ArrayPtr<Ptr<ModeInfo>> MiGridVisible;
|
public ArrayPtr<Ptr<ModeInfo>> MiGridVisible;
|
||||||
|
|
||||||
|
@ -70,6 +112,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
|
|
||||||
public LoopFilterInfoN LfInfo;
|
public LoopFilterInfoN LfInfo;
|
||||||
|
|
||||||
|
public int RefreshFrameContext; /* Two state 0 = NO, 1 = YES */
|
||||||
|
|
||||||
public Array4<sbyte> RefFrameSignBias; /* Two state 0, 1 */
|
public Array4<sbyte> RefFrameSignBias; /* Two state 0, 1 */
|
||||||
|
|
||||||
public LoopFilter Lf;
|
public LoopFilter Lf;
|
||||||
|
@ -81,10 +125,26 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
public ReferenceMode ReferenceMode;
|
public ReferenceMode ReferenceMode;
|
||||||
|
|
||||||
public Ptr<Vp9EntropyProbs> Fc;
|
public Ptr<Vp9EntropyProbs> Fc;
|
||||||
|
public ArrayPtr<Vp9EntropyProbs> FrameContexts; // FRAME_CONTEXTS
|
||||||
|
public uint FrameContextIdx; /* Context to use/update */
|
||||||
public Ptr<Vp9BackwardUpdates> Counts;
|
public Ptr<Vp9BackwardUpdates> Counts;
|
||||||
|
|
||||||
|
public uint CurrentVideoFrame;
|
||||||
|
public BitstreamProfile Profile;
|
||||||
|
|
||||||
|
public BitDepth BitDepth;
|
||||||
|
public BitDepth DequantBitDepth; // bit_depth of current dequantizer
|
||||||
|
|
||||||
|
public int ErrorResilientMode;
|
||||||
|
public int FrameParallelDecodingMode;
|
||||||
|
|
||||||
public int Log2TileCols, Log2TileRows;
|
public int Log2TileCols, Log2TileRows;
|
||||||
|
|
||||||
|
public int ByteAlignment;
|
||||||
|
public int SkipLoopFilter;
|
||||||
|
|
||||||
|
public Ptr<BufferPool> BufferPool;
|
||||||
|
|
||||||
public ArrayPtr<sbyte> AboveSegContext;
|
public ArrayPtr<sbyte> AboveSegContext;
|
||||||
public ArrayPtr<sbyte> AboveContext;
|
public ArrayPtr<sbyte> AboveContext;
|
||||||
|
|
||||||
|
@ -95,8 +155,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
|
|
||||||
public bool CompoundReferenceAllowed()
|
public bool CompoundReferenceAllowed()
|
||||||
{
|
{
|
||||||
int i;
|
for (int i = 1; i < Constants.RefsPerFrame; ++i)
|
||||||
for (i = 1; i < Constants.RefsPerFrame; ++i)
|
|
||||||
{
|
{
|
||||||
if (RefFrameSignBias[i + 1] != RefFrameSignBias[1])
|
if (RefFrameSignBias[i + 1] != RefFrameSignBias[1])
|
||||||
{
|
{
|
||||||
|
@ -107,6 +166,47 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ref Surface GetFrameNewBuffer()
|
||||||
|
{
|
||||||
|
return ref BufferPool.Value.FrameBufs[NewFbIdx].Buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetFreeFb()
|
||||||
|
{
|
||||||
|
ref Array12<RefCntBuffer> frameBufs = ref BufferPool.Value.FrameBufs;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < Constants.FrameBuffers; ++i)
|
||||||
|
{
|
||||||
|
if (frameBufs[i].RefCount == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i != Constants.FrameBuffers)
|
||||||
|
{
|
||||||
|
frameBufs[i].RefCount = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Reset i to be INVALID_IDX to indicate no free buffer found.
|
||||||
|
i = RefBuffer.InvalidIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SwapCurrentAndLastSegMap()
|
||||||
|
{
|
||||||
|
// Swap indices.
|
||||||
|
(SegMapIdx, PrevSegMapIdx) = (PrevSegMapIdx, SegMapIdx);
|
||||||
|
|
||||||
|
CurrentFrameSegMap = SegMapArray[SegMapIdx];
|
||||||
|
LastFrameSegMap = SegMapArray[PrevSegMapIdx];
|
||||||
|
}
|
||||||
|
|
||||||
private static int CalcMiSize(int len)
|
private static int CalcMiSize(int len)
|
||||||
{
|
{
|
||||||
// Len is in mi units.
|
// Len is in mi units.
|
||||||
|
@ -129,7 +229,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
|
|
||||||
public void AllocTileWorkerData(MemoryAllocator allocator, int tileCols, int tileRows, int maxThreads)
|
public void AllocTileWorkerData(MemoryAllocator allocator, int tileCols, int tileRows, int maxThreads)
|
||||||
{
|
{
|
||||||
TileWorkerData = allocator.Allocate<TileWorkerData>(tileCols * tileRows + (maxThreads > 1 ? maxThreads : 0));
|
TileWorkerData =
|
||||||
|
allocator.Allocate<TileWorkerData>((tileCols * tileRows) + (maxThreads > 1 ? maxThreads : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FreeTileWorkerData(MemoryAllocator allocator)
|
public void FreeTileWorkerData(MemoryAllocator allocator)
|
||||||
|
@ -139,9 +240,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
|
|
||||||
private void AllocSegMap(MemoryAllocator allocator, int segMapSize)
|
private void AllocSegMap(MemoryAllocator allocator, int segMapSize)
|
||||||
{
|
{
|
||||||
int i;
|
for (int i = 0; i < Constants.NumPingPongBuffers; ++i)
|
||||||
|
|
||||||
for (i = 0; i < Constants.NumPingPongBuffers; ++i)
|
|
||||||
{
|
{
|
||||||
SegMapArray[i] = allocator.Allocate<byte>(segMapSize);
|
SegMapArray[i] = allocator.Allocate<byte>(segMapSize);
|
||||||
}
|
}
|
||||||
|
@ -156,9 +255,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
|
|
||||||
private void FreeSegMap(MemoryAllocator allocator)
|
private void FreeSegMap(MemoryAllocator allocator)
|
||||||
{
|
{
|
||||||
int i;
|
for (int i = 0; i < Constants.NumPingPongBuffers; ++i)
|
||||||
|
|
||||||
for (i = 0; i < Constants.NumPingPongBuffers; ++i)
|
|
||||||
{
|
{
|
||||||
allocator.Free(SegMapArray[i]);
|
allocator.Free(SegMapArray[i]);
|
||||||
SegMapArray[i] = ArrayPtr<byte>.Null;
|
SegMapArray[i] = ArrayPtr<byte>.Null;
|
||||||
|
@ -194,6 +291,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
Lf.Lfm = ArrayPtr<LoopFilterMask>.Null;
|
Lf.Lfm = ArrayPtr<LoopFilterMask>.Null;
|
||||||
allocator.Free(CurFrameMvs);
|
allocator.Free(CurFrameMvs);
|
||||||
CurFrameMvs = ArrayPtr<MvRef>.Null;
|
CurFrameMvs = ArrayPtr<MvRef>.Null;
|
||||||
|
|
||||||
if (UsePrevFrameMvs)
|
if (UsePrevFrameMvs)
|
||||||
{
|
{
|
||||||
allocator.Free(PrevFrameMvs);
|
allocator.Free(PrevFrameMvs);
|
||||||
|
@ -209,7 +307,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
Lf.Lfm = allocator.Allocate<LoopFilterMask>(((MiRows + (Constants.MiBlockSize - 1)) >> 3) * Lf.LfmStride);
|
Lf.Lfm = allocator.Allocate<LoopFilterMask>(((MiRows + (Constants.MiBlockSize - 1)) >> 3) * Lf.LfmStride);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AllocContextBuffers(MemoryAllocator allocator, int width, int height)
|
public bool AllocContextBuffers(MemoryAllocator allocator, int width, int height)
|
||||||
{
|
{
|
||||||
SetMbMi(width, height);
|
SetMbMi(width, height);
|
||||||
int newMiSize = MiStride * CalcMiSize(MiRows);
|
int newMiSize = MiStride * CalcMiSize(MiRows);
|
||||||
|
@ -239,6 +337,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
{
|
{
|
||||||
PrevFrameMvs = allocator.Allocate<MvRef>(MiRows * MiCols);
|
PrevFrameMvs = allocator.Allocate<MvRef>(MiRows * MiCols);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe void DecSetupMi()
|
private unsafe void DecSetupMi()
|
||||||
|
@ -266,9 +366,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
|
|
||||||
internal void InitMacroBlockD(ref MacroBlockD xd, ArrayPtr<int> dqcoeff)
|
internal void InitMacroBlockD(ref MacroBlockD xd, ArrayPtr<int> dqcoeff)
|
||||||
{
|
{
|
||||||
int i;
|
for (int i = 0; i < Constants.MaxMbPlane; ++i)
|
||||||
|
|
||||||
for (i = 0; i < Constants.MaxMbPlane; ++i)
|
|
||||||
{
|
{
|
||||||
xd.Plane[i].DqCoeff = dqcoeff;
|
xd.Plane[i].DqCoeff = dqcoeff;
|
||||||
xd.AboveContext[i] = AboveContext.Slice(i * 2 * TileInfo.MiColsAlignedToSb(MiCols));
|
xd.AboveContext[i] = AboveContext.Slice(i * 2 * TileInfo.MiColsAlignedToSb(MiCols));
|
||||||
|
@ -281,6 +379,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
{
|
{
|
||||||
MemoryUtil.Copy(ref xd.Plane[i].SegDequant, ref UvDequant);
|
MemoryUtil.Copy(ref xd.Plane[i].SegDequant, ref UvDequant);
|
||||||
}
|
}
|
||||||
|
|
||||||
xd.Fc = new Ptr<Vp9EntropyProbs>(ref Fc.Value);
|
xd.Fc = new Ptr<Vp9EntropyProbs>(ref Fc.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,29 +392,27 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
|
|
||||||
public void SetupSegmentationDequant()
|
public void SetupSegmentationDequant()
|
||||||
{
|
{
|
||||||
const BitDepth bitDepth = BitDepth.Bits8; // TODO: Configurable
|
|
||||||
// Build y/uv dequant values based on segmentation.
|
// Build y/uv dequant values based on segmentation.
|
||||||
if (Seg.Enabled)
|
if (Seg.Enabled)
|
||||||
{
|
{
|
||||||
int i;
|
for (int i = 0; i < Constants.MaxSegments; ++i)
|
||||||
for (i = 0; i < Constants.MaxSegments; ++i)
|
|
||||||
{
|
{
|
||||||
int qIndex = QuantCommon.GetQIndex(ref Seg, i, BaseQindex);
|
int qindex = Seg.GetQIndex(i, BaseQindex);
|
||||||
YDequant[i][0] = QuantCommon.DcQuant(qIndex, YDcDeltaQ, bitDepth);
|
YDequant[i][0] = QuantCommon.DcQuant(qindex, YDcDeltaQ, BitDepth);
|
||||||
YDequant[i][1] = QuantCommon.AcQuant(qIndex, 0, bitDepth);
|
YDequant[i][1] = QuantCommon.AcQuant(qindex, 0, BitDepth);
|
||||||
UvDequant[i][0] = QuantCommon.DcQuant(qIndex, UvDcDeltaQ, bitDepth);
|
UvDequant[i][0] = QuantCommon.DcQuant(qindex, UvDcDeltaQ, BitDepth);
|
||||||
UvDequant[i][1] = QuantCommon.AcQuant(qIndex, UvAcDeltaQ, bitDepth);
|
UvDequant[i][1] = QuantCommon.AcQuant(qindex, UvAcDeltaQ, BitDepth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int qIndex = BaseQindex;
|
int qindex = BaseQindex;
|
||||||
// When segmentation is disabled, only the first value is used. The
|
// When segmentation is disabled, only the first value is used. The
|
||||||
// remaining are don't cares.
|
// remaining are don't cares.
|
||||||
YDequant[0][0] = QuantCommon.DcQuant(qIndex, YDcDeltaQ, bitDepth);
|
YDequant[0][0] = QuantCommon.DcQuant(qindex, YDcDeltaQ, BitDepth);
|
||||||
YDequant[0][1] = QuantCommon.AcQuant(qIndex, 0, bitDepth);
|
YDequant[0][1] = QuantCommon.AcQuant(qindex, 0, BitDepth);
|
||||||
UvDequant[0][0] = QuantCommon.DcQuant(qIndex, UvDcDeltaQ, bitDepth);
|
UvDequant[0][0] = QuantCommon.DcQuant(qindex, UvDcDeltaQ, BitDepth);
|
||||||
UvDequant[0][1] = QuantCommon.AcQuant(qIndex, UvAcDeltaQ, bitDepth);
|
UvDequant[0][1] = QuantCommon.AcQuant(qindex, UvAcDeltaQ, BitDepth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,5 +424,576 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
refBuf.Sf.SetupScaleFactorsForFrame(refBuf.Buf.Width, refBuf.Buf.Height, Width, Height);
|
refBuf.Sf.SetupScaleFactorsForFrame(refBuf.Buf.Width, refBuf.Buf.Height, Width, Height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ReadFrameReferenceModeProbs(ref Reader r)
|
||||||
|
{
|
||||||
|
ref Vp9EntropyProbs fc = ref Fc.Value;
|
||||||
|
|
||||||
|
|
||||||
|
if (ReferenceMode == ReferenceMode.Select)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Constants.CompInterContexts; ++i)
|
||||||
|
{
|
||||||
|
r.DiffUpdateProb(ref fc.CompInterProb[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ReferenceMode != ReferenceMode.Compound)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Constants.RefContexts; ++i)
|
||||||
|
{
|
||||||
|
r.DiffUpdateProb(ref fc.SingleRefProb[i][0]);
|
||||||
|
r.DiffUpdateProb(ref fc.SingleRefProb[i][1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ReferenceMode != ReferenceMode.Single)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Constants.RefContexts; ++i)
|
||||||
|
{
|
||||||
|
r.DiffUpdateProb(ref fc.CompRefProb[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReferenceMode ReadFrameReferenceMode(ref Reader r)
|
||||||
|
{
|
||||||
|
if (CompoundReferenceAllowed())
|
||||||
|
{
|
||||||
|
return r.ReadBit() != 0
|
||||||
|
? r.ReadBit() != 0 ? ReferenceMode.Select : ReferenceMode.Compound
|
||||||
|
: ReferenceMode.Single;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ReferenceMode.Single;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetupCompoundReferenceMode()
|
||||||
|
{
|
||||||
|
if (RefFrameSignBias[Constants.LastFrame] == RefFrameSignBias[Constants.GoldenFrame])
|
||||||
|
{
|
||||||
|
CompFixedRef = Constants.AltRefFrame;
|
||||||
|
CompVarRef[0] = Constants.LastFrame;
|
||||||
|
CompVarRef[1] = Constants.GoldenFrame;
|
||||||
|
}
|
||||||
|
else if (RefFrameSignBias[Constants.LastFrame] == RefFrameSignBias[Constants.AltRefFrame])
|
||||||
|
{
|
||||||
|
CompFixedRef = Constants.GoldenFrame;
|
||||||
|
CompVarRef[0] = Constants.LastFrame;
|
||||||
|
CompVarRef[1] = Constants.AltRefFrame;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CompFixedRef = Constants.LastFrame;
|
||||||
|
CompVarRef[0] = Constants.GoldenFrame;
|
||||||
|
CompVarRef[1] = Constants.AltRefFrame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void InitMvProbs()
|
||||||
|
{
|
||||||
|
Fc.Value.Joints[0] = 32;
|
||||||
|
Fc.Value.Joints[1] = 64;
|
||||||
|
Fc.Value.Joints[2] = 96;
|
||||||
|
|
||||||
|
Fc.Value.Sign[0] = 128;
|
||||||
|
Fc.Value.Classes[0][0] = 224;
|
||||||
|
Fc.Value.Classes[0][1] = 144;
|
||||||
|
Fc.Value.Classes[0][2] = 192;
|
||||||
|
Fc.Value.Classes[0][3] = 168;
|
||||||
|
Fc.Value.Classes[0][4] = 192;
|
||||||
|
Fc.Value.Classes[0][5] = 176;
|
||||||
|
Fc.Value.Classes[0][6] = 192;
|
||||||
|
Fc.Value.Classes[0][7] = 198;
|
||||||
|
Fc.Value.Classes[0][8] = 198;
|
||||||
|
Fc.Value.Classes[0][9] = 245;
|
||||||
|
Fc.Value.Class0[0][0] = 216;
|
||||||
|
Fc.Value.Bits[0][0] = 136;
|
||||||
|
Fc.Value.Bits[0][1] = 140;
|
||||||
|
Fc.Value.Bits[0][2] = 148;
|
||||||
|
Fc.Value.Bits[0][3] = 160;
|
||||||
|
Fc.Value.Bits[0][4] = 176;
|
||||||
|
Fc.Value.Bits[0][5] = 192;
|
||||||
|
Fc.Value.Bits[0][6] = 224;
|
||||||
|
Fc.Value.Bits[0][7] = 234;
|
||||||
|
Fc.Value.Bits[0][8] = 234;
|
||||||
|
Fc.Value.Bits[0][9] = 240;
|
||||||
|
Fc.Value.Class0Fp[0][0][0] = 128;
|
||||||
|
Fc.Value.Class0Fp[0][0][1] = 128;
|
||||||
|
Fc.Value.Class0Fp[0][0][2] = 64;
|
||||||
|
Fc.Value.Class0Fp[0][1][0] = 96;
|
||||||
|
Fc.Value.Class0Fp[0][1][1] = 112;
|
||||||
|
Fc.Value.Class0Fp[0][1][2] = 64;
|
||||||
|
Fc.Value.Fp[0][0] = 64;
|
||||||
|
Fc.Value.Fp[0][1] = 96;
|
||||||
|
Fc.Value.Fp[0][2] = 64;
|
||||||
|
Fc.Value.Class0Hp[0] = 160;
|
||||||
|
Fc.Value.Hp[0] = 128;
|
||||||
|
|
||||||
|
Fc.Value.Sign[1] = 128;
|
||||||
|
Fc.Value.Classes[1][0] = 216;
|
||||||
|
Fc.Value.Classes[1][1] = 128;
|
||||||
|
Fc.Value.Classes[1][2] = 176;
|
||||||
|
Fc.Value.Classes[1][3] = 160;
|
||||||
|
Fc.Value.Classes[1][4] = 176;
|
||||||
|
Fc.Value.Classes[1][5] = 176;
|
||||||
|
Fc.Value.Classes[1][6] = 192;
|
||||||
|
Fc.Value.Classes[1][7] = 198;
|
||||||
|
Fc.Value.Classes[1][8] = 198;
|
||||||
|
Fc.Value.Classes[1][9] = 208;
|
||||||
|
Fc.Value.Class0[1][0] = 208;
|
||||||
|
Fc.Value.Bits[1][0] = 136;
|
||||||
|
Fc.Value.Bits[1][1] = 140;
|
||||||
|
Fc.Value.Bits[1][2] = 148;
|
||||||
|
Fc.Value.Bits[1][3] = 160;
|
||||||
|
Fc.Value.Bits[1][4] = 176;
|
||||||
|
Fc.Value.Bits[1][5] = 192;
|
||||||
|
Fc.Value.Bits[1][6] = 224;
|
||||||
|
Fc.Value.Bits[1][7] = 234;
|
||||||
|
Fc.Value.Bits[1][8] = 234;
|
||||||
|
Fc.Value.Bits[1][9] = 240;
|
||||||
|
Fc.Value.Class0Fp[1][0][0] = 128;
|
||||||
|
Fc.Value.Class0Fp[1][0][1] = 128;
|
||||||
|
Fc.Value.Class0Fp[1][0][2] = 64;
|
||||||
|
Fc.Value.Class0Fp[1][1][0] = 96;
|
||||||
|
Fc.Value.Class0Fp[1][1][1] = 112;
|
||||||
|
Fc.Value.Class0Fp[1][1][2] = 64;
|
||||||
|
Fc.Value.Fp[1][0] = 64;
|
||||||
|
Fc.Value.Fp[1][1] = 96;
|
||||||
|
Fc.Value.Fp[1][2] = 64;
|
||||||
|
Fc.Value.Class0Hp[1] = 160;
|
||||||
|
Fc.Value.Hp[1] = 128;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AdaptMvProbs(bool allowHp)
|
||||||
|
{
|
||||||
|
ref Vp9EntropyProbs fc = ref Fc.Value;
|
||||||
|
ref Vp9EntropyProbs preFc = ref FrameContexts[(int)FrameContextIdx];
|
||||||
|
ref Vp9BackwardUpdates counts = ref Counts.Value;
|
||||||
|
|
||||||
|
Prob.VpxTreeMergeProbs(
|
||||||
|
EntropyMv.JointTree,
|
||||||
|
preFc.Joints.AsSpan(),
|
||||||
|
counts.Joints.AsSpan(),
|
||||||
|
fc.Joints.AsSpan());
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; ++i)
|
||||||
|
{
|
||||||
|
fc.Sign[i] = Prob.ModeMvMergeProbs(preFc.Sign[i], ref counts.Sign[i]);
|
||||||
|
Prob.VpxTreeMergeProbs(
|
||||||
|
EntropyMv.ClassTree,
|
||||||
|
preFc.Classes[i].AsSpan(),
|
||||||
|
counts.Classes[i].AsSpan(),
|
||||||
|
fc.Classes[i].AsSpan());
|
||||||
|
Prob.VpxTreeMergeProbs(
|
||||||
|
EntropyMv.Class0Tree,
|
||||||
|
preFc.Class0[i].AsSpan(),
|
||||||
|
counts.Class0[i].AsSpan(),
|
||||||
|
fc.Class0[i].AsSpan());
|
||||||
|
|
||||||
|
for (int j = 0; j < EntropyMv.OffsetBits; ++j)
|
||||||
|
{
|
||||||
|
fc.Bits[i][j] = Prob.ModeMvMergeProbs(preFc.Bits[i][j], ref counts.Bits[i][j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 0; j < EntropyMv.Class0Size; ++j)
|
||||||
|
{
|
||||||
|
Prob.VpxTreeMergeProbs(
|
||||||
|
EntropyMv.FpTree,
|
||||||
|
preFc.Class0Fp[i][j].AsSpan(),
|
||||||
|
counts.Class0Fp[i][j].AsSpan(),
|
||||||
|
fc.Class0Fp[i][j].AsSpan());
|
||||||
|
}
|
||||||
|
|
||||||
|
Prob.VpxTreeMergeProbs(EntropyMv.FpTree, preFc.Fp[i].AsSpan(), counts.Fp[i].AsSpan(),
|
||||||
|
fc.Fp[i].AsSpan());
|
||||||
|
|
||||||
|
if (allowHp)
|
||||||
|
{
|
||||||
|
fc.Class0Hp[i] = Prob.ModeMvMergeProbs(preFc.Class0Hp[i], ref counts.Class0Hp[i]);
|
||||||
|
fc.Hp[i] = Prob.ModeMvMergeProbs(preFc.Hp[i], ref counts.Hp[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResizeContextBuffers(MemoryAllocator allocator, int width, int height)
|
||||||
|
{
|
||||||
|
if (Width != width || Height != height)
|
||||||
|
{
|
||||||
|
int newMiRows = BitUtils.AlignPowerOfTwo(height, Constants.MiSizeLog2) >> Constants.MiSizeLog2;
|
||||||
|
int newMiCols = BitUtils.AlignPowerOfTwo(width, Constants.MiSizeLog2) >> Constants.MiSizeLog2;
|
||||||
|
|
||||||
|
// Allocations in AllocContextBuffers() depend on individual
|
||||||
|
// dimensions as well as the overall size.
|
||||||
|
if (newMiCols > MiCols || newMiRows > MiRows)
|
||||||
|
{
|
||||||
|
if (AllocContextBuffers(allocator, width, height))
|
||||||
|
{
|
||||||
|
// The Mi* values have been cleared and any existing context
|
||||||
|
// buffers have been freed. Clear Width and Height to be
|
||||||
|
// consistent and to force a realloc next time.
|
||||||
|
Width = 0;
|
||||||
|
Height = 0;
|
||||||
|
Error.InternalError(CodecErr.MemError, "Failed to allocate context buffers");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetMbMi(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
InitContextBuffers();
|
||||||
|
Width = width;
|
||||||
|
Height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CurFrameMvs.IsNull ||
|
||||||
|
MiRows > CurFrame.Value.MiRows ||
|
||||||
|
MiCols > CurFrame.Value.MiCols)
|
||||||
|
{
|
||||||
|
ResizeMvBuffer(allocator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CheckMemError<T>(ref ArrayPtr<T> lval, ArrayPtr<T> expr)
|
||||||
|
where T : unmanaged
|
||||||
|
{
|
||||||
|
lval = expr;
|
||||||
|
if (lval.IsNull)
|
||||||
|
{
|
||||||
|
Error.InternalError(CodecErr.MemError, "Failed to allocate");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ResizeMvBuffer(MemoryAllocator allocator)
|
||||||
|
{
|
||||||
|
allocator.Free(CurFrameMvs);
|
||||||
|
CurFrame.Value.MiRows = MiRows;
|
||||||
|
CurFrame.Value.MiCols = MiCols;
|
||||||
|
CheckMemError(ref CurFrameMvs, allocator.Allocate<MvRef>(MiRows * MiCols));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CheckMemError<T>(ref Ptr<T> lval, Ptr<T> expr) where T : unmanaged
|
||||||
|
{
|
||||||
|
lval = expr;
|
||||||
|
if (lval.IsNull)
|
||||||
|
{
|
||||||
|
Error.InternalError(CodecErr.MemError, "Failed to allocate");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetupTileInfo(ref ReadBitBuffer rb)
|
||||||
|
{
|
||||||
|
int minLog2TileCols = 0, maxLog2TileCols = 0, maxOnes;
|
||||||
|
TileInfo.GetTileNBits(MiCols, out minLog2TileCols, out maxLog2TileCols);
|
||||||
|
|
||||||
|
// columns
|
||||||
|
maxOnes = maxLog2TileCols - minLog2TileCols;
|
||||||
|
Log2TileCols = minLog2TileCols;
|
||||||
|
while (maxOnes-- != 0 && rb.ReadBit() != 0)
|
||||||
|
{
|
||||||
|
Log2TileCols++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Log2TileCols > 6)
|
||||||
|
{
|
||||||
|
Error.InternalError(CodecErr.CorruptFrame, "Invalid number of tile columns");
|
||||||
|
}
|
||||||
|
|
||||||
|
// rows
|
||||||
|
Log2TileRows = rb.ReadBit();
|
||||||
|
if (Log2TileRows != 0)
|
||||||
|
{
|
||||||
|
Log2TileRows += rb.ReadBit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReadBitdepthColorspaceSampling(ref ReadBitBuffer rb)
|
||||||
|
{
|
||||||
|
if (Profile >= BitstreamProfile.Profile2)
|
||||||
|
{
|
||||||
|
BitDepth = rb.ReadBit() != 0 ? BitDepth.Bits12 : BitDepth.Bits10;
|
||||||
|
UseHighBitDepth = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BitDepth = BitDepth.Bits8;
|
||||||
|
UseHighBitDepth = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorSpace = (VpxColorSpace)rb.ReadLiteral(3);
|
||||||
|
if (ColorSpace != VpxColorSpace.Srgb)
|
||||||
|
{
|
||||||
|
ColorRange = (VpxColorRange)rb.ReadBit();
|
||||||
|
if (Profile == BitstreamProfile.Profile1 || Profile == BitstreamProfile.Profile3)
|
||||||
|
{
|
||||||
|
SubsamplingX = rb.ReadBit();
|
||||||
|
SubsamplingY = rb.ReadBit();
|
||||||
|
if (SubsamplingX == 1 && SubsamplingY == 1)
|
||||||
|
{
|
||||||
|
Error.InternalError(CodecErr.UnsupBitstream,
|
||||||
|
"4:2:0 color not supported in profile 1 or 3");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rb.ReadBit() != 0)
|
||||||
|
{
|
||||||
|
Error.InternalError(CodecErr.UnsupBitstream, "Reserved bit set");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SubsamplingY = SubsamplingX = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ColorRange = VpxColorRange.Full;
|
||||||
|
if (Profile == BitstreamProfile.Profile1 || Profile == BitstreamProfile.Profile3)
|
||||||
|
{
|
||||||
|
// Note if colorspace is SRGB then 4:4:4 chroma sampling is assumed.
|
||||||
|
// 4:2:2 or 4:4:0 chroma sampling is not allowed.
|
||||||
|
SubsamplingY = SubsamplingX = 0;
|
||||||
|
if (rb.ReadBit() != 0)
|
||||||
|
{
|
||||||
|
Error.InternalError(CodecErr.UnsupBitstream, "Reserved bit set");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Error.InternalError(CodecErr.UnsupBitstream, "4:4:4 color not supported in profile 0 or 2");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AdaptModeProbs()
|
||||||
|
{
|
||||||
|
ref Vp9EntropyProbs fc = ref Fc.Value;
|
||||||
|
ref Vp9EntropyProbs preFc = ref FrameContexts[(int)FrameContextIdx];
|
||||||
|
ref Vp9BackwardUpdates counts = ref Counts.Value;
|
||||||
|
|
||||||
|
for (int i = 0; i < Constants.IntraInterContexts; i++)
|
||||||
|
{
|
||||||
|
fc.IntraInterProb[i] = Prob.ModeMvMergeProbs(preFc.IntraInterProb[i], ref counts.IntraInter[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < Constants.CompInterContexts; i++)
|
||||||
|
{
|
||||||
|
fc.CompInterProb[i] = Prob.ModeMvMergeProbs(preFc.CompInterProb[i], ref counts.CompInter[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < Constants.RefContexts; i++)
|
||||||
|
{
|
||||||
|
fc.CompRefProb[i] = Prob.ModeMvMergeProbs(preFc.CompRefProb[i], ref counts.CompRef[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < Constants.RefContexts; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < 2; j++)
|
||||||
|
{
|
||||||
|
fc.SingleRefProb[i][j] =
|
||||||
|
Prob.ModeMvMergeProbs(preFc.SingleRefProb[i][j], ref counts.SingleRef[i][j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < Constants.InterModeContexts; i++)
|
||||||
|
{
|
||||||
|
Prob.VpxTreeMergeProbs(
|
||||||
|
EntropyMode.InterModeTree,
|
||||||
|
preFc.InterModeProb[i].AsSpan(),
|
||||||
|
counts.InterMode[i].AsSpan(),
|
||||||
|
fc.InterModeProb[i].AsSpan());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < EntropyMode.BlockSizeGroups; i++)
|
||||||
|
{
|
||||||
|
Prob.VpxTreeMergeProbs(
|
||||||
|
EntropyMode.IntraModeTree,
|
||||||
|
preFc.YModeProb[i].AsSpan(),
|
||||||
|
counts.YMode[i].AsSpan(),
|
||||||
|
fc.YModeProb[i].AsSpan());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < Constants.IntraModes; ++i)
|
||||||
|
{
|
||||||
|
Prob.VpxTreeMergeProbs(
|
||||||
|
EntropyMode.IntraModeTree,
|
||||||
|
preFc.UvModeProb[i].AsSpan(),
|
||||||
|
counts.UvMode[i].AsSpan(),
|
||||||
|
fc.UvModeProb[i].AsSpan());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < Constants.PartitionContexts; i++)
|
||||||
|
{
|
||||||
|
Prob.VpxTreeMergeProbs(
|
||||||
|
EntropyMode.PartitionTree,
|
||||||
|
preFc.PartitionProb[i].AsSpan(),
|
||||||
|
counts.Partition[i].AsSpan(),
|
||||||
|
fc.PartitionProb[i].AsSpan());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (InterpFilter == Constants.Switchable)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Constants.SwitchableFilterContexts; i++)
|
||||||
|
{
|
||||||
|
Prob.VpxTreeMergeProbs(
|
||||||
|
EntropyMode.SwitchableInterpTree,
|
||||||
|
preFc.SwitchableInterpProb[i].AsSpan(),
|
||||||
|
counts.SwitchableInterp[i].AsSpan(),
|
||||||
|
fc.SwitchableInterpProb[i].AsSpan());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TxMode == TxMode.TxModeSelect)
|
||||||
|
{
|
||||||
|
Array1<Array2<uint>> branchCt8x8P = new();
|
||||||
|
Array2<Array2<uint>> branchCt16x16P = new();
|
||||||
|
Array3<Array2<uint>> branchCt32x32P = new();
|
||||||
|
|
||||||
|
for (int i = 0; i < EntropyMode.TxSizeContexts; ++i)
|
||||||
|
{
|
||||||
|
EntropyMode.TxCountsToBranchCounts8x8(counts.Tx8x8[i].AsSpan(), ref branchCt8x8P);
|
||||||
|
for (int j = 0; j < (int)TxSize.TxSizes - 3; ++j)
|
||||||
|
{
|
||||||
|
fc.Tx8x8Prob[i][j] = Prob.ModeMvMergeProbs(preFc.Tx8x8Prob[i][j], ref branchCt8x8P[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
EntropyMode.TxCountsToBranchCounts16x16(counts.Tx16x16[i].AsSpan(), ref branchCt16x16P);
|
||||||
|
for (int j = 0; j < (int)TxSize.TxSizes - 2; ++j)
|
||||||
|
{
|
||||||
|
fc.Tx16x16Prob[i][j] =
|
||||||
|
Prob.ModeMvMergeProbs(preFc.Tx16x16Prob[i][j], ref branchCt16x16P[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
EntropyMode.TxCountsToBranchCounts32x32(counts.Tx32x32[i].AsSpan(), ref branchCt32x32P);
|
||||||
|
for (int j = 0; j < (int)TxSize.TxSizes - 1; ++j)
|
||||||
|
{
|
||||||
|
fc.Tx32x32Prob[i][j] =
|
||||||
|
Prob.ModeMvMergeProbs(preFc.Tx32x32Prob[i][j], ref branchCt32x32P[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < Constants.SkipContexts; ++i)
|
||||||
|
{
|
||||||
|
fc.SkipProb[i] = Prob.ModeMvMergeProbs(preFc.SkipProb[i], ref counts.Skip[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AdaptCoefProbs()
|
||||||
|
{
|
||||||
|
byte t;
|
||||||
|
uint countSat, updateFactor;
|
||||||
|
|
||||||
|
if (FrameIsIntraOnly())
|
||||||
|
{
|
||||||
|
updateFactor = Entropy.CoefMaxUpdateFactorKey;
|
||||||
|
countSat = Entropy.CoefCountSatKey;
|
||||||
|
}
|
||||||
|
else if (LastFrameType == FrameType.KeyFrame)
|
||||||
|
{
|
||||||
|
updateFactor = Entropy.CoefMaxUpdateFactorAfterKey; /* adapt quickly */
|
||||||
|
countSat = Entropy.CoefCountSatAfterKey;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
updateFactor = Entropy.CoefMaxUpdateFactor;
|
||||||
|
countSat = Entropy.CoefCountSat;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (t = (int)TxSize.Tx4x4; t <= (int)TxSize.Tx32x32; t++)
|
||||||
|
{
|
||||||
|
AdaptCoefProbs(t, countSat, updateFactor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetMvs(ReadOnlySpan<Vp9MvRef> mvs)
|
||||||
|
{
|
||||||
|
if (mvs.Length > PrevFrameMvs.Length)
|
||||||
|
{
|
||||||
|
throw new ArgumentException(
|
||||||
|
$"Size mismatch, expected: {PrevFrameMvs.Length}, but got: {mvs.Length}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < mvs.Length; i++)
|
||||||
|
{
|
||||||
|
ref MvRef mv = ref 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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetMvs(Span<Vp9MvRef> mvs)
|
||||||
|
{
|
||||||
|
if (mvs.Length > CurFrameMvs.Length)
|
||||||
|
{
|
||||||
|
throw new ArgumentException(
|
||||||
|
$"Size mismatch, expected: {CurFrameMvs.Length}, but got: {mvs.Length}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < mvs.Length; i++)
|
||||||
|
{
|
||||||
|
ref MvRef mv = ref 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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AdaptCoefProbs(byte txSize, uint countSat, uint updateFactor)
|
||||||
|
{
|
||||||
|
ref Vp9EntropyProbs preFc = ref FrameContexts[(int)FrameContextIdx];
|
||||||
|
ref Array2<Array2<Array6<Array6<Array3<byte>>>>> probs = ref Fc.Value.CoefProbs[txSize];
|
||||||
|
ref Array2<Array2<Array6<Array6<Array3<byte>>>>> preProbs = ref preFc.CoefProbs[txSize];
|
||||||
|
ref Array2<Array2<Array6<Array6<Array4<uint>>>>> counts = ref Counts.Value.Coef[txSize];
|
||||||
|
ref Array2<Array2<Array6<Array6<uint>>>> eobCounts = ref Counts.Value.EobBranch[txSize];
|
||||||
|
|
||||||
|
for (int i = 0; i < Constants.PlaneTypes; ++i)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < Entropy.RefTypes; ++j)
|
||||||
|
{
|
||||||
|
for (int k = 0; k < Entropy.CoefBands; ++k)
|
||||||
|
{
|
||||||
|
for (int l = 0; l < Entropy.BAND_COEFF_CONTEXTS(k); ++l)
|
||||||
|
{
|
||||||
|
int n0 = (int)counts[i][j][k][l][Entropy.ZeroToken];
|
||||||
|
int n1 = (int)counts[i][j][k][l][Entropy.OneToken];
|
||||||
|
int n2 = (int)counts[i][j][k][l][Entropy.TwoToken];
|
||||||
|
int neob = (int)counts[i][j][k][l][Entropy.EobModelToken];
|
||||||
|
Array3<Array2<uint>> branchCt = new();
|
||||||
|
branchCt[0][0] = (uint)neob;
|
||||||
|
branchCt[0][1] = (uint)(eobCounts[i][j][k][l] - neob);
|
||||||
|
branchCt[1][0] = (uint)n0;
|
||||||
|
branchCt[1][1] = (uint)(n1 + n2);
|
||||||
|
branchCt[2][0] = (uint)n1;
|
||||||
|
branchCt[2][1] = (uint)n2;
|
||||||
|
for (int m = 0; m < Entropy.UnconstrainedNodes; ++m)
|
||||||
|
{
|
||||||
|
probs[i][j][k][l][m] = Prob.MergeProbs(preProbs[i][j][k][l][m], ref branchCt[m],
|
||||||
|
countSat, updateFactor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DefaultCoefProbs()
|
||||||
|
{
|
||||||
|
Entropy.CopyProbs(ref Fc.Value.CoefProbs[(int)TxSize.Tx4x4], Entropy.DefaultCoefProbs4x4);
|
||||||
|
Entropy.CopyProbs(ref Fc.Value.CoefProbs[(int)TxSize.Tx8x8], Entropy.DefaultCoefProbs8x8);
|
||||||
|
Entropy.CopyProbs(ref Fc.Value.CoefProbs[(int)TxSize.Tx16x16], Entropy.DefaultCoefProbs16x16);
|
||||||
|
Entropy.CopyProbs(ref Fc.Value.CoefProbs[(int)TxSize.Tx32x32], Entropy.DefaultCoefProbs32x32);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
410
src/Ryujinx.Graphics.Nvdec.Vp9/Types/Vp9Decoder.cs
Normal file
410
src/Ryujinx.Graphics.Nvdec.Vp9/Types/Vp9Decoder.cs
Normal file
|
@ -0,0 +1,410 @@
|
||||||
|
using Ryujinx.Common.Memory;
|
||||||
|
using Ryujinx.Graphics.Nvdec.Vp9.Common;
|
||||||
|
using Ryujinx.Graphics.Video;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
|
{
|
||||||
|
internal struct Vp9Decoder
|
||||||
|
{
|
||||||
|
public Vp9Common Common;
|
||||||
|
|
||||||
|
public int ReadyForNewData;
|
||||||
|
|
||||||
|
public int RefreshFrameFlags;
|
||||||
|
|
||||||
|
public int NeedResync; // Wait for key/intra-only frame.
|
||||||
|
public int HoldRefBuf; // Hold the reference buffer.
|
||||||
|
|
||||||
|
private static void DecreaseRefCount(int idx, ref Array12<RefCntBuffer> frameBufs, ref BufferPool pool)
|
||||||
|
{
|
||||||
|
if (idx >= 0 && frameBufs[idx].RefCount > 0)
|
||||||
|
{
|
||||||
|
--frameBufs[idx].RefCount;
|
||||||
|
// A worker may only get a free framebuffer index when calling GetFreeFb.
|
||||||
|
// But the private buffer is not set up until finish decoding header.
|
||||||
|
// So any error happens during decoding header, the frame_bufs will not
|
||||||
|
// have valid priv buffer.
|
||||||
|
if (frameBufs[idx].Released == 0 && frameBufs[idx].RefCount == 0 &&
|
||||||
|
!frameBufs[idx].RawFrameBuffer.Priv.IsNull)
|
||||||
|
{
|
||||||
|
FrameBuffers.ReleaseFrameBuffer(pool.CbPriv, ref frameBufs[idx].RawFrameBuffer);
|
||||||
|
frameBufs[idx].Released = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Create(MemoryAllocator allocator, ref BufferPool pool)
|
||||||
|
{
|
||||||
|
ref Vp9Common cm = ref Common;
|
||||||
|
|
||||||
|
cm.CheckMemError(ref cm.Fc,
|
||||||
|
new Ptr<Vp9EntropyProbs>(ref allocator.Allocate<Vp9EntropyProbs>(1)[0]));
|
||||||
|
cm.CheckMemError(ref cm.FrameContexts,
|
||||||
|
allocator.Allocate<Vp9EntropyProbs>(Constants.FrameContexts));
|
||||||
|
|
||||||
|
for (int i = 0; i < EntropyMode.KfYModeProb.Length; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < EntropyMode.KfYModeProb[i].Length; j++)
|
||||||
|
{
|
||||||
|
for (int k = 0; k < EntropyMode.KfYModeProb[i][j].Length; k++)
|
||||||
|
{
|
||||||
|
cm.Fc.Value.KfYModeProb[i][j][k] = EntropyMode.KfYModeProb[i][j][k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < EntropyMode.KfUvModeProb.Length; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < EntropyMode.KfUvModeProb[i].Length; j++)
|
||||||
|
{
|
||||||
|
cm.Fc.Value.KfUvModeProb[i][j] = EntropyMode.KfUvModeProb[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[][] KfPartitionProbs =
|
||||||
|
{
|
||||||
|
// 8x8 . 4x4
|
||||||
|
new byte[] { 158, 97, 94 }, // a/l both not split
|
||||||
|
new byte[] { 93, 24, 99 }, // a split, l not split
|
||||||
|
new byte[] { 85, 119, 44 }, // l split, a not split
|
||||||
|
new byte[] { 62, 59, 67 }, // a/l both split
|
||||||
|
|
||||||
|
// 16x16 . 8x8
|
||||||
|
new byte[] { 149, 53, 53 }, // a/l both not split
|
||||||
|
new byte[] { 94, 20, 48 }, // a split, l not split
|
||||||
|
new byte[] { 83, 53, 24 }, // l split, a not split
|
||||||
|
new byte[] { 52, 18, 18 }, // a/l both split
|
||||||
|
|
||||||
|
// 32x32 . 16x16
|
||||||
|
new byte[] { 150, 40, 39 }, // a/l both not split
|
||||||
|
new byte[] { 78, 12, 26 }, // a split, l not split
|
||||||
|
new byte[] { 67, 33, 11 }, // l split, a not split
|
||||||
|
new byte[] { 24, 7, 5 }, // a/l both split
|
||||||
|
|
||||||
|
// 64x64 . 32x32
|
||||||
|
new byte[] { 174, 35, 49 }, // a/l both not split
|
||||||
|
new byte[] { 68, 11, 27 }, // a split, l not split
|
||||||
|
new byte[] { 57, 15, 9 }, // l split, a not split
|
||||||
|
new byte[] { 12, 3, 3 } // a/l both split
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 0; i < KfPartitionProbs.Length; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < KfPartitionProbs[i].Length; j++)
|
||||||
|
{
|
||||||
|
cm.Fc.Value.KfPartitionProb[i][j] = KfPartitionProbs[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cm.Counts = new Ptr<Vp9BackwardUpdates>(ref allocator.Allocate<Vp9BackwardUpdates>(1)[0]);
|
||||||
|
|
||||||
|
NeedResync = 1;
|
||||||
|
|
||||||
|
// Initialize the references to not point to any frame buffers.
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
cm.RefFrameMap[i] = -1;
|
||||||
|
cm.NextRefFrameMap[i] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cm.CurrentVideoFrame = 0;
|
||||||
|
ReadyForNewData = 1;
|
||||||
|
Common.BufferPool = new Ptr<BufferPool>(ref pool);
|
||||||
|
|
||||||
|
cm.BitDepth = BitDepth.Bits8;
|
||||||
|
cm.DequantBitDepth = BitDepth.Bits8;
|
||||||
|
|
||||||
|
// vp9_loop_filter_init(ref cm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If any buffer updating is signaled it should be done here. */
|
||||||
|
private void SwapFrameBuffers()
|
||||||
|
{
|
||||||
|
int refIndex = 0, mask;
|
||||||
|
ref Vp9Common cm = ref Common;
|
||||||
|
ref BufferPool pool = ref cm.BufferPool.Value;
|
||||||
|
ref Array12<RefCntBuffer> frameBufs = ref cm.BufferPool.Value.FrameBufs;
|
||||||
|
|
||||||
|
for (mask = RefreshFrameFlags; mask != 0; mask >>= 1)
|
||||||
|
{
|
||||||
|
int oldIdx = cm.RefFrameMap[refIndex];
|
||||||
|
// Current thread releases the holding of reference frame.
|
||||||
|
DecreaseRefCount(oldIdx, ref frameBufs, ref pool);
|
||||||
|
|
||||||
|
// Release the reference frame in reference map.
|
||||||
|
if ((mask & 1) != 0)
|
||||||
|
{
|
||||||
|
DecreaseRefCount(oldIdx, ref frameBufs, ref pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
cm.RefFrameMap[refIndex] = cm.NextRefFrameMap[refIndex];
|
||||||
|
++refIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Current thread releases the holding of reference frame.
|
||||||
|
for (; refIndex < Constants.RefFrames && cm.ShowExistingFrame == 0; ++refIndex)
|
||||||
|
{
|
||||||
|
int oldIdx = cm.RefFrameMap[refIndex];
|
||||||
|
DecreaseRefCount(oldIdx, ref frameBufs, ref pool);
|
||||||
|
cm.RefFrameMap[refIndex] = cm.NextRefFrameMap[refIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
HoldRefBuf = 0;
|
||||||
|
cm.FrameToShow = new Ptr<Surface>(ref cm.GetFrameNewBuffer());
|
||||||
|
|
||||||
|
--frameBufs[cm.NewFbIdx].RefCount;
|
||||||
|
|
||||||
|
// Invalidate these references until the next frame starts.
|
||||||
|
for (refIndex = 0; refIndex < 3; refIndex++)
|
||||||
|
{
|
||||||
|
cm.FrameRefs[refIndex].Idx = RefBuffer.InvalidIdx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public CodecErr ReceiveCompressedData(MemoryAllocator allocator, ulong size, ref ArrayPtr<byte> psource)
|
||||||
|
{
|
||||||
|
ref Vp9Common cm = ref Common;
|
||||||
|
ref BufferPool pool = ref cm.BufferPool.Value;
|
||||||
|
ref Array12<RefCntBuffer> frameBufs = ref cm.BufferPool.Value.FrameBufs;
|
||||||
|
ArrayPtr<byte> source = psource;
|
||||||
|
CodecErr retcode = 0;
|
||||||
|
cm.Error.ErrorCode = CodecErr.Ok;
|
||||||
|
|
||||||
|
if (size == 0)
|
||||||
|
{
|
||||||
|
// This is used to signal that we are missing frames.
|
||||||
|
// We do not know if the missing frame(s) was supposed to update
|
||||||
|
// any of the reference buffers, but we act conservative and
|
||||||
|
// mark only the last buffer as corrupted.
|
||||||
|
|
||||||
|
if (cm.FrameRefs[0].Idx > 0)
|
||||||
|
{
|
||||||
|
cm.FrameRefs[0].Buf.Corrupted = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadyForNewData = 0;
|
||||||
|
|
||||||
|
// Check if the previous frame was a frame without any references to it.
|
||||||
|
if (cm.NewFbIdx >= 0 && frameBufs[cm.NewFbIdx].RefCount == 0 &&
|
||||||
|
frameBufs[cm.NewFbIdx].Released == 0)
|
||||||
|
{
|
||||||
|
FrameBuffers.ReleaseFrameBuffer(pool.CbPriv, ref frameBufs[cm.NewFbIdx].RawFrameBuffer);
|
||||||
|
frameBufs[cm.NewFbIdx].Released = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find a free frame buffer. Return error if can not find any.
|
||||||
|
cm.NewFbIdx = cm.GetFreeFb();
|
||||||
|
if (cm.NewFbIdx == RefBuffer.InvalidIdx)
|
||||||
|
{
|
||||||
|
ReadyForNewData = 1;
|
||||||
|
cm.Error.InternalError(CodecErr.MemError, "Unable to find free frame buffer");
|
||||||
|
|
||||||
|
return cm.Error.ErrorCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assign a MV array to the frame buffer.
|
||||||
|
cm.CurFrame = new Ptr<RefCntBuffer>(ref pool.FrameBufs[cm.NewFbIdx]);
|
||||||
|
|
||||||
|
HoldRefBuf = 0;
|
||||||
|
|
||||||
|
DecodeFrame.Decode(allocator, ref this, new ArrayPtr<byte>(ref source[0], (int)size), out psource);
|
||||||
|
|
||||||
|
SwapFrameBuffers();
|
||||||
|
|
||||||
|
// vpx_clear_system_state();
|
||||||
|
|
||||||
|
if (cm.ShowExistingFrame == 0)
|
||||||
|
{
|
||||||
|
cm.LastShowFrame = cm.ShowFrame;
|
||||||
|
cm.PrevFrame = cm.CurFrame;
|
||||||
|
|
||||||
|
if (cm.PrevFrameMvs.IsNull || cm.PrevFrameMvs.Length != cm.CurFrameMvs.Length)
|
||||||
|
{
|
||||||
|
allocator.Free(cm.PrevFrameMvs);
|
||||||
|
cm.PrevFrameMvs = allocator.Allocate<MvRef>(cm.CurFrameMvs.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
cm.CurFrameMvs.AsSpan().CopyTo(cm.PrevFrameMvs.AsSpan());
|
||||||
|
if (cm.Seg.Enabled)
|
||||||
|
{
|
||||||
|
cm.SwapCurrentAndLastSegMap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cm.ShowFrame != 0)
|
||||||
|
{
|
||||||
|
cm.CurShowFrameFbIdx = cm.NewFbIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update progress in frame parallel decode.
|
||||||
|
cm.LastWidth = cm.Width;
|
||||||
|
cm.LastHeight = cm.Height;
|
||||||
|
if (cm.ShowFrame != 0)
|
||||||
|
{
|
||||||
|
cm.CurrentVideoFrame++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return retcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetRawFrame(ref Surface sd)
|
||||||
|
{
|
||||||
|
ref Vp9Common cm = ref Common;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (ReadyForNewData == 1)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadyForNewData = 1;
|
||||||
|
|
||||||
|
if (cm.ShowFrame == 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadyForNewData = 1;
|
||||||
|
|
||||||
|
sd = cm.FrameToShow.Value;
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CodecErr Decode(MemoryAllocator allocator, ArrayPtr<byte> data)
|
||||||
|
{
|
||||||
|
ArrayPtr<byte> dataStart = data;
|
||||||
|
CodecErr res;
|
||||||
|
Array8<uint> frameSizes = new();
|
||||||
|
int frameCount = 0;
|
||||||
|
|
||||||
|
res = Types.Decoder.ParseSuperframeIndex(data, (ulong)data.Length, ref frameSizes, out frameCount);
|
||||||
|
if (res != CodecErr.Ok)
|
||||||
|
{
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode in serial mode.
|
||||||
|
if (frameCount > 0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < frameCount; ++i)
|
||||||
|
{
|
||||||
|
ArrayPtr<byte> dataStartCopy = dataStart;
|
||||||
|
uint frameSize = frameSizes[i];
|
||||||
|
if (frameSize > (uint)dataStart.Length)
|
||||||
|
{
|
||||||
|
return CodecErr.CorruptFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = ReceiveCompressedData(allocator, frameSize, ref dataStartCopy);
|
||||||
|
if (res != CodecErr.Ok)
|
||||||
|
{
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
dataStart = dataStart.Slice((int)frameSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (dataStart.Length != 0)
|
||||||
|
{
|
||||||
|
uint frameSize = (uint)dataStart.Length;
|
||||||
|
res = ReceiveCompressedData(allocator, frameSize, ref dataStart);
|
||||||
|
if (res != CodecErr.Ok)
|
||||||
|
{
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Account for suboptimal termination by the encoder.
|
||||||
|
while (dataStart.Length != 0)
|
||||||
|
{
|
||||||
|
byte marker = Types.Decoder.ReadMarker(dataStart);
|
||||||
|
if (marker != 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dataStart = dataStart.Slice(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static class Decoder
|
||||||
|
{
|
||||||
|
public static byte ReadMarker(ArrayPtr<byte> data)
|
||||||
|
{
|
||||||
|
return data[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CodecErr ParseSuperframeIndex(ArrayPtr<byte> data, ulong dataSz, ref Array8<uint> sizes, out int count)
|
||||||
|
{
|
||||||
|
// A chunk ending with a byte matching 0xc0 is an invalid chunk unless
|
||||||
|
// it is a super frame index. If the last byte of real video compression
|
||||||
|
// data is 0xc0 the encoder must add a 0 byte. If we have the marker but
|
||||||
|
// not the associated matching marker byte at the front of the index we have
|
||||||
|
// an invalid bitstream and need to return an error.
|
||||||
|
|
||||||
|
byte marker;
|
||||||
|
|
||||||
|
Debug.Assert(dataSz != 0);
|
||||||
|
marker = ReadMarker(data.Slice((int)dataSz - 1));
|
||||||
|
count = 0;
|
||||||
|
|
||||||
|
if ((marker & 0xe0) == 0xc0)
|
||||||
|
{
|
||||||
|
uint frames = (uint)(marker & 0x7) + 1;
|
||||||
|
uint mag = (uint)((marker >> 3) & 0x3) + 1;
|
||||||
|
ulong indexSz = 2 + (mag * frames);
|
||||||
|
|
||||||
|
// This chunk is marked as having a superframe index but doesn't have
|
||||||
|
// enough data for it, thus it's an invalid superframe index.
|
||||||
|
if (dataSz < indexSz)
|
||||||
|
{
|
||||||
|
return CodecErr.CorruptFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
byte marker2 = ReadMarker(data.Slice((int)(dataSz - indexSz)));
|
||||||
|
|
||||||
|
// This chunk is marked as having a superframe index but doesn't have
|
||||||
|
// the matching marker byte at the front of the index therefore it's an
|
||||||
|
// invalid chunk.
|
||||||
|
if (marker != marker2)
|
||||||
|
{
|
||||||
|
return CodecErr.CorruptFrame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Found a valid superframe index.
|
||||||
|
ArrayPtr<byte> x = data.Slice((int)(dataSz - indexSz + 1));
|
||||||
|
|
||||||
|
for (int i = 0; i < frames; ++i)
|
||||||
|
{
|
||||||
|
uint thisSz = 0;
|
||||||
|
|
||||||
|
for (int j = 0; j < mag; ++j)
|
||||||
|
{
|
||||||
|
thisSz |= (uint)x[0] << j * 8;
|
||||||
|
x = x.Slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sizes[i] = thisSz;
|
||||||
|
}
|
||||||
|
|
||||||
|
count = (int)frames;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return CodecErr.Ok;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxCodecFrameBuffer.cs
Normal file
10
src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxCodecFrameBuffer.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
using Ryujinx.Common.Memory;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
|
{
|
||||||
|
internal struct VpxCodecFrameBuffer
|
||||||
|
{
|
||||||
|
public ArrayPtr<byte> Data;
|
||||||
|
public Ptr<InternalFrameBuffer> Priv;
|
||||||
|
}
|
||||||
|
}
|
11
src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxColorRange.cs
Normal file
11
src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxColorRange.cs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
|
{
|
||||||
|
internal enum VpxColorRange
|
||||||
|
{
|
||||||
|
// Y [16..235], UV [16..240]
|
||||||
|
Studio,
|
||||||
|
|
||||||
|
// YUV/RGB [0..255]
|
||||||
|
Full
|
||||||
|
}
|
||||||
|
}
|
29
src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxColorSpace.cs
Normal file
29
src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxColorSpace.cs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
|
{
|
||||||
|
internal enum VpxColorSpace
|
||||||
|
{
|
||||||
|
// Unknown
|
||||||
|
Unknown,
|
||||||
|
|
||||||
|
// BT.601
|
||||||
|
Bt601,
|
||||||
|
|
||||||
|
// BT.709
|
||||||
|
Bt709,
|
||||||
|
|
||||||
|
// SMPTE.170
|
||||||
|
Smpte170,
|
||||||
|
|
||||||
|
// SMPTE.240
|
||||||
|
Smpte240,
|
||||||
|
|
||||||
|
// BT.2020
|
||||||
|
Bt2020,
|
||||||
|
|
||||||
|
// Reserved
|
||||||
|
Reserved,
|
||||||
|
|
||||||
|
// sRGB
|
||||||
|
Srgb
|
||||||
|
}
|
||||||
|
}
|
|
@ -59,6 +59,8 @@ namespace Ryujinx.Graphics.Nvdec.Types.Vp9
|
||||||
Flags.HasFlag(FrameFlags.LastShowFrame) &&
|
Flags.HasFlag(FrameFlags.LastShowFrame) &&
|
||||||
!Flags.HasFlag(FrameFlags.LastFrameIsKeyFrame),
|
!Flags.HasFlag(FrameFlags.LastFrameIsKeyFrame),
|
||||||
RefFrameSignBias = RefFrameSignBias,
|
RefFrameSignBias = RefFrameSignBias,
|
||||||
|
LoopFilterLevel = FirstLevel,
|
||||||
|
LoopFilterSharpnessLevel = SharpnessLevel,
|
||||||
BaseQIndex = BaseQIndex,
|
BaseQIndex = BaseQIndex,
|
||||||
YDcDeltaQ = YDcDeltaQ,
|
YDcDeltaQ = YDcDeltaQ,
|
||||||
UvDcDeltaQ = UvDcDeltaQ,
|
UvDcDeltaQ = UvDcDeltaQ,
|
||||||
|
|
|
@ -10,6 +10,8 @@ namespace Ryujinx.Graphics.Video
|
||||||
public bool IsKeyFrame;
|
public bool IsKeyFrame;
|
||||||
public bool IntraOnly;
|
public bool IntraOnly;
|
||||||
public Array4<sbyte> RefFrameSignBias;
|
public Array4<sbyte> RefFrameSignBias;
|
||||||
|
public int LoopFilterLevel;
|
||||||
|
public int LoopFilterSharpnessLevel;
|
||||||
public int BaseQIndex;
|
public int BaseQIndex;
|
||||||
public int YDcDeltaQ;
|
public int YDcDeltaQ;
|
||||||
public int UvDcDeltaQ;
|
public int UvDcDeltaQ;
|
||||||
|
|
Loading…
Reference in a new issue