blob: 8b2abc8e297d614fa32bb7b01433de1f37805d8d [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"
34#include "webrtc/system_wrappers/include/sleep.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000035#include "webrtc/test/call_test.h"
36#include "webrtc/test/direct_transport.h"
37#include "webrtc/test/encoder_settings.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000038#include "webrtc/test/fake_decoder.h"
39#include "webrtc/test/fake_encoder.h"
40#include "webrtc/test/frame_generator.h"
41#include "webrtc/test/frame_generator_capturer.h"
Åsa Persson352b2d72015-04-15 18:00:40 +020042#include "webrtc/test/histogram.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000043#include "webrtc/test/null_transport.h"
asapersson@webrtc.org37c05592015-01-28 13:58:27 +000044#include "webrtc/test/rtcp_packet_parser.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000045#include "webrtc/test/rtp_rtcp_observer.h"
46#include "webrtc/test/testsupport/fileutils.h"
47#include "webrtc/test/testsupport/perf_test.h"
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +000048#include "webrtc/video_encoder.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000049
50namespace webrtc {
51
Peter Boström5811a392015-12-10 13:02:50 +010052static const int kSilenceTimeoutMs = 2000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000053
54class EndToEndTest : public test::CallTest {
55 public:
56 EndToEndTest() {}
57
58 virtual ~EndToEndTest() {
stefanff483612015-12-21 03:14:00 -080059 EXPECT_EQ(nullptr, video_send_stream_);
60 EXPECT_TRUE(video_receive_streams_.empty());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000061 }
62
63 protected:
pbos2d566682015-09-28 09:59:31 -070064 class UnusedTransport : public Transport {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000065 private:
stefan1d8a5062015-10-02 03:39:33 -070066 bool SendRtp(const uint8_t* packet,
67 size_t length,
68 const PacketOptions& options) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000069 ADD_FAILURE() << "Unexpected RTP sent.";
70 return false;
71 }
72
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000073 bool SendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000074 ADD_FAILURE() << "Unexpected RTCP sent.";
75 return false;
76 }
77 };
78
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
336TEST_F(EndToEndTest, SendsAndReceivesVP9) {
337 CodecObserver test(500, kVideoRotation_0, "VP9",
338 VideoEncoder::Create(VideoEncoder::kVp9),
339 VP9Decoder::Create());
340 RunBaseTest(&test);
341}
342
343TEST_F(EndToEndTest, SendsAndReceivesVP9VideoRotation90) {
344 CodecObserver test(5, kVideoRotation_90, "VP9",
345 VideoEncoder::Create(VideoEncoder::kVp9),
346 VP9Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800347 RunBaseTest(&test);
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000348}
349
hbosbab934b2016-01-27 01:36:03 -0800350#if defined(WEBRTC_END_TO_END_H264_TESTS)
351
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000352TEST_F(EndToEndTest, SendsAndReceivesH264) {
Perba7dc722016-04-19 15:01:23 +0200353 CodecObserver test(500, kVideoRotation_0, "H264",
354 VideoEncoder::Create(VideoEncoder::kH264),
355 H264Decoder::Create());
356 RunBaseTest(&test);
357}
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000358
Perba7dc722016-04-19 15:01:23 +0200359TEST_F(EndToEndTest, SendsAndReceivesH264VideoRotation90) {
360 CodecObserver test(5, kVideoRotation_90, "H264",
361 VideoEncoder::Create(VideoEncoder::kH264),
362 H264Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800363 RunBaseTest(&test);
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000364}
365
hbosbab934b2016-01-27 01:36:03 -0800366#endif // defined(WEBRTC_END_TO_END_H264_TESTS)
367
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000368TEST_F(EndToEndTest, ReceiverUsesLocalSsrc) {
369 class SyncRtcpObserver : public test::EndToEndTest {
370 public:
371 SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {}
372
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000373 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000374 RTCPUtility::RTCPParserV2 parser(packet, length, true);
375 EXPECT_TRUE(parser.IsValid());
376 uint32_t ssrc = 0;
377 ssrc |= static_cast<uint32_t>(packet[4]) << 24;
378 ssrc |= static_cast<uint32_t>(packet[5]) << 16;
379 ssrc |= static_cast<uint32_t>(packet[6]) << 8;
380 ssrc |= static_cast<uint32_t>(packet[7]) << 0;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100381 EXPECT_EQ(kReceiverLocalVideoSsrc, ssrc);
Peter Boström5811a392015-12-10 13:02:50 +0100382 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000383
384 return SEND_PACKET;
385 }
386
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000387 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100388 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000389 << "Timed out while waiting for a receiver RTCP packet to be sent.";
390 }
391 } test;
392
stefane74eef12016-01-08 06:47:13 -0800393 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000394}
395
396TEST_F(EndToEndTest, ReceivesAndRetransmitsNack) {
397 static const int kNumberOfNacksToObserve = 2;
398 static const int kLossBurstSize = 2;
399 static const int kPacketsBetweenLossBursts = 9;
400 class NackObserver : public test::EndToEndTest {
401 public:
402 NackObserver()
403 : EndToEndTest(kLongTimeoutMs),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000404 sent_rtp_packets_(0),
405 packets_left_to_drop_(0),
406 nacks_left_(kNumberOfNacksToObserve) {}
407
408 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000409 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700410 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000411 RTPHeader header;
Peter Boström03671cb2015-12-07 15:22:24 +0100412 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000413
414 // Never drop retransmitted packets.
415 if (dropped_packets_.find(header.sequenceNumber) !=
416 dropped_packets_.end()) {
417 retransmitted_packets_.insert(header.sequenceNumber);
Stefan Holmer586b19b2015-09-18 11:14:31 +0200418 if (nacks_left_ <= 0 &&
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000419 retransmitted_packets_.size() == dropped_packets_.size()) {
Peter Boström5811a392015-12-10 13:02:50 +0100420 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000421 }
422 return SEND_PACKET;
423 }
424
425 ++sent_rtp_packets_;
426
427 // Enough NACKs received, stop dropping packets.
Stefan Holmer586b19b2015-09-18 11:14:31 +0200428 if (nacks_left_ <= 0)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000429 return SEND_PACKET;
430
431 // Check if it's time for a new loss burst.
432 if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
433 packets_left_to_drop_ = kLossBurstSize;
434
Stefan Holmer01b48882015-05-05 10:21:24 +0200435 // Never drop padding packets as those won't be retransmitted.
436 if (packets_left_to_drop_ > 0 && header.paddingLength == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000437 --packets_left_to_drop_;
438 dropped_packets_.insert(header.sequenceNumber);
439 return DROP_PACKET;
440 }
441
442 return SEND_PACKET;
443 }
444
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000445 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700446 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000447 RTCPUtility::RTCPParserV2 parser(packet, length, true);
448 EXPECT_TRUE(parser.IsValid());
449
450 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +0200451 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
452 if (packet_type == RTCPUtility::RTCPPacketTypes::kRtpfbNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000453 --nacks_left_;
454 break;
455 }
456 packet_type = parser.Iterate();
457 }
458 return SEND_PACKET;
459 }
460
stefanff483612015-12-21 03:14:00 -0800461 void ModifyVideoConfigs(
462 VideoSendStream::Config* send_config,
463 std::vector<VideoReceiveStream::Config>* receive_configs,
464 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000465 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000466 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000467 }
468
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000469 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100470 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000471 << "Timed out waiting for packets to be NACKed, retransmitted and "
472 "rendered.";
473 }
474
stefanf116bd02015-10-27 08:29:42 -0700475 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000476 std::set<uint16_t> dropped_packets_;
477 std::set<uint16_t> retransmitted_packets_;
478 uint64_t sent_rtp_packets_;
479 int packets_left_to_drop_;
stefanf116bd02015-10-27 08:29:42 -0700480 int nacks_left_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000481 } test;
482
stefane74eef12016-01-08 06:47:13 -0800483 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000484}
485
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000486TEST_F(EndToEndTest, CanReceiveFec) {
nisse7ade7b32016-03-23 04:48:10 -0700487 class FecRenderObserver : public test::EndToEndTest,
488 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000489 public:
490 FecRenderObserver()
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000491 : EndToEndTest(kDefaultTimeoutMs), state_(kFirstPacket) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000492
493 private:
stefanf116bd02015-10-27 08:29:42 -0700494 Action OnSendRtp(const uint8_t* packet, size_t length) override {
495 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000496 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000497 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000498
Stefan Holmer01b48882015-05-05 10:21:24 +0200499 int encapsulated_payload_type = -1;
500 if (header.payloadType == kRedPayloadType) {
501 encapsulated_payload_type =
502 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100503 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200504 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
505 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100506 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200507 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000508
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000509 if (protected_sequence_numbers_.count(header.sequenceNumber) != 0) {
510 // Retransmitted packet, should not count.
511 protected_sequence_numbers_.erase(header.sequenceNumber);
512 EXPECT_GT(protected_timestamps_.count(header.timestamp), 0u);
513 protected_timestamps_.erase(header.timestamp);
514 return SEND_PACKET;
515 }
516
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000517 switch (state_) {
518 case kFirstPacket:
519 state_ = kDropEveryOtherPacketUntilFec;
520 break;
521 case kDropEveryOtherPacketUntilFec:
522 if (encapsulated_payload_type == kUlpfecPayloadType) {
523 state_ = kDropNextMediaPacket;
524 return SEND_PACKET;
525 }
526 if (header.sequenceNumber % 2 == 0)
527 return DROP_PACKET;
528 break;
529 case kDropNextMediaPacket:
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100530 if (encapsulated_payload_type == kFakeVideoSendPayloadType) {
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000531 protected_sequence_numbers_.insert(header.sequenceNumber);
532 protected_timestamps_.insert(header.timestamp);
533 state_ = kDropEveryOtherPacketUntilFec;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000534 return DROP_PACKET;
535 }
536 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000537 }
538
539 return SEND_PACKET;
540 }
541
nisseeb83a1a2016-03-21 01:27:56 -0700542 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200543 rtc::CritScope lock(&crit_);
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000544 // Rendering frame with timestamp of packet that was dropped -> FEC
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000545 // protection worked.
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000546 if (protected_timestamps_.count(video_frame.timestamp()) != 0)
Peter Boström5811a392015-12-10 13:02:50 +0100547 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000548 }
549
550 enum {
551 kFirstPacket,
552 kDropEveryOtherPacketUntilFec,
553 kDropNextMediaPacket,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000554 } state_;
555
stefanff483612015-12-21 03:14:00 -0800556 void ModifyVideoConfigs(
557 VideoSendStream::Config* send_config,
558 std::vector<VideoReceiveStream::Config>* receive_configs,
559 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000560 // TODO(pbos): Run this test with combined NACK/FEC enabled as well.
561 // int rtp_history_ms = 1000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000562 // (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000563 // send_config->rtp.nack.rtp_history_ms = rtp_history_ms;
564 send_config->rtp.fec.red_payload_type = kRedPayloadType;
565 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
566
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000567 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
568 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
569 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000570 }
571
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000572 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100573 EXPECT_TRUE(Wait())
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000574 << "Timed out waiting for dropped frames frames to be rendered.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000575 }
576
stefanf116bd02015-10-27 08:29:42 -0700577 rtc::CriticalSection crit_;
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000578 std::set<uint32_t> protected_sequence_numbers_ GUARDED_BY(crit_);
579 std::set<uint32_t> protected_timestamps_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000580 } test;
581
stefane74eef12016-01-08 06:47:13 -0800582 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000583}
584
Henrik Kjellanderdb313b62015-04-02 08:45:41 +0200585// Flacky on all platforms. See webrtc:4328.
586TEST_F(EndToEndTest, DISABLED_ReceivedFecPacketsNotNacked) {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000587 class FecNackObserver : public test::EndToEndTest {
588 public:
mflodmand1590b22015-12-09 07:07:59 -0800589 FecNackObserver()
stefanf116bd02015-10-27 08:29:42 -0700590 : EndToEndTest(kDefaultTimeoutMs),
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000591 state_(kFirstPacket),
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000592 fec_sequence_number_(0),
593 has_last_sequence_number_(false),
594 last_sequence_number_(0) {}
595
596 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000597 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800598 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000599 RTPHeader header;
600 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000601
Stefan Holmer01b48882015-05-05 10:21:24 +0200602 int encapsulated_payload_type = -1;
603 if (header.payloadType == kRedPayloadType) {
604 encapsulated_payload_type =
605 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100606 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200607 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
608 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100609 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200610 }
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000611
612 if (has_last_sequence_number_ &&
613 !IsNewerSequenceNumber(header.sequenceNumber,
614 last_sequence_number_)) {
615 // Drop retransmitted packets.
616 return DROP_PACKET;
617 }
618 last_sequence_number_ = header.sequenceNumber;
619 has_last_sequence_number_ = true;
620
621 bool fec_packet = encapsulated_payload_type == kUlpfecPayloadType;
622 switch (state_) {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000623 case kFirstPacket:
624 state_ = kDropEveryOtherPacketUntilFec;
625 break;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000626 case kDropEveryOtherPacketUntilFec:
627 if (fec_packet) {
628 state_ = kDropAllMediaPacketsUntilFec;
629 } else if (header.sequenceNumber % 2 == 0) {
630 return DROP_PACKET;
631 }
632 break;
633 case kDropAllMediaPacketsUntilFec:
634 if (!fec_packet)
635 return DROP_PACKET;
636 fec_sequence_number_ = header.sequenceNumber;
637 state_ = kVerifyFecPacketNotInNackList;
638 break;
639 case kVerifyFecPacketNotInNackList:
640 // Continue to drop packets. Make sure no frame can be decoded.
641 if (fec_packet || header.sequenceNumber % 2 == 0)
642 return DROP_PACKET;
643 break;
644 }
645 return SEND_PACKET;
646 }
647
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000648 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800649 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000650 if (state_ == kVerifyFecPacketNotInNackList) {
651 test::RtcpPacketParser rtcp_parser;
652 rtcp_parser.Parse(packet, length);
653 std::vector<uint16_t> nacks = rtcp_parser.nack_item()->last_nack_list();
654 if (!nacks.empty() &&
655 IsNewerSequenceNumber(nacks.back(), fec_sequence_number_)) {
656 EXPECT_TRUE(std::find(
657 nacks.begin(), nacks.end(), fec_sequence_number_) == nacks.end());
Peter Boström5811a392015-12-10 13:02:50 +0100658 observation_complete_.Set();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000659 }
660 }
661 return SEND_PACKET;
662 }
663
stefane74eef12016-01-08 06:47:13 -0800664 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
665 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
666 // Configure some network delay.
667 const int kNetworkDelayMs = 50;
668 FakeNetworkPipe::Config config;
669 config.queue_delay_ms = kNetworkDelayMs;
670 return new test::PacketTransport(sender_call, this,
671 test::PacketTransport::kSender, config);
672 }
673
Stefan Holmere5904162015-03-26 11:11:06 +0100674 // TODO(holmer): Investigate why we don't send FEC packets when the bitrate
675 // is 10 kbps.
676 Call::Config GetSenderCallConfig() override {
solenberg4fbae2b2015-08-28 04:07:10 -0700677 Call::Config config;
Stefan Holmere5904162015-03-26 11:11:06 +0100678 const int kMinBitrateBps = 30000;
679 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
680 return config;
681 }
682
stefanff483612015-12-21 03:14:00 -0800683 void ModifyVideoConfigs(
684 VideoSendStream::Config* send_config,
685 std::vector<VideoReceiveStream::Config>* receive_configs,
686 VideoEncoderConfig* encoder_config) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000687 // Configure hybrid NACK/FEC.
688 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
689 send_config->rtp.fec.red_payload_type = kRedPayloadType;
690 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
691 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
692 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
693 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
694 }
695
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000696 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100697 EXPECT_TRUE(Wait())
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000698 << "Timed out while waiting for FEC packets to be received.";
699 }
700
701 enum {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000702 kFirstPacket,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000703 kDropEveryOtherPacketUntilFec,
704 kDropAllMediaPacketsUntilFec,
705 kVerifyFecPacketNotInNackList,
706 } state_;
707
stefan608213e2015-11-01 14:56:10 -0800708 rtc::CriticalSection crit_;
709 uint16_t fec_sequence_number_ GUARDED_BY(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000710 bool has_last_sequence_number_;
711 uint16_t last_sequence_number_;
stefanf116bd02015-10-27 08:29:42 -0700712 } test;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000713
stefane74eef12016-01-08 06:47:13 -0800714 RunBaseTest(&test);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000715}
716
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000717// This test drops second RTP packet with a marker bit set, makes sure it's
718// retransmitted and renders. Retransmission SSRCs are also checked.
Peter Boström39593972016-02-15 11:27:15 +0100719void EndToEndTest::DecodesRetransmittedFrame(bool enable_rtx, bool enable_red) {
Peter Boström67680c12016-02-17 11:10:04 +0100720 static const int kDroppedFrameNumber = 10;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000721 class RetransmissionObserver : public test::EndToEndTest,
722 public I420FrameCallback {
723 public:
Peter Boström39593972016-02-15 11:27:15 +0100724 RetransmissionObserver(bool enable_rtx, bool enable_red)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000725 : EndToEndTest(kDefaultTimeoutMs),
Peter Boström39593972016-02-15 11:27:15 +0100726 payload_type_(GetPayloadType(false, enable_red)),
727 retransmission_ssrc_(enable_rtx ? kSendRtxSsrcs[0]
728 : kVideoSendSsrcs[0]),
729 retransmission_payload_type_(GetPayloadType(enable_rtx, enable_red)),
730 encoder_(VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000731 marker_bits_observed_(0),
732 retransmitted_timestamp_(0),
733 frame_retransmitted_(false) {}
734
735 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000736 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700737 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000738 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000739 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000740
Peter Boström67680c12016-02-17 11:10:04 +0100741 // Ignore padding-only packets over RTX.
742 if (header.payloadType != payload_type_) {
743 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
744 if (length == header.headerLength + header.paddingLength)
745 return SEND_PACKET;
Stefan Holmer586b19b2015-09-18 11:14:31 +0200746 }
Peter Boström67680c12016-02-17 11:10:04 +0100747
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000748 if (header.timestamp == retransmitted_timestamp_) {
749 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
750 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
751 frame_retransmitted_ = true;
752 return SEND_PACKET;
753 }
754
Stefan Holmer10880012016-02-03 13:29:59 +0100755 EXPECT_EQ(kVideoSendSsrcs[0], header.ssrc)
756 << "Payload type " << static_cast<int>(header.payloadType)
757 << " not expected.";
Shao Changbine62202f2015-04-21 20:24:50 +0800758 EXPECT_EQ(payload_type_, header.payloadType);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000759
Stefan Holmer586b19b2015-09-18 11:14:31 +0200760 // Found the final packet of the frame to inflict loss to, drop this and
761 // expect a retransmission.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000762 if (header.markerBit && ++marker_bits_observed_ == kDroppedFrameNumber) {
763 retransmitted_timestamp_ = header.timestamp;
764 return DROP_PACKET;
765 }
766
767 return SEND_PACKET;
768 }
769
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700770 void FrameCallback(VideoFrame* frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200771 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000772 if (frame->timestamp() == retransmitted_timestamp_) {
773 EXPECT_TRUE(frame_retransmitted_);
Peter Boström5811a392015-12-10 13:02:50 +0100774 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000775 }
776 }
777
stefanff483612015-12-21 03:14:00 -0800778 void ModifyVideoConfigs(
779 VideoSendStream::Config* send_config,
780 std::vector<VideoReceiveStream::Config>* receive_configs,
781 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000782 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000783 (*receive_configs)[0].pre_render_callback = this;
784 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
Shao Changbine62202f2015-04-21 20:24:50 +0800785
786 if (payload_type_ == kRedPayloadType) {
787 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
788 send_config->rtp.fec.red_payload_type = kRedPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +0100789 if (retransmission_ssrc_ == kSendRtxSsrcs[0])
790 send_config->rtp.fec.red_rtx_payload_type = kRtxRedPayloadType;
791 (*receive_configs)[0].rtp.fec.ulpfec_payload_type =
792 send_config->rtp.fec.ulpfec_payload_type;
793 (*receive_configs)[0].rtp.fec.red_payload_type =
794 send_config->rtp.fec.red_payload_type;
795 (*receive_configs)[0].rtp.fec.red_rtx_payload_type =
796 send_config->rtp.fec.red_rtx_payload_type;
Shao Changbine62202f2015-04-21 20:24:50 +0800797 }
798
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000799 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
800 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000801 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +0100802 (*receive_configs)[0].rtp.rtx[payload_type_].ssrc = kSendRtxSsrcs[0];
803 (*receive_configs)[0].rtp.rtx[payload_type_].payload_type =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000804 kSendRtxPayloadType;
805 }
Peter Boström39593972016-02-15 11:27:15 +0100806 // Configure encoding and decoding with VP8, since generic packetization
807 // doesn't support FEC with NACK.
808 RTC_DCHECK_EQ(1u, (*receive_configs)[0].decoders.size());
809 send_config->encoder_settings.encoder = encoder_.get();
810 send_config->encoder_settings.payload_name = "VP8";
811 (*receive_configs)[0].decoders[0].payload_name = "VP8";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000812 }
813
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000814 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100815 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000816 << "Timed out while waiting for retransmission to render.";
817 }
818
Shao Changbine62202f2015-04-21 20:24:50 +0800819 int GetPayloadType(bool use_rtx, bool use_red) {
Stefan Holmer10880012016-02-03 13:29:59 +0100820 if (use_red) {
821 if (use_rtx)
822 return kRtxRedPayloadType;
823 return kRedPayloadType;
824 }
825 if (use_rtx)
826 return kSendRtxPayloadType;
827 return kFakeVideoSendPayloadType;
Shao Changbine62202f2015-04-21 20:24:50 +0800828 }
829
stefanf116bd02015-10-27 08:29:42 -0700830 rtc::CriticalSection crit_;
Shao Changbine62202f2015-04-21 20:24:50 +0800831 const int payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000832 const uint32_t retransmission_ssrc_;
833 const int retransmission_payload_type_;
kwiberg27f982b2016-03-01 11:52:33 -0800834 std::unique_ptr<VideoEncoder> encoder_;
Peter Boström39593972016-02-15 11:27:15 +0100835 const std::string payload_name_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000836 int marker_bits_observed_;
stefanf116bd02015-10-27 08:29:42 -0700837 uint32_t retransmitted_timestamp_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000838 bool frame_retransmitted_;
Peter Boström39593972016-02-15 11:27:15 +0100839 } test(enable_rtx, enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000840
stefane74eef12016-01-08 06:47:13 -0800841 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000842}
843
844TEST_F(EndToEndTest, DecodesRetransmittedFrame) {
Shao Changbine62202f2015-04-21 20:24:50 +0800845 DecodesRetransmittedFrame(false, false);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000846}
847
848TEST_F(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +0800849 DecodesRetransmittedFrame(true, false);
850}
851
852TEST_F(EndToEndTest, DecodesRetransmittedFrameByRed) {
853 DecodesRetransmittedFrame(false, true);
854}
855
856TEST_F(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
857 DecodesRetransmittedFrame(true, true);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000858}
859
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000860void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
861 static const int kPacketsToDrop = 1;
862
nisse7ade7b32016-03-23 04:48:10 -0700863 class PliObserver : public test::EndToEndTest,
864 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000865 public:
866 explicit PliObserver(int rtp_history_ms)
867 : EndToEndTest(kLongTimeoutMs),
868 rtp_history_ms_(rtp_history_ms),
869 nack_enabled_(rtp_history_ms > 0),
870 highest_dropped_timestamp_(0),
871 frames_to_drop_(0),
872 received_pli_(false) {}
873
874 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000875 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700876 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000877 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000878 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000879
880 // Drop all retransmitted packets to force a PLI.
881 if (header.timestamp <= highest_dropped_timestamp_)
882 return DROP_PACKET;
883
884 if (frames_to_drop_ > 0) {
885 highest_dropped_timestamp_ = header.timestamp;
886 --frames_to_drop_;
887 return DROP_PACKET;
888 }
889
890 return SEND_PACKET;
891 }
892
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000893 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700894 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000895 RTCPUtility::RTCPParserV2 parser(packet, length, true);
896 EXPECT_TRUE(parser.IsValid());
897
898 for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +0200899 packet_type != RTCPUtility::RTCPPacketTypes::kInvalid;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000900 packet_type = parser.Iterate()) {
901 if (!nack_enabled_)
Erik Språng242e22b2015-05-11 10:17:43 +0200902 EXPECT_NE(packet_type, RTCPUtility::RTCPPacketTypes::kRtpfbNack);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000903
Erik Språng242e22b2015-05-11 10:17:43 +0200904 if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbPli) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000905 received_pli_ = true;
906 break;
907 }
908 }
909 return SEND_PACKET;
910 }
911
nisseeb83a1a2016-03-21 01:27:56 -0700912 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200913 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000914 if (received_pli_ &&
915 video_frame.timestamp() > highest_dropped_timestamp_) {
Peter Boström5811a392015-12-10 13:02:50 +0100916 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000917 }
918 if (!received_pli_)
919 frames_to_drop_ = kPacketsToDrop;
920 }
921
stefanff483612015-12-21 03:14:00 -0800922 void ModifyVideoConfigs(
923 VideoSendStream::Config* send_config,
924 std::vector<VideoReceiveStream::Config>* receive_configs,
925 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000926 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000927 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
928 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000929 }
930
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000931 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100932 EXPECT_TRUE(Wait()) << "Timed out waiting for PLI to be "
933 "received and a frame to be "
934 "rendered afterwards.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000935 }
936
stefanf116bd02015-10-27 08:29:42 -0700937 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000938 int rtp_history_ms_;
939 bool nack_enabled_;
stefanf116bd02015-10-27 08:29:42 -0700940 uint32_t highest_dropped_timestamp_ GUARDED_BY(&crit_);
941 int frames_to_drop_ GUARDED_BY(&crit_);
942 bool received_pli_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000943 } test(rtp_history_ms);
944
stefane74eef12016-01-08 06:47:13 -0800945 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000946}
947
948TEST_F(EndToEndTest, ReceivesPliAndRecoversWithNack) {
949 ReceivesPliAndRecovers(1000);
950}
951
jbauchdb81ffd2015-11-23 03:59:02 -0800952TEST_F(EndToEndTest, ReceivesPliAndRecoversWithoutNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000953 ReceivesPliAndRecovers(0);
954}
955
956TEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
957 class PacketInputObserver : public PacketReceiver {
958 public:
959 explicit PacketInputObserver(PacketReceiver* receiver)
Peter Boström5811a392015-12-10 13:02:50 +0100960 : receiver_(receiver), delivered_packet_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000961
Peter Boström5811a392015-12-10 13:02:50 +0100962 bool Wait() { return delivered_packet_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000963
964 private:
stefan68786d22015-09-08 05:36:15 -0700965 DeliveryStatus DeliverPacket(MediaType media_type,
966 const uint8_t* packet,
967 size_t length,
968 const PacketTime& packet_time) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000969 if (RtpHeaderParser::IsRtcp(packet, length)) {
stefan68786d22015-09-08 05:36:15 -0700970 return receiver_->DeliverPacket(media_type, packet, length,
971 packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000972 } else {
973 DeliveryStatus delivery_status =
stefan68786d22015-09-08 05:36:15 -0700974 receiver_->DeliverPacket(media_type, packet, length, packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000975 EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
Peter Boström5811a392015-12-10 13:02:50 +0100976 delivered_packet_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000977 return delivery_status;
978 }
979 }
980
981 PacketReceiver* receiver_;
Peter Boström5811a392015-12-10 13:02:50 +0100982 rtc::Event delivered_packet_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000983 };
984
solenberg4fbae2b2015-08-28 04:07:10 -0700985 CreateCalls(Call::Config(), Call::Config());
986
stefanf116bd02015-10-27 08:29:42 -0700987 test::DirectTransport send_transport(sender_call_.get());
988 test::DirectTransport receive_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000989 PacketInputObserver input_observer(receiver_call_->Receiver());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000990 send_transport.SetReceiver(&input_observer);
991 receive_transport.SetReceiver(sender_call_->Receiver());
992
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100993 CreateSendConfig(1, 0, &send_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700994 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000995
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100996 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000997 CreateFrameGeneratorCapturer();
998 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000999
stefanff483612015-12-21 03:14:00 -08001000 receiver_call_->DestroyVideoReceiveStream(video_receive_streams_[0]);
1001 video_receive_streams_.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001002
1003 // Wait() waits for a received packet.
Peter Boström5811a392015-12-10 13:02:50 +01001004 EXPECT_TRUE(input_observer.Wait());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001005
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001006 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001007
1008 DestroyStreams();
1009
1010 send_transport.StopSending();
1011 receive_transport.StopSending();
1012}
1013
pbosda903ea2015-10-02 02:36:56 -07001014void EndToEndTest::RespectsRtcpMode(RtcpMode rtcp_mode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001015 static const int kNumCompoundRtcpPacketsToObserve = 10;
1016 class RtcpModeObserver : public test::EndToEndTest {
1017 public:
pbosda903ea2015-10-02 02:36:56 -07001018 explicit RtcpModeObserver(RtcpMode rtcp_mode)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001019 : EndToEndTest(kDefaultTimeoutMs),
1020 rtcp_mode_(rtcp_mode),
1021 sent_rtp_(0),
1022 sent_rtcp_(0) {}
1023
1024 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001025 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001026 if (++sent_rtp_ % 3 == 0)
1027 return DROP_PACKET;
1028
1029 return SEND_PACKET;
1030 }
1031
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001032 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001033 ++sent_rtcp_;
1034 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1035 EXPECT_TRUE(parser.IsValid());
1036
1037 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1038 bool has_report_block = false;
Erik Språng242e22b2015-05-11 10:17:43 +02001039 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1040 EXPECT_NE(RTCPUtility::RTCPPacketTypes::kSr, packet_type);
1041 if (packet_type == RTCPUtility::RTCPPacketTypes::kRr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001042 has_report_block = true;
1043 break;
1044 }
1045 packet_type = parser.Iterate();
1046 }
1047
1048 switch (rtcp_mode_) {
pbosda903ea2015-10-02 02:36:56 -07001049 case RtcpMode::kCompound:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001050 if (!has_report_block) {
1051 ADD_FAILURE() << "Received RTCP packet without receiver report for "
pbosda903ea2015-10-02 02:36:56 -07001052 "RtcpMode::kCompound.";
Peter Boström5811a392015-12-10 13:02:50 +01001053 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001054 }
1055
1056 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
Peter Boström5811a392015-12-10 13:02:50 +01001057 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001058
1059 break;
pbosda903ea2015-10-02 02:36:56 -07001060 case RtcpMode::kReducedSize:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001061 if (!has_report_block)
Peter Boström5811a392015-12-10 13:02:50 +01001062 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001063 break;
pbosda903ea2015-10-02 02:36:56 -07001064 case RtcpMode::kOff:
1065 RTC_NOTREACHED();
1066 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001067 }
1068
1069 return SEND_PACKET;
1070 }
1071
stefanff483612015-12-21 03:14:00 -08001072 void ModifyVideoConfigs(
1073 VideoSendStream::Config* send_config,
1074 std::vector<VideoReceiveStream::Config>* receive_configs,
1075 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001076 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001077 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1078 (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001079 }
1080
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001081 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001082 EXPECT_TRUE(Wait())
pbosda903ea2015-10-02 02:36:56 -07001083 << (rtcp_mode_ == RtcpMode::kCompound
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001084 ? "Timed out before observing enough compound packets."
1085 : "Timed out before receiving a non-compound RTCP packet.");
1086 }
1087
pbosda903ea2015-10-02 02:36:56 -07001088 RtcpMode rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001089 int sent_rtp_;
1090 int sent_rtcp_;
1091 } test(rtcp_mode);
1092
stefane74eef12016-01-08 06:47:13 -08001093 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001094}
1095
1096TEST_F(EndToEndTest, UsesRtcpCompoundMode) {
pbosda903ea2015-10-02 02:36:56 -07001097 RespectsRtcpMode(RtcpMode::kCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001098}
1099
1100TEST_F(EndToEndTest, UsesRtcpReducedSizeMode) {
pbosda903ea2015-10-02 02:36:56 -07001101 RespectsRtcpMode(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001102}
1103
1104// Test sets up a Call multiple senders with different resolutions and SSRCs.
1105// Another is set up to receive all three of these with different renderers.
sprang867fb522015-08-03 04:38:41 -07001106class MultiStreamTest {
1107 public:
1108 static const size_t kNumStreams = 3;
1109 struct CodecSettings {
1110 uint32_t ssrc;
1111 int width;
1112 int height;
1113 } codec_settings[kNumStreams];
1114
1115 MultiStreamTest() {
1116 // TODO(sprang): Cleanup when msvc supports explicit initializers for array.
1117 codec_settings[0] = {1, 640, 480};
1118 codec_settings[1] = {2, 320, 240};
1119 codec_settings[2] = {3, 240, 160};
1120 }
1121
1122 virtual ~MultiStreamTest() {}
1123
1124 void RunTest() {
kwiberg27f982b2016-03-01 11:52:33 -08001125 std::unique_ptr<Call> sender_call(Call::Create(Call::Config()));
1126 std::unique_ptr<Call> receiver_call(Call::Create(Call::Config()));
1127 std::unique_ptr<test::DirectTransport> sender_transport(
stefanf116bd02015-10-27 08:29:42 -07001128 CreateSendTransport(sender_call.get()));
kwiberg27f982b2016-03-01 11:52:33 -08001129 std::unique_ptr<test::DirectTransport> receiver_transport(
stefanf116bd02015-10-27 08:29:42 -07001130 CreateReceiveTransport(receiver_call.get()));
sprang867fb522015-08-03 04:38:41 -07001131 sender_transport->SetReceiver(receiver_call->Receiver());
1132 receiver_transport->SetReceiver(sender_call->Receiver());
1133
kwiberg27f982b2016-03-01 11:52:33 -08001134 std::unique_ptr<VideoEncoder> encoders[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001135 for (size_t i = 0; i < kNumStreams; ++i)
1136 encoders[i].reset(VideoEncoder::Create(VideoEncoder::kVp8));
1137
1138 VideoSendStream* send_streams[kNumStreams];
1139 VideoReceiveStream* receive_streams[kNumStreams];
1140
1141 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
kwiberg4a206a92016-03-31 10:24:26 -07001142 std::vector<std::unique_ptr<VideoDecoder>> allocated_decoders;
sprang867fb522015-08-03 04:38:41 -07001143 for (size_t i = 0; i < kNumStreams; ++i) {
1144 uint32_t ssrc = codec_settings[i].ssrc;
1145 int width = codec_settings[i].width;
1146 int height = codec_settings[i].height;
1147
solenberg4fbae2b2015-08-28 04:07:10 -07001148 VideoSendStream::Config send_config(sender_transport.get());
sprang867fb522015-08-03 04:38:41 -07001149 send_config.rtp.ssrcs.push_back(ssrc);
1150 send_config.encoder_settings.encoder = encoders[i].get();
1151 send_config.encoder_settings.payload_name = "VP8";
1152 send_config.encoder_settings.payload_type = 124;
1153 VideoEncoderConfig encoder_config;
1154 encoder_config.streams = test::CreateVideoStreams(1);
1155 VideoStream* stream = &encoder_config.streams[0];
1156 stream->width = width;
1157 stream->height = height;
1158 stream->max_framerate = 5;
1159 stream->min_bitrate_bps = stream->target_bitrate_bps =
1160 stream->max_bitrate_bps = 100000;
1161
1162 UpdateSendConfig(i, &send_config, &encoder_config, &frame_generators[i]);
1163
1164 send_streams[i] =
1165 sender_call->CreateVideoSendStream(send_config, encoder_config);
1166 send_streams[i]->Start();
1167
solenberg4fbae2b2015-08-28 04:07:10 -07001168 VideoReceiveStream::Config receive_config(receiver_transport.get());
sprang867fb522015-08-03 04:38:41 -07001169 receive_config.rtp.remote_ssrc = ssrc;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001170 receive_config.rtp.local_ssrc = test::CallTest::kReceiverLocalVideoSsrc;
sprang867fb522015-08-03 04:38:41 -07001171 VideoReceiveStream::Decoder decoder =
1172 test::CreateMatchingDecoder(send_config.encoder_settings);
kwiberg4a206a92016-03-31 10:24:26 -07001173 allocated_decoders.push_back(
1174 std::unique_ptr<VideoDecoder>(decoder.decoder));
sprang867fb522015-08-03 04:38:41 -07001175 receive_config.decoders.push_back(decoder);
1176
1177 UpdateReceiveConfig(i, &receive_config);
1178
1179 receive_streams[i] =
1180 receiver_call->CreateVideoReceiveStream(receive_config);
1181 receive_streams[i]->Start();
1182
1183 frame_generators[i] = test::FrameGeneratorCapturer::Create(
1184 send_streams[i]->Input(), width, height, 30,
1185 Clock::GetRealTimeClock());
1186 frame_generators[i]->Start();
1187 }
1188
1189 Wait();
1190
1191 for (size_t i = 0; i < kNumStreams; ++i) {
1192 frame_generators[i]->Stop();
1193 sender_call->DestroyVideoSendStream(send_streams[i]);
1194 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1195 delete frame_generators[i];
1196 }
1197
1198 sender_transport->StopSending();
1199 receiver_transport->StopSending();
1200 }
1201
1202 protected:
1203 virtual void Wait() = 0;
1204 // Note: frame_generator is a point-to-pointer, since the actual instance
1205 // hasn't been created at the time of this call. Only when packets/frames
1206 // start flowing should this be dereferenced.
1207 virtual void UpdateSendConfig(
1208 size_t stream_index,
1209 VideoSendStream::Config* send_config,
1210 VideoEncoderConfig* encoder_config,
1211 test::FrameGeneratorCapturer** frame_generator) {}
1212 virtual void UpdateReceiveConfig(size_t stream_index,
1213 VideoReceiveStream::Config* receive_config) {
1214 }
stefanf116bd02015-10-27 08:29:42 -07001215 virtual test::DirectTransport* CreateSendTransport(Call* sender_call) {
1216 return new test::DirectTransport(sender_call);
sprang867fb522015-08-03 04:38:41 -07001217 }
stefanf116bd02015-10-27 08:29:42 -07001218 virtual test::DirectTransport* CreateReceiveTransport(Call* receiver_call) {
1219 return new test::DirectTransport(receiver_call);
sprang867fb522015-08-03 04:38:41 -07001220 }
1221};
1222
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001223// Each renderer verifies that it receives the expected resolution, and as soon
1224// as every renderer has received a frame, the test finishes.
andresp@webrtc.org02686112014-09-19 08:24:19 +00001225TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) {
nisse7ade7b32016-03-23 04:48:10 -07001226 class VideoOutputObserver : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001227 public:
sprang867fb522015-08-03 04:38:41 -07001228 VideoOutputObserver(const MultiStreamTest::CodecSettings& settings,
1229 uint32_t ssrc,
1230 test::FrameGeneratorCapturer** frame_generator)
1231 : settings_(settings),
1232 ssrc_(ssrc),
1233 frame_generator_(frame_generator),
Peter Boström5811a392015-12-10 13:02:50 +01001234 done_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001235
nisseeb83a1a2016-03-21 01:27:56 -07001236 void OnFrame(const VideoFrame& video_frame) override {
sprang867fb522015-08-03 04:38:41 -07001237 EXPECT_EQ(settings_.width, video_frame.width());
1238 EXPECT_EQ(settings_.height, video_frame.height());
1239 (*frame_generator_)->Stop();
Peter Boström5811a392015-12-10 13:02:50 +01001240 done_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001241 }
1242
sprang867fb522015-08-03 04:38:41 -07001243 uint32_t Ssrc() { return ssrc_; }
1244
Peter Boström5811a392015-12-10 13:02:50 +01001245 bool Wait() { return done_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001246
1247 private:
sprang867fb522015-08-03 04:38:41 -07001248 const MultiStreamTest::CodecSettings& settings_;
1249 const uint32_t ssrc_;
1250 test::FrameGeneratorCapturer** const frame_generator_;
Peter Boström5811a392015-12-10 13:02:50 +01001251 rtc::Event done_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001252 };
1253
sprang867fb522015-08-03 04:38:41 -07001254 class Tester : public MultiStreamTest {
1255 public:
1256 Tester() {}
1257 virtual ~Tester() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001258
sprang867fb522015-08-03 04:38:41 -07001259 protected:
1260 void Wait() override {
1261 for (const auto& observer : observers_) {
Peter Boström5811a392015-12-10 13:02:50 +01001262 EXPECT_TRUE(observer->Wait()) << "Time out waiting for from on ssrc "
1263 << observer->Ssrc();
sprang867fb522015-08-03 04:38:41 -07001264 }
1265 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001266
sprang867fb522015-08-03 04:38:41 -07001267 void UpdateSendConfig(
1268 size_t stream_index,
1269 VideoSendStream::Config* send_config,
1270 VideoEncoderConfig* encoder_config,
1271 test::FrameGeneratorCapturer** frame_generator) override {
1272 observers_[stream_index].reset(new VideoOutputObserver(
1273 codec_settings[stream_index], send_config->rtp.ssrcs.front(),
1274 frame_generator));
1275 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001276
sprang867fb522015-08-03 04:38:41 -07001277 void UpdateReceiveConfig(
1278 size_t stream_index,
1279 VideoReceiveStream::Config* receive_config) override {
1280 receive_config->renderer = observers_[stream_index].get();
1281 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001282
sprang867fb522015-08-03 04:38:41 -07001283 private:
kwiberg27f982b2016-03-01 11:52:33 -08001284 std::unique_ptr<VideoOutputObserver> observers_[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001285 } tester;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001286
sprang867fb522015-08-03 04:38:41 -07001287 tester.RunTest();
1288}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001289
sprang867fb522015-08-03 04:38:41 -07001290TEST_F(EndToEndTest, AssignsTransportSequenceNumbers) {
sprang867fb522015-08-03 04:38:41 -07001291 static const int kExtensionId = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001292
sprang867fb522015-08-03 04:38:41 -07001293 class RtpExtensionHeaderObserver : public test::DirectTransport {
1294 public:
stefanf116bd02015-10-27 08:29:42 -07001295 RtpExtensionHeaderObserver(Call* sender_call,
1296 const uint32_t& first_media_ssrc,
sprang861c55e2015-10-16 10:01:21 -07001297 const std::map<uint32_t, uint32_t>& ssrc_map)
stefanf116bd02015-10-27 08:29:42 -07001298 : DirectTransport(sender_call),
Peter Boström5811a392015-12-10 13:02:50 +01001299 done_(false, false),
sprang867fb522015-08-03 04:38:41 -07001300 parser_(RtpHeaderParser::Create()),
sprang861c55e2015-10-16 10:01:21 -07001301 first_media_ssrc_(first_media_ssrc),
1302 rtx_to_media_ssrcs_(ssrc_map),
sprang867fb522015-08-03 04:38:41 -07001303 padding_observed_(false),
sprang861c55e2015-10-16 10:01:21 -07001304 rtx_padding_observed_(false),
1305 retransmit_observed_(false),
1306 started_(false) {
sprang867fb522015-08-03 04:38:41 -07001307 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
1308 kExtensionId);
1309 }
1310 virtual ~RtpExtensionHeaderObserver() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001311
stefan1d8a5062015-10-02 03:39:33 -07001312 bool SendRtp(const uint8_t* data,
1313 size_t length,
1314 const PacketOptions& options) override {
sprang861c55e2015-10-16 10:01:21 -07001315 {
1316 rtc::CritScope cs(&lock_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001317
Erik Språng8d629712015-08-04 16:24:03 +02001318 if (IsDone())
sprang861c55e2015-10-16 10:01:21 -07001319 return false;
1320
1321 if (started_) {
1322 RTPHeader header;
1323 EXPECT_TRUE(parser_->Parse(data, length, &header));
1324 bool drop_packet = false;
1325
1326 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
1327 EXPECT_EQ(options.packet_id,
1328 header.extension.transportSequenceNumber);
1329 if (!streams_observed_.empty()) {
1330 // Unwrap packet id and verify uniqueness.
1331 int64_t packet_id = unwrapper_.Unwrap(options.packet_id);
1332 EXPECT_TRUE(received_packed_ids_.insert(packet_id).second);
1333 }
1334
1335 // Drop (up to) every 17th packet, so we get retransmits.
1336 // Only drop media, and not on the first stream (otherwise it will be
1337 // hard to distinguish from padding, which is always sent on the first
1338 // stream).
1339 if (header.payloadType != kSendRtxPayloadType &&
1340 header.ssrc != first_media_ssrc_ &&
1341 header.extension.transportSequenceNumber % 17 == 0) {
1342 dropped_seq_[header.ssrc].insert(header.sequenceNumber);
1343 drop_packet = true;
1344 }
1345
1346 size_t payload_length =
1347 length - (header.headerLength + header.paddingLength);
1348 if (payload_length == 0) {
1349 padding_observed_ = true;
1350 } else if (header.payloadType == kSendRtxPayloadType) {
1351 uint16_t original_sequence_number =
1352 ByteReader<uint16_t>::ReadBigEndian(&data[header.headerLength]);
1353 uint32_t original_ssrc =
1354 rtx_to_media_ssrcs_.find(header.ssrc)->second;
1355 std::set<uint16_t>* seq_no_map = &dropped_seq_[original_ssrc];
1356 auto it = seq_no_map->find(original_sequence_number);
1357 if (it != seq_no_map->end()) {
1358 retransmit_observed_ = true;
1359 seq_no_map->erase(it);
1360 } else {
1361 rtx_padding_observed_ = true;
1362 }
1363 } else {
1364 streams_observed_.insert(header.ssrc);
1365 }
1366
1367 if (IsDone())
Peter Boström5811a392015-12-10 13:02:50 +01001368 done_.Set();
sprang861c55e2015-10-16 10:01:21 -07001369
1370 if (drop_packet)
1371 return true;
1372 }
sprang867fb522015-08-03 04:38:41 -07001373 }
sprang861c55e2015-10-16 10:01:21 -07001374
stefan1d8a5062015-10-02 03:39:33 -07001375 return test::DirectTransport::SendRtp(data, length, options);
sprang867fb522015-08-03 04:38:41 -07001376 }
1377
Erik Språng8d629712015-08-04 16:24:03 +02001378 bool IsDone() {
sprang861c55e2015-10-16 10:01:21 -07001379 bool observed_types_ok =
1380 streams_observed_.size() == MultiStreamTest::kNumStreams &&
1381 padding_observed_ && retransmit_observed_ && rtx_padding_observed_;
1382 if (!observed_types_ok)
1383 return false;
1384 // We should not have any gaps in the sequence number range.
1385 size_t seqno_range =
1386 *received_packed_ids_.rbegin() - *received_packed_ids_.begin() + 1;
1387 return seqno_range == received_packed_ids_.size();
Erik Språng8d629712015-08-04 16:24:03 +02001388 }
1389
Peter Boström5811a392015-12-10 13:02:50 +01001390 bool Wait() {
sprang861c55e2015-10-16 10:01:21 -07001391 {
1392 // Can't be sure until this point that rtx_to_media_ssrcs_ etc have
1393 // been initialized and are OK to read.
1394 rtc::CritScope cs(&lock_);
1395 started_ = true;
1396 }
Peter Boström5811a392015-12-10 13:02:50 +01001397 return done_.Wait(kDefaultTimeoutMs);
sprang861c55e2015-10-16 10:01:21 -07001398 }
sprang867fb522015-08-03 04:38:41 -07001399
sprang861c55e2015-10-16 10:01:21 -07001400 rtc::CriticalSection lock_;
Peter Boström5811a392015-12-10 13:02:50 +01001401 rtc::Event done_;
kwiberg27f982b2016-03-01 11:52:33 -08001402 std::unique_ptr<RtpHeaderParser> parser_;
sprang861c55e2015-10-16 10:01:21 -07001403 SequenceNumberUnwrapper unwrapper_;
1404 std::set<int64_t> received_packed_ids_;
sprang867fb522015-08-03 04:38:41 -07001405 std::set<uint32_t> streams_observed_;
sprang861c55e2015-10-16 10:01:21 -07001406 std::map<uint32_t, std::set<uint16_t>> dropped_seq_;
1407 const uint32_t& first_media_ssrc_;
1408 const std::map<uint32_t, uint32_t>& rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001409 bool padding_observed_;
1410 bool rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001411 bool retransmit_observed_;
1412 bool started_;
sprang867fb522015-08-03 04:38:41 -07001413 };
1414
1415 class TransportSequenceNumberTester : public MultiStreamTest {
1416 public:
sprang861c55e2015-10-16 10:01:21 -07001417 TransportSequenceNumberTester()
1418 : first_media_ssrc_(0), observer_(nullptr) {}
sprang867fb522015-08-03 04:38:41 -07001419 virtual ~TransportSequenceNumberTester() {}
1420
1421 protected:
1422 void Wait() override {
Peter Boström74f6e9e2016-04-04 17:56:10 +02001423 RTC_DCHECK(observer_);
Peter Boström5811a392015-12-10 13:02:50 +01001424 EXPECT_TRUE(observer_->Wait());
sprang867fb522015-08-03 04:38:41 -07001425 }
1426
1427 void UpdateSendConfig(
1428 size_t stream_index,
1429 VideoSendStream::Config* send_config,
1430 VideoEncoderConfig* encoder_config,
1431 test::FrameGeneratorCapturer** frame_generator) override {
1432 send_config->rtp.extensions.clear();
1433 send_config->rtp.extensions.push_back(
1434 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
1435
1436 // Force some padding to be sent.
1437 const int kPaddingBitrateBps = 50000;
1438 int total_target_bitrate = 0;
1439 for (const VideoStream& stream : encoder_config->streams)
1440 total_target_bitrate += stream.target_bitrate_bps;
1441 encoder_config->min_transmit_bitrate_bps =
1442 total_target_bitrate + kPaddingBitrateBps;
1443
1444 // Configure RTX for redundant payload padding.
1445 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang861c55e2015-10-16 10:01:21 -07001446 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[stream_index]);
sprang867fb522015-08-03 04:38:41 -07001447 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
sprang861c55e2015-10-16 10:01:21 -07001448 rtx_to_media_ssrcs_[kSendRtxSsrcs[stream_index]] =
1449 send_config->rtp.ssrcs[0];
1450
1451 if (stream_index == 0)
1452 first_media_ssrc_ = send_config->rtp.ssrcs[0];
sprang867fb522015-08-03 04:38:41 -07001453 }
1454
1455 void UpdateReceiveConfig(
1456 size_t stream_index,
1457 VideoReceiveStream::Config* receive_config) override {
sprang861c55e2015-10-16 10:01:21 -07001458 receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang867fb522015-08-03 04:38:41 -07001459 receive_config->rtp.extensions.clear();
1460 receive_config->rtp.extensions.push_back(
1461 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
1462 }
1463
stefanf116bd02015-10-27 08:29:42 -07001464 test::DirectTransport* CreateSendTransport(Call* sender_call) override {
1465 observer_ = new RtpExtensionHeaderObserver(sender_call, first_media_ssrc_,
sprang861c55e2015-10-16 10:01:21 -07001466 rtx_to_media_ssrcs_);
sprang867fb522015-08-03 04:38:41 -07001467 return observer_;
1468 }
1469
1470 private:
sprang861c55e2015-10-16 10:01:21 -07001471 uint32_t first_media_ssrc_;
1472 std::map<uint32_t, uint32_t> rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001473 RtpExtensionHeaderObserver* observer_;
1474 } tester;
1475
1476 tester.RunTest();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001477}
1478
Stefan Holmer04cb7632016-01-14 20:34:30 +01001479class TransportFeedbackTester : public test::EndToEndTest {
1480 public:
1481 explicit TransportFeedbackTester(bool feedback_enabled,
1482 size_t num_video_streams,
1483 size_t num_audio_streams)
1484 : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
1485 feedback_enabled_(feedback_enabled),
1486 num_video_streams_(num_video_streams),
1487 num_audio_streams_(num_audio_streams) {
1488 // Only one stream of each supported for now.
1489 EXPECT_LE(num_video_streams, 1u);
1490 EXPECT_LE(num_audio_streams, 1u);
1491 }
1492
1493 protected:
1494 Action OnSendRtcp(const uint8_t* data, size_t length) override {
1495 EXPECT_FALSE(HasTransportFeedback(data, length));
1496 return SEND_PACKET;
1497 }
1498
1499 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
1500 if (HasTransportFeedback(data, length))
1501 observation_complete_.Set();
1502 return SEND_PACKET;
1503 }
1504
1505 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
1506 RTCPUtility::RTCPParserV2 parser(data, length, true);
1507 EXPECT_TRUE(parser.IsValid());
1508
1509 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1510 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1511 if (packet_type == RTCPUtility::RTCPPacketTypes::kTransportFeedback)
1512 return true;
1513 packet_type = parser.Iterate();
1514 }
1515
1516 return false;
1517 }
1518
1519 void PerformTest() override {
1520 const int64_t kDisabledFeedbackTimeoutMs = 5000;
1521 EXPECT_EQ(feedback_enabled_,
1522 observation_complete_.Wait(feedback_enabled_
1523 ? test::CallTest::kDefaultTimeoutMs
1524 : kDisabledFeedbackTimeoutMs));
1525 }
1526
1527 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1528 receiver_call_ = receiver_call;
1529 }
1530
1531 size_t GetNumVideoStreams() const override { return num_video_streams_; }
1532 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
1533
1534 void ModifyVideoConfigs(
1535 VideoSendStream::Config* send_config,
1536 std::vector<VideoReceiveStream::Config>* receive_configs,
1537 VideoEncoderConfig* encoder_config) override {
1538 send_config->rtp.extensions.clear();
1539 send_config->rtp.extensions.push_back(
1540 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
1541 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1542 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
1543 }
1544
1545 void ModifyAudioConfigs(
1546 AudioSendStream::Config* send_config,
1547 std::vector<AudioReceiveStream::Config>* receive_configs) override {
1548 send_config->rtp.extensions.clear();
1549 send_config->rtp.extensions.push_back(
1550 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
1551 (*receive_configs)[0].rtp.extensions.clear();
1552 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1553 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001554 }
1555
1556 private:
Erik Språng6b8d3552015-09-24 15:06:57 +02001557 static const int kExtensionId = 5;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001558 const bool feedback_enabled_;
1559 const size_t num_video_streams_;
1560 const size_t num_audio_streams_;
1561 Call* receiver_call_;
1562};
Erik Språng6b8d3552015-09-24 15:06:57 +02001563
Stefan Holmer04cb7632016-01-14 20:34:30 +01001564TEST_F(EndToEndTest, VideoReceivesTransportFeedback) {
1565 TransportFeedbackTester test(true, 1, 0);
1566 RunBaseTest(&test);
Erik Språng6b8d3552015-09-24 15:06:57 +02001567}
stefan43edf0f2015-11-20 18:05:48 -08001568
Stefan Holmer04cb7632016-01-14 20:34:30 +01001569TEST_F(EndToEndTest, VideoTransportFeedbackNotConfigured) {
1570 TransportFeedbackTester test(false, 1, 0);
1571 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001572}
1573
Stefan Holmer04cb7632016-01-14 20:34:30 +01001574TEST_F(EndToEndTest, AudioReceivesTransportFeedback) {
1575 TransportFeedbackTester test(true, 0, 1);
1576 RunBaseTest(&test);
1577}
1578
1579TEST_F(EndToEndTest, AudioTransportFeedbackNotConfigured) {
1580 TransportFeedbackTester test(false, 0, 1);
1581 RunBaseTest(&test);
1582}
1583
1584TEST_F(EndToEndTest, AudioVideoReceivesTransportFeedback) {
1585 TransportFeedbackTester test(true, 1, 1);
1586 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001587}
1588
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001589TEST_F(EndToEndTest, ObserversEncodedFrames) {
1590 class EncodedFrameTestObserver : public EncodedFrameObserver {
1591 public:
1592 EncodedFrameTestObserver()
Peter Boström5811a392015-12-10 13:02:50 +01001593 : length_(0), frame_type_(kEmptyFrame), called_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001594 virtual ~EncodedFrameTestObserver() {}
1595
1596 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
1597 frame_type_ = encoded_frame.frame_type_;
1598 length_ = encoded_frame.length_;
1599 buffer_.reset(new uint8_t[length_]);
1600 memcpy(buffer_.get(), encoded_frame.data_, length_);
Peter Boström5811a392015-12-10 13:02:50 +01001601 called_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001602 }
1603
Peter Boström5811a392015-12-10 13:02:50 +01001604 bool Wait() { return called_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001605
1606 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
1607 ASSERT_EQ(length_, observer.length_)
1608 << "Observed frames are of different lengths.";
1609 EXPECT_EQ(frame_type_, observer.frame_type_)
1610 << "Observed frames have different frame types.";
1611 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
1612 << "Observed encoded frames have different content.";
1613 }
1614
1615 private:
kwiberg27f982b2016-03-01 11:52:33 -08001616 std::unique_ptr<uint8_t[]> buffer_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001617 size_t length_;
1618 FrameType frame_type_;
Peter Boström5811a392015-12-10 13:02:50 +01001619 rtc::Event called_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001620 };
1621
1622 EncodedFrameTestObserver post_encode_observer;
1623 EncodedFrameTestObserver pre_decode_observer;
1624
solenberg4fbae2b2015-08-28 04:07:10 -07001625 CreateCalls(Call::Config(), Call::Config());
1626
stefanf116bd02015-10-27 08:29:42 -07001627 test::DirectTransport sender_transport(sender_call_.get());
1628 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001629 sender_transport.SetReceiver(receiver_call_->Receiver());
1630 receiver_transport.SetReceiver(sender_call_->Receiver());
1631
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001632 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001633 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -08001634 video_send_config_.post_encode_callback = &post_encode_observer;
1635 video_receive_configs_[0].pre_decode_callback = &pre_decode_observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001636
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001637 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001638 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001639
kwiberg27f982b2016-03-01 11:52:33 -08001640 std::unique_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +00001641 test::FrameGenerator::CreateChromaGenerator(
stefanff483612015-12-21 03:14:00 -08001642 video_encoder_config_.streams[0].width,
1643 video_encoder_config_.streams[0].height));
1644 video_send_stream_->Input()->IncomingCapturedFrame(
1645 *frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001646
Peter Boström5811a392015-12-10 13:02:50 +01001647 EXPECT_TRUE(post_encode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001648 << "Timed out while waiting for send-side encoded-frame callback.";
1649
Peter Boström5811a392015-12-10 13:02:50 +01001650 EXPECT_TRUE(pre_decode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001651 << "Timed out while waiting for pre-decode encoded-frame callback.";
1652
1653 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
1654
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001655 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001656
1657 sender_transport.StopSending();
1658 receiver_transport.StopSending();
1659
1660 DestroyStreams();
1661}
1662
1663TEST_F(EndToEndTest, ReceiveStreamSendsRemb) {
1664 class RembObserver : public test::EndToEndTest {
1665 public:
1666 RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
1667
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001668 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001669 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1670 EXPECT_TRUE(parser.IsValid());
1671
1672 bool received_psfb = false;
1673 bool received_remb = false;
1674 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02001675 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1676 if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbRemb) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001677 const RTCPUtility::RTCPPacket& packet = parser.Packet();
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001678 EXPECT_EQ(packet.PSFBAPP.SenderSSRC, kReceiverLocalVideoSsrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001679 received_psfb = true;
Erik Språng242e22b2015-05-11 10:17:43 +02001680 } else if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbRembItem) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001681 const RTCPUtility::RTCPPacket& packet = parser.Packet();
1682 EXPECT_GT(packet.REMBItem.BitRate, 0u);
1683 EXPECT_EQ(packet.REMBItem.NumberOfSSRCs, 1u);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001684 EXPECT_EQ(packet.REMBItem.SSRCs[0], kVideoSendSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001685 received_remb = true;
1686 }
1687 packet_type = parser.Iterate();
1688 }
1689 if (received_psfb && received_remb)
Peter Boström5811a392015-12-10 13:02:50 +01001690 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001691 return SEND_PACKET;
1692 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001693 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001694 EXPECT_TRUE(Wait()) << "Timed out while waiting for a "
1695 "receiver RTCP REMB packet to be "
1696 "sent.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001697 }
1698 } test;
1699
stefane74eef12016-01-08 06:47:13 -08001700 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001701}
1702
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001703TEST_F(EndToEndTest, VerifyBandwidthStats) {
stefanf116bd02015-10-27 08:29:42 -07001704 class RtcpObserver : public test::EndToEndTest {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001705 public:
1706 RtcpObserver()
1707 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001708 sender_call_(nullptr),
1709 receiver_call_(nullptr),
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001710 has_seen_pacer_delay_(false) {}
1711
stefanf116bd02015-10-27 08:29:42 -07001712 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001713 Call::Stats sender_stats = sender_call_->GetStats();
1714 Call::Stats receiver_stats = receiver_call_->GetStats();
1715 if (!has_seen_pacer_delay_)
1716 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
1717 if (sender_stats.send_bandwidth_bps > 0 &&
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001718 receiver_stats.recv_bandwidth_bps > 0 && has_seen_pacer_delay_) {
Peter Boström5811a392015-12-10 13:02:50 +01001719 observation_complete_.Set();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001720 }
stefanf116bd02015-10-27 08:29:42 -07001721 return SEND_PACKET;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001722 }
1723
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001724 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001725 sender_call_ = sender_call;
1726 receiver_call_ = receiver_call;
1727 }
1728
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001729 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001730 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
1731 "non-zero bandwidth stats.";
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001732 }
1733
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001734 private:
1735 Call* sender_call_;
1736 Call* receiver_call_;
1737 bool has_seen_pacer_delay_;
1738 } test;
1739
stefane74eef12016-01-08 06:47:13 -08001740 RunBaseTest(&test);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001741}
1742
stefan32f81542016-01-20 07:13:58 -08001743
1744// Verifies that it's possible to limit the send BWE by sending a REMB.
1745// This is verified by allowing the send BWE to ramp-up to >1000 kbps,
1746// then have the test generate a REMB of 500 kbps and verify that the send BWE
1747// is reduced to exactly 500 kbps. Then a REMB of 1000 kbps is generated and the
1748// test verifies that the send BWE ramps back up to exactly 1000 kbps.
1749TEST_F(EndToEndTest, RembWithSendSideBwe) {
1750 class BweObserver : public test::EndToEndTest {
1751 public:
1752 BweObserver()
1753 : EndToEndTest(kDefaultTimeoutMs),
1754 sender_call_(nullptr),
1755 clock_(Clock::GetRealTimeClock()),
1756 sender_ssrc_(0),
1757 remb_bitrate_bps_(1000000),
1758 receive_transport_(nullptr),
1759 event_(false, false),
1760 poller_thread_(&BitrateStatsPollingThread,
1761 this,
1762 "BitrateStatsPollingThread"),
1763 state_(kWaitForFirstRampUp) {}
1764
1765 ~BweObserver() {}
1766
nisseef8b61e2016-04-29 06:09:15 -07001767 test::PacketTransport* CreateReceiveTransport() override {
stefan32f81542016-01-20 07:13:58 -08001768 receive_transport_ = new test::PacketTransport(
1769 nullptr, this, test::PacketTransport::kReceiver,
1770 FakeNetworkPipe::Config());
1771 return receive_transport_;
1772 }
1773
1774 Call::Config GetSenderCallConfig() override {
1775 Call::Config config;
1776 // Set a high start bitrate to reduce the test completion time.
1777 config.bitrate_config.start_bitrate_bps = remb_bitrate_bps_;
1778 return config;
1779 }
1780
1781 void ModifyVideoConfigs(
1782 VideoSendStream::Config* send_config,
1783 std::vector<VideoReceiveStream::Config>* receive_configs,
1784 VideoEncoderConfig* encoder_config) override {
1785 ASSERT_EQ(1u, send_config->rtp.ssrcs.size());
1786 send_config->rtp.extensions.clear();
1787 send_config->rtp.extensions.push_back(
1788 RtpExtension(RtpExtension::kTransportSequenceNumber,
1789 test::kTransportSequenceNumberExtensionId));
1790 sender_ssrc_ = send_config->rtp.ssrcs[0];
1791
1792 encoder_config->streams[0].max_bitrate_bps =
1793 encoder_config->streams[0].target_bitrate_bps = 2000000;
1794
1795 ASSERT_EQ(1u, receive_configs->size());
1796 (*receive_configs)[0].rtp.remb = false;
1797 (*receive_configs)[0].rtp.transport_cc = true;
1798 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1799 RtpRtcp::Configuration config;
1800 config.receiver_only = true;
1801 config.clock = clock_;
1802 config.outgoing_transport = receive_transport_;
1803 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
1804 rtp_rtcp_->SetRemoteSSRC((*receive_configs)[0].rtp.remote_ssrc);
1805 rtp_rtcp_->SetSSRC((*receive_configs)[0].rtp.local_ssrc);
1806 rtp_rtcp_->SetREMBStatus(true);
1807 rtp_rtcp_->SetSendingStatus(true);
1808 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
1809 }
1810
1811 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1812 sender_call_ = sender_call;
1813 }
1814
1815 static bool BitrateStatsPollingThread(void* obj) {
1816 return static_cast<BweObserver*>(obj)->PollStats();
1817 }
1818
1819 bool PollStats() {
1820 if (sender_call_) {
1821 Call::Stats stats = sender_call_->GetStats();
1822 switch (state_) {
1823 case kWaitForFirstRampUp:
1824 if (stats.send_bandwidth_bps >= remb_bitrate_bps_) {
1825 state_ = kWaitForRemb;
1826 remb_bitrate_bps_ /= 2;
1827 rtp_rtcp_->SetREMBData(
1828 remb_bitrate_bps_,
1829 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
1830 rtp_rtcp_->SendRTCP(kRtcpRr);
1831 }
1832 break;
1833
1834 case kWaitForRemb:
1835 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
1836 state_ = kWaitForSecondRampUp;
1837 remb_bitrate_bps_ *= 2;
1838 rtp_rtcp_->SetREMBData(
1839 remb_bitrate_bps_,
1840 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
1841 rtp_rtcp_->SendRTCP(kRtcpRr);
1842 }
1843 break;
1844
1845 case kWaitForSecondRampUp:
1846 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
1847 observation_complete_.Set();
1848 }
1849 break;
1850 }
1851 }
1852
1853 return !event_.Wait(1000);
1854 }
1855
1856 void PerformTest() override {
1857 poller_thread_.Start();
1858 EXPECT_TRUE(Wait())
1859 << "Timed out while waiting for bitrate to change according to REMB.";
1860 poller_thread_.Stop();
1861 }
1862
1863 private:
1864 enum TestState { kWaitForFirstRampUp, kWaitForRemb, kWaitForSecondRampUp };
1865
1866 Call* sender_call_;
1867 Clock* const clock_;
1868 uint32_t sender_ssrc_;
1869 int remb_bitrate_bps_;
kwiberg27f982b2016-03-01 11:52:33 -08001870 std::unique_ptr<RtpRtcp> rtp_rtcp_;
stefan32f81542016-01-20 07:13:58 -08001871 test::PacketTransport* receive_transport_;
1872 rtc::Event event_;
1873 rtc::PlatformThread poller_thread_;
1874 TestState state_;
1875 } test;
1876
1877 RunBaseTest(&test);
1878}
1879
Åsa Persson352b2d72015-04-15 18:00:40 +02001880TEST_F(EndToEndTest, VerifyNackStats) {
1881 static const int kPacketNumberToDrop = 200;
1882 class NackObserver : public test::EndToEndTest {
1883 public:
1884 NackObserver()
1885 : EndToEndTest(kLongTimeoutMs),
1886 sent_rtp_packets_(0),
1887 dropped_rtp_packet_(0),
1888 dropped_rtp_packet_requested_(false),
1889 send_stream_(nullptr),
1890 start_runtime_ms_(-1) {}
1891
1892 private:
1893 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08001894 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02001895 if (++sent_rtp_packets_ == kPacketNumberToDrop) {
kwiberg27f982b2016-03-01 11:52:33 -08001896 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
Åsa Persson352b2d72015-04-15 18:00:40 +02001897 RTPHeader header;
1898 EXPECT_TRUE(parser->Parse(packet, length, &header));
1899 dropped_rtp_packet_ = header.sequenceNumber;
1900 return DROP_PACKET;
1901 }
1902 VerifyStats();
1903 return SEND_PACKET;
1904 }
1905
1906 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08001907 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02001908 test::RtcpPacketParser rtcp_parser;
1909 rtcp_parser.Parse(packet, length);
1910 std::vector<uint16_t> nacks = rtcp_parser.nack_item()->last_nack_list();
1911 if (!nacks.empty() && std::find(
1912 nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) {
1913 dropped_rtp_packet_requested_ = true;
1914 }
1915 return SEND_PACKET;
1916 }
1917
stefan608213e2015-11-01 14:56:10 -08001918 void VerifyStats() EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
Åsa Persson352b2d72015-04-15 18:00:40 +02001919 if (!dropped_rtp_packet_requested_)
1920 return;
1921 int send_stream_nack_packets = 0;
1922 int receive_stream_nack_packets = 0;
1923 VideoSendStream::Stats stats = send_stream_->GetStats();
1924 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
1925 stats.substreams.begin(); it != stats.substreams.end(); ++it) {
1926 const VideoSendStream::StreamStats& stream_stats = it->second;
1927 send_stream_nack_packets +=
1928 stream_stats.rtcp_packet_type_counts.nack_packets;
1929 }
1930 for (size_t i = 0; i < receive_streams_.size(); ++i) {
1931 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
1932 receive_stream_nack_packets +=
1933 stats.rtcp_packet_type_counts.nack_packets;
1934 }
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001935 if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) {
Åsa Persson352b2d72015-04-15 18:00:40 +02001936 // NACK packet sent on receive stream and received on sent stream.
1937 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01001938 observation_complete_.Set();
Åsa Persson352b2d72015-04-15 18:00:40 +02001939 }
1940 }
1941
1942 bool MinMetricRunTimePassed() {
1943 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
1944 if (start_runtime_ms_ == -1) {
1945 start_runtime_ms_ = now;
1946 return false;
1947 }
1948 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
1949 return elapsed_sec > metrics::kMinRunTimeInSeconds;
1950 }
1951
stefanff483612015-12-21 03:14:00 -08001952 void ModifyVideoConfigs(
1953 VideoSendStream::Config* send_config,
1954 std::vector<VideoReceiveStream::Config>* receive_configs,
1955 VideoEncoderConfig* encoder_config) override {
Åsa Persson352b2d72015-04-15 18:00:40 +02001956 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1957 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1958 }
1959
stefanff483612015-12-21 03:14:00 -08001960 void OnVideoStreamsCreated(
Åsa Persson352b2d72015-04-15 18:00:40 +02001961 VideoSendStream* send_stream,
1962 const std::vector<VideoReceiveStream*>& receive_streams) override {
1963 send_stream_ = send_stream;
1964 receive_streams_ = receive_streams;
1965 }
1966
1967 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001968 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson352b2d72015-04-15 18:00:40 +02001969 }
1970
stefan608213e2015-11-01 14:56:10 -08001971 rtc::CriticalSection crit_;
Åsa Persson352b2d72015-04-15 18:00:40 +02001972 uint64_t sent_rtp_packets_;
stefan608213e2015-11-01 14:56:10 -08001973 uint16_t dropped_rtp_packet_ GUARDED_BY(&crit_);
1974 bool dropped_rtp_packet_requested_ GUARDED_BY(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02001975 std::vector<VideoReceiveStream*> receive_streams_;
1976 VideoSendStream* send_stream_;
1977 int64_t start_runtime_ms_;
1978 } test;
1979
Åsa Persson3c391cb2015-04-27 10:09:49 +02001980 test::ClearHistograms();
stefane74eef12016-01-08 06:47:13 -08001981 RunBaseTest(&test);
Åsa Persson352b2d72015-04-15 18:00:40 +02001982
Åsa Persson3c391cb2015-04-27 10:09:49 +02001983 EXPECT_EQ(1, test::NumHistogramSamples(
Åsa Persson352b2d72015-04-15 18:00:40 +02001984 "WebRTC.Video.UniqueNackRequestsSentInPercent"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02001985 EXPECT_EQ(1, test::NumHistogramSamples(
Åsa Persson352b2d72015-04-15 18:00:40 +02001986 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
1987 EXPECT_GT(test::LastHistogramSample(
1988 "WebRTC.Video.NackPacketsSentPerMinute"), 0);
1989 EXPECT_GT(test::LastHistogramSample(
1990 "WebRTC.Video.NackPacketsReceivedPerMinute"), 0);
1991}
1992
sprangb4a1ae52015-12-03 08:10:08 -08001993void EndToEndTest::VerifyHistogramStats(bool use_rtx,
1994 bool use_red,
1995 bool screenshare) {
stefanf116bd02015-10-27 08:29:42 -07001996 class StatsObserver : public test::EndToEndTest {
Åsa Persson3c391cb2015-04-27 10:09:49 +02001997 public:
sprangb4a1ae52015-12-03 08:10:08 -08001998 StatsObserver(bool use_rtx, bool use_red, bool screenshare)
Åsa Persson3c391cb2015-04-27 10:09:49 +02001999 : EndToEndTest(kLongTimeoutMs),
2000 use_rtx_(use_rtx),
2001 use_red_(use_red),
sprangb4a1ae52015-12-03 08:10:08 -08002002 screenshare_(screenshare),
Peter Boström39593972016-02-15 11:27:15 +01002003 // This test uses NACK, so to send FEC we can't use a fake encoder.
2004 vp8_encoder_(
2005 use_red ? VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)
2006 : nullptr),
Åsa Persson3c391cb2015-04-27 10:09:49 +02002007 sender_call_(nullptr),
2008 receiver_call_(nullptr),
2009 start_runtime_ms_(-1) {}
2010
2011 private:
2012 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2013 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002014 observation_complete_.Set();
Åsa Persson3c391cb2015-04-27 10:09:49 +02002015
stefanf116bd02015-10-27 08:29:42 -07002016 return SEND_PACKET;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002017 }
2018
2019 bool MinMetricRunTimePassed() {
2020 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2021 if (start_runtime_ms_ == -1) {
2022 start_runtime_ms_ = now;
2023 return false;
2024 }
2025 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2026 return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
2027 }
2028
stefanff483612015-12-21 03:14:00 -08002029 void ModifyVideoConfigs(
2030 VideoSendStream::Config* send_config,
2031 std::vector<VideoReceiveStream::Config>* receive_configs,
2032 VideoEncoderConfig* encoder_config) override {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002033 // NACK
2034 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2035 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2036 // FEC
2037 if (use_red_) {
2038 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
2039 send_config->rtp.fec.red_payload_type = kRedPayloadType;
Peter Boström39593972016-02-15 11:27:15 +01002040 send_config->encoder_settings.encoder = vp8_encoder_.get();
2041 send_config->encoder_settings.payload_name = "VP8";
2042 (*receive_configs)[0].decoders[0].payload_name = "VP8";
Åsa Persson3c391cb2015-04-27 10:09:49 +02002043 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
2044 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
2045 }
2046 // RTX
2047 if (use_rtx_) {
2048 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
2049 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002050 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002051 kSendRtxSsrcs[0];
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002052 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002053 kSendRtxPayloadType;
2054 }
sprangb4a1ae52015-12-03 08:10:08 -08002055 encoder_config->content_type =
2056 screenshare_ ? VideoEncoderConfig::ContentType::kScreen
2057 : VideoEncoderConfig::ContentType::kRealtimeVideo;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002058 }
2059
2060 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2061 sender_call_ = sender_call;
2062 receiver_call_ = receiver_call;
2063 }
2064
Åsa Persson3c391cb2015-04-27 10:09:49 +02002065 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002066 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson3c391cb2015-04-27 10:09:49 +02002067 }
2068
sprangb4a1ae52015-12-03 08:10:08 -08002069 const bool use_rtx_;
2070 const bool use_red_;
2071 const bool screenshare_;
kwiberg27f982b2016-03-01 11:52:33 -08002072 const std::unique_ptr<VideoEncoder> vp8_encoder_;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002073 Call* sender_call_;
2074 Call* receiver_call_;
2075 int64_t start_runtime_ms_;
sprangb4a1ae52015-12-03 08:10:08 -08002076 } test(use_rtx, use_red, screenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002077
2078 test::ClearHistograms();
stefane74eef12016-01-08 06:47:13 -08002079 RunBaseTest(&test);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002080
stefan91d92602015-11-11 10:13:02 -08002081 // Delete the call for Call stats to be reported.
stefan18adf0a2015-11-17 06:24:56 -08002082 sender_call_.reset();
stefan91d92602015-11-11 10:13:02 -08002083 receiver_call_.reset();
2084
sprangb4a1ae52015-12-03 08:10:08 -08002085 std::string video_prefix =
2086 screenshare ? "WebRTC.Video.Screenshare." : "WebRTC.Video.";
2087
Åsa Persson3c391cb2015-04-27 10:09:49 +02002088 // Verify that stats have been updated once.
stefan91d92602015-11-11 10:13:02 -08002089 EXPECT_EQ(
2090 1, test::NumHistogramSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
2091 EXPECT_EQ(1,
2092 test::NumHistogramSamples("WebRTC.Call.RtcpBitrateReceivedInBps"));
2093 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Call.BitrateReceivedInKbps"));
stefan18adf0a2015-11-17 06:24:56 -08002094 EXPECT_EQ(
2095 1, test::NumHistogramSamples("WebRTC.Call.EstimatedSendBitrateInKbps"));
2096 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Call.PacerBitrateInKbps"));
stefan91d92602015-11-11 10:13:02 -08002097
Åsa Persson3c391cb2015-04-27 10:09:49 +02002098 EXPECT_EQ(1, test::NumHistogramSamples(
2099 "WebRTC.Video.NackPacketsSentPerMinute"));
sprang07fb9be2016-02-24 07:55:00 -08002100 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix +
2101 "NackPacketsReceivedPerMinute"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002102 EXPECT_EQ(1, test::NumHistogramSamples(
2103 "WebRTC.Video.FirPacketsSentPerMinute"));
sprang07fb9be2016-02-24 07:55:00 -08002104 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix +
2105 "FirPacketsReceivedPerMinute"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002106 EXPECT_EQ(1, test::NumHistogramSamples(
2107 "WebRTC.Video.PliPacketsSentPerMinute"));
sprang07fb9be2016-02-24 07:55:00 -08002108 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix +
2109 "PliPacketsReceivedPerMinute"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002110
sprangb4a1ae52015-12-03 08:10:08 -08002111 EXPECT_EQ(
2112 1, test::NumHistogramSamples(video_prefix + "KeyFramesSentInPermille"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002113 EXPECT_EQ(1, test::NumHistogramSamples(
2114 "WebRTC.Video.KeyFramesReceivedInPermille"));
2115
sprange2d83d62016-02-19 09:03:26 -08002116 EXPECT_EQ(
2117 1, test::NumHistogramSamples(video_prefix + "SentPacketsLostInPercent"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002118 EXPECT_EQ(1, test::NumHistogramSamples(
2119 "WebRTC.Video.ReceivedPacketsLostInPercent"));
2120
sprangb4a1ae52015-12-03 08:10:08 -08002121 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "InputWidthInPixels"));
2122 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "InputHeightInPixels"));
2123 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SentWidthInPixels"));
2124 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SentHeightInPixels"));
asaperssond89920b2015-07-22 06:52:00 -07002125 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.ReceivedWidthInPixels"));
2126 EXPECT_EQ(1,
2127 test::NumHistogramSamples("WebRTC.Video.ReceivedHeightInPixels"));
2128
stefanff483612015-12-21 03:14:00 -08002129 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].width),
sprangb4a1ae52015-12-03 08:10:08 -08002130 test::LastHistogramSample(video_prefix + "InputWidthInPixels"));
stefanff483612015-12-21 03:14:00 -08002131 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].height),
sprangb4a1ae52015-12-03 08:10:08 -08002132 test::LastHistogramSample(video_prefix + "InputHeightInPixels"));
stefanff483612015-12-21 03:14:00 -08002133 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].width),
sprangb4a1ae52015-12-03 08:10:08 -08002134 test::LastHistogramSample(video_prefix + "SentWidthInPixels"));
stefanff483612015-12-21 03:14:00 -08002135 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].height),
sprangb4a1ae52015-12-03 08:10:08 -08002136 test::LastHistogramSample(video_prefix + "SentHeightInPixels"));
stefanff483612015-12-21 03:14:00 -08002137 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].width),
asaperssond89920b2015-07-22 06:52:00 -07002138 test::LastHistogramSample("WebRTC.Video.ReceivedWidthInPixels"));
stefanff483612015-12-21 03:14:00 -08002139 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].height),
asaperssond89920b2015-07-22 06:52:00 -07002140 test::LastHistogramSample("WebRTC.Video.ReceivedHeightInPixels"));
2141
sprangb4a1ae52015-12-03 08:10:08 -08002142 EXPECT_EQ(1,
2143 test::NumHistogramSamples(video_prefix + "InputFramesPerSecond"));
2144 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SentFramesPerSecond"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002145 EXPECT_EQ(1, test::NumHistogramSamples(
2146 "WebRTC.Video.DecodedFramesPerSecond"));
asaperssond89920b2015-07-22 06:52:00 -07002147 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.RenderFramesPerSecond"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002148
asapersson8688a4e2016-04-27 23:42:35 -07002149 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.JitterBufferDelayInMs"));
2150 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.TargetDelayInMs"));
2151 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.CurrentDelayInMs"));
asapersson6f14be82015-11-16 00:40:49 -08002152 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.OnewayDelayInMs"));
2153 EXPECT_EQ(
2154 1, test::NumHistogramSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
2155
sprangb4a1ae52015-12-03 08:10:08 -08002156 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "EncodeTimeInMs"));
asapersson6718e972015-07-24 00:20:58 -07002157 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.DecodeTimeInMs"));
2158
Erik Språng22c2b482016-03-01 09:40:42 +01002159 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "BitrateSentInKbps"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002160 EXPECT_EQ(1, test::NumHistogramSamples(
2161 "WebRTC.Video.BitrateReceivedInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002162 EXPECT_EQ(1,
2163 test::NumHistogramSamples(video_prefix + "MediaBitrateSentInKbps"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002164 EXPECT_EQ(1, test::NumHistogramSamples(
2165 "WebRTC.Video.MediaBitrateReceivedInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002166 EXPECT_EQ(
2167 1, test::NumHistogramSamples(video_prefix + "PaddingBitrateSentInKbps"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002168 EXPECT_EQ(1, test::NumHistogramSamples(
2169 "WebRTC.Video.PaddingBitrateReceivedInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002170 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix +
2171 "RetransmittedBitrateSentInKbps"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002172 EXPECT_EQ(1, test::NumHistogramSamples(
2173 "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
2174
sprangb4a1ae52015-12-03 08:10:08 -08002175 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SendSideDelayInMs"));
2176 EXPECT_EQ(1,
2177 test::NumHistogramSamples(video_prefix + "SendSideDelayMaxInMs"));
asapersson35151f32016-05-02 23:44:01 -07002178 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.SendDelayInMs"));
asapersson6f14be82015-11-16 00:40:49 -08002179
Åsa Persson3c391cb2015-04-27 10:09:49 +02002180 int num_rtx_samples = use_rtx ? 1 : 0;
2181 EXPECT_EQ(num_rtx_samples, test::NumHistogramSamples(
2182 "WebRTC.Video.RtxBitrateSentInKbps"));
2183 EXPECT_EQ(num_rtx_samples, test::NumHistogramSamples(
2184 "WebRTC.Video.RtxBitrateReceivedInKbps"));
2185
2186 int num_red_samples = use_red ? 1 : 0;
2187 EXPECT_EQ(num_red_samples, test::NumHistogramSamples(
2188 "WebRTC.Video.FecBitrateSentInKbps"));
2189 EXPECT_EQ(num_red_samples, test::NumHistogramSamples(
2190 "WebRTC.Video.FecBitrateReceivedInKbps"));
2191 EXPECT_EQ(num_red_samples, test::NumHistogramSamples(
2192 "WebRTC.Video.ReceivedFecPacketsInPercent"));
2193}
2194
2195TEST_F(EndToEndTest, VerifyHistogramStatsWithRtx) {
2196 const bool kEnabledRtx = true;
2197 const bool kEnabledRed = false;
sprangb4a1ae52015-12-03 08:10:08 -08002198 const bool kScreenshare = false;
2199 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002200}
2201
2202TEST_F(EndToEndTest, VerifyHistogramStatsWithRed) {
2203 const bool kEnabledRtx = false;
2204 const bool kEnabledRed = true;
sprangb4a1ae52015-12-03 08:10:08 -08002205 const bool kScreenshare = false;
2206 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
2207}
2208
2209TEST_F(EndToEndTest, VerifyHistogramStatsWithScreenshare) {
2210 const bool kEnabledRtx = false;
2211 const bool kEnabledRed = false;
2212 const bool kScreenshare = true;
2213 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002214}
2215
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002216void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
2217 static const int kNumRtcpReportPacketsToObserve = 5;
2218 class RtcpXrObserver : public test::EndToEndTest {
2219 public:
2220 explicit RtcpXrObserver(bool enable_rrtr)
2221 : EndToEndTest(kDefaultTimeoutMs),
2222 enable_rrtr_(enable_rrtr),
2223 sent_rtcp_sr_(0),
2224 sent_rtcp_rr_(0),
2225 sent_rtcp_rrtr_(0),
2226 sent_rtcp_dlrr_(0) {}
2227
2228 private:
2229 // Receive stream should send RR packets (and RRTR packets if enabled).
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002230 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002231 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002232 RTCPUtility::RTCPParserV2 parser(packet, length, true);
2233 EXPECT_TRUE(parser.IsValid());
2234
2235 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02002236 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
2237 if (packet_type == RTCPUtility::RTCPPacketTypes::kRr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002238 ++sent_rtcp_rr_;
2239 } else if (packet_type ==
Erik Språng242e22b2015-05-11 10:17:43 +02002240 RTCPUtility::RTCPPacketTypes::kXrReceiverReferenceTime) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002241 ++sent_rtcp_rrtr_;
2242 }
Erik Språng242e22b2015-05-11 10:17:43 +02002243 EXPECT_NE(packet_type, RTCPUtility::RTCPPacketTypes::kSr);
2244 EXPECT_NE(packet_type,
2245 RTCPUtility::RTCPPacketTypes::kXrDlrrReportBlockItem);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002246 packet_type = parser.Iterate();
2247 }
2248 return SEND_PACKET;
2249 }
2250 // Send stream should send SR packets (and DLRR packets if enabled).
nisseef8b61e2016-04-29 06:09:15 -07002251 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002252 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002253 RTCPUtility::RTCPParserV2 parser(packet, length, true);
2254 EXPECT_TRUE(parser.IsValid());
2255
2256 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02002257 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
2258 if (packet_type == RTCPUtility::RTCPPacketTypes::kSr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002259 ++sent_rtcp_sr_;
Erik Språng242e22b2015-05-11 10:17:43 +02002260 } else if (packet_type ==
2261 RTCPUtility::RTCPPacketTypes::kXrDlrrReportBlockItem) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002262 ++sent_rtcp_dlrr_;
2263 }
Erik Språng242e22b2015-05-11 10:17:43 +02002264 EXPECT_NE(packet_type,
2265 RTCPUtility::RTCPPacketTypes::kXrReceiverReferenceTime);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002266 packet_type = parser.Iterate();
2267 }
2268 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
2269 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve) {
2270 if (enable_rrtr_) {
2271 EXPECT_GT(sent_rtcp_rrtr_, 0);
2272 EXPECT_GT(sent_rtcp_dlrr_, 0);
2273 } else {
2274 EXPECT_EQ(0, sent_rtcp_rrtr_);
2275 EXPECT_EQ(0, sent_rtcp_dlrr_);
2276 }
Peter Boström5811a392015-12-10 13:02:50 +01002277 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002278 }
2279 return SEND_PACKET;
2280 }
2281
stefanff483612015-12-21 03:14:00 -08002282 void ModifyVideoConfigs(
2283 VideoSendStream::Config* send_config,
2284 std::vector<VideoReceiveStream::Config>* receive_configs,
2285 VideoEncoderConfig* encoder_config) override {
pbosda903ea2015-10-02 02:36:56 -07002286 (*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002287 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
2288 enable_rrtr_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002289 }
2290
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002291 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002292 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002293 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
2294 }
2295
stefan608213e2015-11-01 14:56:10 -08002296 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002297 bool enable_rrtr_;
2298 int sent_rtcp_sr_;
stefan608213e2015-11-01 14:56:10 -08002299 int sent_rtcp_rr_ GUARDED_BY(&crit_);
2300 int sent_rtcp_rrtr_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002301 int sent_rtcp_dlrr_;
2302 } test(enable_rrtr);
2303
stefane74eef12016-01-08 06:47:13 -08002304 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002305}
2306
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002307void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
2308 bool send_single_ssrc_first) {
2309 class SendsSetSsrcs : public test::EndToEndTest {
2310 public:
2311 SendsSetSsrcs(const uint32_t* ssrcs,
2312 size_t num_ssrcs,
2313 bool send_single_ssrc_first)
2314 : EndToEndTest(kDefaultTimeoutMs),
2315 num_ssrcs_(num_ssrcs),
2316 send_single_ssrc_first_(send_single_ssrc_first),
2317 ssrcs_to_observe_(num_ssrcs),
sprang867fb522015-08-03 04:38:41 -07002318 expect_single_ssrc_(send_single_ssrc_first),
2319 send_stream_(nullptr) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002320 for (size_t i = 0; i < num_ssrcs; ++i)
2321 valid_ssrcs_[ssrcs[i]] = true;
2322 }
2323
2324 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002325 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002326 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002327 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002328
2329 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
2330 << "Received unknown SSRC: " << header.ssrc;
2331
2332 if (!valid_ssrcs_[header.ssrc])
Peter Boström5811a392015-12-10 13:02:50 +01002333 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002334
2335 if (!is_observed_[header.ssrc]) {
2336 is_observed_[header.ssrc] = true;
2337 --ssrcs_to_observe_;
2338 if (expect_single_ssrc_) {
2339 expect_single_ssrc_ = false;
Peter Boström5811a392015-12-10 13:02:50 +01002340 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002341 }
2342 }
2343
2344 if (ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002345 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002346
2347 return SEND_PACKET;
2348 }
2349
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002350 size_t GetNumVideoStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002351
stefanff483612015-12-21 03:14:00 -08002352 void ModifyVideoConfigs(
2353 VideoSendStream::Config* send_config,
2354 std::vector<VideoReceiveStream::Config>* receive_configs,
2355 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002356 if (num_ssrcs_ > 1) {
2357 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002358 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2359 encoder_config->streams[i].min_bitrate_bps = 10000;
2360 encoder_config->streams[i].target_bitrate_bps = 15000;
2361 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002362 }
2363 }
2364
stefanff483612015-12-21 03:14:00 -08002365 video_encoder_config_all_streams_ = *encoder_config;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002366 if (send_single_ssrc_first_)
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002367 encoder_config->streams.resize(1);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002368 }
2369
stefanff483612015-12-21 03:14:00 -08002370 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002371 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002372 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002373 send_stream_ = send_stream;
2374 }
2375
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002376 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002377 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2378 << (send_single_ssrc_first_ ? "first SSRC."
2379 : "SSRCs.");
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002380
2381 if (send_single_ssrc_first_) {
2382 // Set full simulcast and continue with the rest of the SSRCs.
stefanff483612015-12-21 03:14:00 -08002383 send_stream_->ReconfigureVideoEncoder(
2384 video_encoder_config_all_streams_);
Peter Boström5811a392015-12-10 13:02:50 +01002385 EXPECT_TRUE(Wait()) << "Timed out while waiting on additional SSRCs.";
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002386 }
2387 }
2388
2389 private:
2390 std::map<uint32_t, bool> valid_ssrcs_;
2391 std::map<uint32_t, bool> is_observed_;
2392
2393 const size_t num_ssrcs_;
2394 const bool send_single_ssrc_first_;
2395
2396 size_t ssrcs_to_observe_;
2397 bool expect_single_ssrc_;
2398
2399 VideoSendStream* send_stream_;
stefanff483612015-12-21 03:14:00 -08002400 VideoEncoderConfig video_encoder_config_all_streams_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002401 } test(kVideoSendSsrcs, num_ssrcs, send_single_ssrc_first);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002402
stefane74eef12016-01-08 06:47:13 -08002403 RunBaseTest(&test);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002404}
2405
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002406TEST_F(EndToEndTest, ReportsSetEncoderRates) {
2407 class EncoderRateStatsTest : public test::EndToEndTest,
2408 public test::FakeEncoder {
2409 public:
2410 EncoderRateStatsTest()
2411 : EndToEndTest(kDefaultTimeoutMs),
sprang867fb522015-08-03 04:38:41 -07002412 FakeEncoder(Clock::GetRealTimeClock()),
2413 send_stream_(nullptr),
2414 bitrate_kbps_(0) {}
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002415
stefanff483612015-12-21 03:14:00 -08002416 void OnVideoStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002417 VideoSendStream* send_stream,
2418 const std::vector<VideoReceiveStream*>& receive_streams) override {
2419 send_stream_ = send_stream;
2420 }
2421
stefanff483612015-12-21 03:14:00 -08002422 void ModifyVideoConfigs(
2423 VideoSendStream::Config* send_config,
2424 std::vector<VideoReceiveStream::Config>* receive_configs,
2425 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002426 send_config->encoder_settings.encoder = this;
2427 }
2428
2429 int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override {
2430 // Make sure not to trigger on any default zero bitrates.
2431 if (new_target_bitrate == 0)
2432 return 0;
Peter Boströmf2f82832015-05-01 13:00:41 +02002433 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002434 bitrate_kbps_ = new_target_bitrate;
Peter Boström5811a392015-12-10 13:02:50 +01002435 observation_complete_.Set();
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002436 return 0;
2437 }
2438
2439 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002440 ASSERT_TRUE(Wait())
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002441 << "Timed out while waiting for encoder SetRates() call.";
2442 // Wait for GetStats to report a corresponding bitrate.
Peter Boström5811a392015-12-10 13:02:50 +01002443 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002444 VideoSendStream::Stats stats = send_stream_->GetStats();
2445 {
Peter Boströmf2f82832015-05-01 13:00:41 +02002446 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002447 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
2448 static_cast<int>(bitrate_kbps_)) {
2449 return;
2450 }
2451 }
2452 SleepMs(1);
2453 }
2454 FAIL()
2455 << "Timed out waiting for stats reporting the currently set bitrate.";
2456 }
2457
2458 private:
stefanf116bd02015-10-27 08:29:42 -07002459 rtc::CriticalSection crit_;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002460 VideoSendStream* send_stream_;
2461 uint32_t bitrate_kbps_ GUARDED_BY(crit_);
2462 } test;
2463
stefane74eef12016-01-08 06:47:13 -08002464 RunBaseTest(&test);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002465}
2466
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002467TEST_F(EndToEndTest, GetStats) {
2468 static const int kStartBitrateBps = 3000000;
Peter Boströmdef398832015-05-27 17:59:11 +02002469 static const int kExpectedRenderDelayMs = 20;
nissed30a1112016-04-18 05:15:22 -07002470 class StatsObserver : public test::EndToEndTest,
2471 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002472 public:
stefanf116bd02015-10-27 08:29:42 -07002473 StatsObserver()
2474 : EndToEndTest(kLongTimeoutMs),
Peter Boströmc6e16e32016-02-05 14:15:53 +01002475 encoder_(Clock::GetRealTimeClock(), 10),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002476 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002477 expected_send_ssrcs_(),
Peter Boström5811a392015-12-10 13:02:50 +01002478 check_stats_event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002479
2480 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002481 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002482 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002483 return SEND_PACKET;
2484 }
2485
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002486 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002487 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002488 return SEND_PACKET;
2489 }
2490
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002491 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002492 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002493 return SEND_PACKET;
2494 }
2495
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002496 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002497 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002498 return SEND_PACKET;
2499 }
2500
nissed30a1112016-04-18 05:15:22 -07002501 void OnFrame(const VideoFrame& video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002502 // Ensure that we have at least 5ms send side delay.
nissed30a1112016-04-18 05:15:22 -07002503 SleepMs(5);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002504 }
2505
2506 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002507 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2508 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2509 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002510
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002511 // Make sure all fields have been populated.
2512 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
2513 // always filled for all receivers.
2514 receive_stats_filled_["IncomingRate"] |=
2515 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002516
Peter Boströmb7d9a972015-12-18 16:01:11 +01002517 send_stats_filled_["DecoderImplementationName"] |=
2518 stats.decoder_implementation_name ==
2519 test::FakeDecoder::kImplementationName;
Peter Boströmdef398832015-05-27 17:59:11 +02002520 receive_stats_filled_["RenderDelayAsHighAsExpected"] |=
2521 stats.render_delay_ms >= kExpectedRenderDelayMs;
2522
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002523 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002524
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002525 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002526
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002527 receive_stats_filled_["StatisticsUpdated"] |=
2528 stats.rtcp_stats.cumulative_lost != 0 ||
2529 stats.rtcp_stats.extended_max_sequence_number != 0 ||
2530 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002531
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002532 receive_stats_filled_["DataCountersUpdated"] |=
2533 stats.rtp_stats.transmitted.payload_bytes != 0 ||
2534 stats.rtp_stats.fec.packets != 0 ||
2535 stats.rtp_stats.transmitted.header_bytes != 0 ||
2536 stats.rtp_stats.transmitted.packets != 0 ||
2537 stats.rtp_stats.transmitted.padding_bytes != 0 ||
2538 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002539
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002540 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002541 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002542
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002543 receive_stats_filled_["FrameCounts"] |=
2544 stats.frame_counts.key_frames != 0 ||
2545 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002546
pbosbb36fdf2015-07-09 07:48:14 -07002547 receive_stats_filled_["CName"] |= !stats.c_name.empty();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002548
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002549 receive_stats_filled_["RtcpPacketTypeCount"] |=
2550 stats.rtcp_packet_type_counts.fir_packets != 0 ||
2551 stats.rtcp_packet_type_counts.nack_packets != 0 ||
2552 stats.rtcp_packet_type_counts.pli_packets != 0 ||
2553 stats.rtcp_packet_type_counts.nack_requests != 0 ||
2554 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbosf42376c2015-08-28 07:35:32 -07002555
2556 assert(stats.current_payload_type == -1 ||
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002557 stats.current_payload_type == kFakeVideoSendPayloadType);
pbosf42376c2015-08-28 07:35:32 -07002558 receive_stats_filled_["IncomingPayloadType"] |=
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002559 stats.current_payload_type == kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002560 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002561
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002562 return AllStatsFilled(receive_stats_filled_);
2563 }
2564
2565 bool CheckSendStats() {
Peter Boström74f6e9e2016-04-04 17:56:10 +02002566 RTC_DCHECK(send_stream_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002567 VideoSendStream::Stats stats = send_stream_->GetStats();
2568
2569 send_stats_filled_["NumStreams"] |=
2570 stats.substreams.size() == expected_send_ssrcs_.size();
2571
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002572 send_stats_filled_["CpuOveruseMetrics"] |=
Peter Boströme4499152016-02-05 11:13:28 +01002573 stats.avg_encode_time_ms != 0 && stats.encode_usage_percent != 0;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002574
Peter Boströmb7d9a972015-12-18 16:01:11 +01002575 send_stats_filled_["EncoderImplementationName"] |=
2576 stats.encoder_implementation_name ==
2577 test::FakeEncoder::kImplementationName;
2578
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002579 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002580 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002581 it != stats.substreams.end(); ++it) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002582 EXPECT_TRUE(expected_send_ssrcs_.find(it->first) !=
2583 expected_send_ssrcs_.end());
2584
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002585 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002586 stats.input_frame_rate != 0;
2587
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002588 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002589
2590 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
2591 stream_stats.rtcp_stats.cumulative_lost != 0 ||
2592 stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
2593 stream_stats.rtcp_stats.fraction_lost != 0;
2594
2595 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002596 stream_stats.rtp_stats.fec.packets != 0 ||
2597 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
2598 stream_stats.rtp_stats.retransmitted.packets != 0 ||
2599 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002600
2601 send_stats_filled_[CompoundKey("BitrateStatisticsObserver",
2602 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002603 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002604
2605 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002606 stream_stats.frame_counts.delta_frames != 0 ||
2607 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002608
2609 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
2610 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00002611
2612 send_stats_filled_[CompoundKey("Delay", it->first)] |=
2613 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002614
2615 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
2616 // report dropped packets.
2617 send_stats_filled_["RtcpPacketTypeCount"] |=
2618 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
2619 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
2620 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
2621 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
2622 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002623 }
2624
2625 return AllStatsFilled(send_stats_filled_);
2626 }
2627
2628 std::string CompoundKey(const char* name, uint32_t ssrc) {
2629 std::ostringstream oss;
2630 oss << name << "_" << ssrc;
2631 return oss.str();
2632 }
2633
2634 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
2635 for (std::map<std::string, bool>::const_iterator it = stats_map.begin();
2636 it != stats_map.end();
2637 ++it) {
2638 if (!it->second)
2639 return false;
2640 }
2641 return true;
2642 }
2643
stefane74eef12016-01-08 06:47:13 -08002644 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
2645 FakeNetworkPipe::Config network_config;
2646 network_config.loss_percent = 5;
2647 return new test::PacketTransport(
2648 sender_call, this, test::PacketTransport::kSender, network_config);
2649 }
2650
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002651 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002652 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01002653 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002654 return config;
2655 }
2656
stefanff483612015-12-21 03:14:00 -08002657 void ModifyVideoConfigs(
2658 VideoSendStream::Config* send_config,
2659 std::vector<VideoReceiveStream::Config>* receive_configs,
2660 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002661 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002662 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002663
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002664 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002665 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002666 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002667 expected_receive_ssrcs_.push_back(
2668 (*receive_configs)[i].rtp.remote_ssrc);
Peter Boströmdef398832015-05-27 17:59:11 +02002669 (*receive_configs)[i].render_delay_ms = kExpectedRenderDelayMs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002670 }
Peter Boströmc6e16e32016-02-05 14:15:53 +01002671 // Use a delayed encoder to make sure we see CpuOveruseMetrics stats that
2672 // are non-zero.
2673 send_config->encoder_settings.encoder = &encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002674 }
2675
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002676 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00002677
stefanff483612015-12-21 03:14:00 -08002678 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002679 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002680 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002681 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002682 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002683 }
2684
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002685 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002686 Clock* clock = Clock::GetRealTimeClock();
2687 int64_t now = clock->TimeInMilliseconds();
2688 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
2689 bool receive_ok = false;
2690 bool send_ok = false;
2691
2692 while (now < stop_time) {
2693 if (!receive_ok)
2694 receive_ok = CheckReceiveStats();
2695 if (!send_ok)
2696 send_ok = CheckSendStats();
2697
2698 if (receive_ok && send_ok)
2699 return;
2700
2701 int64_t time_until_timout_ = stop_time - now;
2702 if (time_until_timout_ > 0)
Peter Boström5811a392015-12-10 13:02:50 +01002703 check_stats_event_.Wait(time_until_timout_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002704 now = clock->TimeInMilliseconds();
2705 }
2706
2707 ADD_FAILURE() << "Timed out waiting for filled stats.";
2708 for (std::map<std::string, bool>::const_iterator it =
2709 receive_stats_filled_.begin();
2710 it != receive_stats_filled_.end();
2711 ++it) {
2712 if (!it->second) {
2713 ADD_FAILURE() << "Missing receive stats: " << it->first;
2714 }
2715 }
2716
2717 for (std::map<std::string, bool>::const_iterator it =
2718 send_stats_filled_.begin();
2719 it != send_stats_filled_.end();
2720 ++it) {
2721 if (!it->second) {
2722 ADD_FAILURE() << "Missing send stats: " << it->first;
2723 }
2724 }
2725 }
2726
Peter Boströmc6e16e32016-02-05 14:15:53 +01002727 test::DelayedEncoder encoder_;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002728 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002729 std::map<std::string, bool> receive_stats_filled_;
2730
2731 VideoSendStream* send_stream_;
2732 std::map<std::string, bool> send_stats_filled_;
2733
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002734 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002735 std::set<uint32_t> expected_send_ssrcs_;
2736 std::string expected_cname_;
2737
Peter Boström5811a392015-12-10 13:02:50 +01002738 rtc::Event check_stats_event_;
stefanf116bd02015-10-27 08:29:42 -07002739 } test;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002740
stefane74eef12016-01-08 06:47:13 -08002741 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002742}
2743
2744TEST_F(EndToEndTest, ReceiverReferenceTimeReportEnabled) {
2745 TestXrReceiverReferenceTimeReport(true);
2746}
2747
2748TEST_F(EndToEndTest, ReceiverReferenceTimeReportDisabled) {
2749 TestXrReceiverReferenceTimeReport(false);
2750}
2751
2752TEST_F(EndToEndTest, TestReceivedRtpPacketStats) {
2753 static const size_t kNumRtpPacketsToSend = 5;
2754 class ReceivedRtpStatsObserver : public test::EndToEndTest {
2755 public:
2756 ReceivedRtpStatsObserver()
2757 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002758 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002759 sent_rtp_(0) {}
2760
2761 private:
stefanff483612015-12-21 03:14:00 -08002762 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002763 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002764 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002765 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002766 }
2767
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002768 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002769 if (sent_rtp_ >= kNumRtpPacketsToSend) {
2770 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002771 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
Peter Boström5811a392015-12-10 13:02:50 +01002772 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002773 }
2774 return DROP_PACKET;
2775 }
2776 ++sent_rtp_;
2777 return SEND_PACKET;
2778 }
2779
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002780 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002781 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002782 << "Timed out while verifying number of received RTP packets.";
2783 }
2784
2785 VideoReceiveStream* receive_stream_;
2786 uint32_t sent_rtp_;
2787 } test;
2788
stefane74eef12016-01-08 06:47:13 -08002789 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002790}
2791
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002792TEST_F(EndToEndTest, SendsSetSsrc) { TestSendsSetSsrcs(1, false); }
2793
2794TEST_F(EndToEndTest, SendsSetSimulcastSsrcs) {
2795 TestSendsSetSsrcs(kNumSsrcs, false);
2796}
2797
2798TEST_F(EndToEndTest, CanSwitchToUseAllSsrcs) {
2799 TestSendsSetSsrcs(kNumSsrcs, true);
2800}
2801
mflodman@webrtc.orgf9460682014-07-24 16:41:25 +00002802TEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002803 class ObserveRedundantPayloads: public test::EndToEndTest {
2804 public:
2805 ObserveRedundantPayloads()
2806 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00002807 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002808 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
2809 }
2810 }
2811
2812 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002813 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002814 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002815 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002816
2817 if (!registered_rtx_ssrc_[header.ssrc])
2818 return SEND_PACKET;
2819
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002820 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002821 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002822 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002823
2824 if (!packet_is_redundant_payload)
2825 return SEND_PACKET;
2826
2827 if (!observed_redundant_retransmission_[header.ssrc]) {
2828 observed_redundant_retransmission_[header.ssrc] = true;
2829 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002830 observation_complete_.Set();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002831 }
2832
2833 return SEND_PACKET;
2834 }
2835
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002836 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002837
stefanff483612015-12-21 03:14:00 -08002838 void ModifyVideoConfigs(
2839 VideoSendStream::Config* send_config,
2840 std::vector<VideoReceiveStream::Config>* receive_configs,
2841 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002842 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002843 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2844 encoder_config->streams[i].min_bitrate_bps = 10000;
2845 encoder_config->streams[i].target_bitrate_bps = 15000;
2846 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002847 }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002848
2849 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002850
2851 for (size_t i = 0; i < kNumSsrcs; ++i)
2852 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00002853
2854 // Significantly higher than max bitrates for all video streams -> forcing
2855 // padding to trigger redundant padding on all RTX SSRCs.
2856 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002857 }
2858
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002859 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002860 EXPECT_TRUE(Wait())
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002861 << "Timed out while waiting for redundant payloads on all SSRCs.";
2862 }
2863
2864 private:
2865 size_t ssrcs_to_observe_;
2866 std::map<uint32_t, bool> observed_redundant_retransmission_;
2867 std::map<uint32_t, bool> registered_rtx_ssrc_;
2868 } test;
2869
stefane74eef12016-01-08 06:47:13 -08002870 RunBaseTest(&test);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002871}
2872
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002873void EndToEndTest::TestRtpStatePreservation(bool use_rtx) {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002874 class RtpSequenceObserver : public test::RtpRtcpObserver {
2875 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00002876 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002877 : test::RtpRtcpObserver(kDefaultTimeoutMs),
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002878 ssrcs_to_observe_(kNumSsrcs) {
2879 for (size_t i = 0; i < kNumSsrcs; ++i) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002880 configured_ssrcs_[kVideoSendSsrcs[i]] = true;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002881 if (use_rtx)
2882 configured_ssrcs_[kSendRtxSsrcs[i]] = true;
2883 }
2884 }
2885
2886 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
Peter Boströmf2f82832015-05-01 13:00:41 +02002887 rtc::CritScope lock(&crit_);
danilchap34877ee2016-02-01 08:25:04 -08002888 ssrc_observed_.clear();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002889 ssrcs_to_observe_ = num_expected_ssrcs;
2890 }
2891
2892 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002893 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002894 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002895 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002896 const uint32_t ssrc = header.ssrc;
danilchap5c35cf92016-02-03 14:14:49 -08002897 const int64_t sequence_number =
2898 seq_numbers_unwrapper_.Unwrap(header.sequenceNumber);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002899 const uint32_t timestamp = header.timestamp;
danilchap34877ee2016-02-01 08:25:04 -08002900 const bool only_padding =
2901 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002902
2903 EXPECT_TRUE(configured_ssrcs_[ssrc])
2904 << "Received SSRC that wasn't configured: " << ssrc;
2905
danilchap5c35cf92016-02-03 14:14:49 -08002906 static const int64_t kMaxSequenceNumberGap = 100;
2907 std::list<int64_t>* seq_numbers = &last_observed_seq_numbers_[ssrc];
2908 if (seq_numbers->empty()) {
2909 seq_numbers->push_back(sequence_number);
2910 } else {
2911 // We shouldn't get replays of previous sequence numbers.
2912 for (int64_t observed : *seq_numbers) {
2913 EXPECT_NE(observed, sequence_number)
2914 << "Received sequence number " << sequence_number
2915 << " for SSRC " << ssrc << " 2nd time.";
2916 }
2917 // Verify sequence numbers are reasonably close.
2918 int64_t latest_observed = seq_numbers->back();
2919 int64_t sequence_number_gap = sequence_number - latest_observed;
2920 EXPECT_LE(std::abs(sequence_number_gap), kMaxSequenceNumberGap)
2921 << "Gap in sequence numbers (" << latest_observed << " -> "
2922 << sequence_number << ") too large for SSRC: " << ssrc << ".";
2923 seq_numbers->push_back(sequence_number);
2924 if (seq_numbers->size() >= kMaxSequenceNumberGap) {
2925 seq_numbers->pop_front();
2926 }
2927 }
2928
2929 static const int32_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
2930 auto timestamp_it = last_observed_timestamp_.find(ssrc);
2931 if (timestamp_it == last_observed_timestamp_.end()) {
danilchap34877ee2016-02-01 08:25:04 -08002932 last_observed_timestamp_[ssrc] = timestamp;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002933 } else {
danilchap5c35cf92016-02-03 14:14:49 -08002934 // Verify timestamps are reasonably close.
2935 uint32_t latest_observed = timestamp_it->second;
Honghai Zhang82d78622016-05-06 11:29:15 -07002936 // Wraparound handling is unnecessary here as long as an int variable
2937 // is used to store the result.
2938 int32_t timestamp_gap = timestamp - latest_observed;
danilchap5c35cf92016-02-03 14:14:49 -08002939 EXPECT_LE(std::abs(timestamp_gap), kMaxTimestampGap)
2940 << "Gap in timestamps (" << latest_observed << " -> "
2941 << timestamp << ") too large for SSRC: " << ssrc << ".";
2942 timestamp_it->second = timestamp;
danilchapf4b9c772016-01-28 06:14:24 -08002943 }
danilchap34877ee2016-02-01 08:25:04 -08002944
2945 rtc::CritScope lock(&crit_);
2946 // Wait for media packets on all ssrcs.
2947 if (!ssrc_observed_[ssrc] && !only_padding) {
2948 ssrc_observed_[ssrc] = true;
2949 if (--ssrcs_to_observe_ == 0)
2950 observation_complete_.Set();
2951 }
2952
danilchapf4b9c772016-01-28 06:14:24 -08002953 return SEND_PACKET;
2954 }
2955
danilchap5c35cf92016-02-03 14:14:49 -08002956 SequenceNumberUnwrapper seq_numbers_unwrapper_;
2957 std::map<uint32_t, std::list<int64_t>> last_observed_seq_numbers_;
danilchap34877ee2016-02-01 08:25:04 -08002958 std::map<uint32_t, uint32_t> last_observed_timestamp_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002959 std::map<uint32_t, bool> configured_ssrcs_;
2960
Peter Boströmf2f82832015-05-01 13:00:41 +02002961 rtc::CriticalSection crit_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002962 size_t ssrcs_to_observe_ GUARDED_BY(crit_);
danilchap34877ee2016-02-01 08:25:04 -08002963 std::map<uint32_t, bool> ssrc_observed_ GUARDED_BY(crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002964 } observer(use_rtx);
2965
solenberg4fbae2b2015-08-28 04:07:10 -07002966 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002967
stefanf116bd02015-10-27 08:29:42 -07002968 test::PacketTransport send_transport(sender_call_.get(), &observer,
2969 test::PacketTransport::kSender,
2970 FakeNetworkPipe::Config());
2971 test::PacketTransport receive_transport(nullptr, &observer,
2972 test::PacketTransport::kReceiver,
2973 FakeNetworkPipe::Config());
2974 send_transport.SetReceiver(receiver_call_->Receiver());
2975 receive_transport.SetReceiver(sender_call_->Receiver());
2976
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002977 CreateSendConfig(kNumSsrcs, 0, &send_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002978
2979 if (use_rtx) {
2980 for (size_t i = 0; i < kNumSsrcs; ++i) {
stefanff483612015-12-21 03:14:00 -08002981 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002982 }
stefanff483612015-12-21 03:14:00 -08002983 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002984 }
2985
2986 // Lower bitrates so that all streams send initially.
stefanff483612015-12-21 03:14:00 -08002987 for (size_t i = 0; i < video_encoder_config_.streams.size(); ++i) {
2988 video_encoder_config_.streams[i].min_bitrate_bps = 10000;
2989 video_encoder_config_.streams[i].target_bitrate_bps = 15000;
2990 video_encoder_config_.streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002991 }
2992
pbos@webrtc.org32452b22014-10-22 12:15:24 +00002993 // Use the same total bitrates when sending a single stream to avoid lowering
2994 // the bitrate estimate and requiring a subsequent rampup.
stefanff483612015-12-21 03:14:00 -08002995 VideoEncoderConfig one_stream = video_encoder_config_;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00002996 one_stream.streams.resize(1);
stefanff483612015-12-21 03:14:00 -08002997 for (size_t i = 1; i < video_encoder_config_.streams.size(); ++i) {
pbos@webrtc.org32452b22014-10-22 12:15:24 +00002998 one_stream.streams.front().min_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08002999 video_encoder_config_.streams[i].min_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003000 one_stream.streams.front().target_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003001 video_encoder_config_.streams[i].target_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003002 one_stream.streams.front().max_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003003 video_encoder_config_.streams[i].max_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003004 }
3005
stefanf116bd02015-10-27 08:29:42 -07003006 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003007
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003008 CreateVideoStreams();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003009 CreateFrameGeneratorCapturer();
3010
3011 Start();
Peter Boström5811a392015-12-10 13:02:50 +01003012 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003013 << "Timed out waiting for all SSRCs to send packets.";
3014
3015 // Test stream resetting more than once to make sure that the state doesn't
3016 // get set once (this could be due to using std::map::insert for instance).
3017 for (size_t i = 0; i < 3; ++i) {
3018 frame_generator_capturer_->Stop();
stefanff483612015-12-21 03:14:00 -08003019 sender_call_->DestroyVideoSendStream(video_send_stream_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003020
3021 // Re-create VideoSendStream with only one stream.
stefanff483612015-12-21 03:14:00 -08003022 video_send_stream_ =
3023 sender_call_->CreateVideoSendStream(video_send_config_, one_stream);
3024 video_send_stream_->Start();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003025 CreateFrameGeneratorCapturer();
3026 frame_generator_capturer_->Start();
3027
3028 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003029 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003030
3031 // Reconfigure back to use all streams.
stefanff483612015-12-21 03:14:00 -08003032 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003033 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003034 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003035 << "Timed out waiting for all SSRCs to send packets.";
3036
3037 // Reconfigure down to one stream.
stefanff483612015-12-21 03:14:00 -08003038 video_send_stream_->ReconfigureVideoEncoder(one_stream);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003039 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003040 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003041
3042 // Reconfigure back to use all streams.
stefanff483612015-12-21 03:14:00 -08003043 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003044 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003045 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003046 << "Timed out waiting for all SSRCs to send packets.";
3047 }
3048
stefanf116bd02015-10-27 08:29:42 -07003049 send_transport.StopSending();
3050 receive_transport.StopSending();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003051
3052 Stop();
3053 DestroyStreams();
3054}
3055
Peter Boströmfc968a22016-02-19 16:14:37 +01003056TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpState) {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003057 TestRtpStatePreservation(false);
3058}
3059
3060TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpStatesWithRtx) {
3061 TestRtpStatePreservation(true);
3062}
3063
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003064TEST_F(EndToEndTest, RespectsNetworkState) {
3065 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
3066 // down blocks until no more packets will be sent.
3067
3068 // Pacer will send from its packet list and then send required padding before
3069 // checking paused_ again. This should be enough for one round of pacing,
3070 // otherwise increase.
3071 static const int kNumAcceptedDowntimeRtp = 5;
3072 // A single RTCP may be in the pipeline.
3073 static const int kNumAcceptedDowntimeRtcp = 1;
3074 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
3075 public:
3076 NetworkStateTest()
3077 : EndToEndTest(kDefaultTimeoutMs),
3078 FakeEncoder(Clock::GetRealTimeClock()),
Peter Boström5811a392015-12-10 13:02:50 +01003079 encoded_frames_(false, false),
3080 packet_event_(false, false),
sprang867fb522015-08-03 04:38:41 -07003081 sender_call_(nullptr),
3082 receiver_call_(nullptr),
Jelena Marusiccd670222015-07-16 09:30:09 +02003083 sender_state_(kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003084 sender_rtp_(0),
3085 sender_rtcp_(0),
3086 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003087 down_frames_(0) {}
3088
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003089 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003090 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003091 ++sender_rtp_;
Peter Boström5811a392015-12-10 13:02:50 +01003092 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003093 return SEND_PACKET;
3094 }
3095
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003096 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003097 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003098 ++sender_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003099 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003100 return SEND_PACKET;
3101 }
3102
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003103 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003104 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
3105 return SEND_PACKET;
3106 }
3107
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003108 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003109 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003110 ++receiver_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003111 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003112 return SEND_PACKET;
3113 }
3114
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003115 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003116 sender_call_ = sender_call;
3117 receiver_call_ = receiver_call;
3118 }
3119
stefanff483612015-12-21 03:14:00 -08003120 void ModifyVideoConfigs(
3121 VideoSendStream::Config* send_config,
3122 std::vector<VideoReceiveStream::Config>* receive_configs,
3123 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003124 send_config->encoder_settings.encoder = this;
3125 }
3126
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003127 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003128 EXPECT_TRUE(encoded_frames_.Wait(kDefaultTimeoutMs))
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003129 << "No frames received by the encoder.";
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003130 // Wait for packets from both sender/receiver.
3131 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003132
skvlad7a43d252016-03-22 15:32:27 -07003133 // Sender-side network down for audio; there should be no effect on video
3134 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3135 WaitForPacketsOrSilence(false, false);
3136
3137 // Receiver-side network down for audio; no change expected
3138 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3139 WaitForPacketsOrSilence(false, false);
3140
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003141 // Sender-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003142 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003143 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003144 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003145 // After network goes down we shouldn't be encoding more frames.
Jelena Marusiccd670222015-07-16 09:30:09 +02003146 sender_state_ = kNetworkDown;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003147 }
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003148 // Wait for receiver-packets and no sender packets.
3149 WaitForPacketsOrSilence(true, false);
3150
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003151 // Receiver-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003152 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
3153 WaitForPacketsOrSilence(true, true);
3154
3155 // Network up for audio for both sides; video is still not expected to
3156 // start
3157 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
3158 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003159 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003160
3161 // Network back up again for both.
3162 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003163 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003164 // It's OK to encode frames again, as we're about to bring up the
3165 // network.
Jelena Marusiccd670222015-07-16 09:30:09 +02003166 sender_state_ = kNetworkUp;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003167 }
skvlad7a43d252016-03-22 15:32:27 -07003168 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
3169 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003170 WaitForPacketsOrSilence(false, false);
skvlad7a43d252016-03-22 15:32:27 -07003171
3172 // TODO(skvlad): add tests to verify that the audio streams are stopped
3173 // when the network goes down for audio once the workaround in
3174 // paced_sender.cc is removed.
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003175 }
3176
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07003177 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003178 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07003179 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003180 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003181 rtc::CritScope lock(&test_crit_);
Jelena Marusiccd670222015-07-16 09:30:09 +02003182 if (sender_state_ == kNetworkDown) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003183 ++down_frames_;
3184 EXPECT_LE(down_frames_, 1)
3185 << "Encoding more than one frame while network is down.";
3186 if (down_frames_ > 1)
Peter Boström5811a392015-12-10 13:02:50 +01003187 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003188 } else {
Peter Boström5811a392015-12-10 13:02:50 +01003189 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003190 }
3191 }
3192 return test::FakeEncoder::Encode(
3193 input_image, codec_specific_info, frame_types);
3194 }
3195
3196 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003197 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
3198 int64_t initial_time_ms = clock_->TimeInMilliseconds();
3199 int initial_sender_rtp;
3200 int initial_sender_rtcp;
3201 int initial_receiver_rtcp;
3202 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003203 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003204 initial_sender_rtp = sender_rtp_;
3205 initial_sender_rtcp = sender_rtcp_;
3206 initial_receiver_rtcp = receiver_rtcp_;
3207 }
3208 bool sender_done = false;
3209 bool receiver_done = false;
mflodmand1590b22015-12-09 07:07:59 -08003210 while (!sender_done || !receiver_done) {
Peter Boström5811a392015-12-10 13:02:50 +01003211 packet_event_.Wait(kSilenceTimeoutMs);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003212 int64_t time_now_ms = clock_->TimeInMilliseconds();
Peter Boströmf2f82832015-05-01 13:00:41 +02003213 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003214 if (sender_down) {
3215 ASSERT_LE(sender_rtp_ - initial_sender_rtp, kNumAcceptedDowntimeRtp)
3216 << "RTP sent during sender-side downtime.";
3217 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
3218 kNumAcceptedDowntimeRtcp)
3219 << "RTCP sent during sender-side downtime.";
3220 if (time_now_ms - initial_time_ms >=
3221 static_cast<int64_t>(kSilenceTimeoutMs)) {
3222 sender_done = true;
3223 }
3224 } else {
skvlad7a43d252016-03-22 15:32:27 -07003225 if (sender_rtp_ > initial_sender_rtp + kNumAcceptedDowntimeRtp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003226 sender_done = true;
3227 }
3228 if (receiver_down) {
3229 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
3230 kNumAcceptedDowntimeRtcp)
3231 << "RTCP sent during receiver-side downtime.";
3232 if (time_now_ms - initial_time_ms >=
3233 static_cast<int64_t>(kSilenceTimeoutMs)) {
3234 receiver_done = true;
3235 }
3236 } else {
skvlad7a43d252016-03-22 15:32:27 -07003237 if (receiver_rtcp_ > initial_receiver_rtcp + kNumAcceptedDowntimeRtcp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003238 receiver_done = true;
3239 }
3240 }
3241 }
3242
Peter Boströmf2f82832015-05-01 13:00:41 +02003243 rtc::CriticalSection test_crit_;
Peter Boström5811a392015-12-10 13:02:50 +01003244 rtc::Event encoded_frames_;
3245 rtc::Event packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003246 Call* sender_call_;
3247 Call* receiver_call_;
Jelena Marusiccd670222015-07-16 09:30:09 +02003248 NetworkState sender_state_ GUARDED_BY(test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003249 int sender_rtp_ GUARDED_BY(test_crit_);
3250 int sender_rtcp_ GUARDED_BY(test_crit_);
3251 int receiver_rtcp_ GUARDED_BY(test_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003252 int down_frames_ GUARDED_BY(test_crit_);
3253 } test;
3254
stefane74eef12016-01-08 06:47:13 -08003255 RunBaseTest(&test);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003256}
3257
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003258TEST_F(EndToEndTest, CallReportsRttForSender) {
3259 static const int kSendDelayMs = 30;
3260 static const int kReceiveDelayMs = 70;
3261
solenberg4fbae2b2015-08-28 04:07:10 -07003262 CreateCalls(Call::Config(), Call::Config());
3263
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003264 FakeNetworkPipe::Config config;
3265 config.queue_delay_ms = kSendDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003266 test::DirectTransport sender_transport(config, sender_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003267 config.queue_delay_ms = kReceiveDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003268 test::DirectTransport receiver_transport(config, receiver_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003269 sender_transport.SetReceiver(receiver_call_->Receiver());
3270 receiver_transport.SetReceiver(sender_call_->Receiver());
3271
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003272 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07003273 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003274
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003275 CreateVideoStreams();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003276 CreateFrameGeneratorCapturer();
3277 Start();
3278
3279 int64_t start_time_ms = clock_->TimeInMilliseconds();
3280 while (true) {
3281 Call::Stats stats = sender_call_->GetStats();
3282 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
3283 clock_->TimeInMilliseconds())
3284 << "No RTT stats before timeout!";
3285 if (stats.rtt_ms != -1) {
3286 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs);
3287 break;
3288 }
3289 SleepMs(10);
3290 }
3291
3292 Stop();
3293 DestroyStreams();
3294}
3295
skvlad7a43d252016-03-22 15:32:27 -07003296void EndToEndTest::VerifyNewVideoSendStreamsRespectNetworkState(
3297 MediaType network_to_bring_down,
3298 VideoEncoder* encoder,
3299 Transport* transport) {
solenberg4fbae2b2015-08-28 04:07:10 -07003300 CreateSenderCall(Call::Config());
skvlad7a43d252016-03-22 15:32:27 -07003301 sender_call_->SignalChannelNetworkState(network_to_bring_down, kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003302
skvlad7a43d252016-03-22 15:32:27 -07003303 CreateSendConfig(1, 0, transport);
3304 video_send_config_.encoder_settings.encoder = encoder;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003305 CreateVideoStreams();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003306 CreateFrameGeneratorCapturer();
3307
3308 Start();
3309 SleepMs(kSilenceTimeoutMs);
3310 Stop();
3311
3312 DestroyStreams();
3313}
3314
skvlad7a43d252016-03-22 15:32:27 -07003315void EndToEndTest::VerifyNewVideoReceiveStreamsRespectNetworkState(
3316 MediaType network_to_bring_down,
3317 Transport* transport) {
solenberg4fbae2b2015-08-28 04:07:10 -07003318 CreateCalls(Call::Config(), Call::Config());
skvlad7a43d252016-03-22 15:32:27 -07003319 receiver_call_->SignalChannelNetworkState(network_to_bring_down,
3320 kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003321
stefanf116bd02015-10-27 08:29:42 -07003322 test::DirectTransport sender_transport(sender_call_.get());
solenberg4fbae2b2015-08-28 04:07:10 -07003323 sender_transport.SetReceiver(receiver_call_->Receiver());
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003324 CreateSendConfig(1, 0, &sender_transport);
skvlad7a43d252016-03-22 15:32:27 -07003325 CreateMatchingReceiveConfigs(transport);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003326 CreateVideoStreams();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003327 CreateFrameGeneratorCapturer();
3328
3329 Start();
3330 SleepMs(kSilenceTimeoutMs);
3331 Stop();
3332
3333 sender_transport.StopSending();
3334
3335 DestroyStreams();
3336}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00003337
skvlad7a43d252016-03-22 15:32:27 -07003338TEST_F(EndToEndTest, NewVideoSendStreamsRespectVideoNetworkDown) {
3339 class UnusedEncoder : public test::FakeEncoder {
3340 public:
3341 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
3342 int32_t Encode(const VideoFrame& input_image,
3343 const CodecSpecificInfo* codec_specific_info,
3344 const std::vector<FrameType>* frame_types) override {
3345 ADD_FAILURE() << "Unexpected frame encode.";
3346 return test::FakeEncoder::Encode(input_image, codec_specific_info,
3347 frame_types);
3348 }
3349 };
3350
3351 UnusedEncoder unused_encoder;
3352 UnusedTransport unused_transport;
3353 VerifyNewVideoSendStreamsRespectNetworkState(
3354 MediaType::VIDEO, &unused_encoder, &unused_transport);
3355}
3356
3357TEST_F(EndToEndTest, NewVideoSendStreamsIgnoreAudioNetworkDown) {
3358 class RequiredEncoder : public test::FakeEncoder {
3359 public:
3360 RequiredEncoder()
3361 : FakeEncoder(Clock::GetRealTimeClock()), encoded_frame_(false) {}
3362 ~RequiredEncoder() {
3363 if (!encoded_frame_) {
3364 ADD_FAILURE() << "Didn't encode an expected frame";
3365 }
3366 }
3367 int32_t Encode(const VideoFrame& input_image,
3368 const CodecSpecificInfo* codec_specific_info,
3369 const std::vector<FrameType>* frame_types) override {
3370 encoded_frame_ = true;
3371 return test::FakeEncoder::Encode(input_image, codec_specific_info,
3372 frame_types);
3373 }
3374
3375 private:
3376 bool encoded_frame_;
3377 };
3378
3379 RequiredTransport required_transport(true /*rtp*/, false /*rtcp*/);
3380 RequiredEncoder required_encoder;
3381 VerifyNewVideoSendStreamsRespectNetworkState(
3382 MediaType::AUDIO, &required_encoder, &required_transport);
3383}
3384
3385TEST_F(EndToEndTest, NewVideoReceiveStreamsRespectVideoNetworkDown) {
3386 UnusedTransport transport;
3387 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::VIDEO, &transport);
3388}
3389
3390TEST_F(EndToEndTest, NewVideoReceiveStreamsIgnoreAudioNetworkDown) {
3391 RequiredTransport transport(false /*rtp*/, true /*rtcp*/);
3392 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::AUDIO, &transport);
3393}
3394
Peter Boströmd7da1202015-06-05 14:09:38 +02003395void VerifyEmptyNackConfig(const NackConfig& config) {
3396 EXPECT_EQ(0, config.rtp_history_ms)
3397 << "Enabling NACK requires rtcp-fb: nack negotiation.";
3398}
3399
3400void VerifyEmptyFecConfig(const FecConfig& config) {
3401 EXPECT_EQ(-1, config.ulpfec_payload_type)
3402 << "Enabling FEC requires rtpmap: ulpfec negotiation.";
3403 EXPECT_EQ(-1, config.red_payload_type)
3404 << "Enabling FEC requires rtpmap: red negotiation.";
3405 EXPECT_EQ(-1, config.red_rtx_payload_type)
3406 << "Enabling RTX in FEC requires rtpmap: rtx negotiation.";
3407}
3408
3409TEST_F(EndToEndTest, VerifyDefaultSendConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003410 VideoSendStream::Config default_send_config(nullptr);
Peter Boströmd7da1202015-06-05 14:09:38 +02003411 EXPECT_EQ(0, default_send_config.rtp.nack.rtp_history_ms)
3412 << "Enabling NACK require rtcp-fb: nack negotiation.";
3413 EXPECT_TRUE(default_send_config.rtp.rtx.ssrcs.empty())
3414 << "Enabling RTX requires rtpmap: rtx negotiation.";
3415 EXPECT_TRUE(default_send_config.rtp.extensions.empty())
3416 << "Enabling RTP extensions require negotiation.";
3417
3418 VerifyEmptyNackConfig(default_send_config.rtp.nack);
3419 VerifyEmptyFecConfig(default_send_config.rtp.fec);
3420}
3421
3422TEST_F(EndToEndTest, VerifyDefaultReceiveConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003423 VideoReceiveStream::Config default_receive_config(nullptr);
pbosda903ea2015-10-02 02:36:56 -07003424 EXPECT_EQ(RtcpMode::kCompound, default_receive_config.rtp.rtcp_mode)
Peter Boströmd7da1202015-06-05 14:09:38 +02003425 << "Reduced-size RTCP require rtcp-rsize to be negotiated.";
3426 EXPECT_FALSE(default_receive_config.rtp.remb)
3427 << "REMB require rtcp-fb: goog-remb to be negotiated.";
3428 EXPECT_FALSE(
3429 default_receive_config.rtp.rtcp_xr.receiver_reference_time_report)
3430 << "RTCP XR settings require rtcp-xr to be negotiated.";
3431 EXPECT_TRUE(default_receive_config.rtp.rtx.empty())
3432 << "Enabling RTX requires rtpmap: rtx negotiation.";
3433 EXPECT_TRUE(default_receive_config.rtp.extensions.empty())
3434 << "Enabling RTP extensions require negotiation.";
3435
3436 VerifyEmptyNackConfig(default_receive_config.rtp.nack);
3437 VerifyEmptyFecConfig(default_receive_config.rtp.fec);
3438}
3439
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003440TEST_F(EndToEndTest, TransportSeqNumOnAudioAndVideo) {
3441 static const int kExtensionId = 8;
3442 class TransportSequenceNumberTest : public test::EndToEndTest {
3443 public:
3444 TransportSequenceNumberTest()
3445 : EndToEndTest(kDefaultTimeoutMs),
3446 video_observed_(false),
3447 audio_observed_(false) {
3448 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
3449 kExtensionId);
3450 }
3451
3452 size_t GetNumVideoStreams() const override { return 1; }
3453 size_t GetNumAudioStreams() const override { return 1; }
3454
3455 void ModifyVideoConfigs(
3456 VideoSendStream::Config* send_config,
3457 std::vector<VideoReceiveStream::Config>* receive_configs,
3458 VideoEncoderConfig* encoder_config) override {
3459 send_config->rtp.extensions.clear();
3460 send_config->rtp.extensions.push_back(
3461 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
3462 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3463 }
3464
3465 void ModifyAudioConfigs(
3466 AudioSendStream::Config* send_config,
3467 std::vector<AudioReceiveStream::Config>* receive_configs) override {
3468 send_config->rtp.extensions.clear();
3469 send_config->rtp.extensions.push_back(
3470 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
3471 (*receive_configs)[0].rtp.extensions.clear();
3472 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3473 }
3474
3475 Action OnSendRtp(const uint8_t* packet, size_t length) override {
3476 RTPHeader header;
3477 EXPECT_TRUE(parser_->Parse(packet, length, &header));
3478 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
3479 // Unwrap packet id and verify uniqueness.
3480 int64_t packet_id =
3481 unwrapper_.Unwrap(header.extension.transportSequenceNumber);
3482 EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
3483
3484 if (header.ssrc == kVideoSendSsrcs[0])
3485 video_observed_ = true;
3486 if (header.ssrc == kAudioSendSsrc)
3487 audio_observed_ = true;
3488 if (audio_observed_ && video_observed_ &&
3489 received_packet_ids_.size() == 50) {
3490 size_t packet_id_range =
3491 *received_packet_ids_.rbegin() - *received_packet_ids_.begin() + 1;
3492 EXPECT_EQ(received_packet_ids_.size(), packet_id_range);
3493 observation_complete_.Set();
3494 }
3495 return SEND_PACKET;
3496 }
3497
3498 void PerformTest() override {
3499 EXPECT_TRUE(Wait()) << "Timed out while waiting for audio and video "
3500 "packets with transport sequence number.";
3501 }
3502
3503 private:
3504 bool video_observed_;
3505 bool audio_observed_;
3506 SequenceNumberUnwrapper unwrapper_;
3507 std::set<int64_t> received_packet_ids_;
3508 } test;
3509
stefane74eef12016-01-08 06:47:13 -08003510 RunBaseTest(&test);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003511}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003512} // namespace webrtc