blob: 0d367cb9c5e73ad2705bc394409b0ebf9fe47485 [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
ossu7bb87ee2017-01-23 04:56:25 -080011#include "webrtc/pc/test/fakeaudiocapturemodule.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000012
Edward Lemurc20978e2017-07-06 19:44:34 +020013#include "webrtc/rtc_base/checks.h"
14#include "webrtc/rtc_base/refcount.h"
15#include "webrtc/rtc_base/thread.h"
16#include "webrtc/rtc_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/
Honghai Zhang82d78622016-05-06 11:29:15 -070026static const int 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() {
Honghai Zhang82d78622016-05-06 11:29:15 -070076 const int64_t current_time = rtc::TimeMillis();
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 }
Honghai Zhang82d78622016-05-06 11:29:15 -070081 const int64_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() {
Honghai Zhang82d78622016-05-06 11:29:15 -070089 last_process_time_ms_ = rtc::TimeMillis();
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 {
nissec80e7412017-01-11 05:56:46 -080094 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +000095 return 0;
96}
97
98webrtc::AudioDeviceModule::ErrorCode FakeAudioCaptureModule::LastError() const {
nissec80e7412017-01-11 05:56:46 -080099 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000100 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 {
nissec80e7412017-01-11 05:56:46 -0800128 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000129 return 0;
130}
131
132int16_t FakeAudioCaptureModule::PlayoutDevices() {
nissec80e7412017-01-11 05:56:46 -0800133 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000134 return 0;
135}
136
137int16_t FakeAudioCaptureModule::RecordingDevices() {
nissec80e7412017-01-11 05:56:46 -0800138 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000139 return 0;
140}
141
142int32_t FakeAudioCaptureModule::PlayoutDeviceName(
143 uint16_t /*index*/,
144 char /*name*/[webrtc::kAdmMaxDeviceNameSize],
145 char /*guid*/[webrtc::kAdmMaxGuidSize]) {
nissec80e7412017-01-11 05:56:46 -0800146 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000147 return 0;
148}
149
150int32_t FakeAudioCaptureModule::RecordingDeviceName(
151 uint16_t /*index*/,
152 char /*name*/[webrtc::kAdmMaxDeviceNameSize],
153 char /*guid*/[webrtc::kAdmMaxGuidSize]) {
nissec80e7412017-01-11 05:56:46 -0800154 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000155 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*/) {
nissec80e7412017-01-11 05:56:46 -0800184 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000185 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*/) {
nissec80e7412017-01-11 05:56:46 -0800198 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000199 return 0;
200}
201
202int32_t FakeAudioCaptureModule::InitRecording() {
203 rec_is_initialized_ = true;
204 return 0;
205}
206
207bool FakeAudioCaptureModule::RecordingIsInitialized() const {
solenbergd53a3f92016-04-14 13:56:37 -0700208 return rec_is_initialized_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000209}
210
211int32_t FakeAudioCaptureModule::StartPlayout() {
212 if (!play_is_initialized_) {
213 return -1;
214 }
wu@webrtc.org8804a292013-10-22 23:09:20 +0000215 {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000216 rtc::CritScope cs(&crit_);
wu@webrtc.org8804a292013-10-22 23:09:20 +0000217 playing_ = true;
218 }
219 bool start = true;
220 UpdateProcessing(start);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000221 return 0;
222}
223
224int32_t FakeAudioCaptureModule::StopPlayout() {
wu@webrtc.org8804a292013-10-22 23:09:20 +0000225 bool start = false;
226 {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000227 rtc::CritScope cs(&crit_);
wu@webrtc.org8804a292013-10-22 23:09:20 +0000228 playing_ = false;
229 start = ShouldStartProcessing();
230 }
231 UpdateProcessing(start);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000232 return 0;
233}
234
235bool FakeAudioCaptureModule::Playing() const {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000236 rtc::CritScope cs(&crit_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000237 return playing_;
238}
239
240int32_t FakeAudioCaptureModule::StartRecording() {
241 if (!rec_is_initialized_) {
242 return -1;
243 }
wu@webrtc.org8804a292013-10-22 23:09:20 +0000244 {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000245 rtc::CritScope cs(&crit_);
wu@webrtc.org8804a292013-10-22 23:09:20 +0000246 recording_ = true;
247 }
248 bool start = true;
249 UpdateProcessing(start);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000250 return 0;
251}
252
253int32_t FakeAudioCaptureModule::StopRecording() {
wu@webrtc.org8804a292013-10-22 23:09:20 +0000254 bool start = false;
255 {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000256 rtc::CritScope cs(&crit_);
wu@webrtc.org8804a292013-10-22 23:09:20 +0000257 recording_ = false;
258 start = ShouldStartProcessing();
259 }
260 UpdateProcessing(start);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000261 return 0;
262}
263
264bool FakeAudioCaptureModule::Recording() const {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000265 rtc::CritScope cs(&crit_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000266 return recording_;
267}
268
269int32_t FakeAudioCaptureModule::SetAGC(bool /*enable*/) {
270 // No AGC but not needed since audio is pregenerated. Return success.
271 return 0;
272}
273
274bool FakeAudioCaptureModule::AGC() const {
nissec80e7412017-01-11 05:56:46 -0800275 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000276 return 0;
277}
278
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000279int32_t FakeAudioCaptureModule::InitSpeaker() {
280 // No speaker, just playing from file. Return success.
281 return 0;
282}
283
284bool FakeAudioCaptureModule::SpeakerIsInitialized() const {
nissec80e7412017-01-11 05:56:46 -0800285 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000286 return 0;
287}
288
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000289int32_t FakeAudioCaptureModule::InitMicrophone() {
290 // No microphone, just playing from file. Return success.
291 return 0;
292}
293
294bool FakeAudioCaptureModule::MicrophoneIsInitialized() const {
nissec80e7412017-01-11 05:56:46 -0800295 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000296 return 0;
297}
298
299int32_t FakeAudioCaptureModule::SpeakerVolumeIsAvailable(bool* /*available*/) {
nissec80e7412017-01-11 05:56:46 -0800300 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000301 return 0;
302}
303
304int32_t FakeAudioCaptureModule::SetSpeakerVolume(uint32_t /*volume*/) {
nissec80e7412017-01-11 05:56:46 -0800305 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000306 return 0;
307}
308
309int32_t FakeAudioCaptureModule::SpeakerVolume(uint32_t* /*volume*/) const {
nissec80e7412017-01-11 05:56:46 -0800310 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000311 return 0;
312}
313
314int32_t FakeAudioCaptureModule::MaxSpeakerVolume(
315 uint32_t* /*max_volume*/) const {
nissec80e7412017-01-11 05:56:46 -0800316 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000317 return 0;
318}
319
320int32_t FakeAudioCaptureModule::MinSpeakerVolume(
321 uint32_t* /*min_volume*/) const {
nissec80e7412017-01-11 05:56:46 -0800322 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000323 return 0;
324}
325
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000326int32_t FakeAudioCaptureModule::MicrophoneVolumeIsAvailable(
327 bool* /*available*/) {
nissec80e7412017-01-11 05:56:46 -0800328 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000329 return 0;
330}
331
wu@webrtc.org8804a292013-10-22 23:09:20 +0000332int32_t FakeAudioCaptureModule::SetMicrophoneVolume(uint32_t volume) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000333 rtc::CritScope cs(&crit_);
wu@webrtc.org8804a292013-10-22 23:09:20 +0000334 current_mic_level_ = volume;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000335 return 0;
336}
337
338int32_t FakeAudioCaptureModule::MicrophoneVolume(uint32_t* volume) const {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000339 rtc::CritScope cs(&crit_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000340 *volume = current_mic_level_;
341 return 0;
342}
343
344int32_t FakeAudioCaptureModule::MaxMicrophoneVolume(
345 uint32_t* max_volume) const {
346 *max_volume = kMaxVolume;
347 return 0;
348}
349
350int32_t FakeAudioCaptureModule::MinMicrophoneVolume(
351 uint32_t* /*min_volume*/) const {
nissec80e7412017-01-11 05:56:46 -0800352 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000353 return 0;
354}
355
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000356int32_t FakeAudioCaptureModule::SpeakerMuteIsAvailable(bool* /*available*/) {
nissec80e7412017-01-11 05:56:46 -0800357 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000358 return 0;
359}
360
361int32_t FakeAudioCaptureModule::SetSpeakerMute(bool /*enable*/) {
nissec80e7412017-01-11 05:56:46 -0800362 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000363 return 0;
364}
365
366int32_t FakeAudioCaptureModule::SpeakerMute(bool* /*enabled*/) const {
nissec80e7412017-01-11 05:56:46 -0800367 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000368 return 0;
369}
370
371int32_t FakeAudioCaptureModule::MicrophoneMuteIsAvailable(bool* /*available*/) {
nissec80e7412017-01-11 05:56:46 -0800372 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000373 return 0;
374}
375
376int32_t FakeAudioCaptureModule::SetMicrophoneMute(bool /*enable*/) {
nissec80e7412017-01-11 05:56:46 -0800377 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000378 return 0;
379}
380
381int32_t FakeAudioCaptureModule::MicrophoneMute(bool* /*enabled*/) const {
nissec80e7412017-01-11 05:56:46 -0800382 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000383 return 0;
384}
385
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000386int32_t FakeAudioCaptureModule::StereoPlayoutIsAvailable(
387 bool* available) const {
388 // No recording device, just dropping audio. Stereo can be dropped just
389 // as easily as mono.
390 *available = true;
391 return 0;
392}
393
394int32_t FakeAudioCaptureModule::SetStereoPlayout(bool /*enable*/) {
395 // No recording device, just dropping audio. Stereo can be dropped just
396 // as easily as mono.
397 return 0;
398}
399
400int32_t FakeAudioCaptureModule::StereoPlayout(bool* /*enabled*/) const {
nissec80e7412017-01-11 05:56:46 -0800401 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000402 return 0;
403}
404
405int32_t FakeAudioCaptureModule::StereoRecordingIsAvailable(
406 bool* available) const {
407 // Keep thing simple. No stereo recording.
408 *available = false;
409 return 0;
410}
411
412int32_t FakeAudioCaptureModule::SetStereoRecording(bool enable) {
413 if (!enable) {
414 return 0;
415 }
416 return -1;
417}
418
419int32_t FakeAudioCaptureModule::StereoRecording(bool* /*enabled*/) const {
nissec80e7412017-01-11 05:56:46 -0800420 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000421 return 0;
422}
423
424int32_t FakeAudioCaptureModule::SetRecordingChannel(
425 const ChannelType channel) {
426 if (channel != AudioDeviceModule::kChannelBoth) {
427 // There is no right or left in mono. I.e. kChannelBoth should be used for
428 // mono.
nissec80e7412017-01-11 05:56:46 -0800429 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000430 return -1;
431 }
432 return 0;
433}
434
435int32_t FakeAudioCaptureModule::RecordingChannel(ChannelType* channel) const {
436 // Stereo recording not supported. However, WebRTC ADM returns kChannelBoth
437 // in that case. Do the same here.
438 *channel = AudioDeviceModule::kChannelBoth;
439 return 0;
440}
441
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000442int32_t FakeAudioCaptureModule::PlayoutDelay(uint16_t* delay_ms) const {
443 // No delay since audio frames are dropped.
444 *delay_ms = 0;
445 return 0;
446}
447
448int32_t FakeAudioCaptureModule::RecordingDelay(uint16_t* /*delay_ms*/) const {
nissec80e7412017-01-11 05:56:46 -0800449 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000450 return 0;
451}
452
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000453int32_t FakeAudioCaptureModule::SetRecordingSampleRate(
454 const uint32_t /*samples_per_sec*/) {
nissec80e7412017-01-11 05:56:46 -0800455 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000456 return 0;
457}
458
459int32_t FakeAudioCaptureModule::RecordingSampleRate(
460 uint32_t* /*samples_per_sec*/) const {
nissec80e7412017-01-11 05:56:46 -0800461 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000462 return 0;
463}
464
465int32_t FakeAudioCaptureModule::SetPlayoutSampleRate(
466 const uint32_t /*samples_per_sec*/) {
nissec80e7412017-01-11 05:56:46 -0800467 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000468 return 0;
469}
470
471int32_t FakeAudioCaptureModule::PlayoutSampleRate(
472 uint32_t* /*samples_per_sec*/) const {
nissec80e7412017-01-11 05:56:46 -0800473 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000474 return 0;
475}
476
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000477int32_t FakeAudioCaptureModule::SetLoudspeakerStatus(bool /*enable*/) {
nissec80e7412017-01-11 05:56:46 -0800478 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000479 return 0;
480}
481
482int32_t FakeAudioCaptureModule::GetLoudspeakerStatus(bool* /*enabled*/) const {
nissec80e7412017-01-11 05:56:46 -0800483 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000484 return 0;
485}
486
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000487void FakeAudioCaptureModule::OnMessage(rtc::Message* msg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000488 switch (msg->message_id) {
wu@webrtc.org8804a292013-10-22 23:09:20 +0000489 case MSG_START_PROCESS:
490 StartProcessP();
491 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000492 case MSG_RUN_PROCESS:
493 ProcessFrameP();
494 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000495 default:
496 // All existing messages should be caught. Getting here should never
497 // happen.
nissec80e7412017-01-11 05:56:46 -0800498 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000499 }
500}
501
502bool FakeAudioCaptureModule::Initialize() {
503 // Set the send buffer samples high enough that it would not occur on the
504 // remote side unless a packet containing a sample of that magnitude has been
505 // sent to it. Note that the audio processing pipeline will likely distort the
506 // original signal.
507 SetSendBuffer(kHighSampleValue);
Honghai Zhang82d78622016-05-06 11:29:15 -0700508 last_process_time_ms_ = rtc::TimeMillis();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000509 return true;
510}
511
512void FakeAudioCaptureModule::SetSendBuffer(int value) {
513 Sample* buffer_ptr = reinterpret_cast<Sample*>(send_buffer_);
Peter Kastingdce40cf2015-08-24 14:52:23 -0700514 const size_t buffer_size_in_samples =
Peter Kasting728d9032015-06-11 14:31:38 -0700515 sizeof(send_buffer_) / kNumberBytesPerSample;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700516 for (size_t i = 0; i < buffer_size_in_samples; ++i) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000517 buffer_ptr[i] = value;
518 }
519}
520
521void FakeAudioCaptureModule::ResetRecBuffer() {
522 memset(rec_buffer_, 0, sizeof(rec_buffer_));
523}
524
525bool FakeAudioCaptureModule::CheckRecBuffer(int value) {
526 const Sample* buffer_ptr = reinterpret_cast<const Sample*>(rec_buffer_);
Peter Kastingdce40cf2015-08-24 14:52:23 -0700527 const size_t buffer_size_in_samples =
Peter Kasting728d9032015-06-11 14:31:38 -0700528 sizeof(rec_buffer_) / kNumberBytesPerSample;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700529 for (size_t i = 0; i < buffer_size_in_samples; ++i) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000530 if (buffer_ptr[i] >= value) return true;
531 }
532 return false;
533}
534
wu@webrtc.org8804a292013-10-22 23:09:20 +0000535bool FakeAudioCaptureModule::ShouldStartProcessing() {
536 return recording_ || playing_;
537}
538
539void FakeAudioCaptureModule::UpdateProcessing(bool start) {
540 if (start) {
deadbeefee8c6d32015-08-13 14:27:18 -0700541 if (!process_thread_) {
tommie7251592017-07-14 14:44:46 -0700542 process_thread_ = rtc::Thread::Create();
deadbeefee8c6d32015-08-13 14:27:18 -0700543 process_thread_->Start();
544 }
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700545 process_thread_->Post(RTC_FROM_HERE, this, MSG_START_PROCESS);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000546 } else {
deadbeefee8c6d32015-08-13 14:27:18 -0700547 if (process_thread_) {
548 process_thread_->Stop();
549 process_thread_.reset(nullptr);
550 }
551 started_ = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000552 }
553}
554
wu@webrtc.org8804a292013-10-22 23:09:20 +0000555void FakeAudioCaptureModule::StartProcessP() {
nissec8ee8822017-01-18 07:20:55 -0800556 RTC_CHECK(process_thread_->IsCurrent());
wu@webrtc.org8804a292013-10-22 23:09:20 +0000557 if (started_) {
558 // Already started.
559 return;
560 }
561 ProcessFrameP();
562}
563
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000564void FakeAudioCaptureModule::ProcessFrameP() {
nissec8ee8822017-01-18 07:20:55 -0800565 RTC_CHECK(process_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000566 if (!started_) {
Honghai Zhang82d78622016-05-06 11:29:15 -0700567 next_frame_time_ = rtc::TimeMillis();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000568 started_ = true;
569 }
wu@webrtc.org8804a292013-10-22 23:09:20 +0000570
wu@webrtc.org8804a292013-10-22 23:09:20 +0000571 {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000572 rtc::CritScope cs(&crit_);
deadbeefee8c6d32015-08-13 14:27:18 -0700573 // Receive and send frames every kTimePerFrameMs.
574 if (playing_) {
575 ReceiveFrameP();
576 }
577 if (recording_) {
578 SendFrameP();
579 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000580 }
581
582 next_frame_time_ += kTimePerFrameMs;
Honghai Zhang82d78622016-05-06 11:29:15 -0700583 const int64_t current_time = rtc::TimeMillis();
584 const int64_t wait_time =
Peter Boström0c4e06b2015-10-07 12:23:21 +0200585 (next_frame_time_ > current_time) ? next_frame_time_ - current_time : 0;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700586 process_thread_->PostDelayed(RTC_FROM_HERE, wait_time, this, MSG_RUN_PROCESS);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000587}
588
589void FakeAudioCaptureModule::ReceiveFrameP() {
nissec8ee8822017-01-18 07:20:55 -0800590 RTC_CHECK(process_thread_->IsCurrent());
wu@webrtc.org8804a292013-10-22 23:09:20 +0000591 {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000592 rtc::CritScope cs(&crit_callback_);
wu@webrtc.org8804a292013-10-22 23:09:20 +0000593 if (!audio_callback_) {
594 return;
595 }
596 ResetRecBuffer();
Peter Kastingdce40cf2015-08-24 14:52:23 -0700597 size_t nSamplesOut = 0;
wu@webrtc.org94454b72014-06-05 20:34:08 +0000598 int64_t elapsed_time_ms = 0;
wu@webrtc.orgcb711f72014-05-19 17:39:11 +0000599 int64_t ntp_time_ms = 0;
600 if (audio_callback_->NeedMorePlayData(kNumberSamples, kNumberBytesPerSample,
601 kNumberOfChannels, kSamplesPerSecond,
602 rec_buffer_, nSamplesOut,
wu@webrtc.org94454b72014-06-05 20:34:08 +0000603 &elapsed_time_ms, &ntp_time_ms) != 0) {
nissec80e7412017-01-11 05:56:46 -0800604 RTC_NOTREACHED();
wu@webrtc.org8804a292013-10-22 23:09:20 +0000605 }
nissec8ee8822017-01-18 07:20:55 -0800606 RTC_CHECK(nSamplesOut == kNumberSamples);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000607 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000608 // The SetBuffer() function ensures that after decoding, the audio buffer
609 // should contain samples of similar magnitude (there is likely to be some
610 // distortion due to the audio pipeline). If one sample is detected to
611 // have the same or greater magnitude somewhere in the frame, an actual frame
612 // has been received from the remote side (i.e. faked frames are not being
613 // pulled).
wu@webrtc.org8804a292013-10-22 23:09:20 +0000614 if (CheckRecBuffer(kHighSampleValue)) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000615 rtc::CritScope cs(&crit_);
wu@webrtc.org8804a292013-10-22 23:09:20 +0000616 ++frames_received_;
617 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000618}
619
620void FakeAudioCaptureModule::SendFrameP() {
nissec8ee8822017-01-18 07:20:55 -0800621 RTC_CHECK(process_thread_->IsCurrent());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000622 rtc::CritScope cs(&crit_callback_);
wu@webrtc.org8804a292013-10-22 23:09:20 +0000623 if (!audio_callback_) {
624 return;
625 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000626 bool key_pressed = false;
wu@webrtc.org8804a292013-10-22 23:09:20 +0000627 uint32_t current_mic_level = 0;
628 MicrophoneVolume(&current_mic_level);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000629 if (audio_callback_->RecordedDataIsAvailable(send_buffer_, kNumberSamples,
630 kNumberBytesPerSample,
631 kNumberOfChannels,
632 kSamplesPerSecond, kTotalDelayMs,
wu@webrtc.org8804a292013-10-22 23:09:20 +0000633 kClockDriftMs, current_mic_level,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000634 key_pressed,
wu@webrtc.org8804a292013-10-22 23:09:20 +0000635 current_mic_level) != 0) {
nissec80e7412017-01-11 05:56:46 -0800636 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000637 }
wu@webrtc.org8804a292013-10-22 23:09:20 +0000638 SetMicrophoneVolume(current_mic_level);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000639}