Browse Source

More bug fixes

pull/2633/head
Ynse Hoornenborg 2 years ago
parent
commit
30d7c09ec3
  1. 16
      src/ImageSharp/Formats/Heif/Av1/Av1Constants.cs
  2. 12
      src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs
  3. 8
      src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuSequenceHeader.cs
  4. 4
      src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuWriter.cs
  5. 2
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameBuffer.cs
  6. 47
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1ParseAboveNeighbor4x4Context.cs
  7. 52
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1ParseLeftNeighbor4x4Context.cs
  8. 75
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileDecoder.cs

16
src/ImageSharp/Formats/Heif/Av1/Av1Constants.cs

@ -145,6 +145,14 @@ internal static class Av1Constants
public const int CoefficientBaseRange = 12; public const int CoefficientBaseRange = 12;
public const int MaxTransformSize = 1 << 6;
public const int MaxTransformSizeUnit = MaxTransformSize >> 2;
public const int CoefficientContextBitCount = 6;
public const int CoefficientContextMask = (1 << CoefficientContextBitCount) - 1;
public const int TransformPadHorizontalLog2 = 2; public const int TransformPadHorizontalLog2 = 2;
public const int TransformPadHorizontal = 1 << TransformPadHorizontalLog2; public const int TransformPadHorizontal = 1 << TransformPadHorizontalLog2;
@ -153,16 +161,8 @@ internal static class Av1Constants
public const int TransformPadEnd = 16; public const int TransformPadEnd = 16;
public const int CoefficientContextBitCount = 6;
public const int CoefficientContextMask = (1 << CoefficientContextBitCount) - 1;
public const int TransformPad2d = ((MaxTransformSize + TransformPadHorizontal) * (MaxTransformSize + TransformPadVertical)) + TransformPadEnd; public const int TransformPad2d = ((MaxTransformSize + TransformPadHorizontal) * (MaxTransformSize + TransformPadVertical)) + TransformPadEnd;
public const int MaxTransformSize = 1 << 6;
public const int MaxTransformSizeUnit = MaxTransformSize >> 2;
public const int TransformPadTop = 2; public const int TransformPadTop = 2;
public const int BaseRangeSizeMinus1 = 3; public const int BaseRangeSizeMinus1 = 3;

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

