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