Removed unused VideoCaptureCapability parameters.
[chromium-blink-merge.git] / media / audio / android / opensles_input.cc
bloba0e4ce3b987e8e73b2ebda8e795d08dae3aa2b5f
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/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 OpenSLESInputStream::OpenSLESInputStream(AudioManagerAndroid* audio_manager,
23 const AudioParameters& params)
24 : audio_manager_(audio_manager),
25 callback_(NULL),
26 recorder_(NULL),
27 simple_buffer_queue_(NULL),
28 active_buffer_index_(0),
29 buffer_size_bytes_(0),
30 started_(false) {
31 DVLOG(2) << "OpenSLESInputStream::OpenSLESInputStream()";
32 format_.formatType = SL_DATAFORMAT_PCM;
33 format_.numChannels = static_cast<SLuint32>(params.channels());
34 // Provides sampling rate in milliHertz to OpenSLES.
35 format_.samplesPerSec = static_cast<SLuint32>(params.sample_rate() * 1000);
36 format_.bitsPerSample = params.bits_per_sample();
37 format_.containerSize = params.bits_per_sample();
38 format_.endianness = SL_BYTEORDER_LITTLEENDIAN;
39 if (format_.numChannels == 1)
40 format_.channelMask = SL_SPEAKER_FRONT_CENTER;
41 else if (format_.numChannels == 2)
42 format_.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
43 else
44 NOTREACHED() << "Unsupported number of channels: " << format_.numChannels;
46 buffer_size_bytes_ = params.GetBytesPerBuffer();
48 memset(&audio_data_, 0, sizeof(audio_data_));
51 OpenSLESInputStream::~OpenSLESInputStream() {
52 DVLOG(2) << "OpenSLESInputStream::~OpenSLESInputStream()";
53 DCHECK(thread_checker_.CalledOnValidThread());
54 DCHECK(!recorder_object_.Get());
55 DCHECK(!engine_object_.Get());
56 DCHECK(!recorder_);
57 DCHECK(!simple_buffer_queue_);
58 DCHECK(!audio_data_[0]);
61 bool OpenSLESInputStream::Open() {
62 DVLOG(2) << "OpenSLESInputStream::Open()";
63 DCHECK(thread_checker_.CalledOnValidThread());
64 if (engine_object_.Get())
65 return false;
67 if (!CreateRecorder())
68 return false;
70 SetupAudioBuffer();
72 return true;
75 void OpenSLESInputStream::Start(AudioInputCallback* callback) {
76 DVLOG(2) << "OpenSLESInputStream::Start()";
77 DCHECK(thread_checker_.CalledOnValidThread());
78 DCHECK(callback);
79 DCHECK(recorder_);
80 DCHECK(simple_buffer_queue_);
81 if (started_)
82 return;
84 base::AutoLock lock(lock_);
85 DCHECK(callback_ == NULL || callback_ == callback);
86 callback_ = callback;
87 active_buffer_index_ = 0;
89 // Enqueues kMaxNumOfBuffersInQueue zero buffers to get the ball rolling.
90 // TODO(henrika): add support for Start/Stop/Start sequences when we are
91 // able to clear the buffer queue. There is currently a bug in the OpenSLES
92 // implementation which forces us to always call Stop() and Close() before
93 // calling Start() again.
94 SLresult err = SL_RESULT_UNKNOWN_ERROR;
95 for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) {
96 err = (*simple_buffer_queue_)->Enqueue(
97 simple_buffer_queue_, audio_data_[i], buffer_size_bytes_);
98 if (SL_RESULT_SUCCESS != err) {
99 HandleError(err);
100 started_ = false;
101 return;
105 // Start the recording by setting the state to SL_RECORDSTATE_RECORDING.
106 // When the object is in the SL_RECORDSTATE_RECORDING state, adding buffers
107 // will implicitly start the filling process.
108 err = (*recorder_)->SetRecordState(recorder_, SL_RECORDSTATE_RECORDING);
109 if (SL_RESULT_SUCCESS != err) {
110 HandleError(err);
111 started_ = false;
112 return;
115 started_ = true;
118 void OpenSLESInputStream::Stop() {
119 DVLOG(2) << "OpenSLESInputStream::Stop()";
120 DCHECK(thread_checker_.CalledOnValidThread());
121 if (!started_)
122 return;
124 base::AutoLock lock(lock_);
126 // Stop recording by setting the record state to SL_RECORDSTATE_STOPPED.
127 LOG_ON_FAILURE_AND_RETURN(
128 (*recorder_)->SetRecordState(recorder_, SL_RECORDSTATE_STOPPED));
130 // Clear the buffer queue to get rid of old data when resuming recording.
131 LOG_ON_FAILURE_AND_RETURN(
132 (*simple_buffer_queue_)->Clear(simple_buffer_queue_));
134 started_ = false;
137 void OpenSLESInputStream::Close() {
138 DVLOG(2) << "OpenSLESInputStream::Close()";
139 DCHECK(thread_checker_.CalledOnValidThread());
141 // Stop the stream if it is still recording.
142 Stop();
144 base::AutoLock lock(lock_);
146 // TODO(henrika): we use |callback_| in Close() but |callback_| is set
147 // in Start(). Hence, it should be cleared in Stop() and not used here.
148 if (callback_) {
149 callback_->OnClose(this);
150 callback_ = NULL;
153 // Destroy the buffer queue recorder object and invalidate all associated
154 // interfaces.
155 recorder_object_.Reset();
156 simple_buffer_queue_ = NULL;
157 recorder_ = NULL;
159 // Destroy the engine object. We don't store any associated interface for
160 // this object.
161 engine_object_.Reset();
162 ReleaseAudioBuffer();
165 audio_manager_->ReleaseInputStream(this);
168 double OpenSLESInputStream::GetMaxVolume() {
169 NOTIMPLEMENTED();
170 return 0.0;
173 void OpenSLESInputStream::SetVolume(double volume) { NOTIMPLEMENTED(); }
175 double OpenSLESInputStream::GetVolume() {
176 NOTIMPLEMENTED();
177 return 0.0;
180 void OpenSLESInputStream::SetAutomaticGainControl(bool enabled) {
181 NOTIMPLEMENTED();
184 bool OpenSLESInputStream::GetAutomaticGainControl() {
185 NOTIMPLEMENTED();
186 return false;
189 bool OpenSLESInputStream::CreateRecorder() {
190 DCHECK(thread_checker_.CalledOnValidThread());
191 DCHECK(!engine_object_.Get());
192 DCHECK(!recorder_object_.Get());
193 DCHECK(!recorder_);
194 DCHECK(!simple_buffer_queue_);
196 // Initializes the engine object with specific option. After working with the
197 // object, we need to free the object and its resources.
198 SLEngineOption option[] = {
199 {SL_ENGINEOPTION_THREADSAFE, static_cast<SLuint32>(SL_BOOLEAN_TRUE)}};
200 LOG_ON_FAILURE_AND_RETURN(
201 slCreateEngine(engine_object_.Receive(), 1, option, 0, NULL, NULL),
202 false);
204 // Realize the SL engine object in synchronous mode.
205 LOG_ON_FAILURE_AND_RETURN(
206 engine_object_->Realize(engine_object_.Get(), SL_BOOLEAN_FALSE), false);
208 // Get the SL engine interface which is implicit.
209 SLEngineItf engine;
210 LOG_ON_FAILURE_AND_RETURN(engine_object_->GetInterface(
211 engine_object_.Get(), SL_IID_ENGINE, &engine),
212 false);
214 // Audio source configuration.
215 SLDataLocator_IODevice mic_locator = {
216 SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT,
217 SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};
218 SLDataSource audio_source = {&mic_locator, NULL};
220 // Audio sink configuration.
221 SLDataLocator_AndroidSimpleBufferQueue buffer_queue = {
222 SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,
223 static_cast<SLuint32>(kMaxNumOfBuffersInQueue)};
224 SLDataSink audio_sink = {&buffer_queue, &format_};
226 // Create an audio recorder.
227 const SLInterfaceID interface_id[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
228 SL_IID_ANDROIDCONFIGURATION};
229 const SLboolean interface_required[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
231 // Create AudioRecorder and specify SL_IID_ANDROIDCONFIGURATION.
232 LOG_ON_FAILURE_AND_RETURN(
233 (*engine)->CreateAudioRecorder(engine,
234 recorder_object_.Receive(),
235 &audio_source,
236 &audio_sink,
237 arraysize(interface_id),
238 interface_id,
239 interface_required),
240 false);
242 SLAndroidConfigurationItf recorder_config;
243 LOG_ON_FAILURE_AND_RETURN(
244 recorder_object_->GetInterface(recorder_object_.Get(),
245 SL_IID_ANDROIDCONFIGURATION,
246 &recorder_config),
247 false);
249 // Uses the main microphone tuned for audio communications.
250 SLint32 stream_type = SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION;
251 LOG_ON_FAILURE_AND_RETURN(
252 (*recorder_config)->SetConfiguration(recorder_config,
253 SL_ANDROID_KEY_RECORDING_PRESET,
254 &stream_type,
255 sizeof(SLint32)),
256 false);
258 // Realize the recorder object in synchronous mode.
259 LOG_ON_FAILURE_AND_RETURN(
260 recorder_object_->Realize(recorder_object_.Get(), SL_BOOLEAN_FALSE),
261 false);
263 // Get an implicit recorder interface.
264 LOG_ON_FAILURE_AND_RETURN(
265 recorder_object_->GetInterface(
266 recorder_object_.Get(), SL_IID_RECORD, &recorder_),
267 false);
269 // Get the simple buffer queue interface.
270 LOG_ON_FAILURE_AND_RETURN(
271 recorder_object_->GetInterface(recorder_object_.Get(),
272 SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
273 &simple_buffer_queue_),
274 false);
276 // Register the input callback for the simple buffer queue.
277 // This callback will be called when receiving new data from the device.
278 LOG_ON_FAILURE_AND_RETURN(
279 (*simple_buffer_queue_)->RegisterCallback(
280 simple_buffer_queue_, SimpleBufferQueueCallback, this),
281 false);
283 return true;
286 void OpenSLESInputStream::SimpleBufferQueueCallback(
287 SLAndroidSimpleBufferQueueItf buffer_queue,
288 void* instance) {
289 OpenSLESInputStream* stream =
290 reinterpret_cast<OpenSLESInputStream*>(instance);
291 stream->ReadBufferQueue();
294 void OpenSLESInputStream::ReadBufferQueue() {
295 base::AutoLock lock(lock_);
296 if (!started_)
297 return;
299 TRACE_EVENT0("audio", "OpenSLESOutputStream::ReadBufferQueue");
301 // TODO(henrika): Investigate if it is possible to get an accurate
302 // delay estimation.
303 callback_->OnData(this,
304 audio_data_[active_buffer_index_],
305 buffer_size_bytes_,
306 buffer_size_bytes_,
307 0.0);
309 // Done with this buffer. Send it to device for recording.
310 SLresult err =
311 (*simple_buffer_queue_)->Enqueue(simple_buffer_queue_,
312 audio_data_[active_buffer_index_],
313 buffer_size_bytes_);
314 if (SL_RESULT_SUCCESS != err)
315 HandleError(err);
317 active_buffer_index_ = (active_buffer_index_ + 1) % kMaxNumOfBuffersInQueue;
320 void OpenSLESInputStream::SetupAudioBuffer() {
321 DCHECK(thread_checker_.CalledOnValidThread());
322 DCHECK(!audio_data_[0]);
323 for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) {
324 audio_data_[i] = new uint8[buffer_size_bytes_];
328 void OpenSLESInputStream::ReleaseAudioBuffer() {
329 DCHECK(thread_checker_.CalledOnValidThread());
330 if (audio_data_[0]) {
331 for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) {
332 delete[] audio_data_[i];
333 audio_data_[i] = NULL;
338 void OpenSLESInputStream::HandleError(SLresult error) {
339 DLOG(ERROR) << "OpenSLES Input error " << error;
340 if (callback_)
341 callback_->OnError(this);
344 } // namespace media