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