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