1# Copyright (c) 2014 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
5import logging
6import os
7import tempfile
8
9from autotest_lib.client.bin import utils
10from autotest_lib.client.common_lib import error
11from autotest_lib.client.cros.audio import audio_helper
12from autotest_lib.client.cros.audio import cmd_utils
13from autotest_lib.client.cros.audio import cras_utils
14from autotest_lib.client.cros.audio import sox_utils
15
16
17NUMBER_OF_SEEKING = 6
18SEEKING_TIME = 50
19
20class audio_SeekAudioFeedback(audio_helper.chrome_rms_test):
21    """Verifies audio output on seeking forward/back."""
22
23    version = 1
24
25    def run_once(self, test_file, test_duration):
26        self._rms_values = {}
27        noise_file = os.path.join(self.resultsdir, 'noise.wav')
28        noiseprof_file = tempfile.NamedTemporaryFile()
29
30        # Record a sample of "silence" to use as a noise profile.
31        cras_utils.capture(noise_file, duration=2)
32        sox_utils.noise_profile(noise_file, noiseprof_file.name)
33
34        # Open the test page
35        self.chrome.browser.platform.SetHTTPServerDirectories(self.bindir)
36        tab = self.chrome.browser.tabs[0]
37        tab.Navigate(self.chrome.browser.platform.http_server.UrlOf(
38                os.path.join(self.bindir, 'play.html')))
39        tab.WaitForDocumentReadyStateToBeComplete()
40
41        # Test audio file.
42        self.rms_test(tab, test_file, noiseprof_file.name, test_duration)
43        self.write_perf_keyval(self._rms_values)
44
45
46    def rms_test(self, tab, test_file, noiseprof_file, test_duration):
47        logging.info('rms test on media file %s.', test_file)
48        recorded_file = os.path.join(self.resultsdir, 'recorded.wav')
49        loopback_file = os.path.join(self.resultsdir, 'loopback.wav')
50
51
52        # Plays the test_file in the browser and seek 6 times.
53        for x in range(0,NUMBER_OF_SEEKING):
54            self.play_media(tab, test_file, x)
55            # Record the audio output and also the CRAS loopback output.
56            p1 = cmd_utils.popen(cras_utils.capture_cmd(
57                    recorded_file, duration=test_duration ))
58            p2 = cmd_utils.popen(cras_utils.loopback_cmd(
59                    loopback_file, duration=test_duration ))
60            cmd_utils.wait_and_check_returncode(p1, p2)
61
62            # See if we recorded something.
63
64            # We captured two channels of audio in the CRAS loopback.
65            # The RMS values are for debugging only.
66            loopback_stats = [audio_helper.get_channel_sox_stat(
67                    loopback_file, i) for i in (1, 2)]
68            logging.info('loopback stat: %s', [str(s) for s in loopback_stats])
69
70            reduced_file = tempfile.NamedTemporaryFile()
71            sox_utils.noise_reduce(
72                    recorded_file, reduced_file.name, noiseprof_file)
73            rms = audio_helper.get_rms(reduced_file.name)[0]
74
75            self._rms_values['%s_rms_value' % test_file.replace('.', '_')]=rms
76
77
78    def wait_player_end(self, tab):
79        """Wait for player ends playing."""
80        utils.poll_for_condition(
81            condition=lambda: tab.EvaluateJavaScript('player.ended'),
82            exception=error.TestError('Player never end until timeout.'))
83
84
85    def play_media(self, tab, test_file, value):
86        """Plays a media file in Chromium.
87
88        @param test_file: Media file to test.
89        @param vlaue: Index of the loop
90        """
91        tab.EvaluateJavaScript('play("%s")' % test_file)
92        def get_current_time():
93            return tab.EvaluateJavaScript('player.currentTime')
94
95        if value <=(NUMBER_OF_SEEKING/2):
96            new_seek = (value * SEEKING_TIME)
97        else:
98            new_seek = (((NUMBER_OF_SEEKING - value) * SEEKING_TIME))
99        # Make sure the audio is being played
100        old_time = get_current_time()
101        utils.poll_for_condition(
102            condition=lambda: get_current_time() > old_time,
103            exception=error.TestError('Player never start until timeout.'))
104        tab.EvaluateJavaScript('player.currentTime = %d' % new_seek)
105