Home | History | Annotate | Download | only in test
      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(&current_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 
    745