Browse Source

Extend AV1 partition search through 32x32

pull/2633/head
James Jackson-South 4 weeks ago
parent
commit
aac829723a
  1. 8
      HEIF_IMPLEMENTATION_PLAN.md
  2. 5
      src/ImageSharp/Formats/Heif/Av1/Pipeline/Av1EncoderModeDecisionWorkspace.cs
  3. 5
      src/ImageSharp/Formats/Heif/Av1/Pipeline/Av1IntraSuperblockEncoder.ModeDecision.cs
  4. 40
      tests/ImageSharp.Tests/Formats/Heif/Av1/Av1EncoderFrameTests.cs

8
HEIF_IMPLEMENTATION_PLAN.md

File diff suppressed because one or more lines are too long

5
src/ImageSharp/Formats/Heif/Av1/Pipeline/Av1EncoderModeDecisionWorkspace.cs

@ -18,7 +18,7 @@ internal readonly ref struct Av1EncoderModeDecisionWorkspace<TSample>
/// <summary>
/// The largest coding-block dimension evaluated directly by the current partition search.
/// </summary>
public const int MaximumBlockDimension = 16;
public const int MaximumBlockDimension = 32;
/// <summary>
/// The maximum number of samples in one directly evaluated coding block.
@ -49,8 +49,7 @@ internal readonly ref struct Av1EncoderModeDecisionWorkspace<TSample>
2 * (MaximumBlockDimension >> Av1Constants.ModeInfoSizeLog2) * sizeof(byte) / sizeof(int);
private const int TransientStorageOffset = TransformContextStorageOffset + TransformContextStorageLength;
private const int ChromaFromLumaSampleCount =
Av1ChromaFromLumaContext.BufferLine * MaximumBlockDimension;
private const int ChromaFromLumaSampleCount = Av1ChromaFromLumaContext.BufferLength;
private const int ChromaFromLumaSampleStorageLength = ChromaFromLumaSampleCount * sizeof(short) / sizeof(int);
private const int ChromaFromLumaBlueRateOffset = ChromaFromLumaSampleStorageLength;

5
src/ImageSharp/Formats/Heif/Av1/Pipeline/Av1IntraSuperblockEncoder.ModeDecision.cs

@ -183,7 +183,10 @@ internal static partial class Av1IntraSuperblockEncoder
Av1BlockSize blockSize,
Av1PartitionType preparedPartition)
{
if (blockSize is not Av1BlockSize.Block8x8 and not Av1BlockSize.Block16x16)
bool searchPartition = blockSize is Av1BlockSize.Block8x8 or Av1BlockSize.Block16x16 ||
(this.effort == 10 && blockSize == Av1BlockSize.Block32x32);
if (!searchPartition)
{
return preparedPartition;
}

40
tests/ImageSharp.Tests/Formats/Heif/Av1/Av1EncoderFrameTests.cs

@ -274,6 +274,46 @@ public class Av1EncoderFrameTests
Assert.Equal(new Size(Size, Size), decoded.Size);
}
[Fact]
public void EncodeEffortTenSelectsThirtyTwoByThirtyTwoBlocks()
{
const int Size = 64;
using Image<Rgba32> source = new(Size, Size);
for (int y = 0; y < Size; y++)
{
Span<Rgba32> row = source.Frames.RootFrame.PixelBuffer.DangerousGetRowSpan(y);
for (int x = 0; x < Size; x++)
{
row[x] = new Rgba32(128, 128, 128);
}
}
using MemoryStream stream = new();
_ = Av1FrameEncoder.Encode(
Configuration.Default,
source.Frames.RootFrame,
stream,
CreateColorConfig(Av1BitDepth.EightBit, Av1ColorFormat.Yuv400),
qIndex: 4,
effort: 10);
byte[] payload = stream.ToArray();
using Av1Decoder decoder = new(Configuration.Default);
using Image<Rgba32> decoded = decoder.Decode<Rgba32>(payload);
Av1FrameInfo frameInfo = Assert.IsType<Av1FrameInfo>(decoder.FrameInfo);
for (int modeInfoY = 0; modeInfoY < 16; modeInfoY++)
{
for (int modeInfoX = 0; modeInfoX < 16; modeInfoX++)
{
Assert.Equal(
Av1BlockSize.Block32x32,
frameInfo.GetModeInfoAt(new Point(modeInfoX, modeInfoY)).BlockSize);
}
}
Assert.Equal(new Size(Size, Size), decoded.Size);
}
[Theory]
[InlineData(EightBit)]
[InlineData(TenBit)]

Loading…
Cancel
Save