blob: 0b6478ed2f63c32613c6910c8098dea245dded38 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
kjellanderb24317b2016-02-10 07:54:43 -08002 * Copyright 2012 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
kjellanderb24317b2016-02-10 07:54:43 -08004 * 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.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00009 */
10
Henrik Kjellander15583c12016-02-10 10:53:12 +010011#include "webrtc/api/test/fakeaudiocapturemodule.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000012
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000013#include "webrtc/base/common.h"
14#include "webrtc/base/refcount.h"
15#include "webrtc/base/thread.h"
16#include "webrtc/base/timeutils.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000017
18// Audio sample value that is high enough that it doesn't occur naturally when
19// frames are being faked. E.g. NetEq will not generate this large sample value
20// unless it has received an audio frame containing a sample of this value.
21// Even simpler buffers would likely just contain audio sample values of 0.
22static const int kHighSampleValue = 10000;
23
24// Same value as src/modules/audio_device/main/source/audio_device_config.h in
25// https://code.google.com/p/webrtc/
Peter Boström0c4e06b2015-10-07 12:23:21 +020026static const uint32_t kAdmMaxIdleTimeProcess = 1000;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000027
28// Constants here are derived by running VoE using a real ADM.
29// The constants correspond to 10ms of mono audio at 44kHz.
30static const int kTimePerFrameMs = 10;
Peter Kastingb7e50542015-06-11 12:55:50 -070031static const uint8_t kNumberOfChannels = 1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000032static const int kSamplesPerSecond = 44000;
33static const int kTotalDelayMs = 0;
34static const int kClockDriftMs = 0;
35static const uint32_t kMaxVolume = 14392;
36
37enum {
wu@webrtc.org8804a292013-10-22 23:09:20 +000038 MSG_START_PROCESS,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000039 MSG_RUN_PROCESS,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000040};
41
deadbeefee8c6d32015-08-13 14:27:18 -070042FakeAudioCaptureModule::FakeAudioCaptureModule()
henrike@webrtc.org28e20752013-07-10 00:45:36 +000043 : last_process_time_ms_(0),
deadbeefee8c6d32015-08-13 14:27:18 -070044 audio_callback_(nullptr),
henrike@webrtc.org28e20752013-07-10 00:45:36 +000045 recording_(false),
46 playing_(false),
47 play_is_initialized_(false),
48 rec_is_initialized_(false),
49 current_mic_level_(kMaxVolume),
50 started_(false),
51 next_frame_time_(0),
henrike@webrtc.org28e20752013-07-10 00:45:36 +000052 frames_received_(0) {
53}
54
55FakeAudioCaptureModule::~FakeAudioCaptureModule() {
deadbeefee8c6d32015-08-13 14:27:18 -070056 if (process_thread_) {
57 process_thread_->Stop();
58 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +000059}
60
deadbeefee8c6d32015-08-13 14:27:18 -070061rtc::scoped_refptr<FakeAudioCaptureModule> FakeAudioCaptureModule::Create() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000062 rtc::scoped_refptr<FakeAudioCaptureModule> capture_module(
deadbeefee8c6d32015-08-13 14:27:18 -070063 new rtc::RefCountedObject<FakeAudioCaptureModule>());
henrike@webrtc.org28e20752013-07-10 00:45:36 +000064 if (!capture_module->Initialize()) {
deadbeefee8c6d32015-08-13 14:27:18 -070065 return nullptr;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000066 }
67 return capture_module;
68}
69
70int FakeAudioCaptureModule::frames_received() const {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000071 rtc::CritScope cs(&crit_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000072 return frames_received_;
73}
74
pkasting@chromium.org0b1534c2014-12-15 22:09:40 +000075int64_t FakeAudioCaptureModule::TimeUntilNextProcess() {
Peter Boström0c4e06b2015-10-07 12:23:21 +020076 const uint32_t current_time = rtc::Time();
henrike@webrtc.org28e20752013-07-10 00:45:36 +000077 if (current_time < last_process_time_ms_) {
78 // TODO: wraparound could be handled more gracefully.
79 return 0;
80 }
Peter Boström0c4e06b2015-10-07 12:23:21 +020081 const uint32_t elapsed_time = current_time - last_process_time_ms_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000082 if (kAdmMaxIdleTimeProcess < elapsed_time) {
83 return 0;
84 }
85 return kAdmMaxIdleTimeProcess - elapsed_time;
86}
87
pbosa26ac922016-02-25 04:50:01 -080088void FakeAudioCaptureModule::Process() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000089 last_process_time_ms_ = rtc::Time();
henrike@webrtc.org28e20752013-07-10 00:45:36 +000090}
91
henrike@webrtc.org28e20752013-07-10 00:45:36 +000092int32_t FakeAudioCaptureModule::ActiveAudioLayer(
93 AudioLayer* /*audio_layer*/) const {
94 ASSERT(false);
95 return 0;
96}
97
98webrtc::AudioDeviceModule::ErrorCode FakeAudioCaptureModule::LastError() const {
99 ASSERT(false);
100 return webrtc::AudioDeviceModule::kAdmErrNone;
101}
102
103int32_t FakeAudioCaptureModule::RegisterEventObserver(
104 webrtc::AudioDeviceObserver* /*event_callback*/) {
105 // Only used to report warnings and errors. This fake implementation won't
106 // generate any so discard this callback.
107 return 0;
108}
109
110int32_t FakeAudioCaptureModule::RegisterAudioCallback(
111 webrtc::AudioTransport* audio_callback) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000112 rtc::CritScope cs(&crit_callback_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000113 audio_callback_ = audio_callback;
114 return 0;
115}
116
117int32_t FakeAudioCaptureModule::Init() {
118 // Initialize is called by the factory method. Safe to ignore this Init call.
119 return 0;
120}
121
122int32_t FakeAudioCaptureModule::Terminate() {
123 // Clean up in the destructor. No action here, just success.
124 return 0;
125}
126
127bool FakeAudioCaptureModule::Initialized() const {
128 ASSERT(false);
129 return 0;
130}
131
132int16_t FakeAudioCaptureModule::PlayoutDevices() {
133 ASSERT(false);
134 return 0;
135}
136
137int16_t FakeAudioCaptureModule::RecordingDevices() {
138 ASSERT(false);
139 return 0;
140}
141
142int32_t FakeAudioCaptureModule::PlayoutDeviceName(
143 uint16_t /*index*/,
144 char /*name*/[webrtc::kAdmMaxDeviceNameSize],
145 char /*guid*/[webrtc::kAdmMaxGuidSize]) {
146 ASSERT(false);
147 return 0;
148}
149
150int32_t FakeAudioCaptureModule::RecordingDeviceName(
151 uint16_t /*index*/,
152 char /*name*/[webrtc::kAdmMaxDeviceNameSize],
153 char /*guid*/[webrtc::kAdmMaxGuidSize]) {
154 ASSERT(false);
155 return 0;
156}
157
158int32_t FakeAudioCaptureModule::SetPlayoutDevice(uint16_t /*index*/) {
159 // No playout device, just playing from file. Return success.
160 return 0;
161}
162
163int32_t FakeAudioCaptureModule::SetPlayoutDevice(WindowsDeviceType /*device*/) {
164 if (play_is_initialized_) {
165 return -1;
166 }
167 return 0;
168}
169
170int32_t FakeAudioCaptureModule::SetRecordingDevice(uint16_t /*index*/) {
171 // No recording device, just dropping audio. Return success.
172 return 0;
173}
174
175int32_t FakeAudioCaptureModule::SetRecordingDevice(
176 WindowsDeviceType /*device*/) {
177 if (rec_is_initialized_) {
178 return -1;
179 }
180 return 0;
181}
182
183int32_t FakeAudioCaptureModule::PlayoutIsAvailable(bool* /*available*/) {
184 ASSERT(false);
185 return 0;
186}
187
188int32_t FakeAudioCaptureModule::InitPlayout() {
189 play_is_initialized_ = true;
190 return 0;
191}
192
193bool FakeAudioCaptureModule::PlayoutIsInitialized() const {
194 return play_is_initialized_;
195}
196
197int32_t FakeAudioCaptureModule::RecordingIsAvailable(bool* /*available*/) {
198 ASSERT(false);
199 return 0;
200}
201
202int32_t FakeAudioCaptureModule::InitRecording() {
203 rec_is_initialized_ = true;
204 return 0;
205}
206
207bool FakeAudioCaptureModule::RecordingIsInitialized() const {
208 ASSERT(false);
209 return 0;
210}
211
212int32_t FakeAudioCaptureModule::StartPlayout() {
213 if (!play_is_initialized_) {
214 return -1;
215 }
wu@webrtc.org8804a292013-10-22 23:09:20 +0000216 {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000217 rtc::CritScope cs(&crit_);
wu@webrtc.org8804a292013-10-22 23:09:20 +0000218 playing_ = true;
219 }
220 bool start = true;
221 UpdateProcessing(start);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000222 return 0;
223}
224
225int32_t FakeAudioCaptureModule::StopPlayout() {
wu@webrtc.org8804a292013-10-22 23:09:20 +0000226 bool start = false;
227 {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000228 rtc::CritScope cs(&crit_);
wu@webrtc.org8804a292013-10-22 23:09:20 +0000229 playing_ = false;
230 start = ShouldStartProcessing();
231 }
232 UpdateProcessing(start);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000233 return 0;
234}
235
236bool FakeAudioCaptureModule::Playing() const {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000237 rtc::CritScope cs(&crit_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000238 return playing_;
239}
240
241int32_t FakeAudioCaptureModule::StartRecording() {
242 if (!rec_is_initialized_) {
243 return -1;
244 }
wu@webrtc.org8804a292013-10-22 23:09:20 +0000245 {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000246 rtc::CritScope cs(&crit_);
wu@webrtc.org8804a292013-10-22 23:09:20 +0000247 recording_ = true;
248 }
249 bool start = true;
250 UpdateProcessing(start);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000251 return 0;
252}
253
254int32_t FakeAudioCaptureModule::StopRecording() {
wu@webrtc.org8804a292013-10-22 23:09:20 +0000255 bool start = false;
256 {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000257 rtc::CritScope cs(&crit_);
wu@webrtc.org8804a292013-10-22 23:09:20 +0000258 recording_ = false;
259 start = ShouldStartProcessing();
260 }
261 UpdateProcessing(start);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000262 return 0;
263}
264
265bool FakeAudioCaptureModule::Recording() const {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000266 rtc::CritScope cs(&crit_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000267 return recording_;
268}
269
270int32_t FakeAudioCaptureModule::SetAGC(bool /*enable*/) {
271 // No AGC but not needed since audio is pregenerated. Return success.
272 return 0;
273}
274
275bool FakeAudioCaptureModule::AGC() const {
276 ASSERT(false);
277 return 0;
278}
279
280int32_t FakeAudioCaptureModule::SetWaveOutVolume(uint16_t /*volume_left*/,
281 uint16_t /*volume_right*/) {
282 ASSERT(false);
283 return 0;
284}
285
286int32_t FakeAudioCaptureModule::WaveOutVolume(
287 uint16_t* /*volume_left*/,
288 uint16_t* /*volume_right*/) const {
289 ASSERT(false);
290 return 0;
291}
292
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000293int32_t FakeAudioCaptureModule::InitSpeaker() {
294 // No speaker, just playing from file. Return success.
295 return 0;
296}
297
298bool FakeAudioCaptureModule::SpeakerIsInitialized() const {
299 ASSERT(false);
300 return 0;
301}
302
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000303int32_t FakeAudioCaptureModule::InitMicrophone() {
304 // No microphone, just playing from file. Return success.
305 return 0;
306}
307
308bool FakeAudioCaptureModule::MicrophoneIsInitialized() const {
309 ASSERT(false);
310 return 0;
311}
312
313int32_t FakeAudioCaptureModule::SpeakerVolumeIsAvailable(bool* /*available*/) {
314 ASSERT(false);
315 return 0;
316}
317
318int32_t FakeAudioCaptureModule::SetSpeakerVolume(uint32_t /*volume*/) {
319 ASSERT(false);
320 return 0;
321}
322
323int32_t FakeAudioCaptureModule::SpeakerVolume(uint32_t* /*volume*/) const {
324 ASSERT(false);
325 return 0;
326}
327
328int32_t FakeAudioCaptureModule::MaxSpeakerVolume(
329 uint32_t* /*max_volume*/) const {
330 ASSERT(false);
331 return 0;
332}
333
334int32_t FakeAudioCaptureModule::MinSpeakerVolume(
335 uint32_t* /*min_volume*/) const {
336 ASSERT(false);
337 return 0;
338}
339
340int32_t FakeAudioCaptureModule::SpeakerVolumeStepSize(
341 uint16_t* /*step_size*/) const {
342 ASSERT(false);
343 return 0;
344}
345
346int32_t FakeAudioCaptureModule::MicrophoneVolumeIsAvailable(
347 bool* /*available*/) {
348 ASSERT(false);
349 return 0;
350}
351
wu@webrtc.org8804a292013-10-22 23:09:20 +0000352int32_t FakeAudioCaptureModule::SetMicrophoneVolume(uint32_t volume) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000353 rtc::CritScope cs(&crit_);
wu@webrtc.org8804a292013-10-22 23:09:20 +0000354 current_mic_level_ = volume;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000355 return 0;
356}
357
358int32_t FakeAudioCaptureModule::MicrophoneVolume(uint32_t* volume) const {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000359 rtc::CritScope cs(&crit_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000360 *volume = current_mic_level_;
361 return 0;
362}
363
364int32_t FakeAudioCaptureModule::MaxMicrophoneVolume(
365 uint32_t* max_volume) const {
366 *max_volume = kMaxVolume;
367 return 0;
368}
369
370int32_t FakeAudioCaptureModule::MinMicrophoneVolume(
371 uint32_t* /*min_volume*/) const {
372 ASSERT(false);
373 return 0;
374}
375
376int32_t FakeAudioCaptureModule::MicrophoneVolumeStepSize(
377 uint16_t* /*step_size*/) const {
378 ASSERT(false);
379 return 0;
380}
381
382int32_t FakeAudioCaptureModule::SpeakerMuteIsAvailable(bool* /*available*/) {
383 ASSERT(false);
384 return 0;
385}
386
387int32_t FakeAudioCaptureModule::SetSpeakerMute(bool /*enable*/) {
388 ASSERT(false);
389 return 0;
390}
391
392int32_t FakeAudioCaptureModule::SpeakerMute(bool* /*enabled*/) const {
393 ASSERT(false);
394 return 0;
395}
396
397int32_t FakeAudioCaptureModule::MicrophoneMuteIsAvailable(bool* /*available*/) {
398 ASSERT(false);
399 return 0;
400}
401
402int32_t FakeAudioCaptureModule::SetMicrophoneMute(bool /*enable*/) {
403 ASSERT(false);
404 return 0;
405}
406
407int32_t FakeAudioCaptureModule::MicrophoneMute(bool* /*enabled*/) const {
408 ASSERT(false);
409 return 0;
410}
411
412int32_t FakeAudioCaptureModule::MicrophoneBoostIsAvailable(
413 bool* /*available*/) {
414 ASSERT(false);
415 return 0;
416}
417
418int32_t FakeAudioCaptureModule::SetMicrophoneBoost(bool /*enable*/) {
419 ASSERT(false);
420 return 0;
421}
422
423int32_t FakeAudioCaptureModule::MicrophoneBoost(bool* /*enabled*/) const {
424 ASSERT(false);
425 return 0;
426}
427
428int32_t FakeAudioCaptureModule::StereoPlayoutIsAvailable(
429 bool* available) const {
430 // No recording device, just dropping audio. Stereo can be dropped just
431 // as easily as mono.
432 *available = true;
433 return 0;
434}
435
436int32_t FakeAudioCaptureModule::SetStereoPlayout(bool /*enable*/) {
437 // No recording device, just dropping audio. Stereo can be dropped just
438 // as easily as mono.
439 return 0;
440}
441
442int32_t FakeAudioCaptureModule::StereoPlayout(bool* /*enabled*/) const {
443 ASSERT(false);
444 return 0;
445}
446
447int32_t FakeAudioCaptureModule::StereoRecordingIsAvailable(
448 bool* available) const {
449 // Keep thing simple. No stereo recording.
450 *available = false;
451 return 0;
452}
453
454int32_t FakeAudioCaptureModule::SetStereoRecording(bool enable) {
455 if (!enable) {
456 return 0;
457 }
458 return -1;
459}
460
461int32_t FakeAudioCaptureModule::StereoRecording(bool* /*enabled*/) const {
462 ASSERT(false);
463 return 0;
464}
465
466int32_t FakeAudioCaptureModule::SetRecordingChannel(
467 const ChannelType channel) {
468 if (channel != AudioDeviceModule::kChannelBoth) {
469 // There is no right or left in mono. I.e. kChannelBoth should be used for
470 // mono.
471 ASSERT(false);
472 return -1;
473 }
474 return 0;
475}
476
477int32_t FakeAudioCaptureModule::RecordingChannel(ChannelType* channel) const {
478 // Stereo recording not supported. However, WebRTC ADM returns kChannelBoth
479 // in that case. Do the same here.
480 *channel = AudioDeviceModule::kChannelBoth;
481 return 0;
482}
483
484int32_t FakeAudioCaptureModule::SetPlayoutBuffer(const BufferType /*type*/,
485 uint16_t /*size_ms*/) {
486 ASSERT(false);
487 return 0;
488}
489
490int32_t FakeAudioCaptureModule::PlayoutBuffer(BufferType* /*type*/,
491 uint16_t* /*size_ms*/) const {
492 ASSERT(false);
493 return 0;
494}
495
496int32_t FakeAudioCaptureModule::PlayoutDelay(uint16_t* delay_ms) const {
497 // No delay since audio frames are dropped.
498 *delay_ms = 0;
499 return 0;
500}
501
502int32_t FakeAudioCaptureModule::RecordingDelay(uint16_t* /*delay_ms*/) const {
503 ASSERT(false);
504 return 0;
505}
506
507int32_t FakeAudioCaptureModule::CPULoad(uint16_t* /*load*/) const {
508 ASSERT(false);
509 return 0;
510}
511
512int32_t FakeAudioCaptureModule::StartRawOutputFileRecording(
513 const char /*pcm_file_name_utf8*/[webrtc::kAdmMaxFileNameSize]) {
514 ASSERT(false);
515 return 0;
516}
517
518int32_t FakeAudioCaptureModule::StopRawOutputFileRecording() {
519 ASSERT(false);
520 return 0;
521}
522
523int32_t FakeAudioCaptureModule::StartRawInputFileRecording(
524 const char /*pcm_file_name_utf8*/[webrtc::kAdmMaxFileNameSize]) {
525 ASSERT(false);
526 return 0;
527}
528
529int32_t FakeAudioCaptureModule::StopRawInputFileRecording() {
530 ASSERT(false);
531 return 0;
532}
533
534int32_t FakeAudioCaptureModule::SetRecordingSampleRate(
535 const uint32_t /*samples_per_sec*/) {
536 ASSERT(false);
537 return 0;
538}
539
540int32_t FakeAudioCaptureModule::RecordingSampleRate(
541 uint32_t* /*samples_per_sec*/) const {
542 ASSERT(false);
543 return 0;
544}
545
546int32_t FakeAudioCaptureModule::SetPlayoutSampleRate(
547 const uint32_t /*samples_per_sec*/) {
548 ASSERT(false);
549 return 0;
550}
551
552int32_t FakeAudioCaptureModule::PlayoutSampleRate(
553 uint32_t* /*samples_per_sec*/) const {
554 ASSERT(false);
555 return 0;
556}
557
558int32_t FakeAudioCaptureModule::ResetAudioDevice() {
559 ASSERT(false);
560 return 0;
561}
562
563int32_t FakeAudioCaptureModule::SetLoudspeakerStatus(bool /*enable*/) {
564 ASSERT(false);
565 return 0;
566}
567
568int32_t FakeAudioCaptureModule::GetLoudspeakerStatus(bool* /*enabled*/) const {
569 ASSERT(false);
570 return 0;
571}
572
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000573void FakeAudioCaptureModule::OnMessage(rtc::Message* msg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000574 switch (msg->message_id) {
wu@webrtc.org8804a292013-10-22 23:09:20 +0000575 case MSG_START_PROCESS:
576 StartProcessP();
577 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000578 case MSG_RUN_PROCESS:
579 ProcessFrameP();
580 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000581 default:
582 // All existing messages should be caught. Getting here should never
583 // happen.
584 ASSERT(false);
585 }
586}
587
588bool FakeAudioCaptureModule::Initialize() {
589 // Set the send buffer samples high enough that it would not occur on the
590 // remote side unless a packet containing a sample of that magnitude has been
591 // sent to it. Note that the audio processing pipeline will likely distort the
592 // original signal.
593 SetSendBuffer(kHighSampleValue);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000594 last_process_time_ms_ = rtc::Time();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000595 return true;
596}
597
598void FakeAudioCaptureModule::SetSendBuffer(int value) {
599 Sample* buffer_ptr = reinterpret_cast<Sample*>(send_buffer_);
Peter Kastingdce40cf2015-08-24 14:52:23 -0700600 const size_t buffer_size_in_samples =
Peter Kasting728d9032015-06-11 14:31:38 -0700601 sizeof(send_buffer_) / kNumberBytesPerSample;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700602 for (size_t i = 0; i < buffer_size_in_samples; ++i) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000603 buffer_ptr[i] = value;
604 }
605}
606
607void FakeAudioCaptureModule::ResetRecBuffer() {
608 memset(rec_buffer_, 0, sizeof(rec_buffer_));
609}
610
611bool FakeAudioCaptureModule::CheckRecBuffer(int value) {
612 const Sample* buffer_ptr = reinterpret_cast<const Sample*>(rec_buffer_);
Peter Kastingdce40cf2015-08-24 14:52:23 -0700613 const size_t buffer_size_in_samples =
Peter Kasting728d9032015-06-11 14:31:38 -0700614 sizeof(rec_buffer_) / kNumberBytesPerSample;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700615 for (size_t i = 0; i < buffer_size_in_samples; ++i) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000616 if (buffer_ptr[i] >= value) return true;
617 }
618 return false;
619}
620
wu@webrtc.org8804a292013-10-22 23:09:20 +0000621bool FakeAudioCaptureModule::ShouldStartProcessing() {
622 return recording_ || playing_;
623}
624
625void FakeAudioCaptureModule::UpdateProcessing(bool start) {
626 if (start) {
deadbeefee8c6d32015-08-13 14:27:18 -0700627 if (!process_thread_) {
628 process_thread_.reset(new rtc::Thread());
629 process_thread_->Start();
630 }
wu@webrtc.org8804a292013-10-22 23:09:20 +0000631 process_thread_->Post(this, MSG_START_PROCESS);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000632 } else {
deadbeefee8c6d32015-08-13 14:27:18 -0700633 if (process_thread_) {
634 process_thread_->Stop();
635 process_thread_.reset(nullptr);
636 }
637 started_ = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000638 }
639}
640
wu@webrtc.org8804a292013-10-22 23:09:20 +0000641void FakeAudioCaptureModule::StartProcessP() {
deadbeefee8c6d32015-08-13 14:27:18 -0700642 ASSERT(process_thread_->IsCurrent());
wu@webrtc.org8804a292013-10-22 23:09:20 +0000643 if (started_) {
644 // Already started.
645 return;
646 }
647 ProcessFrameP();
648}
649
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000650void FakeAudioCaptureModule::ProcessFrameP() {
deadbeefee8c6d32015-08-13 14:27:18 -0700651 ASSERT(process_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000652 if (!started_) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000653 next_frame_time_ = rtc::Time();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000654 started_ = true;
655 }
wu@webrtc.org8804a292013-10-22 23:09:20 +0000656
wu@webrtc.org8804a292013-10-22 23:09:20 +0000657 {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000658 rtc::CritScope cs(&crit_);
deadbeefee8c6d32015-08-13 14:27:18 -0700659 // Receive and send frames every kTimePerFrameMs.
660 if (playing_) {
661 ReceiveFrameP();
662 }
663 if (recording_) {
664 SendFrameP();
665 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000666 }
667
668 next_frame_time_ += kTimePerFrameMs;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200669 const uint32_t current_time = rtc::Time();
670 const uint32_t wait_time =
671 (next_frame_time_ > current_time) ? next_frame_time_ - current_time : 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000672 process_thread_->PostDelayed(wait_time, this, MSG_RUN_PROCESS);
673}
674
675void FakeAudioCaptureModule::ReceiveFrameP() {
deadbeefee8c6d32015-08-13 14:27:18 -0700676 ASSERT(process_thread_->IsCurrent());
wu@webrtc.org8804a292013-10-22 23:09:20 +0000677 {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000678 rtc::CritScope cs(&crit_callback_);
wu@webrtc.org8804a292013-10-22 23:09:20 +0000679 if (!audio_callback_) {
680 return;
681 }
682 ResetRecBuffer();
Peter Kastingdce40cf2015-08-24 14:52:23 -0700683 size_t nSamplesOut = 0;
wu@webrtc.org94454b72014-06-05 20:34:08 +0000684 int64_t elapsed_time_ms = 0;
wu@webrtc.orgcb711f72014-05-19 17:39:11 +0000685 int64_t ntp_time_ms = 0;
686 if (audio_callback_->NeedMorePlayData(kNumberSamples, kNumberBytesPerSample,
687 kNumberOfChannels, kSamplesPerSecond,
688 rec_buffer_, nSamplesOut,
wu@webrtc.org94454b72014-06-05 20:34:08 +0000689 &elapsed_time_ms, &ntp_time_ms) != 0) {
wu@webrtc.org8804a292013-10-22 23:09:20 +0000690 ASSERT(false);
691 }
692 ASSERT(nSamplesOut == kNumberSamples);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000693 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000694 // The SetBuffer() function ensures that after decoding, the audio buffer
695 // should contain samples of similar magnitude (there is likely to be some
696 // distortion due to the audio pipeline). If one sample is detected to
697 // have the same or greater magnitude somewhere in the frame, an actual frame
698 // has been received from the remote side (i.e. faked frames are not being
699 // pulled).
wu@webrtc.org8804a292013-10-22 23:09:20 +0000700 if (CheckRecBuffer(kHighSampleValue)) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000701 rtc::CritScope cs(&crit_);
wu@webrtc.org8804a292013-10-22 23:09:20 +0000702 ++frames_received_;
703 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000704}
705
706void FakeAudioCaptureModule::SendFrameP() {
deadbeefee8c6d32015-08-13 14:27:18 -0700707 ASSERT(process_thread_->IsCurrent());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000708 rtc::CritScope cs(&crit_callback_);
wu@webrtc.org8804a292013-10-22 23:09:20 +0000709 if (!audio_callback_) {
710 return;
711 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000712 bool key_pressed = false;
wu@webrtc.org8804a292013-10-22 23:09:20 +0000713 uint32_t current_mic_level = 0;
714 MicrophoneVolume(&current_mic_level);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000715 if (audio_callback_->RecordedDataIsAvailable(send_buffer_, kNumberSamples,
716 kNumberBytesPerSample,
717 kNumberOfChannels,
718 kSamplesPerSecond, kTotalDelayMs,
wu@webrtc.org8804a292013-10-22 23:09:20 +0000719 kClockDriftMs, current_mic_level,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000720 key_pressed,
wu@webrtc.org8804a292013-10-22 23:09:20 +0000721 current_mic_level) != 0) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000722 ASSERT(false);
723 }
wu@webrtc.org8804a292013-10-22 23:09:20 +0000724 SetMicrophoneVolume(current_mic_level);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000725}
726