Home | History | Annotate | Download | only in android
      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_input.h"
      6 
      7 #include "base/debug/trace_event.h"
      8 #include "base/logging.h"
      9 #include "media/audio/android/audio_manager_android.h"
     10 #include "media/base/audio_bus.h"
     11 
     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)
     20 
     21 namespace media {
     22 
     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;
     47 
     48   buffer_size_bytes_ = params.GetBytesPerBuffer();
     49 
     50   memset(&audio_data_, 0, sizeof(audio_data_));
     51 }
     52 
     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]);
     61 }
     62 
     63 bool OpenSLESInputStream::Open() {
     64   DVLOG(2) << __PRETTY_FUNCTION__;
     65   DCHECK(thread_checker_.CalledOnValidThread());
     66   if (engine_object_.Get())
     67     return false;
     68 
     69   if (!CreateRecorder())
     70     return false;
     71 
     72   SetupAudioBuffer();
     73 
     74   return true;
     75 }
     76 
     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;
     85 
     86   base::AutoLock lock(lock_);
     87   DCHECK(callback_ == NULL || callback_ == callback);
     88   callback_ = callback;
     89   active_buffer_index_ = 0;
     90 
     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;
    104     }
    105   }
    106 
    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;
    115   }
    116 
    117   started_ = true;
    118 }
    119 
    120 void OpenSLESInputStream::Stop() {
    121   DVLOG(2) << __PRETTY_FUNCTION__;
    122   DCHECK(thread_checker_.CalledOnValidThread());
    123   if (!started_)
    124     return;
    125 
    126   base::AutoLock lock(lock_);
    127 
    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));
    131 
    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_));
    135 
    136   started_ = false;
    137   callback_ = NULL;
    138 }
    139 
    140 void OpenSLESInputStream::Close() {
    141   DVLOG(2) << __PRETTY_FUNCTION__;
    142   DCHECK(thread_checker_.CalledOnValidThread());
    143 
    144   // Stop the stream if it is still recording.
    145   Stop();
    146   {
    147     // TODO(henrika): Do we need to hold the lock here?
    148     base::AutoLock lock(lock_);
    149 
    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;
    155 
    156     // Destroy the engine object. We don't store any associated interface for
    157     // this object.
    158     engine_object_.Reset();
    159     ReleaseAudioBuffer();
    160   }
    161 
    162   audio_manager_->ReleaseInputStream(this);
    163 }
    164 
    165 double OpenSLESInputStream::GetMaxVolume() {
    166   NOTIMPLEMENTED();
    167   return 0.0;
    168 }
    169 
    170 void OpenSLESInputStream::SetVolume(double volume) {
    171   NOTIMPLEMENTED();
    172 }
    173 
    174 double OpenSLESInputStream::GetVolume() {
    175   NOTIMPLEMENTED();
    176   return 0.0;
    177 }
    178 
    179 void OpenSLESInputStream::SetAutomaticGainControl(bool enabled) {
    180   NOTIMPLEMENTED();
    181 }
    182 
    183 bool OpenSLESInputStream::GetAutomaticGainControl() {
    184   NOTIMPLEMENTED();
    185   return false;
    186 }
    187 
    188 bool OpenSLESInputStream::IsMuted() {
    189   NOTIMPLEMENTED();
    190   return false;
    191 }
    192 
    193 bool OpenSLESInputStream::CreateRecorder() {
    194   DCHECK(thread_checker_.CalledOnValidThread());
    195   DCHECK(!engine_object_.Get());
    196   DCHECK(!recorder_object_.Get());
    197   DCHECK(!recorder_);
    198   DCHECK(!simple_buffer_queue_);
    199 
    200   // Initializes the engine object with specific option. After working with the
    201   // object, we need to free the object and its resources.
    202   SLEngineOption option[] = {
    203       {SL_ENGINEOPTION_THREADSAFE, static_cast<SLuint32>(SL_BOOLEAN_TRUE)}};
    204   LOG_ON_FAILURE_AND_RETURN(
    205       slCreateEngine(engine_object_.Receive(), 1, option, 0, NULL, NULL),
    206       false);
    207 
    208   // Realize the SL engine object in synchronous mode.
    209   LOG_ON_FAILURE_AND_RETURN(
    210       engine_object_->Realize(engine_object_.Get(), SL_BOOLEAN_FALSE), false);
    211 
    212   // Get the SL engine interface which is implicit.
    213   SLEngineItf engine;
    214   LOG_ON_FAILURE_AND_RETURN(engine_object_->GetInterface(
    215                                 engine_object_.Get(), SL_IID_ENGINE, &engine),
    216                             false);
    217 
    218   // Audio source configuration.
    219   SLDataLocator_IODevice mic_locator = {
    220       SL_DATALOCATOR_IODEVICE,       SL_IODEVICE_AUDIOINPUT,
    221       SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};
    222   SLDataSource audio_source = {&mic_locator, NULL};
    223 
    224   // Audio sink configuration.
    225   SLDataLocator_AndroidSimpleBufferQueue buffer_queue = {
    226       SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,
    227       static_cast<SLuint32>(kMaxNumOfBuffersInQueue)};
    228   SLDataSink audio_sink = {&buffer_queue, &format_};
    229 
    230   // Create an audio recorder.
    231   const SLInterfaceID interface_id[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
    232                                         SL_IID_ANDROIDCONFIGURATION};
    233   const SLboolean interface_required[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
    234 
    235   // Create AudioRecorder and specify SL_IID_ANDROIDCONFIGURATION.
    236   LOG_ON_FAILURE_AND_RETURN(
    237       (*engine)->CreateAudioRecorder(engine,
    238                                      recorder_object_.Receive(),
    239                                      &audio_source,
    240                                      &audio_sink,
    241                                      arraysize(interface_id),
    242                                      interface_id,
    243                                      interface_required),
    244       false);
    245 
    246   SLAndroidConfigurationItf recorder_config;
    247   LOG_ON_FAILURE_AND_RETURN(
    248       recorder_object_->GetInterface(recorder_object_.Get(),
    249                                      SL_IID_ANDROIDCONFIGURATION,
    250                                      &recorder_config),
    251       false);
    252 
    253   // Uses the main microphone tuned for audio communications.
    254   SLint32 stream_type = SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION;
    255   LOG_ON_FAILURE_AND_RETURN(
    256       (*recorder_config)->SetConfiguration(recorder_config,
    257                                            SL_ANDROID_KEY_RECORDING_PRESET,
    258                                            &stream_type,
    259                                            sizeof(SLint32)),
    260       false);
    261 
    262   // Realize the recorder object in synchronous mode.
    263   LOG_ON_FAILURE_AND_RETURN(
    264       recorder_object_->Realize(recorder_object_.Get(), SL_BOOLEAN_FALSE),
    265       false);
    266 
    267   // Get an implicit recorder interface.
    268   LOG_ON_FAILURE_AND_RETURN(
    269       recorder_object_->GetInterface(
    270           recorder_object_.Get(), SL_IID_RECORD, &recorder_),
    271       false);
    272 
    273   // Get the simple buffer queue interface.
    274   LOG_ON_FAILURE_AND_RETURN(
    275       recorder_object_->GetInterface(recorder_object_.Get(),
    276                                      SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
    277                                      &simple_buffer_queue_),
    278       false);
    279 
    280   // Register the input callback for the simple buffer queue.
    281   // This callback will be called when receiving new data from the device.
    282   LOG_ON_FAILURE_AND_RETURN(
    283       (*simple_buffer_queue_)->RegisterCallback(
    284           simple_buffer_queue_, SimpleBufferQueueCallback, this),
    285       false);
    286 
    287   return true;
    288 }
    289 
    290 void OpenSLESInputStream::SimpleBufferQueueCallback(
    291     SLAndroidSimpleBufferQueueItf buffer_queue,
    292     void* instance) {
    293   OpenSLESInputStream* stream =
    294       reinterpret_cast<OpenSLESInputStream*>(instance);
    295   stream->ReadBufferQueue();
    296 }
    297 
    298 void OpenSLESInputStream::ReadBufferQueue() {
    299   base::AutoLock lock(lock_);
    300   if (!started_)
    301     return;
    302 
    303   TRACE_EVENT0("audio", "OpenSLESOutputStream::ReadBufferQueue");
    304 
    305   // Convert from interleaved format to deinterleaved audio bus format.
    306   audio_bus_->FromInterleaved(audio_data_[active_buffer_index_],
    307                               audio_bus_->frames(),
    308                               format_.bitsPerSample / 8);
    309 
    310   // TODO(henrika): Investigate if it is possible to get an accurate
    311   // delay estimation.
    312   callback_->OnData(this, audio_bus_.get(), buffer_size_bytes_, 0.0);
    313 
    314   // Done with this buffer. Send it to device for recording.
    315   SLresult err =
    316       (*simple_buffer_queue_)->Enqueue(simple_buffer_queue_,
    317                                        audio_data_[active_buffer_index_],
    318                                        buffer_size_bytes_);
    319   if (SL_RESULT_SUCCESS != err)
    320     HandleError(err);
    321 
    322   active_buffer_index_ = (active_buffer_index_ + 1) % kMaxNumOfBuffersInQueue;
    323 }
    324 
    325 void OpenSLESInputStream::SetupAudioBuffer() {
    326   DCHECK(thread_checker_.CalledOnValidThread());
    327   DCHECK(!audio_data_[0]);
    328   for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) {
    329     audio_data_[i] = new uint8[buffer_size_bytes_];
    330   }
    331 }
    332 
    333 void OpenSLESInputStream::ReleaseAudioBuffer() {
    334   DCHECK(thread_checker_.CalledOnValidThread());
    335   if (audio_data_[0]) {
    336     for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) {
    337       delete[] audio_data_[i];
    338       audio_data_[i] = NULL;
    339     }
    340   }
    341 }
    342 
    343 void OpenSLESInputStream::HandleError(SLresult error) {
    344   DLOG(ERROR) << "OpenSLES Input error " << error;
    345   if (callback_)
    346     callback_->OnError(this);
    347 }
    348 
    349 }  // namespace media
    350