blob: 8d1135a4ab93ef7b426b84b461e67861d74a5ff6 [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>
kwiberg4a206a92016-03-31 10:24:26 -070016#include <vector>
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000017
18#include "testing/gtest/include/gtest/gtest.h"
19
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000020#include "webrtc/base/checks.h"
Erik Språng6b8d3552015-09-24 15:06:57 +020021#include "webrtc/base/event.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"
pbosa96b60b2016-04-18 21:12:48 -070024#include "webrtc/common_video/include/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"
asapersson01d70a32016-05-20 06:29:46 -070034#include "webrtc/system_wrappers/include/metrics_default.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010035#include "webrtc/system_wrappers/include/sleep.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000036#include "webrtc/test/call_test.h"
37#include "webrtc/test/direct_transport.h"
38#include "webrtc/test/encoder_settings.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000039#include "webrtc/test/fake_decoder.h"
40#include "webrtc/test/fake_encoder.h"
41#include "webrtc/test/frame_generator.h"
42#include "webrtc/test/frame_generator_capturer.h"
43#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
skvlad7a43d252016-03-22 15:32:27 -070079 class RequiredTransport : public Transport {
80 public:
81 RequiredTransport(bool rtp_required, bool rtcp_required)
82 : need_rtp_(rtp_required), need_rtcp_(rtcp_required) {}
83 ~RequiredTransport() {
84 if (need_rtp_) {
85 ADD_FAILURE() << "Expected RTP packet not sent.";
86 }
87 if (need_rtcp_) {
88 ADD_FAILURE() << "Expected RTCP packet not sent.";
89 }
90 }
91
92 private:
93 bool SendRtp(const uint8_t* packet,
94 size_t length,
95 const PacketOptions& options) override {
96 need_rtp_ = false;
97 return true;
98 }
99
100 bool SendRtcp(const uint8_t* packet, size_t length) override {
101 need_rtcp_ = false;
102 return true;
103 }
104 bool need_rtp_;
105 bool need_rtcp_;
106 };
107
Peter Boström39593972016-02-15 11:27:15 +0100108 void DecodesRetransmittedFrame(bool enable_rtx, bool enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000109 void ReceivesPliAndRecovers(int rtp_history_ms);
pbosda903ea2015-10-02 02:36:56 -0700110 void RespectsRtcpMode(RtcpMode rtcp_mode);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000111 void TestXrReceiverReferenceTimeReport(bool enable_rrtr);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000112 void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000113 void TestRtpStatePreservation(bool use_rtx);
sprangb4a1ae52015-12-03 08:10:08 -0800114 void VerifyHistogramStats(bool use_rtx, bool use_red, bool screenshare);
skvlad7a43d252016-03-22 15:32:27 -0700115 void VerifyNewVideoSendStreamsRespectNetworkState(
116 MediaType network_to_bring_down,
117 VideoEncoder* encoder,
118 Transport* transport);
119 void VerifyNewVideoReceiveStreamsRespectNetworkState(
120 MediaType network_to_bring_down,
121 Transport* transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000122};
123
124TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
solenberg4fbae2b2015-08-28 04:07:10 -0700125 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000126
solenberg4fbae2b2015-08-28 04:07:10 -0700127 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100128 CreateSendConfig(1, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700129 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000130
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100131 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000132
stefanff483612015-12-21 03:14:00 -0800133 video_receive_streams_[0]->Start();
134 video_receive_streams_[0]->Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000135
136 DestroyStreams();
137}
138
139TEST_F(EndToEndTest, ReceiverCanBeStoppedTwice) {
solenberg4fbae2b2015-08-28 04:07:10 -0700140 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000141
solenberg4fbae2b2015-08-28 04:07:10 -0700142 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100143 CreateSendConfig(1, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700144 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000145
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100146 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000147
stefanff483612015-12-21 03:14:00 -0800148 video_receive_streams_[0]->Stop();
149 video_receive_streams_[0]->Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000150
151 DestroyStreams();
152}
153
154TEST_F(EndToEndTest, RendersSingleDelayedFrame) {
155 static const int kWidth = 320;
156 static const int kHeight = 240;
157 // This constant is chosen to be higher than the timeout in the video_render
158 // module. This makes sure that frames aren't dropped if there are no other
159 // frames in the queue.
160 static const int kDelayRenderCallbackMs = 1000;
161
nisse7ade7b32016-03-23 04:48:10 -0700162 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000163 public:
Peter Boström5811a392015-12-10 13:02:50 +0100164 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000165
nisseeb83a1a2016-03-21 01:27:56 -0700166 void OnFrame(const VideoFrame& video_frame) override { event_.Set(); }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000167
Peter Boström5811a392015-12-10 13:02:50 +0100168 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000169
Peter Boström5811a392015-12-10 13:02:50 +0100170 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000171 } renderer;
172
173 class TestFrameCallback : public I420FrameCallback {
174 public:
Peter Boström5811a392015-12-10 13:02:50 +0100175 TestFrameCallback() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000176
Peter Boström5811a392015-12-10 13:02:50 +0100177 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000178
179 private:
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700180 void FrameCallback(VideoFrame* frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000181 SleepMs(kDelayRenderCallbackMs);
Peter Boström5811a392015-12-10 13:02:50 +0100182 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000183 }
184
Peter Boström5811a392015-12-10 13:02:50 +0100185 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000186 };
187
solenberg4fbae2b2015-08-28 04:07:10 -0700188 CreateCalls(Call::Config(), Call::Config());
189
stefanf116bd02015-10-27 08:29:42 -0700190 test::DirectTransport sender_transport(sender_call_.get());
191 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000192 sender_transport.SetReceiver(receiver_call_->Receiver());
193 receiver_transport.SetReceiver(sender_call_->Receiver());
194
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100195 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700196 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000197
198 TestFrameCallback pre_render_callback;
stefanff483612015-12-21 03:14:00 -0800199 video_receive_configs_[0].pre_render_callback = &pre_render_callback;
200 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000201
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100202 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000203 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000204
205 // Create frames that are smaller than the send width/height, this is done to
206 // check that the callbacks are done after processing video.
kwiberg27f982b2016-03-01 11:52:33 -0800207 std::unique_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000208 test::FrameGenerator::CreateChromaGenerator(kWidth, kHeight));
stefanff483612015-12-21 03:14:00 -0800209 video_send_stream_->Input()->IncomingCapturedFrame(
210 *frame_generator->NextFrame());
Peter Boström5811a392015-12-10 13:02:50 +0100211 EXPECT_TRUE(pre_render_callback.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000212 << "Timed out while waiting for pre-render callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100213 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000214 << "Timed out while waiting for the frame to render.";
215
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000216 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000217
218 sender_transport.StopSending();
219 receiver_transport.StopSending();
220
221 DestroyStreams();
222}
223
224TEST_F(EndToEndTest, TransmitsFirstFrame) {
nisse7ade7b32016-03-23 04:48:10 -0700225 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000226 public:
Peter Boström5811a392015-12-10 13:02:50 +0100227 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000228
nisseeb83a1a2016-03-21 01:27:56 -0700229 void OnFrame(const VideoFrame& video_frame) override { event_.Set(); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000230
Peter Boström5811a392015-12-10 13:02:50 +0100231 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000232
Peter Boström5811a392015-12-10 13:02:50 +0100233 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000234 } renderer;
235
solenberg4fbae2b2015-08-28 04:07:10 -0700236 CreateCalls(Call::Config(), Call::Config());
237
stefanf116bd02015-10-27 08:29:42 -0700238 test::DirectTransport sender_transport(sender_call_.get());
239 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000240 sender_transport.SetReceiver(receiver_call_->Receiver());
241 receiver_transport.SetReceiver(sender_call_->Receiver());
242
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100243 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700244 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -0800245 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000246
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100247 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000248 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000249
kwiberg27f982b2016-03-01 11:52:33 -0800250 std::unique_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000251 test::FrameGenerator::CreateChromaGenerator(
stefanff483612015-12-21 03:14:00 -0800252 video_encoder_config_.streams[0].width,
253 video_encoder_config_.streams[0].height));
254 video_send_stream_->Input()->IncomingCapturedFrame(
255 *frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000256
Peter Boström5811a392015-12-10 13:02:50 +0100257 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000258 << "Timed out while waiting for the frame to render.";
259
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000260 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000261
262 sender_transport.StopSending();
263 receiver_transport.StopSending();
264
265 DestroyStreams();
266}
267
Perba7dc722016-04-19 15:01:23 +0200268class CodecObserver : public test::EndToEndTest,
nisse7ade7b32016-03-23 04:48:10 -0700269 public rtc::VideoSinkInterface<VideoFrame> {
Perba7dc722016-04-19 15:01:23 +0200270 public:
271 CodecObserver(int no_frames_to_wait_for,
272 VideoRotation rotation_to_test,
273 const std::string& payload_name,
274 webrtc::VideoEncoder* encoder,
275 webrtc::VideoDecoder* decoder)
276 : EndToEndTest(2 * webrtc::EndToEndTest::kDefaultTimeoutMs),
277 no_frames_to_wait_for_(no_frames_to_wait_for),
278 expected_rotation_(rotation_to_test),
279 payload_name_(payload_name),
280 encoder_(encoder),
281 decoder_(decoder),
282 frame_counter_(0) {}
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000283
Perba7dc722016-04-19 15:01:23 +0200284 void PerformTest() override {
285 EXPECT_TRUE(Wait())
286 << "Timed out while waiting for enough frames to be decoded.";
287 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000288
Perba7dc722016-04-19 15:01:23 +0200289 void ModifyVideoConfigs(
290 VideoSendStream::Config* send_config,
291 std::vector<VideoReceiveStream::Config>* receive_configs,
292 VideoEncoderConfig* encoder_config) override {
293 send_config->encoder_settings.encoder = encoder_.get();
294 send_config->encoder_settings.payload_name = payload_name_;
295 send_config->encoder_settings.payload_type = 126;
296 encoder_config->streams[0].min_bitrate_bps = 50000;
297 encoder_config->streams[0].target_bitrate_bps =
298 encoder_config->streams[0].max_bitrate_bps = 2000000;
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000299
Perba7dc722016-04-19 15:01:23 +0200300 (*receive_configs)[0].renderer = this;
301 (*receive_configs)[0].decoders.resize(1);
302 (*receive_configs)[0].decoders[0].payload_type =
303 send_config->encoder_settings.payload_type;
304 (*receive_configs)[0].decoders[0].payload_name =
305 send_config->encoder_settings.payload_name;
306 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
307 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000308
Perba7dc722016-04-19 15:01:23 +0200309 void OnFrame(const VideoFrame& video_frame) override {
310 EXPECT_EQ(expected_rotation_, video_frame.rotation());
311 if (++frame_counter_ == no_frames_to_wait_for_)
312 observation_complete_.Set();
313 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000314
Perba7dc722016-04-19 15:01:23 +0200315 void OnFrameGeneratorCapturerCreated(
316 test::FrameGeneratorCapturer* frame_generator_capturer) override {
317 frame_generator_capturer->SetFakeRotation(expected_rotation_);
318 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000319
Perba7dc722016-04-19 15:01:23 +0200320 private:
321 int no_frames_to_wait_for_;
322 VideoRotation expected_rotation_;
323 std::string payload_name_;
324 std::unique_ptr<webrtc::VideoEncoder> encoder_;
325 std::unique_ptr<webrtc::VideoDecoder> decoder_;
326 int frame_counter_;
327};
328
329TEST_F(EndToEndTest, SendsAndReceivesVP8Rotation90) {
330 CodecObserver test(5, kVideoRotation_90, "VP8",
331 VideoEncoder::Create(VideoEncoder::kVp8),
332 VP8Decoder::Create());
333 RunBaseTest(&test);
334}
335
Peter Boström12996152016-05-14 02:03:18 +0200336#if !defined(RTC_DISABLE_VP9)
Perba7dc722016-04-19 15:01:23 +0200337TEST_F(EndToEndTest, SendsAndReceivesVP9) {
338 CodecObserver test(500, kVideoRotation_0, "VP9",
339 VideoEncoder::Create(VideoEncoder::kVp9),
340 VP9Decoder::Create());
341 RunBaseTest(&test);
342}
343
344TEST_F(EndToEndTest, SendsAndReceivesVP9VideoRotation90) {
345 CodecObserver test(5, kVideoRotation_90, "VP9",
346 VideoEncoder::Create(VideoEncoder::kVp9),
347 VP9Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800348 RunBaseTest(&test);
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000349}
Peter Boström12996152016-05-14 02:03:18 +0200350#endif // !defined(RTC_DISABLE_VP9)
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000351
hbosbab934b2016-01-27 01:36:03 -0800352#if defined(WEBRTC_END_TO_END_H264_TESTS)
353
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000354TEST_F(EndToEndTest, SendsAndReceivesH264) {
Perba7dc722016-04-19 15:01:23 +0200355 CodecObserver test(500, kVideoRotation_0, "H264",
356 VideoEncoder::Create(VideoEncoder::kH264),
357 H264Decoder::Create());
358 RunBaseTest(&test);
359}
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000360
Perba7dc722016-04-19 15:01:23 +0200361TEST_F(EndToEndTest, SendsAndReceivesH264VideoRotation90) {
362 CodecObserver test(5, kVideoRotation_90, "H264",
363 VideoEncoder::Create(VideoEncoder::kH264),
364 H264Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800365 RunBaseTest(&test);
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000366}
367
hbosbab934b2016-01-27 01:36:03 -0800368#endif // defined(WEBRTC_END_TO_END_H264_TESTS)
369
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000370TEST_F(EndToEndTest, ReceiverUsesLocalSsrc) {
371 class SyncRtcpObserver : public test::EndToEndTest {
372 public:
373 SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {}
374
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000375 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000376 RTCPUtility::RTCPParserV2 parser(packet, length, true);
377 EXPECT_TRUE(parser.IsValid());
378 uint32_t ssrc = 0;
379 ssrc |= static_cast<uint32_t>(packet[4]) << 24;
380 ssrc |= static_cast<uint32_t>(packet[5]) << 16;
381 ssrc |= static_cast<uint32_t>(packet[6]) << 8;
382 ssrc |= static_cast<uint32_t>(packet[7]) << 0;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100383 EXPECT_EQ(kReceiverLocalVideoSsrc, ssrc);
Peter Boström5811a392015-12-10 13:02:50 +0100384 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000385
386 return SEND_PACKET;
387 }
388
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000389 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100390 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000391 << "Timed out while waiting for a receiver RTCP packet to be sent.";
392 }
393 } test;
394
stefane74eef12016-01-08 06:47:13 -0800395 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000396}
397
398TEST_F(EndToEndTest, ReceivesAndRetransmitsNack) {
399 static const int kNumberOfNacksToObserve = 2;
400 static const int kLossBurstSize = 2;
401 static const int kPacketsBetweenLossBursts = 9;
402 class NackObserver : public test::EndToEndTest {
403 public:
404 NackObserver()
405 : EndToEndTest(kLongTimeoutMs),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000406 sent_rtp_packets_(0),
407 packets_left_to_drop_(0),
408 nacks_left_(kNumberOfNacksToObserve) {}
409
410 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000411 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700412 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000413 RTPHeader header;
Peter Boström03671cb2015-12-07 15:22:24 +0100414 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000415
416 // Never drop retransmitted packets.
417 if (dropped_packets_.find(header.sequenceNumber) !=
418 dropped_packets_.end()) {
419 retransmitted_packets_.insert(header.sequenceNumber);
Stefan Holmer586b19b2015-09-18 11:14:31 +0200420 if (nacks_left_ <= 0 &&
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000421 retransmitted_packets_.size() == dropped_packets_.size()) {
Peter Boström5811a392015-12-10 13:02:50 +0100422 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000423 }
424 return SEND_PACKET;
425 }
426
427 ++sent_rtp_packets_;
428
429 // Enough NACKs received, stop dropping packets.
Stefan Holmer586b19b2015-09-18 11:14:31 +0200430 if (nacks_left_ <= 0)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000431 return SEND_PACKET;
432
433 // Check if it's time for a new loss burst.
434 if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
435 packets_left_to_drop_ = kLossBurstSize;
436
Stefan Holmer01b48882015-05-05 10:21:24 +0200437 // Never drop padding packets as those won't be retransmitted.
438 if (packets_left_to_drop_ > 0 && header.paddingLength == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000439 --packets_left_to_drop_;
440 dropped_packets_.insert(header.sequenceNumber);
441 return DROP_PACKET;
442 }
443
444 return SEND_PACKET;
445 }
446
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000447 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700448 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000449 RTCPUtility::RTCPParserV2 parser(packet, length, true);
450 EXPECT_TRUE(parser.IsValid());
451
452 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +0200453 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
454 if (packet_type == RTCPUtility::RTCPPacketTypes::kRtpfbNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000455 --nacks_left_;
456 break;
457 }
458 packet_type = parser.Iterate();
459 }
460 return SEND_PACKET;
461 }
462
stefanff483612015-12-21 03:14:00 -0800463 void ModifyVideoConfigs(
464 VideoSendStream::Config* send_config,
465 std::vector<VideoReceiveStream::Config>* receive_configs,
466 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000467 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000468 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000469 }
470
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000471 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100472 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000473 << "Timed out waiting for packets to be NACKed, retransmitted and "
474 "rendered.";
475 }
476
stefanf116bd02015-10-27 08:29:42 -0700477 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000478 std::set<uint16_t> dropped_packets_;
479 std::set<uint16_t> retransmitted_packets_;
480 uint64_t sent_rtp_packets_;
481 int packets_left_to_drop_;
stefanf116bd02015-10-27 08:29:42 -0700482 int nacks_left_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000483 } test;
484
stefane74eef12016-01-08 06:47:13 -0800485 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000486}
487
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000488TEST_F(EndToEndTest, CanReceiveFec) {
nisse7ade7b32016-03-23 04:48:10 -0700489 class FecRenderObserver : public test::EndToEndTest,
490 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000491 public:
492 FecRenderObserver()
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000493 : EndToEndTest(kDefaultTimeoutMs), state_(kFirstPacket) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000494
495 private:
stefanf116bd02015-10-27 08:29:42 -0700496 Action OnSendRtp(const uint8_t* packet, size_t length) override {
497 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000498 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000499 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000500
Stefan Holmer01b48882015-05-05 10:21:24 +0200501 int encapsulated_payload_type = -1;
502 if (header.payloadType == kRedPayloadType) {
503 encapsulated_payload_type =
504 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100505 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200506 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
507 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100508 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200509 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000510
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000511 if (protected_sequence_numbers_.count(header.sequenceNumber) != 0) {
512 // Retransmitted packet, should not count.
513 protected_sequence_numbers_.erase(header.sequenceNumber);
514 EXPECT_GT(protected_timestamps_.count(header.timestamp), 0u);
515 protected_timestamps_.erase(header.timestamp);
516 return SEND_PACKET;
517 }
518
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000519 switch (state_) {
520 case kFirstPacket:
521 state_ = kDropEveryOtherPacketUntilFec;
522 break;
523 case kDropEveryOtherPacketUntilFec:
524 if (encapsulated_payload_type == kUlpfecPayloadType) {
525 state_ = kDropNextMediaPacket;
526 return SEND_PACKET;
527 }
528 if (header.sequenceNumber % 2 == 0)
529 return DROP_PACKET;
530 break;
531 case kDropNextMediaPacket:
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100532 if (encapsulated_payload_type == kFakeVideoSendPayloadType) {
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000533 protected_sequence_numbers_.insert(header.sequenceNumber);
534 protected_timestamps_.insert(header.timestamp);
535 state_ = kDropEveryOtherPacketUntilFec;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000536 return DROP_PACKET;
537 }
538 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000539 }
540
541 return SEND_PACKET;
542 }
543
nisseeb83a1a2016-03-21 01:27:56 -0700544 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200545 rtc::CritScope lock(&crit_);
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000546 // Rendering frame with timestamp of packet that was dropped -> FEC
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000547 // protection worked.
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000548 if (protected_timestamps_.count(video_frame.timestamp()) != 0)
Peter Boström5811a392015-12-10 13:02:50 +0100549 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000550 }
551
552 enum {
553 kFirstPacket,
554 kDropEveryOtherPacketUntilFec,
555 kDropNextMediaPacket,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000556 } state_;
557
stefanff483612015-12-21 03:14:00 -0800558 void ModifyVideoConfigs(
559 VideoSendStream::Config* send_config,
560 std::vector<VideoReceiveStream::Config>* receive_configs,
561 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000562 // TODO(pbos): Run this test with combined NACK/FEC enabled as well.
563 // int rtp_history_ms = 1000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000564 // (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000565 // send_config->rtp.nack.rtp_history_ms = rtp_history_ms;
566 send_config->rtp.fec.red_payload_type = kRedPayloadType;
567 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
568
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000569 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
570 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
571 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000572 }
573
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000574 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100575 EXPECT_TRUE(Wait())
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000576 << "Timed out waiting for dropped frames frames to be rendered.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000577 }
578
stefanf116bd02015-10-27 08:29:42 -0700579 rtc::CriticalSection crit_;
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000580 std::set<uint32_t> protected_sequence_numbers_ GUARDED_BY(crit_);
581 std::set<uint32_t> protected_timestamps_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000582 } test;
583
stefane74eef12016-01-08 06:47:13 -0800584 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000585}
586
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200587TEST_F(EndToEndTest, ReceivedFecPacketsNotNacked) {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000588 class FecNackObserver : public test::EndToEndTest {
589 public:
mflodmand1590b22015-12-09 07:07:59 -0800590 FecNackObserver()
stefanf116bd02015-10-27 08:29:42 -0700591 : EndToEndTest(kDefaultTimeoutMs),
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000592 state_(kFirstPacket),
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000593 fec_sequence_number_(0),
594 has_last_sequence_number_(false),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200595 last_sequence_number_(0),
596 encoder_(VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)),
597 decoder_(VP8Decoder::Create()) {}
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000598
599 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000600 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800601 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000602 RTPHeader header;
603 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000604
Stefan Holmer01b48882015-05-05 10:21:24 +0200605 int encapsulated_payload_type = -1;
606 if (header.payloadType == kRedPayloadType) {
607 encapsulated_payload_type =
608 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100609 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200610 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
611 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100612 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200613 }
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000614
615 if (has_last_sequence_number_ &&
616 !IsNewerSequenceNumber(header.sequenceNumber,
617 last_sequence_number_)) {
618 // Drop retransmitted packets.
619 return DROP_PACKET;
620 }
621 last_sequence_number_ = header.sequenceNumber;
622 has_last_sequence_number_ = true;
623
624 bool fec_packet = encapsulated_payload_type == kUlpfecPayloadType;
625 switch (state_) {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000626 case kFirstPacket:
627 state_ = kDropEveryOtherPacketUntilFec;
628 break;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000629 case kDropEveryOtherPacketUntilFec:
630 if (fec_packet) {
631 state_ = kDropAllMediaPacketsUntilFec;
632 } else if (header.sequenceNumber % 2 == 0) {
633 return DROP_PACKET;
634 }
635 break;
636 case kDropAllMediaPacketsUntilFec:
637 if (!fec_packet)
638 return DROP_PACKET;
639 fec_sequence_number_ = header.sequenceNumber;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200640 state_ = kDropOneMediaPacket;
641 break;
642 case kDropOneMediaPacket:
643 if (fec_packet)
644 return DROP_PACKET;
645 state_ = kPassOneMediaPacket;
646 return DROP_PACKET;
647 break;
648 case kPassOneMediaPacket:
649 if (fec_packet)
650 return DROP_PACKET;
651 // Pass one media packet after dropped packet after last FEC,
652 // otherwise receiver might never see a seq_no after
653 // |fec_sequence_number_|
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000654 state_ = kVerifyFecPacketNotInNackList;
655 break;
656 case kVerifyFecPacketNotInNackList:
657 // Continue to drop packets. Make sure no frame can be decoded.
658 if (fec_packet || header.sequenceNumber % 2 == 0)
659 return DROP_PACKET;
660 break;
661 }
662 return SEND_PACKET;
663 }
664
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000665 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800666 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000667 if (state_ == kVerifyFecPacketNotInNackList) {
668 test::RtcpPacketParser rtcp_parser;
669 rtcp_parser.Parse(packet, length);
670 std::vector<uint16_t> nacks = rtcp_parser.nack_item()->last_nack_list();
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200671 EXPECT_TRUE(std::find(nacks.begin(), nacks.end(),
672 fec_sequence_number_) == nacks.end())
673 << "Got nack for FEC packet";
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000674 if (!nacks.empty() &&
675 IsNewerSequenceNumber(nacks.back(), fec_sequence_number_)) {
Peter Boström5811a392015-12-10 13:02:50 +0100676 observation_complete_.Set();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000677 }
678 }
679 return SEND_PACKET;
680 }
681
stefane74eef12016-01-08 06:47:13 -0800682 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
683 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
684 // Configure some network delay.
685 const int kNetworkDelayMs = 50;
686 FakeNetworkPipe::Config config;
687 config.queue_delay_ms = kNetworkDelayMs;
688 return new test::PacketTransport(sender_call, this,
689 test::PacketTransport::kSender, config);
690 }
691
Stefan Holmere5904162015-03-26 11:11:06 +0100692 // TODO(holmer): Investigate why we don't send FEC packets when the bitrate
693 // is 10 kbps.
694 Call::Config GetSenderCallConfig() override {
solenberg4fbae2b2015-08-28 04:07:10 -0700695 Call::Config config;
Stefan Holmere5904162015-03-26 11:11:06 +0100696 const int kMinBitrateBps = 30000;
697 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
698 return config;
699 }
700
stefanff483612015-12-21 03:14:00 -0800701 void ModifyVideoConfigs(
702 VideoSendStream::Config* send_config,
703 std::vector<VideoReceiveStream::Config>* receive_configs,
704 VideoEncoderConfig* encoder_config) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000705 // Configure hybrid NACK/FEC.
706 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
707 send_config->rtp.fec.red_payload_type = kRedPayloadType;
708 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200709 // Set codec to VP8, otherwise NACK/FEC hybrid will be disabled.
710 send_config->encoder_settings.encoder = encoder_.get();
711 send_config->encoder_settings.payload_name = "VP8";
712 send_config->encoder_settings.payload_type = kFakeVideoSendPayloadType;
713 encoder_config->streams[0].min_bitrate_bps = 50000;
714 encoder_config->streams[0].max_bitrate_bps =
715 encoder_config->streams[0].target_bitrate_bps = 2000000;
716
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000717 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
718 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
719 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200720
721 (*receive_configs)[0].decoders.resize(1);
722 (*receive_configs)[0].decoders[0].payload_type =
723 send_config->encoder_settings.payload_type;
724 (*receive_configs)[0].decoders[0].payload_name =
725 send_config->encoder_settings.payload_name;
726 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000727 }
728
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000729 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100730 EXPECT_TRUE(Wait())
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000731 << "Timed out while waiting for FEC packets to be received.";
732 }
733
734 enum {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000735 kFirstPacket,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000736 kDropEveryOtherPacketUntilFec,
737 kDropAllMediaPacketsUntilFec,
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200738 kDropOneMediaPacket,
739 kPassOneMediaPacket,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000740 kVerifyFecPacketNotInNackList,
741 } state_;
742
stefan608213e2015-11-01 14:56:10 -0800743 rtc::CriticalSection crit_;
744 uint16_t fec_sequence_number_ GUARDED_BY(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000745 bool has_last_sequence_number_;
746 uint16_t last_sequence_number_;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200747 std::unique_ptr<webrtc::VideoEncoder> encoder_;
748 std::unique_ptr<webrtc::VideoDecoder> decoder_;
stefanf116bd02015-10-27 08:29:42 -0700749 } test;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000750
stefane74eef12016-01-08 06:47:13 -0800751 RunBaseTest(&test);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000752}
753
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000754// This test drops second RTP packet with a marker bit set, makes sure it's
755// retransmitted and renders. Retransmission SSRCs are also checked.
Peter Boström39593972016-02-15 11:27:15 +0100756void EndToEndTest::DecodesRetransmittedFrame(bool enable_rtx, bool enable_red) {
Peter Boström67680c12016-02-17 11:10:04 +0100757 static const int kDroppedFrameNumber = 10;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000758 class RetransmissionObserver : public test::EndToEndTest,
759 public I420FrameCallback {
760 public:
Peter Boström39593972016-02-15 11:27:15 +0100761 RetransmissionObserver(bool enable_rtx, bool enable_red)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000762 : EndToEndTest(kDefaultTimeoutMs),
Peter Boström39593972016-02-15 11:27:15 +0100763 payload_type_(GetPayloadType(false, enable_red)),
764 retransmission_ssrc_(enable_rtx ? kSendRtxSsrcs[0]
765 : kVideoSendSsrcs[0]),
766 retransmission_payload_type_(GetPayloadType(enable_rtx, enable_red)),
767 encoder_(VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000768 marker_bits_observed_(0),
769 retransmitted_timestamp_(0),
770 frame_retransmitted_(false) {}
771
772 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000773 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700774 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000775 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000776 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000777
Peter Boström67680c12016-02-17 11:10:04 +0100778 // Ignore padding-only packets over RTX.
779 if (header.payloadType != payload_type_) {
780 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
781 if (length == header.headerLength + header.paddingLength)
782 return SEND_PACKET;
Stefan Holmer586b19b2015-09-18 11:14:31 +0200783 }
Peter Boström67680c12016-02-17 11:10:04 +0100784
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000785 if (header.timestamp == retransmitted_timestamp_) {
786 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
787 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
788 frame_retransmitted_ = true;
789 return SEND_PACKET;
790 }
791
Stefan Holmer10880012016-02-03 13:29:59 +0100792 EXPECT_EQ(kVideoSendSsrcs[0], header.ssrc)
793 << "Payload type " << static_cast<int>(header.payloadType)
794 << " not expected.";
Shao Changbine62202f2015-04-21 20:24:50 +0800795 EXPECT_EQ(payload_type_, header.payloadType);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000796
Stefan Holmer586b19b2015-09-18 11:14:31 +0200797 // Found the final packet of the frame to inflict loss to, drop this and
798 // expect a retransmission.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000799 if (header.markerBit && ++marker_bits_observed_ == kDroppedFrameNumber) {
800 retransmitted_timestamp_ = header.timestamp;
801 return DROP_PACKET;
802 }
803
804 return SEND_PACKET;
805 }
806
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700807 void FrameCallback(VideoFrame* frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200808 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000809 if (frame->timestamp() == retransmitted_timestamp_) {
810 EXPECT_TRUE(frame_retransmitted_);
Peter Boström5811a392015-12-10 13:02:50 +0100811 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000812 }
813 }
814
stefanff483612015-12-21 03:14:00 -0800815 void ModifyVideoConfigs(
816 VideoSendStream::Config* send_config,
817 std::vector<VideoReceiveStream::Config>* receive_configs,
818 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000819 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000820 (*receive_configs)[0].pre_render_callback = this;
821 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
Shao Changbine62202f2015-04-21 20:24:50 +0800822
823 if (payload_type_ == kRedPayloadType) {
824 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
825 send_config->rtp.fec.red_payload_type = kRedPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +0100826 if (retransmission_ssrc_ == kSendRtxSsrcs[0])
827 send_config->rtp.fec.red_rtx_payload_type = kRtxRedPayloadType;
828 (*receive_configs)[0].rtp.fec.ulpfec_payload_type =
829 send_config->rtp.fec.ulpfec_payload_type;
830 (*receive_configs)[0].rtp.fec.red_payload_type =
831 send_config->rtp.fec.red_payload_type;
832 (*receive_configs)[0].rtp.fec.red_rtx_payload_type =
833 send_config->rtp.fec.red_rtx_payload_type;
Shao Changbine62202f2015-04-21 20:24:50 +0800834 }
835
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000836 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
837 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000838 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +0100839 (*receive_configs)[0].rtp.rtx[payload_type_].ssrc = kSendRtxSsrcs[0];
840 (*receive_configs)[0].rtp.rtx[payload_type_].payload_type =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000841 kSendRtxPayloadType;
842 }
Peter Boström39593972016-02-15 11:27:15 +0100843 // Configure encoding and decoding with VP8, since generic packetization
844 // doesn't support FEC with NACK.
845 RTC_DCHECK_EQ(1u, (*receive_configs)[0].decoders.size());
846 send_config->encoder_settings.encoder = encoder_.get();
847 send_config->encoder_settings.payload_name = "VP8";
848 (*receive_configs)[0].decoders[0].payload_name = "VP8";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000849 }
850
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000851 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100852 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000853 << "Timed out while waiting for retransmission to render.";
854 }
855
Shao Changbine62202f2015-04-21 20:24:50 +0800856 int GetPayloadType(bool use_rtx, bool use_red) {
Stefan Holmer10880012016-02-03 13:29:59 +0100857 if (use_red) {
858 if (use_rtx)
859 return kRtxRedPayloadType;
860 return kRedPayloadType;
861 }
862 if (use_rtx)
863 return kSendRtxPayloadType;
864 return kFakeVideoSendPayloadType;
Shao Changbine62202f2015-04-21 20:24:50 +0800865 }
866
stefanf116bd02015-10-27 08:29:42 -0700867 rtc::CriticalSection crit_;
Shao Changbine62202f2015-04-21 20:24:50 +0800868 const int payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000869 const uint32_t retransmission_ssrc_;
870 const int retransmission_payload_type_;
kwiberg27f982b2016-03-01 11:52:33 -0800871 std::unique_ptr<VideoEncoder> encoder_;
Peter Boström39593972016-02-15 11:27:15 +0100872 const std::string payload_name_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000873 int marker_bits_observed_;
stefanf116bd02015-10-27 08:29:42 -0700874 uint32_t retransmitted_timestamp_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000875 bool frame_retransmitted_;
Peter Boström39593972016-02-15 11:27:15 +0100876 } test(enable_rtx, enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000877
stefane74eef12016-01-08 06:47:13 -0800878 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000879}
880
881TEST_F(EndToEndTest, DecodesRetransmittedFrame) {
Shao Changbine62202f2015-04-21 20:24:50 +0800882 DecodesRetransmittedFrame(false, false);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000883}
884
885TEST_F(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +0800886 DecodesRetransmittedFrame(true, false);
887}
888
889TEST_F(EndToEndTest, DecodesRetransmittedFrameByRed) {
890 DecodesRetransmittedFrame(false, true);
891}
892
893TEST_F(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
894 DecodesRetransmittedFrame(true, true);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000895}
896
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000897void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
898 static const int kPacketsToDrop = 1;
899
nisse7ade7b32016-03-23 04:48:10 -0700900 class PliObserver : public test::EndToEndTest,
901 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000902 public:
903 explicit PliObserver(int rtp_history_ms)
904 : EndToEndTest(kLongTimeoutMs),
905 rtp_history_ms_(rtp_history_ms),
906 nack_enabled_(rtp_history_ms > 0),
907 highest_dropped_timestamp_(0),
908 frames_to_drop_(0),
909 received_pli_(false) {}
910
911 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000912 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700913 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000914 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000915 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000916
917 // Drop all retransmitted packets to force a PLI.
918 if (header.timestamp <= highest_dropped_timestamp_)
919 return DROP_PACKET;
920
921 if (frames_to_drop_ > 0) {
922 highest_dropped_timestamp_ = header.timestamp;
923 --frames_to_drop_;
924 return DROP_PACKET;
925 }
926
927 return SEND_PACKET;
928 }
929
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000930 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700931 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000932 RTCPUtility::RTCPParserV2 parser(packet, length, true);
933 EXPECT_TRUE(parser.IsValid());
934
935 for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +0200936 packet_type != RTCPUtility::RTCPPacketTypes::kInvalid;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000937 packet_type = parser.Iterate()) {
938 if (!nack_enabled_)
Erik Språng242e22b2015-05-11 10:17:43 +0200939 EXPECT_NE(packet_type, RTCPUtility::RTCPPacketTypes::kRtpfbNack);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000940
Erik Språng242e22b2015-05-11 10:17:43 +0200941 if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbPli) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000942 received_pli_ = true;
943 break;
944 }
945 }
946 return SEND_PACKET;
947 }
948
nisseeb83a1a2016-03-21 01:27:56 -0700949 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200950 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000951 if (received_pli_ &&
952 video_frame.timestamp() > highest_dropped_timestamp_) {
Peter Boström5811a392015-12-10 13:02:50 +0100953 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000954 }
955 if (!received_pli_)
956 frames_to_drop_ = kPacketsToDrop;
957 }
958
stefanff483612015-12-21 03:14:00 -0800959 void ModifyVideoConfigs(
960 VideoSendStream::Config* send_config,
961 std::vector<VideoReceiveStream::Config>* receive_configs,
962 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000963 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000964 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
965 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000966 }
967
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000968 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100969 EXPECT_TRUE(Wait()) << "Timed out waiting for PLI to be "
970 "received and a frame to be "
971 "rendered afterwards.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000972 }
973
stefanf116bd02015-10-27 08:29:42 -0700974 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000975 int rtp_history_ms_;
976 bool nack_enabled_;
stefanf116bd02015-10-27 08:29:42 -0700977 uint32_t highest_dropped_timestamp_ GUARDED_BY(&crit_);
978 int frames_to_drop_ GUARDED_BY(&crit_);
979 bool received_pli_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000980 } test(rtp_history_ms);
981
stefane74eef12016-01-08 06:47:13 -0800982 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000983}
984
985TEST_F(EndToEndTest, ReceivesPliAndRecoversWithNack) {
986 ReceivesPliAndRecovers(1000);
987}
988
jbauchdb81ffd2015-11-23 03:59:02 -0800989TEST_F(EndToEndTest, ReceivesPliAndRecoversWithoutNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000990 ReceivesPliAndRecovers(0);
991}
992
993TEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
994 class PacketInputObserver : public PacketReceiver {
995 public:
996 explicit PacketInputObserver(PacketReceiver* receiver)
Peter Boström5811a392015-12-10 13:02:50 +0100997 : receiver_(receiver), delivered_packet_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000998
Peter Boström5811a392015-12-10 13:02:50 +0100999 bool Wait() { return delivered_packet_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001000
1001 private:
stefan68786d22015-09-08 05:36:15 -07001002 DeliveryStatus DeliverPacket(MediaType media_type,
1003 const uint8_t* packet,
1004 size_t length,
1005 const PacketTime& packet_time) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001006 if (RtpHeaderParser::IsRtcp(packet, length)) {
stefan68786d22015-09-08 05:36:15 -07001007 return receiver_->DeliverPacket(media_type, packet, length,
1008 packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001009 } else {
1010 DeliveryStatus delivery_status =
stefan68786d22015-09-08 05:36:15 -07001011 receiver_->DeliverPacket(media_type, packet, length, packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001012 EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
Peter Boström5811a392015-12-10 13:02:50 +01001013 delivered_packet_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001014 return delivery_status;
1015 }
1016 }
1017
1018 PacketReceiver* receiver_;
Peter Boström5811a392015-12-10 13:02:50 +01001019 rtc::Event delivered_packet_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001020 };
1021
solenberg4fbae2b2015-08-28 04:07:10 -07001022 CreateCalls(Call::Config(), Call::Config());
1023
stefanf116bd02015-10-27 08:29:42 -07001024 test::DirectTransport send_transport(sender_call_.get());
1025 test::DirectTransport receive_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001026 PacketInputObserver input_observer(receiver_call_->Receiver());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001027 send_transport.SetReceiver(&input_observer);
1028 receive_transport.SetReceiver(sender_call_->Receiver());
1029
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001030 CreateSendConfig(1, 0, &send_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001031 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001032
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001033 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001034 CreateFrameGeneratorCapturer();
1035 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001036
stefanff483612015-12-21 03:14:00 -08001037 receiver_call_->DestroyVideoReceiveStream(video_receive_streams_[0]);
1038 video_receive_streams_.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001039
1040 // Wait() waits for a received packet.
Peter Boström5811a392015-12-10 13:02:50 +01001041 EXPECT_TRUE(input_observer.Wait());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001042
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001043 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001044
1045 DestroyStreams();
1046
1047 send_transport.StopSending();
1048 receive_transport.StopSending();
1049}
1050
pbosda903ea2015-10-02 02:36:56 -07001051void EndToEndTest::RespectsRtcpMode(RtcpMode rtcp_mode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001052 static const int kNumCompoundRtcpPacketsToObserve = 10;
1053 class RtcpModeObserver : public test::EndToEndTest {
1054 public:
pbosda903ea2015-10-02 02:36:56 -07001055 explicit RtcpModeObserver(RtcpMode rtcp_mode)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001056 : EndToEndTest(kDefaultTimeoutMs),
1057 rtcp_mode_(rtcp_mode),
1058 sent_rtp_(0),
1059 sent_rtcp_(0) {}
1060
1061 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001062 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001063 if (++sent_rtp_ % 3 == 0)
1064 return DROP_PACKET;
1065
1066 return SEND_PACKET;
1067 }
1068
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001069 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001070 ++sent_rtcp_;
1071 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1072 EXPECT_TRUE(parser.IsValid());
1073
1074 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1075 bool has_report_block = false;
Erik Språng242e22b2015-05-11 10:17:43 +02001076 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1077 EXPECT_NE(RTCPUtility::RTCPPacketTypes::kSr, packet_type);
1078 if (packet_type == RTCPUtility::RTCPPacketTypes::kRr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001079 has_report_block = true;
1080 break;
1081 }
1082 packet_type = parser.Iterate();
1083 }
1084
1085 switch (rtcp_mode_) {
pbosda903ea2015-10-02 02:36:56 -07001086 case RtcpMode::kCompound:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001087 if (!has_report_block) {
1088 ADD_FAILURE() << "Received RTCP packet without receiver report for "
pbosda903ea2015-10-02 02:36:56 -07001089 "RtcpMode::kCompound.";
Peter Boström5811a392015-12-10 13:02:50 +01001090 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001091 }
1092
1093 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
Peter Boström5811a392015-12-10 13:02:50 +01001094 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001095
1096 break;
pbosda903ea2015-10-02 02:36:56 -07001097 case RtcpMode::kReducedSize:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001098 if (!has_report_block)
Peter Boström5811a392015-12-10 13:02:50 +01001099 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001100 break;
pbosda903ea2015-10-02 02:36:56 -07001101 case RtcpMode::kOff:
1102 RTC_NOTREACHED();
1103 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001104 }
1105
1106 return SEND_PACKET;
1107 }
1108
stefanff483612015-12-21 03:14:00 -08001109 void ModifyVideoConfigs(
1110 VideoSendStream::Config* send_config,
1111 std::vector<VideoReceiveStream::Config>* receive_configs,
1112 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001113 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001114 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1115 (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001116 }
1117
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001118 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001119 EXPECT_TRUE(Wait())
pbosda903ea2015-10-02 02:36:56 -07001120 << (rtcp_mode_ == RtcpMode::kCompound
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001121 ? "Timed out before observing enough compound packets."
1122 : "Timed out before receiving a non-compound RTCP packet.");
1123 }
1124
pbosda903ea2015-10-02 02:36:56 -07001125 RtcpMode rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001126 int sent_rtp_;
1127 int sent_rtcp_;
1128 } test(rtcp_mode);
1129
stefane74eef12016-01-08 06:47:13 -08001130 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001131}
1132
1133TEST_F(EndToEndTest, UsesRtcpCompoundMode) {
pbosda903ea2015-10-02 02:36:56 -07001134 RespectsRtcpMode(RtcpMode::kCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001135}
1136
1137TEST_F(EndToEndTest, UsesRtcpReducedSizeMode) {
pbosda903ea2015-10-02 02:36:56 -07001138 RespectsRtcpMode(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001139}
1140
1141// Test sets up a Call multiple senders with different resolutions and SSRCs.
1142// Another is set up to receive all three of these with different renderers.
sprang867fb522015-08-03 04:38:41 -07001143class MultiStreamTest {
1144 public:
1145 static const size_t kNumStreams = 3;
1146 struct CodecSettings {
1147 uint32_t ssrc;
1148 int width;
1149 int height;
1150 } codec_settings[kNumStreams];
1151
1152 MultiStreamTest() {
1153 // TODO(sprang): Cleanup when msvc supports explicit initializers for array.
1154 codec_settings[0] = {1, 640, 480};
1155 codec_settings[1] = {2, 320, 240};
1156 codec_settings[2] = {3, 240, 160};
1157 }
1158
1159 virtual ~MultiStreamTest() {}
1160
1161 void RunTest() {
kwiberg27f982b2016-03-01 11:52:33 -08001162 std::unique_ptr<Call> sender_call(Call::Create(Call::Config()));
1163 std::unique_ptr<Call> receiver_call(Call::Create(Call::Config()));
1164 std::unique_ptr<test::DirectTransport> sender_transport(
stefanf116bd02015-10-27 08:29:42 -07001165 CreateSendTransport(sender_call.get()));
kwiberg27f982b2016-03-01 11:52:33 -08001166 std::unique_ptr<test::DirectTransport> receiver_transport(
stefanf116bd02015-10-27 08:29:42 -07001167 CreateReceiveTransport(receiver_call.get()));
sprang867fb522015-08-03 04:38:41 -07001168 sender_transport->SetReceiver(receiver_call->Receiver());
1169 receiver_transport->SetReceiver(sender_call->Receiver());
1170
kwiberg27f982b2016-03-01 11:52:33 -08001171 std::unique_ptr<VideoEncoder> encoders[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001172 for (size_t i = 0; i < kNumStreams; ++i)
1173 encoders[i].reset(VideoEncoder::Create(VideoEncoder::kVp8));
1174
1175 VideoSendStream* send_streams[kNumStreams];
1176 VideoReceiveStream* receive_streams[kNumStreams];
1177
1178 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
kwiberg4a206a92016-03-31 10:24:26 -07001179 std::vector<std::unique_ptr<VideoDecoder>> allocated_decoders;
sprang867fb522015-08-03 04:38:41 -07001180 for (size_t i = 0; i < kNumStreams; ++i) {
1181 uint32_t ssrc = codec_settings[i].ssrc;
1182 int width = codec_settings[i].width;
1183 int height = codec_settings[i].height;
1184
solenberg4fbae2b2015-08-28 04:07:10 -07001185 VideoSendStream::Config send_config(sender_transport.get());
sprang867fb522015-08-03 04:38:41 -07001186 send_config.rtp.ssrcs.push_back(ssrc);
1187 send_config.encoder_settings.encoder = encoders[i].get();
1188 send_config.encoder_settings.payload_name = "VP8";
1189 send_config.encoder_settings.payload_type = 124;
1190 VideoEncoderConfig encoder_config;
1191 encoder_config.streams = test::CreateVideoStreams(1);
1192 VideoStream* stream = &encoder_config.streams[0];
1193 stream->width = width;
1194 stream->height = height;
1195 stream->max_framerate = 5;
1196 stream->min_bitrate_bps = stream->target_bitrate_bps =
1197 stream->max_bitrate_bps = 100000;
1198
1199 UpdateSendConfig(i, &send_config, &encoder_config, &frame_generators[i]);
1200
1201 send_streams[i] =
1202 sender_call->CreateVideoSendStream(send_config, encoder_config);
1203 send_streams[i]->Start();
1204
solenberg4fbae2b2015-08-28 04:07:10 -07001205 VideoReceiveStream::Config receive_config(receiver_transport.get());
sprang867fb522015-08-03 04:38:41 -07001206 receive_config.rtp.remote_ssrc = ssrc;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001207 receive_config.rtp.local_ssrc = test::CallTest::kReceiverLocalVideoSsrc;
sprang867fb522015-08-03 04:38:41 -07001208 VideoReceiveStream::Decoder decoder =
1209 test::CreateMatchingDecoder(send_config.encoder_settings);
kwiberg4a206a92016-03-31 10:24:26 -07001210 allocated_decoders.push_back(
1211 std::unique_ptr<VideoDecoder>(decoder.decoder));
sprang867fb522015-08-03 04:38:41 -07001212 receive_config.decoders.push_back(decoder);
1213
1214 UpdateReceiveConfig(i, &receive_config);
1215
1216 receive_streams[i] =
1217 receiver_call->CreateVideoReceiveStream(receive_config);
1218 receive_streams[i]->Start();
1219
1220 frame_generators[i] = test::FrameGeneratorCapturer::Create(
1221 send_streams[i]->Input(), width, height, 30,
1222 Clock::GetRealTimeClock());
1223 frame_generators[i]->Start();
1224 }
1225
1226 Wait();
1227
1228 for (size_t i = 0; i < kNumStreams; ++i) {
1229 frame_generators[i]->Stop();
1230 sender_call->DestroyVideoSendStream(send_streams[i]);
1231 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1232 delete frame_generators[i];
1233 }
1234
1235 sender_transport->StopSending();
1236 receiver_transport->StopSending();
1237 }
1238
1239 protected:
1240 virtual void Wait() = 0;
1241 // Note: frame_generator is a point-to-pointer, since the actual instance
1242 // hasn't been created at the time of this call. Only when packets/frames
1243 // start flowing should this be dereferenced.
1244 virtual void UpdateSendConfig(
1245 size_t stream_index,
1246 VideoSendStream::Config* send_config,
1247 VideoEncoderConfig* encoder_config,
1248 test::FrameGeneratorCapturer** frame_generator) {}
1249 virtual void UpdateReceiveConfig(size_t stream_index,
1250 VideoReceiveStream::Config* receive_config) {
1251 }
stefanf116bd02015-10-27 08:29:42 -07001252 virtual test::DirectTransport* CreateSendTransport(Call* sender_call) {
1253 return new test::DirectTransport(sender_call);
sprang867fb522015-08-03 04:38:41 -07001254 }
stefanf116bd02015-10-27 08:29:42 -07001255 virtual test::DirectTransport* CreateReceiveTransport(Call* receiver_call) {
1256 return new test::DirectTransport(receiver_call);
sprang867fb522015-08-03 04:38:41 -07001257 }
1258};
1259
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001260// Each renderer verifies that it receives the expected resolution, and as soon
1261// as every renderer has received a frame, the test finishes.
andresp@webrtc.org02686112014-09-19 08:24:19 +00001262TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) {
nisse7ade7b32016-03-23 04:48:10 -07001263 class VideoOutputObserver : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001264 public:
sprang867fb522015-08-03 04:38:41 -07001265 VideoOutputObserver(const MultiStreamTest::CodecSettings& settings,
1266 uint32_t ssrc,
1267 test::FrameGeneratorCapturer** frame_generator)
1268 : settings_(settings),
1269 ssrc_(ssrc),
1270 frame_generator_(frame_generator),
Peter Boström5811a392015-12-10 13:02:50 +01001271 done_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001272
nisseeb83a1a2016-03-21 01:27:56 -07001273 void OnFrame(const VideoFrame& video_frame) override {
sprang867fb522015-08-03 04:38:41 -07001274 EXPECT_EQ(settings_.width, video_frame.width());
1275 EXPECT_EQ(settings_.height, video_frame.height());
1276 (*frame_generator_)->Stop();
Peter Boström5811a392015-12-10 13:02:50 +01001277 done_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001278 }
1279
sprang867fb522015-08-03 04:38:41 -07001280 uint32_t Ssrc() { return ssrc_; }
1281
Peter Boström5811a392015-12-10 13:02:50 +01001282 bool Wait() { return done_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001283
1284 private:
sprang867fb522015-08-03 04:38:41 -07001285 const MultiStreamTest::CodecSettings& settings_;
1286 const uint32_t ssrc_;
1287 test::FrameGeneratorCapturer** const frame_generator_;
Peter Boström5811a392015-12-10 13:02:50 +01001288 rtc::Event done_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001289 };
1290
sprang867fb522015-08-03 04:38:41 -07001291 class Tester : public MultiStreamTest {
1292 public:
1293 Tester() {}
1294 virtual ~Tester() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001295
sprang867fb522015-08-03 04:38:41 -07001296 protected:
1297 void Wait() override {
1298 for (const auto& observer : observers_) {
Peter Boström5811a392015-12-10 13:02:50 +01001299 EXPECT_TRUE(observer->Wait()) << "Time out waiting for from on ssrc "
1300 << observer->Ssrc();
sprang867fb522015-08-03 04:38:41 -07001301 }
1302 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001303
sprang867fb522015-08-03 04:38:41 -07001304 void UpdateSendConfig(
1305 size_t stream_index,
1306 VideoSendStream::Config* send_config,
1307 VideoEncoderConfig* encoder_config,
1308 test::FrameGeneratorCapturer** frame_generator) override {
1309 observers_[stream_index].reset(new VideoOutputObserver(
1310 codec_settings[stream_index], send_config->rtp.ssrcs.front(),
1311 frame_generator));
1312 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001313
sprang867fb522015-08-03 04:38:41 -07001314 void UpdateReceiveConfig(
1315 size_t stream_index,
1316 VideoReceiveStream::Config* receive_config) override {
1317 receive_config->renderer = observers_[stream_index].get();
1318 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001319
sprang867fb522015-08-03 04:38:41 -07001320 private:
kwiberg27f982b2016-03-01 11:52:33 -08001321 std::unique_ptr<VideoOutputObserver> observers_[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001322 } tester;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001323
sprang867fb522015-08-03 04:38:41 -07001324 tester.RunTest();
1325}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001326
sprang867fb522015-08-03 04:38:41 -07001327TEST_F(EndToEndTest, AssignsTransportSequenceNumbers) {
sprang867fb522015-08-03 04:38:41 -07001328 static const int kExtensionId = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001329
sprang867fb522015-08-03 04:38:41 -07001330 class RtpExtensionHeaderObserver : public test::DirectTransport {
1331 public:
stefanf116bd02015-10-27 08:29:42 -07001332 RtpExtensionHeaderObserver(Call* sender_call,
1333 const uint32_t& first_media_ssrc,
sprang861c55e2015-10-16 10:01:21 -07001334 const std::map<uint32_t, uint32_t>& ssrc_map)
stefanf116bd02015-10-27 08:29:42 -07001335 : DirectTransport(sender_call),
Peter Boström5811a392015-12-10 13:02:50 +01001336 done_(false, false),
sprang867fb522015-08-03 04:38:41 -07001337 parser_(RtpHeaderParser::Create()),
sprang861c55e2015-10-16 10:01:21 -07001338 first_media_ssrc_(first_media_ssrc),
1339 rtx_to_media_ssrcs_(ssrc_map),
sprang867fb522015-08-03 04:38:41 -07001340 padding_observed_(false),
sprang861c55e2015-10-16 10:01:21 -07001341 rtx_padding_observed_(false),
1342 retransmit_observed_(false),
1343 started_(false) {
sprang867fb522015-08-03 04:38:41 -07001344 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
1345 kExtensionId);
1346 }
1347 virtual ~RtpExtensionHeaderObserver() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001348
stefan1d8a5062015-10-02 03:39:33 -07001349 bool SendRtp(const uint8_t* data,
1350 size_t length,
1351 const PacketOptions& options) override {
sprang861c55e2015-10-16 10:01:21 -07001352 {
1353 rtc::CritScope cs(&lock_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001354
Erik Språng8d629712015-08-04 16:24:03 +02001355 if (IsDone())
sprang861c55e2015-10-16 10:01:21 -07001356 return false;
1357
1358 if (started_) {
1359 RTPHeader header;
1360 EXPECT_TRUE(parser_->Parse(data, length, &header));
1361 bool drop_packet = false;
1362
1363 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
1364 EXPECT_EQ(options.packet_id,
1365 header.extension.transportSequenceNumber);
1366 if (!streams_observed_.empty()) {
1367 // Unwrap packet id and verify uniqueness.
1368 int64_t packet_id = unwrapper_.Unwrap(options.packet_id);
1369 EXPECT_TRUE(received_packed_ids_.insert(packet_id).second);
1370 }
1371
1372 // Drop (up to) every 17th packet, so we get retransmits.
1373 // Only drop media, and not on the first stream (otherwise it will be
1374 // hard to distinguish from padding, which is always sent on the first
1375 // stream).
1376 if (header.payloadType != kSendRtxPayloadType &&
1377 header.ssrc != first_media_ssrc_ &&
1378 header.extension.transportSequenceNumber % 17 == 0) {
1379 dropped_seq_[header.ssrc].insert(header.sequenceNumber);
1380 drop_packet = true;
1381 }
1382
1383 size_t payload_length =
1384 length - (header.headerLength + header.paddingLength);
1385 if (payload_length == 0) {
1386 padding_observed_ = true;
1387 } else if (header.payloadType == kSendRtxPayloadType) {
1388 uint16_t original_sequence_number =
1389 ByteReader<uint16_t>::ReadBigEndian(&data[header.headerLength]);
1390 uint32_t original_ssrc =
1391 rtx_to_media_ssrcs_.find(header.ssrc)->second;
1392 std::set<uint16_t>* seq_no_map = &dropped_seq_[original_ssrc];
1393 auto it = seq_no_map->find(original_sequence_number);
1394 if (it != seq_no_map->end()) {
1395 retransmit_observed_ = true;
1396 seq_no_map->erase(it);
1397 } else {
1398 rtx_padding_observed_ = true;
1399 }
1400 } else {
1401 streams_observed_.insert(header.ssrc);
1402 }
1403
1404 if (IsDone())
Peter Boström5811a392015-12-10 13:02:50 +01001405 done_.Set();
sprang861c55e2015-10-16 10:01:21 -07001406
1407 if (drop_packet)
1408 return true;
1409 }
sprang867fb522015-08-03 04:38:41 -07001410 }
sprang861c55e2015-10-16 10:01:21 -07001411
stefan1d8a5062015-10-02 03:39:33 -07001412 return test::DirectTransport::SendRtp(data, length, options);
sprang867fb522015-08-03 04:38:41 -07001413 }
1414
Erik Språng8d629712015-08-04 16:24:03 +02001415 bool IsDone() {
sprang861c55e2015-10-16 10:01:21 -07001416 bool observed_types_ok =
1417 streams_observed_.size() == MultiStreamTest::kNumStreams &&
1418 padding_observed_ && retransmit_observed_ && rtx_padding_observed_;
1419 if (!observed_types_ok)
1420 return false;
1421 // We should not have any gaps in the sequence number range.
1422 size_t seqno_range =
1423 *received_packed_ids_.rbegin() - *received_packed_ids_.begin() + 1;
1424 return seqno_range == received_packed_ids_.size();
Erik Språng8d629712015-08-04 16:24:03 +02001425 }
1426
Peter Boström5811a392015-12-10 13:02:50 +01001427 bool Wait() {
sprang861c55e2015-10-16 10:01:21 -07001428 {
1429 // Can't be sure until this point that rtx_to_media_ssrcs_ etc have
1430 // been initialized and are OK to read.
1431 rtc::CritScope cs(&lock_);
1432 started_ = true;
1433 }
Peter Boström5811a392015-12-10 13:02:50 +01001434 return done_.Wait(kDefaultTimeoutMs);
sprang861c55e2015-10-16 10:01:21 -07001435 }
sprang867fb522015-08-03 04:38:41 -07001436
sprang861c55e2015-10-16 10:01:21 -07001437 rtc::CriticalSection lock_;
Peter Boström5811a392015-12-10 13:02:50 +01001438 rtc::Event done_;
kwiberg27f982b2016-03-01 11:52:33 -08001439 std::unique_ptr<RtpHeaderParser> parser_;
sprang861c55e2015-10-16 10:01:21 -07001440 SequenceNumberUnwrapper unwrapper_;
1441 std::set<int64_t> received_packed_ids_;
sprang867fb522015-08-03 04:38:41 -07001442 std::set<uint32_t> streams_observed_;
sprang861c55e2015-10-16 10:01:21 -07001443 std::map<uint32_t, std::set<uint16_t>> dropped_seq_;
1444 const uint32_t& first_media_ssrc_;
1445 const std::map<uint32_t, uint32_t>& rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001446 bool padding_observed_;
1447 bool rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001448 bool retransmit_observed_;
1449 bool started_;
sprang867fb522015-08-03 04:38:41 -07001450 };
1451
1452 class TransportSequenceNumberTester : public MultiStreamTest {
1453 public:
sprang861c55e2015-10-16 10:01:21 -07001454 TransportSequenceNumberTester()
1455 : first_media_ssrc_(0), observer_(nullptr) {}
sprang867fb522015-08-03 04:38:41 -07001456 virtual ~TransportSequenceNumberTester() {}
1457
1458 protected:
1459 void Wait() override {
Peter Boström74f6e9e2016-04-04 17:56:10 +02001460 RTC_DCHECK(observer_);
Peter Boström5811a392015-12-10 13:02:50 +01001461 EXPECT_TRUE(observer_->Wait());
sprang867fb522015-08-03 04:38:41 -07001462 }
1463
1464 void UpdateSendConfig(
1465 size_t stream_index,
1466 VideoSendStream::Config* send_config,
1467 VideoEncoderConfig* encoder_config,
1468 test::FrameGeneratorCapturer** frame_generator) override {
1469 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001470 send_config->rtp.extensions.push_back(RtpExtension(
1471 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sprang867fb522015-08-03 04:38:41 -07001472
1473 // Force some padding to be sent.
1474 const int kPaddingBitrateBps = 50000;
1475 int total_target_bitrate = 0;
1476 for (const VideoStream& stream : encoder_config->streams)
1477 total_target_bitrate += stream.target_bitrate_bps;
1478 encoder_config->min_transmit_bitrate_bps =
1479 total_target_bitrate + kPaddingBitrateBps;
1480
1481 // Configure RTX for redundant payload padding.
1482 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang861c55e2015-10-16 10:01:21 -07001483 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[stream_index]);
sprang867fb522015-08-03 04:38:41 -07001484 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
sprang861c55e2015-10-16 10:01:21 -07001485 rtx_to_media_ssrcs_[kSendRtxSsrcs[stream_index]] =
1486 send_config->rtp.ssrcs[0];
1487
1488 if (stream_index == 0)
1489 first_media_ssrc_ = send_config->rtp.ssrcs[0];
sprang867fb522015-08-03 04:38:41 -07001490 }
1491
1492 void UpdateReceiveConfig(
1493 size_t stream_index,
1494 VideoReceiveStream::Config* receive_config) override {
sprang861c55e2015-10-16 10:01:21 -07001495 receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang867fb522015-08-03 04:38:41 -07001496 receive_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001497 receive_config->rtp.extensions.push_back(RtpExtension(
1498 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sprang867fb522015-08-03 04:38:41 -07001499 }
1500
stefanf116bd02015-10-27 08:29:42 -07001501 test::DirectTransport* CreateSendTransport(Call* sender_call) override {
1502 observer_ = new RtpExtensionHeaderObserver(sender_call, first_media_ssrc_,
sprang861c55e2015-10-16 10:01:21 -07001503 rtx_to_media_ssrcs_);
sprang867fb522015-08-03 04:38:41 -07001504 return observer_;
1505 }
1506
1507 private:
sprang861c55e2015-10-16 10:01:21 -07001508 uint32_t first_media_ssrc_;
1509 std::map<uint32_t, uint32_t> rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001510 RtpExtensionHeaderObserver* observer_;
1511 } tester;
1512
1513 tester.RunTest();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001514}
1515
Stefan Holmer04cb7632016-01-14 20:34:30 +01001516class TransportFeedbackTester : public test::EndToEndTest {
1517 public:
1518 explicit TransportFeedbackTester(bool feedback_enabled,
1519 size_t num_video_streams,
1520 size_t num_audio_streams)
1521 : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
1522 feedback_enabled_(feedback_enabled),
1523 num_video_streams_(num_video_streams),
1524 num_audio_streams_(num_audio_streams) {
1525 // Only one stream of each supported for now.
1526 EXPECT_LE(num_video_streams, 1u);
1527 EXPECT_LE(num_audio_streams, 1u);
1528 }
1529
1530 protected:
1531 Action OnSendRtcp(const uint8_t* data, size_t length) override {
1532 EXPECT_FALSE(HasTransportFeedback(data, length));
1533 return SEND_PACKET;
1534 }
1535
1536 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
1537 if (HasTransportFeedback(data, length))
1538 observation_complete_.Set();
1539 return SEND_PACKET;
1540 }
1541
1542 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
1543 RTCPUtility::RTCPParserV2 parser(data, length, true);
1544 EXPECT_TRUE(parser.IsValid());
1545
1546 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1547 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1548 if (packet_type == RTCPUtility::RTCPPacketTypes::kTransportFeedback)
1549 return true;
1550 packet_type = parser.Iterate();
1551 }
1552
1553 return false;
1554 }
1555
1556 void PerformTest() override {
1557 const int64_t kDisabledFeedbackTimeoutMs = 5000;
1558 EXPECT_EQ(feedback_enabled_,
1559 observation_complete_.Wait(feedback_enabled_
1560 ? test::CallTest::kDefaultTimeoutMs
1561 : kDisabledFeedbackTimeoutMs));
1562 }
1563
1564 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1565 receiver_call_ = receiver_call;
1566 }
1567
1568 size_t GetNumVideoStreams() const override { return num_video_streams_; }
1569 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
1570
1571 void ModifyVideoConfigs(
1572 VideoSendStream::Config* send_config,
1573 std::vector<VideoReceiveStream::Config>* receive_configs,
1574 VideoEncoderConfig* encoder_config) override {
1575 send_config->rtp.extensions.clear();
1576 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001577 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001578 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1579 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
1580 }
1581
1582 void ModifyAudioConfigs(
1583 AudioSendStream::Config* send_config,
1584 std::vector<AudioReceiveStream::Config>* receive_configs) override {
1585 send_config->rtp.extensions.clear();
1586 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001587 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001588 (*receive_configs)[0].rtp.extensions.clear();
1589 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1590 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001591 }
1592
1593 private:
Erik Språng6b8d3552015-09-24 15:06:57 +02001594 static const int kExtensionId = 5;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001595 const bool feedback_enabled_;
1596 const size_t num_video_streams_;
1597 const size_t num_audio_streams_;
1598 Call* receiver_call_;
1599};
Erik Språng6b8d3552015-09-24 15:06:57 +02001600
Stefan Holmer04cb7632016-01-14 20:34:30 +01001601TEST_F(EndToEndTest, VideoReceivesTransportFeedback) {
1602 TransportFeedbackTester test(true, 1, 0);
1603 RunBaseTest(&test);
Erik Språng6b8d3552015-09-24 15:06:57 +02001604}
stefan43edf0f2015-11-20 18:05:48 -08001605
Stefan Holmer04cb7632016-01-14 20:34:30 +01001606TEST_F(EndToEndTest, VideoTransportFeedbackNotConfigured) {
1607 TransportFeedbackTester test(false, 1, 0);
1608 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001609}
1610
Stefan Holmer04cb7632016-01-14 20:34:30 +01001611TEST_F(EndToEndTest, AudioReceivesTransportFeedback) {
1612 TransportFeedbackTester test(true, 0, 1);
1613 RunBaseTest(&test);
1614}
1615
1616TEST_F(EndToEndTest, AudioTransportFeedbackNotConfigured) {
1617 TransportFeedbackTester test(false, 0, 1);
1618 RunBaseTest(&test);
1619}
1620
1621TEST_F(EndToEndTest, AudioVideoReceivesTransportFeedback) {
1622 TransportFeedbackTester test(true, 1, 1);
1623 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001624}
1625
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001626TEST_F(EndToEndTest, ObserversEncodedFrames) {
1627 class EncodedFrameTestObserver : public EncodedFrameObserver {
1628 public:
1629 EncodedFrameTestObserver()
Peter Boström5811a392015-12-10 13:02:50 +01001630 : length_(0), frame_type_(kEmptyFrame), called_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001631 virtual ~EncodedFrameTestObserver() {}
1632
1633 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
1634 frame_type_ = encoded_frame.frame_type_;
1635 length_ = encoded_frame.length_;
1636 buffer_.reset(new uint8_t[length_]);
1637 memcpy(buffer_.get(), encoded_frame.data_, length_);
Peter Boström5811a392015-12-10 13:02:50 +01001638 called_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001639 }
1640
Peter Boström5811a392015-12-10 13:02:50 +01001641 bool Wait() { return called_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001642
1643 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
1644 ASSERT_EQ(length_, observer.length_)
1645 << "Observed frames are of different lengths.";
1646 EXPECT_EQ(frame_type_, observer.frame_type_)
1647 << "Observed frames have different frame types.";
1648 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
1649 << "Observed encoded frames have different content.";
1650 }
1651
1652 private:
kwiberg27f982b2016-03-01 11:52:33 -08001653 std::unique_ptr<uint8_t[]> buffer_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001654 size_t length_;
1655 FrameType frame_type_;
Peter Boström5811a392015-12-10 13:02:50 +01001656 rtc::Event called_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001657 };
1658
1659 EncodedFrameTestObserver post_encode_observer;
1660 EncodedFrameTestObserver pre_decode_observer;
1661
solenberg4fbae2b2015-08-28 04:07:10 -07001662 CreateCalls(Call::Config(), Call::Config());
1663
stefanf116bd02015-10-27 08:29:42 -07001664 test::DirectTransport sender_transport(sender_call_.get());
1665 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001666 sender_transport.SetReceiver(receiver_call_->Receiver());
1667 receiver_transport.SetReceiver(sender_call_->Receiver());
1668
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001669 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001670 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -08001671 video_send_config_.post_encode_callback = &post_encode_observer;
1672 video_receive_configs_[0].pre_decode_callback = &pre_decode_observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001673
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001674 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001675 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001676
kwiberg27f982b2016-03-01 11:52:33 -08001677 std::unique_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +00001678 test::FrameGenerator::CreateChromaGenerator(
stefanff483612015-12-21 03:14:00 -08001679 video_encoder_config_.streams[0].width,
1680 video_encoder_config_.streams[0].height));
1681 video_send_stream_->Input()->IncomingCapturedFrame(
1682 *frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001683
Peter Boström5811a392015-12-10 13:02:50 +01001684 EXPECT_TRUE(post_encode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001685 << "Timed out while waiting for send-side encoded-frame callback.";
1686
Peter Boström5811a392015-12-10 13:02:50 +01001687 EXPECT_TRUE(pre_decode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001688 << "Timed out while waiting for pre-decode encoded-frame callback.";
1689
1690 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
1691
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001692 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001693
1694 sender_transport.StopSending();
1695 receiver_transport.StopSending();
1696
1697 DestroyStreams();
1698}
1699
1700TEST_F(EndToEndTest, ReceiveStreamSendsRemb) {
1701 class RembObserver : public test::EndToEndTest {
1702 public:
1703 RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
1704
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001705 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001706 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1707 EXPECT_TRUE(parser.IsValid());
1708
1709 bool received_psfb = false;
1710 bool received_remb = false;
1711 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02001712 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1713 if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbRemb) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001714 const RTCPUtility::RTCPPacket& packet = parser.Packet();
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001715 EXPECT_EQ(packet.PSFBAPP.SenderSSRC, kReceiverLocalVideoSsrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001716 received_psfb = true;
Erik Språng242e22b2015-05-11 10:17:43 +02001717 } else if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbRembItem) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001718 const RTCPUtility::RTCPPacket& packet = parser.Packet();
1719 EXPECT_GT(packet.REMBItem.BitRate, 0u);
1720 EXPECT_EQ(packet.REMBItem.NumberOfSSRCs, 1u);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001721 EXPECT_EQ(packet.REMBItem.SSRCs[0], kVideoSendSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001722 received_remb = true;
1723 }
1724 packet_type = parser.Iterate();
1725 }
1726 if (received_psfb && received_remb)
Peter Boström5811a392015-12-10 13:02:50 +01001727 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001728 return SEND_PACKET;
1729 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001730 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001731 EXPECT_TRUE(Wait()) << "Timed out while waiting for a "
1732 "receiver RTCP REMB packet to be "
1733 "sent.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001734 }
1735 } test;
1736
stefane74eef12016-01-08 06:47:13 -08001737 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001738}
1739
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001740TEST_F(EndToEndTest, VerifyBandwidthStats) {
stefanf116bd02015-10-27 08:29:42 -07001741 class RtcpObserver : public test::EndToEndTest {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001742 public:
1743 RtcpObserver()
1744 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001745 sender_call_(nullptr),
1746 receiver_call_(nullptr),
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001747 has_seen_pacer_delay_(false) {}
1748
stefanf116bd02015-10-27 08:29:42 -07001749 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001750 Call::Stats sender_stats = sender_call_->GetStats();
1751 Call::Stats receiver_stats = receiver_call_->GetStats();
1752 if (!has_seen_pacer_delay_)
1753 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
1754 if (sender_stats.send_bandwidth_bps > 0 &&
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001755 receiver_stats.recv_bandwidth_bps > 0 && has_seen_pacer_delay_) {
Peter Boström5811a392015-12-10 13:02:50 +01001756 observation_complete_.Set();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001757 }
stefanf116bd02015-10-27 08:29:42 -07001758 return SEND_PACKET;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001759 }
1760
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001761 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001762 sender_call_ = sender_call;
1763 receiver_call_ = receiver_call;
1764 }
1765
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001766 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001767 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
1768 "non-zero bandwidth stats.";
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001769 }
1770
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001771 private:
1772 Call* sender_call_;
1773 Call* receiver_call_;
1774 bool has_seen_pacer_delay_;
1775 } test;
1776
stefane74eef12016-01-08 06:47:13 -08001777 RunBaseTest(&test);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001778}
1779
stefan32f81542016-01-20 07:13:58 -08001780
1781// Verifies that it's possible to limit the send BWE by sending a REMB.
1782// This is verified by allowing the send BWE to ramp-up to >1000 kbps,
1783// then have the test generate a REMB of 500 kbps and verify that the send BWE
1784// is reduced to exactly 500 kbps. Then a REMB of 1000 kbps is generated and the
1785// test verifies that the send BWE ramps back up to exactly 1000 kbps.
1786TEST_F(EndToEndTest, RembWithSendSideBwe) {
1787 class BweObserver : public test::EndToEndTest {
1788 public:
1789 BweObserver()
1790 : EndToEndTest(kDefaultTimeoutMs),
1791 sender_call_(nullptr),
1792 clock_(Clock::GetRealTimeClock()),
1793 sender_ssrc_(0),
1794 remb_bitrate_bps_(1000000),
1795 receive_transport_(nullptr),
1796 event_(false, false),
1797 poller_thread_(&BitrateStatsPollingThread,
1798 this,
1799 "BitrateStatsPollingThread"),
1800 state_(kWaitForFirstRampUp) {}
1801
1802 ~BweObserver() {}
1803
nisseef8b61e2016-04-29 06:09:15 -07001804 test::PacketTransport* CreateReceiveTransport() override {
stefan32f81542016-01-20 07:13:58 -08001805 receive_transport_ = new test::PacketTransport(
1806 nullptr, this, test::PacketTransport::kReceiver,
1807 FakeNetworkPipe::Config());
1808 return receive_transport_;
1809 }
1810
1811 Call::Config GetSenderCallConfig() override {
1812 Call::Config config;
1813 // Set a high start bitrate to reduce the test completion time.
1814 config.bitrate_config.start_bitrate_bps = remb_bitrate_bps_;
1815 return config;
1816 }
1817
1818 void ModifyVideoConfigs(
1819 VideoSendStream::Config* send_config,
1820 std::vector<VideoReceiveStream::Config>* receive_configs,
1821 VideoEncoderConfig* encoder_config) override {
1822 ASSERT_EQ(1u, send_config->rtp.ssrcs.size());
1823 send_config->rtp.extensions.clear();
1824 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001825 RtpExtension(RtpExtension::kTransportSequenceNumberUri,
stefan32f81542016-01-20 07:13:58 -08001826 test::kTransportSequenceNumberExtensionId));
1827 sender_ssrc_ = send_config->rtp.ssrcs[0];
1828
1829 encoder_config->streams[0].max_bitrate_bps =
1830 encoder_config->streams[0].target_bitrate_bps = 2000000;
1831
1832 ASSERT_EQ(1u, receive_configs->size());
1833 (*receive_configs)[0].rtp.remb = false;
1834 (*receive_configs)[0].rtp.transport_cc = true;
1835 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1836 RtpRtcp::Configuration config;
1837 config.receiver_only = true;
1838 config.clock = clock_;
1839 config.outgoing_transport = receive_transport_;
1840 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
1841 rtp_rtcp_->SetRemoteSSRC((*receive_configs)[0].rtp.remote_ssrc);
1842 rtp_rtcp_->SetSSRC((*receive_configs)[0].rtp.local_ssrc);
1843 rtp_rtcp_->SetREMBStatus(true);
1844 rtp_rtcp_->SetSendingStatus(true);
1845 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
1846 }
1847
1848 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1849 sender_call_ = sender_call;
1850 }
1851
1852 static bool BitrateStatsPollingThread(void* obj) {
1853 return static_cast<BweObserver*>(obj)->PollStats();
1854 }
1855
1856 bool PollStats() {
1857 if (sender_call_) {
1858 Call::Stats stats = sender_call_->GetStats();
1859 switch (state_) {
1860 case kWaitForFirstRampUp:
1861 if (stats.send_bandwidth_bps >= remb_bitrate_bps_) {
1862 state_ = kWaitForRemb;
1863 remb_bitrate_bps_ /= 2;
1864 rtp_rtcp_->SetREMBData(
1865 remb_bitrate_bps_,
1866 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
1867 rtp_rtcp_->SendRTCP(kRtcpRr);
1868 }
1869 break;
1870
1871 case kWaitForRemb:
1872 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
1873 state_ = kWaitForSecondRampUp;
1874 remb_bitrate_bps_ *= 2;
1875 rtp_rtcp_->SetREMBData(
1876 remb_bitrate_bps_,
1877 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
1878 rtp_rtcp_->SendRTCP(kRtcpRr);
1879 }
1880 break;
1881
1882 case kWaitForSecondRampUp:
1883 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
1884 observation_complete_.Set();
1885 }
1886 break;
1887 }
1888 }
1889
1890 return !event_.Wait(1000);
1891 }
1892
1893 void PerformTest() override {
1894 poller_thread_.Start();
1895 EXPECT_TRUE(Wait())
1896 << "Timed out while waiting for bitrate to change according to REMB.";
1897 poller_thread_.Stop();
1898 }
1899
1900 private:
1901 enum TestState { kWaitForFirstRampUp, kWaitForRemb, kWaitForSecondRampUp };
1902
1903 Call* sender_call_;
1904 Clock* const clock_;
1905 uint32_t sender_ssrc_;
1906 int remb_bitrate_bps_;
kwiberg27f982b2016-03-01 11:52:33 -08001907 std::unique_ptr<RtpRtcp> rtp_rtcp_;
stefan32f81542016-01-20 07:13:58 -08001908 test::PacketTransport* receive_transport_;
1909 rtc::Event event_;
1910 rtc::PlatformThread poller_thread_;
1911 TestState state_;
1912 } test;
1913
1914 RunBaseTest(&test);
1915}
1916
Åsa Persson352b2d72015-04-15 18:00:40 +02001917TEST_F(EndToEndTest, VerifyNackStats) {
1918 static const int kPacketNumberToDrop = 200;
1919 class NackObserver : public test::EndToEndTest {
1920 public:
1921 NackObserver()
1922 : EndToEndTest(kLongTimeoutMs),
1923 sent_rtp_packets_(0),
1924 dropped_rtp_packet_(0),
1925 dropped_rtp_packet_requested_(false),
1926 send_stream_(nullptr),
1927 start_runtime_ms_(-1) {}
1928
1929 private:
1930 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08001931 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02001932 if (++sent_rtp_packets_ == kPacketNumberToDrop) {
kwiberg27f982b2016-03-01 11:52:33 -08001933 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
Åsa Persson352b2d72015-04-15 18:00:40 +02001934 RTPHeader header;
1935 EXPECT_TRUE(parser->Parse(packet, length, &header));
1936 dropped_rtp_packet_ = header.sequenceNumber;
1937 return DROP_PACKET;
1938 }
1939 VerifyStats();
1940 return SEND_PACKET;
1941 }
1942
1943 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08001944 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02001945 test::RtcpPacketParser rtcp_parser;
1946 rtcp_parser.Parse(packet, length);
1947 std::vector<uint16_t> nacks = rtcp_parser.nack_item()->last_nack_list();
1948 if (!nacks.empty() && std::find(
1949 nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) {
1950 dropped_rtp_packet_requested_ = true;
1951 }
1952 return SEND_PACKET;
1953 }
1954
stefan608213e2015-11-01 14:56:10 -08001955 void VerifyStats() EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
Åsa Persson352b2d72015-04-15 18:00:40 +02001956 if (!dropped_rtp_packet_requested_)
1957 return;
1958 int send_stream_nack_packets = 0;
1959 int receive_stream_nack_packets = 0;
1960 VideoSendStream::Stats stats = send_stream_->GetStats();
1961 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
1962 stats.substreams.begin(); it != stats.substreams.end(); ++it) {
1963 const VideoSendStream::StreamStats& stream_stats = it->second;
1964 send_stream_nack_packets +=
1965 stream_stats.rtcp_packet_type_counts.nack_packets;
1966 }
1967 for (size_t i = 0; i < receive_streams_.size(); ++i) {
1968 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
1969 receive_stream_nack_packets +=
1970 stats.rtcp_packet_type_counts.nack_packets;
1971 }
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001972 if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) {
Åsa Persson352b2d72015-04-15 18:00:40 +02001973 // NACK packet sent on receive stream and received on sent stream.
1974 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01001975 observation_complete_.Set();
Åsa Persson352b2d72015-04-15 18:00:40 +02001976 }
1977 }
1978
1979 bool MinMetricRunTimePassed() {
1980 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
1981 if (start_runtime_ms_ == -1) {
1982 start_runtime_ms_ = now;
1983 return false;
1984 }
1985 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
1986 return elapsed_sec > metrics::kMinRunTimeInSeconds;
1987 }
1988
stefanff483612015-12-21 03:14:00 -08001989 void ModifyVideoConfigs(
1990 VideoSendStream::Config* send_config,
1991 std::vector<VideoReceiveStream::Config>* receive_configs,
1992 VideoEncoderConfig* encoder_config) override {
Åsa Persson352b2d72015-04-15 18:00:40 +02001993 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1994 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1995 }
1996
stefanff483612015-12-21 03:14:00 -08001997 void OnVideoStreamsCreated(
Åsa Persson352b2d72015-04-15 18:00:40 +02001998 VideoSendStream* send_stream,
1999 const std::vector<VideoReceiveStream*>& receive_streams) override {
2000 send_stream_ = send_stream;
2001 receive_streams_ = receive_streams;
2002 }
2003
2004 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002005 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson352b2d72015-04-15 18:00:40 +02002006 }
2007
stefan608213e2015-11-01 14:56:10 -08002008 rtc::CriticalSection crit_;
Åsa Persson352b2d72015-04-15 18:00:40 +02002009 uint64_t sent_rtp_packets_;
stefan608213e2015-11-01 14:56:10 -08002010 uint16_t dropped_rtp_packet_ GUARDED_BY(&crit_);
2011 bool dropped_rtp_packet_requested_ GUARDED_BY(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002012 std::vector<VideoReceiveStream*> receive_streams_;
2013 VideoSendStream* send_stream_;
2014 int64_t start_runtime_ms_;
2015 } test;
2016
asapersson01d70a32016-05-20 06:29:46 -07002017 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002018 RunBaseTest(&test);
Åsa Persson352b2d72015-04-15 18:00:40 +02002019
asapersson01d70a32016-05-20 06:29:46 -07002020 EXPECT_EQ(
2021 1, metrics::NumSamples("WebRTC.Video.UniqueNackRequestsSentInPercent"));
2022 EXPECT_EQ(1, metrics::NumSamples(
2023 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
2024 EXPECT_GT(metrics::MinSample("WebRTC.Video.NackPacketsSentPerMinute"), 0);
Åsa Persson352b2d72015-04-15 18:00:40 +02002025}
2026
sprangb4a1ae52015-12-03 08:10:08 -08002027void EndToEndTest::VerifyHistogramStats(bool use_rtx,
2028 bool use_red,
2029 bool screenshare) {
stefanf116bd02015-10-27 08:29:42 -07002030 class StatsObserver : public test::EndToEndTest {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002031 public:
sprangb4a1ae52015-12-03 08:10:08 -08002032 StatsObserver(bool use_rtx, bool use_red, bool screenshare)
Åsa Persson3c391cb2015-04-27 10:09:49 +02002033 : EndToEndTest(kLongTimeoutMs),
2034 use_rtx_(use_rtx),
2035 use_red_(use_red),
sprangb4a1ae52015-12-03 08:10:08 -08002036 screenshare_(screenshare),
Peter Boström39593972016-02-15 11:27:15 +01002037 // This test uses NACK, so to send FEC we can't use a fake encoder.
2038 vp8_encoder_(
2039 use_red ? VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)
2040 : nullptr),
Åsa Persson3c391cb2015-04-27 10:09:49 +02002041 sender_call_(nullptr),
2042 receiver_call_(nullptr),
2043 start_runtime_ms_(-1) {}
2044
2045 private:
2046 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2047 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002048 observation_complete_.Set();
Åsa Persson3c391cb2015-04-27 10:09:49 +02002049
stefanf116bd02015-10-27 08:29:42 -07002050 return SEND_PACKET;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002051 }
2052
2053 bool MinMetricRunTimePassed() {
2054 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2055 if (start_runtime_ms_ == -1) {
2056 start_runtime_ms_ = now;
2057 return false;
2058 }
2059 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2060 return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
2061 }
2062
stefanff483612015-12-21 03:14:00 -08002063 void ModifyVideoConfigs(
2064 VideoSendStream::Config* send_config,
2065 std::vector<VideoReceiveStream::Config>* receive_configs,
2066 VideoEncoderConfig* encoder_config) override {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002067 // NACK
2068 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2069 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2070 // FEC
2071 if (use_red_) {
2072 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
2073 send_config->rtp.fec.red_payload_type = kRedPayloadType;
Peter Boström39593972016-02-15 11:27:15 +01002074 send_config->encoder_settings.encoder = vp8_encoder_.get();
2075 send_config->encoder_settings.payload_name = "VP8";
2076 (*receive_configs)[0].decoders[0].payload_name = "VP8";
Åsa Persson3c391cb2015-04-27 10:09:49 +02002077 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
2078 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
2079 }
2080 // RTX
2081 if (use_rtx_) {
2082 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
2083 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002084 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002085 kSendRtxSsrcs[0];
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002086 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002087 kSendRtxPayloadType;
2088 }
sprangb4a1ae52015-12-03 08:10:08 -08002089 encoder_config->content_type =
2090 screenshare_ ? VideoEncoderConfig::ContentType::kScreen
2091 : VideoEncoderConfig::ContentType::kRealtimeVideo;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002092 }
2093
2094 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2095 sender_call_ = sender_call;
2096 receiver_call_ = receiver_call;
2097 }
2098
Åsa Persson3c391cb2015-04-27 10:09:49 +02002099 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002100 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson3c391cb2015-04-27 10:09:49 +02002101 }
2102
sprangb4a1ae52015-12-03 08:10:08 -08002103 const bool use_rtx_;
2104 const bool use_red_;
2105 const bool screenshare_;
kwiberg27f982b2016-03-01 11:52:33 -08002106 const std::unique_ptr<VideoEncoder> vp8_encoder_;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002107 Call* sender_call_;
2108 Call* receiver_call_;
2109 int64_t start_runtime_ms_;
sprangb4a1ae52015-12-03 08:10:08 -08002110 } test(use_rtx, use_red, screenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002111
asapersson01d70a32016-05-20 06:29:46 -07002112 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002113 RunBaseTest(&test);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002114
stefan91d92602015-11-11 10:13:02 -08002115 // Delete the call for Call stats to be reported.
stefan18adf0a2015-11-17 06:24:56 -08002116 sender_call_.reset();
stefan91d92602015-11-11 10:13:02 -08002117 receiver_call_.reset();
2118
sprangb4a1ae52015-12-03 08:10:08 -08002119 std::string video_prefix =
2120 screenshare ? "WebRTC.Video.Screenshare." : "WebRTC.Video.";
2121
Åsa Persson3c391cb2015-04-27 10:09:49 +02002122 // Verify that stats have been updated once.
asapersson01d70a32016-05-20 06:29:46 -07002123 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
2124 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.RtcpBitrateReceivedInBps"));
2125 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.BitrateReceivedInKbps"));
2126 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.EstimatedSendBitrateInKbps"));
2127 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.PacerBitrateInKbps"));
2128
2129 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
stefan91d92602015-11-11 10:13:02 -08002130 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002131 metrics::NumSamples(video_prefix + "NackPacketsReceivedPerMinute"));
2132 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
asaperssond89920b2015-07-22 06:52:00 -07002133 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002134 metrics::NumSamples(video_prefix + "FirPacketsReceivedPerMinute"));
2135 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
sprangb4a1ae52015-12-03 08:10:08 -08002136 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002137 metrics::NumSamples(video_prefix + "PliPacketsReceivedPerMinute"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002138
asapersson01d70a32016-05-20 06:29:46 -07002139 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "KeyFramesSentInPermille"));
2140 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
2141
2142 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentPacketsLostInPercent"));
2143 EXPECT_EQ(1,
2144 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
2145
2146 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputWidthInPixels"));
2147 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputHeightInPixels"));
2148 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentWidthInPixels"));
2149 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentHeightInPixels"));
2150 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
2151 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
2152
2153 EXPECT_EQ(1, metrics::NumEvents(
2154 video_prefix + "InputWidthInPixels",
2155 static_cast<int>(video_encoder_config_.streams[0].width)));
2156 EXPECT_EQ(1, metrics::NumEvents(
2157 video_prefix + "InputHeightInPixels",
2158 static_cast<int>(video_encoder_config_.streams[0].height)));
2159 EXPECT_EQ(1, metrics::NumEvents(
2160 video_prefix + "SentWidthInPixels",
2161 static_cast<int>(video_encoder_config_.streams[0].width)));
2162 EXPECT_EQ(1, metrics::NumEvents(
2163 video_prefix + "SentHeightInPixels",
2164 static_cast<int>(video_encoder_config_.streams[0].height)));
2165 EXPECT_EQ(1, metrics::NumEvents(
2166 "WebRTC.Video.ReceivedWidthInPixels",
2167 static_cast<int>(video_encoder_config_.streams[0].width)));
2168 EXPECT_EQ(1, metrics::NumEvents(
2169 "WebRTC.Video.ReceivedHeightInPixels",
2170 static_cast<int>(video_encoder_config_.streams[0].height)));
2171
2172 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputFramesPerSecond"));
2173 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentFramesPerSecond"));
2174 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
2175 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
2176
2177 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
2178 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
2179 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
2180 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
2181
2182 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
2183
2184 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EncodeTimeInMs"));
2185 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
2186
2187 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "BitrateSentInKbps"));
2188 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateReceivedInKbps"));
2189 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "MediaBitrateSentInKbps"));
2190 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateReceivedInKbps"));
2191 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PaddingBitrateSentInKbps"));
2192 EXPECT_EQ(1,
2193 metrics::NumSamples("WebRTC.Video.PaddingBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002194 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002195 1, metrics::NumSamples(video_prefix + "RetransmittedBitrateSentInKbps"));
2196 EXPECT_EQ(1, metrics::NumSamples(
2197 "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002198
asapersson01d70a32016-05-20 06:29:46 -07002199 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendDelayInMs"));
2200 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayInMs"));
2201 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayMaxInMs"));
asapersson6f14be82015-11-16 00:40:49 -08002202
Åsa Persson3c391cb2015-04-27 10:09:49 +02002203 int num_rtx_samples = use_rtx ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002204 EXPECT_EQ(num_rtx_samples,
2205 metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2206 EXPECT_EQ(num_rtx_samples,
2207 metrics::NumSamples("WebRTC.Video.RtxBitrateReceivedInKbps"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002208
2209 int num_red_samples = use_red ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002210 EXPECT_EQ(num_red_samples,
2211 metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2212 EXPECT_EQ(num_red_samples,
2213 metrics::NumSamples("WebRTC.Video.FecBitrateReceivedInKbps"));
2214 EXPECT_EQ(num_red_samples,
2215 metrics::NumSamples("WebRTC.Video.ReceivedFecPacketsInPercent"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002216}
2217
2218TEST_F(EndToEndTest, VerifyHistogramStatsWithRtx) {
2219 const bool kEnabledRtx = true;
2220 const bool kEnabledRed = false;
sprangb4a1ae52015-12-03 08:10:08 -08002221 const bool kScreenshare = false;
2222 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002223}
2224
2225TEST_F(EndToEndTest, VerifyHistogramStatsWithRed) {
2226 const bool kEnabledRtx = false;
2227 const bool kEnabledRed = true;
sprangb4a1ae52015-12-03 08:10:08 -08002228 const bool kScreenshare = false;
2229 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
2230}
2231
2232TEST_F(EndToEndTest, VerifyHistogramStatsWithScreenshare) {
2233 const bool kEnabledRtx = false;
2234 const bool kEnabledRed = false;
2235 const bool kScreenshare = true;
2236 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002237}
2238
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002239void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
2240 static const int kNumRtcpReportPacketsToObserve = 5;
2241 class RtcpXrObserver : public test::EndToEndTest {
2242 public:
2243 explicit RtcpXrObserver(bool enable_rrtr)
2244 : EndToEndTest(kDefaultTimeoutMs),
2245 enable_rrtr_(enable_rrtr),
2246 sent_rtcp_sr_(0),
2247 sent_rtcp_rr_(0),
2248 sent_rtcp_rrtr_(0),
2249 sent_rtcp_dlrr_(0) {}
2250
2251 private:
2252 // Receive stream should send RR packets (and RRTR packets if enabled).
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002253 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002254 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002255 RTCPUtility::RTCPParserV2 parser(packet, length, true);
2256 EXPECT_TRUE(parser.IsValid());
2257
2258 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02002259 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
2260 if (packet_type == RTCPUtility::RTCPPacketTypes::kRr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002261 ++sent_rtcp_rr_;
2262 } else if (packet_type ==
Erik Språng242e22b2015-05-11 10:17:43 +02002263 RTCPUtility::RTCPPacketTypes::kXrReceiverReferenceTime) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002264 ++sent_rtcp_rrtr_;
2265 }
Erik Språng242e22b2015-05-11 10:17:43 +02002266 EXPECT_NE(packet_type, RTCPUtility::RTCPPacketTypes::kSr);
2267 EXPECT_NE(packet_type,
2268 RTCPUtility::RTCPPacketTypes::kXrDlrrReportBlockItem);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002269 packet_type = parser.Iterate();
2270 }
2271 return SEND_PACKET;
2272 }
2273 // Send stream should send SR packets (and DLRR packets if enabled).
nisseef8b61e2016-04-29 06:09:15 -07002274 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002275 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002276 RTCPUtility::RTCPParserV2 parser(packet, length, true);
2277 EXPECT_TRUE(parser.IsValid());
2278
2279 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02002280 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
2281 if (packet_type == RTCPUtility::RTCPPacketTypes::kSr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002282 ++sent_rtcp_sr_;
Erik Språng242e22b2015-05-11 10:17:43 +02002283 } else if (packet_type ==
2284 RTCPUtility::RTCPPacketTypes::kXrDlrrReportBlockItem) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002285 ++sent_rtcp_dlrr_;
2286 }
Erik Språng242e22b2015-05-11 10:17:43 +02002287 EXPECT_NE(packet_type,
2288 RTCPUtility::RTCPPacketTypes::kXrReceiverReferenceTime);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002289 packet_type = parser.Iterate();
2290 }
2291 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
2292 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve) {
2293 if (enable_rrtr_) {
2294 EXPECT_GT(sent_rtcp_rrtr_, 0);
2295 EXPECT_GT(sent_rtcp_dlrr_, 0);
2296 } else {
2297 EXPECT_EQ(0, sent_rtcp_rrtr_);
2298 EXPECT_EQ(0, sent_rtcp_dlrr_);
2299 }
Peter Boström5811a392015-12-10 13:02:50 +01002300 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002301 }
2302 return SEND_PACKET;
2303 }
2304
stefanff483612015-12-21 03:14:00 -08002305 void ModifyVideoConfigs(
2306 VideoSendStream::Config* send_config,
2307 std::vector<VideoReceiveStream::Config>* receive_configs,
2308 VideoEncoderConfig* encoder_config) override {
pbosda903ea2015-10-02 02:36:56 -07002309 (*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002310 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
2311 enable_rrtr_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002312 }
2313
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002314 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002315 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002316 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
2317 }
2318
stefan608213e2015-11-01 14:56:10 -08002319 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002320 bool enable_rrtr_;
2321 int sent_rtcp_sr_;
stefan608213e2015-11-01 14:56:10 -08002322 int sent_rtcp_rr_ GUARDED_BY(&crit_);
2323 int sent_rtcp_rrtr_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002324 int sent_rtcp_dlrr_;
2325 } test(enable_rrtr);
2326
stefane74eef12016-01-08 06:47:13 -08002327 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002328}
2329
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002330void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
2331 bool send_single_ssrc_first) {
2332 class SendsSetSsrcs : public test::EndToEndTest {
2333 public:
2334 SendsSetSsrcs(const uint32_t* ssrcs,
2335 size_t num_ssrcs,
2336 bool send_single_ssrc_first)
2337 : EndToEndTest(kDefaultTimeoutMs),
2338 num_ssrcs_(num_ssrcs),
2339 send_single_ssrc_first_(send_single_ssrc_first),
2340 ssrcs_to_observe_(num_ssrcs),
sprang867fb522015-08-03 04:38:41 -07002341 expect_single_ssrc_(send_single_ssrc_first),
2342 send_stream_(nullptr) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002343 for (size_t i = 0; i < num_ssrcs; ++i)
2344 valid_ssrcs_[ssrcs[i]] = true;
2345 }
2346
2347 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002348 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002349 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002350 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002351
2352 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
2353 << "Received unknown SSRC: " << header.ssrc;
2354
2355 if (!valid_ssrcs_[header.ssrc])
Peter Boström5811a392015-12-10 13:02:50 +01002356 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002357
2358 if (!is_observed_[header.ssrc]) {
2359 is_observed_[header.ssrc] = true;
2360 --ssrcs_to_observe_;
2361 if (expect_single_ssrc_) {
2362 expect_single_ssrc_ = false;
Peter Boström5811a392015-12-10 13:02:50 +01002363 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002364 }
2365 }
2366
2367 if (ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002368 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002369
2370 return SEND_PACKET;
2371 }
2372
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002373 size_t GetNumVideoStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002374
stefanff483612015-12-21 03:14:00 -08002375 void ModifyVideoConfigs(
2376 VideoSendStream::Config* send_config,
2377 std::vector<VideoReceiveStream::Config>* receive_configs,
2378 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002379 if (num_ssrcs_ > 1) {
2380 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002381 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2382 encoder_config->streams[i].min_bitrate_bps = 10000;
2383 encoder_config->streams[i].target_bitrate_bps = 15000;
2384 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002385 }
2386 }
2387
stefanff483612015-12-21 03:14:00 -08002388 video_encoder_config_all_streams_ = *encoder_config;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002389 if (send_single_ssrc_first_)
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002390 encoder_config->streams.resize(1);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002391 }
2392
stefanff483612015-12-21 03:14:00 -08002393 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002394 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002395 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002396 send_stream_ = send_stream;
2397 }
2398
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002399 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002400 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2401 << (send_single_ssrc_first_ ? "first SSRC."
2402 : "SSRCs.");
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002403
2404 if (send_single_ssrc_first_) {
2405 // Set full simulcast and continue with the rest of the SSRCs.
stefanff483612015-12-21 03:14:00 -08002406 send_stream_->ReconfigureVideoEncoder(
2407 video_encoder_config_all_streams_);
Peter Boström5811a392015-12-10 13:02:50 +01002408 EXPECT_TRUE(Wait()) << "Timed out while waiting on additional SSRCs.";
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002409 }
2410 }
2411
2412 private:
2413 std::map<uint32_t, bool> valid_ssrcs_;
2414 std::map<uint32_t, bool> is_observed_;
2415
2416 const size_t num_ssrcs_;
2417 const bool send_single_ssrc_first_;
2418
2419 size_t ssrcs_to_observe_;
2420 bool expect_single_ssrc_;
2421
2422 VideoSendStream* send_stream_;
stefanff483612015-12-21 03:14:00 -08002423 VideoEncoderConfig video_encoder_config_all_streams_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002424 } test(kVideoSendSsrcs, num_ssrcs, send_single_ssrc_first);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002425
stefane74eef12016-01-08 06:47:13 -08002426 RunBaseTest(&test);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002427}
2428
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002429TEST_F(EndToEndTest, ReportsSetEncoderRates) {
2430 class EncoderRateStatsTest : public test::EndToEndTest,
2431 public test::FakeEncoder {
2432 public:
2433 EncoderRateStatsTest()
2434 : EndToEndTest(kDefaultTimeoutMs),
sprang867fb522015-08-03 04:38:41 -07002435 FakeEncoder(Clock::GetRealTimeClock()),
2436 send_stream_(nullptr),
2437 bitrate_kbps_(0) {}
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002438
stefanff483612015-12-21 03:14:00 -08002439 void OnVideoStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002440 VideoSendStream* send_stream,
2441 const std::vector<VideoReceiveStream*>& receive_streams) override {
2442 send_stream_ = send_stream;
2443 }
2444
stefanff483612015-12-21 03:14:00 -08002445 void ModifyVideoConfigs(
2446 VideoSendStream::Config* send_config,
2447 std::vector<VideoReceiveStream::Config>* receive_configs,
2448 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002449 send_config->encoder_settings.encoder = this;
2450 }
2451
2452 int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override {
2453 // Make sure not to trigger on any default zero bitrates.
2454 if (new_target_bitrate == 0)
2455 return 0;
Peter Boströmf2f82832015-05-01 13:00:41 +02002456 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002457 bitrate_kbps_ = new_target_bitrate;
Peter Boström5811a392015-12-10 13:02:50 +01002458 observation_complete_.Set();
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002459 return 0;
2460 }
2461
2462 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002463 ASSERT_TRUE(Wait())
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002464 << "Timed out while waiting for encoder SetRates() call.";
2465 // Wait for GetStats to report a corresponding bitrate.
Peter Boström5811a392015-12-10 13:02:50 +01002466 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002467 VideoSendStream::Stats stats = send_stream_->GetStats();
2468 {
Peter Boströmf2f82832015-05-01 13:00:41 +02002469 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002470 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
2471 static_cast<int>(bitrate_kbps_)) {
2472 return;
2473 }
2474 }
2475 SleepMs(1);
2476 }
2477 FAIL()
2478 << "Timed out waiting for stats reporting the currently set bitrate.";
2479 }
2480
2481 private:
stefanf116bd02015-10-27 08:29:42 -07002482 rtc::CriticalSection crit_;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002483 VideoSendStream* send_stream_;
2484 uint32_t bitrate_kbps_ GUARDED_BY(crit_);
2485 } test;
2486
stefane74eef12016-01-08 06:47:13 -08002487 RunBaseTest(&test);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002488}
2489
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002490TEST_F(EndToEndTest, GetStats) {
2491 static const int kStartBitrateBps = 3000000;
Peter Boströmdef398832015-05-27 17:59:11 +02002492 static const int kExpectedRenderDelayMs = 20;
nissed30a1112016-04-18 05:15:22 -07002493 class StatsObserver : public test::EndToEndTest,
2494 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002495 public:
stefanf116bd02015-10-27 08:29:42 -07002496 StatsObserver()
2497 : EndToEndTest(kLongTimeoutMs),
Peter Boströmc6e16e32016-02-05 14:15:53 +01002498 encoder_(Clock::GetRealTimeClock(), 10),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002499 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002500 expected_send_ssrcs_(),
Peter Boström5811a392015-12-10 13:02:50 +01002501 check_stats_event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002502
2503 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002504 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002505 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002506 return SEND_PACKET;
2507 }
2508
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002509 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002510 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002511 return SEND_PACKET;
2512 }
2513
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002514 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002515 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002516 return SEND_PACKET;
2517 }
2518
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002519 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002520 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002521 return SEND_PACKET;
2522 }
2523
nissed30a1112016-04-18 05:15:22 -07002524 void OnFrame(const VideoFrame& video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002525 // Ensure that we have at least 5ms send side delay.
nissed30a1112016-04-18 05:15:22 -07002526 SleepMs(5);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002527 }
2528
2529 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002530 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2531 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2532 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002533
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002534 // Make sure all fields have been populated.
2535 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
2536 // always filled for all receivers.
2537 receive_stats_filled_["IncomingRate"] |=
2538 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002539
Peter Boströmb7d9a972015-12-18 16:01:11 +01002540 send_stats_filled_["DecoderImplementationName"] |=
2541 stats.decoder_implementation_name ==
2542 test::FakeDecoder::kImplementationName;
Peter Boströmdef398832015-05-27 17:59:11 +02002543 receive_stats_filled_["RenderDelayAsHighAsExpected"] |=
2544 stats.render_delay_ms >= kExpectedRenderDelayMs;
2545
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002546 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002547
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002548 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002549
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002550 receive_stats_filled_["StatisticsUpdated"] |=
2551 stats.rtcp_stats.cumulative_lost != 0 ||
2552 stats.rtcp_stats.extended_max_sequence_number != 0 ||
2553 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002554
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002555 receive_stats_filled_["DataCountersUpdated"] |=
2556 stats.rtp_stats.transmitted.payload_bytes != 0 ||
2557 stats.rtp_stats.fec.packets != 0 ||
2558 stats.rtp_stats.transmitted.header_bytes != 0 ||
2559 stats.rtp_stats.transmitted.packets != 0 ||
2560 stats.rtp_stats.transmitted.padding_bytes != 0 ||
2561 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002562
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002563 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002564 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002565
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002566 receive_stats_filled_["FrameCounts"] |=
2567 stats.frame_counts.key_frames != 0 ||
2568 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002569
pbosbb36fdf2015-07-09 07:48:14 -07002570 receive_stats_filled_["CName"] |= !stats.c_name.empty();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002571
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002572 receive_stats_filled_["RtcpPacketTypeCount"] |=
2573 stats.rtcp_packet_type_counts.fir_packets != 0 ||
2574 stats.rtcp_packet_type_counts.nack_packets != 0 ||
2575 stats.rtcp_packet_type_counts.pli_packets != 0 ||
2576 stats.rtcp_packet_type_counts.nack_requests != 0 ||
2577 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbosf42376c2015-08-28 07:35:32 -07002578
2579 assert(stats.current_payload_type == -1 ||
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002580 stats.current_payload_type == kFakeVideoSendPayloadType);
pbosf42376c2015-08-28 07:35:32 -07002581 receive_stats_filled_["IncomingPayloadType"] |=
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002582 stats.current_payload_type == kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002583 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002584
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002585 return AllStatsFilled(receive_stats_filled_);
2586 }
2587
2588 bool CheckSendStats() {
Peter Boström74f6e9e2016-04-04 17:56:10 +02002589 RTC_DCHECK(send_stream_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002590 VideoSendStream::Stats stats = send_stream_->GetStats();
2591
2592 send_stats_filled_["NumStreams"] |=
2593 stats.substreams.size() == expected_send_ssrcs_.size();
2594
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002595 send_stats_filled_["CpuOveruseMetrics"] |=
Peter Boströme4499152016-02-05 11:13:28 +01002596 stats.avg_encode_time_ms != 0 && stats.encode_usage_percent != 0;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002597
Peter Boströmb7d9a972015-12-18 16:01:11 +01002598 send_stats_filled_["EncoderImplementationName"] |=
2599 stats.encoder_implementation_name ==
2600 test::FakeEncoder::kImplementationName;
2601
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002602 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002603 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002604 it != stats.substreams.end(); ++it) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002605 EXPECT_TRUE(expected_send_ssrcs_.find(it->first) !=
2606 expected_send_ssrcs_.end());
2607
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002608 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002609 stats.input_frame_rate != 0;
2610
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002611 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002612
2613 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
2614 stream_stats.rtcp_stats.cumulative_lost != 0 ||
2615 stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
2616 stream_stats.rtcp_stats.fraction_lost != 0;
2617
2618 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002619 stream_stats.rtp_stats.fec.packets != 0 ||
2620 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
2621 stream_stats.rtp_stats.retransmitted.packets != 0 ||
2622 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002623
2624 send_stats_filled_[CompoundKey("BitrateStatisticsObserver",
2625 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002626 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002627
2628 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002629 stream_stats.frame_counts.delta_frames != 0 ||
2630 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002631
2632 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
2633 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00002634
2635 send_stats_filled_[CompoundKey("Delay", it->first)] |=
2636 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002637
2638 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
2639 // report dropped packets.
2640 send_stats_filled_["RtcpPacketTypeCount"] |=
2641 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
2642 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
2643 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
2644 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
2645 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002646 }
2647
2648 return AllStatsFilled(send_stats_filled_);
2649 }
2650
2651 std::string CompoundKey(const char* name, uint32_t ssrc) {
2652 std::ostringstream oss;
2653 oss << name << "_" << ssrc;
2654 return oss.str();
2655 }
2656
2657 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
2658 for (std::map<std::string, bool>::const_iterator it = stats_map.begin();
2659 it != stats_map.end();
2660 ++it) {
2661 if (!it->second)
2662 return false;
2663 }
2664 return true;
2665 }
2666
stefane74eef12016-01-08 06:47:13 -08002667 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
2668 FakeNetworkPipe::Config network_config;
2669 network_config.loss_percent = 5;
2670 return new test::PacketTransport(
2671 sender_call, this, test::PacketTransport::kSender, network_config);
2672 }
2673
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002674 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002675 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01002676 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002677 return config;
2678 }
2679
stefanff483612015-12-21 03:14:00 -08002680 void ModifyVideoConfigs(
2681 VideoSendStream::Config* send_config,
2682 std::vector<VideoReceiveStream::Config>* receive_configs,
2683 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002684 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002685 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002686
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002687 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002688 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002689 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002690 expected_receive_ssrcs_.push_back(
2691 (*receive_configs)[i].rtp.remote_ssrc);
Peter Boströmdef398832015-05-27 17:59:11 +02002692 (*receive_configs)[i].render_delay_ms = kExpectedRenderDelayMs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002693 }
Peter Boströmc6e16e32016-02-05 14:15:53 +01002694 // Use a delayed encoder to make sure we see CpuOveruseMetrics stats that
2695 // are non-zero.
2696 send_config->encoder_settings.encoder = &encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002697 }
2698
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002699 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00002700
stefanff483612015-12-21 03:14:00 -08002701 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002702 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002703 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002704 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002705 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002706 }
2707
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002708 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002709 Clock* clock = Clock::GetRealTimeClock();
2710 int64_t now = clock->TimeInMilliseconds();
2711 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
2712 bool receive_ok = false;
2713 bool send_ok = false;
2714
2715 while (now < stop_time) {
2716 if (!receive_ok)
2717 receive_ok = CheckReceiveStats();
2718 if (!send_ok)
2719 send_ok = CheckSendStats();
2720
2721 if (receive_ok && send_ok)
2722 return;
2723
2724 int64_t time_until_timout_ = stop_time - now;
2725 if (time_until_timout_ > 0)
Peter Boström5811a392015-12-10 13:02:50 +01002726 check_stats_event_.Wait(time_until_timout_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002727 now = clock->TimeInMilliseconds();
2728 }
2729
2730 ADD_FAILURE() << "Timed out waiting for filled stats.";
2731 for (std::map<std::string, bool>::const_iterator it =
2732 receive_stats_filled_.begin();
2733 it != receive_stats_filled_.end();
2734 ++it) {
2735 if (!it->second) {
2736 ADD_FAILURE() << "Missing receive stats: " << it->first;
2737 }
2738 }
2739
2740 for (std::map<std::string, bool>::const_iterator it =
2741 send_stats_filled_.begin();
2742 it != send_stats_filled_.end();
2743 ++it) {
2744 if (!it->second) {
2745 ADD_FAILURE() << "Missing send stats: " << it->first;
2746 }
2747 }
2748 }
2749
Peter Boströmc6e16e32016-02-05 14:15:53 +01002750 test::DelayedEncoder encoder_;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002751 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002752 std::map<std::string, bool> receive_stats_filled_;
2753
2754 VideoSendStream* send_stream_;
2755 std::map<std::string, bool> send_stats_filled_;
2756
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002757 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002758 std::set<uint32_t> expected_send_ssrcs_;
2759 std::string expected_cname_;
2760
Peter Boström5811a392015-12-10 13:02:50 +01002761 rtc::Event check_stats_event_;
stefanf116bd02015-10-27 08:29:42 -07002762 } test;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002763
stefane74eef12016-01-08 06:47:13 -08002764 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002765}
2766
2767TEST_F(EndToEndTest, ReceiverReferenceTimeReportEnabled) {
2768 TestXrReceiverReferenceTimeReport(true);
2769}
2770
2771TEST_F(EndToEndTest, ReceiverReferenceTimeReportDisabled) {
2772 TestXrReceiverReferenceTimeReport(false);
2773}
2774
2775TEST_F(EndToEndTest, TestReceivedRtpPacketStats) {
2776 static const size_t kNumRtpPacketsToSend = 5;
2777 class ReceivedRtpStatsObserver : public test::EndToEndTest {
2778 public:
2779 ReceivedRtpStatsObserver()
2780 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002781 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002782 sent_rtp_(0) {}
2783
2784 private:
stefanff483612015-12-21 03:14:00 -08002785 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002786 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002787 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002788 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002789 }
2790
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002791 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002792 if (sent_rtp_ >= kNumRtpPacketsToSend) {
2793 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002794 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
Peter Boström5811a392015-12-10 13:02:50 +01002795 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002796 }
2797 return DROP_PACKET;
2798 }
2799 ++sent_rtp_;
2800 return SEND_PACKET;
2801 }
2802
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002803 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002804 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002805 << "Timed out while verifying number of received RTP packets.";
2806 }
2807
2808 VideoReceiveStream* receive_stream_;
2809 uint32_t sent_rtp_;
2810 } test;
2811
stefane74eef12016-01-08 06:47:13 -08002812 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002813}
2814
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002815TEST_F(EndToEndTest, SendsSetSsrc) { TestSendsSetSsrcs(1, false); }
2816
2817TEST_F(EndToEndTest, SendsSetSimulcastSsrcs) {
2818 TestSendsSetSsrcs(kNumSsrcs, false);
2819}
2820
2821TEST_F(EndToEndTest, CanSwitchToUseAllSsrcs) {
2822 TestSendsSetSsrcs(kNumSsrcs, true);
2823}
2824
mflodman@webrtc.orgf9460682014-07-24 16:41:25 +00002825TEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002826 class ObserveRedundantPayloads: public test::EndToEndTest {
2827 public:
2828 ObserveRedundantPayloads()
2829 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00002830 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002831 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
2832 }
2833 }
2834
2835 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002836 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002837 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002838 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002839
2840 if (!registered_rtx_ssrc_[header.ssrc])
2841 return SEND_PACKET;
2842
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002843 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002844 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002845 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002846
2847 if (!packet_is_redundant_payload)
2848 return SEND_PACKET;
2849
2850 if (!observed_redundant_retransmission_[header.ssrc]) {
2851 observed_redundant_retransmission_[header.ssrc] = true;
2852 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002853 observation_complete_.Set();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002854 }
2855
2856 return SEND_PACKET;
2857 }
2858
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002859 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002860
stefanff483612015-12-21 03:14:00 -08002861 void ModifyVideoConfigs(
2862 VideoSendStream::Config* send_config,
2863 std::vector<VideoReceiveStream::Config>* receive_configs,
2864 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002865 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002866 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2867 encoder_config->streams[i].min_bitrate_bps = 10000;
2868 encoder_config->streams[i].target_bitrate_bps = 15000;
2869 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002870 }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002871
2872 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002873
2874 for (size_t i = 0; i < kNumSsrcs; ++i)
2875 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00002876
2877 // Significantly higher than max bitrates for all video streams -> forcing
2878 // padding to trigger redundant padding on all RTX SSRCs.
2879 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002880 }
2881
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002882 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002883 EXPECT_TRUE(Wait())
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002884 << "Timed out while waiting for redundant payloads on all SSRCs.";
2885 }
2886
2887 private:
2888 size_t ssrcs_to_observe_;
2889 std::map<uint32_t, bool> observed_redundant_retransmission_;
2890 std::map<uint32_t, bool> registered_rtx_ssrc_;
2891 } test;
2892
stefane74eef12016-01-08 06:47:13 -08002893 RunBaseTest(&test);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002894}
2895
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002896void EndToEndTest::TestRtpStatePreservation(bool use_rtx) {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002897 class RtpSequenceObserver : public test::RtpRtcpObserver {
2898 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00002899 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002900 : test::RtpRtcpObserver(kDefaultTimeoutMs),
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002901 ssrcs_to_observe_(kNumSsrcs) {
2902 for (size_t i = 0; i < kNumSsrcs; ++i) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002903 configured_ssrcs_[kVideoSendSsrcs[i]] = true;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002904 if (use_rtx)
2905 configured_ssrcs_[kSendRtxSsrcs[i]] = true;
2906 }
2907 }
2908
2909 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
Peter Boströmf2f82832015-05-01 13:00:41 +02002910 rtc::CritScope lock(&crit_);
danilchap34877ee2016-02-01 08:25:04 -08002911 ssrc_observed_.clear();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002912 ssrcs_to_observe_ = num_expected_ssrcs;
2913 }
2914
2915 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002916 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002917 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002918 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002919 const uint32_t ssrc = header.ssrc;
danilchap5c35cf92016-02-03 14:14:49 -08002920 const int64_t sequence_number =
2921 seq_numbers_unwrapper_.Unwrap(header.sequenceNumber);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002922 const uint32_t timestamp = header.timestamp;
danilchap34877ee2016-02-01 08:25:04 -08002923 const bool only_padding =
2924 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002925
2926 EXPECT_TRUE(configured_ssrcs_[ssrc])
2927 << "Received SSRC that wasn't configured: " << ssrc;
2928
danilchap5c35cf92016-02-03 14:14:49 -08002929 static const int64_t kMaxSequenceNumberGap = 100;
2930 std::list<int64_t>* seq_numbers = &last_observed_seq_numbers_[ssrc];
2931 if (seq_numbers->empty()) {
2932 seq_numbers->push_back(sequence_number);
2933 } else {
2934 // We shouldn't get replays of previous sequence numbers.
2935 for (int64_t observed : *seq_numbers) {
2936 EXPECT_NE(observed, sequence_number)
2937 << "Received sequence number " << sequence_number
2938 << " for SSRC " << ssrc << " 2nd time.";
2939 }
2940 // Verify sequence numbers are reasonably close.
2941 int64_t latest_observed = seq_numbers->back();
2942 int64_t sequence_number_gap = sequence_number - latest_observed;
2943 EXPECT_LE(std::abs(sequence_number_gap), kMaxSequenceNumberGap)
2944 << "Gap in sequence numbers (" << latest_observed << " -> "
2945 << sequence_number << ") too large for SSRC: " << ssrc << ".";
2946 seq_numbers->push_back(sequence_number);
2947 if (seq_numbers->size() >= kMaxSequenceNumberGap) {
2948 seq_numbers->pop_front();
2949 }
2950 }
2951
2952 static const int32_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
2953 auto timestamp_it = last_observed_timestamp_.find(ssrc);
2954 if (timestamp_it == last_observed_timestamp_.end()) {
danilchap34877ee2016-02-01 08:25:04 -08002955 last_observed_timestamp_[ssrc] = timestamp;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002956 } else {
danilchap5c35cf92016-02-03 14:14:49 -08002957 // Verify timestamps are reasonably close.
2958 uint32_t latest_observed = timestamp_it->second;
Honghai Zhang82d78622016-05-06 11:29:15 -07002959 // Wraparound handling is unnecessary here as long as an int variable
2960 // is used to store the result.
2961 int32_t timestamp_gap = timestamp - latest_observed;
danilchap5c35cf92016-02-03 14:14:49 -08002962 EXPECT_LE(std::abs(timestamp_gap), kMaxTimestampGap)
2963 << "Gap in timestamps (" << latest_observed << " -> "
2964 << timestamp << ") too large for SSRC: " << ssrc << ".";
2965 timestamp_it->second = timestamp;
danilchapf4b9c772016-01-28 06:14:24 -08002966 }
danilchap34877ee2016-02-01 08:25:04 -08002967
2968 rtc::CritScope lock(&crit_);
2969 // Wait for media packets on all ssrcs.
2970 if (!ssrc_observed_[ssrc] && !only_padding) {
2971 ssrc_observed_[ssrc] = true;
2972 if (--ssrcs_to_observe_ == 0)
2973 observation_complete_.Set();
2974 }
2975
danilchapf4b9c772016-01-28 06:14:24 -08002976 return SEND_PACKET;
2977 }
2978
danilchap5c35cf92016-02-03 14:14:49 -08002979 SequenceNumberUnwrapper seq_numbers_unwrapper_;
2980 std::map<uint32_t, std::list<int64_t>> last_observed_seq_numbers_;
danilchap34877ee2016-02-01 08:25:04 -08002981 std::map<uint32_t, uint32_t> last_observed_timestamp_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002982 std::map<uint32_t, bool> configured_ssrcs_;
2983
Peter Boströmf2f82832015-05-01 13:00:41 +02002984 rtc::CriticalSection crit_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002985 size_t ssrcs_to_observe_ GUARDED_BY(crit_);
danilchap34877ee2016-02-01 08:25:04 -08002986 std::map<uint32_t, bool> ssrc_observed_ GUARDED_BY(crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002987 } observer(use_rtx);
2988
solenberg4fbae2b2015-08-28 04:07:10 -07002989 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002990
stefanf116bd02015-10-27 08:29:42 -07002991 test::PacketTransport send_transport(sender_call_.get(), &observer,
2992 test::PacketTransport::kSender,
2993 FakeNetworkPipe::Config());
2994 test::PacketTransport receive_transport(nullptr, &observer,
2995 test::PacketTransport::kReceiver,
2996 FakeNetworkPipe::Config());
2997 send_transport.SetReceiver(receiver_call_->Receiver());
2998 receive_transport.SetReceiver(sender_call_->Receiver());
2999
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003000 CreateSendConfig(kNumSsrcs, 0, &send_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003001
3002 if (use_rtx) {
3003 for (size_t i = 0; i < kNumSsrcs; ++i) {
stefanff483612015-12-21 03:14:00 -08003004 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003005 }
stefanff483612015-12-21 03:14:00 -08003006 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003007 }
3008
3009 // Lower bitrates so that all streams send initially.
stefanff483612015-12-21 03:14:00 -08003010 for (size_t i = 0; i < video_encoder_config_.streams.size(); ++i) {
3011 video_encoder_config_.streams[i].min_bitrate_bps = 10000;
3012 video_encoder_config_.streams[i].target_bitrate_bps = 15000;
3013 video_encoder_config_.streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003014 }
3015
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003016 // Use the same total bitrates when sending a single stream to avoid lowering
3017 // the bitrate estimate and requiring a subsequent rampup.
stefanff483612015-12-21 03:14:00 -08003018 VideoEncoderConfig one_stream = video_encoder_config_;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003019 one_stream.streams.resize(1);
stefanff483612015-12-21 03:14:00 -08003020 for (size_t i = 1; i < video_encoder_config_.streams.size(); ++i) {
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003021 one_stream.streams.front().min_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003022 video_encoder_config_.streams[i].min_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003023 one_stream.streams.front().target_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003024 video_encoder_config_.streams[i].target_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003025 one_stream.streams.front().max_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003026 video_encoder_config_.streams[i].max_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003027 }
3028
stefanf116bd02015-10-27 08:29:42 -07003029 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003030
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003031 CreateVideoStreams();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003032 CreateFrameGeneratorCapturer();
3033
3034 Start();
Peter Boström5811a392015-12-10 13:02:50 +01003035 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003036 << "Timed out waiting for all SSRCs to send packets.";
3037
3038 // Test stream resetting more than once to make sure that the state doesn't
3039 // get set once (this could be due to using std::map::insert for instance).
3040 for (size_t i = 0; i < 3; ++i) {
3041 frame_generator_capturer_->Stop();
stefanff483612015-12-21 03:14:00 -08003042 sender_call_->DestroyVideoSendStream(video_send_stream_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003043
3044 // Re-create VideoSendStream with only one stream.
stefanff483612015-12-21 03:14:00 -08003045 video_send_stream_ =
3046 sender_call_->CreateVideoSendStream(video_send_config_, one_stream);
3047 video_send_stream_->Start();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003048 CreateFrameGeneratorCapturer();
3049 frame_generator_capturer_->Start();
3050
3051 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003052 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003053
3054 // Reconfigure back to use all streams.
stefanff483612015-12-21 03:14:00 -08003055 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003056 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003057 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003058 << "Timed out waiting for all SSRCs to send packets.";
3059
3060 // Reconfigure down to one stream.
stefanff483612015-12-21 03:14:00 -08003061 video_send_stream_->ReconfigureVideoEncoder(one_stream);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003062 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003063 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003064
3065 // Reconfigure back to use all streams.
stefanff483612015-12-21 03:14:00 -08003066 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003067 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003068 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003069 << "Timed out waiting for all SSRCs to send packets.";
3070 }
3071
stefanf116bd02015-10-27 08:29:42 -07003072 send_transport.StopSending();
3073 receive_transport.StopSending();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003074
3075 Stop();
3076 DestroyStreams();
3077}
3078
Peter Boströmfc968a22016-02-19 16:14:37 +01003079TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpState) {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003080 TestRtpStatePreservation(false);
3081}
3082
ossu799467d2016-05-31 05:17:32 -07003083#if defined(WEBRTC_MAC)
3084#define MAYBE_RestartingSendStreamPreservesRtpStatesWithRtx \
3085 DISABLED_RestartingSendStreamPreservesRtpStatesWithRtx
3086#else
3087#define MAYBE_RestartingSendStreamPreservesRtpStatesWithRtx \
3088 RestartingSendStreamPreservesRtpStatesWithRtx
3089#endif
3090TEST_F(EndToEndTest, MAYBE_RestartingSendStreamPreservesRtpStatesWithRtx) {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003091 TestRtpStatePreservation(true);
3092}
3093
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003094TEST_F(EndToEndTest, RespectsNetworkState) {
3095 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
3096 // down blocks until no more packets will be sent.
3097
3098 // Pacer will send from its packet list and then send required padding before
3099 // checking paused_ again. This should be enough for one round of pacing,
3100 // otherwise increase.
3101 static const int kNumAcceptedDowntimeRtp = 5;
3102 // A single RTCP may be in the pipeline.
3103 static const int kNumAcceptedDowntimeRtcp = 1;
3104 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
3105 public:
3106 NetworkStateTest()
3107 : EndToEndTest(kDefaultTimeoutMs),
3108 FakeEncoder(Clock::GetRealTimeClock()),
Peter Boström5811a392015-12-10 13:02:50 +01003109 encoded_frames_(false, false),
3110 packet_event_(false, false),
sprang867fb522015-08-03 04:38:41 -07003111 sender_call_(nullptr),
3112 receiver_call_(nullptr),
Jelena Marusiccd670222015-07-16 09:30:09 +02003113 sender_state_(kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003114 sender_rtp_(0),
3115 sender_rtcp_(0),
3116 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003117 down_frames_(0) {}
3118
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003119 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003120 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003121 ++sender_rtp_;
Peter Boström5811a392015-12-10 13:02:50 +01003122 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003123 return SEND_PACKET;
3124 }
3125
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003126 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003127 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003128 ++sender_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003129 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003130 return SEND_PACKET;
3131 }
3132
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003133 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003134 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
3135 return SEND_PACKET;
3136 }
3137
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003138 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003139 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003140 ++receiver_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003141 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003142 return SEND_PACKET;
3143 }
3144
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003145 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003146 sender_call_ = sender_call;
3147 receiver_call_ = receiver_call;
3148 }
3149
stefanff483612015-12-21 03:14:00 -08003150 void ModifyVideoConfigs(
3151 VideoSendStream::Config* send_config,
3152 std::vector<VideoReceiveStream::Config>* receive_configs,
3153 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003154 send_config->encoder_settings.encoder = this;
3155 }
3156
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003157 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003158 EXPECT_TRUE(encoded_frames_.Wait(kDefaultTimeoutMs))
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003159 << "No frames received by the encoder.";
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003160 // Wait for packets from both sender/receiver.
3161 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003162
skvlad7a43d252016-03-22 15:32:27 -07003163 // Sender-side network down for audio; there should be no effect on video
3164 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3165 WaitForPacketsOrSilence(false, false);
3166
3167 // Receiver-side network down for audio; no change expected
3168 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3169 WaitForPacketsOrSilence(false, false);
3170
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003171 // Sender-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003172 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003173 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003174 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003175 // After network goes down we shouldn't be encoding more frames.
Jelena Marusiccd670222015-07-16 09:30:09 +02003176 sender_state_ = kNetworkDown;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003177 }
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003178 // Wait for receiver-packets and no sender packets.
3179 WaitForPacketsOrSilence(true, false);
3180
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003181 // Receiver-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003182 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
3183 WaitForPacketsOrSilence(true, true);
3184
3185 // Network up for audio for both sides; video is still not expected to
3186 // start
3187 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
3188 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003189 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003190
3191 // Network back up again for both.
3192 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003193 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003194 // It's OK to encode frames again, as we're about to bring up the
3195 // network.
Jelena Marusiccd670222015-07-16 09:30:09 +02003196 sender_state_ = kNetworkUp;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003197 }
skvlad7a43d252016-03-22 15:32:27 -07003198 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
3199 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003200 WaitForPacketsOrSilence(false, false);
skvlad7a43d252016-03-22 15:32:27 -07003201
3202 // TODO(skvlad): add tests to verify that the audio streams are stopped
3203 // when the network goes down for audio once the workaround in
3204 // paced_sender.cc is removed.
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003205 }
3206
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07003207 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003208 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07003209 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003210 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003211 rtc::CritScope lock(&test_crit_);
Jelena Marusiccd670222015-07-16 09:30:09 +02003212 if (sender_state_ == kNetworkDown) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003213 ++down_frames_;
3214 EXPECT_LE(down_frames_, 1)
3215 << "Encoding more than one frame while network is down.";
3216 if (down_frames_ > 1)
Peter Boström5811a392015-12-10 13:02:50 +01003217 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003218 } else {
Peter Boström5811a392015-12-10 13:02:50 +01003219 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003220 }
3221 }
3222 return test::FakeEncoder::Encode(
3223 input_image, codec_specific_info, frame_types);
3224 }
3225
3226 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003227 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
3228 int64_t initial_time_ms = clock_->TimeInMilliseconds();
3229 int initial_sender_rtp;
3230 int initial_sender_rtcp;
3231 int initial_receiver_rtcp;
3232 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003233 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003234 initial_sender_rtp = sender_rtp_;
3235 initial_sender_rtcp = sender_rtcp_;
3236 initial_receiver_rtcp = receiver_rtcp_;
3237 }
3238 bool sender_done = false;
3239 bool receiver_done = false;
mflodmand1590b22015-12-09 07:07:59 -08003240 while (!sender_done || !receiver_done) {
Peter Boström5811a392015-12-10 13:02:50 +01003241 packet_event_.Wait(kSilenceTimeoutMs);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003242 int64_t time_now_ms = clock_->TimeInMilliseconds();
Peter Boströmf2f82832015-05-01 13:00:41 +02003243 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003244 if (sender_down) {
3245 ASSERT_LE(sender_rtp_ - initial_sender_rtp, kNumAcceptedDowntimeRtp)
3246 << "RTP sent during sender-side downtime.";
3247 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
3248 kNumAcceptedDowntimeRtcp)
3249 << "RTCP sent during sender-side downtime.";
3250 if (time_now_ms - initial_time_ms >=
3251 static_cast<int64_t>(kSilenceTimeoutMs)) {
3252 sender_done = true;
3253 }
3254 } else {
skvlad7a43d252016-03-22 15:32:27 -07003255 if (sender_rtp_ > initial_sender_rtp + kNumAcceptedDowntimeRtp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003256 sender_done = true;
3257 }
3258 if (receiver_down) {
3259 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
3260 kNumAcceptedDowntimeRtcp)
3261 << "RTCP sent during receiver-side downtime.";
3262 if (time_now_ms - initial_time_ms >=
3263 static_cast<int64_t>(kSilenceTimeoutMs)) {
3264 receiver_done = true;
3265 }
3266 } else {
skvlad7a43d252016-03-22 15:32:27 -07003267 if (receiver_rtcp_ > initial_receiver_rtcp + kNumAcceptedDowntimeRtcp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003268 receiver_done = true;
3269 }
3270 }
3271 }
3272
Peter Boströmf2f82832015-05-01 13:00:41 +02003273 rtc::CriticalSection test_crit_;
Peter Boström5811a392015-12-10 13:02:50 +01003274 rtc::Event encoded_frames_;
3275 rtc::Event packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003276 Call* sender_call_;
3277 Call* receiver_call_;
Jelena Marusiccd670222015-07-16 09:30:09 +02003278 NetworkState sender_state_ GUARDED_BY(test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003279 int sender_rtp_ GUARDED_BY(test_crit_);
3280 int sender_rtcp_ GUARDED_BY(test_crit_);
3281 int receiver_rtcp_ GUARDED_BY(test_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003282 int down_frames_ GUARDED_BY(test_crit_);
3283 } test;
3284
stefane74eef12016-01-08 06:47:13 -08003285 RunBaseTest(&test);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003286}
3287
danilchapa6a70072016-06-01 11:20:43 -07003288TEST_F(EndToEndTest, CallReportsRttForSender) {
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003289 static const int kSendDelayMs = 30;
3290 static const int kReceiveDelayMs = 70;
3291
solenberg4fbae2b2015-08-28 04:07:10 -07003292 CreateCalls(Call::Config(), Call::Config());
3293
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003294 FakeNetworkPipe::Config config;
3295 config.queue_delay_ms = kSendDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003296 test::DirectTransport sender_transport(config, sender_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003297 config.queue_delay_ms = kReceiveDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003298 test::DirectTransport receiver_transport(config, receiver_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003299 sender_transport.SetReceiver(receiver_call_->Receiver());
3300 receiver_transport.SetReceiver(sender_call_->Receiver());
3301
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003302 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07003303 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003304
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003305 CreateVideoStreams();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003306 CreateFrameGeneratorCapturer();
3307 Start();
3308
3309 int64_t start_time_ms = clock_->TimeInMilliseconds();
3310 while (true) {
3311 Call::Stats stats = sender_call_->GetStats();
3312 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
3313 clock_->TimeInMilliseconds())
3314 << "No RTT stats before timeout!";
3315 if (stats.rtt_ms != -1) {
3316 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs);
3317 break;
3318 }
3319 SleepMs(10);
3320 }
3321
3322 Stop();
3323 DestroyStreams();
3324}
3325
skvlad7a43d252016-03-22 15:32:27 -07003326void EndToEndTest::VerifyNewVideoSendStreamsRespectNetworkState(
3327 MediaType network_to_bring_down,
3328 VideoEncoder* encoder,
3329 Transport* transport) {
solenberg4fbae2b2015-08-28 04:07:10 -07003330 CreateSenderCall(Call::Config());
skvlad7a43d252016-03-22 15:32:27 -07003331 sender_call_->SignalChannelNetworkState(network_to_bring_down, kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003332
skvlad7a43d252016-03-22 15:32:27 -07003333 CreateSendConfig(1, 0, transport);
3334 video_send_config_.encoder_settings.encoder = encoder;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003335 CreateVideoStreams();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003336 CreateFrameGeneratorCapturer();
3337
3338 Start();
3339 SleepMs(kSilenceTimeoutMs);
3340 Stop();
3341
3342 DestroyStreams();
3343}
3344
skvlad7a43d252016-03-22 15:32:27 -07003345void EndToEndTest::VerifyNewVideoReceiveStreamsRespectNetworkState(
3346 MediaType network_to_bring_down,
3347 Transport* transport) {
solenberg4fbae2b2015-08-28 04:07:10 -07003348 CreateCalls(Call::Config(), Call::Config());
skvlad7a43d252016-03-22 15:32:27 -07003349 receiver_call_->SignalChannelNetworkState(network_to_bring_down,
3350 kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003351
stefanf116bd02015-10-27 08:29:42 -07003352 test::DirectTransport sender_transport(sender_call_.get());
solenberg4fbae2b2015-08-28 04:07:10 -07003353 sender_transport.SetReceiver(receiver_call_->Receiver());
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003354 CreateSendConfig(1, 0, &sender_transport);
skvlad7a43d252016-03-22 15:32:27 -07003355 CreateMatchingReceiveConfigs(transport);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003356 CreateVideoStreams();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003357 CreateFrameGeneratorCapturer();
3358
3359 Start();
3360 SleepMs(kSilenceTimeoutMs);
3361 Stop();
3362
3363 sender_transport.StopSending();
3364
3365 DestroyStreams();
3366}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00003367
skvlad7a43d252016-03-22 15:32:27 -07003368TEST_F(EndToEndTest, NewVideoSendStreamsRespectVideoNetworkDown) {
3369 class UnusedEncoder : public test::FakeEncoder {
3370 public:
3371 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
perkjfea93092016-05-14 00:58:48 -07003372
3373 int32_t InitEncode(const VideoCodec* config,
3374 int32_t number_of_cores,
3375 size_t max_payload_size) override {
3376 EXPECT_GT(config->startBitrate, 0u);
3377 return 0;
3378 }
skvlad7a43d252016-03-22 15:32:27 -07003379 int32_t Encode(const VideoFrame& input_image,
3380 const CodecSpecificInfo* codec_specific_info,
3381 const std::vector<FrameType>* frame_types) override {
3382 ADD_FAILURE() << "Unexpected frame encode.";
3383 return test::FakeEncoder::Encode(input_image, codec_specific_info,
3384 frame_types);
3385 }
3386 };
3387
3388 UnusedEncoder unused_encoder;
3389 UnusedTransport unused_transport;
3390 VerifyNewVideoSendStreamsRespectNetworkState(
3391 MediaType::VIDEO, &unused_encoder, &unused_transport);
3392}
3393
3394TEST_F(EndToEndTest, NewVideoSendStreamsIgnoreAudioNetworkDown) {
3395 class RequiredEncoder : public test::FakeEncoder {
3396 public:
3397 RequiredEncoder()
3398 : FakeEncoder(Clock::GetRealTimeClock()), encoded_frame_(false) {}
3399 ~RequiredEncoder() {
3400 if (!encoded_frame_) {
3401 ADD_FAILURE() << "Didn't encode an expected frame";
3402 }
3403 }
3404 int32_t Encode(const VideoFrame& input_image,
3405 const CodecSpecificInfo* codec_specific_info,
3406 const std::vector<FrameType>* frame_types) override {
3407 encoded_frame_ = true;
3408 return test::FakeEncoder::Encode(input_image, codec_specific_info,
3409 frame_types);
3410 }
3411
3412 private:
3413 bool encoded_frame_;
3414 };
3415
3416 RequiredTransport required_transport(true /*rtp*/, false /*rtcp*/);
3417 RequiredEncoder required_encoder;
3418 VerifyNewVideoSendStreamsRespectNetworkState(
3419 MediaType::AUDIO, &required_encoder, &required_transport);
3420}
3421
3422TEST_F(EndToEndTest, NewVideoReceiveStreamsRespectVideoNetworkDown) {
3423 UnusedTransport transport;
3424 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::VIDEO, &transport);
3425}
3426
3427TEST_F(EndToEndTest, NewVideoReceiveStreamsIgnoreAudioNetworkDown) {
3428 RequiredTransport transport(false /*rtp*/, true /*rtcp*/);
3429 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::AUDIO, &transport);
3430}
3431
Peter Boströmd7da1202015-06-05 14:09:38 +02003432void VerifyEmptyNackConfig(const NackConfig& config) {
3433 EXPECT_EQ(0, config.rtp_history_ms)
3434 << "Enabling NACK requires rtcp-fb: nack negotiation.";
3435}
3436
3437void VerifyEmptyFecConfig(const FecConfig& config) {
3438 EXPECT_EQ(-1, config.ulpfec_payload_type)
3439 << "Enabling FEC requires rtpmap: ulpfec negotiation.";
3440 EXPECT_EQ(-1, config.red_payload_type)
3441 << "Enabling FEC requires rtpmap: red negotiation.";
3442 EXPECT_EQ(-1, config.red_rtx_payload_type)
3443 << "Enabling RTX in FEC requires rtpmap: rtx negotiation.";
3444}
3445
3446TEST_F(EndToEndTest, VerifyDefaultSendConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003447 VideoSendStream::Config default_send_config(nullptr);
Peter Boströmd7da1202015-06-05 14:09:38 +02003448 EXPECT_EQ(0, default_send_config.rtp.nack.rtp_history_ms)
3449 << "Enabling NACK require rtcp-fb: nack negotiation.";
3450 EXPECT_TRUE(default_send_config.rtp.rtx.ssrcs.empty())
3451 << "Enabling RTX requires rtpmap: rtx negotiation.";
3452 EXPECT_TRUE(default_send_config.rtp.extensions.empty())
3453 << "Enabling RTP extensions require negotiation.";
3454
3455 VerifyEmptyNackConfig(default_send_config.rtp.nack);
3456 VerifyEmptyFecConfig(default_send_config.rtp.fec);
3457}
3458
3459TEST_F(EndToEndTest, VerifyDefaultReceiveConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003460 VideoReceiveStream::Config default_receive_config(nullptr);
pbosda903ea2015-10-02 02:36:56 -07003461 EXPECT_EQ(RtcpMode::kCompound, default_receive_config.rtp.rtcp_mode)
Peter Boströmd7da1202015-06-05 14:09:38 +02003462 << "Reduced-size RTCP require rtcp-rsize to be negotiated.";
3463 EXPECT_FALSE(default_receive_config.rtp.remb)
3464 << "REMB require rtcp-fb: goog-remb to be negotiated.";
3465 EXPECT_FALSE(
3466 default_receive_config.rtp.rtcp_xr.receiver_reference_time_report)
3467 << "RTCP XR settings require rtcp-xr to be negotiated.";
3468 EXPECT_TRUE(default_receive_config.rtp.rtx.empty())
3469 << "Enabling RTX requires rtpmap: rtx negotiation.";
3470 EXPECT_TRUE(default_receive_config.rtp.extensions.empty())
3471 << "Enabling RTP extensions require negotiation.";
3472
3473 VerifyEmptyNackConfig(default_receive_config.rtp.nack);
3474 VerifyEmptyFecConfig(default_receive_config.rtp.fec);
3475}
3476
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003477TEST_F(EndToEndTest, TransportSeqNumOnAudioAndVideo) {
3478 static const int kExtensionId = 8;
3479 class TransportSequenceNumberTest : public test::EndToEndTest {
3480 public:
3481 TransportSequenceNumberTest()
3482 : EndToEndTest(kDefaultTimeoutMs),
3483 video_observed_(false),
3484 audio_observed_(false) {
3485 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
3486 kExtensionId);
3487 }
3488
3489 size_t GetNumVideoStreams() const override { return 1; }
3490 size_t GetNumAudioStreams() const override { return 1; }
3491
3492 void ModifyVideoConfigs(
3493 VideoSendStream::Config* send_config,
3494 std::vector<VideoReceiveStream::Config>* receive_configs,
3495 VideoEncoderConfig* encoder_config) override {
3496 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07003497 send_config->rtp.extensions.push_back(RtpExtension(
3498 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003499 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3500 }
3501
3502 void ModifyAudioConfigs(
3503 AudioSendStream::Config* send_config,
3504 std::vector<AudioReceiveStream::Config>* receive_configs) override {
3505 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07003506 send_config->rtp.extensions.push_back(RtpExtension(
3507 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003508 (*receive_configs)[0].rtp.extensions.clear();
3509 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3510 }
3511
3512 Action OnSendRtp(const uint8_t* packet, size_t length) override {
3513 RTPHeader header;
3514 EXPECT_TRUE(parser_->Parse(packet, length, &header));
3515 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
3516 // Unwrap packet id and verify uniqueness.
3517 int64_t packet_id =
3518 unwrapper_.Unwrap(header.extension.transportSequenceNumber);
3519 EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
3520
3521 if (header.ssrc == kVideoSendSsrcs[0])
3522 video_observed_ = true;
3523 if (header.ssrc == kAudioSendSsrc)
3524 audio_observed_ = true;
3525 if (audio_observed_ && video_observed_ &&
3526 received_packet_ids_.size() == 50) {
3527 size_t packet_id_range =
3528 *received_packet_ids_.rbegin() - *received_packet_ids_.begin() + 1;
3529 EXPECT_EQ(received_packet_ids_.size(), packet_id_range);
3530 observation_complete_.Set();
3531 }
3532 return SEND_PACKET;
3533 }
3534
3535 void PerformTest() override {
3536 EXPECT_TRUE(Wait()) << "Timed out while waiting for audio and video "
3537 "packets with transport sequence number.";
3538 }
3539
3540 private:
3541 bool video_observed_;
3542 bool audio_observed_;
3543 SequenceNumberUnwrapper unwrapper_;
3544 std::set<int64_t> received_packet_ids_;
3545 } test;
3546
stefane74eef12016-01-08 06:47:13 -08003547 RunBaseTest(&test);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003548}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003549} // namespace webrtc