| # Copyright 2015 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import logging |
| import os |
| import re |
| |
| from autotest_lib.client.bin import test |
| from autotest_lib.client.bin import utils |
| from autotest_lib.client.common_lib import error |
| from autotest_lib.client.common_lib.cros import chrome |
| |
| EXTRA_BROWSER_ARGS = ['--use-fake-ui-for-media-stream'] |
| |
| # Statistics from the loopback.html page. |
| TEST_PROGRESS = 'testProgress' |
| |
| # Polling timeout |
| TIMEOUT = 90 |
| |
| RES_720P = [1280, 720] |
| RES_VGA = [640, 480] |
| |
| # max number of allowed blackframes or frozen frames |
| BLACK_FRAMES_THRESHOLD = 10 |
| FROZEN_FRAMES_THRESHOLD = 10 |
| |
| class video_WebRtcPeerConnectionWithCamera(test.test): |
| """Local Peer connection test with webcam at 720p.""" |
| version = 1 |
| |
| def start_loopback(self, cr): |
| """Opens WebRTC loopback page. |
| |
| @param cr: Autotest Chrome instance. |
| """ |
| cr.browser.platform.SetHTTPServerDirectories(self.bindir) |
| |
| self.tab = cr.browser.tabs[0] |
| self.tab.Navigate(cr.browser.platform.http_server.UrlOf( |
| os.path.join(self.bindir, 'loopback.html'))) |
| self.tab.WaitForDocumentReadyStateToBeComplete() |
| self.tab.EvaluateJavaScript("testCamera(%s)" % |
| self.chosen_resolution) |
| |
| |
| def webcam_supports_720p(self): |
| """Checks if 720p capture supported. |
| |
| @returns: True if 720p supported, false if VGA is supported. |
| @raises: TestError if neither 720p nor VGA are supported. |
| """ |
| cmd = 'lsusb -v' |
| # Get usb devices and make output a string with no newline marker. |
| usb_devices = utils.system_output(cmd, ignore_status=True).splitlines() |
| usb_devices = ''.join(usb_devices) |
| |
| # Check if 720p resolution supported. |
| if re.search(r'\s+wWidth\s+1280\s+wHeight\s+720', usb_devices): |
| return True |
| # The device should support at least VGA. |
| # Otherwise the cam must be broken. |
| if re.search(r'\s+wWidth\s+640\s+wHeight\s+480', usb_devices): |
| return False |
| # This should not happen. |
| raise error.TestFail( |
| 'Could not find any cameras reporting ' |
| 'either VGA or 720p in lsusb output: %s' % usb_devices) |
| |
| |
| def is_test_completed(self): |
| """Checks if WebRTC peerconnection test is done. |
| |
| @returns True if test complete, False otherwise. |
| |
| """ |
| def test_done(): |
| """Check the testProgress variable in HTML page.""" |
| |
| # Wait for test completion on web page. |
| test_progress = self.tab.EvaluateJavaScript(TEST_PROGRESS) |
| return test_progress == 1 |
| |
| try: |
| utils.poll_for_condition( |
| test_done, timeout=TIMEOUT, |
| exception=error.TestError('Cannot find testProgress value.'), |
| sleep_interval=1) |
| except error.TestError: |
| partial_results = self.tab.EvaluateJavaScript('getResults()') |
| logging.info('Here are the partial results so far: %s', |
| partial_results) |
| return False |
| else: |
| return True |
| |
| |
| def run_once(self): |
| """Runs the video_WebRtcPeerConnectionWithCamera test.""" |
| # Check webcamera resolution capabilities. |
| # Some laptops have low resolution capture. |
| if self.webcam_supports_720p(): |
| self.chosen_resolution = RES_720P |
| else: |
| self.chosen_resolution = RES_VGA |
| with chrome.Chrome(extra_browser_args=EXTRA_BROWSER_ARGS) as cr: |
| # Open WebRTC loopback page and start the loopback. |
| self.start_loopback(cr) |
| if not self.check_loopback_result(): |
| raise error.TestFail('Failed %s local peer connection test' % |
| self.chosen_resolution) |
| |
| |
| def check_loopback_result(self): |
| """Get the WebRTC Peerconnection loopback results.""" |
| if not self.is_test_completed(): |
| logging.error('loopback.html did not complete') |
| return False |
| try: |
| results = self.tab.EvaluateJavaScript('getResults()') |
| except: |
| logging.error('Cannot retrieve results from loopback.html page') |
| return False |
| logging.info('Camera Type: %s', results['cameraType']) |
| logging.info('Camera Errors: %s', results['cameraErrors']) |
| logging.info('PeerConnectionstats: %s', |
| results['peerConnectionStats']) |
| logging.info('FrameStats: %s', results['frameStats']) |
| if results['cameraErrors']: |
| logging.error('Camera error: %s', results['cameraErrors']) |
| return False |
| if not results['peerConnectionStats']: |
| logging.info('Peer Connection Stats is empty') |
| return False |
| if results['peerConnectionStats'][1] == 0: |
| logging.error('Max Input FPS is zero') |
| return False |
| if results['peerConnectionStats'][4] == 0: |
| logging.error('Max Sent FPS is zero') |
| return False |
| if not results['frameStats']: |
| logging.error('Frame Stats is empty') |
| return False |
| if results['frameStats']['numBlackFrames'] > BLACK_FRAMES_THRESHOLD: |
| logging.error('BlackFrames threshold overreach: ' |
| 'got %s > %s allowed', |
| results['frameStats']['numBlackFrames'], |
| BLACK_FRAMES_THRESHOLD) |
| return False |
| if results['frameStats']['numFrozenFrames'] > FROZEN_FRAMES_THRESHOLD: |
| logging.error('Frozen Frames threshold overreach: ' |
| 'got %s > %s allowed', |
| results['frameStats']['numFrozenFrames'], |
| FROZEN_FRAMES_THRESHOLD) |
| return False |
| if results['frameStats']['numFrames'] == 0: |
| logging.error('%s Frames were found', |
| results['frameStats']['numFrames']) |
| return False |
| return True |