Browse Source

Tiling initialization fixes

pull/2633/head
Ynse Hoornenborg 2 years ago
parent
commit
0cf272626f
  1. 5
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1BlockModeInfo.cs
  2. 50
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameBuffer.cs
  3. 17
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1ParseAboveContext.cs
  4. 2
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1ParseAboveNeighbor4x4Context.cs
  5. 13
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1ParseLeftContext.cs
  6. 122
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileDecoder.cs
  7. 4
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileInfo.cs

5
src/ImageSharp/Formats/Heif/Av1/Tiling/Av1BlockModeInfo.cs

@ -9,9 +9,10 @@ internal class Av1BlockModeInfo
{
private int[] paletteSize;
public Av1BlockModeInfo(int numPlanes, Av1BlockSize blockSize)
public Av1BlockModeInfo(int numPlanes, Av1BlockSize blockSize, Point position)
{
this.BlockSize = blockSize;
this.PositionInSuperblock = position;
this.AngleDelta = new int[numPlanes];
this.paletteSize = new int[numPlanes - 1];
this.FilterIntraModeInfo = new();
@ -39,7 +40,7 @@ internal class Av1BlockModeInfo
public int[] AngleDelta { get; set; }
public Size IndexInSuperblock { get; set; }
public Point PositionInSuperblock { get; set; }
public Av1IntraFilterModeInfo FilterIntraModeInfo { get; internal set; }

50
src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameBuffer.cs

@ -39,17 +39,43 @@ internal class Av1FrameBuffer
int superblockCount = this.superblockColumnCount * this.superblockRowCount;
this.modeInfoSizePerSuperblock = 1 << (superblockSizeLog2 - Av1Constants.ModeInfoSizeLog2);
this.modeInfoCountPerSuperblock = this.modeInfoSizePerSuperblock * this.modeInfoSizePerSuperblock;
int numPlanes = sequenceHeader.ColorConfig.IsMonochrome ? 1 : Av1Constants.MaxPlanes;
// Allocate the arrays.
this.superblockInfos = new Av1SuperblockInfo[superblockCount];
this.modeInfos = new Av1BlockModeInfo[superblockCount * this.modeInfoCountPerSuperblock];
this.transformInfosY = new Av1TransformInfo[superblockCount * this.modeInfoCountPerSuperblock];
this.transformInfosUv = new Av1TransformInfo[2 * superblockCount * this.modeInfoCountPerSuperblock];
this.coefficientsY = new int[superblockCount * this.modeInfoCountPerSuperblock * CoefficientCountPerModeInfo];
// Initialize the arrays.
int i = 0;
int j = 0;
for (int y = 0; y < this.superblockRowCount; y++)
{
for (int x = 0; x < this.superblockColumnCount; x++)
{
Point point = new(x, y);
this.superblockInfos[i] = new(this, point);
for (int u = 0; u < this.modeInfoSizePerSuperblock; u++)
{
for (int v = 0; v < this.modeInfoSizePerSuperblock; v++)
{
this.modeInfos[j] = new Av1BlockModeInfo(numPlanes, Av1BlockSize.Block4x4, new Point(u, v));
j++;
}
}
i++;
}
}
bool subX = sequenceHeader.ColorConfig.SubSamplingX;
bool subY = sequenceHeader.ColorConfig.SubSamplingY;
// Factor: 444 => 0, 422 => 1, 420 => 2.
this.subsamplingFactor = (subX && subY) ? 2 : (subX && !subY) ? 1 : (!subX && !subY) ? 0 : -1;
Guard.IsFalse(this.subsamplingFactor == -1, nameof(this.subsamplingFactor), "Invalid combination of subsampling.");
this.coefficientsY = new int[superblockCount * this.modeInfoCountPerSuperblock * CoefficientCountPerModeInfo];
this.coefficientsU = new int[(this.modeInfoCountPerSuperblock * CoefficientCountPerModeInfo) >> this.subsamplingFactor];
this.coefficientsV = new int[(this.modeInfoCountPerSuperblock * CoefficientCountPerModeInfo) >> this.subsamplingFactor];
this.deltaQ = new int[superblockCount];
@ -68,12 +94,19 @@ internal class Av1FrameBuffer
return span[i];
}
public Av1BlockModeInfo GetModeInfo(Point superblockIndex)
{
Span<Av1BlockModeInfo> span = this.modeInfos;
int superblock = (superblockIndex.Y * this.superblockColumnCount) + superblockIndex.X;
return span[superblock * this.modeInfoCountPerSuperblock];
}
public Av1BlockModeInfo GetModeInfo(Point superblockIndex, Point modeInfoIndex)
{
Span<Av1BlockModeInfo> span = this.modeInfos;
int baseIndex = ((superblockIndex.Y * this.superblockColumnCount) + superblockIndex.X) * this.modeInfoCountPerSuperblock;
int offset = (modeInfoIndex.Y * this.modeInfoSizePerSuperblock) + modeInfoIndex.X;
return span[baseIndex + offset];
int superblock = (superblockIndex.Y * this.superblockColumnCount) + superblockIndex.X;
int modeInfo = (modeInfoIndex.Y * this.modeInfoSizePerSuperblock) + modeInfoIndex.X;
return span[(superblock * this.modeInfoCountPerSuperblock) + modeInfo];
}
public Av1TransformInfo GetTransformY(Point index)
@ -126,6 +159,15 @@ internal class Av1FrameBuffer
return span.Slice(i, 1 << this.cdefStrengthFactorLog2);
}
internal void ClearCdef(Point index)
{
Span<int> cdefs = this.GetCdefStrength(index);
for (int i = 0; i < cdefs.Length; i++)
{
cdefs[i] = -1;
}
}
public Span<int> GetDeltaLoopFilter(Point index)
{
Span<int> span = this.deltaLoopFilter;

17
src/ImageSharp/Formats/Heif/Av1/Tiling/Av1ParseAboveContext.cs

@ -1,17 +0,0 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Symbol;
internal class Av1ParseAboveContext
{
public int PartitionWidth { get; set; }
public int[][] AboveContext { get; set; } = [];
internal void Clear(int startColumnIndex, int endColumnIndex)
{
this.PartitionWidth = -1;
this.AboveContext = [];
}
}

2
src/ImageSharp/Formats/Heif/Av1/Tiling/Av1ParseAboveNeighbor4x4Context.cs

@ -59,7 +59,7 @@ internal class Av1ParseAboveNeighbor4x4Context
Array.Fill(this.aboveCompGroupIndex, 0);
}
public void UpdatePartition(Point modeInfoLocation, Av1TileLocation tileLoc, Av1BlockSize subSize, Av1BlockSize blockSize)
public void UpdatePartition(Point modeInfoLocation, Av1TileInfo tileLoc, Av1BlockSize subSize, Av1BlockSize blockSize)
{
int startIndex = modeInfoLocation.X - tileLoc.ModeInfoColumnStart;
int bw = blockSize.Get4x4WideCount();

13
src/ImageSharp/Formats/Heif/Av1/Tiling/Av1ParseLeftContext.cs

@ -1,13 +0,0 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Symbol;
internal class Av1ParseLeftContext
{
public int PartitionHeight { get; set; }
public int[][] LeftContext { get; set; } = [];
internal void Clear() => throw new NotImplementedException();
}

122
src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileDecoder.cs

@ -1,10 +1,12 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System.Data.Common;
using SixLabors.ImageSharp.Formats.Heif.Av1;
using SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit;
using SixLabors.ImageSharp.Formats.Heif.Av1.Prediction;
using SixLabors.ImageSharp.Formats.Heif.Av1.Quantization;
using static SixLabors.ImageSharp.PixelFormats.Utils.Vector4Converters;
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Symbol;
@ -17,8 +19,6 @@ internal class Av1TileDecoder : IAv1TileDecoder
private bool[][][] blockDecoded = [];
private int[][] referenceSgrXqd = [];
private int[][][] referenceLrWiener = [];
private Av1ParseAboveContext aboveContext = new();
private Av1ParseLeftContext leftContext = new();
private Av1ParseAboveNeighbor4x4Context aboveNeighborContext;
private Av1ParseLeftNeighbor4x4Context leftNeighborContext;
private int currentQuantizerIndex;
@ -30,12 +30,13 @@ internal class Av1TileDecoder : IAv1TileDecoder
private int maxLumaWidth;
private int maxLumaHeight;
private int deltaLoopFilterResolution = -1;
private int deltaQuantizerResolution = -1;
private bool readDeltas;
public Av1TileDecoder(ObuSequenceHeader sequenceHeader, ObuFrameHeader frameInfo)
{
this.FrameInfo = frameInfo;
this.SequenceHeader = sequenceHeader;
this.readDeltas = frameInfo.DeltaQParameters.IsPresent;
// init_main_frame_ctxt
this.FrameBuffer = new(this.SequenceHeader);
@ -68,9 +69,11 @@ internal class Av1TileDecoder : IAv1TileDecoder
int tileColumnIndex = tileNum % this.FrameInfo.TilesInfo.TileColumnCount;
int tileRowIndex = tileNum / this.FrameInfo.TilesInfo.TileColumnCount;
this.aboveContext.Clear(this.FrameInfo.TilesInfo.TileColumnStartModeInfo[tileColumnIndex], this.FrameInfo.TilesInfo.TileColumnStartModeInfo[tileColumnIndex + 1]);
this.aboveNeighborContext.Clear(this.SequenceHeader);
this.ClearLoopFilterDelta();
int planesCount = this.SequenceHeader.ColorConfig.IsMonochrome ? 1 : 3;
// Default initialization of Wiener and SGR Filter.
this.referenceSgrXqd = new int[planesCount][];
this.referenceLrWiener = new int[planesCount][][];
for (int plane = 0; plane < planesCount; plane++)
@ -85,30 +88,25 @@ internal class Av1TileDecoder : IAv1TileDecoder
}
}
// TODO: Initialize this.blockDecoded and this.segmentIds
// TODO: Initialize this.blockDecoded
Av1TileInfo tileInfo = new(tileRowIndex, tileColumnIndex, this.FrameInfo);
Av1BlockSize superBlockSize = this.SequenceHeader.Use128x128SuperBlock ? Av1BlockSize.Block128x128 : Av1BlockSize.Block64x64;
int superBlock4x4Size = superBlockSize.Get4x4WideCount();
for (int row = this.FrameInfo.TilesInfo.TileRowStartModeInfo[tileRowIndex]; row < this.FrameInfo.TilesInfo.TileRowStartModeInfo[tileRowIndex + 1]; row += this.SequenceHeader.ModeInfoSize)
{
int superBlockRow = row << Av1Constants.ModeInfoSizeLog2 >> this.SequenceHeader.SuperBlockSizeLog2;
this.leftContext.Clear();
this.leftNeighborContext.Clear(this.SequenceHeader);
for (int column = this.FrameInfo.TilesInfo.TileColumnStartModeInfo[tileColumnIndex]; column < this.FrameInfo.TilesInfo.TileColumnStartModeInfo[tileColumnIndex + 1]; column += this.SequenceHeader.ModeInfoSize)
{
int superBlockColumn = column << Av1Constants.ModeInfoSizeLog2 >> this.SequenceHeader.SuperBlockSizeLog2;
// bool subSamplingX = this.SequenceHeader.ColorConfig.SubSamplingX;
// bool subSamplingY = this.SequenceHeader.ColorConfig.SubSamplingY;
bool readDeltas = this.FrameInfo.DeltaQParameters.IsPresent;
Av1TileLocation tileLoc = new(row, column, this.FrameInfo);
// this.ClearBlockDecodedFlags(row, column, superBlock4x4Size);
Point superblockPosition = new(superBlockColumn, superBlockRow);
Av1SuperblockInfo superblockInfo = new(this.FrameBuffer, superblockPosition);
Av1SuperblockInfo superblockInfo = this.FrameBuffer.GetSuperblock(superblockPosition);
// Nothing to do for CDEF
// this.ClearCdef(row, column);
// this.ReadLoopRestoration(row, column, superBlockSize);
this.ParsePartition(ref reader, new Point(column, row), superBlockSize, superblockInfo, tileLoc);
// this.ClearBlockDecodedFlags(row, column, superBlock4x4Size);
this.FrameBuffer.ClearCdef(superblockPosition);
Point modeInfoLocation = new(column, row);
this.ReadLoopRestoration(modeInfoLocation, superBlockSize);
this.ParsePartition(ref reader, modeInfoLocation, superBlockSize, superblockInfo, tileInfo);
}
}
}
@ -154,7 +152,7 @@ internal class Av1TileDecoder : IAv1TileDecoder
}
}
private void ReadLoopRestoration(int row, int column, Av1BlockSize superBlockSize)
private void ReadLoopRestoration(Point modeInfoLocation, Av1BlockSize superBlockSize)
{
int planesCount = this.SequenceHeader.ColorConfig.ChannelCount;
for (int plane = 0; plane < planesCount; plane++)
@ -177,7 +175,7 @@ internal class Av1TileDecoder : IAv1TileDecoder
// TODO: Implement
}
private void ParsePartition(ref Av1SymbolDecoder reader, Point modeInfoLocation, Av1BlockSize blockSize, Av1SuperblockInfo superblockInfo, Av1TileLocation tileLoc)
private void ParsePartition(ref Av1SymbolDecoder reader, Point modeInfoLocation, Av1BlockSize blockSize, Av1SuperblockInfo superblockInfo, Av1TileInfo tileInfo)
{
int columnIndex = modeInfoLocation.X;
int rowIndex = modeInfoLocation.Y;
@ -200,18 +198,18 @@ internal class Av1TileDecoder : IAv1TileDecoder
}
else if (hasRows && hasColumns)
{
int ctx = this.GetPartitionContext(modeInfoLocation, blockSize, tileLoc, this.FrameInfo.ModeInfoRowCount);
int ctx = this.GetPartitionContext(modeInfoLocation, blockSize, tileInfo, this.FrameInfo.ModeInfoRowCount);
partitionType = reader.ReadPartitionType(ctx);
}
else if (hasColumns)
{
int ctx = this.GetPartitionContext(modeInfoLocation, blockSize, tileLoc, this.FrameInfo.ModeInfoRowCount);
int ctx = this.GetPartitionContext(modeInfoLocation, blockSize, tileInfo, this.FrameInfo.ModeInfoRowCount);
bool splitOrHorizontal = reader.ReadSplitOrHorizontal(blockSize, ctx);
partitionType = splitOrHorizontal ? Av1PartitionType.Split : Av1PartitionType.Horizontal;
}
else if (hasRows)
{
int ctx = this.GetPartitionContext(modeInfoLocation, blockSize, tileLoc, this.FrameInfo.ModeInfoRowCount);
int ctx = this.GetPartitionContext(modeInfoLocation, blockSize, tileInfo, this.FrameInfo.ModeInfoRowCount);
bool splitOrVertical = reader.ReadSplitOrVertical(blockSize, ctx);
partitionType = splitOrVertical ? Av1PartitionType.Split : Av1PartitionType.Vertical;
}
@ -224,49 +222,59 @@ internal class Av1TileDecoder : IAv1TileDecoder
Point loc1 = new Point(modeInfoLocation.X, modeInfoLocation.Y + halfBlock4x4Size);
Point loc2 = new Point(modeInfoLocation.X + halfBlock4x4Size, modeInfoLocation.Y);
Point loc3 = new Point(modeInfoLocation.X + halfBlock4x4Size, modeInfoLocation.Y + halfBlock4x4Size);
this.ParsePartition(ref reader, modeInfoLocation, subSize, superblockInfo, tileLoc);
this.ParsePartition(ref reader, loc1, subSize, superblockInfo, tileLoc);
this.ParsePartition(ref reader, loc2, subSize, superblockInfo, tileLoc);
this.ParsePartition(ref reader, loc3, subSize, superblockInfo, tileLoc);
this.ParsePartition(ref reader, modeInfoLocation, subSize, superblockInfo, tileInfo);
this.ParsePartition(ref reader, loc1, subSize, superblockInfo, tileInfo);
this.ParsePartition(ref reader, loc2, subSize, superblockInfo, tileInfo);
this.ParsePartition(ref reader, loc3, subSize, superblockInfo, tileInfo);
break;
case Av1PartitionType.None:
this.ParseBlock(ref reader, rowIndex, columnIndex, subSize, superblockInfo, Av1PartitionType.None);
this.ParseBlock(ref reader, modeInfoLocation, subSize, superblockInfo, Av1PartitionType.None);
break;
case Av1PartitionType.Horizontal:
this.ParseBlock(ref reader, rowIndex, columnIndex, subSize, superblockInfo, Av1PartitionType.Horizontal);
this.ParseBlock(ref reader, modeInfoLocation, subSize, superblockInfo, Av1PartitionType.Horizontal);
if (hasRows)
{
this.ParseBlock(ref reader, rowIndex + halfBlock4x4Size, columnIndex, subSize, superblockInfo, Av1PartitionType.Horizontal);
Point halfLocation = new(columnIndex, rowIndex + halfBlock4x4Size);
this.ParseBlock(ref reader, halfLocation, subSize, superblockInfo, Av1PartitionType.Horizontal);
}
break;
case Av1PartitionType.Vertical:
this.ParseBlock(ref reader, rowIndex, columnIndex, subSize, superblockInfo, Av1PartitionType.Vertical);
this.ParseBlock(ref reader, modeInfoLocation, subSize, superblockInfo, Av1PartitionType.Vertical);
if (hasRows)
{
this.ParseBlock(ref reader, rowIndex, columnIndex + halfBlock4x4Size, subSize, superblockInfo, Av1PartitionType.Vertical);
Point halfLocation = new(columnIndex + halfBlock4x4Size, rowIndex);
this.ParseBlock(ref reader, halfLocation, subSize, superblockInfo, Av1PartitionType.Vertical);
}
break;
case Av1PartitionType.HorizontalA:
this.ParseBlock(ref reader, rowIndex, columnIndex, splitSize, superblockInfo, Av1PartitionType.HorizontalA);
this.ParseBlock(ref reader, rowIndex, columnIndex + halfBlock4x4Size, splitSize, superblockInfo, Av1PartitionType.HorizontalA);
this.ParseBlock(ref reader, rowIndex + halfBlock4x4Size, columnIndex + halfBlock4x4Size, subSize, superblockInfo, Av1PartitionType.HorizontalA);
this.ParseBlock(ref reader, modeInfoLocation, splitSize, superblockInfo, Av1PartitionType.HorizontalA);
Point locHorA1 = new(columnIndex + halfBlock4x4Size, rowIndex);
this.ParseBlock(ref reader, locHorA1, splitSize, superblockInfo, Av1PartitionType.HorizontalA);
Point locHorA2 = new(columnIndex, rowIndex + halfBlock4x4Size);
this.ParseBlock(ref reader, locHorA2, subSize, superblockInfo, Av1PartitionType.HorizontalA);
break;
case Av1PartitionType.HorizontalB:
this.ParseBlock(ref reader, rowIndex, columnIndex, subSize, superblockInfo, Av1PartitionType.HorizontalB);
this.ParseBlock(ref reader, rowIndex + halfBlock4x4Size, columnIndex, splitSize, superblockInfo, Av1PartitionType.HorizontalB);
this.ParseBlock(ref reader, rowIndex + halfBlock4x4Size, columnIndex + halfBlock4x4Size, splitSize, superblockInfo, Av1PartitionType.HorizontalB);
this.ParseBlock(ref reader, modeInfoLocation, subSize, superblockInfo, Av1PartitionType.HorizontalB);
Point locHorB1 = new(columnIndex + halfBlock4x4Size, rowIndex);
this.ParseBlock(ref reader, locHorB1, splitSize, superblockInfo, Av1PartitionType.HorizontalB);
Point locHorB2 = new(columnIndex + halfBlock4x4Size, rowIndex + halfBlock4x4Size);
this.ParseBlock(ref reader, locHorB2, splitSize, superblockInfo, Av1PartitionType.HorizontalB);
break;
case Av1PartitionType.VerticalA:
this.ParseBlock(ref reader, rowIndex, columnIndex, splitSize, superblockInfo, Av1PartitionType.VerticalA);
this.ParseBlock(ref reader, rowIndex + halfBlock4x4Size, columnIndex, splitSize, superblockInfo, Av1PartitionType.VerticalA);
this.ParseBlock(ref reader, rowIndex + halfBlock4x4Size, columnIndex + halfBlock4x4Size, subSize, superblockInfo, Av1PartitionType.VerticalA);
this.ParseBlock(ref reader, modeInfoLocation, splitSize, superblockInfo, Av1PartitionType.VerticalA);
Point locVertA1 = new(columnIndex, rowIndex + halfBlock4x4Size);
this.ParseBlock(ref reader, locVertA1, splitSize, superblockInfo, Av1PartitionType.VerticalA);
Point locVertA2 = new(columnIndex + halfBlock4x4Size, rowIndex);
this.ParseBlock(ref reader, locVertA2, subSize, superblockInfo, Av1PartitionType.VerticalA);
break;
case Av1PartitionType.VerticalB:
this.ParseBlock(ref reader, rowIndex, columnIndex, subSize, superblockInfo, Av1PartitionType.VerticalB);
this.ParseBlock(ref reader, rowIndex, columnIndex + halfBlock4x4Size, splitSize, superblockInfo, Av1PartitionType.VerticalB);
this.ParseBlock(ref reader, rowIndex + halfBlock4x4Size, columnIndex + halfBlock4x4Size, splitSize, superblockInfo, Av1PartitionType.VerticalB);
this.ParseBlock(ref reader, modeInfoLocation, subSize, superblockInfo, Av1PartitionType.VerticalB);
Point locVertB1 = new(columnIndex + halfBlock4x4Size, rowIndex + halfBlock4x4Size);
this.ParseBlock(ref reader, locVertB1, splitSize, superblockInfo, Av1PartitionType.VerticalB);
Point locVertB2 = new(columnIndex + halfBlock4x4Size, rowIndex + halfBlock4x4Size);
this.ParseBlock(ref reader, locVertB2, splitSize, superblockInfo, Av1PartitionType.VerticalB);
break;
case Av1PartitionType.Horizontal4:
for (int i = 0; i < 4; i++)
@ -277,7 +285,8 @@ internal class Av1TileDecoder : IAv1TileDecoder
break;
}
this.ParseBlock(ref reader, currentBlockRow, columnIndex, subSize, superblockInfo, Av1PartitionType.Horizontal4);
Point currentLocation = new(modeInfoLocation.X, currentBlockRow);
this.ParseBlock(ref reader, currentLocation, subSize, superblockInfo, Av1PartitionType.Horizontal4);
}
break;
@ -290,7 +299,8 @@ internal class Av1TileDecoder : IAv1TileDecoder
break;
}
this.ParseBlock(ref reader, rowIndex, currentBlockColumn, subSize, superblockInfo, Av1PartitionType.Vertical4);
Point currentLocation = new(currentBlockColumn, modeInfoLocation.Y);
this.ParseBlock(ref reader, currentLocation, subSize, superblockInfo, Av1PartitionType.Vertical4);
}
break;
@ -298,15 +308,17 @@ internal class Av1TileDecoder : IAv1TileDecoder
throw new NotImplementedException($"Partition type: {partitionType} is not supported.");
}
this.UpdatePartitionContext(new Point(columnIndex, rowIndex), tileLoc, superblockInfo, subSize, blockSize, partitionType);
this.UpdatePartitionContext(new Point(columnIndex, rowIndex), tileInfo, superblockInfo, subSize, blockSize, partitionType);
}
private void ParseBlock(ref Av1SymbolDecoder reader, int rowIndex, int columnIndex, Av1BlockSize blockSize, Av1SuperblockInfo superblockInfo, Av1PartitionType partitionType)
private void ParseBlock(ref Av1SymbolDecoder reader, Point modeInfoLocation, Av1BlockSize blockSize, Av1SuperblockInfo superblockInfo, Av1PartitionType partitionType)
{
int rowIndex = modeInfoLocation.Y;
int columnIndex = modeInfoLocation.X;
int block4x4Width = blockSize.Get4x4WideCount();
int block4x4Height = blockSize.Get4x4HighCount();
int planesCount = this.SequenceHeader.ColorConfig.ChannelCount;
Av1BlockModeInfo blockModeInfo = new(planesCount, blockSize);
Av1BlockModeInfo blockModeInfo = superblockInfo.GetModeInfo(modeInfoLocation);
bool hasChroma = this.HasChroma(rowIndex, columnIndex, blockSize);
Av1PartitionInfo partitionInfo = new(blockModeInfo, superblockInfo, hasChroma, partitionType);
partitionInfo.ColumnIndex = columnIndex;
@ -383,7 +395,8 @@ internal class Av1TileDecoder : IAv1TileDecoder
int columnChunk = columnIndex + (chunkX << 4);
int subBlockRow = rowChunk & superBlockMask;
int subBlockColumn = columnChunk & superBlockMask;
for (int plane = 0; plane < 1 + (this.HasChroma(rowIndex, columnIndex, blockSize) ? 2 : 0); plane++)
int endPlane = 1 + (this.HasChroma(rowIndex, columnIndex, blockSize) ? 2 : 0);
for (int plane = 0; plane < endPlane; plane++)
{
Av1TransformSize transformSize = this.FrameInfo.CodedLossless ? Av1TransformSize.Size4x4 : this.GetSize(plane, -1);
int stepX = transformSize.GetWidth() >> 2;
@ -426,7 +439,7 @@ internal class Av1TileDecoder : IAv1TileDecoder
private void TransformBlock(int plane, int baseX, int baseY, Av1TransformSize transformSize, int x, int y)
{
Av1PartitionInfo partitionInfo = new(new(1, Av1BlockSize.Invalid), new(this.FrameBuffer, default), false, Av1PartitionType.None);
Av1PartitionInfo partitionInfo = new(new(1, Av1BlockSize.Invalid, new Point(0, 0)), new(this.FrameBuffer, default), false, Av1PartitionType.None);
int startX = (baseX + 4) * x;
int startY = (baseY + 4) * y;
bool subsamplingX = this.SequenceHeader.ColorConfig.SubSamplingX;
@ -954,7 +967,8 @@ internal class Av1TileDecoder : IAv1TileDecoder
{
bool deltaQuantizerSignBit = reader.ReadLiteral(1) > 0;
int reducedDeltaQuantizerIndex = deltaQuantizerSignBit ? -deltaQuantizerAbsolute : deltaQuantizerAbsolute;
this.currentQuantizerIndex = Av1Math.Clip3(1, 255, this.currentQuantizerIndex + (reducedDeltaQuantizerIndex << this.deltaQuantizerResolution));
int deltaQuantizerResolution = this.FrameInfo.DeltaQParameters.Resolution;
this.currentQuantizerIndex = Av1Math.Clip3(1, 255, this.currentQuantizerIndex + (reducedDeltaQuantizerIndex << deltaQuantizerResolution));
partitionInfo.SuperblockInfo.SuperblockDeltaQ = this.currentQuantizerIndex;
}
}
@ -976,7 +990,7 @@ internal class Av1TileDecoder : IAv1TileDecoder
return xPos && yPos;
}*/
private int GetPartitionContext(Point location, Av1BlockSize blockSize, Av1TileLocation tileLoc, int superblockModeInfoRowCount)
private int GetPartitionContext(Point location, Av1BlockSize blockSize, Av1TileInfo tileLoc, int superblockModeInfoRowCount)
{
// Maximum partition point is 8x8. Offset the log value occordingly.
int aboveCtx = this.aboveNeighborContext.AbovePartitionWidth[location.X - tileLoc.ModeInfoColumnStart];
@ -987,7 +1001,7 @@ internal class Av1TileDecoder : IAv1TileDecoder
return (left * 2) + above + (blockSizeLog * PartitionProbabilitySet);
}
private void UpdatePartitionContext(Point modeInfoLocation, Av1TileLocation tileLoc, Av1SuperblockInfo superblockInfo, Av1BlockSize subSize, Av1BlockSize blockSize, Av1PartitionType partition)
private void UpdatePartitionContext(Point modeInfoLocation, Av1TileInfo tileLoc, Av1SuperblockInfo superblockInfo, Av1BlockSize subSize, Av1BlockSize blockSize, Av1PartitionType partition)
{
if (blockSize >= Av1BlockSize.Block8x8)
{

4
src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileLocation.cs → src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileInfo.cs

@ -5,9 +5,9 @@ using SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit;
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Symbol;
internal class Av1TileLocation
internal class Av1TileInfo
{
public Av1TileLocation(int row, int column, ObuFrameHeader frameInfo)
public Av1TileInfo(int row, int column, ObuFrameHeader frameInfo)
{
this.SetTileRow(frameInfo.TilesInfo, frameInfo.ModeInfoRowCount, row);
this.SetTileColumn(frameInfo.TilesInfo, frameInfo.ModeInfoColumnCount, column);
Loading…
Cancel
Save