blob: 873644fae59001344dfd9efba7b9aaf1ceecdf20 [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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "api/optional.h"
19#include "api/video_codecs/video_encoder.h"
20#include "call/call.h"
21#include "common_video/include/frame_callback.h"
22#include "logging/rtc_event_log/rtc_event_log.h"
23#include "media/base/fakevideorenderer.h"
24#include "media/base/mediaconstants.h"
25#include "media/engine/internalencoderfactory.h"
26#include "media/engine/simulcast_encoder_adapter.h"
27#include "media/engine/webrtcvideoencoderfactory.h"
28#include "modules/include/module_common_types.h"
29#include "modules/rtp_rtcp/include/rtp_rtcp.h"
30#include "modules/rtp_rtcp/source/byte_io.h"
31#include "modules/rtp_rtcp/source/rtcp_packet/nack.h"
32#include "modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.h"
33#include "modules/rtp_rtcp/source/rtp_format.h"
34#include "modules/rtp_rtcp/source/rtp_utility.h"
35#include "modules/video_coding/codecs/h264/include/h264.h"
36#include "modules/video_coding/codecs/vp8/include/vp8.h"
37#include "modules/video_coding/codecs/vp9/include/vp9.h"
38#include "modules/video_coding/include/video_coding_defines.h"
39#include "rtc_base/checks.h"
40#include "rtc_base/event.h"
41#include "rtc_base/file.h"
42#include "rtc_base/ptr_util.h"
43#include "rtc_base/random.h"
44#include "rtc_base/rate_limiter.h"
45#include "system_wrappers/include/metrics.h"
46#include "system_wrappers/include/metrics_default.h"
47#include "system_wrappers/include/sleep.h"
48#include "test/call_test.h"
49#include "test/direct_transport.h"
50#include "test/encoder_settings.h"
51#include "test/fake_decoder.h"
52#include "test/fake_encoder.h"
53#include "test/field_trial.h"
54#include "test/frame_generator.h"
55#include "test/frame_generator_capturer.h"
56#include "test/gmock.h"
57#include "test/gtest.h"
58#include "test/null_transport.h"
59#include "test/rtcp_packet_parser.h"
60#include "test/rtp_rtcp_observer.h"
61#include "test/testsupport/fileutils.h"
62#include "test/testsupport/perf_test.h"
63#include "video/transport_adapter.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000064
oprypin45197522017-06-22 01:47:20 -070065// Flaky under MemorySanitizer: bugs.webrtc.org/7419
aleloi7057b6b2017-03-29 02:07:33 -070066#if defined(MEMORY_SANITIZER)
oprypin45197522017-06-22 01:47:20 -070067#define MAYBE_InitialProbing DISABLED_InitialProbing
68// Fails on iOS bots: bugs.webrtc.org/7851
69#elif defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR
aleloi7057b6b2017-03-29 02:07:33 -070070#define MAYBE_InitialProbing DISABLED_InitialProbing
71#else
72#define MAYBE_InitialProbing InitialProbing
73#endif
74
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000075namespace webrtc {
76
minyue20c84cc2017-04-10 16:57:57 -070077namespace {
78constexpr int kSilenceTimeoutMs = 2000;
79}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000080
philipelccdfcca2017-10-23 12:42:17 +020081class EndToEndTest : public test::CallTest,
82 public testing::WithParamInterface<std::string> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000083 public:
philipelccdfcca2017-10-23 12:42:17 +020084 EndToEndTest() : field_trial_(GetParam()) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000085
86 virtual ~EndToEndTest() {
stefanff483612015-12-21 03:14:00 -080087 EXPECT_EQ(nullptr, video_send_stream_);
88 EXPECT_TRUE(video_receive_streams_.empty());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000089 }
90
91 protected:
pbos2d566682015-09-28 09:59:31 -070092 class UnusedTransport : public Transport {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000093 private:
stefan1d8a5062015-10-02 03:39:33 -070094 bool SendRtp(const uint8_t* packet,
95 size_t length,
96 const PacketOptions& options) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000097 ADD_FAILURE() << "Unexpected RTP sent.";
98 return false;
99 }
100
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000101 bool SendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000102 ADD_FAILURE() << "Unexpected RTCP sent.";
103 return false;
104 }
105 };
106
skvlad7a43d252016-03-22 15:32:27 -0700107 class RequiredTransport : public Transport {
108 public:
109 RequiredTransport(bool rtp_required, bool rtcp_required)
110 : need_rtp_(rtp_required), need_rtcp_(rtcp_required) {}
111 ~RequiredTransport() {
112 if (need_rtp_) {
113 ADD_FAILURE() << "Expected RTP packet not sent.";
114 }
115 if (need_rtcp_) {
116 ADD_FAILURE() << "Expected RTCP packet not sent.";
117 }
118 }
119
120 private:
121 bool SendRtp(const uint8_t* packet,
122 size_t length,
123 const PacketOptions& options) override {
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700124 rtc::CritScope lock(&crit_);
skvlad7a43d252016-03-22 15:32:27 -0700125 need_rtp_ = false;
126 return true;
127 }
128
129 bool SendRtcp(const uint8_t* packet, size_t length) override {
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700130 rtc::CritScope lock(&crit_);
skvlad7a43d252016-03-22 15:32:27 -0700131 need_rtcp_ = false;
132 return true;
133 }
134 bool need_rtp_;
135 bool need_rtcp_;
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700136 rtc::CriticalSection crit_;
skvlad7a43d252016-03-22 15:32:27 -0700137 };
138
Peter Boström39593972016-02-15 11:27:15 +0100139 void DecodesRetransmittedFrame(bool enable_rtx, bool enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000140 void ReceivesPliAndRecovers(int rtp_history_ms);
pbosda903ea2015-10-02 02:36:56 -0700141 void RespectsRtcpMode(RtcpMode rtcp_mode);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000142 void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200143 void TestRtpStatePreservation(bool use_rtx, bool provoke_rtcpsr_before_rtp);
nisse3b3622f2017-09-26 02:49:21 -0700144 void VerifyHistogramStats(bool use_rtx, bool use_fec, bool screenshare);
skvlad7a43d252016-03-22 15:32:27 -0700145 void VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -0800146 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -0700147 VideoEncoder* encoder,
148 Transport* transport);
149 void VerifyNewVideoReceiveStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -0800150 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -0700151 Transport* transport);
philipelccdfcca2017-10-23 12:42:17 +0200152
153 test::ScopedFieldTrials field_trial_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000154};
155
philipelccdfcca2017-10-23 12:42:17 +0200156TEST_P(EndToEndTest, ReceiverCanBeStartedTwice) {
philipel4fb651d2017-04-10 03:54:05 -0700157 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000158
solenberg4fbae2b2015-08-28 04:07:10 -0700159 test::NullTransport transport;
brandtr841de6a2016-11-15 07:10:52 -0800160 CreateSendConfig(1, 0, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700161 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000162
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100163 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000164
stefanff483612015-12-21 03:14:00 -0800165 video_receive_streams_[0]->Start();
166 video_receive_streams_[0]->Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000167
168 DestroyStreams();
169}
170
philipelccdfcca2017-10-23 12:42:17 +0200171TEST_P(EndToEndTest, ReceiverCanBeStoppedTwice) {
philipel4fb651d2017-04-10 03:54:05 -0700172 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000173
solenberg4fbae2b2015-08-28 04:07:10 -0700174 test::NullTransport transport;
brandtr841de6a2016-11-15 07:10:52 -0800175 CreateSendConfig(1, 0, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700176 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000177
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100178 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000179
stefanff483612015-12-21 03:14:00 -0800180 video_receive_streams_[0]->Stop();
181 video_receive_streams_[0]->Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000182
183 DestroyStreams();
184}
185
philipelccdfcca2017-10-23 12:42:17 +0200186TEST_P(EndToEndTest, ReceiverCanBeStoppedAndRestarted) {
philipel4fb651d2017-04-10 03:54:05 -0700187 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
sprang113bdca2016-10-11 03:10:10 -0700188
189 test::NullTransport transport;
brandtr841de6a2016-11-15 07:10:52 -0800190 CreateSendConfig(1, 0, 0, &transport);
sprang113bdca2016-10-11 03:10:10 -0700191 CreateMatchingReceiveConfigs(&transport);
192
193 CreateVideoStreams();
194
195 video_receive_streams_[0]->Stop();
196 video_receive_streams_[0]->Start();
197 video_receive_streams_[0]->Stop();
198
199 DestroyStreams();
200}
201
philipelccdfcca2017-10-23 12:42:17 +0200202TEST_P(EndToEndTest, RendersSingleDelayedFrame) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000203 static const int kWidth = 320;
204 static const int kHeight = 240;
205 // This constant is chosen to be higher than the timeout in the video_render
206 // module. This makes sure that frames aren't dropped if there are no other
207 // frames in the queue.
nisse76bc8e82017-02-07 09:37:41 -0800208 static const int kRenderDelayMs = 1000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000209
nisse7ade7b32016-03-23 04:48:10 -0700210 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000211 public:
Peter Boström5811a392015-12-10 13:02:50 +0100212 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000213
nisse76bc8e82017-02-07 09:37:41 -0800214 void OnFrame(const VideoFrame& video_frame) override {
215 SleepMs(kRenderDelayMs);
216 event_.Set();
217 }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000218
Peter Boström5811a392015-12-10 13:02:50 +0100219 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000220
Peter Boström5811a392015-12-10 13:02:50 +0100221 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000222 } renderer;
223
perkja49cbd32016-09-16 07:53:41 -0700224 test::FrameForwarder frame_forwarder;
eladalon413ee9a2017-08-22 04:02:52 -0700225 std::unique_ptr<test::DirectTransport> sender_transport;
226 std::unique_ptr<test::DirectTransport> receiver_transport;
perkja49cbd32016-09-16 07:53:41 -0700227
eladalon413ee9a2017-08-22 04:02:52 -0700228 task_queue_.SendTask([this, &renderer, &frame_forwarder, &sender_transport,
229 &receiver_transport]() {
230 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
231
232 sender_transport = rtc::MakeUnique<test::DirectTransport>(
233 &task_queue_, sender_call_.get(), payload_type_map_);
234 receiver_transport = rtc::MakeUnique<test::DirectTransport>(
235 &task_queue_, receiver_call_.get(), payload_type_map_);
236 sender_transport->SetReceiver(receiver_call_->Receiver());
237 receiver_transport->SetReceiver(sender_call_->Receiver());
238
239 CreateSendConfig(1, 0, 0, sender_transport.get());
240 CreateMatchingReceiveConfigs(receiver_transport.get());
241
242 video_receive_configs_[0].renderer = &renderer;
243
244 CreateVideoStreams();
245 Start();
246
247 // Create frames that are smaller than the send width/height, this is done
248 // to check that the callbacks are done after processing video.
249 std::unique_ptr<test::FrameGenerator> frame_generator(
250 test::FrameGenerator::CreateSquareGenerator(kWidth, kHeight));
251 video_send_stream_->SetSource(
252 &frame_forwarder,
253 VideoSendStream::DegradationPreference::kMaintainFramerate);
254
255 frame_forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
256 });
257
Peter Boström5811a392015-12-10 13:02:50 +0100258 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000259 << "Timed out while waiting for the frame to render.";
260
eladalon413ee9a2017-08-22 04:02:52 -0700261 task_queue_.SendTask([this, &sender_transport, &receiver_transport]() {
262 Stop();
263 DestroyStreams();
264 sender_transport.reset();
265 receiver_transport.reset();
266 DestroyCalls();
267 });
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000268}
269
philipelccdfcca2017-10-23 12:42:17 +0200270TEST_P(EndToEndTest, TransmitsFirstFrame) {
nisse7ade7b32016-03-23 04:48:10 -0700271 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000272 public:
Peter Boström5811a392015-12-10 13:02:50 +0100273 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000274
nisseeb83a1a2016-03-21 01:27:56 -0700275 void OnFrame(const VideoFrame& video_frame) override { event_.Set(); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000276
Peter Boström5811a392015-12-10 13:02:50 +0100277 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000278
Peter Boström5811a392015-12-10 13:02:50 +0100279 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000280 } renderer;
281
eladalon413ee9a2017-08-22 04:02:52 -0700282 std::unique_ptr<test::FrameGenerator> frame_generator;
perkja49cbd32016-09-16 07:53:41 -0700283 test::FrameForwarder frame_forwarder;
eladalon413ee9a2017-08-22 04:02:52 -0700284
285 std::unique_ptr<test::DirectTransport> sender_transport;
286 std::unique_ptr<test::DirectTransport> receiver_transport;
287
288 task_queue_.SendTask([this, &renderer, &frame_generator, &frame_forwarder,
289 &sender_transport, &receiver_transport]() {
290 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
291
292 sender_transport = rtc::MakeUnique<test::DirectTransport>(
293 &task_queue_, sender_call_.get(), payload_type_map_);
294 receiver_transport = rtc::MakeUnique<test::DirectTransport>(
295 &task_queue_, receiver_call_.get(), payload_type_map_);
296 sender_transport->SetReceiver(receiver_call_->Receiver());
297 receiver_transport->SetReceiver(sender_call_->Receiver());
298
299 CreateSendConfig(1, 0, 0, sender_transport.get());
300 CreateMatchingReceiveConfigs(receiver_transport.get());
301 video_receive_configs_[0].renderer = &renderer;
302
303 CreateVideoStreams();
304 Start();
305
306 frame_generator = test::FrameGenerator::CreateSquareGenerator(
307 kDefaultWidth, kDefaultHeight);
308 video_send_stream_->SetSource(
309 &frame_forwarder,
310 VideoSendStream::DegradationPreference::kMaintainFramerate);
311 frame_forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
312 });
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000313
Peter Boström5811a392015-12-10 13:02:50 +0100314 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000315 << "Timed out while waiting for the frame to render.";
316
eladalon413ee9a2017-08-22 04:02:52 -0700317 task_queue_.SendTask([this, &sender_transport, &receiver_transport]() {
318 Stop();
319 DestroyStreams();
320 sender_transport.reset();
321 receiver_transport.reset();
322 DestroyCalls();
323 });
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000324}
325
Perba7dc722016-04-19 15:01:23 +0200326class CodecObserver : public test::EndToEndTest,
nisse7ade7b32016-03-23 04:48:10 -0700327 public rtc::VideoSinkInterface<VideoFrame> {
Perba7dc722016-04-19 15:01:23 +0200328 public:
329 CodecObserver(int no_frames_to_wait_for,
330 VideoRotation rotation_to_test,
331 const std::string& payload_name,
332 webrtc::VideoEncoder* encoder,
333 webrtc::VideoDecoder* decoder)
hta9aa96882016-12-06 05:36:03 -0800334 : EndToEndTest(4 * webrtc::EndToEndTest::kDefaultTimeoutMs),
335 // TODO(hta): This timeout (120 seconds) is excessive.
336 // https://bugs.webrtc.org/6830
Perba7dc722016-04-19 15:01:23 +0200337 no_frames_to_wait_for_(no_frames_to_wait_for),
338 expected_rotation_(rotation_to_test),
339 payload_name_(payload_name),
340 encoder_(encoder),
341 decoder_(decoder),
342 frame_counter_(0) {}
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000343
Perba7dc722016-04-19 15:01:23 +0200344 void PerformTest() override {
345 EXPECT_TRUE(Wait())
346 << "Timed out while waiting for enough frames to be decoded.";
347 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000348
Perba7dc722016-04-19 15:01:23 +0200349 void ModifyVideoConfigs(
350 VideoSendStream::Config* send_config,
351 std::vector<VideoReceiveStream::Config>* receive_configs,
352 VideoEncoderConfig* encoder_config) override {
353 send_config->encoder_settings.encoder = encoder_.get();
354 send_config->encoder_settings.payload_name = payload_name_;
minyue20c84cc2017-04-10 16:57:57 -0700355 send_config->encoder_settings.payload_type =
356 test::CallTest::kVideoSendPayloadType;
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000357
Perba7dc722016-04-19 15:01:23 +0200358 (*receive_configs)[0].renderer = this;
359 (*receive_configs)[0].decoders.resize(1);
360 (*receive_configs)[0].decoders[0].payload_type =
361 send_config->encoder_settings.payload_type;
362 (*receive_configs)[0].decoders[0].payload_name =
363 send_config->encoder_settings.payload_name;
364 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
365 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000366
Perba7dc722016-04-19 15:01:23 +0200367 void OnFrame(const VideoFrame& video_frame) override {
368 EXPECT_EQ(expected_rotation_, video_frame.rotation());
369 if (++frame_counter_ == no_frames_to_wait_for_)
370 observation_complete_.Set();
371 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000372
Perba7dc722016-04-19 15:01:23 +0200373 void OnFrameGeneratorCapturerCreated(
374 test::FrameGeneratorCapturer* frame_generator_capturer) override {
375 frame_generator_capturer->SetFakeRotation(expected_rotation_);
376 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000377
Perba7dc722016-04-19 15:01:23 +0200378 private:
379 int no_frames_to_wait_for_;
380 VideoRotation expected_rotation_;
381 std::string payload_name_;
382 std::unique_ptr<webrtc::VideoEncoder> encoder_;
383 std::unique_ptr<webrtc::VideoDecoder> decoder_;
384 int frame_counter_;
385};
386
philipelccdfcca2017-10-23 12:42:17 +0200387TEST_P(EndToEndTest, SendsAndReceivesVP8) {
philipel266f0a42016-11-28 08:49:07 -0800388 CodecObserver test(5, kVideoRotation_0, "VP8", VP8Encoder::Create(),
389 VP8Decoder::Create());
390 RunBaseTest(&test);
391}
392
philipelccdfcca2017-10-23 12:42:17 +0200393TEST_P(EndToEndTest, SendsAndReceivesVP8Rotation90) {
magjed509e4fe2016-11-18 01:34:11 -0800394 CodecObserver test(5, kVideoRotation_90, "VP8", VP8Encoder::Create(),
Perba7dc722016-04-19 15:01:23 +0200395 VP8Decoder::Create());
396 RunBaseTest(&test);
397}
398
Peter Boström12996152016-05-14 02:03:18 +0200399#if !defined(RTC_DISABLE_VP9)
philipelccdfcca2017-10-23 12:42:17 +0200400TEST_P(EndToEndTest, SendsAndReceivesVP9) {
magjed509e4fe2016-11-18 01:34:11 -0800401 CodecObserver test(500, kVideoRotation_0, "VP9", VP9Encoder::Create(),
Perba7dc722016-04-19 15:01:23 +0200402 VP9Decoder::Create());
403 RunBaseTest(&test);
404}
405
philipelccdfcca2017-10-23 12:42:17 +0200406TEST_P(EndToEndTest, SendsAndReceivesVP9VideoRotation90) {
magjed509e4fe2016-11-18 01:34:11 -0800407 CodecObserver test(5, kVideoRotation_90, "VP9", VP9Encoder::Create(),
Perba7dc722016-04-19 15:01:23 +0200408 VP9Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800409 RunBaseTest(&test);
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000410}
Peter Boström12996152016-05-14 02:03:18 +0200411#endif // !defined(RTC_DISABLE_VP9)
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000412
brandtr445fb8f2016-11-14 04:11:23 -0800413#if defined(WEBRTC_USE_H264)
philipelccdfcca2017-10-23 12:42:17 +0200414TEST_P(EndToEndTest, SendsAndReceivesH264) {
magjedceecea42016-11-28 07:20:21 -0800415 CodecObserver test(500, kVideoRotation_0, "H264",
416 H264Encoder::Create(cricket::VideoCodec("H264")),
Perba7dc722016-04-19 15:01:23 +0200417 H264Decoder::Create());
418 RunBaseTest(&test);
419}
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000420
philipelccdfcca2017-10-23 12:42:17 +0200421TEST_P(EndToEndTest, SendsAndReceivesH264VideoRotation90) {
magjedceecea42016-11-28 07:20:21 -0800422 CodecObserver test(5, kVideoRotation_90, "H264",
423 H264Encoder::Create(cricket::VideoCodec("H264")),
Perba7dc722016-04-19 15:01:23 +0200424 H264Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800425 RunBaseTest(&test);
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000426}
hta9aa96882016-12-06 05:36:03 -0800427
philipelccdfcca2017-10-23 12:42:17 +0200428TEST_P(EndToEndTest, SendsAndReceivesH264PacketizationMode0) {
hta9aa96882016-12-06 05:36:03 -0800429 cricket::VideoCodec codec = cricket::VideoCodec("H264");
430 codec.SetParam(cricket::kH264FmtpPacketizationMode, "0");
431 CodecObserver test(500, kVideoRotation_0, "H264", H264Encoder::Create(codec),
432 H264Decoder::Create());
433 RunBaseTest(&test);
434}
435
philipelccdfcca2017-10-23 12:42:17 +0200436TEST_P(EndToEndTest, SendsAndReceivesH264PacketizationMode1) {
hta9aa96882016-12-06 05:36:03 -0800437 cricket::VideoCodec codec = cricket::VideoCodec("H264");
438 codec.SetParam(cricket::kH264FmtpPacketizationMode, "1");
439 CodecObserver test(500, kVideoRotation_0, "H264", H264Encoder::Create(codec),
440 H264Decoder::Create());
441 RunBaseTest(&test);
442}
443
brandtr445fb8f2016-11-14 04:11:23 -0800444#endif // defined(WEBRTC_USE_H264)
hbosbab934b2016-01-27 01:36:03 -0800445
philipelccdfcca2017-10-23 12:42:17 +0200446TEST_P(EndToEndTest, ReceiverUsesLocalSsrc) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000447 class SyncRtcpObserver : public test::EndToEndTest {
448 public:
449 SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {}
450
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000451 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
danilchap3dc929e2016-11-02 08:21:59 -0700452 test::RtcpPacketParser parser;
453 EXPECT_TRUE(parser.Parse(packet, length));
454 EXPECT_EQ(kReceiverLocalVideoSsrc, parser.sender_ssrc());
Peter Boström5811a392015-12-10 13:02:50 +0100455 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000456
457 return SEND_PACKET;
458 }
459
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000460 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100461 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000462 << "Timed out while waiting for a receiver RTCP packet to be sent.";
463 }
464 } test;
465
stefane74eef12016-01-08 06:47:13 -0800466 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000467}
468
philipelccdfcca2017-10-23 12:42:17 +0200469TEST_P(EndToEndTest, ReceivesAndRetransmitsNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000470 static const int kNumberOfNacksToObserve = 2;
471 static const int kLossBurstSize = 2;
472 static const int kPacketsBetweenLossBursts = 9;
473 class NackObserver : public test::EndToEndTest {
474 public:
475 NackObserver()
476 : EndToEndTest(kLongTimeoutMs),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000477 sent_rtp_packets_(0),
478 packets_left_to_drop_(0),
479 nacks_left_(kNumberOfNacksToObserve) {}
480
481 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000482 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700483 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000484 RTPHeader header;
Peter Boström03671cb2015-12-07 15:22:24 +0100485 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000486
487 // Never drop retransmitted packets.
488 if (dropped_packets_.find(header.sequenceNumber) !=
489 dropped_packets_.end()) {
490 retransmitted_packets_.insert(header.sequenceNumber);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000491 return SEND_PACKET;
492 }
493
philipel8054c7e2017-01-10 05:19:19 -0800494 if (nacks_left_ <= 0 &&
495 retransmitted_packets_.size() == dropped_packets_.size()) {
496 observation_complete_.Set();
497 }
498
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000499 ++sent_rtp_packets_;
500
501 // Enough NACKs received, stop dropping packets.
Stefan Holmer586b19b2015-09-18 11:14:31 +0200502 if (nacks_left_ <= 0)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000503 return SEND_PACKET;
504
505 // Check if it's time for a new loss burst.
506 if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
507 packets_left_to_drop_ = kLossBurstSize;
508
Stefan Holmer01b48882015-05-05 10:21:24 +0200509 // Never drop padding packets as those won't be retransmitted.
510 if (packets_left_to_drop_ > 0 && header.paddingLength == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000511 --packets_left_to_drop_;
512 dropped_packets_.insert(header.sequenceNumber);
513 return DROP_PACKET;
514 }
515
516 return SEND_PACKET;
517 }
518
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000519 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700520 rtc::CritScope lock(&crit_);
danilchap3dc929e2016-11-02 08:21:59 -0700521 test::RtcpPacketParser parser;
522 EXPECT_TRUE(parser.Parse(packet, length));
523 nacks_left_ -= parser.nack()->num_packets();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000524 return SEND_PACKET;
525 }
526
stefanff483612015-12-21 03:14:00 -0800527 void ModifyVideoConfigs(
528 VideoSendStream::Config* send_config,
529 std::vector<VideoReceiveStream::Config>* receive_configs,
530 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000531 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000532 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000533 }
534
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000535 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100536 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000537 << "Timed out waiting for packets to be NACKed, retransmitted and "
538 "rendered.";
539 }
540
stefanf116bd02015-10-27 08:29:42 -0700541 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000542 std::set<uint16_t> dropped_packets_;
543 std::set<uint16_t> retransmitted_packets_;
544 uint64_t sent_rtp_packets_;
545 int packets_left_to_drop_;
danilchapa37de392017-09-09 04:17:22 -0700546 int nacks_left_ RTC_GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000547 } test;
548
stefane74eef12016-01-08 06:47:13 -0800549 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000550}
551
philipelccdfcca2017-10-23 12:42:17 +0200552TEST_P(EndToEndTest, ReceivesNackAndRetransmitsAudio) {
Erik Språng737336d2016-07-29 12:59:36 +0200553 class NackObserver : public test::EndToEndTest {
554 public:
555 NackObserver()
556 : EndToEndTest(kLongTimeoutMs),
557 local_ssrc_(0),
558 remote_ssrc_(0),
559 receive_transport_(nullptr) {}
560
561 private:
562 size_t GetNumVideoStreams() const override { return 0; }
563 size_t GetNumAudioStreams() const override { return 1; }
564
eladalon413ee9a2017-08-22 04:02:52 -0700565 test::PacketTransport* CreateReceiveTransport(
566 test::SingleThreadedTaskQueueForTesting* task_queue) override {
Erik Språng737336d2016-07-29 12:59:36 +0200567 test::PacketTransport* receive_transport = new test::PacketTransport(
eladalon413ee9a2017-08-22 04:02:52 -0700568 task_queue, nullptr, this, test::PacketTransport::kReceiver,
569 payload_type_map_, FakeNetworkPipe::Config());
Erik Språng737336d2016-07-29 12:59:36 +0200570 receive_transport_ = receive_transport;
571 return receive_transport;
572 }
573
574 Action OnSendRtp(const uint8_t* packet, size_t length) override {
575 RTPHeader header;
576 EXPECT_TRUE(parser_->Parse(packet, length, &header));
577
578 if (!sequence_number_to_retransmit_) {
579 sequence_number_to_retransmit_ =
580 rtc::Optional<uint16_t>(header.sequenceNumber);
581
582 // Don't ask for retransmission straight away, may be deduped in pacer.
583 } else if (header.sequenceNumber == *sequence_number_to_retransmit_) {
584 observation_complete_.Set();
585 } else {
586 // Send a NACK as often as necessary until retransmission is received.
587 rtcp::Nack nack;
danilchap822a16f2016-09-27 09:27:47 -0700588 nack.SetSenderSsrc(local_ssrc_);
589 nack.SetMediaSsrc(remote_ssrc_);
Erik Språng737336d2016-07-29 12:59:36 +0200590 uint16_t nack_list[] = {*sequence_number_to_retransmit_};
danilchap822a16f2016-09-27 09:27:47 -0700591 nack.SetPacketIds(nack_list, 1);
Erik Språng737336d2016-07-29 12:59:36 +0200592 rtc::Buffer buffer = nack.Build();
593
594 EXPECT_TRUE(receive_transport_->SendRtcp(buffer.data(), buffer.size()));
595 }
596
597 return SEND_PACKET;
598 }
599
600 void ModifyAudioConfigs(
601 AudioSendStream::Config* send_config,
602 std::vector<AudioReceiveStream::Config>* receive_configs) override {
603 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
604 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
605 local_ssrc_ = (*receive_configs)[0].rtp.local_ssrc;
606 remote_ssrc_ = (*receive_configs)[0].rtp.remote_ssrc;
607 }
608
609 void PerformTest() override {
610 EXPECT_TRUE(Wait())
611 << "Timed out waiting for packets to be NACKed, retransmitted and "
612 "rendered.";
613 }
614
615 uint32_t local_ssrc_;
616 uint32_t remote_ssrc_;
617 Transport* receive_transport_;
618 rtc::Optional<uint16_t> sequence_number_to_retransmit_;
619 } test;
620
621 RunBaseTest(&test);
622}
623
philipelccdfcca2017-10-23 12:42:17 +0200624TEST_P(EndToEndTest, ReceivesUlpfec) {
brandtr535830e2016-10-31 03:45:58 -0700625 class UlpfecRenderObserver : public test::EndToEndTest,
626 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000627 public:
brandtr535830e2016-10-31 03:45:58 -0700628 UlpfecRenderObserver()
brandtr1134b7b2017-02-06 06:35:47 -0800629 : EndToEndTest(kDefaultTimeoutMs),
brandtrc55f27a2017-03-20 06:32:59 -0700630 encoder_(VP8Encoder::Create()),
brandtr1134b7b2017-02-06 06:35:47 -0800631 random_(0xcafef00d1),
632 num_packets_sent_(0) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000633
634 private:
stefanf116bd02015-10-27 08:29:42 -0700635 Action OnSendRtp(const uint8_t* packet, size_t length) override {
636 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000637 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000638 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000639
brandtrc55f27a2017-03-20 06:32:59 -0700640 EXPECT_TRUE(header.payloadType == kVideoSendPayloadType ||
brandtr1134b7b2017-02-06 06:35:47 -0800641 header.payloadType == kRedPayloadType)
642 << "Unknown payload type received.";
643 EXPECT_EQ(kVideoSendSsrcs[0], header.ssrc) << "Unknown SSRC received.";
644
645 // Parse RED header.
Stefan Holmer01b48882015-05-05 10:21:24 +0200646 int encapsulated_payload_type = -1;
647 if (header.payloadType == kRedPayloadType) {
648 encapsulated_payload_type =
649 static_cast<int>(packet[header.headerLength]);
brandtr1134b7b2017-02-06 06:35:47 -0800650
brandtrc55f27a2017-03-20 06:32:59 -0700651 EXPECT_TRUE(encapsulated_payload_type == kVideoSendPayloadType ||
brandtr1134b7b2017-02-06 06:35:47 -0800652 encapsulated_payload_type == kUlpfecPayloadType)
653 << "Unknown encapsulated payload type received.";
Stefan Holmer01b48882015-05-05 10:21:24 +0200654 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000655
brandtrc55f27a2017-03-20 06:32:59 -0700656 // To minimize test flakiness, always let ULPFEC packets through.
brandtr1134b7b2017-02-06 06:35:47 -0800657 if (encapsulated_payload_type == kUlpfecPayloadType) {
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000658 return SEND_PACKET;
659 }
660
brandtr1134b7b2017-02-06 06:35:47 -0800661 // Simulate 5% video packet loss after rampup period. Record the
662 // corresponding timestamps that were dropped.
663 if (num_packets_sent_++ > 100 && random_.Rand(1, 100) <= 5) {
brandtrc55f27a2017-03-20 06:32:59 -0700664 if (encapsulated_payload_type == kVideoSendPayloadType) {
brandtr1134b7b2017-02-06 06:35:47 -0800665 dropped_sequence_numbers_.insert(header.sequenceNumber);
666 dropped_timestamps_.insert(header.timestamp);
667 }
brandtr1134b7b2017-02-06 06:35:47 -0800668 return DROP_PACKET;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000669 }
670
671 return SEND_PACKET;
672 }
673
nisseeb83a1a2016-03-21 01:27:56 -0700674 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200675 rtc::CritScope lock(&crit_);
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000676 // Rendering frame with timestamp of packet that was dropped -> FEC
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000677 // protection worked.
brandtr1134b7b2017-02-06 06:35:47 -0800678 auto it = dropped_timestamps_.find(video_frame.timestamp());
679 if (it != dropped_timestamps_.end()) {
Peter Boström5811a392015-12-10 13:02:50 +0100680 observation_complete_.Set();
brandtr1134b7b2017-02-06 06:35:47 -0800681 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000682 }
683
stefanff483612015-12-21 03:14:00 -0800684 void ModifyVideoConfigs(
685 VideoSendStream::Config* send_config,
686 std::vector<VideoReceiveStream::Config>* receive_configs,
687 VideoEncoderConfig* encoder_config) override {
brandtrc55f27a2017-03-20 06:32:59 -0700688 // Use VP8 instead of FAKE, since the latter does not have PictureID
689 // in the packetization headers.
690 send_config->encoder_settings.encoder = encoder_.get();
691 send_config->encoder_settings.payload_name = "VP8";
692 send_config->encoder_settings.payload_type = kVideoSendPayloadType;
693 VideoReceiveStream::Decoder decoder =
694 test::CreateMatchingDecoder(send_config->encoder_settings);
695 decoder_.reset(decoder.decoder);
696 (*receive_configs)[0].decoders.clear();
697 (*receive_configs)[0].decoders.push_back(decoder);
698
699 // Enable ULPFEC over RED.
brandtrb5f2c3f2016-10-04 23:28:39 -0700700 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
701 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
nisse3b3622f2017-09-26 02:49:21 -0700702 (*receive_configs)[0].rtp.red_payload_type = kRedPayloadType;
703 (*receive_configs)[0].rtp.ulpfec_payload_type = kUlpfecPayloadType;
brandtrc55f27a2017-03-20 06:32:59 -0700704
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000705 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000706 }
707
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000708 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100709 EXPECT_TRUE(Wait())
brandtr1e3dfbf2016-11-16 22:45:19 -0800710 << "Timed out waiting for dropped frames to be rendered.";
711 }
712
713 rtc::CriticalSection crit_;
brandtrc55f27a2017-03-20 06:32:59 -0700714 std::unique_ptr<VideoEncoder> encoder_;
715 std::unique_ptr<VideoDecoder> decoder_;
danilchapa37de392017-09-09 04:17:22 -0700716 std::set<uint32_t> dropped_sequence_numbers_ RTC_GUARDED_BY(crit_);
brandtr1134b7b2017-02-06 06:35:47 -0800717 // Several packets can have the same timestamp.
danilchapa37de392017-09-09 04:17:22 -0700718 std::multiset<uint32_t> dropped_timestamps_ RTC_GUARDED_BY(crit_);
brandtr1134b7b2017-02-06 06:35:47 -0800719 Random random_;
danilchapa37de392017-09-09 04:17:22 -0700720 int num_packets_sent_ RTC_GUARDED_BY(crit_);
brandtr1e3dfbf2016-11-16 22:45:19 -0800721 } test;
722
723 RunBaseTest(&test);
724}
725
brandtrfa5a3682017-01-17 01:33:54 -0800726class FlexfecRenderObserver : public test::EndToEndTest,
727 public rtc::VideoSinkInterface<VideoFrame> {
728 public:
729 static constexpr uint32_t kVideoLocalSsrc = 123;
730 static constexpr uint32_t kFlexfecLocalSsrc = 456;
brandtr1e3dfbf2016-11-16 22:45:19 -0800731
brandtr1134b7b2017-02-06 06:35:47 -0800732 explicit FlexfecRenderObserver(bool enable_nack, bool expect_flexfec_rtcp)
brandtrfa5a3682017-01-17 01:33:54 -0800733 : test::EndToEndTest(test::CallTest::kDefaultTimeoutMs),
brandtr1134b7b2017-02-06 06:35:47 -0800734 enable_nack_(enable_nack),
brandtrfa5a3682017-01-17 01:33:54 -0800735 expect_flexfec_rtcp_(expect_flexfec_rtcp),
736 received_flexfec_rtcp_(false),
brandtr1134b7b2017-02-06 06:35:47 -0800737 random_(0xcafef00d1),
738 num_packets_sent_(0) {}
brandtr1e3dfbf2016-11-16 22:45:19 -0800739
brandtrfa5a3682017-01-17 01:33:54 -0800740 size_t GetNumFlexfecStreams() const override { return 1; }
brandtr1e3dfbf2016-11-16 22:45:19 -0800741
brandtrfa5a3682017-01-17 01:33:54 -0800742 private:
743 Action OnSendRtp(const uint8_t* packet, size_t length) override {
744 rtc::CritScope lock(&crit_);
745 RTPHeader header;
746 EXPECT_TRUE(parser_->Parse(packet, length, &header));
brandtr1e3dfbf2016-11-16 22:45:19 -0800747
brandtr1134b7b2017-02-06 06:35:47 -0800748 EXPECT_TRUE(header.payloadType ==
749 test::CallTest::kFakeVideoSendPayloadType ||
750 header.payloadType == test::CallTest::kFlexfecPayloadType ||
751 (enable_nack_ &&
752 header.payloadType == test::CallTest::kSendRtxPayloadType))
753 << "Unknown payload type received.";
754 EXPECT_TRUE(
755 header.ssrc == test::CallTest::kVideoSendSsrcs[0] ||
756 header.ssrc == test::CallTest::kFlexfecSendSsrc ||
757 (enable_nack_ && header.ssrc == test::CallTest::kSendRtxSsrcs[0]))
758 << "Unknown SSRC received.";
759
760 // To reduce test flakiness, always let FlexFEC packets through.
761 if (header.payloadType == test::CallTest::kFlexfecPayloadType) {
762 EXPECT_EQ(test::CallTest::kFlexfecSendSsrc, header.ssrc);
763
764 return SEND_PACKET;
brandtr1e3dfbf2016-11-16 22:45:19 -0800765 }
766
brandtr1134b7b2017-02-06 06:35:47 -0800767 // To reduce test flakiness, always let RTX packets through.
768 if (header.payloadType == test::CallTest::kSendRtxPayloadType) {
769 EXPECT_EQ(test::CallTest::kSendRtxSsrcs[0], header.ssrc);
770
771 // Parse RTX header.
772 uint16_t original_sequence_number =
773 ByteReader<uint16_t>::ReadBigEndian(&packet[header.headerLength]);
774
775 // From the perspective of FEC, a retransmitted packet is no longer
776 // dropped, so remove it from list of dropped packets.
777 auto seq_num_it =
778 dropped_sequence_numbers_.find(original_sequence_number);
brandtrfa5a3682017-01-17 01:33:54 -0800779 if (seq_num_it != dropped_sequence_numbers_.end()) {
780 dropped_sequence_numbers_.erase(seq_num_it);
781 auto ts_it = dropped_timestamps_.find(header.timestamp);
782 EXPECT_NE(ts_it, dropped_timestamps_.end());
783 dropped_timestamps_.erase(ts_it);
brandtrfd8d2652017-02-06 06:19:51 -0800784 }
brandtr1134b7b2017-02-06 06:35:47 -0800785
786 return SEND_PACKET;
brandtrfa5a3682017-01-17 01:33:54 -0800787 }
788
brandtr1134b7b2017-02-06 06:35:47 -0800789 // Simulate 5% video packet loss after rampup period. Record the
790 // corresponding timestamps that were dropped.
791 if (num_packets_sent_++ > 100 && random_.Rand(1, 100) <= 5) {
792 EXPECT_EQ(test::CallTest::kFakeVideoSendPayloadType, header.payloadType);
793 EXPECT_EQ(test::CallTest::kVideoSendSsrcs[0], header.ssrc);
794
795 dropped_sequence_numbers_.insert(header.sequenceNumber);
796 dropped_timestamps_.insert(header.timestamp);
brandtrfa5a3682017-01-17 01:33:54 -0800797
798 return DROP_PACKET;
799 }
800
801 return SEND_PACKET;
802 }
803
804 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
805 test::RtcpPacketParser parser;
806
807 parser.Parse(data, length);
808 if (parser.sender_ssrc() == kFlexfecLocalSsrc) {
809 EXPECT_EQ(1, parser.receiver_report()->num_packets());
810 const std::vector<rtcp::ReportBlock>& report_blocks =
811 parser.receiver_report()->report_blocks();
812 if (!report_blocks.empty()) {
813 EXPECT_EQ(1U, report_blocks.size());
814 EXPECT_EQ(test::CallTest::kFlexfecSendSsrc,
815 report_blocks[0].source_ssrc());
brandtr1d2d7892017-01-18 00:40:07 -0800816 rtc::CritScope lock(&crit_);
brandtrfa5a3682017-01-17 01:33:54 -0800817 received_flexfec_rtcp_ = true;
818 }
819 }
820
821 return SEND_PACKET;
822 }
823
eladalon413ee9a2017-08-22 04:02:52 -0700824 test::PacketTransport* CreateSendTransport(
825 test::SingleThreadedTaskQueueForTesting* task_queue,
826 Call* sender_call) override {
brandtr1134b7b2017-02-06 06:35:47 -0800827 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
828 const int kNetworkDelayMs = 100;
829 FakeNetworkPipe::Config config;
830 config.queue_delay_ms = kNetworkDelayMs;
eladalon413ee9a2017-08-22 04:02:52 -0700831 return new test::PacketTransport(task_queue, sender_call, this,
nissee5ad5ca2017-03-29 23:57:43 -0700832 test::PacketTransport::kSender,
minyue20c84cc2017-04-10 16:57:57 -0700833 test::CallTest::payload_type_map_, config);
brandtr1134b7b2017-02-06 06:35:47 -0800834 }
835
brandtrfa5a3682017-01-17 01:33:54 -0800836 void OnFrame(const VideoFrame& video_frame) override {
brandtrcaea68f2017-08-23 00:55:17 -0700837 EXPECT_EQ(kVideoRotation_90, video_frame.rotation());
838
brandtrfa5a3682017-01-17 01:33:54 -0800839 rtc::CritScope lock(&crit_);
840 // Rendering frame with timestamp of packet that was dropped -> FEC
841 // protection worked.
842 auto it = dropped_timestamps_.find(video_frame.timestamp());
843 if (it != dropped_timestamps_.end()) {
844 if (!expect_flexfec_rtcp_ || received_flexfec_rtcp_) {
brandtr1e3dfbf2016-11-16 22:45:19 -0800845 observation_complete_.Set();
brandtrfa5a3682017-01-17 01:33:54 -0800846 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800847 }
brandtrfa5a3682017-01-17 01:33:54 -0800848 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800849
brandtrfa5a3682017-01-17 01:33:54 -0800850 void ModifyVideoConfigs(
851 VideoSendStream::Config* send_config,
852 std::vector<VideoReceiveStream::Config>* receive_configs,
853 VideoEncoderConfig* encoder_config) override {
854 (*receive_configs)[0].rtp.local_ssrc = kVideoLocalSsrc;
855 (*receive_configs)[0].renderer = this;
brandtr1134b7b2017-02-06 06:35:47 -0800856
857 if (enable_nack_) {
858 send_config->rtp.nack.rtp_history_ms = test::CallTest::kNackRtpHistoryMs;
brandtr1134b7b2017-02-06 06:35:47 -0800859 send_config->rtp.rtx.ssrcs.push_back(test::CallTest::kSendRtxSsrcs[0]);
860 send_config->rtp.rtx.payload_type = test::CallTest::kSendRtxPayloadType;
861
862 (*receive_configs)[0].rtp.nack.rtp_history_ms =
863 test::CallTest::kNackRtpHistoryMs;
brandtr1134b7b2017-02-06 06:35:47 -0800864 (*receive_configs)[0].rtp.rtx_ssrc = test::CallTest::kSendRtxSsrcs[0];
865 (*receive_configs)[0]
nisse26e3abb2017-08-25 04:44:25 -0700866 .rtp
867 .rtx_associated_payload_types[test::CallTest::kSendRtxPayloadType] =
868 test::CallTest::kVideoSendPayloadType;
brandtr1134b7b2017-02-06 06:35:47 -0800869 }
brandtrfa5a3682017-01-17 01:33:54 -0800870 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800871
brandtrcaea68f2017-08-23 00:55:17 -0700872 void OnFrameGeneratorCapturerCreated(
873 test::FrameGeneratorCapturer* frame_generator_capturer) override {
874 frame_generator_capturer->SetFakeRotation(kVideoRotation_90);
875 }
876
brandtrfa5a3682017-01-17 01:33:54 -0800877 void ModifyFlexfecConfigs(
878 std::vector<FlexfecReceiveStream::Config>* receive_configs) override {
879 (*receive_configs)[0].local_ssrc = kFlexfecLocalSsrc;
880 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000881
brandtrfa5a3682017-01-17 01:33:54 -0800882 void PerformTest() override {
883 EXPECT_TRUE(Wait())
884 << "Timed out waiting for dropped frames to be rendered.";
885 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000886
brandtrfa5a3682017-01-17 01:33:54 -0800887 rtc::CriticalSection crit_;
danilchapa37de392017-09-09 04:17:22 -0700888 std::set<uint32_t> dropped_sequence_numbers_ RTC_GUARDED_BY(crit_);
brandtr1134b7b2017-02-06 06:35:47 -0800889 // Several packets can have the same timestamp.
danilchapa37de392017-09-09 04:17:22 -0700890 std::multiset<uint32_t> dropped_timestamps_ RTC_GUARDED_BY(crit_);
brandtr1134b7b2017-02-06 06:35:47 -0800891 const bool enable_nack_;
brandtr1d2d7892017-01-18 00:40:07 -0800892 const bool expect_flexfec_rtcp_;
danilchapa37de392017-09-09 04:17:22 -0700893 bool received_flexfec_rtcp_ RTC_GUARDED_BY(crit_);
brandtrfa5a3682017-01-17 01:33:54 -0800894 Random random_;
brandtr1134b7b2017-02-06 06:35:47 -0800895 int num_packets_sent_;
brandtrfa5a3682017-01-17 01:33:54 -0800896};
897
philipelccdfcca2017-10-23 12:42:17 +0200898TEST_P(EndToEndTest, RecoversWithFlexfec) {
brandtr1134b7b2017-02-06 06:35:47 -0800899 FlexfecRenderObserver test(false, false);
brandtrfa5a3682017-01-17 01:33:54 -0800900 RunBaseTest(&test);
901}
902
philipelccdfcca2017-10-23 12:42:17 +0200903TEST_P(EndToEndTest, RecoversWithFlexfecAndNack) {
brandtr1134b7b2017-02-06 06:35:47 -0800904 FlexfecRenderObserver test(true, false);
905 RunBaseTest(&test);
906}
907
philipelccdfcca2017-10-23 12:42:17 +0200908TEST_P(EndToEndTest, RecoversWithFlexfecAndSendsCorrespondingRtcp) {
brandtr1134b7b2017-02-06 06:35:47 -0800909 FlexfecRenderObserver test(false, true);
stefane74eef12016-01-08 06:47:13 -0800910 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000911}
912
philipelccdfcca2017-10-23 12:42:17 +0200913TEST_P(EndToEndTest, ReceivedUlpfecPacketsNotNacked) {
brandtr535830e2016-10-31 03:45:58 -0700914 class UlpfecNackObserver : public test::EndToEndTest {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000915 public:
brandtr535830e2016-10-31 03:45:58 -0700916 UlpfecNackObserver()
stefanf116bd02015-10-27 08:29:42 -0700917 : EndToEndTest(kDefaultTimeoutMs),
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000918 state_(kFirstPacket),
brandtr535830e2016-10-31 03:45:58 -0700919 ulpfec_sequence_number_(0),
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000920 has_last_sequence_number_(false),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200921 last_sequence_number_(0),
magjed509e4fe2016-11-18 01:34:11 -0800922 encoder_(VP8Encoder::Create()),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200923 decoder_(VP8Decoder::Create()) {}
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000924
925 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000926 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800927 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000928 RTPHeader header;
929 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000930
Stefan Holmer01b48882015-05-05 10:21:24 +0200931 int encapsulated_payload_type = -1;
932 if (header.payloadType == kRedPayloadType) {
933 encapsulated_payload_type =
934 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100935 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200936 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
937 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100938 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200939 }
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000940
941 if (has_last_sequence_number_ &&
942 !IsNewerSequenceNumber(header.sequenceNumber,
943 last_sequence_number_)) {
944 // Drop retransmitted packets.
945 return DROP_PACKET;
946 }
947 last_sequence_number_ = header.sequenceNumber;
948 has_last_sequence_number_ = true;
949
brandtr535830e2016-10-31 03:45:58 -0700950 bool ulpfec_packet = encapsulated_payload_type == kUlpfecPayloadType;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000951 switch (state_) {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000952 case kFirstPacket:
brandtr535830e2016-10-31 03:45:58 -0700953 state_ = kDropEveryOtherPacketUntilUlpfec;
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000954 break;
brandtr535830e2016-10-31 03:45:58 -0700955 case kDropEveryOtherPacketUntilUlpfec:
956 if (ulpfec_packet) {
957 state_ = kDropAllMediaPacketsUntilUlpfec;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000958 } else if (header.sequenceNumber % 2 == 0) {
959 return DROP_PACKET;
960 }
961 break;
brandtr535830e2016-10-31 03:45:58 -0700962 case kDropAllMediaPacketsUntilUlpfec:
963 if (!ulpfec_packet)
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000964 return DROP_PACKET;
brandtr535830e2016-10-31 03:45:58 -0700965 ulpfec_sequence_number_ = header.sequenceNumber;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200966 state_ = kDropOneMediaPacket;
967 break;
968 case kDropOneMediaPacket:
brandtr535830e2016-10-31 03:45:58 -0700969 if (ulpfec_packet)
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200970 return DROP_PACKET;
971 state_ = kPassOneMediaPacket;
972 return DROP_PACKET;
973 break;
974 case kPassOneMediaPacket:
brandtr535830e2016-10-31 03:45:58 -0700975 if (ulpfec_packet)
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200976 return DROP_PACKET;
977 // Pass one media packet after dropped packet after last FEC,
978 // otherwise receiver might never see a seq_no after
brandtr535830e2016-10-31 03:45:58 -0700979 // |ulpfec_sequence_number_|
980 state_ = kVerifyUlpfecPacketNotInNackList;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000981 break;
brandtr535830e2016-10-31 03:45:58 -0700982 case kVerifyUlpfecPacketNotInNackList:
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000983 // Continue to drop packets. Make sure no frame can be decoded.
brandtr535830e2016-10-31 03:45:58 -0700984 if (ulpfec_packet || header.sequenceNumber % 2 == 0)
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000985 return DROP_PACKET;
986 break;
987 }
988 return SEND_PACKET;
989 }
990
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000991 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800992 rtc::CritScope lock_(&crit_);
brandtr535830e2016-10-31 03:45:58 -0700993 if (state_ == kVerifyUlpfecPacketNotInNackList) {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000994 test::RtcpPacketParser rtcp_parser;
995 rtcp_parser.Parse(packet, length);
Danil Chapovalovba6f7be2016-09-02 18:29:10 +0200996 const std::vector<uint16_t>& nacks = rtcp_parser.nack()->packet_ids();
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200997 EXPECT_TRUE(std::find(nacks.begin(), nacks.end(),
brandtr535830e2016-10-31 03:45:58 -0700998 ulpfec_sequence_number_) == nacks.end())
999 << "Got nack for ULPFEC packet";
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001000 if (!nacks.empty() &&
brandtr535830e2016-10-31 03:45:58 -07001001 IsNewerSequenceNumber(nacks.back(), ulpfec_sequence_number_)) {
Peter Boström5811a392015-12-10 13:02:50 +01001002 observation_complete_.Set();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001003 }
1004 }
1005 return SEND_PACKET;
1006 }
1007
eladalon413ee9a2017-08-22 04:02:52 -07001008 test::PacketTransport* CreateSendTransport(
1009 test::SingleThreadedTaskQueueForTesting* task_queue,
1010 Call* sender_call) override {
stefane74eef12016-01-08 06:47:13 -08001011 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
1012 // Configure some network delay.
1013 const int kNetworkDelayMs = 50;
1014 FakeNetworkPipe::Config config;
1015 config.queue_delay_ms = kNetworkDelayMs;
eladalon413ee9a2017-08-22 04:02:52 -07001016 return new test::PacketTransport(task_queue, sender_call, this,
nissee5ad5ca2017-03-29 23:57:43 -07001017 test::PacketTransport::kSender,
minyue20c84cc2017-04-10 16:57:57 -07001018 payload_type_map_, config);
stefane74eef12016-01-08 06:47:13 -08001019 }
1020
Stefan Holmere5904162015-03-26 11:11:06 +01001021 // TODO(holmer): Investigate why we don't send FEC packets when the bitrate
1022 // is 10 kbps.
1023 Call::Config GetSenderCallConfig() override {
philipel4fb651d2017-04-10 03:54:05 -07001024 Call::Config config(event_log_.get());
Stefan Holmere5904162015-03-26 11:11:06 +01001025 const int kMinBitrateBps = 30000;
1026 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
1027 return config;
1028 }
1029
stefanff483612015-12-21 03:14:00 -08001030 void ModifyVideoConfigs(
1031 VideoSendStream::Config* send_config,
1032 std::vector<VideoReceiveStream::Config>* receive_configs,
1033 VideoEncoderConfig* encoder_config) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001034 // Configure hybrid NACK/FEC.
1035 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
brandtrb5f2c3f2016-10-04 23:28:39 -07001036 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
1037 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001038 // Set codec to VP8, otherwise NACK/FEC hybrid will be disabled.
1039 send_config->encoder_settings.encoder = encoder_.get();
1040 send_config->encoder_settings.payload_name = "VP8";
1041 send_config->encoder_settings.payload_type = kFakeVideoSendPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001042
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001043 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
nisse3b3622f2017-09-26 02:49:21 -07001044 (*receive_configs)[0].rtp.red_payload_type = kRedPayloadType;
1045 (*receive_configs)[0].rtp.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001046
1047 (*receive_configs)[0].decoders.resize(1);
1048 (*receive_configs)[0].decoders[0].payload_type =
1049 send_config->encoder_settings.payload_type;
1050 (*receive_configs)[0].decoders[0].payload_name =
1051 send_config->encoder_settings.payload_name;
1052 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001053 }
1054
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001055 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001056 EXPECT_TRUE(Wait())
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001057 << "Timed out while waiting for FEC packets to be received.";
1058 }
1059
1060 enum {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +00001061 kFirstPacket,
brandtr535830e2016-10-31 03:45:58 -07001062 kDropEveryOtherPacketUntilUlpfec,
1063 kDropAllMediaPacketsUntilUlpfec,
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001064 kDropOneMediaPacket,
1065 kPassOneMediaPacket,
brandtr535830e2016-10-31 03:45:58 -07001066 kVerifyUlpfecPacketNotInNackList,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001067 } state_;
1068
stefan608213e2015-11-01 14:56:10 -08001069 rtc::CriticalSection crit_;
danilchapa37de392017-09-09 04:17:22 -07001070 uint16_t ulpfec_sequence_number_ RTC_GUARDED_BY(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001071 bool has_last_sequence_number_;
1072 uint16_t last_sequence_number_;
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001073 std::unique_ptr<webrtc::VideoEncoder> encoder_;
1074 std::unique_ptr<webrtc::VideoDecoder> decoder_;
stefanf116bd02015-10-27 08:29:42 -07001075 } test;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001076
stefane74eef12016-01-08 06:47:13 -08001077 RunBaseTest(&test);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001078}
1079
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001080// This test drops second RTP packet with a marker bit set, makes sure it's
1081// retransmitted and renders. Retransmission SSRCs are also checked.
Peter Boström39593972016-02-15 11:27:15 +01001082void EndToEndTest::DecodesRetransmittedFrame(bool enable_rtx, bool enable_red) {
Peter Boström67680c12016-02-17 11:10:04 +01001083 static const int kDroppedFrameNumber = 10;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001084 class RetransmissionObserver : public test::EndToEndTest,
nisse76bc8e82017-02-07 09:37:41 -08001085 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001086 public:
Peter Boström39593972016-02-15 11:27:15 +01001087 RetransmissionObserver(bool enable_rtx, bool enable_red)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001088 : EndToEndTest(kDefaultTimeoutMs),
Peter Boström39593972016-02-15 11:27:15 +01001089 payload_type_(GetPayloadType(false, enable_red)),
1090 retransmission_ssrc_(enable_rtx ? kSendRtxSsrcs[0]
1091 : kVideoSendSsrcs[0]),
1092 retransmission_payload_type_(GetPayloadType(enable_rtx, enable_red)),
magjed509e4fe2016-11-18 01:34:11 -08001093 encoder_(VP8Encoder::Create()),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001094 marker_bits_observed_(0),
danilchap192717e2016-07-25 08:20:51 -07001095 retransmitted_timestamp_(0) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001096
1097 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001098 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001099 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001100 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001101 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001102
Peter Boström67680c12016-02-17 11:10:04 +01001103 // Ignore padding-only packets over RTX.
1104 if (header.payloadType != payload_type_) {
1105 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
1106 if (length == header.headerLength + header.paddingLength)
1107 return SEND_PACKET;
Stefan Holmer586b19b2015-09-18 11:14:31 +02001108 }
Peter Boström67680c12016-02-17 11:10:04 +01001109
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001110 if (header.timestamp == retransmitted_timestamp_) {
1111 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
1112 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001113 return SEND_PACKET;
1114 }
1115
Stefan Holmer586b19b2015-09-18 11:14:31 +02001116 // Found the final packet of the frame to inflict loss to, drop this and
1117 // expect a retransmission.
danilchapfdd381c2016-07-25 04:03:20 -07001118 if (header.payloadType == payload_type_ && header.markerBit &&
1119 ++marker_bits_observed_ == kDroppedFrameNumber) {
Danil Chapovalov18c65a42016-06-29 15:29:34 +02001120 // This should be the only dropped packet.
1121 EXPECT_EQ(0u, retransmitted_timestamp_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001122 retransmitted_timestamp_ = header.timestamp;
danilchap192717e2016-07-25 08:20:51 -07001123 if (std::find(rendered_timestamps_.begin(), rendered_timestamps_.end(),
1124 retransmitted_timestamp_) != rendered_timestamps_.end()) {
1125 // Frame was rendered before last packet was scheduled for sending.
1126 // This is extremly rare but possible scenario because prober able to
1127 // resend packet before it was send.
1128 // TODO(danilchap): Remove this corner case when prober would not be
1129 // able to sneak in between packet saved to history for resending and
1130 // pacer notified about existance of that packet for sending.
1131 // See https://bugs.chromium.org/p/webrtc/issues/detail?id=5540 for
1132 // details.
1133 observation_complete_.Set();
1134 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001135 return DROP_PACKET;
1136 }
1137
1138 return SEND_PACKET;
1139 }
1140
nisse76bc8e82017-02-07 09:37:41 -08001141 void OnFrame(const VideoFrame& frame) override {
brandtrcaea68f2017-08-23 00:55:17 -07001142 EXPECT_EQ(kVideoRotation_90, frame.rotation());
stefan5d837802017-02-08 07:09:05 -08001143 {
1144 rtc::CritScope lock(&crit_);
1145 if (frame.timestamp() == retransmitted_timestamp_)
1146 observation_complete_.Set();
1147 rendered_timestamps_.push_back(frame.timestamp());
1148 }
nisse76bc8e82017-02-07 09:37:41 -08001149 orig_renderer_->OnFrame(frame);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001150 }
1151
stefanff483612015-12-21 03:14:00 -08001152 void ModifyVideoConfigs(
1153 VideoSendStream::Config* send_config,
1154 std::vector<VideoReceiveStream::Config>* receive_configs,
1155 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001156 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
nisse76bc8e82017-02-07 09:37:41 -08001157
1158 // Insert ourselves into the rendering pipeline.
1159 RTC_DCHECK(!orig_renderer_);
1160 orig_renderer_ = (*receive_configs)[0].renderer;
1161 RTC_DCHECK(orig_renderer_);
stefan5d837802017-02-08 07:09:05 -08001162 (*receive_configs)[0].disable_prerenderer_smoothing = true;
nisse76bc8e82017-02-07 09:37:41 -08001163 (*receive_configs)[0].renderer = this;
1164
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001165 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
Shao Changbine62202f2015-04-21 20:24:50 +08001166
1167 if (payload_type_ == kRedPayloadType) {
brandtrb5f2c3f2016-10-04 23:28:39 -07001168 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
1169 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +01001170 if (retransmission_ssrc_ == kSendRtxSsrcs[0])
brandtrb5f2c3f2016-10-04 23:28:39 -07001171 send_config->rtp.ulpfec.red_rtx_payload_type = kRtxRedPayloadType;
nisse3b3622f2017-09-26 02:49:21 -07001172 (*receive_configs)[0].rtp.ulpfec_payload_type =
brandtrb5f2c3f2016-10-04 23:28:39 -07001173 send_config->rtp.ulpfec.ulpfec_payload_type;
nisse3b3622f2017-09-26 02:49:21 -07001174 (*receive_configs)[0].rtp.red_payload_type =
brandtrb5f2c3f2016-10-04 23:28:39 -07001175 send_config->rtp.ulpfec.red_payload_type;
Shao Changbine62202f2015-04-21 20:24:50 +08001176 }
1177
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001178 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
1179 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001180 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
brandtr14742122017-01-27 04:53:07 -08001181 (*receive_configs)[0].rtp.rtx_ssrc = kSendRtxSsrcs[0];
nisse26e3abb2017-08-25 04:44:25 -07001182 (*receive_configs)[0]
nisseca5706d2017-09-11 02:32:16 -07001183 .rtp.rtx_associated_payload_types[(payload_type_ == kRedPayloadType)
1184 ? kRtxRedPayloadType
1185 : kSendRtxPayloadType] =
nisse26e3abb2017-08-25 04:44:25 -07001186 payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001187 }
Peter Boström39593972016-02-15 11:27:15 +01001188 // Configure encoding and decoding with VP8, since generic packetization
1189 // doesn't support FEC with NACK.
kwibergaf476c72016-11-28 15:21:39 -08001190 RTC_DCHECK_EQ(1, (*receive_configs)[0].decoders.size());
Peter Boström39593972016-02-15 11:27:15 +01001191 send_config->encoder_settings.encoder = encoder_.get();
1192 send_config->encoder_settings.payload_name = "VP8";
1193 (*receive_configs)[0].decoders[0].payload_name = "VP8";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001194 }
1195
brandtrcaea68f2017-08-23 00:55:17 -07001196 void OnFrameGeneratorCapturerCreated(
1197 test::FrameGeneratorCapturer* frame_generator_capturer) override {
1198 frame_generator_capturer->SetFakeRotation(kVideoRotation_90);
1199 }
1200
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001201 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001202 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001203 << "Timed out while waiting for retransmission to render.";
1204 }
1205
nisse3b3622f2017-09-26 02:49:21 -07001206 int GetPayloadType(bool use_rtx, bool use_fec) {
1207 if (use_fec) {
Stefan Holmer10880012016-02-03 13:29:59 +01001208 if (use_rtx)
1209 return kRtxRedPayloadType;
1210 return kRedPayloadType;
1211 }
1212 if (use_rtx)
1213 return kSendRtxPayloadType;
1214 return kFakeVideoSendPayloadType;
Shao Changbine62202f2015-04-21 20:24:50 +08001215 }
1216
stefanf116bd02015-10-27 08:29:42 -07001217 rtc::CriticalSection crit_;
nisse76bc8e82017-02-07 09:37:41 -08001218 rtc::VideoSinkInterface<VideoFrame>* orig_renderer_ = nullptr;
Shao Changbine62202f2015-04-21 20:24:50 +08001219 const int payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001220 const uint32_t retransmission_ssrc_;
1221 const int retransmission_payload_type_;
kwiberg27f982b2016-03-01 11:52:33 -08001222 std::unique_ptr<VideoEncoder> encoder_;
Peter Boström39593972016-02-15 11:27:15 +01001223 const std::string payload_name_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001224 int marker_bits_observed_;
danilchapa37de392017-09-09 04:17:22 -07001225 uint32_t retransmitted_timestamp_ RTC_GUARDED_BY(&crit_);
1226 std::vector<uint32_t> rendered_timestamps_ RTC_GUARDED_BY(&crit_);
Peter Boström39593972016-02-15 11:27:15 +01001227 } test(enable_rtx, enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001228
stefane74eef12016-01-08 06:47:13 -08001229 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001230}
1231
philipelccdfcca2017-10-23 12:42:17 +02001232TEST_P(EndToEndTest, DecodesRetransmittedFrame) {
Shao Changbine62202f2015-04-21 20:24:50 +08001233 DecodesRetransmittedFrame(false, false);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001234}
1235
philipelccdfcca2017-10-23 12:42:17 +02001236TEST_P(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +08001237 DecodesRetransmittedFrame(true, false);
1238}
1239
philipelccdfcca2017-10-23 12:42:17 +02001240TEST_P(EndToEndTest, DecodesRetransmittedFrameByRed) {
Shao Changbine62202f2015-04-21 20:24:50 +08001241 DecodesRetransmittedFrame(false, true);
1242}
1243
philipelccdfcca2017-10-23 12:42:17 +02001244TEST_P(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +08001245 DecodesRetransmittedFrame(true, true);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001246}
1247
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001248void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
1249 static const int kPacketsToDrop = 1;
1250
nisse7ade7b32016-03-23 04:48:10 -07001251 class PliObserver : public test::EndToEndTest,
1252 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001253 public:
1254 explicit PliObserver(int rtp_history_ms)
1255 : EndToEndTest(kLongTimeoutMs),
1256 rtp_history_ms_(rtp_history_ms),
1257 nack_enabled_(rtp_history_ms > 0),
1258 highest_dropped_timestamp_(0),
1259 frames_to_drop_(0),
1260 received_pli_(false) {}
1261
1262 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001263 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001264 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001265 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001266 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001267
1268 // Drop all retransmitted packets to force a PLI.
1269 if (header.timestamp <= highest_dropped_timestamp_)
1270 return DROP_PACKET;
1271
1272 if (frames_to_drop_ > 0) {
1273 highest_dropped_timestamp_ = header.timestamp;
1274 --frames_to_drop_;
1275 return DROP_PACKET;
1276 }
1277
1278 return SEND_PACKET;
1279 }
1280
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001281 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001282 rtc::CritScope lock(&crit_);
danilchap3dc929e2016-11-02 08:21:59 -07001283 test::RtcpPacketParser parser;
1284 EXPECT_TRUE(parser.Parse(packet, length));
1285 if (!nack_enabled_)
1286 EXPECT_EQ(0, parser.nack()->num_packets());
1287 if (parser.pli()->num_packets() > 0)
1288 received_pli_ = true;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001289 return SEND_PACKET;
1290 }
1291
nisseeb83a1a2016-03-21 01:27:56 -07001292 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001293 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001294 if (received_pli_ &&
1295 video_frame.timestamp() > highest_dropped_timestamp_) {
Peter Boström5811a392015-12-10 13:02:50 +01001296 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001297 }
1298 if (!received_pli_)
1299 frames_to_drop_ = kPacketsToDrop;
1300 }
1301
stefanff483612015-12-21 03:14:00 -08001302 void ModifyVideoConfigs(
1303 VideoSendStream::Config* send_config,
1304 std::vector<VideoReceiveStream::Config>* receive_configs,
1305 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001306 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001307 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
1308 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001309 }
1310
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001311 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001312 EXPECT_TRUE(Wait()) << "Timed out waiting for PLI to be "
1313 "received and a frame to be "
1314 "rendered afterwards.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001315 }
1316
stefanf116bd02015-10-27 08:29:42 -07001317 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001318 int rtp_history_ms_;
1319 bool nack_enabled_;
danilchapa37de392017-09-09 04:17:22 -07001320 uint32_t highest_dropped_timestamp_ RTC_GUARDED_BY(&crit_);
1321 int frames_to_drop_ RTC_GUARDED_BY(&crit_);
1322 bool received_pli_ RTC_GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001323 } test(rtp_history_ms);
1324
stefane74eef12016-01-08 06:47:13 -08001325 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001326}
1327
philipelccdfcca2017-10-23 12:42:17 +02001328TEST_P(EndToEndTest, ReceivesPliAndRecoversWithNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001329 ReceivesPliAndRecovers(1000);
1330}
1331
philipelccdfcca2017-10-23 12:42:17 +02001332TEST_P(EndToEndTest, ReceivesPliAndRecoversWithoutNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001333 ReceivesPliAndRecovers(0);
1334}
1335
philipelccdfcca2017-10-23 12:42:17 +02001336TEST_P(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001337 class PacketInputObserver : public PacketReceiver {
1338 public:
1339 explicit PacketInputObserver(PacketReceiver* receiver)
Peter Boström5811a392015-12-10 13:02:50 +01001340 : receiver_(receiver), delivered_packet_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001341
Peter Boström5811a392015-12-10 13:02:50 +01001342 bool Wait() { return delivered_packet_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001343
1344 private:
stefan68786d22015-09-08 05:36:15 -07001345 DeliveryStatus DeliverPacket(MediaType media_type,
1346 const uint8_t* packet,
1347 size_t length,
1348 const PacketTime& packet_time) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001349 if (RtpHeaderParser::IsRtcp(packet, length)) {
stefan68786d22015-09-08 05:36:15 -07001350 return receiver_->DeliverPacket(media_type, packet, length,
1351 packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001352 } else {
1353 DeliveryStatus delivery_status =
stefan68786d22015-09-08 05:36:15 -07001354 receiver_->DeliverPacket(media_type, packet, length, packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001355 EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
Peter Boström5811a392015-12-10 13:02:50 +01001356 delivered_packet_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001357 return delivery_status;
1358 }
1359 }
1360
1361 PacketReceiver* receiver_;
Peter Boström5811a392015-12-10 13:02:50 +01001362 rtc::Event delivered_packet_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001363 };
1364
eladalon413ee9a2017-08-22 04:02:52 -07001365 std::unique_ptr<test::DirectTransport> send_transport;
1366 std::unique_ptr<test::DirectTransport> receive_transport;
1367 std::unique_ptr<PacketInputObserver> input_observer;
solenberg4fbae2b2015-08-28 04:07:10 -07001368
eladalon413ee9a2017-08-22 04:02:52 -07001369 task_queue_.SendTask([this, &send_transport, &receive_transport,
1370 &input_observer]() {
1371 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001372
eladalon413ee9a2017-08-22 04:02:52 -07001373 send_transport = rtc::MakeUnique<test::DirectTransport>(
1374 &task_queue_, sender_call_.get(), payload_type_map_);
1375 receive_transport = rtc::MakeUnique<test::DirectTransport>(
1376 &task_queue_, receiver_call_.get(), payload_type_map_);
1377 input_observer =
1378 rtc::MakeUnique<PacketInputObserver>(receiver_call_->Receiver());
1379 send_transport->SetReceiver(input_observer.get());
1380 receive_transport->SetReceiver(sender_call_->Receiver());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001381
eladalon413ee9a2017-08-22 04:02:52 -07001382 CreateSendConfig(1, 0, 0, send_transport.get());
1383 CreateMatchingReceiveConfigs(receive_transport.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001384
eladalon413ee9a2017-08-22 04:02:52 -07001385 CreateVideoStreams();
1386 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
1387 kDefaultHeight);
1388 Start();
1389
1390 receiver_call_->DestroyVideoReceiveStream(video_receive_streams_[0]);
1391 video_receive_streams_.clear();
1392 });
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001393
1394 // Wait() waits for a received packet.
eladalon413ee9a2017-08-22 04:02:52 -07001395 EXPECT_TRUE(input_observer->Wait());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001396
eladalon413ee9a2017-08-22 04:02:52 -07001397 task_queue_.SendTask([this, &send_transport, &receive_transport]() {
1398 Stop();
1399 DestroyStreams();
1400 send_transport.reset();
1401 receive_transport.reset();
1402 DestroyCalls();
1403 });
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001404}
1405
pbosda903ea2015-10-02 02:36:56 -07001406void EndToEndTest::RespectsRtcpMode(RtcpMode rtcp_mode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001407 static const int kNumCompoundRtcpPacketsToObserve = 10;
1408 class RtcpModeObserver : public test::EndToEndTest {
1409 public:
pbosda903ea2015-10-02 02:36:56 -07001410 explicit RtcpModeObserver(RtcpMode rtcp_mode)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001411 : EndToEndTest(kDefaultTimeoutMs),
1412 rtcp_mode_(rtcp_mode),
1413 sent_rtp_(0),
1414 sent_rtcp_(0) {}
1415
1416 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001417 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanb77c7162017-02-06 06:29:38 -08001418 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001419 if (++sent_rtp_ % 3 == 0)
1420 return DROP_PACKET;
1421
1422 return SEND_PACKET;
1423 }
1424
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001425 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanb77c7162017-02-06 06:29:38 -08001426 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001427 ++sent_rtcp_;
danilchap3dc929e2016-11-02 08:21:59 -07001428 test::RtcpPacketParser parser;
1429 EXPECT_TRUE(parser.Parse(packet, length));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001430
danilchap3dc929e2016-11-02 08:21:59 -07001431 EXPECT_EQ(0, parser.sender_report()->num_packets());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001432
1433 switch (rtcp_mode_) {
pbosda903ea2015-10-02 02:36:56 -07001434 case RtcpMode::kCompound:
stefanb77c7162017-02-06 06:29:38 -08001435 // TODO(holmer): We shouldn't send transport feedback alone if
1436 // compound RTCP is negotiated.
1437 if (parser.receiver_report()->num_packets() == 0 &&
1438 parser.transport_feedback()->num_packets() == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001439 ADD_FAILURE() << "Received RTCP packet without receiver report for "
pbosda903ea2015-10-02 02:36:56 -07001440 "RtcpMode::kCompound.";
Peter Boström5811a392015-12-10 13:02:50 +01001441 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001442 }
1443
1444 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
Peter Boström5811a392015-12-10 13:02:50 +01001445 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001446
1447 break;
pbosda903ea2015-10-02 02:36:56 -07001448 case RtcpMode::kReducedSize:
danilchap3dc929e2016-11-02 08:21:59 -07001449 if (parser.receiver_report()->num_packets() == 0)
Peter Boström5811a392015-12-10 13:02:50 +01001450 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001451 break;
pbosda903ea2015-10-02 02:36:56 -07001452 case RtcpMode::kOff:
1453 RTC_NOTREACHED();
1454 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001455 }
1456
1457 return SEND_PACKET;
1458 }
1459
stefanff483612015-12-21 03:14:00 -08001460 void ModifyVideoConfigs(
1461 VideoSendStream::Config* send_config,
1462 std::vector<VideoReceiveStream::Config>* receive_configs,
1463 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001464 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001465 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1466 (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001467 }
1468
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001469 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001470 EXPECT_TRUE(Wait())
pbosda903ea2015-10-02 02:36:56 -07001471 << (rtcp_mode_ == RtcpMode::kCompound
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001472 ? "Timed out before observing enough compound packets."
1473 : "Timed out before receiving a non-compound RTCP packet.");
1474 }
1475
pbosda903ea2015-10-02 02:36:56 -07001476 RtcpMode rtcp_mode_;
stefanb77c7162017-02-06 06:29:38 -08001477 rtc::CriticalSection crit_;
1478 // Must be protected since RTCP can be sent by both the process thread
1479 // and the pacer thread.
danilchapa37de392017-09-09 04:17:22 -07001480 int sent_rtp_ RTC_GUARDED_BY(&crit_);
1481 int sent_rtcp_ RTC_GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001482 } test(rtcp_mode);
1483
stefane74eef12016-01-08 06:47:13 -08001484 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001485}
1486
philipelccdfcca2017-10-23 12:42:17 +02001487TEST_P(EndToEndTest, UsesRtcpCompoundMode) {
pbosda903ea2015-10-02 02:36:56 -07001488 RespectsRtcpMode(RtcpMode::kCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001489}
1490
philipelccdfcca2017-10-23 12:42:17 +02001491TEST_P(EndToEndTest, UsesRtcpReducedSizeMode) {
pbosda903ea2015-10-02 02:36:56 -07001492 RespectsRtcpMode(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001493}
1494
1495// Test sets up a Call multiple senders with different resolutions and SSRCs.
1496// Another is set up to receive all three of these with different renderers.
sprang867fb522015-08-03 04:38:41 -07001497class MultiStreamTest {
1498 public:
minyue20c84cc2017-04-10 16:57:57 -07001499 static constexpr size_t kNumStreams = 3;
1500 const uint8_t kVideoPayloadType = 124;
1501 const std::map<uint8_t, MediaType> payload_type_map_ = {
1502 {kVideoPayloadType, MediaType::VIDEO}};
1503
sprang867fb522015-08-03 04:38:41 -07001504 struct CodecSettings {
1505 uint32_t ssrc;
1506 int width;
1507 int height;
1508 } codec_settings[kNumStreams];
1509
eladalon413ee9a2017-08-22 04:02:52 -07001510 explicit MultiStreamTest(test::SingleThreadedTaskQueueForTesting* task_queue)
1511 : task_queue_(task_queue) {
sprang867fb522015-08-03 04:38:41 -07001512 // TODO(sprang): Cleanup when msvc supports explicit initializers for array.
1513 codec_settings[0] = {1, 640, 480};
1514 codec_settings[1] = {2, 320, 240};
1515 codec_settings[2] = {3, 240, 160};
1516 }
1517
1518 virtual ~MultiStreamTest() {}
1519
1520 void RunTest() {
skvlad11a9cbf2016-10-07 11:53:05 -07001521 webrtc::RtcEventLogNullImpl event_log;
1522 Call::Config config(&event_log);
eladalon413ee9a2017-08-22 04:02:52 -07001523 std::unique_ptr<Call> sender_call;
1524 std::unique_ptr<Call> receiver_call;
1525 std::unique_ptr<test::DirectTransport> sender_transport;
1526 std::unique_ptr<test::DirectTransport> receiver_transport;
sprang867fb522015-08-03 04:38:41 -07001527
1528 VideoSendStream* send_streams[kNumStreams];
1529 VideoReceiveStream* receive_streams[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001530 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
kwiberg4a206a92016-03-31 10:24:26 -07001531 std::vector<std::unique_ptr<VideoDecoder>> allocated_decoders;
eladalon413ee9a2017-08-22 04:02:52 -07001532 std::unique_ptr<VideoEncoder> encoders[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001533
eladalon413ee9a2017-08-22 04:02:52 -07001534 task_queue_->SendTask([&]() {
1535 sender_call = rtc::WrapUnique(Call::Create(config));
1536 receiver_call = rtc::WrapUnique(Call::Create(config));
1537 sender_transport =
1538 rtc::WrapUnique(CreateSendTransport(task_queue_, sender_call.get()));
1539 receiver_transport = rtc::WrapUnique(
1540 CreateReceiveTransport(task_queue_, receiver_call.get()));
sprang867fb522015-08-03 04:38:41 -07001541
eladalon413ee9a2017-08-22 04:02:52 -07001542 sender_transport->SetReceiver(receiver_call->Receiver());
1543 receiver_transport->SetReceiver(sender_call->Receiver());
sprang867fb522015-08-03 04:38:41 -07001544
eladalon413ee9a2017-08-22 04:02:52 -07001545 for (size_t i = 0; i < kNumStreams; ++i)
1546 encoders[i].reset(VP8Encoder::Create());
sprang867fb522015-08-03 04:38:41 -07001547
eladalon413ee9a2017-08-22 04:02:52 -07001548 for (size_t i = 0; i < kNumStreams; ++i) {
1549 uint32_t ssrc = codec_settings[i].ssrc;
1550 int width = codec_settings[i].width;
1551 int height = codec_settings[i].height;
sprang867fb522015-08-03 04:38:41 -07001552
eladalon413ee9a2017-08-22 04:02:52 -07001553 VideoSendStream::Config send_config(sender_transport.get());
1554 send_config.rtp.ssrcs.push_back(ssrc);
1555 send_config.encoder_settings.encoder = encoders[i].get();
1556 send_config.encoder_settings.payload_name = "VP8";
1557 send_config.encoder_settings.payload_type = kVideoPayloadType;
1558 VideoEncoderConfig encoder_config;
1559 test::FillEncoderConfiguration(1, &encoder_config);
1560 encoder_config.max_bitrate_bps = 100000;
sprang867fb522015-08-03 04:38:41 -07001561
eladalon413ee9a2017-08-22 04:02:52 -07001562 UpdateSendConfig(i, &send_config, &encoder_config,
1563 &frame_generators[i]);
sprang867fb522015-08-03 04:38:41 -07001564
eladalon413ee9a2017-08-22 04:02:52 -07001565 send_streams[i] = sender_call->CreateVideoSendStream(
1566 send_config.Copy(), encoder_config.Copy());
1567 send_streams[i]->Start();
1568
1569 VideoReceiveStream::Config receive_config(receiver_transport.get());
1570 receive_config.rtp.remote_ssrc = ssrc;
1571 receive_config.rtp.local_ssrc = test::CallTest::kReceiverLocalVideoSsrc;
1572 VideoReceiveStream::Decoder decoder =
1573 test::CreateMatchingDecoder(send_config.encoder_settings);
1574 allocated_decoders.push_back(
1575 std::unique_ptr<VideoDecoder>(decoder.decoder));
1576 receive_config.decoders.push_back(decoder);
1577
1578 UpdateReceiveConfig(i, &receive_config);
1579
1580 receive_streams[i] =
1581 receiver_call->CreateVideoReceiveStream(std::move(receive_config));
1582 receive_streams[i]->Start();
1583
1584 frame_generators[i] = test::FrameGeneratorCapturer::Create(
1585 width, height, 30, Clock::GetRealTimeClock());
1586 send_streams[i]->SetSource(
1587 frame_generators[i],
1588 VideoSendStream::DegradationPreference::kMaintainFramerate);
1589 frame_generators[i]->Start();
1590 }
1591 });
sprang867fb522015-08-03 04:38:41 -07001592
1593 Wait();
1594
eladalon413ee9a2017-08-22 04:02:52 -07001595 task_queue_->SendTask([&]() {
1596 for (size_t i = 0; i < kNumStreams; ++i) {
1597 frame_generators[i]->Stop();
1598 sender_call->DestroyVideoSendStream(send_streams[i]);
1599 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1600 delete frame_generators[i];
1601 }
sprang867fb522015-08-03 04:38:41 -07001602
eladalon413ee9a2017-08-22 04:02:52 -07001603 sender_transport.reset();
1604 receiver_transport.reset();
1605
1606 sender_call.reset();
1607 receiver_call.reset();
1608 });
sprang867fb522015-08-03 04:38:41 -07001609 }
1610
1611 protected:
1612 virtual void Wait() = 0;
1613 // Note: frame_generator is a point-to-pointer, since the actual instance
1614 // hasn't been created at the time of this call. Only when packets/frames
1615 // start flowing should this be dereferenced.
1616 virtual void UpdateSendConfig(
1617 size_t stream_index,
1618 VideoSendStream::Config* send_config,
1619 VideoEncoderConfig* encoder_config,
1620 test::FrameGeneratorCapturer** frame_generator) {}
1621 virtual void UpdateReceiveConfig(size_t stream_index,
1622 VideoReceiveStream::Config* receive_config) {
1623 }
eladalon413ee9a2017-08-22 04:02:52 -07001624 virtual test::DirectTransport* CreateSendTransport(
1625 test::SingleThreadedTaskQueueForTesting* task_queue,
1626 Call* sender_call) {
1627 return new test::DirectTransport(task_queue, sender_call,
1628 payload_type_map_);
sprang867fb522015-08-03 04:38:41 -07001629 }
eladalon413ee9a2017-08-22 04:02:52 -07001630 virtual test::DirectTransport* CreateReceiveTransport(
1631 test::SingleThreadedTaskQueueForTesting* task_queue,
1632 Call* receiver_call) {
1633 return new test::DirectTransport(task_queue, receiver_call,
1634 payload_type_map_);
sprang867fb522015-08-03 04:38:41 -07001635 }
eladalon413ee9a2017-08-22 04:02:52 -07001636
1637 test::SingleThreadedTaskQueueForTesting* const task_queue_;
sprang867fb522015-08-03 04:38:41 -07001638};
1639
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001640// Each renderer verifies that it receives the expected resolution, and as soon
1641// as every renderer has received a frame, the test finishes.
philipelccdfcca2017-10-23 12:42:17 +02001642TEST_P(EndToEndTest, SendsAndReceivesMultipleStreams) {
nisse7ade7b32016-03-23 04:48:10 -07001643 class VideoOutputObserver : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001644 public:
sprang867fb522015-08-03 04:38:41 -07001645 VideoOutputObserver(const MultiStreamTest::CodecSettings& settings,
1646 uint32_t ssrc,
1647 test::FrameGeneratorCapturer** frame_generator)
1648 : settings_(settings),
1649 ssrc_(ssrc),
1650 frame_generator_(frame_generator),
Peter Boström5811a392015-12-10 13:02:50 +01001651 done_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001652
nisseeb83a1a2016-03-21 01:27:56 -07001653 void OnFrame(const VideoFrame& video_frame) override {
sprang867fb522015-08-03 04:38:41 -07001654 EXPECT_EQ(settings_.width, video_frame.width());
1655 EXPECT_EQ(settings_.height, video_frame.height());
1656 (*frame_generator_)->Stop();
Peter Boström5811a392015-12-10 13:02:50 +01001657 done_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001658 }
1659
sprang867fb522015-08-03 04:38:41 -07001660 uint32_t Ssrc() { return ssrc_; }
1661
Peter Boström5811a392015-12-10 13:02:50 +01001662 bool Wait() { return done_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001663
1664 private:
sprang867fb522015-08-03 04:38:41 -07001665 const MultiStreamTest::CodecSettings& settings_;
1666 const uint32_t ssrc_;
1667 test::FrameGeneratorCapturer** const frame_generator_;
Peter Boström5811a392015-12-10 13:02:50 +01001668 rtc::Event done_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001669 };
1670
sprang867fb522015-08-03 04:38:41 -07001671 class Tester : public MultiStreamTest {
1672 public:
eladalon413ee9a2017-08-22 04:02:52 -07001673 explicit Tester(test::SingleThreadedTaskQueueForTesting* task_queue)
1674 : MultiStreamTest(task_queue) {}
sprang867fb522015-08-03 04:38:41 -07001675 virtual ~Tester() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001676
sprang867fb522015-08-03 04:38:41 -07001677 protected:
1678 void Wait() override {
1679 for (const auto& observer : observers_) {
Peter Boström5811a392015-12-10 13:02:50 +01001680 EXPECT_TRUE(observer->Wait()) << "Time out waiting for from on ssrc "
1681 << observer->Ssrc();
sprang867fb522015-08-03 04:38:41 -07001682 }
1683 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001684
sprang867fb522015-08-03 04:38:41 -07001685 void UpdateSendConfig(
1686 size_t stream_index,
1687 VideoSendStream::Config* send_config,
1688 VideoEncoderConfig* encoder_config,
1689 test::FrameGeneratorCapturer** frame_generator) override {
1690 observers_[stream_index].reset(new VideoOutputObserver(
1691 codec_settings[stream_index], send_config->rtp.ssrcs.front(),
1692 frame_generator));
1693 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001694
sprang867fb522015-08-03 04:38:41 -07001695 void UpdateReceiveConfig(
1696 size_t stream_index,
1697 VideoReceiveStream::Config* receive_config) override {
1698 receive_config->renderer = observers_[stream_index].get();
1699 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001700
sprang867fb522015-08-03 04:38:41 -07001701 private:
kwiberg27f982b2016-03-01 11:52:33 -08001702 std::unique_ptr<VideoOutputObserver> observers_[kNumStreams];
eladalon413ee9a2017-08-22 04:02:52 -07001703 } tester(&task_queue_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001704
sprang867fb522015-08-03 04:38:41 -07001705 tester.RunTest();
1706}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001707
philipelccdfcca2017-10-23 12:42:17 +02001708TEST_P(EndToEndTest, AssignsTransportSequenceNumbers) {
sprang867fb522015-08-03 04:38:41 -07001709 static const int kExtensionId = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001710
sprang867fb522015-08-03 04:38:41 -07001711 class RtpExtensionHeaderObserver : public test::DirectTransport {
1712 public:
minyue20c84cc2017-04-10 16:57:57 -07001713 RtpExtensionHeaderObserver(
eladalon413ee9a2017-08-22 04:02:52 -07001714 test::SingleThreadedTaskQueueForTesting* task_queue,
minyue20c84cc2017-04-10 16:57:57 -07001715 Call* sender_call,
1716 const uint32_t& first_media_ssrc,
1717 const std::map<uint32_t, uint32_t>& ssrc_map,
1718 const std::map<uint8_t, MediaType>& payload_type_map)
eladalon413ee9a2017-08-22 04:02:52 -07001719 : DirectTransport(task_queue, sender_call, payload_type_map),
Peter Boström5811a392015-12-10 13:02:50 +01001720 done_(false, false),
sprang867fb522015-08-03 04:38:41 -07001721 parser_(RtpHeaderParser::Create()),
sprang861c55e2015-10-16 10:01:21 -07001722 first_media_ssrc_(first_media_ssrc),
1723 rtx_to_media_ssrcs_(ssrc_map),
sprang867fb522015-08-03 04:38:41 -07001724 padding_observed_(false),
sprang861c55e2015-10-16 10:01:21 -07001725 rtx_padding_observed_(false),
1726 retransmit_observed_(false),
1727 started_(false) {
sprang867fb522015-08-03 04:38:41 -07001728 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
1729 kExtensionId);
1730 }
1731 virtual ~RtpExtensionHeaderObserver() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001732
stefan1d8a5062015-10-02 03:39:33 -07001733 bool SendRtp(const uint8_t* data,
1734 size_t length,
1735 const PacketOptions& options) override {
sprang861c55e2015-10-16 10:01:21 -07001736 {
1737 rtc::CritScope cs(&lock_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001738
Erik Språng8d629712015-08-04 16:24:03 +02001739 if (IsDone())
sprang861c55e2015-10-16 10:01:21 -07001740 return false;
1741
1742 if (started_) {
1743 RTPHeader header;
1744 EXPECT_TRUE(parser_->Parse(data, length, &header));
1745 bool drop_packet = false;
1746
1747 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
1748 EXPECT_EQ(options.packet_id,
1749 header.extension.transportSequenceNumber);
1750 if (!streams_observed_.empty()) {
1751 // Unwrap packet id and verify uniqueness.
1752 int64_t packet_id = unwrapper_.Unwrap(options.packet_id);
1753 EXPECT_TRUE(received_packed_ids_.insert(packet_id).second);
1754 }
1755
1756 // Drop (up to) every 17th packet, so we get retransmits.
1757 // Only drop media, and not on the first stream (otherwise it will be
1758 // hard to distinguish from padding, which is always sent on the first
1759 // stream).
1760 if (header.payloadType != kSendRtxPayloadType &&
1761 header.ssrc != first_media_ssrc_ &&
1762 header.extension.transportSequenceNumber % 17 == 0) {
1763 dropped_seq_[header.ssrc].insert(header.sequenceNumber);
1764 drop_packet = true;
1765 }
1766
perkja8ba1952017-02-27 06:52:10 -08001767 if (header.payloadType == kSendRtxPayloadType) {
sprang861c55e2015-10-16 10:01:21 -07001768 uint16_t original_sequence_number =
1769 ByteReader<uint16_t>::ReadBigEndian(&data[header.headerLength]);
1770 uint32_t original_ssrc =
1771 rtx_to_media_ssrcs_.find(header.ssrc)->second;
1772 std::set<uint16_t>* seq_no_map = &dropped_seq_[original_ssrc];
1773 auto it = seq_no_map->find(original_sequence_number);
1774 if (it != seq_no_map->end()) {
1775 retransmit_observed_ = true;
1776 seq_no_map->erase(it);
1777 } else {
1778 rtx_padding_observed_ = true;
1779 }
1780 } else {
1781 streams_observed_.insert(header.ssrc);
1782 }
1783
1784 if (IsDone())
Peter Boström5811a392015-12-10 13:02:50 +01001785 done_.Set();
sprang861c55e2015-10-16 10:01:21 -07001786
1787 if (drop_packet)
1788 return true;
1789 }
sprang867fb522015-08-03 04:38:41 -07001790 }
sprang861c55e2015-10-16 10:01:21 -07001791
stefan1d8a5062015-10-02 03:39:33 -07001792 return test::DirectTransport::SendRtp(data, length, options);
sprang867fb522015-08-03 04:38:41 -07001793 }
1794
Erik Språng8d629712015-08-04 16:24:03 +02001795 bool IsDone() {
sprang861c55e2015-10-16 10:01:21 -07001796 bool observed_types_ok =
1797 streams_observed_.size() == MultiStreamTest::kNumStreams &&
perkja8ba1952017-02-27 06:52:10 -08001798 retransmit_observed_ && rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001799 if (!observed_types_ok)
1800 return false;
1801 // We should not have any gaps in the sequence number range.
1802 size_t seqno_range =
1803 *received_packed_ids_.rbegin() - *received_packed_ids_.begin() + 1;
1804 return seqno_range == received_packed_ids_.size();
Erik Språng8d629712015-08-04 16:24:03 +02001805 }
1806
Peter Boström5811a392015-12-10 13:02:50 +01001807 bool Wait() {
sprang861c55e2015-10-16 10:01:21 -07001808 {
1809 // Can't be sure until this point that rtx_to_media_ssrcs_ etc have
1810 // been initialized and are OK to read.
1811 rtc::CritScope cs(&lock_);
1812 started_ = true;
1813 }
Peter Boström5811a392015-12-10 13:02:50 +01001814 return done_.Wait(kDefaultTimeoutMs);
sprang861c55e2015-10-16 10:01:21 -07001815 }
sprang867fb522015-08-03 04:38:41 -07001816
sprang861c55e2015-10-16 10:01:21 -07001817 rtc::CriticalSection lock_;
Peter Boström5811a392015-12-10 13:02:50 +01001818 rtc::Event done_;
kwiberg27f982b2016-03-01 11:52:33 -08001819 std::unique_ptr<RtpHeaderParser> parser_;
sprang861c55e2015-10-16 10:01:21 -07001820 SequenceNumberUnwrapper unwrapper_;
1821 std::set<int64_t> received_packed_ids_;
sprang867fb522015-08-03 04:38:41 -07001822 std::set<uint32_t> streams_observed_;
sprang861c55e2015-10-16 10:01:21 -07001823 std::map<uint32_t, std::set<uint16_t>> dropped_seq_;
1824 const uint32_t& first_media_ssrc_;
1825 const std::map<uint32_t, uint32_t>& rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001826 bool padding_observed_;
1827 bool rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001828 bool retransmit_observed_;
1829 bool started_;
sprang867fb522015-08-03 04:38:41 -07001830 };
1831
1832 class TransportSequenceNumberTester : public MultiStreamTest {
1833 public:
eladalon413ee9a2017-08-22 04:02:52 -07001834 explicit TransportSequenceNumberTester(
1835 test::SingleThreadedTaskQueueForTesting* task_queue)
1836 : MultiStreamTest(task_queue),
1837 first_media_ssrc_(0),
1838 observer_(nullptr) {}
sprang867fb522015-08-03 04:38:41 -07001839 virtual ~TransportSequenceNumberTester() {}
1840
1841 protected:
1842 void Wait() override {
Peter Boström74f6e9e2016-04-04 17:56:10 +02001843 RTC_DCHECK(observer_);
Peter Boström5811a392015-12-10 13:02:50 +01001844 EXPECT_TRUE(observer_->Wait());
sprang867fb522015-08-03 04:38:41 -07001845 }
1846
1847 void UpdateSendConfig(
1848 size_t stream_index,
1849 VideoSendStream::Config* send_config,
1850 VideoEncoderConfig* encoder_config,
1851 test::FrameGeneratorCapturer** frame_generator) override {
1852 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001853 send_config->rtp.extensions.push_back(RtpExtension(
1854 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sprang867fb522015-08-03 04:38:41 -07001855
perkja8ba1952017-02-27 06:52:10 -08001856 // Force some padding to be sent. Note that since we do send media
1857 // packets we can not guarantee that a padding only packet is sent.
1858 // Instead, padding will most likely be send as an RTX packet.
sprang867fb522015-08-03 04:38:41 -07001859 const int kPaddingBitrateBps = 50000;
perkja8ba1952017-02-27 06:52:10 -08001860 encoder_config->max_bitrate_bps = 200000;
sprang867fb522015-08-03 04:38:41 -07001861 encoder_config->min_transmit_bitrate_bps =
perkjfa10b552016-10-02 23:45:26 -07001862 encoder_config->max_bitrate_bps + kPaddingBitrateBps;
sprang867fb522015-08-03 04:38:41 -07001863
1864 // Configure RTX for redundant payload padding.
1865 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang861c55e2015-10-16 10:01:21 -07001866 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[stream_index]);
sprang867fb522015-08-03 04:38:41 -07001867 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
sprang861c55e2015-10-16 10:01:21 -07001868 rtx_to_media_ssrcs_[kSendRtxSsrcs[stream_index]] =
1869 send_config->rtp.ssrcs[0];
1870
1871 if (stream_index == 0)
1872 first_media_ssrc_ = send_config->rtp.ssrcs[0];
sprang867fb522015-08-03 04:38:41 -07001873 }
1874
1875 void UpdateReceiveConfig(
1876 size_t stream_index,
1877 VideoReceiveStream::Config* receive_config) override {
sprang861c55e2015-10-16 10:01:21 -07001878 receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang867fb522015-08-03 04:38:41 -07001879 receive_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001880 receive_config->rtp.extensions.push_back(RtpExtension(
1881 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sakal55d932b2016-09-30 06:19:08 -07001882 receive_config->renderer = &fake_renderer_;
sprang867fb522015-08-03 04:38:41 -07001883 }
1884
eladalon413ee9a2017-08-22 04:02:52 -07001885 test::DirectTransport* CreateSendTransport(
1886 test::SingleThreadedTaskQueueForTesting* task_queue,
1887 Call* sender_call) override {
minyue20c84cc2017-04-10 16:57:57 -07001888 std::map<uint8_t, MediaType> payload_type_map =
1889 MultiStreamTest::payload_type_map_;
1890 RTC_DCHECK(payload_type_map.find(kSendRtxPayloadType) ==
1891 payload_type_map.end());
1892 payload_type_map[kSendRtxPayloadType] = MediaType::VIDEO;
eladalon413ee9a2017-08-22 04:02:52 -07001893 observer_ = new RtpExtensionHeaderObserver(
1894 task_queue, sender_call, first_media_ssrc_, rtx_to_media_ssrcs_,
1895 payload_type_map);
sprang867fb522015-08-03 04:38:41 -07001896 return observer_;
1897 }
1898
1899 private:
sakal55d932b2016-09-30 06:19:08 -07001900 test::FakeVideoRenderer fake_renderer_;
sprang861c55e2015-10-16 10:01:21 -07001901 uint32_t first_media_ssrc_;
1902 std::map<uint32_t, uint32_t> rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001903 RtpExtensionHeaderObserver* observer_;
eladalon413ee9a2017-08-22 04:02:52 -07001904 } tester(&task_queue_);
sprang867fb522015-08-03 04:38:41 -07001905
1906 tester.RunTest();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001907}
1908
Stefan Holmer04cb7632016-01-14 20:34:30 +01001909class TransportFeedbackTester : public test::EndToEndTest {
1910 public:
stefan9e117c5e12017-08-16 08:16:25 -07001911 TransportFeedbackTester(bool feedback_enabled,
1912 size_t num_video_streams,
1913 size_t num_audio_streams)
Stefan Holmer04cb7632016-01-14 20:34:30 +01001914 : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
1915 feedback_enabled_(feedback_enabled),
1916 num_video_streams_(num_video_streams),
sprangcd349d92016-07-13 09:11:28 -07001917 num_audio_streams_(num_audio_streams),
1918 receiver_call_(nullptr) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001919 // Only one stream of each supported for now.
1920 EXPECT_LE(num_video_streams, 1u);
1921 EXPECT_LE(num_audio_streams, 1u);
1922 }
1923
1924 protected:
1925 Action OnSendRtcp(const uint8_t* data, size_t length) override {
1926 EXPECT_FALSE(HasTransportFeedback(data, length));
1927 return SEND_PACKET;
1928 }
1929
1930 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
1931 if (HasTransportFeedback(data, length))
1932 observation_complete_.Set();
1933 return SEND_PACKET;
1934 }
1935
1936 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
danilchap3dc929e2016-11-02 08:21:59 -07001937 test::RtcpPacketParser parser;
1938 EXPECT_TRUE(parser.Parse(data, length));
1939 return parser.transport_feedback()->num_packets() > 0;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001940 }
1941
1942 void PerformTest() override {
1943 const int64_t kDisabledFeedbackTimeoutMs = 5000;
1944 EXPECT_EQ(feedback_enabled_,
1945 observation_complete_.Wait(feedback_enabled_
1946 ? test::CallTest::kDefaultTimeoutMs
1947 : kDisabledFeedbackTimeoutMs));
1948 }
1949
1950 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1951 receiver_call_ = receiver_call;
1952 }
1953
1954 size_t GetNumVideoStreams() const override { return num_video_streams_; }
1955 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
1956
1957 void ModifyVideoConfigs(
1958 VideoSendStream::Config* send_config,
1959 std::vector<VideoReceiveStream::Config>* receive_configs,
1960 VideoEncoderConfig* encoder_config) override {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001961 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
1962 }
1963
1964 void ModifyAudioConfigs(
1965 AudioSendStream::Config* send_config,
1966 std::vector<AudioReceiveStream::Config>* receive_configs) override {
1967 send_config->rtp.extensions.clear();
1968 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001969 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001970 (*receive_configs)[0].rtp.extensions.clear();
1971 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1972 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001973 }
1974
1975 private:
Erik Språng6b8d3552015-09-24 15:06:57 +02001976 static const int kExtensionId = 5;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001977 const bool feedback_enabled_;
1978 const size_t num_video_streams_;
1979 const size_t num_audio_streams_;
1980 Call* receiver_call_;
1981};
Erik Språng6b8d3552015-09-24 15:06:57 +02001982
philipelccdfcca2017-10-23 12:42:17 +02001983TEST_P(EndToEndTest, VideoReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001984 TransportFeedbackTester test(true, 1, 0);
1985 RunBaseTest(&test);
Erik Språng6b8d3552015-09-24 15:06:57 +02001986}
stefan43edf0f2015-11-20 18:05:48 -08001987
philipelccdfcca2017-10-23 12:42:17 +02001988TEST_P(EndToEndTest, VideoTransportFeedbackNotConfigured) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001989 TransportFeedbackTester test(false, 1, 0);
1990 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001991}
1992
philipelccdfcca2017-10-23 12:42:17 +02001993TEST_P(EndToEndTest, AudioReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001994 TransportFeedbackTester test(true, 0, 1);
1995 RunBaseTest(&test);
1996}
1997
philipelccdfcca2017-10-23 12:42:17 +02001998TEST_P(EndToEndTest, AudioTransportFeedbackNotConfigured) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001999 TransportFeedbackTester test(false, 0, 1);
2000 RunBaseTest(&test);
2001}
2002
philipelccdfcca2017-10-23 12:42:17 +02002003TEST_P(EndToEndTest, AudioVideoReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01002004 TransportFeedbackTester test(true, 1, 1);
2005 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08002006}
2007
philipelccdfcca2017-10-23 12:42:17 +02002008TEST_P(EndToEndTest, StopsSendingMediaWithoutFeedback) {
stefan9e117c5e12017-08-16 08:16:25 -07002009 test::ScopedFieldTrials override_field_trials(
stefan74418272017-08-17 02:13:54 -07002010 "WebRTC-CwndExperiment/Enabled-250/");
stefan9e117c5e12017-08-16 08:16:25 -07002011
2012 class TransportFeedbackTester : public test::EndToEndTest {
2013 public:
2014 TransportFeedbackTester(size_t num_video_streams, size_t num_audio_streams)
2015 : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
2016 num_video_streams_(num_video_streams),
2017 num_audio_streams_(num_audio_streams),
2018 media_sent_(0),
2019 padding_sent_(0) {
2020 // Only one stream of each supported for now.
2021 EXPECT_LE(num_video_streams, 1u);
2022 EXPECT_LE(num_audio_streams, 1u);
2023 }
2024
2025 protected:
2026 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2027 RTPHeader header;
2028 EXPECT_TRUE(parser_->Parse(packet, length, &header));
2029 const bool only_padding =
2030 header.headerLength + header.paddingLength == length;
2031 rtc::CritScope lock(&crit_);
2032 if (only_padding) {
2033 ++padding_sent_;
2034 } else {
2035 ++media_sent_;
2036 EXPECT_LT(media_sent_, 40) << "Media sent without feedback.";
2037 }
2038
2039 return SEND_PACKET;
2040 }
2041
2042 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
2043 rtc::CritScope lock(&crit_);
2044 if (media_sent_ > 20 && HasTransportFeedback(data, length)) {
2045 return DROP_PACKET;
2046 }
2047 return SEND_PACKET;
2048 }
2049
2050 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
2051 test::RtcpPacketParser parser;
2052 EXPECT_TRUE(parser.Parse(data, length));
2053 return parser.transport_feedback()->num_packets() > 0;
2054 }
2055
2056 Call::Config GetSenderCallConfig() override {
2057 Call::Config config = EndToEndTest::GetSenderCallConfig();
2058 config.bitrate_config.max_bitrate_bps = 300000;
2059 return config;
2060 }
2061
2062 void PerformTest() override {
2063 const int64_t kDisabledFeedbackTimeoutMs = 10000;
2064 observation_complete_.Wait(kDisabledFeedbackTimeoutMs);
2065 rtc::CritScope lock(&crit_);
2066 EXPECT_GT(padding_sent_, 0);
2067 }
2068
2069 size_t GetNumVideoStreams() const override { return num_video_streams_; }
2070 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
2071
2072 private:
2073 const size_t num_video_streams_;
2074 const size_t num_audio_streams_;
2075 rtc::CriticalSection crit_;
danilchapa37de392017-09-09 04:17:22 -07002076 int media_sent_ RTC_GUARDED_BY(crit_);
2077 int padding_sent_ RTC_GUARDED_BY(crit_);
stefan9e117c5e12017-08-16 08:16:25 -07002078 } test(1, 0);
2079 RunBaseTest(&test);
2080}
2081
philipelccdfcca2017-10-23 12:42:17 +02002082TEST_P(EndToEndTest, ObserversEncodedFrames) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002083 class EncodedFrameTestObserver : public EncodedFrameObserver {
2084 public:
2085 EncodedFrameTestObserver()
Peter Boström5811a392015-12-10 13:02:50 +01002086 : length_(0), frame_type_(kEmptyFrame), called_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002087 virtual ~EncodedFrameTestObserver() {}
2088
2089 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
2090 frame_type_ = encoded_frame.frame_type_;
2091 length_ = encoded_frame.length_;
2092 buffer_.reset(new uint8_t[length_]);
2093 memcpy(buffer_.get(), encoded_frame.data_, length_);
Peter Boström5811a392015-12-10 13:02:50 +01002094 called_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002095 }
2096
Peter Boström5811a392015-12-10 13:02:50 +01002097 bool Wait() { return called_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002098
2099 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
2100 ASSERT_EQ(length_, observer.length_)
2101 << "Observed frames are of different lengths.";
2102 EXPECT_EQ(frame_type_, observer.frame_type_)
2103 << "Observed frames have different frame types.";
2104 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
2105 << "Observed encoded frames have different content.";
2106 }
2107
2108 private:
kwiberg27f982b2016-03-01 11:52:33 -08002109 std::unique_ptr<uint8_t[]> buffer_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002110 size_t length_;
2111 FrameType frame_type_;
Peter Boström5811a392015-12-10 13:02:50 +01002112 rtc::Event called_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002113 };
2114
2115 EncodedFrameTestObserver post_encode_observer;
2116 EncodedFrameTestObserver pre_decode_observer;
perkja49cbd32016-09-16 07:53:41 -07002117 test::FrameForwarder forwarder;
eladalon413ee9a2017-08-22 04:02:52 -07002118 std::unique_ptr<test::FrameGenerator> frame_generator;
2119
2120 std::unique_ptr<test::DirectTransport> sender_transport;
2121 std::unique_ptr<test::DirectTransport> receiver_transport;
2122
2123 task_queue_.SendTask([&]() {
2124 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
2125
2126 sender_transport = rtc::MakeUnique<test::DirectTransport>(
2127 &task_queue_, sender_call_.get(), payload_type_map_);
2128 receiver_transport = rtc::MakeUnique<test::DirectTransport>(
2129 &task_queue_, receiver_call_.get(), payload_type_map_);
2130 sender_transport->SetReceiver(receiver_call_->Receiver());
2131 receiver_transport->SetReceiver(sender_call_->Receiver());
2132
2133 CreateSendConfig(1, 0, 0, sender_transport.get());
2134 CreateMatchingReceiveConfigs(receiver_transport.get());
2135 video_send_config_.post_encode_callback = &post_encode_observer;
2136 video_receive_configs_[0].pre_decode_callback = &pre_decode_observer;
2137
2138 CreateVideoStreams();
2139 Start();
2140
2141 frame_generator = test::FrameGenerator::CreateSquareGenerator(
2142 kDefaultWidth, kDefaultHeight);
2143 video_send_stream_->SetSource(
2144 &forwarder, VideoSendStream::DegradationPreference::kMaintainFramerate);
2145 forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
2146 });
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002147
Peter Boström5811a392015-12-10 13:02:50 +01002148 EXPECT_TRUE(post_encode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002149 << "Timed out while waiting for send-side encoded-frame callback.";
2150
Peter Boström5811a392015-12-10 13:02:50 +01002151 EXPECT_TRUE(pre_decode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002152 << "Timed out while waiting for pre-decode encoded-frame callback.";
2153
2154 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
2155
eladalon413ee9a2017-08-22 04:02:52 -07002156 task_queue_.SendTask([this, &sender_transport, &receiver_transport]() {
2157 Stop();
2158 DestroyStreams();
2159 sender_transport.reset();
2160 receiver_transport.reset();
2161 DestroyCalls();
2162 });
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002163}
2164
philipelccdfcca2017-10-23 12:42:17 +02002165TEST_P(EndToEndTest, ReceiveStreamSendsRemb) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002166 class RembObserver : public test::EndToEndTest {
2167 public:
2168 RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
2169
stefanb77c7162017-02-06 06:29:38 -08002170 void ModifyVideoConfigs(
2171 VideoSendStream::Config* send_config,
2172 std::vector<VideoReceiveStream::Config>* receive_configs,
2173 VideoEncoderConfig* encoder_config) override {
2174 send_config->rtp.extensions.clear();
2175 send_config->rtp.extensions.push_back(RtpExtension(
2176 RtpExtension::kAbsSendTimeUri, test::kAbsSendTimeExtensionId));
2177 (*receive_configs)[0].rtp.remb = true;
2178 (*receive_configs)[0].rtp.transport_cc = false;
2179 }
2180
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002181 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
danilchap3dc929e2016-11-02 08:21:59 -07002182 test::RtcpPacketParser parser;
2183 EXPECT_TRUE(parser.Parse(packet, length));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002184
danilchap3dc929e2016-11-02 08:21:59 -07002185 if (parser.remb()->num_packets() > 0) {
2186 EXPECT_EQ(kReceiverLocalVideoSsrc, parser.remb()->sender_ssrc());
2187 EXPECT_LT(0U, parser.remb()->bitrate_bps());
2188 EXPECT_EQ(1U, parser.remb()->ssrcs().size());
2189 EXPECT_EQ(kVideoSendSsrcs[0], parser.remb()->ssrcs()[0]);
Peter Boström5811a392015-12-10 13:02:50 +01002190 observation_complete_.Set();
danilchap3dc929e2016-11-02 08:21:59 -07002191 }
2192
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002193 return SEND_PACKET;
2194 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002195 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002196 EXPECT_TRUE(Wait()) << "Timed out while waiting for a "
2197 "receiver RTCP REMB packet to be "
2198 "sent.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002199 }
2200 } test;
2201
stefane74eef12016-01-08 06:47:13 -08002202 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002203}
2204
stefanb77c7162017-02-06 06:29:38 -08002205class BandwidthStatsTest : public test::EndToEndTest {
2206 public:
2207 explicit BandwidthStatsTest(bool send_side_bwe)
2208 : EndToEndTest(test::CallTest::kDefaultTimeoutMs),
2209 sender_call_(nullptr),
2210 receiver_call_(nullptr),
2211 has_seen_pacer_delay_(false),
2212 send_side_bwe_(send_side_bwe) {}
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002213
stefanb77c7162017-02-06 06:29:38 -08002214 void ModifyVideoConfigs(
2215 VideoSendStream::Config* send_config,
2216 std::vector<VideoReceiveStream::Config>* receive_configs,
2217 VideoEncoderConfig* encoder_config) override {
2218 if (!send_side_bwe_) {
2219 send_config->rtp.extensions.clear();
2220 send_config->rtp.extensions.push_back(RtpExtension(
2221 RtpExtension::kAbsSendTimeUri, test::kAbsSendTimeExtensionId));
2222 (*receive_configs)[0].rtp.remb = true;
2223 (*receive_configs)[0].rtp.transport_cc = false;
2224 }
2225 }
2226
2227 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2228 Call::Stats sender_stats = sender_call_->GetStats();
2229 Call::Stats receiver_stats = receiver_call_->GetStats();
2230 if (!has_seen_pacer_delay_)
2231 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
2232 if (sender_stats.send_bandwidth_bps > 0 && has_seen_pacer_delay_) {
2233 if (send_side_bwe_ || receiver_stats.recv_bandwidth_bps > 0)
Peter Boström5811a392015-12-10 13:02:50 +01002234 observation_complete_.Set();
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002235 }
stefanb77c7162017-02-06 06:29:38 -08002236 return SEND_PACKET;
2237 }
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002238
stefanb77c7162017-02-06 06:29:38 -08002239 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2240 sender_call_ = sender_call;
2241 receiver_call_ = receiver_call;
2242 }
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002243
stefanb77c7162017-02-06 06:29:38 -08002244 void PerformTest() override {
2245 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2246 "non-zero bandwidth stats.";
2247 }
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002248
stefanb77c7162017-02-06 06:29:38 -08002249 private:
2250 Call* sender_call_;
2251 Call* receiver_call_;
2252 bool has_seen_pacer_delay_;
2253 const bool send_side_bwe_;
2254};
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002255
philipelccdfcca2017-10-23 12:42:17 +02002256TEST_P(EndToEndTest, VerifySendSideBweStats) {
stefanb77c7162017-02-06 06:29:38 -08002257 BandwidthStatsTest test(true);
stefane74eef12016-01-08 06:47:13 -08002258 RunBaseTest(&test);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002259}
2260
philipelccdfcca2017-10-23 12:42:17 +02002261TEST_P(EndToEndTest, VerifyRecvSideBweStats) {
stefanb77c7162017-02-06 06:29:38 -08002262 BandwidthStatsTest test(false);
2263 RunBaseTest(&test);
2264}
stefan32f81542016-01-20 07:13:58 -08002265
2266// Verifies that it's possible to limit the send BWE by sending a REMB.
2267// This is verified by allowing the send BWE to ramp-up to >1000 kbps,
2268// then have the test generate a REMB of 500 kbps and verify that the send BWE
2269// is reduced to exactly 500 kbps. Then a REMB of 1000 kbps is generated and the
2270// test verifies that the send BWE ramps back up to exactly 1000 kbps.
philipelccdfcca2017-10-23 12:42:17 +02002271TEST_P(EndToEndTest, RembWithSendSideBwe) {
stefan32f81542016-01-20 07:13:58 -08002272 class BweObserver : public test::EndToEndTest {
2273 public:
2274 BweObserver()
2275 : EndToEndTest(kDefaultTimeoutMs),
2276 sender_call_(nullptr),
2277 clock_(Clock::GetRealTimeClock()),
2278 sender_ssrc_(0),
2279 remb_bitrate_bps_(1000000),
2280 receive_transport_(nullptr),
Tommi5dd5f5a2017-02-21 14:22:59 +01002281 stop_event_(false, false),
stefan32f81542016-01-20 07:13:58 -08002282 poller_thread_(&BitrateStatsPollingThread,
2283 this,
2284 "BitrateStatsPollingThread"),
Erik Språng737336d2016-07-29 12:59:36 +02002285 state_(kWaitForFirstRampUp),
2286 retransmission_rate_limiter_(clock_, 1000) {}
stefan32f81542016-01-20 07:13:58 -08002287
2288 ~BweObserver() {}
2289
eladalon413ee9a2017-08-22 04:02:52 -07002290 test::PacketTransport* CreateReceiveTransport(
2291 test::SingleThreadedTaskQueueForTesting* task_queue) override {
stefan32f81542016-01-20 07:13:58 -08002292 receive_transport_ = new test::PacketTransport(
eladalon413ee9a2017-08-22 04:02:52 -07002293 task_queue, nullptr, this, test::PacketTransport::kReceiver,
2294 payload_type_map_, FakeNetworkPipe::Config());
stefan32f81542016-01-20 07:13:58 -08002295 return receive_transport_;
2296 }
2297
2298 Call::Config GetSenderCallConfig() override {
philipel4fb651d2017-04-10 03:54:05 -07002299 Call::Config config(event_log_.get());
stefan32f81542016-01-20 07:13:58 -08002300 // Set a high start bitrate to reduce the test completion time.
2301 config.bitrate_config.start_bitrate_bps = remb_bitrate_bps_;
2302 return config;
2303 }
2304
2305 void ModifyVideoConfigs(
2306 VideoSendStream::Config* send_config,
2307 std::vector<VideoReceiveStream::Config>* receive_configs,
2308 VideoEncoderConfig* encoder_config) override {
2309 ASSERT_EQ(1u, send_config->rtp.ssrcs.size());
stefan32f81542016-01-20 07:13:58 -08002310 sender_ssrc_ = send_config->rtp.ssrcs[0];
2311
perkjfa10b552016-10-02 23:45:26 -07002312 encoder_config->max_bitrate_bps = 2000000;
stefan32f81542016-01-20 07:13:58 -08002313
2314 ASSERT_EQ(1u, receive_configs->size());
stefan32f81542016-01-20 07:13:58 -08002315 RtpRtcp::Configuration config;
2316 config.receiver_only = true;
2317 config.clock = clock_;
2318 config.outgoing_transport = receive_transport_;
Erik Språng737336d2016-07-29 12:59:36 +02002319 config.retransmission_rate_limiter = &retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08002320 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
2321 rtp_rtcp_->SetRemoteSSRC((*receive_configs)[0].rtp.remote_ssrc);
2322 rtp_rtcp_->SetSSRC((*receive_configs)[0].rtp.local_ssrc);
stefan32f81542016-01-20 07:13:58 -08002323 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
2324 }
2325
2326 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2327 sender_call_ = sender_call;
2328 }
2329
tommi0f8b4032017-02-22 11:22:05 -08002330 static void BitrateStatsPollingThread(void* obj) {
2331 static_cast<BweObserver*>(obj)->PollStats();
stefan32f81542016-01-20 07:13:58 -08002332 }
2333
tommi0f8b4032017-02-22 11:22:05 -08002334 void PollStats() {
2335 do {
2336 if (sender_call_) {
2337 Call::Stats stats = sender_call_->GetStats();
2338 switch (state_) {
2339 case kWaitForFirstRampUp:
2340 if (stats.send_bandwidth_bps >= remb_bitrate_bps_) {
2341 state_ = kWaitForRemb;
2342 remb_bitrate_bps_ /= 2;
Danil Chapovalov51e21aa2017-10-10 17:46:26 +02002343 rtp_rtcp_->SetRemb(
tommi0f8b4032017-02-22 11:22:05 -08002344 remb_bitrate_bps_,
2345 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
2346 rtp_rtcp_->SendRTCP(kRtcpRr);
2347 }
2348 break;
stefan32f81542016-01-20 07:13:58 -08002349
tommi0f8b4032017-02-22 11:22:05 -08002350 case kWaitForRemb:
2351 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
2352 state_ = kWaitForSecondRampUp;
2353 remb_bitrate_bps_ *= 2;
Danil Chapovalov51e21aa2017-10-10 17:46:26 +02002354 rtp_rtcp_->SetRemb(
tommi0f8b4032017-02-22 11:22:05 -08002355 remb_bitrate_bps_,
2356 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
2357 rtp_rtcp_->SendRTCP(kRtcpRr);
2358 }
2359 break;
stefan32f81542016-01-20 07:13:58 -08002360
tommi0f8b4032017-02-22 11:22:05 -08002361 case kWaitForSecondRampUp:
2362 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
2363 observation_complete_.Set();
2364 }
2365 break;
2366 }
stefan32f81542016-01-20 07:13:58 -08002367 }
tommi0f8b4032017-02-22 11:22:05 -08002368 } while (!stop_event_.Wait(1000));
stefan32f81542016-01-20 07:13:58 -08002369 }
2370
2371 void PerformTest() override {
2372 poller_thread_.Start();
2373 EXPECT_TRUE(Wait())
2374 << "Timed out while waiting for bitrate to change according to REMB.";
Tommi5dd5f5a2017-02-21 14:22:59 +01002375 stop_event_.Set();
stefan32f81542016-01-20 07:13:58 -08002376 poller_thread_.Stop();
2377 }
2378
2379 private:
2380 enum TestState { kWaitForFirstRampUp, kWaitForRemb, kWaitForSecondRampUp };
2381
2382 Call* sender_call_;
2383 Clock* const clock_;
2384 uint32_t sender_ssrc_;
2385 int remb_bitrate_bps_;
kwiberg27f982b2016-03-01 11:52:33 -08002386 std::unique_ptr<RtpRtcp> rtp_rtcp_;
stefan32f81542016-01-20 07:13:58 -08002387 test::PacketTransport* receive_transport_;
Tommi5dd5f5a2017-02-21 14:22:59 +01002388 rtc::Event stop_event_;
stefan32f81542016-01-20 07:13:58 -08002389 rtc::PlatformThread poller_thread_;
2390 TestState state_;
Erik Språng737336d2016-07-29 12:59:36 +02002391 RateLimiter retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08002392 } test;
2393
2394 RunBaseTest(&test);
2395}
2396
philipelccdfcca2017-10-23 12:42:17 +02002397TEST_P(EndToEndTest, StopSendingKeyframeRequestsForInactiveStream) {
philipel3184f8e2017-05-18 08:08:53 -07002398 class KeyframeRequestObserver : public test::EndToEndTest {
2399 public:
eladalon413ee9a2017-08-22 04:02:52 -07002400 explicit KeyframeRequestObserver(
2401 test::SingleThreadedTaskQueueForTesting* task_queue)
2402 : clock_(Clock::GetRealTimeClock()), task_queue_(task_queue) {}
philipel3184f8e2017-05-18 08:08:53 -07002403
2404 void OnVideoStreamsCreated(
2405 VideoSendStream* send_stream,
2406 const std::vector<VideoReceiveStream*>& receive_streams) override {
2407 RTC_DCHECK_EQ(1, receive_streams.size());
2408 send_stream_ = send_stream;
2409 receive_stream_ = receive_streams[0];
2410 }
2411
2412 void PerformTest() override {
2413 bool frame_decoded = false;
2414 int64_t start_time = clock_->TimeInMilliseconds();
2415 while (clock_->TimeInMilliseconds() - start_time <= 5000) {
2416 if (receive_stream_->GetStats().frames_decoded > 0) {
2417 frame_decoded = true;
2418 break;
2419 }
2420 SleepMs(100);
2421 }
2422 ASSERT_TRUE(frame_decoded);
eladalon413ee9a2017-08-22 04:02:52 -07002423 task_queue_->SendTask([this]() { send_stream_->Stop(); });
philipel3184f8e2017-05-18 08:08:53 -07002424 SleepMs(10000);
2425 ASSERT_EQ(
2426 1U, receive_stream_->GetStats().rtcp_packet_type_counts.pli_packets);
2427 }
2428
2429 private:
2430 Clock* clock_;
2431 VideoSendStream* send_stream_;
2432 VideoReceiveStream* receive_stream_;
eladalon413ee9a2017-08-22 04:02:52 -07002433 test::SingleThreadedTaskQueueForTesting* const task_queue_;
2434 } test(&task_queue_);
philipel3184f8e2017-05-18 08:08:53 -07002435
2436 RunBaseTest(&test);
2437}
2438
philipele828c962017-03-21 03:24:27 -07002439class ProbingTest : public test::EndToEndTest {
2440 public:
2441 explicit ProbingTest(int start_bitrate_bps)
2442 : clock_(Clock::GetRealTimeClock()),
2443 start_bitrate_bps_(start_bitrate_bps),
2444 state_(0),
2445 sender_call_(nullptr) {}
2446
2447 ~ProbingTest() {}
2448
2449 Call::Config GetSenderCallConfig() override {
philipel4fb651d2017-04-10 03:54:05 -07002450 Call::Config config(event_log_.get());
philipele828c962017-03-21 03:24:27 -07002451 config.bitrate_config.start_bitrate_bps = start_bitrate_bps_;
2452 return config;
2453 }
2454
2455 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2456 sender_call_ = sender_call;
2457 }
2458
2459 protected:
2460 Clock* const clock_;
2461 const int start_bitrate_bps_;
2462 int state_;
2463 Call* sender_call_;
2464};
2465
philipelccdfcca2017-10-23 12:42:17 +02002466TEST_P(EndToEndTest, MAYBE_InitialProbing) {
philipele828c962017-03-21 03:24:27 -07002467 class InitialProbingTest : public ProbingTest {
2468 public:
philipel8a256522017-03-30 05:06:22 -07002469 explicit InitialProbingTest(bool* success)
eladaloncf038f72017-08-10 10:42:53 -07002470 : ProbingTest(300000), success_(success) {
2471 *success_ = false;
2472 }
philipele828c962017-03-21 03:24:27 -07002473
2474 void PerformTest() override {
2475 int64_t start_time_ms = clock_->TimeInMilliseconds();
2476 do {
philipel8a256522017-03-30 05:06:22 -07002477 if (clock_->TimeInMilliseconds() - start_time_ms > kTimeoutMs)
philipele828c962017-03-21 03:24:27 -07002478 break;
philipele828c962017-03-21 03:24:27 -07002479
2480 Call::Stats stats = sender_call_->GetStats();
2481 // Initial probing is done with a x3 and x6 multiplier of the start
2482 // bitrate, so a x4 multiplier is a high enough threshold.
philipel8a256522017-03-30 05:06:22 -07002483 if (stats.send_bandwidth_bps > 4 * 300000) {
2484 *success_ = true;
philipele828c962017-03-21 03:24:27 -07002485 break;
philipel8a256522017-03-30 05:06:22 -07002486 }
philipele828c962017-03-21 03:24:27 -07002487 } while (!observation_complete_.Wait(20));
2488 }
2489
2490 private:
2491 const int kTimeoutMs = 1000;
philipel8a256522017-03-30 05:06:22 -07002492 bool* const success_;
2493 };
philipele828c962017-03-21 03:24:27 -07002494
eladaloncf038f72017-08-10 10:42:53 -07002495 bool success = false;
philipel8a256522017-03-30 05:06:22 -07002496 const int kMaxAttempts = 3;
2497 for (int i = 0; i < kMaxAttempts; ++i) {
2498 InitialProbingTest test(&success);
2499 RunBaseTest(&test);
2500 if (success)
2501 return;
2502 }
eladaloncf038f72017-08-10 10:42:53 -07002503 EXPECT_TRUE(success) << "Failed to perform mid initial probing ("
2504 << kMaxAttempts << " attempts).";
philipele828c962017-03-21 03:24:27 -07002505}
2506
aleloi18703f92017-03-30 04:24:08 -07002507// Fails on Linux MSan: bugs.webrtc.org/7428
2508#if defined(MEMORY_SANITIZER)
philipelccdfcca2017-10-23 12:42:17 +02002509TEST_P(EndToEndTest, DISABLED_TriggerMidCallProbing) {
oprypin45197522017-06-22 01:47:20 -07002510// Fails on iOS bots: bugs.webrtc.org/7851
2511#elif defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR
philipelccdfcca2017-10-23 12:42:17 +02002512TEST_P(EndToEndTest, DISABLED_TriggerMidCallProbing) {
aleloi18703f92017-03-30 04:24:08 -07002513#else
philipelccdfcca2017-10-23 12:42:17 +02002514TEST_P(EndToEndTest, TriggerMidCallProbing) {
aleloi18703f92017-03-30 04:24:08 -07002515#endif
2516
philipele828c962017-03-21 03:24:27 -07002517 class TriggerMidCallProbingTest : public ProbingTest {
2518 public:
eladalon413ee9a2017-08-22 04:02:52 -07002519 TriggerMidCallProbingTest(
2520 test::SingleThreadedTaskQueueForTesting* task_queue,
2521 bool* success)
2522 : ProbingTest(300000), success_(success), task_queue_(task_queue) {}
philipele828c962017-03-21 03:24:27 -07002523
2524 void PerformTest() override {
philipel8a256522017-03-30 05:06:22 -07002525 *success_ = false;
philipele828c962017-03-21 03:24:27 -07002526 int64_t start_time_ms = clock_->TimeInMilliseconds();
2527 do {
philipel8a256522017-03-30 05:06:22 -07002528 if (clock_->TimeInMilliseconds() - start_time_ms > kTimeoutMs)
philipele828c962017-03-21 03:24:27 -07002529 break;
philipele828c962017-03-21 03:24:27 -07002530
2531 Call::Stats stats = sender_call_->GetStats();
2532
2533 switch (state_) {
2534 case 0:
2535 if (stats.send_bandwidth_bps > 5 * 300000) {
2536 Call::Config::BitrateConfig bitrate_config;
2537 bitrate_config.max_bitrate_bps = 100000;
eladalon413ee9a2017-08-22 04:02:52 -07002538 task_queue_->SendTask([this, &bitrate_config]() {
2539 sender_call_->SetBitrateConfig(bitrate_config);
2540 });
philipele828c962017-03-21 03:24:27 -07002541 ++state_;
2542 }
2543 break;
2544 case 1:
2545 if (stats.send_bandwidth_bps < 110000) {
2546 Call::Config::BitrateConfig bitrate_config;
2547 bitrate_config.max_bitrate_bps = 2500000;
eladalon413ee9a2017-08-22 04:02:52 -07002548 task_queue_->SendTask([this, &bitrate_config]() {
2549 sender_call_->SetBitrateConfig(bitrate_config);
2550 });
philipele828c962017-03-21 03:24:27 -07002551 ++state_;
2552 }
2553 break;
2554 case 2:
2555 // During high cpu load the pacer will not be able to pace packets
2556 // at the correct speed, but if we go from 110 to 1250 kbps
2557 // in 5 seconds then it is due to probing.
philipel8a256522017-03-30 05:06:22 -07002558 if (stats.send_bandwidth_bps > 1250000) {
2559 *success_ = true;
philipele828c962017-03-21 03:24:27 -07002560 observation_complete_.Set();
philipel8a256522017-03-30 05:06:22 -07002561 }
philipele828c962017-03-21 03:24:27 -07002562 break;
2563 }
2564 } while (!observation_complete_.Wait(20));
2565 }
2566
2567 private:
2568 const int kTimeoutMs = 5000;
philipel8a256522017-03-30 05:06:22 -07002569 bool* const success_;
eladalon413ee9a2017-08-22 04:02:52 -07002570 test::SingleThreadedTaskQueueForTesting* const task_queue_;
philipel8a256522017-03-30 05:06:22 -07002571 };
philipele828c962017-03-21 03:24:27 -07002572
eladaloncf038f72017-08-10 10:42:53 -07002573 bool success = false;
philipel8a256522017-03-30 05:06:22 -07002574 const int kMaxAttempts = 3;
2575 for (int i = 0; i < kMaxAttempts; ++i) {
eladalon413ee9a2017-08-22 04:02:52 -07002576 TriggerMidCallProbingTest test(&task_queue_, &success);
philipel8a256522017-03-30 05:06:22 -07002577 RunBaseTest(&test);
2578 if (success)
2579 return;
2580 }
stefan9e117c5e12017-08-16 08:16:25 -07002581 EXPECT_TRUE(success) << "Failed to perform mid call probing (" << kMaxAttempts
2582 << " attempts).";
philipele828c962017-03-21 03:24:27 -07002583}
2584
philipelccdfcca2017-10-23 12:42:17 +02002585TEST_P(EndToEndTest, VerifyNackStats) {
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002586 static const int kPacketNumberToDrop = 200;
2587 class NackObserver : public test::EndToEndTest {
2588 public:
2589 NackObserver()
2590 : EndToEndTest(kLongTimeoutMs),
2591 sent_rtp_packets_(0),
2592 dropped_rtp_packet_(0),
2593 dropped_rtp_packet_requested_(false),
2594 send_stream_(nullptr),
2595 start_runtime_ms_(-1) {}
2596
2597 private:
2598 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002599 rtc::CritScope lock(&crit_);
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002600 if (++sent_rtp_packets_ == kPacketNumberToDrop) {
kwiberg27f982b2016-03-01 11:52:33 -08002601 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002602 RTPHeader header;
2603 EXPECT_TRUE(parser->Parse(packet, length, &header));
2604 dropped_rtp_packet_ = header.sequenceNumber;
2605 return DROP_PACKET;
2606 }
2607 VerifyStats();
2608 return SEND_PACKET;
2609 }
2610
2611 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002612 rtc::CritScope lock(&crit_);
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002613 test::RtcpPacketParser rtcp_parser;
2614 rtcp_parser.Parse(packet, length);
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02002615 const std::vector<uint16_t>& nacks = rtcp_parser.nack()->packet_ids();
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002616 if (!nacks.empty() && std::find(
2617 nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) {
2618 dropped_rtp_packet_requested_ = true;
2619 }
2620 return SEND_PACKET;
2621 }
2622
danilchapa37de392017-09-09 04:17:22 -07002623 void VerifyStats() RTC_EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002624 if (!dropped_rtp_packet_requested_)
2625 return;
2626 int send_stream_nack_packets = 0;
2627 int receive_stream_nack_packets = 0;
2628 VideoSendStream::Stats stats = send_stream_->GetStats();
2629 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
2630 stats.substreams.begin(); it != stats.substreams.end(); ++it) {
2631 const VideoSendStream::StreamStats& stream_stats = it->second;
2632 send_stream_nack_packets +=
2633 stream_stats.rtcp_packet_type_counts.nack_packets;
2634 }
2635 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2636 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2637 receive_stream_nack_packets +=
2638 stats.rtcp_packet_type_counts.nack_packets;
2639 }
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002640 if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) {
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002641 // NACK packet sent on receive stream and received on sent stream.
2642 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002643 observation_complete_.Set();
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002644 }
2645 }
2646
2647 bool MinMetricRunTimePassed() {
2648 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2649 if (start_runtime_ms_ == -1) {
2650 start_runtime_ms_ = now;
2651 return false;
2652 }
2653 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2654 return elapsed_sec > metrics::kMinRunTimeInSeconds;
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 {
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002661 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2662 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sakal55d932b2016-09-30 06:19:08 -07002663 (*receive_configs)[0].renderer = &fake_renderer_;
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002664 }
2665
stefanff483612015-12-21 03:14:00 -08002666 void OnVideoStreamsCreated(
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002667 VideoSendStream* send_stream,
2668 const std::vector<VideoReceiveStream*>& receive_streams) override {
2669 send_stream_ = send_stream;
2670 receive_streams_ = receive_streams;
2671 }
2672
2673 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002674 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002675 }
2676
sakal55d932b2016-09-30 06:19:08 -07002677 test::FakeVideoRenderer fake_renderer_;
stefan608213e2015-11-01 14:56:10 -08002678 rtc::CriticalSection crit_;
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002679 uint64_t sent_rtp_packets_;
danilchapa37de392017-09-09 04:17:22 -07002680 uint16_t dropped_rtp_packet_ RTC_GUARDED_BY(&crit_);
2681 bool dropped_rtp_packet_requested_ RTC_GUARDED_BY(&crit_);
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002682 std::vector<VideoReceiveStream*> receive_streams_;
2683 VideoSendStream* send_stream_;
2684 int64_t start_runtime_ms_;
2685 } test;
2686
asapersson01d70a32016-05-20 06:29:46 -07002687 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002688 RunBaseTest(&test);
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002689
asapersson01d70a32016-05-20 06:29:46 -07002690 EXPECT_EQ(
2691 1, metrics::NumSamples("WebRTC.Video.UniqueNackRequestsSentInPercent"));
2692 EXPECT_EQ(1, metrics::NumSamples(
2693 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
2694 EXPECT_GT(metrics::MinSample("WebRTC.Video.NackPacketsSentPerMinute"), 0);
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002695}
2696
sprangb4a1ae52015-12-03 08:10:08 -08002697void EndToEndTest::VerifyHistogramStats(bool use_rtx,
nisse3b3622f2017-09-26 02:49:21 -07002698 bool use_fec,
sprangb4a1ae52015-12-03 08:10:08 -08002699 bool screenshare) {
tommi2e82f382016-06-21 00:26:43 -07002700 class StatsObserver : public test::EndToEndTest,
2701 public rtc::VideoSinkInterface<VideoFrame> {
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002702 public:
nisse3b3622f2017-09-26 02:49:21 -07002703 StatsObserver(bool use_rtx, bool use_fec, bool screenshare)
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002704 : EndToEndTest(kLongTimeoutMs),
2705 use_rtx_(use_rtx),
nisse3b3622f2017-09-26 02:49:21 -07002706 use_fec_(use_fec),
sprangb4a1ae52015-12-03 08:10:08 -08002707 screenshare_(screenshare),
Peter Boström39593972016-02-15 11:27:15 +01002708 // This test uses NACK, so to send FEC we can't use a fake encoder.
nisse3b3622f2017-09-26 02:49:21 -07002709 vp8_encoder_(use_fec ? VP8Encoder::Create() : nullptr),
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002710 sender_call_(nullptr),
2711 receiver_call_(nullptr),
asapersson1394c7b2016-10-18 11:50:50 -07002712 start_runtime_ms_(-1),
2713 num_frames_received_(0) {}
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002714
2715 private:
asapersson1394c7b2016-10-18 11:50:50 -07002716 void OnFrame(const VideoFrame& video_frame) override {
2717 // The RTT is needed to estimate |ntp_time_ms| which is used by
2718 // end-to-end delay stats. Therefore, start counting received frames once
2719 // |ntp_time_ms| is valid.
2720 if (video_frame.ntp_time_ms() > 0 &&
2721 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() >=
2722 video_frame.ntp_time_ms()) {
2723 rtc::CritScope lock(&crit_);
2724 ++num_frames_received_;
2725 }
2726 }
tommi2e82f382016-06-21 00:26:43 -07002727
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002728 Action OnSendRtp(const uint8_t* packet, size_t length) override {
asapersson1394c7b2016-10-18 11:50:50 -07002729 if (MinMetricRunTimePassed() && MinNumberOfFramesReceived())
Peter Boström5811a392015-12-10 13:02:50 +01002730 observation_complete_.Set();
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002731
stefanf116bd02015-10-27 08:29:42 -07002732 return SEND_PACKET;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002733 }
2734
2735 bool MinMetricRunTimePassed() {
2736 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2737 if (start_runtime_ms_ == -1) {
2738 start_runtime_ms_ = now;
2739 return false;
2740 }
2741 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2742 return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
2743 }
2744
asapersson1394c7b2016-10-18 11:50:50 -07002745 bool MinNumberOfFramesReceived() const {
2746 const int kMinRequiredHistogramSamples = 200;
2747 rtc::CritScope lock(&crit_);
2748 return num_frames_received_ > kMinRequiredHistogramSamples;
2749 }
2750
stefanff483612015-12-21 03:14:00 -08002751 void ModifyVideoConfigs(
2752 VideoSendStream::Config* send_config,
2753 std::vector<VideoReceiveStream::Config>* receive_configs,
2754 VideoEncoderConfig* encoder_config) override {
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002755 // NACK
2756 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2757 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
tommi2e82f382016-06-21 00:26:43 -07002758 (*receive_configs)[0].renderer = this;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002759 // FEC
nisse3b3622f2017-09-26 02:49:21 -07002760 if (use_fec_) {
brandtrb5f2c3f2016-10-04 23:28:39 -07002761 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
2762 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
Peter Boström39593972016-02-15 11:27:15 +01002763 send_config->encoder_settings.encoder = vp8_encoder_.get();
2764 send_config->encoder_settings.payload_name = "VP8";
2765 (*receive_configs)[0].decoders[0].payload_name = "VP8";
nisse3b3622f2017-09-26 02:49:21 -07002766 (*receive_configs)[0].rtp.red_payload_type = kRedPayloadType;
2767 (*receive_configs)[0].rtp.ulpfec_payload_type = kUlpfecPayloadType;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002768 }
2769 // RTX
2770 if (use_rtx_) {
2771 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
2772 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
brandtr14742122017-01-27 04:53:07 -08002773 (*receive_configs)[0].rtp.rtx_ssrc = kSendRtxSsrcs[0];
nisse26e3abb2017-08-25 04:44:25 -07002774 (*receive_configs)[0]
2775 .rtp.rtx_associated_payload_types[kSendRtxPayloadType] =
2776 kFakeVideoSendPayloadType;
nisse3b3622f2017-09-26 02:49:21 -07002777 if (use_fec_) {
2778 send_config->rtp.ulpfec.red_rtx_payload_type = kRtxRedPayloadType;
2779 (*receive_configs)[0]
2780 .rtp.rtx_associated_payload_types[kRtxRedPayloadType] =
2781 kSendRtxPayloadType;
2782 }
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002783 }
asapersson1490f7a2016-09-23 02:09:46 -07002784 // RTT needed for RemoteNtpTimeEstimator for the receive stream.
2785 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = true;
sprangb4a1ae52015-12-03 08:10:08 -08002786 encoder_config->content_type =
2787 screenshare_ ? VideoEncoderConfig::ContentType::kScreen
2788 : VideoEncoderConfig::ContentType::kRealtimeVideo;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002789 }
2790
2791 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2792 sender_call_ = sender_call;
2793 receiver_call_ = receiver_call;
2794 }
2795
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002796 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002797 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002798 }
2799
asapersson1394c7b2016-10-18 11:50:50 -07002800 rtc::CriticalSection crit_;
sprangb4a1ae52015-12-03 08:10:08 -08002801 const bool use_rtx_;
nisse3b3622f2017-09-26 02:49:21 -07002802 const bool use_fec_;
sprangb4a1ae52015-12-03 08:10:08 -08002803 const bool screenshare_;
kwiberg27f982b2016-03-01 11:52:33 -08002804 const std::unique_ptr<VideoEncoder> vp8_encoder_;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002805 Call* sender_call_;
2806 Call* receiver_call_;
2807 int64_t start_runtime_ms_;
danilchapa37de392017-09-09 04:17:22 -07002808 int num_frames_received_ RTC_GUARDED_BY(&crit_);
nisse3b3622f2017-09-26 02:49:21 -07002809 } test(use_rtx, use_fec, screenshare);
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002810
asapersson01d70a32016-05-20 06:29:46 -07002811 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002812 RunBaseTest(&test);
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002813
sprangb4a1ae52015-12-03 08:10:08 -08002814 std::string video_prefix =
2815 screenshare ? "WebRTC.Video.Screenshare." : "WebRTC.Video.";
ilnik6d5b4d62017-08-30 03:32:14 -07002816 // The content type extension is disabled in non screenshare test,
2817 // therefore no slicing on simulcast id should be present.
2818 std::string video_suffix = screenshare ? ".S0" : "";
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002819 // Verify that stats have been updated once.
asapersson4374a092016-07-27 00:39:09 -07002820 EXPECT_EQ(2, metrics::NumSamples("WebRTC.Call.LifetimeInSeconds"));
saza0d7f04d2017-07-04 04:05:06 -07002821 EXPECT_EQ(1, metrics::NumSamples(
2822 "WebRTC.Call.TimeReceivingVideoRtpPacketsInSeconds"));
asapersson01d70a32016-05-20 06:29:46 -07002823 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
2824 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.RtcpBitrateReceivedInBps"));
2825 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.BitrateReceivedInKbps"));
2826 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.EstimatedSendBitrateInKbps"));
2827 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.PacerBitrateInKbps"));
2828
asapersson4374a092016-07-27 00:39:09 -07002829 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
2830 EXPECT_EQ(1,
2831 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
2832
asapersson01d70a32016-05-20 06:29:46 -07002833 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
stefan91d92602015-11-11 10:13:02 -08002834 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002835 metrics::NumSamples(video_prefix + "NackPacketsReceivedPerMinute"));
2836 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
asaperssond89920b2015-07-22 06:52:00 -07002837 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002838 metrics::NumSamples(video_prefix + "FirPacketsReceivedPerMinute"));
2839 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
sprangb4a1ae52015-12-03 08:10:08 -08002840 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002841 metrics::NumSamples(video_prefix + "PliPacketsReceivedPerMinute"));
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002842
asapersson01d70a32016-05-20 06:29:46 -07002843 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "KeyFramesSentInPermille"));
2844 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
2845
2846 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentPacketsLostInPercent"));
2847 EXPECT_EQ(1,
2848 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
2849
2850 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputWidthInPixels"));
2851 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputHeightInPixels"));
2852 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentWidthInPixels"));
2853 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentHeightInPixels"));
ilnik6d5b4d62017-08-30 03:32:14 -07002854 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "ReceivedWidthInPixels"));
2855 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "ReceivedHeightInPixels"));
asapersson01d70a32016-05-20 06:29:46 -07002856
perkjfa10b552016-10-02 23:45:26 -07002857 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputWidthInPixels",
2858 kDefaultWidth));
2859 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputHeightInPixels",
2860 kDefaultHeight));
2861 EXPECT_EQ(
2862 1, metrics::NumEvents(video_prefix + "SentWidthInPixels", kDefaultWidth));
2863 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "SentHeightInPixels",
2864 kDefaultHeight));
ilnik6d5b4d62017-08-30 03:32:14 -07002865 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "ReceivedWidthInPixels",
perkjfa10b552016-10-02 23:45:26 -07002866 kDefaultWidth));
ilnik6d5b4d62017-08-30 03:32:14 -07002867 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "ReceivedHeightInPixels",
perkjfa10b552016-10-02 23:45:26 -07002868 kDefaultHeight));
asapersson01d70a32016-05-20 06:29:46 -07002869
2870 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputFramesPerSecond"));
2871 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentFramesPerSecond"));
2872 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
2873 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
2874
2875 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
2876 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
2877 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
2878 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
2879
ilnik6d5b4d62017-08-30 03:32:14 -07002880 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EndToEndDelayInMs" +
2881 video_suffix));
2882 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EndToEndDelayMaxInMs" +
2883 video_suffix));
2884 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InterframeDelayInMs" +
2885 video_suffix));
2886 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InterframeDelayMaxInMs" +
2887 video_suffix));
ilnik4257ab22017-07-03 01:15:58 -07002888
asapersson01d70a32016-05-20 06:29:46 -07002889 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
2890
2891 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EncodeTimeInMs"));
2892 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
2893
asapersson66d4b372016-12-19 06:50:53 -08002894 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "NumberOfPauseEvents"));
2895 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PausedTimeInPercent"));
2896
asapersson01d70a32016-05-20 06:29:46 -07002897 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "BitrateSentInKbps"));
2898 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateReceivedInKbps"));
2899 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "MediaBitrateSentInKbps"));
2900 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateReceivedInKbps"));
2901 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PaddingBitrateSentInKbps"));
2902 EXPECT_EQ(1,
2903 metrics::NumSamples("WebRTC.Video.PaddingBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002904 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002905 1, metrics::NumSamples(video_prefix + "RetransmittedBitrateSentInKbps"));
2906 EXPECT_EQ(1, metrics::NumSamples(
2907 "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002908
asapersson01d70a32016-05-20 06:29:46 -07002909 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendDelayInMs"));
2910 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayInMs"));
2911 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayMaxInMs"));
asapersson6f14be82015-11-16 00:40:49 -08002912
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002913 int num_rtx_samples = use_rtx ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002914 EXPECT_EQ(num_rtx_samples,
2915 metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2916 EXPECT_EQ(num_rtx_samples,
2917 metrics::NumSamples("WebRTC.Video.RtxBitrateReceivedInKbps"));
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002918
nisse3b3622f2017-09-26 02:49:21 -07002919 int num_red_samples = use_fec ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002920 EXPECT_EQ(num_red_samples,
2921 metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2922 EXPECT_EQ(num_red_samples,
2923 metrics::NumSamples("WebRTC.Video.FecBitrateReceivedInKbps"));
2924 EXPECT_EQ(num_red_samples,
2925 metrics::NumSamples("WebRTC.Video.ReceivedFecPacketsInPercent"));
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002926}
2927
Lu Liufb9e7512017-04-13 14:09:56 -07002928#if defined(WEBRTC_WIN)
2929// Disabled due to flakiness on Windows (bugs.webrtc.org/7483).
2930#define MAYBE_ContentTypeSwitches DISABLED_ContentTypeSwitches
2931#else
2932#define MAYBE_ContentTypeSwitches ContentTypeSwitches
2933#endif
philipelccdfcca2017-10-23 12:42:17 +02002934TEST_P(EndToEndTest, MAYBE_ContentTypeSwitches) {
ilnik00d802b2017-04-11 10:34:31 -07002935 class StatsObserver : public test::BaseTest,
2936 public rtc::VideoSinkInterface<VideoFrame> {
2937 public:
2938 StatsObserver() : BaseTest(kLongTimeoutMs), num_frames_received_(0) {}
2939
2940 bool ShouldCreateReceivers() const override { return true; }
2941
2942 void OnFrame(const VideoFrame& video_frame) override {
2943 // The RTT is needed to estimate |ntp_time_ms| which is used by
2944 // end-to-end delay stats. Therefore, start counting received frames once
2945 // |ntp_time_ms| is valid.
2946 if (video_frame.ntp_time_ms() > 0 &&
2947 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() >=
2948 video_frame.ntp_time_ms()) {
2949 rtc::CritScope lock(&crit_);
2950 ++num_frames_received_;
2951 }
2952 }
2953
2954 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2955 if (MinNumberOfFramesReceived())
2956 observation_complete_.Set();
2957 return SEND_PACKET;
2958 }
2959
2960 bool MinNumberOfFramesReceived() const {
ilnikf6f808f2017-04-18 09:17:53 -07002961 // Have some room for frames with wrong content type during switch.
2962 const int kMinRequiredHistogramSamples = 200+50;
ilnik00d802b2017-04-11 10:34:31 -07002963 rtc::CritScope lock(&crit_);
2964 return num_frames_received_ > kMinRequiredHistogramSamples;
2965 }
2966
2967 // May be called several times.
2968 void PerformTest() override {
2969 EXPECT_TRUE(Wait()) << "Timed out waiting for enough packets.";
2970 // Reset frame counter so next PerformTest() call will do something.
2971 {
2972 rtc::CritScope lock(&crit_);
2973 num_frames_received_ = 0;
2974 }
2975 }
2976
2977 rtc::CriticalSection crit_;
danilchapa37de392017-09-09 04:17:22 -07002978 int num_frames_received_ RTC_GUARDED_BY(&crit_);
ilnik00d802b2017-04-11 10:34:31 -07002979 } test;
2980
2981 metrics::Reset();
2982
2983 Call::Config send_config(test.GetSenderCallConfig());
ilnik00d802b2017-04-11 10:34:31 -07002984 Call::Config recv_config(test.GetReceiverCallConfig());
eladalon413ee9a2017-08-22 04:02:52 -07002985 VideoEncoderConfig encoder_config_with_screenshare;
ilnik00d802b2017-04-11 10:34:31 -07002986
ilnik41cadbc2017-08-23 00:44:27 -07002987 task_queue_.SendTask([this, &test, &send_config,
eladalon413ee9a2017-08-22 04:02:52 -07002988 &recv_config, &encoder_config_with_screenshare]() {
2989 CreateSenderCall(send_config);
2990 CreateReceiverCall(recv_config);
ilnik00d802b2017-04-11 10:34:31 -07002991
eladalon413ee9a2017-08-22 04:02:52 -07002992 receive_transport_.reset(test.CreateReceiveTransport(&task_queue_));
2993 send_transport_.reset(
2994 test.CreateSendTransport(&task_queue_, sender_call_.get()));
2995 send_transport_->SetReceiver(receiver_call_->Receiver());
2996 receive_transport_->SetReceiver(sender_call_->Receiver());
2997
2998 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
2999 CreateSendConfig(1, 0, 0, send_transport_.get());
3000 CreateMatchingReceiveConfigs(receive_transport_.get());
3001
3002 // Modify send and receive configs.
3003 video_send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
3004 video_receive_configs_[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
3005 video_receive_configs_[0].renderer = &test;
3006 // RTT needed for RemoteNtpTimeEstimator for the receive stream.
3007 video_receive_configs_[0].rtp.rtcp_xr.receiver_reference_time_report = true;
3008 // Start with realtime video.
3009 video_encoder_config_.content_type =
3010 VideoEncoderConfig::ContentType::kRealtimeVideo;
3011 // Second encoder config for the second part of the test uses screenshare
3012 encoder_config_with_screenshare = video_encoder_config_.Copy();
3013 encoder_config_with_screenshare.content_type =
3014 VideoEncoderConfig::ContentType::kScreen;
3015
3016 CreateVideoStreams();
3017 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
3018 kDefaultHeight);
3019 Start();
3020 });
ilnik00d802b2017-04-11 10:34:31 -07003021
3022 test.PerformTest();
3023
3024 // Replace old send stream.
eladalon413ee9a2017-08-22 04:02:52 -07003025 task_queue_.SendTask([this, &encoder_config_with_screenshare]() {
3026 sender_call_->DestroyVideoSendStream(video_send_stream_);
3027 video_send_stream_ = sender_call_->CreateVideoSendStream(
3028 video_send_config_.Copy(), encoder_config_with_screenshare.Copy());
3029 video_send_stream_->SetSource(
3030 frame_generator_capturer_.get(),
3031 VideoSendStream::DegradationPreference::kBalanced);
3032 video_send_stream_->Start();
3033 });
ilnik00d802b2017-04-11 10:34:31 -07003034
3035 // Continue to run test but now with screenshare.
3036 test.PerformTest();
3037
eladalon413ee9a2017-08-22 04:02:52 -07003038 task_queue_.SendTask([this]() {
3039 Stop();
3040 DestroyStreams();
3041 send_transport_.reset();
3042 receive_transport_.reset();
3043 DestroyCalls();
3044 });
ilnik00d802b2017-04-11 10:34:31 -07003045
3046 // Verify that stats have been updated for both screenshare and video.
3047 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.EndToEndDelayInMs"));
3048 EXPECT_EQ(1,
3049 metrics::NumSamples("WebRTC.Video.Screenshare.EndToEndDelayInMs"));
3050 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.EndToEndDelayMaxInMs"));
3051 EXPECT_EQ(
3052 1, metrics::NumSamples("WebRTC.Video.Screenshare.EndToEndDelayMaxInMs"));
ilnik4257ab22017-07-03 01:15:58 -07003053 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
3054 EXPECT_EQ(1,
3055 metrics::NumSamples(
3056 "WebRTC.Video.Screenshare.InterframeDelayInMs"));
3057 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
3058 EXPECT_EQ(1,
3059 metrics::NumSamples(
3060 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
ilnik00d802b2017-04-11 10:34:31 -07003061}
3062
philipelccdfcca2017-10-23 12:42:17 +02003063TEST_P(EndToEndTest, VerifyHistogramStatsWithRtx) {
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02003064 const bool kEnabledRtx = true;
3065 const bool kEnabledRed = false;
sprangb4a1ae52015-12-03 08:10:08 -08003066 const bool kScreenshare = false;
3067 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02003068}
3069
philipelccdfcca2017-10-23 12:42:17 +02003070TEST_P(EndToEndTest, VerifyHistogramStatsWithRed) {
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02003071 const bool kEnabledRtx = false;
3072 const bool kEnabledRed = true;
sprangb4a1ae52015-12-03 08:10:08 -08003073 const bool kScreenshare = false;
3074 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
3075}
3076
philipelccdfcca2017-10-23 12:42:17 +02003077TEST_P(EndToEndTest, VerifyHistogramStatsWithScreenshare) {
sprangb4a1ae52015-12-03 08:10:08 -08003078 const bool kEnabledRtx = false;
3079 const bool kEnabledRed = false;
3080 const bool kScreenshare = true;
3081 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02003082}
3083
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003084void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
3085 bool send_single_ssrc_first) {
3086 class SendsSetSsrcs : public test::EndToEndTest {
3087 public:
3088 SendsSetSsrcs(const uint32_t* ssrcs,
3089 size_t num_ssrcs,
3090 bool send_single_ssrc_first)
3091 : EndToEndTest(kDefaultTimeoutMs),
3092 num_ssrcs_(num_ssrcs),
3093 send_single_ssrc_first_(send_single_ssrc_first),
3094 ssrcs_to_observe_(num_ssrcs),
sprang867fb522015-08-03 04:38:41 -07003095 expect_single_ssrc_(send_single_ssrc_first),
3096 send_stream_(nullptr) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003097 for (size_t i = 0; i < num_ssrcs; ++i)
3098 valid_ssrcs_[ssrcs[i]] = true;
3099 }
3100
3101 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003102 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003103 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003104 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003105
3106 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
3107 << "Received unknown SSRC: " << header.ssrc;
3108
3109 if (!valid_ssrcs_[header.ssrc])
Peter Boström5811a392015-12-10 13:02:50 +01003110 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003111
3112 if (!is_observed_[header.ssrc]) {
3113 is_observed_[header.ssrc] = true;
3114 --ssrcs_to_observe_;
3115 if (expect_single_ssrc_) {
3116 expect_single_ssrc_ = false;
Peter Boström5811a392015-12-10 13:02:50 +01003117 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003118 }
3119 }
3120
3121 if (ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01003122 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003123
3124 return SEND_PACKET;
3125 }
3126
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003127 size_t GetNumVideoStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003128
perkjfa10b552016-10-02 23:45:26 -07003129 // This test use other VideoStream settings than the the default settings
3130 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3131 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3132 // in ModifyVideoConfigs.
3133 class VideoStreamFactory
3134 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3135 public:
3136 VideoStreamFactory() {}
3137
3138 private:
3139 std::vector<VideoStream> CreateEncoderStreams(
3140 int width,
3141 int height,
3142 const VideoEncoderConfig& encoder_config) override {
3143 std::vector<VideoStream> streams =
3144 test::CreateVideoStreams(width, height, encoder_config);
3145 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
3146 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3147 streams[i].min_bitrate_bps = 10000;
3148 streams[i].target_bitrate_bps = 15000;
3149 streams[i].max_bitrate_bps = 20000;
3150 }
3151 return streams;
3152 }
3153 };
3154
stefanff483612015-12-21 03:14:00 -08003155 void ModifyVideoConfigs(
3156 VideoSendStream::Config* send_config,
3157 std::vector<VideoReceiveStream::Config>* receive_configs,
3158 VideoEncoderConfig* encoder_config) override {
perkjfa10b552016-10-02 23:45:26 -07003159 encoder_config->video_stream_factory =
3160 new rtc::RefCountedObject<VideoStreamFactory>();
perkj26091b12016-09-01 01:17:40 -07003161 video_encoder_config_all_streams_ = encoder_config->Copy();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003162 if (send_single_ssrc_first_)
perkjfa10b552016-10-02 23:45:26 -07003163 encoder_config->number_of_streams = 1;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003164 }
3165
stefanff483612015-12-21 03:14:00 -08003166 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003167 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003168 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003169 send_stream_ = send_stream;
3170 }
3171
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003172 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003173 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
3174 << (send_single_ssrc_first_ ? "first SSRC."
3175 : "SSRCs.");
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003176
3177 if (send_single_ssrc_first_) {
3178 // Set full simulcast and continue with the rest of the SSRCs.
stefanff483612015-12-21 03:14:00 -08003179 send_stream_->ReconfigureVideoEncoder(
perkj26091b12016-09-01 01:17:40 -07003180 std::move(video_encoder_config_all_streams_));
Peter Boström5811a392015-12-10 13:02:50 +01003181 EXPECT_TRUE(Wait()) << "Timed out while waiting on additional SSRCs.";
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003182 }
3183 }
3184
3185 private:
3186 std::map<uint32_t, bool> valid_ssrcs_;
3187 std::map<uint32_t, bool> is_observed_;
3188
3189 const size_t num_ssrcs_;
3190 const bool send_single_ssrc_first_;
3191
3192 size_t ssrcs_to_observe_;
3193 bool expect_single_ssrc_;
3194
3195 VideoSendStream* send_stream_;
stefanff483612015-12-21 03:14:00 -08003196 VideoEncoderConfig video_encoder_config_all_streams_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003197 } test(kVideoSendSsrcs, num_ssrcs, send_single_ssrc_first);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003198
stefane74eef12016-01-08 06:47:13 -08003199 RunBaseTest(&test);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003200}
3201
philipelccdfcca2017-10-23 12:42:17 +02003202TEST_P(EndToEndTest, ReportsSetEncoderRates) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003203 class EncoderRateStatsTest : public test::EndToEndTest,
3204 public test::FakeEncoder {
3205 public:
eladalon413ee9a2017-08-22 04:02:52 -07003206 explicit EncoderRateStatsTest(
3207 test::SingleThreadedTaskQueueForTesting* task_queue)
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003208 : EndToEndTest(kDefaultTimeoutMs),
sprang867fb522015-08-03 04:38:41 -07003209 FakeEncoder(Clock::GetRealTimeClock()),
eladalon413ee9a2017-08-22 04:02:52 -07003210 task_queue_(task_queue),
sprang867fb522015-08-03 04:38:41 -07003211 send_stream_(nullptr),
3212 bitrate_kbps_(0) {}
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003213
stefanff483612015-12-21 03:14:00 -08003214 void OnVideoStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003215 VideoSendStream* send_stream,
3216 const std::vector<VideoReceiveStream*>& receive_streams) override {
3217 send_stream_ = send_stream;
3218 }
3219
stefanff483612015-12-21 03:14:00 -08003220 void ModifyVideoConfigs(
3221 VideoSendStream::Config* send_config,
3222 std::vector<VideoReceiveStream::Config>* receive_configs,
3223 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003224 send_config->encoder_settings.encoder = this;
kwibergaf476c72016-11-28 15:21:39 -08003225 RTC_DCHECK_EQ(1, encoder_config->number_of_streams);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003226 }
3227
Erik Språng08127a92016-11-16 16:41:30 +01003228 int32_t SetRateAllocation(const BitrateAllocation& rate_allocation,
3229 uint32_t framerate) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003230 // Make sure not to trigger on any default zero bitrates.
Erik Språng08127a92016-11-16 16:41:30 +01003231 if (rate_allocation.get_sum_bps() == 0)
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003232 return 0;
Peter Boströmf2f82832015-05-01 13:00:41 +02003233 rtc::CritScope lock(&crit_);
Erik Språng08127a92016-11-16 16:41:30 +01003234 bitrate_kbps_ = rate_allocation.get_sum_kbps();
Peter Boström5811a392015-12-10 13:02:50 +01003235 observation_complete_.Set();
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003236 return 0;
3237 }
3238
3239 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003240 ASSERT_TRUE(Wait())
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003241 << "Timed out while waiting for encoder SetRates() call.";
eladalon413ee9a2017-08-22 04:02:52 -07003242
3243 task_queue_->SendTask([this]() {
3244 WaitForEncoderTargetBitrateMatchStats();
3245 send_stream_->Stop();
3246 WaitForStatsReportZeroTargetBitrate();
3247 send_stream_->Start();
3248 WaitForEncoderTargetBitrateMatchStats();
3249 });
perkjf5b2e512016-07-05 08:34:04 -07003250 }
3251
3252 void WaitForEncoderTargetBitrateMatchStats() {
Peter Boström5811a392015-12-10 13:02:50 +01003253 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003254 VideoSendStream::Stats stats = send_stream_->GetStats();
3255 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003256 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003257 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
3258 static_cast<int>(bitrate_kbps_)) {
3259 return;
3260 }
3261 }
3262 SleepMs(1);
3263 }
3264 FAIL()
3265 << "Timed out waiting for stats reporting the currently set bitrate.";
3266 }
3267
perkjf5b2e512016-07-05 08:34:04 -07003268 void WaitForStatsReportZeroTargetBitrate() {
3269 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
3270 if (send_stream_->GetStats().target_media_bitrate_bps == 0) {
3271 return;
3272 }
3273 SleepMs(1);
3274 }
3275 FAIL() << "Timed out waiting for stats reporting zero bitrate.";
3276 }
3277
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003278 private:
eladalon413ee9a2017-08-22 04:02:52 -07003279 test::SingleThreadedTaskQueueForTesting* const task_queue_;
stefanf116bd02015-10-27 08:29:42 -07003280 rtc::CriticalSection crit_;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003281 VideoSendStream* send_stream_;
danilchapa37de392017-09-09 04:17:22 -07003282 uint32_t bitrate_kbps_ RTC_GUARDED_BY(crit_);
eladalon413ee9a2017-08-22 04:02:52 -07003283 } test(&task_queue_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003284
stefane74eef12016-01-08 06:47:13 -08003285 RunBaseTest(&test);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003286}
3287
philipelccdfcca2017-10-23 12:42:17 +02003288TEST_P(EndToEndTest, GetStats) {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00003289 static const int kStartBitrateBps = 3000000;
Peter Boströmdef398832015-05-27 17:59:11 +02003290 static const int kExpectedRenderDelayMs = 20;
tommi2e82f382016-06-21 00:26:43 -07003291
3292 class ReceiveStreamRenderer : public rtc::VideoSinkInterface<VideoFrame> {
3293 public:
3294 ReceiveStreamRenderer() {}
3295
3296 private:
3297 void OnFrame(const VideoFrame& video_frame) override {}
3298 };
3299
nissed30a1112016-04-18 05:15:22 -07003300 class StatsObserver : public test::EndToEndTest,
3301 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003302 public:
stefanf116bd02015-10-27 08:29:42 -07003303 StatsObserver()
3304 : EndToEndTest(kLongTimeoutMs),
Peter Boströmc6e16e32016-02-05 14:15:53 +01003305 encoder_(Clock::GetRealTimeClock(), 10),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00003306 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003307 expected_send_ssrcs_(),
Peter Boström5811a392015-12-10 13:02:50 +01003308 check_stats_event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003309
3310 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003311 Action OnSendRtp(const uint8_t* packet, size_t length) override {
sprangcd349d92016-07-13 09:11:28 -07003312 // Drop every 25th packet => 4% loss.
3313 static const int kPacketLossFrac = 25;
3314 RTPHeader header;
3315 RtpUtility::RtpHeaderParser parser(packet, length);
3316 if (parser.Parse(&header) &&
3317 expected_send_ssrcs_.find(header.ssrc) !=
3318 expected_send_ssrcs_.end() &&
3319 header.sequenceNumber % kPacketLossFrac == 0) {
3320 return DROP_PACKET;
3321 }
Peter Boström5811a392015-12-10 13:02:50 +01003322 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003323 return SEND_PACKET;
3324 }
3325
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003326 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01003327 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003328 return SEND_PACKET;
3329 }
3330
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003331 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01003332 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003333 return SEND_PACKET;
3334 }
3335
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003336 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01003337 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003338 return SEND_PACKET;
3339 }
3340
nissed30a1112016-04-18 05:15:22 -07003341 void OnFrame(const VideoFrame& video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003342 // Ensure that we have at least 5ms send side delay.
nissed30a1112016-04-18 05:15:22 -07003343 SleepMs(5);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003344 }
3345
3346 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003347 for (size_t i = 0; i < receive_streams_.size(); ++i) {
3348 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
3349 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003350
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003351 // Make sure all fields have been populated.
3352 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
3353 // always filled for all receivers.
3354 receive_stats_filled_["IncomingRate"] |=
3355 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003356
Peter Boströmb7d9a972015-12-18 16:01:11 +01003357 send_stats_filled_["DecoderImplementationName"] |=
3358 stats.decoder_implementation_name ==
3359 test::FakeDecoder::kImplementationName;
Peter Boströmdef398832015-05-27 17:59:11 +02003360 receive_stats_filled_["RenderDelayAsHighAsExpected"] |=
3361 stats.render_delay_ms >= kExpectedRenderDelayMs;
3362
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003363 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003364
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003365 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003366
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003367 receive_stats_filled_["StatisticsUpdated"] |=
srte186d9c32017-08-04 05:03:53 -07003368 stats.rtcp_stats.packets_lost != 0 ||
3369 stats.rtcp_stats.extended_highest_sequence_number != 0 ||
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003370 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003371
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003372 receive_stats_filled_["DataCountersUpdated"] |=
3373 stats.rtp_stats.transmitted.payload_bytes != 0 ||
3374 stats.rtp_stats.fec.packets != 0 ||
3375 stats.rtp_stats.transmitted.header_bytes != 0 ||
3376 stats.rtp_stats.transmitted.packets != 0 ||
3377 stats.rtp_stats.transmitted.padding_bytes != 0 ||
3378 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003379
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003380 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003381 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003382
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003383 receive_stats_filled_["FrameCounts"] |=
3384 stats.frame_counts.key_frames != 0 ||
3385 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00003386
pbosbb36fdf2015-07-09 07:48:14 -07003387 receive_stats_filled_["CName"] |= !stats.c_name.empty();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00003388
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003389 receive_stats_filled_["RtcpPacketTypeCount"] |=
3390 stats.rtcp_packet_type_counts.fir_packets != 0 ||
3391 stats.rtcp_packet_type_counts.nack_packets != 0 ||
3392 stats.rtcp_packet_type_counts.pli_packets != 0 ||
3393 stats.rtcp_packet_type_counts.nack_requests != 0 ||
3394 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbosf42376c2015-08-28 07:35:32 -07003395
3396 assert(stats.current_payload_type == -1 ||
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003397 stats.current_payload_type == kFakeVideoSendPayloadType);
pbosf42376c2015-08-28 07:35:32 -07003398 receive_stats_filled_["IncomingPayloadType"] |=
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003399 stats.current_payload_type == kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003400 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003401
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003402 return AllStatsFilled(receive_stats_filled_);
3403 }
3404
3405 bool CheckSendStats() {
Peter Boström74f6e9e2016-04-04 17:56:10 +02003406 RTC_DCHECK(send_stream_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003407 VideoSendStream::Stats stats = send_stream_->GetStats();
3408
philipel20d05a92016-12-19 04:17:27 -08003409 size_t expected_num_streams = kNumSsrcs + expected_send_ssrcs_.size();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003410 send_stats_filled_["NumStreams"] |=
philipel20d05a92016-12-19 04:17:27 -08003411 stats.substreams.size() == expected_num_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003412
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00003413 send_stats_filled_["CpuOveruseMetrics"] |=
Peter Boströme4499152016-02-05 11:13:28 +01003414 stats.avg_encode_time_ms != 0 && stats.encode_usage_percent != 0;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00003415
Peter Boströmb7d9a972015-12-18 16:01:11 +01003416 send_stats_filled_["EncoderImplementationName"] |=
3417 stats.encoder_implementation_name ==
3418 test::FakeEncoder::kImplementationName;
3419
Pera48ddb72016-09-29 11:48:50 +02003420 send_stats_filled_["EncoderPreferredBitrate"] |=
3421 stats.preferred_media_bitrate_bps > 0;
3422
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003423 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003424 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003425 it != stats.substreams.end(); ++it) {
sprangcd349d92016-07-13 09:11:28 -07003426 if (expected_send_ssrcs_.find(it->first) == expected_send_ssrcs_.end())
3427 continue; // Probably RTX.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003428
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003429 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003430 stats.input_frame_rate != 0;
3431
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003432 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003433
3434 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
srte186d9c32017-08-04 05:03:53 -07003435 stream_stats.rtcp_stats.packets_lost != 0 ||
3436 stream_stats.rtcp_stats.extended_highest_sequence_number != 0 ||
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003437 stream_stats.rtcp_stats.fraction_lost != 0;
3438
3439 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00003440 stream_stats.rtp_stats.fec.packets != 0 ||
3441 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
3442 stream_stats.rtp_stats.retransmitted.packets != 0 ||
3443 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003444
sprangcd349d92016-07-13 09:11:28 -07003445 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Total",
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003446 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00003447 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003448
sprangcd349d92016-07-13 09:11:28 -07003449 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Retransmit",
3450 it->first)] |=
3451 stream_stats.retransmit_bitrate_bps != 0;
3452
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003453 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00003454 stream_stats.frame_counts.delta_frames != 0 ||
3455 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003456
3457 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
3458 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00003459
3460 send_stats_filled_[CompoundKey("Delay", it->first)] |=
3461 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003462
3463 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
3464 // report dropped packets.
3465 send_stats_filled_["RtcpPacketTypeCount"] |=
3466 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
3467 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
3468 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
3469 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
3470 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003471 }
3472
3473 return AllStatsFilled(send_stats_filled_);
3474 }
3475
3476 std::string CompoundKey(const char* name, uint32_t ssrc) {
3477 std::ostringstream oss;
3478 oss << name << "_" << ssrc;
3479 return oss.str();
3480 }
3481
3482 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
sprangcd349d92016-07-13 09:11:28 -07003483 for (const auto& stat : stats_map) {
3484 if (!stat.second)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003485 return false;
3486 }
3487 return true;
3488 }
3489
eladalon413ee9a2017-08-22 04:02:52 -07003490 test::PacketTransport* CreateSendTransport(
3491 test::SingleThreadedTaskQueueForTesting* task_queue,
3492 Call* sender_call) override {
stefane74eef12016-01-08 06:47:13 -08003493 FakeNetworkPipe::Config network_config;
3494 network_config.loss_percent = 5;
eladalon413ee9a2017-08-22 04:02:52 -07003495 return new test::PacketTransport(task_queue, sender_call, this,
minyue20c84cc2017-04-10 16:57:57 -07003496 test::PacketTransport::kSender,
3497 payload_type_map_, network_config);
stefane74eef12016-01-08 06:47:13 -08003498 }
3499
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003500 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00003501 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01003502 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00003503 return config;
3504 }
3505
perkjfa10b552016-10-02 23:45:26 -07003506 // This test use other VideoStream settings than the the default settings
3507 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3508 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3509 // in ModifyVideoConfigs.
3510 class VideoStreamFactory
3511 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3512 public:
3513 VideoStreamFactory() {}
3514
3515 private:
3516 std::vector<VideoStream> CreateEncoderStreams(
3517 int width,
3518 int height,
3519 const VideoEncoderConfig& encoder_config) override {
3520 std::vector<VideoStream> streams =
3521 test::CreateVideoStreams(width, height, encoder_config);
3522 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
3523 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3524 streams[i].min_bitrate_bps = 10000;
3525 streams[i].target_bitrate_bps = 15000;
3526 streams[i].max_bitrate_bps = 20000;
3527 }
3528 return streams;
3529 }
3530 };
3531
stefanff483612015-12-21 03:14:00 -08003532 void ModifyVideoConfigs(
3533 VideoSendStream::Config* send_config,
3534 std::vector<VideoReceiveStream::Config>* receive_configs,
3535 VideoEncoderConfig* encoder_config) override {
perkjfa10b552016-10-02 23:45:26 -07003536 encoder_config->video_stream_factory =
3537 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003538 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003539 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003540
sprangcd349d92016-07-13 09:11:28 -07003541 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
3542 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
3543
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003544 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003545 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003546 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003547 expected_receive_ssrcs_.push_back(
3548 (*receive_configs)[i].rtp.remote_ssrc);
Peter Boströmdef398832015-05-27 17:59:11 +02003549 (*receive_configs)[i].render_delay_ms = kExpectedRenderDelayMs;
tommi2e82f382016-06-21 00:26:43 -07003550 (*receive_configs)[i].renderer = &receive_stream_renderer_;
sprangcd349d92016-07-13 09:11:28 -07003551 (*receive_configs)[i].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
3552
brandtr14742122017-01-27 04:53:07 -08003553 (*receive_configs)[i].rtp.rtx_ssrc = kSendRtxSsrcs[i];
nisse26e3abb2017-08-25 04:44:25 -07003554 (*receive_configs)[i]
3555 .rtp.rtx_associated_payload_types[kSendRtxPayloadType] =
3556 kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003557 }
sprangcd349d92016-07-13 09:11:28 -07003558
3559 for (size_t i = 0; i < kNumSsrcs; ++i)
3560 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
3561
Peter Boströmc6e16e32016-02-05 14:15:53 +01003562 // Use a delayed encoder to make sure we see CpuOveruseMetrics stats that
3563 // are non-zero.
3564 send_config->encoder_settings.encoder = &encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003565 }
3566
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003567 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00003568
stefanff483612015-12-21 03:14:00 -08003569 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003570 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003571 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003572 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003573 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003574 }
3575
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003576 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003577 Clock* clock = Clock::GetRealTimeClock();
3578 int64_t now = clock->TimeInMilliseconds();
3579 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
3580 bool receive_ok = false;
3581 bool send_ok = false;
3582
3583 while (now < stop_time) {
3584 if (!receive_ok)
3585 receive_ok = CheckReceiveStats();
3586 if (!send_ok)
3587 send_ok = CheckSendStats();
3588
3589 if (receive_ok && send_ok)
3590 return;
3591
3592 int64_t time_until_timout_ = stop_time - now;
3593 if (time_until_timout_ > 0)
Peter Boström5811a392015-12-10 13:02:50 +01003594 check_stats_event_.Wait(time_until_timout_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003595 now = clock->TimeInMilliseconds();
3596 }
3597
3598 ADD_FAILURE() << "Timed out waiting for filled stats.";
3599 for (std::map<std::string, bool>::const_iterator it =
3600 receive_stats_filled_.begin();
eladalon413ee9a2017-08-22 04:02:52 -07003601 it != receive_stats_filled_.end(); ++it) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003602 if (!it->second) {
3603 ADD_FAILURE() << "Missing receive stats: " << it->first;
3604 }
3605 }
3606
3607 for (std::map<std::string, bool>::const_iterator it =
3608 send_stats_filled_.begin();
eladalon413ee9a2017-08-22 04:02:52 -07003609 it != send_stats_filled_.end(); ++it) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003610 if (!it->second) {
3611 ADD_FAILURE() << "Missing send stats: " << it->first;
3612 }
3613 }
3614 }
3615
Peter Boströmc6e16e32016-02-05 14:15:53 +01003616 test::DelayedEncoder encoder_;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003617 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003618 std::map<std::string, bool> receive_stats_filled_;
3619
3620 VideoSendStream* send_stream_;
3621 std::map<std::string, bool> send_stats_filled_;
3622
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003623 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003624 std::set<uint32_t> expected_send_ssrcs_;
3625 std::string expected_cname_;
3626
Peter Boström5811a392015-12-10 13:02:50 +01003627 rtc::Event check_stats_event_;
tommi2e82f382016-06-21 00:26:43 -07003628 ReceiveStreamRenderer receive_stream_renderer_;
stefanf116bd02015-10-27 08:29:42 -07003629 } test;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003630
stefane74eef12016-01-08 06:47:13 -08003631 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003632}
3633
philipelccdfcca2017-10-23 12:42:17 +02003634TEST_P(EndToEndTest, TimingFramesAreReported) {
ilnik2edc6842017-07-06 03:06:50 -07003635 static const int kExtensionId = 5;
3636
3637 class StatsObserver : public test::EndToEndTest {
3638 public:
3639 StatsObserver() : EndToEndTest(kLongTimeoutMs) {}
3640
3641 private:
ilnik2edc6842017-07-06 03:06:50 -07003642 void ModifyVideoConfigs(
3643 VideoSendStream::Config* send_config,
3644 std::vector<VideoReceiveStream::Config>* receive_configs,
3645 VideoEncoderConfig* encoder_config) override {
3646 send_config->rtp.extensions.clear();
3647 send_config->rtp.extensions.push_back(
3648 RtpExtension(RtpExtension::kVideoTimingUri, kExtensionId));
3649 for (size_t i = 0; i < receive_configs->size(); ++i) {
3650 (*receive_configs)[i].rtp.extensions.clear();
3651 (*receive_configs)[i].rtp.extensions.push_back(
3652 RtpExtension(RtpExtension::kVideoTimingUri, kExtensionId));
3653 }
3654 }
3655
3656 void OnVideoStreamsCreated(
3657 VideoSendStream* send_stream,
3658 const std::vector<VideoReceiveStream*>& receive_streams) override {
3659 receive_streams_ = receive_streams;
3660 }
3661
3662 void PerformTest() override {
3663 // No frames reported initially.
3664 for (size_t i = 0; i < receive_streams_.size(); ++i) {
ilnik75204c52017-09-04 03:35:40 -07003665 EXPECT_FALSE(receive_streams_[i]->GetStats().timing_frame_info);
ilnik2edc6842017-07-06 03:06:50 -07003666 }
3667 // Wait for at least one timing frame to be sent with 100ms grace period.
3668 SleepMs(kDefaultTimingFramesDelayMs + 100);
3669 // Check that timing frames are reported for each stream.
3670 for (size_t i = 0; i < receive_streams_.size(); ++i) {
ilnik75204c52017-09-04 03:35:40 -07003671 EXPECT_TRUE(receive_streams_[i]->GetStats().timing_frame_info);
ilnik2edc6842017-07-06 03:06:50 -07003672 }
3673 }
3674
3675 std::vector<VideoReceiveStream*> receive_streams_;
3676 } test;
3677
3678 RunBaseTest(&test);
3679}
3680
sprang1a646ee2016-12-01 06:34:11 -08003681class RtcpXrObserver : public test::EndToEndTest {
3682 public:
sprang44b3ef62017-01-13 07:30:25 -08003683 RtcpXrObserver(bool enable_rrtr, bool enable_target_bitrate)
sprang1a646ee2016-12-01 06:34:11 -08003684 : EndToEndTest(test::CallTest::kDefaultTimeoutMs),
3685 enable_rrtr_(enable_rrtr),
sprang44b3ef62017-01-13 07:30:25 -08003686 enable_target_bitrate_(enable_target_bitrate),
sprang1a646ee2016-12-01 06:34:11 -08003687 sent_rtcp_sr_(0),
3688 sent_rtcp_rr_(0),
3689 sent_rtcp_rrtr_(0),
3690 sent_rtcp_target_bitrate_(false),
3691 sent_rtcp_dlrr_(0) {}
3692
3693 private:
3694 // Receive stream should send RR packets (and RRTR packets if enabled).
3695 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
3696 rtc::CritScope lock(&crit_);
3697 test::RtcpPacketParser parser;
3698 EXPECT_TRUE(parser.Parse(packet, length));
3699
3700 sent_rtcp_rr_ += parser.receiver_report()->num_packets();
3701 EXPECT_EQ(0, parser.sender_report()->num_packets());
3702 EXPECT_GE(1, parser.xr()->num_packets());
3703 if (parser.xr()->num_packets() > 0) {
3704 if (parser.xr()->rrtr())
3705 ++sent_rtcp_rrtr_;
3706 EXPECT_FALSE(parser.xr()->dlrr());
3707 }
3708
3709 return SEND_PACKET;
3710 }
3711 // Send stream should send SR packets (and DLRR packets if enabled).
3712 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
3713 rtc::CritScope lock(&crit_);
3714 test::RtcpPacketParser parser;
3715 EXPECT_TRUE(parser.Parse(packet, length));
3716
3717 sent_rtcp_sr_ += parser.sender_report()->num_packets();
3718 EXPECT_LE(parser.xr()->num_packets(), 1);
3719 if (parser.xr()->num_packets() > 0) {
3720 EXPECT_FALSE(parser.xr()->rrtr());
3721 if (parser.xr()->dlrr())
3722 ++sent_rtcp_dlrr_;
3723 if (parser.xr()->target_bitrate())
3724 sent_rtcp_target_bitrate_ = true;
3725 }
3726
3727 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
3728 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve &&
sprang44b3ef62017-01-13 07:30:25 -08003729 (sent_rtcp_target_bitrate_ || !enable_target_bitrate_)) {
sprang1a646ee2016-12-01 06:34:11 -08003730 if (enable_rrtr_) {
3731 EXPECT_GT(sent_rtcp_rrtr_, 0);
3732 EXPECT_GT(sent_rtcp_dlrr_, 0);
3733 } else {
3734 EXPECT_EQ(sent_rtcp_rrtr_, 0);
3735 EXPECT_EQ(sent_rtcp_dlrr_, 0);
3736 }
sprang44b3ef62017-01-13 07:30:25 -08003737 EXPECT_EQ(enable_target_bitrate_, sent_rtcp_target_bitrate_);
sprang1a646ee2016-12-01 06:34:11 -08003738 observation_complete_.Set();
3739 }
3740 return SEND_PACKET;
3741 }
3742
3743 void ModifyVideoConfigs(
3744 VideoSendStream::Config* send_config,
3745 std::vector<VideoReceiveStream::Config>* receive_configs,
3746 VideoEncoderConfig* encoder_config) override {
sprang44b3ef62017-01-13 07:30:25 -08003747 if (enable_target_bitrate_) {
3748 // TargetBitrate only signaled for screensharing.
3749 encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
3750 }
sprang1a646ee2016-12-01 06:34:11 -08003751 (*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
3752 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
3753 enable_rrtr_;
3754 }
3755
3756 void PerformTest() override {
3757 EXPECT_TRUE(Wait())
3758 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
3759 }
3760
3761 static const int kNumRtcpReportPacketsToObserve = 5;
3762
3763 rtc::CriticalSection crit_;
sprang44b3ef62017-01-13 07:30:25 -08003764 const bool enable_rrtr_;
3765 const bool enable_target_bitrate_;
sprang1a646ee2016-12-01 06:34:11 -08003766 int sent_rtcp_sr_;
danilchapa37de392017-09-09 04:17:22 -07003767 int sent_rtcp_rr_ RTC_GUARDED_BY(&crit_);
3768 int sent_rtcp_rrtr_ RTC_GUARDED_BY(&crit_);
3769 bool sent_rtcp_target_bitrate_ RTC_GUARDED_BY(&crit_);
sprang1a646ee2016-12-01 06:34:11 -08003770 int sent_rtcp_dlrr_;
3771};
3772
philipelccdfcca2017-10-23 12:42:17 +02003773TEST_P(EndToEndTest, TestExtendedReportsWithRrtrWithoutTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003774 RtcpXrObserver test(true, false);
sprang1a646ee2016-12-01 06:34:11 -08003775 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003776}
3777
philipelccdfcca2017-10-23 12:42:17 +02003778TEST_P(EndToEndTest, TestExtendedReportsWithoutRrtrWithoutTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003779 RtcpXrObserver test(false, false);
3780 RunBaseTest(&test);
3781}
3782
philipelccdfcca2017-10-23 12:42:17 +02003783TEST_P(EndToEndTest, TestExtendedReportsWithRrtrWithTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003784 RtcpXrObserver test(true, true);
3785 RunBaseTest(&test);
3786}
3787
philipelccdfcca2017-10-23 12:42:17 +02003788TEST_P(EndToEndTest, TestExtendedReportsWithoutRrtrWithTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003789 RtcpXrObserver test(false, true);
sprang1a646ee2016-12-01 06:34:11 -08003790 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003791}
3792
philipelccdfcca2017-10-23 12:42:17 +02003793TEST_P(EndToEndTest, TestReceivedRtpPacketStats) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003794 static const size_t kNumRtpPacketsToSend = 5;
3795 class ReceivedRtpStatsObserver : public test::EndToEndTest {
3796 public:
3797 ReceivedRtpStatsObserver()
3798 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00003799 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003800 sent_rtp_(0) {}
3801
3802 private:
stefanff483612015-12-21 03:14:00 -08003803 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003804 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003805 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003806 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003807 }
3808
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003809 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003810 if (sent_rtp_ >= kNumRtpPacketsToSend) {
3811 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00003812 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
Peter Boström5811a392015-12-10 13:02:50 +01003813 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003814 }
3815 return DROP_PACKET;
3816 }
3817 ++sent_rtp_;
3818 return SEND_PACKET;
3819 }
3820
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003821 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003822 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003823 << "Timed out while verifying number of received RTP packets.";
3824 }
3825
3826 VideoReceiveStream* receive_stream_;
3827 uint32_t sent_rtp_;
3828 } test;
3829
stefane74eef12016-01-08 06:47:13 -08003830 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003831}
3832
philipelccdfcca2017-10-23 12:42:17 +02003833TEST_P(EndToEndTest, SendsSetSsrc) {
philipel266f0a42016-11-28 08:49:07 -08003834 TestSendsSetSsrcs(1, false);
3835}
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003836
philipelccdfcca2017-10-23 12:42:17 +02003837TEST_P(EndToEndTest, SendsSetSimulcastSsrcs) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003838 TestSendsSetSsrcs(kNumSsrcs, false);
3839}
3840
philipelccdfcca2017-10-23 12:42:17 +02003841TEST_P(EndToEndTest, CanSwitchToUseAllSsrcs) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003842 TestSendsSetSsrcs(kNumSsrcs, true);
3843}
3844
philipelccdfcca2017-10-23 12:42:17 +02003845TEST_P(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003846 class ObserveRedundantPayloads: public test::EndToEndTest {
3847 public:
3848 ObserveRedundantPayloads()
3849 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003850 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003851 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
3852 }
3853 }
3854
3855 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003856 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003857 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003858 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003859
3860 if (!registered_rtx_ssrc_[header.ssrc])
3861 return SEND_PACKET;
3862
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003863 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003864 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003865 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003866
3867 if (!packet_is_redundant_payload)
3868 return SEND_PACKET;
3869
3870 if (!observed_redundant_retransmission_[header.ssrc]) {
3871 observed_redundant_retransmission_[header.ssrc] = true;
3872 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01003873 observation_complete_.Set();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003874 }
3875
3876 return SEND_PACKET;
3877 }
3878
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003879 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003880
perkjfa10b552016-10-02 23:45:26 -07003881 // This test use other VideoStream settings than the the default settings
3882 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3883 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3884 // in ModifyVideoConfigs.
3885 class VideoStreamFactory
3886 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3887 public:
3888 VideoStreamFactory() {}
3889
3890 private:
3891 std::vector<VideoStream> CreateEncoderStreams(
3892 int width,
3893 int height,
3894 const VideoEncoderConfig& encoder_config) override {
3895 std::vector<VideoStream> streams =
3896 test::CreateVideoStreams(width, height, encoder_config);
3897 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
3898 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3899 streams[i].min_bitrate_bps = 10000;
3900 streams[i].target_bitrate_bps = 15000;
3901 streams[i].max_bitrate_bps = 20000;
3902 }
3903 return streams;
3904 }
3905 };
3906
stefanff483612015-12-21 03:14:00 -08003907 void ModifyVideoConfigs(
3908 VideoSendStream::Config* send_config,
3909 std::vector<VideoReceiveStream::Config>* receive_configs,
3910 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003911 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
perkjfa10b552016-10-02 23:45:26 -07003912 encoder_config->video_stream_factory =
3913 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003914 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003915
3916 for (size_t i = 0; i < kNumSsrcs; ++i)
3917 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00003918
3919 // Significantly higher than max bitrates for all video streams -> forcing
3920 // padding to trigger redundant padding on all RTX SSRCs.
3921 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003922 }
3923
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003924 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003925 EXPECT_TRUE(Wait())
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003926 << "Timed out while waiting for redundant payloads on all SSRCs.";
3927 }
3928
3929 private:
3930 size_t ssrcs_to_observe_;
3931 std::map<uint32_t, bool> observed_redundant_retransmission_;
3932 std::map<uint32_t, bool> registered_rtx_ssrc_;
3933 } test;
3934
stefane74eef12016-01-08 06:47:13 -08003935 RunBaseTest(&test);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003936}
3937
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003938void EndToEndTest::TestRtpStatePreservation(bool use_rtx,
3939 bool provoke_rtcpsr_before_rtp) {
brandtr5e171752017-05-23 03:32:16 -07003940 // This test uses other VideoStream settings than the the default settings
3941 // implemented in DefaultVideoStreamFactory. Therefore this test implements
perkjfa10b552016-10-02 23:45:26 -07003942 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3943 // in ModifyVideoConfigs.
3944 class VideoStreamFactory
3945 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3946 public:
3947 VideoStreamFactory() {}
3948
3949 private:
3950 std::vector<VideoStream> CreateEncoderStreams(
3951 int width,
3952 int height,
3953 const VideoEncoderConfig& encoder_config) override {
3954 std::vector<VideoStream> streams =
3955 test::CreateVideoStreams(width, height, encoder_config);
3956
3957 if (encoder_config.number_of_streams > 1) {
3958 // Lower bitrates so that all streams send initially.
kwibergaf476c72016-11-28 15:21:39 -08003959 RTC_DCHECK_EQ(3, encoder_config.number_of_streams);
perkjfa10b552016-10-02 23:45:26 -07003960 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3961 streams[i].min_bitrate_bps = 10000;
3962 streams[i].target_bitrate_bps = 15000;
3963 streams[i].max_bitrate_bps = 20000;
3964 }
3965 } else {
3966 // Use the same total bitrates when sending a single stream to avoid
3967 // lowering
3968 // the bitrate estimate and requiring a subsequent rampup.
3969 streams[0].min_bitrate_bps = 3 * 10000;
3970 streams[0].target_bitrate_bps = 3 * 15000;
3971 streams[0].max_bitrate_bps = 3 * 20000;
3972 }
3973 return streams;
3974 }
3975 };
3976
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003977 class RtpSequenceObserver : public test::RtpRtcpObserver {
3978 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003979 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003980 : test::RtpRtcpObserver(kDefaultTimeoutMs),
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003981 ssrcs_to_observe_(kNumSsrcs) {
3982 for (size_t i = 0; i < kNumSsrcs; ++i) {
danilchap32cd2c42016-08-01 06:58:34 -07003983 ssrc_is_rtx_[kVideoSendSsrcs[i]] = false;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003984 if (use_rtx)
danilchap32cd2c42016-08-01 06:58:34 -07003985 ssrc_is_rtx_[kSendRtxSsrcs[i]] = true;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003986 }
3987 }
3988
3989 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
Peter Boströmf2f82832015-05-01 13:00:41 +02003990 rtc::CritScope lock(&crit_);
danilchap34877ee2016-02-01 08:25:04 -08003991 ssrc_observed_.clear();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003992 ssrcs_to_observe_ = num_expected_ssrcs;
3993 }
3994
3995 private:
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003996 void ValidateTimestampGap(uint32_t ssrc,
3997 uint32_t timestamp,
3998 bool only_padding)
danilchapa37de392017-09-09 04:17:22 -07003999 RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004000 static const int32_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
4001 auto timestamp_it = last_observed_timestamp_.find(ssrc);
4002 if (timestamp_it == last_observed_timestamp_.end()) {
4003 EXPECT_FALSE(only_padding);
4004 last_observed_timestamp_[ssrc] = timestamp;
4005 } else {
4006 // Verify timestamps are reasonably close.
4007 uint32_t latest_observed = timestamp_it->second;
4008 // Wraparound handling is unnecessary here as long as an int variable
4009 // is used to store the result.
4010 int32_t timestamp_gap = timestamp - latest_observed;
4011 EXPECT_LE(std::abs(timestamp_gap), kMaxTimestampGap)
4012 << "Gap in timestamps (" << latest_observed << " -> " << timestamp
4013 << ") too large for SSRC: " << ssrc << ".";
4014 timestamp_it->second = timestamp;
4015 }
4016 }
4017
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004018 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004019 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00004020 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004021 const uint32_t ssrc = header.ssrc;
danilchap5c35cf92016-02-03 14:14:49 -08004022 const int64_t sequence_number =
4023 seq_numbers_unwrapper_.Unwrap(header.sequenceNumber);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004024 const uint32_t timestamp = header.timestamp;
danilchap34877ee2016-02-01 08:25:04 -08004025 const bool only_padding =
4026 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004027
danilchap32cd2c42016-08-01 06:58:34 -07004028 EXPECT_TRUE(ssrc_is_rtx_.find(ssrc) != ssrc_is_rtx_.end())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004029 << "Received SSRC that wasn't configured: " << ssrc;
4030
danilchap5c35cf92016-02-03 14:14:49 -08004031 static const int64_t kMaxSequenceNumberGap = 100;
4032 std::list<int64_t>* seq_numbers = &last_observed_seq_numbers_[ssrc];
4033 if (seq_numbers->empty()) {
4034 seq_numbers->push_back(sequence_number);
4035 } else {
4036 // We shouldn't get replays of previous sequence numbers.
4037 for (int64_t observed : *seq_numbers) {
4038 EXPECT_NE(observed, sequence_number)
4039 << "Received sequence number " << sequence_number
4040 << " for SSRC " << ssrc << " 2nd time.";
4041 }
4042 // Verify sequence numbers are reasonably close.
4043 int64_t latest_observed = seq_numbers->back();
4044 int64_t sequence_number_gap = sequence_number - latest_observed;
4045 EXPECT_LE(std::abs(sequence_number_gap), kMaxSequenceNumberGap)
4046 << "Gap in sequence numbers (" << latest_observed << " -> "
4047 << sequence_number << ") too large for SSRC: " << ssrc << ".";
4048 seq_numbers->push_back(sequence_number);
4049 if (seq_numbers->size() >= kMaxSequenceNumberGap) {
4050 seq_numbers->pop_front();
4051 }
4052 }
4053
danilchap32cd2c42016-08-01 06:58:34 -07004054 if (!ssrc_is_rtx_[ssrc]) {
4055 rtc::CritScope lock(&crit_);
4056 ValidateTimestampGap(ssrc, timestamp, only_padding);
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004057
danilchap32cd2c42016-08-01 06:58:34 -07004058 // Wait for media packets on all ssrcs.
4059 if (!ssrc_observed_[ssrc] && !only_padding) {
4060 ssrc_observed_[ssrc] = true;
4061 if (--ssrcs_to_observe_ == 0)
4062 observation_complete_.Set();
4063 }
danilchap34877ee2016-02-01 08:25:04 -08004064 }
4065
danilchapf4b9c772016-01-28 06:14:24 -08004066 return SEND_PACKET;
4067 }
4068
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004069 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
4070 test::RtcpPacketParser rtcp_parser;
4071 rtcp_parser.Parse(packet, length);
4072 if (rtcp_parser.sender_report()->num_packets() > 0) {
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02004073 uint32_t ssrc = rtcp_parser.sender_report()->sender_ssrc();
4074 uint32_t rtcp_timestamp = rtcp_parser.sender_report()->rtp_timestamp();
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004075
4076 rtc::CritScope lock(&crit_);
4077 ValidateTimestampGap(ssrc, rtcp_timestamp, false);
4078 }
4079 return SEND_PACKET;
4080 }
4081
danilchap5c35cf92016-02-03 14:14:49 -08004082 SequenceNumberUnwrapper seq_numbers_unwrapper_;
4083 std::map<uint32_t, std::list<int64_t>> last_observed_seq_numbers_;
danilchap34877ee2016-02-01 08:25:04 -08004084 std::map<uint32_t, uint32_t> last_observed_timestamp_;
danilchap32cd2c42016-08-01 06:58:34 -07004085 std::map<uint32_t, bool> ssrc_is_rtx_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004086
Peter Boströmf2f82832015-05-01 13:00:41 +02004087 rtc::CriticalSection crit_;
danilchapa37de392017-09-09 04:17:22 -07004088 size_t ssrcs_to_observe_ RTC_GUARDED_BY(crit_);
4089 std::map<uint32_t, bool> ssrc_observed_ RTC_GUARDED_BY(crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004090 } observer(use_rtx);
4091
eladalon413ee9a2017-08-22 04:02:52 -07004092 std::unique_ptr<test::PacketTransport> send_transport;
4093 std::unique_ptr<test::PacketTransport> receive_transport;
4094
philipel4fb651d2017-04-10 03:54:05 -07004095 Call::Config config(event_log_.get());
eladalon413ee9a2017-08-22 04:02:52 -07004096 VideoEncoderConfig one_stream;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004097
eladalon413ee9a2017-08-22 04:02:52 -07004098 task_queue_.SendTask([this, &observer, &send_transport, &receive_transport,
4099 &config, &one_stream, use_rtx]() {
4100 CreateCalls(config, config);
stefanf116bd02015-10-27 08:29:42 -07004101
eladalon413ee9a2017-08-22 04:02:52 -07004102 send_transport = rtc::MakeUnique<test::PacketTransport>(
4103 &task_queue_, sender_call_.get(), &observer,
4104 test::PacketTransport::kSender, payload_type_map_,
4105 FakeNetworkPipe::Config());
4106 receive_transport = rtc::MakeUnique<test::PacketTransport>(
4107 &task_queue_, nullptr, &observer, test::PacketTransport::kReceiver,
4108 payload_type_map_, FakeNetworkPipe::Config());
4109 send_transport->SetReceiver(receiver_call_->Receiver());
4110 receive_transport->SetReceiver(sender_call_->Receiver());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004111
eladalon413ee9a2017-08-22 04:02:52 -07004112 CreateSendConfig(kNumSsrcs, 0, 0, send_transport.get());
4113
4114 if (use_rtx) {
4115 for (size_t i = 0; i < kNumSsrcs; ++i) {
4116 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
4117 }
4118 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004119 }
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004120
eladalon413ee9a2017-08-22 04:02:52 -07004121 video_encoder_config_.video_stream_factory =
4122 new rtc::RefCountedObject<VideoStreamFactory>();
4123 // Use the same total bitrates when sending a single stream to avoid
4124 // lowering the bitrate estimate and requiring a subsequent rampup.
4125 one_stream = video_encoder_config_.Copy();
4126 // one_stream.streams.resize(1);
4127 one_stream.number_of_streams = 1;
4128 CreateMatchingReceiveConfigs(receive_transport.get());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004129
eladalon413ee9a2017-08-22 04:02:52 -07004130 CreateVideoStreams();
4131 CreateFrameGeneratorCapturer(30, 1280, 720);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004132
eladalon413ee9a2017-08-22 04:02:52 -07004133 Start();
4134 });
4135
Peter Boström5811a392015-12-10 13:02:50 +01004136 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004137 << "Timed out waiting for all SSRCs to send packets.";
4138
4139 // Test stream resetting more than once to make sure that the state doesn't
4140 // get set once (this could be due to using std::map::insert for instance).
4141 for (size_t i = 0; i < 3; ++i) {
eladalon413ee9a2017-08-22 04:02:52 -07004142 task_queue_.SendTask([&]() {
4143 frame_generator_capturer_->Stop();
4144 sender_call_->DestroyVideoSendStream(video_send_stream_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004145
eladalon413ee9a2017-08-22 04:02:52 -07004146 // Re-create VideoSendStream with only one stream.
4147 video_send_stream_ = sender_call_->CreateVideoSendStream(
4148 video_send_config_.Copy(), one_stream.Copy());
4149 video_send_stream_->Start();
4150 if (provoke_rtcpsr_before_rtp) {
4151 // Rapid Resync Request forces sending RTCP Sender Report back.
4152 // Using this request speeds up this test because then there is no need
4153 // to wait for a second for periodic Sender Report.
4154 rtcp::RapidResyncRequest force_send_sr_back_request;
4155 rtc::Buffer packet = force_send_sr_back_request.Build();
4156 static_cast<webrtc::test::DirectTransport*>(receive_transport.get())
4157 ->SendRtcp(packet.data(), packet.size());
4158 }
4159 CreateFrameGeneratorCapturer(30, 1280, 720);
4160 frame_generator_capturer_->Start();
4161 });
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004162
4163 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01004164 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004165
4166 // Reconfigure back to use all streams.
eladalon413ee9a2017-08-22 04:02:52 -07004167 task_queue_.SendTask([this]() {
4168 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
4169 });
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004170 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01004171 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004172 << "Timed out waiting for all SSRCs to send packets.";
4173
4174 // Reconfigure down to one stream.
eladalon413ee9a2017-08-22 04:02:52 -07004175 task_queue_.SendTask([this, &one_stream]() {
4176 video_send_stream_->ReconfigureVideoEncoder(one_stream.Copy());
4177 });
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004178 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01004179 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004180
4181 // Reconfigure back to use all streams.
eladalon413ee9a2017-08-22 04:02:52 -07004182 task_queue_.SendTask([this]() {
4183 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
4184 });
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004185 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01004186 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004187 << "Timed out waiting for all SSRCs to send packets.";
4188 }
4189
eladalon413ee9a2017-08-22 04:02:52 -07004190 task_queue_.SendTask([this, &send_transport, &receive_transport]() {
4191 Stop();
4192 DestroyStreams();
4193 send_transport.reset();
4194 receive_transport.reset();
4195 DestroyCalls();
4196 });
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004197}
4198
philipelccdfcca2017-10-23 12:42:17 +02004199TEST_P(EndToEndTest, RestartingSendStreamPreservesRtpState) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004200 TestRtpStatePreservation(false, false);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004201}
4202
philipelccdfcca2017-10-23 12:42:17 +02004203TEST_P(EndToEndTest, RestartingSendStreamPreservesRtpStatesWithRtx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004204 TestRtpStatePreservation(true, false);
4205}
4206
philipelccdfcca2017-10-23 12:42:17 +02004207TEST_P(EndToEndTest, RestartingSendStreamKeepsRtpAndRtcpTimestampsSynced) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004208 TestRtpStatePreservation(true, true);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004209}
4210
brandtreb806792017-05-31 07:46:56 -07004211// This test is flaky on linux_memcheck. Disable on all linux bots until
4212// flakyness has been fixed.
4213// https://bugs.chromium.org/p/webrtc/issues/detail?id=7737
4214#if defined(WEBRTC_LINUX)
philipelccdfcca2017-10-23 12:42:17 +02004215TEST_P(EndToEndTest, DISABLED_TestFlexfecRtpStatePreservation) {
brandtreb806792017-05-31 07:46:56 -07004216#else
philipelccdfcca2017-10-23 12:42:17 +02004217TEST_P(EndToEndTest, TestFlexfecRtpStatePreservation) {
brandtreb806792017-05-31 07:46:56 -07004218#endif
brandtr48d21a22017-05-30 02:32:12 -07004219 class RtpSequenceObserver : public test::RtpRtcpObserver {
4220 public:
4221 RtpSequenceObserver()
4222 : test::RtpRtcpObserver(kDefaultTimeoutMs),
4223 num_flexfec_packets_sent_(0) {}
4224
4225 void ResetPacketCount() {
4226 rtc::CritScope lock(&crit_);
4227 num_flexfec_packets_sent_ = 0;
4228 }
4229
4230 private:
4231 Action OnSendRtp(const uint8_t* packet, size_t length) override {
4232 rtc::CritScope lock(&crit_);
4233
4234 RTPHeader header;
4235 EXPECT_TRUE(parser_->Parse(packet, length, &header));
4236 const uint16_t sequence_number = header.sequenceNumber;
4237 const uint32_t timestamp = header.timestamp;
4238 const uint32_t ssrc = header.ssrc;
4239
4240 if (ssrc == kVideoSendSsrcs[0] || ssrc == kSendRtxSsrcs[0]) {
4241 return SEND_PACKET;
4242 }
4243 EXPECT_EQ(kFlexfecSendSsrc, ssrc) << "Unknown SSRC sent.";
4244
4245 ++num_flexfec_packets_sent_;
4246
4247 // If this is the first packet, we have nothing to compare to.
4248 if (!last_observed_sequence_number_) {
4249 last_observed_sequence_number_.emplace(sequence_number);
4250 last_observed_timestamp_.emplace(timestamp);
4251
4252 return SEND_PACKET;
4253 }
4254
4255 // Verify continuity and monotonicity of RTP sequence numbers.
4256 EXPECT_EQ(static_cast<uint16_t>(*last_observed_sequence_number_ + 1),
4257 sequence_number);
4258 last_observed_sequence_number_.emplace(sequence_number);
4259
4260 // Timestamps should be non-decreasing...
4261 const bool timestamp_is_same_or_newer =
4262 timestamp == *last_observed_timestamp_ ||
4263 IsNewerTimestamp(timestamp, *last_observed_timestamp_);
4264 EXPECT_TRUE(timestamp_is_same_or_newer);
4265 // ...but reasonably close in time.
4266 const int k10SecondsInRtpTimestampBase = 10 * kVideoPayloadTypeFrequency;
4267 EXPECT_TRUE(IsNewerTimestamp(
4268 *last_observed_timestamp_ + k10SecondsInRtpTimestampBase, timestamp));
4269 last_observed_timestamp_.emplace(timestamp);
4270
4271 // Pass test when enough packets have been let through.
4272 if (num_flexfec_packets_sent_ >= 10) {
4273 observation_complete_.Set();
4274 }
4275
4276 return SEND_PACKET;
4277 }
4278
danilchapa37de392017-09-09 04:17:22 -07004279 rtc::Optional<uint16_t> last_observed_sequence_number_
4280 RTC_GUARDED_BY(crit_);
4281 rtc::Optional<uint32_t> last_observed_timestamp_ RTC_GUARDED_BY(crit_);
4282 size_t num_flexfec_packets_sent_ RTC_GUARDED_BY(crit_);
brandtr48d21a22017-05-30 02:32:12 -07004283 rtc::CriticalSection crit_;
4284 } observer;
4285
eladalon05b07bb2017-08-24 07:40:16 -07004286 static constexpr int kFrameMaxWidth = 320;
4287 static constexpr int kFrameMaxHeight = 180;
4288 static constexpr int kFrameRate = 15;
eladalon413ee9a2017-08-22 04:02:52 -07004289
brandtr48d21a22017-05-30 02:32:12 -07004290 Call::Config config(event_log_.get());
brandtr48d21a22017-05-30 02:32:12 -07004291
eladalon413ee9a2017-08-22 04:02:52 -07004292 std::unique_ptr<test::PacketTransport> send_transport;
4293 std::unique_ptr<test::PacketTransport> receive_transport;
4294 std::unique_ptr<VideoEncoder> encoder;
brandtr48d21a22017-05-30 02:32:12 -07004295
eladalon413ee9a2017-08-22 04:02:52 -07004296 task_queue_.SendTask([&]() {
4297 CreateCalls(config, config);
brandtr48d21a22017-05-30 02:32:12 -07004298
eladalon413ee9a2017-08-22 04:02:52 -07004299 FakeNetworkPipe::Config lossy_delayed_link;
4300 lossy_delayed_link.loss_percent = 2;
4301 lossy_delayed_link.queue_delay_ms = 50;
brandtr48d21a22017-05-30 02:32:12 -07004302
eladalon413ee9a2017-08-22 04:02:52 -07004303 send_transport = rtc::MakeUnique<test::PacketTransport>(
4304 &task_queue_, sender_call_.get(), &observer,
4305 test::PacketTransport::kSender, payload_type_map_, lossy_delayed_link);
4306 send_transport->SetReceiver(receiver_call_->Receiver());
brandtr48d21a22017-05-30 02:32:12 -07004307
eladalon413ee9a2017-08-22 04:02:52 -07004308 FakeNetworkPipe::Config flawless_link;
4309 receive_transport = rtc::MakeUnique<test::PacketTransport>(
4310 &task_queue_, nullptr, &observer, test::PacketTransport::kReceiver,
4311 payload_type_map_, flawless_link);
4312 receive_transport->SetReceiver(sender_call_->Receiver());
brandtr48d21a22017-05-30 02:32:12 -07004313
eladalon413ee9a2017-08-22 04:02:52 -07004314 // For reduced flakyness, we use a real VP8 encoder together with NACK
4315 // and RTX.
4316 const int kNumVideoStreams = 1;
4317 const int kNumFlexfecStreams = 1;
4318 CreateSendConfig(kNumVideoStreams, 0, kNumFlexfecStreams,
4319 send_transport.get());
4320 encoder = rtc::WrapUnique(VP8Encoder::Create());
4321 video_send_config_.encoder_settings.encoder = encoder.get();
4322 video_send_config_.encoder_settings.payload_name = "VP8";
4323 video_send_config_.encoder_settings.payload_type = kVideoSendPayloadType;
4324 video_send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
4325 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
4326 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
brandtr48d21a22017-05-30 02:32:12 -07004327
eladalon413ee9a2017-08-22 04:02:52 -07004328 CreateMatchingReceiveConfigs(receive_transport.get());
4329 video_receive_configs_[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
4330 video_receive_configs_[0].rtp.rtx_ssrc = kSendRtxSsrcs[0];
nisse26e3abb2017-08-25 04:44:25 -07004331 video_receive_configs_[0]
4332 .rtp.rtx_associated_payload_types[kSendRtxPayloadType] =
4333 kVideoSendPayloadType;
brandtr48d21a22017-05-30 02:32:12 -07004334
eladalon413ee9a2017-08-22 04:02:52 -07004335 // The matching FlexFEC receive config is not created by
4336 // CreateMatchingReceiveConfigs since this is not a test::BaseTest.
4337 // Set up the receive config manually instead.
4338 FlexfecReceiveStream::Config flexfec_receive_config(
4339 receive_transport.get());
4340 flexfec_receive_config.payload_type =
4341 video_send_config_.rtp.flexfec.payload_type;
4342 flexfec_receive_config.remote_ssrc = video_send_config_.rtp.flexfec.ssrc;
4343 flexfec_receive_config.protected_media_ssrcs =
4344 video_send_config_.rtp.flexfec.protected_media_ssrcs;
4345 flexfec_receive_config.local_ssrc = kReceiverLocalVideoSsrc;
4346 flexfec_receive_config.transport_cc = true;
4347 flexfec_receive_config.rtp_header_extensions.emplace_back(
4348 RtpExtension::kTransportSequenceNumberUri,
4349 test::kTransportSequenceNumberExtensionId);
4350 flexfec_receive_configs_.push_back(flexfec_receive_config);
4351
4352 CreateFlexfecStreams();
4353 CreateVideoStreams();
4354
4355 // RTCP might be disabled if the network is "down".
4356 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
4357 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
4358
4359 CreateFrameGeneratorCapturer(kFrameRate, kFrameMaxWidth, kFrameMaxHeight);
4360
4361 Start();
4362 });
brandtr48d21a22017-05-30 02:32:12 -07004363
4364 // Initial test.
brandtr48d21a22017-05-30 02:32:12 -07004365 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for packets.";
4366
eladalon413ee9a2017-08-22 04:02:52 -07004367 task_queue_.SendTask([this, &observer]() {
4368 // Ensure monotonicity when the VideoSendStream is restarted.
4369 Stop();
4370 observer.ResetPacketCount();
4371 Start();
4372 });
4373
brandtr48d21a22017-05-30 02:32:12 -07004374 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for packets.";
4375
eladalon05b07bb2017-08-24 07:40:16 -07004376 task_queue_.SendTask([this, &observer]() {
eladalon413ee9a2017-08-22 04:02:52 -07004377 // Ensure monotonicity when the VideoSendStream is recreated.
4378 frame_generator_capturer_->Stop();
4379 sender_call_->DestroyVideoSendStream(video_send_stream_);
4380 observer.ResetPacketCount();
4381 video_send_stream_ = sender_call_->CreateVideoSendStream(
4382 video_send_config_.Copy(), video_encoder_config_.Copy());
4383 video_send_stream_->Start();
4384 CreateFrameGeneratorCapturer(kFrameRate, kFrameMaxWidth, kFrameMaxHeight);
4385 frame_generator_capturer_->Start();
4386 });
4387
brandtr48d21a22017-05-30 02:32:12 -07004388 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for packets.";
4389
4390 // Cleanup.
eladalon413ee9a2017-08-22 04:02:52 -07004391 task_queue_.SendTask([this, &send_transport, &receive_transport]() {
4392 Stop();
4393 DestroyStreams();
4394 send_transport.reset();
4395 receive_transport.reset();
4396 DestroyCalls();
4397 });
brandtr48d21a22017-05-30 02:32:12 -07004398}
4399
philipelccdfcca2017-10-23 12:42:17 +02004400TEST_P(EndToEndTest, RespectsNetworkState) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004401 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
4402 // down blocks until no more packets will be sent.
4403
4404 // Pacer will send from its packet list and then send required padding before
4405 // checking paused_ again. This should be enough for one round of pacing,
4406 // otherwise increase.
4407 static const int kNumAcceptedDowntimeRtp = 5;
4408 // A single RTCP may be in the pipeline.
4409 static const int kNumAcceptedDowntimeRtcp = 1;
4410 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
4411 public:
eladalon413ee9a2017-08-22 04:02:52 -07004412 explicit NetworkStateTest(
4413 test::SingleThreadedTaskQueueForTesting* task_queue)
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004414 : EndToEndTest(kDefaultTimeoutMs),
4415 FakeEncoder(Clock::GetRealTimeClock()),
eladalon413ee9a2017-08-22 04:02:52 -07004416 task_queue_(task_queue),
Peter Boström5811a392015-12-10 13:02:50 +01004417 encoded_frames_(false, false),
4418 packet_event_(false, false),
sprang867fb522015-08-03 04:38:41 -07004419 sender_call_(nullptr),
4420 receiver_call_(nullptr),
Jelena Marusiccd670222015-07-16 09:30:09 +02004421 sender_state_(kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004422 sender_rtp_(0),
stefan9e117c5e12017-08-16 08:16:25 -07004423 sender_padding_(0),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004424 sender_rtcp_(0),
4425 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004426 down_frames_(0) {}
4427
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004428 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02004429 rtc::CritScope lock(&test_crit_);
stefan9e117c5e12017-08-16 08:16:25 -07004430 RTPHeader header;
4431 EXPECT_TRUE(parser_->Parse(packet, length, &header));
4432 if (length == header.headerLength + header.paddingLength)
4433 ++sender_padding_;
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004434 ++sender_rtp_;
Peter Boström5811a392015-12-10 13:02:50 +01004435 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004436 return SEND_PACKET;
4437 }
4438
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004439 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02004440 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004441 ++sender_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01004442 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004443 return SEND_PACKET;
4444 }
4445
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004446 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004447 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
4448 return SEND_PACKET;
4449 }
4450
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004451 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02004452 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004453 ++receiver_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01004454 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004455 return SEND_PACKET;
4456 }
4457
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004458 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004459 sender_call_ = sender_call;
4460 receiver_call_ = receiver_call;
4461 }
4462
stefanff483612015-12-21 03:14:00 -08004463 void ModifyVideoConfigs(
4464 VideoSendStream::Config* send_config,
4465 std::vector<VideoReceiveStream::Config>* receive_configs,
4466 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004467 send_config->encoder_settings.encoder = this;
4468 }
4469
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004470 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01004471 EXPECT_TRUE(encoded_frames_.Wait(kDefaultTimeoutMs))
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004472 << "No frames received by the encoder.";
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004473
eladalon413ee9a2017-08-22 04:02:52 -07004474 task_queue_->SendTask([this]() {
4475 // Wait for packets from both sender/receiver.
4476 WaitForPacketsOrSilence(false, false);
skvlad7a43d252016-03-22 15:32:27 -07004477
eladalon413ee9a2017-08-22 04:02:52 -07004478 // Sender-side network down for audio; there should be no effect on
4479 // video
4480 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
4481 WaitForPacketsOrSilence(false, false);
skvlad7a43d252016-03-22 15:32:27 -07004482
eladalon413ee9a2017-08-22 04:02:52 -07004483 // Receiver-side network down for audio; no change expected
4484 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO,
4485 kNetworkDown);
4486 WaitForPacketsOrSilence(false, false);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004487
eladalon413ee9a2017-08-22 04:02:52 -07004488 // Sender-side network down.
4489 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
4490 {
4491 rtc::CritScope lock(&test_crit_);
4492 // After network goes down we shouldn't be encoding more frames.
4493 sender_state_ = kNetworkDown;
4494 }
4495 // Wait for receiver-packets and no sender packets.
4496 WaitForPacketsOrSilence(true, false);
skvlad7a43d252016-03-22 15:32:27 -07004497
eladalon413ee9a2017-08-22 04:02:52 -07004498 // Receiver-side network down.
4499 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO,
4500 kNetworkDown);
4501 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004502
eladalon413ee9a2017-08-22 04:02:52 -07004503 // Network up for audio for both sides; video is still not expected to
4504 // start
4505 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
4506 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
4507 WaitForPacketsOrSilence(true, true);
skvlad7a43d252016-03-22 15:32:27 -07004508
eladalon413ee9a2017-08-22 04:02:52 -07004509 // Network back up again for both.
4510 {
4511 rtc::CritScope lock(&test_crit_);
4512 // It's OK to encode frames again, as we're about to bring up the
4513 // network.
4514 sender_state_ = kNetworkUp;
4515 }
4516 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
4517 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
4518 WaitForPacketsOrSilence(false, false);
4519
4520 // TODO(skvlad): add tests to verify that the audio streams are stopped
4521 // when the network goes down for audio once the workaround in
4522 // paced_sender.cc is removed.
4523 });
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004524 }
4525
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07004526 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004527 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07004528 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004529 {
Peter Boströmf2f82832015-05-01 13:00:41 +02004530 rtc::CritScope lock(&test_crit_);
Jelena Marusiccd670222015-07-16 09:30:09 +02004531 if (sender_state_ == kNetworkDown) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004532 ++down_frames_;
4533 EXPECT_LE(down_frames_, 1)
4534 << "Encoding more than one frame while network is down.";
4535 if (down_frames_ > 1)
Peter Boström5811a392015-12-10 13:02:50 +01004536 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004537 } else {
Peter Boström5811a392015-12-10 13:02:50 +01004538 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004539 }
4540 }
4541 return test::FakeEncoder::Encode(
4542 input_image, codec_specific_info, frame_types);
4543 }
4544
4545 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004546 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
4547 int64_t initial_time_ms = clock_->TimeInMilliseconds();
4548 int initial_sender_rtp;
4549 int initial_sender_rtcp;
4550 int initial_receiver_rtcp;
4551 {
Peter Boströmf2f82832015-05-01 13:00:41 +02004552 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004553 initial_sender_rtp = sender_rtp_;
4554 initial_sender_rtcp = sender_rtcp_;
4555 initial_receiver_rtcp = receiver_rtcp_;
4556 }
4557 bool sender_done = false;
4558 bool receiver_done = false;
mflodmand1590b22015-12-09 07:07:59 -08004559 while (!sender_done || !receiver_done) {
Peter Boström5811a392015-12-10 13:02:50 +01004560 packet_event_.Wait(kSilenceTimeoutMs);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004561 int64_t time_now_ms = clock_->TimeInMilliseconds();
Peter Boströmf2f82832015-05-01 13:00:41 +02004562 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004563 if (sender_down) {
stefan9e117c5e12017-08-16 08:16:25 -07004564 ASSERT_LE(sender_rtp_ - initial_sender_rtp - sender_padding_,
4565 kNumAcceptedDowntimeRtp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004566 << "RTP sent during sender-side downtime.";
4567 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
4568 kNumAcceptedDowntimeRtcp)
4569 << "RTCP sent during sender-side downtime.";
4570 if (time_now_ms - initial_time_ms >=
4571 static_cast<int64_t>(kSilenceTimeoutMs)) {
4572 sender_done = true;
4573 }
4574 } else {
skvlad7a43d252016-03-22 15:32:27 -07004575 if (sender_rtp_ > initial_sender_rtp + kNumAcceptedDowntimeRtp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004576 sender_done = true;
4577 }
4578 if (receiver_down) {
4579 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
4580 kNumAcceptedDowntimeRtcp)
4581 << "RTCP sent during receiver-side downtime.";
4582 if (time_now_ms - initial_time_ms >=
4583 static_cast<int64_t>(kSilenceTimeoutMs)) {
4584 receiver_done = true;
4585 }
4586 } else {
skvlad7a43d252016-03-22 15:32:27 -07004587 if (receiver_rtcp_ > initial_receiver_rtcp + kNumAcceptedDowntimeRtcp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004588 receiver_done = true;
4589 }
4590 }
4591 }
4592
eladalon413ee9a2017-08-22 04:02:52 -07004593 test::SingleThreadedTaskQueueForTesting* const task_queue_;
Peter Boströmf2f82832015-05-01 13:00:41 +02004594 rtc::CriticalSection test_crit_;
Peter Boström5811a392015-12-10 13:02:50 +01004595 rtc::Event encoded_frames_;
4596 rtc::Event packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004597 Call* sender_call_;
4598 Call* receiver_call_;
danilchapa37de392017-09-09 04:17:22 -07004599 NetworkState sender_state_ RTC_GUARDED_BY(test_crit_);
4600 int sender_rtp_ RTC_GUARDED_BY(test_crit_);
4601 int sender_padding_ RTC_GUARDED_BY(test_crit_);
4602 int sender_rtcp_ RTC_GUARDED_BY(test_crit_);
4603 int receiver_rtcp_ RTC_GUARDED_BY(test_crit_);
4604 int down_frames_ RTC_GUARDED_BY(test_crit_);
eladalon413ee9a2017-08-22 04:02:52 -07004605 } test(&task_queue_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004606
stefane74eef12016-01-08 06:47:13 -08004607 RunBaseTest(&test);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004608}
4609
philipelccdfcca2017-10-23 12:42:17 +02004610TEST_P(EndToEndTest, CallReportsRttForSender) {
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004611 static const int kSendDelayMs = 30;
4612 static const int kReceiveDelayMs = 70;
solenberg4fbae2b2015-08-28 04:07:10 -07004613
eladalon413ee9a2017-08-22 04:02:52 -07004614 std::unique_ptr<test::DirectTransport> sender_transport;
4615 std::unique_ptr<test::DirectTransport> receiver_transport;
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004616
eladalon413ee9a2017-08-22 04:02:52 -07004617 task_queue_.SendTask([this, &sender_transport, &receiver_transport]() {
4618 FakeNetworkPipe::Config config;
4619 config.queue_delay_ms = kSendDelayMs;
4620 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
4621 sender_transport = rtc::MakeUnique<test::DirectTransport>(
4622 &task_queue_, config, sender_call_.get(), payload_type_map_);
4623 config.queue_delay_ms = kReceiveDelayMs;
4624 receiver_transport = rtc::MakeUnique<test::DirectTransport>(
4625 &task_queue_, config, receiver_call_.get(), payload_type_map_);
4626 sender_transport->SetReceiver(receiver_call_->Receiver());
4627 receiver_transport->SetReceiver(sender_call_->Receiver());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004628
eladalon413ee9a2017-08-22 04:02:52 -07004629 CreateSendConfig(1, 0, 0, sender_transport.get());
4630 CreateMatchingReceiveConfigs(receiver_transport.get());
4631
4632 CreateVideoStreams();
4633 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
4634 kDefaultHeight);
4635 Start();
4636 });
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004637
4638 int64_t start_time_ms = clock_->TimeInMilliseconds();
4639 while (true) {
4640 Call::Stats stats = sender_call_->GetStats();
4641 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
4642 clock_->TimeInMilliseconds())
4643 << "No RTT stats before timeout!";
4644 if (stats.rtt_ms != -1) {
Danil Chapovalov10e8f8e2016-09-07 15:05:29 +02004645 // To avoid failures caused by rounding or minor ntp clock adjustments,
4646 // relax expectation by 1ms.
4647 constexpr int kAllowedErrorMs = 1;
4648 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs - kAllowedErrorMs);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004649 break;
4650 }
4651 SleepMs(10);
4652 }
4653
eladalon413ee9a2017-08-22 04:02:52 -07004654 task_queue_.SendTask([this, &sender_transport, &receiver_transport]() {
4655 Stop();
4656 DestroyStreams();
4657 sender_transport.reset();
4658 receiver_transport.reset();
4659 DestroyCalls();
4660 });
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004661}
4662
skvlad7a43d252016-03-22 15:32:27 -07004663void EndToEndTest::VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004664 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -07004665 VideoEncoder* encoder,
4666 Transport* transport) {
eladalon413ee9a2017-08-22 04:02:52 -07004667 task_queue_.SendTask([this, network_to_bring_up, encoder, transport]() {
4668 CreateSenderCall(Call::Config(event_log_.get()));
4669 sender_call_->SignalChannelNetworkState(network_to_bring_up, kNetworkUp);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004670
eladalon413ee9a2017-08-22 04:02:52 -07004671 CreateSendConfig(1, 0, 0, transport);
4672 video_send_config_.encoder_settings.encoder = encoder;
4673 CreateVideoStreams();
4674 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
4675 kDefaultHeight);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004676
eladalon413ee9a2017-08-22 04:02:52 -07004677 Start();
4678 });
4679
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004680 SleepMs(kSilenceTimeoutMs);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004681
eladalon413ee9a2017-08-22 04:02:52 -07004682 task_queue_.SendTask([this]() {
4683 Stop();
4684 DestroyStreams();
4685 DestroyCalls();
4686 });
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004687}
4688
skvlad7a43d252016-03-22 15:32:27 -07004689void EndToEndTest::VerifyNewVideoReceiveStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004690 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -07004691 Transport* transport) {
eladalon413ee9a2017-08-22 04:02:52 -07004692 std::unique_ptr<test::DirectTransport> sender_transport;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004693
eladalon413ee9a2017-08-22 04:02:52 -07004694 task_queue_.SendTask([this, &sender_transport, network_to_bring_up,
4695 transport]() {
4696 Call::Config config(event_log_.get());
4697 CreateCalls(config, config);
4698 receiver_call_->SignalChannelNetworkState(network_to_bring_up, kNetworkUp);
4699 sender_transport = rtc::MakeUnique<test::DirectTransport>(
4700 &task_queue_, sender_call_.get(), payload_type_map_);
4701 sender_transport->SetReceiver(receiver_call_->Receiver());
4702 CreateSendConfig(1, 0, 0, sender_transport.get());
4703 CreateMatchingReceiveConfigs(transport);
4704 CreateVideoStreams();
4705 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
4706 kDefaultHeight);
4707 Start();
4708 });
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004709
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004710 SleepMs(kSilenceTimeoutMs);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004711
eladalon413ee9a2017-08-22 04:02:52 -07004712 task_queue_.SendTask([this, &sender_transport]() {
4713 Stop();
4714 DestroyStreams();
4715 sender_transport.reset();
4716 DestroyCalls();
4717 });
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004718}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00004719
philipelccdfcca2017-10-23 12:42:17 +02004720TEST_P(EndToEndTest, NewVideoSendStreamsRespectVideoNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004721 class UnusedEncoder : public test::FakeEncoder {
4722 public:
4723 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
perkjfea93092016-05-14 00:58:48 -07004724
4725 int32_t InitEncode(const VideoCodec* config,
4726 int32_t number_of_cores,
4727 size_t max_payload_size) override {
4728 EXPECT_GT(config->startBitrate, 0u);
4729 return 0;
4730 }
skvlad7a43d252016-03-22 15:32:27 -07004731 int32_t Encode(const VideoFrame& input_image,
4732 const CodecSpecificInfo* codec_specific_info,
4733 const std::vector<FrameType>* frame_types) override {
4734 ADD_FAILURE() << "Unexpected frame encode.";
4735 return test::FakeEncoder::Encode(input_image, codec_specific_info,
4736 frame_types);
4737 }
4738 };
4739
4740 UnusedEncoder unused_encoder;
4741 UnusedTransport unused_transport;
4742 VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004743 MediaType::AUDIO, &unused_encoder, &unused_transport);
skvlad7a43d252016-03-22 15:32:27 -07004744}
4745
philipelccdfcca2017-10-23 12:42:17 +02004746TEST_P(EndToEndTest, NewVideoSendStreamsIgnoreAudioNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004747 class RequiredEncoder : public test::FakeEncoder {
4748 public:
4749 RequiredEncoder()
4750 : FakeEncoder(Clock::GetRealTimeClock()), encoded_frame_(false) {}
4751 ~RequiredEncoder() {
4752 if (!encoded_frame_) {
4753 ADD_FAILURE() << "Didn't encode an expected frame";
4754 }
4755 }
4756 int32_t Encode(const VideoFrame& input_image,
4757 const CodecSpecificInfo* codec_specific_info,
4758 const std::vector<FrameType>* frame_types) override {
4759 encoded_frame_ = true;
4760 return test::FakeEncoder::Encode(input_image, codec_specific_info,
4761 frame_types);
4762 }
4763
4764 private:
4765 bool encoded_frame_;
4766 };
4767
4768 RequiredTransport required_transport(true /*rtp*/, false /*rtcp*/);
4769 RequiredEncoder required_encoder;
4770 VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004771 MediaType::VIDEO, &required_encoder, &required_transport);
skvlad7a43d252016-03-22 15:32:27 -07004772}
4773
philipelccdfcca2017-10-23 12:42:17 +02004774TEST_P(EndToEndTest, NewVideoReceiveStreamsRespectVideoNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004775 UnusedTransport transport;
Sergey Ulanove2b15012016-11-22 16:08:30 -08004776 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::AUDIO, &transport);
skvlad7a43d252016-03-22 15:32:27 -07004777}
4778
philipelccdfcca2017-10-23 12:42:17 +02004779TEST_P(EndToEndTest, NewVideoReceiveStreamsIgnoreAudioNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004780 RequiredTransport transport(false /*rtp*/, true /*rtcp*/);
Sergey Ulanove2b15012016-11-22 16:08:30 -08004781 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::VIDEO, &transport);
skvlad7a43d252016-03-22 15:32:27 -07004782}
4783
Peter Boströmd7da1202015-06-05 14:09:38 +02004784void VerifyEmptyNackConfig(const NackConfig& config) {
4785 EXPECT_EQ(0, config.rtp_history_ms)
4786 << "Enabling NACK requires rtcp-fb: nack negotiation.";
4787}
4788
brandtrb5f2c3f2016-10-04 23:28:39 -07004789void VerifyEmptyUlpfecConfig(const UlpfecConfig& config) {
Peter Boströmd7da1202015-06-05 14:09:38 +02004790 EXPECT_EQ(-1, config.ulpfec_payload_type)
brandtr535830e2016-10-31 03:45:58 -07004791 << "Enabling ULPFEC requires rtpmap: ulpfec negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02004792 EXPECT_EQ(-1, config.red_payload_type)
brandtr535830e2016-10-31 03:45:58 -07004793 << "Enabling ULPFEC requires rtpmap: red negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02004794 EXPECT_EQ(-1, config.red_rtx_payload_type)
brandtr535830e2016-10-31 03:45:58 -07004795 << "Enabling RTX in ULPFEC requires rtpmap: rtx negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02004796}
4797
brandtr3d200bd2017-01-16 06:59:19 -08004798void VerifyEmptyFlexfecConfig(
4799 const VideoSendStream::Config::Rtp::Flexfec& config) {
4800 EXPECT_EQ(-1, config.payload_type)
brandtr1e3dfbf2016-11-16 22:45:19 -08004801 << "Enabling FlexFEC requires rtpmap: flexfec negotiation.";
brandtr3d200bd2017-01-16 06:59:19 -08004802 EXPECT_EQ(0U, config.ssrc)
brandtr1cfbd602016-12-08 04:17:53 -08004803 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
brandtr1e3dfbf2016-11-16 22:45:19 -08004804 EXPECT_TRUE(config.protected_media_ssrcs.empty())
4805 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
4806}
4807
philipelccdfcca2017-10-23 12:42:17 +02004808TEST_P(EndToEndTest, VerifyDefaultSendConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07004809 VideoSendStream::Config default_send_config(nullptr);
Peter Boströmd7da1202015-06-05 14:09:38 +02004810 EXPECT_EQ(0, default_send_config.rtp.nack.rtp_history_ms)
4811 << "Enabling NACK require rtcp-fb: nack negotiation.";
4812 EXPECT_TRUE(default_send_config.rtp.rtx.ssrcs.empty())
4813 << "Enabling RTX requires rtpmap: rtx negotiation.";
4814 EXPECT_TRUE(default_send_config.rtp.extensions.empty())
4815 << "Enabling RTP extensions require negotiation.";
4816
4817 VerifyEmptyNackConfig(default_send_config.rtp.nack);
brandtrb5f2c3f2016-10-04 23:28:39 -07004818 VerifyEmptyUlpfecConfig(default_send_config.rtp.ulpfec);
brandtr1e3dfbf2016-11-16 22:45:19 -08004819 VerifyEmptyFlexfecConfig(default_send_config.rtp.flexfec);
Peter Boströmd7da1202015-06-05 14:09:38 +02004820}
4821
philipelccdfcca2017-10-23 12:42:17 +02004822TEST_P(EndToEndTest, VerifyDefaultVideoReceiveConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07004823 VideoReceiveStream::Config default_receive_config(nullptr);
pbosda903ea2015-10-02 02:36:56 -07004824 EXPECT_EQ(RtcpMode::kCompound, default_receive_config.rtp.rtcp_mode)
Peter Boströmd7da1202015-06-05 14:09:38 +02004825 << "Reduced-size RTCP require rtcp-rsize to be negotiated.";
4826 EXPECT_FALSE(default_receive_config.rtp.remb)
4827 << "REMB require rtcp-fb: goog-remb to be negotiated.";
4828 EXPECT_FALSE(
4829 default_receive_config.rtp.rtcp_xr.receiver_reference_time_report)
4830 << "RTCP XR settings require rtcp-xr to be negotiated.";
brandtr14742122017-01-27 04:53:07 -08004831 EXPECT_EQ(0U, default_receive_config.rtp.rtx_ssrc)
4832 << "Enabling RTX requires ssrc-group: FID negotiation";
nisse26e3abb2017-08-25 04:44:25 -07004833 EXPECT_TRUE(default_receive_config.rtp.rtx_associated_payload_types.empty())
Peter Boströmd7da1202015-06-05 14:09:38 +02004834 << "Enabling RTX requires rtpmap: rtx negotiation.";
4835 EXPECT_TRUE(default_receive_config.rtp.extensions.empty())
4836 << "Enabling RTP extensions require negotiation.";
4837
4838 VerifyEmptyNackConfig(default_receive_config.rtp.nack);
nisse3b3622f2017-09-26 02:49:21 -07004839 EXPECT_EQ(-1, default_receive_config.rtp.ulpfec_payload_type)
4840 << "Enabling ULPFEC requires rtpmap: ulpfec negotiation.";
4841 EXPECT_EQ(-1, default_receive_config.rtp.red_payload_type)
4842 << "Enabling ULPFEC requires rtpmap: red negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02004843}
4844
philipelccdfcca2017-10-23 12:42:17 +02004845TEST_P(EndToEndTest, VerifyDefaultFlexfecReceiveConfigParameters) {
brandtr8313a6f2017-01-13 07:41:19 -08004846 test::NullTransport rtcp_send_transport;
4847 FlexfecReceiveStream::Config default_receive_config(&rtcp_send_transport);
brandtr1cfbd602016-12-08 04:17:53 -08004848 EXPECT_EQ(-1, default_receive_config.payload_type)
4849 << "Enabling FlexFEC requires rtpmap: flexfec negotiation.";
4850 EXPECT_EQ(0U, default_receive_config.remote_ssrc)
4851 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
4852 EXPECT_TRUE(default_receive_config.protected_media_ssrcs.empty())
4853 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
brandtr1e3dfbf2016-11-16 22:45:19 -08004854}
4855
philipelccdfcca2017-10-23 12:42:17 +02004856TEST_P(EndToEndTest, TransportSeqNumOnAudioAndVideo) {
danilchap4336d732017-03-03 06:21:54 -08004857 static constexpr int kExtensionId = 8;
4858 static constexpr size_t kMinPacketsToWaitFor = 50;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004859 class TransportSequenceNumberTest : public test::EndToEndTest {
4860 public:
4861 TransportSequenceNumberTest()
4862 : EndToEndTest(kDefaultTimeoutMs),
4863 video_observed_(false),
4864 audio_observed_(false) {
4865 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
4866 kExtensionId);
4867 }
4868
4869 size_t GetNumVideoStreams() const override { return 1; }
4870 size_t GetNumAudioStreams() const override { return 1; }
4871
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004872 void ModifyAudioConfigs(
4873 AudioSendStream::Config* send_config,
4874 std::vector<AudioReceiveStream::Config>* receive_configs) override {
4875 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07004876 send_config->rtp.extensions.push_back(RtpExtension(
4877 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004878 (*receive_configs)[0].rtp.extensions.clear();
4879 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
4880 }
4881
4882 Action OnSendRtp(const uint8_t* packet, size_t length) override {
4883 RTPHeader header;
4884 EXPECT_TRUE(parser_->Parse(packet, length, &header));
4885 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
4886 // Unwrap packet id and verify uniqueness.
4887 int64_t packet_id =
4888 unwrapper_.Unwrap(header.extension.transportSequenceNumber);
4889 EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
4890
4891 if (header.ssrc == kVideoSendSsrcs[0])
4892 video_observed_ = true;
4893 if (header.ssrc == kAudioSendSsrc)
4894 audio_observed_ = true;
4895 if (audio_observed_ && video_observed_ &&
danilchap4336d732017-03-03 06:21:54 -08004896 received_packet_ids_.size() >= kMinPacketsToWaitFor) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004897 size_t packet_id_range =
4898 *received_packet_ids_.rbegin() - *received_packet_ids_.begin() + 1;
4899 EXPECT_EQ(received_packet_ids_.size(), packet_id_range);
4900 observation_complete_.Set();
4901 }
4902 return SEND_PACKET;
4903 }
4904
4905 void PerformTest() override {
4906 EXPECT_TRUE(Wait()) << "Timed out while waiting for audio and video "
4907 "packets with transport sequence number.";
4908 }
4909
danilchap4336d732017-03-03 06:21:54 -08004910 void ExpectSuccessful() {
4911 EXPECT_TRUE(video_observed_);
4912 EXPECT_TRUE(audio_observed_);
4913 EXPECT_GE(received_packet_ids_.size(), kMinPacketsToWaitFor);
4914 }
4915
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004916 private:
4917 bool video_observed_;
4918 bool audio_observed_;
4919 SequenceNumberUnwrapper unwrapper_;
4920 std::set<int64_t> received_packet_ids_;
4921 } test;
4922
stefane74eef12016-01-08 06:47:13 -08004923 RunBaseTest(&test);
danilchap4336d732017-03-03 06:21:54 -08004924 // Double check conditions for successful test to produce better error
4925 // message when the test fail.
4926 test.ExpectSuccessful();
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004927}
palmkviste75f2042016-09-28 06:19:48 -07004928
4929class EndToEndLogTest : public EndToEndTest {
4930 void SetUp() { paths_.clear(); }
4931 void TearDown() {
4932 for (const auto& path : paths_) {
4933 rtc::RemoveFile(path);
4934 }
4935 }
4936
4937 public:
4938 int AddFile() {
4939 paths_.push_back(test::TempFilename(test::OutputPath(), "test_file"));
4940 return static_cast<int>(paths_.size()) - 1;
4941 }
4942
4943 rtc::PlatformFile OpenFile(int idx) {
4944 return rtc::OpenPlatformFile(paths_[idx]);
4945 }
4946
4947 void LogSend(bool open) {
4948 if (open) {
4949 video_send_stream_->EnableEncodedFrameRecording(
4950 std::vector<rtc::PlatformFile>(1, OpenFile(AddFile())), 0);
4951 } else {
4952 video_send_stream_->DisableEncodedFrameRecording();
4953 }
4954 }
4955 void LogReceive(bool open) {
4956 if (open) {
4957 video_receive_streams_[0]->EnableEncodedFrameRecording(
4958 OpenFile(AddFile()), 0);
4959 } else {
4960 video_receive_streams_[0]->DisableEncodedFrameRecording();
4961 }
4962 }
4963
4964 std::vector<std::string> paths_;
4965};
4966
philipelccdfcca2017-10-23 12:42:17 +02004967TEST_P(EndToEndLogTest, LogsEncodedFramesWhenRequested) {
palmkviste75f2042016-09-28 06:19:48 -07004968 static const int kNumFramesToRecord = 10;
4969 class LogEncodingObserver : public test::EndToEndTest,
4970 public EncodedFrameObserver {
4971 public:
4972 explicit LogEncodingObserver(EndToEndLogTest* fixture)
4973 : EndToEndTest(kDefaultTimeoutMs),
4974 fixture_(fixture),
4975 recorded_frames_(0) {}
4976
4977 void PerformTest() override {
4978 fixture_->LogSend(true);
4979 fixture_->LogReceive(true);
4980 ASSERT_TRUE(Wait()) << "Timed out while waiting for frame logging.";
4981 }
4982
4983 void ModifyVideoConfigs(
4984 VideoSendStream::Config* send_config,
4985 std::vector<VideoReceiveStream::Config>* receive_configs,
4986 VideoEncoderConfig* encoder_config) override {
magjed509e4fe2016-11-18 01:34:11 -08004987 encoder_.reset(VP8Encoder::Create());
palmkviste75f2042016-09-28 06:19:48 -07004988 decoder_.reset(VP8Decoder::Create());
4989
4990 send_config->post_encode_callback = this;
4991 send_config->encoder_settings.payload_name = "VP8";
4992 send_config->encoder_settings.encoder = encoder_.get();
4993
4994 (*receive_configs)[0].decoders.resize(1);
4995 (*receive_configs)[0].decoders[0].payload_type =
4996 send_config->encoder_settings.payload_type;
4997 (*receive_configs)[0].decoders[0].payload_name =
4998 send_config->encoder_settings.payload_name;
4999 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
5000 }
5001
5002 void EncodedFrameCallback(const EncodedFrame& encoded_frame) override {
5003 rtc::CritScope lock(&crit_);
5004 if (recorded_frames_++ > kNumFramesToRecord) {
5005 fixture_->LogSend(false);
5006 fixture_->LogReceive(false);
5007 rtc::File send_file(fixture_->OpenFile(0));
5008 rtc::File receive_file(fixture_->OpenFile(1));
5009 uint8_t out[100];
5010 // If logging has worked correctly neither file should be empty, i.e.
5011 // we should be able to read something from them.
5012 EXPECT_LT(0u, send_file.Read(out, 100));
5013 EXPECT_LT(0u, receive_file.Read(out, 100));
5014 observation_complete_.Set();
5015 }
5016 }
5017
5018 private:
5019 EndToEndLogTest* const fixture_;
5020 std::unique_ptr<VideoEncoder> encoder_;
5021 std::unique_ptr<VideoDecoder> decoder_;
5022 rtc::CriticalSection crit_;
danilchapa37de392017-09-09 04:17:22 -07005023 int recorded_frames_ RTC_GUARDED_BY(crit_);
palmkviste75f2042016-09-28 06:19:48 -07005024 } test(this);
5025
5026 RunBaseTest(&test);
5027}
5028
philipelccdfcca2017-10-23 12:42:17 +02005029INSTANTIATE_TEST_CASE_P(RoundRobin,
5030 EndToEndTest,
5031 ::testing::Values("WebRTC-RoundRobinPacing/Disabled/",
5032 "WebRTC-RoundRobinPacing/Enabled/"));
5033
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00005034} // namespace webrtc