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