Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(322)

Side by Side Diff: chrome/browser/media/webrtc/webrtc_audio_quality_browsertest.cc

Issue 2773803002: Revert of WebRTC: Use the MediaStream Recording API for the audio_quality_browsertest. (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | chrome/test/data/webrtc/audio_extraction.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <stddef.h> 5 #include <stddef.h>
6 6
7 #include <ctime> 7 #include <ctime>
8 8
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/files/file_enumerator.h" 10 #include "base/files/file_enumerator.h"
11 #include "base/files/file_util.h" 11 #include "base/files/file_util.h"
12 #include "base/files/scoped_temp_dir.h" 12 #include "base/files/scoped_temp_dir.h"
13 #include "base/macros.h" 13 #include "base/macros.h"
14 #include "base/process/launch.h" 14 #include "base/process/launch.h"
15 #include "base/process/process.h" 15 #include "base/process/process.h"
16 #include "base/scoped_native_library.h" 16 #include "base/scoped_native_library.h"
17 #include "base/strings/string_number_conversions.h" 17 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/string_util.h" 18 #include "base/strings/string_util.h"
19 #include "base/strings/stringprintf.h" 19 #include "base/strings/stringprintf.h"
20 #include "base/strings/utf_string_conversions.h" 20 #include "base/strings/utf_string_conversions.h"
21 #include "base/test/test_file_util.h"
22 #include "build/build_config.h" 21 #include "build/build_config.h"
23 #include "chrome/browser/media/webrtc/webrtc_browsertest_audio.h" 22 #include "chrome/browser/media/webrtc/webrtc_browsertest_audio.h"
24 #include "chrome/browser/media/webrtc/webrtc_browsertest_base.h" 23 #include "chrome/browser/media/webrtc/webrtc_browsertest_base.h"
25 #include "chrome/browser/media/webrtc/webrtc_browsertest_common.h" 24 #include "chrome/browser/media/webrtc/webrtc_browsertest_common.h"
26 #include "chrome/browser/profiles/profile.h" 25 #include "chrome/browser/profiles/profile.h"
27 #include "chrome/browser/ui/browser.h" 26 #include "chrome/browser/ui/browser.h"
28 #include "chrome/browser/ui/browser_tabstrip.h" 27 #include "chrome/browser/ui/browser_tabstrip.h"
29 #include "chrome/browser/ui/tabs/tab_strip_model.h" 28 #include "chrome/browser/ui/tabs/tab_strip_model.h"
30 #include "chrome/common/chrome_paths.h" 29 #include "chrome/common/chrome_paths.h"
31 #include "chrome/common/chrome_switches.h" 30 #include "chrome/common/chrome_switches.h"
32 #include "chrome/common/pref_names.h"
33 #include "chrome/test/base/ui_test_utils.h" 31 #include "chrome/test/base/ui_test_utils.h"
34 #include "components/prefs/pref_service.h"
35 #include "content/public/common/content_switches.h" 32 #include "content/public/common/content_switches.h"
36 #include "content/public/test/browser_test_utils.h" 33 #include "content/public/test/browser_test_utils.h"
37 #include "media/base/audio_parameters.h" 34 #include "media/base/audio_parameters.h"
38 #include "media/base/media_switches.h" 35 #include "media/base/media_switches.h"
39 #include "net/test/embedded_test_server/embedded_test_server.h" 36 #include "net/test/embedded_test_server/embedded_test_server.h"
40 #include "testing/perf/perf_test.h" 37 #include "testing/perf/perf_test.h"
41 38
42 namespace { 39 namespace {
43 40
44 static const base::FilePath::CharType kReferenceFile[] = 41 static const base::FilePath::CharType kReferenceFile[] =
45 FILE_PATH_LITERAL("speech_44kHz_16bit_stereo.wav"); 42 FILE_PATH_LITERAL("speech_44kHz_16bit_stereo.wav");
46 43
47 // The javascript will load the reference file relative to its location, 44 // The javascript will load the reference file relative to its location,
48 // which is in /webrtc on the web server. The files we are looking for are in 45 // which is in /webrtc on the web server. The files we are looking for are in
49 // webrtc/resources in the chrome/test/data folder. 46 // webrtc/resources in the chrome/test/data folder.
50 static const char kReferenceFileRelativeUrl[] = 47 static const char kReferenceFileRelativeUrl[] =
51 "resources/speech_44kHz_16bit_stereo.wav"; 48 "resources/speech_44kHz_16bit_stereo.wav";
52 49
53 static const char kWebRtcAudioTestHtmlPage[] = 50 static const char kWebRtcAudioTestHtmlPage[] =
54 "/webrtc/webrtc_audio_quality_test.html"; 51 "/webrtc/webrtc_audio_quality_test.html";
55 52
56 // How long to record the audio in the receiving peerConnection.
57 static const int kCaptureDurationInSeconds = 25;
58
59 // The name where the recorded WebM audio file will be saved.
60 static const char kWebmRecordingFilename[] = "recording.webm";
61
62 // How often to ask the test page whether the audio recording is completed.
63 const int kPollingIntervalInMs = 1000;
64
65 // For the AGC test, there are 6 speech segments split on silence. If one 53 // For the AGC test, there are 6 speech segments split on silence. If one
66 // segment is significantly different in length compared to the same segment in 54 // segment is significantly different in length compared to the same segment in
67 // the reference file, there's something fishy going on. 55 // the reference file, there's something fishy going on.
68 const int kMaxAgcSegmentDiffMs = 56 const int kMaxAgcSegmentDiffMs =
69 #if defined(OS_MACOSX) 57 #if defined(OS_MACOSX)
70 // Something is different on Mac; http://crbug.com/477653. 58 // Something is different on Mac; http://crbug.com/477653.
71 600; 59 600;
72 #else 60 #else
73 200; 61 200;
74 #endif 62 #endif
75 63
76 #if defined(OS_LINUX) || defined(OS_WIN) || defined(OS_MACOSX) 64 #if defined(OS_LINUX) || defined(OS_WIN) || defined(OS_MACOSX)
77 #define MAYBE_WebRtcAudioQualityBrowserTest WebRtcAudioQualityBrowserTest 65 #define MAYBE_WebRtcAudioQualityBrowserTest WebRtcAudioQualityBrowserTest
78 #else 66 #else
79 // Not implemented on Android, ChromeOS etc. 67 // Not implemented on Android, ChromeOS etc.
80 #define MAYBE_WebRtcAudioQualityBrowserTest DISABLED_WebRtcAudioQualityBrowserTe st 68 #define MAYBE_WebRtcAudioQualityBrowserTest DISABLED_WebRtcAudioQualityBrowserTe st
81 #endif 69 #endif
82 70
83 } // namespace 71 } // namespace
84 72
85 // Test we can set up a WebRTC call and play audio through it. 73 // Test we can set up a WebRTC call and play audio through it.
86 // 74 //
87 // If you're not a googler and want to run this test, you need to provide a 75 // If you're not a googler and want to run this test, you need to provide a
88 // pesq binary for your platform (and sox.exe on windows). Read more on how 76 // pesq binary for your platform (and sox.exe on windows). Read more on how
89 // resources are managed in chrome/test/data/webrtc/resources/README. 77 // resources are managed in chrome/test/data/webrtc/resources/README.
90 // 78 //
79 // This test will only work on machines that have been configured to record
80 // their own input.
81 //
91 // On Linux: 82 // On Linux:
92 // 1. # sudo apt-get install sox 83 // 1. # sudo apt-get install pavucontrol sox
84 // 2. For the user who will run the test: # pavucontrol
85 // 3. In a separate terminal, # arecord dummy
86 // 4. In pavucontrol, go to the recording tab.
87 // 5. For the ALSA plugin [aplay]: ALSA Capture from, change from <x> to
88 // <Monitor of x>, where x is whatever your primary sound device is called.
89 // 6. Try launching chrome as the target user on the target machine, try
90 // playing, say, a YouTube video, and record with # arecord -f dat tmp.dat.
91 // Verify the recording with aplay (should have recorded what you played
92 // from chrome).
93 //
94 // Note: the volume for ALL your input devices will be forced to 100% by
95 // running this test on Linux.
93 // 96 //
94 // On Mac: 97 // On Mac:
95 // TODO(phoglund): download sox from gs instead. 98 // TODO(phoglund): download sox from gs instead.
96 // 1. Get SoundFlower: http://rogueamoeba.com/freebies/soundflower/download.php 99 // 1. Get SoundFlower: http://rogueamoeba.com/freebies/soundflower/download.php
97 // 2. Install it + reboot. 100 // 2. Install it + reboot.
98 // 3. Install MacPorts (http://www.macports.org/). 101 // 3. Install MacPorts (http://www.macports.org/).
99 // 4. Install sox: sudo port install sox. 102 // 4. Install sox: sudo port install sox.
100 // 5. (For Chrome bots) Ensure sox is reachable from the env the test 103 // 5. (For Chrome bots) Ensure sox and rec are reachable from the env the test
101 // executes in (sox tends to install in /opt/, which generally isn't in the 104 // executes in (sox and rec tends to install in /opt/, which generally isn't
102 // Chrome bots' env). For instance, run 105 // in the Chrome bots' env). For instance, run
106 // sudo ln -s /opt/local/bin/rec /usr/local/bin/rec
103 // sudo ln -s /opt/local/bin/sox /usr/local/bin/sox 107 // sudo ln -s /opt/local/bin/sox /usr/local/bin/sox
108 // 6. In Sound Preferences, set both input and output to Soundflower (2ch).
109 // Note: You will no longer hear audio on this machine, and it will no
110 // longer use any built-in mics.
111 // 7. Try launching chrome as the target user on the target machine, try
112 // playing, say, a YouTube video, and record with 'rec test.wav trim 0 5'.
113 // Stop the video in chrome and try playing back the file; you should hear
114 // a recording of the video (note; if you play back on the target machine
115 // you must revert the changes in step 3 first).
116 //
117 // On Windows 7:
118 // 1. Control panel > Sound > Manage audio devices.
119 // 2. In the recording tab, right-click in an empty space in the pane with the
120 // devices. Tick 'show disabled devices'.
121 // 3. You should see a 'stereo mix' device - this is what your speakers output.
122 // If you don't have one, your driver doesn't support stereo mix devices.
123 // Some drivers use different names for the mix device though (like "Wave").
124 // Right click > Properties.
125 // 4. Ensure "listen to this device" is unchecked, otherwise you get echo.
126 // 5. Ensure the mix device is the default recording device.
127 // 6. Launch chrome and try playing a video with sound. You should see
128 // in the volume meter for the mix device. Configure the mix device to have
129 // 50 / 100 in level. Also go into the playback tab, right-click Speakers,
130 // and set that level to 50 / 100. Otherwise you will get distortion in
131 // the recording.
104 class MAYBE_WebRtcAudioQualityBrowserTest : public WebRtcTestBase { 132 class MAYBE_WebRtcAudioQualityBrowserTest : public WebRtcTestBase {
105 public: 133 public:
106 MAYBE_WebRtcAudioQualityBrowserTest() {} 134 MAYBE_WebRtcAudioQualityBrowserTest() {}
107 void SetUpInProcessBrowserTestFixture() override { 135 void SetUpInProcessBrowserTestFixture() override {
108 DetectErrorsInJavaScript(); // Look for errors in our rather complex js. 136 DetectErrorsInJavaScript(); // Look for errors in our rather complex js.
109 } 137 }
110 138
111 void SetUpOnMainThread() override {
112 base::FilePath tmp_dir;
113 EXPECT_TRUE(base::GetTempDir(&tmp_dir));
114 webm_recorded_output_filename_ =
115 tmp_dir.Append(FILE_PATH_LITERAL("recording.webm"));
116
117 browser()->profile()->GetPrefs()->SetFilePath(
118 prefs::kDownloadDefaultDirectory, tmp_dir);
119 browser()->profile()->GetPrefs()->SetBoolean(prefs::kPromptForDownload,
120 false);
121 }
122
123 void SetUpCommandLine(base::CommandLine* command_line) override { 139 void SetUpCommandLine(base::CommandLine* command_line) override {
124 EXPECT_FALSE(command_line->HasSwitch( 140 EXPECT_FALSE(command_line->HasSwitch(
125 switches::kUseFakeUIForMediaStream)); 141 switches::kUseFakeUIForMediaStream));
126 142
127 // The WebAudio-based tests don't care what devices are available to 143 // The WebAudio-based tests don't care what devices are available to
128 // getUserMedia, and the getUserMedia-based tests will play back a file 144 // getUserMedia, and the getUserMedia-based tests will play back a file
129 // through the fake device using using --use-file-for-fake-audio-capture. 145 // through the fake device using using --use-file-for-fake-audio-capture.
130 command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream); 146 command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
131 147
132 // Add loopback interface such that there is always connectivity. 148 // Add loopback interface such that there is always connectivity.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 content::WebContents* tab_contents) { 184 content::WebContents* tab_contents) {
169 EXPECT_EQ("ok-muted", ExecuteJavascript( 185 EXPECT_EQ("ok-muted", ExecuteJavascript(
170 "setMediaElementMuted('" + element_id + "', true)", tab_contents)); 186 "setMediaElementMuted('" + element_id + "', true)", tab_contents));
171 } 187 }
172 188
173 protected: 189 protected:
174 void TestAutoGainControl(const base::FilePath::StringType& reference_filename, 190 void TestAutoGainControl(const base::FilePath::StringType& reference_filename,
175 const std::string& constraints, 191 const std::string& constraints,
176 const std::string& perf_modifier); 192 const std::string& perf_modifier);
177 void SetupAndRecordAudioCall(const base::FilePath& reference_file, 193 void SetupAndRecordAudioCall(const base::FilePath& reference_file,
178 const base::FilePath& recorded_output_path, 194 const base::FilePath& recording,
179 const std::string& constraints); 195 const std::string& constraints,
196 const base::TimeDelta recording_time);
180 void TestWithFakeDeviceGetUserMedia(const std::string& constraints, 197 void TestWithFakeDeviceGetUserMedia(const std::string& constraints,
181 const std::string& perf_modifier); 198 const std::string& perf_modifier);
182
183 base::FilePath webm_recorded_output_filename_;
184 }; 199 };
185 200
186 namespace { 201 namespace {
187 202
203 class AudioRecorder {
204 public:
205 AudioRecorder() {}
206 ~AudioRecorder() {}
207
208 // Starts the recording program for the specified duration. Returns true
209 // on success. We record in 16-bit 44.1 kHz Stereo (mostly because that's
210 // what SoundRecorder.exe will give us and we can't change that).
211 bool StartRecording(base::TimeDelta recording_time,
212 const base::FilePath& output_file) {
213 EXPECT_FALSE(recording_application_.IsValid())
214 << "Tried to record, but is already recording.";
215
216 int duration_sec = static_cast<int>(recording_time.InSeconds());
217 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
218
219 #if defined(OS_WIN)
220 // This disable is required to run SoundRecorder.exe on 64-bit Windows
221 // from a 32-bit binary. We need to load the wow64 disable function from
222 // the DLL since it doesn't exist on Windows XP.
223 base::ScopedNativeLibrary kernel32_lib(base::FilePath(L"kernel32"));
224 if (kernel32_lib.is_valid()) {
225 typedef BOOL (WINAPI* Wow64DisableWow64FSRedirection)(PVOID*);
226 Wow64DisableWow64FSRedirection wow_64_disable_wow_64_fs_redirection;
227 wow_64_disable_wow_64_fs_redirection =
228 reinterpret_cast<Wow64DisableWow64FSRedirection>(
229 kernel32_lib.GetFunctionPointer(
230 "Wow64DisableWow64FsRedirection"));
231 if (wow_64_disable_wow_64_fs_redirection != NULL) {
232 PVOID* ignored = NULL;
233 wow_64_disable_wow_64_fs_redirection(ignored);
234 }
235 }
236
237 char duration_in_hms[128] = {0};
238 struct tm duration_tm = {0};
239 duration_tm.tm_sec = duration_sec;
240 EXPECT_NE(0u, strftime(duration_in_hms, arraysize(duration_in_hms),
241 "%H:%M:%S", &duration_tm));
242
243 command_line.SetProgram(
244 base::FilePath(FILE_PATH_LITERAL("SoundRecorder.exe")));
245 command_line.AppendArg("/FILE");
246 command_line.AppendArgPath(output_file);
247 command_line.AppendArg("/DURATION");
248 command_line.AppendArg(duration_in_hms);
249 #elif defined(OS_MACOSX)
250 command_line.SetProgram(base::FilePath("rec"));
251 command_line.AppendArg("-b");
252 command_line.AppendArg("16");
253 command_line.AppendArg("-q");
254 command_line.AppendArgPath(output_file);
255 command_line.AppendArg("trim");
256 command_line.AppendArg("0");
257 command_line.AppendArg(base::IntToString(duration_sec));
258 #else
259 command_line.SetProgram(base::FilePath("arecord"));
260 command_line.AppendArg("-d");
261 command_line.AppendArg(base::IntToString(duration_sec));
262 command_line.AppendArg("-f");
263 command_line.AppendArg("cd");
264 command_line.AppendArg("-c");
265 command_line.AppendArg("2");
266 command_line.AppendArgPath(output_file);
267 #endif
268
269 DVLOG(0) << "Running " << command_line.GetCommandLineString();
270 recording_application_ =
271 base::LaunchProcess(command_line, base::LaunchOptions());
272 return recording_application_.IsValid();
273 }
274
275 // Joins the recording program. Returns true on success.
276 bool WaitForRecordingToEnd() {
277 int exit_code = -1;
278 recording_application_.WaitForExit(&exit_code);
279 return exit_code == 0;
280 }
281 private:
282 base::Process recording_application_;
283 };
284
285 bool ForceMicrophoneVolumeTo100Percent() {
286 #if defined(OS_WIN)
287 // Note: the force binary isn't in tools since it's one of our own.
288 base::CommandLine command_line(test::GetReferenceFilesDir().Append(
289 FILE_PATH_LITERAL("force_mic_volume_max.exe")));
290 DVLOG(0) << "Running " << command_line.GetCommandLineString();
291 std::string result;
292 if (!base::GetAppOutput(command_line, &result)) {
293 LOG(ERROR) << "Failed to set source volume: output was " << result;
294 return false;
295 }
296 #elif defined(OS_MACOSX)
297 base::CommandLine command_line(
298 base::FilePath(FILE_PATH_LITERAL("osascript")));
299 command_line.AppendArg("-e");
300 command_line.AppendArg("set volume input volume 100");
301 command_line.AppendArg("-e");
302 command_line.AppendArg("set volume output volume 85");
303
304 std::string result;
305 if (!base::GetAppOutput(command_line, &result)) {
306 LOG(ERROR) << "Failed to set source volume: output was " << result;
307 return false;
308 }
309 #else
310 // Just force the volume of, say the first 5 devices. A machine will rarely
311 // have more input sources than that. This is way easier than finding the
312 // input device we happen to be using.
313 for (int device_index = 0; device_index < 5; ++device_index) {
314 std::string result;
315 const std::string kHundredPercentVolume = "65536";
316 base::CommandLine command_line(base::FilePath(FILE_PATH_LITERAL("pacmd")));
317 command_line.AppendArg("set-source-volume");
318 command_line.AppendArg(base::IntToString(device_index));
319 command_line.AppendArg(kHundredPercentVolume);
320 DVLOG(0) << "Running " << command_line.GetCommandLineString();
321 if (!base::GetAppOutput(command_line, &result)) {
322 LOG(ERROR) << "Failed to set source volume: output was " << result;
323 return false;
324 }
325 }
326 #endif
327 return true;
328 }
329
188 // Sox is the "Swiss army knife" of audio processing. We mainly use it for 330 // Sox is the "Swiss army knife" of audio processing. We mainly use it for
189 // silence trimming. See http://sox.sourceforge.net. 331 // silence trimming. See http://sox.sourceforge.net.
190 base::CommandLine MakeSoxCommandLine() { 332 base::CommandLine MakeSoxCommandLine() {
191 #if defined(OS_WIN) 333 #if defined(OS_WIN)
192 base::FilePath sox_path = test::GetToolForPlatform("sox"); 334 base::FilePath sox_path = test::GetToolForPlatform("sox");
193 if (!base::PathExists(sox_path)) { 335 if (!base::PathExists(sox_path)) {
194 LOG(ERROR) << "Missing sox.exe binary in " << sox_path.value() 336 LOG(ERROR) << "Missing sox.exe binary in " << sox_path.value()
195 << "; you may have to provide this binary yourself."; 337 << "; you may have to provide this binary yourself.";
196 return base::CommandLine(base::CommandLine::NO_PROGRAM); 338 return base::CommandLine(base::CommandLine::NO_PROGRAM);
197 } 339 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 command_line.AppendArg(kDuration); 379 command_line.AppendArg(kDuration);
238 command_line.AppendArg(kTreshold); 380 command_line.AppendArg(kTreshold);
239 command_line.AppendArg("reverse"); 381 command_line.AppendArg("reverse");
240 382
241 DVLOG(0) << "Running " << command_line.GetCommandLineString(); 383 DVLOG(0) << "Running " << command_line.GetCommandLineString();
242 std::string result; 384 std::string result;
243 bool ok = base::GetAppOutput(command_line, &result); 385 bool ok = base::GetAppOutput(command_line, &result);
244 DVLOG(0) << "Output was:\n\n" << result; 386 DVLOG(0) << "Output was:\n\n" << result;
245 return ok; 387 return ok;
246 } 388 }
247
248 // Runs ffmpeg on the captured webm video and writes it to a .wav file.
249 bool RunWebmToWavConverter(const base::FilePath& webm_recorded_output_path,
250 const base::FilePath& wav_recorded_output_path) {
251 const base::FilePath path_to_ffmpeg = test::GetToolForPlatform("ffmpeg");
252 if (!base::PathExists(path_to_ffmpeg)) {
253 LOG(ERROR) << "Missing ffmpeg: should be in " << path_to_ffmpeg.value();
254 return false;
255 }
256
257 // Set up ffmpeg to output at a certain bitrate (-ab). This is hopefully set
258 // high enough to avoid degrading audio quality too much.
259 base::CommandLine ffmpeg_command(path_to_ffmpeg);
260 ffmpeg_command.AppendArg("-i");
261 ffmpeg_command.AppendArgPath(webm_recorded_output_path);
262 ffmpeg_command.AppendArg("-ab");
263 ffmpeg_command.AppendArg("300k");
264 ffmpeg_command.AppendArg("-y");
265 ffmpeg_command.AppendArgPath(wav_recorded_output_path);
266
267 // We produce an output file that will later be used as an input to the
268 // barcode decoder and frame analyzer tools.
269 DVLOG(0) << "Running " << ffmpeg_command.GetCommandLineString();
270 std::string result;
271 bool ok = base::GetAppOutputAndError(ffmpeg_command, &result);
272 DVLOG(0) << "Output was:\n\n" << result;
273 return ok;
274 }
275 389
276 // Looks for 0.2 second audio segments surrounded by silences under 0.3% audio 390 // Looks for 0.2 second audio segments surrounded by silences under 0.3% audio
277 // power and splits the input file on those silences. Output files are written 391 // power and splits the input file on those silences. Output files are written
278 // according to the output file template (e.g. /tmp/out.wav writes 392 // according to the output file template (e.g. /tmp/out.wav writes
279 // /tmp/out001.wav, /tmp/out002.wav, etc if there are two silence-padded 393 // /tmp/out001.wav, /tmp/out002.wav, etc if there are two silence-padded
280 // regions in the file). The silences between speech segments must be at 394 // regions in the file). The silences between speech segments must be at
281 // least 500 ms for this to be reliable. 395 // least 500 ms for this to be reliable.
282 bool SplitFileOnSilence(const base::FilePath& input_file, 396 bool SplitFileOnSilence(const base::FilePath& input_file,
283 const base::FilePath& output_file_template) { 397 const base::FilePath& output_file_template) {
284 base::CommandLine command_line = MakeSoxCommandLine(); 398 base::CommandLine command_line = MakeSoxCommandLine();
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
466 float difference_in_decibel = AnalyzeOneSegment(ref_segments[i], 580 float difference_in_decibel = AnalyzeOneSegment(ref_segments[i],
467 actual_segments[i], 581 actual_segments[i],
468 i); 582 i);
469 std::string trace_name = MakeTraceName(reference_file, i); 583 std::string trace_name = MakeTraceName(reference_file, i);
470 perf_test::PrintResult("agc_energy_diff", perf_modifier, trace_name, 584 perf_test::PrintResult("agc_energy_diff", perf_modifier, trace_name,
471 difference_in_decibel, "dB", false); 585 difference_in_decibel, "dB", false);
472 } 586 }
473 } 587 }
474 588
475 void ComputeAndPrintPesqResults(const base::FilePath& reference_file, 589 void ComputeAndPrintPesqResults(const base::FilePath& reference_file,
476 const base::FilePath& recorded_output_path, 590 const base::FilePath& recording,
477 const std::string& perf_modifier) { 591 const std::string& perf_modifier) {
478 base::FilePath trimmed_reference = CreateTemporaryWaveFile(); 592 base::FilePath trimmed_reference = CreateTemporaryWaveFile();
479 base::FilePath trimmed_recording = CreateTemporaryWaveFile(); 593 base::FilePath trimmed_recording = CreateTemporaryWaveFile();
480 594
481 ASSERT_TRUE(RemoveSilence(reference_file, trimmed_reference)); 595 ASSERT_TRUE(RemoveSilence(reference_file, trimmed_reference));
482 ASSERT_TRUE(RemoveSilence(recorded_output_path, trimmed_recording)); 596 ASSERT_TRUE(RemoveSilence(recording, trimmed_recording));
483 597
484 std::string raw_mos; 598 std::string raw_mos;
485 std::string mos_lqo; 599 std::string mos_lqo;
486 bool succeeded = RunPesq(trimmed_reference, trimmed_recording, 16000, 600 bool succeeded = RunPesq(trimmed_reference, trimmed_recording, 16000,
487 &raw_mos, &mos_lqo); 601 &raw_mos, &mos_lqo);
488 EXPECT_TRUE(succeeded) << "Failed to run PESQ."; 602 EXPECT_TRUE(succeeded) << "Failed to run PESQ.";
489 if (succeeded) { 603 if (succeeded) {
490 perf_test::PrintResult( 604 perf_test::PrintResult(
491 "audio_pesq", perf_modifier, "raw_mos", raw_mos, "score", true); 605 "audio_pesq", perf_modifier, "raw_mos", raw_mos, "score", true);
492 perf_test::PrintResult( 606 perf_test::PrintResult(
493 "audio_pesq", perf_modifier, "mos_lqo", mos_lqo, "score", true); 607 "audio_pesq", perf_modifier, "mos_lqo", mos_lqo, "score", true);
494 } 608 }
495 609
496 DeleteFileUnlessTestFailed(trimmed_reference, false); 610 DeleteFileUnlessTestFailed(trimmed_reference, false);
497 DeleteFileUnlessTestFailed(trimmed_recording, false); 611 DeleteFileUnlessTestFailed(trimmed_recording, false);
498 } 612 }
499 613
500 } // namespace 614 } // namespace
501 615
502 // Sets up a two-way WebRTC call and records its output to 616 // Sets up a two-way WebRTC call and records its output to |recording|, using
503 // |recorded_output_path|, using getUserMedia. 617 // getUserMedia.
504 // 618 //
505 // |reference_file| should have at least five seconds of silence in the 619 // |reference_file| should have at least five seconds of silence in the
506 // beginning: otherwise all the reference audio will not be picked up by the 620 // beginning: otherwise all the reference audio will not be picked up by the
507 // recording. Note that the reference file will start playing as soon as the 621 // recording. Note that the reference file will start playing as soon as the
508 // audio device is up following the getUserMedia call in the left tab. The time 622 // audio device is up following the getUserMedia call in the left tab. The time
509 // it takes to negotiate a call isn't deterministic, but five seconds should be 623 // it takes to negotiate a call isn't deterministic, but five seconds should be
510 // plenty of time. Similarly, the recording time should be enough to catch the 624 // plenty of time. Similarly, the recording time should be enough to catch the
511 // whole reference file. If you then silence-trim the reference file and actual 625 // whole reference file. If you then silence-trim the reference file and actual
512 // file, you should end up with two time-synchronized files. 626 // file, you should end up with two time-synchronized files.
513 void MAYBE_WebRtcAudioQualityBrowserTest::SetupAndRecordAudioCall( 627 void MAYBE_WebRtcAudioQualityBrowserTest::SetupAndRecordAudioCall(
514 const base::FilePath& reference_file, 628 const base::FilePath& reference_file,
515 const base::FilePath& recorded_output_path, 629 const base::FilePath& recording,
516 const std::string& constraints) { 630 const std::string& constraints,
631 const base::TimeDelta recording_time) {
517 ASSERT_TRUE(embedded_test_server()->Start()); 632 ASSERT_TRUE(embedded_test_server()->Start());
518 ASSERT_TRUE(test::HasReferenceFilesInCheckout()); 633 ASSERT_TRUE(test::HasReferenceFilesInCheckout());
634 ASSERT_TRUE(ForceMicrophoneVolumeTo100Percent());
519 635
520 ConfigureFakeDeviceToPlayFile(reference_file); 636 ConfigureFakeDeviceToPlayFile(reference_file);
521 637
522 // Create a two-way call. Mute one of the receivers though; that way it will 638 // Create a two-way call. Mute one of the receivers though; that way it will
523 // be receiving audio bytes, but we will not be playing out of both elements. 639 // be receiving audio bytes, but we will not be playing out of both elements.
524 GURL test_page = embedded_test_server()->GetURL(kWebRtcAudioTestHtmlPage); 640 GURL test_page = embedded_test_server()->GetURL(kWebRtcAudioTestHtmlPage);
525 content::WebContents* left_tab = 641 content::WebContents* left_tab =
526 OpenPageAndGetUserMediaInNewTabWithConstraints(test_page, constraints); 642 OpenPageAndGetUserMediaInNewTabWithConstraints(test_page, constraints);
527 SetupPeerconnectionWithLocalStream(left_tab); 643 SetupPeerconnectionWithLocalStream(left_tab);
528 MuteMediaElement("remote-view", left_tab); 644 MuteMediaElement("remote-view", left_tab);
529 645
530 content::WebContents* right_tab = 646 content::WebContents* right_tab =
531 OpenPageAndGetUserMediaInNewTabWithConstraints(test_page, constraints); 647 OpenPageAndGetUserMediaInNewTabWithConstraints(test_page, constraints);
532 SetupPeerconnectionWithLocalStream(right_tab); 648 SetupPeerconnectionWithLocalStream(right_tab);
533 649
650 AudioRecorder recorder;
651 ASSERT_TRUE(recorder.StartRecording(recording_time, recording));
652
534 NegotiateCall(left_tab, right_tab); 653 NegotiateCall(left_tab, right_tab);
535 654
536 EXPECT_EQ( 655 ASSERT_TRUE(recorder.WaitForRecordingToEnd());
537 "ok-capturing", 656 DVLOG(0) << "Done recording to " << recording.value() << std::endl;
538 ExecuteJavascript(
539 base::StringPrintf("startAudioCapture(%d, \"%s\");",
540 kCaptureDurationInSeconds, kWebmRecordingFilename),
541 right_tab));
542
543 EXPECT_TRUE(test::PollingWaitUntil("testIsDoneCapturing();", "true",
544 right_tab, kPollingIntervalInMs));
545 657
546 HangUp(left_tab); 658 HangUp(left_tab);
547
548 RunWebmToWavConverter(webm_recorded_output_filename_, recorded_output_path);
549 EXPECT_TRUE(base::DieFileDie(webm_recorded_output_filename_, false));
550
551 DVLOG(0) << "Done recording to " << recorded_output_path.MaybeAsASCII();
552 } 659 }
553 660
554 void MAYBE_WebRtcAudioQualityBrowserTest::TestWithFakeDeviceGetUserMedia( 661 void MAYBE_WebRtcAudioQualityBrowserTest::TestWithFakeDeviceGetUserMedia(
555 const std::string& constraints, 662 const std::string& constraints,
556 const std::string& perf_modifier) { 663 const std::string& perf_modifier) {
557 if (OnWin8()) { 664 if (OnWin8()) {
558 // http://crbug.com/379798. 665 // http://crbug.com/379798.
559 LOG(ERROR) << "This test is not implemented for Windows XP/Win8."; 666 LOG(ERROR) << "This test is not implemented for Windows XP/Win8.";
560 return; 667 return;
561 } 668 }
562 669
563 base::FilePath reference_file = 670 base::FilePath reference_file =
564 test::GetReferenceFilesDir().Append(kReferenceFile); 671 test::GetReferenceFilesDir().Append(kReferenceFile);
565 base::FilePath recorded_output_path = CreateTemporaryWaveFile(); 672 base::FilePath recording = CreateTemporaryWaveFile();
566 673
567 ASSERT_NO_FATAL_FAILURE(SetupAndRecordAudioCall( 674 ASSERT_NO_FATAL_FAILURE(SetupAndRecordAudioCall(
568 reference_file, recorded_output_path, constraints)); 675 reference_file, recording, constraints,
676 base::TimeDelta::FromSeconds(30)));
569 677
570 ComputeAndPrintPesqResults(reference_file, recorded_output_path, 678 ComputeAndPrintPesqResults(reference_file, recording, perf_modifier);
571 perf_modifier); 679 DeleteFileUnlessTestFailed(recording, false);
572 DeleteFileUnlessTestFailed(recorded_output_path, false);
573 } 680 }
574 681
575 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcAudioQualityBrowserTest, 682 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcAudioQualityBrowserTest,
576 MANUAL_TestCallQualityWithAudioFromFakeDevice) { 683 MANUAL_TestCallQualityWithAudioFromFakeDevice) {
577 TestWithFakeDeviceGetUserMedia(kAudioOnlyCallConstraints, "_getusermedia"); 684 TestWithFakeDeviceGetUserMedia(kAudioOnlyCallConstraints, "_getusermedia");
578 } 685 }
579 686
580 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcAudioQualityBrowserTest, 687 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcAudioQualityBrowserTest,
581 MANUAL_TestCallQualityWithAudioFromWebAudio) { 688 MANUAL_TestCallQualityWithAudioFromWebAudio) {
582 if (OnWin8()) { 689 if (OnWin8()) {
583 // http://crbug.com/379798. 690 // http://crbug.com/379798.
584 LOG(ERROR) << "This test is not implemented for Windows XP/Win8."; 691 LOG(ERROR) << "This test is not implemented for Windows XP/Win8.";
585 return; 692 return;
586 } 693 }
587 ASSERT_TRUE(test::HasReferenceFilesInCheckout()); 694 ASSERT_TRUE(test::HasReferenceFilesInCheckout());
588 ASSERT_TRUE(embedded_test_server()->Start()); 695 ASSERT_TRUE(embedded_test_server()->Start());
589 696
697 ASSERT_TRUE(ForceMicrophoneVolumeTo100Percent());
698
590 content::WebContents* left_tab = 699 content::WebContents* left_tab =
591 OpenPageWithoutGetUserMedia(kWebRtcAudioTestHtmlPage); 700 OpenPageWithoutGetUserMedia(kWebRtcAudioTestHtmlPage);
592 content::WebContents* right_tab = 701 content::WebContents* right_tab =
593 OpenPageWithoutGetUserMedia(kWebRtcAudioTestHtmlPage); 702 OpenPageWithoutGetUserMedia(kWebRtcAudioTestHtmlPage);
594 703
595 AddAudioFileToWebAudio(kReferenceFileRelativeUrl, left_tab); 704 AddAudioFileToWebAudio(kReferenceFileRelativeUrl, left_tab);
596 705
597 NegotiateCall(left_tab, right_tab); 706 NegotiateCall(left_tab, right_tab);
598 707
599 const base::FilePath recorded_output_path = CreateTemporaryWaveFile(); 708 base::FilePath recording = CreateTemporaryWaveFile();
709
710 // Note: the sound clip is 21.6 seconds: record for 25 seconds to get some
711 // safety margins on each side.
712 AudioRecorder recorder;
713 ASSERT_TRUE(recorder.StartRecording(base::TimeDelta::FromSeconds(25),
714 recording));
600 715
601 PlayAudioFileThroughWebAudio(left_tab); 716 PlayAudioFileThroughWebAudio(left_tab);
602 717
603 EXPECT_EQ( 718 ASSERT_TRUE(recorder.WaitForRecordingToEnd());
604 "ok-capturing", 719 DVLOG(0) << "Done recording to " << recording.value() << std::endl;
605 ExecuteJavascript(
606 base::StringPrintf("startAudioCapture(%d, \"%s\");",
607 kCaptureDurationInSeconds, kWebmRecordingFilename),
608 right_tab));
609
610 EXPECT_TRUE(test::PollingWaitUntil("testIsDoneCapturing();", "true",
611 right_tab, kPollingIntervalInMs));
612 720
613 HangUp(left_tab); 721 HangUp(left_tab);
614 722
615 RunWebmToWavConverter(webm_recorded_output_filename_, recorded_output_path);
616 EXPECT_TRUE(base::DieFileDie(webm_recorded_output_filename_, false));
617
618 DVLOG(0) << "Done recording to " << recorded_output_path.MaybeAsASCII();
619
620 // Compare with the reference file on disk (this is the same file we played 723 // Compare with the reference file on disk (this is the same file we played
621 // through WebAudio earlier). 724 // through WebAudio earlier).
622 base::FilePath reference_file = 725 base::FilePath reference_file =
623 test::GetReferenceFilesDir().Append(kReferenceFile); 726 test::GetReferenceFilesDir().Append(kReferenceFile);
624 ComputeAndPrintPesqResults(reference_file, recorded_output_path, "_webaudio"); 727 ComputeAndPrintPesqResults(reference_file, recording, "_webaudio");
625 } 728 }
626 729
627 /** 730 /**
628 * The auto gain control test plays a file into the fake microphone. Then it 731 * The auto gain control test plays a file into the fake microphone. Then it
629 * sets up a one-way WebRTC call with audio only and records Chrome's output on 732 * sets up a one-way WebRTC call with audio only and records Chrome's output on
630 * the receiving side using the audio loopback provided by the quality test 733 * the receiving side using the audio loopback provided by the quality test
631 * (see the class comments for more details). 734 * (see the class comments for more details).
632 * 735 *
633 * Then both the recording and reference file are split on silence. This creates 736 * Then both the recording and reference file are split on silence. This creates
634 * a number of segments with speech in them. The reason for this is to provide 737 * a number of segments with speech in them. The reason for this is to provide
(...skipping 23 matching lines...) Expand all
658 const base::FilePath::StringType& reference_filename, 761 const base::FilePath::StringType& reference_filename,
659 const std::string& constraints, 762 const std::string& constraints,
660 const std::string& perf_modifier) { 763 const std::string& perf_modifier) {
661 if (OnWin8()) { 764 if (OnWin8()) {
662 // http://crbug.com/379798. 765 // http://crbug.com/379798.
663 LOG(ERROR) << "This test is not implemented for Windows XP/Win8."; 766 LOG(ERROR) << "This test is not implemented for Windows XP/Win8.";
664 return; 767 return;
665 } 768 }
666 base::FilePath reference_file = 769 base::FilePath reference_file =
667 test::GetReferenceFilesDir().Append(reference_filename); 770 test::GetReferenceFilesDir().Append(reference_filename);
668 base::FilePath recorded_output_path = CreateTemporaryWaveFile(); 771 base::FilePath recording = CreateTemporaryWaveFile();
669 772
670 ASSERT_NO_FATAL_FAILURE(SetupAndRecordAudioCall( 773 ASSERT_NO_FATAL_FAILURE(SetupAndRecordAudioCall(
671 reference_file, recorded_output_path, constraints)); 774 reference_file, recording, constraints,
775 base::TimeDelta::FromSeconds(30)));
672 776
673 base::ScopedTempDir split_ref_files; 777 base::ScopedTempDir split_ref_files;
674 ASSERT_TRUE(split_ref_files.CreateUniqueTempDir()); 778 ASSERT_TRUE(split_ref_files.CreateUniqueTempDir());
675 ASSERT_NO_FATAL_FAILURE( 779 ASSERT_NO_FATAL_FAILURE(
676 SplitFileOnSilenceIntoDir(reference_file, split_ref_files.GetPath())); 780 SplitFileOnSilenceIntoDir(reference_file, split_ref_files.GetPath()));
677 std::vector<base::FilePath> ref_segments = 781 std::vector<base::FilePath> ref_segments =
678 ListWavFilesInDir(split_ref_files.GetPath()); 782 ListWavFilesInDir(split_ref_files.GetPath());
679 783
680 base::ScopedTempDir split_actual_files; 784 base::ScopedTempDir split_actual_files;
681 ASSERT_TRUE(split_actual_files.CreateUniqueTempDir()); 785 ASSERT_TRUE(split_actual_files.CreateUniqueTempDir());
682 ASSERT_NO_FATAL_FAILURE(SplitFileOnSilenceIntoDir( 786 ASSERT_NO_FATAL_FAILURE(
683 recorded_output_path, split_actual_files.GetPath())); 787 SplitFileOnSilenceIntoDir(recording, split_actual_files.GetPath()));
684 788
685 // Keep the recording and split files if the analysis fails. 789 // Keep the recording and split files if the analysis fails.
686 base::FilePath actual_files_dir = split_actual_files.Take(); 790 base::FilePath actual_files_dir = split_actual_files.Take();
687 std::vector<base::FilePath> actual_segments = 791 std::vector<base::FilePath> actual_segments =
688 ListWavFilesInDir(actual_files_dir); 792 ListWavFilesInDir(actual_files_dir);
689 793
690 AnalyzeSegmentsAndPrintResult( 794 AnalyzeSegmentsAndPrintResult(
691 ref_segments, actual_segments, reference_file, perf_modifier); 795 ref_segments, actual_segments, reference_file, perf_modifier);
692 796
693 DeleteFileUnlessTestFailed(recorded_output_path, false); 797 DeleteFileUnlessTestFailed(recording, false);
694 DeleteFileUnlessTestFailed(actual_files_dir, true); 798 DeleteFileUnlessTestFailed(actual_files_dir, true);
695 } 799 }
696 800
697 // The AGC should apply non-zero gain here. 801 // The AGC should apply non-zero gain here.
698 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcAudioQualityBrowserTest, 802 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcAudioQualityBrowserTest,
699 MANUAL_TestAutoGainControlOnLowAudio) { 803 MANUAL_TestAutoGainControlOnLowAudio) {
700 ASSERT_NO_FATAL_FAILURE(TestAutoGainControl( 804 ASSERT_NO_FATAL_FAILURE(TestAutoGainControl(
701 kReferenceFile, kAudioOnlyCallConstraints, "_with_agc")); 805 kReferenceFile, kAudioOnlyCallConstraints, "_with_agc"));
702 } 806 }
703 807
704 // Since the AGC is off here there should be no gain at all. 808 // Since the AGC is off here there should be no gain at all.
705 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcAudioQualityBrowserTest, 809 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcAudioQualityBrowserTest,
706 MANUAL_TestAutoGainIsOffWithAudioProcessingOff) { 810 MANUAL_TestAutoGainIsOffWithAudioProcessingOff) {
707 const char* kAudioCallWithoutAudioProcessing = 811 const char* kAudioCallWithoutAudioProcessing =
708 "{audio: { mandatory: { echoCancellation: false } } }"; 812 "{audio: { mandatory: { echoCancellation: false } } }";
709 ASSERT_NO_FATAL_FAILURE(TestAutoGainControl( 813 ASSERT_NO_FATAL_FAILURE(TestAutoGainControl(
710 kReferenceFile, kAudioCallWithoutAudioProcessing, "_no_agc")); 814 kReferenceFile, kAudioCallWithoutAudioProcessing, "_no_agc"));
711 } 815 }
OLDNEW
« no previous file with comments | « no previous file | chrome/test/data/webrtc/audio_extraction.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698