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::CreateRecorder() {
    189   DCHECK(thread_checker_.CalledOnValidThread());
    190   DCHECK(!engine_object_.Get());
    191   DCHECK(!recorder_object_.Get());
    192   DCHECK(!recorder_);
    193   DCHECK(!simple_buffer_queue_);
    194 
    195   // Initializes the engine object with specific option. After working with the
    196   // object, we need to free the object and its resources.
    197   SLEngineOption option[] = {
    198       {SL_ENGINEOPTION_THREADSAFE, static_cast<SLuint32>(SL_BOOLEAN_TRUE)}};
    199   LOG_ON_FAILURE_AND_RETURN(
    200       slCreateEngine(engine_object_.Receive(), 1, option, 0, NULL, NULL),
    201       false);
    202 
    203   // Realize the SL engine object in synchronous mode.
    204   LOG_ON_FAILURE_AND_RETURN(
    205       engine_object_->Realize(engine_object_.Get(), SL_BOOLEAN_FALSE), false);
    206 
    207   // Get the SL engine interface which is implicit.
    208   SLEngineItf engine;
    209   LOG_ON_FAILURE_AND_RETURN(engine_object_->GetInterface(
    210                                 engine_object_.Get(), SL_IID_ENGINE, &engine),
    211                             false);
    212 
    213   // Audio source configuration.
    214   SLDataLocator_IODevice mic_locator = {
    215       SL_DATALOCATOR_IODEVICE,       SL_IODEVICE_AUDIOINPUT,
    216       SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};
    217   SLDataSource audio_source = {&mic_locator, NULL};
    218 
    219   // Audio sink configuration.
    220   SLDataLocator_AndroidSimpleBufferQueue buffer_queue = {
    221       SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,
    222       static_cast<SLuint32>(kMaxNumOfBuffersInQueue)};
    223   SLDataSink audio_sink = {&buffer_queue, &format_};
    224 
    225   // Create an audio recorder.
    226   const SLInterfaceID interface_id[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
    227                                         SL_IID_ANDROIDCONFIGURATION};
    228   const SLboolean interface_required[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
    229 
    230   // Create AudioRecorder and specify SL_IID_ANDROIDCONFIGURATION.
    231   LOG_ON_FAILURE_AND_RETURN(
    232       (*engine)->CreateAudioRecorder(engine,
    233                                      recorder_object_.Receive(),
    234                                      &audio_source,
    235                                      &audio_sink,
    236                                      arraysize(interface_id),
    237                                      interface_id,
    238                                      interface_required),
    239       false);
    240 
    241   SLAndroidConfigurationItf recorder_config;
    242   LOG_ON_FAILURE_AND_RETURN(
    243       recorder_object_->GetInterface(recorder_object_.Get(),
    244                                      SL_IID_ANDROIDCONFIGURATION,
    245                                      &recorder_config),
    246       false);
    247 
    248   // Uses the main microphone tuned for audio communications.
    249   SLint32 stream_type = SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION;
    250   LOG_ON_FAILURE_AND_RETURN(
    251       (*recorder_config)->SetConfiguration(recorder_config,
    252                                            SL_ANDROID_KEY_RECORDING_PRESET,
    253                                            &stream_type,
    254                                            sizeof(SLint32)),
    255       false);
    256 
    257   // Realize the recorder object in synchronous mode.
    258   LOG_ON_FAILURE_AND_RETURN(
    259       recorder_object_->Realize(recorder_object_.Get(), SL_BOOLEAN_FALSE),
    260       false);
    261 
    262   // Get an implicit recorder interface.
    263   LOG_ON_FAILURE_AND_RETURN(
    264       recorder_object_->GetInterface(
    265           recorder_object_.Get(), SL_IID_RECORD, &recorder_),
    266       false);
    267 
    268   // Get the simple buffer queue interface.
    269   LOG_ON_FAILURE_AND_RETURN(
    270       recorder_object_->GetInterface(recorder_object_.Get(),
    271                                      SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
    272                                      &simple_buffer_queue_),
    273       false);
    274 
    275   // Register the input callback for the simple buffer queue.
    276   // This callback will be called when receiving new data from the device.
    277   LOG_ON_FAILURE_AND_RETURN(
    278       (*simple_buffer_queue_)->RegisterCallback(
    279           simple_buffer_queue_, SimpleBufferQueueCallback, this),
    280       false);
    281 
    282   return true;
    283 }
    284 
    285 void OpenSLESInputStream::SimpleBufferQueueCallback(
    286     SLAndroidSimpleBufferQueueItf buffer_queue,
    287     void* instance) {
    288   OpenSLESInputStream* stream =
    289       reinterpret_cast<OpenSLESInputStream*>(instance);
    290   stream->ReadBufferQueue();
    291 }
    292 
    293 void OpenSLESInputStream::ReadBufferQueue() {
    294   base::AutoLock lock(lock_);
    295   if (!started_)
    296     return;
    297 
    298   TRACE_EVENT0("audio", "OpenSLESOutputStream::ReadBufferQueue");
    299 
    300   // Convert from interleaved format to deinterleaved audio bus format.
    301   audio_bus_->FromInterleaved(audio_data_[active_buffer_index_],
    302                               audio_bus_->frames(),
    303                               format_.bitsPerSample / 8);
    304 
    305   // TODO(henrika): Investigate if it is possible to get an accurate
    306   // delay estimation.
    307   callback_->OnData(this, audio_bus_.get(), buffer_size_bytes_, 0.0);
    308 
    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);
    316 
    317   active_buffer_index_ = (active_buffer_index_ + 1) % kMaxNumOfBuffersInQueue;
    318 }
    319 
    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_];
    325   }
    326 }
    327 
    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;
    334     }
    335   }
    336 }
    337 
    338 void OpenSLESInputStream::HandleError(SLresult error) {
    339   DLOG(ERROR) << "OpenSLES Input error " << error;
    340   if (callback_)
    341     callback_->OnError(this);
    342 }
    343 
    344 }  // namespace media
    345