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