summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/direct_transport.cc52
-rw-r--r--test/direct_transport.h12
-rw-r--r--test/fake_audio_device.cc146
-rw-r--r--test/fake_audio_device.h69
-rw-r--r--test/rtp_rtcp_observer.h30
-rw-r--r--test/webrtc_test_common.gyp3
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',
],