end_to_end_tests.cc was over 5000 lines and covered many different areas in it's testing. In this change it is separated into multiple smaller test sets separated by the functionality they are testing. The reasoning behind this is that the fact that a test is working end to end should be secondary to what functionality the test is actually testing. A slight functional change is that for some of the tests the parametrization over round robin pacing being controlled with a field trial is removed since they are simple enough that they should not be affected by the pacing method. Bug: None Change-Id: I4b7eba80fc142ecfc8fa642dab9b6f587d914048 Reviewed-on: https://webrtc-review.googlesource.com/46143 Commit-Queue: Sebastian Jansson <srte@webrtc.org> Reviewed-by: Stefan Holmer <stefan@webrtc.org> Cr-Commit-Position: refs/heads/master@{#21876}
337 lines
11 KiB
C++
337 lines
11 KiB
C++
/*
|
|
* Copyright 2018 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 "test/call_test.h"
|
|
#include "test/gtest.h"
|
|
#include "test/rtcp_packet_parser.h"
|
|
|
|
namespace webrtc {
|
|
class SsrcEndToEndTest : public test::CallTest {
|
|
protected:
|
|
void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
|
|
};
|
|
|
|
TEST_F(SsrcEndToEndTest, ReceiverUsesLocalSsrc) {
|
|
class SyncRtcpObserver : public test::EndToEndTest {
|
|
public:
|
|
SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {}
|
|
|
|
Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
|
|
test::RtcpPacketParser parser;
|
|
EXPECT_TRUE(parser.Parse(packet, length));
|
|
EXPECT_EQ(kReceiverLocalVideoSsrc, parser.sender_ssrc());
|
|
observation_complete_.Set();
|
|
|
|
return SEND_PACKET;
|
|
}
|
|
|
|
void PerformTest() override {
|
|
EXPECT_TRUE(Wait())
|
|
<< "Timed out while waiting for a receiver RTCP packet to be sent.";
|
|
}
|
|
} test;
|
|
|
|
RunBaseTest(&test);
|
|
}
|
|
|
|
TEST_F(SsrcEndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
|
|
class PacketInputObserver : public PacketReceiver {
|
|
public:
|
|
explicit PacketInputObserver(PacketReceiver* receiver)
|
|
: receiver_(receiver), delivered_packet_(false, false) {}
|
|
|
|
bool Wait() { return delivered_packet_.Wait(kDefaultTimeoutMs); }
|
|
|
|
private:
|
|
DeliveryStatus DeliverPacket(MediaType media_type,
|
|
rtc::CopyOnWriteBuffer packet,
|
|
const PacketTime& packet_time) override {
|
|
if (RtpHeaderParser::IsRtcp(packet.cdata(), packet.size())) {
|
|
return receiver_->DeliverPacket(media_type, std::move(packet),
|
|
packet_time);
|
|
} else {
|
|
DeliveryStatus delivery_status = receiver_->DeliverPacket(
|
|
media_type, std::move(packet), packet_time);
|
|
EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
|
|
delivered_packet_.Set();
|
|
return delivery_status;
|
|
}
|
|
}
|
|
|
|
PacketReceiver* receiver_;
|
|
rtc::Event delivered_packet_;
|
|
};
|
|
|
|
std::unique_ptr<test::DirectTransport> send_transport;
|
|
std::unique_ptr<test::DirectTransport> receive_transport;
|
|
std::unique_ptr<PacketInputObserver> input_observer;
|
|
|
|
task_queue_.SendTask([this, &send_transport, &receive_transport,
|
|
&input_observer]() {
|
|
CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
|
|
|
|
send_transport = rtc::MakeUnique<test::DirectTransport>(
|
|
&task_queue_, sender_call_.get(), payload_type_map_);
|
|
receive_transport = rtc::MakeUnique<test::DirectTransport>(
|
|
&task_queue_, receiver_call_.get(), payload_type_map_);
|
|
input_observer =
|
|
rtc::MakeUnique<PacketInputObserver>(receiver_call_->Receiver());
|
|
send_transport->SetReceiver(input_observer.get());
|
|
receive_transport->SetReceiver(sender_call_->Receiver());
|
|
|
|
CreateSendConfig(1, 0, 0, send_transport.get());
|
|
CreateMatchingReceiveConfigs(receive_transport.get());
|
|
|
|
CreateVideoStreams();
|
|
CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
|
|
kDefaultHeight);
|
|
Start();
|
|
|
|
receiver_call_->DestroyVideoReceiveStream(video_receive_streams_[0]);
|
|
video_receive_streams_.clear();
|
|
});
|
|
|
|
// Wait() waits for a received packet.
|
|
EXPECT_TRUE(input_observer->Wait());
|
|
|
|
task_queue_.SendTask([this, &send_transport, &receive_transport]() {
|
|
Stop();
|
|
DestroyStreams();
|
|
send_transport.reset();
|
|
receive_transport.reset();
|
|
DestroyCalls();
|
|
});
|
|
}
|
|
|
|
void SsrcEndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
|
|
bool send_single_ssrc_first) {
|
|
class SendsSetSsrcs : public test::EndToEndTest {
|
|
public:
|
|
SendsSetSsrcs(const uint32_t* ssrcs,
|
|
size_t num_ssrcs,
|
|
bool send_single_ssrc_first)
|
|
: EndToEndTest(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),
|
|
send_stream_(nullptr) {
|
|
for (size_t i = 0; i < num_ssrcs; ++i)
|
|
valid_ssrcs_[ssrcs[i]] = true;
|
|
}
|
|
|
|
private:
|
|
Action OnSendRtp(const uint8_t* packet, size_t length) override {
|
|
RTPHeader header;
|
|
EXPECT_TRUE(parser_->Parse(packet, length, &header));
|
|
|
|
EXPECT_TRUE(valid_ssrcs_[header.ssrc])
|
|
<< "Received unknown SSRC: " << header.ssrc;
|
|
|
|
if (!valid_ssrcs_[header.ssrc])
|
|
observation_complete_.Set();
|
|
|
|
if (!is_observed_[header.ssrc]) {
|
|
is_observed_[header.ssrc] = true;
|
|
--ssrcs_to_observe_;
|
|
if (expect_single_ssrc_) {
|
|
expect_single_ssrc_ = false;
|
|
observation_complete_.Set();
|
|
}
|
|
}
|
|
|
|
if (ssrcs_to_observe_ == 0)
|
|
observation_complete_.Set();
|
|
|
|
return SEND_PACKET;
|
|
}
|
|
|
|
size_t GetNumVideoStreams() const override { return num_ssrcs_; }
|
|
|
|
// This test use other VideoStream settings than the the default settings
|
|
// implemented in DefaultVideoStreamFactory. Therefore this test implement
|
|
// its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
|
|
// in ModifyVideoConfigs.
|
|
class VideoStreamFactory
|
|
: public VideoEncoderConfig::VideoStreamFactoryInterface {
|
|
public:
|
|
VideoStreamFactory() {}
|
|
|
|
private:
|
|
std::vector<VideoStream> CreateEncoderStreams(
|
|
int width,
|
|
int height,
|
|
const VideoEncoderConfig& encoder_config) override {
|
|
std::vector<VideoStream> streams =
|
|
test::CreateVideoStreams(width, height, encoder_config);
|
|
// Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
|
|
for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
|
|
streams[i].min_bitrate_bps = 10000;
|
|
streams[i].target_bitrate_bps = 15000;
|
|
streams[i].max_bitrate_bps = 20000;
|
|
}
|
|
return streams;
|
|
}
|
|
};
|
|
|
|
void ModifyVideoConfigs(
|
|
VideoSendStream::Config* send_config,
|
|
std::vector<VideoReceiveStream::Config>* receive_configs,
|
|
VideoEncoderConfig* encoder_config) override {
|
|
encoder_config->video_stream_factory =
|
|
new rtc::RefCountedObject<VideoStreamFactory>();
|
|
video_encoder_config_all_streams_ = encoder_config->Copy();
|
|
if (send_single_ssrc_first_)
|
|
encoder_config->number_of_streams = 1;
|
|
}
|
|
|
|
void OnVideoStreamsCreated(
|
|
VideoSendStream* send_stream,
|
|
const std::vector<VideoReceiveStream*>& receive_streams) override {
|
|
send_stream_ = send_stream;
|
|
}
|
|
|
|
void PerformTest() override {
|
|
EXPECT_TRUE(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(
|
|
std::move(video_encoder_config_all_streams_));
|
|
EXPECT_TRUE(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_;
|
|
|
|
VideoSendStream* send_stream_;
|
|
VideoEncoderConfig video_encoder_config_all_streams_;
|
|
} test(kVideoSendSsrcs, num_ssrcs, send_single_ssrc_first);
|
|
|
|
RunBaseTest(&test);
|
|
}
|
|
|
|
TEST_F(SsrcEndToEndTest, SendsSetSsrc) {
|
|
TestSendsSetSsrcs(1, false);
|
|
}
|
|
|
|
TEST_F(SsrcEndToEndTest, SendsSetSimulcastSsrcs) {
|
|
TestSendsSetSsrcs(kNumSimulcastStreams, false);
|
|
}
|
|
|
|
TEST_F(SsrcEndToEndTest, CanSwitchToUseAllSsrcs) {
|
|
TestSendsSetSsrcs(kNumSimulcastStreams, true);
|
|
}
|
|
|
|
TEST_F(SsrcEndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
|
|
class ObserveRedundantPayloads : public test::EndToEndTest {
|
|
public:
|
|
ObserveRedundantPayloads()
|
|
: EndToEndTest(kDefaultTimeoutMs),
|
|
ssrcs_to_observe_(kNumSimulcastStreams) {
|
|
for (size_t i = 0; i < kNumSimulcastStreams; ++i) {
|
|
registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
|
|
}
|
|
}
|
|
|
|
private:
|
|
Action OnSendRtp(const uint8_t* packet, size_t length) override {
|
|
RTPHeader header;
|
|
EXPECT_TRUE(parser_->Parse(packet, length, &header));
|
|
|
|
if (!registered_rtx_ssrc_[header.ssrc])
|
|
return SEND_PACKET;
|
|
|
|
EXPECT_LE(header.headerLength + header.paddingLength, length);
|
|
const bool packet_is_redundant_payload =
|
|
header.headerLength + header.paddingLength < length;
|
|
|
|
if (!packet_is_redundant_payload)
|
|
return SEND_PACKET;
|
|
|
|
if (!observed_redundant_retransmission_[header.ssrc]) {
|
|
observed_redundant_retransmission_[header.ssrc] = true;
|
|
if (--ssrcs_to_observe_ == 0)
|
|
observation_complete_.Set();
|
|
}
|
|
|
|
return SEND_PACKET;
|
|
}
|
|
|
|
size_t GetNumVideoStreams() const override { return kNumSimulcastStreams; }
|
|
|
|
// This test use other VideoStream settings than the the default settings
|
|
// implemented in DefaultVideoStreamFactory. Therefore this test implement
|
|
// its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
|
|
// in ModifyVideoConfigs.
|
|
class VideoStreamFactory
|
|
: public VideoEncoderConfig::VideoStreamFactoryInterface {
|
|
public:
|
|
VideoStreamFactory() {}
|
|
|
|
private:
|
|
std::vector<VideoStream> CreateEncoderStreams(
|
|
int width,
|
|
int height,
|
|
const VideoEncoderConfig& encoder_config) override {
|
|
std::vector<VideoStream> streams =
|
|
test::CreateVideoStreams(width, height, encoder_config);
|
|
// Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
|
|
for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
|
|
streams[i].min_bitrate_bps = 10000;
|
|
streams[i].target_bitrate_bps = 15000;
|
|
streams[i].max_bitrate_bps = 20000;
|
|
}
|
|
return streams;
|
|
}
|
|
};
|
|
|
|
void ModifyVideoConfigs(
|
|
VideoSendStream::Config* send_config,
|
|
std::vector<VideoReceiveStream::Config>* receive_configs,
|
|
VideoEncoderConfig* encoder_config) override {
|
|
// Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
|
|
encoder_config->video_stream_factory =
|
|
new rtc::RefCountedObject<VideoStreamFactory>();
|
|
send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
|
|
|
|
for (size_t i = 0; i < kNumSimulcastStreams; ++i)
|
|
send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
|
|
|
|
// Significantly higher than max bitrates for all video streams -> forcing
|
|
// padding to trigger redundant padding on all RTX SSRCs.
|
|
encoder_config->min_transmit_bitrate_bps = 100000;
|
|
}
|
|
|
|
void PerformTest() override {
|
|
EXPECT_TRUE(Wait())
|
|
<< "Timed out while waiting for redundant payloads on all SSRCs.";
|
|
}
|
|
|
|
private:
|
|
size_t ssrcs_to_observe_;
|
|
std::map<uint32_t, bool> observed_redundant_retransmission_;
|
|
std::map<uint32_t, bool> registered_rtx_ssrc_;
|
|
} test;
|
|
|
|
RunBaseTest(&test);
|
|
}
|
|
} // namespace webrtc
|