• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2015 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
5import logging
6import os
7import re
8
9from autotest_lib.client.bin import test
10from autotest_lib.client.bin import utils
11from autotest_lib.client.common_lib import error
12from autotest_lib.client.common_lib.cros import chrome
13
14EXTRA_BROWSER_ARGS = ['--use-fake-ui-for-media-stream']
15
16# Statistics from the loopback.html page.
17TEST_PROGRESS = 'testProgress'
18
19# Polling timeout
20TIMEOUT = 240
21
22# max number of allowed blackframes or frozen frames
23BLACK_FRAMES_THRESHOLD = 10
24FROZEN_FRAMES_THRESHOLD = 10
25
26class video_WebRtcCamera(test.test):
27    """Local Peer connection test with webcam at 720p."""
28    version = 1
29
30    def start_loopback(self, cr):
31        """Opens WebRTC loopback page.
32
33        @param cr: Autotest Chrome instance.
34        """
35        cr.browser.platform.SetHTTPServerDirectories(self.bindir)
36
37        self.tab = cr.browser.tabs[0]
38        self.tab.Navigate(cr.browser.platform.http_server.UrlOf(
39                os.path.join(self.bindir, 'loopback.html')))
40        self.tab.WaitForDocumentReadyStateToBeComplete()
41
42
43    def webcam_supports_720p(self):
44        """Checks if 720p capture supported.
45
46        @returns: True if 720p supported, false if VGA is supported.
47        @raises: TestError if neither 720p nor VGA are supported.
48        """
49        cmd = 'lsusb -v'
50        # Get usb devices and make output a string with no newline marker.
51        usb_devices = utils.system_output(cmd, ignore_status=True).splitlines()
52        usb_devices = ''.join(usb_devices)
53
54        # Check if 720p resolution supported.
55        if re.search(r'\s+wWidth\s+1280\s+wHeight\s+720', usb_devices):
56            return True
57        # The device should support at least VGA.
58        # Otherwise the cam must be broken.
59        if re.search(r'\s+wWidth\s+640\s+wHeight\s+480', usb_devices):
60            return False
61        # This should not happen.
62        raise error.TestFail(
63                'Could not find any cameras reporting '
64                'either VGA or 720p in lsusb output: %s' % usb_devices)
65
66
67    def is_test_completed(self):
68        """Checks if WebRTC peerconnection test is done.
69
70        @returns True if test complete, False otherwise.
71
72        """
73        def test_done():
74          """Check the testProgress variable in HTML page."""
75
76          # Wait for test completion on web page.
77          test_progress = self.tab.EvaluateJavaScript(TEST_PROGRESS)
78          return test_progress == 1
79
80        try:
81            utils.poll_for_condition(
82                    test_done, timeout=TIMEOUT,
83                    exception=error.TestError(
84                        'Cannot find testProgress value.'),
85                    sleep_interval=1)
86        except error.TestError:
87            partial_results = self.tab.EvaluateJavaScript('getResults()')
88            logging.info('Here are the partial results so far: %s',
89                         partial_results)
90            return False
91        else:
92            return True
93
94
95    def run_once(self):
96        """Runs the video_WebRtcPeerConnectionWithCamera test."""
97        self.board = utils.get_current_board()
98        with chrome.Chrome(extra_browser_args=EXTRA_BROWSER_ARGS) as cr:
99            # Open WebRTC loopback page and start the loopback.
100            self.start_loopback(cr)
101            if not self.check_loopback_result():
102                raise error.TestFail('Failed webrtc camera test')
103
104
105    def check_loopback_result(self):
106        """Get the WebRTC Camera results."""
107        if not self.is_test_completed():
108            logging.error('loopback.html did not complete')
109            return False
110        try:
111            results = self.tab.EvaluateJavaScript('getResults()')
112        except:
113            logging.error('Cannot retrieve results from loopback.html page')
114            return False
115        logging.info('Results: %s', results)
116        for resolution in results:
117            item = results[resolution]
118            if (item['cameraErrors'] and resolution == '1280,720'
119                    and self.webcam_supports_720p()):
120                logging.error('Camera error: %s', item['cameraErrors'])
121                return False
122            if not item['frameStats']:
123                output_resolution = re.sub(',', 'x', resolution)
124                logging.error('Frame Stats is empty for resolution: %s',
125                              output_resolution)
126                return False
127
128            if item['frameStats']['numBlackFrames'] > BLACK_FRAMES_THRESHOLD:
129                logging.error('BlackFrames threshold overreach: '
130                              'got %s > %s allowed',
131                              item['frameStats']['numBlackFrames'],
132                              BLACK_FRAMES_THRESHOLD)
133                return False
134            if item['frameStats']['numFrozenFrames'] > FROZEN_FRAMES_THRESHOLD:
135                logging.error('FrozenFrames threshold overreach: '
136                              'got %s > %s allowed',
137                              item['frameStats']['numFrozenFrames'],
138                              FROZEN_FRAMES_THRESHOLD)
139                return False
140            if item['frameStats']['numFrames'] == 0:
141                logging.error('%s Frames were found',
142                              item['frameStats']['numFrames'])
143                return False
144
145        return True
146