1 /*
2 * Copyright 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "pc/test/fake_audio_capture_module.h"
12
13 #include <string.h>
14
15 #include "api/make_ref_counted.h"
16 #include "api/units/time_delta.h"
17 #include "rtc_base/checks.h"
18 #include "rtc_base/thread.h"
19 #include "rtc_base/time_utils.h"
20
21 using ::webrtc::TimeDelta;
22
23 // Audio sample value that is high enough that it doesn't occur naturally when
24 // frames are being faked. E.g. NetEq will not generate this large sample value
25 // unless it has received an audio frame containing a sample of this value.
26 // Even simpler buffers would likely just contain audio sample values of 0.
27 static const int kHighSampleValue = 10000;
28
29 // Constants here are derived by running VoE using a real ADM.
30 // The constants correspond to 10ms of mono audio at 44kHz.
31 static const int kTimePerFrameMs = 10;
32 static const uint8_t kNumberOfChannels = 1;
33 static const int kSamplesPerSecond = 44000;
34 static const int kTotalDelayMs = 0;
35 static const int kClockDriftMs = 0;
36 static const uint32_t kMaxVolume = 14392;
37
FakeAudioCaptureModule()38 FakeAudioCaptureModule::FakeAudioCaptureModule()
39 : audio_callback_(nullptr),
40 recording_(false),
41 playing_(false),
42 play_is_initialized_(false),
43 rec_is_initialized_(false),
44 current_mic_level_(kMaxVolume),
45 started_(false),
46 next_frame_time_(0),
47 frames_received_(0) {
48 process_thread_checker_.Detach();
49 }
50
~FakeAudioCaptureModule()51 FakeAudioCaptureModule::~FakeAudioCaptureModule() {
52 if (process_thread_) {
53 process_thread_->Stop();
54 }
55 }
56
Create()57 rtc::scoped_refptr<FakeAudioCaptureModule> FakeAudioCaptureModule::Create() {
58 auto capture_module = rtc::make_ref_counted<FakeAudioCaptureModule>();
59 if (!capture_module->Initialize()) {
60 return nullptr;
61 }
62 return capture_module;
63 }
64
frames_received() const65 int FakeAudioCaptureModule::frames_received() const {
66 webrtc::MutexLock lock(&mutex_);
67 return frames_received_;
68 }
69
ActiveAudioLayer(AudioLayer *) const70 int32_t FakeAudioCaptureModule::ActiveAudioLayer(
71 AudioLayer* /*audio_layer*/) const {
72 RTC_DCHECK_NOTREACHED();
73 return 0;
74 }
75
RegisterAudioCallback(webrtc::AudioTransport * audio_callback)76 int32_t FakeAudioCaptureModule::RegisterAudioCallback(
77 webrtc::AudioTransport* audio_callback) {
78 webrtc::MutexLock lock(&mutex_);
79 audio_callback_ = audio_callback;
80 return 0;
81 }
82
Init()83 int32_t FakeAudioCaptureModule::Init() {
84 // Initialize is called by the factory method. Safe to ignore this Init call.
85 return 0;
86 }
87
Terminate()88 int32_t FakeAudioCaptureModule::Terminate() {
89 // Clean up in the destructor. No action here, just success.
90 return 0;
91 }
92
Initialized() const93 bool FakeAudioCaptureModule::Initialized() const {
94 RTC_DCHECK_NOTREACHED();
95 return 0;
96 }
97
PlayoutDevices()98 int16_t FakeAudioCaptureModule::PlayoutDevices() {
99 RTC_DCHECK_NOTREACHED();
100 return 0;
101 }
102
RecordingDevices()103 int16_t FakeAudioCaptureModule::RecordingDevices() {
104 RTC_DCHECK_NOTREACHED();
105 return 0;
106 }
107
PlayoutDeviceName(uint16_t,char[webrtc::kAdmMaxDeviceNameSize],char[webrtc::kAdmMaxGuidSize])108 int32_t FakeAudioCaptureModule::PlayoutDeviceName(
109 uint16_t /*index*/,
110 char /*name*/[webrtc::kAdmMaxDeviceNameSize],
111 char /*guid*/[webrtc::kAdmMaxGuidSize]) {
112 RTC_DCHECK_NOTREACHED();
113 return 0;
114 }
115
RecordingDeviceName(uint16_t,char[webrtc::kAdmMaxDeviceNameSize],char[webrtc::kAdmMaxGuidSize])116 int32_t FakeAudioCaptureModule::RecordingDeviceName(
117 uint16_t /*index*/,
118 char /*name*/[webrtc::kAdmMaxDeviceNameSize],
119 char /*guid*/[webrtc::kAdmMaxGuidSize]) {
120 RTC_DCHECK_NOTREACHED();
121 return 0;
122 }
123
SetPlayoutDevice(uint16_t)124 int32_t FakeAudioCaptureModule::SetPlayoutDevice(uint16_t /*index*/) {
125 // No playout device, just playing from file. Return success.
126 return 0;
127 }
128
SetPlayoutDevice(WindowsDeviceType)129 int32_t FakeAudioCaptureModule::SetPlayoutDevice(WindowsDeviceType /*device*/) {
130 if (play_is_initialized_) {
131 return -1;
132 }
133 return 0;
134 }
135
SetRecordingDevice(uint16_t)136 int32_t FakeAudioCaptureModule::SetRecordingDevice(uint16_t /*index*/) {
137 // No recording device, just dropping audio. Return success.
138 return 0;
139 }
140
SetRecordingDevice(WindowsDeviceType)141 int32_t FakeAudioCaptureModule::SetRecordingDevice(
142 WindowsDeviceType /*device*/) {
143 if (rec_is_initialized_) {
144 return -1;
145 }
146 return 0;
147 }
148
PlayoutIsAvailable(bool *)149 int32_t FakeAudioCaptureModule::PlayoutIsAvailable(bool* /*available*/) {
150 RTC_DCHECK_NOTREACHED();
151 return 0;
152 }
153
InitPlayout()154 int32_t FakeAudioCaptureModule::InitPlayout() {
155 play_is_initialized_ = true;
156 return 0;
157 }
158
PlayoutIsInitialized() const159 bool FakeAudioCaptureModule::PlayoutIsInitialized() const {
160 return play_is_initialized_;
161 }
162
RecordingIsAvailable(bool *)163 int32_t FakeAudioCaptureModule::RecordingIsAvailable(bool* /*available*/) {
164 RTC_DCHECK_NOTREACHED();
165 return 0;
166 }
167
InitRecording()168 int32_t FakeAudioCaptureModule::InitRecording() {
169 rec_is_initialized_ = true;
170 return 0;
171 }
172
RecordingIsInitialized() const173 bool FakeAudioCaptureModule::RecordingIsInitialized() const {
174 return rec_is_initialized_;
175 }
176
StartPlayout()177 int32_t FakeAudioCaptureModule::StartPlayout() {
178 if (!play_is_initialized_) {
179 return -1;
180 }
181 {
182 webrtc::MutexLock lock(&mutex_);
183 playing_ = true;
184 }
185 bool start = true;
186 UpdateProcessing(start);
187 return 0;
188 }
189
StopPlayout()190 int32_t FakeAudioCaptureModule::StopPlayout() {
191 bool start = false;
192 {
193 webrtc::MutexLock lock(&mutex_);
194 playing_ = false;
195 start = ShouldStartProcessing();
196 }
197 UpdateProcessing(start);
198 return 0;
199 }
200
Playing() const201 bool FakeAudioCaptureModule::Playing() const {
202 webrtc::MutexLock lock(&mutex_);
203 return playing_;
204 }
205
StartRecording()206 int32_t FakeAudioCaptureModule::StartRecording() {
207 if (!rec_is_initialized_) {
208 return -1;
209 }
210 {
211 webrtc::MutexLock lock(&mutex_);
212 recording_ = true;
213 }
214 bool start = true;
215 UpdateProcessing(start);
216 return 0;
217 }
218
StopRecording()219 int32_t FakeAudioCaptureModule::StopRecording() {
220 bool start = false;
221 {
222 webrtc::MutexLock lock(&mutex_);
223 recording_ = false;
224 start = ShouldStartProcessing();
225 }
226 UpdateProcessing(start);
227 return 0;
228 }
229
Recording() const230 bool FakeAudioCaptureModule::Recording() const {
231 webrtc::MutexLock lock(&mutex_);
232 return recording_;
233 }
234
InitSpeaker()235 int32_t FakeAudioCaptureModule::InitSpeaker() {
236 // No speaker, just playing from file. Return success.
237 return 0;
238 }
239
SpeakerIsInitialized() const240 bool FakeAudioCaptureModule::SpeakerIsInitialized() const {
241 RTC_DCHECK_NOTREACHED();
242 return 0;
243 }
244
InitMicrophone()245 int32_t FakeAudioCaptureModule::InitMicrophone() {
246 // No microphone, just playing from file. Return success.
247 return 0;
248 }
249
MicrophoneIsInitialized() const250 bool FakeAudioCaptureModule::MicrophoneIsInitialized() const {
251 RTC_DCHECK_NOTREACHED();
252 return 0;
253 }
254
SpeakerVolumeIsAvailable(bool *)255 int32_t FakeAudioCaptureModule::SpeakerVolumeIsAvailable(bool* /*available*/) {
256 RTC_DCHECK_NOTREACHED();
257 return 0;
258 }
259
SetSpeakerVolume(uint32_t)260 int32_t FakeAudioCaptureModule::SetSpeakerVolume(uint32_t /*volume*/) {
261 RTC_DCHECK_NOTREACHED();
262 return 0;
263 }
264
SpeakerVolume(uint32_t *) const265 int32_t FakeAudioCaptureModule::SpeakerVolume(uint32_t* /*volume*/) const {
266 RTC_DCHECK_NOTREACHED();
267 return 0;
268 }
269
MaxSpeakerVolume(uint32_t *) const270 int32_t FakeAudioCaptureModule::MaxSpeakerVolume(
271 uint32_t* /*max_volume*/) const {
272 RTC_DCHECK_NOTREACHED();
273 return 0;
274 }
275
MinSpeakerVolume(uint32_t *) const276 int32_t FakeAudioCaptureModule::MinSpeakerVolume(
277 uint32_t* /*min_volume*/) const {
278 RTC_DCHECK_NOTREACHED();
279 return 0;
280 }
281
MicrophoneVolumeIsAvailable(bool *)282 int32_t FakeAudioCaptureModule::MicrophoneVolumeIsAvailable(
283 bool* /*available*/) {
284 RTC_DCHECK_NOTREACHED();
285 return 0;
286 }
287
SetMicrophoneVolume(uint32_t volume)288 int32_t FakeAudioCaptureModule::SetMicrophoneVolume(uint32_t volume) {
289 webrtc::MutexLock lock(&mutex_);
290 current_mic_level_ = volume;
291 return 0;
292 }
293
MicrophoneVolume(uint32_t * volume) const294 int32_t FakeAudioCaptureModule::MicrophoneVolume(uint32_t* volume) const {
295 webrtc::MutexLock lock(&mutex_);
296 *volume = current_mic_level_;
297 return 0;
298 }
299
MaxMicrophoneVolume(uint32_t * max_volume) const300 int32_t FakeAudioCaptureModule::MaxMicrophoneVolume(
301 uint32_t* max_volume) const {
302 *max_volume = kMaxVolume;
303 return 0;
304 }
305
MinMicrophoneVolume(uint32_t *) const306 int32_t FakeAudioCaptureModule::MinMicrophoneVolume(
307 uint32_t* /*min_volume*/) const {
308 RTC_DCHECK_NOTREACHED();
309 return 0;
310 }
311
SpeakerMuteIsAvailable(bool *)312 int32_t FakeAudioCaptureModule::SpeakerMuteIsAvailable(bool* /*available*/) {
313 RTC_DCHECK_NOTREACHED();
314 return 0;
315 }
316
SetSpeakerMute(bool)317 int32_t FakeAudioCaptureModule::SetSpeakerMute(bool /*enable*/) {
318 RTC_DCHECK_NOTREACHED();
319 return 0;
320 }
321
SpeakerMute(bool *) const322 int32_t FakeAudioCaptureModule::SpeakerMute(bool* /*enabled*/) const {
323 RTC_DCHECK_NOTREACHED();
324 return 0;
325 }
326
MicrophoneMuteIsAvailable(bool *)327 int32_t FakeAudioCaptureModule::MicrophoneMuteIsAvailable(bool* /*available*/) {
328 RTC_DCHECK_NOTREACHED();
329 return 0;
330 }
331
SetMicrophoneMute(bool)332 int32_t FakeAudioCaptureModule::SetMicrophoneMute(bool /*enable*/) {
333 RTC_DCHECK_NOTREACHED();
334 return 0;
335 }
336
MicrophoneMute(bool *) const337 int32_t FakeAudioCaptureModule::MicrophoneMute(bool* /*enabled*/) const {
338 RTC_DCHECK_NOTREACHED();
339 return 0;
340 }
341
StereoPlayoutIsAvailable(bool * available) const342 int32_t FakeAudioCaptureModule::StereoPlayoutIsAvailable(
343 bool* available) const {
344 // No recording device, just dropping audio. Stereo can be dropped just
345 // as easily as mono.
346 *available = true;
347 return 0;
348 }
349
SetStereoPlayout(bool)350 int32_t FakeAudioCaptureModule::SetStereoPlayout(bool /*enable*/) {
351 // No recording device, just dropping audio. Stereo can be dropped just
352 // as easily as mono.
353 return 0;
354 }
355
StereoPlayout(bool *) const356 int32_t FakeAudioCaptureModule::StereoPlayout(bool* /*enabled*/) const {
357 RTC_DCHECK_NOTREACHED();
358 return 0;
359 }
360
StereoRecordingIsAvailable(bool * available) const361 int32_t FakeAudioCaptureModule::StereoRecordingIsAvailable(
362 bool* available) const {
363 // Keep thing simple. No stereo recording.
364 *available = false;
365 return 0;
366 }
367
SetStereoRecording(bool enable)368 int32_t FakeAudioCaptureModule::SetStereoRecording(bool enable) {
369 if (!enable) {
370 return 0;
371 }
372 return -1;
373 }
374
StereoRecording(bool *) const375 int32_t FakeAudioCaptureModule::StereoRecording(bool* /*enabled*/) const {
376 RTC_DCHECK_NOTREACHED();
377 return 0;
378 }
379
PlayoutDelay(uint16_t * delay_ms) const380 int32_t FakeAudioCaptureModule::PlayoutDelay(uint16_t* delay_ms) const {
381 // No delay since audio frames are dropped.
382 *delay_ms = 0;
383 return 0;
384 }
385
Initialize()386 bool FakeAudioCaptureModule::Initialize() {
387 // Set the send buffer samples high enough that it would not occur on the
388 // remote side unless a packet containing a sample of that magnitude has been
389 // sent to it. Note that the audio processing pipeline will likely distort the
390 // original signal.
391 SetSendBuffer(kHighSampleValue);
392 return true;
393 }
394
SetSendBuffer(int value)395 void FakeAudioCaptureModule::SetSendBuffer(int value) {
396 Sample* buffer_ptr = reinterpret_cast<Sample*>(send_buffer_);
397 const size_t buffer_size_in_samples =
398 sizeof(send_buffer_) / kNumberBytesPerSample;
399 for (size_t i = 0; i < buffer_size_in_samples; ++i) {
400 buffer_ptr[i] = value;
401 }
402 }
403
ResetRecBuffer()404 void FakeAudioCaptureModule::ResetRecBuffer() {
405 memset(rec_buffer_, 0, sizeof(rec_buffer_));
406 }
407
CheckRecBuffer(int value)408 bool FakeAudioCaptureModule::CheckRecBuffer(int value) {
409 const Sample* buffer_ptr = reinterpret_cast<const Sample*>(rec_buffer_);
410 const size_t buffer_size_in_samples =
411 sizeof(rec_buffer_) / kNumberBytesPerSample;
412 for (size_t i = 0; i < buffer_size_in_samples; ++i) {
413 if (buffer_ptr[i] >= value)
414 return true;
415 }
416 return false;
417 }
418
ShouldStartProcessing()419 bool FakeAudioCaptureModule::ShouldStartProcessing() {
420 return recording_ || playing_;
421 }
422
UpdateProcessing(bool start)423 void FakeAudioCaptureModule::UpdateProcessing(bool start) {
424 if (start) {
425 if (!process_thread_) {
426 process_thread_ = rtc::Thread::Create();
427 process_thread_->Start();
428 }
429 process_thread_->PostTask([this] { StartProcessP(); });
430 } else {
431 if (process_thread_) {
432 process_thread_->Stop();
433 process_thread_.reset(nullptr);
434 process_thread_checker_.Detach();
435 }
436 webrtc::MutexLock lock(&mutex_);
437 started_ = false;
438 }
439 }
440
StartProcessP()441 void FakeAudioCaptureModule::StartProcessP() {
442 RTC_DCHECK_RUN_ON(&process_thread_checker_);
443 {
444 webrtc::MutexLock lock(&mutex_);
445 if (started_) {
446 // Already started.
447 return;
448 }
449 }
450 ProcessFrameP();
451 }
452
ProcessFrameP()453 void FakeAudioCaptureModule::ProcessFrameP() {
454 RTC_DCHECK_RUN_ON(&process_thread_checker_);
455 {
456 webrtc::MutexLock lock(&mutex_);
457 if (!started_) {
458 next_frame_time_ = rtc::TimeMillis();
459 started_ = true;
460 }
461
462 // Receive and send frames every kTimePerFrameMs.
463 if (playing_) {
464 ReceiveFrameP();
465 }
466 if (recording_) {
467 SendFrameP();
468 }
469 }
470
471 next_frame_time_ += kTimePerFrameMs;
472 const int64_t current_time = rtc::TimeMillis();
473 const int64_t wait_time =
474 (next_frame_time_ > current_time) ? next_frame_time_ - current_time : 0;
475 process_thread_->PostDelayedTask([this] { ProcessFrameP(); },
476 TimeDelta::Millis(wait_time));
477 }
478
ReceiveFrameP()479 void FakeAudioCaptureModule::ReceiveFrameP() {
480 RTC_DCHECK_RUN_ON(&process_thread_checker_);
481 if (!audio_callback_) {
482 return;
483 }
484 ResetRecBuffer();
485 size_t nSamplesOut = 0;
486 int64_t elapsed_time_ms = 0;
487 int64_t ntp_time_ms = 0;
488 if (audio_callback_->NeedMorePlayData(kNumberSamples, kNumberBytesPerSample,
489 kNumberOfChannels, kSamplesPerSecond,
490 rec_buffer_, nSamplesOut,
491 &elapsed_time_ms, &ntp_time_ms) != 0) {
492 RTC_DCHECK_NOTREACHED();
493 }
494 RTC_CHECK(nSamplesOut == kNumberSamples);
495
496 // The SetBuffer() function ensures that after decoding, the audio buffer
497 // should contain samples of similar magnitude (there is likely to be some
498 // distortion due to the audio pipeline). If one sample is detected to
499 // have the same or greater magnitude somewhere in the frame, an actual frame
500 // has been received from the remote side (i.e. faked frames are not being
501 // pulled).
502 if (CheckRecBuffer(kHighSampleValue)) {
503 ++frames_received_;
504 }
505 }
506
SendFrameP()507 void FakeAudioCaptureModule::SendFrameP() {
508 RTC_DCHECK_RUN_ON(&process_thread_checker_);
509 if (!audio_callback_) {
510 return;
511 }
512 bool key_pressed = false;
513 uint32_t current_mic_level = current_mic_level_;
514 if (audio_callback_->RecordedDataIsAvailable(
515 send_buffer_, kNumberSamples, kNumberBytesPerSample,
516 kNumberOfChannels, kSamplesPerSecond, kTotalDelayMs, kClockDriftMs,
517 current_mic_level, key_pressed, current_mic_level) != 0) {
518 RTC_DCHECK_NOTREACHED();
519 }
520 current_mic_level_ = current_mic_level;
521 }
522