cc: Added inline to Tile::IsReadyToDraw
[chromium-blink-merge.git] / media / audio / audio_manager_base.cc
blobdb77f004e386ec801a595a7c7fc030df6cbb0603
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/audio/audio_manager_base.h"
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/command_line.h"
10 #include "base/message_loop/message_loop_proxy.h"
11 #include "base/threading/thread.h"
12 #include "build/build_config.h"
13 #include "media/audio/audio_output_dispatcher_impl.h"
14 #include "media/audio/audio_output_proxy.h"
15 #include "media/audio/audio_output_resampler.h"
16 #include "media/audio/audio_util.h"
17 #include "media/audio/fake_audio_input_stream.h"
18 #include "media/audio/fake_audio_output_stream.h"
19 #include "media/base/media_switches.h"
21 namespace media {
23 static const int kStreamCloseDelaySeconds = 5;
25 // Default maximum number of output streams that can be open simultaneously
26 // for all platforms.
27 static const int kDefaultMaxOutputStreams = 16;
29 // Default maximum number of input streams that can be open simultaneously
30 // for all platforms.
31 static const int kDefaultMaxInputStreams = 16;
33 static const int kMaxInputChannels = 2;
35 const char AudioManagerBase::kDefaultDeviceName[] = "Default";
36 const char AudioManagerBase::kDefaultDeviceId[] = "default";
38 struct AudioManagerBase::DispatcherParams {
39 DispatcherParams(const AudioParameters& input,
40 const AudioParameters& output,
41 const std::string& device_id)
42 : input_params(input),
43 output_params(output),
44 input_device_id(device_id) {}
45 ~DispatcherParams() {}
47 const AudioParameters input_params;
48 const AudioParameters output_params;
49 const std::string input_device_id;
50 scoped_refptr<AudioOutputDispatcher> dispatcher;
52 private:
53 DISALLOW_COPY_AND_ASSIGN(DispatcherParams);
56 class AudioManagerBase::CompareByParams {
57 public:
58 explicit CompareByParams(const DispatcherParams* dispatcher)
59 : dispatcher_(dispatcher) {}
60 bool operator()(DispatcherParams* dispatcher_in) const {
61 // We will reuse the existing dispatcher when:
62 // 1) Unified IO is not used, input_params and output_params of the
63 // existing dispatcher are the same as the requested dispatcher.
64 // 2) Unified IO is used, input_params, output_params and input_device_id
65 // of the existing dispatcher are the same as the request dispatcher.
66 return (dispatcher_->input_params == dispatcher_in->input_params &&
67 dispatcher_->output_params == dispatcher_in->output_params &&
68 (!dispatcher_->input_params.input_channels() ||
69 dispatcher_->input_device_id == dispatcher_in->input_device_id));
72 private:
73 const DispatcherParams* dispatcher_;
76 AudioManagerBase::AudioManagerBase()
77 : max_num_output_streams_(kDefaultMaxOutputStreams),
78 max_num_input_streams_(kDefaultMaxInputStreams),
79 num_output_streams_(0),
80 num_input_streams_(0),
81 // TODO(dalecurtis): Switch this to an ObserverListThreadSafe, so we don't
82 // block the UI thread when swapping devices.
83 output_listeners_(
84 ObserverList<AudioDeviceListener>::NOTIFY_EXISTING_ONLY),
85 audio_thread_(new base::Thread("AudioThread")) {
86 #if defined(OS_WIN)
87 audio_thread_->init_com_with_mta(true);
88 #elif defined(OS_MACOSX)
89 // CoreAudio calls must occur on the main thread of the process, which in our
90 // case is sadly the browser UI thread. Failure to execute calls on the right
91 // thread leads to crashes and odd behavior. See http://crbug.com/158170.
92 // TODO(dalecurtis): We should require the message loop to be passed in.
93 const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
94 if (!cmd_line->HasSwitch(switches::kDisableMainThreadAudio) &&
95 base::MessageLoopProxy::current().get() &&
96 base::MessageLoop::current()->IsType(base::MessageLoop::TYPE_UI)) {
97 message_loop_ = base::MessageLoopProxy::current();
98 return;
100 #endif
102 CHECK(audio_thread_->Start());
103 message_loop_ = audio_thread_->message_loop_proxy();
106 AudioManagerBase::~AudioManagerBase() {
107 // The platform specific AudioManager implementation must have already
108 // stopped the audio thread. Otherwise, we may destroy audio streams before
109 // stopping the thread, resulting an unexpected behavior.
110 // This way we make sure activities of the audio streams are all stopped
111 // before we destroy them.
112 CHECK(!audio_thread_.get());
113 // All the output streams should have been deleted.
114 DCHECK_EQ(0, num_output_streams_);
115 // All the input streams should have been deleted.
116 DCHECK_EQ(0, num_input_streams_);
119 string16 AudioManagerBase::GetAudioInputDeviceModel() {
120 return string16();
123 scoped_refptr<base::MessageLoopProxy> AudioManagerBase::GetMessageLoop() {
124 return message_loop_;
127 scoped_refptr<base::MessageLoopProxy> AudioManagerBase::GetWorkerLoop() {
128 // Lazily start the worker thread.
129 if (!audio_thread_->IsRunning())
130 CHECK(audio_thread_->Start());
132 return audio_thread_->message_loop_proxy();
135 AudioOutputStream* AudioManagerBase::MakeAudioOutputStream(
136 const AudioParameters& params,
137 const std::string& input_device_id) {
138 // TODO(miu): Fix ~50 call points across several unit test modules to call
139 // this method on the audio thread, then uncomment the following:
140 // DCHECK(message_loop_->BelongsToCurrentThread());
142 if (!params.IsValid()) {
143 DLOG(ERROR) << "Audio parameters are invalid";
144 return NULL;
147 // Limit the number of audio streams opened. This is to prevent using
148 // excessive resources for a large number of audio streams. More
149 // importantly it prevents instability on certain systems.
150 // See bug: http://crbug.com/30242.
151 if (num_output_streams_ >= max_num_output_streams_) {
152 DLOG(ERROR) << "Number of opened output audio streams "
153 << num_output_streams_
154 << " exceed the max allowed number "
155 << max_num_output_streams_;
156 return NULL;
159 AudioOutputStream* stream;
160 switch (params.format()) {
161 case AudioParameters::AUDIO_PCM_LINEAR:
162 stream = MakeLinearOutputStream(params);
163 break;
164 case AudioParameters::AUDIO_PCM_LOW_LATENCY:
165 stream = MakeLowLatencyOutputStream(params, input_device_id);
166 break;
167 case AudioParameters::AUDIO_FAKE:
168 stream = FakeAudioOutputStream::MakeFakeStream(this, params);
169 break;
170 default:
171 stream = NULL;
172 break;
175 if (stream) {
176 ++num_output_streams_;
179 return stream;
182 AudioInputStream* AudioManagerBase::MakeAudioInputStream(
183 const AudioParameters& params, const std::string& device_id) {
184 // TODO(miu): Fix ~20 call points across several unit test modules to call
185 // this method on the audio thread, then uncomment the following:
186 // DCHECK(message_loop_->BelongsToCurrentThread());
188 if (!params.IsValid() || (params.channels() > kMaxInputChannels) ||
189 device_id.empty()) {
190 DLOG(ERROR) << "Audio parameters are invalid for device " << device_id;
191 return NULL;
194 if (num_input_streams_ >= max_num_input_streams_) {
195 DLOG(ERROR) << "Number of opened input audio streams "
196 << num_input_streams_
197 << " exceed the max allowed number " << max_num_input_streams_;
198 return NULL;
201 AudioInputStream* stream;
202 switch (params.format()) {
203 case AudioParameters::AUDIO_PCM_LINEAR:
204 stream = MakeLinearInputStream(params, device_id);
205 break;
206 case AudioParameters::AUDIO_PCM_LOW_LATENCY:
207 stream = MakeLowLatencyInputStream(params, device_id);
208 break;
209 case AudioParameters::AUDIO_FAKE:
210 stream = FakeAudioInputStream::MakeFakeStream(this, params);
211 break;
212 default:
213 stream = NULL;
214 break;
217 if (stream) {
218 ++num_input_streams_;
221 return stream;
224 AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy(
225 const AudioParameters& params, const std::string& input_device_id) {
226 #if defined(OS_IOS)
227 // IOS implements audio input only.
228 NOTIMPLEMENTED();
229 return NULL;
230 #else
231 DCHECK(message_loop_->BelongsToCurrentThread());
233 // If we're not using AudioOutputResampler our output parameters are the same
234 // as our input parameters.
235 AudioParameters output_params = params;
236 if (params.format() == AudioParameters::AUDIO_PCM_LOW_LATENCY) {
237 output_params = GetPreferredOutputStreamParameters(params);
239 // Ensure we only pass on valid output parameters.
240 if (!output_params.IsValid()) {
241 // We've received invalid audio output parameters, so switch to a mock
242 // output device based on the input parameters. This may happen if the OS
243 // provided us junk values for the hardware configuration.
244 LOG(ERROR) << "Invalid audio output parameters received; using fake "
245 << "audio path. Channels: " << output_params.channels() << ", "
246 << "Sample Rate: " << output_params.sample_rate() << ", "
247 << "Bits Per Sample: " << output_params.bits_per_sample()
248 << ", Frames Per Buffer: "
249 << output_params.frames_per_buffer();
251 // Tell the AudioManager to create a fake output device.
252 output_params = AudioParameters(
253 AudioParameters::AUDIO_FAKE, params.channel_layout(),
254 params.sample_rate(), params.bits_per_sample(),
255 params.frames_per_buffer());
259 DispatcherParams* dispatcher_params =
260 new DispatcherParams(params, output_params, input_device_id);
262 AudioOutputDispatchers::iterator it =
263 std::find_if(output_dispatchers_.begin(), output_dispatchers_.end(),
264 CompareByParams(dispatcher_params));
265 if (it != output_dispatchers_.end()) {
266 delete dispatcher_params;
267 return new AudioOutputProxy((*it)->dispatcher.get());
270 const base::TimeDelta kCloseDelay =
271 base::TimeDelta::FromSeconds(kStreamCloseDelaySeconds);
272 scoped_refptr<AudioOutputDispatcher> dispatcher;
273 if (output_params.format() != AudioParameters::AUDIO_FAKE) {
274 dispatcher = new AudioOutputResampler(this, params, output_params,
275 input_device_id, kCloseDelay);
276 } else {
277 dispatcher = new AudioOutputDispatcherImpl(this, output_params,
278 input_device_id, kCloseDelay);
281 dispatcher_params->dispatcher = dispatcher;
282 output_dispatchers_.push_back(dispatcher_params);
283 return new AudioOutputProxy(dispatcher.get());
284 #endif // defined(OS_IOS)
287 void AudioManagerBase::ShowAudioInputSettings() {
290 void AudioManagerBase::GetAudioInputDeviceNames(
291 media::AudioDeviceNames* device_names) {
294 void AudioManagerBase::ReleaseOutputStream(AudioOutputStream* stream) {
295 DCHECK(stream);
296 // TODO(xians) : Have a clearer destruction path for the AudioOutputStream.
297 // For example, pass the ownership to AudioManager so it can delete the
298 // streams.
299 --num_output_streams_;
300 delete stream;
303 void AudioManagerBase::ReleaseInputStream(AudioInputStream* stream) {
304 DCHECK(stream);
305 // TODO(xians) : Have a clearer destruction path for the AudioInputStream.
306 --num_input_streams_;
307 delete stream;
310 void AudioManagerBase::Shutdown() {
311 // To avoid running into deadlocks while we stop the thread, shut it down
312 // via a local variable while not holding the audio thread lock.
313 scoped_ptr<base::Thread> audio_thread;
315 base::AutoLock lock(audio_thread_lock_);
316 audio_thread_.swap(audio_thread);
319 if (!audio_thread)
320 return;
322 // Only true when we're sharing the UI message loop with the browser. The UI
323 // loop is no longer running at this time and browser destruction is imminent.
324 if (message_loop_->BelongsToCurrentThread()) {
325 ShutdownOnAudioThread();
326 } else {
327 message_loop_->PostTask(FROM_HERE, base::Bind(
328 &AudioManagerBase::ShutdownOnAudioThread, base::Unretained(this)));
331 // Stop() will wait for any posted messages to be processed first.
332 audio_thread->Stop();
335 void AudioManagerBase::ShutdownOnAudioThread() {
336 // IOS implements audio input only.
337 #if defined(OS_IOS)
338 return;
339 #else
340 // This should always be running on the audio thread, but since we've cleared
341 // the audio_thread_ member pointer when we get here, we can't verify exactly
342 // what thread we're running on. The method is not public though and only
343 // called from one place, so we'll leave it at that.
344 AudioOutputDispatchers::iterator it = output_dispatchers_.begin();
345 for (; it != output_dispatchers_.end(); ++it) {
346 scoped_refptr<AudioOutputDispatcher>& dispatcher = (*it)->dispatcher;
347 if (dispatcher.get()) {
348 dispatcher->Shutdown();
349 // All AudioOutputProxies must have been freed before Shutdown is called.
350 // If they still exist, things will go bad. They have direct pointers to
351 // both physical audio stream objects that belong to the dispatcher as
352 // well as the message loop of the audio thread that will soon go away.
353 // So, better crash now than later.
354 DCHECK(dispatcher->HasOneRef()) << "AudioOutputProxies are still alive";
355 dispatcher = NULL;
359 output_dispatchers_.clear();
360 #endif // defined(OS_IOS)
363 void AudioManagerBase::AddOutputDeviceChangeListener(
364 AudioDeviceListener* listener) {
365 DCHECK(message_loop_->BelongsToCurrentThread());
366 output_listeners_.AddObserver(listener);
369 void AudioManagerBase::RemoveOutputDeviceChangeListener(
370 AudioDeviceListener* listener) {
371 DCHECK(message_loop_->BelongsToCurrentThread());
372 output_listeners_.RemoveObserver(listener);
375 void AudioManagerBase::NotifyAllOutputDeviceChangeListeners() {
376 DCHECK(message_loop_->BelongsToCurrentThread());
377 DVLOG(1) << "Firing OnDeviceChange() notifications.";
378 FOR_EACH_OBSERVER(AudioDeviceListener, output_listeners_, OnDeviceChange());
381 AudioParameters AudioManagerBase::GetDefaultOutputStreamParameters() {
382 return GetPreferredOutputStreamParameters(AudioParameters());
385 AudioParameters AudioManagerBase::GetInputStreamParameters(
386 const std::string& device_id) {
387 NOTREACHED();
388 return AudioParameters();
391 } // namespace media