1/* 2 * Copyright (c) 2013 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/test/fake_audio_device.h" 12 13#include <algorithm> 14 15#include "testing/gtest/include/gtest/gtest.h" 16#include "webrtc/modules/media_file/source/media_file_utility.h" 17#include "webrtc/system_wrappers/interface/clock.h" 18#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" 19#include "webrtc/system_wrappers/interface/event_wrapper.h" 20#include "webrtc/system_wrappers/interface/file_wrapper.h" 21#include "webrtc/system_wrappers/interface/thread_wrapper.h" 22 23namespace webrtc { 24namespace test { 25 26FakeAudioDevice::FakeAudioDevice(Clock* clock, const std::string& filename) 27 : audio_callback_(NULL), 28 capturing_(false), 29 captured_audio_(), 30 playout_buffer_(), 31 last_playout_ms_(-1), 32 clock_(clock), 33 tick_(EventWrapper::Create()), 34 lock_(CriticalSectionWrapper::CreateCriticalSection()), 35 file_utility_(new ModuleFileUtility(0)), 36 input_stream_(FileWrapper::Create()) { 37 memset(captured_audio_, 0, sizeof(captured_audio_)); 38 memset(playout_buffer_, 0, sizeof(playout_buffer_)); 39 // Open audio input file as read-only and looping. 40 EXPECT_EQ(0, input_stream_->OpenFile(filename.c_str(), true, true)) 41 << filename; 42} 43 44FakeAudioDevice::~FakeAudioDevice() { 45 Stop(); 46 47 if (thread_.get() != NULL) 48 thread_->Stop(); 49} 50 51int32_t FakeAudioDevice::Init() { 52 CriticalSectionScoped cs(lock_.get()); 53 if (file_utility_->InitPCMReading(*input_stream_.get()) != 0) 54 return -1; 55 56 if (!tick_->StartTimer(true, 10)) 57 return -1; 58 thread_.reset(ThreadWrapper::CreateThread( 59 FakeAudioDevice::Run, this, webrtc::kHighPriority, "FakeAudioDevice")); 60 if (thread_.get() == NULL) 61 return -1; 62 unsigned int thread_id; 63 if (!thread_->Start(thread_id)) { 64 thread_.reset(); 65 return -1; 66 } 67 return 0; 68} 69 70int32_t FakeAudioDevice::RegisterAudioCallback(AudioTransport* callback) { 71 CriticalSectionScoped cs(lock_.get()); 72 audio_callback_ = callback; 73 return 0; 74} 75 76bool FakeAudioDevice::Playing() const { 77 CriticalSectionScoped cs(lock_.get()); 78 return capturing_; 79} 80 81int32_t FakeAudioDevice::PlayoutDelay(uint16_t* delay_ms) const { 82 *delay_ms = 0; 83 return 0; 84} 85 86bool FakeAudioDevice::Recording() const { 87 CriticalSectionScoped cs(lock_.get()); 88 return capturing_; 89} 90 91bool FakeAudioDevice::Run(void* obj) { 92 static_cast<FakeAudioDevice*>(obj)->CaptureAudio(); 93 return true; 94} 95 96void FakeAudioDevice::CaptureAudio() { 97 { 98 CriticalSectionScoped cs(lock_.get()); 99 if (capturing_) { 100 int bytes_read = file_utility_->ReadPCMData( 101 *input_stream_.get(), captured_audio_, kBufferSizeBytes); 102 if (bytes_read <= 0) 103 return; 104 int num_samples = bytes_read / 2; // 2 bytes per sample. 105 uint32_t new_mic_level; 106 EXPECT_EQ(0, 107 audio_callback_->RecordedDataIsAvailable(captured_audio_, 108 num_samples, 109 2, 110 1, 111 kFrequencyHz, 112 0, 113 0, 114 0, 115 false, 116 new_mic_level)); 117 uint32_t samples_needed = kFrequencyHz / 100; 118 int64_t now_ms = clock_->TimeInMilliseconds(); 119 uint32_t time_since_last_playout_ms = now_ms - last_playout_ms_; 120 if (last_playout_ms_ > 0 && time_since_last_playout_ms > 0) 121 samples_needed = std::min(kFrequencyHz / time_since_last_playout_ms, 122 kBufferSizeBytes / 2); 123 uint32_t samples_out = 0; 124 int64_t elapsed_time_ms = -1; 125 int64_t ntp_time_ms = -1; 126 EXPECT_EQ(0, 127 audio_callback_->NeedMorePlayData(samples_needed, 128 2, 129 1, 130 kFrequencyHz, 131 playout_buffer_, 132 samples_out, 133 &elapsed_time_ms, 134 &ntp_time_ms)); 135 } 136 } 137 tick_->Wait(WEBRTC_EVENT_INFINITE); 138} 139 140void FakeAudioDevice::Start() { 141 CriticalSectionScoped cs(lock_.get()); 142 capturing_ = true; 143} 144 145void FakeAudioDevice::Stop() { 146 CriticalSectionScoped cs(lock_.get()); 147 capturing_ = false; 148} 149} // namespace test 150} // namespace webrtc 151