| 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 |