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 time 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 from autotest_lib.client.cros.video import device_capability 14 from autotest_lib.client.cros.video import helper_logger 15 16 EXTRA_BROWSER_ARGS = ['--use-fake-ui-for-media-stream'] 17 18 # Variables from the getusermedia.html page. 19 IS_VIDEO_INPUT_FOUND = 'isVideoInputFound' 20 21 # Polling timeout. 22 TIMEOUT = 90 23 24 25 class video_WebRtcPeerConnectionWithCamera(test.test): 26 """Tests a full WebRTC call with a real webcam.""" 27 version = 1 28 29 def cleanup(self): 30 """Autotest cleanup function 31 32 It is run by common_lib/test.py. 33 """ 34 if utils.is_virtual_machine(): 35 try: 36 utils.run('sudo modprobe -r vivid') 37 except Exception as e: 38 raise error.TestFail('Failed to unload vivid', e) 39 40 def start_loopback(self, cr, video_codec): 41 """Opens WebRTC loopback page. 42 43 @param cr: Autotest Chrome instance. 44 @param video_codec: video codec to use. 45 """ 46 cr.browser.platform.SetHTTPServerDirectories(self.bindir) 47 48 self.tab = cr.browser.tabs[0] 49 self.tab.Navigate(cr.browser.platform.http_server.UrlOf( 50 os.path.join(self.bindir, 'loopback.html'))) 51 self.tab.WaitForDocumentReadyStateToBeComplete() 52 53 if utils.is_virtual_machine(): 54 # Make sure if Chrome has already recognized vivid as an 55 # external camera before calling 'getUserMedia()'. 56 self.wait_camera_detected() 57 58 self.tab.EvaluateJavaScript( 59 "testWebRtcLoopbackCall('%s')" % video_codec) 60 61 def wait_camera_detected(self): 62 """Waits until a camera is detected. 63 """ 64 for _ in range(10): 65 self.tab.EvaluateJavaScript('checkVideoInput()') 66 if self.tab.EvaluateJavaScript(IS_VIDEO_INPUT_FOUND): 67 return 68 time.sleep(1) 69 70 raise error.TestFail('Can not find video input device') 71 72 def wait_test_completed(self, timeout_secs): 73 """Waits until the test is done. 74 75 @param timeout_secs Max time to wait in seconds. 76 77 @raises TestError on timeout, or javascript eval fails. 78 """ 79 def _test_done(): 80 status = self.tab.EvaluateJavaScript('getStatus()') 81 logging.debug(status); 82 return status != 'running' 83 84 utils.poll_for_condition( 85 _test_done, timeout=timeout_secs, sleep_interval=1, 86 desc='loopback.html reports itself as finished') 87 88 @helper_logger.video_log_wrapper 89 def run_once(self, video_codec, capability): 90 """Runs the video_WebRtcPeerConnectionWithCamera test. 91 92 @param video_codec: video codec to use. 93 @param capability: Capability required for executing this test. 94 """ 95 device_capability.DeviceCapability().ensure_capability(capability) 96 with chrome.Chrome(extra_browser_args=EXTRA_BROWSER_ARGS +\ 97 [helper_logger.chrome_vmodule_flag()], 98 init_network_controller=True) as cr: 99 100 # TODO(keiichiw): vivid should be loaded in self.setup() after 101 # crbug.com/871185 is fixed 102 if utils.is_virtual_machine(): 103 try: 104 utils.run('sudo modprobe vivid n_devs=1 node_types=0x1') 105 except Exception as e: 106 raise error.TestFail('Failed to load vivid', e) 107 108 self.start_loopback(cr, video_codec) 109 self.wait_test_completed(TIMEOUT) 110 self.print_loopback_result(video_codec) 111 112 def print_loopback_result(self, video_codec): 113 """Prints loopback results (unless we failed to retrieve them). 114 115 @param video_codec: video codec to use. 116 @raises TestError if the test failed outright. 117 """ 118 status = self.tab.EvaluateJavaScript('getStatus()') 119 if status != 'ok-done': 120 raise error.TestFail('Failed: %s' % status) 121 122 results = self.tab.EvaluateJavaScript('getResults()') 123 logging.info('Camera Type: %s', results['cameraType']) 124 logging.info('PeerConnectionstats: %s', results['peerConnectionStats']) 125 logging.info('FrameStats: %s', results['frameStats']) 126 127 pc_stats = results.get('peerConnectionStats') 128 if not pc_stats: 129 raise error.TestFail('Peer Connection Stats is empty') 130 self.output_perf_value( 131 description='max_input_fps_%s' % video_codec, 132 value=pc_stats[1], units='fps', higher_is_better=True) 133 self.output_perf_value( 134 description='max_sent_fps_%s' % video_codec, 135 value=pc_stats[4], units='fps', higher_is_better=True) 136 137 frame_stats = results.get('frameStats') 138 if not frame_stats: 139 raise error.TestFail('Frame Stats is empty') 140 141 self.output_perf_value( 142 description='black_frames_%s' % video_codec, 143 value=frame_stats['numBlackFrames'], 144 units='frames', higher_is_better=False) 145 self.output_perf_value( 146 description='frozen_frames_%s' % video_codec, 147 value=frame_stats['numFrozenFrames'], 148 units='frames', higher_is_better=False) 149 self.output_perf_value( 150 description='total_num_frames_%s' % video_codec, 151 value=frame_stats['numFrames'], 152 units='frames', higher_is_better=True) 153