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

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

Issue 17491007: Enable audio volume control on Android. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: rebase and update description Created 7 years, 6 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 | Annotate | Revision Log
« no previous file with comments | « media/audio/android/opensles_output.h ('k') | media/audio/android/opensles_util.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/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
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
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
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
OLDNEW
« no previous file with comments | « media/audio/android/opensles_output.h ('k') | media/audio/android/opensles_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698