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