| 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" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/message_loop/message_loop.h" |
| 12 #include "base/strings/string_number_conversions.h" | 13 #include "base/strings/string_number_conversions.h" |
| 13 #include "jni/AudioManagerAndroid_jni.h" | 14 #include "jni/AudioManagerAndroid_jni.h" |
| 14 #include "media/audio/android/audio_record_input.h" | 15 #include "media/audio/android/audio_record_input.h" |
| 15 #include "media/audio/android/opensles_input.h" | 16 #include "media/audio/android/opensles_input.h" |
| 16 #include "media/audio/android/opensles_output.h" | 17 #include "media/audio/android/opensles_output.h" |
| 17 #include "media/audio/audio_manager.h" | 18 #include "media/audio/audio_manager.h" |
| 18 #include "media/audio/audio_parameters.h" | 19 #include "media/audio/audio_parameters.h" |
| 19 #include "media/audio/fake_audio_input_stream.h" | 20 #include "media/audio/fake_audio_input_stream.h" |
| 20 #include "media/base/channel_layout.h" | 21 #include "media/base/channel_layout.h" |
| 21 | 22 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 42 | 43 |
| 43 AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) { | 44 AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) { |
| 44 return new AudioManagerAndroid(audio_log_factory); | 45 return new AudioManagerAndroid(audio_log_factory); |
| 45 } | 46 } |
| 46 | 47 |
| 47 AudioManagerAndroid::AudioManagerAndroid(AudioLogFactory* audio_log_factory) | 48 AudioManagerAndroid::AudioManagerAndroid(AudioLogFactory* audio_log_factory) |
| 48 : AudioManagerBase(audio_log_factory), | 49 : AudioManagerBase(audio_log_factory), |
| 49 communication_mode_is_on_(false) { | 50 communication_mode_is_on_(false) { |
| 50 SetMaxOutputStreamsAllowed(kMaxOutputStreams); | 51 SetMaxOutputStreamsAllowed(kMaxOutputStreams); |
| 51 | 52 |
| 52 j_audio_manager_.Reset( | 53 // WARNING: This is executed on the UI loop, do not add any code here which |
| 53 Java_AudioManagerAndroid_createAudioManagerAndroid( | 54 // loads libraries or attempts to call out into the OS. Instead add such code |
| 54 base::android::AttachCurrentThread(), | 55 // to the InitializeOnAudioThread() method below. |
| 55 base::android::GetApplicationContext(), | 56 |
| 56 reinterpret_cast<intptr_t>(this))); | 57 // Task must be posted last to avoid races from handing out "this" to the |
| 57 Init(); | 58 // audio thread. |
| 59 GetTaskRunner()->PostTask(FROM_HERE, base::Bind( |
| 60 &AudioManagerAndroid::InitializeOnAudioThread, |
| 61 base::Unretained(this))); |
| 58 } | 62 } |
| 59 | 63 |
| 60 AudioManagerAndroid::~AudioManagerAndroid() { | 64 AudioManagerAndroid::~AudioManagerAndroid() { |
| 61 Close(); | 65 // It's safe to post a task here since Shutdown() will wait for all tasks to |
| 66 // complete before returning. |
| 67 GetTaskRunner()->PostTask(FROM_HERE, base::Bind( |
| 68 &AudioManagerAndroid::ShutdownOnAudioThread, base::Unretained(this))); |
| 62 Shutdown(); | 69 Shutdown(); |
| 63 } | 70 } |
| 64 | 71 |
| 65 bool AudioManagerAndroid::HasAudioOutputDevices() { | 72 bool AudioManagerAndroid::HasAudioOutputDevices() { |
| 66 return true; | 73 return true; |
| 67 } | 74 } |
| 68 | 75 |
| 69 bool AudioManagerAndroid::HasAudioInputDevices() { | 76 bool AudioManagerAndroid::HasAudioInputDevices() { |
| 70 return true; | 77 return true; |
| 71 } | 78 } |
| 72 | 79 |
| 73 void AudioManagerAndroid::GetAudioInputDeviceNames( | 80 void AudioManagerAndroid::GetAudioInputDeviceNames( |
| 74 AudioDeviceNames* device_names) { | 81 AudioDeviceNames* device_names) { |
| 82 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
| 83 |
| 75 // Always add default device parameters as first element. | 84 // Always add default device parameters as first element. |
| 76 DCHECK(device_names->empty()); | 85 DCHECK(device_names->empty()); |
| 77 AddDefaultDevice(device_names); | 86 AddDefaultDevice(device_names); |
| 78 | 87 |
| 88 // Get list of available audio devices. |
| 79 JNIEnv* env = AttachCurrentThread(); | 89 JNIEnv* env = AttachCurrentThread(); |
| 80 ScopedJavaLocalRef<jobjectArray> j_device_array = | 90 ScopedJavaLocalRef<jobjectArray> j_device_array = |
| 81 Java_AudioManagerAndroid_getAudioInputDeviceNames( | 91 Java_AudioManagerAndroid_getAudioInputDeviceNames( |
| 82 env, j_audio_manager_.obj()); | 92 env, j_audio_manager_.obj()); |
| 83 jsize len = env->GetArrayLength(j_device_array.obj()); | 93 jsize len = env->GetArrayLength(j_device_array.obj()); |
| 84 AudioDeviceName device; | 94 AudioDeviceName device; |
| 85 for (jsize i = 0; i < len; ++i) { | 95 for (jsize i = 0; i < len; ++i) { |
| 86 ScopedJavaLocalRef<jobject> j_device( | 96 ScopedJavaLocalRef<jobject> j_device( |
| 87 env, env->GetObjectArrayElement(j_device_array.obj(), i)); | 97 env, env->GetObjectArrayElement(j_device_array.obj(), i)); |
| 88 ScopedJavaLocalRef<jstring> j_device_name = | 98 ScopedJavaLocalRef<jstring> j_device_name = |
| 89 Java_AudioDeviceName_name(env, j_device.obj()); | 99 Java_AudioDeviceName_name(env, j_device.obj()); |
| 90 ConvertJavaStringToUTF8(env, j_device_name.obj(), &device.device_name); | 100 ConvertJavaStringToUTF8(env, j_device_name.obj(), &device.device_name); |
| 91 ScopedJavaLocalRef<jstring> j_device_id = | 101 ScopedJavaLocalRef<jstring> j_device_id = |
| 92 Java_AudioDeviceName_id(env, j_device.obj()); | 102 Java_AudioDeviceName_id(env, j_device.obj()); |
| 93 ConvertJavaStringToUTF8(env, j_device_id.obj(), &device.unique_id); | 103 ConvertJavaStringToUTF8(env, j_device_id.obj(), &device.unique_id); |
| 94 device_names->push_back(device); | 104 device_names->push_back(device); |
| 95 } | 105 } |
| 96 } | 106 } |
| 97 | 107 |
| 98 void AudioManagerAndroid::GetAudioOutputDeviceNames( | 108 void AudioManagerAndroid::GetAudioOutputDeviceNames( |
| 99 AudioDeviceNames* device_names) { | 109 AudioDeviceNames* device_names) { |
| 100 // TODO(henrika): enumerate using GetAudioInputDeviceNames(). | 110 // TODO(henrika): enumerate using GetAudioInputDeviceNames(). |
| 101 AddDefaultDevice(device_names); | 111 AddDefaultDevice(device_names); |
| 102 } | 112 } |
| 103 | 113 |
| 104 AudioParameters AudioManagerAndroid::GetInputStreamParameters( | 114 AudioParameters AudioManagerAndroid::GetInputStreamParameters( |
| 105 const std::string& device_id) { | 115 const std::string& device_id) { |
| 106 JNIEnv* env = AttachCurrentThread(); | 116 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
| 117 |
| 107 // Use mono as preferred number of input channels on Android to save | 118 // Use mono as preferred number of input channels on Android to save |
| 108 // resources. Using mono also avoids a driver issue seen on Samsung | 119 // resources. Using mono also avoids a driver issue seen on Samsung |
| 109 // Galaxy S3 and S4 devices. See http://crbug.com/256851 for details. | 120 // Galaxy S3 and S4 devices. See http://crbug.com/256851 for details. |
| 121 JNIEnv* env = AttachCurrentThread(); |
| 110 ChannelLayout channel_layout = CHANNEL_LAYOUT_MONO; | 122 ChannelLayout channel_layout = CHANNEL_LAYOUT_MONO; |
| 111 int buffer_size = Java_AudioManagerAndroid_getMinInputFrameSize( | 123 int buffer_size = Java_AudioManagerAndroid_getMinInputFrameSize( |
| 112 env, GetNativeOutputSampleRate(), | 124 env, GetNativeOutputSampleRate(), |
| 113 ChannelLayoutToChannelCount(channel_layout)); | 125 ChannelLayoutToChannelCount(channel_layout)); |
| 114 int effects = AudioParameters::NO_EFFECTS; | 126 int effects = AudioParameters::NO_EFFECTS; |
| 115 effects |= Java_AudioManagerAndroid_shouldUseAcousticEchoCanceler(env) ? | 127 effects |= Java_AudioManagerAndroid_shouldUseAcousticEchoCanceler(env) ? |
| 116 AudioParameters::ECHO_CANCELLER : AudioParameters::NO_EFFECTS; | 128 AudioParameters::ECHO_CANCELLER : AudioParameters::NO_EFFECTS; |
| 117 AudioParameters params( | 129 AudioParameters params( |
| 118 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, 0, | 130 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, 0, |
| 119 GetNativeOutputSampleRate(), 16, | 131 GetNativeOutputSampleRate(), 16, |
| 120 buffer_size <= 0 ? kDefaultInputBufferSize : buffer_size, effects); | 132 buffer_size <= 0 ? kDefaultInputBufferSize : buffer_size, effects); |
| 121 return params; | 133 return params; |
| 122 } | 134 } |
| 123 | 135 |
| 124 AudioOutputStream* AudioManagerAndroid::MakeAudioOutputStream( | 136 AudioOutputStream* AudioManagerAndroid::MakeAudioOutputStream( |
| 125 const AudioParameters& params, | 137 const AudioParameters& params, |
| 126 const std::string& device_id) { | 138 const std::string& device_id) { |
| 139 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
| 127 AudioOutputStream* stream = | 140 AudioOutputStream* stream = |
| 128 AudioManagerBase::MakeAudioOutputStream(params, std::string()); | 141 AudioManagerBase::MakeAudioOutputStream(params, std::string()); |
| 129 { | 142 streams_.insert(static_cast<OpenSLESOutputStream*>(stream)); |
| 130 base::AutoLock lock(streams_lock_); | |
| 131 streams_.insert(static_cast<OpenSLESOutputStream*>(stream)); | |
| 132 } | |
| 133 | |
| 134 return stream; | 143 return stream; |
| 135 } | 144 } |
| 136 | 145 |
| 137 AudioInputStream* AudioManagerAndroid::MakeAudioInputStream( | 146 AudioInputStream* AudioManagerAndroid::MakeAudioInputStream( |
| 138 const AudioParameters& params, const std::string& device_id) { | 147 const AudioParameters& params, const std::string& device_id) { |
| 148 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
| 139 bool has_no_input_streams = HasNoAudioInputStreams(); | 149 bool has_no_input_streams = HasNoAudioInputStreams(); |
| 140 AudioInputStream* stream = | 150 AudioInputStream* stream = |
| 141 AudioManagerBase::MakeAudioInputStream(params, device_id); | 151 AudioManagerBase::MakeAudioInputStream(params, device_id); |
| 142 | 152 |
| 143 // The audio manager for Android creates streams intended for real-time | 153 // The audio manager for Android creates streams intended for real-time |
| 144 // VoIP sessions and therefore sets the audio mode to MODE_IN_COMMUNICATION. | 154 // VoIP sessions and therefore sets the audio mode to MODE_IN_COMMUNICATION. |
| 145 // If a Bluetooth headset is used, the audio stream will use the SCO | 155 // If a Bluetooth headset is used, the audio stream will use the SCO |
| 146 // channel and therefore have a limited bandwidth (8kHz). | 156 // channel and therefore have a limited bandwidth (8kHz). |
| 147 if (stream && has_no_input_streams) { | 157 if (stream && has_no_input_streams) { |
| 148 communication_mode_is_on_ = true; | 158 communication_mode_is_on_ = true; |
| 149 SetCommunicationAudioModeOn(true); | 159 SetCommunicationAudioModeOn(true); |
| 150 } | 160 } |
| 151 return stream; | 161 return stream; |
| 152 } | 162 } |
| 153 | 163 |
| 154 void AudioManagerAndroid::ReleaseOutputStream(AudioOutputStream* stream) { | 164 void AudioManagerAndroid::ReleaseOutputStream(AudioOutputStream* stream) { |
| 165 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
| 155 AudioManagerBase::ReleaseOutputStream(stream); | 166 AudioManagerBase::ReleaseOutputStream(stream); |
| 156 base::AutoLock lock(streams_lock_); | |
| 157 streams_.erase(static_cast<OpenSLESOutputStream*>(stream)); | 167 streams_.erase(static_cast<OpenSLESOutputStream*>(stream)); |
| 158 } | 168 } |
| 159 | 169 |
| 160 void AudioManagerAndroid::ReleaseInputStream(AudioInputStream* stream) { | 170 void AudioManagerAndroid::ReleaseInputStream(AudioInputStream* stream) { |
| 171 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
| 172 DCHECK(!j_audio_manager_.is_null()); |
| 161 AudioManagerBase::ReleaseInputStream(stream); | 173 AudioManagerBase::ReleaseInputStream(stream); |
| 162 | 174 |
| 163 // Restore the audio mode which was used before the first communication- | 175 // Restore the audio mode which was used before the first communication- |
| 164 // mode stream was created. | 176 // mode stream was created. |
| 165 if (HasNoAudioInputStreams()) { | 177 if (HasNoAudioInputStreams()) { |
| 166 communication_mode_is_on_ = false; | 178 communication_mode_is_on_ = false; |
| 167 SetCommunicationAudioModeOn(false); | 179 SetCommunicationAudioModeOn(false); |
| 168 } | 180 } |
| 169 } | 181 } |
| 170 | 182 |
| 171 AudioOutputStream* AudioManagerAndroid::MakeLinearOutputStream( | 183 AudioOutputStream* AudioManagerAndroid::MakeLinearOutputStream( |
| 172 const AudioParameters& params) { | 184 const AudioParameters& params) { |
| 173 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format()); | 185 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format()); |
| 186 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
| 174 return new OpenSLESOutputStream(this, params, SL_ANDROID_STREAM_MEDIA); | 187 return new OpenSLESOutputStream(this, params, SL_ANDROID_STREAM_MEDIA); |
| 175 } | 188 } |
| 176 | 189 |
| 177 AudioOutputStream* AudioManagerAndroid::MakeLowLatencyOutputStream( | 190 AudioOutputStream* AudioManagerAndroid::MakeLowLatencyOutputStream( |
| 178 const AudioParameters& params, | 191 const AudioParameters& params, |
| 179 const std::string& device_id) { | 192 const std::string& device_id) { |
| 180 DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!"; | 193 DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!"; |
| 181 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format()); | 194 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format()); |
| 182 | 195 |
| 183 // Set stream type which matches the current system-wide audio mode used by | 196 // Set stream type which matches the current system-wide audio mode used by |
| 184 // the Android audio manager. | 197 // the Android audio manager. |
| 185 const SLint32 stream_type = communication_mode_is_on_ ? | 198 const SLint32 stream_type = communication_mode_is_on_ ? |
| 186 SL_ANDROID_STREAM_VOICE : SL_ANDROID_STREAM_MEDIA; | 199 SL_ANDROID_STREAM_VOICE : SL_ANDROID_STREAM_MEDIA; |
| 187 return new OpenSLESOutputStream(this, params, stream_type); | 200 return new OpenSLESOutputStream(this, params, stream_type); |
| 188 } | 201 } |
| 189 | 202 |
| 190 AudioInputStream* AudioManagerAndroid::MakeLinearInputStream( | 203 AudioInputStream* AudioManagerAndroid::MakeLinearInputStream( |
| 191 const AudioParameters& params, const std::string& device_id) { | 204 const AudioParameters& params, const std::string& device_id) { |
| 192 // TODO(henrika): add support for device selection if/when any client | 205 // TODO(henrika): add support for device selection if/when any client |
| 193 // needs it. | 206 // needs it. |
| 194 DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!"; | 207 DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!"; |
| 195 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format()); | 208 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format()); |
| 196 return new OpenSLESInputStream(this, params); | 209 return new OpenSLESInputStream(this, params); |
| 197 } | 210 } |
| 198 | 211 |
| 199 AudioInputStream* AudioManagerAndroid::MakeLowLatencyInputStream( | 212 AudioInputStream* AudioManagerAndroid::MakeLowLatencyInputStream( |
| 200 const AudioParameters& params, const std::string& device_id) { | 213 const AudioParameters& params, const std::string& device_id) { |
| 214 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
| 201 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format()); | 215 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format()); |
| 202 DLOG_IF(ERROR, device_id.empty()) << "Invalid device ID!"; | 216 DLOG_IF(ERROR, device_id.empty()) << "Invalid device ID!"; |
| 217 |
| 203 // Use the device ID to select the correct input device. | 218 // Use the device ID to select the correct input device. |
| 204 // Note that the input device is always associated with a certain output | 219 // Note that the input device is always associated with a certain output |
| 205 // device, i.e., this selection does also switch the output device. | 220 // device, i.e., this selection does also switch the output device. |
| 206 // All input and output streams will be affected by the device selection. | 221 // All input and output streams will be affected by the device selection. |
| 207 if (!SetAudioDevice(device_id)) { | 222 if (!SetAudioDevice(device_id)) { |
| 208 LOG(ERROR) << "Unable to select audio device!"; | 223 LOG(ERROR) << "Unable to select audio device!"; |
| 209 return NULL; | 224 return NULL; |
| 210 } | 225 } |
| 211 | 226 |
| 212 if (params.effects() != AudioParameters::NO_EFFECTS) { | 227 if (params.effects() != AudioParameters::NO_EFFECTS) { |
| 213 // Platform effects can only be enabled through the AudioRecord path. | 228 // Platform effects can only be enabled through the AudioRecord path. |
| 214 // An effect should only have been requested here if recommended by | 229 // An effect should only have been requested here if recommended by |
| 215 // AudioManagerAndroid.shouldUse<Effect>. | 230 // AudioManagerAndroid.shouldUse<Effect>. |
| 216 // | 231 // |
| 217 // Creating this class requires Jelly Bean, which is already guaranteed by | 232 // Creating this class requires Jelly Bean, which is already guaranteed by |
| 218 // shouldUse<Effect>. Only DCHECK on that condition to allow tests to use | 233 // shouldUse<Effect>. Only DCHECK on that condition to allow tests to use |
| 219 // the effect settings as a way to select the input path. | 234 // the effect settings as a way to select the input path. |
| 220 DCHECK_GE(base::android::BuildInfo::GetInstance()->sdk_int(), 16); | 235 DCHECK_GE(base::android::BuildInfo::GetInstance()->sdk_int(), 16); |
| 221 DVLOG(1) << "Creating AudioRecordInputStream"; | 236 DVLOG(1) << "Creating AudioRecordInputStream"; |
| 222 return new AudioRecordInputStream(this, params); | 237 return new AudioRecordInputStream(this, params); |
| 223 } | 238 } |
| 224 DVLOG(1) << "Creating OpenSLESInputStream"; | 239 DVLOG(1) << "Creating OpenSLESInputStream"; |
| 225 return new OpenSLESInputStream(this, params); | 240 return new OpenSLESInputStream(this, params); |
| 226 } | 241 } |
| 227 | 242 |
| 228 int AudioManagerAndroid::GetOptimalOutputFrameSize(int sample_rate, | 243 // static |
| 229 int channels) { | 244 bool AudioManagerAndroid::RegisterAudioManager(JNIEnv* env) { |
| 230 if (IsAudioLowLatencySupported()) { | 245 return RegisterNativesImpl(env); |
| 231 return GetAudioLowLatencyOutputFrameSize(); | 246 } |
| 232 } else { | 247 |
| 233 return std::max(kDefaultOutputBufferSize, | 248 void AudioManagerAndroid::SetMute(JNIEnv* env, jobject obj, jboolean muted) { |
| 234 Java_AudioManagerAndroid_getMinOutputFrameSize( | 249 GetTaskRunner()->PostTask( |
| 235 base::android::AttachCurrentThread(), | 250 FROM_HERE, |
| 236 sample_rate, channels)); | 251 base::Bind( |
| 237 } | 252 &AudioManagerAndroid::DoSetMuteOnAudioThread, |
| 253 base::Unretained(this), |
| 254 muted)); |
| 238 } | 255 } |
| 239 | 256 |
| 240 AudioParameters AudioManagerAndroid::GetPreferredOutputStreamParameters( | 257 AudioParameters AudioManagerAndroid::GetPreferredOutputStreamParameters( |
| 241 const std::string& output_device_id, | 258 const std::string& output_device_id, |
| 242 const AudioParameters& input_params) { | 259 const AudioParameters& input_params) { |
| 243 // TODO(tommi): Support |output_device_id|. | 260 // TODO(tommi): Support |output_device_id|. |
| 261 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
| 244 DLOG_IF(ERROR, !output_device_id.empty()) << "Not implemented!"; | 262 DLOG_IF(ERROR, !output_device_id.empty()) << "Not implemented!"; |
| 245 ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO; | 263 ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO; |
| 246 int sample_rate = GetNativeOutputSampleRate(); | 264 int sample_rate = GetNativeOutputSampleRate(); |
| 247 int buffer_size = GetOptimalOutputFrameSize(sample_rate, 2); | 265 int buffer_size = GetOptimalOutputFrameSize(sample_rate, 2); |
| 248 int bits_per_sample = 16; | 266 int bits_per_sample = 16; |
| 249 int input_channels = 0; | 267 int input_channels = 0; |
| 250 if (input_params.IsValid()) { | 268 if (input_params.IsValid()) { |
| 251 // Use the client's input parameters if they are valid. | 269 // Use the client's input parameters if they are valid. |
| 252 sample_rate = input_params.sample_rate(); | 270 sample_rate = input_params.sample_rate(); |
| 253 bits_per_sample = input_params.bits_per_sample(); | 271 bits_per_sample = input_params.bits_per_sample(); |
| 254 channel_layout = input_params.channel_layout(); | 272 channel_layout = input_params.channel_layout(); |
| 255 input_channels = input_params.input_channels(); | 273 input_channels = input_params.input_channels(); |
| 256 buffer_size = GetOptimalOutputFrameSize( | 274 buffer_size = GetOptimalOutputFrameSize( |
| 257 sample_rate, ChannelLayoutToChannelCount(channel_layout)); | 275 sample_rate, ChannelLayoutToChannelCount(channel_layout)); |
| 258 } | 276 } |
| 259 | 277 |
| 260 int user_buffer_size = GetUserBufferSize(); | 278 int user_buffer_size = GetUserBufferSize(); |
| 261 if (user_buffer_size) | 279 if (user_buffer_size) |
| 262 buffer_size = user_buffer_size; | 280 buffer_size = user_buffer_size; |
| 263 | 281 |
| 264 return AudioParameters( | 282 return AudioParameters( |
| 265 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, input_channels, | 283 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, input_channels, |
| 266 sample_rate, bits_per_sample, buffer_size, AudioParameters::NO_EFFECTS); | 284 sample_rate, bits_per_sample, buffer_size, AudioParameters::NO_EFFECTS); |
| 267 } | 285 } |
| 268 | 286 |
| 269 bool AudioManagerAndroid::HasNoAudioInputStreams() { | 287 bool AudioManagerAndroid::HasNoAudioInputStreams() { |
| 270 return input_stream_count() == 0; | 288 return input_stream_count() == 0; |
| 271 } | 289 } |
| 272 | 290 |
| 273 // static | 291 void AudioManagerAndroid::InitializeOnAudioThread() { |
| 274 bool AudioManagerAndroid::RegisterAudioManager(JNIEnv* env) { | 292 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
| 275 return RegisterNativesImpl(env); | |
| 276 } | |
| 277 | 293 |
| 278 void AudioManagerAndroid::Init() { | 294 // Create the Android audio manager on the audio thread. |
| 295 DVLOG(2) << "Creating Java part of the audio manager"; |
| 296 j_audio_manager_.Reset( |
| 297 Java_AudioManagerAndroid_createAudioManagerAndroid( |
| 298 base::android::AttachCurrentThread(), |
| 299 base::android::GetApplicationContext(), |
| 300 reinterpret_cast<intptr_t>(this))); |
| 301 |
| 302 // Prepare the list of audio devices and register receivers for device |
| 303 // notifications. |
| 279 Java_AudioManagerAndroid_init( | 304 Java_AudioManagerAndroid_init( |
| 280 base::android::AttachCurrentThread(), | 305 base::android::AttachCurrentThread(), |
| 281 j_audio_manager_.obj()); | 306 j_audio_manager_.obj()); |
| 282 } | 307 } |
| 283 | 308 |
| 284 void AudioManagerAndroid::Close() { | 309 void AudioManagerAndroid::ShutdownOnAudioThread() { |
| 310 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
| 311 DVLOG(2) << "Destroying Java part of the audio manager"; |
| 285 Java_AudioManagerAndroid_close( | 312 Java_AudioManagerAndroid_close( |
| 286 base::android::AttachCurrentThread(), | 313 base::android::AttachCurrentThread(), |
| 287 j_audio_manager_.obj()); | 314 j_audio_manager_.obj()); |
| 288 } | 315 j_audio_manager_.Reset(); |
| 289 | |
| 290 void AudioManagerAndroid::SetMute(JNIEnv* env, jobject obj, jboolean muted) { | |
| 291 GetTaskRunner()->PostTask( | |
| 292 FROM_HERE, | |
| 293 base::Bind( | |
| 294 &AudioManagerAndroid::DoSetMuteOnAudioThread, | |
| 295 base::Unretained(this), | |
| 296 muted)); | |
| 297 } | |
| 298 | |
| 299 void AudioManagerAndroid::DoSetMuteOnAudioThread(bool muted) { | |
| 300 base::AutoLock lock(streams_lock_); | |
| 301 for (OutputStreams::iterator it = streams_.begin(); | |
| 302 it != streams_.end(); ++it) { | |
| 303 (*it)->SetMute(muted); | |
| 304 } | |
| 305 } | 316 } |
| 306 | 317 |
| 307 void AudioManagerAndroid::SetCommunicationAudioModeOn(bool on) { | 318 void AudioManagerAndroid::SetCommunicationAudioModeOn(bool on) { |
| 308 Java_AudioManagerAndroid_setCommunicationAudioModeOn( | 319 Java_AudioManagerAndroid_setCommunicationAudioModeOn( |
| 309 base::android::AttachCurrentThread(), | 320 base::android::AttachCurrentThread(), |
| 310 j_audio_manager_.obj(), on); | 321 j_audio_manager_.obj(), on); |
| 311 } | 322 } |
| 312 | 323 |
| 313 bool AudioManagerAndroid::SetAudioDevice(const std::string& device_id) { | 324 bool AudioManagerAndroid::SetAudioDevice(const std::string& device_id) { |
| 314 JNIEnv* env = AttachCurrentThread(); | 325 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
| 315 | 326 |
| 316 // Send the unique device ID to the Java audio manager and make the | 327 // Send the unique device ID to the Java audio manager and make the |
| 317 // device switch. Provide an empty string to the Java audio manager | 328 // device switch. Provide an empty string to the Java audio manager |
| 318 // if the default device is selected. | 329 // if the default device is selected. |
| 330 JNIEnv* env = AttachCurrentThread(); |
| 319 ScopedJavaLocalRef<jstring> j_device_id = ConvertUTF8ToJavaString( | 331 ScopedJavaLocalRef<jstring> j_device_id = ConvertUTF8ToJavaString( |
| 320 env, | 332 env, |
| 321 device_id == AudioManagerBase::kDefaultDeviceId ? | 333 device_id == AudioManagerBase::kDefaultDeviceId ? |
| 322 std::string() : device_id); | 334 std::string() : device_id); |
| 323 return Java_AudioManagerAndroid_setDevice( | 335 return Java_AudioManagerAndroid_setDevice( |
| 324 env, j_audio_manager_.obj(), j_device_id.obj()); | 336 env, j_audio_manager_.obj(), j_device_id.obj()); |
| 325 } | 337 } |
| 326 | 338 |
| 327 int AudioManagerAndroid::GetNativeOutputSampleRate() { | 339 int AudioManagerAndroid::GetNativeOutputSampleRate() { |
| 328 return Java_AudioManagerAndroid_getNativeOutputSampleRate( | 340 return Java_AudioManagerAndroid_getNativeOutputSampleRate( |
| 329 base::android::AttachCurrentThread(), | 341 base::android::AttachCurrentThread(), |
| 330 j_audio_manager_.obj()); | 342 j_audio_manager_.obj()); |
| 331 } | 343 } |
| 332 | 344 |
| 333 bool AudioManagerAndroid::IsAudioLowLatencySupported() { | 345 bool AudioManagerAndroid::IsAudioLowLatencySupported() { |
| 334 return Java_AudioManagerAndroid_isAudioLowLatencySupported( | 346 return Java_AudioManagerAndroid_isAudioLowLatencySupported( |
| 335 base::android::AttachCurrentThread(), | 347 base::android::AttachCurrentThread(), |
| 336 j_audio_manager_.obj()); | 348 j_audio_manager_.obj()); |
| 337 } | 349 } |
| 338 | 350 |
| 339 int AudioManagerAndroid::GetAudioLowLatencyOutputFrameSize() { | 351 int AudioManagerAndroid::GetAudioLowLatencyOutputFrameSize() { |
| 340 return Java_AudioManagerAndroid_getAudioLowLatencyOutputFrameSize( | 352 return Java_AudioManagerAndroid_getAudioLowLatencyOutputFrameSize( |
| 341 base::android::AttachCurrentThread(), | 353 base::android::AttachCurrentThread(), |
| 342 j_audio_manager_.obj()); | 354 j_audio_manager_.obj()); |
| 343 } | 355 } |
| 344 | 356 |
| 357 int AudioManagerAndroid::GetOptimalOutputFrameSize(int sample_rate, |
| 358 int channels) { |
| 359 if (IsAudioLowLatencySupported()) |
| 360 return GetAudioLowLatencyOutputFrameSize(); |
| 361 |
| 362 return std::max(kDefaultOutputBufferSize, |
| 363 Java_AudioManagerAndroid_getMinOutputFrameSize( |
| 364 base::android::AttachCurrentThread(), |
| 365 sample_rate, channels)); |
| 366 } |
| 367 |
| 368 void AudioManagerAndroid::DoSetMuteOnAudioThread(bool muted) { |
| 369 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
| 370 for (OutputStreams::iterator it = streams_.begin(); |
| 371 it != streams_.end(); ++it) { |
| 372 (*it)->SetMute(muted); |
| 373 } |
| 374 } |
| 375 |
| 345 } // namespace media | 376 } // namespace media |
| OLD | NEW |