diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/direct_transport.cc | 52 | ||||
-rw-r--r-- | test/direct_transport.h | 12 | ||||
-rw-r--r-- | test/fake_audio_device.cc | 146 | ||||
-rw-r--r-- | test/fake_audio_device.h | 69 | ||||
-rw-r--r-- | test/rtp_rtcp_observer.h | 30 | ||||
-rw-r--r-- | test/webrtc_test_common.gyp | 3 |
6 files changed, 296 insertions, 16 deletions
diff --git a/test/direct_transport.cc b/test/direct_transport.cc index af8ebcd3..aed7002e 100644 --- a/test/direct_transport.cc +++ b/test/direct_transport.cc @@ -12,6 +12,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "webrtc/call.h" +#include "webrtc/system_wrappers/interface/clock.h" namespace webrtc { namespace test { @@ -20,8 +21,22 @@ DirectTransport::DirectTransport() : lock_(CriticalSectionWrapper::CreateCriticalSection()), packet_event_(EventWrapper::Create()), thread_(ThreadWrapper::CreateThread(NetworkProcess, this)), + clock_(Clock::GetRealTimeClock()), shutting_down_(false), - receiver_(NULL) { + receiver_(NULL), + delay_ms_(0) { + unsigned int thread_id; + EXPECT_TRUE(thread_->Start(thread_id)); +} + +DirectTransport::DirectTransport(int delay_ms) + : lock_(CriticalSectionWrapper::CreateCriticalSection()), + packet_event_(EventWrapper::Create()), + thread_(ThreadWrapper::CreateThread(NetworkProcess, this)), + clock_(Clock::GetRealTimeClock()), + shutting_down_(false), + receiver_(NULL), + delay_ms_(delay_ms) { unsigned int thread_id; EXPECT_TRUE(thread_->Start(thread_id)); } @@ -43,28 +58,32 @@ void DirectTransport::SetReceiver(PacketReceiver* receiver) { } bool DirectTransport::SendRTP(const uint8_t* data, size_t length) { - QueuePacket(data, length); + QueuePacket(data, length, clock_->TimeInMilliseconds() + delay_ms_); return true; } bool DirectTransport::SendRTCP(const uint8_t* data, size_t length) { - QueuePacket(data, length); + QueuePacket(data, length, clock_->TimeInMilliseconds() + delay_ms_); return true; } -DirectTransport::Packet::Packet() : length(0) {} +DirectTransport::Packet::Packet() : length(0), delivery_time_ms(0) {} -DirectTransport::Packet::Packet(const uint8_t* data, size_t length) - : length(length) { +DirectTransport::Packet::Packet(const uint8_t* data, + size_t length, + int64_t delivery_time_ms) + : length(length), delivery_time_ms(delivery_time_ms) { EXPECT_LE(length, sizeof(this->data)); memcpy(this->data, data, length); } -void DirectTransport::QueuePacket(const uint8_t* data, size_t length) { +void DirectTransport::QueuePacket(const uint8_t* data, + size_t length, + int64_t delivery_time_ms) { CriticalSectionScoped crit(lock_.get()); if (receiver_ == NULL) return; - packet_queue_.push_back(Packet(data, length)); + packet_queue_.push_back(Packet(data, length, delivery_time_ms)); packet_event_->Set(); } @@ -80,12 +99,27 @@ bool DirectTransport::SendPackets() { if (packet_queue_.empty()) break; p = packet_queue_.front(); + if (p.delivery_time_ms > clock_->TimeInMilliseconds()) + break; packet_queue_.pop_front(); } receiver_->DeliverPacket(p.data, p.length); } + uint32_t time_until_next_delivery = WEBRTC_EVENT_INFINITE; + { + CriticalSectionScoped crit(lock_.get()); + if (!packet_queue_.empty()) { + int64_t now_ms = clock_->TimeInMilliseconds(); + const int64_t delivery_time_ms = packet_queue_.front().delivery_time_ms; + if (delivery_time_ms > now_ms) { + time_until_next_delivery = delivery_time_ms - now_ms; + } else { + time_until_next_delivery = 0; + } + } + } - switch (packet_event_->Wait(WEBRTC_EVENT_INFINITE)) { + switch (packet_event_->Wait(time_until_next_delivery)) { case kEventSignaled: packet_event_->Reset(); break; diff --git a/test/direct_transport.h b/test/direct_transport.h index d4cb45aa..30412e0c 100644 --- a/test/direct_transport.h +++ b/test/direct_transport.h @@ -22,6 +22,7 @@ namespace webrtc { +class Clock; class PacketReceiver; namespace test { @@ -29,6 +30,7 @@ namespace test { class DirectTransport : public newapi::Transport { public: DirectTransport(); + explicit DirectTransport(int delay_ms); ~DirectTransport(); virtual void StopSending(); @@ -40,13 +42,16 @@ class DirectTransport : public newapi::Transport { private: struct Packet { Packet(); - Packet(const uint8_t* data, size_t length); + Packet(const uint8_t* data, size_t length, int64_t delivery_time_ms); uint8_t data[1500]; size_t length; + int64_t delivery_time_ms; }; - void QueuePacket(const uint8_t* data, size_t length); + void QueuePacket(const uint8_t* data, + size_t length, + int64_t delivery_time_ms); static bool NetworkProcess(void* transport); bool SendPackets(); @@ -54,11 +59,14 @@ class DirectTransport : public newapi::Transport { scoped_ptr<CriticalSectionWrapper> lock_; scoped_ptr<EventWrapper> packet_event_; scoped_ptr<ThreadWrapper> thread_; + Clock* clock_; bool shutting_down_; std::deque<Packet> packet_queue_; PacketReceiver* receiver_; + // TODO(stefan): Replace this with FakeNetworkPipe. + const int delay_ms_; }; } // namespace test } // namespace webrtc diff --git a/test/fake_audio_device.cc b/test/fake_audio_device.cc new file mode 100644 index 00000000..a6fe165b --- /dev/null +++ b/test/fake_audio_device.cc @@ -0,0 +1,146 @@ +/* + * 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 <algorithm> + +#include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/modules/media_file/source/media_file_utility.h" +#include "webrtc/system_wrappers/interface/clock.h" +#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" +#include "webrtc/system_wrappers/interface/event_wrapper.h" +#include "webrtc/system_wrappers/interface/file_wrapper.h" +#include "webrtc/system_wrappers/interface/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_(EventWrapper::Create()), + lock_(CriticalSectionWrapper::CreateCriticalSection()), + 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() { + CriticalSectionScoped cs(lock_.get()); + if (file_utility_->InitPCMReading(*input_stream_.get()) != 0) + return -1; + + if (!tick_->StartTimer(true, 10)) + return -1; + thread_.reset(ThreadWrapper::CreateThread( + FakeAudioDevice::Run, this, webrtc::kHighPriority, "FakeAudioDevice")); + if (thread_.get() == NULL) + return -1; + unsigned int thread_id; + if (!thread_->Start(thread_id)) { + thread_.reset(); + return -1; + } + return 0; +} + +int32_t FakeAudioDevice::RegisterAudioCallback(AudioTransport* callback) { + CriticalSectionScoped cs(lock_.get()); + audio_callback_ = callback; + return 0; +} + +bool FakeAudioDevice::Playing() const { + CriticalSectionScoped cs(lock_.get()); + return capturing_; +} + +int32_t FakeAudioDevice::PlayoutDelay(uint16_t* delay_ms) const { + *delay_ms = 0; + return 0; +} + +bool FakeAudioDevice::Recording() const { + CriticalSectionScoped cs(lock_.get()); + return capturing_; +} + +bool FakeAudioDevice::Run(void* obj) { + static_cast<FakeAudioDevice*>(obj)->CaptureAudio(); + return true; +} + +void FakeAudioDevice::CaptureAudio() { + { + CriticalSectionScoped cs(lock_.get()); + if (capturing_) { + int bytes_read = file_utility_->ReadPCMData( + *input_stream_.get(), captured_audio_, kBufferSizeBytes); + if (bytes_read <= 0) + return; + int num_samples = bytes_read / 2; // 2 bytes per sample. + 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)); + uint32_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(kFrequencyHz / time_since_last_playout_ms, + kBufferSizeBytes / 2); + uint32_t samples_out = 0; + EXPECT_EQ(0, + audio_callback_->NeedMorePlayData(samples_needed, + 2, + 1, + kFrequencyHz, + playout_buffer_, + samples_out)); + } + } + tick_->Wait(WEBRTC_EVENT_INFINITE); +} + +void FakeAudioDevice::Start() { + CriticalSectionScoped cs(lock_.get()); + capturing_ = true; +} + +void FakeAudioDevice::Stop() { + CriticalSectionScoped cs(lock_.get()); + capturing_ = false; +} +} // namespace test +} // namespace webrtc diff --git a/test/fake_audio_device.h b/test/fake_audio_device.h new file mode 100644 index 00000000..40a7547d --- /dev/null +++ b/test/fake_audio_device.h @@ -0,0 +1,69 @@ +/* + * 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. + */ +#ifndef WEBRTC_TEST_FAKE_AUDIO_DEVICE_H_ +#define WEBRTC_TEST_FAKE_AUDIO_DEVICE_H_ + +#include <string> + +#include "webrtc/modules/audio_device/include/fake_audio_device.h" +#include "webrtc/system_wrappers/interface/scoped_ptr.h" +#include "webrtc/typedefs.h" + +namespace webrtc { + +class Clock; +class CriticalSectionWrapper; +class EventWrapper; +class FileWrapper; +class ModuleFileUtility; +class ThreadWrapper; + +namespace test { + +class FakeAudioDevice : public FakeAudioDeviceModule { + public: + FakeAudioDevice(Clock* clock, const std::string& filename); + + virtual ~FakeAudioDevice(); + + virtual int32_t Init() OVERRIDE; + virtual int32_t RegisterAudioCallback(AudioTransport* callback) OVERRIDE; + + virtual bool Playing() const OVERRIDE; + virtual int32_t PlayoutDelay(uint16_t* delay_ms) const OVERRIDE; + virtual bool Recording() const OVERRIDE; + + void Start(); + void Stop(); + + private: + static bool Run(void* obj); + void CaptureAudio(); + + static const uint32_t kFrequencyHz = 16000; + static const uint32_t kBufferSizeBytes = 2 * kFrequencyHz; + + AudioTransport* audio_callback_; + bool capturing_; + int8_t captured_audio_[kBufferSizeBytes]; + int8_t playout_buffer_[kBufferSizeBytes]; + int64_t last_playout_ms_; + + Clock* clock_; + scoped_ptr<EventWrapper> tick_; + scoped_ptr<CriticalSectionWrapper> lock_; + scoped_ptr<ThreadWrapper> thread_; + scoped_ptr<ModuleFileUtility> file_utility_; + scoped_ptr<FileWrapper> input_stream_; +}; +} // namespace test +} // namespace webrtc + +#endif // WEBRTC_TEST_FAKE_AUDIO_DEVICE_H_ diff --git a/test/rtp_rtcp_observer.h b/test/rtp_rtcp_observer.h index 922981cc..39b43c0e 100644 --- a/test/rtp_rtcp_observer.h +++ b/test/rtp_rtcp_observer.h @@ -46,18 +46,35 @@ class RtpRtcpObserver { } protected: - RtpRtcpObserver(unsigned int event_timeout_ms) + RtpRtcpObserver(unsigned int event_timeout_ms, int delay_ms) : lock_(CriticalSectionWrapper::CreateCriticalSection()), observation_complete_(EventWrapper::Create()), parser_(RtpHeaderParser::Create()), send_transport_(lock_.get(), this, &RtpRtcpObserver::OnSendRtp, - &RtpRtcpObserver::OnSendRtcp), + &RtpRtcpObserver::OnSendRtcp, + delay_ms), receive_transport_(lock_.get(), this, &RtpRtcpObserver::OnReceiveRtp, - &RtpRtcpObserver::OnReceiveRtcp), + &RtpRtcpObserver::OnReceiveRtcp, + delay_ms), + timeout_ms_(event_timeout_ms) {} + + explicit RtpRtcpObserver(unsigned int event_timeout_ms) + : lock_(CriticalSectionWrapper::CreateCriticalSection()), + observation_complete_(EventWrapper::Create()), + send_transport_(lock_.get(), + this, + &RtpRtcpObserver::OnSendRtp, + &RtpRtcpObserver::OnSendRtcp, + 0), + receive_transport_(lock_.get(), + this, + &RtpRtcpObserver::OnReceiveRtp, + &RtpRtcpObserver::OnReceiveRtcp, + 0), timeout_ms_(event_timeout_ms) {} enum Action { @@ -87,11 +104,14 @@ class RtpRtcpObserver { public: typedef Action (RtpRtcpObserver::*PacketTransportAction)(const uint8_t*, size_t); + PacketTransport(CriticalSectionWrapper* lock, RtpRtcpObserver* observer, PacketTransportAction on_rtp, - PacketTransportAction on_rtcp) - : lock_(lock), + PacketTransportAction on_rtcp, + int delay_ms) + : test::DirectTransport(delay_ms), + lock_(lock), observer_(observer), on_rtp_(on_rtp), on_rtcp_(on_rtcp) {} diff --git a/test/webrtc_test_common.gyp b/test/webrtc_test_common.gyp index 1a7e579a..5b546c74 100644 --- a/test/webrtc_test_common.gyp +++ b/test/webrtc_test_common.gyp @@ -16,6 +16,8 @@ 'sources': [ 'direct_transport.cc', 'direct_transport.h', + 'fake_audio_device.cc', + 'fake_audio_device.h', 'fake_decoder.cc', 'fake_decoder.h', 'fake_encoder.cc', @@ -115,6 +117,7 @@ '<(DEPTH)/testing/gtest.gyp:gtest', '<(DEPTH)/third_party/gflags/gflags.gyp:gflags', '<(webrtc_root)/modules/modules.gyp:video_capture_module', + '<(webrtc_root)/modules/modules.gyp:media_file', '<(webrtc_root)/test/test.gyp:test_support', '<(webrtc_root)/common_video/common_video.gyp:frame_generator', ], |