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

Side by Side Diff: content/browser/media/webrtc_audio_debug_recordings_browsertest.cc

Issue 1272223003: Implement writing mic audio input data to file for debugging purposes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Renamed and updated browser test. Rebase. Created 5 years, 3 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
OLDNEW
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2014 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 "base/process/process_handle.h" 5 #include "base/process/process_handle.h"
6 #include "base/strings/string_number_conversions.h" 6 #include "base/strings/string_number_conversions.h"
7 #include "base/strings/stringprintf.h" 7 #include "base/strings/stringprintf.h"
8 #include "content/browser/media/webrtc_internals.h" 8 #include "content/browser/media/webrtc_internals.h"
9 #include "content/browser/web_contents/web_contents_impl.h" 9 #include "content/browser/web_contents/web_contents_impl.h"
10 #include "content/public/test/browser_test_utils.h" 10 #include "content/public/test/browser_test_utils.h"
11 #include "content/public/test/content_browser_test_utils.h" 11 #include "content/public/test/content_browser_test_utils.h"
12 #include "content/shell/browser/shell.h" 12 #include "content/shell/browser/shell.h"
13 #include "content/test/webrtc_content_browsertest_base.h" 13 #include "content/test/webrtc_content_browsertest_base.h"
14 #include "media/audio/audio_manager.h" 14 #include "media/audio/audio_manager.h"
15 #include "net/test/embedded_test_server/embedded_test_server.h" 15 #include "net/test/embedded_test_server/embedded_test_server.h"
16 16
17 #if defined(OS_WIN)
18 #define IntToStringType base::IntToString16
tommi (sloooow) - chröme 2015/08/31 17:19:06 nit / pondering: Can this be done with 'using' now
Henrik Grunell 2015/09/04 12:37:37 No, can alias types and templates but not function
19 #else
20 #define IntToStringType base::IntToString
21 #endif
22
17 namespace { 23 namespace {
18 24
19 const int kExpectedConsumerId = 0; 25 const int kExpectedConsumerId = 1;
26 const int kExpectedStreamId = 1;
20 27
21 // Get the ID for the render process host when there should only be one. 28 // Get the ID for the render process host when there should only be one.
22 bool GetRenderProcessHostId(base::ProcessId* id) { 29 bool GetRenderProcessHostId(base::ProcessId* id) {
23 content::RenderProcessHost::iterator it( 30 content::RenderProcessHost::iterator it(
24 content::RenderProcessHost::AllHostsIterator()); 31 content::RenderProcessHost::AllHostsIterator());
25 *id = base::GetProcId(it.GetCurrentValue()->GetHandle()); 32 *id = base::GetProcId(it.GetCurrentValue()->GetHandle());
26 EXPECT_NE(base::kNullProcessId, *id); 33 EXPECT_NE(base::kNullProcessId, *id);
27 if (*id == base::kNullProcessId) 34 if (*id == base::kNullProcessId)
28 return false; 35 return false;
29 it.Advance(); 36 it.Advance();
30 EXPECT_TRUE(it.IsAtEnd()); 37 EXPECT_TRUE(it.IsAtEnd());
31 return it.IsAtEnd(); 38 return it.IsAtEnd();
32 } 39 }
33 40
41 // Get the expected AEC dump file name. The name will be
42 // <temporary path>.<render process id>.aec_dump.<consumer id>, for example
43 // "/tmp/.com.google.Chrome.Z6UC3P.12345.aec_dump.1".
44 base::FilePath GetExpectedAecDumpFileName(const base::FilePath& base_file,
45 int render_process_id) {
46 return base_file.AddExtension(IntToStringType(render_process_id))
47 .AddExtension("aec_dump")
48 .AddExtension(IntToStringType(kExpectedConsumerId));
49 }
50
51 // Get the expected input audio file name. The name will be
52 // <temporary path>.<render process id>.source_input.<stream id>.pcm, for
53 // example "/tmp/.com.google.Chrome.Z6UC3P.12345.source_input.1.pcm".
54 base::FilePath GetExpectedInputAudioFileName(const base::FilePath& base_file,
55 int render_process_id) {
56 return base_file.AddExtension(IntToStringType(render_process_id))
57 .AddExtension("source_input")
58 .AddExtension(IntToStringType(kExpectedStreamId))
59 .AddExtension("pcm");
60 }
61
34 } // namespace 62 } // namespace
35 63
36 namespace content { 64 namespace content {
37 65
38 class WebRtcAecDumpBrowserTest : public WebRtcContentBrowserTest { 66 class WebRtcAudioDebugRecordingsBrowserTest : public WebRtcContentBrowserTest {
39 public: 67 public:
40 WebRtcAecDumpBrowserTest() {} 68 WebRtcAudioDebugRecordingsBrowserTest() {}
41 ~WebRtcAecDumpBrowserTest() override {} 69 ~WebRtcAudioDebugRecordingsBrowserTest() override {}
42 }; 70 };
43 71
44 #if defined(OS_WIN)
45 #define IntToStringType base::IntToString16
46 #else
47 #define IntToStringType base::IntToString
48 #endif
49
50 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY) 72 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
51 // Timing out on ARM linux bot: http://crbug.com/238490 73 // Timing out on ARM linux bot: http://crbug.com/238490
52 #define MAYBE_CallWithAecDump DISABLED_CallWithAecDump 74 #define MAYBE_CallWithAudioDebugRecordings DISABLED_CallWithAudioDebugRecordings
53 #elif defined(OS_ANDROID) && defined(ADDRESS_SANITIZER) 75 #elif defined(OS_ANDROID) && defined(ADDRESS_SANITIZER)
54 // Renderer crashes under Android ASAN: https://crbug.com/408496. 76 // Renderer crashes under Android ASAN: https://crbug.com/408496.
55 #define MAYBE_CallWithAecDump DISABLED_CallWithAecDump 77 #define MAYBE_CallWithAudioDebugRecordings DISABLED_CallWithAudioDebugRecordings
56 #else 78 #else
57 #define MAYBE_CallWithAecDump CallWithAecDump 79 #define MAYBE_CallWithAudioDebugRecordings CallWithAudioDebugRecordings
58 #endif 80 #endif
59 81
60 // This tests will make a complete PeerConnection-based call, verify that 82 // This tests will make a complete PeerConnection-based call, verify that
61 // video is playing for the call, and verify that a non-empty AEC dump file 83 // video is playing for the call, and verify that a non-empty AEC dump file
62 // exists. The AEC dump is enabled through webrtc-internals. The HTML and 84 // exists. The AEC dump is enabled through webrtc-internals. The HTML and
63 // Javascript is bypassed since it would trigger a file picker dialog. Instead, 85 // Javascript is bypassed since it would trigger a file picker dialog. Instead,
64 // the dialog callback FileSelected() is invoked directly. In fact, there's 86 // the dialog callback FileSelected() is invoked directly. In fact, there's
65 // never a webrtc-internals page opened at all since that's not needed. 87 // never a webrtc-internals page opened at all since that's not needed.
66 IN_PROC_BROWSER_TEST_F(WebRtcAecDumpBrowserTest, MAYBE_CallWithAecDump) { 88 IN_PROC_BROWSER_TEST_F(WebRtcAudioDebugRecordingsBrowserTest,
89 MAYBE_CallWithAudioDebugRecordings) {
67 if (!media::AudioManager::Get()->HasAudioOutputDevices()) { 90 if (!media::AudioManager::Get()->HasAudioOutputDevices()) {
68 LOG(INFO) << "Missing output devices: skipping test..."; 91 LOG(INFO) << "Missing output devices: skipping test...";
69 return; 92 return;
70 } 93 }
71 94
72 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 95 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
73 96
74 // We must navigate somewhere first so that the render process is created. 97 // We must navigate somewhere first so that the render process is created.
75 NavigateToURL(shell(), GURL("")); 98 NavigateToURL(shell(), GURL(""));
76 99
77 base::FilePath dump_file; 100 base::FilePath base_file;
78 ASSERT_TRUE(CreateTemporaryFile(&dump_file)); 101 ASSERT_TRUE(CreateTemporaryFile(&base_file));
79 base::DeleteFile(dump_file, false); 102 base::DeleteFile(base_file, false);
80 103
81 // This fakes the behavior of another open tab with webrtc-internals, and 104 // This fakes the behavior of another open tab with webrtc-internals, and
82 // enabling AEC dump in that tab. 105 // enabling AEC dump in that tab.
83 WebRTCInternals::GetInstance()->FileSelected(dump_file, -1, NULL); 106 WebRTCInternals::GetInstance()->FileSelected(base_file, -1, NULL);
84 107
85 GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html")); 108 GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
86 NavigateToURL(shell(), url); 109 NavigateToURL(shell(), url);
87 ExecuteJavascriptAndWaitForOk("call({video: true, audio: true});"); 110 ExecuteJavascriptAndWaitForOk("call({video: true, audio: true});");
88 111
89 EXPECT_FALSE(base::PathExists(dump_file)); 112 EXPECT_FALSE(base::PathExists(base_file));
90 113
91 // Add file extensions that we expect to be added. The dump name will be 114 // Verify that the expected AEC dump file exists and contains some data.
92 // <temporary path>.<render process id>.<consumer id>, for example
93 // "/tmp/.com.google.Chrome.Z6UC3P.12345.0".
94 base::ProcessId render_process_id = base::kNullProcessId; 115 base::ProcessId render_process_id = base::kNullProcessId;
95 EXPECT_TRUE(GetRenderProcessHostId(&render_process_id)); 116 EXPECT_TRUE(GetRenderProcessHostId(&render_process_id));
96 dump_file = dump_file.AddExtension(IntToStringType(render_process_id)) 117 base::FilePath aec_dump_file = GetExpectedAecDumpFileName(base_file,
97 .AddExtension(IntToStringType(kExpectedConsumerId)); 118 render_process_id);
98 119
99 EXPECT_TRUE(base::PathExists(dump_file)); 120 EXPECT_TRUE(base::PathExists(aec_dump_file));
100 int64 file_size = 0; 121 int64 file_size = 0;
101 EXPECT_TRUE(base::GetFileSize(dump_file, &file_size)); 122 EXPECT_TRUE(base::GetFileSize(aec_dump_file, &file_size));
102 EXPECT_GT(file_size, 0); 123 EXPECT_GT(file_size, 0);
103 124
104 base::DeleteFile(dump_file, false); 125 base::DeleteFile(aec_dump_file, false);
126
127 // Verify that the expected input audio file exists and contains some data.
128 base::FilePath input_audio_file =
129 GetExpectedInputAudioFileName(base_file, render_process_id);
130
131 EXPECT_TRUE(base::PathExists(input_audio_file));
132 file_size = 0;
133 EXPECT_TRUE(base::GetFileSize(input_audio_file, &file_size));
134 EXPECT_GT(file_size, 0);
135
136 base::DeleteFile(input_audio_file, false);
105 } 137 }
106 138
107 // TODO(grunell): Add test for multiple dumps when re-use of 139 // TODO(grunell): Add test for multiple dumps when re-use of
108 // MediaStreamAudioProcessor in AudioCapturer has been removed. 140 // MediaStreamAudioProcessor in AudioCapturer has been removed.
109 141
110 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY) 142 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
111 // Timing out on ARM linux bot: http://crbug.com/238490 143 // Timing out on ARM linux bot: http://crbug.com/238490
112 #define MAYBE_CallWithAecDumpEnabledThenDisabled DISABLED_CallWithAecDumpEnabled ThenDisabled 144 #define MAYBE_CallWithAudioDebugRecordingsEnabledThenDisabled DISABLED_CallWithA udioDebugRecordingsEnabledThenDisabled
113 #elif defined(OS_ANDROID) && defined(ADDRESS_SANITIZER) 145 #elif defined(OS_ANDROID) && defined(ADDRESS_SANITIZER)
114 // Renderer crashes under Android ASAN: https://crbug.com/408496. 146 // Renderer crashes under Android ASAN: https://crbug.com/408496.
115 #define MAYBE_CallWithAecDumpEnabledThenDisabled DISABLED_CallWithAecDumpEnabled ThenDisabled 147 #define MAYBE_CallWithAudioDebugRecordingsEnabledThenDisabled DISABLED_CallWithA udioDebugRecordingsEnabledThenDisabled
116 #else 148 #else
117 #define MAYBE_CallWithAecDumpEnabledThenDisabled CallWithAecDumpEnabledThenDisab led 149 #define MAYBE_CallWithAudioDebugRecordingsEnabledThenDisabled CallWithAudioDebug RecordingsEnabledThenDisabled
118 #endif 150 #endif
119 151
120 // As above, but enable and disable dump before starting a call. The file should 152 // As above, but enable and disable dump before starting a call. The file should
121 // be created, but should be empty. 153 // be created, but should be empty.
122 IN_PROC_BROWSER_TEST_F(WebRtcAecDumpBrowserTest, 154 IN_PROC_BROWSER_TEST_F(WebRtcAudioDebugRecordingsBrowserTest,
123 MAYBE_CallWithAecDumpEnabledThenDisabled) { 155 MAYBE_CallWithAudioDebugRecordingsEnabledThenDisabled) {
124 if (!media::AudioManager::Get()->HasAudioOutputDevices()) { 156 if (!media::AudioManager::Get()->HasAudioOutputDevices()) {
125 LOG(INFO) << "Missing output devices: skipping test..."; 157 LOG(INFO) << "Missing output devices: skipping test...";
126 return; 158 return;
127 } 159 }
128 160
129 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 161 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
130 162
131 // We must navigate somewhere first so that the render process is created. 163 // We must navigate somewhere first so that the render process is created.
132 NavigateToURL(shell(), GURL("")); 164 NavigateToURL(shell(), GURL(""));
133 165
134 base::FilePath dump_file; 166 base::FilePath base_file;
135 ASSERT_TRUE(CreateTemporaryFile(&dump_file)); 167 ASSERT_TRUE(CreateTemporaryFile(&base_file));
136 base::DeleteFile(dump_file, false); 168 base::DeleteFile(base_file, false);
137 169
138 // This fakes the behavior of another open tab with webrtc-internals, and 170 // This fakes the behavior of another open tab with webrtc-internals, and
139 // enabling AEC dump in that tab, then disabling it. 171 // enabling AEC dump in that tab, then disabling it.
140 WebRTCInternals::GetInstance()->FileSelected(dump_file, -1, NULL); 172 WebRTCInternals::GetInstance()->FileSelected(base_file, -1, NULL);
141 WebRTCInternals::GetInstance()->DisableAecDump(); 173 WebRTCInternals::GetInstance()->DisableAudioDebugRecordings();
142 174
143 GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html")); 175 GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
144 NavigateToURL(shell(), url); 176 NavigateToURL(shell(), url);
145 ExecuteJavascriptAndWaitForOk("call({video: true, audio: true});"); 177 ExecuteJavascriptAndWaitForOk("call({video: true, audio: true});");
146 178
147 // Add file extensions that we expect to be added. 179 // Verify that the expected AEC dump file doesn't exist.
148 base::ProcessId render_process_id = base::kNullProcessId; 180 base::ProcessId render_process_id = base::kNullProcessId;
149 EXPECT_TRUE(GetRenderProcessHostId(&render_process_id)); 181 EXPECT_TRUE(GetRenderProcessHostId(&render_process_id));
150 dump_file = dump_file.AddExtension(IntToStringType(render_process_id)) 182 base::FilePath aec_dump_file = GetExpectedAecDumpFileName(base_file,
151 .AddExtension(IntToStringType(kExpectedConsumerId)); 183 render_process_id);
184 EXPECT_FALSE(base::PathExists(aec_dump_file));
185 base::DeleteFile(aec_dump_file, false);
152 186
153 EXPECT_FALSE(base::PathExists(dump_file)); 187 // Verify that the expected input audio file doesn't exist.
154 188 base::FilePath input_audio_file =
155 base::DeleteFile(dump_file, false); 189 GetExpectedInputAudioFileName(base_file, render_process_id);
190 EXPECT_FALSE(base::PathExists(input_audio_file));
191 base::DeleteFile(input_audio_file, false);
156 } 192 }
157 193
158 // Timing out on ARM linux bot: http://crbug.com/238490 194 // Timing out on ARM linux bot: http://crbug.com/238490
159 // Renderer crashes under Android ASAN: https://crbug.com/408496. 195 // Renderer crashes under Android ASAN: https://crbug.com/408496.
160 // Flaky on XP and Mac: http://crbug.com/425034. 196 // Flaky on XP and Mac: http://crbug.com/425034.
161 IN_PROC_BROWSER_TEST_F(WebRtcAecDumpBrowserTest, DISABLED_TwoCallsWithAecDump) { 197 IN_PROC_BROWSER_TEST_F(WebRtcAudioDebugRecordingsBrowserTest,
198 DISABLED_TwoCallsWithAudioDebugRecordings) {
162 if (OnWinXp()) { 199 if (OnWinXp()) {
163 LOG(INFO) << "Disabled on Win XP: skipping test..."; 200 LOG(INFO) << "Disabled on Win XP: skipping test...";
164 return; 201 return;
165 } 202 }
166 if (!media::AudioManager::Get()->HasAudioOutputDevices()) { 203 if (!media::AudioManager::Get()->HasAudioOutputDevices()) {
167 LOG(INFO) << "Missing output devices: skipping test..."; 204 LOG(INFO) << "Missing output devices: skipping test...";
168 return; 205 return;
169 } 206 }
170 207
171 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 208 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
172 209
173 // We must navigate somewhere first so that the render process is created. 210 // We must navigate somewhere first so that the render process is created.
174 NavigateToURL(shell(), GURL("")); 211 NavigateToURL(shell(), GURL(""));
175 212
176 // Create a second window. 213 // Create a second window.
177 Shell* shell2 = CreateBrowser(); 214 Shell* shell2 = CreateBrowser();
178 NavigateToURL(shell2, GURL("")); 215 NavigateToURL(shell2, GURL(""));
179 216
180 base::FilePath dump_file; 217 base::FilePath base_file;
181 ASSERT_TRUE(CreateTemporaryFile(&dump_file)); 218 ASSERT_TRUE(CreateTemporaryFile(&base_file));
182 base::DeleteFile(dump_file, false); 219 base::DeleteFile(base_file, false);
183 220
184 // This fakes the behavior of another open tab with webrtc-internals, and 221 // This fakes the behavior of another open tab with webrtc-internals, and
185 // enabling AEC dump in that tab. 222 // enabling AEC dump in that tab.
186 WebRTCInternals::GetInstance()->FileSelected(dump_file, -1, NULL); 223 WebRTCInternals::GetInstance()->FileSelected(base_file, -1, NULL);
187 224
188 GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html")); 225 GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
189 226
190 NavigateToURL(shell(), url); 227 NavigateToURL(shell(), url);
191 NavigateToURL(shell2, url); 228 NavigateToURL(shell2, url);
192 ExecuteJavascriptAndWaitForOk("call({video: true, audio: true});"); 229 ExecuteJavascriptAndWaitForOk("call({video: true, audio: true});");
193 std::string result; 230 std::string result;
194 EXPECT_TRUE(ExecuteScriptAndExtractString( 231 EXPECT_TRUE(ExecuteScriptAndExtractString(
195 shell2->web_contents(), 232 shell2->web_contents(),
196 "call({video: true, audio: true});", 233 "call({video: true, audio: true});",
197 &result)); 234 &result));
198 ASSERT_STREQ("OK", result.c_str()); 235 ASSERT_STREQ("OK", result.c_str());
199 236
200 EXPECT_FALSE(base::PathExists(dump_file)); 237 EXPECT_FALSE(base::PathExists(base_file));
201 238
202 RenderProcessHost::iterator it = 239 RenderProcessHost::iterator it =
203 content::RenderProcessHost::AllHostsIterator(); 240 content::RenderProcessHost::AllHostsIterator();
241
204 for (; !it.IsAtEnd(); it.Advance()) { 242 for (; !it.IsAtEnd(); it.Advance()) {
205 base::ProcessId render_process_id = 243 base::ProcessId render_process_id =
206 base::GetProcId(it.GetCurrentValue()->GetHandle()); 244 base::GetProcId(it.GetCurrentValue()->GetHandle());
207 EXPECT_NE(base::kNullProcessId, render_process_id); 245 EXPECT_NE(base::kNullProcessId, render_process_id);
208 246
209 // Add file extensions that we expect to be added. 247 // Verify that the expected AEC dump file exists and contains some data.
210 base::FilePath unique_dump_file = 248 base::FilePath aec_dump_file =
211 dump_file.AddExtension(IntToStringType(render_process_id)) 249 GetExpectedAecDumpFileName(base_file, render_process_id);
212 .AddExtension(IntToStringType(kExpectedConsumerId));
213 250
214 EXPECT_TRUE(base::PathExists(unique_dump_file)); 251 EXPECT_TRUE(base::PathExists(aec_dump_file));
215 int64 file_size = 0; 252 int64 file_size = 0;
216 EXPECT_TRUE(base::GetFileSize(unique_dump_file, &file_size)); 253 EXPECT_TRUE(base::GetFileSize(aec_dump_file, &file_size));
217 EXPECT_GT(file_size, 0); 254 EXPECT_GT(file_size, 0);
218 255
219 base::DeleteFile(unique_dump_file, false); 256 base::DeleteFile(aec_dump_file, false);
257
258 // Verify that the expected input audio file exists and contains some data.
259 base::FilePath input_audio_file =
260 GetExpectedInputAudioFileName(base_file, render_process_id);
261
262 EXPECT_TRUE(base::PathExists(input_audio_file));
263 file_size = 0;
264 EXPECT_TRUE(base::GetFileSize(input_audio_file, &file_size));
265 EXPECT_GT(file_size, 0);
266
267 base::DeleteFile(input_audio_file, false);
220 } 268 }
221 } 269 }
222 270
223 } // namespace content 271 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698