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 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 SLresult err = (*player_)->SetPlayState(player_, SL_PLAYSTATE_PLAYING); |
82 DCHECK_EQ(SL_RESULT_SUCCESS, err); | |
83 if (SL_RESULT_SUCCESS != err) { | 82 if (SL_RESULT_SUCCESS != err) { |
84 DLOG(WARNING) << "SetPlayState() failed to start playing"; | 83 DLOG(WARNING) << "SetPlayState() failed to start playing"; |
Ami GONE FROM CHROMIUM
2013/03/22 16:24:41
Why is this a WARNING when the rest of the failure
| |
85 } | 84 } |
86 } | 85 } |
87 | 86 |
88 void OpenSLESOutputStream::Stop() { | 87 void OpenSLESOutputStream::Stop() { |
89 if (!started_) | 88 if (!started_) |
90 return; | 89 return; |
91 | 90 |
92 started_ = false; | 91 started_ = false; |
93 // Stop playing by setting the play state to |SL_PLAYSTATE_STOPPED|. | 92 // Stop playing by setting the play state to |SL_PLAYSTATE_STOPPED|. |
94 SLresult err = (*player_)->SetPlayState(player_, SL_PLAYSTATE_STOPPED); | 93 SLresult err = (*player_)->SetPlayState(player_, SL_PLAYSTATE_STOPPED); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
134 } | 133 } |
135 | 134 |
136 bool OpenSLESOutputStream::CreatePlayer() { | 135 bool OpenSLESOutputStream::CreatePlayer() { |
137 // Initializes the engine object with specific option. After working with the | 136 // Initializes the engine object with specific option. After working with the |
138 // object, we need to free the object and its resources. | 137 // object, we need to free the object and its resources. |
139 SLEngineOption option[] = { | 138 SLEngineOption option[] = { |
140 { SL_ENGINEOPTION_THREADSAFE, static_cast<SLuint32>(SL_BOOLEAN_TRUE) } | 139 { SL_ENGINEOPTION_THREADSAFE, static_cast<SLuint32>(SL_BOOLEAN_TRUE) } |
141 }; | 140 }; |
142 SLresult err = slCreateEngine(engine_object_.Receive(), 1, option, 0, | 141 SLresult err = slCreateEngine(engine_object_.Receive(), 1, option, 0, |
143 NULL, NULL); | 142 NULL, NULL); |
144 DCHECK_EQ(SL_RESULT_SUCCESS, err); | 143 if (SL_RESULT_SUCCESS != err) { |
145 if (SL_RESULT_SUCCESS != err) | 144 DLOG(ERROR) << "CreatePlayer slCreateEngine: " << err; |
Ami GONE FROM CHROMIUM
2013/03/22 16:24:41
When there is this much duplicated code, it's usua
leozwang1
2013/03/23 07:00:39
Done.
| |
146 return false; | 145 return false; |
146 } | |
147 | 147 |
148 // Realize the SL engine object in synchronous mode. | 148 // Realize the SL engine object in synchronous mode. |
149 err = engine_object_->Realize(engine_object_.Get(), SL_BOOLEAN_FALSE); | 149 err = engine_object_->Realize(engine_object_.Get(), SL_BOOLEAN_FALSE); |
150 DCHECK_EQ(SL_RESULT_SUCCESS, err); | 150 if (SL_RESULT_SUCCESS != err) { |
151 if (SL_RESULT_SUCCESS != err) | 151 DLOG(ERROR) << "CreatePlayer Realize: " << err; |
152 return false; | 152 return false; |
153 } | |
153 | 154 |
154 // Get the SL engine interface which is implicit. | 155 // Get the SL engine interface which is implicit. |
155 SLEngineItf engine; | 156 SLEngineItf engine; |
156 err = engine_object_->GetInterface(engine_object_.Get(), | 157 err = engine_object_->GetInterface(engine_object_.Get(), |
157 SL_IID_ENGINE, | 158 SL_IID_ENGINE, |
158 &engine); | 159 &engine); |
159 DCHECK_EQ(SL_RESULT_SUCCESS, err); | 160 if (SL_RESULT_SUCCESS != err) { |
160 if (SL_RESULT_SUCCESS != err) | 161 DLOG(ERROR) << "GetInterface(SL_IID_ENGINE): " << err; |
Ami GONE FROM CHROMIUM
2013/03/22 16:24:41
These log messages are pretty inconsistent; some h
leozwang1
2013/03/23 07:00:39
Done.
| |
161 return false; | 162 return false; |
163 } | |
162 | 164 |
163 // Create ouput mixer object to be used by the player. | 165 // Create ouput mixer object to be used by the player. |
164 // TODO(xians): Do we need the environmental reverb auxiliary effect? | 166 // TODO(xians): Do we need the environmental reverb auxiliary effect? |
165 err = (*engine)->CreateOutputMix(engine, | 167 err = (*engine)->CreateOutputMix(engine, |
166 output_mixer_.Receive(), | 168 output_mixer_.Receive(), |
167 0, | 169 0, |
168 NULL, | 170 NULL, |
169 NULL); | 171 NULL); |
170 DCHECK_EQ(SL_RESULT_SUCCESS, err); | 172 if (SL_RESULT_SUCCESS != err) { |
171 if (SL_RESULT_SUCCESS != err) | 173 DLOG(ERROR) << "CreateOutputMix: " << err; |
172 return false; | 174 return false; |
175 } | |
173 | 176 |
174 // Realizing the output mix object in synchronous mode. | 177 // Realizing the output mix object in synchronous mode. |
175 err = output_mixer_->Realize(output_mixer_.Get(), SL_BOOLEAN_FALSE); | 178 err = output_mixer_->Realize(output_mixer_.Get(), SL_BOOLEAN_FALSE); |
176 DCHECK_EQ(SL_RESULT_SUCCESS, err); | 179 if (SL_RESULT_SUCCESS != err) { |
177 if (SL_RESULT_SUCCESS != err) | 180 DLOG(ERROR) << "mixer Realize: " << err; |
178 return false; | 181 return false; |
182 } | |
179 | 183 |
180 // Audio source configuration. | 184 // Audio source configuration. |
181 SLDataLocator_AndroidSimpleBufferQueue simple_buffer_queue = { | 185 SLDataLocator_AndroidSimpleBufferQueue simple_buffer_queue = { |
182 SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, | 186 SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, |
183 static_cast<SLuint32>(kNumOfQueuesInBuffer) | 187 static_cast<SLuint32>(kNumOfQueuesInBuffer) |
184 }; | 188 }; |
185 SLDataSource audio_source = { &simple_buffer_queue, &format_ }; | 189 SLDataSource audio_source = { &simple_buffer_queue, &format_ }; |
186 | 190 |
187 // Audio sink configuration. | 191 // Audio sink configuration. |
188 SLDataLocator_OutputMix locator_output_mix = { | 192 SLDataLocator_OutputMix locator_output_mix = { |
189 SL_DATALOCATOR_OUTPUTMIX, output_mixer_.Get() | 193 SL_DATALOCATOR_OUTPUTMIX, output_mixer_.Get() |
190 }; | 194 }; |
191 SLDataSink audio_sink = { &locator_output_mix, NULL }; | 195 SLDataSink audio_sink = { &locator_output_mix, NULL }; |
192 | 196 |
193 // Create an audio player. | 197 // Create an audio player. |
194 const SLuint32 number_of_interfaces = 1; | 198 const SLInterfaceID interface_id[] = { |
195 const SLInterfaceID interface_id[number_of_interfaces] = { | 199 SL_IID_BUFFERQUEUE, |
196 SL_IID_BUFFERQUEUE | 200 SL_IID_VOLUME, |
201 SL_IID_ANDROIDCONFIGURATION | |
197 }; | 202 }; |
203 const SLuint32 number_of_interfaces = arraysize(interface_id); | |
Ami GONE FROM CHROMIUM
2013/03/22 16:24:41
inline into call below.
| |
198 const SLboolean interface_required[number_of_interfaces] = { | 204 const SLboolean interface_required[number_of_interfaces] = { |
Ami GONE FROM CHROMIUM
2013/03/22 16:24:41
drop number_of_interfaces
leozwang1
2013/03/22 21:37:09
Done.
| |
205 SL_BOOLEAN_TRUE, | |
206 SL_BOOLEAN_TRUE, | |
199 SL_BOOLEAN_TRUE | 207 SL_BOOLEAN_TRUE |
200 }; | 208 }; |
201 err = (*engine)->CreateAudioPlayer(engine, | 209 err = (*engine)->CreateAudioPlayer(engine, |
202 player_object_.Receive(), | 210 player_object_.Receive(), |
203 &audio_source, | 211 &audio_source, |
204 &audio_sink, | 212 &audio_sink, |
205 number_of_interfaces, | 213 number_of_interfaces, |
206 interface_id, | 214 interface_id, |
207 interface_required); | 215 interface_required); |
208 DCHECK_EQ(SL_RESULT_SUCCESS, err); | |
209 if (SL_RESULT_SUCCESS != err) { | 216 if (SL_RESULT_SUCCESS != err) { |
210 DLOG(ERROR) << "CreateAudioPlayer() failed with error code " << err; | 217 DLOG(ERROR) << "CreateAudioPlayer() failed with error code " << err; |
211 return false; | 218 return false; |
212 } | 219 } |
213 | 220 |
221 // Create AudioPlayer and specify SL_IID_ANDROIDCONFIGURATION. | |
222 SLAndroidConfigurationItf player_config; | |
223 err = player_object_->GetInterface(player_object_.Get(), | |
224 SL_IID_ANDROIDCONFIGURATION, | |
225 &player_config); | |
226 if (SL_RESULT_SUCCESS != err) { | |
227 DLOG(ERROR) << "GetInterface(SL_IID_ANDROIDCONFIGURATION): " << err; | |
228 return false; | |
229 } | |
230 | |
231 SLint32 stream_type = SL_ANDROID_STREAM_VOICE; | |
Ami GONE FROM CHROMIUM
2013/03/22 16:24:41
this variable is obscuring what the call below act
Ami GONE FROM CHROMIUM
2013/03/22 16:24:41
This seems to be the heart of the potential proble
leozwang1
2013/03/22 21:37:09
It's my concern too, we're going to do some tests.
Ami GONE FROM CHROMIUM
2013/03/22 22:29:55
I don't think you'd want to make the stream contai
leozwang1
2013/03/22 22:44:48
can you teach me how this "global state button (mi
Ami GONE FROM CHROMIUM
2013/03/22 23:34:20
I just mean that the toggle of what global mode to
| |
232 err = (*player_config)->SetConfiguration(player_config, | |
233 SL_ANDROID_KEY_STREAM_TYPE, | |
234 &stream_type, sizeof(SLint32)); | |
235 if (SL_RESULT_SUCCESS != err) { | |
236 DLOG(ERROR) << "SetConfiguration(SL_ANDROID_STREAM_VOICE): " << err; | |
237 return false; | |
238 } | |
239 | |
214 // Realize the player object in synchronous mode. | 240 // Realize the player object in synchronous mode. |
215 err = player_object_->Realize(player_object_.Get(), SL_BOOLEAN_FALSE); | 241 err = player_object_->Realize(player_object_.Get(), SL_BOOLEAN_FALSE); |
216 DCHECK_EQ(SL_RESULT_SUCCESS, err); | |
217 if (SL_RESULT_SUCCESS != err) { | 242 if (SL_RESULT_SUCCESS != err) { |
218 DLOG(ERROR) << "Player Realize() failed with error code " << err; | 243 DLOG(ERROR) << "Player Realize() failed with error code " << err; |
219 return false; | 244 return false; |
220 } | 245 } |
221 | 246 |
222 // Get an implicit player interface. | 247 // Get an implicit player interface. |
223 err = player_object_->GetInterface( | 248 err = player_object_->GetInterface( |
224 player_object_.Get(), SL_IID_PLAY, &player_); | 249 player_object_.Get(), SL_IID_PLAY, &player_); |
225 DCHECK_EQ(SL_RESULT_SUCCESS, err); | 250 if (SL_RESULT_SUCCESS != err) { |
226 if (SL_RESULT_SUCCESS != err) | 251 DLOG(ERROR) << "GetInterface(SL_IID_PLAYN): " << err; |
227 return false; | 252 return false; |
253 } | |
228 | 254 |
229 // Get the simple buffer queue interface. | 255 // Get the simple buffer queue interface. |
230 err = player_object_->GetInterface(player_object_.Get(), | 256 err = player_object_->GetInterface(player_object_.Get(), |
231 SL_IID_BUFFERQUEUE, | 257 SL_IID_BUFFERQUEUE, |
232 &simple_buffer_queue_); | 258 &simple_buffer_queue_); |
233 DCHECK_EQ(SL_RESULT_SUCCESS, err); | 259 if (SL_RESULT_SUCCESS != err) { |
234 if (SL_RESULT_SUCCESS != err) | 260 DLOG(ERROR) << "GetInterface(SL_IID_BUFFERQUEUE): " << err; |
235 return false; | 261 return false; |
262 } | |
236 | 263 |
237 // Register the input callback for the simple buffer queue. | 264 // Register the input callback for the simple buffer queue. |
238 // This callback will be called when the soundcard needs data. | 265 // This callback will be called when the soundcard needs data. |
239 err = (*simple_buffer_queue_)->RegisterCallback(simple_buffer_queue_, | 266 err = (*simple_buffer_queue_)->RegisterCallback(simple_buffer_queue_, |
240 SimpleBufferQueueCallback, | 267 SimpleBufferQueueCallback, |
241 this); | 268 this); |
242 DCHECK_EQ(SL_RESULT_SUCCESS, err); | 269 if (SL_RESULT_SUCCESS != err) { |
270 DLOG(ERROR) << "AudioPlayer RegisterCallback: " << err; | |
271 return false; | |
272 } | |
243 | 273 |
244 return (SL_RESULT_SUCCESS == err); | 274 return true; |
245 } | 275 } |
246 | 276 |
247 void OpenSLESOutputStream::SimpleBufferQueueCallback( | 277 void OpenSLESOutputStream::SimpleBufferQueueCallback( |
248 SLAndroidSimpleBufferQueueItf buffer_queue, void* instance) { | 278 SLAndroidSimpleBufferQueueItf buffer_queue, void* instance) { |
249 OpenSLESOutputStream* stream = | 279 OpenSLESOutputStream* stream = |
250 reinterpret_cast<OpenSLESOutputStream*>(instance); | 280 reinterpret_cast<OpenSLESOutputStream*>(instance); |
251 stream->FillBufferQueue(); | 281 stream->FillBufferQueue(); |
252 } | 282 } |
253 | 283 |
254 void OpenSLESOutputStream::FillBufferQueue() { | 284 void OpenSLESOutputStream::FillBufferQueue() { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
304 } | 334 } |
305 } | 335 } |
306 | 336 |
307 void OpenSLESOutputStream::HandleError(SLresult error) { | 337 void OpenSLESOutputStream::HandleError(SLresult error) { |
308 DLOG(ERROR) << "OpenSLES error " << error; | 338 DLOG(ERROR) << "OpenSLES error " << error; |
309 if (callback_) | 339 if (callback_) |
310 callback_->OnError(this, error); | 340 callback_->OnError(this, error); |
311 } | 341 } |
312 | 342 |
313 } // namespace media | 343 } // namespace media |
OLD | NEW |