blob: 2ae3ceefbc2f6190508e7df2e8a8befcb7878648 [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);
2320 rtp_rtcp_->SetREMBStatus(true);
stefan32f81542016-01-20 07:13:58 -08002321 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
2322 }
2323
2324 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2325 sender_call_ = sender_call;
2326 }
2327
tommi0f8b4032017-02-22 11:22:05 -08002328 static void BitrateStatsPollingThread(void* obj) {
2329 static_cast<BweObserver*>(obj)->PollStats();
stefan32f81542016-01-20 07:13:58 -08002330 }
2331
tommi0f8b4032017-02-22 11:22:05 -08002332 void PollStats() {
2333 do {
2334 if (sender_call_) {
2335 Call::Stats stats = sender_call_->GetStats();
2336 switch (state_) {
2337 case kWaitForFirstRampUp:
2338 if (stats.send_bandwidth_bps >= remb_bitrate_bps_) {
2339 state_ = kWaitForRemb;
2340 remb_bitrate_bps_ /= 2;
2341 rtp_rtcp_->SetREMBData(
2342 remb_bitrate_bps_,
2343 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
2344 rtp_rtcp_->SendRTCP(kRtcpRr);
2345 }
2346 break;
stefan32f81542016-01-20 07:13:58 -08002347
tommi0f8b4032017-02-22 11:22:05 -08002348 case kWaitForRemb:
2349 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
2350 state_ = kWaitForSecondRampUp;
2351 remb_bitrate_bps_ *= 2;
2352 rtp_rtcp_->SetREMBData(
2353 remb_bitrate_bps_,
2354 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
2355 rtp_rtcp_->SendRTCP(kRtcpRr);
2356 }
2357 break;
stefan32f81542016-01-20 07:13:58 -08002358
tommi0f8b4032017-02-22 11:22:05 -08002359 case kWaitForSecondRampUp:
2360 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
2361 observation_complete_.Set();
2362 }
2363 break;
2364 }
stefan32f81542016-01-20 07:13:58 -08002365 }
tommi0f8b4032017-02-22 11:22:05 -08002366 } while (!stop_event_.Wait(1000));
stefan32f81542016-01-20 07:13:58 -08002367 }
2368
2369 void PerformTest() override {
2370 poller_thread_.Start();
2371 EXPECT_TRUE(Wait())
2372 << "Timed out while waiting for bitrate to change according to REMB.";
Tommi5dd5f5a2017-02-21 14:22:59 +01002373 stop_event_.Set();
stefan32f81542016-01-20 07:13:58 -08002374 poller_thread_.Stop();
2375 }
2376
2377 private:
2378 enum TestState { kWaitForFirstRampUp, kWaitForRemb, kWaitForSecondRampUp };
2379
2380 Call* sender_call_;
2381 Clock* const clock_;
2382 uint32_t sender_ssrc_;
2383 int remb_bitrate_bps_;
kwiberg27f982b2016-03-01 11:52:33 -08002384 std::unique_ptr<RtpRtcp> rtp_rtcp_;
stefan32f81542016-01-20 07:13:58 -08002385 test::PacketTransport* receive_transport_;
Tommi5dd5f5a2017-02-21 14:22:59 +01002386 rtc::Event stop_event_;
stefan32f81542016-01-20 07:13:58 -08002387 rtc::PlatformThread poller_thread_;
2388 TestState state_;
Erik Språng737336d2016-07-29 12:59:36 +02002389 RateLimiter retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08002390 } test;
2391
2392 RunBaseTest(&test);
2393}
2394
philipel3184f8e2017-05-18 08:08:53 -07002395TEST_F(EndToEndTest, StopSendingKeyframeRequestsForInactiveStream) {
2396 class KeyframeRequestObserver : public test::EndToEndTest {
2397 public:
eladalon413ee9a2017-08-22 04:02:52 -07002398 explicit KeyframeRequestObserver(
2399 test::SingleThreadedTaskQueueForTesting* task_queue)
2400 : clock_(Clock::GetRealTimeClock()), task_queue_(task_queue) {}
philipel3184f8e2017-05-18 08:08:53 -07002401
2402 void OnVideoStreamsCreated(
2403 VideoSendStream* send_stream,
2404 const std::vector<VideoReceiveStream*>& receive_streams) override {
2405 RTC_DCHECK_EQ(1, receive_streams.size());
2406 send_stream_ = send_stream;
2407 receive_stream_ = receive_streams[0];
2408 }
2409
2410 void PerformTest() override {
2411 bool frame_decoded = false;
2412 int64_t start_time = clock_->TimeInMilliseconds();
2413 while (clock_->TimeInMilliseconds() - start_time <= 5000) {
2414 if (receive_stream_->GetStats().frames_decoded > 0) {
2415 frame_decoded = true;
2416 break;
2417 }
2418 SleepMs(100);
2419 }
2420 ASSERT_TRUE(frame_decoded);
eladalon413ee9a2017-08-22 04:02:52 -07002421 task_queue_->SendTask([this]() { send_stream_->Stop(); });
philipel3184f8e2017-05-18 08:08:53 -07002422 SleepMs(10000);
2423 ASSERT_EQ(
2424 1U, receive_stream_->GetStats().rtcp_packet_type_counts.pli_packets);
2425 }
2426
2427 private:
2428 Clock* clock_;
2429 VideoSendStream* send_stream_;
2430 VideoReceiveStream* receive_stream_;
eladalon413ee9a2017-08-22 04:02:52 -07002431 test::SingleThreadedTaskQueueForTesting* const task_queue_;
2432 } test(&task_queue_);
philipel3184f8e2017-05-18 08:08:53 -07002433
2434 RunBaseTest(&test);
2435}
2436
philipele828c962017-03-21 03:24:27 -07002437class ProbingTest : public test::EndToEndTest {
2438 public:
2439 explicit ProbingTest(int start_bitrate_bps)
2440 : clock_(Clock::GetRealTimeClock()),
2441 start_bitrate_bps_(start_bitrate_bps),
2442 state_(0),
2443 sender_call_(nullptr) {}
2444
2445 ~ProbingTest() {}
2446
2447 Call::Config GetSenderCallConfig() override {
philipel4fb651d2017-04-10 03:54:05 -07002448 Call::Config config(event_log_.get());
philipele828c962017-03-21 03:24:27 -07002449 config.bitrate_config.start_bitrate_bps = start_bitrate_bps_;
2450 return config;
2451 }
2452
2453 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2454 sender_call_ = sender_call;
2455 }
2456
2457 protected:
2458 Clock* const clock_;
2459 const int start_bitrate_bps_;
2460 int state_;
2461 Call* sender_call_;
2462};
2463
aleloi7057b6b2017-03-29 02:07:33 -07002464TEST_F(EndToEndTest, MAYBE_InitialProbing) {
philipele828c962017-03-21 03:24:27 -07002465 class InitialProbingTest : public ProbingTest {
2466 public:
philipel8a256522017-03-30 05:06:22 -07002467 explicit InitialProbingTest(bool* success)
eladaloncf038f72017-08-10 10:42:53 -07002468 : ProbingTest(300000), success_(success) {
2469 *success_ = false;
2470 }
philipele828c962017-03-21 03:24:27 -07002471
2472 void PerformTest() override {
2473 int64_t start_time_ms = clock_->TimeInMilliseconds();
2474 do {
philipel8a256522017-03-30 05:06:22 -07002475 if (clock_->TimeInMilliseconds() - start_time_ms > kTimeoutMs)
philipele828c962017-03-21 03:24:27 -07002476 break;
philipele828c962017-03-21 03:24:27 -07002477
2478 Call::Stats stats = sender_call_->GetStats();
2479 // Initial probing is done with a x3 and x6 multiplier of the start
2480 // bitrate, so a x4 multiplier is a high enough threshold.
philipel8a256522017-03-30 05:06:22 -07002481 if (stats.send_bandwidth_bps > 4 * 300000) {
2482 *success_ = true;
philipele828c962017-03-21 03:24:27 -07002483 break;
philipel8a256522017-03-30 05:06:22 -07002484 }
philipele828c962017-03-21 03:24:27 -07002485 } while (!observation_complete_.Wait(20));
2486 }
2487
2488 private:
2489 const int kTimeoutMs = 1000;
philipel8a256522017-03-30 05:06:22 -07002490 bool* const success_;
2491 };
philipele828c962017-03-21 03:24:27 -07002492
eladaloncf038f72017-08-10 10:42:53 -07002493 bool success = false;
philipel8a256522017-03-30 05:06:22 -07002494 const int kMaxAttempts = 3;
2495 for (int i = 0; i < kMaxAttempts; ++i) {
2496 InitialProbingTest test(&success);
2497 RunBaseTest(&test);
2498 if (success)
2499 return;
2500 }
eladaloncf038f72017-08-10 10:42:53 -07002501 EXPECT_TRUE(success) << "Failed to perform mid initial probing ("
2502 << kMaxAttempts << " attempts).";
philipele828c962017-03-21 03:24:27 -07002503}
2504
aleloi18703f92017-03-30 04:24:08 -07002505// Fails on Linux MSan: bugs.webrtc.org/7428
2506#if defined(MEMORY_SANITIZER)
2507TEST_F(EndToEndTest, DISABLED_TriggerMidCallProbing) {
oprypin45197522017-06-22 01:47:20 -07002508// Fails on iOS bots: bugs.webrtc.org/7851
2509#elif defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR
2510TEST_F(EndToEndTest, DISABLED_TriggerMidCallProbing) {
aleloi18703f92017-03-30 04:24:08 -07002511#else
philipele828c962017-03-21 03:24:27 -07002512TEST_F(EndToEndTest, TriggerMidCallProbing) {
aleloi18703f92017-03-30 04:24:08 -07002513#endif
2514
philipele828c962017-03-21 03:24:27 -07002515 class TriggerMidCallProbingTest : public ProbingTest {
2516 public:
eladalon413ee9a2017-08-22 04:02:52 -07002517 TriggerMidCallProbingTest(
2518 test::SingleThreadedTaskQueueForTesting* task_queue,
2519 bool* success)
2520 : ProbingTest(300000), success_(success), task_queue_(task_queue) {}
philipele828c962017-03-21 03:24:27 -07002521
2522 void PerformTest() override {
philipel8a256522017-03-30 05:06:22 -07002523 *success_ = false;
philipele828c962017-03-21 03:24:27 -07002524 int64_t start_time_ms = clock_->TimeInMilliseconds();
2525 do {
philipel8a256522017-03-30 05:06:22 -07002526 if (clock_->TimeInMilliseconds() - start_time_ms > kTimeoutMs)
philipele828c962017-03-21 03:24:27 -07002527 break;
philipele828c962017-03-21 03:24:27 -07002528
2529 Call::Stats stats = sender_call_->GetStats();
2530
2531 switch (state_) {
2532 case 0:
2533 if (stats.send_bandwidth_bps > 5 * 300000) {
2534 Call::Config::BitrateConfig bitrate_config;
2535 bitrate_config.max_bitrate_bps = 100000;
eladalon413ee9a2017-08-22 04:02:52 -07002536 task_queue_->SendTask([this, &bitrate_config]() {
2537 sender_call_->SetBitrateConfig(bitrate_config);
2538 });
philipele828c962017-03-21 03:24:27 -07002539 ++state_;
2540 }
2541 break;
2542 case 1:
2543 if (stats.send_bandwidth_bps < 110000) {
2544 Call::Config::BitrateConfig bitrate_config;
2545 bitrate_config.max_bitrate_bps = 2500000;
eladalon413ee9a2017-08-22 04:02:52 -07002546 task_queue_->SendTask([this, &bitrate_config]() {
2547 sender_call_->SetBitrateConfig(bitrate_config);
2548 });
philipele828c962017-03-21 03:24:27 -07002549 ++state_;
2550 }
2551 break;
2552 case 2:
2553 // During high cpu load the pacer will not be able to pace packets
2554 // at the correct speed, but if we go from 110 to 1250 kbps
2555 // in 5 seconds then it is due to probing.
philipel8a256522017-03-30 05:06:22 -07002556 if (stats.send_bandwidth_bps > 1250000) {
2557 *success_ = true;
philipele828c962017-03-21 03:24:27 -07002558 observation_complete_.Set();
philipel8a256522017-03-30 05:06:22 -07002559 }
philipele828c962017-03-21 03:24:27 -07002560 break;
2561 }
2562 } while (!observation_complete_.Wait(20));
2563 }
2564
2565 private:
2566 const int kTimeoutMs = 5000;
philipel8a256522017-03-30 05:06:22 -07002567 bool* const success_;
eladalon413ee9a2017-08-22 04:02:52 -07002568 test::SingleThreadedTaskQueueForTesting* const task_queue_;
philipel8a256522017-03-30 05:06:22 -07002569 };
philipele828c962017-03-21 03:24:27 -07002570
eladaloncf038f72017-08-10 10:42:53 -07002571 bool success = false;
philipel8a256522017-03-30 05:06:22 -07002572 const int kMaxAttempts = 3;
2573 for (int i = 0; i < kMaxAttempts; ++i) {
eladalon413ee9a2017-08-22 04:02:52 -07002574 TriggerMidCallProbingTest test(&task_queue_, &success);
philipel8a256522017-03-30 05:06:22 -07002575 RunBaseTest(&test);
2576 if (success)
2577 return;
2578 }
stefan9e117c5e12017-08-16 08:16:25 -07002579 EXPECT_TRUE(success) << "Failed to perform mid call probing (" << kMaxAttempts
2580 << " attempts).";
philipele828c962017-03-21 03:24:27 -07002581}
2582
philipel277a8b52017-03-16 05:19:49 -07002583TEST_F(EndToEndTest, VerifyNackStats) {
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002584 static const int kPacketNumberToDrop = 200;
2585 class NackObserver : public test::EndToEndTest {
2586 public:
2587 NackObserver()
2588 : EndToEndTest(kLongTimeoutMs),
2589 sent_rtp_packets_(0),
2590 dropped_rtp_packet_(0),
2591 dropped_rtp_packet_requested_(false),
2592 send_stream_(nullptr),
2593 start_runtime_ms_(-1) {}
2594
2595 private:
2596 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002597 rtc::CritScope lock(&crit_);
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002598 if (++sent_rtp_packets_ == kPacketNumberToDrop) {
kwiberg27f982b2016-03-01 11:52:33 -08002599 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002600 RTPHeader header;
2601 EXPECT_TRUE(parser->Parse(packet, length, &header));
2602 dropped_rtp_packet_ = header.sequenceNumber;
2603 return DROP_PACKET;
2604 }
2605 VerifyStats();
2606 return SEND_PACKET;
2607 }
2608
2609 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002610 rtc::CritScope lock(&crit_);
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002611 test::RtcpPacketParser rtcp_parser;
2612 rtcp_parser.Parse(packet, length);
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02002613 const std::vector<uint16_t>& nacks = rtcp_parser.nack()->packet_ids();
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002614 if (!nacks.empty() && std::find(
2615 nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) {
2616 dropped_rtp_packet_requested_ = true;
2617 }
2618 return SEND_PACKET;
2619 }
2620
danilchapa37de392017-09-09 04:17:22 -07002621 void VerifyStats() RTC_EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002622 if (!dropped_rtp_packet_requested_)
2623 return;
2624 int send_stream_nack_packets = 0;
2625 int receive_stream_nack_packets = 0;
2626 VideoSendStream::Stats stats = send_stream_->GetStats();
2627 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
2628 stats.substreams.begin(); it != stats.substreams.end(); ++it) {
2629 const VideoSendStream::StreamStats& stream_stats = it->second;
2630 send_stream_nack_packets +=
2631 stream_stats.rtcp_packet_type_counts.nack_packets;
2632 }
2633 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2634 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2635 receive_stream_nack_packets +=
2636 stats.rtcp_packet_type_counts.nack_packets;
2637 }
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002638 if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) {
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002639 // NACK packet sent on receive stream and received on sent stream.
2640 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002641 observation_complete_.Set();
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002642 }
2643 }
2644
2645 bool MinMetricRunTimePassed() {
2646 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2647 if (start_runtime_ms_ == -1) {
2648 start_runtime_ms_ = now;
2649 return false;
2650 }
2651 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2652 return elapsed_sec > metrics::kMinRunTimeInSeconds;
2653 }
2654
stefanff483612015-12-21 03:14:00 -08002655 void ModifyVideoConfigs(
2656 VideoSendStream::Config* send_config,
2657 std::vector<VideoReceiveStream::Config>* receive_configs,
2658 VideoEncoderConfig* encoder_config) override {
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002659 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2660 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sakal55d932b2016-09-30 06:19:08 -07002661 (*receive_configs)[0].renderer = &fake_renderer_;
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002662 }
2663
stefanff483612015-12-21 03:14:00 -08002664 void OnVideoStreamsCreated(
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002665 VideoSendStream* send_stream,
2666 const std::vector<VideoReceiveStream*>& receive_streams) override {
2667 send_stream_ = send_stream;
2668 receive_streams_ = receive_streams;
2669 }
2670
2671 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002672 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002673 }
2674
sakal55d932b2016-09-30 06:19:08 -07002675 test::FakeVideoRenderer fake_renderer_;
stefan608213e2015-11-01 14:56:10 -08002676 rtc::CriticalSection crit_;
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002677 uint64_t sent_rtp_packets_;
danilchapa37de392017-09-09 04:17:22 -07002678 uint16_t dropped_rtp_packet_ RTC_GUARDED_BY(&crit_);
2679 bool dropped_rtp_packet_requested_ RTC_GUARDED_BY(&crit_);
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002680 std::vector<VideoReceiveStream*> receive_streams_;
2681 VideoSendStream* send_stream_;
2682 int64_t start_runtime_ms_;
2683 } test;
2684
asapersson01d70a32016-05-20 06:29:46 -07002685 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002686 RunBaseTest(&test);
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002687
asapersson01d70a32016-05-20 06:29:46 -07002688 EXPECT_EQ(
2689 1, metrics::NumSamples("WebRTC.Video.UniqueNackRequestsSentInPercent"));
2690 EXPECT_EQ(1, metrics::NumSamples(
2691 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
2692 EXPECT_GT(metrics::MinSample("WebRTC.Video.NackPacketsSentPerMinute"), 0);
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002693}
2694
sprangb4a1ae52015-12-03 08:10:08 -08002695void EndToEndTest::VerifyHistogramStats(bool use_rtx,
nisse3b3622f2017-09-26 02:49:21 -07002696 bool use_fec,
sprangb4a1ae52015-12-03 08:10:08 -08002697 bool screenshare) {
tommi2e82f382016-06-21 00:26:43 -07002698 class StatsObserver : public test::EndToEndTest,
2699 public rtc::VideoSinkInterface<VideoFrame> {
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002700 public:
nisse3b3622f2017-09-26 02:49:21 -07002701 StatsObserver(bool use_rtx, bool use_fec, bool screenshare)
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002702 : EndToEndTest(kLongTimeoutMs),
2703 use_rtx_(use_rtx),
nisse3b3622f2017-09-26 02:49:21 -07002704 use_fec_(use_fec),
sprangb4a1ae52015-12-03 08:10:08 -08002705 screenshare_(screenshare),
Peter Boström39593972016-02-15 11:27:15 +01002706 // This test uses NACK, so to send FEC we can't use a fake encoder.
nisse3b3622f2017-09-26 02:49:21 -07002707 vp8_encoder_(use_fec ? VP8Encoder::Create() : nullptr),
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002708 sender_call_(nullptr),
2709 receiver_call_(nullptr),
asapersson1394c7b2016-10-18 11:50:50 -07002710 start_runtime_ms_(-1),
2711 num_frames_received_(0) {}
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002712
2713 private:
asapersson1394c7b2016-10-18 11:50:50 -07002714 void OnFrame(const VideoFrame& video_frame) override {
2715 // The RTT is needed to estimate |ntp_time_ms| which is used by
2716 // end-to-end delay stats. Therefore, start counting received frames once
2717 // |ntp_time_ms| is valid.
2718 if (video_frame.ntp_time_ms() > 0 &&
2719 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() >=
2720 video_frame.ntp_time_ms()) {
2721 rtc::CritScope lock(&crit_);
2722 ++num_frames_received_;
2723 }
2724 }
tommi2e82f382016-06-21 00:26:43 -07002725
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002726 Action OnSendRtp(const uint8_t* packet, size_t length) override {
asapersson1394c7b2016-10-18 11:50:50 -07002727 if (MinMetricRunTimePassed() && MinNumberOfFramesReceived())
Peter Boström5811a392015-12-10 13:02:50 +01002728 observation_complete_.Set();
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002729
stefanf116bd02015-10-27 08:29:42 -07002730 return SEND_PACKET;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002731 }
2732
2733 bool MinMetricRunTimePassed() {
2734 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2735 if (start_runtime_ms_ == -1) {
2736 start_runtime_ms_ = now;
2737 return false;
2738 }
2739 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2740 return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
2741 }
2742
asapersson1394c7b2016-10-18 11:50:50 -07002743 bool MinNumberOfFramesReceived() const {
2744 const int kMinRequiredHistogramSamples = 200;
2745 rtc::CritScope lock(&crit_);
2746 return num_frames_received_ > kMinRequiredHistogramSamples;
2747 }
2748
stefanff483612015-12-21 03:14:00 -08002749 void ModifyVideoConfigs(
2750 VideoSendStream::Config* send_config,
2751 std::vector<VideoReceiveStream::Config>* receive_configs,
2752 VideoEncoderConfig* encoder_config) override {
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002753 // NACK
2754 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2755 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
tommi2e82f382016-06-21 00:26:43 -07002756 (*receive_configs)[0].renderer = this;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002757 // FEC
nisse3b3622f2017-09-26 02:49:21 -07002758 if (use_fec_) {
brandtrb5f2c3f2016-10-04 23:28:39 -07002759 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
2760 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
Peter Boström39593972016-02-15 11:27:15 +01002761 send_config->encoder_settings.encoder = vp8_encoder_.get();
2762 send_config->encoder_settings.payload_name = "VP8";
2763 (*receive_configs)[0].decoders[0].payload_name = "VP8";
nisse3b3622f2017-09-26 02:49:21 -07002764 (*receive_configs)[0].rtp.red_payload_type = kRedPayloadType;
2765 (*receive_configs)[0].rtp.ulpfec_payload_type = kUlpfecPayloadType;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002766 }
2767 // RTX
2768 if (use_rtx_) {
2769 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
2770 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
brandtr14742122017-01-27 04:53:07 -08002771 (*receive_configs)[0].rtp.rtx_ssrc = kSendRtxSsrcs[0];
nisse26e3abb2017-08-25 04:44:25 -07002772 (*receive_configs)[0]
2773 .rtp.rtx_associated_payload_types[kSendRtxPayloadType] =
2774 kFakeVideoSendPayloadType;
nisse3b3622f2017-09-26 02:49:21 -07002775 if (use_fec_) {
2776 send_config->rtp.ulpfec.red_rtx_payload_type = kRtxRedPayloadType;
2777 (*receive_configs)[0]
2778 .rtp.rtx_associated_payload_types[kRtxRedPayloadType] =
2779 kSendRtxPayloadType;
2780 }
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002781 }
asapersson1490f7a2016-09-23 02:09:46 -07002782 // RTT needed for RemoteNtpTimeEstimator for the receive stream.
2783 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = true;
sprangb4a1ae52015-12-03 08:10:08 -08002784 encoder_config->content_type =
2785 screenshare_ ? VideoEncoderConfig::ContentType::kScreen
2786 : VideoEncoderConfig::ContentType::kRealtimeVideo;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002787 }
2788
2789 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2790 sender_call_ = sender_call;
2791 receiver_call_ = receiver_call;
2792 }
2793
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002794 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002795 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002796 }
2797
asapersson1394c7b2016-10-18 11:50:50 -07002798 rtc::CriticalSection crit_;
sprangb4a1ae52015-12-03 08:10:08 -08002799 const bool use_rtx_;
nisse3b3622f2017-09-26 02:49:21 -07002800 const bool use_fec_;
sprangb4a1ae52015-12-03 08:10:08 -08002801 const bool screenshare_;
kwiberg27f982b2016-03-01 11:52:33 -08002802 const std::unique_ptr<VideoEncoder> vp8_encoder_;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002803 Call* sender_call_;
2804 Call* receiver_call_;
2805 int64_t start_runtime_ms_;
danilchapa37de392017-09-09 04:17:22 -07002806 int num_frames_received_ RTC_GUARDED_BY(&crit_);
nisse3b3622f2017-09-26 02:49:21 -07002807 } test(use_rtx, use_fec, screenshare);
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002808
asapersson01d70a32016-05-20 06:29:46 -07002809 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002810 RunBaseTest(&test);
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002811
sprangb4a1ae52015-12-03 08:10:08 -08002812 std::string video_prefix =
2813 screenshare ? "WebRTC.Video.Screenshare." : "WebRTC.Video.";
ilnik6d5b4d62017-08-30 03:32:14 -07002814 // The content type extension is disabled in non screenshare test,
2815 // therefore no slicing on simulcast id should be present.
2816 std::string video_suffix = screenshare ? ".S0" : "";
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002817 // Verify that stats have been updated once.
asapersson4374a092016-07-27 00:39:09 -07002818 EXPECT_EQ(2, metrics::NumSamples("WebRTC.Call.LifetimeInSeconds"));
saza0d7f04d2017-07-04 04:05:06 -07002819 EXPECT_EQ(1, metrics::NumSamples(
2820 "WebRTC.Call.TimeReceivingVideoRtpPacketsInSeconds"));
asapersson01d70a32016-05-20 06:29:46 -07002821 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
2822 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.RtcpBitrateReceivedInBps"));
2823 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.BitrateReceivedInKbps"));
2824 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.EstimatedSendBitrateInKbps"));
2825 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.PacerBitrateInKbps"));
2826
asapersson4374a092016-07-27 00:39:09 -07002827 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
2828 EXPECT_EQ(1,
2829 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
2830
asapersson01d70a32016-05-20 06:29:46 -07002831 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
stefan91d92602015-11-11 10:13:02 -08002832 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002833 metrics::NumSamples(video_prefix + "NackPacketsReceivedPerMinute"));
2834 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
asaperssond89920b2015-07-22 06:52:00 -07002835 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002836 metrics::NumSamples(video_prefix + "FirPacketsReceivedPerMinute"));
2837 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
sprangb4a1ae52015-12-03 08:10:08 -08002838 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002839 metrics::NumSamples(video_prefix + "PliPacketsReceivedPerMinute"));
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002840
asapersson01d70a32016-05-20 06:29:46 -07002841 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "KeyFramesSentInPermille"));
2842 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
2843
2844 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentPacketsLostInPercent"));
2845 EXPECT_EQ(1,
2846 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
2847
2848 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputWidthInPixels"));
2849 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputHeightInPixels"));
2850 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentWidthInPixels"));
2851 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentHeightInPixels"));
ilnik6d5b4d62017-08-30 03:32:14 -07002852 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "ReceivedWidthInPixels"));
2853 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "ReceivedHeightInPixels"));
asapersson01d70a32016-05-20 06:29:46 -07002854
perkjfa10b552016-10-02 23:45:26 -07002855 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputWidthInPixels",
2856 kDefaultWidth));
2857 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputHeightInPixels",
2858 kDefaultHeight));
2859 EXPECT_EQ(
2860 1, metrics::NumEvents(video_prefix + "SentWidthInPixels", kDefaultWidth));
2861 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "SentHeightInPixels",
2862 kDefaultHeight));
ilnik6d5b4d62017-08-30 03:32:14 -07002863 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "ReceivedWidthInPixels",
perkjfa10b552016-10-02 23:45:26 -07002864 kDefaultWidth));
ilnik6d5b4d62017-08-30 03:32:14 -07002865 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "ReceivedHeightInPixels",
perkjfa10b552016-10-02 23:45:26 -07002866 kDefaultHeight));
asapersson01d70a32016-05-20 06:29:46 -07002867
2868 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputFramesPerSecond"));
2869 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentFramesPerSecond"));
2870 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
2871 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
2872
2873 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
2874 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
2875 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
2876 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
2877
ilnik6d5b4d62017-08-30 03:32:14 -07002878 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EndToEndDelayInMs" +
2879 video_suffix));
2880 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EndToEndDelayMaxInMs" +
2881 video_suffix));
2882 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InterframeDelayInMs" +
2883 video_suffix));
2884 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InterframeDelayMaxInMs" +
2885 video_suffix));
ilnik4257ab22017-07-03 01:15:58 -07002886
asapersson01d70a32016-05-20 06:29:46 -07002887 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
2888
2889 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EncodeTimeInMs"));
2890 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
2891
asapersson66d4b372016-12-19 06:50:53 -08002892 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "NumberOfPauseEvents"));
2893 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PausedTimeInPercent"));
2894
asapersson01d70a32016-05-20 06:29:46 -07002895 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "BitrateSentInKbps"));
2896 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateReceivedInKbps"));
2897 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "MediaBitrateSentInKbps"));
2898 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateReceivedInKbps"));
2899 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PaddingBitrateSentInKbps"));
2900 EXPECT_EQ(1,
2901 metrics::NumSamples("WebRTC.Video.PaddingBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002902 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002903 1, metrics::NumSamples(video_prefix + "RetransmittedBitrateSentInKbps"));
2904 EXPECT_EQ(1, metrics::NumSamples(
2905 "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002906
asapersson01d70a32016-05-20 06:29:46 -07002907 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendDelayInMs"));
2908 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayInMs"));
2909 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayMaxInMs"));
asapersson6f14be82015-11-16 00:40:49 -08002910
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002911 int num_rtx_samples = use_rtx ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002912 EXPECT_EQ(num_rtx_samples,
2913 metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2914 EXPECT_EQ(num_rtx_samples,
2915 metrics::NumSamples("WebRTC.Video.RtxBitrateReceivedInKbps"));
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002916
nisse3b3622f2017-09-26 02:49:21 -07002917 int num_red_samples = use_fec ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002918 EXPECT_EQ(num_red_samples,
2919 metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2920 EXPECT_EQ(num_red_samples,
2921 metrics::NumSamples("WebRTC.Video.FecBitrateReceivedInKbps"));
2922 EXPECT_EQ(num_red_samples,
2923 metrics::NumSamples("WebRTC.Video.ReceivedFecPacketsInPercent"));
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002924}
2925
Lu Liufb9e7512017-04-13 14:09:56 -07002926#if defined(WEBRTC_WIN)
2927// Disabled due to flakiness on Windows (bugs.webrtc.org/7483).
2928#define MAYBE_ContentTypeSwitches DISABLED_ContentTypeSwitches
2929#else
2930#define MAYBE_ContentTypeSwitches ContentTypeSwitches
2931#endif
2932TEST_F(EndToEndTest, MAYBE_ContentTypeSwitches) {
ilnik00d802b2017-04-11 10:34:31 -07002933 class StatsObserver : public test::BaseTest,
2934 public rtc::VideoSinkInterface<VideoFrame> {
2935 public:
2936 StatsObserver() : BaseTest(kLongTimeoutMs), num_frames_received_(0) {}
2937
2938 bool ShouldCreateReceivers() const override { return true; }
2939
2940 void OnFrame(const VideoFrame& video_frame) override {
2941 // The RTT is needed to estimate |ntp_time_ms| which is used by
2942 // end-to-end delay stats. Therefore, start counting received frames once
2943 // |ntp_time_ms| is valid.
2944 if (video_frame.ntp_time_ms() > 0 &&
2945 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() >=
2946 video_frame.ntp_time_ms()) {
2947 rtc::CritScope lock(&crit_);
2948 ++num_frames_received_;
2949 }
2950 }
2951
2952 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2953 if (MinNumberOfFramesReceived())
2954 observation_complete_.Set();
2955 return SEND_PACKET;
2956 }
2957
2958 bool MinNumberOfFramesReceived() const {
ilnikf6f808f2017-04-18 09:17:53 -07002959 // Have some room for frames with wrong content type during switch.
2960 const int kMinRequiredHistogramSamples = 200+50;
ilnik00d802b2017-04-11 10:34:31 -07002961 rtc::CritScope lock(&crit_);
2962 return num_frames_received_ > kMinRequiredHistogramSamples;
2963 }
2964
2965 // May be called several times.
2966 void PerformTest() override {
2967 EXPECT_TRUE(Wait()) << "Timed out waiting for enough packets.";
2968 // Reset frame counter so next PerformTest() call will do something.
2969 {
2970 rtc::CritScope lock(&crit_);
2971 num_frames_received_ = 0;
2972 }
2973 }
2974
2975 rtc::CriticalSection crit_;
danilchapa37de392017-09-09 04:17:22 -07002976 int num_frames_received_ RTC_GUARDED_BY(&crit_);
ilnik00d802b2017-04-11 10:34:31 -07002977 } test;
2978
2979 metrics::Reset();
2980
2981 Call::Config send_config(test.GetSenderCallConfig());
ilnik00d802b2017-04-11 10:34:31 -07002982 Call::Config recv_config(test.GetReceiverCallConfig());
eladalon413ee9a2017-08-22 04:02:52 -07002983 VideoEncoderConfig encoder_config_with_screenshare;
ilnik00d802b2017-04-11 10:34:31 -07002984
ilnik41cadbc2017-08-23 00:44:27 -07002985 task_queue_.SendTask([this, &test, &send_config,
eladalon413ee9a2017-08-22 04:02:52 -07002986 &recv_config, &encoder_config_with_screenshare]() {
2987 CreateSenderCall(send_config);
2988 CreateReceiverCall(recv_config);
ilnik00d802b2017-04-11 10:34:31 -07002989
eladalon413ee9a2017-08-22 04:02:52 -07002990 receive_transport_.reset(test.CreateReceiveTransport(&task_queue_));
2991 send_transport_.reset(
2992 test.CreateSendTransport(&task_queue_, sender_call_.get()));
2993 send_transport_->SetReceiver(receiver_call_->Receiver());
2994 receive_transport_->SetReceiver(sender_call_->Receiver());
2995
2996 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
2997 CreateSendConfig(1, 0, 0, send_transport_.get());
2998 CreateMatchingReceiveConfigs(receive_transport_.get());
2999
3000 // Modify send and receive configs.
3001 video_send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
3002 video_receive_configs_[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
3003 video_receive_configs_[0].renderer = &test;
3004 // RTT needed for RemoteNtpTimeEstimator for the receive stream.
3005 video_receive_configs_[0].rtp.rtcp_xr.receiver_reference_time_report = true;
3006 // Start with realtime video.
3007 video_encoder_config_.content_type =
3008 VideoEncoderConfig::ContentType::kRealtimeVideo;
3009 // Second encoder config for the second part of the test uses screenshare
3010 encoder_config_with_screenshare = video_encoder_config_.Copy();
3011 encoder_config_with_screenshare.content_type =
3012 VideoEncoderConfig::ContentType::kScreen;
3013
3014 CreateVideoStreams();
3015 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
3016 kDefaultHeight);
3017 Start();
3018 });
ilnik00d802b2017-04-11 10:34:31 -07003019
3020 test.PerformTest();
3021
3022 // Replace old send stream.
eladalon413ee9a2017-08-22 04:02:52 -07003023 task_queue_.SendTask([this, &encoder_config_with_screenshare]() {
3024 sender_call_->DestroyVideoSendStream(video_send_stream_);
3025 video_send_stream_ = sender_call_->CreateVideoSendStream(
3026 video_send_config_.Copy(), encoder_config_with_screenshare.Copy());
3027 video_send_stream_->SetSource(
3028 frame_generator_capturer_.get(),
3029 VideoSendStream::DegradationPreference::kBalanced);
3030 video_send_stream_->Start();
3031 });
ilnik00d802b2017-04-11 10:34:31 -07003032
3033 // Continue to run test but now with screenshare.
3034 test.PerformTest();
3035
eladalon413ee9a2017-08-22 04:02:52 -07003036 task_queue_.SendTask([this]() {
3037 Stop();
3038 DestroyStreams();
3039 send_transport_.reset();
3040 receive_transport_.reset();
3041 DestroyCalls();
3042 });
ilnik00d802b2017-04-11 10:34:31 -07003043
3044 // Verify that stats have been updated for both screenshare and video.
3045 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.EndToEndDelayInMs"));
3046 EXPECT_EQ(1,
3047 metrics::NumSamples("WebRTC.Video.Screenshare.EndToEndDelayInMs"));
3048 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.EndToEndDelayMaxInMs"));
3049 EXPECT_EQ(
3050 1, metrics::NumSamples("WebRTC.Video.Screenshare.EndToEndDelayMaxInMs"));
ilnik4257ab22017-07-03 01:15:58 -07003051 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
3052 EXPECT_EQ(1,
3053 metrics::NumSamples(
3054 "WebRTC.Video.Screenshare.InterframeDelayInMs"));
3055 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
3056 EXPECT_EQ(1,
3057 metrics::NumSamples(
3058 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
ilnik00d802b2017-04-11 10:34:31 -07003059}
3060
philipel277a8b52017-03-16 05:19:49 -07003061TEST_F(EndToEndTest, VerifyHistogramStatsWithRtx) {
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02003062 const bool kEnabledRtx = true;
3063 const bool kEnabledRed = false;
sprangb4a1ae52015-12-03 08:10:08 -08003064 const bool kScreenshare = false;
3065 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02003066}
3067
philipel277a8b52017-03-16 05:19:49 -07003068TEST_F(EndToEndTest, VerifyHistogramStatsWithRed) {
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02003069 const bool kEnabledRtx = false;
3070 const bool kEnabledRed = true;
sprangb4a1ae52015-12-03 08:10:08 -08003071 const bool kScreenshare = false;
3072 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
3073}
3074
philipel277a8b52017-03-16 05:19:49 -07003075TEST_F(EndToEndTest, VerifyHistogramStatsWithScreenshare) {
sprangb4a1ae52015-12-03 08:10:08 -08003076 const bool kEnabledRtx = false;
3077 const bool kEnabledRed = false;
3078 const bool kScreenshare = true;
3079 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02003080}
3081
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003082void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
3083 bool send_single_ssrc_first) {
3084 class SendsSetSsrcs : public test::EndToEndTest {
3085 public:
3086 SendsSetSsrcs(const uint32_t* ssrcs,
3087 size_t num_ssrcs,
3088 bool send_single_ssrc_first)
3089 : EndToEndTest(kDefaultTimeoutMs),
3090 num_ssrcs_(num_ssrcs),
3091 send_single_ssrc_first_(send_single_ssrc_first),
3092 ssrcs_to_observe_(num_ssrcs),
sprang867fb522015-08-03 04:38:41 -07003093 expect_single_ssrc_(send_single_ssrc_first),
3094 send_stream_(nullptr) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003095 for (size_t i = 0; i < num_ssrcs; ++i)
3096 valid_ssrcs_[ssrcs[i]] = true;
3097 }
3098
3099 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003100 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003101 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003102 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003103
3104 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
3105 << "Received unknown SSRC: " << header.ssrc;
3106
3107 if (!valid_ssrcs_[header.ssrc])
Peter Boström5811a392015-12-10 13:02:50 +01003108 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003109
3110 if (!is_observed_[header.ssrc]) {
3111 is_observed_[header.ssrc] = true;
3112 --ssrcs_to_observe_;
3113 if (expect_single_ssrc_) {
3114 expect_single_ssrc_ = false;
Peter Boström5811a392015-12-10 13:02:50 +01003115 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003116 }
3117 }
3118
3119 if (ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01003120 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003121
3122 return SEND_PACKET;
3123 }
3124
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003125 size_t GetNumVideoStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003126
perkjfa10b552016-10-02 23:45:26 -07003127 // This test use other VideoStream settings than the the default settings
3128 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3129 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3130 // in ModifyVideoConfigs.
3131 class VideoStreamFactory
3132 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3133 public:
3134 VideoStreamFactory() {}
3135
3136 private:
3137 std::vector<VideoStream> CreateEncoderStreams(
3138 int width,
3139 int height,
3140 const VideoEncoderConfig& encoder_config) override {
3141 std::vector<VideoStream> streams =
3142 test::CreateVideoStreams(width, height, encoder_config);
3143 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
3144 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3145 streams[i].min_bitrate_bps = 10000;
3146 streams[i].target_bitrate_bps = 15000;
3147 streams[i].max_bitrate_bps = 20000;
3148 }
3149 return streams;
3150 }
3151 };
3152
stefanff483612015-12-21 03:14:00 -08003153 void ModifyVideoConfigs(
3154 VideoSendStream::Config* send_config,
3155 std::vector<VideoReceiveStream::Config>* receive_configs,
3156 VideoEncoderConfig* encoder_config) override {
perkjfa10b552016-10-02 23:45:26 -07003157 encoder_config->video_stream_factory =
3158 new rtc::RefCountedObject<VideoStreamFactory>();
perkj26091b12016-09-01 01:17:40 -07003159 video_encoder_config_all_streams_ = encoder_config->Copy();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003160 if (send_single_ssrc_first_)
perkjfa10b552016-10-02 23:45:26 -07003161 encoder_config->number_of_streams = 1;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003162 }
3163
stefanff483612015-12-21 03:14:00 -08003164 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003165 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003166 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003167 send_stream_ = send_stream;
3168 }
3169
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003170 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003171 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
3172 << (send_single_ssrc_first_ ? "first SSRC."
3173 : "SSRCs.");
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003174
3175 if (send_single_ssrc_first_) {
3176 // Set full simulcast and continue with the rest of the SSRCs.
stefanff483612015-12-21 03:14:00 -08003177 send_stream_->ReconfigureVideoEncoder(
perkj26091b12016-09-01 01:17:40 -07003178 std::move(video_encoder_config_all_streams_));
Peter Boström5811a392015-12-10 13:02:50 +01003179 EXPECT_TRUE(Wait()) << "Timed out while waiting on additional SSRCs.";
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003180 }
3181 }
3182
3183 private:
3184 std::map<uint32_t, bool> valid_ssrcs_;
3185 std::map<uint32_t, bool> is_observed_;
3186
3187 const size_t num_ssrcs_;
3188 const bool send_single_ssrc_first_;
3189
3190 size_t ssrcs_to_observe_;
3191 bool expect_single_ssrc_;
3192
3193 VideoSendStream* send_stream_;
stefanff483612015-12-21 03:14:00 -08003194 VideoEncoderConfig video_encoder_config_all_streams_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003195 } test(kVideoSendSsrcs, num_ssrcs, send_single_ssrc_first);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003196
stefane74eef12016-01-08 06:47:13 -08003197 RunBaseTest(&test);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003198}
3199
philipel277a8b52017-03-16 05:19:49 -07003200TEST_F(EndToEndTest, ReportsSetEncoderRates) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003201 class EncoderRateStatsTest : public test::EndToEndTest,
3202 public test::FakeEncoder {
3203 public:
eladalon413ee9a2017-08-22 04:02:52 -07003204 explicit EncoderRateStatsTest(
3205 test::SingleThreadedTaskQueueForTesting* task_queue)
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003206 : EndToEndTest(kDefaultTimeoutMs),
sprang867fb522015-08-03 04:38:41 -07003207 FakeEncoder(Clock::GetRealTimeClock()),
eladalon413ee9a2017-08-22 04:02:52 -07003208 task_queue_(task_queue),
sprang867fb522015-08-03 04:38:41 -07003209 send_stream_(nullptr),
3210 bitrate_kbps_(0) {}
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003211
stefanff483612015-12-21 03:14:00 -08003212 void OnVideoStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003213 VideoSendStream* send_stream,
3214 const std::vector<VideoReceiveStream*>& receive_streams) override {
3215 send_stream_ = send_stream;
3216 }
3217
stefanff483612015-12-21 03:14:00 -08003218 void ModifyVideoConfigs(
3219 VideoSendStream::Config* send_config,
3220 std::vector<VideoReceiveStream::Config>* receive_configs,
3221 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003222 send_config->encoder_settings.encoder = this;
kwibergaf476c72016-11-28 15:21:39 -08003223 RTC_DCHECK_EQ(1, encoder_config->number_of_streams);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003224 }
3225
Erik Språng08127a92016-11-16 16:41:30 +01003226 int32_t SetRateAllocation(const BitrateAllocation& rate_allocation,
3227 uint32_t framerate) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003228 // Make sure not to trigger on any default zero bitrates.
Erik Språng08127a92016-11-16 16:41:30 +01003229 if (rate_allocation.get_sum_bps() == 0)
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003230 return 0;
Peter Boströmf2f82832015-05-01 13:00:41 +02003231 rtc::CritScope lock(&crit_);
Erik Språng08127a92016-11-16 16:41:30 +01003232 bitrate_kbps_ = rate_allocation.get_sum_kbps();
Peter Boström5811a392015-12-10 13:02:50 +01003233 observation_complete_.Set();
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003234 return 0;
3235 }
3236
3237 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003238 ASSERT_TRUE(Wait())
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003239 << "Timed out while waiting for encoder SetRates() call.";
eladalon413ee9a2017-08-22 04:02:52 -07003240
3241 task_queue_->SendTask([this]() {
3242 WaitForEncoderTargetBitrateMatchStats();
3243 send_stream_->Stop();
3244 WaitForStatsReportZeroTargetBitrate();
3245 send_stream_->Start();
3246 WaitForEncoderTargetBitrateMatchStats();
3247 });
perkjf5b2e512016-07-05 08:34:04 -07003248 }
3249
3250 void WaitForEncoderTargetBitrateMatchStats() {
Peter Boström5811a392015-12-10 13:02:50 +01003251 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003252 VideoSendStream::Stats stats = send_stream_->GetStats();
3253 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003254 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003255 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
3256 static_cast<int>(bitrate_kbps_)) {
3257 return;
3258 }
3259 }
3260 SleepMs(1);
3261 }
3262 FAIL()
3263 << "Timed out waiting for stats reporting the currently set bitrate.";
3264 }
3265
perkjf5b2e512016-07-05 08:34:04 -07003266 void WaitForStatsReportZeroTargetBitrate() {
3267 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
3268 if (send_stream_->GetStats().target_media_bitrate_bps == 0) {
3269 return;
3270 }
3271 SleepMs(1);
3272 }
3273 FAIL() << "Timed out waiting for stats reporting zero bitrate.";
3274 }
3275
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003276 private:
eladalon413ee9a2017-08-22 04:02:52 -07003277 test::SingleThreadedTaskQueueForTesting* const task_queue_;
stefanf116bd02015-10-27 08:29:42 -07003278 rtc::CriticalSection crit_;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003279 VideoSendStream* send_stream_;
danilchapa37de392017-09-09 04:17:22 -07003280 uint32_t bitrate_kbps_ RTC_GUARDED_BY(crit_);
eladalon413ee9a2017-08-22 04:02:52 -07003281 } test(&task_queue_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003282
stefane74eef12016-01-08 06:47:13 -08003283 RunBaseTest(&test);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003284}
3285
philipel277a8b52017-03-16 05:19:49 -07003286TEST_F(EndToEndTest, GetStats) {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00003287 static const int kStartBitrateBps = 3000000;
Peter Boströmdef398832015-05-27 17:59:11 +02003288 static const int kExpectedRenderDelayMs = 20;
tommi2e82f382016-06-21 00:26:43 -07003289
3290 class ReceiveStreamRenderer : public rtc::VideoSinkInterface<VideoFrame> {
3291 public:
3292 ReceiveStreamRenderer() {}
3293
3294 private:
3295 void OnFrame(const VideoFrame& video_frame) override {}
3296 };
3297
nissed30a1112016-04-18 05:15:22 -07003298 class StatsObserver : public test::EndToEndTest,
3299 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003300 public:
stefanf116bd02015-10-27 08:29:42 -07003301 StatsObserver()
3302 : EndToEndTest(kLongTimeoutMs),
Peter Boströmc6e16e32016-02-05 14:15:53 +01003303 encoder_(Clock::GetRealTimeClock(), 10),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00003304 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003305 expected_send_ssrcs_(),
Peter Boström5811a392015-12-10 13:02:50 +01003306 check_stats_event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003307
3308 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003309 Action OnSendRtp(const uint8_t* packet, size_t length) override {
sprangcd349d92016-07-13 09:11:28 -07003310 // Drop every 25th packet => 4% loss.
3311 static const int kPacketLossFrac = 25;
3312 RTPHeader header;
3313 RtpUtility::RtpHeaderParser parser(packet, length);
3314 if (parser.Parse(&header) &&
3315 expected_send_ssrcs_.find(header.ssrc) !=
3316 expected_send_ssrcs_.end() &&
3317 header.sequenceNumber % kPacketLossFrac == 0) {
3318 return DROP_PACKET;
3319 }
Peter Boström5811a392015-12-10 13:02:50 +01003320 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003321 return SEND_PACKET;
3322 }
3323
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003324 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01003325 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003326 return SEND_PACKET;
3327 }
3328
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003329 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01003330 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003331 return SEND_PACKET;
3332 }
3333
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003334 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01003335 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003336 return SEND_PACKET;
3337 }
3338
nissed30a1112016-04-18 05:15:22 -07003339 void OnFrame(const VideoFrame& video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003340 // Ensure that we have at least 5ms send side delay.
nissed30a1112016-04-18 05:15:22 -07003341 SleepMs(5);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003342 }
3343
3344 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003345 for (size_t i = 0; i < receive_streams_.size(); ++i) {
3346 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
3347 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003348
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003349 // Make sure all fields have been populated.
3350 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
3351 // always filled for all receivers.
3352 receive_stats_filled_["IncomingRate"] |=
3353 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003354
Peter Boströmb7d9a972015-12-18 16:01:11 +01003355 send_stats_filled_["DecoderImplementationName"] |=
3356 stats.decoder_implementation_name ==
3357 test::FakeDecoder::kImplementationName;
Peter Boströmdef398832015-05-27 17:59:11 +02003358 receive_stats_filled_["RenderDelayAsHighAsExpected"] |=
3359 stats.render_delay_ms >= kExpectedRenderDelayMs;
3360
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003361 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003362
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003363 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003364
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003365 receive_stats_filled_["StatisticsUpdated"] |=
srte186d9c32017-08-04 05:03:53 -07003366 stats.rtcp_stats.packets_lost != 0 ||
3367 stats.rtcp_stats.extended_highest_sequence_number != 0 ||
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003368 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003369
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003370 receive_stats_filled_["DataCountersUpdated"] |=
3371 stats.rtp_stats.transmitted.payload_bytes != 0 ||
3372 stats.rtp_stats.fec.packets != 0 ||
3373 stats.rtp_stats.transmitted.header_bytes != 0 ||
3374 stats.rtp_stats.transmitted.packets != 0 ||
3375 stats.rtp_stats.transmitted.padding_bytes != 0 ||
3376 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003377
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003378 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003379 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003380
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003381 receive_stats_filled_["FrameCounts"] |=
3382 stats.frame_counts.key_frames != 0 ||
3383 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00003384
pbosbb36fdf2015-07-09 07:48:14 -07003385 receive_stats_filled_["CName"] |= !stats.c_name.empty();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00003386
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003387 receive_stats_filled_["RtcpPacketTypeCount"] |=
3388 stats.rtcp_packet_type_counts.fir_packets != 0 ||
3389 stats.rtcp_packet_type_counts.nack_packets != 0 ||
3390 stats.rtcp_packet_type_counts.pli_packets != 0 ||
3391 stats.rtcp_packet_type_counts.nack_requests != 0 ||
3392 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbosf42376c2015-08-28 07:35:32 -07003393
3394 assert(stats.current_payload_type == -1 ||
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003395 stats.current_payload_type == kFakeVideoSendPayloadType);
pbosf42376c2015-08-28 07:35:32 -07003396 receive_stats_filled_["IncomingPayloadType"] |=
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003397 stats.current_payload_type == kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003398 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003399
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003400 return AllStatsFilled(receive_stats_filled_);
3401 }
3402
3403 bool CheckSendStats() {
Peter Boström74f6e9e2016-04-04 17:56:10 +02003404 RTC_DCHECK(send_stream_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003405 VideoSendStream::Stats stats = send_stream_->GetStats();
3406
philipel20d05a92016-12-19 04:17:27 -08003407 size_t expected_num_streams = kNumSsrcs + expected_send_ssrcs_.size();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003408 send_stats_filled_["NumStreams"] |=
philipel20d05a92016-12-19 04:17:27 -08003409 stats.substreams.size() == expected_num_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003410
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00003411 send_stats_filled_["CpuOveruseMetrics"] |=
Peter Boströme4499152016-02-05 11:13:28 +01003412 stats.avg_encode_time_ms != 0 && stats.encode_usage_percent != 0;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00003413
Peter Boströmb7d9a972015-12-18 16:01:11 +01003414 send_stats_filled_["EncoderImplementationName"] |=
3415 stats.encoder_implementation_name ==
3416 test::FakeEncoder::kImplementationName;
3417
Pera48ddb72016-09-29 11:48:50 +02003418 send_stats_filled_["EncoderPreferredBitrate"] |=
3419 stats.preferred_media_bitrate_bps > 0;
3420
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003421 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003422 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003423 it != stats.substreams.end(); ++it) {
sprangcd349d92016-07-13 09:11:28 -07003424 if (expected_send_ssrcs_.find(it->first) == expected_send_ssrcs_.end())
3425 continue; // Probably RTX.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003426
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003427 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003428 stats.input_frame_rate != 0;
3429
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003430 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003431
3432 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
srte186d9c32017-08-04 05:03:53 -07003433 stream_stats.rtcp_stats.packets_lost != 0 ||
3434 stream_stats.rtcp_stats.extended_highest_sequence_number != 0 ||
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003435 stream_stats.rtcp_stats.fraction_lost != 0;
3436
3437 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00003438 stream_stats.rtp_stats.fec.packets != 0 ||
3439 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
3440 stream_stats.rtp_stats.retransmitted.packets != 0 ||
3441 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003442
sprangcd349d92016-07-13 09:11:28 -07003443 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Total",
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003444 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00003445 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003446
sprangcd349d92016-07-13 09:11:28 -07003447 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Retransmit",
3448 it->first)] |=
3449 stream_stats.retransmit_bitrate_bps != 0;
3450
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003451 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00003452 stream_stats.frame_counts.delta_frames != 0 ||
3453 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003454
3455 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
3456 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00003457
3458 send_stats_filled_[CompoundKey("Delay", it->first)] |=
3459 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003460
3461 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
3462 // report dropped packets.
3463 send_stats_filled_["RtcpPacketTypeCount"] |=
3464 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
3465 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
3466 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
3467 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
3468 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003469 }
3470
3471 return AllStatsFilled(send_stats_filled_);
3472 }
3473
3474 std::string CompoundKey(const char* name, uint32_t ssrc) {
3475 std::ostringstream oss;
3476 oss << name << "_" << ssrc;
3477 return oss.str();
3478 }
3479
3480 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
sprangcd349d92016-07-13 09:11:28 -07003481 for (const auto& stat : stats_map) {
3482 if (!stat.second)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003483 return false;
3484 }
3485 return true;
3486 }
3487
eladalon413ee9a2017-08-22 04:02:52 -07003488 test::PacketTransport* CreateSendTransport(
3489 test::SingleThreadedTaskQueueForTesting* task_queue,
3490 Call* sender_call) override {
stefane74eef12016-01-08 06:47:13 -08003491 FakeNetworkPipe::Config network_config;
3492 network_config.loss_percent = 5;
eladalon413ee9a2017-08-22 04:02:52 -07003493 return new test::PacketTransport(task_queue, sender_call, this,
minyue20c84cc2017-04-10 16:57:57 -07003494 test::PacketTransport::kSender,
3495 payload_type_map_, network_config);
stefane74eef12016-01-08 06:47:13 -08003496 }
3497
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003498 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00003499 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01003500 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00003501 return config;
3502 }
3503
perkjfa10b552016-10-02 23:45:26 -07003504 // This test use other VideoStream settings than the the default settings
3505 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3506 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3507 // in ModifyVideoConfigs.
3508 class VideoStreamFactory
3509 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3510 public:
3511 VideoStreamFactory() {}
3512
3513 private:
3514 std::vector<VideoStream> CreateEncoderStreams(
3515 int width,
3516 int height,
3517 const VideoEncoderConfig& encoder_config) override {
3518 std::vector<VideoStream> streams =
3519 test::CreateVideoStreams(width, height, encoder_config);
3520 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
3521 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3522 streams[i].min_bitrate_bps = 10000;
3523 streams[i].target_bitrate_bps = 15000;
3524 streams[i].max_bitrate_bps = 20000;
3525 }
3526 return streams;
3527 }
3528 };
3529
stefanff483612015-12-21 03:14:00 -08003530 void ModifyVideoConfigs(
3531 VideoSendStream::Config* send_config,
3532 std::vector<VideoReceiveStream::Config>* receive_configs,
3533 VideoEncoderConfig* encoder_config) override {
perkjfa10b552016-10-02 23:45:26 -07003534 encoder_config->video_stream_factory =
3535 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003536 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003537 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003538
sprangcd349d92016-07-13 09:11:28 -07003539 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
3540 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
3541
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003542 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003543 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003544 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003545 expected_receive_ssrcs_.push_back(
3546 (*receive_configs)[i].rtp.remote_ssrc);
Peter Boströmdef398832015-05-27 17:59:11 +02003547 (*receive_configs)[i].render_delay_ms = kExpectedRenderDelayMs;
tommi2e82f382016-06-21 00:26:43 -07003548 (*receive_configs)[i].renderer = &receive_stream_renderer_;
sprangcd349d92016-07-13 09:11:28 -07003549 (*receive_configs)[i].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
3550
brandtr14742122017-01-27 04:53:07 -08003551 (*receive_configs)[i].rtp.rtx_ssrc = kSendRtxSsrcs[i];
nisse26e3abb2017-08-25 04:44:25 -07003552 (*receive_configs)[i]
3553 .rtp.rtx_associated_payload_types[kSendRtxPayloadType] =
3554 kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003555 }
sprangcd349d92016-07-13 09:11:28 -07003556
3557 for (size_t i = 0; i < kNumSsrcs; ++i)
3558 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
3559
Peter Boströmc6e16e32016-02-05 14:15:53 +01003560 // Use a delayed encoder to make sure we see CpuOveruseMetrics stats that
3561 // are non-zero.
3562 send_config->encoder_settings.encoder = &encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003563 }
3564
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003565 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00003566
stefanff483612015-12-21 03:14:00 -08003567 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003568 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003569 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003570 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003571 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003572 }
3573
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003574 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003575 Clock* clock = Clock::GetRealTimeClock();
3576 int64_t now = clock->TimeInMilliseconds();
3577 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
3578 bool receive_ok = false;
3579 bool send_ok = false;
3580
3581 while (now < stop_time) {
3582 if (!receive_ok)
3583 receive_ok = CheckReceiveStats();
3584 if (!send_ok)
3585 send_ok = CheckSendStats();
3586
3587 if (receive_ok && send_ok)
3588 return;
3589
3590 int64_t time_until_timout_ = stop_time - now;
3591 if (time_until_timout_ > 0)
Peter Boström5811a392015-12-10 13:02:50 +01003592 check_stats_event_.Wait(time_until_timout_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003593 now = clock->TimeInMilliseconds();
3594 }
3595
3596 ADD_FAILURE() << "Timed out waiting for filled stats.";
3597 for (std::map<std::string, bool>::const_iterator it =
3598 receive_stats_filled_.begin();
eladalon413ee9a2017-08-22 04:02:52 -07003599 it != receive_stats_filled_.end(); ++it) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003600 if (!it->second) {
3601 ADD_FAILURE() << "Missing receive stats: " << it->first;
3602 }
3603 }
3604
3605 for (std::map<std::string, bool>::const_iterator it =
3606 send_stats_filled_.begin();
eladalon413ee9a2017-08-22 04:02:52 -07003607 it != send_stats_filled_.end(); ++it) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003608 if (!it->second) {
3609 ADD_FAILURE() << "Missing send stats: " << it->first;
3610 }
3611 }
3612 }
3613
Peter Boströmc6e16e32016-02-05 14:15:53 +01003614 test::DelayedEncoder encoder_;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003615 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003616 std::map<std::string, bool> receive_stats_filled_;
3617
3618 VideoSendStream* send_stream_;
3619 std::map<std::string, bool> send_stats_filled_;
3620
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003621 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003622 std::set<uint32_t> expected_send_ssrcs_;
3623 std::string expected_cname_;
3624
Peter Boström5811a392015-12-10 13:02:50 +01003625 rtc::Event check_stats_event_;
tommi2e82f382016-06-21 00:26:43 -07003626 ReceiveStreamRenderer receive_stream_renderer_;
stefanf116bd02015-10-27 08:29:42 -07003627 } test;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003628
stefane74eef12016-01-08 06:47:13 -08003629 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003630}
3631
ilnik75204c52017-09-04 03:35:40 -07003632TEST_F(EndToEndTest, TimingFramesAreReported) {
ilnik2edc6842017-07-06 03:06:50 -07003633 static const int kExtensionId = 5;
3634
3635 class StatsObserver : public test::EndToEndTest {
3636 public:
3637 StatsObserver() : EndToEndTest(kLongTimeoutMs) {}
3638
3639 private:
ilnik2edc6842017-07-06 03:06:50 -07003640 void ModifyVideoConfigs(
3641 VideoSendStream::Config* send_config,
3642 std::vector<VideoReceiveStream::Config>* receive_configs,
3643 VideoEncoderConfig* encoder_config) override {
3644 send_config->rtp.extensions.clear();
3645 send_config->rtp.extensions.push_back(
3646 RtpExtension(RtpExtension::kVideoTimingUri, kExtensionId));
3647 for (size_t i = 0; i < receive_configs->size(); ++i) {
3648 (*receive_configs)[i].rtp.extensions.clear();
3649 (*receive_configs)[i].rtp.extensions.push_back(
3650 RtpExtension(RtpExtension::kVideoTimingUri, kExtensionId));
3651 }
3652 }
3653
3654 void OnVideoStreamsCreated(
3655 VideoSendStream* send_stream,
3656 const std::vector<VideoReceiveStream*>& receive_streams) override {
3657 receive_streams_ = receive_streams;
3658 }
3659
3660 void PerformTest() override {
3661 // No frames reported initially.
3662 for (size_t i = 0; i < receive_streams_.size(); ++i) {
ilnik75204c52017-09-04 03:35:40 -07003663 EXPECT_FALSE(receive_streams_[i]->GetStats().timing_frame_info);
ilnik2edc6842017-07-06 03:06:50 -07003664 }
3665 // Wait for at least one timing frame to be sent with 100ms grace period.
3666 SleepMs(kDefaultTimingFramesDelayMs + 100);
3667 // Check that timing frames are reported for each stream.
3668 for (size_t i = 0; i < receive_streams_.size(); ++i) {
ilnik75204c52017-09-04 03:35:40 -07003669 EXPECT_TRUE(receive_streams_[i]->GetStats().timing_frame_info);
ilnik2edc6842017-07-06 03:06:50 -07003670 }
3671 }
3672
3673 std::vector<VideoReceiveStream*> receive_streams_;
3674 } test;
3675
3676 RunBaseTest(&test);
3677}
3678
sprang1a646ee2016-12-01 06:34:11 -08003679class RtcpXrObserver : public test::EndToEndTest {
3680 public:
sprang44b3ef62017-01-13 07:30:25 -08003681 RtcpXrObserver(bool enable_rrtr, bool enable_target_bitrate)
sprang1a646ee2016-12-01 06:34:11 -08003682 : EndToEndTest(test::CallTest::kDefaultTimeoutMs),
3683 enable_rrtr_(enable_rrtr),
sprang44b3ef62017-01-13 07:30:25 -08003684 enable_target_bitrate_(enable_target_bitrate),
sprang1a646ee2016-12-01 06:34:11 -08003685 sent_rtcp_sr_(0),
3686 sent_rtcp_rr_(0),
3687 sent_rtcp_rrtr_(0),
3688 sent_rtcp_target_bitrate_(false),
3689 sent_rtcp_dlrr_(0) {}
3690
3691 private:
3692 // Receive stream should send RR packets (and RRTR packets if enabled).
3693 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
3694 rtc::CritScope lock(&crit_);
3695 test::RtcpPacketParser parser;
3696 EXPECT_TRUE(parser.Parse(packet, length));
3697
3698 sent_rtcp_rr_ += parser.receiver_report()->num_packets();
3699 EXPECT_EQ(0, parser.sender_report()->num_packets());
3700 EXPECT_GE(1, parser.xr()->num_packets());
3701 if (parser.xr()->num_packets() > 0) {
3702 if (parser.xr()->rrtr())
3703 ++sent_rtcp_rrtr_;
3704 EXPECT_FALSE(parser.xr()->dlrr());
3705 }
3706
3707 return SEND_PACKET;
3708 }
3709 // Send stream should send SR packets (and DLRR packets if enabled).
3710 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
3711 rtc::CritScope lock(&crit_);
3712 test::RtcpPacketParser parser;
3713 EXPECT_TRUE(parser.Parse(packet, length));
3714
3715 sent_rtcp_sr_ += parser.sender_report()->num_packets();
3716 EXPECT_LE(parser.xr()->num_packets(), 1);
3717 if (parser.xr()->num_packets() > 0) {
3718 EXPECT_FALSE(parser.xr()->rrtr());
3719 if (parser.xr()->dlrr())
3720 ++sent_rtcp_dlrr_;
3721 if (parser.xr()->target_bitrate())
3722 sent_rtcp_target_bitrate_ = true;
3723 }
3724
3725 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
3726 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve &&
sprang44b3ef62017-01-13 07:30:25 -08003727 (sent_rtcp_target_bitrate_ || !enable_target_bitrate_)) {
sprang1a646ee2016-12-01 06:34:11 -08003728 if (enable_rrtr_) {
3729 EXPECT_GT(sent_rtcp_rrtr_, 0);
3730 EXPECT_GT(sent_rtcp_dlrr_, 0);
3731 } else {
3732 EXPECT_EQ(sent_rtcp_rrtr_, 0);
3733 EXPECT_EQ(sent_rtcp_dlrr_, 0);
3734 }
sprang44b3ef62017-01-13 07:30:25 -08003735 EXPECT_EQ(enable_target_bitrate_, sent_rtcp_target_bitrate_);
sprang1a646ee2016-12-01 06:34:11 -08003736 observation_complete_.Set();
3737 }
3738 return SEND_PACKET;
3739 }
3740
3741 void ModifyVideoConfigs(
3742 VideoSendStream::Config* send_config,
3743 std::vector<VideoReceiveStream::Config>* receive_configs,
3744 VideoEncoderConfig* encoder_config) override {
sprang44b3ef62017-01-13 07:30:25 -08003745 if (enable_target_bitrate_) {
3746 // TargetBitrate only signaled for screensharing.
3747 encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
3748 }
sprang1a646ee2016-12-01 06:34:11 -08003749 (*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
3750 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
3751 enable_rrtr_;
3752 }
3753
3754 void PerformTest() override {
3755 EXPECT_TRUE(Wait())
3756 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
3757 }
3758
3759 static const int kNumRtcpReportPacketsToObserve = 5;
3760
3761 rtc::CriticalSection crit_;
sprang44b3ef62017-01-13 07:30:25 -08003762 const bool enable_rrtr_;
3763 const bool enable_target_bitrate_;
sprang1a646ee2016-12-01 06:34:11 -08003764 int sent_rtcp_sr_;
danilchapa37de392017-09-09 04:17:22 -07003765 int sent_rtcp_rr_ RTC_GUARDED_BY(&crit_);
3766 int sent_rtcp_rrtr_ RTC_GUARDED_BY(&crit_);
3767 bool sent_rtcp_target_bitrate_ RTC_GUARDED_BY(&crit_);
sprang1a646ee2016-12-01 06:34:11 -08003768 int sent_rtcp_dlrr_;
3769};
3770
philipel277a8b52017-03-16 05:19:49 -07003771TEST_F(EndToEndTest, TestExtendedReportsWithRrtrWithoutTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003772 RtcpXrObserver test(true, false);
sprang1a646ee2016-12-01 06:34:11 -08003773 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003774}
3775
philipel277a8b52017-03-16 05:19:49 -07003776TEST_F(EndToEndTest, TestExtendedReportsWithoutRrtrWithoutTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003777 RtcpXrObserver test(false, false);
3778 RunBaseTest(&test);
3779}
3780
philipel277a8b52017-03-16 05:19:49 -07003781TEST_F(EndToEndTest, TestExtendedReportsWithRrtrWithTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003782 RtcpXrObserver test(true, true);
3783 RunBaseTest(&test);
3784}
3785
philipel277a8b52017-03-16 05:19:49 -07003786TEST_F(EndToEndTest, TestExtendedReportsWithoutRrtrWithTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003787 RtcpXrObserver test(false, true);
sprang1a646ee2016-12-01 06:34:11 -08003788 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003789}
3790
philipel277a8b52017-03-16 05:19:49 -07003791TEST_F(EndToEndTest, TestReceivedRtpPacketStats) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003792 static const size_t kNumRtpPacketsToSend = 5;
3793 class ReceivedRtpStatsObserver : public test::EndToEndTest {
3794 public:
3795 ReceivedRtpStatsObserver()
3796 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00003797 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003798 sent_rtp_(0) {}
3799
3800 private:
stefanff483612015-12-21 03:14:00 -08003801 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003802 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003803 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003804 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003805 }
3806
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003807 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003808 if (sent_rtp_ >= kNumRtpPacketsToSend) {
3809 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00003810 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
Peter Boström5811a392015-12-10 13:02:50 +01003811 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003812 }
3813 return DROP_PACKET;
3814 }
3815 ++sent_rtp_;
3816 return SEND_PACKET;
3817 }
3818
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003819 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003820 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003821 << "Timed out while verifying number of received RTP packets.";
3822 }
3823
3824 VideoReceiveStream* receive_stream_;
3825 uint32_t sent_rtp_;
3826 } test;
3827
stefane74eef12016-01-08 06:47:13 -08003828 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003829}
3830
philipel277a8b52017-03-16 05:19:49 -07003831TEST_F(EndToEndTest, SendsSetSsrc) {
philipel266f0a42016-11-28 08:49:07 -08003832 TestSendsSetSsrcs(1, false);
3833}
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003834
philipel277a8b52017-03-16 05:19:49 -07003835TEST_F(EndToEndTest, SendsSetSimulcastSsrcs) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003836 TestSendsSetSsrcs(kNumSsrcs, false);
3837}
3838
philipel277a8b52017-03-16 05:19:49 -07003839TEST_F(EndToEndTest, CanSwitchToUseAllSsrcs) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003840 TestSendsSetSsrcs(kNumSsrcs, true);
3841}
3842
philipel277a8b52017-03-16 05:19:49 -07003843TEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003844 class ObserveRedundantPayloads: public test::EndToEndTest {
3845 public:
3846 ObserveRedundantPayloads()
3847 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003848 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003849 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
3850 }
3851 }
3852
3853 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003854 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003855 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003856 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003857
3858 if (!registered_rtx_ssrc_[header.ssrc])
3859 return SEND_PACKET;
3860
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003861 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003862 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003863 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003864
3865 if (!packet_is_redundant_payload)
3866 return SEND_PACKET;
3867
3868 if (!observed_redundant_retransmission_[header.ssrc]) {
3869 observed_redundant_retransmission_[header.ssrc] = true;
3870 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01003871 observation_complete_.Set();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003872 }
3873
3874 return SEND_PACKET;
3875 }
3876
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003877 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003878
perkjfa10b552016-10-02 23:45:26 -07003879 // This test use other VideoStream settings than the the default settings
3880 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3881 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3882 // in ModifyVideoConfigs.
3883 class VideoStreamFactory
3884 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3885 public:
3886 VideoStreamFactory() {}
3887
3888 private:
3889 std::vector<VideoStream> CreateEncoderStreams(
3890 int width,
3891 int height,
3892 const VideoEncoderConfig& encoder_config) override {
3893 std::vector<VideoStream> streams =
3894 test::CreateVideoStreams(width, height, encoder_config);
3895 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
3896 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3897 streams[i].min_bitrate_bps = 10000;
3898 streams[i].target_bitrate_bps = 15000;
3899 streams[i].max_bitrate_bps = 20000;
3900 }
3901 return streams;
3902 }
3903 };
3904
stefanff483612015-12-21 03:14:00 -08003905 void ModifyVideoConfigs(
3906 VideoSendStream::Config* send_config,
3907 std::vector<VideoReceiveStream::Config>* receive_configs,
3908 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003909 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
perkjfa10b552016-10-02 23:45:26 -07003910 encoder_config->video_stream_factory =
3911 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003912 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003913
3914 for (size_t i = 0; i < kNumSsrcs; ++i)
3915 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00003916
3917 // Significantly higher than max bitrates for all video streams -> forcing
3918 // padding to trigger redundant padding on all RTX SSRCs.
3919 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003920 }
3921
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003922 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003923 EXPECT_TRUE(Wait())
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003924 << "Timed out while waiting for redundant payloads on all SSRCs.";
3925 }
3926
3927 private:
3928 size_t ssrcs_to_observe_;
3929 std::map<uint32_t, bool> observed_redundant_retransmission_;
3930 std::map<uint32_t, bool> registered_rtx_ssrc_;
3931 } test;
3932
stefane74eef12016-01-08 06:47:13 -08003933 RunBaseTest(&test);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003934}
3935
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003936void EndToEndTest::TestRtpStatePreservation(bool use_rtx,
3937 bool provoke_rtcpsr_before_rtp) {
brandtr5e171752017-05-23 03:32:16 -07003938 // This test uses other VideoStream settings than the the default settings
3939 // implemented in DefaultVideoStreamFactory. Therefore this test implements
perkjfa10b552016-10-02 23:45:26 -07003940 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3941 // in ModifyVideoConfigs.
3942 class VideoStreamFactory
3943 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3944 public:
3945 VideoStreamFactory() {}
3946
3947 private:
3948 std::vector<VideoStream> CreateEncoderStreams(
3949 int width,
3950 int height,
3951 const VideoEncoderConfig& encoder_config) override {
3952 std::vector<VideoStream> streams =
3953 test::CreateVideoStreams(width, height, encoder_config);
3954
3955 if (encoder_config.number_of_streams > 1) {
3956 // Lower bitrates so that all streams send initially.
kwibergaf476c72016-11-28 15:21:39 -08003957 RTC_DCHECK_EQ(3, encoder_config.number_of_streams);
perkjfa10b552016-10-02 23:45:26 -07003958 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3959 streams[i].min_bitrate_bps = 10000;
3960 streams[i].target_bitrate_bps = 15000;
3961 streams[i].max_bitrate_bps = 20000;
3962 }
3963 } else {
3964 // Use the same total bitrates when sending a single stream to avoid
3965 // lowering
3966 // the bitrate estimate and requiring a subsequent rampup.
3967 streams[0].min_bitrate_bps = 3 * 10000;
3968 streams[0].target_bitrate_bps = 3 * 15000;
3969 streams[0].max_bitrate_bps = 3 * 20000;
3970 }
3971 return streams;
3972 }
3973 };
3974
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003975 class RtpSequenceObserver : public test::RtpRtcpObserver {
3976 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003977 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003978 : test::RtpRtcpObserver(kDefaultTimeoutMs),
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003979 ssrcs_to_observe_(kNumSsrcs) {
3980 for (size_t i = 0; i < kNumSsrcs; ++i) {
danilchap32cd2c42016-08-01 06:58:34 -07003981 ssrc_is_rtx_[kVideoSendSsrcs[i]] = false;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003982 if (use_rtx)
danilchap32cd2c42016-08-01 06:58:34 -07003983 ssrc_is_rtx_[kSendRtxSsrcs[i]] = true;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003984 }
3985 }
3986
3987 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
Peter Boströmf2f82832015-05-01 13:00:41 +02003988 rtc::CritScope lock(&crit_);
danilchap34877ee2016-02-01 08:25:04 -08003989 ssrc_observed_.clear();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003990 ssrcs_to_observe_ = num_expected_ssrcs;
3991 }
3992
3993 private:
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003994 void ValidateTimestampGap(uint32_t ssrc,
3995 uint32_t timestamp,
3996 bool only_padding)
danilchapa37de392017-09-09 04:17:22 -07003997 RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003998 static const int32_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
3999 auto timestamp_it = last_observed_timestamp_.find(ssrc);
4000 if (timestamp_it == last_observed_timestamp_.end()) {
4001 EXPECT_FALSE(only_padding);
4002 last_observed_timestamp_[ssrc] = timestamp;
4003 } else {
4004 // Verify timestamps are reasonably close.
4005 uint32_t latest_observed = timestamp_it->second;
4006 // Wraparound handling is unnecessary here as long as an int variable
4007 // is used to store the result.
4008 int32_t timestamp_gap = timestamp - latest_observed;
4009 EXPECT_LE(std::abs(timestamp_gap), kMaxTimestampGap)
4010 << "Gap in timestamps (" << latest_observed << " -> " << timestamp
4011 << ") too large for SSRC: " << ssrc << ".";
4012 timestamp_it->second = timestamp;
4013 }
4014 }
4015
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004016 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004017 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00004018 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004019 const uint32_t ssrc = header.ssrc;
danilchap5c35cf92016-02-03 14:14:49 -08004020 const int64_t sequence_number =
4021 seq_numbers_unwrapper_.Unwrap(header.sequenceNumber);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004022 const uint32_t timestamp = header.timestamp;
danilchap34877ee2016-02-01 08:25:04 -08004023 const bool only_padding =
4024 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004025
danilchap32cd2c42016-08-01 06:58:34 -07004026 EXPECT_TRUE(ssrc_is_rtx_.find(ssrc) != ssrc_is_rtx_.end())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004027 << "Received SSRC that wasn't configured: " << ssrc;
4028
danilchap5c35cf92016-02-03 14:14:49 -08004029 static const int64_t kMaxSequenceNumberGap = 100;
4030 std::list<int64_t>* seq_numbers = &last_observed_seq_numbers_[ssrc];
4031 if (seq_numbers->empty()) {
4032 seq_numbers->push_back(sequence_number);
4033 } else {
4034 // We shouldn't get replays of previous sequence numbers.
4035 for (int64_t observed : *seq_numbers) {
4036 EXPECT_NE(observed, sequence_number)
4037 << "Received sequence number " << sequence_number
4038 << " for SSRC " << ssrc << " 2nd time.";
4039 }
4040 // Verify sequence numbers are reasonably close.
4041 int64_t latest_observed = seq_numbers->back();
4042 int64_t sequence_number_gap = sequence_number - latest_observed;
4043 EXPECT_LE(std::abs(sequence_number_gap), kMaxSequenceNumberGap)
4044 << "Gap in sequence numbers (" << latest_observed << " -> "
4045 << sequence_number << ") too large for SSRC: " << ssrc << ".";
4046 seq_numbers->push_back(sequence_number);
4047 if (seq_numbers->size() >= kMaxSequenceNumberGap) {
4048 seq_numbers->pop_front();
4049 }
4050 }
4051
danilchap32cd2c42016-08-01 06:58:34 -07004052 if (!ssrc_is_rtx_[ssrc]) {
4053 rtc::CritScope lock(&crit_);
4054 ValidateTimestampGap(ssrc, timestamp, only_padding);
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004055
danilchap32cd2c42016-08-01 06:58:34 -07004056 // Wait for media packets on all ssrcs.
4057 if (!ssrc_observed_[ssrc] && !only_padding) {
4058 ssrc_observed_[ssrc] = true;
4059 if (--ssrcs_to_observe_ == 0)
4060 observation_complete_.Set();
4061 }
danilchap34877ee2016-02-01 08:25:04 -08004062 }
4063
danilchapf4b9c772016-01-28 06:14:24 -08004064 return SEND_PACKET;
4065 }
4066
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004067 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
4068 test::RtcpPacketParser rtcp_parser;
4069 rtcp_parser.Parse(packet, length);
4070 if (rtcp_parser.sender_report()->num_packets() > 0) {
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02004071 uint32_t ssrc = rtcp_parser.sender_report()->sender_ssrc();
4072 uint32_t rtcp_timestamp = rtcp_parser.sender_report()->rtp_timestamp();
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004073
4074 rtc::CritScope lock(&crit_);
4075 ValidateTimestampGap(ssrc, rtcp_timestamp, false);
4076 }
4077 return SEND_PACKET;
4078 }
4079
danilchap5c35cf92016-02-03 14:14:49 -08004080 SequenceNumberUnwrapper seq_numbers_unwrapper_;
4081 std::map<uint32_t, std::list<int64_t>> last_observed_seq_numbers_;
danilchap34877ee2016-02-01 08:25:04 -08004082 std::map<uint32_t, uint32_t> last_observed_timestamp_;
danilchap32cd2c42016-08-01 06:58:34 -07004083 std::map<uint32_t, bool> ssrc_is_rtx_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004084
Peter Boströmf2f82832015-05-01 13:00:41 +02004085 rtc::CriticalSection crit_;
danilchapa37de392017-09-09 04:17:22 -07004086 size_t ssrcs_to_observe_ RTC_GUARDED_BY(crit_);
4087 std::map<uint32_t, bool> ssrc_observed_ RTC_GUARDED_BY(crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004088 } observer(use_rtx);
4089
eladalon413ee9a2017-08-22 04:02:52 -07004090 std::unique_ptr<test::PacketTransport> send_transport;
4091 std::unique_ptr<test::PacketTransport> receive_transport;
4092
philipel4fb651d2017-04-10 03:54:05 -07004093 Call::Config config(event_log_.get());
eladalon413ee9a2017-08-22 04:02:52 -07004094 VideoEncoderConfig one_stream;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004095
eladalon413ee9a2017-08-22 04:02:52 -07004096 task_queue_.SendTask([this, &observer, &send_transport, &receive_transport,
4097 &config, &one_stream, use_rtx]() {
4098 CreateCalls(config, config);
stefanf116bd02015-10-27 08:29:42 -07004099
eladalon413ee9a2017-08-22 04:02:52 -07004100 send_transport = rtc::MakeUnique<test::PacketTransport>(
4101 &task_queue_, sender_call_.get(), &observer,
4102 test::PacketTransport::kSender, payload_type_map_,
4103 FakeNetworkPipe::Config());
4104 receive_transport = rtc::MakeUnique<test::PacketTransport>(
4105 &task_queue_, nullptr, &observer, test::PacketTransport::kReceiver,
4106 payload_type_map_, FakeNetworkPipe::Config());
4107 send_transport->SetReceiver(receiver_call_->Receiver());
4108 receive_transport->SetReceiver(sender_call_->Receiver());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004109
eladalon413ee9a2017-08-22 04:02:52 -07004110 CreateSendConfig(kNumSsrcs, 0, 0, send_transport.get());
4111
4112 if (use_rtx) {
4113 for (size_t i = 0; i < kNumSsrcs; ++i) {
4114 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
4115 }
4116 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004117 }
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004118
eladalon413ee9a2017-08-22 04:02:52 -07004119 video_encoder_config_.video_stream_factory =
4120 new rtc::RefCountedObject<VideoStreamFactory>();
4121 // Use the same total bitrates when sending a single stream to avoid
4122 // lowering the bitrate estimate and requiring a subsequent rampup.
4123 one_stream = video_encoder_config_.Copy();
4124 // one_stream.streams.resize(1);
4125 one_stream.number_of_streams = 1;
4126 CreateMatchingReceiveConfigs(receive_transport.get());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004127
eladalon413ee9a2017-08-22 04:02:52 -07004128 CreateVideoStreams();
4129 CreateFrameGeneratorCapturer(30, 1280, 720);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004130
eladalon413ee9a2017-08-22 04:02:52 -07004131 Start();
4132 });
4133
Peter Boström5811a392015-12-10 13:02:50 +01004134 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004135 << "Timed out waiting for all SSRCs to send packets.";
4136
4137 // Test stream resetting more than once to make sure that the state doesn't
4138 // get set once (this could be due to using std::map::insert for instance).
4139 for (size_t i = 0; i < 3; ++i) {
eladalon413ee9a2017-08-22 04:02:52 -07004140 task_queue_.SendTask([&]() {
4141 frame_generator_capturer_->Stop();
4142 sender_call_->DestroyVideoSendStream(video_send_stream_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004143
eladalon413ee9a2017-08-22 04:02:52 -07004144 // Re-create VideoSendStream with only one stream.
4145 video_send_stream_ = sender_call_->CreateVideoSendStream(
4146 video_send_config_.Copy(), one_stream.Copy());
4147 video_send_stream_->Start();
4148 if (provoke_rtcpsr_before_rtp) {
4149 // Rapid Resync Request forces sending RTCP Sender Report back.
4150 // Using this request speeds up this test because then there is no need
4151 // to wait for a second for periodic Sender Report.
4152 rtcp::RapidResyncRequest force_send_sr_back_request;
4153 rtc::Buffer packet = force_send_sr_back_request.Build();
4154 static_cast<webrtc::test::DirectTransport*>(receive_transport.get())
4155 ->SendRtcp(packet.data(), packet.size());
4156 }
4157 CreateFrameGeneratorCapturer(30, 1280, 720);
4158 frame_generator_capturer_->Start();
4159 });
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004160
4161 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01004162 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004163
4164 // Reconfigure back to use all streams.
eladalon413ee9a2017-08-22 04:02:52 -07004165 task_queue_.SendTask([this]() {
4166 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
4167 });
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004168 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01004169 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004170 << "Timed out waiting for all SSRCs to send packets.";
4171
4172 // Reconfigure down to one stream.
eladalon413ee9a2017-08-22 04:02:52 -07004173 task_queue_.SendTask([this, &one_stream]() {
4174 video_send_stream_->ReconfigureVideoEncoder(one_stream.Copy());
4175 });
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004176 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01004177 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004178
4179 // Reconfigure back to use all streams.
eladalon413ee9a2017-08-22 04:02:52 -07004180 task_queue_.SendTask([this]() {
4181 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
4182 });
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004183 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01004184 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004185 << "Timed out waiting for all SSRCs to send packets.";
4186 }
4187
eladalon413ee9a2017-08-22 04:02:52 -07004188 task_queue_.SendTask([this, &send_transport, &receive_transport]() {
4189 Stop();
4190 DestroyStreams();
4191 send_transport.reset();
4192 receive_transport.reset();
4193 DestroyCalls();
4194 });
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004195}
4196
philipel277a8b52017-03-16 05:19:49 -07004197TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpState) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004198 TestRtpStatePreservation(false, false);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004199}
4200
philipel277a8b52017-03-16 05:19:49 -07004201TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpStatesWithRtx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004202 TestRtpStatePreservation(true, false);
4203}
4204
philipel277a8b52017-03-16 05:19:49 -07004205TEST_F(EndToEndTest, RestartingSendStreamKeepsRtpAndRtcpTimestampsSynced) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004206 TestRtpStatePreservation(true, true);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004207}
4208
brandtreb806792017-05-31 07:46:56 -07004209// This test is flaky on linux_memcheck. Disable on all linux bots until
4210// flakyness has been fixed.
4211// https://bugs.chromium.org/p/webrtc/issues/detail?id=7737
4212#if defined(WEBRTC_LINUX)
4213#define MAYBE_TestFlexfecRtpStatePreservation \
4214 DISABLED_TestFlexfecRtpStatePreservation
4215#else
4216#define MAYBE_TestFlexfecRtpStatePreservation TestFlexfecRtpStatePreservation
4217#endif
4218TEST_F(EndToEndTest, MAYBE_TestFlexfecRtpStatePreservation) {
brandtr48d21a22017-05-30 02:32:12 -07004219 class RtpSequenceObserver : public test::RtpRtcpObserver {
4220 public:
4221 RtpSequenceObserver()
4222 : test::RtpRtcpObserver(kDefaultTimeoutMs),
4223 num_flexfec_packets_sent_(0) {}
4224
4225 void ResetPacketCount() {
4226 rtc::CritScope lock(&crit_);
4227 num_flexfec_packets_sent_ = 0;
4228 }
4229
4230 private:
4231 Action OnSendRtp(const uint8_t* packet, size_t length) override {
4232 rtc::CritScope lock(&crit_);
4233
4234 RTPHeader header;
4235 EXPECT_TRUE(parser_->Parse(packet, length, &header));
4236 const uint16_t sequence_number = header.sequenceNumber;
4237 const uint32_t timestamp = header.timestamp;
4238 const uint32_t ssrc = header.ssrc;
4239
4240 if (ssrc == kVideoSendSsrcs[0] || ssrc == kSendRtxSsrcs[0]) {
4241 return SEND_PACKET;
4242 }
4243 EXPECT_EQ(kFlexfecSendSsrc, ssrc) << "Unknown SSRC sent.";
4244
4245 ++num_flexfec_packets_sent_;
4246
4247 // If this is the first packet, we have nothing to compare to.
4248 if (!last_observed_sequence_number_) {
4249 last_observed_sequence_number_.emplace(sequence_number);
4250 last_observed_timestamp_.emplace(timestamp);
4251
4252 return SEND_PACKET;
4253 }
4254
4255 // Verify continuity and monotonicity of RTP sequence numbers.
4256 EXPECT_EQ(static_cast<uint16_t>(*last_observed_sequence_number_ + 1),
4257 sequence_number);
4258 last_observed_sequence_number_.emplace(sequence_number);
4259
4260 // Timestamps should be non-decreasing...
4261 const bool timestamp_is_same_or_newer =
4262 timestamp == *last_observed_timestamp_ ||
4263 IsNewerTimestamp(timestamp, *last_observed_timestamp_);
4264 EXPECT_TRUE(timestamp_is_same_or_newer);
4265 // ...but reasonably close in time.
4266 const int k10SecondsInRtpTimestampBase = 10 * kVideoPayloadTypeFrequency;
4267 EXPECT_TRUE(IsNewerTimestamp(
4268 *last_observed_timestamp_ + k10SecondsInRtpTimestampBase, timestamp));
4269 last_observed_timestamp_.emplace(timestamp);
4270
4271 // Pass test when enough packets have been let through.
4272 if (num_flexfec_packets_sent_ >= 10) {
4273 observation_complete_.Set();
4274 }
4275
4276 return SEND_PACKET;
4277 }
4278
danilchapa37de392017-09-09 04:17:22 -07004279 rtc::Optional<uint16_t> last_observed_sequence_number_
4280 RTC_GUARDED_BY(crit_);
4281 rtc::Optional<uint32_t> last_observed_timestamp_ RTC_GUARDED_BY(crit_);
4282 size_t num_flexfec_packets_sent_ RTC_GUARDED_BY(crit_);
brandtr48d21a22017-05-30 02:32:12 -07004283 rtc::CriticalSection crit_;
4284 } observer;
4285
eladalon05b07bb2017-08-24 07:40:16 -07004286 static constexpr int kFrameMaxWidth = 320;
4287 static constexpr int kFrameMaxHeight = 180;
4288 static constexpr int kFrameRate = 15;
eladalon413ee9a2017-08-22 04:02:52 -07004289
brandtr48d21a22017-05-30 02:32:12 -07004290 Call::Config config(event_log_.get());
brandtr48d21a22017-05-30 02:32:12 -07004291
eladalon413ee9a2017-08-22 04:02:52 -07004292 std::unique_ptr<test::PacketTransport> send_transport;
4293 std::unique_ptr<test::PacketTransport> receive_transport;
4294 std::unique_ptr<VideoEncoder> encoder;
brandtr48d21a22017-05-30 02:32:12 -07004295
eladalon413ee9a2017-08-22 04:02:52 -07004296 task_queue_.SendTask([&]() {
4297 CreateCalls(config, config);
brandtr48d21a22017-05-30 02:32:12 -07004298
eladalon413ee9a2017-08-22 04:02:52 -07004299 FakeNetworkPipe::Config lossy_delayed_link;
4300 lossy_delayed_link.loss_percent = 2;
4301 lossy_delayed_link.queue_delay_ms = 50;
brandtr48d21a22017-05-30 02:32:12 -07004302
eladalon413ee9a2017-08-22 04:02:52 -07004303 send_transport = rtc::MakeUnique<test::PacketTransport>(
4304 &task_queue_, sender_call_.get(), &observer,
4305 test::PacketTransport::kSender, payload_type_map_, lossy_delayed_link);
4306 send_transport->SetReceiver(receiver_call_->Receiver());
brandtr48d21a22017-05-30 02:32:12 -07004307
eladalon413ee9a2017-08-22 04:02:52 -07004308 FakeNetworkPipe::Config flawless_link;
4309 receive_transport = rtc::MakeUnique<test::PacketTransport>(
4310 &task_queue_, nullptr, &observer, test::PacketTransport::kReceiver,
4311 payload_type_map_, flawless_link);
4312 receive_transport->SetReceiver(sender_call_->Receiver());
brandtr48d21a22017-05-30 02:32:12 -07004313
eladalon413ee9a2017-08-22 04:02:52 -07004314 // For reduced flakyness, we use a real VP8 encoder together with NACK
4315 // and RTX.
4316 const int kNumVideoStreams = 1;
4317 const int kNumFlexfecStreams = 1;
4318 CreateSendConfig(kNumVideoStreams, 0, kNumFlexfecStreams,
4319 send_transport.get());
4320 encoder = rtc::WrapUnique(VP8Encoder::Create());
4321 video_send_config_.encoder_settings.encoder = encoder.get();
4322 video_send_config_.encoder_settings.payload_name = "VP8";
4323 video_send_config_.encoder_settings.payload_type = kVideoSendPayloadType;
4324 video_send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
4325 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
4326 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
brandtr48d21a22017-05-30 02:32:12 -07004327
eladalon413ee9a2017-08-22 04:02:52 -07004328 CreateMatchingReceiveConfigs(receive_transport.get());
4329 video_receive_configs_[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
4330 video_receive_configs_[0].rtp.rtx_ssrc = kSendRtxSsrcs[0];
nisse26e3abb2017-08-25 04:44:25 -07004331 video_receive_configs_[0]
4332 .rtp.rtx_associated_payload_types[kSendRtxPayloadType] =
4333 kVideoSendPayloadType;
brandtr48d21a22017-05-30 02:32:12 -07004334
eladalon413ee9a2017-08-22 04:02:52 -07004335 // The matching FlexFEC receive config is not created by
4336 // CreateMatchingReceiveConfigs since this is not a test::BaseTest.
4337 // Set up the receive config manually instead.
4338 FlexfecReceiveStream::Config flexfec_receive_config(
4339 receive_transport.get());
4340 flexfec_receive_config.payload_type =
4341 video_send_config_.rtp.flexfec.payload_type;
4342 flexfec_receive_config.remote_ssrc = video_send_config_.rtp.flexfec.ssrc;
4343 flexfec_receive_config.protected_media_ssrcs =
4344 video_send_config_.rtp.flexfec.protected_media_ssrcs;
4345 flexfec_receive_config.local_ssrc = kReceiverLocalVideoSsrc;
4346 flexfec_receive_config.transport_cc = true;
4347 flexfec_receive_config.rtp_header_extensions.emplace_back(
4348 RtpExtension::kTransportSequenceNumberUri,
4349 test::kTransportSequenceNumberExtensionId);
4350 flexfec_receive_configs_.push_back(flexfec_receive_config);
4351
4352 CreateFlexfecStreams();
4353 CreateVideoStreams();
4354
4355 // RTCP might be disabled if the network is "down".
4356 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
4357 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
4358
4359 CreateFrameGeneratorCapturer(kFrameRate, kFrameMaxWidth, kFrameMaxHeight);
4360
4361 Start();
4362 });
brandtr48d21a22017-05-30 02:32:12 -07004363
4364 // Initial test.
brandtr48d21a22017-05-30 02:32:12 -07004365 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for packets.";
4366
eladalon413ee9a2017-08-22 04:02:52 -07004367 task_queue_.SendTask([this, &observer]() {
4368 // Ensure monotonicity when the VideoSendStream is restarted.
4369 Stop();
4370 observer.ResetPacketCount();
4371 Start();
4372 });
4373
brandtr48d21a22017-05-30 02:32:12 -07004374 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for packets.";
4375
eladalon05b07bb2017-08-24 07:40:16 -07004376 task_queue_.SendTask([this, &observer]() {
eladalon413ee9a2017-08-22 04:02:52 -07004377 // Ensure monotonicity when the VideoSendStream is recreated.
4378 frame_generator_capturer_->Stop();
4379 sender_call_->DestroyVideoSendStream(video_send_stream_);
4380 observer.ResetPacketCount();
4381 video_send_stream_ = sender_call_->CreateVideoSendStream(
4382 video_send_config_.Copy(), video_encoder_config_.Copy());
4383 video_send_stream_->Start();
4384 CreateFrameGeneratorCapturer(kFrameRate, kFrameMaxWidth, kFrameMaxHeight);
4385 frame_generator_capturer_->Start();
4386 });
4387
brandtr48d21a22017-05-30 02:32:12 -07004388 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for packets.";
4389
4390 // Cleanup.
eladalon413ee9a2017-08-22 04:02:52 -07004391 task_queue_.SendTask([this, &send_transport, &receive_transport]() {
4392 Stop();
4393 DestroyStreams();
4394 send_transport.reset();
4395 receive_transport.reset();
4396 DestroyCalls();
4397 });
brandtr48d21a22017-05-30 02:32:12 -07004398}
4399
philipel277a8b52017-03-16 05:19:49 -07004400TEST_F(EndToEndTest, RespectsNetworkState) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004401 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
4402 // down blocks until no more packets will be sent.
4403
4404 // Pacer will send from its packet list and then send required padding before
4405 // checking paused_ again. This should be enough for one round of pacing,
4406 // otherwise increase.
4407 static const int kNumAcceptedDowntimeRtp = 5;
4408 // A single RTCP may be in the pipeline.
4409 static const int kNumAcceptedDowntimeRtcp = 1;
4410 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
4411 public:
eladalon413ee9a2017-08-22 04:02:52 -07004412 explicit NetworkStateTest(
4413 test::SingleThreadedTaskQueueForTesting* task_queue)
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004414 : EndToEndTest(kDefaultTimeoutMs),
4415 FakeEncoder(Clock::GetRealTimeClock()),
eladalon413ee9a2017-08-22 04:02:52 -07004416 task_queue_(task_queue),
Peter Boström5811a392015-12-10 13:02:50 +01004417 encoded_frames_(false, false),
4418 packet_event_(false, false),
sprang867fb522015-08-03 04:38:41 -07004419 sender_call_(nullptr),
4420 receiver_call_(nullptr),
Jelena Marusiccd670222015-07-16 09:30:09 +02004421 sender_state_(kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004422 sender_rtp_(0),
stefan9e117c5e12017-08-16 08:16:25 -07004423 sender_padding_(0),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004424 sender_rtcp_(0),
4425 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004426 down_frames_(0) {}
4427
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004428 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02004429 rtc::CritScope lock(&test_crit_);
stefan9e117c5e12017-08-16 08:16:25 -07004430 RTPHeader header;
4431 EXPECT_TRUE(parser_->Parse(packet, length, &header));
4432 if (length == header.headerLength + header.paddingLength)
4433 ++sender_padding_;
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004434 ++sender_rtp_;
Peter Boström5811a392015-12-10 13:02:50 +01004435 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004436 return SEND_PACKET;
4437 }
4438
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004439 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02004440 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004441 ++sender_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01004442 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004443 return SEND_PACKET;
4444 }
4445
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004446 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004447 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
4448 return SEND_PACKET;
4449 }
4450
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004451 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02004452 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004453 ++receiver_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01004454 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004455 return SEND_PACKET;
4456 }
4457
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004458 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004459 sender_call_ = sender_call;
4460 receiver_call_ = receiver_call;
4461 }
4462
stefanff483612015-12-21 03:14:00 -08004463 void ModifyVideoConfigs(
4464 VideoSendStream::Config* send_config,
4465 std::vector<VideoReceiveStream::Config>* receive_configs,
4466 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004467 send_config->encoder_settings.encoder = this;
4468 }
4469
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004470 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01004471 EXPECT_TRUE(encoded_frames_.Wait(kDefaultTimeoutMs))
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004472 << "No frames received by the encoder.";
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004473
eladalon413ee9a2017-08-22 04:02:52 -07004474 task_queue_->SendTask([this]() {
4475 // Wait for packets from both sender/receiver.
4476 WaitForPacketsOrSilence(false, false);
skvlad7a43d252016-03-22 15:32:27 -07004477
eladalon413ee9a2017-08-22 04:02:52 -07004478 // Sender-side network down for audio; there should be no effect on
4479 // video
4480 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
4481 WaitForPacketsOrSilence(false, false);
skvlad7a43d252016-03-22 15:32:27 -07004482
eladalon413ee9a2017-08-22 04:02:52 -07004483 // Receiver-side network down for audio; no change expected
4484 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO,
4485 kNetworkDown);
4486 WaitForPacketsOrSilence(false, false);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004487
eladalon413ee9a2017-08-22 04:02:52 -07004488 // Sender-side network down.
4489 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
4490 {
4491 rtc::CritScope lock(&test_crit_);
4492 // After network goes down we shouldn't be encoding more frames.
4493 sender_state_ = kNetworkDown;
4494 }
4495 // Wait for receiver-packets and no sender packets.
4496 WaitForPacketsOrSilence(true, false);
skvlad7a43d252016-03-22 15:32:27 -07004497
eladalon413ee9a2017-08-22 04:02:52 -07004498 // Receiver-side network down.
4499 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO,
4500 kNetworkDown);
4501 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004502
eladalon413ee9a2017-08-22 04:02:52 -07004503 // Network up for audio for both sides; video is still not expected to
4504 // start
4505 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
4506 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
4507 WaitForPacketsOrSilence(true, true);
skvlad7a43d252016-03-22 15:32:27 -07004508
eladalon413ee9a2017-08-22 04:02:52 -07004509 // Network back up again for both.
4510 {
4511 rtc::CritScope lock(&test_crit_);
4512 // It's OK to encode frames again, as we're about to bring up the
4513 // network.
4514 sender_state_ = kNetworkUp;
4515 }
4516 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
4517 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
4518 WaitForPacketsOrSilence(false, false);
4519
4520 // TODO(skvlad): add tests to verify that the audio streams are stopped
4521 // when the network goes down for audio once the workaround in
4522 // paced_sender.cc is removed.
4523 });
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004524 }
4525
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07004526 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004527 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07004528 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004529 {
Peter Boströmf2f82832015-05-01 13:00:41 +02004530 rtc::CritScope lock(&test_crit_);
Jelena Marusiccd670222015-07-16 09:30:09 +02004531 if (sender_state_ == kNetworkDown) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004532 ++down_frames_;
4533 EXPECT_LE(down_frames_, 1)
4534 << "Encoding more than one frame while network is down.";
4535 if (down_frames_ > 1)
Peter Boström5811a392015-12-10 13:02:50 +01004536 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004537 } else {
Peter Boström5811a392015-12-10 13:02:50 +01004538 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004539 }
4540 }
4541 return test::FakeEncoder::Encode(
4542 input_image, codec_specific_info, frame_types);
4543 }
4544
4545 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004546 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
4547 int64_t initial_time_ms = clock_->TimeInMilliseconds();
4548 int initial_sender_rtp;
4549 int initial_sender_rtcp;
4550 int initial_receiver_rtcp;
4551 {
Peter Boströmf2f82832015-05-01 13:00:41 +02004552 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004553 initial_sender_rtp = sender_rtp_;
4554 initial_sender_rtcp = sender_rtcp_;
4555 initial_receiver_rtcp = receiver_rtcp_;
4556 }
4557 bool sender_done = false;
4558 bool receiver_done = false;
mflodmand1590b22015-12-09 07:07:59 -08004559 while (!sender_done || !receiver_done) {
Peter Boström5811a392015-12-10 13:02:50 +01004560 packet_event_.Wait(kSilenceTimeoutMs);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004561 int64_t time_now_ms = clock_->TimeInMilliseconds();
Peter Boströmf2f82832015-05-01 13:00:41 +02004562 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004563 if (sender_down) {
stefan9e117c5e12017-08-16 08:16:25 -07004564 ASSERT_LE(sender_rtp_ - initial_sender_rtp - sender_padding_,
4565 kNumAcceptedDowntimeRtp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004566 << "RTP sent during sender-side downtime.";
4567 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
4568 kNumAcceptedDowntimeRtcp)
4569 << "RTCP sent during sender-side downtime.";
4570 if (time_now_ms - initial_time_ms >=
4571 static_cast<int64_t>(kSilenceTimeoutMs)) {
4572 sender_done = true;
4573 }
4574 } else {
skvlad7a43d252016-03-22 15:32:27 -07004575 if (sender_rtp_ > initial_sender_rtp + kNumAcceptedDowntimeRtp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004576 sender_done = true;
4577 }
4578 if (receiver_down) {
4579 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
4580 kNumAcceptedDowntimeRtcp)
4581 << "RTCP sent during receiver-side downtime.";
4582 if (time_now_ms - initial_time_ms >=
4583 static_cast<int64_t>(kSilenceTimeoutMs)) {
4584 receiver_done = true;
4585 }
4586 } else {
skvlad7a43d252016-03-22 15:32:27 -07004587 if (receiver_rtcp_ > initial_receiver_rtcp + kNumAcceptedDowntimeRtcp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004588 receiver_done = true;
4589 }
4590 }
4591 }
4592
eladalon413ee9a2017-08-22 04:02:52 -07004593 test::SingleThreadedTaskQueueForTesting* const task_queue_;
Peter Boströmf2f82832015-05-01 13:00:41 +02004594 rtc::CriticalSection test_crit_;
Peter Boström5811a392015-12-10 13:02:50 +01004595 rtc::Event encoded_frames_;
4596 rtc::Event packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004597 Call* sender_call_;
4598 Call* receiver_call_;
danilchapa37de392017-09-09 04:17:22 -07004599 NetworkState sender_state_ RTC_GUARDED_BY(test_crit_);
4600 int sender_rtp_ RTC_GUARDED_BY(test_crit_);
4601 int sender_padding_ RTC_GUARDED_BY(test_crit_);
4602 int sender_rtcp_ RTC_GUARDED_BY(test_crit_);
4603 int receiver_rtcp_ RTC_GUARDED_BY(test_crit_);
4604 int down_frames_ RTC_GUARDED_BY(test_crit_);
eladalon413ee9a2017-08-22 04:02:52 -07004605 } test(&task_queue_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004606
stefane74eef12016-01-08 06:47:13 -08004607 RunBaseTest(&test);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004608}
4609
philipel277a8b52017-03-16 05:19:49 -07004610TEST_F(EndToEndTest, CallReportsRttForSender) {
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004611 static const int kSendDelayMs = 30;
4612 static const int kReceiveDelayMs = 70;
solenberg4fbae2b2015-08-28 04:07:10 -07004613
eladalon413ee9a2017-08-22 04:02:52 -07004614 std::unique_ptr<test::DirectTransport> sender_transport;
4615 std::unique_ptr<test::DirectTransport> receiver_transport;
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004616
eladalon413ee9a2017-08-22 04:02:52 -07004617 task_queue_.SendTask([this, &sender_transport, &receiver_transport]() {
4618 FakeNetworkPipe::Config config;
4619 config.queue_delay_ms = kSendDelayMs;
4620 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
4621 sender_transport = rtc::MakeUnique<test::DirectTransport>(
4622 &task_queue_, config, sender_call_.get(), payload_type_map_);
4623 config.queue_delay_ms = kReceiveDelayMs;
4624 receiver_transport = rtc::MakeUnique<test::DirectTransport>(
4625 &task_queue_, config, receiver_call_.get(), payload_type_map_);
4626 sender_transport->SetReceiver(receiver_call_->Receiver());
4627 receiver_transport->SetReceiver(sender_call_->Receiver());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004628
eladalon413ee9a2017-08-22 04:02:52 -07004629 CreateSendConfig(1, 0, 0, sender_transport.get());
4630 CreateMatchingReceiveConfigs(receiver_transport.get());
4631
4632 CreateVideoStreams();
4633 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
4634 kDefaultHeight);
4635 Start();
4636 });
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004637
4638 int64_t start_time_ms = clock_->TimeInMilliseconds();
4639 while (true) {
4640 Call::Stats stats = sender_call_->GetStats();
4641 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
4642 clock_->TimeInMilliseconds())
4643 << "No RTT stats before timeout!";
4644 if (stats.rtt_ms != -1) {
Danil Chapovalov10e8f8e2016-09-07 15:05:29 +02004645 // To avoid failures caused by rounding or minor ntp clock adjustments,
4646 // relax expectation by 1ms.
4647 constexpr int kAllowedErrorMs = 1;
4648 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs - kAllowedErrorMs);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004649 break;
4650 }
4651 SleepMs(10);
4652 }
4653
eladalon413ee9a2017-08-22 04:02:52 -07004654 task_queue_.SendTask([this, &sender_transport, &receiver_transport]() {
4655 Stop();
4656 DestroyStreams();
4657 sender_transport.reset();
4658 receiver_transport.reset();
4659 DestroyCalls();
4660 });
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004661}
4662
skvlad7a43d252016-03-22 15:32:27 -07004663void EndToEndTest::VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004664 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -07004665 VideoEncoder* encoder,
4666 Transport* transport) {
eladalon413ee9a2017-08-22 04:02:52 -07004667 task_queue_.SendTask([this, network_to_bring_up, encoder, transport]() {
4668 CreateSenderCall(Call::Config(event_log_.get()));
4669 sender_call_->SignalChannelNetworkState(network_to_bring_up, kNetworkUp);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004670
eladalon413ee9a2017-08-22 04:02:52 -07004671 CreateSendConfig(1, 0, 0, transport);
4672 video_send_config_.encoder_settings.encoder = encoder;
4673 CreateVideoStreams();
4674 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
4675 kDefaultHeight);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004676
eladalon413ee9a2017-08-22 04:02:52 -07004677 Start();
4678 });
4679
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004680 SleepMs(kSilenceTimeoutMs);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004681
eladalon413ee9a2017-08-22 04:02:52 -07004682 task_queue_.SendTask([this]() {
4683 Stop();
4684 DestroyStreams();
4685 DestroyCalls();
4686 });
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004687}
4688
skvlad7a43d252016-03-22 15:32:27 -07004689void EndToEndTest::VerifyNewVideoReceiveStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004690 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -07004691 Transport* transport) {
eladalon413ee9a2017-08-22 04:02:52 -07004692 std::unique_ptr<test::DirectTransport> sender_transport;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004693
eladalon413ee9a2017-08-22 04:02:52 -07004694 task_queue_.SendTask([this, &sender_transport, network_to_bring_up,
4695 transport]() {
4696 Call::Config config(event_log_.get());
4697 CreateCalls(config, config);
4698 receiver_call_->SignalChannelNetworkState(network_to_bring_up, kNetworkUp);
4699 sender_transport = rtc::MakeUnique<test::DirectTransport>(
4700 &task_queue_, sender_call_.get(), payload_type_map_);
4701 sender_transport->SetReceiver(receiver_call_->Receiver());
4702 CreateSendConfig(1, 0, 0, sender_transport.get());
4703 CreateMatchingReceiveConfigs(transport);
4704 CreateVideoStreams();
4705 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
4706 kDefaultHeight);
4707 Start();
4708 });
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004709
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004710 SleepMs(kSilenceTimeoutMs);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004711
eladalon413ee9a2017-08-22 04:02:52 -07004712 task_queue_.SendTask([this, &sender_transport]() {
4713 Stop();
4714 DestroyStreams();
4715 sender_transport.reset();
4716 DestroyCalls();
4717 });
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004718}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00004719
philipel277a8b52017-03-16 05:19:49 -07004720TEST_F(EndToEndTest, NewVideoSendStreamsRespectVideoNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004721 class UnusedEncoder : public test::FakeEncoder {
4722 public:
4723 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
perkjfea93092016-05-14 00:58:48 -07004724
4725 int32_t InitEncode(const VideoCodec* config,
4726 int32_t number_of_cores,
4727 size_t max_payload_size) override {
4728 EXPECT_GT(config->startBitrate, 0u);
4729 return 0;
4730 }
skvlad7a43d252016-03-22 15:32:27 -07004731 int32_t Encode(const VideoFrame& input_image,
4732 const CodecSpecificInfo* codec_specific_info,
4733 const std::vector<FrameType>* frame_types) override {
4734 ADD_FAILURE() << "Unexpected frame encode.";
4735 return test::FakeEncoder::Encode(input_image, codec_specific_info,
4736 frame_types);
4737 }
4738 };
4739
4740 UnusedEncoder unused_encoder;
4741 UnusedTransport unused_transport;
4742 VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004743 MediaType::AUDIO, &unused_encoder, &unused_transport);
skvlad7a43d252016-03-22 15:32:27 -07004744}
4745
philipel277a8b52017-03-16 05:19:49 -07004746TEST_F(EndToEndTest, NewVideoSendStreamsIgnoreAudioNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004747 class RequiredEncoder : public test::FakeEncoder {
4748 public:
4749 RequiredEncoder()
4750 : FakeEncoder(Clock::GetRealTimeClock()), encoded_frame_(false) {}
4751 ~RequiredEncoder() {
4752 if (!encoded_frame_) {
4753 ADD_FAILURE() << "Didn't encode an expected frame";
4754 }
4755 }
4756 int32_t Encode(const VideoFrame& input_image,
4757 const CodecSpecificInfo* codec_specific_info,
4758 const std::vector<FrameType>* frame_types) override {
4759 encoded_frame_ = true;
4760 return test::FakeEncoder::Encode(input_image, codec_specific_info,
4761 frame_types);
4762 }
4763
4764 private:
4765 bool encoded_frame_;
4766 };
4767
4768 RequiredTransport required_transport(true /*rtp*/, false /*rtcp*/);
4769 RequiredEncoder required_encoder;
4770 VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004771 MediaType::VIDEO, &required_encoder, &required_transport);
skvlad7a43d252016-03-22 15:32:27 -07004772}
4773
philipel277a8b52017-03-16 05:19:49 -07004774TEST_F(EndToEndTest, NewVideoReceiveStreamsRespectVideoNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004775 UnusedTransport transport;
Sergey Ulanove2b15012016-11-22 16:08:30 -08004776 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::AUDIO, &transport);
skvlad7a43d252016-03-22 15:32:27 -07004777}
4778
philipel277a8b52017-03-16 05:19:49 -07004779TEST_F(EndToEndTest, NewVideoReceiveStreamsIgnoreAudioNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004780 RequiredTransport transport(false /*rtp*/, true /*rtcp*/);
Sergey Ulanove2b15012016-11-22 16:08:30 -08004781 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::VIDEO, &transport);
skvlad7a43d252016-03-22 15:32:27 -07004782}
4783
Peter Boströmd7da1202015-06-05 14:09:38 +02004784void VerifyEmptyNackConfig(const NackConfig& config) {
4785 EXPECT_EQ(0, config.rtp_history_ms)
4786 << "Enabling NACK requires rtcp-fb: nack negotiation.";
4787}
4788
brandtrb5f2c3f2016-10-04 23:28:39 -07004789void VerifyEmptyUlpfecConfig(const UlpfecConfig& config) {
Peter Boströmd7da1202015-06-05 14:09:38 +02004790 EXPECT_EQ(-1, config.ulpfec_payload_type)
brandtr535830e2016-10-31 03:45:58 -07004791 << "Enabling ULPFEC requires rtpmap: ulpfec negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02004792 EXPECT_EQ(-1, config.red_payload_type)
brandtr535830e2016-10-31 03:45:58 -07004793 << "Enabling ULPFEC requires rtpmap: red negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02004794 EXPECT_EQ(-1, config.red_rtx_payload_type)
brandtr535830e2016-10-31 03:45:58 -07004795 << "Enabling RTX in ULPFEC requires rtpmap: rtx negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02004796}
4797
brandtr3d200bd2017-01-16 06:59:19 -08004798void VerifyEmptyFlexfecConfig(
4799 const VideoSendStream::Config::Rtp::Flexfec& config) {
4800 EXPECT_EQ(-1, config.payload_type)
brandtr1e3dfbf2016-11-16 22:45:19 -08004801 << "Enabling FlexFEC requires rtpmap: flexfec negotiation.";
brandtr3d200bd2017-01-16 06:59:19 -08004802 EXPECT_EQ(0U, config.ssrc)
brandtr1cfbd602016-12-08 04:17:53 -08004803 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
brandtr1e3dfbf2016-11-16 22:45:19 -08004804 EXPECT_TRUE(config.protected_media_ssrcs.empty())
4805 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
4806}
4807
philipel277a8b52017-03-16 05:19:49 -07004808TEST_F(EndToEndTest, VerifyDefaultSendConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07004809 VideoSendStream::Config default_send_config(nullptr);
Peter Boströmd7da1202015-06-05 14:09:38 +02004810 EXPECT_EQ(0, default_send_config.rtp.nack.rtp_history_ms)
4811 << "Enabling NACK require rtcp-fb: nack negotiation.";
4812 EXPECT_TRUE(default_send_config.rtp.rtx.ssrcs.empty())
4813 << "Enabling RTX requires rtpmap: rtx negotiation.";
4814 EXPECT_TRUE(default_send_config.rtp.extensions.empty())
4815 << "Enabling RTP extensions require negotiation.";
4816
4817 VerifyEmptyNackConfig(default_send_config.rtp.nack);
brandtrb5f2c3f2016-10-04 23:28:39 -07004818 VerifyEmptyUlpfecConfig(default_send_config.rtp.ulpfec);
brandtr1e3dfbf2016-11-16 22:45:19 -08004819 VerifyEmptyFlexfecConfig(default_send_config.rtp.flexfec);
Peter Boströmd7da1202015-06-05 14:09:38 +02004820}
4821
philipel277a8b52017-03-16 05:19:49 -07004822TEST_F(EndToEndTest, VerifyDefaultVideoReceiveConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07004823 VideoReceiveStream::Config default_receive_config(nullptr);
pbosda903ea2015-10-02 02:36:56 -07004824 EXPECT_EQ(RtcpMode::kCompound, default_receive_config.rtp.rtcp_mode)
Peter Boströmd7da1202015-06-05 14:09:38 +02004825 << "Reduced-size RTCP require rtcp-rsize to be negotiated.";
4826 EXPECT_FALSE(default_receive_config.rtp.remb)
4827 << "REMB require rtcp-fb: goog-remb to be negotiated.";
4828 EXPECT_FALSE(
4829 default_receive_config.rtp.rtcp_xr.receiver_reference_time_report)
4830 << "RTCP XR settings require rtcp-xr to be negotiated.";
brandtr14742122017-01-27 04:53:07 -08004831 EXPECT_EQ(0U, default_receive_config.rtp.rtx_ssrc)
4832 << "Enabling RTX requires ssrc-group: FID negotiation";
nisse26e3abb2017-08-25 04:44:25 -07004833 EXPECT_TRUE(default_receive_config.rtp.rtx_associated_payload_types.empty())
Peter Boströmd7da1202015-06-05 14:09:38 +02004834 << "Enabling RTX requires rtpmap: rtx negotiation.";
4835 EXPECT_TRUE(default_receive_config.rtp.extensions.empty())
4836 << "Enabling RTP extensions require negotiation.";
4837
4838 VerifyEmptyNackConfig(default_receive_config.rtp.nack);
nisse3b3622f2017-09-26 02:49:21 -07004839 EXPECT_EQ(-1, default_receive_config.rtp.ulpfec_payload_type)
4840 << "Enabling ULPFEC requires rtpmap: ulpfec negotiation.";
4841 EXPECT_EQ(-1, default_receive_config.rtp.red_payload_type)
4842 << "Enabling ULPFEC requires rtpmap: red negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02004843}
4844
philipel277a8b52017-03-16 05:19:49 -07004845TEST_F(EndToEndTest, VerifyDefaultFlexfecReceiveConfigParameters) {
brandtr8313a6f2017-01-13 07:41:19 -08004846 test::NullTransport rtcp_send_transport;
4847 FlexfecReceiveStream::Config default_receive_config(&rtcp_send_transport);
brandtr1cfbd602016-12-08 04:17:53 -08004848 EXPECT_EQ(-1, default_receive_config.payload_type)
4849 << "Enabling FlexFEC requires rtpmap: flexfec negotiation.";
4850 EXPECT_EQ(0U, default_receive_config.remote_ssrc)
4851 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
4852 EXPECT_TRUE(default_receive_config.protected_media_ssrcs.empty())
4853 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
brandtr1e3dfbf2016-11-16 22:45:19 -08004854}
4855
philipel277a8b52017-03-16 05:19:49 -07004856TEST_F(EndToEndTest, TransportSeqNumOnAudioAndVideo) {
danilchap4336d732017-03-03 06:21:54 -08004857 static constexpr int kExtensionId = 8;
4858 static constexpr size_t kMinPacketsToWaitFor = 50;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004859 class TransportSequenceNumberTest : public test::EndToEndTest {
4860 public:
4861 TransportSequenceNumberTest()
4862 : EndToEndTest(kDefaultTimeoutMs),
4863 video_observed_(false),
4864 audio_observed_(false) {
4865 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
4866 kExtensionId);
4867 }
4868
4869 size_t GetNumVideoStreams() const override { return 1; }
4870 size_t GetNumAudioStreams() const override { return 1; }
4871
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004872 void ModifyAudioConfigs(
4873 AudioSendStream::Config* send_config,
4874 std::vector<AudioReceiveStream::Config>* receive_configs) override {
4875 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07004876 send_config->rtp.extensions.push_back(RtpExtension(
4877 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004878 (*receive_configs)[0].rtp.extensions.clear();
4879 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
4880 }
4881
4882 Action OnSendRtp(const uint8_t* packet, size_t length) override {
4883 RTPHeader header;
4884 EXPECT_TRUE(parser_->Parse(packet, length, &header));
4885 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
4886 // Unwrap packet id and verify uniqueness.
4887 int64_t packet_id =
4888 unwrapper_.Unwrap(header.extension.transportSequenceNumber);
4889 EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
4890
4891 if (header.ssrc == kVideoSendSsrcs[0])
4892 video_observed_ = true;
4893 if (header.ssrc == kAudioSendSsrc)
4894 audio_observed_ = true;
4895 if (audio_observed_ && video_observed_ &&
danilchap4336d732017-03-03 06:21:54 -08004896 received_packet_ids_.size() >= kMinPacketsToWaitFor) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004897 size_t packet_id_range =
4898 *received_packet_ids_.rbegin() - *received_packet_ids_.begin() + 1;
4899 EXPECT_EQ(received_packet_ids_.size(), packet_id_range);
4900 observation_complete_.Set();
4901 }
4902 return SEND_PACKET;
4903 }
4904
4905 void PerformTest() override {
4906 EXPECT_TRUE(Wait()) << "Timed out while waiting for audio and video "
4907 "packets with transport sequence number.";
4908 }
4909
danilchap4336d732017-03-03 06:21:54 -08004910 void ExpectSuccessful() {
4911 EXPECT_TRUE(video_observed_);
4912 EXPECT_TRUE(audio_observed_);
4913 EXPECT_GE(received_packet_ids_.size(), kMinPacketsToWaitFor);
4914 }
4915
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004916 private:
4917 bool video_observed_;
4918 bool audio_observed_;
4919 SequenceNumberUnwrapper unwrapper_;
4920 std::set<int64_t> received_packet_ids_;
4921 } test;
4922
stefane74eef12016-01-08 06:47:13 -08004923 RunBaseTest(&test);
danilchap4336d732017-03-03 06:21:54 -08004924 // Double check conditions for successful test to produce better error
4925 // message when the test fail.
4926 test.ExpectSuccessful();
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004927}
palmkviste75f2042016-09-28 06:19:48 -07004928
4929class EndToEndLogTest : public EndToEndTest {
4930 void SetUp() { paths_.clear(); }
4931 void TearDown() {
4932 for (const auto& path : paths_) {
4933 rtc::RemoveFile(path);
4934 }
4935 }
4936
4937 public:
4938 int AddFile() {
4939 paths_.push_back(test::TempFilename(test::OutputPath(), "test_file"));
4940 return static_cast<int>(paths_.size()) - 1;
4941 }
4942
4943 rtc::PlatformFile OpenFile(int idx) {
4944 return rtc::OpenPlatformFile(paths_[idx]);
4945 }
4946
4947 void LogSend(bool open) {
4948 if (open) {
4949 video_send_stream_->EnableEncodedFrameRecording(
4950 std::vector<rtc::PlatformFile>(1, OpenFile(AddFile())), 0);
4951 } else {
4952 video_send_stream_->DisableEncodedFrameRecording();
4953 }
4954 }
4955 void LogReceive(bool open) {
4956 if (open) {
4957 video_receive_streams_[0]->EnableEncodedFrameRecording(
4958 OpenFile(AddFile()), 0);
4959 } else {
4960 video_receive_streams_[0]->DisableEncodedFrameRecording();
4961 }
4962 }
4963
4964 std::vector<std::string> paths_;
4965};
4966
philipel277a8b52017-03-16 05:19:49 -07004967TEST_F(EndToEndLogTest, LogsEncodedFramesWhenRequested) {
palmkviste75f2042016-09-28 06:19:48 -07004968 static const int kNumFramesToRecord = 10;
4969 class LogEncodingObserver : public test::EndToEndTest,
4970 public EncodedFrameObserver {
4971 public:
4972 explicit LogEncodingObserver(EndToEndLogTest* fixture)
4973 : EndToEndTest(kDefaultTimeoutMs),
4974 fixture_(fixture),
4975 recorded_frames_(0) {}
4976
4977 void PerformTest() override {
4978 fixture_->LogSend(true);
4979 fixture_->LogReceive(true);
4980 ASSERT_TRUE(Wait()) << "Timed out while waiting for frame logging.";
4981 }
4982
4983 void ModifyVideoConfigs(
4984 VideoSendStream::Config* send_config,
4985 std::vector<VideoReceiveStream::Config>* receive_configs,
4986 VideoEncoderConfig* encoder_config) override {
magjed509e4fe2016-11-18 01:34:11 -08004987 encoder_.reset(VP8Encoder::Create());
palmkviste75f2042016-09-28 06:19:48 -07004988 decoder_.reset(VP8Decoder::Create());
4989
4990 send_config->post_encode_callback = this;
4991 send_config->encoder_settings.payload_name = "VP8";
4992 send_config->encoder_settings.encoder = encoder_.get();
4993
4994 (*receive_configs)[0].decoders.resize(1);
4995 (*receive_configs)[0].decoders[0].payload_type =
4996 send_config->encoder_settings.payload_type;
4997 (*receive_configs)[0].decoders[0].payload_name =
4998 send_config->encoder_settings.payload_name;
4999 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
5000 }
5001
5002 void EncodedFrameCallback(const EncodedFrame& encoded_frame) override {
5003 rtc::CritScope lock(&crit_);
5004 if (recorded_frames_++ > kNumFramesToRecord) {
5005 fixture_->LogSend(false);
5006 fixture_->LogReceive(false);
5007 rtc::File send_file(fixture_->OpenFile(0));
5008 rtc::File receive_file(fixture_->OpenFile(1));
5009 uint8_t out[100];
5010 // If logging has worked correctly neither file should be empty, i.e.
5011 // we should be able to read something from them.
5012 EXPECT_LT(0u, send_file.Read(out, 100));
5013 EXPECT_LT(0u, receive_file.Read(out, 100));
5014 observation_complete_.Set();
5015 }
5016 }
5017
5018 private:
5019 EndToEndLogTest* const fixture_;
5020 std::unique_ptr<VideoEncoder> encoder_;
5021 std::unique_ptr<VideoDecoder> decoder_;
5022 rtc::CriticalSection crit_;
danilchapa37de392017-09-09 04:17:22 -07005023 int recorded_frames_ RTC_GUARDED_BY(crit_);
palmkviste75f2042016-09-28 06:19:48 -07005024 } test(this);
5025
5026 RunBaseTest(&test);
5027}
5028
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00005029} // namespace webrtc