1cc1dc7a3Sopenharmony_ci#!/usr/bin/env python3
2cc1dc7a3Sopenharmony_ci# SPDX-License-Identifier: Apache-2.0
3cc1dc7a3Sopenharmony_ci# -----------------------------------------------------------------------------
4cc1dc7a3Sopenharmony_ci# Copyright 2021-2022 Arm Limited
5cc1dc7a3Sopenharmony_ci#
6cc1dc7a3Sopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License"); you may not
7cc1dc7a3Sopenharmony_ci# use this file except in compliance with the License. You may obtain a copy
8cc1dc7a3Sopenharmony_ci# of the License at:
9cc1dc7a3Sopenharmony_ci#
10cc1dc7a3Sopenharmony_ci#     http://www.apache.org/licenses/LICENSE-2.0
11cc1dc7a3Sopenharmony_ci#
12cc1dc7a3Sopenharmony_ci# Unless required by applicable law or agreed to in writing, software
13cc1dc7a3Sopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14cc1dc7a3Sopenharmony_ci# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15cc1dc7a3Sopenharmony_ci# License for the specific language governing permissions and limitations
16cc1dc7a3Sopenharmony_ci# under the License.
17cc1dc7a3Sopenharmony_ci# -----------------------------------------------------------------------------
18cc1dc7a3Sopenharmony_ci"""
19cc1dc7a3Sopenharmony_ciThe ``astc_quality_test`` utility provides a tool to sweep quality settings.
20cc1dc7a3Sopenharmony_ci"""
21cc1dc7a3Sopenharmony_ci
22cc1dc7a3Sopenharmony_ciimport numpy as np
23cc1dc7a3Sopenharmony_ciimport re
24cc1dc7a3Sopenharmony_ciimport subprocess as sp
25cc1dc7a3Sopenharmony_ciimport sys
26cc1dc7a3Sopenharmony_ci
27cc1dc7a3Sopenharmony_ci
28cc1dc7a3Sopenharmony_cidef get_psnr_pattern():
29cc1dc7a3Sopenharmony_ci    return r"\s*PSNR \(LDR-RGB\):\s*([0-9.]*) dB"
30cc1dc7a3Sopenharmony_ci
31cc1dc7a3Sopenharmony_ci
32cc1dc7a3Sopenharmony_cidef get_coding_rate_pattern():
33cc1dc7a3Sopenharmony_ci    return r"\s*Coding rate:\s*([0-9.]*) MT/s"
34cc1dc7a3Sopenharmony_ci
35cc1dc7a3Sopenharmony_ci
36cc1dc7a3Sopenharmony_cidef parse_output(output):
37cc1dc7a3Sopenharmony_ci    # Regex pattern for image quality
38cc1dc7a3Sopenharmony_ci    patternPSNR = re.compile(get_psnr_pattern())
39cc1dc7a3Sopenharmony_ci    patternCRate = re.compile(get_coding_rate_pattern())
40cc1dc7a3Sopenharmony_ci
41cc1dc7a3Sopenharmony_ci    # Extract results from the log
42cc1dc7a3Sopenharmony_ci    runPSNR = None
43cc1dc7a3Sopenharmony_ci    runCRate = None
44cc1dc7a3Sopenharmony_ci
45cc1dc7a3Sopenharmony_ci    for line in output:
46cc1dc7a3Sopenharmony_ci        match = patternPSNR.match(line)
47cc1dc7a3Sopenharmony_ci        if match:
48cc1dc7a3Sopenharmony_ci            runPSNR = float(match.group(1))
49cc1dc7a3Sopenharmony_ci
50cc1dc7a3Sopenharmony_ci        match = patternCRate.match(line)
51cc1dc7a3Sopenharmony_ci        if match:
52cc1dc7a3Sopenharmony_ci            runCRate = float(match.group(1))
53cc1dc7a3Sopenharmony_ci
54cc1dc7a3Sopenharmony_ci    assert runPSNR is not None, "No coding PSNR found"
55cc1dc7a3Sopenharmony_ci    assert runCRate is not None, "No coding rate found"
56cc1dc7a3Sopenharmony_ci    return (runPSNR, runCRate)
57cc1dc7a3Sopenharmony_ci
58cc1dc7a3Sopenharmony_cidef execute(command):
59cc1dc7a3Sopenharmony_ci    """
60cc1dc7a3Sopenharmony_ci    Run a subprocess with the specified command.
61cc1dc7a3Sopenharmony_ci
62cc1dc7a3Sopenharmony_ci    Args:
63cc1dc7a3Sopenharmony_ci        command (list(str)): The list of command line arguments.
64cc1dc7a3Sopenharmony_ci
65cc1dc7a3Sopenharmony_ci    Returns:
66cc1dc7a3Sopenharmony_ci        list(str): The output log (stdout) split into lines.
67cc1dc7a3Sopenharmony_ci    """
68cc1dc7a3Sopenharmony_ci    try:
69cc1dc7a3Sopenharmony_ci        result = sp.run(command, stdout=sp.PIPE, stderr=sp.PIPE,
70cc1dc7a3Sopenharmony_ci                        check=True, universal_newlines=True)
71cc1dc7a3Sopenharmony_ci    except (OSError, sp.CalledProcessError):
72cc1dc7a3Sopenharmony_ci        print("ERROR: Test run failed")
73cc1dc7a3Sopenharmony_ci        print("  + %s" % " ".join(command))
74cc1dc7a3Sopenharmony_ci        qcommand = ["\"%s\"" % x for x in command]
75cc1dc7a3Sopenharmony_ci        print("  + %s" % ", ".join(qcommand))
76cc1dc7a3Sopenharmony_ci        sys.exit(1)
77cc1dc7a3Sopenharmony_ci
78cc1dc7a3Sopenharmony_ci    return result.stdout.splitlines()
79cc1dc7a3Sopenharmony_ci
80cc1dc7a3Sopenharmony_cidef main():
81cc1dc7a3Sopenharmony_ci    """
82cc1dc7a3Sopenharmony_ci    The main function.
83cc1dc7a3Sopenharmony_ci
84cc1dc7a3Sopenharmony_ci    Returns:
85cc1dc7a3Sopenharmony_ci        int: The process return code.
86cc1dc7a3Sopenharmony_ci    """
87cc1dc7a3Sopenharmony_ci    for block in ("4x4", "5x5", "6x6", "8x8", "10x10"):
88cc1dc7a3Sopenharmony_ci
89cc1dc7a3Sopenharmony_ci        for quality in range (0, 101, 2):
90cc1dc7a3Sopenharmony_ci
91cc1dc7a3Sopenharmony_ci            resultsQ = []
92cc1dc7a3Sopenharmony_ci            resultsS = []
93cc1dc7a3Sopenharmony_ci
94cc1dc7a3Sopenharmony_ci            if (quality < 40):
95cc1dc7a3Sopenharmony_ci                repeats = 20
96cc1dc7a3Sopenharmony_ci            elif (quality < 75):
97cc1dc7a3Sopenharmony_ci                repeats = 10
98cc1dc7a3Sopenharmony_ci            else:
99cc1dc7a3Sopenharmony_ci                repeats = 5
100cc1dc7a3Sopenharmony_ci
101cc1dc7a3Sopenharmony_ci            for _ in range(0, repeats):
102cc1dc7a3Sopenharmony_ci                command = [
103cc1dc7a3Sopenharmony_ci                    "./bin/astcenc-avx2",
104cc1dc7a3Sopenharmony_ci                    "-tl",
105cc1dc7a3Sopenharmony_ci                    "./Test/Images/Kodak/LDR-RGB/ldr-rgb-kodak23.png",
106cc1dc7a3Sopenharmony_ci                    "/dev/null",
107cc1dc7a3Sopenharmony_ci                    block,
108cc1dc7a3Sopenharmony_ci                    "%s" % quality,
109cc1dc7a3Sopenharmony_ci                    "-silent"
110cc1dc7a3Sopenharmony_ci                ]
111cc1dc7a3Sopenharmony_ci
112cc1dc7a3Sopenharmony_ci                stdout = execute(command)
113cc1dc7a3Sopenharmony_ci                psnr, mts = parse_output(stdout)
114cc1dc7a3Sopenharmony_ci                resultsQ.append(psnr)
115cc1dc7a3Sopenharmony_ci                resultsS.append(mts)
116cc1dc7a3Sopenharmony_ci
117cc1dc7a3Sopenharmony_ci            print("%s, %u, %0.3f, %0.3f" % (block, quality, np.mean(resultsS), np.mean(resultsQ)))
118cc1dc7a3Sopenharmony_ci
119cc1dc7a3Sopenharmony_ci
120cc1dc7a3Sopenharmony_ci    return 0
121cc1dc7a3Sopenharmony_ci
122cc1dc7a3Sopenharmony_ci
123cc1dc7a3Sopenharmony_ciif __name__ == "__main__":
124cc1dc7a3Sopenharmony_ci    sys.exit(main())
125