Home | History | Annotate | Download | only in pulse
      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/pulse/pulse_input.h"
      6 
      7 #include "base/logging.h"
      8 #include "media/audio/pulse/audio_manager_pulse.h"
      9 #include "media/audio/pulse/pulse_util.h"
     10 
     11 namespace media {
     12 
     13 using pulse::AutoPulseLock;
     14 using pulse::WaitForOperationCompletion;
     15 
     16 // Number of blocks of buffers used in the |fifo_|.
     17 const int kNumberOfBlocksBufferInFifo = 2;
     18 
     19 PulseAudioInputStream::PulseAudioInputStream(AudioManagerPulse* audio_manager,
     20                                              const std::string& device_name,
     21                                              const AudioParameters& params,
     22                                              pa_threaded_mainloop* mainloop,
     23                                              pa_context* context)
     24     : audio_manager_(audio_manager),
     25       callback_(NULL),
     26       device_name_(device_name),
     27       params_(params),
     28       channels_(0),
     29       volume_(0.0),
     30       stream_started_(false),
     31       muted_(false),
     32       fifo_(params.channels(),
     33             params.frames_per_buffer(),
     34             kNumberOfBlocksBufferInFifo),
     35       pa_mainloop_(mainloop),
     36       pa_context_(context),
     37       handle_(NULL),
     38       context_state_changed_(false) {
     39   DCHECK(mainloop);
     40   DCHECK(context);
     41   CHECK(params_.IsValid());
     42 }
     43 
     44 PulseAudioInputStream::~PulseAudioInputStream() {
     45   // All internal structures should already have been freed in Close(),
     46   // which calls AudioManagerPulse::Release which deletes this object.
     47   DCHECK(!handle_);
     48 }
     49 
     50 bool PulseAudioInputStream::Open() {
     51   DCHECK(thread_checker_.CalledOnValidThread());
     52   AutoPulseLock auto_lock(pa_mainloop_);
     53   if (!pulse::CreateInputStream(pa_mainloop_, pa_context_, &handle_, params_,
     54                                 device_name_, &StreamNotifyCallback, this)) {
     55     return false;
     56   }
     57 
     58   DCHECK(handle_);
     59 
     60   return true;
     61 }
     62 
     63 void PulseAudioInputStream::Start(AudioInputCallback* callback) {
     64   DCHECK(thread_checker_.CalledOnValidThread());
     65   DCHECK(callback);
     66   DCHECK(handle_);
     67 
     68   // AGC needs to be started out of the lock.
     69   StartAgc();
     70 
     71   AutoPulseLock auto_lock(pa_mainloop_);
     72 
     73   if (stream_started_)
     74     return;
     75 
     76   // Clean up the old buffer.
     77   pa_stream_drop(handle_);
     78   fifo_.Clear();
     79 
     80   // Start the streaming.
     81   callback_ = callback;
     82   pa_stream_set_read_callback(handle_, &ReadCallback, this);
     83   pa_stream_readable_size(handle_);
     84   stream_started_ = true;
     85 
     86   pa_operation* operation = pa_stream_cork(handle_, 0, NULL, NULL);
     87   WaitForOperationCompletion(pa_mainloop_, operation);
     88 }
     89 
     90 void PulseAudioInputStream::Stop() {
     91   DCHECK(thread_checker_.CalledOnValidThread());
     92   AutoPulseLock auto_lock(pa_mainloop_);
     93   if (!stream_started_)
     94     return;
     95 
     96   StopAgc();
     97 
     98   // Set the flag to false to stop filling new data to soundcard.
     99   stream_started_ = false;
    100 
    101   pa_operation* operation = pa_stream_flush(handle_,
    102                                             &pulse::StreamSuccessCallback,
    103                                             pa_mainloop_);
    104   WaitForOperationCompletion(pa_mainloop_, operation);
    105 
    106   // Stop the stream.
    107   pa_stream_set_read_callback(handle_, NULL, NULL);
    108   operation = pa_stream_cork(handle_, 1, &pulse::StreamSuccessCallback,
    109                              pa_mainloop_);
    110   WaitForOperationCompletion(pa_mainloop_, operation);
    111   callback_ = NULL;
    112 }
    113 
    114 void PulseAudioInputStream::Close() {
    115   DCHECK(thread_checker_.CalledOnValidThread());
    116   {
    117     AutoPulseLock auto_lock(pa_mainloop_);
    118     if (handle_) {
    119       // Disable all the callbacks before disconnecting.
    120       pa_stream_set_state_callback(handle_, NULL, NULL);
    121       pa_operation* operation = pa_stream_flush(
    122           handle_, &pulse::StreamSuccessCallback, pa_mainloop_);
    123       WaitForOperationCompletion(pa_mainloop_, operation);
    124 
    125       if (pa_stream_get_state(handle_) != PA_STREAM_UNCONNECTED)
    126         pa_stream_disconnect(handle_);
    127 
    128       // Release PulseAudio structures.
    129       pa_stream_unref(handle_);
    130       handle_ = NULL;
    131     }
    132   }
    133 
    134   // Signal to the manager that we're closed and can be removed.
    135   // This should be the last call in the function as it deletes "this".
    136   audio_manager_->ReleaseInputStream(this);
    137 }
    138 
    139 double PulseAudioInputStream::GetMaxVolume() {
    140   return static_cast<double>(PA_VOLUME_NORM);
    141 }
    142 
    143 void PulseAudioInputStream::SetVolume(double volume) {
    144   AutoPulseLock auto_lock(pa_mainloop_);
    145   if (!handle_)
    146     return;
    147 
    148   size_t index = pa_stream_get_device_index(handle_);
    149   pa_operation* operation = NULL;
    150   if (!channels_) {
    151     // Get the number of channels for the source only when the |channels_| is 0.
    152     // We are assuming the stream source is not changed on the fly here.
    153     operation = pa_context_get_source_info_by_index(
    154         pa_context_, index, &VolumeCallback, this);
    155     WaitForOperationCompletion(pa_mainloop_, operation);
    156     if (!channels_) {
    157       DLOG(WARNING) << "Failed to get the number of channels for the source";
    158       return;
    159     }
    160   }
    161 
    162   pa_cvolume pa_volume;
    163   pa_cvolume_set(&pa_volume, channels_, volume);
    164   operation = pa_context_set_source_volume_by_index(
    165       pa_context_, index, &pa_volume, NULL, NULL);
    166 
    167   // Don't need to wait for this task to complete.
    168   pa_operation_unref(operation);
    169 }
    170 
    171 double PulseAudioInputStream::GetVolume() {
    172   if (pa_threaded_mainloop_in_thread(pa_mainloop_)) {
    173     // When being called by the pulse thread, GetVolume() is asynchronous and
    174     // called under AutoPulseLock.
    175     if (!handle_)
    176       return 0.0;
    177 
    178     size_t index = pa_stream_get_device_index(handle_);
    179     pa_operation* operation = pa_context_get_source_info_by_index(
    180         pa_context_, index, &VolumeCallback, this);
    181     // Do not wait for the operation since we can't block the pulse thread.
    182     pa_operation_unref(operation);
    183 
    184     // Return zero and the callback will asynchronously update the |volume_|.
    185     return 0.0;
    186   } else {
    187     GetSourceInformation(&VolumeCallback);
    188     return volume_;
    189   }
    190 }
    191 
    192 bool PulseAudioInputStream::IsMuted() {
    193   DCHECK(thread_checker_.CalledOnValidThread());
    194   GetSourceInformation(&MuteCallback);
    195   return muted_;
    196 }
    197 
    198 // static, used by pa_stream_set_read_callback.
    199 void PulseAudioInputStream::ReadCallback(pa_stream* handle,
    200                                          size_t length,
    201                                          void* user_data) {
    202   PulseAudioInputStream* stream =
    203       reinterpret_cast<PulseAudioInputStream*>(user_data);
    204 
    205   stream->ReadData();
    206 }
    207 
    208 // static, used by pa_context_get_source_info_by_index.
    209 void PulseAudioInputStream::VolumeCallback(pa_context* context,
    210                                            const pa_source_info* info,
    211                                            int error, void* user_data) {
    212   PulseAudioInputStream* stream =
    213       reinterpret_cast<PulseAudioInputStream*>(user_data);
    214 
    215   if (error) {
    216     pa_threaded_mainloop_signal(stream->pa_mainloop_, 0);
    217     return;
    218   }
    219 
    220   if (stream->channels_ != info->channel_map.channels)
    221     stream->channels_ = info->channel_map.channels;
    222 
    223   pa_volume_t volume = PA_VOLUME_MUTED;  // Minimum possible value.
    224   // Use the max volume of any channel as the volume.
    225   for (int i = 0; i < stream->channels_; ++i) {
    226     if (volume < info->volume.values[i])
    227       volume = info->volume.values[i];
    228   }
    229 
    230   // It is safe to access |volume_| here since VolumeCallback() is running
    231   // under PulseLock.
    232   stream->volume_ = static_cast<double>(volume);
    233 }
    234 
    235 // static, used by pa_context_get_source_info_by_index.
    236 void PulseAudioInputStream::MuteCallback(pa_context* context,
    237                                          const pa_source_info* info,
    238                                          int error,
    239                                          void* user_data) {
    240   // Runs on PulseAudio callback thread. It might be possible to make this
    241   // method more thread safe by passing a struct (or pair) of a local copy of
    242   // |pa_mainloop_| and |muted_| instead.
    243   PulseAudioInputStream* stream =
    244       reinterpret_cast<PulseAudioInputStream*>(user_data);
    245 
    246   // Avoid infinite wait loop in case of error.
    247   if (error) {
    248     pa_threaded_mainloop_signal(stream->pa_mainloop_, 0);
    249     return;
    250   }
    251 
    252   stream->muted_ = info->mute != 0;
    253 }
    254 
    255 // static, used by pa_stream_set_state_callback.
    256 void PulseAudioInputStream::StreamNotifyCallback(pa_stream* s,
    257                                                  void* user_data) {
    258   PulseAudioInputStream* stream =
    259       reinterpret_cast<PulseAudioInputStream*>(user_data);
    260 
    261   if (s && stream->callback_ &&
    262       pa_stream_get_state(s) == PA_STREAM_FAILED) {
    263     stream->callback_->OnError(stream);
    264   }
    265 
    266   pa_threaded_mainloop_signal(stream->pa_mainloop_, 0);
    267 }
    268 
    269 void PulseAudioInputStream::ReadData() {
    270   uint32 hardware_delay = pulse::GetHardwareLatencyInBytes(
    271       handle_, params_.sample_rate(), params_.GetBytesPerFrame());
    272 
    273   // Update the AGC volume level once every second. Note that,
    274   // |volume| is also updated each time SetVolume() is called
    275   // through IPC by the render-side AGC.
    276   // We disregard the |normalized_volume| from GetAgcVolume()
    277   // and use the value calculated by |volume_|.
    278   double normalized_volume = 0.0;
    279   GetAgcVolume(&normalized_volume);
    280   normalized_volume = volume_ / GetMaxVolume();
    281 
    282   do {
    283     size_t length = 0;
    284     const void* data = NULL;
    285     pa_stream_peek(handle_, &data, &length);
    286     if (!data || length == 0)
    287       break;
    288 
    289     const int number_of_frames = length / params_.GetBytesPerFrame();
    290     if (number_of_frames > fifo_.GetUnfilledFrames()) {
    291       // Dynamically increase capacity to the FIFO to handle larger buffer got
    292       // from Pulse.
    293       const int increase_blocks_of_buffer = static_cast<int>(
    294           (number_of_frames - fifo_.GetUnfilledFrames()) /
    295               params_.frames_per_buffer()) + 1;
    296       fifo_.IncreaseCapacity(increase_blocks_of_buffer);
    297     }
    298 
    299     fifo_.Push(data, number_of_frames, params_.bits_per_sample() / 8);
    300 
    301     // Checks if we still have data.
    302     pa_stream_drop(handle_);
    303   } while (pa_stream_readable_size(handle_) > 0);
    304 
    305   while (fifo_.available_blocks()) {
    306     const AudioBus* audio_bus = fifo_.Consume();
    307 
    308     // Compensate the audio delay caused by the FIFO.
    309     hardware_delay += fifo_.GetAvailableFrames() * params_.GetBytesPerFrame();
    310     callback_->OnData(this, audio_bus, hardware_delay, normalized_volume);
    311 
    312     // Sleep 5ms to wait until render consumes the data in order to avoid
    313     // back to back OnData() method.
    314     if (fifo_.available_blocks())
    315       base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(5));
    316   }
    317 
    318   pa_threaded_mainloop_signal(pa_mainloop_, 0);
    319 }
    320 
    321 bool PulseAudioInputStream::GetSourceInformation(pa_source_info_cb_t callback) {
    322   AutoPulseLock auto_lock(pa_mainloop_);
    323   if (!handle_)
    324     return false;
    325 
    326   size_t index = pa_stream_get_device_index(handle_);
    327   pa_operation* operation =
    328       pa_context_get_source_info_by_index(pa_context_, index, callback, this);
    329   WaitForOperationCompletion(pa_mainloop_, operation);
    330   return true;
    331 }
    332 
    333 }  // namespace media
    334