Browse Source

Fix frame buffer extents

pull/2633/head
Ynse Hoornenborg 2 years ago
parent
commit
1b8b02d400
  1. 6
      src/ImageSharp/Formats/Heif/Av1/Av1FrameBuffer.cs
  2. 18
      src/ImageSharp/Formats/Heif/Av1/Prediction/Av1PredictionDecoder.cs
  3. 37
      src/ImageSharp/Formats/Heif/Av1/Transform/Av1BlockDecoder.cs

6
src/ImageSharp/Formats/Heif/Av1/Av1FrameBuffer.cs

@ -49,15 +49,15 @@ internal class Av1FrameBuffer<T> : IDisposable
{ {
case Av1ColorFormat.Yuv420: case Av1ColorFormat.Yuv420:
strideChroma = (strideY + 1) >> 1; strideChroma = (strideY + 1) >> 1;
heightChroma = (this.Height + 1) >> 1; heightChroma = (heightY + 1) >> 1;
break; break;
case Av1ColorFormat.Yuv422: case Av1ColorFormat.Yuv422:
strideChroma = (strideY + 1) >> 1; strideChroma = (strideY + 1) >> 1;
heightChroma = this.Height; heightChroma = heightY;
break; break;
case Av1ColorFormat.Yuv444: case Av1ColorFormat.Yuv444:
strideChroma = strideY; strideChroma = strideY;
heightChroma = this.Height; heightChroma = heightY;
break; break;
} }

18
src/ImageSharp/Formats/Heif/Av1/Prediction/Av1PredictionDecoder.cs

