From e58a775cc014ffe448a59d5b21b79fcc8809ec9c Mon Sep 17 00:00:00 2001 From: Ynse Hoornenborg Date: Fri, 15 Nov 2024 20:33:56 +0100 Subject: [PATCH] Move end-of-block position reading to Av1SymbolDecoder --- .../Heif/Av1/Tiling/Av1SymbolDecoder.cs | 77 ++++++++++++++----- .../Formats/Heif/Av1/Tiling/Av1TileReader.cs | 41 +--------- 2 files changed, 60 insertions(+), 58 deletions(-) diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1SymbolDecoder.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1SymbolDecoder.cs index 57de6659c5..a327d7094a 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1SymbolDecoder.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1SymbolDecoder.cs @@ -10,6 +10,8 @@ internal ref struct Av1SymbolDecoder { private static readonly int[] IntraModeContext = [0, 1, 2, 3, 4, 4, 4, 4, 3, 0, 1, 2, 0]; private static readonly int[] AlphaVContexts = [-1, 0, 3, -1, 1, 4, -1, 2, 5]; + private static readonly int[] EndOfBlockOffsetBits = [0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + private static readonly int[] EndOfBlockGroupStart = [0, 1, 2, 3, 5, 9, 17, 33, 65, 129, 257, 513]; private readonly Av1Distribution tileIntraBlockCopy = Av1DefaultDistributions.IntraBlockCopy; private readonly Av1Distribution[] tilePartitionTypes = Av1DefaultDistributions.PartitionTypes; @@ -177,26 +179,12 @@ internal ref struct Av1SymbolDecoder return transformSize; } - public int ReadEndOfBlockFlag(Av1PlaneType planeType, Av1TransformClass transformClass, Av1TransformSize transformSize) - { - int endOfBlockContext = transformClass == Av1TransformClass.Class2D ? 0 : 1; - int endOfBlockMultiSize = transformSize.GetLog2Minus4(); - ref Av1SymbolReader r = ref this.reader; - return r.ReadSymbol(this.endOfBlockFlag[endOfBlockMultiSize][(int)planeType][endOfBlockContext]) + 1; - } - public bool ReadTransformBlockSkip(Av1TransformSize transformSizeContext, int skipContext) { ref Av1SymbolReader r = ref this.reader; return r.ReadSymbol(this.transformBlockSkip[(int)transformSizeContext][skipContext]) > 0; } - public bool ReadEndOfBlockExtra(Av1TransformSize transformSizeContext, Av1PlaneType planeType, int endOfBlockContext) - { - ref Av1SymbolReader r = ref this.reader; - return r.ReadSymbol(this.endOfBlockExtra[(int)transformSizeContext][(int)planeType][endOfBlockContext]) > 0; - } - public int ReadChromFromLumaSign() { ref Av1SymbolReader r = ref this.reader; @@ -217,6 +205,34 @@ internal ref struct Av1SymbolDecoder return r.ReadSymbol(this.chromeForLumaAlpha[context]); } + public int ReadEndOfBlockPosition(Av1TransformSize transformSize, Av1TransformClass transformClass, Av1TransformSize transformSizeContext, Av1PlaneType planeType) + { + int endOfBlockExtra = 0; + int endOfBlockPoint = this.ReadEndOfBlockFlag(planeType, transformClass, transformSize); + int endOfBlockShift = EndOfBlockOffsetBits[endOfBlockPoint]; + if (endOfBlockShift > 0) + { + int endOfBlockContext = endOfBlockPoint; + bool bit = this.ReadEndOfBlockExtra(transformSizeContext, planeType, endOfBlockContext); + if (bit) + { + endOfBlockExtra += 1 << (endOfBlockShift - 1); + } + else + { + for (int j = 1; j < endOfBlockShift; j++) + { + if (this.ReadLiteral(1) != 0) + { + endOfBlockExtra += 1 << (endOfBlockShift - 1 - j); + } + } + } + } + + return RecordEndOfBlockPosition(endOfBlockPoint, endOfBlockExtra); + } + public void ReadCoefficientsEndOfBlock(Av1TransformClass transformClass, int endOfBlock, int height, ReadOnlySpan scan, int bwl, Span levels, Av1TransformSize transformSizeContext, Av1PlaneType planeType) { int i = endOfBlock - 1; @@ -240,9 +256,9 @@ internal ref struct Av1SymbolDecoder levels[GetPaddedIndex(pos, bwl)] = level; } - public void ReadCoefficientsReverse2d(Av1TransformSize transformSize, int startSi, int endSi, ReadOnlySpan scan, int bwl, Span levels, Av1TransformSize transformSizeContext, Av1PlaneType planeType) + public void ReadCoefficientsReverse2d(Av1TransformSize transformSize, int startScanIndex, int endScanIndex, ReadOnlySpan scan, int bwl, Span levels, Av1TransformSize transformSizeContext, Av1PlaneType planeType) { - for (int c = endSi; c >= startSi; --c) + for (int c = endScanIndex; c >= startScanIndex; --c) { int pos = scan[c]; int coefficientContext = GetLowerLevelsContext2d(levels, pos, bwl, transformSize); @@ -265,9 +281,9 @@ internal ref struct Av1SymbolDecoder } } - public void ReadCoefficientsReverse(Av1TransformSize transformSize, Av1TransformClass transformClass, int startSi, int endSi, ReadOnlySpan scan, int bwl, Span levels, Av1TransformSize transformSizeContext, Av1PlaneType planeType) + public void ReadCoefficientsReverse(Av1TransformSize transformSize, Av1TransformClass transformClass, int startScanIndex, int endScanIndex, ReadOnlySpan scan, int bwl, Span levels, Av1TransformSize transformSizeContext, Av1PlaneType planeType) { - for (int c = endSi; c >= startSi; --c) + for (int c = endScanIndex; c >= startScanIndex; --c) { int pos = scan[c]; int coefficientContext = GetLowerLevelsContext(levels, pos, bwl, transformSize, transformClass); @@ -335,6 +351,20 @@ internal ref struct Av1SymbolDecoder return culLevel; } + private int ReadEndOfBlockFlag(Av1PlaneType planeType, Av1TransformClass transformClass, Av1TransformSize transformSize) + { + int endOfBlockContext = transformClass == Av1TransformClass.Class2D ? 0 : 1; + int endOfBlockMultiSize = transformSize.GetLog2Minus4(); + ref Av1SymbolReader r = ref this.reader; + return r.ReadSymbol(this.endOfBlockFlag[endOfBlockMultiSize][(int)planeType][endOfBlockContext]) + 1; + } + + private bool ReadEndOfBlockExtra(Av1TransformSize transformSizeContext, Av1PlaneType planeType, int endOfBlockContext) + { + ref Av1SymbolReader r = ref this.reader; + return r.ReadSymbol(this.endOfBlockExtra[(int)transformSizeContext][(int)planeType][endOfBlockContext]) > 0; + } + private int ReadCoefficientsBaseRange(Av1TransformSize transformSizeContext, Av1PlaneType planeType, int baseRangeContext) { ref Av1SymbolReader r = ref this.reader; @@ -359,6 +389,17 @@ internal ref struct Av1SymbolDecoder return r.ReadSymbol(this.coefficientsBase[(int)transformSizeContext][(int)planeType][coefficientContext]); } + private static int RecordEndOfBlockPosition(int endOfBlockPoint, int endOfBlockExtra) + { + int endOfBlock = EndOfBlockGroupStart[endOfBlockPoint]; + if (endOfBlock > 2) + { + endOfBlock += endOfBlockExtra; + } + + return endOfBlock; + } + private static int GetBaseRangeContextEndOfBlock(int pos, int bwl, Av1TransformClass transformClass) { int row = pos >> bwl; diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileReader.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileReader.cs index e4b5b6a9aa..2d6372ad6c 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileReader.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileReader.cs @@ -22,9 +22,6 @@ internal class Av1TileReader : IAv1TileReader private static readonly int[][] SkipContexts = [ [1, 2, 2, 2, 3], [1, 4, 4, 4, 5], [1, 4, 4, 4, 5], [1, 4, 4, 4, 5], [1, 4, 4, 4, 6]]; - private static readonly int[] EndOfBlockGroupStart = [0, 1, 2, 3, 5, 9, 17, 33, 65, 129, 257, 513]; - private static readonly int[] EndOfBlockOffsetBits = [0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; - private int[][] referenceSgrXqd = []; private int[][][] referenceLrWiener = []; private readonly Av1ParseAboveNeighbor4x4Context aboveNeighborContext; @@ -585,37 +582,12 @@ internal class Av1TileReader : IAv1TileReader return 0; } - int endOfBlockExtra = 0; - int endOfBlockPoint = 0; - transformInfo.Type = this.ComputeTransformType(planeType, partitionInfo, transformSize, transformInfo); Av1TransformClass transformClass = transformInfo.Type.ToClass(); Av1ScanOrder scanOrder = Av1ScanOrderConstants.GetScanOrder(transformSize, transformInfo.Type); ReadOnlySpan scan = scanOrder.Scan; - endOfBlockPoint = reader.ReadEndOfBlockFlag(planeType, transformClass, transformSize); - int endOfBlockShift = EndOfBlockOffsetBits[endOfBlockPoint]; - if (endOfBlockShift > 0) - { - int endOfBlockContext = endOfBlockPoint; - bool bit = reader.ReadEndOfBlockExtra(transformSizeContext, planeType, endOfBlockContext); - if (bit) - { - endOfBlockExtra += 1 << (endOfBlockShift - 1); - } - else - { - for (int j = 1; j < endOfBlockShift; j++) - { - if (reader.ReadLiteral(1) != 0) - { - endOfBlockExtra += 1 << (endOfBlockShift - 1 - j); - } - } - } - } - - endOfBlock = RecordEndOfBlockPosition(endOfBlockPoint, endOfBlockExtra); + endOfBlock = reader.ReadEndOfBlockPosition(transformSize, transformClass, transformSizeContext, planeType); if (endOfBlock > 1) { Array.Fill(levelsBuffer, 0, 0, ((width + Av1Constants.TransformPadHorizontal) * (height + Av1Constants.TransformPadVertical)) + Av1Constants.TransformPadEnd); @@ -679,17 +651,6 @@ internal class Av1TileReader : IAv1TileReader } } - private static int RecordEndOfBlockPosition(int endOfBlockPoint, int endOfBlockExtra) - { - int endOfBlock = EndOfBlockGroupStart[endOfBlockPoint]; - if (endOfBlock > 2) - { - endOfBlock += endOfBlockExtra; - } - - return endOfBlock; - } - private Av1TransformType ComputeTransformType(Av1PlaneType planeType, Av1PartitionInfo partitionInfo, Av1TransformSize transformSize, Av1TransformInfo transformInfo) { Av1TransformType transformType = Av1TransformType.DctDct;