diff options
| -rw-r--r-- | media/audio/audio_output_controller_unittest.cc | 2 | ||||
| -rw-r--r-- | media/audio/audio_util.cc | 15 | ||||
| -rw-r--r-- | media/audio/audio_util.h | 3 | ||||
| -rw-r--r-- | media/audio/win/audio_manager_win.cc | 5 | ||||
| -rw-r--r-- | media/audio/win/audio_output_win_unittest.cc | 53 |
5 files changed, 54 insertions, 24 deletions
diff --git a/media/audio/audio_output_controller_unittest.cc b/media/audio/audio_output_controller_unittest.cc index f40a9ae..6fe2499 100644 --- a/media/audio/audio_output_controller_unittest.cc +++ b/media/audio/audio_output_controller_unittest.cc @@ -196,7 +196,7 @@ TEST_F(AudioOutputControllerTest, PlayPausePlayClose) { MockAudioOutputControllerSyncReader sync_reader; EXPECT_CALL(sync_reader, UpdatePendingBytes(_)) - .Times(AtLeast(2)); + .Times(AtLeast(1)); EXPECT_CALL(sync_reader, Read(_, kHardwareBufferSize)) .WillRepeatedly(DoAll(SignalEvent(&event), Return(4))); EXPECT_CALL(sync_reader, DataReady()) diff --git a/media/audio/audio_util.cc b/media/audio/audio_util.cc index 23aad0f..4035d28 100644 --- a/media/audio/audio_util.cc +++ b/media/audio/audio_util.cc @@ -21,6 +21,7 @@ #include "base/shared_memory.h" #include "base/time.h" #if defined(OS_WIN) +#include "base/sys_info.h" #include "base/win/windows_version.h" #include "media/audio/audio_manager_base.h" #endif @@ -519,6 +520,20 @@ bool IsWASAPISupported() { return base::win::GetVersion() >= base::win::VERSION_VISTA; } +int NumberOfWaveOutBuffers() { + // Simple heuristic: use 3 buffers on single-core system or on Vista, + // 2 otherwise. + // Entire Windows audio stack was rewritten for Windows Vista, and wave out + // API is simulated on top of new API, so there is noticeable performance + // degradation compared to Windows XP. Part of regression was fixed in + // Windows 7. Maybe it is fixed in Vista Serice Pack, but let's be cautious. + if ((base::SysInfo::NumberOfProcessors() < 2) || + (base::win::GetVersion() == base::win::VERSION_VISTA)) { + return 3; + } + return 2; +} + #endif } // namespace media diff --git a/media/audio/audio_util.h b/media/audio/audio_util.h index df5683f..4ac0ef6 100644 --- a/media/audio/audio_util.h +++ b/media/audio/audio_util.h @@ -132,6 +132,9 @@ MEDIA_EXPORT bool IsUnknownDataSize(base::SharedMemory* shared_memory, // sometimes check was written incorrectly, so move into separate function. MEDIA_EXPORT bool IsWASAPISupported(); +// Returns number of buffers to be used by wave out. +MEDIA_EXPORT int NumberOfWaveOutBuffers(); + #endif // defined(OS_WIN) } // namespace media diff --git a/media/audio/win/audio_manager_win.cc b/media/audio/win/audio_manager_win.cc index 93dcf2f..38c4615 100644 --- a/media/audio/win/audio_manager_win.cc +++ b/media/audio/win/audio_manager_win.cc @@ -244,7 +244,10 @@ AudioOutputStream* AudioManagerWin::MakeLinearOutputStream( if (params.channels() > kWinMaxChannels) return NULL; - return new PCMWaveOutAudioOutputStream(this, params, 3, WAVE_MAPPER); + return new PCMWaveOutAudioOutputStream(this, + params, + media::NumberOfWaveOutBuffers(), + WAVE_MAPPER); } // Factory for the implementations of AudioOutputStream for diff --git a/media/audio/win/audio_output_win_unittest.cc b/media/audio/win/audio_output_win_unittest.cc index 4066643..d954093 100644 --- a/media/audio/win/audio_output_win_unittest.cc +++ b/media/audio/win/audio_output_win_unittest.cc @@ -76,7 +76,7 @@ class TestSourceBasic : public AudioOutputStream::AudioSourceCallback { int had_error_; }; -const int kNumBuffers = 3; +const int kMaxNumBuffers = 3; // Specializes TestSourceBasic to detect that the AudioStream is using // triple buffering correctly. class TestSourceTripleBuffer : public TestSourceBasic { @@ -92,14 +92,14 @@ class TestSourceTripleBuffer : public TestSourceBasic { AudioBuffersState buffers_state) { // Call the base, which increments the callback_count_. TestSourceBasic::OnMoreData(dest, max_size, buffers_state); - if (callback_count() % kNumBuffers == 2) { + if (callback_count() % NumberOfWaveOutBuffers() == 2) { set_error(!CompareExistingIfNotNULL(2, dest)); - } else if (callback_count() % kNumBuffers == 1) { + } else if (callback_count() % NumberOfWaveOutBuffers() == 1) { set_error(!CompareExistingIfNotNULL(1, dest)); } else { set_error(!CompareExistingIfNotNULL(0, dest)); } - if (callback_count() > kNumBuffers) { + if (callback_count() > kMaxNumBuffers) { set_error(buffer_address_[0] == buffer_address_[1]); set_error(buffer_address_[1] == buffer_address_[2]); } @@ -114,7 +114,7 @@ class TestSourceTripleBuffer : public TestSourceBasic { return (entry == address); } - void* buffer_address_[kNumBuffers]; + void* buffer_address_[kMaxNumBuffers]; }; // Specializes TestSourceBasic to simulate a source that blocks for some time @@ -129,7 +129,7 @@ class TestSourceLaggy : public TestSourceBasic { AudioBuffersState buffers_state) { // Call the base, which increments the callback_count_. TestSourceBasic::OnMoreData(dest, max_size, buffers_state); - if (callback_count() > kNumBuffers) { + if (callback_count() > kMaxNumBuffers) { ::Sleep(lag_in_ms_); } return max_size; @@ -312,7 +312,7 @@ TEST(WinAudioTest, PCMWaveStreamTripleBuffer) { EXPECT_TRUE(oas->Open()); oas->Start(&test_triple_buffer); ::Sleep(300); - EXPECT_GT(test_triple_buffer.callback_count(), kNumBuffers); + EXPECT_GT(test_triple_buffer.callback_count(), kMaxNumBuffers); EXPECT_FALSE(test_triple_buffer.had_error()); oas->Stop(); ::Sleep(500); @@ -600,28 +600,37 @@ TEST(WinAudioTest, PCMWaveStreamPendingBytes) { uint32 bytes_100_ms = samples_100_ms * 2; - // We expect the amount of pending bytes will reaching 2 times of - // |bytes_100_ms| because the audio output stream has a triple buffer scheme. + // Audio output stream has either a double or triple buffer scheme. + // We expect the amount of pending bytes will reaching up to 2 times of + // |bytes_100_ms| depending on number of buffers used. // From that it would decrease as we are playing the data but not providing // new one. And then we will try to provide zero data so the amount of // pending bytes will go down and eventually read zero. InSequence s; + EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, Field(&AudioBuffersState::pending_bytes, 0))) .WillOnce(Return(bytes_100_ms)); - EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, - Field(&AudioBuffersState::pending_bytes, - bytes_100_ms))) - .WillOnce(Return(bytes_100_ms)); - EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, - Field(&AudioBuffersState::pending_bytes, - 2 * bytes_100_ms))) - .WillOnce(Return(bytes_100_ms)); - EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, - Field(&AudioBuffersState::pending_bytes, - 2 * bytes_100_ms))) - .Times(AnyNumber()) - .WillRepeatedly(Return(0)); + switch (NumberOfWaveOutBuffers()) { + case 2: + break; // Calls are the same as at end of 3-buffer scheme. + case 3: + EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, + Field(&AudioBuffersState::pending_bytes, + bytes_100_ms))) + .WillOnce(Return(bytes_100_ms)); + EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, + Field(&AudioBuffersState::pending_bytes, + 2 * bytes_100_ms))) + .WillOnce(Return(bytes_100_ms)); + EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, + Field(&AudioBuffersState::pending_bytes, + 2 * bytes_100_ms))) + .Times(AnyNumber()) + .WillRepeatedly(Return(0)); + default: + ASSERT_TRUE(false) << "Unexpected number of buffers"; + } EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, Field(&AudioBuffersState::pending_bytes, bytes_100_ms))) |
