Browse Source

Prune ITileDecoder interface

pull/2633/head
Ynse Hoornenborg 2 years ago
parent
commit
c771350559
  1. 19
      src/ImageSharp/Formats/Heif/Av1/Av1Decoder.cs
  2. 12
      src/ImageSharp/Formats/Heif/Av1/IAv1TileDecoder.cs
  3. 2
      src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs
  4. 93
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileDecoder.cs

19
src/ImageSharp/Formats/Heif/Av1/Av1Decoder.cs

@ -25,16 +25,15 @@ internal class Av1Decoder : IAv1TileDecoder
this.frameBuffer = this.tileDecoder?.FrameBuffer;
}
public void StartDecodeTiles()
public void DecodeTile(Span<byte> tileData, int tileNum)
{
this.SequenceHeader = this.obuReader.SequenceHeader;
this.FrameHeader = this.obuReader.FrameHeader;
this.tileDecoder = new Av1TileDecoder(this.SequenceHeader!, this.FrameHeader!);
if (this.tileDecoder == null)
{
this.SequenceHeader = this.obuReader.SequenceHeader;
this.FrameHeader = this.obuReader.FrameHeader;
this.tileDecoder = new Av1TileDecoder(this.SequenceHeader!, this.FrameHeader!);
}
this.tileDecoder.DecodeTile(tileData, tileNum);
}
public void DecodeTile(Span<byte> tileData, int tileNum)
=> this.tileDecoder!.DecodeTile(tileData, tileNum);
public void FinishDecodeTiles(bool doCdef, bool doLoopRestoration)
=> this.tileDecoder!.FinishDecodeTiles(doCdef, doLoopRestoration);
}

12
src/ImageSharp/Formats/Heif/Av1/IAv1TileDecoder.cs

@ -8,11 +8,6 @@ namespace SixLabors.ImageSharp.Formats.Heif.Av1;
/// </summary>
internal interface IAv1TileDecoder
{
/// <summary>
/// Start decoding all tiles of a frame.
/// </summary>
void StartDecodeTiles();
/// <summary>
/// Decode a single tile.
/// </summary>
@ -21,11 +16,4 @@ internal interface IAv1TileDecoder
/// </param>
/// <param name="tileNum">The index of the tile that is to be decoded.</param>
void DecodeTile(Span<byte> tileData, int tileNum);
/// <summary>
/// Finshed decoding all tiles of a frame.
/// </summary>
/// <param name="doCdef">Apply the CDF filter.</param>
/// <param name="doLoopRestoration">Apply the loop filters.</param>
void FinishDecodeTiles(bool doCdef, bool doLoopRestoration);
}

2
src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs

@ -1272,7 +1272,7 @@ internal class ObuReader
return;
}
decoder.FinishDecodeTiles(doCdef, doLoopRestoration);
// TODO: Share doCdef and doLoopRestoration
}
/// <summary>

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

