1# Copyright (c) 2013 The Chromium OS 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
5"""Test to probe the video capability."""
6import glob, logging, os, sys
7
8from autotest_lib.client.bin import test, utils
9from autotest_lib.client.common_lib import error
10
11# The following VA_XXX values are copied from va/va.h
12# VA profiles that we are interested in
13VAProfileH264Main = 6
14VAProfileH264High = 7
15VAProfileH264ConstrainedBaseline = 13
16
17# VA Entrypoint that we are interested in
18VAEntrypointVLD = 1
19
20# VA_RT_FORMAT that we are interested in
21VA_RT_FORMAT_YUV420 = 0x01
22
23KEY_DEVICE = 'device'
24KEY_FORMATS = 'formats'
25
26class hardware_VideoDecodeCapable(test.test):
27    """Test class to verify hardware video decoding capability."""
28
29    version = 1
30
31    REQUESTED_VAAPI_PROFILES = [
32        VAProfileH264ConstrainedBaseline,
33        VAProfileH264Main,
34        VAProfileH264High]
35
36    REQUESTED_V4L2_FORMATS = [
37        # Requested formats for decoding devices
38        {KEY_DEVICE: '/dev/video-dec',
39         KEY_FORMATS: ['cap_fmt_VM12', 'cap_fmt_NM12',
40                      'out_fmt_H264', 'out_fmt_VP80']},
41        # REQUESTED formats for GSCALER devices
42        {KEY_DEVICE: '/dev/gsc*',
43         KEY_FORMATS: ['cap_fmt_RGB4', 'out_fmt_VM12']}]
44
45
46    def assertTrue(self, condition, message = '', *args):
47        """Raises an TestFail when the assertion failed"""
48        if (not condition):
49            raise error.TestFail(message % args)
50
51
52    def verifyProfile(self, vaapi, display, profile):
53        """Verifies the given profile satisfies the requirements.
54
55        1. It has the VLD entrypoint
56        2. It supports  YUV420 for RT_FORMAT
57
58        @param vaapi: the vaapi module
59
60        @param display: the va_display instance
61
62        @param profile: the profile under test
63
64        @raise error.TestFail: when verification fails
65        """
66        entrypoints = vaapi.query_entrypoints(display, profile)
67        logging.info('Entrypoints of profile %s: %s', profile, entrypoints)
68        self.assertTrue(VAEntrypointVLD in entrypoints,
69                        'VAEntrypointVLD is not supported')
70
71        rt_format = vaapi.get_rt_format(display, profile, VAEntrypointVLD)
72        logging.info('RT_Format: %s', rt_format)
73        self.assertTrue(VA_RT_FORMAT_YUV420 & rt_format,
74                        'VA_RT_FORMAT_YUV420 is not supported')
75
76
77    def setup(self):
78        os.chdir(self.srcdir)
79
80        # Ignores the fail status since vaapi module won't get built on
81        # platforms without VAAPI support (e.g., Daisy). On those platforms
82        # we will test with the v4l2 module.
83        utils.make('v4l2', ignore_status = True)
84        utils.make('vaapi', ignore_status = True)
85        utils.make('vaapi_drm', ignore_status = True)
86
87
88    def run_once_vaapi(self):
89        sys.path.append(self.bindir)
90        import vaapi
91
92        if not utils.is_freon():
93            # Set the XAUTHORITY for connecting to the X server
94            utils.assert_has_X_server()
95            os.environ.setdefault('XAUTHORITY', '/home/chronos/.Xauthority')
96
97            display = vaapi.create_display(':0.0')
98        else:
99            display = vaapi.create_display('/dev/dri/card0')
100
101        supported_profiles = vaapi.query_profiles(display)
102        logging.info('Vaapi Profiles: %s', supported_profiles)
103
104        for profile in self.REQUESTED_VAAPI_PROFILES:
105            self.assertTrue(profile in supported_profiles,
106                            'Profile:%s is not supported',
107                            profile)
108            self.verifyProfile(vaapi, display, profile)
109
110
111    def _enum_formats(self, video_device):
112        """Use the v4l2 binary to enum formats.
113
114        Runs the embedded v4l2 binary to enumerate supported
115        capture formats and output formats.
116
117        @param video_device: device interrogated (e.g. /dev/video-dec).
118
119        @return a dict of keyvals reflecting the formats supported.
120        """
121        sys.path.append(self.bindir)
122        import v4l2
123
124        capture_formats = v4l2.enum_capture_formats(video_device)
125        logging.info('%s, capture formats=%s', video_device, capture_formats)
126        output_formats = v4l2.enum_output_formats(video_device)
127        logging.info('%s, output formats=%s', video_device, output_formats)
128
129        return (['cap_fmt_%s' % fmt for fmt in capture_formats] +
130                ['out_fmt_%s' % fmt for fmt in output_formats])
131
132
133    def run_once_v4l2(self):
134        """Check supported image formats for all expected device nodes
135        """
136        for rules in self.REQUESTED_V4L2_FORMATS:
137            formats = rules[KEY_FORMATS]
138            devices = glob.glob(rules[KEY_DEVICE])
139            self.assertTrue(len(devices) > 0,
140                            'No matched devices: %s', rules[KEY_DEVICE])
141            for device in devices:
142                missed = set(formats) - set(self._enum_formats(device))
143                self.assertTrue(not missed,
144                                'Formats: %s is not supported for device: %s',
145                                missed, device)
146
147    def run_once(self, type='v4l2'):
148        if type == 'v4l2':
149            self.run_once_v4l2()
150        else:
151            self.run_once_vaapi()
152
153