@ -24,6 +24,9 @@ internal class Av1PredictionDecoder
this.is16BitPipeline = is16BitPipeline; this.is16BitPipeline = is16BitPipeline;
} }
/// <summary>
/// SVT: svt_av1_predict_intra
/// </summary>
public void Decode( public void Decode(
Av1PartitionInfo partitionInfo, Av1PartitionInfo partitionInfo,
Av1Plane plane, Av1Plane plane,
@ -37,8 +40,11 @@ internal class Av1PredictionDecoder
{ {
int bytesPerPixel = (bitDepth == Av1BitDepth.EightBit && !this.is16BitPipeline) ? 2 : 1; int bytesPerPixel = (bitDepth == Av1BitDepth.EightBit && !this.is16BitPipeline) ? 2 : 1;
int stride = pixelStride * bytesPerPixel; int stride = pixelStride * bytesPerPixel;
Span<byte> topNeighbor = pixelBuffer.Slice(-stride);
Span<byte> leftNeighbor = pixelBuffer.Slice(-1); // Deviation from SVT: Buffer starts at PREVIOUS row.
Span<byte> topNeighbor = pixelBuffer;
Span<byte> leftNeighbor = pixelBuffer[(stride - 1)..];
Span<byte> startOfPixels = pixelBuffer[stride..];
bool is16BitPipeline = this.is16BitPipeline; bool is16BitPipeline = this.is16BitPipeline;
Av1PredictionMode mode = (plane == Av1Plane.Y) ? partitionInfo.ModeInfo.YMode : partitionInfo.ModeInfo.UvMode; Av1PredictionMode mode = (plane == Av1Plane.Y) ? partitionInfo.ModeInfo.YMode : partitionInfo.ModeInfo.UvMode;
@ -50,7 +56,7 @@ internal class Av1PredictionDecoder
plane, plane,
transformSize, transformSize,
tileInfo, tileInfo,
pixelBuffer, startOfPixels,
stride, stride,
topNeighbor, topNeighbor,
leftNeighbor, leftNeighbor,
@ -63,7 +69,7 @@ internal class Av1PredictionDecoder
this.PredictChromaFromLumaBlock( this.PredictChromaFromLumaBlock(
partitionInfo, partitionInfo,
partitionInfo.ChromaFromLumaContext, partitionInfo.ChromaFromLumaContext,
ref pixelBuffer, startOfPixels,
stride, stride,
transformSize, transformSize,
plane); plane);
@ -76,7 +82,7 @@ internal class Av1PredictionDecoder
plane, plane,
transformSize, transformSize,
tileInfo, tileInfo,
pixelBuffer, startOfPixels,
stride, stride,
topNeighbor, topNeighbor,
leftNeighbor, leftNeighbor,
@ -87,7 +93,7 @@ internal class Av1PredictionDecoder
bitDepth); bitDepth);
} }
private void PredictChromaFromLumaBlock(Av1PartitionInfo partitionInfo, Av1ChromaFromLumaContext? chromaFromLumaContext, ref Span<byte> pixelBuffer, int stride, Av1TransformSize transformSize, Av1Plane plane) private void PredictChromaFromLumaBlock(Av1PartitionInfo partitionInfo, Av1ChromaFromLumaContext? chromaFromLumaContext, Span<byte> pixelBuffer, int stride, Av1TransformSize transformSize, Av1Plane plane)
{ {
Av1BlockModeInfo modeInfo = partitionInfo.ModeInfo; Av1BlockModeInfo modeInfo = partitionInfo.ModeInfo;
bool isChromaFromLumaAllowedFlag = IsChromaFromLumaAllowedWithFrameHeader(partitionInfo, this.sequenceHeader.ColorConfig, this.frameHeader); bool isChromaFromLumaAllowedFlag = IsChromaFromLumaAllowedWithFrameHeader(partitionInfo, this.sequenceHeader.ColorConfig, this.frameHeader);

37
src/ImageSharp/Formats/Heif/Av1/Transform/Av1BlockDecoder.cs

@ -146,7 +146,6 @@ internal class Av1BlockDecoder
} }
// if (!inter_block) // if (!inter_block)
if (true)
{ {
// SVT: svt_av1_predict_intra // SVT: svt_av1_predict_intra
predictionDecoder.Decode( predictionDecoder.Decode(
@ -226,25 +225,29 @@ internal class Av1BlockDecoder
{ {
int blockOffset; int blockOffset;
if (plane == 0) switch (plane)
{ {
blockOffset = ((frameBuffer.OriginY + blockRowInPixels) * frameBuffer.BufferY!.Width) + case 0:
(frameBuffer.OriginX + blockColumnInPixels); reconstructionStride = frameBuffer.BufferY!.Width;
reconstructionStride = frameBuffer.BufferY!.Width; blockOffset = ((frameBuffer.OriginY + blockRowInPixels) * reconstructionStride) +
} (frameBuffer.OriginX + blockColumnInPixels);
else if (plane == 1) break;
{ case 1:
blockOffset = (((frameBuffer.OriginY >> subY) + blockRowInPixels) * frameBuffer.BufferCb!.Width) + reconstructionStride = frameBuffer.BufferCb!.Width;
((frameBuffer.OriginX >> subX) + blockColumnInPixels); blockOffset = (((frameBuffer.OriginY >> subY) + blockRowInPixels) * reconstructionStride) +
reconstructionStride = frameBuffer.BufferCb!.Width; ((frameBuffer.OriginX >> subX) + blockColumnInPixels);
} break;
else default:
{ reconstructionStride = frameBuffer.BufferCr!.Width;
blockOffset = (((frameBuffer.OriginY >> subY) + blockRowInPixels) * frameBuffer.BufferCr!.Width) + blockOffset = (((frameBuffer.OriginY >> subY) + blockRowInPixels) * reconstructionStride) +
((frameBuffer.OriginX >> subX) + blockColumnInPixels); ((frameBuffer.OriginX >> subX) + blockColumnInPixels);
reconstructionStride = frameBuffer.BufferCr!.Width; break;
} }
// Deviation from SVT, return PREVIOUS row in Block Reconstruction Buffer.
blockOffset -= reconstructionStride;
Guard.MustBeGreaterThanOrEqualTo(blockOffset, 0, nameof(blockOffset));
if (frameBuffer.BitDepth != Av1BitDepth.EightBit || frameBuffer.Is16BitPipeline) if (frameBuffer.BitDepth != Av1BitDepth.EightBit || frameBuffer.Is16BitPipeline)
{ {
// 16bit pipeline // 16bit pipeline

Loading…
Cancel
Save