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