Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(165)

Side by Side Diff: media/audio/android/opensles_output.cc

Issue 12806009: Add OpenSL configurations (Closed) Base URL: https://src.chromium.org/svn/trunk/src/
Patch Set: Addressed comments Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698