@ -24,18 +24,17 @@ internal class Av1TileDecoder : IAv1TileDecoder
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 bool[][][] blockDecoded = [];
private int[][] referenceSgrXqd = [];
private int[][][] referenceLrWiener = [];
private readonly Av1ParseAboveNeighbor4x4Context aboveNeighborContext;
private readonly Av1ParseLeftNeighbor4x4Context leftNeighborContext;
private int currentQuantizerIndex;
private int[][] segmentIds = [];
private readonly int[][] segmentIds = [];
private int deltaLoopFilterResolution = -1;
private bool readDeltas;
private int[][] tusCount;
private int[] firstTransformOffset = new int[2];
private int[] coefficientIndex = [];
private readonly bool readDeltas;
private readonly int[][] tusCount;
private readonly int[] firstTransformOffset = new int[2];
private readonly int[] coefficientIndex = [];
public Av1TileDecoder(ObuSequenceHeader sequenceHeader, ObuFrameHeader frameInfo)
{
@ -55,9 +54,9 @@ internal class Av1TileDecoder : IAv1TileDecoder
// Hard code number of threads to 1 for now.
int planesCount = sequenceHeader.ColorConfig.IsMonochrome ? 1 : Av1Constants.MaxPlanes;
int superblockColumnCount =
AlignPowerOfTwo(sequenceHeader.MaxFrameWidth, sequenceHeader.SuperBlockSizeLog2) >> sequenceHeader.SuperBlockSizeLog2;
Av1Math.AlignPowerOf2(sequenceHeader.MaxFrameWidth, sequenceHeader.SuperBlockSizeLog2) >> sequenceHeader.SuperBlockSizeLog2;
int modeInfoWideColumnCount = superblockColumnCount * sequenceHeader.ModeInfoSize;
modeInfoWideColumnCount = AlignPowerOfTwo(modeInfoWideColumnCount, sequenceHeader.SuperBlockSizeLog2 - 2);
modeInfoWideColumnCount = Av1Math.AlignPowerOf2(modeInfoWideColumnCount, sequenceHeader.SuperBlockSizeLog2 - 2);
this.aboveNeighborContext = new Av1ParseAboveNeighbor4x4Context(planesCount, modeInfoWideColumnCount);
this.leftNeighborContext = new Av1ParseLeftNeighbor4x4Context(planesCount, sequenceHeader.ModeInfoSize);
this.tusCount = new int[Av1Constants.MaxPlanes][];
@ -98,7 +97,6 @@ internal class Av1TileDecoder : IAv1TileDecoder
}
}
// TODO: Initialize this.blockDecoded
Av1TileInfo tileInfo = new(tileRowIndex, tileColumnIndex, this.FrameInfo);
Av1BlockSize superBlockSize = this.SequenceHeader.Use128x128SuperBlock ? Av1BlockSize.Block128x128 : Av1BlockSize.Block64x64;
int superBlock4x4Size = superBlockSize.Get4x4WideCount();
@ -115,54 +113,23 @@ internal class Av1TileDecoder : IAv1TileDecoder
// this.ClearBlockDecodedFlags(modeInfoLocation, superBlock4x4Size);
Point modeInfoLocation = new(column, row);
this.FrameBuffer.ClearCdef(superblockPosition);
this.firstTransformOffset[0] = 0;
this.firstTransformOffset[1] = 0;
this.ReadLoopRestoration(modeInfoLocation, superBlockSize);
this.ParsePartition(ref reader, modeInfoLocation, superBlockSize, superblockInfo, tileInfo);
}
}
}
private static int AlignPowerOfTwo(int value, int n) => (value + ((1 << n) - 1)) & ~((1 << n) - 1);
private void ClearLoopFilterDelta()
=> this.FrameBuffer.ClearDeltaLoopFilter();
/// <summary>
/// 5.11.3. Clear block decoded flags function.
/// </summary>
private void ClearBlockDecodedFlags(Point modeInfoLocation, int superBlock4x4Size)
private static void ClearBlockDecodedFlags(Point modeInfoLocation, int superBlock4x4Size)
{
int planesCount = this.SequenceHeader.ColorConfig.ChannelCount;
this.blockDecoded = new bool[planesCount][][];
for (int plane = 0; plane < planesCount; plane++)
{
int subX = plane > 0 && this.SequenceHeader.ColorConfig.SubSamplingX ? 1 : 0;
int subY = plane > 0 && this.SequenceHeader.ColorConfig.SubSamplingY ? 1 : 0;
int superBlock4x4Width = (this.FrameInfo.ModeInfoColumnCount - modeInfoLocation.X) >> subX;
int superBlock4x4Height = (this.FrameInfo.ModeInfoRowCount - modeInfoLocation.Y) >> subY;
this.blockDecoded[plane] = new bool[(superBlock4x4Size >> subY) + 3][];
for (int y = -1; y <= superBlock4x4Size >> subY; y++)
{
this.blockDecoded[plane][y] = new bool[(superBlock4x4Size >> subX) + 3];
for (int x = -1; x <= superBlock4x4Size >> subX; x++)
{
if (y < 0 && x < superBlock4x4Width)
{
this.blockDecoded[plane][y][x] = true;
}
else if (x < 0 && y < superBlock4x4Height)
{
this.blockDecoded[plane][y][x] = true;
}
else
{
this.blockDecoded[plane][y][x] = false;
}
}
}
int lastIndex = this.blockDecoded[plane][(superBlock4x4Size >> subY) - 1].Length - 1;
this.blockDecoded[plane][(superBlock4x4Size >> subY) - 1][lastIndex] = false;
}
// Nothing to do here.
}
private void ReadLoopRestoration(Point modeInfoLocation, Av1BlockSize superBlockSize)
@ -178,16 +145,6 @@ internal class Av1TileDecoder : IAv1TileDecoder
}
}
public void StartDecodeTiles()
{
// TODO: Implement
}
public void FinishDecodeTiles(bool doCdef, bool doLoopRestoration)
{
// TODO: Implement
}
/// <summary>
/// 5.11.4. Decode partition syntax.
/// </summary>
@ -200,8 +157,6 @@ internal class Av1TileDecoder : IAv1TileDecoder
return;
}
bool availableUp = this.IsInside(rowIndex - 1, columnIndex);
bool availableLeft = this.IsInside(rowIndex, columnIndex - 1);
int block4x4Size = blockSize.Get4x4WideCount();
int halfBlock4x4Size = block4x4Size >> 1;
int quarterBlock4x4Size = halfBlock4x4Size >> 1;
@ -235,9 +190,9 @@ internal class Av1TileDecoder : IAv1TileDecoder
switch (partitionType)
{
case Av1PartitionType.Split:
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);
Point loc1 = new(modeInfoLocation.X, modeInfoLocation.Y + halfBlock4x4Size);
Point loc2 = new(modeInfoLocation.X + halfBlock4x4Size, modeInfoLocation.Y);
Point loc3 = new(modeInfoLocation.X + halfBlock4x4Size, modeInfoLocation.Y + halfBlock4x4Size);
this.ParsePartition(ref reader, modeInfoLocation, subSize, superblockInfo, tileInfo);
this.ParsePartition(ref reader, loc1, subSize, superblockInfo, tileInfo);
this.ParsePartition(ref reader, loc2, subSize, superblockInfo, tileInfo);
@ -257,7 +212,7 @@ internal class Av1TileDecoder : IAv1TileDecoder
break;
case Av1PartitionType.Vertical:
this.ParseBlock(ref reader, modeInfoLocation, subSize, superblockInfo, tileInfo, Av1PartitionType.Vertical);
if (hasRows)
if (hasColumns)
{
Point halfLocation = new(columnIndex + halfBlock4x4Size, rowIndex);
this.ParseBlock(ref reader, halfLocation, subSize, superblockInfo, tileInfo, Av1PartitionType.Vertical);
@ -273,7 +228,7 @@ internal class Av1TileDecoder : IAv1TileDecoder
break;
case Av1PartitionType.HorizontalB:
this.ParseBlock(ref reader, modeInfoLocation, subSize, superblockInfo, tileInfo, Av1PartitionType.HorizontalB);
Point locHorB1 = new(columnIndex + halfBlock4x4Size, rowIndex);
Point locHorB1 = new(columnIndex, rowIndex + halfBlock4x4Size);
this.ParseBlock(ref reader, locHorB1, splitSize, superblockInfo, tileInfo, Av1PartitionType.HorizontalB);
Point locHorB2 = new(columnIndex + halfBlock4x4Size, rowIndex + halfBlock4x4Size);
this.ParseBlock(ref reader, locHorB2, splitSize, superblockInfo, tileInfo, Av1PartitionType.HorizontalB);
@ -287,7 +242,7 @@ internal class Av1TileDecoder : IAv1TileDecoder
break;
case Av1PartitionType.VerticalB:
this.ParseBlock(ref reader, modeInfoLocation, subSize, superblockInfo, tileInfo, Av1PartitionType.VerticalB);
Point locVertB1 = new(columnIndex + halfBlock4x4Size, rowIndex + halfBlock4x4Size);
Point locVertB1 = new(columnIndex + halfBlock4x4Size, rowIndex);
this.ParseBlock(ref reader, locVertB1, splitSize, superblockInfo, tileInfo, Av1PartitionType.VerticalB);
Point locVertB2 = new(columnIndex + halfBlock4x4Size, rowIndex + halfBlock4x4Size);
this.ParseBlock(ref reader, locVertB2, splitSize, superblockInfo, tileInfo, Av1PartitionType.VerticalB);
@ -336,7 +291,9 @@ internal class Av1TileDecoder : IAv1TileDecoder
int planesCount = this.SequenceHeader.ColorConfig.ChannelCount;
Av1BlockModeInfo blockModeInfo = superblockInfo.GetModeInfo(modeInfoLocation);
blockModeInfo.PartitionType = partitionType;
bool hasChroma = this.HasChroma(rowIndex, columnIndex, blockSize);
blockModeInfo.FirstTransformLocation[0] = this.firstTransformOffset[0];
blockModeInfo.FirstTransformLocation[1] = this.firstTransformOffset[1];
bool hasChroma = this.HasChroma(modeInfoLocation, blockSize);
Av1PartitionInfo partitionInfo = new(blockModeInfo, superblockInfo, hasChroma, partitionType);
partitionInfo.ColumnIndex = columnIndex;
partitionInfo.RowIndex = rowIndex;
@ -490,14 +447,14 @@ internal class Av1TileDecoder : IAv1TileDecoder
}
}
private bool HasChroma(int rowIndex, int columnIndex, Av1BlockSize blockSize)
private bool HasChroma(Point modeInfoLocation, Av1BlockSize blockSize)
{
int bw = blockSize.Get4x4WideCount();
int bh = blockSize.Get4x4HighCount();
int blockWide = blockSize.Get4x4WideCount();
int blockHigh = blockSize.Get4x4HighCount();
bool subX = this.SequenceHeader.ColorConfig.SubSamplingX;
bool subY = this.SequenceHeader.ColorConfig.SubSamplingY;
bool hasChroma = ((rowIndex & 0x01) != 0 || (bh & 0x01) == 0 || !subY) &&
((columnIndex & 0x01) != 0 || (bw & 0x01) == 0 || !subX);
bool hasChroma = ((modeInfoLocation.Y & 0x01) != 0 || (blockHigh & 0x01) == 0 || !subY) &&
((modeInfoLocation.X & 0x01) != 0 || (blockWide & 0x01) == 0 || !subX);
return hasChroma;
}

Loading…
Cancel
Save