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/logging.h"
      8 #include "media/audio/android/audio_manager_android.h"
      9 
     10 #define LOG_ON_FAILURE_AND_RETURN(op, ...) \
     11   do { \
     12     SLresult err = (op);            \
     13     if (err != SL_RESULT_SUCCESS) { \
     14       DLOG(ERROR) << #op << " failed: " << err; \
     15       return __VA_ARGS__; \
     16     } \
     17   } while (0)
     18 
     19 namespace media {
     20 
     21 OpenSLESInputStream::OpenSLESInputStream(AudioManagerAndroid* audio_manager,
     22                                          const AudioParameters& params)
     23     : audio_manager_(audio_manager),
     24       callback_(NULL),
     25       recorder_(NULL),
     26       simple_buffer_queue_(NULL),
     27       active_queue_(0),
     28       buffer_size_bytes_(0),
     29       started_(false) {
     30   format_.formatType = SL_DATAFORMAT_PCM;
     31   format_.numChannels = static_cast<SLuint32>(params.channels());
     32   // Provides sampling rate in milliHertz to OpenSLES.
     33   format_.samplesPerSec = static_cast<SLuint32>(params.sample_rate() * 1000);
     34   format_.bitsPerSample = params.bits_per_sample();
     35   format_.containerSize = params.bits_per_sample();
     36   format_.endianness = SL_BYTEORDER_LITTLEENDIAN;
     37   if (format_.numChannels == 1)
     38     format_.channelMask = SL_SPEAKER_FRONT_CENTER;
     39   else if (format_.numChannels == 2)
     40     format_.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
     41   else
     42     NOTREACHED() << "Unsupported number of channels: " << format_.numChannels;
     43 
     44   buffer_size_bytes_ = params.GetBytesPerBuffer();
     45 
     46   memset(&audio_data_, 0, sizeof(audio_data_));
     47 }
     48 
     49 OpenSLESInputStream::~OpenSLESInputStream() {
     50   DCHECK(!recorder_object_.Get());
     51   DCHECK(!engine_object_.Get());
     52   DCHECK(!recorder_);
     53   DCHECK(!simple_buffer_queue_);
     54   DCHECK(!audio_data_[0]);
     55 }
     56 
     57 bool OpenSLESInputStream::Open() {
     58   if (engine_object_.Get())
     59     return false;
     60 
     61   if (!CreateRecorder())
     62     return false;
     63 
     64   SetupAudioBuffer();
     65 
     66   return true;
     67 }
     68 
     69 void OpenSLESInputStream::Start(AudioInputCallback* callback) {
     70   DCHECK(callback);
     71   DCHECK(recorder_);
     72   DCHECK(simple_buffer_queue_);
     73   if (started_)
     74     return;
     75 
     76   // Enable the flags before streaming.
     77   callback_ = callback;
     78   active_queue_ = 0;
     79   started_ = true;
     80 
     81   SLresult err = SL_RESULT_UNKNOWN_ERROR;
     82   // Enqueues |kNumOfQueuesInBuffer| zero buffers to get the ball rolling.
     83   for (int i = 0; i < kNumOfQueuesInBuffer; ++i) {
     84     err = (*simple_buffer_queue_)->Enqueue(
     85         simple_buffer_queue_,
     86         audio_data_[i],
     87         buffer_size_bytes_);
     88     if (SL_RESULT_SUCCESS != err) {
     89       HandleError(err);
     90       return;
     91     }
     92   }
     93 
     94   // Start the recording by setting the state to |SL_RECORDSTATE_RECORDING|.
     95   err = (*recorder_)->SetRecordState(recorder_, SL_RECORDSTATE_RECORDING);
     96   if (SL_RESULT_SUCCESS != err)
     97     HandleError(err);
     98 }
     99 
    100 void OpenSLESInputStream::Stop() {
    101   if (!started_)
    102     return;
    103 
    104   // Stop recording by setting the record state to |SL_RECORDSTATE_STOPPED|.
    105   LOG_ON_FAILURE_AND_RETURN(
    106       (*recorder_)->SetRecordState(recorder_,
    107                                    SL_RECORDSTATE_STOPPED));
    108 
    109   // Clear the buffer queue to get rid of old data when resuming recording.
    110   LOG_ON_FAILURE_AND_RETURN(
    111       (*simple_buffer_queue_)->Clear(simple_buffer_queue_));
    112 
    113   started_ = false;
    114 }
    115 
    116 void OpenSLESInputStream::Close() {
    117   // Stop the stream if it is still recording.
    118   Stop();
    119 
    120   // Explicitly free the player objects and invalidate their associated
    121   // interfaces. They have to be done in the correct order.
    122   recorder_object_.Reset();
    123   engine_object_.Reset();
    124   simple_buffer_queue_ = NULL;
    125   recorder_ = NULL;
    126 
    127   ReleaseAudioBuffer();
    128 
    129   audio_manager_->ReleaseInputStream(this);
    130 }
    131 
    132 double OpenSLESInputStream::GetMaxVolume() {
    133   NOTIMPLEMENTED();
    134   return 0.0;
    135 }
    136 
    137 void OpenSLESInputStream::SetVolume(double volume) {
    138   NOTIMPLEMENTED();
    139 }
    140 
    141 double OpenSLESInputStream::GetVolume() {
    142   NOTIMPLEMENTED();
    143   return 0.0;
    144 }
    145 
    146 void OpenSLESInputStream::SetAutomaticGainControl(bool enabled) {
    147   NOTIMPLEMENTED();
    148 }
    149 
    150 bool OpenSLESInputStream::GetAutomaticGainControl() {
    151   NOTIMPLEMENTED();
    152   return false;
    153 }
    154 
    155 bool OpenSLESInputStream::CreateRecorder() {
    156   // Initializes the engine object with specific option. After working with the
    157   // object, we need to free the object and its resources.
    158   SLEngineOption option[] = {
    159     { SL_ENGINEOPTION_THREADSAFE, static_cast<SLuint32>(SL_BOOLEAN_TRUE) }
    160   };
    161   LOG_ON_FAILURE_AND_RETURN(slCreateEngine(engine_object_.Receive(),
    162                                            1,
    163                                            option,
    164                                            0,
    165                                            NULL,
    166                                            NULL),
    167                             false);
    168 
    169   // Realize the SL engine object in synchronous mode.
    170   LOG_ON_FAILURE_AND_RETURN(engine_object_->Realize(engine_object_.Get(),
    171                                                     SL_BOOLEAN_FALSE),
    172                             false);
    173 
    174   // Get the SL engine interface which is implicit.
    175   SLEngineItf engine;
    176   LOG_ON_FAILURE_AND_RETURN(engine_object_->GetInterface(engine_object_.Get(),
    177                                                          SL_IID_ENGINE,
    178                                                          &engine),
    179                             false);
    180 
    181   // Audio source configuration.
    182   SLDataLocator_IODevice mic_locator = {
    183     SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT,
    184     SL_DEFAULTDEVICEID_AUDIOINPUT, NULL
    185   };
    186   SLDataSource audio_source = { &mic_locator, NULL };
    187 
    188   // Audio sink configuration.
    189   SLDataLocator_AndroidSimpleBufferQueue buffer_queue = {
    190     SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,  // Locator type.
    191     static_cast<SLuint32>(kNumOfQueuesInBuffer)  // Number of buffers.
    192   };
    193   SLDataSink audio_sink = { &buffer_queue, &format_ };
    194 
    195   // Create an audio recorder.
    196   const SLInterfaceID interface_id[] = {
    197     SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
    198     SL_IID_ANDROIDCONFIGURATION
    199   };
    200   const SLboolean interface_required[] = {
    201     SL_BOOLEAN_TRUE,
    202     SL_BOOLEAN_TRUE
    203   };
    204   // Create AudioRecorder and specify SL_IID_ANDROIDCONFIGURATION.
    205   LOG_ON_FAILURE_AND_RETURN(
    206       (*engine)->CreateAudioRecorder(engine,
    207                                      recorder_object_.Receive(),
    208                                      &audio_source,
    209                                      &audio_sink,
    210                                      arraysize(interface_id),
    211                                      interface_id,
    212                                      interface_required),
    213       false);
    214 
    215   SLAndroidConfigurationItf recorder_config;
    216   LOG_ON_FAILURE_AND_RETURN(
    217       recorder_object_->GetInterface(recorder_object_.Get(),
    218                                      SL_IID_ANDROIDCONFIGURATION,
    219                                      &recorder_config),
    220       false);
    221 
    222   SLint32 stream_type = SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION;
    223   LOG_ON_FAILURE_AND_RETURN(
    224       (*recorder_config)->SetConfiguration(recorder_config,
    225                                            SL_ANDROID_KEY_RECORDING_PRESET,
    226                                            &stream_type, sizeof(SLint32)),
    227       false);
    228 
    229   // Realize the recorder object in synchronous mode.
    230   LOG_ON_FAILURE_AND_RETURN(
    231       recorder_object_->Realize(recorder_object_.Get(),
    232                                 SL_BOOLEAN_FALSE),
    233       false);
    234 
    235   // Get an implicit recorder interface.
    236   LOG_ON_FAILURE_AND_RETURN(
    237       recorder_object_->GetInterface(recorder_object_.Get(),
    238                                      SL_IID_RECORD,
    239                                      &recorder_),
    240       false);
    241 
    242   // Get the simple buffer queue interface.
    243   LOG_ON_FAILURE_AND_RETURN(
    244       recorder_object_->GetInterface(recorder_object_.Get(),
    245                                      SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
    246                                      &simple_buffer_queue_),
    247       false);
    248 
    249   // Register the input callback for the simple buffer queue.
    250   // This callback will be called when receiving new data from the device.
    251   LOG_ON_FAILURE_AND_RETURN(
    252       (*simple_buffer_queue_)->RegisterCallback(simple_buffer_queue_,
    253                                                 SimpleBufferQueueCallback,
    254                                                 this),
    255       false);
    256 
    257   return true;
    258 }
    259 
    260 void OpenSLESInputStream::SimpleBufferQueueCallback(
    261     SLAndroidSimpleBufferQueueItf buffer_queue, void* instance) {
    262   OpenSLESInputStream* stream =
    263       reinterpret_cast<OpenSLESInputStream*>(instance);
    264   stream->ReadBufferQueue();
    265 }
    266 
    267 void OpenSLESInputStream::ReadBufferQueue() {
    268   if (!started_)
    269     return;
    270 
    271   // TODO(xians): Get an accurate delay estimation.
    272   callback_->OnData(this,
    273                     audio_data_[active_queue_],
    274                     buffer_size_bytes_,
    275                     buffer_size_bytes_,
    276                     0.0);
    277 
    278   // Done with this buffer. Send it to device for recording.
    279   SLresult err = (*simple_buffer_queue_)->Enqueue(
    280       simple_buffer_queue_,
    281       audio_data_[active_queue_],
    282       buffer_size_bytes_);
    283   if (SL_RESULT_SUCCESS != err)
    284     HandleError(err);
    285 
    286   active_queue_ = (active_queue_ + 1) % kNumOfQueuesInBuffer;
    287 }
    288 
    289 void OpenSLESInputStream::SetupAudioBuffer() {
    290   DCHECK(!audio_data_[0]);
    291   for (int i = 0; i < kNumOfQueuesInBuffer; ++i) {
    292     audio_data_[i] = new uint8[buffer_size_bytes_];
    293   }
    294 }
    295 
    296 void OpenSLESInputStream::ReleaseAudioBuffer() {
    297   if (audio_data_[0]) {
    298     for (int i = 0; i < kNumOfQueuesInBuffer; ++i) {
    299       delete [] audio_data_[i];
    300       audio_data_[i] = NULL;
    301     }
    302   }
    303 }
    304 
    305 void OpenSLESInputStream::HandleError(SLresult error) {
    306   DLOG(FATAL) << "OpenSLES Input error " << error;
    307   if (callback_)
    308     callback_->OnError(this);
    309 }
    310 
    311 }  // namespace media
    312