1 /*
2 * libjingle
3 * Copyright 2012 Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include "talk/app/webrtc/test/fakeaudiocapturemodule.h"
29
30 #include "webrtc/base/common.h"
31 #include "webrtc/base/refcount.h"
32 #include "webrtc/base/thread.h"
33 #include "webrtc/base/timeutils.h"
34
35 // Audio sample value that is high enough that it doesn't occur naturally when
36 // frames are being faked. E.g. NetEq will not generate this large sample value
37 // unless it has received an audio frame containing a sample of this value.
38 // Even simpler buffers would likely just contain audio sample values of 0.
39 static const int kHighSampleValue = 10000;
40
41 // Same value as src/modules/audio_device/main/source/audio_device_config.h in
42 // https://code.google.com/p/webrtc/
43 static const uint32_t kAdmMaxIdleTimeProcess = 1000;
44
45 // Constants here are derived by running VoE using a real ADM.
46 // The constants correspond to 10ms of mono audio at 44kHz.
47 static const int kTimePerFrameMs = 10;
48 static const uint8_t kNumberOfChannels = 1;
49 static const int kSamplesPerSecond = 44000;
50 static const int kTotalDelayMs = 0;
51 static const int kClockDriftMs = 0;
52 static const uint32_t kMaxVolume = 14392;
53
54 enum {
55 MSG_START_PROCESS,
56 MSG_RUN_PROCESS,
57 };
58
FakeAudioCaptureModule()59 FakeAudioCaptureModule::FakeAudioCaptureModule()
60 : last_process_time_ms_(0),
61 audio_callback_(nullptr),
62 recording_(false),
63 playing_(false),
64 play_is_initialized_(false),
65 rec_is_initialized_(false),
66 current_mic_level_(kMaxVolume),
67 started_(false),
68 next_frame_time_(0),
69 frames_received_(0) {
70 }
71
~FakeAudioCaptureModule()72 FakeAudioCaptureModule::~FakeAudioCaptureModule() {
73 if (process_thread_) {
74 process_thread_->Stop();
75 }
76 }
77
Create()78 rtc::scoped_refptr<FakeAudioCaptureModule> FakeAudioCaptureModule::Create() {
79 rtc::scoped_refptr<FakeAudioCaptureModule> capture_module(
80 new rtc::RefCountedObject<FakeAudioCaptureModule>());
81 if (!capture_module->Initialize()) {
82 return nullptr;
83 }
84 return capture_module;
85 }
86
frames_received() const87 int FakeAudioCaptureModule::frames_received() const {
88 rtc::CritScope cs(&crit_);
89 return frames_received_;
90 }
91
TimeUntilNextProcess()92 int64_t FakeAudioCaptureModule::TimeUntilNextProcess() {
93 const uint32_t current_time = rtc::Time();
94 if (current_time < last_process_time_ms_) {
95 // TODO: wraparound could be handled more gracefully.
96 return 0;
97 }
98 const uint32_t elapsed_time = current_time - last_process_time_ms_;
99 if (kAdmMaxIdleTimeProcess < elapsed_time) {
100 return 0;
101 }
102 return kAdmMaxIdleTimeProcess - elapsed_time;
103 }
104
Process()105 int32_t FakeAudioCaptureModule::Process() {
106 last_process_time_ms_ = rtc::Time();
107 return 0;
108 }
109
ActiveAudioLayer(AudioLayer *) const110 int32_t FakeAudioCaptureModule::ActiveAudioLayer(
111 AudioLayer* /*audio_layer*/) const {
112 ASSERT(false);
113 return 0;
114 }
115
LastError() const116 webrtc::AudioDeviceModule::ErrorCode FakeAudioCaptureModule::LastError() const {
117 ASSERT(false);
118 return webrtc::AudioDeviceModule::kAdmErrNone;
119 }
120
RegisterEventObserver(webrtc::AudioDeviceObserver *)121 int32_t FakeAudioCaptureModule::RegisterEventObserver(
122 webrtc::AudioDeviceObserver* /*event_callback*/) {
123 // Only used to report warnings and errors. This fake implementation won't
124 // generate any so discard this callback.
125 return 0;
126 }
127
RegisterAudioCallback(webrtc::AudioTransport * audio_callback)128 int32_t FakeAudioCaptureModule::RegisterAudioCallback(
129 webrtc::AudioTransport* audio_callback) {
130 rtc::CritScope cs(&crit_callback_);
131 audio_callback_ = audio_callback;
132 return 0;
133 }
134
Init()135 int32_t FakeAudioCaptureModule::Init() {
136 // Initialize is called by the factory method. Safe to ignore this Init call.
137 return 0;
138 }
139
Terminate()140 int32_t FakeAudioCaptureModule::Terminate() {
141 // Clean up in the destructor. No action here, just success.
142 return 0;
143 }
144
Initialized() const145 bool FakeAudioCaptureModule::Initialized() const {
146 ASSERT(false);
147 return 0;
148 }
149
PlayoutDevices()150 int16_t FakeAudioCaptureModule::PlayoutDevices() {
151 ASSERT(false);
152 return 0;
153 }
154
RecordingDevices()155 int16_t FakeAudioCaptureModule::RecordingDevices() {
156 ASSERT(false);
157 return 0;
158 }
159
PlayoutDeviceName(uint16_t,char[webrtc::kAdmMaxDeviceNameSize],char[webrtc::kAdmMaxGuidSize])160 int32_t FakeAudioCaptureModule::PlayoutDeviceName(
161 uint16_t /*index*/,
162 char /*name*/[webrtc::kAdmMaxDeviceNameSize],
163 char /*guid*/[webrtc::kAdmMaxGuidSize]) {
164 ASSERT(false);
165 return 0;
166 }
167
RecordingDeviceName(uint16_t,char[webrtc::kAdmMaxDeviceNameSize],char[webrtc::kAdmMaxGuidSize])168 int32_t FakeAudioCaptureModule::RecordingDeviceName(
169 uint16_t /*index*/,
170 char /*name*/[webrtc::kAdmMaxDeviceNameSize],
171 char /*guid*/[webrtc::kAdmMaxGuidSize]) {
172 ASSERT(false);
173 return 0;
174 }
175
SetPlayoutDevice(uint16_t)176 int32_t FakeAudioCaptureModule::SetPlayoutDevice(uint16_t /*index*/) {
177 // No playout device, just playing from file. Return success.
178 return 0;
179 }
180
SetPlayoutDevice(WindowsDeviceType)181 int32_t FakeAudioCaptureModule::SetPlayoutDevice(WindowsDeviceType /*device*/) {
182 if (play_is_initialized_) {
183 return -1;
184 }
185 return 0;
186 }
187
SetRecordingDevice(uint16_t)188 int32_t FakeAudioCaptureModule::SetRecordingDevice(uint16_t /*index*/) {
189 // No recording device, just dropping audio. Return success.
190 return 0;
191 }
192
SetRecordingDevice(WindowsDeviceType)193 int32_t FakeAudioCaptureModule::SetRecordingDevice(
194 WindowsDeviceType /*device*/) {
195 if (rec_is_initialized_) {
196 return -1;
197 }
198 return 0;
199 }
200
PlayoutIsAvailable(bool *)201 int32_t FakeAudioCaptureModule::PlayoutIsAvailable(bool* /*available*/) {
202 ASSERT(false);
203 return 0;
204 }
205
InitPlayout()206 int32_t FakeAudioCaptureModule::InitPlayout() {
207 play_is_initialized_ = true;
208 return 0;
209 }
210
PlayoutIsInitialized() const211 bool FakeAudioCaptureModule::PlayoutIsInitialized() const {
212 return play_is_initialized_;
213 }
214
RecordingIsAvailable(bool *)215 int32_t FakeAudioCaptureModule::RecordingIsAvailable(bool* /*available*/) {
216 ASSERT(false);
217 return 0;
218 }
219
InitRecording()220 int32_t FakeAudioCaptureModule::InitRecording() {
221 rec_is_initialized_ = true;
222 return 0;
223 }
224
RecordingIsInitialized() const225 bool FakeAudioCaptureModule::RecordingIsInitialized() const {
226 ASSERT(false);
227 return 0;
228 }
229
StartPlayout()230 int32_t FakeAudioCaptureModule::StartPlayout() {
231 if (!play_is_initialized_) {
232 return -1;
233 }
234 {
235 rtc::CritScope cs(&crit_);
236 playing_ = true;
237 }
238 bool start = true;
239 UpdateProcessing(start);
240 return 0;
241 }
242
StopPlayout()243 int32_t FakeAudioCaptureModule::StopPlayout() {
244 bool start = false;
245 {
246 rtc::CritScope cs(&crit_);
247 playing_ = false;
248 start = ShouldStartProcessing();
249 }
250 UpdateProcessing(start);
251 return 0;
252 }
253
Playing() const254 bool FakeAudioCaptureModule::Playing() const {
255 rtc::CritScope cs(&crit_);
256 return playing_;
257 }
258
StartRecording()259 int32_t FakeAudioCaptureModule::StartRecording() {
260 if (!rec_is_initialized_) {
261 return -1;
262 }
263 {
264 rtc::CritScope cs(&crit_);
265 recording_ = true;
266 }
267 bool start = true;
268 UpdateProcessing(start);
269 return 0;
270 }
271
StopRecording()272 int32_t FakeAudioCaptureModule::StopRecording() {
273 bool start = false;
274 {
275 rtc::CritScope cs(&crit_);
276 recording_ = false;
277 start = ShouldStartProcessing();
278 }
279 UpdateProcessing(start);
280 return 0;
281 }
282
Recording() const283 bool FakeAudioCaptureModule::Recording() const {
284 rtc::CritScope cs(&crit_);
285 return recording_;
286 }
287
SetAGC(bool)288 int32_t FakeAudioCaptureModule::SetAGC(bool /*enable*/) {
289 // No AGC but not needed since audio is pregenerated. Return success.
290 return 0;
291 }
292
AGC() const293 bool FakeAudioCaptureModule::AGC() const {
294 ASSERT(false);
295 return 0;
296 }
297
SetWaveOutVolume(uint16_t,uint16_t)298 int32_t FakeAudioCaptureModule::SetWaveOutVolume(uint16_t /*volume_left*/,
299 uint16_t /*volume_right*/) {
300 ASSERT(false);
301 return 0;
302 }
303
WaveOutVolume(uint16_t *,uint16_t *) const304 int32_t FakeAudioCaptureModule::WaveOutVolume(
305 uint16_t* /*volume_left*/,
306 uint16_t* /*volume_right*/) const {
307 ASSERT(false);
308 return 0;
309 }
310
InitSpeaker()311 int32_t FakeAudioCaptureModule::InitSpeaker() {
312 // No speaker, just playing from file. Return success.
313 return 0;
314 }
315
SpeakerIsInitialized() const316 bool FakeAudioCaptureModule::SpeakerIsInitialized() const {
317 ASSERT(false);
318 return 0;
319 }
320
InitMicrophone()321 int32_t FakeAudioCaptureModule::InitMicrophone() {
322 // No microphone, just playing from file. Return success.
323 return 0;
324 }
325
MicrophoneIsInitialized() const326 bool FakeAudioCaptureModule::MicrophoneIsInitialized() const {
327 ASSERT(false);
328 return 0;
329 }
330
SpeakerVolumeIsAvailable(bool *)331 int32_t FakeAudioCaptureModule::SpeakerVolumeIsAvailable(bool* /*available*/) {
332 ASSERT(false);
333 return 0;
334 }
335
SetSpeakerVolume(uint32_t)336 int32_t FakeAudioCaptureModule::SetSpeakerVolume(uint32_t /*volume*/) {
337 ASSERT(false);
338 return 0;
339 }
340
SpeakerVolume(uint32_t *) const341 int32_t FakeAudioCaptureModule::SpeakerVolume(uint32_t* /*volume*/) const {
342 ASSERT(false);
343 return 0;
344 }
345
MaxSpeakerVolume(uint32_t *) const346 int32_t FakeAudioCaptureModule::MaxSpeakerVolume(
347 uint32_t* /*max_volume*/) const {
348 ASSERT(false);
349 return 0;
350 }
351
MinSpeakerVolume(uint32_t *) const352 int32_t FakeAudioCaptureModule::MinSpeakerVolume(
353 uint32_t* /*min_volume*/) const {
354 ASSERT(false);
355 return 0;
356 }
357
SpeakerVolumeStepSize(uint16_t *) const358 int32_t FakeAudioCaptureModule::SpeakerVolumeStepSize(
359 uint16_t* /*step_size*/) const {
360 ASSERT(false);
361 return 0;
362 }
363
MicrophoneVolumeIsAvailable(bool *)364 int32_t FakeAudioCaptureModule::MicrophoneVolumeIsAvailable(
365 bool* /*available*/) {
366 ASSERT(false);
367 return 0;
368 }
369
SetMicrophoneVolume(uint32_t volume)370 int32_t FakeAudioCaptureModule::SetMicrophoneVolume(uint32_t volume) {
371 rtc::CritScope cs(&crit_);
372 current_mic_level_ = volume;
373 return 0;
374 }
375
MicrophoneVolume(uint32_t * volume) const376 int32_t FakeAudioCaptureModule::MicrophoneVolume(uint32_t* volume) const {
377 rtc::CritScope cs(&crit_);
378 *volume = current_mic_level_;
379 return 0;
380 }
381
MaxMicrophoneVolume(uint32_t * max_volume) const382 int32_t FakeAudioCaptureModule::MaxMicrophoneVolume(
383 uint32_t* max_volume) const {
384 *max_volume = kMaxVolume;
385 return 0;
386 }
387
MinMicrophoneVolume(uint32_t *) const388 int32_t FakeAudioCaptureModule::MinMicrophoneVolume(
389 uint32_t* /*min_volume*/) const {
390 ASSERT(false);
391 return 0;
392 }
393
MicrophoneVolumeStepSize(uint16_t *) const394 int32_t FakeAudioCaptureModule::MicrophoneVolumeStepSize(
395 uint16_t* /*step_size*/) const {
396 ASSERT(false);
397 return 0;
398 }
399
SpeakerMuteIsAvailable(bool *)400 int32_t FakeAudioCaptureModule::SpeakerMuteIsAvailable(bool* /*available*/) {
401 ASSERT(false);
402 return 0;
403 }
404
SetSpeakerMute(bool)405 int32_t FakeAudioCaptureModule::SetSpeakerMute(bool /*enable*/) {
406 ASSERT(false);
407 return 0;
408 }
409
SpeakerMute(bool *) const410 int32_t FakeAudioCaptureModule::SpeakerMute(bool* /*enabled*/) const {
411 ASSERT(false);
412 return 0;
413 }
414
MicrophoneMuteIsAvailable(bool *)415 int32_t FakeAudioCaptureModule::MicrophoneMuteIsAvailable(bool* /*available*/) {
416 ASSERT(false);
417 return 0;
418 }
419
SetMicrophoneMute(bool)420 int32_t FakeAudioCaptureModule::SetMicrophoneMute(bool /*enable*/) {
421 ASSERT(false);
422 return 0;
423 }
424
MicrophoneMute(bool *) const425 int32_t FakeAudioCaptureModule::MicrophoneMute(bool* /*enabled*/) const {
426 ASSERT(false);
427 return 0;
428 }
429
MicrophoneBoostIsAvailable(bool *)430 int32_t FakeAudioCaptureModule::MicrophoneBoostIsAvailable(
431 bool* /*available*/) {
432 ASSERT(false);
433 return 0;
434 }
435
SetMicrophoneBoost(bool)436 int32_t FakeAudioCaptureModule::SetMicrophoneBoost(bool /*enable*/) {
437 ASSERT(false);
438 return 0;
439 }
440
MicrophoneBoost(bool *) const441 int32_t FakeAudioCaptureModule::MicrophoneBoost(bool* /*enabled*/) const {
442 ASSERT(false);
443 return 0;
444 }
445
StereoPlayoutIsAvailable(bool * available) const446 int32_t FakeAudioCaptureModule::StereoPlayoutIsAvailable(
447 bool* available) const {
448 // No recording device, just dropping audio. Stereo can be dropped just
449 // as easily as mono.
450 *available = true;
451 return 0;
452 }
453
SetStereoPlayout(bool)454 int32_t FakeAudioCaptureModule::SetStereoPlayout(bool /*enable*/) {
455 // No recording device, just dropping audio. Stereo can be dropped just
456 // as easily as mono.
457 return 0;
458 }
459
StereoPlayout(bool *) const460 int32_t FakeAudioCaptureModule::StereoPlayout(bool* /*enabled*/) const {
461 ASSERT(false);
462 return 0;
463 }
464
StereoRecordingIsAvailable(bool * available) const465 int32_t FakeAudioCaptureModule::StereoRecordingIsAvailable(
466 bool* available) const {
467 // Keep thing simple. No stereo recording.
468 *available = false;
469 return 0;
470 }
471
SetStereoRecording(bool enable)472 int32_t FakeAudioCaptureModule::SetStereoRecording(bool enable) {
473 if (!enable) {
474 return 0;
475 }
476 return -1;
477 }
478
StereoRecording(bool *) const479 int32_t FakeAudioCaptureModule::StereoRecording(bool* /*enabled*/) const {
480 ASSERT(false);
481 return 0;
482 }
483
SetRecordingChannel(const ChannelType channel)484 int32_t FakeAudioCaptureModule::SetRecordingChannel(
485 const ChannelType channel) {
486 if (channel != AudioDeviceModule::kChannelBoth) {
487 // There is no right or left in mono. I.e. kChannelBoth should be used for
488 // mono.
489 ASSERT(false);
490 return -1;
491 }
492 return 0;
493 }
494
RecordingChannel(ChannelType * channel) const495 int32_t FakeAudioCaptureModule::RecordingChannel(ChannelType* channel) const {
496 // Stereo recording not supported. However, WebRTC ADM returns kChannelBoth
497 // in that case. Do the same here.
498 *channel = AudioDeviceModule::kChannelBoth;
499 return 0;
500 }
501
SetPlayoutBuffer(const BufferType,uint16_t)502 int32_t FakeAudioCaptureModule::SetPlayoutBuffer(const BufferType /*type*/,
503 uint16_t /*size_ms*/) {
504 ASSERT(false);
505 return 0;
506 }
507
PlayoutBuffer(BufferType *,uint16_t *) const508 int32_t FakeAudioCaptureModule::PlayoutBuffer(BufferType* /*type*/,
509 uint16_t* /*size_ms*/) const {
510 ASSERT(false);
511 return 0;
512 }
513
PlayoutDelay(uint16_t * delay_ms) const514 int32_t FakeAudioCaptureModule::PlayoutDelay(uint16_t* delay_ms) const {
515 // No delay since audio frames are dropped.
516 *delay_ms = 0;
517 return 0;
518 }
519
RecordingDelay(uint16_t *) const520 int32_t FakeAudioCaptureModule::RecordingDelay(uint16_t* /*delay_ms*/) const {
521 ASSERT(false);
522 return 0;
523 }
524
CPULoad(uint16_t *) const525 int32_t FakeAudioCaptureModule::CPULoad(uint16_t* /*load*/) const {
526 ASSERT(false);
527 return 0;
528 }
529
StartRawOutputFileRecording(const char[webrtc::kAdmMaxFileNameSize])530 int32_t FakeAudioCaptureModule::StartRawOutputFileRecording(
531 const char /*pcm_file_name_utf8*/[webrtc::kAdmMaxFileNameSize]) {
532 ASSERT(false);
533 return 0;
534 }
535
StopRawOutputFileRecording()536 int32_t FakeAudioCaptureModule::StopRawOutputFileRecording() {
537 ASSERT(false);
538 return 0;
539 }
540
StartRawInputFileRecording(const char[webrtc::kAdmMaxFileNameSize])541 int32_t FakeAudioCaptureModule::StartRawInputFileRecording(
542 const char /*pcm_file_name_utf8*/[webrtc::kAdmMaxFileNameSize]) {
543 ASSERT(false);
544 return 0;
545 }
546
StopRawInputFileRecording()547 int32_t FakeAudioCaptureModule::StopRawInputFileRecording() {
548 ASSERT(false);
549 return 0;
550 }
551
SetRecordingSampleRate(const uint32_t)552 int32_t FakeAudioCaptureModule::SetRecordingSampleRate(
553 const uint32_t /*samples_per_sec*/) {
554 ASSERT(false);
555 return 0;
556 }
557
RecordingSampleRate(uint32_t *) const558 int32_t FakeAudioCaptureModule::RecordingSampleRate(
559 uint32_t* /*samples_per_sec*/) const {
560 ASSERT(false);
561 return 0;
562 }
563
SetPlayoutSampleRate(const uint32_t)564 int32_t FakeAudioCaptureModule::SetPlayoutSampleRate(
565 const uint32_t /*samples_per_sec*/) {
566 ASSERT(false);
567 return 0;
568 }
569
PlayoutSampleRate(uint32_t *) const570 int32_t FakeAudioCaptureModule::PlayoutSampleRate(
571 uint32_t* /*samples_per_sec*/) const {
572 ASSERT(false);
573 return 0;
574 }
575
ResetAudioDevice()576 int32_t FakeAudioCaptureModule::ResetAudioDevice() {
577 ASSERT(false);
578 return 0;
579 }
580
SetLoudspeakerStatus(bool)581 int32_t FakeAudioCaptureModule::SetLoudspeakerStatus(bool /*enable*/) {
582 ASSERT(false);
583 return 0;
584 }
585
GetLoudspeakerStatus(bool *) const586 int32_t FakeAudioCaptureModule::GetLoudspeakerStatus(bool* /*enabled*/) const {
587 ASSERT(false);
588 return 0;
589 }
590
OnMessage(rtc::Message * msg)591 void FakeAudioCaptureModule::OnMessage(rtc::Message* msg) {
592 switch (msg->message_id) {
593 case MSG_START_PROCESS:
594 StartProcessP();
595 break;
596 case MSG_RUN_PROCESS:
597 ProcessFrameP();
598 break;
599 default:
600 // All existing messages should be caught. Getting here should never
601 // happen.
602 ASSERT(false);
603 }
604 }
605
Initialize()606 bool FakeAudioCaptureModule::Initialize() {
607 // Set the send buffer samples high enough that it would not occur on the
608 // remote side unless a packet containing a sample of that magnitude has been
609 // sent to it. Note that the audio processing pipeline will likely distort the
610 // original signal.
611 SetSendBuffer(kHighSampleValue);
612 last_process_time_ms_ = rtc::Time();
613 return true;
614 }
615
SetSendBuffer(int value)616 void FakeAudioCaptureModule::SetSendBuffer(int value) {
617 Sample* buffer_ptr = reinterpret_cast<Sample*>(send_buffer_);
618 const size_t buffer_size_in_samples =
619 sizeof(send_buffer_) / kNumberBytesPerSample;
620 for (size_t i = 0; i < buffer_size_in_samples; ++i) {
621 buffer_ptr[i] = value;
622 }
623 }
624
ResetRecBuffer()625 void FakeAudioCaptureModule::ResetRecBuffer() {
626 memset(rec_buffer_, 0, sizeof(rec_buffer_));
627 }
628
CheckRecBuffer(int value)629 bool FakeAudioCaptureModule::CheckRecBuffer(int value) {
630 const Sample* buffer_ptr = reinterpret_cast<const Sample*>(rec_buffer_);
631 const size_t buffer_size_in_samples =
632 sizeof(rec_buffer_) / kNumberBytesPerSample;
633 for (size_t i = 0; i < buffer_size_in_samples; ++i) {
634 if (buffer_ptr[i] >= value) return true;
635 }
636 return false;
637 }
638
ShouldStartProcessing()639 bool FakeAudioCaptureModule::ShouldStartProcessing() {
640 return recording_ || playing_;
641 }
642
UpdateProcessing(bool start)643 void FakeAudioCaptureModule::UpdateProcessing(bool start) {
644 if (start) {
645 if (!process_thread_) {
646 process_thread_.reset(new rtc::Thread());
647 process_thread_->Start();
648 }
649 process_thread_->Post(this, MSG_START_PROCESS);
650 } else {
651 if (process_thread_) {
652 process_thread_->Stop();
653 process_thread_.reset(nullptr);
654 }
655 started_ = false;
656 }
657 }
658
StartProcessP()659 void FakeAudioCaptureModule::StartProcessP() {
660 ASSERT(process_thread_->IsCurrent());
661 if (started_) {
662 // Already started.
663 return;
664 }
665 ProcessFrameP();
666 }
667
ProcessFrameP()668 void FakeAudioCaptureModule::ProcessFrameP() {
669 ASSERT(process_thread_->IsCurrent());
670 if (!started_) {
671 next_frame_time_ = rtc::Time();
672 started_ = true;
673 }
674
675 {
676 rtc::CritScope cs(&crit_);
677 // Receive and send frames every kTimePerFrameMs.
678 if (playing_) {
679 ReceiveFrameP();
680 }
681 if (recording_) {
682 SendFrameP();
683 }
684 }
685
686 next_frame_time_ += kTimePerFrameMs;
687 const uint32_t current_time = rtc::Time();
688 const uint32_t wait_time =
689 (next_frame_time_ > current_time) ? next_frame_time_ - current_time : 0;
690 process_thread_->PostDelayed(wait_time, this, MSG_RUN_PROCESS);
691 }
692
ReceiveFrameP()693 void FakeAudioCaptureModule::ReceiveFrameP() {
694 ASSERT(process_thread_->IsCurrent());
695 {
696 rtc::CritScope cs(&crit_callback_);
697 if (!audio_callback_) {
698 return;
699 }
700 ResetRecBuffer();
701 size_t nSamplesOut = 0;
702 int64_t elapsed_time_ms = 0;
703 int64_t ntp_time_ms = 0;
704 if (audio_callback_->NeedMorePlayData(kNumberSamples, kNumberBytesPerSample,
705 kNumberOfChannels, kSamplesPerSecond,
706 rec_buffer_, nSamplesOut,
707 &elapsed_time_ms, &ntp_time_ms) != 0) {
708 ASSERT(false);
709 }
710 ASSERT(nSamplesOut == kNumberSamples);
711 }
712 // The SetBuffer() function ensures that after decoding, the audio buffer
713 // should contain samples of similar magnitude (there is likely to be some
714 // distortion due to the audio pipeline). If one sample is detected to
715 // have the same or greater magnitude somewhere in the frame, an actual frame
716 // has been received from the remote side (i.e. faked frames are not being
717 // pulled).
718 if (CheckRecBuffer(kHighSampleValue)) {
719 rtc::CritScope cs(&crit_);
720 ++frames_received_;
721 }
722 }
723
SendFrameP()724 void FakeAudioCaptureModule::SendFrameP() {
725 ASSERT(process_thread_->IsCurrent());
726 rtc::CritScope cs(&crit_callback_);
727 if (!audio_callback_) {
728 return;
729 }
730 bool key_pressed = false;
731 uint32_t current_mic_level = 0;
732 MicrophoneVolume(¤t_mic_level);
733 if (audio_callback_->RecordedDataIsAvailable(send_buffer_, kNumberSamples,
734 kNumberBytesPerSample,
735 kNumberOfChannels,
736 kSamplesPerSecond, kTotalDelayMs,
737 kClockDriftMs, current_mic_level,
738 key_pressed,
739 current_mic_level) != 0) {
740 ASSERT(false);
741 }
742 SetMicrophoneVolume(current_mic_level);
743 }
744
745