blob: 562e648863e258d3c6ed7c12c275fc352be2de60 [file] [log] [blame]
pbos@webrtc.org744fbc72013-09-10 09:26:25 +00001/*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10#include <assert.h>
11
12#include <map>
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +000013#include <vector>
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000014
15#include "testing/gtest/include/gtest/gtest.h"
16
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000017#include "webrtc/call.h"
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +000018#include "webrtc/common.h"
19#include "webrtc/experiments.h"
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000020#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
21#include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h"
22#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +000023#include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h"
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000024#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
25#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
26#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
27#include "webrtc/system_wrappers/interface/event_wrapper.h"
28#include "webrtc/system_wrappers/interface/scoped_ptr.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000029#include "webrtc/test/direct_transport.h"
30#include "webrtc/test/fake_decoder.h"
31#include "webrtc/test/fake_encoder.h"
32#include "webrtc/test/frame_generator_capturer.h"
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +000033#include "webrtc/test/testsupport/perf_test.h"
pbos@webrtc.org27326b62013-11-20 12:17:04 +000034#include "webrtc/video/transport_adapter.h"
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000035
36namespace webrtc {
37
pbos@webrtc.org29023282013-09-11 10:14:56 +000038namespace {
39 static const int kTOffsetExtensionId = 7;
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +000040 static const int kMaxPacketSize = 1500;
pbos@webrtc.org29023282013-09-11 10:14:56 +000041}
42
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000043class StreamObserver : public newapi::Transport, public RemoteBitrateObserver {
44 public:
45 typedef std::map<uint32_t, int> BytesSentMap;
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +000046 typedef std::map<uint32_t, uint32_t> SsrcMap;
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000047 StreamObserver(int num_expected_ssrcs,
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +000048 const SsrcMap& rtx_media_ssrcs,
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000049 newapi::Transport* feedback_transport,
50 Clock* clock)
51 : critical_section_(CriticalSectionWrapper::CreateCriticalSection()),
52 all_ssrcs_sent_(EventWrapper::Create()),
53 rtp_parser_(RtpHeaderParser::Create()),
pbos@webrtc.org27326b62013-11-20 12:17:04 +000054 feedback_transport_(feedback_transport),
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000055 receive_stats_(ReceiveStatistics::Create(clock)),
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +000056 payload_registry_(new RTPPayloadRegistry(
57 -1, RTPPayloadStrategy::CreateStrategy(false))),
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000058 clock_(clock),
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +000059 num_expected_ssrcs_(num_expected_ssrcs),
60 rtx_media_ssrcs_(rtx_media_ssrcs),
61 total_sent_(0),
62 padding_sent_(0),
63 rtx_media_sent_(0),
64 total_packets_sent_(0),
65 padding_packets_sent_(0),
66 rtx_media_packets_sent_(0) {
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000067 // Ideally we would only have to instantiate an RtcpSender, an
68 // RtpHeaderParser and a RemoteBitrateEstimator here, but due to the current
69 // state of the RTP module we need a full module and receive statistics to
70 // be able to produce an RTCP with REMB.
71 RtpRtcp::Configuration config;
72 config.receive_statistics = receive_stats_.get();
pbos@webrtc.org27326b62013-11-20 12:17:04 +000073 config.outgoing_transport = &feedback_transport_;
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000074 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
75 rtp_rtcp_->SetREMBStatus(true);
76 rtp_rtcp_->SetRTCPStatus(kRtcpNonCompound);
77 rtp_parser_->RegisterRtpHeaderExtension(kRtpExtensionTransmissionTimeOffset,
pbos@webrtc.org29023282013-09-11 10:14:56 +000078 kTOffsetExtensionId);
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000079 AbsoluteSendTimeRemoteBitrateEstimatorFactory rbe_factory;
80 remote_bitrate_estimator_.reset(rbe_factory.Create(this, clock));
81 }
82
83 virtual void OnReceiveBitrateChanged(const std::vector<unsigned int>& ssrcs,
84 unsigned int bitrate) {
85 CriticalSectionScoped lock(critical_section_.get());
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +000086 if (ssrcs.size() == num_expected_ssrcs_ && bitrate >= kExpectedBitrateBps) {
87 if (rtx_media_ssrcs_.empty() || rtx_media_sent_ > 0) {
88 const ::testing::TestInfo* const test_info =
89 ::testing::UnitTest::GetInstance()->current_test_info();
90 webrtc::test::PrintResult("total-sent", "", test_info->name(),
91 total_sent_, "bytes", false);
92 webrtc::test::PrintResult("padding-sent", "", test_info->name(),
93 padding_sent_, "bytes", false);
94 webrtc::test::PrintResult("rtx-media-sent", "", test_info->name(),
95 rtx_media_sent_, "bytes", false);
96 webrtc::test::PrintResult("total-packets-sent", "", test_info->name(),
97 total_packets_sent_, "packets", false);
98 webrtc::test::PrintResult("padding-packets-sent", "", test_info->name(),
99 padding_packets_sent_, "packets", false);
100 webrtc::test::PrintResult("rtx-packets-sent", "", test_info->name(),
101 rtx_media_packets_sent_, "packets", false);
102 all_ssrcs_sent_->Set();
103 }
104 }
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000105 rtp_rtcp_->SetREMBData(
106 bitrate, static_cast<uint8_t>(ssrcs.size()), &ssrcs[0]);
107 rtp_rtcp_->Process();
108 }
109
pbos@webrtc.org27326b62013-11-20 12:17:04 +0000110 virtual bool SendRtp(const uint8_t* packet, size_t length) OVERRIDE {
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000111 CriticalSectionScoped lock(critical_section_.get());
112 RTPHeader header;
113 EXPECT_TRUE(rtp_parser_->Parse(packet, static_cast<int>(length), &header));
114 receive_stats_->IncomingPacket(header, length, false);
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000115 payload_registry_->SetIncomingPayloadType(header);
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000116 remote_bitrate_estimator_->IncomingPacket(
117 clock_->TimeInMilliseconds(), static_cast<int>(length - 12), header);
118 if (remote_bitrate_estimator_->TimeUntilNextProcess() <= 0) {
119 remote_bitrate_estimator_->Process();
120 }
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000121 total_sent_ += length;
122 padding_sent_ += header.paddingLength;
123 ++total_packets_sent_;
124 if (header.paddingLength > 0)
125 ++padding_packets_sent_;
126 if (rtx_media_ssrcs_.find(header.ssrc) != rtx_media_ssrcs_.end()) {
127 rtx_media_sent_ += length - header.headerLength - header.paddingLength;
128 if (header.paddingLength == 0)
129 ++rtx_media_packets_sent_;
130 uint8_t restored_packet[kMaxPacketSize];
131 uint8_t* restored_packet_ptr = restored_packet;
132 int restored_length = static_cast<int>(length);
133 payload_registry_->RestoreOriginalPacket(
134 &restored_packet_ptr, packet, &restored_length,
135 rtx_media_ssrcs_[header.ssrc],
136 header);
137 length = restored_length;
138 EXPECT_TRUE(rtp_parser_->Parse(restored_packet, static_cast<int>(length),
139 &header));
140 } else {
141 rtp_rtcp_->SetRemoteSSRC(header.ssrc);
142 }
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000143 return true;
144 }
145
pbos@webrtc.org27326b62013-11-20 12:17:04 +0000146 virtual bool SendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000147 return true;
148 }
149
150 EventTypeWrapper Wait() { return all_ssrcs_sent_->Wait(120 * 1000); }
151
152 private:
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000153 static const unsigned int kExpectedBitrateBps = 1200000;
154
155 scoped_ptr<CriticalSectionWrapper> critical_section_;
156 scoped_ptr<EventWrapper> all_ssrcs_sent_;
157 scoped_ptr<RtpHeaderParser> rtp_parser_;
158 scoped_ptr<RtpRtcp> rtp_rtcp_;
pbos@webrtc.org27326b62013-11-20 12:17:04 +0000159 internal::TransportAdapter feedback_transport_;
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000160 scoped_ptr<ReceiveStatistics> receive_stats_;
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000161 scoped_ptr<RTPPayloadRegistry> payload_registry_;
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000162 scoped_ptr<RemoteBitrateEstimator> remote_bitrate_estimator_;
163 Clock* clock_;
164 const size_t num_expected_ssrcs_;
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000165 SsrcMap rtx_media_ssrcs_;
166 size_t total_sent_;
167 size_t padding_sent_;
168 size_t rtx_media_sent_;
169 int total_packets_sent_;
170 int padding_packets_sent_;
171 int rtx_media_packets_sent_;
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000172};
173
174class RampUpTest : public ::testing::TestWithParam<bool> {
175 public:
176 virtual void SetUp() { reserved_ssrcs_.clear(); }
177
178 protected:
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000179 void RunRampUpTest(bool pacing, bool rtx) {
180 const size_t kNumberOfStreams = 3;
181 std::vector<uint32_t> ssrcs;
182 for (size_t i = 0; i < kNumberOfStreams; ++i)
183 ssrcs.push_back(static_cast<uint32_t>(i + 1));
184 uint32_t kRtxSsrcs[kNumberOfStreams] = {111, 112, 113};
185 StreamObserver::SsrcMap rtx_ssrc_map;
186 if (rtx) {
187 for (size_t i = 0; i < ssrcs.size(); ++i)
188 rtx_ssrc_map[kRtxSsrcs[i]] = ssrcs[i];
189 }
190 test::DirectTransport receiver_transport;
191 int num_expected_ssrcs = kNumberOfStreams + (rtx ? 1 : 0);
192 StreamObserver stream_observer(
193 num_expected_ssrcs, rtx_ssrc_map, &receiver_transport,
194 Clock::GetRealTimeClock());
195
196 Call::Config call_config(&stream_observer);
197 webrtc::Config webrtc_config;
198 call_config.webrtc_config = &webrtc_config;
199 webrtc_config.Set<PaddingStrategy>(new PaddingStrategy(rtx));
200 scoped_ptr<Call> call(Call::Create(call_config));
201 VideoSendStream::Config send_config = call->GetDefaultSendConfig();
202
203 receiver_transport.SetReceiver(call->Receiver());
204
205 test::FakeEncoder encoder(Clock::GetRealTimeClock());
206 send_config.encoder = &encoder;
207 send_config.internal_source = false;
208 test::FakeEncoder::SetCodecSettings(&send_config.codec, kNumberOfStreams);
209 send_config.codec.plType = 125;
210 send_config.pacing = pacing;
211 send_config.rtp.nack.rtp_history_ms = 1000;
212 send_config.rtp.ssrcs.insert(send_config.rtp.ssrcs.begin(), ssrcs.begin(),
213 ssrcs.end());
214 if (rtx) {
215 send_config.rtp.rtx.rtx_payload_type = 96;
216 send_config.rtp.rtx.ssrcs.insert(send_config.rtp.rtx.ssrcs.begin(),
217 kRtxSsrcs,
218 kRtxSsrcs + kNumberOfStreams);
219 }
220 send_config.rtp.extensions.push_back(
221 RtpExtension(RtpExtension::kTOffset, kTOffsetExtensionId));
222
223 VideoSendStream* send_stream = call->CreateVideoSendStream(send_config);
224
225 scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
226 test::FrameGeneratorCapturer::Create(send_stream->Input(),
227 send_config.codec.width,
228 send_config.codec.height,
229 30,
230 Clock::GetRealTimeClock()));
231
232 send_stream->StartSending();
233 frame_generator_capturer->Start();
234
235 EXPECT_EQ(kEventSignaled, stream_observer.Wait());
236
237 frame_generator_capturer->Stop();
238 send_stream->StopSending();
239
240 call->DestroyVideoSendStream(send_stream);
241 }
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000242 std::map<uint32_t, bool> reserved_ssrcs_;
243};
244
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000245TEST_F(RampUpTest, WithoutPacing) {
246 RunRampUpTest(false, false);
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000247}
248
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000249TEST_F(RampUpTest, WithPacing) {
250 RunRampUpTest(true, false);
251}
252
253TEST_F(RampUpTest, WithPacingAndRtx) {
254 RunRampUpTest(true, true);
255}
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000256
257} // namespace webrtc