• 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_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 whether line-out or headphone is detected.
101                hp_jack_node_type = audio_test_utils.check_hp_or_lineout_plugged(
102                        audio_facade)
103
104                # Checks headphone and USB nodes are plugged.
105                # Let Chrome select the proper I/O nodes.
106                # Input is USB, output is headphone.
107                audio_test_utils.check_and_set_chrome_active_node_types(
108                        audio_facade=audio_facade,
109                        output_type=hp_jack_node_type,
110                        input_type='USB')
111
112                logging.info('Setting playback data on Chameleon')
113                usb_out.set_playback_data(golden_file)
114
115                browser_facade = factory.create_browser_facade()
116                apprtc = webrtc_utils.AppRTCController(browser_facade)
117                logging.info('Load AppRTC loopback webpage')
118                apprtc.new_apprtc_loopback_page()
119
120                logging.info('Start recording from Chameleon.')
121                linein.start_recording()
122
123                logging.info('Start playing %s on Cros device',
124                        golden_file.path)
125                usb_out.start_playback()
126
127                time.sleep(self.RECORD_SECONDS)
128
129                linein.stop_recording()
130                logging.info('Stopped recording from Chameleon.')
131
132                audio_test_utils.dump_cros_audio_logs(
133                        host, audio_facade, self.resultsdir, 'after_recording')
134
135                usb_out.stop_playback()
136
137                linein.read_recorded_binary()
138                logging.info('Read recorded binary from Chameleon.')
139
140        golden_file.delete()
141
142        recorded_file = os.path.join(self.resultsdir, "recorded.raw")
143        logging.info('Saving recorded data to %s', recorded_file)
144        linein.save_file(recorded_file)
145
146        diagnostic_path = os.path.join(
147                self.resultsdir,
148                'audio_diagnostics.txt.after_recording')
149        logging.info('Examine diagnostic file at %s', diagnostic_path)
150        diag_warning_msg = audio_test_utils.examine_audio_diagnostics(
151                diagnostic_path)
152        if diag_warning_msg:
153            logging.warning(diag_warning_msg)
154
155        # Raise error.TestFail if there is issue.
156        audio_test_utils.check_recorded_frequency(
157                golden_file, linein, check_artifacts=check_quality)
158