blob: 96996ba932ff66211bbec7b96316a8aec57f55ae [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)
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200414class EndToEndTestH264 : public EndToEndTest {};
415
416const auto h264_field_trial_combinations = ::testing::Values(
417 "WebRTC-SpsPpsIdrIsH264Keyframe/Disabled/WebRTC-RoundRobinPacing/Disabled/",
418 "WebRTC-SpsPpsIdrIsH264Keyframe/Enabled/WebRTC-RoundRobinPacing/Disabled/",
419 "WebRTC-SpsPpsIdrIsH264Keyframe/Disabled/WebRTC-RoundRobinPacing/Enabled/",
420 "WebRTC-SpsPpsIdrIsH264Keyframe/Enabled/WebRTC-RoundRobinPacing/Enabled/");
421INSTANTIATE_TEST_CASE_P(SpsPpsIdrIsKeyframe,
422 EndToEndTestH264,
423 h264_field_trial_combinations);
424
425TEST_P(EndToEndTestH264, SendsAndReceivesH264) {
magjedceecea42016-11-28 07:20:21 -0800426 CodecObserver test(500, kVideoRotation_0, "H264",
427 H264Encoder::Create(cricket::VideoCodec("H264")),
Perba7dc722016-04-19 15:01:23 +0200428 H264Decoder::Create());
429 RunBaseTest(&test);
430}
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000431
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200432TEST_P(EndToEndTestH264, SendsAndReceivesH264VideoRotation90) {
magjedceecea42016-11-28 07:20:21 -0800433 CodecObserver test(5, kVideoRotation_90, "H264",
434 H264Encoder::Create(cricket::VideoCodec("H264")),
Perba7dc722016-04-19 15:01:23 +0200435 H264Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800436 RunBaseTest(&test);
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000437}
hta9aa96882016-12-06 05:36:03 -0800438
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200439TEST_P(EndToEndTestH264, SendsAndReceivesH264PacketizationMode0) {
hta9aa96882016-12-06 05:36:03 -0800440 cricket::VideoCodec codec = cricket::VideoCodec("H264");
441 codec.SetParam(cricket::kH264FmtpPacketizationMode, "0");
442 CodecObserver test(500, kVideoRotation_0, "H264", H264Encoder::Create(codec),
443 H264Decoder::Create());
444 RunBaseTest(&test);
445}
446
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200447TEST_P(EndToEndTestH264, SendsAndReceivesH264PacketizationMode1) {
hta9aa96882016-12-06 05:36:03 -0800448 cricket::VideoCodec codec = cricket::VideoCodec("H264");
449 codec.SetParam(cricket::kH264FmtpPacketizationMode, "1");
450 CodecObserver test(500, kVideoRotation_0, "H264", H264Encoder::Create(codec),
451 H264Decoder::Create());
452 RunBaseTest(&test);
453}
brandtr445fb8f2016-11-14 04:11:23 -0800454#endif // defined(WEBRTC_USE_H264)
hbosbab934b2016-01-27 01:36:03 -0800455
philipelccdfcca2017-10-23 12:42:17 +0200456TEST_P(EndToEndTest, ReceiverUsesLocalSsrc) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000457 class SyncRtcpObserver : public test::EndToEndTest {
458 public:
459 SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {}
460
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000461 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
danilchap3dc929e2016-11-02 08:21:59 -0700462 test::RtcpPacketParser parser;
463 EXPECT_TRUE(parser.Parse(packet, length));
464 EXPECT_EQ(kReceiverLocalVideoSsrc, parser.sender_ssrc());
Peter Boström5811a392015-12-10 13:02:50 +0100465 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000466
467 return SEND_PACKET;
468 }
469
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000470 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100471 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000472 << "Timed out while waiting for a receiver RTCP packet to be sent.";
473 }
474 } test;
475
stefane74eef12016-01-08 06:47:13 -0800476 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000477}
478
philipelccdfcca2017-10-23 12:42:17 +0200479TEST_P(EndToEndTest, ReceivesAndRetransmitsNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000480 static const int kNumberOfNacksToObserve = 2;
481 static const int kLossBurstSize = 2;
482 static const int kPacketsBetweenLossBursts = 9;
483 class NackObserver : public test::EndToEndTest {
484 public:
485 NackObserver()
486 : EndToEndTest(kLongTimeoutMs),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000487 sent_rtp_packets_(0),
488 packets_left_to_drop_(0),
489 nacks_left_(kNumberOfNacksToObserve) {}
490
491 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000492 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700493 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000494 RTPHeader header;
Peter Boström03671cb2015-12-07 15:22:24 +0100495 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000496
497 // Never drop retransmitted packets.
498 if (dropped_packets_.find(header.sequenceNumber) !=
499 dropped_packets_.end()) {
500 retransmitted_packets_.insert(header.sequenceNumber);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000501 return SEND_PACKET;
502 }
503
philipel8054c7e2017-01-10 05:19:19 -0800504 if (nacks_left_ <= 0 &&
505 retransmitted_packets_.size() == dropped_packets_.size()) {
506 observation_complete_.Set();
507 }
508
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000509 ++sent_rtp_packets_;
510
511 // Enough NACKs received, stop dropping packets.
Stefan Holmer586b19b2015-09-18 11:14:31 +0200512 if (nacks_left_ <= 0)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000513 return SEND_PACKET;
514
515 // Check if it's time for a new loss burst.
516 if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
517 packets_left_to_drop_ = kLossBurstSize;
518
Stefan Holmer01b48882015-05-05 10:21:24 +0200519 // Never drop padding packets as those won't be retransmitted.
520 if (packets_left_to_drop_ > 0 && header.paddingLength == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000521 --packets_left_to_drop_;
522 dropped_packets_.insert(header.sequenceNumber);
523 return DROP_PACKET;
524 }
525
526 return SEND_PACKET;
527 }
528
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000529 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700530 rtc::CritScope lock(&crit_);
danilchap3dc929e2016-11-02 08:21:59 -0700531 test::RtcpPacketParser parser;
532 EXPECT_TRUE(parser.Parse(packet, length));
533 nacks_left_ -= parser.nack()->num_packets();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000534 return SEND_PACKET;
535 }
536
stefanff483612015-12-21 03:14:00 -0800537 void ModifyVideoConfigs(
538 VideoSendStream::Config* send_config,
539 std::vector<VideoReceiveStream::Config>* receive_configs,
540 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000541 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000542 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000543 }
544
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000545 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100546 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000547 << "Timed out waiting for packets to be NACKed, retransmitted and "
548 "rendered.";
549 }
550
stefanf116bd02015-10-27 08:29:42 -0700551 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000552 std::set<uint16_t> dropped_packets_;
553 std::set<uint16_t> retransmitted_packets_;
554 uint64_t sent_rtp_packets_;
555 int packets_left_to_drop_;
danilchapa37de392017-09-09 04:17:22 -0700556 int nacks_left_ RTC_GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000557 } test;
558
stefane74eef12016-01-08 06:47:13 -0800559 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000560}
561
philipelccdfcca2017-10-23 12:42:17 +0200562TEST_P(EndToEndTest, ReceivesNackAndRetransmitsAudio) {
Erik Språng737336d2016-07-29 12:59:36 +0200563 class NackObserver : public test::EndToEndTest {
564 public:
565 NackObserver()
566 : EndToEndTest(kLongTimeoutMs),
567 local_ssrc_(0),
568 remote_ssrc_(0),
569 receive_transport_(nullptr) {}
570
571 private:
572 size_t GetNumVideoStreams() const override { return 0; }
573 size_t GetNumAudioStreams() const override { return 1; }
574
eladalon413ee9a2017-08-22 04:02:52 -0700575 test::PacketTransport* CreateReceiveTransport(
576 test::SingleThreadedTaskQueueForTesting* task_queue) override {
Erik Språng737336d2016-07-29 12:59:36 +0200577 test::PacketTransport* receive_transport = new test::PacketTransport(
eladalon413ee9a2017-08-22 04:02:52 -0700578 task_queue, nullptr, this, test::PacketTransport::kReceiver,
579 payload_type_map_, FakeNetworkPipe::Config());
Erik Språng737336d2016-07-29 12:59:36 +0200580 receive_transport_ = receive_transport;
581 return receive_transport;
582 }
583
584 Action OnSendRtp(const uint8_t* packet, size_t length) override {
585 RTPHeader header;
586 EXPECT_TRUE(parser_->Parse(packet, length, &header));
587
588 if (!sequence_number_to_retransmit_) {
589 sequence_number_to_retransmit_ =
590 rtc::Optional<uint16_t>(header.sequenceNumber);
591
592 // Don't ask for retransmission straight away, may be deduped in pacer.
593 } else if (header.sequenceNumber == *sequence_number_to_retransmit_) {
594 observation_complete_.Set();
595 } else {
596 // Send a NACK as often as necessary until retransmission is received.
597 rtcp::Nack nack;
danilchap822a16f2016-09-27 09:27:47 -0700598 nack.SetSenderSsrc(local_ssrc_);
599 nack.SetMediaSsrc(remote_ssrc_);
Erik Språng737336d2016-07-29 12:59:36 +0200600 uint16_t nack_list[] = {*sequence_number_to_retransmit_};
danilchap822a16f2016-09-27 09:27:47 -0700601 nack.SetPacketIds(nack_list, 1);
Erik Språng737336d2016-07-29 12:59:36 +0200602 rtc::Buffer buffer = nack.Build();
603
604 EXPECT_TRUE(receive_transport_->SendRtcp(buffer.data(), buffer.size()));
605 }
606
607 return SEND_PACKET;
608 }
609
610 void ModifyAudioConfigs(
611 AudioSendStream::Config* send_config,
612 std::vector<AudioReceiveStream::Config>* receive_configs) override {
613 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
614 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
615 local_ssrc_ = (*receive_configs)[0].rtp.local_ssrc;
616 remote_ssrc_ = (*receive_configs)[0].rtp.remote_ssrc;
617 }
618
619 void PerformTest() override {
620 EXPECT_TRUE(Wait())
621 << "Timed out waiting for packets to be NACKed, retransmitted and "
622 "rendered.";
623 }
624
625 uint32_t local_ssrc_;
626 uint32_t remote_ssrc_;
627 Transport* receive_transport_;
628 rtc::Optional<uint16_t> sequence_number_to_retransmit_;
629 } test;
630
631 RunBaseTest(&test);
632}
633
philipelccdfcca2017-10-23 12:42:17 +0200634TEST_P(EndToEndTest, ReceivesUlpfec) {
brandtr535830e2016-10-31 03:45:58 -0700635 class UlpfecRenderObserver : public test::EndToEndTest,
636 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000637 public:
brandtr535830e2016-10-31 03:45:58 -0700638 UlpfecRenderObserver()
brandtr1134b7b2017-02-06 06:35:47 -0800639 : EndToEndTest(kDefaultTimeoutMs),
brandtrc55f27a2017-03-20 06:32:59 -0700640 encoder_(VP8Encoder::Create()),
brandtr1134b7b2017-02-06 06:35:47 -0800641 random_(0xcafef00d1),
642 num_packets_sent_(0) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000643
644 private:
stefanf116bd02015-10-27 08:29:42 -0700645 Action OnSendRtp(const uint8_t* packet, size_t length) override {
646 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000647 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000648 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000649
brandtrc55f27a2017-03-20 06:32:59 -0700650 EXPECT_TRUE(header.payloadType == kVideoSendPayloadType ||
brandtr1134b7b2017-02-06 06:35:47 -0800651 header.payloadType == kRedPayloadType)
652 << "Unknown payload type received.";
653 EXPECT_EQ(kVideoSendSsrcs[0], header.ssrc) << "Unknown SSRC received.";
654
655 // Parse RED header.
Stefan Holmer01b48882015-05-05 10:21:24 +0200656 int encapsulated_payload_type = -1;
657 if (header.payloadType == kRedPayloadType) {
658 encapsulated_payload_type =
659 static_cast<int>(packet[header.headerLength]);
brandtr1134b7b2017-02-06 06:35:47 -0800660
brandtrc55f27a2017-03-20 06:32:59 -0700661 EXPECT_TRUE(encapsulated_payload_type == kVideoSendPayloadType ||
brandtr1134b7b2017-02-06 06:35:47 -0800662 encapsulated_payload_type == kUlpfecPayloadType)
663 << "Unknown encapsulated payload type received.";
Stefan Holmer01b48882015-05-05 10:21:24 +0200664 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000665
brandtrc55f27a2017-03-20 06:32:59 -0700666 // To minimize test flakiness, always let ULPFEC packets through.
brandtr1134b7b2017-02-06 06:35:47 -0800667 if (encapsulated_payload_type == kUlpfecPayloadType) {
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000668 return SEND_PACKET;
669 }
670
brandtr1134b7b2017-02-06 06:35:47 -0800671 // Simulate 5% video packet loss after rampup period. Record the
672 // corresponding timestamps that were dropped.
673 if (num_packets_sent_++ > 100 && random_.Rand(1, 100) <= 5) {
brandtrc55f27a2017-03-20 06:32:59 -0700674 if (encapsulated_payload_type == kVideoSendPayloadType) {
brandtr1134b7b2017-02-06 06:35:47 -0800675 dropped_sequence_numbers_.insert(header.sequenceNumber);
676 dropped_timestamps_.insert(header.timestamp);
677 }
brandtr1134b7b2017-02-06 06:35:47 -0800678 return DROP_PACKET;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000679 }
680
681 return SEND_PACKET;
682 }
683
nisseeb83a1a2016-03-21 01:27:56 -0700684 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200685 rtc::CritScope lock(&crit_);
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000686 // Rendering frame with timestamp of packet that was dropped -> FEC
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000687 // protection worked.
brandtr1134b7b2017-02-06 06:35:47 -0800688 auto it = dropped_timestamps_.find(video_frame.timestamp());
689 if (it != dropped_timestamps_.end()) {
Peter Boström5811a392015-12-10 13:02:50 +0100690 observation_complete_.Set();
brandtr1134b7b2017-02-06 06:35:47 -0800691 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000692 }
693
stefanff483612015-12-21 03:14:00 -0800694 void ModifyVideoConfigs(
695 VideoSendStream::Config* send_config,
696 std::vector<VideoReceiveStream::Config>* receive_configs,
697 VideoEncoderConfig* encoder_config) override {
brandtrc55f27a2017-03-20 06:32:59 -0700698 // Use VP8 instead of FAKE, since the latter does not have PictureID
699 // in the packetization headers.
700 send_config->encoder_settings.encoder = encoder_.get();
701 send_config->encoder_settings.payload_name = "VP8";
702 send_config->encoder_settings.payload_type = kVideoSendPayloadType;
703 VideoReceiveStream::Decoder decoder =
704 test::CreateMatchingDecoder(send_config->encoder_settings);
705 decoder_.reset(decoder.decoder);
706 (*receive_configs)[0].decoders.clear();
707 (*receive_configs)[0].decoders.push_back(decoder);
708
709 // Enable ULPFEC over RED.
brandtrb5f2c3f2016-10-04 23:28:39 -0700710 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
711 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
nisse3b3622f2017-09-26 02:49:21 -0700712 (*receive_configs)[0].rtp.red_payload_type = kRedPayloadType;
713 (*receive_configs)[0].rtp.ulpfec_payload_type = kUlpfecPayloadType;
brandtrc55f27a2017-03-20 06:32:59 -0700714
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000715 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000716 }
717
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000718 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100719 EXPECT_TRUE(Wait())
brandtr1e3dfbf2016-11-16 22:45:19 -0800720 << "Timed out waiting for dropped frames to be rendered.";
721 }
722
723 rtc::CriticalSection crit_;
brandtrc55f27a2017-03-20 06:32:59 -0700724 std::unique_ptr<VideoEncoder> encoder_;
725 std::unique_ptr<VideoDecoder> decoder_;
danilchapa37de392017-09-09 04:17:22 -0700726 std::set<uint32_t> dropped_sequence_numbers_ RTC_GUARDED_BY(crit_);
brandtr1134b7b2017-02-06 06:35:47 -0800727 // Several packets can have the same timestamp.
danilchapa37de392017-09-09 04:17:22 -0700728 std::multiset<uint32_t> dropped_timestamps_ RTC_GUARDED_BY(crit_);
brandtr1134b7b2017-02-06 06:35:47 -0800729 Random random_;
danilchapa37de392017-09-09 04:17:22 -0700730 int num_packets_sent_ RTC_GUARDED_BY(crit_);
brandtr1e3dfbf2016-11-16 22:45:19 -0800731 } test;
732
733 RunBaseTest(&test);
734}
735
brandtrfa5a3682017-01-17 01:33:54 -0800736class FlexfecRenderObserver : public test::EndToEndTest,
737 public rtc::VideoSinkInterface<VideoFrame> {
738 public:
739 static constexpr uint32_t kVideoLocalSsrc = 123;
740 static constexpr uint32_t kFlexfecLocalSsrc = 456;
brandtr1e3dfbf2016-11-16 22:45:19 -0800741
brandtr1134b7b2017-02-06 06:35:47 -0800742 explicit FlexfecRenderObserver(bool enable_nack, bool expect_flexfec_rtcp)
brandtrfa5a3682017-01-17 01:33:54 -0800743 : test::EndToEndTest(test::CallTest::kDefaultTimeoutMs),
brandtr1134b7b2017-02-06 06:35:47 -0800744 enable_nack_(enable_nack),
brandtrfa5a3682017-01-17 01:33:54 -0800745 expect_flexfec_rtcp_(expect_flexfec_rtcp),
746 received_flexfec_rtcp_(false),
brandtr1134b7b2017-02-06 06:35:47 -0800747 random_(0xcafef00d1),
748 num_packets_sent_(0) {}
brandtr1e3dfbf2016-11-16 22:45:19 -0800749
brandtrfa5a3682017-01-17 01:33:54 -0800750 size_t GetNumFlexfecStreams() const override { return 1; }
brandtr1e3dfbf2016-11-16 22:45:19 -0800751
brandtrfa5a3682017-01-17 01:33:54 -0800752 private:
753 Action OnSendRtp(const uint8_t* packet, size_t length) override {
754 rtc::CritScope lock(&crit_);
755 RTPHeader header;
756 EXPECT_TRUE(parser_->Parse(packet, length, &header));
brandtr1e3dfbf2016-11-16 22:45:19 -0800757
brandtr1134b7b2017-02-06 06:35:47 -0800758 EXPECT_TRUE(header.payloadType ==
759 test::CallTest::kFakeVideoSendPayloadType ||
760 header.payloadType == test::CallTest::kFlexfecPayloadType ||
761 (enable_nack_ &&
762 header.payloadType == test::CallTest::kSendRtxPayloadType))
763 << "Unknown payload type received.";
764 EXPECT_TRUE(
765 header.ssrc == test::CallTest::kVideoSendSsrcs[0] ||
766 header.ssrc == test::CallTest::kFlexfecSendSsrc ||
767 (enable_nack_ && header.ssrc == test::CallTest::kSendRtxSsrcs[0]))
768 << "Unknown SSRC received.";
769
770 // To reduce test flakiness, always let FlexFEC packets through.
771 if (header.payloadType == test::CallTest::kFlexfecPayloadType) {
772 EXPECT_EQ(test::CallTest::kFlexfecSendSsrc, header.ssrc);
773
774 return SEND_PACKET;
brandtr1e3dfbf2016-11-16 22:45:19 -0800775 }
776
brandtr1134b7b2017-02-06 06:35:47 -0800777 // To reduce test flakiness, always let RTX packets through.
778 if (header.payloadType == test::CallTest::kSendRtxPayloadType) {
779 EXPECT_EQ(test::CallTest::kSendRtxSsrcs[0], header.ssrc);
780
781 // Parse RTX header.
782 uint16_t original_sequence_number =
783 ByteReader<uint16_t>::ReadBigEndian(&packet[header.headerLength]);
784
785 // From the perspective of FEC, a retransmitted packet is no longer
786 // dropped, so remove it from list of dropped packets.
787 auto seq_num_it =
788 dropped_sequence_numbers_.find(original_sequence_number);
brandtrfa5a3682017-01-17 01:33:54 -0800789 if (seq_num_it != dropped_sequence_numbers_.end()) {
790 dropped_sequence_numbers_.erase(seq_num_it);
791 auto ts_it = dropped_timestamps_.find(header.timestamp);
792 EXPECT_NE(ts_it, dropped_timestamps_.end());
793 dropped_timestamps_.erase(ts_it);
brandtrfd8d2652017-02-06 06:19:51 -0800794 }
brandtr1134b7b2017-02-06 06:35:47 -0800795
796 return SEND_PACKET;
brandtrfa5a3682017-01-17 01:33:54 -0800797 }
798
brandtr1134b7b2017-02-06 06:35:47 -0800799 // Simulate 5% video packet loss after rampup period. Record the
800 // corresponding timestamps that were dropped.
801 if (num_packets_sent_++ > 100 && random_.Rand(1, 100) <= 5) {
802 EXPECT_EQ(test::CallTest::kFakeVideoSendPayloadType, header.payloadType);
803 EXPECT_EQ(test::CallTest::kVideoSendSsrcs[0], header.ssrc);
804
805 dropped_sequence_numbers_.insert(header.sequenceNumber);
806 dropped_timestamps_.insert(header.timestamp);
brandtrfa5a3682017-01-17 01:33:54 -0800807
808 return DROP_PACKET;
809 }
810
811 return SEND_PACKET;
812 }
813
814 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
815 test::RtcpPacketParser parser;
816
817 parser.Parse(data, length);
818 if (parser.sender_ssrc() == kFlexfecLocalSsrc) {
819 EXPECT_EQ(1, parser.receiver_report()->num_packets());
820 const std::vector<rtcp::ReportBlock>& report_blocks =
821 parser.receiver_report()->report_blocks();
822 if (!report_blocks.empty()) {
823 EXPECT_EQ(1U, report_blocks.size());
824 EXPECT_EQ(test::CallTest::kFlexfecSendSsrc,
825 report_blocks[0].source_ssrc());
brandtr1d2d7892017-01-18 00:40:07 -0800826 rtc::CritScope lock(&crit_);
brandtrfa5a3682017-01-17 01:33:54 -0800827 received_flexfec_rtcp_ = true;
828 }
829 }
830
831 return SEND_PACKET;
832 }
833
eladalon413ee9a2017-08-22 04:02:52 -0700834 test::PacketTransport* CreateSendTransport(
835 test::SingleThreadedTaskQueueForTesting* task_queue,
836 Call* sender_call) override {
brandtr1134b7b2017-02-06 06:35:47 -0800837 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
838 const int kNetworkDelayMs = 100;
839 FakeNetworkPipe::Config config;
840 config.queue_delay_ms = kNetworkDelayMs;
eladalon413ee9a2017-08-22 04:02:52 -0700841 return new test::PacketTransport(task_queue, sender_call, this,
nissee5ad5ca2017-03-29 23:57:43 -0700842 test::PacketTransport::kSender,
minyue20c84cc2017-04-10 16:57:57 -0700843 test::CallTest::payload_type_map_, config);
brandtr1134b7b2017-02-06 06:35:47 -0800844 }
845
brandtrfa5a3682017-01-17 01:33:54 -0800846 void OnFrame(const VideoFrame& video_frame) override {
brandtrcaea68f2017-08-23 00:55:17 -0700847 EXPECT_EQ(kVideoRotation_90, video_frame.rotation());
848
brandtrfa5a3682017-01-17 01:33:54 -0800849 rtc::CritScope lock(&crit_);
850 // Rendering frame with timestamp of packet that was dropped -> FEC
851 // protection worked.
852 auto it = dropped_timestamps_.find(video_frame.timestamp());
853 if (it != dropped_timestamps_.end()) {
854 if (!expect_flexfec_rtcp_ || received_flexfec_rtcp_) {
brandtr1e3dfbf2016-11-16 22:45:19 -0800855 observation_complete_.Set();
brandtrfa5a3682017-01-17 01:33:54 -0800856 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800857 }
brandtrfa5a3682017-01-17 01:33:54 -0800858 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800859
brandtrfa5a3682017-01-17 01:33:54 -0800860 void ModifyVideoConfigs(
861 VideoSendStream::Config* send_config,
862 std::vector<VideoReceiveStream::Config>* receive_configs,
863 VideoEncoderConfig* encoder_config) override {
864 (*receive_configs)[0].rtp.local_ssrc = kVideoLocalSsrc;
865 (*receive_configs)[0].renderer = this;
brandtr1134b7b2017-02-06 06:35:47 -0800866
867 if (enable_nack_) {
868 send_config->rtp.nack.rtp_history_ms = test::CallTest::kNackRtpHistoryMs;
brandtr1134b7b2017-02-06 06:35:47 -0800869 send_config->rtp.rtx.ssrcs.push_back(test::CallTest::kSendRtxSsrcs[0]);
870 send_config->rtp.rtx.payload_type = test::CallTest::kSendRtxPayloadType;
871
872 (*receive_configs)[0].rtp.nack.rtp_history_ms =
873 test::CallTest::kNackRtpHistoryMs;
brandtr1134b7b2017-02-06 06:35:47 -0800874 (*receive_configs)[0].rtp.rtx_ssrc = test::CallTest::kSendRtxSsrcs[0];
875 (*receive_configs)[0]
nisse26e3abb2017-08-25 04:44:25 -0700876 .rtp
877 .rtx_associated_payload_types[test::CallTest::kSendRtxPayloadType] =
878 test::CallTest::kVideoSendPayloadType;
brandtr1134b7b2017-02-06 06:35:47 -0800879 }
brandtrfa5a3682017-01-17 01:33:54 -0800880 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800881
brandtrcaea68f2017-08-23 00:55:17 -0700882 void OnFrameGeneratorCapturerCreated(
883 test::FrameGeneratorCapturer* frame_generator_capturer) override {
884 frame_generator_capturer->SetFakeRotation(kVideoRotation_90);
885 }
886
brandtrfa5a3682017-01-17 01:33:54 -0800887 void ModifyFlexfecConfigs(
888 std::vector<FlexfecReceiveStream::Config>* receive_configs) override {
889 (*receive_configs)[0].local_ssrc = kFlexfecLocalSsrc;
890 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000891
brandtrfa5a3682017-01-17 01:33:54 -0800892 void PerformTest() override {
893 EXPECT_TRUE(Wait())
894 << "Timed out waiting for dropped frames to be rendered.";
895 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000896
brandtrfa5a3682017-01-17 01:33:54 -0800897 rtc::CriticalSection crit_;
danilchapa37de392017-09-09 04:17:22 -0700898 std::set<uint32_t> dropped_sequence_numbers_ RTC_GUARDED_BY(crit_);
brandtr1134b7b2017-02-06 06:35:47 -0800899 // Several packets can have the same timestamp.
danilchapa37de392017-09-09 04:17:22 -0700900 std::multiset<uint32_t> dropped_timestamps_ RTC_GUARDED_BY(crit_);
brandtr1134b7b2017-02-06 06:35:47 -0800901 const bool enable_nack_;
brandtr1d2d7892017-01-18 00:40:07 -0800902 const bool expect_flexfec_rtcp_;
danilchapa37de392017-09-09 04:17:22 -0700903 bool received_flexfec_rtcp_ RTC_GUARDED_BY(crit_);
brandtrfa5a3682017-01-17 01:33:54 -0800904 Random random_;
brandtr1134b7b2017-02-06 06:35:47 -0800905 int num_packets_sent_;
brandtrfa5a3682017-01-17 01:33:54 -0800906};
907
philipelccdfcca2017-10-23 12:42:17 +0200908TEST_P(EndToEndTest, RecoversWithFlexfec) {
brandtr1134b7b2017-02-06 06:35:47 -0800909 FlexfecRenderObserver test(false, false);
brandtrfa5a3682017-01-17 01:33:54 -0800910 RunBaseTest(&test);
911}
912
philipelccdfcca2017-10-23 12:42:17 +0200913TEST_P(EndToEndTest, RecoversWithFlexfecAndNack) {
brandtr1134b7b2017-02-06 06:35:47 -0800914 FlexfecRenderObserver test(true, false);
915 RunBaseTest(&test);
916}
917
philipelccdfcca2017-10-23 12:42:17 +0200918TEST_P(EndToEndTest, RecoversWithFlexfecAndSendsCorrespondingRtcp) {
brandtr1134b7b2017-02-06 06:35:47 -0800919 FlexfecRenderObserver test(false, true);
stefane74eef12016-01-08 06:47:13 -0800920 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000921}
922
philipelccdfcca2017-10-23 12:42:17 +0200923TEST_P(EndToEndTest, ReceivedUlpfecPacketsNotNacked) {
brandtr535830e2016-10-31 03:45:58 -0700924 class UlpfecNackObserver : public test::EndToEndTest {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000925 public:
brandtr535830e2016-10-31 03:45:58 -0700926 UlpfecNackObserver()
stefanf116bd02015-10-27 08:29:42 -0700927 : EndToEndTest(kDefaultTimeoutMs),
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000928 state_(kFirstPacket),
brandtr535830e2016-10-31 03:45:58 -0700929 ulpfec_sequence_number_(0),
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000930 has_last_sequence_number_(false),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200931 last_sequence_number_(0),
magjed509e4fe2016-11-18 01:34:11 -0800932 encoder_(VP8Encoder::Create()),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200933 decoder_(VP8Decoder::Create()) {}
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000934
935 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000936 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800937 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000938 RTPHeader header;
939 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000940
Stefan Holmer01b48882015-05-05 10:21:24 +0200941 int encapsulated_payload_type = -1;
942 if (header.payloadType == kRedPayloadType) {
943 encapsulated_payload_type =
944 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100945 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200946 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
947 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100948 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200949 }
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000950
951 if (has_last_sequence_number_ &&
952 !IsNewerSequenceNumber(header.sequenceNumber,
953 last_sequence_number_)) {
954 // Drop retransmitted packets.
955 return DROP_PACKET;
956 }
957 last_sequence_number_ = header.sequenceNumber;
958 has_last_sequence_number_ = true;
959
brandtr535830e2016-10-31 03:45:58 -0700960 bool ulpfec_packet = encapsulated_payload_type == kUlpfecPayloadType;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000961 switch (state_) {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000962 case kFirstPacket:
brandtr535830e2016-10-31 03:45:58 -0700963 state_ = kDropEveryOtherPacketUntilUlpfec;
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000964 break;
brandtr535830e2016-10-31 03:45:58 -0700965 case kDropEveryOtherPacketUntilUlpfec:
966 if (ulpfec_packet) {
967 state_ = kDropAllMediaPacketsUntilUlpfec;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000968 } else if (header.sequenceNumber % 2 == 0) {
969 return DROP_PACKET;
970 }
971 break;
brandtr535830e2016-10-31 03:45:58 -0700972 case kDropAllMediaPacketsUntilUlpfec:
973 if (!ulpfec_packet)
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000974 return DROP_PACKET;
brandtr535830e2016-10-31 03:45:58 -0700975 ulpfec_sequence_number_ = header.sequenceNumber;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200976 state_ = kDropOneMediaPacket;
977 break;
978 case kDropOneMediaPacket:
brandtr535830e2016-10-31 03:45:58 -0700979 if (ulpfec_packet)
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200980 return DROP_PACKET;
981 state_ = kPassOneMediaPacket;
982 return DROP_PACKET;
983 break;
984 case kPassOneMediaPacket:
brandtr535830e2016-10-31 03:45:58 -0700985 if (ulpfec_packet)
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200986 return DROP_PACKET;
987 // Pass one media packet after dropped packet after last FEC,
988 // otherwise receiver might never see a seq_no after
brandtr535830e2016-10-31 03:45:58 -0700989 // |ulpfec_sequence_number_|
990 state_ = kVerifyUlpfecPacketNotInNackList;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000991 break;
brandtr535830e2016-10-31 03:45:58 -0700992 case kVerifyUlpfecPacketNotInNackList:
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000993 // Continue to drop packets. Make sure no frame can be decoded.
brandtr535830e2016-10-31 03:45:58 -0700994 if (ulpfec_packet || header.sequenceNumber % 2 == 0)
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000995 return DROP_PACKET;
996 break;
997 }
998 return SEND_PACKET;
999 }
1000
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001001 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08001002 rtc::CritScope lock_(&crit_);
brandtr535830e2016-10-31 03:45:58 -07001003 if (state_ == kVerifyUlpfecPacketNotInNackList) {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001004 test::RtcpPacketParser rtcp_parser;
1005 rtcp_parser.Parse(packet, length);
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02001006 const std::vector<uint16_t>& nacks = rtcp_parser.nack()->packet_ids();
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001007 EXPECT_TRUE(std::find(nacks.begin(), nacks.end(),
brandtr535830e2016-10-31 03:45:58 -07001008 ulpfec_sequence_number_) == nacks.end())
1009 << "Got nack for ULPFEC packet";
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001010 if (!nacks.empty() &&
brandtr535830e2016-10-31 03:45:58 -07001011 IsNewerSequenceNumber(nacks.back(), ulpfec_sequence_number_)) {
Peter Boström5811a392015-12-10 13:02:50 +01001012 observation_complete_.Set();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001013 }
1014 }
1015 return SEND_PACKET;
1016 }
1017
eladalon413ee9a2017-08-22 04:02:52 -07001018 test::PacketTransport* CreateSendTransport(
1019 test::SingleThreadedTaskQueueForTesting* task_queue,
1020 Call* sender_call) override {
stefane74eef12016-01-08 06:47:13 -08001021 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
1022 // Configure some network delay.
1023 const int kNetworkDelayMs = 50;
1024 FakeNetworkPipe::Config config;
1025 config.queue_delay_ms = kNetworkDelayMs;
eladalon413ee9a2017-08-22 04:02:52 -07001026 return new test::PacketTransport(task_queue, sender_call, this,
nissee5ad5ca2017-03-29 23:57:43 -07001027 test::PacketTransport::kSender,
minyue20c84cc2017-04-10 16:57:57 -07001028 payload_type_map_, config);
stefane74eef12016-01-08 06:47:13 -08001029 }
1030
Stefan Holmere5904162015-03-26 11:11:06 +01001031 // TODO(holmer): Investigate why we don't send FEC packets when the bitrate
1032 // is 10 kbps.
1033 Call::Config GetSenderCallConfig() override {
philipel4fb651d2017-04-10 03:54:05 -07001034 Call::Config config(event_log_.get());
Stefan Holmere5904162015-03-26 11:11:06 +01001035 const int kMinBitrateBps = 30000;
1036 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
1037 return config;
1038 }
1039
stefanff483612015-12-21 03:14:00 -08001040 void ModifyVideoConfigs(
1041 VideoSendStream::Config* send_config,
1042 std::vector<VideoReceiveStream::Config>* receive_configs,
1043 VideoEncoderConfig* encoder_config) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001044 // Configure hybrid NACK/FEC.
1045 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
brandtrb5f2c3f2016-10-04 23:28:39 -07001046 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
1047 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001048 // Set codec to VP8, otherwise NACK/FEC hybrid will be disabled.
1049 send_config->encoder_settings.encoder = encoder_.get();
1050 send_config->encoder_settings.payload_name = "VP8";
1051 send_config->encoder_settings.payload_type = kFakeVideoSendPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001052
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001053 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
nisse3b3622f2017-09-26 02:49:21 -07001054 (*receive_configs)[0].rtp.red_payload_type = kRedPayloadType;
1055 (*receive_configs)[0].rtp.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001056
1057 (*receive_configs)[0].decoders.resize(1);
1058 (*receive_configs)[0].decoders[0].payload_type =
1059 send_config->encoder_settings.payload_type;
1060 (*receive_configs)[0].decoders[0].payload_name =
1061 send_config->encoder_settings.payload_name;
1062 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001063 }
1064
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001065 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001066 EXPECT_TRUE(Wait())
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001067 << "Timed out while waiting for FEC packets to be received.";
1068 }
1069
1070 enum {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +00001071 kFirstPacket,
brandtr535830e2016-10-31 03:45:58 -07001072 kDropEveryOtherPacketUntilUlpfec,
1073 kDropAllMediaPacketsUntilUlpfec,
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001074 kDropOneMediaPacket,
1075 kPassOneMediaPacket,
brandtr535830e2016-10-31 03:45:58 -07001076 kVerifyUlpfecPacketNotInNackList,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001077 } state_;
1078
stefan608213e2015-11-01 14:56:10 -08001079 rtc::CriticalSection crit_;
danilchapa37de392017-09-09 04:17:22 -07001080 uint16_t ulpfec_sequence_number_ RTC_GUARDED_BY(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001081 bool has_last_sequence_number_;
1082 uint16_t last_sequence_number_;
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001083 std::unique_ptr<webrtc::VideoEncoder> encoder_;
1084 std::unique_ptr<webrtc::VideoDecoder> decoder_;
stefanf116bd02015-10-27 08:29:42 -07001085 } test;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001086
stefane74eef12016-01-08 06:47:13 -08001087 RunBaseTest(&test);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001088}
1089
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001090// This test drops second RTP packet with a marker bit set, makes sure it's
1091// retransmitted and renders. Retransmission SSRCs are also checked.
Peter Boström39593972016-02-15 11:27:15 +01001092void EndToEndTest::DecodesRetransmittedFrame(bool enable_rtx, bool enable_red) {
Peter Boström67680c12016-02-17 11:10:04 +01001093 static const int kDroppedFrameNumber = 10;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001094 class RetransmissionObserver : public test::EndToEndTest,
nisse76bc8e82017-02-07 09:37:41 -08001095 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001096 public:
Peter Boström39593972016-02-15 11:27:15 +01001097 RetransmissionObserver(bool enable_rtx, bool enable_red)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001098 : EndToEndTest(kDefaultTimeoutMs),
Peter Boström39593972016-02-15 11:27:15 +01001099 payload_type_(GetPayloadType(false, enable_red)),
1100 retransmission_ssrc_(enable_rtx ? kSendRtxSsrcs[0]
1101 : kVideoSendSsrcs[0]),
1102 retransmission_payload_type_(GetPayloadType(enable_rtx, enable_red)),
magjed509e4fe2016-11-18 01:34:11 -08001103 encoder_(VP8Encoder::Create()),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001104 marker_bits_observed_(0),
danilchap192717e2016-07-25 08:20:51 -07001105 retransmitted_timestamp_(0) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001106
1107 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001108 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001109 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001110 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001111 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001112
Peter Boström67680c12016-02-17 11:10:04 +01001113 // Ignore padding-only packets over RTX.
1114 if (header.payloadType != payload_type_) {
1115 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
1116 if (length == header.headerLength + header.paddingLength)
1117 return SEND_PACKET;
Stefan Holmer586b19b2015-09-18 11:14:31 +02001118 }
Peter Boström67680c12016-02-17 11:10:04 +01001119
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001120 if (header.timestamp == retransmitted_timestamp_) {
1121 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
1122 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001123 return SEND_PACKET;
1124 }
1125
Stefan Holmer586b19b2015-09-18 11:14:31 +02001126 // Found the final packet of the frame to inflict loss to, drop this and
1127 // expect a retransmission.
danilchapfdd381c2016-07-25 04:03:20 -07001128 if (header.payloadType == payload_type_ && header.markerBit &&
1129 ++marker_bits_observed_ == kDroppedFrameNumber) {
Danil Chapovalov18c65a42016-06-29 15:29:34 +02001130 // This should be the only dropped packet.
1131 EXPECT_EQ(0u, retransmitted_timestamp_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001132 retransmitted_timestamp_ = header.timestamp;
danilchap192717e2016-07-25 08:20:51 -07001133 if (std::find(rendered_timestamps_.begin(), rendered_timestamps_.end(),
1134 retransmitted_timestamp_) != rendered_timestamps_.end()) {
1135 // Frame was rendered before last packet was scheduled for sending.
1136 // This is extremly rare but possible scenario because prober able to
1137 // resend packet before it was send.
1138 // TODO(danilchap): Remove this corner case when prober would not be
1139 // able to sneak in between packet saved to history for resending and
1140 // pacer notified about existance of that packet for sending.
1141 // See https://bugs.chromium.org/p/webrtc/issues/detail?id=5540 for
1142 // details.
1143 observation_complete_.Set();
1144 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001145 return DROP_PACKET;
1146 }
1147
1148 return SEND_PACKET;
1149 }
1150
nisse76bc8e82017-02-07 09:37:41 -08001151 void OnFrame(const VideoFrame& frame) override {
brandtrcaea68f2017-08-23 00:55:17 -07001152 EXPECT_EQ(kVideoRotation_90, frame.rotation());
stefan5d837802017-02-08 07:09:05 -08001153 {
1154 rtc::CritScope lock(&crit_);
1155 if (frame.timestamp() == retransmitted_timestamp_)
1156 observation_complete_.Set();
1157 rendered_timestamps_.push_back(frame.timestamp());
1158 }
nisse76bc8e82017-02-07 09:37:41 -08001159 orig_renderer_->OnFrame(frame);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001160 }
1161
stefanff483612015-12-21 03:14:00 -08001162 void ModifyVideoConfigs(
1163 VideoSendStream::Config* send_config,
1164 std::vector<VideoReceiveStream::Config>* receive_configs,
1165 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001166 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
nisse76bc8e82017-02-07 09:37:41 -08001167
1168 // Insert ourselves into the rendering pipeline.
1169 RTC_DCHECK(!orig_renderer_);
1170 orig_renderer_ = (*receive_configs)[0].renderer;
1171 RTC_DCHECK(orig_renderer_);
stefan5d837802017-02-08 07:09:05 -08001172 (*receive_configs)[0].disable_prerenderer_smoothing = true;
nisse76bc8e82017-02-07 09:37:41 -08001173 (*receive_configs)[0].renderer = this;
1174
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001175 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
Shao Changbine62202f2015-04-21 20:24:50 +08001176
1177 if (payload_type_ == kRedPayloadType) {
brandtrb5f2c3f2016-10-04 23:28:39 -07001178 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
1179 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +01001180 if (retransmission_ssrc_ == kSendRtxSsrcs[0])
brandtrb5f2c3f2016-10-04 23:28:39 -07001181 send_config->rtp.ulpfec.red_rtx_payload_type = kRtxRedPayloadType;
nisse3b3622f2017-09-26 02:49:21 -07001182 (*receive_configs)[0].rtp.ulpfec_payload_type =
brandtrb5f2c3f2016-10-04 23:28:39 -07001183 send_config->rtp.ulpfec.ulpfec_payload_type;
nisse3b3622f2017-09-26 02:49:21 -07001184 (*receive_configs)[0].rtp.red_payload_type =
brandtrb5f2c3f2016-10-04 23:28:39 -07001185 send_config->rtp.ulpfec.red_payload_type;
Shao Changbine62202f2015-04-21 20:24:50 +08001186 }
1187
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001188 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
1189 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001190 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
brandtr14742122017-01-27 04:53:07 -08001191 (*receive_configs)[0].rtp.rtx_ssrc = kSendRtxSsrcs[0];
nisse26e3abb2017-08-25 04:44:25 -07001192 (*receive_configs)[0]
nisseca5706d2017-09-11 02:32:16 -07001193 .rtp.rtx_associated_payload_types[(payload_type_ == kRedPayloadType)
1194 ? kRtxRedPayloadType
1195 : kSendRtxPayloadType] =
nisse26e3abb2017-08-25 04:44:25 -07001196 payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001197 }
Peter Boström39593972016-02-15 11:27:15 +01001198 // Configure encoding and decoding with VP8, since generic packetization
1199 // doesn't support FEC with NACK.
kwibergaf476c72016-11-28 15:21:39 -08001200 RTC_DCHECK_EQ(1, (*receive_configs)[0].decoders.size());
Peter Boström39593972016-02-15 11:27:15 +01001201 send_config->encoder_settings.encoder = encoder_.get();
1202 send_config->encoder_settings.payload_name = "VP8";
1203 (*receive_configs)[0].decoders[0].payload_name = "VP8";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001204 }
1205
brandtrcaea68f2017-08-23 00:55:17 -07001206 void OnFrameGeneratorCapturerCreated(
1207 test::FrameGeneratorCapturer* frame_generator_capturer) override {
1208 frame_generator_capturer->SetFakeRotation(kVideoRotation_90);
1209 }
1210
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001211 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001212 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001213 << "Timed out while waiting for retransmission to render.";
1214 }
1215
nisse3b3622f2017-09-26 02:49:21 -07001216 int GetPayloadType(bool use_rtx, bool use_fec) {
1217 if (use_fec) {
Stefan Holmer10880012016-02-03 13:29:59 +01001218 if (use_rtx)
1219 return kRtxRedPayloadType;
1220 return kRedPayloadType;
1221 }
1222 if (use_rtx)
1223 return kSendRtxPayloadType;
1224 return kFakeVideoSendPayloadType;
Shao Changbine62202f2015-04-21 20:24:50 +08001225 }
1226
stefanf116bd02015-10-27 08:29:42 -07001227 rtc::CriticalSection crit_;
nisse76bc8e82017-02-07 09:37:41 -08001228 rtc::VideoSinkInterface<VideoFrame>* orig_renderer_ = nullptr;
Shao Changbine62202f2015-04-21 20:24:50 +08001229 const int payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001230 const uint32_t retransmission_ssrc_;
1231 const int retransmission_payload_type_;
kwiberg27f982b2016-03-01 11:52:33 -08001232 std::unique_ptr<VideoEncoder> encoder_;
Peter Boström39593972016-02-15 11:27:15 +01001233 const std::string payload_name_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001234 int marker_bits_observed_;
danilchapa37de392017-09-09 04:17:22 -07001235 uint32_t retransmitted_timestamp_ RTC_GUARDED_BY(&crit_);
1236 std::vector<uint32_t> rendered_timestamps_ RTC_GUARDED_BY(&crit_);
Peter Boström39593972016-02-15 11:27:15 +01001237 } test(enable_rtx, enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001238
stefane74eef12016-01-08 06:47:13 -08001239 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001240}
1241
philipelccdfcca2017-10-23 12:42:17 +02001242TEST_P(EndToEndTest, DecodesRetransmittedFrame) {
Shao Changbine62202f2015-04-21 20:24:50 +08001243 DecodesRetransmittedFrame(false, false);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001244}
1245
philipelccdfcca2017-10-23 12:42:17 +02001246TEST_P(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +08001247 DecodesRetransmittedFrame(true, false);
1248}
1249
philipelccdfcca2017-10-23 12:42:17 +02001250TEST_P(EndToEndTest, DecodesRetransmittedFrameByRed) {
Shao Changbine62202f2015-04-21 20:24:50 +08001251 DecodesRetransmittedFrame(false, true);
1252}
1253
philipelccdfcca2017-10-23 12:42:17 +02001254TEST_P(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +08001255 DecodesRetransmittedFrame(true, true);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001256}
1257
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001258void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
1259 static const int kPacketsToDrop = 1;
1260
nisse7ade7b32016-03-23 04:48:10 -07001261 class PliObserver : public test::EndToEndTest,
1262 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001263 public:
1264 explicit PliObserver(int rtp_history_ms)
1265 : EndToEndTest(kLongTimeoutMs),
1266 rtp_history_ms_(rtp_history_ms),
1267 nack_enabled_(rtp_history_ms > 0),
1268 highest_dropped_timestamp_(0),
1269 frames_to_drop_(0),
1270 received_pli_(false) {}
1271
1272 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001273 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001274 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001275 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001276 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001277
1278 // Drop all retransmitted packets to force a PLI.
1279 if (header.timestamp <= highest_dropped_timestamp_)
1280 return DROP_PACKET;
1281
1282 if (frames_to_drop_ > 0) {
1283 highest_dropped_timestamp_ = header.timestamp;
1284 --frames_to_drop_;
1285 return DROP_PACKET;
1286 }
1287
1288 return SEND_PACKET;
1289 }
1290
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001291 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001292 rtc::CritScope lock(&crit_);
danilchap3dc929e2016-11-02 08:21:59 -07001293 test::RtcpPacketParser parser;
1294 EXPECT_TRUE(parser.Parse(packet, length));
1295 if (!nack_enabled_)
1296 EXPECT_EQ(0, parser.nack()->num_packets());
1297 if (parser.pli()->num_packets() > 0)
1298 received_pli_ = true;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001299 return SEND_PACKET;
1300 }
1301
nisseeb83a1a2016-03-21 01:27:56 -07001302 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001303 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001304 if (received_pli_ &&
1305 video_frame.timestamp() > highest_dropped_timestamp_) {
Peter Boström5811a392015-12-10 13:02:50 +01001306 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001307 }
1308 if (!received_pli_)
1309 frames_to_drop_ = kPacketsToDrop;
1310 }
1311
stefanff483612015-12-21 03:14:00 -08001312 void ModifyVideoConfigs(
1313 VideoSendStream::Config* send_config,
1314 std::vector<VideoReceiveStream::Config>* receive_configs,
1315 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001316 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001317 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
1318 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001319 }
1320
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001321 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001322 EXPECT_TRUE(Wait()) << "Timed out waiting for PLI to be "
1323 "received and a frame to be "
1324 "rendered afterwards.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001325 }
1326
stefanf116bd02015-10-27 08:29:42 -07001327 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001328 int rtp_history_ms_;
1329 bool nack_enabled_;
danilchapa37de392017-09-09 04:17:22 -07001330 uint32_t highest_dropped_timestamp_ RTC_GUARDED_BY(&crit_);
1331 int frames_to_drop_ RTC_GUARDED_BY(&crit_);
1332 bool received_pli_ RTC_GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001333 } test(rtp_history_ms);
1334
stefane74eef12016-01-08 06:47:13 -08001335 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001336}
1337
philipelccdfcca2017-10-23 12:42:17 +02001338TEST_P(EndToEndTest, ReceivesPliAndRecoversWithNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001339 ReceivesPliAndRecovers(1000);
1340}
1341
philipelccdfcca2017-10-23 12:42:17 +02001342TEST_P(EndToEndTest, ReceivesPliAndRecoversWithoutNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001343 ReceivesPliAndRecovers(0);
1344}
1345
philipelccdfcca2017-10-23 12:42:17 +02001346TEST_P(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001347 class PacketInputObserver : public PacketReceiver {
1348 public:
1349 explicit PacketInputObserver(PacketReceiver* receiver)
Peter Boström5811a392015-12-10 13:02:50 +01001350 : receiver_(receiver), delivered_packet_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001351
Peter Boström5811a392015-12-10 13:02:50 +01001352 bool Wait() { return delivered_packet_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001353
1354 private:
stefan68786d22015-09-08 05:36:15 -07001355 DeliveryStatus DeliverPacket(MediaType media_type,
1356 const uint8_t* packet,
1357 size_t length,
1358 const PacketTime& packet_time) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001359 if (RtpHeaderParser::IsRtcp(packet, length)) {
stefan68786d22015-09-08 05:36:15 -07001360 return receiver_->DeliverPacket(media_type, packet, length,
1361 packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001362 } else {
1363 DeliveryStatus delivery_status =
stefan68786d22015-09-08 05:36:15 -07001364 receiver_->DeliverPacket(media_type, packet, length, packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001365 EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
Peter Boström5811a392015-12-10 13:02:50 +01001366 delivered_packet_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001367 return delivery_status;
1368 }
1369 }
1370
1371 PacketReceiver* receiver_;
Peter Boström5811a392015-12-10 13:02:50 +01001372 rtc::Event delivered_packet_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001373 };
1374
eladalon413ee9a2017-08-22 04:02:52 -07001375 std::unique_ptr<test::DirectTransport> send_transport;
1376 std::unique_ptr<test::DirectTransport> receive_transport;
1377 std::unique_ptr<PacketInputObserver> input_observer;
solenberg4fbae2b2015-08-28 04:07:10 -07001378
eladalon413ee9a2017-08-22 04:02:52 -07001379 task_queue_.SendTask([this, &send_transport, &receive_transport,
1380 &input_observer]() {
1381 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001382
eladalon413ee9a2017-08-22 04:02:52 -07001383 send_transport = rtc::MakeUnique<test::DirectTransport>(
1384 &task_queue_, sender_call_.get(), payload_type_map_);
1385 receive_transport = rtc::MakeUnique<test::DirectTransport>(
1386 &task_queue_, receiver_call_.get(), payload_type_map_);
1387 input_observer =
1388 rtc::MakeUnique<PacketInputObserver>(receiver_call_->Receiver());
1389 send_transport->SetReceiver(input_observer.get());
1390 receive_transport->SetReceiver(sender_call_->Receiver());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001391
eladalon413ee9a2017-08-22 04:02:52 -07001392 CreateSendConfig(1, 0, 0, send_transport.get());
1393 CreateMatchingReceiveConfigs(receive_transport.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001394
eladalon413ee9a2017-08-22 04:02:52 -07001395 CreateVideoStreams();
1396 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
1397 kDefaultHeight);
1398 Start();
1399
1400 receiver_call_->DestroyVideoReceiveStream(video_receive_streams_[0]);
1401 video_receive_streams_.clear();
1402 });
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001403
1404 // Wait() waits for a received packet.
eladalon413ee9a2017-08-22 04:02:52 -07001405 EXPECT_TRUE(input_observer->Wait());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001406
eladalon413ee9a2017-08-22 04:02:52 -07001407 task_queue_.SendTask([this, &send_transport, &receive_transport]() {
1408 Stop();
1409 DestroyStreams();
1410 send_transport.reset();
1411 receive_transport.reset();
1412 DestroyCalls();
1413 });
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001414}
1415
pbosda903ea2015-10-02 02:36:56 -07001416void EndToEndTest::RespectsRtcpMode(RtcpMode rtcp_mode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001417 static const int kNumCompoundRtcpPacketsToObserve = 10;
1418 class RtcpModeObserver : public test::EndToEndTest {
1419 public:
pbosda903ea2015-10-02 02:36:56 -07001420 explicit RtcpModeObserver(RtcpMode rtcp_mode)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001421 : EndToEndTest(kDefaultTimeoutMs),
1422 rtcp_mode_(rtcp_mode),
1423 sent_rtp_(0),
1424 sent_rtcp_(0) {}
1425
1426 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001427 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanb77c7162017-02-06 06:29:38 -08001428 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001429 if (++sent_rtp_ % 3 == 0)
1430 return DROP_PACKET;
1431
1432 return SEND_PACKET;
1433 }
1434
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001435 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanb77c7162017-02-06 06:29:38 -08001436 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001437 ++sent_rtcp_;
danilchap3dc929e2016-11-02 08:21:59 -07001438 test::RtcpPacketParser parser;
1439 EXPECT_TRUE(parser.Parse(packet, length));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001440
danilchap3dc929e2016-11-02 08:21:59 -07001441 EXPECT_EQ(0, parser.sender_report()->num_packets());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001442
1443 switch (rtcp_mode_) {
pbosda903ea2015-10-02 02:36:56 -07001444 case RtcpMode::kCompound:
stefanb77c7162017-02-06 06:29:38 -08001445 // TODO(holmer): We shouldn't send transport feedback alone if
1446 // compound RTCP is negotiated.
1447 if (parser.receiver_report()->num_packets() == 0 &&
1448 parser.transport_feedback()->num_packets() == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001449 ADD_FAILURE() << "Received RTCP packet without receiver report for "
pbosda903ea2015-10-02 02:36:56 -07001450 "RtcpMode::kCompound.";
Peter Boström5811a392015-12-10 13:02:50 +01001451 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001452 }
1453
1454 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
Peter Boström5811a392015-12-10 13:02:50 +01001455 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001456
1457 break;
pbosda903ea2015-10-02 02:36:56 -07001458 case RtcpMode::kReducedSize:
danilchap3dc929e2016-11-02 08:21:59 -07001459 if (parser.receiver_report()->num_packets() == 0)
Peter Boström5811a392015-12-10 13:02:50 +01001460 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001461 break;
pbosda903ea2015-10-02 02:36:56 -07001462 case RtcpMode::kOff:
1463 RTC_NOTREACHED();
1464 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001465 }
1466
1467 return SEND_PACKET;
1468 }
1469
stefanff483612015-12-21 03:14:00 -08001470 void ModifyVideoConfigs(
1471 VideoSendStream::Config* send_config,
1472 std::vector<VideoReceiveStream::Config>* receive_configs,
1473 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001474 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001475 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1476 (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001477 }
1478
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001479 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001480 EXPECT_TRUE(Wait())
pbosda903ea2015-10-02 02:36:56 -07001481 << (rtcp_mode_ == RtcpMode::kCompound
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001482 ? "Timed out before observing enough compound packets."
1483 : "Timed out before receiving a non-compound RTCP packet.");
1484 }
1485
pbosda903ea2015-10-02 02:36:56 -07001486 RtcpMode rtcp_mode_;
stefanb77c7162017-02-06 06:29:38 -08001487 rtc::CriticalSection crit_;
1488 // Must be protected since RTCP can be sent by both the process thread
1489 // and the pacer thread.
danilchapa37de392017-09-09 04:17:22 -07001490 int sent_rtp_ RTC_GUARDED_BY(&crit_);
1491 int sent_rtcp_ RTC_GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001492 } test(rtcp_mode);
1493
stefane74eef12016-01-08 06:47:13 -08001494 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001495}
1496
philipelccdfcca2017-10-23 12:42:17 +02001497TEST_P(EndToEndTest, UsesRtcpCompoundMode) {
pbosda903ea2015-10-02 02:36:56 -07001498 RespectsRtcpMode(RtcpMode::kCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001499}
1500
philipelccdfcca2017-10-23 12:42:17 +02001501TEST_P(EndToEndTest, UsesRtcpReducedSizeMode) {
pbosda903ea2015-10-02 02:36:56 -07001502 RespectsRtcpMode(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001503}
1504
1505// Test sets up a Call multiple senders with different resolutions and SSRCs.
1506// Another is set up to receive all three of these with different renderers.
sprang867fb522015-08-03 04:38:41 -07001507class MultiStreamTest {
1508 public:
minyue20c84cc2017-04-10 16:57:57 -07001509 static constexpr size_t kNumStreams = 3;
1510 const uint8_t kVideoPayloadType = 124;
1511 const std::map<uint8_t, MediaType> payload_type_map_ = {
1512 {kVideoPayloadType, MediaType::VIDEO}};
1513
sprang867fb522015-08-03 04:38:41 -07001514 struct CodecSettings {
1515 uint32_t ssrc;
1516 int width;
1517 int height;
1518 } codec_settings[kNumStreams];
1519
eladalon413ee9a2017-08-22 04:02:52 -07001520 explicit MultiStreamTest(test::SingleThreadedTaskQueueForTesting* task_queue)
1521 : task_queue_(task_queue) {
sprang867fb522015-08-03 04:38:41 -07001522 // TODO(sprang): Cleanup when msvc supports explicit initializers for array.
1523 codec_settings[0] = {1, 640, 480};
1524 codec_settings[1] = {2, 320, 240};
1525 codec_settings[2] = {3, 240, 160};
1526 }
1527
1528 virtual ~MultiStreamTest() {}
1529
1530 void RunTest() {
skvlad11a9cbf2016-10-07 11:53:05 -07001531 webrtc::RtcEventLogNullImpl event_log;
1532 Call::Config config(&event_log);
eladalon413ee9a2017-08-22 04:02:52 -07001533 std::unique_ptr<Call> sender_call;
1534 std::unique_ptr<Call> receiver_call;
1535 std::unique_ptr<test::DirectTransport> sender_transport;
1536 std::unique_ptr<test::DirectTransport> receiver_transport;
sprang867fb522015-08-03 04:38:41 -07001537
1538 VideoSendStream* send_streams[kNumStreams];
1539 VideoReceiveStream* receive_streams[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001540 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
kwiberg4a206a92016-03-31 10:24:26 -07001541 std::vector<std::unique_ptr<VideoDecoder>> allocated_decoders;
eladalon413ee9a2017-08-22 04:02:52 -07001542 std::unique_ptr<VideoEncoder> encoders[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001543
eladalon413ee9a2017-08-22 04:02:52 -07001544 task_queue_->SendTask([&]() {
1545 sender_call = rtc::WrapUnique(Call::Create(config));
1546 receiver_call = rtc::WrapUnique(Call::Create(config));
1547 sender_transport =
1548 rtc::WrapUnique(CreateSendTransport(task_queue_, sender_call.get()));
1549 receiver_transport = rtc::WrapUnique(
1550 CreateReceiveTransport(task_queue_, receiver_call.get()));
sprang867fb522015-08-03 04:38:41 -07001551
eladalon413ee9a2017-08-22 04:02:52 -07001552 sender_transport->SetReceiver(receiver_call->Receiver());
1553 receiver_transport->SetReceiver(sender_call->Receiver());
sprang867fb522015-08-03 04:38:41 -07001554
eladalon413ee9a2017-08-22 04:02:52 -07001555 for (size_t i = 0; i < kNumStreams; ++i)
1556 encoders[i].reset(VP8Encoder::Create());
sprang867fb522015-08-03 04:38:41 -07001557
eladalon413ee9a2017-08-22 04:02:52 -07001558 for (size_t i = 0; i < kNumStreams; ++i) {
1559 uint32_t ssrc = codec_settings[i].ssrc;
1560 int width = codec_settings[i].width;
1561 int height = codec_settings[i].height;
sprang867fb522015-08-03 04:38:41 -07001562
eladalon413ee9a2017-08-22 04:02:52 -07001563 VideoSendStream::Config send_config(sender_transport.get());
1564 send_config.rtp.ssrcs.push_back(ssrc);
1565 send_config.encoder_settings.encoder = encoders[i].get();
1566 send_config.encoder_settings.payload_name = "VP8";
1567 send_config.encoder_settings.payload_type = kVideoPayloadType;
1568 VideoEncoderConfig encoder_config;
1569 test::FillEncoderConfiguration(1, &encoder_config);
1570 encoder_config.max_bitrate_bps = 100000;
sprang867fb522015-08-03 04:38:41 -07001571
eladalon413ee9a2017-08-22 04:02:52 -07001572 UpdateSendConfig(i, &send_config, &encoder_config,
1573 &frame_generators[i]);
sprang867fb522015-08-03 04:38:41 -07001574
eladalon413ee9a2017-08-22 04:02:52 -07001575 send_streams[i] = sender_call->CreateVideoSendStream(
1576 send_config.Copy(), encoder_config.Copy());
1577 send_streams[i]->Start();
1578
1579 VideoReceiveStream::Config receive_config(receiver_transport.get());
1580 receive_config.rtp.remote_ssrc = ssrc;
1581 receive_config.rtp.local_ssrc = test::CallTest::kReceiverLocalVideoSsrc;
1582 VideoReceiveStream::Decoder decoder =
1583 test::CreateMatchingDecoder(send_config.encoder_settings);
1584 allocated_decoders.push_back(
1585 std::unique_ptr<VideoDecoder>(decoder.decoder));
1586 receive_config.decoders.push_back(decoder);
1587
1588 UpdateReceiveConfig(i, &receive_config);
1589
1590 receive_streams[i] =
1591 receiver_call->CreateVideoReceiveStream(std::move(receive_config));
1592 receive_streams[i]->Start();
1593
1594 frame_generators[i] = test::FrameGeneratorCapturer::Create(
1595 width, height, 30, Clock::GetRealTimeClock());
1596 send_streams[i]->SetSource(
1597 frame_generators[i],
1598 VideoSendStream::DegradationPreference::kMaintainFramerate);
1599 frame_generators[i]->Start();
1600 }
1601 });
sprang867fb522015-08-03 04:38:41 -07001602
1603 Wait();
1604
eladalon413ee9a2017-08-22 04:02:52 -07001605 task_queue_->SendTask([&]() {
1606 for (size_t i = 0; i < kNumStreams; ++i) {
1607 frame_generators[i]->Stop();
1608 sender_call->DestroyVideoSendStream(send_streams[i]);
1609 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1610 delete frame_generators[i];
1611 }
sprang867fb522015-08-03 04:38:41 -07001612
eladalon413ee9a2017-08-22 04:02:52 -07001613 sender_transport.reset();
1614 receiver_transport.reset();
1615
1616 sender_call.reset();
1617 receiver_call.reset();
1618 });
sprang867fb522015-08-03 04:38:41 -07001619 }
1620
1621 protected:
1622 virtual void Wait() = 0;
1623 // Note: frame_generator is a point-to-pointer, since the actual instance
1624 // hasn't been created at the time of this call. Only when packets/frames
1625 // start flowing should this be dereferenced.
1626 virtual void UpdateSendConfig(
1627 size_t stream_index,
1628 VideoSendStream::Config* send_config,
1629 VideoEncoderConfig* encoder_config,
1630 test::FrameGeneratorCapturer** frame_generator) {}
1631 virtual void UpdateReceiveConfig(size_t stream_index,
1632 VideoReceiveStream::Config* receive_config) {
1633 }
eladalon413ee9a2017-08-22 04:02:52 -07001634 virtual test::DirectTransport* CreateSendTransport(
1635 test::SingleThreadedTaskQueueForTesting* task_queue,
1636 Call* sender_call) {
1637 return new test::DirectTransport(task_queue, sender_call,
1638 payload_type_map_);
sprang867fb522015-08-03 04:38:41 -07001639 }
eladalon413ee9a2017-08-22 04:02:52 -07001640 virtual test::DirectTransport* CreateReceiveTransport(
1641 test::SingleThreadedTaskQueueForTesting* task_queue,
1642 Call* receiver_call) {
1643 return new test::DirectTransport(task_queue, receiver_call,
1644 payload_type_map_);
sprang867fb522015-08-03 04:38:41 -07001645 }
eladalon413ee9a2017-08-22 04:02:52 -07001646
1647 test::SingleThreadedTaskQueueForTesting* const task_queue_;
sprang867fb522015-08-03 04:38:41 -07001648};
1649
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001650// Each renderer verifies that it receives the expected resolution, and as soon
1651// as every renderer has received a frame, the test finishes.
philipelccdfcca2017-10-23 12:42:17 +02001652TEST_P(EndToEndTest, SendsAndReceivesMultipleStreams) {
nisse7ade7b32016-03-23 04:48:10 -07001653 class VideoOutputObserver : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001654 public:
sprang867fb522015-08-03 04:38:41 -07001655 VideoOutputObserver(const MultiStreamTest::CodecSettings& settings,
1656 uint32_t ssrc,
1657 test::FrameGeneratorCapturer** frame_generator)
1658 : settings_(settings),
1659 ssrc_(ssrc),
1660 frame_generator_(frame_generator),
Peter Boström5811a392015-12-10 13:02:50 +01001661 done_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001662
nisseeb83a1a2016-03-21 01:27:56 -07001663 void OnFrame(const VideoFrame& video_frame) override {
sprang867fb522015-08-03 04:38:41 -07001664 EXPECT_EQ(settings_.width, video_frame.width());
1665 EXPECT_EQ(settings_.height, video_frame.height());
1666 (*frame_generator_)->Stop();
Peter Boström5811a392015-12-10 13:02:50 +01001667 done_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001668 }
1669
sprang867fb522015-08-03 04:38:41 -07001670 uint32_t Ssrc() { return ssrc_; }
1671
Peter Boström5811a392015-12-10 13:02:50 +01001672 bool Wait() { return done_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001673
1674 private:
sprang867fb522015-08-03 04:38:41 -07001675 const MultiStreamTest::CodecSettings& settings_;
1676 const uint32_t ssrc_;
1677 test::FrameGeneratorCapturer** const frame_generator_;
Peter Boström5811a392015-12-10 13:02:50 +01001678 rtc::Event done_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001679 };
1680
sprang867fb522015-08-03 04:38:41 -07001681 class Tester : public MultiStreamTest {
1682 public:
eladalon413ee9a2017-08-22 04:02:52 -07001683 explicit Tester(test::SingleThreadedTaskQueueForTesting* task_queue)
1684 : MultiStreamTest(task_queue) {}
sprang867fb522015-08-03 04:38:41 -07001685 virtual ~Tester() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001686
sprang867fb522015-08-03 04:38:41 -07001687 protected:
1688 void Wait() override {
1689 for (const auto& observer : observers_) {
Peter Boström5811a392015-12-10 13:02:50 +01001690 EXPECT_TRUE(observer->Wait()) << "Time out waiting for from on ssrc "
1691 << observer->Ssrc();
sprang867fb522015-08-03 04:38:41 -07001692 }
1693 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001694
sprang867fb522015-08-03 04:38:41 -07001695 void UpdateSendConfig(
1696 size_t stream_index,
1697 VideoSendStream::Config* send_config,
1698 VideoEncoderConfig* encoder_config,
1699 test::FrameGeneratorCapturer** frame_generator) override {
1700 observers_[stream_index].reset(new VideoOutputObserver(
1701 codec_settings[stream_index], send_config->rtp.ssrcs.front(),
1702 frame_generator));
1703 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001704
sprang867fb522015-08-03 04:38:41 -07001705 void UpdateReceiveConfig(
1706 size_t stream_index,
1707 VideoReceiveStream::Config* receive_config) override {
1708 receive_config->renderer = observers_[stream_index].get();
1709 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001710
sprang867fb522015-08-03 04:38:41 -07001711 private:
kwiberg27f982b2016-03-01 11:52:33 -08001712 std::unique_ptr<VideoOutputObserver> observers_[kNumStreams];
eladalon413ee9a2017-08-22 04:02:52 -07001713 } tester(&task_queue_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001714
sprang867fb522015-08-03 04:38:41 -07001715 tester.RunTest();
1716}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001717
philipelccdfcca2017-10-23 12:42:17 +02001718TEST_P(EndToEndTest, AssignsTransportSequenceNumbers) {
sprang867fb522015-08-03 04:38:41 -07001719 static const int kExtensionId = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001720
sprang867fb522015-08-03 04:38:41 -07001721 class RtpExtensionHeaderObserver : public test::DirectTransport {
1722 public:
minyue20c84cc2017-04-10 16:57:57 -07001723 RtpExtensionHeaderObserver(
eladalon413ee9a2017-08-22 04:02:52 -07001724 test::SingleThreadedTaskQueueForTesting* task_queue,
minyue20c84cc2017-04-10 16:57:57 -07001725 Call* sender_call,
1726 const uint32_t& first_media_ssrc,
1727 const std::map<uint32_t, uint32_t>& ssrc_map,
1728 const std::map<uint8_t, MediaType>& payload_type_map)
eladalon413ee9a2017-08-22 04:02:52 -07001729 : DirectTransport(task_queue, sender_call, payload_type_map),
Peter Boström5811a392015-12-10 13:02:50 +01001730 done_(false, false),
sprang867fb522015-08-03 04:38:41 -07001731 parser_(RtpHeaderParser::Create()),
sprang861c55e2015-10-16 10:01:21 -07001732 first_media_ssrc_(first_media_ssrc),
1733 rtx_to_media_ssrcs_(ssrc_map),
sprang867fb522015-08-03 04:38:41 -07001734 padding_observed_(false),
sprang861c55e2015-10-16 10:01:21 -07001735 rtx_padding_observed_(false),
1736 retransmit_observed_(false),
1737 started_(false) {
sprang867fb522015-08-03 04:38:41 -07001738 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
1739 kExtensionId);
1740 }
1741 virtual ~RtpExtensionHeaderObserver() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001742
stefan1d8a5062015-10-02 03:39:33 -07001743 bool SendRtp(const uint8_t* data,
1744 size_t length,
1745 const PacketOptions& options) override {
sprang861c55e2015-10-16 10:01:21 -07001746 {
1747 rtc::CritScope cs(&lock_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001748
Erik Språng8d629712015-08-04 16:24:03 +02001749 if (IsDone())
sprang861c55e2015-10-16 10:01:21 -07001750 return false;
1751
1752 if (started_) {
1753 RTPHeader header;
1754 EXPECT_TRUE(parser_->Parse(data, length, &header));
1755 bool drop_packet = false;
1756
1757 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
1758 EXPECT_EQ(options.packet_id,
1759 header.extension.transportSequenceNumber);
1760 if (!streams_observed_.empty()) {
1761 // Unwrap packet id and verify uniqueness.
1762 int64_t packet_id = unwrapper_.Unwrap(options.packet_id);
1763 EXPECT_TRUE(received_packed_ids_.insert(packet_id).second);
1764 }
1765
1766 // Drop (up to) every 17th packet, so we get retransmits.
1767 // Only drop media, and not on the first stream (otherwise it will be
1768 // hard to distinguish from padding, which is always sent on the first
1769 // stream).
1770 if (header.payloadType != kSendRtxPayloadType &&
1771 header.ssrc != first_media_ssrc_ &&
1772 header.extension.transportSequenceNumber % 17 == 0) {
1773 dropped_seq_[header.ssrc].insert(header.sequenceNumber);
1774 drop_packet = true;
1775 }
1776
perkja8ba1952017-02-27 06:52:10 -08001777 if (header.payloadType == kSendRtxPayloadType) {
sprang861c55e2015-10-16 10:01:21 -07001778 uint16_t original_sequence_number =
1779 ByteReader<uint16_t>::ReadBigEndian(&data[header.headerLength]);
1780 uint32_t original_ssrc =
1781 rtx_to_media_ssrcs_.find(header.ssrc)->second;
1782 std::set<uint16_t>* seq_no_map = &dropped_seq_[original_ssrc];
1783 auto it = seq_no_map->find(original_sequence_number);
1784 if (it != seq_no_map->end()) {
1785 retransmit_observed_ = true;
1786 seq_no_map->erase(it);
1787 } else {
1788 rtx_padding_observed_ = true;
1789 }
1790 } else {
1791 streams_observed_.insert(header.ssrc);
1792 }
1793
1794 if (IsDone())
Peter Boström5811a392015-12-10 13:02:50 +01001795 done_.Set();
sprang861c55e2015-10-16 10:01:21 -07001796
1797 if (drop_packet)
1798 return true;
1799 }
sprang867fb522015-08-03 04:38:41 -07001800 }
sprang861c55e2015-10-16 10:01:21 -07001801
stefan1d8a5062015-10-02 03:39:33 -07001802 return test::DirectTransport::SendRtp(data, length, options);
sprang867fb522015-08-03 04:38:41 -07001803 }
1804
Erik Språng8d629712015-08-04 16:24:03 +02001805 bool IsDone() {
sprang861c55e2015-10-16 10:01:21 -07001806 bool observed_types_ok =
1807 streams_observed_.size() == MultiStreamTest::kNumStreams &&
perkja8ba1952017-02-27 06:52:10 -08001808 retransmit_observed_ && rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001809 if (!observed_types_ok)
1810 return false;
1811 // We should not have any gaps in the sequence number range.
1812 size_t seqno_range =
1813 *received_packed_ids_.rbegin() - *received_packed_ids_.begin() + 1;
1814 return seqno_range == received_packed_ids_.size();
Erik Språng8d629712015-08-04 16:24:03 +02001815 }
1816
Peter Boström5811a392015-12-10 13:02:50 +01001817 bool Wait() {
sprang861c55e2015-10-16 10:01:21 -07001818 {
1819 // Can't be sure until this point that rtx_to_media_ssrcs_ etc have
1820 // been initialized and are OK to read.
1821 rtc::CritScope cs(&lock_);
1822 started_ = true;
1823 }
Peter Boström5811a392015-12-10 13:02:50 +01001824 return done_.Wait(kDefaultTimeoutMs);
sprang861c55e2015-10-16 10:01:21 -07001825 }
sprang867fb522015-08-03 04:38:41 -07001826
sprang861c55e2015-10-16 10:01:21 -07001827 rtc::CriticalSection lock_;
Peter Boström5811a392015-12-10 13:02:50 +01001828 rtc::Event done_;
kwiberg27f982b2016-03-01 11:52:33 -08001829 std::unique_ptr<RtpHeaderParser> parser_;
sprang861c55e2015-10-16 10:01:21 -07001830 SequenceNumberUnwrapper unwrapper_;
1831 std::set<int64_t> received_packed_ids_;
sprang867fb522015-08-03 04:38:41 -07001832 std::set<uint32_t> streams_observed_;
sprang861c55e2015-10-16 10:01:21 -07001833 std::map<uint32_t, std::set<uint16_t>> dropped_seq_;
1834 const uint32_t& first_media_ssrc_;
1835 const std::map<uint32_t, uint32_t>& rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001836 bool padding_observed_;
1837 bool rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001838 bool retransmit_observed_;
1839 bool started_;
sprang867fb522015-08-03 04:38:41 -07001840 };
1841
1842 class TransportSequenceNumberTester : public MultiStreamTest {
1843 public:
eladalon413ee9a2017-08-22 04:02:52 -07001844 explicit TransportSequenceNumberTester(
1845 test::SingleThreadedTaskQueueForTesting* task_queue)
1846 : MultiStreamTest(task_queue),
1847 first_media_ssrc_(0),
1848 observer_(nullptr) {}
sprang867fb522015-08-03 04:38:41 -07001849 virtual ~TransportSequenceNumberTester() {}
1850
1851 protected:
1852 void Wait() override {
Peter Boström74f6e9e2016-04-04 17:56:10 +02001853 RTC_DCHECK(observer_);
Peter Boström5811a392015-12-10 13:02:50 +01001854 EXPECT_TRUE(observer_->Wait());
sprang867fb522015-08-03 04:38:41 -07001855 }
1856
1857 void UpdateSendConfig(
1858 size_t stream_index,
1859 VideoSendStream::Config* send_config,
1860 VideoEncoderConfig* encoder_config,
1861 test::FrameGeneratorCapturer** frame_generator) override {
1862 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001863 send_config->rtp.extensions.push_back(RtpExtension(
1864 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sprang867fb522015-08-03 04:38:41 -07001865
perkja8ba1952017-02-27 06:52:10 -08001866 // Force some padding to be sent. Note that since we do send media
1867 // packets we can not guarantee that a padding only packet is sent.
1868 // Instead, padding will most likely be send as an RTX packet.
sprang867fb522015-08-03 04:38:41 -07001869 const int kPaddingBitrateBps = 50000;
perkja8ba1952017-02-27 06:52:10 -08001870 encoder_config->max_bitrate_bps = 200000;
sprang867fb522015-08-03 04:38:41 -07001871 encoder_config->min_transmit_bitrate_bps =
perkjfa10b552016-10-02 23:45:26 -07001872 encoder_config->max_bitrate_bps + kPaddingBitrateBps;
sprang867fb522015-08-03 04:38:41 -07001873
1874 // Configure RTX for redundant payload padding.
1875 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang861c55e2015-10-16 10:01:21 -07001876 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[stream_index]);
sprang867fb522015-08-03 04:38:41 -07001877 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
sprang861c55e2015-10-16 10:01:21 -07001878 rtx_to_media_ssrcs_[kSendRtxSsrcs[stream_index]] =
1879 send_config->rtp.ssrcs[0];
1880
1881 if (stream_index == 0)
1882 first_media_ssrc_ = send_config->rtp.ssrcs[0];
sprang867fb522015-08-03 04:38:41 -07001883 }
1884
1885 void UpdateReceiveConfig(
1886 size_t stream_index,
1887 VideoReceiveStream::Config* receive_config) override {
sprang861c55e2015-10-16 10:01:21 -07001888 receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang867fb522015-08-03 04:38:41 -07001889 receive_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001890 receive_config->rtp.extensions.push_back(RtpExtension(
1891 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sakal55d932b2016-09-30 06:19:08 -07001892 receive_config->renderer = &fake_renderer_;
sprang867fb522015-08-03 04:38:41 -07001893 }
1894
eladalon413ee9a2017-08-22 04:02:52 -07001895 test::DirectTransport* CreateSendTransport(
1896 test::SingleThreadedTaskQueueForTesting* task_queue,
1897 Call* sender_call) override {
minyue20c84cc2017-04-10 16:57:57 -07001898 std::map<uint8_t, MediaType> payload_type_map =
1899 MultiStreamTest::payload_type_map_;
1900 RTC_DCHECK(payload_type_map.find(kSendRtxPayloadType) ==
1901 payload_type_map.end());
1902 payload_type_map[kSendRtxPayloadType] = MediaType::VIDEO;
eladalon413ee9a2017-08-22 04:02:52 -07001903 observer_ = new RtpExtensionHeaderObserver(
1904 task_queue, sender_call, first_media_ssrc_, rtx_to_media_ssrcs_,
1905 payload_type_map);
sprang867fb522015-08-03 04:38:41 -07001906 return observer_;
1907 }
1908
1909 private:
sakal55d932b2016-09-30 06:19:08 -07001910 test::FakeVideoRenderer fake_renderer_;
sprang861c55e2015-10-16 10:01:21 -07001911 uint32_t first_media_ssrc_;
1912 std::map<uint32_t, uint32_t> rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001913 RtpExtensionHeaderObserver* observer_;
eladalon413ee9a2017-08-22 04:02:52 -07001914 } tester(&task_queue_);
sprang867fb522015-08-03 04:38:41 -07001915
1916 tester.RunTest();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001917}
1918
Stefan Holmer04cb7632016-01-14 20:34:30 +01001919class TransportFeedbackTester : public test::EndToEndTest {
1920 public:
stefan9e117c5e12017-08-16 08:16:25 -07001921 TransportFeedbackTester(bool feedback_enabled,
1922 size_t num_video_streams,
1923 size_t num_audio_streams)
Stefan Holmer04cb7632016-01-14 20:34:30 +01001924 : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
1925 feedback_enabled_(feedback_enabled),
1926 num_video_streams_(num_video_streams),
sprangcd349d92016-07-13 09:11:28 -07001927 num_audio_streams_(num_audio_streams),
1928 receiver_call_(nullptr) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001929 // Only one stream of each supported for now.
1930 EXPECT_LE(num_video_streams, 1u);
1931 EXPECT_LE(num_audio_streams, 1u);
1932 }
1933
1934 protected:
1935 Action OnSendRtcp(const uint8_t* data, size_t length) override {
1936 EXPECT_FALSE(HasTransportFeedback(data, length));
1937 return SEND_PACKET;
1938 }
1939
1940 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
1941 if (HasTransportFeedback(data, length))
1942 observation_complete_.Set();
1943 return SEND_PACKET;
1944 }
1945
1946 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
danilchap3dc929e2016-11-02 08:21:59 -07001947 test::RtcpPacketParser parser;
1948 EXPECT_TRUE(parser.Parse(data, length));
1949 return parser.transport_feedback()->num_packets() > 0;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001950 }
1951
1952 void PerformTest() override {
1953 const int64_t kDisabledFeedbackTimeoutMs = 5000;
1954 EXPECT_EQ(feedback_enabled_,
1955 observation_complete_.Wait(feedback_enabled_
1956 ? test::CallTest::kDefaultTimeoutMs
1957 : kDisabledFeedbackTimeoutMs));
1958 }
1959
1960 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1961 receiver_call_ = receiver_call;
1962 }
1963
1964 size_t GetNumVideoStreams() const override { return num_video_streams_; }
1965 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
1966
1967 void ModifyVideoConfigs(
1968 VideoSendStream::Config* send_config,
1969 std::vector<VideoReceiveStream::Config>* receive_configs,
1970 VideoEncoderConfig* encoder_config) override {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001971 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
1972 }
1973
1974 void ModifyAudioConfigs(
1975 AudioSendStream::Config* send_config,
1976 std::vector<AudioReceiveStream::Config>* receive_configs) override {
1977 send_config->rtp.extensions.clear();
1978 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001979 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001980 (*receive_configs)[0].rtp.extensions.clear();
1981 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1982 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001983 }
1984
1985 private:
Erik Språng6b8d3552015-09-24 15:06:57 +02001986 static const int kExtensionId = 5;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001987 const bool feedback_enabled_;
1988 const size_t num_video_streams_;
1989 const size_t num_audio_streams_;
1990 Call* receiver_call_;
1991};
Erik Språng6b8d3552015-09-24 15:06:57 +02001992
philipelccdfcca2017-10-23 12:42:17 +02001993TEST_P(EndToEndTest, VideoReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001994 TransportFeedbackTester test(true, 1, 0);
1995 RunBaseTest(&test);
Erik Språng6b8d3552015-09-24 15:06:57 +02001996}
stefan43edf0f2015-11-20 18:05:48 -08001997
philipelccdfcca2017-10-23 12:42:17 +02001998TEST_P(EndToEndTest, VideoTransportFeedbackNotConfigured) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001999 TransportFeedbackTester test(false, 1, 0);
2000 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08002001}
2002
philipelccdfcca2017-10-23 12:42:17 +02002003TEST_P(EndToEndTest, AudioReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01002004 TransportFeedbackTester test(true, 0, 1);
2005 RunBaseTest(&test);
2006}
2007
philipelccdfcca2017-10-23 12:42:17 +02002008TEST_P(EndToEndTest, AudioTransportFeedbackNotConfigured) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01002009 TransportFeedbackTester test(false, 0, 1);
2010 RunBaseTest(&test);
2011}
2012
philipelccdfcca2017-10-23 12:42:17 +02002013TEST_P(EndToEndTest, AudioVideoReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01002014 TransportFeedbackTester test(true, 1, 1);
2015 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08002016}
2017
philipelccdfcca2017-10-23 12:42:17 +02002018TEST_P(EndToEndTest, StopsSendingMediaWithoutFeedback) {
stefan9e117c5e12017-08-16 08:16:25 -07002019 test::ScopedFieldTrials override_field_trials(
stefan74418272017-08-17 02:13:54 -07002020 "WebRTC-CwndExperiment/Enabled-250/");
stefan9e117c5e12017-08-16 08:16:25 -07002021
2022 class TransportFeedbackTester : public test::EndToEndTest {
2023 public:
2024 TransportFeedbackTester(size_t num_video_streams, size_t num_audio_streams)
2025 : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
2026 num_video_streams_(num_video_streams),
2027 num_audio_streams_(num_audio_streams),
2028 media_sent_(0),
2029 padding_sent_(0) {
2030 // Only one stream of each supported for now.
2031 EXPECT_LE(num_video_streams, 1u);
2032 EXPECT_LE(num_audio_streams, 1u);
2033 }
2034
2035 protected:
2036 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2037 RTPHeader header;
2038 EXPECT_TRUE(parser_->Parse(packet, length, &header));
2039 const bool only_padding =
2040 header.headerLength + header.paddingLength == length;
2041 rtc::CritScope lock(&crit_);
2042 if (only_padding) {
2043 ++padding_sent_;
2044 } else {
2045 ++media_sent_;
2046 EXPECT_LT(media_sent_, 40) << "Media sent without feedback.";
2047 }
2048
2049 return SEND_PACKET;
2050 }
2051
2052 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
2053 rtc::CritScope lock(&crit_);
2054 if (media_sent_ > 20 && HasTransportFeedback(data, length)) {
2055 return DROP_PACKET;
2056 }
2057 return SEND_PACKET;
2058 }
2059
2060 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
2061 test::RtcpPacketParser parser;
2062 EXPECT_TRUE(parser.Parse(data, length));
2063 return parser.transport_feedback()->num_packets() > 0;
2064 }
2065
2066 Call::Config GetSenderCallConfig() override {
2067 Call::Config config = EndToEndTest::GetSenderCallConfig();
2068 config.bitrate_config.max_bitrate_bps = 300000;
2069 return config;
2070 }
2071
2072 void PerformTest() override {
2073 const int64_t kDisabledFeedbackTimeoutMs = 10000;
2074 observation_complete_.Wait(kDisabledFeedbackTimeoutMs);
2075 rtc::CritScope lock(&crit_);
2076 EXPECT_GT(padding_sent_, 0);
2077 }
2078
2079 size_t GetNumVideoStreams() const override { return num_video_streams_; }
2080 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
2081
2082 private:
2083 const size_t num_video_streams_;
2084 const size_t num_audio_streams_;
2085 rtc::CriticalSection crit_;
danilchapa37de392017-09-09 04:17:22 -07002086 int media_sent_ RTC_GUARDED_BY(crit_);
2087 int padding_sent_ RTC_GUARDED_BY(crit_);
stefan9e117c5e12017-08-16 08:16:25 -07002088 } test(1, 0);
2089 RunBaseTest(&test);
2090}
2091
philipelccdfcca2017-10-23 12:42:17 +02002092TEST_P(EndToEndTest, ObserversEncodedFrames) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002093 class EncodedFrameTestObserver : public EncodedFrameObserver {
2094 public:
2095 EncodedFrameTestObserver()
Peter Boström5811a392015-12-10 13:02:50 +01002096 : length_(0), frame_type_(kEmptyFrame), called_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002097 virtual ~EncodedFrameTestObserver() {}
2098
2099 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
2100 frame_type_ = encoded_frame.frame_type_;
2101 length_ = encoded_frame.length_;
2102 buffer_.reset(new uint8_t[length_]);
2103 memcpy(buffer_.get(), encoded_frame.data_, length_);
Peter Boström5811a392015-12-10 13:02:50 +01002104 called_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002105 }
2106
Peter Boström5811a392015-12-10 13:02:50 +01002107 bool Wait() { return called_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002108
2109 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
2110 ASSERT_EQ(length_, observer.length_)
2111 << "Observed frames are of different lengths.";
2112 EXPECT_EQ(frame_type_, observer.frame_type_)
2113 << "Observed frames have different frame types.";
2114 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
2115 << "Observed encoded frames have different content.";
2116 }
2117
2118 private:
kwiberg27f982b2016-03-01 11:52:33 -08002119 std::unique_ptr<uint8_t[]> buffer_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002120 size_t length_;
2121 FrameType frame_type_;
Peter Boström5811a392015-12-10 13:02:50 +01002122 rtc::Event called_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002123 };
2124
2125 EncodedFrameTestObserver post_encode_observer;
2126 EncodedFrameTestObserver pre_decode_observer;
perkja49cbd32016-09-16 07:53:41 -07002127 test::FrameForwarder forwarder;
eladalon413ee9a2017-08-22 04:02:52 -07002128 std::unique_ptr<test::FrameGenerator> frame_generator;
2129
2130 std::unique_ptr<test::DirectTransport> sender_transport;
2131 std::unique_ptr<test::DirectTransport> receiver_transport;
2132
2133 task_queue_.SendTask([&]() {
2134 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
2135
2136 sender_transport = rtc::MakeUnique<test::DirectTransport>(
2137 &task_queue_, sender_call_.get(), payload_type_map_);
2138 receiver_transport = rtc::MakeUnique<test::DirectTransport>(
2139 &task_queue_, receiver_call_.get(), payload_type_map_);
2140 sender_transport->SetReceiver(receiver_call_->Receiver());
2141 receiver_transport->SetReceiver(sender_call_->Receiver());
2142
2143 CreateSendConfig(1, 0, 0, sender_transport.get());
2144 CreateMatchingReceiveConfigs(receiver_transport.get());
2145 video_send_config_.post_encode_callback = &post_encode_observer;
2146 video_receive_configs_[0].pre_decode_callback = &pre_decode_observer;
2147
2148 CreateVideoStreams();
2149 Start();
2150
2151 frame_generator = test::FrameGenerator::CreateSquareGenerator(
2152 kDefaultWidth, kDefaultHeight);
2153 video_send_stream_->SetSource(
2154 &forwarder, VideoSendStream::DegradationPreference::kMaintainFramerate);
2155 forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
2156 });
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002157
Peter Boström5811a392015-12-10 13:02:50 +01002158 EXPECT_TRUE(post_encode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002159 << "Timed out while waiting for send-side encoded-frame callback.";
2160
Peter Boström5811a392015-12-10 13:02:50 +01002161 EXPECT_TRUE(pre_decode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002162 << "Timed out while waiting for pre-decode encoded-frame callback.";
2163
2164 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
2165
eladalon413ee9a2017-08-22 04:02:52 -07002166 task_queue_.SendTask([this, &sender_transport, &receiver_transport]() {
2167 Stop();
2168 DestroyStreams();
2169 sender_transport.reset();
2170 receiver_transport.reset();
2171 DestroyCalls();
2172 });
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002173}
2174
philipelccdfcca2017-10-23 12:42:17 +02002175TEST_P(EndToEndTest, ReceiveStreamSendsRemb) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002176 class RembObserver : public test::EndToEndTest {
2177 public:
2178 RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
2179
stefanb77c7162017-02-06 06:29:38 -08002180 void ModifyVideoConfigs(
2181 VideoSendStream::Config* send_config,
2182 std::vector<VideoReceiveStream::Config>* receive_configs,
2183 VideoEncoderConfig* encoder_config) override {
2184 send_config->rtp.extensions.clear();
2185 send_config->rtp.extensions.push_back(RtpExtension(
2186 RtpExtension::kAbsSendTimeUri, test::kAbsSendTimeExtensionId));
2187 (*receive_configs)[0].rtp.remb = true;
2188 (*receive_configs)[0].rtp.transport_cc = false;
2189 }
2190
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002191 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
danilchap3dc929e2016-11-02 08:21:59 -07002192 test::RtcpPacketParser parser;
2193 EXPECT_TRUE(parser.Parse(packet, length));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002194
danilchap3dc929e2016-11-02 08:21:59 -07002195 if (parser.remb()->num_packets() > 0) {
2196 EXPECT_EQ(kReceiverLocalVideoSsrc, parser.remb()->sender_ssrc());
2197 EXPECT_LT(0U, parser.remb()->bitrate_bps());
2198 EXPECT_EQ(1U, parser.remb()->ssrcs().size());
2199 EXPECT_EQ(kVideoSendSsrcs[0], parser.remb()->ssrcs()[0]);
Peter Boström5811a392015-12-10 13:02:50 +01002200 observation_complete_.Set();
danilchap3dc929e2016-11-02 08:21:59 -07002201 }
2202
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002203 return SEND_PACKET;
2204 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002205 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002206 EXPECT_TRUE(Wait()) << "Timed out while waiting for a "
2207 "receiver RTCP REMB packet to be "
2208 "sent.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002209 }
2210 } test;
2211
stefane74eef12016-01-08 06:47:13 -08002212 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002213}
2214
stefanb77c7162017-02-06 06:29:38 -08002215class BandwidthStatsTest : public test::EndToEndTest {
2216 public:
2217 explicit BandwidthStatsTest(bool send_side_bwe)
2218 : EndToEndTest(test::CallTest::kDefaultTimeoutMs),
2219 sender_call_(nullptr),
2220 receiver_call_(nullptr),
2221 has_seen_pacer_delay_(false),
2222 send_side_bwe_(send_side_bwe) {}
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002223
stefanb77c7162017-02-06 06:29:38 -08002224 void ModifyVideoConfigs(
2225 VideoSendStream::Config* send_config,
2226 std::vector<VideoReceiveStream::Config>* receive_configs,
2227 VideoEncoderConfig* encoder_config) override {
2228 if (!send_side_bwe_) {
2229 send_config->rtp.extensions.clear();
2230 send_config->rtp.extensions.push_back(RtpExtension(
2231 RtpExtension::kAbsSendTimeUri, test::kAbsSendTimeExtensionId));
2232 (*receive_configs)[0].rtp.remb = true;
2233 (*receive_configs)[0].rtp.transport_cc = false;
2234 }
2235 }
2236
2237 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2238 Call::Stats sender_stats = sender_call_->GetStats();
2239 Call::Stats receiver_stats = receiver_call_->GetStats();
2240 if (!has_seen_pacer_delay_)
2241 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
2242 if (sender_stats.send_bandwidth_bps > 0 && has_seen_pacer_delay_) {
2243 if (send_side_bwe_ || receiver_stats.recv_bandwidth_bps > 0)
Peter Boström5811a392015-12-10 13:02:50 +01002244 observation_complete_.Set();
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002245 }
stefanb77c7162017-02-06 06:29:38 -08002246 return SEND_PACKET;
2247 }
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002248
stefanb77c7162017-02-06 06:29:38 -08002249 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2250 sender_call_ = sender_call;
2251 receiver_call_ = receiver_call;
2252 }
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002253
stefanb77c7162017-02-06 06:29:38 -08002254 void PerformTest() override {
2255 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2256 "non-zero bandwidth stats.";
2257 }
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002258
stefanb77c7162017-02-06 06:29:38 -08002259 private:
2260 Call* sender_call_;
2261 Call* receiver_call_;
2262 bool has_seen_pacer_delay_;
2263 const bool send_side_bwe_;
2264};
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002265
philipelccdfcca2017-10-23 12:42:17 +02002266TEST_P(EndToEndTest, VerifySendSideBweStats) {
stefanb77c7162017-02-06 06:29:38 -08002267 BandwidthStatsTest test(true);
stefane74eef12016-01-08 06:47:13 -08002268 RunBaseTest(&test);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002269}
2270
philipelccdfcca2017-10-23 12:42:17 +02002271TEST_P(EndToEndTest, VerifyRecvSideBweStats) {
stefanb77c7162017-02-06 06:29:38 -08002272 BandwidthStatsTest test(false);
2273 RunBaseTest(&test);
2274}
stefan32f81542016-01-20 07:13:58 -08002275
2276// Verifies that it's possible to limit the send BWE by sending a REMB.
2277// This is verified by allowing the send BWE to ramp-up to >1000 kbps,
2278// then have the test generate a REMB of 500 kbps and verify that the send BWE
2279// is reduced to exactly 500 kbps. Then a REMB of 1000 kbps is generated and the
2280// test verifies that the send BWE ramps back up to exactly 1000 kbps.
philipelccdfcca2017-10-23 12:42:17 +02002281TEST_P(EndToEndTest, RembWithSendSideBwe) {
stefan32f81542016-01-20 07:13:58 -08002282 class BweObserver : public test::EndToEndTest {
2283 public:
2284 BweObserver()
2285 : EndToEndTest(kDefaultTimeoutMs),
2286 sender_call_(nullptr),
2287 clock_(Clock::GetRealTimeClock()),
2288 sender_ssrc_(0),
2289 remb_bitrate_bps_(1000000),
2290 receive_transport_(nullptr),
Tommi5dd5f5a2017-02-21 14:22:59 +01002291 stop_event_(false, false),
stefan32f81542016-01-20 07:13:58 -08002292 poller_thread_(&BitrateStatsPollingThread,
2293 this,
2294 "BitrateStatsPollingThread"),
Erik Språng737336d2016-07-29 12:59:36 +02002295 state_(kWaitForFirstRampUp),
2296 retransmission_rate_limiter_(clock_, 1000) {}
stefan32f81542016-01-20 07:13:58 -08002297
2298 ~BweObserver() {}
2299
eladalon413ee9a2017-08-22 04:02:52 -07002300 test::PacketTransport* CreateReceiveTransport(
2301 test::SingleThreadedTaskQueueForTesting* task_queue) override {
stefan32f81542016-01-20 07:13:58 -08002302 receive_transport_ = new test::PacketTransport(
eladalon413ee9a2017-08-22 04:02:52 -07002303 task_queue, nullptr, this, test::PacketTransport::kReceiver,
2304 payload_type_map_, FakeNetworkPipe::Config());
stefan32f81542016-01-20 07:13:58 -08002305 return receive_transport_;
2306 }
2307
2308 Call::Config GetSenderCallConfig() override {
philipel4fb651d2017-04-10 03:54:05 -07002309 Call::Config config(event_log_.get());
stefan32f81542016-01-20 07:13:58 -08002310 // Set a high start bitrate to reduce the test completion time.
2311 config.bitrate_config.start_bitrate_bps = remb_bitrate_bps_;
2312 return config;
2313 }
2314
2315 void ModifyVideoConfigs(
2316 VideoSendStream::Config* send_config,
2317 std::vector<VideoReceiveStream::Config>* receive_configs,
2318 VideoEncoderConfig* encoder_config) override {
2319 ASSERT_EQ(1u, send_config->rtp.ssrcs.size());
stefan32f81542016-01-20 07:13:58 -08002320 sender_ssrc_ = send_config->rtp.ssrcs[0];
2321
perkjfa10b552016-10-02 23:45:26 -07002322 encoder_config->max_bitrate_bps = 2000000;
stefan32f81542016-01-20 07:13:58 -08002323
2324 ASSERT_EQ(1u, receive_configs->size());
stefan32f81542016-01-20 07:13:58 -08002325 RtpRtcp::Configuration config;
2326 config.receiver_only = true;
2327 config.clock = clock_;
2328 config.outgoing_transport = receive_transport_;
Erik Språng737336d2016-07-29 12:59:36 +02002329 config.retransmission_rate_limiter = &retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08002330 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
2331 rtp_rtcp_->SetRemoteSSRC((*receive_configs)[0].rtp.remote_ssrc);
2332 rtp_rtcp_->SetSSRC((*receive_configs)[0].rtp.local_ssrc);
stefan32f81542016-01-20 07:13:58 -08002333 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
2334 }
2335
2336 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2337 sender_call_ = sender_call;
2338 }
2339
tommi0f8b4032017-02-22 11:22:05 -08002340 static void BitrateStatsPollingThread(void* obj) {
2341 static_cast<BweObserver*>(obj)->PollStats();
stefan32f81542016-01-20 07:13:58 -08002342 }
2343
tommi0f8b4032017-02-22 11:22:05 -08002344 void PollStats() {
2345 do {
2346 if (sender_call_) {
2347 Call::Stats stats = sender_call_->GetStats();
2348 switch (state_) {
2349 case kWaitForFirstRampUp:
2350 if (stats.send_bandwidth_bps >= remb_bitrate_bps_) {
2351 state_ = kWaitForRemb;
2352 remb_bitrate_bps_ /= 2;
Danil Chapovalov51e21aa2017-10-10 17:46:26 +02002353 rtp_rtcp_->SetRemb(
tommi0f8b4032017-02-22 11:22:05 -08002354 remb_bitrate_bps_,
2355 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
2356 rtp_rtcp_->SendRTCP(kRtcpRr);
2357 }
2358 break;
stefan32f81542016-01-20 07:13:58 -08002359
tommi0f8b4032017-02-22 11:22:05 -08002360 case kWaitForRemb:
2361 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
2362 state_ = kWaitForSecondRampUp;
2363 remb_bitrate_bps_ *= 2;
Danil Chapovalov51e21aa2017-10-10 17:46:26 +02002364 rtp_rtcp_->SetRemb(
tommi0f8b4032017-02-22 11:22:05 -08002365 remb_bitrate_bps_,
2366 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
2367 rtp_rtcp_->SendRTCP(kRtcpRr);
2368 }
2369 break;
stefan32f81542016-01-20 07:13:58 -08002370
tommi0f8b4032017-02-22 11:22:05 -08002371 case kWaitForSecondRampUp:
2372 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
2373 observation_complete_.Set();
2374 }
2375 break;
2376 }
stefan32f81542016-01-20 07:13:58 -08002377 }
tommi0f8b4032017-02-22 11:22:05 -08002378 } while (!stop_event_.Wait(1000));
stefan32f81542016-01-20 07:13:58 -08002379 }
2380
2381 void PerformTest() override {
2382 poller_thread_.Start();
2383 EXPECT_TRUE(Wait())
2384 << "Timed out while waiting for bitrate to change according to REMB.";
Tommi5dd5f5a2017-02-21 14:22:59 +01002385 stop_event_.Set();
stefan32f81542016-01-20 07:13:58 -08002386 poller_thread_.Stop();
2387 }
2388
2389 private:
2390 enum TestState { kWaitForFirstRampUp, kWaitForRemb, kWaitForSecondRampUp };
2391
2392 Call* sender_call_;
2393 Clock* const clock_;
2394 uint32_t sender_ssrc_;
2395 int remb_bitrate_bps_;
kwiberg27f982b2016-03-01 11:52:33 -08002396 std::unique_ptr<RtpRtcp> rtp_rtcp_;
stefan32f81542016-01-20 07:13:58 -08002397 test::PacketTransport* receive_transport_;
Tommi5dd5f5a2017-02-21 14:22:59 +01002398 rtc::Event stop_event_;
stefan32f81542016-01-20 07:13:58 -08002399 rtc::PlatformThread poller_thread_;
2400 TestState state_;
Erik Språng737336d2016-07-29 12:59:36 +02002401 RateLimiter retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08002402 } test;
2403
2404 RunBaseTest(&test);
2405}
2406
philipelccdfcca2017-10-23 12:42:17 +02002407TEST_P(EndToEndTest, StopSendingKeyframeRequestsForInactiveStream) {
philipel3184f8e2017-05-18 08:08:53 -07002408 class KeyframeRequestObserver : public test::EndToEndTest {
2409 public:
eladalon413ee9a2017-08-22 04:02:52 -07002410 explicit KeyframeRequestObserver(
2411 test::SingleThreadedTaskQueueForTesting* task_queue)
2412 : clock_(Clock::GetRealTimeClock()), task_queue_(task_queue) {}
philipel3184f8e2017-05-18 08:08:53 -07002413
2414 void OnVideoStreamsCreated(
2415 VideoSendStream* send_stream,
2416 const std::vector<VideoReceiveStream*>& receive_streams) override {
2417 RTC_DCHECK_EQ(1, receive_streams.size());
2418 send_stream_ = send_stream;
2419 receive_stream_ = receive_streams[0];
2420 }
2421
2422 void PerformTest() override {
2423 bool frame_decoded = false;
2424 int64_t start_time = clock_->TimeInMilliseconds();
2425 while (clock_->TimeInMilliseconds() - start_time <= 5000) {
2426 if (receive_stream_->GetStats().frames_decoded > 0) {
2427 frame_decoded = true;
2428 break;
2429 }
2430 SleepMs(100);
2431 }
2432 ASSERT_TRUE(frame_decoded);
eladalon413ee9a2017-08-22 04:02:52 -07002433 task_queue_->SendTask([this]() { send_stream_->Stop(); });
philipel3184f8e2017-05-18 08:08:53 -07002434 SleepMs(10000);
2435 ASSERT_EQ(
2436 1U, receive_stream_->GetStats().rtcp_packet_type_counts.pli_packets);
2437 }
2438
2439 private:
2440 Clock* clock_;
2441 VideoSendStream* send_stream_;
2442 VideoReceiveStream* receive_stream_;
eladalon413ee9a2017-08-22 04:02:52 -07002443 test::SingleThreadedTaskQueueForTesting* const task_queue_;
2444 } test(&task_queue_);
philipel3184f8e2017-05-18 08:08:53 -07002445
2446 RunBaseTest(&test);
2447}
2448
philipele828c962017-03-21 03:24:27 -07002449class ProbingTest : public test::EndToEndTest {
2450 public:
2451 explicit ProbingTest(int start_bitrate_bps)
2452 : clock_(Clock::GetRealTimeClock()),
2453 start_bitrate_bps_(start_bitrate_bps),
2454 state_(0),
2455 sender_call_(nullptr) {}
2456
2457 ~ProbingTest() {}
2458
2459 Call::Config GetSenderCallConfig() override {
philipel4fb651d2017-04-10 03:54:05 -07002460 Call::Config config(event_log_.get());
philipele828c962017-03-21 03:24:27 -07002461 config.bitrate_config.start_bitrate_bps = start_bitrate_bps_;
2462 return config;
2463 }
2464
2465 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2466 sender_call_ = sender_call;
2467 }
2468
2469 protected:
2470 Clock* const clock_;
2471 const int start_bitrate_bps_;
2472 int state_;
2473 Call* sender_call_;
2474};
2475
philipelccdfcca2017-10-23 12:42:17 +02002476TEST_P(EndToEndTest, MAYBE_InitialProbing) {
philipele828c962017-03-21 03:24:27 -07002477 class InitialProbingTest : public ProbingTest {
2478 public:
philipel8a256522017-03-30 05:06:22 -07002479 explicit InitialProbingTest(bool* success)
eladaloncf038f72017-08-10 10:42:53 -07002480 : ProbingTest(300000), success_(success) {
2481 *success_ = false;
2482 }
philipele828c962017-03-21 03:24:27 -07002483
2484 void PerformTest() override {
2485 int64_t start_time_ms = clock_->TimeInMilliseconds();
2486 do {
philipel8a256522017-03-30 05:06:22 -07002487 if (clock_->TimeInMilliseconds() - start_time_ms > kTimeoutMs)
philipele828c962017-03-21 03:24:27 -07002488 break;
philipele828c962017-03-21 03:24:27 -07002489
2490 Call::Stats stats = sender_call_->GetStats();
2491 // Initial probing is done with a x3 and x6 multiplier of the start
2492 // bitrate, so a x4 multiplier is a high enough threshold.
philipel8a256522017-03-30 05:06:22 -07002493 if (stats.send_bandwidth_bps > 4 * 300000) {
2494 *success_ = true;
philipele828c962017-03-21 03:24:27 -07002495 break;
philipel8a256522017-03-30 05:06:22 -07002496 }
philipele828c962017-03-21 03:24:27 -07002497 } while (!observation_complete_.Wait(20));
2498 }
2499
2500 private:
2501 const int kTimeoutMs = 1000;
philipel8a256522017-03-30 05:06:22 -07002502 bool* const success_;
2503 };
philipele828c962017-03-21 03:24:27 -07002504
eladaloncf038f72017-08-10 10:42:53 -07002505 bool success = false;
philipel8a256522017-03-30 05:06:22 -07002506 const int kMaxAttempts = 3;
2507 for (int i = 0; i < kMaxAttempts; ++i) {
2508 InitialProbingTest test(&success);
2509 RunBaseTest(&test);
2510 if (success)
2511 return;
2512 }
eladaloncf038f72017-08-10 10:42:53 -07002513 EXPECT_TRUE(success) << "Failed to perform mid initial probing ("
2514 << kMaxAttempts << " attempts).";
philipele828c962017-03-21 03:24:27 -07002515}
2516
aleloi18703f92017-03-30 04:24:08 -07002517// Fails on Linux MSan: bugs.webrtc.org/7428
2518#if defined(MEMORY_SANITIZER)
philipelccdfcca2017-10-23 12:42:17 +02002519TEST_P(EndToEndTest, DISABLED_TriggerMidCallProbing) {
oprypin45197522017-06-22 01:47:20 -07002520// Fails on iOS bots: bugs.webrtc.org/7851
2521#elif defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR
philipelccdfcca2017-10-23 12:42:17 +02002522TEST_P(EndToEndTest, DISABLED_TriggerMidCallProbing) {
aleloi18703f92017-03-30 04:24:08 -07002523#else
philipelccdfcca2017-10-23 12:42:17 +02002524TEST_P(EndToEndTest, TriggerMidCallProbing) {
aleloi18703f92017-03-30 04:24:08 -07002525#endif
2526
philipele828c962017-03-21 03:24:27 -07002527 class TriggerMidCallProbingTest : public ProbingTest {
2528 public:
eladalon413ee9a2017-08-22 04:02:52 -07002529 TriggerMidCallProbingTest(
2530 test::SingleThreadedTaskQueueForTesting* task_queue,
2531 bool* success)
2532 : ProbingTest(300000), success_(success), task_queue_(task_queue) {}
philipele828c962017-03-21 03:24:27 -07002533
2534 void PerformTest() override {
philipel8a256522017-03-30 05:06:22 -07002535 *success_ = false;
philipele828c962017-03-21 03:24:27 -07002536 int64_t start_time_ms = clock_->TimeInMilliseconds();
2537 do {
philipel8a256522017-03-30 05:06:22 -07002538 if (clock_->TimeInMilliseconds() - start_time_ms > kTimeoutMs)
philipele828c962017-03-21 03:24:27 -07002539 break;
philipele828c962017-03-21 03:24:27 -07002540
2541 Call::Stats stats = sender_call_->GetStats();
2542
2543 switch (state_) {
2544 case 0:
2545 if (stats.send_bandwidth_bps > 5 * 300000) {
2546 Call::Config::BitrateConfig bitrate_config;
2547 bitrate_config.max_bitrate_bps = 100000;
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 1:
2555 if (stats.send_bandwidth_bps < 110000) {
2556 Call::Config::BitrateConfig bitrate_config;
2557 bitrate_config.max_bitrate_bps = 2500000;
eladalon413ee9a2017-08-22 04:02:52 -07002558 task_queue_->SendTask([this, &bitrate_config]() {
2559 sender_call_->SetBitrateConfig(bitrate_config);
2560 });
philipele828c962017-03-21 03:24:27 -07002561 ++state_;
2562 }
2563 break;
2564 case 2:
2565 // During high cpu load the pacer will not be able to pace packets
2566 // at the correct speed, but if we go from 110 to 1250 kbps
2567 // in 5 seconds then it is due to probing.
philipel8a256522017-03-30 05:06:22 -07002568 if (stats.send_bandwidth_bps > 1250000) {
2569 *success_ = true;
philipele828c962017-03-21 03:24:27 -07002570 observation_complete_.Set();
philipel8a256522017-03-30 05:06:22 -07002571 }
philipele828c962017-03-21 03:24:27 -07002572 break;
2573 }
2574 } while (!observation_complete_.Wait(20));
2575 }
2576
2577 private:
2578 const int kTimeoutMs = 5000;
philipel8a256522017-03-30 05:06:22 -07002579 bool* const success_;
eladalon413ee9a2017-08-22 04:02:52 -07002580 test::SingleThreadedTaskQueueForTesting* const task_queue_;
philipel8a256522017-03-30 05:06:22 -07002581 };
philipele828c962017-03-21 03:24:27 -07002582
eladaloncf038f72017-08-10 10:42:53 -07002583 bool success = false;
philipel8a256522017-03-30 05:06:22 -07002584 const int kMaxAttempts = 3;
2585 for (int i = 0; i < kMaxAttempts; ++i) {
eladalon413ee9a2017-08-22 04:02:52 -07002586 TriggerMidCallProbingTest test(&task_queue_, &success);
philipel8a256522017-03-30 05:06:22 -07002587 RunBaseTest(&test);
2588 if (success)
2589 return;
2590 }
stefan9e117c5e12017-08-16 08:16:25 -07002591 EXPECT_TRUE(success) << "Failed to perform mid call probing (" << kMaxAttempts
2592 << " attempts).";
philipele828c962017-03-21 03:24:27 -07002593}
2594
philipelccdfcca2017-10-23 12:42:17 +02002595TEST_P(EndToEndTest, VerifyNackStats) {
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002596 static const int kPacketNumberToDrop = 200;
2597 class NackObserver : public test::EndToEndTest {
2598 public:
2599 NackObserver()
2600 : EndToEndTest(kLongTimeoutMs),
2601 sent_rtp_packets_(0),
2602 dropped_rtp_packet_(0),
2603 dropped_rtp_packet_requested_(false),
2604 send_stream_(nullptr),
2605 start_runtime_ms_(-1) {}
2606
2607 private:
2608 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002609 rtc::CritScope lock(&crit_);
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002610 if (++sent_rtp_packets_ == kPacketNumberToDrop) {
kwiberg27f982b2016-03-01 11:52:33 -08002611 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002612 RTPHeader header;
2613 EXPECT_TRUE(parser->Parse(packet, length, &header));
2614 dropped_rtp_packet_ = header.sequenceNumber;
2615 return DROP_PACKET;
2616 }
2617 VerifyStats();
2618 return SEND_PACKET;
2619 }
2620
2621 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002622 rtc::CritScope lock(&crit_);
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002623 test::RtcpPacketParser rtcp_parser;
2624 rtcp_parser.Parse(packet, length);
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02002625 const std::vector<uint16_t>& nacks = rtcp_parser.nack()->packet_ids();
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002626 if (!nacks.empty() && std::find(
2627 nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) {
2628 dropped_rtp_packet_requested_ = true;
2629 }
2630 return SEND_PACKET;
2631 }
2632
danilchapa37de392017-09-09 04:17:22 -07002633 void VerifyStats() RTC_EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002634 if (!dropped_rtp_packet_requested_)
2635 return;
2636 int send_stream_nack_packets = 0;
2637 int receive_stream_nack_packets = 0;
2638 VideoSendStream::Stats stats = send_stream_->GetStats();
2639 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
2640 stats.substreams.begin(); it != stats.substreams.end(); ++it) {
2641 const VideoSendStream::StreamStats& stream_stats = it->second;
2642 send_stream_nack_packets +=
2643 stream_stats.rtcp_packet_type_counts.nack_packets;
2644 }
2645 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2646 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2647 receive_stream_nack_packets +=
2648 stats.rtcp_packet_type_counts.nack_packets;
2649 }
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002650 if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) {
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002651 // NACK packet sent on receive stream and received on sent stream.
2652 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002653 observation_complete_.Set();
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002654 }
2655 }
2656
2657 bool MinMetricRunTimePassed() {
2658 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2659 if (start_runtime_ms_ == -1) {
2660 start_runtime_ms_ = now;
2661 return false;
2662 }
2663 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2664 return elapsed_sec > metrics::kMinRunTimeInSeconds;
2665 }
2666
stefanff483612015-12-21 03:14:00 -08002667 void ModifyVideoConfigs(
2668 VideoSendStream::Config* send_config,
2669 std::vector<VideoReceiveStream::Config>* receive_configs,
2670 VideoEncoderConfig* encoder_config) override {
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002671 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2672 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sakal55d932b2016-09-30 06:19:08 -07002673 (*receive_configs)[0].renderer = &fake_renderer_;
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002674 }
2675
stefanff483612015-12-21 03:14:00 -08002676 void OnVideoStreamsCreated(
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002677 VideoSendStream* send_stream,
2678 const std::vector<VideoReceiveStream*>& receive_streams) override {
2679 send_stream_ = send_stream;
2680 receive_streams_ = receive_streams;
2681 }
2682
2683 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002684 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002685 }
2686
sakal55d932b2016-09-30 06:19:08 -07002687 test::FakeVideoRenderer fake_renderer_;
stefan608213e2015-11-01 14:56:10 -08002688 rtc::CriticalSection crit_;
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002689 uint64_t sent_rtp_packets_;
danilchapa37de392017-09-09 04:17:22 -07002690 uint16_t dropped_rtp_packet_ RTC_GUARDED_BY(&crit_);
2691 bool dropped_rtp_packet_requested_ RTC_GUARDED_BY(&crit_);
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002692 std::vector<VideoReceiveStream*> receive_streams_;
2693 VideoSendStream* send_stream_;
2694 int64_t start_runtime_ms_;
2695 } test;
2696
asapersson01d70a32016-05-20 06:29:46 -07002697 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002698 RunBaseTest(&test);
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002699
asapersson01d70a32016-05-20 06:29:46 -07002700 EXPECT_EQ(
2701 1, metrics::NumSamples("WebRTC.Video.UniqueNackRequestsSentInPercent"));
2702 EXPECT_EQ(1, metrics::NumSamples(
2703 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
2704 EXPECT_GT(metrics::MinSample("WebRTC.Video.NackPacketsSentPerMinute"), 0);
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002705}
2706
sprangb4a1ae52015-12-03 08:10:08 -08002707void EndToEndTest::VerifyHistogramStats(bool use_rtx,
nisse3b3622f2017-09-26 02:49:21 -07002708 bool use_fec,
sprangb4a1ae52015-12-03 08:10:08 -08002709 bool screenshare) {
tommi2e82f382016-06-21 00:26:43 -07002710 class StatsObserver : public test::EndToEndTest,
2711 public rtc::VideoSinkInterface<VideoFrame> {
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002712 public:
nisse3b3622f2017-09-26 02:49:21 -07002713 StatsObserver(bool use_rtx, bool use_fec, bool screenshare)
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002714 : EndToEndTest(kLongTimeoutMs),
2715 use_rtx_(use_rtx),
nisse3b3622f2017-09-26 02:49:21 -07002716 use_fec_(use_fec),
sprangb4a1ae52015-12-03 08:10:08 -08002717 screenshare_(screenshare),
Peter Boström39593972016-02-15 11:27:15 +01002718 // This test uses NACK, so to send FEC we can't use a fake encoder.
nisse3b3622f2017-09-26 02:49:21 -07002719 vp8_encoder_(use_fec ? VP8Encoder::Create() : nullptr),
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002720 sender_call_(nullptr),
2721 receiver_call_(nullptr),
asapersson1394c7b2016-10-18 11:50:50 -07002722 start_runtime_ms_(-1),
2723 num_frames_received_(0) {}
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002724
2725 private:
asapersson1394c7b2016-10-18 11:50:50 -07002726 void OnFrame(const VideoFrame& video_frame) override {
2727 // The RTT is needed to estimate |ntp_time_ms| which is used by
2728 // end-to-end delay stats. Therefore, start counting received frames once
2729 // |ntp_time_ms| is valid.
2730 if (video_frame.ntp_time_ms() > 0 &&
2731 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() >=
2732 video_frame.ntp_time_ms()) {
2733 rtc::CritScope lock(&crit_);
2734 ++num_frames_received_;
2735 }
2736 }
tommi2e82f382016-06-21 00:26:43 -07002737
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002738 Action OnSendRtp(const uint8_t* packet, size_t length) override {
asapersson1394c7b2016-10-18 11:50:50 -07002739 if (MinMetricRunTimePassed() && MinNumberOfFramesReceived())
Peter Boström5811a392015-12-10 13:02:50 +01002740 observation_complete_.Set();
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002741
stefanf116bd02015-10-27 08:29:42 -07002742 return SEND_PACKET;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002743 }
2744
2745 bool MinMetricRunTimePassed() {
2746 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2747 if (start_runtime_ms_ == -1) {
2748 start_runtime_ms_ = now;
2749 return false;
2750 }
2751 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2752 return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
2753 }
2754
asapersson1394c7b2016-10-18 11:50:50 -07002755 bool MinNumberOfFramesReceived() const {
2756 const int kMinRequiredHistogramSamples = 200;
2757 rtc::CritScope lock(&crit_);
2758 return num_frames_received_ > kMinRequiredHistogramSamples;
2759 }
2760
stefanff483612015-12-21 03:14:00 -08002761 void ModifyVideoConfigs(
2762 VideoSendStream::Config* send_config,
2763 std::vector<VideoReceiveStream::Config>* receive_configs,
2764 VideoEncoderConfig* encoder_config) override {
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002765 // NACK
2766 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2767 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
tommi2e82f382016-06-21 00:26:43 -07002768 (*receive_configs)[0].renderer = this;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002769 // FEC
nisse3b3622f2017-09-26 02:49:21 -07002770 if (use_fec_) {
brandtrb5f2c3f2016-10-04 23:28:39 -07002771 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
2772 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
Peter Boström39593972016-02-15 11:27:15 +01002773 send_config->encoder_settings.encoder = vp8_encoder_.get();
2774 send_config->encoder_settings.payload_name = "VP8";
2775 (*receive_configs)[0].decoders[0].payload_name = "VP8";
nisse3b3622f2017-09-26 02:49:21 -07002776 (*receive_configs)[0].rtp.red_payload_type = kRedPayloadType;
2777 (*receive_configs)[0].rtp.ulpfec_payload_type = kUlpfecPayloadType;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002778 }
2779 // RTX
2780 if (use_rtx_) {
2781 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
2782 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
brandtr14742122017-01-27 04:53:07 -08002783 (*receive_configs)[0].rtp.rtx_ssrc = kSendRtxSsrcs[0];
nisse26e3abb2017-08-25 04:44:25 -07002784 (*receive_configs)[0]
2785 .rtp.rtx_associated_payload_types[kSendRtxPayloadType] =
2786 kFakeVideoSendPayloadType;
nisse3b3622f2017-09-26 02:49:21 -07002787 if (use_fec_) {
2788 send_config->rtp.ulpfec.red_rtx_payload_type = kRtxRedPayloadType;
2789 (*receive_configs)[0]
2790 .rtp.rtx_associated_payload_types[kRtxRedPayloadType] =
2791 kSendRtxPayloadType;
2792 }
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002793 }
asapersson1490f7a2016-09-23 02:09:46 -07002794 // RTT needed for RemoteNtpTimeEstimator for the receive stream.
2795 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = true;
sprangb4a1ae52015-12-03 08:10:08 -08002796 encoder_config->content_type =
2797 screenshare_ ? VideoEncoderConfig::ContentType::kScreen
2798 : VideoEncoderConfig::ContentType::kRealtimeVideo;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002799 }
2800
2801 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2802 sender_call_ = sender_call;
2803 receiver_call_ = receiver_call;
2804 }
2805
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002806 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002807 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002808 }
2809
asapersson1394c7b2016-10-18 11:50:50 -07002810 rtc::CriticalSection crit_;
sprangb4a1ae52015-12-03 08:10:08 -08002811 const bool use_rtx_;
nisse3b3622f2017-09-26 02:49:21 -07002812 const bool use_fec_;
sprangb4a1ae52015-12-03 08:10:08 -08002813 const bool screenshare_;
kwiberg27f982b2016-03-01 11:52:33 -08002814 const std::unique_ptr<VideoEncoder> vp8_encoder_;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002815 Call* sender_call_;
2816 Call* receiver_call_;
2817 int64_t start_runtime_ms_;
danilchapa37de392017-09-09 04:17:22 -07002818 int num_frames_received_ RTC_GUARDED_BY(&crit_);
nisse3b3622f2017-09-26 02:49:21 -07002819 } test(use_rtx, use_fec, screenshare);
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002820
asapersson01d70a32016-05-20 06:29:46 -07002821 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002822 RunBaseTest(&test);
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002823
sprangb4a1ae52015-12-03 08:10:08 -08002824 std::string video_prefix =
2825 screenshare ? "WebRTC.Video.Screenshare." : "WebRTC.Video.";
ilnik6d5b4d62017-08-30 03:32:14 -07002826 // The content type extension is disabled in non screenshare test,
2827 // therefore no slicing on simulcast id should be present.
2828 std::string video_suffix = screenshare ? ".S0" : "";
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002829 // Verify that stats have been updated once.
asapersson4374a092016-07-27 00:39:09 -07002830 EXPECT_EQ(2, metrics::NumSamples("WebRTC.Call.LifetimeInSeconds"));
saza0d7f04d2017-07-04 04:05:06 -07002831 EXPECT_EQ(1, metrics::NumSamples(
2832 "WebRTC.Call.TimeReceivingVideoRtpPacketsInSeconds"));
asapersson01d70a32016-05-20 06:29:46 -07002833 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
2834 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.RtcpBitrateReceivedInBps"));
2835 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.BitrateReceivedInKbps"));
2836 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.EstimatedSendBitrateInKbps"));
2837 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.PacerBitrateInKbps"));
2838
asapersson4374a092016-07-27 00:39:09 -07002839 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
2840 EXPECT_EQ(1,
2841 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
2842
asapersson01d70a32016-05-20 06:29:46 -07002843 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
stefan91d92602015-11-11 10:13:02 -08002844 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002845 metrics::NumSamples(video_prefix + "NackPacketsReceivedPerMinute"));
2846 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
asaperssond89920b2015-07-22 06:52:00 -07002847 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002848 metrics::NumSamples(video_prefix + "FirPacketsReceivedPerMinute"));
2849 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
sprangb4a1ae52015-12-03 08:10:08 -08002850 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002851 metrics::NumSamples(video_prefix + "PliPacketsReceivedPerMinute"));
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002852
asapersson01d70a32016-05-20 06:29:46 -07002853 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "KeyFramesSentInPermille"));
2854 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
2855
2856 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentPacketsLostInPercent"));
2857 EXPECT_EQ(1,
2858 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
2859
2860 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputWidthInPixels"));
2861 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputHeightInPixels"));
2862 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentWidthInPixels"));
2863 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentHeightInPixels"));
ilnik6d5b4d62017-08-30 03:32:14 -07002864 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "ReceivedWidthInPixels"));
2865 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "ReceivedHeightInPixels"));
asapersson01d70a32016-05-20 06:29:46 -07002866
perkjfa10b552016-10-02 23:45:26 -07002867 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputWidthInPixels",
2868 kDefaultWidth));
2869 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputHeightInPixels",
2870 kDefaultHeight));
2871 EXPECT_EQ(
2872 1, metrics::NumEvents(video_prefix + "SentWidthInPixels", kDefaultWidth));
2873 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "SentHeightInPixels",
2874 kDefaultHeight));
ilnik6d5b4d62017-08-30 03:32:14 -07002875 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "ReceivedWidthInPixels",
perkjfa10b552016-10-02 23:45:26 -07002876 kDefaultWidth));
ilnik6d5b4d62017-08-30 03:32:14 -07002877 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "ReceivedHeightInPixels",
perkjfa10b552016-10-02 23:45:26 -07002878 kDefaultHeight));
asapersson01d70a32016-05-20 06:29:46 -07002879
2880 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputFramesPerSecond"));
2881 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentFramesPerSecond"));
2882 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
2883 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
2884
2885 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
2886 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
2887 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
2888 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
2889
ilnik6d5b4d62017-08-30 03:32:14 -07002890 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EndToEndDelayInMs" +
2891 video_suffix));
2892 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EndToEndDelayMaxInMs" +
2893 video_suffix));
2894 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InterframeDelayInMs" +
2895 video_suffix));
2896 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InterframeDelayMaxInMs" +
2897 video_suffix));
ilnik4257ab22017-07-03 01:15:58 -07002898
asapersson01d70a32016-05-20 06:29:46 -07002899 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
2900
2901 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EncodeTimeInMs"));
2902 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
2903
asapersson66d4b372016-12-19 06:50:53 -08002904 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "NumberOfPauseEvents"));
2905 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PausedTimeInPercent"));
2906
asapersson01d70a32016-05-20 06:29:46 -07002907 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "BitrateSentInKbps"));
2908 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateReceivedInKbps"));
2909 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "MediaBitrateSentInKbps"));
2910 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateReceivedInKbps"));
2911 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PaddingBitrateSentInKbps"));
2912 EXPECT_EQ(1,
2913 metrics::NumSamples("WebRTC.Video.PaddingBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002914 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002915 1, metrics::NumSamples(video_prefix + "RetransmittedBitrateSentInKbps"));
2916 EXPECT_EQ(1, metrics::NumSamples(
2917 "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002918
asapersson01d70a32016-05-20 06:29:46 -07002919 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendDelayInMs"));
2920 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayInMs"));
2921 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayMaxInMs"));
asapersson6f14be82015-11-16 00:40:49 -08002922
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002923 int num_rtx_samples = use_rtx ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002924 EXPECT_EQ(num_rtx_samples,
2925 metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2926 EXPECT_EQ(num_rtx_samples,
2927 metrics::NumSamples("WebRTC.Video.RtxBitrateReceivedInKbps"));
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002928
nisse3b3622f2017-09-26 02:49:21 -07002929 int num_red_samples = use_fec ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002930 EXPECT_EQ(num_red_samples,
2931 metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2932 EXPECT_EQ(num_red_samples,
2933 metrics::NumSamples("WebRTC.Video.FecBitrateReceivedInKbps"));
2934 EXPECT_EQ(num_red_samples,
2935 metrics::NumSamples("WebRTC.Video.ReceivedFecPacketsInPercent"));
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002936}
2937
Lu Liufb9e7512017-04-13 14:09:56 -07002938#if defined(WEBRTC_WIN)
2939// Disabled due to flakiness on Windows (bugs.webrtc.org/7483).
2940#define MAYBE_ContentTypeSwitches DISABLED_ContentTypeSwitches
2941#else
2942#define MAYBE_ContentTypeSwitches ContentTypeSwitches
2943#endif
philipelccdfcca2017-10-23 12:42:17 +02002944TEST_P(EndToEndTest, MAYBE_ContentTypeSwitches) {
ilnik00d802b2017-04-11 10:34:31 -07002945 class StatsObserver : public test::BaseTest,
2946 public rtc::VideoSinkInterface<VideoFrame> {
2947 public:
2948 StatsObserver() : BaseTest(kLongTimeoutMs), num_frames_received_(0) {}
2949
2950 bool ShouldCreateReceivers() const override { return true; }
2951
2952 void OnFrame(const VideoFrame& video_frame) override {
2953 // The RTT is needed to estimate |ntp_time_ms| which is used by
2954 // end-to-end delay stats. Therefore, start counting received frames once
2955 // |ntp_time_ms| is valid.
2956 if (video_frame.ntp_time_ms() > 0 &&
2957 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() >=
2958 video_frame.ntp_time_ms()) {
2959 rtc::CritScope lock(&crit_);
2960 ++num_frames_received_;
2961 }
2962 }
2963
2964 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2965 if (MinNumberOfFramesReceived())
2966 observation_complete_.Set();
2967 return SEND_PACKET;
2968 }
2969
2970 bool MinNumberOfFramesReceived() const {
ilnikf6f808f2017-04-18 09:17:53 -07002971 // Have some room for frames with wrong content type during switch.
2972 const int kMinRequiredHistogramSamples = 200+50;
ilnik00d802b2017-04-11 10:34:31 -07002973 rtc::CritScope lock(&crit_);
2974 return num_frames_received_ > kMinRequiredHistogramSamples;
2975 }
2976
2977 // May be called several times.
2978 void PerformTest() override {
2979 EXPECT_TRUE(Wait()) << "Timed out waiting for enough packets.";
2980 // Reset frame counter so next PerformTest() call will do something.
2981 {
2982 rtc::CritScope lock(&crit_);
2983 num_frames_received_ = 0;
2984 }
2985 }
2986
2987 rtc::CriticalSection crit_;
danilchapa37de392017-09-09 04:17:22 -07002988 int num_frames_received_ RTC_GUARDED_BY(&crit_);
ilnik00d802b2017-04-11 10:34:31 -07002989 } test;
2990
2991 metrics::Reset();
2992
2993 Call::Config send_config(test.GetSenderCallConfig());
ilnik00d802b2017-04-11 10:34:31 -07002994 Call::Config recv_config(test.GetReceiverCallConfig());
eladalon413ee9a2017-08-22 04:02:52 -07002995 VideoEncoderConfig encoder_config_with_screenshare;
ilnik00d802b2017-04-11 10:34:31 -07002996
ilnik41cadbc2017-08-23 00:44:27 -07002997 task_queue_.SendTask([this, &test, &send_config,
eladalon413ee9a2017-08-22 04:02:52 -07002998 &recv_config, &encoder_config_with_screenshare]() {
2999 CreateSenderCall(send_config);
3000 CreateReceiverCall(recv_config);
ilnik00d802b2017-04-11 10:34:31 -07003001
eladalon413ee9a2017-08-22 04:02:52 -07003002 receive_transport_.reset(test.CreateReceiveTransport(&task_queue_));
3003 send_transport_.reset(
3004 test.CreateSendTransport(&task_queue_, sender_call_.get()));
3005 send_transport_->SetReceiver(receiver_call_->Receiver());
3006 receive_transport_->SetReceiver(sender_call_->Receiver());
3007
3008 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
3009 CreateSendConfig(1, 0, 0, send_transport_.get());
3010 CreateMatchingReceiveConfigs(receive_transport_.get());
3011
3012 // Modify send and receive configs.
3013 video_send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
3014 video_receive_configs_[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
3015 video_receive_configs_[0].renderer = &test;
3016 // RTT needed for RemoteNtpTimeEstimator for the receive stream.
3017 video_receive_configs_[0].rtp.rtcp_xr.receiver_reference_time_report = true;
3018 // Start with realtime video.
3019 video_encoder_config_.content_type =
3020 VideoEncoderConfig::ContentType::kRealtimeVideo;
3021 // Second encoder config for the second part of the test uses screenshare
3022 encoder_config_with_screenshare = video_encoder_config_.Copy();
3023 encoder_config_with_screenshare.content_type =
3024 VideoEncoderConfig::ContentType::kScreen;
3025
3026 CreateVideoStreams();
3027 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
3028 kDefaultHeight);
3029 Start();
3030 });
ilnik00d802b2017-04-11 10:34:31 -07003031
3032 test.PerformTest();
3033
3034 // Replace old send stream.
eladalon413ee9a2017-08-22 04:02:52 -07003035 task_queue_.SendTask([this, &encoder_config_with_screenshare]() {
3036 sender_call_->DestroyVideoSendStream(video_send_stream_);
3037 video_send_stream_ = sender_call_->CreateVideoSendStream(
3038 video_send_config_.Copy(), encoder_config_with_screenshare.Copy());
3039 video_send_stream_->SetSource(
3040 frame_generator_capturer_.get(),
3041 VideoSendStream::DegradationPreference::kBalanced);
3042 video_send_stream_->Start();
3043 });
ilnik00d802b2017-04-11 10:34:31 -07003044
3045 // Continue to run test but now with screenshare.
3046 test.PerformTest();
3047
eladalon413ee9a2017-08-22 04:02:52 -07003048 task_queue_.SendTask([this]() {
3049 Stop();
3050 DestroyStreams();
3051 send_transport_.reset();
3052 receive_transport_.reset();
3053 DestroyCalls();
3054 });
ilnik00d802b2017-04-11 10:34:31 -07003055
3056 // Verify that stats have been updated for both screenshare and video.
3057 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.EndToEndDelayInMs"));
3058 EXPECT_EQ(1,
3059 metrics::NumSamples("WebRTC.Video.Screenshare.EndToEndDelayInMs"));
3060 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.EndToEndDelayMaxInMs"));
3061 EXPECT_EQ(
3062 1, metrics::NumSamples("WebRTC.Video.Screenshare.EndToEndDelayMaxInMs"));
ilnik4257ab22017-07-03 01:15:58 -07003063 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
3064 EXPECT_EQ(1,
3065 metrics::NumSamples(
3066 "WebRTC.Video.Screenshare.InterframeDelayInMs"));
3067 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
3068 EXPECT_EQ(1,
3069 metrics::NumSamples(
3070 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
ilnik00d802b2017-04-11 10:34:31 -07003071}
3072
philipelccdfcca2017-10-23 12:42:17 +02003073TEST_P(EndToEndTest, VerifyHistogramStatsWithRtx) {
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02003074 const bool kEnabledRtx = true;
3075 const bool kEnabledRed = false;
sprangb4a1ae52015-12-03 08:10:08 -08003076 const bool kScreenshare = false;
3077 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02003078}
3079
philipelccdfcca2017-10-23 12:42:17 +02003080TEST_P(EndToEndTest, VerifyHistogramStatsWithRed) {
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02003081 const bool kEnabledRtx = false;
3082 const bool kEnabledRed = true;
sprangb4a1ae52015-12-03 08:10:08 -08003083 const bool kScreenshare = false;
3084 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
3085}
3086
philipelccdfcca2017-10-23 12:42:17 +02003087TEST_P(EndToEndTest, VerifyHistogramStatsWithScreenshare) {
sprangb4a1ae52015-12-03 08:10:08 -08003088 const bool kEnabledRtx = false;
3089 const bool kEnabledRed = false;
3090 const bool kScreenshare = true;
3091 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02003092}
3093
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003094void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
3095 bool send_single_ssrc_first) {
3096 class SendsSetSsrcs : public test::EndToEndTest {
3097 public:
3098 SendsSetSsrcs(const uint32_t* ssrcs,
3099 size_t num_ssrcs,
3100 bool send_single_ssrc_first)
3101 : EndToEndTest(kDefaultTimeoutMs),
3102 num_ssrcs_(num_ssrcs),
3103 send_single_ssrc_first_(send_single_ssrc_first),
3104 ssrcs_to_observe_(num_ssrcs),
sprang867fb522015-08-03 04:38:41 -07003105 expect_single_ssrc_(send_single_ssrc_first),
3106 send_stream_(nullptr) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003107 for (size_t i = 0; i < num_ssrcs; ++i)
3108 valid_ssrcs_[ssrcs[i]] = true;
3109 }
3110
3111 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003112 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003113 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003114 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003115
3116 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
3117 << "Received unknown SSRC: " << header.ssrc;
3118
3119 if (!valid_ssrcs_[header.ssrc])
Peter Boström5811a392015-12-10 13:02:50 +01003120 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003121
3122 if (!is_observed_[header.ssrc]) {
3123 is_observed_[header.ssrc] = true;
3124 --ssrcs_to_observe_;
3125 if (expect_single_ssrc_) {
3126 expect_single_ssrc_ = false;
Peter Boström5811a392015-12-10 13:02:50 +01003127 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003128 }
3129 }
3130
3131 if (ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01003132 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003133
3134 return SEND_PACKET;
3135 }
3136
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003137 size_t GetNumVideoStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003138
perkjfa10b552016-10-02 23:45:26 -07003139 // This test use other VideoStream settings than the the default settings
3140 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3141 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3142 // in ModifyVideoConfigs.
3143 class VideoStreamFactory
3144 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3145 public:
3146 VideoStreamFactory() {}
3147
3148 private:
3149 std::vector<VideoStream> CreateEncoderStreams(
3150 int width,
3151 int height,
3152 const VideoEncoderConfig& encoder_config) override {
3153 std::vector<VideoStream> streams =
3154 test::CreateVideoStreams(width, height, encoder_config);
3155 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
3156 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3157 streams[i].min_bitrate_bps = 10000;
3158 streams[i].target_bitrate_bps = 15000;
3159 streams[i].max_bitrate_bps = 20000;
3160 }
3161 return streams;
3162 }
3163 };
3164
stefanff483612015-12-21 03:14:00 -08003165 void ModifyVideoConfigs(
3166 VideoSendStream::Config* send_config,
3167 std::vector<VideoReceiveStream::Config>* receive_configs,
3168 VideoEncoderConfig* encoder_config) override {
perkjfa10b552016-10-02 23:45:26 -07003169 encoder_config->video_stream_factory =
3170 new rtc::RefCountedObject<VideoStreamFactory>();
perkj26091b12016-09-01 01:17:40 -07003171 video_encoder_config_all_streams_ = encoder_config->Copy();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003172 if (send_single_ssrc_first_)
perkjfa10b552016-10-02 23:45:26 -07003173 encoder_config->number_of_streams = 1;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003174 }
3175
stefanff483612015-12-21 03:14:00 -08003176 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003177 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003178 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003179 send_stream_ = send_stream;
3180 }
3181
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003182 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003183 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
3184 << (send_single_ssrc_first_ ? "first SSRC."
3185 : "SSRCs.");
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003186
3187 if (send_single_ssrc_first_) {
3188 // Set full simulcast and continue with the rest of the SSRCs.
stefanff483612015-12-21 03:14:00 -08003189 send_stream_->ReconfigureVideoEncoder(
perkj26091b12016-09-01 01:17:40 -07003190 std::move(video_encoder_config_all_streams_));
Peter Boström5811a392015-12-10 13:02:50 +01003191 EXPECT_TRUE(Wait()) << "Timed out while waiting on additional SSRCs.";
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003192 }
3193 }
3194
3195 private:
3196 std::map<uint32_t, bool> valid_ssrcs_;
3197 std::map<uint32_t, bool> is_observed_;
3198
3199 const size_t num_ssrcs_;
3200 const bool send_single_ssrc_first_;
3201
3202 size_t ssrcs_to_observe_;
3203 bool expect_single_ssrc_;
3204
3205 VideoSendStream* send_stream_;
stefanff483612015-12-21 03:14:00 -08003206 VideoEncoderConfig video_encoder_config_all_streams_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003207 } test(kVideoSendSsrcs, num_ssrcs, send_single_ssrc_first);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003208
stefane74eef12016-01-08 06:47:13 -08003209 RunBaseTest(&test);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003210}
3211
philipelccdfcca2017-10-23 12:42:17 +02003212TEST_P(EndToEndTest, ReportsSetEncoderRates) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003213 class EncoderRateStatsTest : public test::EndToEndTest,
3214 public test::FakeEncoder {
3215 public:
eladalon413ee9a2017-08-22 04:02:52 -07003216 explicit EncoderRateStatsTest(
3217 test::SingleThreadedTaskQueueForTesting* task_queue)
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003218 : EndToEndTest(kDefaultTimeoutMs),
sprang867fb522015-08-03 04:38:41 -07003219 FakeEncoder(Clock::GetRealTimeClock()),
eladalon413ee9a2017-08-22 04:02:52 -07003220 task_queue_(task_queue),
sprang867fb522015-08-03 04:38:41 -07003221 send_stream_(nullptr),
3222 bitrate_kbps_(0) {}
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003223
stefanff483612015-12-21 03:14:00 -08003224 void OnVideoStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003225 VideoSendStream* send_stream,
3226 const std::vector<VideoReceiveStream*>& receive_streams) override {
3227 send_stream_ = send_stream;
3228 }
3229
stefanff483612015-12-21 03:14:00 -08003230 void ModifyVideoConfigs(
3231 VideoSendStream::Config* send_config,
3232 std::vector<VideoReceiveStream::Config>* receive_configs,
3233 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003234 send_config->encoder_settings.encoder = this;
kwibergaf476c72016-11-28 15:21:39 -08003235 RTC_DCHECK_EQ(1, encoder_config->number_of_streams);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003236 }
3237
Erik Språng08127a92016-11-16 16:41:30 +01003238 int32_t SetRateAllocation(const BitrateAllocation& rate_allocation,
3239 uint32_t framerate) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003240 // Make sure not to trigger on any default zero bitrates.
Erik Språng08127a92016-11-16 16:41:30 +01003241 if (rate_allocation.get_sum_bps() == 0)
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003242 return 0;
Peter Boströmf2f82832015-05-01 13:00:41 +02003243 rtc::CritScope lock(&crit_);
Erik Språng08127a92016-11-16 16:41:30 +01003244 bitrate_kbps_ = rate_allocation.get_sum_kbps();
Peter Boström5811a392015-12-10 13:02:50 +01003245 observation_complete_.Set();
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003246 return 0;
3247 }
3248
3249 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003250 ASSERT_TRUE(Wait())
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003251 << "Timed out while waiting for encoder SetRates() call.";
eladalon413ee9a2017-08-22 04:02:52 -07003252
3253 task_queue_->SendTask([this]() {
3254 WaitForEncoderTargetBitrateMatchStats();
3255 send_stream_->Stop();
3256 WaitForStatsReportZeroTargetBitrate();
3257 send_stream_->Start();
3258 WaitForEncoderTargetBitrateMatchStats();
3259 });
perkjf5b2e512016-07-05 08:34:04 -07003260 }
3261
3262 void WaitForEncoderTargetBitrateMatchStats() {
Peter Boström5811a392015-12-10 13:02:50 +01003263 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003264 VideoSendStream::Stats stats = send_stream_->GetStats();
3265 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003266 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003267 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
3268 static_cast<int>(bitrate_kbps_)) {
3269 return;
3270 }
3271 }
3272 SleepMs(1);
3273 }
3274 FAIL()
3275 << "Timed out waiting for stats reporting the currently set bitrate.";
3276 }
3277
perkjf5b2e512016-07-05 08:34:04 -07003278 void WaitForStatsReportZeroTargetBitrate() {
3279 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
3280 if (send_stream_->GetStats().target_media_bitrate_bps == 0) {
3281 return;
3282 }
3283 SleepMs(1);
3284 }
3285 FAIL() << "Timed out waiting for stats reporting zero bitrate.";
3286 }
3287
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003288 private:
eladalon413ee9a2017-08-22 04:02:52 -07003289 test::SingleThreadedTaskQueueForTesting* const task_queue_;
stefanf116bd02015-10-27 08:29:42 -07003290 rtc::CriticalSection crit_;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003291 VideoSendStream* send_stream_;
danilchapa37de392017-09-09 04:17:22 -07003292 uint32_t bitrate_kbps_ RTC_GUARDED_BY(crit_);
eladalon413ee9a2017-08-22 04:02:52 -07003293 } test(&task_queue_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003294
stefane74eef12016-01-08 06:47:13 -08003295 RunBaseTest(&test);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003296}
3297
philipelccdfcca2017-10-23 12:42:17 +02003298TEST_P(EndToEndTest, GetStats) {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00003299 static const int kStartBitrateBps = 3000000;
Peter Boströmdef398832015-05-27 17:59:11 +02003300 static const int kExpectedRenderDelayMs = 20;
tommi2e82f382016-06-21 00:26:43 -07003301
3302 class ReceiveStreamRenderer : public rtc::VideoSinkInterface<VideoFrame> {
3303 public:
3304 ReceiveStreamRenderer() {}
3305
3306 private:
3307 void OnFrame(const VideoFrame& video_frame) override {}
3308 };
3309
nissed30a1112016-04-18 05:15:22 -07003310 class StatsObserver : public test::EndToEndTest,
3311 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003312 public:
stefanf116bd02015-10-27 08:29:42 -07003313 StatsObserver()
3314 : EndToEndTest(kLongTimeoutMs),
Peter Boströmc6e16e32016-02-05 14:15:53 +01003315 encoder_(Clock::GetRealTimeClock(), 10),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00003316 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003317 expected_send_ssrcs_(),
Peter Boström5811a392015-12-10 13:02:50 +01003318 check_stats_event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003319
3320 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003321 Action OnSendRtp(const uint8_t* packet, size_t length) override {
sprangcd349d92016-07-13 09:11:28 -07003322 // Drop every 25th packet => 4% loss.
3323 static const int kPacketLossFrac = 25;
3324 RTPHeader header;
3325 RtpUtility::RtpHeaderParser parser(packet, length);
3326 if (parser.Parse(&header) &&
3327 expected_send_ssrcs_.find(header.ssrc) !=
3328 expected_send_ssrcs_.end() &&
3329 header.sequenceNumber % kPacketLossFrac == 0) {
3330 return DROP_PACKET;
3331 }
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 OnSendRtcp(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
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003341 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01003342 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003343 return SEND_PACKET;
3344 }
3345
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003346 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01003347 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003348 return SEND_PACKET;
3349 }
3350
nissed30a1112016-04-18 05:15:22 -07003351 void OnFrame(const VideoFrame& video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003352 // Ensure that we have at least 5ms send side delay.
nissed30a1112016-04-18 05:15:22 -07003353 SleepMs(5);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003354 }
3355
3356 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003357 for (size_t i = 0; i < receive_streams_.size(); ++i) {
3358 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
3359 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003360
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003361 // Make sure all fields have been populated.
3362 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
3363 // always filled for all receivers.
3364 receive_stats_filled_["IncomingRate"] |=
3365 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003366
Peter Boströmb7d9a972015-12-18 16:01:11 +01003367 send_stats_filled_["DecoderImplementationName"] |=
3368 stats.decoder_implementation_name ==
3369 test::FakeDecoder::kImplementationName;
Peter Boströmdef398832015-05-27 17:59:11 +02003370 receive_stats_filled_["RenderDelayAsHighAsExpected"] |=
3371 stats.render_delay_ms >= kExpectedRenderDelayMs;
3372
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003373 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003374
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003375 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003376
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003377 receive_stats_filled_["StatisticsUpdated"] |=
srte186d9c32017-08-04 05:03:53 -07003378 stats.rtcp_stats.packets_lost != 0 ||
3379 stats.rtcp_stats.extended_highest_sequence_number != 0 ||
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003380 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003381
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003382 receive_stats_filled_["DataCountersUpdated"] |=
3383 stats.rtp_stats.transmitted.payload_bytes != 0 ||
3384 stats.rtp_stats.fec.packets != 0 ||
3385 stats.rtp_stats.transmitted.header_bytes != 0 ||
3386 stats.rtp_stats.transmitted.packets != 0 ||
3387 stats.rtp_stats.transmitted.padding_bytes != 0 ||
3388 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003389
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003390 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003391 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003392
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003393 receive_stats_filled_["FrameCounts"] |=
3394 stats.frame_counts.key_frames != 0 ||
3395 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00003396
pbosbb36fdf2015-07-09 07:48:14 -07003397 receive_stats_filled_["CName"] |= !stats.c_name.empty();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00003398
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003399 receive_stats_filled_["RtcpPacketTypeCount"] |=
3400 stats.rtcp_packet_type_counts.fir_packets != 0 ||
3401 stats.rtcp_packet_type_counts.nack_packets != 0 ||
3402 stats.rtcp_packet_type_counts.pli_packets != 0 ||
3403 stats.rtcp_packet_type_counts.nack_requests != 0 ||
3404 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbosf42376c2015-08-28 07:35:32 -07003405
3406 assert(stats.current_payload_type == -1 ||
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003407 stats.current_payload_type == kFakeVideoSendPayloadType);
pbosf42376c2015-08-28 07:35:32 -07003408 receive_stats_filled_["IncomingPayloadType"] |=
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003409 stats.current_payload_type == kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003410 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003411
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003412 return AllStatsFilled(receive_stats_filled_);
3413 }
3414
3415 bool CheckSendStats() {
Peter Boström74f6e9e2016-04-04 17:56:10 +02003416 RTC_DCHECK(send_stream_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003417 VideoSendStream::Stats stats = send_stream_->GetStats();
3418
philipel20d05a92016-12-19 04:17:27 -08003419 size_t expected_num_streams = kNumSsrcs + expected_send_ssrcs_.size();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003420 send_stats_filled_["NumStreams"] |=
philipel20d05a92016-12-19 04:17:27 -08003421 stats.substreams.size() == expected_num_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003422
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00003423 send_stats_filled_["CpuOveruseMetrics"] |=
Peter Boströme4499152016-02-05 11:13:28 +01003424 stats.avg_encode_time_ms != 0 && stats.encode_usage_percent != 0;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00003425
Peter Boströmb7d9a972015-12-18 16:01:11 +01003426 send_stats_filled_["EncoderImplementationName"] |=
3427 stats.encoder_implementation_name ==
3428 test::FakeEncoder::kImplementationName;
3429
Pera48ddb72016-09-29 11:48:50 +02003430 send_stats_filled_["EncoderPreferredBitrate"] |=
3431 stats.preferred_media_bitrate_bps > 0;
3432
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003433 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003434 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003435 it != stats.substreams.end(); ++it) {
sprangcd349d92016-07-13 09:11:28 -07003436 if (expected_send_ssrcs_.find(it->first) == expected_send_ssrcs_.end())
3437 continue; // Probably RTX.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003438
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003439 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003440 stats.input_frame_rate != 0;
3441
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003442 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003443
3444 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
srte186d9c32017-08-04 05:03:53 -07003445 stream_stats.rtcp_stats.packets_lost != 0 ||
3446 stream_stats.rtcp_stats.extended_highest_sequence_number != 0 ||
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003447 stream_stats.rtcp_stats.fraction_lost != 0;
3448
3449 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00003450 stream_stats.rtp_stats.fec.packets != 0 ||
3451 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
3452 stream_stats.rtp_stats.retransmitted.packets != 0 ||
3453 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003454
sprangcd349d92016-07-13 09:11:28 -07003455 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Total",
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003456 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00003457 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003458
sprangcd349d92016-07-13 09:11:28 -07003459 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Retransmit",
3460 it->first)] |=
3461 stream_stats.retransmit_bitrate_bps != 0;
3462
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003463 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00003464 stream_stats.frame_counts.delta_frames != 0 ||
3465 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003466
3467 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
3468 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00003469
3470 send_stats_filled_[CompoundKey("Delay", it->first)] |=
3471 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003472
3473 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
3474 // report dropped packets.
3475 send_stats_filled_["RtcpPacketTypeCount"] |=
3476 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
3477 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
3478 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
3479 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
3480 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003481 }
3482
3483 return AllStatsFilled(send_stats_filled_);
3484 }
3485
3486 std::string CompoundKey(const char* name, uint32_t ssrc) {
3487 std::ostringstream oss;
3488 oss << name << "_" << ssrc;
3489 return oss.str();
3490 }
3491
3492 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
sprangcd349d92016-07-13 09:11:28 -07003493 for (const auto& stat : stats_map) {
3494 if (!stat.second)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003495 return false;
3496 }
3497 return true;
3498 }
3499
eladalon413ee9a2017-08-22 04:02:52 -07003500 test::PacketTransport* CreateSendTransport(
3501 test::SingleThreadedTaskQueueForTesting* task_queue,
3502 Call* sender_call) override {
stefane74eef12016-01-08 06:47:13 -08003503 FakeNetworkPipe::Config network_config;
3504 network_config.loss_percent = 5;
eladalon413ee9a2017-08-22 04:02:52 -07003505 return new test::PacketTransport(task_queue, sender_call, this,
minyue20c84cc2017-04-10 16:57:57 -07003506 test::PacketTransport::kSender,
3507 payload_type_map_, network_config);
stefane74eef12016-01-08 06:47:13 -08003508 }
3509
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003510 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00003511 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01003512 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00003513 return config;
3514 }
3515
perkjfa10b552016-10-02 23:45:26 -07003516 // This test use other VideoStream settings than the the default settings
3517 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3518 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3519 // in ModifyVideoConfigs.
3520 class VideoStreamFactory
3521 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3522 public:
3523 VideoStreamFactory() {}
3524
3525 private:
3526 std::vector<VideoStream> CreateEncoderStreams(
3527 int width,
3528 int height,
3529 const VideoEncoderConfig& encoder_config) override {
3530 std::vector<VideoStream> streams =
3531 test::CreateVideoStreams(width, height, encoder_config);
3532 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
3533 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3534 streams[i].min_bitrate_bps = 10000;
3535 streams[i].target_bitrate_bps = 15000;
3536 streams[i].max_bitrate_bps = 20000;
3537 }
3538 return streams;
3539 }
3540 };
3541
stefanff483612015-12-21 03:14:00 -08003542 void ModifyVideoConfigs(
3543 VideoSendStream::Config* send_config,
3544 std::vector<VideoReceiveStream::Config>* receive_configs,
3545 VideoEncoderConfig* encoder_config) override {
perkjfa10b552016-10-02 23:45:26 -07003546 encoder_config->video_stream_factory =
3547 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003548 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003549 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003550
sprangcd349d92016-07-13 09:11:28 -07003551 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
3552 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
3553
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003554 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003555 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003556 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003557 expected_receive_ssrcs_.push_back(
3558 (*receive_configs)[i].rtp.remote_ssrc);
Peter Boströmdef398832015-05-27 17:59:11 +02003559 (*receive_configs)[i].render_delay_ms = kExpectedRenderDelayMs;
tommi2e82f382016-06-21 00:26:43 -07003560 (*receive_configs)[i].renderer = &receive_stream_renderer_;
sprangcd349d92016-07-13 09:11:28 -07003561 (*receive_configs)[i].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
3562
brandtr14742122017-01-27 04:53:07 -08003563 (*receive_configs)[i].rtp.rtx_ssrc = kSendRtxSsrcs[i];
nisse26e3abb2017-08-25 04:44:25 -07003564 (*receive_configs)[i]
3565 .rtp.rtx_associated_payload_types[kSendRtxPayloadType] =
3566 kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003567 }
sprangcd349d92016-07-13 09:11:28 -07003568
3569 for (size_t i = 0; i < kNumSsrcs; ++i)
3570 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
3571
Peter Boströmc6e16e32016-02-05 14:15:53 +01003572 // Use a delayed encoder to make sure we see CpuOveruseMetrics stats that
3573 // are non-zero.
3574 send_config->encoder_settings.encoder = &encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003575 }
3576
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003577 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00003578
stefanff483612015-12-21 03:14:00 -08003579 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003580 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003581 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003582 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003583 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003584 }
3585
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003586 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003587 Clock* clock = Clock::GetRealTimeClock();
3588 int64_t now = clock->TimeInMilliseconds();
3589 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
3590 bool receive_ok = false;
3591 bool send_ok = false;
3592
3593 while (now < stop_time) {
3594 if (!receive_ok)
3595 receive_ok = CheckReceiveStats();
3596 if (!send_ok)
3597 send_ok = CheckSendStats();
3598
3599 if (receive_ok && send_ok)
3600 return;
3601
3602 int64_t time_until_timout_ = stop_time - now;
3603 if (time_until_timout_ > 0)
Peter Boström5811a392015-12-10 13:02:50 +01003604 check_stats_event_.Wait(time_until_timout_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003605 now = clock->TimeInMilliseconds();
3606 }
3607
3608 ADD_FAILURE() << "Timed out waiting for filled stats.";
3609 for (std::map<std::string, bool>::const_iterator it =
3610 receive_stats_filled_.begin();
eladalon413ee9a2017-08-22 04:02:52 -07003611 it != receive_stats_filled_.end(); ++it) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003612 if (!it->second) {
3613 ADD_FAILURE() << "Missing receive stats: " << it->first;
3614 }
3615 }
3616
3617 for (std::map<std::string, bool>::const_iterator it =
3618 send_stats_filled_.begin();
eladalon413ee9a2017-08-22 04:02:52 -07003619 it != send_stats_filled_.end(); ++it) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003620 if (!it->second) {
3621 ADD_FAILURE() << "Missing send stats: " << it->first;
3622 }
3623 }
3624 }
3625
Peter Boströmc6e16e32016-02-05 14:15:53 +01003626 test::DelayedEncoder encoder_;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003627 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003628 std::map<std::string, bool> receive_stats_filled_;
3629
3630 VideoSendStream* send_stream_;
3631 std::map<std::string, bool> send_stats_filled_;
3632
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003633 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003634 std::set<uint32_t> expected_send_ssrcs_;
3635 std::string expected_cname_;
3636
Peter Boström5811a392015-12-10 13:02:50 +01003637 rtc::Event check_stats_event_;
tommi2e82f382016-06-21 00:26:43 -07003638 ReceiveStreamRenderer receive_stream_renderer_;
stefanf116bd02015-10-27 08:29:42 -07003639 } test;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003640
stefane74eef12016-01-08 06:47:13 -08003641 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003642}
3643
philipelccdfcca2017-10-23 12:42:17 +02003644TEST_P(EndToEndTest, TimingFramesAreReported) {
ilnik2edc6842017-07-06 03:06:50 -07003645 static const int kExtensionId = 5;
3646
3647 class StatsObserver : public test::EndToEndTest {
3648 public:
3649 StatsObserver() : EndToEndTest(kLongTimeoutMs) {}
3650
3651 private:
ilnik2edc6842017-07-06 03:06:50 -07003652 void ModifyVideoConfigs(
3653 VideoSendStream::Config* send_config,
3654 std::vector<VideoReceiveStream::Config>* receive_configs,
3655 VideoEncoderConfig* encoder_config) override {
3656 send_config->rtp.extensions.clear();
3657 send_config->rtp.extensions.push_back(
3658 RtpExtension(RtpExtension::kVideoTimingUri, kExtensionId));
3659 for (size_t i = 0; i < receive_configs->size(); ++i) {
3660 (*receive_configs)[i].rtp.extensions.clear();
3661 (*receive_configs)[i].rtp.extensions.push_back(
3662 RtpExtension(RtpExtension::kVideoTimingUri, kExtensionId));
3663 }
3664 }
3665
3666 void OnVideoStreamsCreated(
3667 VideoSendStream* send_stream,
3668 const std::vector<VideoReceiveStream*>& receive_streams) override {
3669 receive_streams_ = receive_streams;
3670 }
3671
3672 void PerformTest() override {
3673 // No frames reported initially.
3674 for (size_t i = 0; i < receive_streams_.size(); ++i) {
ilnik75204c52017-09-04 03:35:40 -07003675 EXPECT_FALSE(receive_streams_[i]->GetStats().timing_frame_info);
ilnik2edc6842017-07-06 03:06:50 -07003676 }
3677 // Wait for at least one timing frame to be sent with 100ms grace period.
3678 SleepMs(kDefaultTimingFramesDelayMs + 100);
3679 // Check that timing frames are reported for each stream.
3680 for (size_t i = 0; i < receive_streams_.size(); ++i) {
ilnik75204c52017-09-04 03:35:40 -07003681 EXPECT_TRUE(receive_streams_[i]->GetStats().timing_frame_info);
ilnik2edc6842017-07-06 03:06:50 -07003682 }
3683 }
3684
3685 std::vector<VideoReceiveStream*> receive_streams_;
3686 } test;
3687
3688 RunBaseTest(&test);
3689}
3690
sprang1a646ee2016-12-01 06:34:11 -08003691class RtcpXrObserver : public test::EndToEndTest {
3692 public:
sprang44b3ef62017-01-13 07:30:25 -08003693 RtcpXrObserver(bool enable_rrtr, bool enable_target_bitrate)
sprang1a646ee2016-12-01 06:34:11 -08003694 : EndToEndTest(test::CallTest::kDefaultTimeoutMs),
3695 enable_rrtr_(enable_rrtr),
sprang44b3ef62017-01-13 07:30:25 -08003696 enable_target_bitrate_(enable_target_bitrate),
sprang1a646ee2016-12-01 06:34:11 -08003697 sent_rtcp_sr_(0),
3698 sent_rtcp_rr_(0),
3699 sent_rtcp_rrtr_(0),
3700 sent_rtcp_target_bitrate_(false),
3701 sent_rtcp_dlrr_(0) {}
3702
3703 private:
3704 // Receive stream should send RR packets (and RRTR packets if enabled).
3705 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
3706 rtc::CritScope lock(&crit_);
3707 test::RtcpPacketParser parser;
3708 EXPECT_TRUE(parser.Parse(packet, length));
3709
3710 sent_rtcp_rr_ += parser.receiver_report()->num_packets();
3711 EXPECT_EQ(0, parser.sender_report()->num_packets());
3712 EXPECT_GE(1, parser.xr()->num_packets());
3713 if (parser.xr()->num_packets() > 0) {
3714 if (parser.xr()->rrtr())
3715 ++sent_rtcp_rrtr_;
3716 EXPECT_FALSE(parser.xr()->dlrr());
3717 }
3718
3719 return SEND_PACKET;
3720 }
3721 // Send stream should send SR packets (and DLRR packets if enabled).
3722 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
3723 rtc::CritScope lock(&crit_);
3724 test::RtcpPacketParser parser;
3725 EXPECT_TRUE(parser.Parse(packet, length));
3726
3727 sent_rtcp_sr_ += parser.sender_report()->num_packets();
3728 EXPECT_LE(parser.xr()->num_packets(), 1);
3729 if (parser.xr()->num_packets() > 0) {
3730 EXPECT_FALSE(parser.xr()->rrtr());
3731 if (parser.xr()->dlrr())
3732 ++sent_rtcp_dlrr_;
3733 if (parser.xr()->target_bitrate())
3734 sent_rtcp_target_bitrate_ = true;
3735 }
3736
3737 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
3738 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve &&
sprang44b3ef62017-01-13 07:30:25 -08003739 (sent_rtcp_target_bitrate_ || !enable_target_bitrate_)) {
sprang1a646ee2016-12-01 06:34:11 -08003740 if (enable_rrtr_) {
3741 EXPECT_GT(sent_rtcp_rrtr_, 0);
3742 EXPECT_GT(sent_rtcp_dlrr_, 0);
3743 } else {
3744 EXPECT_EQ(sent_rtcp_rrtr_, 0);
3745 EXPECT_EQ(sent_rtcp_dlrr_, 0);
3746 }
sprang44b3ef62017-01-13 07:30:25 -08003747 EXPECT_EQ(enable_target_bitrate_, sent_rtcp_target_bitrate_);
sprang1a646ee2016-12-01 06:34:11 -08003748 observation_complete_.Set();
3749 }
3750 return SEND_PACKET;
3751 }
3752
3753 void ModifyVideoConfigs(
3754 VideoSendStream::Config* send_config,
3755 std::vector<VideoReceiveStream::Config>* receive_configs,
3756 VideoEncoderConfig* encoder_config) override {
sprang44b3ef62017-01-13 07:30:25 -08003757 if (enable_target_bitrate_) {
3758 // TargetBitrate only signaled for screensharing.
3759 encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
3760 }
sprang1a646ee2016-12-01 06:34:11 -08003761 (*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
3762 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
3763 enable_rrtr_;
3764 }
3765
3766 void PerformTest() override {
3767 EXPECT_TRUE(Wait())
3768 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
3769 }
3770
3771 static const int kNumRtcpReportPacketsToObserve = 5;
3772
3773 rtc::CriticalSection crit_;
sprang44b3ef62017-01-13 07:30:25 -08003774 const bool enable_rrtr_;
3775 const bool enable_target_bitrate_;
sprang1a646ee2016-12-01 06:34:11 -08003776 int sent_rtcp_sr_;
danilchapa37de392017-09-09 04:17:22 -07003777 int sent_rtcp_rr_ RTC_GUARDED_BY(&crit_);
3778 int sent_rtcp_rrtr_ RTC_GUARDED_BY(&crit_);
3779 bool sent_rtcp_target_bitrate_ RTC_GUARDED_BY(&crit_);
sprang1a646ee2016-12-01 06:34:11 -08003780 int sent_rtcp_dlrr_;
3781};
3782
philipelccdfcca2017-10-23 12:42:17 +02003783TEST_P(EndToEndTest, TestExtendedReportsWithRrtrWithoutTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003784 RtcpXrObserver test(true, false);
sprang1a646ee2016-12-01 06:34:11 -08003785 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003786}
3787
philipelccdfcca2017-10-23 12:42:17 +02003788TEST_P(EndToEndTest, TestExtendedReportsWithoutRrtrWithoutTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003789 RtcpXrObserver test(false, false);
3790 RunBaseTest(&test);
3791}
3792
philipelccdfcca2017-10-23 12:42:17 +02003793TEST_P(EndToEndTest, TestExtendedReportsWithRrtrWithTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003794 RtcpXrObserver test(true, true);
3795 RunBaseTest(&test);
3796}
3797
philipelccdfcca2017-10-23 12:42:17 +02003798TEST_P(EndToEndTest, TestExtendedReportsWithoutRrtrWithTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003799 RtcpXrObserver test(false, true);
sprang1a646ee2016-12-01 06:34:11 -08003800 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003801}
3802
philipelccdfcca2017-10-23 12:42:17 +02003803TEST_P(EndToEndTest, TestReceivedRtpPacketStats) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003804 static const size_t kNumRtpPacketsToSend = 5;
3805 class ReceivedRtpStatsObserver : public test::EndToEndTest {
3806 public:
3807 ReceivedRtpStatsObserver()
3808 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00003809 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003810 sent_rtp_(0) {}
3811
3812 private:
stefanff483612015-12-21 03:14:00 -08003813 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003814 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003815 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003816 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003817 }
3818
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003819 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003820 if (sent_rtp_ >= kNumRtpPacketsToSend) {
3821 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00003822 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
Peter Boström5811a392015-12-10 13:02:50 +01003823 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003824 }
3825 return DROP_PACKET;
3826 }
3827 ++sent_rtp_;
3828 return SEND_PACKET;
3829 }
3830
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003831 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003832 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003833 << "Timed out while verifying number of received RTP packets.";
3834 }
3835
3836 VideoReceiveStream* receive_stream_;
3837 uint32_t sent_rtp_;
3838 } test;
3839
stefane74eef12016-01-08 06:47:13 -08003840 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003841}
3842
philipelccdfcca2017-10-23 12:42:17 +02003843TEST_P(EndToEndTest, SendsSetSsrc) {
philipel266f0a42016-11-28 08:49:07 -08003844 TestSendsSetSsrcs(1, false);
3845}
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003846
philipelccdfcca2017-10-23 12:42:17 +02003847TEST_P(EndToEndTest, SendsSetSimulcastSsrcs) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003848 TestSendsSetSsrcs(kNumSsrcs, false);
3849}
3850
philipelccdfcca2017-10-23 12:42:17 +02003851TEST_P(EndToEndTest, CanSwitchToUseAllSsrcs) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003852 TestSendsSetSsrcs(kNumSsrcs, true);
3853}
3854
philipelccdfcca2017-10-23 12:42:17 +02003855TEST_P(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003856 class ObserveRedundantPayloads: public test::EndToEndTest {
3857 public:
3858 ObserveRedundantPayloads()
3859 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003860 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003861 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
3862 }
3863 }
3864
3865 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003866 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003867 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003868 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003869
3870 if (!registered_rtx_ssrc_[header.ssrc])
3871 return SEND_PACKET;
3872
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003873 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003874 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003875 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003876
3877 if (!packet_is_redundant_payload)
3878 return SEND_PACKET;
3879
3880 if (!observed_redundant_retransmission_[header.ssrc]) {
3881 observed_redundant_retransmission_[header.ssrc] = true;
3882 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01003883 observation_complete_.Set();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003884 }
3885
3886 return SEND_PACKET;
3887 }
3888
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003889 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003890
perkjfa10b552016-10-02 23:45:26 -07003891 // This test use other VideoStream settings than the the default settings
3892 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3893 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3894 // in ModifyVideoConfigs.
3895 class VideoStreamFactory
3896 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3897 public:
3898 VideoStreamFactory() {}
3899
3900 private:
3901 std::vector<VideoStream> CreateEncoderStreams(
3902 int width,
3903 int height,
3904 const VideoEncoderConfig& encoder_config) override {
3905 std::vector<VideoStream> streams =
3906 test::CreateVideoStreams(width, height, encoder_config);
3907 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
3908 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3909 streams[i].min_bitrate_bps = 10000;
3910 streams[i].target_bitrate_bps = 15000;
3911 streams[i].max_bitrate_bps = 20000;
3912 }
3913 return streams;
3914 }
3915 };
3916
stefanff483612015-12-21 03:14:00 -08003917 void ModifyVideoConfigs(
3918 VideoSendStream::Config* send_config,
3919 std::vector<VideoReceiveStream::Config>* receive_configs,
3920 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003921 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
perkjfa10b552016-10-02 23:45:26 -07003922 encoder_config->video_stream_factory =
3923 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003924 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003925
3926 for (size_t i = 0; i < kNumSsrcs; ++i)
3927 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00003928
3929 // Significantly higher than max bitrates for all video streams -> forcing
3930 // padding to trigger redundant padding on all RTX SSRCs.
3931 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003932 }
3933
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003934 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003935 EXPECT_TRUE(Wait())
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003936 << "Timed out while waiting for redundant payloads on all SSRCs.";
3937 }
3938
3939 private:
3940 size_t ssrcs_to_observe_;
3941 std::map<uint32_t, bool> observed_redundant_retransmission_;
3942 std::map<uint32_t, bool> registered_rtx_ssrc_;
3943 } test;
3944
stefane74eef12016-01-08 06:47:13 -08003945 RunBaseTest(&test);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003946}
3947
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003948void EndToEndTest::TestRtpStatePreservation(bool use_rtx,
3949 bool provoke_rtcpsr_before_rtp) {
brandtr5e171752017-05-23 03:32:16 -07003950 // This test uses other VideoStream settings than the the default settings
3951 // implemented in DefaultVideoStreamFactory. Therefore this test implements
perkjfa10b552016-10-02 23:45:26 -07003952 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3953 // in ModifyVideoConfigs.
3954 class VideoStreamFactory
3955 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3956 public:
3957 VideoStreamFactory() {}
3958
3959 private:
3960 std::vector<VideoStream> CreateEncoderStreams(
3961 int width,
3962 int height,
3963 const VideoEncoderConfig& encoder_config) override {
3964 std::vector<VideoStream> streams =
3965 test::CreateVideoStreams(width, height, encoder_config);
3966
3967 if (encoder_config.number_of_streams > 1) {
3968 // Lower bitrates so that all streams send initially.
kwibergaf476c72016-11-28 15:21:39 -08003969 RTC_DCHECK_EQ(3, encoder_config.number_of_streams);
perkjfa10b552016-10-02 23:45:26 -07003970 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3971 streams[i].min_bitrate_bps = 10000;
3972 streams[i].target_bitrate_bps = 15000;
3973 streams[i].max_bitrate_bps = 20000;
3974 }
3975 } else {
3976 // Use the same total bitrates when sending a single stream to avoid
3977 // lowering
3978 // the bitrate estimate and requiring a subsequent rampup.
3979 streams[0].min_bitrate_bps = 3 * 10000;
3980 streams[0].target_bitrate_bps = 3 * 15000;
3981 streams[0].max_bitrate_bps = 3 * 20000;
3982 }
3983 return streams;
3984 }
3985 };
3986
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003987 class RtpSequenceObserver : public test::RtpRtcpObserver {
3988 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003989 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003990 : test::RtpRtcpObserver(kDefaultTimeoutMs),
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003991 ssrcs_to_observe_(kNumSsrcs) {
3992 for (size_t i = 0; i < kNumSsrcs; ++i) {
danilchap32cd2c42016-08-01 06:58:34 -07003993 ssrc_is_rtx_[kVideoSendSsrcs[i]] = false;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003994 if (use_rtx)
danilchap32cd2c42016-08-01 06:58:34 -07003995 ssrc_is_rtx_[kSendRtxSsrcs[i]] = true;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003996 }
3997 }
3998
3999 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
Peter Boströmf2f82832015-05-01 13:00:41 +02004000 rtc::CritScope lock(&crit_);
danilchap34877ee2016-02-01 08:25:04 -08004001 ssrc_observed_.clear();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004002 ssrcs_to_observe_ = num_expected_ssrcs;
4003 }
4004
4005 private:
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004006 void ValidateTimestampGap(uint32_t ssrc,
4007 uint32_t timestamp,
4008 bool only_padding)
danilchapa37de392017-09-09 04:17:22 -07004009 RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004010 static const int32_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
4011 auto timestamp_it = last_observed_timestamp_.find(ssrc);
4012 if (timestamp_it == last_observed_timestamp_.end()) {
4013 EXPECT_FALSE(only_padding);
4014 last_observed_timestamp_[ssrc] = timestamp;
4015 } else {
4016 // Verify timestamps are reasonably close.
4017 uint32_t latest_observed = timestamp_it->second;
4018 // Wraparound handling is unnecessary here as long as an int variable
4019 // is used to store the result.
4020 int32_t timestamp_gap = timestamp - latest_observed;
4021 EXPECT_LE(std::abs(timestamp_gap), kMaxTimestampGap)
4022 << "Gap in timestamps (" << latest_observed << " -> " << timestamp
4023 << ") too large for SSRC: " << ssrc << ".";
4024 timestamp_it->second = timestamp;
4025 }
4026 }
4027
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004028 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004029 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00004030 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004031 const uint32_t ssrc = header.ssrc;
danilchap5c35cf92016-02-03 14:14:49 -08004032 const int64_t sequence_number =
4033 seq_numbers_unwrapper_.Unwrap(header.sequenceNumber);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004034 const uint32_t timestamp = header.timestamp;
danilchap34877ee2016-02-01 08:25:04 -08004035 const bool only_padding =
4036 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004037
danilchap32cd2c42016-08-01 06:58:34 -07004038 EXPECT_TRUE(ssrc_is_rtx_.find(ssrc) != ssrc_is_rtx_.end())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004039 << "Received SSRC that wasn't configured: " << ssrc;
4040
danilchap5c35cf92016-02-03 14:14:49 -08004041 static const int64_t kMaxSequenceNumberGap = 100;
4042 std::list<int64_t>* seq_numbers = &last_observed_seq_numbers_[ssrc];
4043 if (seq_numbers->empty()) {
4044 seq_numbers->push_back(sequence_number);
4045 } else {
4046 // We shouldn't get replays of previous sequence numbers.
4047 for (int64_t observed : *seq_numbers) {
4048 EXPECT_NE(observed, sequence_number)
4049 << "Received sequence number " << sequence_number
4050 << " for SSRC " << ssrc << " 2nd time.";
4051 }
4052 // Verify sequence numbers are reasonably close.
4053 int64_t latest_observed = seq_numbers->back();
4054 int64_t sequence_number_gap = sequence_number - latest_observed;
4055 EXPECT_LE(std::abs(sequence_number_gap), kMaxSequenceNumberGap)
4056 << "Gap in sequence numbers (" << latest_observed << " -> "
4057 << sequence_number << ") too large for SSRC: " << ssrc << ".";
4058 seq_numbers->push_back(sequence_number);
4059 if (seq_numbers->size() >= kMaxSequenceNumberGap) {
4060 seq_numbers->pop_front();
4061 }
4062 }
4063
danilchap32cd2c42016-08-01 06:58:34 -07004064 if (!ssrc_is_rtx_[ssrc]) {
4065 rtc::CritScope lock(&crit_);
4066 ValidateTimestampGap(ssrc, timestamp, only_padding);
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004067
danilchap32cd2c42016-08-01 06:58:34 -07004068 // Wait for media packets on all ssrcs.
4069 if (!ssrc_observed_[ssrc] && !only_padding) {
4070 ssrc_observed_[ssrc] = true;
4071 if (--ssrcs_to_observe_ == 0)
4072 observation_complete_.Set();
4073 }
danilchap34877ee2016-02-01 08:25:04 -08004074 }
4075
danilchapf4b9c772016-01-28 06:14:24 -08004076 return SEND_PACKET;
4077 }
4078
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004079 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
4080 test::RtcpPacketParser rtcp_parser;
4081 rtcp_parser.Parse(packet, length);
4082 if (rtcp_parser.sender_report()->num_packets() > 0) {
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02004083 uint32_t ssrc = rtcp_parser.sender_report()->sender_ssrc();
4084 uint32_t rtcp_timestamp = rtcp_parser.sender_report()->rtp_timestamp();
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004085
4086 rtc::CritScope lock(&crit_);
4087 ValidateTimestampGap(ssrc, rtcp_timestamp, false);
4088 }
4089 return SEND_PACKET;
4090 }
4091
danilchap5c35cf92016-02-03 14:14:49 -08004092 SequenceNumberUnwrapper seq_numbers_unwrapper_;
4093 std::map<uint32_t, std::list<int64_t>> last_observed_seq_numbers_;
danilchap34877ee2016-02-01 08:25:04 -08004094 std::map<uint32_t, uint32_t> last_observed_timestamp_;
danilchap32cd2c42016-08-01 06:58:34 -07004095 std::map<uint32_t, bool> ssrc_is_rtx_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004096
Peter Boströmf2f82832015-05-01 13:00:41 +02004097 rtc::CriticalSection crit_;
danilchapa37de392017-09-09 04:17:22 -07004098 size_t ssrcs_to_observe_ RTC_GUARDED_BY(crit_);
4099 std::map<uint32_t, bool> ssrc_observed_ RTC_GUARDED_BY(crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004100 } observer(use_rtx);
4101
eladalon413ee9a2017-08-22 04:02:52 -07004102 std::unique_ptr<test::PacketTransport> send_transport;
4103 std::unique_ptr<test::PacketTransport> receive_transport;
4104
philipel4fb651d2017-04-10 03:54:05 -07004105 Call::Config config(event_log_.get());
eladalon413ee9a2017-08-22 04:02:52 -07004106 VideoEncoderConfig one_stream;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004107
eladalon413ee9a2017-08-22 04:02:52 -07004108 task_queue_.SendTask([this, &observer, &send_transport, &receive_transport,
4109 &config, &one_stream, use_rtx]() {
4110 CreateCalls(config, config);
stefanf116bd02015-10-27 08:29:42 -07004111
eladalon413ee9a2017-08-22 04:02:52 -07004112 send_transport = rtc::MakeUnique<test::PacketTransport>(
4113 &task_queue_, sender_call_.get(), &observer,
4114 test::PacketTransport::kSender, payload_type_map_,
4115 FakeNetworkPipe::Config());
4116 receive_transport = rtc::MakeUnique<test::PacketTransport>(
4117 &task_queue_, nullptr, &observer, test::PacketTransport::kReceiver,
4118 payload_type_map_, FakeNetworkPipe::Config());
4119 send_transport->SetReceiver(receiver_call_->Receiver());
4120 receive_transport->SetReceiver(sender_call_->Receiver());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004121
eladalon413ee9a2017-08-22 04:02:52 -07004122 CreateSendConfig(kNumSsrcs, 0, 0, send_transport.get());
4123
4124 if (use_rtx) {
4125 for (size_t i = 0; i < kNumSsrcs; ++i) {
4126 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
4127 }
4128 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004129 }
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004130
eladalon413ee9a2017-08-22 04:02:52 -07004131 video_encoder_config_.video_stream_factory =
4132 new rtc::RefCountedObject<VideoStreamFactory>();
4133 // Use the same total bitrates when sending a single stream to avoid
4134 // lowering the bitrate estimate and requiring a subsequent rampup.
4135 one_stream = video_encoder_config_.Copy();
4136 // one_stream.streams.resize(1);
4137 one_stream.number_of_streams = 1;
4138 CreateMatchingReceiveConfigs(receive_transport.get());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004139
eladalon413ee9a2017-08-22 04:02:52 -07004140 CreateVideoStreams();
4141 CreateFrameGeneratorCapturer(30, 1280, 720);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004142
eladalon413ee9a2017-08-22 04:02:52 -07004143 Start();
4144 });
4145
Peter Boström5811a392015-12-10 13:02:50 +01004146 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004147 << "Timed out waiting for all SSRCs to send packets.";
4148
4149 // Test stream resetting more than once to make sure that the state doesn't
4150 // get set once (this could be due to using std::map::insert for instance).
4151 for (size_t i = 0; i < 3; ++i) {
eladalon413ee9a2017-08-22 04:02:52 -07004152 task_queue_.SendTask([&]() {
4153 frame_generator_capturer_->Stop();
4154 sender_call_->DestroyVideoSendStream(video_send_stream_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004155
eladalon413ee9a2017-08-22 04:02:52 -07004156 // Re-create VideoSendStream with only one stream.
4157 video_send_stream_ = sender_call_->CreateVideoSendStream(
4158 video_send_config_.Copy(), one_stream.Copy());
4159 video_send_stream_->Start();
4160 if (provoke_rtcpsr_before_rtp) {
4161 // Rapid Resync Request forces sending RTCP Sender Report back.
4162 // Using this request speeds up this test because then there is no need
4163 // to wait for a second for periodic Sender Report.
4164 rtcp::RapidResyncRequest force_send_sr_back_request;
4165 rtc::Buffer packet = force_send_sr_back_request.Build();
4166 static_cast<webrtc::test::DirectTransport*>(receive_transport.get())
4167 ->SendRtcp(packet.data(), packet.size());
4168 }
4169 CreateFrameGeneratorCapturer(30, 1280, 720);
4170 frame_generator_capturer_->Start();
4171 });
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004172
4173 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01004174 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004175
4176 // Reconfigure back to use all streams.
eladalon413ee9a2017-08-22 04:02:52 -07004177 task_queue_.SendTask([this]() {
4178 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
4179 });
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004180 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01004181 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004182 << "Timed out waiting for all SSRCs to send packets.";
4183
4184 // Reconfigure down to one stream.
eladalon413ee9a2017-08-22 04:02:52 -07004185 task_queue_.SendTask([this, &one_stream]() {
4186 video_send_stream_->ReconfigureVideoEncoder(one_stream.Copy());
4187 });
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004188 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01004189 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004190
4191 // Reconfigure back to use all streams.
eladalon413ee9a2017-08-22 04:02:52 -07004192 task_queue_.SendTask([this]() {
4193 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
4194 });
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004195 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01004196 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004197 << "Timed out waiting for all SSRCs to send packets.";
4198 }
4199
eladalon413ee9a2017-08-22 04:02:52 -07004200 task_queue_.SendTask([this, &send_transport, &receive_transport]() {
4201 Stop();
4202 DestroyStreams();
4203 send_transport.reset();
4204 receive_transport.reset();
4205 DestroyCalls();
4206 });
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004207}
4208
philipelccdfcca2017-10-23 12:42:17 +02004209TEST_P(EndToEndTest, RestartingSendStreamPreservesRtpState) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004210 TestRtpStatePreservation(false, false);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004211}
4212
philipelccdfcca2017-10-23 12:42:17 +02004213TEST_P(EndToEndTest, RestartingSendStreamPreservesRtpStatesWithRtx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004214 TestRtpStatePreservation(true, false);
4215}
4216
philipelccdfcca2017-10-23 12:42:17 +02004217TEST_P(EndToEndTest, RestartingSendStreamKeepsRtpAndRtcpTimestampsSynced) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004218 TestRtpStatePreservation(true, true);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004219}
4220
brandtreb806792017-05-31 07:46:56 -07004221// This test is flaky on linux_memcheck. Disable on all linux bots until
4222// flakyness has been fixed.
4223// https://bugs.chromium.org/p/webrtc/issues/detail?id=7737
4224#if defined(WEBRTC_LINUX)
philipelccdfcca2017-10-23 12:42:17 +02004225TEST_P(EndToEndTest, DISABLED_TestFlexfecRtpStatePreservation) {
brandtreb806792017-05-31 07:46:56 -07004226#else
philipelccdfcca2017-10-23 12:42:17 +02004227TEST_P(EndToEndTest, TestFlexfecRtpStatePreservation) {
brandtreb806792017-05-31 07:46:56 -07004228#endif
brandtr48d21a22017-05-30 02:32:12 -07004229 class RtpSequenceObserver : public test::RtpRtcpObserver {
4230 public:
4231 RtpSequenceObserver()
4232 : test::RtpRtcpObserver(kDefaultTimeoutMs),
4233 num_flexfec_packets_sent_(0) {}
4234
4235 void ResetPacketCount() {
4236 rtc::CritScope lock(&crit_);
4237 num_flexfec_packets_sent_ = 0;
4238 }
4239
4240 private:
4241 Action OnSendRtp(const uint8_t* packet, size_t length) override {
4242 rtc::CritScope lock(&crit_);
4243
4244 RTPHeader header;
4245 EXPECT_TRUE(parser_->Parse(packet, length, &header));
4246 const uint16_t sequence_number = header.sequenceNumber;
4247 const uint32_t timestamp = header.timestamp;
4248 const uint32_t ssrc = header.ssrc;
4249
4250 if (ssrc == kVideoSendSsrcs[0] || ssrc == kSendRtxSsrcs[0]) {
4251 return SEND_PACKET;
4252 }
4253 EXPECT_EQ(kFlexfecSendSsrc, ssrc) << "Unknown SSRC sent.";
4254
4255 ++num_flexfec_packets_sent_;
4256
4257 // If this is the first packet, we have nothing to compare to.
4258 if (!last_observed_sequence_number_) {
4259 last_observed_sequence_number_.emplace(sequence_number);
4260 last_observed_timestamp_.emplace(timestamp);
4261
4262 return SEND_PACKET;
4263 }
4264
4265 // Verify continuity and monotonicity of RTP sequence numbers.
4266 EXPECT_EQ(static_cast<uint16_t>(*last_observed_sequence_number_ + 1),
4267 sequence_number);
4268 last_observed_sequence_number_.emplace(sequence_number);
4269
4270 // Timestamps should be non-decreasing...
4271 const bool timestamp_is_same_or_newer =
4272 timestamp == *last_observed_timestamp_ ||
4273 IsNewerTimestamp(timestamp, *last_observed_timestamp_);
4274 EXPECT_TRUE(timestamp_is_same_or_newer);
4275 // ...but reasonably close in time.
4276 const int k10SecondsInRtpTimestampBase = 10 * kVideoPayloadTypeFrequency;
4277 EXPECT_TRUE(IsNewerTimestamp(
4278 *last_observed_timestamp_ + k10SecondsInRtpTimestampBase, timestamp));
4279 last_observed_timestamp_.emplace(timestamp);
4280
4281 // Pass test when enough packets have been let through.
4282 if (num_flexfec_packets_sent_ >= 10) {
4283 observation_complete_.Set();
4284 }
4285
4286 return SEND_PACKET;
4287 }
4288
danilchapa37de392017-09-09 04:17:22 -07004289 rtc::Optional<uint16_t> last_observed_sequence_number_
4290 RTC_GUARDED_BY(crit_);
4291 rtc::Optional<uint32_t> last_observed_timestamp_ RTC_GUARDED_BY(crit_);
4292 size_t num_flexfec_packets_sent_ RTC_GUARDED_BY(crit_);
brandtr48d21a22017-05-30 02:32:12 -07004293 rtc::CriticalSection crit_;
4294 } observer;
4295
eladalon05b07bb2017-08-24 07:40:16 -07004296 static constexpr int kFrameMaxWidth = 320;
4297 static constexpr int kFrameMaxHeight = 180;
4298 static constexpr int kFrameRate = 15;
eladalon413ee9a2017-08-22 04:02:52 -07004299
brandtr48d21a22017-05-30 02:32:12 -07004300 Call::Config config(event_log_.get());
brandtr48d21a22017-05-30 02:32:12 -07004301
eladalon413ee9a2017-08-22 04:02:52 -07004302 std::unique_ptr<test::PacketTransport> send_transport;
4303 std::unique_ptr<test::PacketTransport> receive_transport;
4304 std::unique_ptr<VideoEncoder> encoder;
brandtr48d21a22017-05-30 02:32:12 -07004305
eladalon413ee9a2017-08-22 04:02:52 -07004306 task_queue_.SendTask([&]() {
4307 CreateCalls(config, config);
brandtr48d21a22017-05-30 02:32:12 -07004308
eladalon413ee9a2017-08-22 04:02:52 -07004309 FakeNetworkPipe::Config lossy_delayed_link;
4310 lossy_delayed_link.loss_percent = 2;
4311 lossy_delayed_link.queue_delay_ms = 50;
brandtr48d21a22017-05-30 02:32:12 -07004312
eladalon413ee9a2017-08-22 04:02:52 -07004313 send_transport = rtc::MakeUnique<test::PacketTransport>(
4314 &task_queue_, sender_call_.get(), &observer,
4315 test::PacketTransport::kSender, payload_type_map_, lossy_delayed_link);
4316 send_transport->SetReceiver(receiver_call_->Receiver());
brandtr48d21a22017-05-30 02:32:12 -07004317
eladalon413ee9a2017-08-22 04:02:52 -07004318 FakeNetworkPipe::Config flawless_link;
4319 receive_transport = rtc::MakeUnique<test::PacketTransport>(
4320 &task_queue_, nullptr, &observer, test::PacketTransport::kReceiver,
4321 payload_type_map_, flawless_link);
4322 receive_transport->SetReceiver(sender_call_->Receiver());
brandtr48d21a22017-05-30 02:32:12 -07004323
eladalon413ee9a2017-08-22 04:02:52 -07004324 // For reduced flakyness, we use a real VP8 encoder together with NACK
4325 // and RTX.
4326 const int kNumVideoStreams = 1;
4327 const int kNumFlexfecStreams = 1;
4328 CreateSendConfig(kNumVideoStreams, 0, kNumFlexfecStreams,
4329 send_transport.get());
4330 encoder = rtc::WrapUnique(VP8Encoder::Create());
4331 video_send_config_.encoder_settings.encoder = encoder.get();
4332 video_send_config_.encoder_settings.payload_name = "VP8";
4333 video_send_config_.encoder_settings.payload_type = kVideoSendPayloadType;
4334 video_send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
4335 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
4336 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
brandtr48d21a22017-05-30 02:32:12 -07004337
eladalon413ee9a2017-08-22 04:02:52 -07004338 CreateMatchingReceiveConfigs(receive_transport.get());
4339 video_receive_configs_[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
4340 video_receive_configs_[0].rtp.rtx_ssrc = kSendRtxSsrcs[0];
nisse26e3abb2017-08-25 04:44:25 -07004341 video_receive_configs_[0]
4342 .rtp.rtx_associated_payload_types[kSendRtxPayloadType] =
4343 kVideoSendPayloadType;
brandtr48d21a22017-05-30 02:32:12 -07004344
eladalon413ee9a2017-08-22 04:02:52 -07004345 // The matching FlexFEC receive config is not created by
4346 // CreateMatchingReceiveConfigs since this is not a test::BaseTest.
4347 // Set up the receive config manually instead.
4348 FlexfecReceiveStream::Config flexfec_receive_config(
4349 receive_transport.get());
4350 flexfec_receive_config.payload_type =
4351 video_send_config_.rtp.flexfec.payload_type;
4352 flexfec_receive_config.remote_ssrc = video_send_config_.rtp.flexfec.ssrc;
4353 flexfec_receive_config.protected_media_ssrcs =
4354 video_send_config_.rtp.flexfec.protected_media_ssrcs;
4355 flexfec_receive_config.local_ssrc = kReceiverLocalVideoSsrc;
4356 flexfec_receive_config.transport_cc = true;
4357 flexfec_receive_config.rtp_header_extensions.emplace_back(
4358 RtpExtension::kTransportSequenceNumberUri,
4359 test::kTransportSequenceNumberExtensionId);
4360 flexfec_receive_configs_.push_back(flexfec_receive_config);
4361
4362 CreateFlexfecStreams();
4363 CreateVideoStreams();
4364
4365 // RTCP might be disabled if the network is "down".
4366 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
4367 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
4368
4369 CreateFrameGeneratorCapturer(kFrameRate, kFrameMaxWidth, kFrameMaxHeight);
4370
4371 Start();
4372 });
brandtr48d21a22017-05-30 02:32:12 -07004373
4374 // Initial test.
brandtr48d21a22017-05-30 02:32:12 -07004375 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for packets.";
4376
eladalon413ee9a2017-08-22 04:02:52 -07004377 task_queue_.SendTask([this, &observer]() {
4378 // Ensure monotonicity when the VideoSendStream is restarted.
4379 Stop();
4380 observer.ResetPacketCount();
4381 Start();
4382 });
4383
brandtr48d21a22017-05-30 02:32:12 -07004384 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for packets.";
4385
eladalon05b07bb2017-08-24 07:40:16 -07004386 task_queue_.SendTask([this, &observer]() {
eladalon413ee9a2017-08-22 04:02:52 -07004387 // Ensure monotonicity when the VideoSendStream is recreated.
4388 frame_generator_capturer_->Stop();
4389 sender_call_->DestroyVideoSendStream(video_send_stream_);
4390 observer.ResetPacketCount();
4391 video_send_stream_ = sender_call_->CreateVideoSendStream(
4392 video_send_config_.Copy(), video_encoder_config_.Copy());
4393 video_send_stream_->Start();
4394 CreateFrameGeneratorCapturer(kFrameRate, kFrameMaxWidth, kFrameMaxHeight);
4395 frame_generator_capturer_->Start();
4396 });
4397
brandtr48d21a22017-05-30 02:32:12 -07004398 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for packets.";
4399
4400 // Cleanup.
eladalon413ee9a2017-08-22 04:02:52 -07004401 task_queue_.SendTask([this, &send_transport, &receive_transport]() {
4402 Stop();
4403 DestroyStreams();
4404 send_transport.reset();
4405 receive_transport.reset();
4406 DestroyCalls();
4407 });
brandtr48d21a22017-05-30 02:32:12 -07004408}
4409
philipelccdfcca2017-10-23 12:42:17 +02004410TEST_P(EndToEndTest, RespectsNetworkState) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004411 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
4412 // down blocks until no more packets will be sent.
4413
4414 // Pacer will send from its packet list and then send required padding before
4415 // checking paused_ again. This should be enough for one round of pacing,
4416 // otherwise increase.
4417 static const int kNumAcceptedDowntimeRtp = 5;
4418 // A single RTCP may be in the pipeline.
4419 static const int kNumAcceptedDowntimeRtcp = 1;
4420 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
4421 public:
eladalon413ee9a2017-08-22 04:02:52 -07004422 explicit NetworkStateTest(
4423 test::SingleThreadedTaskQueueForTesting* task_queue)
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004424 : EndToEndTest(kDefaultTimeoutMs),
4425 FakeEncoder(Clock::GetRealTimeClock()),
eladalon413ee9a2017-08-22 04:02:52 -07004426 task_queue_(task_queue),
Peter Boström5811a392015-12-10 13:02:50 +01004427 encoded_frames_(false, false),
4428 packet_event_(false, false),
sprang867fb522015-08-03 04:38:41 -07004429 sender_call_(nullptr),
4430 receiver_call_(nullptr),
Jelena Marusiccd670222015-07-16 09:30:09 +02004431 sender_state_(kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004432 sender_rtp_(0),
stefan9e117c5e12017-08-16 08:16:25 -07004433 sender_padding_(0),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004434 sender_rtcp_(0),
4435 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004436 down_frames_(0) {}
4437
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004438 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02004439 rtc::CritScope lock(&test_crit_);
stefan9e117c5e12017-08-16 08:16:25 -07004440 RTPHeader header;
4441 EXPECT_TRUE(parser_->Parse(packet, length, &header));
4442 if (length == header.headerLength + header.paddingLength)
4443 ++sender_padding_;
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004444 ++sender_rtp_;
Peter Boström5811a392015-12-10 13:02:50 +01004445 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004446 return SEND_PACKET;
4447 }
4448
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004449 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02004450 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004451 ++sender_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01004452 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004453 return SEND_PACKET;
4454 }
4455
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004456 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004457 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
4458 return SEND_PACKET;
4459 }
4460
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004461 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02004462 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004463 ++receiver_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01004464 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004465 return SEND_PACKET;
4466 }
4467
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004468 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004469 sender_call_ = sender_call;
4470 receiver_call_ = receiver_call;
4471 }
4472
stefanff483612015-12-21 03:14:00 -08004473 void ModifyVideoConfigs(
4474 VideoSendStream::Config* send_config,
4475 std::vector<VideoReceiveStream::Config>* receive_configs,
4476 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004477 send_config->encoder_settings.encoder = this;
4478 }
4479
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004480 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01004481 EXPECT_TRUE(encoded_frames_.Wait(kDefaultTimeoutMs))
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004482 << "No frames received by the encoder.";
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004483
eladalon413ee9a2017-08-22 04:02:52 -07004484 task_queue_->SendTask([this]() {
4485 // Wait for packets from both sender/receiver.
4486 WaitForPacketsOrSilence(false, false);
skvlad7a43d252016-03-22 15:32:27 -07004487
eladalon413ee9a2017-08-22 04:02:52 -07004488 // Sender-side network down for audio; there should be no effect on
4489 // video
4490 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
4491 WaitForPacketsOrSilence(false, false);
skvlad7a43d252016-03-22 15:32:27 -07004492
eladalon413ee9a2017-08-22 04:02:52 -07004493 // Receiver-side network down for audio; no change expected
4494 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO,
4495 kNetworkDown);
4496 WaitForPacketsOrSilence(false, false);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004497
eladalon413ee9a2017-08-22 04:02:52 -07004498 // Sender-side network down.
4499 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
4500 {
4501 rtc::CritScope lock(&test_crit_);
4502 // After network goes down we shouldn't be encoding more frames.
4503 sender_state_ = kNetworkDown;
4504 }
4505 // Wait for receiver-packets and no sender packets.
4506 WaitForPacketsOrSilence(true, false);
skvlad7a43d252016-03-22 15:32:27 -07004507
eladalon413ee9a2017-08-22 04:02:52 -07004508 // Receiver-side network down.
4509 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO,
4510 kNetworkDown);
4511 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004512
eladalon413ee9a2017-08-22 04:02:52 -07004513 // Network up for audio for both sides; video is still not expected to
4514 // start
4515 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
4516 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
4517 WaitForPacketsOrSilence(true, true);
skvlad7a43d252016-03-22 15:32:27 -07004518
eladalon413ee9a2017-08-22 04:02:52 -07004519 // Network back up again for both.
4520 {
4521 rtc::CritScope lock(&test_crit_);
4522 // It's OK to encode frames again, as we're about to bring up the
4523 // network.
4524 sender_state_ = kNetworkUp;
4525 }
4526 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
4527 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
4528 WaitForPacketsOrSilence(false, false);
4529
4530 // TODO(skvlad): add tests to verify that the audio streams are stopped
4531 // when the network goes down for audio once the workaround in
4532 // paced_sender.cc is removed.
4533 });
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004534 }
4535
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07004536 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004537 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07004538 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004539 {
Peter Boströmf2f82832015-05-01 13:00:41 +02004540 rtc::CritScope lock(&test_crit_);
Jelena Marusiccd670222015-07-16 09:30:09 +02004541 if (sender_state_ == kNetworkDown) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004542 ++down_frames_;
4543 EXPECT_LE(down_frames_, 1)
4544 << "Encoding more than one frame while network is down.";
4545 if (down_frames_ > 1)
Peter Boström5811a392015-12-10 13:02:50 +01004546 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004547 } else {
Peter Boström5811a392015-12-10 13:02:50 +01004548 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004549 }
4550 }
4551 return test::FakeEncoder::Encode(
4552 input_image, codec_specific_info, frame_types);
4553 }
4554
4555 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004556 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
4557 int64_t initial_time_ms = clock_->TimeInMilliseconds();
4558 int initial_sender_rtp;
4559 int initial_sender_rtcp;
4560 int initial_receiver_rtcp;
4561 {
Peter Boströmf2f82832015-05-01 13:00:41 +02004562 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004563 initial_sender_rtp = sender_rtp_;
4564 initial_sender_rtcp = sender_rtcp_;
4565 initial_receiver_rtcp = receiver_rtcp_;
4566 }
4567 bool sender_done = false;
4568 bool receiver_done = false;
mflodmand1590b22015-12-09 07:07:59 -08004569 while (!sender_done || !receiver_done) {
Peter Boström5811a392015-12-10 13:02:50 +01004570 packet_event_.Wait(kSilenceTimeoutMs);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004571 int64_t time_now_ms = clock_->TimeInMilliseconds();
Peter Boströmf2f82832015-05-01 13:00:41 +02004572 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004573 if (sender_down) {
stefan9e117c5e12017-08-16 08:16:25 -07004574 ASSERT_LE(sender_rtp_ - initial_sender_rtp - sender_padding_,
4575 kNumAcceptedDowntimeRtp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004576 << "RTP sent during sender-side downtime.";
4577 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
4578 kNumAcceptedDowntimeRtcp)
4579 << "RTCP sent during sender-side downtime.";
4580 if (time_now_ms - initial_time_ms >=
4581 static_cast<int64_t>(kSilenceTimeoutMs)) {
4582 sender_done = true;
4583 }
4584 } else {
skvlad7a43d252016-03-22 15:32:27 -07004585 if (sender_rtp_ > initial_sender_rtp + kNumAcceptedDowntimeRtp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004586 sender_done = true;
4587 }
4588 if (receiver_down) {
4589 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
4590 kNumAcceptedDowntimeRtcp)
4591 << "RTCP sent during receiver-side downtime.";
4592 if (time_now_ms - initial_time_ms >=
4593 static_cast<int64_t>(kSilenceTimeoutMs)) {
4594 receiver_done = true;
4595 }
4596 } else {
skvlad7a43d252016-03-22 15:32:27 -07004597 if (receiver_rtcp_ > initial_receiver_rtcp + kNumAcceptedDowntimeRtcp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004598 receiver_done = true;
4599 }
4600 }
4601 }
4602
eladalon413ee9a2017-08-22 04:02:52 -07004603 test::SingleThreadedTaskQueueForTesting* const task_queue_;
Peter Boströmf2f82832015-05-01 13:00:41 +02004604 rtc::CriticalSection test_crit_;
Peter Boström5811a392015-12-10 13:02:50 +01004605 rtc::Event encoded_frames_;
4606 rtc::Event packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004607 Call* sender_call_;
4608 Call* receiver_call_;
danilchapa37de392017-09-09 04:17:22 -07004609 NetworkState sender_state_ RTC_GUARDED_BY(test_crit_);
4610 int sender_rtp_ RTC_GUARDED_BY(test_crit_);
4611 int sender_padding_ RTC_GUARDED_BY(test_crit_);
4612 int sender_rtcp_ RTC_GUARDED_BY(test_crit_);
4613 int receiver_rtcp_ RTC_GUARDED_BY(test_crit_);
4614 int down_frames_ RTC_GUARDED_BY(test_crit_);
eladalon413ee9a2017-08-22 04:02:52 -07004615 } test(&task_queue_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004616
stefane74eef12016-01-08 06:47:13 -08004617 RunBaseTest(&test);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004618}
4619
philipelccdfcca2017-10-23 12:42:17 +02004620TEST_P(EndToEndTest, CallReportsRttForSender) {
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004621 static const int kSendDelayMs = 30;
4622 static const int kReceiveDelayMs = 70;
solenberg4fbae2b2015-08-28 04:07:10 -07004623
eladalon413ee9a2017-08-22 04:02:52 -07004624 std::unique_ptr<test::DirectTransport> sender_transport;
4625 std::unique_ptr<test::DirectTransport> receiver_transport;
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004626
eladalon413ee9a2017-08-22 04:02:52 -07004627 task_queue_.SendTask([this, &sender_transport, &receiver_transport]() {
4628 FakeNetworkPipe::Config config;
4629 config.queue_delay_ms = kSendDelayMs;
4630 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
4631 sender_transport = rtc::MakeUnique<test::DirectTransport>(
4632 &task_queue_, config, sender_call_.get(), payload_type_map_);
4633 config.queue_delay_ms = kReceiveDelayMs;
4634 receiver_transport = rtc::MakeUnique<test::DirectTransport>(
4635 &task_queue_, config, receiver_call_.get(), payload_type_map_);
4636 sender_transport->SetReceiver(receiver_call_->Receiver());
4637 receiver_transport->SetReceiver(sender_call_->Receiver());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004638
eladalon413ee9a2017-08-22 04:02:52 -07004639 CreateSendConfig(1, 0, 0, sender_transport.get());
4640 CreateMatchingReceiveConfigs(receiver_transport.get());
4641
4642 CreateVideoStreams();
4643 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
4644 kDefaultHeight);
4645 Start();
4646 });
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004647
4648 int64_t start_time_ms = clock_->TimeInMilliseconds();
4649 while (true) {
4650 Call::Stats stats = sender_call_->GetStats();
4651 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
4652 clock_->TimeInMilliseconds())
4653 << "No RTT stats before timeout!";
4654 if (stats.rtt_ms != -1) {
Danil Chapovalov10e8f8e2016-09-07 15:05:29 +02004655 // To avoid failures caused by rounding or minor ntp clock adjustments,
4656 // relax expectation by 1ms.
4657 constexpr int kAllowedErrorMs = 1;
4658 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs - kAllowedErrorMs);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004659 break;
4660 }
4661 SleepMs(10);
4662 }
4663
eladalon413ee9a2017-08-22 04:02:52 -07004664 task_queue_.SendTask([this, &sender_transport, &receiver_transport]() {
4665 Stop();
4666 DestroyStreams();
4667 sender_transport.reset();
4668 receiver_transport.reset();
4669 DestroyCalls();
4670 });
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004671}
4672
skvlad7a43d252016-03-22 15:32:27 -07004673void EndToEndTest::VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004674 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -07004675 VideoEncoder* encoder,
4676 Transport* transport) {
eladalon413ee9a2017-08-22 04:02:52 -07004677 task_queue_.SendTask([this, network_to_bring_up, encoder, transport]() {
4678 CreateSenderCall(Call::Config(event_log_.get()));
4679 sender_call_->SignalChannelNetworkState(network_to_bring_up, kNetworkUp);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004680
eladalon413ee9a2017-08-22 04:02:52 -07004681 CreateSendConfig(1, 0, 0, transport);
4682 video_send_config_.encoder_settings.encoder = encoder;
4683 CreateVideoStreams();
4684 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
4685 kDefaultHeight);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004686
eladalon413ee9a2017-08-22 04:02:52 -07004687 Start();
4688 });
4689
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004690 SleepMs(kSilenceTimeoutMs);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004691
eladalon413ee9a2017-08-22 04:02:52 -07004692 task_queue_.SendTask([this]() {
4693 Stop();
4694 DestroyStreams();
4695 DestroyCalls();
4696 });
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004697}
4698
skvlad7a43d252016-03-22 15:32:27 -07004699void EndToEndTest::VerifyNewVideoReceiveStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004700 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -07004701 Transport* transport) {
eladalon413ee9a2017-08-22 04:02:52 -07004702 std::unique_ptr<test::DirectTransport> sender_transport;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004703
eladalon413ee9a2017-08-22 04:02:52 -07004704 task_queue_.SendTask([this, &sender_transport, network_to_bring_up,
4705 transport]() {
4706 Call::Config config(event_log_.get());
4707 CreateCalls(config, config);
4708 receiver_call_->SignalChannelNetworkState(network_to_bring_up, kNetworkUp);
4709 sender_transport = rtc::MakeUnique<test::DirectTransport>(
4710 &task_queue_, sender_call_.get(), payload_type_map_);
4711 sender_transport->SetReceiver(receiver_call_->Receiver());
4712 CreateSendConfig(1, 0, 0, sender_transport.get());
4713 CreateMatchingReceiveConfigs(transport);
4714 CreateVideoStreams();
4715 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
4716 kDefaultHeight);
4717 Start();
4718 });
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004719
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004720 SleepMs(kSilenceTimeoutMs);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004721
eladalon413ee9a2017-08-22 04:02:52 -07004722 task_queue_.SendTask([this, &sender_transport]() {
4723 Stop();
4724 DestroyStreams();
4725 sender_transport.reset();
4726 DestroyCalls();
4727 });
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004728}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00004729
philipelccdfcca2017-10-23 12:42:17 +02004730TEST_P(EndToEndTest, NewVideoSendStreamsRespectVideoNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004731 class UnusedEncoder : public test::FakeEncoder {
4732 public:
4733 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
perkjfea93092016-05-14 00:58:48 -07004734
4735 int32_t InitEncode(const VideoCodec* config,
4736 int32_t number_of_cores,
4737 size_t max_payload_size) override {
4738 EXPECT_GT(config->startBitrate, 0u);
4739 return 0;
4740 }
skvlad7a43d252016-03-22 15:32:27 -07004741 int32_t Encode(const VideoFrame& input_image,
4742 const CodecSpecificInfo* codec_specific_info,
4743 const std::vector<FrameType>* frame_types) override {
4744 ADD_FAILURE() << "Unexpected frame encode.";
4745 return test::FakeEncoder::Encode(input_image, codec_specific_info,
4746 frame_types);
4747 }
4748 };
4749
4750 UnusedEncoder unused_encoder;
4751 UnusedTransport unused_transport;
4752 VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004753 MediaType::AUDIO, &unused_encoder, &unused_transport);
skvlad7a43d252016-03-22 15:32:27 -07004754}
4755
philipelccdfcca2017-10-23 12:42:17 +02004756TEST_P(EndToEndTest, NewVideoSendStreamsIgnoreAudioNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004757 class RequiredEncoder : public test::FakeEncoder {
4758 public:
4759 RequiredEncoder()
4760 : FakeEncoder(Clock::GetRealTimeClock()), encoded_frame_(false) {}
4761 ~RequiredEncoder() {
4762 if (!encoded_frame_) {
4763 ADD_FAILURE() << "Didn't encode an expected frame";
4764 }
4765 }
4766 int32_t Encode(const VideoFrame& input_image,
4767 const CodecSpecificInfo* codec_specific_info,
4768 const std::vector<FrameType>* frame_types) override {
4769 encoded_frame_ = true;
4770 return test::FakeEncoder::Encode(input_image, codec_specific_info,
4771 frame_types);
4772 }
4773
4774 private:
4775 bool encoded_frame_;
4776 };
4777
4778 RequiredTransport required_transport(true /*rtp*/, false /*rtcp*/);
4779 RequiredEncoder required_encoder;
4780 VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004781 MediaType::VIDEO, &required_encoder, &required_transport);
skvlad7a43d252016-03-22 15:32:27 -07004782}
4783
philipelccdfcca2017-10-23 12:42:17 +02004784TEST_P(EndToEndTest, NewVideoReceiveStreamsRespectVideoNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004785 UnusedTransport transport;
Sergey Ulanove2b15012016-11-22 16:08:30 -08004786 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::AUDIO, &transport);
skvlad7a43d252016-03-22 15:32:27 -07004787}
4788
philipelccdfcca2017-10-23 12:42:17 +02004789TEST_P(EndToEndTest, NewVideoReceiveStreamsIgnoreAudioNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004790 RequiredTransport transport(false /*rtp*/, true /*rtcp*/);
Sergey Ulanove2b15012016-11-22 16:08:30 -08004791 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::VIDEO, &transport);
skvlad7a43d252016-03-22 15:32:27 -07004792}
4793
Peter Boströmd7da1202015-06-05 14:09:38 +02004794void VerifyEmptyNackConfig(const NackConfig& config) {
4795 EXPECT_EQ(0, config.rtp_history_ms)
4796 << "Enabling NACK requires rtcp-fb: nack negotiation.";
4797}
4798
brandtrb5f2c3f2016-10-04 23:28:39 -07004799void VerifyEmptyUlpfecConfig(const UlpfecConfig& config) {
Peter Boströmd7da1202015-06-05 14:09:38 +02004800 EXPECT_EQ(-1, config.ulpfec_payload_type)
brandtr535830e2016-10-31 03:45:58 -07004801 << "Enabling ULPFEC requires rtpmap: ulpfec negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02004802 EXPECT_EQ(-1, config.red_payload_type)
brandtr535830e2016-10-31 03:45:58 -07004803 << "Enabling ULPFEC requires rtpmap: red negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02004804 EXPECT_EQ(-1, config.red_rtx_payload_type)
brandtr535830e2016-10-31 03:45:58 -07004805 << "Enabling RTX in ULPFEC requires rtpmap: rtx negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02004806}
4807
brandtr3d200bd2017-01-16 06:59:19 -08004808void VerifyEmptyFlexfecConfig(
4809 const VideoSendStream::Config::Rtp::Flexfec& config) {
4810 EXPECT_EQ(-1, config.payload_type)
brandtr1e3dfbf2016-11-16 22:45:19 -08004811 << "Enabling FlexFEC requires rtpmap: flexfec negotiation.";
brandtr3d200bd2017-01-16 06:59:19 -08004812 EXPECT_EQ(0U, config.ssrc)
brandtr1cfbd602016-12-08 04:17:53 -08004813 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
brandtr1e3dfbf2016-11-16 22:45:19 -08004814 EXPECT_TRUE(config.protected_media_ssrcs.empty())
4815 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
4816}
4817
philipelccdfcca2017-10-23 12:42:17 +02004818TEST_P(EndToEndTest, VerifyDefaultSendConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07004819 VideoSendStream::Config default_send_config(nullptr);
Peter Boströmd7da1202015-06-05 14:09:38 +02004820 EXPECT_EQ(0, default_send_config.rtp.nack.rtp_history_ms)
4821 << "Enabling NACK require rtcp-fb: nack negotiation.";
4822 EXPECT_TRUE(default_send_config.rtp.rtx.ssrcs.empty())
4823 << "Enabling RTX requires rtpmap: rtx negotiation.";
4824 EXPECT_TRUE(default_send_config.rtp.extensions.empty())
4825 << "Enabling RTP extensions require negotiation.";
4826
4827 VerifyEmptyNackConfig(default_send_config.rtp.nack);
brandtrb5f2c3f2016-10-04 23:28:39 -07004828 VerifyEmptyUlpfecConfig(default_send_config.rtp.ulpfec);
brandtr1e3dfbf2016-11-16 22:45:19 -08004829 VerifyEmptyFlexfecConfig(default_send_config.rtp.flexfec);
Peter Boströmd7da1202015-06-05 14:09:38 +02004830}
4831
philipelccdfcca2017-10-23 12:42:17 +02004832TEST_P(EndToEndTest, VerifyDefaultVideoReceiveConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07004833 VideoReceiveStream::Config default_receive_config(nullptr);
pbosda903ea2015-10-02 02:36:56 -07004834 EXPECT_EQ(RtcpMode::kCompound, default_receive_config.rtp.rtcp_mode)
Peter Boströmd7da1202015-06-05 14:09:38 +02004835 << "Reduced-size RTCP require rtcp-rsize to be negotiated.";
4836 EXPECT_FALSE(default_receive_config.rtp.remb)
4837 << "REMB require rtcp-fb: goog-remb to be negotiated.";
4838 EXPECT_FALSE(
4839 default_receive_config.rtp.rtcp_xr.receiver_reference_time_report)
4840 << "RTCP XR settings require rtcp-xr to be negotiated.";
brandtr14742122017-01-27 04:53:07 -08004841 EXPECT_EQ(0U, default_receive_config.rtp.rtx_ssrc)
4842 << "Enabling RTX requires ssrc-group: FID negotiation";
nisse26e3abb2017-08-25 04:44:25 -07004843 EXPECT_TRUE(default_receive_config.rtp.rtx_associated_payload_types.empty())
Peter Boströmd7da1202015-06-05 14:09:38 +02004844 << "Enabling RTX requires rtpmap: rtx negotiation.";
4845 EXPECT_TRUE(default_receive_config.rtp.extensions.empty())
4846 << "Enabling RTP extensions require negotiation.";
4847
4848 VerifyEmptyNackConfig(default_receive_config.rtp.nack);
nisse3b3622f2017-09-26 02:49:21 -07004849 EXPECT_EQ(-1, default_receive_config.rtp.ulpfec_payload_type)
4850 << "Enabling ULPFEC requires rtpmap: ulpfec negotiation.";
4851 EXPECT_EQ(-1, default_receive_config.rtp.red_payload_type)
4852 << "Enabling ULPFEC requires rtpmap: red negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02004853}
4854
philipelccdfcca2017-10-23 12:42:17 +02004855TEST_P(EndToEndTest, VerifyDefaultFlexfecReceiveConfigParameters) {
brandtr8313a6f2017-01-13 07:41:19 -08004856 test::NullTransport rtcp_send_transport;
4857 FlexfecReceiveStream::Config default_receive_config(&rtcp_send_transport);
brandtr1cfbd602016-12-08 04:17:53 -08004858 EXPECT_EQ(-1, default_receive_config.payload_type)
4859 << "Enabling FlexFEC requires rtpmap: flexfec negotiation.";
4860 EXPECT_EQ(0U, default_receive_config.remote_ssrc)
4861 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
4862 EXPECT_TRUE(default_receive_config.protected_media_ssrcs.empty())
4863 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
brandtr1e3dfbf2016-11-16 22:45:19 -08004864}
4865
philipelccdfcca2017-10-23 12:42:17 +02004866TEST_P(EndToEndTest, TransportSeqNumOnAudioAndVideo) {
danilchap4336d732017-03-03 06:21:54 -08004867 static constexpr int kExtensionId = 8;
4868 static constexpr size_t kMinPacketsToWaitFor = 50;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004869 class TransportSequenceNumberTest : public test::EndToEndTest {
4870 public:
4871 TransportSequenceNumberTest()
4872 : EndToEndTest(kDefaultTimeoutMs),
4873 video_observed_(false),
4874 audio_observed_(false) {
4875 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
4876 kExtensionId);
4877 }
4878
4879 size_t GetNumVideoStreams() const override { return 1; }
4880 size_t GetNumAudioStreams() const override { return 1; }
4881
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004882 void ModifyAudioConfigs(
4883 AudioSendStream::Config* send_config,
4884 std::vector<AudioReceiveStream::Config>* receive_configs) override {
4885 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07004886 send_config->rtp.extensions.push_back(RtpExtension(
4887 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004888 (*receive_configs)[0].rtp.extensions.clear();
4889 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
4890 }
4891
4892 Action OnSendRtp(const uint8_t* packet, size_t length) override {
4893 RTPHeader header;
4894 EXPECT_TRUE(parser_->Parse(packet, length, &header));
4895 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
4896 // Unwrap packet id and verify uniqueness.
4897 int64_t packet_id =
4898 unwrapper_.Unwrap(header.extension.transportSequenceNumber);
4899 EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
4900
4901 if (header.ssrc == kVideoSendSsrcs[0])
4902 video_observed_ = true;
4903 if (header.ssrc == kAudioSendSsrc)
4904 audio_observed_ = true;
4905 if (audio_observed_ && video_observed_ &&
danilchap4336d732017-03-03 06:21:54 -08004906 received_packet_ids_.size() >= kMinPacketsToWaitFor) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004907 size_t packet_id_range =
4908 *received_packet_ids_.rbegin() - *received_packet_ids_.begin() + 1;
4909 EXPECT_EQ(received_packet_ids_.size(), packet_id_range);
4910 observation_complete_.Set();
4911 }
4912 return SEND_PACKET;
4913 }
4914
4915 void PerformTest() override {
4916 EXPECT_TRUE(Wait()) << "Timed out while waiting for audio and video "
4917 "packets with transport sequence number.";
4918 }
4919
danilchap4336d732017-03-03 06:21:54 -08004920 void ExpectSuccessful() {
4921 EXPECT_TRUE(video_observed_);
4922 EXPECT_TRUE(audio_observed_);
4923 EXPECT_GE(received_packet_ids_.size(), kMinPacketsToWaitFor);
4924 }
4925
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004926 private:
4927 bool video_observed_;
4928 bool audio_observed_;
4929 SequenceNumberUnwrapper unwrapper_;
4930 std::set<int64_t> received_packet_ids_;
4931 } test;
4932
stefane74eef12016-01-08 06:47:13 -08004933 RunBaseTest(&test);
danilchap4336d732017-03-03 06:21:54 -08004934 // Double check conditions for successful test to produce better error
4935 // message when the test fail.
4936 test.ExpectSuccessful();
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004937}
palmkviste75f2042016-09-28 06:19:48 -07004938
4939class EndToEndLogTest : public EndToEndTest {
4940 void SetUp() { paths_.clear(); }
4941 void TearDown() {
4942 for (const auto& path : paths_) {
4943 rtc::RemoveFile(path);
4944 }
4945 }
4946
4947 public:
4948 int AddFile() {
4949 paths_.push_back(test::TempFilename(test::OutputPath(), "test_file"));
4950 return static_cast<int>(paths_.size()) - 1;
4951 }
4952
4953 rtc::PlatformFile OpenFile(int idx) {
4954 return rtc::OpenPlatformFile(paths_[idx]);
4955 }
4956
4957 void LogSend(bool open) {
4958 if (open) {
4959 video_send_stream_->EnableEncodedFrameRecording(
4960 std::vector<rtc::PlatformFile>(1, OpenFile(AddFile())), 0);
4961 } else {
4962 video_send_stream_->DisableEncodedFrameRecording();
4963 }
4964 }
4965 void LogReceive(bool open) {
4966 if (open) {
4967 video_receive_streams_[0]->EnableEncodedFrameRecording(
4968 OpenFile(AddFile()), 0);
4969 } else {
4970 video_receive_streams_[0]->DisableEncodedFrameRecording();
4971 }
4972 }
4973
4974 std::vector<std::string> paths_;
4975};
4976
philipelccdfcca2017-10-23 12:42:17 +02004977TEST_P(EndToEndLogTest, LogsEncodedFramesWhenRequested) {
palmkviste75f2042016-09-28 06:19:48 -07004978 static const int kNumFramesToRecord = 10;
4979 class LogEncodingObserver : public test::EndToEndTest,
4980 public EncodedFrameObserver {
4981 public:
4982 explicit LogEncodingObserver(EndToEndLogTest* fixture)
4983 : EndToEndTest(kDefaultTimeoutMs),
4984 fixture_(fixture),
4985 recorded_frames_(0) {}
4986
4987 void PerformTest() override {
4988 fixture_->LogSend(true);
4989 fixture_->LogReceive(true);
4990 ASSERT_TRUE(Wait()) << "Timed out while waiting for frame logging.";
4991 }
4992
4993 void ModifyVideoConfigs(
4994 VideoSendStream::Config* send_config,
4995 std::vector<VideoReceiveStream::Config>* receive_configs,
4996 VideoEncoderConfig* encoder_config) override {
magjed509e4fe2016-11-18 01:34:11 -08004997 encoder_.reset(VP8Encoder::Create());
palmkviste75f2042016-09-28 06:19:48 -07004998 decoder_.reset(VP8Decoder::Create());
4999
5000 send_config->post_encode_callback = this;
5001 send_config->encoder_settings.payload_name = "VP8";
5002 send_config->encoder_settings.encoder = encoder_.get();
5003
5004 (*receive_configs)[0].decoders.resize(1);
5005 (*receive_configs)[0].decoders[0].payload_type =
5006 send_config->encoder_settings.payload_type;
5007 (*receive_configs)[0].decoders[0].payload_name =
5008 send_config->encoder_settings.payload_name;
5009 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
5010 }
5011
5012 void EncodedFrameCallback(const EncodedFrame& encoded_frame) override {
5013 rtc::CritScope lock(&crit_);
5014 if (recorded_frames_++ > kNumFramesToRecord) {
5015 fixture_->LogSend(false);
5016 fixture_->LogReceive(false);
5017 rtc::File send_file(fixture_->OpenFile(0));
5018 rtc::File receive_file(fixture_->OpenFile(1));
5019 uint8_t out[100];
5020 // If logging has worked correctly neither file should be empty, i.e.
5021 // we should be able to read something from them.
5022 EXPECT_LT(0u, send_file.Read(out, 100));
5023 EXPECT_LT(0u, receive_file.Read(out, 100));
5024 observation_complete_.Set();
5025 }
5026 }
5027
5028 private:
5029 EndToEndLogTest* const fixture_;
5030 std::unique_ptr<VideoEncoder> encoder_;
5031 std::unique_ptr<VideoDecoder> decoder_;
5032 rtc::CriticalSection crit_;
danilchapa37de392017-09-09 04:17:22 -07005033 int recorded_frames_ RTC_GUARDED_BY(crit_);
palmkviste75f2042016-09-28 06:19:48 -07005034 } test(this);
5035
5036 RunBaseTest(&test);
5037}
5038
philipelccdfcca2017-10-23 12:42:17 +02005039INSTANTIATE_TEST_CASE_P(RoundRobin,
5040 EndToEndTest,
5041 ::testing::Values("WebRTC-RoundRobinPacing/Disabled/",
5042 "WebRTC-RoundRobinPacing/Enabled/"));
5043
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00005044} // namespace webrtc