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/opensles_output.h" | 5 #include "media/audio/android/opensles_output.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "media/audio/android/audio_manager_android.h" | 8 #include "media/audio/android/audio_manager_android.h" |
9 | 9 |
| 10 #define LOG_ON_FAILURE_AND_RETURN(op, ...) \ |
| 11 do { \ |
| 12 SLresult err = (op); \ |
| 13 if (err != SL_RESULT_SUCCESS) { \ |
| 14 DLOG(ERROR) << #op << " failed: " << err; \ |
| 15 return __VA_ARGS__; \ |
| 16 } \ |
| 17 } while (0) |
| 18 |
10 namespace media { | 19 namespace media { |
11 | 20 |
12 OpenSLESOutputStream::OpenSLESOutputStream(AudioManagerAndroid* manager, | 21 OpenSLESOutputStream::OpenSLESOutputStream(AudioManagerAndroid* manager, |
13 const AudioParameters& params) | 22 const AudioParameters& params) |
14 : audio_manager_(manager), | 23 : audio_manager_(manager), |
15 callback_(NULL), | 24 callback_(NULL), |
16 player_(NULL), | 25 player_(NULL), |
17 simple_buffer_queue_(NULL), | 26 simple_buffer_queue_(NULL), |
18 active_queue_(0), | 27 active_queue_(0), |
19 buffer_size_bytes_(0), | 28 buffer_size_bytes_(0), |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
70 // Enable the flags before streaming. | 79 // Enable the flags before streaming. |
71 callback_ = callback; | 80 callback_ = callback; |
72 active_queue_ = 0; | 81 active_queue_ = 0; |
73 started_ = true; | 82 started_ = true; |
74 | 83 |
75 // Avoid start-up glitches by filling up one buffer queue before starting | 84 // Avoid start-up glitches by filling up one buffer queue before starting |
76 // the stream. | 85 // the stream. |
77 FillBufferQueue(); | 86 FillBufferQueue(); |
78 | 87 |
79 // Start streaming data by setting the play state to |SL_PLAYSTATE_PLAYING|. | 88 // Start streaming data by setting the play state to |SL_PLAYSTATE_PLAYING|. |
80 SLresult err = (*player_)->SetPlayState(player_, SL_PLAYSTATE_PLAYING); | 89 LOG_ON_FAILURE_AND_RETURN( |
81 DCHECK_EQ(SL_RESULT_SUCCESS, err); | 90 (*player_)->SetPlayState(player_, SL_PLAYSTATE_PLAYING)); |
82 if (SL_RESULT_SUCCESS != err) { | |
83 DLOG(WARNING) << "SetPlayState() failed to start playing"; | |
84 } | |
85 } | 91 } |
86 | 92 |
87 void OpenSLESOutputStream::Stop() { | 93 void OpenSLESOutputStream::Stop() { |
88 if (!started_) | 94 if (!started_) |
89 return; | 95 return; |
90 | 96 |
91 started_ = false; | 97 started_ = false; |
92 // Stop playing by setting the play state to |SL_PLAYSTATE_STOPPED|. | 98 // Stop playing by setting the play state to |SL_PLAYSTATE_STOPPED|. |
93 SLresult err = (*player_)->SetPlayState(player_, SL_PLAYSTATE_STOPPED); | 99 LOG_ON_FAILURE_AND_RETURN( |
94 if (SL_RESULT_SUCCESS != err) { | 100 (*player_)->SetPlayState(player_, SL_PLAYSTATE_STOPPED)); |
95 DLOG(WARNING) << "SetPlayState() failed to set the state to stop"; | |
96 } | |
97 | 101 |
98 // Clear the buffer queue so that the old data won't be played when | 102 // Clear the buffer queue so that the old data won't be played when |
99 // resuming playing. | 103 // resuming playing. |
100 err = (*simple_buffer_queue_)->Clear(simple_buffer_queue_); | 104 LOG_ON_FAILURE_AND_RETURN( |
101 if (SL_RESULT_SUCCESS != err) { | 105 (*simple_buffer_queue_)->Clear(simple_buffer_queue_)); |
102 DLOG(WARNING) << "Clear() failed to clear the buffer queue"; | |
103 } | |
104 } | 106 } |
105 | 107 |
106 void OpenSLESOutputStream::Close() { | 108 void OpenSLESOutputStream::Close() { |
107 // Stop the stream if it is still playing. | 109 // Stop the stream if it is still playing. |
108 Stop(); | 110 Stop(); |
109 | 111 |
110 // Explicitly free the player objects and invalidate their associated | 112 // Explicitly free the player objects and invalidate their associated |
111 // interfaces. They have to be done in the correct order. | 113 // interfaces. They have to be done in the correct order. |
112 player_object_.Reset(); | 114 player_object_.Reset(); |
113 output_mixer_.Reset(); | 115 output_mixer_.Reset(); |
(...skipping 17 matching lines...) Expand all Loading... |
131 void OpenSLESOutputStream::GetVolume(double* volume) { | 133 void OpenSLESOutputStream::GetVolume(double* volume) { |
132 *volume = static_cast<double>(volume_); | 134 *volume = static_cast<double>(volume_); |
133 } | 135 } |
134 | 136 |
135 bool OpenSLESOutputStream::CreatePlayer() { | 137 bool OpenSLESOutputStream::CreatePlayer() { |
136 // Initializes the engine object with specific option. After working with the | 138 // Initializes the engine object with specific option. After working with the |
137 // object, we need to free the object and its resources. | 139 // object, we need to free the object and its resources. |
138 SLEngineOption option[] = { | 140 SLEngineOption option[] = { |
139 { SL_ENGINEOPTION_THREADSAFE, static_cast<SLuint32>(SL_BOOLEAN_TRUE) } | 141 { SL_ENGINEOPTION_THREADSAFE, static_cast<SLuint32>(SL_BOOLEAN_TRUE) } |
140 }; | 142 }; |
141 SLresult err = slCreateEngine(engine_object_.Receive(), 1, option, 0, | 143 LOG_ON_FAILURE_AND_RETURN( |
142 NULL, NULL); | 144 slCreateEngine(engine_object_.Receive(), 1, option, 0, NULL, NULL), |
143 DCHECK_EQ(SL_RESULT_SUCCESS, err); | 145 false); |
144 if (SL_RESULT_SUCCESS != err) | |
145 return false; | |
146 | 146 |
147 // Realize the SL engine object in synchronous mode. | 147 // Realize the SL engine object in synchronous mode. |
148 err = engine_object_->Realize(engine_object_.Get(), SL_BOOLEAN_FALSE); | 148 LOG_ON_FAILURE_AND_RETURN( |
149 DCHECK_EQ(SL_RESULT_SUCCESS, err); | 149 engine_object_->Realize(engine_object_.Get(), SL_BOOLEAN_FALSE), |
150 if (SL_RESULT_SUCCESS != err) | 150 false); |
151 return false; | |
152 | 151 |
153 // Get the SL engine interface which is implicit. | 152 // Get the SL engine interface which is implicit. |
154 SLEngineItf engine; | 153 SLEngineItf engine; |
155 err = engine_object_->GetInterface(engine_object_.Get(), | 154 LOG_ON_FAILURE_AND_RETURN( |
156 SL_IID_ENGINE, | 155 engine_object_->GetInterface(engine_object_.Get(), |
157 &engine); | 156 SL_IID_ENGINE, |
158 DCHECK_EQ(SL_RESULT_SUCCESS, err); | 157 &engine), |
159 if (SL_RESULT_SUCCESS != err) | 158 false); |
160 return false; | |
161 | 159 |
162 // Create ouput mixer object to be used by the player. | 160 // Create ouput mixer object to be used by the player. |
163 // TODO(xians): Do we need the environmental reverb auxiliary effect? | 161 LOG_ON_FAILURE_AND_RETURN( |
164 err = (*engine)->CreateOutputMix(engine, | 162 (*engine)->CreateOutputMix(engine, |
165 output_mixer_.Receive(), | 163 output_mixer_.Receive(), |
166 0, | 164 0, |
167 NULL, | 165 NULL, |
168 NULL); | 166 NULL), |
169 DCHECK_EQ(SL_RESULT_SUCCESS, err); | 167 false); |
170 if (SL_RESULT_SUCCESS != err) | |
171 return false; | |
172 | 168 |
173 // Realizing the output mix object in synchronous mode. | 169 // Realizing the output mix object in synchronous mode. |
174 err = output_mixer_->Realize(output_mixer_.Get(), SL_BOOLEAN_FALSE); | 170 LOG_ON_FAILURE_AND_RETURN( |
175 DCHECK_EQ(SL_RESULT_SUCCESS, err); | 171 output_mixer_->Realize(output_mixer_.Get(), SL_BOOLEAN_FALSE), |
176 if (SL_RESULT_SUCCESS != err) | 172 false); |
177 return false; | |
178 | 173 |
179 // Audio source configuration. | 174 // Audio source configuration. |
180 SLDataLocator_AndroidSimpleBufferQueue simple_buffer_queue = { | 175 SLDataLocator_AndroidSimpleBufferQueue simple_buffer_queue = { |
181 SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, | 176 SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, |
182 static_cast<SLuint32>(kNumOfQueuesInBuffer) | 177 static_cast<SLuint32>(kNumOfQueuesInBuffer) |
183 }; | 178 }; |
184 SLDataSource audio_source = { &simple_buffer_queue, &format_ }; | 179 SLDataSource audio_source = { &simple_buffer_queue, &format_ }; |
185 | 180 |
186 // Audio sink configuration. | 181 // Audio sink configuration. |
187 SLDataLocator_OutputMix locator_output_mix = { | 182 SLDataLocator_OutputMix locator_output_mix = { |
188 SL_DATALOCATOR_OUTPUTMIX, output_mixer_.Get() | 183 SL_DATALOCATOR_OUTPUTMIX, output_mixer_.Get() |
189 }; | 184 }; |
190 SLDataSink audio_sink = { &locator_output_mix, NULL }; | 185 SLDataSink audio_sink = { &locator_output_mix, NULL }; |
191 | 186 |
192 // Create an audio player. | 187 // Create an audio player. |
193 const SLuint32 number_of_interfaces = 1; | 188 const SLInterfaceID interface_id[] = { |
194 const SLInterfaceID interface_id[number_of_interfaces] = { | 189 SL_IID_BUFFERQUEUE, |
195 SL_IID_BUFFERQUEUE | 190 SL_IID_VOLUME, |
| 191 SL_IID_ANDROIDCONFIGURATION |
196 }; | 192 }; |
197 const SLboolean interface_required[number_of_interfaces] = { | 193 const SLboolean interface_required[] = { |
| 194 SL_BOOLEAN_TRUE, |
| 195 SL_BOOLEAN_TRUE, |
198 SL_BOOLEAN_TRUE | 196 SL_BOOLEAN_TRUE |
199 }; | 197 }; |
200 err = (*engine)->CreateAudioPlayer(engine, | 198 LOG_ON_FAILURE_AND_RETURN( |
201 player_object_.Receive(), | 199 (*engine)->CreateAudioPlayer(engine, |
202 &audio_source, | 200 player_object_.Receive(), |
203 &audio_sink, | 201 &audio_source, |
204 number_of_interfaces, | 202 &audio_sink, |
205 interface_id, | 203 arraysize(interface_id), |
206 interface_required); | 204 interface_id, |
207 DCHECK_EQ(SL_RESULT_SUCCESS, err); | 205 interface_required), |
208 if (SL_RESULT_SUCCESS != err) { | 206 false); |
209 DLOG(ERROR) << "CreateAudioPlayer() failed with error code " << err; | 207 |
210 return false; | 208 // Create AudioPlayer and specify SL_IID_ANDROIDCONFIGURATION. |
211 } | 209 SLAndroidConfigurationItf player_config; |
| 210 LOG_ON_FAILURE_AND_RETURN( |
| 211 player_object_->GetInterface(player_object_.Get(), |
| 212 SL_IID_ANDROIDCONFIGURATION, |
| 213 &player_config), |
| 214 false); |
| 215 |
| 216 SLint32 stream_type = SL_ANDROID_STREAM_VOICE; |
| 217 LOG_ON_FAILURE_AND_RETURN( |
| 218 (*player_config)->SetConfiguration(player_config, |
| 219 SL_ANDROID_KEY_STREAM_TYPE, |
| 220 &stream_type, sizeof(SLint32)), |
| 221 false); |
212 | 222 |
213 // Realize the player object in synchronous mode. | 223 // Realize the player object in synchronous mode. |
214 err = player_object_->Realize(player_object_.Get(), SL_BOOLEAN_FALSE); | 224 LOG_ON_FAILURE_AND_RETURN( |
215 DCHECK_EQ(SL_RESULT_SUCCESS, err); | 225 player_object_->Realize(player_object_.Get(), SL_BOOLEAN_FALSE), |
216 if (SL_RESULT_SUCCESS != err) { | 226 false); |
217 DLOG(ERROR) << "Player Realize() failed with error code " << err; | |
218 return false; | |
219 } | |
220 | 227 |
221 // Get an implicit player interface. | 228 // Get an implicit player interface. |
222 err = player_object_->GetInterface( | 229 LOG_ON_FAILURE_AND_RETURN( |
223 player_object_.Get(), SL_IID_PLAY, &player_); | 230 player_object_->GetInterface(player_object_.Get(), SL_IID_PLAY, &player_), |
224 DCHECK_EQ(SL_RESULT_SUCCESS, err); | 231 false); |
225 if (SL_RESULT_SUCCESS != err) | |
226 return false; | |
227 | 232 |
228 // Get the simple buffer queue interface. | 233 // Get the simple buffer queue interface. |
229 err = player_object_->GetInterface(player_object_.Get(), | 234 LOG_ON_FAILURE_AND_RETURN( |
230 SL_IID_BUFFERQUEUE, | 235 player_object_->GetInterface(player_object_.Get(), |
231 &simple_buffer_queue_); | 236 SL_IID_BUFFERQUEUE, |
232 DCHECK_EQ(SL_RESULT_SUCCESS, err); | 237 &simple_buffer_queue_), |
233 if (SL_RESULT_SUCCESS != err) | 238 false); |
234 return false; | |
235 | 239 |
236 // Register the input callback for the simple buffer queue. | 240 // Register the input callback for the simple buffer queue. |
237 // This callback will be called when the soundcard needs data. | 241 // This callback will be called when the soundcard needs data. |
238 err = (*simple_buffer_queue_)->RegisterCallback(simple_buffer_queue_, | 242 LOG_ON_FAILURE_AND_RETURN( |
239 SimpleBufferQueueCallback, | 243 (*simple_buffer_queue_)->RegisterCallback(simple_buffer_queue_, |
240 this); | 244 SimpleBufferQueueCallback, |
241 DCHECK_EQ(SL_RESULT_SUCCESS, err); | 245 this), |
| 246 false); |
242 | 247 |
243 return (SL_RESULT_SUCCESS == err); | 248 return true; |
244 } | 249 } |
245 | 250 |
246 void OpenSLESOutputStream::SimpleBufferQueueCallback( | 251 void OpenSLESOutputStream::SimpleBufferQueueCallback( |
247 SLAndroidSimpleBufferQueueItf buffer_queue, void* instance) { | 252 SLAndroidSimpleBufferQueueItf buffer_queue, void* instance) { |
248 OpenSLESOutputStream* stream = | 253 OpenSLESOutputStream* stream = |
249 reinterpret_cast<OpenSLESOutputStream*>(instance); | 254 reinterpret_cast<OpenSLESOutputStream*>(instance); |
250 stream->FillBufferQueue(); | 255 stream->FillBufferQueue(); |
251 } | 256 } |
252 | 257 |
253 void OpenSLESOutputStream::FillBufferQueue() { | 258 void OpenSLESOutputStream::FillBufferQueue() { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
291 void OpenSLESOutputStream::ReleaseAudioBuffer() { | 296 void OpenSLESOutputStream::ReleaseAudioBuffer() { |
292 if (audio_data_[0]) { | 297 if (audio_data_[0]) { |
293 for (int i = 0; i < kNumOfQueuesInBuffer; ++i) { | 298 for (int i = 0; i < kNumOfQueuesInBuffer; ++i) { |
294 delete [] audio_data_[i]; | 299 delete [] audio_data_[i]; |
295 audio_data_[i] = NULL; | 300 audio_data_[i] = NULL; |
296 } | 301 } |
297 } | 302 } |
298 } | 303 } |
299 | 304 |
300 void OpenSLESOutputStream::HandleError(SLresult error) { | 305 void OpenSLESOutputStream::HandleError(SLresult error) { |
301 DLOG(ERROR) << "OpenSLES error " << error; | 306 DLOG(ERROR) << "OpenSLES Output error " << error; |
302 if (callback_) | 307 if (callback_) |
303 callback_->OnError(this); | 308 callback_->OnError(this); |
304 } | 309 } |
305 | 310 |
306 } // namespace media | 311 } // namespace media |
OLD | NEW |