| 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 EXPECT_TRUE(input_debug_writer_->IsRecording()); |
| 195 |
| 196 DoDebugRecording(); |
| 197 |
| 198 input_debug_writer_->Stop(); |
| 199 EXPECT_FALSE(input_debug_writer_->IsRecording()); |
| 200 |
| 201 WaitForRecordingCompletion(); |
| 202 |
| 203 VerifyRecording(file_path); |
| 204 |
| 205 if (::testing::Test::HasFailure()) { |
| 206 LOG(ERROR) << "Test failed; keeping recording(s) at [" |
| 207 << file_path.value().c_str() << "]."; |
| 208 } else { |
| 209 EXPECT_TRUE(base::DeleteFile(file_path, false)); |
| 210 } |
| 211 } |
| 212 |
| 192 protected: | 213 protected: |
| 193 TestBrowserThreadBundle thread_bundle_; | 214 TestBrowserThreadBundle thread_bundle_; |
| 194 | 215 |
| 195 // Writer under test. | 216 // Writer under test. |
| 196 std::unique_ptr<AudioInputDebugWriter> input_debug_writer_; | 217 std::unique_ptr<AudioInputDebugWriter> input_debug_writer_; |
| 197 | 218 |
| 198 // AudioBus parameters. | 219 // AudioBus parameters. |
| 199 media::AudioParameters params_; | 220 media::AudioParameters params_; |
| 200 | 221 |
| 201 // Number of times to write AudioBus to the file. | 222 // Number of times to write AudioBus to the file. |
| 202 int writes_; | 223 int writes_; |
| 203 | 224 |
| 204 // Number of samples in the source data. | 225 // Number of samples in the source data. |
| 205 int source_samples_; | 226 int source_samples_; |
| 206 | 227 |
| 207 // Source data. | 228 // Source data. |
| 208 std::unique_ptr<int16_t[]> source_interleaved_; | 229 std::unique_ptr<int16_t[]> source_interleaved_; |
| 209 | 230 |
| 210 private: | 231 private: |
| 211 DISALLOW_COPY_AND_ASSIGN(AudioInputDebugWriterTest); | 232 DISALLOW_COPY_AND_ASSIGN(AudioInputDebugWriterTest); |
| 212 }; | 233 }; |
| 213 | 234 |
| 235 class AudioInputDebugWriterBehavioralTest : public AudioInputDebugWriterTest {}; |
| 236 |
| 214 TEST_P(AudioInputDebugWriterTest, WaveRecordingTest) { | 237 TEST_P(AudioInputDebugWriterTest, WaveRecordingTest) { |
| 238 input_debug_writer_.reset(new AudioInputDebugWriter(params_)); |
| 239 |
| 240 RecordAndVerifyOnce(); |
| 241 } |
| 242 |
| 243 TEST_P(AudioInputDebugWriterBehavioralTest, |
| 244 DeletedBeforeRecordingFinishedOnFileThread) { |
| 245 input_debug_writer_.reset(new AudioInputDebugWriter(params_)); |
| 246 |
| 215 base::FilePath file_path; | 247 base::FilePath file_path; |
| 216 EXPECT_TRUE(base::CreateTemporaryFile(&file_path)); | 248 EXPECT_TRUE(base::CreateTemporaryFile(&file_path)); |
| 217 | 249 |
| 218 base::File file(file_path, | 250 base::WaitableEvent* wait_for_deletion = |
| 219 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); | 251 new base::WaitableEvent(base::WaitableEvent::ResetPolicy::MANUAL, |
| 220 EXPECT_TRUE(file.IsValid()); | 252 base::WaitableEvent::InitialState::NOT_SIGNALED); |
| 221 | 253 |
| 222 DoDebugRecording(std::move(file)); | 254 BrowserThread::PostTask( |
| 255 BrowserThread::FILE, FROM_HERE, |
| 256 base::Bind(&base::WaitableEvent::Wait, base::Owned(wait_for_deletion))); |
| 257 |
| 258 input_debug_writer_->Start(file_path); |
| 259 EXPECT_TRUE(input_debug_writer_->IsRecording()); |
| 260 |
| 261 DoDebugRecording(); |
| 262 |
| 263 input_debug_writer_.reset(); |
| 264 wait_for_deletion->Signal(); |
| 265 |
| 266 WaitForRecordingCompletion(); |
| 223 | 267 |
| 224 VerifyRecording(file_path); | 268 VerifyRecording(file_path); |
| 225 | 269 |
| 226 if (::testing::Test::HasFailure()) { | 270 if (::testing::Test::HasFailure()) { |
| 227 LOG(ERROR) << "Test failed; keeping recording(s) at [" | 271 LOG(ERROR) << "Test failed; keeping recording(s) at [" |
| 228 << file_path.value().c_str() << "]."; | 272 << file_path.value().c_str() << "]."; |
| 229 } else { | 273 } else { |
| 230 EXPECT_TRUE(base::DeleteFile(file_path, false)); | 274 EXPECT_TRUE(base::DeleteFile(file_path, false)); |
| 231 } | 275 } |
| 232 } | 276 } |
| 233 | 277 |
| 278 TEST_P(AudioInputDebugWriterBehavioralTest, FileCreationError) { |
| 279 input_debug_writer_.reset(new AudioInputDebugWriter(params_)); |
| 280 |
| 281 base::FilePath file_path; // Empty file name. |
| 282 input_debug_writer_->Start(file_path); |
| 283 EXPECT_TRUE(input_debug_writer_->IsRecording()); |
| 284 DoDebugRecording(); |
| 285 } |
| 286 |
| 287 TEST_P(AudioInputDebugWriterBehavioralTest, StartStopStartStop) { |
| 288 input_debug_writer_.reset(new AudioInputDebugWriter(params_)); |
| 289 RecordAndVerifyOnce(); |
| 290 RecordAndVerifyOnce(); |
| 291 } |
| 292 |
| 234 INSTANTIATE_TEST_CASE_P( | 293 INSTANTIATE_TEST_CASE_P( |
| 235 AudioInputDebugWriterTest, | 294 AudioInputDebugWriterTest, |
| 236 AudioInputDebugWriterTest, | 295 AudioInputDebugWriterTest, |
| 237 // Using 10ms sframes per buffer everywhere. | 296 // Using 10ms frames per buffer everywhere. |
| 238 testing::Values( | 297 testing::Values( |
| 239 // No writes. | 298 // No writes. |
| 240 std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_MONO, | 299 std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_MONO, |
| 241 44100, | 300 44100, |
| 242 44100 / 100, | 301 44100 / 100, |
| 243 0), | 302 0), |
| 244 // 1 write of mono. | 303 // 1 write of mono. |
| 245 std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_MONO, | 304 std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_MONO, |
| 246 44100, | 305 44100, |
| 247 44100 / 100, | 306 44100 / 100, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 260 std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_STEREO, | 319 std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_STEREO, |
| 261 44100, | 320 44100, |
| 262 44100 / 100, | 321 44100 / 100, |
| 263 100), | 322 100), |
| 264 // 15 seconds of stereo, higher rate. | 323 // 15 seconds of stereo, higher rate. |
| 265 std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_STEREO, | 324 std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_STEREO, |
| 266 48000, | 325 48000, |
| 267 48000 / 100, | 326 48000 / 100, |
| 268 1500))); | 327 1500))); |
| 269 | 328 |
| 329 INSTANTIATE_TEST_CASE_P( |
| 330 AudioInputDebugWriterBehavioralTest, |
| 331 AudioInputDebugWriterBehavioralTest, |
| 332 // Using 10ms frames per buffer everywhere. |
| 333 testing::Values( |
| 334 // No writes. |
| 335 std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_MONO, |
| 336 44100, |
| 337 44100 / 100, |
| 338 100))); |
| 339 |
| 270 } // namespace content | 340 } // namespace content |
| OLD | NEW |