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]; 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; 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) public Av1SuperblockInfo GetSuperblock(Point index)
{ {
Span<Av1SuperblockInfo> span = this.superblockInfos; 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) 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 bh = blockSize.Get4x4HighCount();
int value = Av1PartitionContext.GetLeftContext(subSize); int value = Av1PartitionContext.GetLeftContext(subSize);
DebugGuard.MustBeLessThanOrEqualTo(startIndex, this.LeftTransformHeight.Length - bh, nameof(startIndex)); 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) 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 transformHeight = transformSize.GetHeight();
int n4h = blockSize.Get4x4HighCount(); int n4h = blockSize.Get4x4HighCount();
if (skip) if (skip)

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

@ -18,6 +18,11 @@ internal class Av1SuperblockInfo
/// </summary> /// </summary>
public Point Position { get; } 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 ref int SuperblockDeltaQ => ref this.frameInfo.GetDeltaQuantizationIndex(this.Position);
public Av1BlockModeInfo SuperblockModeInfo => this.GetModeInfo(new Point(0, 0)); 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 txsWide = planeBlockSize.GetWidth() >> 2;
int txsHigh = planeBlockSize.GetHeight() >> 2; int txsHigh = planeBlockSize.GetHeight() >> 2;
int aboveOffset = (partitionInfo.ColumnIndex - tileInfo.ModeInfoColumnStart) >> subX; 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.aboveNeighborContext.ClearContext(i, aboveOffset, txsWide);
this.leftNeighborContext.ClearContext(i, leftOffset, txsHigh); this.leftNeighborContext.ClearContext(i, leftOffset, txsHigh);
} }
@ -1267,7 +1267,7 @@ internal class Av1TileReader : IAv1TileReader
Av1TransformSize maxTransformSize = partitionInfo.ModeInfo.BlockSize.GetMaximumTransformSize(); Av1TransformSize maxTransformSize = partitionInfo.ModeInfo.BlockSize.GetMaximumTransformSize();
int aboveWidth = this.aboveNeighborContext.AboveTransformWidth[partitionInfo.ColumnIndex - tileInfo.ModeInfoColumnStart]; int aboveWidth = this.aboveNeighborContext.AboveTransformWidth[partitionInfo.ColumnIndex - tileInfo.ModeInfoColumnStart];
int above = (aboveWidth >= maxTransformSize.GetWidth()) ? 1 : 0; 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; int left = (leftHeight >= maxTransformSize.GetHeight()) ? 1 : 0;
bool hasAbove = partitionInfo.AvailableAbove; bool hasAbove = partitionInfo.AvailableAbove;
bool hasLeft = partitionInfo.AvailableLeft; bool hasLeft = partitionInfo.AvailableLeft;
@ -1880,7 +1880,7 @@ internal class Av1TileReader : IAv1TileReader
{ {
// Maximum partition point is 8x8. Offset the log value occordingly. // Maximum partition point is 8x8. Offset the log value occordingly.
int aboveCtx = this.aboveNeighborContext.AbovePartitionWidth[location.X - tileInfo.ModeInfoColumnStart]; 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 blockSizeLog = blockSize.Get4x4WidthLog2() - Av1BlockSize.Block8x8.Get4x4WidthLog2();
int above = (aboveCtx >> blockSizeLog) & 0x1; int above = (aboveCtx >> blockSizeLog) & 0x1;
int left = (leftCtx >> 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;
using SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; using SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit;
using SixLabors.ImageSharp.Formats.Heif.Av1.Pipeline;
using SixLabors.ImageSharp.Formats.Heif.Av1.Tiling; using SixLabors.ImageSharp.Formats.Heif.Av1.Tiling;
namespace SixLabors.ImageSharp.Tests.Formats.Heif.Av1; namespace SixLabors.ImageSharp.Tests.Formats.Heif.Av1;
@ -12,9 +11,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Heif.Av1;
public class Av1TilingTests public class Av1TilingTests
{ {
[Theory] [Theory]
[InlineData(TestImages.Heif.XnConvert, 0x010E, 0x03CC, 18)] [InlineData(TestImages.Heif.XnConvert, 0x010E, 0x03CC, 18, 16)]
// [InlineData(TestImages.Heif.Orange4x4, 0x010E, 0x001d, 21)] [InlineData(TestImages.Heif.Orange4x4, 0x010E, 0x001d, 21, 1)]
public void ReadFirstTile(string filename, int dataOffset, int dataSize, int tileOffset) public void ReadFirstTile(string filename, int dataOffset, int dataSize, int tileOffset, int superblockCount)
{ {
// Assign // Assign
string filePath = Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, filename); string filePath = Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, filename);
@ -27,7 +26,7 @@ public class Av1TilingTests
obuReader.ReadAll(ref bitStreamReader, dataSize, stub); obuReader.ReadAll(ref bitStreamReader, dataSize, stub);
Av1FrameBuffer frameBuffer = new(Configuration.Default, obuReader.SequenceHeader, Av1ColorFormat.Yuv444, false); Av1FrameBuffer frameBuffer = new(Configuration.Default, obuReader.SequenceHeader, Av1ColorFormat.Yuv444, false);
Av1FrameInfo frameInfo = new(obuReader.SequenceHeader); 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); Av1TileReader tileReader = new(Configuration.Default, obuReader.SequenceHeader, obuReader.FrameHeader, frameDecoder);
// Act // Act
@ -35,5 +34,6 @@ public class Av1TilingTests
// Assert // Assert
Assert.Equal(dataSize * 8, bitStreamReader.BitPosition); Assert.Equal(dataSize * 8, bitStreamReader.BitPosition);
Assert.Equal(superblockCount, frameDecoder.SuperblockCount);
} }
} }

Loading…
Cancel
Save