Home | History | Annotate | Download | only in audio_WebRtcAudioLoopback
      1 # Copyright 2017 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 
      8 from autotest_lib.client.bin import test
      9 from autotest_lib.client.bin import utils
     10 from autotest_lib.client.common_lib import error
     11 from autotest_lib.client.common_lib.cros import chrome
     12 from autotest_lib.client.cros.video import helper_logger
     13 from autotest_lib.client.cros.audio import audio_helper
     14 from autotest_lib.client.cros.audio import cras_utils
     15 
     16 # Suppress the media Permission Dialog.
     17 EXTRA_BROWSER_ARGS = [
     18     '--use-fake-ui-for-media-stream',  # Suppress the Permission Dialog
     19     '--use-fake-device-for-media-stream'  # Use fake audio & video
     20 ]
     21 
     22 AUDIO_LOOPBACK_PAGE = 'audio_loopback.html'
     23 
     24 # The test's runtime.
     25 TEST_RUNTIME_SECONDS = 10
     26 
     27 # Number of peer connections to use.
     28 NUM_PEER_CONNECTIONS = 1
     29 
     30 # Polling timeout.
     31 TIMEOUT = TEST_RUNTIME_SECONDS + 10
     32 
     33 
     34 class audio_WebRtcAudioLoopback(test.test):
     35     """Tests a WebRTC call with a fake audio."""
     36     version = 1
     37 
     38     def start_test(self, cr, recorded_file):
     39         """Opens the WebRTC audio loopback page and records audio output.
     40 
     41         @param cr: Autotest Chrome instance.
     42         @param recorded_file: File to recorder the audio output to.
     43         """
     44         cr.browser.platform.SetHTTPServerDirectories(self.bindir)
     45 
     46         self.tab = cr.browser.tabs[0]
     47         self.tab.Navigate(cr.browser.platform.http_server.UrlOf(
     48             os.path.join(self.bindir, AUDIO_LOOPBACK_PAGE)))
     49         self.tab.WaitForDocumentReadyStateToBeComplete()
     50         self.tab.EvaluateJavaScript(
     51             "run(%d, %d)" % (TEST_RUNTIME_SECONDS, NUM_PEER_CONNECTIONS))
     52         self.wait_for_active_stream_count(1)
     53         cras_utils.capture(recorded_file, duration=TEST_RUNTIME_SECONDS)
     54 
     55     def wait_test_completed(self, timeout_secs):
     56         """Waits until the test is done.
     57 
     58         @param timeout_secs Max time to wait in seconds.
     59 
     60         @raises TestError on timeout, or javascript eval fails.
     61         """
     62         def _test_done():
     63             status = self.tab.EvaluateJavaScript('testRunner.getStatus()')
     64             logging.info(status)
     65             return status == 'ok-done'
     66 
     67         utils.poll_for_condition(
     68                 _test_done, timeout=timeout_secs, sleep_interval=1,
     69                 desc='audio.html reports itself as finished')
     70 
     71     @staticmethod
     72     def wait_for_active_stream_count(expected_count):
     73         """Waits for the expected number of active streams.
     74 
     75         @param expected_count: expected count of active streams.
     76         """
     77         utils.poll_for_condition(
     78             lambda: cras_utils.get_active_stream_count() == expected_count,
     79             exception=error.TestError(
     80                 'Timeout waiting active stream count to become %d' %
     81                  expected_count))
     82 
     83     @helper_logger.video_log_wrapper
     84     def run_once(self):
     85         """Runs the audio_WebRtcAudioLoopback test."""
     86         # Record a sample of "silence" to use as a noise profile.
     87         noise_file = os.path.join(self.resultsdir, 'cras_noise.wav')
     88         cras_utils.capture(noise_file, duration=1)
     89 
     90         # Create a file for the audio recording.
     91         recorded_file = os.path.join(self.resultsdir, 'cras_recorded.wav')
     92 
     93         self.wait_for_active_stream_count(0)
     94         with chrome.Chrome(extra_browser_args=EXTRA_BROWSER_ARGS +\
     95                             [helper_logger.chrome_vmodule_flag()],
     96                            init_network_controller=True) as cr:
     97             self.start_test(cr, recorded_file)
     98             self.wait_test_completed(TIMEOUT)
     99             self.print_result(recorded_file, noise_file)
    100 
    101     def print_result(self, recorded_file, noise_file):
    102         """Prints results unless status is different from ok-done.
    103 
    104         @raises TestError if the test failed outright.
    105         @param recorded_file: File to recorder the audio output to.
    106         @param noise_file: Noise recording, used for comparison.
    107         """
    108         status = self.tab.EvaluateJavaScript('testRunner.getStatus()')
    109         if status != 'ok-done':
    110             raise error.TestFail('Failed: %s' % status)
    111 
    112         results = self.tab.EvaluateJavaScript('testRunner.getResults()')
    113         logging.info('runTimeSeconds: %.2f', results['runTimeSeconds'])
    114 
    115         rms_value = audio_helper.reduce_noise_and_get_rms(
    116                 recorded_file, noise_file)[0]
    117         logging.info('rms_value: %f', rms_value)
    118         self.output_perf_value(
    119                 description='rms_value',
    120                 value=rms_value,
    121                 units='', higher_is_better=True)
    122 
    123