1# Copyright 2018 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import logging
6import os
7from autotest_lib.client.common_lib import file_utils
8from autotest_lib.client.cros import chrome_binary_test
9from autotest_lib.client.cros.video import helper_logger
10
11DOWNLOAD_BASE = ('http://commondatastorage.googleapis.com/'
12                 'chromiumos-test-assets-public/')
13TEST_LOG = 'test_log'
14REPEAT_TIMES = 100
15TIME_UNIT = 'millisecond'
16HW_ENCODE_LABEL = 'hw_encode_time'
17SW_ENCODE_LABEL = 'sw_encode_time'
18LATENCY_50_SUFFIX = '.encode_latency.50_percentile'
19LATENCY_75_SUFFIX = '.encode_latency.75_percentile'
20LATENCY_95_SUFFIX = '.encode_latency.95_percentile'
21HW_PREFIX = 'hw_'
22SW_PREFIX = 'sw_'
23
24class video_JEAPerf(chrome_binary_test.ChromeBinaryTest):
25    """
26    This test monitors performance metrics reported by Chrome test binary,
27    jpeg_encode_accelerator_unittest.
28    """
29
30    version = 1
31    binary = 'jpeg_encode_accelerator_unittest'
32
33    def report_perf_results(self, test_name, output_path):
34        hw_times = []
35        sw_times = []
36        with open(output_path, 'r') as f:
37            lines = f.readlines()
38            lines = [line.strip() for line in lines]
39            for line in lines:
40                key_value = line.split(':')
41                if len(key_value) != 2:
42                    continue
43                (key, value) = (key_value[0].strip(), key_value[1].strip())
44                if key == HW_ENCODE_LABEL:
45                    hw_times.append(int(value))
46                if key == SW_ENCODE_LABEL:
47                    sw_times.append(int(value))
48        hw_times.sort()
49        sw_times.sort()
50
51        if len(hw_times) > 0:
52            percentile_50 = len(hw_times) / 2
53            percentile_75 = len(hw_times) * 3 / 4
54            percentile_95 = len(hw_times) * 95 / 100
55            test_title = HW_PREFIX + test_name
56            self.output_perf_value(description=(test_title + LATENCY_50_SUFFIX),
57                value=hw_times[percentile_50],
58                units=TIME_UNIT, higher_is_better=False)
59            self.output_perf_value(description=(test_title + LATENCY_75_SUFFIX),
60                value=hw_times[percentile_75],
61                units=TIME_UNIT, higher_is_better=False)
62            self.output_perf_value(description=(test_title + LATENCY_95_SUFFIX),
63                value=hw_times[percentile_95],
64                units=TIME_UNIT, higher_is_better=False)
65
66        if len(sw_times) > 0:
67            percentile_50 = len(sw_times) / 2
68            percentile_75 = len(sw_times) * 3 / 4
69            percentile_95 = len(sw_times) * 95 / 100
70            test_title = SW_PREFIX + test_name
71            self.output_perf_value(description=(test_title + LATENCY_50_SUFFIX),
72                value=sw_times[percentile_50],
73                units=TIME_UNIT, higher_is_better=False)
74            self.output_perf_value(description=(test_title + LATENCY_75_SUFFIX),
75                value=sw_times[percentile_75],
76                units=TIME_UNIT, higher_is_better=False)
77            self.output_perf_value(description=(test_title + LATENCY_95_SUFFIX),
78                value=sw_times[percentile_95],
79                units=TIME_UNIT, higher_is_better=False)
80
81    def remove_if_exists(self, file_path):
82        try:
83            os.remove(file_path)
84        except OSError as e:
85            if e.errno != errno.ENOENT:  # no such file
86                raise
87
88    @helper_logger.video_log_wrapper
89    @chrome_binary_test.nuke_chrome
90    def run_once(self, test_cases):
91        """
92        Runs JpegEncodeAcceleratorTest.SimpleEncode on the device and reports
93        latency values for HW and SW.
94        """
95
96        for (image_path, width, height) in test_cases:
97            url = DOWNLOAD_BASE + image_path
98            file_name = os.path.basename(image_path)
99            input_path = os.path.join(self.bindir, file_name)
100            file_utils.download_file(url, input_path)
101            test_name = ('%s_%dx%d' % (file_name, width, height))
102            output_path = os.path.join(self.tmpdir, TEST_LOG)
103
104            cmd_line_list = [helper_logger.chrome_vmodule_flag()] + [
105                '--gtest_filter=JpegEncodeAcceleratorTest.SimpleEncode',
106                ('--output_log=%s' % output_path),
107                ('--repeat=%d' % REPEAT_TIMES),
108                ('--yuv_filenames="%s:%dx%d"' % (input_path, width, height))
109            ]
110            cmd_line = ' '.join(cmd_line_list)
111            try:
112                self.run_chrome_test_binary(self.binary, cmd_line)
113                self.report_perf_results(test_name, output_path)
114            except Exception as last_error:
115                # Log the error and continue to the next test case.
116                logging.exception(last_error)
117            finally:
118                self.remove_if_exists(input_path)
119                self.remove_if_exists(output_path)
120
121