Chromium Code Reviews| Index: remoting/protocol/webrtc_audio_module.cc |
| diff --git a/remoting/protocol/webrtc_audio_module.cc b/remoting/protocol/webrtc_audio_module.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..0feda9c44a37da3f4593af4bc58603a1a8168633 |
| --- /dev/null |
| +++ b/remoting/protocol/webrtc_audio_module.cc |
| @@ -0,0 +1,526 @@ |
| +// Copyright 2016 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/protocol/webrtc_audio_module.h" |
| + |
| +#include "base/bind.h" |
| +#include "base/stl_util.h" |
| +#include "base/threading/thread_task_runner_handle.h" |
| + |
| +namespace remoting { |
| +namespace protocol { |
| + |
| +namespace { |
|
nicholss
2016/10/04 21:42:00
Is the plan to finish implementing the reset of th
Sergey Ulanov
2016/10/04 22:32:32
Nope. The only reason we need this class is to cal
|
| + |
| +const int kSamplingRate = 48000; |
| + |
| +// Webrtc uses 10ms frames. |
| +const int kFrameLengthMs = 10; |
| +const int kSamplesPerFrame = kSamplingRate * kFrameLengthMs / 1000; |
| + |
| +constexpr base::TimeDelta kPollInterval = |
| + base::TimeDelta::FromMilliseconds(5 * kFrameLengthMs); |
| +const int kChannels = 2; |
| +const int kBytesPerSample = 2; |
| + |
| +} // namespace |
| + |
| +WebrtcAudioModule::WebrtcAudioModule() {} |
| +WebrtcAudioModule::~WebrtcAudioModule() {} |
| + |
| +void WebrtcAudioModule::Initialize( |
| + scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner) { |
| + DCHECK(!audio_task_runner_); |
| + DCHECK(audio_task_runner); |
| + audio_task_runner_ = audio_task_runner; |
| +} |
| + |
| +int64_t WebrtcAudioModule::TimeUntilNextProcess() { |
| + // We don't need to do anything in Process(), so returning just an arbitrary |
| + // value that's not too low, so that Process() doesn't get called too |
| + // frequently. |
| + return 1000000; |
| +} |
| + |
| +void WebrtcAudioModule::Process() {} |
| + |
| +int32_t WebrtcAudioModule::ActiveAudioLayer(AudioLayer* audio_layer) const { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +WebrtcAudioModule::ErrorCode WebrtcAudioModule::LastError() const { |
| + return kAdmErrNone; |
| +} |
| + |
| +int32_t WebrtcAudioModule::RegisterEventObserver( |
| + webrtc::AudioDeviceObserver* event_callback) { |
| + return 0; |
| +} |
| + |
| +int32_t WebrtcAudioModule::RegisterAudioCallback( |
| + webrtc::AudioTransport* audio_transport) { |
| + base::AutoLock lock(lock_); |
| + audio_transport_ = audio_transport; |
| + return 0; |
| +} |
| + |
| +int32_t WebrtcAudioModule::Init() { |
| + base::AutoLock auto_lock(lock_); |
| + initialized_ = true; |
| + return 0; |
| +} |
| + |
| +int32_t WebrtcAudioModule::Terminate() { |
| + base::AutoLock auto_lock(lock_); |
| + initialized_ = false; |
| + return 0; |
| +} |
| + |
| +bool WebrtcAudioModule::Initialized() const { |
| + base::AutoLock auto_lock(lock_); |
| + return initialized_; |
| +} |
| + |
| +int16_t WebrtcAudioModule::PlayoutDevices() { |
| + return 0; |
| +} |
| + |
| +int16_t WebrtcAudioModule::RecordingDevices() { |
| + return 0; |
| +} |
| + |
| +int32_t WebrtcAudioModule::PlayoutDeviceName( |
| + uint16_t index, |
| + char name[webrtc::kAdmMaxDeviceNameSize], |
| + char guid[webrtc::kAdmMaxGuidSize]) { |
| + return 0; |
| +} |
| + |
| +int32_t WebrtcAudioModule::RecordingDeviceName( |
| + uint16_t index, |
| + char name[webrtc::kAdmMaxDeviceNameSize], |
| + char guid[webrtc::kAdmMaxGuidSize]) { |
| + return 0; |
| +} |
| + |
| +int32_t WebrtcAudioModule::SetPlayoutDevice(uint16_t index) { |
| + return 0; |
| +} |
| + |
| +int32_t WebrtcAudioModule::SetPlayoutDevice(WindowsDeviceType device) { |
| + return 0; |
| +} |
| + |
| +int32_t WebrtcAudioModule::SetRecordingDevice(uint16_t index) { |
| + return 0; |
| +} |
| + |
| +int32_t WebrtcAudioModule::SetRecordingDevice(WindowsDeviceType device) { |
| + return 0; |
| +} |
| + |
| +int32_t WebrtcAudioModule::PlayoutIsAvailable(bool* available) { |
| + base::AutoLock auto_lock(lock_); |
| + *available = initialized_; |
|
nicholss
2016/10/04 21:42:00
Is this call intended to be a buffer check? Playou
Sergey Ulanov
2016/10/04 22:32:32
I assume the intended use of this method is to det
|
| + return 0; |
| +} |
| + |
| +int32_t WebrtcAudioModule::InitPlayout() { |
| + return 0; |
| +} |
| + |
| +bool WebrtcAudioModule::PlayoutIsInitialized() const { |
| + base::AutoLock auto_lock(lock_); |
| + return initialized_; |
| +} |
| + |
| +int32_t WebrtcAudioModule::RecordingIsAvailable(bool* available) { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::InitRecording() { |
| + return 0; |
| +} |
| + |
| +bool WebrtcAudioModule::RecordingIsInitialized() const { |
| + return false; |
| +} |
| + |
| +int32_t WebrtcAudioModule::StartPlayout() { |
| + base::AutoLock auto_lock(lock_); |
| + if (!playing_ && audio_task_runner_) { |
| + audio_task_runner_->PostTask( |
| + FROM_HERE, |
| + base::Bind(&WebrtcAudioModule::StartPlayoutOnAudioThread, this)); |
| + playing_ = true; |
| + } |
| + return 0; |
| +} |
| + |
| +int32_t WebrtcAudioModule::StopPlayout() { |
| + base::AutoLock auto_lock(lock_); |
| + if (playing_) { |
| + audio_task_runner_->PostTask( |
| + FROM_HERE, |
| + base::Bind(&WebrtcAudioModule::StopPlayoutOnAudioThread, this)); |
| + playing_ = false; |
| + } |
| + return 0; |
| +} |
| + |
| +bool WebrtcAudioModule::Playing() const { |
| + base::AutoLock auto_lock(lock_); |
| + return playing_; |
| +} |
| + |
| +int32_t WebrtcAudioModule::StartRecording() { |
| + return 0; |
| +} |
| + |
| +int32_t WebrtcAudioModule::StopRecording() { |
| + return 0; |
| +} |
| + |
| +bool WebrtcAudioModule::Recording() const { |
| + return false; |
| +} |
| + |
| +int32_t WebrtcAudioModule::SetAGC(bool enable) { |
| + return 0; |
| +} |
| + |
| +bool WebrtcAudioModule::AGC() const { |
| + NOTREACHED(); |
| + return false; |
| +} |
| + |
| +int32_t WebrtcAudioModule::SetWaveOutVolume(uint16_t volume_left, |
| + uint16_t volume_right) { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::WaveOutVolume(uint16_t* volume_left, |
| + uint16_t* volume_right) const { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::InitSpeaker() { |
| + return 0; |
| +} |
| + |
| +bool WebrtcAudioModule::SpeakerIsInitialized() const { |
| + return false; |
| +} |
| + |
| +int32_t WebrtcAudioModule::InitMicrophone() { |
| + return 0; |
| +} |
| + |
| +bool WebrtcAudioModule::MicrophoneIsInitialized() const { |
| + return false; |
| +} |
| + |
| +int32_t WebrtcAudioModule::SpeakerVolumeIsAvailable(bool* available) { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::SetSpeakerVolume(uint32_t volume) { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::SpeakerVolume(uint32_t* volume) const { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::MaxSpeakerVolume(uint32_t* max_volume) const { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::MinSpeakerVolume(uint32_t* min_volume) const { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::SpeakerVolumeStepSize(uint16_t* step_size) const { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::MicrophoneVolumeIsAvailable(bool* available) { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::SetMicrophoneVolume(uint32_t volume) { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::MicrophoneVolume(uint32_t* volume) const { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::MaxMicrophoneVolume(uint32_t* max_volume) const { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::MinMicrophoneVolume(uint32_t* min_volume) const { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::MicrophoneVolumeStepSize(uint16_t* step_size) const { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::SpeakerMuteIsAvailable(bool* available) { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::SetSpeakerMute(bool enable) { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::SpeakerMute(bool* enabled) const { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::MicrophoneMuteIsAvailable(bool* available) { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::SetMicrophoneMute(bool enable) { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::MicrophoneMute(bool* enabled) const { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::MicrophoneBoostIsAvailable(bool* available) { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::SetMicrophoneBoost(bool enable) { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::MicrophoneBoost(bool* enabled) const { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::StereoPlayoutIsAvailable(bool* available) const { |
| + *available = true; |
| + return 0; |
| +} |
| + |
| +int32_t WebrtcAudioModule::SetStereoPlayout(bool enable) { |
| + DCHECK(enable); |
| + return 0; |
| +} |
| + |
| +int32_t WebrtcAudioModule::StereoPlayout(bool* enabled) const { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::StereoRecordingIsAvailable(bool* available) const { |
| + *available = false; |
| + return 0; |
| +} |
| + |
| +int32_t WebrtcAudioModule::SetStereoRecording(bool enable) { |
| + return 0; |
| +} |
| + |
| +int32_t WebrtcAudioModule::StereoRecording(bool* enabled) const { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::SetRecordingChannel(const ChannelType channel) { |
| + return 0; |
| +} |
| + |
| +int32_t WebrtcAudioModule::RecordingChannel(ChannelType* channel) const { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::SetPlayoutBuffer(const BufferType type, |
| + uint16_t size_ms) { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::PlayoutBuffer(BufferType* type, |
| + uint16_t* size_ms) const { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::PlayoutDelay(uint16_t* delay_ms) const { |
| + *delay_ms = 0; |
| + return 0; |
| +} |
| + |
| +int32_t WebrtcAudioModule::RecordingDelay(uint16_t* delay_ms) const { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::CPULoad(uint16_t* load) const { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::StartRawOutputFileRecording( |
| + const char pcm_file_name_utf8[webrtc::kAdmMaxFileNameSize]) { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::StopRawOutputFileRecording() { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::StartRawInputFileRecording( |
| + const char pcm_file_name_utf8[webrtc::kAdmMaxFileNameSize]) { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::StopRawInputFileRecording() { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::SetRecordingSampleRate( |
| + const uint32_t samples_per_sec) { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::RecordingSampleRate( |
| + uint32_t* samples_per_sec) const { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::SetPlayoutSampleRate( |
| + const uint32_t samples_per_sec) { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::PlayoutSampleRate(uint32_t* samples_per_sec) const { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::ResetAudioDevice() { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::SetLoudspeakerStatus(bool enable) { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::GetLoudspeakerStatus(bool* enabled) const { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +bool WebrtcAudioModule::BuiltInAECIsAvailable() const { |
| + return false; |
| +} |
| + |
| +bool WebrtcAudioModule::BuiltInAGCIsAvailable() const { |
| + return false; |
| +} |
| + |
| +bool WebrtcAudioModule::BuiltInNSIsAvailable() const { |
| + return false; |
| +} |
| + |
| +int32_t WebrtcAudioModule::EnableBuiltInAEC(bool enable) { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::EnableBuiltInAGC(bool enable) { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int32_t WebrtcAudioModule::EnableBuiltInNS(bool enable) { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +#if defined(WEBRTC_IOS) |
| +int WebrtcAudioModule::GetPlayoutAudioParameters( |
| + AudioParameters* params) const { |
| + NOTREACHED(); |
| + return -1; |
| +} |
| + |
| +int WebrtcAudioModule::GetRecordAudioParameters(AudioParameters* params) const { |
| +} |
| +#endif // WEBRTC_IOS |
| + |
| +void WebrtcAudioModule::StartPlayoutOnAudioThread() { |
| + DCHECK(audio_task_runner_->BelongsToCurrentThread()); |
| + poll_timer_.Start( |
| + FROM_HERE, kPollInterval, |
| + base::Bind(&WebrtcAudioModule::PollFromSource, base::Unretained(this))); |
| +} |
| + |
| +void WebrtcAudioModule::StopPlayoutOnAudioThread() { |
| + DCHECK(audio_task_runner_->BelongsToCurrentThread()); |
| + poll_timer_.Stop(); |
| +} |
| + |
| +void WebrtcAudioModule::PollFromSource() { |
| + DCHECK(audio_task_runner_->BelongsToCurrentThread()); |
| + |
| + base::AutoLock lock(lock_); |
| + if (!audio_transport_) |
| + return; |
| + |
| + for (int i = 0; i < kPollInterval.InMilliseconds() / kFrameLengthMs; i++) { |
| + int64_t elapsed_time_ms = -1; |
| + int64_t ntp_time_ms = -1; |
| + char data[kBytesPerSample * kChannels * kSamplesPerFrame]; |
| + audio_transport_->PullRenderData(kBytesPerSample * 8, kSamplingRate, |
| + kChannels, kSamplesPerFrame, data, |
| + &elapsed_time_ms, &ntp_time_ms); |
| + } |
| +} |
| + |
| +} // namespace protocol |
| +} // namespace remoting |