Browse Source

Move coefficients reading into Av1SymbolEncoder class

pull/2633/head
Ynse Hoornenborg 2 years ago
parent
commit
0dacc04985
  1. 328
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1SymbolDecoder.cs
  2. 298
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileReader.cs

328
src/ImageSharp/Formats/Heif/Av1/Tiling/Av1SymbolDecoder.cs

@ -197,48 +197,346 @@ internal ref struct Av1SymbolDecoder
return r.ReadSymbol(this.endOfBlockExtra[(int)transformSizeContext][(int)planeType][endOfBlockContext]) > 0; return r.ReadSymbol(this.endOfBlockExtra[(int)transformSizeContext][(int)planeType][endOfBlockContext]) > 0;
} }
public int ReadCoefficientsBaseRange(Av1TransformSize transformSizeContext, Av1PlaneType planeType, int baseRangeContext) public int ReadChromFromLumaSign()
{
ref Av1SymbolReader r = ref this.reader;
return r.ReadSymbol(this.chromeForLumaSign);
}
public int ReadChromaFromLumaAlphaU(int jointSignPlus1)
{
ref Av1SymbolReader r = ref this.reader;
int context = jointSignPlus1 - 3;
return r.ReadSymbol(this.chromeForLumaAlpha[context]);
}
public int ReadChromaFromLumaAlphaV(int jointSignPlus1)
{
ref Av1SymbolReader r = ref this.reader;
int context = AlphaVContexts[jointSignPlus1];
return r.ReadSymbol(this.chromeForLumaAlpha[context]);
}
public void ReadCoefficientsEndOfBlock(Av1TransformClass transformClass, int endOfBlock, int height, Span<short> scan, int bwl, Span<int> levels, Av1TransformSize transformSizeContext, Av1PlaneType planeType)
{
int i = endOfBlock - 1;
int pos = scan[i];
int coefficientContext = GetLowerLevelContextEndOfBlock(bwl, height, i);
int level = this.ReadBaseEndOfBlock(transformSizeContext, planeType, coefficientContext);
if (level > Av1Constants.BaseLevelsCount)
{
int baseRangeContext = GetBaseRangeContextEndOfBlock(pos, bwl, transformClass);
for (int idx = 0; idx < Av1Constants.CoefficientBaseRange / Av1Constants.BaseRangeSizeMinus1; idx++)
{
int coefficinetBaseRange = this.ReadCoefficientsBaseRange(transformSizeContext, planeType, baseRangeContext);
level += coefficinetBaseRange;
if (coefficinetBaseRange < Av1Constants.BaseRangeSizeMinus1)
{
break;
}
}
}
levels[GetPaddedIndex(pos, bwl)] = level;
}
public void ReadCoefficientsReverse2d(Av1TransformSize transformSize, int startSi, int endSi, Span<short> scan, int bwl, Span<int> levels, Av1TransformSize transformSizeContext, Av1PlaneType planeType)
{
for (int c = endSi; c >= startSi; --c)
{
int pos = scan[c];
int coefficientContext = GetLowerLevelsContext2d(levels, pos, bwl, transformSize);
int level = this.ReadCoefficientsBase(coefficientContext, transformSizeContext, planeType);
if (level > Av1Constants.BaseLevelsCount)
{
int baseRangeContext = GetBaseRangeContext2d(levels, pos, bwl);
for (int idx = 0; idx < Av1Constants.CoefficientBaseRange; idx += Av1Constants.BaseRangeSizeMinus1)
{
int k = this.ReadCoefficientsBaseRange(transformSizeContext, planeType, baseRangeContext);
level += k;
if (k < Av1Constants.BaseRangeSizeMinus1)
{
break;
}
}
}
levels[GetPaddedIndex(pos, bwl)] = level;
}
}
public void ReadCoefficientsReverse(Av1TransformSize transformSize, Av1TransformClass transformClass, int startSi, int endSi, Span<short> scan, int bwl, Span<int> levels, Av1TransformSize transformSizeContext, Av1PlaneType planeType)
{
for (int c = endSi; c >= startSi; --c)
{
int pos = scan[c];
int coefficientContext = GetLowerLevelsContext(levels, pos, bwl, transformSize, transformClass);
int level = this.ReadCoefficientsBase(coefficientContext, transformSizeContext, planeType);
if (level > Av1Constants.BaseLevelsCount)
{
int baseRangeContext = GetBaseRangeContext(levels, pos, bwl, transformClass);
for (int idx = 0; idx < Av1Constants.CoefficientBaseRange; idx += Av1Constants.BaseRangeSizeMinus1)
{
int k = this.ReadCoefficientsBaseRange(transformSizeContext, planeType, baseRangeContext);
level += k;
if (k < Av1Constants.BaseRangeSizeMinus1)
{
break;
}
}
}
levels[GetPaddedIndex(pos, bwl)] = level;
}
}
public int ReadCoefficientsDc(Span<int> coefficientBuffer, int endOfBlock, Span<short> scan, int bwl, Span<int> levels, int dcSignContext, Av1PlaneType planeType)
{
int maxScanLine = 0;
int culLevel = 0;
int dcValue = 0;
coefficientBuffer[0] = endOfBlock;
for (int c = 0; c < endOfBlock; c++)
{
int sign = 0;
int level = levels[GetPaddedIndex(scan[c], bwl)];
if (level != 0)
{
maxScanLine = Math.Max(maxScanLine, scan[c]);
if (c == 0)
{
sign = this.ReadDcSign(planeType, dcSignContext);
}
else
{
sign = this.ReadLiteral(1);
}
if (level >= Av1Constants.CoefficientBaseRange + Av1Constants.BaseLevelsCount + 1)
{
level += this.ReadGolomb();
}
if (c == 0)
{
dcValue = sign != 0 ? -level : level;
}
level &= 0xfffff;
culLevel += level;
}
coefficientBuffer[c + 1] = sign != 0 ? -level : level;
}
culLevel = Math.Min(Av1Constants.CoefficientContextMask, culLevel);
SetDcSign(ref culLevel, dcValue);
return culLevel;
}
private int ReadCoefficientsBaseRange(Av1TransformSize transformSizeContext, Av1PlaneType planeType, int baseRangeContext)
{ {
ref Av1SymbolReader r = ref this.reader; ref Av1SymbolReader r = ref this.reader;
return r.ReadSymbol(this.coefficientsBaseRange[(int)transformSizeContext][(int)planeType][baseRangeContext]); return r.ReadSymbol(this.coefficientsBaseRange[(int)transformSizeContext][(int)planeType][baseRangeContext]);
} }
public int ReadDcSign(Av1PlaneType planeType, int dcSignContext) private int ReadDcSign(Av1PlaneType planeType, int dcSignContext)
{ {
ref Av1SymbolReader r = ref this.reader; ref Av1SymbolReader r = ref this.reader;
return r.ReadSymbol(this.dcSign[(int)planeType][dcSignContext]); return r.ReadSymbol(this.dcSign[(int)planeType][dcSignContext]);
} }
public int ReadBaseEndOfBlock(Av1TransformSize transformSizeContext, Av1PlaneType planeType, int coefficientContext) private int ReadBaseEndOfBlock(Av1TransformSize transformSizeContext, Av1PlaneType planeType, int coefficientContext)
{ {
ref Av1SymbolReader r = ref this.reader; ref Av1SymbolReader r = ref this.reader;
return r.ReadSymbol(this.baseEndOfBlock[(int)transformSizeContext][(int)planeType][coefficientContext]); return r.ReadSymbol(this.baseEndOfBlock[(int)transformSizeContext][(int)planeType][coefficientContext]);
} }
public int ReadCoefficientsBase(int coefficientContext, Av1TransformSize transformSizeContext, Av1PlaneType planeType) private int ReadCoefficientsBase(int coefficientContext, Av1TransformSize transformSizeContext, Av1PlaneType planeType)
{ {
ref Av1SymbolReader r = ref this.reader; ref Av1SymbolReader r = ref this.reader;
return r.ReadSymbol(this.coefficientsBase[(int)transformSizeContext][(int)planeType][coefficientContext]); return r.ReadSymbol(this.coefficientsBase[(int)transformSizeContext][(int)planeType][coefficientContext]);
} }
public int ReadChromFromLumaSign() private static int GetBaseRangeContextEndOfBlock(int pos, int bwl, Av1TransformClass transformClass)
{ {
ref Av1SymbolReader r = ref this.reader; int row = pos >> bwl;
return r.ReadSymbol(this.chromeForLumaSign); int col = pos - (row << bwl);
if (pos == 0)
{
return 0;
}
if ((transformClass == Av1TransformClass.Class2D && row < 2 && col < 2) ||
(transformClass == Av1TransformClass.ClassHorizontal && col == 0) ||
(transformClass == Av1TransformClass.ClassVertical && row == 0))
{
return 7;
}
return 14;
} }
public int ReadChromaFromLumaAlphaU(int jointSignPlus1) private static int GetLowerLevelContextEndOfBlock(int bwl, int height, int scanIndex)
{ {
ref Av1SymbolReader r = ref this.reader; if (scanIndex == 0)
int context = jointSignPlus1 - 3; {
return r.ReadSymbol(this.chromeForLumaAlpha[context]); return 0;
}
if (scanIndex <= (height << bwl) >> 3)
{
return 1;
}
if (scanIndex <= (height << bwl) >> 2)
{
return 2;
}
return 3;
} }
public int ReadChromaFromLumaAlphaV(int jointSignPlus1) private static int GetBaseRangeContext2d(Span<int> levels, int c, int bwl)
{ {
ref Av1SymbolReader r = ref this.reader; DebugGuard.MustBeGreaterThan(c, 0, nameof(c));
int context = AlphaVContexts[jointSignPlus1]; int row = c >> bwl;
return r.ReadSymbol(this.chromeForLumaAlpha[context]); int col = c - (row << bwl);
int stride = (1 << bwl) + Av1Constants.TransformPadHorizontal;
int pos = (row * stride) + col;
int mag =
Math.Min(levels[pos + 1], Av1Constants.MaxBaseRange) +
Math.Min(levels[pos + stride], Av1Constants.MaxBaseRange) +
Math.Min(levels[pos + 1 + stride], Av1Constants.MaxBaseRange);
mag = Math.Min((mag + 1) >> 1, 6);
if ((row | col) < 2)
{
return mag + 7;
}
return mag + 14;
}
private static int GetLowerLevelsContext2d(Span<int> levels, int pos, int bwl, Av1TransformSize transformSize)
{
DebugGuard.MustBeGreaterThan(pos, 0, nameof(pos));
int mag;
levels = levels[GetPaddedIndex(pos, bwl)..];
mag = Math.Min(levels[1], 3); // { 0, 1 }
mag += Math.Min(levels[(1 << bwl) + Av1Constants.TransformPadHorizontal], 3); // { 1, 0 }
mag += Math.Min(levels[(1 << bwl) + Av1Constants.TransformPadHorizontal + 1], 3); // { 1, 1 }
mag += Math.Min(levels[2], 3); // { 0, 2 }
mag += Math.Min(levels[(2 << bwl) + (2 << Av1Constants.TransformPadHorizontalLog2)], 3); // { 2, 0 }
int ctx = Math.Min((mag + 1) >> 1, 4);
return ctx + Av1NzMap.GetNzMapContext(transformSize, pos);
}
private static int GetBaseRangeContext(Span<int> levels, int c, int bwl, Av1TransformClass transformClass)
{
int row = c >> bwl;
int col = c - (row << bwl);
int stride = (1 << bwl) + Av1Constants.TransformPadHorizontal;
int pos = (row * stride) + col;
int mag = levels[pos + 1];
mag += levels[pos + stride];
switch (transformClass)
{
case Av1TransformClass.Class2D:
mag += levels[pos + stride + 1];
mag = Math.Min((mag + 1) >> 1, 6);
if (c == 0)
{
return mag;
}
if ((row < 2) && (col < 2))
{
return mag + 7;
}
break;
case Av1TransformClass.ClassHorizontal:
mag += levels[pos + 2];
mag = Math.Min((mag + 1) >> 1, 6);
if (c == 0)
{
return mag;
}
if (col == 0)
{
return mag + 7;
}
break;
case Av1TransformClass.ClassVertical:
mag += levels[pos + (stride << 1)];
mag = Math.Min((mag + 1) >> 1, 6);
if (c == 0)
{
return mag;
}
if (row == 0)
{
return mag + 7;
}
break;
default:
break;
}
return mag + 14;
}
private static int GetLowerLevelsContext(Span<int> levels, int pos, int bwl, Av1TransformSize transformSize, Av1TransformClass transformClass)
{
int stats = Av1NzMap.GetNzMagnitude(levels[GetPaddedIndex(pos, bwl)..], bwl, transformClass);
return Av1NzMap.GetNzMapContextFromStats(stats, pos, bwl, transformSize, transformClass);
}
private static int GetPaddedIndex(int scanIndex, int bwl)
=> scanIndex + ((scanIndex >> bwl) << Av1Constants.TransformPadHorizontalLog2);
private int ReadGolomb()
{
int x = 1;
int length = 0;
int i = 0;
while (i == 0)
{
i = this.ReadLiteral(1);
++length;
if (length > 20)
{
// SVT_LOG("Invalid length in read_golomb");
break;
}
}
for (i = 0; i < length - 1; ++i)
{
x <<= 1;
x += this.ReadLiteral(1);
}
return x - 1;
}
private static void SetDcSign(ref int culLevel, int dcValue)
{
if (dcValue < 0)
{
culLevel |= 1 << Av1Constants.CoefficientContextBitCount;
}
else if (dcValue > 0)
{
culLevel += 2 << Av1Constants.CoefficientContextBitCount;
}
} }
internal static Av1Distribution GetSplitOrHorizontalDistribution(Av1Distribution[] inputs, Av1BlockSize blockSize, int context) internal static Av1Distribution GetSplitOrHorizontalDistribution(Av1Distribution[] inputs, Av1BlockSize blockSize, int context)

