• 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 = 90
21
22RES_720P = [1280, 720]
23RES_VGA = [640, 480]
24
25# max number of allowed blackframes or frozen frames
26BLACK_FRAMES_THRESHOLD = 10
27FROZEN_FRAMES_THRESHOLD = 10
28
29class video_WebRtcPeerConnectionWithCamera(test.test):
30    """Local Peer connection test with webcam at 720p."""
31    version = 1
32
33    def start_loopback(self, cr):
34        """Opens WebRTC loopback page.
35
36        @param cr: Autotest Chrome instance.
37        """
38        cr.browser.platform.SetHTTPServerDirectories(self.bindir)
39
40        self.tab = cr.browser.tabs[0]
41        self.tab.Navigate(cr.browser.platform.http_server.UrlOf(
42                os.path.join(self.bindir, 'loopback.html')))
43        self.tab.WaitForDocumentReadyStateToBeComplete()
44        self.tab.EvaluateJavaScript("testCamera(%s)" %
45                                    self.chosen_resolution)
46
47
48    def webcam_supports_720p(self):
49        """Checks if 720p capture supported.
50
51        @returns: True if 720p supported, false if VGA is supported.
52        @raises: TestError if neither 720p nor VGA are supported.
53        """
54        cmd = 'lsusb -v'
55        # Get usb devices and make output a string with no newline marker.
56        usb_devices = utils.system_output(cmd, ignore_status=True).splitlines()
57        usb_devices = ''.join(usb_devices)
58
59        # Check if 720p resolution supported.
60        if re.search(r'\s+wWidth\s+1280\s+wHeight\s+720', usb_devices):
61            return True
62        # The device should support at least VGA.
63        # Otherwise the cam must be broken.
64        if re.search(r'\s+wWidth\s+640\s+wHeight\s+480', usb_devices):
65            return False
66        # This should not happen.
67        raise error.TestFail(
68                'Could not find any cameras reporting '
69                'either VGA or 720p in lsusb output: %s' % usb_devices)
70
71
72    def is_test_completed(self):
73        """Checks if WebRTC peerconnection test is done.
74
75        @returns True if test complete, False otherwise.
76
77        """
78        def test_done():
79          """Check the testProgress variable in HTML page."""
80
81          # Wait for test completion on web page.
82          test_progress = self.tab.EvaluateJavaScript(TEST_PROGRESS)
83          return test_progress == 1
84
85        try:
86            utils.poll_for_condition(
87                    test_done, timeout=TIMEOUT,
88                    exception=error.TestError('Cannot find testProgress value.'),
89                    sleep_interval=1)
90        except error.TestError:
91            partial_results = self.tab.EvaluateJavaScript('getResults()')
92            logging.info('Here are the partial results so far: %s',
93                         partial_results)
94            return False
95        else:
96            return True
97
98
99    def run_once(self):
100        """Runs the video_WebRtcPeerConnectionWithCamera test."""
101        # Check webcamera resolution capabilities.
102        # Some laptops have low resolution capture.
103        if self.webcam_supports_720p():
104          self.chosen_resolution = RES_720P
105        else:
106          self.chosen_resolution =  RES_VGA
107        with chrome.Chrome(extra_browser_args=EXTRA_BROWSER_ARGS) as cr:
108            # Open WebRTC loopback page and start the loopback.
109            self.start_loopback(cr)
110            if not self.check_loopback_result():
111                raise error.TestFail('Failed %s local peer connection test' %
112                                     self.chosen_resolution)
113
114
115    def check_loopback_result(self):
116        """Get the WebRTC Peerconnection loopback results."""
117        if not self.is_test_completed():
118            logging.error('loopback.html did not complete')
119            return False
120        try:
121            results = self.tab.EvaluateJavaScript('getResults()')
122        except:
123            logging.error('Cannot retrieve results from loopback.html page')
124            return False
125        logging.info('Camera Type: %s', results['cameraType'])
126        logging.info('Camera Errors: %s', results['cameraErrors'])
127        logging.info('PeerConnectionstats: %s',
128                     results['peerConnectionStats'])
129        logging.info('FrameStats: %s', results['frameStats'])
130        if results['cameraErrors']:
131            logging.error('Camera error: %s', results['cameraErrors'])
132            return False
133        if not results['peerConnectionStats']:
134            logging.info('Peer Connection Stats is empty')
135            return False
136        if results['peerConnectionStats'][1] == 0:
137            logging.error('Max Input FPS is zero')
138            return False
139        if results['peerConnectionStats'][4] == 0:
140            logging.error('Max Sent FPS is zero')
141            return False
142        if not results['frameStats']:
143            logging.error('Frame Stats is empty')
144            return False
145        if results['frameStats']['numBlackFrames'] > BLACK_FRAMES_THRESHOLD:
146            logging.error('BlackFrames threshold overreach: '
147                          'got %s > %s allowed',
148                          results['frameStats']['numBlackFrames'],
149                          BLACK_FRAMES_THRESHOLD)
150            return False
151        if results['frameStats']['numFrozenFrames'] > FROZEN_FRAMES_THRESHOLD:
152            logging.error('Frozen Frames threshold overreach: '
153                          'got %s > %s allowed',
154                          results['frameStats']['numFrozenFrames'],
155                          FROZEN_FRAMES_THRESHOLD)
156            return False
157        if results['frameStats']['numFrames'] == 0:
158            logging.error('%s Frames were found',
159                          results['frameStats']['numFrames'])
160            return False
161        return True
162