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