summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/browser_process.h3
-rw-r--r--chrome/browser/browser_process_impl.cc9
-rw-r--r--chrome/browser/browser_process_impl.h3
-rw-r--r--chrome/browser/profiles/profile_io_data.cc6
-rw-r--r--chrome/browser/profiles/profile_io_data.h2
-rw-r--r--chrome/browser/speech/chrome_speech_input_manager.cc19
-rw-r--r--chrome/browser/speech/chrome_speech_input_manager.h3
-rw-r--r--chrome/browser/speech/speech_input_bubble_gtk.cc20
-rw-r--r--chrome/browser/speech/speech_input_bubble_views.cc6
-rw-r--r--chrome/browser/speech/speech_input_extension_manager.cc15
-rw-r--r--chrome/test/base/testing_browser_process.cc4
-rw-r--r--chrome/test/base/testing_browser_process.h1
-rw-r--r--content/browser/renderer_host/media/audio_input_device_manager.cc7
-rw-r--r--content/browser/renderer_host/media/audio_input_device_manager.h5
-rw-r--r--content/browser/renderer_host/media/audio_input_device_manager_unittest.cc52
-rw-r--r--content/browser/renderer_host/media/audio_input_renderer_host.cc1
-rw-r--r--content/browser/renderer_host/media/audio_renderer_host.cc15
-rw-r--r--content/browser/renderer_host/media/audio_renderer_host_unittest.cc28
-rw-r--r--content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc6
-rw-r--r--content/browser/renderer_host/media/media_stream_manager.cc9
-rw-r--r--content/browser/renderer_host/media/media_stream_manager.h6
-rw-r--r--content/browser/renderer_host/media/video_capture_host_unittest.cc7
-rw-r--r--content/browser/renderer_host/render_process_host_impl.cc92
-rw-r--r--content/browser/resource_context.cc16
-rw-r--r--content/browser/resource_context.h5
-rw-r--r--content/browser/speech/speech_input_browsertest.cc51
-rw-r--r--content/browser/speech/speech_input_dispatcher_host.cc11
-rw-r--r--content/browser/speech/speech_input_dispatcher_host.h8
-rw-r--r--content/browser/speech/speech_input_manager.cc55
-rw-r--r--content/browser/speech/speech_input_manager.h15
-rw-r--r--content/browser/speech/speech_recognizer.cc7
-rw-r--r--content/browser/speech/speech_recognizer.h4
-rw-r--r--content/browser/speech/speech_recognizer_unittest.cc10
-rw-r--r--content/renderer/media/webrtc_audio_device_unittest.cc45
-rw-r--r--content/test/webrtc_audio_device_test.cc83
-rw-r--r--content/test/webrtc_audio_device_test.h22
-rw-r--r--media/audio/android/audio_manager_android.cc3
-rw-r--r--media/audio/audio_input_controller.cc25
-rw-r--r--media/audio/audio_input_controller.h13
-rw-r--r--media/audio/audio_input_controller_unittest.cc15
-rw-r--r--media/audio/audio_input_device_unittest.cc48
-rw-r--r--media/audio/audio_input_unittest.cc44
-rw-r--r--media/audio/audio_manager.cc45
-rw-r--r--media/audio/audio_manager.h48
-rw-r--r--media/audio/audio_manager_base.cc79
-rw-r--r--media/audio/audio_manager_base.h28
-rw-r--r--media/audio/audio_output_controller.cc67
-rw-r--r--media/audio/audio_output_controller.h29
-rw-r--r--media/audio/audio_output_controller_unittest.cc77
-rw-r--r--media/audio/audio_output_dispatcher.cc46
-rw-r--r--media/audio/audio_output_dispatcher.h41
-rw-r--r--media/audio/audio_output_proxy.cc13
-rw-r--r--media/audio/audio_output_proxy.h11
-rw-r--r--media/audio/audio_output_proxy_unittest.cc32
-rw-r--r--media/audio/linux/alsa_input.cc12
-rw-r--r--media/audio/linux/alsa_input.h10
-rw-r--r--media/audio/linux/alsa_output_unittest.cc31
-rw-r--r--media/audio/linux/audio_manager_linux.cc37
-rw-r--r--media/audio/linux/audio_manager_linux.h5
-rw-r--r--media/audio/mac/audio_low_latency_input_mac_unittest.cc93
-rw-r--r--media/audio/mac/audio_manager_mac.cc3
-rw-r--r--media/audio/mac/audio_output_mac_unittest.cc18
-rw-r--r--media/audio/openbsd/audio_manager_openbsd.cc2
-rw-r--r--media/audio/simple_sources_unittest.cc5
-rw-r--r--media/audio/test_audio_input_controller_factory.cc7
-rw-r--r--media/audio/test_audio_input_controller_factory.h2
-rw-r--r--media/audio/win/audio_low_latency_input_win_unittest.cc55
-rw-r--r--media/audio/win/audio_low_latency_output_win_unittest.cc81
-rw-r--r--media/audio/win/audio_manager_win.cc2
-rw-r--r--media/audio/win/audio_output_win_unittest.cc47
-rw-r--r--media/filters/reference_audio_renderer.cc8
-rw-r--r--media/filters/reference_audio_renderer.h9
-rw-r--r--media/tools/player_wtl/movie.cc7
-rw-r--r--media/tools/player_wtl/movie.h4
-rw-r--r--media/tools/player_x11/player_x11.cc25
75 files changed, 1061 insertions, 717 deletions
diff --git a/chrome/browser/browser_process.h b/chrome/browser/browser_process.h
index abc4e14..ac56561 100644
--- a/chrome/browser/browser_process.h
+++ b/chrome/browser/browser_process.h
@@ -18,6 +18,7 @@
#include "base/memory/ref_counted.h"
#include "ipc/ipc_message.h"
+class AudioManager;
class AutomationProviderList;
class BackgroundModeManager;
class ChromeNetLog;
@@ -202,6 +203,8 @@ class BrowserProcess {
virtual CRLSetFetcher* crl_set_fetcher() = 0;
+ virtual AudioManager* audio_manager() = 0;
+
private:
DISALLOW_COPY_AND_ASSIGN(BrowserProcess);
};
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index cb752ff..a5ee0be 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -81,6 +81,7 @@
#include "content/public/browser/notification_details.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/url_fetcher.h"
+#include "media/audio/audio_manager.h"
#include "net/socket/client_socket_pool_manager.h"
#include "net/url_request/url_request_context_getter.h"
#include "ui/base/clipboard/clipboard.h"
@@ -702,6 +703,14 @@ CRLSetFetcher* BrowserProcessImpl::crl_set_fetcher() {
#endif
}
+AudioManager* BrowserProcessImpl::audio_manager() {
+ DCHECK(CalledOnValidThread());
+ if (!audio_manager_)
+ audio_manager_ = AudioManager::Create();
+
+ return audio_manager_;
+}
+
void BrowserProcessImpl::CreateResourceDispatcherHost() {
DCHECK(!created_resource_dispatcher_host_ &&
resource_dispatcher_host_.get() == NULL);
diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_process_impl.h
index cc7fa00..dc7b932 100644
--- a/chrome/browser/browser_process_impl.h
+++ b/chrome/browser/browser_process_impl.h
@@ -125,6 +125,7 @@ class BrowserProcessImpl : public BrowserProcess,
virtual MHTMLGenerationManager* mhtml_generation_manager() OVERRIDE;
virtual ComponentUpdateService* component_updater() OVERRIDE;
virtual CRLSetFetcher* crl_set_fetcher() OVERRIDE;
+ virtual AudioManager* audio_manager() OVERRIDE;
private:
// Must be called right before the IO thread is started.
@@ -282,6 +283,8 @@ class BrowserProcessImpl : public BrowserProcess,
scoped_refptr<CRLSetFetcher> crl_set_fetcher_;
#endif
+ scoped_refptr<AudioManager> audio_manager_;
+
DISALLOW_COPY_AND_ASSIGN(BrowserProcessImpl);
};
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc
index 9c0a285..d92f4ce 100644
--- a/chrome/browser/profiles/profile_io_data.cc
+++ b/chrome/browser/profiles/profile_io_data.cc
@@ -52,6 +52,7 @@
#include "content/browser/resource_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
+#include "media/audio/audio_manager.h"
#include "net/base/origin_bound_cert_service.h"
#include "net/http/http_transaction_factory.h"
#include "net/http/http_util.h"
@@ -223,6 +224,7 @@ void ProfileIOData::InitializeOnUIThread(Profile* profile) {
params->referrer_charset = default_charset;
params->io_thread = g_browser_process->io_thread();
+ params->audio_manager = g_browser_process->audio_manager();
params->host_content_settings_map = profile->GetHostContentSettingsMap();
params->cookie_settings = CookieSettings::GetForProfile(profile);
@@ -496,7 +498,8 @@ void ProfileIOData::LazyInitialize() const {
job_factory_->AddInterceptor(new chromeos::GViewRequestInterceptor);
#endif // defined(OS_CHROMEOS) && !defined(GOOGLE_CHROME_BUILD)
- media_stream_manager_.reset(new media_stream::MediaStreamManager);
+ media_stream_manager_.reset(
+ new media_stream::MediaStreamManager(profile_params_->audio_manager));
// Take ownership over these parameters.
database_tracker_ = profile_params_->database_tracker;
@@ -523,6 +526,7 @@ void ProfileIOData::LazyInitialize() const {
io_thread_globals->media.media_internals.get());
resource_context_.set_download_id_factory(download_id_factory_);
resource_context_.set_media_stream_manager(media_stream_manager_.get());
+ resource_context_.set_audio_manager(profile_params_->audio_manager);
LazyInitializeInternal(profile_params_.get());
diff --git a/chrome/browser/profiles/profile_io_data.h b/chrome/browser/profiles/profile_io_data.h
index 5bd4088..2bed053 100644
--- a/chrome/browser/profiles/profile_io_data.h
+++ b/chrome/browser/profiles/profile_io_data.h
@@ -20,6 +20,7 @@
#include "content/browser/resource_context.h"
#include "net/base/cookie_monster.h"
+class AudioManager;
class ChromeAppCacheService;
class ChromeBlobStorageContext;
class CookieSettings;
@@ -147,6 +148,7 @@ class ProfileIOData {
std::string accept_charset;
std::string referrer_charset;
IOThread* io_thread;
+ scoped_refptr<AudioManager> audio_manager;
scoped_refptr<HostContentSettingsMap> host_content_settings_map;
scoped_refptr<CookieSettings> cookie_settings;
scoped_refptr<HostZoomMap> host_zoom_map;
diff --git a/chrome/browser/speech/chrome_speech_input_manager.cc b/chrome/browser/speech/chrome_speech_input_manager.cc
index b4e969e..90dbf06 100644
--- a/chrome/browser/speech/chrome_speech_input_manager.cc
+++ b/chrome/browser/speech/chrome_speech_input_manager.cc
@@ -12,8 +12,10 @@
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/tab_contents/tab_util.h"
#include "chrome/common/pref_names.h"
+#include "content/browser/resource_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/speech_input_result.h"
#include "grit/generated_resources.h"
@@ -35,7 +37,10 @@ namespace speech_input {
class ChromeSpeechInputManager::OptionalRequestInfo
: public base::RefCountedThreadSafe<OptionalRequestInfo> {
public:
- OptionalRequestInfo() : can_report_metrics_(false) {}
+ explicit OptionalRequestInfo(AudioManager* audio_manager)
+ : can_report_metrics_(false), audio_manager_(audio_manager) {
+ DCHECK(audio_manager_); // Fail early.
+ }
void Refresh() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
@@ -61,10 +66,10 @@ class ChromeSpeechInputManager::OptionalRequestInfo
#if defined(OS_WIN)
value_ = UTF16ToUTF8(
installer::WMIComputerSystem::GetModel() + L"|" +
- AudioManager::GetAudioManager()->GetAudioInputDeviceModel());
+ audio_manager_->GetAudioInputDeviceModel());
#else // defined(OS_WIN)
value_ = UTF16ToUTF8(
- AudioManager::GetAudioManager()->GetAudioInputDeviceModel());
+ audio_manager_->GetAudioInputDeviceModel());
#endif // defined(OS_WIN)
}
@@ -86,6 +91,7 @@ class ChromeSpeechInputManager::OptionalRequestInfo
base::Lock lock_;
std::string value_;
bool can_report_metrics_;
+ scoped_refptr<AudioManager> audio_manager_;
DISALLOW_COPY_AND_ASSIGN(OptionalRequestInfo);
};
@@ -112,9 +118,12 @@ void ChromeSpeechInputManager::ShowRecognitionRequested(
}
void ChromeSpeechInputManager::GetRequestInfo(
- bool* can_report_metrics, std::string* request_info) {
+ AudioManager* audio_manager,
+ bool* can_report_metrics,
+ std::string* request_info) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (!optional_request_info_.get()) {
- optional_request_info_ = new OptionalRequestInfo();
+ optional_request_info_ = new OptionalRequestInfo(audio_manager);
// Since hardware info is optional with speech input requests, we start an
// asynchronous fetch here and move on with recording audio. This first
// speech input request would send an empty string for hardware info and
diff --git a/chrome/browser/speech/chrome_speech_input_manager.h b/chrome/browser/speech/chrome_speech_input_manager.h
index 09483b1..627c750 100644
--- a/chrome/browser/speech/chrome_speech_input_manager.h
+++ b/chrome/browser/speech/chrome_speech_input_manager.h
@@ -27,7 +27,8 @@ class ChromeSpeechInputManager : public SpeechInputManager,
protected:
// SpeechInputManager methods.
- virtual void GetRequestInfo(bool* can_report_metrics,
+ virtual void GetRequestInfo(AudioManager* audio_manager,
+ bool* can_report_metrics,
std::string* request_info) OVERRIDE;
virtual void ShowRecognitionRequested(int caller_id,
int render_process_id,
diff --git a/chrome/browser/speech/speech_input_bubble_gtk.cc b/chrome/browser/speech/speech_input_bubble_gtk.cc
index 55efc47..842b558 100644
--- a/chrome/browser/speech/speech_input_bubble_gtk.cc
+++ b/chrome/browser/speech/speech_input_bubble_gtk.cc
@@ -14,6 +14,8 @@
#include "chrome/browser/ui/gtk/gtk_theme_service.h"
#include "chrome/browser/ui/gtk/gtk_util.h"
#include "chrome/browser/ui/gtk/location_bar_view_gtk.h"
+#include "content/browser/resource_context.h"
+#include "content/browser/speech/speech_input_manager.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
@@ -107,7 +109,8 @@ void SpeechInputBubbleGtk::OnTryAgainClicked(GtkWidget* widget) {
}
void SpeechInputBubbleGtk::OnMicSettingsClicked(GtkWidget* widget) {
- AudioManager::GetAudioManager()->ShowAudioInputSettings();
+ speech_input::SpeechInputManager::ShowAudioInputSettingsFromUI(
+ &tab_contents()->browser_context()->GetResourceContext());
Hide();
}
@@ -133,7 +136,14 @@ void SpeechInputBubbleGtk::Show() {
gtk_box_pack_start(GTK_BOX(vbox), label_, FALSE, FALSE,
kBubbleControlVerticalSpacing);
- if (AudioManager::GetAudioManager()->CanShowAudioInputSettings()) {
+ Profile* profile = Profile::FromBrowserContext(
+ tab_contents()->browser_context());
+
+ // TODO(tommi): The audio_manager property can only be accessed from the
+ // IO thread, so we can't call CanShowAudioInputSettings directly here if
+ // we can show the input settings. For now, we always show the link (like
+ // we do on other platforms).
+ if (true) {
mic_settings_ = gtk_chrome_link_button_new(
l10n_util::GetStringUTF8(IDS_SPEECH_INPUT_MIC_SETTINGS).c_str());
gtk_box_pack_start(GTK_BOX(vbox), mic_settings_, FALSE, FALSE,
@@ -164,8 +174,6 @@ void SpeechInputBubbleGtk::Show() {
kBubbleControlHorizontalSpacing, kBubbleControlHorizontalSpacing);
gtk_container_add(GTK_CONTAINER(content), vbox);
- Profile* profile =
- Profile::FromBrowserContext(tab_contents()->browser_context());
GtkThemeService* theme_provider = GtkThemeService::GetFrom(profile);
GtkWidget* reference_widget = tab_contents()->GetNativeView();
gfx::Rect container_rect;
@@ -190,8 +198,8 @@ void SpeechInputBubbleGtk::Show() {
&target_rect,
content,
BubbleGtk::ARROW_LOCATION_TOP_LEFT,
- false, // match_system_theme
- true, // grab_input
+ false, // match_system_theme
+ true, // grab_input
theme_provider,
this);
diff --git a/chrome/browser/speech/speech_input_bubble_views.cc b/chrome/browser/speech/speech_input_bubble_views.cc
index 8ece4d9..6e4025c 100644
--- a/chrome/browser/speech/speech_input_bubble_views.cc
+++ b/chrome/browser/speech/speech_input_bubble_views.cc
@@ -12,11 +12,12 @@
#include "chrome/browser/ui/views/location_bar/location_icon_view.h"
#include "chrome/browser/ui/views/toolbar_view.h"
#include "chrome/browser/ui/views/window.h"
+#include "content/browser/resource_context.h"
+#include "content/browser/speech/speech_input_manager.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "content/browser/tab_contents/tab_contents_view.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
-#include "media/audio/audio_manager.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/views/bubble/bubble_delegate.h"
@@ -204,7 +205,8 @@ void SpeechInputBubbleView::ButtonPressed(views::Button* source,
void SpeechInputBubbleView::LinkClicked(views::Link* source, int event_flags) {
DCHECK_EQ(source, mic_settings_);
- AudioManager::GetAudioManager()->ShowAudioInputSettings();
+ speech_input::SpeechInputManager::ShowAudioInputSettingsFromUI(
+ &tab_contents_->browser_context()->GetResourceContext());
}
gfx::Size SpeechInputBubbleView::GetPreferredSize() {
diff --git a/chrome/browser/speech/speech_input_extension_manager.cc b/chrome/browser/speech/speech_input_extension_manager.cc
index 0c62408..146d2993 100644
--- a/chrome/browser/speech/speech_input_extension_manager.cc
+++ b/chrome/browser/speech/speech_input_extension_manager.cc
@@ -19,12 +19,13 @@
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/pref_names.h"
+#include "content/browser/resource_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "content/public/common/speech_input_result.h"
using content::BrowserThread;
-using namespace speech_input;
+using speech_input::SpeechRecognizer;
namespace {
@@ -74,7 +75,6 @@ class SpeechInputExtensionManagerWrapper : public ProfileKeyedService {
scoped_refptr<SpeechInputExtensionManager> manager_;
};
-
}
// Factory for SpeechInputExtensionManagers as profile keyed services.
@@ -151,7 +151,7 @@ SpeechInputExtensionManager::~SpeechInputExtensionManager() {
SpeechInputExtensionManager* SpeechInputExtensionManager::GetForProfile(
Profile* profile) {
- SpeechInputExtensionManagerWrapper *wrapper =
+ SpeechInputExtensionManagerWrapper* wrapper =
Factory::GetInstance()->GetForProfile(profile);
if (!wrapper)
return NULL;
@@ -462,7 +462,7 @@ void SpeechInputExtensionManager::DispatchError(
// Used for errors that are also reported via the onError event.
if (dispatch_event) {
ListValue args;
- DictionaryValue *js_error = new DictionaryValue();
+ DictionaryValue* js_error = new DictionaryValue();
args.Append(js_error);
js_error->SetString(kErrorCodeKey, error);
std::string json_args;
@@ -546,12 +546,12 @@ void SpeechInputExtensionManager::StartOnIOThread(
}
bool SpeechInputExtensionManager::HasAudioInputDevices() {
- return AudioManager::GetAudioManager()->HasAudioInputDevices();
+ return profile_->GetResourceContext().audio_manager()->HasAudioInputDevices();
}
bool SpeechInputExtensionManager::IsRecordingInProcess() {
// Thread-safe query.
- return AudioManager::GetAudioManager()->IsRecordingInProcess();
+ return profile_->GetResourceContext().audio_manager()->IsRecordingInProcess();
}
bool SpeechInputExtensionManager::IsRecording() {
@@ -565,7 +565,8 @@ void SpeechInputExtensionManager::StartRecording(
bool filter_profanities) {
DCHECK(!recognizer_);
recognizer_ = new SpeechRecognizer(delegate, caller_id, language, grammar,
- context_getter, filter_profanities, "", "");
+ context_getter, profile_->GetResourceContext().audio_manager(),
+ filter_profanities, "", "");
recognizer_->StartRecording();
}
diff --git a/chrome/test/base/testing_browser_process.cc b/chrome/test/base/testing_browser_process.cc
index fc6af74..9df1a4d 100644
--- a/chrome/test/base/testing_browser_process.cc
+++ b/chrome/test/base/testing_browser_process.cc
@@ -226,6 +226,10 @@ CRLSetFetcher* TestingBrowserProcess::crl_set_fetcher() {
return NULL;
}
+AudioManager* TestingBrowserProcess::audio_manager() {
+ return NULL;
+}
+
void TestingBrowserProcess::SetLocalState(PrefService* local_state) {
if (!local_state && notification_ui_manager_.get())
notification_ui_manager_.reset(); // Used local_state_.
diff --git a/chrome/test/base/testing_browser_process.h b/chrome/test/base/testing_browser_process.h
index 57587ea..c434ca6 100644
--- a/chrome/test/base/testing_browser_process.h
+++ b/chrome/test/base/testing_browser_process.h
@@ -102,6 +102,7 @@ class TestingBrowserProcess : public BrowserProcess {
virtual MHTMLGenerationManager* mhtml_generation_manager() OVERRIDE;
virtual ComponentUpdateService* component_updater() OVERRIDE;
virtual CRLSetFetcher* crl_set_fetcher() OVERRIDE;
+ virtual AudioManager* audio_manager() OVERRIDE;
// Set the local state for tests. Consumer is responsible for cleaning it up
// afterwards (using ScopedTestingLocalState, for example).
diff --git a/content/browser/renderer_host/media/audio_input_device_manager.cc b/content/browser/renderer_host/media/audio_input_device_manager.cc
index 08469bf..b664090 100644
--- a/content/browser/renderer_host/media/audio_input_device_manager.cc
+++ b/content/browser/renderer_host/media/audio_input_device_manager.cc
@@ -21,9 +21,10 @@ const char AudioInputDeviceManager::kInvalidDeviceId[] = "";
// Starting id for the first capture session.
const int kFirstSessionId = AudioInputDeviceManager::kFakeOpenSessionId + 1;
-AudioInputDeviceManager::AudioInputDeviceManager()
+AudioInputDeviceManager::AudioInputDeviceManager(AudioManager* audio_manager)
: listener_(NULL),
- next_capture_session_id_(kFirstSessionId) {
+ next_capture_session_id_(kFirstSessionId),
+ audio_manager_(audio_manager) {
}
AudioInputDeviceManager::~AudioInputDeviceManager() {
@@ -46,7 +47,7 @@ void AudioInputDeviceManager::EnumerateDevices() {
DCHECK(listener_);
media::AudioDeviceNames device_names;
- AudioManager::GetAudioManager()->GetAudioInputDeviceNames(&device_names);
+ audio_manager_->GetAudioInputDeviceNames(&device_names);
StreamDeviceInfoArray* devices = new StreamDeviceInfoArray;
for (media::AudioDeviceNames::iterator it = device_names.begin();
diff --git a/content/browser/renderer_host/media/audio_input_device_manager.h b/content/browser/renderer_host/media/audio_input_device_manager.h
index e861499..2f21583 100644
--- a/content/browser/renderer_host/media/audio_input_device_manager.h
+++ b/content/browser/renderer_host/media/audio_input_device_manager.h
@@ -20,6 +20,8 @@
#include "content/common/media/media_stream_options.h"
#include "media/audio/audio_device_name.h"
+class AudioManager;
+
namespace media_stream {
class AudioInputDeviceManagerEventHandler;
@@ -34,7 +36,7 @@ class CONTENT_EXPORT AudioInputDeviceManager : public MediaStreamProvider {
static const int kInvalidSessionId;
static const char kInvalidDeviceId[];
- AudioInputDeviceManager();
+ explicit AudioInputDeviceManager(AudioManager* audio_manager);
virtual ~AudioInputDeviceManager();
// MediaStreamProvider implementation, called on IO thread.
@@ -64,6 +66,7 @@ class CONTENT_EXPORT AudioInputDeviceManager : public MediaStreamProvider {
EventHandlerMap event_handlers_;
typedef std::map<int, media::AudioDeviceName> AudioInputDeviceMap;
AudioInputDeviceMap devices_;
+ scoped_refptr<AudioManager> audio_manager_;
DISALLOW_COPY_AND_ASSIGN(AudioInputDeviceManager);
};
diff --git a/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc b/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
index e36ff92..337d655 100644
--- a/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
+++ b/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
@@ -14,13 +14,13 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-using ::testing::_;
-using ::testing::AnyNumber;
-using ::testing::InSequence;
-using ::testing::Return;
using content::BrowserThread;
-
using content::BrowserThreadImpl;
+using media_stream::AudioInputDeviceManager;
+using testing::_;
+using testing::AnyNumber;
+using testing::InSequence;
+using testing::Return;
namespace media_stream {
@@ -80,26 +80,23 @@ class MockAudioInputDeviceManagerEventHandler
DISALLOW_COPY_AND_ASSIGN(MockAudioInputDeviceManagerEventHandler);
};
-// Returns true if machine has audio input device, else returns false.
-static bool CanRunAudioInputDeviceTests() {
- AudioManager* audio_manager = AudioManager::GetAudioManager();
- if (!audio_manager)
- return false;
-
- return audio_manager->HasAudioInputDevices();
-}
-
ACTION_P(ExitMessageLoop, message_loop) {
message_loop->PostTask(FROM_HERE, MessageLoop::QuitClosure());
}
-class AudioInputDeviceManagerTest: public testing::Test {
+class AudioInputDeviceManagerTest : public testing::Test {
public:
AudioInputDeviceManagerTest()
: message_loop_(),
io_thread_(),
manager_(),
- audio_input_listener_() {}
+ audio_input_listener_() {
+ }
+
+ // Returns true iff machine has an audio input device.
+ bool CanRunAudioInputDeviceTests() {
+ return audio_manager_->HasAudioInputDevices();
+ }
protected:
virtual void SetUp() {
@@ -107,7 +104,9 @@ class AudioInputDeviceManagerTest: public testing::Test {
message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO));
io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
message_loop_.get()));
- manager_.reset(new media_stream::AudioInputDeviceManager());
+ audio_manager_ = AudioManager::Create();
+
+ manager_.reset(new AudioInputDeviceManager(audio_manager_));
audio_input_listener_.reset(new MockAudioInputDeviceManagerListener());
manager_->Register(audio_input_listener_.get());
@@ -129,6 +128,7 @@ class AudioInputDeviceManagerTest: public testing::Test {
scoped_ptr<BrowserThreadImpl> io_thread_;
scoped_ptr<AudioInputDeviceManager> manager_;
scoped_ptr<MockAudioInputDeviceManagerListener> audio_input_listener_;
+ scoped_refptr<AudioManager> audio_manager_;
private:
DISALLOW_COPY_AND_ASSIGN(AudioInputDeviceManagerTest);
@@ -138,6 +138,9 @@ class AudioInputDeviceManagerTest: public testing::Test {
TEST_F(AudioInputDeviceManagerTest, OpenAndCloseDevice) {
if (!CanRunAudioInputDeviceTests())
return;
+
+ ASSERT_FALSE(audio_input_listener_->devices_.empty());
+
InSequence s;
for (StreamDeviceInfoArray::const_iterator iter =
@@ -162,6 +165,9 @@ TEST_F(AudioInputDeviceManagerTest, OpenAndCloseDevice) {
TEST_F(AudioInputDeviceManagerTest, OpenMultipleDevices) {
if (!CanRunAudioInputDeviceTests())
return;
+
+ ASSERT_FALSE(audio_input_listener_->devices_.empty());
+
InSequence s;
int index = 0;
@@ -225,6 +231,9 @@ TEST_F(AudioInputDeviceManagerTest, OpenNotExistingDevice) {
TEST_F(AudioInputDeviceManagerTest, OpenDeviceTwice) {
if (!CanRunAudioInputDeviceTests())
return;
+
+ ASSERT_FALSE(audio_input_listener_->devices_.empty());
+
InSequence s;
// Opens and closes the default device twice.
@@ -254,6 +263,9 @@ TEST_F(AudioInputDeviceManagerTest, OpenDeviceTwice) {
TEST_F(AudioInputDeviceManagerTest, StartAndStopSession) {
if (!CanRunAudioInputDeviceTests())
return;
+
+ ASSERT_FALSE(audio_input_listener_->devices_.empty());
+
InSequence s;
int index = 0;
@@ -297,6 +309,9 @@ TEST_F(AudioInputDeviceManagerTest, StartAndStopSession) {
TEST_F(AudioInputDeviceManagerTest, CloseWithoutStopSession) {
if (!CanRunAudioInputDeviceTests())
return;
+
+ ASSERT_FALSE(audio_input_listener_->devices_.empty());
+
InSequence s;
int index = 0;
@@ -343,6 +358,9 @@ TEST_F(AudioInputDeviceManagerTest, CloseWithoutStopSession) {
TEST_F(AudioInputDeviceManagerTest, StartDeviceTwice) {
if (!CanRunAudioInputDeviceTests())
return;
+
+ ASSERT_FALSE(audio_input_listener_->devices_.empty());
+
InSequence s;
// Create one EventHandler for each session.
diff --git a/content/browser/renderer_host/media/audio_input_renderer_host.cc b/content/browser/renderer_host/media/audio_input_renderer_host.cc
index 6a3e146..8d5131c 100644
--- a/content/browser/renderer_host/media/audio_input_renderer_host.cc
+++ b/content/browser/renderer_host/media/audio_input_renderer_host.cc
@@ -246,6 +246,7 @@ void AudioInputRendererHost::OnCreateStream(
// entry and construct an AudioInputController.
entry->writer.reset(writer.release());
entry->controller = media::AudioInputController::CreateLowLatency(
+ resource_context_->audio_manager(),
this,
audio_params,
device_id,
diff --git a/content/browser/renderer_host/media/audio_renderer_host.cc b/content/browser/renderer_host/media/audio_renderer_host.cc
index 2b2aa07..4d331b8 100644
--- a/content/browser/renderer_host/media/audio_renderer_host.cc
+++ b/content/browser/renderer_host/media/audio_renderer_host.cc
@@ -270,13 +270,15 @@ void AudioRendererHost::OnCreateStream(
// entry and construct an AudioOutputController.
entry->reader.reset(reader.release());
entry->controller =
- media::AudioOutputController::CreateLowLatency(this, audio_params,
- entry->reader.get());
+ media::AudioOutputController::CreateLowLatency(
+ resource_context_->audio_manager(), this, audio_params,
+ entry->reader.get());
} else {
// The choice of buffer capacity is based on experiment.
entry->controller =
- media::AudioOutputController::Create(this, audio_params,
- 3 * packet_size);
+ media::AudioOutputController::Create(
+ resource_context_->audio_manager(), this, audio_params,
+ 3 * packet_size);
}
if (!entry->controller) {
@@ -399,6 +401,8 @@ void AudioRendererHost::DeleteEntries() {
}
void AudioRendererHost::CloseAndDeleteStream(AudioEntry* entry) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
if (!entry->pending_close) {
entry->controller->Close(
base::Bind(&AudioRendererHost::OnStreamClosed, this, entry));
@@ -407,7 +411,8 @@ void AudioRendererHost::CloseAndDeleteStream(AudioEntry* entry) {
}
void AudioRendererHost::OnStreamClosed(AudioEntry* entry) {
- // Delete the entry after we've closed the stream.
+ // Delete the entry on the IO thread after we've closed the stream.
+ // (We're currently on the audio thread).
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&AudioRendererHost::DeleteEntry, this, entry));
diff --git a/content/browser/renderer_host/media/audio_renderer_host_unittest.cc b/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
index 4d62d35..715e19a5 100644
--- a/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
+++ b/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
@@ -42,7 +42,8 @@ static bool IsRunningHeadless() {
class MockAudioRendererHost : public AudioRendererHost {
public:
- MockAudioRendererHost(const content::ResourceContext* resource_context)
+ explicit MockAudioRendererHost(
+ const content::ResourceContext* resource_context)
: AudioRendererHost(resource_context),
shared_memory_length_(0) {
}
@@ -182,11 +183,12 @@ class AudioRendererHostTest : public testing::Test {
message_loop_.get()));
ui_thread_.reset(new BrowserThreadImpl(BrowserThread::UI,
message_loop_.get()));
-
+ audio_manager_ = AudioManager::Create();
observer_.reset(new MockMediaObserver());
content::MockResourceContext* context =
content::MockResourceContext::GetInstance();
context->set_media_observer(observer_.get());
+ context->set_audio_manager(audio_manager_);
host_ = new MockAudioRendererHost(context);
// Simulate IPC channel connected.
@@ -204,6 +206,14 @@ class AudioRendererHostTest : public testing::Test {
// We need to continue running message_loop_ to complete all destructions.
SyncWithAudioThread();
+ // Since the MockResourceContext object is a singleton that lives across
+ // multiple tests, we must clear pointers to objects that are about to die.
+ content::MockResourceContext* context =
+ content::MockResourceContext::GetInstance();
+ context->set_audio_manager(NULL);
+ context->set_media_observer(NULL);
+ audio_manager_ = NULL;
+
io_thread_.reset();
ui_thread_.reset();
}
@@ -338,9 +348,10 @@ class AudioRendererHostTest : public testing::Test {
}
// Called on the main thread.
- static void PostQuitOnAudioThread(MessageLoop* message_loop) {
- AudioManager::GetAudioManager()->GetMessageLoop()->PostTask(
- FROM_HERE, base::Bind(&PostQuitMessageLoop, message_loop));
+ static void PostQuitOnAudioThread(AudioManager* audio_manager,
+ MessageLoop* message_loop) {
+ audio_manager->GetMessageLoop()->PostTask(FROM_HERE,
+ base::Bind(&PostQuitMessageLoop, message_loop));
}
// SyncWithAudioThread() waits until all pending tasks on the audio thread
@@ -348,8 +359,12 @@ class AudioRendererHostTest : public testing::Test {
// current thread. It is used to synchronize with the audio thread when we are
// closing an audio stream.
void SyncWithAudioThread() {
+ // Don't use scoped_refptr to addref the AudioManager when posting
+ // to the thread that itself owns.
message_loop_->PostTask(
- FROM_HERE, base::Bind(&PostQuitOnAudioThread, message_loop_.get()));
+ FROM_HERE, base::Bind(&PostQuitOnAudioThread,
+ base::Unretained(audio_manager_.get()),
+ message_loop_.get()));
message_loop_->Run();
}
@@ -364,6 +379,7 @@ class AudioRendererHostTest : public testing::Test {
scoped_ptr<MessageLoop> message_loop_;
scoped_ptr<BrowserThreadImpl> io_thread_;
scoped_ptr<BrowserThreadImpl> ui_thread_;
+ scoped_refptr<AudioManager> audio_manager_;
DISALLOW_COPY_AND_ASSIGN(AudioRendererHostTest);
};
diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
index 1a11c90..0e3ba72 100644
--- a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
+++ b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
@@ -15,6 +15,7 @@
#include "content/common/media/media_stream_messages.h"
#include "content/common/media/media_stream_options.h"
#include "ipc/ipc_message_macros.h"
+#include "media/audio/audio_manager.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -151,9 +152,11 @@ class MediaStreamDispatcherHostTest : public testing::Test {
io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
message_loop_.get()));
+ audio_manager_ = AudioManager::Create();
+
// Create a MediaStreamManager instance and hand over pointer to
// ResourceContext.
- media_stream_manager_.reset(new MediaStreamManager());
+ media_stream_manager_.reset(new MediaStreamManager(audio_manager_));
// Make sure we use fake devices to avoid long delays.
media_stream_manager_->UseFakeDevice();
content::MockResourceContext::GetInstance()->set_media_stream_manager(
@@ -202,6 +205,7 @@ class MediaStreamDispatcherHostTest : public testing::Test {
scoped_ptr<BrowserThreadImpl> ui_thread_;
scoped_ptr<BrowserThreadImpl> io_thread_;
scoped_ptr<MediaStreamManager> media_stream_manager_;
+ scoped_refptr<AudioManager> audio_manager_;
};
TEST_F(MediaStreamDispatcherHostTest, GenerateStream) {
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc
index d9d8db2..6cb46b8 100644
--- a/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -16,6 +16,7 @@
#include "content/browser/renderer_host/media/video_capture_manager.h"
#include "content/common/media/media_stream_options.h"
#include "content/public/browser/browser_thread.h"
+#include "media/audio/audio_manager.h"
using content::BrowserThread;
@@ -80,10 +81,11 @@ struct MediaStreamManager::DeviceRequest {
StreamDeviceInfoArray video_devices;
};
-MediaStreamManager::MediaStreamManager()
+MediaStreamManager::MediaStreamManager(AudioManager* audio_manager)
: ALLOW_THIS_IN_INITIALIZER_LIST(
device_settings_(new MediaStreamDeviceSettings(this))),
- enumeration_in_progress_(kNumMediaStreamTypes, false) {
+ enumeration_in_progress_(kNumMediaStreamTypes, false),
+ audio_manager_(audio_manager) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
}
@@ -103,7 +105,8 @@ VideoCaptureManager* MediaStreamManager::video_capture_manager() {
AudioInputDeviceManager* MediaStreamManager::audio_input_device_manager() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (!audio_input_device_manager_.get()) {
- audio_input_device_manager_.reset(new AudioInputDeviceManager());
+ audio_input_device_manager_.reset(
+ new AudioInputDeviceManager(audio_manager_));
audio_input_device_manager_->Register(this);
}
return audio_input_device_manager_.get();
diff --git a/content/browser/renderer_host/media/media_stream_manager.h b/content/browser/renderer_host/media/media_stream_manager.h
index 0f48afe..1eb130e 100644
--- a/content/browser/renderer_host/media/media_stream_manager.h
+++ b/content/browser/renderer_host/media/media_stream_manager.h
@@ -25,11 +25,14 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/ref_counted.h"
#include "content/browser/renderer_host/media/media_stream_provider.h"
#include "content/browser/renderer_host/media/media_stream_settings_requester.h"
#include "content/common/media/media_stream_options.h"
#include "content/common/content_export.h"
+class AudioManager;
+
namespace media_stream {
class AudioInputDeviceManager;
@@ -45,7 +48,7 @@ class CONTENT_EXPORT MediaStreamManager
: public MediaStreamProviderListener,
public SettingsRequester {
public:
- MediaStreamManager();
+ explicit MediaStreamManager(AudioManager* audio_manager);
virtual ~MediaStreamManager();
// Used to access VideoCaptureManager.
@@ -109,6 +112,7 @@ class CONTENT_EXPORT MediaStreamManager
// All non-closed request.
typedef std::map<std::string, DeviceRequest> DeviceRequests;
DeviceRequests requests_;
+ scoped_refptr<AudioManager> audio_manager_;
DISALLOW_COPY_AND_ASSIGN(MediaStreamManager);
};
diff --git a/content/browser/renderer_host/media/video_capture_host_unittest.cc b/content/browser/renderer_host/media/video_capture_host_unittest.cc
index da06442..cf99b49 100644
--- a/content/browser/renderer_host/media/video_capture_host_unittest.cc
+++ b/content/browser/renderer_host/media/video_capture_host_unittest.cc
@@ -19,6 +19,7 @@
#include "content/browser/renderer_host/media/video_capture_manager.h"
#include "content/browser/resource_context.h"
#include "content/common/media/video_capture_messages.h"
+#include "media/audio/audio_manager.h"
#include "media/video/capture/video_capture_types.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -205,9 +206,12 @@ class VideoCaptureHostTest : public testing::Test {
io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
message_loop_.get()));
+ audio_manager_ = AudioManager::Create();
+
// Create a MediaStreamManager instance and hand over pointer to
// ResourceContext.
- media_stream_manager_.reset(new media_stream::MediaStreamManager());
+ media_stream_manager_.reset(new media_stream::MediaStreamManager(
+ audio_manager_));
#ifndef TEST_REAL_CAPTURE_DEVICE
media_stream_manager_->UseFakeDevice();
@@ -368,6 +372,7 @@ class VideoCaptureHostTest : public testing::Test {
scoped_ptr<BrowserThreadImpl> ui_thread_;
scoped_ptr<BrowserThreadImpl> io_thread_;
scoped_ptr<media_stream::MediaStreamManager> media_stream_manager_;
+ scoped_refptr<AudioManager> audio_manager_;
DISALLOW_COPY_AND_ASSIGN(VideoCaptureHostTest);
};
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 1f9ff8d..61b136b 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -7,6 +7,10 @@
#include "content/browser/renderer_host/render_process_host_impl.h"
+#if defined(OS_WIN)
+#include <objbase.h> // For CoInitialize/CoUninitialize.
+#endif
+
#include <algorithm>
#include <limits>
#include <vector>
@@ -73,6 +77,7 @@
#include "content/browser/renderer_host/socket_stream_dispatcher_host.h"
#include "content/browser/renderer_host/text_input_client_message_filter.h"
#include "content/browser/resolve_proxy_msg_helper.h"
+#include "content/browser/resource_context.h"
#include "content/browser/speech/speech_input_dispatcher_host.h"
#include "content/browser/trace_message_filter.h"
#include "content/browser/user_metrics.h"
@@ -104,7 +109,6 @@
#include "webkit/plugins/plugin_switches.h"
#if defined(OS_WIN)
-#include <objbase.h>
#include "base/synchronization/waitable_event.h"
#include "content/common/font_cache_dispatcher_win.h"
#endif
@@ -460,55 +464,47 @@ void RenderProcessHostImpl::CreateMessageFilters() {
GetBrowserContext()->GetRequestContextForRenderProcess(GetID()),
widget_helper_));
channel_->AddFilter(render_message_filter);
+ content::BrowserContext* browser_context = GetBrowserContext();
+ const content::ResourceContext* resource_context =
+ &browser_context->GetResourceContext();
ResourceMessageFilter* resource_message_filter = new ResourceMessageFilter(
GetID(), content::PROCESS_TYPE_RENDERER,
- &GetBrowserContext()->GetResourceContext(),
- new RendererURLRequestContextSelector(GetBrowserContext(), GetID()),
+ resource_context,
+ new RendererURLRequestContextSelector(browser_context, GetID()),
content::GetContentClient()->browser()->GetResourceDispatcherHost());
channel_->AddFilter(resource_message_filter);
- channel_->AddFilter(new AudioInputRendererHost(
- &GetBrowserContext()->GetResourceContext()));
- channel_->AddFilter(
- new AudioRendererHost(&GetBrowserContext()->GetResourceContext()));
- channel_->AddFilter(
- new VideoCaptureHost(&GetBrowserContext()->GetResourceContext()));
- channel_->AddFilter(
- new AppCacheDispatcherHost(GetBrowserContext()->GetAppCacheService(),
- GetID()));
+ channel_->AddFilter(new AudioInputRendererHost(resource_context));
+ channel_->AddFilter(new AudioRendererHost(resource_context));
+ channel_->AddFilter(new VideoCaptureHost(resource_context));
+ channel_->AddFilter(new AppCacheDispatcherHost(
+ browser_context->GetAppCacheService(), GetID()));
channel_->AddFilter(new ClipboardMessageFilter());
- channel_->AddFilter(
- new DOMStorageMessageFilter(GetID(),
- GetBrowserContext()->GetWebKitContext()));
- channel_->AddFilter(
- new IndexedDBDispatcherHost(GetID(),
- GetBrowserContext()->GetWebKitContext()));
- channel_->AddFilter(
- GeolocationDispatcherHost::New(
- GetID(), GetBrowserContext()->GetGeolocationPermissionContext()));
+ channel_->AddFilter(new DOMStorageMessageFilter(GetID(),
+ browser_context->GetWebKitContext()));
+ channel_->AddFilter(new IndexedDBDispatcherHost(GetID(),
+ browser_context->GetWebKitContext()));
+ channel_->AddFilter(GeolocationDispatcherHost::New(
+ GetID(), browser_context->GetGeolocationPermissionContext()));
channel_->AddFilter(new GpuMessageFilter(GetID(), widget_helper_.get()));
channel_->AddFilter(new media_stream::MediaStreamDispatcherHost(
- &GetBrowserContext()->GetResourceContext(), GetID()));
- channel_->AddFilter(new PepperFileMessageFilter(GetID(),
- GetBrowserContext()));
- channel_->AddFilter(
- new PepperMessageFilter(&GetBrowserContext()->GetResourceContext()));
+ resource_context, GetID()));
+ channel_->AddFilter(new PepperFileMessageFilter(GetID(), browser_context));
+ channel_->AddFilter(new PepperMessageFilter(resource_context));
channel_->AddFilter(new speech_input::SpeechInputDispatcherHost(
- GetID(), GetBrowserContext()->GetRequestContext(),
- GetBrowserContext()->GetSpeechInputPreferences()));
- channel_->AddFilter(
- new FileSystemDispatcherHost(
- GetBrowserContext()->GetRequestContext(),
- GetBrowserContext()->GetFileSystemContext()));
+ GetID(), browser_context->GetRequestContext(),
+ browser_context->GetSpeechInputPreferences(), resource_context));
+ channel_->AddFilter(new FileSystemDispatcherHost(
+ browser_context->GetRequestContext(),
+ browser_context->GetFileSystemContext()));
channel_->AddFilter(new device_orientation::MessageFilter());
- channel_->AddFilter(
- new BlobMessageFilter(GetID(),
- GetBrowserContext()->GetBlobStorageContext()));
+ channel_->AddFilter(new BlobMessageFilter(GetID(),
+ browser_context->GetBlobStorageContext()));
channel_->AddFilter(new FileUtilitiesMessageFilter(GetID()));
channel_->AddFilter(new MimeRegistryMessageFilter());
channel_->AddFilter(new DatabaseMessageFilter(
- GetBrowserContext()->GetDatabaseTracker()));
+ browser_context->GetDatabaseTracker()));
#if defined(OS_MACOSX)
channel_->AddFilter(new TextInputClientMessageFilter(GetID()));
#elif defined(OS_WIN)
@@ -517,28 +513,24 @@ void RenderProcessHostImpl::CreateMessageFilters() {
SocketStreamDispatcherHost* socket_stream_dispatcher_host =
new SocketStreamDispatcherHost(
- new RendererURLRequestContextSelector(GetBrowserContext(), GetID()),
- &GetBrowserContext()->GetResourceContext());
+ new RendererURLRequestContextSelector(browser_context, GetID()),
+ resource_context);
channel_->AddFilter(socket_stream_dispatcher_host);
- channel_->AddFilter(
- new WorkerMessageFilter(
- GetID(),
- &GetBrowserContext()->GetResourceContext(),
- content::GetContentClient()->browser()->GetResourceDispatcherHost(),
- base::Bind(&RenderWidgetHelper::GetNextRoutingID,
- base::Unretained(widget_helper_.get()))));
+ channel_->AddFilter(new WorkerMessageFilter(GetID(), resource_context,
+ content::GetContentClient()->browser()->GetResourceDispatcherHost(),
+ base::Bind(&RenderWidgetHelper::GetNextRoutingID,
+ base::Unretained(widget_helper_.get()))));
#if defined(ENABLE_P2P_APIS)
- channel_->AddFilter(new content::P2PSocketDispatcherHost(
- &GetBrowserContext()->GetResourceContext()));
+ channel_->AddFilter(new content::P2PSocketDispatcherHost(resource_context));
#endif
channel_->AddFilter(new TraceMessageFilter());
channel_->AddFilter(new ResolveProxyMsgHelper(
- GetBrowserContext()->GetRequestContextForRenderProcess(GetID())));
- channel_->AddFilter(new QuotaDispatcherHost(
- GetID(), GetBrowserContext()->GetQuotaManager(),
+ browser_context->GetRequestContextForRenderProcess(GetID())));
+ channel_->AddFilter(new QuotaDispatcherHost(GetID(),
+ browser_context->GetQuotaManager(),
content::GetContentClient()->browser()->CreateQuotaPermissionContext()));
channel_->AddFilter(new content::GamepadBrowserMessageFilter(this));
channel_->AddFilter(new ProfilerMessageFilter());
diff --git a/content/browser/resource_context.cc b/content/browser/resource_context.cc
index d20b1e1..6eb7646 100644
--- a/content/browser/resource_context.cc
+++ b/content/browser/resource_context.cc
@@ -21,7 +21,9 @@ ResourceContext::ResourceContext()
quota_manager_(NULL),
host_zoom_map_(NULL),
media_observer_(NULL),
- media_stream_manager_(NULL) {
+ download_id_factory_(NULL),
+ media_stream_manager_(NULL),
+ audio_manager_(NULL) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
@@ -158,6 +160,7 @@ DownloadIdFactory* ResourceContext::download_id_factory() const {
EnsureInitialized();
return download_id_factory_;
}
+
void ResourceContext::set_download_id_factory(
DownloadIdFactory* download_id_factory) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
@@ -177,4 +180,15 @@ void ResourceContext::set_media_stream_manager(
media_stream_manager_ = media_stream_manager;
}
+AudioManager* ResourceContext::audio_manager() const {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ EnsureInitialized();
+ return audio_manager_;
+}
+
+void ResourceContext::set_audio_manager(AudioManager* audio_manager) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ audio_manager_ = audio_manager;
+}
+
} // namespace content
diff --git a/content/browser/resource_context.h b/content/browser/resource_context.h
index 39358f5..21f36de 100644
--- a/content/browser/resource_context.h
+++ b/content/browser/resource_context.h
@@ -12,6 +12,7 @@
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
+class AudioManager;
class ChromeAppCacheService;
class ChromeBlobStorageContext;
class DownloadIdFactory;
@@ -83,6 +84,9 @@ class CONTENT_EXPORT ResourceContext {
void set_media_stream_manager(
media_stream::MediaStreamManager* media_stream_manager);
+ AudioManager* audio_manager() const;
+ void set_audio_manager(AudioManager* audio_manager);
+
protected:
ResourceContext();
@@ -100,6 +104,7 @@ class CONTENT_EXPORT ResourceContext {
MediaObserver* media_observer_;
DownloadIdFactory* download_id_factory_;
media_stream::MediaStreamManager* media_stream_manager_;
+ AudioManager* audio_manager_;
// Externally-defined data accessible by key.
typedef std::map<const void*, void*> UserDataMap;
diff --git a/content/browser/speech/speech_input_browsertest.cc b/content/browser/speech/speech_input_browsertest.cc
index 7dd1f9f..f0c6321 100644
--- a/content/browser/speech/speech_input_browsertest.cc
+++ b/content/browser/speech/speech_input_browsertest.cc
@@ -49,16 +49,13 @@ class FakeSpeechInputManager : public SpeechInputManager {
}
// SpeechInputManager methods.
- virtual void StartRecognition(Delegate* delegate,
- int caller_id,
- int render_process_id,
- int render_view_id,
- const gfx::Rect& element_rect,
- const std::string& language,
- const std::string& grammar,
- const std::string& origin_url,
- net::URLRequestContextGetter* context_getter,
- SpeechInputPreferences* speech_input_prefs) {
+ virtual void StartRecognition(Delegate* delegate, int caller_id,
+ int render_process_id, int render_view_id, const gfx::Rect& element_rect,
+ const std::string& language, const std::string& grammar,
+ const std::string& origin_url,
+ net::URLRequestContextGetter* context_getter,
+ SpeechInputPreferences* speech_input_prefs,
+ AudioManager* audio_manager) OVERRIDE {
VLOG(1) << "StartRecognition invoked.";
EXPECT_EQ(0, caller_id_);
EXPECT_EQ(NULL, delegate_);
@@ -77,18 +74,18 @@ class FakeSpeechInputManager : public SpeechInputManager {
base::Unretained(this)));
}
}
- virtual void CancelRecognition(int caller_id) {
+ virtual void CancelRecognition(int caller_id) OVERRIDE {
VLOG(1) << "CancelRecognition invoked.";
EXPECT_EQ(caller_id_, caller_id);
caller_id_ = 0;
delegate_ = NULL;
}
- virtual void StopRecording(int caller_id) {
+ virtual void StopRecording(int caller_id) OVERRIDE {
VLOG(1) << "StopRecording invoked.";
EXPECT_EQ(caller_id_, caller_id);
// Nothing to do here since we aren't really recording.
}
- virtual void CancelAllRequestsWithDelegate(Delegate* delegate) {
+ virtual void CancelAllRequestsWithDelegate(Delegate* delegate) OVERRIDE {
VLOG(1) << "CancelAllRequestsWithDelegate invoked.";
// delegate_ is set to NULL if a fake result was received (see below), so
// check that delegate_ matches the incoming parameter only when there is
@@ -98,23 +95,21 @@ class FakeSpeechInputManager : public SpeechInputManager {
}
protected:
- virtual void GetRequestInfo(bool* can_report_metrics,
- std::string* request_info) {}
- virtual void ShowRecognitionRequested(int caller_id,
- int render_process_id,
- int render_view_id,
- const gfx::Rect& element_rect) {}
- virtual void ShowWarmUp(int caller_id) {}
- virtual void ShowRecognizing(int caller_id) {}
- virtual void ShowRecording(int caller_id) {}
- virtual void ShowInputVolume(int caller_id,
- float volume,
- float noise_volume) {}
+ virtual void GetRequestInfo(AudioManager* audio_manager,
+ bool* can_report_metrics,
+ std::string* request_info) OVERRIDE {}
+ virtual void ShowRecognitionRequested(int caller_id, int render_process_id,
+ int render_view_id, const gfx::Rect& element_rect) OVERRIDE {}
+ virtual void ShowWarmUp(int caller_id) OVERRIDE {}
+ virtual void ShowRecognizing(int caller_id) OVERRIDE {}
+ virtual void ShowRecording(int caller_id) OVERRIDE {}
+ virtual void ShowInputVolume(int caller_id, float volume,
+ float noise_volume) OVERRIDE {}
virtual void ShowMicError(int caller_id,
- SpeechInputManager::MicError error) {}
+ SpeechInputManager::MicError error) OVERRIDE {}
virtual void ShowRecognizerError(int caller_id,
- content::SpeechInputError error) {}
- virtual void DoClose(int caller_id) {}
+ content::SpeechInputError error) OVERRIDE {}
+ virtual void DoClose(int caller_id) OVERRIDE {}
private:
void SetFakeRecognitionResult() {
diff --git a/content/browser/speech/speech_input_dispatcher_host.cc b/content/browser/speech/speech_input_dispatcher_host.cc
index 15b927b..8f4632c 100644
--- a/content/browser/speech/speech_input_dispatcher_host.cc
+++ b/content/browser/speech/speech_input_dispatcher_host.cc
@@ -5,6 +5,7 @@
#include "content/browser/speech/speech_input_dispatcher_host.h"
#include "base/lazy_instance.h"
+#include "content/browser/resource_context.h"
#include "content/browser/speech/speech_input_preferences.h"
#include "content/common/speech_input_messages.h"
#include "content/public/browser/content_browser_client.h"
@@ -114,11 +115,13 @@ void SpeechInputDispatcherHost::set_manager(SpeechInputManager* manager) {
SpeechInputDispatcherHost::SpeechInputDispatcherHost(
int render_process_id,
net::URLRequestContextGetter* context_getter,
- SpeechInputPreferences* speech_input_preferences)
+ SpeechInputPreferences* speech_input_preferences,
+ const content::ResourceContext* resource_context)
: render_process_id_(render_process_id),
may_have_pending_requests_(false),
context_getter_(context_getter),
- speech_input_preferences_(speech_input_preferences) {
+ speech_input_preferences_(speech_input_preferences),
+ resource_context_(resource_context) {
// This is initialized by Browser. Do not add any non-trivial
// initialization here, instead do it lazily when required (e.g. see the
// method |manager()|) or add an Init() method.
@@ -161,6 +164,7 @@ bool SpeechInputDispatcherHost::OnMessageReceived(
void SpeechInputDispatcherHost::OnStartRecognition(
const SpeechInputHostMsg_StartRecognition_Params &params) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
int caller_id = g_speech_input_callers.Get().CreateId(
render_process_id_, params.render_view_id, params.request_id);
manager()->StartRecognition(this, caller_id,
@@ -169,7 +173,8 @@ void SpeechInputDispatcherHost::OnStartRecognition(
params.language, params.grammar,
params.origin_url,
context_getter_.get(),
- speech_input_preferences_.get());
+ speech_input_preferences_.get(),
+ resource_context_->audio_manager());
}
void SpeechInputDispatcherHost::OnCancelRecognition(int render_view_id,
diff --git a/content/browser/speech/speech_input_dispatcher_host.h b/content/browser/speech/speech_input_dispatcher_host.h
index e6f91b1..a801ff0 100644
--- a/content/browser/speech/speech_input_dispatcher_host.h
+++ b/content/browser/speech/speech_input_dispatcher_host.h
@@ -13,6 +13,10 @@
struct SpeechInputHostMsg_StartRecognition_Params;
+namespace content {
+class ResourceContext;
+}
+
namespace speech_input {
// SpeechInputDispatcherHost is a delegate for Speech API messages used by
@@ -26,7 +30,8 @@ class SpeechInputDispatcherHost : public BrowserMessageFilter,
SpeechInputDispatcherHost(
int render_process_id,
net::URLRequestContextGetter* context_getter,
- SpeechInputPreferences* speech_input_preferences);
+ SpeechInputPreferences* speech_input_preferences,
+ const content::ResourceContext* resource_context);
// SpeechInputManager::Delegate methods.
virtual void SetRecognitionResult(
@@ -59,6 +64,7 @@ class SpeechInputDispatcherHost : public BrowserMessageFilter,
scoped_refptr<net::URLRequestContextGetter> context_getter_;
scoped_refptr<SpeechInputPreferences> speech_input_preferences_;
+ const content::ResourceContext* resource_context_;
static SpeechInputManager* manager_;
diff --git a/content/browser/speech/speech_input_manager.cc b/content/browser/speech/speech_input_manager.cc
index a3c243f..79a5753 100644
--- a/content/browser/speech/speech_input_manager.cc
+++ b/content/browser/speech/speech_input_manager.cc
@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "content/browser/renderer_host/render_view_host.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
+#include "content/browser/resource_context.h"
#include "content/browser/speech/speech_input_preferences.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/view_type.h"
@@ -26,7 +27,8 @@ struct SpeechInputManager::SpeechInputParams {
const std::string& grammar,
const std::string& origin_url,
net::URLRequestContextGetter* context_getter,
- SpeechInputPreferences* speech_input_prefs)
+ SpeechInputPreferences* speech_input_prefs,
+ AudioManager* audio_manager)
: delegate(delegate),
caller_id(caller_id),
render_process_id(render_process_id),
@@ -36,7 +38,8 @@ struct SpeechInputManager::SpeechInputParams {
grammar(grammar),
origin_url(origin_url),
context_getter(context_getter),
- speech_input_prefs(speech_input_prefs) {
+ speech_input_prefs(speech_input_prefs),
+ audio_manager_(audio_manager) {
}
Delegate* delegate;
@@ -49,6 +52,7 @@ struct SpeechInputManager::SpeechInputParams {
std::string origin_url;
net::URLRequestContextGetter* context_getter;
SpeechInputPreferences* speech_input_prefs;
+ scoped_refptr<AudioManager> audio_manager_;
};
SpeechInputManager::SpeechInputManager()
@@ -70,19 +74,34 @@ SpeechInputManagerDelegate* SpeechInputManager::GetDelegate(
return requests_.find(caller_id)->second.delegate;
}
-void SpeechInputManager::ShowAudioInputSettings() {
+// static
+void SpeechInputManager::ShowAudioInputSettings(AudioManager* audio_manager) {
// Since AudioManager::ShowAudioInputSettings can potentially launch external
// processes, do that in the FILE thread to not block the calling threads.
if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
- base::Bind(&SpeechInputManager::ShowAudioInputSettings));
+ base::Bind(&SpeechInputManager::ShowAudioInputSettings,
+ base::Unretained(audio_manager)));
return;
}
- DCHECK(AudioManager::GetAudioManager()->CanShowAudioInputSettings());
- if (AudioManager::GetAudioManager()->CanShowAudioInputSettings())
- AudioManager::GetAudioManager()->ShowAudioInputSettings();
+ DCHECK(audio_manager->CanShowAudioInputSettings());
+ if (audio_manager->CanShowAudioInputSettings())
+ audio_manager->ShowAudioInputSettings();
+}
+
+// static
+void SpeechInputManager::ShowAudioInputSettingsFromUI(
+ const content::ResourceContext* resource_context) {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&SpeechInputManager::ShowAudioInputSettingsFromUI,
+ base::Unretained(resource_context)));
+ return;
+ }
+ ShowAudioInputSettings(resource_context->audio_manager());
}
void SpeechInputManager::StartRecognition(
@@ -95,14 +114,15 @@ void SpeechInputManager::StartRecognition(
const std::string& grammar,
const std::string& origin_url,
net::URLRequestContextGetter* context_getter,
- SpeechInputPreferences* speech_input_prefs) {
+ SpeechInputPreferences* speech_input_prefs,
+ AudioManager* audio_manager) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&SpeechInputManager::CheckRenderViewTypeAndStartRecognition,
base::Unretained(this), SpeechInputParams(delegate, caller_id,
render_process_id, render_view_id, element_rect, language, grammar,
- origin_url, context_getter, speech_input_prefs)));
+ origin_url, context_getter, speech_input_prefs, audio_manager)));
}
void SpeechInputManager::CheckRenderViewTypeAndStartRecognition(
@@ -137,13 +157,15 @@ void SpeechInputManager::ProceedStartingRecognition(
ShowRecognitionRequested(
params.caller_id, params.render_process_id, params.render_view_id,
params.element_rect);
- GetRequestInfo(&can_report_metrics_, &request_info_);
+ GetRequestInfo(params.audio_manager_, &can_report_metrics_,
+ &request_info_);
SpeechInputRequest* request = &requests_[params.caller_id];
request->delegate = params.delegate;
request->recognizer = new SpeechRecognizer(
this, params.caller_id, params.language, params.grammar,
- params.context_getter, params.speech_input_prefs->filter_profanities(),
+ params.context_getter, params.audio_manager_,
+ params.speech_input_prefs->filter_profanities(),
request_info_, can_report_metrics_ ? params.origin_url : "");
request->is_active = false;
@@ -151,15 +173,20 @@ void SpeechInputManager::ProceedStartingRecognition(
}
void SpeechInputManager::StartRecognitionForRequest(int caller_id) {
- DCHECK(HasPendingRequest(caller_id));
+ SpeechRecognizerMap::iterator request = requests_.find(caller_id);
+ if (request == requests_.end()) {
+ NOTREACHED();
+ return;
+ }
// If we are currently recording audio for another caller, abort that cleanly.
if (recording_caller_id_)
CancelRecognitionAndInformDelegate(recording_caller_id_);
- if (!AudioManager::GetAudioManager()->HasAudioInputDevices()) {
+ AudioManager* audio_man = request->second.recognizer->audio_manager();
+ if (!audio_man->HasAudioInputDevices()) {
ShowMicError(caller_id, kNoDeviceAvailable);
- } else if (AudioManager::GetAudioManager()->IsRecordingInProcess()) {
+ } else if (audio_man->IsRecordingInProcess()) {
ShowMicError(caller_id, kDeviceInUse);
} else {
recording_caller_id_ = caller_id;
diff --git a/content/browser/speech/speech_input_manager.h b/content/browser/speech/speech_input_manager.h
index 65c381c..d78b0f9 100644
--- a/content/browser/speech/speech_input_manager.h
+++ b/content/browser/speech/speech_input_manager.h
@@ -16,6 +16,7 @@
class SpeechInputPreferences;
namespace content {
+class ResourceContext;
struct SpeechInputResult;
}
@@ -50,7 +51,13 @@ class CONTENT_EXPORT SpeechInputManager : public SpeechRecognizerDelegate {
// Invokes the platform provided microphone settings UI in a non-blocking way,
// via the BrowserThread::FILE thread.
- static void ShowAudioInputSettings();
+ static void ShowAudioInputSettings(AudioManager* audio_manager);
+
+ // Same as ShowAudioInputSettings above but can be called from the UI thread
+ // where the caller has a pointer to a resource context, but due to not
+ // running on the IO thread, cannot access its properties.
+ static void ShowAudioInputSettingsFromUI(
+ const content::ResourceContext* resource_context);
virtual ~SpeechInputManager();
@@ -71,7 +78,8 @@ class CONTENT_EXPORT SpeechInputManager : public SpeechRecognizerDelegate {
const std::string& grammar,
const std::string& origin_url,
net::URLRequestContextGetter* context_getter,
- SpeechInputPreferences* speech_input_prefs);
+ SpeechInputPreferences* speech_input_prefs,
+ AudioManager* audio_manager);
virtual void CancelRecognition(int caller_id);
virtual void CancelAllRequestsWithDelegate(Delegate* delegate);
virtual void StopRecording(int caller_id);
@@ -97,7 +105,8 @@ class CONTENT_EXPORT SpeechInputManager : public SpeechRecognizerDelegate {
// recognition and for fetching optional request information.
// Get the optional request information if available.
- virtual void GetRequestInfo(bool* can_report_metrics,
+ virtual void GetRequestInfo(AudioManager* audio_manager,
+ bool* can_report_metrics,
std::string* request_info) = 0;
// Called when recognition has been requested from point |element_rect_| on
diff --git a/content/browser/speech/speech_recognizer.cc b/content/browser/speech/speech_recognizer.cc
index a21bafb..4704867 100644
--- a/content/browser/speech/speech_recognizer.cc
+++ b/content/browser/speech/speech_recognizer.cc
@@ -61,6 +61,7 @@ SpeechRecognizer::SpeechRecognizer(Delegate* delegate,
const std::string& language,
const std::string& grammar,
net::URLRequestContextGetter* context_getter,
+ AudioManager* audio_manager,
bool filter_profanities,
const std::string& hardware_info,
const std::string& origin_url)
@@ -72,6 +73,7 @@ SpeechRecognizer::SpeechRecognizer(Delegate* delegate,
hardware_info_(hardware_info),
origin_url_(origin_url),
context_getter_(context_getter),
+ audio_manager_(audio_manager),
codec_(AudioEncoder::CODEC_FLAC),
encoder_(NULL),
endpointer_(kAudioSampleRate),
@@ -111,7 +113,8 @@ bool SpeechRecognizer::StartRecording() {
AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout,
kAudioSampleRate, kNumBitsPerAudioSample,
samples_per_packet);
- audio_controller_ = AudioInputController::Create(this, params);
+ audio_controller_ = AudioInputController::Create(audio_manager_, this,
+ params);
DCHECK(audio_controller_.get());
VLOG(1) << "SpeechRecognizer starting record.";
num_samples_recorded_ = 0;
@@ -215,7 +218,7 @@ void SpeechRecognizer::HandleOnData(string* data) {
bool speech_was_heard_before_packet = endpointer_.DidStartReceivingSpeech();
const short* samples = reinterpret_cast<const short*>(data->data());
- DCHECK((data->length() % sizeof(short)) == 0);
+ DCHECK_EQ((data->length() % sizeof(short)), 0U);
int num_samples = data->length() / sizeof(short);
encoder_->Encode(samples, num_samples);
float rms;
diff --git a/content/browser/speech/speech_recognizer.h b/content/browser/speech/speech_recognizer.h
index 5d64af7..f1b3cf2 100644
--- a/content/browser/speech/speech_recognizer.h
+++ b/content/browser/speech/speech_recognizer.h
@@ -86,6 +86,7 @@ class CONTENT_EXPORT SpeechRecognizer
const std::string& language,
const std::string& grammar,
net::URLRequestContextGetter* context_getter,
+ AudioManager* audio_manager,
bool filter_profanities,
const std::string& hardware_info,
const std::string& origin_url);
@@ -118,6 +119,8 @@ class CONTENT_EXPORT SpeechRecognizer
virtual void SetRecognitionResult(
const content::SpeechInputResult& result) OVERRIDE;
+ AudioManager* audio_manager() const { return audio_manager_; }
+
static const int kAudioSampleRate;
static const int kAudioPacketIntervalMs; // Duration of each audio packet.
static const ChannelLayout kChannelLayout;
@@ -145,6 +148,7 @@ class CONTENT_EXPORT SpeechRecognizer
scoped_ptr<SpeechRecognitionRequest> request_;
scoped_refptr<media::AudioInputController> audio_controller_;
scoped_refptr<net::URLRequestContextGetter> context_getter_;
+ scoped_refptr<AudioManager> audio_manager_;
AudioEncoder::Codec codec_;
scoped_ptr<AudioEncoder> encoder_;
Endpointer endpointer_;
diff --git a/content/browser/speech/speech_recognizer_unittest.cc b/content/browser/speech/speech_recognizer_unittest.cc
index 5845cd4..6dcaec6 100644
--- a/content/browser/speech/speech_recognizer_unittest.cc
+++ b/content/browser/speech/speech_recognizer_unittest.cc
@@ -7,6 +7,7 @@
#include "content/browser/browser_thread_impl.h"
#include "content/browser/speech/speech_recognizer.h"
#include "content/test/test_url_fetcher_factory.h"
+#include "media/audio/audio_manager.h"
#include "media/audio/test_audio_input_controller_factory.h"
#include "net/base/net_errors.h"
#include "net/url_request/url_request_status.h"
@@ -25,16 +26,16 @@ class SpeechRecognizerTest : public SpeechRecognizerDelegate,
public:
SpeechRecognizerTest()
: io_thread_(BrowserThread::IO, &message_loop_),
- ALLOW_THIS_IN_INITIALIZER_LIST(
- recognizer_(new SpeechRecognizer(this, 1, std::string(),
- std::string(), NULL, false,
- std::string(), std::string()))),
+ audio_manager_(AudioManager::Create()),
recording_complete_(false),
recognition_complete_(false),
result_received_(false),
audio_received_(false),
error_(content::SPEECH_INPUT_ERROR_NONE),
volume_(-1.0f) {
+ recognizer_ = new SpeechRecognizer(this, 1, std::string(), std::string(),
+ NULL, audio_manager_, false,
+ std::string(), std::string());
int audio_packet_length_bytes =
(SpeechRecognizer::kAudioSampleRate *
SpeechRecognizer::kAudioPacketIntervalMs *
@@ -111,6 +112,7 @@ class SpeechRecognizerTest : public SpeechRecognizerDelegate,
MessageLoopForIO message_loop_;
BrowserThreadImpl io_thread_;
scoped_refptr<SpeechRecognizer> recognizer_;
+ scoped_refptr<AudioManager> audio_manager_;
bool recording_complete_;
bool recognition_complete_;
bool result_received_;
diff --git a/content/renderer/media/webrtc_audio_device_unittest.cc b/content/renderer/media/webrtc_audio_device_unittest.cc
index bd11fb8..14bbcde 100644
--- a/content/renderer/media/webrtc_audio_device_unittest.cc
+++ b/content/renderer/media/webrtc_audio_device_unittest.cc
@@ -157,39 +157,9 @@ class WebRTCMediaProcessImpl : public webrtc::VoEMediaProcess {
} // end namespace
-// Utility class to delete the AudioManager.
-// TODO(tommi): Remove when we've fixed issue 105249.
-class AutoAudioManagerCleanup {
- public:
- AutoAudioManagerCleanup() {
- // Log an error if a previous test didn't clean up the AudioManager.
- if (DeleteAndResurrect()) {
- LOG(ERROR)
- << "AudioManager singleton was not cleaned up by some previous test!";
- }
- }
- ~AutoAudioManagerCleanup() {
- DeleteAndResurrect();
- }
-
- private:
- // Returns true iff the AudioManager existed and was deleted.
- bool DeleteAndResurrect() {
- if (AudioManager::SingletonExists()) {
- AudioManager::Destroy(NULL);
- AudioManager::Resurrect();
- return true;
- }
- return false;
- }
-
- DISALLOW_COPY_AND_ASSIGN(AutoAudioManagerCleanup);
-};
-
// Basic test that instantiates and initializes an instance of
// WebRtcAudioDeviceImpl.
TEST_F(WebRTCAudioDeviceTest, Construct) {
- AutoAudioManagerCleanup audio_manager_cleanup;
AudioUtilNoHardware audio_util(48000.0, 48000.0);
SetAudioUtilCallback(&audio_util);
scoped_refptr<WebRtcAudioDeviceImpl> audio_device(
@@ -212,8 +182,6 @@ TEST_F(WebRTCAudioDeviceTest, Construct) {
// verify that streaming starts correctly.
// Disabled when running headless since the bots don't have the required config.
TEST_F(WebRTCAudioDeviceTest, StartPlayout) {
- AutoAudioManagerCleanup audio_manager_cleanup;
-
if (IsRunningHeadless())
return;
@@ -286,8 +254,6 @@ TEST_F(WebRTCAudioDeviceTest, StartPlayout) {
// that the audio capturing starts as it should.
// Disabled when running headless since the bots don't have the required config.
TEST_F(WebRTCAudioDeviceTest, StartRecording) {
- AutoAudioManagerCleanup audio_manager_cleanup;
-
if (IsRunningHeadless())
return;
@@ -355,8 +321,6 @@ TEST_F(WebRTCAudioDeviceTest, StartRecording) {
// Uses WebRtcAudioDeviceImpl to play a local wave file.
// Disabled when running headless since the bots don't have the required config.
TEST_F(WebRTCAudioDeviceTest, PlayLocalFile) {
- AutoAudioManagerCleanup audio_manager_cleanup;
-
if (IsRunningHeadless())
return;
@@ -403,11 +367,16 @@ TEST_F(WebRTCAudioDeviceTest, PlayLocalFile) {
EXPECT_EQ(0, file->StartPlayingFileLocally(ch, file_path.c_str(), false,
webrtc::kFileFormatPcm16kHzFile));
+ // Play 2 seconds worth of audio and then quit.
message_loop_.PostDelayedTask(FROM_HERE,
MessageLoop::QuitClosure(),
- TestTimeouts::action_timeout_ms());
+ 2000);
message_loop_.Run();
+
+ EXPECT_EQ(0, base->StopSend(ch));
+ EXPECT_EQ(0, base->StopPlayout(ch));
+ EXPECT_EQ(0, base->DeleteChannel(ch));
EXPECT_EQ(0, base->Terminate());
}
@@ -420,8 +389,6 @@ TEST_F(WebRTCAudioDeviceTest, PlayLocalFile) {
// TODO(henrika): improve quality by using a wideband codec, enabling noise-
// suppressions and perhaps also the digital AGC.
TEST_F(WebRTCAudioDeviceTest, FullDuplexAudio) {
- AutoAudioManagerCleanup audio_manager_cleanup;
-
if (IsRunningHeadless())
return;
diff --git a/content/test/webrtc_audio_device_test.cc b/content/test/webrtc_audio_device_test.cc
index 1bd5225..d4ea8b7 100644
--- a/content/test/webrtc_audio_device_test.cc
+++ b/content/test/webrtc_audio_device_test.cc
@@ -96,7 +96,7 @@ ACTION_P(QuitMessageLoop, loop_or_proxy) {
} // end namespace
WebRTCAudioDeviceTest::WebRTCAudioDeviceTest()
- : render_thread_(NULL), event_(false, false), audio_util_callback_(NULL) {
+ : render_thread_(NULL), audio_util_callback_(NULL) {
}
WebRTCAudioDeviceTest::~WebRTCAudioDeviceTest() {}
@@ -116,10 +116,9 @@ void WebRTCAudioDeviceTest::SetUp() {
resource_context_.reset(new WebRTCMockResourceContext());
static const char kThreadName[] = "RenderThread";
- ChildProcess::current()->io_message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&SetupTask::InitializeIOThread, new SetupTask(this),
- kThreadName));
+ ChildProcess::current()->io_message_loop()->PostTask(FROM_HERE,
+ base::Bind(&WebRTCAudioDeviceTest::InitializeIOThread,
+ base::Unretained(this), kThreadName));
WaitForIOThreadCompletion();
render_thread_ = new RenderThreadImpl(kThreadName);
@@ -129,11 +128,25 @@ void WebRTCAudioDeviceTest::SetUp() {
void WebRTCAudioDeviceTest::TearDown() {
SetAudioUtilCallback(NULL);
- ChildProcess::current()->io_message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&SetupTask::UninitializeIOThread, new SetupTask(this)));
- EXPECT_TRUE(event_.TimedWait(
- base::TimeDelta::FromMilliseconds(TestTimeouts::action_timeout_ms())));
+ // Kick of the cleanup process by closing the channel. This queues up
+ // OnStreamClosed calls to be executed on the audio thread.
+ ChildProcess::current()->io_message_loop()->PostTask(FROM_HERE,
+ base::Bind(&WebRTCAudioDeviceTest::DestroyChannel,
+ base::Unretained(this)));
+ WaitForIOThreadCompletion();
+
+ // When audio [input] render hosts are notified that the channel has
+ // been closed, they post tasks to the audio thread to close the
+ // AudioOutputController and once that's completed, a task is posted back to
+ // the IO thread to actually delete the AudioEntry for the audio stream. Only
+ // then is the reference to the audio manager released, so we wait for the
+ // whole thing to be torn down before we finally uninitialize the io thread.
+ WaitForAudioManagerCompletion();
+
+ ChildProcess::current()->io_message_loop()->PostTask(FROM_HERE,
+ base::Bind(&WebRTCAudioDeviceTest::UninitializeIOThread,
+ base::Unretained((this))));
+ WaitForIOThreadCompletion();
mock_process_.reset();
}
@@ -156,33 +169,40 @@ void WebRTCAudioDeviceTest::InitializeIOThread(const char* thread_name) {
// Set the current thread as the IO thread.
io_thread_.reset(new content::TestBrowserThread(content::BrowserThread::IO,
MessageLoop::current()));
+
+ audio_manager_ = AudioManager::Create();
+
+ // Populate our resource context.
test_request_context_ = new TestURLRequestContext();
resource_context_->set_request_context(test_request_context_.get());
media_observer_.reset(new MockMediaObserver());
resource_context_->set_media_observer(media_observer_.get());
- media_stream_manager_.reset(new media_stream::MediaStreamManager());
+ media_stream_manager_.reset(new media_stream::MediaStreamManager(
+ audio_manager_));
resource_context_->set_media_stream_manager(media_stream_manager_.get());
+ resource_context_->set_audio_manager(audio_manager_);
- CreateChannel(thread_name, resource_context_.get());
+ // Create an IPC channel that handles incoming messages on the IO thread.
+ CreateChannel(thread_name);
}
void WebRTCAudioDeviceTest::UninitializeIOThread() {
- DestroyChannel();
resource_context_.reset();
media_stream_manager_.reset();
+
+ EXPECT_TRUE(audio_manager_->HasOneRef());
+ audio_manager_ = NULL;
test_request_context_ = NULL;
initialize_com_.reset();
- event_.Signal();
}
-void WebRTCAudioDeviceTest::CreateChannel(
- const char* name,
- content::ResourceContext* resource_context) {
+void WebRTCAudioDeviceTest::CreateChannel(const char* name) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
- audio_render_host_ = new AudioRendererHost(resource_context);
+ audio_render_host_ = new AudioRendererHost(resource_context_.get());
audio_render_host_->OnChannelConnected(base::GetCurrentProcId());
- audio_input_renderer_host_ = new AudioInputRendererHost(resource_context);
+ audio_input_renderer_host_ = new AudioInputRendererHost(
+ resource_context_.get());
audio_input_renderer_host_->OnChannelConnected(base::GetCurrentProcId());
channel_.reset(new IPC::Channel(name, IPC::Channel::MODE_SERVER, this));
@@ -257,11 +277,26 @@ bool WebRTCAudioDeviceTest::OnMessageReceived(const IPC::Message& message) {
// Posts a final task to the IO message loop and waits for completion.
void WebRTCAudioDeviceTest::WaitForIOThreadCompletion() {
- ChildProcess::current()->io_message_loop()->PostTask(
- FROM_HERE, base::Bind(&base::WaitableEvent::Signal,
- base::Unretained(&event_)));
- EXPECT_TRUE(event_.TimedWait(
- base::TimeDelta::FromMilliseconds(TestTimeouts::action_timeout_ms())));
+ WaitForMessageLoopCompletion(ChildProcess::current()->io_message_loop());
+}
+
+void WebRTCAudioDeviceTest::WaitForAudioManagerCompletion() {
+ if (audio_manager_)
+ WaitForMessageLoopCompletion(audio_manager_->GetMessageLoop());
+}
+
+void WebRTCAudioDeviceTest::WaitForMessageLoopCompletion(MessageLoop* loop) {
+ base::WaitableEvent* event = new base::WaitableEvent(false, false);
+ loop->PostTask(FROM_HERE, base::Bind(&base::WaitableEvent::Signal,
+ base::Unretained(event)));
+ if (event->TimedWait(base::TimeDelta::FromMilliseconds(
+ TestTimeouts::action_max_timeout_ms()))) {
+ delete event;
+ } else {
+ // Don't delete the event object in case the message ever gets processed.
+ // If we do, we will crash the test process.
+ ADD_FAILURE() << "Failed to wait for message loop";
+ }
}
std::string WebRTCAudioDeviceTest::GetTestDataPath(
diff --git a/content/test/webrtc_audio_device_test.h b/content/test/webrtc_audio_device_test.h
index 376a05a..d1caead 100644
--- a/content/test/webrtc_audio_device_test.h
+++ b/content/test/webrtc_audio_device_test.h
@@ -12,7 +12,6 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
-#include "base/synchronization/waitable_event.h"
#include "content/browser/renderer_host/media/mock_media_observer.h"
#include "content/renderer/mock_content_renderer_client.h"
#include "ipc/ipc_channel.h"
@@ -20,6 +19,7 @@
#include "third_party/webrtc/common_types.h"
class AudioInputRendererHost;
+class AudioManager;
class AudioRendererHost;
class RenderThreadImpl;
class WebRTCMockRenderProcess;
@@ -118,19 +118,6 @@ class WebRTCAudioDeviceTest
: public ::testing::Test,
public IPC::Channel::Listener {
public:
- class SetupTask : public base::RefCountedThreadSafe<SetupTask> {
- public:
- explicit SetupTask(WebRTCAudioDeviceTest* test) : test_(test) {
- DCHECK(test); // Catch this early since we dereference much later.
- }
- void InitializeIOThread(const char* thread_name) {
- test_->InitializeIOThread(thread_name);
- }
- void UninitializeIOThread() { test_->UninitializeIOThread(); }
- protected:
- WebRTCAudioDeviceTest* test_;
- };
-
WebRTCAudioDeviceTest();
virtual ~WebRTCAudioDeviceTest();
@@ -145,8 +132,7 @@ class WebRTCAudioDeviceTest
protected:
void InitializeIOThread(const char* thread_name);
void UninitializeIOThread();
- void CreateChannel(const char* name,
- content::ResourceContext* resource_context);
+ void CreateChannel(const char* name);
void DestroyChannel();
void OnGetHardwareSampleRate(double* sample_rate);
@@ -157,6 +143,8 @@ class WebRTCAudioDeviceTest
// Posts a final task to the IO message loop and waits for completion.
void WaitForIOThreadCompletion();
+ void WaitForAudioManagerCompletion();
+ void WaitForMessageLoopCompletion(MessageLoop* loop);
// Convenience getter for gmock.
MockMediaObserver& media_observer() const {
@@ -170,9 +158,9 @@ class WebRTCAudioDeviceTest
content::MockContentRendererClient mock_content_renderer_client_;
RenderThreadImpl* render_thread_; // Owned by mock_process_.
scoped_ptr<WebRTCMockRenderProcess> mock_process_;
- base::WaitableEvent event_;
scoped_ptr<MockMediaObserver> media_observer_;
scoped_ptr<media_stream::MediaStreamManager> media_stream_manager_;
+ scoped_refptr<AudioManager> audio_manager_;
scoped_ptr<content::ResourceContext> resource_context_;
scoped_refptr<net::URLRequestContext> test_request_context_;
scoped_ptr<IPC::Channel> channel_;
diff --git a/media/audio/android/audio_manager_android.cc b/media/audio/android/audio_manager_android.cc
index 0330fec..0779337 100644
--- a/media/audio/android/audio_manager_android.cc
+++ b/media/audio/android/audio_manager_android.cc
@@ -10,8 +10,7 @@
#include "media/audio/fake_audio_input_stream.h"
#include "media/audio/fake_audio_output_stream.h"
-// static
-AudioManager* AudioManager::CreateAudioManager() {
+AudioManager* CreateAudioManager() {
return new AudioManagerAndroid();
}
diff --git a/media/audio/audio_input_controller.cc b/media/audio/audio_input_controller.cc
index 197378c..7bb1d26 100644
--- a/media/audio/audio_input_controller.cc
+++ b/media/audio/audio_input_controller.cc
@@ -10,7 +10,7 @@
namespace {
const int kMaxInputChannels = 2;
-const int kTimerResetInterval = 1; // One second.
+const int kTimerResetInterval = 1; // One second.
}
namespace media {
@@ -18,9 +18,11 @@ namespace media {
// static
AudioInputController::Factory* AudioInputController::factory_ = NULL;
-AudioInputController::AudioInputController(EventHandler* handler,
+AudioInputController::AudioInputController(AudioManager* audio_manager,
+ EventHandler* handler,
SyncWriter* sync_writer)
- : handler_(handler),
+ : audio_manager_(audio_manager),
+ handler_(handler),
stream_(NULL),
ALLOW_THIS_IN_INITIALIZER_LIST(no_data_timer_(FROM_HERE,
base::TimeDelta::FromSeconds(kTimerResetInterval),
@@ -29,6 +31,7 @@ AudioInputController::AudioInputController(EventHandler* handler,
state_(kEmpty),
thread_("AudioInputControllerThread"),
sync_writer_(sync_writer) {
+ DCHECK(audio_manager_); // Fail early.
}
AudioInputController::~AudioInputController() {
@@ -37,17 +40,19 @@ AudioInputController::~AudioInputController() {
// static
scoped_refptr<AudioInputController> AudioInputController::Create(
+ AudioManager* audio_manager,
EventHandler* event_handler,
const AudioParameters& params) {
+ DCHECK(audio_manager);
if (!params.IsValid() || (params.channels > kMaxInputChannels))
return NULL;
if (factory_) {
- return factory_->Create(event_handler, params);
+ return factory_->Create(audio_manager, event_handler, params);
}
scoped_refptr<AudioInputController> controller(new AudioInputController(
- event_handler, NULL));
+ audio_manager, event_handler, NULL));
// Start the thread and post a task to create the audio input stream.
// Pass an empty string to indicate using default device.
@@ -61,21 +66,20 @@ scoped_refptr<AudioInputController> AudioInputController::Create(
// static
scoped_refptr<AudioInputController> AudioInputController::CreateLowLatency(
+ AudioManager* audio_manager,
EventHandler* event_handler,
const AudioParameters& params,
const std::string& device_id,
SyncWriter* sync_writer) {
+ DCHECK(audio_manager);
DCHECK(sync_writer);
if (!params.IsValid() || (params.channels > kMaxInputChannels))
return NULL;
- if (!AudioManager::GetAudioManager())
- return NULL;
-
// Starts the audio controller thread.
scoped_refptr<AudioInputController> controller(new AudioInputController(
- event_handler, sync_writer));
+ audio_manager, event_handler, sync_writer));
// Start the thread and post a task to create the audio input stream.
controller->thread_.Start();
@@ -114,8 +118,7 @@ void AudioInputController::Close() {
void AudioInputController::DoCreate(const AudioParameters& params,
const std::string& device_id) {
- stream_ = AudioManager::GetAudioManager()->MakeAudioInputStream(params,
- device_id);
+ stream_ = audio_manager_->MakeAudioInputStream(params, device_id);
if (!stream_) {
// TODO(satish): Define error types.
diff --git a/media/audio/audio_input_controller.h b/media/audio/audio_input_controller.h
index 387041a..e929467 100644
--- a/media/audio/audio_input_controller.h
+++ b/media/audio/audio_input_controller.h
@@ -5,6 +5,7 @@
#ifndef MEDIA_AUDIO_AUDIO_INPUT_CONTROLLER_H_
#define MEDIA_AUDIO_AUDIO_INPUT_CONTROLLER_H_
+#include <string>
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/synchronization/lock.h"
@@ -73,8 +74,10 @@ class MEDIA_EXPORT AudioInputController
// create the AudioInputController. Factory is intended for testing.
class Factory {
public:
- virtual AudioInputController* Create(EventHandler* event_handler,
- AudioParameters params) = 0;
+ virtual AudioInputController* Create(
+ AudioManager* audio_manager,
+ EventHandler* event_handler,
+ AudioParameters params) = 0;
protected:
virtual ~Factory() {}
};
@@ -86,11 +89,13 @@ class MEDIA_EXPORT AudioInputController
// device will be created on the new thread and when that is done event
// handler will receive a OnCreated() call.
static scoped_refptr<AudioInputController> Create(
+ AudioManager* audio_manager,
EventHandler* event_handler,
const AudioParameters& params);
// Factory method for creating a low latency audio stream.
static scoped_refptr<AudioInputController> CreateLowLatency(
+ AudioManager* audio_manager,
EventHandler* event_handler,
const AudioParameters& params,
const std::string& device_id,
@@ -133,7 +138,8 @@ class MEDIA_EXPORT AudioInputController
kError
};
- AudioInputController(EventHandler* handler, SyncWriter* sync_writer);
+ AudioInputController(AudioManager* audio_manager, EventHandler* handler,
+ SyncWriter* sync_writer);
// The following methods are executed on the audio controller thread.
void DoCreate(const AudioParameters& params, const std::string& device_id);
@@ -143,6 +149,7 @@ class MEDIA_EXPORT AudioInputController
void DoReportNoDataError();
void DoResetNoDataTimer();
+ scoped_refptr<AudioManager> audio_manager_;
EventHandler* handler_;
AudioInputStream* stream_;
diff --git a/media/audio/audio_input_controller_unittest.cc b/media/audio/audio_input_controller_unittest.cc
index 090d97f4..f238426 100644
--- a/media/audio/audio_input_controller_unittest.cc
+++ b/media/audio/audio_input_controller_unittest.cc
@@ -51,10 +51,11 @@ TEST(AudioInputControllerTest, CreateAndClose) {
EXPECT_CALL(event_handler, OnCreated(NotNull()))
.WillOnce(InvokeWithoutArgs(&event, &base::WaitableEvent::Signal));
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
AudioParameters params(AudioParameters::AUDIO_MOCK, kChannelLayout,
kSampleRate, kBitsPerSample, kSamplesPerPacket);
scoped_refptr<AudioInputController> controller =
- AudioInputController::Create(&event_handler, params);
+ AudioInputController::Create(audio_manager, &event_handler, params);
ASSERT_TRUE(controller.get());
// Wait for OnCreated() to be called.
@@ -82,10 +83,11 @@ TEST(AudioInputControllerTest, RecordAndClose) {
.Times(AtLeast(10))
.WillRepeatedly(CheckCountAndSignalEvent(&count, 10, &event));
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
AudioParameters params(AudioParameters::AUDIO_MOCK, kChannelLayout,
kSampleRate, kBitsPerSample, kSamplesPerPacket);
scoped_refptr<AudioInputController> controller =
- AudioInputController::Create(&event_handler, params);
+ AudioInputController::Create(audio_manager, &event_handler, params);
ASSERT_TRUE(controller.get());
// Wait for OnCreated() to be called.
@@ -123,10 +125,11 @@ TEST(AudioInputControllerTest, RecordAndError) {
EXPECT_CALL(event_handler, OnError(NotNull(), 0))
.WillOnce(InvokeWithoutArgs(&event, &base::WaitableEvent::Signal));
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
AudioParameters params(AudioParameters::AUDIO_MOCK, kChannelLayout,
kSampleRate, kBitsPerSample, kSamplesPerPacket);
scoped_refptr<AudioInputController> controller =
- AudioInputController::Create(&event_handler, params);
+ AudioInputController::Create(audio_manager, &event_handler, params);
ASSERT_TRUE(controller.get());
// Wait for OnCreated() to be called.
@@ -151,10 +154,11 @@ TEST(AudioInputControllerTest, SamplesPerPacketTooLarge) {
// Create an audio device with a very large packet size.
MockAudioInputControllerEventHandler event_handler;
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
AudioParameters params(AudioParameters::AUDIO_MOCK, kChannelLayout,
kSampleRate, kBitsPerSample, kSamplesPerPacket * 1000);
scoped_refptr<AudioInputController> controller = AudioInputController::Create(
- &event_handler, params);
+ audio_manager, &event_handler, params);
ASSERT_FALSE(controller);
}
@@ -162,10 +166,11 @@ TEST(AudioInputControllerTest, SamplesPerPacketTooLarge) {
TEST(AudioInputControllerTest, CloseTwice) {
MockAudioInputControllerEventHandler event_handler;
EXPECT_CALL(event_handler, OnCreated(NotNull()));
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
AudioParameters params(AudioParameters::AUDIO_MOCK, kChannelLayout,
kSampleRate, kBitsPerSample, kSamplesPerPacket);
scoped_refptr<AudioInputController> controller =
- AudioInputController::Create(&event_handler, params);
+ AudioInputController::Create(audio_manager, &event_handler, params);
ASSERT_TRUE(controller.get());
controller->Close();
diff --git a/media/audio/audio_input_device_unittest.cc b/media/audio/audio_input_device_unittest.cc
index 2d50f4b..07d98ac 100644
--- a/media/audio/audio_input_device_unittest.cc
+++ b/media/audio/audio_input_device_unittest.cc
@@ -20,22 +20,13 @@ using media::AudioDeviceNames;
class AudioInputDeviceTest
: public ::testing::Test {
protected:
-#if defined(OS_WIN)
- // Store current device-enumeration type to ensure that it can be restored
- // after last test in this test suite.
- static void SetUpTestCase() {
- enumeration_type_ = static_cast<AudioManagerWin*>(
- AudioManager::GetAudioManager())->enumeration_type();
- }
-
- // Restore pre-test state of device-enumeration type.
- static void TearDownTestCase() {
- static_cast<AudioManagerWin*>(
- AudioManager::GetAudioManager())->SetEnumerationType(enumeration_type_);
+ AudioInputDeviceTest() {
+ audio_manager_ = AudioManager::Create();
}
- bool SetMMDeviceEnumeration(AudioManager* audio_manager) {
- AudioManagerWin* amw = static_cast<AudioManagerWin*>(audio_manager);
+#if defined(OS_WIN)
+ bool SetMMDeviceEnumeration() {
+ AudioManagerWin* amw = static_cast<AudioManagerWin*>(audio_manager_.get());
// Windows Wave is used as default if Windows XP was detected =>
// return false since MMDevice is not supported on XP.
if (amw->enumeration_type() == AudioManagerWin::kWaveEnumeration)
@@ -45,20 +36,14 @@ class AudioInputDeviceTest
return true;
}
- void SetWaveEnumeration(AudioManager* audio_manager) {
- AudioManagerWin* amw = static_cast<AudioManagerWin*>(audio_manager);
+ void SetWaveEnumeration() {
+ AudioManagerWin* amw = static_cast<AudioManagerWin*>(audio_manager_.get());
amw->SetEnumerationType(AudioManagerWin::kWaveEnumeration);
}
-
- // Stores the pre-test state representing the device-enumeration type.
- static AudioManagerWin::EnumerationType enumeration_type_;
#endif
-};
-#if defined(OS_WIN)
-AudioManagerWin::EnumerationType AudioInputDeviceTest::enumeration_type_ =
- AudioManagerWin::kUninitializedEnumeration;
-#endif
+ scoped_refptr<AudioManager> audio_manager_;
+};
// Convenience method which ensures that we are not running on the build
// bots which lacks audio device support.
@@ -102,9 +87,7 @@ TEST_F(AudioInputDeviceTest, EnumerateDevices) {
// The MMDevice API requires a correct COM environment.
ScopedCOMInitializer com_init(ScopedCOMInitializer::kMTA);
AudioDeviceNames device_names;
- AudioManager* audio_man = AudioManager::GetAudioManager();
- EXPECT_TRUE(audio_man != NULL);
- audio_man->GetAudioInputDeviceNames(&device_names);
+ audio_manager_->GetAudioInputDeviceNames(&device_names);
CheckDeviceNames(device_names);
}
@@ -121,12 +104,11 @@ TEST_F(AudioInputDeviceTest, EnumerateDevicesWinMMDevice) {
// The MMDevice API requires a correct COM environment.
ScopedCOMInitializer com_init(ScopedCOMInitializer::kMTA);
AudioDeviceNames device_names;
- AudioManager* audio_man = AudioManager::GetAudioManager();
- if (!SetMMDeviceEnumeration(audio_man)) {
+ if (!SetMMDeviceEnumeration()) {
// Usage of MMDevice will fail on XP and lower.
return;
}
- audio_man->GetAudioInputDeviceNames(&device_names);
+ audio_manager_->GetAudioInputDeviceNames(&device_names);
CheckDeviceNames(device_names);
}
@@ -136,10 +118,8 @@ TEST_F(AudioInputDeviceTest, EnumerateDevicesWinWave) {
if (!CanRunAudioTests())
return;
AudioDeviceNames device_names;
- AudioManager* audio_man = AudioManager::GetAudioManager();
- EXPECT_TRUE(audio_man != NULL);
- SetWaveEnumeration(audio_man);
- audio_man->GetAudioInputDeviceNames(&device_names);
+ SetWaveEnumeration();
+ audio_manager_->GetAudioInputDeviceNames(&device_names);
CheckDeviceNames(device_names);
}
diff --git a/media/audio/audio_input_unittest.cc b/media/audio/audio_input_unittest.cc
index da07c53..5faa2e9 100644
--- a/media/audio/audio_input_unittest.cc
+++ b/media/audio/audio_input_unittest.cc
@@ -31,7 +31,7 @@ class TestInputCallback : public AudioInputStream::AudioInputCallback {
if (size) {
ASSERT_LE(static_cast<int>(size), max_data_bytes_);
int value = data[0];
- EXPECT_TRUE(value >= 0);
+ EXPECT_GE(value, 0);
}
}
virtual void OnClose(AudioInputStream* stream) {
@@ -87,20 +87,18 @@ class TestInputCallbackBlocking : public TestInputCallback {
int block_for_ms_;
};
-static bool CanRunAudioTests() {
- scoped_ptr<base::Environment> env(base::Environment::Create());
- if (env->HasVar("CHROME_HEADLESS"))
+static bool CanRunAudioTests(AudioManager* audio_man) {
+ if (NULL == audio_man)
return false;
- AudioManager* audio_man = AudioManager::GetAudioManager();
- if (NULL == audio_man)
+ scoped_ptr<base::Environment> env(base::Environment::Create());
+ if (env->HasVar("CHROME_HEADLESS"))
return false;
return audio_man->HasAudioInputDevices();
}
-static AudioInputStream* CreateTestAudioInputStream() {
- AudioManager* audio_man = AudioManager::GetAudioManager();
+static AudioInputStream* CreateTestAudioInputStream(AudioManager* audio_man) {
AudioInputStream* ais = audio_man->MakeAudioInputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO,
kSamplingRate, 16, kSamplesPerPacket),
@@ -111,9 +109,10 @@ static AudioInputStream* CreateTestAudioInputStream() {
// Test that AudioInputStream rejects out of range parameters.
TEST(AudioInputTest, SanityOnMakeParams) {
- if (!CanRunAudioTests())
+ scoped_refptr<AudioManager> audio_man(AudioManager::Create());
+ if (!CanRunAudioTests(audio_man.get()))
return;
- AudioManager* audio_man = AudioManager::GetAudioManager();
+
AudioParameters::Format fmt = AudioParameters::AUDIO_PCM_LINEAR;
EXPECT_TRUE(NULL == audio_man->MakeAudioInputStream(
AudioParameters(fmt, CHANNEL_LAYOUT_7POINT1, 8000, 16,
@@ -144,26 +143,29 @@ TEST(AudioInputTest, SanityOnMakeParams) {
// Test create and close of an AudioInputStream without recording audio.
TEST(AudioInputTest, CreateAndClose) {
- if (!CanRunAudioTests())
+ scoped_refptr<AudioManager> audio_man(AudioManager::Create());
+ if (!CanRunAudioTests(audio_man.get()))
return;
- AudioInputStream* ais = CreateTestAudioInputStream();
+ AudioInputStream* ais = CreateTestAudioInputStream(audio_man.get());
ais->Close();
}
// Test create, open and close of an AudioInputStream without recording audio.
TEST(AudioInputTest, OpenAndClose) {
- if (!CanRunAudioTests())
+ scoped_refptr<AudioManager> audio_man(AudioManager::Create());
+ if (!CanRunAudioTests(audio_man.get()))
return;
- AudioInputStream* ais = CreateTestAudioInputStream();
+ AudioInputStream* ais = CreateTestAudioInputStream(audio_man.get());
EXPECT_TRUE(ais->Open());
ais->Close();
}
// Test create, open, stop and close of an AudioInputStream without recording.
TEST(AudioInputTest, OpenStopAndClose) {
- if (!CanRunAudioTests())
+ scoped_refptr<AudioManager> audio_man(AudioManager::Create());
+ if (!CanRunAudioTests(audio_man.get()))
return;
- AudioInputStream* ais = CreateTestAudioInputStream();
+ AudioInputStream* ais = CreateTestAudioInputStream(audio_man.get());
EXPECT_TRUE(ais->Open());
ais->Stop();
ais->Close();
@@ -171,10 +173,11 @@ TEST(AudioInputTest, OpenStopAndClose) {
// Test a normal recording sequence using an AudioInputStream.
TEST(AudioInputTest, Record) {
- if (!CanRunAudioTests())
+ scoped_refptr<AudioManager> audio_man(AudioManager::Create());
+ if (!CanRunAudioTests(audio_man.get()))
return;
MessageLoop message_loop(MessageLoop::TYPE_DEFAULT);
- AudioInputStream* ais = CreateTestAudioInputStream();
+ AudioInputStream* ais = CreateTestAudioInputStream(audio_man.get());
EXPECT_TRUE(ais->Open());
TestInputCallback test_callback(kSamplesPerPacket * 4);
@@ -192,10 +195,11 @@ TEST(AudioInputTest, Record) {
// Test a recording sequence with delays in the audio callback.
TEST(AudioInputTest, RecordWithSlowSink) {
- if (!CanRunAudioTests())
+ scoped_refptr<AudioManager> audio_man(AudioManager::Create());
+ if (!CanRunAudioTests(audio_man.get()))
return;
MessageLoop message_loop(MessageLoop::TYPE_DEFAULT);
- AudioInputStream* ais = CreateTestAudioInputStream();
+ AudioInputStream* ais = CreateTestAudioInputStream(audio_man.get());
EXPECT_TRUE(ais->Open());
// We should normally get a callback every 50ms, and a 20ms delay inside each
diff --git a/media/audio/audio_manager.cc b/media/audio/audio_manager.cc
index 45c67f9..295aa06 100644
--- a/media/audio/audio_manager.cc
+++ b/media/audio/audio_manager.cc
@@ -6,39 +6,38 @@
#include "base/at_exit.h"
#include "base/logging.h"
+#include "base/message_loop.h"
-static bool g_destroy_called = false;
+// Used only to make sure we never create more than one instance.
static AudioManager* g_audio_manager = NULL;
-// static
-void AudioManager::Destroy(void* not_used) {
- g_destroy_called = true;
+// Forward declaration of the platform specific AudioManager factory function.
+AudioManager* CreateAudioManager();
- if (g_audio_manager) {
- g_audio_manager->Cleanup();
+AudioManager::AudioManager() {
+ CHECK(g_audio_manager == NULL);
+ g_audio_manager = this;
+}
- AudioManager* audio_manager = g_audio_manager;
- g_audio_manager = NULL;
- delete audio_manager;
- }
+AudioManager::~AudioManager() {
+ CHECK(g_audio_manager == this);
+ g_audio_manager = NULL;
}
-// static
-AudioManager* AudioManager::GetAudioManager() {
- if (!g_audio_manager && !g_destroy_called) {
- g_audio_manager = CreateAudioManager();
- g_audio_manager->Init();
- base::AtExitManager::RegisterCallback(&AudioManager::Destroy, NULL);
- }
- return g_audio_manager;
+#ifndef NDEBUG
+void AudioManager::AddRef() const {
+ base::RefCountedThreadSafe<AudioManager>::AddRef();
}
-// static
-bool AudioManager::SingletonExists() {
- return g_audio_manager != NULL;
+void AudioManager::Release() const {
+ base::RefCountedThreadSafe<AudioManager>::Release();
}
+#endif
// static
-void AudioManager::Resurrect() {
- g_destroy_called = false;
+scoped_refptr<AudioManager> AudioManager::Create() {
+ AudioManager* ret = CreateAudioManager();
+ DCHECK(ret == g_audio_manager);
+ ret->Init();
+ return ret;
}
diff --git a/media/audio/audio_manager.h b/media/audio/audio_manager.h
index 817761a..74d839b 100644
--- a/media/audio/audio_manager.h
+++ b/media/audio/audio_manager.h
@@ -5,7 +5,10 @@
#ifndef MEDIA_AUDIO_AUDIO_MANAGER_H_
#define MEDIA_AUDIO_AUDIO_MANAGER_H_
+#include <string>
+
#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
#include "base/string16.h"
#include "base/task.h"
#include "media/audio/audio_device_name.h"
@@ -15,14 +18,29 @@ class AudioInputStream;
class AudioOutputStream;
class MessageLoop;
-// TODO(sergeyu): In this interface and some other places AudioParameters struct
-// is passed by value. It is better to change it to const reference.
-
// Manages all audio resources. In particular it owns the AudioOutputStream
// objects. Provides some convenience functions that avoid the need to provide
// iterators over the existing streams.
-class MEDIA_EXPORT AudioManager {
+// TODO(tommi): Make the manager non-refcounted when it's safe to do so.
+// -> Bug 107087.
+class MEDIA_EXPORT AudioManager
+ : public base::RefCountedThreadSafe<AudioManager> {
public:
+ AudioManager();
+
+#ifndef NDEBUG
+ // Allow base classes in debug builds to override the reference counting
+ // functions. This allows us to protect against regressions and enforce
+ // correct usage. The default implementation just calls the base class.
+ virtual void AddRef() const;
+ virtual void Release() const;
+#endif
+
+ // Use to construct the audio manager.
+ // NOTE: There should only be one instance. If you try to create more than
+ // one instance, it will hit a CHECK().
+ static scoped_refptr<AudioManager> Create();
+
// Returns true if the OS reports existence of audio devices. This does not
// guarantee that the existing devices support all formats and sample rates.
virtual bool HasAudioOutputDevices() = 0;
@@ -106,28 +124,12 @@ class MEDIA_EXPORT AudioManager {
// Returns message loop used for audio IO.
virtual MessageLoop* GetMessageLoop() = 0;
- // Get AudioManager singleton.
- // TODO(cpu): Define threading requirements for interacting with AudioManager.
- static AudioManager* GetAudioManager();
-
protected:
- virtual ~AudioManager() {}
-
- // Called from GetAudioManager() to initialiaze the instance.
+ // Called from Create() to initialize the instance.
virtual void Init() = 0;
- // Called by Destroy() to cleanup the instance before destruction.
- virtual void Cleanup() = 0;
-
- private:
- // Allow unit tests to delete and recreate the singleton.
- friend class AutoAudioManagerCleanup;
- static void Destroy(void*);
- static bool SingletonExists();
- static void Resurrect();
-
- // Called by GetAudioManager() to create platform-specific audio manager.
- static AudioManager* CreateAudioManager();
+ friend class base::RefCountedThreadSafe<AudioManager>;
+ virtual ~AudioManager();
};
DISABLE_RUNNABLE_METHOD_REFCOUNT(AudioManager);
diff --git a/media/audio/audio_manager_base.cc b/media/audio/audio_manager_base.cc
index 0c872ce..3af7f69 100644
--- a/media/audio/audio_manager_base.cc
+++ b/media/audio/audio_manager_base.cc
@@ -3,6 +3,8 @@
// found in the LICENSE file.
#include "media/audio/audio_manager_base.h"
+
+#include "base/bind.h"
#include "media/audio/audio_output_dispatcher.h"
#include "media/audio/audio_output_proxy.h"
@@ -13,23 +15,29 @@ const char AudioManagerBase::kDefaultDeviceId[] = "default";
AudioManagerBase::AudioManagerBase()
: audio_thread_("AudioThread"),
- initialized_(false),
num_active_input_streams_(0) {
}
AudioManagerBase::~AudioManagerBase() {
- DCHECK(!audio_thread_.IsRunning());
+ Shutdown();
}
-void AudioManagerBase::Init() {
- initialized_ = audio_thread_.Start();
+#ifndef NDEBUG
+void AudioManagerBase::AddRef() const {
+ const MessageLoop* loop = audio_thread_.message_loop();
+ DCHECK(loop == NULL || loop != MessageLoop::current());
+ AudioManager::AddRef();
}
-void AudioManagerBase::Cleanup() {
- if (initialized_) {
- initialized_ = false;
- audio_thread_.Stop();
- }
+void AudioManagerBase::Release() const {
+ const MessageLoop* loop = audio_thread_.message_loop();
+ DCHECK(loop == NULL || loop != MessageLoop::current());
+ AudioManager::Release();
+}
+#endif
+
+void AudioManagerBase::Init() {
+ CHECK(audio_thread_.Start());
}
string16 AudioManagerBase::GetAudioInputDeviceModel() {
@@ -37,20 +45,20 @@ string16 AudioManagerBase::GetAudioInputDeviceModel() {
}
MessageLoop* AudioManagerBase::GetMessageLoop() {
- DCHECK(initialized_);
return audio_thread_.message_loop();
}
AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy(
const AudioParameters& params) {
- if (!initialized_)
+ DCHECK_EQ(MessageLoop::current(), GetMessageLoop());
+
+ if (!initialized())
return NULL;
scoped_refptr<AudioOutputDispatcher>& dispatcher =
output_dispatchers_[params];
if (!dispatcher)
dispatcher = new AudioOutputDispatcher(this, params, kStreamCloseDelayMs);
-
return new AudioOutputProxy(dispatcher);
}
@@ -66,17 +74,50 @@ void AudioManagerBase::GetAudioInputDeviceNames(
}
void AudioManagerBase::IncreaseActiveInputStreamCount() {
- base::AutoLock auto_lock(active_input_streams_lock_);
- ++num_active_input_streams_;
+ base::AtomicRefCountInc(&num_active_input_streams_);
}
void AudioManagerBase::DecreaseActiveInputStreamCount() {
- base::AutoLock auto_lock(active_input_streams_lock_);
- DCHECK_GT(num_active_input_streams_, 0);
- --num_active_input_streams_;
+ DCHECK(IsRecordingInProcess());
+ base::AtomicRefCountDec(&num_active_input_streams_);
}
bool AudioManagerBase::IsRecordingInProcess() {
- base::AutoLock auto_lock(active_input_streams_lock_);
- return num_active_input_streams_ > 0;
+ return !base::AtomicRefCountIsZero(&num_active_input_streams_);
+}
+
+void AudioManagerBase::Shutdown() {
+ if (!initialized())
+ return;
+
+ DCHECK_NE(MessageLoop::current(), GetMessageLoop());
+
+ // We must use base::Unretained since Shutdown might have been called from
+ // the destructor and we can't alter the refcount of the object at that point.
+ GetMessageLoop()->PostTask(FROM_HERE, base::Bind(
+ &AudioManagerBase::ShutdownOnAudioThread,
+ base::Unretained(this)));
+ // Stop() will wait for any posted messages to be processed first.
+ audio_thread_.Stop();
+}
+
+void AudioManagerBase::ShutdownOnAudioThread() {
+ DCHECK_EQ(MessageLoop::current(), GetMessageLoop());
+
+ AudioOutputDispatchersMap::iterator it = output_dispatchers_.begin();
+ for (; it != output_dispatchers_.end(); ++it) {
+ scoped_refptr<AudioOutputDispatcher>& dispatcher = (*it).second;
+ if (dispatcher) {
+ dispatcher->Shutdown();
+ // All AudioOutputProxies must have been freed before Shutdown is called.
+ // If they still exist, things will go bad. They have direct pointers to
+ // both physical audio stream objects that belong to the dispatcher as
+ // well as the message loop of the audio thread that will soon go away.
+ // So, better crash now than later.
+ CHECK(dispatcher->HasOneRef()) << "AudioOutputProxies are still alive";
+ dispatcher = NULL;
+ }
+ }
+
+ output_dispatchers_.clear();
}
diff --git a/media/audio/audio_manager_base.h b/media/audio/audio_manager_base.h
index 025c35f..15e18be 100644
--- a/media/audio/audio_manager_base.h
+++ b/media/audio/audio_manager_base.h
@@ -7,6 +7,7 @@
#include <map>
+#include "base/atomic_ref_count.h"
#include "base/compiler_specific.h"
#include "base/threading/thread.h"
#include "media/audio/audio_manager.h"
@@ -23,8 +24,15 @@ class MEDIA_EXPORT AudioManagerBase : public AudioManager {
AudioManagerBase();
+#ifndef NDEBUG
+ // Overridden to make sure we don't accidentally get added reference counts on
+ // the audio thread. The AudioManagerBase instance must always be deleted
+ // from outside the audio thread.
+ virtual void AddRef() const OVERRIDE;
+ virtual void Release() const OVERRIDE;
+#endif
+
virtual void Init() OVERRIDE;
- virtual void Cleanup() OVERRIDE;
virtual MessageLoop* GetMessageLoop() OVERRIDE;
@@ -44,6 +52,11 @@ class MEDIA_EXPORT AudioManagerBase : public AudioManager {
void IncreaseActiveInputStreamCount();
void DecreaseActiveInputStreamCount();
+ // Shuts down the audio thread and releases all the audio output dispatchers
+ // on the audio thread. All AudioOutputProxy instances should be freed before
+ // Shutdown is called.
+ void Shutdown();
+
protected:
virtual ~AudioManagerBase();
@@ -51,24 +64,19 @@ class MEDIA_EXPORT AudioManagerBase : public AudioManager {
AudioParameters::Compare>
AudioOutputDispatchersMap;
- bool initialized() { return initialized_; }
+ void ShutdownOnAudioThread();
+
+ bool initialized() { return audio_thread_.IsRunning(); }
// Thread used to interact with AudioOutputStreams created by this
// audio manger.
base::Thread audio_thread_;
- bool initialized_;
-
AudioOutputDispatchersMap output_dispatchers_;
// Counts the number of active input streams to find out if something else
// is currently recording in Chrome.
- int num_active_input_streams_;
-
- // Lock used to synchronize the access to num_active_input_streams_.
- // Do not use for anything else and try to avoid using other locks
- // in this code whenever possible.
- base::Lock active_input_streams_lock_;
+ base::AtomicRefCount num_active_input_streams_;
DISALLOW_COPY_AND_ASSIGN(AudioManagerBase);
};
diff --git a/media/audio/audio_output_controller.cc b/media/audio/audio_output_controller.cc
index b83aa61..d3cca44 100644
--- a/media/audio/audio_output_controller.cc
+++ b/media/audio/audio_output_controller.cc
@@ -21,10 +21,12 @@ const int AudioOutputController::kPauseMark = -1;
const int AudioOutputController::kPollNumAttempts = 3;
const int AudioOutputController::kPollPauseInMilliseconds = 3;
-AudioOutputController::AudioOutputController(EventHandler* handler,
+AudioOutputController::AudioOutputController(AudioManager* audio_manager,
+ EventHandler* handler,
uint32 capacity,
SyncReader* sync_reader)
- : handler_(handler),
+ : audio_manager_(audio_manager),
+ handler_(handler),
stream_(NULL),
volume_(1.0),
state_(kEmpty),
@@ -32,7 +34,8 @@ AudioOutputController::AudioOutputController(EventHandler* handler,
pending_request_(false),
sync_reader_(sync_reader),
message_loop_(NULL),
- number_polling_attempts_left_(0) {
+ number_polling_attempts_left_(0),
+ ALLOW_THIS_IN_INITIALIZER_LIST(weak_this_(this)) {
}
AudioOutputController::~AudioOutputController() {
@@ -42,81 +45,77 @@ AudioOutputController::~AudioOutputController() {
// static
scoped_refptr<AudioOutputController> AudioOutputController::Create(
+ AudioManager* audio_manager,
EventHandler* event_handler,
const AudioParameters& params,
uint32 buffer_capacity) {
-
- if (!params.IsValid())
- return NULL;
-
- if (!AudioManager::GetAudioManager())
+ DCHECK(audio_manager);
+ if (!params.IsValid() || !audio_manager)
return NULL;
// Starts the audio controller thread.
scoped_refptr<AudioOutputController> controller(new AudioOutputController(
- event_handler, buffer_capacity, NULL));
+ audio_manager, event_handler, buffer_capacity, NULL));
- controller->message_loop_ =
- AudioManager::GetAudioManager()->GetMessageLoop();
+ controller->message_loop_ = audio_manager->GetMessageLoop();
controller->message_loop_->PostTask(FROM_HERE, base::Bind(
- &AudioOutputController::DoCreate, controller.get(), params));
+ &AudioOutputController::DoCreate, base::Unretained(controller.get()),
+ params));
return controller;
}
// static
scoped_refptr<AudioOutputController> AudioOutputController::CreateLowLatency(
+ AudioManager* audio_manager,
EventHandler* event_handler,
const AudioParameters& params,
SyncReader* sync_reader) {
-
+ DCHECK(audio_manager);
DCHECK(sync_reader);
- if (!params.IsValid())
- return NULL;
-
- if (!AudioManager::GetAudioManager())
+ if (!params.IsValid() || !audio_manager)
return NULL;
// Starts the audio controller thread.
scoped_refptr<AudioOutputController> controller(new AudioOutputController(
- event_handler, 0, sync_reader));
+ audio_manager, event_handler, 0, sync_reader));
- controller->message_loop_ =
- AudioManager::GetAudioManager()->GetMessageLoop();
+ controller->message_loop_ = audio_manager->GetMessageLoop();
controller->message_loop_->PostTask(FROM_HERE, base::Bind(
- &AudioOutputController::DoCreate, controller.get(), params));
+ &AudioOutputController::DoCreate, base::Unretained(controller.get()),
+ params));
return controller;
}
void AudioOutputController::Play() {
DCHECK(message_loop_);
message_loop_->PostTask(FROM_HERE, base::Bind(
- &AudioOutputController::DoPlay, this));
+ &AudioOutputController::DoPlay, base::Unretained(this)));
}
void AudioOutputController::Pause() {
DCHECK(message_loop_);
message_loop_->PostTask(FROM_HERE, base::Bind(
- &AudioOutputController::DoPause, this));
+ &AudioOutputController::DoPause, base::Unretained(this)));
}
void AudioOutputController::Flush() {
DCHECK(message_loop_);
message_loop_->PostTask(FROM_HERE, base::Bind(
- &AudioOutputController::DoFlush, this));
+ &AudioOutputController::DoFlush, base::Unretained(this)));
}
void AudioOutputController::Close(const base::Closure& closed_task) {
DCHECK(!closed_task.is_null());
DCHECK(message_loop_);
message_loop_->PostTask(FROM_HERE, base::Bind(
- &AudioOutputController::DoClose, this, closed_task));
+ &AudioOutputController::DoClose, base::Unretained(this), closed_task));
}
void AudioOutputController::SetVolume(double volume) {
DCHECK(message_loop_);
message_loop_->PostTask(FROM_HERE, base::Bind(
- &AudioOutputController::DoSetVolume, this, volume));
+ &AudioOutputController::DoSetVolume, base::Unretained(this), volume));
}
void AudioOutputController::EnqueueData(const uint8* data, uint32 size) {
@@ -140,11 +139,8 @@ void AudioOutputController::DoCreate(const AudioParameters& params) {
return;
DCHECK_EQ(kEmpty, state_);
- if (!AudioManager::GetAudioManager())
- return;
-
StopCloseAndClearStream();
- stream_ = AudioManager::GetAudioManager()->MakeAudioOutputStreamProxy(params);
+ stream_ = audio_manager_->MakeAudioOutputStreamProxy(params);
if (!stream_) {
// TODO(hclam): Define error types.
handler_->OnError(this, 0);
@@ -193,7 +189,8 @@ void AudioOutputController::DoPlay() {
number_polling_attempts_left_ = kPollNumAttempts;
message_loop_->PostDelayedTask(
FROM_HERE,
- base::Bind(&AudioOutputController::PollAndStartIfDataReady, this),
+ base::Bind(&AudioOutputController::PollAndStartIfDataReady,
+ weak_this_.GetWeakPtr()),
kPollPauseInMilliseconds);
} else {
StartStream();
@@ -203,7 +200,7 @@ void AudioOutputController::DoPlay() {
void AudioOutputController::PollAndStartIfDataReady() {
DCHECK_EQ(message_loop_, MessageLoop::current());
- // Being paranoic: do nothing if state unexpectedly changed.
+ // Being paranoid: do nothing if state unexpectedly changed.
if ((state_ != kStarting) && (state_ != kPausedWhenStarting))
return;
@@ -220,7 +217,8 @@ void AudioOutputController::PollAndStartIfDataReady() {
} else {
message_loop_->PostDelayedTask(
FROM_HERE,
- base::Bind(&AudioOutputController::PollAndStartIfDataReady, this),
+ base::Bind(&AudioOutputController::PollAndStartIfDataReady,
+ weak_this_.GetWeakPtr()),
kPollPauseInMilliseconds);
}
}
@@ -379,7 +377,7 @@ void AudioOutputController::WaitTillDataReady() {
void AudioOutputController::OnError(AudioOutputStream* stream, int code) {
// Handle error on the audio controller thread.
message_loop_->PostTask(FROM_HERE, base::Bind(
- &AudioOutputController::DoReportError, this, code));
+ &AudioOutputController::DoReportError, base::Unretained(this), code));
}
void AudioOutputController::SubmitOnMoreData_Locked() {
@@ -409,6 +407,7 @@ void AudioOutputController::StopCloseAndClearStream() {
stream_->Stop();
stream_->Close();
stream_ = NULL;
+ weak_this_.InvalidateWeakPtrs();
}
} // namespace media
diff --git a/media/audio/audio_output_controller.h b/media/audio/audio_output_controller.h
index d60af07..5234f58 100644
--- a/media/audio/audio_output_controller.h
+++ b/media/audio/audio_output_controller.h
@@ -8,6 +8,7 @@
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "base/synchronization/lock.h"
#include "base/time.h"
#include "media/audio/audio_buffers_state.h"
@@ -22,8 +23,8 @@ class MessageLoop;
// audio operations like play, pause, stop, etc. on a separate thread,
// namely the audio controller thread.
//
-// All the public methods of AudioOutputController are non-blocking except
-// close, the actual operations are performed on the audio controller thread.
+// All the public methods of AudioOutputController are non-blocking.
+// The actual operations are performed on the audio thread.
//
// Here is a state diagram for the AudioOutputController for default low
// latency mode; in normal latency mode there is no "starting" or "paused when
@@ -53,6 +54,16 @@ class MessageLoop;
// In this mode a DataSource object is given to the AudioOutputController
// and AudioOutputController reads from it synchronously.
//
+// The audio thread itself is owned by the AudioManager that the
+// AudioOutputController holds a reference to. When performing tasks on the
+// audio thread, the controller must not add or release references to the
+// AudioManager or itself (since it in turn holds a reference to the manager),
+// for delayed tasks as it can slow down or even prevent normal shut down.
+// So, for tasks on the audio thread, the controller uses WeakPtr which enables
+// us to safely cancel pending polling tasks.
+// The owner of the audio thread, AudioManager, will take care of properly
+// shutting it down.
+//
#include "media/base/media_export.h"
namespace media {
@@ -115,6 +126,7 @@ class MEDIA_EXPORT AudioOutputController
// will be created on the audio controller thread and when that is done
// event handler will receive a OnCreated() call.
static scoped_refptr<AudioOutputController> Create(
+ AudioManager* audio_manager,
EventHandler* event_handler,
const AudioParameters& params,
// Soft limit for buffer capacity in this controller. This parameter
@@ -123,6 +135,7 @@ class MEDIA_EXPORT AudioOutputController
// Factory method for creating a low latency audio stream.
static scoped_refptr<AudioOutputController> CreateLowLatency(
+ AudioManager* audio_manager,
EventHandler* event_handler,
const AudioParameters& params,
// External synchronous reader for audio controller.
@@ -186,7 +199,8 @@ class MEDIA_EXPORT AudioOutputController
static const int kPollNumAttempts;
static const int kPollPauseInMilliseconds;
- AudioOutputController(EventHandler* handler,
+ AudioOutputController(AudioManager* audio_manager,
+ EventHandler* handler,
uint32 capacity, SyncReader* sync_reader);
// The following methods are executed on the audio controller thread.
@@ -208,6 +222,7 @@ class MEDIA_EXPORT AudioOutputController
// Helper method that stops, closes, and NULLs |*stream_|.
void StopCloseAndClearStream();
+ scoped_refptr<AudioManager> audio_manager_;
// |handler_| may be called only if |state_| is not kClosed.
EventHandler* handler_;
AudioOutputStream* stream_;
@@ -239,9 +254,15 @@ class MEDIA_EXPORT AudioOutputController
// Number of times left.
int number_polling_attempts_left_;
+ // Used to post delayed tasks to ourselves that we can cancel.
+ // We don't want the tasks to hold onto a reference as it will slow down
+ // shutdown and force it to wait for the most delayed task.
+ // Also, if we're shutting down, we do not want to poll for more data.
+ base::WeakPtrFactory<AudioOutputController> weak_this_;
+
DISALLOW_COPY_AND_ASSIGN(AudioOutputController);
};
} // namespace media
-#endif // MEDIA_AUDIO_AUDIO_OUTPUT_CONTROLLER_H_
+#endif // MEDIA_AUDIO_AUDIO_OUTPUT_CONTROLLER_H_
diff --git a/media/audio/audio_output_controller_unittest.cc b/media/audio/audio_output_controller_unittest.cc
index 74e0e68..c4b0d4e 100644
--- a/media/audio/audio_output_controller_unittest.cc
+++ b/media/audio/audio_output_controller_unittest.cc
@@ -61,12 +61,6 @@ class MockAudioOutputControllerSyncReader
DISALLOW_COPY_AND_ASSIGN(MockAudioOutputControllerSyncReader);
};
-static bool HasAudioOutputDevices() {
- AudioManager* audio_man = AudioManager::GetAudioManager();
- CHECK(audio_man);
- return audio_man->HasAudioOutputDevices();
-}
-
static bool IsRunningHeadless() {
scoped_ptr<base::Environment> env(base::Environment::Create());
if (env->HasVar("CHROME_HEADLESS"))
@@ -91,7 +85,11 @@ static void CloseAudioController(AudioOutputController* controller) {
}
TEST(AudioOutputControllerTest, CreateAndClose) {
- if (!HasAudioOutputDevices() || IsRunningHeadless())
+ if (IsRunningHeadless())
+ return;
+
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
+ if (!audio_manager->HasAudioOutputDevices())
return;
MockAudioOutputControllerEventHandler event_handler;
@@ -103,7 +101,8 @@ TEST(AudioOutputControllerTest, CreateAndClose) {
AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout,
kSampleRate, kBitsPerSample, kSamplesPerPacket);
scoped_refptr<AudioOutputController> controller =
- AudioOutputController::Create(&event_handler, params, kBufferCapacity);
+ AudioOutputController::Create(audio_manager, &event_handler, params,
+ kBufferCapacity);
ASSERT_TRUE(controller.get());
// Close the controller immediately.
@@ -111,7 +110,11 @@ TEST(AudioOutputControllerTest, CreateAndClose) {
}
TEST(AudioOutputControllerTest, PlayAndClose) {
- if (!HasAudioOutputDevices() || IsRunningHeadless())
+ if (IsRunningHeadless())
+ return;
+
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
+ if (!audio_manager->HasAudioOutputDevices())
return;
MockAudioOutputControllerEventHandler event_handler;
@@ -133,7 +136,8 @@ TEST(AudioOutputControllerTest, PlayAndClose) {
AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout,
kSampleRate, kBitsPerSample, kSamplesPerPacket);
scoped_refptr<AudioOutputController> controller =
- AudioOutputController::Create(&event_handler, params, kBufferCapacity);
+ AudioOutputController::Create(audio_manager, &event_handler, params,
+ kBufferCapacity);
ASSERT_TRUE(controller.get());
// Wait for OnCreated() to be called.
@@ -153,7 +157,11 @@ TEST(AudioOutputControllerTest, PlayAndClose) {
}
TEST(AudioOutputControllerTest, PlayAndCloseLowLatency) {
- if (!HasAudioOutputDevices() || IsRunningHeadless())
+ if (IsRunningHeadless())
+ return;
+
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
+ if (!audio_manager->HasAudioOutputDevices())
return;
MockAudioOutputControllerEventHandler event_handler;
@@ -183,7 +191,8 @@ TEST(AudioOutputControllerTest, PlayAndCloseLowLatency) {
AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout,
kSampleRate, kBitsPerSample, kSamplesPerPacket);
scoped_refptr<AudioOutputController> controller =
- AudioOutputController::CreateLowLatency(&event_handler,
+ AudioOutputController::CreateLowLatency(audio_manager,
+ &event_handler,
params,
&sync_reader);
ASSERT_TRUE(controller.get());
@@ -205,7 +214,11 @@ TEST(AudioOutputControllerTest, PlayAndCloseLowLatency) {
}
TEST(AudioOutputControllerTest, PlayPauseClose) {
- if (!HasAudioOutputDevices() || IsRunningHeadless())
+ if (IsRunningHeadless())
+ return;
+
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
+ if (!audio_manager->HasAudioOutputDevices())
return;
MockAudioOutputControllerEventHandler event_handler;
@@ -234,7 +247,8 @@ TEST(AudioOutputControllerTest, PlayPauseClose) {
AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout,
kSampleRate, kBitsPerSample, kSamplesPerPacket);
scoped_refptr<AudioOutputController> controller =
- AudioOutputController::Create(&event_handler, params, kBufferCapacity);
+ AudioOutputController::Create(audio_manager, &event_handler, params,
+ kBufferCapacity);
ASSERT_TRUE(controller.get());
// Wait for OnCreated() to be called.
@@ -259,7 +273,11 @@ TEST(AudioOutputControllerTest, PlayPauseClose) {
}
TEST(AudioOutputControllerTest, PlayPauseCloseLowLatency) {
- if (!HasAudioOutputDevices() || IsRunningHeadless())
+ if (IsRunningHeadless())
+ return;
+
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
+ if (!audio_manager->HasAudioOutputDevices())
return;
MockAudioOutputControllerEventHandler event_handler;
@@ -286,7 +304,8 @@ TEST(AudioOutputControllerTest, PlayPauseCloseLowLatency) {
AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout,
kSampleRate, kBitsPerSample, kSamplesPerPacket);
scoped_refptr<AudioOutputController> controller =
- AudioOutputController::CreateLowLatency(&event_handler,
+ AudioOutputController::CreateLowLatency(audio_manager,
+ &event_handler,
params,
&sync_reader);
ASSERT_TRUE(controller.get());
@@ -304,7 +323,11 @@ TEST(AudioOutputControllerTest, PlayPauseCloseLowLatency) {
}
TEST(AudioOutputControllerTest, PlayPausePlay) {
- if (!HasAudioOutputDevices() || IsRunningHeadless())
+ if (IsRunningHeadless())
+ return;
+
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
+ if (!audio_manager->HasAudioOutputDevices())
return;
MockAudioOutputControllerEventHandler event_handler;
@@ -339,7 +362,8 @@ TEST(AudioOutputControllerTest, PlayPausePlay) {
AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout,
kSampleRate, kBitsPerSample, kSamplesPerPacket);
scoped_refptr<AudioOutputController> controller =
- AudioOutputController::Create(&event_handler, params, kBufferCapacity);
+ AudioOutputController::Create(audio_manager, &event_handler, params,
+ kBufferCapacity);
ASSERT_TRUE(controller.get());
// Wait for OnCreated() to be called.
@@ -374,7 +398,11 @@ TEST(AudioOutputControllerTest, PlayPausePlay) {
}
TEST(AudioOutputControllerTest, HardwareBufferTooLarge) {
- if (!HasAudioOutputDevices() || IsRunningHeadless())
+ if (IsRunningHeadless())
+ return;
+
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
+ if (!audio_manager->HasAudioOutputDevices())
return;
// Create an audio device with a very large hardware buffer size.
@@ -383,7 +411,7 @@ TEST(AudioOutputControllerTest, HardwareBufferTooLarge) {
kSampleRate, kBitsPerSample,
kSamplesPerPacket * 1000);
scoped_refptr<AudioOutputController> controller =
- AudioOutputController::Create(&event_handler, params,
+ AudioOutputController::Create(audio_manager, &event_handler, params,
kBufferCapacity);
// Use assert because we don't stop the device and assume we can't
@@ -392,7 +420,11 @@ TEST(AudioOutputControllerTest, HardwareBufferTooLarge) {
}
TEST(AudioOutputControllerTest, CloseTwice) {
- if (!HasAudioOutputDevices() || IsRunningHeadless())
+ if (IsRunningHeadless())
+ return;
+
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
+ if (!audio_manager->HasAudioOutputDevices())
return;
MockAudioOutputControllerEventHandler event_handler;
@@ -410,7 +442,8 @@ TEST(AudioOutputControllerTest, CloseTwice) {
AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout,
kSampleRate, kBitsPerSample, kSamplesPerPacket);
scoped_refptr<AudioOutputController> controller =
- AudioOutputController::Create(&event_handler, params, kBufferCapacity);
+ AudioOutputController::Create(audio_manager, &event_handler, params,
+ kBufferCapacity);
ASSERT_TRUE(controller.get());
// Wait for OnCreated() to be called.
diff --git a/media/audio/audio_output_dispatcher.cc b/media/audio/audio_output_dispatcher.cc
index 803407e..35c9b55 100644
--- a/media/audio/audio_output_dispatcher.cc
+++ b/media/audio/audio_output_dispatcher.cc
@@ -19,12 +19,16 @@ AudioOutputDispatcher::AudioOutputDispatcher(
pause_delay_milliseconds_(2 * params.samples_per_packet *
base::Time::kMillisecondsPerSecond / params.sample_rate),
paused_proxies_(0),
- ALLOW_THIS_IN_INITIALIZER_LIST(close_timer_(FROM_HERE,
+ ALLOW_THIS_IN_INITIALIZER_LIST(weak_this_(this)),
+ close_timer_(FROM_HERE,
base::TimeDelta::FromMilliseconds(close_delay_ms),
- this, &AudioOutputDispatcher::ClosePendingStreams)) {
+ weak_this_.GetWeakPtr(),
+ &AudioOutputDispatcher::ClosePendingStreams) {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
}
AudioOutputDispatcher::~AudioOutputDispatcher() {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
}
bool AudioOutputDispatcher::StreamOpened() {
@@ -58,7 +62,7 @@ AudioOutputStream* AudioOutputDispatcher::StreamStarted() {
// Schedule task to allocate streams for other proxies if we need to.
message_loop_->PostTask(FROM_HERE, base::Bind(
- &AudioOutputDispatcher::OpenTask, this));
+ &AudioOutputDispatcher::OpenTask, weak_this_.GetWeakPtr()));
return stream;
}
@@ -73,13 +77,17 @@ void AudioOutputDispatcher::StreamStopped(AudioOutputStream* stream) {
// Don't recycle stream until two buffers worth of time has elapsed.
message_loop_->PostDelayedTask(
FROM_HERE,
- base::Bind(&AudioOutputDispatcher::StopStreamTask, this),
+ base::Bind(&AudioOutputDispatcher::StopStreamTask,
+ weak_this_.GetWeakPtr()),
pause_delay_milliseconds_);
}
void AudioOutputDispatcher::StopStreamTask() {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+
if (pausing_streams_.empty())
return;
+
AudioOutputStream* stream = pausing_streams_.back();
pausing_streams_.pop_back();
idle_streams_.push_back(stream);
@@ -103,16 +111,36 @@ void AudioOutputDispatcher::StreamClosed() {
}
}
+void AudioOutputDispatcher::Shutdown() {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+
+ // Cancel any pending tasks to close paused streams or create new ones.
+ weak_this_.InvalidateWeakPtrs();
+
+ // No AudioOutputProxy objects should hold a reference to us when we get
+ // to this stage.
+ DCHECK(HasOneRef()) << "Only the AudioManager should hold a reference";
+
+ AudioOutputStreamList::iterator it = idle_streams_.begin();
+ for (; it != idle_streams_.end(); ++it)
+ (*it)->Close();
+ idle_streams_.clear();
+
+ it = pausing_streams_.begin();
+ for (; it != pausing_streams_.end(); ++it)
+ (*it)->Close();
+ pausing_streams_.clear();
+}
+
MessageLoop* AudioOutputDispatcher::message_loop() {
return message_loop_;
}
bool AudioOutputDispatcher::CreateAndOpenStream() {
- AudioOutputStream* stream =
- audio_manager_->MakeAudioOutputStream(params_);
- if (!stream) {
+ AudioOutputStream* stream = audio_manager_->MakeAudioOutputStream(params_);
+ if (!stream)
return false;
- }
+
if (!stream->Open()) {
stream->Close();
return false;
@@ -134,6 +162,8 @@ void AudioOutputDispatcher::OpenTask() {
// This method is called by |close_timer_|.
void AudioOutputDispatcher::ClosePendingStreams() {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+
while (!idle_streams_.empty()) {
idle_streams_.back()->Close();
idle_streams_.pop_back();
diff --git a/media/audio/audio_output_dispatcher.h b/media/audio/audio_output_dispatcher.h
index 7a4d019..5602d2a 100644
--- a/media/audio/audio_output_dispatcher.h
+++ b/media/audio/audio_output_dispatcher.h
@@ -2,21 +2,22 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// AudioOutputDispatcher dispatches creation and deletion of audio
-// output streams. AudioOutputProxy objects use this class to allocate
-// and recycle actual audio output streams. When playback is started,
-// the proxy calls StreamStarted() to get an output stream that it
-// uses to play the sound. When playback is stopped, the proxy returns
-// the stream back to the dispatcher by calling StreamStopped().
+// AudioOutputDispatcher is a single-threaded class that dispatches creation and
+// deletion of audio output streams. AudioOutputProxy objects use this class to
+// allocate and recycle actual audio output streams. When playback is started,
+// the proxy calls StreamStarted() to get an output stream that it uses to play
+// audio. When playback is stopped, the proxy returns the stream back to the
+// dispatcher by calling StreamStopped().
//
-// To avoid opening and closing audio devices more frequently than it
-// is neccessary, each dispatcher has a pool of inactive physical
-// streams. A stream is closed only if it hasn't been used for a
-// certain period of time (specified in the constructor).
+// To avoid opening and closing audio devices more frequently than necessary,
+// each dispatcher has a pool of inactive physical streams. A stream is closed
+// only if it hasn't been used for a certain period of time (specified via the
+// constructor).
//
-// AudioManagerBase creates one AudioOutputDispatcher per each
-// possible set of audio parameters, i.e. streams with different
-// parameters are managed independently.
+// AudioManagerBase creates one AudioOutputDispatcher on the audio thread for
+// each possible set of audio parameters. I.e streams with different parameters
+// are managed independently. The AudioOutputDispatcher instance is then
+// deleted on the audio thread when the AudioManager shuts down.
#ifndef MEDIA_AUDIO_AUDIO_OUTPUT_DISPATCHER_H_
#define MEDIA_AUDIO_AUDIO_OUTPUT_DISPATCHER_H_
@@ -26,6 +27,7 @@
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
#include "base/timer.h"
#include "media/audio/audio_manager.h"
#include "media/audio/audio_parameters.h"
@@ -64,6 +66,9 @@ class MEDIA_EXPORT AudioOutputDispatcher
// Called by AudioOutputProxy when the stream is closed.
void StreamClosed();
+ // Called on the audio thread when the AudioManager is shutting down.
+ void Shutdown();
+
MessageLoop* message_loop();
private:
@@ -85,14 +90,20 @@ class MEDIA_EXPORT AudioOutputDispatcher
// Called by |close_timer_|. Closes all pending stream.
void ClosePendingStreams();
+ // A no-reference-held pointer (we don't want circular references) back to the
+ // AudioManager that owns this object.
AudioManager* audio_manager_;
MessageLoop* message_loop_;
AudioParameters params_;
int64 pause_delay_milliseconds_;
size_t paused_proxies_;
- std::vector<AudioOutputStream*> idle_streams_;
- std::list<AudioOutputStream*> pausing_streams_;
+ typedef std::list<AudioOutputStream*> AudioOutputStreamList;
+ AudioOutputStreamList idle_streams_;
+ AudioOutputStreamList pausing_streams_;
+
+ // Used to post delayed tasks to ourselves that we cancel inside Shutdown().
+ base::WeakPtrFactory<AudioOutputDispatcher> weak_this_;
base::DelayTimer<AudioOutputDispatcher> close_timer_;
DISALLOW_COPY_AND_ASSIGN(AudioOutputDispatcher);
diff --git a/media/audio/audio_output_proxy.cc b/media/audio/audio_output_proxy.cc
index c162867..b304ebb 100644
--- a/media/audio/audio_output_proxy.cc
+++ b/media/audio/audio_output_proxy.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -84,9 +84,14 @@ void AudioOutputProxy::Close() {
DCHECK(state_ == kCreated || state_ == kError || state_ == kOpened);
DCHECK(!physical_stream_);
- if (state_ != kCreated) {
+ if (state_ != kCreated)
dispatcher_->StreamClosed();
- }
- dispatcher_->message_loop()->DeleteSoon(FROM_HERE, this);
+
state_ = kClosed;
+
+ // Delete the object now like is done in the Close() implementation of
+ // physical stream objects. If we delete the object via DeleteSoon, we
+ // unnecessarily complicate the Shutdown procedure of the
+ // dispatcher+audio manager.
+ delete this;
}
diff --git a/media/audio/audio_output_proxy.h b/media/audio/audio_output_proxy.h
index f9a2554..064771d 100644
--- a/media/audio/audio_output_proxy.h
+++ b/media/audio/audio_output_proxy.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MEDIA_AUDIO_AUDIO_OUTPUT_STREAM_PROXY_H_
-#define MEDIA_AUDIO_AUDIO_OUTPUT_STREAM_PROXY_H_
+#ifndef MEDIA_AUDIO_AUDIO_OUTPUT_PROXY_H_
+#define MEDIA_AUDIO_AUDIO_OUTPUT_PROXY_H_
#include "base/basictypes.h"
#include "base/task.h"
@@ -23,7 +23,7 @@ class AudioOutputDispatcher;
class MEDIA_EXPORT AudioOutputProxy : public AudioOutputStream {
public:
// Caller keeps ownership of |dispatcher|.
- AudioOutputProxy(AudioOutputDispatcher* dispatcher);
+ explicit AudioOutputProxy(AudioOutputDispatcher* dispatcher);
// AudioOutputStream interface.
virtual bool Open() OVERRIDE;
@@ -34,9 +34,6 @@ class MEDIA_EXPORT AudioOutputProxy : public AudioOutputStream {
virtual void Close() OVERRIDE;
private:
- // Needs to access destructor.
- friend class DeleteTask<AudioOutputProxy>;
-
enum State {
kCreated,
kOpened,
@@ -61,4 +58,4 @@ class MEDIA_EXPORT AudioOutputProxy : public AudioOutputStream {
DISALLOW_COPY_AND_ASSIGN(AudioOutputProxy);
};
-#endif // MEDIA_AUDIO_AUDIO_OUTPUT_STREAM_PROXY_H_
+#endif // MEDIA_AUDIO_AUDIO_OUTPUT_PROXY_H_
diff --git a/media/audio/audio_output_proxy_unittest.cc b/media/audio/audio_output_proxy_unittest.cc
index 683ca2d..436a0ba 100644
--- a/media/audio/audio_output_proxy_unittest.cc
+++ b/media/audio/audio_output_proxy_unittest.cc
@@ -67,8 +67,10 @@ class MockAudioSourceCallback : public AudioOutputStream::AudioSourceCallback {
class AudioOutputProxyTest : public testing::Test {
protected:
virtual void SetUp() {
- EXPECT_CALL(manager_, GetMessageLoop())
+ MockAudioManager* manager = new MockAudioManager();
+ EXPECT_CALL(*manager, GetMessageLoop())
.WillRepeatedly(Return(&message_loop_));
+ manager_ = manager;
InitDispatcher(kTestCloseDelayMs);
}
@@ -84,17 +86,21 @@ class AudioOutputProxyTest : public testing::Test {
void InitDispatcher(int close_delay_ms) {
AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
CHANNEL_LAYOUT_STEREO, 44100, 16, 1024);
- dispatcher_ = new AudioOutputDispatcher(&manager_, params, close_delay_ms);
+ dispatcher_ = new AudioOutputDispatcher(&manager(), params, close_delay_ms);
// Necessary to know how long the dispatcher will wait before posting
// StopStreamTask.
pause_delay_milliseconds_ = dispatcher_->pause_delay_milliseconds_;
}
+ MockAudioManager& manager() {
+ return *manager_;
+ }
+
MessageLoop message_loop_;
scoped_refptr<AudioOutputDispatcher> dispatcher_;
int64 pause_delay_milliseconds_;
- MockAudioManager manager_;
+ scoped_refptr<MockAudioManager> manager_;
MockAudioSourceCallback callback_;
};
@@ -106,7 +112,7 @@ TEST_F(AudioOutputProxyTest, CreateAndClose) {
TEST_F(AudioOutputProxyTest, OpenAndClose) {
MockAudioOutputStream stream;
- EXPECT_CALL(manager_, MakeAudioOutputStream(_))
+ EXPECT_CALL(manager(), MakeAudioOutputStream(_))
.WillOnce(Return(&stream));
EXPECT_CALL(stream, Open())
.WillOnce(Return(true));
@@ -123,7 +129,7 @@ TEST_F(AudioOutputProxyTest, OpenAndClose) {
TEST_F(AudioOutputProxyTest, CreateAndWait) {
MockAudioOutputStream stream;
- EXPECT_CALL(manager_, MakeAudioOutputStream(_))
+ EXPECT_CALL(manager(), MakeAudioOutputStream(_))
.WillOnce(Return(&stream));
EXPECT_CALL(stream, Open())
.WillOnce(Return(true));
@@ -147,7 +153,7 @@ TEST_F(AudioOutputProxyTest, CreateAndWait) {
TEST_F(AudioOutputProxyTest, StartAndStop) {
MockAudioOutputStream stream;
- EXPECT_CALL(manager_, MakeAudioOutputStream(_))
+ EXPECT_CALL(manager(), MakeAudioOutputStream(_))
.WillOnce(Return(&stream));
EXPECT_CALL(stream, Open())
.WillOnce(Return(true));
@@ -173,7 +179,7 @@ TEST_F(AudioOutputProxyTest, StartAndStop) {
TEST_F(AudioOutputProxyTest, CloseAfterStop) {
MockAudioOutputStream stream;
- EXPECT_CALL(manager_, MakeAudioOutputStream(_))
+ EXPECT_CALL(manager(), MakeAudioOutputStream(_))
.WillOnce(Return(&stream));
EXPECT_CALL(stream, Open())
.WillOnce(Return(true));
@@ -210,7 +216,7 @@ TEST_F(AudioOutputProxyTest, CloseAfterStop) {
TEST_F(AudioOutputProxyTest, TwoStreams) {
MockAudioOutputStream stream;
- EXPECT_CALL(manager_, MakeAudioOutputStream(_))
+ EXPECT_CALL(manager(), MakeAudioOutputStream(_))
.WillOnce(Return(&stream));
EXPECT_CALL(stream, Open())
.WillOnce(Return(true));
@@ -233,7 +239,7 @@ TEST_F(AudioOutputProxyTest, TwoStreams_OnePlaying) {
InitDispatcher(kTestBigCloseDelayMs);
- EXPECT_CALL(manager_, MakeAudioOutputStream(_))
+ EXPECT_CALL(manager(), MakeAudioOutputStream(_))
.WillOnce(Return(&stream1))
.WillOnce(Return(&stream2));
@@ -273,7 +279,7 @@ TEST_F(AudioOutputProxyTest, TwoStreams_BothPlaying) {
InitDispatcher(kTestBigCloseDelayMs);
- EXPECT_CALL(manager_, MakeAudioOutputStream(_))
+ EXPECT_CALL(manager(), MakeAudioOutputStream(_))
.WillOnce(Return(&stream1))
.WillOnce(Return(&stream2));
@@ -317,7 +323,7 @@ TEST_F(AudioOutputProxyTest, TwoStreams_BothPlaying) {
TEST_F(AudioOutputProxyTest, OpenFailed) {
MockAudioOutputStream stream;
- EXPECT_CALL(manager_, MakeAudioOutputStream(_))
+ EXPECT_CALL(manager(), MakeAudioOutputStream(_))
.WillOnce(Return(&stream));
EXPECT_CALL(stream, Open())
.WillOnce(Return(false));
@@ -333,7 +339,7 @@ TEST_F(AudioOutputProxyTest, OpenFailed) {
TEST_F(AudioOutputProxyTest, StartFailed) {
MockAudioOutputStream stream;
- EXPECT_CALL(manager_, MakeAudioOutputStream(_))
+ EXPECT_CALL(manager(), MakeAudioOutputStream(_))
.WillOnce(Return(&stream));
EXPECT_CALL(stream, Open())
.WillOnce(Return(true));
@@ -351,7 +357,7 @@ TEST_F(AudioOutputProxyTest, StartFailed) {
Mock::VerifyAndClear(&stream);
// |stream| is closed at this point. Start() should reopen it again.
- EXPECT_CALL(manager_, MakeAudioOutputStream(_))
+ EXPECT_CALL(manager(), MakeAudioOutputStream(_))
.WillOnce(Return(reinterpret_cast<AudioOutputStream*>(NULL)));
EXPECT_CALL(callback_, OnError(_, _))
diff --git a/media/audio/linux/alsa_input.cc b/media/audio/linux/alsa_input.cc
index a986238..1e677ba 100644
--- a/media/audio/linux/alsa_input.cc
+++ b/media/audio/linux/alsa_input.cc
@@ -22,10 +22,12 @@ static const char kDefaultDevice2[] = "plug:default";
const char* AlsaPcmInputStream::kAutoSelectDevice = "";
-AlsaPcmInputStream::AlsaPcmInputStream(const std::string& device_name,
+AlsaPcmInputStream::AlsaPcmInputStream(AudioManagerLinux* audio_manager,
+ const std::string& device_name,
const AudioParameters& params,
AlsaWrapper* wrapper)
- : device_name_(device_name),
+ : audio_manager_(audio_manager),
+ device_name_(device_name),
params_(params),
bytes_per_packet_(params.samples_per_packet *
(params.channels * params.bits_per_sample) / 8),
@@ -110,8 +112,7 @@ void AlsaPcmInputStream::Start(AudioInputCallback* callback) {
base::Bind(&AlsaPcmInputStream::ReadAudio, weak_factory_.GetWeakPtr()),
delay_ms);
- static_cast<AudioManagerLinux*>(AudioManager::GetAudioManager())->
- IncreaseActiveInputStreamCount();
+ audio_manager_->IncreaseActiveInputStreamCount();
}
}
@@ -224,8 +225,7 @@ void AlsaPcmInputStream::Stop() {
// Stop is always called before Close. In case of error, this will be
// also called when closing the input controller.
- static_cast<AudioManagerLinux*>(AudioManager::GetAudioManager())->
- DecreaseActiveInputStreamCount();
+ audio_manager_->DecreaseActiveInputStreamCount();
weak_factory_.InvalidateWeakPtrs(); // Cancel the next scheduled read.
int error = wrapper_->PcmDrop(device_handle_);
diff --git a/media/audio/linux/alsa_input.h b/media/audio/linux/alsa_input.h
index 6aa1b87..c70f0de 100644
--- a/media/audio/linux/alsa_input.h
+++ b/media/audio/linux/alsa_input.h
@@ -16,6 +16,7 @@
#include "media/audio/audio_parameters.h"
class AlsaWrapper;
+class AudioManagerLinux;
// Provides an input stream for audio capture based on the ALSA PCM interface.
// This object is not thread safe and all methods should be invoked in the
@@ -29,7 +30,8 @@ class AlsaPcmInputStream : public AudioInputStream {
// Create a PCM Output stream for the ALSA device identified by
// |device_name|. If unsure of what to use for |device_name|, use
// |kAutoSelectDevice|.
- AlsaPcmInputStream(const std::string& device_name,
+ AlsaPcmInputStream(AudioManagerLinux* audio_manager,
+ const std::string& device_name,
const AudioParameters& params,
AlsaWrapper* wrapper);
virtual ~AlsaPcmInputStream();
@@ -54,6 +56,12 @@ class AlsaPcmInputStream : public AudioInputStream {
// Utility function for talking with the ALSA API.
snd_pcm_sframes_t GetCurrentDelay();
+ // Non-refcounted pointer back to the audio manager.
+ // The AudioManager indirectly holds on to stream objects, so we don't
+ // want circular references. Additionally, stream objects live on the audio
+ // thread, which is owned by the audio manager and we don't want to addref
+ // the manager from that thread.
+ AudioManagerLinux* audio_manager_;
std::string device_name_;
AudioParameters params_;
int bytes_per_packet_;
diff --git a/media/audio/linux/alsa_output_unittest.cc b/media/audio/linux/alsa_output_unittest.cc
index 3191472..50db8c4 100644
--- a/media/audio/linux/alsa_output_unittest.cc
+++ b/media/audio/linux/alsa_output_unittest.cc
@@ -91,6 +91,7 @@ class MockAudioManagerLinux : public AudioManagerLinux {
class AlsaPcmOutputStreamTest : public testing::Test {
protected:
AlsaPcmOutputStreamTest() {
+ mock_manager_ = new StrictMock<MockAudioManagerLinux>();
test_stream_.reset(CreateStream(kTestChannelLayout));
}
@@ -109,7 +110,7 @@ class AlsaPcmOutputStreamTest : public testing::Test {
return new AlsaPcmOutputStream(kTestDeviceName,
params,
&mock_alsa_wrapper_,
- &mock_manager_,
+ mock_manager_,
&message_loop_);
}
@@ -132,6 +133,10 @@ class AlsaPcmOutputStreamTest : public testing::Test {
test_stream_->buffer_->Append(packet_.get());
}
+ MockAudioManagerLinux& mock_manager() {
+ return *mock_manager_;
+ }
+
static const ChannelLayout kTestChannelLayout;
static const int kTestSampleRate;
static const int kTestBitsPerSample;
@@ -154,7 +159,7 @@ class AlsaPcmOutputStreamTest : public testing::Test {
static void* kFakeHints[];
StrictMock<MockAlsaWrapper> mock_alsa_wrapper_;
- StrictMock<MockAudioManagerLinux> mock_manager_;
+ scoped_refptr<StrictMock<MockAudioManagerLinux> > mock_manager_;
MessageLoop message_loop_;
scoped_ptr<AlsaPcmOutputStream> test_stream_;
scoped_refptr<media::DataBuffer> packet_;
@@ -211,7 +216,7 @@ TEST_F(AlsaPcmOutputStreamTest, ConstructedState) {
test_stream_.reset(new AlsaPcmOutputStream(kTestDeviceName,
bad_bps_params,
&mock_alsa_wrapper_,
- &mock_manager_,
+ mock_manager_,
&message_loop_));
EXPECT_EQ(AlsaPcmOutputStream::kInError, test_stream_->state());
@@ -222,7 +227,7 @@ TEST_F(AlsaPcmOutputStreamTest, ConstructedState) {
test_stream_.reset(new AlsaPcmOutputStream(kTestDeviceName,
bad_format_params,
&mock_alsa_wrapper_,
- &mock_manager_,
+ mock_manager_,
&message_loop_));
EXPECT_EQ(AlsaPcmOutputStream::kInError, test_stream_->state());
}
@@ -257,12 +262,12 @@ TEST_F(AlsaPcmOutputStreamTest, LatencyFloor) {
EXPECT_CALL(mock_alsa_wrapper_, PcmClose(kFakeHandle)).WillOnce(Return(0));
EXPECT_CALL(mock_alsa_wrapper_, PcmName(kFakeHandle))
.WillOnce(Return(kTestDeviceName));
- EXPECT_CALL(mock_manager_, ReleaseOutputStream(test_stream_.get()));
+ EXPECT_CALL(mock_manager(), ReleaseOutputStream(test_stream_.get()));
test_stream_->Close();
message_loop_.RunAllPending();
Mock::VerifyAndClear(&mock_alsa_wrapper_);
- Mock::VerifyAndClear(&mock_manager_);
+ Mock::VerifyAndClear(mock_manager_);
// Test that having more packets ends up with a latency based on packet size.
const int kOverMinLatencyPacketSize = kPacketFramesInMinLatency + 1;
@@ -289,12 +294,12 @@ TEST_F(AlsaPcmOutputStreamTest, LatencyFloor) {
.WillOnce(Return(0));
EXPECT_CALL(mock_alsa_wrapper_, PcmName(kFakeHandle))
.WillOnce(Return(kTestDeviceName));
- EXPECT_CALL(mock_manager_, ReleaseOutputStream(test_stream_.get()));
+ EXPECT_CALL(mock_manager(), ReleaseOutputStream(test_stream_.get()));
test_stream_->Close();
message_loop_.RunAllPending();
Mock::VerifyAndClear(&mock_alsa_wrapper_);
- Mock::VerifyAndClear(&mock_manager_);
+ Mock::VerifyAndClear(mock_manager_);
}
TEST_F(AlsaPcmOutputStreamTest, OpenClose) {
@@ -339,7 +344,7 @@ TEST_F(AlsaPcmOutputStreamTest, OpenClose) {
.WillOnce(Return(0));
EXPECT_CALL(mock_alsa_wrapper_, PcmName(kFakeHandle))
.WillOnce(Return(kTestDeviceName));
- EXPECT_CALL(mock_manager_, ReleaseOutputStream(test_stream_.get()));
+ EXPECT_CALL(mock_manager(), ReleaseOutputStream(test_stream_.get()));
test_stream_->Close();
message_loop_.RunAllPending();
@@ -367,7 +372,7 @@ TEST_F(AlsaPcmOutputStreamTest, PcmOpenFailed) {
EXPECT_FALSE(test_stream_->buffer_.get());
// Close the stream since we opened it to make destruction happy.
- EXPECT_CALL(mock_manager_, ReleaseOutputStream(test_stream_.get()));
+ EXPECT_CALL(mock_manager(), ReleaseOutputStream(test_stream_.get()));
test_stream_->Close();
message_loop_.RunAllPending();
}
@@ -399,7 +404,7 @@ TEST_F(AlsaPcmOutputStreamTest, PcmSetParamsFailed) {
EXPECT_FALSE(test_stream_->buffer_.get());
// Close the stream since we opened it to make destruction happy.
- EXPECT_CALL(mock_manager_, ReleaseOutputStream(test_stream_.get()));
+ EXPECT_CALL(mock_manager(), ReleaseOutputStream(test_stream_.get()));
test_stream_->Close();
message_loop_.RunAllPending();
}
@@ -456,7 +461,7 @@ TEST_F(AlsaPcmOutputStreamTest, StartStop) {
test_stream_->Start(&mock_callback);
message_loop_.RunAllPending();
- EXPECT_CALL(mock_manager_, ReleaseOutputStream(test_stream_.get()));
+ EXPECT_CALL(mock_manager(), ReleaseOutputStream(test_stream_.get()));
EXPECT_CALL(mock_alsa_wrapper_, PcmClose(kFakeHandle))
.WillOnce(Return(0));
EXPECT_CALL(mock_alsa_wrapper_, PcmName(kFakeHandle))
@@ -685,7 +690,7 @@ TEST_F(AlsaPcmOutputStreamTest, AutoSelectDevice_DeviceSelect) {
EXPECT_EQ(kExpectedDownmix[i], test_stream_->should_downmix_);
Mock::VerifyAndClearExpectations(&mock_alsa_wrapper_);
- Mock::VerifyAndClearExpectations(&mock_manager_);
+ Mock::VerifyAndClearExpectations(mock_manager_);
}
}
diff --git a/media/audio/linux/audio_manager_linux.cc b/media/audio/linux/audio_manager_linux.cc
index 656c0bc..a85806f 100644
--- a/media/audio/linux/audio_manager_linux.cc
+++ b/media/audio/linux/audio_manager_linux.cc
@@ -56,13 +56,14 @@ AudioOutputStream* AudioManagerLinux::MakeAudioOutputStream(
}
if (!initialized()) {
+ // We should never get here since this method is called on the audio thread.
+ NOTREACHED();
return NULL;
}
// Don't allow opening more than |kMaxOutputStreams| streams.
- if (active_streams_.size() >= kMaxOutputStreams) {
+ if (active_output_stream_count_ >= kMaxOutputStreams)
return NULL;
- }
AudioOutputStream* stream;
#if defined(USE_PULSEAUDIO)
@@ -81,15 +82,16 @@ AudioOutputStream* AudioManagerLinux::MakeAudioOutputStream(
#if defined(USE_PULSEAUDIO)
}
#endif
- active_streams_.insert(stream);
+ ++active_output_stream_count_;
return stream;
}
AudioInputStream* AudioManagerLinux::MakeAudioInputStream(
const AudioParameters& params, const std::string& device_id) {
if (!params.IsValid() || params.channels > kMaxInputChannels ||
- device_id.empty())
+ device_id.empty()) {
return NULL;
+ }
if (params.format == AudioParameters::AUDIO_MOCK) {
return FakeAudioInputStream::MakeFakeStream(params);
@@ -107,29 +109,18 @@ AudioInputStream* AudioManagerLinux::MakeAudioInputStream(
switches::kAlsaInputDevice);
}
- AlsaPcmInputStream* stream = new AlsaPcmInputStream(
+ AlsaPcmInputStream* stream = new AlsaPcmInputStream(this,
device_name, params, wrapper_.get());
return stream;
}
-AudioManagerLinux::AudioManagerLinux() {
-}
+AudioManagerLinux::AudioManagerLinux() : active_output_stream_count_(0U) {}
AudioManagerLinux::~AudioManagerLinux() {
- // Make sure we stop the thread first. If we allow the default destructor to
- // destroy the members, we may destroy audio streams before stopping the
- // thread, resulting an unexpected behavior.
- // This way we make sure activities of the audio streams are all stopped
- // before we destroy them.
- audio_thread_.Stop();
-
- // Free output dispatchers, closing all remaining open streams.
- output_dispatchers_.clear();
-
- // Delete all the streams. Have to do it manually, we don't have ScopedSet<>,
- // and we are not using ScopedVector<> because search there is slow.
- STLDeleteElements(&active_streams_);
+ Shutdown();
+ // All the streams should have been deleted on the audio thread via Shutdown.
+ CHECK_EQ(active_output_stream_count_, 0U);
}
void AudioManagerLinux::Init() {
@@ -147,8 +138,9 @@ void AudioManagerLinux::UnMuteAll() {
void AudioManagerLinux::ReleaseOutputStream(AudioOutputStream* stream) {
if (stream) {
- active_streams_.erase(stream);
delete stream;
+ --active_output_stream_count_;
+ DCHECK_GE(active_output_stream_count_, 0U);
}
}
@@ -324,7 +316,6 @@ bool AudioManagerLinux::HasAnyAlsaAudioDevice(StreamType stream) {
return has_device;
}
-// static
-AudioManager* AudioManager::CreateAudioManager() {
+AudioManager* CreateAudioManager() {
return new AudioManagerLinux();
}
diff --git a/media/audio/linux/audio_manager_linux.h b/media/audio/linux/audio_manager_linux.h
index 5185013..d4d4bb1 100644
--- a/media/audio/linux/audio_manager_linux.h
+++ b/media/audio/linux/audio_manager_linux.h
@@ -5,8 +5,7 @@
#ifndef MEDIA_AUDIO_LINUX_AUDIO_MANAGER_LINUX_H_
#define MEDIA_AUDIO_LINUX_AUDIO_MANAGER_LINUX_H_
-#include <set>
-
+#include <string>
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/threading/thread.h"
@@ -61,7 +60,7 @@ class MEDIA_EXPORT AudioManagerLinux : public AudioManagerBase {
scoped_ptr<AlsaWrapper> wrapper_;
- std::set<AudioOutputStream*> active_streams_;
+ size_t active_output_stream_count_;
DISALLOW_COPY_AND_ASSIGN(AudioManagerLinux);
};
diff --git a/media/audio/mac/audio_low_latency_input_mac_unittest.cc b/media/audio/mac/audio_low_latency_input_mac_unittest.cc
index e18f1c8..baad701 100644
--- a/media/audio/mac/audio_low_latency_input_mac_unittest.cc
+++ b/media/audio/mac/audio_low_latency_input_mac_unittest.cc
@@ -84,49 +84,52 @@ class WriteToFileAudioSink : public AudioInputStream::AudioInputCallback {
size_t bytes_to_write_;
};
-// Convenience method which ensures that we are not running on the build
-// bots and that at least one valid input device can be found.
-static bool CanRunAudioTests() {
- scoped_ptr<base::Environment> env(base::Environment::Create());
- if (env->HasVar("CHROME_HEADLESS"))
- return false;
- AudioManager* audio_man = AudioManager::GetAudioManager();
- if (NULL == audio_man)
- return false;
- return audio_man->HasAudioInputDevices();
-}
+class MacAudioInputTest : public testing::Test {
+ protected:
+ MacAudioInputTest() : audio_manager_(AudioManager::Create()) {}
+ virtual ~MacAudioInputTest() {}
+
+ // Convenience method which ensures that we are not running on the build
+ // bots and that at least one valid input device can be found.
+ bool CanRunAudioTests() {
+ scoped_ptr<base::Environment> env(base::Environment::Create());
+ if (env->HasVar("CHROME_HEADLESS"))
+ return false;
+ return audio_manager_->HasAudioInputDevices();
+ }
-// Convenience method which creates a default AudioInputStream object using
-// a 10ms frame size and a sample rate which is set to the hardware sample rate.
-static AudioInputStream* CreateDefaultAudioInputStream() {
- AudioManager* audio_man = AudioManager::GetAudioManager();
- int fs = static_cast<int>(AUAudioInputStream::HardwareSampleRate());
- int samples_per_packet = fs / 100;
- AudioInputStream* ais = audio_man->MakeAudioInputStream(
- AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
- CHANNEL_LAYOUT_STEREO, fs, 16, samples_per_packet),
- AudioManagerBase::kDefaultDeviceId);
- EXPECT_TRUE(ais);
- return ais;
-}
+ // Convenience method which creates a default AudioInputStream object using
+ // a 10ms frame size and a sample rate which is set to the hardware sample
+ // rate.
+ AudioInputStream* CreateDefaultAudioInputStream() {
+ int fs = static_cast<int>(AUAudioInputStream::HardwareSampleRate());
+ int samples_per_packet = fs / 100;
+ AudioInputStream* ais = audio_manager_->MakeAudioInputStream(
+ AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ CHANNEL_LAYOUT_STEREO, fs, 16, samples_per_packet),
+ AudioManagerBase::kDefaultDeviceId);
+ EXPECT_TRUE(ais);
+ return ais;
+ }
-// Convenience method which creates an AudioInputStream object with a specified
-// channel layout.
-static AudioInputStream* CreateAudioInputStream(ChannelLayout channel_layout) {
- AudioManager* audio_man = AudioManager::GetAudioManager();
- int fs = static_cast<int>(AUAudioInputStream::HardwareSampleRate());
- int samples_per_packet = fs / 100;
- AudioInputStream* ais = audio_man->MakeAudioInputStream(
- AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
- channel_layout, fs, 16, samples_per_packet),
- AudioManagerBase::kDefaultDeviceId);
- EXPECT_TRUE(ais);
- return ais;
-}
+ // Convenience method which creates an AudioInputStream object with a
+ // specified channel layout.
+ AudioInputStream* CreateAudioInputStream(ChannelLayout channel_layout) {
+ int fs = static_cast<int>(AUAudioInputStream::HardwareSampleRate());
+ int samples_per_packet = fs / 100;
+ AudioInputStream* ais = audio_manager_->MakeAudioInputStream(
+ AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ channel_layout, fs, 16, samples_per_packet),
+ AudioManagerBase::kDefaultDeviceId);
+ EXPECT_TRUE(ais);
+ return ais;
+ }
+ scoped_refptr<AudioManager> audio_manager_;
+};
// Test Create(), Close().
-TEST(MacAudioInputTest, AUAudioInputStreamCreateAndClose) {
+TEST_F(MacAudioInputTest, AUAudioInputStreamCreateAndClose) {
if (!CanRunAudioTests())
return;
AudioInputStream* ais = CreateDefaultAudioInputStream();
@@ -134,7 +137,7 @@ TEST(MacAudioInputTest, AUAudioInputStreamCreateAndClose) {
}
// Test Open(), Close().
-TEST(MacAudioInputTest, AUAudioInputStreamOpenAndClose) {
+TEST_F(MacAudioInputTest, AUAudioInputStreamOpenAndClose) {
if (!CanRunAudioTests())
return;
AudioInputStream* ais = CreateDefaultAudioInputStream();
@@ -143,7 +146,7 @@ TEST(MacAudioInputTest, AUAudioInputStreamOpenAndClose) {
}
// Test Open(), Start(), Close().
-TEST(MacAudioInputTest, AUAudioInputStreamOpenStartAndClose) {
+TEST_F(MacAudioInputTest, AUAudioInputStreamOpenStartAndClose) {
if (!CanRunAudioTests())
return;
AudioInputStream* ais = CreateDefaultAudioInputStream();
@@ -156,7 +159,7 @@ TEST(MacAudioInputTest, AUAudioInputStreamOpenStartAndClose) {
}
// Test Open(), Start(), Stop(), Close().
-TEST(MacAudioInputTest, AUAudioInputStreamOpenStartStopAndClose) {
+TEST_F(MacAudioInputTest, AUAudioInputStreamOpenStartStopAndClose) {
if (!CanRunAudioTests())
return;
AudioInputStream* ais = CreateDefaultAudioInputStream();
@@ -170,7 +173,7 @@ TEST(MacAudioInputTest, AUAudioInputStreamOpenStartStopAndClose) {
}
// Test some additional calling sequences.
-TEST(MacAudioInputTest, AUAudioInputStreamMiscCallingSequences) {
+TEST_F(MacAudioInputTest, AUAudioInputStreamMiscCallingSequences) {
if (!CanRunAudioTests())
return;
AudioInputStream* ais = CreateDefaultAudioInputStream();
@@ -200,7 +203,7 @@ TEST(MacAudioInputTest, AUAudioInputStreamMiscCallingSequences) {
}
// Verify that recording starts and stops correctly in mono using mocked sink.
-TEST(MacAudioInputTest, AUAudioInputStreamVerifyMonoRecording) {
+TEST_F(MacAudioInputTest, AUAudioInputStreamVerifyMonoRecording) {
if (!CanRunAudioTests())
return;
@@ -234,7 +237,7 @@ TEST(MacAudioInputTest, AUAudioInputStreamVerifyMonoRecording) {
}
// Verify that recording starts and stops correctly in mono using mocked sink.
-TEST(MacAudioInputTest, AUAudioInputStreamVerifyStereoRecording) {
+TEST_F(MacAudioInputTest, AUAudioInputStreamVerifyStereoRecording) {
if (!CanRunAudioTests())
return;
@@ -273,7 +276,7 @@ TEST(MacAudioInputTest, AUAudioInputStreamVerifyStereoRecording) {
// 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(MacAudioInputTest, DISABLED_AUAudioInputStreamRecordToFile) {
+TEST_F(MacAudioInputTest, DISABLED_AUAudioInputStreamRecordToFile) {
if (!CanRunAudioTests())
return;
const char* file_name = "out_stereo_10sec.pcm";
diff --git a/media/audio/mac/audio_manager_mac.cc b/media/audio/mac/audio_manager_mac.cc
index f2380cb..420415d 100644
--- a/media/audio/mac/audio_manager_mac.cc
+++ b/media/audio/mac/audio_manager_mac.cc
@@ -333,7 +333,6 @@ void AudioManagerMac::ReleaseInputStream(AudioInputStream* stream) {
delete stream;
}
-// static
-AudioManager* AudioManager::CreateAudioManager() {
+AudioManager* CreateAudioManager() {
return new AudioManagerMac();
}
diff --git a/media/audio/mac/audio_output_mac_unittest.cc b/media/audio/mac/audio_output_mac_unittest.cc
index 265e7fd..f15ab69 100644
--- a/media/audio/mac/audio_output_mac_unittest.cc
+++ b/media/audio/mac/audio_output_mac_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
#include "media/audio/audio_io.h"
#include "media/audio/audio_manager.h"
#include "media/audio/simple_sources.h"
@@ -47,13 +48,12 @@ TEST(MacAudioTest, SineWaveAudio16MonoTest) {
// ===========================================================================
// Validation of AudioParameters::AUDIO_PCM_LINEAR
//
-// Unlike windows, the tests can reliably detect the existense of real
+// Unlike windows, the tests can reliably detect the existence of real
// audio devices on the bots thus no need for 'headless' detection.
// Test that can it be created and closed.
TEST(MacAudioTest, PCMWaveStreamGetAndClose) {
- AudioManager* audio_man = AudioManager::GetAudioManager();
- ASSERT_TRUE(NULL != audio_man);
+ scoped_refptr<AudioManager> audio_man(AudioManager::Create());
if (!audio_man->HasAudioOutputDevices())
return;
AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
@@ -65,8 +65,7 @@ TEST(MacAudioTest, PCMWaveStreamGetAndClose) {
// Test that it can be opened and closed.
TEST(MacAudioTest, PCMWaveStreamOpenAndClose) {
- AudioManager* audio_man = AudioManager::GetAudioManager();
- ASSERT_TRUE(NULL != audio_man);
+ scoped_refptr<AudioManager> audio_man(AudioManager::Create());
if (!audio_man->HasAudioOutputDevices())
return;
AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
@@ -82,8 +81,7 @@ TEST(MacAudioTest, PCMWaveStreamOpenAndClose) {
// pops or noises while the sound is playing. The sound must also be identical
// to the sound of PCMWaveStreamPlay200HzTone22KssMono test.
TEST(MacAudioTest, PCMWaveStreamPlay200HzTone44KssMono) {
- AudioManager* audio_man = AudioManager::GetAudioManager();
- ASSERT_TRUE(NULL != audio_man);
+ scoped_refptr<AudioManager> audio_man(AudioManager::Create());
if (!audio_man->HasAudioOutputDevices())
return;
uint32 frames_100_ms = AudioParameters::kAudioCDSampleRate / 10;
@@ -113,8 +111,7 @@ TEST(MacAudioTest, PCMWaveStreamPlay200HzTone44KssMono) {
// or noises while the sound is playing. The sound must also be identical to the
// sound of PCMWaveStreamPlay200HzTone44KssMono test.
TEST(MacAudioTest, PCMWaveStreamPlay200HzTone22KssMono) {
- AudioManager* audio_man = AudioManager::GetAudioManager();
- ASSERT_TRUE(NULL != audio_man);
+ scoped_refptr<AudioManager> audio_man(AudioManager::Create());
if (!audio_man->HasAudioOutputDevices())
return;
uint32 frames_100_ms = AudioParameters::kAudioCDSampleRate / 10;
@@ -140,8 +137,7 @@ static void ClearBuffer(AudioOutputStream* stream, uint8* dest,
}
TEST(MacAudioTest, PCMWaveStreamPendingBytes) {
- AudioManager* audio_man = AudioManager::GetAudioManager();
- ASSERT_TRUE(NULL != audio_man);
+ scoped_refptr<AudioManager> audio_man(AudioManager::Create());
if (!audio_man->HasAudioOutputDevices())
return;
diff --git a/media/audio/openbsd/audio_manager_openbsd.cc b/media/audio/openbsd/audio_manager_openbsd.cc
index 2ee9034..40b8a62 100644
--- a/media/audio/openbsd/audio_manager_openbsd.cc
+++ b/media/audio/openbsd/audio_manager_openbsd.cc
@@ -118,6 +118,6 @@ void AudioManagerOpenBSD::ReleaseOutputStream(AudioOutputStream* stream) {
}
// static
-AudioManager* AudioManager::CreateAudioManager() {
+AudioManager* CreateAudioManager() {
return new AudioManagerOpenBSD();
}
diff --git a/media/audio/simple_sources_unittest.cc b/media/audio/simple_sources_unittest.cc
index ff0e30e..def0411 100644
--- a/media/audio/simple_sources_unittest.cc
+++ b/media/audio/simple_sources_unittest.cc
@@ -21,7 +21,7 @@ static void GenerateRandomData(char* buffer, uint32 len) {
}
for (uint32 i = 0; i < len; i++)
- buffer[i] = static_cast<char>(rand());
+ buffer[i] = static_cast<char>(rand()); // NOLINT
}
// To test write size smaller than read size.
@@ -68,8 +68,7 @@ TEST(SimpleSources, SineWaveAudio16MonoTest) {
SineWaveAudioSource source(SineWaveAudioSource::FORMAT_16BIT_LINEAR_PCM, 1,
freq, AudioParameters::kTelephoneSampleRate);
- AudioManager* audio_man = AudioManager::GetAudioManager();
- ASSERT_TRUE(NULL != audio_man);
+ scoped_refptr<AudioManager> audio_man(AudioManager::Create());
AudioParameters params(
AudioParameters::AUDIO_MOCK, CHANNEL_LAYOUT_MONO,
AudioParameters::kTelephoneSampleRate, bytes_per_sample * 2, samples);
diff --git a/media/audio/test_audio_input_controller_factory.cc b/media/audio/test_audio_input_controller_factory.cc
index d141c9e..38543c5 100644
--- a/media/audio/test_audio_input_controller_factory.cc
+++ b/media/audio/test_audio_input_controller_factory.cc
@@ -9,9 +9,10 @@ namespace media {
TestAudioInputController::TestAudioInputController(
TestAudioInputControllerFactory* factory,
+ AudioManager* audio_manager,
EventHandler* event_handler,
SyncWriter* sync_writer)
- : AudioInputController(event_handler, sync_writer),
+ : AudioInputController(audio_manager, event_handler, sync_writer),
factory_(factory),
event_handler_(event_handler) {
}
@@ -26,10 +27,12 @@ TestAudioInputControllerFactory::TestAudioInputControllerFactory()
}
AudioInputController* TestAudioInputControllerFactory::Create(
+ AudioManager* audio_manager,
AudioInputController::EventHandler* event_handler,
AudioParameters params) {
DCHECK(!controller_); // Only one test instance managed at a time.
- controller_ = new TestAudioInputController(this, event_handler, NULL);
+ controller_ = new TestAudioInputController(this, audio_manager,
+ event_handler, NULL);
return controller_;
}
diff --git a/media/audio/test_audio_input_controller_factory.h b/media/audio/test_audio_input_controller_factory.h
index 7b178c4..1720969 100644
--- a/media/audio/test_audio_input_controller_factory.h
+++ b/media/audio/test_audio_input_controller_factory.h
@@ -45,6 +45,7 @@ class TestAudioInputControllerFactory;
class TestAudioInputController : public AudioInputController {
public:
TestAudioInputController(TestAudioInputControllerFactory* factory,
+ AudioManager* audio_manager,
EventHandler* event_handler,
SyncWriter* sync_writer);
virtual ~TestAudioInputController();
@@ -74,6 +75,7 @@ class TestAudioInputControllerFactory : public AudioInputController::Factory {
// AudioInputController::Factory methods.
virtual AudioInputController* Create(
+ AudioManager* audio_manager,
AudioInputController::EventHandler* event_handler,
AudioParameters params) OVERRIDE;
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 6e0c8c0..2ec87aa 100644
--- a/media/audio/win/audio_low_latency_input_win_unittest.cc
+++ b/media/audio/win/audio_low_latency_input_win_unittest.cc
@@ -88,13 +88,11 @@ class WriteToFileAudioSink : public AudioInputStream::AudioInputCallback {
// Convenience method which ensures that we are not running on the build
// bots and that at least one valid input device can be found.
-static bool CanRunAudioTests() {
+static bool CanRunAudioTests(AudioManager* audio_man) {
scoped_ptr<base::Environment> env(base::Environment::Create());
if (env->HasVar("CHROME_HEADLESS"))
return false;
- AudioManager* audio_man = AudioManager::GetAudioManager();
- if (NULL == audio_man)
- return false;
+
// TODO(henrika): note that we use Wave today to query the number of
// existing input devices.
return audio_man->HasAudioInputDevices();
@@ -104,9 +102,9 @@ static bool CanRunAudioTests() {
// also allows the user to modify the default settings.
class AudioInputStreamWrapper {
public:
- AudioInputStreamWrapper()
+ explicit AudioInputStreamWrapper(AudioManager* audio_manager)
: com_init_(ScopedCOMInitializer::kMTA),
- audio_man_(AudioManager::GetAudioManager()),
+ audio_man_(audio_manager),
format_(AudioParameters::AUDIO_PCM_LOW_LATENCY),
channel_layout_(CHANNEL_LAYOUT_STEREO),
bits_per_sample_(16) {
@@ -149,7 +147,7 @@ class AudioInputStreamWrapper {
}
ScopedCOMInitializer com_init_;
- AudioManager* audio_man_;
+ scoped_refptr<AudioManager> audio_man_;
AudioParameters::Format format_;
ChannelLayout channel_layout_;
int bits_per_sample_;
@@ -158,8 +156,9 @@ class AudioInputStreamWrapper {
};
// Convenience method which creates a default AudioInputStream object.
-static AudioInputStream* CreateDefaultAudioInputStream() {
- AudioInputStreamWrapper aisw;
+static AudioInputStream* CreateDefaultAudioInputStream(
+ AudioManager* audio_manager) {
+ AudioInputStreamWrapper aisw(audio_manager);
AudioInputStream* ais = aisw.Create();
return ais;
}
@@ -170,7 +169,8 @@ static AudioInputStream* CreateDefaultAudioInputStream() {
// endpoint device.
// TODO(henrika): modify this test when we suport full device enumeration.
TEST(WinAudioInputTest, WASAPIAudioInputStreamHardwareSampleRate) {
- if (!CanRunAudioTests())
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
+ if (!CanRunAudioTests(audio_manager))
return;
ScopedCOMInitializer com_init(ScopedCOMInitializer::kMTA);
@@ -194,26 +194,29 @@ TEST(WinAudioInputTest, WASAPIAudioInputStreamHardwareSampleRate) {
// Test Create(), Close() calling sequence.
TEST(WinAudioInputTest, WASAPIAudioInputStreamCreateAndClose) {
- if (!CanRunAudioTests())
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
+ if (!CanRunAudioTests(audio_manager))
return;
- AudioInputStream* ais = CreateDefaultAudioInputStream();
+ AudioInputStream* ais = CreateDefaultAudioInputStream(audio_manager);
ais->Close();
}
// Test Open(), Close() calling sequence.
TEST(WinAudioInputTest, WASAPIAudioInputStreamOpenAndClose) {
- if (!CanRunAudioTests())
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
+ if (!CanRunAudioTests(audio_manager))
return;
- AudioInputStream* ais = CreateDefaultAudioInputStream();
+ AudioInputStream* ais = CreateDefaultAudioInputStream(audio_manager);
EXPECT_TRUE(ais->Open());
ais->Close();
}
// Test Open(), Start(), Close() calling sequence.
TEST(WinAudioInputTest, WASAPIAudioInputStreamOpenStartAndClose) {
- if (!CanRunAudioTests())
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
+ if (!CanRunAudioTests(audio_manager))
return;
- AudioInputStream* ais = CreateDefaultAudioInputStream();
+ AudioInputStream* ais = CreateDefaultAudioInputStream(audio_manager);
EXPECT_TRUE(ais->Open());
MockAudioInputCallback sink;
ais->Start(&sink);
@@ -224,9 +227,10 @@ TEST(WinAudioInputTest, WASAPIAudioInputStreamOpenStartAndClose) {
// Test Open(), Start(), Stop(), Close() calling sequence.
TEST(WinAudioInputTest, WASAPIAudioInputStreamOpenStartStopAndClose) {
- if (!CanRunAudioTests())
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
+ if (!CanRunAudioTests(audio_manager))
return;
- AudioInputStream* ais = CreateDefaultAudioInputStream();
+ AudioInputStream* ais = CreateDefaultAudioInputStream(audio_manager);
EXPECT_TRUE(ais->Open());
MockAudioInputCallback sink;
ais->Start(&sink);
@@ -238,9 +242,10 @@ TEST(WinAudioInputTest, WASAPIAudioInputStreamOpenStartStopAndClose) {
// Test some additional calling sequences.
TEST(MacAudioInputTest, WASAPIAudioInputStreamMiscCallingSequences) {
- if (!CanRunAudioTests())
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
+ if (!CanRunAudioTests(audio_manager))
return;
- AudioInputStream* ais = CreateDefaultAudioInputStream();
+ AudioInputStream* ais = CreateDefaultAudioInputStream(audio_manager);
WASAPIAudioInputStream* wais = static_cast<WASAPIAudioInputStream*>(ais);
// Open(), Open() should fail the second time.
@@ -267,14 +272,15 @@ TEST(MacAudioInputTest, WASAPIAudioInputStreamMiscCallingSequences) {
}
TEST(WinAudioInputTest, WASAPIAudioInputStreamTestPacketSizes) {
- if (!CanRunAudioTests())
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
+ if (!CanRunAudioTests(audio_manager))
return;
// 10 ms packet size.
// Create default WASAPI input stream which records in stereo using
// the shared mixing rate. The default buffer size is 10ms.
- AudioInputStreamWrapper aisw;
+ AudioInputStreamWrapper aisw(audio_manager);
AudioInputStream* ais = aisw.Create();
EXPECT_TRUE(ais->Open());
@@ -347,12 +353,13 @@ TEST(WinAudioInputTest, WASAPIAudioInputStreamTestPacketSizes) {
// 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) {
- if (!CanRunAudioTests())
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
+ if (!CanRunAudioTests(audio_manager))
return;
const char* file_name = "out_stereo_10sec.pcm";
- AudioInputStreamWrapper aisw;
+ AudioInputStreamWrapper aisw(audio_manager);
AudioInputStream* ais = aisw.Create();
EXPECT_TRUE(ais->Open());
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 aaed644..8f7b28c 100644
--- a/media/audio/win/audio_low_latency_output_win_unittest.cc
+++ b/media/audio/win/audio_low_latency_output_win_unittest.cc
@@ -142,13 +142,13 @@ class ReadFromFileAudioSource : public AudioOutputStream::AudioSourceCallback {
// Convenience method which ensures that we are not running on the build
// bots and that at least one valid output device can be found.
-static bool CanRunAudioTests() {
+static bool CanRunAudioTests(AudioManager* audio_man) {
+ if (NULL == audio_man)
+ return false;
+
scoped_ptr<base::Environment> env(base::Environment::Create());
if (env->HasVar("CHROME_HEADLESS"))
return false;
- AudioManager* audio_man = AudioManager::GetAudioManager();
- if (NULL == audio_man)
- return false;
// TODO(henrika): note that we use Wave today to query the number of
// existing output devices.
return audio_man->HasAudioOutputDevices();
@@ -158,9 +158,9 @@ static bool CanRunAudioTests() {
// also allows the user to modify the default settings.
class AudioOutputStreamWrapper {
public:
- AudioOutputStreamWrapper()
+ explicit AudioOutputStreamWrapper(AudioManager* audio_manager)
: com_init_(ScopedCOMInitializer::kMTA),
- audio_man_(AudioManager::GetAudioManager()),
+ audio_man_(audio_manager),
format_(AudioParameters::AUDIO_PCM_LOW_LATENCY),
channel_layout_(CHANNEL_LAYOUT_STEREO),
bits_per_sample_(16) {
@@ -208,7 +208,7 @@ class AudioOutputStreamWrapper {
}
ScopedCOMInitializer com_init_;
- AudioManager* audio_man_;
+ scoped_refptr<AudioManager> audio_man_;
AudioParameters::Format format_;
ChannelLayout channel_layout_;
int bits_per_sample_;
@@ -217,8 +217,9 @@ class AudioOutputStreamWrapper {
};
// Convenience method which creates a default AudioOutputStream object.
-static AudioOutputStream* CreateDefaultAudioOutputStream() {
- AudioOutputStreamWrapper aosw;
+static AudioOutputStream* CreateDefaultAudioOutputStream(
+ AudioManager* audio_manager) {
+ AudioOutputStreamWrapper aosw(audio_manager);
AudioOutputStream* aos = aosw.Create();
return aos;
}
@@ -233,7 +234,8 @@ static void QuitMessageLoop(base::MessageLoopProxy* proxy) {
// endpoint device.
// TODO(henrika): modify this test when we support full device enumeration.
TEST(WinAudioOutputTest, WASAPIAudioOutputStreamTestHardwareSampleRate) {
- if (!CanRunAudioTests())
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
+ if (!CanRunAudioTests(audio_manager))
return;
ScopedCOMInitializer com_init(ScopedCOMInitializer::kMTA);
@@ -257,26 +259,29 @@ TEST(WinAudioOutputTest, WASAPIAudioOutputStreamTestHardwareSampleRate) {
// Test Create(), Close() calling sequence.
TEST(WinAudioOutputTest, WASAPIAudioOutputStreamTestCreateAndClose) {
- if (!CanRunAudioTests())
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
+ if (!CanRunAudioTests(audio_manager))
return;
- AudioOutputStream* aos = CreateDefaultAudioOutputStream();
+ AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager);
aos->Close();
}
// Test Open(), Close() calling sequence.
TEST(WinAudioOutputTest, WASAPIAudioOutputStreamTestOpenAndClose) {
- if (!CanRunAudioTests())
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
+ if (!CanRunAudioTests(audio_manager))
return;
- AudioOutputStream* aos = CreateDefaultAudioOutputStream();
+ AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager);
EXPECT_TRUE(aos->Open());
aos->Close();
}
// Test Open(), Start(), Close() calling sequence.
TEST(WinAudioOutputTest, WASAPIAudioOutputStreamTestOpenStartAndClose) {
- if (!CanRunAudioTests())
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
+ if (!CanRunAudioTests(audio_manager))
return;
- AudioOutputStream* aos = CreateDefaultAudioOutputStream();
+ AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager);
EXPECT_TRUE(aos->Open());
MockAudioSourceCallback source;
EXPECT_CALL(source, OnError(aos, _))
@@ -287,9 +292,10 @@ TEST(WinAudioOutputTest, WASAPIAudioOutputStreamTestOpenStartAndClose) {
// Test Open(), Start(), Stop(), Close() calling sequence.
TEST(WinAudioOutputTest, WASAPIAudioOutputStreamTestOpenStartStopAndClose) {
- if (!CanRunAudioTests())
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
+ if (!CanRunAudioTests(audio_manager))
return;
- AudioOutputStream* aos = CreateDefaultAudioOutputStream();
+ AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager);
EXPECT_TRUE(aos->Open());
MockAudioSourceCallback source;
EXPECT_CALL(source, OnError(aos, _))
@@ -301,9 +307,10 @@ TEST(WinAudioOutputTest, WASAPIAudioOutputStreamTestOpenStartStopAndClose) {
// Test SetVolume(), GetVolume()
TEST(WinAudioOutputTest, WASAPIAudioOutputStreamTestVolume) {
- if (!CanRunAudioTests())
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
+ if (!CanRunAudioTests(audio_manager))
return;
- AudioOutputStream* aos = CreateDefaultAudioOutputStream();
+ AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager);
// Initial volume should be full volume (1.0).
double volume = 0.0;
@@ -337,9 +344,11 @@ TEST(WinAudioOutputTest, WASAPIAudioOutputStreamTestVolume) {
// Test some additional calling sequences.
TEST(WinAudioOutputTest, WASAPIAudioOutputStreamTestMiscCallingSequences) {
- if (!CanRunAudioTests())
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
+ if (!CanRunAudioTests(audio_manager))
return;
- AudioOutputStream* aos = CreateDefaultAudioOutputStream();
+
+ AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager);
WASAPIAudioOutputStream* waos = static_cast<WASAPIAudioOutputStream*>(aos);
// Open(), Open() is a valid calling sequence (second call does nothing).
@@ -365,7 +374,8 @@ TEST(WinAudioOutputTest, WASAPIAudioOutputStreamTestMiscCallingSequences) {
// Use default packet size (10ms) and verify that rendering starts.
TEST(WinAudioOutputTest, WASAPIAudioOutputStreamTestPacketSizeInMilliseconds) {
- if (!CanRunAudioTests())
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
+ if (!CanRunAudioTests(audio_manager))
return;
MessageLoopForUI loop;
@@ -375,7 +385,7 @@ TEST(WinAudioOutputTest, WASAPIAudioOutputStreamTestPacketSizeInMilliseconds) {
// Create default WASAPI output stream which plays out in stereo using
// the shared mixing rate. The default buffer size is 10ms.
- AudioOutputStreamWrapper aosw;
+ AudioOutputStreamWrapper aosw(audio_manager);
AudioOutputStream* aos = aosw.Create();
EXPECT_TRUE(aos->Open());
@@ -406,7 +416,8 @@ TEST(WinAudioOutputTest, WASAPIAudioOutputStreamTestPacketSizeInMilliseconds) {
// Use a fixed packets size (independent of sample rate) and verify
// that rendering starts.
TEST(WinAudioOutputTest, WASAPIAudioOutputStreamTestPacketSizeInSamples) {
- if (!CanRunAudioTests())
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
+ if (!CanRunAudioTests(audio_manager))
return;
MessageLoopForUI loop;
@@ -416,7 +427,7 @@ TEST(WinAudioOutputTest, WASAPIAudioOutputStreamTestPacketSizeInSamples) {
// Create default WASAPI output stream which plays out in stereo using
// the shared mixing rate. The buffer size is set to 1024 samples.
- AudioOutputStreamWrapper aosw;
+ AudioOutputStreamWrapper aosw(audio_manager);
AudioOutputStream* aos = aosw.Create(1024);
EXPECT_TRUE(aos->Open());
@@ -445,7 +456,8 @@ TEST(WinAudioOutputTest, WASAPIAudioOutputStreamTestPacketSizeInSamples) {
}
TEST(WinAudioOutputTest, WASAPIAudioOutputStreamTestMono) {
- if (!CanRunAudioTests())
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
+ if (!CanRunAudioTests(audio_manager))
return;
MessageLoopForUI loop;
@@ -455,10 +467,14 @@ TEST(WinAudioOutputTest, WASAPIAudioOutputStreamTestMono) {
// Create default WASAPI output stream which plays out in *mono* using
// the shared mixing rate. The default buffer size is 10ms.
- AudioOutputStreamWrapper aosw;
+ AudioOutputStreamWrapper aosw(audio_manager);
AudioOutputStream* aos = aosw.Create(CHANNEL_LAYOUT_MONO);
- EXPECT_TRUE(aos->Open());
-
+ bool opened;
+ EXPECT_TRUE(opened = aos->Open());
+ if (!opened) {
+ delete aos;
+ return;
+ }
// Derive the expected size in bytes of each packet.
uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() *
(aosw.bits_per_sample() / 8);
@@ -490,10 +506,11 @@ TEST(WinAudioOutputTest, WASAPIAudioOutputStreamTestMono) {
// environment variable to a value greater than 0.
// The test files are approximately 20 seconds long.
TEST(WinAudioOutputTest, DISABLED_WASAPIAudioOutputStreamReadFromFile) {
- if (!CanRunAudioTests())
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
+ if (!CanRunAudioTests(audio_manager))
return;
- AudioOutputStreamWrapper aosw;
+ AudioOutputStreamWrapper aosw(audio_manager);
AudioOutputStream* aos = aosw.Create();
EXPECT_TRUE(aos->Open());
diff --git a/media/audio/win/audio_manager_win.cc b/media/audio/win/audio_manager_win.cc
index 158053f..f563d2c 100644
--- a/media/audio/win/audio_manager_win.cc
+++ b/media/audio/win/audio_manager_win.cc
@@ -304,6 +304,6 @@ void AudioManagerWin::GetAudioInputDeviceNames(
}
/// static
-AudioManager* AudioManager::CreateAudioManager() {
+AudioManager* CreateAudioManager() {
return new AudioManagerWin();
}
diff --git a/media/audio/win/audio_output_win_unittest.cc b/media/audio/win/audio_output_win_unittest.cc
index 71c0d0c..72f078a 100644
--- a/media/audio/win/audio_output_win_unittest.cc
+++ b/media/audio/win/audio_output_win_unittest.cc
@@ -199,8 +199,7 @@ class ReadOnlyMappedFile {
// ============================================================================
// Validate that the AudioManager::AUDIO_MOCK callbacks work.
TEST(WinAudioTest, MockStreamBasicCallbacks) {
- AudioManager* audio_man = AudioManager::GetAudioManager();
- ASSERT_TRUE(NULL != audio_man);
+ scoped_refptr<AudioManager> audio_man(AudioManager::Create());
AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_MOCK, CHANNEL_LAYOUT_STEREO, 8000,
8, 128));
@@ -226,8 +225,7 @@ TEST(WinAudioTest, MockStreamBasicCallbacks) {
TEST(WinAudioTest, PCMWaveStreamGetAndClose) {
if (IsRunningHeadless())
return;
- AudioManager* audio_man = AudioManager::GetAudioManager();
- ASSERT_TRUE(NULL != audio_man);
+ scoped_refptr<AudioManager> audio_man(AudioManager::Create());
if (!audio_man->HasAudioOutputDevices())
return;
AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
@@ -241,8 +239,7 @@ TEST(WinAudioTest, PCMWaveStreamGetAndClose) {
TEST(WinAudioTest, SanityOnMakeParams) {
if (IsRunningHeadless())
return;
- AudioManager* audio_man = AudioManager::GetAudioManager();
- ASSERT_TRUE(NULL != audio_man);
+ scoped_refptr<AudioManager> audio_man(AudioManager::Create());
if (!audio_man->HasAudioOutputDevices())
return;
AudioParameters::Format fmt = AudioParameters::AUDIO_PCM_LINEAR;
@@ -269,8 +266,7 @@ TEST(WinAudioTest, SanityOnMakeParams) {
TEST(WinAudioTest, PCMWaveStreamOpenAndClose) {
if (IsRunningHeadless())
return;
- AudioManager* audio_man = AudioManager::GetAudioManager();
- ASSERT_TRUE(NULL != audio_man);
+ scoped_refptr<AudioManager> audio_man(AudioManager::Create());
if (!audio_man->HasAudioOutputDevices())
return;
AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
@@ -285,8 +281,7 @@ TEST(WinAudioTest, PCMWaveStreamOpenAndClose) {
TEST(WinAudioTest, PCMWaveStreamOpenLimit) {
if (IsRunningHeadless())
return;
- AudioManager* audio_man = AudioManager::GetAudioManager();
- ASSERT_TRUE(NULL != audio_man);
+ scoped_refptr<AudioManager> audio_man(AudioManager::Create());
if (!audio_man->HasAudioOutputDevices())
return;
AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
@@ -302,8 +297,7 @@ TEST(WinAudioTest, PCMWaveStreamOpenLimit) {
TEST(WinAudioTest, PCMWaveStreamTripleBuffer) {
if (IsRunningHeadless())
return;
- AudioManager* audio_man = AudioManager::GetAudioManager();
- ASSERT_TRUE(NULL != audio_man);
+ scoped_refptr<AudioManager> audio_man(AudioManager::Create());
if (!audio_man->HasAudioOutputDevices())
return;
AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
@@ -327,8 +321,7 @@ TEST(WinAudioTest, PCMWaveStreamTripleBuffer) {
TEST(WinAudioTest, PCMWaveSlowSource) {
if (IsRunningHeadless())
return;
- AudioManager* audio_man = AudioManager::GetAudioManager();
- ASSERT_TRUE(NULL != audio_man);
+ scoped_refptr<AudioManager> audio_man(AudioManager::Create());
if (!audio_man->HasAudioOutputDevices())
return;
AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
@@ -354,8 +347,7 @@ TEST(WinAudioTest, PCMWaveSlowSource) {
TEST(WinAudioTest, PCMWaveStreamPlaySlowLoop) {
if (IsRunningHeadless())
return;
- AudioManager* audio_man = AudioManager::GetAudioManager();
- ASSERT_TRUE(NULL != audio_man);
+ scoped_refptr<AudioManager> audio_man(AudioManager::Create());
if (!audio_man->HasAudioOutputDevices())
return;
uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
@@ -385,8 +377,7 @@ TEST(WinAudioTest, PCMWaveStreamPlaySlowLoop) {
TEST(WinAudioTest, PCMWaveStreamPlay200HzTone44Kss) {
if (IsRunningHeadless())
return;
- AudioManager* audio_man = AudioManager::GetAudioManager();
- ASSERT_TRUE(NULL != audio_man);
+ scoped_refptr<AudioManager> audio_man(AudioManager::Create());
if (!audio_man->HasAudioOutputDevices())
return;
uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
@@ -413,8 +404,7 @@ TEST(WinAudioTest, PCMWaveStreamPlay200HzTone44Kss) {
TEST(WinAudioTest, PCMWaveStreamPlay200HzTone22Kss) {
if (IsRunningHeadless())
return;
- AudioManager* audio_man = AudioManager::GetAudioManager();
- ASSERT_TRUE(NULL != audio_man);
+ scoped_refptr<AudioManager> audio_man(AudioManager::Create());
if (!audio_man->HasAudioOutputDevices())
return;
uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 20;
@@ -460,8 +450,7 @@ TEST(WinAudioTest, PushSourceFile16KHz) {
ReadOnlyMappedFile file_reader(audio_file.value().c_str());
ASSERT_TRUE(file_reader.is_valid());
- AudioManager* audio_man = AudioManager::GetAudioManager();
- ASSERT_TRUE(NULL != audio_man);
+ scoped_refptr<AudioManager> audio_man(AudioManager::Create());
if (!audio_man->HasAudioOutputDevices())
return;
@@ -508,8 +497,7 @@ TEST(WinAudioTest, PushSourceFile16KHz) {
TEST(WinAudioTest, PCMWaveStreamPlayTwice200HzTone44Kss) {
if (IsRunningHeadless())
return;
- AudioManager* audio_man = AudioManager::GetAudioManager();
- ASSERT_TRUE(NULL != audio_man);
+ scoped_refptr<AudioManager> audio_man(AudioManager::Create());
if (!audio_man->HasAudioOutputDevices())
return;
@@ -546,8 +534,7 @@ TEST(WinAudioTest, PCMWaveStreamPlayTwice200HzTone44Kss) {
TEST(WinAudioTest, PCMWaveStreamPlay200HzToneLowLatency) {
if (IsRunningHeadless())
return;
- AudioManager* audio_man = AudioManager::GetAudioManager();
- ASSERT_TRUE(NULL != audio_man);
+ scoped_refptr<AudioManager> audio_man(AudioManager::Create());
if (!audio_man->HasAudioOutputDevices())
return;
@@ -583,8 +570,7 @@ TEST(WinAudioTest, PCMWaveStreamPlay200HzToneLowLatency) {
TEST(WinAudioTest, PCMWaveStreamPendingBytes) {
if (IsRunningHeadless())
return;
- AudioManager* audio_man = AudioManager::GetAudioManager();
- ASSERT_TRUE(NULL != audio_man);
+ scoped_refptr<AudioManager> audio_man(AudioManager::Create());
if (!audio_man->HasAudioOutputDevices())
return;
@@ -681,7 +667,7 @@ DWORD __stdcall SyncSocketThread(void* context) {
SyncThreadContext& ctx = *(reinterpret_cast<SyncThreadContext*>(context));
const int kTwoSecBytes =
- AudioParameters::kAudioCDSampleRate * 2 * sizeof(uint16);
+ AudioParameters::kAudioCDSampleRate * 2 * sizeof(uint16); // NOLINT
uint8* buffer = new uint8[kTwoSecBytes];
SineWaveAudioSource sine(SineWaveAudioSource::FORMAT_16BIT_LINEAR_PCM,
1, ctx.sine_freq, ctx.sample_rate);
@@ -713,8 +699,7 @@ TEST(WinAudioTest, SyncSocketBasic) {
if (IsRunningHeadless())
return;
- AudioManager* audio_man = AudioManager::GetAudioManager();
- ASSERT_TRUE(NULL != audio_man);
+ scoped_refptr<AudioManager> audio_man(AudioManager::Create());
if (!audio_man->HasAudioOutputDevices())
return;
diff --git a/media/filters/reference_audio_renderer.cc b/media/filters/reference_audio_renderer.cc
index deae588..8e95628 100644
--- a/media/filters/reference_audio_renderer.cc
+++ b/media/filters/reference_audio_renderer.cc
@@ -10,8 +10,9 @@
namespace media {
-ReferenceAudioRenderer::ReferenceAudioRenderer()
+ReferenceAudioRenderer::ReferenceAudioRenderer(AudioManager* audio_manager)
: AudioRendererBase(),
+ audio_manager_(audio_manager),
bytes_per_second_(0) {
}
@@ -71,7 +72,7 @@ bool ReferenceAudioRenderer::OnInitialize(int bits_per_channel,
int sample_rate) {
int samples_per_packet = sample_rate / 10;
int hardware_buffer_size = samples_per_packet *
- ChannelLayoutToChannelCount(channel_layout) * bits_per_channel / 8;
+ ChannelLayoutToChannelCount(channel_layout) * bits_per_channel / 8;
// Allocate audio buffer based on hardware buffer size.
buffer_capacity_ = 3 * hardware_buffer_size;
@@ -81,7 +82,8 @@ bool ReferenceAudioRenderer::OnInitialize(int bits_per_channel,
sample_rate, bits_per_channel, samples_per_packet);
bytes_per_second_ = params.GetBytesPerSecond();
- controller_ = AudioOutputController::Create(this, params, buffer_capacity_);
+ controller_ = AudioOutputController::Create(audio_manager_, this, params,
+ buffer_capacity_);
return controller_ != NULL;
}
diff --git a/media/filters/reference_audio_renderer.h b/media/filters/reference_audio_renderer.h
index 9ab9b26..409e3850 100644
--- a/media/filters/reference_audio_renderer.h
+++ b/media/filters/reference_audio_renderer.h
@@ -17,13 +17,15 @@
#include "media/audio/audio_output_controller.h"
#include "media/filters/audio_renderer_base.h"
+class AudioManager;
+
namespace media {
class MEDIA_EXPORT ReferenceAudioRenderer
: public AudioRendererBase,
public AudioOutputController::EventHandler {
public:
- ReferenceAudioRenderer();
+ explicit ReferenceAudioRenderer(AudioManager* audio_manager);
virtual ~ReferenceAudioRenderer();
// Filter implementation.
@@ -49,11 +51,12 @@ class MEDIA_EXPORT ReferenceAudioRenderer
virtual void OnStop() OVERRIDE;
private:
- int bytes_per_second_;
-
// AudioOutputController::Close callback.
virtual void OnClose();
+ scoped_refptr<AudioManager> audio_manager_;
+ int bytes_per_second_;
+
// Audio output controller.
scoped_refptr<media::AudioOutputController> controller_;
diff --git a/media/tools/player_wtl/movie.cc b/media/tools/player_wtl/movie.cc
index 9b298ca..b6bd2f8 100644
--- a/media/tools/player_wtl/movie.cc
+++ b/media/tools/player_wtl/movie.cc
@@ -7,6 +7,7 @@
#include "base/memory/singleton.h"
#include "base/threading/platform_thread.h"
#include "base/utf_string_conversions.h"
+#include "media/audio/audio_manager.h"
#include "media/base/filter_collection.h"
#include "media/base/media_log.h"
#include "media/base/message_loop_factory_impl.h"
@@ -30,7 +31,8 @@ using media::ReferenceAudioRenderer;
namespace media {
Movie::Movie()
- : enable_audio_(true),
+ : audio_manager_(AudioManager::Create()),
+ enable_audio_(true),
enable_draw_(true),
enable_dump_yuv_file_(false),
enable_pause_(false),
@@ -78,7 +80,8 @@ bool Movie::Open(const wchar_t* url, WtlVideoRenderer* video_renderer) {
message_loop_factory_->GetMessageLoop("VideoDecoderThread")));
if (enable_audio_) {
- collection->AddAudioRenderer(new ReferenceAudioRenderer());
+ collection->AddAudioRenderer(
+ new ReferenceAudioRenderer(audio_manager_));
} else {
collection->AddAudioRenderer(new media::NullAudioRenderer());
}
diff --git a/media/tools/player_wtl/movie.h b/media/tools/player_wtl/movie.h
index afe80be..cd24c88 100644
--- a/media/tools/player_wtl/movie.h
+++ b/media/tools/player_wtl/movie.h
@@ -13,6 +13,7 @@
#include "base/memory/scoped_ptr.h"
#include "media/base/message_loop_factory.h"
+class AudioManager;
template <typename T> struct DefaultSingletonTraits;
class WtlVideoRenderer;
@@ -22,7 +23,7 @@ class PipelineImpl;
class Movie {
public:
- // Returns the singleton instance.
+ // Returns the singleton instance.
static Movie* GetInstance();
// Open a movie.
@@ -84,6 +85,7 @@ class Movie {
scoped_refptr<PipelineImpl> pipeline_;
scoped_ptr<media::MessageLoopFactory> message_loop_factory_;
+ scoped_refptr<AudioManager> audio_manager_;
bool enable_audio_;
bool enable_draw_;
diff --git a/media/tools/player_x11/player_x11.cc b/media/tools/player_x11/player_x11.cc
index 323f250..d563328 100644
--- a/media/tools/player_x11/player_x11.cc
+++ b/media/tools/player_x11/player_x11.cc
@@ -2,10 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <iostream>
-#include <signal.h>
#include <X11/keysym.h>
#include <X11/Xlib.h>
+#include <signal.h>
+
+#include <iostream> // NOLINT
#include "base/at_exit.h"
#include "base/bind.h"
@@ -14,6 +15,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread.h"
+#include "media/audio/audio_manager.h"
#include "media/base/filter_collection.h"
#include "media/base/media.h"
#include "media/base/media_log.h"
@@ -33,6 +35,8 @@ static Display* g_display = NULL;
static Window g_window = 0;
static bool g_running = false;
+AudioManager* g_audio_manager = NULL;
+
class MessageLoopQuitter {
public:
explicit MessageLoopQuitter(MessageLoop* loop) : loop_(loop) {}
@@ -102,10 +106,12 @@ bool InitPipeline(MessageLoop* message_loop,
new X11VideoRenderer(g_display, g_window, paint_message_loop));
}
- if (enable_audio)
- collection->AddAudioRenderer(new media::ReferenceAudioRenderer());
- else
+ if (enable_audio) {
+ collection->AddAudioRenderer(
+ new media::ReferenceAudioRenderer(g_audio_manager));
+ } else {
collection->AddAudioRenderer(new media::NullAudioRenderer());
+ }
// Create the pipeline and start it.
*pipeline = new media::PipelineImpl(message_loop, new media::MediaLog());
@@ -176,7 +182,7 @@ void PeriodicalUpdate(
base::Unretained(quitter)));
return;
} else if (key == XK_space) {
- if (pipeline->GetPlaybackRate() < 0.01f) // paused
+ if (pipeline->GetPlaybackRate() < 0.01f) // paused
pipeline->SetPlaybackRate(1.0f);
else
pipeline->SetPlaybackRate(0.0f);
@@ -194,6 +200,9 @@ void PeriodicalUpdate(
}
int main(int argc, char** argv) {
+ scoped_refptr<AudioManager> audio_manager(AudioManager::Create());
+ g_audio_manager = audio_manager;
+
// Read arguments.
if (argc == 1) {
std::cout << "Usage: " << argv[0] << " --file=FILE" << std::endl
@@ -252,7 +261,7 @@ int main(int argc, char** argv) {
message_loop.PostTask(FROM_HERE, base::Bind(
&PeriodicalUpdate, pipeline, &message_loop, audio_only));
message_loop.Run();
- } else{
+ } else {
std::cout << "Pipeline initialization failed..." << std::endl;
}
@@ -262,5 +271,7 @@ int main(int argc, char** argv) {
thread->Stop();
XDestroyWindow(g_display, g_window);
XCloseDisplay(g_display);
+ g_audio_manager = NULL;
+
return 0;
}