PredCommon.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. using Ryujinx.Graphics.Nvdec.Vp9.Types;
  2. using System.Diagnostics;
  3. namespace Ryujinx.Graphics.Nvdec.Vp9
  4. {
  5. internal static class PredCommon
  6. {
  7. public static int GetReferenceModeContext(ref Vp9Common cm, ref MacroBlockD xd)
  8. {
  9. int ctx;
  10. // Note:
  11. // The mode info data structure has a one element border above and to the
  12. // left of the entries corresponding to real macroblocks.
  13. // The prediction flags in these dummy entries are initialized to 0.
  14. if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
  15. { // both edges available
  16. if (!xd.AboveMi.Value.HasSecondRef() && !xd.LeftMi.Value.HasSecondRef())
  17. {
  18. // Neither edge uses comp pred (0/1)
  19. ctx = (xd.AboveMi.Value.RefFrame[0] == cm.CompFixedRef ? 1 : 0) ^
  20. (xd.LeftMi.Value.RefFrame[0] == cm.CompFixedRef ? 1 : 0);
  21. }
  22. else if (!xd.AboveMi.Value.HasSecondRef())
  23. {
  24. // One of two edges uses comp pred (2/3)
  25. ctx = 2 + (xd.AboveMi.Value.RefFrame[0] == cm.CompFixedRef || !xd.AboveMi.Value.IsInterBlock() ? 1 : 0);
  26. }
  27. else if (!xd.LeftMi.Value.HasSecondRef())
  28. {
  29. // One of two edges uses comp pred (2/3)
  30. ctx = 2 + (xd.LeftMi.Value.RefFrame[0] == cm.CompFixedRef || !xd.LeftMi.Value.IsInterBlock() ? 1 : 0);
  31. }
  32. else // Both edges use comp pred (4)
  33. {
  34. ctx = 4;
  35. }
  36. }
  37. else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
  38. { // One edge available
  39. ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
  40. if (!edgeMi.HasSecondRef())
  41. {
  42. // Edge does not use comp pred (0/1)
  43. ctx = edgeMi.RefFrame[0] == cm.CompFixedRef ? 1 : 0;
  44. }
  45. else
  46. {
  47. // Edge uses comp pred (3)
  48. ctx = 3;
  49. }
  50. }
  51. else
  52. { // No edges available (1)
  53. ctx = 1;
  54. }
  55. Debug.Assert(ctx >= 0 && ctx < Constants.CompInterContexts);
  56. return ctx;
  57. }
  58. // Returns a context number for the given MB prediction signal
  59. public static int GetPredContextCompRefP(ref Vp9Common cm, ref MacroBlockD xd)
  60. {
  61. int predContext;
  62. // Note:
  63. // The mode info data structure has a one element border above and to the
  64. // left of the entries corresponding to real macroblocks.
  65. // The prediction flags in these dummy entries are initialized to 0.
  66. int fixRefIdx = cm.RefFrameSignBias[cm.CompFixedRef];
  67. int varRefIdx = fixRefIdx == 0 ? 1 : 0;
  68. if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
  69. { // Both edges available
  70. bool aboveIntra = !xd.AboveMi.Value.IsInterBlock();
  71. bool leftIntra = !xd.LeftMi.Value.IsInterBlock();
  72. if (aboveIntra && leftIntra)
  73. { // Intra/Intra (2)
  74. predContext = 2;
  75. }
  76. else if (aboveIntra || leftIntra)
  77. { // Intra/Inter
  78. ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value;
  79. if (!edgeMi.HasSecondRef()) // single pred (1/3)
  80. {
  81. predContext = 1 + 2 * (edgeMi.RefFrame[0] != cm.CompVarRef[1] ? 1 : 0);
  82. }
  83. else // Comp pred (1/3)
  84. {
  85. predContext = 1 + 2 * (edgeMi.RefFrame[varRefIdx] != cm.CompVarRef[1] ? 1 : 0);
  86. }
  87. }
  88. else
  89. { // Inter/Inter
  90. bool lSg = !xd.LeftMi.Value.HasSecondRef();
  91. bool aSg = !xd.AboveMi.Value.HasSecondRef();
  92. sbyte vrfa = aSg ? xd.AboveMi.Value.RefFrame[0] : xd.AboveMi.Value.RefFrame[varRefIdx];
  93. sbyte vrfl = lSg ? xd.LeftMi.Value.RefFrame[0] : xd.LeftMi.Value.RefFrame[varRefIdx];
  94. if (vrfa == vrfl && cm.CompVarRef[1] == vrfa)
  95. {
  96. predContext = 0;
  97. }
  98. else if (lSg && aSg)
  99. { // Single/Single
  100. if ((vrfa == cm.CompFixedRef && vrfl == cm.CompVarRef[0]) ||
  101. (vrfl == cm.CompFixedRef && vrfa == cm.CompVarRef[0]))
  102. {
  103. predContext = 4;
  104. }
  105. else if (vrfa == vrfl)
  106. {
  107. predContext = 3;
  108. }
  109. else
  110. {
  111. predContext = 1;
  112. }
  113. }
  114. else if (lSg || aSg)
  115. { // Single/Comp
  116. sbyte vrfc = lSg ? vrfa : vrfl;
  117. sbyte rfs = aSg ? vrfa : vrfl;
  118. if (vrfc == cm.CompVarRef[1] && rfs != cm.CompVarRef[1])
  119. {
  120. predContext = 1;
  121. }
  122. else if (rfs == cm.CompVarRef[1] && vrfc != cm.CompVarRef[1])
  123. {
  124. predContext = 2;
  125. }
  126. else
  127. {
  128. predContext = 4;
  129. }
  130. }
  131. else if (vrfa == vrfl)
  132. { // Comp/Comp
  133. predContext = 4;
  134. }
  135. else
  136. {
  137. predContext = 2;
  138. }
  139. }
  140. }
  141. else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
  142. { // One edge available
  143. ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
  144. if (!edgeMi.IsInterBlock())
  145. {
  146. predContext = 2;
  147. }
  148. else
  149. {
  150. if (edgeMi.HasSecondRef())
  151. {
  152. predContext = 4 * (edgeMi.RefFrame[varRefIdx] != cm.CompVarRef[1] ? 1 : 0);
  153. }
  154. else
  155. {
  156. predContext = 3 * (edgeMi.RefFrame[0] != cm.CompVarRef[1] ? 1 : 0);
  157. }
  158. }
  159. }
  160. else
  161. { // No edges available (2)
  162. predContext = 2;
  163. }
  164. Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
  165. return predContext;
  166. }
  167. public static int GetPredContextSingleRefP1(ref MacroBlockD xd)
  168. {
  169. int predContext;
  170. // Note:
  171. // The mode info data structure has a one element border above and to the
  172. // left of the entries corresponding to real macroblocks.
  173. // The prediction flags in these dummy entries are initialized to 0.
  174. if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
  175. { // Both edges available
  176. bool aboveIntra = !xd.AboveMi.Value.IsInterBlock();
  177. bool leftIntra = !xd.LeftMi.Value.IsInterBlock();
  178. if (aboveIntra && leftIntra)
  179. { // Intra/Intra
  180. predContext = 2;
  181. }
  182. else if (aboveIntra || leftIntra)
  183. { // Intra/Inter or Inter/Intra
  184. ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value;
  185. if (!edgeMi.HasSecondRef())
  186. {
  187. predContext = 4 * (edgeMi.RefFrame[0] == Constants.LastFrame ? 1 : 0);
  188. }
  189. else
  190. {
  191. predContext = 1 + (edgeMi.RefFrame[0] == Constants.LastFrame ||
  192. edgeMi.RefFrame[1] == Constants.LastFrame ? 1 : 0);
  193. }
  194. }
  195. else
  196. { // Inter/Inter
  197. bool aboveHasSecond = xd.AboveMi.Value.HasSecondRef();
  198. bool leftHasSecond = xd.LeftMi.Value.HasSecondRef();
  199. sbyte above0 = xd.AboveMi.Value.RefFrame[0];
  200. sbyte above1 = xd.AboveMi.Value.RefFrame[1];
  201. sbyte left0 = xd.LeftMi.Value.RefFrame[0];
  202. sbyte left1 = xd.LeftMi.Value.RefFrame[1];
  203. if (aboveHasSecond && leftHasSecond)
  204. {
  205. predContext = 1 + (above0 == Constants.LastFrame || above1 == Constants.LastFrame ||
  206. left0 == Constants.LastFrame || left1 == Constants.LastFrame ? 1 : 0);
  207. }
  208. else if (aboveHasSecond || leftHasSecond)
  209. {
  210. sbyte rfs = !aboveHasSecond ? above0 : left0;
  211. sbyte crf1 = aboveHasSecond ? above0 : left0;
  212. sbyte crf2 = aboveHasSecond ? above1 : left1;
  213. if (rfs == Constants.LastFrame)
  214. {
  215. predContext = 3 + (crf1 == Constants.LastFrame || crf2 == Constants.LastFrame ? 1 : 0);
  216. }
  217. else
  218. {
  219. predContext = (crf1 == Constants.LastFrame || crf2 == Constants.LastFrame ? 1 : 0);
  220. }
  221. }
  222. else
  223. {
  224. predContext = 2 * (above0 == Constants.LastFrame ? 1 : 0) + 2 * (left0 == Constants.LastFrame ? 1 : 0);
  225. }
  226. }
  227. }
  228. else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
  229. { // One edge available
  230. ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
  231. if (!edgeMi.IsInterBlock())
  232. { // Intra
  233. predContext = 2;
  234. }
  235. else
  236. { // Inter
  237. if (!edgeMi.HasSecondRef())
  238. {
  239. predContext = 4 * (edgeMi.RefFrame[0] == Constants.LastFrame ? 1 : 0);
  240. }
  241. else
  242. {
  243. predContext = 1 + (edgeMi.RefFrame[0] == Constants.LastFrame ||
  244. edgeMi.RefFrame[1] == Constants.LastFrame ? 1 : 0);
  245. }
  246. }
  247. }
  248. else
  249. { // No edges available
  250. predContext = 2;
  251. }
  252. Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
  253. return predContext;
  254. }
  255. public static int GetPredContextSingleRefP2(ref MacroBlockD xd)
  256. {
  257. int predContext;
  258. // Note:
  259. // The mode info data structure has a one element border above and to the
  260. // left of the entries corresponding to real macroblocks.
  261. // The prediction flags in these dummy entries are initialized to 0.
  262. if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
  263. { // Both edges available
  264. bool aboveIntra = !xd.AboveMi.Value.IsInterBlock();
  265. bool leftIntra = !xd.LeftMi.Value.IsInterBlock();
  266. if (aboveIntra && leftIntra)
  267. { // Intra/Intra
  268. predContext = 2;
  269. }
  270. else if (aboveIntra || leftIntra)
  271. { // Intra/Inter or Inter/Intra
  272. ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value;
  273. if (!edgeMi.HasSecondRef())
  274. {
  275. if (edgeMi.RefFrame[0] == Constants.LastFrame)
  276. {
  277. predContext = 3;
  278. }
  279. else
  280. {
  281. predContext = 4 * (edgeMi.RefFrame[0] == Constants.GoldenFrame ? 1 : 0);
  282. }
  283. }
  284. else
  285. {
  286. predContext = 1 + 2 * (edgeMi.RefFrame[0] == Constants.GoldenFrame ||
  287. edgeMi.RefFrame[1] == Constants.GoldenFrame ? 1 : 0);
  288. }
  289. }
  290. else
  291. { // Inter/Inter
  292. bool aboveHasSecond = xd.AboveMi.Value.HasSecondRef();
  293. bool leftHasSecond = xd.LeftMi.Value.HasSecondRef();
  294. sbyte above0 = xd.AboveMi.Value.RefFrame[0];
  295. sbyte above1 = xd.AboveMi.Value.RefFrame[1];
  296. sbyte left0 = xd.LeftMi.Value.RefFrame[0];
  297. sbyte left1 = xd.LeftMi.Value.RefFrame[1];
  298. if (aboveHasSecond && leftHasSecond)
  299. {
  300. if (above0 == left0 && above1 == left1)
  301. {
  302. predContext = 3 * (above0 == Constants.GoldenFrame || above1 == Constants.GoldenFrame ||
  303. left0 == Constants.GoldenFrame || left1 == Constants.GoldenFrame ? 1 : 0);
  304. }
  305. else
  306. {
  307. predContext = 2;
  308. }
  309. }
  310. else if (aboveHasSecond || leftHasSecond)
  311. {
  312. sbyte rfs = !aboveHasSecond ? above0 : left0;
  313. sbyte crf1 = aboveHasSecond ? above0 : left0;
  314. sbyte crf2 = aboveHasSecond ? above1 : left1;
  315. if (rfs == Constants.GoldenFrame)
  316. {
  317. predContext = 3 + (crf1 == Constants.GoldenFrame || crf2 == Constants.GoldenFrame ? 1 : 0);
  318. }
  319. else if (rfs == Constants.AltRefFrame)
  320. {
  321. predContext = crf1 == Constants.GoldenFrame || crf2 == Constants.GoldenFrame ? 1 : 0;
  322. }
  323. else
  324. {
  325. predContext = 1 + 2 * (crf1 == Constants.GoldenFrame || crf2 == Constants.GoldenFrame ? 1 : 0);
  326. }
  327. }
  328. else
  329. {
  330. if (above0 == Constants.LastFrame && left0 == Constants.LastFrame)
  331. {
  332. predContext = 3;
  333. }
  334. else if (above0 == Constants.LastFrame || left0 == Constants.LastFrame)
  335. {
  336. sbyte edge0 = (above0 == Constants.LastFrame) ? left0 : above0;
  337. predContext = 4 * (edge0 == Constants.GoldenFrame ? 1 : 0);
  338. }
  339. else
  340. {
  341. predContext = 2 * (above0 == Constants.GoldenFrame ? 1 : 0) + 2 * (left0 == Constants.GoldenFrame ? 1 : 0);
  342. }
  343. }
  344. }
  345. }
  346. else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
  347. { // One edge available
  348. ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
  349. if (!edgeMi.IsInterBlock() || (edgeMi.RefFrame[0] == Constants.LastFrame && !edgeMi.HasSecondRef()))
  350. {
  351. predContext = 2;
  352. }
  353. else if (!edgeMi.HasSecondRef())
  354. {
  355. predContext = 4 * (edgeMi.RefFrame[0] == Constants.GoldenFrame ? 1 : 0);
  356. }
  357. else
  358. {
  359. predContext = 3 * (edgeMi.RefFrame[0] == Constants.GoldenFrame ||
  360. edgeMi.RefFrame[1] == Constants.GoldenFrame ? 1 : 0);
  361. }
  362. }
  363. else
  364. { // No edges available (2)
  365. predContext = 2;
  366. }
  367. Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
  368. return predContext;
  369. }
  370. }
  371. }