Chromium Code Reviews| 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 has_no_streams = HasNoAudioStreams(); | |
| 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 |
| 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 && has_no_streams) { | |
|
tommi (sloooow) - chröme
2013/12/13 11:30:13
nit: no {}
henrika (OOO until Aug 14)
2013/12/13 14:15:27
Done.
| |
| 131 SetCommunicationAudioModeOn(true); | |
| 129 } | 132 } |
| 130 | 133 |
| 131 { | 134 { |
| 132 base::AutoLock lock(streams_lock_); | 135 base::AutoLock lock(streams_lock_); |
| 133 streams_.insert(static_cast<OpenSLESOutputStream*>(stream)); | 136 streams_.insert(static_cast<OpenSLESOutputStream*>(stream)); |
| 134 } | 137 } |
| 135 | 138 |
| 136 return stream; | 139 return stream; |
| 137 } | 140 } |
| 138 | 141 |
| 139 AudioInputStream* AudioManagerAndroid::MakeAudioInputStream( | 142 AudioInputStream* AudioManagerAndroid::MakeAudioInputStream( |
| 140 const AudioParameters& params, const std::string& device_id) { | 143 const AudioParameters& params, const std::string& device_id) { |
| 144 bool has_no_streams = HasNoAudioStreams(); | |
| 141 AudioInputStream* stream = | 145 AudioInputStream* stream = |
| 142 AudioManagerBase::MakeAudioInputStream(params, device_id); | 146 AudioManagerBase::MakeAudioInputStream(params, device_id); |
| 147 | |
| 148 // The audio manager for Android creates streams intended for real-time | |
| 149 // VoIP sessions and therefore sets the audio mode to MODE_IN_COMMUNICATION. | |
| 150 // If a Bluetooth headset is used, the audio stream will use the SCO | |
| 151 // channel and therefore have a limited bandwidth (8kHz). | |
| 152 if (stream && has_no_streams) { | |
|
tommi (sloooow) - chröme
2013/12/13 11:30:13
nit: no {}
henrika (OOO until Aug 14)
2013/12/13 14:15:27
Done.
| |
| 153 SetCommunicationAudioModeOn(true); | |
| 154 } | |
| 143 return stream; | 155 return stream; |
| 144 } | 156 } |
| 145 | 157 |
| 146 void AudioManagerAndroid::ReleaseOutputStream(AudioOutputStream* stream) { | 158 void AudioManagerAndroid::ReleaseOutputStream(AudioOutputStream* stream) { |
| 147 AudioManagerBase::ReleaseOutputStream(stream); | 159 AudioManagerBase::ReleaseOutputStream(stream); |
| 148 if (!output_stream_count()) { | 160 |
| 149 SetAudioMode(kAudioModeNormal); | 161 // Restore the audio mode which was used before the first communication- |
| 162 // mode stream was created. | |
| 163 if (HasNoAudioStreams()) { | |
|
tommi (sloooow) - chröme
2013/12/13 11:30:13
nit: no {}
henrika (OOO until Aug 14)
2013/12/13 14:15:27
Done.
| |
| 164 SetCommunicationAudioModeOn(false); | |
| 150 } | 165 } |
| 151 base::AutoLock lock(streams_lock_); | 166 base::AutoLock lock(streams_lock_); |
| 152 streams_.erase(static_cast<OpenSLESOutputStream*>(stream)); | 167 streams_.erase(static_cast<OpenSLESOutputStream*>(stream)); |
| 153 } | 168 } |
| 154 | 169 |
| 155 void AudioManagerAndroid::ReleaseInputStream(AudioInputStream* stream) { | 170 void AudioManagerAndroid::ReleaseInputStream(AudioInputStream* stream) { |
| 156 AudioManagerBase::ReleaseInputStream(stream); | 171 AudioManagerBase::ReleaseInputStream(stream); |
| 172 | |
| 173 // Restore the audio mode which was used before the first communication- | |
| 174 // mode stream was created. | |
| 175 if (HasNoAudioStreams()) { | |
|
tommi (sloooow) - chröme
2013/12/13 11:30:13
nit: no {}
henrika (OOO until Aug 14)
2013/12/13 14:15:27
Done.
| |
| 176 SetCommunicationAudioModeOn(false); | |
| 177 } | |
| 157 } | 178 } |
| 158 | 179 |
| 159 AudioOutputStream* AudioManagerAndroid::MakeLinearOutputStream( | 180 AudioOutputStream* AudioManagerAndroid::MakeLinearOutputStream( |
| 160 const AudioParameters& params) { | 181 const AudioParameters& params) { |
| 161 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format()); | 182 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format()); |
| 162 return new OpenSLESOutputStream(this, params); | 183 return new OpenSLESOutputStream(this, params); |
| 163 } | 184 } |
| 164 | 185 |
| 165 AudioOutputStream* AudioManagerAndroid::MakeLowLatencyOutputStream( | 186 AudioOutputStream* AudioManagerAndroid::MakeLowLatencyOutputStream( |
| 166 const AudioParameters& params, | 187 const AudioParameters& params, |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 177 // needs it. | 198 // needs it. |
| 178 DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!"; | 199 DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!"; |
| 179 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format()); | 200 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format()); |
| 180 return new OpenSLESInputStream(this, params); | 201 return new OpenSLESInputStream(this, params); |
| 181 } | 202 } |
| 182 | 203 |
| 183 AudioInputStream* AudioManagerAndroid::MakeLowLatencyInputStream( | 204 AudioInputStream* AudioManagerAndroid::MakeLowLatencyInputStream( |
| 184 const AudioParameters& params, const std::string& device_id) { | 205 const AudioParameters& params, const std::string& device_id) { |
| 185 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format()); | 206 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format()); |
| 186 DLOG_IF(ERROR, device_id.empty()) << "Invalid device ID!"; | 207 DLOG_IF(ERROR, device_id.empty()) << "Invalid device ID!"; |
| 187 // Utilize the device ID to select the correct input device. | 208 // Use the device ID to select the correct input device. |
| 188 // Note that the input device is always associated with a certain output | 209 // Note that the input device is always associated with a certain output |
| 189 // device, i.e., this selection does also switch the output device. | 210 // device, i.e., this selection does also switch the output device. |
| 190 // All input and output streams will be affected by the device selection. | 211 // All input and output streams will be affected by the device selection. |
| 191 SetAudioDevice(device_id); | 212 if (!SetAudioDevice(device_id)) { |
| 213 LOG(ERROR) << "Unable to select audio device!"; | |
| 214 return NULL; | |
| 215 } | |
| 192 return new OpenSLESInputStream(this, params); | 216 return new OpenSLESInputStream(this, params); |
| 193 } | 217 } |
| 194 | 218 |
| 195 int AudioManagerAndroid::GetOptimalOutputFrameSize(int sample_rate, | 219 int AudioManagerAndroid::GetOptimalOutputFrameSize(int sample_rate, |
| 196 int channels) { | 220 int channels) { |
| 197 if (IsAudioLowLatencySupported()) { | 221 if (IsAudioLowLatencySupported()) { |
| 198 return GetAudioLowLatencyOutputFrameSize(); | 222 return GetAudioLowLatencyOutputFrameSize(); |
| 199 } else { | 223 } else { |
| 200 return std::max(kDefaultOutputBufferSize, | 224 return std::max(kDefaultOutputBufferSize, |
| 201 Java_AudioManagerAndroid_getMinOutputFrameSize( | 225 Java_AudioManagerAndroid_getMinOutputFrameSize( |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 226 | 250 |
| 227 int user_buffer_size = GetUserBufferSize(); | 251 int user_buffer_size = GetUserBufferSize(); |
| 228 if (user_buffer_size) | 252 if (user_buffer_size) |
| 229 buffer_size = user_buffer_size; | 253 buffer_size = user_buffer_size; |
| 230 | 254 |
| 231 return AudioParameters( | 255 return AudioParameters( |
| 232 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, input_channels, | 256 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, input_channels, |
| 233 sample_rate, bits_per_sample, buffer_size); | 257 sample_rate, bits_per_sample, buffer_size); |
| 234 } | 258 } |
| 235 | 259 |
| 260 bool AudioManagerAndroid::HasNoAudioStreams() { | |
| 261 return output_stream_count() == 0 && input_stream_count() == 0; | |
| 262 } | |
| 263 | |
| 236 // static | 264 // static |
| 237 bool AudioManagerAndroid::RegisterAudioManager(JNIEnv* env) { | 265 bool AudioManagerAndroid::RegisterAudioManager(JNIEnv* env) { |
| 238 return RegisterNativesImpl(env); | 266 return RegisterNativesImpl(env); |
| 239 } | 267 } |
| 240 | 268 |
| 241 void AudioManagerAndroid::Init() { | 269 void AudioManagerAndroid::Init() { |
| 242 Java_AudioManagerAndroid_init( | 270 Java_AudioManagerAndroid_init( |
| 243 base::android::AttachCurrentThread(), | 271 base::android::AttachCurrentThread(), |
| 244 j_audio_manager_.obj()); | 272 j_audio_manager_.obj()); |
| 245 } | 273 } |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 260 } | 288 } |
| 261 | 289 |
| 262 void AudioManagerAndroid::DoSetMuteOnAudioThread(bool muted) { | 290 void AudioManagerAndroid::DoSetMuteOnAudioThread(bool muted) { |
| 263 base::AutoLock lock(streams_lock_); | 291 base::AutoLock lock(streams_lock_); |
| 264 for (OutputStreams::iterator it = streams_.begin(); | 292 for (OutputStreams::iterator it = streams_.begin(); |
| 265 it != streams_.end(); ++it) { | 293 it != streams_.end(); ++it) { |
| 266 (*it)->SetMute(muted); | 294 (*it)->SetMute(muted); |
| 267 } | 295 } |
| 268 } | 296 } |
| 269 | 297 |
| 270 void AudioManagerAndroid::SetAudioMode(int mode) { | 298 void AudioManagerAndroid::SetCommunicationAudioModeOn(bool on) { |
| 271 Java_AudioManagerAndroid_setMode( | 299 Java_AudioManagerAndroid_setCommunicationAudioModeOn( |
| 272 base::android::AttachCurrentThread(), | 300 base::android::AttachCurrentThread(), |
| 273 j_audio_manager_.obj(), mode); | 301 j_audio_manager_.obj(), on); |
| 274 } | 302 } |
| 275 | 303 |
| 276 void AudioManagerAndroid::SetAudioDevice(const std::string& device_id) { | 304 bool AudioManagerAndroid::SetAudioDevice(const std::string& device_id) { |
| 277 JNIEnv* env = AttachCurrentThread(); | 305 JNIEnv* env = AttachCurrentThread(); |
| 278 | 306 |
| 279 // Send the unique device ID to the Java audio manager and make the | 307 // 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 | 308 // device switch. Provide an empty string to the Java audio manager |
| 281 // if the default device is selected. | 309 // if the default device is selected. |
| 282 ScopedJavaLocalRef<jstring> j_device_id = ConvertUTF8ToJavaString( | 310 ScopedJavaLocalRef<jstring> j_device_id = ConvertUTF8ToJavaString( |
| 283 env, | 311 env, |
| 284 device_id == AudioManagerBase::kDefaultDeviceId ? | 312 device_id == AudioManagerBase::kDefaultDeviceId ? |
| 285 std::string() : device_id); | 313 std::string() : device_id); |
| 286 Java_AudioManagerAndroid_setDevice( | 314 return Java_AudioManagerAndroid_setDevice( |
| 287 env, j_audio_manager_.obj(), j_device_id.obj()); | 315 env, j_audio_manager_.obj(), j_device_id.obj()); |
| 288 } | 316 } |
| 289 | 317 |
| 290 int AudioManagerAndroid::GetNativeOutputSampleRate() { | 318 int AudioManagerAndroid::GetNativeOutputSampleRate() { |
| 291 return Java_AudioManagerAndroid_getNativeOutputSampleRate( | 319 return Java_AudioManagerAndroid_getNativeOutputSampleRate( |
| 292 base::android::AttachCurrentThread(), | 320 base::android::AttachCurrentThread(), |
| 293 j_audio_manager_.obj()); | 321 j_audio_manager_.obj()); |
| 294 } | 322 } |
| 295 | 323 |
| 296 bool AudioManagerAndroid::IsAudioLowLatencySupported() { | 324 bool AudioManagerAndroid::IsAudioLowLatencySupported() { |
| 297 return Java_AudioManagerAndroid_isAudioLowLatencySupported( | 325 return Java_AudioManagerAndroid_isAudioLowLatencySupported( |
| 298 base::android::AttachCurrentThread(), | 326 base::android::AttachCurrentThread(), |
| 299 j_audio_manager_.obj()); | 327 j_audio_manager_.obj()); |
| 300 } | 328 } |
| 301 | 329 |
| 302 int AudioManagerAndroid::GetAudioLowLatencyOutputFrameSize() { | 330 int AudioManagerAndroid::GetAudioLowLatencyOutputFrameSize() { |
| 303 return Java_AudioManagerAndroid_getAudioLowLatencyOutputFrameSize( | 331 return Java_AudioManagerAndroid_getAudioLowLatencyOutputFrameSize( |
| 304 base::android::AttachCurrentThread(), | 332 base::android::AttachCurrentThread(), |
| 305 j_audio_manager_.obj()); | 333 j_audio_manager_.obj()); |
| 306 } | 334 } |
| 307 | 335 |
| 308 } // namespace media | 336 } // namespace media |
| OLD | NEW |