// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using BenchmarkDotNet.Attributes; using SixLabors.ImageSharp.Formats.Heif.Hevc; namespace SixLabors.ImageSharp.Benchmarks.Codecs.Heif; /// /// Measures complete coded-frame traversal through HEVC inverse-transform reconstruction. /// [MemoryDiagnoser(displayGenColumns: false)] public class HevcInverseTransformBenchmarks { /// /// The coded frame width, which is an exact multiple of the maximum transform-block side. /// private const int Width = 1920; /// /// The coded frame height including the final padded coding-tree row for a 1080-line presentation. /// private const int Height = 1088; /// /// The base-two logarithm of the benchmark transform-block side. /// private const int BlockLog2 = 5; /// /// The transform-block side in samples. /// private const int BlockSize = 1 << BlockLog2; /// /// The deterministic dequantized coefficients reused by each benchmark block. /// private readonly int[] coefficients = new int[BlockSize * BlockSize]; /// /// The frame-wide predicted and reconstructed samples. /// private readonly ushort[] destination = new ushort[Width * Height]; /// /// The maximum-block inverse-transform scratch reused throughout each coded frame. /// private readonly int[] scratch = new int[HevcInverseTransformer.GetScratchLength(BlockLog2, BlockLog2)]; /// /// Populates a dense, deterministic twelve-bit transform workload outside the measured frame traversal. /// [GlobalSetup] public void Setup() { for (int i = 0; i < this.coefficients.Length; i++) { this.coefficients[i] = (((i * 37) + 11) % 127) - 63; } this.destination.AsSpan().Fill(2048); } /// /// Measures factorized inverse DCT, both transpositions, and saturated prediction addition for a coded frame. /// /// The final reconstructed sample, keeping the frame output observable. [Benchmark] public ushort TransformFrame() { for (int y = 0; y < Height; y += BlockSize) { for (int x = 0; x < Width; x += BlockSize) { HevcInverseTransformer.TransformAdd( this.coefficients, this.destination.AsSpan((y * Width) + x), Width, BlockLog2, BlockLog2, 12, 18, false, this.scratch); } } return this.destination[^1]; } }