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 13from autotest_lib.client.cros.video import helper_logger 14 15EXTRA_BROWSER_ARGS = ['--use-fake-ui-for-media-stream'] 16 17# Variables from the getusermedia.html page. 18IS_TEST_DONE = 'isTestDone' 19 20# Polling timeout. 21SEVERAL_MINUTES_IN_SECS = 240 22 23 24class video_WebRtcCamera(test.test): 25 """Local getUserMedia test with webcam at VGA (and 720p, if supported).""" 26 version = 1 27 28 def start_getusermedia(self, cr): 29 """Opens the test page. 30 31 @param cr: Autotest Chrome instance. 32 """ 33 cr.browser.platform.SetHTTPServerDirectories(self.bindir) 34 35 self.tab = cr.browser.tabs[0] 36 self.tab.Navigate(cr.browser.platform.http_server.UrlOf( 37 os.path.join(self.bindir, 'getusermedia.html'))) 38 self.tab.WaitForDocumentReadyStateToBeComplete() 39 40 41 def webcam_supports_720p(self): 42 """Checks if 720p capture supported. 43 44 @returns: True if 720p supported, false if VGA is supported. 45 @raises: TestError if neither 720p nor VGA are supported. 46 """ 47 cmd = 'lsusb -v' 48 # Get usb devices and make output a string with no newline marker. 49 usb_devices = utils.system_output(cmd, ignore_status=True).splitlines() 50 usb_devices = ''.join(usb_devices) 51 52 # Check if 720p resolution supported. 53 if re.search(r'\s+wWidth\s+1280\s+wHeight\s+720', usb_devices): 54 return True 55 # The device should support at least VGA. 56 # Otherwise the cam must be broken. 57 if re.search(r'\s+wWidth\s+640\s+wHeight\s+480', usb_devices): 58 return False 59 # This should not happen. 60 raise error.TestFail( 61 'Could not find any cameras reporting ' 62 'either VGA or 720p in lsusb output: %s' % usb_devices) 63 64 65 def wait_test_completed(self, timeout_secs): 66 """Waits until the test is done. 67 68 @param timeout_secs Max time to wait in seconds. 69 70 @raises TestError on timeout, or javascript eval fails. 71 """ 72 def _test_done(): 73 is_test_done = self.tab.EvaluateJavaScript(IS_TEST_DONE) 74 return is_test_done == 1 75 76 utils.poll_for_condition( 77 _test_done, timeout=timeout_secs, sleep_interval=1, 78 desc=('getusermedia.html:reportTestDone did not run. Test did not ' 79 'complete successfully.')) 80 81 @helper_logger.video_log_wrapper 82 def run_once(self): 83 """Runs the test.""" 84 self.board = utils.get_current_board() 85 with chrome.Chrome(extra_browser_args=EXTRA_BROWSER_ARGS +\ 86 [helper_logger.chrome_vmodule_flag()], 87 init_network_controller=True) as cr: 88 self.start_getusermedia(cr) 89 self.print_perf_results() 90 91 92 def print_perf_results(self): 93 """Prints the perf results unless there was an error. 94 95 @returns the empty string if perf results were printed, otherwise 96 a description of the error that occured. 97 """ 98 self.wait_test_completed(SEVERAL_MINUTES_IN_SECS) 99 try: 100 results = self.tab.EvaluateJavaScript('getResults()') 101 except Exception as e: 102 raise error.TestFail('Failed to get getusermedia.html results', e) 103 logging.info('Results: %s', results) 104 105 errors = [] 106 for width_height, data in results.iteritems(): 107 resolution = re.sub(',', 'x', width_height) 108 if data['cameraErrors']: 109 if (resolution == '1280x720' and 110 not self.webcam_supports_720p()): 111 logging.info('Accepting 720p failure since device webcam ' 112 'does not support 720p') 113 continue 114 115 # Else we had a VGA failure or a legit 720p failure. 116 errors.append('Camera error: %s for resolution ' 117 '%s.' % (data['cameraErrors'], resolution)) 118 continue 119 if not data['frameStats']: 120 errors.append('Frame Stats is empty ' 121 'for resolution: %s' % resolution) 122 continue 123 self.output_perf_value( 124 description='black_frames_%s' % resolution, 125 value=data['frameStats']['numBlackFrames'], 126 units='frames', higher_is_better=False) 127 self.output_perf_value( 128 description='frozen_frames_%s' % resolution, 129 value=data['frameStats']['numFrozenFrames'], 130 units='frames', higher_is_better=False) 131 self.output_perf_value( 132 description='total_num_frames_%s' % resolution, 133 value=data['frameStats']['numFrames'], 134 units='frames', higher_is_better=True) 135 if errors: 136 raise error.TestFail('Found errors: %s' % ', '.join(errors)) 137