summaryrefslogtreecommitdiffstats
path: root/media/audio
diff options
context:
space:
mode:
authordalecurtis <dalecurtis@chromium.org>2015-04-22 12:42:47 -0700
committerCommit bot <commit-bot@chromium.org>2015-04-22 19:42:50 +0000
commit43f3b0d25752d924390a4d6fc868d6e9469edc4f (patch)
treec98b782a7a0ee1b939a744759e32a14e87fcfed9 /media/audio
parent2c7c723477f83a3ae5fae494948c24163fd3aa0e (diff)
downloadchromium_src-43f3b0d25752d924390a4d6fc868d6e9469edc4f.zip
chromium_src-43f3b0d25752d924390a4d6fc868d6e9469edc4f.tar.gz
chromium_src-43f3b0d25752d924390a4d6fc868d6e9469edc4f.tar.bz2
Switch to STA mode for audio thread and WASAPI I/O streams.
Using COM marshalling to share necessary worker thread pointers with the render and capture threads. BUG=422522 TEST=all unit tests pass, audio input and output work. Review URL: https://codereview.chromium.org/1097553003 Cr-Commit-Position: refs/heads/master@{#326360}
Diffstat (limited to 'media/audio')
-rw-r--r--media/audio/audio_input_volume_unittest.cc22
-rw-r--r--media/audio/audio_manager.cc15
-rw-r--r--media/audio/audio_manager_base.cc5
-rw-r--r--media/audio/audio_manager_unittest.cc18
-rw-r--r--media/audio/win/audio_device_listener_win_unittest.cc4
-rw-r--r--media/audio/win/audio_low_latency_input_win.cc52
-rw-r--r--media/audio/win/audio_low_latency_input_win.h27
-rw-r--r--media/audio/win/audio_low_latency_input_win_unittest.cc88
-rw-r--r--media/audio/win/audio_low_latency_output_win.cc107
-rw-r--r--media/audio/win/audio_low_latency_output_win.h31
-rw-r--r--media/audio/win/audio_low_latency_output_win_unittest.cc99
-rw-r--r--media/audio/win/audio_manager_win.h4
-rw-r--r--media/audio/win/audio_output_win_unittest.cc2
-rw-r--r--media/audio/win/core_audio_util_win.cc8
-rw-r--r--media/audio/win/core_audio_util_win_unittest.cc7
-rw-r--r--media/audio/win/device_enumeration_win.h2
16 files changed, 320 insertions, 171 deletions
diff --git a/media/audio/audio_input_volume_unittest.cc b/media/audio/audio_input_volume_unittest.cc
index d6ee313..19c712a 100644
--- a/media/audio/audio_input_volume_unittest.cc
+++ b/media/audio/audio_input_volume_unittest.cc
@@ -38,13 +38,7 @@ double GetVolumeAfterSetVolumeOnLinux(AudioInputStream* ais,
class AudioInputVolumeTest : public ::testing::Test {
protected:
- AudioInputVolumeTest()
- : audio_manager_(AudioManager::CreateForTesting())
-#if defined(OS_WIN)
- , com_init_(base::win::ScopedCOMInitializer::kMTA)
-#endif
- {
- }
+ AudioInputVolumeTest() : audio_manager_(AudioManager::CreateForTesting()) {}
bool HasCoreAudioAndInputDevices() {
#if defined(OS_WIN)
@@ -70,27 +64,27 @@ class AudioInputVolumeTest : public ::testing::Test {
params, device_id);
EXPECT_TRUE(NULL != ais);
-#if defined(OS_LINUX) || defined(OS_OPENBSD)
- // Some linux devices do not support our settings, we may fail to open
- // those devices.
+#if defined(OS_MACOSX)
+ EXPECT_TRUE(ais->Open());
+#else
+ // Some linux devices do not support our settings and some Windows devices
+ // may be "currently unavailable", we may fail to open those devices.
if (!ais->Open()) {
// Default device should always be able to be opened.
EXPECT_TRUE(AudioManagerBase::kDefaultDeviceId != device_id);
ais->Close();
ais = NULL;
}
-#elif defined(OS_WIN) || defined(OS_MACOSX)
- EXPECT_TRUE(ais->Open());
#endif
return ais;
}
- scoped_ptr<AudioManager> audio_manager_;
-
#if defined(OS_WIN)
base::win::ScopedCOMInitializer com_init_;
#endif
+
+ scoped_ptr<AudioManager> audio_manager_;
};
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
diff --git a/media/audio/audio_manager.cc b/media/audio/audio_manager.cc
index 6ee61d1..2bbffa7 100644
--- a/media/audio/audio_manager.cc
+++ b/media/audio/audio_manager.cc
@@ -11,6 +11,7 @@
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/power_monitor/power_monitor.h"
+#include "base/synchronization/waitable_event.h"
#include "build/build_config.h"
#include "media/audio/fake_audio_log_factory.h"
@@ -157,7 +158,19 @@ AudioManager* AudioManager::CreateWithHangTimer(
// static
AudioManager* AudioManager::CreateForTesting() {
- return Create(g_helper.Pointer()->fake_log_factory());
+ AudioManager* manager = Create(g_helper.Pointer()->fake_log_factory());
+
+ // When created for testing, always ensure all methods are ready to run (even
+ // if they end up called from other threads.
+ if (!manager->GetTaskRunner()->BelongsToCurrentThread()) {
+ base::WaitableEvent event(false, false);
+ manager->GetTaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)));
+ event.Wait();
+ }
+
+ return manager;
}
// static
diff --git a/media/audio/audio_manager_base.cc b/media/audio/audio_manager_base.cc
index edaabf4..24e0883 100644
--- a/media/audio/audio_manager_base.cc
+++ b/media/audio/audio_manager_base.cc
@@ -83,7 +83,10 @@ AudioManagerBase::AudioManagerBase(AudioLogFactory* audio_log_factory)
audio_thread_("AudioThread"),
audio_log_factory_(audio_log_factory) {
#if defined(OS_WIN)
- audio_thread_.init_com_with_mta(true);
+ // Do not use MTA mode initalization as it causes hangs for a significant
+ // population of users and is not supported on Windows 8 for audio capture
+ // and rendering. See http://crbug.com/422522.
+ audio_thread_.init_com_with_mta(false);
#elif defined(OS_MACOSX)
// CoreAudio calls must occur on the main thread of the process, which in our
// case is sadly the browser UI thread. Failure to execute calls on the right
diff --git a/media/audio/audio_manager_unittest.cc b/media/audio/audio_manager_unittest.cc
index 26c110e..e876dd1 100644
--- a/media/audio/audio_manager_unittest.cc
+++ b/media/audio/audio_manager_unittest.cc
@@ -33,19 +33,7 @@ namespace media {
// Windows.
class AudioManagerTest : public ::testing::Test {
protected:
- AudioManagerTest()
- : audio_manager_(AudioManager::CreateForTesting())
-#if defined(OS_WIN)
- , com_init_(base::win::ScopedCOMInitializer::kMTA)
-#endif
- {
- // Wait for audio thread initialization to complete. Otherwise the
- // enumeration type may not have been set yet.
- base::WaitableEvent event(false, false);
- audio_manager_->GetTaskRunner()->PostTask(FROM_HERE, base::Bind(
- &base::WaitableEvent::Signal, base::Unretained(&event)));
- event.Wait();
- }
+ AudioManagerTest() : audio_manager_(AudioManager::CreateForTesting()) {}
#if defined(OS_WIN)
bool SetMMDeviceEnumeration() {
@@ -55,13 +43,13 @@ class AudioManagerTest : public ::testing::Test {
if (amw->enumeration_type() == AudioManagerWin::kWaveEnumeration)
return false;
- amw->SetEnumerationType(AudioManagerWin::kMMDeviceEnumeration);
+ amw->set_enumeration_type(AudioManagerWin::kMMDeviceEnumeration);
return true;
}
void SetWaveEnumeration() {
AudioManagerWin* amw = static_cast<AudioManagerWin*>(audio_manager_.get());
- amw->SetEnumerationType(AudioManagerWin::kWaveEnumeration);
+ amw->set_enumeration_type(AudioManagerWin::kWaveEnumeration);
}
std::string GetDeviceIdFromPCMWaveInAudioInputStream(
diff --git a/media/audio/win/audio_device_listener_win_unittest.cc b/media/audio/win/audio_device_listener_win_unittest.cc
index 49a1359..9f9dc2b 100644
--- a/media/audio/win/audio_device_listener_win_unittest.cc
+++ b/media/audio/win/audio_device_listener_win_unittest.cc
@@ -25,9 +25,7 @@ static const char kSecondTestDevice[] = "test_device_1";
class AudioDeviceListenerWinTest : public testing::Test {
public:
- AudioDeviceListenerWinTest()
- : com_init_(ScopedCOMInitializer::kMTA) {
- }
+ AudioDeviceListenerWinTest() {}
virtual void SetUp() {
if (!CoreAudioUtil::IsSupported())
diff --git a/media/audio/win/audio_low_latency_input_win.cc b/media/audio/win/audio_low_latency_input_win.cc
index 72d1d72..674a097 100644
--- a/media/audio/win/audio_low_latency_input_win.cc
+++ b/media/audio/win/audio_low_latency_input_win.cc
@@ -158,6 +158,11 @@ void WASAPIAudioInputStream::Start(AudioInputCallback* callback) {
// using SetAutomaticGainControl().
StartAgc();
+ if (!MarshalComPointers()) {
+ HandleError(S_FALSE);
+ return;
+ }
+
// Create and start the thread that will drive the capturing by waiting for
// capture events.
capture_thread_ =
@@ -172,6 +177,8 @@ void WASAPIAudioInputStream::Start(AudioInputCallback* callback) {
hr = audio_render_client_for_loopback_->Start();
started_ = SUCCEEDED(hr);
+ if (!started_)
+ HandleError(hr);
}
void WASAPIAudioInputStream::Stop() {
@@ -350,7 +357,7 @@ HRESULT WASAPIAudioInputStream::GetMixFormat(const std::string& device_id,
}
void WASAPIAudioInputStream::Run() {
- ScopedCOMInitializer com_init(ScopedCOMInitializer::kMTA);
+ ScopedCOMInitializer com_init;
// Increase the thread priority.
capture_thread_->SetThreadPriority(base::ThreadPriority::REALTIME_AUDIO);
@@ -369,6 +376,10 @@ void WASAPIAudioInputStream::Run() {
LOG(WARNING) << "Failed to enable MMCSS (error code=" << err << ").";
}
+ // Retrieve COM pointers from the main thread.
+ ScopedComPtr<IAudioCaptureClient> audio_capture_client;
+ UnmarshalComPointers(&audio_capture_client);
+
// Allocate a buffer with a size that enables us to take care of cases like:
// 1) The recorded buffer size is smaller, or does not match exactly with,
// the selected packet size used in each callback.
@@ -383,7 +394,7 @@ void WASAPIAudioInputStream::Run() {
LARGE_INTEGER now_count;
bool recording = true;
bool error = false;
- double volume = GetVolume();
+ double volume = 0;
HANDLE wait_array[2] =
{ stop_capture_event_.Get(), audio_samples_ready_event_.Get() };
@@ -412,11 +423,9 @@ void WASAPIAudioInputStream::Run() {
// Retrieve the amount of data in the capture endpoint buffer,
// replace it with silence if required, create callbacks for each
// packet and store non-delivered data for the next event.
- hr = audio_capture_client_->GetBuffer(&data_ptr,
- &num_frames_to_read,
- &flags,
- &device_position,
- &first_audio_frame_timestamp);
+ hr = audio_capture_client->GetBuffer(
+ &data_ptr, &num_frames_to_read, &flags, &device_position,
+ &first_audio_frame_timestamp);
if (FAILED(hr)) {
DLOG(ERROR) << "Failed to get data from the capture buffer";
continue;
@@ -438,7 +447,7 @@ void WASAPIAudioInputStream::Run() {
buffer_frame_index += num_frames_to_read;
}
- hr = audio_capture_client_->ReleaseBuffer(num_frames_to_read);
+ hr = audio_capture_client->ReleaseBuffer(num_frames_to_read);
DLOG_IF(ERROR, FAILED(hr)) << "Failed to release capture buffer";
// Derive a delay estimate for the captured audio packet.
@@ -676,8 +685,11 @@ HRESULT WASAPIAudioInputStream::InitializeAudioEngine() {
&format_,
(effects_ & AudioParameters::DUCKING) ? &kCommunicationsSessionId : NULL);
- if (FAILED(hr))
+ if (FAILED(hr)) {
+ PLOG(ERROR) << "Failed to initalize IAudioClient: " << std::hex << hr
+ << " : ";
return hr;
+ }
// Retrieve the length of the endpoint buffer shared between the client
// and the audio engine. The buffer length determines the maximum amount
@@ -768,4 +780,26 @@ HRESULT WASAPIAudioInputStream::InitializeAudioEngine() {
return hr;
}
+bool WASAPIAudioInputStream::MarshalComPointers() {
+ DCHECK(CalledOnValidThread());
+ DCHECK(!com_stream_);
+ HRESULT hr = CoMarshalInterThreadInterfaceInStream(
+ __uuidof(IAudioCaptureClient), audio_capture_client_.get(),
+ com_stream_.Receive());
+ if (FAILED(hr))
+ DLOG(ERROR) << "Marshal failed for IAudioCaptureClient: " << std::hex << hr;
+ DCHECK_EQ(SUCCEEDED(hr), !!com_stream_);
+ return SUCCEEDED(hr);
+}
+
+void WASAPIAudioInputStream::UnmarshalComPointers(
+ ScopedComPtr<IAudioCaptureClient>* audio_capture_client) {
+ DCHECK_EQ(capture_thread_->tid(), base::PlatformThread::CurrentId());
+ DCHECK(com_stream_);
+ HRESULT hr = CoGetInterfaceAndReleaseStream(
+ com_stream_.Detach(), __uuidof(IAudioCaptureClient),
+ audio_capture_client->ReceiveVoid());
+ CHECK(SUCCEEDED(hr));
+}
+
} // namespace media
diff --git a/media/audio/win/audio_low_latency_input_win.h b/media/audio/win/audio_low_latency_input_win.h
index 7501405..00a7de7 100644
--- a/media/audio/win/audio_low_latency_input_win.h
+++ b/media/audio/win/audio_low_latency_input_win.h
@@ -131,6 +131,13 @@ class MEDIA_EXPORT WASAPIAudioInputStream
WAVEFORMATEX** device_format,
int* effects);
+ // Handles sharing of COM pointers between the audio and capture threads. The
+ // marshal method must be called on the audio manager thread, while unmarshal
+ // must be called on |capture_thread_|.
+ bool MarshalComPointers();
+ void UnmarshalComPointers(
+ base::win::ScopedComPtr<IAudioCaptureClient>* audio_capture_client);
+
// Our creator, the audio manager needs to be notified when we close.
AudioManagerWin* manager_;
@@ -179,8 +186,17 @@ class MEDIA_EXPORT WASAPIAudioInputStream
// Pointer to the object that will receive the recorded audio samples.
AudioInputCallback* sink_;
- // Windows Multimedia Device (MMDevice) API interfaces.
+ // ------------------------------------------------------
+ // Warning: COM pointers must be marshaled from the audio thread to be used
+ // on any other thread. Do not use any of these interfaces on a thread other
+ // than the audio thread. See MarshalComPointers() and UnmarshalComPointers()
+ // for marshaling pointers to the capture thread.
+
+ // Stream into which the COM pointers below are marshaled so that they can
+ // be used on another thread.
+ base::win::ScopedComPtr<IStream> com_stream_;
+ // Windows Multimedia Device (MMDevice) API interfaces.
// An IMMDevice interface which represents an audio endpoint device.
base::win::ScopedComPtr<IMMDevice> endpoint_device_;
@@ -198,16 +214,17 @@ class MEDIA_EXPORT WASAPIAudioInputStream
// details.
base::win::ScopedComPtr<IAudioClient> audio_render_client_for_loopback_;
- // The IAudioCaptureClient interface enables a client to read input data
- // from a capture endpoint buffer.
- base::win::ScopedComPtr<IAudioCaptureClient> audio_capture_client_;
-
// The ISimpleAudioVolume interface enables a client to control the
// master volume level of an audio session.
// The volume-level is a value in the range 0.0 to 1.0.
// This interface does only work with shared-mode streams.
base::win::ScopedComPtr<ISimpleAudioVolume> simple_audio_volume_;
+ // The IAudioCaptureClient interface enables a client to read input data
+ // from a capture endpoint buffer.
+ base::win::ScopedComPtr<IAudioCaptureClient> audio_capture_client_;
+ // ------------------------------------------------------
+
// The audio engine will signal this event each time a buffer has been
// recorded.
base::win::ScopedHandle audio_samples_ready_event_;
diff --git a/media/audio/win/audio_low_latency_input_win_unittest.cc b/media/audio/win/audio_low_latency_input_win_unittest.cc
index 69a24f8..60d386d 100644
--- a/media/audio/win/audio_low_latency_input_win_unittest.cc
+++ b/media/audio/win/audio_low_latency_input_win_unittest.cc
@@ -163,11 +163,9 @@ static bool HasCoreAudioAndInputDevices(AudioManager* audio_man) {
class AudioInputStreamWrapper {
public:
explicit AudioInputStreamWrapper(AudioManager* audio_manager)
- : com_init_(ScopedCOMInitializer::kMTA),
- audio_man_(audio_manager),
- default_params_(
- audio_manager->GetInputStreamParameters(
- AudioManagerBase::kDefaultDeviceId)) {
+ : audio_man_(audio_manager),
+ default_params_(audio_man_->GetInputStreamParameters(
+ AudioManagerBase::kDefaultDeviceId)) {
EXPECT_EQ(format(), AudioParameters::AUDIO_PCM_LOW_LATENCY);
frames_per_buffer_ = default_params_.frames_per_buffer();
// We expect the default buffer size to be a 10ms buffer.
@@ -207,7 +205,6 @@ class AudioInputStreamWrapper {
return ais;
}
- ScopedCOMInitializer com_init_;
AudioManager* audio_man_;
const AudioParameters default_params_;
int frames_per_buffer_;
@@ -254,17 +251,24 @@ class ScopedAudioInputStream {
DISALLOW_COPY_AND_ASSIGN(ScopedAudioInputStream);
};
+class WinAudioInputTest : public testing::Test {
+ public:
+ WinAudioInputTest() : audio_manager_(AudioManager::CreateForTesting()) {}
+ ~WinAudioInputTest() override {}
+
+ protected:
+ ScopedCOMInitializer com_init_;
+ scoped_ptr<AudioManager> audio_manager_;
+};
+
// Verify that we can retrieve the current hardware/mixing sample rate
// for all available input devices.
-TEST(WinAudioInputTest, WASAPIAudioInputStreamHardwareSampleRate) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get()));
-
- ScopedCOMInitializer com_init(ScopedCOMInitializer::kMTA);
+TEST_F(WinAudioInputTest, WASAPIAudioInputStreamHardwareSampleRate) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));
// Retrieve a list of all available input devices.
media::AudioDeviceNames device_names;
- audio_manager->GetAudioInputDeviceNames(&device_names);
+ audio_manager_->GetAudioInputDeviceNames(&device_names);
// Scan all available input devices and repeat the same test for all of them.
for (media::AudioDeviceNames::const_iterator it = device_names.begin();
@@ -277,30 +281,27 @@ TEST(WinAudioInputTest, WASAPIAudioInputStreamHardwareSampleRate) {
}
// Test Create(), Close() calling sequence.
-TEST(WinAudioInputTest, WASAPIAudioInputStreamCreateAndClose) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get()));
+TEST_F(WinAudioInputTest, WASAPIAudioInputStreamCreateAndClose) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));
ScopedAudioInputStream ais(
- CreateDefaultAudioInputStream(audio_manager.get()));
+ CreateDefaultAudioInputStream(audio_manager_.get()));
ais.Close();
}
// Test Open(), Close() calling sequence.
-TEST(WinAudioInputTest, WASAPIAudioInputStreamOpenAndClose) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get()));
+TEST_F(WinAudioInputTest, WASAPIAudioInputStreamOpenAndClose) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));
ScopedAudioInputStream ais(
- CreateDefaultAudioInputStream(audio_manager.get()));
+ CreateDefaultAudioInputStream(audio_manager_.get()));
EXPECT_TRUE(ais->Open());
ais.Close();
}
// Test Open(), Start(), Close() calling sequence.
-TEST(WinAudioInputTest, WASAPIAudioInputStreamOpenStartAndClose) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get()));
+TEST_F(WinAudioInputTest, WASAPIAudioInputStreamOpenStartAndClose) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));
ScopedAudioInputStream ais(
- CreateDefaultAudioInputStream(audio_manager.get()));
+ CreateDefaultAudioInputStream(audio_manager_.get()));
EXPECT_TRUE(ais->Open());
MockAudioInputCallback sink;
ais->Start(&sink);
@@ -308,11 +309,10 @@ TEST(WinAudioInputTest, WASAPIAudioInputStreamOpenStartAndClose) {
}
// Test Open(), Start(), Stop(), Close() calling sequence.
-TEST(WinAudioInputTest, WASAPIAudioInputStreamOpenStartStopAndClose) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get()));
+TEST_F(WinAudioInputTest, WASAPIAudioInputStreamOpenStartStopAndClose) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));
ScopedAudioInputStream ais(
- CreateDefaultAudioInputStream(audio_manager.get()));
+ CreateDefaultAudioInputStream(audio_manager_.get()));
EXPECT_TRUE(ais->Open());
MockAudioInputCallback sink;
ais->Start(&sink);
@@ -321,11 +321,10 @@ TEST(WinAudioInputTest, WASAPIAudioInputStreamOpenStartStopAndClose) {
}
// Test some additional calling sequences.
-TEST(WinAudioInputTest, WASAPIAudioInputStreamMiscCallingSequences) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get()));
+TEST_F(WinAudioInputTest, WASAPIAudioInputStreamMiscCallingSequences) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));
ScopedAudioInputStream ais(
- CreateDefaultAudioInputStream(audio_manager.get()));
+ CreateDefaultAudioInputStream(audio_manager_.get()));
WASAPIAudioInputStream* wais =
static_cast<WASAPIAudioInputStream*>(ais.get());
@@ -349,9 +348,8 @@ TEST(WinAudioInputTest, WASAPIAudioInputStreamMiscCallingSequences) {
ais.Close();
}
-TEST(WinAudioInputTest, WASAPIAudioInputStreamTestPacketSizes) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get()));
+TEST_F(WinAudioInputTest, WASAPIAudioInputStreamTestPacketSizes) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));
int count = 0;
base::MessageLoopForUI loop;
@@ -360,7 +358,7 @@ TEST(WinAudioInputTest, WASAPIAudioInputStreamTestPacketSizes) {
// Create default WASAPI input stream which records in stereo using
// the shared mixing rate. The default buffer size is 10ms.
- AudioInputStreamWrapper aisw(audio_manager.get());
+ AudioInputStreamWrapper aisw(audio_manager_.get());
ScopedAudioInputStream ais(aisw.Create());
EXPECT_TRUE(ais->Open());
@@ -419,21 +417,20 @@ TEST(WinAudioInputTest, WASAPIAudioInputStreamTestPacketSizes) {
}
// Test that we can capture a stream in loopback.
-TEST(WinAudioInputTest, WASAPIAudioInputStreamLoopback) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(audio_manager->HasAudioOutputDevices() &&
+TEST_F(WinAudioInputTest, WASAPIAudioInputStreamLoopback) {
+ ABORT_AUDIO_TEST_IF_NOT(audio_manager_->HasAudioOutputDevices() &&
CoreAudioUtil::IsSupported());
- AudioParameters params = audio_manager->GetInputStreamParameters(
+ AudioParameters params = audio_manager_->GetInputStreamParameters(
AudioManagerBase::kLoopbackInputDeviceId);
EXPECT_EQ(params.effects(), 0);
AudioParameters output_params =
- audio_manager->GetOutputStreamParameters(std::string());
+ audio_manager_->GetOutputStreamParameters(std::string());
EXPECT_EQ(params.sample_rate(), output_params.sample_rate());
EXPECT_EQ(params.channel_layout(), output_params.channel_layout());
- ScopedAudioInputStream stream(audio_manager->MakeAudioInputStream(
+ ScopedAudioInputStream stream(audio_manager_->MakeAudioInputStream(
params, AudioManagerBase::kLoopbackInputDeviceId));
ASSERT_TRUE(stream->Open());
FakeAudioInputCallback sink;
@@ -453,16 +450,15 @@ TEST(WinAudioInputTest, WASAPIAudioInputStreamLoopback) {
// To include disabled tests in test execution, just invoke the test program
// with --gtest_also_run_disabled_tests or set the GTEST_ALSO_RUN_DISABLED_TESTS
// environment variable to a value greater than 0.
-TEST(WinAudioInputTest, DISABLED_WASAPIAudioInputStreamRecordToFile) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get()));
+TEST_F(WinAudioInputTest, DISABLED_WASAPIAudioInputStreamRecordToFile) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));
// Name of the output PCM file containing captured data. The output file
// will be stored in the directory containing 'media_unittests.exe'.
// Example of full name: \src\build\Debug\out_stereo_10sec.pcm.
const char* file_name = "out_stereo_10sec.pcm";
- AudioInputStreamWrapper aisw(audio_manager.get());
+ AudioInputStreamWrapper aisw(audio_manager_.get());
ScopedAudioInputStream ais(aisw.Create());
EXPECT_TRUE(ais->Open());
diff --git a/media/audio/win/audio_low_latency_output_win.cc b/media/audio/win/audio_low_latency_output_win.cc
index f7b31a3..a9d637c 100644
--- a/media/audio/win/audio_low_latency_output_win.cc
+++ b/media/audio/win/audio_low_latency_output_win.cc
@@ -249,6 +249,11 @@ void WASAPIAudioOutputStream::Start(AudioSourceCallback* callback) {
}
num_written_frames_ = endpoint_buffer_size_frames_;
+ if (!MarshalComPointers()) {
+ callback->OnError(this);
+ return;
+ }
+
// Create and start the thread that will drive the rendering by waiting for
// render events.
render_thread_.reset(
@@ -333,7 +338,7 @@ void WASAPIAudioOutputStream::GetVolume(double* volume) {
}
void WASAPIAudioOutputStream::Run() {
- ScopedCOMInitializer com_init(ScopedCOMInitializer::kMTA);
+ ScopedCOMInitializer com_init;
// Increase the thread priority.
render_thread_->SetThreadPriority(base::ThreadPriority::REALTIME_AUDIO);
@@ -352,6 +357,12 @@ void WASAPIAudioOutputStream::Run() {
LOG(WARNING) << "Failed to enable MMCSS (error code=" << err << ").";
}
+ // Retrieve COM pointers from the main thread.
+ ScopedComPtr<IAudioClient> audio_client;
+ ScopedComPtr<IAudioRenderClient> audio_render_client;
+ ScopedComPtr<IAudioClock> audio_clock;
+ UnmarshalComPointers(&audio_client, &audio_render_client, &audio_clock);
+
HRESULT hr = S_FALSE;
bool playing = true;
@@ -362,7 +373,7 @@ void WASAPIAudioOutputStream::Run() {
// The device frequency is the frequency generated by the hardware clock in
// the audio device. The GetFrequency() method reports a constant frequency.
- hr = audio_clock_->GetFrequency(&device_frequency);
+ hr = audio_clock->GetFrequency(&device_frequency);
error = FAILED(hr);
PLOG_IF(ERROR, error) << "Failed to acquire IAudioClock interface: "
<< std::hex << hr;
@@ -383,7 +394,9 @@ void WASAPIAudioOutputStream::Run() {
break;
case WAIT_OBJECT_0 + 1:
// |audio_samples_render_event_| has been set.
- error = !RenderAudioFromSource(device_frequency);
+ error = !RenderAudioFromSource(device_frequency, audio_client.get(),
+ audio_render_client.get(),
+ audio_clock.get());
break;
default:
error = true;
@@ -391,11 +404,11 @@ void WASAPIAudioOutputStream::Run() {
}
}
- if (playing && error) {
+ if (playing && error && audio_client) {
// Stop audio rendering since something has gone wrong in our main thread
// loop. Note that, we are still in a "started" state, hence a Stop() call
// is required to join the thread properly.
- audio_client_->Stop();
+ audio_client->Stop();
PLOG(ERROR) << "WASAPI rendering failed.";
}
@@ -405,7 +418,11 @@ void WASAPIAudioOutputStream::Run() {
}
}
-bool WASAPIAudioOutputStream::RenderAudioFromSource(UINT64 device_frequency) {
+bool WASAPIAudioOutputStream::RenderAudioFromSource(
+ UINT64 device_frequency,
+ IAudioClient* audio_client,
+ IAudioRenderClient* audio_render_client,
+ IAudioClock* audio_clock) {
TRACE_EVENT0("audio", "RenderAudioFromSource");
HRESULT hr = S_FALSE;
@@ -420,7 +437,7 @@ bool WASAPIAudioOutputStream::RenderAudioFromSource(UINT64 device_frequency) {
if (share_mode_ == AUDCLNT_SHAREMODE_SHARED) {
// Get the padding value which represents the amount of rendering
// data that is queued up to play in the endpoint buffer.
- hr = audio_client_->GetCurrentPadding(&num_queued_frames);
+ hr = audio_client->GetCurrentPadding(&num_queued_frames);
num_available_frames =
endpoint_buffer_size_frames_ - num_queued_frames;
if (FAILED(hr)) {
@@ -462,8 +479,7 @@ bool WASAPIAudioOutputStream::RenderAudioFromSource(UINT64 device_frequency) {
for (size_t n = 0; n < num_packets; ++n) {
// Grab all available space in the rendering endpoint buffer
// into which the client can write a data packet.
- hr = audio_render_client_->GetBuffer(packet_size_frames_,
- &audio_data);
+ hr = audio_render_client->GetBuffer(packet_size_frames_, &audio_data);
if (FAILED(hr)) {
DLOG(ERROR) << "Failed to use rendering audio buffer: "
<< std::hex << hr;
@@ -477,7 +493,7 @@ bool WASAPIAudioOutputStream::RenderAudioFromSource(UINT64 device_frequency) {
// unit at the render side.
UINT64 position = 0;
uint32 audio_delay_bytes = 0;
- hr = audio_clock_->GetPosition(&position, NULL);
+ hr = audio_clock->GetPosition(&position, NULL);
if (SUCCEEDED(hr)) {
// Stream position of the sample that is currently playing
// through the speaker.
@@ -517,7 +533,7 @@ bool WASAPIAudioOutputStream::RenderAudioFromSource(UINT64 device_frequency) {
// Render silence if we were not able to fill up the buffer totally.
DWORD flags = (num_filled_bytes < packet_size_bytes_) ?
AUDCLNT_BUFFERFLAGS_SILENT : 0;
- audio_render_client_->ReleaseBuffer(packet_size_frames_, flags);
+ audio_render_client->ReleaseBuffer(packet_size_frames_, flags);
num_written_frames_ += packet_size_frames_;
}
@@ -622,4 +638,73 @@ void WASAPIAudioOutputStream::StopThread() {
source_ = NULL;
}
+bool WASAPIAudioOutputStream::MarshalComPointers() {
+ DCHECK_EQ(creating_thread_id_, base::PlatformThread::CurrentId());
+ DCHECK(!com_stream_);
+
+ ScopedComPtr<IStream> com_stream;
+ HRESULT hr = CreateStreamOnHGlobal(NULL, TRUE, com_stream.Receive());
+ if (FAILED(hr)) {
+ DLOG(ERROR) << "Failed to create stream for marshaling COM pointers.";
+ return false;
+ }
+
+ hr = CoMarshalInterface(com_stream.get(), __uuidof(IAudioClient),
+ audio_client_.get(), MSHCTX_INPROC, NULL,
+ MSHLFLAGS_NORMAL);
+ if (FAILED(hr)) {
+ DLOG(ERROR) << "Marshal failed for IAudioClient: " << std::hex << hr;
+ return false;
+ }
+
+ hr = CoMarshalInterface(com_stream.get(), __uuidof(IAudioRenderClient),
+ audio_render_client_.get(), MSHCTX_INPROC, NULL,
+ MSHLFLAGS_NORMAL);
+ if (FAILED(hr)) {
+ DLOG(ERROR) << "Marshal failed for IAudioRenderClient: " << std::hex << hr;
+ return false;
+ }
+
+ hr = CoMarshalInterface(com_stream.get(), __uuidof(IAudioClock),
+ audio_clock_.get(), MSHCTX_INPROC, NULL,
+ MSHLFLAGS_NORMAL);
+ if (FAILED(hr)) {
+ DLOG(ERROR) << "Marshal failed for IAudioClock: " << std::hex << hr;
+ return false;
+ }
+
+ LARGE_INTEGER pos = {0};
+ hr = com_stream->Seek(pos, STREAM_SEEK_SET, NULL);
+ if (FAILED(hr)) {
+ DLOG(ERROR) << "Failed to seek IStream for marshaling: " << std::hex << hr;
+ return false;
+ }
+
+ com_stream_ = com_stream.Pass();
+ return true;
+}
+
+void WASAPIAudioOutputStream::UnmarshalComPointers(
+ ScopedComPtr<IAudioClient>* audio_client,
+ ScopedComPtr<IAudioRenderClient>* audio_render_client,
+ ScopedComPtr<IAudioClock>* audio_clock) {
+ DCHECK_EQ(render_thread_->tid(), base::PlatformThread::CurrentId());
+
+ DCHECK(com_stream_);
+ ScopedComPtr<IStream> com_stream;
+ com_stream = com_stream_.Pass();
+
+ HRESULT hr = CoUnmarshalInterface(com_stream.get(), __uuidof(IAudioClient),
+ audio_client->ReceiveVoid());
+ CHECK(SUCCEEDED(hr));
+
+ hr = CoUnmarshalInterface(com_stream.get(), __uuidof(IAudioRenderClient),
+ audio_render_client->ReceiveVoid());
+ CHECK(SUCCEEDED(hr));
+
+ hr = CoUnmarshalInterface(com_stream.get(), __uuidof(IAudioClock),
+ audio_clock->ReceiveVoid());
+ CHECK(SUCCEEDED(hr));
+}
+
} // namespace media
diff --git a/media/audio/win/audio_low_latency_output_win.h b/media/audio/win/audio_low_latency_output_win.h
index 9d612b3..30e791b 100644
--- a/media/audio/win/audio_low_latency_output_win.h
+++ b/media/audio/win/audio_low_latency_output_win.h
@@ -157,7 +157,10 @@ class MEDIA_EXPORT WASAPIAudioOutputStream :
// Checks available amount of space in the endpoint buffer and reads
// data from the client to fill up the buffer without causing audio
// glitches.
- bool RenderAudioFromSource(UINT64 device_frequency);
+ bool RenderAudioFromSource(UINT64 device_frequency,
+ IAudioClient* thread_audio_client,
+ IAudioRenderClient* thread_audio_render_client,
+ IAudioClock* thread_audio_clock);
// Called when the device will be opened in exclusive mode and use the
// application specified format.
@@ -172,6 +175,15 @@ class MEDIA_EXPORT WASAPIAudioOutputStream :
// |source_| is set to NULL.
void StopThread();
+ // Handles sharing of COM pointers between the audio and render threads. The
+ // marshal method must be called on the audio manager thread, while unmarshal
+ // must be called on |render_thread_|.
+ bool MarshalComPointers();
+ void UnmarshalComPointers(
+ base::win::ScopedComPtr<IAudioClient>* audio_client,
+ base::win::ScopedComPtr<IAudioRenderClient>* audio_render_client,
+ base::win::ScopedComPtr<IAudioClock>* audio_clock);
+
// Contains the thread ID of the creating thread.
base::PlatformThreadId creating_thread_id_;
@@ -221,6 +233,18 @@ class MEDIA_EXPORT WASAPIAudioOutputStream :
// Pointer to the client that will deliver audio samples to be played out.
AudioSourceCallback* source_;
+ // ------------------------------------------------------
+ // Warning: COM pointers must be marshaled from the audio thread to be used
+ // on any other thread. Do not use any of these interfaces on a thread other
+ // than the audio thread. See MarshalComPointers() and UnmarshalComPointers()
+ // for marshaling pointers to the render thread.
+
+ // Stream into which the COM pointers below are marshaled so that they can
+ // be used on another thread.
+ base::win::ScopedComPtr<IStream> com_stream_;
+
+ // Windows Audio Session API (WASAPI) interfaces.
+
// An IAudioClient interface which enables a client to create and initialize
// an audio stream between an audio application and the audio engine.
base::win::ScopedComPtr<IAudioClient> audio_client_;
@@ -229,6 +253,9 @@ class MEDIA_EXPORT WASAPIAudioOutputStream :
// data to a rendering endpoint buffer.
base::win::ScopedComPtr<IAudioRenderClient> audio_render_client_;
+ base::win::ScopedComPtr<IAudioClock> audio_clock_;
+ // ------------------------------------------------------
+
// The audio engine will signal this event each time a buffer becomes
// ready to be filled by the client.
base::win::ScopedHandle audio_samples_render_event_;
@@ -239,8 +266,6 @@ class MEDIA_EXPORT WASAPIAudioOutputStream :
// Container for retrieving data from AudioSourceCallback::OnMoreData().
scoped_ptr<AudioBus> audio_bus_;
- base::win::ScopedComPtr<IAudioClock> audio_clock_;
-
DISALLOW_COPY_AND_ASSIGN(WASAPIAudioOutputStream);
};
diff --git a/media/audio/win/audio_low_latency_output_win_unittest.cc b/media/audio/win/audio_low_latency_output_win_unittest.cc
index afd565a..193c082 100644
--- a/media/audio/win/audio_low_latency_output_win_unittest.cc
+++ b/media/audio/win/audio_low_latency_output_win_unittest.cc
@@ -6,6 +6,7 @@
#include <mmsystem.h>
#include "base/basictypes.h"
+#include "base/bind.h"
#include "base/environment.h"
#include "base/files/file_util.h"
#include "base/memory/scoped_ptr.h"
@@ -226,14 +227,24 @@ static AudioOutputStream* CreateDefaultAudioOutputStream(
return aos;
}
+class WASAPIAudioOutputStreamTest : public testing::Test {
+ public:
+ WASAPIAudioOutputStreamTest()
+ : audio_manager_(AudioManager::CreateForTesting()) {}
+ ~WASAPIAudioOutputStreamTest() override {}
+
+ protected:
+ ScopedCOMInitializer com_init_;
+ scoped_ptr<AudioManager> audio_manager_;
+};
+
// Verify that we can retrieve the current hardware/mixing sample rate
// for the default audio device.
// TODO(henrika): modify this test when we support full device enumeration.
-TEST(WASAPIAudioOutputStreamTest, HardwareSampleRate) {
+TEST_F(WASAPIAudioOutputStreamTest, HardwareSampleRate) {
// Skip this test in exclusive mode since the resulting rate is only utilized
// for shared mode streams.
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get()) &&
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get()) &&
ExclusiveModeIsEnabled());
// Default device intended for games, system notification sounds,
@@ -244,27 +255,24 @@ TEST(WASAPIAudioOutputStreamTest, HardwareSampleRate) {
}
// Test Create(), Close() calling sequence.
-TEST(WASAPIAudioOutputStreamTest, CreateAndClose) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get()));
- AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
+TEST_F(WASAPIAudioOutputStreamTest, CreateAndClose) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get()));
+ AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager_.get());
aos->Close();
}
// Test Open(), Close() calling sequence.
-TEST(WASAPIAudioOutputStreamTest, OpenAndClose) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get()));
- AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
+TEST_F(WASAPIAudioOutputStreamTest, OpenAndClose) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get()));
+ AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager_.get());
EXPECT_TRUE(aos->Open());
aos->Close();
}
// Test Open(), Start(), Close() calling sequence.
-TEST(WASAPIAudioOutputStreamTest, OpenStartAndClose) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get()));
- AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
+TEST_F(WASAPIAudioOutputStreamTest, OpenStartAndClose) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get()));
+ AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager_.get());
EXPECT_TRUE(aos->Open());
MockAudioSourceCallback source;
EXPECT_CALL(source, OnError(aos))
@@ -274,10 +282,9 @@ TEST(WASAPIAudioOutputStreamTest, OpenStartAndClose) {
}
// Test Open(), Start(), Stop(), Close() calling sequence.
-TEST(WASAPIAudioOutputStreamTest, OpenStartStopAndClose) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get()));
- AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
+TEST_F(WASAPIAudioOutputStreamTest, OpenStartStopAndClose) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get()));
+ AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager_.get());
EXPECT_TRUE(aos->Open());
MockAudioSourceCallback source;
EXPECT_CALL(source, OnError(aos))
@@ -288,10 +295,9 @@ TEST(WASAPIAudioOutputStreamTest, OpenStartStopAndClose) {
}
// Test SetVolume(), GetVolume()
-TEST(WASAPIAudioOutputStreamTest, Volume) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get()));
- AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
+TEST_F(WASAPIAudioOutputStreamTest, Volume) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get()));
+ AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager_.get());
// Initial volume should be full volume (1.0).
double volume = 0.0;
@@ -324,11 +330,10 @@ TEST(WASAPIAudioOutputStreamTest, Volume) {
}
// Test some additional calling sequences.
-TEST(WASAPIAudioOutputStreamTest, MiscCallingSequences) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get()));
+TEST_F(WASAPIAudioOutputStreamTest, MiscCallingSequences) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get()));
- AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
+ AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager_.get());
WASAPIAudioOutputStream* waos = static_cast<WASAPIAudioOutputStream*>(aos);
// Open(), Open() is a valid calling sequence (second call does nothing).
@@ -363,16 +368,15 @@ TEST(WASAPIAudioOutputStreamTest, MiscCallingSequences) {
}
// Use preferred packet size and verify that rendering starts.
-TEST(WASAPIAudioOutputStreamTest, ValidPacketSize) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get()));
+TEST_F(WASAPIAudioOutputStreamTest, ValidPacketSize) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get()));
base::MessageLoopForUI loop;
MockAudioSourceCallback source;
// Create default WASAPI output stream which plays out in stereo using
// the shared mixing rate. The default buffer size is 10ms.
- AudioOutputStreamWrapper aosw(audio_manager.get());
+ AudioOutputStreamWrapper aosw(audio_manager_.get());
AudioOutputStream* aos = aosw.Create();
EXPECT_TRUE(aos->Open());
@@ -401,11 +405,10 @@ TEST(WASAPIAudioOutputStreamTest, ValidPacketSize) {
// with --gtest_also_run_disabled_tests or set the GTEST_ALSO_RUN_DISABLED_TESTS
// environment variable to a value greater than 0.
// The test files are approximately 20 seconds long.
-TEST(WASAPIAudioOutputStreamTest, DISABLED_ReadFromStereoFile) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get()));
+TEST_F(WASAPIAudioOutputStreamTest, DISABLED_ReadFromStereoFile) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get()));
- AudioOutputStreamWrapper aosw(audio_manager.get());
+ AudioOutputStreamWrapper aosw(audio_manager_.get());
AudioOutputStream* aos = aosw.Create();
EXPECT_TRUE(aos->Open());
@@ -450,12 +453,11 @@ TEST(WASAPIAudioOutputStreamTest, DISABLED_ReadFromStereoFile) {
// certain set of audio parameters and a sample rate of 48kHz.
// The expected outcomes of each setting in this test has been derived
// manually using log outputs (--v=1).
-TEST(WASAPIAudioOutputStreamTest, ExclusiveModeBufferSizesAt48kHz) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get()) &&
+TEST_F(WASAPIAudioOutputStreamTest, ExclusiveModeBufferSizesAt48kHz) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get()) &&
ExclusiveModeIsEnabled());
- AudioOutputStreamWrapper aosw(audio_manager.get());
+ AudioOutputStreamWrapper aosw(audio_manager_.get());
// 10ms @ 48kHz shall work.
// Note that, this is the same size as we can use for shared-mode streaming
@@ -498,12 +500,11 @@ TEST(WASAPIAudioOutputStreamTest, ExclusiveModeBufferSizesAt48kHz) {
// certain set of audio parameters and a sample rate of 44.1kHz.
// The expected outcomes of each setting in this test has been derived
// manually using log outputs (--v=1).
-TEST(WASAPIAudioOutputStreamTest, ExclusiveModeBufferSizesAt44kHz) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get()) &&
+TEST_F(WASAPIAudioOutputStreamTest, ExclusiveModeBufferSizesAt44kHz) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get()) &&
ExclusiveModeIsEnabled());
- AudioOutputStreamWrapper aosw(audio_manager.get());
+ AudioOutputStreamWrapper aosw(audio_manager_.get());
// 10ms @ 44.1kHz does not work due to misalignment.
// This test will propose an aligned buffer size of 10.1587ms.
@@ -553,9 +554,8 @@ TEST(WASAPIAudioOutputStreamTest, ExclusiveModeBufferSizesAt44kHz) {
// Verify that we can open and start the output stream in exclusive mode at
// the lowest possible delay at 48kHz.
-TEST(WASAPIAudioOutputStreamTest, ExclusiveModeMinBufferSizeAt48kHz) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get()) &&
+TEST_F(WASAPIAudioOutputStreamTest, ExclusiveModeMinBufferSizeAt48kHz) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get()) &&
ExclusiveModeIsEnabled());
base::MessageLoopForUI loop;
@@ -563,7 +563,7 @@ TEST(WASAPIAudioOutputStreamTest, ExclusiveModeMinBufferSizeAt48kHz) {
// Create exclusive-mode WASAPI output stream which plays out in stereo
// using the minimum buffer size at 48kHz sample rate.
- AudioOutputStreamWrapper aosw(audio_manager.get());
+ AudioOutputStreamWrapper aosw(audio_manager_.get());
AudioOutputStream* aos = aosw.Create(48000, 160);
EXPECT_TRUE(aos->Open());
@@ -588,16 +588,15 @@ TEST(WASAPIAudioOutputStreamTest, ExclusiveModeMinBufferSizeAt48kHz) {
// Verify that we can open and start the output stream in exclusive mode at
// the lowest possible delay at 44.1kHz.
-TEST(WASAPIAudioOutputStreamTest, ExclusiveModeMinBufferSizeAt44kHz) {
+TEST_F(WASAPIAudioOutputStreamTest, ExclusiveModeMinBufferSizeAt44kHz) {
ABORT_AUDIO_TEST_IF_NOT(ExclusiveModeIsEnabled());
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
base::MessageLoopForUI loop;
MockAudioSourceCallback source;
// Create exclusive-mode WASAPI output stream which plays out in stereo
// using the minimum buffer size at 44.1kHz sample rate.
- AudioOutputStreamWrapper aosw(audio_manager.get());
+ AudioOutputStreamWrapper aosw(audio_manager_.get());
AudioOutputStream* aos = aosw.Create(44100, 160);
EXPECT_TRUE(aos->Open());
diff --git a/media/audio/win/audio_manager_win.h b/media/audio/win/audio_manager_win.h
index 9826566..afd1ef9 100644
--- a/media/audio/win/audio_manager_win.h
+++ b/media/audio/win/audio_manager_win.h
@@ -64,9 +64,7 @@ class MEDIA_EXPORT AudioManagerWin : public AudioManagerBase {
EnumerationType enumeration_type_;
EnumerationType enumeration_type() { return enumeration_type_; }
- void SetEnumerationType(EnumerationType type) {
- enumeration_type_ = type;
- }
+ void set_enumeration_type(EnumerationType type) { enumeration_type_ = type; }
inline bool core_audio_supported() const {
return enumeration_type_ == kMMDeviceEnumeration;
diff --git a/media/audio/win/audio_output_win_unittest.cc b/media/audio/win/audio_output_win_unittest.cc
index 93454fc..c1dc5b4 100644
--- a/media/audio/win/audio_output_win_unittest.cc
+++ b/media/audio/win/audio_output_win_unittest.cc
@@ -427,7 +427,7 @@ TEST(WinAudioTest, PCMWaveStreamPlay200HzToneLowLatency) {
ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
// The WASAPI API requires a correct COM environment.
- ScopedCOMInitializer com_init(ScopedCOMInitializer::kMTA);
+ ScopedCOMInitializer com_init;
// Use 10 ms buffer size for WASAPI and 50 ms buffer size for Wave.
// Take the existing native sample rate into account.
diff --git a/media/audio/win/core_audio_util_win.cc b/media/audio/win/core_audio_util_win.cc
index 53530df..4f72564 100644
--- a/media/audio/win/core_audio_util_win.cc
+++ b/media/audio/win/core_audio_util_win.cc
@@ -178,10 +178,12 @@ static ScopedComPtr<IMMDeviceEnumerator> CreateDeviceEnumeratorInternal() {
// fail with CO_E_NOTINITIALIZED in combination with certain 3rd party
// modules. Calling CoInitializeEx is an attempt to resolve the reported
// issues. See http://crbug.com/378465 for details.
- hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
+ hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (SUCCEEDED(hr)) {
- hr = device_enumerator.CreateInstance(__uuidof(MMDeviceEnumerator),
- NULL, CLSCTX_INPROC_SERVER);
+ hr = device_enumerator.CreateInstance(__uuidof(MMDeviceEnumerator), NULL,
+ CLSCTX_INPROC_SERVER);
+ } else {
+ LOG(ERROR) << "CoCreateInstance still failed! " << std::hex << hr;
}
}
return device_enumerator;
diff --git a/media/audio/win/core_audio_util_win_unittest.cc b/media/audio/win/core_audio_util_win_unittest.cc
index 31f91e9..1a24e5d 100644
--- a/media/audio/win/core_audio_util_win_unittest.cc
+++ b/media/audio/win/core_audio_util_win_unittest.cc
@@ -19,13 +19,10 @@ namespace media {
class CoreAudioUtilWinTest : public ::testing::Test {
protected:
- // The test runs on a COM thread in the multithreaded apartment (MTA).
+ // The test runs on a COM thread in the singlethreaded apartment (STA).
// If we don't initialize the COM library on a thread before using COM,
// all function calls will return CO_E_NOTINITIALIZED.
- CoreAudioUtilWinTest()
- : com_init_(ScopedCOMInitializer::kMTA) {
- DCHECK(com_init_.succeeded());
- }
+ CoreAudioUtilWinTest() { DCHECK(com_init_.succeeded()); }
virtual ~CoreAudioUtilWinTest() {}
bool DevicesAvailable() {
diff --git a/media/audio/win/device_enumeration_win.h b/media/audio/win/device_enumeration_win.h
index e61a331..e6485db 100644
--- a/media/audio/win/device_enumeration_win.h
+++ b/media/audio/win/device_enumeration_win.h
@@ -17,7 +17,7 @@ namespace media {
// Example record in the output list:
// - device_name: "Microphone (Realtek High Definition Audio)".
// - unique_id: "{0.0.1.00000000}.{8db6020f-18e3-4f25-b6f5-7726c9122574}"
-// This method must be called from a COM thread using MTA.
+// This method must be called from a COM thread using STA.
bool GetInputDeviceNamesWin(media::AudioDeviceNames* device_names);
bool GetOutputDeviceNamesWin(media::AudioDeviceNames* device_names);