| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "remoting/host/audio_capturer_linux.h" |
| |
| #include "base/files/file_path.h" |
| #include "base/lazy_instance.h" |
| #include "base/logging.h" |
| #include "remoting/proto/audio.pb.h" |
| |
| namespace remoting { |
| |
| namespace { |
| |
| // PulseAudio's module-pipe-sink must be configured to use the following |
| // parameters for the sink we read from. |
| const AudioPacket_SamplingRate kSamplingRate = AudioPacket::SAMPLING_RATE_48000; |
| |
| base::LazyInstance<scoped_refptr<AudioPipeReader> >::Leaky |
| g_pulseaudio_pipe_sink_reader = LAZY_INSTANCE_INITIALIZER; |
| |
| } // namespace |
| |
| // TODO(wez): Remove this and have the DesktopEnvironmentFactory own the |
| // AudioPipeReader rather than having it process-global. |
| // See crbug.com/161373 and crbug.com/104544. |
| void AudioCapturerLinux::InitializePipeReader( |
| scoped_refptr<base::SingleThreadTaskRunner> task_runner, |
| const base::FilePath& pipe_name) { |
| scoped_refptr<AudioPipeReader> pipe_reader; |
| if (!pipe_name.empty()) |
| pipe_reader = AudioPipeReader::Create(task_runner, pipe_name); |
| g_pulseaudio_pipe_sink_reader.Get() = pipe_reader; |
| } |
| |
| AudioCapturerLinux::AudioCapturerLinux( |
| scoped_refptr<AudioPipeReader> pipe_reader) |
| : pipe_reader_(pipe_reader), |
| silence_detector_(0) { |
| } |
| |
| AudioCapturerLinux::~AudioCapturerLinux() { |
| } |
| |
| bool AudioCapturerLinux::Start(const PacketCapturedCallback& callback) { |
| callback_ = callback; |
| silence_detector_.Reset(kSamplingRate, AudioPacket::CHANNELS_STEREO); |
| pipe_reader_->AddObserver(this); |
| return true; |
| } |
| |
| void AudioCapturerLinux::Stop() { |
| pipe_reader_->RemoveObserver(this); |
| callback_.Reset(); |
| } |
| |
| bool AudioCapturerLinux::IsStarted() { |
| return !callback_.is_null(); |
| } |
| |
| void AudioCapturerLinux::OnDataRead( |
| scoped_refptr<base::RefCountedString> data) { |
| DCHECK(!callback_.is_null()); |
| |
| if (silence_detector_.IsSilence( |
| reinterpret_cast<const int16*>(data->data().data()), |
| data->data().size() / sizeof(int16))) { |
| return; |
| } |
| |
| scoped_ptr<AudioPacket> packet(new AudioPacket()); |
| packet->add_data(data->data()); |
| packet->set_encoding(AudioPacket::ENCODING_RAW); |
| packet->set_sampling_rate(kSamplingRate); |
| packet->set_bytes_per_sample(AudioPacket::BYTES_PER_SAMPLE_2); |
| packet->set_channels(AudioPacket::CHANNELS_STEREO); |
| callback_.Run(packet.Pass()); |
| } |
| |
| bool AudioCapturer::IsSupported() { |
| return g_pulseaudio_pipe_sink_reader.Get().get() != NULL; |
| } |
| |
| scoped_ptr<AudioCapturer> AudioCapturer::Create() { |
| scoped_refptr<AudioPipeReader> reader = |
| g_pulseaudio_pipe_sink_reader.Get(); |
| if (!reader.get()) |
| return scoped_ptr<AudioCapturer>(); |
| return scoped_ptr<AudioCapturer>(new AudioCapturerLinux(reader)); |
| } |
| |
| } // namespace remoting |