Refactor Call-based tests.
Greatly reduces duplication of constants and setup code for tests based
on the new webrtc::Call APIs. It also makes it significantly easier to
convert sender-only to end-to-end tests as they share more code.
BUG=3035
R=kjellander@webrtc.org, stefan@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/17789004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@6551 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/tools/valgrind-webrtc/gtest_exclude/video_engine_tests.gtest-drmemory_win32.txt b/tools/valgrind-webrtc/gtest_exclude/video_engine_tests.gtest-drmemory_win32.txt
index bfc6b54..6a213a2 100644
--- a/tools/valgrind-webrtc/gtest_exclude/video_engine_tests.gtest-drmemory_win32.txt
+++ b/tools/valgrind-webrtc/gtest_exclude/video_engine_tests.gtest-drmemory_win32.txt
@@ -1,6 +1,6 @@
# Never completes on Dr Memory Full.
# https://code.google.com/p/webrtc/issues/detail?id=3159
-CallTest.SendsAndReceivesMultipleStreams
-CallTest.ReceivesAndRetransmitsNack
+EndToEndTest.SendsAndReceivesMultipleStreams
+EndToEndTest.ReceivesAndRetransmitsNack
# https://code.google.com/p/webrtc/issues/detail?id=3471
VideoSendStreamTest.RetransmitsNackOverRtxWithPacing
diff --git a/tools/valgrind-webrtc/gtest_exclude/video_engine_tests.gtest-tsan.txt b/tools/valgrind-webrtc/gtest_exclude/video_engine_tests.gtest-tsan.txt
deleted file mode 100644
index 6dab6251..0000000
--- a/tools/valgrind-webrtc/gtest_exclude/video_engine_tests.gtest-tsan.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-# https://code.google.com/p/webrtc/issues/detail?id=2908
-CallTest.ReceivesAndRetransmitsNack
diff --git a/webrtc/test/call_test.cc b/webrtc/test/call_test.cc
new file mode 100644
index 0000000..ad2416f
--- /dev/null
+++ b/webrtc/test/call_test.cc
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2014 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/call_test.h"
+
+#include "webrtc/test/encoder_settings.h"
+
+namespace webrtc {
+namespace test {
+
+CallTest::CallTest()
+ : send_stream_(NULL),
+ receive_stream_(NULL),
+ fake_encoder_(Clock::GetRealTimeClock()) {
+}
+CallTest::~CallTest() {
+}
+
+void CallTest::RunBaseTest(BaseTest* test) {
+ CreateSenderCall(test->GetSenderCallConfig());
+ if (test->ShouldCreateReceivers())
+ CreateReceiverCall(test->GetReceiverCallConfig());
+ test->OnCallsCreated(sender_call_.get(), receiver_call_.get());
+
+ if (test->ShouldCreateReceivers()) {
+ test->SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
+ } else {
+ // Sender-only call delivers to itself.
+ test->SetReceivers(sender_call_->Receiver(), NULL);
+ }
+
+ CreateSendConfig(test->GetNumStreams());
+ if (test->ShouldCreateReceivers()) {
+ CreateMatchingReceiveConfigs();
+ }
+ test->ModifyConfigs(&send_config_, &receive_config_, &video_streams_);
+ CreateStreams();
+ test->OnStreamsCreated(send_stream_, receive_stream_);
+
+ CreateFrameGeneratorCapturer();
+ test->OnFrameGeneratorCapturerCreated(frame_generator_capturer_.get());
+
+ Start();
+ test->PerformTest();
+ test->StopSending();
+ Stop();
+
+ DestroyStreams();
+}
+
+void CallTest::Start() {
+ send_stream_->Start();
+ if (receive_stream_ != NULL)
+ receive_stream_->Start();
+ frame_generator_capturer_->Start();
+}
+
+void CallTest::Stop() {
+ frame_generator_capturer_->Stop();
+ if (receive_stream_ != NULL)
+ receive_stream_->Stop();
+ send_stream_->Stop();
+}
+
+void CallTest::CreateCalls(const Call::Config& sender_config,
+ const Call::Config& receiver_config) {
+ CreateSenderCall(sender_config);
+ CreateReceiverCall(receiver_config);
+}
+
+void CallTest::CreateSenderCall(const Call::Config& config) {
+ sender_call_.reset(Call::Create(config));
+}
+
+void CallTest::CreateReceiverCall(const Call::Config& config) {
+ receiver_call_.reset(Call::Create(config));
+}
+
+void CallTest::CreateSendConfig(size_t num_streams) {
+ assert(num_streams <= kNumSsrcs);
+ send_config_ = sender_call_->GetDefaultSendConfig();
+ send_config_.encoder_settings.encoder = &fake_encoder_;
+ send_config_.encoder_settings.payload_name = "FAKE";
+ send_config_.encoder_settings.payload_type = kFakeSendPayloadType;
+ video_streams_ = test::CreateVideoStreams(num_streams);
+ for (size_t i = 0; i < num_streams; ++i)
+ send_config_.rtp.ssrcs.push_back(kSendSsrcs[i]);
+}
+
+// TODO(pbos): Make receive configs into a vector.
+void CallTest::CreateMatchingReceiveConfigs() {
+ assert(send_config_.rtp.ssrcs.size() == 1);
+ receive_config_ = receiver_call_->GetDefaultReceiveConfig();
+ VideoCodec codec =
+ test::CreateDecoderVideoCodec(send_config_.encoder_settings);
+ receive_config_.codecs.push_back(codec);
+ if (send_config_.encoder_settings.encoder == &fake_encoder_) {
+ ExternalVideoDecoder decoder;
+ decoder.decoder = &fake_decoder_;
+ decoder.payload_type = send_config_.encoder_settings.payload_type;
+ receive_config_.external_decoders.push_back(decoder);
+ }
+ receive_config_.rtp.remote_ssrc = send_config_.rtp.ssrcs[0];
+ receive_config_.rtp.local_ssrc = kReceiverLocalSsrc;
+}
+
+void CallTest::CreateFrameGeneratorCapturer() {
+ VideoStream stream = video_streams_.back();
+ frame_generator_capturer_.reset(
+ test::FrameGeneratorCapturer::Create(send_stream_->Input(),
+ stream.width,
+ stream.height,
+ stream.max_framerate,
+ Clock::GetRealTimeClock()));
+}
+void CallTest::CreateStreams() {
+ assert(send_stream_ == NULL);
+ assert(receive_stream_ == NULL);
+
+ send_stream_ =
+ sender_call_->CreateVideoSendStream(send_config_, video_streams_, NULL);
+
+ if (receiver_call_.get() != NULL)
+ receive_stream_ = receiver_call_->CreateVideoReceiveStream(receive_config_);
+}
+
+void CallTest::DestroyStreams() {
+ if (send_stream_ != NULL)
+ sender_call_->DestroyVideoSendStream(send_stream_);
+ if (receive_stream_ != NULL)
+ receiver_call_->DestroyVideoReceiveStream(receive_stream_);
+ send_stream_ = NULL;
+ receive_stream_ = NULL;
+}
+
+const unsigned int CallTest::kDefaultTimeoutMs = 30 * 1000;
+const unsigned int CallTest::kLongTimeoutMs = 120 * 1000;
+const uint8_t CallTest::kSendPayloadType = 100;
+const uint8_t CallTest::kFakeSendPayloadType = 125;
+const uint8_t CallTest::kSendRtxPayloadType = 98;
+const uint32_t CallTest::kSendRtxSsrc = 0xBADCAFE;
+const uint32_t CallTest::kSendSsrcs[kNumSsrcs] = {0xC0FFED, 0xC0FFEE, 0xC0FFEF};
+const uint32_t CallTest::kReceiverLocalSsrc = 0x123456;
+const int CallTest::kNackRtpHistoryMs = 1000;
+
+BaseTest::BaseTest(unsigned int timeout_ms) : RtpRtcpObserver(timeout_ms) {
+}
+
+BaseTest::BaseTest(unsigned int timeout_ms,
+ const FakeNetworkPipe::Config& config)
+ : RtpRtcpObserver(timeout_ms, config) {
+}
+
+BaseTest::~BaseTest() {
+}
+
+Call::Config BaseTest::GetSenderCallConfig() {
+ return Call::Config(SendTransport());
+}
+
+Call::Config BaseTest::GetReceiverCallConfig() {
+ return Call::Config(ReceiveTransport());
+}
+
+void BaseTest::OnCallsCreated(Call* sender_call, Call* receiver_call) {
+}
+
+size_t BaseTest::GetNumStreams() const {
+ return 1;
+}
+
+void BaseTest::ModifyConfigs(VideoSendStream::Config* send_config,
+ VideoReceiveStream::Config* receive_config,
+ std::vector<VideoStream>* video_streams) {
+}
+
+void BaseTest::OnStreamsCreated(VideoSendStream* send_stream,
+ VideoReceiveStream* receive_stream) {
+}
+
+void BaseTest::OnFrameGeneratorCapturerCreated(
+ FrameGeneratorCapturer* frame_generator_capturer) {
+}
+
+SendTest::SendTest(unsigned int timeout_ms) : BaseTest(timeout_ms) {
+}
+
+SendTest::SendTest(unsigned int timeout_ms,
+ const FakeNetworkPipe::Config& config)
+ : BaseTest(timeout_ms, config) {
+}
+
+bool SendTest::ShouldCreateReceivers() const {
+ return false;
+}
+
+EndToEndTest::EndToEndTest(unsigned int timeout_ms) : BaseTest(timeout_ms) {
+}
+
+EndToEndTest::EndToEndTest(unsigned int timeout_ms,
+ const FakeNetworkPipe::Config& config)
+ : BaseTest(timeout_ms, config) {
+}
+
+bool EndToEndTest::ShouldCreateReceivers() const {
+ return true;
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/webrtc/test/call_test.h b/webrtc/test/call_test.h
new file mode 100644
index 0000000..94ac2fa
--- /dev/null
+++ b/webrtc/test/call_test.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2014 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_COMMON_CALL_TEST_H_
+#define WEBRTC_TEST_COMMON_CALL_TEST_H_
+
+#include <vector>
+
+#include "webrtc/call.h"
+#include "webrtc/test/fake_decoder.h"
+#include "webrtc/test/fake_encoder.h"
+#include "webrtc/test/frame_generator_capturer.h"
+#include "webrtc/test/rtp_rtcp_observer.h"
+
+namespace webrtc {
+namespace test {
+
+class BaseTest;
+
+class CallTest : public ::testing::Test {
+ public:
+ CallTest();
+ ~CallTest();
+
+ static const size_t kNumSsrcs = 3;
+
+ static const unsigned int kDefaultTimeoutMs;
+ static const unsigned int kLongTimeoutMs;
+ static const uint8_t kSendPayloadType;
+ static const uint8_t kSendRtxPayloadType;
+ static const uint8_t kFakeSendPayloadType;
+ static const uint32_t kSendRtxSsrc;
+ static const uint32_t kSendSsrcs[kNumSsrcs];
+ static const uint32_t kReceiverLocalSsrc;
+ static const int kNackRtpHistoryMs;
+
+ protected:
+ void RunBaseTest(BaseTest* test);
+
+ void CreateCalls(const Call::Config& sender_config,
+ const Call::Config& receiver_config);
+ void CreateSenderCall(const Call::Config& config);
+ void CreateReceiverCall(const Call::Config& config);
+
+ void CreateSendConfig(size_t num_streams);
+ void CreateMatchingReceiveConfigs();
+
+ void CreateFrameGeneratorCapturer();
+
+ void CreateStreams();
+ void Start();
+ void Stop();
+ void DestroyStreams();
+
+ scoped_ptr<Call> sender_call_;
+ VideoSendStream::Config send_config_;
+ std::vector<VideoStream> video_streams_;
+ VideoSendStream* send_stream_;
+
+ scoped_ptr<Call> receiver_call_;
+ VideoReceiveStream::Config receive_config_;
+ VideoReceiveStream* receive_stream_;
+
+ scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer_;
+ test::FakeEncoder fake_encoder_;
+ test::FakeDecoder fake_decoder_;
+};
+
+class BaseTest : public RtpRtcpObserver {
+ public:
+ explicit BaseTest(unsigned int timeout_ms);
+ BaseTest(unsigned int timeout_ms, const FakeNetworkPipe::Config& config);
+ virtual ~BaseTest();
+
+ virtual void PerformTest() = 0;
+ virtual bool ShouldCreateReceivers() const = 0;
+
+ virtual size_t GetNumStreams() const;
+
+ virtual Call::Config GetSenderCallConfig();
+ virtual Call::Config GetReceiverCallConfig();
+ virtual void OnCallsCreated(Call* sender_call, Call* receiver_call);
+
+ virtual void ModifyConfigs(VideoSendStream::Config* send_config,
+ VideoReceiveStream::Config* receive_config,
+ std::vector<VideoStream>* video_streams);
+ virtual void OnStreamsCreated(VideoSendStream* send_stream,
+ VideoReceiveStream* receive_stream);
+
+ virtual void OnFrameGeneratorCapturerCreated(
+ FrameGeneratorCapturer* frame_generator_capturer);
+};
+
+class SendTest : public BaseTest {
+ public:
+ explicit SendTest(unsigned int timeout_ms);
+ SendTest(unsigned int timeout_ms, const FakeNetworkPipe::Config& config);
+
+ virtual bool ShouldCreateReceivers() const OVERRIDE;
+};
+
+class EndToEndTest : public BaseTest {
+ public:
+ explicit EndToEndTest(unsigned int timeout_ms);
+ EndToEndTest(unsigned int timeout_ms, const FakeNetworkPipe::Config& config);
+
+ virtual bool ShouldCreateReceivers() const OVERRIDE;
+};
+
+} // namespace test
+} // namespace webrtc
+
+#endif // WEBRTC_TEST_COMMON_CALL_TEST_H_
diff --git a/webrtc/test/rtp_rtcp_observer.h b/webrtc/test/rtp_rtcp_observer.h
index e448653..670a29d 100644
--- a/webrtc/test/rtp_rtcp_observer.h
+++ b/webrtc/test/rtp_rtcp_observer.h
@@ -16,6 +16,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
+#include "webrtc/test/direct_transport.h"
#include "webrtc/typedefs.h"
#include "webrtc/video_send_stream.h"
diff --git a/webrtc/test/webrtc_test_common.gyp b/webrtc/test/webrtc_test_common.gyp
index 556a445..8c8774f 100644
--- a/webrtc/test/webrtc_test_common.gyp
+++ b/webrtc/test/webrtc_test_common.gyp
@@ -14,6 +14,8 @@
'target_name': 'webrtc_test_common',
'type': 'static_library',
'sources': [
+ 'call_test.cc',
+ 'call_test.h',
'configurable_frame_size_encoder.cc',
'configurable_frame_size_encoder.h',
'direct_transport.cc',
@@ -54,10 +56,11 @@
'dependencies': [
'<(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)/modules/modules.gyp:video_capture_module',
'<(webrtc_root)/test/test.gyp:frame_generator',
'<(webrtc_root)/test/test.gyp:test_support',
+ '<(webrtc_root)/webrtc.gyp:webrtc',
],
},
{
diff --git a/webrtc/video/bitrate_estimator_tests.cc b/webrtc/video/bitrate_estimator_tests.cc
index f8b9060..d21de17 100644
--- a/webrtc/video/bitrate_estimator_tests.cc
+++ b/webrtc/video/bitrate_estimator_tests.cc
@@ -19,6 +19,7 @@
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
#include "webrtc/system_wrappers/interface/thread_annotations.h"
#include "webrtc/system_wrappers/interface/trace.h"
+#include "webrtc/test/call_test.h"
#include "webrtc/test/direct_transport.h"
#include "webrtc/test/encoder_settings.h"
#include "webrtc/test/fake_decoder.h"
@@ -30,12 +31,7 @@
static const int kTOFExtensionId = 4;
static const int kASTExtensionId = 5;
-static unsigned int kDefaultTimeoutMs = 30 * 1000;
-static const uint32_t kSendSsrc = 0x654321;
-static const uint32_t kReceiverLocalSsrc = 0x123456;
-static const uint8_t kSendPayloadType = 125;
-
-class BitrateEstimatorTest : public ::testing::Test {
+class BitrateEstimatorTest : public test::CallTest {
public:
BitrateEstimatorTest()
: receiver_trace_(),
@@ -43,7 +39,6 @@
receive_transport_(),
sender_call_(),
receiver_call_(),
- send_config_(),
receive_config_(),
streams_() {
}
@@ -68,11 +63,11 @@
receive_transport_.SetReceiver(sender_call_->Receiver());
send_config_ = sender_call_->GetDefaultSendConfig();
- send_config_.rtp.ssrcs.push_back(kSendSsrc);
+ send_config_.rtp.ssrcs.push_back(kSendSsrcs[0]);
// Encoders will be set separately per stream.
send_config_.encoder_settings.encoder = NULL;
send_config_.encoder_settings.payload_name = "FAKE";
- send_config_.encoder_settings.payload_type = kSendPayloadType;
+ send_config_.encoder_settings.payload_type = kFakeSendPayloadType;
video_streams_ = test::CreateVideoStreams(1);
receive_config_ = receiver_call_->GetDefaultReceiveConfig();
@@ -228,8 +223,6 @@
test::DirectTransport receive_transport_;
scoped_ptr<Call> sender_call_;
scoped_ptr<Call> receiver_call_;
- VideoSendStream::Config send_config_;
- std::vector<VideoStream> video_streams_;
VideoReceiveStream::Config receive_config_;
std::vector<Stream*> streams_;
};
diff --git a/webrtc/video/call_perf_tests.cc b/webrtc/video/call_perf_tests.cc
index fa3f238..b6e2b34 100644
--- a/webrtc/video/call_perf_tests.cc
+++ b/webrtc/video/call_perf_tests.cc
@@ -23,6 +23,7 @@
#include "webrtc/system_wrappers/interface/rtp_to_ntp.h"
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
#include "webrtc/system_wrappers/interface/thread_annotations.h"
+#include "webrtc/test/call_test.h"
#include "webrtc/test/direct_transport.h"
#include "webrtc/test/encoder_settings.h"
#include "webrtc/test/fake_audio_device.h"
@@ -42,61 +43,20 @@
namespace webrtc {
-static unsigned int kLongTimeoutMs = 120 * 1000;
-static const uint32_t kSendSsrc = 0x654321;
-static const uint32_t kReceiverLocalSsrc = 0x123456;
-static const uint8_t kSendPayloadType = 125;
-
-class CallPerfTest : public ::testing::Test {
- public:
- CallPerfTest()
- : send_stream_(NULL), fake_encoder_(Clock::GetRealTimeClock()) {}
-
+class CallPerfTest : public test::CallTest {
protected:
- void CreateTestConfig(Call* call) {
- send_config_ = call->GetDefaultSendConfig();
- send_config_.rtp.ssrcs.push_back(kSendSsrc);
- send_config_.encoder_settings.encoder = &fake_encoder_;
- send_config_.encoder_settings.payload_type = kSendPayloadType;
- send_config_.encoder_settings.payload_name = "FAKE";
- video_streams_ = test::CreateVideoStreams(1);
- }
-
- void RunVideoSendTest(Call* call,
- const VideoSendStream::Config& config,
- test::RtpRtcpObserver* observer) {
- send_stream_ = call->CreateVideoSendStream(config, video_streams_, NULL);
- scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
- test::FrameGeneratorCapturer::Create(
- send_stream_->Input(), 320, 240, 30, Clock::GetRealTimeClock()));
- send_stream_->Start();
- frame_generator_capturer->Start();
-
- EXPECT_EQ(kEventSignaled, observer->Wait());
-
- observer->StopSending();
- frame_generator_capturer->Stop();
- send_stream_->Stop();
- call->DestroyVideoSendStream(send_stream_);
- }
-
void TestMinTransmitBitrate(bool pad_to_min_bitrate);
void TestCaptureNtpTime(const FakeNetworkPipe::Config& net_config,
int threshold_ms,
int start_time_ms,
int run_time_ms);
-
- VideoSendStream::Config send_config_;
- std::vector<VideoStream> video_streams_;
- VideoSendStream* send_stream_;
- test::FakeEncoder fake_encoder_;
};
class SyncRtcpObserver : public test::RtpRtcpObserver {
public:
explicit SyncRtcpObserver(const FakeNetworkPipe::Config& config)
- : test::RtpRtcpObserver(kLongTimeoutMs, config),
+ : test::RtpRtcpObserver(CallPerfTest::kLongTimeoutMs, config),
crit_(CriticalSectionWrapper::CreateCriticalSection()) {}
virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
@@ -226,6 +186,31 @@
};
TEST_F(CallPerfTest, PlaysOutAudioAndVideoInSync) {
+ class AudioPacketReceiver : public PacketReceiver {
+ public:
+ AudioPacketReceiver(int channel, VoENetwork* voe_network)
+ : channel_(channel),
+ voe_network_(voe_network),
+ parser_(RtpHeaderParser::Create()) {}
+ virtual DeliveryStatus DeliverPacket(const uint8_t* packet,
+ size_t length) OVERRIDE {
+ int ret;
+ if (parser_->IsRtcp(packet, static_cast<int>(length))) {
+ ret = voe_network_->ReceivedRTCPPacket(
+ channel_, packet, static_cast<unsigned int>(length));
+ } else {
+ ret = voe_network_->ReceivedRTPPacket(
+ channel_, packet, static_cast<unsigned int>(length), PacketTime());
+ }
+ return ret == 0 ? DELIVERY_OK : DELIVERY_PACKET_ERROR;
+ }
+
+ private:
+ int channel_;
+ VoENetwork* voe_network_;
+ scoped_ptr<RtpHeaderParser> parser_;
+ };
+
VoiceEngine* voice_engine = VoiceEngine::Create();
VoEBase* voe_base = VoEBase::GetInterface(voice_engine);
VoECodec* voe_codec = VoECodec::GetInterface(voice_engine);
@@ -249,37 +234,12 @@
Call::Config receiver_config(observer.ReceiveTransport());
receiver_config.voice_engine = voice_engine;
- scoped_ptr<Call> sender_call(
- Call::Create(Call::Config(observer.SendTransport())));
- scoped_ptr<Call> receiver_call(Call::Create(receiver_config));
+ CreateCalls(Call::Config(observer.SendTransport()), receiver_config);
+
CodecInst isac = {103, "ISAC", 16000, 480, 1, 32000};
EXPECT_EQ(0, voe_codec->SetSendCodec(channel, isac));
- class VoicePacketReceiver : public PacketReceiver {
- public:
- VoicePacketReceiver(int channel, VoENetwork* voe_network)
- : channel_(channel),
- voe_network_(voe_network),
- parser_(RtpHeaderParser::Create()) {}
- virtual DeliveryStatus DeliverPacket(const uint8_t* packet,
- size_t length) OVERRIDE {
- int ret;
- if (parser_->IsRtcp(packet, static_cast<int>(length))) {
- ret = voe_network_->ReceivedRTCPPacket(
- channel_, packet, static_cast<unsigned int>(length));
- } else {
- ret = voe_network_->ReceivedRTPPacket(
- channel_, packet, static_cast<unsigned int>(length), PacketTime());
- }
- return ret == 0 ? DELIVERY_OK : DELIVERY_PACKET_ERROR;
- }
-
- private:
- int channel_;
- VoENetwork* voe_network_;
- scoped_ptr<RtpHeaderParser> parser_;
- } voe_packet_receiver(channel, voe_network);
-
+ AudioPacketReceiver voe_packet_receiver(channel, voe_network);
audio_observer.SetReceivers(&voe_packet_receiver, &voe_packet_receiver);
internal::TransportAdapter transport_adapter(audio_observer.SendTransport());
@@ -287,41 +247,21 @@
EXPECT_EQ(0,
voe_network->RegisterExternalTransport(channel, transport_adapter));
- observer.SetReceivers(receiver_call->Receiver(), sender_call->Receiver());
+ observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
test::FakeDecoder fake_decoder;
- CreateTestConfig(sender_call.get());
+ CreateSendConfig(1);
+ CreateMatchingReceiveConfigs();
- VideoReceiveStream::Config receive_config =
- receiver_call->GetDefaultReceiveConfig();
- assert(receive_config.codecs.empty());
- VideoCodec codec =
- test::CreateDecoderVideoCodec(send_config_.encoder_settings);
- receive_config.codecs.push_back(codec);
- assert(receive_config.external_decoders.empty());
- ExternalVideoDecoder decoder;
- decoder.decoder = &fake_decoder;
- decoder.payload_type = send_config_.encoder_settings.payload_type;
- receive_config.external_decoders.push_back(decoder);
- receive_config.rtp.remote_ssrc = send_config_.rtp.ssrcs[0];
- receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
- receive_config.renderer = &observer;
- receive_config.audio_channel_id = channel;
+ receive_config_.renderer = &observer;
+ receive_config_.audio_channel_id = channel;
- VideoSendStream* send_stream =
- sender_call->CreateVideoSendStream(send_config_, video_streams_, NULL);
- VideoReceiveStream* receive_stream =
- receiver_call->CreateVideoReceiveStream(receive_config);
- scoped_ptr<test::FrameGeneratorCapturer> capturer(
- test::FrameGeneratorCapturer::Create(send_stream->Input(),
- video_streams_[0].width,
- video_streams_[0].height,
- 30,
- Clock::GetRealTimeClock()));
- receive_stream->Start();
- send_stream->Start();
- capturer->Start();
+ CreateStreams();
+
+ CreateFrameGeneratorCapturer();
+
+ Start();
fake_audio_device.Start();
EXPECT_EQ(0, voe_base->StartPlayout(channel));
@@ -336,9 +276,7 @@
EXPECT_EQ(0, voe_base->StopPlayout(channel));
fake_audio_device.Stop();
- capturer->Stop();
- send_stream->Stop();
- receive_stream->Stop();
+ Stop();
observer.StopSending();
audio_observer.StopSending();
@@ -347,174 +285,126 @@
voe_codec->Release();
voe_network->Release();
voe_sync->Release();
- sender_call->DestroyVideoSendStream(send_stream);
- receiver_call->DestroyVideoReceiveStream(receive_stream);
+
+ DestroyStreams();
+
VoiceEngine::Delete(voice_engine);
}
-class CaptureNtpTimeObserver : public test::RtpRtcpObserver,
- public VideoRenderer {
- public:
- CaptureNtpTimeObserver(Clock* clock,
- const FakeNetworkPipe::Config& config,
- int threshold_ms,
- int start_time_ms,
- int run_time_ms)
- : RtpRtcpObserver(kLongTimeoutMs, config),
- clock_(clock),
- threshold_ms_(threshold_ms),
- start_time_ms_(start_time_ms),
- run_time_ms_(run_time_ms),
- creation_time_ms_(clock_->TimeInMilliseconds()),
- capturer_(NULL),
- rtp_start_timestamp_set_(false),
- rtp_start_timestamp_(0) {}
-
- virtual void RenderFrame(const I420VideoFrame& video_frame,
- int time_to_render_ms) OVERRIDE {
- if (video_frame.ntp_time_ms() <= 0) {
- // Haven't got enough RTCP SR in order to calculate the capture ntp time.
- return;
- }
-
- int64_t now_ms = clock_->TimeInMilliseconds();
- int64_t time_since_creation = now_ms - creation_time_ms_;
- if (time_since_creation < start_time_ms_) {
- // Wait for |start_time_ms_| before start measuring.
- return;
- }
-
- if (time_since_creation > run_time_ms_) {
- observation_complete_->Set();
- }
-
- FrameCaptureTimeList::iterator iter =
- capture_time_list_.find(video_frame.timestamp());
- EXPECT_TRUE(iter != capture_time_list_.end());
-
- // The real capture time has been wrapped to uint32_t before converted
- // to rtp timestamp in the sender side. So here we convert the estimated
- // capture time to a uint32_t 90k timestamp also for comparing.
- uint32_t estimated_capture_timestamp =
- 90 * static_cast<uint32_t>(video_frame.ntp_time_ms());
- uint32_t real_capture_timestamp = iter->second;
- int time_offset_ms = real_capture_timestamp - estimated_capture_timestamp;
- time_offset_ms = time_offset_ms / 90;
- std::stringstream ss;
- ss << time_offset_ms;
-
- webrtc::test::PrintResult("capture_ntp_time",
- "",
- "real - estimated",
- ss.str(),
- "ms",
- true);
- EXPECT_TRUE(std::abs(time_offset_ms) < threshold_ms_);
- }
-
- virtual Action OnSendRtp(const uint8_t* packet, size_t length) {
- RTPHeader header;
- EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
-
- if (!rtp_start_timestamp_set_) {
- // Calculate the rtp timestamp offset in order to calculate the real
- // capture time.
- uint32_t first_capture_timestamp =
- 90 * static_cast<uint32_t>(capturer_->first_frame_capture_time());
- rtp_start_timestamp_ = header.timestamp - first_capture_timestamp;
- rtp_start_timestamp_set_ = true;
- }
-
- uint32_t capture_timestamp = header.timestamp - rtp_start_timestamp_;
- capture_time_list_.insert(capture_time_list_.end(),
- std::make_pair(header.timestamp,
- capture_timestamp));
- return SEND_PACKET;
- }
-
- void SetCapturer(test::FrameGeneratorCapturer* capturer) {
- capturer_ = capturer;
- }
-
- private:
- Clock* clock_;
- int threshold_ms_;
- int start_time_ms_;
- int run_time_ms_;
- int64_t creation_time_ms_;
- test::FrameGeneratorCapturer* capturer_;
- bool rtp_start_timestamp_set_;
- uint32_t rtp_start_timestamp_;
- typedef std::map<uint32_t, uint32_t> FrameCaptureTimeList;
- FrameCaptureTimeList capture_time_list_;
-};
-
void CallPerfTest::TestCaptureNtpTime(const FakeNetworkPipe::Config& net_config,
int threshold_ms,
int start_time_ms,
int run_time_ms) {
- CaptureNtpTimeObserver observer(Clock::GetRealTimeClock(),
- net_config,
- threshold_ms,
- start_time_ms,
- run_time_ms);
+ class CaptureNtpTimeObserver : public test::EndToEndTest,
+ public VideoRenderer {
+ public:
+ CaptureNtpTimeObserver(const FakeNetworkPipe::Config& config,
+ int threshold_ms,
+ int start_time_ms,
+ int run_time_ms)
+ : EndToEndTest(kLongTimeoutMs, config),
+ clock_(Clock::GetRealTimeClock()),
+ threshold_ms_(threshold_ms),
+ start_time_ms_(start_time_ms),
+ run_time_ms_(run_time_ms),
+ creation_time_ms_(clock_->TimeInMilliseconds()),
+ capturer_(NULL),
+ rtp_start_timestamp_set_(false),
+ rtp_start_timestamp_(0) {}
- // Sender/receiver call.
- Call::Config receiver_config(observer.ReceiveTransport());
- scoped_ptr<Call> receiver_call(Call::Create(receiver_config));
- scoped_ptr<Call> sender_call(
- Call::Create(Call::Config(observer.SendTransport())));
- observer.SetReceivers(receiver_call->Receiver(), sender_call->Receiver());
+ private:
+ virtual void RenderFrame(const I420VideoFrame& video_frame,
+ int time_to_render_ms) OVERRIDE {
+ if (video_frame.ntp_time_ms() <= 0) {
+ // Haven't got enough RTCP SR in order to calculate the capture ntp
+ // time.
+ return;
+ }
- // Configure send stream.
- CreateTestConfig(sender_call.get());
- VideoSendStream* send_stream =
- sender_call->CreateVideoSendStream(send_config_, video_streams_, NULL);
- scoped_ptr<test::FrameGeneratorCapturer> capturer(
- test::FrameGeneratorCapturer::Create(send_stream->Input(),
- video_streams_[0].width,
- video_streams_[0].height,
- 30,
- Clock::GetRealTimeClock()));
- observer.SetCapturer(capturer.get());
+ int64_t now_ms = clock_->TimeInMilliseconds();
+ int64_t time_since_creation = now_ms - creation_time_ms_;
+ if (time_since_creation < start_time_ms_) {
+ // Wait for |start_time_ms_| before start measuring.
+ return;
+ }
- // Configure receive stream.
- VideoReceiveStream::Config receive_config =
- receiver_call->GetDefaultReceiveConfig();
- assert(receive_config.codecs.empty());
- VideoCodec codec =
- test::CreateDecoderVideoCodec(send_config_.encoder_settings);
- receive_config.codecs.push_back(codec);
- assert(receive_config.external_decoders.empty());
- ExternalVideoDecoder decoder;
- test::FakeDecoder fake_decoder;
- decoder.decoder = &fake_decoder;
- decoder.payload_type = send_config_.encoder_settings.payload_type;
- receive_config.external_decoders.push_back(decoder);
- receive_config.rtp.remote_ssrc = send_config_.rtp.ssrcs[0];
- receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
- receive_config.renderer = &observer;
- // Enable the receiver side rtt calculation.
- receive_config.rtp.rtcp_xr.receiver_reference_time_report = true;
- VideoReceiveStream* receive_stream =
- receiver_call->CreateVideoReceiveStream(receive_config);
+ if (time_since_creation > run_time_ms_) {
+ observation_complete_->Set();
+ }
- // Start the test
- receive_stream->Start();
- send_stream->Start();
- capturer->Start();
+ FrameCaptureTimeList::iterator iter =
+ capture_time_list_.find(video_frame.timestamp());
+ EXPECT_TRUE(iter != capture_time_list_.end());
- EXPECT_EQ(kEventSignaled, observer.Wait())
- << "Timed out while waiting for estimated capture ntp time to be "
- << "within bounds.";
+ // The real capture time has been wrapped to uint32_t before converted
+ // to rtp timestamp in the sender side. So here we convert the estimated
+ // capture time to a uint32_t 90k timestamp also for comparing.
+ uint32_t estimated_capture_timestamp =
+ 90 * static_cast<uint32_t>(video_frame.ntp_time_ms());
+ uint32_t real_capture_timestamp = iter->second;
+ int time_offset_ms = real_capture_timestamp - estimated_capture_timestamp;
+ time_offset_ms = time_offset_ms / 90;
+ std::stringstream ss;
+ ss << time_offset_ms;
- capturer->Stop();
- send_stream->Stop();
- receive_stream->Stop();
- observer.StopSending();
+ webrtc::test::PrintResult(
+ "capture_ntp_time", "", "real - estimated", ss.str(), "ms", true);
+ EXPECT_TRUE(std::abs(time_offset_ms) < threshold_ms_);
+ }
- sender_call->DestroyVideoSendStream(send_stream);
- receiver_call->DestroyVideoReceiveStream(receive_stream);
+ virtual Action OnSendRtp(const uint8_t* packet, size_t length) {
+ RTPHeader header;
+ EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
+
+ if (!rtp_start_timestamp_set_) {
+ // Calculate the rtp timestamp offset in order to calculate the real
+ // capture time.
+ uint32_t first_capture_timestamp =
+ 90 * static_cast<uint32_t>(capturer_->first_frame_capture_time());
+ rtp_start_timestamp_ = header.timestamp - first_capture_timestamp;
+ rtp_start_timestamp_set_ = true;
+ }
+
+ uint32_t capture_timestamp = header.timestamp - rtp_start_timestamp_;
+ capture_time_list_.insert(
+ capture_time_list_.end(),
+ std::make_pair(header.timestamp, capture_timestamp));
+ return SEND_PACKET;
+ }
+
+ virtual void OnFrameGeneratorCapturerCreated(
+ test::FrameGeneratorCapturer* frame_generator_capturer) OVERRIDE {
+ capturer_ = frame_generator_capturer;
+ }
+
+ virtual void ModifyConfigs(
+ VideoSendStream::Config* send_config,
+ VideoReceiveStream::Config* receive_config,
+ std::vector<VideoStream>* video_streams) OVERRIDE {
+ receive_config->renderer = this;
+ // Enable the receiver side rtt calculation.
+ receive_config->rtp.rtcp_xr.receiver_reference_time_report = true;
+ }
+
+ virtual void PerformTest() OVERRIDE {
+ EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for "
+ "estimated capture NTP time to be "
+ "within bounds.";
+ }
+
+ Clock* clock_;
+ int threshold_ms_;
+ int start_time_ms_;
+ int run_time_ms_;
+ int64_t creation_time_ms_;
+ test::FrameGeneratorCapturer* capturer_;
+ bool rtp_start_timestamp_set_;
+ uint32_t rtp_start_timestamp_;
+ typedef std::map<uint32_t, uint32_t> FrameCaptureTimeList;
+ FrameCaptureTimeList capture_time_list_;
+ } test(net_config, threshold_ms, start_time_ms, run_time_ms);
+
+ RunBaseTest(&test);
}
TEST_F(CallPerfTest, CaptureNtpTimeWithNetworkDelay) {
@@ -542,26 +432,32 @@
TEST_F(CallPerfTest, RegisterCpuOveruseObserver) {
// Verifies that either a normal or overuse callback is triggered.
- class OveruseCallbackObserver : public test::RtpRtcpObserver,
+ class OveruseCallbackObserver : public test::SendTest,
public webrtc::OveruseCallback {
public:
- OveruseCallbackObserver() : RtpRtcpObserver(kLongTimeoutMs) {}
+ OveruseCallbackObserver() : SendTest(kLongTimeoutMs) {}
virtual void OnOveruse() OVERRIDE {
observation_complete_->Set();
}
+
virtual void OnNormalUse() OVERRIDE {
observation_complete_->Set();
}
- };
- OveruseCallbackObserver observer;
- Call::Config call_config(observer.SendTransport());
- call_config.overuse_callback = &observer;
- scoped_ptr<Call> call(Call::Create(call_config));
+ virtual Call::Config GetSenderCallConfig() OVERRIDE {
+ Call::Config config(SendTransport());
+ config.overuse_callback = this;
+ return config;
+ }
- CreateTestConfig(call.get());
- RunVideoSendTest(call.get(), send_config_, &observer);
+ virtual void PerformTest() OVERRIDE {
+ EXPECT_EQ(kEventSignaled, Wait())
+ << "Timed out before receiving an overuse callback.";
+ }
+ } test;
+
+ RunBaseTest(&test);
}
void CallPerfTest::TestMinTransmitBitrate(bool pad_to_min_bitrate) {
@@ -570,15 +466,16 @@
static const int kMinAcceptableTransmitBitrate = 130;
static const int kMaxAcceptableTransmitBitrate = 170;
static const int kNumBitrateObservationsInRange = 100;
- class BitrateObserver : public test::RtpRtcpObserver, public PacketReceiver {
+ class BitrateObserver : public test::EndToEndTest, public PacketReceiver {
public:
explicit BitrateObserver(bool using_min_transmit_bitrate)
- : test::RtpRtcpObserver(kLongTimeoutMs),
+ : EndToEndTest(kLongTimeoutMs),
send_stream_(NULL),
send_transport_receiver_(NULL),
- using_min_transmit_bitrate_(using_min_transmit_bitrate),
+ pad_to_min_bitrate_(using_min_transmit_bitrate),
num_bitrate_observations_in_range_(0) {}
+ private:
virtual void SetReceivers(PacketReceiver* send_transport_receiver,
PacketReceiver* receive_transport_receiver)
OVERRIDE {
@@ -586,11 +483,6 @@
test::RtpRtcpObserver::SetReceivers(this, receive_transport_receiver);
}
- void SetSendStream(VideoSendStream* send_stream) {
- send_stream_ = send_stream;
- }
-
- private:
virtual DeliveryStatus DeliverPacket(const uint8_t* packet,
size_t length) OVERRIDE {
VideoSendStream::Stats stats = send_stream_->GetStats();
@@ -600,13 +492,13 @@
if (bitrate_kbps > 0) {
test::PrintResult(
"bitrate_stats_",
- (using_min_transmit_bitrate_ ? "min_transmit_bitrate"
- : "without_min_transmit_bitrate"),
+ (pad_to_min_bitrate_ ? "min_transmit_bitrate"
+ : "without_min_transmit_bitrate"),
"bitrate_kbps",
static_cast<size_t>(bitrate_kbps),
"kbps",
false);
- if (using_min_transmit_bitrate_) {
+ if (pad_to_min_bitrate_) {
if (bitrate_kbps > kMinAcceptableTransmitBitrate &&
bitrate_kbps < kMaxAcceptableTransmitBitrate) {
++num_bitrate_observations_in_range_;
@@ -626,66 +518,35 @@
return send_transport_receiver_->DeliverPacket(packet, length);
}
+ virtual void OnStreamsCreated(VideoSendStream* send_stream,
+ VideoReceiveStream* receive_stream) {
+ send_stream_ = send_stream;
+ }
+
+ virtual void ModifyConfigs(
+ VideoSendStream::Config* send_config,
+ VideoReceiveStream::Config* receive_config,
+ std::vector<VideoStream>* video_streams) OVERRIDE {
+ if (pad_to_min_bitrate_) {
+ send_config->rtp.min_transmit_bitrate_bps = kMinTransmitBitrateBps;
+ } else {
+ assert(send_config->rtp.min_transmit_bitrate_bps == 0);
+ }
+ }
+
+ virtual void PerformTest() OVERRIDE {
+ EXPECT_EQ(kEventSignaled, Wait())
+ << "Timeout while waiting for send-bitrate stats.";
+ }
+
VideoSendStream* send_stream_;
PacketReceiver* send_transport_receiver_;
- const bool using_min_transmit_bitrate_;
+ const bool pad_to_min_bitrate_;
int num_bitrate_observations_in_range_;
- } observer(pad_to_min_bitrate);
+ } test(pad_to_min_bitrate);
- scoped_ptr<Call> sender_call(
- Call::Create(Call::Config(observer.SendTransport())));
- scoped_ptr<Call> receiver_call(
- Call::Create(Call::Config(observer.ReceiveTransport())));
-
- CreateTestConfig(sender_call.get());
fake_encoder_.SetMaxBitrate(kMaxEncodeBitrateKbps);
-
- observer.SetReceivers(receiver_call->Receiver(), sender_call->Receiver());
-
- if (pad_to_min_bitrate) {
- send_config_.rtp.min_transmit_bitrate_bps = kMinTransmitBitrateBps;
- } else {
- assert(send_config_.rtp.min_transmit_bitrate_bps == 0);
- }
-
- VideoReceiveStream::Config receive_config =
- receiver_call->GetDefaultReceiveConfig();
- receive_config.codecs.clear();
- VideoCodec codec =
- test::CreateDecoderVideoCodec(send_config_.encoder_settings);
- receive_config.codecs.push_back(codec);
- test::FakeDecoder fake_decoder;
- ExternalVideoDecoder decoder;
- decoder.decoder = &fake_decoder;
- decoder.payload_type = send_config_.encoder_settings.payload_type;
- receive_config.external_decoders.push_back(decoder);
- receive_config.rtp.remote_ssrc = send_config_.rtp.ssrcs[0];
- receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
-
- VideoSendStream* send_stream =
- sender_call->CreateVideoSendStream(send_config_, video_streams_, NULL);
- VideoReceiveStream* receive_stream =
- receiver_call->CreateVideoReceiveStream(receive_config);
- scoped_ptr<test::FrameGeneratorCapturer> capturer(
- test::FrameGeneratorCapturer::Create(send_stream->Input(),
- video_streams_[0].width,
- video_streams_[0].height,
- 30,
- Clock::GetRealTimeClock()));
- observer.SetSendStream(send_stream);
- receive_stream->Start();
- send_stream->Start();
- capturer->Start();
-
- EXPECT_EQ(kEventSignaled, observer.Wait())
- << "Timeout while waiting for send-bitrate stats.";
-
- send_stream->Stop();
- receive_stream->Stop();
- observer.StopSending();
- capturer->Stop();
- sender_call->DestroyVideoSendStream(send_stream);
- receiver_call->DestroyVideoReceiveStream(receive_stream);
+ RunBaseTest(&test);
}
TEST_F(CallPerfTest, PadsToMinTransmitBitrate) { TestMinTransmitBitrate(true); }
diff --git a/webrtc/video/call_tests.cc b/webrtc/video/call_tests.cc
deleted file mode 100644
index 5bcf115..0000000
--- a/webrtc/video/call_tests.cc
+++ /dev/null
@@ -1,1612 +0,0 @@
-/*
- * 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 <assert.h>
-
-#include <algorithm>
-#include <map>
-#include <sstream>
-#include <string>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-#include "webrtc/call.h"
-#include "webrtc/frame_callback.h"
-#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
-#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
-#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
-#include "webrtc/system_wrappers/interface/event_wrapper.h"
-#include "webrtc/system_wrappers/interface/scoped_ptr.h"
-#include "webrtc/system_wrappers/interface/sleep.h"
-#include "webrtc/test/direct_transport.h"
-#include "webrtc/test/encoder_settings.h"
-#include "webrtc/test/fake_audio_device.h"
-#include "webrtc/test/fake_decoder.h"
-#include "webrtc/test/fake_encoder.h"
-#include "webrtc/test/frame_generator.h"
-#include "webrtc/test/frame_generator_capturer.h"
-#include "webrtc/test/null_transport.h"
-#include "webrtc/test/rtp_rtcp_observer.h"
-#include "webrtc/test/testsupport/fileutils.h"
-#include "webrtc/test/testsupport/perf_test.h"
-#include "webrtc/video/transport_adapter.h"
-
-namespace webrtc {
-
-static unsigned int kDefaultTimeoutMs = 30 * 1000;
-static unsigned int kLongTimeoutMs = 120 * 1000;
-static const uint32_t kSendSsrc = 0x654321;
-static const uint32_t kSendRtxSsrc = 0x424242;
-static const uint32_t kReceiverLocalSsrc = 0x123456;
-static const uint8_t kSendPayloadType = 125;
-static const uint8_t kSendRtxPayloadType = 126;
-static const int kRedPayloadType = 118;
-static const int kUlpfecPayloadType = 119;
-
-class CallTest : public ::testing::Test {
- public:
- CallTest()
- : send_stream_(NULL),
- receive_stream_(NULL),
- fake_encoder_(Clock::GetRealTimeClock()) {}
-
- virtual ~CallTest() {
- EXPECT_EQ(NULL, send_stream_);
- EXPECT_EQ(NULL, receive_stream_);
- }
-
- protected:
- void CreateCalls(const Call::Config& sender_config,
- const Call::Config& receiver_config) {
- sender_call_.reset(Call::Create(sender_config));
- receiver_call_.reset(Call::Create(receiver_config));
- }
-
- void CreateTestConfigs() {
- send_config_ = sender_call_->GetDefaultSendConfig();
- receive_config_ = receiver_call_->GetDefaultReceiveConfig();
-
- send_config_.rtp.ssrcs.push_back(kSendSsrc);
- send_config_.encoder_settings.encoder = &fake_encoder_;
- send_config_.encoder_settings.payload_name = "FAKE";
- send_config_.encoder_settings.payload_type = kSendPayloadType;
- video_streams_ = test::CreateVideoStreams(1);
-
- assert(receive_config_.codecs.empty());
- VideoCodec codec =
- test::CreateDecoderVideoCodec(send_config_.encoder_settings);
- receive_config_.codecs.push_back(codec);
- ExternalVideoDecoder decoder;
- decoder.decoder = &fake_decoder_;
- decoder.payload_type = send_config_.encoder_settings.payload_type;
- receive_config_.external_decoders.push_back(decoder);
- receive_config_.rtp.remote_ssrc = send_config_.rtp.ssrcs[0];
- receive_config_.rtp.local_ssrc = kReceiverLocalSsrc;
- }
-
- void CreateStreams() {
- assert(send_stream_ == NULL);
- assert(receive_stream_ == NULL);
-
- send_stream_ =
- sender_call_->CreateVideoSendStream(send_config_, video_streams_, NULL);
- receive_stream_ = receiver_call_->CreateVideoReceiveStream(receive_config_);
- }
-
- void CreateFrameGenerator() {
- frame_generator_capturer_.reset(
- test::FrameGeneratorCapturer::Create(send_stream_->Input(),
- video_streams_[0].width,
- video_streams_[0].height,
- 30,
- Clock::GetRealTimeClock()));
- }
-
- void StartSending() {
- receive_stream_->Start();
- send_stream_->Start();
- if (frame_generator_capturer_.get() != NULL)
- frame_generator_capturer_->Start();
- }
-
- void StopSending() {
- if (frame_generator_capturer_.get() != NULL)
- frame_generator_capturer_->Stop();
- if (send_stream_ != NULL)
- send_stream_->Stop();
- if (receive_stream_ != NULL)
- receive_stream_->Stop();
- }
-
- void DestroyStreams() {
- if (send_stream_ != NULL)
- sender_call_->DestroyVideoSendStream(send_stream_);
- if (receive_stream_ != NULL)
- receiver_call_->DestroyVideoReceiveStream(receive_stream_);
- send_stream_ = NULL;
- receive_stream_ = NULL;
- }
-
- void DecodesRetransmittedFrame(bool retransmit_over_rtx);
- void ReceivesPliAndRecovers(int rtp_history_ms);
- void RespectsRtcpMode(newapi::RtcpMode rtcp_mode);
- void TestXrReceiverReferenceTimeReport(bool enable_rrtr);
-
- scoped_ptr<Call> sender_call_;
- scoped_ptr<Call> receiver_call_;
-
- VideoSendStream::Config send_config_;
- std::vector<VideoStream> video_streams_;
- VideoReceiveStream::Config receive_config_;
-
- VideoSendStream* send_stream_;
- VideoReceiveStream* receive_stream_;
-
- scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer_;
-
- test::FakeEncoder fake_encoder_;
- test::FakeDecoder fake_decoder_;
-};
-
-class NackObserver : public test::RtpRtcpObserver {
- static const int kNumberOfNacksToObserve = 2;
- static const int kLossBurstSize = 2;
- static const int kPacketsBetweenLossBursts = 9;
-
- public:
- NackObserver()
- : test::RtpRtcpObserver(kLongTimeoutMs),
- rtp_parser_(RtpHeaderParser::Create()),
- sent_rtp_packets_(0),
- packets_left_to_drop_(0),
- nacks_left_(kNumberOfNacksToObserve) {}
-
- private:
- virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
- RTPHeader header;
- EXPECT_TRUE(rtp_parser_->Parse(packet, static_cast<int>(length), &header));
-
- // Never drop retransmitted packets.
- if (dropped_packets_.find(header.sequenceNumber) !=
- dropped_packets_.end()) {
- retransmitted_packets_.insert(header.sequenceNumber);
- if (nacks_left_ == 0 &&
- retransmitted_packets_.size() == dropped_packets_.size()) {
- observation_complete_->Set();
- }
- return SEND_PACKET;
- }
-
- ++sent_rtp_packets_;
-
- // Enough NACKs received, stop dropping packets.
- if (nacks_left_ == 0)
- return SEND_PACKET;
-
- // Check if it's time for a new loss burst.
- if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
- packets_left_to_drop_ = kLossBurstSize;
-
- if (packets_left_to_drop_ > 0) {
- --packets_left_to_drop_;
- dropped_packets_.insert(header.sequenceNumber);
- return DROP_PACKET;
- }
-
- return SEND_PACKET;
- }
-
- virtual Action OnReceiveRtcp(const uint8_t* packet, size_t length) OVERRIDE {
- RTCPUtility::RTCPParserV2 parser(packet, length, true);
- EXPECT_TRUE(parser.IsValid());
-
- RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
- while (packet_type != RTCPUtility::kRtcpNotValidCode) {
- if (packet_type == RTCPUtility::kRtcpRtpfbNackCode) {
- --nacks_left_;
- break;
- }
- packet_type = parser.Iterate();
- }
- return SEND_PACKET;
- }
-
- private:
- scoped_ptr<RtpHeaderParser> rtp_parser_;
- std::set<uint16_t> dropped_packets_;
- std::set<uint16_t> retransmitted_packets_;
- uint64_t sent_rtp_packets_;
- int packets_left_to_drop_;
- int nacks_left_;
-};
-
-TEST_F(CallTest, ReceiverCanBeStartedTwice) {
- test::NullTransport transport;
- CreateCalls(Call::Config(&transport), Call::Config(&transport));
-
- CreateTestConfigs();
- CreateStreams();
-
- receive_stream_->Start();
- receive_stream_->Start();
-
- DestroyStreams();
-}
-
-TEST_F(CallTest, ReceiverCanBeStoppedTwice) {
- test::NullTransport transport;
- CreateCalls(Call::Config(&transport), Call::Config(&transport));
-
- CreateTestConfigs();
- CreateStreams();
-
- receive_stream_->Stop();
- receive_stream_->Stop();
-
- DestroyStreams();
-}
-
-TEST_F(CallTest, RendersSingleDelayedFrame) {
- static const int kWidth = 320;
- static const int kHeight = 240;
- // This constant is chosen to be higher than the timeout in the video_render
- // module. This makes sure that frames aren't dropped if there are no other
- // frames in the queue.
- static const int kDelayRenderCallbackMs = 1000;
-
- class Renderer : public VideoRenderer {
- public:
- Renderer() : event_(EventWrapper::Create()) {}
-
- virtual void RenderFrame(const I420VideoFrame& video_frame,
- int /*time_to_render_ms*/) OVERRIDE {
- event_->Set();
- }
-
- EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
-
- scoped_ptr<EventWrapper> event_;
- } renderer;
-
- class TestFrameCallback : public I420FrameCallback {
- public:
- TestFrameCallback() : event_(EventWrapper::Create()) {}
-
- EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
-
- private:
- virtual void FrameCallback(I420VideoFrame* frame) OVERRIDE {
- SleepMs(kDelayRenderCallbackMs);
- event_->Set();
- }
-
- scoped_ptr<EventWrapper> event_;
- };
-
- test::DirectTransport sender_transport, receiver_transport;
-
- CreateCalls(Call::Config(&sender_transport),
- Call::Config(&receiver_transport));
-
- sender_transport.SetReceiver(receiver_call_->Receiver());
- receiver_transport.SetReceiver(sender_call_->Receiver());
-
- CreateTestConfigs();
-
- TestFrameCallback pre_render_callback;
- receive_config_.pre_render_callback = &pre_render_callback;
- receive_config_.renderer = &renderer;
-
- CreateStreams();
- StartSending();
-
- // Create frames that are smaller than the send width/height, this is done to
- // check that the callbacks are done after processing video.
- scoped_ptr<test::FrameGenerator> frame_generator(
- test::FrameGenerator::Create(kWidth, kHeight));
- send_stream_->Input()->SwapFrame(frame_generator->NextFrame());
- EXPECT_EQ(kEventSignaled, pre_render_callback.Wait())
- << "Timed out while waiting for pre-render callback.";
- EXPECT_EQ(kEventSignaled, renderer.Wait())
- << "Timed out while waiting for the frame to render.";
-
- StopSending();
-
- sender_transport.StopSending();
- receiver_transport.StopSending();
-
- DestroyStreams();
-}
-
-TEST_F(CallTest, TransmitsFirstFrame) {
- class Renderer : public VideoRenderer {
- public:
- Renderer() : event_(EventWrapper::Create()) {}
-
- virtual void RenderFrame(const I420VideoFrame& video_frame,
- int /*time_to_render_ms*/) OVERRIDE {
- event_->Set();
- }
-
- EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
-
- scoped_ptr<EventWrapper> event_;
- } renderer;
-
- test::DirectTransport sender_transport, receiver_transport;
-
- CreateCalls(Call::Config(&sender_transport),
- Call::Config(&receiver_transport));
-
- sender_transport.SetReceiver(receiver_call_->Receiver());
- receiver_transport.SetReceiver(sender_call_->Receiver());
-
- CreateTestConfigs();
- receive_config_.renderer = &renderer;
-
- CreateStreams();
- StartSending();
-
- scoped_ptr<test::FrameGenerator> frame_generator(test::FrameGenerator::Create(
- video_streams_[0].width, video_streams_[0].height));
- send_stream_->Input()->SwapFrame(frame_generator->NextFrame());
-
- EXPECT_EQ(kEventSignaled, renderer.Wait())
- << "Timed out while waiting for the frame to render.";
-
- StopSending();
-
- sender_transport.StopSending();
- receiver_transport.StopSending();
-
- DestroyStreams();
-}
-
-TEST_F(CallTest, ReceiverUsesLocalSsrc) {
- class SyncRtcpObserver : public test::RtpRtcpObserver {
- public:
- SyncRtcpObserver() : test::RtpRtcpObserver(kDefaultTimeoutMs) {}
-
- virtual Action OnReceiveRtcp(const uint8_t* packet,
- size_t length) OVERRIDE {
- RTCPUtility::RTCPParserV2 parser(packet, length, true);
- EXPECT_TRUE(parser.IsValid());
- uint32_t ssrc = 0;
- ssrc |= static_cast<uint32_t>(packet[4]) << 24;
- ssrc |= static_cast<uint32_t>(packet[5]) << 16;
- ssrc |= static_cast<uint32_t>(packet[6]) << 8;
- ssrc |= static_cast<uint32_t>(packet[7]) << 0;
- EXPECT_EQ(kReceiverLocalSsrc, ssrc);
- observation_complete_->Set();
-
- return SEND_PACKET;
- }
- } observer;
-
- CreateCalls(Call::Config(observer.SendTransport()),
- Call::Config(observer.ReceiveTransport()));
-
- observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
-
- CreateTestConfigs();
-
- CreateStreams();
- CreateFrameGenerator();
- StartSending();
-
- EXPECT_EQ(kEventSignaled, observer.Wait())
- << "Timed out while waiting for a receiver RTCP packet to be sent.";
-
- StopSending();
-
- observer.StopSending();
-
- DestroyStreams();
-}
-
-TEST_F(CallTest, ReceivesAndRetransmitsNack) {
- NackObserver observer;
-
- CreateCalls(Call::Config(observer.SendTransport()),
- Call::Config(observer.ReceiveTransport()));
-
- observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
-
- CreateTestConfigs();
- int rtp_history_ms = 1000;
- send_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
- receive_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
-
- CreateStreams();
- CreateFrameGenerator();
- StartSending();
-
- // Wait() waits for an event triggered when NACKs have been received, NACKed
- // packets retransmitted and frames rendered again.
- EXPECT_EQ(kEventSignaled, observer.Wait());
-
- StopSending();
-
- observer.StopSending();
-
- DestroyStreams();
-}
-
-// TODO(pbos): Flaky, webrtc:3269
-TEST_F(CallTest, DISABLED_CanReceiveFec) {
- class FecRenderObserver : public test::RtpRtcpObserver, public VideoRenderer {
- public:
- FecRenderObserver()
- : RtpRtcpObserver(kDefaultTimeoutMs),
- state_(kFirstPacket),
- protected_sequence_number_(0),
- protected_frame_timestamp_(0) {}
-
- private:
- virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE
- EXCLUSIVE_LOCKS_REQUIRED(crit_) {
- RTPHeader header;
- EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
-
- EXPECT_EQ(kRedPayloadType, header.payloadType);
- int encapsulated_payload_type =
- static_cast<int>(packet[header.headerLength]);
- if (encapsulated_payload_type != kSendPayloadType)
- EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
-
- switch(state_) {
- case kFirstPacket:
- state_ = kDropEveryOtherPacketUntilFec;
- break;
- case kDropEveryOtherPacketUntilFec:
- if (encapsulated_payload_type == kUlpfecPayloadType) {
- state_ = kDropNextMediaPacket;
- return SEND_PACKET;
- }
- if (header.sequenceNumber % 2 == 0)
- return DROP_PACKET;
- break;
- case kDropNextMediaPacket:
- if (encapsulated_payload_type == kSendPayloadType) {
- protected_sequence_number_ = header.sequenceNumber;
- protected_frame_timestamp_ = header.timestamp;
- state_ = kProtectedPacketDropped;
- return DROP_PACKET;
- }
- break;
- case kProtectedPacketDropped:
- EXPECT_NE(header.sequenceNumber, protected_sequence_number_)
- << "Protected packet retransmitted. Should not happen with FEC.";
- break;
- }
-
- return SEND_PACKET;
- }
-
- virtual void RenderFrame(const I420VideoFrame& video_frame,
- int time_to_render_ms) OVERRIDE {
- CriticalSectionScoped lock(crit_.get());
- // Rendering frame with timestamp associated with dropped packet -> FEC
- // protection worked.
- if (state_ == kProtectedPacketDropped &&
- video_frame.timestamp() == protected_frame_timestamp_) {
- observation_complete_->Set();
- }
- }
-
- enum {
- kFirstPacket,
- kDropEveryOtherPacketUntilFec,
- kDropNextMediaPacket,
- kProtectedPacketDropped,
- } state_;
-
- uint32_t protected_sequence_number_ GUARDED_BY(crit_);
- uint32_t protected_frame_timestamp_ GUARDED_BY(crit_);
- } observer;
-
- CreateCalls(Call::Config(observer.SendTransport()),
- Call::Config(observer.ReceiveTransport()));
-
- observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
-
- CreateTestConfigs();
- // TODO(pbos): Run this test with combined NACK/FEC enabled as well.
- // int rtp_history_ms = 1000;
- // receive_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
- // send_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
- send_config_.rtp.fec.red_payload_type = kRedPayloadType;
- send_config_.rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
-
- receive_config_.rtp.fec.red_payload_type = kRedPayloadType;
- receive_config_.rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
- receive_config_.renderer = &observer;
-
- CreateStreams();
- CreateFrameGenerator();
- StartSending();
-
- // Wait() waits for an event triggered when NACKs have been received, NACKed
- // packets retransmitted and frames rendered again.
- EXPECT_EQ(kEventSignaled, observer.Wait());
-
- StopSending();
-
- observer.StopSending();
-
- DestroyStreams();
-}
-
-// This test drops second RTP packet with a marker bit set, makes sure it's
-// retransmitted and renders. Retransmission SSRCs are also checked.
-void CallTest::DecodesRetransmittedFrame(bool retransmit_over_rtx) {
- static const int kDroppedFrameNumber = 2;
- class RetransmissionObserver : public test::RtpRtcpObserver,
- public I420FrameCallback {
- public:
- RetransmissionObserver(bool expect_rtx)
- : RtpRtcpObserver(kDefaultTimeoutMs),
- retransmission_ssrc_(expect_rtx ? kSendRtxSsrc : kSendSsrc),
- retransmission_payload_type_(expect_rtx ? kSendRtxPayloadType
- : kSendPayloadType),
- marker_bits_observed_(0),
- retransmitted_timestamp_(0),
- frame_retransmitted_(false) {}
-
- private:
- virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
- RTPHeader header;
- EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
-
- if (header.timestamp == retransmitted_timestamp_) {
- EXPECT_EQ(retransmission_ssrc_, header.ssrc);
- EXPECT_EQ(retransmission_payload_type_, header.payloadType);
- frame_retransmitted_ = true;
- return SEND_PACKET;
- }
-
- EXPECT_EQ(kSendSsrc, header.ssrc);
- EXPECT_EQ(kSendPayloadType, header.payloadType);
-
- // Found the second frame's final packet, drop this and expect a
- // retransmission.
- if (header.markerBit && ++marker_bits_observed_ == kDroppedFrameNumber) {
- retransmitted_timestamp_ = header.timestamp;
- return DROP_PACKET;
- }
-
- return SEND_PACKET;
- }
-
- virtual void FrameCallback(I420VideoFrame* frame) OVERRIDE {
- CriticalSectionScoped lock(crit_.get());
- if (frame->timestamp() == retransmitted_timestamp_) {
- EXPECT_TRUE(frame_retransmitted_);
- observation_complete_->Set();
- }
- }
-
- const uint32_t retransmission_ssrc_;
- const int retransmission_payload_type_;
- int marker_bits_observed_;
- uint32_t retransmitted_timestamp_;
- bool frame_retransmitted_;
- } observer(retransmit_over_rtx);
-
- CreateCalls(Call::Config(observer.SendTransport()),
- Call::Config(observer.ReceiveTransport()));
-
- observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
-
- CreateTestConfigs();
- send_config_.rtp.nack.rtp_history_ms =
- receive_config_.rtp.nack.rtp_history_ms = 1000;
- if (retransmit_over_rtx) {
- send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrc);
- send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
- int payload_type = send_config_.encoder_settings.payload_type;
- receive_config_.rtp.rtx[payload_type].ssrc = kSendRtxSsrc;
- receive_config_.rtp.rtx[payload_type].payload_type = kSendRtxPayloadType;
- }
- receive_config_.pre_render_callback = &observer;
-
- CreateStreams();
- CreateFrameGenerator();
- StartSending();
-
- EXPECT_EQ(kEventSignaled, observer.Wait())
- << "Timed out while waiting for retransmission to render.";
-
- StopSending();
- observer.StopSending();
- DestroyStreams();
-}
-
-TEST_F(CallTest, DecodesRetransmittedFrame) {
- DecodesRetransmittedFrame(false);
-}
-
-TEST_F(CallTest, DecodesRetransmittedFrameOverRtx) {
- DecodesRetransmittedFrame(true);
-}
-
-TEST_F(CallTest, UsesFrameCallbacks) {
- static const int kWidth = 320;
- static const int kHeight = 240;
-
- class Renderer : public VideoRenderer {
- public:
- Renderer() : event_(EventWrapper::Create()) {}
-
- virtual void RenderFrame(const I420VideoFrame& video_frame,
- int /*time_to_render_ms*/) OVERRIDE {
- EXPECT_EQ(0, *video_frame.buffer(kYPlane))
- << "Rendered frame should have zero luma which is applied by the "
- "pre-render callback.";
- event_->Set();
- }
-
- EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
- scoped_ptr<EventWrapper> event_;
- } renderer;
-
- class TestFrameCallback : public I420FrameCallback {
- public:
- TestFrameCallback(int expected_luma_byte, int next_luma_byte)
- : event_(EventWrapper::Create()),
- expected_luma_byte_(expected_luma_byte),
- next_luma_byte_(next_luma_byte) {}
-
- EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
-
- private:
- virtual void FrameCallback(I420VideoFrame* frame) {
- EXPECT_EQ(kWidth, frame->width())
- << "Width not as expected, callback done before resize?";
- EXPECT_EQ(kHeight, frame->height())
- << "Height not as expected, callback done before resize?";
-
- // Previous luma specified, observed luma should be fairly close.
- if (expected_luma_byte_ != -1) {
- EXPECT_NEAR(expected_luma_byte_, *frame->buffer(kYPlane), 10);
- }
-
- memset(frame->buffer(kYPlane),
- next_luma_byte_,
- frame->allocated_size(kYPlane));
-
- event_->Set();
- }
-
- scoped_ptr<EventWrapper> event_;
- int expected_luma_byte_;
- int next_luma_byte_;
- };
-
- TestFrameCallback pre_encode_callback(-1, 255); // Changes luma to 255.
- TestFrameCallback pre_render_callback(255, 0); // Changes luma from 255 to 0.
-
- test::DirectTransport sender_transport, receiver_transport;
-
- CreateCalls(Call::Config(&sender_transport),
- Call::Config(&receiver_transport));
-
- sender_transport.SetReceiver(receiver_call_->Receiver());
- receiver_transport.SetReceiver(sender_call_->Receiver());
-
- CreateTestConfigs();
- scoped_ptr<VP8Encoder> encoder(VP8Encoder::Create());
- send_config_.encoder_settings.encoder = encoder.get();
- send_config_.encoder_settings.payload_name = "VP8";
- ASSERT_EQ(1u, video_streams_.size()) << "Test setup error.";
- video_streams_[0].width = kWidth;
- video_streams_[0].height = kHeight;
- send_config_.pre_encode_callback = &pre_encode_callback;
- receive_config_.codecs.clear();
- VideoCodec codec =
- test::CreateDecoderVideoCodec(send_config_.encoder_settings);
- receive_config_.external_decoders.clear();
- receive_config_.codecs.push_back(codec);
- receive_config_.pre_render_callback = &pre_render_callback;
- receive_config_.renderer = &renderer;
-
- CreateStreams();
- StartSending();
-
- // Create frames that are smaller than the send width/height, this is done to
- // check that the callbacks are done after processing video.
- scoped_ptr<test::FrameGenerator> frame_generator(
- test::FrameGenerator::Create(kWidth / 2, kHeight / 2));
- send_stream_->Input()->SwapFrame(frame_generator->NextFrame());
-
- EXPECT_EQ(kEventSignaled, pre_encode_callback.Wait())
- << "Timed out while waiting for pre-encode callback.";
- EXPECT_EQ(kEventSignaled, pre_render_callback.Wait())
- << "Timed out while waiting for pre-render callback.";
- EXPECT_EQ(kEventSignaled, renderer.Wait())
- << "Timed out while waiting for the frame to render.";
-
- StopSending();
-
- sender_transport.StopSending();
- receiver_transport.StopSending();
-
- DestroyStreams();
-}
-
-class PliObserver : public test::RtpRtcpObserver, public VideoRenderer {
- static const int kInverseDropProbability = 16;
-
- public:
- explicit PliObserver(bool nack_enabled)
- : test::RtpRtcpObserver(kLongTimeoutMs),
- nack_enabled_(nack_enabled),
- highest_dropped_timestamp_(0),
- frames_to_drop_(0),
- received_pli_(false) {}
-
- virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
- RTPHeader header;
- EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
-
- // Drop all retransmitted packets to force a PLI.
- if (header.timestamp <= highest_dropped_timestamp_)
- return DROP_PACKET;
-
- if (frames_to_drop_ > 0) {
- highest_dropped_timestamp_ = header.timestamp;
- --frames_to_drop_;
- return DROP_PACKET;
- }
-
- return SEND_PACKET;
- }
-
- virtual Action OnReceiveRtcp(const uint8_t* packet, size_t length) OVERRIDE {
- RTCPUtility::RTCPParserV2 parser(packet, length, true);
- EXPECT_TRUE(parser.IsValid());
-
- for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
- packet_type != RTCPUtility::kRtcpNotValidCode;
- packet_type = parser.Iterate()) {
- if (!nack_enabled_)
- EXPECT_NE(packet_type, RTCPUtility::kRtcpRtpfbNackCode);
-
- if (packet_type == RTCPUtility::kRtcpPsfbPliCode) {
- received_pli_ = true;
- break;
- }
- }
- return SEND_PACKET;
- }
-
- virtual void RenderFrame(const I420VideoFrame& video_frame,
- int time_to_render_ms) OVERRIDE {
- CriticalSectionScoped lock(crit_.get());
- if (received_pli_ && video_frame.timestamp() > highest_dropped_timestamp_) {
- observation_complete_->Set();
- }
- if (!received_pli_)
- frames_to_drop_ = kPacketsToDrop;
- }
-
- private:
- static const int kPacketsToDrop = 1;
-
- bool nack_enabled_;
- uint32_t highest_dropped_timestamp_;
- int frames_to_drop_;
- bool received_pli_;
-};
-
-void CallTest::ReceivesPliAndRecovers(int rtp_history_ms) {
- PliObserver observer(rtp_history_ms > 0);
-
- CreateCalls(Call::Config(observer.SendTransport()),
- Call::Config(observer.ReceiveTransport()));
-
- observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
-
- CreateTestConfigs();
- send_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
- receive_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
- receive_config_.renderer = &observer;
-
- CreateStreams();
- CreateFrameGenerator();
- StartSending();
-
- // Wait() waits for an event triggered when Pli has been received and frames
- // have been rendered afterwards.
- EXPECT_EQ(kEventSignaled, observer.Wait());
-
- StopSending();
-
- observer.StopSending();
-
- DestroyStreams();
-}
-
-TEST_F(CallTest, ReceivesPliAndRecoversWithNack) {
- ReceivesPliAndRecovers(1000);
-}
-
-// TODO(pbos): Enable this when 2250 is resolved.
-TEST_F(CallTest, DISABLED_ReceivesPliAndRecoversWithoutNack) {
- ReceivesPliAndRecovers(0);
-}
-
-TEST_F(CallTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
- class PacketInputObserver : public PacketReceiver {
- public:
- explicit PacketInputObserver(PacketReceiver* receiver)
- : receiver_(receiver), delivered_packet_(EventWrapper::Create()) {}
-
- EventTypeWrapper Wait() {
- return delivered_packet_->Wait(kDefaultTimeoutMs);
- }
-
- private:
- virtual DeliveryStatus DeliverPacket(const uint8_t* packet,
- size_t length) OVERRIDE {
- if (RtpHeaderParser::IsRtcp(packet, static_cast<int>(length))) {
- return receiver_->DeliverPacket(packet, length);
- } else {
- DeliveryStatus delivery_status =
- receiver_->DeliverPacket(packet, length);
- EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
- delivered_packet_->Set();
- return delivery_status;
- }
- }
-
- PacketReceiver* receiver_;
- scoped_ptr<EventWrapper> delivered_packet_;
- };
-
- test::DirectTransport send_transport, receive_transport;
-
- CreateCalls(Call::Config(&send_transport), Call::Config(&receive_transport));
- PacketInputObserver input_observer(receiver_call_->Receiver());
-
- send_transport.SetReceiver(&input_observer);
- receive_transport.SetReceiver(sender_call_->Receiver());
-
- CreateTestConfigs();
-
- CreateStreams();
- CreateFrameGenerator();
- StartSending();
-
- receiver_call_->DestroyVideoReceiveStream(receive_stream_);
- receive_stream_ = NULL;
-
- // Wait() waits for a received packet.
- EXPECT_EQ(kEventSignaled, input_observer.Wait());
-
- StopSending();
-
- DestroyStreams();
-
- send_transport.StopSending();
- receive_transport.StopSending();
-}
-
-void CallTest::RespectsRtcpMode(newapi::RtcpMode rtcp_mode) {
- static const int kRtpHistoryMs = 1000;
- static const int kNumCompoundRtcpPacketsToObserve = 10;
- class RtcpModeObserver : public test::RtpRtcpObserver {
- public:
- explicit RtcpModeObserver(newapi::RtcpMode rtcp_mode)
- : test::RtpRtcpObserver(kDefaultTimeoutMs),
- rtcp_mode_(rtcp_mode),
- sent_rtp_(0),
- sent_rtcp_(0) {}
-
- private:
- virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
- if (++sent_rtp_ % 3 == 0)
- return DROP_PACKET;
-
- return SEND_PACKET;
- }
-
- virtual Action OnReceiveRtcp(const uint8_t* packet,
- size_t length) OVERRIDE {
- ++sent_rtcp_;
- RTCPUtility::RTCPParserV2 parser(packet, length, true);
- EXPECT_TRUE(parser.IsValid());
-
- RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
- bool has_report_block = false;
- while (packet_type != RTCPUtility::kRtcpNotValidCode) {
- EXPECT_NE(RTCPUtility::kRtcpSrCode, packet_type);
- if (packet_type == RTCPUtility::kRtcpRrCode) {
- has_report_block = true;
- break;
- }
- packet_type = parser.Iterate();
- }
-
- switch (rtcp_mode_) {
- case newapi::kRtcpCompound:
- if (!has_report_block) {
- ADD_FAILURE() << "Received RTCP packet without receiver report for "
- "kRtcpCompound.";
- observation_complete_->Set();
- }
-
- if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
- observation_complete_->Set();
-
- break;
- case newapi::kRtcpReducedSize:
- if (!has_report_block)
- observation_complete_->Set();
- break;
- }
-
- return SEND_PACKET;
- }
-
- newapi::RtcpMode rtcp_mode_;
- int sent_rtp_;
- int sent_rtcp_;
- } observer(rtcp_mode);
-
- CreateCalls(Call::Config(observer.SendTransport()),
- Call::Config(observer.ReceiveTransport()));
-
- observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
-
- CreateTestConfigs();
- send_config_.rtp.nack.rtp_history_ms = kRtpHistoryMs;
- receive_config_.rtp.nack.rtp_history_ms = kRtpHistoryMs;
- receive_config_.rtp.rtcp_mode = rtcp_mode;
-
- CreateStreams();
- CreateFrameGenerator();
- StartSending();
-
- EXPECT_EQ(kEventSignaled, observer.Wait())
- << (rtcp_mode == newapi::kRtcpCompound
- ? "Timed out before observing enough compound packets."
- : "Timed out before receiving a non-compound RTCP packet.");
-
- StopSending();
- observer.StopSending();
- DestroyStreams();
-}
-
-TEST_F(CallTest, UsesRtcpCompoundMode) {
- RespectsRtcpMode(newapi::kRtcpCompound);
-}
-
-TEST_F(CallTest, UsesRtcpReducedSizeMode) {
- RespectsRtcpMode(newapi::kRtcpReducedSize);
-}
-
-// Test sets up a Call multiple senders with different resolutions and SSRCs.
-// Another is set up to receive all three of these with different renderers.
-// Each renderer verifies that it receives the expected resolution, and as soon
-// as every renderer has received a frame, the test finishes.
-TEST_F(CallTest, SendsAndReceivesMultipleStreams) {
- static const size_t kNumStreams = 3;
-
- class VideoOutputObserver : public VideoRenderer {
- public:
- VideoOutputObserver(test::FrameGeneratorCapturer** capturer,
- int width,
- int height)
- : capturer_(capturer),
- width_(width),
- height_(height),
- done_(EventWrapper::Create()) {}
-
- virtual void RenderFrame(const I420VideoFrame& video_frame,
- int time_to_render_ms) OVERRIDE {
- EXPECT_EQ(width_, video_frame.width());
- EXPECT_EQ(height_, video_frame.height());
- (*capturer_)->Stop();
- done_->Set();
- }
-
- EventTypeWrapper Wait() { return done_->Wait(kDefaultTimeoutMs); }
-
- private:
- test::FrameGeneratorCapturer** capturer_;
- int width_;
- int height_;
- scoped_ptr<EventWrapper> done_;
- };
-
- struct {
- uint32_t ssrc;
- int width;
- int height;
- } codec_settings[kNumStreams] = {{1, 640, 480}, {2, 320, 240}, {3, 240, 160}};
-
- test::DirectTransport sender_transport, receiver_transport;
- scoped_ptr<Call> sender_call(Call::Create(Call::Config(&sender_transport)));
- scoped_ptr<Call> receiver_call(
- Call::Create(Call::Config(&receiver_transport)));
- sender_transport.SetReceiver(receiver_call->Receiver());
- receiver_transport.SetReceiver(sender_call->Receiver());
-
- VideoSendStream* send_streams[kNumStreams];
- VideoReceiveStream* receive_streams[kNumStreams];
-
- VideoOutputObserver* observers[kNumStreams];
- test::FrameGeneratorCapturer* frame_generators[kNumStreams];
-
- scoped_ptr<VP8Encoder> encoders[kNumStreams];
- for (size_t i = 0; i < kNumStreams; ++i)
- encoders[i].reset(VP8Encoder::Create());
-
- for (size_t i = 0; i < kNumStreams; ++i) {
- uint32_t ssrc = codec_settings[i].ssrc;
- int width = codec_settings[i].width;
- int height = codec_settings[i].height;
- observers[i] = new VideoOutputObserver(&frame_generators[i], width, height);
-
- VideoSendStream::Config send_config = sender_call->GetDefaultSendConfig();
- send_config.rtp.ssrcs.push_back(ssrc);
- send_config.encoder_settings.encoder = encoders[i].get();
- send_config.encoder_settings.payload_name = "VP8";
- send_config.encoder_settings.payload_type = 124;
- std::vector<VideoStream> video_streams = test::CreateVideoStreams(1);
- VideoStream* stream = &video_streams[0];
- stream->width = width;
- stream->height = height;
- stream->max_framerate = 5;
- stream->min_bitrate_bps = stream->target_bitrate_bps =
- stream->max_bitrate_bps = 100000;
- send_streams[i] =
- sender_call->CreateVideoSendStream(send_config, video_streams, NULL);
- send_streams[i]->Start();
-
- VideoReceiveStream::Config receive_config =
- receiver_call->GetDefaultReceiveConfig();
- receive_config.renderer = observers[i];
- receive_config.rtp.remote_ssrc = ssrc;
- receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
- VideoCodec codec =
- test::CreateDecoderVideoCodec(send_config.encoder_settings);
- receive_config.codecs.push_back(codec);
- receive_streams[i] =
- receiver_call->CreateVideoReceiveStream(receive_config);
- receive_streams[i]->Start();
-
- frame_generators[i] = test::FrameGeneratorCapturer::Create(
- send_streams[i]->Input(), width, height, 30, Clock::GetRealTimeClock());
- frame_generators[i]->Start();
- }
-
- for (size_t i = 0; i < kNumStreams; ++i) {
- EXPECT_EQ(kEventSignaled, observers[i]->Wait())
- << "Timed out while waiting for observer " << i << " to render.";
- }
-
- for (size_t i = 0; i < kNumStreams; ++i) {
- frame_generators[i]->Stop();
- sender_call->DestroyVideoSendStream(send_streams[i]);
- receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
- delete frame_generators[i];
- delete observers[i];
- }
-
- sender_transport.StopSending();
- receiver_transport.StopSending();
-};
-
-TEST_F(CallTest, ObserversEncodedFrames) {
- class EncodedFrameTestObserver : public EncodedFrameObserver {
- public:
- EncodedFrameTestObserver()
- : length_(0),
- frame_type_(kFrameEmpty),
- called_(EventWrapper::Create()) {}
- virtual ~EncodedFrameTestObserver() {}
-
- virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
- frame_type_ = encoded_frame.frame_type_;
- length_ = encoded_frame.length_;
- buffer_.reset(new uint8_t[length_]);
- memcpy(buffer_.get(), encoded_frame.data_, length_);
- called_->Set();
- }
-
- EventTypeWrapper Wait() { return called_->Wait(kDefaultTimeoutMs); }
-
- void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
- ASSERT_EQ(length_, observer.length_)
- << "Observed frames are of different lengths.";
- EXPECT_EQ(frame_type_, observer.frame_type_)
- << "Observed frames have different frame types.";
- EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
- << "Observed encoded frames have different content.";
- }
-
- private:
- scoped_ptr<uint8_t[]> buffer_;
- size_t length_;
- FrameType frame_type_;
- scoped_ptr<EventWrapper> called_;
- };
-
- EncodedFrameTestObserver post_encode_observer;
- EncodedFrameTestObserver pre_decode_observer;
-
- test::DirectTransport sender_transport, receiver_transport;
-
- CreateCalls(Call::Config(&sender_transport),
- Call::Config(&receiver_transport));
-
- sender_transport.SetReceiver(receiver_call_->Receiver());
- receiver_transport.SetReceiver(sender_call_->Receiver());
-
- CreateTestConfigs();
- send_config_.post_encode_callback = &post_encode_observer;
- receive_config_.pre_decode_callback = &pre_decode_observer;
-
- CreateStreams();
- StartSending();
-
- scoped_ptr<test::FrameGenerator> frame_generator(test::FrameGenerator::Create(
- video_streams_[0].width, video_streams_[0].height));
- send_stream_->Input()->SwapFrame(frame_generator->NextFrame());
-
- EXPECT_EQ(kEventSignaled, post_encode_observer.Wait())
- << "Timed out while waiting for send-side encoded-frame callback.";
-
- EXPECT_EQ(kEventSignaled, pre_decode_observer.Wait())
- << "Timed out while waiting for pre-decode encoded-frame callback.";
-
- post_encode_observer.ExpectEqualFrames(pre_decode_observer);
-
- StopSending();
-
- sender_transport.StopSending();
- receiver_transport.StopSending();
-
- DestroyStreams();
-}
-
-TEST_F(CallTest, ReceiveStreamSendsRemb) {
- class RembObserver : public test::RtpRtcpObserver {
- public:
- RembObserver() : test::RtpRtcpObserver(kDefaultTimeoutMs) {}
-
- virtual Action OnReceiveRtcp(const uint8_t* packet,
- size_t length) OVERRIDE {
- RTCPUtility::RTCPParserV2 parser(packet, length, true);
- EXPECT_TRUE(parser.IsValid());
-
- bool received_psfb = false;
- bool received_remb = false;
- RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
- while (packet_type != RTCPUtility::kRtcpNotValidCode) {
- if (packet_type == RTCPUtility::kRtcpPsfbRembCode) {
- const RTCPUtility::RTCPPacket& packet = parser.Packet();
- EXPECT_EQ(packet.PSFBAPP.SenderSSRC, kReceiverLocalSsrc);
- received_psfb = true;
- } else if (packet_type == RTCPUtility::kRtcpPsfbRembItemCode) {
- const RTCPUtility::RTCPPacket& packet = parser.Packet();
- EXPECT_GT(packet.REMBItem.BitRate, 0u);
- EXPECT_EQ(packet.REMBItem.NumberOfSSRCs, 1u);
- EXPECT_EQ(packet.REMBItem.SSRCs[0], kSendSsrc);
- received_remb = true;
- }
- packet_type = parser.Iterate();
- }
- if (received_psfb && received_remb)
- observation_complete_->Set();
- return SEND_PACKET;
- }
- } observer;
-
- CreateCalls(Call::Config(observer.SendTransport()),
- Call::Config(observer.ReceiveTransport()));
- observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
- CreateTestConfigs();
- CreateStreams();
- CreateFrameGenerator();
- StartSending();
-
- EXPECT_EQ(kEventSignaled, observer.Wait())
- << "Timed out while waiting for a receiver RTCP REMB packet to be sent.";
-
- StopSending();
- observer.StopSending();
- DestroyStreams();
-}
-
-void CallTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
- static const int kNumRtcpReportPacketsToObserve = 5;
- class RtcpXrObserver : public test::RtpRtcpObserver {
- public:
- explicit RtcpXrObserver(bool enable_rrtr)
- : test::RtpRtcpObserver(kDefaultTimeoutMs),
- enable_rrtr_(enable_rrtr),
- sent_rtcp_sr_(0),
- sent_rtcp_rr_(0),
- sent_rtcp_rrtr_(0),
- sent_rtcp_dlrr_(0) {}
-
- private:
- // Receive stream should send RR packets (and RRTR packets if enabled).
- virtual Action OnReceiveRtcp(const uint8_t* packet,
- size_t length) OVERRIDE {
- RTCPUtility::RTCPParserV2 parser(packet, length, true);
- EXPECT_TRUE(parser.IsValid());
-
- RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
- while (packet_type != RTCPUtility::kRtcpNotValidCode) {
- if (packet_type == RTCPUtility::kRtcpRrCode) {
- ++sent_rtcp_rr_;
- } else if (packet_type ==
- RTCPUtility::kRtcpXrReceiverReferenceTimeCode) {
- ++sent_rtcp_rrtr_;
- }
- EXPECT_NE(packet_type, RTCPUtility::kRtcpSrCode);
- EXPECT_NE(packet_type, RTCPUtility::kRtcpXrDlrrReportBlockItemCode);
- packet_type = parser.Iterate();
- }
- return SEND_PACKET;
- }
- // Send stream should send SR packets (and DLRR packets if enabled).
- virtual Action OnSendRtcp(const uint8_t* packet, size_t length) {
- RTCPUtility::RTCPParserV2 parser(packet, length, true);
- EXPECT_TRUE(parser.IsValid());
-
- RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
- while (packet_type != RTCPUtility::kRtcpNotValidCode) {
- if (packet_type == RTCPUtility::kRtcpSrCode) {
- ++sent_rtcp_sr_;
- } else if (packet_type == RTCPUtility::kRtcpXrDlrrReportBlockItemCode) {
- ++sent_rtcp_dlrr_;
- }
- EXPECT_NE(packet_type, RTCPUtility::kRtcpXrReceiverReferenceTimeCode);
- packet_type = parser.Iterate();
- }
- if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
- sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve) {
- if (enable_rrtr_) {
- EXPECT_GT(sent_rtcp_rrtr_, 0);
- EXPECT_GT(sent_rtcp_dlrr_, 0);
- } else {
- EXPECT_EQ(0, sent_rtcp_rrtr_);
- EXPECT_EQ(0, sent_rtcp_dlrr_);
- }
- observation_complete_->Set();
- }
- return SEND_PACKET;
- }
- bool enable_rrtr_;
- int sent_rtcp_sr_;
- int sent_rtcp_rr_;
- int sent_rtcp_rrtr_;
- int sent_rtcp_dlrr_;
- } observer(enable_rrtr);
-
- CreateCalls(Call::Config(observer.SendTransport()),
- Call::Config(observer.ReceiveTransport()));
- observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
-
- CreateTestConfigs();
- receive_config_.rtp.rtcp_mode = newapi::kRtcpReducedSize;
- receive_config_.rtp.rtcp_xr.receiver_reference_time_report = enable_rrtr;
-
- CreateStreams();
- CreateFrameGenerator();
- StartSending();
-
- EXPECT_EQ(kEventSignaled, observer.Wait())
- << "Timed out while waiting for RTCP SR/RR packets to be sent.";
-
- StopSending();
- observer.StopSending();
- DestroyStreams();
-}
-
-class StatsObserver : public test::RtpRtcpObserver, public I420FrameCallback {
- public:
- StatsObserver()
- : test::RtpRtcpObserver(kLongTimeoutMs),
- receive_stream_(NULL),
- send_stream_(NULL),
- expected_receive_ssrc_(),
- expected_send_ssrcs_(),
- check_stats_event_(EventWrapper::Create()) {}
-
- void SetExpectedReceiveSsrc(uint32_t ssrc) { expected_receive_ssrc_ = ssrc; }
-
- void SetExpectedSendSsrcs(const std::vector<uint32_t>& ssrcs) {
- for (std::vector<uint32_t>::const_iterator it = ssrcs.begin();
- it != ssrcs.end();
- ++it) {
- expected_send_ssrcs_.insert(*it);
- }
- }
-
- void SetExpectedCName(std::string cname) { expected_cname_ = cname; }
-
- void SetReceiveStream(VideoReceiveStream* stream) {
- receive_stream_ = stream;
- }
-
- void SetSendStream(VideoSendStream* stream) { send_stream_ = stream; }
-
- void WaitForFilledStats() {
- Clock* clock = Clock::GetRealTimeClock();
- int64_t now = clock->TimeInMilliseconds();
- int64_t stop_time = now + kLongTimeoutMs;
- bool receive_ok = false;
- bool send_ok = false;
-
- while (now < stop_time) {
- if (!receive_ok)
- receive_ok = CheckReceiveStats();
- if (!send_ok)
- send_ok = CheckSendStats();
-
- if (receive_ok && send_ok)
- return;
-
- int64_t time_until_timout_ = stop_time - now;
- if (time_until_timout_ > 0)
- check_stats_event_->Wait(time_until_timout_);
- now = clock->TimeInMilliseconds();
- }
-
- ADD_FAILURE() << "Timed out waiting for filled stats.";
- for (std::map<std::string, bool>::const_iterator it =
- receive_stats_filled_.begin();
- it != receive_stats_filled_.end();
- ++it) {
- if (!it->second) {
- ADD_FAILURE() << "Missing receive stats: " << it->first;
- }
- }
-
- for (std::map<std::string, bool>::const_iterator it =
- send_stats_filled_.begin();
- it != send_stats_filled_.end();
- ++it) {
- if (!it->second) {
- ADD_FAILURE() << "Missing send stats: " << it->first;
- }
- }
- }
-
- private:
- virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
- check_stats_event_->Set();
- return SEND_PACKET;
- }
-
- virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
- check_stats_event_->Set();
- return SEND_PACKET;
- }
-
- virtual Action OnReceiveRtp(const uint8_t* packet, size_t length) OVERRIDE {
- check_stats_event_->Set();
- return SEND_PACKET;
- }
-
- virtual Action OnReceiveRtcp(const uint8_t* packet, size_t length) OVERRIDE {
- check_stats_event_->Set();
- return SEND_PACKET;
- }
-
- virtual void FrameCallback(I420VideoFrame* video_frame) OVERRIDE {
- // Ensure that we have at least 5ms send side delay.
- int64_t render_time = video_frame->render_time_ms();
- if (render_time > 0)
- video_frame->set_render_time_ms(render_time - 5);
- }
-
- bool CheckReceiveStats() {
- assert(receive_stream_ != NULL);
- VideoReceiveStream::Stats stats = receive_stream_->GetStats();
- EXPECT_EQ(expected_receive_ssrc_, stats.ssrc);
-
- // Make sure all fields have been populated.
-
- receive_stats_filled_["IncomingRate"] |=
- stats.network_frame_rate != 0 || stats.bitrate_bps != 0;
-
- receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
-
- receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
-
- receive_stats_filled_["StatisticsUpdated"] |=
- stats.rtcp_stats.cumulative_lost != 0 ||
- stats.rtcp_stats.extended_max_sequence_number != 0 ||
- stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
-
- receive_stats_filled_["DataCountersUpdated"] |=
- stats.rtp_stats.bytes != 0 || stats.rtp_stats.fec_packets != 0 ||
- stats.rtp_stats.header_bytes != 0 || stats.rtp_stats.packets != 0 ||
- stats.rtp_stats.padding_bytes != 0 ||
- stats.rtp_stats.retransmitted_packets != 0;
-
- receive_stats_filled_["CodecStats"] |=
- stats.avg_delay_ms != 0 || stats.discarded_packets != 0 ||
- stats.key_frames != 0 || stats.delta_frames != 0;
-
- receive_stats_filled_["CName"] |= stats.c_name == expected_cname_;
-
- return AllStatsFilled(receive_stats_filled_);
- }
-
- bool CheckSendStats() {
- assert(send_stream_ != NULL);
- VideoSendStream::Stats stats = send_stream_->GetStats();
-
- send_stats_filled_["NumStreams"] |=
- stats.substreams.size() == expected_send_ssrcs_.size();
-
- send_stats_filled_["Delay"] |=
- stats.avg_delay_ms != 0 || stats.max_delay_ms != 0;
-
- receive_stats_filled_["CName"] |= stats.c_name == expected_cname_;
-
- for (std::map<uint32_t, StreamStats>::const_iterator it =
- stats.substreams.begin();
- it != stats.substreams.end();
- ++it) {
- EXPECT_TRUE(expected_send_ssrcs_.find(it->first) !=
- expected_send_ssrcs_.end());
-
- send_stats_filled_[CompoundKey("IncomingRate", it->first)] |=
- stats.input_frame_rate != 0;
-
- const StreamStats& stream_stats = it->second;
-
- send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
- stream_stats.rtcp_stats.cumulative_lost != 0 ||
- stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
- stream_stats.rtcp_stats.fraction_lost != 0;
-
- send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
- stream_stats.rtp_stats.fec_packets != 0 ||
- stream_stats.rtp_stats.padding_bytes != 0 ||
- stream_stats.rtp_stats.retransmitted_packets != 0 ||
- stream_stats.rtp_stats.packets != 0;
-
- send_stats_filled_[CompoundKey("BitrateStatisticsObserver", it->first)] |=
- stream_stats.bitrate_bps != 0;
-
- send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
- stream_stats.delta_frames != 0 || stream_stats.key_frames != 0;
-
- send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
- stats.encode_frame_rate != 0;
- }
-
- return AllStatsFilled(send_stats_filled_);
- }
-
- std::string CompoundKey(const char* name, uint32_t ssrc) {
- std::ostringstream oss;
- oss << name << "_" << ssrc;
- return oss.str();
- }
-
- bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
- for (std::map<std::string, bool>::const_iterator it = stats_map.begin();
- it != stats_map.end();
- ++it) {
- if (!it->second)
- return false;
- }
- return true;
- }
-
- VideoReceiveStream* receive_stream_;
- std::map<std::string, bool> receive_stats_filled_;
-
- VideoSendStream* send_stream_;
- std::map<std::string, bool> send_stats_filled_;
-
- uint32_t expected_receive_ssrc_;
- std::set<uint32_t> expected_send_ssrcs_;
- std::string expected_cname_;
-
- scoped_ptr<EventWrapper> check_stats_event_;
-};
-
-TEST_F(CallTest, GetStats) {
- StatsObserver observer;
-
- CreateCalls(Call::Config(observer.SendTransport()),
- Call::Config(observer.ReceiveTransport()));
-
- observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
-
- CreateTestConfigs();
- send_config_.pre_encode_callback = &observer; // Used to inject delay.
- send_config_.rtp.c_name = "SomeCName";
-
- observer.SetExpectedReceiveSsrc(receive_config_.rtp.local_ssrc);
- observer.SetExpectedSendSsrcs(send_config_.rtp.ssrcs);
- observer.SetExpectedCName(send_config_.rtp.c_name);
-
- CreateStreams();
- observer.SetReceiveStream(receive_stream_);
- observer.SetSendStream(send_stream_);
- CreateFrameGenerator();
- StartSending();
-
- observer.WaitForFilledStats();
-
- StopSending();
- observer.StopSending();
- DestroyStreams();
-}
-
-TEST_F(CallTest, ReceiverReferenceTimeReportEnabled) {
- TestXrReceiverReferenceTimeReport(true);
-}
-
-TEST_F(CallTest, ReceiverReferenceTimeReportDisabled) {
- TestXrReceiverReferenceTimeReport(false);
-}
-
-TEST_F(CallTest, TestReceivedRtpPacketStats) {
- static const size_t kNumRtpPacketsToSend = 5;
- class ReceivedRtpStatsObserver : public test::RtpRtcpObserver {
- public:
- ReceivedRtpStatsObserver()
- : test::RtpRtcpObserver(kDefaultTimeoutMs),
- receive_stream_(NULL),
- sent_rtp_(0) {}
-
- void SetReceiveStream(VideoReceiveStream* stream) {
- receive_stream_ = stream;
- }
-
- private:
- virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
- if (sent_rtp_ >= kNumRtpPacketsToSend) {
- VideoReceiveStream::Stats stats = receive_stream_->GetStats();
- if (kNumRtpPacketsToSend == stats.rtp_stats.packets) {
- observation_complete_->Set();
- }
- return DROP_PACKET;
- }
- ++sent_rtp_;
- return SEND_PACKET;
- }
-
- VideoReceiveStream* receive_stream_;
- uint32_t sent_rtp_;
- } observer;
-
- CreateCalls(Call::Config(observer.SendTransport()),
- Call::Config(observer.ReceiveTransport()));
- observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
-
- CreateTestConfigs();
- CreateStreams();
- observer.SetReceiveStream(receive_stream_);
- CreateFrameGenerator();
- StartSending();
-
- EXPECT_EQ(kEventSignaled, observer.Wait())
- << "Timed out while verifying number of received RTP packets.";
-
- StopSending();
- observer.StopSending();
- DestroyStreams();
-}
-
-} // namespace webrtc
diff --git a/webrtc/video/end_to_end_tests.cc b/webrtc/video/end_to_end_tests.cc
new file mode 100644
index 0000000..0f6f2dc
--- /dev/null
+++ b/webrtc/video/end_to_end_tests.cc
@@ -0,0 +1,1459 @@
+/*
+ * 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 <assert.h>
+
+#include <algorithm>
+#include <map>
+#include <sstream>
+#include <string>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+#include "webrtc/call.h"
+#include "webrtc/frame_callback.h"
+#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
+#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
+#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
+#include "webrtc/system_wrappers/interface/event_wrapper.h"
+#include "webrtc/system_wrappers/interface/scoped_ptr.h"
+#include "webrtc/system_wrappers/interface/sleep.h"
+#include "webrtc/test/call_test.h"
+#include "webrtc/test/direct_transport.h"
+#include "webrtc/test/encoder_settings.h"
+#include "webrtc/test/fake_audio_device.h"
+#include "webrtc/test/fake_decoder.h"
+#include "webrtc/test/fake_encoder.h"
+#include "webrtc/test/frame_generator.h"
+#include "webrtc/test/frame_generator_capturer.h"
+#include "webrtc/test/null_transport.h"
+#include "webrtc/test/rtp_rtcp_observer.h"
+#include "webrtc/test/testsupport/fileutils.h"
+#include "webrtc/test/testsupport/perf_test.h"
+#include "webrtc/video/transport_adapter.h"
+
+namespace webrtc {
+
+static const int kRedPayloadType = 118;
+static const int kUlpfecPayloadType = 119;
+
+class EndToEndTest : public test::CallTest {
+ public:
+ EndToEndTest() {}
+
+ virtual ~EndToEndTest() {
+ EXPECT_EQ(NULL, send_stream_);
+ EXPECT_EQ(NULL, receive_stream_);
+ }
+
+ protected:
+ void CreateFrameGenerator() {
+ frame_generator_capturer_.reset(
+ test::FrameGeneratorCapturer::Create(send_stream_->Input(),
+ video_streams_[0].width,
+ video_streams_[0].height,
+ 30,
+ Clock::GetRealTimeClock()));
+ }
+
+ void StartSending() {
+ receive_stream_->Start();
+ send_stream_->Start();
+ if (frame_generator_capturer_.get() != NULL)
+ frame_generator_capturer_->Start();
+ }
+
+ void StopSending() {
+ if (frame_generator_capturer_.get() != NULL)
+ frame_generator_capturer_->Stop();
+ if (send_stream_ != NULL)
+ send_stream_->Stop();
+ if (receive_stream_ != NULL)
+ receive_stream_->Stop();
+ }
+
+ void DecodesRetransmittedFrame(bool retransmit_over_rtx);
+ void ReceivesPliAndRecovers(int rtp_history_ms);
+ void RespectsRtcpMode(newapi::RtcpMode rtcp_mode);
+ void TestXrReceiverReferenceTimeReport(bool enable_rrtr);
+};
+
+TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
+ test::NullTransport transport;
+ CreateCalls(Call::Config(&transport), Call::Config(&transport));
+
+ CreateSendConfig(1);
+ CreateMatchingReceiveConfigs();
+
+ CreateStreams();
+
+ receive_stream_->Start();
+ receive_stream_->Start();
+
+ DestroyStreams();
+}
+
+TEST_F(EndToEndTest, ReceiverCanBeStoppedTwice) {
+ test::NullTransport transport;
+ CreateCalls(Call::Config(&transport), Call::Config(&transport));
+
+ CreateSendConfig(1);
+ CreateMatchingReceiveConfigs();
+
+ CreateStreams();
+
+ receive_stream_->Stop();
+ receive_stream_->Stop();
+
+ DestroyStreams();
+}
+
+TEST_F(EndToEndTest, RendersSingleDelayedFrame) {
+ static const int kWidth = 320;
+ static const int kHeight = 240;
+ // This constant is chosen to be higher than the timeout in the video_render
+ // module. This makes sure that frames aren't dropped if there are no other
+ // frames in the queue.
+ static const int kDelayRenderCallbackMs = 1000;
+
+ class Renderer : public VideoRenderer {
+ public:
+ Renderer() : event_(EventWrapper::Create()) {}
+
+ virtual void RenderFrame(const I420VideoFrame& video_frame,
+ int /*time_to_render_ms*/) OVERRIDE {
+ event_->Set();
+ }
+
+ EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
+
+ scoped_ptr<EventWrapper> event_;
+ } renderer;
+
+ class TestFrameCallback : public I420FrameCallback {
+ public:
+ TestFrameCallback() : event_(EventWrapper::Create()) {}
+
+ EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
+
+ private:
+ virtual void FrameCallback(I420VideoFrame* frame) OVERRIDE {
+ SleepMs(kDelayRenderCallbackMs);
+ event_->Set();
+ }
+
+ scoped_ptr<EventWrapper> event_;
+ };
+
+ test::DirectTransport sender_transport, receiver_transport;
+
+ CreateCalls(Call::Config(&sender_transport),
+ Call::Config(&receiver_transport));
+
+ sender_transport.SetReceiver(receiver_call_->Receiver());
+ receiver_transport.SetReceiver(sender_call_->Receiver());
+
+ CreateSendConfig(1);
+ CreateMatchingReceiveConfigs();
+
+ TestFrameCallback pre_render_callback;
+ receive_config_.pre_render_callback = &pre_render_callback;
+ receive_config_.renderer = &renderer;
+
+ CreateStreams();
+ StartSending();
+
+ // Create frames that are smaller than the send width/height, this is done to
+ // check that the callbacks are done after processing video.
+ scoped_ptr<test::FrameGenerator> frame_generator(
+ test::FrameGenerator::Create(kWidth, kHeight));
+ send_stream_->Input()->SwapFrame(frame_generator->NextFrame());
+ EXPECT_EQ(kEventSignaled, pre_render_callback.Wait())
+ << "Timed out while waiting for pre-render callback.";
+ EXPECT_EQ(kEventSignaled, renderer.Wait())
+ << "Timed out while waiting for the frame to render.";
+
+ StopSending();
+
+ sender_transport.StopSending();
+ receiver_transport.StopSending();
+
+ DestroyStreams();
+}
+
+TEST_F(EndToEndTest, TransmitsFirstFrame) {
+ class Renderer : public VideoRenderer {
+ public:
+ Renderer() : event_(EventWrapper::Create()) {}
+
+ virtual void RenderFrame(const I420VideoFrame& video_frame,
+ int /*time_to_render_ms*/) OVERRIDE {
+ event_->Set();
+ }
+
+ EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
+
+ scoped_ptr<EventWrapper> event_;
+ } renderer;
+
+ test::DirectTransport sender_transport, receiver_transport;
+
+ CreateCalls(Call::Config(&sender_transport),
+ Call::Config(&receiver_transport));
+
+ sender_transport.SetReceiver(receiver_call_->Receiver());
+ receiver_transport.SetReceiver(sender_call_->Receiver());
+
+ CreateSendConfig(1);
+ CreateMatchingReceiveConfigs();
+ receive_config_.renderer = &renderer;
+
+ CreateStreams();
+ StartSending();
+
+ scoped_ptr<test::FrameGenerator> frame_generator(test::FrameGenerator::Create(
+ video_streams_[0].width, video_streams_[0].height));
+ send_stream_->Input()->SwapFrame(frame_generator->NextFrame());
+
+ EXPECT_EQ(kEventSignaled, renderer.Wait())
+ << "Timed out while waiting for the frame to render.";
+
+ StopSending();
+
+ sender_transport.StopSending();
+ receiver_transport.StopSending();
+
+ DestroyStreams();
+}
+
+TEST_F(EndToEndTest, ReceiverUsesLocalSsrc) {
+ class SyncRtcpObserver : public test::EndToEndTest {
+ public:
+ SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {}
+
+ virtual Action OnReceiveRtcp(const uint8_t* packet,
+ size_t length) OVERRIDE {
+ RTCPUtility::RTCPParserV2 parser(packet, length, true);
+ EXPECT_TRUE(parser.IsValid());
+ uint32_t ssrc = 0;
+ ssrc |= static_cast<uint32_t>(packet[4]) << 24;
+ ssrc |= static_cast<uint32_t>(packet[5]) << 16;
+ ssrc |= static_cast<uint32_t>(packet[6]) << 8;
+ ssrc |= static_cast<uint32_t>(packet[7]) << 0;
+ EXPECT_EQ(kReceiverLocalSsrc, ssrc);
+ observation_complete_->Set();
+
+ return SEND_PACKET;
+ }
+
+ virtual void PerformTest() OVERRIDE {
+ EXPECT_EQ(kEventSignaled, Wait())
+ << "Timed out while waiting for a receiver RTCP packet to be sent.";
+ }
+ } test;
+
+ RunBaseTest(&test);
+}
+
+TEST_F(EndToEndTest, ReceivesAndRetransmitsNack) {
+ static const int kNumberOfNacksToObserve = 2;
+ static const int kLossBurstSize = 2;
+ static const int kPacketsBetweenLossBursts = 9;
+ class NackObserver : public test::EndToEndTest {
+ public:
+ NackObserver()
+ : EndToEndTest(kLongTimeoutMs),
+ rtp_parser_(RtpHeaderParser::Create()),
+ sent_rtp_packets_(0),
+ packets_left_to_drop_(0),
+ nacks_left_(kNumberOfNacksToObserve) {}
+
+ private:
+ virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
+ RTPHeader header;
+ EXPECT_TRUE(
+ rtp_parser_->Parse(packet, static_cast<int>(length), &header));
+
+ // Never drop retransmitted packets.
+ if (dropped_packets_.find(header.sequenceNumber) !=
+ dropped_packets_.end()) {
+ retransmitted_packets_.insert(header.sequenceNumber);
+ if (nacks_left_ == 0 &&
+ retransmitted_packets_.size() == dropped_packets_.size()) {
+ observation_complete_->Set();
+ }
+ return SEND_PACKET;
+ }
+
+ ++sent_rtp_packets_;
+
+ // Enough NACKs received, stop dropping packets.
+ if (nacks_left_ == 0)
+ return SEND_PACKET;
+
+ // Check if it's time for a new loss burst.
+ if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
+ packets_left_to_drop_ = kLossBurstSize;
+
+ if (packets_left_to_drop_ > 0) {
+ --packets_left_to_drop_;
+ dropped_packets_.insert(header.sequenceNumber);
+ return DROP_PACKET;
+ }
+
+ return SEND_PACKET;
+ }
+
+ virtual Action OnReceiveRtcp(const uint8_t* packet,
+ size_t length) OVERRIDE {
+ RTCPUtility::RTCPParserV2 parser(packet, length, true);
+ EXPECT_TRUE(parser.IsValid());
+
+ RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
+ while (packet_type != RTCPUtility::kRtcpNotValidCode) {
+ if (packet_type == RTCPUtility::kRtcpRtpfbNackCode) {
+ --nacks_left_;
+ break;
+ }
+ packet_type = parser.Iterate();
+ }
+ return SEND_PACKET;
+ }
+
+ virtual void ModifyConfigs(
+ VideoSendStream::Config* send_config,
+ VideoReceiveStream::Config* receive_config,
+ std::vector<VideoStream>* video_streams) OVERRIDE {
+ send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
+ receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
+ }
+
+ virtual void PerformTest() OVERRIDE {
+ EXPECT_EQ(kEventSignaled, Wait())
+ << "Timed out waiting for packets to be NACKed, retransmitted and "
+ "rendered.";
+ }
+
+ scoped_ptr<RtpHeaderParser> rtp_parser_;
+ std::set<uint16_t> dropped_packets_;
+ std::set<uint16_t> retransmitted_packets_;
+ uint64_t sent_rtp_packets_;
+ int packets_left_to_drop_;
+ int nacks_left_;
+ } test;
+
+ RunBaseTest(&test);
+}
+
+// TODO(pbos): Flaky, webrtc:3269
+TEST_F(EndToEndTest, DISABLED_CanReceiveFec) {
+ class FecRenderObserver : public test::EndToEndTest, public VideoRenderer {
+ public:
+ FecRenderObserver()
+ : EndToEndTest(kDefaultTimeoutMs),
+ state_(kFirstPacket),
+ protected_sequence_number_(0),
+ protected_frame_timestamp_(0) {}
+
+ private:
+ virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE
+ EXCLUSIVE_LOCKS_REQUIRED(crit_) {
+ RTPHeader header;
+ EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
+
+ EXPECT_EQ(kRedPayloadType, header.payloadType);
+ int encapsulated_payload_type =
+ static_cast<int>(packet[header.headerLength]);
+ if (encapsulated_payload_type != kFakeSendPayloadType)
+ EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
+
+ switch (state_) {
+ case kFirstPacket:
+ state_ = kDropEveryOtherPacketUntilFec;
+ break;
+ case kDropEveryOtherPacketUntilFec:
+ if (encapsulated_payload_type == kUlpfecPayloadType) {
+ state_ = kDropNextMediaPacket;
+ return SEND_PACKET;
+ }
+ if (header.sequenceNumber % 2 == 0)
+ return DROP_PACKET;
+ break;
+ case kDropNextMediaPacket:
+ if (encapsulated_payload_type == kFakeSendPayloadType) {
+ protected_sequence_number_ = header.sequenceNumber;
+ protected_frame_timestamp_ = header.timestamp;
+ state_ = kProtectedPacketDropped;
+ return DROP_PACKET;
+ }
+ break;
+ case kProtectedPacketDropped:
+ EXPECT_NE(header.sequenceNumber, protected_sequence_number_)
+ << "Protected packet retransmitted. Should not happen with FEC.";
+ break;
+ }
+
+ return SEND_PACKET;
+ }
+
+ virtual void RenderFrame(const I420VideoFrame& video_frame,
+ int time_to_render_ms) OVERRIDE {
+ CriticalSectionScoped lock(crit_.get());
+ // Rendering frame with timestamp associated with dropped packet -> FEC
+ // protection worked.
+ if (state_ == kProtectedPacketDropped &&
+ video_frame.timestamp() == protected_frame_timestamp_) {
+ observation_complete_->Set();
+ }
+ }
+
+ enum {
+ kFirstPacket,
+ kDropEveryOtherPacketUntilFec,
+ kDropNextMediaPacket,
+ kProtectedPacketDropped,
+ } state_;
+
+ virtual void ModifyConfigs(
+ VideoSendStream::Config* send_config,
+ VideoReceiveStream::Config* receive_config,
+ std::vector<VideoStream>* video_streams) OVERRIDE {
+ // TODO(pbos): Run this test with combined NACK/FEC enabled as well.
+ // int rtp_history_ms = 1000;
+ // receive_config->rtp.nack.rtp_history_ms = rtp_history_ms;
+ // send_config->rtp.nack.rtp_history_ms = rtp_history_ms;
+ send_config->rtp.fec.red_payload_type = kRedPayloadType;
+ send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
+
+ receive_config->rtp.fec.red_payload_type = kRedPayloadType;
+ receive_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
+ receive_config->renderer = this;
+ }
+
+ virtual void PerformTest() OVERRIDE {
+ EXPECT_EQ(kEventSignaled, Wait())
+ << "Timed out while waiting for retransmitted NACKed frames to be "
+ "rendered again.";
+ }
+
+ uint32_t protected_sequence_number_ GUARDED_BY(crit_);
+ uint32_t protected_frame_timestamp_ GUARDED_BY(crit_);
+ } test;
+
+ RunBaseTest(&test);
+}
+
+// This test drops second RTP packet with a marker bit set, makes sure it's
+// retransmitted and renders. Retransmission SSRCs are also checked.
+void EndToEndTest::DecodesRetransmittedFrame(bool retransmit_over_rtx) {
+ static const int kDroppedFrameNumber = 2;
+ class RetransmissionObserver : public test::EndToEndTest,
+ public I420FrameCallback {
+ public:
+ explicit RetransmissionObserver(bool expect_rtx)
+ : EndToEndTest(kDefaultTimeoutMs),
+ retransmission_ssrc_(expect_rtx ? kSendRtxSsrc : kSendSsrcs[0]),
+ retransmission_payload_type_(expect_rtx ? kSendRtxPayloadType
+ : kFakeSendPayloadType),
+ marker_bits_observed_(0),
+ retransmitted_timestamp_(0),
+ frame_retransmitted_(false) {}
+
+ private:
+ virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
+ RTPHeader header;
+ EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
+
+ if (header.timestamp == retransmitted_timestamp_) {
+ EXPECT_EQ(retransmission_ssrc_, header.ssrc);
+ EXPECT_EQ(retransmission_payload_type_, header.payloadType);
+ frame_retransmitted_ = true;
+ return SEND_PACKET;
+ }
+
+ EXPECT_EQ(kSendSsrcs[0], header.ssrc);
+ EXPECT_EQ(kFakeSendPayloadType, header.payloadType);
+
+ // Found the second frame's final packet, drop this and expect a
+ // retransmission.
+ if (header.markerBit && ++marker_bits_observed_ == kDroppedFrameNumber) {
+ retransmitted_timestamp_ = header.timestamp;
+ return DROP_PACKET;
+ }
+
+ return SEND_PACKET;
+ }
+
+ virtual void FrameCallback(I420VideoFrame* frame) OVERRIDE {
+ CriticalSectionScoped lock(crit_.get());
+ if (frame->timestamp() == retransmitted_timestamp_) {
+ EXPECT_TRUE(frame_retransmitted_);
+ observation_complete_->Set();
+ }
+ }
+
+ virtual void ModifyConfigs(
+ VideoSendStream::Config* send_config,
+ VideoReceiveStream::Config* receive_config,
+ std::vector<VideoStream>* video_streams) OVERRIDE {
+ send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
+ receive_config->pre_render_callback = this;
+ receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
+ if (retransmission_ssrc_ == kSendRtxSsrc) {
+ send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrc);
+ send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
+ receive_config->rtp.rtx[kSendRtxPayloadType].ssrc = kSendRtxSsrc;
+ receive_config->rtp.rtx[kSendRtxPayloadType].payload_type =
+ kSendRtxPayloadType;
+ }
+ }
+
+ virtual void PerformTest() OVERRIDE {
+ EXPECT_EQ(kEventSignaled, Wait())
+ << "Timed out while waiting for retransmission to render.";
+ }
+
+ const uint32_t retransmission_ssrc_;
+ const int retransmission_payload_type_;
+ int marker_bits_observed_;
+ uint32_t retransmitted_timestamp_;
+ bool frame_retransmitted_;
+ } test(retransmit_over_rtx);
+
+ RunBaseTest(&test);
+}
+
+TEST_F(EndToEndTest, DecodesRetransmittedFrame) {
+ DecodesRetransmittedFrame(false);
+}
+
+TEST_F(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
+ DecodesRetransmittedFrame(true);
+}
+
+TEST_F(EndToEndTest, UsesFrameCallbacks) {
+ static const int kWidth = 320;
+ static const int kHeight = 240;
+
+ class Renderer : public VideoRenderer {
+ public:
+ Renderer() : event_(EventWrapper::Create()) {}
+
+ virtual void RenderFrame(const I420VideoFrame& video_frame,
+ int /*time_to_render_ms*/) OVERRIDE {
+ EXPECT_EQ(0, *video_frame.buffer(kYPlane))
+ << "Rendered frame should have zero luma which is applied by the "
+ "pre-render callback.";
+ event_->Set();
+ }
+
+ EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
+ scoped_ptr<EventWrapper> event_;
+ } renderer;
+
+ class TestFrameCallback : public I420FrameCallback {
+ public:
+ TestFrameCallback(int expected_luma_byte, int next_luma_byte)
+ : event_(EventWrapper::Create()),
+ expected_luma_byte_(expected_luma_byte),
+ next_luma_byte_(next_luma_byte) {}
+
+ EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
+
+ private:
+ virtual void FrameCallback(I420VideoFrame* frame) {
+ EXPECT_EQ(kWidth, frame->width())
+ << "Width not as expected, callback done before resize?";
+ EXPECT_EQ(kHeight, frame->height())
+ << "Height not as expected, callback done before resize?";
+
+ // Previous luma specified, observed luma should be fairly close.
+ if (expected_luma_byte_ != -1) {
+ EXPECT_NEAR(expected_luma_byte_, *frame->buffer(kYPlane), 10);
+ }
+
+ memset(frame->buffer(kYPlane),
+ next_luma_byte_,
+ frame->allocated_size(kYPlane));
+
+ event_->Set();
+ }
+
+ scoped_ptr<EventWrapper> event_;
+ int expected_luma_byte_;
+ int next_luma_byte_;
+ };
+
+ TestFrameCallback pre_encode_callback(-1, 255); // Changes luma to 255.
+ TestFrameCallback pre_render_callback(255, 0); // Changes luma from 255 to 0.
+
+ test::DirectTransport sender_transport, receiver_transport;
+
+ CreateCalls(Call::Config(&sender_transport),
+ Call::Config(&receiver_transport));
+
+ sender_transport.SetReceiver(receiver_call_->Receiver());
+ receiver_transport.SetReceiver(sender_call_->Receiver());
+
+ CreateSendConfig(1);
+ scoped_ptr<VP8Encoder> encoder(VP8Encoder::Create());
+ send_config_.encoder_settings.encoder = encoder.get();
+ send_config_.encoder_settings.payload_name = "VP8";
+ ASSERT_EQ(1u, video_streams_.size()) << "Test setup error.";
+ video_streams_[0].width = kWidth;
+ video_streams_[0].height = kHeight;
+ send_config_.pre_encode_callback = &pre_encode_callback;
+
+ CreateMatchingReceiveConfigs();
+ receive_config_.pre_render_callback = &pre_render_callback;
+ receive_config_.renderer = &renderer;
+
+ CreateStreams();
+ StartSending();
+
+ // Create frames that are smaller than the send width/height, this is done to
+ // check that the callbacks are done after processing video.
+ scoped_ptr<test::FrameGenerator> frame_generator(
+ test::FrameGenerator::Create(kWidth / 2, kHeight / 2));
+ send_stream_->Input()->SwapFrame(frame_generator->NextFrame());
+
+ EXPECT_EQ(kEventSignaled, pre_encode_callback.Wait())
+ << "Timed out while waiting for pre-encode callback.";
+ EXPECT_EQ(kEventSignaled, pre_render_callback.Wait())
+ << "Timed out while waiting for pre-render callback.";
+ EXPECT_EQ(kEventSignaled, renderer.Wait())
+ << "Timed out while waiting for the frame to render.";
+
+ StopSending();
+
+ sender_transport.StopSending();
+ receiver_transport.StopSending();
+
+ DestroyStreams();
+}
+
+void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
+ static const int kPacketsToDrop = 1;
+
+ class PliObserver : public test::EndToEndTest, public VideoRenderer {
+ public:
+ explicit PliObserver(int rtp_history_ms)
+ : EndToEndTest(kLongTimeoutMs),
+ rtp_history_ms_(rtp_history_ms),
+ nack_enabled_(rtp_history_ms > 0),
+ highest_dropped_timestamp_(0),
+ frames_to_drop_(0),
+ received_pli_(false) {}
+
+ private:
+ virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
+ RTPHeader header;
+ EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
+
+ // Drop all retransmitted packets to force a PLI.
+ if (header.timestamp <= highest_dropped_timestamp_)
+ return DROP_PACKET;
+
+ if (frames_to_drop_ > 0) {
+ highest_dropped_timestamp_ = header.timestamp;
+ --frames_to_drop_;
+ return DROP_PACKET;
+ }
+
+ return SEND_PACKET;
+ }
+
+ virtual Action OnReceiveRtcp(const uint8_t* packet,
+ size_t length) OVERRIDE {
+ RTCPUtility::RTCPParserV2 parser(packet, length, true);
+ EXPECT_TRUE(parser.IsValid());
+
+ for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
+ packet_type != RTCPUtility::kRtcpNotValidCode;
+ packet_type = parser.Iterate()) {
+ if (!nack_enabled_)
+ EXPECT_NE(packet_type, RTCPUtility::kRtcpRtpfbNackCode);
+
+ if (packet_type == RTCPUtility::kRtcpPsfbPliCode) {
+ received_pli_ = true;
+ break;
+ }
+ }
+ return SEND_PACKET;
+ }
+
+ virtual void RenderFrame(const I420VideoFrame& video_frame,
+ int time_to_render_ms) OVERRIDE {
+ CriticalSectionScoped lock(crit_.get());
+ if (received_pli_ &&
+ video_frame.timestamp() > highest_dropped_timestamp_) {
+ observation_complete_->Set();
+ }
+ if (!received_pli_)
+ frames_to_drop_ = kPacketsToDrop;
+ }
+
+ virtual void ModifyConfigs(
+ VideoSendStream::Config* send_config,
+ VideoReceiveStream::Config* receive_config,
+ std::vector<VideoStream>* video_streams) OVERRIDE {
+ send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
+ receive_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
+ receive_config->renderer = this;
+ }
+
+ virtual void PerformTest() OVERRIDE {
+ EXPECT_EQ(kEventSignaled, Wait()) << "Timed out waiting for PLI to be "
+ "received and a frame to be "
+ "rendered afterwards.";
+ }
+
+ int rtp_history_ms_;
+ bool nack_enabled_;
+ uint32_t highest_dropped_timestamp_;
+ int frames_to_drop_;
+ bool received_pli_;
+ } test(rtp_history_ms);
+
+ RunBaseTest(&test);
+}
+
+TEST_F(EndToEndTest, ReceivesPliAndRecoversWithNack) {
+ ReceivesPliAndRecovers(1000);
+}
+
+// TODO(pbos): Enable this when 2250 is resolved.
+TEST_F(EndToEndTest, DISABLED_ReceivesPliAndRecoversWithoutNack) {
+ ReceivesPliAndRecovers(0);
+}
+
+TEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
+ class PacketInputObserver : public PacketReceiver {
+ public:
+ explicit PacketInputObserver(PacketReceiver* receiver)
+ : receiver_(receiver), delivered_packet_(EventWrapper::Create()) {}
+
+ EventTypeWrapper Wait() {
+ return delivered_packet_->Wait(kDefaultTimeoutMs);
+ }
+
+ private:
+ virtual DeliveryStatus DeliverPacket(const uint8_t* packet,
+ size_t length) OVERRIDE {
+ if (RtpHeaderParser::IsRtcp(packet, static_cast<int>(length))) {
+ return receiver_->DeliverPacket(packet, length);
+ } else {
+ DeliveryStatus delivery_status =
+ receiver_->DeliverPacket(packet, length);
+ EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
+ delivered_packet_->Set();
+ return delivery_status;
+ }
+ }
+
+ PacketReceiver* receiver_;
+ scoped_ptr<EventWrapper> delivered_packet_;
+ };
+
+ test::DirectTransport send_transport, receive_transport;
+
+ CreateCalls(Call::Config(&send_transport), Call::Config(&receive_transport));
+ PacketInputObserver input_observer(receiver_call_->Receiver());
+
+ send_transport.SetReceiver(&input_observer);
+ receive_transport.SetReceiver(sender_call_->Receiver());
+
+ CreateSendConfig(1);
+ CreateMatchingReceiveConfigs();
+
+ CreateStreams();
+ CreateFrameGenerator();
+ StartSending();
+
+ receiver_call_->DestroyVideoReceiveStream(receive_stream_);
+ receive_stream_ = NULL;
+
+ // Wait() waits for a received packet.
+ EXPECT_EQ(kEventSignaled, input_observer.Wait());
+
+ StopSending();
+
+ DestroyStreams();
+
+ send_transport.StopSending();
+ receive_transport.StopSending();
+}
+
+void EndToEndTest::RespectsRtcpMode(newapi::RtcpMode rtcp_mode) {
+ static const int kNumCompoundRtcpPacketsToObserve = 10;
+ class RtcpModeObserver : public test::EndToEndTest {
+ public:
+ explicit RtcpModeObserver(newapi::RtcpMode rtcp_mode)
+ : EndToEndTest(kDefaultTimeoutMs),
+ rtcp_mode_(rtcp_mode),
+ sent_rtp_(0),
+ sent_rtcp_(0) {}
+
+ private:
+ virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
+ if (++sent_rtp_ % 3 == 0)
+ return DROP_PACKET;
+
+ return SEND_PACKET;
+ }
+
+ virtual Action OnReceiveRtcp(const uint8_t* packet,
+ size_t length) OVERRIDE {
+ ++sent_rtcp_;
+ RTCPUtility::RTCPParserV2 parser(packet, length, true);
+ EXPECT_TRUE(parser.IsValid());
+
+ RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
+ bool has_report_block = false;
+ while (packet_type != RTCPUtility::kRtcpNotValidCode) {
+ EXPECT_NE(RTCPUtility::kRtcpSrCode, packet_type);
+ if (packet_type == RTCPUtility::kRtcpRrCode) {
+ has_report_block = true;
+ break;
+ }
+ packet_type = parser.Iterate();
+ }
+
+ switch (rtcp_mode_) {
+ case newapi::kRtcpCompound:
+ if (!has_report_block) {
+ ADD_FAILURE() << "Received RTCP packet without receiver report for "
+ "kRtcpCompound.";
+ observation_complete_->Set();
+ }
+
+ if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
+ observation_complete_->Set();
+
+ break;
+ case newapi::kRtcpReducedSize:
+ if (!has_report_block)
+ observation_complete_->Set();
+ break;
+ }
+
+ return SEND_PACKET;
+ }
+
+ virtual void ModifyConfigs(
+ VideoSendStream::Config* send_config,
+ VideoReceiveStream::Config* receive_config,
+ std::vector<VideoStream>* video_streams) OVERRIDE {
+ send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
+ receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
+ receive_config->rtp.rtcp_mode = rtcp_mode_;
+ }
+
+ virtual void PerformTest() OVERRIDE {
+ EXPECT_EQ(kEventSignaled, Wait())
+ << (rtcp_mode_ == newapi::kRtcpCompound
+ ? "Timed out before observing enough compound packets."
+ : "Timed out before receiving a non-compound RTCP packet.");
+ }
+
+ newapi::RtcpMode rtcp_mode_;
+ int sent_rtp_;
+ int sent_rtcp_;
+ } test(rtcp_mode);
+
+ RunBaseTest(&test);
+}
+
+TEST_F(EndToEndTest, UsesRtcpCompoundMode) {
+ RespectsRtcpMode(newapi::kRtcpCompound);
+}
+
+TEST_F(EndToEndTest, UsesRtcpReducedSizeMode) {
+ RespectsRtcpMode(newapi::kRtcpReducedSize);
+}
+
+// Test sets up a Call multiple senders with different resolutions and SSRCs.
+// Another is set up to receive all three of these with different renderers.
+// Each renderer verifies that it receives the expected resolution, and as soon
+// as every renderer has received a frame, the test finishes.
+TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) {
+ static const size_t kNumStreams = 3;
+
+ class VideoOutputObserver : public VideoRenderer {
+ public:
+ VideoOutputObserver(test::FrameGeneratorCapturer** capturer,
+ int width,
+ int height)
+ : capturer_(capturer),
+ width_(width),
+ height_(height),
+ done_(EventWrapper::Create()) {}
+
+ virtual void RenderFrame(const I420VideoFrame& video_frame,
+ int time_to_render_ms) OVERRIDE {
+ EXPECT_EQ(width_, video_frame.width());
+ EXPECT_EQ(height_, video_frame.height());
+ (*capturer_)->Stop();
+ done_->Set();
+ }
+
+ EventTypeWrapper Wait() { return done_->Wait(kDefaultTimeoutMs); }
+
+ private:
+ test::FrameGeneratorCapturer** capturer_;
+ int width_;
+ int height_;
+ scoped_ptr<EventWrapper> done_;
+ };
+
+ struct {
+ uint32_t ssrc;
+ int width;
+ int height;
+ } codec_settings[kNumStreams] = {{1, 640, 480}, {2, 320, 240}, {3, 240, 160}};
+
+ test::DirectTransport sender_transport, receiver_transport;
+ scoped_ptr<Call> sender_call(Call::Create(Call::Config(&sender_transport)));
+ scoped_ptr<Call> receiver_call(
+ Call::Create(Call::Config(&receiver_transport)));
+ sender_transport.SetReceiver(receiver_call->Receiver());
+ receiver_transport.SetReceiver(sender_call->Receiver());
+
+ VideoSendStream* send_streams[kNumStreams];
+ VideoReceiveStream* receive_streams[kNumStreams];
+
+ VideoOutputObserver* observers[kNumStreams];
+ test::FrameGeneratorCapturer* frame_generators[kNumStreams];
+
+ scoped_ptr<VP8Encoder> encoders[kNumStreams];
+ for (size_t i = 0; i < kNumStreams; ++i)
+ encoders[i].reset(VP8Encoder::Create());
+
+ for (size_t i = 0; i < kNumStreams; ++i) {
+ uint32_t ssrc = codec_settings[i].ssrc;
+ int width = codec_settings[i].width;
+ int height = codec_settings[i].height;
+ observers[i] = new VideoOutputObserver(&frame_generators[i], width, height);
+
+ VideoSendStream::Config send_config = sender_call->GetDefaultSendConfig();
+ send_config.rtp.ssrcs.push_back(ssrc);
+ send_config.encoder_settings.encoder = encoders[i].get();
+ send_config.encoder_settings.payload_name = "VP8";
+ send_config.encoder_settings.payload_type = 124;
+ std::vector<VideoStream> video_streams = test::CreateVideoStreams(1);
+ VideoStream* stream = &video_streams[0];
+ stream->width = width;
+ stream->height = height;
+ stream->max_framerate = 5;
+ stream->min_bitrate_bps = stream->target_bitrate_bps =
+ stream->max_bitrate_bps = 100000;
+ send_streams[i] =
+ sender_call->CreateVideoSendStream(send_config, video_streams, NULL);
+ send_streams[i]->Start();
+
+ VideoReceiveStream::Config receive_config =
+ receiver_call->GetDefaultReceiveConfig();
+ receive_config.renderer = observers[i];
+ receive_config.rtp.remote_ssrc = ssrc;
+ receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
+ VideoCodec codec =
+ test::CreateDecoderVideoCodec(send_config.encoder_settings);
+ receive_config.codecs.push_back(codec);
+ receive_streams[i] =
+ receiver_call->CreateVideoReceiveStream(receive_config);
+ receive_streams[i]->Start();
+
+ frame_generators[i] = test::FrameGeneratorCapturer::Create(
+ send_streams[i]->Input(), width, height, 30, Clock::GetRealTimeClock());
+ frame_generators[i]->Start();
+ }
+
+ for (size_t i = 0; i < kNumStreams; ++i) {
+ EXPECT_EQ(kEventSignaled, observers[i]->Wait())
+ << "Timed out while waiting for observer " << i << " to render.";
+ }
+
+ for (size_t i = 0; i < kNumStreams; ++i) {
+ frame_generators[i]->Stop();
+ sender_call->DestroyVideoSendStream(send_streams[i]);
+ receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
+ delete frame_generators[i];
+ delete observers[i];
+ }
+
+ sender_transport.StopSending();
+ receiver_transport.StopSending();
+}
+
+TEST_F(EndToEndTest, ObserversEncodedFrames) {
+ class EncodedFrameTestObserver : public EncodedFrameObserver {
+ public:
+ EncodedFrameTestObserver()
+ : length_(0),
+ frame_type_(kFrameEmpty),
+ called_(EventWrapper::Create()) {}
+ virtual ~EncodedFrameTestObserver() {}
+
+ virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
+ frame_type_ = encoded_frame.frame_type_;
+ length_ = encoded_frame.length_;
+ buffer_.reset(new uint8_t[length_]);
+ memcpy(buffer_.get(), encoded_frame.data_, length_);
+ called_->Set();
+ }
+
+ EventTypeWrapper Wait() { return called_->Wait(kDefaultTimeoutMs); }
+
+ void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
+ ASSERT_EQ(length_, observer.length_)
+ << "Observed frames are of different lengths.";
+ EXPECT_EQ(frame_type_, observer.frame_type_)
+ << "Observed frames have different frame types.";
+ EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
+ << "Observed encoded frames have different content.";
+ }
+
+ private:
+ scoped_ptr<uint8_t[]> buffer_;
+ size_t length_;
+ FrameType frame_type_;
+ scoped_ptr<EventWrapper> called_;
+ };
+
+ EncodedFrameTestObserver post_encode_observer;
+ EncodedFrameTestObserver pre_decode_observer;
+
+ test::DirectTransport sender_transport, receiver_transport;
+
+ CreateCalls(Call::Config(&sender_transport),
+ Call::Config(&receiver_transport));
+
+ sender_transport.SetReceiver(receiver_call_->Receiver());
+ receiver_transport.SetReceiver(sender_call_->Receiver());
+
+ CreateSendConfig(1);
+ CreateMatchingReceiveConfigs();
+ send_config_.post_encode_callback = &post_encode_observer;
+ receive_config_.pre_decode_callback = &pre_decode_observer;
+
+ CreateStreams();
+ StartSending();
+
+ scoped_ptr<test::FrameGenerator> frame_generator(test::FrameGenerator::Create(
+ video_streams_[0].width, video_streams_[0].height));
+ send_stream_->Input()->SwapFrame(frame_generator->NextFrame());
+
+ EXPECT_EQ(kEventSignaled, post_encode_observer.Wait())
+ << "Timed out while waiting for send-side encoded-frame callback.";
+
+ EXPECT_EQ(kEventSignaled, pre_decode_observer.Wait())
+ << "Timed out while waiting for pre-decode encoded-frame callback.";
+
+ post_encode_observer.ExpectEqualFrames(pre_decode_observer);
+
+ StopSending();
+
+ sender_transport.StopSending();
+ receiver_transport.StopSending();
+
+ DestroyStreams();
+}
+
+TEST_F(EndToEndTest, ReceiveStreamSendsRemb) {
+ class RembObserver : public test::EndToEndTest {
+ public:
+ RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
+
+ virtual Action OnReceiveRtcp(const uint8_t* packet,
+ size_t length) OVERRIDE {
+ RTCPUtility::RTCPParserV2 parser(packet, length, true);
+ EXPECT_TRUE(parser.IsValid());
+
+ bool received_psfb = false;
+ bool received_remb = false;
+ RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
+ while (packet_type != RTCPUtility::kRtcpNotValidCode) {
+ if (packet_type == RTCPUtility::kRtcpPsfbRembCode) {
+ const RTCPUtility::RTCPPacket& packet = parser.Packet();
+ EXPECT_EQ(packet.PSFBAPP.SenderSSRC, kReceiverLocalSsrc);
+ received_psfb = true;
+ } else if (packet_type == RTCPUtility::kRtcpPsfbRembItemCode) {
+ const RTCPUtility::RTCPPacket& packet = parser.Packet();
+ EXPECT_GT(packet.REMBItem.BitRate, 0u);
+ EXPECT_EQ(packet.REMBItem.NumberOfSSRCs, 1u);
+ EXPECT_EQ(packet.REMBItem.SSRCs[0], kSendSsrcs[0]);
+ received_remb = true;
+ }
+ packet_type = parser.Iterate();
+ }
+ if (received_psfb && received_remb)
+ observation_complete_->Set();
+ return SEND_PACKET;
+ }
+ virtual void PerformTest() OVERRIDE {
+ EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for a "
+ "receiver RTCP REMB packet to be "
+ "sent.";
+ }
+ } test;
+
+ RunBaseTest(&test);
+}
+
+void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
+ static const int kNumRtcpReportPacketsToObserve = 5;
+ class RtcpXrObserver : public test::EndToEndTest {
+ public:
+ explicit RtcpXrObserver(bool enable_rrtr)
+ : EndToEndTest(kDefaultTimeoutMs),
+ enable_rrtr_(enable_rrtr),
+ sent_rtcp_sr_(0),
+ sent_rtcp_rr_(0),
+ sent_rtcp_rrtr_(0),
+ sent_rtcp_dlrr_(0) {}
+
+ private:
+ // Receive stream should send RR packets (and RRTR packets if enabled).
+ virtual Action OnReceiveRtcp(const uint8_t* packet,
+ size_t length) OVERRIDE {
+ RTCPUtility::RTCPParserV2 parser(packet, length, true);
+ EXPECT_TRUE(parser.IsValid());
+
+ RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
+ while (packet_type != RTCPUtility::kRtcpNotValidCode) {
+ if (packet_type == RTCPUtility::kRtcpRrCode) {
+ ++sent_rtcp_rr_;
+ } else if (packet_type ==
+ RTCPUtility::kRtcpXrReceiverReferenceTimeCode) {
+ ++sent_rtcp_rrtr_;
+ }
+ EXPECT_NE(packet_type, RTCPUtility::kRtcpSrCode);
+ EXPECT_NE(packet_type, RTCPUtility::kRtcpXrDlrrReportBlockItemCode);
+ packet_type = parser.Iterate();
+ }
+ return SEND_PACKET;
+ }
+ // Send stream should send SR packets (and DLRR packets if enabled).
+ virtual Action OnSendRtcp(const uint8_t* packet, size_t length) {
+ RTCPUtility::RTCPParserV2 parser(packet, length, true);
+ EXPECT_TRUE(parser.IsValid());
+
+ RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
+ while (packet_type != RTCPUtility::kRtcpNotValidCode) {
+ if (packet_type == RTCPUtility::kRtcpSrCode) {
+ ++sent_rtcp_sr_;
+ } else if (packet_type == RTCPUtility::kRtcpXrDlrrReportBlockItemCode) {
+ ++sent_rtcp_dlrr_;
+ }
+ EXPECT_NE(packet_type, RTCPUtility::kRtcpXrReceiverReferenceTimeCode);
+ packet_type = parser.Iterate();
+ }
+ if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
+ sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve) {
+ if (enable_rrtr_) {
+ EXPECT_GT(sent_rtcp_rrtr_, 0);
+ EXPECT_GT(sent_rtcp_dlrr_, 0);
+ } else {
+ EXPECT_EQ(0, sent_rtcp_rrtr_);
+ EXPECT_EQ(0, sent_rtcp_dlrr_);
+ }
+ observation_complete_->Set();
+ }
+ return SEND_PACKET;
+ }
+
+ virtual void ModifyConfigs(
+ VideoSendStream::Config* send_config,
+ VideoReceiveStream::Config* receive_config,
+ std::vector<VideoStream>* video_streams) OVERRIDE {
+ receive_config->rtp.rtcp_mode = newapi::kRtcpReducedSize;
+ receive_config->rtp.rtcp_xr.receiver_reference_time_report = enable_rrtr_;
+ }
+
+ virtual void PerformTest() OVERRIDE {
+ EXPECT_EQ(kEventSignaled, Wait())
+ << "Timed out while waiting for RTCP SR/RR packets to be sent.";
+ }
+
+ bool enable_rrtr_;
+ int sent_rtcp_sr_;
+ int sent_rtcp_rr_;
+ int sent_rtcp_rrtr_;
+ int sent_rtcp_dlrr_;
+ } test(enable_rrtr);
+
+ RunBaseTest(&test);
+}
+
+TEST_F(EndToEndTest, GetStats) {
+ class StatsObserver : public test::EndToEndTest, public I420FrameCallback {
+ public:
+ StatsObserver()
+ : EndToEndTest(kLongTimeoutMs),
+ receive_stream_(NULL),
+ send_stream_(NULL),
+ expected_receive_ssrc_(),
+ expected_send_ssrcs_(),
+ check_stats_event_(EventWrapper::Create()) {}
+
+ private:
+ virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
+ check_stats_event_->Set();
+ return SEND_PACKET;
+ }
+
+ virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
+ check_stats_event_->Set();
+ return SEND_PACKET;
+ }
+
+ virtual Action OnReceiveRtp(const uint8_t* packet, size_t length) OVERRIDE {
+ check_stats_event_->Set();
+ return SEND_PACKET;
+ }
+
+ virtual Action OnReceiveRtcp(const uint8_t* packet,
+ size_t length) OVERRIDE {
+ check_stats_event_->Set();
+ return SEND_PACKET;
+ }
+
+ virtual void FrameCallback(I420VideoFrame* video_frame) OVERRIDE {
+ // Ensure that we have at least 5ms send side delay.
+ int64_t render_time = video_frame->render_time_ms();
+ if (render_time > 0)
+ video_frame->set_render_time_ms(render_time - 5);
+ }
+
+ bool CheckReceiveStats() {
+ assert(receive_stream_ != NULL);
+ VideoReceiveStream::Stats stats = receive_stream_->GetStats();
+ EXPECT_EQ(expected_receive_ssrc_, stats.ssrc);
+
+ // Make sure all fields have been populated.
+
+ receive_stats_filled_["IncomingRate"] |=
+ stats.network_frame_rate != 0 || stats.bitrate_bps != 0;
+
+ receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
+
+ receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
+
+ receive_stats_filled_["StatisticsUpdated"] |=
+ stats.rtcp_stats.cumulative_lost != 0 ||
+ stats.rtcp_stats.extended_max_sequence_number != 0 ||
+ stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
+
+ receive_stats_filled_["DataCountersUpdated"] |=
+ stats.rtp_stats.bytes != 0 || stats.rtp_stats.fec_packets != 0 ||
+ stats.rtp_stats.header_bytes != 0 || stats.rtp_stats.packets != 0 ||
+ stats.rtp_stats.padding_bytes != 0 ||
+ stats.rtp_stats.retransmitted_packets != 0;
+
+ receive_stats_filled_["CodecStats"] |=
+ stats.avg_delay_ms != 0 || stats.discarded_packets != 0 ||
+ stats.key_frames != 0 || stats.delta_frames != 0;
+
+ receive_stats_filled_["CName"] |= stats.c_name == expected_cname_;
+
+ return AllStatsFilled(receive_stats_filled_);
+ }
+
+ bool CheckSendStats() {
+ assert(send_stream_ != NULL);
+ VideoSendStream::Stats stats = send_stream_->GetStats();
+
+ send_stats_filled_["NumStreams"] |=
+ stats.substreams.size() == expected_send_ssrcs_.size();
+
+ send_stats_filled_["Delay"] |=
+ stats.avg_delay_ms != 0 || stats.max_delay_ms != 0;
+
+ receive_stats_filled_["CName"] |= stats.c_name == expected_cname_;
+
+ for (std::map<uint32_t, StreamStats>::const_iterator it =
+ stats.substreams.begin();
+ it != stats.substreams.end();
+ ++it) {
+ EXPECT_TRUE(expected_send_ssrcs_.find(it->first) !=
+ expected_send_ssrcs_.end());
+
+ send_stats_filled_[CompoundKey("IncomingRate", it->first)] |=
+ stats.input_frame_rate != 0;
+
+ const StreamStats& stream_stats = it->second;
+
+ send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
+ stream_stats.rtcp_stats.cumulative_lost != 0 ||
+ stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
+ stream_stats.rtcp_stats.fraction_lost != 0;
+
+ send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
+ stream_stats.rtp_stats.fec_packets != 0 ||
+ stream_stats.rtp_stats.padding_bytes != 0 ||
+ stream_stats.rtp_stats.retransmitted_packets != 0 ||
+ stream_stats.rtp_stats.packets != 0;
+
+ send_stats_filled_[CompoundKey("BitrateStatisticsObserver",
+ it->first)] |=
+ stream_stats.bitrate_bps != 0;
+
+ send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
+ stream_stats.delta_frames != 0 || stream_stats.key_frames != 0;
+
+ send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
+ stats.encode_frame_rate != 0;
+ }
+
+ return AllStatsFilled(send_stats_filled_);
+ }
+
+ std::string CompoundKey(const char* name, uint32_t ssrc) {
+ std::ostringstream oss;
+ oss << name << "_" << ssrc;
+ return oss.str();
+ }
+
+ bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
+ for (std::map<std::string, bool>::const_iterator it = stats_map.begin();
+ it != stats_map.end();
+ ++it) {
+ if (!it->second)
+ return false;
+ }
+ return true;
+ }
+
+ virtual void ModifyConfigs(
+ VideoSendStream::Config* send_config,
+ VideoReceiveStream::Config* receive_config,
+ std::vector<VideoStream>* video_streams) OVERRIDE {
+ send_config->pre_encode_callback = this; // Used to inject delay.
+ send_config->rtp.c_name = "SomeCName";
+
+ expected_receive_ssrc_ = receive_config->rtp.local_ssrc;
+ const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
+ for (size_t i = 0; i < ssrcs.size(); ++i)
+ expected_send_ssrcs_.insert(ssrcs[i]);
+
+ expected_cname_ = send_config->rtp.c_name;
+ }
+
+ virtual void OnStreamsCreated(VideoSendStream* send_stream,
+ VideoReceiveStream* receive_stream) OVERRIDE {
+ send_stream_ = send_stream;
+ receive_stream_ = receive_stream;
+ }
+
+ virtual void PerformTest() OVERRIDE {
+ Clock* clock = Clock::GetRealTimeClock();
+ int64_t now = clock->TimeInMilliseconds();
+ int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
+ bool receive_ok = false;
+ bool send_ok = false;
+
+ while (now < stop_time) {
+ if (!receive_ok)
+ receive_ok = CheckReceiveStats();
+ if (!send_ok)
+ send_ok = CheckSendStats();
+
+ if (receive_ok && send_ok)
+ return;
+
+ int64_t time_until_timout_ = stop_time - now;
+ if (time_until_timout_ > 0)
+ check_stats_event_->Wait(time_until_timout_);
+ now = clock->TimeInMilliseconds();
+ }
+
+ ADD_FAILURE() << "Timed out waiting for filled stats.";
+ for (std::map<std::string, bool>::const_iterator it =
+ receive_stats_filled_.begin();
+ it != receive_stats_filled_.end();
+ ++it) {
+ if (!it->second) {
+ ADD_FAILURE() << "Missing receive stats: " << it->first;
+ }
+ }
+
+ for (std::map<std::string, bool>::const_iterator it =
+ send_stats_filled_.begin();
+ it != send_stats_filled_.end();
+ ++it) {
+ if (!it->second) {
+ ADD_FAILURE() << "Missing send stats: " << it->first;
+ }
+ }
+ }
+
+ VideoReceiveStream* receive_stream_;
+ std::map<std::string, bool> receive_stats_filled_;
+
+ VideoSendStream* send_stream_;
+ std::map<std::string, bool> send_stats_filled_;
+
+ uint32_t expected_receive_ssrc_;
+ std::set<uint32_t> expected_send_ssrcs_;
+ std::string expected_cname_;
+
+ scoped_ptr<EventWrapper> check_stats_event_;
+ } test;
+
+ RunBaseTest(&test);
+}
+
+TEST_F(EndToEndTest, ReceiverReferenceTimeReportEnabled) {
+ TestXrReceiverReferenceTimeReport(true);
+}
+
+TEST_F(EndToEndTest, ReceiverReferenceTimeReportDisabled) {
+ TestXrReceiverReferenceTimeReport(false);
+}
+
+TEST_F(EndToEndTest, TestReceivedRtpPacketStats) {
+ static const size_t kNumRtpPacketsToSend = 5;
+ class ReceivedRtpStatsObserver : public test::EndToEndTest {
+ public:
+ ReceivedRtpStatsObserver()
+ : EndToEndTest(kDefaultTimeoutMs),
+ receive_stream_(NULL),
+ sent_rtp_(0) {}
+
+ private:
+ virtual void OnStreamsCreated(VideoSendStream* send_stream,
+ VideoReceiveStream* receive_stream) OVERRIDE {
+ receive_stream_ = receive_stream;
+ }
+
+ virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
+ if (sent_rtp_ >= kNumRtpPacketsToSend) {
+ VideoReceiveStream::Stats stats = receive_stream_->GetStats();
+ if (kNumRtpPacketsToSend == stats.rtp_stats.packets) {
+ observation_complete_->Set();
+ }
+ return DROP_PACKET;
+ }
+ ++sent_rtp_;
+ return SEND_PACKET;
+ }
+
+ virtual void PerformTest() OVERRIDE {
+ EXPECT_EQ(kEventSignaled, Wait())
+ << "Timed out while verifying number of received RTP packets.";
+ }
+
+ VideoReceiveStream* receive_stream_;
+ uint32_t sent_rtp_;
+ } test;
+
+ RunBaseTest(&test);
+}
+
+} // namespace webrtc
diff --git a/webrtc/video/full_stack.cc b/webrtc/video/full_stack.cc
index 6b21cbe..1c03042 100644
--- a/webrtc/video/full_stack.cc
+++ b/webrtc/video/full_stack.cc
@@ -24,6 +24,7 @@
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
#include "webrtc/system_wrappers/interface/sleep.h"
#include "webrtc/system_wrappers/interface/thread_annotations.h"
+#include "webrtc/test/call_test.h"
#include "webrtc/test/direct_transport.h"
#include "webrtc/test/encoder_settings.h"
#include "webrtc/test/fake_encoder.h"
@@ -34,7 +35,6 @@
namespace webrtc {
-static const uint32_t kSendSsrc = 0x654321;
static const int kFullStackTestDurationSecs = 10;
struct FullStackTestParams {
@@ -49,20 +49,9 @@
double avg_ssim_threshold;
};
-FullStackTestParams paris_qcif = {
- "net_delay_0_0_plr_0", {"paris_qcif", 176, 144, 30}, 300, 36.0, 0.96};
-
-// TODO(pbos): Decide on psnr/ssim thresholds for foreman_cif.
-FullStackTestParams foreman_cif = {
- "foreman_cif_net_delay_0_0_plr_0",
- {"foreman_cif", 352, 288, 30},
- 700,
- 0.0,
- 0.0};
-
-class FullStackTest : public ::testing::TestWithParam<FullStackTestParams> {
+class FullStackTest : public test::CallTest {
protected:
- std::map<uint32_t, bool> reserved_ssrcs_;
+ void TestWithoutPacketLoss(const FullStackTestParams& params);
};
class VideoAnalyzer : public PacketReceiver,
@@ -200,7 +189,9 @@
last_rendered_frame_.CopyFrame(video_frame);
}
- void Wait() { done_->Wait(120 * 1000); }
+ void Wait() {
+ EXPECT_EQ(kEventSignaled, done_->Wait(FullStackTest::kLongTimeoutMs));
+ }
VideoSendStreamInput* input_;
Transport* transport_;
@@ -376,10 +367,7 @@
const scoped_ptr<EventWrapper> done_;
};
-TEST_P(FullStackTest, NoPacketLoss) {
- static const uint32_t kReceiverLocalSsrc = 0x123456;
- FullStackTestParams params = GetParam();
-
+void FullStackTest::TestWithoutPacketLoss(const FullStackTestParams& params) {
test::DirectTransport transport;
VideoAnalyzer analyzer(NULL,
&transport,
@@ -388,32 +376,32 @@
params.avg_ssim_threshold,
kFullStackTestDurationSecs * params.clip.fps);
- Call::Config call_config(&analyzer);
+ CreateCalls(Call::Config(&analyzer), Call::Config(&analyzer));
- scoped_ptr<Call> call(Call::Create(call_config));
- analyzer.SetReceiver(call->Receiver());
+ analyzer.SetReceiver(receiver_call_->Receiver());
transport.SetReceiver(&analyzer);
- VideoSendStream::Config send_config = call->GetDefaultSendConfig();
- send_config.rtp.ssrcs.push_back(kSendSsrc);
+ CreateSendConfig(1);
scoped_ptr<VP8Encoder> encoder(VP8Encoder::Create());
- send_config.encoder_settings.encoder = encoder.get();
- send_config.encoder_settings.payload_name = "VP8";
- send_config.encoder_settings.payload_type = 124;
- std::vector<VideoStream> video_streams = test::CreateVideoStreams(1);
- VideoStream* stream = &video_streams[0];
+ send_config_.encoder_settings.encoder = encoder.get();
+ send_config_.encoder_settings.payload_name = "VP8";
+ send_config_.encoder_settings.payload_type = 124;
+
+ VideoStream* stream = &video_streams_[0];
stream->width = params.clip.width;
stream->height = params.clip.height;
stream->min_bitrate_bps = stream->target_bitrate_bps =
stream->max_bitrate_bps = params.bitrate * 1000;
stream->max_framerate = params.clip.fps;
- VideoSendStream* send_stream =
- call->CreateVideoSendStream(send_config, video_streams, NULL);
- analyzer.input_ = send_stream->Input();
+ CreateMatchingReceiveConfigs();
+ receive_config_.renderer = &analyzer;
- scoped_ptr<test::FrameGeneratorCapturer> file_capturer(
+ CreateStreams();
+ analyzer.input_ = send_stream_->Input();
+
+ frame_generator_capturer_.reset(
test::FrameGeneratorCapturer::CreateFromYuvFile(
&analyzer,
test::ResourcePath(params.clip.name, "yuv").c_str(),
@@ -421,39 +409,41 @@
params.clip.height,
params.clip.fps,
Clock::GetRealTimeClock()));
- ASSERT_TRUE(file_capturer.get() != NULL)
+
+ ASSERT_TRUE(frame_generator_capturer_.get() != NULL)
<< "Could not create capturer for " << params.clip.name
<< ".yuv. Is this resource file present?";
- VideoReceiveStream::Config receive_config = call->GetDefaultReceiveConfig();
- VideoCodec codec =
- test::CreateDecoderVideoCodec(send_config.encoder_settings);
- receive_config.codecs.push_back(codec);
- receive_config.rtp.remote_ssrc = send_config.rtp.ssrcs[0];
- receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
- receive_config.renderer = &analyzer;
-
- VideoReceiveStream* receive_stream =
- call->CreateVideoReceiveStream(receive_config);
-
- receive_stream->Start();
- send_stream->Start();
- file_capturer->Start();
+ Start();
analyzer.Wait();
- file_capturer->Stop();
- send_stream->Stop();
- receive_stream->Stop();
-
- call->DestroyVideoReceiveStream(receive_stream);
- call->DestroyVideoSendStream(send_stream);
-
transport.StopSending();
+
+ Stop();
+
+ DestroyStreams();
}
-INSTANTIATE_TEST_CASE_P(FullStack,
- FullStackTest,
- ::testing::Values(paris_qcif, foreman_cif));
+FullStackTestParams paris_qcif = {"net_delay_0_0_plr_0",
+ {"paris_qcif", 176, 144, 30},
+ 300,
+ 36.0,
+ 0.96};
+
+// TODO(pbos): Decide on psnr/ssim thresholds for foreman_cif.
+FullStackTestParams foreman_cif = {"foreman_cif_net_delay_0_0_plr_0",
+ {"foreman_cif", 352, 288, 30},
+ 700,
+ 0.0,
+ 0.0};
+
+TEST_F(FullStackTest, ParisQcifWithoutPacketLoss) {
+ TestWithoutPacketLoss(paris_qcif);
+}
+
+TEST_F(FullStackTest, ForemanCifWithoutPacketLoss) {
+ TestWithoutPacketLoss(foreman_cif);
+}
} // namespace webrtc
diff --git a/webrtc/video/rampup_tests.cc b/webrtc/video/rampup_tests.cc
index 94f1c19..5529f92 100644
--- a/webrtc/video/rampup_tests.cc
+++ b/webrtc/video/rampup_tests.cc
@@ -27,6 +27,7 @@
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/event_wrapper.h"
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
+#include "webrtc/test/call_test.h"
#include "webrtc/test/direct_transport.h"
#include "webrtc/test/encoder_settings.h"
#include "webrtc/test/fake_decoder.h"
@@ -388,7 +389,9 @@
}
}
- EventTypeWrapper Wait() { return test_done_->Wait(120 * 1000); }
+ EventTypeWrapper Wait() {
+ return test_done_->Wait(test::CallTest::kLongTimeoutMs);
+ }
private:
static const unsigned int kHighBandwidthLimitBps = 80000;
@@ -420,10 +423,7 @@
};
} // namespace
-class RampUpTest : public ::testing::Test {
- public:
- virtual void SetUp() { reserved_ssrcs_.clear(); }
-
+class RampUpTest : public test::CallTest {
protected:
void RunRampUpTest(bool rtx,
size_t num_streams,
@@ -445,33 +445,26 @@
call_config.start_bitrate_bps = start_bitrate_bps;
stream_observer.set_start_bitrate_bps(start_bitrate_bps);
}
- scoped_ptr<Call> call(Call::Create(call_config));
- VideoSendStream::Config send_config = call->GetDefaultSendConfig();
- receiver_transport.SetReceiver(call->Receiver());
+ CreateSenderCall(call_config);
+ CreateSendConfig(num_streams);
- test::FakeEncoder encoder(Clock::GetRealTimeClock());
- send_config.encoder_settings.encoder = &encoder;
- send_config.encoder_settings.payload_type = 125;
- send_config.encoder_settings.payload_name = "FAKE";
- std::vector<VideoStream> video_streams =
- test::CreateVideoStreams(num_streams);
+ receiver_transport.SetReceiver(sender_call_->Receiver());
if (num_streams == 1) {
- video_streams[0].target_bitrate_bps = 2000000;
- video_streams[0].max_bitrate_bps = 2000000;
+ video_streams_[0].target_bitrate_bps = 2000000;
+ video_streams_[0].max_bitrate_bps = 2000000;
}
- send_config.rtp.nack.rtp_history_ms = 1000;
- send_config.rtp.ssrcs = ssrcs;
+ send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
+ send_config_.rtp.ssrcs = ssrcs;
if (rtx) {
- send_config.rtp.rtx.payload_type = 96;
- send_config.rtp.rtx.ssrcs = rtx_ssrcs;
- send_config.rtp.rtx.pad_with_redundant_payloads = true;
+ send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
+ send_config_.rtp.rtx.ssrcs = rtx_ssrcs;
+ send_config_.rtp.rtx.pad_with_redundant_payloads = true;
}
- send_config.rtp.extensions.push_back(
- RtpExtension(RtpExtension::kTOffset,
- kTransmissionTimeOffsetExtensionId));
+ send_config_.rtp.extensions.push_back(RtpExtension(
+ RtpExtension::kTOffset, kTransmissionTimeOffsetExtensionId));
if (num_streams == 1) {
// For single stream rampup until 1mbps
@@ -480,32 +473,22 @@
// For multi stream rampup until all streams are being sent. That means
// enough birate to send all the target streams plus the min bitrate of
// the last one.
- int expected_bitrate_bps = video_streams.back().min_bitrate_bps;
- for (size_t i = 0; i < video_streams.size() - 1; ++i) {
- expected_bitrate_bps += video_streams[i].target_bitrate_bps;
+ int expected_bitrate_bps = video_streams_.back().min_bitrate_bps;
+ for (size_t i = 0; i < video_streams_.size() - 1; ++i) {
+ expected_bitrate_bps += video_streams_[i].target_bitrate_bps;
}
stream_observer.set_expected_bitrate_bps(expected_bitrate_bps);
}
- VideoSendStream* send_stream =
- call->CreateVideoSendStream(send_config, video_streams, NULL);
+ CreateStreams();
+ CreateFrameGeneratorCapturer();
- scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
- test::FrameGeneratorCapturer::Create(send_stream->Input(),
- video_streams.back().width,
- video_streams.back().height,
- video_streams.back().max_framerate,
- Clock::GetRealTimeClock()));
-
- send_stream->Start();
- frame_generator_capturer->Start();
+ Start();
EXPECT_EQ(kEventSignaled, stream_observer.Wait());
- frame_generator_capturer->Stop();
- send_stream->Stop();
-
- call->DestroyVideoSendStream(send_stream);
+ Stop();
+ DestroyStreams();
}
void RunRampUpDownUpTest(size_t number_of_streams, bool rtx) {
@@ -520,59 +503,27 @@
webrtc::Config webrtc_config;
call_config.webrtc_config = &webrtc_config;
webrtc_config.Set<PaddingStrategy>(new PaddingStrategy(rtx));
- scoped_ptr<Call> call(Call::Create(call_config));
- VideoSendStream::Config send_config = call->GetDefaultSendConfig();
+ CreateSenderCall(call_config);
+ receiver_transport.SetReceiver(sender_call_->Receiver());
- receiver_transport.SetReceiver(call->Receiver());
+ CreateSendConfig(number_of_streams);
- test::FakeEncoder encoder(Clock::GetRealTimeClock());
- send_config.encoder_settings.encoder = &encoder;
- send_config.encoder_settings.payload_type = 125;
- send_config.encoder_settings.payload_name = "FAKE";
- std::vector<VideoStream> video_streams =
- test::CreateVideoStreams(number_of_streams);
+ send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
+ send_config_.rtp.extensions.push_back(RtpExtension(
+ RtpExtension::kTOffset, kTransmissionTimeOffsetExtensionId));
+ send_config_.suspend_below_min_bitrate = true;
- send_config.rtp.nack.rtp_history_ms = 1000;
- send_config.rtp.ssrcs.insert(
- send_config.rtp.ssrcs.begin(), ssrcs.begin(), ssrcs.end());
- send_config.rtp.extensions.push_back(
- RtpExtension(RtpExtension::kTOffset,
- kTransmissionTimeOffsetExtensionId));
- send_config.suspend_below_min_bitrate = true;
+ CreateStreams();
+ stream_observer.SetSendStream(send_stream_);
- VideoSendStream* send_stream =
- call->CreateVideoSendStream(send_config, video_streams, NULL);
- stream_observer.SetSendStream(send_stream);
+ CreateFrameGeneratorCapturer();
- size_t width = 0;
- size_t height = 0;
- for (size_t i = 0; i < video_streams.size(); ++i) {
- size_t stream_width = video_streams[i].width;
- size_t stream_height = video_streams[i].height;
- if (stream_width > width)
- width = stream_width;
- if (stream_height > height)
- height = stream_height;
- }
-
- scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
- test::FrameGeneratorCapturer::Create(send_stream->Input(),
- width,
- height,
- 30,
- Clock::GetRealTimeClock()));
-
- send_stream->Start();
- frame_generator_capturer->Start();
+ Start();
EXPECT_EQ(kEventSignaled, stream_observer.Wait());
- stream_observer.StopSending();
- receiver_transport.StopSending();
- frame_generator_capturer->Stop();
- send_stream->Stop();
-
- call->DestroyVideoSendStream(send_stream);
+ Stop();
+ DestroyStreams();
}
private:
@@ -583,8 +534,6 @@
ssrcs.push_back(static_cast<uint32_t>(ssrc_offset + i));
return ssrcs;
}
-
- std::map<uint32_t, bool> reserved_ssrcs_;
};
TEST_F(RampUpTest, SingleStream) {
diff --git a/webrtc/video/video_send_stream_tests.cc b/webrtc/video/video_send_stream_tests.cc
index 3ae15d4..2d9bf5b 100644
--- a/webrtc/video/video_send_stream_tests.cc
+++ b/webrtc/video/video_send_stream_tests.cc
@@ -27,13 +27,9 @@
#include "webrtc/system_wrappers/interface/scoped_vector.h"
#include "webrtc/system_wrappers/interface/sleep.h"
#include "webrtc/system_wrappers/interface/thread_wrapper.h"
-#include "webrtc/test/direct_transport.h"
+#include "webrtc/test/call_test.h"
#include "webrtc/test/configurable_frame_size_encoder.h"
-#include "webrtc/test/encoder_settings.h"
-#include "webrtc/test/fake_encoder.h"
-#include "webrtc/test/frame_generator_capturer.h"
#include "webrtc/test/null_transport.h"
-#include "webrtc/test/rtp_rtcp_observer.h"
#include "webrtc/test/testsupport/perf_test.h"
#include "webrtc/video/transport_adapter.h"
#include "webrtc/video_send_stream.h"
@@ -59,94 +55,43 @@
virtual void* GetHandle() { return NULL; }
};
-class VideoSendStreamTest : public ::testing::Test {
- public:
- VideoSendStreamTest()
- : send_stream_(NULL), fake_encoder_(Clock::GetRealTimeClock()) {}
-
+class VideoSendStreamTest : public test::CallTest {
protected:
- void RunSendTest(Call* call,
- test::RtpRtcpObserver* observer) {
- send_stream_ =
- call->CreateVideoSendStream(send_config_, video_streams_, NULL);
- scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
- test::FrameGeneratorCapturer::Create(
- send_stream_->Input(), 320, 240, 30, Clock::GetRealTimeClock()));
- send_stream_->Start();
- frame_generator_capturer->Start();
-
- EXPECT_EQ(kEventSignaled, observer->Wait());
-
- observer->StopSending();
- frame_generator_capturer->Stop();
- send_stream_->Stop();
- call->DestroyVideoSendStream(send_stream_);
- }
-
- void CreateTestConfig(Call* call, size_t num_streams) {
- assert(num_streams <= kNumSendSsrcs);
- send_config_ = call->GetDefaultSendConfig();
- send_config_.encoder_settings.encoder = &fake_encoder_;
- send_config_.encoder_settings.payload_name = "FAKE";
- send_config_.encoder_settings.payload_type = kFakeSendPayloadType;
- video_streams_ = test::CreateVideoStreams(num_streams);
- send_config_.encoder_settings.payload_type = kFakeSendPayloadType;
- for (size_t i = 0; i < num_streams; ++i)
- send_config_.rtp.ssrcs.push_back(kSendSsrcs[i]);
- }
-
void TestNackRetransmission(uint32_t retransmit_ssrc,
uint8_t retransmit_payload_type);
-
void TestPacketFragmentationSize(VideoFormat format, bool with_fec);
-
void SendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
- enum { kNumSendSsrcs = 3 };
- static const uint8_t kSendPayloadType;
- static const uint8_t kSendRtxPayloadType;
- static const uint8_t kFakeSendPayloadType;
- static const uint32_t kSendSsrc;
- static const uint32_t kSendRtxSsrc;
- static const uint32_t kSendSsrcs[kNumSendSsrcs];
-
- VideoSendStream::Config send_config_;
- std::vector<VideoStream> video_streams_;
- VideoSendStream* send_stream_;
- test::FakeEncoder fake_encoder_;
};
-const uint8_t VideoSendStreamTest::kSendPayloadType = 100;
-const uint8_t VideoSendStreamTest::kFakeSendPayloadType = 125;
-const uint8_t VideoSendStreamTest::kSendRtxPayloadType = 98;
-const uint32_t VideoSendStreamTest::kSendRtxSsrc = 0xBADCAFE;
-const uint32_t VideoSendStreamTest::kSendSsrcs[kNumSendSsrcs] = {
- 0xC0FFED, 0xC0FFEE, 0xC0FFEF};
-const uint32_t VideoSendStreamTest::kSendSsrc =
- VideoSendStreamTest::kSendSsrcs[0];
-
void VideoSendStreamTest::SendsSetSsrcs(size_t num_ssrcs,
bool send_single_ssrc_first) {
- class SendSsrcObserver : public test::RtpRtcpObserver {
+ class SendsSetSsrcs : public test::SendTest {
public:
- SendSsrcObserver(const uint32_t* ssrcs,
- size_t num_ssrcs,
- bool send_single_ssrc_first)
- : RtpRtcpObserver(30 * 1000),
+ SendsSetSsrcs(const uint32_t* ssrcs,
+ size_t num_ssrcs,
+ bool send_single_ssrc_first)
+ : SendTest(kDefaultTimeoutMs),
+ num_ssrcs_(num_ssrcs),
+ send_single_ssrc_first_(send_single_ssrc_first),
ssrcs_to_observe_(num_ssrcs),
expect_single_ssrc_(send_single_ssrc_first) {
for (size_t i = 0; i < num_ssrcs; ++i)
valid_ssrcs_[ssrcs[i]] = true;
}
+ private:
virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
RTPHeader header;
EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
// TODO(pbos): Reenable this part of the test when #1695 is resolved and
- // all SSRCs are allocated on startup. This test was observed
- // to fail on TSan as the codec gets set before the SSRCs are
- // set up and some frames are sent on a random-generated SSRC
+ // all SSRCs are allocated on startup. This test was
+ // observed
+ // to fail on TSan as the codec gets set before the SSRCs
+ // are
+ // set up and some frames are sent on a random-generated
+ // SSRC
// before the correct SSRC gets set.
// EXPECT_TRUE(valid_ssrcs_[header.ssrc])
// << "Received unknown SSRC: " << header.ssrc;
@@ -169,98 +114,100 @@
return SEND_PACKET;
}
+ virtual void ModifyConfigs(
+ VideoSendStream::Config* send_config,
+ VideoReceiveStream::Config* receive_config,
+ std::vector<VideoStream>* video_streams) OVERRIDE {
+ if (num_ssrcs_ > 1) {
+ // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
+ for (size_t i = 0; i < video_streams->size(); ++i) {
+ (*video_streams)[i].min_bitrate_bps = 10000;
+ (*video_streams)[i].target_bitrate_bps = 10000;
+ (*video_streams)[i].max_bitrate_bps = 10000;
+ }
+ }
+
+ all_streams_ = *video_streams;
+ if (send_single_ssrc_first_)
+ video_streams->resize(1);
+ }
+
+ virtual void OnStreamsCreated(VideoSendStream* send_stream,
+ VideoReceiveStream* receive_stream) OVERRIDE {
+ send_stream_ = send_stream;
+ }
+
+ virtual void PerformTest() OVERRIDE {
+ EXPECT_EQ(kEventSignaled, Wait())
+ << "Timed out while waiting for "
+ << (send_single_ssrc_first_ ? "first SSRC." : "SSRCs.");
+
+ if (send_single_ssrc_first_) {
+ // Set full simulcast and continue with the rest of the SSRCs.
+ send_stream_->ReconfigureVideoEncoder(all_streams_, NULL);
+ EXPECT_EQ(kEventSignaled, Wait())
+ << "Timed out while waiting on additional SSRCs.";
+ }
+ }
+
private:
std::map<uint32_t, bool> valid_ssrcs_;
std::map<uint32_t, bool> is_observed_;
+
+ const size_t num_ssrcs_;
+ const bool send_single_ssrc_first_;
+
size_t ssrcs_to_observe_;
bool expect_single_ssrc_;
- } observer(kSendSsrcs, num_ssrcs, send_single_ssrc_first);
- Call::Config call_config(observer.SendTransport());
- scoped_ptr<Call> call(Call::Create(call_config));
+ VideoSendStream* send_stream_;
+ std::vector<VideoStream> all_streams_;
+ } test(kSendSsrcs, num_ssrcs, send_single_ssrc_first);
- CreateTestConfig(call.get(), num_ssrcs);
-
- if (num_ssrcs > 1) {
- // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
- for (size_t i = 0; i < video_streams_.size(); ++i) {
- video_streams_[i].min_bitrate_bps = 10000;
- video_streams_[i].target_bitrate_bps = 10000;
- video_streams_[i].max_bitrate_bps = 10000;
- }
- }
-
- std::vector<VideoStream> all_streams = video_streams_;
- if (send_single_ssrc_first)
- video_streams_.resize(1);
-
- send_stream_ =
- call->CreateVideoSendStream(send_config_, video_streams_, NULL);
- scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
- test::FrameGeneratorCapturer::Create(
- send_stream_->Input(), 320, 240, 30, Clock::GetRealTimeClock()));
- send_stream_->Start();
- frame_generator_capturer->Start();
-
- EXPECT_EQ(kEventSignaled, observer.Wait())
- << "Timed out while waiting for "
- << (send_single_ssrc_first ? "first SSRC." : "SSRCs.");
-
- if (send_single_ssrc_first) {
- // Set full simulcast and continue with the rest of the SSRCs.
- send_stream_->ReconfigureVideoEncoder(all_streams, NULL);
- EXPECT_EQ(kEventSignaled, observer.Wait())
- << "Timed out while waiting on additional SSRCs.";
- }
-
- observer.StopSending();
- frame_generator_capturer->Stop();
- send_stream_->Stop();
- call->DestroyVideoSendStream(send_stream_);
+ RunBaseTest(&test);
}
TEST_F(VideoSendStreamTest, CanStartStartedStream) {
test::NullTransport transport;
Call::Config call_config(&transport);
- scoped_ptr<Call> call(Call::Create(call_config));
+ CreateSenderCall(call_config);
- CreateTestConfig(call.get(), 1);
- VideoSendStream* stream =
- call->CreateVideoSendStream(send_config_, video_streams_, NULL);
- stream->Start();
- stream->Start();
- call->DestroyVideoSendStream(stream);
+ CreateSendConfig(1);
+ CreateStreams();
+ send_stream_->Start();
+ send_stream_->Start();
+ DestroyStreams();
}
TEST_F(VideoSendStreamTest, CanStopStoppedStream) {
test::NullTransport transport;
Call::Config call_config(&transport);
- scoped_ptr<Call> call(Call::Create(call_config));
+ CreateSenderCall(call_config);
- CreateTestConfig(call.get(), 1);
- VideoSendStream* stream =
- call->CreateVideoSendStream(send_config_, video_streams_, NULL);
- stream->Stop();
- stream->Stop();
- call->DestroyVideoSendStream(stream);
+ CreateSendConfig(1);
+ CreateStreams();
+ send_stream_->Stop();
+ send_stream_->Stop();
+ DestroyStreams();
}
TEST_F(VideoSendStreamTest, SendsSetSsrc) { SendsSetSsrcs(1, false); }
TEST_F(VideoSendStreamTest, DISABLED_SendsSetSimulcastSsrcs) {
- SendsSetSsrcs(kNumSendSsrcs, false);
+ SendsSetSsrcs(kNumSsrcs, false);
}
TEST_F(VideoSendStreamTest, DISABLED_CanSwitchToUseAllSsrcs) {
- SendsSetSsrcs(kNumSendSsrcs, true);
+ SendsSetSsrcs(kNumSsrcs, true);
}
TEST_F(VideoSendStreamTest, SupportsCName) {
static std::string kCName = "PjQatC14dGfbVwGPUOA9IH7RlsFDbWl4AhXEiDsBizo=";
- class CNameObserver : public test::RtpRtcpObserver {
+ class CNameObserver : public test::SendTest {
public:
- CNameObserver() : RtpRtcpObserver(30 * 1000) {}
+ CNameObserver() : SendTest(kDefaultTimeoutMs) {}
+ private:
virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
RTCPUtility::RTCPParserV2 parser(packet, length, true);
EXPECT_TRUE(parser.IsValid());
@@ -277,22 +224,28 @@
return SEND_PACKET;
}
- } observer;
- Call::Config call_config(observer.SendTransport());
- scoped_ptr<Call> call(Call::Create(call_config));
+ virtual void ModifyConfigs(
+ VideoSendStream::Config* send_config,
+ VideoReceiveStream::Config* receive_config,
+ std::vector<VideoStream>* video_streams) OVERRIDE {
+ send_config->rtp.c_name = kCName;
+ }
- CreateTestConfig(call.get(), 1);
- send_config_.rtp.c_name = kCName;
+ virtual void PerformTest() OVERRIDE {
+ EXPECT_EQ(kEventSignaled, Wait())
+ << "Timed out while waiting for RTCP with CNAME.";
+ }
+ } test;
- RunSendTest(call.get(), &observer);
+ RunBaseTest(&test);
}
TEST_F(VideoSendStreamTest, SupportsAbsoluteSendTime) {
static const uint8_t kAbsSendTimeExtensionId = 13;
- class AbsoluteSendTimeObserver : public test::RtpRtcpObserver {
+ class AbsoluteSendTimeObserver : public test::SendTest {
public:
- AbsoluteSendTimeObserver() : RtpRtcpObserver(30 * 1000) {
+ AbsoluteSendTimeObserver() : SendTest(kDefaultTimeoutMs) {
EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
kRtpExtensionAbsoluteSendTime, kAbsSendTimeExtensionId));
}
@@ -309,41 +262,35 @@
return SEND_PACKET;
}
- } observer;
- Call::Config call_config(observer.SendTransport());
- scoped_ptr<Call> call(Call::Create(call_config));
+ virtual void ModifyConfigs(
+ VideoSendStream::Config* send_config,
+ VideoReceiveStream::Config* receive_config,
+ std::vector<VideoStream>* video_streams) OVERRIDE {
+ send_config->rtp.extensions.push_back(
+ RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId));
+ }
+ virtual void PerformTest() OVERRIDE {
+ EXPECT_EQ(kEventSignaled, Wait())
+ << "Timed out while waiting for single RTP packet.";
+ }
- CreateTestConfig(call.get(), 1);
- send_config_.rtp.extensions.push_back(
- RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId));
+ } test;
- RunSendTest(call.get(), &observer);
+ RunBaseTest(&test);
}
TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) {
static const uint8_t kTOffsetExtensionId = 13;
- class DelayedEncoder : public test::FakeEncoder {
+ class TransmissionTimeOffsetObserver : public test::SendTest {
public:
- explicit DelayedEncoder(Clock* clock) : test::FakeEncoder(clock) {}
- virtual int32_t Encode(const I420VideoFrame& input_image,
- const CodecSpecificInfo* codec_specific_info,
- const std::vector<VideoFrameType>* frame_types)
- OVERRIDE {
- // A delay needs to be introduced to assure that we get a timestamp
- // offset.
- SleepMs(5);
- return FakeEncoder::Encode(input_image, codec_specific_info, frame_types);
- }
- } encoder(Clock::GetRealTimeClock());
-
- class TransmissionTimeOffsetObserver : public test::RtpRtcpObserver {
- public:
- TransmissionTimeOffsetObserver() : RtpRtcpObserver(30 * 1000) {
+ TransmissionTimeOffsetObserver()
+ : SendTest(kDefaultTimeoutMs), encoder_(Clock::GetRealTimeClock()) {
EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
kRtpExtensionTransmissionTimeOffset, kTOffsetExtensionId));
}
+ private:
virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
RTPHeader header;
EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
@@ -356,17 +303,40 @@
return SEND_PACKET;
}
- } observer;
- Call::Config call_config(observer.SendTransport());
- scoped_ptr<Call> call(Call::Create(call_config));
+ virtual void ModifyConfigs(
+ VideoSendStream::Config* send_config,
+ VideoReceiveStream::Config* receive_config,
+ std::vector<VideoStream>* video_streams) OVERRIDE {
+ send_config->encoder_settings.encoder = &encoder_;
+ send_config->rtp.extensions.push_back(
+ RtpExtension(RtpExtension::kTOffset, kTOffsetExtensionId));
+ }
- CreateTestConfig(call.get(), 1);
- send_config_.encoder_settings.encoder = &encoder;
- send_config_.rtp.extensions.push_back(
- RtpExtension(RtpExtension::kTOffset, kTOffsetExtensionId));
+ virtual void PerformTest() OVERRIDE {
+ EXPECT_EQ(kEventSignaled, Wait())
+ << "Timed out while waiting single RTP packet.";
+ }
- RunSendTest(call.get(), &observer);
+ class DelayedEncoder : public test::FakeEncoder {
+ public:
+ explicit DelayedEncoder(Clock* clock) : test::FakeEncoder(clock) {}
+ virtual int32_t Encode(
+ const I420VideoFrame& input_image,
+ const CodecSpecificInfo* codec_specific_info,
+ const std::vector<VideoFrameType>* frame_types) OVERRIDE {
+ // A delay needs to be introduced to assure that we get a timestamp
+ // offset.
+ SleepMs(5);
+ return FakeEncoder::Encode(
+ input_image, codec_specific_info, frame_types);
+ }
+ };
+
+ DelayedEncoder encoder_;
+ } test;
+
+ RunBaseTest(&test);
}
class FakeReceiveStatistics : public NullReceiveStatistics {
@@ -433,32 +403,31 @@
test::NullTransport transport;
Call::Config call_config(&transport);
- scoped_ptr<Call> call(Call::Create(call_config));
+ CreateSenderCall(call_config);
- CreateTestConfig(call.get(), 1);
- VideoSendStream* video_send_stream =
- call->CreateVideoSendStream(send_config_, video_streams_, NULL);
- video_send_stream->Start();
+ CreateSendConfig(1);
+ CreateStreams();
+ send_stream_->Start();
I420VideoFrame frame;
frame.CreateEmptyFrame(
kWidth, kHeight, kWidth, (kWidth + 1) / 2, (kWidth + 1) / 2);
uint8_t* old_y_buffer = frame.buffer(kYPlane);
- video_send_stream->Input()->SwapFrame(&frame);
+ send_stream_->Input()->SwapFrame(&frame);
EXPECT_NE(frame.buffer(kYPlane), old_y_buffer);
- call->DestroyVideoSendStream(video_send_stream);
+ DestroyStreams();
}
TEST_F(VideoSendStreamTest, SupportsFec) {
static const int kRedPayloadType = 118;
static const int kUlpfecPayloadType = 119;
- class FecObserver : public test::RtpRtcpObserver {
+ class FecObserver : public test::SendTest {
public:
FecObserver()
- : RtpRtcpObserver(30 * 1000),
+ : SendTest(kDefaultTimeoutMs),
transport_adapter_(SendTransport()),
send_count_(0),
received_media_(false),
@@ -466,6 +435,7 @@
transport_adapter_.Enable();
}
+ private:
virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
RTPHeader header;
EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
@@ -474,13 +444,13 @@
if (send_count_++ % 2 != 0) {
// Receive statistics reporting having lost 50% of the packets.
FakeReceiveStatistics lossy_receive_stats(
- kSendSsrc, header.sequenceNumber, send_count_ / 2, 127);
+ kSendSsrcs[0], header.sequenceNumber, send_count_ / 2, 127);
RTCPSender rtcp_sender(
0, false, Clock::GetRealTimeClock(), &lossy_receive_stats);
EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
- rtcp_sender.SetRemoteSSRC(kSendSsrc);
+ rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
RTCPSender::FeedbackState feedback_state;
@@ -503,33 +473,35 @@
return SEND_PACKET;
}
- private:
+ virtual void ModifyConfigs(
+ VideoSendStream::Config* send_config,
+ VideoReceiveStream::Config* receive_config,
+ std::vector<VideoStream>* video_streams) OVERRIDE {
+ send_config->rtp.fec.red_payload_type = kRedPayloadType;
+ send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
+ }
+
+ virtual void PerformTest() OVERRIDE {
+ EXPECT_TRUE(Wait()) << "Timed out waiting for FEC and media packets.";
+ }
+
internal::TransportAdapter transport_adapter_;
int send_count_;
bool received_media_;
bool received_fec_;
- } observer;
+ } test;
- Call::Config call_config(observer.SendTransport());
- scoped_ptr<Call> call(Call::Create(call_config));
-
- observer.SetReceivers(call->Receiver(), NULL);
-
- CreateTestConfig(call.get(), 1);
- send_config_.rtp.fec.red_payload_type = kRedPayloadType;
- send_config_.rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
-
- RunSendTest(call.get(), &observer);
+ RunBaseTest(&test);
}
void VideoSendStreamTest::TestNackRetransmission(
uint32_t retransmit_ssrc,
uint8_t retransmit_payload_type) {
- class NackObserver : public test::RtpRtcpObserver {
+ class NackObserver : public test::SendTest {
public:
explicit NackObserver(uint32_t retransmit_ssrc,
uint8_t retransmit_payload_type)
- : RtpRtcpObserver(30 * 1000),
+ : SendTest(kDefaultTimeoutMs),
transport_adapter_(SendTransport()),
send_count_(0),
retransmit_ssrc_(retransmit_ssrc),
@@ -538,6 +510,7 @@
transport_adapter_.Enable();
}
+ private:
virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
RTPHeader header;
EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
@@ -552,7 +525,7 @@
EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
- rtcp_sender.SetRemoteSSRC(kSendSsrc);
+ rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
RTCPSender::FeedbackState feedback_state;
@@ -563,8 +536,10 @@
uint16_t sequence_number = header.sequenceNumber;
- if (header.ssrc == retransmit_ssrc_ && retransmit_ssrc_ != kSendSsrc) {
- // Not kSendSsrc, assume correct RTX packet. Extract sequence number.
+ if (header.ssrc == retransmit_ssrc_ &&
+ retransmit_ssrc_ != kSendSsrcs[0]) {
+ // Not kSendSsrcs[0], assume correct RTX packet. Extract sequence
+ // number.
const uint8_t* rtx_header = packet + header.headerLength;
sequence_number = (rtx_header[0] << 8) + rtx_header[1];
}
@@ -578,30 +553,34 @@
return SEND_PACKET;
}
- private:
+ virtual void ModifyConfigs(
+ VideoSendStream::Config* send_config,
+ VideoReceiveStream::Config* receive_config,
+ std::vector<VideoStream>* video_streams) OVERRIDE {
+ send_config->rtp.nack.rtp_history_ms = 1000;
+ send_config->rtp.rtx.payload_type = retransmit_payload_type_;
+ if (retransmit_ssrc_ != kSendSsrcs[0])
+ send_config->rtp.rtx.ssrcs.push_back(retransmit_ssrc_);
+ }
+
+ virtual void PerformTest() OVERRIDE {
+ EXPECT_EQ(kEventSignaled, Wait())
+ << "Timed out while waiting for NACK retransmission.";
+ }
+
internal::TransportAdapter transport_adapter_;
int send_count_;
uint32_t retransmit_ssrc_;
uint8_t retransmit_payload_type_;
int nacked_sequence_number_;
- } observer(retransmit_ssrc, retransmit_payload_type);
+ } test(retransmit_ssrc, retransmit_payload_type);
- Call::Config call_config(observer.SendTransport());
- scoped_ptr<Call> call(Call::Create(call_config));
- observer.SetReceivers(call->Receiver(), NULL);
-
- CreateTestConfig(call.get(), 1);
- send_config_.rtp.nack.rtp_history_ms = 1000;
- send_config_.rtp.rtx.payload_type = retransmit_payload_type;
- if (retransmit_ssrc != kSendSsrc)
- send_config_.rtp.rtx.ssrcs.push_back(retransmit_ssrc);
-
- RunSendTest(call.get(), &observer);
+ RunBaseTest(&test);
}
TEST_F(VideoSendStreamTest, RetransmitsNack) {
// Normal NACKs should use the send SSRC.
- TestNackRetransmission(kSendSsrc, kFakeSendPayloadType);
+ TestNackRetransmission(kSendSsrcs[0], kFakeSendPayloadType);
}
TEST_F(VideoSendStreamTest, RetransmitsNackOverRtx) {
@@ -611,22 +590,28 @@
void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format,
bool with_fec) {
+ // Use a fake encoder to output a frame of every size in the range [90, 290],
+ // for each size making sure that the exact number of payload bytes received
+ // is correct and that packets are fragmented to respect max packet size.
+ static const uint32_t kMaxPacketSize = 128;
+ static const uint32_t start = 90;
+ static const uint32_t stop = 290;
+
static const int kRedPayloadType = 118;
static const int kUlpfecPayloadType = 119;
// Observer that verifies that the expected number of packets and bytes
// arrive for each frame size, from start_size to stop_size.
- class FrameFragmentationObserver : public test::RtpRtcpObserver,
- public EncodedFrameObserver {
+ class FrameFragmentationTest : public test::SendTest,
+ public EncodedFrameObserver {
public:
- FrameFragmentationObserver(uint32_t max_packet_size,
- uint32_t start_size,
- uint32_t stop_size,
- test::ConfigurableFrameSizeEncoder* encoder,
- bool test_generic_packetization,
- bool use_fec)
- : RtpRtcpObserver(120 * 1000), // Timeout after two minutes.
+ FrameFragmentationTest(uint32_t max_packet_size,
+ uint32_t start_size,
+ uint32_t stop_size,
+ bool test_generic_packetization,
+ bool use_fec)
+ : SendTest(kLongTimeoutMs),
transport_adapter_(SendTransport()),
- encoder_(encoder),
+ encoder_(stop),
max_packet_size_(max_packet_size),
stop_size_(stop_size),
test_generic_packetization_(test_generic_packetization),
@@ -638,10 +623,12 @@
current_size_rtp_(start_size),
current_size_frame_(start_size) {
// Fragmentation required, this test doesn't make sense without it.
+ encoder_.SetFrameSize(start);
assert(stop_size > max_packet_size);
transport_adapter_.Enable();
}
+ private:
virtual Action OnSendRtp(const uint8_t* packet, size_t size) OVERRIDE {
uint32_t length = static_cast<int>(size);
RTPHeader header;
@@ -717,13 +704,13 @@
if (packet_count_++ % 2 != 0) {
// Receive statistics reporting having lost 50% of the packets.
FakeReceiveStatistics lossy_receive_stats(
- kSendSsrc, header.sequenceNumber, packet_count_ / 2, 127);
+ kSendSsrcs[0], header.sequenceNumber, packet_count_ / 2, 127);
RTCPSender rtcp_sender(
0, false, Clock::GetRealTimeClock(), &lossy_receive_stats);
EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
- rtcp_sender.SetRemoteSSRC(kSendSsrc);
+ rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
RTCPSender::FeedbackState feedback_state;
@@ -738,12 +725,39 @@
current_size_frame_.Value() < static_cast<int32_t>(stop_size_)) {
++current_size_frame_;
}
- encoder_->SetFrameSize(current_size_frame_.Value());
+ encoder_.SetFrameSize(current_size_frame_.Value());
}
- private:
+ virtual void ModifyConfigs(
+ VideoSendStream::Config* send_config,
+ VideoReceiveStream::Config* receive_config,
+ std::vector<VideoStream>* video_streams) OVERRIDE {
+ if (use_fec_) {
+ send_config->rtp.fec.red_payload_type = kRedPayloadType;
+ send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
+ }
+
+ if (!test_generic_packetization_)
+ send_config->encoder_settings.payload_name = "VP8";
+
+ send_config->encoder_settings.encoder = &encoder_;
+ send_config->rtp.max_packet_size = kMaxPacketSize;
+ send_config->post_encode_callback = this;
+
+ // Add an extension header, to make the RTP header larger than the base
+ // length of 12 bytes.
+ static const uint8_t kAbsSendTimeExtensionId = 13;
+ send_config->rtp.extensions.push_back(
+ RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId));
+ }
+
+ virtual void PerformTest() OVERRIDE {
+ EXPECT_EQ(kEventSignaled, Wait())
+ << "Timed out while observing incoming RTP packets.";
+ }
+
internal::TransportAdapter transport_adapter_;
- test::ConfigurableFrameSizeEncoder* const encoder_;
+ test::ConfigurableFrameSizeEncoder encoder_;
const uint32_t max_packet_size_;
const uint32_t stop_size_;
@@ -759,45 +773,12 @@
Atomic32 current_size_frame_;
};
- // Use a fake encoder to output a frame of every size in the range [90, 290],
- // for each size making sure that the exact number of payload bytes received
- // is correct and that packets are fragmented to respect max packet size.
- static const uint32_t kMaxPacketSize = 128;
- static const uint32_t start = 90;
- static const uint32_t stop = 290;
-
// Don't auto increment if FEC is used; continue sending frame size until
// a FEC packet has been received.
- test::ConfigurableFrameSizeEncoder encoder(stop);
- encoder.SetFrameSize(start);
+ FrameFragmentationTest test(
+ kMaxPacketSize, start, stop, format == kGeneric, with_fec);
- FrameFragmentationObserver observer(
- kMaxPacketSize, start, stop, &encoder, format == kGeneric, with_fec);
- Call::Config call_config(observer.SendTransport());
- scoped_ptr<Call> call(Call::Create(call_config));
-
- observer.SetReceivers(call->Receiver(), NULL);
-
- CreateTestConfig(call.get(), 1);
- if (with_fec) {
- send_config_.rtp.fec.red_payload_type = kRedPayloadType;
- send_config_.rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
- }
-
- if (format == kVP8)
- send_config_.encoder_settings.payload_name = "VP8";
-
- send_config_.encoder_settings.encoder = &encoder;
- send_config_.rtp.max_packet_size = kMaxPacketSize;
- send_config_.post_encode_callback = &observer;
-
- // Add an extension header, to make the RTP header larger than the base
- // length of 12 bytes.
- static const uint8_t kAbsSendTimeExtensionId = 13;
- send_config_.rtp.extensions.push_back(
- RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId));
-
- RunSendTest(call.get(), &observer);
+ RunBaseTest(&test);
}
// TODO(sprang): Is there any way of speeding up these tests?
@@ -829,13 +810,12 @@
TEST_F(VideoSendStreamTest, SuspendBelowMinBitrate) {
static const int kSuspendTimeFrames = 60; // Suspend for 2 seconds @ 30 fps.
- class RembObserver : public test::RtpRtcpObserver, public I420FrameCallback {
+ class RembObserver : public test::SendTest, public I420FrameCallback {
public:
- RembObserver(VideoSendStream** send_stream_ptr)
- : RtpRtcpObserver(30 * 1000), // Timeout after 30 seconds.
+ RembObserver()
+ : SendTest(kDefaultTimeoutMs),
transport_adapter_(&transport_),
clock_(Clock::GetRealTimeClock()),
- send_stream_ptr_(send_stream_ptr),
crit_(CriticalSectionWrapper::CreateCriticalSection()),
test_state_(kBeforeSuspend),
rtp_count_(0),
@@ -846,10 +826,7 @@
transport_adapter_.Enable();
}
- void SetReceiver(PacketReceiver* receiver) {
- transport_.SetReceiver(receiver);
- }
-
+ private:
virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
// Receive statistics reporting having lost 0% of the packets.
// This is needed for the send-side bitrate controller to work properly.
@@ -882,8 +859,7 @@
test_state_ = kWaitingForStats;
}
} else if (test_state_ == kWaitingForStats) {
- assert(*send_stream_ptr_);
- VideoSendStream::Stats stats = (*send_stream_ptr_)->GetStats();
+ VideoSendStream::Stats stats = stream_->GetStats();
if (stats.suspended == false) {
// Stats flipped to false. Test is complete.
observation_complete_->Set();
@@ -898,8 +874,7 @@
CriticalSectionScoped lock(crit_.get());
if (test_state_ == kDuringSuspend &&
++suspended_frame_count_ > kSuspendTimeFrames) {
- assert(*send_stream_ptr_);
- VideoSendStream::Stats stats = (*send_stream_ptr_)->GetStats();
+ VideoSendStream::Stats stats = stream_->GetStats();
EXPECT_TRUE(stats.suspended);
SendRtcpFeedback(high_remb_bps_);
test_state_ = kWaitingForPacket;
@@ -916,9 +891,38 @@
high_remb_bps_ = value;
}
- void Stop() { transport_.StopSending(); }
+ virtual void SetReceivers(
+ PacketReceiver* send_transport_receiver,
+ PacketReceiver* receive_transport_receiver) OVERRIDE {
+ transport_.SetReceiver(send_transport_receiver);
+ }
- private:
+ virtual void OnStreamsCreated(VideoSendStream* send_stream,
+ VideoReceiveStream* receive_stream) OVERRIDE {
+ stream_ = send_stream;
+ }
+
+ virtual void ModifyConfigs(
+ VideoSendStream::Config* send_config,
+ VideoReceiveStream::Config* receive_config,
+ std::vector<VideoStream>* video_streams) OVERRIDE {
+ send_config->rtp.nack.rtp_history_ms = 1000;
+ send_config->pre_encode_callback = this;
+ send_config->suspend_below_min_bitrate = true;
+ int min_bitrate_bps = (*video_streams)[0].min_bitrate_bps;
+ set_low_remb_bps(min_bitrate_bps - 10000);
+ int threshold_window = std::max(min_bitrate_bps / 10, 10000);
+ ASSERT_GT((*video_streams)[0].max_bitrate_bps,
+ min_bitrate_bps + threshold_window + 5000);
+ set_high_remb_bps(min_bitrate_bps + threshold_window + 5000);
+ }
+
+ virtual void PerformTest() OVERRIDE {
+ EXPECT_EQ(kEventSignaled, Wait())
+ << "Timed out during suspend-below-min-bitrate test.";
+ transport_.StopSending();
+ }
+
enum TestState {
kBeforeSuspend,
kDuringSuspend,
@@ -929,12 +933,12 @@
virtual void SendRtcpFeedback(int remb_value)
EXCLUSIVE_LOCKS_REQUIRED(crit_) {
FakeReceiveStatistics receive_stats(
- kSendSsrc, last_sequence_number_, rtp_count_, 0);
+ kSendSsrcs[0], last_sequence_number_, rtp_count_, 0);
RTCPSender rtcp_sender(0, false, clock_, &receive_stats);
EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
- rtcp_sender.SetRemoteSSRC(kSendSsrc);
+ rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
if (remb_value > 0) {
rtcp_sender.SetREMBStatus(true);
rtcp_sender.SetREMBData(remb_value, 0, NULL);
@@ -946,7 +950,7 @@
internal::TransportAdapter transport_adapter_;
test::DirectTransport transport_;
Clock* const clock_;
- VideoSendStream** const send_stream_ptr_;
+ VideoSendStream* stream_;
const scoped_ptr<CriticalSectionWrapper> crit_;
TestState test_state_ GUARDED_BY(crit_);
@@ -955,34 +959,16 @@
int suspended_frame_count_ GUARDED_BY(crit_);
int low_remb_bps_ GUARDED_BY(crit_);
int high_remb_bps_ GUARDED_BY(crit_);
- } observer(&send_stream_);
- // Note that |send_stream_| is created in RunSendTest(), called below. This
- // is why a pointer to |send_stream_| must be provided here.
+ } test;
- Call::Config call_config(observer.SendTransport());
- scoped_ptr<Call> call(Call::Create(call_config));
- observer.SetReceiver(call->Receiver());
-
- CreateTestConfig(call.get(), 1);
- send_config_.rtp.nack.rtp_history_ms = 1000;
- send_config_.pre_encode_callback = &observer;
- send_config_.suspend_below_min_bitrate = true;
- int min_bitrate_bps = video_streams_[0].min_bitrate_bps;
- observer.set_low_remb_bps(min_bitrate_bps - 10000);
- int threshold_window = std::max(min_bitrate_bps / 10, 10000);
- ASSERT_GT(video_streams_[0].max_bitrate_bps,
- min_bitrate_bps + threshold_window + 5000);
- observer.set_high_remb_bps(min_bitrate_bps + threshold_window + 5000);
-
- RunSendTest(call.get(), &observer);
- observer.Stop();
+ RunBaseTest(&test);
}
TEST_F(VideoSendStreamTest, NoPaddingWhenVideoIsMuted) {
- class PacketObserver : public test::RtpRtcpObserver {
+ class NoPaddingWhenVideoIsMuted : public test::SendTest {
public:
- PacketObserver()
- : RtpRtcpObserver(30 * 1000), // Timeout after 30 seconds.
+ NoPaddingWhenVideoIsMuted()
+ : SendTest(kDefaultTimeoutMs),
clock_(Clock::GetRealTimeClock()),
transport_adapter_(ReceiveTransport()),
crit_(CriticalSectionWrapper::CreateCriticalSection()),
@@ -991,11 +977,7 @@
transport_adapter_.Enable();
}
- void SetCapturer(test::FrameGeneratorCapturer* capturer) {
- CriticalSectionScoped lock(crit_.get());
- capturer_ = capturer;
- }
-
+ private:
virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
CriticalSectionScoped lock(crit_.get());
last_packet_time_ms_ = clock_->TimeInMilliseconds();
@@ -1025,46 +1007,43 @@
return SEND_PACKET;
}
- private:
+ virtual void SetReceivers(
+ PacketReceiver* send_transport_receiver,
+ PacketReceiver* receive_transport_receiver) OVERRIDE {
+ RtpRtcpObserver::SetReceivers(send_transport_receiver,
+ send_transport_receiver);
+ }
+
+ virtual size_t GetNumStreams() const OVERRIDE { return 3; }
+
+ virtual void OnFrameGeneratorCapturerCreated(
+ test::FrameGeneratorCapturer* frame_generator_capturer) {
+ CriticalSectionScoped lock(crit_.get());
+ capturer_ = frame_generator_capturer;
+ }
+
+ virtual void PerformTest() OVERRIDE {
+ EXPECT_EQ(kEventSignaled, Wait())
+ << "Timed out while waiting for RTP packets to stop being sent.";
+ }
+
Clock* const clock_;
internal::TransportAdapter transport_adapter_;
const scoped_ptr<CriticalSectionWrapper> crit_;
int64_t last_packet_time_ms_ GUARDED_BY(crit_);
test::FrameGeneratorCapturer* capturer_ GUARDED_BY(crit_);
- } observer;
+ } test;
- Call::Config call_config(observer.SendTransport());
- scoped_ptr<Call> call(Call::Create(call_config));
- observer.SetReceivers(call->Receiver(), call->Receiver());
-
- CreateTestConfig(call.get(), 3);
-
- send_stream_ =
- call->CreateVideoSendStream(send_config_, video_streams_, NULL);
- scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
- test::FrameGeneratorCapturer::Create(
- send_stream_->Input(), 320, 240, 30, Clock::GetRealTimeClock()));
- observer.SetCapturer(frame_generator_capturer.get());
- send_stream_->Start();
- frame_generator_capturer->Start();
-
- EXPECT_EQ(kEventSignaled, observer.Wait())
- << "Timed out while waiting for RTP packets to stop being sent.";
-
- observer.StopSending();
- frame_generator_capturer->Stop();
- send_stream_->Stop();
- call->DestroyVideoSendStream(send_stream_);
+ RunBaseTest(&test);
}
TEST_F(VideoSendStreamTest, ProducesStats) {
static const std::string kCName =
"PjQatC14dGfbVwGPUOA9IH7RlsFDbWl4AhXEiDsBizo=";
- static const uint32_t kTimeoutMs = 30 * 1000;
- class StatsObserver : public test::RtpRtcpObserver {
+ class ProducesStats : public test::SendTest {
public:
- StatsObserver()
- : RtpRtcpObserver(kTimeoutMs),
+ ProducesStats()
+ : SendTest(kDefaultTimeoutMs),
stream_(NULL),
event_(EventWrapper::Create()) {}
@@ -1074,10 +1053,11 @@
return SEND_PACKET;
}
+ private:
bool WaitForFilledStats() {
Clock* clock = Clock::GetRealTimeClock();
int64_t now = clock->TimeInMilliseconds();
- int64_t stop_time = now + kTimeoutMs;
+ int64_t stop_time = now + kDefaultTimeoutMs;
while (now < stop_time) {
int64_t time_left = stop_time - now;
if (time_left > 0 && event_->Wait(time_left) == kEventSignaled &&
@@ -1113,36 +1093,30 @@
void SetConfig(const VideoSendStream::Config& config) { config_ = config; }
- void SetSendStream(VideoSendStream* stream) { stream_ = stream; }
+ virtual void ModifyConfigs(
+ VideoSendStream::Config* send_config,
+ VideoReceiveStream::Config* receive_config,
+ std::vector<VideoStream>* video_streams) OVERRIDE {
+ send_config->rtp.c_name = kCName;
+ SetConfig(*send_config);
+ }
+
+ virtual void OnStreamsCreated(VideoSendStream* send_stream,
+ VideoReceiveStream* receive_stream) OVERRIDE {
+ stream_ = send_stream;
+ }
+
+ virtual void PerformTest() OVERRIDE {
+ EXPECT_TRUE(WaitForFilledStats())
+ << "Timed out waiting for filled statistics.";
+ }
VideoSendStream* stream_;
VideoSendStream::Config config_;
scoped_ptr<EventWrapper> event_;
- } observer;
+ } test;
- Call::Config call_config(observer.SendTransport());
- scoped_ptr<Call> call(Call::Create(call_config));
-
- CreateTestConfig(call.get(), 1);
- send_config_.rtp.c_name = kCName;
- observer.SetConfig(send_config_);
-
- send_stream_ =
- call->CreateVideoSendStream(send_config_, video_streams_, NULL);
- observer.SetSendStream(send_stream_);
- scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
- test::FrameGeneratorCapturer::Create(
- send_stream_->Input(), 320, 240, 30, Clock::GetRealTimeClock()));
- send_stream_->Start();
- frame_generator_capturer->Start();
-
- EXPECT_TRUE(observer.WaitForFilledStats())
- << "Timed out waiting for filled statistics.";
-
- observer.StopSending();
- frame_generator_capturer->Stop();
- send_stream_->Stop();
- call->DestroyVideoSendStream(send_stream_);
+ RunBaseTest(&test);
}
// This test first observes "high" bitrate use at which point it sends a REMB to
@@ -1157,12 +1131,11 @@
static const int kHighBitrateBps = 150000;
static const int kRembBitrateBps = 80000;
static const int kRembRespectedBitrateBps = 100000;
- class BitrateObserver: public test::RtpRtcpObserver, public PacketReceiver {
+ class BitrateObserver : public test::SendTest, public PacketReceiver {
public:
BitrateObserver()
- : RtpRtcpObserver(30 * 1000),
+ : SendTest(kDefaultTimeoutMs),
feedback_transport_(ReceiveTransport()),
- send_stream_(NULL),
bitrate_capped_(false) {
RtpRtcp::Configuration config;
feedback_transport_.Enable();
@@ -1172,8 +1145,9 @@
rtp_rtcp_->SetRTCPStatus(kRtcpNonCompound);
}
- void SetSendStream(VideoSendStream* send_stream) {
- send_stream_ = send_stream;
+ virtual void OnStreamsCreated(VideoSendStream* send_stream,
+ VideoReceiveStream* receive_stream) OVERRIDE {
+ stream_ = send_stream;
}
private:
@@ -1185,8 +1159,8 @@
RTPHeader header;
if (!parser_->Parse(packet, static_cast<int>(length), &header))
return DELIVERY_PACKET_ERROR;
- assert(send_stream_ != NULL);
- VideoSendStream::Stats stats = send_stream_->GetStats();
+ assert(stream_ != NULL);
+ VideoSendStream::Stats stats = stream_->GetStats();
if (!stats.substreams.empty()) {
EXPECT_EQ(1u, stats.substreams.size());
int bitrate_bps = stats.substreams.begin()->second.bitrate_bps;
@@ -1209,35 +1183,31 @@
return DELIVERY_OK;
}
+ virtual void SetReceivers(
+ PacketReceiver* send_transport_receiver,
+ PacketReceiver* receive_transport_receiver) OVERRIDE {
+ RtpRtcpObserver::SetReceivers(this, send_transport_receiver);
+ }
+
+ virtual void ModifyConfigs(
+ VideoSendStream::Config* send_config,
+ VideoReceiveStream::Config* receive_config,
+ std::vector<VideoStream>* video_streams) OVERRIDE {
+ send_config->rtp.min_transmit_bitrate_bps = kMinTransmitBitrateBps;
+ }
+
+ virtual void PerformTest() OVERRIDE {
+ EXPECT_EQ(kEventSignaled, Wait())
+ << "Timeout while waiting for low bitrate stats after REMB.";
+ }
+
scoped_ptr<RtpRtcp> rtp_rtcp_;
internal::TransportAdapter feedback_transport_;
- VideoSendStream* send_stream_;
+ VideoSendStream* stream_;
bool bitrate_capped_;
- } observer;
+ } test;
- Call::Config call_config(observer.SendTransport());
- scoped_ptr<Call> call(Call::Create(call_config));
- observer.SetReceivers(&observer, call->Receiver());
-
- CreateTestConfig(call.get(), 1);
- send_config_.rtp.min_transmit_bitrate_bps = kMinTransmitBitrateBps;
- send_stream_ =
- call->CreateVideoSendStream(send_config_, video_streams_, NULL);
- observer.SetSendStream(send_stream_);
-
- scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
- test::FrameGeneratorCapturer::Create(
- send_stream_->Input(), 320, 240, 30, Clock::GetRealTimeClock()));
- send_stream_->Start();
- frame_generator_capturer->Start();
-
- EXPECT_EQ(kEventSignaled, observer.Wait())
- << "Timeout while waiting for low bitrate stats after REMB.";
-
- observer.StopSending();
- frame_generator_capturer->Stop();
- send_stream_->Stop();
- call->DestroyVideoSendStream(send_stream_);
+ RunBaseTest(&test);
}
TEST_F(VideoSendStreamTest, CapturesTextureAndI420VideoFrames) {
@@ -1271,13 +1241,12 @@
// Initialize send stream.
test::NullTransport transport;
- Call::Config call_config(&transport);
- scoped_ptr<Call> call(Call::Create(call_config));
- CreateTestConfig(call.get(), 1);
+ CreateSenderCall(Call::Config(&transport));
+
+ CreateSendConfig(1);
FrameObserver observer;
send_config_.pre_encode_callback = &observer;
- send_stream_ =
- call->CreateVideoSendStream(send_config_, video_streams_, NULL);
+ CreateStreams();
// Prepare five input frames. Send I420VideoFrame and TextureVideoFrame
// alternatively.
@@ -1314,7 +1283,7 @@
// timestamp are not compared because capturer sets those values.
ExpectEqualFramesVector(input_frames.get(), observer.output_frames());
- call->DestroyVideoSendStream(send_stream_);
+ DestroyStreams();
}
void ExpectEqualFrames(const I420VideoFrame& frame1,
diff --git a/webrtc/webrtc_tests.gypi b/webrtc/webrtc_tests.gypi
index 3c1dca6..85a7e73 100644
--- a/webrtc/webrtc_tests.gypi
+++ b/webrtc/webrtc_tests.gypi
@@ -46,7 +46,7 @@
'type': '<(gtest_target_type)',
'sources': [
'video/bitrate_estimator_tests.cc',
- 'video/call_tests.cc',
+ 'video/end_to_end_tests.cc',
'video/send_statistics_proxy_unittest.cc',
'video/video_send_stream_tests.cc',
'test/common_unittest.cc',