@ -369,10 +369,10 @@ internal class ObuReader
} }
// Video related flags removed // Video related flags removed
sequenceHeader.Use128x128SuperBlock = reader.ReadBoolean(); sequenceHeader.Use128x128Superblock = reader.ReadBoolean();
sequenceHeader.SuperBlockSize = sequenceHeader.Use128x128SuperBlock ? Av1BlockSize.Block128x128 : Av1BlockSize.Block64x64; sequenceHeader.SuperblockSize = sequenceHeader.Use128x128Superblock ? Av1BlockSize.Block128x128 : Av1BlockSize.Block64x64;
sequenceHeader.ModeInfoSize = sequenceHeader.Use128x128SuperBlock ? 32 : 16; sequenceHeader.SuperblockModeInfoSize = sequenceHeader.Use128x128Superblock ? 32 : 16;
sequenceHeader.SuperBlockSizeLog2 = sequenceHeader.Use128x128SuperBlock ? 7 : 6; sequenceHeader.SuperblockSizeLog2 = sequenceHeader.Use128x128Superblock ? 7 : 6;
sequenceHeader.EnableFilterIntra = reader.ReadBoolean(); sequenceHeader.EnableFilterIntra = reader.ReadBoolean();
sequenceHeader.EnableIntraEdgeFilter = reader.ReadBoolean(); sequenceHeader.EnableIntraEdgeFilter = reader.ReadBoolean();
@ -701,7 +701,7 @@ internal class ObuReader
int superBlockColumnCount; int superBlockColumnCount;
int superBlockRowCount; int superBlockRowCount;
int superBlockShift; int superBlockShift;
if (sequenceHeader.Use128x128SuperBlock) if (sequenceHeader.Use128x128Superblock)
{ {
superBlockColumnCount = (frameInfo.ModeInfoColumnCount + 31) >> 5; superBlockColumnCount = (frameInfo.ModeInfoColumnCount + 31) >> 5;
superBlockRowCount = (frameInfo.ModeInfoRowCount + 31) >> 5; superBlockRowCount = (frameInfo.ModeInfoRowCount + 31) >> 5;
@ -1579,7 +1579,7 @@ internal class ObuReader
if (usesLoopRestoration) if (usesLoopRestoration)
{ {
uint loopRestorationShift = reader.ReadLiteral(1); uint loopRestorationShift = reader.ReadLiteral(1);
if (sequenceHeader.Use128x128SuperBlock) if (sequenceHeader.Use128x128Superblock)
{ {
loopRestorationShift++; loopRestorationShift++;
} }

8
src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuSequenceHeader.cs

@ -37,13 +37,13 @@ internal class ObuSequenceHeader
public int MaxFrameHeight { get; set; } public int MaxFrameHeight { get; set; }
public bool Use128x128SuperBlock { get; set; } public bool Use128x128Superblock { get; set; }
public Av1BlockSize SuperBlockSize { get; set; } public Av1BlockSize SuperblockSize { get; set; }
public int ModeInfoSize { get; set; } public int SuperblockModeInfoSize { get; set; }
public int SuperBlockSizeLog2 { get; set; } public int SuperblockSizeLog2 { get; set; }
public int FilterIntraLevel { get; set; } public int FilterIntraLevel { get; set; }

4
src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuWriter.cs

@ -91,7 +91,7 @@ internal class ObuWriter
writer.WriteLiteral((uint)sequenceHeader.MaxFrameHeight - 1, sequenceHeader.FrameHeightBits); writer.WriteLiteral((uint)sequenceHeader.MaxFrameHeight - 1, sequenceHeader.FrameHeightBits);
// Video related flags removed // Video related flags removed
writer.WriteBoolean(sequenceHeader.Use128x128SuperBlock); writer.WriteBoolean(sequenceHeader.Use128x128Superblock);
writer.WriteBoolean(sequenceHeader.EnableFilterIntra); writer.WriteBoolean(sequenceHeader.EnableFilterIntra);
writer.WriteBoolean(sequenceHeader.EnableIntraEdgeFilter); writer.WriteBoolean(sequenceHeader.EnableIntraEdgeFilter);
@ -223,7 +223,7 @@ internal class ObuWriter
int superBlockColumnCount; int superBlockColumnCount;
int superBlockRowCount; int superBlockRowCount;
int superBlockShift; int superBlockShift;
if (sequenceHeader.Use128x128SuperBlock) if (sequenceHeader.Use128x128Superblock)
{ {
superBlockColumnCount = (frameInfo.ModeInfoColumnCount + 31) >> 5; superBlockColumnCount = (frameInfo.ModeInfoColumnCount + 31) >> 5;
superBlockRowCount = (frameInfo.ModeInfoRowCount + 31) >> 5; superBlockRowCount = (frameInfo.ModeInfoRowCount + 31) >> 5;

2
src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameBuffer.cs

@ -33,7 +33,7 @@ internal class Av1FrameBuffer
public Av1FrameBuffer(ObuSequenceHeader sequenceHeader) public Av1FrameBuffer(ObuSequenceHeader sequenceHeader)
{ {
// init_main_frame_ctxt // init_main_frame_ctxt
int superblockSizeLog2 = sequenceHeader.SuperBlockSizeLog2; int superblockSizeLog2 = sequenceHeader.SuperblockSizeLog2;
int superblockAlignedWidth = Av1Math.AlignPowerOf2(sequenceHeader.MaxFrameWidth, superblockSizeLog2); int superblockAlignedWidth = Av1Math.AlignPowerOf2(sequenceHeader.MaxFrameWidth, superblockSizeLog2);
int superblockAlignedHeight = Av1Math.AlignPowerOf2(sequenceHeader.MaxFrameHeight, superblockSizeLog2); int superblockAlignedHeight = Av1Math.AlignPowerOf2(sequenceHeader.MaxFrameHeight, superblockSizeLog2);
this.superblockColumnCount = superblockAlignedWidth >> superblockSizeLog2; this.superblockColumnCount = superblockAlignedWidth >> superblockSizeLog2;

47
src/ImageSharp/Formats/Heif/Av1/Tiling/Av1ParseAboveNeighbor4x4Context.cs

@ -8,30 +8,24 @@ namespace SixLabors.ImageSharp.Formats.Heif.Av1.Symbol;
internal class Av1ParseAboveNeighbor4x4Context internal class Av1ParseAboveNeighbor4x4Context
{ {
/* Buffer holding the transform sizes of the previous 4x4 block row. */
private readonly int[] aboveTransformWidth;
/* Buffer holding the partition context of the previous 4x4 block row. */
private int[] abovePartitionWidth;
/* Buffer holding the sign of the DC coefficients and the /* Buffer holding the sign of the DC coefficients and the
cumulative sum of the coefficient levels of the above 4x4 cumulative sum of the coefficient levels of the above 4x4
blocks corresponding to the current super block row. */ blocks corresponding to the current super block row. */
private int[][] aboveContext = new int[Av1Constants.MaxPlanes][]; private readonly int[][] aboveContext = new int[Av1Constants.MaxPlanes][];
/* Buffer holding the seg_id_predicted of the previous 4x4 block row. */ /* Buffer holding the seg_id_predicted of the previous 4x4 block row. */
private int[] aboveSegmentIdPredictionContext; private readonly int[] aboveSegmentIdPredictionContext;
/* Value of base colors for Y, U, and V */ /* Value of base colors for Y, U, and V */
private int[][] abovePaletteColors = new int[Av1Constants.MaxPlanes][]; private readonly int[][] abovePaletteColors = new int[Av1Constants.MaxPlanes][];
private int[] aboveCompGroupIndex; private readonly int[] aboveCompGroupIndex;
public Av1ParseAboveNeighbor4x4Context(int planesCount, int modeInfoColumnCount) public Av1ParseAboveNeighbor4x4Context(int planesCount, int modeInfoColumnCount)
{ {
int wide64x64Count = Av1BlockSize.Block64x64.Get4x4WideCount(); int wide64x64Count = Av1BlockSize.Block64x64.Get4x4WideCount();
this.aboveTransformWidth = new int[modeInfoColumnCount]; this.AboveTransformWidth = new int[modeInfoColumnCount];
this.abovePartitionWidth = new int[modeInfoColumnCount]; this.AbovePartitionWidth = new int[modeInfoColumnCount];
for (int i = 0; i < planesCount; i++) for (int i = 0; i < planesCount; i++)
{ {
this.aboveContext[i] = new int[modeInfoColumnCount]; this.aboveContext[i] = new int[modeInfoColumnCount];
@ -42,25 +36,32 @@ internal class Av1ParseAboveNeighbor4x4Context
this.aboveCompGroupIndex = new int[modeInfoColumnCount]; this.aboveCompGroupIndex = new int[modeInfoColumnCount];
} }
public int[] AbovePartitionWidth => this.abovePartitionWidth; /// <summary>
/// Gets a buffer holding the partition context of the previous 4x4 block row.
/// </summary>
public int[] AbovePartitionWidth { get; }
public int[] AboveTransformWidth => this.aboveTransformWidth; /// <summary>
/// Gets a buffer holding the transform sizes of the previous 4x4 block row.
/// </summary>
public int[] AboveTransformWidth { get; }
public int[] GetContext(int plane) => this.aboveContext[plane]; public int[] GetContext(int plane) => this.aboveContext[plane];
public void Clear(ObuSequenceHeader sequenceHeader) public void Clear(ObuSequenceHeader sequenceHeader, int modeInfoColumnStart, int modeInfoColumnEnd)
{ {
int planeCount = sequenceHeader.ColorConfig.ChannelCount; int planeCount = sequenceHeader.ColorConfig.ChannelCount;
Array.Fill(this.aboveTransformWidth, Av1TransformSize.Size64x64.GetWidth()); int width = modeInfoColumnEnd - modeInfoColumnStart;
Array.Fill(this.abovePartitionWidth, 0); Array.Fill(this.AboveTransformWidth, Av1TransformSize.Size64x64.GetWidth(), 0, width);
Array.Fill(this.AbovePartitionWidth, 0, 0, width);
for (int i = 0; i < planeCount; i++) for (int i = 0; i < planeCount; i++)
{ {
Array.Fill(this.aboveContext[i], 0); Array.Fill(this.aboveContext[i], 0, 0, width);
Array.Fill(this.abovePaletteColors[i], 0); Array.Fill(this.abovePaletteColors[i], 0, 0, width);
} }
Array.Fill(this.aboveSegmentIdPredictionContext, 0); Array.Fill(this.aboveSegmentIdPredictionContext, 0, 0, width);
Array.Fill(this.aboveCompGroupIndex, 0); Array.Fill(this.aboveCompGroupIndex, 0, 0, width);
} }
public void UpdatePartition(Point modeInfoLocation, Av1TileInfo tileLoc, Av1BlockSize subSize, Av1BlockSize blockSize) public void UpdatePartition(Point modeInfoLocation, Av1TileInfo tileLoc, Av1BlockSize subSize, Av1BlockSize blockSize)
@ -70,7 +71,7 @@ internal class Av1ParseAboveNeighbor4x4Context
int value = Av1PartitionContext.GetAboveContext(subSize); int value = Av1PartitionContext.GetAboveContext(subSize);
for (int i = 0; i < bw; i++) for (int i = 0; i < bw; i++)
{ {
this.abovePartitionWidth[startIndex + i] = value; this.AbovePartitionWidth[startIndex + i] = value;
} }
} }
@ -84,7 +85,7 @@ internal class Av1ParseAboveNeighbor4x4Context
transformWidth = n4w << Av1Constants.ModeInfoSizeLog2; transformWidth = n4w << Av1Constants.ModeInfoSizeLog2;
} }
Array.Fill(this.aboveTransformWidth, transformWidth, startIndex, n4w); Array.Fill(this.AboveTransformWidth, transformWidth, startIndex, n4w);
} }
internal void ClearContext(int plane, int offset, int length) internal void ClearContext(int plane, int offset, int length)

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

@ -8,31 +8,23 @@ namespace SixLabors.ImageSharp.Formats.Heif.Av1.Symbol;
internal class Av1ParseLeftNeighbor4x4Context internal class Av1ParseLeftNeighbor4x4Context
{ {
/* Buffer holding the transform sizes of the left 4x4 blocks corresponding
to the current super block row. */
private readonly int[] leftTransformHeight;
/* Buffer holding the partition context of the left 4x4 blocks corresponding
to the current super block row. */
private int[] leftPartitionHeight;
/* Buffer holding the sign of the DC coefficients and the /* Buffer holding the sign of the DC coefficients and the
cumulative sum of the coefficient levels of the left 4x4 cumulative sum of the coefficient levels of the left 4x4
blocks corresponding to the current super block row. */ blocks corresponding to the current super block row. */
private int[][] leftContext = new int[Av1Constants.MaxPlanes][]; private readonly int[][] leftContext = new int[Av1Constants.MaxPlanes][];
/* Buffer holding the seg_id_predicted of the previous 4x4 block row. */ /* Buffer holding the seg_id_predicted of the previous 4x4 block row. */
private int[] leftSegmentIdPredictionContext; private readonly int[] leftSegmentIdPredictionContext;
/* Value of base colors for Y, U, and V */ /* Value of base colors for Y, U, and V */
private int[][] leftPaletteColors = new int[Av1Constants.MaxPlanes][]; private readonly int[][] leftPaletteColors = new int[Av1Constants.MaxPlanes][];
private int[] leftCompGroupIndex; private readonly int[] leftCompGroupIndex;
public Av1ParseLeftNeighbor4x4Context(int planesCount, int superblockModeInfoSize) public Av1ParseLeftNeighbor4x4Context(int planesCount, int superblockModeInfoSize)
{ {
this.leftTransformHeight = new int[superblockModeInfoSize]; this.LeftTransformHeight = new int[superblockModeInfoSize];
this.leftPartitionHeight = new int[superblockModeInfoSize]; this.LeftPartitionHeight = new int[superblockModeInfoSize];
for (int i = 0; i < planesCount; i++) for (int i = 0; i < planesCount; i++)
{ {
this.leftContext[i] = new int[superblockModeInfoSize]; this.leftContext[i] = new int[superblockModeInfoSize];
@ -43,23 +35,33 @@ internal class Av1ParseLeftNeighbor4x4Context
this.leftCompGroupIndex = new int[superblockModeInfoSize]; this.leftCompGroupIndex = new int[superblockModeInfoSize];
} }
public int[] LeftPartitionHeight => this.leftPartitionHeight; /// <summary>
/// Gets a buffer holding the partition context of the left 4x4 blocks corresponding
/// to the current super block row.
/// </summary>
public int[] LeftPartitionHeight { get; }
public int[] LeftTransformHeight => this.leftTransformHeight; /// <summary>
/// Gets a buffer holding the transform sizes of the left 4x4 blocks corresponding
/// to the current super block row.
/// </summary>
public int[] LeftTransformHeight { get; }
public void Clear(ObuSequenceHeader sequenceHeader) public void Clear(ObuSequenceHeader sequenceHeader)
{ {
int blockCount = sequenceHeader.SuperblockModeInfoSize;
int planeCount = sequenceHeader.ColorConfig.ChannelCount; int planeCount = sequenceHeader.ColorConfig.ChannelCount;
Array.Fill(this.leftTransformHeight, Av1TransformSize.Size64x64.GetHeight()); int neighbor4x4Count = sequenceHeader.SuperblockModeInfoSize;
Array.Fill(this.leftPartitionHeight, 0); Array.Fill(this.LeftTransformHeight, Av1TransformSize.Size64x64.GetHeight(), 0, blockCount);
Array.Fill(this.LeftPartitionHeight, 0, 0, blockCount);
for (int i = 0; i < planeCount; i++) for (int i = 0; i < planeCount; i++)
{ {
Array.Fill(this.leftContext[i], 0); Array.Fill(this.leftContext[i], 0, 0, blockCount);
Array.Fill(this.leftPaletteColors[i], 0); Array.Fill(this.leftPaletteColors[i], 0, 0, blockCount);
} }
Array.Fill(this.leftSegmentIdPredictionContext, 0); Array.Fill(this.leftSegmentIdPredictionContext, 0, 0, blockCount);
Array.Fill(this.leftCompGroupIndex, 0); Array.Fill(this.leftCompGroupIndex, 0, 0, blockCount);
} }
public void UpdatePartition(Point modeInfoLocation, Av1SuperblockInfo superblockInfo, Av1BlockSize subSize, Av1BlockSize blockSize) public void UpdatePartition(Point modeInfoLocation, Av1SuperblockInfo superblockInfo, Av1BlockSize subSize, Av1BlockSize blockSize)
@ -69,7 +71,7 @@ internal class Av1ParseLeftNeighbor4x4Context
int value = Av1PartitionContext.GetLeftContext(subSize); int value = Av1PartitionContext.GetLeftContext(subSize);
for (int i = 0; i < bh; i++) for (int i = 0; i < bh; i++)
{ {
this.leftPartitionHeight[startIndex + i] = value; this.LeftPartitionHeight[startIndex + i] = value;
} }
} }
@ -83,8 +85,8 @@ internal class Av1ParseLeftNeighbor4x4Context
transformHeight = n4h << Av1Constants.ModeInfoSizeLog2; transformHeight = n4h << Av1Constants.ModeInfoSizeLog2;
} }
DebugGuard.MustBeLessThanOrEqualTo(startIndex + n4h, this.leftTransformHeight.Length, nameof(startIndex)); DebugGuard.MustBeLessThanOrEqualTo(startIndex + n4h, this.LeftTransformHeight.Length, nameof(startIndex));
Array.Fill(this.leftTransformHeight, transformHeight, startIndex, n4h); Array.Fill(this.LeftTransformHeight, transformHeight, startIndex, n4h);
} }
internal void ClearContext(int plane, int offset, int length) internal void ClearContext(int plane, int offset, int length)

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

@ -54,11 +54,11 @@ internal class Av1TileDecoder : IAv1TileDecoder
// Hard code number of threads to 1 for now. // Hard code number of threads to 1 for now.
int planesCount = sequenceHeader.ColorConfig.IsMonochrome ? 1 : Av1Constants.MaxPlanes; int planesCount = sequenceHeader.ColorConfig.IsMonochrome ? 1 : Av1Constants.MaxPlanes;
int superblockColumnCount = int superblockColumnCount =
Av1Math.AlignPowerOf2(sequenceHeader.MaxFrameWidth, sequenceHeader.SuperBlockSizeLog2) >> sequenceHeader.SuperBlockSizeLog2; Av1Math.AlignPowerOf2(sequenceHeader.MaxFrameWidth, sequenceHeader.SuperblockSizeLog2) >> sequenceHeader.SuperblockSizeLog2;
int modeInfoWideColumnCount = superblockColumnCount * sequenceHeader.ModeInfoSize; int modeInfoWideColumnCount = superblockColumnCount * sequenceHeader.SuperblockModeInfoSize;
modeInfoWideColumnCount = Av1Math.AlignPowerOf2(modeInfoWideColumnCount, sequenceHeader.SuperBlockSizeLog2 - 2); modeInfoWideColumnCount = Av1Math.AlignPowerOf2(modeInfoWideColumnCount, sequenceHeader.SuperblockSizeLog2 - 2);
this.aboveNeighborContext = new Av1ParseAboveNeighbor4x4Context(planesCount, modeInfoWideColumnCount); this.aboveNeighborContext = new Av1ParseAboveNeighbor4x4Context(planesCount, modeInfoWideColumnCount);
this.leftNeighborContext = new Av1ParseLeftNeighbor4x4Context(planesCount, sequenceHeader.ModeInfoSize); this.leftNeighborContext = new Av1ParseLeftNeighbor4x4Context(planesCount, sequenceHeader.SuperblockModeInfoSize);
this.tusCount = new int[Av1Constants.MaxPlanes][]; this.tusCount = new int[Av1Constants.MaxPlanes][];
this.tusCount[0] = new int[this.FrameBuffer.ModeInfoCount]; this.tusCount[0] = new int[this.FrameBuffer.ModeInfoCount];
this.tusCount[1] = new int[this.FrameBuffer.ModeInfoCount]; this.tusCount[1] = new int[this.FrameBuffer.ModeInfoCount];
@ -78,7 +78,11 @@ internal class Av1TileDecoder : IAv1TileDecoder
int tileColumnIndex = tileNum % this.FrameInfo.TilesInfo.TileColumnCount; int tileColumnIndex = tileNum % this.FrameInfo.TilesInfo.TileColumnCount;
int tileRowIndex = tileNum / this.FrameInfo.TilesInfo.TileColumnCount; int tileRowIndex = tileNum / this.FrameInfo.TilesInfo.TileColumnCount;
this.aboveNeighborContext.Clear(this.SequenceHeader); int modeInfoColumnStart = this.FrameInfo.TilesInfo.TileColumnStartModeInfo[tileColumnIndex];
int modeInfoColumnEnd = this.FrameInfo.TilesInfo.TileColumnStartModeInfo[tileColumnIndex + 1];
int modeInfoRowStart = this.FrameInfo.TilesInfo.TileRowStartModeInfo[tileRowIndex];
int modeInfoRowEnd = this.FrameInfo.TilesInfo.TileRowStartModeInfo[tileRowIndex + 1];
this.aboveNeighborContext.Clear(this.SequenceHeader, modeInfoColumnStart, modeInfoColumnEnd);
this.ClearLoopFilterDelta(); this.ClearLoopFilterDelta();
int planesCount = this.SequenceHeader.ColorConfig.ChannelCount; int planesCount = this.SequenceHeader.ColorConfig.ChannelCount;
@ -98,15 +102,15 @@ internal class Av1TileDecoder : IAv1TileDecoder
} }
Av1TileInfo tileInfo = new(tileRowIndex, tileColumnIndex, this.FrameInfo); Av1TileInfo tileInfo = new(tileRowIndex, tileColumnIndex, this.FrameInfo);
Av1BlockSize superBlockSize = this.SequenceHeader.Use128x128SuperBlock ? Av1BlockSize.Block128x128 : Av1BlockSize.Block64x64; Av1BlockSize superBlockSize = this.SequenceHeader.Use128x128Superblock ? Av1BlockSize.Block128x128 : Av1BlockSize.Block64x64;
int superBlock4x4Size = superBlockSize.Get4x4WideCount(); int superBlock4x4Size = superBlockSize.Get4x4WideCount();
for (int row = this.FrameInfo.TilesInfo.TileRowStartModeInfo[tileRowIndex]; row < this.FrameInfo.TilesInfo.TileRowStartModeInfo[tileRowIndex + 1]; row += this.SequenceHeader.ModeInfoSize) for (int row = modeInfoRowStart; row < modeInfoRowEnd; row += this.SequenceHeader.SuperblockModeInfoSize)
{ {
int superBlockRow = row << Av1Constants.ModeInfoSizeLog2 >> this.SequenceHeader.SuperBlockSizeLog2; int superBlockRow = row << Av1Constants.ModeInfoSizeLog2 >> this.SequenceHeader.SuperblockSizeLog2;
this.leftNeighborContext.Clear(this.SequenceHeader); this.leftNeighborContext.Clear(this.SequenceHeader);
for (int column = this.FrameInfo.TilesInfo.TileColumnStartModeInfo[tileColumnIndex]; column < this.FrameInfo.TilesInfo.TileColumnStartModeInfo[tileColumnIndex + 1]; column += this.SequenceHeader.ModeInfoSize) for (int column = modeInfoColumnStart; column < modeInfoColumnEnd; column += this.SequenceHeader.SuperblockModeInfoSize)
{ {
int superBlockColumn = column << Av1Constants.ModeInfoSizeLog2 >> this.SequenceHeader.SuperBlockSizeLog2; int superBlockColumn = column << Av1Constants.ModeInfoSizeLog2 >> this.SequenceHeader.SuperblockSizeLog2;
Point superblockPosition = new(superBlockColumn, superBlockRow); Point superblockPosition = new(superBlockColumn, superBlockRow);
Av1SuperblockInfo superblockInfo = this.FrameBuffer.GetSuperblock(superblockPosition); Av1SuperblockInfo superblockInfo = this.FrameBuffer.GetSuperblock(superblockPosition);
@ -162,6 +166,7 @@ internal class Av1TileDecoder : IAv1TileDecoder
int quarterBlock4x4Size = halfBlock4x4Size >> 1; int quarterBlock4x4Size = halfBlock4x4Size >> 1;
bool hasRows = (modeInfoLocation.Y + halfBlock4x4Size) < this.FrameInfo.ModeInfoRowCount; bool hasRows = (modeInfoLocation.Y + halfBlock4x4Size) < this.FrameInfo.ModeInfoRowCount;
bool hasColumns = (modeInfoLocation.X + halfBlock4x4Size) < this.FrameInfo.ModeInfoColumnCount; bool hasColumns = (modeInfoLocation.X + halfBlock4x4Size) < this.FrameInfo.ModeInfoColumnCount;
int ctx = this.GetPartitionPlaneContext(modeInfoLocation, blockSize, tileInfo, superblockInfo);
Av1PartitionType partitionType = Av1PartitionType.Split; Av1PartitionType partitionType = Av1PartitionType.Split;
if (blockSize < Av1BlockSize.Block8x8) if (blockSize < Av1BlockSize.Block8x8)
{ {
@ -169,20 +174,17 @@ internal class Av1TileDecoder : IAv1TileDecoder
} }
else if (hasRows && hasColumns) else if (hasRows && hasColumns)
{ {
int ctx = this.GetPartitionPlaneContext(modeInfoLocation, blockSize, tileInfo, superblockInfo);
partitionType = reader.ReadPartitionType(ctx); partitionType = reader.ReadPartitionType(ctx);
} }
else if (hasColumns) else if (hasColumns)
{ {
int ctx = this.GetPartitionPlaneContext(modeInfoLocation, blockSize, tileInfo, superblockInfo); bool splitOrVertical = reader.ReadSplitOrVertical(blockSize, ctx);
bool splitOrHorizontal = reader.ReadSplitOrHorizontal(blockSize, ctx); partitionType = splitOrVertical ? Av1PartitionType.Split : Av1PartitionType.Horizontal;
partitionType = splitOrHorizontal ? Av1PartitionType.Split : Av1PartitionType.Horizontal;
} }
else if (hasRows) else if (hasRows)
{ {
int ctx = this.GetPartitionPlaneContext(modeInfoLocation, blockSize, tileInfo, superblockInfo); bool splitOrHorizontal = reader.ReadSplitOrHorizontal(blockSize, ctx);
bool splitOrVertical = reader.ReadSplitOrVertical(blockSize, ctx); partitionType = splitOrHorizontal ? Av1PartitionType.Split : Av1PartitionType.Vertical;
partitionType = splitOrVertical ? Av1PartitionType.Split : Av1PartitionType.Vertical;
} }
Av1BlockSize subSize = partitionType.GetBlockSubSize(blockSize); Av1BlockSize subSize = partitionType.GetBlockSubSize(blockSize);
@ -1204,27 +1206,6 @@ internal class Av1TileDecoder : IAv1TileDecoder
return (aboveEntropyContext ? 1 : 0) + (leftEntropyContext ? 1 : 0); return (aboveEntropyContext ? 1 : 0) + (leftEntropyContext ? 1 : 0);
} }
private void Reconstruct(int plane, int startX, int startY, Av1TransformSize transformSize) => throw new NotImplementedException();
private int Coefficients(int plane, int startX, int startY, Av1TransformSize transformSize) => throw new NotImplementedException();
private void PredictChromaFromLuma(int plane, int startX, int startY, Av1TransformSize transformSize) => throw new NotImplementedException();
/// <summary>
/// 7.11.2. Intra prediction process.
/// </summary>
private void PredictIntra(int plane, int startX, int startY, bool leftAvailable, bool upAvailable, bool haveAboveRight, bool haveBelowLeft, Av1PredictionMode mode, int log2Width, int log2Height) => throw new NotImplementedException();
private void PredictPalette(int plane, int startX, int startY, int x, int y, Av1TransformSize transformSize) => throw new NotImplementedException();
/// <summary>
/// Page 65, below 5.11.5. Decode block syntax.
/// </summary>
private static void ResetBlockContext(int rowIndex, int columnIndex, Av1BlockSize blockSize)
{
// TODO: Do we still need this method.
}
/// <summary> /// <summary>
/// 5.11.15. TX size syntax. /// 5.11.15. TX size syntax.
/// </summary> /// </summary>
@ -1236,7 +1217,7 @@ internal class Av1TileDecoder : IAv1TileDecoder
return Av1TransformSize.Size4x4; return Av1TransformSize.Size4x4;
} }
if (modeInfo.BlockSize > Av1BlockSize.Block4x4 && allowSelect && this.FrameInfo.TransformMode == Transform.Av1TransformMode.Select) if (modeInfo.BlockSize > Av1BlockSize.Block4x4 && allowSelect && this.FrameInfo.TransformMode == Av1TransformMode.Select)
{ {
return this.ReadSelectedTransformSize(ref reader, partitionInfo, superblockInfo, tileInfo); return this.ReadSelectedTransformSize(ref reader, partitionInfo, superblockInfo, tileInfo);
} }
@ -1719,7 +1700,7 @@ internal class Av1TileDecoder : IAv1TileDecoder
if (partitionInfo.CdefStrength[r][c] == -1) if (partitionInfo.CdefStrength[r][c] == -1)
{ {
partitionInfo.CdefStrength[r][c] = reader.ReadLiteral(this.FrameInfo.CdefParameters.BitCount); partitionInfo.CdefStrength[r][c] = reader.ReadLiteral(this.FrameInfo.CdefParameters.BitCount);
if (this.SequenceHeader.SuperBlockSize == Av1BlockSize.Block128x128) if (this.SequenceHeader.SuperblockSize == Av1BlockSize.Block128x128)
{ {
int w4 = partitionInfo.ModeInfo.BlockSize.Get4x4WideCount(); int w4 = partitionInfo.ModeInfo.BlockSize.Get4x4WideCount();
int h4 = partitionInfo.ModeInfo.BlockSize.Get4x4HighCount(); int h4 = partitionInfo.ModeInfo.BlockSize.Get4x4HighCount();
@ -1736,7 +1717,7 @@ internal class Av1TileDecoder : IAv1TileDecoder
private void ReadDeltaLoopFilter(ref Av1SymbolDecoder reader, Av1PartitionInfo partitionInfo) private void ReadDeltaLoopFilter(ref Av1SymbolDecoder reader, Av1PartitionInfo partitionInfo)
{ {
Av1BlockSize superBlockSize = this.SequenceHeader.Use128x128SuperBlock ? Av1BlockSize.Block128x128 : Av1BlockSize.Block64x64; Av1BlockSize superBlockSize = this.SequenceHeader.Use128x128Superblock ? Av1BlockSize.Block128x128 : Av1BlockSize.Block64x64;
if (this.FrameInfo.DeltaLoopFilterParameters.IsPresent || if (this.FrameInfo.DeltaLoopFilterParameters.IsPresent ||
(partitionInfo.ModeInfo.BlockSize == superBlockSize && partitionInfo.ModeInfo.Skip)) (partitionInfo.ModeInfo.BlockSize == superBlockSize && partitionInfo.ModeInfo.Skip))
{ {
@ -1790,14 +1771,14 @@ internal class Av1TileDecoder : IAv1TileDecoder
private void ReadDeltaQuantizerIndex(ref Av1SymbolDecoder reader, Av1PartitionInfo partitionInfo) private void ReadDeltaQuantizerIndex(ref Av1SymbolDecoder reader, Av1PartitionInfo partitionInfo)
{ {
Av1BlockSize superBlockSize = this.SequenceHeader.Use128x128SuperBlock ? Av1BlockSize.Block128x128 : Av1BlockSize.Block64x64; Av1BlockSize superBlockSize = this.SequenceHeader.Use128x128Superblock ? Av1BlockSize.Block128x128 : Av1BlockSize.Block64x64;
if (!this.FrameInfo.DeltaQParameters.IsPresent || if (!this.FrameInfo.DeltaQParameters.IsPresent ||
(partitionInfo.ModeInfo.BlockSize == superBlockSize && partitionInfo.ModeInfo.Skip)) (partitionInfo.ModeInfo.BlockSize == superBlockSize && partitionInfo.ModeInfo.Skip))
{ {
return; return;
} }
if (partitionInfo.ModeInfo.BlockSize != this.SequenceHeader.SuperBlockSize || !partitionInfo.ModeInfo.Skip) if (partitionInfo.ModeInfo.BlockSize != this.SequenceHeader.SuperblockSize || !partitionInfo.ModeInfo.Skip)
{ {
int deltaQuantizerAbsolute = reader.ReadDeltaQuantizerAbsolute(); int deltaQuantizerAbsolute = reader.ReadDeltaQuantizerAbsolute();
if (deltaQuantizerAbsolute == Av1Constants.DeltaQuantizerSmall) if (deltaQuantizerAbsolute == Av1Constants.DeltaQuantizerSmall)
@ -1834,15 +1815,17 @@ internal class Av1TileDecoder : IAv1TileDecoder
return xPos && yPos; return xPos && yPos;
}*/ }*/
private int GetPartitionPlaneContext(Point location, Av1BlockSize blockSize, Av1TileInfo tileLoc, Av1SuperblockInfo superblockInfo) private int GetPartitionPlaneContext(Point location, Av1BlockSize blockSize, Av1TileInfo tileInfo, Av1SuperblockInfo superblockInfo)
{ {
// 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 - tileLoc.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.Position.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;
return (left * 2) + above + (blockSizeLog * PartitionProbabilitySet); DebugGuard.IsTrue(blockSize.Get4x4WidthLog2() == blockSize.Get4x4HeightLog2(), "Blocks should be square");
DebugGuard.MustBeGreaterThanOrEqualTo(blockSizeLog, 0, nameof(blockSizeLog));
return ((left << 1) + above) + (blockSizeLog * PartitionProbabilitySet);
} }
private void UpdatePartitionContext(Point modeInfoLocation, Av1TileInfo tileLoc, Av1SuperblockInfo superblockInfo, Av1BlockSize subSize, Av1BlockSize blockSize, Av1PartitionType partition) private void UpdatePartitionContext(Point modeInfoLocation, Av1TileInfo tileLoc, Av1SuperblockInfo superblockInfo, Av1BlockSize subSize, Av1BlockSize blockSize, Av1PartitionType partition)

Loading…
Cancel
Save