Browse Source

Decode superblock immediately after parsing it

pull/2633/head
Ynse Hoornenborg 2 years ago
parent
commit
a33bc1895a
  1. 8
      src/ImageSharp/Formats/Heif/Av1/Av1Decoder.cs
  2. 4
      src/ImageSharp/Formats/Heif/Av1/Pipeline/Av1FrameDecoder.cs
  3. 20
      src/ImageSharp/Formats/Heif/Av1/Pipeline/IAv1FrameDecoder.cs
  4. 23
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileReader.cs
  5. 6
      tests/ImageSharp.Tests/Formats/Heif/Av1/Av1TilingTests.cs

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

@ -48,7 +48,13 @@ internal class Av1Decoder : IAv1TileReader
{
this.SequenceHeader = this.obuReader.SequenceHeader;
this.FrameHeader = this.obuReader.FrameHeader;
this.tileReader = new Av1TileReader(this.configuration, this.SequenceHeader!, this.FrameHeader!);
Guard.NotNull(this.tileReader, nameof(this.tileReader));
Guard.NotNull(this.SequenceHeader, nameof(this.SequenceHeader));
Guard.NotNull(this.FrameHeader, nameof(this.FrameHeader));
this.FrameInfo = new(this.SequenceHeader);
this.FrameBuffer = new(this.configuration, this.SequenceHeader, this.SequenceHeader.ColorConfig.GetColorFormat(), false);
this.frameDecoder = new(this.SequenceHeader, this.FrameHeader, this.FrameInfo, this.FrameBuffer);
this.tileReader = new Av1TileReader(this.configuration, this.SequenceHeader, this.FrameHeader, this.frameDecoder);
}
this.tileReader.ReadTile(tileData, tileNum);

4
src/ImageSharp/Formats/Heif/Av1/Pipeline/Av1FrameDecoder.cs

