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;
}
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;
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;
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;
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;
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;
return r.ReadSymbol(this.chromeForLumaSign);
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;
}
public int ReadChromaFromLumaAlphaU(int jointSignPlus1)
private static int GetLowerLevelContextEndOfBlock(int bwl, int height, int scanIndex)
{
ref Av1SymbolReader r = ref this.reader;
int context = jointSignPlus1 - 3;
return r.ReadSymbol(this.chromeForLumaAlpha[context]);
if (scanIndex == 0)
{
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;
int context = AlphaVContexts[jointSignPlus1];
return r.ReadSymbol(this.chromeForLumaAlpha[context]);
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 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)

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);
Av1PlaneType planeType = (Av1PlaneType)Math.Min(plane, 1);
int culLevel = 0;
int dcValue = 0;
int[] levelsBuffer = new int[Av1Constants.TransformPad2d];
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);
int bwl = transformSize.GetBlockWidthLog2();
int endOfBlock;
int maxScanLine = 0;
if (allZero)
{
if (plane == 0)
@ -623,314 +621,28 @@ internal class Av1TileReader : IAv1TileReader
Array.Fill(levelsBuffer, 0, 0, ((width + Av1Constants.TransformPadHorizontal) * (height + Av1Constants.TransformPadVertical)) + Av1Constants.TransformPadEnd);
}
int i = endOfBlock - 1;
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;
reader.ReadCoefficientsEndOfBlock(transformClass, endOfBlock, height, scan, bwl, levels, transformSizeContext, planeType);
if (endOfBlock > 1)
{
if (transformClass == Av1TransformClass.Class2D)
{
ReadCoefficientsReverse2d(ref reader, transformSize, 1, endOfBlock - 1 - 1, scan, bwl, levels, transformSizeContext, planeType);
ReadCoefficientsReverse(ref reader, transformSize, transformInfo.Type, 0, 0, scan, bwl, levels, transformSizeContext, planeType);
reader.ReadCoefficientsReverse2d(transformSize, 1, endOfBlock - 1 - 1, scan, bwl, levels, transformSizeContext, planeType);
reader.ReadCoefficientsReverse(transformSize, transformClass, 0, 0, scan, bwl, levels, transformSizeContext, planeType);
}
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));
coefficientBuffer[0] = endOfBlock;
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);
culLevel = reader.ReadCoefficientsDc(coefficientBuffer, endOfBlock, scan, bwl, levels, transformBlockContext.DcSignContext, planeType);
this.UpdateCoefficientContext(plane, partitionInfo, transformSize, blockRow, blockColumn, aboveOffset, leftOffset, culLevel);
transformInfo.CodeBlockFlag = true;
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)
{
bool subX = this.SequenceHeader.ColorConfig.SubSamplingX;

Loading…
Cancel
Save