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

Side by Side Diff: content/browser/renderer_host/media/audio_input_debug_writer_unittest.cc

Issue 2390153006: Audio input debug recording refactoring to reduce thread hops and simplify object ownership (Closed)
Patch Set: Rebase Created 4 years, 2 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 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 <stdint.h> 5 #include <stdint.h>
6 6
7 #include "base/files/file_util.h" 7 #include "base/files/file_util.h"
8 #include "base/memory/ptr_util.h"
9 #include "base/synchronization/waitable_event.h"
8 #include "base/sys_byteorder.h" 10 #include "base/sys_byteorder.h"
9 #include "content/browser/renderer_host/media/audio_input_debug_writer.h" 11 #include "content/browser/renderer_host/media/audio_input_debug_writer.h"
10 #include "content/public/browser/browser_thread.h" 12 #include "content/public/browser/browser_thread.h"
11 #include "content/public/test/test_browser_thread_bundle.h" 13 #include "content/public/test/test_browser_thread_bundle.h"
12 #include "media/base/audio_bus.h" 14 #include "media/base/audio_bus.h"
13 #include "media/base/test_helpers.h" 15 #include "media/base/test_helpers.h"
14 #include "testing/gtest/include/gtest/gtest.h" 16 #include "testing/gtest/include/gtest/gtest.h"
15 17
16 namespace content { 18 namespace content {
17 19
(...skipping 16 matching lines...) Expand all
34 } // namespace 36 } // namespace
35 37
36 // <channel layout, sample rate, frames per buffer, number of buffer writes 38 // <channel layout, sample rate, frames per buffer, number of buffer writes
37 typedef std::tr1::tuple<media::ChannelLayout, int, int, int> 39 typedef std::tr1::tuple<media::ChannelLayout, int, int, int>
38 AudioInputDebugWriterTestData; 40 AudioInputDebugWriterTestData;
39 41
40 class AudioInputDebugWriterTest 42 class AudioInputDebugWriterTest
41 : public testing::TestWithParam<AudioInputDebugWriterTestData> { 43 : public testing::TestWithParam<AudioInputDebugWriterTestData> {
42 public: 44 public:
43 AudioInputDebugWriterTest() 45 AudioInputDebugWriterTest()
44 : params_(media::AudioParameters::Format::AUDIO_PCM_LINEAR, 46 : thread_bundle_(content::TestBrowserThreadBundle::REAL_FILE_THREAD),
47 params_(media::AudioParameters::Format::AUDIO_PCM_LINEAR,
45 std::tr1::get<0>(GetParam()), 48 std::tr1::get<0>(GetParam()),
46 std::tr1::get<1>(GetParam()), 49 std::tr1::get<1>(GetParam()),
47 kBytesPerSample * 8, 50 kBytesPerSample * 8,
48 std::tr1::get<2>(GetParam())), 51 std::tr1::get<2>(GetParam())),
49 writes_(std::tr1::get<3>(GetParam())), 52 writes_(std::tr1::get<3>(GetParam())),
50 source_samples_(params_.frames_per_buffer() * params_.channels() * 53 source_samples_(params_.frames_per_buffer() * params_.channels() *
51 writes_), 54 writes_),
52 source_interleaved_(source_samples_ ? new int16_t[source_samples_] 55 source_interleaved_(source_samples_ ? new int16_t[source_samples_]
53 : nullptr) { 56 : nullptr) {
54 InitSourceInterleaved(source_interleaved_.get(), source_samples_); 57 InitSourceInterleaved(source_interleaved_.get(), source_samples_);
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 EXPECT_EQ(static_cast<int>(file.GetLength() - kWavHeaderSize), read); 148 EXPECT_EQ(static_cast<int>(file.GetLength() - kWavHeaderSize), read);
146 149
147 VerifyDataRecording(source_interleaved_.get(), result_interleaved.get(), 150 VerifyDataRecording(source_interleaved_.get(), result_interleaved.get(),
148 source_samples_); 151 source_samples_);
149 } 152 }
150 } 153 }
151 154
152 void TestDoneOnFileThread(const base::Closure& callback) { 155 void TestDoneOnFileThread(const base::Closure& callback) {
153 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 156 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
154 157
155 // |writer| must be destroyed on FILE thread.
156 input_debug_writer_.reset(nullptr);
157 callback.Run(); 158 callback.Run();
158 } 159 }
159 160
160 void DoDebugRecording(base::File file) { 161 void DoDebugRecording() {
161 if (!file.IsValid())
162 return;
163
164 input_debug_writer_.reset(
165 new AudioInputDebugWriter(std::move(file), params_));
166 // Write tasks are posted to BrowserThread::FILE. 162 // Write tasks are posted to BrowserThread::FILE.
167 for (int i = 0; i < writes_; ++i) { 163 for (int i = 0; i < writes_; ++i) {
168 std::unique_ptr<media::AudioBus> bus = media::AudioBus::Create( 164 std::unique_ptr<media::AudioBus> bus = media::AudioBus::Create(
169 params_.channels(), params_.frames_per_buffer()); 165 params_.channels(), params_.frames_per_buffer());
170 166
171 bus->FromInterleaved( 167 bus->FromInterleaved(
172 source_interleaved_.get() + 168 source_interleaved_.get() +
173 i * params_.channels() * params_.frames_per_buffer(), 169 i * params_.channels() * params_.frames_per_buffer(),
174 params_.frames_per_buffer(), kBytesPerSample); 170 params_.frames_per_buffer(), kBytesPerSample);
175 171
176 input_debug_writer_->Write(std::move(bus)); 172 input_debug_writer_->Write(std::move(bus));
177 } 173 }
174 }
178 175
176 void WaitForRecordingCompletion() {
179 media::WaitableMessageLoopEvent event; 177 media::WaitableMessageLoopEvent event;
180 178
181 // Post a task to BrowserThread::FILE indicating that all the writes are 179 // Post a task to BrowserThread::FILE indicating that all the writes are
182 // done. 180 // done.
183 BrowserThread::PostTask( 181 BrowserThread::PostTask(
184 BrowserThread::FILE, FROM_HERE, 182 BrowserThread::FILE, FROM_HERE,
185 base::Bind(&AudioInputDebugWriterTest::TestDoneOnFileThread, 183 base::Bind(&AudioInputDebugWriterTest::TestDoneOnFileThread,
186 base::Unretained(this), event.GetClosure())); 184 base::Unretained(this), event.GetClosure()));
187 185
188 // Wait for TestDoneOnFileThread() to call event's closure. 186 // Wait for TestDoneOnFileThread() to call event's closure.
189 event.RunAndWait(); 187 event.RunAndWait();
190 } 188 }
191 189
190 void RecordAndVerifyOnce() {
191 base::FilePath file_path;
192 EXPECT_TRUE(base::CreateTemporaryFile(&file_path));
193
194 input_debug_writer_->Start(file_path);
195
196 DoDebugRecording();
197
198 input_debug_writer_->Stop();
199
200 WaitForRecordingCompletion();
201
202 VerifyRecording(file_path);
203
204 if (::testing::Test::HasFailure()) {
205 LOG(ERROR) << "Test failed; keeping recording(s) at ["
206 << file_path.value().c_str() << "].";
207 } else {
208 EXPECT_TRUE(base::DeleteFile(file_path, false));
209 }
210 }
211
192 protected: 212 protected:
193 TestBrowserThreadBundle thread_bundle_; 213 TestBrowserThreadBundle thread_bundle_;
194 214
195 // Writer under test. 215 // Writer under test.
196 std::unique_ptr<AudioInputDebugWriter> input_debug_writer_; 216 std::unique_ptr<AudioInputDebugWriter> input_debug_writer_;
197 217
198 // AudioBus parameters. 218 // AudioBus parameters.
199 media::AudioParameters params_; 219 media::AudioParameters params_;
200 220
201 // Number of times to write AudioBus to the file. 221 // Number of times to write AudioBus to the file.
202 int writes_; 222 int writes_;
203 223
204 // Number of samples in the source data. 224 // Number of samples in the source data.
205 int source_samples_; 225 int source_samples_;
206 226
207 // Source data. 227 // Source data.
208 std::unique_ptr<int16_t[]> source_interleaved_; 228 std::unique_ptr<int16_t[]> source_interleaved_;
209 229
210 private: 230 private:
211 DISALLOW_COPY_AND_ASSIGN(AudioInputDebugWriterTest); 231 DISALLOW_COPY_AND_ASSIGN(AudioInputDebugWriterTest);
212 }; 232 };
213 233
234 class AudioInputDebugWriterBehavioralTest : public AudioInputDebugWriterTest {};
235
214 TEST_P(AudioInputDebugWriterTest, WaveRecordingTest) { 236 TEST_P(AudioInputDebugWriterTest, WaveRecordingTest) {
237 input_debug_writer_.reset(new AudioInputDebugWriter(params_));
238
239 RecordAndVerifyOnce();
240 }
241
242 TEST_P(AudioInputDebugWriterBehavioralTest,
243 DeletedBeforeRecordingFinishedOnFileThread) {
244 input_debug_writer_.reset(new AudioInputDebugWriter(params_));
245
215 base::FilePath file_path; 246 base::FilePath file_path;
216 EXPECT_TRUE(base::CreateTemporaryFile(&file_path)); 247 EXPECT_TRUE(base::CreateTemporaryFile(&file_path));
217 248
218 base::File file(file_path, 249 base::WaitableEvent* wait_for_deletion =
219 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); 250 new base::WaitableEvent(base::WaitableEvent::ResetPolicy::MANUAL,
220 EXPECT_TRUE(file.IsValid()); 251 base::WaitableEvent::InitialState::NOT_SIGNALED);
221 252
222 DoDebugRecording(std::move(file)); 253 BrowserThread::PostTask(
254 BrowserThread::FILE, FROM_HERE,
255 base::Bind(&base::WaitableEvent::Wait, base::Owned(wait_for_deletion)));
256
257 input_debug_writer_->Start(file_path);
258
259 DoDebugRecording();
260
261 input_debug_writer_.reset();
262 wait_for_deletion->Signal();
263
264 WaitForRecordingCompletion();
223 265
224 VerifyRecording(file_path); 266 VerifyRecording(file_path);
225 267
226 if (::testing::Test::HasFailure()) { 268 if (::testing::Test::HasFailure()) {
227 LOG(ERROR) << "Test failed; keeping recording(s) at [" 269 LOG(ERROR) << "Test failed; keeping recording(s) at ["
228 << file_path.value().c_str() << "]."; 270 << file_path.value().c_str() << "].";
229 } else { 271 } else {
230 EXPECT_TRUE(base::DeleteFile(file_path, false)); 272 EXPECT_TRUE(base::DeleteFile(file_path, false));
231 } 273 }
232 } 274 }
233 275
276 TEST_P(AudioInputDebugWriterBehavioralTest, FileCreationError) {
277 input_debug_writer_.reset(new AudioInputDebugWriter(params_));
278 base::FilePath file_path; // Empty file name.
279 input_debug_writer_->Start(file_path);
280 DoDebugRecording();
281 }
282
283 TEST_P(AudioInputDebugWriterBehavioralTest, StartStopStartStop) {
284 input_debug_writer_.reset(new AudioInputDebugWriter(params_));
285 RecordAndVerifyOnce();
286 RecordAndVerifyOnce();
287 }
288
289 TEST_P(AudioInputDebugWriterBehavioralTest, DestroyNotStarted) {
290 input_debug_writer_.reset(new AudioInputDebugWriter(params_));
291 input_debug_writer_.reset();
292 }
293
294 TEST_P(AudioInputDebugWriterBehavioralTest, DestroyStarted) {
295 input_debug_writer_.reset(new AudioInputDebugWriter(params_));
296 base::FilePath file_path;
297 EXPECT_TRUE(base::CreateTemporaryFile(&file_path));
298 input_debug_writer_->Start(file_path);
299 input_debug_writer_.reset();
300 }
301
234 INSTANTIATE_TEST_CASE_P( 302 INSTANTIATE_TEST_CASE_P(
235 AudioInputDebugWriterTest, 303 AudioInputDebugWriterTest,
236 AudioInputDebugWriterTest, 304 AudioInputDebugWriterTest,
237 // Using 10ms sframes per buffer everywhere. 305 // Using 10ms frames per buffer everywhere.
238 testing::Values( 306 testing::Values(
239 // No writes. 307 // No writes.
240 std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_MONO, 308 std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_MONO,
241 44100, 309 44100,
242 44100 / 100, 310 44100 / 100,
243 0), 311 0),
244 // 1 write of mono. 312 // 1 write of mono.
245 std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_MONO, 313 std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_MONO,
246 44100, 314 44100,
247 44100 / 100, 315 44100 / 100,
(...skipping 12 matching lines...) Expand all
260 std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_STEREO, 328 std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_STEREO,
261 44100, 329 44100,
262 44100 / 100, 330 44100 / 100,
263 100), 331 100),
264 // 15 seconds of stereo, higher rate. 332 // 15 seconds of stereo, higher rate.
265 std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_STEREO, 333 std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_STEREO,
266 48000, 334 48000,
267 48000 / 100, 335 48000 / 100,
268 1500))); 336 1500)));
269 337
338 INSTANTIATE_TEST_CASE_P(
339 AudioInputDebugWriterBehavioralTest,
340 AudioInputDebugWriterBehavioralTest,
341 // Using 10ms frames per buffer everywhere.
342 testing::Values(
343 // No writes.
344 std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_MONO,
345 44100,
346 44100 / 100,
347 100)));
348
270 } // namespace content 349 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698