mirror of https://github.com/SixLabors/ImageSharp
6 changed files with 349 additions and 40 deletions
@ -0,0 +1,75 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
using SixLabors.ImageSharp.Formats.Heif.Av1.Quantization; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Symbol; |
|||
|
|||
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 |
|||
cumulative sum of the coefficient levels of the above 4x4 |
|||
blocks corresponding to the current super block row. */ |
|||
private int[][] aboveContext = new int[Av1Constants.MaxPlanes][]; |
|||
|
|||
/* Buffer holding the seg_id_predicted of the previous 4x4 block row. */ |
|||
private int[] aboveSegmentIdPredictionContext; |
|||
|
|||
/* Value of base colors for Y, U, and V */ |
|||
private int[][] abovePaletteColors = new int[Av1Constants.MaxPlanes][]; |
|||
|
|||
private int[] aboveCompGroupIndex; |
|||
|
|||
public Av1ParseAboveNeighbor4x4Context(int planesCount, int modeInfoColumnCount) |
|||
{ |
|||
int wide64x64Count = Av1BlockSize.Block64x64.Get4x4WideCount(); |
|||
this.aboveTransformWidth = new int[modeInfoColumnCount]; |
|||
this.abovePartitionWidth = new int[modeInfoColumnCount]; |
|||
for (int i = 0; i < planesCount; i++) |
|||
{ |
|||
this.aboveContext[i] = new int[modeInfoColumnCount]; |
|||
this.abovePaletteColors[i] = new int[wide64x64Count * Av1Constants.PaletteMaxSize]; |
|||
} |
|||
|
|||
this.aboveSegmentIdPredictionContext = new int[modeInfoColumnCount]; |
|||
this.aboveCompGroupIndex = new int[modeInfoColumnCount]; |
|||
} |
|||
|
|||
public int[] AbovePartitionWidth => this.abovePartitionWidth; |
|||
|
|||
public void Clear(ObuSequenceHeader sequenceHeader) |
|||
{ |
|||
int planeCount = sequenceHeader.ColorConfig.ChannelCount; |
|||
Array.Fill(this.aboveTransformWidth, Av1TransformSize.Size64x64.GetWidth()); |
|||
Array.Fill(this.abovePartitionWidth, 0); |
|||
for (int i = 0; i < planeCount; i++) |
|||
{ |
|||
Array.Fill(this.aboveContext[i], 0); |
|||
Array.Fill(this.abovePaletteColors[i], 0); |
|||
} |
|||
|
|||
Array.Fill(this.aboveSegmentIdPredictionContext, 0); |
|||
Array.Fill(this.aboveCompGroupIndex, 0); |
|||
} |
|||
|
|||
public void UpdatePartition(Point modeInfoLocation, Av1TileLocation tileLoc, Av1BlockSize subSize, Av1BlockSize blockSize) |
|||
{ |
|||
int startIndex = modeInfoLocation.X - tileLoc.ModeInfoColumnStart; |
|||
int bw = blockSize.Get4x4WideCount(); |
|||
int value = Av1PartitionContext.GetAboveContext(subSize); |
|||
for (int i = 0; i < bw; i++) |
|||
{ |
|||
this.abovePartitionWidth[startIndex + i] = value; |
|||
} |
|||
} |
|||
|
|||
internal void ClearContext(int plane, int offset, int length) |
|||
=> Array.Fill(this.aboveContext[plane], 0, offset, length); |
|||
} |
|||
@ -0,0 +1,76 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
using SixLabors.ImageSharp.Formats.Heif.Av1.Quantization; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Symbol; |
|||
|
|||
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 |
|||
cumulative sum of the coefficient levels of the left 4x4 |
|||
blocks corresponding to the current super block row. */ |
|||
private int[][] leftContext = new int[Av1Constants.MaxPlanes][]; |
|||
|
|||
/* Buffer holding the seg_id_predicted of the previous 4x4 block row. */ |
|||
private int[] leftSegmentIdPredictionContext; |
|||
|
|||
/* Value of base colors for Y, U, and V */ |
|||
private int[][] leftPaletteColors = new int[Av1Constants.MaxPlanes][]; |
|||
|
|||
private int[] leftCompGroupIndex; |
|||
|
|||
public Av1ParseLeftNeighbor4x4Context(int planesCount, int superblockModeInfoSize) |
|||
{ |
|||
this.leftTransformHeight = new int[superblockModeInfoSize]; |
|||
this.leftPartitionHeight = new int[superblockModeInfoSize]; |
|||
for (int i = 0; i < planesCount; i++) |
|||
{ |
|||
this.leftContext[i] = new int[superblockModeInfoSize]; |
|||
this.leftPaletteColors[i] = new int[superblockModeInfoSize * Av1Constants.PaletteMaxSize]; |
|||
} |
|||
|
|||
this.leftSegmentIdPredictionContext = new int[superblockModeInfoSize]; |
|||
this.leftCompGroupIndex = new int[superblockModeInfoSize]; |
|||
} |
|||
|
|||
public int[] LeftPartitionHeight => this.leftPartitionHeight; |
|||
|
|||
public void Clear(ObuSequenceHeader sequenceHeader) |
|||
{ |
|||
int planeCount = sequenceHeader.ColorConfig.ChannelCount; |
|||
Array.Fill(this.leftTransformHeight, Av1TransformSize.Size64x64.GetHeight()); |
|||
Array.Fill(this.leftPartitionHeight, 0); |
|||
for (int i = 0; i < planeCount; i++) |
|||
{ |
|||
Array.Fill(this.leftContext[i], 0); |
|||
Array.Fill(this.leftPaletteColors[i], 0); |
|||
} |
|||
|
|||
Array.Fill(this.leftSegmentIdPredictionContext, 0); |
|||
Array.Fill(this.leftCompGroupIndex, 0); |
|||
} |
|||
|
|||
public void UpdatePartition(Point modeInfoLocation, Av1SuperblockInfo superblockInfo, Av1BlockSize subSize, Av1BlockSize blockSize) |
|||
{ |
|||
int startIndex = (modeInfoLocation.Y - superblockInfo.Position.Y) & Av1PartitionContext.Mask; |
|||
int bh = blockSize.Get4x4HighCount(); |
|||
int value = Av1PartitionContext.GetLeftContext(subSize); |
|||
for (int i = 0; i < bh; i++) |
|||
{ |
|||
this.leftPartitionHeight[startIndex + i] = value; |
|||
} |
|||
} |
|||
|
|||
internal void ClearContext(int plane, int offset, int length) |
|||
=> Array.Fill(this.leftContext[plane], 0, offset, length); |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Symbol; |
|||
|
|||
// Generates 5 bit field in which each bit set to 1 represents
|
|||
// a BlockSize partition 11111 means we split 128x128, 64x64, 32x32, 16x16
|
|||
// and 8x8. 10000 means we just split the 128x128 to 64x64
|
|||
internal class Av1PartitionContext |
|||
{ |
|||
private static readonly int[] AboveLookup = |
|||
[31, 31, 30, 30, 30, 28, 28, 28, 24, 24, 24, 16, 16, 16, 0, 0, 31, 28, 30, 24, 28, 16]; |
|||
|
|||
private static readonly int[] LeftLookup = |
|||
[31, 30, 31, 30, 28, 30, 28, 24, 28, 24, 16, 24, 16, 0, 16, 0, 28, 31, 24, 30, 16, 28]; |
|||
|
|||
// Mask to extract ModeInfo offset within max ModeInfoBlock
|
|||
public const int Mask = (1 << (7 - 2)) - 1; |
|||
|
|||
public static int GetAboveContext(Av1BlockSize blockSize) => AboveLookup[(int)blockSize]; |
|||
|
|||
public static int GetLeftContext(Av1BlockSize blockSize) => LeftLookup[(int)blockSize]; |
|||
} |
|||
@ -0,0 +1,45 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Symbol; |
|||
|
|||
internal class Av1TileLocation |
|||
{ |
|||
public Av1TileLocation(int row, int column, ObuFrameHeader frameInfo) |
|||
{ |
|||
this.SetTileRow(frameInfo.TilesInfo, frameInfo.ModeInfoRowCount, row); |
|||
this.SetTileColumn(frameInfo.TilesInfo, frameInfo.ModeInfoColumnCount, column); |
|||
} |
|||
|
|||
public int ModeInfoRowStart { get; private set; } |
|||
|
|||
public int ModeInfoRowEnd { get; private set; } |
|||
|
|||
public int ModeInfoColumnStart { get; private set; } |
|||
|
|||
public int ModeInfoColumnEnd { get; private set; } |
|||
|
|||
public Point TileIndex { get; private set; } |
|||
|
|||
public int TileIndexInRasterOrder { get; } |
|||
|
|||
public void SetTileRow(ObuTileGroupHeader tileGroupHeader, int modeInfoRowCount, int row) |
|||
{ |
|||
this.ModeInfoRowStart = tileGroupHeader.TileRowStartModeInfo[row]; |
|||
this.ModeInfoRowEnd = Math.Min(tileGroupHeader.TileRowStartModeInfo[row + 1], modeInfoRowCount); |
|||
Point loc = this.TileIndex; |
|||
loc.Y = row; |
|||
this.TileIndex = loc; |
|||
} |
|||
|
|||
public void SetTileColumn(ObuTileGroupHeader tileGroupHeader, int modeInfoColumnCount, int column) |
|||
{ |
|||
this.ModeInfoColumnStart = tileGroupHeader.TileColumnStartModeInfo[column]; |
|||
this.ModeInfoColumnEnd = Math.Min(tileGroupHeader.TileColumnStartModeInfo[column + 1], modeInfoColumnCount); |
|||
Point loc = this.TileIndex; |
|||
loc.X = column; |
|||
this.TileIndex = loc; |
|||
} |
|||
} |
|||
Loading…
Reference in new issue