pulse_input.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
130692c65c4174412c90e79489e98ab85c1a7412fBen Cheng// Copyright (c) 2012 The Chromium Authors. All rights reserved. 230692c65c4174412c90e79489e98ab85c1a7412fBen Cheng// Use of this source code is governed by a BSD-style license that can be 330692c65c4174412c90e79489e98ab85c1a7412fBen Cheng// found in the LICENSE file. 430692c65c4174412c90e79489e98ab85c1a7412fBen Cheng 530692c65c4174412c90e79489e98ab85c1a7412fBen Cheng#include "media/audio/pulse/pulse_input.h" 630692c65c4174412c90e79489e98ab85c1a7412fBen Cheng 730692c65c4174412c90e79489e98ab85c1a7412fBen Cheng#include <pulse/pulseaudio.h> 830692c65c4174412c90e79489e98ab85c1a7412fBen Cheng 930692c65c4174412c90e79489e98ab85c1a7412fBen Cheng#include "base/logging.h" 1030692c65c4174412c90e79489e98ab85c1a7412fBen Cheng#include "base/message_loop.h" 1130692c65c4174412c90e79489e98ab85c1a7412fBen Cheng#include "media/audio/pulse/audio_manager_pulse.h" 1230692c65c4174412c90e79489e98ab85c1a7412fBen Cheng#include "media/audio/pulse/pulse_util.h" 13#include "media/base/seekable_buffer.h" 14 15namespace media { 16 17using pulse::AutoPulseLock; 18using pulse::WaitForOperationCompletion; 19 20PulseAudioInputStream::PulseAudioInputStream(AudioManagerPulse* audio_manager, 21 const std::string& device_name, 22 const AudioParameters& params, 23 pa_threaded_mainloop* mainloop, 24 pa_context* context) 25 : audio_manager_(audio_manager), 26 callback_(NULL), 27 device_name_(device_name), 28 params_(params), 29 channels_(0), 30 volume_(0.0), 31 stream_started_(false), 32 pa_mainloop_(mainloop), 33 pa_context_(context), 34 handle_(NULL), 35 context_state_changed_(false) { 36 DCHECK(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); 37 DCHECK(mainloop); 38 DCHECK(context); 39} 40 41PulseAudioInputStream::~PulseAudioInputStream() { 42 // All internal structures should already have been freed in Close(), 43 // which calls AudioManagerPulse::Release which deletes this object. 44 DCHECK(!handle_); 45} 46 47bool PulseAudioInputStream::Open() { 48 DCHECK(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); 49 AutoPulseLock auto_lock(pa_mainloop_); 50 51 // Set sample specifications. 52 pa_sample_spec pa_sample_specifications; 53 pa_sample_specifications.format = pulse::BitsToPASampleFormat( 54 params_.bits_per_sample()); 55 pa_sample_specifications.rate = params_.sample_rate(); 56 pa_sample_specifications.channels = params_.channels(); 57 58 // Get channel mapping and open recording stream. 59 pa_channel_map source_channel_map = pulse::ChannelLayoutToPAChannelMap( 60 params_.channel_layout()); 61 pa_channel_map* map = (source_channel_map.channels != 0)? 62 &source_channel_map : NULL; 63 64 // Create a new recording stream. 65 handle_ = pa_stream_new(pa_context_, "RecordStream", 66 &pa_sample_specifications, map); 67 if (!handle_) { 68 DLOG(ERROR) << "Open: failed to create PA stream"; 69 return false; 70 } 71 72 pa_stream_set_state_callback(handle_, &StreamNotifyCallback, this); 73 74 // Set server-side capture buffer metrics. Detailed documentation on what 75 // values should be chosen can be found at 76 // freedesktop.org/software/pulseaudio/doxygen/structpa__buffer__attr.html. 77 pa_buffer_attr buffer_attributes; 78 const unsigned int buffer_size = params_.GetBytesPerBuffer(); 79 buffer_attributes.maxlength = static_cast<uint32_t>(-1); 80 buffer_attributes.tlength = buffer_size; 81 buffer_attributes.minreq = buffer_size; 82 buffer_attributes.prebuf = static_cast<uint32_t>(-1); 83 buffer_attributes.fragsize = buffer_size; 84 int flags = PA_STREAM_AUTO_TIMING_UPDATE | 85 PA_STREAM_INTERPOLATE_TIMING | 86 PA_STREAM_ADJUST_LATENCY | 87 PA_STREAM_START_CORKED; 88 int err = pa_stream_connect_record( 89 handle_, 90 device_name_ == AudioManagerBase::kDefaultDeviceId ? 91 NULL : device_name_.c_str(), 92 &buffer_attributes, 93 static_cast<pa_stream_flags_t>(flags)); 94 if (err) { 95 DLOG(ERROR) << "pa_stream_connect_playback FAILED " << err; 96 return false; 97 } 98 99 // Wait for the stream to be ready. 100 while (true) { 101 pa_stream_state_t stream_state = pa_stream_get_state(handle_); 102 if(!PA_STREAM_IS_GOOD(stream_state)) { 103 DLOG(ERROR) << "Invalid PulseAudio stream state"; 104 return false; 105 } 106 107 if (stream_state == PA_STREAM_READY) 108 break; 109 pa_threaded_mainloop_wait(pa_mainloop_); 110 } 111 112 pa_stream_set_read_callback(handle_, &ReadCallback, this); 113 pa_stream_readable_size(handle_); 114 115 buffer_.reset(new media::SeekableBuffer(0, 2 * params_.GetBytesPerBuffer())); 116 audio_data_buffer_.reset(new uint8[params_.GetBytesPerBuffer()]); 117 return true; 118} 119 120void PulseAudioInputStream::Start(AudioInputCallback* callback) { 121 DCHECK(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); 122 DCHECK(callback); 123 DCHECK(handle_); 124 AutoPulseLock auto_lock(pa_mainloop_); 125 126 if (stream_started_) 127 return; 128 129 // Clean up the old buffer. 130 pa_stream_drop(handle_); 131 buffer_->Clear(); 132 133 // Start the streaming. 134 stream_started_ = true; 135 callback_ = callback; 136 137 pa_operation* operation = pa_stream_cork(handle_, 0, NULL, NULL); 138 WaitForOperationCompletion(pa_mainloop_, operation); 139} 140 141void PulseAudioInputStream::Stop() { 142 DCHECK(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); 143 AutoPulseLock auto_lock(pa_mainloop_); 144 if (!stream_started_) 145 return; 146 147 // Set the flag to false to stop filling new data to soundcard. 148 stream_started_ = false; 149 150 pa_operation* operation = pa_stream_flush( 151 handle_, &pulse::StreamSuccessCallback, pa_mainloop_); 152 WaitForOperationCompletion(pa_mainloop_, operation); 153 154 // Stop the stream. 155 pa_stream_set_read_callback(handle_, NULL, NULL); 156 operation = pa_stream_cork(handle_, 1, &pulse::StreamSuccessCallback, 157 pa_mainloop_); 158 WaitForOperationCompletion(pa_mainloop_, operation); 159} 160 161void PulseAudioInputStream::Close() { 162 DCHECK(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); 163 { 164 AutoPulseLock auto_lock(pa_mainloop_); 165 if (handle_) { 166 // Disable all the callbacks before disconnecting. 167 pa_stream_set_state_callback(handle_, NULL, NULL); 168 pa_stream_flush(handle_, NULL, NULL); 169 170 if (pa_stream_get_state(handle_) != PA_STREAM_UNCONNECTED) 171 pa_stream_disconnect(handle_); 172 173 // Release PulseAudio structures. 174 pa_stream_unref(handle_); 175 handle_ = NULL; 176 } 177 } 178 179 if (callback_) 180 callback_->OnClose(this); 181 182 // Signal to the manager that we're closed and can be removed. 183 // This should be the last call in the function as it deletes "this". 184 audio_manager_->ReleaseInputStream(this); 185} 186 187double PulseAudioInputStream::GetMaxVolume() { 188 return static_cast<double>(PA_VOLUME_NORM); 189} 190 191void PulseAudioInputStream::SetVolume(double volume) { 192 AutoPulseLock auto_lock(pa_mainloop_); 193 if (!handle_) 194 return; 195 196 size_t index = pa_stream_get_device_index(handle_); 197 pa_operation* operation = NULL; 198 if (!channels_) { 199 // Get the number of channels for the source only when the |channels_| is 0. 200 // We are assuming the stream source is not changed on the fly here. 201 operation = pa_context_get_source_info_by_index( 202 pa_context_, index, &VolumeCallback, this); 203 WaitForOperationCompletion(pa_mainloop_, operation); 204 if (!channels_) { 205 DLOG(WARNING) << "Failed to get the number of channels for the source"; 206 return; 207 } 208 } 209 210 pa_cvolume pa_volume; 211 pa_cvolume_set(&pa_volume, channels_, volume); 212 operation = pa_context_set_source_volume_by_index( 213 pa_context_, index, &pa_volume, NULL, NULL); 214 215 // Don't need to wait for this task to complete. 216 pa_operation_unref(operation); 217} 218 219double PulseAudioInputStream::GetVolume() { 220 if (pa_threaded_mainloop_in_thread(pa_mainloop_)) { 221 // When being called by the pulse thread, GetVolume() is asynchronous and 222 // called under AutoPulseLock. 223 if (!handle_) 224 return 0.0; 225 226 size_t index = pa_stream_get_device_index(handle_); 227 pa_operation* operation = pa_context_get_source_info_by_index( 228 pa_context_, index, &VolumeCallback, this); 229 // Do not wait for the operation since we can't block the pulse thread. 230 pa_operation_unref(operation); 231 232 // Return zero and the callback will asynchronously update the |volume_|. 233 return 0.0; 234 } else { 235 // Called by other thread, put an AutoPulseLock and wait for the operation. 236 AutoPulseLock auto_lock(pa_mainloop_); 237 if (!handle_) 238 return 0.0; 239 240 size_t index = pa_stream_get_device_index(handle_); 241 pa_operation* operation = pa_context_get_source_info_by_index( 242 pa_context_, index, &VolumeCallback, this); 243 WaitForOperationCompletion(pa_mainloop_, operation); 244 245 return volume_; 246 } 247} 248 249// static, used by pa_stream_set_read_callback. 250void PulseAudioInputStream::ReadCallback(pa_stream* handle, 251 size_t length, 252 void* user_data) { 253 PulseAudioInputStream* stream = 254 reinterpret_cast<PulseAudioInputStream*>(user_data); 255 256 stream->ReadData(); 257} 258 259// static, used by pa_context_get_source_info_by_index. 260void PulseAudioInputStream::VolumeCallback(pa_context* context, 261 const pa_source_info* info, 262 int error, void* user_data) { 263 PulseAudioInputStream* stream = 264 reinterpret_cast<PulseAudioInputStream*>(user_data); 265 266 if (error) { 267 pa_threaded_mainloop_signal(stream->pa_mainloop_, 0); 268 return; 269 } 270 271 if (stream->channels_ != info->channel_map.channels) 272 stream->channels_ = info->channel_map.channels; 273 274 pa_volume_t volume = PA_VOLUME_MUTED; // Minimum possible value. 275 // Use the max volume of any channel as the volume. 276 for (int i = 0; i < stream->channels_; ++i) { 277 if (volume < info->volume.values[i]) 278 volume = info->volume.values[i]; 279 } 280 281 // It is safe to access |volume_| here since VolumeCallback() is running 282 // under PulseLock. 283 stream->volume_ = static_cast<double>(volume); 284} 285 286// static, used by pa_stream_set_state_callback. 287void PulseAudioInputStream::StreamNotifyCallback(pa_stream* s, 288 void* user_data) { 289 PulseAudioInputStream* stream = 290 reinterpret_cast<PulseAudioInputStream*>(user_data); 291 if (s && stream->callback_ && 292 pa_stream_get_state(s) == PA_STREAM_FAILED) { 293 stream->callback_->OnError(stream); 294 } 295 296 pa_threaded_mainloop_signal(stream->pa_mainloop_, 0); 297} 298 299void PulseAudioInputStream::ReadData() { 300 uint32 hardware_delay = pulse::GetHardwareLatencyInBytes( 301 handle_, params_.sample_rate(), params_.GetBytesPerFrame()); 302 303 // Update the AGC volume level once every second. Note that, 304 // |volume| is also updated each time SetVolume() is called 305 // through IPC by the render-side AGC. 306 // QueryAgcVolume() will trigger a callback to asynchronously update the 307 // |volume_|, we disregard the |normalized_volume| from QueryAgcVolume() 308 // and use the value calculated by |volume_|. 309 double normalized_volume = 0.0; 310 QueryAgcVolume(&normalized_volume); 311 normalized_volume = volume_ / GetMaxVolume(); 312 313 do { 314 size_t length = 0; 315 const void* data = NULL; 316 pa_stream_peek(handle_, &data, &length); 317 if (!data || length == 0) 318 break; 319 320 buffer_->Append(reinterpret_cast<const uint8*>(data), length); 321 322 // Checks if we still have data. 323 pa_stream_drop(handle_); 324 } while (pa_stream_readable_size(handle_) > 0); 325 326 int packet_size = params_.GetBytesPerBuffer(); 327 while (buffer_->forward_bytes() >= packet_size) { 328 buffer_->Read(audio_data_buffer_.get(), packet_size); 329 callback_->OnData(this, audio_data_buffer_.get(), packet_size, 330 hardware_delay, normalized_volume); 331 332 if (buffer_->forward_bytes() < packet_size) 333 break; 334 335 // TODO(xians): improve the code by implementing a WaitTillDataReady on the 336 // input side. 337 DVLOG(1) << "OnData is being called consecutively, sleep 5ms to " 338 << "wait until render consumes the data"; 339 base::PlatformThread::Sleep( 340 base::TimeDelta::FromMilliseconds(5)); 341 } 342 343 pa_threaded_mainloop_signal(pa_mainloop_, 0); 344} 345 346} // namespace media 347