blob: b86b2c9d3013f2f5f516593fa83843fabbc7eefc [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>
danilchap5c35cf92016-02-03 14:14:49 -080011#include <list>
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000012#include <map>
kwiberg27f982b2016-03-01 11:52:33 -080013#include <memory>
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000014#include <sstream>
15#include <string>
16
17#include "testing/gtest/include/gtest/gtest.h"
18
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000019#include "webrtc/base/checks.h"
Erik Språng6b8d3552015-09-24 15:06:57 +020020#include "webrtc/base/event.h"
danilchap5c35cf92016-02-03 14:14:49 -080021#include "webrtc/base/timeutils.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000022#include "webrtc/call.h"
Peter Boström5c389d32015-09-25 13:58:30 +020023#include "webrtc/call/transport_adapter.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000024#include "webrtc/frame_callback.h"
danilchap5c35cf92016-02-03 14:14:49 -080025#include "webrtc/modules/include/module_common_types.h"
stefan32f81542016-01-20 07:13:58 -080026#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
sprang861c55e2015-10-16 10:01:21 -070027#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000028#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
hbosbab934b2016-01-27 01:36:03 -080029#include "webrtc/modules/video_coding/codecs/h264/include/h264.h"
marpan@webrtc.org5b883172014-11-01 06:10:48 +000030#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
31#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010032#include "webrtc/modules/video_coding/include/video_coding_defines.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010033#include "webrtc/system_wrappers/include/metrics.h"
34#include "webrtc/system_wrappers/include/sleep.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000035#include "webrtc/test/call_test.h"
36#include "webrtc/test/direct_transport.h"
37#include "webrtc/test/encoder_settings.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000038#include "webrtc/test/fake_decoder.h"
39#include "webrtc/test/fake_encoder.h"
40#include "webrtc/test/frame_generator.h"
41#include "webrtc/test/frame_generator_capturer.h"
Åsa Persson352b2d72015-04-15 18:00:40 +020042#include "webrtc/test/histogram.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000043#include "webrtc/test/null_transport.h"
asapersson@webrtc.org37c05592015-01-28 13:58:27 +000044#include "webrtc/test/rtcp_packet_parser.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000045#include "webrtc/test/rtp_rtcp_observer.h"
46#include "webrtc/test/testsupport/fileutils.h"
47#include "webrtc/test/testsupport/perf_test.h"
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +000048#include "webrtc/video_encoder.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000049
50namespace webrtc {
51
Peter Boström5811a392015-12-10 13:02:50 +010052static const int kSilenceTimeoutMs = 2000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000053
54class EndToEndTest : public test::CallTest {
55 public:
56 EndToEndTest() {}
57
58 virtual ~EndToEndTest() {
stefanff483612015-12-21 03:14:00 -080059 EXPECT_EQ(nullptr, video_send_stream_);
60 EXPECT_TRUE(video_receive_streams_.empty());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000061 }
62
63 protected:
pbos2d566682015-09-28 09:59:31 -070064 class UnusedTransport : public Transport {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000065 private:
stefan1d8a5062015-10-02 03:39:33 -070066 bool SendRtp(const uint8_t* packet,
67 size_t length,
68 const PacketOptions& options) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000069 ADD_FAILURE() << "Unexpected RTP sent.";
70 return false;
71 }
72
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000073 bool SendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000074 ADD_FAILURE() << "Unexpected RTCP sent.";
75 return false;
76 }
77 };
78
Peter Boström39593972016-02-15 11:27:15 +010079 void DecodesRetransmittedFrame(bool enable_rtx, bool enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000080 void ReceivesPliAndRecovers(int rtp_history_ms);
pbosda903ea2015-10-02 02:36:56 -070081 void RespectsRtcpMode(RtcpMode rtcp_mode);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000082 void TestXrReceiverReferenceTimeReport(bool enable_rrtr);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +000083 void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +000084 void TestRtpStatePreservation(bool use_rtx);
sprangb4a1ae52015-12-03 08:10:08 -080085 void VerifyHistogramStats(bool use_rtx, bool use_red, bool screenshare);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000086};
87
88TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
solenberg4fbae2b2015-08-28 04:07:10 -070089 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000090
solenberg4fbae2b2015-08-28 04:07:10 -070091 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +010092 CreateSendConfig(1, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -070093 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000094
Stefan Holmer9fea80f2016-01-07 17:43:18 +010095 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000096
stefanff483612015-12-21 03:14:00 -080097 video_receive_streams_[0]->Start();
98 video_receive_streams_[0]->Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000099
100 DestroyStreams();
101}
102
103TEST_F(EndToEndTest, ReceiverCanBeStoppedTwice) {
solenberg4fbae2b2015-08-28 04:07:10 -0700104 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000105
solenberg4fbae2b2015-08-28 04:07:10 -0700106 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100107 CreateSendConfig(1, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700108 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000109
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100110 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000111
stefanff483612015-12-21 03:14:00 -0800112 video_receive_streams_[0]->Stop();
113 video_receive_streams_[0]->Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000114
115 DestroyStreams();
116}
117
118TEST_F(EndToEndTest, RendersSingleDelayedFrame) {
119 static const int kWidth = 320;
120 static const int kHeight = 240;
121 // This constant is chosen to be higher than the timeout in the video_render
122 // module. This makes sure that frames aren't dropped if there are no other
123 // frames in the queue.
124 static const int kDelayRenderCallbackMs = 1000;
125
126 class Renderer : public VideoRenderer {
127 public:
Peter Boström5811a392015-12-10 13:02:50 +0100128 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000129
nisseeb83a1a2016-03-21 01:27:56 -0700130 void OnFrame(const VideoFrame& video_frame) override { event_.Set(); }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000131
Peter Boström5811a392015-12-10 13:02:50 +0100132 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000133
Peter Boström5811a392015-12-10 13:02:50 +0100134 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000135 } renderer;
136
137 class TestFrameCallback : public I420FrameCallback {
138 public:
Peter Boström5811a392015-12-10 13:02:50 +0100139 TestFrameCallback() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000140
Peter Boström5811a392015-12-10 13:02:50 +0100141 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000142
143 private:
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700144 void FrameCallback(VideoFrame* frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000145 SleepMs(kDelayRenderCallbackMs);
Peter Boström5811a392015-12-10 13:02:50 +0100146 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000147 }
148
Peter Boström5811a392015-12-10 13:02:50 +0100149 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000150 };
151
solenberg4fbae2b2015-08-28 04:07:10 -0700152 CreateCalls(Call::Config(), Call::Config());
153
stefanf116bd02015-10-27 08:29:42 -0700154 test::DirectTransport sender_transport(sender_call_.get());
155 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000156 sender_transport.SetReceiver(receiver_call_->Receiver());
157 receiver_transport.SetReceiver(sender_call_->Receiver());
158
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100159 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700160 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000161
162 TestFrameCallback pre_render_callback;
stefanff483612015-12-21 03:14:00 -0800163 video_receive_configs_[0].pre_render_callback = &pre_render_callback;
164 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000165
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100166 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000167 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000168
169 // Create frames that are smaller than the send width/height, this is done to
170 // check that the callbacks are done after processing video.
kwiberg27f982b2016-03-01 11:52:33 -0800171 std::unique_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000172 test::FrameGenerator::CreateChromaGenerator(kWidth, kHeight));
stefanff483612015-12-21 03:14:00 -0800173 video_send_stream_->Input()->IncomingCapturedFrame(
174 *frame_generator->NextFrame());
Peter Boström5811a392015-12-10 13:02:50 +0100175 EXPECT_TRUE(pre_render_callback.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000176 << "Timed out while waiting for pre-render callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100177 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000178 << "Timed out while waiting for the frame to render.";
179
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000180 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000181
182 sender_transport.StopSending();
183 receiver_transport.StopSending();
184
185 DestroyStreams();
186}
187
188TEST_F(EndToEndTest, TransmitsFirstFrame) {
189 class Renderer : public VideoRenderer {
190 public:
Peter Boström5811a392015-12-10 13:02:50 +0100191 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000192
nisseeb83a1a2016-03-21 01:27:56 -0700193 void OnFrame(const VideoFrame& video_frame) override { event_.Set(); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000194
Peter Boström5811a392015-12-10 13:02:50 +0100195 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000196
Peter Boström5811a392015-12-10 13:02:50 +0100197 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000198 } renderer;
199
solenberg4fbae2b2015-08-28 04:07:10 -0700200 CreateCalls(Call::Config(), Call::Config());
201
stefanf116bd02015-10-27 08:29:42 -0700202 test::DirectTransport sender_transport(sender_call_.get());
203 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000204 sender_transport.SetReceiver(receiver_call_->Receiver());
205 receiver_transport.SetReceiver(sender_call_->Receiver());
206
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100207 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700208 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -0800209 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000210
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100211 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000212 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000213
kwiberg27f982b2016-03-01 11:52:33 -0800214 std::unique_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000215 test::FrameGenerator::CreateChromaGenerator(
stefanff483612015-12-21 03:14:00 -0800216 video_encoder_config_.streams[0].width,
217 video_encoder_config_.streams[0].height));
218 video_send_stream_->Input()->IncomingCapturedFrame(
219 *frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000220
Peter Boström5811a392015-12-10 13:02:50 +0100221 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000222 << "Timed out while waiting for the frame to render.";
223
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000224 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000225
226 sender_transport.StopSending();
227 receiver_transport.StopSending();
228
229 DestroyStreams();
230}
231
marpan@webrtc.org5f1e2e42014-11-06 02:02:28 +0000232TEST_F(EndToEndTest, SendsAndReceivesVP9) {
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000233 class VP9Observer : public test::EndToEndTest, public VideoRenderer {
234 public:
235 VP9Observer()
236 : EndToEndTest(2 * kDefaultTimeoutMs),
237 encoder_(VideoEncoder::Create(VideoEncoder::kVp9)),
238 decoder_(VP9Decoder::Create()),
239 frame_counter_(0) {}
240
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000241 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100242 EXPECT_TRUE(Wait())
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000243 << "Timed out while waiting for enough frames to be decoded.";
244 }
245
stefanff483612015-12-21 03:14:00 -0800246 void ModifyVideoConfigs(
247 VideoSendStream::Config* send_config,
248 std::vector<VideoReceiveStream::Config>* receive_configs,
249 VideoEncoderConfig* encoder_config) override {
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000250 send_config->encoder_settings.encoder = encoder_.get();
251 send_config->encoder_settings.payload_name = "VP9";
pbosa7d70542015-07-07 07:35:49 -0700252 send_config->encoder_settings.payload_type = 124;
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000253 encoder_config->streams[0].min_bitrate_bps = 50000;
254 encoder_config->streams[0].target_bitrate_bps =
255 encoder_config->streams[0].max_bitrate_bps = 2000000;
256
257 (*receive_configs)[0].renderer = this;
258 (*receive_configs)[0].decoders.resize(1);
259 (*receive_configs)[0].decoders[0].payload_type =
260 send_config->encoder_settings.payload_type;
261 (*receive_configs)[0].decoders[0].payload_name =
262 send_config->encoder_settings.payload_name;
263 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
264 }
265
nisseeb83a1a2016-03-21 01:27:56 -0700266 void OnFrame(const VideoFrame& video_frame) override {
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000267 const int kRequiredFrames = 500;
268 if (++frame_counter_ == kRequiredFrames)
Peter Boström5811a392015-12-10 13:02:50 +0100269 observation_complete_.Set();
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000270 }
271
272 private:
kwiberg27f982b2016-03-01 11:52:33 -0800273 std::unique_ptr<webrtc::VideoEncoder> encoder_;
274 std::unique_ptr<webrtc::VideoDecoder> decoder_;
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000275 int frame_counter_;
276 } test;
277
stefane74eef12016-01-08 06:47:13 -0800278 RunBaseTest(&test);
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000279}
280
hbosbab934b2016-01-27 01:36:03 -0800281#if defined(WEBRTC_END_TO_END_H264_TESTS)
282
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000283TEST_F(EndToEndTest, SendsAndReceivesH264) {
284 class H264Observer : public test::EndToEndTest, public VideoRenderer {
285 public:
286 H264Observer()
287 : EndToEndTest(2 * kDefaultTimeoutMs),
hbosbab934b2016-01-27 01:36:03 -0800288 encoder_(VideoEncoder::Create(VideoEncoder::kH264)),
289 decoder_(H264Decoder::Create()),
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000290 frame_counter_(0) {}
291
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000292 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100293 EXPECT_TRUE(Wait())
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000294 << "Timed out while waiting for enough frames to be decoded.";
295 }
296
stefanff483612015-12-21 03:14:00 -0800297 void ModifyVideoConfigs(
298 VideoSendStream::Config* send_config,
299 std::vector<VideoReceiveStream::Config>* receive_configs,
300 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org8278c072015-02-23 11:11:49 +0000301 send_config->rtp.nack.rtp_history_ms =
302 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
hbosbab934b2016-01-27 01:36:03 -0800303 send_config->encoder_settings.encoder = encoder_.get();
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000304 send_config->encoder_settings.payload_name = "H264";
hbosbab934b2016-01-27 01:36:03 -0800305 send_config->encoder_settings.payload_type = 126;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000306 encoder_config->streams[0].min_bitrate_bps = 50000;
307 encoder_config->streams[0].target_bitrate_bps =
308 encoder_config->streams[0].max_bitrate_bps = 2000000;
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000309
310 (*receive_configs)[0].renderer = this;
pbos@webrtc.org776e6f22014-10-29 15:28:39 +0000311 (*receive_configs)[0].decoders.resize(1);
312 (*receive_configs)[0].decoders[0].payload_type =
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000313 send_config->encoder_settings.payload_type;
pbos@webrtc.org776e6f22014-10-29 15:28:39 +0000314 (*receive_configs)[0].decoders[0].payload_name =
315 send_config->encoder_settings.payload_name;
hbosbab934b2016-01-27 01:36:03 -0800316 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000317 }
318
nisseeb83a1a2016-03-21 01:27:56 -0700319 void OnFrame(const VideoFrame& video_frame) override {
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000320 const int kRequiredFrames = 500;
321 if (++frame_counter_ == kRequiredFrames)
Peter Boström5811a392015-12-10 13:02:50 +0100322 observation_complete_.Set();
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000323 }
324
325 private:
kwiberg27f982b2016-03-01 11:52:33 -0800326 std::unique_ptr<webrtc::VideoEncoder> encoder_;
327 std::unique_ptr<webrtc::VideoDecoder> decoder_;
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000328 int frame_counter_;
329 } test;
330
stefane74eef12016-01-08 06:47:13 -0800331 RunBaseTest(&test);
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000332}
333
hbosbab934b2016-01-27 01:36:03 -0800334#endif // defined(WEBRTC_END_TO_END_H264_TESTS)
335
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000336TEST_F(EndToEndTest, ReceiverUsesLocalSsrc) {
337 class SyncRtcpObserver : public test::EndToEndTest {
338 public:
339 SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {}
340
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000341 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000342 RTCPUtility::RTCPParserV2 parser(packet, length, true);
343 EXPECT_TRUE(parser.IsValid());
344 uint32_t ssrc = 0;
345 ssrc |= static_cast<uint32_t>(packet[4]) << 24;
346 ssrc |= static_cast<uint32_t>(packet[5]) << 16;
347 ssrc |= static_cast<uint32_t>(packet[6]) << 8;
348 ssrc |= static_cast<uint32_t>(packet[7]) << 0;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100349 EXPECT_EQ(kReceiverLocalVideoSsrc, ssrc);
Peter Boström5811a392015-12-10 13:02:50 +0100350 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000351
352 return SEND_PACKET;
353 }
354
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000355 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100356 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000357 << "Timed out while waiting for a receiver RTCP packet to be sent.";
358 }
359 } test;
360
stefane74eef12016-01-08 06:47:13 -0800361 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000362}
363
364TEST_F(EndToEndTest, ReceivesAndRetransmitsNack) {
365 static const int kNumberOfNacksToObserve = 2;
366 static const int kLossBurstSize = 2;
367 static const int kPacketsBetweenLossBursts = 9;
368 class NackObserver : public test::EndToEndTest {
369 public:
370 NackObserver()
371 : EndToEndTest(kLongTimeoutMs),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000372 sent_rtp_packets_(0),
373 packets_left_to_drop_(0),
374 nacks_left_(kNumberOfNacksToObserve) {}
375
376 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000377 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700378 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000379 RTPHeader header;
Peter Boström03671cb2015-12-07 15:22:24 +0100380 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000381
382 // Never drop retransmitted packets.
383 if (dropped_packets_.find(header.sequenceNumber) !=
384 dropped_packets_.end()) {
385 retransmitted_packets_.insert(header.sequenceNumber);
Stefan Holmer586b19b2015-09-18 11:14:31 +0200386 if (nacks_left_ <= 0 &&
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000387 retransmitted_packets_.size() == dropped_packets_.size()) {
Peter Boström5811a392015-12-10 13:02:50 +0100388 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000389 }
390 return SEND_PACKET;
391 }
392
393 ++sent_rtp_packets_;
394
395 // Enough NACKs received, stop dropping packets.
Stefan Holmer586b19b2015-09-18 11:14:31 +0200396 if (nacks_left_ <= 0)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000397 return SEND_PACKET;
398
399 // Check if it's time for a new loss burst.
400 if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
401 packets_left_to_drop_ = kLossBurstSize;
402
Stefan Holmer01b48882015-05-05 10:21:24 +0200403 // Never drop padding packets as those won't be retransmitted.
404 if (packets_left_to_drop_ > 0 && header.paddingLength == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000405 --packets_left_to_drop_;
406 dropped_packets_.insert(header.sequenceNumber);
407 return DROP_PACKET;
408 }
409
410 return SEND_PACKET;
411 }
412
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000413 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700414 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000415 RTCPUtility::RTCPParserV2 parser(packet, length, true);
416 EXPECT_TRUE(parser.IsValid());
417
418 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +0200419 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
420 if (packet_type == RTCPUtility::RTCPPacketTypes::kRtpfbNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000421 --nacks_left_;
422 break;
423 }
424 packet_type = parser.Iterate();
425 }
426 return SEND_PACKET;
427 }
428
stefanff483612015-12-21 03:14:00 -0800429 void ModifyVideoConfigs(
430 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 {
Peter Boström5811a392015-12-10 13:02:50 +0100438 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000439 << "Timed out waiting for packets to be NACKed, retransmitted and "
440 "rendered.";
441 }
442
stefanf116bd02015-10-27 08:29:42 -0700443 rtc::CriticalSection crit_;
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_;
stefanf116bd02015-10-27 08:29:42 -0700448 int nacks_left_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000449 } test;
450
stefane74eef12016-01-08 06:47:13 -0800451 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000452}
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:
stefanf116bd02015-10-27 08:29:42 -0700461 Action OnSendRtp(const uint8_t* packet, size_t length) override {
462 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000463 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
Stefan Holmer01b48882015-05-05 10:21:24 +0200466 int encapsulated_payload_type = -1;
467 if (header.payloadType == kRedPayloadType) {
468 encapsulated_payload_type =
469 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100470 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200471 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
472 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100473 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200474 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000475
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000476 if (protected_sequence_numbers_.count(header.sequenceNumber) != 0) {
477 // Retransmitted packet, should not count.
478 protected_sequence_numbers_.erase(header.sequenceNumber);
479 EXPECT_GT(protected_timestamps_.count(header.timestamp), 0u);
480 protected_timestamps_.erase(header.timestamp);
481 return SEND_PACKET;
482 }
483
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000484 switch (state_) {
485 case kFirstPacket:
486 state_ = kDropEveryOtherPacketUntilFec;
487 break;
488 case kDropEveryOtherPacketUntilFec:
489 if (encapsulated_payload_type == kUlpfecPayloadType) {
490 state_ = kDropNextMediaPacket;
491 return SEND_PACKET;
492 }
493 if (header.sequenceNumber % 2 == 0)
494 return DROP_PACKET;
495 break;
496 case kDropNextMediaPacket:
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100497 if (encapsulated_payload_type == kFakeVideoSendPayloadType) {
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000498 protected_sequence_numbers_.insert(header.sequenceNumber);
499 protected_timestamps_.insert(header.timestamp);
500 state_ = kDropEveryOtherPacketUntilFec;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000501 return DROP_PACKET;
502 }
503 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000504 }
505
506 return SEND_PACKET;
507 }
508
nisseeb83a1a2016-03-21 01:27:56 -0700509 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200510 rtc::CritScope lock(&crit_);
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000511 // Rendering frame with timestamp of packet that was dropped -> FEC
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000512 // protection worked.
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000513 if (protected_timestamps_.count(video_frame.timestamp()) != 0)
Peter Boström5811a392015-12-10 13:02:50 +0100514 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000515 }
516
517 enum {
518 kFirstPacket,
519 kDropEveryOtherPacketUntilFec,
520 kDropNextMediaPacket,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000521 } state_;
522
stefanff483612015-12-21 03:14:00 -0800523 void ModifyVideoConfigs(
524 VideoSendStream::Config* send_config,
525 std::vector<VideoReceiveStream::Config>* receive_configs,
526 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000527 // TODO(pbos): Run this test with combined NACK/FEC enabled as well.
528 // int rtp_history_ms = 1000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000529 // (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000530 // send_config->rtp.nack.rtp_history_ms = rtp_history_ms;
531 send_config->rtp.fec.red_payload_type = kRedPayloadType;
532 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
533
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000534 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
535 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
536 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000537 }
538
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000539 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100540 EXPECT_TRUE(Wait())
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000541 << "Timed out waiting for dropped frames frames to be rendered.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000542 }
543
stefanf116bd02015-10-27 08:29:42 -0700544 rtc::CriticalSection crit_;
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000545 std::set<uint32_t> protected_sequence_numbers_ GUARDED_BY(crit_);
546 std::set<uint32_t> protected_timestamps_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000547 } test;
548
stefane74eef12016-01-08 06:47:13 -0800549 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000550}
551
Henrik Kjellanderdb313b62015-04-02 08:45:41 +0200552// Flacky on all platforms. See webrtc:4328.
553TEST_F(EndToEndTest, DISABLED_ReceivedFecPacketsNotNacked) {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000554 class FecNackObserver : public test::EndToEndTest {
555 public:
mflodmand1590b22015-12-09 07:07:59 -0800556 FecNackObserver()
stefanf116bd02015-10-27 08:29:42 -0700557 : EndToEndTest(kDefaultTimeoutMs),
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000558 state_(kFirstPacket),
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000559 fec_sequence_number_(0),
560 has_last_sequence_number_(false),
561 last_sequence_number_(0) {}
562
563 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000564 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800565 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000566 RTPHeader header;
567 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000568
Stefan Holmer01b48882015-05-05 10:21:24 +0200569 int encapsulated_payload_type = -1;
570 if (header.payloadType == kRedPayloadType) {
571 encapsulated_payload_type =
572 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100573 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200574 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
575 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100576 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200577 }
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000578
579 if (has_last_sequence_number_ &&
580 !IsNewerSequenceNumber(header.sequenceNumber,
581 last_sequence_number_)) {
582 // Drop retransmitted packets.
583 return DROP_PACKET;
584 }
585 last_sequence_number_ = header.sequenceNumber;
586 has_last_sequence_number_ = true;
587
588 bool fec_packet = encapsulated_payload_type == kUlpfecPayloadType;
589 switch (state_) {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000590 case kFirstPacket:
591 state_ = kDropEveryOtherPacketUntilFec;
592 break;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000593 case kDropEveryOtherPacketUntilFec:
594 if (fec_packet) {
595 state_ = kDropAllMediaPacketsUntilFec;
596 } else if (header.sequenceNumber % 2 == 0) {
597 return DROP_PACKET;
598 }
599 break;
600 case kDropAllMediaPacketsUntilFec:
601 if (!fec_packet)
602 return DROP_PACKET;
603 fec_sequence_number_ = header.sequenceNumber;
604 state_ = kVerifyFecPacketNotInNackList;
605 break;
606 case kVerifyFecPacketNotInNackList:
607 // Continue to drop packets. Make sure no frame can be decoded.
608 if (fec_packet || header.sequenceNumber % 2 == 0)
609 return DROP_PACKET;
610 break;
611 }
612 return SEND_PACKET;
613 }
614
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000615 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800616 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000617 if (state_ == kVerifyFecPacketNotInNackList) {
618 test::RtcpPacketParser rtcp_parser;
619 rtcp_parser.Parse(packet, length);
620 std::vector<uint16_t> nacks = rtcp_parser.nack_item()->last_nack_list();
621 if (!nacks.empty() &&
622 IsNewerSequenceNumber(nacks.back(), fec_sequence_number_)) {
623 EXPECT_TRUE(std::find(
624 nacks.begin(), nacks.end(), fec_sequence_number_) == nacks.end());
Peter Boström5811a392015-12-10 13:02:50 +0100625 observation_complete_.Set();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000626 }
627 }
628 return SEND_PACKET;
629 }
630
stefane74eef12016-01-08 06:47:13 -0800631 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
632 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
633 // Configure some network delay.
634 const int kNetworkDelayMs = 50;
635 FakeNetworkPipe::Config config;
636 config.queue_delay_ms = kNetworkDelayMs;
637 return new test::PacketTransport(sender_call, this,
638 test::PacketTransport::kSender, config);
639 }
640
Stefan Holmere5904162015-03-26 11:11:06 +0100641 // TODO(holmer): Investigate why we don't send FEC packets when the bitrate
642 // is 10 kbps.
643 Call::Config GetSenderCallConfig() override {
solenberg4fbae2b2015-08-28 04:07:10 -0700644 Call::Config config;
Stefan Holmere5904162015-03-26 11:11:06 +0100645 const int kMinBitrateBps = 30000;
646 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
647 return config;
648 }
649
stefanff483612015-12-21 03:14:00 -0800650 void ModifyVideoConfigs(
651 VideoSendStream::Config* send_config,
652 std::vector<VideoReceiveStream::Config>* receive_configs,
653 VideoEncoderConfig* encoder_config) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000654 // Configure hybrid NACK/FEC.
655 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
656 send_config->rtp.fec.red_payload_type = kRedPayloadType;
657 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
658 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
659 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
660 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
661 }
662
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000663 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100664 EXPECT_TRUE(Wait())
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000665 << "Timed out while waiting for FEC packets to be received.";
666 }
667
668 enum {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000669 kFirstPacket,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000670 kDropEveryOtherPacketUntilFec,
671 kDropAllMediaPacketsUntilFec,
672 kVerifyFecPacketNotInNackList,
673 } state_;
674
stefan608213e2015-11-01 14:56:10 -0800675 rtc::CriticalSection crit_;
676 uint16_t fec_sequence_number_ GUARDED_BY(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000677 bool has_last_sequence_number_;
678 uint16_t last_sequence_number_;
stefanf116bd02015-10-27 08:29:42 -0700679 } test;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000680
stefane74eef12016-01-08 06:47:13 -0800681 RunBaseTest(&test);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000682}
683
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000684// This test drops second RTP packet with a marker bit set, makes sure it's
685// retransmitted and renders. Retransmission SSRCs are also checked.
Peter Boström39593972016-02-15 11:27:15 +0100686void EndToEndTest::DecodesRetransmittedFrame(bool enable_rtx, bool enable_red) {
Peter Boström67680c12016-02-17 11:10:04 +0100687 static const int kDroppedFrameNumber = 10;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000688 class RetransmissionObserver : public test::EndToEndTest,
689 public I420FrameCallback {
690 public:
Peter Boström39593972016-02-15 11:27:15 +0100691 RetransmissionObserver(bool enable_rtx, bool enable_red)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000692 : EndToEndTest(kDefaultTimeoutMs),
Peter Boström39593972016-02-15 11:27:15 +0100693 payload_type_(GetPayloadType(false, enable_red)),
694 retransmission_ssrc_(enable_rtx ? kSendRtxSsrcs[0]
695 : kVideoSendSsrcs[0]),
696 retransmission_payload_type_(GetPayloadType(enable_rtx, enable_red)),
697 encoder_(VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000698 marker_bits_observed_(0),
699 retransmitted_timestamp_(0),
700 frame_retransmitted_(false) {}
701
702 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000703 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700704 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000705 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000706 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000707
Peter Boström67680c12016-02-17 11:10:04 +0100708 // Ignore padding-only packets over RTX.
709 if (header.payloadType != payload_type_) {
710 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
711 if (length == header.headerLength + header.paddingLength)
712 return SEND_PACKET;
Stefan Holmer586b19b2015-09-18 11:14:31 +0200713 }
Peter Boström67680c12016-02-17 11:10:04 +0100714
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000715 if (header.timestamp == retransmitted_timestamp_) {
716 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
717 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
718 frame_retransmitted_ = true;
719 return SEND_PACKET;
720 }
721
Stefan Holmer10880012016-02-03 13:29:59 +0100722 EXPECT_EQ(kVideoSendSsrcs[0], header.ssrc)
723 << "Payload type " << static_cast<int>(header.payloadType)
724 << " not expected.";
Shao Changbine62202f2015-04-21 20:24:50 +0800725 EXPECT_EQ(payload_type_, header.payloadType);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000726
Stefan Holmer586b19b2015-09-18 11:14:31 +0200727 // Found the final packet of the frame to inflict loss to, drop this and
728 // expect a retransmission.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000729 if (header.markerBit && ++marker_bits_observed_ == kDroppedFrameNumber) {
730 retransmitted_timestamp_ = header.timestamp;
731 return DROP_PACKET;
732 }
733
734 return SEND_PACKET;
735 }
736
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700737 void FrameCallback(VideoFrame* frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200738 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000739 if (frame->timestamp() == retransmitted_timestamp_) {
740 EXPECT_TRUE(frame_retransmitted_);
Peter Boström5811a392015-12-10 13:02:50 +0100741 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000742 }
743 }
744
stefanff483612015-12-21 03:14:00 -0800745 void ModifyVideoConfigs(
746 VideoSendStream::Config* send_config,
747 std::vector<VideoReceiveStream::Config>* receive_configs,
748 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000749 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000750 (*receive_configs)[0].pre_render_callback = this;
751 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
Shao Changbine62202f2015-04-21 20:24:50 +0800752
753 if (payload_type_ == kRedPayloadType) {
754 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
755 send_config->rtp.fec.red_payload_type = kRedPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +0100756 if (retransmission_ssrc_ == kSendRtxSsrcs[0])
757 send_config->rtp.fec.red_rtx_payload_type = kRtxRedPayloadType;
758 (*receive_configs)[0].rtp.fec.ulpfec_payload_type =
759 send_config->rtp.fec.ulpfec_payload_type;
760 (*receive_configs)[0].rtp.fec.red_payload_type =
761 send_config->rtp.fec.red_payload_type;
762 (*receive_configs)[0].rtp.fec.red_rtx_payload_type =
763 send_config->rtp.fec.red_rtx_payload_type;
Shao Changbine62202f2015-04-21 20:24:50 +0800764 }
765
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000766 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
767 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000768 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +0100769 (*receive_configs)[0].rtp.rtx[payload_type_].ssrc = kSendRtxSsrcs[0];
770 (*receive_configs)[0].rtp.rtx[payload_type_].payload_type =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000771 kSendRtxPayloadType;
772 }
Peter Boström39593972016-02-15 11:27:15 +0100773 // Configure encoding and decoding with VP8, since generic packetization
774 // doesn't support FEC with NACK.
775 RTC_DCHECK_EQ(1u, (*receive_configs)[0].decoders.size());
776 send_config->encoder_settings.encoder = encoder_.get();
777 send_config->encoder_settings.payload_name = "VP8";
778 (*receive_configs)[0].decoders[0].payload_name = "VP8";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000779 }
780
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000781 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100782 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000783 << "Timed out while waiting for retransmission to render.";
784 }
785
Shao Changbine62202f2015-04-21 20:24:50 +0800786 int GetPayloadType(bool use_rtx, bool use_red) {
Stefan Holmer10880012016-02-03 13:29:59 +0100787 if (use_red) {
788 if (use_rtx)
789 return kRtxRedPayloadType;
790 return kRedPayloadType;
791 }
792 if (use_rtx)
793 return kSendRtxPayloadType;
794 return kFakeVideoSendPayloadType;
Shao Changbine62202f2015-04-21 20:24:50 +0800795 }
796
stefanf116bd02015-10-27 08:29:42 -0700797 rtc::CriticalSection crit_;
Shao Changbine62202f2015-04-21 20:24:50 +0800798 const int payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000799 const uint32_t retransmission_ssrc_;
800 const int retransmission_payload_type_;
kwiberg27f982b2016-03-01 11:52:33 -0800801 std::unique_ptr<VideoEncoder> encoder_;
Peter Boström39593972016-02-15 11:27:15 +0100802 const std::string payload_name_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000803 int marker_bits_observed_;
stefanf116bd02015-10-27 08:29:42 -0700804 uint32_t retransmitted_timestamp_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000805 bool frame_retransmitted_;
Peter Boström39593972016-02-15 11:27:15 +0100806 } test(enable_rtx, enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000807
stefane74eef12016-01-08 06:47:13 -0800808 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000809}
810
811TEST_F(EndToEndTest, DecodesRetransmittedFrame) {
Shao Changbine62202f2015-04-21 20:24:50 +0800812 DecodesRetransmittedFrame(false, false);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000813}
814
815TEST_F(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +0800816 DecodesRetransmittedFrame(true, false);
817}
818
819TEST_F(EndToEndTest, DecodesRetransmittedFrameByRed) {
820 DecodesRetransmittedFrame(false, true);
821}
822
823TEST_F(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
824 DecodesRetransmittedFrame(true, true);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000825}
826
andresp@webrtc.org02686112014-09-19 08:24:19 +0000827TEST_F(EndToEndTest, UsesFrameCallbacks) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000828 static const int kWidth = 320;
829 static const int kHeight = 240;
830
831 class Renderer : public VideoRenderer {
832 public:
Peter Boström5811a392015-12-10 13:02:50 +0100833 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000834
nisseeb83a1a2016-03-21 01:27:56 -0700835 void OnFrame(const VideoFrame& video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000836 EXPECT_EQ(0, *video_frame.buffer(kYPlane))
837 << "Rendered frame should have zero luma which is applied by the "
838 "pre-render callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100839 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000840 }
841
Peter Boström5811a392015-12-10 13:02:50 +0100842 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
843 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000844 } renderer;
845
846 class TestFrameCallback : public I420FrameCallback {
847 public:
848 TestFrameCallback(int expected_luma_byte, int next_luma_byte)
Peter Boström5811a392015-12-10 13:02:50 +0100849 : event_(false, false),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000850 expected_luma_byte_(expected_luma_byte),
851 next_luma_byte_(next_luma_byte) {}
852
Peter Boström5811a392015-12-10 13:02:50 +0100853 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000854
855 private:
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700856 virtual void FrameCallback(VideoFrame* frame) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000857 EXPECT_EQ(kWidth, frame->width())
858 << "Width not as expected, callback done before resize?";
859 EXPECT_EQ(kHeight, frame->height())
860 << "Height not as expected, callback done before resize?";
861
862 // Previous luma specified, observed luma should be fairly close.
863 if (expected_luma_byte_ != -1) {
864 EXPECT_NEAR(expected_luma_byte_, *frame->buffer(kYPlane), 10);
865 }
866
867 memset(frame->buffer(kYPlane),
868 next_luma_byte_,
869 frame->allocated_size(kYPlane));
870
Peter Boström5811a392015-12-10 13:02:50 +0100871 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000872 }
873
Peter Boström5811a392015-12-10 13:02:50 +0100874 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000875 int expected_luma_byte_;
876 int next_luma_byte_;
877 };
878
879 TestFrameCallback pre_encode_callback(-1, 255); // Changes luma to 255.
880 TestFrameCallback pre_render_callback(255, 0); // Changes luma from 255 to 0.
881
solenberg4fbae2b2015-08-28 04:07:10 -0700882 CreateCalls(Call::Config(), Call::Config());
883
stefanf116bd02015-10-27 08:29:42 -0700884 test::DirectTransport sender_transport(sender_call_.get());
885 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000886 sender_transport.SetReceiver(receiver_call_->Receiver());
887 receiver_transport.SetReceiver(sender_call_->Receiver());
888
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100889 CreateSendConfig(1, 0, &sender_transport);
kwiberg27f982b2016-03-01 11:52:33 -0800890 std::unique_ptr<VideoEncoder> encoder(
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +0000891 VideoEncoder::Create(VideoEncoder::kVp8));
stefanff483612015-12-21 03:14:00 -0800892 video_send_config_.encoder_settings.encoder = encoder.get();
893 video_send_config_.encoder_settings.payload_name = "VP8";
894 ASSERT_EQ(1u, video_encoder_config_.streams.size()) << "Test setup error.";
895 video_encoder_config_.streams[0].width = kWidth;
896 video_encoder_config_.streams[0].height = kHeight;
897 video_send_config_.pre_encode_callback = &pre_encode_callback;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000898
solenberg4fbae2b2015-08-28 04:07:10 -0700899 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -0800900 video_receive_configs_[0].pre_render_callback = &pre_render_callback;
901 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000902
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100903 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000904 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000905
906 // Create frames that are smaller than the send width/height, this is done to
907 // check that the callbacks are done after processing video.
kwiberg27f982b2016-03-01 11:52:33 -0800908 std::unique_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000909 test::FrameGenerator::CreateChromaGenerator(kWidth / 2, kHeight / 2));
stefanff483612015-12-21 03:14:00 -0800910 video_send_stream_->Input()->IncomingCapturedFrame(
911 *frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000912
Peter Boström5811a392015-12-10 13:02:50 +0100913 EXPECT_TRUE(pre_encode_callback.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000914 << "Timed out while waiting for pre-encode callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100915 EXPECT_TRUE(pre_render_callback.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000916 << "Timed out while waiting for pre-render callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100917 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000918 << "Timed out while waiting for the frame to render.";
919
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000920 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000921
922 sender_transport.StopSending();
923 receiver_transport.StopSending();
924
925 DestroyStreams();
926}
927
928void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
929 static const int kPacketsToDrop = 1;
930
931 class PliObserver : public test::EndToEndTest, public VideoRenderer {
932 public:
933 explicit PliObserver(int rtp_history_ms)
934 : EndToEndTest(kLongTimeoutMs),
935 rtp_history_ms_(rtp_history_ms),
936 nack_enabled_(rtp_history_ms > 0),
937 highest_dropped_timestamp_(0),
938 frames_to_drop_(0),
939 received_pli_(false) {}
940
941 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000942 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700943 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000944 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000945 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000946
947 // Drop all retransmitted packets to force a PLI.
948 if (header.timestamp <= highest_dropped_timestamp_)
949 return DROP_PACKET;
950
951 if (frames_to_drop_ > 0) {
952 highest_dropped_timestamp_ = header.timestamp;
953 --frames_to_drop_;
954 return DROP_PACKET;
955 }
956
957 return SEND_PACKET;
958 }
959
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000960 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700961 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000962 RTCPUtility::RTCPParserV2 parser(packet, length, true);
963 EXPECT_TRUE(parser.IsValid());
964
965 for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +0200966 packet_type != RTCPUtility::RTCPPacketTypes::kInvalid;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000967 packet_type = parser.Iterate()) {
968 if (!nack_enabled_)
Erik Språng242e22b2015-05-11 10:17:43 +0200969 EXPECT_NE(packet_type, RTCPUtility::RTCPPacketTypes::kRtpfbNack);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000970
Erik Språng242e22b2015-05-11 10:17:43 +0200971 if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbPli) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000972 received_pli_ = true;
973 break;
974 }
975 }
976 return SEND_PACKET;
977 }
978
nisseeb83a1a2016-03-21 01:27:56 -0700979 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200980 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000981 if (received_pli_ &&
982 video_frame.timestamp() > highest_dropped_timestamp_) {
Peter Boström5811a392015-12-10 13:02:50 +0100983 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000984 }
985 if (!received_pli_)
986 frames_to_drop_ = kPacketsToDrop;
987 }
988
stefanff483612015-12-21 03:14:00 -0800989 void ModifyVideoConfigs(
990 VideoSendStream::Config* send_config,
991 std::vector<VideoReceiveStream::Config>* receive_configs,
992 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000993 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000994 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
995 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000996 }
997
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000998 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100999 EXPECT_TRUE(Wait()) << "Timed out waiting for PLI to be "
1000 "received and a frame to be "
1001 "rendered afterwards.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001002 }
1003
stefanf116bd02015-10-27 08:29:42 -07001004 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001005 int rtp_history_ms_;
1006 bool nack_enabled_;
stefanf116bd02015-10-27 08:29:42 -07001007 uint32_t highest_dropped_timestamp_ GUARDED_BY(&crit_);
1008 int frames_to_drop_ GUARDED_BY(&crit_);
1009 bool received_pli_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001010 } test(rtp_history_ms);
1011
stefane74eef12016-01-08 06:47:13 -08001012 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001013}
1014
1015TEST_F(EndToEndTest, ReceivesPliAndRecoversWithNack) {
1016 ReceivesPliAndRecovers(1000);
1017}
1018
jbauchdb81ffd2015-11-23 03:59:02 -08001019TEST_F(EndToEndTest, ReceivesPliAndRecoversWithoutNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001020 ReceivesPliAndRecovers(0);
1021}
1022
1023TEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
1024 class PacketInputObserver : public PacketReceiver {
1025 public:
1026 explicit PacketInputObserver(PacketReceiver* receiver)
Peter Boström5811a392015-12-10 13:02:50 +01001027 : receiver_(receiver), delivered_packet_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001028
Peter Boström5811a392015-12-10 13:02:50 +01001029 bool Wait() { return delivered_packet_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001030
1031 private:
stefan68786d22015-09-08 05:36:15 -07001032 DeliveryStatus DeliverPacket(MediaType media_type,
1033 const uint8_t* packet,
1034 size_t length,
1035 const PacketTime& packet_time) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001036 if (RtpHeaderParser::IsRtcp(packet, length)) {
stefan68786d22015-09-08 05:36:15 -07001037 return receiver_->DeliverPacket(media_type, packet, length,
1038 packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001039 } else {
1040 DeliveryStatus delivery_status =
stefan68786d22015-09-08 05:36:15 -07001041 receiver_->DeliverPacket(media_type, packet, length, packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001042 EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
Peter Boström5811a392015-12-10 13:02:50 +01001043 delivered_packet_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001044 return delivery_status;
1045 }
1046 }
1047
1048 PacketReceiver* receiver_;
Peter Boström5811a392015-12-10 13:02:50 +01001049 rtc::Event delivered_packet_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001050 };
1051
solenberg4fbae2b2015-08-28 04:07:10 -07001052 CreateCalls(Call::Config(), Call::Config());
1053
stefanf116bd02015-10-27 08:29:42 -07001054 test::DirectTransport send_transport(sender_call_.get());
1055 test::DirectTransport receive_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001056 PacketInputObserver input_observer(receiver_call_->Receiver());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001057 send_transport.SetReceiver(&input_observer);
1058 receive_transport.SetReceiver(sender_call_->Receiver());
1059
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001060 CreateSendConfig(1, 0, &send_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001061 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001062
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001063 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001064 CreateFrameGeneratorCapturer();
1065 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001066
stefanff483612015-12-21 03:14:00 -08001067 receiver_call_->DestroyVideoReceiveStream(video_receive_streams_[0]);
1068 video_receive_streams_.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001069
1070 // Wait() waits for a received packet.
Peter Boström5811a392015-12-10 13:02:50 +01001071 EXPECT_TRUE(input_observer.Wait());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001072
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001073 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001074
1075 DestroyStreams();
1076
1077 send_transport.StopSending();
1078 receive_transport.StopSending();
1079}
1080
pbosda903ea2015-10-02 02:36:56 -07001081void EndToEndTest::RespectsRtcpMode(RtcpMode rtcp_mode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001082 static const int kNumCompoundRtcpPacketsToObserve = 10;
1083 class RtcpModeObserver : public test::EndToEndTest {
1084 public:
pbosda903ea2015-10-02 02:36:56 -07001085 explicit RtcpModeObserver(RtcpMode rtcp_mode)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001086 : EndToEndTest(kDefaultTimeoutMs),
1087 rtcp_mode_(rtcp_mode),
1088 sent_rtp_(0),
1089 sent_rtcp_(0) {}
1090
1091 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001092 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001093 if (++sent_rtp_ % 3 == 0)
1094 return DROP_PACKET;
1095
1096 return SEND_PACKET;
1097 }
1098
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001099 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001100 ++sent_rtcp_;
1101 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1102 EXPECT_TRUE(parser.IsValid());
1103
1104 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1105 bool has_report_block = false;
Erik Språng242e22b2015-05-11 10:17:43 +02001106 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1107 EXPECT_NE(RTCPUtility::RTCPPacketTypes::kSr, packet_type);
1108 if (packet_type == RTCPUtility::RTCPPacketTypes::kRr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001109 has_report_block = true;
1110 break;
1111 }
1112 packet_type = parser.Iterate();
1113 }
1114
1115 switch (rtcp_mode_) {
pbosda903ea2015-10-02 02:36:56 -07001116 case RtcpMode::kCompound:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001117 if (!has_report_block) {
1118 ADD_FAILURE() << "Received RTCP packet without receiver report for "
pbosda903ea2015-10-02 02:36:56 -07001119 "RtcpMode::kCompound.";
Peter Boström5811a392015-12-10 13:02:50 +01001120 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001121 }
1122
1123 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
Peter Boström5811a392015-12-10 13:02:50 +01001124 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001125
1126 break;
pbosda903ea2015-10-02 02:36:56 -07001127 case RtcpMode::kReducedSize:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001128 if (!has_report_block)
Peter Boström5811a392015-12-10 13:02:50 +01001129 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001130 break;
pbosda903ea2015-10-02 02:36:56 -07001131 case RtcpMode::kOff:
1132 RTC_NOTREACHED();
1133 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001134 }
1135
1136 return SEND_PACKET;
1137 }
1138
stefanff483612015-12-21 03:14:00 -08001139 void ModifyVideoConfigs(
1140 VideoSendStream::Config* send_config,
1141 std::vector<VideoReceiveStream::Config>* receive_configs,
1142 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001143 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001144 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1145 (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001146 }
1147
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001148 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001149 EXPECT_TRUE(Wait())
pbosda903ea2015-10-02 02:36:56 -07001150 << (rtcp_mode_ == RtcpMode::kCompound
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001151 ? "Timed out before observing enough compound packets."
1152 : "Timed out before receiving a non-compound RTCP packet.");
1153 }
1154
pbosda903ea2015-10-02 02:36:56 -07001155 RtcpMode rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001156 int sent_rtp_;
1157 int sent_rtcp_;
1158 } test(rtcp_mode);
1159
stefane74eef12016-01-08 06:47:13 -08001160 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001161}
1162
1163TEST_F(EndToEndTest, UsesRtcpCompoundMode) {
pbosda903ea2015-10-02 02:36:56 -07001164 RespectsRtcpMode(RtcpMode::kCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001165}
1166
1167TEST_F(EndToEndTest, UsesRtcpReducedSizeMode) {
pbosda903ea2015-10-02 02:36:56 -07001168 RespectsRtcpMode(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001169}
1170
1171// Test sets up a Call multiple senders with different resolutions and SSRCs.
1172// Another is set up to receive all three of these with different renderers.
sprang867fb522015-08-03 04:38:41 -07001173class MultiStreamTest {
1174 public:
1175 static const size_t kNumStreams = 3;
1176 struct CodecSettings {
1177 uint32_t ssrc;
1178 int width;
1179 int height;
1180 } codec_settings[kNumStreams];
1181
1182 MultiStreamTest() {
1183 // TODO(sprang): Cleanup when msvc supports explicit initializers for array.
1184 codec_settings[0] = {1, 640, 480};
1185 codec_settings[1] = {2, 320, 240};
1186 codec_settings[2] = {3, 240, 160};
1187 }
1188
1189 virtual ~MultiStreamTest() {}
1190
1191 void RunTest() {
kwiberg27f982b2016-03-01 11:52:33 -08001192 std::unique_ptr<Call> sender_call(Call::Create(Call::Config()));
1193 std::unique_ptr<Call> receiver_call(Call::Create(Call::Config()));
1194 std::unique_ptr<test::DirectTransport> sender_transport(
stefanf116bd02015-10-27 08:29:42 -07001195 CreateSendTransport(sender_call.get()));
kwiberg27f982b2016-03-01 11:52:33 -08001196 std::unique_ptr<test::DirectTransport> receiver_transport(
stefanf116bd02015-10-27 08:29:42 -07001197 CreateReceiveTransport(receiver_call.get()));
sprang867fb522015-08-03 04:38:41 -07001198 sender_transport->SetReceiver(receiver_call->Receiver());
1199 receiver_transport->SetReceiver(sender_call->Receiver());
1200
kwiberg27f982b2016-03-01 11:52:33 -08001201 std::unique_ptr<VideoEncoder> encoders[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001202 for (size_t i = 0; i < kNumStreams; ++i)
1203 encoders[i].reset(VideoEncoder::Create(VideoEncoder::kVp8));
1204
1205 VideoSendStream* send_streams[kNumStreams];
1206 VideoReceiveStream* receive_streams[kNumStreams];
1207
1208 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
1209 ScopedVector<VideoDecoder> allocated_decoders;
1210 for (size_t i = 0; i < kNumStreams; ++i) {
1211 uint32_t ssrc = codec_settings[i].ssrc;
1212 int width = codec_settings[i].width;
1213 int height = codec_settings[i].height;
1214
solenberg4fbae2b2015-08-28 04:07:10 -07001215 VideoSendStream::Config send_config(sender_transport.get());
sprang867fb522015-08-03 04:38:41 -07001216 send_config.rtp.ssrcs.push_back(ssrc);
1217 send_config.encoder_settings.encoder = encoders[i].get();
1218 send_config.encoder_settings.payload_name = "VP8";
1219 send_config.encoder_settings.payload_type = 124;
1220 VideoEncoderConfig encoder_config;
1221 encoder_config.streams = test::CreateVideoStreams(1);
1222 VideoStream* stream = &encoder_config.streams[0];
1223 stream->width = width;
1224 stream->height = height;
1225 stream->max_framerate = 5;
1226 stream->min_bitrate_bps = stream->target_bitrate_bps =
1227 stream->max_bitrate_bps = 100000;
1228
1229 UpdateSendConfig(i, &send_config, &encoder_config, &frame_generators[i]);
1230
1231 send_streams[i] =
1232 sender_call->CreateVideoSendStream(send_config, encoder_config);
1233 send_streams[i]->Start();
1234
solenberg4fbae2b2015-08-28 04:07:10 -07001235 VideoReceiveStream::Config receive_config(receiver_transport.get());
sprang867fb522015-08-03 04:38:41 -07001236 receive_config.rtp.remote_ssrc = ssrc;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001237 receive_config.rtp.local_ssrc = test::CallTest::kReceiverLocalVideoSsrc;
sprang867fb522015-08-03 04:38:41 -07001238 VideoReceiveStream::Decoder decoder =
1239 test::CreateMatchingDecoder(send_config.encoder_settings);
1240 allocated_decoders.push_back(decoder.decoder);
1241 receive_config.decoders.push_back(decoder);
1242
1243 UpdateReceiveConfig(i, &receive_config);
1244
1245 receive_streams[i] =
1246 receiver_call->CreateVideoReceiveStream(receive_config);
1247 receive_streams[i]->Start();
1248
1249 frame_generators[i] = test::FrameGeneratorCapturer::Create(
1250 send_streams[i]->Input(), width, height, 30,
1251 Clock::GetRealTimeClock());
1252 frame_generators[i]->Start();
1253 }
1254
1255 Wait();
1256
1257 for (size_t i = 0; i < kNumStreams; ++i) {
1258 frame_generators[i]->Stop();
1259 sender_call->DestroyVideoSendStream(send_streams[i]);
1260 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1261 delete frame_generators[i];
1262 }
1263
1264 sender_transport->StopSending();
1265 receiver_transport->StopSending();
1266 }
1267
1268 protected:
1269 virtual void Wait() = 0;
1270 // Note: frame_generator is a point-to-pointer, since the actual instance
1271 // hasn't been created at the time of this call. Only when packets/frames
1272 // start flowing should this be dereferenced.
1273 virtual void UpdateSendConfig(
1274 size_t stream_index,
1275 VideoSendStream::Config* send_config,
1276 VideoEncoderConfig* encoder_config,
1277 test::FrameGeneratorCapturer** frame_generator) {}
1278 virtual void UpdateReceiveConfig(size_t stream_index,
1279 VideoReceiveStream::Config* receive_config) {
1280 }
stefanf116bd02015-10-27 08:29:42 -07001281 virtual test::DirectTransport* CreateSendTransport(Call* sender_call) {
1282 return new test::DirectTransport(sender_call);
sprang867fb522015-08-03 04:38:41 -07001283 }
stefanf116bd02015-10-27 08:29:42 -07001284 virtual test::DirectTransport* CreateReceiveTransport(Call* receiver_call) {
1285 return new test::DirectTransport(receiver_call);
sprang867fb522015-08-03 04:38:41 -07001286 }
1287};
1288
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001289// Each renderer verifies that it receives the expected resolution, and as soon
1290// as every renderer has received a frame, the test finishes.
andresp@webrtc.org02686112014-09-19 08:24:19 +00001291TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001292 class VideoOutputObserver : public VideoRenderer {
1293 public:
sprang867fb522015-08-03 04:38:41 -07001294 VideoOutputObserver(const MultiStreamTest::CodecSettings& settings,
1295 uint32_t ssrc,
1296 test::FrameGeneratorCapturer** frame_generator)
1297 : settings_(settings),
1298 ssrc_(ssrc),
1299 frame_generator_(frame_generator),
Peter Boström5811a392015-12-10 13:02:50 +01001300 done_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001301
nisseeb83a1a2016-03-21 01:27:56 -07001302 void OnFrame(const VideoFrame& video_frame) override {
sprang867fb522015-08-03 04:38:41 -07001303 EXPECT_EQ(settings_.width, video_frame.width());
1304 EXPECT_EQ(settings_.height, video_frame.height());
1305 (*frame_generator_)->Stop();
Peter Boström5811a392015-12-10 13:02:50 +01001306 done_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001307 }
1308
sprang867fb522015-08-03 04:38:41 -07001309 uint32_t Ssrc() { return ssrc_; }
1310
Peter Boström5811a392015-12-10 13:02:50 +01001311 bool Wait() { return done_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001312
1313 private:
sprang867fb522015-08-03 04:38:41 -07001314 const MultiStreamTest::CodecSettings& settings_;
1315 const uint32_t ssrc_;
1316 test::FrameGeneratorCapturer** const frame_generator_;
Peter Boström5811a392015-12-10 13:02:50 +01001317 rtc::Event done_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001318 };
1319
sprang867fb522015-08-03 04:38:41 -07001320 class Tester : public MultiStreamTest {
1321 public:
1322 Tester() {}
1323 virtual ~Tester() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001324
sprang867fb522015-08-03 04:38:41 -07001325 protected:
1326 void Wait() override {
1327 for (const auto& observer : observers_) {
Peter Boström5811a392015-12-10 13:02:50 +01001328 EXPECT_TRUE(observer->Wait()) << "Time out waiting for from on ssrc "
1329 << observer->Ssrc();
sprang867fb522015-08-03 04:38:41 -07001330 }
1331 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001332
sprang867fb522015-08-03 04:38:41 -07001333 void UpdateSendConfig(
1334 size_t stream_index,
1335 VideoSendStream::Config* send_config,
1336 VideoEncoderConfig* encoder_config,
1337 test::FrameGeneratorCapturer** frame_generator) override {
1338 observers_[stream_index].reset(new VideoOutputObserver(
1339 codec_settings[stream_index], send_config->rtp.ssrcs.front(),
1340 frame_generator));
1341 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001342
sprang867fb522015-08-03 04:38:41 -07001343 void UpdateReceiveConfig(
1344 size_t stream_index,
1345 VideoReceiveStream::Config* receive_config) override {
1346 receive_config->renderer = observers_[stream_index].get();
1347 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001348
sprang867fb522015-08-03 04:38:41 -07001349 private:
kwiberg27f982b2016-03-01 11:52:33 -08001350 std::unique_ptr<VideoOutputObserver> observers_[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001351 } tester;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001352
sprang867fb522015-08-03 04:38:41 -07001353 tester.RunTest();
1354}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001355
sprang867fb522015-08-03 04:38:41 -07001356TEST_F(EndToEndTest, AssignsTransportSequenceNumbers) {
sprang867fb522015-08-03 04:38:41 -07001357 static const int kExtensionId = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001358
sprang867fb522015-08-03 04:38:41 -07001359 class RtpExtensionHeaderObserver : public test::DirectTransport {
1360 public:
stefanf116bd02015-10-27 08:29:42 -07001361 RtpExtensionHeaderObserver(Call* sender_call,
1362 const uint32_t& first_media_ssrc,
sprang861c55e2015-10-16 10:01:21 -07001363 const std::map<uint32_t, uint32_t>& ssrc_map)
stefanf116bd02015-10-27 08:29:42 -07001364 : DirectTransport(sender_call),
Peter Boström5811a392015-12-10 13:02:50 +01001365 done_(false, false),
sprang867fb522015-08-03 04:38:41 -07001366 parser_(RtpHeaderParser::Create()),
sprang861c55e2015-10-16 10:01:21 -07001367 first_media_ssrc_(first_media_ssrc),
1368 rtx_to_media_ssrcs_(ssrc_map),
sprang867fb522015-08-03 04:38:41 -07001369 padding_observed_(false),
sprang861c55e2015-10-16 10:01:21 -07001370 rtx_padding_observed_(false),
1371 retransmit_observed_(false),
1372 started_(false) {
sprang867fb522015-08-03 04:38:41 -07001373 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
1374 kExtensionId);
1375 }
1376 virtual ~RtpExtensionHeaderObserver() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001377
stefan1d8a5062015-10-02 03:39:33 -07001378 bool SendRtp(const uint8_t* data,
1379 size_t length,
1380 const PacketOptions& options) override {
sprang861c55e2015-10-16 10:01:21 -07001381 {
1382 rtc::CritScope cs(&lock_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001383
Erik Språng8d629712015-08-04 16:24:03 +02001384 if (IsDone())
sprang861c55e2015-10-16 10:01:21 -07001385 return false;
1386
1387 if (started_) {
1388 RTPHeader header;
1389 EXPECT_TRUE(parser_->Parse(data, length, &header));
1390 bool drop_packet = false;
1391
1392 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
1393 EXPECT_EQ(options.packet_id,
1394 header.extension.transportSequenceNumber);
1395 if (!streams_observed_.empty()) {
1396 // Unwrap packet id and verify uniqueness.
1397 int64_t packet_id = unwrapper_.Unwrap(options.packet_id);
1398 EXPECT_TRUE(received_packed_ids_.insert(packet_id).second);
1399 }
1400
1401 // Drop (up to) every 17th packet, so we get retransmits.
1402 // Only drop media, and not on the first stream (otherwise it will be
1403 // hard to distinguish from padding, which is always sent on the first
1404 // stream).
1405 if (header.payloadType != kSendRtxPayloadType &&
1406 header.ssrc != first_media_ssrc_ &&
1407 header.extension.transportSequenceNumber % 17 == 0) {
1408 dropped_seq_[header.ssrc].insert(header.sequenceNumber);
1409 drop_packet = true;
1410 }
1411
1412 size_t payload_length =
1413 length - (header.headerLength + header.paddingLength);
1414 if (payload_length == 0) {
1415 padding_observed_ = true;
1416 } else if (header.payloadType == kSendRtxPayloadType) {
1417 uint16_t original_sequence_number =
1418 ByteReader<uint16_t>::ReadBigEndian(&data[header.headerLength]);
1419 uint32_t original_ssrc =
1420 rtx_to_media_ssrcs_.find(header.ssrc)->second;
1421 std::set<uint16_t>* seq_no_map = &dropped_seq_[original_ssrc];
1422 auto it = seq_no_map->find(original_sequence_number);
1423 if (it != seq_no_map->end()) {
1424 retransmit_observed_ = true;
1425 seq_no_map->erase(it);
1426 } else {
1427 rtx_padding_observed_ = true;
1428 }
1429 } else {
1430 streams_observed_.insert(header.ssrc);
1431 }
1432
1433 if (IsDone())
Peter Boström5811a392015-12-10 13:02:50 +01001434 done_.Set();
sprang861c55e2015-10-16 10:01:21 -07001435
1436 if (drop_packet)
1437 return true;
1438 }
sprang867fb522015-08-03 04:38:41 -07001439 }
sprang861c55e2015-10-16 10:01:21 -07001440
stefan1d8a5062015-10-02 03:39:33 -07001441 return test::DirectTransport::SendRtp(data, length, options);
sprang867fb522015-08-03 04:38:41 -07001442 }
1443
Erik Språng8d629712015-08-04 16:24:03 +02001444 bool IsDone() {
sprang861c55e2015-10-16 10:01:21 -07001445 bool observed_types_ok =
1446 streams_observed_.size() == MultiStreamTest::kNumStreams &&
1447 padding_observed_ && retransmit_observed_ && rtx_padding_observed_;
1448 if (!observed_types_ok)
1449 return false;
1450 // We should not have any gaps in the sequence number range.
1451 size_t seqno_range =
1452 *received_packed_ids_.rbegin() - *received_packed_ids_.begin() + 1;
1453 return seqno_range == received_packed_ids_.size();
Erik Språng8d629712015-08-04 16:24:03 +02001454 }
1455
Peter Boström5811a392015-12-10 13:02:50 +01001456 bool Wait() {
sprang861c55e2015-10-16 10:01:21 -07001457 {
1458 // Can't be sure until this point that rtx_to_media_ssrcs_ etc have
1459 // been initialized and are OK to read.
1460 rtc::CritScope cs(&lock_);
1461 started_ = true;
1462 }
Peter Boström5811a392015-12-10 13:02:50 +01001463 return done_.Wait(kDefaultTimeoutMs);
sprang861c55e2015-10-16 10:01:21 -07001464 }
sprang867fb522015-08-03 04:38:41 -07001465
sprang861c55e2015-10-16 10:01:21 -07001466 rtc::CriticalSection lock_;
Peter Boström5811a392015-12-10 13:02:50 +01001467 rtc::Event done_;
kwiberg27f982b2016-03-01 11:52:33 -08001468 std::unique_ptr<RtpHeaderParser> parser_;
sprang861c55e2015-10-16 10:01:21 -07001469 SequenceNumberUnwrapper unwrapper_;
1470 std::set<int64_t> received_packed_ids_;
sprang867fb522015-08-03 04:38:41 -07001471 std::set<uint32_t> streams_observed_;
sprang861c55e2015-10-16 10:01:21 -07001472 std::map<uint32_t, std::set<uint16_t>> dropped_seq_;
1473 const uint32_t& first_media_ssrc_;
1474 const std::map<uint32_t, uint32_t>& rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001475 bool padding_observed_;
1476 bool rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001477 bool retransmit_observed_;
1478 bool started_;
sprang867fb522015-08-03 04:38:41 -07001479 };
1480
1481 class TransportSequenceNumberTester : public MultiStreamTest {
1482 public:
sprang861c55e2015-10-16 10:01:21 -07001483 TransportSequenceNumberTester()
1484 : first_media_ssrc_(0), observer_(nullptr) {}
sprang867fb522015-08-03 04:38:41 -07001485 virtual ~TransportSequenceNumberTester() {}
1486
1487 protected:
1488 void Wait() override {
henrikg91d6ede2015-09-17 00:24:34 -07001489 RTC_DCHECK(observer_ != nullptr);
Peter Boström5811a392015-12-10 13:02:50 +01001490 EXPECT_TRUE(observer_->Wait());
sprang867fb522015-08-03 04:38:41 -07001491 }
1492
1493 void UpdateSendConfig(
1494 size_t stream_index,
1495 VideoSendStream::Config* send_config,
1496 VideoEncoderConfig* encoder_config,
1497 test::FrameGeneratorCapturer** frame_generator) override {
1498 send_config->rtp.extensions.clear();
1499 send_config->rtp.extensions.push_back(
1500 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
1501
1502 // Force some padding to be sent.
1503 const int kPaddingBitrateBps = 50000;
1504 int total_target_bitrate = 0;
1505 for (const VideoStream& stream : encoder_config->streams)
1506 total_target_bitrate += stream.target_bitrate_bps;
1507 encoder_config->min_transmit_bitrate_bps =
1508 total_target_bitrate + kPaddingBitrateBps;
1509
1510 // Configure RTX for redundant payload padding.
1511 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang861c55e2015-10-16 10:01:21 -07001512 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[stream_index]);
sprang867fb522015-08-03 04:38:41 -07001513 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
sprang861c55e2015-10-16 10:01:21 -07001514 rtx_to_media_ssrcs_[kSendRtxSsrcs[stream_index]] =
1515 send_config->rtp.ssrcs[0];
1516
1517 if (stream_index == 0)
1518 first_media_ssrc_ = send_config->rtp.ssrcs[0];
sprang867fb522015-08-03 04:38:41 -07001519 }
1520
1521 void UpdateReceiveConfig(
1522 size_t stream_index,
1523 VideoReceiveStream::Config* receive_config) override {
sprang861c55e2015-10-16 10:01:21 -07001524 receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang867fb522015-08-03 04:38:41 -07001525 receive_config->rtp.extensions.clear();
1526 receive_config->rtp.extensions.push_back(
1527 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
1528 }
1529
stefanf116bd02015-10-27 08:29:42 -07001530 test::DirectTransport* CreateSendTransport(Call* sender_call) override {
1531 observer_ = new RtpExtensionHeaderObserver(sender_call, first_media_ssrc_,
sprang861c55e2015-10-16 10:01:21 -07001532 rtx_to_media_ssrcs_);
sprang867fb522015-08-03 04:38:41 -07001533 return observer_;
1534 }
1535
1536 private:
sprang861c55e2015-10-16 10:01:21 -07001537 uint32_t first_media_ssrc_;
1538 std::map<uint32_t, uint32_t> rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001539 RtpExtensionHeaderObserver* observer_;
1540 } tester;
1541
1542 tester.RunTest();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001543}
1544
Stefan Holmer04cb7632016-01-14 20:34:30 +01001545class TransportFeedbackTester : public test::EndToEndTest {
1546 public:
1547 explicit TransportFeedbackTester(bool feedback_enabled,
1548 size_t num_video_streams,
1549 size_t num_audio_streams)
1550 : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
1551 feedback_enabled_(feedback_enabled),
1552 num_video_streams_(num_video_streams),
1553 num_audio_streams_(num_audio_streams) {
1554 // Only one stream of each supported for now.
1555 EXPECT_LE(num_video_streams, 1u);
1556 EXPECT_LE(num_audio_streams, 1u);
1557 }
1558
1559 protected:
1560 Action OnSendRtcp(const uint8_t* data, size_t length) override {
1561 EXPECT_FALSE(HasTransportFeedback(data, length));
1562 return SEND_PACKET;
1563 }
1564
1565 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
1566 if (HasTransportFeedback(data, length))
1567 observation_complete_.Set();
1568 return SEND_PACKET;
1569 }
1570
1571 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
1572 RTCPUtility::RTCPParserV2 parser(data, length, true);
1573 EXPECT_TRUE(parser.IsValid());
1574
1575 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1576 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1577 if (packet_type == RTCPUtility::RTCPPacketTypes::kTransportFeedback)
1578 return true;
1579 packet_type = parser.Iterate();
1580 }
1581
1582 return false;
1583 }
1584
1585 void PerformTest() override {
1586 const int64_t kDisabledFeedbackTimeoutMs = 5000;
1587 EXPECT_EQ(feedback_enabled_,
1588 observation_complete_.Wait(feedback_enabled_
1589 ? test::CallTest::kDefaultTimeoutMs
1590 : kDisabledFeedbackTimeoutMs));
1591 }
1592
1593 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1594 receiver_call_ = receiver_call;
1595 }
1596
1597 size_t GetNumVideoStreams() const override { return num_video_streams_; }
1598 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
1599
1600 void ModifyVideoConfigs(
1601 VideoSendStream::Config* send_config,
1602 std::vector<VideoReceiveStream::Config>* receive_configs,
1603 VideoEncoderConfig* encoder_config) override {
1604 send_config->rtp.extensions.clear();
1605 send_config->rtp.extensions.push_back(
1606 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
1607 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1608 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
1609 }
1610
1611 void ModifyAudioConfigs(
1612 AudioSendStream::Config* send_config,
1613 std::vector<AudioReceiveStream::Config>* receive_configs) override {
1614 send_config->rtp.extensions.clear();
1615 send_config->rtp.extensions.push_back(
1616 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
1617 (*receive_configs)[0].rtp.extensions.clear();
1618 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1619 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001620 }
1621
1622 private:
Erik Språng6b8d3552015-09-24 15:06:57 +02001623 static const int kExtensionId = 5;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001624 const bool feedback_enabled_;
1625 const size_t num_video_streams_;
1626 const size_t num_audio_streams_;
1627 Call* receiver_call_;
1628};
Erik Språng6b8d3552015-09-24 15:06:57 +02001629
Stefan Holmer04cb7632016-01-14 20:34:30 +01001630TEST_F(EndToEndTest, VideoReceivesTransportFeedback) {
1631 TransportFeedbackTester test(true, 1, 0);
1632 RunBaseTest(&test);
Erik Språng6b8d3552015-09-24 15:06:57 +02001633}
stefan43edf0f2015-11-20 18:05:48 -08001634
Stefan Holmer04cb7632016-01-14 20:34:30 +01001635TEST_F(EndToEndTest, VideoTransportFeedbackNotConfigured) {
1636 TransportFeedbackTester test(false, 1, 0);
1637 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001638}
1639
Stefan Holmer04cb7632016-01-14 20:34:30 +01001640TEST_F(EndToEndTest, AudioReceivesTransportFeedback) {
1641 TransportFeedbackTester test(true, 0, 1);
1642 RunBaseTest(&test);
1643}
1644
1645TEST_F(EndToEndTest, AudioTransportFeedbackNotConfigured) {
1646 TransportFeedbackTester test(false, 0, 1);
1647 RunBaseTest(&test);
1648}
1649
1650TEST_F(EndToEndTest, AudioVideoReceivesTransportFeedback) {
1651 TransportFeedbackTester test(true, 1, 1);
1652 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001653}
1654
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001655TEST_F(EndToEndTest, ObserversEncodedFrames) {
1656 class EncodedFrameTestObserver : public EncodedFrameObserver {
1657 public:
1658 EncodedFrameTestObserver()
Peter Boström5811a392015-12-10 13:02:50 +01001659 : length_(0), frame_type_(kEmptyFrame), called_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001660 virtual ~EncodedFrameTestObserver() {}
1661
1662 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
1663 frame_type_ = encoded_frame.frame_type_;
1664 length_ = encoded_frame.length_;
1665 buffer_.reset(new uint8_t[length_]);
1666 memcpy(buffer_.get(), encoded_frame.data_, length_);
Peter Boström5811a392015-12-10 13:02:50 +01001667 called_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001668 }
1669
Peter Boström5811a392015-12-10 13:02:50 +01001670 bool Wait() { return called_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001671
1672 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
1673 ASSERT_EQ(length_, observer.length_)
1674 << "Observed frames are of different lengths.";
1675 EXPECT_EQ(frame_type_, observer.frame_type_)
1676 << "Observed frames have different frame types.";
1677 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
1678 << "Observed encoded frames have different content.";
1679 }
1680
1681 private:
kwiberg27f982b2016-03-01 11:52:33 -08001682 std::unique_ptr<uint8_t[]> buffer_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001683 size_t length_;
1684 FrameType frame_type_;
Peter Boström5811a392015-12-10 13:02:50 +01001685 rtc::Event called_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001686 };
1687
1688 EncodedFrameTestObserver post_encode_observer;
1689 EncodedFrameTestObserver pre_decode_observer;
1690
solenberg4fbae2b2015-08-28 04:07:10 -07001691 CreateCalls(Call::Config(), Call::Config());
1692
stefanf116bd02015-10-27 08:29:42 -07001693 test::DirectTransport sender_transport(sender_call_.get());
1694 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001695 sender_transport.SetReceiver(receiver_call_->Receiver());
1696 receiver_transport.SetReceiver(sender_call_->Receiver());
1697
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001698 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001699 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -08001700 video_send_config_.post_encode_callback = &post_encode_observer;
1701 video_receive_configs_[0].pre_decode_callback = &pre_decode_observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001702
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001703 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001704 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001705
kwiberg27f982b2016-03-01 11:52:33 -08001706 std::unique_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +00001707 test::FrameGenerator::CreateChromaGenerator(
stefanff483612015-12-21 03:14:00 -08001708 video_encoder_config_.streams[0].width,
1709 video_encoder_config_.streams[0].height));
1710 video_send_stream_->Input()->IncomingCapturedFrame(
1711 *frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001712
Peter Boström5811a392015-12-10 13:02:50 +01001713 EXPECT_TRUE(post_encode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001714 << "Timed out while waiting for send-side encoded-frame callback.";
1715
Peter Boström5811a392015-12-10 13:02:50 +01001716 EXPECT_TRUE(pre_decode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001717 << "Timed out while waiting for pre-decode encoded-frame callback.";
1718
1719 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
1720
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001721 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001722
1723 sender_transport.StopSending();
1724 receiver_transport.StopSending();
1725
1726 DestroyStreams();
1727}
1728
1729TEST_F(EndToEndTest, ReceiveStreamSendsRemb) {
1730 class RembObserver : public test::EndToEndTest {
1731 public:
1732 RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
1733
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001734 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001735 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1736 EXPECT_TRUE(parser.IsValid());
1737
1738 bool received_psfb = false;
1739 bool received_remb = false;
1740 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02001741 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1742 if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbRemb) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001743 const RTCPUtility::RTCPPacket& packet = parser.Packet();
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001744 EXPECT_EQ(packet.PSFBAPP.SenderSSRC, kReceiverLocalVideoSsrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001745 received_psfb = true;
Erik Språng242e22b2015-05-11 10:17:43 +02001746 } else if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbRembItem) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001747 const RTCPUtility::RTCPPacket& packet = parser.Packet();
1748 EXPECT_GT(packet.REMBItem.BitRate, 0u);
1749 EXPECT_EQ(packet.REMBItem.NumberOfSSRCs, 1u);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001750 EXPECT_EQ(packet.REMBItem.SSRCs[0], kVideoSendSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001751 received_remb = true;
1752 }
1753 packet_type = parser.Iterate();
1754 }
1755 if (received_psfb && received_remb)
Peter Boström5811a392015-12-10 13:02:50 +01001756 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001757 return SEND_PACKET;
1758 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001759 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001760 EXPECT_TRUE(Wait()) << "Timed out while waiting for a "
1761 "receiver RTCP REMB packet to be "
1762 "sent.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001763 }
1764 } test;
1765
stefane74eef12016-01-08 06:47:13 -08001766 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001767}
1768
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001769TEST_F(EndToEndTest, VerifyBandwidthStats) {
stefanf116bd02015-10-27 08:29:42 -07001770 class RtcpObserver : public test::EndToEndTest {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001771 public:
1772 RtcpObserver()
1773 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001774 sender_call_(nullptr),
1775 receiver_call_(nullptr),
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001776 has_seen_pacer_delay_(false) {}
1777
stefanf116bd02015-10-27 08:29:42 -07001778 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001779 Call::Stats sender_stats = sender_call_->GetStats();
1780 Call::Stats receiver_stats = receiver_call_->GetStats();
1781 if (!has_seen_pacer_delay_)
1782 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
1783 if (sender_stats.send_bandwidth_bps > 0 &&
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001784 receiver_stats.recv_bandwidth_bps > 0 && has_seen_pacer_delay_) {
Peter Boström5811a392015-12-10 13:02:50 +01001785 observation_complete_.Set();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001786 }
stefanf116bd02015-10-27 08:29:42 -07001787 return SEND_PACKET;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001788 }
1789
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001790 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001791 sender_call_ = sender_call;
1792 receiver_call_ = receiver_call;
1793 }
1794
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001795 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001796 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
1797 "non-zero bandwidth stats.";
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001798 }
1799
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001800 private:
1801 Call* sender_call_;
1802 Call* receiver_call_;
1803 bool has_seen_pacer_delay_;
1804 } test;
1805
stefane74eef12016-01-08 06:47:13 -08001806 RunBaseTest(&test);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001807}
1808
stefan32f81542016-01-20 07:13:58 -08001809
1810// Verifies that it's possible to limit the send BWE by sending a REMB.
1811// This is verified by allowing the send BWE to ramp-up to >1000 kbps,
1812// then have the test generate a REMB of 500 kbps and verify that the send BWE
1813// is reduced to exactly 500 kbps. Then a REMB of 1000 kbps is generated and the
1814// test verifies that the send BWE ramps back up to exactly 1000 kbps.
1815TEST_F(EndToEndTest, RembWithSendSideBwe) {
1816 class BweObserver : public test::EndToEndTest {
1817 public:
1818 BweObserver()
1819 : EndToEndTest(kDefaultTimeoutMs),
1820 sender_call_(nullptr),
1821 clock_(Clock::GetRealTimeClock()),
1822 sender_ssrc_(0),
1823 remb_bitrate_bps_(1000000),
1824 receive_transport_(nullptr),
1825 event_(false, false),
1826 poller_thread_(&BitrateStatsPollingThread,
1827 this,
1828 "BitrateStatsPollingThread"),
1829 state_(kWaitForFirstRampUp) {}
1830
1831 ~BweObserver() {}
1832
1833 test::PacketTransport* CreateReceiveTransport() {
1834 receive_transport_ = new test::PacketTransport(
1835 nullptr, this, test::PacketTransport::kReceiver,
1836 FakeNetworkPipe::Config());
1837 return receive_transport_;
1838 }
1839
1840 Call::Config GetSenderCallConfig() override {
1841 Call::Config config;
1842 // Set a high start bitrate to reduce the test completion time.
1843 config.bitrate_config.start_bitrate_bps = remb_bitrate_bps_;
1844 return config;
1845 }
1846
1847 void ModifyVideoConfigs(
1848 VideoSendStream::Config* send_config,
1849 std::vector<VideoReceiveStream::Config>* receive_configs,
1850 VideoEncoderConfig* encoder_config) override {
1851 ASSERT_EQ(1u, send_config->rtp.ssrcs.size());
1852 send_config->rtp.extensions.clear();
1853 send_config->rtp.extensions.push_back(
1854 RtpExtension(RtpExtension::kTransportSequenceNumber,
1855 test::kTransportSequenceNumberExtensionId));
1856 sender_ssrc_ = send_config->rtp.ssrcs[0];
1857
1858 encoder_config->streams[0].max_bitrate_bps =
1859 encoder_config->streams[0].target_bitrate_bps = 2000000;
1860
1861 ASSERT_EQ(1u, receive_configs->size());
1862 (*receive_configs)[0].rtp.remb = false;
1863 (*receive_configs)[0].rtp.transport_cc = true;
1864 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1865 RtpRtcp::Configuration config;
1866 config.receiver_only = true;
1867 config.clock = clock_;
1868 config.outgoing_transport = receive_transport_;
1869 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
1870 rtp_rtcp_->SetRemoteSSRC((*receive_configs)[0].rtp.remote_ssrc);
1871 rtp_rtcp_->SetSSRC((*receive_configs)[0].rtp.local_ssrc);
1872 rtp_rtcp_->SetREMBStatus(true);
1873 rtp_rtcp_->SetSendingStatus(true);
1874 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
1875 }
1876
1877 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1878 sender_call_ = sender_call;
1879 }
1880
1881 static bool BitrateStatsPollingThread(void* obj) {
1882 return static_cast<BweObserver*>(obj)->PollStats();
1883 }
1884
1885 bool PollStats() {
1886 if (sender_call_) {
1887 Call::Stats stats = sender_call_->GetStats();
1888 switch (state_) {
1889 case kWaitForFirstRampUp:
1890 if (stats.send_bandwidth_bps >= remb_bitrate_bps_) {
1891 state_ = kWaitForRemb;
1892 remb_bitrate_bps_ /= 2;
1893 rtp_rtcp_->SetREMBData(
1894 remb_bitrate_bps_,
1895 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
1896 rtp_rtcp_->SendRTCP(kRtcpRr);
1897 }
1898 break;
1899
1900 case kWaitForRemb:
1901 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
1902 state_ = kWaitForSecondRampUp;
1903 remb_bitrate_bps_ *= 2;
1904 rtp_rtcp_->SetREMBData(
1905 remb_bitrate_bps_,
1906 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
1907 rtp_rtcp_->SendRTCP(kRtcpRr);
1908 }
1909 break;
1910
1911 case kWaitForSecondRampUp:
1912 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
1913 observation_complete_.Set();
1914 }
1915 break;
1916 }
1917 }
1918
1919 return !event_.Wait(1000);
1920 }
1921
1922 void PerformTest() override {
1923 poller_thread_.Start();
1924 EXPECT_TRUE(Wait())
1925 << "Timed out while waiting for bitrate to change according to REMB.";
1926 poller_thread_.Stop();
1927 }
1928
1929 private:
1930 enum TestState { kWaitForFirstRampUp, kWaitForRemb, kWaitForSecondRampUp };
1931
1932 Call* sender_call_;
1933 Clock* const clock_;
1934 uint32_t sender_ssrc_;
1935 int remb_bitrate_bps_;
kwiberg27f982b2016-03-01 11:52:33 -08001936 std::unique_ptr<RtpRtcp> rtp_rtcp_;
stefan32f81542016-01-20 07:13:58 -08001937 test::PacketTransport* receive_transport_;
1938 rtc::Event event_;
1939 rtc::PlatformThread poller_thread_;
1940 TestState state_;
1941 } test;
1942
1943 RunBaseTest(&test);
1944}
1945
Åsa Persson352b2d72015-04-15 18:00:40 +02001946TEST_F(EndToEndTest, VerifyNackStats) {
1947 static const int kPacketNumberToDrop = 200;
1948 class NackObserver : public test::EndToEndTest {
1949 public:
1950 NackObserver()
1951 : EndToEndTest(kLongTimeoutMs),
1952 sent_rtp_packets_(0),
1953 dropped_rtp_packet_(0),
1954 dropped_rtp_packet_requested_(false),
1955 send_stream_(nullptr),
1956 start_runtime_ms_(-1) {}
1957
1958 private:
1959 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08001960 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02001961 if (++sent_rtp_packets_ == kPacketNumberToDrop) {
kwiberg27f982b2016-03-01 11:52:33 -08001962 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
Åsa Persson352b2d72015-04-15 18:00:40 +02001963 RTPHeader header;
1964 EXPECT_TRUE(parser->Parse(packet, length, &header));
1965 dropped_rtp_packet_ = header.sequenceNumber;
1966 return DROP_PACKET;
1967 }
1968 VerifyStats();
1969 return SEND_PACKET;
1970 }
1971
1972 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08001973 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02001974 test::RtcpPacketParser rtcp_parser;
1975 rtcp_parser.Parse(packet, length);
1976 std::vector<uint16_t> nacks = rtcp_parser.nack_item()->last_nack_list();
1977 if (!nacks.empty() && std::find(
1978 nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) {
1979 dropped_rtp_packet_requested_ = true;
1980 }
1981 return SEND_PACKET;
1982 }
1983
stefan608213e2015-11-01 14:56:10 -08001984 void VerifyStats() EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
Åsa Persson352b2d72015-04-15 18:00:40 +02001985 if (!dropped_rtp_packet_requested_)
1986 return;
1987 int send_stream_nack_packets = 0;
1988 int receive_stream_nack_packets = 0;
1989 VideoSendStream::Stats stats = send_stream_->GetStats();
1990 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
1991 stats.substreams.begin(); it != stats.substreams.end(); ++it) {
1992 const VideoSendStream::StreamStats& stream_stats = it->second;
1993 send_stream_nack_packets +=
1994 stream_stats.rtcp_packet_type_counts.nack_packets;
1995 }
1996 for (size_t i = 0; i < receive_streams_.size(); ++i) {
1997 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
1998 receive_stream_nack_packets +=
1999 stats.rtcp_packet_type_counts.nack_packets;
2000 }
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002001 if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002002 // NACK packet sent on receive stream and received on sent stream.
2003 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002004 observation_complete_.Set();
Åsa Persson352b2d72015-04-15 18:00:40 +02002005 }
2006 }
2007
2008 bool MinMetricRunTimePassed() {
2009 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2010 if (start_runtime_ms_ == -1) {
2011 start_runtime_ms_ = now;
2012 return false;
2013 }
2014 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2015 return elapsed_sec > metrics::kMinRunTimeInSeconds;
2016 }
2017
stefanff483612015-12-21 03:14:00 -08002018 void ModifyVideoConfigs(
2019 VideoSendStream::Config* send_config,
2020 std::vector<VideoReceiveStream::Config>* receive_configs,
2021 VideoEncoderConfig* encoder_config) override {
Åsa Persson352b2d72015-04-15 18:00:40 +02002022 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2023 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2024 }
2025
stefanff483612015-12-21 03:14:00 -08002026 void OnVideoStreamsCreated(
Åsa Persson352b2d72015-04-15 18:00:40 +02002027 VideoSendStream* send_stream,
2028 const std::vector<VideoReceiveStream*>& receive_streams) override {
2029 send_stream_ = send_stream;
2030 receive_streams_ = receive_streams;
2031 }
2032
2033 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002034 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson352b2d72015-04-15 18:00:40 +02002035 }
2036
stefan608213e2015-11-01 14:56:10 -08002037 rtc::CriticalSection crit_;
Åsa Persson352b2d72015-04-15 18:00:40 +02002038 uint64_t sent_rtp_packets_;
stefan608213e2015-11-01 14:56:10 -08002039 uint16_t dropped_rtp_packet_ GUARDED_BY(&crit_);
2040 bool dropped_rtp_packet_requested_ GUARDED_BY(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002041 std::vector<VideoReceiveStream*> receive_streams_;
2042 VideoSendStream* send_stream_;
2043 int64_t start_runtime_ms_;
2044 } test;
2045
Åsa Persson3c391cb2015-04-27 10:09:49 +02002046 test::ClearHistograms();
stefane74eef12016-01-08 06:47:13 -08002047 RunBaseTest(&test);
Åsa Persson352b2d72015-04-15 18:00:40 +02002048
Åsa Persson3c391cb2015-04-27 10:09:49 +02002049 EXPECT_EQ(1, test::NumHistogramSamples(
Åsa Persson352b2d72015-04-15 18:00:40 +02002050 "WebRTC.Video.UniqueNackRequestsSentInPercent"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002051 EXPECT_EQ(1, test::NumHistogramSamples(
Åsa Persson352b2d72015-04-15 18:00:40 +02002052 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
2053 EXPECT_GT(test::LastHistogramSample(
2054 "WebRTC.Video.NackPacketsSentPerMinute"), 0);
2055 EXPECT_GT(test::LastHistogramSample(
2056 "WebRTC.Video.NackPacketsReceivedPerMinute"), 0);
2057}
2058
sprangb4a1ae52015-12-03 08:10:08 -08002059void EndToEndTest::VerifyHistogramStats(bool use_rtx,
2060 bool use_red,
2061 bool screenshare) {
stefanf116bd02015-10-27 08:29:42 -07002062 class StatsObserver : public test::EndToEndTest {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002063 public:
sprangb4a1ae52015-12-03 08:10:08 -08002064 StatsObserver(bool use_rtx, bool use_red, bool screenshare)
Åsa Persson3c391cb2015-04-27 10:09:49 +02002065 : EndToEndTest(kLongTimeoutMs),
2066 use_rtx_(use_rtx),
2067 use_red_(use_red),
sprangb4a1ae52015-12-03 08:10:08 -08002068 screenshare_(screenshare),
Peter Boström39593972016-02-15 11:27:15 +01002069 // This test uses NACK, so to send FEC we can't use a fake encoder.
2070 vp8_encoder_(
2071 use_red ? VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)
2072 : nullptr),
Åsa Persson3c391cb2015-04-27 10:09:49 +02002073 sender_call_(nullptr),
2074 receiver_call_(nullptr),
2075 start_runtime_ms_(-1) {}
2076
2077 private:
2078 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2079 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002080 observation_complete_.Set();
Åsa Persson3c391cb2015-04-27 10:09:49 +02002081
stefanf116bd02015-10-27 08:29:42 -07002082 return SEND_PACKET;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002083 }
2084
2085 bool MinMetricRunTimePassed() {
2086 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2087 if (start_runtime_ms_ == -1) {
2088 start_runtime_ms_ = now;
2089 return false;
2090 }
2091 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2092 return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
2093 }
2094
stefanff483612015-12-21 03:14:00 -08002095 void ModifyVideoConfigs(
2096 VideoSendStream::Config* send_config,
2097 std::vector<VideoReceiveStream::Config>* receive_configs,
2098 VideoEncoderConfig* encoder_config) override {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002099 // NACK
2100 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2101 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2102 // FEC
2103 if (use_red_) {
2104 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
2105 send_config->rtp.fec.red_payload_type = kRedPayloadType;
Peter Boström39593972016-02-15 11:27:15 +01002106 send_config->encoder_settings.encoder = vp8_encoder_.get();
2107 send_config->encoder_settings.payload_name = "VP8";
2108 (*receive_configs)[0].decoders[0].payload_name = "VP8";
Åsa Persson3c391cb2015-04-27 10:09:49 +02002109 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
2110 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
2111 }
2112 // RTX
2113 if (use_rtx_) {
2114 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
2115 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002116 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002117 kSendRtxSsrcs[0];
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002118 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002119 kSendRtxPayloadType;
2120 }
asapersson52495992016-03-08 02:10:16 -08002121 // RTT needed for RemoteNtpTimeEstimator for the receive stream.
2122 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = true;
sprangb4a1ae52015-12-03 08:10:08 -08002123 encoder_config->content_type =
2124 screenshare_ ? VideoEncoderConfig::ContentType::kScreen
2125 : VideoEncoderConfig::ContentType::kRealtimeVideo;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002126 }
2127
2128 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2129 sender_call_ = sender_call;
2130 receiver_call_ = receiver_call;
2131 }
2132
Åsa Persson3c391cb2015-04-27 10:09:49 +02002133 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002134 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson3c391cb2015-04-27 10:09:49 +02002135 }
2136
sprangb4a1ae52015-12-03 08:10:08 -08002137 const bool use_rtx_;
2138 const bool use_red_;
2139 const bool screenshare_;
kwiberg27f982b2016-03-01 11:52:33 -08002140 const std::unique_ptr<VideoEncoder> vp8_encoder_;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002141 Call* sender_call_;
2142 Call* receiver_call_;
2143 int64_t start_runtime_ms_;
sprangb4a1ae52015-12-03 08:10:08 -08002144 } test(use_rtx, use_red, screenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002145
2146 test::ClearHistograms();
stefane74eef12016-01-08 06:47:13 -08002147 RunBaseTest(&test);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002148
stefan91d92602015-11-11 10:13:02 -08002149 // Delete the call for Call stats to be reported.
stefan18adf0a2015-11-17 06:24:56 -08002150 sender_call_.reset();
stefan91d92602015-11-11 10:13:02 -08002151 receiver_call_.reset();
2152
sprangb4a1ae52015-12-03 08:10:08 -08002153 std::string video_prefix =
2154 screenshare ? "WebRTC.Video.Screenshare." : "WebRTC.Video.";
2155
Åsa Persson3c391cb2015-04-27 10:09:49 +02002156 // Verify that stats have been updated once.
stefan91d92602015-11-11 10:13:02 -08002157 EXPECT_EQ(
2158 1, test::NumHistogramSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
2159 EXPECT_EQ(1,
2160 test::NumHistogramSamples("WebRTC.Call.RtcpBitrateReceivedInBps"));
2161 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Call.BitrateReceivedInKbps"));
stefan18adf0a2015-11-17 06:24:56 -08002162 EXPECT_EQ(
2163 1, test::NumHistogramSamples("WebRTC.Call.EstimatedSendBitrateInKbps"));
2164 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Call.PacerBitrateInKbps"));
stefan91d92602015-11-11 10:13:02 -08002165
Åsa Persson3c391cb2015-04-27 10:09:49 +02002166 EXPECT_EQ(1, test::NumHistogramSamples(
2167 "WebRTC.Video.NackPacketsSentPerMinute"));
sprang07fb9be2016-02-24 07:55:00 -08002168 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix +
2169 "NackPacketsReceivedPerMinute"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002170 EXPECT_EQ(1, test::NumHistogramSamples(
2171 "WebRTC.Video.FirPacketsSentPerMinute"));
sprang07fb9be2016-02-24 07:55:00 -08002172 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix +
2173 "FirPacketsReceivedPerMinute"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002174 EXPECT_EQ(1, test::NumHistogramSamples(
2175 "WebRTC.Video.PliPacketsSentPerMinute"));
sprang07fb9be2016-02-24 07:55:00 -08002176 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix +
2177 "PliPacketsReceivedPerMinute"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002178
sprangb4a1ae52015-12-03 08:10:08 -08002179 EXPECT_EQ(
2180 1, test::NumHistogramSamples(video_prefix + "KeyFramesSentInPermille"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002181 EXPECT_EQ(1, test::NumHistogramSamples(
2182 "WebRTC.Video.KeyFramesReceivedInPermille"));
2183
sprange2d83d62016-02-19 09:03:26 -08002184 EXPECT_EQ(
2185 1, test::NumHistogramSamples(video_prefix + "SentPacketsLostInPercent"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002186 EXPECT_EQ(1, test::NumHistogramSamples(
2187 "WebRTC.Video.ReceivedPacketsLostInPercent"));
2188
sprangb4a1ae52015-12-03 08:10:08 -08002189 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "InputWidthInPixels"));
2190 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "InputHeightInPixels"));
2191 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SentWidthInPixels"));
2192 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SentHeightInPixels"));
asaperssond89920b2015-07-22 06:52:00 -07002193 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.ReceivedWidthInPixels"));
2194 EXPECT_EQ(1,
2195 test::NumHistogramSamples("WebRTC.Video.ReceivedHeightInPixels"));
2196
stefanff483612015-12-21 03:14:00 -08002197 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].width),
sprangb4a1ae52015-12-03 08:10:08 -08002198 test::LastHistogramSample(video_prefix + "InputWidthInPixels"));
stefanff483612015-12-21 03:14:00 -08002199 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].height),
sprangb4a1ae52015-12-03 08:10:08 -08002200 test::LastHistogramSample(video_prefix + "InputHeightInPixels"));
stefanff483612015-12-21 03:14:00 -08002201 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].width),
sprangb4a1ae52015-12-03 08:10:08 -08002202 test::LastHistogramSample(video_prefix + "SentWidthInPixels"));
stefanff483612015-12-21 03:14:00 -08002203 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].height),
sprangb4a1ae52015-12-03 08:10:08 -08002204 test::LastHistogramSample(video_prefix + "SentHeightInPixels"));
stefanff483612015-12-21 03:14:00 -08002205 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].width),
asaperssond89920b2015-07-22 06:52:00 -07002206 test::LastHistogramSample("WebRTC.Video.ReceivedWidthInPixels"));
stefanff483612015-12-21 03:14:00 -08002207 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].height),
asaperssond89920b2015-07-22 06:52:00 -07002208 test::LastHistogramSample("WebRTC.Video.ReceivedHeightInPixels"));
2209
sprangb4a1ae52015-12-03 08:10:08 -08002210 EXPECT_EQ(1,
2211 test::NumHistogramSamples(video_prefix + "InputFramesPerSecond"));
2212 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SentFramesPerSecond"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002213 EXPECT_EQ(1, test::NumHistogramSamples(
2214 "WebRTC.Video.DecodedFramesPerSecond"));
asaperssond89920b2015-07-22 06:52:00 -07002215 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.RenderFramesPerSecond"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002216
asapersson6f14be82015-11-16 00:40:49 -08002217 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.OnewayDelayInMs"));
2218 EXPECT_EQ(
2219 1, test::NumHistogramSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
2220
sprangb4a1ae52015-12-03 08:10:08 -08002221 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "EncodeTimeInMs"));
asapersson6718e972015-07-24 00:20:58 -07002222 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.DecodeTimeInMs"));
2223
Erik Språng22c2b482016-03-01 09:40:42 +01002224 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "BitrateSentInKbps"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002225 EXPECT_EQ(1, test::NumHistogramSamples(
2226 "WebRTC.Video.BitrateReceivedInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002227 EXPECT_EQ(1,
2228 test::NumHistogramSamples(video_prefix + "MediaBitrateSentInKbps"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002229 EXPECT_EQ(1, test::NumHistogramSamples(
2230 "WebRTC.Video.MediaBitrateReceivedInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002231 EXPECT_EQ(
2232 1, test::NumHistogramSamples(video_prefix + "PaddingBitrateSentInKbps"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002233 EXPECT_EQ(1, test::NumHistogramSamples(
2234 "WebRTC.Video.PaddingBitrateReceivedInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002235 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix +
2236 "RetransmittedBitrateSentInKbps"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002237 EXPECT_EQ(1, test::NumHistogramSamples(
2238 "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
2239
sprangb4a1ae52015-12-03 08:10:08 -08002240 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SendSideDelayInMs"));
2241 EXPECT_EQ(1,
2242 test::NumHistogramSamples(video_prefix + "SendSideDelayMaxInMs"));
asapersson6f14be82015-11-16 00:40:49 -08002243
Åsa Persson3c391cb2015-04-27 10:09:49 +02002244 int num_rtx_samples = use_rtx ? 1 : 0;
2245 EXPECT_EQ(num_rtx_samples, test::NumHistogramSamples(
2246 "WebRTC.Video.RtxBitrateSentInKbps"));
2247 EXPECT_EQ(num_rtx_samples, test::NumHistogramSamples(
2248 "WebRTC.Video.RtxBitrateReceivedInKbps"));
2249
2250 int num_red_samples = use_red ? 1 : 0;
2251 EXPECT_EQ(num_red_samples, test::NumHistogramSamples(
2252 "WebRTC.Video.FecBitrateSentInKbps"));
2253 EXPECT_EQ(num_red_samples, test::NumHistogramSamples(
2254 "WebRTC.Video.FecBitrateReceivedInKbps"));
2255 EXPECT_EQ(num_red_samples, test::NumHistogramSamples(
2256 "WebRTC.Video.ReceivedFecPacketsInPercent"));
2257}
2258
2259TEST_F(EndToEndTest, VerifyHistogramStatsWithRtx) {
2260 const bool kEnabledRtx = true;
2261 const bool kEnabledRed = false;
sprangb4a1ae52015-12-03 08:10:08 -08002262 const bool kScreenshare = false;
2263 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002264}
2265
2266TEST_F(EndToEndTest, VerifyHistogramStatsWithRed) {
2267 const bool kEnabledRtx = false;
2268 const bool kEnabledRed = true;
sprangb4a1ae52015-12-03 08:10:08 -08002269 const bool kScreenshare = false;
2270 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
2271}
2272
2273TEST_F(EndToEndTest, VerifyHistogramStatsWithScreenshare) {
2274 const bool kEnabledRtx = false;
2275 const bool kEnabledRed = false;
2276 const bool kScreenshare = true;
2277 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002278}
2279
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002280void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
2281 static const int kNumRtcpReportPacketsToObserve = 5;
2282 class RtcpXrObserver : public test::EndToEndTest {
2283 public:
2284 explicit RtcpXrObserver(bool enable_rrtr)
2285 : EndToEndTest(kDefaultTimeoutMs),
2286 enable_rrtr_(enable_rrtr),
2287 sent_rtcp_sr_(0),
2288 sent_rtcp_rr_(0),
2289 sent_rtcp_rrtr_(0),
2290 sent_rtcp_dlrr_(0) {}
2291
2292 private:
2293 // Receive stream should send RR packets (and RRTR packets if enabled).
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002294 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002295 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002296 RTCPUtility::RTCPParserV2 parser(packet, length, true);
2297 EXPECT_TRUE(parser.IsValid());
2298
2299 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02002300 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
2301 if (packet_type == RTCPUtility::RTCPPacketTypes::kRr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002302 ++sent_rtcp_rr_;
2303 } else if (packet_type ==
Erik Språng242e22b2015-05-11 10:17:43 +02002304 RTCPUtility::RTCPPacketTypes::kXrReceiverReferenceTime) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002305 ++sent_rtcp_rrtr_;
2306 }
Erik Språng242e22b2015-05-11 10:17:43 +02002307 EXPECT_NE(packet_type, RTCPUtility::RTCPPacketTypes::kSr);
2308 EXPECT_NE(packet_type,
2309 RTCPUtility::RTCPPacketTypes::kXrDlrrReportBlockItem);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002310 packet_type = parser.Iterate();
2311 }
2312 return SEND_PACKET;
2313 }
2314 // Send stream should send SR packets (and DLRR packets if enabled).
2315 virtual Action OnSendRtcp(const uint8_t* packet, size_t length) {
stefan608213e2015-11-01 14:56:10 -08002316 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002317 RTCPUtility::RTCPParserV2 parser(packet, length, true);
2318 EXPECT_TRUE(parser.IsValid());
2319
2320 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02002321 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
2322 if (packet_type == RTCPUtility::RTCPPacketTypes::kSr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002323 ++sent_rtcp_sr_;
Erik Språng242e22b2015-05-11 10:17:43 +02002324 } else if (packet_type ==
2325 RTCPUtility::RTCPPacketTypes::kXrDlrrReportBlockItem) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002326 ++sent_rtcp_dlrr_;
2327 }
Erik Språng242e22b2015-05-11 10:17:43 +02002328 EXPECT_NE(packet_type,
2329 RTCPUtility::RTCPPacketTypes::kXrReceiverReferenceTime);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002330 packet_type = parser.Iterate();
2331 }
2332 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
2333 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve) {
2334 if (enable_rrtr_) {
2335 EXPECT_GT(sent_rtcp_rrtr_, 0);
2336 EXPECT_GT(sent_rtcp_dlrr_, 0);
2337 } else {
2338 EXPECT_EQ(0, sent_rtcp_rrtr_);
2339 EXPECT_EQ(0, sent_rtcp_dlrr_);
2340 }
Peter Boström5811a392015-12-10 13:02:50 +01002341 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002342 }
2343 return SEND_PACKET;
2344 }
2345
stefanff483612015-12-21 03:14:00 -08002346 void ModifyVideoConfigs(
2347 VideoSendStream::Config* send_config,
2348 std::vector<VideoReceiveStream::Config>* receive_configs,
2349 VideoEncoderConfig* encoder_config) override {
pbosda903ea2015-10-02 02:36:56 -07002350 (*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002351 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
2352 enable_rrtr_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002353 }
2354
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002355 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002356 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002357 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
2358 }
2359
stefan608213e2015-11-01 14:56:10 -08002360 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002361 bool enable_rrtr_;
2362 int sent_rtcp_sr_;
stefan608213e2015-11-01 14:56:10 -08002363 int sent_rtcp_rr_ GUARDED_BY(&crit_);
2364 int sent_rtcp_rrtr_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002365 int sent_rtcp_dlrr_;
2366 } test(enable_rrtr);
2367
stefane74eef12016-01-08 06:47:13 -08002368 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002369}
2370
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002371void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
2372 bool send_single_ssrc_first) {
2373 class SendsSetSsrcs : public test::EndToEndTest {
2374 public:
2375 SendsSetSsrcs(const uint32_t* ssrcs,
2376 size_t num_ssrcs,
2377 bool send_single_ssrc_first)
2378 : EndToEndTest(kDefaultTimeoutMs),
2379 num_ssrcs_(num_ssrcs),
2380 send_single_ssrc_first_(send_single_ssrc_first),
2381 ssrcs_to_observe_(num_ssrcs),
sprang867fb522015-08-03 04:38:41 -07002382 expect_single_ssrc_(send_single_ssrc_first),
2383 send_stream_(nullptr) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002384 for (size_t i = 0; i < num_ssrcs; ++i)
2385 valid_ssrcs_[ssrcs[i]] = true;
2386 }
2387
2388 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002389 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002390 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002391 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002392
2393 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
2394 << "Received unknown SSRC: " << header.ssrc;
2395
2396 if (!valid_ssrcs_[header.ssrc])
Peter Boström5811a392015-12-10 13:02:50 +01002397 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002398
2399 if (!is_observed_[header.ssrc]) {
2400 is_observed_[header.ssrc] = true;
2401 --ssrcs_to_observe_;
2402 if (expect_single_ssrc_) {
2403 expect_single_ssrc_ = false;
Peter Boström5811a392015-12-10 13:02:50 +01002404 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002405 }
2406 }
2407
2408 if (ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002409 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002410
2411 return SEND_PACKET;
2412 }
2413
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002414 size_t GetNumVideoStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002415
stefanff483612015-12-21 03:14:00 -08002416 void ModifyVideoConfigs(
2417 VideoSendStream::Config* send_config,
2418 std::vector<VideoReceiveStream::Config>* receive_configs,
2419 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002420 if (num_ssrcs_ > 1) {
2421 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002422 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2423 encoder_config->streams[i].min_bitrate_bps = 10000;
2424 encoder_config->streams[i].target_bitrate_bps = 15000;
2425 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002426 }
2427 }
2428
stefanff483612015-12-21 03:14:00 -08002429 video_encoder_config_all_streams_ = *encoder_config;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002430 if (send_single_ssrc_first_)
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002431 encoder_config->streams.resize(1);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002432 }
2433
stefanff483612015-12-21 03:14:00 -08002434 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002435 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002436 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002437 send_stream_ = send_stream;
2438 }
2439
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002440 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002441 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2442 << (send_single_ssrc_first_ ? "first SSRC."
2443 : "SSRCs.");
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002444
2445 if (send_single_ssrc_first_) {
2446 // Set full simulcast and continue with the rest of the SSRCs.
stefanff483612015-12-21 03:14:00 -08002447 send_stream_->ReconfigureVideoEncoder(
2448 video_encoder_config_all_streams_);
Peter Boström5811a392015-12-10 13:02:50 +01002449 EXPECT_TRUE(Wait()) << "Timed out while waiting on additional SSRCs.";
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002450 }
2451 }
2452
2453 private:
2454 std::map<uint32_t, bool> valid_ssrcs_;
2455 std::map<uint32_t, bool> is_observed_;
2456
2457 const size_t num_ssrcs_;
2458 const bool send_single_ssrc_first_;
2459
2460 size_t ssrcs_to_observe_;
2461 bool expect_single_ssrc_;
2462
2463 VideoSendStream* send_stream_;
stefanff483612015-12-21 03:14:00 -08002464 VideoEncoderConfig video_encoder_config_all_streams_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002465 } test(kVideoSendSsrcs, num_ssrcs, send_single_ssrc_first);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002466
stefane74eef12016-01-08 06:47:13 -08002467 RunBaseTest(&test);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002468}
2469
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002470TEST_F(EndToEndTest, ReportsSetEncoderRates) {
2471 class EncoderRateStatsTest : public test::EndToEndTest,
2472 public test::FakeEncoder {
2473 public:
2474 EncoderRateStatsTest()
2475 : EndToEndTest(kDefaultTimeoutMs),
sprang867fb522015-08-03 04:38:41 -07002476 FakeEncoder(Clock::GetRealTimeClock()),
2477 send_stream_(nullptr),
2478 bitrate_kbps_(0) {}
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002479
stefanff483612015-12-21 03:14:00 -08002480 void OnVideoStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002481 VideoSendStream* send_stream,
2482 const std::vector<VideoReceiveStream*>& receive_streams) override {
2483 send_stream_ = send_stream;
2484 }
2485
stefanff483612015-12-21 03:14:00 -08002486 void ModifyVideoConfigs(
2487 VideoSendStream::Config* send_config,
2488 std::vector<VideoReceiveStream::Config>* receive_configs,
2489 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002490 send_config->encoder_settings.encoder = this;
2491 }
2492
2493 int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override {
2494 // Make sure not to trigger on any default zero bitrates.
2495 if (new_target_bitrate == 0)
2496 return 0;
Peter Boströmf2f82832015-05-01 13:00:41 +02002497 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002498 bitrate_kbps_ = new_target_bitrate;
Peter Boström5811a392015-12-10 13:02:50 +01002499 observation_complete_.Set();
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002500 return 0;
2501 }
2502
2503 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002504 ASSERT_TRUE(Wait())
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002505 << "Timed out while waiting for encoder SetRates() call.";
2506 // Wait for GetStats to report a corresponding bitrate.
Peter Boström5811a392015-12-10 13:02:50 +01002507 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002508 VideoSendStream::Stats stats = send_stream_->GetStats();
2509 {
Peter Boströmf2f82832015-05-01 13:00:41 +02002510 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002511 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
2512 static_cast<int>(bitrate_kbps_)) {
2513 return;
2514 }
2515 }
2516 SleepMs(1);
2517 }
2518 FAIL()
2519 << "Timed out waiting for stats reporting the currently set bitrate.";
2520 }
2521
2522 private:
stefanf116bd02015-10-27 08:29:42 -07002523 rtc::CriticalSection crit_;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002524 VideoSendStream* send_stream_;
2525 uint32_t bitrate_kbps_ GUARDED_BY(crit_);
2526 } test;
2527
stefane74eef12016-01-08 06:47:13 -08002528 RunBaseTest(&test);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002529}
2530
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002531TEST_F(EndToEndTest, GetStats) {
2532 static const int kStartBitrateBps = 3000000;
Peter Boströmdef398832015-05-27 17:59:11 +02002533 static const int kExpectedRenderDelayMs = 20;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002534 class StatsObserver : public test::EndToEndTest, public I420FrameCallback {
2535 public:
stefanf116bd02015-10-27 08:29:42 -07002536 StatsObserver()
2537 : EndToEndTest(kLongTimeoutMs),
Peter Boströmc6e16e32016-02-05 14:15:53 +01002538 encoder_(Clock::GetRealTimeClock(), 10),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002539 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002540 expected_send_ssrcs_(),
Peter Boström5811a392015-12-10 13:02:50 +01002541 check_stats_event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002542
2543 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002544 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002545 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002546 return SEND_PACKET;
2547 }
2548
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002549 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002550 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002551 return SEND_PACKET;
2552 }
2553
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002554 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002555 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002556 return SEND_PACKET;
2557 }
2558
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002559 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002560 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002561 return SEND_PACKET;
2562 }
2563
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07002564 void FrameCallback(VideoFrame* video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002565 // Ensure that we have at least 5ms send side delay.
2566 int64_t render_time = video_frame->render_time_ms();
2567 if (render_time > 0)
2568 video_frame->set_render_time_ms(render_time - 5);
2569 }
2570
2571 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002572 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2573 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2574 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002575
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002576 // Make sure all fields have been populated.
2577 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
2578 // always filled for all receivers.
2579 receive_stats_filled_["IncomingRate"] |=
2580 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002581
Peter Boströmb7d9a972015-12-18 16:01:11 +01002582 send_stats_filled_["DecoderImplementationName"] |=
2583 stats.decoder_implementation_name ==
2584 test::FakeDecoder::kImplementationName;
Peter Boströmdef398832015-05-27 17:59:11 +02002585 receive_stats_filled_["RenderDelayAsHighAsExpected"] |=
2586 stats.render_delay_ms >= kExpectedRenderDelayMs;
2587
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002588 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002589
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002590 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002591
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002592 receive_stats_filled_["StatisticsUpdated"] |=
2593 stats.rtcp_stats.cumulative_lost != 0 ||
2594 stats.rtcp_stats.extended_max_sequence_number != 0 ||
2595 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002596
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002597 receive_stats_filled_["DataCountersUpdated"] |=
2598 stats.rtp_stats.transmitted.payload_bytes != 0 ||
2599 stats.rtp_stats.fec.packets != 0 ||
2600 stats.rtp_stats.transmitted.header_bytes != 0 ||
2601 stats.rtp_stats.transmitted.packets != 0 ||
2602 stats.rtp_stats.transmitted.padding_bytes != 0 ||
2603 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002604
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002605 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002606 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002607
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002608 receive_stats_filled_["FrameCounts"] |=
2609 stats.frame_counts.key_frames != 0 ||
2610 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002611
pbosbb36fdf2015-07-09 07:48:14 -07002612 receive_stats_filled_["CName"] |= !stats.c_name.empty();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002613
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002614 receive_stats_filled_["RtcpPacketTypeCount"] |=
2615 stats.rtcp_packet_type_counts.fir_packets != 0 ||
2616 stats.rtcp_packet_type_counts.nack_packets != 0 ||
2617 stats.rtcp_packet_type_counts.pli_packets != 0 ||
2618 stats.rtcp_packet_type_counts.nack_requests != 0 ||
2619 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbosf42376c2015-08-28 07:35:32 -07002620
2621 assert(stats.current_payload_type == -1 ||
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002622 stats.current_payload_type == kFakeVideoSendPayloadType);
pbosf42376c2015-08-28 07:35:32 -07002623 receive_stats_filled_["IncomingPayloadType"] |=
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002624 stats.current_payload_type == kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002625 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002626
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002627 return AllStatsFilled(receive_stats_filled_);
2628 }
2629
2630 bool CheckSendStats() {
henrikg91d6ede2015-09-17 00:24:34 -07002631 RTC_DCHECK(send_stream_ != nullptr);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002632 VideoSendStream::Stats stats = send_stream_->GetStats();
2633
2634 send_stats_filled_["NumStreams"] |=
2635 stats.substreams.size() == expected_send_ssrcs_.size();
2636
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002637 send_stats_filled_["CpuOveruseMetrics"] |=
Peter Boströme4499152016-02-05 11:13:28 +01002638 stats.avg_encode_time_ms != 0 && stats.encode_usage_percent != 0;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002639
Peter Boströmb7d9a972015-12-18 16:01:11 +01002640 send_stats_filled_["EncoderImplementationName"] |=
2641 stats.encoder_implementation_name ==
2642 test::FakeEncoder::kImplementationName;
2643
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002644 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002645 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002646 it != stats.substreams.end(); ++it) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002647 EXPECT_TRUE(expected_send_ssrcs_.find(it->first) !=
2648 expected_send_ssrcs_.end());
2649
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002650 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002651 stats.input_frame_rate != 0;
2652
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002653 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002654
2655 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
2656 stream_stats.rtcp_stats.cumulative_lost != 0 ||
2657 stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
2658 stream_stats.rtcp_stats.fraction_lost != 0;
2659
2660 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002661 stream_stats.rtp_stats.fec.packets != 0 ||
2662 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
2663 stream_stats.rtp_stats.retransmitted.packets != 0 ||
2664 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002665
2666 send_stats_filled_[CompoundKey("BitrateStatisticsObserver",
2667 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002668 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002669
2670 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002671 stream_stats.frame_counts.delta_frames != 0 ||
2672 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002673
2674 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
2675 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00002676
2677 send_stats_filled_[CompoundKey("Delay", it->first)] |=
2678 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002679
2680 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
2681 // report dropped packets.
2682 send_stats_filled_["RtcpPacketTypeCount"] |=
2683 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
2684 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
2685 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
2686 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
2687 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002688 }
2689
2690 return AllStatsFilled(send_stats_filled_);
2691 }
2692
2693 std::string CompoundKey(const char* name, uint32_t ssrc) {
2694 std::ostringstream oss;
2695 oss << name << "_" << ssrc;
2696 return oss.str();
2697 }
2698
2699 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
2700 for (std::map<std::string, bool>::const_iterator it = stats_map.begin();
2701 it != stats_map.end();
2702 ++it) {
2703 if (!it->second)
2704 return false;
2705 }
2706 return true;
2707 }
2708
stefane74eef12016-01-08 06:47:13 -08002709 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
2710 FakeNetworkPipe::Config network_config;
2711 network_config.loss_percent = 5;
2712 return new test::PacketTransport(
2713 sender_call, this, test::PacketTransport::kSender, network_config);
2714 }
2715
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002716 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002717 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01002718 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002719 return config;
2720 }
2721
stefanff483612015-12-21 03:14:00 -08002722 void ModifyVideoConfigs(
2723 VideoSendStream::Config* send_config,
2724 std::vector<VideoReceiveStream::Config>* receive_configs,
2725 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002726 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002727 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002728
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002729 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002730 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002731 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002732 expected_receive_ssrcs_.push_back(
2733 (*receive_configs)[i].rtp.remote_ssrc);
Peter Boströmdef398832015-05-27 17:59:11 +02002734 (*receive_configs)[i].render_delay_ms = kExpectedRenderDelayMs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002735 }
Peter Boströmc6e16e32016-02-05 14:15:53 +01002736 // Use a delayed encoder to make sure we see CpuOveruseMetrics stats that
2737 // are non-zero.
2738 send_config->encoder_settings.encoder = &encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002739 }
2740
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002741 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00002742
stefanff483612015-12-21 03:14:00 -08002743 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002744 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002745 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002746 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002747 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002748 }
2749
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002750 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002751 Clock* clock = Clock::GetRealTimeClock();
2752 int64_t now = clock->TimeInMilliseconds();
2753 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
2754 bool receive_ok = false;
2755 bool send_ok = false;
2756
2757 while (now < stop_time) {
2758 if (!receive_ok)
2759 receive_ok = CheckReceiveStats();
2760 if (!send_ok)
2761 send_ok = CheckSendStats();
2762
2763 if (receive_ok && send_ok)
2764 return;
2765
2766 int64_t time_until_timout_ = stop_time - now;
2767 if (time_until_timout_ > 0)
Peter Boström5811a392015-12-10 13:02:50 +01002768 check_stats_event_.Wait(time_until_timout_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002769 now = clock->TimeInMilliseconds();
2770 }
2771
2772 ADD_FAILURE() << "Timed out waiting for filled stats.";
2773 for (std::map<std::string, bool>::const_iterator it =
2774 receive_stats_filled_.begin();
2775 it != receive_stats_filled_.end();
2776 ++it) {
2777 if (!it->second) {
2778 ADD_FAILURE() << "Missing receive stats: " << it->first;
2779 }
2780 }
2781
2782 for (std::map<std::string, bool>::const_iterator it =
2783 send_stats_filled_.begin();
2784 it != send_stats_filled_.end();
2785 ++it) {
2786 if (!it->second) {
2787 ADD_FAILURE() << "Missing send stats: " << it->first;
2788 }
2789 }
2790 }
2791
Peter Boströmc6e16e32016-02-05 14:15:53 +01002792 test::DelayedEncoder encoder_;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002793 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002794 std::map<std::string, bool> receive_stats_filled_;
2795
2796 VideoSendStream* send_stream_;
2797 std::map<std::string, bool> send_stats_filled_;
2798
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002799 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002800 std::set<uint32_t> expected_send_ssrcs_;
2801 std::string expected_cname_;
2802
Peter Boström5811a392015-12-10 13:02:50 +01002803 rtc::Event check_stats_event_;
stefanf116bd02015-10-27 08:29:42 -07002804 } test;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002805
stefane74eef12016-01-08 06:47:13 -08002806 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002807}
2808
2809TEST_F(EndToEndTest, ReceiverReferenceTimeReportEnabled) {
2810 TestXrReceiverReferenceTimeReport(true);
2811}
2812
2813TEST_F(EndToEndTest, ReceiverReferenceTimeReportDisabled) {
2814 TestXrReceiverReferenceTimeReport(false);
2815}
2816
2817TEST_F(EndToEndTest, TestReceivedRtpPacketStats) {
2818 static const size_t kNumRtpPacketsToSend = 5;
2819 class ReceivedRtpStatsObserver : public test::EndToEndTest {
2820 public:
2821 ReceivedRtpStatsObserver()
2822 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002823 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002824 sent_rtp_(0) {}
2825
2826 private:
stefanff483612015-12-21 03:14:00 -08002827 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002828 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002829 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002830 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002831 }
2832
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002833 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002834 if (sent_rtp_ >= kNumRtpPacketsToSend) {
2835 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002836 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
Peter Boström5811a392015-12-10 13:02:50 +01002837 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002838 }
2839 return DROP_PACKET;
2840 }
2841 ++sent_rtp_;
2842 return SEND_PACKET;
2843 }
2844
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002845 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002846 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002847 << "Timed out while verifying number of received RTP packets.";
2848 }
2849
2850 VideoReceiveStream* receive_stream_;
2851 uint32_t sent_rtp_;
2852 } test;
2853
stefane74eef12016-01-08 06:47:13 -08002854 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002855}
2856
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002857TEST_F(EndToEndTest, SendsSetSsrc) { TestSendsSetSsrcs(1, false); }
2858
2859TEST_F(EndToEndTest, SendsSetSimulcastSsrcs) {
2860 TestSendsSetSsrcs(kNumSsrcs, false);
2861}
2862
2863TEST_F(EndToEndTest, CanSwitchToUseAllSsrcs) {
2864 TestSendsSetSsrcs(kNumSsrcs, true);
2865}
2866
mflodman@webrtc.orgf9460682014-07-24 16:41:25 +00002867TEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002868 class ObserveRedundantPayloads: public test::EndToEndTest {
2869 public:
2870 ObserveRedundantPayloads()
2871 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00002872 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002873 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
2874 }
2875 }
2876
2877 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002878 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002879 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002880 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002881
2882 if (!registered_rtx_ssrc_[header.ssrc])
2883 return SEND_PACKET;
2884
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002885 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002886 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002887 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002888
2889 if (!packet_is_redundant_payload)
2890 return SEND_PACKET;
2891
2892 if (!observed_redundant_retransmission_[header.ssrc]) {
2893 observed_redundant_retransmission_[header.ssrc] = true;
2894 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002895 observation_complete_.Set();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002896 }
2897
2898 return SEND_PACKET;
2899 }
2900
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002901 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002902
stefanff483612015-12-21 03:14:00 -08002903 void ModifyVideoConfigs(
2904 VideoSendStream::Config* send_config,
2905 std::vector<VideoReceiveStream::Config>* receive_configs,
2906 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002907 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002908 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2909 encoder_config->streams[i].min_bitrate_bps = 10000;
2910 encoder_config->streams[i].target_bitrate_bps = 15000;
2911 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002912 }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002913
2914 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002915
2916 for (size_t i = 0; i < kNumSsrcs; ++i)
2917 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00002918
2919 // Significantly higher than max bitrates for all video streams -> forcing
2920 // padding to trigger redundant padding on all RTX SSRCs.
2921 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002922 }
2923
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002924 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002925 EXPECT_TRUE(Wait())
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002926 << "Timed out while waiting for redundant payloads on all SSRCs.";
2927 }
2928
2929 private:
2930 size_t ssrcs_to_observe_;
2931 std::map<uint32_t, bool> observed_redundant_retransmission_;
2932 std::map<uint32_t, bool> registered_rtx_ssrc_;
2933 } test;
2934
stefane74eef12016-01-08 06:47:13 -08002935 RunBaseTest(&test);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002936}
2937
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002938void EndToEndTest::TestRtpStatePreservation(bool use_rtx) {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002939 class RtpSequenceObserver : public test::RtpRtcpObserver {
2940 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00002941 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002942 : test::RtpRtcpObserver(kDefaultTimeoutMs),
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002943 ssrcs_to_observe_(kNumSsrcs) {
2944 for (size_t i = 0; i < kNumSsrcs; ++i) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002945 configured_ssrcs_[kVideoSendSsrcs[i]] = true;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002946 if (use_rtx)
2947 configured_ssrcs_[kSendRtxSsrcs[i]] = true;
2948 }
2949 }
2950
2951 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
Peter Boströmf2f82832015-05-01 13:00:41 +02002952 rtc::CritScope lock(&crit_);
danilchap34877ee2016-02-01 08:25:04 -08002953 ssrc_observed_.clear();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002954 ssrcs_to_observe_ = num_expected_ssrcs;
2955 }
2956
2957 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002958 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002959 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002960 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002961 const uint32_t ssrc = header.ssrc;
danilchap5c35cf92016-02-03 14:14:49 -08002962 const int64_t sequence_number =
2963 seq_numbers_unwrapper_.Unwrap(header.sequenceNumber);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002964 const uint32_t timestamp = header.timestamp;
danilchap34877ee2016-02-01 08:25:04 -08002965 const bool only_padding =
2966 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002967
2968 EXPECT_TRUE(configured_ssrcs_[ssrc])
2969 << "Received SSRC that wasn't configured: " << ssrc;
2970
danilchap5c35cf92016-02-03 14:14:49 -08002971 static const int64_t kMaxSequenceNumberGap = 100;
2972 std::list<int64_t>* seq_numbers = &last_observed_seq_numbers_[ssrc];
2973 if (seq_numbers->empty()) {
2974 seq_numbers->push_back(sequence_number);
2975 } else {
2976 // We shouldn't get replays of previous sequence numbers.
2977 for (int64_t observed : *seq_numbers) {
2978 EXPECT_NE(observed, sequence_number)
2979 << "Received sequence number " << sequence_number
2980 << " for SSRC " << ssrc << " 2nd time.";
2981 }
2982 // Verify sequence numbers are reasonably close.
2983 int64_t latest_observed = seq_numbers->back();
2984 int64_t sequence_number_gap = sequence_number - latest_observed;
2985 EXPECT_LE(std::abs(sequence_number_gap), kMaxSequenceNumberGap)
2986 << "Gap in sequence numbers (" << latest_observed << " -> "
2987 << sequence_number << ") too large for SSRC: " << ssrc << ".";
2988 seq_numbers->push_back(sequence_number);
2989 if (seq_numbers->size() >= kMaxSequenceNumberGap) {
2990 seq_numbers->pop_front();
2991 }
2992 }
2993
2994 static const int32_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
2995 auto timestamp_it = last_observed_timestamp_.find(ssrc);
2996 if (timestamp_it == last_observed_timestamp_.end()) {
danilchap34877ee2016-02-01 08:25:04 -08002997 last_observed_timestamp_[ssrc] = timestamp;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002998 } else {
danilchap5c35cf92016-02-03 14:14:49 -08002999 // Verify timestamps are reasonably close.
3000 uint32_t latest_observed = timestamp_it->second;
3001 int32_t timestamp_gap = rtc::TimeDiff(timestamp, latest_observed);
3002 EXPECT_LE(std::abs(timestamp_gap), kMaxTimestampGap)
3003 << "Gap in timestamps (" << latest_observed << " -> "
3004 << timestamp << ") too large for SSRC: " << ssrc << ".";
3005 timestamp_it->second = timestamp;
danilchapf4b9c772016-01-28 06:14:24 -08003006 }
danilchap34877ee2016-02-01 08:25:04 -08003007
3008 rtc::CritScope lock(&crit_);
3009 // Wait for media packets on all ssrcs.
3010 if (!ssrc_observed_[ssrc] && !only_padding) {
3011 ssrc_observed_[ssrc] = true;
3012 if (--ssrcs_to_observe_ == 0)
3013 observation_complete_.Set();
3014 }
3015
danilchapf4b9c772016-01-28 06:14:24 -08003016 return SEND_PACKET;
3017 }
3018
danilchap5c35cf92016-02-03 14:14:49 -08003019 SequenceNumberUnwrapper seq_numbers_unwrapper_;
3020 std::map<uint32_t, std::list<int64_t>> last_observed_seq_numbers_;
danilchap34877ee2016-02-01 08:25:04 -08003021 std::map<uint32_t, uint32_t> last_observed_timestamp_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003022 std::map<uint32_t, bool> configured_ssrcs_;
3023
Peter Boströmf2f82832015-05-01 13:00:41 +02003024 rtc::CriticalSection crit_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003025 size_t ssrcs_to_observe_ GUARDED_BY(crit_);
danilchap34877ee2016-02-01 08:25:04 -08003026 std::map<uint32_t, bool> ssrc_observed_ GUARDED_BY(crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003027 } observer(use_rtx);
3028
solenberg4fbae2b2015-08-28 04:07:10 -07003029 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003030
stefanf116bd02015-10-27 08:29:42 -07003031 test::PacketTransport send_transport(sender_call_.get(), &observer,
3032 test::PacketTransport::kSender,
3033 FakeNetworkPipe::Config());
3034 test::PacketTransport receive_transport(nullptr, &observer,
3035 test::PacketTransport::kReceiver,
3036 FakeNetworkPipe::Config());
3037 send_transport.SetReceiver(receiver_call_->Receiver());
3038 receive_transport.SetReceiver(sender_call_->Receiver());
3039
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003040 CreateSendConfig(kNumSsrcs, 0, &send_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003041
3042 if (use_rtx) {
3043 for (size_t i = 0; i < kNumSsrcs; ++i) {
stefanff483612015-12-21 03:14:00 -08003044 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003045 }
stefanff483612015-12-21 03:14:00 -08003046 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003047 }
3048
3049 // Lower bitrates so that all streams send initially.
stefanff483612015-12-21 03:14:00 -08003050 for (size_t i = 0; i < video_encoder_config_.streams.size(); ++i) {
3051 video_encoder_config_.streams[i].min_bitrate_bps = 10000;
3052 video_encoder_config_.streams[i].target_bitrate_bps = 15000;
3053 video_encoder_config_.streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003054 }
3055
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003056 // Use the same total bitrates when sending a single stream to avoid lowering
3057 // the bitrate estimate and requiring a subsequent rampup.
stefanff483612015-12-21 03:14:00 -08003058 VideoEncoderConfig one_stream = video_encoder_config_;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003059 one_stream.streams.resize(1);
stefanff483612015-12-21 03:14:00 -08003060 for (size_t i = 1; i < video_encoder_config_.streams.size(); ++i) {
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003061 one_stream.streams.front().min_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003062 video_encoder_config_.streams[i].min_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003063 one_stream.streams.front().target_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003064 video_encoder_config_.streams[i].target_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003065 one_stream.streams.front().max_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003066 video_encoder_config_.streams[i].max_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003067 }
3068
stefanf116bd02015-10-27 08:29:42 -07003069 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003070
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003071 CreateVideoStreams();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003072 CreateFrameGeneratorCapturer();
3073
3074 Start();
Peter Boström5811a392015-12-10 13:02:50 +01003075 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003076 << "Timed out waiting for all SSRCs to send packets.";
3077
3078 // Test stream resetting more than once to make sure that the state doesn't
3079 // get set once (this could be due to using std::map::insert for instance).
3080 for (size_t i = 0; i < 3; ++i) {
3081 frame_generator_capturer_->Stop();
stefanff483612015-12-21 03:14:00 -08003082 sender_call_->DestroyVideoSendStream(video_send_stream_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003083
3084 // Re-create VideoSendStream with only one stream.
stefanff483612015-12-21 03:14:00 -08003085 video_send_stream_ =
3086 sender_call_->CreateVideoSendStream(video_send_config_, one_stream);
3087 video_send_stream_->Start();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003088 CreateFrameGeneratorCapturer();
3089 frame_generator_capturer_->Start();
3090
3091 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003092 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003093
3094 // Reconfigure back to use all streams.
stefanff483612015-12-21 03:14:00 -08003095 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003096 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003097 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003098 << "Timed out waiting for all SSRCs to send packets.";
3099
3100 // Reconfigure down to one stream.
stefanff483612015-12-21 03:14:00 -08003101 video_send_stream_->ReconfigureVideoEncoder(one_stream);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003102 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003103 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003104
3105 // Reconfigure back to use all streams.
stefanff483612015-12-21 03:14:00 -08003106 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003107 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003108 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003109 << "Timed out waiting for all SSRCs to send packets.";
3110 }
3111
stefanf116bd02015-10-27 08:29:42 -07003112 send_transport.StopSending();
3113 receive_transport.StopSending();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003114
3115 Stop();
3116 DestroyStreams();
3117}
3118
Peter Boströmfc968a22016-02-19 16:14:37 +01003119TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpState) {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003120 TestRtpStatePreservation(false);
3121}
3122
3123TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpStatesWithRtx) {
3124 TestRtpStatePreservation(true);
3125}
3126
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003127TEST_F(EndToEndTest, RespectsNetworkState) {
3128 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
3129 // down blocks until no more packets will be sent.
3130
3131 // Pacer will send from its packet list and then send required padding before
3132 // checking paused_ again. This should be enough for one round of pacing,
3133 // otherwise increase.
3134 static const int kNumAcceptedDowntimeRtp = 5;
3135 // A single RTCP may be in the pipeline.
3136 static const int kNumAcceptedDowntimeRtcp = 1;
3137 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
3138 public:
3139 NetworkStateTest()
3140 : EndToEndTest(kDefaultTimeoutMs),
3141 FakeEncoder(Clock::GetRealTimeClock()),
Peter Boström5811a392015-12-10 13:02:50 +01003142 encoded_frames_(false, false),
3143 packet_event_(false, false),
sprang867fb522015-08-03 04:38:41 -07003144 sender_call_(nullptr),
3145 receiver_call_(nullptr),
Jelena Marusiccd670222015-07-16 09:30:09 +02003146 sender_state_(kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003147 sender_rtp_(0),
3148 sender_rtcp_(0),
3149 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003150 down_frames_(0) {}
3151
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003152 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003153 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003154 ++sender_rtp_;
Peter Boström5811a392015-12-10 13:02:50 +01003155 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003156 return SEND_PACKET;
3157 }
3158
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003159 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003160 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003161 ++sender_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003162 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003163 return SEND_PACKET;
3164 }
3165
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003166 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003167 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
3168 return SEND_PACKET;
3169 }
3170
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003171 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003172 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003173 ++receiver_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003174 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003175 return SEND_PACKET;
3176 }
3177
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003178 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003179 sender_call_ = sender_call;
3180 receiver_call_ = receiver_call;
3181 }
3182
stefanff483612015-12-21 03:14:00 -08003183 void ModifyVideoConfigs(
3184 VideoSendStream::Config* send_config,
3185 std::vector<VideoReceiveStream::Config>* receive_configs,
3186 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003187 send_config->encoder_settings.encoder = this;
3188 }
3189
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003190 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003191 EXPECT_TRUE(encoded_frames_.Wait(kDefaultTimeoutMs))
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003192 << "No frames received by the encoder.";
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003193 // Wait for packets from both sender/receiver.
3194 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003195
3196 // Sender-side network down.
Jelena Marusiccd670222015-07-16 09:30:09 +02003197 sender_call_->SignalNetworkState(kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003198 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003199 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003200 // After network goes down we shouldn't be encoding more frames.
Jelena Marusiccd670222015-07-16 09:30:09 +02003201 sender_state_ = kNetworkDown;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003202 }
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003203 // Wait for receiver-packets and no sender packets.
3204 WaitForPacketsOrSilence(true, false);
3205
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003206 // Receiver-side network down.
Jelena Marusiccd670222015-07-16 09:30:09 +02003207 receiver_call_->SignalNetworkState(kNetworkDown);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003208 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003209
3210 // Network back up again for both.
3211 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003212 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003213 // It's OK to encode frames again, as we're about to bring up the
3214 // network.
Jelena Marusiccd670222015-07-16 09:30:09 +02003215 sender_state_ = kNetworkUp;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003216 }
Jelena Marusiccd670222015-07-16 09:30:09 +02003217 sender_call_->SignalNetworkState(kNetworkUp);
3218 receiver_call_->SignalNetworkState(kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003219 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003220 }
3221
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07003222 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003223 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07003224 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003225 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003226 rtc::CritScope lock(&test_crit_);
Jelena Marusiccd670222015-07-16 09:30:09 +02003227 if (sender_state_ == kNetworkDown) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003228 ++down_frames_;
3229 EXPECT_LE(down_frames_, 1)
3230 << "Encoding more than one frame while network is down.";
3231 if (down_frames_ > 1)
Peter Boström5811a392015-12-10 13:02:50 +01003232 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003233 } else {
Peter Boström5811a392015-12-10 13:02:50 +01003234 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003235 }
3236 }
3237 return test::FakeEncoder::Encode(
3238 input_image, codec_specific_info, frame_types);
3239 }
3240
3241 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003242 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
3243 int64_t initial_time_ms = clock_->TimeInMilliseconds();
3244 int initial_sender_rtp;
3245 int initial_sender_rtcp;
3246 int initial_receiver_rtcp;
3247 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003248 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003249 initial_sender_rtp = sender_rtp_;
3250 initial_sender_rtcp = sender_rtcp_;
3251 initial_receiver_rtcp = receiver_rtcp_;
3252 }
3253 bool sender_done = false;
3254 bool receiver_done = false;
mflodmand1590b22015-12-09 07:07:59 -08003255 while (!sender_done || !receiver_done) {
Peter Boström5811a392015-12-10 13:02:50 +01003256 packet_event_.Wait(kSilenceTimeoutMs);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003257 int64_t time_now_ms = clock_->TimeInMilliseconds();
Peter Boströmf2f82832015-05-01 13:00:41 +02003258 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003259 if (sender_down) {
3260 ASSERT_LE(sender_rtp_ - initial_sender_rtp, kNumAcceptedDowntimeRtp)
3261 << "RTP sent during sender-side downtime.";
3262 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
3263 kNumAcceptedDowntimeRtcp)
3264 << "RTCP sent during sender-side downtime.";
3265 if (time_now_ms - initial_time_ms >=
3266 static_cast<int64_t>(kSilenceTimeoutMs)) {
3267 sender_done = true;
3268 }
3269 } else {
3270 if (sender_rtp_ > initial_sender_rtp)
3271 sender_done = true;
3272 }
3273 if (receiver_down) {
3274 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
3275 kNumAcceptedDowntimeRtcp)
3276 << "RTCP sent during receiver-side downtime.";
3277 if (time_now_ms - initial_time_ms >=
3278 static_cast<int64_t>(kSilenceTimeoutMs)) {
3279 receiver_done = true;
3280 }
3281 } else {
3282 if (receiver_rtcp_ > initial_receiver_rtcp)
3283 receiver_done = true;
3284 }
3285 }
3286 }
3287
Peter Boströmf2f82832015-05-01 13:00:41 +02003288 rtc::CriticalSection test_crit_;
Peter Boström5811a392015-12-10 13:02:50 +01003289 rtc::Event encoded_frames_;
3290 rtc::Event packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003291 Call* sender_call_;
3292 Call* receiver_call_;
Jelena Marusiccd670222015-07-16 09:30:09 +02003293 NetworkState sender_state_ GUARDED_BY(test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003294 int sender_rtp_ GUARDED_BY(test_crit_);
3295 int sender_rtcp_ GUARDED_BY(test_crit_);
3296 int receiver_rtcp_ GUARDED_BY(test_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003297 int down_frames_ GUARDED_BY(test_crit_);
3298 } test;
3299
stefane74eef12016-01-08 06:47:13 -08003300 RunBaseTest(&test);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003301}
3302
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003303TEST_F(EndToEndTest, CallReportsRttForSender) {
3304 static const int kSendDelayMs = 30;
3305 static const int kReceiveDelayMs = 70;
3306
solenberg4fbae2b2015-08-28 04:07:10 -07003307 CreateCalls(Call::Config(), Call::Config());
3308
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003309 FakeNetworkPipe::Config config;
3310 config.queue_delay_ms = kSendDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003311 test::DirectTransport sender_transport(config, sender_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003312 config.queue_delay_ms = kReceiveDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003313 test::DirectTransport receiver_transport(config, receiver_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003314 sender_transport.SetReceiver(receiver_call_->Receiver());
3315 receiver_transport.SetReceiver(sender_call_->Receiver());
3316
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003317 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07003318 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003319
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003320 CreateVideoStreams();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003321 CreateFrameGeneratorCapturer();
3322 Start();
3323
3324 int64_t start_time_ms = clock_->TimeInMilliseconds();
3325 while (true) {
3326 Call::Stats stats = sender_call_->GetStats();
3327 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
3328 clock_->TimeInMilliseconds())
3329 << "No RTT stats before timeout!";
3330 if (stats.rtt_ms != -1) {
3331 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs);
3332 break;
3333 }
3334 SleepMs(10);
3335 }
3336
3337 Stop();
3338 DestroyStreams();
3339}
3340
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003341TEST_F(EndToEndTest, NewSendStreamsRespectNetworkDown) {
3342 class UnusedEncoder : public test::FakeEncoder {
mflodmand1590b22015-12-09 07:07:59 -08003343 public:
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003344 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07003345 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003346 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07003347 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003348 ADD_FAILURE() << "Unexpected frame encode.";
3349 return test::FakeEncoder::Encode(
3350 input_image, codec_specific_info, frame_types);
3351 }
3352 };
3353
solenberg4fbae2b2015-08-28 04:07:10 -07003354 CreateSenderCall(Call::Config());
Jelena Marusiccd670222015-07-16 09:30:09 +02003355 sender_call_->SignalNetworkState(kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003356
solenberg4fbae2b2015-08-28 04:07:10 -07003357 UnusedTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003358 CreateSendConfig(1, 0, &transport);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003359 UnusedEncoder unused_encoder;
stefanff483612015-12-21 03:14:00 -08003360 video_send_config_.encoder_settings.encoder = &unused_encoder;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003361 CreateVideoStreams();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003362 CreateFrameGeneratorCapturer();
3363
3364 Start();
3365 SleepMs(kSilenceTimeoutMs);
3366 Stop();
3367
3368 DestroyStreams();
3369}
3370
3371TEST_F(EndToEndTest, NewReceiveStreamsRespectNetworkDown) {
solenberg4fbae2b2015-08-28 04:07:10 -07003372 CreateCalls(Call::Config(), Call::Config());
Jelena Marusiccd670222015-07-16 09:30:09 +02003373 receiver_call_->SignalNetworkState(kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003374
stefanf116bd02015-10-27 08:29:42 -07003375 test::DirectTransport sender_transport(sender_call_.get());
solenberg4fbae2b2015-08-28 04:07:10 -07003376 sender_transport.SetReceiver(receiver_call_->Receiver());
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003377 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07003378 UnusedTransport transport;
3379 CreateMatchingReceiveConfigs(&transport);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003380 CreateVideoStreams();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003381 CreateFrameGeneratorCapturer();
3382
3383 Start();
3384 SleepMs(kSilenceTimeoutMs);
3385 Stop();
3386
3387 sender_transport.StopSending();
3388
3389 DestroyStreams();
3390}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00003391
Peter Boströmd7da1202015-06-05 14:09:38 +02003392void VerifyEmptyNackConfig(const NackConfig& config) {
3393 EXPECT_EQ(0, config.rtp_history_ms)
3394 << "Enabling NACK requires rtcp-fb: nack negotiation.";
3395}
3396
3397void VerifyEmptyFecConfig(const FecConfig& config) {
3398 EXPECT_EQ(-1, config.ulpfec_payload_type)
3399 << "Enabling FEC requires rtpmap: ulpfec negotiation.";
3400 EXPECT_EQ(-1, config.red_payload_type)
3401 << "Enabling FEC requires rtpmap: red negotiation.";
3402 EXPECT_EQ(-1, config.red_rtx_payload_type)
3403 << "Enabling RTX in FEC requires rtpmap: rtx negotiation.";
3404}
3405
3406TEST_F(EndToEndTest, VerifyDefaultSendConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003407 VideoSendStream::Config default_send_config(nullptr);
Peter Boströmd7da1202015-06-05 14:09:38 +02003408 EXPECT_EQ(0, default_send_config.rtp.nack.rtp_history_ms)
3409 << "Enabling NACK require rtcp-fb: nack negotiation.";
3410 EXPECT_TRUE(default_send_config.rtp.rtx.ssrcs.empty())
3411 << "Enabling RTX requires rtpmap: rtx negotiation.";
3412 EXPECT_TRUE(default_send_config.rtp.extensions.empty())
3413 << "Enabling RTP extensions require negotiation.";
3414
3415 VerifyEmptyNackConfig(default_send_config.rtp.nack);
3416 VerifyEmptyFecConfig(default_send_config.rtp.fec);
3417}
3418
3419TEST_F(EndToEndTest, VerifyDefaultReceiveConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003420 VideoReceiveStream::Config default_receive_config(nullptr);
pbosda903ea2015-10-02 02:36:56 -07003421 EXPECT_EQ(RtcpMode::kCompound, default_receive_config.rtp.rtcp_mode)
Peter Boströmd7da1202015-06-05 14:09:38 +02003422 << "Reduced-size RTCP require rtcp-rsize to be negotiated.";
3423 EXPECT_FALSE(default_receive_config.rtp.remb)
3424 << "REMB require rtcp-fb: goog-remb to be negotiated.";
3425 EXPECT_FALSE(
3426 default_receive_config.rtp.rtcp_xr.receiver_reference_time_report)
3427 << "RTCP XR settings require rtcp-xr to be negotiated.";
3428 EXPECT_TRUE(default_receive_config.rtp.rtx.empty())
3429 << "Enabling RTX requires rtpmap: rtx negotiation.";
3430 EXPECT_TRUE(default_receive_config.rtp.extensions.empty())
3431 << "Enabling RTP extensions require negotiation.";
3432
3433 VerifyEmptyNackConfig(default_receive_config.rtp.nack);
3434 VerifyEmptyFecConfig(default_receive_config.rtp.fec);
3435}
3436
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003437TEST_F(EndToEndTest, TransportSeqNumOnAudioAndVideo) {
3438 static const int kExtensionId = 8;
3439 class TransportSequenceNumberTest : public test::EndToEndTest {
3440 public:
3441 TransportSequenceNumberTest()
3442 : EndToEndTest(kDefaultTimeoutMs),
3443 video_observed_(false),
3444 audio_observed_(false) {
3445 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
3446 kExtensionId);
3447 }
3448
3449 size_t GetNumVideoStreams() const override { return 1; }
3450 size_t GetNumAudioStreams() const override { return 1; }
3451
3452 void ModifyVideoConfigs(
3453 VideoSendStream::Config* send_config,
3454 std::vector<VideoReceiveStream::Config>* receive_configs,
3455 VideoEncoderConfig* encoder_config) override {
3456 send_config->rtp.extensions.clear();
3457 send_config->rtp.extensions.push_back(
3458 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
3459 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3460 }
3461
3462 void ModifyAudioConfigs(
3463 AudioSendStream::Config* send_config,
3464 std::vector<AudioReceiveStream::Config>* receive_configs) override {
3465 send_config->rtp.extensions.clear();
3466 send_config->rtp.extensions.push_back(
3467 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
3468 (*receive_configs)[0].rtp.extensions.clear();
3469 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3470 }
3471
3472 Action OnSendRtp(const uint8_t* packet, size_t length) override {
3473 RTPHeader header;
3474 EXPECT_TRUE(parser_->Parse(packet, length, &header));
3475 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
3476 // Unwrap packet id and verify uniqueness.
3477 int64_t packet_id =
3478 unwrapper_.Unwrap(header.extension.transportSequenceNumber);
3479 EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
3480
3481 if (header.ssrc == kVideoSendSsrcs[0])
3482 video_observed_ = true;
3483 if (header.ssrc == kAudioSendSsrc)
3484 audio_observed_ = true;
3485 if (audio_observed_ && video_observed_ &&
3486 received_packet_ids_.size() == 50) {
3487 size_t packet_id_range =
3488 *received_packet_ids_.rbegin() - *received_packet_ids_.begin() + 1;
3489 EXPECT_EQ(received_packet_ids_.size(), packet_id_range);
3490 observation_complete_.Set();
3491 }
3492 return SEND_PACKET;
3493 }
3494
3495 void PerformTest() override {
3496 EXPECT_TRUE(Wait()) << "Timed out while waiting for audio and video "
3497 "packets with transport sequence number.";
3498 }
3499
3500 private:
3501 bool video_observed_;
3502 bool audio_observed_;
3503 SequenceNumberUnwrapper unwrapper_;
3504 std::set<int64_t> received_packet_ids_;
3505 } test;
3506
stefane74eef12016-01-08 06:47:13 -08003507 RunBaseTest(&test);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003508}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003509} // namespace webrtc