Mv.cs
1 using Ryujinx.Common.Memory; 2 using Ryujinx.Graphics.Video; 3 using System; 4 using System.Diagnostics; 5 6 namespace Ryujinx.Graphics.Nvdec.Vp9.Types 7 { 8 internal struct Mv 9 { 10 public short Row; 11 public short Col; 12 13 private static ReadOnlySpan<byte> LogInBase2 => new byte[] 14 { 15 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, 16 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, 17 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, 18 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, 19 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, 20 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 21 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 22 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 23 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 24 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, 25 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 26 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 27 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 28 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 29 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 30 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 31 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 32 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 33 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 34 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, 35 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 36 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 37 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 38 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 39 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 40 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 41 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 42 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 43 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 44 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 45 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 46 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 47 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 48 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 49 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 50 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 51 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 52 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 53 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 54 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 55 }; 56 57 public readonly bool UseMvHp() 58 { 59 const int KMvRefThresh = 64; // Threshold for use of high-precision 1/8 mv 60 return Math.Abs(Row) < KMvRefThresh && Math.Abs(Col) < KMvRefThresh; 61 } 62 63 public static bool MvJointVertical(MvJointType type) 64 { 65 return type == MvJointType.MvJointHzvnz || type == MvJointType.MvJointHnzvnz; 66 } 67 68 public static bool MvJointHorizontal(MvJointType type) 69 { 70 return type == MvJointType.MvJointHnzvz || type == MvJointType.MvJointHnzvnz; 71 } 72 73 private static int MvClassBase(MvClassType c) 74 { 75 return c != 0 ? Constants.Class0Size << ((int)c + 2) : 0; 76 } 77 78 private static MvClassType GetMvClass(int z, Ptr<int> offset) 79 { 80 MvClassType c = (z >= Constants.Class0Size * 4096) ? MvClassType.MvClass10 : (MvClassType)LogInBase2[z >> 3]; 81 if (!offset.IsNull) 82 { 83 offset.Value = z - MvClassBase(c); 84 } 85 86 return c; 87 } 88 89 private static void IncMvComponent(int v, ref Vp9BackwardUpdates counts, int comp, int incr, int usehp) 90 { 91 int s, z, c, o = 0, d, e, f; 92 Debug.Assert(v != 0); /* Should not be zero */ 93 s = v < 0 ? 1 : 0; 94 counts.Sign[comp][s] += (uint)incr; 95 z = (s != 0 ? -v : v) - 1; /* Magnitude - 1 */ 96 97 c = (int)GetMvClass(z, new Ptr<int>(ref o)); 98 counts.Classes[comp][c] += (uint)incr; 99 100 d = (o >> 3); /* Int mv data */ 101 f = (o >> 1) & 3; /* Fractional pel mv data */ 102 e = (o & 1); /* High precision mv data */ 103 104 if (c == (int)MvClassType.MvClass0) 105 { 106 counts.Class0[comp][d] += (uint)incr; 107 counts.Class0Fp[comp][d][f] += (uint)incr; 108 counts.Class0Hp[comp][e] += (uint)(usehp * incr); 109 } 110 else 111 { 112 int i; 113 int b = c + Constants.Class0Bits - 1; // Number of bits 114 for (i = 0; i < b; ++i) 115 { 116 counts.Bits[comp][i][((d >> i) & 1)] += (uint)incr; 117 } 118 119 counts.Fp[comp][f] += (uint)incr; 120 counts.Hp[comp][e] += (uint)(usehp * incr); 121 } 122 } 123 124 private readonly MvJointType GetMvJoint() 125 { 126 if (Row == 0) 127 { 128 return Col == 0 ? MvJointType.MvJointZero : MvJointType.MvJointHnzvz; 129 } 130 131 return Col == 0 ? MvJointType.MvJointHzvnz : MvJointType.MvJointHnzvnz; 132 } 133 134 internal readonly void IncMv(Ptr<Vp9BackwardUpdates> counts) 135 { 136 if (!counts.IsNull) 137 { 138 MvJointType j = GetMvJoint(); 139 ++counts.Value.Joints[(int)j]; 140 141 if (MvJointVertical(j)) 142 { 143 IncMvComponent(Row, ref counts.Value, 0, 1, 1); 144 } 145 146 if (MvJointHorizontal(j)) 147 { 148 IncMvComponent(Col, ref counts.Value, 1, 1, 1); 149 } 150 } 151 } 152 153 public void ClampMv(int minCol, int maxCol, int minRow, int maxRow) 154 { 155 Col = (short)Math.Clamp(Col, minCol, maxCol); 156 Row = (short)Math.Clamp(Row, minRow, maxRow); 157 } 158 159 private const int MvBorder = (16 << 3); // Allow 16 pels in 1/8th pel units 160 161 public void ClampMvRef(ref MacroBlockD xd) 162 { 163 ClampMv( 164 xd.MbToLeftEdge - MvBorder, 165 xd.MbToRightEdge + MvBorder, 166 xd.MbToTopEdge - MvBorder, 167 xd.MbToBottomEdge + MvBorder); 168 } 169 170 public void LowerMvPrecision(bool allowHP) 171 { 172 bool useHP = allowHP && UseMvHp(); 173 if (!useHP) 174 { 175 if ((Row & 1) != 0) 176 { 177 Row += (short)(Row > 0 ? -1 : 1); 178 } 179 180 if ((Col & 1) != 0) 181 { 182 Col += (short)(Col > 0 ? -1 : 1); 183 } 184 } 185 } 186 } 187 }