OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2012 The WebRTC project authors. All Rights Reserved. | |
3 * | |
4 * 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. | |
9 */ | |
10 | |
11 #include "webrtc/api/test/fakeaudiocapturemodule.h" | |
12 | |
13 #include "webrtc/base/common.h" | |
14 #include "webrtc/base/refcount.h" | |
15 #include "webrtc/base/thread.h" | |
16 #include "webrtc/base/timeutils.h" | |
17 | |
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. | |
22 static 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/ | |
26 static const int kAdmMaxIdleTimeProcess = 1000; | |
27 | |
28 // Constants here are derived by running VoE using a real ADM. | |
29 // The constants correspond to 10ms of mono audio at 44kHz. | |
30 static const int kTimePerFrameMs = 10; | |
31 static const uint8_t kNumberOfChannels = 1; | |
32 static const int kSamplesPerSecond = 44000; | |
33 static const int kTotalDelayMs = 0; | |
34 static const int kClockDriftMs = 0; | |
35 static const uint32_t kMaxVolume = 14392; | |
36 | |
37 enum { | |
38 MSG_START_PROCESS, | |
39 MSG_RUN_PROCESS, | |
40 }; | |
41 | |
42 FakeAudioCaptureModule::FakeAudioCaptureModule() | |
43 : last_process_time_ms_(0), | |
44 audio_callback_(nullptr), | |
45 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), | |
52 frames_received_(0) { | |
53 } | |
54 | |
55 FakeAudioCaptureModule::~FakeAudioCaptureModule() { | |
56 if (process_thread_) { | |
57 process_thread_->Stop(); | |
58 } | |
59 } | |
60 | |
61 rtc::scoped_refptr<FakeAudioCaptureModule> FakeAudioCaptureModule::Create() { | |
62 rtc::scoped_refptr<FakeAudioCaptureModule> capture_module( | |
63 new rtc::RefCountedObject<FakeAudioCaptureModule>()); | |
64 if (!capture_module->Initialize()) { | |
65 return nullptr; | |
66 } | |
67 return capture_module; | |
68 } | |
69 | |
70 int FakeAudioCaptureModule::frames_received() const { | |
71 rtc::CritScope cs(&crit_); | |
72 return frames_received_; | |
73 } | |
74 | |
75 int64_t FakeAudioCaptureModule::TimeUntilNextProcess() { | |
76 const int64_t current_time = rtc::TimeMillis(); | |
77 if (current_time < last_process_time_ms_) { | |
78 // TODO: wraparound could be handled more gracefully. | |
79 return 0; | |
80 } | |
81 const int64_t elapsed_time = current_time - last_process_time_ms_; | |
82 if (kAdmMaxIdleTimeProcess < elapsed_time) { | |
83 return 0; | |
84 } | |
85 return kAdmMaxIdleTimeProcess - elapsed_time; | |
86 } | |
87 | |
88 void FakeAudioCaptureModule::Process() { | |
89 last_process_time_ms_ = rtc::TimeMillis(); | |
90 } | |
91 | |
92 int32_t FakeAudioCaptureModule::ActiveAudioLayer( | |
93 AudioLayer* /*audio_layer*/) const { | |
94 ASSERT(false); | |
95 return 0; | |
96 } | |
97 | |
98 webrtc::AudioDeviceModule::ErrorCode FakeAudioCaptureModule::LastError() const { | |
99 ASSERT(false); | |
100 return webrtc::AudioDeviceModule::kAdmErrNone; | |
101 } | |
102 | |
103 int32_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 | |
110 int32_t FakeAudioCaptureModule::RegisterAudioCallback( | |
111 webrtc::AudioTransport* audio_callback) { | |
112 rtc::CritScope cs(&crit_callback_); | |
113 audio_callback_ = audio_callback; | |
114 return 0; | |
115 } | |
116 | |
117 int32_t FakeAudioCaptureModule::Init() { | |
118 // Initialize is called by the factory method. Safe to ignore this Init call. | |
119 return 0; | |
120 } | |
121 | |
122 int32_t FakeAudioCaptureModule::Terminate() { | |
123 // Clean up in the destructor. No action here, just success. | |
124 return 0; | |
125 } | |
126 | |
127 bool FakeAudioCaptureModule::Initialized() const { | |
128 ASSERT(false); | |
129 return 0; | |
130 } | |
131 | |
132 int16_t FakeAudioCaptureModule::PlayoutDevices() { | |
133 ASSERT(false); | |
134 return 0; | |
135 } | |
136 | |
137 int16_t FakeAudioCaptureModule::RecordingDevices() { | |
138 ASSERT(false); | |
139 return 0; | |
140 } | |
141 | |
142 int32_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 | |
150 int32_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 | |
158 int32_t FakeAudioCaptureModule::SetPlayoutDevice(uint16_t /*index*/) { | |
159 // No playout device, just playing from file. Return success. | |
160 return 0; | |
161 } | |
162 | |
163 int32_t FakeAudioCaptureModule::SetPlayoutDevice(WindowsDeviceType /*device*/) { | |
164 if (play_is_initialized_) { | |
165 return -1; | |
166 } | |
167 return 0; | |
168 } | |
169 | |
170 int32_t FakeAudioCaptureModule::SetRecordingDevice(uint16_t /*index*/) { | |
171 // No recording device, just dropping audio. Return success. | |
172 return 0; | |
173 } | |
174 | |
175 int32_t FakeAudioCaptureModule::SetRecordingDevice( | |
176 WindowsDeviceType /*device*/) { | |
177 if (rec_is_initialized_) { | |
178 return -1; | |
179 } | |
180 return 0; | |
181 } | |
182 | |
183 int32_t FakeAudioCaptureModule::PlayoutIsAvailable(bool* /*available*/) { | |
184 ASSERT(false); | |
185 return 0; | |
186 } | |
187 | |
188 int32_t FakeAudioCaptureModule::InitPlayout() { | |
189 play_is_initialized_ = true; | |
190 return 0; | |
191 } | |
192 | |
193 bool FakeAudioCaptureModule::PlayoutIsInitialized() const { | |
194 return play_is_initialized_; | |
195 } | |
196 | |
197 int32_t FakeAudioCaptureModule::RecordingIsAvailable(bool* /*available*/) { | |
198 ASSERT(false); | |
199 return 0; | |
200 } | |
201 | |
202 int32_t FakeAudioCaptureModule::InitRecording() { | |
203 rec_is_initialized_ = true; | |
204 return 0; | |
205 } | |
206 | |
207 bool FakeAudioCaptureModule::RecordingIsInitialized() const { | |
208 return rec_is_initialized_; | |
209 } | |
210 | |
211 int32_t FakeAudioCaptureModule::StartPlayout() { | |
212 if (!play_is_initialized_) { | |
213 return -1; | |
214 } | |
215 { | |
216 rtc::CritScope cs(&crit_); | |
217 playing_ = true; | |
218 } | |
219 bool start = true; | |
220 UpdateProcessing(start); | |
221 return 0; | |
222 } | |
223 | |
224 int32_t FakeAudioCaptureModule::StopPlayout() { | |
225 bool start = false; | |
226 { | |
227 rtc::CritScope cs(&crit_); | |
228 playing_ = false; | |
229 start = ShouldStartProcessing(); | |
230 } | |
231 UpdateProcessing(start); | |
232 return 0; | |
233 } | |
234 | |
235 bool FakeAudioCaptureModule::Playing() const { | |
236 rtc::CritScope cs(&crit_); | |
237 return playing_; | |
238 } | |
239 | |
240 int32_t FakeAudioCaptureModule::StartRecording() { | |
241 if (!rec_is_initialized_) { | |
242 return -1; | |
243 } | |
244 { | |
245 rtc::CritScope cs(&crit_); | |
246 recording_ = true; | |
247 } | |
248 bool start = true; | |
249 UpdateProcessing(start); | |
250 return 0; | |
251 } | |
252 | |
253 int32_t FakeAudioCaptureModule::StopRecording() { | |
254 bool start = false; | |
255 { | |
256 rtc::CritScope cs(&crit_); | |
257 recording_ = false; | |
258 start = ShouldStartProcessing(); | |
259 } | |
260 UpdateProcessing(start); | |
261 return 0; | |
262 } | |
263 | |
264 bool FakeAudioCaptureModule::Recording() const { | |
265 rtc::CritScope cs(&crit_); | |
266 return recording_; | |
267 } | |
268 | |
269 int32_t FakeAudioCaptureModule::SetAGC(bool /*enable*/) { | |
270 // No AGC but not needed since audio is pregenerated. Return success. | |
271 return 0; | |
272 } | |
273 | |
274 bool FakeAudioCaptureModule::AGC() const { | |
275 ASSERT(false); | |
276 return 0; | |
277 } | |
278 | |
279 int32_t FakeAudioCaptureModule::SetWaveOutVolume(uint16_t /*volume_left*/, | |
280 uint16_t /*volume_right*/) { | |
281 ASSERT(false); | |
282 return 0; | |
283 } | |
284 | |
285 int32_t FakeAudioCaptureModule::WaveOutVolume( | |
286 uint16_t* /*volume_left*/, | |
287 uint16_t* /*volume_right*/) const { | |
288 ASSERT(false); | |
289 return 0; | |
290 } | |
291 | |
292 int32_t FakeAudioCaptureModule::InitSpeaker() { | |
293 // No speaker, just playing from file. Return success. | |
294 return 0; | |
295 } | |
296 | |
297 bool FakeAudioCaptureModule::SpeakerIsInitialized() const { | |
298 ASSERT(false); | |
299 return 0; | |
300 } | |
301 | |
302 int32_t FakeAudioCaptureModule::InitMicrophone() { | |
303 // No microphone, just playing from file. Return success. | |
304 return 0; | |
305 } | |
306 | |
307 bool FakeAudioCaptureModule::MicrophoneIsInitialized() const { | |
308 ASSERT(false); | |
309 return 0; | |
310 } | |
311 | |
312 int32_t FakeAudioCaptureModule::SpeakerVolumeIsAvailable(bool* /*available*/) { | |
313 ASSERT(false); | |
314 return 0; | |
315 } | |
316 | |
317 int32_t FakeAudioCaptureModule::SetSpeakerVolume(uint32_t /*volume*/) { | |
318 ASSERT(false); | |
319 return 0; | |
320 } | |
321 | |
322 int32_t FakeAudioCaptureModule::SpeakerVolume(uint32_t* /*volume*/) const { | |
323 ASSERT(false); | |
324 return 0; | |
325 } | |
326 | |
327 int32_t FakeAudioCaptureModule::MaxSpeakerVolume( | |
328 uint32_t* /*max_volume*/) const { | |
329 ASSERT(false); | |
330 return 0; | |
331 } | |
332 | |
333 int32_t FakeAudioCaptureModule::MinSpeakerVolume( | |
334 uint32_t* /*min_volume*/) const { | |
335 ASSERT(false); | |
336 return 0; | |
337 } | |
338 | |
339 int32_t FakeAudioCaptureModule::SpeakerVolumeStepSize( | |
340 uint16_t* /*step_size*/) const { | |
341 ASSERT(false); | |
342 return 0; | |
343 } | |
344 | |
345 int32_t FakeAudioCaptureModule::MicrophoneVolumeIsAvailable( | |
346 bool* /*available*/) { | |
347 ASSERT(false); | |
348 return 0; | |
349 } | |
350 | |
351 int32_t FakeAudioCaptureModule::SetMicrophoneVolume(uint32_t volume) { | |
352 rtc::CritScope cs(&crit_); | |
353 current_mic_level_ = volume; | |
354 return 0; | |
355 } | |
356 | |
357 int32_t FakeAudioCaptureModule::MicrophoneVolume(uint32_t* volume) const { | |
358 rtc::CritScope cs(&crit_); | |
359 *volume = current_mic_level_; | |
360 return 0; | |
361 } | |
362 | |
363 int32_t FakeAudioCaptureModule::MaxMicrophoneVolume( | |
364 uint32_t* max_volume) const { | |
365 *max_volume = kMaxVolume; | |
366 return 0; | |
367 } | |
368 | |
369 int32_t FakeAudioCaptureModule::MinMicrophoneVolume( | |
370 uint32_t* /*min_volume*/) const { | |
371 ASSERT(false); | |
372 return 0; | |
373 } | |
374 | |
375 int32_t FakeAudioCaptureModule::MicrophoneVolumeStepSize( | |
376 uint16_t* /*step_size*/) const { | |
377 ASSERT(false); | |
378 return 0; | |
379 } | |
380 | |
381 int32_t FakeAudioCaptureModule::SpeakerMuteIsAvailable(bool* /*available*/) { | |
382 ASSERT(false); | |
383 return 0; | |
384 } | |
385 | |
386 int32_t FakeAudioCaptureModule::SetSpeakerMute(bool /*enable*/) { | |
387 ASSERT(false); | |
388 return 0; | |
389 } | |
390 | |
391 int32_t FakeAudioCaptureModule::SpeakerMute(bool* /*enabled*/) const { | |
392 ASSERT(false); | |
393 return 0; | |
394 } | |
395 | |
396 int32_t FakeAudioCaptureModule::MicrophoneMuteIsAvailable(bool* /*available*/) { | |
397 ASSERT(false); | |
398 return 0; | |
399 } | |
400 | |
401 int32_t FakeAudioCaptureModule::SetMicrophoneMute(bool /*enable*/) { | |
402 ASSERT(false); | |
403 return 0; | |
404 } | |
405 | |
406 int32_t FakeAudioCaptureModule::MicrophoneMute(bool* /*enabled*/) const { | |
407 ASSERT(false); | |
408 return 0; | |
409 } | |
410 | |
411 int32_t FakeAudioCaptureModule::MicrophoneBoostIsAvailable( | |
412 bool* /*available*/) { | |
413 ASSERT(false); | |
414 return 0; | |
415 } | |
416 | |
417 int32_t FakeAudioCaptureModule::SetMicrophoneBoost(bool /*enable*/) { | |
418 ASSERT(false); | |
419 return 0; | |
420 } | |
421 | |
422 int32_t FakeAudioCaptureModule::MicrophoneBoost(bool* /*enabled*/) const { | |
423 ASSERT(false); | |
424 return 0; | |
425 } | |
426 | |
427 int32_t FakeAudioCaptureModule::StereoPlayoutIsAvailable( | |
428 bool* available) const { | |
429 // No recording device, just dropping audio. Stereo can be dropped just | |
430 // as easily as mono. | |
431 *available = true; | |
432 return 0; | |
433 } | |
434 | |
435 int32_t FakeAudioCaptureModule::SetStereoPlayout(bool /*enable*/) { | |
436 // No recording device, just dropping audio. Stereo can be dropped just | |
437 // as easily as mono. | |
438 return 0; | |
439 } | |
440 | |
441 int32_t FakeAudioCaptureModule::StereoPlayout(bool* /*enabled*/) const { | |
442 ASSERT(false); | |
443 return 0; | |
444 } | |
445 | |
446 int32_t FakeAudioCaptureModule::StereoRecordingIsAvailable( | |
447 bool* available) const { | |
448 // Keep thing simple. No stereo recording. | |
449 *available = false; | |
450 return 0; | |
451 } | |
452 | |
453 int32_t FakeAudioCaptureModule::SetStereoRecording(bool enable) { | |
454 if (!enable) { | |
455 return 0; | |
456 } | |
457 return -1; | |
458 } | |
459 | |
460 int32_t FakeAudioCaptureModule::StereoRecording(bool* /*enabled*/) const { | |
461 ASSERT(false); | |
462 return 0; | |
463 } | |
464 | |
465 int32_t FakeAudioCaptureModule::SetRecordingChannel( | |
466 const ChannelType channel) { | |
467 if (channel != AudioDeviceModule::kChannelBoth) { | |
468 // There is no right or left in mono. I.e. kChannelBoth should be used for | |
469 // mono. | |
470 ASSERT(false); | |
471 return -1; | |
472 } | |
473 return 0; | |
474 } | |
475 | |
476 int32_t FakeAudioCaptureModule::RecordingChannel(ChannelType* channel) const { | |
477 // Stereo recording not supported. However, WebRTC ADM returns kChannelBoth | |
478 // in that case. Do the same here. | |
479 *channel = AudioDeviceModule::kChannelBoth; | |
480 return 0; | |
481 } | |
482 | |
483 int32_t FakeAudioCaptureModule::SetPlayoutBuffer(const BufferType /*type*/, | |
484 uint16_t /*size_ms*/) { | |
485 ASSERT(false); | |
486 return 0; | |
487 } | |
488 | |
489 int32_t FakeAudioCaptureModule::PlayoutBuffer(BufferType* /*type*/, | |
490 uint16_t* /*size_ms*/) const { | |
491 ASSERT(false); | |
492 return 0; | |
493 } | |
494 | |
495 int32_t FakeAudioCaptureModule::PlayoutDelay(uint16_t* delay_ms) const { | |
496 // No delay since audio frames are dropped. | |
497 *delay_ms = 0; | |
498 return 0; | |
499 } | |
500 | |
501 int32_t FakeAudioCaptureModule::RecordingDelay(uint16_t* /*delay_ms*/) const { | |
502 ASSERT(false); | |
503 return 0; | |
504 } | |
505 | |
506 int32_t FakeAudioCaptureModule::CPULoad(uint16_t* /*load*/) const { | |
507 ASSERT(false); | |
508 return 0; | |
509 } | |
510 | |
511 int32_t FakeAudioCaptureModule::StartRawOutputFileRecording( | |
512 const char /*pcm_file_name_utf8*/[webrtc::kAdmMaxFileNameSize]) { | |
513 ASSERT(false); | |
514 return 0; | |
515 } | |
516 | |
517 int32_t FakeAudioCaptureModule::StopRawOutputFileRecording() { | |
518 ASSERT(false); | |
519 return 0; | |
520 } | |
521 | |
522 int32_t FakeAudioCaptureModule::StartRawInputFileRecording( | |
523 const char /*pcm_file_name_utf8*/[webrtc::kAdmMaxFileNameSize]) { | |
524 ASSERT(false); | |
525 return 0; | |
526 } | |
527 | |
528 int32_t FakeAudioCaptureModule::StopRawInputFileRecording() { | |
529 ASSERT(false); | |
530 return 0; | |
531 } | |
532 | |
533 int32_t FakeAudioCaptureModule::SetRecordingSampleRate( | |
534 const uint32_t /*samples_per_sec*/) { | |
535 ASSERT(false); | |
536 return 0; | |
537 } | |
538 | |
539 int32_t FakeAudioCaptureModule::RecordingSampleRate( | |
540 uint32_t* /*samples_per_sec*/) const { | |
541 ASSERT(false); | |
542 return 0; | |
543 } | |
544 | |
545 int32_t FakeAudioCaptureModule::SetPlayoutSampleRate( | |
546 const uint32_t /*samples_per_sec*/) { | |
547 ASSERT(false); | |
548 return 0; | |
549 } | |
550 | |
551 int32_t FakeAudioCaptureModule::PlayoutSampleRate( | |
552 uint32_t* /*samples_per_sec*/) const { | |
553 ASSERT(false); | |
554 return 0; | |
555 } | |
556 | |
557 int32_t FakeAudioCaptureModule::ResetAudioDevice() { | |
558 ASSERT(false); | |
559 return 0; | |
560 } | |
561 | |
562 int32_t FakeAudioCaptureModule::SetLoudspeakerStatus(bool /*enable*/) { | |
563 ASSERT(false); | |
564 return 0; | |
565 } | |
566 | |
567 int32_t FakeAudioCaptureModule::GetLoudspeakerStatus(bool* /*enabled*/) const { | |
568 ASSERT(false); | |
569 return 0; | |
570 } | |
571 | |
572 void FakeAudioCaptureModule::OnMessage(rtc::Message* msg) { | |
573 switch (msg->message_id) { | |
574 case MSG_START_PROCESS: | |
575 StartProcessP(); | |
576 break; | |
577 case MSG_RUN_PROCESS: | |
578 ProcessFrameP(); | |
579 break; | |
580 default: | |
581 // All existing messages should be caught. Getting here should never | |
582 // happen. | |
583 ASSERT(false); | |
584 } | |
585 } | |
586 | |
587 bool FakeAudioCaptureModule::Initialize() { | |
588 // Set the send buffer samples high enough that it would not occur on the | |
589 // remote side unless a packet containing a sample of that magnitude has been | |
590 // sent to it. Note that the audio processing pipeline will likely distort the | |
591 // original signal. | |
592 SetSendBuffer(kHighSampleValue); | |
593 last_process_time_ms_ = rtc::TimeMillis(); | |
594 return true; | |
595 } | |
596 | |
597 void FakeAudioCaptureModule::SetSendBuffer(int value) { | |
598 Sample* buffer_ptr = reinterpret_cast<Sample*>(send_buffer_); | |
599 const size_t buffer_size_in_samples = | |
600 sizeof(send_buffer_) / kNumberBytesPerSample; | |
601 for (size_t i = 0; i < buffer_size_in_samples; ++i) { | |
602 buffer_ptr[i] = value; | |
603 } | |
604 } | |
605 | |
606 void FakeAudioCaptureModule::ResetRecBuffer() { | |
607 memset(rec_buffer_, 0, sizeof(rec_buffer_)); | |
608 } | |
609 | |
610 bool FakeAudioCaptureModule::CheckRecBuffer(int value) { | |
611 const Sample* buffer_ptr = reinterpret_cast<const Sample*>(rec_buffer_); | |
612 const size_t buffer_size_in_samples = | |
613 sizeof(rec_buffer_) / kNumberBytesPerSample; | |
614 for (size_t i = 0; i < buffer_size_in_samples; ++i) { | |
615 if (buffer_ptr[i] >= value) return true; | |
616 } | |
617 return false; | |
618 } | |
619 | |
620 bool FakeAudioCaptureModule::ShouldStartProcessing() { | |
621 return recording_ || playing_; | |
622 } | |
623 | |
624 void FakeAudioCaptureModule::UpdateProcessing(bool start) { | |
625 if (start) { | |
626 if (!process_thread_) { | |
627 process_thread_.reset(new rtc::Thread()); | |
628 process_thread_->Start(); | |
629 } | |
630 process_thread_->Post(RTC_FROM_HERE, this, MSG_START_PROCESS); | |
631 } else { | |
632 if (process_thread_) { | |
633 process_thread_->Stop(); | |
634 process_thread_.reset(nullptr); | |
635 } | |
636 started_ = false; | |
637 } | |
638 } | |
639 | |
640 void FakeAudioCaptureModule::StartProcessP() { | |
641 ASSERT(process_thread_->IsCurrent()); | |
642 if (started_) { | |
643 // Already started. | |
644 return; | |
645 } | |
646 ProcessFrameP(); | |
647 } | |
648 | |
649 void FakeAudioCaptureModule::ProcessFrameP() { | |
650 ASSERT(process_thread_->IsCurrent()); | |
651 if (!started_) { | |
652 next_frame_time_ = rtc::TimeMillis(); | |
653 started_ = true; | |
654 } | |
655 | |
656 { | |
657 rtc::CritScope cs(&crit_); | |
658 // Receive and send frames every kTimePerFrameMs. | |
659 if (playing_) { | |
660 ReceiveFrameP(); | |
661 } | |
662 if (recording_) { | |
663 SendFrameP(); | |
664 } | |
665 } | |
666 | |
667 next_frame_time_ += kTimePerFrameMs; | |
668 const int64_t current_time = rtc::TimeMillis(); | |
669 const int64_t wait_time = | |
670 (next_frame_time_ > current_time) ? next_frame_time_ - current_time : 0; | |
671 process_thread_->PostDelayed(RTC_FROM_HERE, wait_time, this, MSG_RUN_PROCESS); | |
672 } | |
673 | |
674 void FakeAudioCaptureModule::ReceiveFrameP() { | |
675 ASSERT(process_thread_->IsCurrent()); | |
676 { | |
677 rtc::CritScope cs(&crit_callback_); | |
678 if (!audio_callback_) { | |
679 return; | |
680 } | |
681 ResetRecBuffer(); | |
682 size_t nSamplesOut = 0; | |
683 int64_t elapsed_time_ms = 0; | |
684 int64_t ntp_time_ms = 0; | |
685 if (audio_callback_->NeedMorePlayData(kNumberSamples, kNumberBytesPerSample, | |
686 kNumberOfChannels, kSamplesPerSecond, | |
687 rec_buffer_, nSamplesOut, | |
688 &elapsed_time_ms, &ntp_time_ms) != 0) { | |
689 ASSERT(false); | |
690 } | |
691 ASSERT(nSamplesOut == kNumberSamples); | |
692 } | |
693 // The SetBuffer() function ensures that after decoding, the audio buffer | |
694 // should contain samples of similar magnitude (there is likely to be some | |
695 // distortion due to the audio pipeline). If one sample is detected to | |
696 // have the same or greater magnitude somewhere in the frame, an actual frame | |
697 // has been received from the remote side (i.e. faked frames are not being | |
698 // pulled). | |
699 if (CheckRecBuffer(kHighSampleValue)) { | |
700 rtc::CritScope cs(&crit_); | |
701 ++frames_received_; | |
702 } | |
703 } | |
704 | |
705 void FakeAudioCaptureModule::SendFrameP() { | |
706 ASSERT(process_thread_->IsCurrent()); | |
707 rtc::CritScope cs(&crit_callback_); | |
708 if (!audio_callback_) { | |
709 return; | |
710 } | |
711 bool key_pressed = false; | |
712 uint32_t current_mic_level = 0; | |
713 MicrophoneVolume(¤t_mic_level); | |
714 if (audio_callback_->RecordedDataIsAvailable(send_buffer_, kNumberSamples, | |
715 kNumberBytesPerSample, | |
716 kNumberOfChannels, | |
717 kSamplesPerSecond, kTotalDelayMs, | |
718 kClockDriftMs, current_mic_level, | |
719 key_pressed, | |
720 current_mic_level) != 0) { | |
721 ASSERT(false); | |
722 } | |
723 SetMicrophoneVolume(current_mic_level); | |
724 } | |
725 | |
OLD | NEW |