| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389 |
- using Ryujinx.Graphics.Nvdec.Vp9.Types;
- using System.Diagnostics;
- namespace Ryujinx.Graphics.Nvdec.Vp9
- {
- internal static class PredCommon
- {
- public static int GetReferenceModeContext(ref Vp9Common cm, ref MacroBlockD xd)
- {
- int ctx;
- // Note:
- // The mode info data structure has a one element border above and to the
- // left of the entries corresponding to real macroblocks.
- // The prediction flags in these dummy entries are initialized to 0.
- if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
- { // both edges available
- if (!xd.AboveMi.Value.HasSecondRef() && !xd.LeftMi.Value.HasSecondRef())
- {
- // Neither edge uses comp pred (0/1)
- ctx = (xd.AboveMi.Value.RefFrame[0] == cm.CompFixedRef ? 1 : 0) ^
- (xd.LeftMi.Value.RefFrame[0] == cm.CompFixedRef ? 1 : 0);
- }
- else if (!xd.AboveMi.Value.HasSecondRef())
- {
- // One of two edges uses comp pred (2/3)
- ctx = 2 + (xd.AboveMi.Value.RefFrame[0] == cm.CompFixedRef || !xd.AboveMi.Value.IsInterBlock() ? 1 : 0);
- }
- else if (!xd.LeftMi.Value.HasSecondRef())
- {
- // One of two edges uses comp pred (2/3)
- ctx = 2 + (xd.LeftMi.Value.RefFrame[0] == cm.CompFixedRef || !xd.LeftMi.Value.IsInterBlock() ? 1 : 0);
- }
- else // Both edges use comp pred (4)
- {
- ctx = 4;
- }
- }
- else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
- { // One edge available
- ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
- if (!edgeMi.HasSecondRef())
- {
- // Edge does not use comp pred (0/1)
- ctx = edgeMi.RefFrame[0] == cm.CompFixedRef ? 1 : 0;
- }
- else
- {
- // Edge uses comp pred (3)
- ctx = 3;
- }
- }
- else
- { // No edges available (1)
- ctx = 1;
- }
- Debug.Assert(ctx >= 0 && ctx < Constants.CompInterContexts);
- return ctx;
- }
- // Returns a context number for the given MB prediction signal
- public static int GetPredContextCompRefP(ref Vp9Common cm, ref MacroBlockD xd)
- {
- int predContext;
- // Note:
- // The mode info data structure has a one element border above and to the
- // left of the entries corresponding to real macroblocks.
- // The prediction flags in these dummy entries are initialized to 0.
- int fixRefIdx = cm.RefFrameSignBias[cm.CompFixedRef];
- int varRefIdx = fixRefIdx == 0 ? 1 : 0;
- if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
- { // Both edges available
- bool aboveIntra = !xd.AboveMi.Value.IsInterBlock();
- bool leftIntra = !xd.LeftMi.Value.IsInterBlock();
- if (aboveIntra && leftIntra)
- { // Intra/Intra (2)
- predContext = 2;
- }
- else if (aboveIntra || leftIntra)
- { // Intra/Inter
- ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value;
- if (!edgeMi.HasSecondRef()) // single pred (1/3)
- {
- predContext = 1 + 2 * (edgeMi.RefFrame[0] != cm.CompVarRef[1] ? 1 : 0);
- }
- else // Comp pred (1/3)
- {
- predContext = 1 + 2 * (edgeMi.RefFrame[varRefIdx] != cm.CompVarRef[1] ? 1 : 0);
- }
- }
- else
- { // Inter/Inter
- bool lSg = !xd.LeftMi.Value.HasSecondRef();
- bool aSg = !xd.AboveMi.Value.HasSecondRef();
- sbyte vrfa = aSg ? xd.AboveMi.Value.RefFrame[0] : xd.AboveMi.Value.RefFrame[varRefIdx];
- sbyte vrfl = lSg ? xd.LeftMi.Value.RefFrame[0] : xd.LeftMi.Value.RefFrame[varRefIdx];
- if (vrfa == vrfl && cm.CompVarRef[1] == vrfa)
- {
- predContext = 0;
- }
- else if (lSg && aSg)
- { // Single/Single
- if ((vrfa == cm.CompFixedRef && vrfl == cm.CompVarRef[0]) ||
- (vrfl == cm.CompFixedRef && vrfa == cm.CompVarRef[0]))
- {
- predContext = 4;
- }
- else if (vrfa == vrfl)
- {
- predContext = 3;
- }
- else
- {
- predContext = 1;
- }
- }
- else if (lSg || aSg)
- { // Single/Comp
- sbyte vrfc = lSg ? vrfa : vrfl;
- sbyte rfs = aSg ? vrfa : vrfl;
- if (vrfc == cm.CompVarRef[1] && rfs != cm.CompVarRef[1])
- {
- predContext = 1;
- }
- else if (rfs == cm.CompVarRef[1] && vrfc != cm.CompVarRef[1])
- {
- predContext = 2;
- }
- else
- {
- predContext = 4;
- }
- }
- else if (vrfa == vrfl)
- { // Comp/Comp
- predContext = 4;
- }
- else
- {
- predContext = 2;
- }
- }
- }
- else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
- { // One edge available
- ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
- if (!edgeMi.IsInterBlock())
- {
- predContext = 2;
- }
- else
- {
- if (edgeMi.HasSecondRef())
- {
- predContext = 4 * (edgeMi.RefFrame[varRefIdx] != cm.CompVarRef[1] ? 1 : 0);
- }
- else
- {
- predContext = 3 * (edgeMi.RefFrame[0] != cm.CompVarRef[1] ? 1 : 0);
- }
- }
- }
- else
- { // No edges available (2)
- predContext = 2;
- }
- Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
- return predContext;
- }
- public static int GetPredContextSingleRefP1(ref MacroBlockD xd)
- {
- int predContext;
- // Note:
- // The mode info data structure has a one element border above and to the
- // left of the entries corresponding to real macroblocks.
- // The prediction flags in these dummy entries are initialized to 0.
- if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
- { // Both edges available
- bool aboveIntra = !xd.AboveMi.Value.IsInterBlock();
- bool leftIntra = !xd.LeftMi.Value.IsInterBlock();
- if (aboveIntra && leftIntra)
- { // Intra/Intra
- predContext = 2;
- }
- else if (aboveIntra || leftIntra)
- { // Intra/Inter or Inter/Intra
- ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value;
- if (!edgeMi.HasSecondRef())
- {
- predContext = 4 * (edgeMi.RefFrame[0] == Constants.LastFrame ? 1 : 0);
- }
- else
- {
- predContext = 1 + (edgeMi.RefFrame[0] == Constants.LastFrame ||
- edgeMi.RefFrame[1] == Constants.LastFrame ? 1 : 0);
- }
- }
- else
- { // Inter/Inter
- bool aboveHasSecond = xd.AboveMi.Value.HasSecondRef();
- bool leftHasSecond = xd.LeftMi.Value.HasSecondRef();
- sbyte above0 = xd.AboveMi.Value.RefFrame[0];
- sbyte above1 = xd.AboveMi.Value.RefFrame[1];
- sbyte left0 = xd.LeftMi.Value.RefFrame[0];
- sbyte left1 = xd.LeftMi.Value.RefFrame[1];
- if (aboveHasSecond && leftHasSecond)
- {
- predContext = 1 + (above0 == Constants.LastFrame || above1 == Constants.LastFrame ||
- left0 == Constants.LastFrame || left1 == Constants.LastFrame ? 1 : 0);
- }
- else if (aboveHasSecond || leftHasSecond)
- {
- sbyte rfs = !aboveHasSecond ? above0 : left0;
- sbyte crf1 = aboveHasSecond ? above0 : left0;
- sbyte crf2 = aboveHasSecond ? above1 : left1;
- if (rfs == Constants.LastFrame)
- {
- predContext = 3 + (crf1 == Constants.LastFrame || crf2 == Constants.LastFrame ? 1 : 0);
- }
- else
- {
- predContext = (crf1 == Constants.LastFrame || crf2 == Constants.LastFrame ? 1 : 0);
- }
- }
- else
- {
- predContext = 2 * (above0 == Constants.LastFrame ? 1 : 0) + 2 * (left0 == Constants.LastFrame ? 1 : 0);
- }
- }
- }
- else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
- { // One edge available
- ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
- if (!edgeMi.IsInterBlock())
- { // Intra
- predContext = 2;
- }
- else
- { // Inter
- if (!edgeMi.HasSecondRef())
- {
- predContext = 4 * (edgeMi.RefFrame[0] == Constants.LastFrame ? 1 : 0);
- }
- else
- {
- predContext = 1 + (edgeMi.RefFrame[0] == Constants.LastFrame ||
- edgeMi.RefFrame[1] == Constants.LastFrame ? 1 : 0);
- }
- }
- }
- else
- { // No edges available
- predContext = 2;
- }
- Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
- return predContext;
- }
- public static int GetPredContextSingleRefP2(ref MacroBlockD xd)
- {
- int predContext;
- // Note:
- // The mode info data structure has a one element border above and to the
- // left of the entries corresponding to real macroblocks.
- // The prediction flags in these dummy entries are initialized to 0.
- if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
- { // Both edges available
- bool aboveIntra = !xd.AboveMi.Value.IsInterBlock();
- bool leftIntra = !xd.LeftMi.Value.IsInterBlock();
- if (aboveIntra && leftIntra)
- { // Intra/Intra
- predContext = 2;
- }
- else if (aboveIntra || leftIntra)
- { // Intra/Inter or Inter/Intra
- ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value;
- if (!edgeMi.HasSecondRef())
- {
- if (edgeMi.RefFrame[0] == Constants.LastFrame)
- {
- predContext = 3;
- }
- else
- {
- predContext = 4 * (edgeMi.RefFrame[0] == Constants.GoldenFrame ? 1 : 0);
- }
- }
- else
- {
- predContext = 1 + 2 * (edgeMi.RefFrame[0] == Constants.GoldenFrame ||
- edgeMi.RefFrame[1] == Constants.GoldenFrame ? 1 : 0);
- }
- }
- else
- { // Inter/Inter
- bool aboveHasSecond = xd.AboveMi.Value.HasSecondRef();
- bool leftHasSecond = xd.LeftMi.Value.HasSecondRef();
- sbyte above0 = xd.AboveMi.Value.RefFrame[0];
- sbyte above1 = xd.AboveMi.Value.RefFrame[1];
- sbyte left0 = xd.LeftMi.Value.RefFrame[0];
- sbyte left1 = xd.LeftMi.Value.RefFrame[1];
- if (aboveHasSecond && leftHasSecond)
- {
- if (above0 == left0 && above1 == left1)
- {
- predContext = 3 * (above0 == Constants.GoldenFrame || above1 == Constants.GoldenFrame ||
- left0 == Constants.GoldenFrame || left1 == Constants.GoldenFrame ? 1 : 0);
- }
- else
- {
- predContext = 2;
- }
- }
- else if (aboveHasSecond || leftHasSecond)
- {
- sbyte rfs = !aboveHasSecond ? above0 : left0;
- sbyte crf1 = aboveHasSecond ? above0 : left0;
- sbyte crf2 = aboveHasSecond ? above1 : left1;
- if (rfs == Constants.GoldenFrame)
- {
- predContext = 3 + (crf1 == Constants.GoldenFrame || crf2 == Constants.GoldenFrame ? 1 : 0);
- }
- else if (rfs == Constants.AltRefFrame)
- {
- predContext = crf1 == Constants.GoldenFrame || crf2 == Constants.GoldenFrame ? 1 : 0;
- }
- else
- {
- predContext = 1 + 2 * (crf1 == Constants.GoldenFrame || crf2 == Constants.GoldenFrame ? 1 : 0);
- }
- }
- else
- {
- if (above0 == Constants.LastFrame && left0 == Constants.LastFrame)
- {
- predContext = 3;
- }
- else if (above0 == Constants.LastFrame || left0 == Constants.LastFrame)
- {
- sbyte edge0 = (above0 == Constants.LastFrame) ? left0 : above0;
- predContext = 4 * (edge0 == Constants.GoldenFrame ? 1 : 0);
- }
- else
- {
- predContext = 2 * (above0 == Constants.GoldenFrame ? 1 : 0) + 2 * (left0 == Constants.GoldenFrame ? 1 : 0);
- }
- }
- }
- }
- else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
- { // One edge available
- ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
- if (!edgeMi.IsInterBlock() || (edgeMi.RefFrame[0] == Constants.LastFrame && !edgeMi.HasSecondRef()))
- {
- predContext = 2;
- }
- else if (!edgeMi.HasSecondRef())
- {
- predContext = 4 * (edgeMi.RefFrame[0] == Constants.GoldenFrame ? 1 : 0);
- }
- else
- {
- predContext = 3 * (edgeMi.RefFrame[0] == Constants.GoldenFrame ||
- edgeMi.RefFrame[1] == Constants.GoldenFrame ? 1 : 0);
- }
- }
- else
- { // No edges available (2)
- predContext = 2;
- }
- Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
- return predContext;
- }
- }
- }
|