blob: 9c9a170bac6ff7bac7460f497c25a7377a7b87b8 [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
philipel277a8b52017-03-16 05:19:49 -070081class EndToEndTest : public test::CallTest {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000082 public:
philipel277a8b52017-03-16 05:19:49 -070083 EndToEndTest() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000084
85 virtual ~EndToEndTest() {
stefanff483612015-12-21 03:14:00 -080086 EXPECT_EQ(nullptr, video_send_stream_);
87 EXPECT_TRUE(video_receive_streams_.empty());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000088 }
89
90 protected:
pbos2d566682015-09-28 09:59:31 -070091 class UnusedTransport : public Transport {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000092 private:
stefan1d8a5062015-10-02 03:39:33 -070093 bool SendRtp(const uint8_t* packet,
94 size_t length,
95 const PacketOptions& options) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000096 ADD_FAILURE() << "Unexpected RTP sent.";
97 return false;
98 }
99
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000100 bool SendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000101 ADD_FAILURE() << "Unexpected RTCP sent.";
102 return false;
103 }
104 };
105
skvlad7a43d252016-03-22 15:32:27 -0700106 class RequiredTransport : public Transport {
107 public:
108 RequiredTransport(bool rtp_required, bool rtcp_required)
109 : need_rtp_(rtp_required), need_rtcp_(rtcp_required) {}
110 ~RequiredTransport() {
111 if (need_rtp_) {
112 ADD_FAILURE() << "Expected RTP packet not sent.";
113 }
114 if (need_rtcp_) {
115 ADD_FAILURE() << "Expected RTCP packet not sent.";
116 }
117 }
118
119 private:
120 bool SendRtp(const uint8_t* packet,
121 size_t length,
122 const PacketOptions& options) override {
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700123 rtc::CritScope lock(&crit_);
skvlad7a43d252016-03-22 15:32:27 -0700124 need_rtp_ = false;
125 return true;
126 }
127
128 bool SendRtcp(const uint8_t* packet, size_t length) override {
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700129 rtc::CritScope lock(&crit_);
skvlad7a43d252016-03-22 15:32:27 -0700130 need_rtcp_ = false;
131 return true;
132 }
133 bool need_rtp_;
134 bool need_rtcp_;
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700135 rtc::CriticalSection crit_;
skvlad7a43d252016-03-22 15:32:27 -0700136 };
137
Peter Boström39593972016-02-15 11:27:15 +0100138 void DecodesRetransmittedFrame(bool enable_rtx, bool enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000139 void ReceivesPliAndRecovers(int rtp_history_ms);
pbosda903ea2015-10-02 02:36:56 -0700140 void RespectsRtcpMode(RtcpMode rtcp_mode);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000141 void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200142 void TestRtpStatePreservation(bool use_rtx, bool provoke_rtcpsr_before_rtp);
nisse3b3622f2017-09-26 02:49:21 -0700143 void VerifyHistogramStats(bool use_rtx, bool use_fec, bool screenshare);
skvlad7a43d252016-03-22 15:32:27 -0700144 void VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -0800145 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -0700146 VideoEncoder* encoder,
147 Transport* transport);
148 void VerifyNewVideoReceiveStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -0800149 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -0700150 Transport* transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000151};
152
philipel277a8b52017-03-16 05:19:49 -0700153TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
philipel4fb651d2017-04-10 03:54:05 -0700154 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000155
solenberg4fbae2b2015-08-28 04:07:10 -0700156 test::NullTransport transport;
brandtr841de6a2016-11-15 07:10:52 -0800157 CreateSendConfig(1, 0, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700158 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000159
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100160 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000161
stefanff483612015-12-21 03:14:00 -0800162 video_receive_streams_[0]->Start();
163 video_receive_streams_[0]->Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000164
165 DestroyStreams();
166}
167
philipel277a8b52017-03-16 05:19:49 -0700168TEST_F(EndToEndTest, ReceiverCanBeStoppedTwice) {
philipel4fb651d2017-04-10 03:54:05 -0700169 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000170
solenberg4fbae2b2015-08-28 04:07:10 -0700171 test::NullTransport transport;
brandtr841de6a2016-11-15 07:10:52 -0800172 CreateSendConfig(1, 0, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700173 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000174
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100175 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000176
stefanff483612015-12-21 03:14:00 -0800177 video_receive_streams_[0]->Stop();
178 video_receive_streams_[0]->Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000179
180 DestroyStreams();
181}
182
philipel277a8b52017-03-16 05:19:49 -0700183TEST_F(EndToEndTest, ReceiverCanBeStoppedAndRestarted) {
philipel4fb651d2017-04-10 03:54:05 -0700184 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
sprang113bdca2016-10-11 03:10:10 -0700185
186 test::NullTransport transport;
brandtr841de6a2016-11-15 07:10:52 -0800187 CreateSendConfig(1, 0, 0, &transport);
sprang113bdca2016-10-11 03:10:10 -0700188 CreateMatchingReceiveConfigs(&transport);
189
190 CreateVideoStreams();
191
192 video_receive_streams_[0]->Stop();
193 video_receive_streams_[0]->Start();
194 video_receive_streams_[0]->Stop();
195
196 DestroyStreams();
197}
198
philipel277a8b52017-03-16 05:19:49 -0700199TEST_F(EndToEndTest, RendersSingleDelayedFrame) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000200 static const int kWidth = 320;
201 static const int kHeight = 240;
202 // This constant is chosen to be higher than the timeout in the video_render
203 // module. This makes sure that frames aren't dropped if there are no other
204 // frames in the queue.
nisse76bc8e82017-02-07 09:37:41 -0800205 static const int kRenderDelayMs = 1000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000206
nisse7ade7b32016-03-23 04:48:10 -0700207 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000208 public:
Peter Boström5811a392015-12-10 13:02:50 +0100209 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000210
nisse76bc8e82017-02-07 09:37:41 -0800211 void OnFrame(const VideoFrame& video_frame) override {
212 SleepMs(kRenderDelayMs);
213 event_.Set();
214 }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000215
Peter Boström5811a392015-12-10 13:02:50 +0100216 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000217
Peter Boström5811a392015-12-10 13:02:50 +0100218 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000219 } renderer;
220
perkja49cbd32016-09-16 07:53:41 -0700221 test::FrameForwarder frame_forwarder;
eladalon413ee9a2017-08-22 04:02:52 -0700222 std::unique_ptr<test::DirectTransport> sender_transport;
223 std::unique_ptr<test::DirectTransport> receiver_transport;
perkja49cbd32016-09-16 07:53:41 -0700224
eladalon413ee9a2017-08-22 04:02:52 -0700225 task_queue_.SendTask([this, &renderer, &frame_forwarder, &sender_transport,
226 &receiver_transport]() {
227 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
228
229 sender_transport = rtc::MakeUnique<test::DirectTransport>(
230 &task_queue_, sender_call_.get(), payload_type_map_);
231 receiver_transport = rtc::MakeUnique<test::DirectTransport>(
232 &task_queue_, receiver_call_.get(), payload_type_map_);
233 sender_transport->SetReceiver(receiver_call_->Receiver());
234 receiver_transport->SetReceiver(sender_call_->Receiver());
235
236 CreateSendConfig(1, 0, 0, sender_transport.get());
237 CreateMatchingReceiveConfigs(receiver_transport.get());
238
239 video_receive_configs_[0].renderer = &renderer;
240
241 CreateVideoStreams();
242 Start();
243
244 // Create frames that are smaller than the send width/height, this is done
245 // to check that the callbacks are done after processing video.
246 std::unique_ptr<test::FrameGenerator> frame_generator(
247 test::FrameGenerator::CreateSquareGenerator(kWidth, kHeight));
248 video_send_stream_->SetSource(
249 &frame_forwarder,
250 VideoSendStream::DegradationPreference::kMaintainFramerate);
251
252 frame_forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
253 });
254
Peter Boström5811a392015-12-10 13:02:50 +0100255 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000256 << "Timed out while waiting for the frame to render.";
257
eladalon413ee9a2017-08-22 04:02:52 -0700258 task_queue_.SendTask([this, &sender_transport, &receiver_transport]() {
259 Stop();
260 DestroyStreams();
261 sender_transport.reset();
262 receiver_transport.reset();
263 DestroyCalls();
264 });
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000265}
266
philipel277a8b52017-03-16 05:19:49 -0700267TEST_F(EndToEndTest, TransmitsFirstFrame) {
nisse7ade7b32016-03-23 04:48:10 -0700268 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000269 public:
Peter Boström5811a392015-12-10 13:02:50 +0100270 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000271
nisseeb83a1a2016-03-21 01:27:56 -0700272 void OnFrame(const VideoFrame& video_frame) override { event_.Set(); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000273
Peter Boström5811a392015-12-10 13:02:50 +0100274 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000275
Peter Boström5811a392015-12-10 13:02:50 +0100276 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000277 } renderer;
278
eladalon413ee9a2017-08-22 04:02:52 -0700279 std::unique_ptr<test::FrameGenerator> frame_generator;
perkja49cbd32016-09-16 07:53:41 -0700280 test::FrameForwarder frame_forwarder;
eladalon413ee9a2017-08-22 04:02:52 -0700281
282 std::unique_ptr<test::DirectTransport> sender_transport;
283 std::unique_ptr<test::DirectTransport> receiver_transport;
284
285 task_queue_.SendTask([this, &renderer, &frame_generator, &frame_forwarder,
286 &sender_transport, &receiver_transport]() {
287 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
288
289 sender_transport = rtc::MakeUnique<test::DirectTransport>(
290 &task_queue_, sender_call_.get(), payload_type_map_);
291 receiver_transport = rtc::MakeUnique<test::DirectTransport>(
292 &task_queue_, receiver_call_.get(), payload_type_map_);
293 sender_transport->SetReceiver(receiver_call_->Receiver());
294 receiver_transport->SetReceiver(sender_call_->Receiver());
295
296 CreateSendConfig(1, 0, 0, sender_transport.get());
297 CreateMatchingReceiveConfigs(receiver_transport.get());
298 video_receive_configs_[0].renderer = &renderer;
299
300 CreateVideoStreams();
301 Start();
302
303 frame_generator = test::FrameGenerator::CreateSquareGenerator(
304 kDefaultWidth, kDefaultHeight);
305 video_send_stream_->SetSource(
306 &frame_forwarder,
307 VideoSendStream::DegradationPreference::kMaintainFramerate);
308 frame_forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
309 });
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000310
Peter Boström5811a392015-12-10 13:02:50 +0100311 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000312 << "Timed out while waiting for the frame to render.";
313
eladalon413ee9a2017-08-22 04:02:52 -0700314 task_queue_.SendTask([this, &sender_transport, &receiver_transport]() {
315 Stop();
316 DestroyStreams();
317 sender_transport.reset();
318 receiver_transport.reset();
319 DestroyCalls();
320 });
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000321}
322
Perba7dc722016-04-19 15:01:23 +0200323class CodecObserver : public test::EndToEndTest,
nisse7ade7b32016-03-23 04:48:10 -0700324 public rtc::VideoSinkInterface<VideoFrame> {
Perba7dc722016-04-19 15:01:23 +0200325 public:
326 CodecObserver(int no_frames_to_wait_for,
327 VideoRotation rotation_to_test,
328 const std::string& payload_name,
329 webrtc::VideoEncoder* encoder,
330 webrtc::VideoDecoder* decoder)
hta9aa96882016-12-06 05:36:03 -0800331 : EndToEndTest(4 * webrtc::EndToEndTest::kDefaultTimeoutMs),
332 // TODO(hta): This timeout (120 seconds) is excessive.
333 // https://bugs.webrtc.org/6830
Perba7dc722016-04-19 15:01:23 +0200334 no_frames_to_wait_for_(no_frames_to_wait_for),
335 expected_rotation_(rotation_to_test),
336 payload_name_(payload_name),
337 encoder_(encoder),
338 decoder_(decoder),
339 frame_counter_(0) {}
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000340
Perba7dc722016-04-19 15:01:23 +0200341 void PerformTest() override {
342 EXPECT_TRUE(Wait())
343 << "Timed out while waiting for enough frames to be decoded.";
344 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000345
Perba7dc722016-04-19 15:01:23 +0200346 void ModifyVideoConfigs(
347 VideoSendStream::Config* send_config,
348 std::vector<VideoReceiveStream::Config>* receive_configs,
349 VideoEncoderConfig* encoder_config) override {
350 send_config->encoder_settings.encoder = encoder_.get();
351 send_config->encoder_settings.payload_name = payload_name_;
minyue20c84cc2017-04-10 16:57:57 -0700352 send_config->encoder_settings.payload_type =
353 test::CallTest::kVideoSendPayloadType;
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000354
Perba7dc722016-04-19 15:01:23 +0200355 (*receive_configs)[0].renderer = this;
356 (*receive_configs)[0].decoders.resize(1);
357 (*receive_configs)[0].decoders[0].payload_type =
358 send_config->encoder_settings.payload_type;
359 (*receive_configs)[0].decoders[0].payload_name =
360 send_config->encoder_settings.payload_name;
361 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
362 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000363
Perba7dc722016-04-19 15:01:23 +0200364 void OnFrame(const VideoFrame& video_frame) override {
365 EXPECT_EQ(expected_rotation_, video_frame.rotation());
366 if (++frame_counter_ == no_frames_to_wait_for_)
367 observation_complete_.Set();
368 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000369
Perba7dc722016-04-19 15:01:23 +0200370 void OnFrameGeneratorCapturerCreated(
371 test::FrameGeneratorCapturer* frame_generator_capturer) override {
372 frame_generator_capturer->SetFakeRotation(expected_rotation_);
373 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000374
Perba7dc722016-04-19 15:01:23 +0200375 private:
376 int no_frames_to_wait_for_;
377 VideoRotation expected_rotation_;
378 std::string payload_name_;
379 std::unique_ptr<webrtc::VideoEncoder> encoder_;
380 std::unique_ptr<webrtc::VideoDecoder> decoder_;
381 int frame_counter_;
382};
383
philipel277a8b52017-03-16 05:19:49 -0700384TEST_F(EndToEndTest, SendsAndReceivesVP8) {
philipel266f0a42016-11-28 08:49:07 -0800385 CodecObserver test(5, kVideoRotation_0, "VP8", VP8Encoder::Create(),
386 VP8Decoder::Create());
387 RunBaseTest(&test);
388}
389
philipel277a8b52017-03-16 05:19:49 -0700390TEST_F(EndToEndTest, SendsAndReceivesVP8Rotation90) {
magjed509e4fe2016-11-18 01:34:11 -0800391 CodecObserver test(5, kVideoRotation_90, "VP8", VP8Encoder::Create(),
Perba7dc722016-04-19 15:01:23 +0200392 VP8Decoder::Create());
393 RunBaseTest(&test);
394}
395
Peter Boström12996152016-05-14 02:03:18 +0200396#if !defined(RTC_DISABLE_VP9)
philipel277a8b52017-03-16 05:19:49 -0700397TEST_F(EndToEndTest, SendsAndReceivesVP9) {
magjed509e4fe2016-11-18 01:34:11 -0800398 CodecObserver test(500, kVideoRotation_0, "VP9", VP9Encoder::Create(),
Perba7dc722016-04-19 15:01:23 +0200399 VP9Decoder::Create());
400 RunBaseTest(&test);
401}
402
philipel277a8b52017-03-16 05:19:49 -0700403TEST_F(EndToEndTest, SendsAndReceivesVP9VideoRotation90) {
magjed509e4fe2016-11-18 01:34:11 -0800404 CodecObserver test(5, kVideoRotation_90, "VP9", VP9Encoder::Create(),
Perba7dc722016-04-19 15:01:23 +0200405 VP9Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800406 RunBaseTest(&test);
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000407}
Peter Boström12996152016-05-14 02:03:18 +0200408#endif // !defined(RTC_DISABLE_VP9)
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000409
brandtr445fb8f2016-11-14 04:11:23 -0800410#if defined(WEBRTC_USE_H264)
philipel277a8b52017-03-16 05:19:49 -0700411TEST_F(EndToEndTest, SendsAndReceivesH264) {
magjedceecea42016-11-28 07:20:21 -0800412 CodecObserver test(500, kVideoRotation_0, "H264",
413 H264Encoder::Create(cricket::VideoCodec("H264")),
Perba7dc722016-04-19 15:01:23 +0200414 H264Decoder::Create());
415 RunBaseTest(&test);
416}
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000417
philipel277a8b52017-03-16 05:19:49 -0700418TEST_F(EndToEndTest, SendsAndReceivesH264VideoRotation90) {
magjedceecea42016-11-28 07:20:21 -0800419 CodecObserver test(5, kVideoRotation_90, "H264",
420 H264Encoder::Create(cricket::VideoCodec("H264")),
Perba7dc722016-04-19 15:01:23 +0200421 H264Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800422 RunBaseTest(&test);
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000423}
hta9aa96882016-12-06 05:36:03 -0800424
philipel277a8b52017-03-16 05:19:49 -0700425TEST_F(EndToEndTest, SendsAndReceivesH264PacketizationMode0) {
hta9aa96882016-12-06 05:36:03 -0800426 cricket::VideoCodec codec = cricket::VideoCodec("H264");
427 codec.SetParam(cricket::kH264FmtpPacketizationMode, "0");
428 CodecObserver test(500, kVideoRotation_0, "H264", H264Encoder::Create(codec),
429 H264Decoder::Create());
430 RunBaseTest(&test);
431}
432
philipel277a8b52017-03-16 05:19:49 -0700433TEST_F(EndToEndTest, SendsAndReceivesH264PacketizationMode1) {
hta9aa96882016-12-06 05:36:03 -0800434 cricket::VideoCodec codec = cricket::VideoCodec("H264");
435 codec.SetParam(cricket::kH264FmtpPacketizationMode, "1");
436 CodecObserver test(500, kVideoRotation_0, "H264", H264Encoder::Create(codec),
437 H264Decoder::Create());
438 RunBaseTest(&test);
439}
440
brandtr445fb8f2016-11-14 04:11:23 -0800441#endif // defined(WEBRTC_USE_H264)
hbosbab934b2016-01-27 01:36:03 -0800442
philipel277a8b52017-03-16 05:19:49 -0700443TEST_F(EndToEndTest, ReceiverUsesLocalSsrc) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000444 class SyncRtcpObserver : public test::EndToEndTest {
445 public:
446 SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {}
447
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000448 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
danilchap3dc929e2016-11-02 08:21:59 -0700449 test::RtcpPacketParser parser;
450 EXPECT_TRUE(parser.Parse(packet, length));
451 EXPECT_EQ(kReceiverLocalVideoSsrc, parser.sender_ssrc());
Peter Boström5811a392015-12-10 13:02:50 +0100452 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000453
454 return SEND_PACKET;
455 }
456
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000457 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100458 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000459 << "Timed out while waiting for a receiver RTCP packet to be sent.";
460 }
461 } test;
462
stefane74eef12016-01-08 06:47:13 -0800463 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000464}
465
philipel277a8b52017-03-16 05:19:49 -0700466TEST_F(EndToEndTest, ReceivesAndRetransmitsNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000467 static const int kNumberOfNacksToObserve = 2;
468 static const int kLossBurstSize = 2;
469 static const int kPacketsBetweenLossBursts = 9;
470 class NackObserver : public test::EndToEndTest {
471 public:
472 NackObserver()
473 : EndToEndTest(kLongTimeoutMs),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000474 sent_rtp_packets_(0),
475 packets_left_to_drop_(0),
476 nacks_left_(kNumberOfNacksToObserve) {}
477
478 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000479 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700480 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000481 RTPHeader header;
Peter Boström03671cb2015-12-07 15:22:24 +0100482 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000483
484 // Never drop retransmitted packets.
485 if (dropped_packets_.find(header.sequenceNumber) !=
486 dropped_packets_.end()) {
487 retransmitted_packets_.insert(header.sequenceNumber);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000488 return SEND_PACKET;
489 }
490
philipel8054c7e2017-01-10 05:19:19 -0800491 if (nacks_left_ <= 0 &&
492 retransmitted_packets_.size() == dropped_packets_.size()) {
493 observation_complete_.Set();
494 }
495
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000496 ++sent_rtp_packets_;
497
498 // Enough NACKs received, stop dropping packets.
Stefan Holmer586b19b2015-09-18 11:14:31 +0200499 if (nacks_left_ <= 0)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000500 return SEND_PACKET;
501
502 // Check if it's time for a new loss burst.
503 if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
504 packets_left_to_drop_ = kLossBurstSize;
505
Stefan Holmer01b48882015-05-05 10:21:24 +0200506 // Never drop padding packets as those won't be retransmitted.
507 if (packets_left_to_drop_ > 0 && header.paddingLength == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000508 --packets_left_to_drop_;
509 dropped_packets_.insert(header.sequenceNumber);
510 return DROP_PACKET;
511 }
512
513 return SEND_PACKET;
514 }
515
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000516 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700517 rtc::CritScope lock(&crit_);
danilchap3dc929e2016-11-02 08:21:59 -0700518 test::RtcpPacketParser parser;
519 EXPECT_TRUE(parser.Parse(packet, length));
520 nacks_left_ -= parser.nack()->num_packets();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000521 return SEND_PACKET;
522 }
523
stefanff483612015-12-21 03:14:00 -0800524 void ModifyVideoConfigs(
525 VideoSendStream::Config* send_config,
526 std::vector<VideoReceiveStream::Config>* receive_configs,
527 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000528 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000529 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000530 }
531
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000532 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100533 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000534 << "Timed out waiting for packets to be NACKed, retransmitted and "
535 "rendered.";
536 }
537
stefanf116bd02015-10-27 08:29:42 -0700538 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000539 std::set<uint16_t> dropped_packets_;
540 std::set<uint16_t> retransmitted_packets_;
541 uint64_t sent_rtp_packets_;
542 int packets_left_to_drop_;
danilchapa37de392017-09-09 04:17:22 -0700543 int nacks_left_ RTC_GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000544 } test;
545
stefane74eef12016-01-08 06:47:13 -0800546 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000547}
548
philipel277a8b52017-03-16 05:19:49 -0700549TEST_F(EndToEndTest, ReceivesNackAndRetransmitsAudio) {
Erik Språng737336d2016-07-29 12:59:36 +0200550 class NackObserver : public test::EndToEndTest {
551 public:
552 NackObserver()
553 : EndToEndTest(kLongTimeoutMs),
554 local_ssrc_(0),
555 remote_ssrc_(0),
556 receive_transport_(nullptr) {}
557
558 private:
559 size_t GetNumVideoStreams() const override { return 0; }
560 size_t GetNumAudioStreams() const override { return 1; }
561
eladalon413ee9a2017-08-22 04:02:52 -0700562 test::PacketTransport* CreateReceiveTransport(
563 test::SingleThreadedTaskQueueForTesting* task_queue) override {
Erik Språng737336d2016-07-29 12:59:36 +0200564 test::PacketTransport* receive_transport = new test::PacketTransport(
eladalon413ee9a2017-08-22 04:02:52 -0700565 task_queue, nullptr, this, test::PacketTransport::kReceiver,
566 payload_type_map_, FakeNetworkPipe::Config());
Erik Språng737336d2016-07-29 12:59:36 +0200567 receive_transport_ = receive_transport;
568 return receive_transport;
569 }
570
571 Action OnSendRtp(const uint8_t* packet, size_t length) override {
572 RTPHeader header;
573 EXPECT_TRUE(parser_->Parse(packet, length, &header));
574
575 if (!sequence_number_to_retransmit_) {
576 sequence_number_to_retransmit_ =
577 rtc::Optional<uint16_t>(header.sequenceNumber);
578
579 // Don't ask for retransmission straight away, may be deduped in pacer.
580 } else if (header.sequenceNumber == *sequence_number_to_retransmit_) {
581 observation_complete_.Set();
582 } else {
583 // Send a NACK as often as necessary until retransmission is received.
584 rtcp::Nack nack;
danilchap822a16f2016-09-27 09:27:47 -0700585 nack.SetSenderSsrc(local_ssrc_);
586 nack.SetMediaSsrc(remote_ssrc_);
Erik Språng737336d2016-07-29 12:59:36 +0200587 uint16_t nack_list[] = {*sequence_number_to_retransmit_};
danilchap822a16f2016-09-27 09:27:47 -0700588 nack.SetPacketIds(nack_list, 1);
Erik Språng737336d2016-07-29 12:59:36 +0200589 rtc::Buffer buffer = nack.Build();
590
591 EXPECT_TRUE(receive_transport_->SendRtcp(buffer.data(), buffer.size()));
592 }
593
594 return SEND_PACKET;
595 }
596
597 void ModifyAudioConfigs(
598 AudioSendStream::Config* send_config,
599 std::vector<AudioReceiveStream::Config>* receive_configs) override {
600 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
601 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
602 local_ssrc_ = (*receive_configs)[0].rtp.local_ssrc;
603 remote_ssrc_ = (*receive_configs)[0].rtp.remote_ssrc;
604 }
605
606 void PerformTest() override {
607 EXPECT_TRUE(Wait())
608 << "Timed out waiting for packets to be NACKed, retransmitted and "
609 "rendered.";
610 }
611
612 uint32_t local_ssrc_;
613 uint32_t remote_ssrc_;
614 Transport* receive_transport_;
615 rtc::Optional<uint16_t> sequence_number_to_retransmit_;
616 } test;
617
618 RunBaseTest(&test);
619}
620
brandtrc55f27a2017-03-20 06:32:59 -0700621TEST_F(EndToEndTest, ReceivesUlpfec) {
brandtr535830e2016-10-31 03:45:58 -0700622 class UlpfecRenderObserver : public test::EndToEndTest,
623 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000624 public:
brandtr535830e2016-10-31 03:45:58 -0700625 UlpfecRenderObserver()
brandtr1134b7b2017-02-06 06:35:47 -0800626 : EndToEndTest(kDefaultTimeoutMs),
brandtrc55f27a2017-03-20 06:32:59 -0700627 encoder_(VP8Encoder::Create()),
brandtr1134b7b2017-02-06 06:35:47 -0800628 random_(0xcafef00d1),
629 num_packets_sent_(0) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000630
631 private:
stefanf116bd02015-10-27 08:29:42 -0700632 Action OnSendRtp(const uint8_t* packet, size_t length) override {
633 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000634 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000635 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000636
brandtrc55f27a2017-03-20 06:32:59 -0700637 EXPECT_TRUE(header.payloadType == kVideoSendPayloadType ||
brandtr1134b7b2017-02-06 06:35:47 -0800638 header.payloadType == kRedPayloadType)
639 << "Unknown payload type received.";
640 EXPECT_EQ(kVideoSendSsrcs[0], header.ssrc) << "Unknown SSRC received.";
641
642 // Parse RED header.
Stefan Holmer01b48882015-05-05 10:21:24 +0200643 int encapsulated_payload_type = -1;
644 if (header.payloadType == kRedPayloadType) {
645 encapsulated_payload_type =
646 static_cast<int>(packet[header.headerLength]);
brandtr1134b7b2017-02-06 06:35:47 -0800647
brandtrc55f27a2017-03-20 06:32:59 -0700648 EXPECT_TRUE(encapsulated_payload_type == kVideoSendPayloadType ||
brandtr1134b7b2017-02-06 06:35:47 -0800649 encapsulated_payload_type == kUlpfecPayloadType)
650 << "Unknown encapsulated payload type received.";
Stefan Holmer01b48882015-05-05 10:21:24 +0200651 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000652
brandtrc55f27a2017-03-20 06:32:59 -0700653 // To minimize test flakiness, always let ULPFEC packets through.
brandtr1134b7b2017-02-06 06:35:47 -0800654 if (encapsulated_payload_type == kUlpfecPayloadType) {
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000655 return SEND_PACKET;
656 }
657
brandtr1134b7b2017-02-06 06:35:47 -0800658 // Simulate 5% video packet loss after rampup period. Record the
659 // corresponding timestamps that were dropped.
660 if (num_packets_sent_++ > 100 && random_.Rand(1, 100) <= 5) {
brandtrc55f27a2017-03-20 06:32:59 -0700661 if (encapsulated_payload_type == kVideoSendPayloadType) {
brandtr1134b7b2017-02-06 06:35:47 -0800662 dropped_sequence_numbers_.insert(header.sequenceNumber);
663 dropped_timestamps_.insert(header.timestamp);
664 }
brandtr1134b7b2017-02-06 06:35:47 -0800665 return DROP_PACKET;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000666 }
667
668 return SEND_PACKET;
669 }
670
nisseeb83a1a2016-03-21 01:27:56 -0700671 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200672 rtc::CritScope lock(&crit_);
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000673 // Rendering frame with timestamp of packet that was dropped -> FEC
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000674 // protection worked.
brandtr1134b7b2017-02-06 06:35:47 -0800675 auto it = dropped_timestamps_.find(video_frame.timestamp());
676 if (it != dropped_timestamps_.end()) {
Peter Boström5811a392015-12-10 13:02:50 +0100677 observation_complete_.Set();
brandtr1134b7b2017-02-06 06:35:47 -0800678 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000679 }
680
stefanff483612015-12-21 03:14:00 -0800681 void ModifyVideoConfigs(
682 VideoSendStream::Config* send_config,
683 std::vector<VideoReceiveStream::Config>* receive_configs,
684 VideoEncoderConfig* encoder_config) override {
brandtrc55f27a2017-03-20 06:32:59 -0700685 // Use VP8 instead of FAKE, since the latter does not have PictureID
686 // in the packetization headers.
687 send_config->encoder_settings.encoder = encoder_.get();
688 send_config->encoder_settings.payload_name = "VP8";
689 send_config->encoder_settings.payload_type = kVideoSendPayloadType;
690 VideoReceiveStream::Decoder decoder =
691 test::CreateMatchingDecoder(send_config->encoder_settings);
692 decoder_.reset(decoder.decoder);
693 (*receive_configs)[0].decoders.clear();
694 (*receive_configs)[0].decoders.push_back(decoder);
695
696 // Enable ULPFEC over RED.
brandtrb5f2c3f2016-10-04 23:28:39 -0700697 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
698 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
nisse3b3622f2017-09-26 02:49:21 -0700699 (*receive_configs)[0].rtp.red_payload_type = kRedPayloadType;
700 (*receive_configs)[0].rtp.ulpfec_payload_type = kUlpfecPayloadType;
brandtrc55f27a2017-03-20 06:32:59 -0700701
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000702 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000703 }
704
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000705 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100706 EXPECT_TRUE(Wait())
brandtr1e3dfbf2016-11-16 22:45:19 -0800707 << "Timed out waiting for dropped frames to be rendered.";
708 }
709
710 rtc::CriticalSection crit_;
brandtrc55f27a2017-03-20 06:32:59 -0700711 std::unique_ptr<VideoEncoder> encoder_;
712 std::unique_ptr<VideoDecoder> decoder_;
danilchapa37de392017-09-09 04:17:22 -0700713 std::set<uint32_t> dropped_sequence_numbers_ RTC_GUARDED_BY(crit_);
brandtr1134b7b2017-02-06 06:35:47 -0800714 // Several packets can have the same timestamp.
danilchapa37de392017-09-09 04:17:22 -0700715 std::multiset<uint32_t> dropped_timestamps_ RTC_GUARDED_BY(crit_);
brandtr1134b7b2017-02-06 06:35:47 -0800716 Random random_;
danilchapa37de392017-09-09 04:17:22 -0700717 int num_packets_sent_ RTC_GUARDED_BY(crit_);
brandtr1e3dfbf2016-11-16 22:45:19 -0800718 } test;
719
720 RunBaseTest(&test);
721}
722
brandtrfa5a3682017-01-17 01:33:54 -0800723class FlexfecRenderObserver : public test::EndToEndTest,
724 public rtc::VideoSinkInterface<VideoFrame> {
725 public:
726 static constexpr uint32_t kVideoLocalSsrc = 123;
727 static constexpr uint32_t kFlexfecLocalSsrc = 456;
brandtr1e3dfbf2016-11-16 22:45:19 -0800728
brandtr1134b7b2017-02-06 06:35:47 -0800729 explicit FlexfecRenderObserver(bool enable_nack, bool expect_flexfec_rtcp)
brandtrfa5a3682017-01-17 01:33:54 -0800730 : test::EndToEndTest(test::CallTest::kDefaultTimeoutMs),
brandtr1134b7b2017-02-06 06:35:47 -0800731 enable_nack_(enable_nack),
brandtrfa5a3682017-01-17 01:33:54 -0800732 expect_flexfec_rtcp_(expect_flexfec_rtcp),
733 received_flexfec_rtcp_(false),
brandtr1134b7b2017-02-06 06:35:47 -0800734 random_(0xcafef00d1),
735 num_packets_sent_(0) {}
brandtr1e3dfbf2016-11-16 22:45:19 -0800736
brandtrfa5a3682017-01-17 01:33:54 -0800737 size_t GetNumFlexfecStreams() const override { return 1; }
brandtr1e3dfbf2016-11-16 22:45:19 -0800738
brandtrfa5a3682017-01-17 01:33:54 -0800739 private:
740 Action OnSendRtp(const uint8_t* packet, size_t length) override {
741 rtc::CritScope lock(&crit_);
742 RTPHeader header;
743 EXPECT_TRUE(parser_->Parse(packet, length, &header));
brandtr1e3dfbf2016-11-16 22:45:19 -0800744
brandtr1134b7b2017-02-06 06:35:47 -0800745 EXPECT_TRUE(header.payloadType ==
746 test::CallTest::kFakeVideoSendPayloadType ||
747 header.payloadType == test::CallTest::kFlexfecPayloadType ||
748 (enable_nack_ &&
749 header.payloadType == test::CallTest::kSendRtxPayloadType))
750 << "Unknown payload type received.";
751 EXPECT_TRUE(
752 header.ssrc == test::CallTest::kVideoSendSsrcs[0] ||
753 header.ssrc == test::CallTest::kFlexfecSendSsrc ||
754 (enable_nack_ && header.ssrc == test::CallTest::kSendRtxSsrcs[0]))
755 << "Unknown SSRC received.";
756
757 // To reduce test flakiness, always let FlexFEC packets through.
758 if (header.payloadType == test::CallTest::kFlexfecPayloadType) {
759 EXPECT_EQ(test::CallTest::kFlexfecSendSsrc, header.ssrc);
760
761 return SEND_PACKET;
brandtr1e3dfbf2016-11-16 22:45:19 -0800762 }
763
brandtr1134b7b2017-02-06 06:35:47 -0800764 // To reduce test flakiness, always let RTX packets through.
765 if (header.payloadType == test::CallTest::kSendRtxPayloadType) {
766 EXPECT_EQ(test::CallTest::kSendRtxSsrcs[0], header.ssrc);
767
768 // Parse RTX header.
769 uint16_t original_sequence_number =
770 ByteReader<uint16_t>::ReadBigEndian(&packet[header.headerLength]);
771
772 // From the perspective of FEC, a retransmitted packet is no longer
773 // dropped, so remove it from list of dropped packets.
774 auto seq_num_it =
775 dropped_sequence_numbers_.find(original_sequence_number);
brandtrfa5a3682017-01-17 01:33:54 -0800776 if (seq_num_it != dropped_sequence_numbers_.end()) {
777 dropped_sequence_numbers_.erase(seq_num_it);
778 auto ts_it = dropped_timestamps_.find(header.timestamp);
779 EXPECT_NE(ts_it, dropped_timestamps_.end());
780 dropped_timestamps_.erase(ts_it);
brandtrfd8d2652017-02-06 06:19:51 -0800781 }
brandtr1134b7b2017-02-06 06:35:47 -0800782
783 return SEND_PACKET;
brandtrfa5a3682017-01-17 01:33:54 -0800784 }
785
brandtr1134b7b2017-02-06 06:35:47 -0800786 // Simulate 5% video packet loss after rampup period. Record the
787 // corresponding timestamps that were dropped.
788 if (num_packets_sent_++ > 100 && random_.Rand(1, 100) <= 5) {
789 EXPECT_EQ(test::CallTest::kFakeVideoSendPayloadType, header.payloadType);
790 EXPECT_EQ(test::CallTest::kVideoSendSsrcs[0], header.ssrc);
791
792 dropped_sequence_numbers_.insert(header.sequenceNumber);
793 dropped_timestamps_.insert(header.timestamp);
brandtrfa5a3682017-01-17 01:33:54 -0800794
795 return DROP_PACKET;
796 }
797
798 return SEND_PACKET;
799 }
800
801 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
802 test::RtcpPacketParser parser;
803
804 parser.Parse(data, length);
805 if (parser.sender_ssrc() == kFlexfecLocalSsrc) {
806 EXPECT_EQ(1, parser.receiver_report()->num_packets());
807 const std::vector<rtcp::ReportBlock>& report_blocks =
808 parser.receiver_report()->report_blocks();
809 if (!report_blocks.empty()) {
810 EXPECT_EQ(1U, report_blocks.size());
811 EXPECT_EQ(test::CallTest::kFlexfecSendSsrc,
812 report_blocks[0].source_ssrc());
brandtr1d2d7892017-01-18 00:40:07 -0800813 rtc::CritScope lock(&crit_);
brandtrfa5a3682017-01-17 01:33:54 -0800814 received_flexfec_rtcp_ = true;
815 }
816 }
817
818 return SEND_PACKET;
819 }
820
eladalon413ee9a2017-08-22 04:02:52 -0700821 test::PacketTransport* CreateSendTransport(
822 test::SingleThreadedTaskQueueForTesting* task_queue,
823 Call* sender_call) override {
brandtr1134b7b2017-02-06 06:35:47 -0800824 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
825 const int kNetworkDelayMs = 100;
826 FakeNetworkPipe::Config config;
827 config.queue_delay_ms = kNetworkDelayMs;
eladalon413ee9a2017-08-22 04:02:52 -0700828 return new test::PacketTransport(task_queue, sender_call, this,
nissee5ad5ca2017-03-29 23:57:43 -0700829 test::PacketTransport::kSender,
minyue20c84cc2017-04-10 16:57:57 -0700830 test::CallTest::payload_type_map_, config);
brandtr1134b7b2017-02-06 06:35:47 -0800831 }
832
brandtrfa5a3682017-01-17 01:33:54 -0800833 void OnFrame(const VideoFrame& video_frame) override {
brandtrcaea68f2017-08-23 00:55:17 -0700834 EXPECT_EQ(kVideoRotation_90, video_frame.rotation());
835
brandtrfa5a3682017-01-17 01:33:54 -0800836 rtc::CritScope lock(&crit_);
837 // Rendering frame with timestamp of packet that was dropped -> FEC
838 // protection worked.
839 auto it = dropped_timestamps_.find(video_frame.timestamp());
840 if (it != dropped_timestamps_.end()) {
841 if (!expect_flexfec_rtcp_ || received_flexfec_rtcp_) {
brandtr1e3dfbf2016-11-16 22:45:19 -0800842 observation_complete_.Set();
brandtrfa5a3682017-01-17 01:33:54 -0800843 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800844 }
brandtrfa5a3682017-01-17 01:33:54 -0800845 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800846
brandtrfa5a3682017-01-17 01:33:54 -0800847 void ModifyVideoConfigs(
848 VideoSendStream::Config* send_config,
849 std::vector<VideoReceiveStream::Config>* receive_configs,
850 VideoEncoderConfig* encoder_config) override {
851 (*receive_configs)[0].rtp.local_ssrc = kVideoLocalSsrc;
852 (*receive_configs)[0].renderer = this;
brandtr1134b7b2017-02-06 06:35:47 -0800853
854 if (enable_nack_) {
855 send_config->rtp.nack.rtp_history_ms = test::CallTest::kNackRtpHistoryMs;
brandtr1134b7b2017-02-06 06:35:47 -0800856 send_config->rtp.rtx.ssrcs.push_back(test::CallTest::kSendRtxSsrcs[0]);
857 send_config->rtp.rtx.payload_type = test::CallTest::kSendRtxPayloadType;
858
859 (*receive_configs)[0].rtp.nack.rtp_history_ms =
860 test::CallTest::kNackRtpHistoryMs;
brandtr1134b7b2017-02-06 06:35:47 -0800861 (*receive_configs)[0].rtp.rtx_ssrc = test::CallTest::kSendRtxSsrcs[0];
862 (*receive_configs)[0]
nisse26e3abb2017-08-25 04:44:25 -0700863 .rtp
864 .rtx_associated_payload_types[test::CallTest::kSendRtxPayloadType] =
865 test::CallTest::kVideoSendPayloadType;
brandtr1134b7b2017-02-06 06:35:47 -0800866 }
brandtrfa5a3682017-01-17 01:33:54 -0800867 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800868
brandtrcaea68f2017-08-23 00:55:17 -0700869 void OnFrameGeneratorCapturerCreated(
870 test::FrameGeneratorCapturer* frame_generator_capturer) override {
871 frame_generator_capturer->SetFakeRotation(kVideoRotation_90);
872 }
873
brandtrfa5a3682017-01-17 01:33:54 -0800874 void ModifyFlexfecConfigs(
875 std::vector<FlexfecReceiveStream::Config>* receive_configs) override {
876 (*receive_configs)[0].local_ssrc = kFlexfecLocalSsrc;
877 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000878
brandtrfa5a3682017-01-17 01:33:54 -0800879 void PerformTest() override {
880 EXPECT_TRUE(Wait())
881 << "Timed out waiting for dropped frames to be rendered.";
882 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000883
brandtrfa5a3682017-01-17 01:33:54 -0800884 rtc::CriticalSection crit_;
danilchapa37de392017-09-09 04:17:22 -0700885 std::set<uint32_t> dropped_sequence_numbers_ RTC_GUARDED_BY(crit_);
brandtr1134b7b2017-02-06 06:35:47 -0800886 // Several packets can have the same timestamp.
danilchapa37de392017-09-09 04:17:22 -0700887 std::multiset<uint32_t> dropped_timestamps_ RTC_GUARDED_BY(crit_);
brandtr1134b7b2017-02-06 06:35:47 -0800888 const bool enable_nack_;
brandtr1d2d7892017-01-18 00:40:07 -0800889 const bool expect_flexfec_rtcp_;
danilchapa37de392017-09-09 04:17:22 -0700890 bool received_flexfec_rtcp_ RTC_GUARDED_BY(crit_);
brandtrfa5a3682017-01-17 01:33:54 -0800891 Random random_;
brandtr1134b7b2017-02-06 06:35:47 -0800892 int num_packets_sent_;
brandtrfa5a3682017-01-17 01:33:54 -0800893};
894
philipel277a8b52017-03-16 05:19:49 -0700895TEST_F(EndToEndTest, RecoversWithFlexfec) {
brandtr1134b7b2017-02-06 06:35:47 -0800896 FlexfecRenderObserver test(false, false);
brandtrfa5a3682017-01-17 01:33:54 -0800897 RunBaseTest(&test);
898}
899
philipel277a8b52017-03-16 05:19:49 -0700900TEST_F(EndToEndTest, RecoversWithFlexfecAndNack) {
brandtr1134b7b2017-02-06 06:35:47 -0800901 FlexfecRenderObserver test(true, false);
902 RunBaseTest(&test);
903}
904
philipel277a8b52017-03-16 05:19:49 -0700905TEST_F(EndToEndTest, RecoversWithFlexfecAndSendsCorrespondingRtcp) {
brandtr1134b7b2017-02-06 06:35:47 -0800906 FlexfecRenderObserver test(false, true);
stefane74eef12016-01-08 06:47:13 -0800907 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000908}
909
philipel277a8b52017-03-16 05:19:49 -0700910TEST_F(EndToEndTest, ReceivedUlpfecPacketsNotNacked) {
brandtr535830e2016-10-31 03:45:58 -0700911 class UlpfecNackObserver : public test::EndToEndTest {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000912 public:
brandtr535830e2016-10-31 03:45:58 -0700913 UlpfecNackObserver()
stefanf116bd02015-10-27 08:29:42 -0700914 : EndToEndTest(kDefaultTimeoutMs),
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000915 state_(kFirstPacket),
brandtr535830e2016-10-31 03:45:58 -0700916 ulpfec_sequence_number_(0),
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000917 has_last_sequence_number_(false),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200918 last_sequence_number_(0),
magjed509e4fe2016-11-18 01:34:11 -0800919 encoder_(VP8Encoder::Create()),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200920 decoder_(VP8Decoder::Create()) {}
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000921
922 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000923 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800924 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000925 RTPHeader header;
926 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000927
Stefan Holmer01b48882015-05-05 10:21:24 +0200928 int encapsulated_payload_type = -1;
929 if (header.payloadType == kRedPayloadType) {
930 encapsulated_payload_type =
931 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100932 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200933 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
934 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100935 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200936 }
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000937
938 if (has_last_sequence_number_ &&
939 !IsNewerSequenceNumber(header.sequenceNumber,
940 last_sequence_number_)) {
941 // Drop retransmitted packets.
942 return DROP_PACKET;
943 }
944 last_sequence_number_ = header.sequenceNumber;
945 has_last_sequence_number_ = true;
946
brandtr535830e2016-10-31 03:45:58 -0700947 bool ulpfec_packet = encapsulated_payload_type == kUlpfecPayloadType;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000948 switch (state_) {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000949 case kFirstPacket:
brandtr535830e2016-10-31 03:45:58 -0700950 state_ = kDropEveryOtherPacketUntilUlpfec;
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000951 break;
brandtr535830e2016-10-31 03:45:58 -0700952 case kDropEveryOtherPacketUntilUlpfec:
953 if (ulpfec_packet) {
954 state_ = kDropAllMediaPacketsUntilUlpfec;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000955 } else if (header.sequenceNumber % 2 == 0) {
956 return DROP_PACKET;
957 }
958 break;
brandtr535830e2016-10-31 03:45:58 -0700959 case kDropAllMediaPacketsUntilUlpfec:
960 if (!ulpfec_packet)
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000961 return DROP_PACKET;
brandtr535830e2016-10-31 03:45:58 -0700962 ulpfec_sequence_number_ = header.sequenceNumber;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200963 state_ = kDropOneMediaPacket;
964 break;
965 case kDropOneMediaPacket:
brandtr535830e2016-10-31 03:45:58 -0700966 if (ulpfec_packet)
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200967 return DROP_PACKET;
968 state_ = kPassOneMediaPacket;
969 return DROP_PACKET;
970 break;
971 case kPassOneMediaPacket:
brandtr535830e2016-10-31 03:45:58 -0700972 if (ulpfec_packet)
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200973 return DROP_PACKET;
974 // Pass one media packet after dropped packet after last FEC,
975 // otherwise receiver might never see a seq_no after
brandtr535830e2016-10-31 03:45:58 -0700976 // |ulpfec_sequence_number_|
977 state_ = kVerifyUlpfecPacketNotInNackList;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000978 break;
brandtr535830e2016-10-31 03:45:58 -0700979 case kVerifyUlpfecPacketNotInNackList:
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000980 // Continue to drop packets. Make sure no frame can be decoded.
brandtr535830e2016-10-31 03:45:58 -0700981 if (ulpfec_packet || header.sequenceNumber % 2 == 0)
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000982 return DROP_PACKET;
983 break;
984 }
985 return SEND_PACKET;
986 }
987
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000988 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800989 rtc::CritScope lock_(&crit_);
brandtr535830e2016-10-31 03:45:58 -0700990 if (state_ == kVerifyUlpfecPacketNotInNackList) {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000991 test::RtcpPacketParser rtcp_parser;
992 rtcp_parser.Parse(packet, length);
Danil Chapovalovba6f7be2016-09-02 18:29:10 +0200993 const std::vector<uint16_t>& nacks = rtcp_parser.nack()->packet_ids();
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200994 EXPECT_TRUE(std::find(nacks.begin(), nacks.end(),
brandtr535830e2016-10-31 03:45:58 -0700995 ulpfec_sequence_number_) == nacks.end())
996 << "Got nack for ULPFEC packet";
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000997 if (!nacks.empty() &&
brandtr535830e2016-10-31 03:45:58 -0700998 IsNewerSequenceNumber(nacks.back(), ulpfec_sequence_number_)) {
Peter Boström5811a392015-12-10 13:02:50 +0100999 observation_complete_.Set();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001000 }
1001 }
1002 return SEND_PACKET;
1003 }
1004
eladalon413ee9a2017-08-22 04:02:52 -07001005 test::PacketTransport* CreateSendTransport(
1006 test::SingleThreadedTaskQueueForTesting* task_queue,
1007 Call* sender_call) override {
stefane74eef12016-01-08 06:47:13 -08001008 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
1009 // Configure some network delay.
1010 const int kNetworkDelayMs = 50;
1011 FakeNetworkPipe::Config config;
1012 config.queue_delay_ms = kNetworkDelayMs;
eladalon413ee9a2017-08-22 04:02:52 -07001013 return new test::PacketTransport(task_queue, sender_call, this,
nissee5ad5ca2017-03-29 23:57:43 -07001014 test::PacketTransport::kSender,
minyue20c84cc2017-04-10 16:57:57 -07001015 payload_type_map_, config);
stefane74eef12016-01-08 06:47:13 -08001016 }
1017
Stefan Holmere5904162015-03-26 11:11:06 +01001018 // TODO(holmer): Investigate why we don't send FEC packets when the bitrate
1019 // is 10 kbps.
1020 Call::Config GetSenderCallConfig() override {
philipel4fb651d2017-04-10 03:54:05 -07001021 Call::Config config(event_log_.get());
Stefan Holmere5904162015-03-26 11:11:06 +01001022 const int kMinBitrateBps = 30000;
1023 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
1024 return config;
1025 }
1026
stefanff483612015-12-21 03:14:00 -08001027 void ModifyVideoConfigs(
1028 VideoSendStream::Config* send_config,
1029 std::vector<VideoReceiveStream::Config>* receive_configs,
1030 VideoEncoderConfig* encoder_config) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001031 // Configure hybrid NACK/FEC.
1032 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
brandtrb5f2c3f2016-10-04 23:28:39 -07001033 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
1034 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001035 // Set codec to VP8, otherwise NACK/FEC hybrid will be disabled.
1036 send_config->encoder_settings.encoder = encoder_.get();
1037 send_config->encoder_settings.payload_name = "VP8";
1038 send_config->encoder_settings.payload_type = kFakeVideoSendPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001039
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001040 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
nisse3b3622f2017-09-26 02:49:21 -07001041 (*receive_configs)[0].rtp.red_payload_type = kRedPayloadType;
1042 (*receive_configs)[0].rtp.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001043
1044 (*receive_configs)[0].decoders.resize(1);
1045 (*receive_configs)[0].decoders[0].payload_type =
1046 send_config->encoder_settings.payload_type;
1047 (*receive_configs)[0].decoders[0].payload_name =
1048 send_config->encoder_settings.payload_name;
1049 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001050 }
1051
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001052 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001053 EXPECT_TRUE(Wait())
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001054 << "Timed out while waiting for FEC packets to be received.";
1055 }
1056
1057 enum {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +00001058 kFirstPacket,
brandtr535830e2016-10-31 03:45:58 -07001059 kDropEveryOtherPacketUntilUlpfec,
1060 kDropAllMediaPacketsUntilUlpfec,
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001061 kDropOneMediaPacket,
1062 kPassOneMediaPacket,
brandtr535830e2016-10-31 03:45:58 -07001063 kVerifyUlpfecPacketNotInNackList,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001064 } state_;
1065
stefan608213e2015-11-01 14:56:10 -08001066 rtc::CriticalSection crit_;
danilchapa37de392017-09-09 04:17:22 -07001067 uint16_t ulpfec_sequence_number_ RTC_GUARDED_BY(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001068 bool has_last_sequence_number_;
1069 uint16_t last_sequence_number_;
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001070 std::unique_ptr<webrtc::VideoEncoder> encoder_;
1071 std::unique_ptr<webrtc::VideoDecoder> decoder_;
stefanf116bd02015-10-27 08:29:42 -07001072 } test;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001073
stefane74eef12016-01-08 06:47:13 -08001074 RunBaseTest(&test);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001075}
1076
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001077// This test drops second RTP packet with a marker bit set, makes sure it's
1078// retransmitted and renders. Retransmission SSRCs are also checked.
Peter Boström39593972016-02-15 11:27:15 +01001079void EndToEndTest::DecodesRetransmittedFrame(bool enable_rtx, bool enable_red) {
Peter Boström67680c12016-02-17 11:10:04 +01001080 static const int kDroppedFrameNumber = 10;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001081 class RetransmissionObserver : public test::EndToEndTest,
nisse76bc8e82017-02-07 09:37:41 -08001082 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001083 public:
Peter Boström39593972016-02-15 11:27:15 +01001084 RetransmissionObserver(bool enable_rtx, bool enable_red)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001085 : EndToEndTest(kDefaultTimeoutMs),
Peter Boström39593972016-02-15 11:27:15 +01001086 payload_type_(GetPayloadType(false, enable_red)),
1087 retransmission_ssrc_(enable_rtx ? kSendRtxSsrcs[0]
1088 : kVideoSendSsrcs[0]),
1089 retransmission_payload_type_(GetPayloadType(enable_rtx, enable_red)),
magjed509e4fe2016-11-18 01:34:11 -08001090 encoder_(VP8Encoder::Create()),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001091 marker_bits_observed_(0),
danilchap192717e2016-07-25 08:20:51 -07001092 retransmitted_timestamp_(0) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001093
1094 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001095 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001096 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001097 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001098 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001099
Peter Boström67680c12016-02-17 11:10:04 +01001100 // Ignore padding-only packets over RTX.
1101 if (header.payloadType != payload_type_) {
1102 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
1103 if (length == header.headerLength + header.paddingLength)
1104 return SEND_PACKET;
Stefan Holmer586b19b2015-09-18 11:14:31 +02001105 }
Peter Boström67680c12016-02-17 11:10:04 +01001106
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001107 if (header.timestamp == retransmitted_timestamp_) {
1108 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
1109 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001110 return SEND_PACKET;
1111 }
1112
Stefan Holmer586b19b2015-09-18 11:14:31 +02001113 // Found the final packet of the frame to inflict loss to, drop this and
1114 // expect a retransmission.
danilchapfdd381c2016-07-25 04:03:20 -07001115 if (header.payloadType == payload_type_ && header.markerBit &&
1116 ++marker_bits_observed_ == kDroppedFrameNumber) {
Danil Chapovalov18c65a42016-06-29 15:29:34 +02001117 // This should be the only dropped packet.
1118 EXPECT_EQ(0u, retransmitted_timestamp_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001119 retransmitted_timestamp_ = header.timestamp;
danilchap192717e2016-07-25 08:20:51 -07001120 if (std::find(rendered_timestamps_.begin(), rendered_timestamps_.end(),
1121 retransmitted_timestamp_) != rendered_timestamps_.end()) {
1122 // Frame was rendered before last packet was scheduled for sending.
1123 // This is extremly rare but possible scenario because prober able to
1124 // resend packet before it was send.
1125 // TODO(danilchap): Remove this corner case when prober would not be
1126 // able to sneak in between packet saved to history for resending and
1127 // pacer notified about existance of that packet for sending.
1128 // See https://bugs.chromium.org/p/webrtc/issues/detail?id=5540 for
1129 // details.
1130 observation_complete_.Set();
1131 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001132 return DROP_PACKET;
1133 }
1134
1135 return SEND_PACKET;
1136 }
1137
nisse76bc8e82017-02-07 09:37:41 -08001138 void OnFrame(const VideoFrame& frame) override {
brandtrcaea68f2017-08-23 00:55:17 -07001139 EXPECT_EQ(kVideoRotation_90, frame.rotation());
stefan5d837802017-02-08 07:09:05 -08001140 {
1141 rtc::CritScope lock(&crit_);
1142 if (frame.timestamp() == retransmitted_timestamp_)
1143 observation_complete_.Set();
1144 rendered_timestamps_.push_back(frame.timestamp());
1145 }
nisse76bc8e82017-02-07 09:37:41 -08001146 orig_renderer_->OnFrame(frame);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001147 }
1148
stefanff483612015-12-21 03:14:00 -08001149 void ModifyVideoConfigs(
1150 VideoSendStream::Config* send_config,
1151 std::vector<VideoReceiveStream::Config>* receive_configs,
1152 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001153 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
nisse76bc8e82017-02-07 09:37:41 -08001154
1155 // Insert ourselves into the rendering pipeline.
1156 RTC_DCHECK(!orig_renderer_);
1157 orig_renderer_ = (*receive_configs)[0].renderer;
1158 RTC_DCHECK(orig_renderer_);
stefan5d837802017-02-08 07:09:05 -08001159 (*receive_configs)[0].disable_prerenderer_smoothing = true;
nisse76bc8e82017-02-07 09:37:41 -08001160 (*receive_configs)[0].renderer = this;
1161
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001162 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
Shao Changbine62202f2015-04-21 20:24:50 +08001163
1164 if (payload_type_ == kRedPayloadType) {
brandtrb5f2c3f2016-10-04 23:28:39 -07001165 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
1166 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +01001167 if (retransmission_ssrc_ == kSendRtxSsrcs[0])
brandtrb5f2c3f2016-10-04 23:28:39 -07001168 send_config->rtp.ulpfec.red_rtx_payload_type = kRtxRedPayloadType;
nisse3b3622f2017-09-26 02:49:21 -07001169 (*receive_configs)[0].rtp.ulpfec_payload_type =
brandtrb5f2c3f2016-10-04 23:28:39 -07001170 send_config->rtp.ulpfec.ulpfec_payload_type;
nisse3b3622f2017-09-26 02:49:21 -07001171 (*receive_configs)[0].rtp.red_payload_type =
brandtrb5f2c3f2016-10-04 23:28:39 -07001172 send_config->rtp.ulpfec.red_payload_type;
Shao Changbine62202f2015-04-21 20:24:50 +08001173 }
1174
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001175 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
1176 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001177 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
brandtr14742122017-01-27 04:53:07 -08001178 (*receive_configs)[0].rtp.rtx_ssrc = kSendRtxSsrcs[0];
nisse26e3abb2017-08-25 04:44:25 -07001179 (*receive_configs)[0]
nisseca5706d2017-09-11 02:32:16 -07001180 .rtp.rtx_associated_payload_types[(payload_type_ == kRedPayloadType)
1181 ? kRtxRedPayloadType
1182 : kSendRtxPayloadType] =
nisse26e3abb2017-08-25 04:44:25 -07001183 payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001184 }
Peter Boström39593972016-02-15 11:27:15 +01001185 // Configure encoding and decoding with VP8, since generic packetization
1186 // doesn't support FEC with NACK.
kwibergaf476c72016-11-28 15:21:39 -08001187 RTC_DCHECK_EQ(1, (*receive_configs)[0].decoders.size());
Peter Boström39593972016-02-15 11:27:15 +01001188 send_config->encoder_settings.encoder = encoder_.get();
1189 send_config->encoder_settings.payload_name = "VP8";
1190 (*receive_configs)[0].decoders[0].payload_name = "VP8";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001191 }
1192
brandtrcaea68f2017-08-23 00:55:17 -07001193 void OnFrameGeneratorCapturerCreated(
1194 test::FrameGeneratorCapturer* frame_generator_capturer) override {
1195 frame_generator_capturer->SetFakeRotation(kVideoRotation_90);
1196 }
1197
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001198 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001199 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001200 << "Timed out while waiting for retransmission to render.";
1201 }
1202
nisse3b3622f2017-09-26 02:49:21 -07001203 int GetPayloadType(bool use_rtx, bool use_fec) {
1204 if (use_fec) {
Stefan Holmer10880012016-02-03 13:29:59 +01001205 if (use_rtx)
1206 return kRtxRedPayloadType;
1207 return kRedPayloadType;
1208 }
1209 if (use_rtx)
1210 return kSendRtxPayloadType;
1211 return kFakeVideoSendPayloadType;
Shao Changbine62202f2015-04-21 20:24:50 +08001212 }
1213
stefanf116bd02015-10-27 08:29:42 -07001214 rtc::CriticalSection crit_;
nisse76bc8e82017-02-07 09:37:41 -08001215 rtc::VideoSinkInterface<VideoFrame>* orig_renderer_ = nullptr;
Shao Changbine62202f2015-04-21 20:24:50 +08001216 const int payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001217 const uint32_t retransmission_ssrc_;
1218 const int retransmission_payload_type_;
kwiberg27f982b2016-03-01 11:52:33 -08001219 std::unique_ptr<VideoEncoder> encoder_;
Peter Boström39593972016-02-15 11:27:15 +01001220 const std::string payload_name_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001221 int marker_bits_observed_;
danilchapa37de392017-09-09 04:17:22 -07001222 uint32_t retransmitted_timestamp_ RTC_GUARDED_BY(&crit_);
1223 std::vector<uint32_t> rendered_timestamps_ RTC_GUARDED_BY(&crit_);
Peter Boström39593972016-02-15 11:27:15 +01001224 } test(enable_rtx, enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001225
stefane74eef12016-01-08 06:47:13 -08001226 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001227}
1228
philipel277a8b52017-03-16 05:19:49 -07001229TEST_F(EndToEndTest, DecodesRetransmittedFrame) {
Shao Changbine62202f2015-04-21 20:24:50 +08001230 DecodesRetransmittedFrame(false, false);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001231}
1232
philipel277a8b52017-03-16 05:19:49 -07001233TEST_F(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +08001234 DecodesRetransmittedFrame(true, false);
1235}
1236
philipel277a8b52017-03-16 05:19:49 -07001237TEST_F(EndToEndTest, DecodesRetransmittedFrameByRed) {
Shao Changbine62202f2015-04-21 20:24:50 +08001238 DecodesRetransmittedFrame(false, true);
1239}
1240
philipel277a8b52017-03-16 05:19:49 -07001241TEST_F(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +08001242 DecodesRetransmittedFrame(true, true);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001243}
1244
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001245void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
1246 static const int kPacketsToDrop = 1;
1247
nisse7ade7b32016-03-23 04:48:10 -07001248 class PliObserver : public test::EndToEndTest,
1249 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001250 public:
1251 explicit PliObserver(int rtp_history_ms)
1252 : EndToEndTest(kLongTimeoutMs),
1253 rtp_history_ms_(rtp_history_ms),
1254 nack_enabled_(rtp_history_ms > 0),
1255 highest_dropped_timestamp_(0),
1256 frames_to_drop_(0),
1257 received_pli_(false) {}
1258
1259 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001260 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001261 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001262 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001263 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001264
1265 // Drop all retransmitted packets to force a PLI.
1266 if (header.timestamp <= highest_dropped_timestamp_)
1267 return DROP_PACKET;
1268
1269 if (frames_to_drop_ > 0) {
1270 highest_dropped_timestamp_ = header.timestamp;
1271 --frames_to_drop_;
1272 return DROP_PACKET;
1273 }
1274
1275 return SEND_PACKET;
1276 }
1277
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001278 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001279 rtc::CritScope lock(&crit_);
danilchap3dc929e2016-11-02 08:21:59 -07001280 test::RtcpPacketParser parser;
1281 EXPECT_TRUE(parser.Parse(packet, length));
1282 if (!nack_enabled_)
1283 EXPECT_EQ(0, parser.nack()->num_packets());
1284 if (parser.pli()->num_packets() > 0)
1285 received_pli_ = true;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001286 return SEND_PACKET;
1287 }
1288
nisseeb83a1a2016-03-21 01:27:56 -07001289 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001290 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001291 if (received_pli_ &&
1292 video_frame.timestamp() > highest_dropped_timestamp_) {
Peter Boström5811a392015-12-10 13:02:50 +01001293 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001294 }
1295 if (!received_pli_)
1296 frames_to_drop_ = kPacketsToDrop;
1297 }
1298
stefanff483612015-12-21 03:14:00 -08001299 void ModifyVideoConfigs(
1300 VideoSendStream::Config* send_config,
1301 std::vector<VideoReceiveStream::Config>* receive_configs,
1302 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001303 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001304 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
1305 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001306 }
1307
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001308 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001309 EXPECT_TRUE(Wait()) << "Timed out waiting for PLI to be "
1310 "received and a frame to be "
1311 "rendered afterwards.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001312 }
1313
stefanf116bd02015-10-27 08:29:42 -07001314 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001315 int rtp_history_ms_;
1316 bool nack_enabled_;
danilchapa37de392017-09-09 04:17:22 -07001317 uint32_t highest_dropped_timestamp_ RTC_GUARDED_BY(&crit_);
1318 int frames_to_drop_ RTC_GUARDED_BY(&crit_);
1319 bool received_pli_ RTC_GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001320 } test(rtp_history_ms);
1321
stefane74eef12016-01-08 06:47:13 -08001322 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001323}
1324
philipel277a8b52017-03-16 05:19:49 -07001325TEST_F(EndToEndTest, ReceivesPliAndRecoversWithNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001326 ReceivesPliAndRecovers(1000);
1327}
1328
philipel277a8b52017-03-16 05:19:49 -07001329TEST_F(EndToEndTest, ReceivesPliAndRecoversWithoutNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001330 ReceivesPliAndRecovers(0);
1331}
1332
philipel277a8b52017-03-16 05:19:49 -07001333TEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001334 class PacketInputObserver : public PacketReceiver {
1335 public:
1336 explicit PacketInputObserver(PacketReceiver* receiver)
Peter Boström5811a392015-12-10 13:02:50 +01001337 : receiver_(receiver), delivered_packet_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001338
Peter Boström5811a392015-12-10 13:02:50 +01001339 bool Wait() { return delivered_packet_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001340
1341 private:
stefan68786d22015-09-08 05:36:15 -07001342 DeliveryStatus DeliverPacket(MediaType media_type,
1343 const uint8_t* packet,
1344 size_t length,
1345 const PacketTime& packet_time) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001346 if (RtpHeaderParser::IsRtcp(packet, length)) {
stefan68786d22015-09-08 05:36:15 -07001347 return receiver_->DeliverPacket(media_type, packet, length,
1348 packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001349 } else {
1350 DeliveryStatus delivery_status =
stefan68786d22015-09-08 05:36:15 -07001351 receiver_->DeliverPacket(media_type, packet, length, packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001352 EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
Peter Boström5811a392015-12-10 13:02:50 +01001353 delivered_packet_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001354 return delivery_status;
1355 }
1356 }
1357
1358 PacketReceiver* receiver_;
Peter Boström5811a392015-12-10 13:02:50 +01001359 rtc::Event delivered_packet_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001360 };
1361
eladalon413ee9a2017-08-22 04:02:52 -07001362 std::unique_ptr<test::DirectTransport> send_transport;
1363 std::unique_ptr<test::DirectTransport> receive_transport;
1364 std::unique_ptr<PacketInputObserver> input_observer;
solenberg4fbae2b2015-08-28 04:07:10 -07001365
eladalon413ee9a2017-08-22 04:02:52 -07001366 task_queue_.SendTask([this, &send_transport, &receive_transport,
1367 &input_observer]() {
1368 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001369
eladalon413ee9a2017-08-22 04:02:52 -07001370 send_transport = rtc::MakeUnique<test::DirectTransport>(
1371 &task_queue_, sender_call_.get(), payload_type_map_);
1372 receive_transport = rtc::MakeUnique<test::DirectTransport>(
1373 &task_queue_, receiver_call_.get(), payload_type_map_);
1374 input_observer =
1375 rtc::MakeUnique<PacketInputObserver>(receiver_call_->Receiver());
1376 send_transport->SetReceiver(input_observer.get());
1377 receive_transport->SetReceiver(sender_call_->Receiver());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001378
eladalon413ee9a2017-08-22 04:02:52 -07001379 CreateSendConfig(1, 0, 0, send_transport.get());
1380 CreateMatchingReceiveConfigs(receive_transport.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001381
eladalon413ee9a2017-08-22 04:02:52 -07001382 CreateVideoStreams();
1383 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
1384 kDefaultHeight);
1385 Start();
1386
1387 receiver_call_->DestroyVideoReceiveStream(video_receive_streams_[0]);
1388 video_receive_streams_.clear();
1389 });
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001390
1391 // Wait() waits for a received packet.
eladalon413ee9a2017-08-22 04:02:52 -07001392 EXPECT_TRUE(input_observer->Wait());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001393
eladalon413ee9a2017-08-22 04:02:52 -07001394 task_queue_.SendTask([this, &send_transport, &receive_transport]() {
1395 Stop();
1396 DestroyStreams();
1397 send_transport.reset();
1398 receive_transport.reset();
1399 DestroyCalls();
1400 });
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001401}
1402
pbosda903ea2015-10-02 02:36:56 -07001403void EndToEndTest::RespectsRtcpMode(RtcpMode rtcp_mode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001404 static const int kNumCompoundRtcpPacketsToObserve = 10;
1405 class RtcpModeObserver : public test::EndToEndTest {
1406 public:
pbosda903ea2015-10-02 02:36:56 -07001407 explicit RtcpModeObserver(RtcpMode rtcp_mode)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001408 : EndToEndTest(kDefaultTimeoutMs),
1409 rtcp_mode_(rtcp_mode),
1410 sent_rtp_(0),
1411 sent_rtcp_(0) {}
1412
1413 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001414 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanb77c7162017-02-06 06:29:38 -08001415 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001416 if (++sent_rtp_ % 3 == 0)
1417 return DROP_PACKET;
1418
1419 return SEND_PACKET;
1420 }
1421
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001422 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanb77c7162017-02-06 06:29:38 -08001423 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001424 ++sent_rtcp_;
danilchap3dc929e2016-11-02 08:21:59 -07001425 test::RtcpPacketParser parser;
1426 EXPECT_TRUE(parser.Parse(packet, length));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001427
danilchap3dc929e2016-11-02 08:21:59 -07001428 EXPECT_EQ(0, parser.sender_report()->num_packets());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001429
1430 switch (rtcp_mode_) {
pbosda903ea2015-10-02 02:36:56 -07001431 case RtcpMode::kCompound:
stefanb77c7162017-02-06 06:29:38 -08001432 // TODO(holmer): We shouldn't send transport feedback alone if
1433 // compound RTCP is negotiated.
1434 if (parser.receiver_report()->num_packets() == 0 &&
1435 parser.transport_feedback()->num_packets() == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001436 ADD_FAILURE() << "Received RTCP packet without receiver report for "
pbosda903ea2015-10-02 02:36:56 -07001437 "RtcpMode::kCompound.";
Peter Boström5811a392015-12-10 13:02:50 +01001438 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001439 }
1440
1441 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
Peter Boström5811a392015-12-10 13:02:50 +01001442 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001443
1444 break;
pbosda903ea2015-10-02 02:36:56 -07001445 case RtcpMode::kReducedSize:
danilchap3dc929e2016-11-02 08:21:59 -07001446 if (parser.receiver_report()->num_packets() == 0)
Peter Boström5811a392015-12-10 13:02:50 +01001447 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001448 break;
pbosda903ea2015-10-02 02:36:56 -07001449 case RtcpMode::kOff:
1450 RTC_NOTREACHED();
1451 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001452 }
1453
1454 return SEND_PACKET;
1455 }
1456
stefanff483612015-12-21 03:14:00 -08001457 void ModifyVideoConfigs(
1458 VideoSendStream::Config* send_config,
1459 std::vector<VideoReceiveStream::Config>* receive_configs,
1460 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001461 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001462 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1463 (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001464 }
1465
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001466 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001467 EXPECT_TRUE(Wait())
pbosda903ea2015-10-02 02:36:56 -07001468 << (rtcp_mode_ == RtcpMode::kCompound
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001469 ? "Timed out before observing enough compound packets."
1470 : "Timed out before receiving a non-compound RTCP packet.");
1471 }
1472
pbosda903ea2015-10-02 02:36:56 -07001473 RtcpMode rtcp_mode_;
stefanb77c7162017-02-06 06:29:38 -08001474 rtc::CriticalSection crit_;
1475 // Must be protected since RTCP can be sent by both the process thread
1476 // and the pacer thread.
danilchapa37de392017-09-09 04:17:22 -07001477 int sent_rtp_ RTC_GUARDED_BY(&crit_);
1478 int sent_rtcp_ RTC_GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001479 } test(rtcp_mode);
1480
stefane74eef12016-01-08 06:47:13 -08001481 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001482}
1483
philipel277a8b52017-03-16 05:19:49 -07001484TEST_F(EndToEndTest, UsesRtcpCompoundMode) {
pbosda903ea2015-10-02 02:36:56 -07001485 RespectsRtcpMode(RtcpMode::kCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001486}
1487
philipel277a8b52017-03-16 05:19:49 -07001488TEST_F(EndToEndTest, UsesRtcpReducedSizeMode) {
pbosda903ea2015-10-02 02:36:56 -07001489 RespectsRtcpMode(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001490}
1491
1492// Test sets up a Call multiple senders with different resolutions and SSRCs.
1493// Another is set up to receive all three of these with different renderers.
sprang867fb522015-08-03 04:38:41 -07001494class MultiStreamTest {
1495 public:
minyue20c84cc2017-04-10 16:57:57 -07001496 static constexpr size_t kNumStreams = 3;
1497 const uint8_t kVideoPayloadType = 124;
1498 const std::map<uint8_t, MediaType> payload_type_map_ = {
1499 {kVideoPayloadType, MediaType::VIDEO}};
1500
sprang867fb522015-08-03 04:38:41 -07001501 struct CodecSettings {
1502 uint32_t ssrc;
1503 int width;
1504 int height;
1505 } codec_settings[kNumStreams];
1506
eladalon413ee9a2017-08-22 04:02:52 -07001507 explicit MultiStreamTest(test::SingleThreadedTaskQueueForTesting* task_queue)
1508 : task_queue_(task_queue) {
sprang867fb522015-08-03 04:38:41 -07001509 // TODO(sprang): Cleanup when msvc supports explicit initializers for array.
1510 codec_settings[0] = {1, 640, 480};
1511 codec_settings[1] = {2, 320, 240};
1512 codec_settings[2] = {3, 240, 160};
1513 }
1514
1515 virtual ~MultiStreamTest() {}
1516
1517 void RunTest() {
skvlad11a9cbf2016-10-07 11:53:05 -07001518 webrtc::RtcEventLogNullImpl event_log;
1519 Call::Config config(&event_log);
eladalon413ee9a2017-08-22 04:02:52 -07001520 std::unique_ptr<Call> sender_call;
1521 std::unique_ptr<Call> receiver_call;
1522 std::unique_ptr<test::DirectTransport> sender_transport;
1523 std::unique_ptr<test::DirectTransport> receiver_transport;
sprang867fb522015-08-03 04:38:41 -07001524
1525 VideoSendStream* send_streams[kNumStreams];
1526 VideoReceiveStream* receive_streams[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001527 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
kwiberg4a206a92016-03-31 10:24:26 -07001528 std::vector<std::unique_ptr<VideoDecoder>> allocated_decoders;
eladalon413ee9a2017-08-22 04:02:52 -07001529 std::unique_ptr<VideoEncoder> encoders[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001530
eladalon413ee9a2017-08-22 04:02:52 -07001531 task_queue_->SendTask([&]() {
1532 sender_call = rtc::WrapUnique(Call::Create(config));
1533 receiver_call = rtc::WrapUnique(Call::Create(config));
1534 sender_transport =
1535 rtc::WrapUnique(CreateSendTransport(task_queue_, sender_call.get()));
1536 receiver_transport = rtc::WrapUnique(
1537 CreateReceiveTransport(task_queue_, receiver_call.get()));
sprang867fb522015-08-03 04:38:41 -07001538
eladalon413ee9a2017-08-22 04:02:52 -07001539 sender_transport->SetReceiver(receiver_call->Receiver());
1540 receiver_transport->SetReceiver(sender_call->Receiver());
sprang867fb522015-08-03 04:38:41 -07001541
eladalon413ee9a2017-08-22 04:02:52 -07001542 for (size_t i = 0; i < kNumStreams; ++i)
1543 encoders[i].reset(VP8Encoder::Create());
sprang867fb522015-08-03 04:38:41 -07001544
eladalon413ee9a2017-08-22 04:02:52 -07001545 for (size_t i = 0; i < kNumStreams; ++i) {
1546 uint32_t ssrc = codec_settings[i].ssrc;
1547 int width = codec_settings[i].width;
1548 int height = codec_settings[i].height;
sprang867fb522015-08-03 04:38:41 -07001549
eladalon413ee9a2017-08-22 04:02:52 -07001550 VideoSendStream::Config send_config(sender_transport.get());
1551 send_config.rtp.ssrcs.push_back(ssrc);
1552 send_config.encoder_settings.encoder = encoders[i].get();
1553 send_config.encoder_settings.payload_name = "VP8";
1554 send_config.encoder_settings.payload_type = kVideoPayloadType;
1555 VideoEncoderConfig encoder_config;
1556 test::FillEncoderConfiguration(1, &encoder_config);
1557 encoder_config.max_bitrate_bps = 100000;
sprang867fb522015-08-03 04:38:41 -07001558
eladalon413ee9a2017-08-22 04:02:52 -07001559 UpdateSendConfig(i, &send_config, &encoder_config,
1560 &frame_generators[i]);
sprang867fb522015-08-03 04:38:41 -07001561
eladalon413ee9a2017-08-22 04:02:52 -07001562 send_streams[i] = sender_call->CreateVideoSendStream(
1563 send_config.Copy(), encoder_config.Copy());
1564 send_streams[i]->Start();
1565
1566 VideoReceiveStream::Config receive_config(receiver_transport.get());
1567 receive_config.rtp.remote_ssrc = ssrc;
1568 receive_config.rtp.local_ssrc = test::CallTest::kReceiverLocalVideoSsrc;
1569 VideoReceiveStream::Decoder decoder =
1570 test::CreateMatchingDecoder(send_config.encoder_settings);
1571 allocated_decoders.push_back(
1572 std::unique_ptr<VideoDecoder>(decoder.decoder));
1573 receive_config.decoders.push_back(decoder);
1574
1575 UpdateReceiveConfig(i, &receive_config);
1576
1577 receive_streams[i] =
1578 receiver_call->CreateVideoReceiveStream(std::move(receive_config));
1579 receive_streams[i]->Start();
1580
1581 frame_generators[i] = test::FrameGeneratorCapturer::Create(
1582 width, height, 30, Clock::GetRealTimeClock());
1583 send_streams[i]->SetSource(
1584 frame_generators[i],
1585 VideoSendStream::DegradationPreference::kMaintainFramerate);
1586 frame_generators[i]->Start();
1587 }
1588 });
sprang867fb522015-08-03 04:38:41 -07001589
1590 Wait();
1591
eladalon413ee9a2017-08-22 04:02:52 -07001592 task_queue_->SendTask([&]() {
1593 for (size_t i = 0; i < kNumStreams; ++i) {
1594 frame_generators[i]->Stop();
1595 sender_call->DestroyVideoSendStream(send_streams[i]);
1596 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1597 delete frame_generators[i];
1598 }
sprang867fb522015-08-03 04:38:41 -07001599
eladalon413ee9a2017-08-22 04:02:52 -07001600 sender_transport.reset();
1601 receiver_transport.reset();
1602
1603 sender_call.reset();
1604 receiver_call.reset();
1605 });
sprang867fb522015-08-03 04:38:41 -07001606 }
1607
1608 protected:
1609 virtual void Wait() = 0;
1610 // Note: frame_generator is a point-to-pointer, since the actual instance
1611 // hasn't been created at the time of this call. Only when packets/frames
1612 // start flowing should this be dereferenced.
1613 virtual void UpdateSendConfig(
1614 size_t stream_index,
1615 VideoSendStream::Config* send_config,
1616 VideoEncoderConfig* encoder_config,
1617 test::FrameGeneratorCapturer** frame_generator) {}
1618 virtual void UpdateReceiveConfig(size_t stream_index,
1619 VideoReceiveStream::Config* receive_config) {
1620 }
eladalon413ee9a2017-08-22 04:02:52 -07001621 virtual test::DirectTransport* CreateSendTransport(
1622 test::SingleThreadedTaskQueueForTesting* task_queue,
1623 Call* sender_call) {
1624 return new test::DirectTransport(task_queue, sender_call,
1625 payload_type_map_);
sprang867fb522015-08-03 04:38:41 -07001626 }
eladalon413ee9a2017-08-22 04:02:52 -07001627 virtual test::DirectTransport* CreateReceiveTransport(
1628 test::SingleThreadedTaskQueueForTesting* task_queue,
1629 Call* receiver_call) {
1630 return new test::DirectTransport(task_queue, receiver_call,
1631 payload_type_map_);
sprang867fb522015-08-03 04:38:41 -07001632 }
eladalon413ee9a2017-08-22 04:02:52 -07001633
1634 test::SingleThreadedTaskQueueForTesting* const task_queue_;
sprang867fb522015-08-03 04:38:41 -07001635};
1636
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001637// Each renderer verifies that it receives the expected resolution, and as soon
1638// as every renderer has received a frame, the test finishes.
philipel277a8b52017-03-16 05:19:49 -07001639TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) {
nisse7ade7b32016-03-23 04:48:10 -07001640 class VideoOutputObserver : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001641 public:
sprang867fb522015-08-03 04:38:41 -07001642 VideoOutputObserver(const MultiStreamTest::CodecSettings& settings,
1643 uint32_t ssrc,
1644 test::FrameGeneratorCapturer** frame_generator)
1645 : settings_(settings),
1646 ssrc_(ssrc),
1647 frame_generator_(frame_generator),
Peter Boström5811a392015-12-10 13:02:50 +01001648 done_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001649
nisseeb83a1a2016-03-21 01:27:56 -07001650 void OnFrame(const VideoFrame& video_frame) override {
sprang867fb522015-08-03 04:38:41 -07001651 EXPECT_EQ(settings_.width, video_frame.width());
1652 EXPECT_EQ(settings_.height, video_frame.height());
1653 (*frame_generator_)->Stop();
Peter Boström5811a392015-12-10 13:02:50 +01001654 done_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001655 }
1656
sprang867fb522015-08-03 04:38:41 -07001657 uint32_t Ssrc() { return ssrc_; }
1658
Peter Boström5811a392015-12-10 13:02:50 +01001659 bool Wait() { return done_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001660
1661 private:
sprang867fb522015-08-03 04:38:41 -07001662 const MultiStreamTest::CodecSettings& settings_;
1663 const uint32_t ssrc_;
1664 test::FrameGeneratorCapturer** const frame_generator_;
Peter Boström5811a392015-12-10 13:02:50 +01001665 rtc::Event done_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001666 };
1667
sprang867fb522015-08-03 04:38:41 -07001668 class Tester : public MultiStreamTest {
1669 public:
eladalon413ee9a2017-08-22 04:02:52 -07001670 explicit Tester(test::SingleThreadedTaskQueueForTesting* task_queue)
1671 : MultiStreamTest(task_queue) {}
sprang867fb522015-08-03 04:38:41 -07001672 virtual ~Tester() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001673
sprang867fb522015-08-03 04:38:41 -07001674 protected:
1675 void Wait() override {
1676 for (const auto& observer : observers_) {
Peter Boström5811a392015-12-10 13:02:50 +01001677 EXPECT_TRUE(observer->Wait()) << "Time out waiting for from on ssrc "
1678 << observer->Ssrc();
sprang867fb522015-08-03 04:38:41 -07001679 }
1680 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001681
sprang867fb522015-08-03 04:38:41 -07001682 void UpdateSendConfig(
1683 size_t stream_index,
1684 VideoSendStream::Config* send_config,
1685 VideoEncoderConfig* encoder_config,
1686 test::FrameGeneratorCapturer** frame_generator) override {
1687 observers_[stream_index].reset(new VideoOutputObserver(
1688 codec_settings[stream_index], send_config->rtp.ssrcs.front(),
1689 frame_generator));
1690 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001691
sprang867fb522015-08-03 04:38:41 -07001692 void UpdateReceiveConfig(
1693 size_t stream_index,
1694 VideoReceiveStream::Config* receive_config) override {
1695 receive_config->renderer = observers_[stream_index].get();
1696 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001697
sprang867fb522015-08-03 04:38:41 -07001698 private:
kwiberg27f982b2016-03-01 11:52:33 -08001699 std::unique_ptr<VideoOutputObserver> observers_[kNumStreams];
eladalon413ee9a2017-08-22 04:02:52 -07001700 } tester(&task_queue_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001701
sprang867fb522015-08-03 04:38:41 -07001702 tester.RunTest();
1703}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001704
philipel277a8b52017-03-16 05:19:49 -07001705TEST_F(EndToEndTest, AssignsTransportSequenceNumbers) {
sprang867fb522015-08-03 04:38:41 -07001706 static const int kExtensionId = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001707
sprang867fb522015-08-03 04:38:41 -07001708 class RtpExtensionHeaderObserver : public test::DirectTransport {
1709 public:
minyue20c84cc2017-04-10 16:57:57 -07001710 RtpExtensionHeaderObserver(
eladalon413ee9a2017-08-22 04:02:52 -07001711 test::SingleThreadedTaskQueueForTesting* task_queue,
minyue20c84cc2017-04-10 16:57:57 -07001712 Call* sender_call,
1713 const uint32_t& first_media_ssrc,
1714 const std::map<uint32_t, uint32_t>& ssrc_map,
1715 const std::map<uint8_t, MediaType>& payload_type_map)
eladalon413ee9a2017-08-22 04:02:52 -07001716 : DirectTransport(task_queue, sender_call, payload_type_map),
Peter Boström5811a392015-12-10 13:02:50 +01001717 done_(false, false),
sprang867fb522015-08-03 04:38:41 -07001718 parser_(RtpHeaderParser::Create()),
sprang861c55e2015-10-16 10:01:21 -07001719 first_media_ssrc_(first_media_ssrc),
1720 rtx_to_media_ssrcs_(ssrc_map),
sprang867fb522015-08-03 04:38:41 -07001721 padding_observed_(false),
sprang861c55e2015-10-16 10:01:21 -07001722 rtx_padding_observed_(false),
1723 retransmit_observed_(false),
1724 started_(false) {
sprang867fb522015-08-03 04:38:41 -07001725 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
1726 kExtensionId);
1727 }
1728 virtual ~RtpExtensionHeaderObserver() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001729
stefan1d8a5062015-10-02 03:39:33 -07001730 bool SendRtp(const uint8_t* data,
1731 size_t length,
1732 const PacketOptions& options) override {
sprang861c55e2015-10-16 10:01:21 -07001733 {
1734 rtc::CritScope cs(&lock_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001735
Erik Språng8d629712015-08-04 16:24:03 +02001736 if (IsDone())
sprang861c55e2015-10-16 10:01:21 -07001737 return false;
1738
1739 if (started_) {
1740 RTPHeader header;
1741 EXPECT_TRUE(parser_->Parse(data, length, &header));
1742 bool drop_packet = false;
1743
1744 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
1745 EXPECT_EQ(options.packet_id,
1746 header.extension.transportSequenceNumber);
1747 if (!streams_observed_.empty()) {
1748 // Unwrap packet id and verify uniqueness.
1749 int64_t packet_id = unwrapper_.Unwrap(options.packet_id);
1750 EXPECT_TRUE(received_packed_ids_.insert(packet_id).second);
1751 }
1752
1753 // Drop (up to) every 17th packet, so we get retransmits.
1754 // Only drop media, and not on the first stream (otherwise it will be
1755 // hard to distinguish from padding, which is always sent on the first
1756 // stream).
1757 if (header.payloadType != kSendRtxPayloadType &&
1758 header.ssrc != first_media_ssrc_ &&
1759 header.extension.transportSequenceNumber % 17 == 0) {
1760 dropped_seq_[header.ssrc].insert(header.sequenceNumber);
1761 drop_packet = true;
1762 }
1763
perkja8ba1952017-02-27 06:52:10 -08001764 if (header.payloadType == kSendRtxPayloadType) {
sprang861c55e2015-10-16 10:01:21 -07001765 uint16_t original_sequence_number =
1766 ByteReader<uint16_t>::ReadBigEndian(&data[header.headerLength]);
1767 uint32_t original_ssrc =
1768 rtx_to_media_ssrcs_.find(header.ssrc)->second;
1769 std::set<uint16_t>* seq_no_map = &dropped_seq_[original_ssrc];
1770 auto it = seq_no_map->find(original_sequence_number);
1771 if (it != seq_no_map->end()) {
1772 retransmit_observed_ = true;
1773 seq_no_map->erase(it);
1774 } else {
1775 rtx_padding_observed_ = true;
1776 }
1777 } else {
1778 streams_observed_.insert(header.ssrc);
1779 }
1780
1781 if (IsDone())
Peter Boström5811a392015-12-10 13:02:50 +01001782 done_.Set();
sprang861c55e2015-10-16 10:01:21 -07001783
1784 if (drop_packet)
1785 return true;
1786 }
sprang867fb522015-08-03 04:38:41 -07001787 }
sprang861c55e2015-10-16 10:01:21 -07001788
stefan1d8a5062015-10-02 03:39:33 -07001789 return test::DirectTransport::SendRtp(data, length, options);
sprang867fb522015-08-03 04:38:41 -07001790 }
1791
Erik Språng8d629712015-08-04 16:24:03 +02001792 bool IsDone() {
sprang861c55e2015-10-16 10:01:21 -07001793 bool observed_types_ok =
1794 streams_observed_.size() == MultiStreamTest::kNumStreams &&
perkja8ba1952017-02-27 06:52:10 -08001795 retransmit_observed_ && rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001796 if (!observed_types_ok)
1797 return false;
1798 // We should not have any gaps in the sequence number range.
1799 size_t seqno_range =
1800 *received_packed_ids_.rbegin() - *received_packed_ids_.begin() + 1;
1801 return seqno_range == received_packed_ids_.size();
Erik Språng8d629712015-08-04 16:24:03 +02001802 }
1803
Peter Boström5811a392015-12-10 13:02:50 +01001804 bool Wait() {
sprang861c55e2015-10-16 10:01:21 -07001805 {
1806 // Can't be sure until this point that rtx_to_media_ssrcs_ etc have
1807 // been initialized and are OK to read.
1808 rtc::CritScope cs(&lock_);
1809 started_ = true;
1810 }
Peter Boström5811a392015-12-10 13:02:50 +01001811 return done_.Wait(kDefaultTimeoutMs);
sprang861c55e2015-10-16 10:01:21 -07001812 }
sprang867fb522015-08-03 04:38:41 -07001813
sprang861c55e2015-10-16 10:01:21 -07001814 rtc::CriticalSection lock_;
Peter Boström5811a392015-12-10 13:02:50 +01001815 rtc::Event done_;
kwiberg27f982b2016-03-01 11:52:33 -08001816 std::unique_ptr<RtpHeaderParser> parser_;
sprang861c55e2015-10-16 10:01:21 -07001817 SequenceNumberUnwrapper unwrapper_;
1818 std::set<int64_t> received_packed_ids_;
sprang867fb522015-08-03 04:38:41 -07001819 std::set<uint32_t> streams_observed_;
sprang861c55e2015-10-16 10:01:21 -07001820 std::map<uint32_t, std::set<uint16_t>> dropped_seq_;
1821 const uint32_t& first_media_ssrc_;
1822 const std::map<uint32_t, uint32_t>& rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001823 bool padding_observed_;
1824 bool rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001825 bool retransmit_observed_;
1826 bool started_;
sprang867fb522015-08-03 04:38:41 -07001827 };
1828
1829 class TransportSequenceNumberTester : public MultiStreamTest {
1830 public:
eladalon413ee9a2017-08-22 04:02:52 -07001831 explicit TransportSequenceNumberTester(
1832 test::SingleThreadedTaskQueueForTesting* task_queue)
1833 : MultiStreamTest(task_queue),
1834 first_media_ssrc_(0),
1835 observer_(nullptr) {}
sprang867fb522015-08-03 04:38:41 -07001836 virtual ~TransportSequenceNumberTester() {}
1837
1838 protected:
1839 void Wait() override {
Peter Boström74f6e9e2016-04-04 17:56:10 +02001840 RTC_DCHECK(observer_);
Peter Boström5811a392015-12-10 13:02:50 +01001841 EXPECT_TRUE(observer_->Wait());
sprang867fb522015-08-03 04:38:41 -07001842 }
1843
1844 void UpdateSendConfig(
1845 size_t stream_index,
1846 VideoSendStream::Config* send_config,
1847 VideoEncoderConfig* encoder_config,
1848 test::FrameGeneratorCapturer** frame_generator) override {
1849 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001850 send_config->rtp.extensions.push_back(RtpExtension(
1851 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sprang867fb522015-08-03 04:38:41 -07001852
perkja8ba1952017-02-27 06:52:10 -08001853 // Force some padding to be sent. Note that since we do send media
1854 // packets we can not guarantee that a padding only packet is sent.
1855 // Instead, padding will most likely be send as an RTX packet.
sprang867fb522015-08-03 04:38:41 -07001856 const int kPaddingBitrateBps = 50000;
perkja8ba1952017-02-27 06:52:10 -08001857 encoder_config->max_bitrate_bps = 200000;
sprang867fb522015-08-03 04:38:41 -07001858 encoder_config->min_transmit_bitrate_bps =
perkjfa10b552016-10-02 23:45:26 -07001859 encoder_config->max_bitrate_bps + kPaddingBitrateBps;
sprang867fb522015-08-03 04:38:41 -07001860
1861 // Configure RTX for redundant payload padding.
1862 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang861c55e2015-10-16 10:01:21 -07001863 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[stream_index]);
sprang867fb522015-08-03 04:38:41 -07001864 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
sprang861c55e2015-10-16 10:01:21 -07001865 rtx_to_media_ssrcs_[kSendRtxSsrcs[stream_index]] =
1866 send_config->rtp.ssrcs[0];
1867
1868 if (stream_index == 0)
1869 first_media_ssrc_ = send_config->rtp.ssrcs[0];
sprang867fb522015-08-03 04:38:41 -07001870 }
1871
1872 void UpdateReceiveConfig(
1873 size_t stream_index,
1874 VideoReceiveStream::Config* receive_config) override {
sprang861c55e2015-10-16 10:01:21 -07001875 receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang867fb522015-08-03 04:38:41 -07001876 receive_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001877 receive_config->rtp.extensions.push_back(RtpExtension(
1878 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sakal55d932b2016-09-30 06:19:08 -07001879 receive_config->renderer = &fake_renderer_;
sprang867fb522015-08-03 04:38:41 -07001880 }
1881
eladalon413ee9a2017-08-22 04:02:52 -07001882 test::DirectTransport* CreateSendTransport(
1883 test::SingleThreadedTaskQueueForTesting* task_queue,
1884 Call* sender_call) override {
minyue20c84cc2017-04-10 16:57:57 -07001885 std::map<uint8_t, MediaType> payload_type_map =
1886 MultiStreamTest::payload_type_map_;
1887 RTC_DCHECK(payload_type_map.find(kSendRtxPayloadType) ==
1888 payload_type_map.end());
1889 payload_type_map[kSendRtxPayloadType] = MediaType::VIDEO;
eladalon413ee9a2017-08-22 04:02:52 -07001890 observer_ = new RtpExtensionHeaderObserver(
1891 task_queue, sender_call, first_media_ssrc_, rtx_to_media_ssrcs_,
1892 payload_type_map);
sprang867fb522015-08-03 04:38:41 -07001893 return observer_;
1894 }
1895
1896 private:
sakal55d932b2016-09-30 06:19:08 -07001897 test::FakeVideoRenderer fake_renderer_;
sprang861c55e2015-10-16 10:01:21 -07001898 uint32_t first_media_ssrc_;
1899 std::map<uint32_t, uint32_t> rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001900 RtpExtensionHeaderObserver* observer_;
eladalon413ee9a2017-08-22 04:02:52 -07001901 } tester(&task_queue_);
sprang867fb522015-08-03 04:38:41 -07001902
1903 tester.RunTest();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001904}
1905
Stefan Holmer04cb7632016-01-14 20:34:30 +01001906class TransportFeedbackTester : public test::EndToEndTest {
1907 public:
stefan9e117c5e12017-08-16 08:16:25 -07001908 TransportFeedbackTester(bool feedback_enabled,
1909 size_t num_video_streams,
1910 size_t num_audio_streams)
Stefan Holmer04cb7632016-01-14 20:34:30 +01001911 : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
1912 feedback_enabled_(feedback_enabled),
1913 num_video_streams_(num_video_streams),
sprangcd349d92016-07-13 09:11:28 -07001914 num_audio_streams_(num_audio_streams),
1915 receiver_call_(nullptr) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001916 // Only one stream of each supported for now.
1917 EXPECT_LE(num_video_streams, 1u);
1918 EXPECT_LE(num_audio_streams, 1u);
1919 }
1920
1921 protected:
1922 Action OnSendRtcp(const uint8_t* data, size_t length) override {
1923 EXPECT_FALSE(HasTransportFeedback(data, length));
1924 return SEND_PACKET;
1925 }
1926
1927 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
1928 if (HasTransportFeedback(data, length))
1929 observation_complete_.Set();
1930 return SEND_PACKET;
1931 }
1932
1933 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
danilchap3dc929e2016-11-02 08:21:59 -07001934 test::RtcpPacketParser parser;
1935 EXPECT_TRUE(parser.Parse(data, length));
1936 return parser.transport_feedback()->num_packets() > 0;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001937 }
1938
1939 void PerformTest() override {
1940 const int64_t kDisabledFeedbackTimeoutMs = 5000;
1941 EXPECT_EQ(feedback_enabled_,
1942 observation_complete_.Wait(feedback_enabled_
1943 ? test::CallTest::kDefaultTimeoutMs
1944 : kDisabledFeedbackTimeoutMs));
1945 }
1946
1947 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1948 receiver_call_ = receiver_call;
1949 }
1950
1951 size_t GetNumVideoStreams() const override { return num_video_streams_; }
1952 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
1953
1954 void ModifyVideoConfigs(
1955 VideoSendStream::Config* send_config,
1956 std::vector<VideoReceiveStream::Config>* receive_configs,
1957 VideoEncoderConfig* encoder_config) override {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001958 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
1959 }
1960
1961 void ModifyAudioConfigs(
1962 AudioSendStream::Config* send_config,
1963 std::vector<AudioReceiveStream::Config>* receive_configs) override {
1964 send_config->rtp.extensions.clear();
1965 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001966 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001967 (*receive_configs)[0].rtp.extensions.clear();
1968 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1969 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001970 }
1971
1972 private:
Erik Språng6b8d3552015-09-24 15:06:57 +02001973 static const int kExtensionId = 5;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001974 const bool feedback_enabled_;
1975 const size_t num_video_streams_;
1976 const size_t num_audio_streams_;
1977 Call* receiver_call_;
1978};
Erik Språng6b8d3552015-09-24 15:06:57 +02001979
philipel277a8b52017-03-16 05:19:49 -07001980TEST_F(EndToEndTest, VideoReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001981 TransportFeedbackTester test(true, 1, 0);
1982 RunBaseTest(&test);
Erik Språng6b8d3552015-09-24 15:06:57 +02001983}
stefan43edf0f2015-11-20 18:05:48 -08001984
philipel277a8b52017-03-16 05:19:49 -07001985TEST_F(EndToEndTest, VideoTransportFeedbackNotConfigured) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001986 TransportFeedbackTester test(false, 1, 0);
1987 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001988}
1989
philipel277a8b52017-03-16 05:19:49 -07001990TEST_F(EndToEndTest, AudioReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001991 TransportFeedbackTester test(true, 0, 1);
1992 RunBaseTest(&test);
1993}
1994
philipel277a8b52017-03-16 05:19:49 -07001995TEST_F(EndToEndTest, AudioTransportFeedbackNotConfigured) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001996 TransportFeedbackTester test(false, 0, 1);
1997 RunBaseTest(&test);
1998}
1999
philipel277a8b52017-03-16 05:19:49 -07002000TEST_F(EndToEndTest, AudioVideoReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01002001 TransportFeedbackTester test(true, 1, 1);
2002 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08002003}
2004
stefan9e117c5e12017-08-16 08:16:25 -07002005TEST_F(EndToEndTest, StopsSendingMediaWithoutFeedback) {
2006 test::ScopedFieldTrials override_field_trials(
stefan74418272017-08-17 02:13:54 -07002007 "WebRTC-CwndExperiment/Enabled-250/");
stefan9e117c5e12017-08-16 08:16:25 -07002008
2009 class TransportFeedbackTester : public test::EndToEndTest {
2010 public:
2011 TransportFeedbackTester(size_t num_video_streams, size_t num_audio_streams)
2012 : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
2013 num_video_streams_(num_video_streams),
2014 num_audio_streams_(num_audio_streams),
2015 media_sent_(0),
2016 padding_sent_(0) {
2017 // Only one stream of each supported for now.
2018 EXPECT_LE(num_video_streams, 1u);
2019 EXPECT_LE(num_audio_streams, 1u);
2020 }
2021
2022 protected:
2023 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2024 RTPHeader header;
2025 EXPECT_TRUE(parser_->Parse(packet, length, &header));
2026 const bool only_padding =
2027 header.headerLength + header.paddingLength == length;
2028 rtc::CritScope lock(&crit_);
2029 if (only_padding) {
2030 ++padding_sent_;
2031 } else {
2032 ++media_sent_;
2033 EXPECT_LT(media_sent_, 40) << "Media sent without feedback.";
2034 }
2035
2036 return SEND_PACKET;
2037 }
2038
2039 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
2040 rtc::CritScope lock(&crit_);
2041 if (media_sent_ > 20 && HasTransportFeedback(data, length)) {
2042 return DROP_PACKET;
2043 }
2044 return SEND_PACKET;
2045 }
2046
2047 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
2048 test::RtcpPacketParser parser;
2049 EXPECT_TRUE(parser.Parse(data, length));
2050 return parser.transport_feedback()->num_packets() > 0;
2051 }
2052
2053 Call::Config GetSenderCallConfig() override {
2054 Call::Config config = EndToEndTest::GetSenderCallConfig();
2055 config.bitrate_config.max_bitrate_bps = 300000;
2056 return config;
2057 }
2058
2059 void PerformTest() override {
2060 const int64_t kDisabledFeedbackTimeoutMs = 10000;
2061 observation_complete_.Wait(kDisabledFeedbackTimeoutMs);
2062 rtc::CritScope lock(&crit_);
2063 EXPECT_GT(padding_sent_, 0);
2064 }
2065
2066 size_t GetNumVideoStreams() const override { return num_video_streams_; }
2067 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
2068
2069 private:
2070 const size_t num_video_streams_;
2071 const size_t num_audio_streams_;
2072 rtc::CriticalSection crit_;
danilchapa37de392017-09-09 04:17:22 -07002073 int media_sent_ RTC_GUARDED_BY(crit_);
2074 int padding_sent_ RTC_GUARDED_BY(crit_);
stefan9e117c5e12017-08-16 08:16:25 -07002075 } test(1, 0);
2076 RunBaseTest(&test);
2077}
2078
philipel277a8b52017-03-16 05:19:49 -07002079TEST_F(EndToEndTest, ObserversEncodedFrames) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002080 class EncodedFrameTestObserver : public EncodedFrameObserver {
2081 public:
2082 EncodedFrameTestObserver()
Peter Boström5811a392015-12-10 13:02:50 +01002083 : length_(0), frame_type_(kEmptyFrame), called_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002084 virtual ~EncodedFrameTestObserver() {}
2085
2086 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
2087 frame_type_ = encoded_frame.frame_type_;
2088 length_ = encoded_frame.length_;
2089 buffer_.reset(new uint8_t[length_]);
2090 memcpy(buffer_.get(), encoded_frame.data_, length_);
Peter Boström5811a392015-12-10 13:02:50 +01002091 called_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002092 }
2093
Peter Boström5811a392015-12-10 13:02:50 +01002094 bool Wait() { return called_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002095
2096 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
2097 ASSERT_EQ(length_, observer.length_)
2098 << "Observed frames are of different lengths.";
2099 EXPECT_EQ(frame_type_, observer.frame_type_)
2100 << "Observed frames have different frame types.";
2101 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
2102 << "Observed encoded frames have different content.";
2103 }
2104
2105 private:
kwiberg27f982b2016-03-01 11:52:33 -08002106 std::unique_ptr<uint8_t[]> buffer_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002107 size_t length_;
2108 FrameType frame_type_;
Peter Boström5811a392015-12-10 13:02:50 +01002109 rtc::Event called_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002110 };
2111
2112 EncodedFrameTestObserver post_encode_observer;
2113 EncodedFrameTestObserver pre_decode_observer;
perkja49cbd32016-09-16 07:53:41 -07002114 test::FrameForwarder forwarder;
eladalon413ee9a2017-08-22 04:02:52 -07002115 std::unique_ptr<test::FrameGenerator> frame_generator;
2116
2117 std::unique_ptr<test::DirectTransport> sender_transport;
2118 std::unique_ptr<test::DirectTransport> receiver_transport;
2119
2120 task_queue_.SendTask([&]() {
2121 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
2122
2123 sender_transport = rtc::MakeUnique<test::DirectTransport>(
2124 &task_queue_, sender_call_.get(), payload_type_map_);
2125 receiver_transport = rtc::MakeUnique<test::DirectTransport>(
2126 &task_queue_, receiver_call_.get(), payload_type_map_);
2127 sender_transport->SetReceiver(receiver_call_->Receiver());
2128 receiver_transport->SetReceiver(sender_call_->Receiver());
2129
2130 CreateSendConfig(1, 0, 0, sender_transport.get());
2131 CreateMatchingReceiveConfigs(receiver_transport.get());
2132 video_send_config_.post_encode_callback = &post_encode_observer;
2133 video_receive_configs_[0].pre_decode_callback = &pre_decode_observer;
2134
2135 CreateVideoStreams();
2136 Start();
2137
2138 frame_generator = test::FrameGenerator::CreateSquareGenerator(
2139 kDefaultWidth, kDefaultHeight);
2140 video_send_stream_->SetSource(
2141 &forwarder, VideoSendStream::DegradationPreference::kMaintainFramerate);
2142 forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
2143 });
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002144
Peter Boström5811a392015-12-10 13:02:50 +01002145 EXPECT_TRUE(post_encode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002146 << "Timed out while waiting for send-side encoded-frame callback.";
2147
Peter Boström5811a392015-12-10 13:02:50 +01002148 EXPECT_TRUE(pre_decode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002149 << "Timed out while waiting for pre-decode encoded-frame callback.";
2150
2151 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
2152
eladalon413ee9a2017-08-22 04:02:52 -07002153 task_queue_.SendTask([this, &sender_transport, &receiver_transport]() {
2154 Stop();
2155 DestroyStreams();
2156 sender_transport.reset();
2157 receiver_transport.reset();
2158 DestroyCalls();
2159 });
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002160}
2161
philipel277a8b52017-03-16 05:19:49 -07002162TEST_F(EndToEndTest, ReceiveStreamSendsRemb) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002163 class RembObserver : public test::EndToEndTest {
2164 public:
2165 RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
2166
stefanb77c7162017-02-06 06:29:38 -08002167 void ModifyVideoConfigs(
2168 VideoSendStream::Config* send_config,
2169 std::vector<VideoReceiveStream::Config>* receive_configs,
2170 VideoEncoderConfig* encoder_config) override {
2171 send_config->rtp.extensions.clear();
2172 send_config->rtp.extensions.push_back(RtpExtension(
2173 RtpExtension::kAbsSendTimeUri, test::kAbsSendTimeExtensionId));
2174 (*receive_configs)[0].rtp.remb = true;
2175 (*receive_configs)[0].rtp.transport_cc = false;
2176 }
2177
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002178 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
danilchap3dc929e2016-11-02 08:21:59 -07002179 test::RtcpPacketParser parser;
2180 EXPECT_TRUE(parser.Parse(packet, length));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002181
danilchap3dc929e2016-11-02 08:21:59 -07002182 if (parser.remb()->num_packets() > 0) {
2183 EXPECT_EQ(kReceiverLocalVideoSsrc, parser.remb()->sender_ssrc());
2184 EXPECT_LT(0U, parser.remb()->bitrate_bps());
2185 EXPECT_EQ(1U, parser.remb()->ssrcs().size());
2186 EXPECT_EQ(kVideoSendSsrcs[0], parser.remb()->ssrcs()[0]);
Peter Boström5811a392015-12-10 13:02:50 +01002187 observation_complete_.Set();
danilchap3dc929e2016-11-02 08:21:59 -07002188 }
2189
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002190 return SEND_PACKET;
2191 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002192 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002193 EXPECT_TRUE(Wait()) << "Timed out while waiting for a "
2194 "receiver RTCP REMB packet to be "
2195 "sent.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002196 }
2197 } test;
2198
stefane74eef12016-01-08 06:47:13 -08002199 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002200}
2201
stefanb77c7162017-02-06 06:29:38 -08002202class BandwidthStatsTest : public test::EndToEndTest {
2203 public:
2204 explicit BandwidthStatsTest(bool send_side_bwe)
2205 : EndToEndTest(test::CallTest::kDefaultTimeoutMs),
2206 sender_call_(nullptr),
2207 receiver_call_(nullptr),
2208 has_seen_pacer_delay_(false),
2209 send_side_bwe_(send_side_bwe) {}
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002210
stefanb77c7162017-02-06 06:29:38 -08002211 void ModifyVideoConfigs(
2212 VideoSendStream::Config* send_config,
2213 std::vector<VideoReceiveStream::Config>* receive_configs,
2214 VideoEncoderConfig* encoder_config) override {
2215 if (!send_side_bwe_) {
2216 send_config->rtp.extensions.clear();
2217 send_config->rtp.extensions.push_back(RtpExtension(
2218 RtpExtension::kAbsSendTimeUri, test::kAbsSendTimeExtensionId));
2219 (*receive_configs)[0].rtp.remb = true;
2220 (*receive_configs)[0].rtp.transport_cc = false;
2221 }
2222 }
2223
2224 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2225 Call::Stats sender_stats = sender_call_->GetStats();
2226 Call::Stats receiver_stats = receiver_call_->GetStats();
2227 if (!has_seen_pacer_delay_)
2228 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
2229 if (sender_stats.send_bandwidth_bps > 0 && has_seen_pacer_delay_) {
2230 if (send_side_bwe_ || receiver_stats.recv_bandwidth_bps > 0)
Peter Boström5811a392015-12-10 13:02:50 +01002231 observation_complete_.Set();
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002232 }
stefanb77c7162017-02-06 06:29:38 -08002233 return SEND_PACKET;
2234 }
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002235
stefanb77c7162017-02-06 06:29:38 -08002236 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2237 sender_call_ = sender_call;
2238 receiver_call_ = receiver_call;
2239 }
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002240
stefanb77c7162017-02-06 06:29:38 -08002241 void PerformTest() override {
2242 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2243 "non-zero bandwidth stats.";
2244 }
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002245
stefanb77c7162017-02-06 06:29:38 -08002246 private:
2247 Call* sender_call_;
2248 Call* receiver_call_;
2249 bool has_seen_pacer_delay_;
2250 const bool send_side_bwe_;
2251};
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002252
philipel277a8b52017-03-16 05:19:49 -07002253TEST_F(EndToEndTest, VerifySendSideBweStats) {
stefanb77c7162017-02-06 06:29:38 -08002254 BandwidthStatsTest test(true);
stefane74eef12016-01-08 06:47:13 -08002255 RunBaseTest(&test);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002256}
2257
philipel277a8b52017-03-16 05:19:49 -07002258TEST_F(EndToEndTest, VerifyRecvSideBweStats) {
stefanb77c7162017-02-06 06:29:38 -08002259 BandwidthStatsTest test(false);
2260 RunBaseTest(&test);
2261}
stefan32f81542016-01-20 07:13:58 -08002262
2263// Verifies that it's possible to limit the send BWE by sending a REMB.
2264// This is verified by allowing the send BWE to ramp-up to >1000 kbps,
2265// then have the test generate a REMB of 500 kbps and verify that the send BWE
2266// is reduced to exactly 500 kbps. Then a REMB of 1000 kbps is generated and the
2267// test verifies that the send BWE ramps back up to exactly 1000 kbps.
philipel277a8b52017-03-16 05:19:49 -07002268TEST_F(EndToEndTest, RembWithSendSideBwe) {
stefan32f81542016-01-20 07:13:58 -08002269 class BweObserver : public test::EndToEndTest {
2270 public:
2271 BweObserver()
2272 : EndToEndTest(kDefaultTimeoutMs),
2273 sender_call_(nullptr),
2274 clock_(Clock::GetRealTimeClock()),
2275 sender_ssrc_(0),
2276 remb_bitrate_bps_(1000000),
2277 receive_transport_(nullptr),
Tommi5dd5f5a2017-02-21 14:22:59 +01002278 stop_event_(false, false),
stefan32f81542016-01-20 07:13:58 -08002279 poller_thread_(&BitrateStatsPollingThread,
2280 this,
2281 "BitrateStatsPollingThread"),
Erik Språng737336d2016-07-29 12:59:36 +02002282 state_(kWaitForFirstRampUp),
2283 retransmission_rate_limiter_(clock_, 1000) {}
stefan32f81542016-01-20 07:13:58 -08002284
2285 ~BweObserver() {}
2286
eladalon413ee9a2017-08-22 04:02:52 -07002287 test::PacketTransport* CreateReceiveTransport(
2288 test::SingleThreadedTaskQueueForTesting* task_queue) override {
stefan32f81542016-01-20 07:13:58 -08002289 receive_transport_ = new test::PacketTransport(
eladalon413ee9a2017-08-22 04:02:52 -07002290 task_queue, nullptr, this, test::PacketTransport::kReceiver,
2291 payload_type_map_, FakeNetworkPipe::Config());
stefan32f81542016-01-20 07:13:58 -08002292 return receive_transport_;
2293 }
2294
2295 Call::Config GetSenderCallConfig() override {
philipel4fb651d2017-04-10 03:54:05 -07002296 Call::Config config(event_log_.get());
stefan32f81542016-01-20 07:13:58 -08002297 // Set a high start bitrate to reduce the test completion time.
2298 config.bitrate_config.start_bitrate_bps = remb_bitrate_bps_;
2299 return config;
2300 }
2301
2302 void ModifyVideoConfigs(
2303 VideoSendStream::Config* send_config,
2304 std::vector<VideoReceiveStream::Config>* receive_configs,
2305 VideoEncoderConfig* encoder_config) override {
2306 ASSERT_EQ(1u, send_config->rtp.ssrcs.size());
stefan32f81542016-01-20 07:13:58 -08002307 sender_ssrc_ = send_config->rtp.ssrcs[0];
2308
perkjfa10b552016-10-02 23:45:26 -07002309 encoder_config->max_bitrate_bps = 2000000;
stefan32f81542016-01-20 07:13:58 -08002310
2311 ASSERT_EQ(1u, receive_configs->size());
stefan32f81542016-01-20 07:13:58 -08002312 RtpRtcp::Configuration config;
2313 config.receiver_only = true;
2314 config.clock = clock_;
2315 config.outgoing_transport = receive_transport_;
Erik Språng737336d2016-07-29 12:59:36 +02002316 config.retransmission_rate_limiter = &retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08002317 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
2318 rtp_rtcp_->SetRemoteSSRC((*receive_configs)[0].rtp.remote_ssrc);
2319 rtp_rtcp_->SetSSRC((*receive_configs)[0].rtp.local_ssrc);
stefan32f81542016-01-20 07:13:58 -08002320 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
2321 }
2322
2323 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2324 sender_call_ = sender_call;
2325 }
2326
tommi0f8b4032017-02-22 11:22:05 -08002327 static void BitrateStatsPollingThread(void* obj) {
2328 static_cast<BweObserver*>(obj)->PollStats();
stefan32f81542016-01-20 07:13:58 -08002329 }
2330
tommi0f8b4032017-02-22 11:22:05 -08002331 void PollStats() {
2332 do {
2333 if (sender_call_) {
2334 Call::Stats stats = sender_call_->GetStats();
2335 switch (state_) {
2336 case kWaitForFirstRampUp:
2337 if (stats.send_bandwidth_bps >= remb_bitrate_bps_) {
2338 state_ = kWaitForRemb;
2339 remb_bitrate_bps_ /= 2;
Danil Chapovalov51e21aa2017-10-10 17:46:26 +02002340 rtp_rtcp_->SetRemb(
tommi0f8b4032017-02-22 11:22:05 -08002341 remb_bitrate_bps_,
2342 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
2343 rtp_rtcp_->SendRTCP(kRtcpRr);
2344 }
2345 break;
stefan32f81542016-01-20 07:13:58 -08002346
tommi0f8b4032017-02-22 11:22:05 -08002347 case kWaitForRemb:
2348 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
2349 state_ = kWaitForSecondRampUp;
2350 remb_bitrate_bps_ *= 2;
Danil Chapovalov51e21aa2017-10-10 17:46:26 +02002351 rtp_rtcp_->SetRemb(
tommi0f8b4032017-02-22 11:22:05 -08002352 remb_bitrate_bps_,
2353 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
2354 rtp_rtcp_->SendRTCP(kRtcpRr);
2355 }
2356 break;
stefan32f81542016-01-20 07:13:58 -08002357
tommi0f8b4032017-02-22 11:22:05 -08002358 case kWaitForSecondRampUp:
2359 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
2360 observation_complete_.Set();
2361 }
2362 break;
2363 }
stefan32f81542016-01-20 07:13:58 -08002364 }
tommi0f8b4032017-02-22 11:22:05 -08002365 } while (!stop_event_.Wait(1000));
stefan32f81542016-01-20 07:13:58 -08002366 }
2367
2368 void PerformTest() override {
2369 poller_thread_.Start();
2370 EXPECT_TRUE(Wait())
2371 << "Timed out while waiting for bitrate to change according to REMB.";
Tommi5dd5f5a2017-02-21 14:22:59 +01002372 stop_event_.Set();
stefan32f81542016-01-20 07:13:58 -08002373 poller_thread_.Stop();
2374 }
2375
2376 private:
2377 enum TestState { kWaitForFirstRampUp, kWaitForRemb, kWaitForSecondRampUp };
2378
2379 Call* sender_call_;
2380 Clock* const clock_;
2381 uint32_t sender_ssrc_;
2382 int remb_bitrate_bps_;
kwiberg27f982b2016-03-01 11:52:33 -08002383 std::unique_ptr<RtpRtcp> rtp_rtcp_;
stefan32f81542016-01-20 07:13:58 -08002384 test::PacketTransport* receive_transport_;
Tommi5dd5f5a2017-02-21 14:22:59 +01002385 rtc::Event stop_event_;
stefan32f81542016-01-20 07:13:58 -08002386 rtc::PlatformThread poller_thread_;
2387 TestState state_;
Erik Språng737336d2016-07-29 12:59:36 +02002388 RateLimiter retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08002389 } test;
2390
2391 RunBaseTest(&test);
2392}
2393
philipel3184f8e2017-05-18 08:08:53 -07002394TEST_F(EndToEndTest, StopSendingKeyframeRequestsForInactiveStream) {
2395 class KeyframeRequestObserver : public test::EndToEndTest {
2396 public:
eladalon413ee9a2017-08-22 04:02:52 -07002397 explicit KeyframeRequestObserver(
2398 test::SingleThreadedTaskQueueForTesting* task_queue)
2399 : clock_(Clock::GetRealTimeClock()), task_queue_(task_queue) {}
philipel3184f8e2017-05-18 08:08:53 -07002400
2401 void OnVideoStreamsCreated(
2402 VideoSendStream* send_stream,
2403 const std::vector<VideoReceiveStream*>& receive_streams) override {
2404 RTC_DCHECK_EQ(1, receive_streams.size());
2405 send_stream_ = send_stream;
2406 receive_stream_ = receive_streams[0];
2407 }
2408
2409 void PerformTest() override {
2410 bool frame_decoded = false;
2411 int64_t start_time = clock_->TimeInMilliseconds();
2412 while (clock_->TimeInMilliseconds() - start_time <= 5000) {
2413 if (receive_stream_->GetStats().frames_decoded > 0) {
2414 frame_decoded = true;
2415 break;
2416 }
2417 SleepMs(100);
2418 }
2419 ASSERT_TRUE(frame_decoded);
eladalon413ee9a2017-08-22 04:02:52 -07002420 task_queue_->SendTask([this]() { send_stream_->Stop(); });
philipel3184f8e2017-05-18 08:08:53 -07002421 SleepMs(10000);
2422 ASSERT_EQ(
2423 1U, receive_stream_->GetStats().rtcp_packet_type_counts.pli_packets);
2424 }
2425
2426 private:
2427 Clock* clock_;
2428 VideoSendStream* send_stream_;
2429 VideoReceiveStream* receive_stream_;
eladalon413ee9a2017-08-22 04:02:52 -07002430 test::SingleThreadedTaskQueueForTesting* const task_queue_;
2431 } test(&task_queue_);
philipel3184f8e2017-05-18 08:08:53 -07002432
2433 RunBaseTest(&test);
2434}
2435
philipele828c962017-03-21 03:24:27 -07002436class ProbingTest : public test::EndToEndTest {
2437 public:
2438 explicit ProbingTest(int start_bitrate_bps)
2439 : clock_(Clock::GetRealTimeClock()),
2440 start_bitrate_bps_(start_bitrate_bps),
2441 state_(0),
2442 sender_call_(nullptr) {}
2443
2444 ~ProbingTest() {}
2445
2446 Call::Config GetSenderCallConfig() override {
philipel4fb651d2017-04-10 03:54:05 -07002447 Call::Config config(event_log_.get());
philipele828c962017-03-21 03:24:27 -07002448 config.bitrate_config.start_bitrate_bps = start_bitrate_bps_;
2449 return config;
2450 }
2451
2452 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2453 sender_call_ = sender_call;
2454 }
2455
2456 protected:
2457 Clock* const clock_;
2458 const int start_bitrate_bps_;
2459 int state_;
2460 Call* sender_call_;
2461};
2462
aleloi7057b6b2017-03-29 02:07:33 -07002463TEST_F(EndToEndTest, MAYBE_InitialProbing) {
philipele828c962017-03-21 03:24:27 -07002464 class InitialProbingTest : public ProbingTest {
2465 public:
philipel8a256522017-03-30 05:06:22 -07002466 explicit InitialProbingTest(bool* success)
eladaloncf038f72017-08-10 10:42:53 -07002467 : ProbingTest(300000), success_(success) {
2468 *success_ = false;
2469 }
philipele828c962017-03-21 03:24:27 -07002470
2471 void PerformTest() override {
2472 int64_t start_time_ms = clock_->TimeInMilliseconds();
2473 do {
philipel8a256522017-03-30 05:06:22 -07002474 if (clock_->TimeInMilliseconds() - start_time_ms > kTimeoutMs)
philipele828c962017-03-21 03:24:27 -07002475 break;
philipele828c962017-03-21 03:24:27 -07002476
2477 Call::Stats stats = sender_call_->GetStats();
2478 // Initial probing is done with a x3 and x6 multiplier of the start
2479 // bitrate, so a x4 multiplier is a high enough threshold.
philipel8a256522017-03-30 05:06:22 -07002480 if (stats.send_bandwidth_bps > 4 * 300000) {
2481 *success_ = true;
philipele828c962017-03-21 03:24:27 -07002482 break;
philipel8a256522017-03-30 05:06:22 -07002483 }
philipele828c962017-03-21 03:24:27 -07002484 } while (!observation_complete_.Wait(20));
2485 }
2486
2487 private:
2488 const int kTimeoutMs = 1000;
philipel8a256522017-03-30 05:06:22 -07002489 bool* const success_;
2490 };
philipele828c962017-03-21 03:24:27 -07002491
eladaloncf038f72017-08-10 10:42:53 -07002492 bool success = false;
philipel8a256522017-03-30 05:06:22 -07002493 const int kMaxAttempts = 3;
2494 for (int i = 0; i < kMaxAttempts; ++i) {
2495 InitialProbingTest test(&success);
2496 RunBaseTest(&test);
2497 if (success)
2498 return;
2499 }
eladaloncf038f72017-08-10 10:42:53 -07002500 EXPECT_TRUE(success) << "Failed to perform mid initial probing ("
2501 << kMaxAttempts << " attempts).";
philipele828c962017-03-21 03:24:27 -07002502}
2503
aleloi18703f92017-03-30 04:24:08 -07002504// Fails on Linux MSan: bugs.webrtc.org/7428
2505#if defined(MEMORY_SANITIZER)
2506TEST_F(EndToEndTest, DISABLED_TriggerMidCallProbing) {
oprypin45197522017-06-22 01:47:20 -07002507// Fails on iOS bots: bugs.webrtc.org/7851
2508#elif defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR
2509TEST_F(EndToEndTest, DISABLED_TriggerMidCallProbing) {
aleloi18703f92017-03-30 04:24:08 -07002510#else
philipele828c962017-03-21 03:24:27 -07002511TEST_F(EndToEndTest, TriggerMidCallProbing) {
aleloi18703f92017-03-30 04:24:08 -07002512#endif
2513
philipele828c962017-03-21 03:24:27 -07002514 class TriggerMidCallProbingTest : public ProbingTest {
2515 public:
eladalon413ee9a2017-08-22 04:02:52 -07002516 TriggerMidCallProbingTest(
2517 test::SingleThreadedTaskQueueForTesting* task_queue,
2518 bool* success)
2519 : ProbingTest(300000), success_(success), task_queue_(task_queue) {}
philipele828c962017-03-21 03:24:27 -07002520
2521 void PerformTest() override {
philipel8a256522017-03-30 05:06:22 -07002522 *success_ = false;
philipele828c962017-03-21 03:24:27 -07002523 int64_t start_time_ms = clock_->TimeInMilliseconds();
2524 do {
philipel8a256522017-03-30 05:06:22 -07002525 if (clock_->TimeInMilliseconds() - start_time_ms > kTimeoutMs)
philipele828c962017-03-21 03:24:27 -07002526 break;
philipele828c962017-03-21 03:24:27 -07002527
2528 Call::Stats stats = sender_call_->GetStats();
2529
2530 switch (state_) {
2531 case 0:
2532 if (stats.send_bandwidth_bps > 5 * 300000) {
2533 Call::Config::BitrateConfig bitrate_config;
2534 bitrate_config.max_bitrate_bps = 100000;
eladalon413ee9a2017-08-22 04:02:52 -07002535 task_queue_->SendTask([this, &bitrate_config]() {
2536 sender_call_->SetBitrateConfig(bitrate_config);
2537 });
philipele828c962017-03-21 03:24:27 -07002538 ++state_;
2539 }
2540 break;
2541 case 1:
2542 if (stats.send_bandwidth_bps < 110000) {
2543 Call::Config::BitrateConfig bitrate_config;
2544 bitrate_config.max_bitrate_bps = 2500000;
eladalon413ee9a2017-08-22 04:02:52 -07002545 task_queue_->SendTask([this, &bitrate_config]() {
2546 sender_call_->SetBitrateConfig(bitrate_config);
2547 });
philipele828c962017-03-21 03:24:27 -07002548 ++state_;
2549 }
2550 break;
2551 case 2:
2552 // During high cpu load the pacer will not be able to pace packets
2553 // at the correct speed, but if we go from 110 to 1250 kbps
2554 // in 5 seconds then it is due to probing.
philipel8a256522017-03-30 05:06:22 -07002555 if (stats.send_bandwidth_bps > 1250000) {
2556 *success_ = true;
philipele828c962017-03-21 03:24:27 -07002557 observation_complete_.Set();
philipel8a256522017-03-30 05:06:22 -07002558 }
philipele828c962017-03-21 03:24:27 -07002559 break;
2560 }
2561 } while (!observation_complete_.Wait(20));
2562 }
2563
2564 private:
2565 const int kTimeoutMs = 5000;
philipel8a256522017-03-30 05:06:22 -07002566 bool* const success_;
eladalon413ee9a2017-08-22 04:02:52 -07002567 test::SingleThreadedTaskQueueForTesting* const task_queue_;
philipel8a256522017-03-30 05:06:22 -07002568 };
philipele828c962017-03-21 03:24:27 -07002569
eladaloncf038f72017-08-10 10:42:53 -07002570 bool success = false;
philipel8a256522017-03-30 05:06:22 -07002571 const int kMaxAttempts = 3;
2572 for (int i = 0; i < kMaxAttempts; ++i) {
eladalon413ee9a2017-08-22 04:02:52 -07002573 TriggerMidCallProbingTest test(&task_queue_, &success);
philipel8a256522017-03-30 05:06:22 -07002574 RunBaseTest(&test);
2575 if (success)
2576 return;
2577 }
stefan9e117c5e12017-08-16 08:16:25 -07002578 EXPECT_TRUE(success) << "Failed to perform mid call probing (" << kMaxAttempts
2579 << " attempts).";
philipele828c962017-03-21 03:24:27 -07002580}
2581
philipel277a8b52017-03-16 05:19:49 -07002582TEST_F(EndToEndTest, VerifyNackStats) {
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002583 static const int kPacketNumberToDrop = 200;
2584 class NackObserver : public test::EndToEndTest {
2585 public:
2586 NackObserver()
2587 : EndToEndTest(kLongTimeoutMs),
2588 sent_rtp_packets_(0),
2589 dropped_rtp_packet_(0),
2590 dropped_rtp_packet_requested_(false),
2591 send_stream_(nullptr),
2592 start_runtime_ms_(-1) {}
2593
2594 private:
2595 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002596 rtc::CritScope lock(&crit_);
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002597 if (++sent_rtp_packets_ == kPacketNumberToDrop) {
kwiberg27f982b2016-03-01 11:52:33 -08002598 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002599 RTPHeader header;
2600 EXPECT_TRUE(parser->Parse(packet, length, &header));
2601 dropped_rtp_packet_ = header.sequenceNumber;
2602 return DROP_PACKET;
2603 }
2604 VerifyStats();
2605 return SEND_PACKET;
2606 }
2607
2608 Action OnReceiveRtcp(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 test::RtcpPacketParser rtcp_parser;
2611 rtcp_parser.Parse(packet, length);
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02002612 const std::vector<uint16_t>& nacks = rtcp_parser.nack()->packet_ids();
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002613 if (!nacks.empty() && std::find(
2614 nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) {
2615 dropped_rtp_packet_requested_ = true;
2616 }
2617 return SEND_PACKET;
2618 }
2619
danilchapa37de392017-09-09 04:17:22 -07002620 void VerifyStats() RTC_EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002621 if (!dropped_rtp_packet_requested_)
2622 return;
2623 int send_stream_nack_packets = 0;
2624 int receive_stream_nack_packets = 0;
2625 VideoSendStream::Stats stats = send_stream_->GetStats();
2626 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
2627 stats.substreams.begin(); it != stats.substreams.end(); ++it) {
2628 const VideoSendStream::StreamStats& stream_stats = it->second;
2629 send_stream_nack_packets +=
2630 stream_stats.rtcp_packet_type_counts.nack_packets;
2631 }
2632 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2633 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2634 receive_stream_nack_packets +=
2635 stats.rtcp_packet_type_counts.nack_packets;
2636 }
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002637 if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) {
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002638 // NACK packet sent on receive stream and received on sent stream.
2639 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002640 observation_complete_.Set();
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002641 }
2642 }
2643
2644 bool MinMetricRunTimePassed() {
2645 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2646 if (start_runtime_ms_ == -1) {
2647 start_runtime_ms_ = now;
2648 return false;
2649 }
2650 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2651 return elapsed_sec > metrics::kMinRunTimeInSeconds;
2652 }
2653
stefanff483612015-12-21 03:14:00 -08002654 void ModifyVideoConfigs(
2655 VideoSendStream::Config* send_config,
2656 std::vector<VideoReceiveStream::Config>* receive_configs,
2657 VideoEncoderConfig* encoder_config) override {
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002658 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2659 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sakal55d932b2016-09-30 06:19:08 -07002660 (*receive_configs)[0].renderer = &fake_renderer_;
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002661 }
2662
stefanff483612015-12-21 03:14:00 -08002663 void OnVideoStreamsCreated(
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002664 VideoSendStream* send_stream,
2665 const std::vector<VideoReceiveStream*>& receive_streams) override {
2666 send_stream_ = send_stream;
2667 receive_streams_ = receive_streams;
2668 }
2669
2670 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002671 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002672 }
2673
sakal55d932b2016-09-30 06:19:08 -07002674 test::FakeVideoRenderer fake_renderer_;
stefan608213e2015-11-01 14:56:10 -08002675 rtc::CriticalSection crit_;
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002676 uint64_t sent_rtp_packets_;
danilchapa37de392017-09-09 04:17:22 -07002677 uint16_t dropped_rtp_packet_ RTC_GUARDED_BY(&crit_);
2678 bool dropped_rtp_packet_requested_ RTC_GUARDED_BY(&crit_);
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002679 std::vector<VideoReceiveStream*> receive_streams_;
2680 VideoSendStream* send_stream_;
2681 int64_t start_runtime_ms_;
2682 } test;
2683
asapersson01d70a32016-05-20 06:29:46 -07002684 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002685 RunBaseTest(&test);
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002686
asapersson01d70a32016-05-20 06:29:46 -07002687 EXPECT_EQ(
2688 1, metrics::NumSamples("WebRTC.Video.UniqueNackRequestsSentInPercent"));
2689 EXPECT_EQ(1, metrics::NumSamples(
2690 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
2691 EXPECT_GT(metrics::MinSample("WebRTC.Video.NackPacketsSentPerMinute"), 0);
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002692}
2693
sprangb4a1ae52015-12-03 08:10:08 -08002694void EndToEndTest::VerifyHistogramStats(bool use_rtx,
nisse3b3622f2017-09-26 02:49:21 -07002695 bool use_fec,
sprangb4a1ae52015-12-03 08:10:08 -08002696 bool screenshare) {
tommi2e82f382016-06-21 00:26:43 -07002697 class StatsObserver : public test::EndToEndTest,
2698 public rtc::VideoSinkInterface<VideoFrame> {
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002699 public:
nisse3b3622f2017-09-26 02:49:21 -07002700 StatsObserver(bool use_rtx, bool use_fec, bool screenshare)
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002701 : EndToEndTest(kLongTimeoutMs),
2702 use_rtx_(use_rtx),
nisse3b3622f2017-09-26 02:49:21 -07002703 use_fec_(use_fec),
sprangb4a1ae52015-12-03 08:10:08 -08002704 screenshare_(screenshare),
Peter Boström39593972016-02-15 11:27:15 +01002705 // This test uses NACK, so to send FEC we can't use a fake encoder.
nisse3b3622f2017-09-26 02:49:21 -07002706 vp8_encoder_(use_fec ? VP8Encoder::Create() : nullptr),
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002707 sender_call_(nullptr),
2708 receiver_call_(nullptr),
asapersson1394c7b2016-10-18 11:50:50 -07002709 start_runtime_ms_(-1),
2710 num_frames_received_(0) {}
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002711
2712 private:
asapersson1394c7b2016-10-18 11:50:50 -07002713 void OnFrame(const VideoFrame& video_frame) override {
2714 // The RTT is needed to estimate |ntp_time_ms| which is used by
2715 // end-to-end delay stats. Therefore, start counting received frames once
2716 // |ntp_time_ms| is valid.
2717 if (video_frame.ntp_time_ms() > 0 &&
2718 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() >=
2719 video_frame.ntp_time_ms()) {
2720 rtc::CritScope lock(&crit_);
2721 ++num_frames_received_;
2722 }
2723 }
tommi2e82f382016-06-21 00:26:43 -07002724
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002725 Action OnSendRtp(const uint8_t* packet, size_t length) override {
asapersson1394c7b2016-10-18 11:50:50 -07002726 if (MinMetricRunTimePassed() && MinNumberOfFramesReceived())
Peter Boström5811a392015-12-10 13:02:50 +01002727 observation_complete_.Set();
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002728
stefanf116bd02015-10-27 08:29:42 -07002729 return SEND_PACKET;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002730 }
2731
2732 bool MinMetricRunTimePassed() {
2733 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2734 if (start_runtime_ms_ == -1) {
2735 start_runtime_ms_ = now;
2736 return false;
2737 }
2738 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2739 return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
2740 }
2741
asapersson1394c7b2016-10-18 11:50:50 -07002742 bool MinNumberOfFramesReceived() const {
2743 const int kMinRequiredHistogramSamples = 200;
2744 rtc::CritScope lock(&crit_);
2745 return num_frames_received_ > kMinRequiredHistogramSamples;
2746 }
2747
stefanff483612015-12-21 03:14:00 -08002748 void ModifyVideoConfigs(
2749 VideoSendStream::Config* send_config,
2750 std::vector<VideoReceiveStream::Config>* receive_configs,
2751 VideoEncoderConfig* encoder_config) override {
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002752 // NACK
2753 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2754 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
tommi2e82f382016-06-21 00:26:43 -07002755 (*receive_configs)[0].renderer = this;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002756 // FEC
nisse3b3622f2017-09-26 02:49:21 -07002757 if (use_fec_) {
brandtrb5f2c3f2016-10-04 23:28:39 -07002758 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
2759 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
Peter Boström39593972016-02-15 11:27:15 +01002760 send_config->encoder_settings.encoder = vp8_encoder_.get();
2761 send_config->encoder_settings.payload_name = "VP8";
2762 (*receive_configs)[0].decoders[0].payload_name = "VP8";
nisse3b3622f2017-09-26 02:49:21 -07002763 (*receive_configs)[0].rtp.red_payload_type = kRedPayloadType;
2764 (*receive_configs)[0].rtp.ulpfec_payload_type = kUlpfecPayloadType;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002765 }
2766 // RTX
2767 if (use_rtx_) {
2768 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
2769 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
brandtr14742122017-01-27 04:53:07 -08002770 (*receive_configs)[0].rtp.rtx_ssrc = kSendRtxSsrcs[0];
nisse26e3abb2017-08-25 04:44:25 -07002771 (*receive_configs)[0]
2772 .rtp.rtx_associated_payload_types[kSendRtxPayloadType] =
2773 kFakeVideoSendPayloadType;
nisse3b3622f2017-09-26 02:49:21 -07002774 if (use_fec_) {
2775 send_config->rtp.ulpfec.red_rtx_payload_type = kRtxRedPayloadType;
2776 (*receive_configs)[0]
2777 .rtp.rtx_associated_payload_types[kRtxRedPayloadType] =
2778 kSendRtxPayloadType;
2779 }
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002780 }
asapersson1490f7a2016-09-23 02:09:46 -07002781 // RTT needed for RemoteNtpTimeEstimator for the receive stream.
2782 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = true;
sprangb4a1ae52015-12-03 08:10:08 -08002783 encoder_config->content_type =
2784 screenshare_ ? VideoEncoderConfig::ContentType::kScreen
2785 : VideoEncoderConfig::ContentType::kRealtimeVideo;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002786 }
2787
2788 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2789 sender_call_ = sender_call;
2790 receiver_call_ = receiver_call;
2791 }
2792
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002793 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002794 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002795 }
2796
asapersson1394c7b2016-10-18 11:50:50 -07002797 rtc::CriticalSection crit_;
sprangb4a1ae52015-12-03 08:10:08 -08002798 const bool use_rtx_;
nisse3b3622f2017-09-26 02:49:21 -07002799 const bool use_fec_;
sprangb4a1ae52015-12-03 08:10:08 -08002800 const bool screenshare_;
kwiberg27f982b2016-03-01 11:52:33 -08002801 const std::unique_ptr<VideoEncoder> vp8_encoder_;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002802 Call* sender_call_;
2803 Call* receiver_call_;
2804 int64_t start_runtime_ms_;
danilchapa37de392017-09-09 04:17:22 -07002805 int num_frames_received_ RTC_GUARDED_BY(&crit_);
nisse3b3622f2017-09-26 02:49:21 -07002806 } test(use_rtx, use_fec, screenshare);
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002807
asapersson01d70a32016-05-20 06:29:46 -07002808 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002809 RunBaseTest(&test);
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002810
sprangb4a1ae52015-12-03 08:10:08 -08002811 std::string video_prefix =
2812 screenshare ? "WebRTC.Video.Screenshare." : "WebRTC.Video.";
ilnik6d5b4d62017-08-30 03:32:14 -07002813 // The content type extension is disabled in non screenshare test,
2814 // therefore no slicing on simulcast id should be present.
2815 std::string video_suffix = screenshare ? ".S0" : "";
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002816 // Verify that stats have been updated once.
asapersson4374a092016-07-27 00:39:09 -07002817 EXPECT_EQ(2, metrics::NumSamples("WebRTC.Call.LifetimeInSeconds"));
saza0d7f04d2017-07-04 04:05:06 -07002818 EXPECT_EQ(1, metrics::NumSamples(
2819 "WebRTC.Call.TimeReceivingVideoRtpPacketsInSeconds"));
asapersson01d70a32016-05-20 06:29:46 -07002820 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
2821 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.RtcpBitrateReceivedInBps"));
2822 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.BitrateReceivedInKbps"));
2823 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.EstimatedSendBitrateInKbps"));
2824 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.PacerBitrateInKbps"));
2825
asapersson4374a092016-07-27 00:39:09 -07002826 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
2827 EXPECT_EQ(1,
2828 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
2829
asapersson01d70a32016-05-20 06:29:46 -07002830 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
stefan91d92602015-11-11 10:13:02 -08002831 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002832 metrics::NumSamples(video_prefix + "NackPacketsReceivedPerMinute"));
2833 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
asaperssond89920b2015-07-22 06:52:00 -07002834 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002835 metrics::NumSamples(video_prefix + "FirPacketsReceivedPerMinute"));
2836 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
sprangb4a1ae52015-12-03 08:10:08 -08002837 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002838 metrics::NumSamples(video_prefix + "PliPacketsReceivedPerMinute"));
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002839
asapersson01d70a32016-05-20 06:29:46 -07002840 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "KeyFramesSentInPermille"));
2841 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
2842
2843 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentPacketsLostInPercent"));
2844 EXPECT_EQ(1,
2845 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
2846
2847 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputWidthInPixels"));
2848 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputHeightInPixels"));
2849 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentWidthInPixels"));
2850 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentHeightInPixels"));
ilnik6d5b4d62017-08-30 03:32:14 -07002851 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "ReceivedWidthInPixels"));
2852 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "ReceivedHeightInPixels"));
asapersson01d70a32016-05-20 06:29:46 -07002853
perkjfa10b552016-10-02 23:45:26 -07002854 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputWidthInPixels",
2855 kDefaultWidth));
2856 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputHeightInPixels",
2857 kDefaultHeight));
2858 EXPECT_EQ(
2859 1, metrics::NumEvents(video_prefix + "SentWidthInPixels", kDefaultWidth));
2860 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "SentHeightInPixels",
2861 kDefaultHeight));
ilnik6d5b4d62017-08-30 03:32:14 -07002862 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "ReceivedWidthInPixels",
perkjfa10b552016-10-02 23:45:26 -07002863 kDefaultWidth));
ilnik6d5b4d62017-08-30 03:32:14 -07002864 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "ReceivedHeightInPixels",
perkjfa10b552016-10-02 23:45:26 -07002865 kDefaultHeight));
asapersson01d70a32016-05-20 06:29:46 -07002866
2867 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputFramesPerSecond"));
2868 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentFramesPerSecond"));
2869 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
2870 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
2871
2872 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
2873 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
2874 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
2875 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
2876
ilnik6d5b4d62017-08-30 03:32:14 -07002877 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EndToEndDelayInMs" +
2878 video_suffix));
2879 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EndToEndDelayMaxInMs" +
2880 video_suffix));
2881 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InterframeDelayInMs" +
2882 video_suffix));
2883 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InterframeDelayMaxInMs" +
2884 video_suffix));
ilnik4257ab22017-07-03 01:15:58 -07002885
asapersson01d70a32016-05-20 06:29:46 -07002886 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
2887
2888 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EncodeTimeInMs"));
2889 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
2890
asapersson66d4b372016-12-19 06:50:53 -08002891 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "NumberOfPauseEvents"));
2892 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PausedTimeInPercent"));
2893
asapersson01d70a32016-05-20 06:29:46 -07002894 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "BitrateSentInKbps"));
2895 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateReceivedInKbps"));
2896 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "MediaBitrateSentInKbps"));
2897 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateReceivedInKbps"));
2898 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PaddingBitrateSentInKbps"));
2899 EXPECT_EQ(1,
2900 metrics::NumSamples("WebRTC.Video.PaddingBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002901 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002902 1, metrics::NumSamples(video_prefix + "RetransmittedBitrateSentInKbps"));
2903 EXPECT_EQ(1, metrics::NumSamples(
2904 "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002905
asapersson01d70a32016-05-20 06:29:46 -07002906 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendDelayInMs"));
2907 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayInMs"));
2908 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayMaxInMs"));
asapersson6f14be82015-11-16 00:40:49 -08002909
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002910 int num_rtx_samples = use_rtx ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002911 EXPECT_EQ(num_rtx_samples,
2912 metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2913 EXPECT_EQ(num_rtx_samples,
2914 metrics::NumSamples("WebRTC.Video.RtxBitrateReceivedInKbps"));
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002915
nisse3b3622f2017-09-26 02:49:21 -07002916 int num_red_samples = use_fec ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002917 EXPECT_EQ(num_red_samples,
2918 metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2919 EXPECT_EQ(num_red_samples,
2920 metrics::NumSamples("WebRTC.Video.FecBitrateReceivedInKbps"));
2921 EXPECT_EQ(num_red_samples,
2922 metrics::NumSamples("WebRTC.Video.ReceivedFecPacketsInPercent"));
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002923}
2924
Lu Liufb9e7512017-04-13 14:09:56 -07002925#if defined(WEBRTC_WIN)
2926// Disabled due to flakiness on Windows (bugs.webrtc.org/7483).
2927#define MAYBE_ContentTypeSwitches DISABLED_ContentTypeSwitches
2928#else
2929#define MAYBE_ContentTypeSwitches ContentTypeSwitches
2930#endif
2931TEST_F(EndToEndTest, MAYBE_ContentTypeSwitches) {
ilnik00d802b2017-04-11 10:34:31 -07002932 class StatsObserver : public test::BaseTest,
2933 public rtc::VideoSinkInterface<VideoFrame> {
2934 public:
2935 StatsObserver() : BaseTest(kLongTimeoutMs), num_frames_received_(0) {}
2936
2937 bool ShouldCreateReceivers() const override { return true; }
2938
2939 void OnFrame(const VideoFrame& video_frame) override {
2940 // The RTT is needed to estimate |ntp_time_ms| which is used by
2941 // end-to-end delay stats. Therefore, start counting received frames once
2942 // |ntp_time_ms| is valid.
2943 if (video_frame.ntp_time_ms() > 0 &&
2944 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() >=
2945 video_frame.ntp_time_ms()) {
2946 rtc::CritScope lock(&crit_);
2947 ++num_frames_received_;
2948 }
2949 }
2950
2951 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2952 if (MinNumberOfFramesReceived())
2953 observation_complete_.Set();
2954 return SEND_PACKET;
2955 }
2956
2957 bool MinNumberOfFramesReceived() const {
ilnikf6f808f2017-04-18 09:17:53 -07002958 // Have some room for frames with wrong content type during switch.
2959 const int kMinRequiredHistogramSamples = 200+50;
ilnik00d802b2017-04-11 10:34:31 -07002960 rtc::CritScope lock(&crit_);
2961 return num_frames_received_ > kMinRequiredHistogramSamples;
2962 }
2963
2964 // May be called several times.
2965 void PerformTest() override {
2966 EXPECT_TRUE(Wait()) << "Timed out waiting for enough packets.";
2967 // Reset frame counter so next PerformTest() call will do something.
2968 {
2969 rtc::CritScope lock(&crit_);
2970 num_frames_received_ = 0;
2971 }
2972 }
2973
2974 rtc::CriticalSection crit_;
danilchapa37de392017-09-09 04:17:22 -07002975 int num_frames_received_ RTC_GUARDED_BY(&crit_);
ilnik00d802b2017-04-11 10:34:31 -07002976 } test;
2977
2978 metrics::Reset();
2979
2980 Call::Config send_config(test.GetSenderCallConfig());
ilnik00d802b2017-04-11 10:34:31 -07002981 Call::Config recv_config(test.GetReceiverCallConfig());
eladalon413ee9a2017-08-22 04:02:52 -07002982 VideoEncoderConfig encoder_config_with_screenshare;
ilnik00d802b2017-04-11 10:34:31 -07002983
ilnik41cadbc2017-08-23 00:44:27 -07002984 task_queue_.SendTask([this, &test, &send_config,
eladalon413ee9a2017-08-22 04:02:52 -07002985 &recv_config, &encoder_config_with_screenshare]() {
2986 CreateSenderCall(send_config);
2987 CreateReceiverCall(recv_config);
ilnik00d802b2017-04-11 10:34:31 -07002988
eladalon413ee9a2017-08-22 04:02:52 -07002989 receive_transport_.reset(test.CreateReceiveTransport(&task_queue_));
2990 send_transport_.reset(
2991 test.CreateSendTransport(&task_queue_, sender_call_.get()));
2992 send_transport_->SetReceiver(receiver_call_->Receiver());
2993 receive_transport_->SetReceiver(sender_call_->Receiver());
2994
2995 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
2996 CreateSendConfig(1, 0, 0, send_transport_.get());
2997 CreateMatchingReceiveConfigs(receive_transport_.get());
2998
2999 // Modify send and receive configs.
3000 video_send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
3001 video_receive_configs_[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
3002 video_receive_configs_[0].renderer = &test;
3003 // RTT needed for RemoteNtpTimeEstimator for the receive stream.
3004 video_receive_configs_[0].rtp.rtcp_xr.receiver_reference_time_report = true;
3005 // Start with realtime video.
3006 video_encoder_config_.content_type =
3007 VideoEncoderConfig::ContentType::kRealtimeVideo;
3008 // Second encoder config for the second part of the test uses screenshare
3009 encoder_config_with_screenshare = video_encoder_config_.Copy();
3010 encoder_config_with_screenshare.content_type =
3011 VideoEncoderConfig::ContentType::kScreen;
3012
3013 CreateVideoStreams();
3014 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
3015 kDefaultHeight);
3016 Start();
3017 });
ilnik00d802b2017-04-11 10:34:31 -07003018
3019 test.PerformTest();
3020
3021 // Replace old send stream.
eladalon413ee9a2017-08-22 04:02:52 -07003022 task_queue_.SendTask([this, &encoder_config_with_screenshare]() {
3023 sender_call_->DestroyVideoSendStream(video_send_stream_);
3024 video_send_stream_ = sender_call_->CreateVideoSendStream(
3025 video_send_config_.Copy(), encoder_config_with_screenshare.Copy());
3026 video_send_stream_->SetSource(
3027 frame_generator_capturer_.get(),
3028 VideoSendStream::DegradationPreference::kBalanced);
3029 video_send_stream_->Start();
3030 });
ilnik00d802b2017-04-11 10:34:31 -07003031
3032 // Continue to run test but now with screenshare.
3033 test.PerformTest();
3034
eladalon413ee9a2017-08-22 04:02:52 -07003035 task_queue_.SendTask([this]() {
3036 Stop();
3037 DestroyStreams();
3038 send_transport_.reset();
3039 receive_transport_.reset();
3040 DestroyCalls();
3041 });
ilnik00d802b2017-04-11 10:34:31 -07003042
3043 // Verify that stats have been updated for both screenshare and video.
3044 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.EndToEndDelayInMs"));
3045 EXPECT_EQ(1,
3046 metrics::NumSamples("WebRTC.Video.Screenshare.EndToEndDelayInMs"));
3047 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.EndToEndDelayMaxInMs"));
3048 EXPECT_EQ(
3049 1, metrics::NumSamples("WebRTC.Video.Screenshare.EndToEndDelayMaxInMs"));
ilnik4257ab22017-07-03 01:15:58 -07003050 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
3051 EXPECT_EQ(1,
3052 metrics::NumSamples(
3053 "WebRTC.Video.Screenshare.InterframeDelayInMs"));
3054 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
3055 EXPECT_EQ(1,
3056 metrics::NumSamples(
3057 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
ilnik00d802b2017-04-11 10:34:31 -07003058}
3059
philipel277a8b52017-03-16 05:19:49 -07003060TEST_F(EndToEndTest, VerifyHistogramStatsWithRtx) {
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02003061 const bool kEnabledRtx = true;
3062 const bool kEnabledRed = false;
sprangb4a1ae52015-12-03 08:10:08 -08003063 const bool kScreenshare = false;
3064 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02003065}
3066
philipel277a8b52017-03-16 05:19:49 -07003067TEST_F(EndToEndTest, VerifyHistogramStatsWithRed) {
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02003068 const bool kEnabledRtx = false;
3069 const bool kEnabledRed = true;
sprangb4a1ae52015-12-03 08:10:08 -08003070 const bool kScreenshare = false;
3071 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
3072}
3073
philipel277a8b52017-03-16 05:19:49 -07003074TEST_F(EndToEndTest, VerifyHistogramStatsWithScreenshare) {
sprangb4a1ae52015-12-03 08:10:08 -08003075 const bool kEnabledRtx = false;
3076 const bool kEnabledRed = false;
3077 const bool kScreenshare = true;
3078 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02003079}
3080
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003081void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
3082 bool send_single_ssrc_first) {
3083 class SendsSetSsrcs : public test::EndToEndTest {
3084 public:
3085 SendsSetSsrcs(const uint32_t* ssrcs,
3086 size_t num_ssrcs,
3087 bool send_single_ssrc_first)
3088 : EndToEndTest(kDefaultTimeoutMs),
3089 num_ssrcs_(num_ssrcs),
3090 send_single_ssrc_first_(send_single_ssrc_first),
3091 ssrcs_to_observe_(num_ssrcs),
sprang867fb522015-08-03 04:38:41 -07003092 expect_single_ssrc_(send_single_ssrc_first),
3093 send_stream_(nullptr) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003094 for (size_t i = 0; i < num_ssrcs; ++i)
3095 valid_ssrcs_[ssrcs[i]] = true;
3096 }
3097
3098 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003099 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003100 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003101 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003102
3103 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
3104 << "Received unknown SSRC: " << header.ssrc;
3105
3106 if (!valid_ssrcs_[header.ssrc])
Peter Boström5811a392015-12-10 13:02:50 +01003107 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003108
3109 if (!is_observed_[header.ssrc]) {
3110 is_observed_[header.ssrc] = true;
3111 --ssrcs_to_observe_;
3112 if (expect_single_ssrc_) {
3113 expect_single_ssrc_ = false;
Peter Boström5811a392015-12-10 13:02:50 +01003114 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003115 }
3116 }
3117
3118 if (ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01003119 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003120
3121 return SEND_PACKET;
3122 }
3123
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003124 size_t GetNumVideoStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003125
perkjfa10b552016-10-02 23:45:26 -07003126 // This test use other VideoStream settings than the the default settings
3127 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3128 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3129 // in ModifyVideoConfigs.
3130 class VideoStreamFactory
3131 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3132 public:
3133 VideoStreamFactory() {}
3134
3135 private:
3136 std::vector<VideoStream> CreateEncoderStreams(
3137 int width,
3138 int height,
3139 const VideoEncoderConfig& encoder_config) override {
3140 std::vector<VideoStream> streams =
3141 test::CreateVideoStreams(width, height, encoder_config);
3142 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
3143 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3144 streams[i].min_bitrate_bps = 10000;
3145 streams[i].target_bitrate_bps = 15000;
3146 streams[i].max_bitrate_bps = 20000;
3147 }
3148 return streams;
3149 }
3150 };
3151
stefanff483612015-12-21 03:14:00 -08003152 void ModifyVideoConfigs(
3153 VideoSendStream::Config* send_config,
3154 std::vector<VideoReceiveStream::Config>* receive_configs,
3155 VideoEncoderConfig* encoder_config) override {
perkjfa10b552016-10-02 23:45:26 -07003156 encoder_config->video_stream_factory =
3157 new rtc::RefCountedObject<VideoStreamFactory>();
perkj26091b12016-09-01 01:17:40 -07003158 video_encoder_config_all_streams_ = encoder_config->Copy();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003159 if (send_single_ssrc_first_)
perkjfa10b552016-10-02 23:45:26 -07003160 encoder_config->number_of_streams = 1;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003161 }
3162
stefanff483612015-12-21 03:14:00 -08003163 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003164 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003165 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003166 send_stream_ = send_stream;
3167 }
3168
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003169 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003170 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
3171 << (send_single_ssrc_first_ ? "first SSRC."
3172 : "SSRCs.");
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003173
3174 if (send_single_ssrc_first_) {
3175 // Set full simulcast and continue with the rest of the SSRCs.
stefanff483612015-12-21 03:14:00 -08003176 send_stream_->ReconfigureVideoEncoder(
perkj26091b12016-09-01 01:17:40 -07003177 std::move(video_encoder_config_all_streams_));
Peter Boström5811a392015-12-10 13:02:50 +01003178 EXPECT_TRUE(Wait()) << "Timed out while waiting on additional SSRCs.";
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003179 }
3180 }
3181
3182 private:
3183 std::map<uint32_t, bool> valid_ssrcs_;
3184 std::map<uint32_t, bool> is_observed_;
3185
3186 const size_t num_ssrcs_;
3187 const bool send_single_ssrc_first_;
3188
3189 size_t ssrcs_to_observe_;
3190 bool expect_single_ssrc_;
3191
3192 VideoSendStream* send_stream_;
stefanff483612015-12-21 03:14:00 -08003193 VideoEncoderConfig video_encoder_config_all_streams_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003194 } test(kVideoSendSsrcs, num_ssrcs, send_single_ssrc_first);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003195
stefane74eef12016-01-08 06:47:13 -08003196 RunBaseTest(&test);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003197}
3198
philipel277a8b52017-03-16 05:19:49 -07003199TEST_F(EndToEndTest, ReportsSetEncoderRates) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003200 class EncoderRateStatsTest : public test::EndToEndTest,
3201 public test::FakeEncoder {
3202 public:
eladalon413ee9a2017-08-22 04:02:52 -07003203 explicit EncoderRateStatsTest(
3204 test::SingleThreadedTaskQueueForTesting* task_queue)
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003205 : EndToEndTest(kDefaultTimeoutMs),
sprang867fb522015-08-03 04:38:41 -07003206 FakeEncoder(Clock::GetRealTimeClock()),
eladalon413ee9a2017-08-22 04:02:52 -07003207 task_queue_(task_queue),
sprang867fb522015-08-03 04:38:41 -07003208 send_stream_(nullptr),
3209 bitrate_kbps_(0) {}
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003210
stefanff483612015-12-21 03:14:00 -08003211 void OnVideoStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003212 VideoSendStream* send_stream,
3213 const std::vector<VideoReceiveStream*>& receive_streams) override {
3214 send_stream_ = send_stream;
3215 }
3216
stefanff483612015-12-21 03:14:00 -08003217 void ModifyVideoConfigs(
3218 VideoSendStream::Config* send_config,
3219 std::vector<VideoReceiveStream::Config>* receive_configs,
3220 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003221 send_config->encoder_settings.encoder = this;
kwibergaf476c72016-11-28 15:21:39 -08003222 RTC_DCHECK_EQ(1, encoder_config->number_of_streams);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003223 }
3224
Erik Språng08127a92016-11-16 16:41:30 +01003225 int32_t SetRateAllocation(const BitrateAllocation& rate_allocation,
3226 uint32_t framerate) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003227 // Make sure not to trigger on any default zero bitrates.
Erik Språng08127a92016-11-16 16:41:30 +01003228 if (rate_allocation.get_sum_bps() == 0)
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003229 return 0;
Peter Boströmf2f82832015-05-01 13:00:41 +02003230 rtc::CritScope lock(&crit_);
Erik Språng08127a92016-11-16 16:41:30 +01003231 bitrate_kbps_ = rate_allocation.get_sum_kbps();
Peter Boström5811a392015-12-10 13:02:50 +01003232 observation_complete_.Set();
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003233 return 0;
3234 }
3235
3236 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003237 ASSERT_TRUE(Wait())
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003238 << "Timed out while waiting for encoder SetRates() call.";
eladalon413ee9a2017-08-22 04:02:52 -07003239
3240 task_queue_->SendTask([this]() {
3241 WaitForEncoderTargetBitrateMatchStats();
3242 send_stream_->Stop();
3243 WaitForStatsReportZeroTargetBitrate();
3244 send_stream_->Start();
3245 WaitForEncoderTargetBitrateMatchStats();
3246 });
perkjf5b2e512016-07-05 08:34:04 -07003247 }
3248
3249 void WaitForEncoderTargetBitrateMatchStats() {
Peter Boström5811a392015-12-10 13:02:50 +01003250 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003251 VideoSendStream::Stats stats = send_stream_->GetStats();
3252 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003253 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003254 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
3255 static_cast<int>(bitrate_kbps_)) {
3256 return;
3257 }
3258 }
3259 SleepMs(1);
3260 }
3261 FAIL()
3262 << "Timed out waiting for stats reporting the currently set bitrate.";
3263 }
3264
perkjf5b2e512016-07-05 08:34:04 -07003265 void WaitForStatsReportZeroTargetBitrate() {
3266 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
3267 if (send_stream_->GetStats().target_media_bitrate_bps == 0) {
3268 return;
3269 }
3270 SleepMs(1);
3271 }
3272 FAIL() << "Timed out waiting for stats reporting zero bitrate.";
3273 }
3274
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003275 private:
eladalon413ee9a2017-08-22 04:02:52 -07003276 test::SingleThreadedTaskQueueForTesting* const task_queue_;
stefanf116bd02015-10-27 08:29:42 -07003277 rtc::CriticalSection crit_;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003278 VideoSendStream* send_stream_;
danilchapa37de392017-09-09 04:17:22 -07003279 uint32_t bitrate_kbps_ RTC_GUARDED_BY(crit_);
eladalon413ee9a2017-08-22 04:02:52 -07003280 } test(&task_queue_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003281
stefane74eef12016-01-08 06:47:13 -08003282 RunBaseTest(&test);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003283}
3284
philipel277a8b52017-03-16 05:19:49 -07003285TEST_F(EndToEndTest, GetStats) {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00003286 static const int kStartBitrateBps = 3000000;
Peter Boströmdef398832015-05-27 17:59:11 +02003287 static const int kExpectedRenderDelayMs = 20;
tommi2e82f382016-06-21 00:26:43 -07003288
3289 class ReceiveStreamRenderer : public rtc::VideoSinkInterface<VideoFrame> {
3290 public:
3291 ReceiveStreamRenderer() {}
3292
3293 private:
3294 void OnFrame(const VideoFrame& video_frame) override {}
3295 };
3296
nissed30a1112016-04-18 05:15:22 -07003297 class StatsObserver : public test::EndToEndTest,
3298 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003299 public:
stefanf116bd02015-10-27 08:29:42 -07003300 StatsObserver()
3301 : EndToEndTest(kLongTimeoutMs),
Peter Boströmc6e16e32016-02-05 14:15:53 +01003302 encoder_(Clock::GetRealTimeClock(), 10),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00003303 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003304 expected_send_ssrcs_(),
Peter Boström5811a392015-12-10 13:02:50 +01003305 check_stats_event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003306
3307 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003308 Action OnSendRtp(const uint8_t* packet, size_t length) override {
sprangcd349d92016-07-13 09:11:28 -07003309 // Drop every 25th packet => 4% loss.
3310 static const int kPacketLossFrac = 25;
3311 RTPHeader header;
3312 RtpUtility::RtpHeaderParser parser(packet, length);
3313 if (parser.Parse(&header) &&
3314 expected_send_ssrcs_.find(header.ssrc) !=
3315 expected_send_ssrcs_.end() &&
3316 header.sequenceNumber % kPacketLossFrac == 0) {
3317 return DROP_PACKET;
3318 }
Peter Boström5811a392015-12-10 13:02:50 +01003319 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003320 return SEND_PACKET;
3321 }
3322
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003323 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01003324 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003325 return SEND_PACKET;
3326 }
3327
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003328 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01003329 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003330 return SEND_PACKET;
3331 }
3332
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003333 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01003334 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003335 return SEND_PACKET;
3336 }
3337
nissed30a1112016-04-18 05:15:22 -07003338 void OnFrame(const VideoFrame& video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003339 // Ensure that we have at least 5ms send side delay.
nissed30a1112016-04-18 05:15:22 -07003340 SleepMs(5);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003341 }
3342
3343 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003344 for (size_t i = 0; i < receive_streams_.size(); ++i) {
3345 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
3346 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003347
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003348 // Make sure all fields have been populated.
3349 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
3350 // always filled for all receivers.
3351 receive_stats_filled_["IncomingRate"] |=
3352 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003353
Peter Boströmb7d9a972015-12-18 16:01:11 +01003354 send_stats_filled_["DecoderImplementationName"] |=
3355 stats.decoder_implementation_name ==
3356 test::FakeDecoder::kImplementationName;
Peter Boströmdef398832015-05-27 17:59:11 +02003357 receive_stats_filled_["RenderDelayAsHighAsExpected"] |=
3358 stats.render_delay_ms >= kExpectedRenderDelayMs;
3359
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003360 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003361
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003362 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003363
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003364 receive_stats_filled_["StatisticsUpdated"] |=
srte186d9c32017-08-04 05:03:53 -07003365 stats.rtcp_stats.packets_lost != 0 ||
3366 stats.rtcp_stats.extended_highest_sequence_number != 0 ||
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003367 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003368
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003369 receive_stats_filled_["DataCountersUpdated"] |=
3370 stats.rtp_stats.transmitted.payload_bytes != 0 ||
3371 stats.rtp_stats.fec.packets != 0 ||
3372 stats.rtp_stats.transmitted.header_bytes != 0 ||
3373 stats.rtp_stats.transmitted.packets != 0 ||
3374 stats.rtp_stats.transmitted.padding_bytes != 0 ||
3375 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003376
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003377 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003378 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003379
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003380 receive_stats_filled_["FrameCounts"] |=
3381 stats.frame_counts.key_frames != 0 ||
3382 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00003383
pbosbb36fdf2015-07-09 07:48:14 -07003384 receive_stats_filled_["CName"] |= !stats.c_name.empty();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00003385
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003386 receive_stats_filled_["RtcpPacketTypeCount"] |=
3387 stats.rtcp_packet_type_counts.fir_packets != 0 ||
3388 stats.rtcp_packet_type_counts.nack_packets != 0 ||
3389 stats.rtcp_packet_type_counts.pli_packets != 0 ||
3390 stats.rtcp_packet_type_counts.nack_requests != 0 ||
3391 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbosf42376c2015-08-28 07:35:32 -07003392
3393 assert(stats.current_payload_type == -1 ||
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003394 stats.current_payload_type == kFakeVideoSendPayloadType);
pbosf42376c2015-08-28 07:35:32 -07003395 receive_stats_filled_["IncomingPayloadType"] |=
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003396 stats.current_payload_type == kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003397 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003398
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003399 return AllStatsFilled(receive_stats_filled_);
3400 }
3401
3402 bool CheckSendStats() {
Peter Boström74f6e9e2016-04-04 17:56:10 +02003403 RTC_DCHECK(send_stream_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003404 VideoSendStream::Stats stats = send_stream_->GetStats();
3405
philipel20d05a92016-12-19 04:17:27 -08003406 size_t expected_num_streams = kNumSsrcs + expected_send_ssrcs_.size();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003407 send_stats_filled_["NumStreams"] |=
philipel20d05a92016-12-19 04:17:27 -08003408 stats.substreams.size() == expected_num_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003409
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00003410 send_stats_filled_["CpuOveruseMetrics"] |=
Peter Boströme4499152016-02-05 11:13:28 +01003411 stats.avg_encode_time_ms != 0 && stats.encode_usage_percent != 0;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00003412
Peter Boströmb7d9a972015-12-18 16:01:11 +01003413 send_stats_filled_["EncoderImplementationName"] |=
3414 stats.encoder_implementation_name ==
3415 test::FakeEncoder::kImplementationName;
3416
Pera48ddb72016-09-29 11:48:50 +02003417 send_stats_filled_["EncoderPreferredBitrate"] |=
3418 stats.preferred_media_bitrate_bps > 0;
3419
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003420 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003421 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003422 it != stats.substreams.end(); ++it) {
sprangcd349d92016-07-13 09:11:28 -07003423 if (expected_send_ssrcs_.find(it->first) == expected_send_ssrcs_.end())
3424 continue; // Probably RTX.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003425
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003426 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003427 stats.input_frame_rate != 0;
3428
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003429 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003430
3431 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
srte186d9c32017-08-04 05:03:53 -07003432 stream_stats.rtcp_stats.packets_lost != 0 ||
3433 stream_stats.rtcp_stats.extended_highest_sequence_number != 0 ||
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003434 stream_stats.rtcp_stats.fraction_lost != 0;
3435
3436 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00003437 stream_stats.rtp_stats.fec.packets != 0 ||
3438 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
3439 stream_stats.rtp_stats.retransmitted.packets != 0 ||
3440 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003441
sprangcd349d92016-07-13 09:11:28 -07003442 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Total",
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003443 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00003444 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003445
sprangcd349d92016-07-13 09:11:28 -07003446 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Retransmit",
3447 it->first)] |=
3448 stream_stats.retransmit_bitrate_bps != 0;
3449
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003450 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00003451 stream_stats.frame_counts.delta_frames != 0 ||
3452 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003453
3454 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
3455 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00003456
3457 send_stats_filled_[CompoundKey("Delay", it->first)] |=
3458 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003459
3460 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
3461 // report dropped packets.
3462 send_stats_filled_["RtcpPacketTypeCount"] |=
3463 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
3464 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
3465 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
3466 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
3467 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003468 }
3469
3470 return AllStatsFilled(send_stats_filled_);
3471 }
3472
3473 std::string CompoundKey(const char* name, uint32_t ssrc) {
3474 std::ostringstream oss;
3475 oss << name << "_" << ssrc;
3476 return oss.str();
3477 }
3478
3479 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
sprangcd349d92016-07-13 09:11:28 -07003480 for (const auto& stat : stats_map) {
3481 if (!stat.second)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003482 return false;
3483 }
3484 return true;
3485 }
3486
eladalon413ee9a2017-08-22 04:02:52 -07003487 test::PacketTransport* CreateSendTransport(
3488 test::SingleThreadedTaskQueueForTesting* task_queue,
3489 Call* sender_call) override {
stefane74eef12016-01-08 06:47:13 -08003490 FakeNetworkPipe::Config network_config;
3491 network_config.loss_percent = 5;
eladalon413ee9a2017-08-22 04:02:52 -07003492 return new test::PacketTransport(task_queue, sender_call, this,
minyue20c84cc2017-04-10 16:57:57 -07003493 test::PacketTransport::kSender,
3494 payload_type_map_, network_config);
stefane74eef12016-01-08 06:47:13 -08003495 }
3496
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003497 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00003498 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01003499 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00003500 return config;
3501 }
3502
perkjfa10b552016-10-02 23:45:26 -07003503 // This test use other VideoStream settings than the the default settings
3504 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3505 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3506 // in ModifyVideoConfigs.
3507 class VideoStreamFactory
3508 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3509 public:
3510 VideoStreamFactory() {}
3511
3512 private:
3513 std::vector<VideoStream> CreateEncoderStreams(
3514 int width,
3515 int height,
3516 const VideoEncoderConfig& encoder_config) override {
3517 std::vector<VideoStream> streams =
3518 test::CreateVideoStreams(width, height, encoder_config);
3519 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
3520 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3521 streams[i].min_bitrate_bps = 10000;
3522 streams[i].target_bitrate_bps = 15000;
3523 streams[i].max_bitrate_bps = 20000;
3524 }
3525 return streams;
3526 }
3527 };
3528
stefanff483612015-12-21 03:14:00 -08003529 void ModifyVideoConfigs(
3530 VideoSendStream::Config* send_config,
3531 std::vector<VideoReceiveStream::Config>* receive_configs,
3532 VideoEncoderConfig* encoder_config) override {
perkjfa10b552016-10-02 23:45:26 -07003533 encoder_config->video_stream_factory =
3534 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003535 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003536 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003537
sprangcd349d92016-07-13 09:11:28 -07003538 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
3539 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
3540
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003541 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003542 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003543 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003544 expected_receive_ssrcs_.push_back(
3545 (*receive_configs)[i].rtp.remote_ssrc);
Peter Boströmdef398832015-05-27 17:59:11 +02003546 (*receive_configs)[i].render_delay_ms = kExpectedRenderDelayMs;
tommi2e82f382016-06-21 00:26:43 -07003547 (*receive_configs)[i].renderer = &receive_stream_renderer_;
sprangcd349d92016-07-13 09:11:28 -07003548 (*receive_configs)[i].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
3549
brandtr14742122017-01-27 04:53:07 -08003550 (*receive_configs)[i].rtp.rtx_ssrc = kSendRtxSsrcs[i];
nisse26e3abb2017-08-25 04:44:25 -07003551 (*receive_configs)[i]
3552 .rtp.rtx_associated_payload_types[kSendRtxPayloadType] =
3553 kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003554 }
sprangcd349d92016-07-13 09:11:28 -07003555
3556 for (size_t i = 0; i < kNumSsrcs; ++i)
3557 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
3558
Peter Boströmc6e16e32016-02-05 14:15:53 +01003559 // Use a delayed encoder to make sure we see CpuOveruseMetrics stats that
3560 // are non-zero.
3561 send_config->encoder_settings.encoder = &encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003562 }
3563
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003564 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00003565
stefanff483612015-12-21 03:14:00 -08003566 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003567 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003568 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003569 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003570 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003571 }
3572
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003573 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003574 Clock* clock = Clock::GetRealTimeClock();
3575 int64_t now = clock->TimeInMilliseconds();
3576 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
3577 bool receive_ok = false;
3578 bool send_ok = false;
3579
3580 while (now < stop_time) {
3581 if (!receive_ok)
3582 receive_ok = CheckReceiveStats();
3583 if (!send_ok)
3584 send_ok = CheckSendStats();
3585
3586 if (receive_ok && send_ok)
3587 return;
3588
3589 int64_t time_until_timout_ = stop_time - now;
3590 if (time_until_timout_ > 0)
Peter Boström5811a392015-12-10 13:02:50 +01003591 check_stats_event_.Wait(time_until_timout_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003592 now = clock->TimeInMilliseconds();
3593 }
3594
3595 ADD_FAILURE() << "Timed out waiting for filled stats.";
3596 for (std::map<std::string, bool>::const_iterator it =
3597 receive_stats_filled_.begin();
eladalon413ee9a2017-08-22 04:02:52 -07003598 it != receive_stats_filled_.end(); ++it) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003599 if (!it->second) {
3600 ADD_FAILURE() << "Missing receive stats: " << it->first;
3601 }
3602 }
3603
3604 for (std::map<std::string, bool>::const_iterator it =
3605 send_stats_filled_.begin();
eladalon413ee9a2017-08-22 04:02:52 -07003606 it != send_stats_filled_.end(); ++it) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003607 if (!it->second) {
3608 ADD_FAILURE() << "Missing send stats: " << it->first;
3609 }
3610 }
3611 }
3612
Peter Boströmc6e16e32016-02-05 14:15:53 +01003613 test::DelayedEncoder encoder_;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003614 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003615 std::map<std::string, bool> receive_stats_filled_;
3616
3617 VideoSendStream* send_stream_;
3618 std::map<std::string, bool> send_stats_filled_;
3619
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003620 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003621 std::set<uint32_t> expected_send_ssrcs_;
3622 std::string expected_cname_;
3623
Peter Boström5811a392015-12-10 13:02:50 +01003624 rtc::Event check_stats_event_;
tommi2e82f382016-06-21 00:26:43 -07003625 ReceiveStreamRenderer receive_stream_renderer_;
stefanf116bd02015-10-27 08:29:42 -07003626 } test;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003627
stefane74eef12016-01-08 06:47:13 -08003628 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003629}
3630
ilnik75204c52017-09-04 03:35:40 -07003631TEST_F(EndToEndTest, TimingFramesAreReported) {
ilnik2edc6842017-07-06 03:06:50 -07003632 static const int kExtensionId = 5;
3633
3634 class StatsObserver : public test::EndToEndTest {
3635 public:
3636 StatsObserver() : EndToEndTest(kLongTimeoutMs) {}
3637
3638 private:
ilnik2edc6842017-07-06 03:06:50 -07003639 void ModifyVideoConfigs(
3640 VideoSendStream::Config* send_config,
3641 std::vector<VideoReceiveStream::Config>* receive_configs,
3642 VideoEncoderConfig* encoder_config) override {
3643 send_config->rtp.extensions.clear();
3644 send_config->rtp.extensions.push_back(
3645 RtpExtension(RtpExtension::kVideoTimingUri, kExtensionId));
3646 for (size_t i = 0; i < receive_configs->size(); ++i) {
3647 (*receive_configs)[i].rtp.extensions.clear();
3648 (*receive_configs)[i].rtp.extensions.push_back(
3649 RtpExtension(RtpExtension::kVideoTimingUri, kExtensionId));
3650 }
3651 }
3652
3653 void OnVideoStreamsCreated(
3654 VideoSendStream* send_stream,
3655 const std::vector<VideoReceiveStream*>& receive_streams) override {
3656 receive_streams_ = receive_streams;
3657 }
3658
3659 void PerformTest() override {
3660 // No frames reported initially.
3661 for (size_t i = 0; i < receive_streams_.size(); ++i) {
ilnik75204c52017-09-04 03:35:40 -07003662 EXPECT_FALSE(receive_streams_[i]->GetStats().timing_frame_info);
ilnik2edc6842017-07-06 03:06:50 -07003663 }
3664 // Wait for at least one timing frame to be sent with 100ms grace period.
3665 SleepMs(kDefaultTimingFramesDelayMs + 100);
3666 // Check that timing frames are reported for each stream.
3667 for (size_t i = 0; i < receive_streams_.size(); ++i) {
ilnik75204c52017-09-04 03:35:40 -07003668 EXPECT_TRUE(receive_streams_[i]->GetStats().timing_frame_info);
ilnik2edc6842017-07-06 03:06:50 -07003669 }
3670 }
3671
3672 std::vector<VideoReceiveStream*> receive_streams_;
3673 } test;
3674
3675 RunBaseTest(&test);
3676}
3677
sprang1a646ee2016-12-01 06:34:11 -08003678class RtcpXrObserver : public test::EndToEndTest {
3679 public:
sprang44b3ef62017-01-13 07:30:25 -08003680 RtcpXrObserver(bool enable_rrtr, bool enable_target_bitrate)
sprang1a646ee2016-12-01 06:34:11 -08003681 : EndToEndTest(test::CallTest::kDefaultTimeoutMs),
3682 enable_rrtr_(enable_rrtr),
sprang44b3ef62017-01-13 07:30:25 -08003683 enable_target_bitrate_(enable_target_bitrate),
sprang1a646ee2016-12-01 06:34:11 -08003684 sent_rtcp_sr_(0),
3685 sent_rtcp_rr_(0),
3686 sent_rtcp_rrtr_(0),
3687 sent_rtcp_target_bitrate_(false),
3688 sent_rtcp_dlrr_(0) {}
3689
3690 private:
3691 // Receive stream should send RR packets (and RRTR packets if enabled).
3692 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
3693 rtc::CritScope lock(&crit_);
3694 test::RtcpPacketParser parser;
3695 EXPECT_TRUE(parser.Parse(packet, length));
3696
3697 sent_rtcp_rr_ += parser.receiver_report()->num_packets();
3698 EXPECT_EQ(0, parser.sender_report()->num_packets());
3699 EXPECT_GE(1, parser.xr()->num_packets());
3700 if (parser.xr()->num_packets() > 0) {
3701 if (parser.xr()->rrtr())
3702 ++sent_rtcp_rrtr_;
3703 EXPECT_FALSE(parser.xr()->dlrr());
3704 }
3705
3706 return SEND_PACKET;
3707 }
3708 // Send stream should send SR packets (and DLRR packets if enabled).
3709 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
3710 rtc::CritScope lock(&crit_);
3711 test::RtcpPacketParser parser;
3712 EXPECT_TRUE(parser.Parse(packet, length));
3713
3714 sent_rtcp_sr_ += parser.sender_report()->num_packets();
3715 EXPECT_LE(parser.xr()->num_packets(), 1);
3716 if (parser.xr()->num_packets() > 0) {
3717 EXPECT_FALSE(parser.xr()->rrtr());
3718 if (parser.xr()->dlrr())
3719 ++sent_rtcp_dlrr_;
3720 if (parser.xr()->target_bitrate())
3721 sent_rtcp_target_bitrate_ = true;
3722 }
3723
3724 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
3725 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve &&
sprang44b3ef62017-01-13 07:30:25 -08003726 (sent_rtcp_target_bitrate_ || !enable_target_bitrate_)) {
sprang1a646ee2016-12-01 06:34:11 -08003727 if (enable_rrtr_) {
3728 EXPECT_GT(sent_rtcp_rrtr_, 0);
3729 EXPECT_GT(sent_rtcp_dlrr_, 0);
3730 } else {
3731 EXPECT_EQ(sent_rtcp_rrtr_, 0);
3732 EXPECT_EQ(sent_rtcp_dlrr_, 0);
3733 }
sprang44b3ef62017-01-13 07:30:25 -08003734 EXPECT_EQ(enable_target_bitrate_, sent_rtcp_target_bitrate_);
sprang1a646ee2016-12-01 06:34:11 -08003735 observation_complete_.Set();
3736 }
3737 return SEND_PACKET;
3738 }
3739
3740 void ModifyVideoConfigs(
3741 VideoSendStream::Config* send_config,
3742 std::vector<VideoReceiveStream::Config>* receive_configs,
3743 VideoEncoderConfig* encoder_config) override {
sprang44b3ef62017-01-13 07:30:25 -08003744 if (enable_target_bitrate_) {
3745 // TargetBitrate only signaled for screensharing.
3746 encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
3747 }
sprang1a646ee2016-12-01 06:34:11 -08003748 (*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
3749 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
3750 enable_rrtr_;
3751 }
3752
3753 void PerformTest() override {
3754 EXPECT_TRUE(Wait())
3755 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
3756 }
3757
3758 static const int kNumRtcpReportPacketsToObserve = 5;
3759
3760 rtc::CriticalSection crit_;
sprang44b3ef62017-01-13 07:30:25 -08003761 const bool enable_rrtr_;
3762 const bool enable_target_bitrate_;
sprang1a646ee2016-12-01 06:34:11 -08003763 int sent_rtcp_sr_;
danilchapa37de392017-09-09 04:17:22 -07003764 int sent_rtcp_rr_ RTC_GUARDED_BY(&crit_);
3765 int sent_rtcp_rrtr_ RTC_GUARDED_BY(&crit_);
3766 bool sent_rtcp_target_bitrate_ RTC_GUARDED_BY(&crit_);
sprang1a646ee2016-12-01 06:34:11 -08003767 int sent_rtcp_dlrr_;
3768};
3769
philipel277a8b52017-03-16 05:19:49 -07003770TEST_F(EndToEndTest, TestExtendedReportsWithRrtrWithoutTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003771 RtcpXrObserver test(true, false);
sprang1a646ee2016-12-01 06:34:11 -08003772 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003773}
3774
philipel277a8b52017-03-16 05:19:49 -07003775TEST_F(EndToEndTest, TestExtendedReportsWithoutRrtrWithoutTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003776 RtcpXrObserver test(false, false);
3777 RunBaseTest(&test);
3778}
3779
philipel277a8b52017-03-16 05:19:49 -07003780TEST_F(EndToEndTest, TestExtendedReportsWithRrtrWithTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003781 RtcpXrObserver test(true, true);
3782 RunBaseTest(&test);
3783}
3784
philipel277a8b52017-03-16 05:19:49 -07003785TEST_F(EndToEndTest, TestExtendedReportsWithoutRrtrWithTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003786 RtcpXrObserver test(false, true);
sprang1a646ee2016-12-01 06:34:11 -08003787 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003788}
3789
philipel277a8b52017-03-16 05:19:49 -07003790TEST_F(EndToEndTest, TestReceivedRtpPacketStats) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003791 static const size_t kNumRtpPacketsToSend = 5;
3792 class ReceivedRtpStatsObserver : public test::EndToEndTest {
3793 public:
3794 ReceivedRtpStatsObserver()
3795 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00003796 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003797 sent_rtp_(0) {}
3798
3799 private:
stefanff483612015-12-21 03:14:00 -08003800 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003801 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003802 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003803 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003804 }
3805
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003806 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003807 if (sent_rtp_ >= kNumRtpPacketsToSend) {
3808 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00003809 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
Peter Boström5811a392015-12-10 13:02:50 +01003810 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003811 }
3812 return DROP_PACKET;
3813 }
3814 ++sent_rtp_;
3815 return SEND_PACKET;
3816 }
3817
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003818 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003819 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003820 << "Timed out while verifying number of received RTP packets.";
3821 }
3822
3823 VideoReceiveStream* receive_stream_;
3824 uint32_t sent_rtp_;
3825 } test;
3826
stefane74eef12016-01-08 06:47:13 -08003827 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003828}
3829
philipel277a8b52017-03-16 05:19:49 -07003830TEST_F(EndToEndTest, SendsSetSsrc) {
philipel266f0a42016-11-28 08:49:07 -08003831 TestSendsSetSsrcs(1, false);
3832}
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003833
philipel277a8b52017-03-16 05:19:49 -07003834TEST_F(EndToEndTest, SendsSetSimulcastSsrcs) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003835 TestSendsSetSsrcs(kNumSsrcs, false);
3836}
3837
philipel277a8b52017-03-16 05:19:49 -07003838TEST_F(EndToEndTest, CanSwitchToUseAllSsrcs) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003839 TestSendsSetSsrcs(kNumSsrcs, true);
3840}
3841
philipel277a8b52017-03-16 05:19:49 -07003842TEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003843 class ObserveRedundantPayloads: public test::EndToEndTest {
3844 public:
3845 ObserveRedundantPayloads()
3846 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003847 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003848 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
3849 }
3850 }
3851
3852 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003853 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003854 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003855 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003856
3857 if (!registered_rtx_ssrc_[header.ssrc])
3858 return SEND_PACKET;
3859
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003860 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003861 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003862 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003863
3864 if (!packet_is_redundant_payload)
3865 return SEND_PACKET;
3866
3867 if (!observed_redundant_retransmission_[header.ssrc]) {
3868 observed_redundant_retransmission_[header.ssrc] = true;
3869 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01003870 observation_complete_.Set();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003871 }
3872
3873 return SEND_PACKET;
3874 }
3875
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003876 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003877
perkjfa10b552016-10-02 23:45:26 -07003878 // This test use other VideoStream settings than the the default settings
3879 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3880 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3881 // in ModifyVideoConfigs.
3882 class VideoStreamFactory
3883 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3884 public:
3885 VideoStreamFactory() {}
3886
3887 private:
3888 std::vector<VideoStream> CreateEncoderStreams(
3889 int width,
3890 int height,
3891 const VideoEncoderConfig& encoder_config) override {
3892 std::vector<VideoStream> streams =
3893 test::CreateVideoStreams(width, height, encoder_config);
3894 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
3895 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3896 streams[i].min_bitrate_bps = 10000;
3897 streams[i].target_bitrate_bps = 15000;
3898 streams[i].max_bitrate_bps = 20000;
3899 }
3900 return streams;
3901 }
3902 };
3903
stefanff483612015-12-21 03:14:00 -08003904 void ModifyVideoConfigs(
3905 VideoSendStream::Config* send_config,
3906 std::vector<VideoReceiveStream::Config>* receive_configs,
3907 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003908 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
perkjfa10b552016-10-02 23:45:26 -07003909 encoder_config->video_stream_factory =
3910 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003911 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003912
3913 for (size_t i = 0; i < kNumSsrcs; ++i)
3914 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00003915
3916 // Significantly higher than max bitrates for all video streams -> forcing
3917 // padding to trigger redundant padding on all RTX SSRCs.
3918 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003919 }
3920
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003921 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003922 EXPECT_TRUE(Wait())
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003923 << "Timed out while waiting for redundant payloads on all SSRCs.";
3924 }
3925
3926 private:
3927 size_t ssrcs_to_observe_;
3928 std::map<uint32_t, bool> observed_redundant_retransmission_;
3929 std::map<uint32_t, bool> registered_rtx_ssrc_;
3930 } test;
3931
stefane74eef12016-01-08 06:47:13 -08003932 RunBaseTest(&test);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003933}
3934
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003935void EndToEndTest::TestRtpStatePreservation(bool use_rtx,
3936 bool provoke_rtcpsr_before_rtp) {
brandtr5e171752017-05-23 03:32:16 -07003937 // This test uses other VideoStream settings than the the default settings
3938 // implemented in DefaultVideoStreamFactory. Therefore this test implements
perkjfa10b552016-10-02 23:45:26 -07003939 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3940 // in ModifyVideoConfigs.
3941 class VideoStreamFactory
3942 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3943 public:
3944 VideoStreamFactory() {}
3945
3946 private:
3947 std::vector<VideoStream> CreateEncoderStreams(
3948 int width,
3949 int height,
3950 const VideoEncoderConfig& encoder_config) override {
3951 std::vector<VideoStream> streams =
3952 test::CreateVideoStreams(width, height, encoder_config);
3953
3954 if (encoder_config.number_of_streams > 1) {
3955 // Lower bitrates so that all streams send initially.
kwibergaf476c72016-11-28 15:21:39 -08003956 RTC_DCHECK_EQ(3, encoder_config.number_of_streams);
perkjfa10b552016-10-02 23:45:26 -07003957 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3958 streams[i].min_bitrate_bps = 10000;
3959 streams[i].target_bitrate_bps = 15000;
3960 streams[i].max_bitrate_bps = 20000;
3961 }
3962 } else {
3963 // Use the same total bitrates when sending a single stream to avoid
3964 // lowering
3965 // the bitrate estimate and requiring a subsequent rampup.
3966 streams[0].min_bitrate_bps = 3 * 10000;
3967 streams[0].target_bitrate_bps = 3 * 15000;
3968 streams[0].max_bitrate_bps = 3 * 20000;
3969 }
3970 return streams;
3971 }
3972 };
3973
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003974 class RtpSequenceObserver : public test::RtpRtcpObserver {
3975 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003976 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003977 : test::RtpRtcpObserver(kDefaultTimeoutMs),
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003978 ssrcs_to_observe_(kNumSsrcs) {
3979 for (size_t i = 0; i < kNumSsrcs; ++i) {
danilchap32cd2c42016-08-01 06:58:34 -07003980 ssrc_is_rtx_[kVideoSendSsrcs[i]] = false;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003981 if (use_rtx)
danilchap32cd2c42016-08-01 06:58:34 -07003982 ssrc_is_rtx_[kSendRtxSsrcs[i]] = true;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003983 }
3984 }
3985
3986 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
Peter Boströmf2f82832015-05-01 13:00:41 +02003987 rtc::CritScope lock(&crit_);
danilchap34877ee2016-02-01 08:25:04 -08003988 ssrc_observed_.clear();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003989 ssrcs_to_observe_ = num_expected_ssrcs;
3990 }
3991
3992 private:
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003993 void ValidateTimestampGap(uint32_t ssrc,
3994 uint32_t timestamp,
3995 bool only_padding)
danilchapa37de392017-09-09 04:17:22 -07003996 RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003997 static const int32_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
3998 auto timestamp_it = last_observed_timestamp_.find(ssrc);
3999 if (timestamp_it == last_observed_timestamp_.end()) {
4000 EXPECT_FALSE(only_padding);
4001 last_observed_timestamp_[ssrc] = timestamp;
4002 } else {
4003 // Verify timestamps are reasonably close.
4004 uint32_t latest_observed = timestamp_it->second;
4005 // Wraparound handling is unnecessary here as long as an int variable
4006 // is used to store the result.
4007 int32_t timestamp_gap = timestamp - latest_observed;
4008 EXPECT_LE(std::abs(timestamp_gap), kMaxTimestampGap)
4009 << "Gap in timestamps (" << latest_observed << " -> " << timestamp
4010 << ") too large for SSRC: " << ssrc << ".";
4011 timestamp_it->second = timestamp;
4012 }
4013 }
4014
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004015 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004016 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00004017 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004018 const uint32_t ssrc = header.ssrc;
danilchap5c35cf92016-02-03 14:14:49 -08004019 const int64_t sequence_number =
4020 seq_numbers_unwrapper_.Unwrap(header.sequenceNumber);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004021 const uint32_t timestamp = header.timestamp;
danilchap34877ee2016-02-01 08:25:04 -08004022 const bool only_padding =
4023 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004024
danilchap32cd2c42016-08-01 06:58:34 -07004025 EXPECT_TRUE(ssrc_is_rtx_.find(ssrc) != ssrc_is_rtx_.end())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004026 << "Received SSRC that wasn't configured: " << ssrc;
4027
danilchap5c35cf92016-02-03 14:14:49 -08004028 static const int64_t kMaxSequenceNumberGap = 100;
4029 std::list<int64_t>* seq_numbers = &last_observed_seq_numbers_[ssrc];
4030 if (seq_numbers->empty()) {
4031 seq_numbers->push_back(sequence_number);
4032 } else {
4033 // We shouldn't get replays of previous sequence numbers.
4034 for (int64_t observed : *seq_numbers) {
4035 EXPECT_NE(observed, sequence_number)
4036 << "Received sequence number " << sequence_number
4037 << " for SSRC " << ssrc << " 2nd time.";
4038 }
4039 // Verify sequence numbers are reasonably close.
4040 int64_t latest_observed = seq_numbers->back();
4041 int64_t sequence_number_gap = sequence_number - latest_observed;
4042 EXPECT_LE(std::abs(sequence_number_gap), kMaxSequenceNumberGap)
4043 << "Gap in sequence numbers (" << latest_observed << " -> "
4044 << sequence_number << ") too large for SSRC: " << ssrc << ".";
4045 seq_numbers->push_back(sequence_number);
4046 if (seq_numbers->size() >= kMaxSequenceNumberGap) {
4047 seq_numbers->pop_front();
4048 }
4049 }
4050
danilchap32cd2c42016-08-01 06:58:34 -07004051 if (!ssrc_is_rtx_[ssrc]) {
4052 rtc::CritScope lock(&crit_);
4053 ValidateTimestampGap(ssrc, timestamp, only_padding);
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004054
danilchap32cd2c42016-08-01 06:58:34 -07004055 // Wait for media packets on all ssrcs.
4056 if (!ssrc_observed_[ssrc] && !only_padding) {
4057 ssrc_observed_[ssrc] = true;
4058 if (--ssrcs_to_observe_ == 0)
4059 observation_complete_.Set();
4060 }
danilchap34877ee2016-02-01 08:25:04 -08004061 }
4062
danilchapf4b9c772016-01-28 06:14:24 -08004063 return SEND_PACKET;
4064 }
4065
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004066 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
4067 test::RtcpPacketParser rtcp_parser;
4068 rtcp_parser.Parse(packet, length);
4069 if (rtcp_parser.sender_report()->num_packets() > 0) {
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02004070 uint32_t ssrc = rtcp_parser.sender_report()->sender_ssrc();
4071 uint32_t rtcp_timestamp = rtcp_parser.sender_report()->rtp_timestamp();
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004072
4073 rtc::CritScope lock(&crit_);
4074 ValidateTimestampGap(ssrc, rtcp_timestamp, false);
4075 }
4076 return SEND_PACKET;
4077 }
4078
danilchap5c35cf92016-02-03 14:14:49 -08004079 SequenceNumberUnwrapper seq_numbers_unwrapper_;
4080 std::map<uint32_t, std::list<int64_t>> last_observed_seq_numbers_;
danilchap34877ee2016-02-01 08:25:04 -08004081 std::map<uint32_t, uint32_t> last_observed_timestamp_;
danilchap32cd2c42016-08-01 06:58:34 -07004082 std::map<uint32_t, bool> ssrc_is_rtx_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004083
Peter Boströmf2f82832015-05-01 13:00:41 +02004084 rtc::CriticalSection crit_;
danilchapa37de392017-09-09 04:17:22 -07004085 size_t ssrcs_to_observe_ RTC_GUARDED_BY(crit_);
4086 std::map<uint32_t, bool> ssrc_observed_ RTC_GUARDED_BY(crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004087 } observer(use_rtx);
4088
eladalon413ee9a2017-08-22 04:02:52 -07004089 std::unique_ptr<test::PacketTransport> send_transport;
4090 std::unique_ptr<test::PacketTransport> receive_transport;
4091
philipel4fb651d2017-04-10 03:54:05 -07004092 Call::Config config(event_log_.get());
eladalon413ee9a2017-08-22 04:02:52 -07004093 VideoEncoderConfig one_stream;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004094
eladalon413ee9a2017-08-22 04:02:52 -07004095 task_queue_.SendTask([this, &observer, &send_transport, &receive_transport,
4096 &config, &one_stream, use_rtx]() {
4097 CreateCalls(config, config);
stefanf116bd02015-10-27 08:29:42 -07004098
eladalon413ee9a2017-08-22 04:02:52 -07004099 send_transport = rtc::MakeUnique<test::PacketTransport>(
4100 &task_queue_, sender_call_.get(), &observer,
4101 test::PacketTransport::kSender, payload_type_map_,
4102 FakeNetworkPipe::Config());
4103 receive_transport = rtc::MakeUnique<test::PacketTransport>(
4104 &task_queue_, nullptr, &observer, test::PacketTransport::kReceiver,
4105 payload_type_map_, FakeNetworkPipe::Config());
4106 send_transport->SetReceiver(receiver_call_->Receiver());
4107 receive_transport->SetReceiver(sender_call_->Receiver());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004108
eladalon413ee9a2017-08-22 04:02:52 -07004109 CreateSendConfig(kNumSsrcs, 0, 0, send_transport.get());
4110
4111 if (use_rtx) {
4112 for (size_t i = 0; i < kNumSsrcs; ++i) {
4113 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
4114 }
4115 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004116 }
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004117
eladalon413ee9a2017-08-22 04:02:52 -07004118 video_encoder_config_.video_stream_factory =
4119 new rtc::RefCountedObject<VideoStreamFactory>();
4120 // Use the same total bitrates when sending a single stream to avoid
4121 // lowering the bitrate estimate and requiring a subsequent rampup.
4122 one_stream = video_encoder_config_.Copy();
4123 // one_stream.streams.resize(1);
4124 one_stream.number_of_streams = 1;
4125 CreateMatchingReceiveConfigs(receive_transport.get());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004126
eladalon413ee9a2017-08-22 04:02:52 -07004127 CreateVideoStreams();
4128 CreateFrameGeneratorCapturer(30, 1280, 720);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004129
eladalon413ee9a2017-08-22 04:02:52 -07004130 Start();
4131 });
4132
Peter Boström5811a392015-12-10 13:02:50 +01004133 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004134 << "Timed out waiting for all SSRCs to send packets.";
4135
4136 // Test stream resetting more than once to make sure that the state doesn't
4137 // get set once (this could be due to using std::map::insert for instance).
4138 for (size_t i = 0; i < 3; ++i) {
eladalon413ee9a2017-08-22 04:02:52 -07004139 task_queue_.SendTask([&]() {
4140 frame_generator_capturer_->Stop();
4141 sender_call_->DestroyVideoSendStream(video_send_stream_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004142
eladalon413ee9a2017-08-22 04:02:52 -07004143 // Re-create VideoSendStream with only one stream.
4144 video_send_stream_ = sender_call_->CreateVideoSendStream(
4145 video_send_config_.Copy(), one_stream.Copy());
4146 video_send_stream_->Start();
4147 if (provoke_rtcpsr_before_rtp) {
4148 // Rapid Resync Request forces sending RTCP Sender Report back.
4149 // Using this request speeds up this test because then there is no need
4150 // to wait for a second for periodic Sender Report.
4151 rtcp::RapidResyncRequest force_send_sr_back_request;
4152 rtc::Buffer packet = force_send_sr_back_request.Build();
4153 static_cast<webrtc::test::DirectTransport*>(receive_transport.get())
4154 ->SendRtcp(packet.data(), packet.size());
4155 }
4156 CreateFrameGeneratorCapturer(30, 1280, 720);
4157 frame_generator_capturer_->Start();
4158 });
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004159
4160 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01004161 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004162
4163 // Reconfigure back to use all streams.
eladalon413ee9a2017-08-22 04:02:52 -07004164 task_queue_.SendTask([this]() {
4165 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
4166 });
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004167 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01004168 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004169 << "Timed out waiting for all SSRCs to send packets.";
4170
4171 // Reconfigure down to one stream.
eladalon413ee9a2017-08-22 04:02:52 -07004172 task_queue_.SendTask([this, &one_stream]() {
4173 video_send_stream_->ReconfigureVideoEncoder(one_stream.Copy());
4174 });
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004175 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01004176 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004177
4178 // Reconfigure back to use all streams.
eladalon413ee9a2017-08-22 04:02:52 -07004179 task_queue_.SendTask([this]() {
4180 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
4181 });
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004182 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01004183 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004184 << "Timed out waiting for all SSRCs to send packets.";
4185 }
4186
eladalon413ee9a2017-08-22 04:02:52 -07004187 task_queue_.SendTask([this, &send_transport, &receive_transport]() {
4188 Stop();
4189 DestroyStreams();
4190 send_transport.reset();
4191 receive_transport.reset();
4192 DestroyCalls();
4193 });
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004194}
4195
philipel277a8b52017-03-16 05:19:49 -07004196TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpState) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004197 TestRtpStatePreservation(false, false);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004198}
4199
philipel277a8b52017-03-16 05:19:49 -07004200TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpStatesWithRtx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004201 TestRtpStatePreservation(true, false);
4202}
4203
philipel277a8b52017-03-16 05:19:49 -07004204TEST_F(EndToEndTest, RestartingSendStreamKeepsRtpAndRtcpTimestampsSynced) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004205 TestRtpStatePreservation(true, true);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004206}
4207
brandtreb806792017-05-31 07:46:56 -07004208// This test is flaky on linux_memcheck. Disable on all linux bots until
4209// flakyness has been fixed.
4210// https://bugs.chromium.org/p/webrtc/issues/detail?id=7737
4211#if defined(WEBRTC_LINUX)
4212#define MAYBE_TestFlexfecRtpStatePreservation \
4213 DISABLED_TestFlexfecRtpStatePreservation
4214#else
4215#define MAYBE_TestFlexfecRtpStatePreservation TestFlexfecRtpStatePreservation
4216#endif
4217TEST_F(EndToEndTest, MAYBE_TestFlexfecRtpStatePreservation) {
brandtr48d21a22017-05-30 02:32:12 -07004218 class RtpSequenceObserver : public test::RtpRtcpObserver {
4219 public:
4220 RtpSequenceObserver()
4221 : test::RtpRtcpObserver(kDefaultTimeoutMs),
4222 num_flexfec_packets_sent_(0) {}
4223
4224 void ResetPacketCount() {
4225 rtc::CritScope lock(&crit_);
4226 num_flexfec_packets_sent_ = 0;
4227 }
4228
4229 private:
4230 Action OnSendRtp(const uint8_t* packet, size_t length) override {
4231 rtc::CritScope lock(&crit_);
4232
4233 RTPHeader header;
4234 EXPECT_TRUE(parser_->Parse(packet, length, &header));
4235 const uint16_t sequence_number = header.sequenceNumber;
4236 const uint32_t timestamp = header.timestamp;
4237 const uint32_t ssrc = header.ssrc;
4238
4239 if (ssrc == kVideoSendSsrcs[0] || ssrc == kSendRtxSsrcs[0]) {
4240 return SEND_PACKET;
4241 }
4242 EXPECT_EQ(kFlexfecSendSsrc, ssrc) << "Unknown SSRC sent.";
4243
4244 ++num_flexfec_packets_sent_;
4245
4246 // If this is the first packet, we have nothing to compare to.
4247 if (!last_observed_sequence_number_) {
4248 last_observed_sequence_number_.emplace(sequence_number);
4249 last_observed_timestamp_.emplace(timestamp);
4250
4251 return SEND_PACKET;
4252 }
4253
4254 // Verify continuity and monotonicity of RTP sequence numbers.
4255 EXPECT_EQ(static_cast<uint16_t>(*last_observed_sequence_number_ + 1),
4256 sequence_number);
4257 last_observed_sequence_number_.emplace(sequence_number);
4258
4259 // Timestamps should be non-decreasing...
4260 const bool timestamp_is_same_or_newer =
4261 timestamp == *last_observed_timestamp_ ||
4262 IsNewerTimestamp(timestamp, *last_observed_timestamp_);
4263 EXPECT_TRUE(timestamp_is_same_or_newer);
4264 // ...but reasonably close in time.
4265 const int k10SecondsInRtpTimestampBase = 10 * kVideoPayloadTypeFrequency;
4266 EXPECT_TRUE(IsNewerTimestamp(
4267 *last_observed_timestamp_ + k10SecondsInRtpTimestampBase, timestamp));
4268 last_observed_timestamp_.emplace(timestamp);
4269
4270 // Pass test when enough packets have been let through.
4271 if (num_flexfec_packets_sent_ >= 10) {
4272 observation_complete_.Set();
4273 }
4274
4275 return SEND_PACKET;
4276 }
4277
danilchapa37de392017-09-09 04:17:22 -07004278 rtc::Optional<uint16_t> last_observed_sequence_number_
4279 RTC_GUARDED_BY(crit_);
4280 rtc::Optional<uint32_t> last_observed_timestamp_ RTC_GUARDED_BY(crit_);
4281 size_t num_flexfec_packets_sent_ RTC_GUARDED_BY(crit_);
brandtr48d21a22017-05-30 02:32:12 -07004282 rtc::CriticalSection crit_;
4283 } observer;
4284
eladalon05b07bb2017-08-24 07:40:16 -07004285 static constexpr int kFrameMaxWidth = 320;
4286 static constexpr int kFrameMaxHeight = 180;
4287 static constexpr int kFrameRate = 15;
eladalon413ee9a2017-08-22 04:02:52 -07004288
brandtr48d21a22017-05-30 02:32:12 -07004289 Call::Config config(event_log_.get());
brandtr48d21a22017-05-30 02:32:12 -07004290
eladalon413ee9a2017-08-22 04:02:52 -07004291 std::unique_ptr<test::PacketTransport> send_transport;
4292 std::unique_ptr<test::PacketTransport> receive_transport;
4293 std::unique_ptr<VideoEncoder> encoder;
brandtr48d21a22017-05-30 02:32:12 -07004294
eladalon413ee9a2017-08-22 04:02:52 -07004295 task_queue_.SendTask([&]() {
4296 CreateCalls(config, config);
brandtr48d21a22017-05-30 02:32:12 -07004297
eladalon413ee9a2017-08-22 04:02:52 -07004298 FakeNetworkPipe::Config lossy_delayed_link;
4299 lossy_delayed_link.loss_percent = 2;
4300 lossy_delayed_link.queue_delay_ms = 50;
brandtr48d21a22017-05-30 02:32:12 -07004301
eladalon413ee9a2017-08-22 04:02:52 -07004302 send_transport = rtc::MakeUnique<test::PacketTransport>(
4303 &task_queue_, sender_call_.get(), &observer,
4304 test::PacketTransport::kSender, payload_type_map_, lossy_delayed_link);
4305 send_transport->SetReceiver(receiver_call_->Receiver());
brandtr48d21a22017-05-30 02:32:12 -07004306
eladalon413ee9a2017-08-22 04:02:52 -07004307 FakeNetworkPipe::Config flawless_link;
4308 receive_transport = rtc::MakeUnique<test::PacketTransport>(
4309 &task_queue_, nullptr, &observer, test::PacketTransport::kReceiver,
4310 payload_type_map_, flawless_link);
4311 receive_transport->SetReceiver(sender_call_->Receiver());
brandtr48d21a22017-05-30 02:32:12 -07004312
eladalon413ee9a2017-08-22 04:02:52 -07004313 // For reduced flakyness, we use a real VP8 encoder together with NACK
4314 // and RTX.
4315 const int kNumVideoStreams = 1;
4316 const int kNumFlexfecStreams = 1;
4317 CreateSendConfig(kNumVideoStreams, 0, kNumFlexfecStreams,
4318 send_transport.get());
4319 encoder = rtc::WrapUnique(VP8Encoder::Create());
4320 video_send_config_.encoder_settings.encoder = encoder.get();
4321 video_send_config_.encoder_settings.payload_name = "VP8";
4322 video_send_config_.encoder_settings.payload_type = kVideoSendPayloadType;
4323 video_send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
4324 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
4325 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
brandtr48d21a22017-05-30 02:32:12 -07004326
eladalon413ee9a2017-08-22 04:02:52 -07004327 CreateMatchingReceiveConfigs(receive_transport.get());
4328 video_receive_configs_[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
4329 video_receive_configs_[0].rtp.rtx_ssrc = kSendRtxSsrcs[0];
nisse26e3abb2017-08-25 04:44:25 -07004330 video_receive_configs_[0]
4331 .rtp.rtx_associated_payload_types[kSendRtxPayloadType] =
4332 kVideoSendPayloadType;
brandtr48d21a22017-05-30 02:32:12 -07004333
eladalon413ee9a2017-08-22 04:02:52 -07004334 // The matching FlexFEC receive config is not created by
4335 // CreateMatchingReceiveConfigs since this is not a test::BaseTest.
4336 // Set up the receive config manually instead.
4337 FlexfecReceiveStream::Config flexfec_receive_config(
4338 receive_transport.get());
4339 flexfec_receive_config.payload_type =
4340 video_send_config_.rtp.flexfec.payload_type;
4341 flexfec_receive_config.remote_ssrc = video_send_config_.rtp.flexfec.ssrc;
4342 flexfec_receive_config.protected_media_ssrcs =
4343 video_send_config_.rtp.flexfec.protected_media_ssrcs;
4344 flexfec_receive_config.local_ssrc = kReceiverLocalVideoSsrc;
4345 flexfec_receive_config.transport_cc = true;
4346 flexfec_receive_config.rtp_header_extensions.emplace_back(
4347 RtpExtension::kTransportSequenceNumberUri,
4348 test::kTransportSequenceNumberExtensionId);
4349 flexfec_receive_configs_.push_back(flexfec_receive_config);
4350
4351 CreateFlexfecStreams();
4352 CreateVideoStreams();
4353
4354 // RTCP might be disabled if the network is "down".
4355 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
4356 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
4357
4358 CreateFrameGeneratorCapturer(kFrameRate, kFrameMaxWidth, kFrameMaxHeight);
4359
4360 Start();
4361 });
brandtr48d21a22017-05-30 02:32:12 -07004362
4363 // Initial test.
brandtr48d21a22017-05-30 02:32:12 -07004364 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for packets.";
4365
eladalon413ee9a2017-08-22 04:02:52 -07004366 task_queue_.SendTask([this, &observer]() {
4367 // Ensure monotonicity when the VideoSendStream is restarted.
4368 Stop();
4369 observer.ResetPacketCount();
4370 Start();
4371 });
4372
brandtr48d21a22017-05-30 02:32:12 -07004373 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for packets.";
4374
eladalon05b07bb2017-08-24 07:40:16 -07004375 task_queue_.SendTask([this, &observer]() {
eladalon413ee9a2017-08-22 04:02:52 -07004376 // Ensure monotonicity when the VideoSendStream is recreated.
4377 frame_generator_capturer_->Stop();
4378 sender_call_->DestroyVideoSendStream(video_send_stream_);
4379 observer.ResetPacketCount();
4380 video_send_stream_ = sender_call_->CreateVideoSendStream(
4381 video_send_config_.Copy(), video_encoder_config_.Copy());
4382 video_send_stream_->Start();
4383 CreateFrameGeneratorCapturer(kFrameRate, kFrameMaxWidth, kFrameMaxHeight);
4384 frame_generator_capturer_->Start();
4385 });
4386
brandtr48d21a22017-05-30 02:32:12 -07004387 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for packets.";
4388
4389 // Cleanup.
eladalon413ee9a2017-08-22 04:02:52 -07004390 task_queue_.SendTask([this, &send_transport, &receive_transport]() {
4391 Stop();
4392 DestroyStreams();
4393 send_transport.reset();
4394 receive_transport.reset();
4395 DestroyCalls();
4396 });
brandtr48d21a22017-05-30 02:32:12 -07004397}
4398
philipel277a8b52017-03-16 05:19:49 -07004399TEST_F(EndToEndTest, RespectsNetworkState) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004400 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
4401 // down blocks until no more packets will be sent.
4402
4403 // Pacer will send from its packet list and then send required padding before
4404 // checking paused_ again. This should be enough for one round of pacing,
4405 // otherwise increase.
4406 static const int kNumAcceptedDowntimeRtp = 5;
4407 // A single RTCP may be in the pipeline.
4408 static const int kNumAcceptedDowntimeRtcp = 1;
4409 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
4410 public:
eladalon413ee9a2017-08-22 04:02:52 -07004411 explicit NetworkStateTest(
4412 test::SingleThreadedTaskQueueForTesting* task_queue)
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004413 : EndToEndTest(kDefaultTimeoutMs),
4414 FakeEncoder(Clock::GetRealTimeClock()),
eladalon413ee9a2017-08-22 04:02:52 -07004415 task_queue_(task_queue),
Peter Boström5811a392015-12-10 13:02:50 +01004416 encoded_frames_(false, false),
4417 packet_event_(false, false),
sprang867fb522015-08-03 04:38:41 -07004418 sender_call_(nullptr),
4419 receiver_call_(nullptr),
Jelena Marusiccd670222015-07-16 09:30:09 +02004420 sender_state_(kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004421 sender_rtp_(0),
stefan9e117c5e12017-08-16 08:16:25 -07004422 sender_padding_(0),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004423 sender_rtcp_(0),
4424 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004425 down_frames_(0) {}
4426
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004427 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02004428 rtc::CritScope lock(&test_crit_);
stefan9e117c5e12017-08-16 08:16:25 -07004429 RTPHeader header;
4430 EXPECT_TRUE(parser_->Parse(packet, length, &header));
4431 if (length == header.headerLength + header.paddingLength)
4432 ++sender_padding_;
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004433 ++sender_rtp_;
Peter Boström5811a392015-12-10 13:02:50 +01004434 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004435 return SEND_PACKET;
4436 }
4437
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004438 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02004439 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004440 ++sender_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01004441 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004442 return SEND_PACKET;
4443 }
4444
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004445 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004446 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
4447 return SEND_PACKET;
4448 }
4449
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004450 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02004451 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004452 ++receiver_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01004453 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004454 return SEND_PACKET;
4455 }
4456
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004457 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004458 sender_call_ = sender_call;
4459 receiver_call_ = receiver_call;
4460 }
4461
stefanff483612015-12-21 03:14:00 -08004462 void ModifyVideoConfigs(
4463 VideoSendStream::Config* send_config,
4464 std::vector<VideoReceiveStream::Config>* receive_configs,
4465 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004466 send_config->encoder_settings.encoder = this;
4467 }
4468
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004469 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01004470 EXPECT_TRUE(encoded_frames_.Wait(kDefaultTimeoutMs))
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004471 << "No frames received by the encoder.";
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004472
eladalon413ee9a2017-08-22 04:02:52 -07004473 task_queue_->SendTask([this]() {
4474 // Wait for packets from both sender/receiver.
4475 WaitForPacketsOrSilence(false, false);
skvlad7a43d252016-03-22 15:32:27 -07004476
eladalon413ee9a2017-08-22 04:02:52 -07004477 // Sender-side network down for audio; there should be no effect on
4478 // video
4479 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
4480 WaitForPacketsOrSilence(false, false);
skvlad7a43d252016-03-22 15:32:27 -07004481
eladalon413ee9a2017-08-22 04:02:52 -07004482 // Receiver-side network down for audio; no change expected
4483 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO,
4484 kNetworkDown);
4485 WaitForPacketsOrSilence(false, false);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004486
eladalon413ee9a2017-08-22 04:02:52 -07004487 // Sender-side network down.
4488 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
4489 {
4490 rtc::CritScope lock(&test_crit_);
4491 // After network goes down we shouldn't be encoding more frames.
4492 sender_state_ = kNetworkDown;
4493 }
4494 // Wait for receiver-packets and no sender packets.
4495 WaitForPacketsOrSilence(true, false);
skvlad7a43d252016-03-22 15:32:27 -07004496
eladalon413ee9a2017-08-22 04:02:52 -07004497 // Receiver-side network down.
4498 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO,
4499 kNetworkDown);
4500 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004501
eladalon413ee9a2017-08-22 04:02:52 -07004502 // Network up for audio for both sides; video is still not expected to
4503 // start
4504 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
4505 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
4506 WaitForPacketsOrSilence(true, true);
skvlad7a43d252016-03-22 15:32:27 -07004507
eladalon413ee9a2017-08-22 04:02:52 -07004508 // Network back up again for both.
4509 {
4510 rtc::CritScope lock(&test_crit_);
4511 // It's OK to encode frames again, as we're about to bring up the
4512 // network.
4513 sender_state_ = kNetworkUp;
4514 }
4515 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
4516 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
4517 WaitForPacketsOrSilence(false, false);
4518
4519 // TODO(skvlad): add tests to verify that the audio streams are stopped
4520 // when the network goes down for audio once the workaround in
4521 // paced_sender.cc is removed.
4522 });
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004523 }
4524
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07004525 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004526 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07004527 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004528 {
Peter Boströmf2f82832015-05-01 13:00:41 +02004529 rtc::CritScope lock(&test_crit_);
Jelena Marusiccd670222015-07-16 09:30:09 +02004530 if (sender_state_ == kNetworkDown) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004531 ++down_frames_;
4532 EXPECT_LE(down_frames_, 1)
4533 << "Encoding more than one frame while network is down.";
4534 if (down_frames_ > 1)
Peter Boström5811a392015-12-10 13:02:50 +01004535 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004536 } else {
Peter Boström5811a392015-12-10 13:02:50 +01004537 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004538 }
4539 }
4540 return test::FakeEncoder::Encode(
4541 input_image, codec_specific_info, frame_types);
4542 }
4543
4544 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004545 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
4546 int64_t initial_time_ms = clock_->TimeInMilliseconds();
4547 int initial_sender_rtp;
4548 int initial_sender_rtcp;
4549 int initial_receiver_rtcp;
4550 {
Peter Boströmf2f82832015-05-01 13:00:41 +02004551 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004552 initial_sender_rtp = sender_rtp_;
4553 initial_sender_rtcp = sender_rtcp_;
4554 initial_receiver_rtcp = receiver_rtcp_;
4555 }
4556 bool sender_done = false;
4557 bool receiver_done = false;
mflodmand1590b22015-12-09 07:07:59 -08004558 while (!sender_done || !receiver_done) {
Peter Boström5811a392015-12-10 13:02:50 +01004559 packet_event_.Wait(kSilenceTimeoutMs);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004560 int64_t time_now_ms = clock_->TimeInMilliseconds();
Peter Boströmf2f82832015-05-01 13:00:41 +02004561 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004562 if (sender_down) {
stefan9e117c5e12017-08-16 08:16:25 -07004563 ASSERT_LE(sender_rtp_ - initial_sender_rtp - sender_padding_,
4564 kNumAcceptedDowntimeRtp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004565 << "RTP sent during sender-side downtime.";
4566 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
4567 kNumAcceptedDowntimeRtcp)
4568 << "RTCP sent during sender-side downtime.";
4569 if (time_now_ms - initial_time_ms >=
4570 static_cast<int64_t>(kSilenceTimeoutMs)) {
4571 sender_done = true;
4572 }
4573 } else {
skvlad7a43d252016-03-22 15:32:27 -07004574 if (sender_rtp_ > initial_sender_rtp + kNumAcceptedDowntimeRtp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004575 sender_done = true;
4576 }
4577 if (receiver_down) {
4578 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
4579 kNumAcceptedDowntimeRtcp)
4580 << "RTCP sent during receiver-side downtime.";
4581 if (time_now_ms - initial_time_ms >=
4582 static_cast<int64_t>(kSilenceTimeoutMs)) {
4583 receiver_done = true;
4584 }
4585 } else {
skvlad7a43d252016-03-22 15:32:27 -07004586 if (receiver_rtcp_ > initial_receiver_rtcp + kNumAcceptedDowntimeRtcp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004587 receiver_done = true;
4588 }
4589 }
4590 }
4591
eladalon413ee9a2017-08-22 04:02:52 -07004592 test::SingleThreadedTaskQueueForTesting* const task_queue_;
Peter Boströmf2f82832015-05-01 13:00:41 +02004593 rtc::CriticalSection test_crit_;
Peter Boström5811a392015-12-10 13:02:50 +01004594 rtc::Event encoded_frames_;
4595 rtc::Event packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004596 Call* sender_call_;
4597 Call* receiver_call_;
danilchapa37de392017-09-09 04:17:22 -07004598 NetworkState sender_state_ RTC_GUARDED_BY(test_crit_);
4599 int sender_rtp_ RTC_GUARDED_BY(test_crit_);
4600 int sender_padding_ RTC_GUARDED_BY(test_crit_);
4601 int sender_rtcp_ RTC_GUARDED_BY(test_crit_);
4602 int receiver_rtcp_ RTC_GUARDED_BY(test_crit_);
4603 int down_frames_ RTC_GUARDED_BY(test_crit_);
eladalon413ee9a2017-08-22 04:02:52 -07004604 } test(&task_queue_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004605
stefane74eef12016-01-08 06:47:13 -08004606 RunBaseTest(&test);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004607}
4608
philipel277a8b52017-03-16 05:19:49 -07004609TEST_F(EndToEndTest, CallReportsRttForSender) {
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004610 static const int kSendDelayMs = 30;
4611 static const int kReceiveDelayMs = 70;
solenberg4fbae2b2015-08-28 04:07:10 -07004612
eladalon413ee9a2017-08-22 04:02:52 -07004613 std::unique_ptr<test::DirectTransport> sender_transport;
4614 std::unique_ptr<test::DirectTransport> receiver_transport;
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004615
eladalon413ee9a2017-08-22 04:02:52 -07004616 task_queue_.SendTask([this, &sender_transport, &receiver_transport]() {
4617 FakeNetworkPipe::Config config;
4618 config.queue_delay_ms = kSendDelayMs;
4619 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
4620 sender_transport = rtc::MakeUnique<test::DirectTransport>(
4621 &task_queue_, config, sender_call_.get(), payload_type_map_);
4622 config.queue_delay_ms = kReceiveDelayMs;
4623 receiver_transport = rtc::MakeUnique<test::DirectTransport>(
4624 &task_queue_, config, receiver_call_.get(), payload_type_map_);
4625 sender_transport->SetReceiver(receiver_call_->Receiver());
4626 receiver_transport->SetReceiver(sender_call_->Receiver());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004627
eladalon413ee9a2017-08-22 04:02:52 -07004628 CreateSendConfig(1, 0, 0, sender_transport.get());
4629 CreateMatchingReceiveConfigs(receiver_transport.get());
4630
4631 CreateVideoStreams();
4632 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
4633 kDefaultHeight);
4634 Start();
4635 });
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004636
4637 int64_t start_time_ms = clock_->TimeInMilliseconds();
4638 while (true) {
4639 Call::Stats stats = sender_call_->GetStats();
4640 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
4641 clock_->TimeInMilliseconds())
4642 << "No RTT stats before timeout!";
4643 if (stats.rtt_ms != -1) {
Danil Chapovalov10e8f8e2016-09-07 15:05:29 +02004644 // To avoid failures caused by rounding or minor ntp clock adjustments,
4645 // relax expectation by 1ms.
4646 constexpr int kAllowedErrorMs = 1;
4647 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs - kAllowedErrorMs);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004648 break;
4649 }
4650 SleepMs(10);
4651 }
4652
eladalon413ee9a2017-08-22 04:02:52 -07004653 task_queue_.SendTask([this, &sender_transport, &receiver_transport]() {
4654 Stop();
4655 DestroyStreams();
4656 sender_transport.reset();
4657 receiver_transport.reset();
4658 DestroyCalls();
4659 });
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004660}
4661
skvlad7a43d252016-03-22 15:32:27 -07004662void EndToEndTest::VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004663 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -07004664 VideoEncoder* encoder,
4665 Transport* transport) {
eladalon413ee9a2017-08-22 04:02:52 -07004666 task_queue_.SendTask([this, network_to_bring_up, encoder, transport]() {
4667 CreateSenderCall(Call::Config(event_log_.get()));
4668 sender_call_->SignalChannelNetworkState(network_to_bring_up, kNetworkUp);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004669
eladalon413ee9a2017-08-22 04:02:52 -07004670 CreateSendConfig(1, 0, 0, transport);
4671 video_send_config_.encoder_settings.encoder = encoder;
4672 CreateVideoStreams();
4673 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
4674 kDefaultHeight);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004675
eladalon413ee9a2017-08-22 04:02:52 -07004676 Start();
4677 });
4678
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004679 SleepMs(kSilenceTimeoutMs);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004680
eladalon413ee9a2017-08-22 04:02:52 -07004681 task_queue_.SendTask([this]() {
4682 Stop();
4683 DestroyStreams();
4684 DestroyCalls();
4685 });
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004686}
4687
skvlad7a43d252016-03-22 15:32:27 -07004688void EndToEndTest::VerifyNewVideoReceiveStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004689 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -07004690 Transport* transport) {
eladalon413ee9a2017-08-22 04:02:52 -07004691 std::unique_ptr<test::DirectTransport> sender_transport;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004692
eladalon413ee9a2017-08-22 04:02:52 -07004693 task_queue_.SendTask([this, &sender_transport, network_to_bring_up,
4694 transport]() {
4695 Call::Config config(event_log_.get());
4696 CreateCalls(config, config);
4697 receiver_call_->SignalChannelNetworkState(network_to_bring_up, kNetworkUp);
4698 sender_transport = rtc::MakeUnique<test::DirectTransport>(
4699 &task_queue_, sender_call_.get(), payload_type_map_);
4700 sender_transport->SetReceiver(receiver_call_->Receiver());
4701 CreateSendConfig(1, 0, 0, sender_transport.get());
4702 CreateMatchingReceiveConfigs(transport);
4703 CreateVideoStreams();
4704 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
4705 kDefaultHeight);
4706 Start();
4707 });
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004708
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004709 SleepMs(kSilenceTimeoutMs);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004710
eladalon413ee9a2017-08-22 04:02:52 -07004711 task_queue_.SendTask([this, &sender_transport]() {
4712 Stop();
4713 DestroyStreams();
4714 sender_transport.reset();
4715 DestroyCalls();
4716 });
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004717}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00004718
philipel277a8b52017-03-16 05:19:49 -07004719TEST_F(EndToEndTest, NewVideoSendStreamsRespectVideoNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004720 class UnusedEncoder : public test::FakeEncoder {
4721 public:
4722 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
perkjfea93092016-05-14 00:58:48 -07004723
4724 int32_t InitEncode(const VideoCodec* config,
4725 int32_t number_of_cores,
4726 size_t max_payload_size) override {
4727 EXPECT_GT(config->startBitrate, 0u);
4728 return 0;
4729 }
skvlad7a43d252016-03-22 15:32:27 -07004730 int32_t Encode(const VideoFrame& input_image,
4731 const CodecSpecificInfo* codec_specific_info,
4732 const std::vector<FrameType>* frame_types) override {
4733 ADD_FAILURE() << "Unexpected frame encode.";
4734 return test::FakeEncoder::Encode(input_image, codec_specific_info,
4735 frame_types);
4736 }
4737 };
4738
4739 UnusedEncoder unused_encoder;
4740 UnusedTransport unused_transport;
4741 VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004742 MediaType::AUDIO, &unused_encoder, &unused_transport);
skvlad7a43d252016-03-22 15:32:27 -07004743}
4744
philipel277a8b52017-03-16 05:19:49 -07004745TEST_F(EndToEndTest, NewVideoSendStreamsIgnoreAudioNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004746 class RequiredEncoder : public test::FakeEncoder {
4747 public:
4748 RequiredEncoder()
4749 : FakeEncoder(Clock::GetRealTimeClock()), encoded_frame_(false) {}
4750 ~RequiredEncoder() {
4751 if (!encoded_frame_) {
4752 ADD_FAILURE() << "Didn't encode an expected frame";
4753 }
4754 }
4755 int32_t Encode(const VideoFrame& input_image,
4756 const CodecSpecificInfo* codec_specific_info,
4757 const std::vector<FrameType>* frame_types) override {
4758 encoded_frame_ = true;
4759 return test::FakeEncoder::Encode(input_image, codec_specific_info,
4760 frame_types);
4761 }
4762
4763 private:
4764 bool encoded_frame_;
4765 };
4766
4767 RequiredTransport required_transport(true /*rtp*/, false /*rtcp*/);
4768 RequiredEncoder required_encoder;
4769 VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004770 MediaType::VIDEO, &required_encoder, &required_transport);
skvlad7a43d252016-03-22 15:32:27 -07004771}
4772
philipel277a8b52017-03-16 05:19:49 -07004773TEST_F(EndToEndTest, NewVideoReceiveStreamsRespectVideoNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004774 UnusedTransport transport;
Sergey Ulanove2b15012016-11-22 16:08:30 -08004775 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::AUDIO, &transport);
skvlad7a43d252016-03-22 15:32:27 -07004776}
4777
philipel277a8b52017-03-16 05:19:49 -07004778TEST_F(EndToEndTest, NewVideoReceiveStreamsIgnoreAudioNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004779 RequiredTransport transport(false /*rtp*/, true /*rtcp*/);
Sergey Ulanove2b15012016-11-22 16:08:30 -08004780 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::VIDEO, &transport);
skvlad7a43d252016-03-22 15:32:27 -07004781}
4782
Peter Boströmd7da1202015-06-05 14:09:38 +02004783void VerifyEmptyNackConfig(const NackConfig& config) {
4784 EXPECT_EQ(0, config.rtp_history_ms)
4785 << "Enabling NACK requires rtcp-fb: nack negotiation.";
4786}
4787
brandtrb5f2c3f2016-10-04 23:28:39 -07004788void VerifyEmptyUlpfecConfig(const UlpfecConfig& config) {
Peter Boströmd7da1202015-06-05 14:09:38 +02004789 EXPECT_EQ(-1, config.ulpfec_payload_type)
brandtr535830e2016-10-31 03:45:58 -07004790 << "Enabling ULPFEC requires rtpmap: ulpfec negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02004791 EXPECT_EQ(-1, config.red_payload_type)
brandtr535830e2016-10-31 03:45:58 -07004792 << "Enabling ULPFEC requires rtpmap: red negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02004793 EXPECT_EQ(-1, config.red_rtx_payload_type)
brandtr535830e2016-10-31 03:45:58 -07004794 << "Enabling RTX in ULPFEC requires rtpmap: rtx negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02004795}
4796
brandtr3d200bd2017-01-16 06:59:19 -08004797void VerifyEmptyFlexfecConfig(
4798 const VideoSendStream::Config::Rtp::Flexfec& config) {
4799 EXPECT_EQ(-1, config.payload_type)
brandtr1e3dfbf2016-11-16 22:45:19 -08004800 << "Enabling FlexFEC requires rtpmap: flexfec negotiation.";
brandtr3d200bd2017-01-16 06:59:19 -08004801 EXPECT_EQ(0U, config.ssrc)
brandtr1cfbd602016-12-08 04:17:53 -08004802 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
brandtr1e3dfbf2016-11-16 22:45:19 -08004803 EXPECT_TRUE(config.protected_media_ssrcs.empty())
4804 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
4805}
4806
philipel277a8b52017-03-16 05:19:49 -07004807TEST_F(EndToEndTest, VerifyDefaultSendConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07004808 VideoSendStream::Config default_send_config(nullptr);
Peter Boströmd7da1202015-06-05 14:09:38 +02004809 EXPECT_EQ(0, default_send_config.rtp.nack.rtp_history_ms)
4810 << "Enabling NACK require rtcp-fb: nack negotiation.";
4811 EXPECT_TRUE(default_send_config.rtp.rtx.ssrcs.empty())
4812 << "Enabling RTX requires rtpmap: rtx negotiation.";
4813 EXPECT_TRUE(default_send_config.rtp.extensions.empty())
4814 << "Enabling RTP extensions require negotiation.";
4815
4816 VerifyEmptyNackConfig(default_send_config.rtp.nack);
brandtrb5f2c3f2016-10-04 23:28:39 -07004817 VerifyEmptyUlpfecConfig(default_send_config.rtp.ulpfec);
brandtr1e3dfbf2016-11-16 22:45:19 -08004818 VerifyEmptyFlexfecConfig(default_send_config.rtp.flexfec);
Peter Boströmd7da1202015-06-05 14:09:38 +02004819}
4820
philipel277a8b52017-03-16 05:19:49 -07004821TEST_F(EndToEndTest, VerifyDefaultVideoReceiveConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07004822 VideoReceiveStream::Config default_receive_config(nullptr);
pbosda903ea2015-10-02 02:36:56 -07004823 EXPECT_EQ(RtcpMode::kCompound, default_receive_config.rtp.rtcp_mode)
Peter Boströmd7da1202015-06-05 14:09:38 +02004824 << "Reduced-size RTCP require rtcp-rsize to be negotiated.";
4825 EXPECT_FALSE(default_receive_config.rtp.remb)
4826 << "REMB require rtcp-fb: goog-remb to be negotiated.";
4827 EXPECT_FALSE(
4828 default_receive_config.rtp.rtcp_xr.receiver_reference_time_report)
4829 << "RTCP XR settings require rtcp-xr to be negotiated.";
brandtr14742122017-01-27 04:53:07 -08004830 EXPECT_EQ(0U, default_receive_config.rtp.rtx_ssrc)
4831 << "Enabling RTX requires ssrc-group: FID negotiation";
nisse26e3abb2017-08-25 04:44:25 -07004832 EXPECT_TRUE(default_receive_config.rtp.rtx_associated_payload_types.empty())
Peter Boströmd7da1202015-06-05 14:09:38 +02004833 << "Enabling RTX requires rtpmap: rtx negotiation.";
4834 EXPECT_TRUE(default_receive_config.rtp.extensions.empty())
4835 << "Enabling RTP extensions require negotiation.";
4836
4837 VerifyEmptyNackConfig(default_receive_config.rtp.nack);
nisse3b3622f2017-09-26 02:49:21 -07004838 EXPECT_EQ(-1, default_receive_config.rtp.ulpfec_payload_type)
4839 << "Enabling ULPFEC requires rtpmap: ulpfec negotiation.";
4840 EXPECT_EQ(-1, default_receive_config.rtp.red_payload_type)
4841 << "Enabling ULPFEC requires rtpmap: red negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02004842}
4843
philipel277a8b52017-03-16 05:19:49 -07004844TEST_F(EndToEndTest, VerifyDefaultFlexfecReceiveConfigParameters) {
brandtr8313a6f2017-01-13 07:41:19 -08004845 test::NullTransport rtcp_send_transport;
4846 FlexfecReceiveStream::Config default_receive_config(&rtcp_send_transport);
brandtr1cfbd602016-12-08 04:17:53 -08004847 EXPECT_EQ(-1, default_receive_config.payload_type)
4848 << "Enabling FlexFEC requires rtpmap: flexfec negotiation.";
4849 EXPECT_EQ(0U, default_receive_config.remote_ssrc)
4850 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
4851 EXPECT_TRUE(default_receive_config.protected_media_ssrcs.empty())
4852 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
brandtr1e3dfbf2016-11-16 22:45:19 -08004853}
4854
philipel277a8b52017-03-16 05:19:49 -07004855TEST_F(EndToEndTest, TransportSeqNumOnAudioAndVideo) {
danilchap4336d732017-03-03 06:21:54 -08004856 static constexpr int kExtensionId = 8;
4857 static constexpr size_t kMinPacketsToWaitFor = 50;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004858 class TransportSequenceNumberTest : public test::EndToEndTest {
4859 public:
4860 TransportSequenceNumberTest()
4861 : EndToEndTest(kDefaultTimeoutMs),
4862 video_observed_(false),
4863 audio_observed_(false) {
4864 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
4865 kExtensionId);
4866 }
4867
4868 size_t GetNumVideoStreams() const override { return 1; }
4869 size_t GetNumAudioStreams() const override { return 1; }
4870
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004871 void ModifyAudioConfigs(
4872 AudioSendStream::Config* send_config,
4873 std::vector<AudioReceiveStream::Config>* receive_configs) override {
4874 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07004875 send_config->rtp.extensions.push_back(RtpExtension(
4876 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004877 (*receive_configs)[0].rtp.extensions.clear();
4878 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
4879 }
4880
4881 Action OnSendRtp(const uint8_t* packet, size_t length) override {
4882 RTPHeader header;
4883 EXPECT_TRUE(parser_->Parse(packet, length, &header));
4884 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
4885 // Unwrap packet id and verify uniqueness.
4886 int64_t packet_id =
4887 unwrapper_.Unwrap(header.extension.transportSequenceNumber);
4888 EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
4889
4890 if (header.ssrc == kVideoSendSsrcs[0])
4891 video_observed_ = true;
4892 if (header.ssrc == kAudioSendSsrc)
4893 audio_observed_ = true;
4894 if (audio_observed_ && video_observed_ &&
danilchap4336d732017-03-03 06:21:54 -08004895 received_packet_ids_.size() >= kMinPacketsToWaitFor) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004896 size_t packet_id_range =
4897 *received_packet_ids_.rbegin() - *received_packet_ids_.begin() + 1;
4898 EXPECT_EQ(received_packet_ids_.size(), packet_id_range);
4899 observation_complete_.Set();
4900 }
4901 return SEND_PACKET;
4902 }
4903
4904 void PerformTest() override {
4905 EXPECT_TRUE(Wait()) << "Timed out while waiting for audio and video "
4906 "packets with transport sequence number.";
4907 }
4908
danilchap4336d732017-03-03 06:21:54 -08004909 void ExpectSuccessful() {
4910 EXPECT_TRUE(video_observed_);
4911 EXPECT_TRUE(audio_observed_);
4912 EXPECT_GE(received_packet_ids_.size(), kMinPacketsToWaitFor);
4913 }
4914
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004915 private:
4916 bool video_observed_;
4917 bool audio_observed_;
4918 SequenceNumberUnwrapper unwrapper_;
4919 std::set<int64_t> received_packet_ids_;
4920 } test;
4921
stefane74eef12016-01-08 06:47:13 -08004922 RunBaseTest(&test);
danilchap4336d732017-03-03 06:21:54 -08004923 // Double check conditions for successful test to produce better error
4924 // message when the test fail.
4925 test.ExpectSuccessful();
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004926}
palmkviste75f2042016-09-28 06:19:48 -07004927
4928class EndToEndLogTest : public EndToEndTest {
4929 void SetUp() { paths_.clear(); }
4930 void TearDown() {
4931 for (const auto& path : paths_) {
4932 rtc::RemoveFile(path);
4933 }
4934 }
4935
4936 public:
4937 int AddFile() {
4938 paths_.push_back(test::TempFilename(test::OutputPath(), "test_file"));
4939 return static_cast<int>(paths_.size()) - 1;
4940 }
4941
4942 rtc::PlatformFile OpenFile(int idx) {
4943 return rtc::OpenPlatformFile(paths_[idx]);
4944 }
4945
4946 void LogSend(bool open) {
4947 if (open) {
4948 video_send_stream_->EnableEncodedFrameRecording(
4949 std::vector<rtc::PlatformFile>(1, OpenFile(AddFile())), 0);
4950 } else {
4951 video_send_stream_->DisableEncodedFrameRecording();
4952 }
4953 }
4954 void LogReceive(bool open) {
4955 if (open) {
4956 video_receive_streams_[0]->EnableEncodedFrameRecording(
4957 OpenFile(AddFile()), 0);
4958 } else {
4959 video_receive_streams_[0]->DisableEncodedFrameRecording();
4960 }
4961 }
4962
4963 std::vector<std::string> paths_;
4964};
4965
philipel277a8b52017-03-16 05:19:49 -07004966TEST_F(EndToEndLogTest, LogsEncodedFramesWhenRequested) {
palmkviste75f2042016-09-28 06:19:48 -07004967 static const int kNumFramesToRecord = 10;
4968 class LogEncodingObserver : public test::EndToEndTest,
4969 public EncodedFrameObserver {
4970 public:
4971 explicit LogEncodingObserver(EndToEndLogTest* fixture)
4972 : EndToEndTest(kDefaultTimeoutMs),
4973 fixture_(fixture),
4974 recorded_frames_(0) {}
4975
4976 void PerformTest() override {
4977 fixture_->LogSend(true);
4978 fixture_->LogReceive(true);
4979 ASSERT_TRUE(Wait()) << "Timed out while waiting for frame logging.";
4980 }
4981
4982 void ModifyVideoConfigs(
4983 VideoSendStream::Config* send_config,
4984 std::vector<VideoReceiveStream::Config>* receive_configs,
4985 VideoEncoderConfig* encoder_config) override {
magjed509e4fe2016-11-18 01:34:11 -08004986 encoder_.reset(VP8Encoder::Create());
palmkviste75f2042016-09-28 06:19:48 -07004987 decoder_.reset(VP8Decoder::Create());
4988
4989 send_config->post_encode_callback = this;
4990 send_config->encoder_settings.payload_name = "VP8";
4991 send_config->encoder_settings.encoder = encoder_.get();
4992
4993 (*receive_configs)[0].decoders.resize(1);
4994 (*receive_configs)[0].decoders[0].payload_type =
4995 send_config->encoder_settings.payload_type;
4996 (*receive_configs)[0].decoders[0].payload_name =
4997 send_config->encoder_settings.payload_name;
4998 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
4999 }
5000
5001 void EncodedFrameCallback(const EncodedFrame& encoded_frame) override {
5002 rtc::CritScope lock(&crit_);
5003 if (recorded_frames_++ > kNumFramesToRecord) {
5004 fixture_->LogSend(false);
5005 fixture_->LogReceive(false);
5006 rtc::File send_file(fixture_->OpenFile(0));
5007 rtc::File receive_file(fixture_->OpenFile(1));
5008 uint8_t out[100];
5009 // If logging has worked correctly neither file should be empty, i.e.
5010 // we should be able to read something from them.
5011 EXPECT_LT(0u, send_file.Read(out, 100));
5012 EXPECT_LT(0u, receive_file.Read(out, 100));
5013 observation_complete_.Set();
5014 }
5015 }
5016
5017 private:
5018 EndToEndLogTest* const fixture_;
5019 std::unique_ptr<VideoEncoder> encoder_;
5020 std::unique_ptr<VideoDecoder> decoder_;
5021 rtc::CriticalSection crit_;
danilchapa37de392017-09-09 04:17:22 -07005022 int recorded_frames_ RTC_GUARDED_BY(crit_);
palmkviste75f2042016-09-28 06:19:48 -07005023 } test(this);
5024
5025 RunBaseTest(&test);
5026}
5027
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00005028} // namespace webrtc