blob: 9f2db3cc3b7c11affedc41953c26885b705f15ce [file] [log] [blame]
sergeyu2c5c0c202016-10-05 22:51:141// Copyright 2016 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 "remoting/protocol/webrtc_audio_module.h"
6
Jinho Bang138fde32018-01-18 23:13:427#include <memory>
8
sergeyu2c5c0c202016-10-05 22:51:149#include "base/bind.h"
Gabriel Charette5ff87ce2017-05-16 18:03:4510#include "base/single_thread_task_runner.h"
sergeyu2c5c0c202016-10-05 22:51:1411#include "base/threading/thread_task_runner_handle.h"
sergeyu53c571c2017-01-24 07:11:0112#include "base/timer/timer.h"
sergeyu2c5c0c202016-10-05 22:51:1413
14namespace remoting {
15namespace protocol {
16
17namespace {
18
19const int kSamplingRate = 48000;
20
21// Webrtc uses 10ms frames.
22const int kFrameLengthMs = 10;
23const int kSamplesPerFrame = kSamplingRate * kFrameLengthMs / 1000;
24
25constexpr base::TimeDelta kPollInterval =
Peter Kastinge5a38ed2021-10-02 03:06:3526 base::Milliseconds(5 * kFrameLengthMs);
sergeyu2c5c0c202016-10-05 22:51:1427const int kChannels = 2;
28const int kBytesPerSample = 2;
29
30} // namespace
31
32// webrtc::AudioDeviceModule is a generic interface that aims to provide all
33// functionality normally supported audio input/output devices, but most of
34// the functions are never called in Webrtc. This class implements only
35// functions that are actually used. All unused functions are marked as
36// NOTREACHED().
37
Chris Watkins6fe52aa2017-11-28 03:24:0538WebrtcAudioModule::WebrtcAudioModule() = default;
39WebrtcAudioModule::~WebrtcAudioModule() = default;
sergeyu2c5c0c202016-10-05 22:51:1440
41void WebrtcAudioModule::SetAudioTaskRunner(
42 scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner) {
43 DCHECK(!audio_task_runner_);
44 DCHECK(audio_task_runner);
45 audio_task_runner_ = audio_task_runner;
46}
47
sergeyu2c5c0c202016-10-05 22:51:1448int32_t WebrtcAudioModule::ActiveAudioLayer(AudioLayer* audio_layer) const {
49 NOTREACHED();
50 return -1;
51}
52
sergeyu2c5c0c202016-10-05 22:51:1453int32_t WebrtcAudioModule::RegisterAudioCallback(
54 webrtc::AudioTransport* audio_transport) {
55 base::AutoLock lock(lock_);
56 audio_transport_ = audio_transport;
57 return 0;
58}
59
60int32_t WebrtcAudioModule::Init() {
61 base::AutoLock auto_lock(lock_);
62 initialized_ = true;
63 return 0;
64}
65
66int32_t WebrtcAudioModule::Terminate() {
67 base::AutoLock auto_lock(lock_);
68 initialized_ = false;
69 return 0;
70}
71
72bool WebrtcAudioModule::Initialized() const {
73 base::AutoLock auto_lock(lock_);
74 return initialized_;
75}
76
77int16_t WebrtcAudioModule::PlayoutDevices() {
78 return 0;
79}
80
81int16_t WebrtcAudioModule::RecordingDevices() {
82 return 0;
83}
84
85int32_t WebrtcAudioModule::PlayoutDeviceName(
86 uint16_t index,
87 char name[webrtc::kAdmMaxDeviceNameSize],
88 char guid[webrtc::kAdmMaxGuidSize]) {
89 return 0;
90}
91
92int32_t WebrtcAudioModule::RecordingDeviceName(
93 uint16_t index,
94 char name[webrtc::kAdmMaxDeviceNameSize],
95 char guid[webrtc::kAdmMaxGuidSize]) {
96 return 0;
97}
98
99int32_t WebrtcAudioModule::SetPlayoutDevice(uint16_t index) {
100 return 0;
101}
102
103int32_t WebrtcAudioModule::SetPlayoutDevice(WindowsDeviceType device) {
104 return 0;
105}
106
107int32_t WebrtcAudioModule::SetRecordingDevice(uint16_t index) {
108 return 0;
109}
110
111int32_t WebrtcAudioModule::SetRecordingDevice(WindowsDeviceType device) {
112 return 0;
113}
114
115int32_t WebrtcAudioModule::PlayoutIsAvailable(bool* available) {
116 NOTREACHED();
117 return -1;
118}
119
120int32_t WebrtcAudioModule::InitPlayout() {
121 return 0;
122}
123
124bool WebrtcAudioModule::PlayoutIsInitialized() const {
125 base::AutoLock auto_lock(lock_);
126 return initialized_;
127}
128
129int32_t WebrtcAudioModule::RecordingIsAvailable(bool* available) {
130 NOTREACHED();
131 return -1;
132}
133
134int32_t WebrtcAudioModule::InitRecording() {
135 return 0;
136}
137
138bool WebrtcAudioModule::RecordingIsInitialized() const {
139 return false;
140}
141
142int32_t WebrtcAudioModule::StartPlayout() {
143 base::AutoLock auto_lock(lock_);
144 if (!playing_ && audio_task_runner_) {
145 audio_task_runner_->PostTask(
tzikecb28472018-07-27 00:59:12146 FROM_HERE, base::BindOnce(&WebrtcAudioModule::StartPlayoutOnAudioThread,
147 rtc::scoped_refptr<WebrtcAudioModule>(this)));
sergeyu2c5c0c202016-10-05 22:51:14148 playing_ = true;
149 }
150 return 0;
151}
152
153int32_t WebrtcAudioModule::StopPlayout() {
154 base::AutoLock auto_lock(lock_);
155 if (playing_) {
156 audio_task_runner_->PostTask(
tzikecb28472018-07-27 00:59:12157 FROM_HERE, base::BindOnce(&WebrtcAudioModule::StopPlayoutOnAudioThread,
158 rtc::scoped_refptr<WebrtcAudioModule>(this)));
sergeyu2c5c0c202016-10-05 22:51:14159 playing_ = false;
160 }
161 return 0;
162}
163
164bool WebrtcAudioModule::Playing() const {
165 base::AutoLock auto_lock(lock_);
166 return playing_;
167}
168
169int32_t WebrtcAudioModule::StartRecording() {
170 return 0;
171}
172
173int32_t WebrtcAudioModule::StopRecording() {
174 return 0;
175}
176
177bool WebrtcAudioModule::Recording() const {
178 return false;
179}
180
sergeyu2c5c0c202016-10-05 22:51:14181int32_t WebrtcAudioModule::InitSpeaker() {
182 return 0;
183}
184
185bool WebrtcAudioModule::SpeakerIsInitialized() const {
186 return false;
187}
188
189int32_t WebrtcAudioModule::InitMicrophone() {
190 return 0;
191}
192
193bool WebrtcAudioModule::MicrophoneIsInitialized() const {
194 return false;
195}
196
197int32_t WebrtcAudioModule::SpeakerVolumeIsAvailable(bool* available) {
198 NOTREACHED();
199 return -1;
200}
201
202int32_t WebrtcAudioModule::SetSpeakerVolume(uint32_t volume) {
203 NOTREACHED();
204 return -1;
205}
206
207int32_t WebrtcAudioModule::SpeakerVolume(uint32_t* volume) const {
208 NOTREACHED();
209 return -1;
210}
211
212int32_t WebrtcAudioModule::MaxSpeakerVolume(uint32_t* max_volume) const {
213 NOTREACHED();
214 return -1;
215}
216
217int32_t WebrtcAudioModule::MinSpeakerVolume(uint32_t* min_volume) const {
218 NOTREACHED();
219 return -1;
220}
221
sergeyu2c5c0c202016-10-05 22:51:14222int32_t WebrtcAudioModule::MicrophoneVolumeIsAvailable(bool* available) {
223 NOTREACHED();
224 return -1;
225}
226
227int32_t WebrtcAudioModule::SetMicrophoneVolume(uint32_t volume) {
228 NOTREACHED();
229 return -1;
230}
231
232int32_t WebrtcAudioModule::MicrophoneVolume(uint32_t* volume) const {
233 NOTREACHED();
234 return -1;
235}
236
237int32_t WebrtcAudioModule::MaxMicrophoneVolume(uint32_t* max_volume) const {
238 NOTREACHED();
239 return -1;
240}
241
242int32_t WebrtcAudioModule::MinMicrophoneVolume(uint32_t* min_volume) const {
243 NOTREACHED();
244 return -1;
245}
246
sergeyu2c5c0c202016-10-05 22:51:14247int32_t WebrtcAudioModule::SpeakerMuteIsAvailable(bool* available) {
248 NOTREACHED();
249 return -1;
250}
251
252int32_t WebrtcAudioModule::SetSpeakerMute(bool enable) {
253 NOTREACHED();
254 return -1;
255}
256
257int32_t WebrtcAudioModule::SpeakerMute(bool* enabled) const {
258 NOTREACHED();
259 return -1;
260}
261
262int32_t WebrtcAudioModule::MicrophoneMuteIsAvailable(bool* available) {
263 NOTREACHED();
264 return -1;
265}
266
267int32_t WebrtcAudioModule::SetMicrophoneMute(bool enable) {
268 NOTREACHED();
269 return -1;
270}
271
272int32_t WebrtcAudioModule::MicrophoneMute(bool* enabled) const {
273 NOTREACHED();
274 return -1;
275}
276
sergeyu2c5c0c202016-10-05 22:51:14277int32_t WebrtcAudioModule::StereoPlayoutIsAvailable(bool* available) const {
278 *available = true;
279 return 0;
280}
281
282int32_t WebrtcAudioModule::SetStereoPlayout(bool enable) {
283 DCHECK(enable);
284 return 0;
285}
286
287int32_t WebrtcAudioModule::StereoPlayout(bool* enabled) const {
288 NOTREACHED();
289 return -1;
290}
291
292int32_t WebrtcAudioModule::StereoRecordingIsAvailable(bool* available) const {
293 *available = false;
294 return 0;
295}
296
297int32_t WebrtcAudioModule::SetStereoRecording(bool enable) {
298 return 0;
299}
300
301int32_t WebrtcAudioModule::StereoRecording(bool* enabled) const {
302 NOTREACHED();
303 return -1;
304}
305
sergeyu2c5c0c202016-10-05 22:51:14306int32_t WebrtcAudioModule::PlayoutDelay(uint16_t* delay_ms) const {
307 *delay_ms = 0;
308 return 0;
309}
310
sergeyu2c5c0c202016-10-05 22:51:14311bool WebrtcAudioModule::BuiltInAECIsAvailable() const {
312 return false;
313}
314
315bool WebrtcAudioModule::BuiltInAGCIsAvailable() const {
316 return false;
317}
318
319bool WebrtcAudioModule::BuiltInNSIsAvailable() const {
320 return false;
321}
322
323int32_t WebrtcAudioModule::EnableBuiltInAEC(bool enable) {
324 NOTREACHED();
325 return -1;
326}
327
328int32_t WebrtcAudioModule::EnableBuiltInAGC(bool enable) {
329 NOTREACHED();
330 return -1;
331}
332
333int32_t WebrtcAudioModule::EnableBuiltInNS(bool enable) {
334 NOTREACHED();
335 return -1;
336}
337
338#if defined(WEBRTC_IOS)
339int WebrtcAudioModule::GetPlayoutAudioParameters(
nicholss1b5df0c2016-10-25 16:04:49340 webrtc::AudioParameters* params) const {
sergeyu2c5c0c202016-10-05 22:51:14341 NOTREACHED();
342 return -1;
343}
344
nicholss1b5df0c2016-10-25 16:04:49345int WebrtcAudioModule::GetRecordAudioParameters(
346 webrtc::AudioParameters* params) const {
sergeyu2c5c0c202016-10-05 22:51:14347 NOTREACHED();
348 return -1;
349}
350#endif // WEBRTC_IOS
351
352void WebrtcAudioModule::StartPlayoutOnAudioThread() {
353 DCHECK(audio_task_runner_->BelongsToCurrentThread());
Jinho Bang138fde32018-01-18 23:13:42354 poll_timer_ = std::make_unique<base::RepeatingTimer>();
tzikecb28472018-07-27 00:59:12355 poll_timer_->Start(FROM_HERE, kPollInterval,
356 base::BindRepeating(&WebrtcAudioModule::PollFromSource,
357 base::Unretained(this)));
sergeyu2c5c0c202016-10-05 22:51:14358}
359
360void WebrtcAudioModule::StopPlayoutOnAudioThread() {
361 DCHECK(audio_task_runner_->BelongsToCurrentThread());
sergeyu53c571c2017-01-24 07:11:01362 poll_timer_.reset();
sergeyu2c5c0c202016-10-05 22:51:14363}
364
365void WebrtcAudioModule::PollFromSource() {
366 DCHECK(audio_task_runner_->BelongsToCurrentThread());
367
368 base::AutoLock lock(lock_);
369 if (!audio_transport_)
370 return;
371
372 for (int i = 0; i < kPollInterval.InMilliseconds() / kFrameLengthMs; i++) {
373 int64_t elapsed_time_ms = -1;
374 int64_t ntp_time_ms = -1;
375 char data[kBytesPerSample * kChannels * kSamplesPerFrame];
376 audio_transport_->PullRenderData(kBytesPerSample * 8, kSamplingRate,
377 kChannels, kSamplesPerFrame, data,
378 &elapsed_time_ms, &ntp_time_ms);
379 }
380}
381
382} // namespace protocol
383} // namespace remoting