Prob.cs 2.5 KB

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