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