blob: e320826ba5bdfbbf3c9e026c14165fd1af7507cd [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
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000018#include "webrtc/base/checks.h"
Erik Språng6b8d3552015-09-24 15:06:57 +020019#include "webrtc/base/event.h"
palmkviste75f2042016-09-28 06:19:48 -070020#include "webrtc/base/file.h"
Erik Språng737336d2016-07-29 12:59:36 +020021#include "webrtc/base/optional.h"
brandtr35364632016-12-09 06:51:29 -080022#include "webrtc/base/random.h"
Erik Språng737336d2016-07-29 12:59:36 +020023#include "webrtc/base/rate_limiter.h"
ossuf515ab82016-12-07 04:52:58 -080024#include "webrtc/call/call.h"
pbosa96b60b2016-04-18 21:12:48 -070025#include "webrtc/common_video/include/frame_callback.h"
skvlad11a9cbf2016-10-07 11:53:05 -070026#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
sakal55d932b2016-09-30 06:19:08 -070027#include "webrtc/media/base/fakevideorenderer.h"
danilchap5c35cf92016-02-03 14:14:49 -080028#include "webrtc/modules/include/module_common_types.h"
stefan32f81542016-01-20 07:13:58 -080029#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
sprang861c55e2015-10-16 10:01:21 -070030#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
Erik Språng737336d2016-07-29 12:59:36 +020031#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h"
Danil Chapovalov70ffead2016-07-20 15:26:59 +020032#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.h"
sprangcd349d92016-07-13 09:11:28 -070033#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
hbosbab934b2016-01-27 01:36:03 -080034#include "webrtc/modules/video_coding/codecs/h264/include/h264.h"
marpan@webrtc.org5b883172014-11-01 06:10:48 +000035#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
36#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010037#include "webrtc/modules/video_coding/include/video_coding_defines.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010038#include "webrtc/system_wrappers/include/metrics.h"
asapersson01d70a32016-05-20 06:29:46 -070039#include "webrtc/system_wrappers/include/metrics_default.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010040#include "webrtc/system_wrappers/include/sleep.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000041#include "webrtc/test/call_test.h"
42#include "webrtc/test/direct_transport.h"
43#include "webrtc/test/encoder_settings.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000044#include "webrtc/test/fake_decoder.h"
45#include "webrtc/test/fake_encoder.h"
philipel266f0a42016-11-28 08:49:07 -080046#include "webrtc/test/field_trial.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000047#include "webrtc/test/frame_generator.h"
48#include "webrtc/test/frame_generator_capturer.h"
kwibergac9f8762016-09-30 22:29:43 -070049#include "webrtc/test/gtest.h"
philipel266f0a42016-11-28 08:49:07 -080050#include "webrtc/test/gmock.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000051#include "webrtc/test/null_transport.h"
asapersson@webrtc.org37c05592015-01-28 13:58:27 +000052#include "webrtc/test/rtcp_packet_parser.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000053#include "webrtc/test/rtp_rtcp_observer.h"
54#include "webrtc/test/testsupport/fileutils.h"
55#include "webrtc/test/testsupport/perf_test.h"
charujainbf6a45b2016-11-03 04:21:42 -070056#include "webrtc/video/transport_adapter.h"
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +000057#include "webrtc/video_encoder.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000058
aleloi7057b6b2017-03-29 02:07:33 -070059#if defined(MEMORY_SANITIZER)
60// Flaky under MemorySanitizer, see
61// https://bugs.chromium.org/p/webrtc/issues/detail?id=7419
62#define MAYBE_InitialProbing DISABLED_InitialProbing
63#else
64#define MAYBE_InitialProbing InitialProbing
65#endif
66
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000067namespace webrtc {
68
Peter Boström5811a392015-12-10 13:02:50 +010069static const int kSilenceTimeoutMs = 2000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000070
philipel277a8b52017-03-16 05:19:49 -070071class EndToEndTest : public test::CallTest {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000072 public:
philipel277a8b52017-03-16 05:19:49 -070073 EndToEndTest() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000074
75 virtual ~EndToEndTest() {
stefanff483612015-12-21 03:14:00 -080076 EXPECT_EQ(nullptr, video_send_stream_);
77 EXPECT_TRUE(video_receive_streams_.empty());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000078 }
79
80 protected:
pbos2d566682015-09-28 09:59:31 -070081 class UnusedTransport : public Transport {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000082 private:
stefan1d8a5062015-10-02 03:39:33 -070083 bool SendRtp(const uint8_t* packet,
84 size_t length,
85 const PacketOptions& options) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000086 ADD_FAILURE() << "Unexpected RTP sent.";
87 return false;
88 }
89
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000090 bool SendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000091 ADD_FAILURE() << "Unexpected RTCP sent.";
92 return false;
93 }
94 };
95
skvlad7a43d252016-03-22 15:32:27 -070096 class RequiredTransport : public Transport {
97 public:
98 RequiredTransport(bool rtp_required, bool rtcp_required)
99 : need_rtp_(rtp_required), need_rtcp_(rtcp_required) {}
100 ~RequiredTransport() {
101 if (need_rtp_) {
102 ADD_FAILURE() << "Expected RTP packet not sent.";
103 }
104 if (need_rtcp_) {
105 ADD_FAILURE() << "Expected RTCP packet not sent.";
106 }
107 }
108
109 private:
110 bool SendRtp(const uint8_t* packet,
111 size_t length,
112 const PacketOptions& options) override {
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700113 rtc::CritScope lock(&crit_);
skvlad7a43d252016-03-22 15:32:27 -0700114 need_rtp_ = false;
115 return true;
116 }
117
118 bool SendRtcp(const uint8_t* packet, size_t length) override {
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700119 rtc::CritScope lock(&crit_);
skvlad7a43d252016-03-22 15:32:27 -0700120 need_rtcp_ = false;
121 return true;
122 }
123 bool need_rtp_;
124 bool need_rtcp_;
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700125 rtc::CriticalSection crit_;
skvlad7a43d252016-03-22 15:32:27 -0700126 };
127
Peter Boström39593972016-02-15 11:27:15 +0100128 void DecodesRetransmittedFrame(bool enable_rtx, bool enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000129 void ReceivesPliAndRecovers(int rtp_history_ms);
pbosda903ea2015-10-02 02:36:56 -0700130 void RespectsRtcpMode(RtcpMode rtcp_mode);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000131 void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200132 void TestRtpStatePreservation(bool use_rtx, bool provoke_rtcpsr_before_rtp);
sprangb4a1ae52015-12-03 08:10:08 -0800133 void VerifyHistogramStats(bool use_rtx, bool use_red, bool screenshare);
skvlad7a43d252016-03-22 15:32:27 -0700134 void VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -0800135 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -0700136 VideoEncoder* encoder,
137 Transport* transport);
138 void VerifyNewVideoReceiveStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -0800139 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -0700140 Transport* transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000141};
142
philipel277a8b52017-03-16 05:19:49 -0700143TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
skvlad11a9cbf2016-10-07 11:53:05 -0700144 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000145
solenberg4fbae2b2015-08-28 04:07:10 -0700146 test::NullTransport transport;
brandtr841de6a2016-11-15 07:10:52 -0800147 CreateSendConfig(1, 0, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700148 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000149
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100150 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000151
stefanff483612015-12-21 03:14:00 -0800152 video_receive_streams_[0]->Start();
153 video_receive_streams_[0]->Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000154
155 DestroyStreams();
156}
157
philipel277a8b52017-03-16 05:19:49 -0700158TEST_F(EndToEndTest, ReceiverCanBeStoppedTwice) {
skvlad11a9cbf2016-10-07 11:53:05 -0700159 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000160
solenberg4fbae2b2015-08-28 04:07:10 -0700161 test::NullTransport transport;
brandtr841de6a2016-11-15 07:10:52 -0800162 CreateSendConfig(1, 0, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700163 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000164
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100165 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000166
stefanff483612015-12-21 03:14:00 -0800167 video_receive_streams_[0]->Stop();
168 video_receive_streams_[0]->Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000169
170 DestroyStreams();
171}
172
philipel277a8b52017-03-16 05:19:49 -0700173TEST_F(EndToEndTest, ReceiverCanBeStoppedAndRestarted) {
sprang113bdca2016-10-11 03:10:10 -0700174 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
175
176 test::NullTransport transport;
brandtr841de6a2016-11-15 07:10:52 -0800177 CreateSendConfig(1, 0, 0, &transport);
sprang113bdca2016-10-11 03:10:10 -0700178 CreateMatchingReceiveConfigs(&transport);
179
180 CreateVideoStreams();
181
182 video_receive_streams_[0]->Stop();
183 video_receive_streams_[0]->Start();
184 video_receive_streams_[0]->Stop();
185
186 DestroyStreams();
187}
188
philipel277a8b52017-03-16 05:19:49 -0700189TEST_F(EndToEndTest, RendersSingleDelayedFrame) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000190 static const int kWidth = 320;
191 static const int kHeight = 240;
192 // This constant is chosen to be higher than the timeout in the video_render
193 // module. This makes sure that frames aren't dropped if there are no other
194 // frames in the queue.
nisse76bc8e82017-02-07 09:37:41 -0800195 static const int kRenderDelayMs = 1000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000196
nisse7ade7b32016-03-23 04:48:10 -0700197 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000198 public:
Peter Boström5811a392015-12-10 13:02:50 +0100199 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000200
nisse76bc8e82017-02-07 09:37:41 -0800201 void OnFrame(const VideoFrame& video_frame) override {
202 SleepMs(kRenderDelayMs);
203 event_.Set();
204 }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000205
Peter Boström5811a392015-12-10 13:02:50 +0100206 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000207
Peter Boström5811a392015-12-10 13:02:50 +0100208 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000209 } renderer;
210
skvlad11a9cbf2016-10-07 11:53:05 -0700211 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -0700212
nissee5ad5ca2017-03-29 23:57:43 -0700213 test::DirectTransport sender_transport(
214 sender_call_.get(), MediaType::VIDEO);
215 test::DirectTransport receiver_transport(
216 receiver_call_.get(), MediaType::VIDEO);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000217 sender_transport.SetReceiver(receiver_call_->Receiver());
218 receiver_transport.SetReceiver(sender_call_->Receiver());
219
brandtr841de6a2016-11-15 07:10:52 -0800220 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700221 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000222
stefanff483612015-12-21 03:14:00 -0800223 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000224
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100225 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000226 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000227
228 // Create frames that are smaller than the send width/height, this is done to
229 // check that the callbacks are done after processing video.
kwiberg27f982b2016-03-01 11:52:33 -0800230 std::unique_ptr<test::FrameGenerator> frame_generator(
perkja8ba1952017-02-27 06:52:10 -0800231 test::FrameGenerator::CreateSquareGenerator(kWidth, kHeight));
perkja49cbd32016-09-16 07:53:41 -0700232 test::FrameForwarder frame_forwarder;
perkj803d97f2016-11-01 11:45:46 -0700233 video_send_stream_->SetSource(
sprangc5d62e22017-04-02 23:53:04 -0700234 &frame_forwarder,
235 VideoSendStream::DegradationPreference::kMaintainFramerate);
perkja49cbd32016-09-16 07:53:41 -0700236
237 frame_forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
Peter Boström5811a392015-12-10 13:02:50 +0100238 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000239 << "Timed out while waiting for the frame to render.";
240
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000241 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000242
243 sender_transport.StopSending();
244 receiver_transport.StopSending();
245
246 DestroyStreams();
247}
248
philipel277a8b52017-03-16 05:19:49 -0700249TEST_F(EndToEndTest, TransmitsFirstFrame) {
nisse7ade7b32016-03-23 04:48:10 -0700250 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000251 public:
Peter Boström5811a392015-12-10 13:02:50 +0100252 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000253
nisseeb83a1a2016-03-21 01:27:56 -0700254 void OnFrame(const VideoFrame& video_frame) override { event_.Set(); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000255
Peter Boström5811a392015-12-10 13:02:50 +0100256 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000257
Peter Boström5811a392015-12-10 13:02:50 +0100258 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000259 } renderer;
260
skvlad11a9cbf2016-10-07 11:53:05 -0700261 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -0700262
nissee5ad5ca2017-03-29 23:57:43 -0700263 test::DirectTransport sender_transport(
264 sender_call_.get(), MediaType::VIDEO);
265 test::DirectTransport receiver_transport(
266 receiver_call_.get(), MediaType::VIDEO);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000267 sender_transport.SetReceiver(receiver_call_->Receiver());
268 receiver_transport.SetReceiver(sender_call_->Receiver());
269
brandtr841de6a2016-11-15 07:10:52 -0800270 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700271 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -0800272 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000273
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100274 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000275 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000276
kwiberg27f982b2016-03-01 11:52:33 -0800277 std::unique_ptr<test::FrameGenerator> frame_generator(
perkja8ba1952017-02-27 06:52:10 -0800278 test::FrameGenerator::CreateSquareGenerator(kDefaultWidth,
perkjfa10b552016-10-02 23:45:26 -0700279 kDefaultHeight));
perkja49cbd32016-09-16 07:53:41 -0700280 test::FrameForwarder frame_forwarder;
perkj803d97f2016-11-01 11:45:46 -0700281 video_send_stream_->SetSource(
sprangc5d62e22017-04-02 23:53:04 -0700282 &frame_forwarder,
283 VideoSendStream::DegradationPreference::kMaintainFramerate);
perkja49cbd32016-09-16 07:53:41 -0700284 frame_forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000285
Peter Boström5811a392015-12-10 13:02:50 +0100286 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000287 << "Timed out while waiting for the frame to render.";
288
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000289 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000290
291 sender_transport.StopSending();
292 receiver_transport.StopSending();
293
294 DestroyStreams();
295}
296
Perba7dc722016-04-19 15:01:23 +0200297class CodecObserver : public test::EndToEndTest,
nisse7ade7b32016-03-23 04:48:10 -0700298 public rtc::VideoSinkInterface<VideoFrame> {
Perba7dc722016-04-19 15:01:23 +0200299 public:
300 CodecObserver(int no_frames_to_wait_for,
301 VideoRotation rotation_to_test,
302 const std::string& payload_name,
303 webrtc::VideoEncoder* encoder,
304 webrtc::VideoDecoder* decoder)
hta9aa96882016-12-06 05:36:03 -0800305 : EndToEndTest(4 * webrtc::EndToEndTest::kDefaultTimeoutMs),
306 // TODO(hta): This timeout (120 seconds) is excessive.
307 // https://bugs.webrtc.org/6830
Perba7dc722016-04-19 15:01:23 +0200308 no_frames_to_wait_for_(no_frames_to_wait_for),
309 expected_rotation_(rotation_to_test),
310 payload_name_(payload_name),
311 encoder_(encoder),
312 decoder_(decoder),
313 frame_counter_(0) {}
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000314
Perba7dc722016-04-19 15:01:23 +0200315 void PerformTest() override {
316 EXPECT_TRUE(Wait())
317 << "Timed out while waiting for enough frames to be decoded.";
318 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000319
Perba7dc722016-04-19 15:01:23 +0200320 void ModifyVideoConfigs(
321 VideoSendStream::Config* send_config,
322 std::vector<VideoReceiveStream::Config>* receive_configs,
323 VideoEncoderConfig* encoder_config) override {
324 send_config->encoder_settings.encoder = encoder_.get();
325 send_config->encoder_settings.payload_name = payload_name_;
326 send_config->encoder_settings.payload_type = 126;
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000327
Perba7dc722016-04-19 15:01:23 +0200328 (*receive_configs)[0].renderer = this;
329 (*receive_configs)[0].decoders.resize(1);
330 (*receive_configs)[0].decoders[0].payload_type =
331 send_config->encoder_settings.payload_type;
332 (*receive_configs)[0].decoders[0].payload_name =
333 send_config->encoder_settings.payload_name;
334 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
335 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000336
Perba7dc722016-04-19 15:01:23 +0200337 void OnFrame(const VideoFrame& video_frame) override {
338 EXPECT_EQ(expected_rotation_, video_frame.rotation());
339 if (++frame_counter_ == no_frames_to_wait_for_)
340 observation_complete_.Set();
341 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000342
Perba7dc722016-04-19 15:01:23 +0200343 void OnFrameGeneratorCapturerCreated(
344 test::FrameGeneratorCapturer* frame_generator_capturer) override {
345 frame_generator_capturer->SetFakeRotation(expected_rotation_);
346 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000347
Perba7dc722016-04-19 15:01:23 +0200348 private:
349 int no_frames_to_wait_for_;
350 VideoRotation expected_rotation_;
351 std::string payload_name_;
352 std::unique_ptr<webrtc::VideoEncoder> encoder_;
353 std::unique_ptr<webrtc::VideoDecoder> decoder_;
354 int frame_counter_;
355};
356
philipel277a8b52017-03-16 05:19:49 -0700357TEST_F(EndToEndTest, SendsAndReceivesVP8) {
philipel266f0a42016-11-28 08:49:07 -0800358 CodecObserver test(5, kVideoRotation_0, "VP8", VP8Encoder::Create(),
359 VP8Decoder::Create());
360 RunBaseTest(&test);
361}
362
philipel277a8b52017-03-16 05:19:49 -0700363TEST_F(EndToEndTest, SendsAndReceivesVP8Rotation90) {
magjed509e4fe2016-11-18 01:34:11 -0800364 CodecObserver test(5, kVideoRotation_90, "VP8", VP8Encoder::Create(),
Perba7dc722016-04-19 15:01:23 +0200365 VP8Decoder::Create());
366 RunBaseTest(&test);
367}
368
Peter Boström12996152016-05-14 02:03:18 +0200369#if !defined(RTC_DISABLE_VP9)
philipel277a8b52017-03-16 05:19:49 -0700370TEST_F(EndToEndTest, SendsAndReceivesVP9) {
magjed509e4fe2016-11-18 01:34:11 -0800371 CodecObserver test(500, kVideoRotation_0, "VP9", VP9Encoder::Create(),
Perba7dc722016-04-19 15:01:23 +0200372 VP9Decoder::Create());
373 RunBaseTest(&test);
374}
375
philipel277a8b52017-03-16 05:19:49 -0700376TEST_F(EndToEndTest, SendsAndReceivesVP9VideoRotation90) {
magjed509e4fe2016-11-18 01:34:11 -0800377 CodecObserver test(5, kVideoRotation_90, "VP9", VP9Encoder::Create(),
Perba7dc722016-04-19 15:01:23 +0200378 VP9Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800379 RunBaseTest(&test);
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000380}
Peter Boström12996152016-05-14 02:03:18 +0200381#endif // !defined(RTC_DISABLE_VP9)
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000382
brandtr445fb8f2016-11-14 04:11:23 -0800383#if defined(WEBRTC_USE_H264)
philipel277a8b52017-03-16 05:19:49 -0700384TEST_F(EndToEndTest, SendsAndReceivesH264) {
magjedceecea42016-11-28 07:20:21 -0800385 CodecObserver test(500, kVideoRotation_0, "H264",
386 H264Encoder::Create(cricket::VideoCodec("H264")),
Perba7dc722016-04-19 15:01:23 +0200387 H264Decoder::Create());
388 RunBaseTest(&test);
389}
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000390
philipel277a8b52017-03-16 05:19:49 -0700391TEST_F(EndToEndTest, SendsAndReceivesH264VideoRotation90) {
magjedceecea42016-11-28 07:20:21 -0800392 CodecObserver test(5, kVideoRotation_90, "H264",
393 H264Encoder::Create(cricket::VideoCodec("H264")),
Perba7dc722016-04-19 15:01:23 +0200394 H264Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800395 RunBaseTest(&test);
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000396}
hta9aa96882016-12-06 05:36:03 -0800397
philipel277a8b52017-03-16 05:19:49 -0700398TEST_F(EndToEndTest, SendsAndReceivesH264PacketizationMode0) {
hta9aa96882016-12-06 05:36:03 -0800399 cricket::VideoCodec codec = cricket::VideoCodec("H264");
400 codec.SetParam(cricket::kH264FmtpPacketizationMode, "0");
401 CodecObserver test(500, kVideoRotation_0, "H264", H264Encoder::Create(codec),
402 H264Decoder::Create());
403 RunBaseTest(&test);
404}
405
philipel277a8b52017-03-16 05:19:49 -0700406TEST_F(EndToEndTest, SendsAndReceivesH264PacketizationMode1) {
hta9aa96882016-12-06 05:36:03 -0800407 cricket::VideoCodec codec = cricket::VideoCodec("H264");
408 codec.SetParam(cricket::kH264FmtpPacketizationMode, "1");
409 CodecObserver test(500, kVideoRotation_0, "H264", H264Encoder::Create(codec),
410 H264Decoder::Create());
411 RunBaseTest(&test);
412}
413
brandtr445fb8f2016-11-14 04:11:23 -0800414#endif // defined(WEBRTC_USE_H264)
hbosbab934b2016-01-27 01:36:03 -0800415
philipel277a8b52017-03-16 05:19:49 -0700416TEST_F(EndToEndTest, ReceiverUsesLocalSsrc) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000417 class SyncRtcpObserver : public test::EndToEndTest {
418 public:
419 SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {}
420
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000421 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
danilchap3dc929e2016-11-02 08:21:59 -0700422 test::RtcpPacketParser parser;
423 EXPECT_TRUE(parser.Parse(packet, length));
424 EXPECT_EQ(kReceiverLocalVideoSsrc, parser.sender_ssrc());
Peter Boström5811a392015-12-10 13:02:50 +0100425 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000426
427 return SEND_PACKET;
428 }
429
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000430 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100431 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000432 << "Timed out while waiting for a receiver RTCP packet to be sent.";
433 }
434 } test;
435
stefane74eef12016-01-08 06:47:13 -0800436 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000437}
438
philipel277a8b52017-03-16 05:19:49 -0700439TEST_F(EndToEndTest, ReceivesAndRetransmitsNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000440 static const int kNumberOfNacksToObserve = 2;
441 static const int kLossBurstSize = 2;
442 static const int kPacketsBetweenLossBursts = 9;
443 class NackObserver : public test::EndToEndTest {
444 public:
445 NackObserver()
446 : EndToEndTest(kLongTimeoutMs),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000447 sent_rtp_packets_(0),
448 packets_left_to_drop_(0),
449 nacks_left_(kNumberOfNacksToObserve) {}
450
451 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000452 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700453 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000454 RTPHeader header;
Peter Boström03671cb2015-12-07 15:22:24 +0100455 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000456
457 // Never drop retransmitted packets.
458 if (dropped_packets_.find(header.sequenceNumber) !=
459 dropped_packets_.end()) {
460 retransmitted_packets_.insert(header.sequenceNumber);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000461 return SEND_PACKET;
462 }
463
philipel8054c7e2017-01-10 05:19:19 -0800464 if (nacks_left_ <= 0 &&
465 retransmitted_packets_.size() == dropped_packets_.size()) {
466 observation_complete_.Set();
467 }
468
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000469 ++sent_rtp_packets_;
470
471 // Enough NACKs received, stop dropping packets.
Stefan Holmer586b19b2015-09-18 11:14:31 +0200472 if (nacks_left_ <= 0)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000473 return SEND_PACKET;
474
475 // Check if it's time for a new loss burst.
476 if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
477 packets_left_to_drop_ = kLossBurstSize;
478
Stefan Holmer01b48882015-05-05 10:21:24 +0200479 // Never drop padding packets as those won't be retransmitted.
480 if (packets_left_to_drop_ > 0 && header.paddingLength == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000481 --packets_left_to_drop_;
482 dropped_packets_.insert(header.sequenceNumber);
483 return DROP_PACKET;
484 }
485
486 return SEND_PACKET;
487 }
488
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000489 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700490 rtc::CritScope lock(&crit_);
danilchap3dc929e2016-11-02 08:21:59 -0700491 test::RtcpPacketParser parser;
492 EXPECT_TRUE(parser.Parse(packet, length));
493 nacks_left_ -= parser.nack()->num_packets();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000494 return SEND_PACKET;
495 }
496
stefanff483612015-12-21 03:14:00 -0800497 void ModifyVideoConfigs(
498 VideoSendStream::Config* send_config,
499 std::vector<VideoReceiveStream::Config>* receive_configs,
500 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000501 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000502 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000503 }
504
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000505 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100506 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000507 << "Timed out waiting for packets to be NACKed, retransmitted and "
508 "rendered.";
509 }
510
stefanf116bd02015-10-27 08:29:42 -0700511 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000512 std::set<uint16_t> dropped_packets_;
513 std::set<uint16_t> retransmitted_packets_;
514 uint64_t sent_rtp_packets_;
515 int packets_left_to_drop_;
stefanf116bd02015-10-27 08:29:42 -0700516 int nacks_left_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000517 } test;
518
stefane74eef12016-01-08 06:47:13 -0800519 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000520}
521
philipel277a8b52017-03-16 05:19:49 -0700522TEST_F(EndToEndTest, ReceivesNackAndRetransmitsAudio) {
Erik Språng737336d2016-07-29 12:59:36 +0200523 class NackObserver : public test::EndToEndTest {
524 public:
525 NackObserver()
526 : EndToEndTest(kLongTimeoutMs),
527 local_ssrc_(0),
528 remote_ssrc_(0),
529 receive_transport_(nullptr) {}
530
531 private:
532 size_t GetNumVideoStreams() const override { return 0; }
533 size_t GetNumAudioStreams() const override { return 1; }
534
535 test::PacketTransport* CreateReceiveTransport() override {
536 test::PacketTransport* receive_transport = new test::PacketTransport(
537 nullptr, this, test::PacketTransport::kReceiver,
nissee5ad5ca2017-03-29 23:57:43 -0700538 MediaType::AUDIO,
Erik Språng737336d2016-07-29 12:59:36 +0200539 FakeNetworkPipe::Config());
540 receive_transport_ = receive_transport;
541 return receive_transport;
542 }
543
544 Action OnSendRtp(const uint8_t* packet, size_t length) override {
545 RTPHeader header;
546 EXPECT_TRUE(parser_->Parse(packet, length, &header));
547
548 if (!sequence_number_to_retransmit_) {
549 sequence_number_to_retransmit_ =
550 rtc::Optional<uint16_t>(header.sequenceNumber);
551
552 // Don't ask for retransmission straight away, may be deduped in pacer.
553 } else if (header.sequenceNumber == *sequence_number_to_retransmit_) {
554 observation_complete_.Set();
555 } else {
556 // Send a NACK as often as necessary until retransmission is received.
557 rtcp::Nack nack;
danilchap822a16f2016-09-27 09:27:47 -0700558 nack.SetSenderSsrc(local_ssrc_);
559 nack.SetMediaSsrc(remote_ssrc_);
Erik Språng737336d2016-07-29 12:59:36 +0200560 uint16_t nack_list[] = {*sequence_number_to_retransmit_};
danilchap822a16f2016-09-27 09:27:47 -0700561 nack.SetPacketIds(nack_list, 1);
Erik Språng737336d2016-07-29 12:59:36 +0200562 rtc::Buffer buffer = nack.Build();
563
564 EXPECT_TRUE(receive_transport_->SendRtcp(buffer.data(), buffer.size()));
565 }
566
567 return SEND_PACKET;
568 }
569
570 void ModifyAudioConfigs(
571 AudioSendStream::Config* send_config,
572 std::vector<AudioReceiveStream::Config>* receive_configs) override {
573 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
574 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
575 local_ssrc_ = (*receive_configs)[0].rtp.local_ssrc;
576 remote_ssrc_ = (*receive_configs)[0].rtp.remote_ssrc;
577 }
578
579 void PerformTest() override {
580 EXPECT_TRUE(Wait())
581 << "Timed out waiting for packets to be NACKed, retransmitted and "
582 "rendered.";
583 }
584
585 uint32_t local_ssrc_;
586 uint32_t remote_ssrc_;
587 Transport* receive_transport_;
588 rtc::Optional<uint16_t> sequence_number_to_retransmit_;
589 } test;
590
591 RunBaseTest(&test);
592}
593
brandtrc55f27a2017-03-20 06:32:59 -0700594TEST_F(EndToEndTest, ReceivesUlpfec) {
brandtr535830e2016-10-31 03:45:58 -0700595 class UlpfecRenderObserver : public test::EndToEndTest,
596 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000597 public:
brandtr535830e2016-10-31 03:45:58 -0700598 UlpfecRenderObserver()
brandtr1134b7b2017-02-06 06:35:47 -0800599 : EndToEndTest(kDefaultTimeoutMs),
brandtrc55f27a2017-03-20 06:32:59 -0700600 encoder_(VP8Encoder::Create()),
brandtr1134b7b2017-02-06 06:35:47 -0800601 random_(0xcafef00d1),
602 num_packets_sent_(0) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000603
604 private:
stefanf116bd02015-10-27 08:29:42 -0700605 Action OnSendRtp(const uint8_t* packet, size_t length) override {
606 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000607 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000608 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000609
brandtrc55f27a2017-03-20 06:32:59 -0700610 EXPECT_TRUE(header.payloadType == kVideoSendPayloadType ||
brandtr1134b7b2017-02-06 06:35:47 -0800611 header.payloadType == kRedPayloadType)
612 << "Unknown payload type received.";
613 EXPECT_EQ(kVideoSendSsrcs[0], header.ssrc) << "Unknown SSRC received.";
614
615 // Parse RED header.
Stefan Holmer01b48882015-05-05 10:21:24 +0200616 int encapsulated_payload_type = -1;
617 if (header.payloadType == kRedPayloadType) {
618 encapsulated_payload_type =
619 static_cast<int>(packet[header.headerLength]);
brandtr1134b7b2017-02-06 06:35:47 -0800620
brandtrc55f27a2017-03-20 06:32:59 -0700621 EXPECT_TRUE(encapsulated_payload_type == kVideoSendPayloadType ||
brandtr1134b7b2017-02-06 06:35:47 -0800622 encapsulated_payload_type == kUlpfecPayloadType)
623 << "Unknown encapsulated payload type received.";
Stefan Holmer01b48882015-05-05 10:21:24 +0200624 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000625
brandtrc55f27a2017-03-20 06:32:59 -0700626 // To minimize test flakiness, always let ULPFEC packets through.
brandtr1134b7b2017-02-06 06:35:47 -0800627 if (encapsulated_payload_type == kUlpfecPayloadType) {
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000628 return SEND_PACKET;
629 }
630
brandtr1134b7b2017-02-06 06:35:47 -0800631 // Simulate 5% video packet loss after rampup period. Record the
632 // corresponding timestamps that were dropped.
633 if (num_packets_sent_++ > 100 && random_.Rand(1, 100) <= 5) {
brandtrc55f27a2017-03-20 06:32:59 -0700634 if (encapsulated_payload_type == kVideoSendPayloadType) {
brandtr1134b7b2017-02-06 06:35:47 -0800635 dropped_sequence_numbers_.insert(header.sequenceNumber);
636 dropped_timestamps_.insert(header.timestamp);
637 }
brandtr1134b7b2017-02-06 06:35:47 -0800638 return DROP_PACKET;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000639 }
640
641 return SEND_PACKET;
642 }
643
nisseeb83a1a2016-03-21 01:27:56 -0700644 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200645 rtc::CritScope lock(&crit_);
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000646 // Rendering frame with timestamp of packet that was dropped -> FEC
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000647 // protection worked.
brandtr1134b7b2017-02-06 06:35:47 -0800648 auto it = dropped_timestamps_.find(video_frame.timestamp());
649 if (it != dropped_timestamps_.end()) {
Peter Boström5811a392015-12-10 13:02:50 +0100650 observation_complete_.Set();
brandtr1134b7b2017-02-06 06:35:47 -0800651 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000652 }
653
stefanff483612015-12-21 03:14:00 -0800654 void ModifyVideoConfigs(
655 VideoSendStream::Config* send_config,
656 std::vector<VideoReceiveStream::Config>* receive_configs,
657 VideoEncoderConfig* encoder_config) override {
brandtrc55f27a2017-03-20 06:32:59 -0700658 // Use VP8 instead of FAKE, since the latter does not have PictureID
659 // in the packetization headers.
660 send_config->encoder_settings.encoder = encoder_.get();
661 send_config->encoder_settings.payload_name = "VP8";
662 send_config->encoder_settings.payload_type = kVideoSendPayloadType;
663 VideoReceiveStream::Decoder decoder =
664 test::CreateMatchingDecoder(send_config->encoder_settings);
665 decoder_.reset(decoder.decoder);
666 (*receive_configs)[0].decoders.clear();
667 (*receive_configs)[0].decoders.push_back(decoder);
668
669 // Enable ULPFEC over RED.
brandtrb5f2c3f2016-10-04 23:28:39 -0700670 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
671 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
brandtrb5f2c3f2016-10-04 23:28:39 -0700672 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
673 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
brandtrc55f27a2017-03-20 06:32:59 -0700674
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000675 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000676 }
677
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000678 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100679 EXPECT_TRUE(Wait())
brandtr1e3dfbf2016-11-16 22:45:19 -0800680 << "Timed out waiting for dropped frames to be rendered.";
681 }
682
683 rtc::CriticalSection crit_;
brandtrc55f27a2017-03-20 06:32:59 -0700684 std::unique_ptr<VideoEncoder> encoder_;
685 std::unique_ptr<VideoDecoder> decoder_;
brandtr1134b7b2017-02-06 06:35:47 -0800686 std::set<uint32_t> dropped_sequence_numbers_ GUARDED_BY(crit_);
687 // Several packets can have the same timestamp.
688 std::multiset<uint32_t> dropped_timestamps_ GUARDED_BY(crit_);
689 Random random_;
brandtrc55f27a2017-03-20 06:32:59 -0700690 int num_packets_sent_ GUARDED_BY(crit_);
brandtr1e3dfbf2016-11-16 22:45:19 -0800691 } test;
692
693 RunBaseTest(&test);
694}
695
brandtrfa5a3682017-01-17 01:33:54 -0800696class FlexfecRenderObserver : public test::EndToEndTest,
697 public rtc::VideoSinkInterface<VideoFrame> {
698 public:
699 static constexpr uint32_t kVideoLocalSsrc = 123;
700 static constexpr uint32_t kFlexfecLocalSsrc = 456;
brandtr1e3dfbf2016-11-16 22:45:19 -0800701
brandtr1134b7b2017-02-06 06:35:47 -0800702 explicit FlexfecRenderObserver(bool enable_nack, bool expect_flexfec_rtcp)
brandtrfa5a3682017-01-17 01:33:54 -0800703 : test::EndToEndTest(test::CallTest::kDefaultTimeoutMs),
brandtr1134b7b2017-02-06 06:35:47 -0800704 enable_nack_(enable_nack),
brandtrfa5a3682017-01-17 01:33:54 -0800705 expect_flexfec_rtcp_(expect_flexfec_rtcp),
706 received_flexfec_rtcp_(false),
brandtr1134b7b2017-02-06 06:35:47 -0800707 random_(0xcafef00d1),
708 num_packets_sent_(0) {}
brandtr1e3dfbf2016-11-16 22:45:19 -0800709
brandtrfa5a3682017-01-17 01:33:54 -0800710 size_t GetNumFlexfecStreams() const override { return 1; }
brandtr1e3dfbf2016-11-16 22:45:19 -0800711
brandtrfa5a3682017-01-17 01:33:54 -0800712 private:
713 Action OnSendRtp(const uint8_t* packet, size_t length) override {
714 rtc::CritScope lock(&crit_);
715 RTPHeader header;
716 EXPECT_TRUE(parser_->Parse(packet, length, &header));
brandtr1e3dfbf2016-11-16 22:45:19 -0800717
brandtr1134b7b2017-02-06 06:35:47 -0800718 EXPECT_TRUE(header.payloadType ==
719 test::CallTest::kFakeVideoSendPayloadType ||
720 header.payloadType == test::CallTest::kFlexfecPayloadType ||
721 (enable_nack_ &&
722 header.payloadType == test::CallTest::kSendRtxPayloadType))
723 << "Unknown payload type received.";
724 EXPECT_TRUE(
725 header.ssrc == test::CallTest::kVideoSendSsrcs[0] ||
726 header.ssrc == test::CallTest::kFlexfecSendSsrc ||
727 (enable_nack_ && header.ssrc == test::CallTest::kSendRtxSsrcs[0]))
728 << "Unknown SSRC received.";
729
730 // To reduce test flakiness, always let FlexFEC packets through.
731 if (header.payloadType == test::CallTest::kFlexfecPayloadType) {
732 EXPECT_EQ(test::CallTest::kFlexfecSendSsrc, header.ssrc);
733
734 return SEND_PACKET;
brandtr1e3dfbf2016-11-16 22:45:19 -0800735 }
736
brandtr1134b7b2017-02-06 06:35:47 -0800737 // To reduce test flakiness, always let RTX packets through.
738 if (header.payloadType == test::CallTest::kSendRtxPayloadType) {
739 EXPECT_EQ(test::CallTest::kSendRtxSsrcs[0], header.ssrc);
740
741 // Parse RTX header.
742 uint16_t original_sequence_number =
743 ByteReader<uint16_t>::ReadBigEndian(&packet[header.headerLength]);
744
745 // From the perspective of FEC, a retransmitted packet is no longer
746 // dropped, so remove it from list of dropped packets.
747 auto seq_num_it =
748 dropped_sequence_numbers_.find(original_sequence_number);
brandtrfa5a3682017-01-17 01:33:54 -0800749 if (seq_num_it != dropped_sequence_numbers_.end()) {
750 dropped_sequence_numbers_.erase(seq_num_it);
751 auto ts_it = dropped_timestamps_.find(header.timestamp);
752 EXPECT_NE(ts_it, dropped_timestamps_.end());
753 dropped_timestamps_.erase(ts_it);
brandtrfd8d2652017-02-06 06:19:51 -0800754 }
brandtr1134b7b2017-02-06 06:35:47 -0800755
756 return SEND_PACKET;
brandtrfa5a3682017-01-17 01:33:54 -0800757 }
758
brandtr1134b7b2017-02-06 06:35:47 -0800759 // Simulate 5% video packet loss after rampup period. Record the
760 // corresponding timestamps that were dropped.
761 if (num_packets_sent_++ > 100 && random_.Rand(1, 100) <= 5) {
762 EXPECT_EQ(test::CallTest::kFakeVideoSendPayloadType, header.payloadType);
763 EXPECT_EQ(test::CallTest::kVideoSendSsrcs[0], header.ssrc);
764
765 dropped_sequence_numbers_.insert(header.sequenceNumber);
766 dropped_timestamps_.insert(header.timestamp);
brandtrfa5a3682017-01-17 01:33:54 -0800767
768 return DROP_PACKET;
769 }
770
771 return SEND_PACKET;
772 }
773
774 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
775 test::RtcpPacketParser parser;
776
777 parser.Parse(data, length);
778 if (parser.sender_ssrc() == kFlexfecLocalSsrc) {
779 EXPECT_EQ(1, parser.receiver_report()->num_packets());
780 const std::vector<rtcp::ReportBlock>& report_blocks =
781 parser.receiver_report()->report_blocks();
782 if (!report_blocks.empty()) {
783 EXPECT_EQ(1U, report_blocks.size());
784 EXPECT_EQ(test::CallTest::kFlexfecSendSsrc,
785 report_blocks[0].source_ssrc());
brandtr1d2d7892017-01-18 00:40:07 -0800786 rtc::CritScope lock(&crit_);
brandtrfa5a3682017-01-17 01:33:54 -0800787 received_flexfec_rtcp_ = true;
788 }
789 }
790
791 return SEND_PACKET;
792 }
793
brandtr1134b7b2017-02-06 06:35:47 -0800794 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
795 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
796 const int kNetworkDelayMs = 100;
797 FakeNetworkPipe::Config config;
798 config.queue_delay_ms = kNetworkDelayMs;
799 return new test::PacketTransport(sender_call, this,
nissee5ad5ca2017-03-29 23:57:43 -0700800 test::PacketTransport::kSender,
801 MediaType::VIDEO, config);
brandtr1134b7b2017-02-06 06:35:47 -0800802 }
803
brandtrfa5a3682017-01-17 01:33:54 -0800804 void OnFrame(const VideoFrame& video_frame) override {
805 rtc::CritScope lock(&crit_);
806 // Rendering frame with timestamp of packet that was dropped -> FEC
807 // protection worked.
808 auto it = dropped_timestamps_.find(video_frame.timestamp());
809 if (it != dropped_timestamps_.end()) {
810 if (!expect_flexfec_rtcp_ || received_flexfec_rtcp_) {
brandtr1e3dfbf2016-11-16 22:45:19 -0800811 observation_complete_.Set();
brandtrfa5a3682017-01-17 01:33:54 -0800812 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800813 }
brandtrfa5a3682017-01-17 01:33:54 -0800814 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800815
brandtrfa5a3682017-01-17 01:33:54 -0800816 void ModifyVideoConfigs(
817 VideoSendStream::Config* send_config,
818 std::vector<VideoReceiveStream::Config>* receive_configs,
819 VideoEncoderConfig* encoder_config) override {
820 (*receive_configs)[0].rtp.local_ssrc = kVideoLocalSsrc;
821 (*receive_configs)[0].renderer = this;
brandtr1134b7b2017-02-06 06:35:47 -0800822
823 if (enable_nack_) {
824 send_config->rtp.nack.rtp_history_ms = test::CallTest::kNackRtpHistoryMs;
825 send_config->rtp.ulpfec.red_rtx_payload_type =
826 test::CallTest::kRtxRedPayloadType;
827 send_config->rtp.rtx.ssrcs.push_back(test::CallTest::kSendRtxSsrcs[0]);
828 send_config->rtp.rtx.payload_type = test::CallTest::kSendRtxPayloadType;
829
830 (*receive_configs)[0].rtp.nack.rtp_history_ms =
831 test::CallTest::kNackRtpHistoryMs;
832 (*receive_configs)[0].rtp.ulpfec.red_rtx_payload_type =
833 test::CallTest::kRtxRedPayloadType;
834
835 (*receive_configs)[0].rtp.rtx_ssrc = test::CallTest::kSendRtxSsrcs[0];
836 (*receive_configs)[0]
837 .rtp.rtx_payload_types[test::CallTest::kVideoSendPayloadType] =
838 test::CallTest::kSendRtxPayloadType;
839 }
brandtrfa5a3682017-01-17 01:33:54 -0800840 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800841
brandtrfa5a3682017-01-17 01:33:54 -0800842 void ModifyFlexfecConfigs(
843 std::vector<FlexfecReceiveStream::Config>* receive_configs) override {
844 (*receive_configs)[0].local_ssrc = kFlexfecLocalSsrc;
845 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000846
brandtrfa5a3682017-01-17 01:33:54 -0800847 void PerformTest() override {
848 EXPECT_TRUE(Wait())
849 << "Timed out waiting for dropped frames to be rendered.";
850 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000851
brandtrfa5a3682017-01-17 01:33:54 -0800852 rtc::CriticalSection crit_;
853 std::set<uint32_t> dropped_sequence_numbers_ GUARDED_BY(crit_);
brandtr1134b7b2017-02-06 06:35:47 -0800854 // Several packets can have the same timestamp.
brandtrfa5a3682017-01-17 01:33:54 -0800855 std::multiset<uint32_t> dropped_timestamps_ GUARDED_BY(crit_);
brandtr1134b7b2017-02-06 06:35:47 -0800856 const bool enable_nack_;
brandtr1d2d7892017-01-18 00:40:07 -0800857 const bool expect_flexfec_rtcp_;
858 bool received_flexfec_rtcp_ GUARDED_BY(crit_);
brandtrfa5a3682017-01-17 01:33:54 -0800859 Random random_;
brandtr1134b7b2017-02-06 06:35:47 -0800860 int num_packets_sent_;
brandtrfa5a3682017-01-17 01:33:54 -0800861};
862
philipel277a8b52017-03-16 05:19:49 -0700863TEST_F(EndToEndTest, RecoversWithFlexfec) {
brandtr1134b7b2017-02-06 06:35:47 -0800864 FlexfecRenderObserver test(false, false);
brandtrfa5a3682017-01-17 01:33:54 -0800865 RunBaseTest(&test);
866}
867
philipel277a8b52017-03-16 05:19:49 -0700868TEST_F(EndToEndTest, RecoversWithFlexfecAndNack) {
brandtr1134b7b2017-02-06 06:35:47 -0800869 FlexfecRenderObserver test(true, false);
870 RunBaseTest(&test);
871}
872
philipel277a8b52017-03-16 05:19:49 -0700873TEST_F(EndToEndTest, RecoversWithFlexfecAndSendsCorrespondingRtcp) {
brandtr1134b7b2017-02-06 06:35:47 -0800874 FlexfecRenderObserver test(false, true);
stefane74eef12016-01-08 06:47:13 -0800875 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000876}
877
philipel277a8b52017-03-16 05:19:49 -0700878TEST_F(EndToEndTest, ReceivedUlpfecPacketsNotNacked) {
brandtr535830e2016-10-31 03:45:58 -0700879 class UlpfecNackObserver : public test::EndToEndTest {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000880 public:
brandtr535830e2016-10-31 03:45:58 -0700881 UlpfecNackObserver()
stefanf116bd02015-10-27 08:29:42 -0700882 : EndToEndTest(kDefaultTimeoutMs),
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000883 state_(kFirstPacket),
brandtr535830e2016-10-31 03:45:58 -0700884 ulpfec_sequence_number_(0),
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000885 has_last_sequence_number_(false),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200886 last_sequence_number_(0),
magjed509e4fe2016-11-18 01:34:11 -0800887 encoder_(VP8Encoder::Create()),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200888 decoder_(VP8Decoder::Create()) {}
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000889
890 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000891 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800892 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000893 RTPHeader header;
894 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000895
Stefan Holmer01b48882015-05-05 10:21:24 +0200896 int encapsulated_payload_type = -1;
897 if (header.payloadType == kRedPayloadType) {
898 encapsulated_payload_type =
899 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100900 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200901 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
902 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100903 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200904 }
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000905
906 if (has_last_sequence_number_ &&
907 !IsNewerSequenceNumber(header.sequenceNumber,
908 last_sequence_number_)) {
909 // Drop retransmitted packets.
910 return DROP_PACKET;
911 }
912 last_sequence_number_ = header.sequenceNumber;
913 has_last_sequence_number_ = true;
914
brandtr535830e2016-10-31 03:45:58 -0700915 bool ulpfec_packet = encapsulated_payload_type == kUlpfecPayloadType;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000916 switch (state_) {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000917 case kFirstPacket:
brandtr535830e2016-10-31 03:45:58 -0700918 state_ = kDropEveryOtherPacketUntilUlpfec;
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000919 break;
brandtr535830e2016-10-31 03:45:58 -0700920 case kDropEveryOtherPacketUntilUlpfec:
921 if (ulpfec_packet) {
922 state_ = kDropAllMediaPacketsUntilUlpfec;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000923 } else if (header.sequenceNumber % 2 == 0) {
924 return DROP_PACKET;
925 }
926 break;
brandtr535830e2016-10-31 03:45:58 -0700927 case kDropAllMediaPacketsUntilUlpfec:
928 if (!ulpfec_packet)
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000929 return DROP_PACKET;
brandtr535830e2016-10-31 03:45:58 -0700930 ulpfec_sequence_number_ = header.sequenceNumber;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200931 state_ = kDropOneMediaPacket;
932 break;
933 case kDropOneMediaPacket:
brandtr535830e2016-10-31 03:45:58 -0700934 if (ulpfec_packet)
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200935 return DROP_PACKET;
936 state_ = kPassOneMediaPacket;
937 return DROP_PACKET;
938 break;
939 case kPassOneMediaPacket:
brandtr535830e2016-10-31 03:45:58 -0700940 if (ulpfec_packet)
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200941 return DROP_PACKET;
942 // Pass one media packet after dropped packet after last FEC,
943 // otherwise receiver might never see a seq_no after
brandtr535830e2016-10-31 03:45:58 -0700944 // |ulpfec_sequence_number_|
945 state_ = kVerifyUlpfecPacketNotInNackList;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000946 break;
brandtr535830e2016-10-31 03:45:58 -0700947 case kVerifyUlpfecPacketNotInNackList:
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000948 // Continue to drop packets. Make sure no frame can be decoded.
brandtr535830e2016-10-31 03:45:58 -0700949 if (ulpfec_packet || header.sequenceNumber % 2 == 0)
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000950 return DROP_PACKET;
951 break;
952 }
953 return SEND_PACKET;
954 }
955
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000956 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800957 rtc::CritScope lock_(&crit_);
brandtr535830e2016-10-31 03:45:58 -0700958 if (state_ == kVerifyUlpfecPacketNotInNackList) {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000959 test::RtcpPacketParser rtcp_parser;
960 rtcp_parser.Parse(packet, length);
Danil Chapovalovba6f7be2016-09-02 18:29:10 +0200961 const std::vector<uint16_t>& nacks = rtcp_parser.nack()->packet_ids();
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200962 EXPECT_TRUE(std::find(nacks.begin(), nacks.end(),
brandtr535830e2016-10-31 03:45:58 -0700963 ulpfec_sequence_number_) == nacks.end())
964 << "Got nack for ULPFEC packet";
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000965 if (!nacks.empty() &&
brandtr535830e2016-10-31 03:45:58 -0700966 IsNewerSequenceNumber(nacks.back(), ulpfec_sequence_number_)) {
Peter Boström5811a392015-12-10 13:02:50 +0100967 observation_complete_.Set();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000968 }
969 }
970 return SEND_PACKET;
971 }
972
stefane74eef12016-01-08 06:47:13 -0800973 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
974 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
975 // Configure some network delay.
976 const int kNetworkDelayMs = 50;
977 FakeNetworkPipe::Config config;
978 config.queue_delay_ms = kNetworkDelayMs;
979 return new test::PacketTransport(sender_call, this,
nissee5ad5ca2017-03-29 23:57:43 -0700980 test::PacketTransport::kSender,
981 MediaType::VIDEO, config);
stefane74eef12016-01-08 06:47:13 -0800982 }
983
Stefan Holmere5904162015-03-26 11:11:06 +0100984 // TODO(holmer): Investigate why we don't send FEC packets when the bitrate
985 // is 10 kbps.
986 Call::Config GetSenderCallConfig() override {
skvlad11a9cbf2016-10-07 11:53:05 -0700987 Call::Config config(&event_log_);
Stefan Holmere5904162015-03-26 11:11:06 +0100988 const int kMinBitrateBps = 30000;
989 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
990 return config;
991 }
992
stefanff483612015-12-21 03:14:00 -0800993 void ModifyVideoConfigs(
994 VideoSendStream::Config* send_config,
995 std::vector<VideoReceiveStream::Config>* receive_configs,
996 VideoEncoderConfig* encoder_config) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000997 // Configure hybrid NACK/FEC.
998 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
brandtrb5f2c3f2016-10-04 23:28:39 -0700999 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
1000 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001001 // Set codec to VP8, otherwise NACK/FEC hybrid will be disabled.
1002 send_config->encoder_settings.encoder = encoder_.get();
1003 send_config->encoder_settings.payload_name = "VP8";
1004 send_config->encoder_settings.payload_type = kFakeVideoSendPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001005
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001006 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
brandtrb5f2c3f2016-10-04 23:28:39 -07001007 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
1008 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001009
1010 (*receive_configs)[0].decoders.resize(1);
1011 (*receive_configs)[0].decoders[0].payload_type =
1012 send_config->encoder_settings.payload_type;
1013 (*receive_configs)[0].decoders[0].payload_name =
1014 send_config->encoder_settings.payload_name;
1015 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001016 }
1017
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001018 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001019 EXPECT_TRUE(Wait())
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001020 << "Timed out while waiting for FEC packets to be received.";
1021 }
1022
1023 enum {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +00001024 kFirstPacket,
brandtr535830e2016-10-31 03:45:58 -07001025 kDropEveryOtherPacketUntilUlpfec,
1026 kDropAllMediaPacketsUntilUlpfec,
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001027 kDropOneMediaPacket,
1028 kPassOneMediaPacket,
brandtr535830e2016-10-31 03:45:58 -07001029 kVerifyUlpfecPacketNotInNackList,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001030 } state_;
1031
stefan608213e2015-11-01 14:56:10 -08001032 rtc::CriticalSection crit_;
brandtr535830e2016-10-31 03:45:58 -07001033 uint16_t ulpfec_sequence_number_ GUARDED_BY(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001034 bool has_last_sequence_number_;
1035 uint16_t last_sequence_number_;
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001036 std::unique_ptr<webrtc::VideoEncoder> encoder_;
1037 std::unique_ptr<webrtc::VideoDecoder> decoder_;
stefanf116bd02015-10-27 08:29:42 -07001038 } test;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001039
stefane74eef12016-01-08 06:47:13 -08001040 RunBaseTest(&test);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001041}
1042
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001043// This test drops second RTP packet with a marker bit set, makes sure it's
1044// retransmitted and renders. Retransmission SSRCs are also checked.
Peter Boström39593972016-02-15 11:27:15 +01001045void EndToEndTest::DecodesRetransmittedFrame(bool enable_rtx, bool enable_red) {
Peter Boström67680c12016-02-17 11:10:04 +01001046 static const int kDroppedFrameNumber = 10;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001047 class RetransmissionObserver : public test::EndToEndTest,
nisse76bc8e82017-02-07 09:37:41 -08001048 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001049 public:
Peter Boström39593972016-02-15 11:27:15 +01001050 RetransmissionObserver(bool enable_rtx, bool enable_red)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001051 : EndToEndTest(kDefaultTimeoutMs),
Peter Boström39593972016-02-15 11:27:15 +01001052 payload_type_(GetPayloadType(false, enable_red)),
1053 retransmission_ssrc_(enable_rtx ? kSendRtxSsrcs[0]
1054 : kVideoSendSsrcs[0]),
1055 retransmission_payload_type_(GetPayloadType(enable_rtx, enable_red)),
magjed509e4fe2016-11-18 01:34:11 -08001056 encoder_(VP8Encoder::Create()),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001057 marker_bits_observed_(0),
danilchap192717e2016-07-25 08:20:51 -07001058 retransmitted_timestamp_(0) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001059
1060 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001061 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001062 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001063 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001064 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001065
Peter Boström67680c12016-02-17 11:10:04 +01001066 // Ignore padding-only packets over RTX.
1067 if (header.payloadType != payload_type_) {
1068 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
1069 if (length == header.headerLength + header.paddingLength)
1070 return SEND_PACKET;
Stefan Holmer586b19b2015-09-18 11:14:31 +02001071 }
Peter Boström67680c12016-02-17 11:10:04 +01001072
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001073 if (header.timestamp == retransmitted_timestamp_) {
1074 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
1075 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001076 return SEND_PACKET;
1077 }
1078
Stefan Holmer586b19b2015-09-18 11:14:31 +02001079 // Found the final packet of the frame to inflict loss to, drop this and
1080 // expect a retransmission.
danilchapfdd381c2016-07-25 04:03:20 -07001081 if (header.payloadType == payload_type_ && header.markerBit &&
1082 ++marker_bits_observed_ == kDroppedFrameNumber) {
Danil Chapovalov18c65a42016-06-29 15:29:34 +02001083 // This should be the only dropped packet.
1084 EXPECT_EQ(0u, retransmitted_timestamp_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001085 retransmitted_timestamp_ = header.timestamp;
danilchap192717e2016-07-25 08:20:51 -07001086 if (std::find(rendered_timestamps_.begin(), rendered_timestamps_.end(),
1087 retransmitted_timestamp_) != rendered_timestamps_.end()) {
1088 // Frame was rendered before last packet was scheduled for sending.
1089 // This is extremly rare but possible scenario because prober able to
1090 // resend packet before it was send.
1091 // TODO(danilchap): Remove this corner case when prober would not be
1092 // able to sneak in between packet saved to history for resending and
1093 // pacer notified about existance of that packet for sending.
1094 // See https://bugs.chromium.org/p/webrtc/issues/detail?id=5540 for
1095 // details.
1096 observation_complete_.Set();
1097 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001098 return DROP_PACKET;
1099 }
1100
1101 return SEND_PACKET;
1102 }
1103
nisse76bc8e82017-02-07 09:37:41 -08001104 void OnFrame(const VideoFrame& frame) override {
stefan5d837802017-02-08 07:09:05 -08001105 {
1106 rtc::CritScope lock(&crit_);
1107 if (frame.timestamp() == retransmitted_timestamp_)
1108 observation_complete_.Set();
1109 rendered_timestamps_.push_back(frame.timestamp());
1110 }
nisse76bc8e82017-02-07 09:37:41 -08001111 orig_renderer_->OnFrame(frame);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001112 }
1113
stefanff483612015-12-21 03:14:00 -08001114 void ModifyVideoConfigs(
1115 VideoSendStream::Config* send_config,
1116 std::vector<VideoReceiveStream::Config>* receive_configs,
1117 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001118 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
nisse76bc8e82017-02-07 09:37:41 -08001119
1120 // Insert ourselves into the rendering pipeline.
1121 RTC_DCHECK(!orig_renderer_);
1122 orig_renderer_ = (*receive_configs)[0].renderer;
1123 RTC_DCHECK(orig_renderer_);
stefan5d837802017-02-08 07:09:05 -08001124 (*receive_configs)[0].disable_prerenderer_smoothing = true;
nisse76bc8e82017-02-07 09:37:41 -08001125 (*receive_configs)[0].renderer = this;
1126
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001127 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
Shao Changbine62202f2015-04-21 20:24:50 +08001128
1129 if (payload_type_ == kRedPayloadType) {
brandtrb5f2c3f2016-10-04 23:28:39 -07001130 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
1131 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +01001132 if (retransmission_ssrc_ == kSendRtxSsrcs[0])
brandtrb5f2c3f2016-10-04 23:28:39 -07001133 send_config->rtp.ulpfec.red_rtx_payload_type = kRtxRedPayloadType;
1134 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type =
1135 send_config->rtp.ulpfec.ulpfec_payload_type;
1136 (*receive_configs)[0].rtp.ulpfec.red_payload_type =
1137 send_config->rtp.ulpfec.red_payload_type;
1138 (*receive_configs)[0].rtp.ulpfec.red_rtx_payload_type =
1139 send_config->rtp.ulpfec.red_rtx_payload_type;
Shao Changbine62202f2015-04-21 20:24:50 +08001140 }
1141
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001142 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
1143 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001144 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
brandtr14742122017-01-27 04:53:07 -08001145 (*receive_configs)[0].rtp.rtx_ssrc = kSendRtxSsrcs[0];
1146 (*receive_configs)[0].rtp.rtx_payload_types[payload_type_] =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001147 kSendRtxPayloadType;
1148 }
Peter Boström39593972016-02-15 11:27:15 +01001149 // Configure encoding and decoding with VP8, since generic packetization
1150 // doesn't support FEC with NACK.
kwibergaf476c72016-11-28 15:21:39 -08001151 RTC_DCHECK_EQ(1, (*receive_configs)[0].decoders.size());
Peter Boström39593972016-02-15 11:27:15 +01001152 send_config->encoder_settings.encoder = encoder_.get();
1153 send_config->encoder_settings.payload_name = "VP8";
1154 (*receive_configs)[0].decoders[0].payload_name = "VP8";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001155 }
1156
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001157 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001158 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001159 << "Timed out while waiting for retransmission to render.";
1160 }
1161
Shao Changbine62202f2015-04-21 20:24:50 +08001162 int GetPayloadType(bool use_rtx, bool use_red) {
Stefan Holmer10880012016-02-03 13:29:59 +01001163 if (use_red) {
1164 if (use_rtx)
1165 return kRtxRedPayloadType;
1166 return kRedPayloadType;
1167 }
1168 if (use_rtx)
1169 return kSendRtxPayloadType;
1170 return kFakeVideoSendPayloadType;
Shao Changbine62202f2015-04-21 20:24:50 +08001171 }
1172
stefanf116bd02015-10-27 08:29:42 -07001173 rtc::CriticalSection crit_;
nisse76bc8e82017-02-07 09:37:41 -08001174 rtc::VideoSinkInterface<VideoFrame>* orig_renderer_ = nullptr;
Shao Changbine62202f2015-04-21 20:24:50 +08001175 const int payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001176 const uint32_t retransmission_ssrc_;
1177 const int retransmission_payload_type_;
kwiberg27f982b2016-03-01 11:52:33 -08001178 std::unique_ptr<VideoEncoder> encoder_;
Peter Boström39593972016-02-15 11:27:15 +01001179 const std::string payload_name_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001180 int marker_bits_observed_;
stefanf116bd02015-10-27 08:29:42 -07001181 uint32_t retransmitted_timestamp_ GUARDED_BY(&crit_);
danilchap192717e2016-07-25 08:20:51 -07001182 std::vector<uint32_t> rendered_timestamps_ GUARDED_BY(&crit_);
Peter Boström39593972016-02-15 11:27:15 +01001183 } test(enable_rtx, enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001184
stefane74eef12016-01-08 06:47:13 -08001185 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001186}
1187
philipel277a8b52017-03-16 05:19:49 -07001188TEST_F(EndToEndTest, DecodesRetransmittedFrame) {
Shao Changbine62202f2015-04-21 20:24:50 +08001189 DecodesRetransmittedFrame(false, false);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001190}
1191
philipel277a8b52017-03-16 05:19:49 -07001192TEST_F(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +08001193 DecodesRetransmittedFrame(true, false);
1194}
1195
philipel277a8b52017-03-16 05:19:49 -07001196TEST_F(EndToEndTest, DecodesRetransmittedFrameByRed) {
Shao Changbine62202f2015-04-21 20:24:50 +08001197 DecodesRetransmittedFrame(false, true);
1198}
1199
philipel277a8b52017-03-16 05:19:49 -07001200TEST_F(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +08001201 DecodesRetransmittedFrame(true, true);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001202}
1203
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001204void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
1205 static const int kPacketsToDrop = 1;
1206
nisse7ade7b32016-03-23 04:48:10 -07001207 class PliObserver : public test::EndToEndTest,
1208 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001209 public:
1210 explicit PliObserver(int rtp_history_ms)
1211 : EndToEndTest(kLongTimeoutMs),
1212 rtp_history_ms_(rtp_history_ms),
1213 nack_enabled_(rtp_history_ms > 0),
1214 highest_dropped_timestamp_(0),
1215 frames_to_drop_(0),
1216 received_pli_(false) {}
1217
1218 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001219 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001220 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001221 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001222 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001223
1224 // Drop all retransmitted packets to force a PLI.
1225 if (header.timestamp <= highest_dropped_timestamp_)
1226 return DROP_PACKET;
1227
1228 if (frames_to_drop_ > 0) {
1229 highest_dropped_timestamp_ = header.timestamp;
1230 --frames_to_drop_;
1231 return DROP_PACKET;
1232 }
1233
1234 return SEND_PACKET;
1235 }
1236
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001237 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001238 rtc::CritScope lock(&crit_);
danilchap3dc929e2016-11-02 08:21:59 -07001239 test::RtcpPacketParser parser;
1240 EXPECT_TRUE(parser.Parse(packet, length));
1241 if (!nack_enabled_)
1242 EXPECT_EQ(0, parser.nack()->num_packets());
1243 if (parser.pli()->num_packets() > 0)
1244 received_pli_ = true;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001245 return SEND_PACKET;
1246 }
1247
nisseeb83a1a2016-03-21 01:27:56 -07001248 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001249 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001250 if (received_pli_ &&
1251 video_frame.timestamp() > highest_dropped_timestamp_) {
Peter Boström5811a392015-12-10 13:02:50 +01001252 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001253 }
1254 if (!received_pli_)
1255 frames_to_drop_ = kPacketsToDrop;
1256 }
1257
stefanff483612015-12-21 03:14:00 -08001258 void ModifyVideoConfigs(
1259 VideoSendStream::Config* send_config,
1260 std::vector<VideoReceiveStream::Config>* receive_configs,
1261 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001262 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001263 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
1264 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001265 }
1266
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001267 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001268 EXPECT_TRUE(Wait()) << "Timed out waiting for PLI to be "
1269 "received and a frame to be "
1270 "rendered afterwards.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001271 }
1272
stefanf116bd02015-10-27 08:29:42 -07001273 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001274 int rtp_history_ms_;
1275 bool nack_enabled_;
stefanf116bd02015-10-27 08:29:42 -07001276 uint32_t highest_dropped_timestamp_ GUARDED_BY(&crit_);
1277 int frames_to_drop_ GUARDED_BY(&crit_);
1278 bool received_pli_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001279 } test(rtp_history_ms);
1280
stefane74eef12016-01-08 06:47:13 -08001281 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001282}
1283
philipel277a8b52017-03-16 05:19:49 -07001284TEST_F(EndToEndTest, ReceivesPliAndRecoversWithNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001285 ReceivesPliAndRecovers(1000);
1286}
1287
philipel277a8b52017-03-16 05:19:49 -07001288TEST_F(EndToEndTest, ReceivesPliAndRecoversWithoutNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001289 ReceivesPliAndRecovers(0);
1290}
1291
philipel277a8b52017-03-16 05:19:49 -07001292TEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001293 class PacketInputObserver : public PacketReceiver {
1294 public:
1295 explicit PacketInputObserver(PacketReceiver* receiver)
Peter Boström5811a392015-12-10 13:02:50 +01001296 : receiver_(receiver), delivered_packet_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001297
Peter Boström5811a392015-12-10 13:02:50 +01001298 bool Wait() { return delivered_packet_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001299
1300 private:
stefan68786d22015-09-08 05:36:15 -07001301 DeliveryStatus DeliverPacket(MediaType media_type,
1302 const uint8_t* packet,
1303 size_t length,
1304 const PacketTime& packet_time) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001305 if (RtpHeaderParser::IsRtcp(packet, length)) {
stefan68786d22015-09-08 05:36:15 -07001306 return receiver_->DeliverPacket(media_type, packet, length,
1307 packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001308 } else {
1309 DeliveryStatus delivery_status =
stefan68786d22015-09-08 05:36:15 -07001310 receiver_->DeliverPacket(media_type, packet, length, packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001311 EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
Peter Boström5811a392015-12-10 13:02:50 +01001312 delivered_packet_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001313 return delivery_status;
1314 }
1315 }
1316
1317 PacketReceiver* receiver_;
Peter Boström5811a392015-12-10 13:02:50 +01001318 rtc::Event delivered_packet_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001319 };
1320
skvlad11a9cbf2016-10-07 11:53:05 -07001321 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -07001322
nissee5ad5ca2017-03-29 23:57:43 -07001323 test::DirectTransport send_transport(
1324 sender_call_.get(), MediaType::VIDEO);
1325 test::DirectTransport receive_transport(
1326 receiver_call_.get(), MediaType::VIDEO);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001327 PacketInputObserver input_observer(receiver_call_->Receiver());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001328 send_transport.SetReceiver(&input_observer);
1329 receive_transport.SetReceiver(sender_call_->Receiver());
1330
brandtr841de6a2016-11-15 07:10:52 -08001331 CreateSendConfig(1, 0, 0, &send_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001332 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001333
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001334 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07001335 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
1336 kDefaultHeight);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001337 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001338
stefanff483612015-12-21 03:14:00 -08001339 receiver_call_->DestroyVideoReceiveStream(video_receive_streams_[0]);
1340 video_receive_streams_.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001341
1342 // Wait() waits for a received packet.
Peter Boström5811a392015-12-10 13:02:50 +01001343 EXPECT_TRUE(input_observer.Wait());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001344
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001345 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001346
1347 DestroyStreams();
1348
1349 send_transport.StopSending();
1350 receive_transport.StopSending();
1351}
1352
pbosda903ea2015-10-02 02:36:56 -07001353void EndToEndTest::RespectsRtcpMode(RtcpMode rtcp_mode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001354 static const int kNumCompoundRtcpPacketsToObserve = 10;
1355 class RtcpModeObserver : public test::EndToEndTest {
1356 public:
pbosda903ea2015-10-02 02:36:56 -07001357 explicit RtcpModeObserver(RtcpMode rtcp_mode)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001358 : EndToEndTest(kDefaultTimeoutMs),
1359 rtcp_mode_(rtcp_mode),
1360 sent_rtp_(0),
1361 sent_rtcp_(0) {}
1362
1363 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001364 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanb77c7162017-02-06 06:29:38 -08001365 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001366 if (++sent_rtp_ % 3 == 0)
1367 return DROP_PACKET;
1368
1369 return SEND_PACKET;
1370 }
1371
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001372 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanb77c7162017-02-06 06:29:38 -08001373 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001374 ++sent_rtcp_;
danilchap3dc929e2016-11-02 08:21:59 -07001375 test::RtcpPacketParser parser;
1376 EXPECT_TRUE(parser.Parse(packet, length));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001377
danilchap3dc929e2016-11-02 08:21:59 -07001378 EXPECT_EQ(0, parser.sender_report()->num_packets());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001379
1380 switch (rtcp_mode_) {
pbosda903ea2015-10-02 02:36:56 -07001381 case RtcpMode::kCompound:
stefanb77c7162017-02-06 06:29:38 -08001382 // TODO(holmer): We shouldn't send transport feedback alone if
1383 // compound RTCP is negotiated.
1384 if (parser.receiver_report()->num_packets() == 0 &&
1385 parser.transport_feedback()->num_packets() == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001386 ADD_FAILURE() << "Received RTCP packet without receiver report for "
pbosda903ea2015-10-02 02:36:56 -07001387 "RtcpMode::kCompound.";
Peter Boström5811a392015-12-10 13:02:50 +01001388 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001389 }
1390
1391 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
Peter Boström5811a392015-12-10 13:02:50 +01001392 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001393
1394 break;
pbosda903ea2015-10-02 02:36:56 -07001395 case RtcpMode::kReducedSize:
danilchap3dc929e2016-11-02 08:21:59 -07001396 if (parser.receiver_report()->num_packets() == 0)
Peter Boström5811a392015-12-10 13:02:50 +01001397 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001398 break;
pbosda903ea2015-10-02 02:36:56 -07001399 case RtcpMode::kOff:
1400 RTC_NOTREACHED();
1401 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001402 }
1403
1404 return SEND_PACKET;
1405 }
1406
stefanff483612015-12-21 03:14:00 -08001407 void ModifyVideoConfigs(
1408 VideoSendStream::Config* send_config,
1409 std::vector<VideoReceiveStream::Config>* receive_configs,
1410 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001411 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001412 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1413 (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001414 }
1415
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001416 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001417 EXPECT_TRUE(Wait())
pbosda903ea2015-10-02 02:36:56 -07001418 << (rtcp_mode_ == RtcpMode::kCompound
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001419 ? "Timed out before observing enough compound packets."
1420 : "Timed out before receiving a non-compound RTCP packet.");
1421 }
1422
pbosda903ea2015-10-02 02:36:56 -07001423 RtcpMode rtcp_mode_;
stefanb77c7162017-02-06 06:29:38 -08001424 rtc::CriticalSection crit_;
1425 // Must be protected since RTCP can be sent by both the process thread
1426 // and the pacer thread.
1427 int sent_rtp_ GUARDED_BY(&crit_);
1428 int sent_rtcp_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001429 } test(rtcp_mode);
1430
stefane74eef12016-01-08 06:47:13 -08001431 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001432}
1433
philipel277a8b52017-03-16 05:19:49 -07001434TEST_F(EndToEndTest, UsesRtcpCompoundMode) {
pbosda903ea2015-10-02 02:36:56 -07001435 RespectsRtcpMode(RtcpMode::kCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001436}
1437
philipel277a8b52017-03-16 05:19:49 -07001438TEST_F(EndToEndTest, UsesRtcpReducedSizeMode) {
pbosda903ea2015-10-02 02:36:56 -07001439 RespectsRtcpMode(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001440}
1441
1442// Test sets up a Call multiple senders with different resolutions and SSRCs.
1443// Another is set up to receive all three of these with different renderers.
sprang867fb522015-08-03 04:38:41 -07001444class MultiStreamTest {
1445 public:
1446 static const size_t kNumStreams = 3;
1447 struct CodecSettings {
1448 uint32_t ssrc;
1449 int width;
1450 int height;
1451 } codec_settings[kNumStreams];
1452
1453 MultiStreamTest() {
1454 // TODO(sprang): Cleanup when msvc supports explicit initializers for array.
1455 codec_settings[0] = {1, 640, 480};
1456 codec_settings[1] = {2, 320, 240};
1457 codec_settings[2] = {3, 240, 160};
1458 }
1459
1460 virtual ~MultiStreamTest() {}
1461
1462 void RunTest() {
skvlad11a9cbf2016-10-07 11:53:05 -07001463 webrtc::RtcEventLogNullImpl event_log;
1464 Call::Config config(&event_log);
1465 std::unique_ptr<Call> sender_call(Call::Create(config));
1466 std::unique_ptr<Call> receiver_call(Call::Create(config));
kwiberg27f982b2016-03-01 11:52:33 -08001467 std::unique_ptr<test::DirectTransport> sender_transport(
stefanf116bd02015-10-27 08:29:42 -07001468 CreateSendTransport(sender_call.get()));
kwiberg27f982b2016-03-01 11:52:33 -08001469 std::unique_ptr<test::DirectTransport> receiver_transport(
stefanf116bd02015-10-27 08:29:42 -07001470 CreateReceiveTransport(receiver_call.get()));
sprang867fb522015-08-03 04:38:41 -07001471 sender_transport->SetReceiver(receiver_call->Receiver());
1472 receiver_transport->SetReceiver(sender_call->Receiver());
1473
kwiberg27f982b2016-03-01 11:52:33 -08001474 std::unique_ptr<VideoEncoder> encoders[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001475 for (size_t i = 0; i < kNumStreams; ++i)
magjed509e4fe2016-11-18 01:34:11 -08001476 encoders[i].reset(VP8Encoder::Create());
sprang867fb522015-08-03 04:38:41 -07001477
1478 VideoSendStream* send_streams[kNumStreams];
1479 VideoReceiveStream* receive_streams[kNumStreams];
1480
1481 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
kwiberg4a206a92016-03-31 10:24:26 -07001482 std::vector<std::unique_ptr<VideoDecoder>> allocated_decoders;
sprang867fb522015-08-03 04:38:41 -07001483 for (size_t i = 0; i < kNumStreams; ++i) {
1484 uint32_t ssrc = codec_settings[i].ssrc;
1485 int width = codec_settings[i].width;
1486 int height = codec_settings[i].height;
1487
solenberg4fbae2b2015-08-28 04:07:10 -07001488 VideoSendStream::Config send_config(sender_transport.get());
sprang867fb522015-08-03 04:38:41 -07001489 send_config.rtp.ssrcs.push_back(ssrc);
1490 send_config.encoder_settings.encoder = encoders[i].get();
1491 send_config.encoder_settings.payload_name = "VP8";
1492 send_config.encoder_settings.payload_type = 124;
1493 VideoEncoderConfig encoder_config;
perkjfa10b552016-10-02 23:45:26 -07001494 test::FillEncoderConfiguration(1, &encoder_config);
1495 encoder_config.max_bitrate_bps = 100000;
sprang867fb522015-08-03 04:38:41 -07001496
1497 UpdateSendConfig(i, &send_config, &encoder_config, &frame_generators[i]);
1498
perkj26091b12016-09-01 01:17:40 -07001499 send_streams[i] = sender_call->CreateVideoSendStream(
1500 send_config.Copy(), encoder_config.Copy());
sprang867fb522015-08-03 04:38:41 -07001501 send_streams[i]->Start();
1502
solenberg4fbae2b2015-08-28 04:07:10 -07001503 VideoReceiveStream::Config receive_config(receiver_transport.get());
sprang867fb522015-08-03 04:38:41 -07001504 receive_config.rtp.remote_ssrc = ssrc;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001505 receive_config.rtp.local_ssrc = test::CallTest::kReceiverLocalVideoSsrc;
sprang867fb522015-08-03 04:38:41 -07001506 VideoReceiveStream::Decoder decoder =
1507 test::CreateMatchingDecoder(send_config.encoder_settings);
kwiberg4a206a92016-03-31 10:24:26 -07001508 allocated_decoders.push_back(
1509 std::unique_ptr<VideoDecoder>(decoder.decoder));
sprang867fb522015-08-03 04:38:41 -07001510 receive_config.decoders.push_back(decoder);
1511
1512 UpdateReceiveConfig(i, &receive_config);
1513
1514 receive_streams[i] =
Tommi733b5472016-06-10 17:58:01 +02001515 receiver_call->CreateVideoReceiveStream(std::move(receive_config));
sprang867fb522015-08-03 04:38:41 -07001516 receive_streams[i]->Start();
1517
1518 frame_generators[i] = test::FrameGeneratorCapturer::Create(
perkja49cbd32016-09-16 07:53:41 -07001519 width, height, 30, Clock::GetRealTimeClock());
perkj803d97f2016-11-01 11:45:46 -07001520 send_streams[i]->SetSource(
1521 frame_generators[i],
sprangc5d62e22017-04-02 23:53:04 -07001522 VideoSendStream::DegradationPreference::kMaintainFramerate);
sprang867fb522015-08-03 04:38:41 -07001523 frame_generators[i]->Start();
1524 }
1525
1526 Wait();
1527
1528 for (size_t i = 0; i < kNumStreams; ++i) {
1529 frame_generators[i]->Stop();
1530 sender_call->DestroyVideoSendStream(send_streams[i]);
1531 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1532 delete frame_generators[i];
1533 }
1534
1535 sender_transport->StopSending();
1536 receiver_transport->StopSending();
1537 }
1538
1539 protected:
1540 virtual void Wait() = 0;
1541 // Note: frame_generator is a point-to-pointer, since the actual instance
1542 // hasn't been created at the time of this call. Only when packets/frames
1543 // start flowing should this be dereferenced.
1544 virtual void UpdateSendConfig(
1545 size_t stream_index,
1546 VideoSendStream::Config* send_config,
1547 VideoEncoderConfig* encoder_config,
1548 test::FrameGeneratorCapturer** frame_generator) {}
1549 virtual void UpdateReceiveConfig(size_t stream_index,
1550 VideoReceiveStream::Config* receive_config) {
1551 }
stefanf116bd02015-10-27 08:29:42 -07001552 virtual test::DirectTransport* CreateSendTransport(Call* sender_call) {
nissee5ad5ca2017-03-29 23:57:43 -07001553 return new test::DirectTransport(sender_call, MediaType::VIDEO);
sprang867fb522015-08-03 04:38:41 -07001554 }
stefanf116bd02015-10-27 08:29:42 -07001555 virtual test::DirectTransport* CreateReceiveTransport(Call* receiver_call) {
nissee5ad5ca2017-03-29 23:57:43 -07001556 return new test::DirectTransport(receiver_call, MediaType::VIDEO);
sprang867fb522015-08-03 04:38:41 -07001557 }
1558};
1559
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001560// Each renderer verifies that it receives the expected resolution, and as soon
1561// as every renderer has received a frame, the test finishes.
philipel277a8b52017-03-16 05:19:49 -07001562TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) {
nisse7ade7b32016-03-23 04:48:10 -07001563 class VideoOutputObserver : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001564 public:
sprang867fb522015-08-03 04:38:41 -07001565 VideoOutputObserver(const MultiStreamTest::CodecSettings& settings,
1566 uint32_t ssrc,
1567 test::FrameGeneratorCapturer** frame_generator)
1568 : settings_(settings),
1569 ssrc_(ssrc),
1570 frame_generator_(frame_generator),
Peter Boström5811a392015-12-10 13:02:50 +01001571 done_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001572
nisseeb83a1a2016-03-21 01:27:56 -07001573 void OnFrame(const VideoFrame& video_frame) override {
sprang867fb522015-08-03 04:38:41 -07001574 EXPECT_EQ(settings_.width, video_frame.width());
1575 EXPECT_EQ(settings_.height, video_frame.height());
1576 (*frame_generator_)->Stop();
Peter Boström5811a392015-12-10 13:02:50 +01001577 done_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001578 }
1579
sprang867fb522015-08-03 04:38:41 -07001580 uint32_t Ssrc() { return ssrc_; }
1581
Peter Boström5811a392015-12-10 13:02:50 +01001582 bool Wait() { return done_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001583
1584 private:
sprang867fb522015-08-03 04:38:41 -07001585 const MultiStreamTest::CodecSettings& settings_;
1586 const uint32_t ssrc_;
1587 test::FrameGeneratorCapturer** const frame_generator_;
Peter Boström5811a392015-12-10 13:02:50 +01001588 rtc::Event done_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001589 };
1590
sprang867fb522015-08-03 04:38:41 -07001591 class Tester : public MultiStreamTest {
1592 public:
1593 Tester() {}
1594 virtual ~Tester() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001595
sprang867fb522015-08-03 04:38:41 -07001596 protected:
1597 void Wait() override {
1598 for (const auto& observer : observers_) {
Peter Boström5811a392015-12-10 13:02:50 +01001599 EXPECT_TRUE(observer->Wait()) << "Time out waiting for from on ssrc "
1600 << observer->Ssrc();
sprang867fb522015-08-03 04:38:41 -07001601 }
1602 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001603
sprang867fb522015-08-03 04:38:41 -07001604 void UpdateSendConfig(
1605 size_t stream_index,
1606 VideoSendStream::Config* send_config,
1607 VideoEncoderConfig* encoder_config,
1608 test::FrameGeneratorCapturer** frame_generator) override {
1609 observers_[stream_index].reset(new VideoOutputObserver(
1610 codec_settings[stream_index], send_config->rtp.ssrcs.front(),
1611 frame_generator));
1612 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001613
sprang867fb522015-08-03 04:38:41 -07001614 void UpdateReceiveConfig(
1615 size_t stream_index,
1616 VideoReceiveStream::Config* receive_config) override {
1617 receive_config->renderer = observers_[stream_index].get();
1618 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001619
sprang867fb522015-08-03 04:38:41 -07001620 private:
kwiberg27f982b2016-03-01 11:52:33 -08001621 std::unique_ptr<VideoOutputObserver> observers_[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001622 } tester;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001623
sprang867fb522015-08-03 04:38:41 -07001624 tester.RunTest();
1625}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001626
philipel277a8b52017-03-16 05:19:49 -07001627TEST_F(EndToEndTest, AssignsTransportSequenceNumbers) {
sprang867fb522015-08-03 04:38:41 -07001628 static const int kExtensionId = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001629
sprang867fb522015-08-03 04:38:41 -07001630 class RtpExtensionHeaderObserver : public test::DirectTransport {
1631 public:
stefanf116bd02015-10-27 08:29:42 -07001632 RtpExtensionHeaderObserver(Call* sender_call,
1633 const uint32_t& first_media_ssrc,
sprang861c55e2015-10-16 10:01:21 -07001634 const std::map<uint32_t, uint32_t>& ssrc_map)
nissee5ad5ca2017-03-29 23:57:43 -07001635 : DirectTransport(sender_call, MediaType::VIDEO),
Peter Boström5811a392015-12-10 13:02:50 +01001636 done_(false, false),
sprang867fb522015-08-03 04:38:41 -07001637 parser_(RtpHeaderParser::Create()),
sprang861c55e2015-10-16 10:01:21 -07001638 first_media_ssrc_(first_media_ssrc),
1639 rtx_to_media_ssrcs_(ssrc_map),
sprang867fb522015-08-03 04:38:41 -07001640 padding_observed_(false),
sprang861c55e2015-10-16 10:01:21 -07001641 rtx_padding_observed_(false),
1642 retransmit_observed_(false),
1643 started_(false) {
sprang867fb522015-08-03 04:38:41 -07001644 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
1645 kExtensionId);
1646 }
1647 virtual ~RtpExtensionHeaderObserver() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001648
stefan1d8a5062015-10-02 03:39:33 -07001649 bool SendRtp(const uint8_t* data,
1650 size_t length,
1651 const PacketOptions& options) override {
sprang861c55e2015-10-16 10:01:21 -07001652 {
1653 rtc::CritScope cs(&lock_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001654
Erik Språng8d629712015-08-04 16:24:03 +02001655 if (IsDone())
sprang861c55e2015-10-16 10:01:21 -07001656 return false;
1657
1658 if (started_) {
1659 RTPHeader header;
1660 EXPECT_TRUE(parser_->Parse(data, length, &header));
1661 bool drop_packet = false;
1662
1663 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
1664 EXPECT_EQ(options.packet_id,
1665 header.extension.transportSequenceNumber);
1666 if (!streams_observed_.empty()) {
1667 // Unwrap packet id and verify uniqueness.
1668 int64_t packet_id = unwrapper_.Unwrap(options.packet_id);
1669 EXPECT_TRUE(received_packed_ids_.insert(packet_id).second);
1670 }
1671
1672 // Drop (up to) every 17th packet, so we get retransmits.
1673 // Only drop media, and not on the first stream (otherwise it will be
1674 // hard to distinguish from padding, which is always sent on the first
1675 // stream).
1676 if (header.payloadType != kSendRtxPayloadType &&
1677 header.ssrc != first_media_ssrc_ &&
1678 header.extension.transportSequenceNumber % 17 == 0) {
1679 dropped_seq_[header.ssrc].insert(header.sequenceNumber);
1680 drop_packet = true;
1681 }
1682
perkja8ba1952017-02-27 06:52:10 -08001683 if (header.payloadType == kSendRtxPayloadType) {
sprang861c55e2015-10-16 10:01:21 -07001684 uint16_t original_sequence_number =
1685 ByteReader<uint16_t>::ReadBigEndian(&data[header.headerLength]);
1686 uint32_t original_ssrc =
1687 rtx_to_media_ssrcs_.find(header.ssrc)->second;
1688 std::set<uint16_t>* seq_no_map = &dropped_seq_[original_ssrc];
1689 auto it = seq_no_map->find(original_sequence_number);
1690 if (it != seq_no_map->end()) {
1691 retransmit_observed_ = true;
1692 seq_no_map->erase(it);
1693 } else {
1694 rtx_padding_observed_ = true;
1695 }
1696 } else {
1697 streams_observed_.insert(header.ssrc);
1698 }
1699
1700 if (IsDone())
Peter Boström5811a392015-12-10 13:02:50 +01001701 done_.Set();
sprang861c55e2015-10-16 10:01:21 -07001702
1703 if (drop_packet)
1704 return true;
1705 }
sprang867fb522015-08-03 04:38:41 -07001706 }
sprang861c55e2015-10-16 10:01:21 -07001707
stefan1d8a5062015-10-02 03:39:33 -07001708 return test::DirectTransport::SendRtp(data, length, options);
sprang867fb522015-08-03 04:38:41 -07001709 }
1710
Erik Språng8d629712015-08-04 16:24:03 +02001711 bool IsDone() {
sprang861c55e2015-10-16 10:01:21 -07001712 bool observed_types_ok =
1713 streams_observed_.size() == MultiStreamTest::kNumStreams &&
perkja8ba1952017-02-27 06:52:10 -08001714 retransmit_observed_ && rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001715 if (!observed_types_ok)
1716 return false;
1717 // We should not have any gaps in the sequence number range.
1718 size_t seqno_range =
1719 *received_packed_ids_.rbegin() - *received_packed_ids_.begin() + 1;
1720 return seqno_range == received_packed_ids_.size();
Erik Språng8d629712015-08-04 16:24:03 +02001721 }
1722
Peter Boström5811a392015-12-10 13:02:50 +01001723 bool Wait() {
sprang861c55e2015-10-16 10:01:21 -07001724 {
1725 // Can't be sure until this point that rtx_to_media_ssrcs_ etc have
1726 // been initialized and are OK to read.
1727 rtc::CritScope cs(&lock_);
1728 started_ = true;
1729 }
Peter Boström5811a392015-12-10 13:02:50 +01001730 return done_.Wait(kDefaultTimeoutMs);
sprang861c55e2015-10-16 10:01:21 -07001731 }
sprang867fb522015-08-03 04:38:41 -07001732
sprang861c55e2015-10-16 10:01:21 -07001733 rtc::CriticalSection lock_;
Peter Boström5811a392015-12-10 13:02:50 +01001734 rtc::Event done_;
kwiberg27f982b2016-03-01 11:52:33 -08001735 std::unique_ptr<RtpHeaderParser> parser_;
sprang861c55e2015-10-16 10:01:21 -07001736 SequenceNumberUnwrapper unwrapper_;
1737 std::set<int64_t> received_packed_ids_;
sprang867fb522015-08-03 04:38:41 -07001738 std::set<uint32_t> streams_observed_;
sprang861c55e2015-10-16 10:01:21 -07001739 std::map<uint32_t, std::set<uint16_t>> dropped_seq_;
1740 const uint32_t& first_media_ssrc_;
1741 const std::map<uint32_t, uint32_t>& rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001742 bool padding_observed_;
1743 bool rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001744 bool retransmit_observed_;
1745 bool started_;
sprang867fb522015-08-03 04:38:41 -07001746 };
1747
1748 class TransportSequenceNumberTester : public MultiStreamTest {
1749 public:
sprang861c55e2015-10-16 10:01:21 -07001750 TransportSequenceNumberTester()
1751 : first_media_ssrc_(0), observer_(nullptr) {}
sprang867fb522015-08-03 04:38:41 -07001752 virtual ~TransportSequenceNumberTester() {}
1753
1754 protected:
1755 void Wait() override {
Peter Boström74f6e9e2016-04-04 17:56:10 +02001756 RTC_DCHECK(observer_);
Peter Boström5811a392015-12-10 13:02:50 +01001757 EXPECT_TRUE(observer_->Wait());
sprang867fb522015-08-03 04:38:41 -07001758 }
1759
1760 void UpdateSendConfig(
1761 size_t stream_index,
1762 VideoSendStream::Config* send_config,
1763 VideoEncoderConfig* encoder_config,
1764 test::FrameGeneratorCapturer** frame_generator) override {
1765 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001766 send_config->rtp.extensions.push_back(RtpExtension(
1767 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sprang867fb522015-08-03 04:38:41 -07001768
perkja8ba1952017-02-27 06:52:10 -08001769 // Force some padding to be sent. Note that since we do send media
1770 // packets we can not guarantee that a padding only packet is sent.
1771 // Instead, padding will most likely be send as an RTX packet.
sprang867fb522015-08-03 04:38:41 -07001772 const int kPaddingBitrateBps = 50000;
perkja8ba1952017-02-27 06:52:10 -08001773 encoder_config->max_bitrate_bps = 200000;
sprang867fb522015-08-03 04:38:41 -07001774 encoder_config->min_transmit_bitrate_bps =
perkjfa10b552016-10-02 23:45:26 -07001775 encoder_config->max_bitrate_bps + kPaddingBitrateBps;
sprang867fb522015-08-03 04:38:41 -07001776
1777 // Configure RTX for redundant payload padding.
1778 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang861c55e2015-10-16 10:01:21 -07001779 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[stream_index]);
sprang867fb522015-08-03 04:38:41 -07001780 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
sprang861c55e2015-10-16 10:01:21 -07001781 rtx_to_media_ssrcs_[kSendRtxSsrcs[stream_index]] =
1782 send_config->rtp.ssrcs[0];
1783
1784 if (stream_index == 0)
1785 first_media_ssrc_ = send_config->rtp.ssrcs[0];
sprang867fb522015-08-03 04:38:41 -07001786 }
1787
1788 void UpdateReceiveConfig(
1789 size_t stream_index,
1790 VideoReceiveStream::Config* receive_config) override {
sprang861c55e2015-10-16 10:01:21 -07001791 receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang867fb522015-08-03 04:38:41 -07001792 receive_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001793 receive_config->rtp.extensions.push_back(RtpExtension(
1794 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sakal55d932b2016-09-30 06:19:08 -07001795 receive_config->renderer = &fake_renderer_;
sprang867fb522015-08-03 04:38:41 -07001796 }
1797
stefanf116bd02015-10-27 08:29:42 -07001798 test::DirectTransport* CreateSendTransport(Call* sender_call) override {
1799 observer_ = new RtpExtensionHeaderObserver(sender_call, first_media_ssrc_,
sprang861c55e2015-10-16 10:01:21 -07001800 rtx_to_media_ssrcs_);
sprang867fb522015-08-03 04:38:41 -07001801 return observer_;
1802 }
1803
1804 private:
sakal55d932b2016-09-30 06:19:08 -07001805 test::FakeVideoRenderer fake_renderer_;
sprang861c55e2015-10-16 10:01:21 -07001806 uint32_t first_media_ssrc_;
1807 std::map<uint32_t, uint32_t> rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001808 RtpExtensionHeaderObserver* observer_;
1809 } tester;
1810
1811 tester.RunTest();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001812}
1813
Stefan Holmer04cb7632016-01-14 20:34:30 +01001814class TransportFeedbackTester : public test::EndToEndTest {
1815 public:
1816 explicit TransportFeedbackTester(bool feedback_enabled,
1817 size_t num_video_streams,
1818 size_t num_audio_streams)
1819 : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
1820 feedback_enabled_(feedback_enabled),
1821 num_video_streams_(num_video_streams),
sprangcd349d92016-07-13 09:11:28 -07001822 num_audio_streams_(num_audio_streams),
1823 receiver_call_(nullptr) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001824 // Only one stream of each supported for now.
1825 EXPECT_LE(num_video_streams, 1u);
1826 EXPECT_LE(num_audio_streams, 1u);
1827 }
1828
1829 protected:
1830 Action OnSendRtcp(const uint8_t* data, size_t length) override {
1831 EXPECT_FALSE(HasTransportFeedback(data, length));
1832 return SEND_PACKET;
1833 }
1834
1835 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
1836 if (HasTransportFeedback(data, length))
1837 observation_complete_.Set();
1838 return SEND_PACKET;
1839 }
1840
1841 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
danilchap3dc929e2016-11-02 08:21:59 -07001842 test::RtcpPacketParser parser;
1843 EXPECT_TRUE(parser.Parse(data, length));
1844 return parser.transport_feedback()->num_packets() > 0;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001845 }
1846
1847 void PerformTest() override {
1848 const int64_t kDisabledFeedbackTimeoutMs = 5000;
1849 EXPECT_EQ(feedback_enabled_,
1850 observation_complete_.Wait(feedback_enabled_
1851 ? test::CallTest::kDefaultTimeoutMs
1852 : kDisabledFeedbackTimeoutMs));
1853 }
1854
1855 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1856 receiver_call_ = receiver_call;
1857 }
1858
1859 size_t GetNumVideoStreams() const override { return num_video_streams_; }
1860 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
1861
1862 void ModifyVideoConfigs(
1863 VideoSendStream::Config* send_config,
1864 std::vector<VideoReceiveStream::Config>* receive_configs,
1865 VideoEncoderConfig* encoder_config) override {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001866 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
1867 }
1868
1869 void ModifyAudioConfigs(
1870 AudioSendStream::Config* send_config,
1871 std::vector<AudioReceiveStream::Config>* receive_configs) override {
1872 send_config->rtp.extensions.clear();
1873 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001874 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001875 (*receive_configs)[0].rtp.extensions.clear();
1876 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1877 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001878 }
1879
1880 private:
Erik Språng6b8d3552015-09-24 15:06:57 +02001881 static const int kExtensionId = 5;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001882 const bool feedback_enabled_;
1883 const size_t num_video_streams_;
1884 const size_t num_audio_streams_;
1885 Call* receiver_call_;
1886};
Erik Språng6b8d3552015-09-24 15:06:57 +02001887
philipel277a8b52017-03-16 05:19:49 -07001888TEST_F(EndToEndTest, VideoReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001889 TransportFeedbackTester test(true, 1, 0);
1890 RunBaseTest(&test);
Erik Språng6b8d3552015-09-24 15:06:57 +02001891}
stefan43edf0f2015-11-20 18:05:48 -08001892
philipel277a8b52017-03-16 05:19:49 -07001893TEST_F(EndToEndTest, VideoTransportFeedbackNotConfigured) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001894 TransportFeedbackTester test(false, 1, 0);
1895 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001896}
1897
philipel277a8b52017-03-16 05:19:49 -07001898TEST_F(EndToEndTest, AudioReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001899 TransportFeedbackTester test(true, 0, 1);
1900 RunBaseTest(&test);
1901}
1902
philipel277a8b52017-03-16 05:19:49 -07001903TEST_F(EndToEndTest, AudioTransportFeedbackNotConfigured) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001904 TransportFeedbackTester test(false, 0, 1);
1905 RunBaseTest(&test);
1906}
1907
philipel277a8b52017-03-16 05:19:49 -07001908TEST_F(EndToEndTest, AudioVideoReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001909 TransportFeedbackTester test(true, 1, 1);
1910 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001911}
1912
philipel277a8b52017-03-16 05:19:49 -07001913TEST_F(EndToEndTest, ObserversEncodedFrames) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001914 class EncodedFrameTestObserver : public EncodedFrameObserver {
1915 public:
1916 EncodedFrameTestObserver()
Peter Boström5811a392015-12-10 13:02:50 +01001917 : length_(0), frame_type_(kEmptyFrame), called_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001918 virtual ~EncodedFrameTestObserver() {}
1919
1920 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
1921 frame_type_ = encoded_frame.frame_type_;
1922 length_ = encoded_frame.length_;
1923 buffer_.reset(new uint8_t[length_]);
1924 memcpy(buffer_.get(), encoded_frame.data_, length_);
Peter Boström5811a392015-12-10 13:02:50 +01001925 called_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001926 }
1927
Peter Boström5811a392015-12-10 13:02:50 +01001928 bool Wait() { return called_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001929
1930 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
1931 ASSERT_EQ(length_, observer.length_)
1932 << "Observed frames are of different lengths.";
1933 EXPECT_EQ(frame_type_, observer.frame_type_)
1934 << "Observed frames have different frame types.";
1935 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
1936 << "Observed encoded frames have different content.";
1937 }
1938
1939 private:
kwiberg27f982b2016-03-01 11:52:33 -08001940 std::unique_ptr<uint8_t[]> buffer_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001941 size_t length_;
1942 FrameType frame_type_;
Peter Boström5811a392015-12-10 13:02:50 +01001943 rtc::Event called_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001944 };
1945
1946 EncodedFrameTestObserver post_encode_observer;
1947 EncodedFrameTestObserver pre_decode_observer;
1948
skvlad11a9cbf2016-10-07 11:53:05 -07001949 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -07001950
nissee5ad5ca2017-03-29 23:57:43 -07001951 test::DirectTransport sender_transport(
1952 sender_call_.get(), MediaType::VIDEO);
1953 test::DirectTransport receiver_transport(
1954 receiver_call_.get(), MediaType::VIDEO);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001955 sender_transport.SetReceiver(receiver_call_->Receiver());
1956 receiver_transport.SetReceiver(sender_call_->Receiver());
1957
brandtr841de6a2016-11-15 07:10:52 -08001958 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001959 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -08001960 video_send_config_.post_encode_callback = &post_encode_observer;
1961 video_receive_configs_[0].pre_decode_callback = &pre_decode_observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001962
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001963 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001964 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001965
kwiberg27f982b2016-03-01 11:52:33 -08001966 std::unique_ptr<test::FrameGenerator> frame_generator(
perkja8ba1952017-02-27 06:52:10 -08001967 test::FrameGenerator::CreateSquareGenerator(kDefaultWidth,
perkjfa10b552016-10-02 23:45:26 -07001968 kDefaultHeight));
perkja49cbd32016-09-16 07:53:41 -07001969 test::FrameForwarder forwarder;
perkj803d97f2016-11-01 11:45:46 -07001970 video_send_stream_->SetSource(
sprangc5d62e22017-04-02 23:53:04 -07001971 &forwarder, VideoSendStream::DegradationPreference::kMaintainFramerate);
perkja49cbd32016-09-16 07:53:41 -07001972 forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001973
Peter Boström5811a392015-12-10 13:02:50 +01001974 EXPECT_TRUE(post_encode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001975 << "Timed out while waiting for send-side encoded-frame callback.";
1976
Peter Boström5811a392015-12-10 13:02:50 +01001977 EXPECT_TRUE(pre_decode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001978 << "Timed out while waiting for pre-decode encoded-frame callback.";
1979
1980 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
1981
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001982 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001983
1984 sender_transport.StopSending();
1985 receiver_transport.StopSending();
1986
1987 DestroyStreams();
1988}
1989
philipel277a8b52017-03-16 05:19:49 -07001990TEST_F(EndToEndTest, ReceiveStreamSendsRemb) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001991 class RembObserver : public test::EndToEndTest {
1992 public:
1993 RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
1994
stefanb77c7162017-02-06 06:29:38 -08001995 void ModifyVideoConfigs(
1996 VideoSendStream::Config* send_config,
1997 std::vector<VideoReceiveStream::Config>* receive_configs,
1998 VideoEncoderConfig* encoder_config) override {
1999 send_config->rtp.extensions.clear();
2000 send_config->rtp.extensions.push_back(RtpExtension(
2001 RtpExtension::kAbsSendTimeUri, test::kAbsSendTimeExtensionId));
2002 (*receive_configs)[0].rtp.remb = true;
2003 (*receive_configs)[0].rtp.transport_cc = false;
2004 }
2005
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002006 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
danilchap3dc929e2016-11-02 08:21:59 -07002007 test::RtcpPacketParser parser;
2008 EXPECT_TRUE(parser.Parse(packet, length));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002009
danilchap3dc929e2016-11-02 08:21:59 -07002010 if (parser.remb()->num_packets() > 0) {
2011 EXPECT_EQ(kReceiverLocalVideoSsrc, parser.remb()->sender_ssrc());
2012 EXPECT_LT(0U, parser.remb()->bitrate_bps());
2013 EXPECT_EQ(1U, parser.remb()->ssrcs().size());
2014 EXPECT_EQ(kVideoSendSsrcs[0], parser.remb()->ssrcs()[0]);
Peter Boström5811a392015-12-10 13:02:50 +01002015 observation_complete_.Set();
danilchap3dc929e2016-11-02 08:21:59 -07002016 }
2017
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002018 return SEND_PACKET;
2019 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002020 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002021 EXPECT_TRUE(Wait()) << "Timed out while waiting for a "
2022 "receiver RTCP REMB packet to be "
2023 "sent.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002024 }
2025 } test;
2026
stefane74eef12016-01-08 06:47:13 -08002027 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002028}
2029
stefanb77c7162017-02-06 06:29:38 -08002030class BandwidthStatsTest : public test::EndToEndTest {
2031 public:
2032 explicit BandwidthStatsTest(bool send_side_bwe)
2033 : EndToEndTest(test::CallTest::kDefaultTimeoutMs),
2034 sender_call_(nullptr),
2035 receiver_call_(nullptr),
2036 has_seen_pacer_delay_(false),
2037 send_side_bwe_(send_side_bwe) {}
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002038
stefanb77c7162017-02-06 06:29:38 -08002039 void ModifyVideoConfigs(
2040 VideoSendStream::Config* send_config,
2041 std::vector<VideoReceiveStream::Config>* receive_configs,
2042 VideoEncoderConfig* encoder_config) override {
2043 if (!send_side_bwe_) {
2044 send_config->rtp.extensions.clear();
2045 send_config->rtp.extensions.push_back(RtpExtension(
2046 RtpExtension::kAbsSendTimeUri, test::kAbsSendTimeExtensionId));
2047 (*receive_configs)[0].rtp.remb = true;
2048 (*receive_configs)[0].rtp.transport_cc = false;
2049 }
2050 }
2051
2052 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2053 Call::Stats sender_stats = sender_call_->GetStats();
2054 Call::Stats receiver_stats = receiver_call_->GetStats();
2055 if (!has_seen_pacer_delay_)
2056 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
2057 if (sender_stats.send_bandwidth_bps > 0 && has_seen_pacer_delay_) {
2058 if (send_side_bwe_ || receiver_stats.recv_bandwidth_bps > 0)
Peter Boström5811a392015-12-10 13:02:50 +01002059 observation_complete_.Set();
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002060 }
stefanb77c7162017-02-06 06:29:38 -08002061 return SEND_PACKET;
2062 }
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002063
stefanb77c7162017-02-06 06:29:38 -08002064 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2065 sender_call_ = sender_call;
2066 receiver_call_ = receiver_call;
2067 }
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002068
stefanb77c7162017-02-06 06:29:38 -08002069 void PerformTest() override {
2070 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2071 "non-zero bandwidth stats.";
2072 }
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002073
stefanb77c7162017-02-06 06:29:38 -08002074 private:
2075 Call* sender_call_;
2076 Call* receiver_call_;
2077 bool has_seen_pacer_delay_;
2078 const bool send_side_bwe_;
2079};
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002080
philipel277a8b52017-03-16 05:19:49 -07002081TEST_F(EndToEndTest, VerifySendSideBweStats) {
stefanb77c7162017-02-06 06:29:38 -08002082 BandwidthStatsTest test(true);
stefane74eef12016-01-08 06:47:13 -08002083 RunBaseTest(&test);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002084}
2085
philipel277a8b52017-03-16 05:19:49 -07002086TEST_F(EndToEndTest, VerifyRecvSideBweStats) {
stefanb77c7162017-02-06 06:29:38 -08002087 BandwidthStatsTest test(false);
2088 RunBaseTest(&test);
2089}
stefan32f81542016-01-20 07:13:58 -08002090
2091// Verifies that it's possible to limit the send BWE by sending a REMB.
2092// This is verified by allowing the send BWE to ramp-up to >1000 kbps,
2093// then have the test generate a REMB of 500 kbps and verify that the send BWE
2094// is reduced to exactly 500 kbps. Then a REMB of 1000 kbps is generated and the
2095// test verifies that the send BWE ramps back up to exactly 1000 kbps.
philipel277a8b52017-03-16 05:19:49 -07002096TEST_F(EndToEndTest, RembWithSendSideBwe) {
stefan32f81542016-01-20 07:13:58 -08002097 class BweObserver : public test::EndToEndTest {
2098 public:
2099 BweObserver()
2100 : EndToEndTest(kDefaultTimeoutMs),
2101 sender_call_(nullptr),
2102 clock_(Clock::GetRealTimeClock()),
2103 sender_ssrc_(0),
2104 remb_bitrate_bps_(1000000),
2105 receive_transport_(nullptr),
Tommi5dd5f5a2017-02-21 14:22:59 +01002106 stop_event_(false, false),
stefan32f81542016-01-20 07:13:58 -08002107 poller_thread_(&BitrateStatsPollingThread,
2108 this,
2109 "BitrateStatsPollingThread"),
Erik Språng737336d2016-07-29 12:59:36 +02002110 state_(kWaitForFirstRampUp),
2111 retransmission_rate_limiter_(clock_, 1000) {}
stefan32f81542016-01-20 07:13:58 -08002112
2113 ~BweObserver() {}
2114
nisseef8b61e2016-04-29 06:09:15 -07002115 test::PacketTransport* CreateReceiveTransport() override {
stefan32f81542016-01-20 07:13:58 -08002116 receive_transport_ = new test::PacketTransport(
2117 nullptr, this, test::PacketTransport::kReceiver,
nissee5ad5ca2017-03-29 23:57:43 -07002118 MediaType::VIDEO,
stefan32f81542016-01-20 07:13:58 -08002119 FakeNetworkPipe::Config());
2120 return receive_transport_;
2121 }
2122
2123 Call::Config GetSenderCallConfig() override {
skvlad11a9cbf2016-10-07 11:53:05 -07002124 Call::Config config(&event_log_);
stefan32f81542016-01-20 07:13:58 -08002125 // Set a high start bitrate to reduce the test completion time.
2126 config.bitrate_config.start_bitrate_bps = remb_bitrate_bps_;
2127 return config;
2128 }
2129
2130 void ModifyVideoConfigs(
2131 VideoSendStream::Config* send_config,
2132 std::vector<VideoReceiveStream::Config>* receive_configs,
2133 VideoEncoderConfig* encoder_config) override {
2134 ASSERT_EQ(1u, send_config->rtp.ssrcs.size());
stefan32f81542016-01-20 07:13:58 -08002135 sender_ssrc_ = send_config->rtp.ssrcs[0];
2136
perkjfa10b552016-10-02 23:45:26 -07002137 encoder_config->max_bitrate_bps = 2000000;
stefan32f81542016-01-20 07:13:58 -08002138
2139 ASSERT_EQ(1u, receive_configs->size());
stefan32f81542016-01-20 07:13:58 -08002140 RtpRtcp::Configuration config;
2141 config.receiver_only = true;
2142 config.clock = clock_;
2143 config.outgoing_transport = receive_transport_;
Erik Språng737336d2016-07-29 12:59:36 +02002144 config.retransmission_rate_limiter = &retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08002145 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
2146 rtp_rtcp_->SetRemoteSSRC((*receive_configs)[0].rtp.remote_ssrc);
2147 rtp_rtcp_->SetSSRC((*receive_configs)[0].rtp.local_ssrc);
2148 rtp_rtcp_->SetREMBStatus(true);
stefan32f81542016-01-20 07:13:58 -08002149 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
2150 }
2151
2152 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2153 sender_call_ = sender_call;
2154 }
2155
tommi0f8b4032017-02-22 11:22:05 -08002156 static void BitrateStatsPollingThread(void* obj) {
2157 static_cast<BweObserver*>(obj)->PollStats();
stefan32f81542016-01-20 07:13:58 -08002158 }
2159
tommi0f8b4032017-02-22 11:22:05 -08002160 void PollStats() {
2161 do {
2162 if (sender_call_) {
2163 Call::Stats stats = sender_call_->GetStats();
2164 switch (state_) {
2165 case kWaitForFirstRampUp:
2166 if (stats.send_bandwidth_bps >= remb_bitrate_bps_) {
2167 state_ = kWaitForRemb;
2168 remb_bitrate_bps_ /= 2;
2169 rtp_rtcp_->SetREMBData(
2170 remb_bitrate_bps_,
2171 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
2172 rtp_rtcp_->SendRTCP(kRtcpRr);
2173 }
2174 break;
stefan32f81542016-01-20 07:13:58 -08002175
tommi0f8b4032017-02-22 11:22:05 -08002176 case kWaitForRemb:
2177 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
2178 state_ = kWaitForSecondRampUp;
2179 remb_bitrate_bps_ *= 2;
2180 rtp_rtcp_->SetREMBData(
2181 remb_bitrate_bps_,
2182 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
2183 rtp_rtcp_->SendRTCP(kRtcpRr);
2184 }
2185 break;
stefan32f81542016-01-20 07:13:58 -08002186
tommi0f8b4032017-02-22 11:22:05 -08002187 case kWaitForSecondRampUp:
2188 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
2189 observation_complete_.Set();
2190 }
2191 break;
2192 }
stefan32f81542016-01-20 07:13:58 -08002193 }
tommi0f8b4032017-02-22 11:22:05 -08002194 } while (!stop_event_.Wait(1000));
stefan32f81542016-01-20 07:13:58 -08002195 }
2196
2197 void PerformTest() override {
2198 poller_thread_.Start();
2199 EXPECT_TRUE(Wait())
2200 << "Timed out while waiting for bitrate to change according to REMB.";
Tommi5dd5f5a2017-02-21 14:22:59 +01002201 stop_event_.Set();
stefan32f81542016-01-20 07:13:58 -08002202 poller_thread_.Stop();
2203 }
2204
2205 private:
2206 enum TestState { kWaitForFirstRampUp, kWaitForRemb, kWaitForSecondRampUp };
2207
2208 Call* sender_call_;
2209 Clock* const clock_;
2210 uint32_t sender_ssrc_;
2211 int remb_bitrate_bps_;
kwiberg27f982b2016-03-01 11:52:33 -08002212 std::unique_ptr<RtpRtcp> rtp_rtcp_;
stefan32f81542016-01-20 07:13:58 -08002213 test::PacketTransport* receive_transport_;
Tommi5dd5f5a2017-02-21 14:22:59 +01002214 rtc::Event stop_event_;
stefan32f81542016-01-20 07:13:58 -08002215 rtc::PlatformThread poller_thread_;
2216 TestState state_;
Erik Språng737336d2016-07-29 12:59:36 +02002217 RateLimiter retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08002218 } test;
2219
2220 RunBaseTest(&test);
2221}
2222
philipele828c962017-03-21 03:24:27 -07002223class ProbingTest : public test::EndToEndTest {
2224 public:
2225 explicit ProbingTest(int start_bitrate_bps)
2226 : clock_(Clock::GetRealTimeClock()),
2227 start_bitrate_bps_(start_bitrate_bps),
2228 state_(0),
2229 sender_call_(nullptr) {}
2230
2231 ~ProbingTest() {}
2232
2233 Call::Config GetSenderCallConfig() override {
2234 Call::Config config(&event_log_);
2235 config.bitrate_config.start_bitrate_bps = start_bitrate_bps_;
2236 return config;
2237 }
2238
2239 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2240 sender_call_ = sender_call;
2241 }
2242
2243 protected:
2244 Clock* const clock_;
2245 const int start_bitrate_bps_;
2246 int state_;
2247 Call* sender_call_;
2248};
2249
aleloi7057b6b2017-03-29 02:07:33 -07002250TEST_F(EndToEndTest, MAYBE_InitialProbing) {
philipele828c962017-03-21 03:24:27 -07002251 class InitialProbingTest : public ProbingTest {
2252 public:
philipel8a256522017-03-30 05:06:22 -07002253 explicit InitialProbingTest(bool* success)
2254 : ProbingTest(300000), success_(success) {}
philipele828c962017-03-21 03:24:27 -07002255
2256 void PerformTest() override {
2257 int64_t start_time_ms = clock_->TimeInMilliseconds();
2258 do {
philipel8a256522017-03-30 05:06:22 -07002259 if (clock_->TimeInMilliseconds() - start_time_ms > kTimeoutMs)
philipele828c962017-03-21 03:24:27 -07002260 break;
philipele828c962017-03-21 03:24:27 -07002261
2262 Call::Stats stats = sender_call_->GetStats();
2263 // Initial probing is done with a x3 and x6 multiplier of the start
2264 // bitrate, so a x4 multiplier is a high enough threshold.
philipel8a256522017-03-30 05:06:22 -07002265 if (stats.send_bandwidth_bps > 4 * 300000) {
2266 *success_ = true;
philipele828c962017-03-21 03:24:27 -07002267 break;
philipel8a256522017-03-30 05:06:22 -07002268 }
philipele828c962017-03-21 03:24:27 -07002269 } while (!observation_complete_.Wait(20));
2270 }
2271
2272 private:
2273 const int kTimeoutMs = 1000;
philipel8a256522017-03-30 05:06:22 -07002274 bool* const success_;
2275 };
philipele828c962017-03-21 03:24:27 -07002276
philipel8a256522017-03-30 05:06:22 -07002277 bool success;
2278 const int kMaxAttempts = 3;
2279 for (int i = 0; i < kMaxAttempts; ++i) {
2280 InitialProbingTest test(&success);
2281 RunBaseTest(&test);
2282 if (success)
2283 return;
2284 }
2285 RTC_DCHECK(success) << "Failed to perform mid initial probing ("
2286 << kMaxAttempts << " attempts).";
philipele828c962017-03-21 03:24:27 -07002287}
2288
aleloi18703f92017-03-30 04:24:08 -07002289// Fails on Linux MSan: bugs.webrtc.org/7428
2290#if defined(MEMORY_SANITIZER)
2291TEST_F(EndToEndTest, DISABLED_TriggerMidCallProbing) {
2292#else
philipele828c962017-03-21 03:24:27 -07002293TEST_F(EndToEndTest, TriggerMidCallProbing) {
aleloi18703f92017-03-30 04:24:08 -07002294#endif
2295
philipele828c962017-03-21 03:24:27 -07002296 class TriggerMidCallProbingTest : public ProbingTest {
2297 public:
philipel8a256522017-03-30 05:06:22 -07002298 explicit TriggerMidCallProbingTest(bool* success)
2299 : ProbingTest(300000), success_(success) {}
philipele828c962017-03-21 03:24:27 -07002300
2301 void PerformTest() override {
philipel8a256522017-03-30 05:06:22 -07002302 *success_ = false;
philipele828c962017-03-21 03:24:27 -07002303 int64_t start_time_ms = clock_->TimeInMilliseconds();
2304 do {
philipel8a256522017-03-30 05:06:22 -07002305 if (clock_->TimeInMilliseconds() - start_time_ms > kTimeoutMs)
philipele828c962017-03-21 03:24:27 -07002306 break;
philipele828c962017-03-21 03:24:27 -07002307
2308 Call::Stats stats = sender_call_->GetStats();
2309
2310 switch (state_) {
2311 case 0:
2312 if (stats.send_bandwidth_bps > 5 * 300000) {
2313 Call::Config::BitrateConfig bitrate_config;
2314 bitrate_config.max_bitrate_bps = 100000;
2315 sender_call_->SetBitrateConfig(bitrate_config);
2316 ++state_;
2317 }
2318 break;
2319 case 1:
2320 if (stats.send_bandwidth_bps < 110000) {
2321 Call::Config::BitrateConfig bitrate_config;
2322 bitrate_config.max_bitrate_bps = 2500000;
2323 sender_call_->SetBitrateConfig(bitrate_config);
2324 ++state_;
2325 }
2326 break;
2327 case 2:
2328 // During high cpu load the pacer will not be able to pace packets
2329 // at the correct speed, but if we go from 110 to 1250 kbps
2330 // in 5 seconds then it is due to probing.
philipel8a256522017-03-30 05:06:22 -07002331 if (stats.send_bandwidth_bps > 1250000) {
2332 *success_ = true;
philipele828c962017-03-21 03:24:27 -07002333 observation_complete_.Set();
philipel8a256522017-03-30 05:06:22 -07002334 }
philipele828c962017-03-21 03:24:27 -07002335 break;
2336 }
2337 } while (!observation_complete_.Wait(20));
2338 }
2339
2340 private:
2341 const int kTimeoutMs = 5000;
philipel8a256522017-03-30 05:06:22 -07002342 bool* const success_;
2343 };
philipele828c962017-03-21 03:24:27 -07002344
philipel8a256522017-03-30 05:06:22 -07002345 bool success;
2346 const int kMaxAttempts = 3;
2347 for (int i = 0; i < kMaxAttempts; ++i) {
2348 TriggerMidCallProbingTest test(&success);
2349 RunBaseTest(&test);
2350 if (success)
2351 return;
2352 }
2353 RTC_DCHECK(success) << "Failed to perform mid call probing (" << kMaxAttempts
2354 << " attempts).";
philipele828c962017-03-21 03:24:27 -07002355}
2356
philipel277a8b52017-03-16 05:19:49 -07002357TEST_F(EndToEndTest, VerifyNackStats) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002358 static const int kPacketNumberToDrop = 200;
2359 class NackObserver : public test::EndToEndTest {
2360 public:
2361 NackObserver()
2362 : EndToEndTest(kLongTimeoutMs),
2363 sent_rtp_packets_(0),
2364 dropped_rtp_packet_(0),
2365 dropped_rtp_packet_requested_(false),
2366 send_stream_(nullptr),
2367 start_runtime_ms_(-1) {}
2368
2369 private:
2370 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002371 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002372 if (++sent_rtp_packets_ == kPacketNumberToDrop) {
kwiberg27f982b2016-03-01 11:52:33 -08002373 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
Åsa Persson352b2d72015-04-15 18:00:40 +02002374 RTPHeader header;
2375 EXPECT_TRUE(parser->Parse(packet, length, &header));
2376 dropped_rtp_packet_ = header.sequenceNumber;
2377 return DROP_PACKET;
2378 }
2379 VerifyStats();
2380 return SEND_PACKET;
2381 }
2382
2383 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002384 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002385 test::RtcpPacketParser rtcp_parser;
2386 rtcp_parser.Parse(packet, length);
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02002387 const std::vector<uint16_t>& nacks = rtcp_parser.nack()->packet_ids();
Åsa Persson352b2d72015-04-15 18:00:40 +02002388 if (!nacks.empty() && std::find(
2389 nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) {
2390 dropped_rtp_packet_requested_ = true;
2391 }
2392 return SEND_PACKET;
2393 }
2394
stefan608213e2015-11-01 14:56:10 -08002395 void VerifyStats() EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002396 if (!dropped_rtp_packet_requested_)
2397 return;
2398 int send_stream_nack_packets = 0;
2399 int receive_stream_nack_packets = 0;
2400 VideoSendStream::Stats stats = send_stream_->GetStats();
2401 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
2402 stats.substreams.begin(); it != stats.substreams.end(); ++it) {
2403 const VideoSendStream::StreamStats& stream_stats = it->second;
2404 send_stream_nack_packets +=
2405 stream_stats.rtcp_packet_type_counts.nack_packets;
2406 }
2407 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2408 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2409 receive_stream_nack_packets +=
2410 stats.rtcp_packet_type_counts.nack_packets;
2411 }
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002412 if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002413 // NACK packet sent on receive stream and received on sent stream.
2414 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002415 observation_complete_.Set();
Åsa Persson352b2d72015-04-15 18:00:40 +02002416 }
2417 }
2418
2419 bool MinMetricRunTimePassed() {
2420 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2421 if (start_runtime_ms_ == -1) {
2422 start_runtime_ms_ = now;
2423 return false;
2424 }
2425 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2426 return elapsed_sec > metrics::kMinRunTimeInSeconds;
2427 }
2428
stefanff483612015-12-21 03:14:00 -08002429 void ModifyVideoConfigs(
2430 VideoSendStream::Config* send_config,
2431 std::vector<VideoReceiveStream::Config>* receive_configs,
2432 VideoEncoderConfig* encoder_config) override {
Åsa Persson352b2d72015-04-15 18:00:40 +02002433 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2434 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sakal55d932b2016-09-30 06:19:08 -07002435 (*receive_configs)[0].renderer = &fake_renderer_;
Åsa Persson352b2d72015-04-15 18:00:40 +02002436 }
2437
stefanff483612015-12-21 03:14:00 -08002438 void OnVideoStreamsCreated(
Åsa Persson352b2d72015-04-15 18:00:40 +02002439 VideoSendStream* send_stream,
2440 const std::vector<VideoReceiveStream*>& receive_streams) override {
2441 send_stream_ = send_stream;
2442 receive_streams_ = receive_streams;
2443 }
2444
2445 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002446 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson352b2d72015-04-15 18:00:40 +02002447 }
2448
sakal55d932b2016-09-30 06:19:08 -07002449 test::FakeVideoRenderer fake_renderer_;
stefan608213e2015-11-01 14:56:10 -08002450 rtc::CriticalSection crit_;
Åsa Persson352b2d72015-04-15 18:00:40 +02002451 uint64_t sent_rtp_packets_;
stefan608213e2015-11-01 14:56:10 -08002452 uint16_t dropped_rtp_packet_ GUARDED_BY(&crit_);
2453 bool dropped_rtp_packet_requested_ GUARDED_BY(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002454 std::vector<VideoReceiveStream*> receive_streams_;
2455 VideoSendStream* send_stream_;
2456 int64_t start_runtime_ms_;
2457 } test;
2458
asapersson01d70a32016-05-20 06:29:46 -07002459 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002460 RunBaseTest(&test);
Åsa Persson352b2d72015-04-15 18:00:40 +02002461
asapersson01d70a32016-05-20 06:29:46 -07002462 EXPECT_EQ(
2463 1, metrics::NumSamples("WebRTC.Video.UniqueNackRequestsSentInPercent"));
2464 EXPECT_EQ(1, metrics::NumSamples(
2465 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
2466 EXPECT_GT(metrics::MinSample("WebRTC.Video.NackPacketsSentPerMinute"), 0);
Åsa Persson352b2d72015-04-15 18:00:40 +02002467}
2468
sprangb4a1ae52015-12-03 08:10:08 -08002469void EndToEndTest::VerifyHistogramStats(bool use_rtx,
2470 bool use_red,
2471 bool screenshare) {
tommi2e82f382016-06-21 00:26:43 -07002472 class StatsObserver : public test::EndToEndTest,
2473 public rtc::VideoSinkInterface<VideoFrame> {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002474 public:
sprangb4a1ae52015-12-03 08:10:08 -08002475 StatsObserver(bool use_rtx, bool use_red, bool screenshare)
Åsa Persson3c391cb2015-04-27 10:09:49 +02002476 : EndToEndTest(kLongTimeoutMs),
2477 use_rtx_(use_rtx),
2478 use_red_(use_red),
sprangb4a1ae52015-12-03 08:10:08 -08002479 screenshare_(screenshare),
Peter Boström39593972016-02-15 11:27:15 +01002480 // This test uses NACK, so to send FEC we can't use a fake encoder.
magjed509e4fe2016-11-18 01:34:11 -08002481 vp8_encoder_(use_red ? VP8Encoder::Create() : nullptr),
Åsa Persson3c391cb2015-04-27 10:09:49 +02002482 sender_call_(nullptr),
2483 receiver_call_(nullptr),
asapersson1394c7b2016-10-18 11:50:50 -07002484 start_runtime_ms_(-1),
2485 num_frames_received_(0) {}
Åsa Persson3c391cb2015-04-27 10:09:49 +02002486
2487 private:
asapersson1394c7b2016-10-18 11:50:50 -07002488 void OnFrame(const VideoFrame& video_frame) override {
2489 // The RTT is needed to estimate |ntp_time_ms| which is used by
2490 // end-to-end delay stats. Therefore, start counting received frames once
2491 // |ntp_time_ms| is valid.
2492 if (video_frame.ntp_time_ms() > 0 &&
2493 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() >=
2494 video_frame.ntp_time_ms()) {
2495 rtc::CritScope lock(&crit_);
2496 ++num_frames_received_;
2497 }
2498 }
tommi2e82f382016-06-21 00:26:43 -07002499
Åsa Persson3c391cb2015-04-27 10:09:49 +02002500 Action OnSendRtp(const uint8_t* packet, size_t length) override {
asapersson1394c7b2016-10-18 11:50:50 -07002501 if (MinMetricRunTimePassed() && MinNumberOfFramesReceived())
Peter Boström5811a392015-12-10 13:02:50 +01002502 observation_complete_.Set();
Åsa Persson3c391cb2015-04-27 10:09:49 +02002503
stefanf116bd02015-10-27 08:29:42 -07002504 return SEND_PACKET;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002505 }
2506
2507 bool MinMetricRunTimePassed() {
2508 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2509 if (start_runtime_ms_ == -1) {
2510 start_runtime_ms_ = now;
2511 return false;
2512 }
2513 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2514 return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
2515 }
2516
asapersson1394c7b2016-10-18 11:50:50 -07002517 bool MinNumberOfFramesReceived() const {
2518 const int kMinRequiredHistogramSamples = 200;
2519 rtc::CritScope lock(&crit_);
2520 return num_frames_received_ > kMinRequiredHistogramSamples;
2521 }
2522
stefanff483612015-12-21 03:14:00 -08002523 void ModifyVideoConfigs(
2524 VideoSendStream::Config* send_config,
2525 std::vector<VideoReceiveStream::Config>* receive_configs,
2526 VideoEncoderConfig* encoder_config) override {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002527 // NACK
2528 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2529 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
tommi2e82f382016-06-21 00:26:43 -07002530 (*receive_configs)[0].renderer = this;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002531 // FEC
2532 if (use_red_) {
brandtrb5f2c3f2016-10-04 23:28:39 -07002533 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
2534 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
Peter Boström39593972016-02-15 11:27:15 +01002535 send_config->encoder_settings.encoder = vp8_encoder_.get();
2536 send_config->encoder_settings.payload_name = "VP8";
2537 (*receive_configs)[0].decoders[0].payload_name = "VP8";
brandtrb5f2c3f2016-10-04 23:28:39 -07002538 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
2539 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type =
2540 kUlpfecPayloadType;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002541 }
2542 // RTX
2543 if (use_rtx_) {
2544 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
2545 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
brandtr14742122017-01-27 04:53:07 -08002546 (*receive_configs)[0].rtp.rtx_ssrc = kSendRtxSsrcs[0];
2547 (*receive_configs)[0].rtp.rtx_payload_types[kFakeVideoSendPayloadType] =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002548 kSendRtxPayloadType;
2549 }
asapersson1490f7a2016-09-23 02:09:46 -07002550 // RTT needed for RemoteNtpTimeEstimator for the receive stream.
2551 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = true;
sprangb4a1ae52015-12-03 08:10:08 -08002552 encoder_config->content_type =
2553 screenshare_ ? VideoEncoderConfig::ContentType::kScreen
2554 : VideoEncoderConfig::ContentType::kRealtimeVideo;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002555 }
2556
2557 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2558 sender_call_ = sender_call;
2559 receiver_call_ = receiver_call;
2560 }
2561
Åsa Persson3c391cb2015-04-27 10:09:49 +02002562 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002563 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson3c391cb2015-04-27 10:09:49 +02002564 }
2565
asapersson1394c7b2016-10-18 11:50:50 -07002566 rtc::CriticalSection crit_;
sprangb4a1ae52015-12-03 08:10:08 -08002567 const bool use_rtx_;
2568 const bool use_red_;
2569 const bool screenshare_;
kwiberg27f982b2016-03-01 11:52:33 -08002570 const std::unique_ptr<VideoEncoder> vp8_encoder_;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002571 Call* sender_call_;
2572 Call* receiver_call_;
2573 int64_t start_runtime_ms_;
asapersson1394c7b2016-10-18 11:50:50 -07002574 int num_frames_received_ GUARDED_BY(&crit_);
sprangb4a1ae52015-12-03 08:10:08 -08002575 } test(use_rtx, use_red, screenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002576
asapersson01d70a32016-05-20 06:29:46 -07002577 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002578 RunBaseTest(&test);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002579
stefan91d92602015-11-11 10:13:02 -08002580 // Delete the call for Call stats to be reported.
stefan18adf0a2015-11-17 06:24:56 -08002581 sender_call_.reset();
stefan91d92602015-11-11 10:13:02 -08002582 receiver_call_.reset();
2583
sprangb4a1ae52015-12-03 08:10:08 -08002584 std::string video_prefix =
2585 screenshare ? "WebRTC.Video.Screenshare." : "WebRTC.Video.";
2586
Åsa Persson3c391cb2015-04-27 10:09:49 +02002587 // Verify that stats have been updated once.
asapersson4374a092016-07-27 00:39:09 -07002588 EXPECT_EQ(2, metrics::NumSamples("WebRTC.Call.LifetimeInSeconds"));
asapersson01d70a32016-05-20 06:29:46 -07002589 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
2590 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.RtcpBitrateReceivedInBps"));
2591 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.BitrateReceivedInKbps"));
2592 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.EstimatedSendBitrateInKbps"));
2593 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.PacerBitrateInKbps"));
2594
asapersson4374a092016-07-27 00:39:09 -07002595 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
2596 EXPECT_EQ(1,
2597 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
2598
asapersson01d70a32016-05-20 06:29:46 -07002599 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
stefan91d92602015-11-11 10:13:02 -08002600 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002601 metrics::NumSamples(video_prefix + "NackPacketsReceivedPerMinute"));
2602 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
asaperssond89920b2015-07-22 06:52:00 -07002603 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002604 metrics::NumSamples(video_prefix + "FirPacketsReceivedPerMinute"));
2605 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
sprangb4a1ae52015-12-03 08:10:08 -08002606 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002607 metrics::NumSamples(video_prefix + "PliPacketsReceivedPerMinute"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002608
asapersson01d70a32016-05-20 06:29:46 -07002609 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "KeyFramesSentInPermille"));
2610 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
2611
2612 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentPacketsLostInPercent"));
2613 EXPECT_EQ(1,
2614 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
2615
2616 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputWidthInPixels"));
2617 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputHeightInPixels"));
2618 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentWidthInPixels"));
2619 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentHeightInPixels"));
2620 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
2621 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
2622
perkjfa10b552016-10-02 23:45:26 -07002623 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputWidthInPixels",
2624 kDefaultWidth));
2625 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputHeightInPixels",
2626 kDefaultHeight));
2627 EXPECT_EQ(
2628 1, metrics::NumEvents(video_prefix + "SentWidthInPixels", kDefaultWidth));
2629 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "SentHeightInPixels",
2630 kDefaultHeight));
2631 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedWidthInPixels",
2632 kDefaultWidth));
2633 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedHeightInPixels",
2634 kDefaultHeight));
asapersson01d70a32016-05-20 06:29:46 -07002635
2636 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputFramesPerSecond"));
2637 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentFramesPerSecond"));
2638 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
2639 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
2640
2641 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
2642 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
2643 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
2644 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
2645
asapersson1490f7a2016-09-23 02:09:46 -07002646 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.EndToEndDelayInMs"));
asapersson01d70a32016-05-20 06:29:46 -07002647 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
2648
2649 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EncodeTimeInMs"));
2650 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
2651
asapersson66d4b372016-12-19 06:50:53 -08002652 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "NumberOfPauseEvents"));
2653 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PausedTimeInPercent"));
2654
asapersson01d70a32016-05-20 06:29:46 -07002655 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "BitrateSentInKbps"));
2656 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateReceivedInKbps"));
2657 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "MediaBitrateSentInKbps"));
2658 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateReceivedInKbps"));
2659 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PaddingBitrateSentInKbps"));
2660 EXPECT_EQ(1,
2661 metrics::NumSamples("WebRTC.Video.PaddingBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002662 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002663 1, metrics::NumSamples(video_prefix + "RetransmittedBitrateSentInKbps"));
2664 EXPECT_EQ(1, metrics::NumSamples(
2665 "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002666
asapersson01d70a32016-05-20 06:29:46 -07002667 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendDelayInMs"));
2668 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayInMs"));
2669 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayMaxInMs"));
asapersson6f14be82015-11-16 00:40:49 -08002670
Åsa Persson3c391cb2015-04-27 10:09:49 +02002671 int num_rtx_samples = use_rtx ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002672 EXPECT_EQ(num_rtx_samples,
2673 metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2674 EXPECT_EQ(num_rtx_samples,
2675 metrics::NumSamples("WebRTC.Video.RtxBitrateReceivedInKbps"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002676
2677 int num_red_samples = use_red ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002678 EXPECT_EQ(num_red_samples,
2679 metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2680 EXPECT_EQ(num_red_samples,
2681 metrics::NumSamples("WebRTC.Video.FecBitrateReceivedInKbps"));
2682 EXPECT_EQ(num_red_samples,
2683 metrics::NumSamples("WebRTC.Video.ReceivedFecPacketsInPercent"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002684}
2685
philipel277a8b52017-03-16 05:19:49 -07002686TEST_F(EndToEndTest, VerifyHistogramStatsWithRtx) {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002687 const bool kEnabledRtx = true;
2688 const bool kEnabledRed = false;
sprangb4a1ae52015-12-03 08:10:08 -08002689 const bool kScreenshare = false;
2690 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002691}
2692
philipel277a8b52017-03-16 05:19:49 -07002693TEST_F(EndToEndTest, VerifyHistogramStatsWithRed) {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002694 const bool kEnabledRtx = false;
2695 const bool kEnabledRed = true;
sprangb4a1ae52015-12-03 08:10:08 -08002696 const bool kScreenshare = false;
2697 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
2698}
2699
philipel277a8b52017-03-16 05:19:49 -07002700TEST_F(EndToEndTest, VerifyHistogramStatsWithScreenshare) {
sprangb4a1ae52015-12-03 08:10:08 -08002701 const bool kEnabledRtx = false;
2702 const bool kEnabledRed = false;
2703 const bool kScreenshare = true;
2704 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002705}
2706
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002707void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
2708 bool send_single_ssrc_first) {
2709 class SendsSetSsrcs : public test::EndToEndTest {
2710 public:
2711 SendsSetSsrcs(const uint32_t* ssrcs,
2712 size_t num_ssrcs,
2713 bool send_single_ssrc_first)
2714 : EndToEndTest(kDefaultTimeoutMs),
2715 num_ssrcs_(num_ssrcs),
2716 send_single_ssrc_first_(send_single_ssrc_first),
2717 ssrcs_to_observe_(num_ssrcs),
sprang867fb522015-08-03 04:38:41 -07002718 expect_single_ssrc_(send_single_ssrc_first),
2719 send_stream_(nullptr) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002720 for (size_t i = 0; i < num_ssrcs; ++i)
2721 valid_ssrcs_[ssrcs[i]] = true;
2722 }
2723
2724 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002725 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002726 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002727 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002728
2729 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
2730 << "Received unknown SSRC: " << header.ssrc;
2731
2732 if (!valid_ssrcs_[header.ssrc])
Peter Boström5811a392015-12-10 13:02:50 +01002733 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002734
2735 if (!is_observed_[header.ssrc]) {
2736 is_observed_[header.ssrc] = true;
2737 --ssrcs_to_observe_;
2738 if (expect_single_ssrc_) {
2739 expect_single_ssrc_ = false;
Peter Boström5811a392015-12-10 13:02:50 +01002740 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002741 }
2742 }
2743
2744 if (ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002745 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002746
2747 return SEND_PACKET;
2748 }
2749
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002750 size_t GetNumVideoStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002751
perkjfa10b552016-10-02 23:45:26 -07002752 // This test use other VideoStream settings than the the default settings
2753 // implemented in DefaultVideoStreamFactory. Therefore this test implement
2754 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
2755 // in ModifyVideoConfigs.
2756 class VideoStreamFactory
2757 : public VideoEncoderConfig::VideoStreamFactoryInterface {
2758 public:
2759 VideoStreamFactory() {}
2760
2761 private:
2762 std::vector<VideoStream> CreateEncoderStreams(
2763 int width,
2764 int height,
2765 const VideoEncoderConfig& encoder_config) override {
2766 std::vector<VideoStream> streams =
2767 test::CreateVideoStreams(width, height, encoder_config);
2768 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
2769 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
2770 streams[i].min_bitrate_bps = 10000;
2771 streams[i].target_bitrate_bps = 15000;
2772 streams[i].max_bitrate_bps = 20000;
2773 }
2774 return streams;
2775 }
2776 };
2777
stefanff483612015-12-21 03:14:00 -08002778 void ModifyVideoConfigs(
2779 VideoSendStream::Config* send_config,
2780 std::vector<VideoReceiveStream::Config>* receive_configs,
2781 VideoEncoderConfig* encoder_config) override {
perkjfa10b552016-10-02 23:45:26 -07002782 encoder_config->video_stream_factory =
2783 new rtc::RefCountedObject<VideoStreamFactory>();
perkj26091b12016-09-01 01:17:40 -07002784 video_encoder_config_all_streams_ = encoder_config->Copy();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002785 if (send_single_ssrc_first_)
perkjfa10b552016-10-02 23:45:26 -07002786 encoder_config->number_of_streams = 1;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002787 }
2788
stefanff483612015-12-21 03:14:00 -08002789 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002790 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002791 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002792 send_stream_ = send_stream;
2793 }
2794
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002795 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002796 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2797 << (send_single_ssrc_first_ ? "first SSRC."
2798 : "SSRCs.");
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002799
2800 if (send_single_ssrc_first_) {
2801 // Set full simulcast and continue with the rest of the SSRCs.
stefanff483612015-12-21 03:14:00 -08002802 send_stream_->ReconfigureVideoEncoder(
perkj26091b12016-09-01 01:17:40 -07002803 std::move(video_encoder_config_all_streams_));
Peter Boström5811a392015-12-10 13:02:50 +01002804 EXPECT_TRUE(Wait()) << "Timed out while waiting on additional SSRCs.";
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002805 }
2806 }
2807
2808 private:
2809 std::map<uint32_t, bool> valid_ssrcs_;
2810 std::map<uint32_t, bool> is_observed_;
2811
2812 const size_t num_ssrcs_;
2813 const bool send_single_ssrc_first_;
2814
2815 size_t ssrcs_to_observe_;
2816 bool expect_single_ssrc_;
2817
2818 VideoSendStream* send_stream_;
stefanff483612015-12-21 03:14:00 -08002819 VideoEncoderConfig video_encoder_config_all_streams_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002820 } test(kVideoSendSsrcs, num_ssrcs, send_single_ssrc_first);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002821
stefane74eef12016-01-08 06:47:13 -08002822 RunBaseTest(&test);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002823}
2824
philipel277a8b52017-03-16 05:19:49 -07002825TEST_F(EndToEndTest, ReportsSetEncoderRates) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002826 class EncoderRateStatsTest : public test::EndToEndTest,
2827 public test::FakeEncoder {
2828 public:
2829 EncoderRateStatsTest()
2830 : EndToEndTest(kDefaultTimeoutMs),
sprang867fb522015-08-03 04:38:41 -07002831 FakeEncoder(Clock::GetRealTimeClock()),
2832 send_stream_(nullptr),
2833 bitrate_kbps_(0) {}
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002834
stefanff483612015-12-21 03:14:00 -08002835 void OnVideoStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002836 VideoSendStream* send_stream,
2837 const std::vector<VideoReceiveStream*>& receive_streams) override {
2838 send_stream_ = send_stream;
2839 }
2840
stefanff483612015-12-21 03:14:00 -08002841 void ModifyVideoConfigs(
2842 VideoSendStream::Config* send_config,
2843 std::vector<VideoReceiveStream::Config>* receive_configs,
2844 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002845 send_config->encoder_settings.encoder = this;
kwibergaf476c72016-11-28 15:21:39 -08002846 RTC_DCHECK_EQ(1, encoder_config->number_of_streams);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002847 }
2848
Erik Språng08127a92016-11-16 16:41:30 +01002849 int32_t SetRateAllocation(const BitrateAllocation& rate_allocation,
2850 uint32_t framerate) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002851 // Make sure not to trigger on any default zero bitrates.
Erik Språng08127a92016-11-16 16:41:30 +01002852 if (rate_allocation.get_sum_bps() == 0)
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002853 return 0;
Peter Boströmf2f82832015-05-01 13:00:41 +02002854 rtc::CritScope lock(&crit_);
Erik Språng08127a92016-11-16 16:41:30 +01002855 bitrate_kbps_ = rate_allocation.get_sum_kbps();
Peter Boström5811a392015-12-10 13:02:50 +01002856 observation_complete_.Set();
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002857 return 0;
2858 }
2859
2860 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002861 ASSERT_TRUE(Wait())
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002862 << "Timed out while waiting for encoder SetRates() call.";
perkjf5b2e512016-07-05 08:34:04 -07002863 WaitForEncoderTargetBitrateMatchStats();
2864 send_stream_->Stop();
2865 WaitForStatsReportZeroTargetBitrate();
2866 send_stream_->Start();
2867 WaitForEncoderTargetBitrateMatchStats();
2868 }
2869
2870 void WaitForEncoderTargetBitrateMatchStats() {
Peter Boström5811a392015-12-10 13:02:50 +01002871 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002872 VideoSendStream::Stats stats = send_stream_->GetStats();
2873 {
Peter Boströmf2f82832015-05-01 13:00:41 +02002874 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002875 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
2876 static_cast<int>(bitrate_kbps_)) {
2877 return;
2878 }
2879 }
2880 SleepMs(1);
2881 }
2882 FAIL()
2883 << "Timed out waiting for stats reporting the currently set bitrate.";
2884 }
2885
perkjf5b2e512016-07-05 08:34:04 -07002886 void WaitForStatsReportZeroTargetBitrate() {
2887 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
2888 if (send_stream_->GetStats().target_media_bitrate_bps == 0) {
2889 return;
2890 }
2891 SleepMs(1);
2892 }
2893 FAIL() << "Timed out waiting for stats reporting zero bitrate.";
2894 }
2895
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002896 private:
stefanf116bd02015-10-27 08:29:42 -07002897 rtc::CriticalSection crit_;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002898 VideoSendStream* send_stream_;
2899 uint32_t bitrate_kbps_ GUARDED_BY(crit_);
2900 } test;
2901
stefane74eef12016-01-08 06:47:13 -08002902 RunBaseTest(&test);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002903}
2904
philipel277a8b52017-03-16 05:19:49 -07002905TEST_F(EndToEndTest, GetStats) {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002906 static const int kStartBitrateBps = 3000000;
Peter Boströmdef398832015-05-27 17:59:11 +02002907 static const int kExpectedRenderDelayMs = 20;
tommi2e82f382016-06-21 00:26:43 -07002908
2909 class ReceiveStreamRenderer : public rtc::VideoSinkInterface<VideoFrame> {
2910 public:
2911 ReceiveStreamRenderer() {}
2912
2913 private:
2914 void OnFrame(const VideoFrame& video_frame) override {}
2915 };
2916
nissed30a1112016-04-18 05:15:22 -07002917 class StatsObserver : public test::EndToEndTest,
2918 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002919 public:
stefanf116bd02015-10-27 08:29:42 -07002920 StatsObserver()
2921 : EndToEndTest(kLongTimeoutMs),
Peter Boströmc6e16e32016-02-05 14:15:53 +01002922 encoder_(Clock::GetRealTimeClock(), 10),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002923 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002924 expected_send_ssrcs_(),
Peter Boström5811a392015-12-10 13:02:50 +01002925 check_stats_event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002926
2927 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002928 Action OnSendRtp(const uint8_t* packet, size_t length) override {
sprangcd349d92016-07-13 09:11:28 -07002929 // Drop every 25th packet => 4% loss.
2930 static const int kPacketLossFrac = 25;
2931 RTPHeader header;
2932 RtpUtility::RtpHeaderParser parser(packet, length);
2933 if (parser.Parse(&header) &&
2934 expected_send_ssrcs_.find(header.ssrc) !=
2935 expected_send_ssrcs_.end() &&
2936 header.sequenceNumber % kPacketLossFrac == 0) {
2937 return DROP_PACKET;
2938 }
Peter Boström5811a392015-12-10 13:02:50 +01002939 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002940 return SEND_PACKET;
2941 }
2942
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002943 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002944 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002945 return SEND_PACKET;
2946 }
2947
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002948 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002949 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002950 return SEND_PACKET;
2951 }
2952
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002953 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002954 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002955 return SEND_PACKET;
2956 }
2957
nissed30a1112016-04-18 05:15:22 -07002958 void OnFrame(const VideoFrame& video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002959 // Ensure that we have at least 5ms send side delay.
nissed30a1112016-04-18 05:15:22 -07002960 SleepMs(5);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002961 }
2962
2963 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002964 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2965 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2966 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002967
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002968 // Make sure all fields have been populated.
2969 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
2970 // always filled for all receivers.
2971 receive_stats_filled_["IncomingRate"] |=
2972 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002973
Peter Boströmb7d9a972015-12-18 16:01:11 +01002974 send_stats_filled_["DecoderImplementationName"] |=
2975 stats.decoder_implementation_name ==
2976 test::FakeDecoder::kImplementationName;
Peter Boströmdef398832015-05-27 17:59:11 +02002977 receive_stats_filled_["RenderDelayAsHighAsExpected"] |=
2978 stats.render_delay_ms >= kExpectedRenderDelayMs;
2979
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002980 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002981
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002982 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002983
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002984 receive_stats_filled_["StatisticsUpdated"] |=
2985 stats.rtcp_stats.cumulative_lost != 0 ||
2986 stats.rtcp_stats.extended_max_sequence_number != 0 ||
2987 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002988
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002989 receive_stats_filled_["DataCountersUpdated"] |=
2990 stats.rtp_stats.transmitted.payload_bytes != 0 ||
2991 stats.rtp_stats.fec.packets != 0 ||
2992 stats.rtp_stats.transmitted.header_bytes != 0 ||
2993 stats.rtp_stats.transmitted.packets != 0 ||
2994 stats.rtp_stats.transmitted.padding_bytes != 0 ||
2995 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002996
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002997 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002998 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002999
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003000 receive_stats_filled_["FrameCounts"] |=
3001 stats.frame_counts.key_frames != 0 ||
3002 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00003003
pbosbb36fdf2015-07-09 07:48:14 -07003004 receive_stats_filled_["CName"] |= !stats.c_name.empty();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00003005
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003006 receive_stats_filled_["RtcpPacketTypeCount"] |=
3007 stats.rtcp_packet_type_counts.fir_packets != 0 ||
3008 stats.rtcp_packet_type_counts.nack_packets != 0 ||
3009 stats.rtcp_packet_type_counts.pli_packets != 0 ||
3010 stats.rtcp_packet_type_counts.nack_requests != 0 ||
3011 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbosf42376c2015-08-28 07:35:32 -07003012
3013 assert(stats.current_payload_type == -1 ||
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003014 stats.current_payload_type == kFakeVideoSendPayloadType);
pbosf42376c2015-08-28 07:35:32 -07003015 receive_stats_filled_["IncomingPayloadType"] |=
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003016 stats.current_payload_type == kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003017 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003018
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003019 return AllStatsFilled(receive_stats_filled_);
3020 }
3021
3022 bool CheckSendStats() {
Peter Boström74f6e9e2016-04-04 17:56:10 +02003023 RTC_DCHECK(send_stream_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003024 VideoSendStream::Stats stats = send_stream_->GetStats();
3025
philipel20d05a92016-12-19 04:17:27 -08003026 size_t expected_num_streams = kNumSsrcs + expected_send_ssrcs_.size();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003027 send_stats_filled_["NumStreams"] |=
philipel20d05a92016-12-19 04:17:27 -08003028 stats.substreams.size() == expected_num_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003029
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00003030 send_stats_filled_["CpuOveruseMetrics"] |=
Peter Boströme4499152016-02-05 11:13:28 +01003031 stats.avg_encode_time_ms != 0 && stats.encode_usage_percent != 0;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00003032
Peter Boströmb7d9a972015-12-18 16:01:11 +01003033 send_stats_filled_["EncoderImplementationName"] |=
3034 stats.encoder_implementation_name ==
3035 test::FakeEncoder::kImplementationName;
3036
Pera48ddb72016-09-29 11:48:50 +02003037 send_stats_filled_["EncoderPreferredBitrate"] |=
3038 stats.preferred_media_bitrate_bps > 0;
3039
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003040 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003041 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003042 it != stats.substreams.end(); ++it) {
sprangcd349d92016-07-13 09:11:28 -07003043 if (expected_send_ssrcs_.find(it->first) == expected_send_ssrcs_.end())
3044 continue; // Probably RTX.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003045
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003046 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003047 stats.input_frame_rate != 0;
3048
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003049 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003050
3051 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
3052 stream_stats.rtcp_stats.cumulative_lost != 0 ||
3053 stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
3054 stream_stats.rtcp_stats.fraction_lost != 0;
3055
3056 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00003057 stream_stats.rtp_stats.fec.packets != 0 ||
3058 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
3059 stream_stats.rtp_stats.retransmitted.packets != 0 ||
3060 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003061
sprangcd349d92016-07-13 09:11:28 -07003062 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Total",
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003063 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00003064 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003065
sprangcd349d92016-07-13 09:11:28 -07003066 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Retransmit",
3067 it->first)] |=
3068 stream_stats.retransmit_bitrate_bps != 0;
3069
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003070 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00003071 stream_stats.frame_counts.delta_frames != 0 ||
3072 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003073
3074 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
3075 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00003076
3077 send_stats_filled_[CompoundKey("Delay", it->first)] |=
3078 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003079
3080 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
3081 // report dropped packets.
3082 send_stats_filled_["RtcpPacketTypeCount"] |=
3083 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
3084 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
3085 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
3086 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
3087 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003088 }
3089
3090 return AllStatsFilled(send_stats_filled_);
3091 }
3092
3093 std::string CompoundKey(const char* name, uint32_t ssrc) {
3094 std::ostringstream oss;
3095 oss << name << "_" << ssrc;
3096 return oss.str();
3097 }
3098
3099 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
sprangcd349d92016-07-13 09:11:28 -07003100 for (const auto& stat : stats_map) {
3101 if (!stat.second)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003102 return false;
3103 }
3104 return true;
3105 }
3106
stefane74eef12016-01-08 06:47:13 -08003107 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
3108 FakeNetworkPipe::Config network_config;
3109 network_config.loss_percent = 5;
3110 return new test::PacketTransport(
nissee5ad5ca2017-03-29 23:57:43 -07003111 sender_call, this, test::PacketTransport::kSender, MediaType::VIDEO,
3112 network_config);
stefane74eef12016-01-08 06:47:13 -08003113 }
3114
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003115 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00003116 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01003117 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00003118 return config;
3119 }
3120
perkjfa10b552016-10-02 23:45:26 -07003121 // This test use other VideoStream settings than the the default settings
3122 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3123 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3124 // in ModifyVideoConfigs.
3125 class VideoStreamFactory
3126 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3127 public:
3128 VideoStreamFactory() {}
3129
3130 private:
3131 std::vector<VideoStream> CreateEncoderStreams(
3132 int width,
3133 int height,
3134 const VideoEncoderConfig& encoder_config) override {
3135 std::vector<VideoStream> streams =
3136 test::CreateVideoStreams(width, height, encoder_config);
3137 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
3138 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3139 streams[i].min_bitrate_bps = 10000;
3140 streams[i].target_bitrate_bps = 15000;
3141 streams[i].max_bitrate_bps = 20000;
3142 }
3143 return streams;
3144 }
3145 };
3146
stefanff483612015-12-21 03:14:00 -08003147 void ModifyVideoConfigs(
3148 VideoSendStream::Config* send_config,
3149 std::vector<VideoReceiveStream::Config>* receive_configs,
3150 VideoEncoderConfig* encoder_config) override {
perkjfa10b552016-10-02 23:45:26 -07003151 encoder_config->video_stream_factory =
3152 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003153 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003154 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003155
sprangcd349d92016-07-13 09:11:28 -07003156 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
3157 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
3158
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003159 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003160 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003161 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003162 expected_receive_ssrcs_.push_back(
3163 (*receive_configs)[i].rtp.remote_ssrc);
Peter Boströmdef398832015-05-27 17:59:11 +02003164 (*receive_configs)[i].render_delay_ms = kExpectedRenderDelayMs;
tommi2e82f382016-06-21 00:26:43 -07003165 (*receive_configs)[i].renderer = &receive_stream_renderer_;
sprangcd349d92016-07-13 09:11:28 -07003166 (*receive_configs)[i].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
3167
brandtr14742122017-01-27 04:53:07 -08003168 (*receive_configs)[i].rtp.rtx_ssrc = kSendRtxSsrcs[i];
3169 (*receive_configs)[i].rtp.rtx_payload_types[kFakeVideoSendPayloadType] =
sprangcd349d92016-07-13 09:11:28 -07003170 kSendRtxPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003171 }
sprangcd349d92016-07-13 09:11:28 -07003172
3173 for (size_t i = 0; i < kNumSsrcs; ++i)
3174 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
3175
Peter Boströmc6e16e32016-02-05 14:15:53 +01003176 // Use a delayed encoder to make sure we see CpuOveruseMetrics stats that
3177 // are non-zero.
3178 send_config->encoder_settings.encoder = &encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003179 }
3180
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003181 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00003182
stefanff483612015-12-21 03:14:00 -08003183 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003184 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003185 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003186 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003187 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003188 }
3189
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003190 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003191 Clock* clock = Clock::GetRealTimeClock();
3192 int64_t now = clock->TimeInMilliseconds();
3193 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
3194 bool receive_ok = false;
3195 bool send_ok = false;
3196
3197 while (now < stop_time) {
3198 if (!receive_ok)
3199 receive_ok = CheckReceiveStats();
3200 if (!send_ok)
3201 send_ok = CheckSendStats();
3202
3203 if (receive_ok && send_ok)
3204 return;
3205
3206 int64_t time_until_timout_ = stop_time - now;
3207 if (time_until_timout_ > 0)
Peter Boström5811a392015-12-10 13:02:50 +01003208 check_stats_event_.Wait(time_until_timout_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003209 now = clock->TimeInMilliseconds();
3210 }
3211
3212 ADD_FAILURE() << "Timed out waiting for filled stats.";
3213 for (std::map<std::string, bool>::const_iterator it =
3214 receive_stats_filled_.begin();
3215 it != receive_stats_filled_.end();
3216 ++it) {
3217 if (!it->second) {
3218 ADD_FAILURE() << "Missing receive stats: " << it->first;
3219 }
3220 }
3221
3222 for (std::map<std::string, bool>::const_iterator it =
3223 send_stats_filled_.begin();
3224 it != send_stats_filled_.end();
3225 ++it) {
3226 if (!it->second) {
3227 ADD_FAILURE() << "Missing send stats: " << it->first;
3228 }
3229 }
3230 }
3231
Peter Boströmc6e16e32016-02-05 14:15:53 +01003232 test::DelayedEncoder encoder_;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003233 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003234 std::map<std::string, bool> receive_stats_filled_;
3235
3236 VideoSendStream* send_stream_;
3237 std::map<std::string, bool> send_stats_filled_;
3238
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003239 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003240 std::set<uint32_t> expected_send_ssrcs_;
3241 std::string expected_cname_;
3242
Peter Boström5811a392015-12-10 13:02:50 +01003243 rtc::Event check_stats_event_;
tommi2e82f382016-06-21 00:26:43 -07003244 ReceiveStreamRenderer receive_stream_renderer_;
stefanf116bd02015-10-27 08:29:42 -07003245 } test;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003246
stefane74eef12016-01-08 06:47:13 -08003247 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003248}
3249
sprang1a646ee2016-12-01 06:34:11 -08003250class RtcpXrObserver : public test::EndToEndTest {
3251 public:
sprang44b3ef62017-01-13 07:30:25 -08003252 RtcpXrObserver(bool enable_rrtr, bool enable_target_bitrate)
sprang1a646ee2016-12-01 06:34:11 -08003253 : EndToEndTest(test::CallTest::kDefaultTimeoutMs),
3254 enable_rrtr_(enable_rrtr),
sprang44b3ef62017-01-13 07:30:25 -08003255 enable_target_bitrate_(enable_target_bitrate),
sprang1a646ee2016-12-01 06:34:11 -08003256 sent_rtcp_sr_(0),
3257 sent_rtcp_rr_(0),
3258 sent_rtcp_rrtr_(0),
3259 sent_rtcp_target_bitrate_(false),
3260 sent_rtcp_dlrr_(0) {}
3261
3262 private:
3263 // Receive stream should send RR packets (and RRTR packets if enabled).
3264 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
3265 rtc::CritScope lock(&crit_);
3266 test::RtcpPacketParser parser;
3267 EXPECT_TRUE(parser.Parse(packet, length));
3268
3269 sent_rtcp_rr_ += parser.receiver_report()->num_packets();
3270 EXPECT_EQ(0, parser.sender_report()->num_packets());
3271 EXPECT_GE(1, parser.xr()->num_packets());
3272 if (parser.xr()->num_packets() > 0) {
3273 if (parser.xr()->rrtr())
3274 ++sent_rtcp_rrtr_;
3275 EXPECT_FALSE(parser.xr()->dlrr());
3276 }
3277
3278 return SEND_PACKET;
3279 }
3280 // Send stream should send SR packets (and DLRR packets if enabled).
3281 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
3282 rtc::CritScope lock(&crit_);
3283 test::RtcpPacketParser parser;
3284 EXPECT_TRUE(parser.Parse(packet, length));
3285
3286 sent_rtcp_sr_ += parser.sender_report()->num_packets();
3287 EXPECT_LE(parser.xr()->num_packets(), 1);
3288 if (parser.xr()->num_packets() > 0) {
3289 EXPECT_FALSE(parser.xr()->rrtr());
3290 if (parser.xr()->dlrr())
3291 ++sent_rtcp_dlrr_;
3292 if (parser.xr()->target_bitrate())
3293 sent_rtcp_target_bitrate_ = true;
3294 }
3295
3296 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
3297 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve &&
sprang44b3ef62017-01-13 07:30:25 -08003298 (sent_rtcp_target_bitrate_ || !enable_target_bitrate_)) {
sprang1a646ee2016-12-01 06:34:11 -08003299 if (enable_rrtr_) {
3300 EXPECT_GT(sent_rtcp_rrtr_, 0);
3301 EXPECT_GT(sent_rtcp_dlrr_, 0);
3302 } else {
3303 EXPECT_EQ(sent_rtcp_rrtr_, 0);
3304 EXPECT_EQ(sent_rtcp_dlrr_, 0);
3305 }
sprang44b3ef62017-01-13 07:30:25 -08003306 EXPECT_EQ(enable_target_bitrate_, sent_rtcp_target_bitrate_);
sprang1a646ee2016-12-01 06:34:11 -08003307 observation_complete_.Set();
3308 }
3309 return SEND_PACKET;
3310 }
3311
3312 void ModifyVideoConfigs(
3313 VideoSendStream::Config* send_config,
3314 std::vector<VideoReceiveStream::Config>* receive_configs,
3315 VideoEncoderConfig* encoder_config) override {
sprang44b3ef62017-01-13 07:30:25 -08003316 if (enable_target_bitrate_) {
3317 // TargetBitrate only signaled for screensharing.
3318 encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
3319 }
sprang1a646ee2016-12-01 06:34:11 -08003320 (*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
3321 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
3322 enable_rrtr_;
3323 }
3324
3325 void PerformTest() override {
3326 EXPECT_TRUE(Wait())
3327 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
3328 }
3329
3330 static const int kNumRtcpReportPacketsToObserve = 5;
3331
3332 rtc::CriticalSection crit_;
sprang44b3ef62017-01-13 07:30:25 -08003333 const bool enable_rrtr_;
3334 const bool enable_target_bitrate_;
sprang1a646ee2016-12-01 06:34:11 -08003335 int sent_rtcp_sr_;
3336 int sent_rtcp_rr_ GUARDED_BY(&crit_);
3337 int sent_rtcp_rrtr_ GUARDED_BY(&crit_);
3338 bool sent_rtcp_target_bitrate_ GUARDED_BY(&crit_);
3339 int sent_rtcp_dlrr_;
3340};
3341
philipel277a8b52017-03-16 05:19:49 -07003342TEST_F(EndToEndTest, TestExtendedReportsWithRrtrWithoutTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003343 RtcpXrObserver test(true, false);
sprang1a646ee2016-12-01 06:34:11 -08003344 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003345}
3346
philipel277a8b52017-03-16 05:19:49 -07003347TEST_F(EndToEndTest, TestExtendedReportsWithoutRrtrWithoutTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003348 RtcpXrObserver test(false, false);
3349 RunBaseTest(&test);
3350}
3351
philipel277a8b52017-03-16 05:19:49 -07003352TEST_F(EndToEndTest, TestExtendedReportsWithRrtrWithTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003353 RtcpXrObserver test(true, true);
3354 RunBaseTest(&test);
3355}
3356
philipel277a8b52017-03-16 05:19:49 -07003357TEST_F(EndToEndTest, TestExtendedReportsWithoutRrtrWithTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003358 RtcpXrObserver test(false, true);
sprang1a646ee2016-12-01 06:34:11 -08003359 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003360}
3361
philipel277a8b52017-03-16 05:19:49 -07003362TEST_F(EndToEndTest, TestReceivedRtpPacketStats) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003363 static const size_t kNumRtpPacketsToSend = 5;
3364 class ReceivedRtpStatsObserver : public test::EndToEndTest {
3365 public:
3366 ReceivedRtpStatsObserver()
3367 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00003368 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003369 sent_rtp_(0) {}
3370
3371 private:
stefanff483612015-12-21 03:14:00 -08003372 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003373 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003374 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003375 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003376 }
3377
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003378 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003379 if (sent_rtp_ >= kNumRtpPacketsToSend) {
3380 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00003381 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
Peter Boström5811a392015-12-10 13:02:50 +01003382 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003383 }
3384 return DROP_PACKET;
3385 }
3386 ++sent_rtp_;
3387 return SEND_PACKET;
3388 }
3389
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003390 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003391 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003392 << "Timed out while verifying number of received RTP packets.";
3393 }
3394
3395 VideoReceiveStream* receive_stream_;
3396 uint32_t sent_rtp_;
3397 } test;
3398
stefane74eef12016-01-08 06:47:13 -08003399 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003400}
3401
philipel277a8b52017-03-16 05:19:49 -07003402TEST_F(EndToEndTest, SendsSetSsrc) {
philipel266f0a42016-11-28 08:49:07 -08003403 TestSendsSetSsrcs(1, false);
3404}
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003405
philipel277a8b52017-03-16 05:19:49 -07003406TEST_F(EndToEndTest, SendsSetSimulcastSsrcs) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003407 TestSendsSetSsrcs(kNumSsrcs, false);
3408}
3409
philipel277a8b52017-03-16 05:19:49 -07003410TEST_F(EndToEndTest, CanSwitchToUseAllSsrcs) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003411 TestSendsSetSsrcs(kNumSsrcs, true);
3412}
3413
philipel277a8b52017-03-16 05:19:49 -07003414TEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003415 class ObserveRedundantPayloads: public test::EndToEndTest {
3416 public:
3417 ObserveRedundantPayloads()
3418 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003419 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003420 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
3421 }
3422 }
3423
3424 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003425 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003426 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003427 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003428
3429 if (!registered_rtx_ssrc_[header.ssrc])
3430 return SEND_PACKET;
3431
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003432 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003433 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003434 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003435
3436 if (!packet_is_redundant_payload)
3437 return SEND_PACKET;
3438
3439 if (!observed_redundant_retransmission_[header.ssrc]) {
3440 observed_redundant_retransmission_[header.ssrc] = true;
3441 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01003442 observation_complete_.Set();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003443 }
3444
3445 return SEND_PACKET;
3446 }
3447
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003448 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003449
perkjfa10b552016-10-02 23:45:26 -07003450 // This test use other VideoStream settings than the the default settings
3451 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3452 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3453 // in ModifyVideoConfigs.
3454 class VideoStreamFactory
3455 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3456 public:
3457 VideoStreamFactory() {}
3458
3459 private:
3460 std::vector<VideoStream> CreateEncoderStreams(
3461 int width,
3462 int height,
3463 const VideoEncoderConfig& encoder_config) override {
3464 std::vector<VideoStream> streams =
3465 test::CreateVideoStreams(width, height, encoder_config);
3466 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
3467 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3468 streams[i].min_bitrate_bps = 10000;
3469 streams[i].target_bitrate_bps = 15000;
3470 streams[i].max_bitrate_bps = 20000;
3471 }
3472 return streams;
3473 }
3474 };
3475
stefanff483612015-12-21 03:14:00 -08003476 void ModifyVideoConfigs(
3477 VideoSendStream::Config* send_config,
3478 std::vector<VideoReceiveStream::Config>* receive_configs,
3479 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003480 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
perkjfa10b552016-10-02 23:45:26 -07003481 encoder_config->video_stream_factory =
3482 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003483 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003484
3485 for (size_t i = 0; i < kNumSsrcs; ++i)
3486 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00003487
3488 // Significantly higher than max bitrates for all video streams -> forcing
3489 // padding to trigger redundant padding on all RTX SSRCs.
3490 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003491 }
3492
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003493 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003494 EXPECT_TRUE(Wait())
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003495 << "Timed out while waiting for redundant payloads on all SSRCs.";
3496 }
3497
3498 private:
3499 size_t ssrcs_to_observe_;
3500 std::map<uint32_t, bool> observed_redundant_retransmission_;
3501 std::map<uint32_t, bool> registered_rtx_ssrc_;
3502 } test;
3503
stefane74eef12016-01-08 06:47:13 -08003504 RunBaseTest(&test);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003505}
3506
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003507void EndToEndTest::TestRtpStatePreservation(bool use_rtx,
3508 bool provoke_rtcpsr_before_rtp) {
perkjfa10b552016-10-02 23:45:26 -07003509 // This test use other VideoStream settings than the the default settings
3510 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3511 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3512 // in ModifyVideoConfigs.
3513 class VideoStreamFactory
3514 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3515 public:
3516 VideoStreamFactory() {}
3517
3518 private:
3519 std::vector<VideoStream> CreateEncoderStreams(
3520 int width,
3521 int height,
3522 const VideoEncoderConfig& encoder_config) override {
3523 std::vector<VideoStream> streams =
3524 test::CreateVideoStreams(width, height, encoder_config);
3525
3526 if (encoder_config.number_of_streams > 1) {
3527 // Lower bitrates so that all streams send initially.
kwibergaf476c72016-11-28 15:21:39 -08003528 RTC_DCHECK_EQ(3, encoder_config.number_of_streams);
perkjfa10b552016-10-02 23:45:26 -07003529 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3530 streams[i].min_bitrate_bps = 10000;
3531 streams[i].target_bitrate_bps = 15000;
3532 streams[i].max_bitrate_bps = 20000;
3533 }
3534 } else {
3535 // Use the same total bitrates when sending a single stream to avoid
3536 // lowering
3537 // the bitrate estimate and requiring a subsequent rampup.
3538 streams[0].min_bitrate_bps = 3 * 10000;
3539 streams[0].target_bitrate_bps = 3 * 15000;
3540 streams[0].max_bitrate_bps = 3 * 20000;
3541 }
3542 return streams;
3543 }
3544 };
3545
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003546 class RtpSequenceObserver : public test::RtpRtcpObserver {
3547 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003548 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003549 : test::RtpRtcpObserver(kDefaultTimeoutMs),
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003550 ssrcs_to_observe_(kNumSsrcs) {
3551 for (size_t i = 0; i < kNumSsrcs; ++i) {
danilchap32cd2c42016-08-01 06:58:34 -07003552 ssrc_is_rtx_[kVideoSendSsrcs[i]] = false;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003553 if (use_rtx)
danilchap32cd2c42016-08-01 06:58:34 -07003554 ssrc_is_rtx_[kSendRtxSsrcs[i]] = true;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003555 }
3556 }
3557
3558 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
Peter Boströmf2f82832015-05-01 13:00:41 +02003559 rtc::CritScope lock(&crit_);
danilchap34877ee2016-02-01 08:25:04 -08003560 ssrc_observed_.clear();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003561 ssrcs_to_observe_ = num_expected_ssrcs;
3562 }
3563
3564 private:
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003565 void ValidateTimestampGap(uint32_t ssrc,
3566 uint32_t timestamp,
3567 bool only_padding)
3568 EXCLUSIVE_LOCKS_REQUIRED(crit_) {
3569 static const int32_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
3570 auto timestamp_it = last_observed_timestamp_.find(ssrc);
3571 if (timestamp_it == last_observed_timestamp_.end()) {
3572 EXPECT_FALSE(only_padding);
3573 last_observed_timestamp_[ssrc] = timestamp;
3574 } else {
3575 // Verify timestamps are reasonably close.
3576 uint32_t latest_observed = timestamp_it->second;
3577 // Wraparound handling is unnecessary here as long as an int variable
3578 // is used to store the result.
3579 int32_t timestamp_gap = timestamp - latest_observed;
3580 EXPECT_LE(std::abs(timestamp_gap), kMaxTimestampGap)
3581 << "Gap in timestamps (" << latest_observed << " -> " << timestamp
3582 << ") too large for SSRC: " << ssrc << ".";
3583 timestamp_it->second = timestamp;
3584 }
3585 }
3586
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003587 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003588 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003589 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003590 const uint32_t ssrc = header.ssrc;
danilchap5c35cf92016-02-03 14:14:49 -08003591 const int64_t sequence_number =
3592 seq_numbers_unwrapper_.Unwrap(header.sequenceNumber);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003593 const uint32_t timestamp = header.timestamp;
danilchap34877ee2016-02-01 08:25:04 -08003594 const bool only_padding =
3595 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003596
danilchap32cd2c42016-08-01 06:58:34 -07003597 EXPECT_TRUE(ssrc_is_rtx_.find(ssrc) != ssrc_is_rtx_.end())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003598 << "Received SSRC that wasn't configured: " << ssrc;
3599
danilchap5c35cf92016-02-03 14:14:49 -08003600 static const int64_t kMaxSequenceNumberGap = 100;
3601 std::list<int64_t>* seq_numbers = &last_observed_seq_numbers_[ssrc];
3602 if (seq_numbers->empty()) {
3603 seq_numbers->push_back(sequence_number);
3604 } else {
3605 // We shouldn't get replays of previous sequence numbers.
3606 for (int64_t observed : *seq_numbers) {
3607 EXPECT_NE(observed, sequence_number)
3608 << "Received sequence number " << sequence_number
3609 << " for SSRC " << ssrc << " 2nd time.";
3610 }
3611 // Verify sequence numbers are reasonably close.
3612 int64_t latest_observed = seq_numbers->back();
3613 int64_t sequence_number_gap = sequence_number - latest_observed;
3614 EXPECT_LE(std::abs(sequence_number_gap), kMaxSequenceNumberGap)
3615 << "Gap in sequence numbers (" << latest_observed << " -> "
3616 << sequence_number << ") too large for SSRC: " << ssrc << ".";
3617 seq_numbers->push_back(sequence_number);
3618 if (seq_numbers->size() >= kMaxSequenceNumberGap) {
3619 seq_numbers->pop_front();
3620 }
3621 }
3622
danilchap32cd2c42016-08-01 06:58:34 -07003623 if (!ssrc_is_rtx_[ssrc]) {
3624 rtc::CritScope lock(&crit_);
3625 ValidateTimestampGap(ssrc, timestamp, only_padding);
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003626
danilchap32cd2c42016-08-01 06:58:34 -07003627 // Wait for media packets on all ssrcs.
3628 if (!ssrc_observed_[ssrc] && !only_padding) {
3629 ssrc_observed_[ssrc] = true;
3630 if (--ssrcs_to_observe_ == 0)
3631 observation_complete_.Set();
3632 }
danilchap34877ee2016-02-01 08:25:04 -08003633 }
3634
danilchapf4b9c772016-01-28 06:14:24 -08003635 return SEND_PACKET;
3636 }
3637
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003638 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
3639 test::RtcpPacketParser rtcp_parser;
3640 rtcp_parser.Parse(packet, length);
3641 if (rtcp_parser.sender_report()->num_packets() > 0) {
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02003642 uint32_t ssrc = rtcp_parser.sender_report()->sender_ssrc();
3643 uint32_t rtcp_timestamp = rtcp_parser.sender_report()->rtp_timestamp();
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003644
3645 rtc::CritScope lock(&crit_);
3646 ValidateTimestampGap(ssrc, rtcp_timestamp, false);
3647 }
3648 return SEND_PACKET;
3649 }
3650
danilchap5c35cf92016-02-03 14:14:49 -08003651 SequenceNumberUnwrapper seq_numbers_unwrapper_;
3652 std::map<uint32_t, std::list<int64_t>> last_observed_seq_numbers_;
danilchap34877ee2016-02-01 08:25:04 -08003653 std::map<uint32_t, uint32_t> last_observed_timestamp_;
danilchap32cd2c42016-08-01 06:58:34 -07003654 std::map<uint32_t, bool> ssrc_is_rtx_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003655
Peter Boströmf2f82832015-05-01 13:00:41 +02003656 rtc::CriticalSection crit_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003657 size_t ssrcs_to_observe_ GUARDED_BY(crit_);
danilchap34877ee2016-02-01 08:25:04 -08003658 std::map<uint32_t, bool> ssrc_observed_ GUARDED_BY(crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003659 } observer(use_rtx);
3660
skvlad11a9cbf2016-10-07 11:53:05 -07003661 Call::Config config(&event_log_);
3662 CreateCalls(config, config);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003663
stefanf116bd02015-10-27 08:29:42 -07003664 test::PacketTransport send_transport(sender_call_.get(), &observer,
3665 test::PacketTransport::kSender,
nissee5ad5ca2017-03-29 23:57:43 -07003666 MediaType::VIDEO,
stefanf116bd02015-10-27 08:29:42 -07003667 FakeNetworkPipe::Config());
3668 test::PacketTransport receive_transport(nullptr, &observer,
3669 test::PacketTransport::kReceiver,
nissee5ad5ca2017-03-29 23:57:43 -07003670 MediaType::VIDEO,
stefanf116bd02015-10-27 08:29:42 -07003671 FakeNetworkPipe::Config());
3672 send_transport.SetReceiver(receiver_call_->Receiver());
3673 receive_transport.SetReceiver(sender_call_->Receiver());
3674
brandtr841de6a2016-11-15 07:10:52 -08003675 CreateSendConfig(kNumSsrcs, 0, 0, &send_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003676
3677 if (use_rtx) {
3678 for (size_t i = 0; i < kNumSsrcs; ++i) {
stefanff483612015-12-21 03:14:00 -08003679 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003680 }
stefanff483612015-12-21 03:14:00 -08003681 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003682 }
3683
perkjfa10b552016-10-02 23:45:26 -07003684 video_encoder_config_.video_stream_factory =
3685 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003686 // Use the same total bitrates when sending a single stream to avoid lowering
3687 // the bitrate estimate and requiring a subsequent rampup.
perkj26091b12016-09-01 01:17:40 -07003688 VideoEncoderConfig one_stream = video_encoder_config_.Copy();
perkjfa10b552016-10-02 23:45:26 -07003689 // one_stream.streams.resize(1);
3690 one_stream.number_of_streams = 1;
stefanf116bd02015-10-27 08:29:42 -07003691 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003692
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003693 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003694 CreateFrameGeneratorCapturer(30, 1280, 720);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003695
3696 Start();
Peter Boström5811a392015-12-10 13:02:50 +01003697 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003698 << "Timed out waiting for all SSRCs to send packets.";
3699
3700 // Test stream resetting more than once to make sure that the state doesn't
3701 // get set once (this could be due to using std::map::insert for instance).
3702 for (size_t i = 0; i < 3; ++i) {
3703 frame_generator_capturer_->Stop();
stefanff483612015-12-21 03:14:00 -08003704 sender_call_->DestroyVideoSendStream(video_send_stream_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003705
3706 // Re-create VideoSendStream with only one stream.
perkj26091b12016-09-01 01:17:40 -07003707 video_send_stream_ = sender_call_->CreateVideoSendStream(
3708 video_send_config_.Copy(), one_stream.Copy());
stefanff483612015-12-21 03:14:00 -08003709 video_send_stream_->Start();
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003710 if (provoke_rtcpsr_before_rtp) {
3711 // Rapid Resync Request forces sending RTCP Sender Report back.
3712 // Using this request speeds up this test because then there is no need
3713 // to wait for a second for periodic Sender Report.
3714 rtcp::RapidResyncRequest force_send_sr_back_request;
3715 rtc::Buffer packet = force_send_sr_back_request.Build();
3716 static_cast<webrtc::test::DirectTransport&>(receive_transport)
3717 .SendRtcp(packet.data(), packet.size());
3718 }
perkjfa10b552016-10-02 23:45:26 -07003719 CreateFrameGeneratorCapturer(30, 1280, 720);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003720 frame_generator_capturer_->Start();
3721
3722 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003723 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003724
3725 // Reconfigure back to use all streams.
perkj26091b12016-09-01 01:17:40 -07003726 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003727 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003728 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003729 << "Timed out waiting for all SSRCs to send packets.";
3730
3731 // Reconfigure down to one stream.
perkj26091b12016-09-01 01:17:40 -07003732 video_send_stream_->ReconfigureVideoEncoder(one_stream.Copy());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003733 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003734 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003735
3736 // Reconfigure back to use all streams.
perkj26091b12016-09-01 01:17:40 -07003737 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003738 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003739 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003740 << "Timed out waiting for all SSRCs to send packets.";
3741 }
3742
stefanf116bd02015-10-27 08:29:42 -07003743 send_transport.StopSending();
3744 receive_transport.StopSending();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003745
3746 Stop();
3747 DestroyStreams();
3748}
3749
philipel277a8b52017-03-16 05:19:49 -07003750TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpState) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003751 TestRtpStatePreservation(false, false);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003752}
3753
philipel277a8b52017-03-16 05:19:49 -07003754TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpStatesWithRtx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003755 TestRtpStatePreservation(true, false);
3756}
3757
philipel277a8b52017-03-16 05:19:49 -07003758TEST_F(EndToEndTest, RestartingSendStreamKeepsRtpAndRtcpTimestampsSynced) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003759 TestRtpStatePreservation(true, true);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003760}
3761
philipel277a8b52017-03-16 05:19:49 -07003762TEST_F(EndToEndTest, RespectsNetworkState) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003763 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
3764 // down blocks until no more packets will be sent.
3765
3766 // Pacer will send from its packet list and then send required padding before
3767 // checking paused_ again. This should be enough for one round of pacing,
3768 // otherwise increase.
3769 static const int kNumAcceptedDowntimeRtp = 5;
3770 // A single RTCP may be in the pipeline.
3771 static const int kNumAcceptedDowntimeRtcp = 1;
3772 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
3773 public:
3774 NetworkStateTest()
3775 : EndToEndTest(kDefaultTimeoutMs),
3776 FakeEncoder(Clock::GetRealTimeClock()),
Peter Boström5811a392015-12-10 13:02:50 +01003777 encoded_frames_(false, false),
3778 packet_event_(false, false),
sprang867fb522015-08-03 04:38:41 -07003779 sender_call_(nullptr),
3780 receiver_call_(nullptr),
Jelena Marusiccd670222015-07-16 09:30:09 +02003781 sender_state_(kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003782 sender_rtp_(0),
3783 sender_rtcp_(0),
3784 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003785 down_frames_(0) {}
3786
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003787 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003788 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003789 ++sender_rtp_;
Peter Boström5811a392015-12-10 13:02:50 +01003790 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003791 return SEND_PACKET;
3792 }
3793
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003794 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003795 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003796 ++sender_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003797 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003798 return SEND_PACKET;
3799 }
3800
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003801 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003802 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
3803 return SEND_PACKET;
3804 }
3805
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003806 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003807 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003808 ++receiver_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003809 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003810 return SEND_PACKET;
3811 }
3812
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003813 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003814 sender_call_ = sender_call;
3815 receiver_call_ = receiver_call;
3816 }
3817
stefanff483612015-12-21 03:14:00 -08003818 void ModifyVideoConfigs(
3819 VideoSendStream::Config* send_config,
3820 std::vector<VideoReceiveStream::Config>* receive_configs,
3821 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003822 send_config->encoder_settings.encoder = this;
3823 }
3824
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003825 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003826 EXPECT_TRUE(encoded_frames_.Wait(kDefaultTimeoutMs))
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003827 << "No frames received by the encoder.";
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003828 // Wait for packets from both sender/receiver.
3829 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003830
skvlad7a43d252016-03-22 15:32:27 -07003831 // Sender-side network down for audio; there should be no effect on video
3832 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3833 WaitForPacketsOrSilence(false, false);
3834
3835 // Receiver-side network down for audio; no change expected
3836 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3837 WaitForPacketsOrSilence(false, false);
3838
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003839 // Sender-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003840 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003841 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003842 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003843 // After network goes down we shouldn't be encoding more frames.
Jelena Marusiccd670222015-07-16 09:30:09 +02003844 sender_state_ = kNetworkDown;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003845 }
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003846 // Wait for receiver-packets and no sender packets.
3847 WaitForPacketsOrSilence(true, false);
3848
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003849 // Receiver-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003850 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
3851 WaitForPacketsOrSilence(true, true);
3852
3853 // Network up for audio for both sides; video is still not expected to
3854 // start
3855 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
3856 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003857 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003858
3859 // Network back up again for both.
3860 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003861 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003862 // It's OK to encode frames again, as we're about to bring up the
3863 // network.
Jelena Marusiccd670222015-07-16 09:30:09 +02003864 sender_state_ = kNetworkUp;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003865 }
skvlad7a43d252016-03-22 15:32:27 -07003866 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
3867 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003868 WaitForPacketsOrSilence(false, false);
skvlad7a43d252016-03-22 15:32:27 -07003869
3870 // TODO(skvlad): add tests to verify that the audio streams are stopped
3871 // when the network goes down for audio once the workaround in
3872 // paced_sender.cc is removed.
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003873 }
3874
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07003875 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003876 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07003877 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003878 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003879 rtc::CritScope lock(&test_crit_);
Jelena Marusiccd670222015-07-16 09:30:09 +02003880 if (sender_state_ == kNetworkDown) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003881 ++down_frames_;
3882 EXPECT_LE(down_frames_, 1)
3883 << "Encoding more than one frame while network is down.";
3884 if (down_frames_ > 1)
Peter Boström5811a392015-12-10 13:02:50 +01003885 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003886 } else {
Peter Boström5811a392015-12-10 13:02:50 +01003887 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003888 }
3889 }
3890 return test::FakeEncoder::Encode(
3891 input_image, codec_specific_info, frame_types);
3892 }
3893
3894 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003895 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
3896 int64_t initial_time_ms = clock_->TimeInMilliseconds();
3897 int initial_sender_rtp;
3898 int initial_sender_rtcp;
3899 int initial_receiver_rtcp;
3900 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003901 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003902 initial_sender_rtp = sender_rtp_;
3903 initial_sender_rtcp = sender_rtcp_;
3904 initial_receiver_rtcp = receiver_rtcp_;
3905 }
3906 bool sender_done = false;
3907 bool receiver_done = false;
mflodmand1590b22015-12-09 07:07:59 -08003908 while (!sender_done || !receiver_done) {
Peter Boström5811a392015-12-10 13:02:50 +01003909 packet_event_.Wait(kSilenceTimeoutMs);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003910 int64_t time_now_ms = clock_->TimeInMilliseconds();
Peter Boströmf2f82832015-05-01 13:00:41 +02003911 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003912 if (sender_down) {
3913 ASSERT_LE(sender_rtp_ - initial_sender_rtp, kNumAcceptedDowntimeRtp)
3914 << "RTP sent during sender-side downtime.";
3915 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
3916 kNumAcceptedDowntimeRtcp)
3917 << "RTCP sent during sender-side downtime.";
3918 if (time_now_ms - initial_time_ms >=
3919 static_cast<int64_t>(kSilenceTimeoutMs)) {
3920 sender_done = true;
3921 }
3922 } else {
skvlad7a43d252016-03-22 15:32:27 -07003923 if (sender_rtp_ > initial_sender_rtp + kNumAcceptedDowntimeRtp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003924 sender_done = true;
3925 }
3926 if (receiver_down) {
3927 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
3928 kNumAcceptedDowntimeRtcp)
3929 << "RTCP sent during receiver-side downtime.";
3930 if (time_now_ms - initial_time_ms >=
3931 static_cast<int64_t>(kSilenceTimeoutMs)) {
3932 receiver_done = true;
3933 }
3934 } else {
skvlad7a43d252016-03-22 15:32:27 -07003935 if (receiver_rtcp_ > initial_receiver_rtcp + kNumAcceptedDowntimeRtcp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003936 receiver_done = true;
3937 }
3938 }
3939 }
3940
Peter Boströmf2f82832015-05-01 13:00:41 +02003941 rtc::CriticalSection test_crit_;
Peter Boström5811a392015-12-10 13:02:50 +01003942 rtc::Event encoded_frames_;
3943 rtc::Event packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003944 Call* sender_call_;
3945 Call* receiver_call_;
Jelena Marusiccd670222015-07-16 09:30:09 +02003946 NetworkState sender_state_ GUARDED_BY(test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003947 int sender_rtp_ GUARDED_BY(test_crit_);
3948 int sender_rtcp_ GUARDED_BY(test_crit_);
3949 int receiver_rtcp_ GUARDED_BY(test_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003950 int down_frames_ GUARDED_BY(test_crit_);
3951 } test;
3952
stefane74eef12016-01-08 06:47:13 -08003953 RunBaseTest(&test);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003954}
3955
philipel277a8b52017-03-16 05:19:49 -07003956TEST_F(EndToEndTest, CallReportsRttForSender) {
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003957 static const int kSendDelayMs = 30;
3958 static const int kReceiveDelayMs = 70;
skvlad11a9cbf2016-10-07 11:53:05 -07003959 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -07003960
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003961 FakeNetworkPipe::Config config;
3962 config.queue_delay_ms = kSendDelayMs;
nissee5ad5ca2017-03-29 23:57:43 -07003963 test::DirectTransport sender_transport(
3964 config, sender_call_.get(), MediaType::VIDEO);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003965 config.queue_delay_ms = kReceiveDelayMs;
nissee5ad5ca2017-03-29 23:57:43 -07003966 test::DirectTransport receiver_transport(
3967 config, receiver_call_.get(), MediaType::VIDEO);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003968 sender_transport.SetReceiver(receiver_call_->Receiver());
3969 receiver_transport.SetReceiver(sender_call_->Receiver());
3970
brandtr841de6a2016-11-15 07:10:52 -08003971 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07003972 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003973
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003974 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003975 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
3976 kDefaultHeight);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003977 Start();
3978
3979 int64_t start_time_ms = clock_->TimeInMilliseconds();
3980 while (true) {
3981 Call::Stats stats = sender_call_->GetStats();
3982 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
3983 clock_->TimeInMilliseconds())
3984 << "No RTT stats before timeout!";
3985 if (stats.rtt_ms != -1) {
Danil Chapovalov10e8f8e2016-09-07 15:05:29 +02003986 // To avoid failures caused by rounding or minor ntp clock adjustments,
3987 // relax expectation by 1ms.
3988 constexpr int kAllowedErrorMs = 1;
3989 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs - kAllowedErrorMs);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003990 break;
3991 }
3992 SleepMs(10);
3993 }
3994
philipel266f0a42016-11-28 08:49:07 -08003995 sender_transport.StopSending();
3996 receiver_transport.StopSending();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003997 Stop();
3998 DestroyStreams();
philipel266f0a42016-11-28 08:49:07 -08003999 DestroyCalls();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004000}
4001
skvlad7a43d252016-03-22 15:32:27 -07004002void EndToEndTest::VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004003 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -07004004 VideoEncoder* encoder,
4005 Transport* transport) {
skvlad11a9cbf2016-10-07 11:53:05 -07004006 CreateSenderCall(Call::Config(&event_log_));
Sergey Ulanove2b15012016-11-22 16:08:30 -08004007 sender_call_->SignalChannelNetworkState(network_to_bring_up, kNetworkUp);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004008
brandtr841de6a2016-11-15 07:10:52 -08004009 CreateSendConfig(1, 0, 0, transport);
skvlad7a43d252016-03-22 15:32:27 -07004010 video_send_config_.encoder_settings.encoder = encoder;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004011 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07004012 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
4013 kDefaultHeight);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004014
4015 Start();
4016 SleepMs(kSilenceTimeoutMs);
4017 Stop();
4018
4019 DestroyStreams();
4020}
4021
skvlad7a43d252016-03-22 15:32:27 -07004022void EndToEndTest::VerifyNewVideoReceiveStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004023 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -07004024 Transport* transport) {
skvlad11a9cbf2016-10-07 11:53:05 -07004025 Call::Config config(&event_log_);
4026 CreateCalls(config, config);
Sergey Ulanove2b15012016-11-22 16:08:30 -08004027 receiver_call_->SignalChannelNetworkState(network_to_bring_up, kNetworkUp);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004028
nissee5ad5ca2017-03-29 23:57:43 -07004029 test::DirectTransport sender_transport(sender_call_.get(), MediaType::VIDEO);
solenberg4fbae2b2015-08-28 04:07:10 -07004030 sender_transport.SetReceiver(receiver_call_->Receiver());
brandtr841de6a2016-11-15 07:10:52 -08004031 CreateSendConfig(1, 0, 0, &sender_transport);
skvlad7a43d252016-03-22 15:32:27 -07004032 CreateMatchingReceiveConfigs(transport);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004033 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07004034 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
4035 kDefaultHeight);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004036
4037 Start();
4038 SleepMs(kSilenceTimeoutMs);
4039 Stop();
4040
4041 sender_transport.StopSending();
4042
4043 DestroyStreams();
4044}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00004045
philipel277a8b52017-03-16 05:19:49 -07004046TEST_F(EndToEndTest, NewVideoSendStreamsRespectVideoNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004047 class UnusedEncoder : public test::FakeEncoder {
4048 public:
4049 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
perkjfea93092016-05-14 00:58:48 -07004050
4051 int32_t InitEncode(const VideoCodec* config,
4052 int32_t number_of_cores,
4053 size_t max_payload_size) override {
4054 EXPECT_GT(config->startBitrate, 0u);
4055 return 0;
4056 }
skvlad7a43d252016-03-22 15:32:27 -07004057 int32_t Encode(const VideoFrame& input_image,
4058 const CodecSpecificInfo* codec_specific_info,
4059 const std::vector<FrameType>* frame_types) override {
4060 ADD_FAILURE() << "Unexpected frame encode.";
4061 return test::FakeEncoder::Encode(input_image, codec_specific_info,
4062 frame_types);
4063 }
4064 };
4065
4066 UnusedEncoder unused_encoder;
4067 UnusedTransport unused_transport;
4068 VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004069 MediaType::AUDIO, &unused_encoder, &unused_transport);
skvlad7a43d252016-03-22 15:32:27 -07004070}
4071
philipel277a8b52017-03-16 05:19:49 -07004072TEST_F(EndToEndTest, NewVideoSendStreamsIgnoreAudioNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004073 class RequiredEncoder : public test::FakeEncoder {
4074 public:
4075 RequiredEncoder()
4076 : FakeEncoder(Clock::GetRealTimeClock()), encoded_frame_(false) {}
4077 ~RequiredEncoder() {
4078 if (!encoded_frame_) {
4079 ADD_FAILURE() << "Didn't encode an expected frame";
4080 }
4081 }
4082 int32_t Encode(const VideoFrame& input_image,
4083 const CodecSpecificInfo* codec_specific_info,
4084 const std::vector<FrameType>* frame_types) override {
4085 encoded_frame_ = true;
4086 return test::FakeEncoder::Encode(input_image, codec_specific_info,
4087 frame_types);
4088 }
4089
4090 private:
4091 bool encoded_frame_;
4092 };
4093
4094 RequiredTransport required_transport(true /*rtp*/, false /*rtcp*/);
4095 RequiredEncoder required_encoder;
4096 VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004097 MediaType::VIDEO, &required_encoder, &required_transport);
skvlad7a43d252016-03-22 15:32:27 -07004098}
4099
philipel277a8b52017-03-16 05:19:49 -07004100TEST_F(EndToEndTest, NewVideoReceiveStreamsRespectVideoNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004101 UnusedTransport transport;
Sergey Ulanove2b15012016-11-22 16:08:30 -08004102 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::AUDIO, &transport);
skvlad7a43d252016-03-22 15:32:27 -07004103}
4104
philipel277a8b52017-03-16 05:19:49 -07004105TEST_F(EndToEndTest, NewVideoReceiveStreamsIgnoreAudioNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004106 RequiredTransport transport(false /*rtp*/, true /*rtcp*/);
Sergey Ulanove2b15012016-11-22 16:08:30 -08004107 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::VIDEO, &transport);
skvlad7a43d252016-03-22 15:32:27 -07004108}
4109
Peter Boströmd7da1202015-06-05 14:09:38 +02004110void VerifyEmptyNackConfig(const NackConfig& config) {
4111 EXPECT_EQ(0, config.rtp_history_ms)
4112 << "Enabling NACK requires rtcp-fb: nack negotiation.";
4113}
4114
brandtrb5f2c3f2016-10-04 23:28:39 -07004115void VerifyEmptyUlpfecConfig(const UlpfecConfig& config) {
Peter Boströmd7da1202015-06-05 14:09:38 +02004116 EXPECT_EQ(-1, config.ulpfec_payload_type)
brandtr535830e2016-10-31 03:45:58 -07004117 << "Enabling ULPFEC requires rtpmap: ulpfec negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02004118 EXPECT_EQ(-1, config.red_payload_type)
brandtr535830e2016-10-31 03:45:58 -07004119 << "Enabling ULPFEC requires rtpmap: red negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02004120 EXPECT_EQ(-1, config.red_rtx_payload_type)
brandtr535830e2016-10-31 03:45:58 -07004121 << "Enabling RTX in ULPFEC requires rtpmap: rtx negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02004122}
4123
brandtr3d200bd2017-01-16 06:59:19 -08004124void VerifyEmptyFlexfecConfig(
4125 const VideoSendStream::Config::Rtp::Flexfec& config) {
4126 EXPECT_EQ(-1, config.payload_type)
brandtr1e3dfbf2016-11-16 22:45:19 -08004127 << "Enabling FlexFEC requires rtpmap: flexfec negotiation.";
brandtr3d200bd2017-01-16 06:59:19 -08004128 EXPECT_EQ(0U, config.ssrc)
brandtr1cfbd602016-12-08 04:17:53 -08004129 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
brandtr1e3dfbf2016-11-16 22:45:19 -08004130 EXPECT_TRUE(config.protected_media_ssrcs.empty())
4131 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
4132}
4133
philipel277a8b52017-03-16 05:19:49 -07004134TEST_F(EndToEndTest, VerifyDefaultSendConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07004135 VideoSendStream::Config default_send_config(nullptr);
Peter Boströmd7da1202015-06-05 14:09:38 +02004136 EXPECT_EQ(0, default_send_config.rtp.nack.rtp_history_ms)
4137 << "Enabling NACK require rtcp-fb: nack negotiation.";
4138 EXPECT_TRUE(default_send_config.rtp.rtx.ssrcs.empty())
4139 << "Enabling RTX requires rtpmap: rtx negotiation.";
4140 EXPECT_TRUE(default_send_config.rtp.extensions.empty())
4141 << "Enabling RTP extensions require negotiation.";
4142
4143 VerifyEmptyNackConfig(default_send_config.rtp.nack);
brandtrb5f2c3f2016-10-04 23:28:39 -07004144 VerifyEmptyUlpfecConfig(default_send_config.rtp.ulpfec);
brandtr1e3dfbf2016-11-16 22:45:19 -08004145 VerifyEmptyFlexfecConfig(default_send_config.rtp.flexfec);
Peter Boströmd7da1202015-06-05 14:09:38 +02004146}
4147
philipel277a8b52017-03-16 05:19:49 -07004148TEST_F(EndToEndTest, VerifyDefaultVideoReceiveConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07004149 VideoReceiveStream::Config default_receive_config(nullptr);
pbosda903ea2015-10-02 02:36:56 -07004150 EXPECT_EQ(RtcpMode::kCompound, default_receive_config.rtp.rtcp_mode)
Peter Boströmd7da1202015-06-05 14:09:38 +02004151 << "Reduced-size RTCP require rtcp-rsize to be negotiated.";
4152 EXPECT_FALSE(default_receive_config.rtp.remb)
4153 << "REMB require rtcp-fb: goog-remb to be negotiated.";
4154 EXPECT_FALSE(
4155 default_receive_config.rtp.rtcp_xr.receiver_reference_time_report)
4156 << "RTCP XR settings require rtcp-xr to be negotiated.";
brandtr14742122017-01-27 04:53:07 -08004157 EXPECT_EQ(0U, default_receive_config.rtp.rtx_ssrc)
4158 << "Enabling RTX requires ssrc-group: FID negotiation";
4159 EXPECT_TRUE(default_receive_config.rtp.rtx_payload_types.empty())
Peter Boströmd7da1202015-06-05 14:09:38 +02004160 << "Enabling RTX requires rtpmap: rtx negotiation.";
4161 EXPECT_TRUE(default_receive_config.rtp.extensions.empty())
4162 << "Enabling RTP extensions require negotiation.";
4163
4164 VerifyEmptyNackConfig(default_receive_config.rtp.nack);
brandtrb5f2c3f2016-10-04 23:28:39 -07004165 VerifyEmptyUlpfecConfig(default_receive_config.rtp.ulpfec);
Peter Boströmd7da1202015-06-05 14:09:38 +02004166}
4167
philipel277a8b52017-03-16 05:19:49 -07004168TEST_F(EndToEndTest, VerifyDefaultFlexfecReceiveConfigParameters) {
brandtr8313a6f2017-01-13 07:41:19 -08004169 test::NullTransport rtcp_send_transport;
4170 FlexfecReceiveStream::Config default_receive_config(&rtcp_send_transport);
brandtr1cfbd602016-12-08 04:17:53 -08004171 EXPECT_EQ(-1, default_receive_config.payload_type)
4172 << "Enabling FlexFEC requires rtpmap: flexfec negotiation.";
4173 EXPECT_EQ(0U, default_receive_config.remote_ssrc)
4174 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
4175 EXPECT_TRUE(default_receive_config.protected_media_ssrcs.empty())
4176 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
brandtr1e3dfbf2016-11-16 22:45:19 -08004177}
4178
philipel277a8b52017-03-16 05:19:49 -07004179TEST_F(EndToEndTest, TransportSeqNumOnAudioAndVideo) {
danilchap4336d732017-03-03 06:21:54 -08004180 static constexpr int kExtensionId = 8;
4181 static constexpr size_t kMinPacketsToWaitFor = 50;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004182 class TransportSequenceNumberTest : public test::EndToEndTest {
4183 public:
4184 TransportSequenceNumberTest()
4185 : EndToEndTest(kDefaultTimeoutMs),
4186 video_observed_(false),
4187 audio_observed_(false) {
4188 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
4189 kExtensionId);
4190 }
4191
4192 size_t GetNumVideoStreams() const override { return 1; }
4193 size_t GetNumAudioStreams() const override { return 1; }
4194
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004195 void ModifyAudioConfigs(
4196 AudioSendStream::Config* send_config,
4197 std::vector<AudioReceiveStream::Config>* receive_configs) override {
4198 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07004199 send_config->rtp.extensions.push_back(RtpExtension(
4200 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004201 (*receive_configs)[0].rtp.extensions.clear();
4202 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
4203 }
4204
4205 Action OnSendRtp(const uint8_t* packet, size_t length) override {
4206 RTPHeader header;
4207 EXPECT_TRUE(parser_->Parse(packet, length, &header));
4208 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
4209 // Unwrap packet id and verify uniqueness.
4210 int64_t packet_id =
4211 unwrapper_.Unwrap(header.extension.transportSequenceNumber);
4212 EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
4213
4214 if (header.ssrc == kVideoSendSsrcs[0])
4215 video_observed_ = true;
4216 if (header.ssrc == kAudioSendSsrc)
4217 audio_observed_ = true;
4218 if (audio_observed_ && video_observed_ &&
danilchap4336d732017-03-03 06:21:54 -08004219 received_packet_ids_.size() >= kMinPacketsToWaitFor) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004220 size_t packet_id_range =
4221 *received_packet_ids_.rbegin() - *received_packet_ids_.begin() + 1;
4222 EXPECT_EQ(received_packet_ids_.size(), packet_id_range);
4223 observation_complete_.Set();
4224 }
4225 return SEND_PACKET;
4226 }
4227
4228 void PerformTest() override {
4229 EXPECT_TRUE(Wait()) << "Timed out while waiting for audio and video "
4230 "packets with transport sequence number.";
4231 }
4232
danilchap4336d732017-03-03 06:21:54 -08004233 void ExpectSuccessful() {
4234 EXPECT_TRUE(video_observed_);
4235 EXPECT_TRUE(audio_observed_);
4236 EXPECT_GE(received_packet_ids_.size(), kMinPacketsToWaitFor);
4237 }
4238
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004239 private:
4240 bool video_observed_;
4241 bool audio_observed_;
4242 SequenceNumberUnwrapper unwrapper_;
4243 std::set<int64_t> received_packet_ids_;
4244 } test;
4245
stefane74eef12016-01-08 06:47:13 -08004246 RunBaseTest(&test);
danilchap4336d732017-03-03 06:21:54 -08004247 // Double check conditions for successful test to produce better error
4248 // message when the test fail.
4249 test.ExpectSuccessful();
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004250}
palmkviste75f2042016-09-28 06:19:48 -07004251
4252class EndToEndLogTest : public EndToEndTest {
4253 void SetUp() { paths_.clear(); }
4254 void TearDown() {
4255 for (const auto& path : paths_) {
4256 rtc::RemoveFile(path);
4257 }
4258 }
4259
4260 public:
4261 int AddFile() {
4262 paths_.push_back(test::TempFilename(test::OutputPath(), "test_file"));
4263 return static_cast<int>(paths_.size()) - 1;
4264 }
4265
4266 rtc::PlatformFile OpenFile(int idx) {
4267 return rtc::OpenPlatformFile(paths_[idx]);
4268 }
4269
4270 void LogSend(bool open) {
4271 if (open) {
4272 video_send_stream_->EnableEncodedFrameRecording(
4273 std::vector<rtc::PlatformFile>(1, OpenFile(AddFile())), 0);
4274 } else {
4275 video_send_stream_->DisableEncodedFrameRecording();
4276 }
4277 }
4278 void LogReceive(bool open) {
4279 if (open) {
4280 video_receive_streams_[0]->EnableEncodedFrameRecording(
4281 OpenFile(AddFile()), 0);
4282 } else {
4283 video_receive_streams_[0]->DisableEncodedFrameRecording();
4284 }
4285 }
4286
4287 std::vector<std::string> paths_;
4288};
4289
philipel277a8b52017-03-16 05:19:49 -07004290TEST_F(EndToEndLogTest, LogsEncodedFramesWhenRequested) {
palmkviste75f2042016-09-28 06:19:48 -07004291 static const int kNumFramesToRecord = 10;
4292 class LogEncodingObserver : public test::EndToEndTest,
4293 public EncodedFrameObserver {
4294 public:
4295 explicit LogEncodingObserver(EndToEndLogTest* fixture)
4296 : EndToEndTest(kDefaultTimeoutMs),
4297 fixture_(fixture),
4298 recorded_frames_(0) {}
4299
4300 void PerformTest() override {
4301 fixture_->LogSend(true);
4302 fixture_->LogReceive(true);
4303 ASSERT_TRUE(Wait()) << "Timed out while waiting for frame logging.";
4304 }
4305
4306 void ModifyVideoConfigs(
4307 VideoSendStream::Config* send_config,
4308 std::vector<VideoReceiveStream::Config>* receive_configs,
4309 VideoEncoderConfig* encoder_config) override {
magjed509e4fe2016-11-18 01:34:11 -08004310 encoder_.reset(VP8Encoder::Create());
palmkviste75f2042016-09-28 06:19:48 -07004311 decoder_.reset(VP8Decoder::Create());
4312
4313 send_config->post_encode_callback = this;
4314 send_config->encoder_settings.payload_name = "VP8";
4315 send_config->encoder_settings.encoder = encoder_.get();
4316
4317 (*receive_configs)[0].decoders.resize(1);
4318 (*receive_configs)[0].decoders[0].payload_type =
4319 send_config->encoder_settings.payload_type;
4320 (*receive_configs)[0].decoders[0].payload_name =
4321 send_config->encoder_settings.payload_name;
4322 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
4323 }
4324
4325 void EncodedFrameCallback(const EncodedFrame& encoded_frame) override {
4326 rtc::CritScope lock(&crit_);
4327 if (recorded_frames_++ > kNumFramesToRecord) {
4328 fixture_->LogSend(false);
4329 fixture_->LogReceive(false);
4330 rtc::File send_file(fixture_->OpenFile(0));
4331 rtc::File receive_file(fixture_->OpenFile(1));
4332 uint8_t out[100];
4333 // If logging has worked correctly neither file should be empty, i.e.
4334 // we should be able to read something from them.
4335 EXPECT_LT(0u, send_file.Read(out, 100));
4336 EXPECT_LT(0u, receive_file.Read(out, 100));
4337 observation_complete_.Set();
4338 }
4339 }
4340
4341 private:
4342 EndToEndLogTest* const fixture_;
4343 std::unique_ptr<VideoEncoder> encoder_;
4344 std::unique_ptr<VideoDecoder> decoder_;
4345 rtc::CriticalSection crit_;
4346 int recorded_frames_ GUARDED_BY(crit_);
4347 } test(this);
4348
4349 RunBaseTest(&test);
4350}
4351
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00004352} // namespace webrtc