Prob.cs
 1  using Ryujinx.Graphics.Nvdec.Vp9.Common;
 2  using System;
 3  using System.Diagnostics;
 4  
 5  namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
 6  {
 7      internal static class Prob
 8      {
 9          public const int MaxProb = 255;
10  
11          private static byte GetProb(uint num, uint den)
12          {
13              Debug.Assert(den != 0);
14              {
15                  int p = (int)(((ulong)num * 256 + (den >> 1)) / den);
16                  // (p > 255) ? 255 : (p < 1) ? 1 : p;
17                  int clippedProb = p | ((255 - p) >> 23) | (p == 0 ? 1 : 0);
18  
19                  return (byte)clippedProb;
20              }
21          }
22  
23          /* This function assumes prob1 and prob2 are already within [1,255] range. */
24          public static byte WeightedProb(int prob1, int prob2, int factor)
25          {
26              return (byte)BitUtils.RoundPowerOfTwo(prob1 * (256 - factor) + prob2 * factor, 8);
27          }
28  
29          // MODE_MV_MAX_UPDATE_FACTOR (128) * count / MODE_MV_COUNT_SAT;
30          private static readonly uint[] _countToUpdateFactor = {
31              0,  6,  12, 19, 25, 32,  38,  44,  51,  57, 64,
32              70, 76, 83, 89, 96, 102, 108, 115, 121, 128,
33          };
34  
35          private const int ModeMvCountSat = 20;
36  
37          public static byte ModeMvMergeProbs(byte preProb, uint ct0, uint ct1)
38          {
39              uint den = ct0 + ct1;
40              if (den == 0)
41              {
42                  return preProb;
43              }
44              else
45              {
46                  uint count = Math.Min(den, ModeMvCountSat);
47                  uint factor = _countToUpdateFactor[(int)count];
48                  byte prob = GetProb(ct0, den);
49  
50                  return WeightedProb(preProb, prob, (int)factor);
51              }
52          }
53  
54          private static uint TreeMergeProbsImpl(
55              uint i,
56              sbyte[] tree,
57              ReadOnlySpan<byte> preProbs,
58              ReadOnlySpan<uint> counts,
59              Span<byte> probs)
60          {
61              int l = tree[i];
62              uint leftCount = (l <= 0) ? counts[-l] : TreeMergeProbsImpl((uint)l, tree, preProbs, counts, probs);
63              int r = tree[i + 1];
64              uint rightCount = (r <= 0) ? counts[-r] : TreeMergeProbsImpl((uint)r, tree, preProbs, counts, probs);
65              probs[(int)(i >> 1)] = ModeMvMergeProbs(preProbs[(int)(i >> 1)], leftCount, rightCount);
66  
67              return leftCount + rightCount;
68          }
69  
70          public static void TreeMergeProbs(sbyte[] tree, ReadOnlySpan<byte> preProbs, ReadOnlySpan<uint> counts, Span<byte> probs)
71          {
72              TreeMergeProbsImpl(0, tree, preProbs, counts, probs);
73          }
74      }
75  }