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_output.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 OpenSLESOutputStream::OpenSLESOutputStream(AudioManagerAndroid* manager,
     23                                            const AudioParameters& params,
     24                                            SLint32 stream_type)
     25     : audio_manager_(manager),
     26       stream_type_(stream_type),
     27       callback_(NULL),
     28       player_(NULL),
     29       simple_buffer_queue_(NULL),
     30       active_buffer_index_(0),
     31       buffer_size_bytes_(0),
     32       started_(false),
     33       muted_(false),
     34       volume_(1.0) {
     35   DVLOG(2) << "OpenSLESOutputStream::OpenSLESOutputStream("
     36            << "stream_type=" << stream_type << ")";
     37   format_.formatType = SL_DATAFORMAT_PCM;
     38   format_.numChannels = static_cast<SLuint32>(params.channels());
     39   // Provides sampling rate in milliHertz to OpenSLES.
     40   format_.samplesPerSec = static_cast<SLuint32>(params.sample_rate() * 1000);
     41   format_.bitsPerSample = params.bits_per_sample();
     42   format_.containerSize = params.bits_per_sample();
     43   format_.endianness = SL_BYTEORDER_LITTLEENDIAN;
     44   if (format_.numChannels == 1)
     45     format_.channelMask = SL_SPEAKER_FRONT_CENTER;
     46   else if (format_.numChannels == 2)
     47     format_.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
     48   else
     49     NOTREACHED() << "Unsupported number of channels: " << format_.numChannels;
     50 
     51   buffer_size_bytes_ = params.GetBytesPerBuffer();
     52   audio_bus_ = AudioBus::Create(params);
     53 
     54   memset(&audio_data_, 0, sizeof(audio_data_));
     55 }
     56 
     57 OpenSLESOutputStream::~OpenSLESOutputStream() {
     58   DVLOG(2) << "OpenSLESOutputStream::~OpenSLESOutputStream()";
     59   DCHECK(thread_checker_.CalledOnValidThread());
     60   DCHECK(!engine_object_.Get());
     61   DCHECK(!player_object_.Get());
     62   DCHECK(!output_mixer_.Get());
     63   DCHECK(!player_);
     64   DCHECK(!simple_buffer_queue_);
     65   DCHECK(!audio_data_[0]);
     66 }
     67 
     68 bool OpenSLESOutputStream::Open() {
     69   DVLOG(2) << "OpenSLESOutputStream::Open()";
     70   DCHECK(thread_checker_.CalledOnValidThread());
     71   if (engine_object_.Get())
     72     return false;
     73 
     74   if (!CreatePlayer())
     75     return false;
     76 
     77   SetupAudioBuffer();
     78   active_buffer_index_ = 0;
     79 
     80   return true;
     81 }
     82 
     83 void OpenSLESOutputStream::Start(AudioSourceCallback* callback) {
     84   DVLOG(2) << "OpenSLESOutputStream::Start()";
     85   DCHECK(thread_checker_.CalledOnValidThread());
     86   DCHECK(callback);
     87   DCHECK(player_);
     88   DCHECK(simple_buffer_queue_);
     89   if (started_)
     90     return;
     91 
     92   base::AutoLock lock(lock_);
     93   DCHECK(callback_ == NULL || callback_ == callback);
     94   callback_ = callback;
     95 
     96   // Avoid start-up glitches by filling up one buffer queue before starting
     97   // the stream.
     98   FillBufferQueueNoLock();
     99 
    100   // Start streaming data by setting the play state to SL_PLAYSTATE_PLAYING.
    101   // For a player object, when the object is in the SL_PLAYSTATE_PLAYING
    102   // state, adding buffers will implicitly start playback.
    103   LOG_ON_FAILURE_AND_RETURN(
    104       (*player_)->SetPlayState(player_, SL_PLAYSTATE_PLAYING));
    105 
    106   started_ = true;
    107 }
    108 
    109 void OpenSLESOutputStream::Stop() {
    110   DVLOG(2) << "OpenSLESOutputStream::Stop()";
    111   DCHECK(thread_checker_.CalledOnValidThread());
    112   if (!started_)
    113     return;
    114 
    115   base::AutoLock lock(lock_);
    116 
    117   // Stop playing by setting the play state to SL_PLAYSTATE_STOPPED.
    118   LOG_ON_FAILURE_AND_RETURN(
    119       (*player_)->SetPlayState(player_, SL_PLAYSTATE_STOPPED));
    120 
    121   // Clear the buffer queue so that the old data won't be played when
    122   // resuming playing.
    123   LOG_ON_FAILURE_AND_RETURN(
    124       (*simple_buffer_queue_)->Clear(simple_buffer_queue_));
    125 
    126 #ifndef NDEBUG
    127   // Verify that the buffer queue is in fact cleared as it should.
    128   SLAndroidSimpleBufferQueueState buffer_queue_state;
    129   LOG_ON_FAILURE_AND_RETURN((*simple_buffer_queue_)->GetState(
    130       simple_buffer_queue_, &buffer_queue_state));
    131   DCHECK_EQ(0u, buffer_queue_state.count);
    132   DCHECK_EQ(0u, buffer_queue_state.index);
    133 #endif
    134 
    135   callback_ = NULL;
    136   started_ = false;
    137 }
    138 
    139 void OpenSLESOutputStream::Close() {
    140   DVLOG(2) << "OpenSLESOutputStream::Close()";
    141   DCHECK(thread_checker_.CalledOnValidThread());
    142 
    143   // Stop the stream if it is still playing.
    144   Stop();
    145   {
    146     // Destroy the buffer queue player object and invalidate all associated
    147     // interfaces.
    148     player_object_.Reset();
    149     simple_buffer_queue_ = NULL;
    150     player_ = NULL;
    151 
    152     // Destroy the mixer object. We don't store any associated interface for
    153     // this object.
    154     output_mixer_.Reset();
    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_->ReleaseOutputStream(this);
    163 }
    164 
    165 void OpenSLESOutputStream::SetVolume(double volume) {
    166   DVLOG(2) << "OpenSLESOutputStream::SetVolume(" << volume << ")";
    167   DCHECK(thread_checker_.CalledOnValidThread());
    168   float volume_float = static_cast<float>(volume);
    169   if (volume_float < 0.0f || volume_float > 1.0f) {
    170     return;
    171   }
    172   volume_ = volume_float;
    173 }
    174 
    175 void OpenSLESOutputStream::GetVolume(double* volume) {
    176   DCHECK(thread_checker_.CalledOnValidThread());
    177   *volume = static_cast<double>(volume_);
    178 }
    179 
    180 void OpenSLESOutputStream::SetMute(bool muted) {
    181   DVLOG(2) << "OpenSLESOutputStream::SetMute(" << muted << ")";
    182   DCHECK(thread_checker_.CalledOnValidThread());
    183   muted_ = muted;
    184 }
    185 
    186 bool OpenSLESOutputStream::CreatePlayer() {
    187   DCHECK(thread_checker_.CalledOnValidThread());
    188   DCHECK(!engine_object_.Get());
    189   DCHECK(!player_object_.Get());
    190   DCHECK(!output_mixer_.Get());
    191   DCHECK(!player_);
    192   DCHECK(!simple_buffer_queue_);
    193 
    194   // Initializes the engine object with specific option. After working with the
    195   // object, we need to free the object and its resources.
    196   SLEngineOption option[] = {
    197       {SL_ENGINEOPTION_THREADSAFE, static_cast<SLuint32>(SL_BOOLEAN_TRUE)}};
    198   LOG_ON_FAILURE_AND_RETURN(
    199       slCreateEngine(engine_object_.Receive(), 1, option, 0, NULL, NULL),
    200       false);
    201 
    202   // Realize the SL engine object in synchronous mode.
    203   LOG_ON_FAILURE_AND_RETURN(
    204       engine_object_->Realize(engine_object_.Get(), SL_BOOLEAN_FALSE), false);
    205 
    206   // Get the SL engine interface which is implicit.
    207   SLEngineItf engine;
    208   LOG_ON_FAILURE_AND_RETURN(engine_object_->GetInterface(
    209                                 engine_object_.Get(), SL_IID_ENGINE, &engine),
    210                             false);
    211 
    212   // Create ouput mixer object to be used by the player.
    213   LOG_ON_FAILURE_AND_RETURN((*engine)->CreateOutputMix(
    214                                 engine, output_mixer_.Receive(), 0, NULL, NULL),
    215                             false);
    216 
    217   // Realizing the output mix object in synchronous mode.
    218   LOG_ON_FAILURE_AND_RETURN(
    219       output_mixer_->Realize(output_mixer_.Get(), SL_BOOLEAN_FALSE), false);
    220 
    221   // Audio source configuration.
    222   SLDataLocator_AndroidSimpleBufferQueue simple_buffer_queue = {
    223       SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,
    224       static_cast<SLuint32>(kMaxNumOfBuffersInQueue)};
    225   SLDataSource audio_source = {&simple_buffer_queue, &format_};
    226 
    227   // Audio sink configuration.
    228   SLDataLocator_OutputMix locator_output_mix = {SL_DATALOCATOR_OUTPUTMIX,
    229                                                 output_mixer_.Get()};
    230   SLDataSink audio_sink = {&locator_output_mix, NULL};
    231 
    232   // Create an audio player.
    233   const SLInterfaceID interface_id[] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME,
    234                                         SL_IID_ANDROIDCONFIGURATION};
    235   const SLboolean interface_required[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE,
    236                                           SL_BOOLEAN_TRUE};
    237   LOG_ON_FAILURE_AND_RETURN(
    238       (*engine)->CreateAudioPlayer(engine,
    239                                    player_object_.Receive(),
    240                                    &audio_source,
    241                                    &audio_sink,
    242                                    arraysize(interface_id),
    243                                    interface_id,
    244                                    interface_required),
    245       false);
    246 
    247   // Create AudioPlayer and specify SL_IID_ANDROIDCONFIGURATION.
    248   SLAndroidConfigurationItf player_config;
    249   LOG_ON_FAILURE_AND_RETURN(
    250       player_object_->GetInterface(
    251           player_object_.Get(), SL_IID_ANDROIDCONFIGURATION, &player_config),
    252       false);
    253 
    254   // Set configuration using the stream type provided at construction.
    255   LOG_ON_FAILURE_AND_RETURN(
    256       (*player_config)->SetConfiguration(player_config,
    257                                          SL_ANDROID_KEY_STREAM_TYPE,
    258                                          &stream_type_,
    259                                          sizeof(SLint32)),
    260       false);
    261 
    262   // Realize the player object in synchronous mode.
    263   LOG_ON_FAILURE_AND_RETURN(
    264       player_object_->Realize(player_object_.Get(), SL_BOOLEAN_FALSE), false);
    265 
    266   // Get an implicit player interface.
    267   LOG_ON_FAILURE_AND_RETURN(
    268       player_object_->GetInterface(player_object_.Get(), SL_IID_PLAY, &player_),
    269       false);
    270 
    271   // Get the simple buffer queue interface.
    272   LOG_ON_FAILURE_AND_RETURN(
    273       player_object_->GetInterface(
    274           player_object_.Get(), SL_IID_BUFFERQUEUE, &simple_buffer_queue_),
    275       false);
    276 
    277   // Register the input callback for the simple buffer queue.
    278   // This callback will be called when the soundcard needs data.
    279   LOG_ON_FAILURE_AND_RETURN(
    280       (*simple_buffer_queue_)->RegisterCallback(
    281           simple_buffer_queue_, SimpleBufferQueueCallback, this),
    282       false);
    283 
    284   return true;
    285 }
    286 
    287 void OpenSLESOutputStream::SimpleBufferQueueCallback(
    288     SLAndroidSimpleBufferQueueItf buffer_queue,
    289     void* instance) {
    290   OpenSLESOutputStream* stream =
    291       reinterpret_cast<OpenSLESOutputStream*>(instance);
    292   stream->FillBufferQueue();
    293 }
    294 
    295 void OpenSLESOutputStream::FillBufferQueue() {
    296   base::AutoLock lock(lock_);
    297   if (!started_)
    298     return;
    299 
    300   TRACE_EVENT0("audio", "OpenSLESOutputStream::FillBufferQueue");
    301 
    302   // Verify that we are in a playing state.
    303   SLuint32 state;
    304   SLresult err = (*player_)->GetPlayState(player_, &state);
    305   if (SL_RESULT_SUCCESS != err) {
    306     HandleError(err);
    307     return;
    308   }
    309   if (state != SL_PLAYSTATE_PLAYING) {
    310     DLOG(WARNING) << "Received callback in non-playing state";
    311     return;
    312   }
    313 
    314   // Fill up one buffer in the queue by asking the registered source for
    315   // data using the OnMoreData() callback.
    316   FillBufferQueueNoLock();
    317 }
    318 
    319 void OpenSLESOutputStream::FillBufferQueueNoLock() {
    320   // Ensure that the calling thread has acquired the lock since it is not
    321   // done in this method.
    322   lock_.AssertAcquired();
    323 
    324   // Read data from the registered client source.
    325   // TODO(henrika): Investigate if it is possible to get a more accurate
    326   // delay estimation.
    327   const uint32 hardware_delay = buffer_size_bytes_;
    328   int frames_filled = callback_->OnMoreData(
    329       audio_bus_.get(), AudioBuffersState(0, hardware_delay));
    330   if (frames_filled <= 0) {
    331     // Audio source is shutting down, or halted on error.
    332     return;
    333   }
    334 
    335   // Note: If the internal representation ever changes from 16-bit PCM to
    336   // raw float, the data must be clipped and sanitized since it may come
    337   // from an untrusted source such as NaCl.
    338   audio_bus_->Scale(muted_ ? 0.0f : volume_);
    339   audio_bus_->ToInterleaved(frames_filled,
    340                             format_.bitsPerSample / 8,
    341                             audio_data_[active_buffer_index_]);
    342 
    343   const int num_filled_bytes =
    344       frames_filled * audio_bus_->channels() * format_.bitsPerSample / 8;
    345   DCHECK_LE(static_cast<size_t>(num_filled_bytes), buffer_size_bytes_);
    346 
    347   // Enqueue the buffer for playback.
    348   SLresult err =
    349       (*simple_buffer_queue_)->Enqueue(simple_buffer_queue_,
    350                                        audio_data_[active_buffer_index_],
    351                                        num_filled_bytes);
    352   if (SL_RESULT_SUCCESS != err)
    353     HandleError(err);
    354 
    355   active_buffer_index_ = (active_buffer_index_ + 1) % kMaxNumOfBuffersInQueue;
    356 }
    357 
    358 void OpenSLESOutputStream::SetupAudioBuffer() {
    359   DCHECK(thread_checker_.CalledOnValidThread());
    360   DCHECK(!audio_data_[0]);
    361   for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) {
    362     audio_data_[i] = new uint8[buffer_size_bytes_];
    363   }
    364 }
    365 
    366 void OpenSLESOutputStream::ReleaseAudioBuffer() {
    367   DCHECK(thread_checker_.CalledOnValidThread());
    368   if (audio_data_[0]) {
    369     for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) {
    370       delete[] audio_data_[i];
    371       audio_data_[i] = NULL;
    372     }
    373   }
    374 }
    375 
    376 void OpenSLESOutputStream::HandleError(SLresult error) {
    377   DLOG(ERROR) << "OpenSLES Output error " << error;
    378   if (callback_)
    379     callback_->OnError(this);
    380 }
    381 
    382 }  // namespace media
    383