| OLD | NEW |
| 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" | 8 #include "base/memory/ptr_util.h" |
| 9 #include "base/synchronization/waitable_event.h" | 9 #include "base/synchronization/waitable_event.h" |
| 10 #include "base/sys_byteorder.h" | 10 #include "base/sys_byteorder.h" |
| 11 #include "content/browser/renderer_host/media/audio_debug_file_writer.h" | 11 #include "content/browser/renderer_host/media/audio_debug_file_writer.h" |
| 12 #include "content/public/browser/browser_thread.h" | 12 #include "content/public/browser/browser_thread.h" |
| 13 #include "content/public/test/test_browser_thread_bundle.h" | 13 #include "content/public/test/test_browser_thread_bundle.h" |
| 14 #include "media/base/audio_bus.h" | 14 #include "media/base/audio_bus.h" |
| 15 #include "media/base/audio_sample_types.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 content { |
| 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; |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 | 159 |
| 159 callback.Run(); | 160 callback.Run(); |
| 160 } | 161 } |
| 161 | 162 |
| 162 void DoDebugRecording() { | 163 void DoDebugRecording() { |
| 163 // Write tasks are posted to BrowserThread::FILE. | 164 // Write tasks are posted to BrowserThread::FILE. |
| 164 for (int i = 0; i < writes_; ++i) { | 165 for (int i = 0; i < writes_; ++i) { |
| 165 std::unique_ptr<media::AudioBus> bus = media::AudioBus::Create( | 166 std::unique_ptr<media::AudioBus> bus = media::AudioBus::Create( |
| 166 params_.channels(), params_.frames_per_buffer()); | 167 params_.channels(), params_.frames_per_buffer()); |
| 167 | 168 |
| 168 bus->FromInterleaved( | 169 bus->FromInterleaved<media::SignedInt16SampleTypeTraits>( |
| 169 source_interleaved_.get() + | 170 source_interleaved_.get() + |
| 170 i * params_.channels() * params_.frames_per_buffer(), | 171 i * params_.channels() * params_.frames_per_buffer(), |
| 171 params_.frames_per_buffer(), kBytesPerSample); | 172 params_.frames_per_buffer()); |
| 172 | 173 |
| 173 input_debug_writer_->Write(std::move(bus)); | 174 debug_writer_->Write(std::move(bus)); |
| 174 } | 175 } |
| 175 } | 176 } |
| 176 | 177 |
| 177 void WaitForRecordingCompletion() { | 178 void WaitForRecordingCompletion() { |
| 178 media::WaitableMessageLoopEvent event; | 179 media::WaitableMessageLoopEvent event; |
| 179 | 180 |
| 180 // Post a task to BrowserThread::FILE indicating that all the writes are | 181 // Post a task to BrowserThread::FILE indicating that all the writes are |
| 181 // done. | 182 // done. |
| 182 BrowserThread::PostTask( | 183 BrowserThread::PostTask( |
| 183 BrowserThread::FILE, FROM_HERE, | 184 BrowserThread::FILE, FROM_HERE, |
| 184 base::Bind(&AudioDebugFileWriterTest::TestDoneOnFileThread, | 185 base::Bind(&AudioDebugFileWriterTest::TestDoneOnFileThread, |
| 185 base::Unretained(this), event.GetClosure())); | 186 base::Unretained(this), event.GetClosure())); |
| 186 | 187 |
| 187 // Wait for TestDoneOnFileThread() to call event's closure. | 188 // Wait for TestDoneOnFileThread() to call event's closure. |
| 188 event.RunAndWait(); | 189 event.RunAndWait(); |
| 189 } | 190 } |
| 190 | 191 |
| 191 void RecordAndVerifyOnce() { | 192 void RecordAndVerifyOnce() { |
| 192 base::FilePath file_path; | 193 base::FilePath file_path; |
| 193 EXPECT_TRUE(base::CreateTemporaryFile(&file_path)); | 194 EXPECT_TRUE(base::CreateTemporaryFile(&file_path)); |
| 194 | 195 |
| 195 input_debug_writer_->Start(file_path); | 196 debug_writer_->Start(file_path); |
| 196 | 197 |
| 197 DoDebugRecording(); | 198 DoDebugRecording(); |
| 198 | 199 |
| 199 input_debug_writer_->Stop(); | 200 debug_writer_->Stop(); |
| 200 | 201 |
| 201 WaitForRecordingCompletion(); | 202 WaitForRecordingCompletion(); |
| 202 | 203 |
| 203 VerifyRecording(file_path); | 204 VerifyRecording(file_path); |
| 204 | 205 |
| 205 if (::testing::Test::HasFailure()) { | 206 if (::testing::Test::HasFailure()) { |
| 206 LOG(ERROR) << "Test failed; keeping recording(s) at [" | 207 LOG(ERROR) << "Test failed; keeping recording(s) at [" |
| 207 << file_path.value().c_str() << "]."; | 208 << file_path.value().c_str() << "]."; |
| 208 } else { | 209 } else { |
| 209 EXPECT_TRUE(base::DeleteFile(file_path, false)); | 210 EXPECT_TRUE(base::DeleteFile(file_path, false)); |
| 210 } | 211 } |
| 211 } | 212 } |
| 212 | 213 |
| 213 protected: | 214 protected: |
| 214 TestBrowserThreadBundle thread_bundle_; | 215 TestBrowserThreadBundle thread_bundle_; |
| 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 media::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(new AudioDebugFileWriter(params_)); |
| 240 RecordAndVerifyOnce(); |
| 241 } |
| 239 | 242 |
| 240 RecordAndVerifyOnce(); | 243 TEST_P(AudioDebugFileWriterTest, GetFileNameExtension) { |
| 244 debug_writer_.reset(new AudioDebugFileWriter(params_)); |
| 245 EXPECT_EQ("wav", std::string(debug_writer_->GetFileNameExtension())); |
| 241 } | 246 } |
| 242 | 247 |
| 243 TEST_P(AudioDebugFileWriterBehavioralTest, | 248 TEST_P(AudioDebugFileWriterBehavioralTest, |
| 244 DeletedBeforeRecordingFinishedOnFileThread) { | 249 DeletedBeforeRecordingFinishedOnFileThread) { |
| 245 input_debug_writer_.reset(new AudioDebugFileWriter(params_)); | 250 debug_writer_.reset(new AudioDebugFileWriter(params_)); |
| 246 | 251 |
| 247 base::FilePath file_path; | 252 base::FilePath file_path; |
| 248 EXPECT_TRUE(base::CreateTemporaryFile(&file_path)); | 253 EXPECT_TRUE(base::CreateTemporaryFile(&file_path)); |
| 249 | 254 |
| 250 base::WaitableEvent* wait_for_deletion = | 255 base::WaitableEvent* wait_for_deletion = |
| 251 new base::WaitableEvent(base::WaitableEvent::ResetPolicy::MANUAL, | 256 new base::WaitableEvent(base::WaitableEvent::ResetPolicy::MANUAL, |
| 252 base::WaitableEvent::InitialState::NOT_SIGNALED); | 257 base::WaitableEvent::InitialState::NOT_SIGNALED); |
| 253 | 258 |
| 254 BrowserThread::PostTask( | 259 BrowserThread::PostTask( |
| 255 BrowserThread::FILE, FROM_HERE, | 260 BrowserThread::FILE, FROM_HERE, |
| 256 base::Bind(&base::WaitableEvent::Wait, base::Owned(wait_for_deletion))); | 261 base::Bind(&base::WaitableEvent::Wait, base::Owned(wait_for_deletion))); |
| 257 | 262 |
| 258 input_debug_writer_->Start(file_path); | 263 debug_writer_->Start(file_path); |
| 259 | 264 |
| 260 DoDebugRecording(); | 265 DoDebugRecording(); |
| 261 | 266 |
| 262 input_debug_writer_.reset(); | 267 debug_writer_.reset(); |
| 263 wait_for_deletion->Signal(); | 268 wait_for_deletion->Signal(); |
| 264 | 269 |
| 265 WaitForRecordingCompletion(); | 270 WaitForRecordingCompletion(); |
| 266 | 271 |
| 267 VerifyRecording(file_path); | 272 VerifyRecording(file_path); |
| 268 | 273 |
| 269 if (::testing::Test::HasFailure()) { | 274 if (::testing::Test::HasFailure()) { |
| 270 LOG(ERROR) << "Test failed; keeping recording(s) at [" | 275 LOG(ERROR) << "Test failed; keeping recording(s) at [" |
| 271 << file_path.value().c_str() << "]."; | 276 << file_path.value().c_str() << "]."; |
| 272 } else { | 277 } else { |
| 273 EXPECT_TRUE(base::DeleteFile(file_path, false)); | 278 EXPECT_TRUE(base::DeleteFile(file_path, false)); |
| 274 } | 279 } |
| 275 } | 280 } |
| 276 | 281 |
| 277 TEST_P(AudioDebugFileWriterBehavioralTest, FileCreationError) { | 282 TEST_P(AudioDebugFileWriterBehavioralTest, FileCreationError) { |
| 278 input_debug_writer_.reset(new AudioDebugFileWriter(params_)); | 283 debug_writer_.reset(new AudioDebugFileWriter(params_)); |
| 279 base::FilePath file_path; // Empty file name. | 284 base::FilePath file_path; // Empty file name. |
| 280 input_debug_writer_->Start(file_path); | 285 debug_writer_->Start(file_path); |
| 281 DoDebugRecording(); | 286 DoDebugRecording(); |
| 282 } | 287 } |
| 283 | 288 |
| 284 TEST_P(AudioDebugFileWriterBehavioralTest, StartStopStartStop) { | 289 TEST_P(AudioDebugFileWriterBehavioralTest, StartStopStartStop) { |
| 285 input_debug_writer_.reset(new AudioDebugFileWriter(params_)); | 290 debug_writer_.reset(new AudioDebugFileWriter(params_)); |
| 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(new AudioDebugFileWriter(params_)); |
| 292 input_debug_writer_.reset(); | 297 debug_writer_.reset(); |
| 293 } | 298 } |
| 294 | 299 |
| 295 TEST_P(AudioDebugFileWriterBehavioralTest, DestroyStarted) { | 300 TEST_P(AudioDebugFileWriterBehavioralTest, DestroyStarted) { |
| 296 input_debug_writer_.reset(new AudioDebugFileWriter(params_)); | 301 debug_writer_.reset(new AudioDebugFileWriter(params_)); |
| 297 base::FilePath file_path; | 302 base::FilePath file_path; |
| 298 EXPECT_TRUE(base::CreateTemporaryFile(&file_path)); | 303 EXPECT_TRUE(base::CreateTemporaryFile(&file_path)); |
| 299 input_debug_writer_->Start(file_path); | 304 debug_writer_->Start(file_path); |
| 300 input_debug_writer_.reset(); | 305 debug_writer_.reset(); |
| 301 } | 306 } |
| 302 | 307 |
| 303 INSTANTIATE_TEST_CASE_P( | 308 INSTANTIATE_TEST_CASE_P( |
| 304 AudioDebugFileWriterTest, | 309 AudioDebugFileWriterTest, |
| 305 AudioDebugFileWriterTest, | 310 AudioDebugFileWriterTest, |
| 306 // Using 10ms frames per buffer everywhere. | 311 // Using 10ms frames per buffer everywhere. |
| 307 testing::Values( | 312 testing::Values( |
| 308 // No writes. | 313 // No writes. |
| 309 std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_MONO, | 314 std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_MONO, |
| 310 44100, | 315 44100, |
| (...skipping 30 matching lines...) Expand all Loading... |
| 341 AudioDebugFileWriterBehavioralTest, | 346 AudioDebugFileWriterBehavioralTest, |
| 342 // Using 10ms frames per buffer everywhere. | 347 // Using 10ms frames per buffer everywhere. |
| 343 testing::Values( | 348 testing::Values( |
| 344 // No writes. | 349 // No writes. |
| 345 std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_MONO, | 350 std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_MONO, |
| 346 44100, | 351 44100, |
| 347 44100 / 100, | 352 44100 / 100, |
| 348 100))); | 353 100))); |
| 349 | 354 |
| 350 } // namespace content | 355 } // namespace content |
| OLD | NEW |