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/android/audio_manager_android.h" | 5 #include "media/audio/android/audio_manager_android.h" |
6 | 6 |
7 #include "base/android/build_info.h" | 7 #include "base/android/build_info.h" |
8 #include "base/android/jni_array.h" | 8 #include "base/android/jni_array.h" |
9 #include "base/android/jni_string.h" | 9 #include "base/android/jni_string.h" |
10 #include "base/android/scoped_java_ref.h" | 10 #include "base/android/scoped_java_ref.h" |
(...skipping 19 matching lines...) Expand all Loading... |
30 static void AddDefaultDevice(AudioDeviceNames* device_names) { | 30 static void AddDefaultDevice(AudioDeviceNames* device_names) { |
31 DCHECK(device_names->empty()); | 31 DCHECK(device_names->empty()); |
32 device_names->push_front( | 32 device_names->push_front( |
33 AudioDeviceName(AudioManagerBase::kDefaultDeviceName, | 33 AudioDeviceName(AudioManagerBase::kDefaultDeviceName, |
34 AudioManagerBase::kDefaultDeviceId)); | 34 AudioManagerBase::kDefaultDeviceId)); |
35 } | 35 } |
36 | 36 |
37 // Maximum number of output streams that can be open simultaneously. | 37 // Maximum number of output streams that can be open simultaneously. |
38 static const int kMaxOutputStreams = 10; | 38 static const int kMaxOutputStreams = 10; |
39 | 39 |
40 static const int kAudioModeNormal = 0x00000000; | |
41 static const int kAudioModeInCommunication = 0x00000003; | |
42 | |
43 static const int kDefaultInputBufferSize = 1024; | 40 static const int kDefaultInputBufferSize = 1024; |
44 static const int kDefaultOutputBufferSize = 2048; | 41 static const int kDefaultOutputBufferSize = 2048; |
45 | 42 |
46 AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) { | 43 AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) { |
47 return new AudioManagerAndroid(audio_log_factory); | 44 return new AudioManagerAndroid(audio_log_factory); |
48 } | 45 } |
49 | 46 |
50 AudioManagerAndroid::AudioManagerAndroid(AudioLogFactory* audio_log_factory) | 47 AudioManagerAndroid::AudioManagerAndroid(AudioLogFactory* audio_log_factory) |
51 : AudioManagerBase(audio_log_factory) { | 48 : AudioManagerBase(audio_log_factory) { |
52 SetMaxOutputStreamsAllowed(kMaxOutputStreams); | 49 SetMaxOutputStreamsAllowed(kMaxOutputStreams); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, 0, | 116 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, 0, |
120 GetNativeOutputSampleRate(), 16, | 117 GetNativeOutputSampleRate(), 16, |
121 buffer_size <= 0 ? kDefaultInputBufferSize : buffer_size, effects); | 118 buffer_size <= 0 ? kDefaultInputBufferSize : buffer_size, effects); |
122 return params; | 119 return params; |
123 } | 120 } |
124 | 121 |
125 AudioOutputStream* AudioManagerAndroid::MakeAudioOutputStream( | 122 AudioOutputStream* AudioManagerAndroid::MakeAudioOutputStream( |
126 const AudioParameters& params, | 123 const AudioParameters& params, |
127 const std::string& device_id, | 124 const std::string& device_id, |
128 const std::string& input_device_id) { | 125 const std::string& input_device_id) { |
| 126 bool had_no_streams = HadNoAudioStreams(); |
129 AudioOutputStream* stream = | 127 AudioOutputStream* stream = |
130 AudioManagerBase::MakeAudioOutputStream(params, std::string(), | 128 AudioManagerBase::MakeAudioOutputStream(params, std::string(), |
131 std::string()); | 129 std::string()); |
132 if (stream && output_stream_count() == 1) { | 130 |
133 SetAudioMode(kAudioModeInCommunication); | 131 // The audio manager for Android creates streams intended for real-time |
134 } | 132 // VoIP sessions and therefore sets the audio mode to MODE_IN_COMMUNICATION. |
| 133 // If a Bluetooth headset is used, the audio stream will use the SCO |
| 134 // channel and therefore have a limited bandwidth (8-16kHz). |
| 135 if (stream && had_no_streams) |
| 136 SetCommunicationAudioModeOn(true); |
135 | 137 |
136 { | 138 { |
137 base::AutoLock lock(streams_lock_); | 139 base::AutoLock lock(streams_lock_); |
138 streams_.insert(static_cast<OpenSLESOutputStream*>(stream)); | 140 streams_.insert(static_cast<OpenSLESOutputStream*>(stream)); |
139 } | 141 } |
140 | 142 |
141 return stream; | 143 return stream; |
142 } | 144 } |
143 | 145 |
144 AudioInputStream* AudioManagerAndroid::MakeAudioInputStream( | 146 AudioInputStream* AudioManagerAndroid::MakeAudioInputStream( |
145 const AudioParameters& params, const std::string& device_id) { | 147 const AudioParameters& params, const std::string& device_id) { |
| 148 bool had_no_streams = HadNoAudioStreams(); |
146 AudioInputStream* stream = | 149 AudioInputStream* stream = |
147 AudioManagerBase::MakeAudioInputStream(params, device_id); | 150 AudioManagerBase::MakeAudioInputStream(params, device_id); |
| 151 |
| 152 // The audio manager for Android creates streams intended for real-time |
| 153 // VoIP sessions and therefore sets the audio mode to MODE_IN_COMMUNICATION. |
| 154 // If a Bluetooth headset is used, the audio stream will use the SCO |
| 155 // channel and therefore have a limited bandwidth (8kHz). |
| 156 if (stream && had_no_streams) |
| 157 SetCommunicationAudioModeOn(true); |
148 return stream; | 158 return stream; |
149 } | 159 } |
150 | 160 |
151 void AudioManagerAndroid::ReleaseOutputStream(AudioOutputStream* stream) { | 161 void AudioManagerAndroid::ReleaseOutputStream(AudioOutputStream* stream) { |
152 AudioManagerBase::ReleaseOutputStream(stream); | 162 AudioManagerBase::ReleaseOutputStream(stream); |
153 if (!output_stream_count()) { | 163 |
154 SetAudioMode(kAudioModeNormal); | 164 // Restore the audio mode which was used before the first communication- |
155 } | 165 // mode stream was created. |
| 166 if (HadNoAudioStreams()) |
| 167 SetCommunicationAudioModeOn(false); |
156 base::AutoLock lock(streams_lock_); | 168 base::AutoLock lock(streams_lock_); |
157 streams_.erase(static_cast<OpenSLESOutputStream*>(stream)); | 169 streams_.erase(static_cast<OpenSLESOutputStream*>(stream)); |
158 } | 170 } |
159 | 171 |
160 void AudioManagerAndroid::ReleaseInputStream(AudioInputStream* stream) { | 172 void AudioManagerAndroid::ReleaseInputStream(AudioInputStream* stream) { |
161 AudioManagerBase::ReleaseInputStream(stream); | 173 AudioManagerBase::ReleaseInputStream(stream); |
| 174 |
| 175 // Restore the audio mode which was used before the first communication- |
| 176 // mode stream was created. |
| 177 if (HadNoAudioStreams()) |
| 178 SetCommunicationAudioModeOn(false); |
162 } | 179 } |
163 | 180 |
164 AudioOutputStream* AudioManagerAndroid::MakeLinearOutputStream( | 181 AudioOutputStream* AudioManagerAndroid::MakeLinearOutputStream( |
165 const AudioParameters& params) { | 182 const AudioParameters& params) { |
166 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format()); | 183 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format()); |
167 return new OpenSLESOutputStream(this, params); | 184 return new OpenSLESOutputStream(this, params); |
168 } | 185 } |
169 | 186 |
170 AudioOutputStream* AudioManagerAndroid::MakeLowLatencyOutputStream( | 187 AudioOutputStream* AudioManagerAndroid::MakeLowLatencyOutputStream( |
171 const AudioParameters& params, | 188 const AudioParameters& params, |
(...skipping 10 matching lines...) Expand all Loading... |
182 // needs it. | 199 // needs it. |
183 DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!"; | 200 DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!"; |
184 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format()); | 201 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format()); |
185 return new OpenSLESInputStream(this, params); | 202 return new OpenSLESInputStream(this, params); |
186 } | 203 } |
187 | 204 |
188 AudioInputStream* AudioManagerAndroid::MakeLowLatencyInputStream( | 205 AudioInputStream* AudioManagerAndroid::MakeLowLatencyInputStream( |
189 const AudioParameters& params, const std::string& device_id) { | 206 const AudioParameters& params, const std::string& device_id) { |
190 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format()); | 207 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format()); |
191 DLOG_IF(ERROR, device_id.empty()) << "Invalid device ID!"; | 208 DLOG_IF(ERROR, device_id.empty()) << "Invalid device ID!"; |
192 // Utilize the device ID to select the correct input device. | 209 // Use the device ID to select the correct input device. |
193 // Note that the input device is always associated with a certain output | 210 // Note that the input device is always associated with a certain output |
194 // device, i.e., this selection does also switch the output device. | 211 // device, i.e., this selection does also switch the output device. |
195 // All input and output streams will be affected by the device selection. | 212 // All input and output streams will be affected by the device selection. |
196 SetAudioDevice(device_id); | 213 if (!SetAudioDevice(device_id)) { |
| 214 LOG(ERROR) << "Unable to select audio device!"; |
| 215 return NULL; |
| 216 } |
197 | 217 |
198 if (params.effects() != AudioParameters::NO_EFFECTS) { | 218 if (params.effects() != AudioParameters::NO_EFFECTS) { |
199 // Platform effects can only be enabled through the AudioRecord path. | 219 // Platform effects can only be enabled through the AudioRecord path. |
200 // An effect should only have been requested here if recommended by | 220 // An effect should only have been requested here if recommended by |
201 // AudioManagerAndroid.shouldUse<Effect>. | 221 // AudioManagerAndroid.shouldUse<Effect>. |
202 // | 222 // |
203 // Creating this class requires Jelly Bean, which is already guaranteed by | 223 // Creating this class requires Jelly Bean, which is already guaranteed by |
204 // shouldUse<Effect>. Only DCHECK on that condition to allow tests to use | 224 // shouldUse<Effect>. Only DCHECK on that condition to allow tests to use |
205 // the effect settings as a way to select the input path. | 225 // the effect settings as a way to select the input path. |
206 DCHECK_GE(base::android::BuildInfo::GetInstance()->sdk_int(), 16); | 226 DCHECK_GE(base::android::BuildInfo::GetInstance()->sdk_int(), 16); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 | 265 |
246 int user_buffer_size = GetUserBufferSize(); | 266 int user_buffer_size = GetUserBufferSize(); |
247 if (user_buffer_size) | 267 if (user_buffer_size) |
248 buffer_size = user_buffer_size; | 268 buffer_size = user_buffer_size; |
249 | 269 |
250 return AudioParameters( | 270 return AudioParameters( |
251 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, input_channels, | 271 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, input_channels, |
252 sample_rate, bits_per_sample, buffer_size, AudioParameters::NO_EFFECTS); | 272 sample_rate, bits_per_sample, buffer_size, AudioParameters::NO_EFFECTS); |
253 } | 273 } |
254 | 274 |
| 275 bool AudioManagerAndroid::HadNoAudioStreams() { |
| 276 return output_stream_count() == 0 && input_stream_count() == 0; |
| 277 } |
| 278 |
255 // static | 279 // static |
256 bool AudioManagerAndroid::RegisterAudioManager(JNIEnv* env) { | 280 bool AudioManagerAndroid::RegisterAudioManager(JNIEnv* env) { |
257 return RegisterNativesImpl(env); | 281 return RegisterNativesImpl(env); |
258 } | 282 } |
259 | 283 |
260 void AudioManagerAndroid::Init() { | 284 void AudioManagerAndroid::Init() { |
261 Java_AudioManagerAndroid_init( | 285 Java_AudioManagerAndroid_init( |
262 base::android::AttachCurrentThread(), | 286 base::android::AttachCurrentThread(), |
263 j_audio_manager_.obj()); | 287 j_audio_manager_.obj()); |
264 } | 288 } |
(...skipping 14 matching lines...) Expand all Loading... |
279 } | 303 } |
280 | 304 |
281 void AudioManagerAndroid::DoSetMuteOnAudioThread(bool muted) { | 305 void AudioManagerAndroid::DoSetMuteOnAudioThread(bool muted) { |
282 base::AutoLock lock(streams_lock_); | 306 base::AutoLock lock(streams_lock_); |
283 for (OutputStreams::iterator it = streams_.begin(); | 307 for (OutputStreams::iterator it = streams_.begin(); |
284 it != streams_.end(); ++it) { | 308 it != streams_.end(); ++it) { |
285 (*it)->SetMute(muted); | 309 (*it)->SetMute(muted); |
286 } | 310 } |
287 } | 311 } |
288 | 312 |
289 void AudioManagerAndroid::SetAudioMode(int mode) { | 313 void AudioManagerAndroid::SetCommunicationAudioModeOn(bool on) { |
290 Java_AudioManagerAndroid_setMode( | 314 Java_AudioManagerAndroid_setCommunicationAudioModeOn( |
291 base::android::AttachCurrentThread(), | 315 base::android::AttachCurrentThread(), |
292 j_audio_manager_.obj(), mode); | 316 j_audio_manager_.obj(), on); |
293 } | 317 } |
294 | 318 |
295 void AudioManagerAndroid::SetAudioDevice(const std::string& device_id) { | 319 bool AudioManagerAndroid::SetAudioDevice(const std::string& device_id) { |
296 JNIEnv* env = AttachCurrentThread(); | 320 JNIEnv* env = AttachCurrentThread(); |
297 | 321 |
298 // Send the unique device ID to the Java audio manager and make the | 322 // Send the unique device ID to the Java audio manager and make the |
299 // device switch. Provide an empty string to the Java audio manager | 323 // device switch. Provide an empty string to the Java audio manager |
300 // if the default device is selected. | 324 // if the default device is selected. |
301 ScopedJavaLocalRef<jstring> j_device_id = ConvertUTF8ToJavaString( | 325 ScopedJavaLocalRef<jstring> j_device_id = ConvertUTF8ToJavaString( |
302 env, | 326 env, |
303 device_id == AudioManagerBase::kDefaultDeviceId ? | 327 device_id == AudioManagerBase::kDefaultDeviceId ? |
304 std::string() : device_id); | 328 std::string() : device_id); |
305 Java_AudioManagerAndroid_setDevice( | 329 return Java_AudioManagerAndroid_setDevice( |
306 env, j_audio_manager_.obj(), j_device_id.obj()); | 330 env, j_audio_manager_.obj(), j_device_id.obj()); |
307 } | 331 } |
308 | 332 |
309 int AudioManagerAndroid::GetNativeOutputSampleRate() { | 333 int AudioManagerAndroid::GetNativeOutputSampleRate() { |
310 return Java_AudioManagerAndroid_getNativeOutputSampleRate( | 334 return Java_AudioManagerAndroid_getNativeOutputSampleRate( |
311 base::android::AttachCurrentThread(), | 335 base::android::AttachCurrentThread(), |
312 j_audio_manager_.obj()); | 336 j_audio_manager_.obj()); |
313 } | 337 } |
314 | 338 |
315 bool AudioManagerAndroid::IsAudioLowLatencySupported() { | 339 bool AudioManagerAndroid::IsAudioLowLatencySupported() { |
316 return Java_AudioManagerAndroid_isAudioLowLatencySupported( | 340 return Java_AudioManagerAndroid_isAudioLowLatencySupported( |
317 base::android::AttachCurrentThread(), | 341 base::android::AttachCurrentThread(), |
318 j_audio_manager_.obj()); | 342 j_audio_manager_.obj()); |
319 } | 343 } |
320 | 344 |
321 int AudioManagerAndroid::GetAudioLowLatencyOutputFrameSize() { | 345 int AudioManagerAndroid::GetAudioLowLatencyOutputFrameSize() { |
322 return Java_AudioManagerAndroid_getAudioLowLatencyOutputFrameSize( | 346 return Java_AudioManagerAndroid_getAudioLowLatencyOutputFrameSize( |
323 base::android::AttachCurrentThread(), | 347 base::android::AttachCurrentThread(), |
324 j_audio_manager_.obj()); | 348 j_audio_manager_.obj()); |
325 } | 349 } |
326 | 350 |
327 } // namespace media | 351 } // namespace media |
OLD | NEW |