Chromium Code Reviews| 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 |