summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--media/audio/audio_output_controller_unittest.cc2
-rw-r--r--media/audio/audio_output_mixer.cc50
-rw-r--r--media/audio/audio_util.cc15
-rw-r--r--media/audio/audio_util.h3
-rw-r--r--media/audio/win/audio_manager_win.cc5
-rw-r--r--media/audio/win/audio_output_win_unittest.cc53
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)))