• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   process_thread_checker_.Detach();
52 }
53 
~FakeAudioCaptureModule()54 FakeAudioCaptureModule::~FakeAudioCaptureModule() {
55   if (process_thread_) {
56     process_thread_->Stop();
57   }
58 }
59 
Create()60 rtc::scoped_refptr<FakeAudioCaptureModule> FakeAudioCaptureModule::Create() {
61   rtc::scoped_refptr<FakeAudioCaptureModule> capture_module(
62       new rtc::RefCountedObject<FakeAudioCaptureModule>());
63   if (!capture_module->Initialize()) {
64     return nullptr;
65   }
66   return capture_module;
67 }
68 
frames_received() const69 int FakeAudioCaptureModule::frames_received() const {
70   webrtc::MutexLock lock(&mutex_);
71   return frames_received_;
72 }
73 
ActiveAudioLayer(AudioLayer *) const74 int32_t FakeAudioCaptureModule::ActiveAudioLayer(
75     AudioLayer* /*audio_layer*/) const {
76   RTC_NOTREACHED();
77   return 0;
78 }
79 
RegisterAudioCallback(webrtc::AudioTransport * audio_callback)80 int32_t FakeAudioCaptureModule::RegisterAudioCallback(
81     webrtc::AudioTransport* audio_callback) {
82   webrtc::MutexLock lock(&mutex_);
83   audio_callback_ = audio_callback;
84   return 0;
85 }
86 
Init()87 int32_t FakeAudioCaptureModule::Init() {
88   // Initialize is called by the factory method. Safe to ignore this Init call.
89   return 0;
90 }
91 
Terminate()92 int32_t FakeAudioCaptureModule::Terminate() {
93   // Clean up in the destructor. No action here, just success.
94   return 0;
95 }
96 
Initialized() const97 bool FakeAudioCaptureModule::Initialized() const {
98   RTC_NOTREACHED();
99   return 0;
100 }
101 
PlayoutDevices()102 int16_t FakeAudioCaptureModule::PlayoutDevices() {
103   RTC_NOTREACHED();
104   return 0;
105 }
106 
RecordingDevices()107 int16_t FakeAudioCaptureModule::RecordingDevices() {
108   RTC_NOTREACHED();
109   return 0;
110 }
111 
PlayoutDeviceName(uint16_t,char[webrtc::kAdmMaxDeviceNameSize],char[webrtc::kAdmMaxGuidSize])112 int32_t FakeAudioCaptureModule::PlayoutDeviceName(
113     uint16_t /*index*/,
114     char /*name*/[webrtc::kAdmMaxDeviceNameSize],
115     char /*guid*/[webrtc::kAdmMaxGuidSize]) {
116   RTC_NOTREACHED();
117   return 0;
118 }
119 
RecordingDeviceName(uint16_t,char[webrtc::kAdmMaxDeviceNameSize],char[webrtc::kAdmMaxGuidSize])120 int32_t FakeAudioCaptureModule::RecordingDeviceName(
121     uint16_t /*index*/,
122     char /*name*/[webrtc::kAdmMaxDeviceNameSize],
123     char /*guid*/[webrtc::kAdmMaxGuidSize]) {
124   RTC_NOTREACHED();
125   return 0;
126 }
127 
SetPlayoutDevice(uint16_t)128 int32_t FakeAudioCaptureModule::SetPlayoutDevice(uint16_t /*index*/) {
129   // No playout device, just playing from file. Return success.
130   return 0;
131 }
132 
SetPlayoutDevice(WindowsDeviceType)133 int32_t FakeAudioCaptureModule::SetPlayoutDevice(WindowsDeviceType /*device*/) {
134   if (play_is_initialized_) {
135     return -1;
136   }
137   return 0;
138 }
139 
SetRecordingDevice(uint16_t)140 int32_t FakeAudioCaptureModule::SetRecordingDevice(uint16_t /*index*/) {
141   // No recording device, just dropping audio. Return success.
142   return 0;
143 }
144 
SetRecordingDevice(WindowsDeviceType)145 int32_t FakeAudioCaptureModule::SetRecordingDevice(
146     WindowsDeviceType /*device*/) {
147   if (rec_is_initialized_) {
148     return -1;
149   }
150   return 0;
151 }
152 
PlayoutIsAvailable(bool *)153 int32_t FakeAudioCaptureModule::PlayoutIsAvailable(bool* /*available*/) {
154   RTC_NOTREACHED();
155   return 0;
156 }
157 
InitPlayout()158 int32_t FakeAudioCaptureModule::InitPlayout() {
159   play_is_initialized_ = true;
160   return 0;
161 }
162 
PlayoutIsInitialized() const163 bool FakeAudioCaptureModule::PlayoutIsInitialized() const {
164   return play_is_initialized_;
165 }
166 
RecordingIsAvailable(bool *)167 int32_t FakeAudioCaptureModule::RecordingIsAvailable(bool* /*available*/) {
168   RTC_NOTREACHED();
169   return 0;
170 }
171 
InitRecording()172 int32_t FakeAudioCaptureModule::InitRecording() {
173   rec_is_initialized_ = true;
174   return 0;
175 }
176 
RecordingIsInitialized() const177 bool FakeAudioCaptureModule::RecordingIsInitialized() const {
178   return rec_is_initialized_;
179 }
180 
StartPlayout()181 int32_t FakeAudioCaptureModule::StartPlayout() {
182   if (!play_is_initialized_) {
183     return -1;
184   }
185   {
186     webrtc::MutexLock lock(&mutex_);
187     playing_ = true;
188   }
189   bool start = true;
190   UpdateProcessing(start);
191   return 0;
192 }
193 
StopPlayout()194 int32_t FakeAudioCaptureModule::StopPlayout() {
195   bool start = false;
196   {
197     webrtc::MutexLock lock(&mutex_);
198     playing_ = false;
199     start = ShouldStartProcessing();
200   }
201   UpdateProcessing(start);
202   return 0;
203 }
204 
Playing() const205 bool FakeAudioCaptureModule::Playing() const {
206   webrtc::MutexLock lock(&mutex_);
207   return playing_;
208 }
209 
StartRecording()210 int32_t FakeAudioCaptureModule::StartRecording() {
211   if (!rec_is_initialized_) {
212     return -1;
213   }
214   {
215     webrtc::MutexLock lock(&mutex_);
216     recording_ = true;
217   }
218   bool start = true;
219   UpdateProcessing(start);
220   return 0;
221 }
222 
StopRecording()223 int32_t FakeAudioCaptureModule::StopRecording() {
224   bool start = false;
225   {
226     webrtc::MutexLock lock(&mutex_);
227     recording_ = false;
228     start = ShouldStartProcessing();
229   }
230   UpdateProcessing(start);
231   return 0;
232 }
233 
Recording() const234 bool FakeAudioCaptureModule::Recording() const {
235   webrtc::MutexLock lock(&mutex_);
236   return recording_;
237 }
238 
InitSpeaker()239 int32_t FakeAudioCaptureModule::InitSpeaker() {
240   // No speaker, just playing from file. Return success.
241   return 0;
242 }
243 
SpeakerIsInitialized() const244 bool FakeAudioCaptureModule::SpeakerIsInitialized() const {
245   RTC_NOTREACHED();
246   return 0;
247 }
248 
InitMicrophone()249 int32_t FakeAudioCaptureModule::InitMicrophone() {
250   // No microphone, just playing from file. Return success.
251   return 0;
252 }
253 
MicrophoneIsInitialized() const254 bool FakeAudioCaptureModule::MicrophoneIsInitialized() const {
255   RTC_NOTREACHED();
256   return 0;
257 }
258 
SpeakerVolumeIsAvailable(bool *)259 int32_t FakeAudioCaptureModule::SpeakerVolumeIsAvailable(bool* /*available*/) {
260   RTC_NOTREACHED();
261   return 0;
262 }
263 
SetSpeakerVolume(uint32_t)264 int32_t FakeAudioCaptureModule::SetSpeakerVolume(uint32_t /*volume*/) {
265   RTC_NOTREACHED();
266   return 0;
267 }
268 
SpeakerVolume(uint32_t *) const269 int32_t FakeAudioCaptureModule::SpeakerVolume(uint32_t* /*volume*/) const {
270   RTC_NOTREACHED();
271   return 0;
272 }
273 
MaxSpeakerVolume(uint32_t *) const274 int32_t FakeAudioCaptureModule::MaxSpeakerVolume(
275     uint32_t* /*max_volume*/) const {
276   RTC_NOTREACHED();
277   return 0;
278 }
279 
MinSpeakerVolume(uint32_t *) const280 int32_t FakeAudioCaptureModule::MinSpeakerVolume(
281     uint32_t* /*min_volume*/) const {
282   RTC_NOTREACHED();
283   return 0;
284 }
285 
MicrophoneVolumeIsAvailable(bool *)286 int32_t FakeAudioCaptureModule::MicrophoneVolumeIsAvailable(
287     bool* /*available*/) {
288   RTC_NOTREACHED();
289   return 0;
290 }
291 
SetMicrophoneVolume(uint32_t volume)292 int32_t FakeAudioCaptureModule::SetMicrophoneVolume(uint32_t volume) {
293   webrtc::MutexLock lock(&mutex_);
294   current_mic_level_ = volume;
295   return 0;
296 }
297 
MicrophoneVolume(uint32_t * volume) const298 int32_t FakeAudioCaptureModule::MicrophoneVolume(uint32_t* volume) const {
299   webrtc::MutexLock lock(&mutex_);
300   *volume = current_mic_level_;
301   return 0;
302 }
303 
MaxMicrophoneVolume(uint32_t * max_volume) const304 int32_t FakeAudioCaptureModule::MaxMicrophoneVolume(
305     uint32_t* max_volume) const {
306   *max_volume = kMaxVolume;
307   return 0;
308 }
309 
MinMicrophoneVolume(uint32_t *) const310 int32_t FakeAudioCaptureModule::MinMicrophoneVolume(
311     uint32_t* /*min_volume*/) const {
312   RTC_NOTREACHED();
313   return 0;
314 }
315 
SpeakerMuteIsAvailable(bool *)316 int32_t FakeAudioCaptureModule::SpeakerMuteIsAvailable(bool* /*available*/) {
317   RTC_NOTREACHED();
318   return 0;
319 }
320 
SetSpeakerMute(bool)321 int32_t FakeAudioCaptureModule::SetSpeakerMute(bool /*enable*/) {
322   RTC_NOTREACHED();
323   return 0;
324 }
325 
SpeakerMute(bool *) const326 int32_t FakeAudioCaptureModule::SpeakerMute(bool* /*enabled*/) const {
327   RTC_NOTREACHED();
328   return 0;
329 }
330 
MicrophoneMuteIsAvailable(bool *)331 int32_t FakeAudioCaptureModule::MicrophoneMuteIsAvailable(bool* /*available*/) {
332   RTC_NOTREACHED();
333   return 0;
334 }
335 
SetMicrophoneMute(bool)336 int32_t FakeAudioCaptureModule::SetMicrophoneMute(bool /*enable*/) {
337   RTC_NOTREACHED();
338   return 0;
339 }
340 
MicrophoneMute(bool *) const341 int32_t FakeAudioCaptureModule::MicrophoneMute(bool* /*enabled*/) const {
342   RTC_NOTREACHED();
343   return 0;
344 }
345 
StereoPlayoutIsAvailable(bool * available) const346 int32_t FakeAudioCaptureModule::StereoPlayoutIsAvailable(
347     bool* available) const {
348   // No recording device, just dropping audio. Stereo can be dropped just
349   // as easily as mono.
350   *available = true;
351   return 0;
352 }
353 
SetStereoPlayout(bool)354 int32_t FakeAudioCaptureModule::SetStereoPlayout(bool /*enable*/) {
355   // No recording device, just dropping audio. Stereo can be dropped just
356   // as easily as mono.
357   return 0;
358 }
359 
StereoPlayout(bool *) const360 int32_t FakeAudioCaptureModule::StereoPlayout(bool* /*enabled*/) const {
361   RTC_NOTREACHED();
362   return 0;
363 }
364 
StereoRecordingIsAvailable(bool * available) const365 int32_t FakeAudioCaptureModule::StereoRecordingIsAvailable(
366     bool* available) const {
367   // Keep thing simple. No stereo recording.
368   *available = false;
369   return 0;
370 }
371 
SetStereoRecording(bool enable)372 int32_t FakeAudioCaptureModule::SetStereoRecording(bool enable) {
373   if (!enable) {
374     return 0;
375   }
376   return -1;
377 }
378 
StereoRecording(bool *) const379 int32_t FakeAudioCaptureModule::StereoRecording(bool* /*enabled*/) const {
380   RTC_NOTREACHED();
381   return 0;
382 }
383 
PlayoutDelay(uint16_t * delay_ms) const384 int32_t FakeAudioCaptureModule::PlayoutDelay(uint16_t* delay_ms) const {
385   // No delay since audio frames are dropped.
386   *delay_ms = 0;
387   return 0;
388 }
389 
OnMessage(rtc::Message * msg)390 void FakeAudioCaptureModule::OnMessage(rtc::Message* msg) {
391   switch (msg->message_id) {
392     case MSG_START_PROCESS:
393       StartProcessP();
394       break;
395     case MSG_RUN_PROCESS:
396       ProcessFrameP();
397       break;
398     default:
399       // All existing messages should be caught. Getting here should never
400       // happen.
401       RTC_NOTREACHED();
402   }
403 }
404 
Initialize()405 bool FakeAudioCaptureModule::Initialize() {
406   // Set the send buffer samples high enough that it would not occur on the
407   // remote side unless a packet containing a sample of that magnitude has been
408   // sent to it. Note that the audio processing pipeline will likely distort the
409   // original signal.
410   SetSendBuffer(kHighSampleValue);
411   return true;
412 }
413 
SetSendBuffer(int value)414 void FakeAudioCaptureModule::SetSendBuffer(int value) {
415   Sample* buffer_ptr = reinterpret_cast<Sample*>(send_buffer_);
416   const size_t buffer_size_in_samples =
417       sizeof(send_buffer_) / kNumberBytesPerSample;
418   for (size_t i = 0; i < buffer_size_in_samples; ++i) {
419     buffer_ptr[i] = value;
420   }
421 }
422 
ResetRecBuffer()423 void FakeAudioCaptureModule::ResetRecBuffer() {
424   memset(rec_buffer_, 0, sizeof(rec_buffer_));
425 }
426 
CheckRecBuffer(int value)427 bool FakeAudioCaptureModule::CheckRecBuffer(int value) {
428   const Sample* buffer_ptr = reinterpret_cast<const Sample*>(rec_buffer_);
429   const size_t buffer_size_in_samples =
430       sizeof(rec_buffer_) / kNumberBytesPerSample;
431   for (size_t i = 0; i < buffer_size_in_samples; ++i) {
432     if (buffer_ptr[i] >= value)
433       return true;
434   }
435   return false;
436 }
437 
ShouldStartProcessing()438 bool FakeAudioCaptureModule::ShouldStartProcessing() {
439   return recording_ || playing_;
440 }
441 
UpdateProcessing(bool start)442 void FakeAudioCaptureModule::UpdateProcessing(bool start) {
443   if (start) {
444     if (!process_thread_) {
445       process_thread_ = rtc::Thread::Create();
446       process_thread_->Start();
447     }
448     process_thread_->Post(RTC_FROM_HERE, this, MSG_START_PROCESS);
449   } else {
450     if (process_thread_) {
451       process_thread_->Stop();
452       process_thread_.reset(nullptr);
453       process_thread_checker_.Detach();
454     }
455     webrtc::MutexLock lock(&mutex_);
456     started_ = false;
457   }
458 }
459 
StartProcessP()460 void FakeAudioCaptureModule::StartProcessP() {
461   RTC_DCHECK_RUN_ON(&process_thread_checker_);
462   {
463     webrtc::MutexLock lock(&mutex_);
464     if (started_) {
465       // Already started.
466       return;
467     }
468   }
469   ProcessFrameP();
470 }
471 
ProcessFrameP()472 void FakeAudioCaptureModule::ProcessFrameP() {
473   RTC_DCHECK_RUN_ON(&process_thread_checker_);
474   {
475     webrtc::MutexLock lock(&mutex_);
476     if (!started_) {
477       next_frame_time_ = rtc::TimeMillis();
478       started_ = true;
479     }
480 
481     // Receive and send frames every kTimePerFrameMs.
482     if (playing_) {
483       ReceiveFrameP();
484     }
485     if (recording_) {
486       SendFrameP();
487     }
488   }
489 
490   next_frame_time_ += kTimePerFrameMs;
491   const int64_t current_time = rtc::TimeMillis();
492   const int64_t wait_time =
493       (next_frame_time_ > current_time) ? next_frame_time_ - current_time : 0;
494   process_thread_->PostDelayed(RTC_FROM_HERE, wait_time, this, MSG_RUN_PROCESS);
495 }
496 
ReceiveFrameP()497 void FakeAudioCaptureModule::ReceiveFrameP() {
498   RTC_DCHECK_RUN_ON(&process_thread_checker_);
499   if (!audio_callback_) {
500     return;
501   }
502   ResetRecBuffer();
503   size_t nSamplesOut = 0;
504   int64_t elapsed_time_ms = 0;
505   int64_t ntp_time_ms = 0;
506   if (audio_callback_->NeedMorePlayData(kNumberSamples, kNumberBytesPerSample,
507                                         kNumberOfChannels, kSamplesPerSecond,
508                                         rec_buffer_, nSamplesOut,
509                                         &elapsed_time_ms, &ntp_time_ms) != 0) {
510     RTC_NOTREACHED();
511   }
512   RTC_CHECK(nSamplesOut == kNumberSamples);
513 
514   // The SetBuffer() function ensures that after decoding, the audio buffer
515   // should contain samples of similar magnitude (there is likely to be some
516   // distortion due to the audio pipeline). If one sample is detected to
517   // have the same or greater magnitude somewhere in the frame, an actual frame
518   // has been received from the remote side (i.e. faked frames are not being
519   // pulled).
520   if (CheckRecBuffer(kHighSampleValue)) {
521     ++frames_received_;
522   }
523 }
524 
SendFrameP()525 void FakeAudioCaptureModule::SendFrameP() {
526   RTC_DCHECK_RUN_ON(&process_thread_checker_);
527   if (!audio_callback_) {
528     return;
529   }
530   bool key_pressed = false;
531   uint32_t current_mic_level = current_mic_level_;
532   if (audio_callback_->RecordedDataIsAvailable(
533           send_buffer_, kNumberSamples, kNumberBytesPerSample,
534           kNumberOfChannels, kSamplesPerSecond, kTotalDelayMs, kClockDriftMs,
535           current_mic_level, key_pressed, current_mic_level) != 0) {
536     RTC_NOTREACHED();
537   }
538   current_mic_level_ = current_mic_level;
539 }
540