blob: 6a8f34fdf6a9e7e054750c51fa4ce5ba0702c284 [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
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000016#include "webrtc/call.h"
pbos@webrtc.orge0536292013-10-21 09:02:30 +000017#include "webrtc/common_video/test/frame_generator.h"
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +000018#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
19#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
20#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +000021#include "webrtc/system_wrappers/interface/event_wrapper.h"
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000022#include "webrtc/system_wrappers/interface/scoped_ptr.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000023#include "webrtc/test/direct_transport.h"
24#include "webrtc/test/fake_decoder.h"
25#include "webrtc/test/fake_encoder.h"
26#include "webrtc/test/frame_generator_capturer.h"
27#include "webrtc/test/generate_ssrcs.h"
28#include "webrtc/test/rtp_rtcp_observer.h"
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +000029
30namespace webrtc {
31
pbos@webrtc.orgc11148b2013-10-17 14:14:42 +000032static unsigned int kDefaultTimeoutMs = 30 * 1000;
33static unsigned int kLongTimeoutMs = 120 * 1000;
34
pbos@webrtc.org2e246b42013-09-27 10:54:10 +000035class CallTest : public ::testing::Test {
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +000036 public:
pbos@webrtc.org6917e192013-09-19 14:22:12 +000037 CallTest()
pbos@webrtc.org0181b5f2013-09-09 08:26:30 +000038 : send_stream_(NULL),
39 receive_stream_(NULL),
40 fake_encoder_(Clock::GetRealTimeClock()) {}
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +000041
pbos@webrtc.org6917e192013-09-19 14:22:12 +000042 ~CallTest() {
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +000043 EXPECT_EQ(NULL, send_stream_);
44 EXPECT_EQ(NULL, receive_stream_);
45 }
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +000046
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +000047 protected:
pbos@webrtc.orgde74b642013-10-02 13:36:09 +000048 void CreateCalls(const Call::Config& sender_config,
49 const Call::Config& receiver_config) {
pbos@webrtc.org841c8a42013-09-09 15:04:25 +000050 sender_call_.reset(Call::Create(sender_config));
51 receiver_call_.reset(Call::Create(receiver_config));
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +000052 }
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +000053
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +000054 void CreateTestConfigs() {
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +000055 send_config_ = sender_call_->GetDefaultSendConfig();
56 receive_config_ = receiver_call_->GetDefaultReceiveConfig();
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +000057
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +000058 test::GenerateRandomSsrcs(&send_config_, &reserved_ssrcs_);
pbos@webrtc.org0181b5f2013-09-09 08:26:30 +000059 send_config_.encoder = &fake_encoder_;
60 send_config_.internal_source = false;
61 test::FakeEncoder::SetCodecSettings(&send_config_.codec, 1);
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +000062
pbos@webrtc.org0181b5f2013-09-09 08:26:30 +000063 receive_config_.codecs.clear();
64 receive_config_.codecs.push_back(send_config_.codec);
65 ExternalVideoDecoder decoder;
66 decoder.decoder = &fake_decoder_;
67 decoder.payload_type = send_config_.codec.plType;
68 receive_config_.external_decoders.push_back(decoder);
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +000069 receive_config_.rtp.ssrc = send_config_.rtp.ssrcs[0];
70 }
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +000071
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +000072 void CreateStreams() {
73 assert(send_stream_ == NULL);
74 assert(receive_stream_ == NULL);
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +000075
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +000076 send_stream_ = sender_call_->CreateSendStream(send_config_);
77 receive_stream_ = receiver_call_->CreateReceiveStream(receive_config_);
78 }
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +000079
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +000080 void CreateFrameGenerator() {
andresp@webrtc.orgab654952013-09-19 12:14:03 +000081 frame_generator_capturer_.reset(
82 test::FrameGeneratorCapturer::Create(send_stream_->Input(),
83 send_config_.codec.width,
84 send_config_.codec.height,
85 30,
86 Clock::GetRealTimeClock()));
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +000087 }
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +000088
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +000089 void StartSending() {
90 receive_stream_->StartReceive();
91 send_stream_->StartSend();
pbos@webrtc.orge0536292013-10-21 09:02:30 +000092 if (frame_generator_capturer_.get() != NULL)
93 frame_generator_capturer_->Start();
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +000094 }
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +000095
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +000096 void StopSending() {
pbos@webrtc.orge0536292013-10-21 09:02:30 +000097 if (frame_generator_capturer_.get() != NULL)
98 frame_generator_capturer_->Stop();
pbos@webrtc.org95e51f52013-09-05 12:38:54 +000099 if (send_stream_ != NULL)
100 send_stream_->StopSend();
101 if (receive_stream_ != NULL)
102 receive_stream_->StopReceive();
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000103 }
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000104
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000105 void DestroyStreams() {
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000106 if (send_stream_ != NULL)
107 sender_call_->DestroySendStream(send_stream_);
108 if (receive_stream_ != NULL)
109 receiver_call_->DestroyReceiveStream(receive_stream_);
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000110 send_stream_ = NULL;
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000111 receive_stream_ = NULL;
112 }
113
114 void ReceivesPliAndRecovers(int rtp_history_ms);
pbos@webrtc.orgc11148b2013-10-17 14:14:42 +0000115 void RespectsRtcpMode(newapi::RtcpMode rtcp_mode);
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000116
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000117 scoped_ptr<Call> sender_call_;
118 scoped_ptr<Call> receiver_call_;
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000119
pbos@webrtc.org74fa4892013-08-23 09:19:30 +0000120 VideoSendStream::Config send_config_;
121 VideoReceiveStream::Config receive_config_;
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000122
pbos@webrtc.org74fa4892013-08-23 09:19:30 +0000123 VideoSendStream* send_stream_;
124 VideoReceiveStream* receive_stream_;
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000125
126 scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer_;
127
pbos@webrtc.org0181b5f2013-09-09 08:26:30 +0000128 test::FakeEncoder fake_encoder_;
129 test::FakeDecoder fake_decoder_;
130
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000131 std::map<uint32_t, bool> reserved_ssrcs_;
132};
133
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000134class NackObserver : public test::RtpRtcpObserver {
135 static const int kNumberOfNacksToObserve = 4;
136 static const int kInverseProbabilityToStartLossBurst = 20;
137 static const int kMaxLossBurst = 10;
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000138
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000139 public:
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000140 NackObserver()
pbos@webrtc.orgc11148b2013-10-17 14:14:42 +0000141 : test::RtpRtcpObserver(kLongTimeoutMs),
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000142 rtp_parser_(RtpHeaderParser::Create()),
143 drop_burst_count_(0),
144 sent_rtp_packets_(0),
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000145 nacks_left_(kNumberOfNacksToObserve) {}
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000146
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000147 private:
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000148 virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000149 EXPECT_FALSE(RtpHeaderParser::IsRtcp(packet, static_cast<int>(length)));
150
151 RTPHeader header;
152 EXPECT_TRUE(rtp_parser_->Parse(packet, static_cast<int>(length), &header));
153
154 // Never drop retransmitted packets.
155 if (dropped_packets_.find(header.sequenceNumber) !=
156 dropped_packets_.end()) {
157 retransmitted_packets_.insert(header.sequenceNumber);
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000158 return SEND_PACKET;
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000159 }
160
161 // Enough NACKs received, stop dropping packets.
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000162 if (nacks_left_ == 0) {
163 ++sent_rtp_packets_;
164 return SEND_PACKET;
165 }
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000166
167 // Still dropping packets.
168 if (drop_burst_count_ > 0) {
169 --drop_burst_count_;
170 dropped_packets_.insert(header.sequenceNumber);
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000171 return DROP_PACKET;
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000172 }
173
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000174 // Should we start dropping packets?
175 if (sent_rtp_packets_ > 0 &&
176 rand() % kInverseProbabilityToStartLossBurst == 0) {
177 drop_burst_count_ = rand() % kMaxLossBurst;
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000178 dropped_packets_.insert(header.sequenceNumber);
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000179 return DROP_PACKET;
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000180 }
181
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000182 ++sent_rtp_packets_;
183 return SEND_PACKET;
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000184 }
185
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000186 virtual Action OnReceiveRtcp(const uint8_t* packet, size_t length) OVERRIDE {
187 RTCPUtility::RTCPParserV2 parser(packet, length, true);
188 EXPECT_TRUE(parser.IsValid());
189
190 bool received_nack = false;
191 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
192 while (packet_type != RTCPUtility::kRtcpNotValidCode) {
193 if (packet_type == RTCPUtility::kRtcpRtpfbNackCode)
194 received_nack = true;
195
196 packet_type = parser.Iterate();
197 }
198
199 if (received_nack) {
200 ReceivedNack();
201 } else {
202 RtcpWithoutNack();
203 }
204 return SEND_PACKET;
205 }
206
207 private:
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000208 void ReceivedNack() {
209 if (nacks_left_ > 0)
210 --nacks_left_;
211 rtcp_without_nack_count_ = 0;
212 }
213
214 void RtcpWithoutNack() {
215 if (nacks_left_ > 0)
216 return;
217 ++rtcp_without_nack_count_;
218
219 // All packets retransmitted and no recent NACKs.
220 if (dropped_packets_.size() == retransmitted_packets_.size() &&
221 rtcp_without_nack_count_ >= kRequiredRtcpsWithoutNack) {
pbos@webrtc.org6917e192013-09-19 14:22:12 +0000222 observation_complete_->Set();
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000223 }
224 }
225
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000226 scoped_ptr<RtpHeaderParser> rtp_parser_;
227 std::set<uint16_t> dropped_packets_;
228 std::set<uint16_t> retransmitted_packets_;
229 int drop_burst_count_;
230 uint64_t sent_rtp_packets_;
231 int nacks_left_;
232 int rtcp_without_nack_count_;
233 static const int kRequiredRtcpsWithoutNack = 2;
234};
235
pbos@webrtc.orgde74b642013-10-02 13:36:09 +0000236TEST_F(CallTest, UsesTraceCallback) {
237 const unsigned int kSenderTraceFilter = kTraceDebug;
238 const unsigned int kReceiverTraceFilter = kTraceDefault & (~kTraceDebug);
pbos@webrtc.orgfe1ef932013-10-21 10:34:43 +0000239 class TraceObserver : public TraceCallback {
pbos@webrtc.orgde74b642013-10-02 13:36:09 +0000240 public:
241 TraceObserver(unsigned int filter)
242 : filter_(filter), messages_left_(50), done_(EventWrapper::Create()) {}
243
244 virtual void Print(TraceLevel level,
245 const char* message,
246 int length) OVERRIDE {
247 EXPECT_EQ(0u, level & (~filter_));
248 if (--messages_left_ == 0)
249 done_->Set();
250 }
251
pbos@webrtc.orgc11148b2013-10-17 14:14:42 +0000252 EventTypeWrapper Wait() { return done_->Wait(kDefaultTimeoutMs); }
pbos@webrtc.orgde74b642013-10-02 13:36:09 +0000253
254 private:
255 unsigned int filter_;
256 unsigned int messages_left_;
257 scoped_ptr<EventWrapper> done_;
258 } sender_trace(kSenderTraceFilter), receiver_trace(kReceiverTraceFilter);
259
260 test::DirectTransport send_transport, receive_transport;
261 Call::Config sender_call_config(&send_transport);
262 sender_call_config.trace_callback = &sender_trace;
263 sender_call_config.trace_filter = kSenderTraceFilter;
264 Call::Config receiver_call_config(&receive_transport);
265 receiver_call_config.trace_callback = &receiver_trace;
266 receiver_call_config.trace_filter = kReceiverTraceFilter;
267 CreateCalls(sender_call_config, receiver_call_config);
268 send_transport.SetReceiver(receiver_call_->Receiver());
269 receive_transport.SetReceiver(sender_call_->Receiver());
270
271 CreateTestConfigs();
272
273 CreateStreams();
274 CreateFrameGenerator();
275 StartSending();
276
277 // Wait() waits for a couple of trace callbacks to occur.
278 EXPECT_EQ(kEventSignaled, sender_trace.Wait());
279 EXPECT_EQ(kEventSignaled, receiver_trace.Wait());
280
281 StopSending();
282 send_transport.StopSending();
283 receive_transport.StopSending();
284 DestroyStreams();
285
286 // The TraceCallback instance MUST outlive Calls, destroy Calls explicitly.
287 sender_call_.reset();
288 receiver_call_.reset();
289}
290
pbos@webrtc.orge0536292013-10-21 09:02:30 +0000291TEST_F(CallTest, TransmitsFirstFrame) {
292 class Renderer : public VideoRenderer {
293 public:
294 Renderer() : event_(EventWrapper::Create()) {}
295
296 virtual void RenderFrame(const I420VideoFrame& video_frame,
297 int /*time_to_render_ms*/) OVERRIDE {
298 event_->Set();
299 }
300
301 EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
302
303 scoped_ptr<EventWrapper> event_;
304 } renderer;
305
306 test::DirectTransport sender_transport, receiver_transport;
307
308 CreateCalls(Call::Config(&sender_transport),
309 Call::Config(&receiver_transport));
310
311 sender_transport.SetReceiver(receiver_call_->Receiver());
312 receiver_transport.SetReceiver(sender_call_->Receiver());
313
314 CreateTestConfigs();
315 receive_config_.renderer = &renderer;
316
317 CreateStreams();
318 StartSending();
319
320 scoped_ptr<test::FrameGenerator> frame_generator(test::FrameGenerator::Create(
321 send_config_.codec.width, send_config_.codec.height));
322 send_stream_->Input()->PutFrame(frame_generator->NextFrame(), 0);
323
324 EXPECT_EQ(kEventSignaled, renderer.Wait())
325 << "Timed out while waiting for the frame to render.";
326
327 StopSending();
328
329 sender_transport.StopSending();
330 receiver_transport.StopSending();
331
332 DestroyStreams();
333}
334
pbos@webrtc.org2e246b42013-09-27 10:54:10 +0000335TEST_F(CallTest, ReceivesAndRetransmitsNack) {
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000336 NackObserver observer;
337
pbos@webrtc.orgde74b642013-10-02 13:36:09 +0000338 CreateCalls(Call::Config(observer.SendTransport()),
339 Call::Config(observer.ReceiveTransport()));
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000340
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000341 observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000342
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000343 CreateTestConfigs();
344 int rtp_history_ms = 1000;
345 send_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
346 receive_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000347
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000348 CreateStreams();
349 CreateFrameGenerator();
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000350 StartSending();
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000351
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000352 // Wait() waits for an event triggered when NACKs have been received, NACKed
353 // packets retransmitted and frames rendered again.
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000354 EXPECT_EQ(kEventSignaled, observer.Wait());
355
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000356 StopSending();
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000357
pbos@webrtc.org96684672013-08-12 12:59:04 +0000358 observer.StopSending();
pbos@webrtc.org0181b5f2013-09-09 08:26:30 +0000359
360 DestroyStreams();
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000361}
362
pbos@webrtc.orgfe1ef932013-10-21 10:34:43 +0000363TEST_F(CallTest, UsesFrameCallbacks) {
364 static const int kWidth = 320;
365 static const int kHeight = 240;
366
367 class Renderer : public VideoRenderer {
368 public:
369 Renderer() : event_(EventWrapper::Create()) {}
370
371 virtual void RenderFrame(const I420VideoFrame& video_frame,
372 int /*time_to_render_ms*/) OVERRIDE {
373 EXPECT_EQ(0, *video_frame.buffer(kYPlane))
374 << "Rendered frame should have zero luma which is applied by the "
375 "pre-render callback.";
376 event_->Set();
377 }
378
379 EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
380 scoped_ptr<EventWrapper> event_;
381 } renderer;
382
383 class TestFrameCallback : public I420FrameCallback {
384 public:
385 TestFrameCallback(int expected_luma_byte, int next_luma_byte)
386 : event_(EventWrapper::Create()),
387 expected_luma_byte_(expected_luma_byte),
388 next_luma_byte_(next_luma_byte) {}
389
390 EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
391
392 private:
393 virtual void FrameCallback(I420VideoFrame* frame) {
394 EXPECT_EQ(kWidth, frame->width())
395 << "Width not as expected, callback done before resize?";
396 EXPECT_EQ(kHeight, frame->height())
397 << "Height not as expected, callback done before resize?";
398
399 // Previous luma specified, observed luma should be fairly close.
400 if (expected_luma_byte_ != -1) {
401 EXPECT_NEAR(expected_luma_byte_, *frame->buffer(kYPlane), 10);
402 }
403
404 memset(frame->buffer(kYPlane),
405 next_luma_byte_,
406 frame->allocated_size(kYPlane));
407
408 event_->Set();
409 }
410
411 scoped_ptr<EventWrapper> event_;
412 int expected_luma_byte_;
413 int next_luma_byte_;
414 };
415
416 TestFrameCallback pre_encode_callback(-1, 255); // Changes luma to 255.
417 TestFrameCallback pre_render_callback(255, 0); // Changes luma from 255 to 0.
418
419 test::DirectTransport sender_transport, receiver_transport;
420
421 CreateCalls(Call::Config(&sender_transport),
422 Call::Config(&receiver_transport));
423
424 sender_transport.SetReceiver(receiver_call_->Receiver());
425 receiver_transport.SetReceiver(sender_call_->Receiver());
426
427 CreateTestConfigs();
428 send_config_.encoder = NULL;
429 send_config_.codec = sender_call_->GetVideoCodecs()[0];
430 send_config_.codec.width = kWidth;
431 send_config_.codec.height = kHeight;
432 send_config_.pre_encode_callback = &pre_encode_callback;
433 receive_config_.pre_render_callback = &pre_render_callback;
434 receive_config_.renderer = &renderer;
435
436 CreateStreams();
437 StartSending();
438
439 // Create frames that are smaller than the send width/height, this is done to
440 // check that the callbacks are done after processing video.
441 scoped_ptr<test::FrameGenerator> frame_generator(
442 test::FrameGenerator::Create(kWidth / 2, kHeight / 2));
443 send_stream_->Input()->PutFrame(frame_generator->NextFrame(), 0);
444
445 EXPECT_EQ(kEventSignaled, pre_encode_callback.Wait())
446 << "Timed out while waiting for pre-encode callback.";
447 EXPECT_EQ(kEventSignaled, pre_render_callback.Wait())
448 << "Timed out while waiting for pre-render callback.";
449 EXPECT_EQ(kEventSignaled, renderer.Wait())
450 << "Timed out while waiting for the frame to render.";
451
452 StopSending();
453
454 sender_transport.StopSending();
455 receiver_transport.StopSending();
456
457 DestroyStreams();
458}
459
pbos@webrtc.org6917e192013-09-19 14:22:12 +0000460class PliObserver : public test::RtpRtcpObserver, public VideoRenderer {
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000461 static const int kInverseDropProbability = 16;
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000462
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000463 public:
pbos@webrtc.org6917e192013-09-19 14:22:12 +0000464 explicit PliObserver(bool nack_enabled)
pbos@webrtc.orgc11148b2013-10-17 14:14:42 +0000465 : test::RtpRtcpObserver(kLongTimeoutMs),
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000466 rtp_header_parser_(RtpHeaderParser::Create()),
467 nack_enabled_(nack_enabled),
468 first_retransmitted_timestamp_(0),
469 last_send_timestamp_(0),
470 rendered_frame_(false),
471 received_pli_(false) {}
472
473 virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
474 RTPHeader header;
pbos@webrtc.orgd5f4c152013-08-19 16:35:36 +0000475 EXPECT_TRUE(
476 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000477
478 // Drop all NACK retransmissions. This is to force transmission of a PLI.
479 if (header.timestamp < last_send_timestamp_)
480 return DROP_PACKET;
481
482 if (received_pli_) {
483 if (first_retransmitted_timestamp_ == 0) {
484 first_retransmitted_timestamp_ = header.timestamp;
485 }
486 } else if (rendered_frame_ && rand() % kInverseDropProbability == 0) {
487 return DROP_PACKET;
488 }
489
490 last_send_timestamp_ = header.timestamp;
491 return SEND_PACKET;
492 }
493
494 virtual Action OnReceiveRtcp(const uint8_t* packet, size_t length) OVERRIDE {
495 RTCPUtility::RTCPParserV2 parser(packet, length, true);
496 EXPECT_TRUE(parser.IsValid());
497
498 for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
499 packet_type != RTCPUtility::kRtcpNotValidCode;
500 packet_type = parser.Iterate()) {
501 if (!nack_enabled_)
502 EXPECT_NE(packet_type, RTCPUtility::kRtcpRtpfbNackCode);
503
504 if (packet_type == RTCPUtility::kRtcpPsfbPliCode) {
505 received_pli_ = true;
506 break;
507 }
508 }
509 return SEND_PACKET;
510 }
511
pbos@webrtc.org6917e192013-09-19 14:22:12 +0000512 virtual void RenderFrame(const I420VideoFrame& video_frame,
513 int time_to_render_ms) OVERRIDE {
514 CriticalSectionScoped crit_(lock_.get());
515 if (first_retransmitted_timestamp_ != 0 &&
516 video_frame.timestamp() > first_retransmitted_timestamp_) {
517 EXPECT_TRUE(received_pli_);
518 observation_complete_->Set();
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000519 }
pbos@webrtc.org6917e192013-09-19 14:22:12 +0000520 rendered_frame_ = true;
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000521 }
522
523 private:
524 scoped_ptr<RtpHeaderParser> rtp_header_parser_;
525 bool nack_enabled_;
526
527 uint32_t first_retransmitted_timestamp_;
528 uint32_t last_send_timestamp_;
529
530 bool rendered_frame_;
531 bool received_pli_;
532};
533
pbos@webrtc.org6917e192013-09-19 14:22:12 +0000534void CallTest::ReceivesPliAndRecovers(int rtp_history_ms) {
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000535 PliObserver observer(rtp_history_ms > 0);
536
pbos@webrtc.orgde74b642013-10-02 13:36:09 +0000537 CreateCalls(Call::Config(observer.SendTransport()),
538 Call::Config(observer.ReceiveTransport()));
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000539
540 observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
541
542 CreateTestConfigs();
543 send_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
544 receive_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
pbos@webrtc.org6917e192013-09-19 14:22:12 +0000545 receive_config_.renderer = &observer;
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000546
547 CreateStreams();
548 CreateFrameGenerator();
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000549 StartSending();
550
551 // Wait() waits for an event triggered when Pli has been received and frames
552 // have been rendered afterwards.
553 EXPECT_EQ(kEventSignaled, observer.Wait());
554
555 StopSending();
556
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000557 observer.StopSending();
pbos@webrtc.org0181b5f2013-09-09 08:26:30 +0000558
559 DestroyStreams();
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000560}
561
pbos@webrtc.org2e246b42013-09-27 10:54:10 +0000562TEST_F(CallTest, ReceivesPliAndRecoversWithNack) {
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000563 ReceivesPliAndRecovers(1000);
564}
565
566// TODO(pbos): Enable this when 2250 is resolved.
pbos@webrtc.org2e246b42013-09-27 10:54:10 +0000567TEST_F(CallTest, DISABLED_ReceivesPliAndRecoversWithoutNack) {
pbos@webrtc.orge7f056e2013-08-19 16:09:34 +0000568 ReceivesPliAndRecovers(0);
569}
570
pbos@webrtc.org2e246b42013-09-27 10:54:10 +0000571TEST_F(CallTest, SurvivesIncomingRtpPacketsToDestroyedReceiveStream) {
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000572 class PacketInputObserver : public PacketReceiver {
573 public:
574 explicit PacketInputObserver(PacketReceiver* receiver)
575 : receiver_(receiver), delivered_packet_(EventWrapper::Create()) {}
576
pbos@webrtc.orgc11148b2013-10-17 14:14:42 +0000577 EventTypeWrapper Wait() {
578 return delivered_packet_->Wait(kDefaultTimeoutMs);
579 }
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000580
581 private:
582 virtual bool DeliverPacket(const uint8_t* packet, size_t length) {
583 if (RtpHeaderParser::IsRtcp(packet, static_cast<int>(length))) {
584 return receiver_->DeliverPacket(packet, length);
585 } else {
586 EXPECT_FALSE(receiver_->DeliverPacket(packet, length));
587 delivered_packet_->Set();
588 return false;
589 }
590 }
591
592 PacketReceiver* receiver_;
593 scoped_ptr<EventWrapper> delivered_packet_;
594 };
595
596 test::DirectTransport send_transport, receive_transport;
597
pbos@webrtc.orgde74b642013-10-02 13:36:09 +0000598 CreateCalls(Call::Config(&send_transport), Call::Config(&receive_transport));
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000599 PacketInputObserver input_observer(receiver_call_->Receiver());
600
601 send_transport.SetReceiver(&input_observer);
602 receive_transport.SetReceiver(sender_call_->Receiver());
603
604 CreateTestConfigs();
605
606 CreateStreams();
607 CreateFrameGenerator();
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000608 StartSending();
609
610 receiver_call_->DestroyReceiveStream(receive_stream_);
611 receive_stream_ = NULL;
612
613 // Wait() waits for a received packet.
614 EXPECT_EQ(kEventSignaled, input_observer.Wait());
615
616 StopSending();
617
618 DestroyStreams();
619
620 send_transport.StopSending();
621 receive_transport.StopSending();
622}
pbos@webrtc.orgb74b96f2013-10-01 11:33:24 +0000623
pbos@webrtc.orgc11148b2013-10-17 14:14:42 +0000624void CallTest::RespectsRtcpMode(newapi::RtcpMode rtcp_mode) {
625 static const int kRtpHistoryMs = 1000;
626 static const int kNumCompoundRtcpPacketsToObserve = 10;
627 class RtcpModeObserver : public test::RtpRtcpObserver {
628 public:
629 RtcpModeObserver(newapi::RtcpMode rtcp_mode)
630 : test::RtpRtcpObserver(kDefaultTimeoutMs),
631 rtcp_mode_(rtcp_mode),
632 sent_rtp_(0),
633 sent_rtcp_(0) {}
634
635 private:
636 virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
637 if (++sent_rtp_ % 3 == 0)
638 return DROP_PACKET;
639
640 return SEND_PACKET;
641 }
642
643 virtual Action OnReceiveRtcp(const uint8_t* packet,
644 size_t length) OVERRIDE {
645 ++sent_rtcp_;
646 RTCPUtility::RTCPParserV2 parser(packet, length, true);
647 EXPECT_TRUE(parser.IsValid());
648
649 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
650 bool has_report_block = false;
651 while (packet_type != RTCPUtility::kRtcpNotValidCode) {
652 EXPECT_NE(RTCPUtility::kRtcpSrCode, packet_type);
653 if (packet_type == RTCPUtility::kRtcpRrCode) {
654 has_report_block = true;
655 break;
656 }
657 packet_type = parser.Iterate();
658 }
659
660 switch (rtcp_mode_) {
661 case newapi::kRtcpCompound:
662 if (!has_report_block) {
663 ADD_FAILURE() << "Received RTCP packet without receiver report for "
664 "kRtcpCompound.";
665 observation_complete_->Set();
666 }
667
668 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
669 observation_complete_->Set();
670
671 break;
672 case newapi::kRtcpReducedSize:
673 if (!has_report_block)
674 observation_complete_->Set();
675 break;
676 }
677
678 return SEND_PACKET;
679 }
680
681 newapi::RtcpMode rtcp_mode_;
682 int sent_rtp_;
683 int sent_rtcp_;
684 } observer(rtcp_mode);
685
686 CreateCalls(Call::Config(observer.SendTransport()),
687 Call::Config(observer.ReceiveTransport()));
688
689 observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
690
691 CreateTestConfigs();
692 send_config_.rtp.nack.rtp_history_ms = kRtpHistoryMs;
693 receive_config_.rtp.nack.rtp_history_ms = kRtpHistoryMs;
694 receive_config_.rtp.rtcp_mode = rtcp_mode;
695
696 CreateStreams();
697 CreateFrameGenerator();
698 StartSending();
699
700 EXPECT_EQ(kEventSignaled, observer.Wait())
701 << (rtcp_mode == newapi::kRtcpCompound
702 ? "Timed out before observing enough compound packets."
703 : "Timed out before receiving a non-compound RTCP packet.");
704
705 StopSending();
706 observer.StopSending();
707 DestroyStreams();
708}
709
710TEST_F(CallTest, UsesRtcpCompoundMode) {
711 RespectsRtcpMode(newapi::kRtcpCompound);
712}
713
714TEST_F(CallTest, UsesRtcpReducedSizeMode) {
715 RespectsRtcpMode(newapi::kRtcpReducedSize);
716}
717
pbos@webrtc.orgb74b96f2013-10-01 11:33:24 +0000718// Test sets up a Call multiple senders with different resolutions and SSRCs.
719// Another is set up to receive all three of these with different renderers.
720// Each renderer verifies that it receives the expected resolution, and as soon
721// as every renderer has received a frame, the test finishes.
722TEST_F(CallTest, SendsAndReceivesMultipleStreams) {
723 static const size_t kNumStreams = 3;
724
725 class VideoOutputObserver : public VideoRenderer {
726 public:
727 VideoOutputObserver(int width, int height)
728 : width_(width), height_(height), done_(EventWrapper::Create()) {}
729
730 virtual void RenderFrame(const I420VideoFrame& video_frame,
731 int time_to_render_ms) OVERRIDE {
732 EXPECT_EQ(width_, video_frame.width());
733 EXPECT_EQ(height_, video_frame.height());
734 done_->Set();
735 }
736
pbos@webrtc.orgc11148b2013-10-17 14:14:42 +0000737 void Wait() { done_->Wait(kDefaultTimeoutMs); }
pbos@webrtc.orgb74b96f2013-10-01 11:33:24 +0000738
739 private:
740 int width_;
741 int height_;
742 scoped_ptr<EventWrapper> done_;
743 };
744
745 struct {
746 uint32_t ssrc;
747 int width;
748 int height;
749 } codec_settings[kNumStreams] = {{1, 640, 480}, {2, 320, 240}, {3, 240, 160}};
750
751 test::DirectTransport sender_transport, receiver_transport;
752 scoped_ptr<Call> sender_call(Call::Create(Call::Config(&sender_transport)));
753 scoped_ptr<Call> receiver_call(
754 Call::Create(Call::Config(&receiver_transport)));
755 sender_transport.SetReceiver(receiver_call->Receiver());
756 receiver_transport.SetReceiver(sender_call->Receiver());
757
758 VideoSendStream* send_streams[kNumStreams];
759 VideoReceiveStream* receive_streams[kNumStreams];
760
761 VideoOutputObserver* observers[kNumStreams];
762 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
763
764 for (size_t i = 0; i < kNumStreams; ++i) {
765 uint32_t ssrc = codec_settings[i].ssrc;
766 int width = codec_settings[i].width;
767 int height = codec_settings[i].height;
768 observers[i] = new VideoOutputObserver(width, height);
769
770 VideoReceiveStream::Config receive_config =
771 receiver_call->GetDefaultReceiveConfig();
772 receive_config.renderer = observers[i];
773 receive_config.rtp.ssrc = ssrc;
774 receive_streams[i] = receiver_call->CreateReceiveStream(receive_config);
775 receive_streams[i]->StartReceive();
776
777 VideoSendStream::Config send_config = sender_call->GetDefaultSendConfig();
778 send_config.rtp.ssrcs.push_back(ssrc);
779 send_config.codec.width = width;
780 send_config.codec.height = height;
781 send_streams[i] = sender_call->CreateSendStream(send_config);
782 send_streams[i]->StartSend();
783
784 frame_generators[i] = test::FrameGeneratorCapturer::Create(
785 send_streams[i]->Input(), width, height, 30, Clock::GetRealTimeClock());
786 frame_generators[i]->Start();
787 }
788
789 for (size_t i = 0; i < kNumStreams; ++i) {
790 observers[i]->Wait();
791 }
792
793 for (size_t i = 0; i < kNumStreams; ++i) {
794 frame_generators[i]->Stop();
795 delete frame_generators[i];
796 sender_call->DestroySendStream(send_streams[i]);
797 receiver_call->DestroyReceiveStream(receive_streams[i]);
798 delete observers[i];
799 }
800
801 sender_transport.StopSending();
802 receiver_transport.StopSending();
803}
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000804} // namespace webrtc