Home | History | Annotate | Download | only in video_WebRtcCamera
      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