blob: ef6f3d51a4829c8cb076b10eac81a85870a3e81f [file] [log] [blame] [edit]
# 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
import time
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
from autotest_lib.client.cros.video import device_capability
from autotest_lib.client.cros.video import helper_logger
EXTRA_BROWSER_ARGS = ['--use-fake-ui-for-media-stream']
# Variables from the getusermedia.html page.
IS_TEST_DONE = 'isTestDone'
IS_VIDEO_INPUT_FOUND = 'isVideoInputFound'
# Polling timeout.
SEVERAL_MINUTES_IN_SECS = 240
class video_WebRtcCamera(test.test):
"""Local getUserMedia test with webcam at VGA (and 720p, if supported)."""
version = 1
def cleanup(self):
"""Autotest cleanup function
It is run by common_lib/test.py.
"""
if utils.is_virtual_machine():
try:
utils.run('sudo modprobe -r vivid')
except Exception as e:
raise error.TestFail('Failed to unload vivid', e)
def start_getusermedia(self, cr):
"""Opens the test 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, 'getusermedia.html')))
self.tab.WaitForDocumentReadyStateToBeComplete()
if utils.is_virtual_machine():
# Before calling 'getUserMedia()' again, make sure if Chrome has
# already recognized vivid as an external camera.
self.wait_camera_detected()
# Reload the page to run 'getUserMedia()' again
self.tab.EvaluateJavaScript('location.reload()')
self.tab.WaitForDocumentReadyStateToBeComplete()
def wait_camera_detected(self):
"""Waits until a camera is detected.
"""
for _ in range(10):
self.tab.EvaluateJavaScript('checkVideoInput()')
if self.tab.EvaluateJavaScript(IS_VIDEO_INPUT_FOUND):
return
time.sleep(1)
raise error.TestFail('Can not find video input device')
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 wait_test_completed(self, timeout_secs):
"""Waits until the test is done.
@param timeout_secs Max time to wait in seconds.
@raises TestError on timeout, or javascript eval fails.
"""
def _test_done():
return self.tab.EvaluateJavaScript(IS_TEST_DONE)
utils.poll_for_condition(
_test_done, timeout=timeout_secs, sleep_interval=1,
desc=('getusermedia.html:reportTestDone did not run. Test did not '
'complete successfully.'))
@helper_logger.video_log_wrapper
def run_once(self, capability):
"""Runs the test.
@param capability: Capability required for executing this test.
"""
device_capability.DeviceCapability().ensure_capability(capability)
self.board = utils.get_current_board()
with chrome.Chrome(extra_browser_args=EXTRA_BROWSER_ARGS +\
[helper_logger.chrome_vmodule_flag()],
init_network_controller=True) as cr:
# TODO(keiichiw): vivid should be loaded in self.setup() after
# crbug.com/871185 is fixed
if utils.is_virtual_machine():
try:
utils.run('sudo modprobe vivid n_devs=1 node_types=0x1')
except Exception as e:
raise error.TestFail('Failed to load vivid', e)
self.start_getusermedia(cr)
self.print_perf_results()
def print_perf_results(self):
"""Prints the perf results unless there was an error.
@returns the empty string if perf results were printed, otherwise
a description of the error that occured.
"""
self.wait_test_completed(SEVERAL_MINUTES_IN_SECS)
try:
results = self.tab.EvaluateJavaScript('getResults()')
except Exception as e:
raise error.TestFail('Failed to get getusermedia.html results', e)
logging.info('Results: %s', results)
errors = []
for width_height, data in results.iteritems():
resolution = re.sub(',', 'x', width_height)
if data['cameraErrors']:
if (resolution == '1280x720' and
not self.webcam_supports_720p()):
logging.info('Accepting 720p failure since device webcam '
'does not support 720p')
continue
# Else we had a VGA failure or a legit 720p failure.
errors.append('Camera error: %s for resolution '
'%s.' % (data['cameraErrors'], resolution))
continue
if not data['frameStats']:
errors.append('Frame Stats is empty '
'for resolution: %s' % resolution)
continue
total_num_frames = data['frameStats']['numFrames']
num_black_frames = data['frameStats']['numBlackFrames']
num_frozen_frames = data['frameStats']['numFrozenFrames']
def _percent(num, total):
if total == 0:
return 1.0
return float(num) / float(total)
self.output_perf_value(
description='black_frames_percentage_%s' % resolution,
value=_percent(num_black_frames, total_num_frames),
units='percent', higher_is_better=False)
self.output_perf_value(
description='frozen_frames_percentage_%s' % resolution,
value=_percent(num_frozen_frames, total_num_frames),
units='percent', higher_is_better=False)
if errors:
raise error.TestFail('Found errors: %s' % ', '.join(errors))