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