/* * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "webrtc/test/fake_audio_device.h" #include #include "testing/gtest/include/gtest/gtest.h" #include "webrtc/modules/media_file/source/media_file_utility.h" #include "webrtc/system_wrappers/include/clock.h" #include "webrtc/system_wrappers/include/event_wrapper.h" #include "webrtc/system_wrappers/include/file_wrapper.h" #include "webrtc/system_wrappers/include/thread_wrapper.h" namespace webrtc { namespace test { FakeAudioDevice::FakeAudioDevice(Clock* clock, const std::string& filename) : audio_callback_(NULL), capturing_(false), captured_audio_(), playout_buffer_(), last_playout_ms_(-1), clock_(clock), tick_(EventTimerWrapper::Create()), file_utility_(new ModuleFileUtility(0)), input_stream_(FileWrapper::Create()) { memset(captured_audio_, 0, sizeof(captured_audio_)); memset(playout_buffer_, 0, sizeof(playout_buffer_)); // Open audio input file as read-only and looping. EXPECT_EQ(0, input_stream_->OpenFile(filename.c_str(), true, true)) << filename; } FakeAudioDevice::~FakeAudioDevice() { Stop(); if (thread_.get() != NULL) thread_->Stop(); } int32_t FakeAudioDevice::Init() { rtc::CritScope cs(&lock_); if (file_utility_->InitPCMReading(*input_stream_.get()) != 0) return -1; if (!tick_->StartTimer(true, 10)) return -1; thread_ = ThreadWrapper::CreateThread(FakeAudioDevice::Run, this, "FakeAudioDevice"); if (thread_.get() == NULL) return -1; if (!thread_->Start()) { thread_.reset(); return -1; } thread_->SetPriority(webrtc::kHighPriority); return 0; } int32_t FakeAudioDevice::RegisterAudioCallback(AudioTransport* callback) { rtc::CritScope cs(&lock_); audio_callback_ = callback; return 0; } bool FakeAudioDevice::Playing() const { rtc::CritScope cs(&lock_); return capturing_; } int32_t FakeAudioDevice::PlayoutDelay(uint16_t* delay_ms) const { *delay_ms = 0; return 0; } bool FakeAudioDevice::Recording() const { rtc::CritScope cs(&lock_); return capturing_; } bool FakeAudioDevice::Run(void* obj) { static_cast(obj)->CaptureAudio(); return true; } void FakeAudioDevice::CaptureAudio() { { rtc::CritScope cs(&lock_); if (capturing_) { int bytes_read = file_utility_->ReadPCMData( *input_stream_.get(), captured_audio_, kBufferSizeBytes); if (bytes_read <= 0) return; // 2 bytes per sample. size_t num_samples = static_cast(bytes_read / 2); uint32_t new_mic_level; EXPECT_EQ(0, audio_callback_->RecordedDataIsAvailable(captured_audio_, num_samples, 2, 1, kFrequencyHz, 0, 0, 0, false, new_mic_level)); size_t samples_needed = kFrequencyHz / 100; int64_t now_ms = clock_->TimeInMilliseconds(); uint32_t time_since_last_playout_ms = now_ms - last_playout_ms_; if (last_playout_ms_ > 0 && time_since_last_playout_ms > 0) { samples_needed = std::min( static_cast(kFrequencyHz / time_since_last_playout_ms), kBufferSizeBytes / 2); } size_t samples_out = 0; int64_t elapsed_time_ms = -1; int64_t ntp_time_ms = -1; EXPECT_EQ(0, audio_callback_->NeedMorePlayData(samples_needed, 2, 1, kFrequencyHz, playout_buffer_, samples_out, &elapsed_time_ms, &ntp_time_ms)); } } tick_->Wait(WEBRTC_EVENT_INFINITE); } void FakeAudioDevice::Start() { rtc::CritScope cs(&lock_); capturing_ = true; } void FakeAudioDevice::Stop() { rtc::CritScope cs(&lock_); capturing_ = false; } } // namespace test } // namespace webrtc