Adds "tts" permission for Input Tools & XKB extension.
[chromium-blink-merge.git] / media / audio / android / opensles_input.cc
blob51588a3ebde1f0a1440c57de757567cf163b20de
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_input.h"
7 #include "base/logging.h"
8 #include "base/trace_event/trace_event.h"
9 #include "media/audio/android/audio_manager_android.h"
10 #include "media/base/audio_bus.h"
12 #define LOG_ON_FAILURE_AND_RETURN(op, ...) \
13 do { \
14 SLresult err = (op); \
15 if (err != SL_RESULT_SUCCESS) { \
16 DLOG(ERROR) << #op << " failed: " << err; \
17 return __VA_ARGS__; \
18 } \
19 } while (0)
21 namespace media {
23 OpenSLESInputStream::OpenSLESInputStream(AudioManagerAndroid* audio_manager,
24 const AudioParameters& params)
25 : audio_manager_(audio_manager),
26 callback_(NULL),
27 recorder_(NULL),
28 simple_buffer_queue_(NULL),
29 active_buffer_index_(0),
30 buffer_size_bytes_(0),
31 started_(false),
32 audio_bus_(media::AudioBus::Create(params)) {
33 DVLOG(2) << __PRETTY_FUNCTION__;
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;
48 buffer_size_bytes_ = params.GetBytesPerBuffer();
50 memset(&audio_data_, 0, sizeof(audio_data_));
53 OpenSLESInputStream::~OpenSLESInputStream() {
54 DVLOG(2) << __PRETTY_FUNCTION__;
55 DCHECK(thread_checker_.CalledOnValidThread());
56 DCHECK(!recorder_object_.Get());
57 DCHECK(!engine_object_.Get());
58 DCHECK(!recorder_);
59 DCHECK(!simple_buffer_queue_);
60 DCHECK(!audio_data_[0]);
63 bool OpenSLESInputStream::Open() {
64 DVLOG(2) << __PRETTY_FUNCTION__;
65 DCHECK(thread_checker_.CalledOnValidThread());
66 if (engine_object_.Get())
67 return false;
69 if (!CreateRecorder())
70 return false;
72 SetupAudioBuffer();
74 return true;
77 void OpenSLESInputStream::Start(AudioInputCallback* callback) {
78 DVLOG(2) << __PRETTY_FUNCTION__;
79 DCHECK(thread_checker_.CalledOnValidThread());
80 DCHECK(callback);
81 DCHECK(recorder_);
82 DCHECK(simple_buffer_queue_);
83 if (started_)
84 return;
86 base::AutoLock lock(lock_);
87 DCHECK(callback_ == NULL || callback_ == callback);
88 callback_ = callback;
89 active_buffer_index_ = 0;
91 // Enqueues kMaxNumOfBuffersInQueue zero buffers to get the ball rolling.
92 // TODO(henrika): add support for Start/Stop/Start sequences when we are
93 // able to clear the buffer queue. There is currently a bug in the OpenSLES
94 // implementation which forces us to always call Stop() and Close() before
95 // calling Start() again.
96 SLresult err = SL_RESULT_UNKNOWN_ERROR;
97 for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) {
98 err = (*simple_buffer_queue_)->Enqueue(
99 simple_buffer_queue_, audio_data_[i], buffer_size_bytes_);
100 if (SL_RESULT_SUCCESS != err) {
101 HandleError(err);
102 started_ = false;
103 return;
107 // Start the recording by setting the state to SL_RECORDSTATE_RECORDING.
108 // When the object is in the SL_RECORDSTATE_RECORDING state, adding buffers
109 // will implicitly start the filling process.
110 err = (*recorder_)->SetRecordState(recorder_, SL_RECORDSTATE_RECORDING);
111 if (SL_RESULT_SUCCESS != err) {
112 HandleError(err);
113 started_ = false;
114 return;
117 started_ = true;
120 void OpenSLESInputStream::Stop() {
121 DVLOG(2) << __PRETTY_FUNCTION__;
122 DCHECK(thread_checker_.CalledOnValidThread());
123 if (!started_)
124 return;
126 base::AutoLock lock(lock_);
128 // Stop recording by setting the record state to SL_RECORDSTATE_STOPPED.
129 LOG_ON_FAILURE_AND_RETURN(
130 (*recorder_)->SetRecordState(recorder_, SL_RECORDSTATE_STOPPED));
132 // Clear the buffer queue to get rid of old data when resuming recording.
133 LOG_ON_FAILURE_AND_RETURN(
134 (*simple_buffer_queue_)->Clear(simple_buffer_queue_));
136 started_ = false;
137 callback_ = NULL;
140 void OpenSLESInputStream::Close() {
141 DVLOG(2) << __PRETTY_FUNCTION__;
142 DCHECK(thread_checker_.CalledOnValidThread());
144 // Stop the stream if it is still recording.
145 Stop();
147 // TODO(henrika): Do we need to hold the lock here?
148 base::AutoLock lock(lock_);
150 // Destroy the buffer queue recorder object and invalidate all associated
151 // interfaces.
152 recorder_object_.Reset();
153 simple_buffer_queue_ = NULL;
154 recorder_ = NULL;
156 // Destroy the engine object. We don't store any associated interface for
157 // this object.
158 engine_object_.Reset();
159 ReleaseAudioBuffer();
162 audio_manager_->ReleaseInputStream(this);
165 double OpenSLESInputStream::GetMaxVolume() {
166 NOTIMPLEMENTED();
167 return 0.0;
170 void OpenSLESInputStream::SetVolume(double volume) {
171 NOTIMPLEMENTED();
174 double OpenSLESInputStream::GetVolume() {
175 NOTIMPLEMENTED();
176 return 0.0;
179 bool OpenSLESInputStream::SetAutomaticGainControl(bool enabled) {
180 NOTIMPLEMENTED();
181 return false;
184 bool OpenSLESInputStream::GetAutomaticGainControl() {
185 NOTIMPLEMENTED();
186 return false;
189 bool OpenSLESInputStream::IsMuted() {
190 NOTIMPLEMENTED();
191 return false;
194 bool OpenSLESInputStream::CreateRecorder() {
195 DCHECK(thread_checker_.CalledOnValidThread());
196 DCHECK(!engine_object_.Get());
197 DCHECK(!recorder_object_.Get());
198 DCHECK(!recorder_);
199 DCHECK(!simple_buffer_queue_);
201 // Initializes the engine object with specific option. After working with the
202 // object, we need to free the object and its resources.
203 SLEngineOption option[] = {
204 {SL_ENGINEOPTION_THREADSAFE, static_cast<SLuint32>(SL_BOOLEAN_TRUE)}};
205 LOG_ON_FAILURE_AND_RETURN(
206 slCreateEngine(engine_object_.Receive(), 1, option, 0, NULL, NULL),
207 false);
209 // Realize the SL engine object in synchronous mode.
210 LOG_ON_FAILURE_AND_RETURN(
211 engine_object_->Realize(engine_object_.Get(), SL_BOOLEAN_FALSE), false);
213 // Get the SL engine interface which is implicit.
214 SLEngineItf engine;
215 LOG_ON_FAILURE_AND_RETURN(engine_object_->GetInterface(
216 engine_object_.Get(), SL_IID_ENGINE, &engine),
217 false);
219 // Audio source configuration.
220 SLDataLocator_IODevice mic_locator = {
221 SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT,
222 SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};
223 SLDataSource audio_source = {&mic_locator, NULL};
225 // Audio sink configuration.
226 SLDataLocator_AndroidSimpleBufferQueue buffer_queue = {
227 SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,
228 static_cast<SLuint32>(kMaxNumOfBuffersInQueue)};
229 SLDataSink audio_sink = {&buffer_queue, &format_};
231 // Create an audio recorder.
232 const SLInterfaceID interface_id[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
233 SL_IID_ANDROIDCONFIGURATION};
234 const SLboolean interface_required[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
236 // Create AudioRecorder and specify SL_IID_ANDROIDCONFIGURATION.
237 LOG_ON_FAILURE_AND_RETURN(
238 (*engine)->CreateAudioRecorder(engine,
239 recorder_object_.Receive(),
240 &audio_source,
241 &audio_sink,
242 arraysize(interface_id),
243 interface_id,
244 interface_required),
245 false);
247 SLAndroidConfigurationItf recorder_config;
248 LOG_ON_FAILURE_AND_RETURN(
249 recorder_object_->GetInterface(recorder_object_.Get(),
250 SL_IID_ANDROIDCONFIGURATION,
251 &recorder_config),
252 false);
254 // Uses the main microphone tuned for audio communications.
255 SLint32 stream_type = SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION;
256 LOG_ON_FAILURE_AND_RETURN(
257 (*recorder_config)->SetConfiguration(recorder_config,
258 SL_ANDROID_KEY_RECORDING_PRESET,
259 &stream_type,
260 sizeof(SLint32)),
261 false);
263 // Realize the recorder object in synchronous mode.
264 LOG_ON_FAILURE_AND_RETURN(
265 recorder_object_->Realize(recorder_object_.Get(), SL_BOOLEAN_FALSE),
266 false);
268 // Get an implicit recorder interface.
269 LOG_ON_FAILURE_AND_RETURN(
270 recorder_object_->GetInterface(
271 recorder_object_.Get(), SL_IID_RECORD, &recorder_),
272 false);
274 // Get the simple buffer queue interface.
275 LOG_ON_FAILURE_AND_RETURN(
276 recorder_object_->GetInterface(recorder_object_.Get(),
277 SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
278 &simple_buffer_queue_),
279 false);
281 // Register the input callback for the simple buffer queue.
282 // This callback will be called when receiving new data from the device.
283 LOG_ON_FAILURE_AND_RETURN(
284 (*simple_buffer_queue_)->RegisterCallback(
285 simple_buffer_queue_, SimpleBufferQueueCallback, this),
286 false);
288 return true;
291 void OpenSLESInputStream::SimpleBufferQueueCallback(
292 SLAndroidSimpleBufferQueueItf buffer_queue,
293 void* instance) {
294 OpenSLESInputStream* stream =
295 reinterpret_cast<OpenSLESInputStream*>(instance);
296 stream->ReadBufferQueue();
299 void OpenSLESInputStream::ReadBufferQueue() {
300 base::AutoLock lock(lock_);
301 if (!started_)
302 return;
304 TRACE_EVENT0("audio", "OpenSLESOutputStream::ReadBufferQueue");
306 // Convert from interleaved format to deinterleaved audio bus format.
307 audio_bus_->FromInterleaved(audio_data_[active_buffer_index_],
308 audio_bus_->frames(),
309 format_.bitsPerSample / 8);
311 // TODO(henrika): Investigate if it is possible to get an accurate
312 // delay estimation.
313 callback_->OnData(this, audio_bus_.get(), buffer_size_bytes_, 0.0);
315 // Done with this buffer. Send it to device for recording.
316 SLresult err =
317 (*simple_buffer_queue_)->Enqueue(simple_buffer_queue_,
318 audio_data_[active_buffer_index_],
319 buffer_size_bytes_);
320 if (SL_RESULT_SUCCESS != err)
321 HandleError(err);
323 active_buffer_index_ = (active_buffer_index_ + 1) % kMaxNumOfBuffersInQueue;
326 void OpenSLESInputStream::SetupAudioBuffer() {
327 DCHECK(thread_checker_.CalledOnValidThread());
328 DCHECK(!audio_data_[0]);
329 for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) {
330 audio_data_[i] = new uint8[buffer_size_bytes_];
334 void OpenSLESInputStream::ReleaseAudioBuffer() {
335 DCHECK(thread_checker_.CalledOnValidThread());
336 if (audio_data_[0]) {
337 for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) {
338 delete[] audio_data_[i];
339 audio_data_[i] = NULL;
344 void OpenSLESInputStream::HandleError(SLresult error) {
345 DLOG(ERROR) << "OpenSLES Input error " << error;
346 if (callback_)
347 callback_->OnError(this);
350 } // namespace media