blob: 47f17a1739abe566a38bad9d14ebdfa24b0507d2 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
2 * libjingle
jlmiller@webrtc.org5f93d0a2015-01-20 21:36:13 +00003 * Copyright 2012 Google Inc.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00004 *
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
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000030#include "webrtc/base/common.h"
31#include "webrtc/base/refcount.h"
32#include "webrtc/base/thread.h"
33#include "webrtc/base/timeutils.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000034
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.
39static 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/
43static const uint32 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.
47static const int kTimePerFrameMs = 10;
Peter Kastingb7e50542015-06-11 12:55:50 -070048static const uint8_t kNumberOfChannels = 1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000049static const int kSamplesPerSecond = 44000;
50static const int kTotalDelayMs = 0;
51static const int kClockDriftMs = 0;
52static const uint32_t kMaxVolume = 14392;
53
54enum {
wu@webrtc.org8804a292013-10-22 23:09:20 +000055 MSG_START_PROCESS,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000056 MSG_RUN_PROCESS,
57 MSG_STOP_PROCESS,
58};
59
60FakeAudioCaptureModule::FakeAudioCaptureModule(
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000061 rtc::Thread* process_thread)
henrike@webrtc.org28e20752013-07-10 00:45:36 +000062 : last_process_time_ms_(0),
63 audio_callback_(NULL),
64 recording_(false),
65 playing_(false),
66 play_is_initialized_(false),
67 rec_is_initialized_(false),
68 current_mic_level_(kMaxVolume),
69 started_(false),
70 next_frame_time_(0),
71 process_thread_(process_thread),
72 frames_received_(0) {
73}
74
75FakeAudioCaptureModule::~FakeAudioCaptureModule() {
76 // Ensure that thread stops calling ProcessFrame().
77 process_thread_->Send(this, MSG_STOP_PROCESS);
78}
79
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000080rtc::scoped_refptr<FakeAudioCaptureModule> FakeAudioCaptureModule::Create(
81 rtc::Thread* process_thread) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000082 if (process_thread == NULL) return NULL;
83
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000084 rtc::scoped_refptr<FakeAudioCaptureModule> capture_module(
85 new rtc::RefCountedObject<FakeAudioCaptureModule>(process_thread));
henrike@webrtc.org28e20752013-07-10 00:45:36 +000086 if (!capture_module->Initialize()) {
87 return NULL;
88 }
89 return capture_module;
90}
91
92int FakeAudioCaptureModule::frames_received() const {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000093 rtc::CritScope cs(&crit_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000094 return frames_received_;
95}
96
pkasting@chromium.org0b1534c2014-12-15 22:09:40 +000097int64_t FakeAudioCaptureModule::TimeUntilNextProcess() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000098 const uint32 current_time = rtc::Time();
henrike@webrtc.org28e20752013-07-10 00:45:36 +000099 if (current_time < last_process_time_ms_) {
100 // TODO: wraparound could be handled more gracefully.
101 return 0;
102 }
103 const uint32 elapsed_time = current_time - last_process_time_ms_;
104 if (kAdmMaxIdleTimeProcess < elapsed_time) {
105 return 0;
106 }
107 return kAdmMaxIdleTimeProcess - elapsed_time;
108}
109
110int32_t FakeAudioCaptureModule::Process() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000111 last_process_time_ms_ = rtc::Time();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000112 return 0;
113}
114
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000115int32_t FakeAudioCaptureModule::ActiveAudioLayer(
116 AudioLayer* /*audio_layer*/) const {
117 ASSERT(false);
118 return 0;
119}
120
121webrtc::AudioDeviceModule::ErrorCode FakeAudioCaptureModule::LastError() const {
122 ASSERT(false);
123 return webrtc::AudioDeviceModule::kAdmErrNone;
124}
125
126int32_t FakeAudioCaptureModule::RegisterEventObserver(
127 webrtc::AudioDeviceObserver* /*event_callback*/) {
128 // Only used to report warnings and errors. This fake implementation won't
129 // generate any so discard this callback.
130 return 0;
131}
132
133int32_t FakeAudioCaptureModule::RegisterAudioCallback(
134 webrtc::AudioTransport* audio_callback) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000135 rtc::CritScope cs(&crit_callback_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000136 audio_callback_ = audio_callback;
137 return 0;
138}
139
140int32_t FakeAudioCaptureModule::Init() {
141 // Initialize is called by the factory method. Safe to ignore this Init call.
142 return 0;
143}
144
145int32_t FakeAudioCaptureModule::Terminate() {
146 // Clean up in the destructor. No action here, just success.
147 return 0;
148}
149
150bool FakeAudioCaptureModule::Initialized() const {
151 ASSERT(false);
152 return 0;
153}
154
155int16_t FakeAudioCaptureModule::PlayoutDevices() {
156 ASSERT(false);
157 return 0;
158}
159
160int16_t FakeAudioCaptureModule::RecordingDevices() {
161 ASSERT(false);
162 return 0;
163}
164
165int32_t FakeAudioCaptureModule::PlayoutDeviceName(
166 uint16_t /*index*/,
167 char /*name*/[webrtc::kAdmMaxDeviceNameSize],
168 char /*guid*/[webrtc::kAdmMaxGuidSize]) {
169 ASSERT(false);
170 return 0;
171}
172
173int32_t FakeAudioCaptureModule::RecordingDeviceName(
174 uint16_t /*index*/,
175 char /*name*/[webrtc::kAdmMaxDeviceNameSize],
176 char /*guid*/[webrtc::kAdmMaxGuidSize]) {
177 ASSERT(false);
178 return 0;
179}
180
181int32_t FakeAudioCaptureModule::SetPlayoutDevice(uint16_t /*index*/) {
182 // No playout device, just playing from file. Return success.
183 return 0;
184}
185
186int32_t FakeAudioCaptureModule::SetPlayoutDevice(WindowsDeviceType /*device*/) {
187 if (play_is_initialized_) {
188 return -1;
189 }
190 return 0;
191}
192
193int32_t FakeAudioCaptureModule::SetRecordingDevice(uint16_t /*index*/) {
194 // No recording device, just dropping audio. Return success.
195 return 0;
196}
197
198int32_t FakeAudioCaptureModule::SetRecordingDevice(
199 WindowsDeviceType /*device*/) {
200 if (rec_is_initialized_) {
201 return -1;
202 }
203 return 0;
204}
205
206int32_t FakeAudioCaptureModule::PlayoutIsAvailable(bool* /*available*/) {
207 ASSERT(false);
208 return 0;
209}
210
211int32_t FakeAudioCaptureModule::InitPlayout() {
212 play_is_initialized_ = true;
213 return 0;
214}
215
216bool FakeAudioCaptureModule::PlayoutIsInitialized() const {
217 return play_is_initialized_;
218}
219
220int32_t FakeAudioCaptureModule::RecordingIsAvailable(bool* /*available*/) {
221 ASSERT(false);
222 return 0;
223}
224
225int32_t FakeAudioCaptureModule::InitRecording() {
226 rec_is_initialized_ = true;
227 return 0;
228}
229
230bool FakeAudioCaptureModule::RecordingIsInitialized() const {
231 ASSERT(false);
232 return 0;
233}
234
235int32_t FakeAudioCaptureModule::StartPlayout() {
236 if (!play_is_initialized_) {
237 return -1;
238 }
wu@webrtc.org8804a292013-10-22 23:09:20 +0000239 {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000240 rtc::CritScope cs(&crit_);
wu@webrtc.org8804a292013-10-22 23:09:20 +0000241 playing_ = true;
242 }
243 bool start = true;
244 UpdateProcessing(start);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000245 return 0;
246}
247
248int32_t FakeAudioCaptureModule::StopPlayout() {
wu@webrtc.org8804a292013-10-22 23:09:20 +0000249 bool start = false;
250 {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000251 rtc::CritScope cs(&crit_);
wu@webrtc.org8804a292013-10-22 23:09:20 +0000252 playing_ = false;
253 start = ShouldStartProcessing();
254 }
255 UpdateProcessing(start);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000256 return 0;
257}
258
259bool FakeAudioCaptureModule::Playing() const {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000260 rtc::CritScope cs(&crit_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000261 return playing_;
262}
263
264int32_t FakeAudioCaptureModule::StartRecording() {
265 if (!rec_is_initialized_) {
266 return -1;
267 }
wu@webrtc.org8804a292013-10-22 23:09:20 +0000268 {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000269 rtc::CritScope cs(&crit_);
wu@webrtc.org8804a292013-10-22 23:09:20 +0000270 recording_ = true;
271 }
272 bool start = true;
273 UpdateProcessing(start);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000274 return 0;
275}
276
277int32_t FakeAudioCaptureModule::StopRecording() {
wu@webrtc.org8804a292013-10-22 23:09:20 +0000278 bool start = false;
279 {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000280 rtc::CritScope cs(&crit_);
wu@webrtc.org8804a292013-10-22 23:09:20 +0000281 recording_ = false;
282 start = ShouldStartProcessing();
283 }
284 UpdateProcessing(start);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000285 return 0;
286}
287
288bool FakeAudioCaptureModule::Recording() const {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000289 rtc::CritScope cs(&crit_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000290 return recording_;
291}
292
293int32_t FakeAudioCaptureModule::SetAGC(bool /*enable*/) {
294 // No AGC but not needed since audio is pregenerated. Return success.
295 return 0;
296}
297
298bool FakeAudioCaptureModule::AGC() const {
299 ASSERT(false);
300 return 0;
301}
302
303int32_t FakeAudioCaptureModule::SetWaveOutVolume(uint16_t /*volume_left*/,
304 uint16_t /*volume_right*/) {
305 ASSERT(false);
306 return 0;
307}
308
309int32_t FakeAudioCaptureModule::WaveOutVolume(
310 uint16_t* /*volume_left*/,
311 uint16_t* /*volume_right*/) const {
312 ASSERT(false);
313 return 0;
314}
315
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000316int32_t FakeAudioCaptureModule::InitSpeaker() {
317 // No speaker, just playing from file. Return success.
318 return 0;
319}
320
321bool FakeAudioCaptureModule::SpeakerIsInitialized() const {
322 ASSERT(false);
323 return 0;
324}
325
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000326int32_t FakeAudioCaptureModule::InitMicrophone() {
327 // No microphone, just playing from file. Return success.
328 return 0;
329}
330
331bool FakeAudioCaptureModule::MicrophoneIsInitialized() const {
332 ASSERT(false);
333 return 0;
334}
335
336int32_t FakeAudioCaptureModule::SpeakerVolumeIsAvailable(bool* /*available*/) {
337 ASSERT(false);
338 return 0;
339}
340
341int32_t FakeAudioCaptureModule::SetSpeakerVolume(uint32_t /*volume*/) {
342 ASSERT(false);
343 return 0;
344}
345
346int32_t FakeAudioCaptureModule::SpeakerVolume(uint32_t* /*volume*/) const {
347 ASSERT(false);
348 return 0;
349}
350
351int32_t FakeAudioCaptureModule::MaxSpeakerVolume(
352 uint32_t* /*max_volume*/) const {
353 ASSERT(false);
354 return 0;
355}
356
357int32_t FakeAudioCaptureModule::MinSpeakerVolume(
358 uint32_t* /*min_volume*/) const {
359 ASSERT(false);
360 return 0;
361}
362
363int32_t FakeAudioCaptureModule::SpeakerVolumeStepSize(
364 uint16_t* /*step_size*/) const {
365 ASSERT(false);
366 return 0;
367}
368
369int32_t FakeAudioCaptureModule::MicrophoneVolumeIsAvailable(
370 bool* /*available*/) {
371 ASSERT(false);
372 return 0;
373}
374
wu@webrtc.org8804a292013-10-22 23:09:20 +0000375int32_t FakeAudioCaptureModule::SetMicrophoneVolume(uint32_t volume) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000376 rtc::CritScope cs(&crit_);
wu@webrtc.org8804a292013-10-22 23:09:20 +0000377 current_mic_level_ = volume;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000378 return 0;
379}
380
381int32_t FakeAudioCaptureModule::MicrophoneVolume(uint32_t* volume) const {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000382 rtc::CritScope cs(&crit_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000383 *volume = current_mic_level_;
384 return 0;
385}
386
387int32_t FakeAudioCaptureModule::MaxMicrophoneVolume(
388 uint32_t* max_volume) const {
389 *max_volume = kMaxVolume;
390 return 0;
391}
392
393int32_t FakeAudioCaptureModule::MinMicrophoneVolume(
394 uint32_t* /*min_volume*/) const {
395 ASSERT(false);
396 return 0;
397}
398
399int32_t FakeAudioCaptureModule::MicrophoneVolumeStepSize(
400 uint16_t* /*step_size*/) const {
401 ASSERT(false);
402 return 0;
403}
404
405int32_t FakeAudioCaptureModule::SpeakerMuteIsAvailable(bool* /*available*/) {
406 ASSERT(false);
407 return 0;
408}
409
410int32_t FakeAudioCaptureModule::SetSpeakerMute(bool /*enable*/) {
411 ASSERT(false);
412 return 0;
413}
414
415int32_t FakeAudioCaptureModule::SpeakerMute(bool* /*enabled*/) const {
416 ASSERT(false);
417 return 0;
418}
419
420int32_t FakeAudioCaptureModule::MicrophoneMuteIsAvailable(bool* /*available*/) {
421 ASSERT(false);
422 return 0;
423}
424
425int32_t FakeAudioCaptureModule::SetMicrophoneMute(bool /*enable*/) {
426 ASSERT(false);
427 return 0;
428}
429
430int32_t FakeAudioCaptureModule::MicrophoneMute(bool* /*enabled*/) const {
431 ASSERT(false);
432 return 0;
433}
434
435int32_t FakeAudioCaptureModule::MicrophoneBoostIsAvailable(
436 bool* /*available*/) {
437 ASSERT(false);
438 return 0;
439}
440
441int32_t FakeAudioCaptureModule::SetMicrophoneBoost(bool /*enable*/) {
442 ASSERT(false);
443 return 0;
444}
445
446int32_t FakeAudioCaptureModule::MicrophoneBoost(bool* /*enabled*/) const {
447 ASSERT(false);
448 return 0;
449}
450
451int32_t FakeAudioCaptureModule::StereoPlayoutIsAvailable(
452 bool* available) const {
453 // No recording device, just dropping audio. Stereo can be dropped just
454 // as easily as mono.
455 *available = true;
456 return 0;
457}
458
459int32_t FakeAudioCaptureModule::SetStereoPlayout(bool /*enable*/) {
460 // No recording device, just dropping audio. Stereo can be dropped just
461 // as easily as mono.
462 return 0;
463}
464
465int32_t FakeAudioCaptureModule::StereoPlayout(bool* /*enabled*/) const {
466 ASSERT(false);
467 return 0;
468}
469
470int32_t FakeAudioCaptureModule::StereoRecordingIsAvailable(
471 bool* available) const {
472 // Keep thing simple. No stereo recording.
473 *available = false;
474 return 0;
475}
476
477int32_t FakeAudioCaptureModule::SetStereoRecording(bool enable) {
478 if (!enable) {
479 return 0;
480 }
481 return -1;
482}
483
484int32_t FakeAudioCaptureModule::StereoRecording(bool* /*enabled*/) const {
485 ASSERT(false);
486 return 0;
487}
488
489int32_t FakeAudioCaptureModule::SetRecordingChannel(
490 const ChannelType channel) {
491 if (channel != AudioDeviceModule::kChannelBoth) {
492 // There is no right or left in mono. I.e. kChannelBoth should be used for
493 // mono.
494 ASSERT(false);
495 return -1;
496 }
497 return 0;
498}
499
500int32_t FakeAudioCaptureModule::RecordingChannel(ChannelType* channel) const {
501 // Stereo recording not supported. However, WebRTC ADM returns kChannelBoth
502 // in that case. Do the same here.
503 *channel = AudioDeviceModule::kChannelBoth;
504 return 0;
505}
506
507int32_t FakeAudioCaptureModule::SetPlayoutBuffer(const BufferType /*type*/,
508 uint16_t /*size_ms*/) {
509 ASSERT(false);
510 return 0;
511}
512
513int32_t FakeAudioCaptureModule::PlayoutBuffer(BufferType* /*type*/,
514 uint16_t* /*size_ms*/) const {
515 ASSERT(false);
516 return 0;
517}
518
519int32_t FakeAudioCaptureModule::PlayoutDelay(uint16_t* delay_ms) const {
520 // No delay since audio frames are dropped.
521 *delay_ms = 0;
522 return 0;
523}
524
525int32_t FakeAudioCaptureModule::RecordingDelay(uint16_t* /*delay_ms*/) const {
526 ASSERT(false);
527 return 0;
528}
529
530int32_t FakeAudioCaptureModule::CPULoad(uint16_t* /*load*/) const {
531 ASSERT(false);
532 return 0;
533}
534
535int32_t FakeAudioCaptureModule::StartRawOutputFileRecording(
536 const char /*pcm_file_name_utf8*/[webrtc::kAdmMaxFileNameSize]) {
537 ASSERT(false);
538 return 0;
539}
540
541int32_t FakeAudioCaptureModule::StopRawOutputFileRecording() {
542 ASSERT(false);
543 return 0;
544}
545
546int32_t FakeAudioCaptureModule::StartRawInputFileRecording(
547 const char /*pcm_file_name_utf8*/[webrtc::kAdmMaxFileNameSize]) {
548 ASSERT(false);
549 return 0;
550}
551
552int32_t FakeAudioCaptureModule::StopRawInputFileRecording() {
553 ASSERT(false);
554 return 0;
555}
556
557int32_t FakeAudioCaptureModule::SetRecordingSampleRate(
558 const uint32_t /*samples_per_sec*/) {
559 ASSERT(false);
560 return 0;
561}
562
563int32_t FakeAudioCaptureModule::RecordingSampleRate(
564 uint32_t* /*samples_per_sec*/) const {
565 ASSERT(false);
566 return 0;
567}
568
569int32_t FakeAudioCaptureModule::SetPlayoutSampleRate(
570 const uint32_t /*samples_per_sec*/) {
571 ASSERT(false);
572 return 0;
573}
574
575int32_t FakeAudioCaptureModule::PlayoutSampleRate(
576 uint32_t* /*samples_per_sec*/) const {
577 ASSERT(false);
578 return 0;
579}
580
581int32_t FakeAudioCaptureModule::ResetAudioDevice() {
582 ASSERT(false);
583 return 0;
584}
585
586int32_t FakeAudioCaptureModule::SetLoudspeakerStatus(bool /*enable*/) {
587 ASSERT(false);
588 return 0;
589}
590
591int32_t FakeAudioCaptureModule::GetLoudspeakerStatus(bool* /*enabled*/) const {
592 ASSERT(false);
593 return 0;
594}
595
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000596void FakeAudioCaptureModule::OnMessage(rtc::Message* msg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000597 switch (msg->message_id) {
wu@webrtc.org8804a292013-10-22 23:09:20 +0000598 case MSG_START_PROCESS:
599 StartProcessP();
600 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000601 case MSG_RUN_PROCESS:
602 ProcessFrameP();
603 break;
604 case MSG_STOP_PROCESS:
605 StopProcessP();
606 break;
607 default:
608 // All existing messages should be caught. Getting here should never
609 // happen.
610 ASSERT(false);
611 }
612}
613
614bool FakeAudioCaptureModule::Initialize() {
615 // Set the send buffer samples high enough that it would not occur on the
616 // remote side unless a packet containing a sample of that magnitude has been
617 // sent to it. Note that the audio processing pipeline will likely distort the
618 // original signal.
619 SetSendBuffer(kHighSampleValue);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000620 last_process_time_ms_ = rtc::Time();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000621 return true;
622}
623
624void FakeAudioCaptureModule::SetSendBuffer(int value) {
625 Sample* buffer_ptr = reinterpret_cast<Sample*>(send_buffer_);
Peter Kasting728d9032015-06-11 14:31:38 -0700626 const int buffer_size_in_samples =
627 sizeof(send_buffer_) / kNumberBytesPerSample;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000628 for (int i = 0; i < buffer_size_in_samples; ++i) {
629 buffer_ptr[i] = value;
630 }
631}
632
633void FakeAudioCaptureModule::ResetRecBuffer() {
634 memset(rec_buffer_, 0, sizeof(rec_buffer_));
635}
636
637bool FakeAudioCaptureModule::CheckRecBuffer(int value) {
638 const Sample* buffer_ptr = reinterpret_cast<const Sample*>(rec_buffer_);
Peter Kasting728d9032015-06-11 14:31:38 -0700639 const int buffer_size_in_samples =
640 sizeof(rec_buffer_) / kNumberBytesPerSample;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000641 for (int i = 0; i < buffer_size_in_samples; ++i) {
642 if (buffer_ptr[i] >= value) return true;
643 }
644 return false;
645}
646
wu@webrtc.org8804a292013-10-22 23:09:20 +0000647bool FakeAudioCaptureModule::ShouldStartProcessing() {
648 return recording_ || playing_;
649}
650
651void FakeAudioCaptureModule::UpdateProcessing(bool start) {
652 if (start) {
653 process_thread_->Post(this, MSG_START_PROCESS);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000654 } else {
655 process_thread_->Send(this, MSG_STOP_PROCESS);
656 }
657}
658
wu@webrtc.org8804a292013-10-22 23:09:20 +0000659void FakeAudioCaptureModule::StartProcessP() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000660 ASSERT(rtc::Thread::Current() == process_thread_);
wu@webrtc.org8804a292013-10-22 23:09:20 +0000661 if (started_) {
662 // Already started.
663 return;
664 }
665 ProcessFrameP();
666}
667
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000668void FakeAudioCaptureModule::ProcessFrameP() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000669 ASSERT(rtc::Thread::Current() == process_thread_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000670 if (!started_) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000671 next_frame_time_ = rtc::Time();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000672 started_ = true;
673 }
wu@webrtc.org8804a292013-10-22 23:09:20 +0000674
675 bool playing;
676 bool recording;
677 {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000678 rtc::CritScope cs(&crit_);
wu@webrtc.org8804a292013-10-22 23:09:20 +0000679 playing = playing_;
680 recording = recording_;
681 }
682
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000683 // Receive and send frames every kTimePerFrameMs.
wu@webrtc.org8804a292013-10-22 23:09:20 +0000684 if (playing) {
685 ReceiveFrameP();
686 }
687 if (recording) {
688 SendFrameP();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000689 }
690
691 next_frame_time_ += kTimePerFrameMs;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000692 const uint32 current_time = rtc::Time();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000693 const uint32 wait_time = (next_frame_time_ > current_time) ?
694 next_frame_time_ - current_time : 0;
695 process_thread_->PostDelayed(wait_time, this, MSG_RUN_PROCESS);
696}
697
698void FakeAudioCaptureModule::ReceiveFrameP() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000699 ASSERT(rtc::Thread::Current() == process_thread_);
wu@webrtc.org8804a292013-10-22 23:09:20 +0000700 {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000701 rtc::CritScope cs(&crit_callback_);
wu@webrtc.org8804a292013-10-22 23:09:20 +0000702 if (!audio_callback_) {
703 return;
704 }
705 ResetRecBuffer();
706 uint32_t nSamplesOut = 0;
wu@webrtc.org94454b72014-06-05 20:34:08 +0000707 int64_t elapsed_time_ms = 0;
wu@webrtc.orgcb711f72014-05-19 17:39:11 +0000708 int64_t ntp_time_ms = 0;
709 if (audio_callback_->NeedMorePlayData(kNumberSamples, kNumberBytesPerSample,
710 kNumberOfChannels, kSamplesPerSecond,
711 rec_buffer_, nSamplesOut,
wu@webrtc.org94454b72014-06-05 20:34:08 +0000712 &elapsed_time_ms, &ntp_time_ms) != 0) {
wu@webrtc.org8804a292013-10-22 23:09:20 +0000713 ASSERT(false);
714 }
715 ASSERT(nSamplesOut == kNumberSamples);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000716 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000717 // The SetBuffer() function ensures that after decoding, the audio buffer
718 // should contain samples of similar magnitude (there is likely to be some
719 // distortion due to the audio pipeline). If one sample is detected to
720 // have the same or greater magnitude somewhere in the frame, an actual frame
721 // has been received from the remote side (i.e. faked frames are not being
722 // pulled).
wu@webrtc.org8804a292013-10-22 23:09:20 +0000723 if (CheckRecBuffer(kHighSampleValue)) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000724 rtc::CritScope cs(&crit_);
wu@webrtc.org8804a292013-10-22 23:09:20 +0000725 ++frames_received_;
726 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000727}
728
729void FakeAudioCaptureModule::SendFrameP() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000730 ASSERT(rtc::Thread::Current() == process_thread_);
731 rtc::CritScope cs(&crit_callback_);
wu@webrtc.org8804a292013-10-22 23:09:20 +0000732 if (!audio_callback_) {
733 return;
734 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000735 bool key_pressed = false;
wu@webrtc.org8804a292013-10-22 23:09:20 +0000736 uint32_t current_mic_level = 0;
737 MicrophoneVolume(&current_mic_level);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000738 if (audio_callback_->RecordedDataIsAvailable(send_buffer_, kNumberSamples,
739 kNumberBytesPerSample,
740 kNumberOfChannels,
741 kSamplesPerSecond, kTotalDelayMs,
wu@webrtc.org8804a292013-10-22 23:09:20 +0000742 kClockDriftMs, current_mic_level,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000743 key_pressed,
wu@webrtc.org8804a292013-10-22 23:09:20 +0000744 current_mic_level) != 0) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000745 ASSERT(false);
746 }
wu@webrtc.org8804a292013-10-22 23:09:20 +0000747 SetMicrophoneVolume(current_mic_level);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000748}
749
750void FakeAudioCaptureModule::StopProcessP() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000751 ASSERT(rtc::Thread::Current() == process_thread_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000752 started_ = false;
753 process_thread_->Clear(this);
754}