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
11namespace media {
12
13using pulse::AutoPulseLock;
14using pulse::WaitForOperationCompletion;
15
16// Number of blocks of buffers used in the |fifo_|.
17const int kNumberOfBlocksBufferInFifo = 2;
18
19PulseAudioInputStream::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
44PulseAudioInputStream::~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
50bool 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
63void 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
90void 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
114void 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
139double PulseAudioInputStream::GetMaxVolume() {
140  return static_cast<double>(PA_VOLUME_NORM);
141}
142
143void 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
171double 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
192bool PulseAudioInputStream::IsMuted() {
193  DCHECK(thread_checker_.CalledOnValidThread());
194  GetSourceInformation(&MuteCallback);
195  return muted_;
196}
197
198// static, used by pa_stream_set_read_callback.
199void 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.
209void 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.
236void 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.
256void 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
269void 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
321bool 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