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
3 // found in the LICENSE file.
5 #include "media/audio/android/opensles_output.h"
7 #include "base/logging.h"
8 #include "base/trace_event/trace_event.h"
9 #include "media/audio/android/audio_manager_android.h"
11 #define LOG_ON_FAILURE_AND_RETURN(op, ...) \
13 SLresult err = (op); \
14 if (err != SL_RESULT_SUCCESS) { \
15 DLOG(ERROR) << #op << " failed: " << err; \
22 OpenSLESOutputStream::OpenSLESOutputStream(AudioManagerAndroid
* manager
,
23 const AudioParameters
& params
,
25 : audio_manager_(manager
),
26 stream_type_(stream_type
),
29 simple_buffer_queue_(NULL
),
30 active_buffer_index_(0),
31 buffer_size_bytes_(0),
35 DVLOG(2) << "OpenSLESOutputStream::OpenSLESOutputStream("
36 << "stream_type=" << stream_type
<< ")";
37 format_
.formatType
= SL_DATAFORMAT_PCM
;
38 format_
.numChannels
= static_cast<SLuint32
>(params
.channels());
39 // Provides sampling rate in milliHertz to OpenSLES.
40 format_
.samplesPerSec
= static_cast<SLuint32
>(params
.sample_rate() * 1000);
41 format_
.bitsPerSample
= params
.bits_per_sample();
42 format_
.containerSize
= params
.bits_per_sample();
43 format_
.endianness
= SL_BYTEORDER_LITTLEENDIAN
;
44 if (format_
.numChannels
== 1)
45 format_
.channelMask
= SL_SPEAKER_FRONT_CENTER
;
46 else if (format_
.numChannels
== 2)
47 format_
.channelMask
= SL_SPEAKER_FRONT_LEFT
| SL_SPEAKER_FRONT_RIGHT
;
49 NOTREACHED() << "Unsupported number of channels: " << format_
.numChannels
;
51 buffer_size_bytes_
= params
.GetBytesPerBuffer();
52 audio_bus_
= AudioBus::Create(params
);
54 memset(&audio_data_
, 0, sizeof(audio_data_
));
57 OpenSLESOutputStream::~OpenSLESOutputStream() {
58 DVLOG(2) << "OpenSLESOutputStream::~OpenSLESOutputStream()";
59 DCHECK(thread_checker_
.CalledOnValidThread());
60 DCHECK(!engine_object_
.Get());
61 DCHECK(!player_object_
.Get());
62 DCHECK(!output_mixer_
.Get());
64 DCHECK(!simple_buffer_queue_
);
65 DCHECK(!audio_data_
[0]);
68 bool OpenSLESOutputStream::Open() {
69 DVLOG(2) << "OpenSLESOutputStream::Open()";
70 DCHECK(thread_checker_
.CalledOnValidThread());
71 if (engine_object_
.Get())
78 active_buffer_index_
= 0;
83 void OpenSLESOutputStream::Start(AudioSourceCallback
* callback
) {
84 DVLOG(2) << "OpenSLESOutputStream::Start()";
85 DCHECK(thread_checker_
.CalledOnValidThread());
88 DCHECK(simple_buffer_queue_
);
92 base::AutoLock
lock(lock_
);
93 DCHECK(callback_
== NULL
|| callback_
== callback
);
96 // Avoid start-up glitches by filling up one buffer queue before starting
98 FillBufferQueueNoLock();
100 // Start streaming data by setting the play state to SL_PLAYSTATE_PLAYING.
101 // For a player object, when the object is in the SL_PLAYSTATE_PLAYING
102 // state, adding buffers will implicitly start playback.
103 LOG_ON_FAILURE_AND_RETURN(
104 (*player_
)->SetPlayState(player_
, SL_PLAYSTATE_PLAYING
));
109 void OpenSLESOutputStream::Stop() {
110 DVLOG(2) << "OpenSLESOutputStream::Stop()";
111 DCHECK(thread_checker_
.CalledOnValidThread());
115 base::AutoLock
lock(lock_
);
117 // Stop playing by setting the play state to SL_PLAYSTATE_STOPPED.
118 LOG_ON_FAILURE_AND_RETURN(
119 (*player_
)->SetPlayState(player_
, SL_PLAYSTATE_STOPPED
));
121 // Clear the buffer queue so that the old data won't be played when
123 LOG_ON_FAILURE_AND_RETURN(
124 (*simple_buffer_queue_
)->Clear(simple_buffer_queue_
));
127 // Verify that the buffer queue is in fact cleared as it should.
128 SLAndroidSimpleBufferQueueState buffer_queue_state
;
129 LOG_ON_FAILURE_AND_RETURN((*simple_buffer_queue_
)->GetState(
130 simple_buffer_queue_
, &buffer_queue_state
));
131 DCHECK_EQ(0u, buffer_queue_state
.count
);
132 DCHECK_EQ(0u, buffer_queue_state
.index
);
139 void OpenSLESOutputStream::Close() {
140 DVLOG(2) << "OpenSLESOutputStream::Close()";
141 DCHECK(thread_checker_
.CalledOnValidThread());
143 // Stop the stream if it is still playing.
146 // Destroy the buffer queue player object and invalidate all associated
148 player_object_
.Reset();
149 simple_buffer_queue_
= NULL
;
152 // Destroy the mixer object. We don't store any associated interface for
154 output_mixer_
.Reset();
156 // Destroy the engine object. We don't store any associated interface for
158 engine_object_
.Reset();
159 ReleaseAudioBuffer();
162 audio_manager_
->ReleaseOutputStream(this);
165 void OpenSLESOutputStream::SetVolume(double volume
) {
166 DVLOG(2) << "OpenSLESOutputStream::SetVolume(" << volume
<< ")";
167 DCHECK(thread_checker_
.CalledOnValidThread());
169 double volume_override
= 0;
170 if (audio_manager_
->HasOutputVolumeOverride(&volume_override
)) {
171 volume
= volume_override
;
174 float volume_float
= static_cast<float>(volume
);
175 if (volume_float
< 0.0f
|| volume_float
> 1.0f
) {
178 volume_
= volume_float
;
181 void OpenSLESOutputStream::GetVolume(double* volume
) {
182 DCHECK(thread_checker_
.CalledOnValidThread());
183 *volume
= static_cast<double>(volume_
);
186 void OpenSLESOutputStream::SetMute(bool muted
) {
187 DVLOG(2) << "OpenSLESOutputStream::SetMute(" << muted
<< ")";
188 DCHECK(thread_checker_
.CalledOnValidThread());
192 bool OpenSLESOutputStream::CreatePlayer() {
193 DCHECK(thread_checker_
.CalledOnValidThread());
194 DCHECK(!engine_object_
.Get());
195 DCHECK(!player_object_
.Get());
196 DCHECK(!output_mixer_
.Get());
198 DCHECK(!simple_buffer_queue_
);
200 // Initializes the engine object with specific option. After working with the
201 // object, we need to free the object and its resources.
202 SLEngineOption option
[] = {
203 {SL_ENGINEOPTION_THREADSAFE
, static_cast<SLuint32
>(SL_BOOLEAN_TRUE
)}};
204 LOG_ON_FAILURE_AND_RETURN(
205 slCreateEngine(engine_object_
.Receive(), 1, option
, 0, NULL
, NULL
),
208 // Realize the SL engine object in synchronous mode.
209 LOG_ON_FAILURE_AND_RETURN(
210 engine_object_
->Realize(engine_object_
.Get(), SL_BOOLEAN_FALSE
), false);
212 // Get the SL engine interface which is implicit.
214 LOG_ON_FAILURE_AND_RETURN(engine_object_
->GetInterface(
215 engine_object_
.Get(), SL_IID_ENGINE
, &engine
),
218 // Create ouput mixer object to be used by the player.
219 LOG_ON_FAILURE_AND_RETURN((*engine
)->CreateOutputMix(
220 engine
, output_mixer_
.Receive(), 0, NULL
, NULL
),
223 // Realizing the output mix object in synchronous mode.
224 LOG_ON_FAILURE_AND_RETURN(
225 output_mixer_
->Realize(output_mixer_
.Get(), SL_BOOLEAN_FALSE
), false);
227 // Audio source configuration.
228 SLDataLocator_AndroidSimpleBufferQueue simple_buffer_queue
= {
229 SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE
,
230 static_cast<SLuint32
>(kMaxNumOfBuffersInQueue
)};
231 SLDataSource audio_source
= {&simple_buffer_queue
, &format_
};
233 // Audio sink configuration.
234 SLDataLocator_OutputMix locator_output_mix
= {SL_DATALOCATOR_OUTPUTMIX
,
235 output_mixer_
.Get()};
236 SLDataSink audio_sink
= {&locator_output_mix
, NULL
};
238 // Create an audio player.
239 const SLInterfaceID interface_id
[] = {SL_IID_BUFFERQUEUE
, SL_IID_VOLUME
,
240 SL_IID_ANDROIDCONFIGURATION
};
241 const SLboolean interface_required
[] = {SL_BOOLEAN_TRUE
, SL_BOOLEAN_TRUE
,
243 LOG_ON_FAILURE_AND_RETURN(
244 (*engine
)->CreateAudioPlayer(engine
,
245 player_object_
.Receive(),
248 arraysize(interface_id
),
253 // Create AudioPlayer and specify SL_IID_ANDROIDCONFIGURATION.
254 SLAndroidConfigurationItf player_config
;
255 LOG_ON_FAILURE_AND_RETURN(
256 player_object_
->GetInterface(
257 player_object_
.Get(), SL_IID_ANDROIDCONFIGURATION
, &player_config
),
260 // Set configuration using the stream type provided at construction.
261 LOG_ON_FAILURE_AND_RETURN(
262 (*player_config
)->SetConfiguration(player_config
,
263 SL_ANDROID_KEY_STREAM_TYPE
,
268 // Realize the player object in synchronous mode.
269 LOG_ON_FAILURE_AND_RETURN(
270 player_object_
->Realize(player_object_
.Get(), SL_BOOLEAN_FALSE
), false);
272 // Get an implicit player interface.
273 LOG_ON_FAILURE_AND_RETURN(
274 player_object_
->GetInterface(player_object_
.Get(), SL_IID_PLAY
, &player_
),
277 // Get the simple buffer queue interface.
278 LOG_ON_FAILURE_AND_RETURN(
279 player_object_
->GetInterface(
280 player_object_
.Get(), SL_IID_BUFFERQUEUE
, &simple_buffer_queue_
),
283 // Register the input callback for the simple buffer queue.
284 // This callback will be called when the soundcard needs data.
285 LOG_ON_FAILURE_AND_RETURN(
286 (*simple_buffer_queue_
)->RegisterCallback(
287 simple_buffer_queue_
, SimpleBufferQueueCallback
, this),
293 void OpenSLESOutputStream::SimpleBufferQueueCallback(
294 SLAndroidSimpleBufferQueueItf buffer_queue
,
296 OpenSLESOutputStream
* stream
=
297 reinterpret_cast<OpenSLESOutputStream
*>(instance
);
298 stream
->FillBufferQueue();
301 void OpenSLESOutputStream::FillBufferQueue() {
302 base::AutoLock
lock(lock_
);
306 TRACE_EVENT0("audio", "OpenSLESOutputStream::FillBufferQueue");
308 // Verify that we are in a playing state.
310 SLresult err
= (*player_
)->GetPlayState(player_
, &state
);
311 if (SL_RESULT_SUCCESS
!= err
) {
315 if (state
!= SL_PLAYSTATE_PLAYING
) {
316 DLOG(WARNING
) << "Received callback in non-playing state";
320 // Fill up one buffer in the queue by asking the registered source for
321 // data using the OnMoreData() callback.
322 FillBufferQueueNoLock();
325 void OpenSLESOutputStream::FillBufferQueueNoLock() {
326 // Ensure that the calling thread has acquired the lock since it is not
327 // done in this method.
328 lock_
.AssertAcquired();
330 // Read data from the registered client source.
331 // TODO(henrika): Investigate if it is possible to get a more accurate
333 const uint32 hardware_delay
= buffer_size_bytes_
;
334 int frames_filled
= callback_
->OnMoreData(
335 audio_bus_
.get(), hardware_delay
);
336 if (frames_filled
<= 0) {
337 // Audio source is shutting down, or halted on error.
341 // Note: If the internal representation ever changes from 16-bit PCM to
342 // raw float, the data must be clipped and sanitized since it may come
343 // from an untrusted source such as NaCl.
344 audio_bus_
->Scale(muted_
? 0.0f
: volume_
);
345 audio_bus_
->ToInterleaved(frames_filled
,
346 format_
.bitsPerSample
/ 8,
347 audio_data_
[active_buffer_index_
]);
349 const int num_filled_bytes
=
350 frames_filled
* audio_bus_
->channels() * format_
.bitsPerSample
/ 8;
351 DCHECK_LE(static_cast<size_t>(num_filled_bytes
), buffer_size_bytes_
);
353 // Enqueue the buffer for playback.
355 (*simple_buffer_queue_
)->Enqueue(simple_buffer_queue_
,
356 audio_data_
[active_buffer_index_
],
358 if (SL_RESULT_SUCCESS
!= err
)
361 active_buffer_index_
= (active_buffer_index_
+ 1) % kMaxNumOfBuffersInQueue
;
364 void OpenSLESOutputStream::SetupAudioBuffer() {
365 DCHECK(thread_checker_
.CalledOnValidThread());
366 DCHECK(!audio_data_
[0]);
367 for (int i
= 0; i
< kMaxNumOfBuffersInQueue
; ++i
) {
368 audio_data_
[i
] = new uint8
[buffer_size_bytes_
];
372 void OpenSLESOutputStream::ReleaseAudioBuffer() {
373 DCHECK(thread_checker_
.CalledOnValidThread());
374 if (audio_data_
[0]) {
375 for (int i
= 0; i
< kMaxNumOfBuffersInQueue
; ++i
) {
376 delete[] audio_data_
[i
];
377 audio_data_
[i
] = NULL
;
382 void OpenSLESOutputStream::HandleError(SLresult error
) {
383 DLOG(ERROR
) << "OpenSLES Output error " << error
;
385 callback_
->OnError(this);