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 "rtc_base/checks.h"
16 #include "rtc_base/location.h"
17 #include "rtc_base/ref_counted_object.h"
18 #include "rtc_base/thread.h"
19 #include "rtc_base/time_utils.h"
20
21 // Audio sample value that is high enough that it doesn't occur naturally when
22 // frames are being faked. E.g. NetEq will not generate this large sample value
23 // unless it has received an audio frame containing a sample of this value.
24 // Even simpler buffers would likely just contain audio sample values of 0.
25 static const int kHighSampleValue = 10000;
26
27 // Constants here are derived by running VoE using a real ADM.
28 // The constants correspond to 10ms of mono audio at 44kHz.
29 static const int kTimePerFrameMs = 10;
30 static const uint8_t kNumberOfChannels = 1;
31 static const int kSamplesPerSecond = 44000;
32 static const int kTotalDelayMs = 0;
33 static const int kClockDriftMs = 0;
34 static const uint32_t kMaxVolume = 14392;
35
36 enum {
37 MSG_START_PROCESS,
38 MSG_RUN_PROCESS,
39 };
40
FakeAudioCaptureModule()41 FakeAudioCaptureModule::FakeAudioCaptureModule()
42 : audio_callback_(nullptr),
43 recording_(false),
44 playing_(false),
45 play_is_initialized_(false),
46 rec_is_initialized_(false),
47 current_mic_level_(kMaxVolume),
48 started_(false),
49 next_frame_time_(0),
50 frames_received_(0) {}
51
~FakeAudioCaptureModule()52 FakeAudioCaptureModule::~FakeAudioCaptureModule() {
53 if (process_thread_) {
54 process_thread_->Stop();
55 }
56 }
57
Create()58 rtc::scoped_refptr<FakeAudioCaptureModule> FakeAudioCaptureModule::Create() {
59 rtc::scoped_refptr<FakeAudioCaptureModule> capture_module(
60 new rtc::RefCountedObject<FakeAudioCaptureModule>());
61 if (!capture_module->Initialize()) {
62 return nullptr;
63 }
64 return capture_module;
65 }
66
frames_received() const67 int FakeAudioCaptureModule::frames_received() const {
68 rtc::CritScope cs(&crit_);
69 return frames_received_;
70 }
71
ActiveAudioLayer(AudioLayer *) const72 int32_t FakeAudioCaptureModule::ActiveAudioLayer(
73 AudioLayer* /*audio_layer*/) const {
74 RTC_NOTREACHED();
75 return 0;
76 }
77
RegisterAudioCallback(webrtc::AudioTransport * audio_callback)78 int32_t FakeAudioCaptureModule::RegisterAudioCallback(
79 webrtc::AudioTransport* audio_callback) {
80 rtc::CritScope cs(&crit_callback_);
81 audio_callback_ = audio_callback;
82 return 0;
83 }
84
Init()85 int32_t FakeAudioCaptureModule::Init() {
86 // Initialize is called by the factory method. Safe to ignore this Init call.
87 return 0;
88 }
89
Terminate()90 int32_t FakeAudioCaptureModule::Terminate() {
91 // Clean up in the destructor. No action here, just success.
92 return 0;
93 }
94
Initialized() const95 bool FakeAudioCaptureModule::Initialized() const {
96 RTC_NOTREACHED();
97 return 0;
98 }
99
PlayoutDevices()100 int16_t FakeAudioCaptureModule::PlayoutDevices() {
101 RTC_NOTREACHED();
102 return 0;
103 }
104
RecordingDevices()105 int16_t FakeAudioCaptureModule::RecordingDevices() {
106 RTC_NOTREACHED();
107 return 0;
108 }
109
PlayoutDeviceName(uint16_t,char[webrtc::kAdmMaxDeviceNameSize],char[webrtc::kAdmMaxGuidSize])110 int32_t FakeAudioCaptureModule::PlayoutDeviceName(
111 uint16_t /*index*/,
112 char /*name*/[webrtc::kAdmMaxDeviceNameSize],
113 char /*guid*/[webrtc::kAdmMaxGuidSize]) {
114 RTC_NOTREACHED();
115 return 0;
116 }
117
RecordingDeviceName(uint16_t,char[webrtc::kAdmMaxDeviceNameSize],char[webrtc::kAdmMaxGuidSize])118 int32_t FakeAudioCaptureModule::RecordingDeviceName(
119 uint16_t /*index*/,
120 char /*name*/[webrtc::kAdmMaxDeviceNameSize],
121 char /*guid*/[webrtc::kAdmMaxGuidSize]) {
122 RTC_NOTREACHED();
123 return 0;
124 }
125
SetPlayoutDevice(uint16_t)126 int32_t FakeAudioCaptureModule::SetPlayoutDevice(uint16_t /*index*/) {
127 // No playout device, just playing from file. Return success.
128 return 0;
129 }
130
SetPlayoutDevice(WindowsDeviceType)131 int32_t FakeAudioCaptureModule::SetPlayoutDevice(WindowsDeviceType /*device*/) {
132 if (play_is_initialized_) {
133 return -1;
134 }
135 return 0;
136 }
137
SetRecordingDevice(uint16_t)138 int32_t FakeAudioCaptureModule::SetRecordingDevice(uint16_t /*index*/) {
139 // No recording device, just dropping audio. Return success.
140 return 0;
141 }
142
SetRecordingDevice(WindowsDeviceType)143 int32_t FakeAudioCaptureModule::SetRecordingDevice(
144 WindowsDeviceType /*device*/) {
145 if (rec_is_initialized_) {
146 return -1;
147 }
148 return 0;
149 }
150
PlayoutIsAvailable(bool *)151 int32_t FakeAudioCaptureModule::PlayoutIsAvailable(bool* /*available*/) {
152 RTC_NOTREACHED();
153 return 0;
154 }
155
InitPlayout()156 int32_t FakeAudioCaptureModule::InitPlayout() {
157 play_is_initialized_ = true;
158 return 0;
159 }
160
PlayoutIsInitialized() const161 bool FakeAudioCaptureModule::PlayoutIsInitialized() const {
162 return play_is_initialized_;
163 }
164
RecordingIsAvailable(bool *)165 int32_t FakeAudioCaptureModule::RecordingIsAvailable(bool* /*available*/) {
166 RTC_NOTREACHED();
167 return 0;
168 }
169
InitRecording()170 int32_t FakeAudioCaptureModule::InitRecording() {
171 rec_is_initialized_ = true;
172 return 0;
173 }
174
RecordingIsInitialized() const175 bool FakeAudioCaptureModule::RecordingIsInitialized() const {
176 return rec_is_initialized_;
177 }
178
StartPlayout()179 int32_t FakeAudioCaptureModule::StartPlayout() {
180 if (!play_is_initialized_) {
181 return -1;
182 }
183 {
184 rtc::CritScope cs(&crit_);
185 playing_ = true;
186 }
187 bool start = true;
188 UpdateProcessing(start);
189 return 0;
190 }
191
StopPlayout()192 int32_t FakeAudioCaptureModule::StopPlayout() {
193 bool start = false;
194 {
195 rtc::CritScope cs(&crit_);
196 playing_ = false;
197 start = ShouldStartProcessing();
198 }
199 UpdateProcessing(start);
200 return 0;
201 }
202
Playing() const203 bool FakeAudioCaptureModule::Playing() const {
204 rtc::CritScope cs(&crit_);
205 return playing_;
206 }
207
StartRecording()208 int32_t FakeAudioCaptureModule::StartRecording() {
209 if (!rec_is_initialized_) {
210 return -1;
211 }
212 {
213 rtc::CritScope cs(&crit_);
214 recording_ = true;
215 }
216 bool start = true;
217 UpdateProcessing(start);
218 return 0;
219 }
220
StopRecording()221 int32_t FakeAudioCaptureModule::StopRecording() {
222 bool start = false;
223 {
224 rtc::CritScope cs(&crit_);
225 recording_ = false;
226 start = ShouldStartProcessing();
227 }
228 UpdateProcessing(start);
229 return 0;
230 }
231
Recording() const232 bool FakeAudioCaptureModule::Recording() const {
233 rtc::CritScope cs(&crit_);
234 return recording_;
235 }
236
InitSpeaker()237 int32_t FakeAudioCaptureModule::InitSpeaker() {
238 // No speaker, just playing from file. Return success.
239 return 0;
240 }
241
SpeakerIsInitialized() const242 bool FakeAudioCaptureModule::SpeakerIsInitialized() const {
243 RTC_NOTREACHED();
244 return 0;
245 }
246
InitMicrophone()247 int32_t FakeAudioCaptureModule::InitMicrophone() {
248 // No microphone, just playing from file. Return success.
249 return 0;
250 }
251
MicrophoneIsInitialized() const252 bool FakeAudioCaptureModule::MicrophoneIsInitialized() const {
253 RTC_NOTREACHED();
254 return 0;
255 }
256
SpeakerVolumeIsAvailable(bool *)257 int32_t FakeAudioCaptureModule::SpeakerVolumeIsAvailable(bool* /*available*/) {
258 RTC_NOTREACHED();
259 return 0;
260 }
261
SetSpeakerVolume(uint32_t)262 int32_t FakeAudioCaptureModule::SetSpeakerVolume(uint32_t /*volume*/) {
263 RTC_NOTREACHED();
264 return 0;
265 }
266
SpeakerVolume(uint32_t *) const267 int32_t FakeAudioCaptureModule::SpeakerVolume(uint32_t* /*volume*/) const {
268 RTC_NOTREACHED();
269 return 0;
270 }
271
MaxSpeakerVolume(uint32_t *) const272 int32_t FakeAudioCaptureModule::MaxSpeakerVolume(
273 uint32_t* /*max_volume*/) const {
274 RTC_NOTREACHED();
275 return 0;
276 }
277
MinSpeakerVolume(uint32_t *) const278 int32_t FakeAudioCaptureModule::MinSpeakerVolume(
279 uint32_t* /*min_volume*/) const {
280 RTC_NOTREACHED();
281 return 0;
282 }
283
MicrophoneVolumeIsAvailable(bool *)284 int32_t FakeAudioCaptureModule::MicrophoneVolumeIsAvailable(
285 bool* /*available*/) {
286 RTC_NOTREACHED();
287 return 0;
288 }
289
SetMicrophoneVolume(uint32_t volume)290 int32_t FakeAudioCaptureModule::SetMicrophoneVolume(uint32_t volume) {
291 rtc::CritScope cs(&crit_);
292 current_mic_level_ = volume;
293 return 0;
294 }
295
MicrophoneVolume(uint32_t * volume) const296 int32_t FakeAudioCaptureModule::MicrophoneVolume(uint32_t* volume) const {
297 rtc::CritScope cs(&crit_);
298 *volume = current_mic_level_;
299 return 0;
300 }
301
MaxMicrophoneVolume(uint32_t * max_volume) const302 int32_t FakeAudioCaptureModule::MaxMicrophoneVolume(
303 uint32_t* max_volume) const {
304 *max_volume = kMaxVolume;
305 return 0;
306 }
307
MinMicrophoneVolume(uint32_t *) const308 int32_t FakeAudioCaptureModule::MinMicrophoneVolume(
309 uint32_t* /*min_volume*/) const {
310 RTC_NOTREACHED();
311 return 0;
312 }
313
SpeakerMuteIsAvailable(bool *)314 int32_t FakeAudioCaptureModule::SpeakerMuteIsAvailable(bool* /*available*/) {
315 RTC_NOTREACHED();
316 return 0;
317 }
318
SetSpeakerMute(bool)319 int32_t FakeAudioCaptureModule::SetSpeakerMute(bool /*enable*/) {
320 RTC_NOTREACHED();
321 return 0;
322 }
323
SpeakerMute(bool *) const324 int32_t FakeAudioCaptureModule::SpeakerMute(bool* /*enabled*/) const {
325 RTC_NOTREACHED();
326 return 0;
327 }
328
MicrophoneMuteIsAvailable(bool *)329 int32_t FakeAudioCaptureModule::MicrophoneMuteIsAvailable(bool* /*available*/) {
330 RTC_NOTREACHED();
331 return 0;
332 }
333
SetMicrophoneMute(bool)334 int32_t FakeAudioCaptureModule::SetMicrophoneMute(bool /*enable*/) {
335 RTC_NOTREACHED();
336 return 0;
337 }
338
MicrophoneMute(bool *) const339 int32_t FakeAudioCaptureModule::MicrophoneMute(bool* /*enabled*/) const {
340 RTC_NOTREACHED();
341 return 0;
342 }
343
StereoPlayoutIsAvailable(bool * available) const344 int32_t FakeAudioCaptureModule::StereoPlayoutIsAvailable(
345 bool* available) const {
346 // No recording device, just dropping audio. Stereo can be dropped just
347 // as easily as mono.
348 *available = true;
349 return 0;
350 }
351
SetStereoPlayout(bool)352 int32_t FakeAudioCaptureModule::SetStereoPlayout(bool /*enable*/) {
353 // No recording device, just dropping audio. Stereo can be dropped just
354 // as easily as mono.
355 return 0;
356 }
357
StereoPlayout(bool *) const358 int32_t FakeAudioCaptureModule::StereoPlayout(bool* /*enabled*/) const {
359 RTC_NOTREACHED();
360 return 0;
361 }
362
StereoRecordingIsAvailable(bool * available) const363 int32_t FakeAudioCaptureModule::StereoRecordingIsAvailable(
364 bool* available) const {
365 // Keep thing simple. No stereo recording.
366 *available = false;
367 return 0;
368 }
369
SetStereoRecording(bool enable)370 int32_t FakeAudioCaptureModule::SetStereoRecording(bool enable) {
371 if (!enable) {
372 return 0;
373 }
374 return -1;
375 }
376
StereoRecording(bool *) const377 int32_t FakeAudioCaptureModule::StereoRecording(bool* /*enabled*/) const {
378 RTC_NOTREACHED();
379 return 0;
380 }
381
PlayoutDelay(uint16_t * delay_ms) const382 int32_t FakeAudioCaptureModule::PlayoutDelay(uint16_t* delay_ms) const {
383 // No delay since audio frames are dropped.
384 *delay_ms = 0;
385 return 0;
386 }
387
OnMessage(rtc::Message * msg)388 void FakeAudioCaptureModule::OnMessage(rtc::Message* msg) {
389 switch (msg->message_id) {
390 case MSG_START_PROCESS:
391 StartProcessP();
392 break;
393 case MSG_RUN_PROCESS:
394 ProcessFrameP();
395 break;
396 default:
397 // All existing messages should be caught. Getting here should never
398 // happen.
399 RTC_NOTREACHED();
400 }
401 }
402
Initialize()403 bool FakeAudioCaptureModule::Initialize() {
404 // Set the send buffer samples high enough that it would not occur on the
405 // remote side unless a packet containing a sample of that magnitude has been
406 // sent to it. Note that the audio processing pipeline will likely distort the
407 // original signal.
408 SetSendBuffer(kHighSampleValue);
409 return true;
410 }
411
SetSendBuffer(int value)412 void FakeAudioCaptureModule::SetSendBuffer(int value) {
413 Sample* buffer_ptr = reinterpret_cast<Sample*>(send_buffer_);
414 const size_t buffer_size_in_samples =
415 sizeof(send_buffer_) / kNumberBytesPerSample;
416 for (size_t i = 0; i < buffer_size_in_samples; ++i) {
417 buffer_ptr[i] = value;
418 }
419 }
420
ResetRecBuffer()421 void FakeAudioCaptureModule::ResetRecBuffer() {
422 memset(rec_buffer_, 0, sizeof(rec_buffer_));
423 }
424
CheckRecBuffer(int value)425 bool FakeAudioCaptureModule::CheckRecBuffer(int value) {
426 const Sample* buffer_ptr = reinterpret_cast<const Sample*>(rec_buffer_);
427 const size_t buffer_size_in_samples =
428 sizeof(rec_buffer_) / kNumberBytesPerSample;
429 for (size_t i = 0; i < buffer_size_in_samples; ++i) {
430 if (buffer_ptr[i] >= value)
431 return true;
432 }
433 return false;
434 }
435
ShouldStartProcessing()436 bool FakeAudioCaptureModule::ShouldStartProcessing() {
437 return recording_ || playing_;
438 }
439
UpdateProcessing(bool start)440 void FakeAudioCaptureModule::UpdateProcessing(bool start) {
441 if (start) {
442 if (!process_thread_) {
443 process_thread_ = rtc::Thread::Create();
444 process_thread_->Start();
445 }
446 process_thread_->Post(RTC_FROM_HERE, this, MSG_START_PROCESS);
447 } else {
448 if (process_thread_) {
449 process_thread_->Stop();
450 process_thread_.reset(nullptr);
451 }
452 started_ = false;
453 }
454 }
455
StartProcessP()456 void FakeAudioCaptureModule::StartProcessP() {
457 RTC_CHECK(process_thread_->IsCurrent());
458 if (started_) {
459 // Already started.
460 return;
461 }
462 ProcessFrameP();
463 }
464
ProcessFrameP()465 void FakeAudioCaptureModule::ProcessFrameP() {
466 RTC_CHECK(process_thread_->IsCurrent());
467 if (!started_) {
468 next_frame_time_ = rtc::TimeMillis();
469 started_ = true;
470 }
471
472 {
473 rtc::CritScope cs(&crit_);
474 // Receive and send frames every kTimePerFrameMs.
475 if (playing_) {
476 ReceiveFrameP();
477 }
478 if (recording_) {
479 SendFrameP();
480 }
481 }
482
483 next_frame_time_ += kTimePerFrameMs;
484 const int64_t current_time = rtc::TimeMillis();
485 const int64_t wait_time =
486 (next_frame_time_ > current_time) ? next_frame_time_ - current_time : 0;
487 process_thread_->PostDelayed(RTC_FROM_HERE, wait_time, this, MSG_RUN_PROCESS);
488 }
489
ReceiveFrameP()490 void FakeAudioCaptureModule::ReceiveFrameP() {
491 RTC_CHECK(process_thread_->IsCurrent());
492 {
493 rtc::CritScope cs(&crit_callback_);
494 if (!audio_callback_) {
495 return;
496 }
497 ResetRecBuffer();
498 size_t nSamplesOut = 0;
499 int64_t elapsed_time_ms = 0;
500 int64_t ntp_time_ms = 0;
501 if (audio_callback_->NeedMorePlayData(
502 kNumberSamples, kNumberBytesPerSample, kNumberOfChannels,
503 kSamplesPerSecond, rec_buffer_, nSamplesOut, &elapsed_time_ms,
504 &ntp_time_ms) != 0) {
505 RTC_NOTREACHED();
506 }
507 RTC_CHECK(nSamplesOut == kNumberSamples);
508 }
509 // The SetBuffer() function ensures that after decoding, the audio buffer
510 // should contain samples of similar magnitude (there is likely to be some
511 // distortion due to the audio pipeline). If one sample is detected to
512 // have the same or greater magnitude somewhere in the frame, an actual frame
513 // has been received from the remote side (i.e. faked frames are not being
514 // pulled).
515 if (CheckRecBuffer(kHighSampleValue)) {
516 rtc::CritScope cs(&crit_);
517 ++frames_received_;
518 }
519 }
520
SendFrameP()521 void FakeAudioCaptureModule::SendFrameP() {
522 RTC_CHECK(process_thread_->IsCurrent());
523 rtc::CritScope cs(&crit_callback_);
524 if (!audio_callback_) {
525 return;
526 }
527 bool key_pressed = false;
528 uint32_t current_mic_level = 0;
529 MicrophoneVolume(¤t_mic_level);
530 if (audio_callback_->RecordedDataIsAvailable(
531 send_buffer_, kNumberSamples, kNumberBytesPerSample,
532 kNumberOfChannels, kSamplesPerSecond, kTotalDelayMs, kClockDriftMs,
533 current_mic_level, key_pressed, current_mic_level) != 0) {
534 RTC_NOTREACHED();
535 }
536 SetMicrophoneVolume(current_mic_level);
537 }
538