298
src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileReader.cs

@ -566,7 +566,6 @@ internal class Av1TileReader : IAv1TileReader
Av1TransformSize transformSizeContext = (Av1TransformSize)(((int)transformSize.GetSquareSize() + ((int)transformSize.GetSquareUpSize() + 1)) >> 1); Av1TransformSize transformSizeContext = (Av1TransformSize)(((int)transformSize.GetSquareSize() + ((int)transformSize.GetSquareUpSize() + 1)) >> 1);
Av1PlaneType planeType = (Av1PlaneType)Math.Min(plane, 1); Av1PlaneType planeType = (Av1PlaneType)Math.Min(plane, 1);
int culLevel = 0; int culLevel = 0;
int dcValue = 0;
int[] levelsBuffer = new int[Av1Constants.TransformPad2d]; int[] levelsBuffer = new int[Av1Constants.TransformPad2d];
Span<int> levels = levelsBuffer.AsSpan()[(Av1Constants.TransformPadTop * (width + Av1Constants.TransformPadHorizontal))..]; Span<int> levels = levelsBuffer.AsSpan()[(Av1Constants.TransformPadTop * (width + Av1Constants.TransformPadHorizontal))..];
@ -574,7 +573,6 @@ internal class Av1TileReader : IAv1TileReader
bool allZero = reader.ReadTransformBlockSkip(transformSizeContext, transformBlockContext.SkipContext); bool allZero = reader.ReadTransformBlockSkip(transformSizeContext, transformBlockContext.SkipContext);
int bwl = transformSize.GetBlockWidthLog2(); int bwl = transformSize.GetBlockWidthLog2();
int endOfBlock; int endOfBlock;
int maxScanLine = 0;
if (allZero) if (allZero)
{ {
if (plane == 0) if (plane == 0)
@ -623,314 +621,28 @@ internal class Av1TileReader : IAv1TileReader
Array.Fill(levelsBuffer, 0, 0, ((width + Av1Constants.TransformPadHorizontal) * (height + Av1Constants.TransformPadVertical)) + Av1Constants.TransformPadEnd); Array.Fill(levelsBuffer, 0, 0, ((width + Av1Constants.TransformPadHorizontal) * (height + Av1Constants.TransformPadVertical)) + Av1Constants.TransformPadEnd);
} }
int i = endOfBlock - 1; reader.ReadCoefficientsEndOfBlock(transformClass, endOfBlock, height, scan, bwl, levels, transformSizeContext, planeType);
int pos = scan[i];
int coefficientContext = GetLowerLevelContextEndOfBlock(bwl, height, i);
int level = reader.ReadBaseEndOfBlock(transformSizeContext, planeType, coefficientContext);
if (level > Av1Constants.BaseLevelsCount)
{
int baseRangeContext = GetBaseRangeContextEndOfBlock(pos, bwl, transformClass);
for (int idx = 0; idx < Av1Constants.CoefficientBaseRange / Av1Constants.BaseRangeSizeMinus1; idx++)
{
int coefficinetBaseRange = reader.ReadCoefficientsBaseRange(transformSizeContext, planeType, baseRangeContext);
level += coefficinetBaseRange;
if (coefficinetBaseRange < Av1Constants.BaseRangeSizeMinus1)
{
break;
}
}
}
levels[GetPaddedIndex(pos, bwl)] = level;
if (endOfBlock > 1) if (endOfBlock > 1)
{ {
if (transformClass == Av1TransformClass.Class2D) if (transformClass == Av1TransformClass.Class2D)
{ {
ReadCoefficientsReverse2d(ref reader, transformSize, 1, endOfBlock - 1 - 1, scan, bwl, levels, transformSizeContext, planeType); reader.ReadCoefficientsReverse2d(transformSize, 1, endOfBlock - 1 - 1, scan, bwl, levels, transformSizeContext, planeType);
ReadCoefficientsReverse(ref reader, transformSize, transformInfo.Type, 0, 0, scan, bwl, levels, transformSizeContext, planeType); reader.ReadCoefficientsReverse(transformSize, transformClass, 0, 0, scan, bwl, levels, transformSizeContext, planeType);
} }
else else
{ {
ReadCoefficientsReverse(ref reader, transformSize, transformInfo.Type, 0, endOfBlock - 1 - 1, scan, bwl, levels, transformSizeContext, planeType); reader.ReadCoefficientsReverse(transformSize, transformClass, 0, endOfBlock - 1 - 1, scan, bwl, levels, transformSizeContext, planeType);
} }
} }
DebugGuard.MustBeGreaterThan(scan.Length, 0, nameof(scan)); DebugGuard.MustBeGreaterThan(scan.Length, 0, nameof(scan));
coefficientBuffer[0] = endOfBlock; culLevel = reader.ReadCoefficientsDc(coefficientBuffer, endOfBlock, scan, bwl, levels, transformBlockContext.DcSignContext, planeType);
for (int c = 0; c < endOfBlock; c++)
{
int sign = 0;
level = levels[GetPaddedIndex(scan[c], bwl)];
if (level != 0)
{
maxScanLine = Math.Max(maxScanLine, scan[c]);
if (c == 0)
{
sign = reader.ReadDcSign(planeType, transformBlockContext.DcSignContext);
}
else
{
sign = reader.ReadLiteral(1);
}
if (level >= Av1Constants.CoefficientBaseRange + Av1Constants.BaseLevelsCount + 1)
{
level += ReadGolomb(ref reader);
}
if (c == 0)
{
dcValue = sign != 0 ? -level : level;
}
level &= 0xfffff;
culLevel += level;
}
coefficientBuffer[c + 1] = sign != 0 ? -level : level;
}
culLevel = Math.Min(Av1Constants.CoefficientContextMask, culLevel);
SetDcSign(ref culLevel, dcValue);
this.UpdateCoefficientContext(plane, partitionInfo, transformSize, blockRow, blockColumn, aboveOffset, leftOffset, culLevel); this.UpdateCoefficientContext(plane, partitionInfo, transformSize, blockRow, blockColumn, aboveOffset, leftOffset, culLevel);
transformInfo.CodeBlockFlag = true; transformInfo.CodeBlockFlag = true;
return endOfBlock; return endOfBlock;
} }
private static void ReadCoefficientsReverse2d(ref Av1SymbolDecoder reader, Av1TransformSize transformSize, int startSi, int endSi, Span<short> scan, int bwl, Span<int> levels, Av1TransformSize transformSizeContext, Av1PlaneType planeType)
{
for (int c = endSi; c >= startSi; --c)
{
int pos = scan[c];
int coefficientContext = GetLowerLevelsContext2d(levels, pos, bwl, transformSize);
int level = reader.ReadCoefficientsBase(coefficientContext, transformSizeContext, planeType);
if (level > Av1Constants.BaseLevelsCount)
{
int baseRangeContext = GetBaseRangeContext2d(levels, pos, bwl);
for (int idx = 0; idx < Av1Constants.CoefficientBaseRange; idx += Av1Constants.BaseRangeSizeMinus1)
{
int k = reader.ReadCoefficientsBaseRange(transformSizeContext, planeType, baseRangeContext);
level += k;
if (k < Av1Constants.BaseRangeSizeMinus1)
{
break;
}
}
}
levels[GetPaddedIndex(pos, bwl)] = level;
}
}
private static int GetBaseRangeContext2d(Span<int> levels, int c, int bwl)
{
DebugGuard.MustBeGreaterThan(c, 0, nameof(c));
int row = c >> bwl;
int col = c - (row << bwl);
int stride = (1 << bwl) + Av1Constants.TransformPadHorizontal;
int pos = (row * stride) + col;
int mag =
Math.Min(levels[pos + 1], Av1Constants.MaxBaseRange) +
Math.Min(levels[pos + stride], Av1Constants.MaxBaseRange) +
Math.Min(levels[pos + 1 + stride], Av1Constants.MaxBaseRange);
mag = Math.Min((mag + 1) >> 1, 6);
if ((row | col) < 2)
{
return mag + 7;
}
return mag + 14;
}
private static int GetLowerLevelsContext2d(Span<int> levels, int pos, int bwl, Av1TransformSize transformSize)
{
DebugGuard.MustBeGreaterThan(pos, 0, nameof(pos));
int mag;
levels = levels[GetPaddedIndex(pos, bwl)..];
mag = Math.Min(levels[1], 3); // { 0, 1 }
mag += Math.Min(levels[(1 << bwl) + Av1Constants.TransformPadHorizontal], 3); // { 1, 0 }
mag += Math.Min(levels[(1 << bwl) + Av1Constants.TransformPadHorizontal + 1], 3); // { 1, 1 }
mag += Math.Min(levels[2], 3); // { 0, 2 }
mag += Math.Min(levels[(2 << bwl) + (2 << Av1Constants.TransformPadHorizontalLog2)], 3); // { 2, 0 }
int ctx = Math.Min((mag + 1) >> 1, 4);
return ctx + Av1NzMap.GetNzMapContext(transformSize, pos);
}
private static void ReadCoefficientsReverse(ref Av1SymbolDecoder reader, Av1TransformSize transformSize, Av1TransformType transformType, int startSi, int endSi, Span<short> scan, int bwl, Span<int> levels, Av1TransformSize transformSizeContext, Av1PlaneType planeType)
{
Av1TransformClass transformClass = transformType.ToClass();
for (int c = endSi; c >= startSi; --c)
{
int pos = scan[c];
int coefficientContext = GetLowerLevelsContext(levels, pos, bwl, transformSize, transformClass);
int level = reader.ReadCoefficientsBase(coefficientContext, transformSizeContext, planeType);
if (level > Av1Constants.BaseLevelsCount)
{
int baseRangeContext = GetBaseRangeContext(levels, pos, bwl, transformClass);
for (int idx = 0; idx < Av1Constants.CoefficientBaseRange; idx += Av1Constants.BaseRangeSizeMinus1)
{
int k = reader.ReadCoefficientsBaseRange(transformSizeContext, planeType, baseRangeContext);
level += k;
if (k < Av1Constants.BaseRangeSizeMinus1)
{
break;
}
}
}
levels[GetPaddedIndex(pos, bwl)] = level;
}
}
private static int GetBaseRangeContext(Span<int> levels, int c, int bwl, Av1TransformClass transformClass)
{
int row = c >> bwl;
int col = c - (row << bwl);
int stride = (1 << bwl) + Av1Constants.TransformPadHorizontal;
int pos = (row * stride) + col;
int mag = levels[pos + 1];
mag += levels[pos + stride];
switch (transformClass)
{
case Av1TransformClass.Class2D:
mag += levels[pos + stride + 1];
mag = Math.Min((mag + 1) >> 1, 6);
if (c == 0)
{
return mag;
}
if ((row < 2) && (col < 2))
{
return mag + 7;
}
break;
case Av1TransformClass.ClassHorizontal:
mag += levels[pos + 2];
mag = Math.Min((mag + 1) >> 1, 6);
if (c == 0)
{
return mag;
}
if (col == 0)
{
return mag + 7;
}
break;
case Av1TransformClass.ClassVertical:
mag += levels[pos + (stride << 1)];
mag = Math.Min((mag + 1) >> 1, 6);
if (c == 0)
{
return mag;
}
if (row == 0)
{
return mag + 7;
}
break;
default:
break;
}
return mag + 14;
}
private static int GetLowerLevelsContext(Span<int> levels, int pos, int bwl, Av1TransformSize transformSize, Av1TransformClass transformClass)
{
int stats = Av1NzMap.GetNzMagnitude(levels[GetPaddedIndex(pos, bwl)..], bwl, transformClass);
return Av1NzMap.GetNzMapContextFromStats(stats, pos, bwl, transformSize, transformClass);
}
private static int ReadGolomb(ref Av1SymbolDecoder reader)
{
int x = 1;
int length = 0;
int i = 0;
while (i == 0)
{
i = reader.ReadLiteral(1);
++length;
if (length > 20)
{
// SVT_LOG("Invalid length in read_golomb");
break;
}
}
for (i = 0; i < length - 1; ++i)
{
x <<= 1;
x += reader.ReadLiteral(1);
}
return x - 1;
}
private static void SetDcSign(ref int culLevel, int dcValue)
{
if (dcValue < 0)
{
culLevel |= 1 << Av1Constants.CoefficientContextBitCount;
}
else if (dcValue > 0)
{
culLevel += 2 << Av1Constants.CoefficientContextBitCount;
}
}
private static int GetPaddedIndex(int scanIndex, int bwl)
=> scanIndex + ((scanIndex >> bwl) << Av1Constants.TransformPadHorizontalLog2);
private static int GetBaseRangeContextEndOfBlock(int pos, int bwl, Av1TransformClass transformClass)
{
int row = pos >> bwl;
int col = pos - (row << bwl);
if (pos == 0)
{
return 0;
}
if ((transformClass == Av1TransformClass.Class2D && row < 2 && col < 2) ||
(transformClass == Av1TransformClass.ClassHorizontal && col == 0) ||
(transformClass == Av1TransformClass.ClassVertical && row == 0))
{
return 7;
}
return 14;
}
private static int GetLowerLevelContextEndOfBlock(int bwl, int height, int scanIndex)
{
if (scanIndex == 0)
{
return 0;
}
if (scanIndex <= (height << bwl) >> 3)
{
return 1;
}
if (scanIndex <= (height << bwl) >> 2)
{
return 2;
}
return 3;
}
private void UpdateCoefficientContext(int plane, Av1PartitionInfo partitionInfo, Av1TransformSize transformSize, int blockRow, int blockColumn, int aboveOffset, int leftOffset, int culLevel) private void UpdateCoefficientContext(int plane, Av1PartitionInfo partitionInfo, Av1TransformSize transformSize, int blockRow, int blockColumn, int aboveOffset, int leftOffset, int culLevel)
{ {
bool subX = this.SequenceHeader.ColorConfig.SubSamplingX; bool subX = this.SequenceHeader.ColorConfig.SubSamplingX;

Loading…
Cancel
Save