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