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 # Statistics from the loopback.html page.
     17 TEST_PROGRESS = 'testProgress'
     18 
     19 # Polling timeout
     20 TIMEOUT = 240
     21 
     22 # max number of allowed blackframes or frozen frames
     23 BLACK_FRAMES_THRESHOLD = 10
     24 FROZEN_FRAMES_THRESHOLD = 10
     25 
     26 class video_WebRtcCamera(test.test):
     27     """Local Peer connection test with webcam at 720p."""
     28     version = 1
     29 
     30     def start_loopback(self, cr):
     31         """Opens WebRTC loopback page.
     32 
     33         @param cr: Autotest Chrome instance.
     34         """
     35         cr.browser.platform.SetHTTPServerDirectories(self.bindir)
     36 
     37         self.tab = cr.browser.tabs[0]
     38         self.tab.Navigate(cr.browser.platform.http_server.UrlOf(
     39                 os.path.join(self.bindir, 'loopback.html')))
     40         self.tab.WaitForDocumentReadyStateToBeComplete()
     41 
     42 
     43     def webcam_supports_720p(self):
     44         """Checks if 720p capture supported.
     45 
     46         @returns: True if 720p supported, false if VGA is supported.
     47         @raises: TestError if neither 720p nor VGA are supported.
     48         """
     49         cmd = 'lsusb -v'
     50         # Get usb devices and make output a string with no newline marker.
     51         usb_devices = utils.system_output(cmd, ignore_status=True).splitlines()
     52         usb_devices = ''.join(usb_devices)
     53 
     54         # Check if 720p resolution supported.
     55         if re.search(r'\s+wWidth\s+1280\s+wHeight\s+720', usb_devices):
     56             return True
     57         # The device should support at least VGA.
     58         # Otherwise the cam must be broken.
     59         if re.search(r'\s+wWidth\s+640\s+wHeight\s+480', usb_devices):
     60             return False
     61         # This should not happen.
     62         raise error.TestFail(
     63                 'Could not find any cameras reporting '
     64                 'either VGA or 720p in lsusb output: %s' % usb_devices)
     65 
     66 
     67     def is_test_completed(self):
     68         """Checks if WebRTC peerconnection test is done.
     69 
     70         @returns True if test complete, False otherwise.
     71 
     72         """
     73         def test_done():
     74           """Check the testProgress variable in HTML page."""
     75 
     76           # Wait for test completion on web page.
     77           test_progress = self.tab.EvaluateJavaScript(TEST_PROGRESS)
     78           return test_progress == 1
     79 
     80         try:
     81             utils.poll_for_condition(
     82                     test_done, timeout=TIMEOUT,
     83                     exception=error.TestError(
     84                         'Cannot find testProgress value.'),
     85                     sleep_interval=1)
     86         except error.TestError:
     87             partial_results = self.tab.EvaluateJavaScript('getResults()')
     88             logging.info('Here are the partial results so far: %s',
     89                          partial_results)
     90             return False
     91         else:
     92             return True
     93 
     94 
     95     def run_once(self):
     96         """Runs the video_WebRtcPeerConnectionWithCamera test."""
     97         self.board = utils.get_current_board()
     98         with chrome.Chrome(extra_browser_args=EXTRA_BROWSER_ARGS) as cr:
     99             # Open WebRTC loopback page and start the loopback.
    100             self.start_loopback(cr)
    101             if not self.check_loopback_result():
    102                 raise error.TestFail('Failed webrtc camera test')
    103 
    104 
    105     def check_loopback_result(self):
    106         """Get the WebRTC Camera results."""
    107         if not self.is_test_completed():
    108             logging.error('loopback.html did not complete')
    109             return False
    110         try:
    111             results = self.tab.EvaluateJavaScript('getResults()')
    112         except:
    113             logging.error('Cannot retrieve results from loopback.html page')
    114             return False
    115         logging.info('Results: %s', results)
    116         for resolution in results:
    117             item = results[resolution]
    118             if (item['cameraErrors'] and resolution == '1280,720'
    119                     and self.webcam_supports_720p()):
    120                 logging.error('Camera error: %s', item['cameraErrors'])
    121                 return False
    122             if not item['frameStats']:
    123                 output_resolution = re.sub(',', 'x', resolution)
    124                 logging.error('Frame Stats is empty for resolution: %s',
    125                               output_resolution)
    126                 return False
    127 
    128             if item['frameStats']['numBlackFrames'] > BLACK_FRAMES_THRESHOLD:
    129                 logging.error('BlackFrames threshold overreach: '
    130                               'got %s > %s allowed',
    131                               item['frameStats']['numBlackFrames'],
    132                               BLACK_FRAMES_THRESHOLD)
    133                 return False
    134             if item['frameStats']['numFrozenFrames'] > FROZEN_FRAMES_THRESHOLD:
    135                 logging.error('FrozenFrames threshold overreach: '
    136                               'got %s > %s allowed',
    137                               item['frameStats']['numFrozenFrames'],
    138                               FROZEN_FRAMES_THRESHOLD)
    139                 return False
    140             if item['frameStats']['numFrames'] == 0:
    141                 logging.error('%s Frames were found',
    142                               item['frameStats']['numFrames'])
    143                 return False
    144 
    145         return True
    146