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