diff options
-rw-r--r-- | media/audio/audio_output_controller_unittest.cc | 2 | ||||
-rw-r--r-- | media/audio/audio_output_mixer.cc | 50 | ||||
-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 |
6 files changed, 58 insertions, 70 deletions
diff --git a/media/audio/audio_output_controller_unittest.cc b/media/audio/audio_output_controller_unittest.cc index 6fe2499..f40a9ae 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(1)); + .Times(AtLeast(2)); EXPECT_CALL(sync_reader, Read(_, kHardwareBufferSize)) .WillRepeatedly(DoAll(SignalEvent(&event), Return(4))); EXPECT_CALL(sync_reader, DataReady()) diff --git a/media/audio/audio_output_mixer.cc b/media/audio/audio_output_mixer.cc index 542db78..edce4ea 100644 --- a/media/audio/audio_output_mixer.cc +++ b/media/audio/audio_output_mixer.cc @@ -47,8 +47,6 @@ bool AudioOutputMixer::OpenStream() { } pending_bytes_ = 0; // Just in case. physical_stream_.reset(stream); - physical_stream_->SetVolume(1.0); - physical_stream_->Start(this); close_timer_.Reset(); return true; } @@ -66,24 +64,46 @@ bool AudioOutputMixer::StartStream( double volume = 0.0; stream_proxy->GetVolume(&volume); - - base::AutoLock lock(lock_); - ProxyData* proxy_data = &proxies_[stream_proxy]; - proxy_data->audio_source_callback = callback; - proxy_data->volume = volume; - proxy_data->pending_bytes = 0; + bool should_start = proxies_.empty(); + { + base::AutoLock lock(lock_); + ProxyData* proxy_data = &proxies_[stream_proxy]; + proxy_data->audio_source_callback = callback; + proxy_data->volume = volume; + proxy_data->pending_bytes = 0; + } + // We cannot start physical stream under the lock, + // OnMoreData() would try acquiring it... + if (should_start) { + physical_stream_->SetVolume(1.0); + physical_stream_->Start(this); + } return true; } void AudioOutputMixer::StopStream(AudioOutputProxy* stream_proxy) { DCHECK_EQ(MessageLoop::current(), message_loop_); - base::AutoLock lock(lock_); - ProxyMap::iterator it = proxies_.find(stream_proxy); - if (it != proxies_.end()) - proxies_.erase(it); - if (physical_stream_.get()) + // Because of possible deadlock we cannot stop physical stream under the lock + // (physical_stream_->Stop() can call OnError(), and it acquires the lock to + // iterate through proxies), so acquire the lock, update proxy list, release + // the lock, and only then stop physical stream if necessary. + bool stop_physical_stream = false; + { + base::AutoLock lock(lock_); + ProxyMap::iterator it = proxies_.find(stream_proxy); + if (it != proxies_.end()) { + proxies_.erase(it); + stop_physical_stream = proxies_.empty(); + } + } + if (physical_stream_.get()) { + if (stop_physical_stream) { + physical_stream_->Stop(); + pending_bytes_ = 0; // Just in case. + } close_timer_.Reset(); + } } void AudioOutputMixer::StreamVolumeSet(AudioOutputProxy* stream_proxy, @@ -124,10 +144,8 @@ void AudioOutputMixer::Shutdown() { void AudioOutputMixer::ClosePhysicalStream() { DCHECK_EQ(MessageLoop::current(), message_loop_); - if (proxies_.empty() && physical_stream_.get() != NULL) { - physical_stream_->Stop(); + if (proxies_.empty() && physical_stream_.get() != NULL) physical_stream_.release()->Close(); - } } // AudioSourceCallback implementation. diff --git a/media/audio/audio_util.cc b/media/audio/audio_util.cc index 4035d28..23aad0f 100644 --- a/media/audio/audio_util.cc +++ b/media/audio/audio_util.cc @@ -21,7 +21,6 @@ #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 @@ -520,20 +519,6 @@ 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 4ac0ef6..df5683f 100644 --- a/media/audio/audio_util.h +++ b/media/audio/audio_util.h @@ -132,9 +132,6 @@ 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 38c4615..93dcf2f 100644 --- a/media/audio/win/audio_manager_win.cc +++ b/media/audio/win/audio_manager_win.cc @@ -244,10 +244,7 @@ AudioOutputStream* AudioManagerWin::MakeLinearOutputStream( if (params.channels() > kWinMaxChannels) return NULL; - return new PCMWaveOutAudioOutputStream(this, - params, - media::NumberOfWaveOutBuffers(), - WAVE_MAPPER); + return new PCMWaveOutAudioOutputStream(this, params, 3, 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 d954093..4066643 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 kMaxNumBuffers = 3; +const int kNumBuffers = 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() % NumberOfWaveOutBuffers() == 2) { + if (callback_count() % kNumBuffers == 2) { set_error(!CompareExistingIfNotNULL(2, dest)); - } else if (callback_count() % NumberOfWaveOutBuffers() == 1) { + } else if (callback_count() % kNumBuffers == 1) { set_error(!CompareExistingIfNotNULL(1, dest)); } else { set_error(!CompareExistingIfNotNULL(0, dest)); } - if (callback_count() > kMaxNumBuffers) { + if (callback_count() > kNumBuffers) { 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_[kMaxNumBuffers]; + void* buffer_address_[kNumBuffers]; }; // 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() > kMaxNumBuffers) { + if (callback_count() > kNumBuffers) { ::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(), kMaxNumBuffers); + EXPECT_GT(test_triple_buffer.callback_count(), kNumBuffers); EXPECT_FALSE(test_triple_buffer.had_error()); oas->Stop(); ::Sleep(500); @@ -600,37 +600,28 @@ TEST(WinAudioTest, PCMWaveStreamPendingBytes) { uint32 bytes_100_ms = samples_100_ms * 2; - // 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. + // 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. // 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)); - 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))) + .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)); EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, Field(&AudioBuffersState::pending_bytes, bytes_100_ms))) |