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(&current_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