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

Side by Side Diff: media/audio/audio_debug_file_writer_unittest.cc

Issue 2702323002: Move AudioDebugFileWriter from content/ to media/. (Closed)
Patch Set: Code review. Created 3 years, 10 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/bind.h"
7 #include "base/files/file_util.h" 8 #include "base/files/file_util.h"
8 #include "base/memory/ptr_util.h" 9 #include "base/memory/ptr_util.h"
10 #include "base/message_loop/message_loop.h"
9 #include "base/synchronization/waitable_event.h" 11 #include "base/synchronization/waitable_event.h"
10 #include "base/sys_byteorder.h" 12 #include "base/sys_byteorder.h"
11 #include "content/browser/renderer_host/media/audio_debug_file_writer.h" 13 #include "base/threading/thread.h"
12 #include "content/public/browser/browser_thread.h" 14 #include "media/audio/audio_debug_file_writer.h"
13 #include "content/public/test/test_browser_thread_bundle.h"
14 #include "media/base/audio_bus.h" 15 #include "media/base/audio_bus.h"
15 #include "media/base/test_helpers.h" 16 #include "media/base/test_helpers.h"
16 #include "testing/gtest/include/gtest/gtest.h" 17 #include "testing/gtest/include/gtest/gtest.h"
17 18
18 namespace content { 19 namespace media {
19 20
20 namespace { 21 namespace {
21 22
22 static const uint16_t kBytesPerSample = sizeof(uint16_t); 23 static const uint16_t kBytesPerSample = sizeof(uint16_t);
23 static const uint16_t kPcmEncoding = 1; 24 static const uint16_t kPcmEncoding = 1;
24 static const size_t kWavHeaderSize = 44; 25 static const size_t kWavHeaderSize = 44;
25 26
26 uint16_t ReadLE2(const char* buf) { 27 uint16_t ReadLE2(const char* buf) {
27 return static_cast<uint8_t>(buf[0]) | (static_cast<uint8_t>(buf[1]) << 8); 28 return static_cast<uint8_t>(buf[0]) | (static_cast<uint8_t>(buf[1]) << 8);
28 } 29 }
29 30
30 uint32_t ReadLE4(const char* buf) { 31 uint32_t ReadLE4(const char* buf) {
31 return static_cast<uint8_t>(buf[0]) | (static_cast<uint8_t>(buf[1]) << 8) | 32 return static_cast<uint8_t>(buf[0]) | (static_cast<uint8_t>(buf[1]) << 8) |
32 (static_cast<uint8_t>(buf[2]) << 16) | 33 (static_cast<uint8_t>(buf[2]) << 16) |
33 (static_cast<uint8_t>(buf[3]) << 24); 34 (static_cast<uint8_t>(buf[3]) << 24);
34 } 35 }
35 36
36 } // namespace 37 } // namespace
37 38
38 // <channel layout, sample rate, frames per buffer, number of buffer writes 39 // <channel layout, sample rate, frames per buffer, number of buffer writes
39 typedef std::tr1::tuple<media::ChannelLayout, int, int, int> 40 typedef std::tr1::tuple<ChannelLayout, int, int, int>
40 AudioDebugFileWriterTestData; 41 AudioDebugFileWriterTestData;
41 42
42 class AudioDebugFileWriterTest 43 class AudioDebugFileWriterTest
43 : public testing::TestWithParam<AudioDebugFileWriterTestData> { 44 : public testing::TestWithParam<AudioDebugFileWriterTestData> {
44 public: 45 public:
45 AudioDebugFileWriterTest() 46 AudioDebugFileWriterTest()
46 : thread_bundle_(content::TestBrowserThreadBundle::REAL_FILE_THREAD), 47 : file_thread_("FileThread"),
47 params_(media::AudioParameters::Format::AUDIO_PCM_LINEAR, 48 params_(AudioParameters::Format::AUDIO_PCM_LINEAR,
48 std::tr1::get<0>(GetParam()), 49 std::tr1::get<0>(GetParam()),
49 std::tr1::get<1>(GetParam()), 50 std::tr1::get<1>(GetParam()),
50 kBytesPerSample * 8, 51 kBytesPerSample * 8,
51 std::tr1::get<2>(GetParam())), 52 std::tr1::get<2>(GetParam())),
52 writes_(std::tr1::get<3>(GetParam())), 53 writes_(std::tr1::get<3>(GetParam())),
53 source_samples_(params_.frames_per_buffer() * params_.channels() * 54 source_samples_(params_.frames_per_buffer() * params_.channels() *
54 writes_), 55 writes_),
55 source_interleaved_(source_samples_ ? new int16_t[source_samples_] 56 source_interleaved_(source_samples_ ? new int16_t[source_samples_]
56 : nullptr) { 57 : nullptr) {
58 file_thread_.StartAndWaitForTesting();
57 InitSourceInterleaved(source_interleaved_.get(), source_samples_); 59 InitSourceInterleaved(source_interleaved_.get(), source_samples_);
58 } 60 }
59 61
60 protected: 62 protected:
61 virtual ~AudioDebugFileWriterTest() {} 63 virtual ~AudioDebugFileWriterTest() { file_thread_.Stop(); }
62 64
63 static void InitSourceInterleaved(int16_t* source_interleaved, 65 static void InitSourceInterleaved(int16_t* source_interleaved,
64 int source_samples) { 66 int source_samples) {
65 if (source_samples) { 67 if (source_samples) {
66 // equal steps to cover int16_t range of values 68 // equal steps to cover int16_t range of values
67 int16_t step = 0xffff / source_samples; 69 int16_t step = 0xffff / source_samples;
68 int16_t val = std::numeric_limits<int16_t>::min(); 70 int16_t val = std::numeric_limits<int16_t>::min();
69 for (int i = 0; i < source_samples; ++i, val += step) 71 for (int i = 0; i < source_samples; ++i, val += step)
70 source_interleaved[i] = val; 72 source_interleaved[i] = val;
71 } 73 }
72 } 74 }
73 75
74 static void VerifyHeader(const char(&wav_header)[kWavHeaderSize], 76 static void VerifyHeader(const char (&wav_header)[kWavHeaderSize],
75 const media::AudioParameters& params, 77 const AudioParameters& params,
76 int writes, 78 int writes,
77 int64_t file_length) { 79 int64_t file_length) {
78 uint32_t block_align = params.channels() * kBytesPerSample; 80 uint32_t block_align = params.channels() * kBytesPerSample;
79 uint32_t data_size = 81 uint32_t data_size =
80 static_cast<uint32_t>(params.frames_per_buffer() * params.channels() * 82 static_cast<uint32_t>(params.frames_per_buffer() * params.channels() *
81 writes * kBytesPerSample); 83 writes * kBytesPerSample);
82 // Offset Length Content 84 // Offset Length Content
83 // 0 4 "RIFF" 85 // 0 4 "RIFF"
84 EXPECT_EQ(0, strncmp(wav_header, "RIFF", 4)); 86 EXPECT_EQ(0, strncmp(wav_header, "RIFF", 4));
85 // 4 4 <file length - 8> 87 // 4 4 <file length - 8>
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 reinterpret_cast<char*>(result_interleaved.get()), 149 reinterpret_cast<char*>(result_interleaved.get()),
148 source_samples_ * kBytesPerSample); 150 source_samples_ * kBytesPerSample);
149 EXPECT_EQ(static_cast<int>(file.GetLength() - kWavHeaderSize), read); 151 EXPECT_EQ(static_cast<int>(file.GetLength() - kWavHeaderSize), read);
150 152
151 VerifyDataRecording(source_interleaved_.get(), result_interleaved.get(), 153 VerifyDataRecording(source_interleaved_.get(), result_interleaved.get(),
152 source_samples_); 154 source_samples_);
153 } 155 }
154 } 156 }
155 157
156 void TestDoneOnFileThread(const base::Closure& callback) { 158 void TestDoneOnFileThread(const base::Closure& callback) {
157 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 159 DCHECK(file_thread_.task_runner()->BelongsToCurrentThread());
158 160
159 callback.Run(); 161 callback.Run();
160 } 162 }
161 163
162 void DoDebugRecording() { 164 void DoDebugRecording() {
163 // Write tasks are posted to BrowserThread::FILE. 165 // Write tasks are posted to BrowserThread::FILE.
164 for (int i = 0; i < writes_; ++i) { 166 for (int i = 0; i < writes_; ++i) {
165 std::unique_ptr<media::AudioBus> bus = media::AudioBus::Create( 167 std::unique_ptr<AudioBus> bus =
166 params_.channels(), params_.frames_per_buffer()); 168 AudioBus::Create(params_.channels(), params_.frames_per_buffer());
167 169
168 bus->FromInterleaved( 170 bus->FromInterleaved(
169 source_interleaved_.get() + 171 source_interleaved_.get() +
170 i * params_.channels() * params_.frames_per_buffer(), 172 i * params_.channels() * params_.frames_per_buffer(),
171 params_.frames_per_buffer(), kBytesPerSample); 173 params_.frames_per_buffer(), kBytesPerSample);
172 174
173 input_debug_writer_->Write(std::move(bus)); 175 debug_writer_->Write(std::move(bus));
174 } 176 }
175 } 177 }
176 178
177 void WaitForRecordingCompletion() { 179 void WaitForRecordingCompletion() {
178 media::WaitableMessageLoopEvent event; 180 WaitableMessageLoopEvent event;
179 181
180 // Post a task to BrowserThread::FILE indicating that all the writes are 182 // Post a task to the file thread indicating that all the writes are done.
181 // done. 183 file_thread_.task_runner()->PostTask(
182 BrowserThread::PostTask( 184 FROM_HERE, base::Bind(&AudioDebugFileWriterTest::TestDoneOnFileThread,
183 BrowserThread::FILE, FROM_HERE, 185 base::Unretained(this), event.GetClosure()));
184 base::Bind(&AudioDebugFileWriterTest::TestDoneOnFileThread,
185 base::Unretained(this), event.GetClosure()));
186 186
187 // Wait for TestDoneOnFileThread() to call event's closure. 187 // Wait for TestDoneOnFileThread() to call event's closure.
188 event.RunAndWait(); 188 event.RunAndWait();
189 } 189 }
190 190
191 void RecordAndVerifyOnce() { 191 void RecordAndVerifyOnce() {
192 base::FilePath file_path; 192 base::FilePath file_path;
193 EXPECT_TRUE(base::CreateTemporaryFile(&file_path)); 193 EXPECT_TRUE(base::CreateTemporaryFile(&file_path));
194 194
195 input_debug_writer_->Start(file_path); 195 debug_writer_->Start(file_path);
196 196
197 DoDebugRecording(); 197 DoDebugRecording();
198 198
199 input_debug_writer_->Stop(); 199 debug_writer_->Stop();
200 200
201 WaitForRecordingCompletion(); 201 WaitForRecordingCompletion();
202 202
203 VerifyRecording(file_path); 203 VerifyRecording(file_path);
204 204
205 if (::testing::Test::HasFailure()) { 205 if (::testing::Test::HasFailure()) {
206 LOG(ERROR) << "Test failed; keeping recording(s) at [" 206 LOG(ERROR) << "Test failed; keeping recording(s) at ["
207 << file_path.value().c_str() << "]."; 207 << file_path.value().c_str() << "].";
208 } else { 208 } else {
209 EXPECT_TRUE(base::DeleteFile(file_path, false)); 209 EXPECT_TRUE(base::DeleteFile(file_path, false));
210 } 210 }
211 } 211 }
212 212
213 protected: 213 protected:
214 TestBrowserThreadBundle thread_bundle_; 214 base::Thread file_thread_;
215 base::MessageLoop message_loop_;
215 216
216 // Writer under test. 217 // Writer under test.
217 std::unique_ptr<AudioDebugFileWriter> input_debug_writer_; 218 std::unique_ptr<AudioDebugFileWriter> debug_writer_;
218 219
219 // AudioBus parameters. 220 // AudioBus parameters.
220 media::AudioParameters params_; 221 AudioParameters params_;
221 222
222 // Number of times to write AudioBus to the file. 223 // Number of times to write AudioBus to the file.
223 int writes_; 224 int writes_;
224 225
225 // Number of samples in the source data. 226 // Number of samples in the source data.
226 int source_samples_; 227 int source_samples_;
227 228
228 // Source data. 229 // Source data.
229 std::unique_ptr<int16_t[]> source_interleaved_; 230 std::unique_ptr<int16_t[]> source_interleaved_;
230 231
231 private: 232 private:
232 DISALLOW_COPY_AND_ASSIGN(AudioDebugFileWriterTest); 233 DISALLOW_COPY_AND_ASSIGN(AudioDebugFileWriterTest);
233 }; 234 };
234 235
235 class AudioDebugFileWriterBehavioralTest : public AudioDebugFileWriterTest {}; 236 class AudioDebugFileWriterBehavioralTest : public AudioDebugFileWriterTest {};
236 237
237 TEST_P(AudioDebugFileWriterTest, WaveRecordingTest) { 238 TEST_P(AudioDebugFileWriterTest, WaveRecordingTest) {
238 input_debug_writer_.reset(new AudioDebugFileWriter(params_)); 239 debug_writer_.reset(
240 new AudioDebugFileWriter(params_, file_thread_.task_runner()));
239 241
240 RecordAndVerifyOnce(); 242 RecordAndVerifyOnce();
241 } 243 }
242 244
243 TEST_P(AudioDebugFileWriterBehavioralTest, 245 TEST_P(AudioDebugFileWriterBehavioralTest,
244 DeletedBeforeRecordingFinishedOnFileThread) { 246 DeletedBeforeRecordingFinishedOnFileThread) {
245 input_debug_writer_.reset(new AudioDebugFileWriter(params_)); 247 debug_writer_.reset(
248 new AudioDebugFileWriter(params_, file_thread_.task_runner()));
246 249
247 base::FilePath file_path; 250 base::FilePath file_path;
248 EXPECT_TRUE(base::CreateTemporaryFile(&file_path)); 251 EXPECT_TRUE(base::CreateTemporaryFile(&file_path));
249 252
250 base::WaitableEvent* wait_for_deletion = 253 base::WaitableEvent* wait_for_deletion =
251 new base::WaitableEvent(base::WaitableEvent::ResetPolicy::MANUAL, 254 new base::WaitableEvent(base::WaitableEvent::ResetPolicy::MANUAL,
252 base::WaitableEvent::InitialState::NOT_SIGNALED); 255 base::WaitableEvent::InitialState::NOT_SIGNALED);
253 256
254 BrowserThread::PostTask( 257 file_thread_.task_runner()->PostTask(
255 BrowserThread::FILE, FROM_HERE, 258 FROM_HERE,
256 base::Bind(&base::WaitableEvent::Wait, base::Owned(wait_for_deletion))); 259 base::Bind(&base::WaitableEvent::Wait, base::Owned(wait_for_deletion)));
257 260
258 input_debug_writer_->Start(file_path); 261 debug_writer_->Start(file_path);
259 262
260 DoDebugRecording(); 263 DoDebugRecording();
261 264
262 input_debug_writer_.reset(); 265 debug_writer_.reset();
263 wait_for_deletion->Signal(); 266 wait_for_deletion->Signal();
264 267
265 WaitForRecordingCompletion(); 268 WaitForRecordingCompletion();
266 269
267 VerifyRecording(file_path); 270 VerifyRecording(file_path);
268 271
269 if (::testing::Test::HasFailure()) { 272 if (::testing::Test::HasFailure()) {
270 LOG(ERROR) << "Test failed; keeping recording(s) at [" 273 LOG(ERROR) << "Test failed; keeping recording(s) at ["
271 << file_path.value().c_str() << "]."; 274 << file_path.value().c_str() << "].";
272 } else { 275 } else {
273 EXPECT_TRUE(base::DeleteFile(file_path, false)); 276 EXPECT_TRUE(base::DeleteFile(file_path, false));
274 } 277 }
275 } 278 }
276 279
277 TEST_P(AudioDebugFileWriterBehavioralTest, FileCreationError) { 280 TEST_P(AudioDebugFileWriterBehavioralTest, FileCreationError) {
278 input_debug_writer_.reset(new AudioDebugFileWriter(params_)); 281 debug_writer_.reset(
282 new AudioDebugFileWriter(params_, file_thread_.task_runner()));
279 base::FilePath file_path; // Empty file name. 283 base::FilePath file_path; // Empty file name.
280 input_debug_writer_->Start(file_path); 284 debug_writer_->Start(file_path);
281 DoDebugRecording(); 285 DoDebugRecording();
282 } 286 }
283 287
284 TEST_P(AudioDebugFileWriterBehavioralTest, StartStopStartStop) { 288 TEST_P(AudioDebugFileWriterBehavioralTest, StartStopStartStop) {
285 input_debug_writer_.reset(new AudioDebugFileWriter(params_)); 289 debug_writer_.reset(
290 new AudioDebugFileWriter(params_, file_thread_.task_runner()));
286 RecordAndVerifyOnce(); 291 RecordAndVerifyOnce();
287 RecordAndVerifyOnce(); 292 RecordAndVerifyOnce();
288 } 293 }
289 294
290 TEST_P(AudioDebugFileWriterBehavioralTest, DestroyNotStarted) { 295 TEST_P(AudioDebugFileWriterBehavioralTest, DestroyNotStarted) {
291 input_debug_writer_.reset(new AudioDebugFileWriter(params_)); 296 debug_writer_.reset(
292 input_debug_writer_.reset(); 297 new AudioDebugFileWriter(params_, file_thread_.task_runner()));
298 debug_writer_.reset();
293 } 299 }
294 300
295 TEST_P(AudioDebugFileWriterBehavioralTest, DestroyStarted) { 301 TEST_P(AudioDebugFileWriterBehavioralTest, DestroyStarted) {
296 input_debug_writer_.reset(new AudioDebugFileWriter(params_)); 302 debug_writer_.reset(
303 new AudioDebugFileWriter(params_, file_thread_.task_runner()));
297 base::FilePath file_path; 304 base::FilePath file_path;
298 EXPECT_TRUE(base::CreateTemporaryFile(&file_path)); 305 EXPECT_TRUE(base::CreateTemporaryFile(&file_path));
299 input_debug_writer_->Start(file_path); 306 debug_writer_->Start(file_path);
300 input_debug_writer_.reset(); 307 debug_writer_.reset();
301 } 308 }
302 309
303 INSTANTIATE_TEST_CASE_P( 310 INSTANTIATE_TEST_CASE_P(
304 AudioDebugFileWriterTest, 311 AudioDebugFileWriterTest,
305 AudioDebugFileWriterTest, 312 AudioDebugFileWriterTest,
306 // Using 10ms frames per buffer everywhere. 313 // Using 10ms frames per buffer everywhere.
307 testing::Values( 314 testing::Values(
308 // No writes. 315 // No writes.
309 std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_MONO, 316 std::tr1::make_tuple(ChannelLayout::CHANNEL_LAYOUT_MONO,
310 44100, 317 44100,
311 44100 / 100, 318 44100 / 100,
312 0), 319 0),
313 // 1 write of mono. 320 // 1 write of mono.
314 std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_MONO, 321 std::tr1::make_tuple(ChannelLayout::CHANNEL_LAYOUT_MONO,
315 44100, 322 44100,
316 44100 / 100, 323 44100 / 100,
317 1), 324 1),
318 // 1 second of mono. 325 // 1 second of mono.
319 std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_MONO, 326 std::tr1::make_tuple(ChannelLayout::CHANNEL_LAYOUT_MONO,
320 44100, 327 44100,
321 44100 / 100, 328 44100 / 100,
322 100), 329 100),
323 // 1 second of mono, higher rate. 330 // 1 second of mono, higher rate.
324 std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_MONO, 331 std::tr1::make_tuple(ChannelLayout::CHANNEL_LAYOUT_MONO,
325 48000, 332 48000,
326 48000 / 100, 333 48000 / 100,
327 100), 334 100),
328 // 1 second of stereo. 335 // 1 second of stereo.
329 std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_STEREO, 336 std::tr1::make_tuple(ChannelLayout::CHANNEL_LAYOUT_STEREO,
330 44100, 337 44100,
331 44100 / 100, 338 44100 / 100,
332 100), 339 100),
333 // 15 seconds of stereo, higher rate. 340 // 15 seconds of stereo, higher rate.
334 std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_STEREO, 341 std::tr1::make_tuple(ChannelLayout::CHANNEL_LAYOUT_STEREO,
335 48000, 342 48000,
336 48000 / 100, 343 48000 / 100,
337 1500))); 344 1500)));
338 345
339 INSTANTIATE_TEST_CASE_P( 346 INSTANTIATE_TEST_CASE_P(
340 AudioDebugFileWriterBehavioralTest, 347 AudioDebugFileWriterBehavioralTest,
341 AudioDebugFileWriterBehavioralTest, 348 AudioDebugFileWriterBehavioralTest,
342 // Using 10ms frames per buffer everywhere. 349 // Using 10ms frames per buffer everywhere.
343 testing::Values( 350 testing::Values(
344 // No writes. 351 // No writes.
345 std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_MONO, 352 std::tr1::make_tuple(ChannelLayout::CHANNEL_LAYOUT_MONO,
346 44100, 353 44100,
347 44100 / 100, 354 44100 / 100,
348 100))); 355 100)));
349 356
350 } // namespace content 357 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698