| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/audio/pulse/pulse_input.h" | 5 #include "media/audio/pulse/pulse_input.h" |
| 6 | 6 |
| 7 #include <pulse/pulseaudio.h> | 7 #include <pulse/pulseaudio.h> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "media/audio/pulse/audio_manager_pulse.h" | 10 #include "media/audio/pulse/audio_manager_pulse.h" |
| 11 #include "media/audio/pulse/pulse_util.h" | 11 #include "media/audio/pulse/pulse_util.h" |
| 12 #include "media/base/seekable_buffer.h" | |
| 13 | 12 |
| 14 namespace media { | 13 namespace media { |
| 15 | 14 |
| 16 using pulse::AutoPulseLock; | 15 using pulse::AutoPulseLock; |
| 17 using pulse::WaitForOperationCompletion; | 16 using pulse::WaitForOperationCompletion; |
| 18 | 17 |
| 18 // Number of blocks of buffers used in the |fifo_|. |
| 19 const int kNumberOfBlocksBufferInFifo = 2; |
| 20 |
| 19 PulseAudioInputStream::PulseAudioInputStream(AudioManagerPulse* audio_manager, | 21 PulseAudioInputStream::PulseAudioInputStream(AudioManagerPulse* audio_manager, |
| 20 const std::string& device_name, | 22 const std::string& device_name, |
| 21 const AudioParameters& params, | 23 const AudioParameters& params, |
| 22 pa_threaded_mainloop* mainloop, | 24 pa_threaded_mainloop* mainloop, |
| 23 pa_context* context) | 25 pa_context* context) |
| 24 : audio_manager_(audio_manager), | 26 : audio_manager_(audio_manager), |
| 25 callback_(NULL), | 27 callback_(NULL), |
| 26 device_name_(device_name), | 28 device_name_(device_name), |
| 27 params_(params), | 29 params_(params), |
| 28 channels_(0), | 30 channels_(0), |
| 29 volume_(0.0), | 31 volume_(0.0), |
| 30 stream_started_(false), | 32 stream_started_(false), |
| 33 fifo_(params.channels(), |
| 34 params.frames_per_buffer(), |
| 35 kNumberOfBlocksBufferInFifo), |
| 31 pa_mainloop_(mainloop), | 36 pa_mainloop_(mainloop), |
| 32 pa_context_(context), | 37 pa_context_(context), |
| 33 handle_(NULL), | 38 handle_(NULL), |
| 34 context_state_changed_(false) { | 39 context_state_changed_(false) { |
| 35 DCHECK(mainloop); | 40 DCHECK(mainloop); |
| 36 DCHECK(context); | 41 DCHECK(context); |
| 37 CHECK(params_.IsValid()); | 42 CHECK(params_.IsValid()); |
| 38 audio_bus_ = AudioBus::Create(params_); | |
| 39 } | 43 } |
| 40 | 44 |
| 41 PulseAudioInputStream::~PulseAudioInputStream() { | 45 PulseAudioInputStream::~PulseAudioInputStream() { |
| 42 // All internal structures should already have been freed in Close(), | 46 // All internal structures should already have been freed in Close(), |
| 43 // which calls AudioManagerPulse::Release which deletes this object. | 47 // which calls AudioManagerPulse::Release which deletes this object. |
| 44 DCHECK(!handle_); | 48 DCHECK(!handle_); |
| 45 } | 49 } |
| 46 | 50 |
| 47 bool PulseAudioInputStream::Open() { | 51 bool PulseAudioInputStream::Open() { |
| 48 DCHECK(thread_checker_.CalledOnValidThread()); | 52 DCHECK(thread_checker_.CalledOnValidThread()); |
| 49 AutoPulseLock auto_lock(pa_mainloop_); | 53 AutoPulseLock auto_lock(pa_mainloop_); |
| 50 if (!pulse::CreateInputStream(pa_mainloop_, pa_context_, &handle_, params_, | 54 if (!pulse::CreateInputStream(pa_mainloop_, pa_context_, &handle_, params_, |
| 51 device_name_, &StreamNotifyCallback, this)) { | 55 device_name_, &StreamNotifyCallback, this)) { |
| 52 return false; | 56 return false; |
| 53 } | 57 } |
| 54 | 58 |
| 55 DCHECK(handle_); | 59 DCHECK(handle_); |
| 56 | 60 |
| 57 buffer_.reset(new media::SeekableBuffer(0, 2 * params_.GetBytesPerBuffer())); | |
| 58 audio_data_buffer_.reset(new uint8[params_.GetBytesPerBuffer()]); | |
| 59 return true; | 61 return true; |
| 60 } | 62 } |
| 61 | 63 |
| 62 void PulseAudioInputStream::Start(AudioInputCallback* callback) { | 64 void PulseAudioInputStream::Start(AudioInputCallback* callback) { |
| 63 DCHECK(thread_checker_.CalledOnValidThread()); | 65 DCHECK(thread_checker_.CalledOnValidThread()); |
| 64 DCHECK(callback); | 66 DCHECK(callback); |
| 65 DCHECK(handle_); | 67 DCHECK(handle_); |
| 66 | 68 |
| 67 // AGC needs to be started out of the lock. | 69 // AGC needs to be started out of the lock. |
| 68 StartAgc(); | 70 StartAgc(); |
| 69 | 71 |
| 70 AutoPulseLock auto_lock(pa_mainloop_); | 72 AutoPulseLock auto_lock(pa_mainloop_); |
| 71 | 73 |
| 72 if (stream_started_) | 74 if (stream_started_) |
| 73 return; | 75 return; |
| 74 | 76 |
| 75 // Clean up the old buffer. | 77 // Clean up the old buffer. |
| 76 pa_stream_drop(handle_); | 78 pa_stream_drop(handle_); |
| 77 buffer_->Clear(); | 79 fifo_.Clear(); |
| 78 | 80 |
| 79 // Start the streaming. | 81 // Start the streaming. |
| 80 callback_ = callback; | 82 callback_ = callback; |
| 81 pa_stream_set_read_callback(handle_, &ReadCallback, this); | 83 pa_stream_set_read_callback(handle_, &ReadCallback, this); |
| 82 pa_stream_readable_size(handle_); | 84 pa_stream_readable_size(handle_); |
| 83 stream_started_ = true; | 85 stream_started_ = true; |
| 84 | 86 |
| 85 pa_operation* operation = pa_stream_cork(handle_, 0, NULL, NULL); | 87 pa_operation* operation = pa_stream_cork(handle_, 0, NULL, NULL); |
| 86 WaitForOperationCompletion(pa_mainloop_, operation); | 88 WaitForOperationCompletion(pa_mainloop_, operation); |
| 87 } | 89 } |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 258 GetAgcVolume(&normalized_volume); | 260 GetAgcVolume(&normalized_volume); |
| 259 normalized_volume = volume_ / GetMaxVolume(); | 261 normalized_volume = volume_ / GetMaxVolume(); |
| 260 | 262 |
| 261 do { | 263 do { |
| 262 size_t length = 0; | 264 size_t length = 0; |
| 263 const void* data = NULL; | 265 const void* data = NULL; |
| 264 pa_stream_peek(handle_, &data, &length); | 266 pa_stream_peek(handle_, &data, &length); |
| 265 if (!data || length == 0) | 267 if (!data || length == 0) |
| 266 break; | 268 break; |
| 267 | 269 |
| 268 buffer_->Append(reinterpret_cast<const uint8*>(data), length); | 270 const int number_of_frames = length / params_.GetBytesPerFrame(); |
| 271 fifo_.Push(data, number_of_frames, params_.bits_per_sample() / 8); |
| 269 | 272 |
| 270 // Checks if we still have data. | 273 // Checks if we still have data. |
| 271 pa_stream_drop(handle_); | 274 pa_stream_drop(handle_); |
| 272 } while (pa_stream_readable_size(handle_) > 0); | 275 } while (pa_stream_readable_size(handle_) > 0); |
| 273 | 276 |
| 274 int packet_size = params_.GetBytesPerBuffer(); | 277 while (fifo_.available_blocks()) { |
| 275 while (buffer_->forward_bytes() >= packet_size) { | 278 const AudioBus* audio_bus = fifo_.Consume(); |
| 276 buffer_->Read(audio_data_buffer_.get(), packet_size); | |
| 277 audio_bus_->FromInterleaved(audio_data_buffer_.get(), | |
| 278 audio_bus_->frames(), | |
| 279 params_.bits_per_sample() / 8); | |
| 280 callback_->OnData( | |
| 281 this, audio_bus_.get(), hardware_delay, normalized_volume); | |
| 282 | 279 |
| 283 if (buffer_->forward_bytes() < packet_size) | 280 // Compensate the audio delay caused by the FIFO. |
| 284 break; | 281 hardware_delay += fifo_.GetAvailableFrames() * params_.GetBytesPerFrame(); |
| 282 callback_->OnData(this, audio_bus, hardware_delay, normalized_volume); |
| 285 | 283 |
| 286 // TODO(xians): Remove once PPAPI is using circular buffers. | 284 // TODO(xians): Remove once PPAPI is using circular buffers. |
| 287 DVLOG(1) << "OnData is being called consecutively, sleep 5ms to " | 285 DVLOG(1) << "OnData is being called consecutively, sleep 5ms to " |
| 288 << "wait until render consumes the data"; | 286 << "wait until render consumes the data"; |
| 289 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(5)); | 287 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(5)); |
| 290 } | 288 } |
| 291 | 289 |
| 292 pa_threaded_mainloop_signal(pa_mainloop_, 0); | 290 pa_threaded_mainloop_signal(pa_mainloop_, 0); |
| 293 } | 291 } |
| 294 | 292 |
| 295 } // namespace media | 293 } // namespace media |
| OLD | NEW |