Home | History | Annotate | Download | only in audio_AudioWebRTCLoopback
      1 # Copyright 2016 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 """This is a server side WebRTC audio test using the Chameleon board."""
      6 
      7 import logging
      8 import os
      9 import time
     10 
     11 from autotest_lib.client.cros.audio import audio_test_data
     12 from autotest_lib.client.cros.chameleon import audio_test_utils
     13 from autotest_lib.client.cros.chameleon import chameleon_audio_helper
     14 from autotest_lib.client.cros.chameleon import chameleon_audio_ids
     15 from autotest_lib.client.cros.multimedia import webrtc_utils
     16 from autotest_lib.server.cros.audio import audio_test
     17 from autotest_lib.server.cros.multimedia import remote_facade_factory
     18 
     19 
     20 class audio_AudioWebRTCLoopback(audio_test.AudioTest):
     21     """Server side WebRTC loopback audio test.
     22 
     23     This test talks to a Chameleon board and a Cros device to verify
     24     WebRTC audio function of the Cros device.
     25     A sine tone is played to Cros device from Chameleon USB.
     26     Through AppRTC loopback page, the sine tone is played to Chameleon
     27     LineIn from Cros device headphone.
     28     Using USB as audio source because it can provide completely correct
     29     data to loopback. This enables the test to do quality verification on
     30     headphone.
     31 
     32                   ----------->->->------------
     33          USB out |                            | USB in
     34            -----------                    --------              AppRTC loopback
     35           | Chameleon |                  |  Cros  |  <--------> webpage
     36            -----------                    --------
     37          Line-In |                            |  Headphone
     38                   -----------<-<-<------------
     39 
     40 
     41     The recorded audio is copied to server side and examined for quality.
     42 
     43     """
     44     version = 1
     45     RECORD_SECONDS = 10
     46     DELAY_AFTER_BINDING_SECONDS = 0.5
     47 
     48     def run_once(self, host, check_quality=False, chrome_block_size=None):
     49         """Running basic headphone audio tests.
     50 
     51         @param host: device under test host
     52         @param check_quality: flag to check audio quality.
     53         @param chrome_block_size: A number to be passed to Chrome
     54                                   --audio-buffer-size argument to specify
     55                                   block size.
     56 
     57         """
     58         if not audio_test_utils.has_headphone(host):
     59             logging.info('Skip the test because there is no headphone')
     60             return
     61 
     62         golden_file = audio_test_data.GenerateAudioTestData(
     63                 data_format=dict(file_type='wav',
     64                                  sample_format='S16_LE',
     65                                  channel=2,
     66                                  rate=48000),
     67                 path=os.path.join(self.bindir, 'fix_660_16.wav'),
     68                 duration_secs=60,
     69                 frequencies=[660, 660])
     70 
     71         chameleon_board = host.chameleon
     72 
     73         # Checks if a block size is specified for Chrome.
     74         extra_browser_args = None
     75         if chrome_block_size:
     76             extra_browser_args = ['--audio-buffer-size=%d' % chrome_block_size]
     77 
     78         factory = remote_facade_factory.RemoteFacadeFactory(
     79                 host, results_dir=self.resultsdir,
     80                 extra_browser_args=extra_browser_args)
     81 
     82         chameleon_board.setup_and_reset(self.outputdir)
     83 
     84         widget_factory = chameleon_audio_helper.AudioWidgetFactory(
     85                 factory, host)
     86 
     87         headphone = widget_factory.create_widget(
     88             chameleon_audio_ids.CrosIds.HEADPHONE)
     89         linein = widget_factory.create_widget(
     90             chameleon_audio_ids.ChameleonIds.LINEIN)
     91         headphone_linein_binder = widget_factory.create_binder(headphone, linein)
     92 
     93         usb_out = widget_factory.create_widget(chameleon_audio_ids.ChameleonIds.USBOUT)
     94         usb_in = widget_factory.create_widget(chameleon_audio_ids.CrosIds.USBIN)
     95         usb_binder = widget_factory.create_binder(usb_out, usb_in)
     96 
     97         with chameleon_audio_helper.bind_widgets(headphone_linein_binder):
     98             with chameleon_audio_helper.bind_widgets(usb_binder):
     99                 time.sleep(self.DELAY_AFTER_BINDING_SECONDS)
    100                 audio_facade = factory.create_audio_facade()
    101 
    102                 audio_test_utils.dump_cros_audio_logs(
    103                         host, audio_facade, self.resultsdir, 'after_binding')
    104 
    105                 # Checks whether line-out or headphone is detected.
    106                 hp_jack_node_type = audio_test_utils.check_hp_or_lineout_plugged(
    107                         audio_facade)
    108 
    109                 # Checks headphone and USB nodes are plugged.
    110                 # Let Chrome select the proper I/O nodes.
    111                 # Input is USB, output is headphone.
    112                 audio_test_utils.check_and_set_chrome_active_node_types(
    113                         audio_facade=audio_facade,
    114                         output_type=hp_jack_node_type,
    115                         input_type='USB')
    116 
    117                 logging.info('Setting playback data on Chameleon')
    118                 usb_out.set_playback_data(golden_file)
    119 
    120                 browser_facade = factory.create_browser_facade()
    121                 apprtc = webrtc_utils.AppRTCController(browser_facade)
    122                 logging.info('Load AppRTC loopback webpage')
    123                 apprtc.new_apprtc_loopback_page()
    124 
    125                 logging.info('Start recording from Chameleon.')
    126                 linein.start_recording()
    127 
    128                 logging.info('Start playing %s on Cros device',
    129                         golden_file.path)
    130                 usb_out.start_playback()
    131 
    132                 time.sleep(self.RECORD_SECONDS)
    133 
    134                 linein.stop_recording()
    135                 logging.info('Stopped recording from Chameleon.')
    136 
    137                 audio_test_utils.dump_cros_audio_logs(
    138                         host, audio_facade, self.resultsdir, 'after_recording')
    139 
    140                 usb_out.stop_playback()
    141 
    142                 linein.read_recorded_binary()
    143                 logging.info('Read recorded binary from Chameleon.')
    144 
    145         golden_file.delete()
    146 
    147         recorded_file = os.path.join(self.resultsdir, "recorded.raw")
    148         logging.info('Saving recorded data to %s', recorded_file)
    149         linein.save_file(recorded_file)
    150 
    151         diagnostic_path = os.path.join(
    152                 self.resultsdir,
    153                 'audio_diagnostics.txt.after_recording')
    154         logging.info('Examine diagnostic file at %s', diagnostic_path)
    155         diag_warning_msg = audio_test_utils.examine_audio_diagnostics(
    156                 diagnostic_path)
    157         if diag_warning_msg:
    158             logging.warning(diag_warning_msg)
    159 
    160         # Raise error.TestFail if there is issue.
    161         audio_test_utils.check_recorded_frequency(
    162                 golden_file, linein, check_artifacts=check_quality)
    163