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