Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(13)

Side by Side Diff: media/audio/android/audio_manager_android.cc

Issue 131503006: Initialization of audio manager for Android is now done on the audio thread (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed all unit tests Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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) {
74 // Always add default device parameters as first element. 69 CreateAndInitOnAudioThread();
75 DCHECK(device_names->empty());
76 AddDefaultDevice(device_names);
77 70
78 JNIEnv* env = AttachCurrentThread(); 71 // Get list of available audio devices and use the audio thread to reduce
79 ScopedJavaLocalRef<jobjectArray> j_device_array = 72 // the number of calling threads to the Java layer. Also, ensure that the
80 Java_AudioManagerAndroid_getAudioInputDeviceNames( 73 // calling thread sees this function call as synchronous.
bulach 2014/02/05 19:29:39 what is the calling thread? we obviously try to av
henrika (OOO until Aug 14) 2014/02/05 21:47:30 Right now the calling threads are a device manager
DaleCurtis 2014/02/05 21:50:13 I suspect you can completely remove the IO thread
bulach 2014/02/06 02:06:56 yeah, let's separate the issues here.. :) 1) I'm h
henrika (OOO until Aug 14) 2014/02/06 08:58:57 Calls to GetAudioInputDeviceNames (7 occurrences)
tommi (sloooow) - chröme 2014/02/06 13:52:58 I looked into this and from what I can tell there
henrika (OOO until Aug 14) 2014/02/13 15:00:09 Now only called on audio thread. Modified.
81 env, j_audio_manager_.obj()); 74 scoped_refptr<base::SingleThreadTaskRunner> task_runner(GetTaskRunner());
82 jsize len = env->GetArrayLength(j_device_array.obj()); 75 if (task_runner->BelongsToCurrentThread()) {
83 AudioDeviceName device; 76 GetAudioInputDeviceNamesOnAudioThread(NULL, device_names);
84 for (jsize i = 0; i < len; ++i) { 77 } else {
85 ScopedJavaLocalRef<jobject> j_device( 78 base::WaitableEvent event(false, false);
86 env, env->GetObjectArrayElement(j_device_array.obj(), i)); 79 task_runner->PostTask(
87 ScopedJavaLocalRef<jstring> j_device_name = 80 FROM_HERE,
88 Java_AudioDeviceName_name(env, j_device.obj()); 81 base::Bind(
89 ConvertJavaStringToUTF8(env, j_device_name.obj(), &device.device_name); 82 &AudioManagerAndroid::GetAudioInputDeviceNamesOnAudioThread,
90 ScopedJavaLocalRef<jstring> j_device_id = 83 base::Unretained(this),
91 Java_AudioDeviceName_id(env, j_device.obj()); 84 &event,
92 ConvertJavaStringToUTF8(env, j_device_id.obj(), &device.unique_id); 85 device_names));
93 device_names->push_back(device); 86 event.Wait();
94 } 87 }
95 } 88 }
96 89
97 void AudioManagerAndroid::GetAudioOutputDeviceNames( 90 void AudioManagerAndroid::GetAudioOutputDeviceNames(
98 AudioDeviceNames* device_names) { 91 AudioDeviceNames* device_names) {
99 // TODO(henrika): enumerate using GetAudioInputDeviceNames(). 92 // TODO(henrika): enumerate using GetAudioInputDeviceNames().
100 AddDefaultDevice(device_names); 93 AddDefaultDevice(device_names);
101 } 94 }
102 95
103 AudioParameters AudioManagerAndroid::GetInputStreamParameters( 96 AudioParameters AudioManagerAndroid::GetInputStreamParameters(
104 const std::string& device_id) { 97 const std::string& device_id) {
105 JNIEnv* env = AttachCurrentThread(); 98 // TODO(henrika): improve documentation regarding the threading model.
99 // We are on the audio thread here once the MediaStreamDeviceThread is
100 // removed and replaced by the audio thread but we also call this one from
101 // RenderMessageFilter::OnGetAudioHardwareConfig() on the IO thread.
102 CreateAndInitOnAudioThread();
103
106 // Use mono as preferred number of input channels on Android to save 104 // Use mono as preferred number of input channels on Android to save
107 // resources. Using mono also avoids a driver issue seen on Samsung 105 // resources. Using mono also avoids a driver issue seen on Samsung
108 // Galaxy S3 and S4 devices. See http://crbug.com/256851 for details. 106 // Galaxy S3 and S4 devices. See http://crbug.com/256851 for details.
107 JNIEnv* env = AttachCurrentThread();
108 CHECK(env);
109 ChannelLayout channel_layout = CHANNEL_LAYOUT_MONO; 109 ChannelLayout channel_layout = CHANNEL_LAYOUT_MONO;
110 int buffer_size = Java_AudioManagerAndroid_getMinInputFrameSize( 110 int buffer_size = Java_AudioManagerAndroid_getMinInputFrameSize(
111 env, GetNativeOutputSampleRate(), 111 env, GetNativeOutputSampleRate(),
112 ChannelLayoutToChannelCount(channel_layout)); 112 ChannelLayoutToChannelCount(channel_layout));
113 int effects = AudioParameters::NO_EFFECTS; 113 int effects = AudioParameters::NO_EFFECTS;
114 effects |= Java_AudioManagerAndroid_shouldUseAcousticEchoCanceler(env) ? 114 effects |= Java_AudioManagerAndroid_shouldUseAcousticEchoCanceler(env) ?
115 AudioParameters::ECHO_CANCELLER : AudioParameters::NO_EFFECTS; 115 AudioParameters::ECHO_CANCELLER : AudioParameters::NO_EFFECTS;
116 AudioParameters params( 116 AudioParameters params(
117 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, 0, 117 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, 0,
118 GetNativeOutputSampleRate(), 16, 118 GetNativeOutputSampleRate(), 16,
119 buffer_size <= 0 ? kDefaultInputBufferSize : buffer_size, effects); 119 buffer_size <= 0 ? kDefaultInputBufferSize : buffer_size, effects);
120 return params; 120 return params;
121 } 121 }
122 122
123 AudioOutputStream* AudioManagerAndroid::MakeAudioOutputStream( 123 AudioOutputStream* AudioManagerAndroid::MakeAudioOutputStream(
124 const AudioParameters& params, 124 const AudioParameters& params,
125 const std::string& device_id, 125 const std::string& device_id,
126 const std::string& input_device_id) { 126 const std::string& input_device_id) {
127 bool had_no_streams = HadNoAudioStreams(); 127 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
128 CreateAndInitOnAudioThread();
129 bool has_no_streams = HasNoAudioStreams();
128 AudioOutputStream* stream = 130 AudioOutputStream* stream =
129 AudioManagerBase::MakeAudioOutputStream(params, std::string(), 131 AudioManagerBase::MakeAudioOutputStream(params, std::string(),
130 std::string()); 132 std::string());
131 133
132 // The audio manager for Android creates streams intended for real-time 134 // The audio manager for Android creates streams intended for real-time
133 // VoIP sessions and therefore sets the audio mode to MODE_IN_COMMUNICATION. 135 // VoIP sessions and therefore sets the audio mode to MODE_IN_COMMUNICATION.
134 // If a Bluetooth headset is used, the audio stream will use the SCO 136 // If a Bluetooth headset is used, the audio stream will use the SCO
135 // channel and therefore have a limited bandwidth (8-16kHz). 137 // channel and therefore have a limited bandwidth (8-16kHz).
136 if (stream && had_no_streams) 138 if (stream && has_no_streams)
137 SetCommunicationAudioModeOn(true); 139 SetCommunicationAudioModeOn(true);
138 140
139 { 141 {
140 base::AutoLock lock(streams_lock_); 142 base::AutoLock lock(streams_lock_);
141 streams_.insert(static_cast<OpenSLESOutputStream*>(stream)); 143 streams_.insert(static_cast<OpenSLESOutputStream*>(stream));
142 } 144 }
143 145
144 return stream; 146 return stream;
145 } 147 }
146 148
147 AudioInputStream* AudioManagerAndroid::MakeAudioInputStream( 149 AudioInputStream* AudioManagerAndroid::MakeAudioInputStream(
148 const AudioParameters& params, const std::string& device_id) { 150 const AudioParameters& params, const std::string& device_id) {
149 bool had_no_streams = HadNoAudioStreams(); 151 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
152 CreateAndInitOnAudioThread();
153 bool has_no_streams = HasNoAudioStreams();
150 AudioInputStream* stream = 154 AudioInputStream* stream =
151 AudioManagerBase::MakeAudioInputStream(params, device_id); 155 AudioManagerBase::MakeAudioInputStream(params, device_id);
152 156
153 // The audio manager for Android creates streams intended for real-time 157 // The audio manager for Android creates streams intended for real-time
154 // VoIP sessions and therefore sets the audio mode to MODE_IN_COMMUNICATION. 158 // VoIP sessions and therefore sets the audio mode to MODE_IN_COMMUNICATION.
155 // If a Bluetooth headset is used, the audio stream will use the SCO 159 // If a Bluetooth headset is used, the audio stream will use the SCO
156 // channel and therefore have a limited bandwidth (8kHz). 160 // channel and therefore have a limited bandwidth (8kHz).
157 if (stream && had_no_streams) 161 if (stream && has_no_streams)
158 SetCommunicationAudioModeOn(true); 162 SetCommunicationAudioModeOn(true);
159 return stream; 163 return stream;
160 } 164 }
161 165
162 void AudioManagerAndroid::ReleaseOutputStream(AudioOutputStream* stream) { 166 void AudioManagerAndroid::ReleaseOutputStream(AudioOutputStream* stream) {
163 AudioManagerBase::ReleaseOutputStream(stream); 167 AudioManagerBase::ReleaseOutputStream(stream);
164 168
165 // Restore the audio mode which was used before the first communication- 169 // Restore the audio mode which was used before the first communication-
166 // mode stream was created. 170 // mode stream was created.
167 if (HadNoAudioStreams()) 171 if (HasNoAudioStreams())
168 SetCommunicationAudioModeOn(false); 172 SetCommunicationAudioModeOn(false);
169 base::AutoLock lock(streams_lock_); 173 base::AutoLock lock(streams_lock_);
170 streams_.erase(static_cast<OpenSLESOutputStream*>(stream)); 174 streams_.erase(static_cast<OpenSLESOutputStream*>(stream));
171 } 175 }
172 176
173 void AudioManagerAndroid::ReleaseInputStream(AudioInputStream* stream) { 177 void AudioManagerAndroid::ReleaseInputStream(AudioInputStream* stream) {
178 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
179 DCHECK(!j_audio_manager_.is_null());
174 AudioManagerBase::ReleaseInputStream(stream); 180 AudioManagerBase::ReleaseInputStream(stream);
175 181
176 // Restore the audio mode which was used before the first communication- 182 // Restore the audio mode which was used before the first communication-
177 // mode stream was created. 183 // mode stream was created.
178 if (HadNoAudioStreams()) 184 if (HasNoAudioStreams())
179 SetCommunicationAudioModeOn(false); 185 SetCommunicationAudioModeOn(false);
180 } 186 }
181 187
182 AudioOutputStream* AudioManagerAndroid::MakeLinearOutputStream( 188 AudioOutputStream* AudioManagerAndroid::MakeLinearOutputStream(
183 const AudioParameters& params) { 189 const AudioParameters& params) {
184 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format()); 190 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
185 return new OpenSLESOutputStream(this, params); 191 return new OpenSLESOutputStream(this, params);
186 } 192 }
187 193
188 AudioOutputStream* AudioManagerAndroid::MakeLowLatencyOutputStream( 194 AudioOutputStream* AudioManagerAndroid::MakeLowLatencyOutputStream(
189 const AudioParameters& params, 195 const AudioParameters& params,
190 const std::string& device_id, 196 const std::string& device_id,
191 const std::string& input_device_id) { 197 const std::string& input_device_id) {
192 DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!"; 198 DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!";
193 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format()); 199 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
200 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
201 CreateAndInitOnAudioThread();
194 return new OpenSLESOutputStream(this, params); 202 return new OpenSLESOutputStream(this, params);
195 } 203 }
196 204
197 AudioInputStream* AudioManagerAndroid::MakeLinearInputStream( 205 AudioInputStream* AudioManagerAndroid::MakeLinearInputStream(
198 const AudioParameters& params, const std::string& device_id) { 206 const AudioParameters& params, const std::string& device_id) {
199 // TODO(henrika): add support for device selection if/when any client 207 // TODO(henrika): add support for device selection if/when any client
200 // needs it. 208 // needs it.
201 DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!"; 209 DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!";
202 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format()); 210 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
211 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
212 CreateAndInitOnAudioThread();
203 return new OpenSLESInputStream(this, params); 213 return new OpenSLESInputStream(this, params);
204 } 214 }
205 215
206 AudioInputStream* AudioManagerAndroid::MakeLowLatencyInputStream( 216 AudioInputStream* AudioManagerAndroid::MakeLowLatencyInputStream(
207 const AudioParameters& params, const std::string& device_id) { 217 const AudioParameters& params, const std::string& device_id) {
208 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format()); 218 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
209 DLOG_IF(ERROR, device_id.empty()) << "Invalid device ID!"; 219 DLOG_IF(ERROR, device_id.empty()) << "Invalid device ID!";
220 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
221 CreateAndInitOnAudioThread();
222
210 // Use the device ID to select the correct input device. 223 // Use the device ID to select the correct input device.
211 // 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
212 // device, i.e., this selection does also switch the output device. 225 // device, i.e., this selection does also switch the output device.
213 // 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.
214 if (!SetAudioDevice(device_id)) { 227 if (!SetAudioDevice(device_id)) {
215 LOG(ERROR) << "Unable to select audio device!"; 228 LOG(ERROR) << "Unable to select audio device!";
216 return NULL; 229 return NULL;
217 } 230 }
218 231
219 if (params.effects() != AudioParameters::NO_EFFECTS) { 232 if (params.effects() != AudioParameters::NO_EFFECTS) {
220 // Platform effects can only be enabled through the AudioRecord path. 233 // Platform effects can only be enabled through the AudioRecord path.
221 // An effect should only have been requested here if recommended by 234 // An effect should only have been requested here if recommended by
222 // AudioManagerAndroid.shouldUse<Effect>. 235 // AudioManagerAndroid.shouldUse<Effect>.
223 // 236 //
224 // Creating this class requires Jelly Bean, which is already guaranteed by 237 // Creating this class requires Jelly Bean, which is already guaranteed by
225 // 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
226 // the effect settings as a way to select the input path. 239 // the effect settings as a way to select the input path.
227 DCHECK_GE(base::android::BuildInfo::GetInstance()->sdk_int(), 16); 240 DCHECK_GE(base::android::BuildInfo::GetInstance()->sdk_int(), 16);
228 DVLOG(1) << "Creating AudioRecordInputStream"; 241 DVLOG(1) << "Creating AudioRecordInputStream";
229 return new AudioRecordInputStream(this, params); 242 return new AudioRecordInputStream(this, params);
230 } 243 }
231 DVLOG(1) << "Creating OpenSLESInputStream"; 244 DVLOG(1) << "Creating OpenSLESInputStream";
232 return new OpenSLESInputStream(this, params); 245 return new OpenSLESInputStream(this, params);
233 } 246 }
234 247
235 int AudioManagerAndroid::GetOptimalOutputFrameSize(int sample_rate, 248 // static
236 int channels) { 249 bool AudioManagerAndroid::RegisterAudioManager(JNIEnv* env) {
237 if (IsAudioLowLatencySupported()) { 250 return RegisterNativesImpl(env);
238 return GetAudioLowLatencyOutputFrameSize(); 251 }
239 } else { 252
240 return std::max(kDefaultOutputBufferSize, 253 void AudioManagerAndroid::SetMute(JNIEnv* env, jobject obj, jboolean muted) {
241 Java_AudioManagerAndroid_getMinOutputFrameSize( 254 GetTaskRunner()->PostTask(
242 base::android::AttachCurrentThread(), 255 FROM_HERE,
243 sample_rate, channels)); 256 base::Bind(
244 } 257 &AudioManagerAndroid::DoSetMuteOnAudioThread,
258 base::Unretained(this),
259 muted));
245 } 260 }
246 261
247 AudioParameters AudioManagerAndroid::GetPreferredOutputStreamParameters( 262 AudioParameters AudioManagerAndroid::GetPreferredOutputStreamParameters(
248 const std::string& output_device_id, 263 const std::string& output_device_id,
249 const AudioParameters& input_params) { 264 const AudioParameters& input_params) {
265 // TODO(henrika): improve documentation regarding the threading model.
266 // We are on the audio thread here once the MediaStreamDeviceThread is
267 // removed and replaced by the audio thread but we also call this one from
268 // RenderMessageFilter::OnGetAudioHardwareConfig() on the IO thread.
269 CreateAndInitOnAudioThread();
270
250 // TODO(tommi): Support |output_device_id|. 271 // TODO(tommi): Support |output_device_id|.
251 DLOG_IF(ERROR, !output_device_id.empty()) << "Not implemented!"; 272 DLOG_IF(ERROR, !output_device_id.empty()) << "Not implemented!";
252 ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO; 273 ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
253 int sample_rate = GetNativeOutputSampleRate(); 274 int sample_rate = GetNativeOutputSampleRate();
254 int buffer_size = GetOptimalOutputFrameSize(sample_rate, 2); 275 int buffer_size = GetOptimalOutputFrameSize(sample_rate, 2);
255 int bits_per_sample = 16; 276 int bits_per_sample = 16;
256 int input_channels = 0; 277 int input_channels = 0;
257 if (input_params.IsValid()) { 278 if (input_params.IsValid()) {
258 // Use the client's input parameters if they are valid. 279 // Use the client's input parameters if they are valid.
259 sample_rate = input_params.sample_rate(); 280 sample_rate = input_params.sample_rate();
260 bits_per_sample = input_params.bits_per_sample(); 281 bits_per_sample = input_params.bits_per_sample();
261 channel_layout = input_params.channel_layout(); 282 channel_layout = input_params.channel_layout();
262 input_channels = input_params.input_channels(); 283 input_channels = input_params.input_channels();
263 buffer_size = GetOptimalOutputFrameSize( 284 buffer_size = GetOptimalOutputFrameSize(
264 sample_rate, ChannelLayoutToChannelCount(channel_layout)); 285 sample_rate, ChannelLayoutToChannelCount(channel_layout));
265 } 286 }
266 287
267 int user_buffer_size = GetUserBufferSize(); 288 int user_buffer_size = GetUserBufferSize();
268 if (user_buffer_size) 289 if (user_buffer_size)
269 buffer_size = user_buffer_size; 290 buffer_size = user_buffer_size;
270 291
271 return AudioParameters( 292 return AudioParameters(
272 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, input_channels, 293 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, input_channels,
273 sample_rate, bits_per_sample, buffer_size, AudioParameters::NO_EFFECTS); 294 sample_rate, bits_per_sample, buffer_size, AudioParameters::NO_EFFECTS);
274 } 295 }
275 296
276 bool AudioManagerAndroid::HadNoAudioStreams() { 297 void AudioManagerAndroid::WillDestroyCurrentMessageLoop() {
298 CloseOnAudioThread();
299 }
300
301 void AudioManagerAndroid::CreateAndInitOnAudioThread() {
302 scoped_refptr<base::SingleThreadTaskRunner> task_runner(GetTaskRunner());
303 if (task_runner->BelongsToCurrentThread()) {
304 DoCreateAndInitOnAudioThread(NULL);
305 } else {
306 base::WaitableEvent event(false, false);
bulach 2014/02/05 19:29:39 yeah, as above, this is a really bad pattern, we s
henrika (OOO until Aug 14) 2014/02/05 21:47:30 I think it is a topic which we perhaps could discu
307 task_runner->PostTask(
308 FROM_HERE,
309 base::Bind(
310 &AudioManagerAndroid::DoCreateAndInitOnAudioThread,
311 base::Unretained(this),
312 &event));
313 event.Wait();
314 }
315 }
316
317 void AudioManagerAndroid::DoCreateAndInitOnAudioThread(
318 base::WaitableEvent* event) {
319 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
320 if (!j_audio_manager_.is_null()) {
321 if (event)
322 event->Signal();
323 return;
324 }
325
326 JNIEnv* env = base::android::AttachCurrentThread();
327 CHECK(env);
328
329 // Create the Android audio manager on the audio thread.
330 DVLOG(1) << "Creating Java part of the audio manager";
331 j_audio_manager_.Reset(
332 Java_AudioManagerAndroid_createAudioManagerAndroid(
333 env,
334 base::android::GetApplicationContext(),
335 reinterpret_cast<intptr_t>(this)));
336
337 // Prepare the list of audio devices and register receivers for device
338 // notifications.
339 Init();
340
341 // Ensure that we are notified when the audio thread dies.
342 base::MessageLoop::current()->AddDestructionObserver(this);
343
344 if (event)
345 event->Signal();
346 }
347
348 void AudioManagerAndroid::CloseOnAudioThread() {
349 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
350 if (j_audio_manager_.is_null())
351 return;
352 Close();
353 DVLOG(1) << "Destroying Java part of the audio manager";
354 j_audio_manager_.Reset();
355 }
356
357 bool AudioManagerAndroid::HasNoAudioStreams() {
277 return output_stream_count() == 0 && input_stream_count() == 0; 358 return output_stream_count() == 0 && input_stream_count() == 0;
278 } 359 }
279 360
280 // static
281 bool AudioManagerAndroid::RegisterAudioManager(JNIEnv* env) {
282 return RegisterNativesImpl(env);
283 }
284
285 void AudioManagerAndroid::Init() { 361 void AudioManagerAndroid::Init() {
286 Java_AudioManagerAndroid_init( 362 Java_AudioManagerAndroid_init(
287 base::android::AttachCurrentThread(), 363 base::android::AttachCurrentThread(),
288 j_audio_manager_.obj()); 364 j_audio_manager_.obj());
289 } 365 }
290 366
291 void AudioManagerAndroid::Close() { 367 void AudioManagerAndroid::Close() {
292 Java_AudioManagerAndroid_close( 368 Java_AudioManagerAndroid_close(
293 base::android::AttachCurrentThread(), 369 base::android::AttachCurrentThread(),
294 j_audio_manager_.obj()); 370 j_audio_manager_.obj());
295 } 371 }
296 372
297 void AudioManagerAndroid::SetMute(JNIEnv* env, jobject obj, jboolean muted) {
298 GetTaskRunner()->PostTask(
299 FROM_HERE,
300 base::Bind(
301 &AudioManagerAndroid::DoSetMuteOnAudioThread,
302 base::Unretained(this),
303 muted));
304 }
305
306 void AudioManagerAndroid::DoSetMuteOnAudioThread(bool muted) {
307 base::AutoLock lock(streams_lock_);
308 for (OutputStreams::iterator it = streams_.begin();
309 it != streams_.end(); ++it) {
310 (*it)->SetMute(muted);
311 }
312 }
313
314 void AudioManagerAndroid::SetCommunicationAudioModeOn(bool on) { 373 void AudioManagerAndroid::SetCommunicationAudioModeOn(bool on) {
315 Java_AudioManagerAndroid_setCommunicationAudioModeOn( 374 Java_AudioManagerAndroid_setCommunicationAudioModeOn(
316 base::android::AttachCurrentThread(), 375 base::android::AttachCurrentThread(),
317 j_audio_manager_.obj(), on); 376 j_audio_manager_.obj(), on);
318 } 377 }
319 378
320 bool AudioManagerAndroid::SetAudioDevice(const std::string& device_id) { 379 bool AudioManagerAndroid::SetAudioDevice(const std::string& device_id) {
321 JNIEnv* env = AttachCurrentThread(); 380 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
322 381
323 // Send the unique device ID to the Java audio manager and make the 382 // Send the unique device ID to the Java audio manager and make the
324 // device switch. Provide an empty string to the Java audio manager 383 // device switch. Provide an empty string to the Java audio manager
325 // if the default device is selected. 384 // if the default device is selected.
385 JNIEnv* env = AttachCurrentThread();
386 CHECK(env);
326 ScopedJavaLocalRef<jstring> j_device_id = ConvertUTF8ToJavaString( 387 ScopedJavaLocalRef<jstring> j_device_id = ConvertUTF8ToJavaString(
327 env, 388 env,
328 device_id == AudioManagerBase::kDefaultDeviceId ? 389 device_id == AudioManagerBase::kDefaultDeviceId ?
329 std::string() : device_id); 390 std::string() : device_id);
330 return Java_AudioManagerAndroid_setDevice( 391 return Java_AudioManagerAndroid_setDevice(
331 env, j_audio_manager_.obj(), j_device_id.obj()); 392 env, j_audio_manager_.obj(), j_device_id.obj());
332 } 393 }
333 394
334 int AudioManagerAndroid::GetNativeOutputSampleRate() { 395 int AudioManagerAndroid::GetNativeOutputSampleRate() {
335 return Java_AudioManagerAndroid_getNativeOutputSampleRate( 396 return Java_AudioManagerAndroid_getNativeOutputSampleRate(
336 base::android::AttachCurrentThread(), 397 base::android::AttachCurrentThread(),
337 j_audio_manager_.obj()); 398 j_audio_manager_.obj());
338 } 399 }
339 400
340 bool AudioManagerAndroid::IsAudioLowLatencySupported() { 401 bool AudioManagerAndroid::IsAudioLowLatencySupported() {
341 return Java_AudioManagerAndroid_isAudioLowLatencySupported( 402 return Java_AudioManagerAndroid_isAudioLowLatencySupported(
342 base::android::AttachCurrentThread(), 403 base::android::AttachCurrentThread(),
343 j_audio_manager_.obj()); 404 j_audio_manager_.obj());
344 } 405 }
345 406
346 int AudioManagerAndroid::GetAudioLowLatencyOutputFrameSize() { 407 int AudioManagerAndroid::GetAudioLowLatencyOutputFrameSize() {
347 return Java_AudioManagerAndroid_getAudioLowLatencyOutputFrameSize( 408 return Java_AudioManagerAndroid_getAudioLowLatencyOutputFrameSize(
348 base::android::AttachCurrentThread(), 409 base::android::AttachCurrentThread(),
349 j_audio_manager_.obj()); 410 j_audio_manager_.obj());
350 } 411 }
351 412
413 int AudioManagerAndroid::GetOptimalOutputFrameSize(int sample_rate,
414 int channels) {
415 if (IsAudioLowLatencySupported()) {
416 return GetAudioLowLatencyOutputFrameSize();
417 } else {
418 return std::max(kDefaultOutputBufferSize,
419 Java_AudioManagerAndroid_getMinOutputFrameSize(
420 base::android::AttachCurrentThread(),
421 sample_rate, channels));
422 }
423 }
424
425 void AudioManagerAndroid::GetAudioInputDeviceNamesOnAudioThread(
426 base::WaitableEvent* event, AudioDeviceNames* device_names) {
427 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
428
429 // Always add default device parameters as first element.
430 DCHECK(device_names->empty());
431 AddDefaultDevice(device_names);
432
433 JNIEnv* env = AttachCurrentThread();
434 ScopedJavaLocalRef<jobjectArray> j_device_array =
435 Java_AudioManagerAndroid_getAudioInputDeviceNames(
436 env, j_audio_manager_.obj());
437 jsize len = env->GetArrayLength(j_device_array.obj());
438 AudioDeviceName device;
439 for (jsize i = 0; i < len; ++i) {
440 ScopedJavaLocalRef<jobject> j_device(
441 env, env->GetObjectArrayElement(j_device_array.obj(), i));
442 ScopedJavaLocalRef<jstring> j_device_name =
443 Java_AudioDeviceName_name(env, j_device.obj());
444 ConvertJavaStringToUTF8(env, j_device_name.obj(), &device.device_name);
445 ScopedJavaLocalRef<jstring> j_device_id =
446 Java_AudioDeviceName_id(env, j_device.obj());
447 ConvertJavaStringToUTF8(env, j_device_id.obj(), &device.unique_id);
448 device_names->push_back(device);
449 }
450
451 if (event)
452 event->Signal();
453 }
454
455 void AudioManagerAndroid::DoSetMuteOnAudioThread(bool muted) {
456 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
457 base::AutoLock lock(streams_lock_);
458 for (OutputStreams::iterator it = streams_.begin();
459 it != streams_.end(); ++it) {
460 (*it)->SetMute(muted);
461 }
462 }
463
352 } // namespace media 464 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698