1# Copyright (c) 2012 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 17class desktopui_MediaAudioFeedback(audio_helper.chrome_rms_test): 18 """Verifies if media playback can be captured.""" 19 20 version = 1 21 22 def run_once(self, test_files, test_duration): 23 self._rms_values = {} 24 noise_file = os.path.join(self.resultsdir, 'noise.wav') 25 noiseprof_file = tempfile.NamedTemporaryFile() 26 27 # Record a sample of "silence" to use as a noise profile. 28 cras_utils.capture(noise_file, duration=2) 29 sox_utils.noise_profile(noise_file, noiseprof_file.name) 30 31 # Open the test page 32 self.chrome.browser.platform.SetHTTPServerDirectories(self.bindir) 33 tab = self.chrome.browser.tabs[0] 34 tab.Navigate(self.chrome.browser.platform.http_server.UrlOf( 35 os.path.join(self.bindir, 'play.html'))) 36 tab.WaitForDocumentReadyStateToBeComplete() 37 38 # Test each media file for all channels. 39 for media_file in test_files: 40 self.rms_test(tab, media_file, noiseprof_file.name, test_duration) 41 self.write_perf_keyval(self._rms_values) 42 43 44 def rms_test(self, tab, media_file, noiseprof_file, test_duration): 45 logging.info('rms test on media file %s.', media_file) 46 recorded_file = os.path.join(self.resultsdir, 'recorded.wav') 47 loopback_file = os.path.join(self.resultsdir, 'loopback.wav') 48 49 # Plays the media_file in the browser. 50 self.play_media(tab, media_file) 51 52 # Record the audio output and also the CRAS loopback output. 53 p1 = cmd_utils.popen(cras_utils.capture_cmd( 54 recorded_file, duration=test_duration)) 55 p2 = cmd_utils.popen(cras_utils.loopback_cmd( 56 loopback_file, duration=test_duration)) 57 cmd_utils.wait_and_check_returncode(p1, p2) 58 59 # See if we recorded something. 60 61 # We captured two channels of audio in the CRAS loopback. 62 # The RMS values are for debugging only. 63 loopback_stats = [audio_helper.get_channel_sox_stat( 64 loopback_file, i) for i in (1, 2)] 65 logging.info('loopback stats: %s', [str(s) for s in loopback_stats]) 66 67 reduced_file = tempfile.NamedTemporaryFile() 68 sox_utils.noise_reduce( 69 recorded_file, reduced_file.name, noiseprof_file) 70 rms = audio_helper.get_rms(reduced_file.name)[0] 71 72 self._rms_values['%s_rms_value' % media_file.replace('.', '_')] = rms 73 74 # Make sure the audio can be played to the end. 75 self.wait_player_end(tab) 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, media_file): 86 """Plays a media file in Chromium. 87 88 @param media_file: Media file to test. 89 """ 90 tab.EvaluateJavaScript('play("%s")' % media_file) 91 92 def get_current_time(): 93 return tab.EvaluateJavaScript('player.currentTime') 94 95 # Make sure the audio is being played 96 old_time = get_current_time() 97 utils.poll_for_condition( 98 condition=lambda: get_current_time() > old_time, 99 exception=error.TestError('Player never start until timeout.')) 100