1# Copyright (c) 2014 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
5from contextlib import closing
6import logging
7import os
8import re
9import time
10
11from autotest_lib.client.bin import test, utils
12from autotest_lib.client.common_lib import error
13from autotest_lib.client.common_lib import file_utils
14from autotest_lib.client.common_lib.cros import chrome
15
16
17# Chrome flags to use fake camera and skip camera permission.
18EXTRA_BROWSER_ARGS = ['--use-fake-device-for-media-stream',
19                      '--use-fake-ui-for-media-stream']
20FAKE_FILE_ARG = '--use-file-for-fake-video-capture="%s"'
21DOWNLOAD_BASE = 'http://commondatastorage.googleapis.com/chromiumos-test-assets-public/crowd/'
22VIDEO_NAME = 'crowd720_25frames.y4m'
23
24RTC_VIDEO_ENCODE = 'Media.RTCVideoEncoderInitEncodeSuccess'
25RTC_VIDEO_ENCODE_BUCKET = 1
26RTC_ENCODE_PROFILE = 'Media.RTCVideoEncoderProfile'
27RTC_ENCODE_PROFILE_BUCKET = 11
28HISTOGRAMS_URL = 'chrome://histograms/'
29
30class video_ChromeRTCHWEncodeUsed(test.test):
31    """The test verifies HW Encoding for WebRTC video."""
32    version = 1
33
34
35    def start_loopback(self, cr):
36        """
37        Opens WebRTC loopback page.
38
39        @param cr: Autotest Chrome instance.
40        """
41        tab = cr.browser.tabs[0]
42        tab.Navigate(cr.browser.platform.http_server.UrlOf(
43                os.path.join(self.bindir, 'loopback.html')))
44        tab.WaitForDocumentReadyStateToBeComplete()
45
46
47    def assert_hardware_accelerated(self, cr):
48        """
49        Checks if WebRTC decoding is hardware accelerated.
50
51        @param cr: Autotest Chrome instance.
52
53        @raises error.TestError if decoding is not hardware accelerated.
54        """
55        tab = cr.browser.tabs.New()
56        def histograms_loaded(histogram):
57            """Returns true if histogram is loaded."""
58            tab.Navigate(HISTOGRAMS_URL + histogram)
59            tab.WaitForDocumentReadyStateToBeComplete()
60            return tab.EvaluateJavaScript(
61                    'document.documentElement.innerText.search("%s") != -1'
62                    % histogram)
63
64        def histogram_sucess(histogram, bucket):
65            lines = tab.EvaluateJavaScript(
66                    'document.documentElement.innerText').split("\n")
67            lines = [line for line in lines if line.strip()]
68            logging.info('Histograms for %s:', histogram )
69            logging.info(lines)
70            success = False
71            for line in lines:
72                re_string = '^'+ str(bucket) +'\s\s-(.*)100.0%(.*)'
73                if re.match(re_string, line):
74                    success = True
75                    break
76            if not success:
77                raise error.TestError(
78                        '{0} didn\'t show up or is not 100%'
79                        ' successful.'.format(histogram))
80
81        for histogram, bucket in [(RTC_VIDEO_ENCODE, RTC_VIDEO_ENCODE_BUCKET),
82                (RTC_ENCODE_PROFILE, RTC_ENCODE_PROFILE_BUCKET)]:
83            utils.poll_for_condition(
84                    lambda: histograms_loaded(histogram),
85                    timeout=5,
86                    exception=error.TestError(
87                            'Cannot find %s histogram.' % histogram),
88                    sleep_interval=1)
89            histogram_sucess(histogram, bucket)
90
91
92    def run_once(self):
93        # Download test video.
94        url = DOWNLOAD_BASE + VIDEO_NAME
95        local_path = os.path.join(self.bindir, VIDEO_NAME)
96        file_utils.download_file(url, local_path)
97
98        # Start chrome with test flags.
99        EXTRA_BROWSER_ARGS.append(FAKE_FILE_ARG % local_path)
100        with chrome.Chrome(extra_browser_args=EXTRA_BROWSER_ARGS) as cr:
101            # Open WebRTC loopback page.
102            cr.browser.platform.SetHTTPServerDirectories(self.bindir)
103            self.start_loopback(cr)
104
105            # Make sure decode is hardware accelerated.
106            self.assert_hardware_accelerated(cr)
107