blob: 3978c5241d4e8a82be901480f14d1288fafd5375 [file] [log] [blame]
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +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 */
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +000010#include <assert.h>
11
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +000012#include <map>
13
14#include "testing/gtest/include/gtest/gtest.h"
15
stefan@webrtc.org360e3762013-08-22 09:29:56 +000016#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
17#include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h"
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +000018#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
stefan@webrtc.org360e3762013-08-22 09:29:56 +000019#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +000020#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
21#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
22#include "webrtc/system_wrappers/interface/scoped_ptr.h"
23#include "webrtc/system_wrappers/interface/event_wrapper.h"
pbos@webrtc.orgfd39e132013-08-14 13:52:52 +000024#include "webrtc/video_engine/new_include/video_call.h"
pbos@webrtc.org96684672013-08-12 12:59:04 +000025#include "webrtc/video_engine/test/common/direct_transport.h"
pbos@webrtc.org0181b5f2013-09-09 08:26:30 +000026#include "webrtc/video_engine/test/common/fake_decoder.h"
stefan@webrtc.org360e3762013-08-22 09:29:56 +000027#include "webrtc/video_engine/test/common/fake_encoder.h"
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +000028#include "webrtc/video_engine/test/common/frame_generator.h"
29#include "webrtc/video_engine/test/common/frame_generator_capturer.h"
30#include "webrtc/video_engine/test/common/generate_ssrcs.h"
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +000031#include "webrtc/video_engine/test/common/rtp_rtcp_observer.h"
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +000032
33namespace webrtc {
34
stefan@webrtc.org360e3762013-08-22 09:29:56 +000035class StreamObserver : public newapi::Transport, public RemoteBitrateObserver {
36 public:
37 typedef std::map<uint32_t, int> BytesSentMap;
38 StreamObserver(int num_expected_ssrcs, newapi::Transport* feedback_transport,
39 Clock* clock)
40 : critical_section_(CriticalSectionWrapper::CreateCriticalSection()),
41 all_ssrcs_sent_(EventWrapper::Create()),
42 rtp_parser_(RtpHeaderParser::Create()),
43 feedback_transport_(new TransportWrapper(feedback_transport)),
44 receive_stats_(ReceiveStatistics::Create(clock)),
45 clock_(clock),
46 num_expected_ssrcs_(num_expected_ssrcs) {
47 // Ideally we would only have to instantiate an RtcpSender, an
48 // RtpHeaderParser and a RemoteBitrateEstimator here, but due to the current
49 // state of the RTP module we need a full module and receive statistics to
50 // be able to produce an RTCP with REMB.
51 RtpRtcp::Configuration config;
52 config.receive_statistics = receive_stats_.get();
53 config.outgoing_transport = feedback_transport_.get();
54 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
55 rtp_rtcp_->SetREMBStatus(true);
56 rtp_rtcp_->SetRTCPStatus(kRtcpNonCompound);
57 rtp_parser_->RegisterRtpHeaderExtension(kRtpExtensionTransmissionTimeOffset,
58 1);
59 AbsoluteSendTimeRemoteBitrateEstimatorFactory rbe_factory;
60 remote_bitrate_estimator_.reset(rbe_factory.Create(this, clock));
61 }
62
63 virtual void OnReceiveBitrateChanged(const std::vector<unsigned int>& ssrcs,
64 unsigned int bitrate) {
65 CriticalSectionScoped lock(critical_section_.get());
66 if (ssrcs.size() == num_expected_ssrcs_ && bitrate >= kExpectedBitrateBps)
67 all_ssrcs_sent_->Set();
68 rtp_rtcp_->SetREMBData(bitrate, static_cast<uint8_t>(ssrcs.size()),
69 &ssrcs[0]);
70 rtp_rtcp_->Process();
71 }
72
73 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
74 CriticalSectionScoped lock(critical_section_.get());
75 RTPHeader header;
76 EXPECT_TRUE(rtp_parser_->Parse(packet, static_cast<int>(length),
77 &header));
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +000078 receive_stats_->IncomingPacket(header, length, false);
stefan@webrtc.org360e3762013-08-22 09:29:56 +000079 rtp_rtcp_->SetRemoteSSRC(header.ssrc);
80 remote_bitrate_estimator_->IncomingPacket(clock_->TimeInMilliseconds(),
81 static_cast<int>(length - 12),
82 header);
83 if (remote_bitrate_estimator_->TimeUntilNextProcess() <= 0) {
84 remote_bitrate_estimator_->Process();
85 }
86 return true;
87 }
88
89 virtual bool SendRTCP(const uint8_t* packet, size_t length) OVERRIDE {
90 return true;
91 }
92
93 EventTypeWrapper Wait() {
94 return all_ssrcs_sent_->Wait(120 * 1000);
95 }
96
97 private:
98 class TransportWrapper : public webrtc::Transport {
99 public:
100 explicit TransportWrapper(newapi::Transport* new_transport)
101 : new_transport_(new_transport) {}
102
103 virtual int SendPacket(int channel, const void *data, int len) OVERRIDE {
104 return new_transport_->SendRTP(static_cast<const uint8_t*>(data), len) ?
105 len : -1;
106 }
107
108 virtual int SendRTCPPacket(int channel, const void *data,
109 int len) OVERRIDE {
110 return new_transport_->SendRTCP(static_cast<const uint8_t*>(data), len) ?
111 len : -1;
112 }
113
114 private:
115 newapi::Transport* new_transport_;
116 };
117
118 static const unsigned int kExpectedBitrateBps = 1200000;
119
120 scoped_ptr<CriticalSectionWrapper> critical_section_;
121 scoped_ptr<EventWrapper> all_ssrcs_sent_;
122 scoped_ptr<RtpHeaderParser> rtp_parser_;
123 scoped_ptr<RtpRtcp> rtp_rtcp_;
124 scoped_ptr<TransportWrapper> feedback_transport_;
125 scoped_ptr<ReceiveStatistics> receive_stats_;
126 scoped_ptr<RemoteBitrateEstimator> remote_bitrate_estimator_;
127 Clock* clock_;
128 const size_t num_expected_ssrcs_;
129};
130
131class RampUpTest : public ::testing::TestWithParam<bool> {
132 public:
133 virtual void SetUp() {
134 reserved_ssrcs_.clear();
135 }
136
stefan@webrtc.org360e3762013-08-22 09:29:56 +0000137 protected:
138 std::map<uint32_t, bool> reserved_ssrcs_;
139};
140
141TEST_P(RampUpTest, RampUpWithPadding) {
142 test::DirectTransport receiver_transport;
143 StreamObserver stream_observer(3, &receiver_transport,
144 Clock::GetRealTimeClock());
pbos@webrtc.org74fa4892013-08-23 09:19:30 +0000145 VideoCall::Config call_config(&stream_observer);
146 scoped_ptr<VideoCall> call(VideoCall::Create(call_config));
147 VideoSendStream::Config send_config =
stefan@webrtc.org360e3762013-08-22 09:29:56 +0000148 call->GetDefaultSendConfig();
149
150 receiver_transport.SetReceiver(call->Receiver());
151
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +0000152 test::FakeEncoder encoder(Clock::GetRealTimeClock());
stefan@webrtc.org360e3762013-08-22 09:29:56 +0000153 send_config.encoder = &encoder;
154 send_config.internal_source = false;
pbos@webrtc.org0181b5f2013-09-09 08:26:30 +0000155 test::FakeEncoder::SetCodecSettings(&send_config.codec, 3);
stefan@webrtc.org360e3762013-08-22 09:29:56 +0000156 send_config.pacing = GetParam();
157
158 test::GenerateRandomSsrcs(&send_config, &reserved_ssrcs_);
159
pbos@webrtc.org74fa4892013-08-23 09:19:30 +0000160 VideoSendStream* send_stream =
stefan@webrtc.org360e3762013-08-22 09:29:56 +0000161 call->CreateSendStream(send_config);
162
pbos@webrtc.org74fa4892013-08-23 09:19:30 +0000163 VideoReceiveStream::Config receive_config;
stefan@webrtc.org360e3762013-08-22 09:29:56 +0000164 receive_config.rtp.ssrc = send_config.rtp.ssrcs[0];
165 receive_config.rtp.nack.rtp_history_ms =
166 send_config.rtp.nack.rtp_history_ms;
pbos@webrtc.org74fa4892013-08-23 09:19:30 +0000167 VideoReceiveStream* receive_stream = call->CreateReceiveStream(
stefan@webrtc.org360e3762013-08-22 09:29:56 +0000168 receive_config);
169
170 scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
171 test::FrameGeneratorCapturer::Create(
172 send_stream->Input(),
173 test::FrameGenerator::Create(
174 send_config.codec.width, send_config.codec.height,
175 Clock::GetRealTimeClock()),
176 30));
177
178 receive_stream->StartReceive();
179 send_stream->StartSend();
180 frame_generator_capturer->Start();
181
182 EXPECT_EQ(kEventSignaled, stream_observer.Wait());
183
184 frame_generator_capturer->Stop();
185 send_stream->StopSend();
186 receive_stream->StopReceive();
187
188 call->DestroyReceiveStream(receive_stream);
189 call->DestroySendStream(send_stream);
190}
191
192INSTANTIATE_TEST_CASE_P(RampUpTest, RampUpTest, ::testing::Bool());
193
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000194struct EngineTestParams {
195 size_t width, height;
196 struct {
197 unsigned int min, start, max;
198 } bitrate;
199};
200
201class EngineTest : public ::testing::TestWithParam<EngineTestParams> {
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000202 public:
pbos@webrtc.org0181b5f2013-09-09 08:26:30 +0000203 EngineTest()
204 : send_stream_(NULL),
205 receive_stream_(NULL),
206 fake_encoder_(Clock::GetRealTimeClock()) {}
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000207
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000208 ~EngineTest() {
209 EXPECT_EQ(NULL, send_stream_);
210 EXPECT_EQ(NULL, receive_stream_);
211 }
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000212
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000213 protected:
214 void CreateCalls(newapi::Transport* sender_transport,
215 newapi::Transport* receiver_transport) {
pbos@webrtc.org74fa4892013-08-23 09:19:30 +0000216 VideoCall::Config sender_config(sender_transport);
217 VideoCall::Config receiver_config(receiver_transport);
218 sender_call_.reset(VideoCall::Create(sender_config));
219 receiver_call_.reset(VideoCall::Create(receiver_config));
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000220 }
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000221
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000222 void CreateTestConfigs() {
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000223 send_config_ = sender_call_->GetDefaultSendConfig();
224 receive_config_ = receiver_call_->GetDefaultReceiveConfig();
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000225
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000226 test::GenerateRandomSsrcs(&send_config_, &reserved_ssrcs_);
pbos@webrtc.org0181b5f2013-09-09 08:26:30 +0000227 send_config_.encoder = &fake_encoder_;
228 send_config_.internal_source = false;
229 test::FakeEncoder::SetCodecSettings(&send_config_.codec, 1);
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000230
pbos@webrtc.org0181b5f2013-09-09 08:26:30 +0000231 receive_config_.codecs.clear();
232 receive_config_.codecs.push_back(send_config_.codec);
233 ExternalVideoDecoder decoder;
234 decoder.decoder = &fake_decoder_;
235 decoder.payload_type = send_config_.codec.plType;
236 receive_config_.external_decoders.push_back(decoder);
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000237 receive_config_.rtp.ssrc = send_config_.rtp.ssrcs[0];
238 }
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000239
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000240 void CreateStreams() {
241 assert(send_stream_ == NULL);
242 assert(receive_stream_ == NULL);
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000243
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000244 send_stream_ = sender_call_->CreateSendStream(send_config_);
245 receive_stream_ = receiver_call_->CreateReceiveStream(receive_config_);
246 }
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000247
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000248 void CreateFrameGenerator() {
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000249 frame_generator_capturer_.reset(test::FrameGeneratorCapturer::Create(
250 send_stream_->Input(),
pbos@webrtc.org0181b5f2013-09-09 08:26:30 +0000251 test::FrameGenerator::Create(send_config_.codec.width,
252 send_config_.codec.height,
253 Clock::GetRealTimeClock()),
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000254 30));
255 }
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000256
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000257 void StartSending() {
258 receive_stream_->StartReceive();
259 send_stream_->StartSend();
260 frame_generator_capturer_->Start();
261 }
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000262
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000263 void StopSending() {
264 frame_generator_capturer_->Stop();
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000265 if (send_stream_ != NULL)
266 send_stream_->StopSend();
267 if (receive_stream_ != NULL)
268 receive_stream_->StopReceive();
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000269 }
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000270
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000271 void DestroyStreams() {
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000272 if (send_stream_ != NULL)
273 sender_call_->DestroySendStream(send_stream_);
274 if (receive_stream_ != NULL)
275 receiver_call_->DestroyReceiveStream(receive_stream_);
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000276 send_stream_= NULL;
277 receive_stream_ = NULL;
278 }
279
280 void ReceivesPliAndRecovers(int rtp_history_ms);
281
pbos@webrtc.org74fa4892013-08-23 09:19:30 +0000282 scoped_ptr<VideoCall> sender_call_;
283 scoped_ptr<VideoCall> receiver_call_;
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000284
pbos@webrtc.org74fa4892013-08-23 09:19:30 +0000285 VideoSendStream::Config send_config_;
286 VideoReceiveStream::Config receive_config_;
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000287
pbos@webrtc.org74fa4892013-08-23 09:19:30 +0000288 VideoSendStream* send_stream_;
289 VideoReceiveStream* receive_stream_;
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000290
291 scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer_;
292
pbos@webrtc.org0181b5f2013-09-09 08:26:30 +0000293 test::FakeEncoder fake_encoder_;
294 test::FakeDecoder fake_decoder_;
295
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000296 std::map<uint32_t, bool> reserved_ssrcs_;
297};
298
299// TODO(pbos): What are sane values here for bitrate? Are we missing any
300// important resolutions?
301EngineTestParams video_1080p = {1920, 1080, {300, 600, 800}};
302EngineTestParams video_720p = {1280, 720, {300, 600, 800}};
303EngineTestParams video_vga = {640, 480, {300, 600, 800}};
304EngineTestParams video_qvga = {320, 240, {300, 600, 800}};
305EngineTestParams video_4cif = {704, 576, {300, 600, 800}};
306EngineTestParams video_cif = {352, 288, {300, 600, 800}};
307EngineTestParams video_qcif = {176, 144, {300, 600, 800}};
308
309class NackObserver : public test::RtpRtcpObserver {
310 static const int kNumberOfNacksToObserve = 4;
311 static const int kInverseProbabilityToStartLossBurst = 20;
312 static const int kMaxLossBurst = 10;
313 public:
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000314 NackObserver()
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000315 : received_all_retransmissions_(EventWrapper::Create()),
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000316 rtp_parser_(RtpHeaderParser::Create()),
317 drop_burst_count_(0),
318 sent_rtp_packets_(0),
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000319 nacks_left_(kNumberOfNacksToObserve) {}
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000320
321 EventTypeWrapper Wait() {
322 // 2 minutes should be more than enough time for the test to finish.
323 return received_all_retransmissions_->Wait(2 * 60 * 1000);
324 }
325
326 private:
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000327 virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000328 EXPECT_FALSE(RtpHeaderParser::IsRtcp(packet, static_cast<int>(length)));
329
330 RTPHeader header;
331 EXPECT_TRUE(rtp_parser_->Parse(packet, static_cast<int>(length), &header));
332
333 // Never drop retransmitted packets.
334 if (dropped_packets_.find(header.sequenceNumber) !=
335 dropped_packets_.end()) {
336 retransmitted_packets_.insert(header.sequenceNumber);
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000337 return SEND_PACKET;
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000338 }
339
340 // Enough NACKs received, stop dropping packets.
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000341 if (nacks_left_ == 0) {
342 ++sent_rtp_packets_;
343 return SEND_PACKET;
344 }
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000345
346 // Still dropping packets.
347 if (drop_burst_count_ > 0) {
348 --drop_burst_count_;
349 dropped_packets_.insert(header.sequenceNumber);
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000350 return DROP_PACKET;
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000351 }
352
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000353 // Should we start dropping packets?
354 if (sent_rtp_packets_ > 0 &&
355 rand() % kInverseProbabilityToStartLossBurst == 0) {
356 drop_burst_count_ = rand() % kMaxLossBurst;
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000357 dropped_packets_.insert(header.sequenceNumber);
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000358 return DROP_PACKET;
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000359 }
360
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000361 ++sent_rtp_packets_;
362 return SEND_PACKET;
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000363 }
364
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000365 virtual Action OnReceiveRtcp(const uint8_t* packet, size_t length) OVERRIDE {
366 RTCPUtility::RTCPParserV2 parser(packet, length, true);
367 EXPECT_TRUE(parser.IsValid());
368
369 bool received_nack = false;
370 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
371 while (packet_type != RTCPUtility::kRtcpNotValidCode) {
372 if (packet_type == RTCPUtility::kRtcpRtpfbNackCode)
373 received_nack = true;
374
375 packet_type = parser.Iterate();
376 }
377
378 if (received_nack) {
379 ReceivedNack();
380 } else {
381 RtcpWithoutNack();
382 }
383 return SEND_PACKET;
384 }
385
386 private:
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000387 void ReceivedNack() {
388 if (nacks_left_ > 0)
389 --nacks_left_;
390 rtcp_without_nack_count_ = 0;
391 }
392
393 void RtcpWithoutNack() {
394 if (nacks_left_ > 0)
395 return;
396 ++rtcp_without_nack_count_;
397
398 // All packets retransmitted and no recent NACKs.
399 if (dropped_packets_.size() == retransmitted_packets_.size() &&
400 rtcp_without_nack_count_ >= kRequiredRtcpsWithoutNack) {
401 received_all_retransmissions_->Set();
402 }
403 }
404
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000405 scoped_ptr<EventWrapper> received_all_retransmissions_;
406
407 scoped_ptr<RtpHeaderParser> rtp_parser_;
408 std::set<uint16_t> dropped_packets_;
409 std::set<uint16_t> retransmitted_packets_;
410 int drop_burst_count_;
411 uint64_t sent_rtp_packets_;
412 int nacks_left_;
413 int rtcp_without_nack_count_;
414 static const int kRequiredRtcpsWithoutNack = 2;
415};
416
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000417TEST_P(EngineTest, ReceivesAndRetransmitsNack) {
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000418 NackObserver observer;
419
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000420 CreateCalls(observer.SendTransport(), observer.ReceiveTransport());
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000421
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000422 observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000423
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000424 CreateTestConfigs();
425 int rtp_history_ms = 1000;
426 send_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
427 receive_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000428
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000429 CreateStreams();
430 CreateFrameGenerator();
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000431
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000432 StartSending();
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000433
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000434 // Wait() waits for an event triggered when NACKs have been received, NACKed
435 // packets retransmitted and frames rendered again.
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000436 EXPECT_EQ(kEventSignaled, observer.Wait());
437
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000438 StopSending();
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000439
pbos@webrtc.org96684672013-08-12 12:59:04 +0000440 observer.StopSending();
pbos@webrtc.org0181b5f2013-09-09 08:26:30 +0000441
442 DestroyStreams();
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000443}
444
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000445class PliObserver : public test::RtpRtcpObserver {
446 static const int kInverseDropProbability = 16;
447 public:
448 PliObserver(bool nack_enabled) :
449 renderer_(this),
450 rtp_header_parser_(RtpHeaderParser::Create()),
451 nack_enabled_(nack_enabled),
452 first_retransmitted_timestamp_(0),
453 last_send_timestamp_(0),
454 rendered_frame_(false),
455 received_pli_(false) {}
456
457 virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
458 RTPHeader header;
pbos@webrtc.orgd5f4c152013-08-19 16:35:36 +0000459 EXPECT_TRUE(
460 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000461
462 // Drop all NACK retransmissions. This is to force transmission of a PLI.
463 if (header.timestamp < last_send_timestamp_)
464 return DROP_PACKET;
465
466 if (received_pli_) {
467 if (first_retransmitted_timestamp_ == 0) {
468 first_retransmitted_timestamp_ = header.timestamp;
469 }
470 } else if (rendered_frame_ && rand() % kInverseDropProbability == 0) {
471 return DROP_PACKET;
472 }
473
474 last_send_timestamp_ = header.timestamp;
475 return SEND_PACKET;
476 }
477
478 virtual Action OnReceiveRtcp(const uint8_t* packet, size_t length) OVERRIDE {
479 RTCPUtility::RTCPParserV2 parser(packet, length, true);
480 EXPECT_TRUE(parser.IsValid());
481
482 for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
483 packet_type != RTCPUtility::kRtcpNotValidCode;
484 packet_type = parser.Iterate()) {
485 if (!nack_enabled_)
486 EXPECT_NE(packet_type, RTCPUtility::kRtcpRtpfbNackCode);
487
488 if (packet_type == RTCPUtility::kRtcpPsfbPliCode) {
489 received_pli_ = true;
490 break;
491 }
492 }
493 return SEND_PACKET;
494 }
495
pbos@webrtc.org74fa4892013-08-23 09:19:30 +0000496 class ReceiverRenderer : public VideoRenderer {
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000497 public:
498 ReceiverRenderer(PliObserver* observer)
499 : rendered_retransmission_(EventWrapper::Create()),
500 observer_(observer) {}
501
502 virtual void RenderFrame(const I420VideoFrame& video_frame,
503 int time_to_render_ms) {
504 CriticalSectionScoped crit_(observer_->lock_.get());
505 if (observer_->first_retransmitted_timestamp_ != 0 &&
506 video_frame.timestamp() > observer_->first_retransmitted_timestamp_) {
507 EXPECT_TRUE(observer_->received_pli_);
508 rendered_retransmission_->Set();
509 }
510 observer_->rendered_frame_ = true;
511 }
512 scoped_ptr<EventWrapper> rendered_retransmission_;
513 PliObserver* observer_;
514 } renderer_;
515
516 EventTypeWrapper Wait() {
517 // 120 seconds should be plenty of time.
518 return renderer_.rendered_retransmission_->Wait(2 * 60 * 1000);
519 }
520
521 private:
522 scoped_ptr<RtpHeaderParser> rtp_header_parser_;
523 bool nack_enabled_;
524
525 uint32_t first_retransmitted_timestamp_;
526 uint32_t last_send_timestamp_;
527
528 bool rendered_frame_;
529 bool received_pli_;
530};
531
532void EngineTest::ReceivesPliAndRecovers(int rtp_history_ms) {
533 PliObserver observer(rtp_history_ms > 0);
534
535 CreateCalls(observer.SendTransport(), observer.ReceiveTransport());
536
537 observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
538
539 CreateTestConfigs();
540 send_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
541 receive_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
542 receive_config_.renderer = &observer.renderer_;
543
544 CreateStreams();
545 CreateFrameGenerator();
546
547 StartSending();
548
549 // Wait() waits for an event triggered when Pli has been received and frames
550 // have been rendered afterwards.
551 EXPECT_EQ(kEventSignaled, observer.Wait());
552
553 StopSending();
554
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000555 observer.StopSending();
pbos@webrtc.org0181b5f2013-09-09 08:26:30 +0000556
557 DestroyStreams();
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000558}
559
mflodman@webrtc.orge2d4da62013-09-04 14:21:57 +0000560TEST_P(EngineTest, ReceivesPliAndRecoversWithNack) {
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000561 ReceivesPliAndRecovers(1000);
562}
563
564// TODO(pbos): Enable this when 2250 is resolved.
565TEST_P(EngineTest, DISABLED_ReceivesPliAndRecoversWithoutNack) {
566 ReceivesPliAndRecovers(0);
567}
568
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000569TEST_P(EngineTest, SurvivesIncomingRtpPacketsToDestroyedReceiveStream) {
570 class PacketInputObserver : public PacketReceiver {
571 public:
572 explicit PacketInputObserver(PacketReceiver* receiver)
573 : receiver_(receiver), delivered_packet_(EventWrapper::Create()) {}
574
575 EventTypeWrapper Wait() {
576 return delivered_packet_->Wait(30 * 1000);
577 }
578
579 private:
580 virtual bool DeliverPacket(const uint8_t* packet, size_t length) {
581 if (RtpHeaderParser::IsRtcp(packet, static_cast<int>(length))) {
582 return receiver_->DeliverPacket(packet, length);
583 } else {
584 EXPECT_FALSE(receiver_->DeliverPacket(packet, length));
585 delivered_packet_->Set();
586 return false;
587 }
588 }
589
590 PacketReceiver* receiver_;
591 scoped_ptr<EventWrapper> delivered_packet_;
592 };
593
594 test::DirectTransport send_transport, receive_transport;
595
596 CreateCalls(&send_transport, &receive_transport);
597 PacketInputObserver input_observer(receiver_call_->Receiver());
598
599 send_transport.SetReceiver(&input_observer);
600 receive_transport.SetReceiver(sender_call_->Receiver());
601
602 CreateTestConfigs();
603
604 CreateStreams();
605 CreateFrameGenerator();
606
607 StartSending();
608
609 receiver_call_->DestroyReceiveStream(receive_stream_);
610 receive_stream_ = NULL;
611
612 // Wait() waits for a received packet.
613 EXPECT_EQ(kEventSignaled, input_observer.Wait());
614
615 StopSending();
616
617 DestroyStreams();
618
619 send_transport.StopSending();
620 receive_transport.StopSending();
621}
622
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000623INSTANTIATE_TEST_CASE_P(EngineTest, EngineTest, ::testing::Values(video_vga));
624} // namespace webrtc