OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/audio/audio_manager_base.h" | 5 #include "media/audio/audio_manager_base.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/message_loop_proxy.h" | 10 #include "base/message_loop_proxy.h" |
11 #include "base/threading/thread.h" | 11 #include "base/threading/thread.h" |
| 12 #if defined(OS_ANDROID) |
| 13 #include "jni/AudioManagerAndroid_jni.h" |
| 14 #endif |
12 #include "media/audio/audio_output_dispatcher_impl.h" | 15 #include "media/audio/audio_output_dispatcher_impl.h" |
13 #include "media/audio/audio_output_proxy.h" | 16 #include "media/audio/audio_output_proxy.h" |
14 #include "media/audio/audio_output_resampler.h" | 17 #include "media/audio/audio_output_resampler.h" |
15 #include "media/audio/audio_util.h" | 18 #include "media/audio/audio_util.h" |
16 #include "media/audio/fake_audio_input_stream.h" | 19 #include "media/audio/fake_audio_input_stream.h" |
17 #include "media/audio/fake_audio_output_stream.h" | 20 #include "media/audio/fake_audio_output_stream.h" |
18 #include "media/base/media_switches.h" | 21 #include "media/base/media_switches.h" |
19 | 22 |
20 namespace media { | 23 namespace media { |
21 | 24 |
22 static const int kStreamCloseDelaySeconds = 5; | 25 static const int kStreamCloseDelaySeconds = 5; |
23 | 26 |
24 // Default maximum number of output streams that can be open simultaneously | 27 // Default maximum number of output streams that can be open simultaneously |
25 // for all platforms. | 28 // for all platforms. |
26 static const int kDefaultMaxOutputStreams = 16; | 29 static const int kDefaultMaxOutputStreams = 16; |
27 | 30 |
28 // Default maximum number of input streams that can be open simultaneously | 31 // Default maximum number of input streams that can be open simultaneously |
29 // for all platforms. | 32 // for all platforms. |
30 static const int kDefaultMaxInputStreams = 16; | 33 static const int kDefaultMaxInputStreams = 16; |
31 | 34 |
32 static const int kMaxInputChannels = 2; | 35 static const int kMaxInputChannels = 2; |
33 | 36 |
| 37 #if defined(OS_ANDROID) |
| 38 static const int kAudioModeNormal = 0x00000000; |
| 39 static const int kAudioModeInCommunication = 0x00000003; |
| 40 #endif |
| 41 |
34 const char AudioManagerBase::kDefaultDeviceName[] = "Default"; | 42 const char AudioManagerBase::kDefaultDeviceName[] = "Default"; |
35 const char AudioManagerBase::kDefaultDeviceId[] = "default"; | 43 const char AudioManagerBase::kDefaultDeviceId[] = "default"; |
36 | 44 |
37 AudioManagerBase::AudioManagerBase() | 45 AudioManagerBase::AudioManagerBase() |
38 : num_active_input_streams_(0), | 46 : num_active_input_streams_(0), |
39 max_num_output_streams_(kDefaultMaxOutputStreams), | 47 max_num_output_streams_(kDefaultMaxOutputStreams), |
40 max_num_input_streams_(kDefaultMaxInputStreams), | 48 max_num_input_streams_(kDefaultMaxInputStreams), |
41 num_output_streams_(0), | 49 num_output_streams_(0), |
42 num_input_streams_(0), | 50 num_input_streams_(0), |
43 output_listeners_( | 51 output_listeners_( |
44 ObserverList<AudioDeviceListener>::NOTIFY_EXISTING_ONLY), | 52 ObserverList<AudioDeviceListener>::NOTIFY_EXISTING_ONLY), |
45 audio_thread_(new base::Thread("AudioThread")) { | 53 audio_thread_(new base::Thread("AudioThread")) { |
46 #if defined(OS_WIN) | 54 #if defined(OS_WIN) |
47 audio_thread_->init_com_with_mta(true); | 55 audio_thread_->init_com_with_mta(true); |
48 #endif | 56 #endif |
49 #if defined(OS_MACOSX) | 57 #if defined(OS_MACOSX) |
50 // On Mac, use a UI loop to get native message pump so that CoreAudio property | 58 // On Mac, use a UI loop to get native message pump so that CoreAudio property |
51 // listener callbacks fire. | 59 // listener callbacks fire. |
52 CHECK(audio_thread_->StartWithOptions( | 60 CHECK(audio_thread_->StartWithOptions( |
53 base::Thread::Options(MessageLoop::TYPE_UI, 0))); | 61 base::Thread::Options(MessageLoop::TYPE_UI, 0))); |
54 #else | 62 #else |
55 CHECK(audio_thread_->Start()); | 63 CHECK(audio_thread_->Start()); |
56 #endif | 64 #endif |
57 message_loop_ = audio_thread_->message_loop_proxy(); | 65 message_loop_ = audio_thread_->message_loop_proxy(); |
| 66 |
| 67 #if defined(OS_ANDROID) |
| 68 JNIEnv* env = base::android::AttachCurrentThread(); |
| 69 jobject context = base::android::GetApplicationContext(); |
| 70 j_audio_manager_.Reset( |
| 71 Java_AudioManagerAndroid_createAudioManagerAndroid(env, context)); |
| 72 #endif |
58 } | 73 } |
59 | 74 |
60 AudioManagerBase::~AudioManagerBase() { | 75 AudioManagerBase::~AudioManagerBase() { |
61 // The platform specific AudioManager implementation must have already | 76 // The platform specific AudioManager implementation must have already |
62 // stopped the audio thread. Otherwise, we may destroy audio streams before | 77 // stopped the audio thread. Otherwise, we may destroy audio streams before |
63 // stopping the thread, resulting an unexpected behavior. | 78 // stopping the thread, resulting an unexpected behavior. |
64 // This way we make sure activities of the audio streams are all stopped | 79 // This way we make sure activities of the audio streams are all stopped |
65 // before we destroy them. | 80 // before we destroy them. |
66 CHECK(!audio_thread_.get()); | 81 CHECK(!audio_thread_.get()); |
67 // All the output streams should have been deleted. | 82 // All the output streams should have been deleted. |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 case AudioParameters::AUDIO_FAKE: | 127 case AudioParameters::AUDIO_FAKE: |
113 stream = FakeAudioOutputStream::MakeFakeStream(this, params); | 128 stream = FakeAudioOutputStream::MakeFakeStream(this, params); |
114 break; | 129 break; |
115 default: | 130 default: |
116 stream = NULL; | 131 stream = NULL; |
117 break; | 132 break; |
118 } | 133 } |
119 | 134 |
120 if (stream) { | 135 if (stream) { |
121 ++num_output_streams_; | 136 ++num_output_streams_; |
| 137 #if defined(OS_ANDROID) |
| 138 if (num_output_streams_ == 1) |
| 139 RegisterHeadsetReceiver(); |
| 140 #endif |
122 } | 141 } |
123 | 142 |
124 return stream; | 143 return stream; |
125 } | 144 } |
126 | 145 |
127 AudioInputStream* AudioManagerBase::MakeAudioInputStream( | 146 AudioInputStream* AudioManagerBase::MakeAudioInputStream( |
128 const AudioParameters& params, const std::string& device_id) { | 147 const AudioParameters& params, const std::string& device_id) { |
129 // TODO(miu): Fix ~20 call points across several unit test modules to call | 148 // TODO(miu): Fix ~20 call points across several unit test modules to call |
130 // this method on the audio thread, then uncomment the following: | 149 // this method on the audio thread, then uncomment the following: |
131 // DCHECK(message_loop_->BelongsToCurrentThread()); | 150 // DCHECK(message_loop_->BelongsToCurrentThread()); |
(...skipping 22 matching lines...) Expand all Loading... |
154 case AudioParameters::AUDIO_FAKE: | 173 case AudioParameters::AUDIO_FAKE: |
155 stream = FakeAudioInputStream::MakeFakeStream(this, params); | 174 stream = FakeAudioInputStream::MakeFakeStream(this, params); |
156 break; | 175 break; |
157 default: | 176 default: |
158 stream = NULL; | 177 stream = NULL; |
159 break; | 178 break; |
160 } | 179 } |
161 | 180 |
162 if (stream) { | 181 if (stream) { |
163 ++num_input_streams_; | 182 ++num_input_streams_; |
| 183 #if defined(OS_ANDROID) |
| 184 if (num_input_streams_ == 1) |
| 185 SetAudioMode(kAudioModeInCommunication); |
| 186 #endif |
164 } | 187 } |
165 | 188 |
166 return stream; | 189 return stream; |
167 } | 190 } |
168 | 191 |
169 AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy( | 192 AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy( |
170 const AudioParameters& params) { | 193 const AudioParameters& params) { |
171 #if defined(OS_IOS) | 194 #if defined(OS_IOS) |
172 // IOS implements audio input only. | 195 // IOS implements audio input only. |
173 NOTIMPLEMENTED(); | 196 NOTIMPLEMENTED(); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 media::AudioDeviceNames* device_names) { | 261 media::AudioDeviceNames* device_names) { |
239 } | 262 } |
240 | 263 |
241 void AudioManagerBase::ReleaseOutputStream(AudioOutputStream* stream) { | 264 void AudioManagerBase::ReleaseOutputStream(AudioOutputStream* stream) { |
242 DCHECK(stream); | 265 DCHECK(stream); |
243 // TODO(xians) : Have a clearer destruction path for the AudioOutputStream. | 266 // TODO(xians) : Have a clearer destruction path for the AudioOutputStream. |
244 // For example, pass the ownership to AudioManager so it can delete the | 267 // For example, pass the ownership to AudioManager so it can delete the |
245 // streams. | 268 // streams. |
246 --num_output_streams_; | 269 --num_output_streams_; |
247 delete stream; | 270 delete stream; |
| 271 #if defined(OS_ANDROID) |
| 272 if (!num_output_streams_) |
| 273 UnregisterHeadsetReceiver(); |
| 274 #endif |
248 } | 275 } |
249 | 276 |
250 void AudioManagerBase::ReleaseInputStream(AudioInputStream* stream) { | 277 void AudioManagerBase::ReleaseInputStream(AudioInputStream* stream) { |
251 DCHECK(stream); | 278 DCHECK(stream); |
252 // TODO(xians) : Have a clearer destruction path for the AudioInputStream. | 279 // TODO(xians) : Have a clearer destruction path for the AudioInputStream. |
253 --num_input_streams_; | 280 --num_input_streams_; |
254 delete stream; | 281 delete stream; |
| 282 #if defined(OS_ANDROID) |
| 283 if (!num_input_streams_) |
| 284 SetAudioMode(kAudioModeNormal); |
| 285 #endif |
255 } | 286 } |
256 | 287 |
257 void AudioManagerBase::IncreaseActiveInputStreamCount() { | 288 void AudioManagerBase::IncreaseActiveInputStreamCount() { |
258 base::AtomicRefCountInc(&num_active_input_streams_); | 289 base::AtomicRefCountInc(&num_active_input_streams_); |
259 } | 290 } |
260 | 291 |
261 void AudioManagerBase::DecreaseActiveInputStreamCount() { | 292 void AudioManagerBase::DecreaseActiveInputStreamCount() { |
262 DCHECK(IsRecordingInProcess()); | 293 DCHECK(IsRecordingInProcess()); |
263 base::AtomicRefCountDec(&num_active_input_streams_); | 294 base::AtomicRefCountDec(&num_active_input_streams_); |
264 } | 295 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
312 // So, better crash now than later. | 343 // So, better crash now than later. |
313 DCHECK(dispatcher->HasOneRef()) << "AudioOutputProxies are still alive"; | 344 DCHECK(dispatcher->HasOneRef()) << "AudioOutputProxies are still alive"; |
314 dispatcher = NULL; | 345 dispatcher = NULL; |
315 } | 346 } |
316 } | 347 } |
317 | 348 |
318 output_dispatchers_.clear(); | 349 output_dispatchers_.clear(); |
319 #endif // defined(OS_IOS) | 350 #endif // defined(OS_IOS) |
320 } | 351 } |
321 | 352 |
| 353 #if defined(OS_ANDROID) |
| 354 // static |
| 355 bool AudioManagerBase::RegisterAudioManager(JNIEnv* env) { |
| 356 return RegisterNativesImpl(env); |
| 357 } |
| 358 #endif |
| 359 |
322 void AudioManagerBase::AddOutputDeviceChangeListener( | 360 void AudioManagerBase::AddOutputDeviceChangeListener( |
323 AudioDeviceListener* listener) { | 361 AudioDeviceListener* listener) { |
324 DCHECK(message_loop_->BelongsToCurrentThread()); | 362 DCHECK(message_loop_->BelongsToCurrentThread()); |
325 output_listeners_.AddObserver(listener); | 363 output_listeners_.AddObserver(listener); |
326 } | 364 } |
327 | 365 |
328 void AudioManagerBase::RemoveOutputDeviceChangeListener( | 366 void AudioManagerBase::RemoveOutputDeviceChangeListener( |
329 AudioDeviceListener* listener) { | 367 AudioDeviceListener* listener) { |
330 DCHECK(message_loop_->BelongsToCurrentThread()); | 368 DCHECK(message_loop_->BelongsToCurrentThread()); |
331 output_listeners_.RemoveObserver(listener); | 369 output_listeners_.RemoveObserver(listener); |
332 } | 370 } |
333 | 371 |
334 void AudioManagerBase::NotifyAllOutputDeviceChangeListeners() { | 372 void AudioManagerBase::NotifyAllOutputDeviceChangeListeners() { |
335 DCHECK(message_loop_->BelongsToCurrentThread()); | 373 DCHECK(message_loop_->BelongsToCurrentThread()); |
336 DVLOG(1) << "Firing OnDeviceChange() notifications."; | 374 DVLOG(1) << "Firing OnDeviceChange() notifications."; |
337 FOR_EACH_OBSERVER(AudioDeviceListener, output_listeners_, OnDeviceChange()); | 375 FOR_EACH_OBSERVER(AudioDeviceListener, output_listeners_, OnDeviceChange()); |
338 } | 376 } |
339 | 377 |
340 AudioParameters AudioManagerBase::GetDefaultOutputStreamParameters() { | 378 AudioParameters AudioManagerBase::GetDefaultOutputStreamParameters() { |
341 return GetPreferredOutputStreamParameters(AudioParameters()); | 379 return GetPreferredOutputStreamParameters(AudioParameters()); |
342 } | 380 } |
343 | 381 |
344 AudioParameters AudioManagerBase::GetInputStreamParameters( | 382 AudioParameters AudioManagerBase::GetInputStreamParameters( |
345 const std::string& device_id) { | 383 const std::string& device_id) { |
346 NOTREACHED(); | 384 NOTREACHED(); |
347 return AudioParameters(); | 385 return AudioParameters(); |
348 } | 386 } |
349 | 387 |
| 388 #if defined(OS_ANDROID) |
| 389 void AudioManagerBase::SetAudioMode(int mode) { |
| 390 Java_AudioManagerAndroid_setMode( |
| 391 base::android::AttachCurrentThread(), |
| 392 j_audio_manager_.obj(), mode); |
| 393 } |
| 394 |
| 395 void AudioManagerBase::RegisterHeadsetReceiver() { |
| 396 Java_AudioManagerAndroid_registerHeadsetReceiver( |
| 397 base::android::AttachCurrentThread(), |
| 398 j_audio_manager_.obj()); |
| 399 } |
| 400 |
| 401 void AudioManagerBase::UnregisterHeadsetReceiver() { |
| 402 Java_AudioManagerAndroid_unregisterHeadsetReceiver( |
| 403 base::android::AttachCurrentThread(), |
| 404 j_audio_manager_.obj()); |
| 405 } |
| 406 #endif // defined(OS_ANDROID) |
| 407 |
350 } // namespace media | 408 } // namespace media |
OLD | NEW |