15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/android/opensles_input.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/debug/trace_event.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/android/audio_manager_android.h"
106d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "media/base/audio_bus.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#define LOG_ON_FAILURE_AND_RETURN(op, ...)      \
13d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  do {                                          \
14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    SLresult err = (op);                        \
15d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (err != SL_RESULT_SUCCESS) {             \
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      DLOG(ERROR) << #op << " failed: " << err; \
17d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return __VA_ARGS__;                       \
18d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }                                           \
19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  } while (0)
20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OpenSLESInputStream::OpenSLESInputStream(AudioManagerAndroid* audio_manager,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const AudioParameters& params)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : audio_manager_(audio_manager),
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback_(NULL),
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      recorder_(NULL),
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      simple_buffer_queue_(NULL),
29d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      active_buffer_index_(0),
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      buffer_size_bytes_(0),
316d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      started_(false),
326d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      audio_bus_(media::AudioBus::Create(params)) {
33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DVLOG(2) << __PRETTY_FUNCTION__;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  format_.formatType = SL_DATAFORMAT_PCM;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  format_.numChannels = static_cast<SLuint32>(params.channels());
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Provides sampling rate in milliHertz to OpenSLES.
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  format_.samplesPerSec = static_cast<SLuint32>(params.sample_rate() * 1000);
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  format_.bitsPerSample = params.bits_per_sample();
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  format_.containerSize = params.bits_per_sample();
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  format_.endianness = SL_BYTEORDER_LITTLEENDIAN;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (format_.numChannels == 1)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    format_.channelMask = SL_SPEAKER_FRONT_CENTER;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (format_.numChannels == 2)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    format_.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED() << "Unsupported number of channels: " << format_.numChannels;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffer_size_bytes_ = params.GetBytesPerBuffer();
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&audio_data_, 0, sizeof(audio_data_));
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OpenSLESInputStream::~OpenSLESInputStream() {
54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DVLOG(2) << __PRETTY_FUNCTION__;
55d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!recorder_object_.Get());
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!engine_object_.Get());
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!recorder_);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!simple_buffer_queue_);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!audio_data_[0]);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool OpenSLESInputStream::Open() {
64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DVLOG(2) << __PRETTY_FUNCTION__;
65d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (engine_object_.Get())
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CreateRecorder())
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetupAudioBuffer();
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OpenSLESInputStream::Start(AudioInputCallback* callback) {
78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DVLOG(2) << __PRETTY_FUNCTION__;
79d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(callback);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(recorder_);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(simple_buffer_queue_);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (started_)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
86d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  base::AutoLock lock(lock_);
87d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(callback_ == NULL || callback_ == callback);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback_ = callback;
89d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  active_buffer_index_ = 0;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
91d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Enqueues kMaxNumOfBuffersInQueue zero buffers to get the ball rolling.
92d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // TODO(henrika): add support for Start/Stop/Start sequences when we are
93d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // able to clear the buffer queue. There is currently a bug in the OpenSLES
94d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // implementation which forces us to always call Stop() and Close() before
95d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // calling Start() again.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SLresult err = SL_RESULT_UNKNOWN_ERROR;
97d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    err = (*simple_buffer_queue_)->Enqueue(
99d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        simple_buffer_queue_, audio_data_[i], buffer_size_bytes_);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (SL_RESULT_SUCCESS != err) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HandleError(err);
102d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      started_ = false;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
107d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Start the recording by setting the state to SL_RECORDSTATE_RECORDING.
108d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // When the object is in the SL_RECORDSTATE_RECORDING state, adding buffers
109d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // will implicitly start the filling process.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  err = (*recorder_)->SetRecordState(recorder_, SL_RECORDSTATE_RECORDING);
111d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (SL_RESULT_SUCCESS != err) {
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HandleError(err);
113d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    started_ = false;
114d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return;
115d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
116d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
117d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  started_ = true;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OpenSLESInputStream::Stop() {
121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DVLOG(2) << __PRETTY_FUNCTION__;
122d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!started_)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
126d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  base::AutoLock lock(lock_);
127d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
128d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Stop recording by setting the record state to SL_RECORDSTATE_STOPPED.
129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  LOG_ON_FAILURE_AND_RETURN(
130d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      (*recorder_)->SetRecordState(recorder_, SL_RECORDSTATE_STOPPED));
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Clear the buffer queue to get rid of old data when resuming recording.
133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  LOG_ON_FAILURE_AND_RETURN(
134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      (*simple_buffer_queue_)->Clear(simple_buffer_queue_));
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  started_ = false;
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  callback_ = NULL;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OpenSLESInputStream::Close() {
141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DVLOG(2) << __PRETTY_FUNCTION__;
142d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
143d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Stop the stream if it is still recording.
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Stop();
146d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  {
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // TODO(henrika): Do we need to hold the lock here?
148d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    base::AutoLock lock(lock_);
149d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
150d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // Destroy the buffer queue recorder object and invalidate all associated
151d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // interfaces.
152d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    recorder_object_.Reset();
153d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    simple_buffer_queue_ = NULL;
154d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    recorder_ = NULL;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
156d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // Destroy the engine object. We don't store any associated interface for
157d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // this object.
158d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    engine_object_.Reset();
159d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ReleaseAudioBuffer();
160d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_manager_->ReleaseInputStream(this);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double OpenSLESInputStream::GetMaxVolume() {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTIMPLEMENTED();
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0.0;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
170a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void OpenSLESInputStream::SetVolume(double volume) {
171a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  NOTIMPLEMENTED();
172a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double OpenSLESInputStream::GetVolume() {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTIMPLEMENTED();
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0.0;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OpenSLESInputStream::SetAutomaticGainControl(bool enabled) {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTIMPLEMENTED();
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool OpenSLESInputStream::GetAutomaticGainControl() {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTIMPLEMENTED();
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool OpenSLESInputStream::CreateRecorder() {
189d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
190d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(!engine_object_.Get());
191d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(!recorder_object_.Get());
192d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(!recorder_);
193d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(!simple_buffer_queue_);
194d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initializes the engine object with specific option. After working with the
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // object, we need to free the object and its resources.
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SLEngineOption option[] = {
198d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      {SL_ENGINEOPTION_THREADSAFE, static_cast<SLuint32>(SL_BOOLEAN_TRUE)}};
199d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  LOG_ON_FAILURE_AND_RETURN(
200d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      slCreateEngine(engine_object_.Receive(), 1, option, 0, NULL, NULL),
201d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      false);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Realize the SL engine object in synchronous mode.
204d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  LOG_ON_FAILURE_AND_RETURN(
205d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      engine_object_->Realize(engine_object_.Get(), SL_BOOLEAN_FALSE), false);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the SL engine interface which is implicit.
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SLEngineItf engine;
209d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  LOG_ON_FAILURE_AND_RETURN(engine_object_->GetInterface(
210d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                engine_object_.Get(), SL_IID_ENGINE, &engine),
211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            false);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Audio source configuration.
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SLDataLocator_IODevice mic_locator = {
215d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SL_DATALOCATOR_IODEVICE,       SL_IODEVICE_AUDIOINPUT,
216d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};
217d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  SLDataSource audio_source = {&mic_locator, NULL};
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Audio sink configuration.
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SLDataLocator_AndroidSimpleBufferQueue buffer_queue = {
221d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,
222d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      static_cast<SLuint32>(kMaxNumOfBuffersInQueue)};
223d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  SLDataSink audio_sink = {&buffer_queue, &format_};
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create an audio recorder.
226d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const SLInterfaceID interface_id[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
227d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                        SL_IID_ANDROIDCONFIGURATION};
228d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const SLboolean interface_required[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
229d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Create AudioRecorder and specify SL_IID_ANDROIDCONFIGURATION.
231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  LOG_ON_FAILURE_AND_RETURN(
232eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      (*engine)->CreateAudioRecorder(engine,
233eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     recorder_object_.Receive(),
234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     &audio_source,
235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     &audio_sink,
236eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     arraysize(interface_id),
237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     interface_id,
238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     interface_required),
239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      false);
240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
241eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SLAndroidConfigurationItf recorder_config;
242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  LOG_ON_FAILURE_AND_RETURN(
243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      recorder_object_->GetInterface(recorder_object_.Get(),
244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     SL_IID_ANDROIDCONFIGURATION,
245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     &recorder_config),
246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      false);
247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
248d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Uses the main microphone tuned for audio communications.
249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SLint32 stream_type = SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION;
250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  LOG_ON_FAILURE_AND_RETURN(
251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      (*recorder_config)->SetConfiguration(recorder_config,
252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           SL_ANDROID_KEY_RECORDING_PRESET,
253d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                           &stream_type,
254d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                           sizeof(SLint32)),
255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      false);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Realize the recorder object in synchronous mode.
258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  LOG_ON_FAILURE_AND_RETURN(
259d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      recorder_object_->Realize(recorder_object_.Get(), SL_BOOLEAN_FALSE),
260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      false);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get an implicit recorder interface.
263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  LOG_ON_FAILURE_AND_RETURN(
264d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      recorder_object_->GetInterface(
265d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          recorder_object_.Get(), SL_IID_RECORD, &recorder_),
266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      false);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the simple buffer queue interface.
269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  LOG_ON_FAILURE_AND_RETURN(
270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      recorder_object_->GetInterface(recorder_object_.Get(),
271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     &simple_buffer_queue_),
273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      false);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Register the input callback for the simple buffer queue.
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This callback will be called when receiving new data from the device.
277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  LOG_ON_FAILURE_AND_RETURN(
278d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      (*simple_buffer_queue_)->RegisterCallback(
279d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          simple_buffer_queue_, SimpleBufferQueueCallback, this),
280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      false);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return true;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OpenSLESInputStream::SimpleBufferQueueCallback(
286d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    SLAndroidSimpleBufferQueueItf buffer_queue,
287d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    void* instance) {
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OpenSLESInputStream* stream =
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<OpenSLESInputStream*>(instance);
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stream->ReadBufferQueue();
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OpenSLESInputStream::ReadBufferQueue() {
294d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  base::AutoLock lock(lock_);
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!started_)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
298d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  TRACE_EVENT0("audio", "OpenSLESOutputStream::ReadBufferQueue");
299d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
3006d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // Convert from interleaved format to deinterleaved audio bus format.
3016d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  audio_bus_->FromInterleaved(audio_data_[active_buffer_index_],
3026d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                              audio_bus_->frames(),
3036d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                              format_.bitsPerSample / 8);
3046d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
305d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // TODO(henrika): Investigate if it is possible to get an accurate
306d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // delay estimation.
3076d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  callback_->OnData(this, audio_bus_.get(), buffer_size_bytes_, 0.0);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Done with this buffer. Send it to device for recording.
310d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  SLresult err =
311d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      (*simple_buffer_queue_)->Enqueue(simple_buffer_queue_,
312d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                       audio_data_[active_buffer_index_],
313d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                       buffer_size_bytes_);
31490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (SL_RESULT_SUCCESS != err)
31590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    HandleError(err);
31690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
317d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  active_buffer_index_ = (active_buffer_index_ + 1) % kMaxNumOfBuffersInQueue;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OpenSLESInputStream::SetupAudioBuffer() {
321d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!audio_data_[0]);
323d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    audio_data_[i] = new uint8[buffer_size_bytes_];
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OpenSLESInputStream::ReleaseAudioBuffer() {
329d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (audio_data_[0]) {
331d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) {
332d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      delete[] audio_data_[i];
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      audio_data_[i] = NULL;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OpenSLESInputStream::HandleError(SLresult error) {
339d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DLOG(ERROR) << "OpenSLES Input error " << error;
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (callback_)
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback_->OnError(this);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
345