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  }