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