diff --git a/src/ImageSharp/Formats/Heif/Av1/Av1Constants.cs b/src/ImageSharp/Formats/Heif/Av1/Av1Constants.cs index b997165d74..2cb64a545b 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Av1Constants.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Av1Constants.cs @@ -145,6 +145,14 @@ internal static class Av1Constants 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 TransformPadHorizontal = 1 << TransformPadHorizontalLog2; @@ -153,16 +161,8 @@ internal static class Av1Constants 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 MaxTransformSize = 1 << 6; - - public const int MaxTransformSizeUnit = MaxTransformSize >> 2; - public const int TransformPadTop = 2; public const int BaseRangeSizeMinus1 = 3; diff --git a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs index df1d42c923..269c39810d 100644 --- a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs +++ b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs @@ -369,10 +369,10 @@ internal class ObuReader } // Video related flags removed - sequenceHeader.Use128x128SuperBlock = reader.ReadBoolean(); - sequenceHeader.SuperBlockSize = sequenceHeader.Use128x128SuperBlock ? Av1BlockSize.Block128x128 : Av1BlockSize.Block64x64; - sequenceHeader.ModeInfoSize = sequenceHeader.Use128x128SuperBlock ? 32 : 16; - sequenceHeader.SuperBlockSizeLog2 = sequenceHeader.Use128x128SuperBlock ? 7 : 6; + sequenceHeader.Use128x128Superblock = reader.ReadBoolean(); + sequenceHeader.SuperblockSize = sequenceHeader.Use128x128Superblock ? Av1BlockSize.Block128x128 : Av1BlockSize.Block64x64; + sequenceHeader.SuperblockModeInfoSize = sequenceHeader.Use128x128Superblock ? 32 : 16; + sequenceHeader.SuperblockSizeLog2 = sequenceHeader.Use128x128Superblock ? 7 : 6; sequenceHeader.EnableFilterIntra = reader.ReadBoolean(); sequenceHeader.EnableIntraEdgeFilter = reader.ReadBoolean(); @@ -701,7 +701,7 @@ internal class ObuReader int superBlockColumnCount; int superBlockRowCount; int superBlockShift; - if (sequenceHeader.Use128x128SuperBlock) + if (sequenceHeader.Use128x128Superblock) { superBlockColumnCount = (frameInfo.ModeInfoColumnCount + 31) >> 5; superBlockRowCount = (frameInfo.ModeInfoRowCount + 31) >> 5; @@ -1579,7 +1579,7 @@ internal class ObuReader if (usesLoopRestoration) { uint loopRestorationShift = reader.ReadLiteral(1); - if (sequenceHeader.Use128x128SuperBlock) + if (sequenceHeader.Use128x128Superblock) { loopRestorationShift++; } diff --git a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuSequenceHeader.cs b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuSequenceHeader.cs index b1afb7c7e3..34ce917634 100644 --- a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuSequenceHeader.cs +++ b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuSequenceHeader.cs @@ -37,13 +37,13 @@ internal class ObuSequenceHeader 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; } diff --git a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuWriter.cs b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuWriter.cs index aa4b22a03b..4a154da0e7 100644 --- a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuWriter.cs +++ b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuWriter.cs @@ -91,7 +91,7 @@ internal class ObuWriter writer.WriteLiteral((uint)sequenceHeader.MaxFrameHeight - 1, sequenceHeader.FrameHeightBits); // Video related flags removed - writer.WriteBoolean(sequenceHeader.Use128x128SuperBlock); + writer.WriteBoolean(sequenceHeader.Use128x128Superblock); writer.WriteBoolean(sequenceHeader.EnableFilterIntra); writer.WriteBoolean(sequenceHeader.EnableIntraEdgeFilter); @@ -223,7 +223,7 @@ internal class ObuWriter int superBlockColumnCount; int superBlockRowCount; int superBlockShift; - if (sequenceHeader.Use128x128SuperBlock) + if (sequenceHeader.Use128x128Superblock) { superBlockColumnCount = (frameInfo.ModeInfoColumnCount + 31) >> 5; superBlockRowCount = (frameInfo.ModeInfoRowCount + 31) >> 5; diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameBuffer.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameBuffer.cs index 4c263d072c..29b63928c4 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameBuffer.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameBuffer.cs @@ -33,7 +33,7 @@ internal class Av1FrameBuffer public Av1FrameBuffer(ObuSequenceHeader sequenceHeader) { // init_main_frame_ctxt - int superblockSizeLog2 = sequenceHeader.SuperBlockSizeLog2; + int superblockSizeLog2 = sequenceHeader.SuperblockSizeLog2; int superblockAlignedWidth = Av1Math.AlignPowerOf2(sequenceHeader.MaxFrameWidth, superblockSizeLog2); int superblockAlignedHeight = Av1Math.AlignPowerOf2(sequenceHeader.MaxFrameHeight, superblockSizeLog2); this.superblockColumnCount = superblockAlignedWidth >> superblockSizeLog2; diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1ParseAboveNeighbor4x4Context.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1ParseAboveNeighbor4x4Context.cs index 574735528d..ee82adcedd 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1ParseAboveNeighbor4x4Context.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1ParseAboveNeighbor4x4Context.cs @@ -8,30 +8,24 @@ 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][]; + private readonly int[][] aboveContext = new int[Av1Constants.MaxPlanes][]; /* 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 */ - 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) { int wide64x64Count = Av1BlockSize.Block64x64.Get4x4WideCount(); - this.aboveTransformWidth = new int[modeInfoColumnCount]; - this.abovePartitionWidth = new int[modeInfoColumnCount]; + this.AboveTransformWidth = new int[modeInfoColumnCount]; + this.AbovePartitionWidth = new int[modeInfoColumnCount]; for (int i = 0; i < planesCount; i++) { this.aboveContext[i] = new int[modeInfoColumnCount]; @@ -42,25 +36,32 @@ internal class Av1ParseAboveNeighbor4x4Context this.aboveCompGroupIndex = new int[modeInfoColumnCount]; } - public int[] AbovePartitionWidth => this.abovePartitionWidth; + /// + /// Gets a buffer holding the partition context of the previous 4x4 block row. + /// + public int[] AbovePartitionWidth { get; } - public int[] AboveTransformWidth => this.aboveTransformWidth; + /// + /// Gets a buffer holding the transform sizes of the previous 4x4 block row. + /// + public int[] AboveTransformWidth { get; } 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; - Array.Fill(this.aboveTransformWidth, Av1TransformSize.Size64x64.GetWidth()); - Array.Fill(this.abovePartitionWidth, 0); + int width = modeInfoColumnEnd - modeInfoColumnStart; + Array.Fill(this.AboveTransformWidth, Av1TransformSize.Size64x64.GetWidth(), 0, width); + Array.Fill(this.AbovePartitionWidth, 0, 0, width); for (int i = 0; i < planeCount; i++) { - Array.Fill(this.aboveContext[i], 0); - Array.Fill(this.abovePaletteColors[i], 0); + Array.Fill(this.aboveContext[i], 0, 0, width); + Array.Fill(this.abovePaletteColors[i], 0, 0, width); } - Array.Fill(this.aboveSegmentIdPredictionContext, 0); - Array.Fill(this.aboveCompGroupIndex, 0); + Array.Fill(this.aboveSegmentIdPredictionContext, 0, 0, width); + Array.Fill(this.aboveCompGroupIndex, 0, 0, width); } public void UpdatePartition(Point modeInfoLocation, Av1TileInfo tileLoc, Av1BlockSize subSize, Av1BlockSize blockSize) @@ -70,7 +71,7 @@ internal class Av1ParseAboveNeighbor4x4Context int value = Av1PartitionContext.GetAboveContext(subSize); 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; } - Array.Fill(this.aboveTransformWidth, transformWidth, startIndex, n4w); + Array.Fill(this.AboveTransformWidth, transformWidth, startIndex, n4w); } internal void ClearContext(int plane, int offset, int length) diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1ParseLeftNeighbor4x4Context.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1ParseLeftNeighbor4x4Context.cs index f505774746..7ce7beb624 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1ParseLeftNeighbor4x4Context.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1ParseLeftNeighbor4x4Context.cs @@ -8,31 +8,23 @@ 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][]; + private readonly int[][] leftContext = new int[Av1Constants.MaxPlanes][]; /* 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 */ - 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) { - this.leftTransformHeight = new int[superblockModeInfoSize]; - this.leftPartitionHeight = new 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]; @@ -43,23 +35,33 @@ internal class Av1ParseLeftNeighbor4x4Context this.leftCompGroupIndex = new int[superblockModeInfoSize]; } - public int[] LeftPartitionHeight => this.leftPartitionHeight; + /// + /// Gets a buffer holding the partition context of the left 4x4 blocks corresponding + /// to the current super block row. + /// + public int[] LeftPartitionHeight { get; } - public int[] LeftTransformHeight => this.leftTransformHeight; + /// + /// Gets a buffer holding the transform sizes of the left 4x4 blocks corresponding + /// to the current super block row. + /// + public int[] LeftTransformHeight { get; } public void Clear(ObuSequenceHeader sequenceHeader) { + int blockCount = sequenceHeader.SuperblockModeInfoSize; int planeCount = sequenceHeader.ColorConfig.ChannelCount; - Array.Fill(this.leftTransformHeight, Av1TransformSize.Size64x64.GetHeight()); - Array.Fill(this.leftPartitionHeight, 0); + int neighbor4x4Count = sequenceHeader.SuperblockModeInfoSize; + Array.Fill(this.LeftTransformHeight, Av1TransformSize.Size64x64.GetHeight(), 0, blockCount); + Array.Fill(this.LeftPartitionHeight, 0, 0, blockCount); for (int i = 0; i < planeCount; i++) { - Array.Fill(this.leftContext[i], 0); - Array.Fill(this.leftPaletteColors[i], 0); + Array.Fill(this.leftContext[i], 0, 0, blockCount); + Array.Fill(this.leftPaletteColors[i], 0, 0, blockCount); } - Array.Fill(this.leftSegmentIdPredictionContext, 0); - Array.Fill(this.leftCompGroupIndex, 0); + Array.Fill(this.leftSegmentIdPredictionContext, 0, 0, blockCount); + Array.Fill(this.leftCompGroupIndex, 0, 0, blockCount); } public void UpdatePartition(Point modeInfoLocation, Av1SuperblockInfo superblockInfo, Av1BlockSize subSize, Av1BlockSize blockSize) @@ -69,7 +71,7 @@ internal class Av1ParseLeftNeighbor4x4Context int value = Av1PartitionContext.GetLeftContext(subSize); 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; } - DebugGuard.MustBeLessThanOrEqualTo(startIndex + n4h, this.leftTransformHeight.Length, nameof(startIndex)); - Array.Fill(this.leftTransformHeight, transformHeight, startIndex, n4h); + DebugGuard.MustBeLessThanOrEqualTo(startIndex + n4h, this.LeftTransformHeight.Length, nameof(startIndex)); + Array.Fill(this.LeftTransformHeight, transformHeight, startIndex, n4h); } internal void ClearContext(int plane, int offset, int length) diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileDecoder.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileDecoder.cs index 285e5d13d9..06a41b3156 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileDecoder.cs +++ b/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. int planesCount = sequenceHeader.ColorConfig.IsMonochrome ? 1 : Av1Constants.MaxPlanes; int superblockColumnCount = - Av1Math.AlignPowerOf2(sequenceHeader.MaxFrameWidth, sequenceHeader.SuperBlockSizeLog2) >> sequenceHeader.SuperBlockSizeLog2; - int modeInfoWideColumnCount = superblockColumnCount * sequenceHeader.ModeInfoSize; - modeInfoWideColumnCount = Av1Math.AlignPowerOf2(modeInfoWideColumnCount, sequenceHeader.SuperBlockSizeLog2 - 2); + Av1Math.AlignPowerOf2(sequenceHeader.MaxFrameWidth, sequenceHeader.SuperblockSizeLog2) >> sequenceHeader.SuperblockSizeLog2; + int modeInfoWideColumnCount = superblockColumnCount * sequenceHeader.SuperblockModeInfoSize; + modeInfoWideColumnCount = Av1Math.AlignPowerOf2(modeInfoWideColumnCount, sequenceHeader.SuperblockSizeLog2 - 2); 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[0] = 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 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(); int planesCount = this.SequenceHeader.ColorConfig.ChannelCount; @@ -98,15 +102,15 @@ internal class Av1TileDecoder : IAv1TileDecoder } 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(); - 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); - 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); Av1SuperblockInfo superblockInfo = this.FrameBuffer.GetSuperblock(superblockPosition); @@ -162,6 +166,7 @@ internal class Av1TileDecoder : IAv1TileDecoder int quarterBlock4x4Size = halfBlock4x4Size >> 1; bool hasRows = (modeInfoLocation.Y + halfBlock4x4Size) < this.FrameInfo.ModeInfoRowCount; bool hasColumns = (modeInfoLocation.X + halfBlock4x4Size) < this.FrameInfo.ModeInfoColumnCount; + int ctx = this.GetPartitionPlaneContext(modeInfoLocation, blockSize, tileInfo, superblockInfo); Av1PartitionType partitionType = Av1PartitionType.Split; if (blockSize < Av1BlockSize.Block8x8) { @@ -169,20 +174,17 @@ internal class Av1TileDecoder : IAv1TileDecoder } else if (hasRows && hasColumns) { - int ctx = this.GetPartitionPlaneContext(modeInfoLocation, blockSize, tileInfo, superblockInfo); partitionType = reader.ReadPartitionType(ctx); } else if (hasColumns) { - int ctx = this.GetPartitionPlaneContext(modeInfoLocation, blockSize, tileInfo, superblockInfo); - bool splitOrHorizontal = reader.ReadSplitOrHorizontal(blockSize, ctx); - partitionType = splitOrHorizontal ? Av1PartitionType.Split : Av1PartitionType.Horizontal; + bool splitOrVertical = reader.ReadSplitOrVertical(blockSize, ctx); + partitionType = splitOrVertical ? Av1PartitionType.Split : Av1PartitionType.Horizontal; } else if (hasRows) { - int ctx = this.GetPartitionPlaneContext(modeInfoLocation, blockSize, tileInfo, superblockInfo); - bool splitOrVertical = reader.ReadSplitOrVertical(blockSize, ctx); - partitionType = splitOrVertical ? Av1PartitionType.Split : Av1PartitionType.Vertical; + bool splitOrHorizontal = reader.ReadSplitOrHorizontal(blockSize, ctx); + partitionType = splitOrHorizontal ? Av1PartitionType.Split : Av1PartitionType.Vertical; } Av1BlockSize subSize = partitionType.GetBlockSubSize(blockSize); @@ -1204,27 +1206,6 @@ internal class Av1TileDecoder : IAv1TileDecoder 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(); - - /// - /// 7.11.2. Intra prediction process. - /// - 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(); - - /// - /// Page 65, below 5.11.5. Decode block syntax. - /// - private static void ResetBlockContext(int rowIndex, int columnIndex, Av1BlockSize blockSize) - { - // TODO: Do we still need this method. - } - /// /// 5.11.15. TX size syntax. /// @@ -1236,7 +1217,7 @@ internal class Av1TileDecoder : IAv1TileDecoder 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); } @@ -1719,7 +1700,7 @@ internal class Av1TileDecoder : IAv1TileDecoder if (partitionInfo.CdefStrength[r][c] == -1) { 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 h4 = partitionInfo.ModeInfo.BlockSize.Get4x4HighCount(); @@ -1736,7 +1717,7 @@ internal class Av1TileDecoder : IAv1TileDecoder 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 || (partitionInfo.ModeInfo.BlockSize == superBlockSize && partitionInfo.ModeInfo.Skip)) { @@ -1790,14 +1771,14 @@ internal class Av1TileDecoder : IAv1TileDecoder 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 || (partitionInfo.ModeInfo.BlockSize == superBlockSize && partitionInfo.ModeInfo.Skip)) { 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(); if (deltaQuantizerAbsolute == Av1Constants.DeltaQuantizerSmall) @@ -1834,15 +1815,17 @@ internal class Av1TileDecoder : IAv1TileDecoder 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. - 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 blockSizeLog = blockSize.Get4x4WidthLog2() - Av1BlockSize.Block8x8.Get4x4WidthLog2(); int above = (aboveCtx >> 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)