| 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" |
| 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 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 EXPECT_EQ(static_cast<int>(file.GetLength() - kWavHeaderSize), read); | 147 EXPECT_EQ(static_cast<int>(file.GetLength() - kWavHeaderSize), read); |
| 146 | 148 |
| 147 VerifyDataRecording(source_interleaved_.get(), result_interleaved.get(), | 149 VerifyDataRecording(source_interleaved_.get(), result_interleaved.get(), |
| 148 source_samples_); | 150 source_samples_); |
| 149 } | 151 } |
| 150 } | 152 } |
| 151 | 153 |
| 152 void TestDoneOnFileThread(const base::Closure& callback) { | 154 void TestDoneOnFileThread(const base::Closure& callback) { |
| 153 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 155 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 154 | 156 |
| 155 // |writer| must be destroyed on FILE thread. | |
| 156 input_debug_writer_.reset(nullptr); | |
| 157 callback.Run(); | 157 callback.Run(); |
| 158 } | 158 } |
| 159 | 159 |
| 160 void DoDebugRecording(base::File file) { | 160 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. | 161 // Write tasks are posted to BrowserThread::FILE. |
| 167 for (int i = 0; i < writes_; ++i) { | 162 for (int i = 0; i < writes_; ++i) { |
| 168 std::unique_ptr<media::AudioBus> bus = media::AudioBus::Create( | 163 std::unique_ptr<media::AudioBus> bus = media::AudioBus::Create( |
| 169 params_.channels(), params_.frames_per_buffer()); | 164 params_.channels(), params_.frames_per_buffer()); |
| 170 | 165 |
| 171 bus->FromInterleaved( | 166 bus->FromInterleaved( |
| 172 source_interleaved_.get() + | 167 source_interleaved_.get() + |
| 173 i * params_.channels() * params_.frames_per_buffer(), | 168 i * params_.channels() * params_.frames_per_buffer(), |
| 174 params_.frames_per_buffer(), kBytesPerSample); | 169 params_.frames_per_buffer(), kBytesPerSample); |
| 175 | 170 |
| 176 input_debug_writer_->Write(std::move(bus)); | 171 input_debug_writer_->Write(std::move(bus)); |
| 177 } | 172 } |
| 173 } |
| 178 | 174 |
| 175 void WaitForRecordingCompletion() { |
| 179 media::WaitableMessageLoopEvent event; | 176 media::WaitableMessageLoopEvent event; |
| 180 | 177 |
| 181 // Post a task to BrowserThread::FILE indicating that all the writes are | 178 // Post a task to BrowserThread::FILE indicating that all the writes are |
| 182 // done. | 179 // done. |
| 183 BrowserThread::PostTask( | 180 BrowserThread::PostTask( |
| 184 BrowserThread::FILE, FROM_HERE, | 181 BrowserThread::FILE, FROM_HERE, |
| 185 base::Bind(&AudioInputDebugWriterTest::TestDoneOnFileThread, | 182 base::Bind(&AudioInputDebugWriterTest::TestDoneOnFileThread, |
| 186 base::Unretained(this), event.GetClosure())); | 183 base::Unretained(this), event.GetClosure())); |
| 187 | 184 |
| 188 // Wait for TestDoneOnFileThread() to call event's closure. | 185 // Wait for TestDoneOnFileThread() to call event's closure. |
| 189 event.RunAndWait(); | 186 event.RunAndWait(); |
| 190 } | 187 } |
| 191 | 188 |
| 189 void RecordAndVerifyOnce() { |
| 190 base::FilePath file_path; |
| 191 EXPECT_TRUE(base::CreateTemporaryFile(&file_path)); |
| 192 |
| 193 input_debug_writer_->Start(file_path); |
| 194 |
| 195 DoDebugRecording(); |
| 196 |
| 197 input_debug_writer_->Stop(); |
| 198 |
| 199 WaitForRecordingCompletion(); |
| 200 |
| 201 VerifyRecording(file_path); |
| 202 |
| 203 if (::testing::Test::HasFailure()) { |
| 204 LOG(ERROR) << "Test failed; keeping recording(s) at [" |
| 205 << file_path.value().c_str() << "]."; |
| 206 } else { |
| 207 EXPECT_TRUE(base::DeleteFile(file_path, false)); |
| 208 } |
| 209 } |
| 210 |
| 192 protected: | 211 protected: |
| 193 TestBrowserThreadBundle thread_bundle_; | 212 TestBrowserThreadBundle thread_bundle_; |
| 194 | 213 |
| 195 // Writer under test. | 214 // Writer under test. |
| 196 std::unique_ptr<AudioInputDebugWriter> input_debug_writer_; | 215 std::unique_ptr<AudioInputDebugWriter> input_debug_writer_; |
| 197 | 216 |
| 198 // AudioBus parameters. | 217 // AudioBus parameters. |
| 199 media::AudioParameters params_; | 218 media::AudioParameters params_; |
| 200 | 219 |
| 201 // Number of times to write AudioBus to the file. | 220 // Number of times to write AudioBus to the file. |
| 202 int writes_; | 221 int writes_; |
| 203 | 222 |
| 204 // Number of samples in the source data. | 223 // Number of samples in the source data. |
| 205 int source_samples_; | 224 int source_samples_; |
| 206 | 225 |
| 207 // Source data. | 226 // Source data. |
| 208 std::unique_ptr<int16_t[]> source_interleaved_; | 227 std::unique_ptr<int16_t[]> source_interleaved_; |
| 209 | 228 |
| 210 private: | 229 private: |
| 211 DISALLOW_COPY_AND_ASSIGN(AudioInputDebugWriterTest); | 230 DISALLOW_COPY_AND_ASSIGN(AudioInputDebugWriterTest); |
| 212 }; | 231 }; |
| 213 | 232 |
| 233 class AudioInputDebugWriterBehavioralTest : public AudioInputDebugWriterTest {}; |
| 234 |
| 214 TEST_P(AudioInputDebugWriterTest, WaveRecordingTest) { | 235 TEST_P(AudioInputDebugWriterTest, WaveRecordingTest) { |
| 236 input_debug_writer_.reset(new AudioInputDebugWriter(params_)); |
| 237 |
| 238 RecordAndVerifyOnce(); |
| 239 } |
| 240 |
| 241 TEST_P(AudioInputDebugWriterBehavioralTest, |
| 242 DeletedBeforeRecordingFinishedOnFileThread) { |
| 243 input_debug_writer_.reset(new AudioInputDebugWriter(params_)); |
| 244 |
| 215 base::FilePath file_path; | 245 base::FilePath file_path; |
| 216 EXPECT_TRUE(base::CreateTemporaryFile(&file_path)); | 246 EXPECT_TRUE(base::CreateTemporaryFile(&file_path)); |
| 217 | 247 |
| 218 base::File file(file_path, | 248 base::WaitableEvent* wait_for_deletion = |
| 219 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); | 249 new base::WaitableEvent(base::WaitableEvent::ResetPolicy::MANUAL, |
| 220 EXPECT_TRUE(file.IsValid()); | 250 base::WaitableEvent::InitialState::NOT_SIGNALED); |
| 221 | 251 |
| 222 DoDebugRecording(std::move(file)); | 252 BrowserThread::PostTask( |
| 253 BrowserThread::FILE, FROM_HERE, |
| 254 base::Bind(&base::WaitableEvent::Wait, base::Owned(wait_for_deletion))); |
| 255 |
| 256 input_debug_writer_->Start(file_path); |
| 257 |
| 258 DoDebugRecording(); |
| 259 |
| 260 input_debug_writer_.reset(); |
| 261 wait_for_deletion->Signal(); |
| 262 |
| 263 WaitForRecordingCompletion(); |
| 223 | 264 |
| 224 VerifyRecording(file_path); | 265 VerifyRecording(file_path); |
| 225 | 266 |
| 226 if (::testing::Test::HasFailure()) { | 267 if (::testing::Test::HasFailure()) { |
| 227 LOG(ERROR) << "Test failed; keeping recording(s) at [" | 268 LOG(ERROR) << "Test failed; keeping recording(s) at [" |
| 228 << file_path.value().c_str() << "]."; | 269 << file_path.value().c_str() << "]."; |
| 229 } else { | 270 } else { |
| 230 EXPECT_TRUE(base::DeleteFile(file_path, false)); | 271 EXPECT_TRUE(base::DeleteFile(file_path, false)); |
| 231 } | 272 } |
| 232 } | 273 } |
| 233 | 274 |
| 275 TEST_P(AudioInputDebugWriterBehavioralTest, FileCreationError) { |
| 276 input_debug_writer_.reset(new AudioInputDebugWriter(params_)); |
| 277 |
| 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 Loading... |
| 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 |
| OLD | NEW |