blob: 3b36163240b7a88b06793cad16893d08631ca342 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
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 "talk/base/common.h"
31#include "talk/base/refcount.h"
32#include "talk/base/thread.h"
33#include "talk/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.
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;
48static const int kNumberOfChannels = 1;
49static 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(
61 talk_base::Thread* process_thread)
62 : 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
80talk_base::scoped_refptr<FakeAudioCaptureModule> FakeAudioCaptureModule::Create(
81 talk_base::Thread* process_thread) {
82 if (process_thread == NULL) return NULL;
83
84 talk_base::scoped_refptr<FakeAudioCaptureModule> capture_module(
85 new talk_base::RefCountedObject<FakeAudioCaptureModule>(process_thread));
86 if (!capture_module->Initialize()) {
87 return NULL;
88 }
89 return capture_module;
90}
91
92int FakeAudioCaptureModule::frames_received() const {
wu@webrtc.org8804a292013-10-22 23:09:20 +000093 talk_base::CritScope cs(&crit_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000094 return frames_received_;
95}
96
97int32_t FakeAudioCaptureModule::Version(char* /*version*/,
98 uint32_t& /*remaining_buffer_in_bytes*/,
99 uint32_t& /*position*/) const {
100 ASSERT(false);
101 return 0;
102}
103
104int32_t FakeAudioCaptureModule::TimeUntilNextProcess() {
105 const uint32 current_time = talk_base::Time();
106 if (current_time < last_process_time_ms_) {
107 // TODO: wraparound could be handled more gracefully.
108 return 0;
109 }
110 const uint32 elapsed_time = current_time - last_process_time_ms_;
111 if (kAdmMaxIdleTimeProcess < elapsed_time) {
112 return 0;
113 }
114 return kAdmMaxIdleTimeProcess - elapsed_time;
115}
116
117int32_t FakeAudioCaptureModule::Process() {
118 last_process_time_ms_ = talk_base::Time();
119 return 0;
120}
121
122int32_t FakeAudioCaptureModule::ChangeUniqueId(const int32_t /*id*/) {
123 ASSERT(false);
124 return 0;
125}
126
127int32_t FakeAudioCaptureModule::ActiveAudioLayer(
128 AudioLayer* /*audio_layer*/) const {
129 ASSERT(false);
130 return 0;
131}
132
133webrtc::AudioDeviceModule::ErrorCode FakeAudioCaptureModule::LastError() const {
134 ASSERT(false);
135 return webrtc::AudioDeviceModule::kAdmErrNone;
136}
137
138int32_t FakeAudioCaptureModule::RegisterEventObserver(
139 webrtc::AudioDeviceObserver* /*event_callback*/) {
140 // Only used to report warnings and errors. This fake implementation won't
141 // generate any so discard this callback.
142 return 0;
143}
144
145int32_t FakeAudioCaptureModule::RegisterAudioCallback(
146 webrtc::AudioTransport* audio_callback) {
wu@webrtc.org8804a292013-10-22 23:09:20 +0000147 talk_base::CritScope cs(&crit_callback_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000148 audio_callback_ = audio_callback;
149 return 0;
150}
151
152int32_t FakeAudioCaptureModule::Init() {
153 // Initialize is called by the factory method. Safe to ignore this Init call.
154 return 0;
155}
156
157int32_t FakeAudioCaptureModule::Terminate() {
158 // Clean up in the destructor. No action here, just success.
159 return 0;
160}
161
162bool FakeAudioCaptureModule::Initialized() const {
163 ASSERT(false);
164 return 0;
165}
166
167int16_t FakeAudioCaptureModule::PlayoutDevices() {
168 ASSERT(false);
169 return 0;
170}
171
172int16_t FakeAudioCaptureModule::RecordingDevices() {
173 ASSERT(false);
174 return 0;
175}
176
177int32_t FakeAudioCaptureModule::PlayoutDeviceName(
178 uint16_t /*index*/,
179 char /*name*/[webrtc::kAdmMaxDeviceNameSize],
180 char /*guid*/[webrtc::kAdmMaxGuidSize]) {
181 ASSERT(false);
182 return 0;
183}
184
185int32_t FakeAudioCaptureModule::RecordingDeviceName(
186 uint16_t /*index*/,
187 char /*name*/[webrtc::kAdmMaxDeviceNameSize],
188 char /*guid*/[webrtc::kAdmMaxGuidSize]) {
189 ASSERT(false);
190 return 0;
191}
192
193int32_t FakeAudioCaptureModule::SetPlayoutDevice(uint16_t /*index*/) {
194 // No playout device, just playing from file. Return success.
195 return 0;
196}
197
198int32_t FakeAudioCaptureModule::SetPlayoutDevice(WindowsDeviceType /*device*/) {
199 if (play_is_initialized_) {
200 return -1;
201 }
202 return 0;
203}
204
205int32_t FakeAudioCaptureModule::SetRecordingDevice(uint16_t /*index*/) {
206 // No recording device, just dropping audio. Return success.
207 return 0;
208}
209
210int32_t FakeAudioCaptureModule::SetRecordingDevice(
211 WindowsDeviceType /*device*/) {
212 if (rec_is_initialized_) {
213 return -1;
214 }
215 return 0;
216}
217
218int32_t FakeAudioCaptureModule::PlayoutIsAvailable(bool* /*available*/) {
219 ASSERT(false);
220 return 0;
221}
222
223int32_t FakeAudioCaptureModule::InitPlayout() {
224 play_is_initialized_ = true;
225 return 0;
226}
227
228bool FakeAudioCaptureModule::PlayoutIsInitialized() const {
229 return play_is_initialized_;
230}
231
232int32_t FakeAudioCaptureModule::RecordingIsAvailable(bool* /*available*/) {
233 ASSERT(false);
234 return 0;
235}
236
237int32_t FakeAudioCaptureModule::InitRecording() {
238 rec_is_initialized_ = true;
239 return 0;
240}
241
242bool FakeAudioCaptureModule::RecordingIsInitialized() const {
243 ASSERT(false);
244 return 0;
245}
246
247int32_t FakeAudioCaptureModule::StartPlayout() {
248 if (!play_is_initialized_) {
249 return -1;
250 }
wu@webrtc.org8804a292013-10-22 23:09:20 +0000251 {
252 talk_base::CritScope cs(&crit_);
253 playing_ = true;
254 }
255 bool start = true;
256 UpdateProcessing(start);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000257 return 0;
258}
259
260int32_t FakeAudioCaptureModule::StopPlayout() {
wu@webrtc.org8804a292013-10-22 23:09:20 +0000261 bool start = false;
262 {
263 talk_base::CritScope cs(&crit_);
264 playing_ = false;
265 start = ShouldStartProcessing();
266 }
267 UpdateProcessing(start);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000268 return 0;
269}
270
271bool FakeAudioCaptureModule::Playing() const {
wu@webrtc.org8804a292013-10-22 23:09:20 +0000272 talk_base::CritScope cs(&crit_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000273 return playing_;
274}
275
276int32_t FakeAudioCaptureModule::StartRecording() {
277 if (!rec_is_initialized_) {
278 return -1;
279 }
wu@webrtc.org8804a292013-10-22 23:09:20 +0000280 {
281 talk_base::CritScope cs(&crit_);
282 recording_ = true;
283 }
284 bool start = true;
285 UpdateProcessing(start);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000286 return 0;
287}
288
289int32_t FakeAudioCaptureModule::StopRecording() {
wu@webrtc.org8804a292013-10-22 23:09:20 +0000290 bool start = false;
291 {
292 talk_base::CritScope cs(&crit_);
293 recording_ = false;
294 start = ShouldStartProcessing();
295 }
296 UpdateProcessing(start);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000297 return 0;
298}
299
300bool FakeAudioCaptureModule::Recording() const {
wu@webrtc.org8804a292013-10-22 23:09:20 +0000301 talk_base::CritScope cs(&crit_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000302 return recording_;
303}
304
305int32_t FakeAudioCaptureModule::SetAGC(bool /*enable*/) {
306 // No AGC but not needed since audio is pregenerated. Return success.
307 return 0;
308}
309
310bool FakeAudioCaptureModule::AGC() const {
311 ASSERT(false);
312 return 0;
313}
314
315int32_t FakeAudioCaptureModule::SetWaveOutVolume(uint16_t /*volume_left*/,
316 uint16_t /*volume_right*/) {
317 ASSERT(false);
318 return 0;
319}
320
321int32_t FakeAudioCaptureModule::WaveOutVolume(
322 uint16_t* /*volume_left*/,
323 uint16_t* /*volume_right*/) const {
324 ASSERT(false);
325 return 0;
326}
327
328int32_t FakeAudioCaptureModule::SpeakerIsAvailable(bool* available) {
329 // No speaker, just dropping audio. Return success.
330 *available = true;
331 return 0;
332}
333
334int32_t FakeAudioCaptureModule::InitSpeaker() {
335 // No speaker, just playing from file. Return success.
336 return 0;
337}
338
339bool FakeAudioCaptureModule::SpeakerIsInitialized() const {
340 ASSERT(false);
341 return 0;
342}
343
344int32_t FakeAudioCaptureModule::MicrophoneIsAvailable(bool* available) {
345 // No microphone, just playing from file. Return success.
346 *available = true;
347 return 0;
348}
349
350int32_t FakeAudioCaptureModule::InitMicrophone() {
351 // No microphone, just playing from file. Return success.
352 return 0;
353}
354
355bool FakeAudioCaptureModule::MicrophoneIsInitialized() const {
356 ASSERT(false);
357 return 0;
358}
359
360int32_t FakeAudioCaptureModule::SpeakerVolumeIsAvailable(bool* /*available*/) {
361 ASSERT(false);
362 return 0;
363}
364
365int32_t FakeAudioCaptureModule::SetSpeakerVolume(uint32_t /*volume*/) {
366 ASSERT(false);
367 return 0;
368}
369
370int32_t FakeAudioCaptureModule::SpeakerVolume(uint32_t* /*volume*/) const {
371 ASSERT(false);
372 return 0;
373}
374
375int32_t FakeAudioCaptureModule::MaxSpeakerVolume(
376 uint32_t* /*max_volume*/) const {
377 ASSERT(false);
378 return 0;
379}
380
381int32_t FakeAudioCaptureModule::MinSpeakerVolume(
382 uint32_t* /*min_volume*/) const {
383 ASSERT(false);
384 return 0;
385}
386
387int32_t FakeAudioCaptureModule::SpeakerVolumeStepSize(
388 uint16_t* /*step_size*/) const {
389 ASSERT(false);
390 return 0;
391}
392
393int32_t FakeAudioCaptureModule::MicrophoneVolumeIsAvailable(
394 bool* /*available*/) {
395 ASSERT(false);
396 return 0;
397}
398
wu@webrtc.org8804a292013-10-22 23:09:20 +0000399int32_t FakeAudioCaptureModule::SetMicrophoneVolume(uint32_t volume) {
400 talk_base::CritScope cs(&crit_);
401 current_mic_level_ = volume;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000402 return 0;
403}
404
405int32_t FakeAudioCaptureModule::MicrophoneVolume(uint32_t* volume) const {
wu@webrtc.org8804a292013-10-22 23:09:20 +0000406 talk_base::CritScope cs(&crit_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000407 *volume = current_mic_level_;
408 return 0;
409}
410
411int32_t FakeAudioCaptureModule::MaxMicrophoneVolume(
412 uint32_t* max_volume) const {
413 *max_volume = kMaxVolume;
414 return 0;
415}
416
417int32_t FakeAudioCaptureModule::MinMicrophoneVolume(
418 uint32_t* /*min_volume*/) const {
419 ASSERT(false);
420 return 0;
421}
422
423int32_t FakeAudioCaptureModule::MicrophoneVolumeStepSize(
424 uint16_t* /*step_size*/) const {
425 ASSERT(false);
426 return 0;
427}
428
429int32_t FakeAudioCaptureModule::SpeakerMuteIsAvailable(bool* /*available*/) {
430 ASSERT(false);
431 return 0;
432}
433
434int32_t FakeAudioCaptureModule::SetSpeakerMute(bool /*enable*/) {
435 ASSERT(false);
436 return 0;
437}
438
439int32_t FakeAudioCaptureModule::SpeakerMute(bool* /*enabled*/) const {
440 ASSERT(false);
441 return 0;
442}
443
444int32_t FakeAudioCaptureModule::MicrophoneMuteIsAvailable(bool* /*available*/) {
445 ASSERT(false);
446 return 0;
447}
448
449int32_t FakeAudioCaptureModule::SetMicrophoneMute(bool /*enable*/) {
450 ASSERT(false);
451 return 0;
452}
453
454int32_t FakeAudioCaptureModule::MicrophoneMute(bool* /*enabled*/) const {
455 ASSERT(false);
456 return 0;
457}
458
459int32_t FakeAudioCaptureModule::MicrophoneBoostIsAvailable(
460 bool* /*available*/) {
461 ASSERT(false);
462 return 0;
463}
464
465int32_t FakeAudioCaptureModule::SetMicrophoneBoost(bool /*enable*/) {
466 ASSERT(false);
467 return 0;
468}
469
470int32_t FakeAudioCaptureModule::MicrophoneBoost(bool* /*enabled*/) const {
471 ASSERT(false);
472 return 0;
473}
474
475int32_t FakeAudioCaptureModule::StereoPlayoutIsAvailable(
476 bool* available) const {
477 // No recording device, just dropping audio. Stereo can be dropped just
478 // as easily as mono.
479 *available = true;
480 return 0;
481}
482
483int32_t FakeAudioCaptureModule::SetStereoPlayout(bool /*enable*/) {
484 // No recording device, just dropping audio. Stereo can be dropped just
485 // as easily as mono.
486 return 0;
487}
488
489int32_t FakeAudioCaptureModule::StereoPlayout(bool* /*enabled*/) const {
490 ASSERT(false);
491 return 0;
492}
493
494int32_t FakeAudioCaptureModule::StereoRecordingIsAvailable(
495 bool* available) const {
496 // Keep thing simple. No stereo recording.
497 *available = false;
498 return 0;
499}
500
501int32_t FakeAudioCaptureModule::SetStereoRecording(bool enable) {
502 if (!enable) {
503 return 0;
504 }
505 return -1;
506}
507
508int32_t FakeAudioCaptureModule::StereoRecording(bool* /*enabled*/) const {
509 ASSERT(false);
510 return 0;
511}
512
513int32_t FakeAudioCaptureModule::SetRecordingChannel(
514 const ChannelType channel) {
515 if (channel != AudioDeviceModule::kChannelBoth) {
516 // There is no right or left in mono. I.e. kChannelBoth should be used for
517 // mono.
518 ASSERT(false);
519 return -1;
520 }
521 return 0;
522}
523
524int32_t FakeAudioCaptureModule::RecordingChannel(ChannelType* channel) const {
525 // Stereo recording not supported. However, WebRTC ADM returns kChannelBoth
526 // in that case. Do the same here.
527 *channel = AudioDeviceModule::kChannelBoth;
528 return 0;
529}
530
531int32_t FakeAudioCaptureModule::SetPlayoutBuffer(const BufferType /*type*/,
532 uint16_t /*size_ms*/) {
533 ASSERT(false);
534 return 0;
535}
536
537int32_t FakeAudioCaptureModule::PlayoutBuffer(BufferType* /*type*/,
538 uint16_t* /*size_ms*/) const {
539 ASSERT(false);
540 return 0;
541}
542
543int32_t FakeAudioCaptureModule::PlayoutDelay(uint16_t* delay_ms) const {
544 // No delay since audio frames are dropped.
545 *delay_ms = 0;
546 return 0;
547}
548
549int32_t FakeAudioCaptureModule::RecordingDelay(uint16_t* /*delay_ms*/) const {
550 ASSERT(false);
551 return 0;
552}
553
554int32_t FakeAudioCaptureModule::CPULoad(uint16_t* /*load*/) const {
555 ASSERT(false);
556 return 0;
557}
558
559int32_t FakeAudioCaptureModule::StartRawOutputFileRecording(
560 const char /*pcm_file_name_utf8*/[webrtc::kAdmMaxFileNameSize]) {
561 ASSERT(false);
562 return 0;
563}
564
565int32_t FakeAudioCaptureModule::StopRawOutputFileRecording() {
566 ASSERT(false);
567 return 0;
568}
569
570int32_t FakeAudioCaptureModule::StartRawInputFileRecording(
571 const char /*pcm_file_name_utf8*/[webrtc::kAdmMaxFileNameSize]) {
572 ASSERT(false);
573 return 0;
574}
575
576int32_t FakeAudioCaptureModule::StopRawInputFileRecording() {
577 ASSERT(false);
578 return 0;
579}
580
581int32_t FakeAudioCaptureModule::SetRecordingSampleRate(
582 const uint32_t /*samples_per_sec*/) {
583 ASSERT(false);
584 return 0;
585}
586
587int32_t FakeAudioCaptureModule::RecordingSampleRate(
588 uint32_t* /*samples_per_sec*/) const {
589 ASSERT(false);
590 return 0;
591}
592
593int32_t FakeAudioCaptureModule::SetPlayoutSampleRate(
594 const uint32_t /*samples_per_sec*/) {
595 ASSERT(false);
596 return 0;
597}
598
599int32_t FakeAudioCaptureModule::PlayoutSampleRate(
600 uint32_t* /*samples_per_sec*/) const {
601 ASSERT(false);
602 return 0;
603}
604
605int32_t FakeAudioCaptureModule::ResetAudioDevice() {
606 ASSERT(false);
607 return 0;
608}
609
610int32_t FakeAudioCaptureModule::SetLoudspeakerStatus(bool /*enable*/) {
611 ASSERT(false);
612 return 0;
613}
614
615int32_t FakeAudioCaptureModule::GetLoudspeakerStatus(bool* /*enabled*/) const {
616 ASSERT(false);
617 return 0;
618}
619
620void FakeAudioCaptureModule::OnMessage(talk_base::Message* msg) {
621 switch (msg->message_id) {
wu@webrtc.org8804a292013-10-22 23:09:20 +0000622 case MSG_START_PROCESS:
623 StartProcessP();
624 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000625 case MSG_RUN_PROCESS:
626 ProcessFrameP();
627 break;
628 case MSG_STOP_PROCESS:
629 StopProcessP();
630 break;
631 default:
632 // All existing messages should be caught. Getting here should never
633 // happen.
634 ASSERT(false);
635 }
636}
637
638bool FakeAudioCaptureModule::Initialize() {
639 // Set the send buffer samples high enough that it would not occur on the
640 // remote side unless a packet containing a sample of that magnitude has been
641 // sent to it. Note that the audio processing pipeline will likely distort the
642 // original signal.
643 SetSendBuffer(kHighSampleValue);
644 last_process_time_ms_ = talk_base::Time();
645 return true;
646}
647
648void FakeAudioCaptureModule::SetSendBuffer(int value) {
649 Sample* buffer_ptr = reinterpret_cast<Sample*>(send_buffer_);
650 const int buffer_size_in_samples = sizeof(send_buffer_) /
651 kNumberBytesPerSample;
652 for (int i = 0; i < buffer_size_in_samples; ++i) {
653 buffer_ptr[i] = value;
654 }
655}
656
657void FakeAudioCaptureModule::ResetRecBuffer() {
658 memset(rec_buffer_, 0, sizeof(rec_buffer_));
659}
660
661bool FakeAudioCaptureModule::CheckRecBuffer(int value) {
662 const Sample* buffer_ptr = reinterpret_cast<const Sample*>(rec_buffer_);
663 const int buffer_size_in_samples = sizeof(rec_buffer_) /
664 kNumberBytesPerSample;
665 for (int i = 0; i < buffer_size_in_samples; ++i) {
666 if (buffer_ptr[i] >= value) return true;
667 }
668 return false;
669}
670
wu@webrtc.org8804a292013-10-22 23:09:20 +0000671bool FakeAudioCaptureModule::ShouldStartProcessing() {
672 return recording_ || playing_;
673}
674
675void FakeAudioCaptureModule::UpdateProcessing(bool start) {
676 if (start) {
677 process_thread_->Post(this, MSG_START_PROCESS);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000678 } else {
679 process_thread_->Send(this, MSG_STOP_PROCESS);
680 }
681}
682
wu@webrtc.org8804a292013-10-22 23:09:20 +0000683void FakeAudioCaptureModule::StartProcessP() {
684 ASSERT(talk_base::Thread::Current() == process_thread_);
685 if (started_) {
686 // Already started.
687 return;
688 }
689 ProcessFrameP();
690}
691
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000692void FakeAudioCaptureModule::ProcessFrameP() {
693 ASSERT(talk_base::Thread::Current() == process_thread_);
694 if (!started_) {
695 next_frame_time_ = talk_base::Time();
696 started_ = true;
697 }
wu@webrtc.org8804a292013-10-22 23:09:20 +0000698
699 bool playing;
700 bool recording;
701 {
702 talk_base::CritScope cs(&crit_);
703 playing = playing_;
704 recording = recording_;
705 }
706
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000707 // Receive and send frames every kTimePerFrameMs.
wu@webrtc.org8804a292013-10-22 23:09:20 +0000708 if (playing) {
709 ReceiveFrameP();
710 }
711 if (recording) {
712 SendFrameP();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000713 }
714
715 next_frame_time_ += kTimePerFrameMs;
716 const uint32 current_time = talk_base::Time();
717 const uint32 wait_time = (next_frame_time_ > current_time) ?
718 next_frame_time_ - current_time : 0;
719 process_thread_->PostDelayed(wait_time, this, MSG_RUN_PROCESS);
720}
721
722void FakeAudioCaptureModule::ReceiveFrameP() {
723 ASSERT(talk_base::Thread::Current() == process_thread_);
wu@webrtc.org8804a292013-10-22 23:09:20 +0000724 {
725 talk_base::CritScope cs(&crit_callback_);
726 if (!audio_callback_) {
727 return;
728 }
729 ResetRecBuffer();
730 uint32_t nSamplesOut = 0;
731 if (audio_callback_->NeedMorePlayData(kNumberSamples, kNumberBytesPerSample,
732 kNumberOfChannels, kSamplesPerSecond,
733 rec_buffer_, nSamplesOut) != 0) {
734 ASSERT(false);
735 }
736 ASSERT(nSamplesOut == kNumberSamples);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000737 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000738 // The SetBuffer() function ensures that after decoding, the audio buffer
739 // should contain samples of similar magnitude (there is likely to be some
740 // distortion due to the audio pipeline). If one sample is detected to
741 // have the same or greater magnitude somewhere in the frame, an actual frame
742 // has been received from the remote side (i.e. faked frames are not being
743 // pulled).
wu@webrtc.org8804a292013-10-22 23:09:20 +0000744 if (CheckRecBuffer(kHighSampleValue)) {
745 talk_base::CritScope cs(&crit_);
746 ++frames_received_;
747 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000748}
749
750void FakeAudioCaptureModule::SendFrameP() {
751 ASSERT(talk_base::Thread::Current() == process_thread_);
wu@webrtc.org8804a292013-10-22 23:09:20 +0000752 talk_base::CritScope cs(&crit_callback_);
753 if (!audio_callback_) {
754 return;
755 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000756 bool key_pressed = false;
wu@webrtc.org8804a292013-10-22 23:09:20 +0000757 uint32_t current_mic_level = 0;
758 MicrophoneVolume(&current_mic_level);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000759 if (audio_callback_->RecordedDataIsAvailable(send_buffer_, kNumberSamples,
760 kNumberBytesPerSample,
761 kNumberOfChannels,
762 kSamplesPerSecond, kTotalDelayMs,
wu@webrtc.org8804a292013-10-22 23:09:20 +0000763 kClockDriftMs, current_mic_level,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000764 key_pressed,
wu@webrtc.org8804a292013-10-22 23:09:20 +0000765 current_mic_level) != 0) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000766 ASSERT(false);
767 }
wu@webrtc.org8804a292013-10-22 23:09:20 +0000768 SetMicrophoneVolume(current_mic_level);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000769}
770
771void FakeAudioCaptureModule::StopProcessP() {
772 ASSERT(talk_base::Thread::Current() == process_thread_);
773 started_ = false;
774 process_thread_->Clear(this);
775}