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