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