Removed unused VideoCaptureCapability parameters.
[chromium-blink-merge.git] / media / audio / android / opensles_output.cc
blob5643f833c3dd98f53eeb578e13e6ff4aaf9c6887
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/debug/trace_event.h"
8 #include "base/logging.h"
9 #include "media/audio/android/audio_manager_android.h"
11 #define LOG_ON_FAILURE_AND_RETURN(op, ...) \
12 do { \
13 SLresult err = (op); \
14 if (err != SL_RESULT_SUCCESS) { \
15 DLOG(ERROR) << #op << " failed: " << err; \
16 return __VA_ARGS__; \
17 } \
18 } while (0)
20 namespace media {
22 OpenSLESOutputStream::OpenSLESOutputStream(AudioManagerAndroid* manager,
23 const AudioParameters& params)
24 : audio_manager_(manager),
25 callback_(NULL),
26 player_(NULL),
27 simple_buffer_queue_(NULL),
28 active_buffer_index_(0),
29 buffer_size_bytes_(0),
30 started_(false),
31 volume_(1.0) {
32 DVLOG(2) << "OpenSLESOutputStream::OpenSLESOutputStream()";
33 format_.formatType = SL_DATAFORMAT_PCM;
34 format_.numChannels = static_cast<SLuint32>(params.channels());
35 // Provides sampling rate in milliHertz to OpenSLES.
36 format_.samplesPerSec = static_cast<SLuint32>(params.sample_rate() * 1000);
37 format_.bitsPerSample = params.bits_per_sample();
38 format_.containerSize = params.bits_per_sample();
39 format_.endianness = SL_BYTEORDER_LITTLEENDIAN;
40 if (format_.numChannels == 1)
41 format_.channelMask = SL_SPEAKER_FRONT_CENTER;
42 else if (format_.numChannels == 2)
43 format_.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
44 else
45 NOTREACHED() << "Unsupported number of channels: " << format_.numChannels;
47 buffer_size_bytes_ = params.GetBytesPerBuffer();
48 audio_bus_ = AudioBus::Create(params);
50 memset(&audio_data_, 0, sizeof(audio_data_));
53 OpenSLESOutputStream::~OpenSLESOutputStream() {
54 DVLOG(2) << "OpenSLESOutputStream::~OpenSLESOutputStream()";
55 DCHECK(thread_checker_.CalledOnValidThread());
56 DCHECK(!engine_object_.Get());
57 DCHECK(!player_object_.Get());
58 DCHECK(!output_mixer_.Get());
59 DCHECK(!player_);
60 DCHECK(!simple_buffer_queue_);
61 DCHECK(!audio_data_[0]);
64 bool OpenSLESOutputStream::Open() {
65 DVLOG(2) << "OpenSLESOutputStream::Open()";
66 DCHECK(thread_checker_.CalledOnValidThread());
67 if (engine_object_.Get())
68 return false;
70 if (!CreatePlayer())
71 return false;
73 SetupAudioBuffer();
74 active_buffer_index_ = 0;
76 return true;
79 void OpenSLESOutputStream::Start(AudioSourceCallback* callback) {
80 DVLOG(2) << "OpenSLESOutputStream::Start()";
81 DCHECK(thread_checker_.CalledOnValidThread());
82 DCHECK(callback);
83 DCHECK(player_);
84 DCHECK(simple_buffer_queue_);
85 if (started_)
86 return;
88 base::AutoLock lock(lock_);
89 DCHECK(callback_ == NULL || callback_ == callback);
90 callback_ = callback;
92 // Avoid start-up glitches by filling up one buffer queue before starting
93 // the stream.
94 FillBufferQueueNoLock();
96 // Start streaming data by setting the play state to SL_PLAYSTATE_PLAYING.
97 // For a player object, when the object is in the SL_PLAYSTATE_PLAYING
98 // state, adding buffers will implicitly start playback.
99 LOG_ON_FAILURE_AND_RETURN(
100 (*player_)->SetPlayState(player_, SL_PLAYSTATE_PLAYING));
102 started_ = true;
105 void OpenSLESOutputStream::Stop() {
106 DVLOG(2) << "OpenSLESOutputStream::Stop()";
107 DCHECK(thread_checker_.CalledOnValidThread());
108 if (!started_)
109 return;
111 base::AutoLock lock(lock_);
113 // Stop playing by setting the play state to SL_PLAYSTATE_STOPPED.
114 LOG_ON_FAILURE_AND_RETURN(
115 (*player_)->SetPlayState(player_, SL_PLAYSTATE_STOPPED));
117 // Clear the buffer queue so that the old data won't be played when
118 // resuming playing.
119 LOG_ON_FAILURE_AND_RETURN(
120 (*simple_buffer_queue_)->Clear(simple_buffer_queue_));
122 #ifndef NDEBUG
123 // Verify that the buffer queue is in fact cleared as it should.
124 SLAndroidSimpleBufferQueueState buffer_queue_state;
125 LOG_ON_FAILURE_AND_RETURN((*simple_buffer_queue_)->GetState(
126 simple_buffer_queue_, &buffer_queue_state));
127 DCHECK_EQ(0u, buffer_queue_state.count);
128 DCHECK_EQ(0u, buffer_queue_state.index);
129 #endif
131 started_ = false;
134 void OpenSLESOutputStream::Close() {
135 DVLOG(2) << "OpenSLESOutputStream::Close()";
136 DCHECK(thread_checker_.CalledOnValidThread());
138 // Stop the stream if it is still playing.
139 Stop();
141 // Destroy the buffer queue player object and invalidate all associated
142 // interfaces.
143 player_object_.Reset();
144 simple_buffer_queue_ = NULL;
145 player_ = NULL;
147 // Destroy the mixer object. We don't store any associated interface for
148 // this object.
149 output_mixer_.Reset();
151 // Destroy the engine object. We don't store any associated interface for
152 // this object.
153 engine_object_.Reset();
154 ReleaseAudioBuffer();
157 audio_manager_->ReleaseOutputStream(this);
160 void OpenSLESOutputStream::SetVolume(double volume) {
161 DVLOG(2) << "OpenSLESOutputStream::SetVolume(" << volume << ")";
162 DCHECK(thread_checker_.CalledOnValidThread());
163 float volume_float = static_cast<float>(volume);
164 if (volume_float < 0.0f || volume_float > 1.0f) {
165 return;
167 volume_ = volume_float;
170 void OpenSLESOutputStream::GetVolume(double* volume) {
171 DCHECK(thread_checker_.CalledOnValidThread());
172 *volume = static_cast<double>(volume_);
175 bool OpenSLESOutputStream::CreatePlayer() {
176 DCHECK(thread_checker_.CalledOnValidThread());
177 DCHECK(!engine_object_.Get());
178 DCHECK(!player_object_.Get());
179 DCHECK(!output_mixer_.Get());
180 DCHECK(!player_);
181 DCHECK(!simple_buffer_queue_);
183 // Initializes the engine object with specific option. After working with the
184 // object, we need to free the object and its resources.
185 SLEngineOption option[] = {
186 {SL_ENGINEOPTION_THREADSAFE, static_cast<SLuint32>(SL_BOOLEAN_TRUE)}};
187 LOG_ON_FAILURE_AND_RETURN(
188 slCreateEngine(engine_object_.Receive(), 1, option, 0, NULL, NULL),
189 false);
191 // Realize the SL engine object in synchronous mode.
192 LOG_ON_FAILURE_AND_RETURN(
193 engine_object_->Realize(engine_object_.Get(), SL_BOOLEAN_FALSE), false);
195 // Get the SL engine interface which is implicit.
196 SLEngineItf engine;
197 LOG_ON_FAILURE_AND_RETURN(engine_object_->GetInterface(
198 engine_object_.Get(), SL_IID_ENGINE, &engine),
199 false);
201 // Create ouput mixer object to be used by the player.
202 LOG_ON_FAILURE_AND_RETURN((*engine)->CreateOutputMix(
203 engine, output_mixer_.Receive(), 0, NULL, NULL),
204 false);
206 // Realizing the output mix object in synchronous mode.
207 LOG_ON_FAILURE_AND_RETURN(
208 output_mixer_->Realize(output_mixer_.Get(), SL_BOOLEAN_FALSE), false);
210 // Audio source configuration.
211 SLDataLocator_AndroidSimpleBufferQueue simple_buffer_queue = {
212 SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,
213 static_cast<SLuint32>(kMaxNumOfBuffersInQueue)};
214 SLDataSource audio_source = {&simple_buffer_queue, &format_};
216 // Audio sink configuration.
217 SLDataLocator_OutputMix locator_output_mix = {SL_DATALOCATOR_OUTPUTMIX,
218 output_mixer_.Get()};
219 SLDataSink audio_sink = {&locator_output_mix, NULL};
221 // Create an audio player.
222 const SLInterfaceID interface_id[] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME,
223 SL_IID_ANDROIDCONFIGURATION};
224 const SLboolean interface_required[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE,
225 SL_BOOLEAN_TRUE};
226 LOG_ON_FAILURE_AND_RETURN(
227 (*engine)->CreateAudioPlayer(engine,
228 player_object_.Receive(),
229 &audio_source,
230 &audio_sink,
231 arraysize(interface_id),
232 interface_id,
233 interface_required),
234 false);
236 // Create AudioPlayer and specify SL_IID_ANDROIDCONFIGURATION.
237 SLAndroidConfigurationItf player_config;
238 LOG_ON_FAILURE_AND_RETURN(
239 player_object_->GetInterface(
240 player_object_.Get(), SL_IID_ANDROIDCONFIGURATION, &player_config),
241 false);
243 SLint32 stream_type = SL_ANDROID_STREAM_VOICE;
244 LOG_ON_FAILURE_AND_RETURN(
245 (*player_config)->SetConfiguration(player_config,
246 SL_ANDROID_KEY_STREAM_TYPE,
247 &stream_type,
248 sizeof(SLint32)),
249 false);
251 // Realize the player object in synchronous mode.
252 LOG_ON_FAILURE_AND_RETURN(
253 player_object_->Realize(player_object_.Get(), SL_BOOLEAN_FALSE), false);
255 // Get an implicit player interface.
256 LOG_ON_FAILURE_AND_RETURN(
257 player_object_->GetInterface(player_object_.Get(), SL_IID_PLAY, &player_),
258 false);
260 // Get the simple buffer queue interface.
261 LOG_ON_FAILURE_AND_RETURN(
262 player_object_->GetInterface(
263 player_object_.Get(), SL_IID_BUFFERQUEUE, &simple_buffer_queue_),
264 false);
266 // Register the input callback for the simple buffer queue.
267 // This callback will be called when the soundcard needs data.
268 LOG_ON_FAILURE_AND_RETURN(
269 (*simple_buffer_queue_)->RegisterCallback(
270 simple_buffer_queue_, SimpleBufferQueueCallback, this),
271 false);
273 return true;
276 void OpenSLESOutputStream::SimpleBufferQueueCallback(
277 SLAndroidSimpleBufferQueueItf buffer_queue,
278 void* instance) {
279 OpenSLESOutputStream* stream =
280 reinterpret_cast<OpenSLESOutputStream*>(instance);
281 stream->FillBufferQueue();
284 void OpenSLESOutputStream::FillBufferQueue() {
285 base::AutoLock lock(lock_);
286 if (!started_)
287 return;
289 TRACE_EVENT0("audio", "OpenSLESOutputStream::FillBufferQueue");
291 // Verify that we are in a playing state.
292 SLuint32 state;
293 SLresult err = (*player_)->GetPlayState(player_, &state);
294 if (SL_RESULT_SUCCESS != err) {
295 HandleError(err);
296 return;
298 if (state != SL_PLAYSTATE_PLAYING) {
299 DLOG(WARNING) << "Received callback in non-playing state";
300 return;
303 // Fill up one buffer in the queue by asking the registered source for
304 // data using the OnMoreData() callback.
305 FillBufferQueueNoLock();
308 void OpenSLESOutputStream::FillBufferQueueNoLock() {
309 // Ensure that the calling thread has acquired the lock since it is not
310 // done in this method.
311 lock_.AssertAcquired();
313 // Read data from the registered client source.
314 // TODO(henrika): Investigate if it is possible to get a more accurate
315 // delay estimation.
316 const uint32 hardware_delay = buffer_size_bytes_;
317 int frames_filled = callback_->OnMoreData(
318 audio_bus_.get(), AudioBuffersState(0, hardware_delay));
319 if (frames_filled <= 0) {
320 // Audio source is shutting down, or halted on error.
321 return;
324 // Note: If the internal representation ever changes from 16-bit PCM to
325 // raw float, the data must be clipped and sanitized since it may come
326 // from an untrusted source such as NaCl.
327 audio_bus_->Scale(volume_);
328 audio_bus_->ToInterleaved(frames_filled,
329 format_.bitsPerSample / 8,
330 audio_data_[active_buffer_index_]);
332 const int num_filled_bytes =
333 frames_filled * audio_bus_->channels() * format_.bitsPerSample / 8;
334 DCHECK_LE(static_cast<size_t>(num_filled_bytes), buffer_size_bytes_);
336 // Enqueue the buffer for playback.
337 SLresult err =
338 (*simple_buffer_queue_)->Enqueue(simple_buffer_queue_,
339 audio_data_[active_buffer_index_],
340 num_filled_bytes);
341 if (SL_RESULT_SUCCESS != err)
342 HandleError(err);
344 active_buffer_index_ = (active_buffer_index_ + 1) % kMaxNumOfBuffersInQueue;
347 void OpenSLESOutputStream::SetupAudioBuffer() {
348 DCHECK(thread_checker_.CalledOnValidThread());
349 DCHECK(!audio_data_[0]);
350 for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) {
351 audio_data_[i] = new uint8[buffer_size_bytes_];
355 void OpenSLESOutputStream::ReleaseAudioBuffer() {
356 DCHECK(thread_checker_.CalledOnValidThread());
357 if (audio_data_[0]) {
358 for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) {
359 delete[] audio_data_[i];
360 audio_data_[i] = NULL;
365 void OpenSLESOutputStream::HandleError(SLresult error) {
366 DLOG(ERROR) << "OpenSLES Output error " << error;
367 if (callback_)
368 callback_->OnError(this);
371 } // namespace media