Browse Source

Superblock info exposes its mode info position

pull/2633/head
Ynse Hoornenborg 2 years ago
parent
commit
1f2e05f74c
  1. 8
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameInfo.cs
  2. 4
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1ParseLeftNeighbor4x4Context.cs
  3. 5
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1SuperblockInfo.cs
  4. 6
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileReader.cs
  5. 17
      tests/ImageSharp.Tests/Formats/Heif/Av1/Av1FrameDecoderStub.cs
  6. 10
      tests/ImageSharp.Tests/Formats/Heif/Av1/Av1TilingTests.cs

8
src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameInfo.cs

@ -82,8 +82,16 @@ internal partial class Av1FrameInfo
this.deltaLoopFilter = new int[superblockCount << this.deltaLoopFactorLog2];
}
/// <summary>
/// Gets the number of mode info blocks in a single superblock.
/// </summary>
public int ModeInfoCount => this.modeInfos.Length;
/// <summary>
/// Gets the Width or height of a single superblock, counted in mode info blocks.
/// </summary>
public int SuperblockModeInfoSize => this.modeInfoSizePerSuperblock;
public Av1SuperblockInfo GetSuperblock(Point index)
{
Span<Av1SuperblockInfo> span = this.superblockInfos;

4
src/ImageSharp/Formats/Heif/Av1/Tiling/Av1ParseLeftNeighbor4x4Context.cs

@ -66,7 +66,7 @@ internal class Av1ParseLeftNeighbor4x4Context
public void UpdatePartition(Point modeInfoLocation, Av1SuperblockInfo superblockInfo, Av1BlockSize subSize, Av1BlockSize blockSize)
{
int startIndex = (modeInfoLocation.Y - superblockInfo.Position.Y) & Av1PartitionContext.Mask;
int startIndex = (modeInfoLocation.Y - superblockInfo.ModeInfoPosition.Y) & Av1PartitionContext.Mask;
int bh = blockSize.Get4x4HighCount();
int value = Av1PartitionContext.GetLeftContext(subSize);
DebugGuard.MustBeLessThanOrEqualTo(startIndex, this.LeftTransformHeight.Length - bh, nameof(startIndex));
@ -75,7 +75,7 @@ internal class Av1ParseLeftNeighbor4x4Context
public void UpdateTransformation(Point modeInfoLocation, Av1SuperblockInfo superblockInfo, Av1TransformSize transformSize, Av1BlockSize blockSize, bool skip)
{
int startIndex = modeInfoLocation.Y - superblockInfo.Position.Y;
int startIndex = modeInfoLocation.Y - superblockInfo.ModeInfoPosition.Y;
int transformHeight = transformSize.GetHeight();
int n4h = blockSize.Get4x4HighCount();
if (skip)

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

@ -18,6 +18,11 @@ internal class Av1SuperblockInfo
/// </summary>
public Point Position { get; }
/// <summary>
/// Gets the position of this superblock inside the tile, counted in mode info blocks (of 4x4 pixels).
/// </summary>
public Point ModeInfoPosition => this.Position * this.frameInfo.SuperblockModeInfoSize;
public ref int SuperblockDeltaQ => ref this.frameInfo.GetDeltaQuantizationIndex(this.Position);
public Av1BlockModeInfo SuperblockModeInfo => this.GetModeInfo(new Point(0, 0));

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

@ -372,7 +372,7 @@ internal class Av1TileReader : IAv1TileReader
int txsWide = planeBlockSize.GetWidth() >> 2;
int txsHigh = planeBlockSize.GetHeight() >> 2;
int aboveOffset = (partitionInfo.ColumnIndex - tileInfo.ModeInfoColumnStart) >> subX;
int leftOffset = (partitionInfo.RowIndex - partitionInfo.SuperblockInfo.Position.Y) >> subY;
int leftOffset = (partitionInfo.RowIndex - partitionInfo.SuperblockInfo.ModeInfoPosition.Y) >> subY;
this.aboveNeighborContext.ClearContext(i, aboveOffset, txsWide);
this.leftNeighborContext.ClearContext(i, leftOffset, txsHigh);
}
@ -1267,7 +1267,7 @@ internal class Av1TileReader : IAv1TileReader
Av1TransformSize maxTransformSize = partitionInfo.ModeInfo.BlockSize.GetMaximumTransformSize();
int aboveWidth = this.aboveNeighborContext.AboveTransformWidth[partitionInfo.ColumnIndex - tileInfo.ModeInfoColumnStart];
int above = (aboveWidth >= maxTransformSize.GetWidth()) ? 1 : 0;
int leftHeight = this.leftNeighborContext.LeftTransformHeight[partitionInfo.RowIndex - superblockInfo.Position.Y];
int leftHeight = this.leftNeighborContext.LeftTransformHeight[partitionInfo.RowIndex - superblockInfo.ModeInfoPosition.Y];
int left = (leftHeight >= maxTransformSize.GetHeight()) ? 1 : 0;
bool hasAbove = partitionInfo.AvailableAbove;
bool hasLeft = partitionInfo.AvailableLeft;
@ -1880,7 +1880,7 @@ internal class Av1TileReader : IAv1TileReader
{
// Maximum partition point is 8x8. Offset the log value occordingly.
int aboveCtx = this.aboveNeighborContext.AbovePartitionWidth[location.X - tileInfo.ModeInfoColumnStart];
int leftCtx = this.leftNeighborContext.LeftPartitionHeight[(location.Y - superblockInfo.Position.Y) & Av1PartitionContext.Mask];
int leftCtx = this.leftNeighborContext.LeftPartitionHeight[(location.Y - superblockInfo.ModeInfoPosition.Y) & Av1PartitionContext.Mask];
int blockSizeLog = blockSize.Get4x4WidthLog2() - Av1BlockSize.Block8x8.Get4x4WidthLog2();
int above = (aboveCtx >> blockSizeLog) & 0x1;
int left = (leftCtx >> blockSizeLog) & 0x1;

17
tests/ImageSharp.Tests/Formats/Heif/Av1/Av1FrameDecoderStub.cs

@ -0,0 +1,17 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.Formats.Heif.Av1.Pipeline;
using SixLabors.ImageSharp.Formats.Heif.Av1.Tiling;
namespace SixLabors.ImageSharp.Tests.Formats.Heif.Av1;
internal class Av1FrameDecoderStub : IAv1FrameDecoder
{
private readonly List<Av1SuperblockInfo> superblocks = [];
public void DecodeSuperblock(Point modeInfoPosition, Av1SuperblockInfo superblockInfo, Av1TileInfo tileInfo)
=> this.superblocks.Add(superblockInfo);
public int SuperblockCount => this.superblocks.Count;
}

10
tests/ImageSharp.Tests/Formats/Heif/Av1/Av1TilingTests.cs

@ -3,7 +3,6 @@
using SixLabors.ImageSharp.Formats.Heif.Av1;
using SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit;
using SixLabors.ImageSharp.Formats.Heif.Av1.Pipeline;
using SixLabors.ImageSharp.Formats.Heif.Av1.Tiling;
namespace SixLabors.ImageSharp.Tests.Formats.Heif.Av1;
@ -12,9 +11,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Heif.Av1;
public class Av1TilingTests
{
[Theory]
[InlineData(TestImages.Heif.XnConvert, 0x010E, 0x03CC, 18)]
// [InlineData(TestImages.Heif.Orange4x4, 0x010E, 0x001d, 21)]
public void ReadFirstTile(string filename, int dataOffset, int dataSize, int tileOffset)
[InlineData(TestImages.Heif.XnConvert, 0x010E, 0x03CC, 18, 16)]
[InlineData(TestImages.Heif.Orange4x4, 0x010E, 0x001d, 21, 1)]
public void ReadFirstTile(string filename, int dataOffset, int dataSize, int tileOffset, int superblockCount)
{
// Assign
string filePath = Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, filename);
@ -27,7 +26,7 @@ public class Av1TilingTests
obuReader.ReadAll(ref bitStreamReader, dataSize, stub);
Av1FrameBuffer frameBuffer = new(Configuration.Default, obuReader.SequenceHeader, Av1ColorFormat.Yuv444, false);
Av1FrameInfo frameInfo = new(obuReader.SequenceHeader);
Av1FrameDecoder frameDecoder = new(obuReader.SequenceHeader, obuReader.FrameHeader, frameInfo, frameBuffer);
Av1FrameDecoderStub frameDecoder = new();
Av1TileReader tileReader = new(Configuration.Default, obuReader.SequenceHeader, obuReader.FrameHeader, frameDecoder);
// Act
@ -35,5 +34,6 @@ public class Av1TilingTests
// Assert
Assert.Equal(dataSize * 8, bitStreamReader.BitPosition);
Assert.Equal(superblockCount, frameDecoder.SuperblockCount);
}
}

Loading…
Cancel
Save