blob: 110ab86a7a212d1811da73ba70e8d71ea4cf938a [file] [log] [blame]
pbos@webrtc.org994d0b72014-06-27 08:47:52 +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.org994d0b72014-06-27 08:47:52 +000010#include <algorithm>
11#include <map>
12#include <sstream>
13#include <string>
14
15#include "testing/gtest/include/gtest/gtest.h"
16
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000017#include "webrtc/base/checks.h"
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +000018#include "webrtc/base/scoped_ptr.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000019#include "webrtc/call.h"
20#include "webrtc/frame_callback.h"
21#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
marpan@webrtc.org5b883172014-11-01 06:10:48 +000022#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
23#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
24#include "webrtc/modules/video_coding/main/interface/video_coding_defines.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000025#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
26#include "webrtc/system_wrappers/interface/event_wrapper.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000027#include "webrtc/system_wrappers/interface/sleep.h"
28#include "webrtc/test/call_test.h"
29#include "webrtc/test/direct_transport.h"
30#include "webrtc/test/encoder_settings.h"
31#include "webrtc/test/fake_audio_device.h"
32#include "webrtc/test/fake_decoder.h"
33#include "webrtc/test/fake_encoder.h"
34#include "webrtc/test/frame_generator.h"
35#include "webrtc/test/frame_generator_capturer.h"
36#include "webrtc/test/null_transport.h"
asapersson@webrtc.org37c05592015-01-28 13:58:27 +000037#include "webrtc/test/rtcp_packet_parser.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000038#include "webrtc/test/rtp_rtcp_observer.h"
39#include "webrtc/test/testsupport/fileutils.h"
andresp@webrtc.orgab071da2014-09-18 08:58:15 +000040#include "webrtc/test/testsupport/gtest_disable.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000041#include "webrtc/test/testsupport/perf_test.h"
42#include "webrtc/video/transport_adapter.h"
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +000043#include "webrtc/video_encoder.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000044
45namespace webrtc {
46
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000047static const unsigned long kSilenceTimeoutMs = 2000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000048
49class EndToEndTest : public test::CallTest {
50 public:
51 EndToEndTest() {}
52
53 virtual ~EndToEndTest() {
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000054 EXPECT_EQ(nullptr, send_stream_);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +000055 EXPECT_TRUE(receive_streams_.empty());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000056 }
57
58 protected:
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000059 class UnusedTransport : public newapi::Transport {
60 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000061 bool SendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000062 ADD_FAILURE() << "Unexpected RTP sent.";
63 return false;
64 }
65
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000066 bool SendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000067 ADD_FAILURE() << "Unexpected RTCP sent.";
68 return false;
69 }
70 };
71
andrew@webrtc.org8f27fcc2015-01-09 20:22:46 +000072 void DecodesRetransmittedFrame(bool retransmit_over_rtx);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000073 void ReceivesPliAndRecovers(int rtp_history_ms);
74 void RespectsRtcpMode(newapi::RtcpMode rtcp_mode);
75 void TestXrReceiverReferenceTimeReport(bool enable_rrtr);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +000076 void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +000077 void TestRtpStatePreservation(bool use_rtx);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +000078 void TestReceivedFecPacketsNotNacked(const FakeNetworkPipe::Config& config);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000079};
80
81TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
82 test::NullTransport transport;
83 CreateCalls(Call::Config(&transport), Call::Config(&transport));
84
85 CreateSendConfig(1);
86 CreateMatchingReceiveConfigs();
87
88 CreateStreams();
89
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +000090 receive_streams_[0]->Start();
91 receive_streams_[0]->Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000092
93 DestroyStreams();
94}
95
96TEST_F(EndToEndTest, ReceiverCanBeStoppedTwice) {
97 test::NullTransport transport;
98 CreateCalls(Call::Config(&transport), Call::Config(&transport));
99
100 CreateSendConfig(1);
101 CreateMatchingReceiveConfigs();
102
103 CreateStreams();
104
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000105 receive_streams_[0]->Stop();
106 receive_streams_[0]->Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000107
108 DestroyStreams();
109}
110
111TEST_F(EndToEndTest, RendersSingleDelayedFrame) {
112 static const int kWidth = 320;
113 static const int kHeight = 240;
114 // This constant is chosen to be higher than the timeout in the video_render
115 // module. This makes sure that frames aren't dropped if there are no other
116 // frames in the queue.
117 static const int kDelayRenderCallbackMs = 1000;
118
119 class Renderer : public VideoRenderer {
120 public:
121 Renderer() : event_(EventWrapper::Create()) {}
122
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000123 void RenderFrame(const I420VideoFrame& video_frame,
124 int /*time_to_render_ms*/) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000125 event_->Set();
126 }
127
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000128 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000129
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000130 EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
131
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000132 rtc::scoped_ptr<EventWrapper> event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000133 } renderer;
134
135 class TestFrameCallback : public I420FrameCallback {
136 public:
137 TestFrameCallback() : event_(EventWrapper::Create()) {}
138
139 EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
140
141 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000142 void FrameCallback(I420VideoFrame* frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000143 SleepMs(kDelayRenderCallbackMs);
144 event_->Set();
145 }
146
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000147 rtc::scoped_ptr<EventWrapper> event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000148 };
149
150 test::DirectTransport sender_transport, receiver_transport;
151
152 CreateCalls(Call::Config(&sender_transport),
153 Call::Config(&receiver_transport));
154
155 sender_transport.SetReceiver(receiver_call_->Receiver());
156 receiver_transport.SetReceiver(sender_call_->Receiver());
157
158 CreateSendConfig(1);
159 CreateMatchingReceiveConfigs();
160
161 TestFrameCallback pre_render_callback;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000162 receive_configs_[0].pre_render_callback = &pre_render_callback;
163 receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000164
165 CreateStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000166 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000167
168 // Create frames that are smaller than the send width/height, this is done to
169 // check that the callbacks are done after processing video.
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000170 rtc::scoped_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000171 test::FrameGenerator::CreateChromaGenerator(kWidth, kHeight));
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +0000172 send_stream_->Input()->IncomingCapturedFrame(*frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000173 EXPECT_EQ(kEventSignaled, pre_render_callback.Wait())
174 << "Timed out while waiting for pre-render callback.";
175 EXPECT_EQ(kEventSignaled, renderer.Wait())
176 << "Timed out while waiting for the frame to render.";
177
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000178 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000179
180 sender_transport.StopSending();
181 receiver_transport.StopSending();
182
183 DestroyStreams();
184}
185
186TEST_F(EndToEndTest, TransmitsFirstFrame) {
187 class Renderer : public VideoRenderer {
188 public:
189 Renderer() : event_(EventWrapper::Create()) {}
190
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000191 void RenderFrame(const I420VideoFrame& video_frame,
192 int /*time_to_render_ms*/) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000193 event_->Set();
194 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000195 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000196
197 EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
198
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000199 rtc::scoped_ptr<EventWrapper> event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000200 } renderer;
201
202 test::DirectTransport sender_transport, receiver_transport;
203
204 CreateCalls(Call::Config(&sender_transport),
205 Call::Config(&receiver_transport));
206
207 sender_transport.SetReceiver(receiver_call_->Receiver());
208 receiver_transport.SetReceiver(sender_call_->Receiver());
209
210 CreateSendConfig(1);
211 CreateMatchingReceiveConfigs();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000212 receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000213
214 CreateStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000215 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000216
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000217 rtc::scoped_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000218 test::FrameGenerator::CreateChromaGenerator(
219 encoder_config_.streams[0].width, encoder_config_.streams[0].height));
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +0000220 send_stream_->Input()->IncomingCapturedFrame(*frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000221
222 EXPECT_EQ(kEventSignaled, renderer.Wait())
223 << "Timed out while waiting for the frame to render.";
224
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000225 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000226
227 sender_transport.StopSending();
228 receiver_transport.StopSending();
229
230 DestroyStreams();
231}
232
marpan@webrtc.org5f1e2e42014-11-06 02:02:28 +0000233TEST_F(EndToEndTest, SendsAndReceivesVP9) {
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000234 class VP9Observer : public test::EndToEndTest, public VideoRenderer {
235 public:
236 VP9Observer()
237 : EndToEndTest(2 * kDefaultTimeoutMs),
238 encoder_(VideoEncoder::Create(VideoEncoder::kVp9)),
239 decoder_(VP9Decoder::Create()),
240 frame_counter_(0) {}
241
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000242 void PerformTest() override {
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000243 EXPECT_EQ(kEventSignaled, Wait())
244 << "Timed out while waiting for enough frames to be decoded.";
245 }
246
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000247 void ModifyConfigs(VideoSendStream::Config* send_config,
248 std::vector<VideoReceiveStream::Config>* receive_configs,
249 VideoEncoderConfig* encoder_config) override {
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000250 send_config->encoder_settings.encoder = encoder_.get();
251 send_config->encoder_settings.payload_name = "VP9";
252 send_config->encoder_settings.payload_type = VCM_VP9_PAYLOAD_TYPE;
253 encoder_config->streams[0].min_bitrate_bps = 50000;
254 encoder_config->streams[0].target_bitrate_bps =
255 encoder_config->streams[0].max_bitrate_bps = 2000000;
256
257 (*receive_configs)[0].renderer = this;
258 (*receive_configs)[0].decoders.resize(1);
259 (*receive_configs)[0].decoders[0].payload_type =
260 send_config->encoder_settings.payload_type;
261 (*receive_configs)[0].decoders[0].payload_name =
262 send_config->encoder_settings.payload_name;
263 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
264 }
265
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000266 void RenderFrame(const I420VideoFrame& video_frame,
267 int time_to_render_ms) override {
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000268 const int kRequiredFrames = 500;
269 if (++frame_counter_ == kRequiredFrames)
270 observation_complete_->Set();
271 }
272
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000273 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000274
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000275 private:
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000276 rtc::scoped_ptr<webrtc::VideoEncoder> encoder_;
277 rtc::scoped_ptr<webrtc::VideoDecoder> decoder_;
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000278 int frame_counter_;
279 } test;
280
281 RunBaseTest(&test);
282}
283
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000284TEST_F(EndToEndTest, SendsAndReceivesH264) {
285 class H264Observer : public test::EndToEndTest, public VideoRenderer {
286 public:
287 H264Observer()
288 : EndToEndTest(2 * kDefaultTimeoutMs),
289 fake_encoder_(Clock::GetRealTimeClock()),
290 frame_counter_(0) {}
291
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000292 void PerformTest() override {
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000293 EXPECT_EQ(kEventSignaled, Wait())
294 << "Timed out while waiting for enough frames to be decoded.";
295 }
296
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000297 void ModifyConfigs(VideoSendStream::Config* send_config,
298 std::vector<VideoReceiveStream::Config>* receive_configs,
299 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org8278c072015-02-23 11:11:49 +0000300 send_config->rtp.nack.rtp_history_ms =
301 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000302 send_config->encoder_settings.encoder = &fake_encoder_;
303 send_config->encoder_settings.payload_name = "H264";
304 send_config->encoder_settings.payload_type = kFakeSendPayloadType;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000305 encoder_config->streams[0].min_bitrate_bps = 50000;
306 encoder_config->streams[0].target_bitrate_bps =
307 encoder_config->streams[0].max_bitrate_bps = 2000000;
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000308
309 (*receive_configs)[0].renderer = this;
pbos@webrtc.org776e6f22014-10-29 15:28:39 +0000310 (*receive_configs)[0].decoders.resize(1);
311 (*receive_configs)[0].decoders[0].payload_type =
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000312 send_config->encoder_settings.payload_type;
pbos@webrtc.org776e6f22014-10-29 15:28:39 +0000313 (*receive_configs)[0].decoders[0].payload_name =
314 send_config->encoder_settings.payload_name;
315 (*receive_configs)[0].decoders[0].decoder = &fake_decoder_;
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000316 }
317
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000318 void RenderFrame(const I420VideoFrame& video_frame,
319 int time_to_render_ms) override {
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000320 const int kRequiredFrames = 500;
321 if (++frame_counter_ == kRequiredFrames)
322 observation_complete_->Set();
323 }
324
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000325 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000326
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000327 private:
328 test::FakeH264Decoder fake_decoder_;
329 test::FakeH264Encoder fake_encoder_;
330 int frame_counter_;
331 } test;
332
333 RunBaseTest(&test);
334}
335
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000336TEST_F(EndToEndTest, ReceiverUsesLocalSsrc) {
337 class SyncRtcpObserver : public test::EndToEndTest {
338 public:
339 SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {}
340
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000341 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000342 RTCPUtility::RTCPParserV2 parser(packet, length, true);
343 EXPECT_TRUE(parser.IsValid());
344 uint32_t ssrc = 0;
345 ssrc |= static_cast<uint32_t>(packet[4]) << 24;
346 ssrc |= static_cast<uint32_t>(packet[5]) << 16;
347 ssrc |= static_cast<uint32_t>(packet[6]) << 8;
348 ssrc |= static_cast<uint32_t>(packet[7]) << 0;
349 EXPECT_EQ(kReceiverLocalSsrc, ssrc);
350 observation_complete_->Set();
351
352 return SEND_PACKET;
353 }
354
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000355 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000356 EXPECT_EQ(kEventSignaled, Wait())
357 << "Timed out while waiting for a receiver RTCP packet to be sent.";
358 }
359 } test;
360
361 RunBaseTest(&test);
362}
363
364TEST_F(EndToEndTest, ReceivesAndRetransmitsNack) {
365 static const int kNumberOfNacksToObserve = 2;
366 static const int kLossBurstSize = 2;
367 static const int kPacketsBetweenLossBursts = 9;
368 class NackObserver : public test::EndToEndTest {
369 public:
370 NackObserver()
371 : EndToEndTest(kLongTimeoutMs),
372 rtp_parser_(RtpHeaderParser::Create()),
373 sent_rtp_packets_(0),
374 packets_left_to_drop_(0),
375 nacks_left_(kNumberOfNacksToObserve) {}
376
377 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000378 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000379 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000380 EXPECT_TRUE(rtp_parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000381
382 // Never drop retransmitted packets.
383 if (dropped_packets_.find(header.sequenceNumber) !=
384 dropped_packets_.end()) {
385 retransmitted_packets_.insert(header.sequenceNumber);
386 if (nacks_left_ == 0 &&
387 retransmitted_packets_.size() == dropped_packets_.size()) {
388 observation_complete_->Set();
389 }
390 return SEND_PACKET;
391 }
392
393 ++sent_rtp_packets_;
394
395 // Enough NACKs received, stop dropping packets.
396 if (nacks_left_ == 0)
397 return SEND_PACKET;
398
399 // Check if it's time for a new loss burst.
400 if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
401 packets_left_to_drop_ = kLossBurstSize;
402
403 if (packets_left_to_drop_ > 0) {
404 --packets_left_to_drop_;
405 dropped_packets_.insert(header.sequenceNumber);
406 return DROP_PACKET;
407 }
408
409 return SEND_PACKET;
410 }
411
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000412 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000413 RTCPUtility::RTCPParserV2 parser(packet, length, true);
414 EXPECT_TRUE(parser.IsValid());
415
416 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
417 while (packet_type != RTCPUtility::kRtcpNotValidCode) {
418 if (packet_type == RTCPUtility::kRtcpRtpfbNackCode) {
419 --nacks_left_;
420 break;
421 }
422 packet_type = parser.Iterate();
423 }
424 return SEND_PACKET;
425 }
426
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000427 void ModifyConfigs(VideoSendStream::Config* send_config,
428 std::vector<VideoReceiveStream::Config>* receive_configs,
429 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000430 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000431 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000432 }
433
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000434 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000435 EXPECT_EQ(kEventSignaled, Wait())
436 << "Timed out waiting for packets to be NACKed, retransmitted and "
437 "rendered.";
438 }
439
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000440 rtc::scoped_ptr<RtpHeaderParser> rtp_parser_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000441 std::set<uint16_t> dropped_packets_;
442 std::set<uint16_t> retransmitted_packets_;
443 uint64_t sent_rtp_packets_;
444 int packets_left_to_drop_;
445 int nacks_left_;
446 } test;
447
448 RunBaseTest(&test);
449}
450
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000451TEST_F(EndToEndTest, CanReceiveFec) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000452 class FecRenderObserver : public test::EndToEndTest, public VideoRenderer {
453 public:
454 FecRenderObserver()
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000455 : EndToEndTest(kDefaultTimeoutMs), state_(kFirstPacket) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000456
457 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000458 Action OnSendRtp(const uint8_t* packet, size_t length) override
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000459 EXCLUSIVE_LOCKS_REQUIRED(crit_) {
460 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000461 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000462
463 EXPECT_EQ(kRedPayloadType, header.payloadType);
464 int encapsulated_payload_type =
465 static_cast<int>(packet[header.headerLength]);
466 if (encapsulated_payload_type != kFakeSendPayloadType)
467 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
468
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000469 if (protected_sequence_numbers_.count(header.sequenceNumber) != 0) {
470 // Retransmitted packet, should not count.
471 protected_sequence_numbers_.erase(header.sequenceNumber);
472 EXPECT_GT(protected_timestamps_.count(header.timestamp), 0u);
473 protected_timestamps_.erase(header.timestamp);
474 return SEND_PACKET;
475 }
476
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000477 switch (state_) {
478 case kFirstPacket:
479 state_ = kDropEveryOtherPacketUntilFec;
480 break;
481 case kDropEveryOtherPacketUntilFec:
482 if (encapsulated_payload_type == kUlpfecPayloadType) {
483 state_ = kDropNextMediaPacket;
484 return SEND_PACKET;
485 }
486 if (header.sequenceNumber % 2 == 0)
487 return DROP_PACKET;
488 break;
489 case kDropNextMediaPacket:
490 if (encapsulated_payload_type == kFakeSendPayloadType) {
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000491 protected_sequence_numbers_.insert(header.sequenceNumber);
492 protected_timestamps_.insert(header.timestamp);
493 state_ = kDropEveryOtherPacketUntilFec;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000494 return DROP_PACKET;
495 }
496 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000497 }
498
499 return SEND_PACKET;
500 }
501
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000502 void RenderFrame(const I420VideoFrame& video_frame,
503 int time_to_render_ms) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000504 CriticalSectionScoped lock(crit_.get());
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000505 // Rendering frame with timestamp of packet that was dropped -> FEC
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000506 // protection worked.
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000507 if (protected_timestamps_.count(video_frame.timestamp()) != 0)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000508 observation_complete_->Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000509 }
510
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000511 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000512
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000513 enum {
514 kFirstPacket,
515 kDropEveryOtherPacketUntilFec,
516 kDropNextMediaPacket,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000517 } state_;
518
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000519 void ModifyConfigs(VideoSendStream::Config* send_config,
520 std::vector<VideoReceiveStream::Config>* receive_configs,
521 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000522 // TODO(pbos): Run this test with combined NACK/FEC enabled as well.
523 // int rtp_history_ms = 1000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000524 // (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000525 // send_config->rtp.nack.rtp_history_ms = rtp_history_ms;
526 send_config->rtp.fec.red_payload_type = kRedPayloadType;
527 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
528
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000529 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
530 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
531 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000532 }
533
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000534 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000535 EXPECT_EQ(kEventSignaled, Wait())
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000536 << "Timed out waiting for dropped frames frames to be rendered.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000537 }
538
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000539 std::set<uint32_t> protected_sequence_numbers_ GUARDED_BY(crit_);
540 std::set<uint32_t> protected_timestamps_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000541 } test;
542
543 RunBaseTest(&test);
544}
545
Henrik Kjellanderdb313b62015-04-02 08:45:41 +0200546// Flacky on all platforms. See webrtc:4328.
547TEST_F(EndToEndTest, DISABLED_ReceivedFecPacketsNotNacked) {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000548 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
549 // Configure some network delay.
550 const int kNetworkDelayMs = 50;
551 FakeNetworkPipe::Config config;
552 config.queue_delay_ms = kNetworkDelayMs;
553 TestReceivedFecPacketsNotNacked(config);
554}
555
556void EndToEndTest::TestReceivedFecPacketsNotNacked(
557 const FakeNetworkPipe::Config& config) {
558 class FecNackObserver : public test::EndToEndTest {
559 public:
560 explicit FecNackObserver(const FakeNetworkPipe::Config& config)
561 : EndToEndTest(kDefaultTimeoutMs, config),
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000562 state_(kFirstPacket),
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000563 fec_sequence_number_(0),
564 has_last_sequence_number_(false),
565 last_sequence_number_(0) {}
566
567 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000568 Action OnSendRtp(const uint8_t* packet, size_t length) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000569 RTPHeader header;
570 EXPECT_TRUE(parser_->Parse(packet, length, &header));
571 EXPECT_EQ(kRedPayloadType, header.payloadType);
572
573 int encapsulated_payload_type =
574 static_cast<int>(packet[header.headerLength]);
575 if (encapsulated_payload_type != kFakeSendPayloadType)
576 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
577
578 if (has_last_sequence_number_ &&
579 !IsNewerSequenceNumber(header.sequenceNumber,
580 last_sequence_number_)) {
581 // Drop retransmitted packets.
582 return DROP_PACKET;
583 }
584 last_sequence_number_ = header.sequenceNumber;
585 has_last_sequence_number_ = true;
586
587 bool fec_packet = encapsulated_payload_type == kUlpfecPayloadType;
588 switch (state_) {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000589 case kFirstPacket:
590 state_ = kDropEveryOtherPacketUntilFec;
591 break;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000592 case kDropEveryOtherPacketUntilFec:
593 if (fec_packet) {
594 state_ = kDropAllMediaPacketsUntilFec;
595 } else if (header.sequenceNumber % 2 == 0) {
596 return DROP_PACKET;
597 }
598 break;
599 case kDropAllMediaPacketsUntilFec:
600 if (!fec_packet)
601 return DROP_PACKET;
602 fec_sequence_number_ = header.sequenceNumber;
603 state_ = kVerifyFecPacketNotInNackList;
604 break;
605 case kVerifyFecPacketNotInNackList:
606 // Continue to drop packets. Make sure no frame can be decoded.
607 if (fec_packet || header.sequenceNumber % 2 == 0)
608 return DROP_PACKET;
609 break;
610 }
611 return SEND_PACKET;
612 }
613
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000614 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000615 if (state_ == kVerifyFecPacketNotInNackList) {
616 test::RtcpPacketParser rtcp_parser;
617 rtcp_parser.Parse(packet, length);
618 std::vector<uint16_t> nacks = rtcp_parser.nack_item()->last_nack_list();
619 if (!nacks.empty() &&
620 IsNewerSequenceNumber(nacks.back(), fec_sequence_number_)) {
621 EXPECT_TRUE(std::find(
622 nacks.begin(), nacks.end(), fec_sequence_number_) == nacks.end());
623 observation_complete_->Set();
624 }
625 }
626 return SEND_PACKET;
627 }
628
Stefan Holmere5904162015-03-26 11:11:06 +0100629 // TODO(holmer): Investigate why we don't send FEC packets when the bitrate
630 // is 10 kbps.
631 Call::Config GetSenderCallConfig() override {
632 Call::Config config(SendTransport());
633 const int kMinBitrateBps = 30000;
634 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
635 return config;
636 }
637
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000638 void ModifyConfigs(VideoSendStream::Config* send_config,
639 std::vector<VideoReceiveStream::Config>* receive_configs,
640 VideoEncoderConfig* encoder_config) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000641 // Configure hybrid NACK/FEC.
642 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
643 send_config->rtp.fec.red_payload_type = kRedPayloadType;
644 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
645 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
646 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
647 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
648 }
649
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000650 void PerformTest() override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000651 EXPECT_EQ(kEventSignaled, Wait())
652 << "Timed out while waiting for FEC packets to be received.";
653 }
654
655 enum {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000656 kFirstPacket,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000657 kDropEveryOtherPacketUntilFec,
658 kDropAllMediaPacketsUntilFec,
659 kVerifyFecPacketNotInNackList,
660 } state_;
661
662 uint16_t fec_sequence_number_;
663 bool has_last_sequence_number_;
664 uint16_t last_sequence_number_;
665 } test(config);
666
667 RunBaseTest(&test);
668}
669
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000670// This test drops second RTP packet with a marker bit set, makes sure it's
671// retransmitted and renders. Retransmission SSRCs are also checked.
andrew@webrtc.org8f27fcc2015-01-09 20:22:46 +0000672void EndToEndTest::DecodesRetransmittedFrame(bool retransmit_over_rtx) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000673 static const int kDroppedFrameNumber = 2;
674 class RetransmissionObserver : public test::EndToEndTest,
675 public I420FrameCallback {
676 public:
andrew@webrtc.org8f27fcc2015-01-09 20:22:46 +0000677 explicit RetransmissionObserver(bool expect_rtx)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000678 : EndToEndTest(kDefaultTimeoutMs),
andrew@webrtc.org8f27fcc2015-01-09 20:22:46 +0000679 retransmission_ssrc_(expect_rtx ? kSendRtxSsrcs[0] : kSendSsrcs[0]),
680 retransmission_payload_type_(expect_rtx ? kSendRtxPayloadType
681 : kFakeSendPayloadType),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000682 marker_bits_observed_(0),
683 retransmitted_timestamp_(0),
684 frame_retransmitted_(false) {}
685
686 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000687 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000688 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000689 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000690
691 if (header.timestamp == retransmitted_timestamp_) {
692 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
693 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
694 frame_retransmitted_ = true;
695 return SEND_PACKET;
696 }
697
698 EXPECT_EQ(kSendSsrcs[0], header.ssrc);
andrew@webrtc.org8f27fcc2015-01-09 20:22:46 +0000699 EXPECT_EQ(kFakeSendPayloadType, header.payloadType);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000700
701 // Found the second frame's final packet, drop this and expect a
702 // retransmission.
703 if (header.markerBit && ++marker_bits_observed_ == kDroppedFrameNumber) {
704 retransmitted_timestamp_ = header.timestamp;
705 return DROP_PACKET;
706 }
707
708 return SEND_PACKET;
709 }
710
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000711 void FrameCallback(I420VideoFrame* frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000712 CriticalSectionScoped lock(crit_.get());
713 if (frame->timestamp() == retransmitted_timestamp_) {
714 EXPECT_TRUE(frame_retransmitted_);
715 observation_complete_->Set();
716 }
717 }
718
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000719 void ModifyConfigs(VideoSendStream::Config* send_config,
720 std::vector<VideoReceiveStream::Config>* receive_configs,
721 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000722 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000723 (*receive_configs)[0].pre_render_callback = this;
724 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000725 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
726 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000727 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
andrew@webrtc.org8f27fcc2015-01-09 20:22:46 +0000728 (*receive_configs)[0].rtp.rtx[kSendRtxPayloadType].ssrc =
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000729 kSendRtxSsrcs[0];
andrew@webrtc.org8f27fcc2015-01-09 20:22:46 +0000730 (*receive_configs)[0].rtp.rtx[kSendRtxPayloadType].payload_type =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000731 kSendRtxPayloadType;
732 }
733 }
734
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000735 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000736 EXPECT_EQ(kEventSignaled, Wait())
737 << "Timed out while waiting for retransmission to render.";
738 }
739
740 const uint32_t retransmission_ssrc_;
741 const int retransmission_payload_type_;
742 int marker_bits_observed_;
743 uint32_t retransmitted_timestamp_;
744 bool frame_retransmitted_;
andrew@webrtc.org8f27fcc2015-01-09 20:22:46 +0000745 } test(retransmit_over_rtx);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000746
747 RunBaseTest(&test);
748}
749
750TEST_F(EndToEndTest, DecodesRetransmittedFrame) {
andrew@webrtc.org8f27fcc2015-01-09 20:22:46 +0000751 DecodesRetransmittedFrame(false);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000752}
753
754TEST_F(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
andrew@webrtc.org8f27fcc2015-01-09 20:22:46 +0000755 DecodesRetransmittedFrame(true);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000756}
757
andresp@webrtc.org02686112014-09-19 08:24:19 +0000758TEST_F(EndToEndTest, UsesFrameCallbacks) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000759 static const int kWidth = 320;
760 static const int kHeight = 240;
761
762 class Renderer : public VideoRenderer {
763 public:
764 Renderer() : event_(EventWrapper::Create()) {}
765
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000766 void RenderFrame(const I420VideoFrame& video_frame,
767 int /*time_to_render_ms*/) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000768 EXPECT_EQ(0, *video_frame.buffer(kYPlane))
769 << "Rendered frame should have zero luma which is applied by the "
770 "pre-render callback.";
771 event_->Set();
772 }
773
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000774 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000775
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000776 EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000777 rtc::scoped_ptr<EventWrapper> event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000778 } renderer;
779
780 class TestFrameCallback : public I420FrameCallback {
781 public:
782 TestFrameCallback(int expected_luma_byte, int next_luma_byte)
783 : event_(EventWrapper::Create()),
784 expected_luma_byte_(expected_luma_byte),
785 next_luma_byte_(next_luma_byte) {}
786
787 EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
788
789 private:
790 virtual void FrameCallback(I420VideoFrame* frame) {
791 EXPECT_EQ(kWidth, frame->width())
792 << "Width not as expected, callback done before resize?";
793 EXPECT_EQ(kHeight, frame->height())
794 << "Height not as expected, callback done before resize?";
795
796 // Previous luma specified, observed luma should be fairly close.
797 if (expected_luma_byte_ != -1) {
798 EXPECT_NEAR(expected_luma_byte_, *frame->buffer(kYPlane), 10);
799 }
800
801 memset(frame->buffer(kYPlane),
802 next_luma_byte_,
803 frame->allocated_size(kYPlane));
804
805 event_->Set();
806 }
807
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000808 rtc::scoped_ptr<EventWrapper> event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000809 int expected_luma_byte_;
810 int next_luma_byte_;
811 };
812
813 TestFrameCallback pre_encode_callback(-1, 255); // Changes luma to 255.
814 TestFrameCallback pre_render_callback(255, 0); // Changes luma from 255 to 0.
815
816 test::DirectTransport sender_transport, receiver_transport;
817
818 CreateCalls(Call::Config(&sender_transport),
819 Call::Config(&receiver_transport));
820
821 sender_transport.SetReceiver(receiver_call_->Receiver());
822 receiver_transport.SetReceiver(sender_call_->Receiver());
823
824 CreateSendConfig(1);
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000825 rtc::scoped_ptr<VideoEncoder> encoder(
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +0000826 VideoEncoder::Create(VideoEncoder::kVp8));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000827 send_config_.encoder_settings.encoder = encoder.get();
828 send_config_.encoder_settings.payload_name = "VP8";
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000829 ASSERT_EQ(1u, encoder_config_.streams.size()) << "Test setup error.";
830 encoder_config_.streams[0].width = kWidth;
831 encoder_config_.streams[0].height = kHeight;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000832 send_config_.pre_encode_callback = &pre_encode_callback;
833
834 CreateMatchingReceiveConfigs();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000835 receive_configs_[0].pre_render_callback = &pre_render_callback;
836 receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000837
838 CreateStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000839 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000840
841 // Create frames that are smaller than the send width/height, this is done to
842 // check that the callbacks are done after processing video.
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000843 rtc::scoped_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000844 test::FrameGenerator::CreateChromaGenerator(kWidth / 2, kHeight / 2));
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +0000845 send_stream_->Input()->IncomingCapturedFrame(*frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000846
847 EXPECT_EQ(kEventSignaled, pre_encode_callback.Wait())
848 << "Timed out while waiting for pre-encode callback.";
849 EXPECT_EQ(kEventSignaled, pre_render_callback.Wait())
850 << "Timed out while waiting for pre-render callback.";
851 EXPECT_EQ(kEventSignaled, renderer.Wait())
852 << "Timed out while waiting for the frame to render.";
853
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000854 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000855
856 sender_transport.StopSending();
857 receiver_transport.StopSending();
858
859 DestroyStreams();
860}
861
862void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
863 static const int kPacketsToDrop = 1;
864
865 class PliObserver : public test::EndToEndTest, public VideoRenderer {
866 public:
867 explicit PliObserver(int rtp_history_ms)
868 : EndToEndTest(kLongTimeoutMs),
869 rtp_history_ms_(rtp_history_ms),
870 nack_enabled_(rtp_history_ms > 0),
871 highest_dropped_timestamp_(0),
872 frames_to_drop_(0),
873 received_pli_(false) {}
874
875 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000876 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000877 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000878 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000879
880 // Drop all retransmitted packets to force a PLI.
881 if (header.timestamp <= highest_dropped_timestamp_)
882 return DROP_PACKET;
883
884 if (frames_to_drop_ > 0) {
885 highest_dropped_timestamp_ = header.timestamp;
886 --frames_to_drop_;
887 return DROP_PACKET;
888 }
889
890 return SEND_PACKET;
891 }
892
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000893 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000894 RTCPUtility::RTCPParserV2 parser(packet, length, true);
895 EXPECT_TRUE(parser.IsValid());
896
897 for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
898 packet_type != RTCPUtility::kRtcpNotValidCode;
899 packet_type = parser.Iterate()) {
900 if (!nack_enabled_)
901 EXPECT_NE(packet_type, RTCPUtility::kRtcpRtpfbNackCode);
902
903 if (packet_type == RTCPUtility::kRtcpPsfbPliCode) {
904 received_pli_ = true;
905 break;
906 }
907 }
908 return SEND_PACKET;
909 }
910
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000911 void RenderFrame(const I420VideoFrame& video_frame,
912 int time_to_render_ms) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000913 CriticalSectionScoped lock(crit_.get());
914 if (received_pli_ &&
915 video_frame.timestamp() > highest_dropped_timestamp_) {
916 observation_complete_->Set();
917 }
918 if (!received_pli_)
919 frames_to_drop_ = kPacketsToDrop;
920 }
921
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000922 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000923
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000924 void ModifyConfigs(VideoSendStream::Config* send_config,
925 std::vector<VideoReceiveStream::Config>* receive_configs,
926 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000927 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000928 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
929 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000930 }
931
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000932 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000933 EXPECT_EQ(kEventSignaled, Wait()) << "Timed out waiting for PLI to be "
934 "received and a frame to be "
935 "rendered afterwards.";
936 }
937
938 int rtp_history_ms_;
939 bool nack_enabled_;
940 uint32_t highest_dropped_timestamp_;
941 int frames_to_drop_;
942 bool received_pli_;
943 } test(rtp_history_ms);
944
945 RunBaseTest(&test);
946}
947
948TEST_F(EndToEndTest, ReceivesPliAndRecoversWithNack) {
949 ReceivesPliAndRecovers(1000);
950}
951
952// TODO(pbos): Enable this when 2250 is resolved.
953TEST_F(EndToEndTest, DISABLED_ReceivesPliAndRecoversWithoutNack) {
954 ReceivesPliAndRecovers(0);
955}
956
957TEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
958 class PacketInputObserver : public PacketReceiver {
959 public:
960 explicit PacketInputObserver(PacketReceiver* receiver)
961 : receiver_(receiver), delivered_packet_(EventWrapper::Create()) {}
962
963 EventTypeWrapper Wait() {
964 return delivered_packet_->Wait(kDefaultTimeoutMs);
965 }
966
967 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000968 DeliveryStatus DeliverPacket(const uint8_t* packet,
969 size_t length) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000970 if (RtpHeaderParser::IsRtcp(packet, length)) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000971 return receiver_->DeliverPacket(packet, length);
972 } else {
973 DeliveryStatus delivery_status =
974 receiver_->DeliverPacket(packet, length);
975 EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
976 delivered_packet_->Set();
977 return delivery_status;
978 }
979 }
980
981 PacketReceiver* receiver_;
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000982 rtc::scoped_ptr<EventWrapper> delivered_packet_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000983 };
984
985 test::DirectTransport send_transport, receive_transport;
986
987 CreateCalls(Call::Config(&send_transport), Call::Config(&receive_transport));
988 PacketInputObserver input_observer(receiver_call_->Receiver());
989
990 send_transport.SetReceiver(&input_observer);
991 receive_transport.SetReceiver(sender_call_->Receiver());
992
993 CreateSendConfig(1);
994 CreateMatchingReceiveConfigs();
995
996 CreateStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000997 CreateFrameGeneratorCapturer();
998 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000999
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001000 receiver_call_->DestroyVideoReceiveStream(receive_streams_[0]);
1001 receive_streams_.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001002
1003 // Wait() waits for a received packet.
1004 EXPECT_EQ(kEventSignaled, input_observer.Wait());
1005
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001006 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001007
1008 DestroyStreams();
1009
1010 send_transport.StopSending();
1011 receive_transport.StopSending();
1012}
1013
1014void EndToEndTest::RespectsRtcpMode(newapi::RtcpMode rtcp_mode) {
1015 static const int kNumCompoundRtcpPacketsToObserve = 10;
1016 class RtcpModeObserver : public test::EndToEndTest {
1017 public:
1018 explicit RtcpModeObserver(newapi::RtcpMode rtcp_mode)
1019 : EndToEndTest(kDefaultTimeoutMs),
1020 rtcp_mode_(rtcp_mode),
1021 sent_rtp_(0),
1022 sent_rtcp_(0) {}
1023
1024 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001025 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001026 if (++sent_rtp_ % 3 == 0)
1027 return DROP_PACKET;
1028
1029 return SEND_PACKET;
1030 }
1031
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001032 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001033 ++sent_rtcp_;
1034 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1035 EXPECT_TRUE(parser.IsValid());
1036
1037 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1038 bool has_report_block = false;
1039 while (packet_type != RTCPUtility::kRtcpNotValidCode) {
1040 EXPECT_NE(RTCPUtility::kRtcpSrCode, packet_type);
1041 if (packet_type == RTCPUtility::kRtcpRrCode) {
1042 has_report_block = true;
1043 break;
1044 }
1045 packet_type = parser.Iterate();
1046 }
1047
1048 switch (rtcp_mode_) {
1049 case newapi::kRtcpCompound:
1050 if (!has_report_block) {
1051 ADD_FAILURE() << "Received RTCP packet without receiver report for "
1052 "kRtcpCompound.";
1053 observation_complete_->Set();
1054 }
1055
1056 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
1057 observation_complete_->Set();
1058
1059 break;
1060 case newapi::kRtcpReducedSize:
1061 if (!has_report_block)
1062 observation_complete_->Set();
1063 break;
1064 }
1065
1066 return SEND_PACKET;
1067 }
1068
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001069 void ModifyConfigs(VideoSendStream::Config* send_config,
1070 std::vector<VideoReceiveStream::Config>* receive_configs,
1071 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001072 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001073 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1074 (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001075 }
1076
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001077 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001078 EXPECT_EQ(kEventSignaled, Wait())
1079 << (rtcp_mode_ == newapi::kRtcpCompound
1080 ? "Timed out before observing enough compound packets."
1081 : "Timed out before receiving a non-compound RTCP packet.");
1082 }
1083
1084 newapi::RtcpMode rtcp_mode_;
1085 int sent_rtp_;
1086 int sent_rtcp_;
1087 } test(rtcp_mode);
1088
1089 RunBaseTest(&test);
1090}
1091
1092TEST_F(EndToEndTest, UsesRtcpCompoundMode) {
1093 RespectsRtcpMode(newapi::kRtcpCompound);
1094}
1095
1096TEST_F(EndToEndTest, UsesRtcpReducedSizeMode) {
1097 RespectsRtcpMode(newapi::kRtcpReducedSize);
1098}
1099
1100// Test sets up a Call multiple senders with different resolutions and SSRCs.
1101// Another is set up to receive all three of these with different renderers.
1102// Each renderer verifies that it receives the expected resolution, and as soon
1103// as every renderer has received a frame, the test finishes.
andresp@webrtc.org02686112014-09-19 08:24:19 +00001104TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001105 static const size_t kNumStreams = 3;
1106
1107 class VideoOutputObserver : public VideoRenderer {
1108 public:
1109 VideoOutputObserver(test::FrameGeneratorCapturer** capturer,
1110 int width,
1111 int height)
1112 : capturer_(capturer),
1113 width_(width),
1114 height_(height),
1115 done_(EventWrapper::Create()) {}
1116
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001117 void RenderFrame(const I420VideoFrame& video_frame,
1118 int time_to_render_ms) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001119 EXPECT_EQ(width_, video_frame.width());
1120 EXPECT_EQ(height_, video_frame.height());
1121 (*capturer_)->Stop();
1122 done_->Set();
1123 }
1124
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001125 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00001126
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001127 EventTypeWrapper Wait() { return done_->Wait(kDefaultTimeoutMs); }
1128
1129 private:
1130 test::FrameGeneratorCapturer** capturer_;
1131 int width_;
1132 int height_;
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001133 rtc::scoped_ptr<EventWrapper> done_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001134 };
1135
1136 struct {
1137 uint32_t ssrc;
1138 int width;
1139 int height;
1140 } codec_settings[kNumStreams] = {{1, 640, 480}, {2, 320, 240}, {3, 240, 160}};
1141
1142 test::DirectTransport sender_transport, receiver_transport;
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001143 rtc::scoped_ptr<Call> sender_call(
1144 Call::Create(Call::Config(&sender_transport)));
1145 rtc::scoped_ptr<Call> receiver_call(
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001146 Call::Create(Call::Config(&receiver_transport)));
1147 sender_transport.SetReceiver(receiver_call->Receiver());
1148 receiver_transport.SetReceiver(sender_call->Receiver());
1149
1150 VideoSendStream* send_streams[kNumStreams];
1151 VideoReceiveStream* receive_streams[kNumStreams];
1152
1153 VideoOutputObserver* observers[kNumStreams];
1154 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
1155
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001156 rtc::scoped_ptr<VideoEncoder> encoders[kNumStreams];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001157 for (size_t i = 0; i < kNumStreams; ++i)
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +00001158 encoders[i].reset(VideoEncoder::Create(VideoEncoder::kVp8));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001159
pbos@webrtc.org776e6f22014-10-29 15:28:39 +00001160 ScopedVector<VideoDecoder> allocated_decoders;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001161 for (size_t i = 0; i < kNumStreams; ++i) {
1162 uint32_t ssrc = codec_settings[i].ssrc;
1163 int width = codec_settings[i].width;
1164 int height = codec_settings[i].height;
1165 observers[i] = new VideoOutputObserver(&frame_generators[i], width, height);
1166
pbos@webrtc.orgbd249bc2014-07-07 04:45:15 +00001167 VideoSendStream::Config send_config;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001168 send_config.rtp.ssrcs.push_back(ssrc);
1169 send_config.encoder_settings.encoder = encoders[i].get();
1170 send_config.encoder_settings.payload_name = "VP8";
1171 send_config.encoder_settings.payload_type = 124;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001172 VideoEncoderConfig encoder_config;
1173 encoder_config.streams = test::CreateVideoStreams(1);
1174 VideoStream* stream = &encoder_config.streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001175 stream->width = width;
1176 stream->height = height;
1177 stream->max_framerate = 5;
1178 stream->min_bitrate_bps = stream->target_bitrate_bps =
1179 stream->max_bitrate_bps = 100000;
1180 send_streams[i] =
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001181 sender_call->CreateVideoSendStream(send_config, encoder_config);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001182 send_streams[i]->Start();
1183
pbos@webrtc.orgbd249bc2014-07-07 04:45:15 +00001184 VideoReceiveStream::Config receive_config;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001185 receive_config.renderer = observers[i];
1186 receive_config.rtp.remote_ssrc = ssrc;
1187 receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
pbos@webrtc.org776e6f22014-10-29 15:28:39 +00001188 VideoReceiveStream::Decoder decoder =
1189 test::CreateMatchingDecoder(send_config.encoder_settings);
1190 allocated_decoders.push_back(decoder.decoder);
1191 receive_config.decoders.push_back(decoder);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001192 receive_streams[i] =
1193 receiver_call->CreateVideoReceiveStream(receive_config);
1194 receive_streams[i]->Start();
1195
1196 frame_generators[i] = test::FrameGeneratorCapturer::Create(
1197 send_streams[i]->Input(), width, height, 30, Clock::GetRealTimeClock());
1198 frame_generators[i]->Start();
1199 }
1200
1201 for (size_t i = 0; i < kNumStreams; ++i) {
1202 EXPECT_EQ(kEventSignaled, observers[i]->Wait())
1203 << "Timed out while waiting for observer " << i << " to render.";
1204 }
1205
1206 for (size_t i = 0; i < kNumStreams; ++i) {
1207 frame_generators[i]->Stop();
1208 sender_call->DestroyVideoSendStream(send_streams[i]);
1209 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1210 delete frame_generators[i];
1211 delete observers[i];
1212 }
1213
1214 sender_transport.StopSending();
1215 receiver_transport.StopSending();
1216}
1217
1218TEST_F(EndToEndTest, ObserversEncodedFrames) {
1219 class EncodedFrameTestObserver : public EncodedFrameObserver {
1220 public:
1221 EncodedFrameTestObserver()
1222 : length_(0),
1223 frame_type_(kFrameEmpty),
1224 called_(EventWrapper::Create()) {}
1225 virtual ~EncodedFrameTestObserver() {}
1226
1227 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
1228 frame_type_ = encoded_frame.frame_type_;
1229 length_ = encoded_frame.length_;
1230 buffer_.reset(new uint8_t[length_]);
1231 memcpy(buffer_.get(), encoded_frame.data_, length_);
1232 called_->Set();
1233 }
1234
1235 EventTypeWrapper Wait() { return called_->Wait(kDefaultTimeoutMs); }
1236
1237 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
1238 ASSERT_EQ(length_, observer.length_)
1239 << "Observed frames are of different lengths.";
1240 EXPECT_EQ(frame_type_, observer.frame_type_)
1241 << "Observed frames have different frame types.";
1242 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
1243 << "Observed encoded frames have different content.";
1244 }
1245
1246 private:
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001247 rtc::scoped_ptr<uint8_t[]> buffer_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001248 size_t length_;
1249 FrameType frame_type_;
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001250 rtc::scoped_ptr<EventWrapper> called_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001251 };
1252
1253 EncodedFrameTestObserver post_encode_observer;
1254 EncodedFrameTestObserver pre_decode_observer;
1255
1256 test::DirectTransport sender_transport, receiver_transport;
1257
1258 CreateCalls(Call::Config(&sender_transport),
1259 Call::Config(&receiver_transport));
1260
1261 sender_transport.SetReceiver(receiver_call_->Receiver());
1262 receiver_transport.SetReceiver(sender_call_->Receiver());
1263
1264 CreateSendConfig(1);
1265 CreateMatchingReceiveConfigs();
1266 send_config_.post_encode_callback = &post_encode_observer;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001267 receive_configs_[0].pre_decode_callback = &pre_decode_observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001268
1269 CreateStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001270 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001271
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001272 rtc::scoped_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +00001273 test::FrameGenerator::CreateChromaGenerator(
1274 encoder_config_.streams[0].width, encoder_config_.streams[0].height));
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +00001275 send_stream_->Input()->IncomingCapturedFrame(*frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001276
1277 EXPECT_EQ(kEventSignaled, post_encode_observer.Wait())
1278 << "Timed out while waiting for send-side encoded-frame callback.";
1279
1280 EXPECT_EQ(kEventSignaled, pre_decode_observer.Wait())
1281 << "Timed out while waiting for pre-decode encoded-frame callback.";
1282
1283 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
1284
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001285 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001286
1287 sender_transport.StopSending();
1288 receiver_transport.StopSending();
1289
1290 DestroyStreams();
1291}
1292
1293TEST_F(EndToEndTest, ReceiveStreamSendsRemb) {
1294 class RembObserver : public test::EndToEndTest {
1295 public:
1296 RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
1297
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001298 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001299 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1300 EXPECT_TRUE(parser.IsValid());
1301
1302 bool received_psfb = false;
1303 bool received_remb = false;
1304 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1305 while (packet_type != RTCPUtility::kRtcpNotValidCode) {
1306 if (packet_type == RTCPUtility::kRtcpPsfbRembCode) {
1307 const RTCPUtility::RTCPPacket& packet = parser.Packet();
1308 EXPECT_EQ(packet.PSFBAPP.SenderSSRC, kReceiverLocalSsrc);
1309 received_psfb = true;
1310 } else if (packet_type == RTCPUtility::kRtcpPsfbRembItemCode) {
1311 const RTCPUtility::RTCPPacket& packet = parser.Packet();
1312 EXPECT_GT(packet.REMBItem.BitRate, 0u);
1313 EXPECT_EQ(packet.REMBItem.NumberOfSSRCs, 1u);
1314 EXPECT_EQ(packet.REMBItem.SSRCs[0], kSendSsrcs[0]);
1315 received_remb = true;
1316 }
1317 packet_type = parser.Iterate();
1318 }
1319 if (received_psfb && received_remb)
1320 observation_complete_->Set();
1321 return SEND_PACKET;
1322 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001323 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001324 EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for a "
1325 "receiver RTCP REMB packet to be "
1326 "sent.";
1327 }
1328 } test;
1329
1330 RunBaseTest(&test);
1331}
1332
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001333TEST_F(EndToEndTest, VerifyBandwidthStats) {
1334 class RtcpObserver : public test::EndToEndTest, public PacketReceiver {
1335 public:
1336 RtcpObserver()
1337 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001338 sender_call_(nullptr),
1339 receiver_call_(nullptr),
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001340 has_seen_pacer_delay_(false) {}
1341
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001342 DeliveryStatus DeliverPacket(const uint8_t* packet,
1343 size_t length) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001344 Call::Stats sender_stats = sender_call_->GetStats();
1345 Call::Stats receiver_stats = receiver_call_->GetStats();
1346 if (!has_seen_pacer_delay_)
1347 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
1348 if (sender_stats.send_bandwidth_bps > 0 &&
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001349 receiver_stats.recv_bandwidth_bps > 0 && has_seen_pacer_delay_) {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001350 observation_complete_->Set();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001351 }
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001352 return receiver_call_->Receiver()->DeliverPacket(packet, length);
1353 }
1354
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001355 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001356 sender_call_ = sender_call;
1357 receiver_call_ = receiver_call;
1358 }
1359
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001360 void PerformTest() override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001361 EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for "
1362 "non-zero bandwidth stats.";
1363 }
1364
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001365 void SetReceivers(PacketReceiver* send_transport_receiver,
1366 PacketReceiver* receive_transport_receiver) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001367 test::RtpRtcpObserver::SetReceivers(this, receive_transport_receiver);
1368 }
1369
1370 private:
1371 Call* sender_call_;
1372 Call* receiver_call_;
1373 bool has_seen_pacer_delay_;
1374 } test;
1375
1376 RunBaseTest(&test);
1377}
1378
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001379void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
1380 static const int kNumRtcpReportPacketsToObserve = 5;
1381 class RtcpXrObserver : public test::EndToEndTest {
1382 public:
1383 explicit RtcpXrObserver(bool enable_rrtr)
1384 : EndToEndTest(kDefaultTimeoutMs),
1385 enable_rrtr_(enable_rrtr),
1386 sent_rtcp_sr_(0),
1387 sent_rtcp_rr_(0),
1388 sent_rtcp_rrtr_(0),
1389 sent_rtcp_dlrr_(0) {}
1390
1391 private:
1392 // Receive stream should send RR packets (and RRTR packets if enabled).
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001393 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001394 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1395 EXPECT_TRUE(parser.IsValid());
1396
1397 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1398 while (packet_type != RTCPUtility::kRtcpNotValidCode) {
1399 if (packet_type == RTCPUtility::kRtcpRrCode) {
1400 ++sent_rtcp_rr_;
1401 } else if (packet_type ==
1402 RTCPUtility::kRtcpXrReceiverReferenceTimeCode) {
1403 ++sent_rtcp_rrtr_;
1404 }
1405 EXPECT_NE(packet_type, RTCPUtility::kRtcpSrCode);
1406 EXPECT_NE(packet_type, RTCPUtility::kRtcpXrDlrrReportBlockItemCode);
1407 packet_type = parser.Iterate();
1408 }
1409 return SEND_PACKET;
1410 }
1411 // Send stream should send SR packets (and DLRR packets if enabled).
1412 virtual Action OnSendRtcp(const uint8_t* packet, size_t length) {
1413 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1414 EXPECT_TRUE(parser.IsValid());
1415
1416 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1417 while (packet_type != RTCPUtility::kRtcpNotValidCode) {
1418 if (packet_type == RTCPUtility::kRtcpSrCode) {
1419 ++sent_rtcp_sr_;
1420 } else if (packet_type == RTCPUtility::kRtcpXrDlrrReportBlockItemCode) {
1421 ++sent_rtcp_dlrr_;
1422 }
1423 EXPECT_NE(packet_type, RTCPUtility::kRtcpXrReceiverReferenceTimeCode);
1424 packet_type = parser.Iterate();
1425 }
1426 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
1427 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve) {
1428 if (enable_rrtr_) {
1429 EXPECT_GT(sent_rtcp_rrtr_, 0);
1430 EXPECT_GT(sent_rtcp_dlrr_, 0);
1431 } else {
1432 EXPECT_EQ(0, sent_rtcp_rrtr_);
1433 EXPECT_EQ(0, sent_rtcp_dlrr_);
1434 }
1435 observation_complete_->Set();
1436 }
1437 return SEND_PACKET;
1438 }
1439
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001440 void ModifyConfigs(VideoSendStream::Config* send_config,
1441 std::vector<VideoReceiveStream::Config>* receive_configs,
1442 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001443 (*receive_configs)[0].rtp.rtcp_mode = newapi::kRtcpReducedSize;
1444 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
1445 enable_rrtr_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001446 }
1447
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001448 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001449 EXPECT_EQ(kEventSignaled, Wait())
1450 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
1451 }
1452
1453 bool enable_rrtr_;
1454 int sent_rtcp_sr_;
1455 int sent_rtcp_rr_;
1456 int sent_rtcp_rrtr_;
1457 int sent_rtcp_dlrr_;
1458 } test(enable_rrtr);
1459
1460 RunBaseTest(&test);
1461}
1462
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001463void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
1464 bool send_single_ssrc_first) {
1465 class SendsSetSsrcs : public test::EndToEndTest {
1466 public:
1467 SendsSetSsrcs(const uint32_t* ssrcs,
1468 size_t num_ssrcs,
1469 bool send_single_ssrc_first)
1470 : EndToEndTest(kDefaultTimeoutMs),
1471 num_ssrcs_(num_ssrcs),
1472 send_single_ssrc_first_(send_single_ssrc_first),
1473 ssrcs_to_observe_(num_ssrcs),
1474 expect_single_ssrc_(send_single_ssrc_first) {
1475 for (size_t i = 0; i < num_ssrcs; ++i)
1476 valid_ssrcs_[ssrcs[i]] = true;
1477 }
1478
1479 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001480 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001481 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001482 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001483
1484 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
1485 << "Received unknown SSRC: " << header.ssrc;
1486
1487 if (!valid_ssrcs_[header.ssrc])
1488 observation_complete_->Set();
1489
1490 if (!is_observed_[header.ssrc]) {
1491 is_observed_[header.ssrc] = true;
1492 --ssrcs_to_observe_;
1493 if (expect_single_ssrc_) {
1494 expect_single_ssrc_ = false;
1495 observation_complete_->Set();
1496 }
1497 }
1498
1499 if (ssrcs_to_observe_ == 0)
1500 observation_complete_->Set();
1501
1502 return SEND_PACKET;
1503 }
1504
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001505 size_t GetNumStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001506
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001507 void ModifyConfigs(VideoSendStream::Config* send_config,
1508 std::vector<VideoReceiveStream::Config>* receive_configs,
1509 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001510 if (num_ssrcs_ > 1) {
1511 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001512 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
1513 encoder_config->streams[i].min_bitrate_bps = 10000;
1514 encoder_config->streams[i].target_bitrate_bps = 15000;
1515 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001516 }
1517 }
1518
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001519 encoder_config_all_streams_ = *encoder_config;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001520 if (send_single_ssrc_first_)
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001521 encoder_config->streams.resize(1);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001522 }
1523
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001524 void OnStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001525 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00001526 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001527 send_stream_ = send_stream;
1528 }
1529
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001530 void PerformTest() override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001531 EXPECT_EQ(kEventSignaled, Wait())
1532 << "Timed out while waiting for "
1533 << (send_single_ssrc_first_ ? "first SSRC." : "SSRCs.");
1534
1535 if (send_single_ssrc_first_) {
1536 // Set full simulcast and continue with the rest of the SSRCs.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001537 send_stream_->ReconfigureVideoEncoder(encoder_config_all_streams_);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001538 EXPECT_EQ(kEventSignaled, Wait())
1539 << "Timed out while waiting on additional SSRCs.";
1540 }
1541 }
1542
1543 private:
1544 std::map<uint32_t, bool> valid_ssrcs_;
1545 std::map<uint32_t, bool> is_observed_;
1546
1547 const size_t num_ssrcs_;
1548 const bool send_single_ssrc_first_;
1549
1550 size_t ssrcs_to_observe_;
1551 bool expect_single_ssrc_;
1552
1553 VideoSendStream* send_stream_;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001554 VideoEncoderConfig encoder_config_all_streams_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001555 } test(kSendSsrcs, num_ssrcs, send_single_ssrc_first);
1556
1557 RunBaseTest(&test);
1558}
1559
pbos@webrtc.org891d4832015-02-26 13:15:22 +00001560TEST_F(EndToEndTest, ReportsSetEncoderRates) {
1561 class EncoderRateStatsTest : public test::EndToEndTest,
1562 public test::FakeEncoder {
1563 public:
1564 EncoderRateStatsTest()
1565 : EndToEndTest(kDefaultTimeoutMs),
1566 FakeEncoder(Clock::GetRealTimeClock()) {}
1567
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001568 void OnStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00001569 VideoSendStream* send_stream,
1570 const std::vector<VideoReceiveStream*>& receive_streams) override {
1571 send_stream_ = send_stream;
1572 }
1573
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001574 void ModifyConfigs(VideoSendStream::Config* send_config,
1575 std::vector<VideoReceiveStream::Config>* receive_configs,
1576 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00001577 send_config->encoder_settings.encoder = this;
1578 }
1579
1580 int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override {
1581 // Make sure not to trigger on any default zero bitrates.
1582 if (new_target_bitrate == 0)
1583 return 0;
1584 CriticalSectionScoped lock(crit_.get());
1585 bitrate_kbps_ = new_target_bitrate;
1586 observation_complete_->Set();
1587 return 0;
1588 }
1589
1590 void PerformTest() override {
1591 ASSERT_EQ(kEventSignaled, Wait())
1592 << "Timed out while waiting for encoder SetRates() call.";
1593 // Wait for GetStats to report a corresponding bitrate.
1594 for (unsigned int i = 0; i < kDefaultTimeoutMs; ++i) {
1595 VideoSendStream::Stats stats = send_stream_->GetStats();
1596 {
1597 CriticalSectionScoped lock(crit_.get());
1598 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
1599 static_cast<int>(bitrate_kbps_)) {
1600 return;
1601 }
1602 }
1603 SleepMs(1);
1604 }
1605 FAIL()
1606 << "Timed out waiting for stats reporting the currently set bitrate.";
1607 }
1608
1609 private:
1610 VideoSendStream* send_stream_;
1611 uint32_t bitrate_kbps_ GUARDED_BY(crit_);
1612 } test;
1613
1614 RunBaseTest(&test);
1615}
1616
pbos@webrtc.orgba253472014-11-25 09:39:04 +00001617TEST_F(EndToEndTest, GetStats) {
1618 static const int kStartBitrateBps = 3000000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001619 class StatsObserver : public test::EndToEndTest, public I420FrameCallback {
1620 public:
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001621 explicit StatsObserver(const FakeNetworkPipe::Config& config)
1622 : EndToEndTest(kLongTimeoutMs, config),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001623 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001624 expected_send_ssrcs_(),
1625 check_stats_event_(EventWrapper::Create()) {}
1626
1627 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001628 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001629 check_stats_event_->Set();
1630 return SEND_PACKET;
1631 }
1632
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001633 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001634 check_stats_event_->Set();
1635 return SEND_PACKET;
1636 }
1637
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001638 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001639 check_stats_event_->Set();
1640 return SEND_PACKET;
1641 }
1642
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001643 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001644 check_stats_event_->Set();
1645 return SEND_PACKET;
1646 }
1647
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001648 void FrameCallback(I420VideoFrame* video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001649 // Ensure that we have at least 5ms send side delay.
1650 int64_t render_time = video_frame->render_time_ms();
1651 if (render_time > 0)
1652 video_frame->set_render_time_ms(render_time - 5);
1653 }
1654
1655 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001656 for (size_t i = 0; i < receive_streams_.size(); ++i) {
1657 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
1658 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001659
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001660 // Make sure all fields have been populated.
1661 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
1662 // always filled for all receivers.
1663 receive_stats_filled_["IncomingRate"] |=
1664 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001665
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001666 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001667
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001668 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001669
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001670 receive_stats_filled_["StatisticsUpdated"] |=
1671 stats.rtcp_stats.cumulative_lost != 0 ||
1672 stats.rtcp_stats.extended_max_sequence_number != 0 ||
1673 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001674
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001675 receive_stats_filled_["DataCountersUpdated"] |=
1676 stats.rtp_stats.transmitted.payload_bytes != 0 ||
1677 stats.rtp_stats.fec.packets != 0 ||
1678 stats.rtp_stats.transmitted.header_bytes != 0 ||
1679 stats.rtp_stats.transmitted.packets != 0 ||
1680 stats.rtp_stats.transmitted.padding_bytes != 0 ||
1681 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001682
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001683 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001684 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001685
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001686 receive_stats_filled_["FrameCounts"] |=
1687 stats.frame_counts.key_frames != 0 ||
1688 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00001689
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001690 receive_stats_filled_["CName"] |= stats.c_name != "";
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00001691
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001692 receive_stats_filled_["RtcpPacketTypeCount"] |=
1693 stats.rtcp_packet_type_counts.fir_packets != 0 ||
1694 stats.rtcp_packet_type_counts.nack_packets != 0 ||
1695 stats.rtcp_packet_type_counts.pli_packets != 0 ||
1696 stats.rtcp_packet_type_counts.nack_requests != 0 ||
1697 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
1698 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001699
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001700 return AllStatsFilled(receive_stats_filled_);
1701 }
1702
1703 bool CheckSendStats() {
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001704 DCHECK(send_stream_ != nullptr);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001705 VideoSendStream::Stats stats = send_stream_->GetStats();
1706
1707 send_stats_filled_["NumStreams"] |=
1708 stats.substreams.size() == expected_send_ssrcs_.size();
1709
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00001710 send_stats_filled_["CpuOveruseMetrics"] |=
1711 stats.avg_encode_time_ms != 0 || stats.encode_usage_percent != 0;
1712
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001713 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001714 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001715 it != stats.substreams.end(); ++it) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001716 EXPECT_TRUE(expected_send_ssrcs_.find(it->first) !=
1717 expected_send_ssrcs_.end());
1718
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001719 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001720 stats.input_frame_rate != 0;
1721
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001722 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001723
1724 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
1725 stream_stats.rtcp_stats.cumulative_lost != 0 ||
1726 stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
1727 stream_stats.rtcp_stats.fraction_lost != 0;
1728
1729 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00001730 stream_stats.rtp_stats.fec.packets != 0 ||
1731 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
1732 stream_stats.rtp_stats.retransmitted.packets != 0 ||
1733 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001734
1735 send_stats_filled_[CompoundKey("BitrateStatisticsObserver",
1736 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001737 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001738
1739 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00001740 stream_stats.frame_counts.delta_frames != 0 ||
1741 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001742
1743 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
1744 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00001745
1746 send_stats_filled_[CompoundKey("Delay", it->first)] |=
1747 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001748
1749 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
1750 // report dropped packets.
1751 send_stats_filled_["RtcpPacketTypeCount"] |=
1752 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
1753 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
1754 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
1755 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
1756 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001757 }
1758
1759 return AllStatsFilled(send_stats_filled_);
1760 }
1761
1762 std::string CompoundKey(const char* name, uint32_t ssrc) {
1763 std::ostringstream oss;
1764 oss << name << "_" << ssrc;
1765 return oss.str();
1766 }
1767
1768 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
1769 for (std::map<std::string, bool>::const_iterator it = stats_map.begin();
1770 it != stats_map.end();
1771 ++it) {
1772 if (!it->second)
1773 return false;
1774 }
1775 return true;
1776 }
1777
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00001778 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00001779 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01001780 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00001781 return config;
1782 }
1783
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001784 void ModifyConfigs(VideoSendStream::Config* send_config,
1785 std::vector<VideoReceiveStream::Config>* receive_configs,
1786 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001787 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001788 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001789
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001790 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001791 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001792 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001793 expected_receive_ssrcs_.push_back(
1794 (*receive_configs)[i].rtp.remote_ssrc);
1795 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001796 }
1797
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001798 size_t GetNumStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00001799
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001800 void OnStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001801 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00001802 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001803 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001804 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001805 }
1806
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001807 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001808 Clock* clock = Clock::GetRealTimeClock();
1809 int64_t now = clock->TimeInMilliseconds();
1810 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
1811 bool receive_ok = false;
1812 bool send_ok = false;
1813
1814 while (now < stop_time) {
1815 if (!receive_ok)
1816 receive_ok = CheckReceiveStats();
1817 if (!send_ok)
1818 send_ok = CheckSendStats();
1819
1820 if (receive_ok && send_ok)
1821 return;
1822
1823 int64_t time_until_timout_ = stop_time - now;
1824 if (time_until_timout_ > 0)
1825 check_stats_event_->Wait(time_until_timout_);
1826 now = clock->TimeInMilliseconds();
1827 }
1828
1829 ADD_FAILURE() << "Timed out waiting for filled stats.";
1830 for (std::map<std::string, bool>::const_iterator it =
1831 receive_stats_filled_.begin();
1832 it != receive_stats_filled_.end();
1833 ++it) {
1834 if (!it->second) {
1835 ADD_FAILURE() << "Missing receive stats: " << it->first;
1836 }
1837 }
1838
1839 for (std::map<std::string, bool>::const_iterator it =
1840 send_stats_filled_.begin();
1841 it != send_stats_filled_.end();
1842 ++it) {
1843 if (!it->second) {
1844 ADD_FAILURE() << "Missing send stats: " << it->first;
1845 }
1846 }
1847 }
1848
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001849 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001850 std::map<std::string, bool> receive_stats_filled_;
1851
1852 VideoSendStream* send_stream_;
1853 std::map<std::string, bool> send_stats_filled_;
1854
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001855 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001856 std::set<uint32_t> expected_send_ssrcs_;
1857 std::string expected_cname_;
1858
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001859 rtc::scoped_ptr<EventWrapper> check_stats_event_;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001860 };
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001861
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001862 FakeNetworkPipe::Config network_config;
1863 network_config.loss_percent = 5;
1864
1865 StatsObserver test(network_config);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001866 RunBaseTest(&test);
1867}
1868
1869TEST_F(EndToEndTest, ReceiverReferenceTimeReportEnabled) {
1870 TestXrReceiverReferenceTimeReport(true);
1871}
1872
1873TEST_F(EndToEndTest, ReceiverReferenceTimeReportDisabled) {
1874 TestXrReceiverReferenceTimeReport(false);
1875}
1876
1877TEST_F(EndToEndTest, TestReceivedRtpPacketStats) {
1878 static const size_t kNumRtpPacketsToSend = 5;
1879 class ReceivedRtpStatsObserver : public test::EndToEndTest {
1880 public:
1881 ReceivedRtpStatsObserver()
1882 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001883 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001884 sent_rtp_(0) {}
1885
1886 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001887 void OnStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001888 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00001889 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001890 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001891 }
1892
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001893 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001894 if (sent_rtp_ >= kNumRtpPacketsToSend) {
1895 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00001896 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001897 observation_complete_->Set();
1898 }
1899 return DROP_PACKET;
1900 }
1901 ++sent_rtp_;
1902 return SEND_PACKET;
1903 }
1904
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001905 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001906 EXPECT_EQ(kEventSignaled, Wait())
1907 << "Timed out while verifying number of received RTP packets.";
1908 }
1909
1910 VideoReceiveStream* receive_stream_;
1911 uint32_t sent_rtp_;
1912 } test;
1913
1914 RunBaseTest(&test);
1915}
1916
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001917TEST_F(EndToEndTest, SendsSetSsrc) { TestSendsSetSsrcs(1, false); }
1918
1919TEST_F(EndToEndTest, SendsSetSimulcastSsrcs) {
1920 TestSendsSetSsrcs(kNumSsrcs, false);
1921}
1922
1923TEST_F(EndToEndTest, CanSwitchToUseAllSsrcs) {
1924 TestSendsSetSsrcs(kNumSsrcs, true);
1925}
1926
mflodman@webrtc.orgf9460682014-07-24 16:41:25 +00001927TEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00001928 class ObserveRedundantPayloads: public test::EndToEndTest {
1929 public:
1930 ObserveRedundantPayloads()
1931 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00001932 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00001933 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
1934 }
1935 }
1936
1937 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001938 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00001939 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001940 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00001941
1942 if (!registered_rtx_ssrc_[header.ssrc])
1943 return SEND_PACKET;
1944
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001945 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00001946 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001947 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00001948
1949 if (!packet_is_redundant_payload)
1950 return SEND_PACKET;
1951
1952 if (!observed_redundant_retransmission_[header.ssrc]) {
1953 observed_redundant_retransmission_[header.ssrc] = true;
1954 if (--ssrcs_to_observe_ == 0)
1955 observation_complete_->Set();
1956 }
1957
1958 return SEND_PACKET;
1959 }
1960
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001961 size_t GetNumStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00001962
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001963 void ModifyConfigs(VideoSendStream::Config* send_config,
1964 std::vector<VideoReceiveStream::Config>* receive_configs,
1965 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00001966 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001967 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
1968 encoder_config->streams[i].min_bitrate_bps = 10000;
1969 encoder_config->streams[i].target_bitrate_bps = 15000;
1970 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00001971 }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00001972
1973 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00001974
1975 for (size_t i = 0; i < kNumSsrcs; ++i)
1976 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00001977
1978 // Significantly higher than max bitrates for all video streams -> forcing
1979 // padding to trigger redundant padding on all RTX SSRCs.
1980 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00001981 }
1982
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001983 void PerformTest() override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00001984 EXPECT_EQ(kEventSignaled, Wait())
1985 << "Timed out while waiting for redundant payloads on all SSRCs.";
1986 }
1987
1988 private:
1989 size_t ssrcs_to_observe_;
1990 std::map<uint32_t, bool> observed_redundant_retransmission_;
1991 std::map<uint32_t, bool> registered_rtx_ssrc_;
1992 } test;
1993
1994 RunBaseTest(&test);
1995}
1996
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001997void EndToEndTest::TestRtpStatePreservation(bool use_rtx) {
1998 static const uint32_t kMaxSequenceNumberGap = 100;
1999 static const uint64_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
2000 class RtpSequenceObserver : public test::RtpRtcpObserver {
2001 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00002002 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002003 : test::RtpRtcpObserver(kDefaultTimeoutMs),
2004 crit_(CriticalSectionWrapper::CreateCriticalSection()),
2005 ssrcs_to_observe_(kNumSsrcs) {
2006 for (size_t i = 0; i < kNumSsrcs; ++i) {
2007 configured_ssrcs_[kSendSsrcs[i]] = true;
2008 if (use_rtx)
2009 configured_ssrcs_[kSendRtxSsrcs[i]] = true;
2010 }
2011 }
2012
2013 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
2014 CriticalSectionScoped lock(crit_.get());
2015 ssrc_observed_.clear();
2016 ssrcs_to_observe_ = num_expected_ssrcs;
2017 }
2018
2019 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002020 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002021 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002022 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002023 const uint32_t ssrc = header.ssrc;
2024 const uint16_t sequence_number = header.sequenceNumber;
2025 const uint32_t timestamp = header.timestamp;
2026 const bool only_padding =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002027 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002028
2029 EXPECT_TRUE(configured_ssrcs_[ssrc])
2030 << "Received SSRC that wasn't configured: " << ssrc;
2031
2032 std::map<uint32_t, uint16_t>::iterator it =
2033 last_observed_sequence_number_.find(header.ssrc);
2034 if (it == last_observed_sequence_number_.end()) {
2035 last_observed_sequence_number_[ssrc] = sequence_number;
2036 last_observed_timestamp_[ssrc] = timestamp;
2037 } else {
2038 // Verify sequence numbers are reasonably close.
2039 uint32_t extended_sequence_number = sequence_number;
2040 // Check for roll-over.
2041 if (sequence_number < last_observed_sequence_number_[ssrc])
2042 extended_sequence_number += 0xFFFFu + 1;
2043 EXPECT_LE(
2044 extended_sequence_number - last_observed_sequence_number_[ssrc],
2045 kMaxSequenceNumberGap)
2046 << "Gap in sequence numbers ("
2047 << last_observed_sequence_number_[ssrc] << " -> " << sequence_number
2048 << ") too large for SSRC: " << ssrc << ".";
2049 last_observed_sequence_number_[ssrc] = sequence_number;
2050
2051 // TODO(pbos): Remove this check if we ever have monotonically
2052 // increasing timestamps. Right now padding packets add a delta which
2053 // can cause reordering between padding packets and regular packets,
2054 // hence we drop padding-only packets to not flake.
2055 if (only_padding) {
2056 // Verify that timestamps are reasonably close.
2057 uint64_t extended_timestamp = timestamp;
2058 // Check for roll-over.
2059 if (timestamp < last_observed_timestamp_[ssrc])
2060 extended_timestamp += static_cast<uint64_t>(0xFFFFFFFFu) + 1;
2061 EXPECT_LE(extended_timestamp - last_observed_timestamp_[ssrc],
2062 kMaxTimestampGap)
2063 << "Gap in timestamps (" << last_observed_timestamp_[ssrc]
2064 << " -> " << timestamp << ") too large for SSRC: " << ssrc << ".";
2065 }
2066 last_observed_timestamp_[ssrc] = timestamp;
2067 }
2068
2069 CriticalSectionScoped lock(crit_.get());
2070 // Wait for media packets on all ssrcs.
2071 if (!ssrc_observed_[ssrc] && !only_padding) {
2072 ssrc_observed_[ssrc] = true;
2073 if (--ssrcs_to_observe_ == 0)
2074 observation_complete_->Set();
2075 }
2076
2077 return SEND_PACKET;
2078 }
2079
2080 std::map<uint32_t, uint16_t> last_observed_sequence_number_;
2081 std::map<uint32_t, uint32_t> last_observed_timestamp_;
2082 std::map<uint32_t, bool> configured_ssrcs_;
2083
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00002084 rtc::scoped_ptr<CriticalSectionWrapper> crit_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002085 size_t ssrcs_to_observe_ GUARDED_BY(crit_);
2086 std::map<uint32_t, bool> ssrc_observed_ GUARDED_BY(crit_);
2087 } observer(use_rtx);
2088
2089 CreateCalls(Call::Config(observer.SendTransport()),
2090 Call::Config(observer.ReceiveTransport()));
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002091 observer.SetReceivers(sender_call_->Receiver(), nullptr);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002092
2093 CreateSendConfig(kNumSsrcs);
2094
2095 if (use_rtx) {
2096 for (size_t i = 0; i < kNumSsrcs; ++i) {
2097 send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
2098 }
2099 send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
2100 }
2101
2102 // Lower bitrates so that all streams send initially.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002103 for (size_t i = 0; i < encoder_config_.streams.size(); ++i) {
2104 encoder_config_.streams[i].min_bitrate_bps = 10000;
2105 encoder_config_.streams[i].target_bitrate_bps = 15000;
2106 encoder_config_.streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002107 }
2108
pbos@webrtc.org32452b22014-10-22 12:15:24 +00002109 // Use the same total bitrates when sending a single stream to avoid lowering
2110 // the bitrate estimate and requiring a subsequent rampup.
2111 VideoEncoderConfig one_stream = encoder_config_;
2112 one_stream.streams.resize(1);
2113 for (size_t i = 1; i < encoder_config_.streams.size(); ++i) {
2114 one_stream.streams.front().min_bitrate_bps +=
2115 encoder_config_.streams[i].min_bitrate_bps;
2116 one_stream.streams.front().target_bitrate_bps +=
2117 encoder_config_.streams[i].target_bitrate_bps;
2118 one_stream.streams.front().max_bitrate_bps +=
2119 encoder_config_.streams[i].max_bitrate_bps;
2120 }
2121
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002122 CreateMatchingReceiveConfigs();
2123
2124 CreateStreams();
2125 CreateFrameGeneratorCapturer();
2126
2127 Start();
2128 EXPECT_EQ(kEventSignaled, observer.Wait())
2129 << "Timed out waiting for all SSRCs to send packets.";
2130
2131 // Test stream resetting more than once to make sure that the state doesn't
2132 // get set once (this could be due to using std::map::insert for instance).
2133 for (size_t i = 0; i < 3; ++i) {
2134 frame_generator_capturer_->Stop();
2135 sender_call_->DestroyVideoSendStream(send_stream_);
2136
2137 // Re-create VideoSendStream with only one stream.
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002138 send_stream_ =
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002139 sender_call_->CreateVideoSendStream(send_config_, one_stream);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002140 send_stream_->Start();
2141 CreateFrameGeneratorCapturer();
2142 frame_generator_capturer_->Start();
2143
2144 observer.ResetExpectedSsrcs(1);
2145 EXPECT_EQ(kEventSignaled, observer.Wait())
2146 << "Timed out waiting for single RTP packet.";
2147
2148 // Reconfigure back to use all streams.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002149 send_stream_->ReconfigureVideoEncoder(encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002150 observer.ResetExpectedSsrcs(kNumSsrcs);
2151 EXPECT_EQ(kEventSignaled, observer.Wait())
2152 << "Timed out waiting for all SSRCs to send packets.";
2153
2154 // Reconfigure down to one stream.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002155 send_stream_->ReconfigureVideoEncoder(one_stream);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002156 observer.ResetExpectedSsrcs(1);
2157 EXPECT_EQ(kEventSignaled, observer.Wait())
2158 << "Timed out waiting for single RTP packet.";
2159
2160 // Reconfigure back to use all streams.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002161 send_stream_->ReconfigureVideoEncoder(encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002162 observer.ResetExpectedSsrcs(kNumSsrcs);
2163 EXPECT_EQ(kEventSignaled, observer.Wait())
2164 << "Timed out waiting for all SSRCs to send packets.";
2165 }
2166
2167 observer.StopSending();
2168
2169 Stop();
2170 DestroyStreams();
2171}
2172
aluebs@webrtc.orgb623c5c2014-08-26 14:22:51 +00002173TEST_F(EndToEndTest, DISABLED_RestartingSendStreamPreservesRtpState) {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002174 TestRtpStatePreservation(false);
2175}
2176
2177TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpStatesWithRtx) {
2178 TestRtpStatePreservation(true);
2179}
2180
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002181TEST_F(EndToEndTest, RespectsNetworkState) {
2182 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
2183 // down blocks until no more packets will be sent.
2184
2185 // Pacer will send from its packet list and then send required padding before
2186 // checking paused_ again. This should be enough for one round of pacing,
2187 // otherwise increase.
2188 static const int kNumAcceptedDowntimeRtp = 5;
2189 // A single RTCP may be in the pipeline.
2190 static const int kNumAcceptedDowntimeRtcp = 1;
2191 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
2192 public:
2193 NetworkStateTest()
2194 : EndToEndTest(kDefaultTimeoutMs),
2195 FakeEncoder(Clock::GetRealTimeClock()),
2196 test_crit_(CriticalSectionWrapper::CreateCriticalSection()),
2197 encoded_frames_(EventWrapper::Create()),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002198 packet_event_(EventWrapper::Create()),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002199 sender_state_(Call::kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002200 sender_rtp_(0),
2201 sender_rtcp_(0),
2202 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002203 down_frames_(0) {}
2204
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002205 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002206 CriticalSectionScoped lock(test_crit_.get());
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002207 ++sender_rtp_;
2208 packet_event_->Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002209 return SEND_PACKET;
2210 }
2211
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002212 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002213 CriticalSectionScoped lock(test_crit_.get());
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002214 ++sender_rtcp_;
2215 packet_event_->Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002216 return SEND_PACKET;
2217 }
2218
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002219 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002220 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
2221 return SEND_PACKET;
2222 }
2223
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002224 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002225 CriticalSectionScoped lock(test_crit_.get());
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002226 ++receiver_rtcp_;
2227 packet_event_->Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002228 return SEND_PACKET;
2229 }
2230
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002231 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002232 sender_call_ = sender_call;
2233 receiver_call_ = receiver_call;
2234 }
2235
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002236 void ModifyConfigs(VideoSendStream::Config* send_config,
2237 std::vector<VideoReceiveStream::Config>* receive_configs,
2238 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002239 send_config->encoder_settings.encoder = this;
2240 }
2241
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002242 void PerformTest() override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002243 EXPECT_EQ(kEventSignaled, encoded_frames_->Wait(kDefaultTimeoutMs))
2244 << "No frames received by the encoder.";
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002245 // Wait for packets from both sender/receiver.
2246 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002247
2248 // Sender-side network down.
2249 sender_call_->SignalNetworkState(Call::kNetworkDown);
2250 {
2251 CriticalSectionScoped lock(test_crit_.get());
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002252 // After network goes down we shouldn't be encoding more frames.
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002253 sender_state_ = Call::kNetworkDown;
2254 }
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002255 // Wait for receiver-packets and no sender packets.
2256 WaitForPacketsOrSilence(true, false);
2257
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002258 // Receiver-side network down.
2259 receiver_call_->SignalNetworkState(Call::kNetworkDown);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002260 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002261
2262 // Network back up again for both.
2263 {
2264 CriticalSectionScoped lock(test_crit_.get());
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002265 // It's OK to encode frames again, as we're about to bring up the
2266 // network.
2267 sender_state_ = Call::kNetworkUp;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002268 }
2269 sender_call_->SignalNetworkState(Call::kNetworkUp);
2270 receiver_call_->SignalNetworkState(Call::kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002271 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002272 }
2273
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002274 int32_t Encode(const I420VideoFrame& input_image,
2275 const CodecSpecificInfo* codec_specific_info,
2276 const std::vector<VideoFrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002277 {
2278 CriticalSectionScoped lock(test_crit_.get());
2279 if (sender_state_ == Call::kNetworkDown) {
2280 ++down_frames_;
2281 EXPECT_LE(down_frames_, 1)
2282 << "Encoding more than one frame while network is down.";
2283 if (down_frames_ > 1)
2284 encoded_frames_->Set();
2285 } else {
2286 encoded_frames_->Set();
2287 }
2288 }
2289 return test::FakeEncoder::Encode(
2290 input_image, codec_specific_info, frame_types);
2291 }
2292
2293 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002294 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
2295 int64_t initial_time_ms = clock_->TimeInMilliseconds();
2296 int initial_sender_rtp;
2297 int initial_sender_rtcp;
2298 int initial_receiver_rtcp;
2299 {
2300 CriticalSectionScoped lock(test_crit_.get());
2301 initial_sender_rtp = sender_rtp_;
2302 initial_sender_rtcp = sender_rtcp_;
2303 initial_receiver_rtcp = receiver_rtcp_;
2304 }
2305 bool sender_done = false;
2306 bool receiver_done = false;
2307 while(!sender_done || !receiver_done) {
2308 packet_event_->Wait(kSilenceTimeoutMs);
2309 int64_t time_now_ms = clock_->TimeInMilliseconds();
2310 CriticalSectionScoped lock(test_crit_.get());
2311 if (sender_down) {
2312 ASSERT_LE(sender_rtp_ - initial_sender_rtp, kNumAcceptedDowntimeRtp)
2313 << "RTP sent during sender-side downtime.";
2314 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
2315 kNumAcceptedDowntimeRtcp)
2316 << "RTCP sent during sender-side downtime.";
2317 if (time_now_ms - initial_time_ms >=
2318 static_cast<int64_t>(kSilenceTimeoutMs)) {
2319 sender_done = true;
2320 }
2321 } else {
2322 if (sender_rtp_ > initial_sender_rtp)
2323 sender_done = true;
2324 }
2325 if (receiver_down) {
2326 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
2327 kNumAcceptedDowntimeRtcp)
2328 << "RTCP sent during receiver-side downtime.";
2329 if (time_now_ms - initial_time_ms >=
2330 static_cast<int64_t>(kSilenceTimeoutMs)) {
2331 receiver_done = true;
2332 }
2333 } else {
2334 if (receiver_rtcp_ > initial_receiver_rtcp)
2335 receiver_done = true;
2336 }
2337 }
2338 }
2339
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00002340 const rtc::scoped_ptr<CriticalSectionWrapper> test_crit_;
2341 const rtc::scoped_ptr<EventWrapper> encoded_frames_;
2342 const rtc::scoped_ptr<EventWrapper> packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002343 Call* sender_call_;
2344 Call* receiver_call_;
2345 Call::NetworkState sender_state_ GUARDED_BY(test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002346 int sender_rtp_ GUARDED_BY(test_crit_);
2347 int sender_rtcp_ GUARDED_BY(test_crit_);
2348 int receiver_rtcp_ GUARDED_BY(test_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002349 int down_frames_ GUARDED_BY(test_crit_);
2350 } test;
2351
2352 RunBaseTest(&test);
2353}
2354
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00002355TEST_F(EndToEndTest, CallReportsRttForSender) {
2356 static const int kSendDelayMs = 30;
2357 static const int kReceiveDelayMs = 70;
2358
2359 FakeNetworkPipe::Config config;
2360 config.queue_delay_ms = kSendDelayMs;
2361 test::DirectTransport sender_transport(config);
2362 config.queue_delay_ms = kReceiveDelayMs;
2363 test::DirectTransport receiver_transport(config);
2364
2365 CreateCalls(Call::Config(&sender_transport),
2366 Call::Config(&receiver_transport));
2367
2368 sender_transport.SetReceiver(receiver_call_->Receiver());
2369 receiver_transport.SetReceiver(sender_call_->Receiver());
2370
2371 CreateSendConfig(1);
2372 CreateMatchingReceiveConfigs();
2373
2374 CreateStreams();
2375 CreateFrameGeneratorCapturer();
2376 Start();
2377
2378 int64_t start_time_ms = clock_->TimeInMilliseconds();
2379 while (true) {
2380 Call::Stats stats = sender_call_->GetStats();
2381 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
2382 clock_->TimeInMilliseconds())
2383 << "No RTT stats before timeout!";
2384 if (stats.rtt_ms != -1) {
2385 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs);
2386 break;
2387 }
2388 SleepMs(10);
2389 }
2390
2391 Stop();
2392 DestroyStreams();
2393}
2394
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002395TEST_F(EndToEndTest, NewSendStreamsRespectNetworkDown) {
2396 class UnusedEncoder : public test::FakeEncoder {
2397 public:
2398 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002399 int32_t Encode(const I420VideoFrame& input_image,
2400 const CodecSpecificInfo* codec_specific_info,
2401 const std::vector<VideoFrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002402 ADD_FAILURE() << "Unexpected frame encode.";
2403 return test::FakeEncoder::Encode(
2404 input_image, codec_specific_info, frame_types);
2405 }
2406 };
2407
2408 UnusedTransport transport;
2409 CreateSenderCall(Call::Config(&transport));
2410 sender_call_->SignalNetworkState(Call::kNetworkDown);
2411
2412 CreateSendConfig(1);
2413 UnusedEncoder unused_encoder;
2414 send_config_.encoder_settings.encoder = &unused_encoder;
2415 CreateStreams();
2416 CreateFrameGeneratorCapturer();
2417
2418 Start();
2419 SleepMs(kSilenceTimeoutMs);
2420 Stop();
2421
2422 DestroyStreams();
2423}
2424
2425TEST_F(EndToEndTest, NewReceiveStreamsRespectNetworkDown) {
2426 test::DirectTransport sender_transport;
2427 CreateSenderCall(Call::Config(&sender_transport));
2428 UnusedTransport transport;
2429 CreateReceiverCall(Call::Config(&transport));
2430 sender_transport.SetReceiver(receiver_call_->Receiver());
2431
2432 receiver_call_->SignalNetworkState(Call::kNetworkDown);
2433
2434 CreateSendConfig(1);
2435 CreateMatchingReceiveConfigs();
2436 CreateStreams();
2437 CreateFrameGeneratorCapturer();
2438
2439 Start();
2440 SleepMs(kSilenceTimeoutMs);
2441 Stop();
2442
2443 sender_transport.StopSending();
2444
2445 DestroyStreams();
2446}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00002447
2448// TODO(pbos): Remove this regression test when VideoEngine is no longer used as
2449// a backend. This is to test that we hand channels back properly.
2450TEST_F(EndToEndTest, CanCreateAndDestroyManyVideoStreams) {
2451 test::NullTransport transport;
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00002452 rtc::scoped_ptr<Call> call(Call::Create(Call::Config(&transport)));
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00002453 test::FakeDecoder fake_decoder;
2454 test::FakeEncoder fake_encoder(Clock::GetRealTimeClock());
2455 for (size_t i = 0; i < 100; ++i) {
2456 VideoSendStream::Config send_config;
2457 send_config.encoder_settings.encoder = &fake_encoder;
2458 send_config.encoder_settings.payload_name = "FAKE";
2459 send_config.encoder_settings.payload_type = 123;
2460
2461 VideoEncoderConfig encoder_config;
2462 encoder_config.streams = test::CreateVideoStreams(1);
2463 send_config.rtp.ssrcs.push_back(1);
2464 VideoSendStream* send_stream =
2465 call->CreateVideoSendStream(send_config, encoder_config);
2466 call->DestroyVideoSendStream(send_stream);
2467
2468 VideoReceiveStream::Config receive_config;
2469 receive_config.rtp.remote_ssrc = 1;
2470 receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
2471 VideoReceiveStream::Decoder decoder;
2472 decoder.decoder = &fake_decoder;
2473 decoder.payload_type = 123;
2474 decoder.payload_name = "FAKE";
2475 receive_config.decoders.push_back(decoder);
2476 VideoReceiveStream* receive_stream =
2477 call->CreateVideoReceiveStream(receive_config);
2478 call->DestroyVideoReceiveStream(receive_stream);
2479 }
2480}
andrew@webrtc.org8f27fcc2015-01-09 20:22:46 +00002481
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002482} // namespace webrtc