@ -8,7 +8,7 @@ using SixLabors.ImageSharp.Formats.Heif.Av1.Transform;
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Pipeline;
internal class Av1FrameDecoder
internal class Av1FrameDecoder : IAv1FrameDecoder
{
private readonly ObuSequenceHeader sequenceHeader;
private readonly ObuFrameHeader frameHeader;
@ -108,7 +108,7 @@ internal class Av1FrameDecoder
/// <summary>
/// SVT: svt_aom_decode_super_block
/// </summary>
private void DecodeSuperblock(Point modeInfoPosition, Av1SuperblockInfo superblockInfo, Av1TileInfo tileInfo)
public void DecodeSuperblock(Point modeInfoPosition, Av1SuperblockInfo superblockInfo, Av1TileInfo tileInfo)
{
this.blockDecoder.UpdateSuperblock(superblockInfo);
this.inverseQuantizer.UpdateDequant(this.deQuants, superblockInfo);

20
src/ImageSharp/Formats/Heif/Av1/Pipeline/IAv1FrameDecoder.cs

@ -0,0 +1,20 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.Formats.Heif.Av1.Tiling;
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Pipeline;
/// <summary>
/// Interface for decoder of a single frame.
/// </summary>
internal interface IAv1FrameDecoder
{
/// <summary>
/// Decode a single superblock.
/// </summary>
/// <param name="modeInfoPosition">The top left position of the superblock, in mode info units.</param>
/// <param name="superblockInfo">The superblock to decode</param>
/// <param name="tileInfo">The tile in whcih the superblock is positioned.</param>
void DecodeSuperblock(Point modeInfoPosition, Av1SuperblockInfo superblockInfo, Av1TileInfo tileInfo);
}

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

@ -4,6 +4,7 @@
using System.Runtime.CompilerServices;
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.Prediction;
using SixLabors.ImageSharp.Formats.Heif.Av1.Transform;
@ -35,12 +36,14 @@ internal class Av1TileReader : IAv1TileReader
private readonly int[] firstTransformOffset = new int[2];
private readonly int[] coefficientIndex = [];
private readonly Configuration configuration;
private readonly IAv1FrameDecoder frameDecoder;
public Av1TileReader(Configuration configuration, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader)
public Av1TileReader(Configuration configuration, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader, IAv1FrameDecoder frameDecoder)
{
this.FrameHeader = frameHeader;
this.configuration = configuration;
this.SequenceHeader = sequenceHeader;
this.frameDecoder = frameDecoder;
// init_main_frame_ctxt
this.FrameInfo = new(this.SequenceHeader);
@ -56,7 +59,7 @@ internal class Av1TileReader : IAv1TileReader
int superblockColumnCount =
Av1Math.AlignPowerOf2(sequenceHeader.MaxFrameWidth, sequenceHeader.SuperblockSizeLog2) >> sequenceHeader.SuperblockSizeLog2;
int modeInfoWideColumnCount = superblockColumnCount * sequenceHeader.SuperblockModeInfoSize;
modeInfoWideColumnCount = Av1Math.AlignPowerOf2(modeInfoWideColumnCount, sequenceHeader.SuperblockSizeLog2 - 2);
modeInfoWideColumnCount = Av1Math.AlignPowerOf2(modeInfoWideColumnCount, sequenceHeader.SuperblockSizeLog2 - Av1Constants.ModeInfoSizeLog2);
this.aboveNeighborContext = new Av1ParseAboveNeighbor4x4Context(planesCount, modeInfoWideColumnCount);
this.leftNeighborContext = new Av1ParseLeftNeighbor4x4Context(planesCount, sequenceHeader.SuperblockModeInfoSize);
this.transformUnitCount = new int[Av1Constants.MaxPlanes][];
@ -72,6 +75,9 @@ internal class Av1TileReader : IAv1TileReader
public Av1FrameInfo FrameInfo { get; }
/// <summary>
/// SVT: parse_tile
/// </summary>
public void ReadTile(Span<byte> tileData, int tileNum)
{
Av1SymbolDecoder reader = new(tileData, this.FrameHeader.QuantizationParameters.BaseQIndex);
@ -103,14 +109,15 @@ internal class Av1TileReader : IAv1TileReader
Av1TileInfo tileInfo = new(tileRowIndex, tileColumnIndex, this.FrameHeader);
Av1BlockSize superBlockSize = this.SequenceHeader.SuperblockSize;
int superBlock4x4Size = this.SequenceHeader.SuperblockSizeLog2;
int superBlock4x4Size = this.SequenceHeader.SuperblockSize.Get4x4WideCount();
int superBlockSizeLog2 = this.SequenceHeader.SuperblockSizeLog2;
for (int row = modeInfoRowStart; row < modeInfoRowEnd; row += superBlock4x4Size)
{
int superBlockRow = (row << Av1Constants.ModeInfoSizeLog2) >> superBlock4x4Size;
int superBlockRow = (row << Av1Constants.ModeInfoSizeLog2) >> superBlockSizeLog2;
this.leftNeighborContext.Clear(this.SequenceHeader);
for (int column = modeInfoColumnStart; column < modeInfoColumnEnd; column += superBlock4x4Size)
{
int superBlockColumn = (column << Av1Constants.ModeInfoSizeLog2) >> superBlock4x4Size;
int superBlockColumn = (column << Av1Constants.ModeInfoSizeLog2) >> superBlockSizeLog2;
Point superblockPosition = new(superBlockColumn, superBlockRow);
Av1SuperblockInfo superblockInfo = this.FrameInfo.GetSuperblock(superblockPosition);
@ -120,6 +127,9 @@ internal class Av1TileReader : IAv1TileReader
this.firstTransformOffset[1] = 0;
this.ReadLoopRestoration(modeInfoPosition, superBlockSize);
this.ParsePartition(ref reader, modeInfoPosition, superBlockSize, superblockInfo, tileInfo);
// decoding of the superblock
this.frameDecoder.DecodeSuperblock(modeInfoPosition, superblockInfo, tileInfo);
}
}
}
@ -1863,6 +1873,9 @@ internal class Av1TileReader : IAv1TileReader
return xPos && yPos;
}*/
/// <summary>
/// SVT: partition_plane_context
/// </summary>
private int GetPartitionPlaneContext(Point location, Av1BlockSize blockSize, Av1TileInfo tileInfo, Av1SuperblockInfo superblockInfo)
{
// Maximum partition point is 8x8. Offset the log value occordingly.

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

@ -3,6 +3,7 @@
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;
@ -24,7 +25,10 @@ public class Av1TilingTests
IAv1TileReader stub = new Av1TileDecoderStub();
ObuReader obuReader = new();
obuReader.ReadAll(ref bitStreamReader, dataSize, stub);
Av1TileReader tileReader = new(Configuration.Default, obuReader.SequenceHeader, obuReader.FrameHeader);
Av1FrameBuffer frameBuffer = new(Configuration.Default, obuReader.SequenceHeader, Av1ColorFormat.Yuv444, false);
Av1FrameInfo frameInfo = new(obuReader.SequenceHeader);
Av1FrameDecoder frameDecoder = new(obuReader.SequenceHeader, obuReader.FrameHeader, frameInfo, frameBuffer);
Av1TileReader tileReader = new(Configuration.Default, obuReader.SequenceHeader, obuReader.FrameHeader, frameDecoder);
// Act
tileReader.ReadTile(tileSpan, 0);

Loading…
Cancel
Save