• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
7import logging
8import os
9import time
10
11from autotest_lib.client.common_lib import error
12from autotest_lib.client.cros.audio import audio_test_data
13from autotest_lib.client.cros.chameleon import audio_test_utils
14from autotest_lib.client.cros.chameleon import chameleon_audio_helper
15from autotest_lib.client.cros.chameleon import chameleon_audio_ids
16from autotest_lib.client.cros.multimedia import webrtc_utils
17from autotest_lib.server.cros.audio import audio_test
18from autotest_lib.server.cros.multimedia import remote_facade_factory
19
20
21class 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_audio_jack(host):
60            raise error.TestNAError(
61                    'No audio jack for the DUT.'
62                    'Please check label of the host and control file.'
63                    'Please check the host label and test dependency.')
64
65        golden_file = audio_test_data.GenerateAudioTestData(
66                data_format=dict(file_type='wav',
67                                 sample_format='S16_LE',
68                                 channel=2,
69                                 rate=48000),
70                path=os.path.join(self.bindir, 'fix_660_16.wav'),
71                duration_secs=60,
72                frequencies=[660, 660])
73
74        chameleon_board = host.chameleon
75
76        # Checks if a block size is specified for Chrome.
77        extra_browser_args = None
78        if chrome_block_size:
79            extra_browser_args = ['--audio-buffer-size=%d' % chrome_block_size]
80
81        factory = remote_facade_factory.RemoteFacadeFactory(
82                host, results_dir=self.resultsdir,
83                extra_browser_args=extra_browser_args)
84
85        chameleon_board.setup_and_reset(self.outputdir)
86
87        widget_factory = chameleon_audio_helper.AudioWidgetFactory(
88                factory, host)
89
90        headphone = widget_factory.create_widget(
91            chameleon_audio_ids.CrosIds.HEADPHONE)
92        linein = widget_factory.create_widget(
93            chameleon_audio_ids.ChameleonIds.LINEIN)
94        headphone_linein_binder = widget_factory.create_binder(headphone, linein)
95
96        usb_out = widget_factory.create_widget(chameleon_audio_ids.ChameleonIds.USBOUT)
97        usb_in = widget_factory.create_widget(chameleon_audio_ids.CrosIds.USBIN)
98        usb_binder = widget_factory.create_binder(usb_out, usb_in)
99
100        with chameleon_audio_helper.bind_widgets(headphone_linein_binder):
101            with chameleon_audio_helper.bind_widgets(usb_binder):
102                time.sleep(self.DELAY_AFTER_BINDING_SECONDS)
103                audio_facade = factory.create_audio_facade()
104
105                audio_test_utils.dump_cros_audio_logs(
106                        host, audio_facade, self.resultsdir, 'after_binding')
107
108                # Checks whether line-out or headphone is detected.
109                hp_jack_node_type = audio_test_utils.check_hp_or_lineout_plugged(
110                        audio_facade)
111
112                # Checks headphone and USB nodes are plugged.
113                # Let Chrome select the proper I/O nodes.
114                # Input is USB, output is headphone.
115                audio_test_utils.check_and_set_chrome_active_node_types(
116                        audio_facade=audio_facade,
117                        output_type=hp_jack_node_type,
118                        input_type='USB')
119
120                logging.info('Setting playback data on Chameleon')
121                usb_out.set_playback_data(golden_file)
122
123                browser_facade = factory.create_browser_facade()
124                apprtc = webrtc_utils.AppRTCController(browser_facade)
125                logging.info('Load AppRTC loopback webpage')
126                apprtc.new_apprtc_loopback_page()
127
128                logging.info('Start recording from Chameleon.')
129                linein.start_recording()
130
131                logging.info('Start playing %s on Cros device',
132                        golden_file.path)
133                usb_out.start_playback()
134
135                time.sleep(self.RECORD_SECONDS)
136
137                linein.stop_recording()
138                logging.info('Stopped recording from Chameleon.')
139
140                audio_test_utils.dump_cros_audio_logs(
141                        host, audio_facade, self.resultsdir, 'after_recording')
142
143                usb_out.stop_playback()
144
145                linein.read_recorded_binary()
146                logging.info('Read recorded binary from Chameleon.')
147
148        golden_file.delete()
149
150        recorded_file = os.path.join(self.resultsdir, "recorded.raw")
151        logging.info('Saving recorded data to %s', recorded_file)
152        linein.save_file(recorded_file)
153
154        diagnostic_path = os.path.join(
155                self.resultsdir,
156                'audio_diagnostics.txt.after_recording')
157        logging.info('Examine diagnostic file at %s', diagnostic_path)
158        diag_warning_msg = audio_test_utils.examine_audio_diagnostics(
159                diagnostic_path)
160        if diag_warning_msg:
161            logging.warning(diag_warning_msg)
162
163        # Raise error.TestFail if there is issue.
164        audio_test_utils.check_recorded_frequency(
165                golden_file, linein, check_artifacts=check_quality)
166