blob: 40bb1c72f4bbad680c910a216b11fe2f62b5d181 [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"
Åsa Persson352b2d72015-04-15 18:00:40 +020027#include "webrtc/system_wrappers/interface/metrics.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000028#include "webrtc/system_wrappers/interface/sleep.h"
29#include "webrtc/test/call_test.h"
30#include "webrtc/test/direct_transport.h"
31#include "webrtc/test/encoder_settings.h"
32#include "webrtc/test/fake_audio_device.h"
33#include "webrtc/test/fake_decoder.h"
34#include "webrtc/test/fake_encoder.h"
35#include "webrtc/test/frame_generator.h"
36#include "webrtc/test/frame_generator_capturer.h"
Åsa Persson352b2d72015-04-15 18:00:40 +020037#include "webrtc/test/histogram.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000038#include "webrtc/test/null_transport.h"
asapersson@webrtc.org37c05592015-01-28 13:58:27 +000039#include "webrtc/test/rtcp_packet_parser.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000040#include "webrtc/test/rtp_rtcp_observer.h"
41#include "webrtc/test/testsupport/fileutils.h"
andresp@webrtc.orgab071da2014-09-18 08:58:15 +000042#include "webrtc/test/testsupport/gtest_disable.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000043#include "webrtc/test/testsupport/perf_test.h"
44#include "webrtc/video/transport_adapter.h"
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +000045#include "webrtc/video_encoder.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000046
47namespace webrtc {
48
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000049static const unsigned long kSilenceTimeoutMs = 2000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000050
51class EndToEndTest : public test::CallTest {
52 public:
53 EndToEndTest() {}
54
55 virtual ~EndToEndTest() {
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000056 EXPECT_EQ(nullptr, send_stream_);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +000057 EXPECT_TRUE(receive_streams_.empty());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000058 }
59
60 protected:
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000061 class UnusedTransport : public newapi::Transport {
62 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000063 bool SendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000064 ADD_FAILURE() << "Unexpected RTP sent.";
65 return false;
66 }
67
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000068 bool SendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000069 ADD_FAILURE() << "Unexpected RTCP sent.";
70 return false;
71 }
72 };
73
Shao Changbine62202f2015-04-21 20:24:50 +080074 void DecodesRetransmittedFrame(bool use_rtx, bool use_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000075 void ReceivesPliAndRecovers(int rtp_history_ms);
76 void RespectsRtcpMode(newapi::RtcpMode rtcp_mode);
77 void TestXrReceiverReferenceTimeReport(bool enable_rrtr);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +000078 void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +000079 void TestRtpStatePreservation(bool use_rtx);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +000080 void TestReceivedFecPacketsNotNacked(const FakeNetworkPipe::Config& config);
Åsa Persson3c391cb2015-04-27 10:09:49 +020081 void VerifyHistogramStats(bool use_rtx, bool use_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000082};
83
84TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
85 test::NullTransport transport;
86 CreateCalls(Call::Config(&transport), Call::Config(&transport));
87
88 CreateSendConfig(1);
89 CreateMatchingReceiveConfigs();
90
91 CreateStreams();
92
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +000093 receive_streams_[0]->Start();
94 receive_streams_[0]->Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000095
96 DestroyStreams();
97}
98
99TEST_F(EndToEndTest, ReceiverCanBeStoppedTwice) {
100 test::NullTransport transport;
101 CreateCalls(Call::Config(&transport), Call::Config(&transport));
102
103 CreateSendConfig(1);
104 CreateMatchingReceiveConfigs();
105
106 CreateStreams();
107
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000108 receive_streams_[0]->Stop();
109 receive_streams_[0]->Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000110
111 DestroyStreams();
112}
113
114TEST_F(EndToEndTest, RendersSingleDelayedFrame) {
115 static const int kWidth = 320;
116 static const int kHeight = 240;
117 // This constant is chosen to be higher than the timeout in the video_render
118 // module. This makes sure that frames aren't dropped if there are no other
119 // frames in the queue.
120 static const int kDelayRenderCallbackMs = 1000;
121
122 class Renderer : public VideoRenderer {
123 public:
124 Renderer() : event_(EventWrapper::Create()) {}
125
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000126 void RenderFrame(const I420VideoFrame& video_frame,
127 int /*time_to_render_ms*/) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000128 event_->Set();
129 }
130
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000131 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000132
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000133 EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
134
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000135 rtc::scoped_ptr<EventWrapper> event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000136 } renderer;
137
138 class TestFrameCallback : public I420FrameCallback {
139 public:
140 TestFrameCallback() : event_(EventWrapper::Create()) {}
141
142 EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
143
144 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000145 void FrameCallback(I420VideoFrame* frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000146 SleepMs(kDelayRenderCallbackMs);
147 event_->Set();
148 }
149
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000150 rtc::scoped_ptr<EventWrapper> event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000151 };
152
153 test::DirectTransport sender_transport, receiver_transport;
154
155 CreateCalls(Call::Config(&sender_transport),
156 Call::Config(&receiver_transport));
157
158 sender_transport.SetReceiver(receiver_call_->Receiver());
159 receiver_transport.SetReceiver(sender_call_->Receiver());
160
161 CreateSendConfig(1);
162 CreateMatchingReceiveConfigs();
163
164 TestFrameCallback pre_render_callback;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000165 receive_configs_[0].pre_render_callback = &pre_render_callback;
166 receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000167
168 CreateStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000169 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000170
171 // Create frames that are smaller than the send width/height, this is done to
172 // check that the callbacks are done after processing video.
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000173 rtc::scoped_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000174 test::FrameGenerator::CreateChromaGenerator(kWidth, kHeight));
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +0000175 send_stream_->Input()->IncomingCapturedFrame(*frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000176 EXPECT_EQ(kEventSignaled, pre_render_callback.Wait())
177 << "Timed out while waiting for pre-render callback.";
178 EXPECT_EQ(kEventSignaled, renderer.Wait())
179 << "Timed out while waiting for the frame to render.";
180
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000181 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000182
183 sender_transport.StopSending();
184 receiver_transport.StopSending();
185
186 DestroyStreams();
187}
188
189TEST_F(EndToEndTest, TransmitsFirstFrame) {
190 class Renderer : public VideoRenderer {
191 public:
192 Renderer() : event_(EventWrapper::Create()) {}
193
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000194 void RenderFrame(const I420VideoFrame& video_frame,
195 int /*time_to_render_ms*/) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000196 event_->Set();
197 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000198 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000199
200 EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
201
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000202 rtc::scoped_ptr<EventWrapper> event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000203 } renderer;
204
205 test::DirectTransport sender_transport, receiver_transport;
206
207 CreateCalls(Call::Config(&sender_transport),
208 Call::Config(&receiver_transport));
209
210 sender_transport.SetReceiver(receiver_call_->Receiver());
211 receiver_transport.SetReceiver(sender_call_->Receiver());
212
213 CreateSendConfig(1);
214 CreateMatchingReceiveConfigs();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000215 receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000216
217 CreateStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000218 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000219
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000220 rtc::scoped_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000221 test::FrameGenerator::CreateChromaGenerator(
222 encoder_config_.streams[0].width, encoder_config_.streams[0].height));
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +0000223 send_stream_->Input()->IncomingCapturedFrame(*frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000224
225 EXPECT_EQ(kEventSignaled, renderer.Wait())
226 << "Timed out while waiting for the frame to render.";
227
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000228 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000229
230 sender_transport.StopSending();
231 receiver_transport.StopSending();
232
233 DestroyStreams();
234}
235
marpan@webrtc.org5f1e2e42014-11-06 02:02:28 +0000236TEST_F(EndToEndTest, SendsAndReceivesVP9) {
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000237 class VP9Observer : public test::EndToEndTest, public VideoRenderer {
238 public:
239 VP9Observer()
240 : EndToEndTest(2 * kDefaultTimeoutMs),
241 encoder_(VideoEncoder::Create(VideoEncoder::kVp9)),
242 decoder_(VP9Decoder::Create()),
243 frame_counter_(0) {}
244
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000245 void PerformTest() override {
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000246 EXPECT_EQ(kEventSignaled, Wait())
247 << "Timed out while waiting for enough frames to be decoded.";
248 }
249
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000250 void ModifyConfigs(VideoSendStream::Config* send_config,
251 std::vector<VideoReceiveStream::Config>* receive_configs,
252 VideoEncoderConfig* encoder_config) override {
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000253 send_config->encoder_settings.encoder = encoder_.get();
254 send_config->encoder_settings.payload_name = "VP9";
255 send_config->encoder_settings.payload_type = VCM_VP9_PAYLOAD_TYPE;
256 encoder_config->streams[0].min_bitrate_bps = 50000;
257 encoder_config->streams[0].target_bitrate_bps =
258 encoder_config->streams[0].max_bitrate_bps = 2000000;
259
260 (*receive_configs)[0].renderer = this;
261 (*receive_configs)[0].decoders.resize(1);
262 (*receive_configs)[0].decoders[0].payload_type =
263 send_config->encoder_settings.payload_type;
264 (*receive_configs)[0].decoders[0].payload_name =
265 send_config->encoder_settings.payload_name;
266 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
267 }
268
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000269 void RenderFrame(const I420VideoFrame& video_frame,
270 int time_to_render_ms) override {
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000271 const int kRequiredFrames = 500;
272 if (++frame_counter_ == kRequiredFrames)
273 observation_complete_->Set();
274 }
275
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000276 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000277
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000278 private:
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000279 rtc::scoped_ptr<webrtc::VideoEncoder> encoder_;
280 rtc::scoped_ptr<webrtc::VideoDecoder> decoder_;
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000281 int frame_counter_;
282 } test;
283
284 RunBaseTest(&test);
285}
286
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000287TEST_F(EndToEndTest, SendsAndReceivesH264) {
288 class H264Observer : public test::EndToEndTest, public VideoRenderer {
289 public:
290 H264Observer()
291 : EndToEndTest(2 * kDefaultTimeoutMs),
292 fake_encoder_(Clock::GetRealTimeClock()),
293 frame_counter_(0) {}
294
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000295 void PerformTest() override {
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000296 EXPECT_EQ(kEventSignaled, Wait())
297 << "Timed out while waiting for enough frames to be decoded.";
298 }
299
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000300 void ModifyConfigs(VideoSendStream::Config* send_config,
301 std::vector<VideoReceiveStream::Config>* receive_configs,
302 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org8278c072015-02-23 11:11:49 +0000303 send_config->rtp.nack.rtp_history_ms =
304 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000305 send_config->encoder_settings.encoder = &fake_encoder_;
306 send_config->encoder_settings.payload_name = "H264";
307 send_config->encoder_settings.payload_type = kFakeSendPayloadType;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000308 encoder_config->streams[0].min_bitrate_bps = 50000;
309 encoder_config->streams[0].target_bitrate_bps =
310 encoder_config->streams[0].max_bitrate_bps = 2000000;
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000311
312 (*receive_configs)[0].renderer = this;
pbos@webrtc.org776e6f22014-10-29 15:28:39 +0000313 (*receive_configs)[0].decoders.resize(1);
314 (*receive_configs)[0].decoders[0].payload_type =
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000315 send_config->encoder_settings.payload_type;
pbos@webrtc.org776e6f22014-10-29 15:28:39 +0000316 (*receive_configs)[0].decoders[0].payload_name =
317 send_config->encoder_settings.payload_name;
318 (*receive_configs)[0].decoders[0].decoder = &fake_decoder_;
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000319 }
320
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000321 void RenderFrame(const I420VideoFrame& video_frame,
322 int time_to_render_ms) override {
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000323 const int kRequiredFrames = 500;
324 if (++frame_counter_ == kRequiredFrames)
325 observation_complete_->Set();
326 }
327
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000328 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000329
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000330 private:
331 test::FakeH264Decoder fake_decoder_;
332 test::FakeH264Encoder fake_encoder_;
333 int frame_counter_;
334 } test;
335
336 RunBaseTest(&test);
337}
338
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000339TEST_F(EndToEndTest, ReceiverUsesLocalSsrc) {
340 class SyncRtcpObserver : public test::EndToEndTest {
341 public:
342 SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {}
343
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000344 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000345 RTCPUtility::RTCPParserV2 parser(packet, length, true);
346 EXPECT_TRUE(parser.IsValid());
347 uint32_t ssrc = 0;
348 ssrc |= static_cast<uint32_t>(packet[4]) << 24;
349 ssrc |= static_cast<uint32_t>(packet[5]) << 16;
350 ssrc |= static_cast<uint32_t>(packet[6]) << 8;
351 ssrc |= static_cast<uint32_t>(packet[7]) << 0;
352 EXPECT_EQ(kReceiverLocalSsrc, ssrc);
353 observation_complete_->Set();
354
355 return SEND_PACKET;
356 }
357
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000358 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000359 EXPECT_EQ(kEventSignaled, Wait())
360 << "Timed out while waiting for a receiver RTCP packet to be sent.";
361 }
362 } test;
363
364 RunBaseTest(&test);
365}
366
367TEST_F(EndToEndTest, ReceivesAndRetransmitsNack) {
368 static const int kNumberOfNacksToObserve = 2;
369 static const int kLossBurstSize = 2;
370 static const int kPacketsBetweenLossBursts = 9;
371 class NackObserver : public test::EndToEndTest {
372 public:
373 NackObserver()
374 : EndToEndTest(kLongTimeoutMs),
375 rtp_parser_(RtpHeaderParser::Create()),
376 sent_rtp_packets_(0),
377 packets_left_to_drop_(0),
378 nacks_left_(kNumberOfNacksToObserve) {}
379
380 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000381 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000382 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000383 EXPECT_TRUE(rtp_parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000384
385 // Never drop retransmitted packets.
386 if (dropped_packets_.find(header.sequenceNumber) !=
387 dropped_packets_.end()) {
388 retransmitted_packets_.insert(header.sequenceNumber);
389 if (nacks_left_ == 0 &&
390 retransmitted_packets_.size() == dropped_packets_.size()) {
391 observation_complete_->Set();
392 }
393 return SEND_PACKET;
394 }
395
396 ++sent_rtp_packets_;
397
398 // Enough NACKs received, stop dropping packets.
399 if (nacks_left_ == 0)
400 return SEND_PACKET;
401
402 // Check if it's time for a new loss burst.
403 if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
404 packets_left_to_drop_ = kLossBurstSize;
405
406 if (packets_left_to_drop_ > 0) {
407 --packets_left_to_drop_;
408 dropped_packets_.insert(header.sequenceNumber);
409 return DROP_PACKET;
410 }
411
412 return SEND_PACKET;
413 }
414
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000415 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000416 RTCPUtility::RTCPParserV2 parser(packet, length, true);
417 EXPECT_TRUE(parser.IsValid());
418
419 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
420 while (packet_type != RTCPUtility::kRtcpNotValidCode) {
421 if (packet_type == RTCPUtility::kRtcpRtpfbNackCode) {
422 --nacks_left_;
423 break;
424 }
425 packet_type = parser.Iterate();
426 }
427 return SEND_PACKET;
428 }
429
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000430 void ModifyConfigs(VideoSendStream::Config* send_config,
431 std::vector<VideoReceiveStream::Config>* receive_configs,
432 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000433 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000434 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000435 }
436
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000437 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000438 EXPECT_EQ(kEventSignaled, Wait())
439 << "Timed out waiting for packets to be NACKed, retransmitted and "
440 "rendered.";
441 }
442
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000443 rtc::scoped_ptr<RtpHeaderParser> rtp_parser_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000444 std::set<uint16_t> dropped_packets_;
445 std::set<uint16_t> retransmitted_packets_;
446 uint64_t sent_rtp_packets_;
447 int packets_left_to_drop_;
448 int nacks_left_;
449 } test;
450
451 RunBaseTest(&test);
452}
453
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000454TEST_F(EndToEndTest, CanReceiveFec) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000455 class FecRenderObserver : public test::EndToEndTest, public VideoRenderer {
456 public:
457 FecRenderObserver()
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000458 : EndToEndTest(kDefaultTimeoutMs), state_(kFirstPacket) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000459
460 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000461 Action OnSendRtp(const uint8_t* packet, size_t length) override
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000462 EXCLUSIVE_LOCKS_REQUIRED(crit_) {
463 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000464 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000465
466 EXPECT_EQ(kRedPayloadType, header.payloadType);
467 int encapsulated_payload_type =
468 static_cast<int>(packet[header.headerLength]);
469 if (encapsulated_payload_type != kFakeSendPayloadType)
470 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
471
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000472 if (protected_sequence_numbers_.count(header.sequenceNumber) != 0) {
473 // Retransmitted packet, should not count.
474 protected_sequence_numbers_.erase(header.sequenceNumber);
475 EXPECT_GT(protected_timestamps_.count(header.timestamp), 0u);
476 protected_timestamps_.erase(header.timestamp);
477 return SEND_PACKET;
478 }
479
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000480 switch (state_) {
481 case kFirstPacket:
482 state_ = kDropEveryOtherPacketUntilFec;
483 break;
484 case kDropEveryOtherPacketUntilFec:
485 if (encapsulated_payload_type == kUlpfecPayloadType) {
486 state_ = kDropNextMediaPacket;
487 return SEND_PACKET;
488 }
489 if (header.sequenceNumber % 2 == 0)
490 return DROP_PACKET;
491 break;
492 case kDropNextMediaPacket:
493 if (encapsulated_payload_type == kFakeSendPayloadType) {
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000494 protected_sequence_numbers_.insert(header.sequenceNumber);
495 protected_timestamps_.insert(header.timestamp);
496 state_ = kDropEveryOtherPacketUntilFec;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000497 return DROP_PACKET;
498 }
499 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000500 }
501
502 return SEND_PACKET;
503 }
504
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000505 void RenderFrame(const I420VideoFrame& video_frame,
506 int time_to_render_ms) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000507 CriticalSectionScoped lock(crit_.get());
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000508 // Rendering frame with timestamp of packet that was dropped -> FEC
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000509 // protection worked.
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000510 if (protected_timestamps_.count(video_frame.timestamp()) != 0)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000511 observation_complete_->Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000512 }
513
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000514 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000515
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000516 enum {
517 kFirstPacket,
518 kDropEveryOtherPacketUntilFec,
519 kDropNextMediaPacket,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000520 } state_;
521
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000522 void ModifyConfigs(VideoSendStream::Config* send_config,
523 std::vector<VideoReceiveStream::Config>* receive_configs,
524 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000525 // TODO(pbos): Run this test with combined NACK/FEC enabled as well.
526 // int rtp_history_ms = 1000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000527 // (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000528 // send_config->rtp.nack.rtp_history_ms = rtp_history_ms;
529 send_config->rtp.fec.red_payload_type = kRedPayloadType;
530 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
531
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000532 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
533 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
534 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000535 }
536
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000537 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000538 EXPECT_EQ(kEventSignaled, Wait())
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000539 << "Timed out waiting for dropped frames frames to be rendered.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000540 }
541
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000542 std::set<uint32_t> protected_sequence_numbers_ GUARDED_BY(crit_);
543 std::set<uint32_t> protected_timestamps_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000544 } test;
545
546 RunBaseTest(&test);
547}
548
Henrik Kjellanderdb313b62015-04-02 08:45:41 +0200549// Flacky on all platforms. See webrtc:4328.
550TEST_F(EndToEndTest, DISABLED_ReceivedFecPacketsNotNacked) {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000551 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
552 // Configure some network delay.
553 const int kNetworkDelayMs = 50;
554 FakeNetworkPipe::Config config;
555 config.queue_delay_ms = kNetworkDelayMs;
556 TestReceivedFecPacketsNotNacked(config);
557}
558
559void EndToEndTest::TestReceivedFecPacketsNotNacked(
560 const FakeNetworkPipe::Config& config) {
561 class FecNackObserver : public test::EndToEndTest {
562 public:
563 explicit FecNackObserver(const FakeNetworkPipe::Config& config)
564 : EndToEndTest(kDefaultTimeoutMs, config),
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000565 state_(kFirstPacket),
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000566 fec_sequence_number_(0),
567 has_last_sequence_number_(false),
568 last_sequence_number_(0) {}
569
570 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000571 Action OnSendRtp(const uint8_t* packet, size_t length) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000572 RTPHeader header;
573 EXPECT_TRUE(parser_->Parse(packet, length, &header));
574 EXPECT_EQ(kRedPayloadType, header.payloadType);
575
576 int encapsulated_payload_type =
577 static_cast<int>(packet[header.headerLength]);
578 if (encapsulated_payload_type != kFakeSendPayloadType)
579 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
580
581 if (has_last_sequence_number_ &&
582 !IsNewerSequenceNumber(header.sequenceNumber,
583 last_sequence_number_)) {
584 // Drop retransmitted packets.
585 return DROP_PACKET;
586 }
587 last_sequence_number_ = header.sequenceNumber;
588 has_last_sequence_number_ = true;
589
590 bool fec_packet = encapsulated_payload_type == kUlpfecPayloadType;
591 switch (state_) {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000592 case kFirstPacket:
593 state_ = kDropEveryOtherPacketUntilFec;
594 break;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000595 case kDropEveryOtherPacketUntilFec:
596 if (fec_packet) {
597 state_ = kDropAllMediaPacketsUntilFec;
598 } else if (header.sequenceNumber % 2 == 0) {
599 return DROP_PACKET;
600 }
601 break;
602 case kDropAllMediaPacketsUntilFec:
603 if (!fec_packet)
604 return DROP_PACKET;
605 fec_sequence_number_ = header.sequenceNumber;
606 state_ = kVerifyFecPacketNotInNackList;
607 break;
608 case kVerifyFecPacketNotInNackList:
609 // Continue to drop packets. Make sure no frame can be decoded.
610 if (fec_packet || header.sequenceNumber % 2 == 0)
611 return DROP_PACKET;
612 break;
613 }
614 return SEND_PACKET;
615 }
616
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000617 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000618 if (state_ == kVerifyFecPacketNotInNackList) {
619 test::RtcpPacketParser rtcp_parser;
620 rtcp_parser.Parse(packet, length);
621 std::vector<uint16_t> nacks = rtcp_parser.nack_item()->last_nack_list();
622 if (!nacks.empty() &&
623 IsNewerSequenceNumber(nacks.back(), fec_sequence_number_)) {
624 EXPECT_TRUE(std::find(
625 nacks.begin(), nacks.end(), fec_sequence_number_) == nacks.end());
626 observation_complete_->Set();
627 }
628 }
629 return SEND_PACKET;
630 }
631
Stefan Holmere5904162015-03-26 11:11:06 +0100632 // TODO(holmer): Investigate why we don't send FEC packets when the bitrate
633 // is 10 kbps.
634 Call::Config GetSenderCallConfig() override {
635 Call::Config config(SendTransport());
636 const int kMinBitrateBps = 30000;
637 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
638 return config;
639 }
640
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000641 void ModifyConfigs(VideoSendStream::Config* send_config,
642 std::vector<VideoReceiveStream::Config>* receive_configs,
643 VideoEncoderConfig* encoder_config) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000644 // Configure hybrid NACK/FEC.
645 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
646 send_config->rtp.fec.red_payload_type = kRedPayloadType;
647 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
648 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
649 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
650 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
651 }
652
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000653 void PerformTest() override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000654 EXPECT_EQ(kEventSignaled, Wait())
655 << "Timed out while waiting for FEC packets to be received.";
656 }
657
658 enum {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000659 kFirstPacket,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000660 kDropEveryOtherPacketUntilFec,
661 kDropAllMediaPacketsUntilFec,
662 kVerifyFecPacketNotInNackList,
663 } state_;
664
665 uint16_t fec_sequence_number_;
666 bool has_last_sequence_number_;
667 uint16_t last_sequence_number_;
668 } test(config);
669
670 RunBaseTest(&test);
671}
672
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000673// This test drops second RTP packet with a marker bit set, makes sure it's
674// retransmitted and renders. Retransmission SSRCs are also checked.
Shao Changbine62202f2015-04-21 20:24:50 +0800675void EndToEndTest::DecodesRetransmittedFrame(bool use_rtx, bool use_red) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000676 static const int kDroppedFrameNumber = 2;
677 class RetransmissionObserver : public test::EndToEndTest,
678 public I420FrameCallback {
679 public:
Shao Changbine62202f2015-04-21 20:24:50 +0800680 explicit RetransmissionObserver(bool use_rtx, bool use_red)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000681 : EndToEndTest(kDefaultTimeoutMs),
Shao Changbine62202f2015-04-21 20:24:50 +0800682 payload_type_(GetPayloadType(false, use_red)),
683 retransmission_ssrc_(use_rtx ? kSendRtxSsrcs[0] : kSendSsrcs[0]),
684 retransmission_payload_type_(GetPayloadType(use_rtx, use_red)),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000685 marker_bits_observed_(0),
686 retransmitted_timestamp_(0),
687 frame_retransmitted_(false) {}
688
689 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000690 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000691 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000692 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000693
694 if (header.timestamp == retransmitted_timestamp_) {
695 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
696 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
697 frame_retransmitted_ = true;
698 return SEND_PACKET;
699 }
700
701 EXPECT_EQ(kSendSsrcs[0], header.ssrc);
Shao Changbine62202f2015-04-21 20:24:50 +0800702 EXPECT_EQ(payload_type_, header.payloadType);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000703
704 // Found the second frame's final packet, drop this and expect a
705 // retransmission.
706 if (header.markerBit && ++marker_bits_observed_ == kDroppedFrameNumber) {
707 retransmitted_timestamp_ = header.timestamp;
708 return DROP_PACKET;
709 }
710
711 return SEND_PACKET;
712 }
713
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000714 void FrameCallback(I420VideoFrame* frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000715 CriticalSectionScoped lock(crit_.get());
716 if (frame->timestamp() == retransmitted_timestamp_) {
717 EXPECT_TRUE(frame_retransmitted_);
718 observation_complete_->Set();
719 }
720 }
721
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000722 void ModifyConfigs(VideoSendStream::Config* send_config,
723 std::vector<VideoReceiveStream::Config>* receive_configs,
724 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000725 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000726 (*receive_configs)[0].pre_render_callback = this;
727 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
Shao Changbine62202f2015-04-21 20:24:50 +0800728
729 if (payload_type_ == kRedPayloadType) {
730 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
731 send_config->rtp.fec.red_payload_type = kRedPayloadType;
732 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
733 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
734 }
735
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000736 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
737 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000738 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Shao Changbine62202f2015-04-21 20:24:50 +0800739 (*receive_configs)[0].rtp.rtx[kFakeSendPayloadType].ssrc =
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000740 kSendRtxSsrcs[0];
Shao Changbine62202f2015-04-21 20:24:50 +0800741 (*receive_configs)[0].rtp.rtx[kFakeSendPayloadType].payload_type =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000742 kSendRtxPayloadType;
743 }
744 }
745
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000746 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000747 EXPECT_EQ(kEventSignaled, Wait())
748 << "Timed out while waiting for retransmission to render.";
749 }
750
Shao Changbine62202f2015-04-21 20:24:50 +0800751 int GetPayloadType(bool use_rtx, bool use_red) {
752 return use_rtx ? kSendRtxPayloadType
753 : (use_red ? kRedPayloadType : kFakeSendPayloadType);
754 }
755
756 const int payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000757 const uint32_t retransmission_ssrc_;
758 const int retransmission_payload_type_;
759 int marker_bits_observed_;
760 uint32_t retransmitted_timestamp_;
761 bool frame_retransmitted_;
Shao Changbine62202f2015-04-21 20:24:50 +0800762 } test(use_rtx, use_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000763
764 RunBaseTest(&test);
765}
766
767TEST_F(EndToEndTest, DecodesRetransmittedFrame) {
Shao Changbine62202f2015-04-21 20:24:50 +0800768 DecodesRetransmittedFrame(false, false);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000769}
770
771TEST_F(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +0800772 DecodesRetransmittedFrame(true, false);
773}
774
775TEST_F(EndToEndTest, DecodesRetransmittedFrameByRed) {
776 DecodesRetransmittedFrame(false, true);
777}
778
779TEST_F(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
780 DecodesRetransmittedFrame(true, true);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000781}
782
andresp@webrtc.org02686112014-09-19 08:24:19 +0000783TEST_F(EndToEndTest, UsesFrameCallbacks) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000784 static const int kWidth = 320;
785 static const int kHeight = 240;
786
787 class Renderer : public VideoRenderer {
788 public:
789 Renderer() : event_(EventWrapper::Create()) {}
790
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000791 void RenderFrame(const I420VideoFrame& video_frame,
792 int /*time_to_render_ms*/) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000793 EXPECT_EQ(0, *video_frame.buffer(kYPlane))
794 << "Rendered frame should have zero luma which is applied by the "
795 "pre-render callback.";
796 event_->Set();
797 }
798
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000799 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000800
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000801 EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000802 rtc::scoped_ptr<EventWrapper> event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000803 } renderer;
804
805 class TestFrameCallback : public I420FrameCallback {
806 public:
807 TestFrameCallback(int expected_luma_byte, int next_luma_byte)
808 : event_(EventWrapper::Create()),
809 expected_luma_byte_(expected_luma_byte),
810 next_luma_byte_(next_luma_byte) {}
811
812 EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
813
814 private:
815 virtual void FrameCallback(I420VideoFrame* frame) {
816 EXPECT_EQ(kWidth, frame->width())
817 << "Width not as expected, callback done before resize?";
818 EXPECT_EQ(kHeight, frame->height())
819 << "Height not as expected, callback done before resize?";
820
821 // Previous luma specified, observed luma should be fairly close.
822 if (expected_luma_byte_ != -1) {
823 EXPECT_NEAR(expected_luma_byte_, *frame->buffer(kYPlane), 10);
824 }
825
826 memset(frame->buffer(kYPlane),
827 next_luma_byte_,
828 frame->allocated_size(kYPlane));
829
830 event_->Set();
831 }
832
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000833 rtc::scoped_ptr<EventWrapper> event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000834 int expected_luma_byte_;
835 int next_luma_byte_;
836 };
837
838 TestFrameCallback pre_encode_callback(-1, 255); // Changes luma to 255.
839 TestFrameCallback pre_render_callback(255, 0); // Changes luma from 255 to 0.
840
841 test::DirectTransport sender_transport, receiver_transport;
842
843 CreateCalls(Call::Config(&sender_transport),
844 Call::Config(&receiver_transport));
845
846 sender_transport.SetReceiver(receiver_call_->Receiver());
847 receiver_transport.SetReceiver(sender_call_->Receiver());
848
849 CreateSendConfig(1);
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000850 rtc::scoped_ptr<VideoEncoder> encoder(
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +0000851 VideoEncoder::Create(VideoEncoder::kVp8));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000852 send_config_.encoder_settings.encoder = encoder.get();
853 send_config_.encoder_settings.payload_name = "VP8";
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000854 ASSERT_EQ(1u, encoder_config_.streams.size()) << "Test setup error.";
855 encoder_config_.streams[0].width = kWidth;
856 encoder_config_.streams[0].height = kHeight;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000857 send_config_.pre_encode_callback = &pre_encode_callback;
858
859 CreateMatchingReceiveConfigs();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000860 receive_configs_[0].pre_render_callback = &pre_render_callback;
861 receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000862
863 CreateStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000864 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000865
866 // Create frames that are smaller than the send width/height, this is done to
867 // check that the callbacks are done after processing video.
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000868 rtc::scoped_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000869 test::FrameGenerator::CreateChromaGenerator(kWidth / 2, kHeight / 2));
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +0000870 send_stream_->Input()->IncomingCapturedFrame(*frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000871
872 EXPECT_EQ(kEventSignaled, pre_encode_callback.Wait())
873 << "Timed out while waiting for pre-encode callback.";
874 EXPECT_EQ(kEventSignaled, pre_render_callback.Wait())
875 << "Timed out while waiting for pre-render callback.";
876 EXPECT_EQ(kEventSignaled, renderer.Wait())
877 << "Timed out while waiting for the frame to render.";
878
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000879 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000880
881 sender_transport.StopSending();
882 receiver_transport.StopSending();
883
884 DestroyStreams();
885}
886
887void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
888 static const int kPacketsToDrop = 1;
889
890 class PliObserver : public test::EndToEndTest, public VideoRenderer {
891 public:
892 explicit PliObserver(int rtp_history_ms)
893 : EndToEndTest(kLongTimeoutMs),
894 rtp_history_ms_(rtp_history_ms),
895 nack_enabled_(rtp_history_ms > 0),
896 highest_dropped_timestamp_(0),
897 frames_to_drop_(0),
898 received_pli_(false) {}
899
900 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000901 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000902 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000903 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000904
905 // Drop all retransmitted packets to force a PLI.
906 if (header.timestamp <= highest_dropped_timestamp_)
907 return DROP_PACKET;
908
909 if (frames_to_drop_ > 0) {
910 highest_dropped_timestamp_ = header.timestamp;
911 --frames_to_drop_;
912 return DROP_PACKET;
913 }
914
915 return SEND_PACKET;
916 }
917
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000918 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000919 RTCPUtility::RTCPParserV2 parser(packet, length, true);
920 EXPECT_TRUE(parser.IsValid());
921
922 for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
923 packet_type != RTCPUtility::kRtcpNotValidCode;
924 packet_type = parser.Iterate()) {
925 if (!nack_enabled_)
926 EXPECT_NE(packet_type, RTCPUtility::kRtcpRtpfbNackCode);
927
928 if (packet_type == RTCPUtility::kRtcpPsfbPliCode) {
929 received_pli_ = true;
930 break;
931 }
932 }
933 return SEND_PACKET;
934 }
935
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000936 void RenderFrame(const I420VideoFrame& video_frame,
937 int time_to_render_ms) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000938 CriticalSectionScoped lock(crit_.get());
939 if (received_pli_ &&
940 video_frame.timestamp() > highest_dropped_timestamp_) {
941 observation_complete_->Set();
942 }
943 if (!received_pli_)
944 frames_to_drop_ = kPacketsToDrop;
945 }
946
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000947 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000948
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000949 void ModifyConfigs(VideoSendStream::Config* send_config,
950 std::vector<VideoReceiveStream::Config>* receive_configs,
951 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000952 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000953 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
954 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000955 }
956
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000957 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000958 EXPECT_EQ(kEventSignaled, Wait()) << "Timed out waiting for PLI to be "
959 "received and a frame to be "
960 "rendered afterwards.";
961 }
962
963 int rtp_history_ms_;
964 bool nack_enabled_;
965 uint32_t highest_dropped_timestamp_;
966 int frames_to_drop_;
967 bool received_pli_;
968 } test(rtp_history_ms);
969
970 RunBaseTest(&test);
971}
972
973TEST_F(EndToEndTest, ReceivesPliAndRecoversWithNack) {
974 ReceivesPliAndRecovers(1000);
975}
976
977// TODO(pbos): Enable this when 2250 is resolved.
978TEST_F(EndToEndTest, DISABLED_ReceivesPliAndRecoversWithoutNack) {
979 ReceivesPliAndRecovers(0);
980}
981
982TEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
983 class PacketInputObserver : public PacketReceiver {
984 public:
985 explicit PacketInputObserver(PacketReceiver* receiver)
986 : receiver_(receiver), delivered_packet_(EventWrapper::Create()) {}
987
988 EventTypeWrapper Wait() {
989 return delivered_packet_->Wait(kDefaultTimeoutMs);
990 }
991
992 private:
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200993 DeliveryStatus DeliverPacket(MediaType media_type, const uint8_t* packet,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000994 size_t length) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000995 if (RtpHeaderParser::IsRtcp(packet, length)) {
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200996 return receiver_->DeliverPacket(media_type, packet, length);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000997 } else {
998 DeliveryStatus delivery_status =
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200999 receiver_->DeliverPacket(media_type, packet, length);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001000 EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
1001 delivered_packet_->Set();
1002 return delivery_status;
1003 }
1004 }
1005
1006 PacketReceiver* receiver_;
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001007 rtc::scoped_ptr<EventWrapper> delivered_packet_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001008 };
1009
1010 test::DirectTransport send_transport, receive_transport;
1011
1012 CreateCalls(Call::Config(&send_transport), Call::Config(&receive_transport));
1013 PacketInputObserver input_observer(receiver_call_->Receiver());
1014
1015 send_transport.SetReceiver(&input_observer);
1016 receive_transport.SetReceiver(sender_call_->Receiver());
1017
1018 CreateSendConfig(1);
1019 CreateMatchingReceiveConfigs();
1020
1021 CreateStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001022 CreateFrameGeneratorCapturer();
1023 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001024
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001025 receiver_call_->DestroyVideoReceiveStream(receive_streams_[0]);
1026 receive_streams_.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001027
1028 // Wait() waits for a received packet.
1029 EXPECT_EQ(kEventSignaled, input_observer.Wait());
1030
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001031 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001032
1033 DestroyStreams();
1034
1035 send_transport.StopSending();
1036 receive_transport.StopSending();
1037}
1038
1039void EndToEndTest::RespectsRtcpMode(newapi::RtcpMode rtcp_mode) {
1040 static const int kNumCompoundRtcpPacketsToObserve = 10;
1041 class RtcpModeObserver : public test::EndToEndTest {
1042 public:
1043 explicit RtcpModeObserver(newapi::RtcpMode rtcp_mode)
1044 : EndToEndTest(kDefaultTimeoutMs),
1045 rtcp_mode_(rtcp_mode),
1046 sent_rtp_(0),
1047 sent_rtcp_(0) {}
1048
1049 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001050 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001051 if (++sent_rtp_ % 3 == 0)
1052 return DROP_PACKET;
1053
1054 return SEND_PACKET;
1055 }
1056
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001057 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001058 ++sent_rtcp_;
1059 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1060 EXPECT_TRUE(parser.IsValid());
1061
1062 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1063 bool has_report_block = false;
1064 while (packet_type != RTCPUtility::kRtcpNotValidCode) {
1065 EXPECT_NE(RTCPUtility::kRtcpSrCode, packet_type);
1066 if (packet_type == RTCPUtility::kRtcpRrCode) {
1067 has_report_block = true;
1068 break;
1069 }
1070 packet_type = parser.Iterate();
1071 }
1072
1073 switch (rtcp_mode_) {
1074 case newapi::kRtcpCompound:
1075 if (!has_report_block) {
1076 ADD_FAILURE() << "Received RTCP packet without receiver report for "
1077 "kRtcpCompound.";
1078 observation_complete_->Set();
1079 }
1080
1081 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
1082 observation_complete_->Set();
1083
1084 break;
1085 case newapi::kRtcpReducedSize:
1086 if (!has_report_block)
1087 observation_complete_->Set();
1088 break;
1089 }
1090
1091 return SEND_PACKET;
1092 }
1093
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001094 void ModifyConfigs(VideoSendStream::Config* send_config,
1095 std::vector<VideoReceiveStream::Config>* receive_configs,
1096 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001097 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001098 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1099 (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001100 }
1101
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001102 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001103 EXPECT_EQ(kEventSignaled, Wait())
1104 << (rtcp_mode_ == newapi::kRtcpCompound
1105 ? "Timed out before observing enough compound packets."
1106 : "Timed out before receiving a non-compound RTCP packet.");
1107 }
1108
1109 newapi::RtcpMode rtcp_mode_;
1110 int sent_rtp_;
1111 int sent_rtcp_;
1112 } test(rtcp_mode);
1113
1114 RunBaseTest(&test);
1115}
1116
1117TEST_F(EndToEndTest, UsesRtcpCompoundMode) {
1118 RespectsRtcpMode(newapi::kRtcpCompound);
1119}
1120
1121TEST_F(EndToEndTest, UsesRtcpReducedSizeMode) {
1122 RespectsRtcpMode(newapi::kRtcpReducedSize);
1123}
1124
1125// Test sets up a Call multiple senders with different resolutions and SSRCs.
1126// Another is set up to receive all three of these with different renderers.
1127// Each renderer verifies that it receives the expected resolution, and as soon
1128// as every renderer has received a frame, the test finishes.
andresp@webrtc.org02686112014-09-19 08:24:19 +00001129TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001130 static const size_t kNumStreams = 3;
1131
1132 class VideoOutputObserver : public VideoRenderer {
1133 public:
1134 VideoOutputObserver(test::FrameGeneratorCapturer** capturer,
1135 int width,
1136 int height)
1137 : capturer_(capturer),
1138 width_(width),
1139 height_(height),
1140 done_(EventWrapper::Create()) {}
1141
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001142 void RenderFrame(const I420VideoFrame& video_frame,
1143 int time_to_render_ms) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001144 EXPECT_EQ(width_, video_frame.width());
1145 EXPECT_EQ(height_, video_frame.height());
1146 (*capturer_)->Stop();
1147 done_->Set();
1148 }
1149
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001150 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00001151
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001152 EventTypeWrapper Wait() { return done_->Wait(kDefaultTimeoutMs); }
1153
1154 private:
1155 test::FrameGeneratorCapturer** capturer_;
1156 int width_;
1157 int height_;
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001158 rtc::scoped_ptr<EventWrapper> done_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001159 };
1160
1161 struct {
1162 uint32_t ssrc;
1163 int width;
1164 int height;
1165 } codec_settings[kNumStreams] = {{1, 640, 480}, {2, 320, 240}, {3, 240, 160}};
1166
1167 test::DirectTransport sender_transport, receiver_transport;
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001168 rtc::scoped_ptr<Call> sender_call(
1169 Call::Create(Call::Config(&sender_transport)));
1170 rtc::scoped_ptr<Call> receiver_call(
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001171 Call::Create(Call::Config(&receiver_transport)));
1172 sender_transport.SetReceiver(receiver_call->Receiver());
1173 receiver_transport.SetReceiver(sender_call->Receiver());
1174
1175 VideoSendStream* send_streams[kNumStreams];
1176 VideoReceiveStream* receive_streams[kNumStreams];
1177
1178 VideoOutputObserver* observers[kNumStreams];
1179 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
1180
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001181 rtc::scoped_ptr<VideoEncoder> encoders[kNumStreams];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001182 for (size_t i = 0; i < kNumStreams; ++i)
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +00001183 encoders[i].reset(VideoEncoder::Create(VideoEncoder::kVp8));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001184
pbos@webrtc.org776e6f22014-10-29 15:28:39 +00001185 ScopedVector<VideoDecoder> allocated_decoders;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001186 for (size_t i = 0; i < kNumStreams; ++i) {
1187 uint32_t ssrc = codec_settings[i].ssrc;
1188 int width = codec_settings[i].width;
1189 int height = codec_settings[i].height;
1190 observers[i] = new VideoOutputObserver(&frame_generators[i], width, height);
1191
pbos@webrtc.orgbd249bc2014-07-07 04:45:15 +00001192 VideoSendStream::Config send_config;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001193 send_config.rtp.ssrcs.push_back(ssrc);
1194 send_config.encoder_settings.encoder = encoders[i].get();
1195 send_config.encoder_settings.payload_name = "VP8";
1196 send_config.encoder_settings.payload_type = 124;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001197 VideoEncoderConfig encoder_config;
1198 encoder_config.streams = test::CreateVideoStreams(1);
1199 VideoStream* stream = &encoder_config.streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001200 stream->width = width;
1201 stream->height = height;
1202 stream->max_framerate = 5;
1203 stream->min_bitrate_bps = stream->target_bitrate_bps =
1204 stream->max_bitrate_bps = 100000;
1205 send_streams[i] =
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001206 sender_call->CreateVideoSendStream(send_config, encoder_config);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001207 send_streams[i]->Start();
1208
pbos@webrtc.orgbd249bc2014-07-07 04:45:15 +00001209 VideoReceiveStream::Config receive_config;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001210 receive_config.renderer = observers[i];
1211 receive_config.rtp.remote_ssrc = ssrc;
1212 receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
pbos@webrtc.org776e6f22014-10-29 15:28:39 +00001213 VideoReceiveStream::Decoder decoder =
1214 test::CreateMatchingDecoder(send_config.encoder_settings);
1215 allocated_decoders.push_back(decoder.decoder);
1216 receive_config.decoders.push_back(decoder);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001217 receive_streams[i] =
1218 receiver_call->CreateVideoReceiveStream(receive_config);
1219 receive_streams[i]->Start();
1220
1221 frame_generators[i] = test::FrameGeneratorCapturer::Create(
1222 send_streams[i]->Input(), width, height, 30, Clock::GetRealTimeClock());
1223 frame_generators[i]->Start();
1224 }
1225
1226 for (size_t i = 0; i < kNumStreams; ++i) {
1227 EXPECT_EQ(kEventSignaled, observers[i]->Wait())
1228 << "Timed out while waiting for observer " << i << " to render.";
1229 }
1230
1231 for (size_t i = 0; i < kNumStreams; ++i) {
1232 frame_generators[i]->Stop();
1233 sender_call->DestroyVideoSendStream(send_streams[i]);
1234 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1235 delete frame_generators[i];
1236 delete observers[i];
1237 }
1238
1239 sender_transport.StopSending();
1240 receiver_transport.StopSending();
1241}
1242
1243TEST_F(EndToEndTest, ObserversEncodedFrames) {
1244 class EncodedFrameTestObserver : public EncodedFrameObserver {
1245 public:
1246 EncodedFrameTestObserver()
1247 : length_(0),
1248 frame_type_(kFrameEmpty),
1249 called_(EventWrapper::Create()) {}
1250 virtual ~EncodedFrameTestObserver() {}
1251
1252 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
1253 frame_type_ = encoded_frame.frame_type_;
1254 length_ = encoded_frame.length_;
1255 buffer_.reset(new uint8_t[length_]);
1256 memcpy(buffer_.get(), encoded_frame.data_, length_);
1257 called_->Set();
1258 }
1259
1260 EventTypeWrapper Wait() { return called_->Wait(kDefaultTimeoutMs); }
1261
1262 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
1263 ASSERT_EQ(length_, observer.length_)
1264 << "Observed frames are of different lengths.";
1265 EXPECT_EQ(frame_type_, observer.frame_type_)
1266 << "Observed frames have different frame types.";
1267 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
1268 << "Observed encoded frames have different content.";
1269 }
1270
1271 private:
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001272 rtc::scoped_ptr<uint8_t[]> buffer_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001273 size_t length_;
1274 FrameType frame_type_;
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001275 rtc::scoped_ptr<EventWrapper> called_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001276 };
1277
1278 EncodedFrameTestObserver post_encode_observer;
1279 EncodedFrameTestObserver pre_decode_observer;
1280
1281 test::DirectTransport sender_transport, receiver_transport;
1282
1283 CreateCalls(Call::Config(&sender_transport),
1284 Call::Config(&receiver_transport));
1285
1286 sender_transport.SetReceiver(receiver_call_->Receiver());
1287 receiver_transport.SetReceiver(sender_call_->Receiver());
1288
1289 CreateSendConfig(1);
1290 CreateMatchingReceiveConfigs();
1291 send_config_.post_encode_callback = &post_encode_observer;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001292 receive_configs_[0].pre_decode_callback = &pre_decode_observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001293
1294 CreateStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001295 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001296
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001297 rtc::scoped_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +00001298 test::FrameGenerator::CreateChromaGenerator(
1299 encoder_config_.streams[0].width, encoder_config_.streams[0].height));
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +00001300 send_stream_->Input()->IncomingCapturedFrame(*frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001301
1302 EXPECT_EQ(kEventSignaled, post_encode_observer.Wait())
1303 << "Timed out while waiting for send-side encoded-frame callback.";
1304
1305 EXPECT_EQ(kEventSignaled, pre_decode_observer.Wait())
1306 << "Timed out while waiting for pre-decode encoded-frame callback.";
1307
1308 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
1309
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001310 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001311
1312 sender_transport.StopSending();
1313 receiver_transport.StopSending();
1314
1315 DestroyStreams();
1316}
1317
1318TEST_F(EndToEndTest, ReceiveStreamSendsRemb) {
1319 class RembObserver : public test::EndToEndTest {
1320 public:
1321 RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
1322
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001323 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001324 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1325 EXPECT_TRUE(parser.IsValid());
1326
1327 bool received_psfb = false;
1328 bool received_remb = false;
1329 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1330 while (packet_type != RTCPUtility::kRtcpNotValidCode) {
1331 if (packet_type == RTCPUtility::kRtcpPsfbRembCode) {
1332 const RTCPUtility::RTCPPacket& packet = parser.Packet();
1333 EXPECT_EQ(packet.PSFBAPP.SenderSSRC, kReceiverLocalSsrc);
1334 received_psfb = true;
1335 } else if (packet_type == RTCPUtility::kRtcpPsfbRembItemCode) {
1336 const RTCPUtility::RTCPPacket& packet = parser.Packet();
1337 EXPECT_GT(packet.REMBItem.BitRate, 0u);
1338 EXPECT_EQ(packet.REMBItem.NumberOfSSRCs, 1u);
1339 EXPECT_EQ(packet.REMBItem.SSRCs[0], kSendSsrcs[0]);
1340 received_remb = true;
1341 }
1342 packet_type = parser.Iterate();
1343 }
1344 if (received_psfb && received_remb)
1345 observation_complete_->Set();
1346 return SEND_PACKET;
1347 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001348 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001349 EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for a "
1350 "receiver RTCP REMB packet to be "
1351 "sent.";
1352 }
1353 } test;
1354
1355 RunBaseTest(&test);
1356}
1357
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001358TEST_F(EndToEndTest, VerifyBandwidthStats) {
1359 class RtcpObserver : public test::EndToEndTest, public PacketReceiver {
1360 public:
1361 RtcpObserver()
1362 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001363 sender_call_(nullptr),
1364 receiver_call_(nullptr),
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001365 has_seen_pacer_delay_(false) {}
1366
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +02001367 DeliveryStatus DeliverPacket(MediaType media_type, const uint8_t* packet,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001368 size_t length) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001369 Call::Stats sender_stats = sender_call_->GetStats();
1370 Call::Stats receiver_stats = receiver_call_->GetStats();
1371 if (!has_seen_pacer_delay_)
1372 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
1373 if (sender_stats.send_bandwidth_bps > 0 &&
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001374 receiver_stats.recv_bandwidth_bps > 0 && has_seen_pacer_delay_) {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001375 observation_complete_->Set();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001376 }
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +02001377 return receiver_call_->Receiver()->DeliverPacket(media_type, packet,
1378 length);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001379 }
1380
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001381 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001382 sender_call_ = sender_call;
1383 receiver_call_ = receiver_call;
1384 }
1385
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001386 void PerformTest() override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001387 EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for "
1388 "non-zero bandwidth stats.";
1389 }
1390
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001391 void SetReceivers(PacketReceiver* send_transport_receiver,
1392 PacketReceiver* receive_transport_receiver) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001393 test::RtpRtcpObserver::SetReceivers(this, receive_transport_receiver);
1394 }
1395
1396 private:
1397 Call* sender_call_;
1398 Call* receiver_call_;
1399 bool has_seen_pacer_delay_;
1400 } test;
1401
1402 RunBaseTest(&test);
1403}
1404
Åsa Persson352b2d72015-04-15 18:00:40 +02001405TEST_F(EndToEndTest, VerifyNackStats) {
1406 static const int kPacketNumberToDrop = 200;
1407 class NackObserver : public test::EndToEndTest {
1408 public:
1409 NackObserver()
1410 : EndToEndTest(kLongTimeoutMs),
1411 sent_rtp_packets_(0),
1412 dropped_rtp_packet_(0),
1413 dropped_rtp_packet_requested_(false),
1414 send_stream_(nullptr),
1415 start_runtime_ms_(-1) {}
1416
1417 private:
1418 Action OnSendRtp(const uint8_t* packet, size_t length) override {
1419 if (++sent_rtp_packets_ == kPacketNumberToDrop) {
1420 rtc::scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
1421 RTPHeader header;
1422 EXPECT_TRUE(parser->Parse(packet, length, &header));
1423 dropped_rtp_packet_ = header.sequenceNumber;
1424 return DROP_PACKET;
1425 }
1426 VerifyStats();
1427 return SEND_PACKET;
1428 }
1429
1430 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
1431 test::RtcpPacketParser rtcp_parser;
1432 rtcp_parser.Parse(packet, length);
1433 std::vector<uint16_t> nacks = rtcp_parser.nack_item()->last_nack_list();
1434 if (!nacks.empty() && std::find(
1435 nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) {
1436 dropped_rtp_packet_requested_ = true;
1437 }
1438 return SEND_PACKET;
1439 }
1440
1441 void VerifyStats() {
1442 if (!dropped_rtp_packet_requested_)
1443 return;
1444 int send_stream_nack_packets = 0;
1445 int receive_stream_nack_packets = 0;
1446 VideoSendStream::Stats stats = send_stream_->GetStats();
1447 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
1448 stats.substreams.begin(); it != stats.substreams.end(); ++it) {
1449 const VideoSendStream::StreamStats& stream_stats = it->second;
1450 send_stream_nack_packets +=
1451 stream_stats.rtcp_packet_type_counts.nack_packets;
1452 }
1453 for (size_t i = 0; i < receive_streams_.size(); ++i) {
1454 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
1455 receive_stream_nack_packets +=
1456 stats.rtcp_packet_type_counts.nack_packets;
1457 }
1458 if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) {
1459 // NACK packet sent on receive stream and received on sent stream.
1460 if (MinMetricRunTimePassed())
1461 observation_complete_->Set();
1462 }
1463 }
1464
1465 bool MinMetricRunTimePassed() {
1466 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
1467 if (start_runtime_ms_ == -1) {
1468 start_runtime_ms_ = now;
1469 return false;
1470 }
1471 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
1472 return elapsed_sec > metrics::kMinRunTimeInSeconds;
1473 }
1474
1475 void ModifyConfigs(VideoSendStream::Config* send_config,
1476 std::vector<VideoReceiveStream::Config>* receive_configs,
1477 VideoEncoderConfig* encoder_config) override {
1478 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1479 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1480 }
1481
1482 void OnStreamsCreated(
1483 VideoSendStream* send_stream,
1484 const std::vector<VideoReceiveStream*>& receive_streams) override {
1485 send_stream_ = send_stream;
1486 receive_streams_ = receive_streams;
1487 }
1488
1489 void PerformTest() override {
1490 EXPECT_EQ(kEventSignaled, Wait())
1491 << "Timed out waiting for packet to be NACKed.";
1492 }
1493
1494 uint64_t sent_rtp_packets_;
1495 uint16_t dropped_rtp_packet_;
1496 bool dropped_rtp_packet_requested_;
1497 std::vector<VideoReceiveStream*> receive_streams_;
1498 VideoSendStream* send_stream_;
1499 int64_t start_runtime_ms_;
1500 } test;
1501
Åsa Persson3c391cb2015-04-27 10:09:49 +02001502 test::ClearHistograms();
Åsa Persson352b2d72015-04-15 18:00:40 +02001503 RunBaseTest(&test);
1504
Åsa Persson3c391cb2015-04-27 10:09:49 +02001505 EXPECT_EQ(1, test::NumHistogramSamples(
Åsa Persson352b2d72015-04-15 18:00:40 +02001506 "WebRTC.Video.UniqueNackRequestsSentInPercent"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02001507 EXPECT_EQ(1, test::NumHistogramSamples(
Åsa Persson352b2d72015-04-15 18:00:40 +02001508 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
1509 EXPECT_GT(test::LastHistogramSample(
1510 "WebRTC.Video.NackPacketsSentPerMinute"), 0);
1511 EXPECT_GT(test::LastHistogramSample(
1512 "WebRTC.Video.NackPacketsReceivedPerMinute"), 0);
1513}
1514
Åsa Persson3c391cb2015-04-27 10:09:49 +02001515void EndToEndTest::VerifyHistogramStats(bool use_rtx, bool use_red) {
1516 class StatsObserver : public test::EndToEndTest, public PacketReceiver {
1517 public:
1518 StatsObserver(bool use_rtx, bool use_red)
1519 : EndToEndTest(kLongTimeoutMs),
1520 use_rtx_(use_rtx),
1521 use_red_(use_red),
1522 sender_call_(nullptr),
1523 receiver_call_(nullptr),
1524 start_runtime_ms_(-1) {}
1525
1526 private:
1527 Action OnSendRtp(const uint8_t* packet, size_t length) override {
1528 if (MinMetricRunTimePassed())
1529 observation_complete_->Set();
1530
1531 return SEND_PACKET;
1532 }
1533
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +02001534 DeliveryStatus DeliverPacket(MediaType media_type, const uint8_t* packet,
Åsa Persson3c391cb2015-04-27 10:09:49 +02001535 size_t length) override {
1536 // GetStats calls GetSendChannelRtcpStatistics
1537 // (via VideoSendStream::GetRtt) which updates ReportBlockStats used by
1538 // WebRTC.Video.SentPacketsLostInPercent.
1539 // TODO(asapersson): Remove dependency on calling GetStats.
1540 sender_call_->GetStats();
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +02001541 return receiver_call_->Receiver()->DeliverPacket(media_type, packet,
1542 length);
Åsa Persson3c391cb2015-04-27 10:09:49 +02001543 }
1544
1545 bool MinMetricRunTimePassed() {
1546 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
1547 if (start_runtime_ms_ == -1) {
1548 start_runtime_ms_ = now;
1549 return false;
1550 }
1551 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
1552 return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
1553 }
1554
1555 void ModifyConfigs(VideoSendStream::Config* send_config,
1556 std::vector<VideoReceiveStream::Config>* receive_configs,
1557 VideoEncoderConfig* encoder_config) override {
1558 // NACK
1559 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1560 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1561 // FEC
1562 if (use_red_) {
1563 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
1564 send_config->rtp.fec.red_payload_type = kRedPayloadType;
1565 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
1566 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
1567 }
1568 // RTX
1569 if (use_rtx_) {
1570 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
1571 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
1572 (*receive_configs)[0].rtp.rtx[kFakeSendPayloadType].ssrc =
1573 kSendRtxSsrcs[0];
1574 (*receive_configs)[0].rtp.rtx[kFakeSendPayloadType].payload_type =
1575 kSendRtxPayloadType;
1576 }
1577 }
1578
1579 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1580 sender_call_ = sender_call;
1581 receiver_call_ = receiver_call;
1582 }
1583
1584 void SetReceivers(PacketReceiver* send_transport_receiver,
1585 PacketReceiver* receive_transport_receiver) override {
1586 test::RtpRtcpObserver::SetReceivers(this, receive_transport_receiver);
1587 }
1588
1589 void PerformTest() override {
1590 EXPECT_EQ(kEventSignaled, Wait())
1591 << "Timed out waiting for packet to be NACKed.";
1592 }
1593
1594 bool use_rtx_;
1595 bool use_red_;
1596 Call* sender_call_;
1597 Call* receiver_call_;
1598 int64_t start_runtime_ms_;
1599 } test(use_rtx, use_red);
1600
1601 test::ClearHistograms();
1602 RunBaseTest(&test);
1603
1604 // Verify that stats have been updated once.
1605 EXPECT_EQ(1, test::NumHistogramSamples(
1606 "WebRTC.Video.NackPacketsSentPerMinute"));
1607 EXPECT_EQ(1, test::NumHistogramSamples(
1608 "WebRTC.Video.NackPacketsReceivedPerMinute"));
1609 EXPECT_EQ(1, test::NumHistogramSamples(
1610 "WebRTC.Video.FirPacketsSentPerMinute"));
1611 EXPECT_EQ(1, test::NumHistogramSamples(
1612 "WebRTC.Video.FirPacketsReceivedPerMinute"));
1613 EXPECT_EQ(1, test::NumHistogramSamples(
1614 "WebRTC.Video.PliPacketsSentPerMinute"));
1615 EXPECT_EQ(1, test::NumHistogramSamples(
1616 "WebRTC.Video.PliPacketsReceivedPerMinute"));
1617
1618 EXPECT_EQ(1, test::NumHistogramSamples(
1619 "WebRTC.Video.KeyFramesSentInPermille"));
1620 EXPECT_EQ(1, test::NumHistogramSamples(
1621 "WebRTC.Video.KeyFramesReceivedInPermille"));
1622
1623 EXPECT_EQ(1, test::NumHistogramSamples(
1624 "WebRTC.Video.SentPacketsLostInPercent"));
1625 EXPECT_EQ(1, test::NumHistogramSamples(
1626 "WebRTC.Video.ReceivedPacketsLostInPercent"));
1627
1628 EXPECT_EQ(1, test::NumHistogramSamples(
1629 "WebRTC.Video.DecodedFramesPerSecond"));
1630
1631 EXPECT_EQ(1, test::NumHistogramSamples(
1632 "WebRTC.Video.BitrateSentInKbps"));
1633 EXPECT_EQ(1, test::NumHistogramSamples(
1634 "WebRTC.Video.BitrateReceivedInKbps"));
1635 EXPECT_EQ(1, test::NumHistogramSamples(
1636 "WebRTC.Video.MediaBitrateSentInKbps"));
1637 EXPECT_EQ(1, test::NumHistogramSamples(
1638 "WebRTC.Video.MediaBitrateReceivedInKbps"));
1639 EXPECT_EQ(1, test::NumHistogramSamples(
1640 "WebRTC.Video.PaddingBitrateSentInKbps"));
1641 EXPECT_EQ(1, test::NumHistogramSamples(
1642 "WebRTC.Video.PaddingBitrateReceivedInKbps"));
1643 EXPECT_EQ(1, test::NumHistogramSamples(
1644 "WebRTC.Video.RetransmittedBitrateSentInKbps"));
1645 EXPECT_EQ(1, test::NumHistogramSamples(
1646 "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
1647
1648 int num_rtx_samples = use_rtx ? 1 : 0;
1649 EXPECT_EQ(num_rtx_samples, test::NumHistogramSamples(
1650 "WebRTC.Video.RtxBitrateSentInKbps"));
1651 EXPECT_EQ(num_rtx_samples, test::NumHistogramSamples(
1652 "WebRTC.Video.RtxBitrateReceivedInKbps"));
1653
1654 int num_red_samples = use_red ? 1 : 0;
1655 EXPECT_EQ(num_red_samples, test::NumHistogramSamples(
1656 "WebRTC.Video.FecBitrateSentInKbps"));
1657 EXPECT_EQ(num_red_samples, test::NumHistogramSamples(
1658 "WebRTC.Video.FecBitrateReceivedInKbps"));
1659 EXPECT_EQ(num_red_samples, test::NumHistogramSamples(
1660 "WebRTC.Video.ReceivedFecPacketsInPercent"));
1661}
1662
1663TEST_F(EndToEndTest, VerifyHistogramStatsWithRtx) {
1664 const bool kEnabledRtx = true;
1665 const bool kEnabledRed = false;
1666 VerifyHistogramStats(kEnabledRtx, kEnabledRed);
1667}
1668
1669TEST_F(EndToEndTest, VerifyHistogramStatsWithRed) {
1670 const bool kEnabledRtx = false;
1671 const bool kEnabledRed = true;
1672 VerifyHistogramStats(kEnabledRtx, kEnabledRed);
1673}
1674
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001675void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
1676 static const int kNumRtcpReportPacketsToObserve = 5;
1677 class RtcpXrObserver : public test::EndToEndTest {
1678 public:
1679 explicit RtcpXrObserver(bool enable_rrtr)
1680 : EndToEndTest(kDefaultTimeoutMs),
1681 enable_rrtr_(enable_rrtr),
1682 sent_rtcp_sr_(0),
1683 sent_rtcp_rr_(0),
1684 sent_rtcp_rrtr_(0),
1685 sent_rtcp_dlrr_(0) {}
1686
1687 private:
1688 // Receive stream should send RR packets (and RRTR packets if enabled).
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001689 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001690 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1691 EXPECT_TRUE(parser.IsValid());
1692
1693 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1694 while (packet_type != RTCPUtility::kRtcpNotValidCode) {
1695 if (packet_type == RTCPUtility::kRtcpRrCode) {
1696 ++sent_rtcp_rr_;
1697 } else if (packet_type ==
1698 RTCPUtility::kRtcpXrReceiverReferenceTimeCode) {
1699 ++sent_rtcp_rrtr_;
1700 }
1701 EXPECT_NE(packet_type, RTCPUtility::kRtcpSrCode);
1702 EXPECT_NE(packet_type, RTCPUtility::kRtcpXrDlrrReportBlockItemCode);
1703 packet_type = parser.Iterate();
1704 }
1705 return SEND_PACKET;
1706 }
1707 // Send stream should send SR packets (and DLRR packets if enabled).
1708 virtual Action OnSendRtcp(const uint8_t* packet, size_t length) {
1709 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1710 EXPECT_TRUE(parser.IsValid());
1711
1712 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1713 while (packet_type != RTCPUtility::kRtcpNotValidCode) {
1714 if (packet_type == RTCPUtility::kRtcpSrCode) {
1715 ++sent_rtcp_sr_;
1716 } else if (packet_type == RTCPUtility::kRtcpXrDlrrReportBlockItemCode) {
1717 ++sent_rtcp_dlrr_;
1718 }
1719 EXPECT_NE(packet_type, RTCPUtility::kRtcpXrReceiverReferenceTimeCode);
1720 packet_type = parser.Iterate();
1721 }
1722 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
1723 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve) {
1724 if (enable_rrtr_) {
1725 EXPECT_GT(sent_rtcp_rrtr_, 0);
1726 EXPECT_GT(sent_rtcp_dlrr_, 0);
1727 } else {
1728 EXPECT_EQ(0, sent_rtcp_rrtr_);
1729 EXPECT_EQ(0, sent_rtcp_dlrr_);
1730 }
1731 observation_complete_->Set();
1732 }
1733 return SEND_PACKET;
1734 }
1735
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001736 void ModifyConfigs(VideoSendStream::Config* send_config,
1737 std::vector<VideoReceiveStream::Config>* receive_configs,
1738 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001739 (*receive_configs)[0].rtp.rtcp_mode = newapi::kRtcpReducedSize;
1740 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
1741 enable_rrtr_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001742 }
1743
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001744 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001745 EXPECT_EQ(kEventSignaled, Wait())
1746 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
1747 }
1748
1749 bool enable_rrtr_;
1750 int sent_rtcp_sr_;
1751 int sent_rtcp_rr_;
1752 int sent_rtcp_rrtr_;
1753 int sent_rtcp_dlrr_;
1754 } test(enable_rrtr);
1755
1756 RunBaseTest(&test);
1757}
1758
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001759void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
1760 bool send_single_ssrc_first) {
1761 class SendsSetSsrcs : public test::EndToEndTest {
1762 public:
1763 SendsSetSsrcs(const uint32_t* ssrcs,
1764 size_t num_ssrcs,
1765 bool send_single_ssrc_first)
1766 : EndToEndTest(kDefaultTimeoutMs),
1767 num_ssrcs_(num_ssrcs),
1768 send_single_ssrc_first_(send_single_ssrc_first),
1769 ssrcs_to_observe_(num_ssrcs),
1770 expect_single_ssrc_(send_single_ssrc_first) {
1771 for (size_t i = 0; i < num_ssrcs; ++i)
1772 valid_ssrcs_[ssrcs[i]] = true;
1773 }
1774
1775 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001776 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001777 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001778 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001779
1780 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
1781 << "Received unknown SSRC: " << header.ssrc;
1782
1783 if (!valid_ssrcs_[header.ssrc])
1784 observation_complete_->Set();
1785
1786 if (!is_observed_[header.ssrc]) {
1787 is_observed_[header.ssrc] = true;
1788 --ssrcs_to_observe_;
1789 if (expect_single_ssrc_) {
1790 expect_single_ssrc_ = false;
1791 observation_complete_->Set();
1792 }
1793 }
1794
1795 if (ssrcs_to_observe_ == 0)
1796 observation_complete_->Set();
1797
1798 return SEND_PACKET;
1799 }
1800
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001801 size_t GetNumStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001802
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001803 void ModifyConfigs(VideoSendStream::Config* send_config,
1804 std::vector<VideoReceiveStream::Config>* receive_configs,
1805 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001806 if (num_ssrcs_ > 1) {
1807 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001808 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
1809 encoder_config->streams[i].min_bitrate_bps = 10000;
1810 encoder_config->streams[i].target_bitrate_bps = 15000;
1811 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001812 }
1813 }
1814
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001815 encoder_config_all_streams_ = *encoder_config;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001816 if (send_single_ssrc_first_)
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001817 encoder_config->streams.resize(1);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001818 }
1819
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001820 void OnStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001821 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00001822 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001823 send_stream_ = send_stream;
1824 }
1825
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001826 void PerformTest() override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001827 EXPECT_EQ(kEventSignaled, Wait())
1828 << "Timed out while waiting for "
1829 << (send_single_ssrc_first_ ? "first SSRC." : "SSRCs.");
1830
1831 if (send_single_ssrc_first_) {
1832 // Set full simulcast and continue with the rest of the SSRCs.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001833 send_stream_->ReconfigureVideoEncoder(encoder_config_all_streams_);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001834 EXPECT_EQ(kEventSignaled, Wait())
1835 << "Timed out while waiting on additional SSRCs.";
1836 }
1837 }
1838
1839 private:
1840 std::map<uint32_t, bool> valid_ssrcs_;
1841 std::map<uint32_t, bool> is_observed_;
1842
1843 const size_t num_ssrcs_;
1844 const bool send_single_ssrc_first_;
1845
1846 size_t ssrcs_to_observe_;
1847 bool expect_single_ssrc_;
1848
1849 VideoSendStream* send_stream_;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001850 VideoEncoderConfig encoder_config_all_streams_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001851 } test(kSendSsrcs, num_ssrcs, send_single_ssrc_first);
1852
1853 RunBaseTest(&test);
1854}
1855
pbos@webrtc.org891d4832015-02-26 13:15:22 +00001856TEST_F(EndToEndTest, ReportsSetEncoderRates) {
1857 class EncoderRateStatsTest : public test::EndToEndTest,
1858 public test::FakeEncoder {
1859 public:
1860 EncoderRateStatsTest()
1861 : EndToEndTest(kDefaultTimeoutMs),
1862 FakeEncoder(Clock::GetRealTimeClock()) {}
1863
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001864 void OnStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00001865 VideoSendStream* send_stream,
1866 const std::vector<VideoReceiveStream*>& receive_streams) override {
1867 send_stream_ = send_stream;
1868 }
1869
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001870 void ModifyConfigs(VideoSendStream::Config* send_config,
1871 std::vector<VideoReceiveStream::Config>* receive_configs,
1872 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00001873 send_config->encoder_settings.encoder = this;
1874 }
1875
1876 int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override {
1877 // Make sure not to trigger on any default zero bitrates.
1878 if (new_target_bitrate == 0)
1879 return 0;
1880 CriticalSectionScoped lock(crit_.get());
1881 bitrate_kbps_ = new_target_bitrate;
1882 observation_complete_->Set();
1883 return 0;
1884 }
1885
1886 void PerformTest() override {
1887 ASSERT_EQ(kEventSignaled, Wait())
1888 << "Timed out while waiting for encoder SetRates() call.";
1889 // Wait for GetStats to report a corresponding bitrate.
1890 for (unsigned int i = 0; i < kDefaultTimeoutMs; ++i) {
1891 VideoSendStream::Stats stats = send_stream_->GetStats();
1892 {
1893 CriticalSectionScoped lock(crit_.get());
1894 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
1895 static_cast<int>(bitrate_kbps_)) {
1896 return;
1897 }
1898 }
1899 SleepMs(1);
1900 }
1901 FAIL()
1902 << "Timed out waiting for stats reporting the currently set bitrate.";
1903 }
1904
1905 private:
1906 VideoSendStream* send_stream_;
1907 uint32_t bitrate_kbps_ GUARDED_BY(crit_);
1908 } test;
1909
1910 RunBaseTest(&test);
1911}
1912
pbos@webrtc.orgba253472014-11-25 09:39:04 +00001913TEST_F(EndToEndTest, GetStats) {
1914 static const int kStartBitrateBps = 3000000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001915 class StatsObserver : public test::EndToEndTest, public I420FrameCallback {
1916 public:
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001917 explicit StatsObserver(const FakeNetworkPipe::Config& config)
1918 : EndToEndTest(kLongTimeoutMs, config),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001919 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001920 expected_send_ssrcs_(),
1921 check_stats_event_(EventWrapper::Create()) {}
1922
1923 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001924 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001925 check_stats_event_->Set();
1926 return SEND_PACKET;
1927 }
1928
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001929 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001930 check_stats_event_->Set();
1931 return SEND_PACKET;
1932 }
1933
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001934 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001935 check_stats_event_->Set();
1936 return SEND_PACKET;
1937 }
1938
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001939 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001940 check_stats_event_->Set();
1941 return SEND_PACKET;
1942 }
1943
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001944 void FrameCallback(I420VideoFrame* video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001945 // Ensure that we have at least 5ms send side delay.
1946 int64_t render_time = video_frame->render_time_ms();
1947 if (render_time > 0)
1948 video_frame->set_render_time_ms(render_time - 5);
1949 }
1950
1951 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001952 for (size_t i = 0; i < receive_streams_.size(); ++i) {
1953 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
1954 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001955
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001956 // Make sure all fields have been populated.
1957 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
1958 // always filled for all receivers.
1959 receive_stats_filled_["IncomingRate"] |=
1960 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001961
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001962 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001963
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001964 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001965
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001966 receive_stats_filled_["StatisticsUpdated"] |=
1967 stats.rtcp_stats.cumulative_lost != 0 ||
1968 stats.rtcp_stats.extended_max_sequence_number != 0 ||
1969 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001970
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001971 receive_stats_filled_["DataCountersUpdated"] |=
1972 stats.rtp_stats.transmitted.payload_bytes != 0 ||
1973 stats.rtp_stats.fec.packets != 0 ||
1974 stats.rtp_stats.transmitted.header_bytes != 0 ||
1975 stats.rtp_stats.transmitted.packets != 0 ||
1976 stats.rtp_stats.transmitted.padding_bytes != 0 ||
1977 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001978
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001979 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001980 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001981
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001982 receive_stats_filled_["FrameCounts"] |=
1983 stats.frame_counts.key_frames != 0 ||
1984 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00001985
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001986 receive_stats_filled_["CName"] |= stats.c_name != "";
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00001987
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001988 receive_stats_filled_["RtcpPacketTypeCount"] |=
1989 stats.rtcp_packet_type_counts.fir_packets != 0 ||
1990 stats.rtcp_packet_type_counts.nack_packets != 0 ||
1991 stats.rtcp_packet_type_counts.pli_packets != 0 ||
1992 stats.rtcp_packet_type_counts.nack_requests != 0 ||
1993 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
1994 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001995
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001996 return AllStatsFilled(receive_stats_filled_);
1997 }
1998
1999 bool CheckSendStats() {
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002000 DCHECK(send_stream_ != nullptr);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002001 VideoSendStream::Stats stats = send_stream_->GetStats();
2002
2003 send_stats_filled_["NumStreams"] |=
2004 stats.substreams.size() == expected_send_ssrcs_.size();
2005
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002006 send_stats_filled_["CpuOveruseMetrics"] |=
2007 stats.avg_encode_time_ms != 0 || stats.encode_usage_percent != 0;
2008
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002009 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002010 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002011 it != stats.substreams.end(); ++it) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002012 EXPECT_TRUE(expected_send_ssrcs_.find(it->first) !=
2013 expected_send_ssrcs_.end());
2014
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002015 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002016 stats.input_frame_rate != 0;
2017
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002018 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002019
2020 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
2021 stream_stats.rtcp_stats.cumulative_lost != 0 ||
2022 stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
2023 stream_stats.rtcp_stats.fraction_lost != 0;
2024
2025 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002026 stream_stats.rtp_stats.fec.packets != 0 ||
2027 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
2028 stream_stats.rtp_stats.retransmitted.packets != 0 ||
2029 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002030
2031 send_stats_filled_[CompoundKey("BitrateStatisticsObserver",
2032 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002033 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002034
2035 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002036 stream_stats.frame_counts.delta_frames != 0 ||
2037 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002038
2039 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
2040 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00002041
2042 send_stats_filled_[CompoundKey("Delay", it->first)] |=
2043 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002044
2045 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
2046 // report dropped packets.
2047 send_stats_filled_["RtcpPacketTypeCount"] |=
2048 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
2049 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
2050 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
2051 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
2052 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002053 }
2054
2055 return AllStatsFilled(send_stats_filled_);
2056 }
2057
2058 std::string CompoundKey(const char* name, uint32_t ssrc) {
2059 std::ostringstream oss;
2060 oss << name << "_" << ssrc;
2061 return oss.str();
2062 }
2063
2064 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
2065 for (std::map<std::string, bool>::const_iterator it = stats_map.begin();
2066 it != stats_map.end();
2067 ++it) {
2068 if (!it->second)
2069 return false;
2070 }
2071 return true;
2072 }
2073
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002074 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002075 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01002076 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002077 return config;
2078 }
2079
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002080 void ModifyConfigs(VideoSendStream::Config* send_config,
2081 std::vector<VideoReceiveStream::Config>* receive_configs,
2082 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002083 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002084 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002085
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002086 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002087 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002088 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002089 expected_receive_ssrcs_.push_back(
2090 (*receive_configs)[i].rtp.remote_ssrc);
2091 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002092 }
2093
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002094 size_t GetNumStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00002095
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002096 void OnStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002097 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002098 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002099 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002100 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002101 }
2102
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002103 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002104 Clock* clock = Clock::GetRealTimeClock();
2105 int64_t now = clock->TimeInMilliseconds();
2106 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
2107 bool receive_ok = false;
2108 bool send_ok = false;
2109
2110 while (now < stop_time) {
2111 if (!receive_ok)
2112 receive_ok = CheckReceiveStats();
2113 if (!send_ok)
2114 send_ok = CheckSendStats();
2115
2116 if (receive_ok && send_ok)
2117 return;
2118
2119 int64_t time_until_timout_ = stop_time - now;
2120 if (time_until_timout_ > 0)
2121 check_stats_event_->Wait(time_until_timout_);
2122 now = clock->TimeInMilliseconds();
2123 }
2124
2125 ADD_FAILURE() << "Timed out waiting for filled stats.";
2126 for (std::map<std::string, bool>::const_iterator it =
2127 receive_stats_filled_.begin();
2128 it != receive_stats_filled_.end();
2129 ++it) {
2130 if (!it->second) {
2131 ADD_FAILURE() << "Missing receive stats: " << it->first;
2132 }
2133 }
2134
2135 for (std::map<std::string, bool>::const_iterator it =
2136 send_stats_filled_.begin();
2137 it != send_stats_filled_.end();
2138 ++it) {
2139 if (!it->second) {
2140 ADD_FAILURE() << "Missing send stats: " << it->first;
2141 }
2142 }
2143 }
2144
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002145 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002146 std::map<std::string, bool> receive_stats_filled_;
2147
2148 VideoSendStream* send_stream_;
2149 std::map<std::string, bool> send_stats_filled_;
2150
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002151 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002152 std::set<uint32_t> expected_send_ssrcs_;
2153 std::string expected_cname_;
2154
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00002155 rtc::scoped_ptr<EventWrapper> check_stats_event_;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002156 };
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002157
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002158 FakeNetworkPipe::Config network_config;
2159 network_config.loss_percent = 5;
2160
2161 StatsObserver test(network_config);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002162 RunBaseTest(&test);
2163}
2164
2165TEST_F(EndToEndTest, ReceiverReferenceTimeReportEnabled) {
2166 TestXrReceiverReferenceTimeReport(true);
2167}
2168
2169TEST_F(EndToEndTest, ReceiverReferenceTimeReportDisabled) {
2170 TestXrReceiverReferenceTimeReport(false);
2171}
2172
2173TEST_F(EndToEndTest, TestReceivedRtpPacketStats) {
2174 static const size_t kNumRtpPacketsToSend = 5;
2175 class ReceivedRtpStatsObserver : public test::EndToEndTest {
2176 public:
2177 ReceivedRtpStatsObserver()
2178 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002179 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002180 sent_rtp_(0) {}
2181
2182 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002183 void OnStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002184 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002185 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002186 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002187 }
2188
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002189 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002190 if (sent_rtp_ >= kNumRtpPacketsToSend) {
2191 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002192 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002193 observation_complete_->Set();
2194 }
2195 return DROP_PACKET;
2196 }
2197 ++sent_rtp_;
2198 return SEND_PACKET;
2199 }
2200
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002201 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002202 EXPECT_EQ(kEventSignaled, Wait())
2203 << "Timed out while verifying number of received RTP packets.";
2204 }
2205
2206 VideoReceiveStream* receive_stream_;
2207 uint32_t sent_rtp_;
2208 } test;
2209
2210 RunBaseTest(&test);
2211}
2212
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002213TEST_F(EndToEndTest, SendsSetSsrc) { TestSendsSetSsrcs(1, false); }
2214
2215TEST_F(EndToEndTest, SendsSetSimulcastSsrcs) {
2216 TestSendsSetSsrcs(kNumSsrcs, false);
2217}
2218
2219TEST_F(EndToEndTest, CanSwitchToUseAllSsrcs) {
2220 TestSendsSetSsrcs(kNumSsrcs, true);
2221}
2222
mflodman@webrtc.orgf9460682014-07-24 16:41:25 +00002223TEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002224 class ObserveRedundantPayloads: public test::EndToEndTest {
2225 public:
2226 ObserveRedundantPayloads()
2227 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00002228 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002229 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
2230 }
2231 }
2232
2233 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002234 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002235 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002236 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002237
2238 if (!registered_rtx_ssrc_[header.ssrc])
2239 return SEND_PACKET;
2240
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002241 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002242 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002243 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002244
2245 if (!packet_is_redundant_payload)
2246 return SEND_PACKET;
2247
2248 if (!observed_redundant_retransmission_[header.ssrc]) {
2249 observed_redundant_retransmission_[header.ssrc] = true;
2250 if (--ssrcs_to_observe_ == 0)
2251 observation_complete_->Set();
2252 }
2253
2254 return SEND_PACKET;
2255 }
2256
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002257 size_t GetNumStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002258
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002259 void ModifyConfigs(VideoSendStream::Config* send_config,
2260 std::vector<VideoReceiveStream::Config>* receive_configs,
2261 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002262 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002263 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2264 encoder_config->streams[i].min_bitrate_bps = 10000;
2265 encoder_config->streams[i].target_bitrate_bps = 15000;
2266 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002267 }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002268
2269 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002270
2271 for (size_t i = 0; i < kNumSsrcs; ++i)
2272 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00002273
2274 // Significantly higher than max bitrates for all video streams -> forcing
2275 // padding to trigger redundant padding on all RTX SSRCs.
2276 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002277 }
2278
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002279 void PerformTest() override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002280 EXPECT_EQ(kEventSignaled, Wait())
2281 << "Timed out while waiting for redundant payloads on all SSRCs.";
2282 }
2283
2284 private:
2285 size_t ssrcs_to_observe_;
2286 std::map<uint32_t, bool> observed_redundant_retransmission_;
2287 std::map<uint32_t, bool> registered_rtx_ssrc_;
2288 } test;
2289
2290 RunBaseTest(&test);
2291}
2292
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002293void EndToEndTest::TestRtpStatePreservation(bool use_rtx) {
2294 static const uint32_t kMaxSequenceNumberGap = 100;
2295 static const uint64_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
2296 class RtpSequenceObserver : public test::RtpRtcpObserver {
2297 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00002298 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002299 : test::RtpRtcpObserver(kDefaultTimeoutMs),
2300 crit_(CriticalSectionWrapper::CreateCriticalSection()),
2301 ssrcs_to_observe_(kNumSsrcs) {
2302 for (size_t i = 0; i < kNumSsrcs; ++i) {
2303 configured_ssrcs_[kSendSsrcs[i]] = true;
2304 if (use_rtx)
2305 configured_ssrcs_[kSendRtxSsrcs[i]] = true;
2306 }
2307 }
2308
2309 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
2310 CriticalSectionScoped lock(crit_.get());
2311 ssrc_observed_.clear();
2312 ssrcs_to_observe_ = num_expected_ssrcs;
2313 }
2314
2315 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002316 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002317 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002318 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002319 const uint32_t ssrc = header.ssrc;
2320 const uint16_t sequence_number = header.sequenceNumber;
2321 const uint32_t timestamp = header.timestamp;
2322 const bool only_padding =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002323 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002324
2325 EXPECT_TRUE(configured_ssrcs_[ssrc])
2326 << "Received SSRC that wasn't configured: " << ssrc;
2327
2328 std::map<uint32_t, uint16_t>::iterator it =
2329 last_observed_sequence_number_.find(header.ssrc);
2330 if (it == last_observed_sequence_number_.end()) {
2331 last_observed_sequence_number_[ssrc] = sequence_number;
2332 last_observed_timestamp_[ssrc] = timestamp;
2333 } else {
2334 // Verify sequence numbers are reasonably close.
2335 uint32_t extended_sequence_number = sequence_number;
2336 // Check for roll-over.
2337 if (sequence_number < last_observed_sequence_number_[ssrc])
2338 extended_sequence_number += 0xFFFFu + 1;
2339 EXPECT_LE(
2340 extended_sequence_number - last_observed_sequence_number_[ssrc],
2341 kMaxSequenceNumberGap)
2342 << "Gap in sequence numbers ("
2343 << last_observed_sequence_number_[ssrc] << " -> " << sequence_number
2344 << ") too large for SSRC: " << ssrc << ".";
2345 last_observed_sequence_number_[ssrc] = sequence_number;
2346
2347 // TODO(pbos): Remove this check if we ever have monotonically
2348 // increasing timestamps. Right now padding packets add a delta which
2349 // can cause reordering between padding packets and regular packets,
2350 // hence we drop padding-only packets to not flake.
2351 if (only_padding) {
2352 // Verify that timestamps are reasonably close.
2353 uint64_t extended_timestamp = timestamp;
2354 // Check for roll-over.
2355 if (timestamp < last_observed_timestamp_[ssrc])
2356 extended_timestamp += static_cast<uint64_t>(0xFFFFFFFFu) + 1;
2357 EXPECT_LE(extended_timestamp - last_observed_timestamp_[ssrc],
2358 kMaxTimestampGap)
2359 << "Gap in timestamps (" << last_observed_timestamp_[ssrc]
2360 << " -> " << timestamp << ") too large for SSRC: " << ssrc << ".";
2361 }
2362 last_observed_timestamp_[ssrc] = timestamp;
2363 }
2364
2365 CriticalSectionScoped lock(crit_.get());
2366 // Wait for media packets on all ssrcs.
2367 if (!ssrc_observed_[ssrc] && !only_padding) {
2368 ssrc_observed_[ssrc] = true;
2369 if (--ssrcs_to_observe_ == 0)
2370 observation_complete_->Set();
2371 }
2372
2373 return SEND_PACKET;
2374 }
2375
2376 std::map<uint32_t, uint16_t> last_observed_sequence_number_;
2377 std::map<uint32_t, uint32_t> last_observed_timestamp_;
2378 std::map<uint32_t, bool> configured_ssrcs_;
2379
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00002380 rtc::scoped_ptr<CriticalSectionWrapper> crit_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002381 size_t ssrcs_to_observe_ GUARDED_BY(crit_);
2382 std::map<uint32_t, bool> ssrc_observed_ GUARDED_BY(crit_);
2383 } observer(use_rtx);
2384
2385 CreateCalls(Call::Config(observer.SendTransport()),
2386 Call::Config(observer.ReceiveTransport()));
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002387 observer.SetReceivers(sender_call_->Receiver(), nullptr);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002388
2389 CreateSendConfig(kNumSsrcs);
2390
2391 if (use_rtx) {
2392 for (size_t i = 0; i < kNumSsrcs; ++i) {
2393 send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
2394 }
2395 send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
2396 }
2397
2398 // Lower bitrates so that all streams send initially.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002399 for (size_t i = 0; i < encoder_config_.streams.size(); ++i) {
2400 encoder_config_.streams[i].min_bitrate_bps = 10000;
2401 encoder_config_.streams[i].target_bitrate_bps = 15000;
2402 encoder_config_.streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002403 }
2404
pbos@webrtc.org32452b22014-10-22 12:15:24 +00002405 // Use the same total bitrates when sending a single stream to avoid lowering
2406 // the bitrate estimate and requiring a subsequent rampup.
2407 VideoEncoderConfig one_stream = encoder_config_;
2408 one_stream.streams.resize(1);
2409 for (size_t i = 1; i < encoder_config_.streams.size(); ++i) {
2410 one_stream.streams.front().min_bitrate_bps +=
2411 encoder_config_.streams[i].min_bitrate_bps;
2412 one_stream.streams.front().target_bitrate_bps +=
2413 encoder_config_.streams[i].target_bitrate_bps;
2414 one_stream.streams.front().max_bitrate_bps +=
2415 encoder_config_.streams[i].max_bitrate_bps;
2416 }
2417
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002418 CreateMatchingReceiveConfigs();
2419
2420 CreateStreams();
2421 CreateFrameGeneratorCapturer();
2422
2423 Start();
2424 EXPECT_EQ(kEventSignaled, observer.Wait())
2425 << "Timed out waiting for all SSRCs to send packets.";
2426
2427 // Test stream resetting more than once to make sure that the state doesn't
2428 // get set once (this could be due to using std::map::insert for instance).
2429 for (size_t i = 0; i < 3; ++i) {
2430 frame_generator_capturer_->Stop();
2431 sender_call_->DestroyVideoSendStream(send_stream_);
2432
2433 // Re-create VideoSendStream with only one stream.
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002434 send_stream_ =
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002435 sender_call_->CreateVideoSendStream(send_config_, one_stream);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002436 send_stream_->Start();
2437 CreateFrameGeneratorCapturer();
2438 frame_generator_capturer_->Start();
2439
2440 observer.ResetExpectedSsrcs(1);
2441 EXPECT_EQ(kEventSignaled, observer.Wait())
2442 << "Timed out waiting for single RTP packet.";
2443
2444 // Reconfigure back to use all streams.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002445 send_stream_->ReconfigureVideoEncoder(encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002446 observer.ResetExpectedSsrcs(kNumSsrcs);
2447 EXPECT_EQ(kEventSignaled, observer.Wait())
2448 << "Timed out waiting for all SSRCs to send packets.";
2449
2450 // Reconfigure down to one stream.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002451 send_stream_->ReconfigureVideoEncoder(one_stream);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002452 observer.ResetExpectedSsrcs(1);
2453 EXPECT_EQ(kEventSignaled, observer.Wait())
2454 << "Timed out waiting for single RTP packet.";
2455
2456 // Reconfigure back to use all streams.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002457 send_stream_->ReconfigureVideoEncoder(encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002458 observer.ResetExpectedSsrcs(kNumSsrcs);
2459 EXPECT_EQ(kEventSignaled, observer.Wait())
2460 << "Timed out waiting for all SSRCs to send packets.";
2461 }
2462
2463 observer.StopSending();
2464
2465 Stop();
2466 DestroyStreams();
2467}
2468
aluebs@webrtc.orgb623c5c2014-08-26 14:22:51 +00002469TEST_F(EndToEndTest, DISABLED_RestartingSendStreamPreservesRtpState) {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002470 TestRtpStatePreservation(false);
2471}
2472
2473TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpStatesWithRtx) {
2474 TestRtpStatePreservation(true);
2475}
2476
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002477TEST_F(EndToEndTest, RespectsNetworkState) {
2478 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
2479 // down blocks until no more packets will be sent.
2480
2481 // Pacer will send from its packet list and then send required padding before
2482 // checking paused_ again. This should be enough for one round of pacing,
2483 // otherwise increase.
2484 static const int kNumAcceptedDowntimeRtp = 5;
2485 // A single RTCP may be in the pipeline.
2486 static const int kNumAcceptedDowntimeRtcp = 1;
2487 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
2488 public:
2489 NetworkStateTest()
2490 : EndToEndTest(kDefaultTimeoutMs),
2491 FakeEncoder(Clock::GetRealTimeClock()),
2492 test_crit_(CriticalSectionWrapper::CreateCriticalSection()),
2493 encoded_frames_(EventWrapper::Create()),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002494 packet_event_(EventWrapper::Create()),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002495 sender_state_(Call::kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002496 sender_rtp_(0),
2497 sender_rtcp_(0),
2498 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002499 down_frames_(0) {}
2500
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002501 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002502 CriticalSectionScoped lock(test_crit_.get());
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002503 ++sender_rtp_;
2504 packet_event_->Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002505 return SEND_PACKET;
2506 }
2507
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002508 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002509 CriticalSectionScoped lock(test_crit_.get());
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002510 ++sender_rtcp_;
2511 packet_event_->Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002512 return SEND_PACKET;
2513 }
2514
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002515 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002516 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
2517 return SEND_PACKET;
2518 }
2519
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002520 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002521 CriticalSectionScoped lock(test_crit_.get());
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002522 ++receiver_rtcp_;
2523 packet_event_->Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002524 return SEND_PACKET;
2525 }
2526
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002527 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002528 sender_call_ = sender_call;
2529 receiver_call_ = receiver_call;
2530 }
2531
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002532 void ModifyConfigs(VideoSendStream::Config* send_config,
2533 std::vector<VideoReceiveStream::Config>* receive_configs,
2534 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002535 send_config->encoder_settings.encoder = this;
2536 }
2537
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002538 void PerformTest() override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002539 EXPECT_EQ(kEventSignaled, encoded_frames_->Wait(kDefaultTimeoutMs))
2540 << "No frames received by the encoder.";
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002541 // Wait for packets from both sender/receiver.
2542 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002543
2544 // Sender-side network down.
2545 sender_call_->SignalNetworkState(Call::kNetworkDown);
2546 {
2547 CriticalSectionScoped lock(test_crit_.get());
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002548 // After network goes down we shouldn't be encoding more frames.
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002549 sender_state_ = Call::kNetworkDown;
2550 }
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002551 // Wait for receiver-packets and no sender packets.
2552 WaitForPacketsOrSilence(true, false);
2553
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002554 // Receiver-side network down.
2555 receiver_call_->SignalNetworkState(Call::kNetworkDown);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002556 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002557
2558 // Network back up again for both.
2559 {
2560 CriticalSectionScoped lock(test_crit_.get());
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002561 // It's OK to encode frames again, as we're about to bring up the
2562 // network.
2563 sender_state_ = Call::kNetworkUp;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002564 }
2565 sender_call_->SignalNetworkState(Call::kNetworkUp);
2566 receiver_call_->SignalNetworkState(Call::kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002567 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002568 }
2569
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002570 int32_t Encode(const I420VideoFrame& input_image,
2571 const CodecSpecificInfo* codec_specific_info,
2572 const std::vector<VideoFrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002573 {
2574 CriticalSectionScoped lock(test_crit_.get());
2575 if (sender_state_ == Call::kNetworkDown) {
2576 ++down_frames_;
2577 EXPECT_LE(down_frames_, 1)
2578 << "Encoding more than one frame while network is down.";
2579 if (down_frames_ > 1)
2580 encoded_frames_->Set();
2581 } else {
2582 encoded_frames_->Set();
2583 }
2584 }
2585 return test::FakeEncoder::Encode(
2586 input_image, codec_specific_info, frame_types);
2587 }
2588
2589 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002590 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
2591 int64_t initial_time_ms = clock_->TimeInMilliseconds();
2592 int initial_sender_rtp;
2593 int initial_sender_rtcp;
2594 int initial_receiver_rtcp;
2595 {
2596 CriticalSectionScoped lock(test_crit_.get());
2597 initial_sender_rtp = sender_rtp_;
2598 initial_sender_rtcp = sender_rtcp_;
2599 initial_receiver_rtcp = receiver_rtcp_;
2600 }
2601 bool sender_done = false;
2602 bool receiver_done = false;
2603 while(!sender_done || !receiver_done) {
2604 packet_event_->Wait(kSilenceTimeoutMs);
2605 int64_t time_now_ms = clock_->TimeInMilliseconds();
2606 CriticalSectionScoped lock(test_crit_.get());
2607 if (sender_down) {
2608 ASSERT_LE(sender_rtp_ - initial_sender_rtp, kNumAcceptedDowntimeRtp)
2609 << "RTP sent during sender-side downtime.";
2610 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
2611 kNumAcceptedDowntimeRtcp)
2612 << "RTCP sent during sender-side downtime.";
2613 if (time_now_ms - initial_time_ms >=
2614 static_cast<int64_t>(kSilenceTimeoutMs)) {
2615 sender_done = true;
2616 }
2617 } else {
2618 if (sender_rtp_ > initial_sender_rtp)
2619 sender_done = true;
2620 }
2621 if (receiver_down) {
2622 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
2623 kNumAcceptedDowntimeRtcp)
2624 << "RTCP sent during receiver-side downtime.";
2625 if (time_now_ms - initial_time_ms >=
2626 static_cast<int64_t>(kSilenceTimeoutMs)) {
2627 receiver_done = true;
2628 }
2629 } else {
2630 if (receiver_rtcp_ > initial_receiver_rtcp)
2631 receiver_done = true;
2632 }
2633 }
2634 }
2635
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00002636 const rtc::scoped_ptr<CriticalSectionWrapper> test_crit_;
2637 const rtc::scoped_ptr<EventWrapper> encoded_frames_;
2638 const rtc::scoped_ptr<EventWrapper> packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002639 Call* sender_call_;
2640 Call* receiver_call_;
2641 Call::NetworkState sender_state_ GUARDED_BY(test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002642 int sender_rtp_ GUARDED_BY(test_crit_);
2643 int sender_rtcp_ GUARDED_BY(test_crit_);
2644 int receiver_rtcp_ GUARDED_BY(test_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002645 int down_frames_ GUARDED_BY(test_crit_);
2646 } test;
2647
2648 RunBaseTest(&test);
2649}
2650
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00002651TEST_F(EndToEndTest, CallReportsRttForSender) {
2652 static const int kSendDelayMs = 30;
2653 static const int kReceiveDelayMs = 70;
2654
2655 FakeNetworkPipe::Config config;
2656 config.queue_delay_ms = kSendDelayMs;
2657 test::DirectTransport sender_transport(config);
2658 config.queue_delay_ms = kReceiveDelayMs;
2659 test::DirectTransport receiver_transport(config);
2660
2661 CreateCalls(Call::Config(&sender_transport),
2662 Call::Config(&receiver_transport));
2663
2664 sender_transport.SetReceiver(receiver_call_->Receiver());
2665 receiver_transport.SetReceiver(sender_call_->Receiver());
2666
2667 CreateSendConfig(1);
2668 CreateMatchingReceiveConfigs();
2669
2670 CreateStreams();
2671 CreateFrameGeneratorCapturer();
2672 Start();
2673
2674 int64_t start_time_ms = clock_->TimeInMilliseconds();
2675 while (true) {
2676 Call::Stats stats = sender_call_->GetStats();
2677 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
2678 clock_->TimeInMilliseconds())
2679 << "No RTT stats before timeout!";
2680 if (stats.rtt_ms != -1) {
2681 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs);
2682 break;
2683 }
2684 SleepMs(10);
2685 }
2686
2687 Stop();
2688 DestroyStreams();
2689}
2690
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002691TEST_F(EndToEndTest, NewSendStreamsRespectNetworkDown) {
2692 class UnusedEncoder : public test::FakeEncoder {
2693 public:
2694 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002695 int32_t Encode(const I420VideoFrame& input_image,
2696 const CodecSpecificInfo* codec_specific_info,
2697 const std::vector<VideoFrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002698 ADD_FAILURE() << "Unexpected frame encode.";
2699 return test::FakeEncoder::Encode(
2700 input_image, codec_specific_info, frame_types);
2701 }
2702 };
2703
2704 UnusedTransport transport;
2705 CreateSenderCall(Call::Config(&transport));
2706 sender_call_->SignalNetworkState(Call::kNetworkDown);
2707
2708 CreateSendConfig(1);
2709 UnusedEncoder unused_encoder;
2710 send_config_.encoder_settings.encoder = &unused_encoder;
2711 CreateStreams();
2712 CreateFrameGeneratorCapturer();
2713
2714 Start();
2715 SleepMs(kSilenceTimeoutMs);
2716 Stop();
2717
2718 DestroyStreams();
2719}
2720
2721TEST_F(EndToEndTest, NewReceiveStreamsRespectNetworkDown) {
2722 test::DirectTransport sender_transport;
2723 CreateSenderCall(Call::Config(&sender_transport));
2724 UnusedTransport transport;
2725 CreateReceiverCall(Call::Config(&transport));
2726 sender_transport.SetReceiver(receiver_call_->Receiver());
2727
2728 receiver_call_->SignalNetworkState(Call::kNetworkDown);
2729
2730 CreateSendConfig(1);
2731 CreateMatchingReceiveConfigs();
2732 CreateStreams();
2733 CreateFrameGeneratorCapturer();
2734
2735 Start();
2736 SleepMs(kSilenceTimeoutMs);
2737 Stop();
2738
2739 sender_transport.StopSending();
2740
2741 DestroyStreams();
2742}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00002743
2744// TODO(pbos): Remove this regression test when VideoEngine is no longer used as
2745// a backend. This is to test that we hand channels back properly.
2746TEST_F(EndToEndTest, CanCreateAndDestroyManyVideoStreams) {
2747 test::NullTransport transport;
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00002748 rtc::scoped_ptr<Call> call(Call::Create(Call::Config(&transport)));
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00002749 test::FakeDecoder fake_decoder;
2750 test::FakeEncoder fake_encoder(Clock::GetRealTimeClock());
2751 for (size_t i = 0; i < 100; ++i) {
2752 VideoSendStream::Config send_config;
2753 send_config.encoder_settings.encoder = &fake_encoder;
2754 send_config.encoder_settings.payload_name = "FAKE";
2755 send_config.encoder_settings.payload_type = 123;
2756
2757 VideoEncoderConfig encoder_config;
2758 encoder_config.streams = test::CreateVideoStreams(1);
2759 send_config.rtp.ssrcs.push_back(1);
2760 VideoSendStream* send_stream =
2761 call->CreateVideoSendStream(send_config, encoder_config);
2762 call->DestroyVideoSendStream(send_stream);
2763
2764 VideoReceiveStream::Config receive_config;
2765 receive_config.rtp.remote_ssrc = 1;
2766 receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
2767 VideoReceiveStream::Decoder decoder;
2768 decoder.decoder = &fake_decoder;
2769 decoder.payload_type = 123;
2770 decoder.payload_name = "FAKE";
2771 receive_config.decoders.push_back(decoder);
2772 VideoReceiveStream* receive_stream =
2773 call->CreateVideoReceiveStream(receive_config);
2774 call->DestroyVideoReceiveStream(receive_stream);
2775 }
2776}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002777} // namespace webrtc