blob: f876621fd3551bc2409edf7ee9be9754f07b73ab [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
ilnikd60d06a2017-04-05 03:02:20 -070018#include "webrtc/api/video_codecs/video_encoder.h"
Henrik Kjellandera80c16a2017-07-01 16:48:15 +020019#include "webrtc/base/checks.h"
20#include "webrtc/base/event.h"
21#include "webrtc/base/file.h"
22#include "webrtc/base/optional.h"
23#include "webrtc/base/random.h"
24#include "webrtc/base/rate_limiter.h"
ossuf515ab82016-12-07 04:52:58 -080025#include "webrtc/call/call.h"
pbosa96b60b2016-04-18 21:12:48 -070026#include "webrtc/common_video/include/frame_callback.h"
skvlad11a9cbf2016-10-07 11:53:05 -070027#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
sakal55d932b2016-09-30 06:19:08 -070028#include "webrtc/media/base/fakevideorenderer.h"
brandtr5e171752017-05-23 03:32:16 -070029#include "webrtc/media/base/mediaconstants.h"
30#include "webrtc/media/engine/internalencoderfactory.h"
31#include "webrtc/media/engine/webrtcvideoencoderfactory.h"
danilchap5c35cf92016-02-03 14:14:49 -080032#include "webrtc/modules/include/module_common_types.h"
stefan32f81542016-01-20 07:13:58 -080033#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
sprang861c55e2015-10-16 10:01:21 -070034#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
Erik Språng737336d2016-07-29 12:59:36 +020035#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h"
Danil Chapovalov70ffead2016-07-20 15:26:59 +020036#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.h"
brandtr5e171752017-05-23 03:32:16 -070037#include "webrtc/modules/rtp_rtcp/source/rtp_format.h"
sprangcd349d92016-07-13 09:11:28 -070038#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
hbosbab934b2016-01-27 01:36:03 -080039#include "webrtc/modules/video_coding/codecs/h264/include/h264.h"
marpan@webrtc.org5b883172014-11-01 06:10:48 +000040#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
brandtr5e171752017-05-23 03:32:16 -070041#include "webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.h"
marpan@webrtc.org5b883172014-11-01 06:10:48 +000042#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010043#include "webrtc/modules/video_coding/include/video_coding_defines.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010044#include "webrtc/system_wrappers/include/metrics.h"
asapersson01d70a32016-05-20 06:29:46 -070045#include "webrtc/system_wrappers/include/metrics_default.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010046#include "webrtc/system_wrappers/include/sleep.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000047#include "webrtc/test/call_test.h"
48#include "webrtc/test/direct_transport.h"
49#include "webrtc/test/encoder_settings.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000050#include "webrtc/test/fake_decoder.h"
51#include "webrtc/test/fake_encoder.h"
philipel266f0a42016-11-28 08:49:07 -080052#include "webrtc/test/field_trial.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000053#include "webrtc/test/frame_generator.h"
54#include "webrtc/test/frame_generator_capturer.h"
brandtr56e119e2017-05-19 10:33:03 -070055#include "webrtc/test/gmock.h"
brandtr5e171752017-05-23 03:32:16 -070056#include "webrtc/test/gtest.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000057#include "webrtc/test/null_transport.h"
asapersson@webrtc.org37c05592015-01-28 13:58:27 +000058#include "webrtc/test/rtcp_packet_parser.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000059#include "webrtc/test/rtp_rtcp_observer.h"
60#include "webrtc/test/testsupport/fileutils.h"
61#include "webrtc/test/testsupport/perf_test.h"
charujainbf6a45b2016-11-03 04:21:42 -070062#include "webrtc/video/transport_adapter.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000063
oprypin45197522017-06-22 01:47:20 -070064// Flaky under MemorySanitizer: bugs.webrtc.org/7419
aleloi7057b6b2017-03-29 02:07:33 -070065#if defined(MEMORY_SANITIZER)
oprypin45197522017-06-22 01:47:20 -070066#define MAYBE_InitialProbing DISABLED_InitialProbing
67// Fails on iOS bots: bugs.webrtc.org/7851
68#elif defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR
aleloi7057b6b2017-03-29 02:07:33 -070069#define MAYBE_InitialProbing DISABLED_InitialProbing
70#else
71#define MAYBE_InitialProbing InitialProbing
72#endif
73
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000074namespace webrtc {
75
minyue20c84cc2017-04-10 16:57:57 -070076namespace {
77constexpr int kSilenceTimeoutMs = 2000;
78}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000079
philipel277a8b52017-03-16 05:19:49 -070080class EndToEndTest : public test::CallTest {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000081 public:
philipel277a8b52017-03-16 05:19:49 -070082 EndToEndTest() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000083
84 virtual ~EndToEndTest() {
stefanff483612015-12-21 03:14:00 -080085 EXPECT_EQ(nullptr, video_send_stream_);
86 EXPECT_TRUE(video_receive_streams_.empty());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000087 }
88
89 protected:
pbos2d566682015-09-28 09:59:31 -070090 class UnusedTransport : public Transport {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000091 private:
stefan1d8a5062015-10-02 03:39:33 -070092 bool SendRtp(const uint8_t* packet,
93 size_t length,
94 const PacketOptions& options) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000095 ADD_FAILURE() << "Unexpected RTP sent.";
96 return false;
97 }
98
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000099 bool SendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000100 ADD_FAILURE() << "Unexpected RTCP sent.";
101 return false;
102 }
103 };
104
skvlad7a43d252016-03-22 15:32:27 -0700105 class RequiredTransport : public Transport {
106 public:
107 RequiredTransport(bool rtp_required, bool rtcp_required)
108 : need_rtp_(rtp_required), need_rtcp_(rtcp_required) {}
109 ~RequiredTransport() {
110 if (need_rtp_) {
111 ADD_FAILURE() << "Expected RTP packet not sent.";
112 }
113 if (need_rtcp_) {
114 ADD_FAILURE() << "Expected RTCP packet not sent.";
115 }
116 }
117
118 private:
119 bool SendRtp(const uint8_t* packet,
120 size_t length,
121 const PacketOptions& options) override {
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700122 rtc::CritScope lock(&crit_);
skvlad7a43d252016-03-22 15:32:27 -0700123 need_rtp_ = false;
124 return true;
125 }
126
127 bool SendRtcp(const uint8_t* packet, size_t length) override {
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700128 rtc::CritScope lock(&crit_);
skvlad7a43d252016-03-22 15:32:27 -0700129 need_rtcp_ = false;
130 return true;
131 }
132 bool need_rtp_;
133 bool need_rtcp_;
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700134 rtc::CriticalSection crit_;
skvlad7a43d252016-03-22 15:32:27 -0700135 };
136
Peter Boström39593972016-02-15 11:27:15 +0100137 void DecodesRetransmittedFrame(bool enable_rtx, bool enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000138 void ReceivesPliAndRecovers(int rtp_history_ms);
pbosda903ea2015-10-02 02:36:56 -0700139 void RespectsRtcpMode(RtcpMode rtcp_mode);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000140 void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200141 void TestRtpStatePreservation(bool use_rtx, bool provoke_rtcpsr_before_rtp);
sprangb4a1ae52015-12-03 08:10:08 -0800142 void VerifyHistogramStats(bool use_rtx, bool use_red, bool screenshare);
skvlad7a43d252016-03-22 15:32:27 -0700143 void VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -0800144 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -0700145 VideoEncoder* encoder,
146 Transport* transport);
147 void VerifyNewVideoReceiveStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -0800148 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -0700149 Transport* transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000150};
151
philipel277a8b52017-03-16 05:19:49 -0700152TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
philipel4fb651d2017-04-10 03:54:05 -0700153 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000154
solenberg4fbae2b2015-08-28 04:07:10 -0700155 test::NullTransport transport;
brandtr841de6a2016-11-15 07:10:52 -0800156 CreateSendConfig(1, 0, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700157 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000158
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100159 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000160
stefanff483612015-12-21 03:14:00 -0800161 video_receive_streams_[0]->Start();
162 video_receive_streams_[0]->Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000163
164 DestroyStreams();
165}
166
philipel277a8b52017-03-16 05:19:49 -0700167TEST_F(EndToEndTest, ReceiverCanBeStoppedTwice) {
philipel4fb651d2017-04-10 03:54:05 -0700168 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000169
solenberg4fbae2b2015-08-28 04:07:10 -0700170 test::NullTransport transport;
brandtr841de6a2016-11-15 07:10:52 -0800171 CreateSendConfig(1, 0, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700172 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000173
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100174 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000175
stefanff483612015-12-21 03:14:00 -0800176 video_receive_streams_[0]->Stop();
177 video_receive_streams_[0]->Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000178
179 DestroyStreams();
180}
181
philipel277a8b52017-03-16 05:19:49 -0700182TEST_F(EndToEndTest, ReceiverCanBeStoppedAndRestarted) {
philipel4fb651d2017-04-10 03:54:05 -0700183 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
sprang113bdca2016-10-11 03:10:10 -0700184
185 test::NullTransport transport;
brandtr841de6a2016-11-15 07:10:52 -0800186 CreateSendConfig(1, 0, 0, &transport);
sprang113bdca2016-10-11 03:10:10 -0700187 CreateMatchingReceiveConfigs(&transport);
188
189 CreateVideoStreams();
190
191 video_receive_streams_[0]->Stop();
192 video_receive_streams_[0]->Start();
193 video_receive_streams_[0]->Stop();
194
195 DestroyStreams();
196}
197
philipel277a8b52017-03-16 05:19:49 -0700198TEST_F(EndToEndTest, RendersSingleDelayedFrame) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000199 static const int kWidth = 320;
200 static const int kHeight = 240;
201 // This constant is chosen to be higher than the timeout in the video_render
202 // module. This makes sure that frames aren't dropped if there are no other
203 // frames in the queue.
nisse76bc8e82017-02-07 09:37:41 -0800204 static const int kRenderDelayMs = 1000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000205
nisse7ade7b32016-03-23 04:48:10 -0700206 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000207 public:
Peter Boström5811a392015-12-10 13:02:50 +0100208 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000209
nisse76bc8e82017-02-07 09:37:41 -0800210 void OnFrame(const VideoFrame& video_frame) override {
211 SleepMs(kRenderDelayMs);
212 event_.Set();
213 }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000214
Peter Boström5811a392015-12-10 13:02:50 +0100215 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000216
Peter Boström5811a392015-12-10 13:02:50 +0100217 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000218 } renderer;
219
philipel4fb651d2017-04-10 03:54:05 -0700220 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
solenberg4fbae2b2015-08-28 04:07:10 -0700221
minyue20c84cc2017-04-10 16:57:57 -0700222 test::DirectTransport sender_transport(sender_call_.get(), payload_type_map_);
223 test::DirectTransport receiver_transport(receiver_call_.get(),
224 payload_type_map_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000225 sender_transport.SetReceiver(receiver_call_->Receiver());
226 receiver_transport.SetReceiver(sender_call_->Receiver());
227
brandtr841de6a2016-11-15 07:10:52 -0800228 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700229 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000230
stefanff483612015-12-21 03:14:00 -0800231 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000232
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100233 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000234 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000235
236 // Create frames that are smaller than the send width/height, this is done to
237 // check that the callbacks are done after processing video.
kwiberg27f982b2016-03-01 11:52:33 -0800238 std::unique_ptr<test::FrameGenerator> frame_generator(
perkja8ba1952017-02-27 06:52:10 -0800239 test::FrameGenerator::CreateSquareGenerator(kWidth, kHeight));
perkja49cbd32016-09-16 07:53:41 -0700240 test::FrameForwarder frame_forwarder;
perkj803d97f2016-11-01 11:45:46 -0700241 video_send_stream_->SetSource(
sprangc5d62e22017-04-02 23:53:04 -0700242 &frame_forwarder,
243 VideoSendStream::DegradationPreference::kMaintainFramerate);
perkja49cbd32016-09-16 07:53:41 -0700244
245 frame_forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
Peter Boström5811a392015-12-10 13:02:50 +0100246 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000247 << "Timed out while waiting for the frame to render.";
248
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000249 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000250
251 sender_transport.StopSending();
252 receiver_transport.StopSending();
253
254 DestroyStreams();
255}
256
philipel277a8b52017-03-16 05:19:49 -0700257TEST_F(EndToEndTest, TransmitsFirstFrame) {
nisse7ade7b32016-03-23 04:48:10 -0700258 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000259 public:
Peter Boström5811a392015-12-10 13:02:50 +0100260 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000261
nisseeb83a1a2016-03-21 01:27:56 -0700262 void OnFrame(const VideoFrame& video_frame) override { event_.Set(); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000263
Peter Boström5811a392015-12-10 13:02:50 +0100264 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000265
Peter Boström5811a392015-12-10 13:02:50 +0100266 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000267 } renderer;
268
philipel4fb651d2017-04-10 03:54:05 -0700269 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
solenberg4fbae2b2015-08-28 04:07:10 -0700270
minyue20c84cc2017-04-10 16:57:57 -0700271 test::DirectTransport sender_transport(sender_call_.get(), payload_type_map_);
272 test::DirectTransport receiver_transport(receiver_call_.get(),
273 payload_type_map_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000274 sender_transport.SetReceiver(receiver_call_->Receiver());
275 receiver_transport.SetReceiver(sender_call_->Receiver());
276
brandtr841de6a2016-11-15 07:10:52 -0800277 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700278 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -0800279 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000280
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100281 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000282 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000283
kwiberg27f982b2016-03-01 11:52:33 -0800284 std::unique_ptr<test::FrameGenerator> frame_generator(
perkja8ba1952017-02-27 06:52:10 -0800285 test::FrameGenerator::CreateSquareGenerator(kDefaultWidth,
perkjfa10b552016-10-02 23:45:26 -0700286 kDefaultHeight));
perkja49cbd32016-09-16 07:53:41 -0700287 test::FrameForwarder frame_forwarder;
perkj803d97f2016-11-01 11:45:46 -0700288 video_send_stream_->SetSource(
sprangc5d62e22017-04-02 23:53:04 -0700289 &frame_forwarder,
290 VideoSendStream::DegradationPreference::kMaintainFramerate);
perkja49cbd32016-09-16 07:53:41 -0700291 frame_forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000292
Peter Boström5811a392015-12-10 13:02:50 +0100293 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000294 << "Timed out while waiting for the frame to render.";
295
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000296 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000297
298 sender_transport.StopSending();
299 receiver_transport.StopSending();
300
301 DestroyStreams();
302}
303
Perba7dc722016-04-19 15:01:23 +0200304class CodecObserver : public test::EndToEndTest,
nisse7ade7b32016-03-23 04:48:10 -0700305 public rtc::VideoSinkInterface<VideoFrame> {
Perba7dc722016-04-19 15:01:23 +0200306 public:
307 CodecObserver(int no_frames_to_wait_for,
308 VideoRotation rotation_to_test,
309 const std::string& payload_name,
310 webrtc::VideoEncoder* encoder,
311 webrtc::VideoDecoder* decoder)
hta9aa96882016-12-06 05:36:03 -0800312 : EndToEndTest(4 * webrtc::EndToEndTest::kDefaultTimeoutMs),
313 // TODO(hta): This timeout (120 seconds) is excessive.
314 // https://bugs.webrtc.org/6830
Perba7dc722016-04-19 15:01:23 +0200315 no_frames_to_wait_for_(no_frames_to_wait_for),
316 expected_rotation_(rotation_to_test),
317 payload_name_(payload_name),
318 encoder_(encoder),
319 decoder_(decoder),
320 frame_counter_(0) {}
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000321
Perba7dc722016-04-19 15:01:23 +0200322 void PerformTest() override {
323 EXPECT_TRUE(Wait())
324 << "Timed out while waiting for enough frames to be decoded.";
325 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000326
Perba7dc722016-04-19 15:01:23 +0200327 void ModifyVideoConfigs(
328 VideoSendStream::Config* send_config,
329 std::vector<VideoReceiveStream::Config>* receive_configs,
330 VideoEncoderConfig* encoder_config) override {
331 send_config->encoder_settings.encoder = encoder_.get();
332 send_config->encoder_settings.payload_name = payload_name_;
minyue20c84cc2017-04-10 16:57:57 -0700333 send_config->encoder_settings.payload_type =
334 test::CallTest::kVideoSendPayloadType;
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000335
Perba7dc722016-04-19 15:01:23 +0200336 (*receive_configs)[0].renderer = this;
337 (*receive_configs)[0].decoders.resize(1);
338 (*receive_configs)[0].decoders[0].payload_type =
339 send_config->encoder_settings.payload_type;
340 (*receive_configs)[0].decoders[0].payload_name =
341 send_config->encoder_settings.payload_name;
342 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
343 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000344
Perba7dc722016-04-19 15:01:23 +0200345 void OnFrame(const VideoFrame& video_frame) override {
346 EXPECT_EQ(expected_rotation_, video_frame.rotation());
347 if (++frame_counter_ == no_frames_to_wait_for_)
348 observation_complete_.Set();
349 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000350
Perba7dc722016-04-19 15:01:23 +0200351 void OnFrameGeneratorCapturerCreated(
352 test::FrameGeneratorCapturer* frame_generator_capturer) override {
353 frame_generator_capturer->SetFakeRotation(expected_rotation_);
354 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000355
Perba7dc722016-04-19 15:01:23 +0200356 private:
357 int no_frames_to_wait_for_;
358 VideoRotation expected_rotation_;
359 std::string payload_name_;
360 std::unique_ptr<webrtc::VideoEncoder> encoder_;
361 std::unique_ptr<webrtc::VideoDecoder> decoder_;
362 int frame_counter_;
363};
364
philipel277a8b52017-03-16 05:19:49 -0700365TEST_F(EndToEndTest, SendsAndReceivesVP8) {
philipel266f0a42016-11-28 08:49:07 -0800366 CodecObserver test(5, kVideoRotation_0, "VP8", VP8Encoder::Create(),
367 VP8Decoder::Create());
368 RunBaseTest(&test);
369}
370
philipel277a8b52017-03-16 05:19:49 -0700371TEST_F(EndToEndTest, SendsAndReceivesVP8Rotation90) {
magjed509e4fe2016-11-18 01:34:11 -0800372 CodecObserver test(5, kVideoRotation_90, "VP8", VP8Encoder::Create(),
Perba7dc722016-04-19 15:01:23 +0200373 VP8Decoder::Create());
374 RunBaseTest(&test);
375}
376
Peter Boström12996152016-05-14 02:03:18 +0200377#if !defined(RTC_DISABLE_VP9)
philipel277a8b52017-03-16 05:19:49 -0700378TEST_F(EndToEndTest, SendsAndReceivesVP9) {
magjed509e4fe2016-11-18 01:34:11 -0800379 CodecObserver test(500, kVideoRotation_0, "VP9", VP9Encoder::Create(),
Perba7dc722016-04-19 15:01:23 +0200380 VP9Decoder::Create());
381 RunBaseTest(&test);
382}
383
philipel277a8b52017-03-16 05:19:49 -0700384TEST_F(EndToEndTest, SendsAndReceivesVP9VideoRotation90) {
magjed509e4fe2016-11-18 01:34:11 -0800385 CodecObserver test(5, kVideoRotation_90, "VP9", VP9Encoder::Create(),
Perba7dc722016-04-19 15:01:23 +0200386 VP9Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800387 RunBaseTest(&test);
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000388}
Peter Boström12996152016-05-14 02:03:18 +0200389#endif // !defined(RTC_DISABLE_VP9)
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000390
brandtr445fb8f2016-11-14 04:11:23 -0800391#if defined(WEBRTC_USE_H264)
philipel277a8b52017-03-16 05:19:49 -0700392TEST_F(EndToEndTest, SendsAndReceivesH264) {
magjedceecea42016-11-28 07:20:21 -0800393 CodecObserver test(500, kVideoRotation_0, "H264",
394 H264Encoder::Create(cricket::VideoCodec("H264")),
Perba7dc722016-04-19 15:01:23 +0200395 H264Decoder::Create());
396 RunBaseTest(&test);
397}
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000398
philipel277a8b52017-03-16 05:19:49 -0700399TEST_F(EndToEndTest, SendsAndReceivesH264VideoRotation90) {
magjedceecea42016-11-28 07:20:21 -0800400 CodecObserver test(5, kVideoRotation_90, "H264",
401 H264Encoder::Create(cricket::VideoCodec("H264")),
Perba7dc722016-04-19 15:01:23 +0200402 H264Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800403 RunBaseTest(&test);
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000404}
hta9aa96882016-12-06 05:36:03 -0800405
philipel277a8b52017-03-16 05:19:49 -0700406TEST_F(EndToEndTest, SendsAndReceivesH264PacketizationMode0) {
hta9aa96882016-12-06 05:36:03 -0800407 cricket::VideoCodec codec = cricket::VideoCodec("H264");
408 codec.SetParam(cricket::kH264FmtpPacketizationMode, "0");
409 CodecObserver test(500, kVideoRotation_0, "H264", H264Encoder::Create(codec),
410 H264Decoder::Create());
411 RunBaseTest(&test);
412}
413
philipel277a8b52017-03-16 05:19:49 -0700414TEST_F(EndToEndTest, SendsAndReceivesH264PacketizationMode1) {
hta9aa96882016-12-06 05:36:03 -0800415 cricket::VideoCodec codec = cricket::VideoCodec("H264");
416 codec.SetParam(cricket::kH264FmtpPacketizationMode, "1");
417 CodecObserver test(500, kVideoRotation_0, "H264", H264Encoder::Create(codec),
418 H264Decoder::Create());
419 RunBaseTest(&test);
420}
421
brandtr445fb8f2016-11-14 04:11:23 -0800422#endif // defined(WEBRTC_USE_H264)
hbosbab934b2016-01-27 01:36:03 -0800423
philipel277a8b52017-03-16 05:19:49 -0700424TEST_F(EndToEndTest, ReceiverUsesLocalSsrc) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000425 class SyncRtcpObserver : public test::EndToEndTest {
426 public:
427 SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {}
428
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000429 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
danilchap3dc929e2016-11-02 08:21:59 -0700430 test::RtcpPacketParser parser;
431 EXPECT_TRUE(parser.Parse(packet, length));
432 EXPECT_EQ(kReceiverLocalVideoSsrc, parser.sender_ssrc());
Peter Boström5811a392015-12-10 13:02:50 +0100433 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000434
435 return SEND_PACKET;
436 }
437
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000438 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100439 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000440 << "Timed out while waiting for a receiver RTCP packet to be sent.";
441 }
442 } test;
443
stefane74eef12016-01-08 06:47:13 -0800444 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000445}
446
philipel277a8b52017-03-16 05:19:49 -0700447TEST_F(EndToEndTest, ReceivesAndRetransmitsNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000448 static const int kNumberOfNacksToObserve = 2;
449 static const int kLossBurstSize = 2;
450 static const int kPacketsBetweenLossBursts = 9;
451 class NackObserver : public test::EndToEndTest {
452 public:
453 NackObserver()
454 : EndToEndTest(kLongTimeoutMs),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000455 sent_rtp_packets_(0),
456 packets_left_to_drop_(0),
457 nacks_left_(kNumberOfNacksToObserve) {}
458
459 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000460 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700461 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000462 RTPHeader header;
Peter Boström03671cb2015-12-07 15:22:24 +0100463 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000464
465 // Never drop retransmitted packets.
466 if (dropped_packets_.find(header.sequenceNumber) !=
467 dropped_packets_.end()) {
468 retransmitted_packets_.insert(header.sequenceNumber);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000469 return SEND_PACKET;
470 }
471
philipel8054c7e2017-01-10 05:19:19 -0800472 if (nacks_left_ <= 0 &&
473 retransmitted_packets_.size() == dropped_packets_.size()) {
474 observation_complete_.Set();
475 }
476
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000477 ++sent_rtp_packets_;
478
479 // Enough NACKs received, stop dropping packets.
Stefan Holmer586b19b2015-09-18 11:14:31 +0200480 if (nacks_left_ <= 0)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000481 return SEND_PACKET;
482
483 // Check if it's time for a new loss burst.
484 if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
485 packets_left_to_drop_ = kLossBurstSize;
486
Stefan Holmer01b48882015-05-05 10:21:24 +0200487 // Never drop padding packets as those won't be retransmitted.
488 if (packets_left_to_drop_ > 0 && header.paddingLength == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000489 --packets_left_to_drop_;
490 dropped_packets_.insert(header.sequenceNumber);
491 return DROP_PACKET;
492 }
493
494 return SEND_PACKET;
495 }
496
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000497 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700498 rtc::CritScope lock(&crit_);
danilchap3dc929e2016-11-02 08:21:59 -0700499 test::RtcpPacketParser parser;
500 EXPECT_TRUE(parser.Parse(packet, length));
501 nacks_left_ -= parser.nack()->num_packets();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000502 return SEND_PACKET;
503 }
504
stefanff483612015-12-21 03:14:00 -0800505 void ModifyVideoConfigs(
506 VideoSendStream::Config* send_config,
507 std::vector<VideoReceiveStream::Config>* receive_configs,
508 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000509 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000510 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000511 }
512
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000513 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100514 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000515 << "Timed out waiting for packets to be NACKed, retransmitted and "
516 "rendered.";
517 }
518
stefanf116bd02015-10-27 08:29:42 -0700519 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000520 std::set<uint16_t> dropped_packets_;
521 std::set<uint16_t> retransmitted_packets_;
522 uint64_t sent_rtp_packets_;
523 int packets_left_to_drop_;
stefanf116bd02015-10-27 08:29:42 -0700524 int nacks_left_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000525 } test;
526
stefane74eef12016-01-08 06:47:13 -0800527 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000528}
529
philipel277a8b52017-03-16 05:19:49 -0700530TEST_F(EndToEndTest, ReceivesNackAndRetransmitsAudio) {
Erik Språng737336d2016-07-29 12:59:36 +0200531 class NackObserver : public test::EndToEndTest {
532 public:
533 NackObserver()
534 : EndToEndTest(kLongTimeoutMs),
535 local_ssrc_(0),
536 remote_ssrc_(0),
537 receive_transport_(nullptr) {}
538
539 private:
540 size_t GetNumVideoStreams() const override { return 0; }
541 size_t GetNumAudioStreams() const override { return 1; }
542
543 test::PacketTransport* CreateReceiveTransport() override {
544 test::PacketTransport* receive_transport = new test::PacketTransport(
minyue20c84cc2017-04-10 16:57:57 -0700545 nullptr, this, test::PacketTransport::kReceiver, payload_type_map_,
Erik Språng737336d2016-07-29 12:59:36 +0200546 FakeNetworkPipe::Config());
547 receive_transport_ = receive_transport;
548 return receive_transport;
549 }
550
551 Action OnSendRtp(const uint8_t* packet, size_t length) override {
552 RTPHeader header;
553 EXPECT_TRUE(parser_->Parse(packet, length, &header));
554
555 if (!sequence_number_to_retransmit_) {
556 sequence_number_to_retransmit_ =
557 rtc::Optional<uint16_t>(header.sequenceNumber);
558
559 // Don't ask for retransmission straight away, may be deduped in pacer.
560 } else if (header.sequenceNumber == *sequence_number_to_retransmit_) {
561 observation_complete_.Set();
562 } else {
563 // Send a NACK as often as necessary until retransmission is received.
564 rtcp::Nack nack;
danilchap822a16f2016-09-27 09:27:47 -0700565 nack.SetSenderSsrc(local_ssrc_);
566 nack.SetMediaSsrc(remote_ssrc_);
Erik Språng737336d2016-07-29 12:59:36 +0200567 uint16_t nack_list[] = {*sequence_number_to_retransmit_};
danilchap822a16f2016-09-27 09:27:47 -0700568 nack.SetPacketIds(nack_list, 1);
Erik Språng737336d2016-07-29 12:59:36 +0200569 rtc::Buffer buffer = nack.Build();
570
571 EXPECT_TRUE(receive_transport_->SendRtcp(buffer.data(), buffer.size()));
572 }
573
574 return SEND_PACKET;
575 }
576
577 void ModifyAudioConfigs(
578 AudioSendStream::Config* send_config,
579 std::vector<AudioReceiveStream::Config>* receive_configs) override {
580 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
581 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
582 local_ssrc_ = (*receive_configs)[0].rtp.local_ssrc;
583 remote_ssrc_ = (*receive_configs)[0].rtp.remote_ssrc;
584 }
585
586 void PerformTest() override {
587 EXPECT_TRUE(Wait())
588 << "Timed out waiting for packets to be NACKed, retransmitted and "
589 "rendered.";
590 }
591
592 uint32_t local_ssrc_;
593 uint32_t remote_ssrc_;
594 Transport* receive_transport_;
595 rtc::Optional<uint16_t> sequence_number_to_retransmit_;
596 } test;
597
598 RunBaseTest(&test);
599}
600
brandtrc55f27a2017-03-20 06:32:59 -0700601TEST_F(EndToEndTest, ReceivesUlpfec) {
brandtr535830e2016-10-31 03:45:58 -0700602 class UlpfecRenderObserver : public test::EndToEndTest,
603 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000604 public:
brandtr535830e2016-10-31 03:45:58 -0700605 UlpfecRenderObserver()
brandtr1134b7b2017-02-06 06:35:47 -0800606 : EndToEndTest(kDefaultTimeoutMs),
brandtrc55f27a2017-03-20 06:32:59 -0700607 encoder_(VP8Encoder::Create()),
brandtr1134b7b2017-02-06 06:35:47 -0800608 random_(0xcafef00d1),
609 num_packets_sent_(0) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000610
611 private:
stefanf116bd02015-10-27 08:29:42 -0700612 Action OnSendRtp(const uint8_t* packet, size_t length) override {
613 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000614 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000615 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000616
brandtrc55f27a2017-03-20 06:32:59 -0700617 EXPECT_TRUE(header.payloadType == kVideoSendPayloadType ||
brandtr1134b7b2017-02-06 06:35:47 -0800618 header.payloadType == kRedPayloadType)
619 << "Unknown payload type received.";
620 EXPECT_EQ(kVideoSendSsrcs[0], header.ssrc) << "Unknown SSRC received.";
621
622 // Parse RED header.
Stefan Holmer01b48882015-05-05 10:21:24 +0200623 int encapsulated_payload_type = -1;
624 if (header.payloadType == kRedPayloadType) {
625 encapsulated_payload_type =
626 static_cast<int>(packet[header.headerLength]);
brandtr1134b7b2017-02-06 06:35:47 -0800627
brandtrc55f27a2017-03-20 06:32:59 -0700628 EXPECT_TRUE(encapsulated_payload_type == kVideoSendPayloadType ||
brandtr1134b7b2017-02-06 06:35:47 -0800629 encapsulated_payload_type == kUlpfecPayloadType)
630 << "Unknown encapsulated payload type received.";
Stefan Holmer01b48882015-05-05 10:21:24 +0200631 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000632
brandtrc55f27a2017-03-20 06:32:59 -0700633 // To minimize test flakiness, always let ULPFEC packets through.
brandtr1134b7b2017-02-06 06:35:47 -0800634 if (encapsulated_payload_type == kUlpfecPayloadType) {
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000635 return SEND_PACKET;
636 }
637
brandtr1134b7b2017-02-06 06:35:47 -0800638 // Simulate 5% video packet loss after rampup period. Record the
639 // corresponding timestamps that were dropped.
640 if (num_packets_sent_++ > 100 && random_.Rand(1, 100) <= 5) {
brandtrc55f27a2017-03-20 06:32:59 -0700641 if (encapsulated_payload_type == kVideoSendPayloadType) {
brandtr1134b7b2017-02-06 06:35:47 -0800642 dropped_sequence_numbers_.insert(header.sequenceNumber);
643 dropped_timestamps_.insert(header.timestamp);
644 }
brandtr1134b7b2017-02-06 06:35:47 -0800645 return DROP_PACKET;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000646 }
647
648 return SEND_PACKET;
649 }
650
nisseeb83a1a2016-03-21 01:27:56 -0700651 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200652 rtc::CritScope lock(&crit_);
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000653 // Rendering frame with timestamp of packet that was dropped -> FEC
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000654 // protection worked.
brandtr1134b7b2017-02-06 06:35:47 -0800655 auto it = dropped_timestamps_.find(video_frame.timestamp());
656 if (it != dropped_timestamps_.end()) {
Peter Boström5811a392015-12-10 13:02:50 +0100657 observation_complete_.Set();
brandtr1134b7b2017-02-06 06:35:47 -0800658 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000659 }
660
stefanff483612015-12-21 03:14:00 -0800661 void ModifyVideoConfigs(
662 VideoSendStream::Config* send_config,
663 std::vector<VideoReceiveStream::Config>* receive_configs,
664 VideoEncoderConfig* encoder_config) override {
brandtrc55f27a2017-03-20 06:32:59 -0700665 // Use VP8 instead of FAKE, since the latter does not have PictureID
666 // in the packetization headers.
667 send_config->encoder_settings.encoder = encoder_.get();
668 send_config->encoder_settings.payload_name = "VP8";
669 send_config->encoder_settings.payload_type = kVideoSendPayloadType;
670 VideoReceiveStream::Decoder decoder =
671 test::CreateMatchingDecoder(send_config->encoder_settings);
672 decoder_.reset(decoder.decoder);
673 (*receive_configs)[0].decoders.clear();
674 (*receive_configs)[0].decoders.push_back(decoder);
675
676 // Enable ULPFEC over RED.
brandtrb5f2c3f2016-10-04 23:28:39 -0700677 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
678 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
brandtrb5f2c3f2016-10-04 23:28:39 -0700679 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
680 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
brandtrc55f27a2017-03-20 06:32:59 -0700681
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000682 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000683 }
684
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000685 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100686 EXPECT_TRUE(Wait())
brandtr1e3dfbf2016-11-16 22:45:19 -0800687 << "Timed out waiting for dropped frames to be rendered.";
688 }
689
690 rtc::CriticalSection crit_;
brandtrc55f27a2017-03-20 06:32:59 -0700691 std::unique_ptr<VideoEncoder> encoder_;
692 std::unique_ptr<VideoDecoder> decoder_;
brandtr1134b7b2017-02-06 06:35:47 -0800693 std::set<uint32_t> dropped_sequence_numbers_ GUARDED_BY(crit_);
694 // Several packets can have the same timestamp.
695 std::multiset<uint32_t> dropped_timestamps_ GUARDED_BY(crit_);
696 Random random_;
brandtrc55f27a2017-03-20 06:32:59 -0700697 int num_packets_sent_ GUARDED_BY(crit_);
brandtr1e3dfbf2016-11-16 22:45:19 -0800698 } test;
699
700 RunBaseTest(&test);
701}
702
brandtrfa5a3682017-01-17 01:33:54 -0800703class FlexfecRenderObserver : public test::EndToEndTest,
704 public rtc::VideoSinkInterface<VideoFrame> {
705 public:
706 static constexpr uint32_t kVideoLocalSsrc = 123;
707 static constexpr uint32_t kFlexfecLocalSsrc = 456;
brandtr1e3dfbf2016-11-16 22:45:19 -0800708
brandtr1134b7b2017-02-06 06:35:47 -0800709 explicit FlexfecRenderObserver(bool enable_nack, bool expect_flexfec_rtcp)
brandtrfa5a3682017-01-17 01:33:54 -0800710 : test::EndToEndTest(test::CallTest::kDefaultTimeoutMs),
brandtr1134b7b2017-02-06 06:35:47 -0800711 enable_nack_(enable_nack),
brandtrfa5a3682017-01-17 01:33:54 -0800712 expect_flexfec_rtcp_(expect_flexfec_rtcp),
713 received_flexfec_rtcp_(false),
brandtr1134b7b2017-02-06 06:35:47 -0800714 random_(0xcafef00d1),
715 num_packets_sent_(0) {}
brandtr1e3dfbf2016-11-16 22:45:19 -0800716
brandtrfa5a3682017-01-17 01:33:54 -0800717 size_t GetNumFlexfecStreams() const override { return 1; }
brandtr1e3dfbf2016-11-16 22:45:19 -0800718
brandtrfa5a3682017-01-17 01:33:54 -0800719 private:
720 Action OnSendRtp(const uint8_t* packet, size_t length) override {
721 rtc::CritScope lock(&crit_);
722 RTPHeader header;
723 EXPECT_TRUE(parser_->Parse(packet, length, &header));
brandtr1e3dfbf2016-11-16 22:45:19 -0800724
brandtr1134b7b2017-02-06 06:35:47 -0800725 EXPECT_TRUE(header.payloadType ==
726 test::CallTest::kFakeVideoSendPayloadType ||
727 header.payloadType == test::CallTest::kFlexfecPayloadType ||
728 (enable_nack_ &&
729 header.payloadType == test::CallTest::kSendRtxPayloadType))
730 << "Unknown payload type received.";
731 EXPECT_TRUE(
732 header.ssrc == test::CallTest::kVideoSendSsrcs[0] ||
733 header.ssrc == test::CallTest::kFlexfecSendSsrc ||
734 (enable_nack_ && header.ssrc == test::CallTest::kSendRtxSsrcs[0]))
735 << "Unknown SSRC received.";
736
737 // To reduce test flakiness, always let FlexFEC packets through.
738 if (header.payloadType == test::CallTest::kFlexfecPayloadType) {
739 EXPECT_EQ(test::CallTest::kFlexfecSendSsrc, header.ssrc);
740
741 return SEND_PACKET;
brandtr1e3dfbf2016-11-16 22:45:19 -0800742 }
743
brandtr1134b7b2017-02-06 06:35:47 -0800744 // To reduce test flakiness, always let RTX packets through.
745 if (header.payloadType == test::CallTest::kSendRtxPayloadType) {
746 EXPECT_EQ(test::CallTest::kSendRtxSsrcs[0], header.ssrc);
747
748 // Parse RTX header.
749 uint16_t original_sequence_number =
750 ByteReader<uint16_t>::ReadBigEndian(&packet[header.headerLength]);
751
752 // From the perspective of FEC, a retransmitted packet is no longer
753 // dropped, so remove it from list of dropped packets.
754 auto seq_num_it =
755 dropped_sequence_numbers_.find(original_sequence_number);
brandtrfa5a3682017-01-17 01:33:54 -0800756 if (seq_num_it != dropped_sequence_numbers_.end()) {
757 dropped_sequence_numbers_.erase(seq_num_it);
758 auto ts_it = dropped_timestamps_.find(header.timestamp);
759 EXPECT_NE(ts_it, dropped_timestamps_.end());
760 dropped_timestamps_.erase(ts_it);
brandtrfd8d2652017-02-06 06:19:51 -0800761 }
brandtr1134b7b2017-02-06 06:35:47 -0800762
763 return SEND_PACKET;
brandtrfa5a3682017-01-17 01:33:54 -0800764 }
765
brandtr1134b7b2017-02-06 06:35:47 -0800766 // Simulate 5% video packet loss after rampup period. Record the
767 // corresponding timestamps that were dropped.
768 if (num_packets_sent_++ > 100 && random_.Rand(1, 100) <= 5) {
769 EXPECT_EQ(test::CallTest::kFakeVideoSendPayloadType, header.payloadType);
770 EXPECT_EQ(test::CallTest::kVideoSendSsrcs[0], header.ssrc);
771
772 dropped_sequence_numbers_.insert(header.sequenceNumber);
773 dropped_timestamps_.insert(header.timestamp);
brandtrfa5a3682017-01-17 01:33:54 -0800774
775 return DROP_PACKET;
776 }
777
778 return SEND_PACKET;
779 }
780
781 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
782 test::RtcpPacketParser parser;
783
784 parser.Parse(data, length);
785 if (parser.sender_ssrc() == kFlexfecLocalSsrc) {
786 EXPECT_EQ(1, parser.receiver_report()->num_packets());
787 const std::vector<rtcp::ReportBlock>& report_blocks =
788 parser.receiver_report()->report_blocks();
789 if (!report_blocks.empty()) {
790 EXPECT_EQ(1U, report_blocks.size());
791 EXPECT_EQ(test::CallTest::kFlexfecSendSsrc,
792 report_blocks[0].source_ssrc());
brandtr1d2d7892017-01-18 00:40:07 -0800793 rtc::CritScope lock(&crit_);
brandtrfa5a3682017-01-17 01:33:54 -0800794 received_flexfec_rtcp_ = true;
795 }
796 }
797
798 return SEND_PACKET;
799 }
800
brandtr1134b7b2017-02-06 06:35:47 -0800801 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
802 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
803 const int kNetworkDelayMs = 100;
804 FakeNetworkPipe::Config config;
805 config.queue_delay_ms = kNetworkDelayMs;
806 return new test::PacketTransport(sender_call, this,
nissee5ad5ca2017-03-29 23:57:43 -0700807 test::PacketTransport::kSender,
minyue20c84cc2017-04-10 16:57:57 -0700808 test::CallTest::payload_type_map_, config);
brandtr1134b7b2017-02-06 06:35:47 -0800809 }
810
brandtrfa5a3682017-01-17 01:33:54 -0800811 void OnFrame(const VideoFrame& video_frame) override {
812 rtc::CritScope lock(&crit_);
813 // Rendering frame with timestamp of packet that was dropped -> FEC
814 // protection worked.
815 auto it = dropped_timestamps_.find(video_frame.timestamp());
816 if (it != dropped_timestamps_.end()) {
817 if (!expect_flexfec_rtcp_ || received_flexfec_rtcp_) {
brandtr1e3dfbf2016-11-16 22:45:19 -0800818 observation_complete_.Set();
brandtrfa5a3682017-01-17 01:33:54 -0800819 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800820 }
brandtrfa5a3682017-01-17 01:33:54 -0800821 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800822
brandtrfa5a3682017-01-17 01:33:54 -0800823 void ModifyVideoConfigs(
824 VideoSendStream::Config* send_config,
825 std::vector<VideoReceiveStream::Config>* receive_configs,
826 VideoEncoderConfig* encoder_config) override {
827 (*receive_configs)[0].rtp.local_ssrc = kVideoLocalSsrc;
828 (*receive_configs)[0].renderer = this;
brandtr1134b7b2017-02-06 06:35:47 -0800829
830 if (enable_nack_) {
831 send_config->rtp.nack.rtp_history_ms = test::CallTest::kNackRtpHistoryMs;
832 send_config->rtp.ulpfec.red_rtx_payload_type =
833 test::CallTest::kRtxRedPayloadType;
834 send_config->rtp.rtx.ssrcs.push_back(test::CallTest::kSendRtxSsrcs[0]);
835 send_config->rtp.rtx.payload_type = test::CallTest::kSendRtxPayloadType;
836
837 (*receive_configs)[0].rtp.nack.rtp_history_ms =
838 test::CallTest::kNackRtpHistoryMs;
839 (*receive_configs)[0].rtp.ulpfec.red_rtx_payload_type =
840 test::CallTest::kRtxRedPayloadType;
841
842 (*receive_configs)[0].rtp.rtx_ssrc = test::CallTest::kSendRtxSsrcs[0];
843 (*receive_configs)[0]
844 .rtp.rtx_payload_types[test::CallTest::kVideoSendPayloadType] =
845 test::CallTest::kSendRtxPayloadType;
846 }
brandtrfa5a3682017-01-17 01:33:54 -0800847 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800848
brandtrfa5a3682017-01-17 01:33:54 -0800849 void ModifyFlexfecConfigs(
850 std::vector<FlexfecReceiveStream::Config>* receive_configs) override {
851 (*receive_configs)[0].local_ssrc = kFlexfecLocalSsrc;
852 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000853
brandtrfa5a3682017-01-17 01:33:54 -0800854 void PerformTest() override {
855 EXPECT_TRUE(Wait())
856 << "Timed out waiting for dropped frames to be rendered.";
857 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000858
brandtrfa5a3682017-01-17 01:33:54 -0800859 rtc::CriticalSection crit_;
860 std::set<uint32_t> dropped_sequence_numbers_ GUARDED_BY(crit_);
brandtr1134b7b2017-02-06 06:35:47 -0800861 // Several packets can have the same timestamp.
brandtrfa5a3682017-01-17 01:33:54 -0800862 std::multiset<uint32_t> dropped_timestamps_ GUARDED_BY(crit_);
brandtr1134b7b2017-02-06 06:35:47 -0800863 const bool enable_nack_;
brandtr1d2d7892017-01-18 00:40:07 -0800864 const bool expect_flexfec_rtcp_;
865 bool received_flexfec_rtcp_ GUARDED_BY(crit_);
brandtrfa5a3682017-01-17 01:33:54 -0800866 Random random_;
brandtr1134b7b2017-02-06 06:35:47 -0800867 int num_packets_sent_;
brandtrfa5a3682017-01-17 01:33:54 -0800868};
869
philipel277a8b52017-03-16 05:19:49 -0700870TEST_F(EndToEndTest, RecoversWithFlexfec) {
brandtr1134b7b2017-02-06 06:35:47 -0800871 FlexfecRenderObserver test(false, false);
brandtrfa5a3682017-01-17 01:33:54 -0800872 RunBaseTest(&test);
873}
874
philipel277a8b52017-03-16 05:19:49 -0700875TEST_F(EndToEndTest, RecoversWithFlexfecAndNack) {
brandtr1134b7b2017-02-06 06:35:47 -0800876 FlexfecRenderObserver test(true, false);
877 RunBaseTest(&test);
878}
879
philipel277a8b52017-03-16 05:19:49 -0700880TEST_F(EndToEndTest, RecoversWithFlexfecAndSendsCorrespondingRtcp) {
brandtr1134b7b2017-02-06 06:35:47 -0800881 FlexfecRenderObserver test(false, true);
stefane74eef12016-01-08 06:47:13 -0800882 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000883}
884
philipel277a8b52017-03-16 05:19:49 -0700885TEST_F(EndToEndTest, ReceivedUlpfecPacketsNotNacked) {
brandtr535830e2016-10-31 03:45:58 -0700886 class UlpfecNackObserver : public test::EndToEndTest {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000887 public:
brandtr535830e2016-10-31 03:45:58 -0700888 UlpfecNackObserver()
stefanf116bd02015-10-27 08:29:42 -0700889 : EndToEndTest(kDefaultTimeoutMs),
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000890 state_(kFirstPacket),
brandtr535830e2016-10-31 03:45:58 -0700891 ulpfec_sequence_number_(0),
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000892 has_last_sequence_number_(false),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200893 last_sequence_number_(0),
magjed509e4fe2016-11-18 01:34:11 -0800894 encoder_(VP8Encoder::Create()),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200895 decoder_(VP8Decoder::Create()) {}
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000896
897 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000898 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800899 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000900 RTPHeader header;
901 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000902
Stefan Holmer01b48882015-05-05 10:21:24 +0200903 int encapsulated_payload_type = -1;
904 if (header.payloadType == kRedPayloadType) {
905 encapsulated_payload_type =
906 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100907 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200908 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
909 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100910 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200911 }
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000912
913 if (has_last_sequence_number_ &&
914 !IsNewerSequenceNumber(header.sequenceNumber,
915 last_sequence_number_)) {
916 // Drop retransmitted packets.
917 return DROP_PACKET;
918 }
919 last_sequence_number_ = header.sequenceNumber;
920 has_last_sequence_number_ = true;
921
brandtr535830e2016-10-31 03:45:58 -0700922 bool ulpfec_packet = encapsulated_payload_type == kUlpfecPayloadType;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000923 switch (state_) {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000924 case kFirstPacket:
brandtr535830e2016-10-31 03:45:58 -0700925 state_ = kDropEveryOtherPacketUntilUlpfec;
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000926 break;
brandtr535830e2016-10-31 03:45:58 -0700927 case kDropEveryOtherPacketUntilUlpfec:
928 if (ulpfec_packet) {
929 state_ = kDropAllMediaPacketsUntilUlpfec;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000930 } else if (header.sequenceNumber % 2 == 0) {
931 return DROP_PACKET;
932 }
933 break;
brandtr535830e2016-10-31 03:45:58 -0700934 case kDropAllMediaPacketsUntilUlpfec:
935 if (!ulpfec_packet)
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000936 return DROP_PACKET;
brandtr535830e2016-10-31 03:45:58 -0700937 ulpfec_sequence_number_ = header.sequenceNumber;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200938 state_ = kDropOneMediaPacket;
939 break;
940 case kDropOneMediaPacket:
brandtr535830e2016-10-31 03:45:58 -0700941 if (ulpfec_packet)
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200942 return DROP_PACKET;
943 state_ = kPassOneMediaPacket;
944 return DROP_PACKET;
945 break;
946 case kPassOneMediaPacket:
brandtr535830e2016-10-31 03:45:58 -0700947 if (ulpfec_packet)
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200948 return DROP_PACKET;
949 // Pass one media packet after dropped packet after last FEC,
950 // otherwise receiver might never see a seq_no after
brandtr535830e2016-10-31 03:45:58 -0700951 // |ulpfec_sequence_number_|
952 state_ = kVerifyUlpfecPacketNotInNackList;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000953 break;
brandtr535830e2016-10-31 03:45:58 -0700954 case kVerifyUlpfecPacketNotInNackList:
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000955 // Continue to drop packets. Make sure no frame can be decoded.
brandtr535830e2016-10-31 03:45:58 -0700956 if (ulpfec_packet || header.sequenceNumber % 2 == 0)
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000957 return DROP_PACKET;
958 break;
959 }
960 return SEND_PACKET;
961 }
962
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000963 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800964 rtc::CritScope lock_(&crit_);
brandtr535830e2016-10-31 03:45:58 -0700965 if (state_ == kVerifyUlpfecPacketNotInNackList) {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000966 test::RtcpPacketParser rtcp_parser;
967 rtcp_parser.Parse(packet, length);
Danil Chapovalovba6f7be2016-09-02 18:29:10 +0200968 const std::vector<uint16_t>& nacks = rtcp_parser.nack()->packet_ids();
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200969 EXPECT_TRUE(std::find(nacks.begin(), nacks.end(),
brandtr535830e2016-10-31 03:45:58 -0700970 ulpfec_sequence_number_) == nacks.end())
971 << "Got nack for ULPFEC packet";
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000972 if (!nacks.empty() &&
brandtr535830e2016-10-31 03:45:58 -0700973 IsNewerSequenceNumber(nacks.back(), ulpfec_sequence_number_)) {
Peter Boström5811a392015-12-10 13:02:50 +0100974 observation_complete_.Set();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000975 }
976 }
977 return SEND_PACKET;
978 }
979
stefane74eef12016-01-08 06:47:13 -0800980 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
981 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
982 // Configure some network delay.
983 const int kNetworkDelayMs = 50;
984 FakeNetworkPipe::Config config;
985 config.queue_delay_ms = kNetworkDelayMs;
986 return new test::PacketTransport(sender_call, this,
nissee5ad5ca2017-03-29 23:57:43 -0700987 test::PacketTransport::kSender,
minyue20c84cc2017-04-10 16:57:57 -0700988 payload_type_map_, config);
stefane74eef12016-01-08 06:47:13 -0800989 }
990
Stefan Holmere5904162015-03-26 11:11:06 +0100991 // TODO(holmer): Investigate why we don't send FEC packets when the bitrate
992 // is 10 kbps.
993 Call::Config GetSenderCallConfig() override {
philipel4fb651d2017-04-10 03:54:05 -0700994 Call::Config config(event_log_.get());
Stefan Holmere5904162015-03-26 11:11:06 +0100995 const int kMinBitrateBps = 30000;
996 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
997 return config;
998 }
999
stefanff483612015-12-21 03:14:00 -08001000 void ModifyVideoConfigs(
1001 VideoSendStream::Config* send_config,
1002 std::vector<VideoReceiveStream::Config>* receive_configs,
1003 VideoEncoderConfig* encoder_config) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001004 // Configure hybrid NACK/FEC.
1005 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
brandtrb5f2c3f2016-10-04 23:28:39 -07001006 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
1007 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001008 // Set codec to VP8, otherwise NACK/FEC hybrid will be disabled.
1009 send_config->encoder_settings.encoder = encoder_.get();
1010 send_config->encoder_settings.payload_name = "VP8";
1011 send_config->encoder_settings.payload_type = kFakeVideoSendPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001012
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001013 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
brandtrb5f2c3f2016-10-04 23:28:39 -07001014 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
1015 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001016
1017 (*receive_configs)[0].decoders.resize(1);
1018 (*receive_configs)[0].decoders[0].payload_type =
1019 send_config->encoder_settings.payload_type;
1020 (*receive_configs)[0].decoders[0].payload_name =
1021 send_config->encoder_settings.payload_name;
1022 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001023 }
1024
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001025 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001026 EXPECT_TRUE(Wait())
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001027 << "Timed out while waiting for FEC packets to be received.";
1028 }
1029
1030 enum {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +00001031 kFirstPacket,
brandtr535830e2016-10-31 03:45:58 -07001032 kDropEveryOtherPacketUntilUlpfec,
1033 kDropAllMediaPacketsUntilUlpfec,
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001034 kDropOneMediaPacket,
1035 kPassOneMediaPacket,
brandtr535830e2016-10-31 03:45:58 -07001036 kVerifyUlpfecPacketNotInNackList,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001037 } state_;
1038
stefan608213e2015-11-01 14:56:10 -08001039 rtc::CriticalSection crit_;
brandtr535830e2016-10-31 03:45:58 -07001040 uint16_t ulpfec_sequence_number_ GUARDED_BY(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001041 bool has_last_sequence_number_;
1042 uint16_t last_sequence_number_;
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001043 std::unique_ptr<webrtc::VideoEncoder> encoder_;
1044 std::unique_ptr<webrtc::VideoDecoder> decoder_;
stefanf116bd02015-10-27 08:29:42 -07001045 } test;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001046
stefane74eef12016-01-08 06:47:13 -08001047 RunBaseTest(&test);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001048}
1049
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001050// This test drops second RTP packet with a marker bit set, makes sure it's
1051// retransmitted and renders. Retransmission SSRCs are also checked.
Peter Boström39593972016-02-15 11:27:15 +01001052void EndToEndTest::DecodesRetransmittedFrame(bool enable_rtx, bool enable_red) {
Peter Boström67680c12016-02-17 11:10:04 +01001053 static const int kDroppedFrameNumber = 10;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001054 class RetransmissionObserver : public test::EndToEndTest,
nisse76bc8e82017-02-07 09:37:41 -08001055 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001056 public:
Peter Boström39593972016-02-15 11:27:15 +01001057 RetransmissionObserver(bool enable_rtx, bool enable_red)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001058 : EndToEndTest(kDefaultTimeoutMs),
Peter Boström39593972016-02-15 11:27:15 +01001059 payload_type_(GetPayloadType(false, enable_red)),
1060 retransmission_ssrc_(enable_rtx ? kSendRtxSsrcs[0]
1061 : kVideoSendSsrcs[0]),
1062 retransmission_payload_type_(GetPayloadType(enable_rtx, enable_red)),
magjed509e4fe2016-11-18 01:34:11 -08001063 encoder_(VP8Encoder::Create()),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001064 marker_bits_observed_(0),
danilchap192717e2016-07-25 08:20:51 -07001065 retransmitted_timestamp_(0) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001066
1067 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001068 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001069 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001070 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001071 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001072
Peter Boström67680c12016-02-17 11:10:04 +01001073 // Ignore padding-only packets over RTX.
1074 if (header.payloadType != payload_type_) {
1075 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
1076 if (length == header.headerLength + header.paddingLength)
1077 return SEND_PACKET;
Stefan Holmer586b19b2015-09-18 11:14:31 +02001078 }
Peter Boström67680c12016-02-17 11:10:04 +01001079
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001080 if (header.timestamp == retransmitted_timestamp_) {
1081 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
1082 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001083 return SEND_PACKET;
1084 }
1085
Stefan Holmer586b19b2015-09-18 11:14:31 +02001086 // Found the final packet of the frame to inflict loss to, drop this and
1087 // expect a retransmission.
danilchapfdd381c2016-07-25 04:03:20 -07001088 if (header.payloadType == payload_type_ && header.markerBit &&
1089 ++marker_bits_observed_ == kDroppedFrameNumber) {
Danil Chapovalov18c65a42016-06-29 15:29:34 +02001090 // This should be the only dropped packet.
1091 EXPECT_EQ(0u, retransmitted_timestamp_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001092 retransmitted_timestamp_ = header.timestamp;
danilchap192717e2016-07-25 08:20:51 -07001093 if (std::find(rendered_timestamps_.begin(), rendered_timestamps_.end(),
1094 retransmitted_timestamp_) != rendered_timestamps_.end()) {
1095 // Frame was rendered before last packet was scheduled for sending.
1096 // This is extremly rare but possible scenario because prober able to
1097 // resend packet before it was send.
1098 // TODO(danilchap): Remove this corner case when prober would not be
1099 // able to sneak in between packet saved to history for resending and
1100 // pacer notified about existance of that packet for sending.
1101 // See https://bugs.chromium.org/p/webrtc/issues/detail?id=5540 for
1102 // details.
1103 observation_complete_.Set();
1104 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001105 return DROP_PACKET;
1106 }
1107
1108 return SEND_PACKET;
1109 }
1110
nisse76bc8e82017-02-07 09:37:41 -08001111 void OnFrame(const VideoFrame& frame) override {
stefan5d837802017-02-08 07:09:05 -08001112 {
1113 rtc::CritScope lock(&crit_);
1114 if (frame.timestamp() == retransmitted_timestamp_)
1115 observation_complete_.Set();
1116 rendered_timestamps_.push_back(frame.timestamp());
1117 }
nisse76bc8e82017-02-07 09:37:41 -08001118 orig_renderer_->OnFrame(frame);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001119 }
1120
stefanff483612015-12-21 03:14:00 -08001121 void ModifyVideoConfigs(
1122 VideoSendStream::Config* send_config,
1123 std::vector<VideoReceiveStream::Config>* receive_configs,
1124 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001125 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
nisse76bc8e82017-02-07 09:37:41 -08001126
1127 // Insert ourselves into the rendering pipeline.
1128 RTC_DCHECK(!orig_renderer_);
1129 orig_renderer_ = (*receive_configs)[0].renderer;
1130 RTC_DCHECK(orig_renderer_);
stefan5d837802017-02-08 07:09:05 -08001131 (*receive_configs)[0].disable_prerenderer_smoothing = true;
nisse76bc8e82017-02-07 09:37:41 -08001132 (*receive_configs)[0].renderer = this;
1133
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001134 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
Shao Changbine62202f2015-04-21 20:24:50 +08001135
1136 if (payload_type_ == kRedPayloadType) {
brandtrb5f2c3f2016-10-04 23:28:39 -07001137 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
1138 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +01001139 if (retransmission_ssrc_ == kSendRtxSsrcs[0])
brandtrb5f2c3f2016-10-04 23:28:39 -07001140 send_config->rtp.ulpfec.red_rtx_payload_type = kRtxRedPayloadType;
1141 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type =
1142 send_config->rtp.ulpfec.ulpfec_payload_type;
1143 (*receive_configs)[0].rtp.ulpfec.red_payload_type =
1144 send_config->rtp.ulpfec.red_payload_type;
1145 (*receive_configs)[0].rtp.ulpfec.red_rtx_payload_type =
1146 send_config->rtp.ulpfec.red_rtx_payload_type;
Shao Changbine62202f2015-04-21 20:24:50 +08001147 }
1148
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001149 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
1150 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001151 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
brandtr14742122017-01-27 04:53:07 -08001152 (*receive_configs)[0].rtp.rtx_ssrc = kSendRtxSsrcs[0];
1153 (*receive_configs)[0].rtp.rtx_payload_types[payload_type_] =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001154 kSendRtxPayloadType;
1155 }
Peter Boström39593972016-02-15 11:27:15 +01001156 // Configure encoding and decoding with VP8, since generic packetization
1157 // doesn't support FEC with NACK.
kwibergaf476c72016-11-28 15:21:39 -08001158 RTC_DCHECK_EQ(1, (*receive_configs)[0].decoders.size());
Peter Boström39593972016-02-15 11:27:15 +01001159 send_config->encoder_settings.encoder = encoder_.get();
1160 send_config->encoder_settings.payload_name = "VP8";
1161 (*receive_configs)[0].decoders[0].payload_name = "VP8";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001162 }
1163
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001164 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001165 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001166 << "Timed out while waiting for retransmission to render.";
1167 }
1168
Shao Changbine62202f2015-04-21 20:24:50 +08001169 int GetPayloadType(bool use_rtx, bool use_red) {
Stefan Holmer10880012016-02-03 13:29:59 +01001170 if (use_red) {
1171 if (use_rtx)
1172 return kRtxRedPayloadType;
1173 return kRedPayloadType;
1174 }
1175 if (use_rtx)
1176 return kSendRtxPayloadType;
1177 return kFakeVideoSendPayloadType;
Shao Changbine62202f2015-04-21 20:24:50 +08001178 }
1179
stefanf116bd02015-10-27 08:29:42 -07001180 rtc::CriticalSection crit_;
nisse76bc8e82017-02-07 09:37:41 -08001181 rtc::VideoSinkInterface<VideoFrame>* orig_renderer_ = nullptr;
Shao Changbine62202f2015-04-21 20:24:50 +08001182 const int payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001183 const uint32_t retransmission_ssrc_;
1184 const int retransmission_payload_type_;
kwiberg27f982b2016-03-01 11:52:33 -08001185 std::unique_ptr<VideoEncoder> encoder_;
Peter Boström39593972016-02-15 11:27:15 +01001186 const std::string payload_name_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001187 int marker_bits_observed_;
stefanf116bd02015-10-27 08:29:42 -07001188 uint32_t retransmitted_timestamp_ GUARDED_BY(&crit_);
danilchap192717e2016-07-25 08:20:51 -07001189 std::vector<uint32_t> rendered_timestamps_ GUARDED_BY(&crit_);
Peter Boström39593972016-02-15 11:27:15 +01001190 } test(enable_rtx, enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001191
stefane74eef12016-01-08 06:47:13 -08001192 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001193}
1194
philipel277a8b52017-03-16 05:19:49 -07001195TEST_F(EndToEndTest, DecodesRetransmittedFrame) {
Shao Changbine62202f2015-04-21 20:24:50 +08001196 DecodesRetransmittedFrame(false, false);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001197}
1198
philipel277a8b52017-03-16 05:19:49 -07001199TEST_F(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +08001200 DecodesRetransmittedFrame(true, false);
1201}
1202
philipel277a8b52017-03-16 05:19:49 -07001203TEST_F(EndToEndTest, DecodesRetransmittedFrameByRed) {
Shao Changbine62202f2015-04-21 20:24:50 +08001204 DecodesRetransmittedFrame(false, true);
1205}
1206
philipel277a8b52017-03-16 05:19:49 -07001207TEST_F(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +08001208 DecodesRetransmittedFrame(true, true);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001209}
1210
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001211void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
1212 static const int kPacketsToDrop = 1;
1213
nisse7ade7b32016-03-23 04:48:10 -07001214 class PliObserver : public test::EndToEndTest,
1215 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001216 public:
1217 explicit PliObserver(int rtp_history_ms)
1218 : EndToEndTest(kLongTimeoutMs),
1219 rtp_history_ms_(rtp_history_ms),
1220 nack_enabled_(rtp_history_ms > 0),
1221 highest_dropped_timestamp_(0),
1222 frames_to_drop_(0),
1223 received_pli_(false) {}
1224
1225 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001226 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001227 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001228 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001229 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001230
1231 // Drop all retransmitted packets to force a PLI.
1232 if (header.timestamp <= highest_dropped_timestamp_)
1233 return DROP_PACKET;
1234
1235 if (frames_to_drop_ > 0) {
1236 highest_dropped_timestamp_ = header.timestamp;
1237 --frames_to_drop_;
1238 return DROP_PACKET;
1239 }
1240
1241 return SEND_PACKET;
1242 }
1243
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001244 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001245 rtc::CritScope lock(&crit_);
danilchap3dc929e2016-11-02 08:21:59 -07001246 test::RtcpPacketParser parser;
1247 EXPECT_TRUE(parser.Parse(packet, length));
1248 if (!nack_enabled_)
1249 EXPECT_EQ(0, parser.nack()->num_packets());
1250 if (parser.pli()->num_packets() > 0)
1251 received_pli_ = true;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001252 return SEND_PACKET;
1253 }
1254
nisseeb83a1a2016-03-21 01:27:56 -07001255 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001256 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001257 if (received_pli_ &&
1258 video_frame.timestamp() > highest_dropped_timestamp_) {
Peter Boström5811a392015-12-10 13:02:50 +01001259 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001260 }
1261 if (!received_pli_)
1262 frames_to_drop_ = kPacketsToDrop;
1263 }
1264
stefanff483612015-12-21 03:14:00 -08001265 void ModifyVideoConfigs(
1266 VideoSendStream::Config* send_config,
1267 std::vector<VideoReceiveStream::Config>* receive_configs,
1268 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001269 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001270 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
1271 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001272 }
1273
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001274 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001275 EXPECT_TRUE(Wait()) << "Timed out waiting for PLI to be "
1276 "received and a frame to be "
1277 "rendered afterwards.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001278 }
1279
stefanf116bd02015-10-27 08:29:42 -07001280 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001281 int rtp_history_ms_;
1282 bool nack_enabled_;
stefanf116bd02015-10-27 08:29:42 -07001283 uint32_t highest_dropped_timestamp_ GUARDED_BY(&crit_);
1284 int frames_to_drop_ GUARDED_BY(&crit_);
1285 bool received_pli_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001286 } test(rtp_history_ms);
1287
stefane74eef12016-01-08 06:47:13 -08001288 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001289}
1290
philipel277a8b52017-03-16 05:19:49 -07001291TEST_F(EndToEndTest, ReceivesPliAndRecoversWithNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001292 ReceivesPliAndRecovers(1000);
1293}
1294
philipel277a8b52017-03-16 05:19:49 -07001295TEST_F(EndToEndTest, ReceivesPliAndRecoversWithoutNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001296 ReceivesPliAndRecovers(0);
1297}
1298
philipel277a8b52017-03-16 05:19:49 -07001299TEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001300 class PacketInputObserver : public PacketReceiver {
1301 public:
1302 explicit PacketInputObserver(PacketReceiver* receiver)
Peter Boström5811a392015-12-10 13:02:50 +01001303 : receiver_(receiver), delivered_packet_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001304
Peter Boström5811a392015-12-10 13:02:50 +01001305 bool Wait() { return delivered_packet_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001306
1307 private:
stefan68786d22015-09-08 05:36:15 -07001308 DeliveryStatus DeliverPacket(MediaType media_type,
1309 const uint8_t* packet,
1310 size_t length,
1311 const PacketTime& packet_time) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001312 if (RtpHeaderParser::IsRtcp(packet, length)) {
stefan68786d22015-09-08 05:36:15 -07001313 return receiver_->DeliverPacket(media_type, packet, length,
1314 packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001315 } else {
1316 DeliveryStatus delivery_status =
stefan68786d22015-09-08 05:36:15 -07001317 receiver_->DeliverPacket(media_type, packet, length, packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001318 EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
Peter Boström5811a392015-12-10 13:02:50 +01001319 delivered_packet_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001320 return delivery_status;
1321 }
1322 }
1323
1324 PacketReceiver* receiver_;
Peter Boström5811a392015-12-10 13:02:50 +01001325 rtc::Event delivered_packet_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001326 };
1327
philipel4fb651d2017-04-10 03:54:05 -07001328 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
solenberg4fbae2b2015-08-28 04:07:10 -07001329
minyue20c84cc2017-04-10 16:57:57 -07001330 test::DirectTransport send_transport(sender_call_.get(), payload_type_map_);
1331 test::DirectTransport receive_transport(receiver_call_.get(),
1332 payload_type_map_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001333 PacketInputObserver input_observer(receiver_call_->Receiver());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001334 send_transport.SetReceiver(&input_observer);
1335 receive_transport.SetReceiver(sender_call_->Receiver());
1336
brandtr841de6a2016-11-15 07:10:52 -08001337 CreateSendConfig(1, 0, 0, &send_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001338 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001339
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001340 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07001341 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
1342 kDefaultHeight);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001343 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001344
stefanff483612015-12-21 03:14:00 -08001345 receiver_call_->DestroyVideoReceiveStream(video_receive_streams_[0]);
1346 video_receive_streams_.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001347
1348 // Wait() waits for a received packet.
Peter Boström5811a392015-12-10 13:02:50 +01001349 EXPECT_TRUE(input_observer.Wait());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001350
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001351 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001352
1353 DestroyStreams();
1354
1355 send_transport.StopSending();
1356 receive_transport.StopSending();
1357}
1358
pbosda903ea2015-10-02 02:36:56 -07001359void EndToEndTest::RespectsRtcpMode(RtcpMode rtcp_mode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001360 static const int kNumCompoundRtcpPacketsToObserve = 10;
1361 class RtcpModeObserver : public test::EndToEndTest {
1362 public:
pbosda903ea2015-10-02 02:36:56 -07001363 explicit RtcpModeObserver(RtcpMode rtcp_mode)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001364 : EndToEndTest(kDefaultTimeoutMs),
1365 rtcp_mode_(rtcp_mode),
1366 sent_rtp_(0),
1367 sent_rtcp_(0) {}
1368
1369 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001370 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanb77c7162017-02-06 06:29:38 -08001371 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001372 if (++sent_rtp_ % 3 == 0)
1373 return DROP_PACKET;
1374
1375 return SEND_PACKET;
1376 }
1377
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001378 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanb77c7162017-02-06 06:29:38 -08001379 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001380 ++sent_rtcp_;
danilchap3dc929e2016-11-02 08:21:59 -07001381 test::RtcpPacketParser parser;
1382 EXPECT_TRUE(parser.Parse(packet, length));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001383
danilchap3dc929e2016-11-02 08:21:59 -07001384 EXPECT_EQ(0, parser.sender_report()->num_packets());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001385
1386 switch (rtcp_mode_) {
pbosda903ea2015-10-02 02:36:56 -07001387 case RtcpMode::kCompound:
stefanb77c7162017-02-06 06:29:38 -08001388 // TODO(holmer): We shouldn't send transport feedback alone if
1389 // compound RTCP is negotiated.
1390 if (parser.receiver_report()->num_packets() == 0 &&
1391 parser.transport_feedback()->num_packets() == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001392 ADD_FAILURE() << "Received RTCP packet without receiver report for "
pbosda903ea2015-10-02 02:36:56 -07001393 "RtcpMode::kCompound.";
Peter Boström5811a392015-12-10 13:02:50 +01001394 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001395 }
1396
1397 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
Peter Boström5811a392015-12-10 13:02:50 +01001398 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001399
1400 break;
pbosda903ea2015-10-02 02:36:56 -07001401 case RtcpMode::kReducedSize:
danilchap3dc929e2016-11-02 08:21:59 -07001402 if (parser.receiver_report()->num_packets() == 0)
Peter Boström5811a392015-12-10 13:02:50 +01001403 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001404 break;
pbosda903ea2015-10-02 02:36:56 -07001405 case RtcpMode::kOff:
1406 RTC_NOTREACHED();
1407 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001408 }
1409
1410 return SEND_PACKET;
1411 }
1412
stefanff483612015-12-21 03:14:00 -08001413 void ModifyVideoConfigs(
1414 VideoSendStream::Config* send_config,
1415 std::vector<VideoReceiveStream::Config>* receive_configs,
1416 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001417 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001418 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1419 (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001420 }
1421
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001422 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001423 EXPECT_TRUE(Wait())
pbosda903ea2015-10-02 02:36:56 -07001424 << (rtcp_mode_ == RtcpMode::kCompound
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001425 ? "Timed out before observing enough compound packets."
1426 : "Timed out before receiving a non-compound RTCP packet.");
1427 }
1428
pbosda903ea2015-10-02 02:36:56 -07001429 RtcpMode rtcp_mode_;
stefanb77c7162017-02-06 06:29:38 -08001430 rtc::CriticalSection crit_;
1431 // Must be protected since RTCP can be sent by both the process thread
1432 // and the pacer thread.
1433 int sent_rtp_ GUARDED_BY(&crit_);
1434 int sent_rtcp_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001435 } test(rtcp_mode);
1436
stefane74eef12016-01-08 06:47:13 -08001437 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001438}
1439
philipel277a8b52017-03-16 05:19:49 -07001440TEST_F(EndToEndTest, UsesRtcpCompoundMode) {
pbosda903ea2015-10-02 02:36:56 -07001441 RespectsRtcpMode(RtcpMode::kCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001442}
1443
philipel277a8b52017-03-16 05:19:49 -07001444TEST_F(EndToEndTest, UsesRtcpReducedSizeMode) {
pbosda903ea2015-10-02 02:36:56 -07001445 RespectsRtcpMode(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001446}
1447
1448// Test sets up a Call multiple senders with different resolutions and SSRCs.
1449// Another is set up to receive all three of these with different renderers.
sprang867fb522015-08-03 04:38:41 -07001450class MultiStreamTest {
1451 public:
minyue20c84cc2017-04-10 16:57:57 -07001452 static constexpr size_t kNumStreams = 3;
1453 const uint8_t kVideoPayloadType = 124;
1454 const std::map<uint8_t, MediaType> payload_type_map_ = {
1455 {kVideoPayloadType, MediaType::VIDEO}};
1456
sprang867fb522015-08-03 04:38:41 -07001457 struct CodecSettings {
1458 uint32_t ssrc;
1459 int width;
1460 int height;
1461 } codec_settings[kNumStreams];
1462
1463 MultiStreamTest() {
1464 // TODO(sprang): Cleanup when msvc supports explicit initializers for array.
1465 codec_settings[0] = {1, 640, 480};
1466 codec_settings[1] = {2, 320, 240};
1467 codec_settings[2] = {3, 240, 160};
1468 }
1469
1470 virtual ~MultiStreamTest() {}
1471
1472 void RunTest() {
skvlad11a9cbf2016-10-07 11:53:05 -07001473 webrtc::RtcEventLogNullImpl event_log;
1474 Call::Config config(&event_log);
1475 std::unique_ptr<Call> sender_call(Call::Create(config));
1476 std::unique_ptr<Call> receiver_call(Call::Create(config));
kwiberg27f982b2016-03-01 11:52:33 -08001477 std::unique_ptr<test::DirectTransport> sender_transport(
stefanf116bd02015-10-27 08:29:42 -07001478 CreateSendTransport(sender_call.get()));
kwiberg27f982b2016-03-01 11:52:33 -08001479 std::unique_ptr<test::DirectTransport> receiver_transport(
stefanf116bd02015-10-27 08:29:42 -07001480 CreateReceiveTransport(receiver_call.get()));
sprang867fb522015-08-03 04:38:41 -07001481 sender_transport->SetReceiver(receiver_call->Receiver());
1482 receiver_transport->SetReceiver(sender_call->Receiver());
1483
kwiberg27f982b2016-03-01 11:52:33 -08001484 std::unique_ptr<VideoEncoder> encoders[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001485 for (size_t i = 0; i < kNumStreams; ++i)
magjed509e4fe2016-11-18 01:34:11 -08001486 encoders[i].reset(VP8Encoder::Create());
sprang867fb522015-08-03 04:38:41 -07001487
1488 VideoSendStream* send_streams[kNumStreams];
1489 VideoReceiveStream* receive_streams[kNumStreams];
1490
1491 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
kwiberg4a206a92016-03-31 10:24:26 -07001492 std::vector<std::unique_ptr<VideoDecoder>> allocated_decoders;
sprang867fb522015-08-03 04:38:41 -07001493 for (size_t i = 0; i < kNumStreams; ++i) {
1494 uint32_t ssrc = codec_settings[i].ssrc;
1495 int width = codec_settings[i].width;
1496 int height = codec_settings[i].height;
1497
solenberg4fbae2b2015-08-28 04:07:10 -07001498 VideoSendStream::Config send_config(sender_transport.get());
sprang867fb522015-08-03 04:38:41 -07001499 send_config.rtp.ssrcs.push_back(ssrc);
1500 send_config.encoder_settings.encoder = encoders[i].get();
1501 send_config.encoder_settings.payload_name = "VP8";
minyue20c84cc2017-04-10 16:57:57 -07001502 send_config.encoder_settings.payload_type = kVideoPayloadType;
sprang867fb522015-08-03 04:38:41 -07001503 VideoEncoderConfig encoder_config;
perkjfa10b552016-10-02 23:45:26 -07001504 test::FillEncoderConfiguration(1, &encoder_config);
1505 encoder_config.max_bitrate_bps = 100000;
sprang867fb522015-08-03 04:38:41 -07001506
1507 UpdateSendConfig(i, &send_config, &encoder_config, &frame_generators[i]);
1508
perkj26091b12016-09-01 01:17:40 -07001509 send_streams[i] = sender_call->CreateVideoSendStream(
1510 send_config.Copy(), encoder_config.Copy());
sprang867fb522015-08-03 04:38:41 -07001511 send_streams[i]->Start();
1512
solenberg4fbae2b2015-08-28 04:07:10 -07001513 VideoReceiveStream::Config receive_config(receiver_transport.get());
sprang867fb522015-08-03 04:38:41 -07001514 receive_config.rtp.remote_ssrc = ssrc;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001515 receive_config.rtp.local_ssrc = test::CallTest::kReceiverLocalVideoSsrc;
sprang867fb522015-08-03 04:38:41 -07001516 VideoReceiveStream::Decoder decoder =
1517 test::CreateMatchingDecoder(send_config.encoder_settings);
kwiberg4a206a92016-03-31 10:24:26 -07001518 allocated_decoders.push_back(
1519 std::unique_ptr<VideoDecoder>(decoder.decoder));
sprang867fb522015-08-03 04:38:41 -07001520 receive_config.decoders.push_back(decoder);
1521
1522 UpdateReceiveConfig(i, &receive_config);
1523
1524 receive_streams[i] =
Tommi733b5472016-06-10 17:58:01 +02001525 receiver_call->CreateVideoReceiveStream(std::move(receive_config));
sprang867fb522015-08-03 04:38:41 -07001526 receive_streams[i]->Start();
1527
1528 frame_generators[i] = test::FrameGeneratorCapturer::Create(
perkja49cbd32016-09-16 07:53:41 -07001529 width, height, 30, Clock::GetRealTimeClock());
perkj803d97f2016-11-01 11:45:46 -07001530 send_streams[i]->SetSource(
1531 frame_generators[i],
sprangc5d62e22017-04-02 23:53:04 -07001532 VideoSendStream::DegradationPreference::kMaintainFramerate);
sprang867fb522015-08-03 04:38:41 -07001533 frame_generators[i]->Start();
1534 }
1535
1536 Wait();
1537
1538 for (size_t i = 0; i < kNumStreams; ++i) {
1539 frame_generators[i]->Stop();
1540 sender_call->DestroyVideoSendStream(send_streams[i]);
1541 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1542 delete frame_generators[i];
1543 }
1544
1545 sender_transport->StopSending();
1546 receiver_transport->StopSending();
1547 }
1548
1549 protected:
1550 virtual void Wait() = 0;
1551 // Note: frame_generator is a point-to-pointer, since the actual instance
1552 // hasn't been created at the time of this call. Only when packets/frames
1553 // start flowing should this be dereferenced.
1554 virtual void UpdateSendConfig(
1555 size_t stream_index,
1556 VideoSendStream::Config* send_config,
1557 VideoEncoderConfig* encoder_config,
1558 test::FrameGeneratorCapturer** frame_generator) {}
1559 virtual void UpdateReceiveConfig(size_t stream_index,
1560 VideoReceiveStream::Config* receive_config) {
1561 }
stefanf116bd02015-10-27 08:29:42 -07001562 virtual test::DirectTransport* CreateSendTransport(Call* sender_call) {
minyue20c84cc2017-04-10 16:57:57 -07001563 return new test::DirectTransport(sender_call, payload_type_map_);
sprang867fb522015-08-03 04:38:41 -07001564 }
stefanf116bd02015-10-27 08:29:42 -07001565 virtual test::DirectTransport* CreateReceiveTransport(Call* receiver_call) {
minyue20c84cc2017-04-10 16:57:57 -07001566 return new test::DirectTransport(receiver_call, payload_type_map_);
sprang867fb522015-08-03 04:38:41 -07001567 }
1568};
1569
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001570// Each renderer verifies that it receives the expected resolution, and as soon
1571// as every renderer has received a frame, the test finishes.
philipel277a8b52017-03-16 05:19:49 -07001572TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) {
nisse7ade7b32016-03-23 04:48:10 -07001573 class VideoOutputObserver : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001574 public:
sprang867fb522015-08-03 04:38:41 -07001575 VideoOutputObserver(const MultiStreamTest::CodecSettings& settings,
1576 uint32_t ssrc,
1577 test::FrameGeneratorCapturer** frame_generator)
1578 : settings_(settings),
1579 ssrc_(ssrc),
1580 frame_generator_(frame_generator),
Peter Boström5811a392015-12-10 13:02:50 +01001581 done_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001582
nisseeb83a1a2016-03-21 01:27:56 -07001583 void OnFrame(const VideoFrame& video_frame) override {
sprang867fb522015-08-03 04:38:41 -07001584 EXPECT_EQ(settings_.width, video_frame.width());
1585 EXPECT_EQ(settings_.height, video_frame.height());
1586 (*frame_generator_)->Stop();
Peter Boström5811a392015-12-10 13:02:50 +01001587 done_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001588 }
1589
sprang867fb522015-08-03 04:38:41 -07001590 uint32_t Ssrc() { return ssrc_; }
1591
Peter Boström5811a392015-12-10 13:02:50 +01001592 bool Wait() { return done_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001593
1594 private:
sprang867fb522015-08-03 04:38:41 -07001595 const MultiStreamTest::CodecSettings& settings_;
1596 const uint32_t ssrc_;
1597 test::FrameGeneratorCapturer** const frame_generator_;
Peter Boström5811a392015-12-10 13:02:50 +01001598 rtc::Event done_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001599 };
1600
sprang867fb522015-08-03 04:38:41 -07001601 class Tester : public MultiStreamTest {
1602 public:
1603 Tester() {}
1604 virtual ~Tester() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001605
sprang867fb522015-08-03 04:38:41 -07001606 protected:
1607 void Wait() override {
1608 for (const auto& observer : observers_) {
Peter Boström5811a392015-12-10 13:02:50 +01001609 EXPECT_TRUE(observer->Wait()) << "Time out waiting for from on ssrc "
1610 << observer->Ssrc();
sprang867fb522015-08-03 04:38:41 -07001611 }
1612 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001613
sprang867fb522015-08-03 04:38:41 -07001614 void UpdateSendConfig(
1615 size_t stream_index,
1616 VideoSendStream::Config* send_config,
1617 VideoEncoderConfig* encoder_config,
1618 test::FrameGeneratorCapturer** frame_generator) override {
1619 observers_[stream_index].reset(new VideoOutputObserver(
1620 codec_settings[stream_index], send_config->rtp.ssrcs.front(),
1621 frame_generator));
1622 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001623
sprang867fb522015-08-03 04:38:41 -07001624 void UpdateReceiveConfig(
1625 size_t stream_index,
1626 VideoReceiveStream::Config* receive_config) override {
1627 receive_config->renderer = observers_[stream_index].get();
1628 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001629
sprang867fb522015-08-03 04:38:41 -07001630 private:
kwiberg27f982b2016-03-01 11:52:33 -08001631 std::unique_ptr<VideoOutputObserver> observers_[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001632 } tester;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001633
sprang867fb522015-08-03 04:38:41 -07001634 tester.RunTest();
1635}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001636
philipel277a8b52017-03-16 05:19:49 -07001637TEST_F(EndToEndTest, AssignsTransportSequenceNumbers) {
sprang867fb522015-08-03 04:38:41 -07001638 static const int kExtensionId = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001639
sprang867fb522015-08-03 04:38:41 -07001640 class RtpExtensionHeaderObserver : public test::DirectTransport {
1641 public:
minyue20c84cc2017-04-10 16:57:57 -07001642 RtpExtensionHeaderObserver(
1643 Call* sender_call,
1644 const uint32_t& first_media_ssrc,
1645 const std::map<uint32_t, uint32_t>& ssrc_map,
1646 const std::map<uint8_t, MediaType>& payload_type_map)
1647 : DirectTransport(sender_call, payload_type_map),
Peter Boström5811a392015-12-10 13:02:50 +01001648 done_(false, false),
sprang867fb522015-08-03 04:38:41 -07001649 parser_(RtpHeaderParser::Create()),
sprang861c55e2015-10-16 10:01:21 -07001650 first_media_ssrc_(first_media_ssrc),
1651 rtx_to_media_ssrcs_(ssrc_map),
sprang867fb522015-08-03 04:38:41 -07001652 padding_observed_(false),
sprang861c55e2015-10-16 10:01:21 -07001653 rtx_padding_observed_(false),
1654 retransmit_observed_(false),
1655 started_(false) {
sprang867fb522015-08-03 04:38:41 -07001656 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
1657 kExtensionId);
1658 }
1659 virtual ~RtpExtensionHeaderObserver() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001660
stefan1d8a5062015-10-02 03:39:33 -07001661 bool SendRtp(const uint8_t* data,
1662 size_t length,
1663 const PacketOptions& options) override {
sprang861c55e2015-10-16 10:01:21 -07001664 {
1665 rtc::CritScope cs(&lock_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001666
Erik Språng8d629712015-08-04 16:24:03 +02001667 if (IsDone())
sprang861c55e2015-10-16 10:01:21 -07001668 return false;
1669
1670 if (started_) {
1671 RTPHeader header;
1672 EXPECT_TRUE(parser_->Parse(data, length, &header));
1673 bool drop_packet = false;
1674
1675 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
1676 EXPECT_EQ(options.packet_id,
1677 header.extension.transportSequenceNumber);
1678 if (!streams_observed_.empty()) {
1679 // Unwrap packet id and verify uniqueness.
1680 int64_t packet_id = unwrapper_.Unwrap(options.packet_id);
1681 EXPECT_TRUE(received_packed_ids_.insert(packet_id).second);
1682 }
1683
1684 // Drop (up to) every 17th packet, so we get retransmits.
1685 // Only drop media, and not on the first stream (otherwise it will be
1686 // hard to distinguish from padding, which is always sent on the first
1687 // stream).
1688 if (header.payloadType != kSendRtxPayloadType &&
1689 header.ssrc != first_media_ssrc_ &&
1690 header.extension.transportSequenceNumber % 17 == 0) {
1691 dropped_seq_[header.ssrc].insert(header.sequenceNumber);
1692 drop_packet = true;
1693 }
1694
perkja8ba1952017-02-27 06:52:10 -08001695 if (header.payloadType == kSendRtxPayloadType) {
sprang861c55e2015-10-16 10:01:21 -07001696 uint16_t original_sequence_number =
1697 ByteReader<uint16_t>::ReadBigEndian(&data[header.headerLength]);
1698 uint32_t original_ssrc =
1699 rtx_to_media_ssrcs_.find(header.ssrc)->second;
1700 std::set<uint16_t>* seq_no_map = &dropped_seq_[original_ssrc];
1701 auto it = seq_no_map->find(original_sequence_number);
1702 if (it != seq_no_map->end()) {
1703 retransmit_observed_ = true;
1704 seq_no_map->erase(it);
1705 } else {
1706 rtx_padding_observed_ = true;
1707 }
1708 } else {
1709 streams_observed_.insert(header.ssrc);
1710 }
1711
1712 if (IsDone())
Peter Boström5811a392015-12-10 13:02:50 +01001713 done_.Set();
sprang861c55e2015-10-16 10:01:21 -07001714
1715 if (drop_packet)
1716 return true;
1717 }
sprang867fb522015-08-03 04:38:41 -07001718 }
sprang861c55e2015-10-16 10:01:21 -07001719
stefan1d8a5062015-10-02 03:39:33 -07001720 return test::DirectTransport::SendRtp(data, length, options);
sprang867fb522015-08-03 04:38:41 -07001721 }
1722
Erik Språng8d629712015-08-04 16:24:03 +02001723 bool IsDone() {
sprang861c55e2015-10-16 10:01:21 -07001724 bool observed_types_ok =
1725 streams_observed_.size() == MultiStreamTest::kNumStreams &&
perkja8ba1952017-02-27 06:52:10 -08001726 retransmit_observed_ && rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001727 if (!observed_types_ok)
1728 return false;
1729 // We should not have any gaps in the sequence number range.
1730 size_t seqno_range =
1731 *received_packed_ids_.rbegin() - *received_packed_ids_.begin() + 1;
1732 return seqno_range == received_packed_ids_.size();
Erik Språng8d629712015-08-04 16:24:03 +02001733 }
1734
Peter Boström5811a392015-12-10 13:02:50 +01001735 bool Wait() {
sprang861c55e2015-10-16 10:01:21 -07001736 {
1737 // Can't be sure until this point that rtx_to_media_ssrcs_ etc have
1738 // been initialized and are OK to read.
1739 rtc::CritScope cs(&lock_);
1740 started_ = true;
1741 }
Peter Boström5811a392015-12-10 13:02:50 +01001742 return done_.Wait(kDefaultTimeoutMs);
sprang861c55e2015-10-16 10:01:21 -07001743 }
sprang867fb522015-08-03 04:38:41 -07001744
sprang861c55e2015-10-16 10:01:21 -07001745 rtc::CriticalSection lock_;
Peter Boström5811a392015-12-10 13:02:50 +01001746 rtc::Event done_;
kwiberg27f982b2016-03-01 11:52:33 -08001747 std::unique_ptr<RtpHeaderParser> parser_;
sprang861c55e2015-10-16 10:01:21 -07001748 SequenceNumberUnwrapper unwrapper_;
1749 std::set<int64_t> received_packed_ids_;
sprang867fb522015-08-03 04:38:41 -07001750 std::set<uint32_t> streams_observed_;
sprang861c55e2015-10-16 10:01:21 -07001751 std::map<uint32_t, std::set<uint16_t>> dropped_seq_;
1752 const uint32_t& first_media_ssrc_;
1753 const std::map<uint32_t, uint32_t>& rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001754 bool padding_observed_;
1755 bool rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001756 bool retransmit_observed_;
1757 bool started_;
sprang867fb522015-08-03 04:38:41 -07001758 };
1759
1760 class TransportSequenceNumberTester : public MultiStreamTest {
1761 public:
sprang861c55e2015-10-16 10:01:21 -07001762 TransportSequenceNumberTester()
1763 : first_media_ssrc_(0), observer_(nullptr) {}
sprang867fb522015-08-03 04:38:41 -07001764 virtual ~TransportSequenceNumberTester() {}
1765
1766 protected:
1767 void Wait() override {
Peter Boström74f6e9e2016-04-04 17:56:10 +02001768 RTC_DCHECK(observer_);
Peter Boström5811a392015-12-10 13:02:50 +01001769 EXPECT_TRUE(observer_->Wait());
sprang867fb522015-08-03 04:38:41 -07001770 }
1771
1772 void UpdateSendConfig(
1773 size_t stream_index,
1774 VideoSendStream::Config* send_config,
1775 VideoEncoderConfig* encoder_config,
1776 test::FrameGeneratorCapturer** frame_generator) override {
1777 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001778 send_config->rtp.extensions.push_back(RtpExtension(
1779 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sprang867fb522015-08-03 04:38:41 -07001780
perkja8ba1952017-02-27 06:52:10 -08001781 // Force some padding to be sent. Note that since we do send media
1782 // packets we can not guarantee that a padding only packet is sent.
1783 // Instead, padding will most likely be send as an RTX packet.
sprang867fb522015-08-03 04:38:41 -07001784 const int kPaddingBitrateBps = 50000;
perkja8ba1952017-02-27 06:52:10 -08001785 encoder_config->max_bitrate_bps = 200000;
sprang867fb522015-08-03 04:38:41 -07001786 encoder_config->min_transmit_bitrate_bps =
perkjfa10b552016-10-02 23:45:26 -07001787 encoder_config->max_bitrate_bps + kPaddingBitrateBps;
sprang867fb522015-08-03 04:38:41 -07001788
1789 // Configure RTX for redundant payload padding.
1790 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang861c55e2015-10-16 10:01:21 -07001791 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[stream_index]);
sprang867fb522015-08-03 04:38:41 -07001792 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
sprang861c55e2015-10-16 10:01:21 -07001793 rtx_to_media_ssrcs_[kSendRtxSsrcs[stream_index]] =
1794 send_config->rtp.ssrcs[0];
1795
1796 if (stream_index == 0)
1797 first_media_ssrc_ = send_config->rtp.ssrcs[0];
sprang867fb522015-08-03 04:38:41 -07001798 }
1799
1800 void UpdateReceiveConfig(
1801 size_t stream_index,
1802 VideoReceiveStream::Config* receive_config) override {
sprang861c55e2015-10-16 10:01:21 -07001803 receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang867fb522015-08-03 04:38:41 -07001804 receive_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001805 receive_config->rtp.extensions.push_back(RtpExtension(
1806 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sakal55d932b2016-09-30 06:19:08 -07001807 receive_config->renderer = &fake_renderer_;
sprang867fb522015-08-03 04:38:41 -07001808 }
1809
stefanf116bd02015-10-27 08:29:42 -07001810 test::DirectTransport* CreateSendTransport(Call* sender_call) override {
minyue20c84cc2017-04-10 16:57:57 -07001811 std::map<uint8_t, MediaType> payload_type_map =
1812 MultiStreamTest::payload_type_map_;
1813 RTC_DCHECK(payload_type_map.find(kSendRtxPayloadType) ==
1814 payload_type_map.end());
1815 payload_type_map[kSendRtxPayloadType] = MediaType::VIDEO;
1816 observer_ =
1817 new RtpExtensionHeaderObserver(sender_call, first_media_ssrc_,
1818 rtx_to_media_ssrcs_, payload_type_map);
sprang867fb522015-08-03 04:38:41 -07001819 return observer_;
1820 }
1821
1822 private:
sakal55d932b2016-09-30 06:19:08 -07001823 test::FakeVideoRenderer fake_renderer_;
sprang861c55e2015-10-16 10:01:21 -07001824 uint32_t first_media_ssrc_;
1825 std::map<uint32_t, uint32_t> rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001826 RtpExtensionHeaderObserver* observer_;
1827 } tester;
1828
1829 tester.RunTest();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001830}
1831
Stefan Holmer04cb7632016-01-14 20:34:30 +01001832class TransportFeedbackTester : public test::EndToEndTest {
1833 public:
1834 explicit TransportFeedbackTester(bool feedback_enabled,
1835 size_t num_video_streams,
1836 size_t num_audio_streams)
1837 : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
1838 feedback_enabled_(feedback_enabled),
1839 num_video_streams_(num_video_streams),
sprangcd349d92016-07-13 09:11:28 -07001840 num_audio_streams_(num_audio_streams),
1841 receiver_call_(nullptr) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001842 // Only one stream of each supported for now.
1843 EXPECT_LE(num_video_streams, 1u);
1844 EXPECT_LE(num_audio_streams, 1u);
1845 }
1846
1847 protected:
1848 Action OnSendRtcp(const uint8_t* data, size_t length) override {
1849 EXPECT_FALSE(HasTransportFeedback(data, length));
1850 return SEND_PACKET;
1851 }
1852
1853 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
1854 if (HasTransportFeedback(data, length))
1855 observation_complete_.Set();
1856 return SEND_PACKET;
1857 }
1858
1859 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
danilchap3dc929e2016-11-02 08:21:59 -07001860 test::RtcpPacketParser parser;
1861 EXPECT_TRUE(parser.Parse(data, length));
1862 return parser.transport_feedback()->num_packets() > 0;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001863 }
1864
1865 void PerformTest() override {
1866 const int64_t kDisabledFeedbackTimeoutMs = 5000;
1867 EXPECT_EQ(feedback_enabled_,
1868 observation_complete_.Wait(feedback_enabled_
1869 ? test::CallTest::kDefaultTimeoutMs
1870 : kDisabledFeedbackTimeoutMs));
1871 }
1872
1873 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1874 receiver_call_ = receiver_call;
1875 }
1876
1877 size_t GetNumVideoStreams() const override { return num_video_streams_; }
1878 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
1879
1880 void ModifyVideoConfigs(
1881 VideoSendStream::Config* send_config,
1882 std::vector<VideoReceiveStream::Config>* receive_configs,
1883 VideoEncoderConfig* encoder_config) override {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001884 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
1885 }
1886
1887 void ModifyAudioConfigs(
1888 AudioSendStream::Config* send_config,
1889 std::vector<AudioReceiveStream::Config>* receive_configs) override {
1890 send_config->rtp.extensions.clear();
1891 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001892 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001893 (*receive_configs)[0].rtp.extensions.clear();
1894 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1895 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001896 }
1897
1898 private:
Erik Språng6b8d3552015-09-24 15:06:57 +02001899 static const int kExtensionId = 5;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001900 const bool feedback_enabled_;
1901 const size_t num_video_streams_;
1902 const size_t num_audio_streams_;
1903 Call* receiver_call_;
1904};
Erik Språng6b8d3552015-09-24 15:06:57 +02001905
philipel277a8b52017-03-16 05:19:49 -07001906TEST_F(EndToEndTest, VideoReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001907 TransportFeedbackTester test(true, 1, 0);
1908 RunBaseTest(&test);
Erik Språng6b8d3552015-09-24 15:06:57 +02001909}
stefan43edf0f2015-11-20 18:05:48 -08001910
philipel277a8b52017-03-16 05:19:49 -07001911TEST_F(EndToEndTest, VideoTransportFeedbackNotConfigured) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001912 TransportFeedbackTester test(false, 1, 0);
1913 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001914}
1915
philipel277a8b52017-03-16 05:19:49 -07001916TEST_F(EndToEndTest, AudioReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001917 TransportFeedbackTester test(true, 0, 1);
1918 RunBaseTest(&test);
1919}
1920
philipel277a8b52017-03-16 05:19:49 -07001921TEST_F(EndToEndTest, AudioTransportFeedbackNotConfigured) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001922 TransportFeedbackTester test(false, 0, 1);
1923 RunBaseTest(&test);
1924}
1925
philipel277a8b52017-03-16 05:19:49 -07001926TEST_F(EndToEndTest, AudioVideoReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001927 TransportFeedbackTester test(true, 1, 1);
1928 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001929}
1930
philipel277a8b52017-03-16 05:19:49 -07001931TEST_F(EndToEndTest, ObserversEncodedFrames) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001932 class EncodedFrameTestObserver : public EncodedFrameObserver {
1933 public:
1934 EncodedFrameTestObserver()
Peter Boström5811a392015-12-10 13:02:50 +01001935 : length_(0), frame_type_(kEmptyFrame), called_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001936 virtual ~EncodedFrameTestObserver() {}
1937
1938 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
1939 frame_type_ = encoded_frame.frame_type_;
1940 length_ = encoded_frame.length_;
1941 buffer_.reset(new uint8_t[length_]);
1942 memcpy(buffer_.get(), encoded_frame.data_, length_);
Peter Boström5811a392015-12-10 13:02:50 +01001943 called_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001944 }
1945
Peter Boström5811a392015-12-10 13:02:50 +01001946 bool Wait() { return called_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001947
1948 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
1949 ASSERT_EQ(length_, observer.length_)
1950 << "Observed frames are of different lengths.";
1951 EXPECT_EQ(frame_type_, observer.frame_type_)
1952 << "Observed frames have different frame types.";
1953 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
1954 << "Observed encoded frames have different content.";
1955 }
1956
1957 private:
kwiberg27f982b2016-03-01 11:52:33 -08001958 std::unique_ptr<uint8_t[]> buffer_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001959 size_t length_;
1960 FrameType frame_type_;
Peter Boström5811a392015-12-10 13:02:50 +01001961 rtc::Event called_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001962 };
1963
1964 EncodedFrameTestObserver post_encode_observer;
1965 EncodedFrameTestObserver pre_decode_observer;
1966
philipel4fb651d2017-04-10 03:54:05 -07001967 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
solenberg4fbae2b2015-08-28 04:07:10 -07001968
minyue20c84cc2017-04-10 16:57:57 -07001969 test::DirectTransport sender_transport(sender_call_.get(), payload_type_map_);
1970 test::DirectTransport receiver_transport(receiver_call_.get(),
1971 payload_type_map_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001972 sender_transport.SetReceiver(receiver_call_->Receiver());
1973 receiver_transport.SetReceiver(sender_call_->Receiver());
1974
brandtr841de6a2016-11-15 07:10:52 -08001975 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001976 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -08001977 video_send_config_.post_encode_callback = &post_encode_observer;
1978 video_receive_configs_[0].pre_decode_callback = &pre_decode_observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001979
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001980 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001981 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001982
kwiberg27f982b2016-03-01 11:52:33 -08001983 std::unique_ptr<test::FrameGenerator> frame_generator(
perkja8ba1952017-02-27 06:52:10 -08001984 test::FrameGenerator::CreateSquareGenerator(kDefaultWidth,
perkjfa10b552016-10-02 23:45:26 -07001985 kDefaultHeight));
perkja49cbd32016-09-16 07:53:41 -07001986 test::FrameForwarder forwarder;
perkj803d97f2016-11-01 11:45:46 -07001987 video_send_stream_->SetSource(
sprangc5d62e22017-04-02 23:53:04 -07001988 &forwarder, VideoSendStream::DegradationPreference::kMaintainFramerate);
perkja49cbd32016-09-16 07:53:41 -07001989 forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001990
Peter Boström5811a392015-12-10 13:02:50 +01001991 EXPECT_TRUE(post_encode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001992 << "Timed out while waiting for send-side encoded-frame callback.";
1993
Peter Boström5811a392015-12-10 13:02:50 +01001994 EXPECT_TRUE(pre_decode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001995 << "Timed out while waiting for pre-decode encoded-frame callback.";
1996
1997 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
1998
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001999 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002000
2001 sender_transport.StopSending();
2002 receiver_transport.StopSending();
2003
2004 DestroyStreams();
2005}
2006
philipel277a8b52017-03-16 05:19:49 -07002007TEST_F(EndToEndTest, ReceiveStreamSendsRemb) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002008 class RembObserver : public test::EndToEndTest {
2009 public:
2010 RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
2011
stefanb77c7162017-02-06 06:29:38 -08002012 void ModifyVideoConfigs(
2013 VideoSendStream::Config* send_config,
2014 std::vector<VideoReceiveStream::Config>* receive_configs,
2015 VideoEncoderConfig* encoder_config) override {
2016 send_config->rtp.extensions.clear();
2017 send_config->rtp.extensions.push_back(RtpExtension(
2018 RtpExtension::kAbsSendTimeUri, test::kAbsSendTimeExtensionId));
2019 (*receive_configs)[0].rtp.remb = true;
2020 (*receive_configs)[0].rtp.transport_cc = false;
2021 }
2022
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002023 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
danilchap3dc929e2016-11-02 08:21:59 -07002024 test::RtcpPacketParser parser;
2025 EXPECT_TRUE(parser.Parse(packet, length));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002026
danilchap3dc929e2016-11-02 08:21:59 -07002027 if (parser.remb()->num_packets() > 0) {
2028 EXPECT_EQ(kReceiverLocalVideoSsrc, parser.remb()->sender_ssrc());
2029 EXPECT_LT(0U, parser.remb()->bitrate_bps());
2030 EXPECT_EQ(1U, parser.remb()->ssrcs().size());
2031 EXPECT_EQ(kVideoSendSsrcs[0], parser.remb()->ssrcs()[0]);
Peter Boström5811a392015-12-10 13:02:50 +01002032 observation_complete_.Set();
danilchap3dc929e2016-11-02 08:21:59 -07002033 }
2034
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002035 return SEND_PACKET;
2036 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002037 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002038 EXPECT_TRUE(Wait()) << "Timed out while waiting for a "
2039 "receiver RTCP REMB packet to be "
2040 "sent.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002041 }
2042 } test;
2043
stefane74eef12016-01-08 06:47:13 -08002044 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002045}
2046
stefanb77c7162017-02-06 06:29:38 -08002047class BandwidthStatsTest : public test::EndToEndTest {
2048 public:
2049 explicit BandwidthStatsTest(bool send_side_bwe)
2050 : EndToEndTest(test::CallTest::kDefaultTimeoutMs),
2051 sender_call_(nullptr),
2052 receiver_call_(nullptr),
2053 has_seen_pacer_delay_(false),
2054 send_side_bwe_(send_side_bwe) {}
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002055
stefanb77c7162017-02-06 06:29:38 -08002056 void ModifyVideoConfigs(
2057 VideoSendStream::Config* send_config,
2058 std::vector<VideoReceiveStream::Config>* receive_configs,
2059 VideoEncoderConfig* encoder_config) override {
2060 if (!send_side_bwe_) {
2061 send_config->rtp.extensions.clear();
2062 send_config->rtp.extensions.push_back(RtpExtension(
2063 RtpExtension::kAbsSendTimeUri, test::kAbsSendTimeExtensionId));
2064 (*receive_configs)[0].rtp.remb = true;
2065 (*receive_configs)[0].rtp.transport_cc = false;
2066 }
2067 }
2068
2069 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2070 Call::Stats sender_stats = sender_call_->GetStats();
2071 Call::Stats receiver_stats = receiver_call_->GetStats();
2072 if (!has_seen_pacer_delay_)
2073 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
2074 if (sender_stats.send_bandwidth_bps > 0 && has_seen_pacer_delay_) {
2075 if (send_side_bwe_ || receiver_stats.recv_bandwidth_bps > 0)
Peter Boström5811a392015-12-10 13:02:50 +01002076 observation_complete_.Set();
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002077 }
stefanb77c7162017-02-06 06:29:38 -08002078 return SEND_PACKET;
2079 }
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002080
stefanb77c7162017-02-06 06:29:38 -08002081 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2082 sender_call_ = sender_call;
2083 receiver_call_ = receiver_call;
2084 }
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002085
stefanb77c7162017-02-06 06:29:38 -08002086 void PerformTest() override {
2087 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2088 "non-zero bandwidth stats.";
2089 }
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002090
stefanb77c7162017-02-06 06:29:38 -08002091 private:
2092 Call* sender_call_;
2093 Call* receiver_call_;
2094 bool has_seen_pacer_delay_;
2095 const bool send_side_bwe_;
2096};
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002097
philipel277a8b52017-03-16 05:19:49 -07002098TEST_F(EndToEndTest, VerifySendSideBweStats) {
stefanb77c7162017-02-06 06:29:38 -08002099 BandwidthStatsTest test(true);
stefane74eef12016-01-08 06:47:13 -08002100 RunBaseTest(&test);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002101}
2102
philipel277a8b52017-03-16 05:19:49 -07002103TEST_F(EndToEndTest, VerifyRecvSideBweStats) {
stefanb77c7162017-02-06 06:29:38 -08002104 BandwidthStatsTest test(false);
2105 RunBaseTest(&test);
2106}
stefan32f81542016-01-20 07:13:58 -08002107
2108// Verifies that it's possible to limit the send BWE by sending a REMB.
2109// This is verified by allowing the send BWE to ramp-up to >1000 kbps,
2110// then have the test generate a REMB of 500 kbps and verify that the send BWE
2111// is reduced to exactly 500 kbps. Then a REMB of 1000 kbps is generated and the
2112// test verifies that the send BWE ramps back up to exactly 1000 kbps.
philipel277a8b52017-03-16 05:19:49 -07002113TEST_F(EndToEndTest, RembWithSendSideBwe) {
stefan32f81542016-01-20 07:13:58 -08002114 class BweObserver : public test::EndToEndTest {
2115 public:
2116 BweObserver()
2117 : EndToEndTest(kDefaultTimeoutMs),
2118 sender_call_(nullptr),
2119 clock_(Clock::GetRealTimeClock()),
2120 sender_ssrc_(0),
2121 remb_bitrate_bps_(1000000),
2122 receive_transport_(nullptr),
Tommi5dd5f5a2017-02-21 14:22:59 +01002123 stop_event_(false, false),
stefan32f81542016-01-20 07:13:58 -08002124 poller_thread_(&BitrateStatsPollingThread,
2125 this,
2126 "BitrateStatsPollingThread"),
Erik Språng737336d2016-07-29 12:59:36 +02002127 state_(kWaitForFirstRampUp),
2128 retransmission_rate_limiter_(clock_, 1000) {}
stefan32f81542016-01-20 07:13:58 -08002129
2130 ~BweObserver() {}
2131
nisseef8b61e2016-04-29 06:09:15 -07002132 test::PacketTransport* CreateReceiveTransport() override {
stefan32f81542016-01-20 07:13:58 -08002133 receive_transport_ = new test::PacketTransport(
minyue20c84cc2017-04-10 16:57:57 -07002134 nullptr, this, test::PacketTransport::kReceiver, payload_type_map_,
stefan32f81542016-01-20 07:13:58 -08002135 FakeNetworkPipe::Config());
2136 return receive_transport_;
2137 }
2138
2139 Call::Config GetSenderCallConfig() override {
philipel4fb651d2017-04-10 03:54:05 -07002140 Call::Config config(event_log_.get());
stefan32f81542016-01-20 07:13:58 -08002141 // Set a high start bitrate to reduce the test completion time.
2142 config.bitrate_config.start_bitrate_bps = remb_bitrate_bps_;
2143 return config;
2144 }
2145
2146 void ModifyVideoConfigs(
2147 VideoSendStream::Config* send_config,
2148 std::vector<VideoReceiveStream::Config>* receive_configs,
2149 VideoEncoderConfig* encoder_config) override {
2150 ASSERT_EQ(1u, send_config->rtp.ssrcs.size());
stefan32f81542016-01-20 07:13:58 -08002151 sender_ssrc_ = send_config->rtp.ssrcs[0];
2152
perkjfa10b552016-10-02 23:45:26 -07002153 encoder_config->max_bitrate_bps = 2000000;
stefan32f81542016-01-20 07:13:58 -08002154
2155 ASSERT_EQ(1u, receive_configs->size());
stefan32f81542016-01-20 07:13:58 -08002156 RtpRtcp::Configuration config;
2157 config.receiver_only = true;
2158 config.clock = clock_;
2159 config.outgoing_transport = receive_transport_;
Erik Språng737336d2016-07-29 12:59:36 +02002160 config.retransmission_rate_limiter = &retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08002161 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
2162 rtp_rtcp_->SetRemoteSSRC((*receive_configs)[0].rtp.remote_ssrc);
2163 rtp_rtcp_->SetSSRC((*receive_configs)[0].rtp.local_ssrc);
2164 rtp_rtcp_->SetREMBStatus(true);
stefan32f81542016-01-20 07:13:58 -08002165 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
2166 }
2167
2168 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2169 sender_call_ = sender_call;
2170 }
2171
tommi0f8b4032017-02-22 11:22:05 -08002172 static void BitrateStatsPollingThread(void* obj) {
2173 static_cast<BweObserver*>(obj)->PollStats();
stefan32f81542016-01-20 07:13:58 -08002174 }
2175
tommi0f8b4032017-02-22 11:22:05 -08002176 void PollStats() {
2177 do {
2178 if (sender_call_) {
2179 Call::Stats stats = sender_call_->GetStats();
2180 switch (state_) {
2181 case kWaitForFirstRampUp:
2182 if (stats.send_bandwidth_bps >= remb_bitrate_bps_) {
2183 state_ = kWaitForRemb;
2184 remb_bitrate_bps_ /= 2;
2185 rtp_rtcp_->SetREMBData(
2186 remb_bitrate_bps_,
2187 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
2188 rtp_rtcp_->SendRTCP(kRtcpRr);
2189 }
2190 break;
stefan32f81542016-01-20 07:13:58 -08002191
tommi0f8b4032017-02-22 11:22:05 -08002192 case kWaitForRemb:
2193 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
2194 state_ = kWaitForSecondRampUp;
2195 remb_bitrate_bps_ *= 2;
2196 rtp_rtcp_->SetREMBData(
2197 remb_bitrate_bps_,
2198 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
2199 rtp_rtcp_->SendRTCP(kRtcpRr);
2200 }
2201 break;
stefan32f81542016-01-20 07:13:58 -08002202
tommi0f8b4032017-02-22 11:22:05 -08002203 case kWaitForSecondRampUp:
2204 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
2205 observation_complete_.Set();
2206 }
2207 break;
2208 }
stefan32f81542016-01-20 07:13:58 -08002209 }
tommi0f8b4032017-02-22 11:22:05 -08002210 } while (!stop_event_.Wait(1000));
stefan32f81542016-01-20 07:13:58 -08002211 }
2212
2213 void PerformTest() override {
2214 poller_thread_.Start();
2215 EXPECT_TRUE(Wait())
2216 << "Timed out while waiting for bitrate to change according to REMB.";
Tommi5dd5f5a2017-02-21 14:22:59 +01002217 stop_event_.Set();
stefan32f81542016-01-20 07:13:58 -08002218 poller_thread_.Stop();
2219 }
2220
2221 private:
2222 enum TestState { kWaitForFirstRampUp, kWaitForRemb, kWaitForSecondRampUp };
2223
2224 Call* sender_call_;
2225 Clock* const clock_;
2226 uint32_t sender_ssrc_;
2227 int remb_bitrate_bps_;
kwiberg27f982b2016-03-01 11:52:33 -08002228 std::unique_ptr<RtpRtcp> rtp_rtcp_;
stefan32f81542016-01-20 07:13:58 -08002229 test::PacketTransport* receive_transport_;
Tommi5dd5f5a2017-02-21 14:22:59 +01002230 rtc::Event stop_event_;
stefan32f81542016-01-20 07:13:58 -08002231 rtc::PlatformThread poller_thread_;
2232 TestState state_;
Erik Språng737336d2016-07-29 12:59:36 +02002233 RateLimiter retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08002234 } test;
2235
2236 RunBaseTest(&test);
2237}
2238
philipel3184f8e2017-05-18 08:08:53 -07002239TEST_F(EndToEndTest, StopSendingKeyframeRequestsForInactiveStream) {
2240 class KeyframeRequestObserver : public test::EndToEndTest {
2241 public:
2242 KeyframeRequestObserver() : clock_(Clock::GetRealTimeClock()) {}
2243
2244 void OnVideoStreamsCreated(
2245 VideoSendStream* send_stream,
2246 const std::vector<VideoReceiveStream*>& receive_streams) override {
2247 RTC_DCHECK_EQ(1, receive_streams.size());
2248 send_stream_ = send_stream;
2249 receive_stream_ = receive_streams[0];
2250 }
2251
2252 void PerformTest() override {
2253 bool frame_decoded = false;
2254 int64_t start_time = clock_->TimeInMilliseconds();
2255 while (clock_->TimeInMilliseconds() - start_time <= 5000) {
2256 if (receive_stream_->GetStats().frames_decoded > 0) {
2257 frame_decoded = true;
2258 break;
2259 }
2260 SleepMs(100);
2261 }
2262 ASSERT_TRUE(frame_decoded);
2263 send_stream_->Stop();
2264 SleepMs(10000);
2265 ASSERT_EQ(
2266 1U, receive_stream_->GetStats().rtcp_packet_type_counts.pli_packets);
2267 }
2268
2269 private:
2270 Clock* clock_;
2271 VideoSendStream* send_stream_;
2272 VideoReceiveStream* receive_stream_;
2273 } test;
2274
2275 RunBaseTest(&test);
2276}
2277
philipele828c962017-03-21 03:24:27 -07002278class ProbingTest : public test::EndToEndTest {
2279 public:
2280 explicit ProbingTest(int start_bitrate_bps)
2281 : clock_(Clock::GetRealTimeClock()),
2282 start_bitrate_bps_(start_bitrate_bps),
2283 state_(0),
2284 sender_call_(nullptr) {}
2285
2286 ~ProbingTest() {}
2287
2288 Call::Config GetSenderCallConfig() override {
philipel4fb651d2017-04-10 03:54:05 -07002289 Call::Config config(event_log_.get());
philipele828c962017-03-21 03:24:27 -07002290 config.bitrate_config.start_bitrate_bps = start_bitrate_bps_;
2291 return config;
2292 }
2293
2294 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2295 sender_call_ = sender_call;
2296 }
2297
2298 protected:
2299 Clock* const clock_;
2300 const int start_bitrate_bps_;
2301 int state_;
2302 Call* sender_call_;
2303};
2304
aleloi7057b6b2017-03-29 02:07:33 -07002305TEST_F(EndToEndTest, MAYBE_InitialProbing) {
philipele828c962017-03-21 03:24:27 -07002306 class InitialProbingTest : public ProbingTest {
2307 public:
philipel8a256522017-03-30 05:06:22 -07002308 explicit InitialProbingTest(bool* success)
2309 : ProbingTest(300000), success_(success) {}
philipele828c962017-03-21 03:24:27 -07002310
2311 void PerformTest() override {
2312 int64_t start_time_ms = clock_->TimeInMilliseconds();
2313 do {
philipel8a256522017-03-30 05:06:22 -07002314 if (clock_->TimeInMilliseconds() - start_time_ms > kTimeoutMs)
philipele828c962017-03-21 03:24:27 -07002315 break;
philipele828c962017-03-21 03:24:27 -07002316
2317 Call::Stats stats = sender_call_->GetStats();
2318 // Initial probing is done with a x3 and x6 multiplier of the start
2319 // bitrate, so a x4 multiplier is a high enough threshold.
philipel8a256522017-03-30 05:06:22 -07002320 if (stats.send_bandwidth_bps > 4 * 300000) {
2321 *success_ = true;
philipele828c962017-03-21 03:24:27 -07002322 break;
philipel8a256522017-03-30 05:06:22 -07002323 }
philipele828c962017-03-21 03:24:27 -07002324 } while (!observation_complete_.Wait(20));
2325 }
2326
2327 private:
2328 const int kTimeoutMs = 1000;
philipel8a256522017-03-30 05:06:22 -07002329 bool* const success_;
2330 };
philipele828c962017-03-21 03:24:27 -07002331
philipel8a256522017-03-30 05:06:22 -07002332 bool success;
2333 const int kMaxAttempts = 3;
2334 for (int i = 0; i < kMaxAttempts; ++i) {
2335 InitialProbingTest test(&success);
2336 RunBaseTest(&test);
2337 if (success)
2338 return;
2339 }
2340 RTC_DCHECK(success) << "Failed to perform mid initial probing ("
2341 << kMaxAttempts << " attempts).";
philipele828c962017-03-21 03:24:27 -07002342}
2343
aleloi18703f92017-03-30 04:24:08 -07002344// Fails on Linux MSan: bugs.webrtc.org/7428
2345#if defined(MEMORY_SANITIZER)
2346TEST_F(EndToEndTest, DISABLED_TriggerMidCallProbing) {
oprypin45197522017-06-22 01:47:20 -07002347// Fails on iOS bots: bugs.webrtc.org/7851
2348#elif defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR
2349TEST_F(EndToEndTest, DISABLED_TriggerMidCallProbing) {
aleloi18703f92017-03-30 04:24:08 -07002350#else
philipele828c962017-03-21 03:24:27 -07002351TEST_F(EndToEndTest, TriggerMidCallProbing) {
aleloi18703f92017-03-30 04:24:08 -07002352#endif
2353
philipele828c962017-03-21 03:24:27 -07002354 class TriggerMidCallProbingTest : public ProbingTest {
2355 public:
philipel8a256522017-03-30 05:06:22 -07002356 explicit TriggerMidCallProbingTest(bool* success)
2357 : ProbingTest(300000), success_(success) {}
philipele828c962017-03-21 03:24:27 -07002358
2359 void PerformTest() override {
philipel8a256522017-03-30 05:06:22 -07002360 *success_ = false;
philipele828c962017-03-21 03:24:27 -07002361 int64_t start_time_ms = clock_->TimeInMilliseconds();
2362 do {
philipel8a256522017-03-30 05:06:22 -07002363 if (clock_->TimeInMilliseconds() - start_time_ms > kTimeoutMs)
philipele828c962017-03-21 03:24:27 -07002364 break;
philipele828c962017-03-21 03:24:27 -07002365
2366 Call::Stats stats = sender_call_->GetStats();
2367
2368 switch (state_) {
2369 case 0:
2370 if (stats.send_bandwidth_bps > 5 * 300000) {
2371 Call::Config::BitrateConfig bitrate_config;
2372 bitrate_config.max_bitrate_bps = 100000;
2373 sender_call_->SetBitrateConfig(bitrate_config);
2374 ++state_;
2375 }
2376 break;
2377 case 1:
2378 if (stats.send_bandwidth_bps < 110000) {
2379 Call::Config::BitrateConfig bitrate_config;
2380 bitrate_config.max_bitrate_bps = 2500000;
2381 sender_call_->SetBitrateConfig(bitrate_config);
2382 ++state_;
2383 }
2384 break;
2385 case 2:
2386 // During high cpu load the pacer will not be able to pace packets
2387 // at the correct speed, but if we go from 110 to 1250 kbps
2388 // in 5 seconds then it is due to probing.
philipel8a256522017-03-30 05:06:22 -07002389 if (stats.send_bandwidth_bps > 1250000) {
2390 *success_ = true;
philipele828c962017-03-21 03:24:27 -07002391 observation_complete_.Set();
philipel8a256522017-03-30 05:06:22 -07002392 }
philipele828c962017-03-21 03:24:27 -07002393 break;
2394 }
2395 } while (!observation_complete_.Wait(20));
2396 }
2397
2398 private:
2399 const int kTimeoutMs = 5000;
philipel8a256522017-03-30 05:06:22 -07002400 bool* const success_;
2401 };
philipele828c962017-03-21 03:24:27 -07002402
philipel8a256522017-03-30 05:06:22 -07002403 bool success;
2404 const int kMaxAttempts = 3;
2405 for (int i = 0; i < kMaxAttempts; ++i) {
2406 TriggerMidCallProbingTest test(&success);
2407 RunBaseTest(&test);
2408 if (success)
2409 return;
2410 }
2411 RTC_DCHECK(success) << "Failed to perform mid call probing (" << kMaxAttempts
2412 << " attempts).";
philipele828c962017-03-21 03:24:27 -07002413}
2414
philipel277a8b52017-03-16 05:19:49 -07002415TEST_F(EndToEndTest, VerifyNackStats) {
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002416 static const int kPacketNumberToDrop = 200;
2417 class NackObserver : public test::EndToEndTest {
2418 public:
2419 NackObserver()
2420 : EndToEndTest(kLongTimeoutMs),
2421 sent_rtp_packets_(0),
2422 dropped_rtp_packet_(0),
2423 dropped_rtp_packet_requested_(false),
2424 send_stream_(nullptr),
2425 start_runtime_ms_(-1) {}
2426
2427 private:
2428 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002429 rtc::CritScope lock(&crit_);
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002430 if (++sent_rtp_packets_ == kPacketNumberToDrop) {
kwiberg27f982b2016-03-01 11:52:33 -08002431 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002432 RTPHeader header;
2433 EXPECT_TRUE(parser->Parse(packet, length, &header));
2434 dropped_rtp_packet_ = header.sequenceNumber;
2435 return DROP_PACKET;
2436 }
2437 VerifyStats();
2438 return SEND_PACKET;
2439 }
2440
2441 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002442 rtc::CritScope lock(&crit_);
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002443 test::RtcpPacketParser rtcp_parser;
2444 rtcp_parser.Parse(packet, length);
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02002445 const std::vector<uint16_t>& nacks = rtcp_parser.nack()->packet_ids();
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002446 if (!nacks.empty() && std::find(
2447 nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) {
2448 dropped_rtp_packet_requested_ = true;
2449 }
2450 return SEND_PACKET;
2451 }
2452
stefan608213e2015-11-01 14:56:10 -08002453 void VerifyStats() EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002454 if (!dropped_rtp_packet_requested_)
2455 return;
2456 int send_stream_nack_packets = 0;
2457 int receive_stream_nack_packets = 0;
2458 VideoSendStream::Stats stats = send_stream_->GetStats();
2459 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
2460 stats.substreams.begin(); it != stats.substreams.end(); ++it) {
2461 const VideoSendStream::StreamStats& stream_stats = it->second;
2462 send_stream_nack_packets +=
2463 stream_stats.rtcp_packet_type_counts.nack_packets;
2464 }
2465 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2466 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2467 receive_stream_nack_packets +=
2468 stats.rtcp_packet_type_counts.nack_packets;
2469 }
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002470 if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) {
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002471 // NACK packet sent on receive stream and received on sent stream.
2472 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002473 observation_complete_.Set();
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002474 }
2475 }
2476
2477 bool MinMetricRunTimePassed() {
2478 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2479 if (start_runtime_ms_ == -1) {
2480 start_runtime_ms_ = now;
2481 return false;
2482 }
2483 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2484 return elapsed_sec > metrics::kMinRunTimeInSeconds;
2485 }
2486
stefanff483612015-12-21 03:14:00 -08002487 void ModifyVideoConfigs(
2488 VideoSendStream::Config* send_config,
2489 std::vector<VideoReceiveStream::Config>* receive_configs,
2490 VideoEncoderConfig* encoder_config) override {
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002491 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2492 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sakal55d932b2016-09-30 06:19:08 -07002493 (*receive_configs)[0].renderer = &fake_renderer_;
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002494 }
2495
stefanff483612015-12-21 03:14:00 -08002496 void OnVideoStreamsCreated(
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002497 VideoSendStream* send_stream,
2498 const std::vector<VideoReceiveStream*>& receive_streams) override {
2499 send_stream_ = send_stream;
2500 receive_streams_ = receive_streams;
2501 }
2502
2503 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002504 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002505 }
2506
sakal55d932b2016-09-30 06:19:08 -07002507 test::FakeVideoRenderer fake_renderer_;
stefan608213e2015-11-01 14:56:10 -08002508 rtc::CriticalSection crit_;
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002509 uint64_t sent_rtp_packets_;
stefan608213e2015-11-01 14:56:10 -08002510 uint16_t dropped_rtp_packet_ GUARDED_BY(&crit_);
2511 bool dropped_rtp_packet_requested_ GUARDED_BY(&crit_);
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002512 std::vector<VideoReceiveStream*> receive_streams_;
2513 VideoSendStream* send_stream_;
2514 int64_t start_runtime_ms_;
2515 } test;
2516
asapersson01d70a32016-05-20 06:29:46 -07002517 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002518 RunBaseTest(&test);
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002519
asapersson01d70a32016-05-20 06:29:46 -07002520 EXPECT_EQ(
2521 1, metrics::NumSamples("WebRTC.Video.UniqueNackRequestsSentInPercent"));
2522 EXPECT_EQ(1, metrics::NumSamples(
2523 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
2524 EXPECT_GT(metrics::MinSample("WebRTC.Video.NackPacketsSentPerMinute"), 0);
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002525}
2526
sprangb4a1ae52015-12-03 08:10:08 -08002527void EndToEndTest::VerifyHistogramStats(bool use_rtx,
2528 bool use_red,
2529 bool screenshare) {
tommi2e82f382016-06-21 00:26:43 -07002530 class StatsObserver : public test::EndToEndTest,
2531 public rtc::VideoSinkInterface<VideoFrame> {
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002532 public:
sprangb4a1ae52015-12-03 08:10:08 -08002533 StatsObserver(bool use_rtx, bool use_red, bool screenshare)
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002534 : EndToEndTest(kLongTimeoutMs),
2535 use_rtx_(use_rtx),
2536 use_red_(use_red),
sprangb4a1ae52015-12-03 08:10:08 -08002537 screenshare_(screenshare),
Peter Boström39593972016-02-15 11:27:15 +01002538 // This test uses NACK, so to send FEC we can't use a fake encoder.
magjed509e4fe2016-11-18 01:34:11 -08002539 vp8_encoder_(use_red ? VP8Encoder::Create() : nullptr),
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002540 sender_call_(nullptr),
2541 receiver_call_(nullptr),
asapersson1394c7b2016-10-18 11:50:50 -07002542 start_runtime_ms_(-1),
2543 num_frames_received_(0) {}
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002544
2545 private:
asapersson1394c7b2016-10-18 11:50:50 -07002546 void OnFrame(const VideoFrame& video_frame) override {
2547 // The RTT is needed to estimate |ntp_time_ms| which is used by
2548 // end-to-end delay stats. Therefore, start counting received frames once
2549 // |ntp_time_ms| is valid.
2550 if (video_frame.ntp_time_ms() > 0 &&
2551 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() >=
2552 video_frame.ntp_time_ms()) {
2553 rtc::CritScope lock(&crit_);
2554 ++num_frames_received_;
2555 }
2556 }
tommi2e82f382016-06-21 00:26:43 -07002557
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002558 Action OnSendRtp(const uint8_t* packet, size_t length) override {
asapersson1394c7b2016-10-18 11:50:50 -07002559 if (MinMetricRunTimePassed() && MinNumberOfFramesReceived())
Peter Boström5811a392015-12-10 13:02:50 +01002560 observation_complete_.Set();
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002561
stefanf116bd02015-10-27 08:29:42 -07002562 return SEND_PACKET;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002563 }
2564
2565 bool MinMetricRunTimePassed() {
2566 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2567 if (start_runtime_ms_ == -1) {
2568 start_runtime_ms_ = now;
2569 return false;
2570 }
2571 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2572 return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
2573 }
2574
asapersson1394c7b2016-10-18 11:50:50 -07002575 bool MinNumberOfFramesReceived() const {
2576 const int kMinRequiredHistogramSamples = 200;
2577 rtc::CritScope lock(&crit_);
2578 return num_frames_received_ > kMinRequiredHistogramSamples;
2579 }
2580
stefanff483612015-12-21 03:14:00 -08002581 void ModifyVideoConfigs(
2582 VideoSendStream::Config* send_config,
2583 std::vector<VideoReceiveStream::Config>* receive_configs,
2584 VideoEncoderConfig* encoder_config) override {
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002585 // NACK
2586 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2587 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
tommi2e82f382016-06-21 00:26:43 -07002588 (*receive_configs)[0].renderer = this;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002589 // FEC
2590 if (use_red_) {
brandtrb5f2c3f2016-10-04 23:28:39 -07002591 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
2592 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
Peter Boström39593972016-02-15 11:27:15 +01002593 send_config->encoder_settings.encoder = vp8_encoder_.get();
2594 send_config->encoder_settings.payload_name = "VP8";
2595 (*receive_configs)[0].decoders[0].payload_name = "VP8";
brandtrb5f2c3f2016-10-04 23:28:39 -07002596 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
2597 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type =
2598 kUlpfecPayloadType;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002599 }
2600 // RTX
2601 if (use_rtx_) {
2602 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
2603 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
brandtr14742122017-01-27 04:53:07 -08002604 (*receive_configs)[0].rtp.rtx_ssrc = kSendRtxSsrcs[0];
2605 (*receive_configs)[0].rtp.rtx_payload_types[kFakeVideoSendPayloadType] =
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002606 kSendRtxPayloadType;
2607 }
asapersson1490f7a2016-09-23 02:09:46 -07002608 // RTT needed for RemoteNtpTimeEstimator for the receive stream.
2609 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = true;
sprangb4a1ae52015-12-03 08:10:08 -08002610 encoder_config->content_type =
2611 screenshare_ ? VideoEncoderConfig::ContentType::kScreen
2612 : VideoEncoderConfig::ContentType::kRealtimeVideo;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002613 }
2614
2615 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2616 sender_call_ = sender_call;
2617 receiver_call_ = receiver_call;
2618 }
2619
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002620 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002621 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002622 }
2623
asapersson1394c7b2016-10-18 11:50:50 -07002624 rtc::CriticalSection crit_;
sprangb4a1ae52015-12-03 08:10:08 -08002625 const bool use_rtx_;
2626 const bool use_red_;
2627 const bool screenshare_;
kwiberg27f982b2016-03-01 11:52:33 -08002628 const std::unique_ptr<VideoEncoder> vp8_encoder_;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002629 Call* sender_call_;
2630 Call* receiver_call_;
2631 int64_t start_runtime_ms_;
asapersson1394c7b2016-10-18 11:50:50 -07002632 int num_frames_received_ GUARDED_BY(&crit_);
sprangb4a1ae52015-12-03 08:10:08 -08002633 } test(use_rtx, use_red, screenshare);
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002634
asapersson01d70a32016-05-20 06:29:46 -07002635 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002636 RunBaseTest(&test);
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002637
stefan91d92602015-11-11 10:13:02 -08002638 // Delete the call for Call stats to be reported.
stefan18adf0a2015-11-17 06:24:56 -08002639 sender_call_.reset();
stefan91d92602015-11-11 10:13:02 -08002640 receiver_call_.reset();
2641
sprangb4a1ae52015-12-03 08:10:08 -08002642 std::string video_prefix =
2643 screenshare ? "WebRTC.Video.Screenshare." : "WebRTC.Video.";
2644
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002645 // Verify that stats have been updated once.
asapersson4374a092016-07-27 00:39:09 -07002646 EXPECT_EQ(2, metrics::NumSamples("WebRTC.Call.LifetimeInSeconds"));
saza0d7f04d2017-07-04 04:05:06 -07002647 EXPECT_EQ(1, metrics::NumSamples(
2648 "WebRTC.Call.TimeReceivingVideoRtpPacketsInSeconds"));
asapersson01d70a32016-05-20 06:29:46 -07002649 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
2650 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.RtcpBitrateReceivedInBps"));
2651 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.BitrateReceivedInKbps"));
2652 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.EstimatedSendBitrateInKbps"));
2653 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.PacerBitrateInKbps"));
2654
asapersson4374a092016-07-27 00:39:09 -07002655 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
2656 EXPECT_EQ(1,
2657 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
2658
asapersson01d70a32016-05-20 06:29:46 -07002659 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
stefan91d92602015-11-11 10:13:02 -08002660 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002661 metrics::NumSamples(video_prefix + "NackPacketsReceivedPerMinute"));
2662 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
asaperssond89920b2015-07-22 06:52:00 -07002663 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002664 metrics::NumSamples(video_prefix + "FirPacketsReceivedPerMinute"));
2665 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
sprangb4a1ae52015-12-03 08:10:08 -08002666 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002667 metrics::NumSamples(video_prefix + "PliPacketsReceivedPerMinute"));
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002668
asapersson01d70a32016-05-20 06:29:46 -07002669 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "KeyFramesSentInPermille"));
2670 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
2671
2672 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentPacketsLostInPercent"));
2673 EXPECT_EQ(1,
2674 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
2675
2676 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputWidthInPixels"));
2677 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputHeightInPixels"));
2678 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentWidthInPixels"));
2679 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentHeightInPixels"));
2680 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
2681 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
2682
perkjfa10b552016-10-02 23:45:26 -07002683 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputWidthInPixels",
2684 kDefaultWidth));
2685 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputHeightInPixels",
2686 kDefaultHeight));
2687 EXPECT_EQ(
2688 1, metrics::NumEvents(video_prefix + "SentWidthInPixels", kDefaultWidth));
2689 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "SentHeightInPixels",
2690 kDefaultHeight));
2691 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedWidthInPixels",
2692 kDefaultWidth));
2693 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedHeightInPixels",
2694 kDefaultHeight));
asapersson01d70a32016-05-20 06:29:46 -07002695
2696 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputFramesPerSecond"));
2697 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentFramesPerSecond"));
2698 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
2699 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
2700
2701 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
2702 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
2703 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
2704 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
2705
ilnik00d802b2017-04-11 10:34:31 -07002706 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EndToEndDelayInMs"));
2707 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EndToEndDelayMaxInMs"));
ilnik4257ab22017-07-03 01:15:58 -07002708 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InterframeDelayInMs"));
2709 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InterframeDelayMaxInMs"));
2710
asapersson01d70a32016-05-20 06:29:46 -07002711 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
2712
2713 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EncodeTimeInMs"));
2714 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
2715
asapersson66d4b372016-12-19 06:50:53 -08002716 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "NumberOfPauseEvents"));
2717 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PausedTimeInPercent"));
2718
asapersson01d70a32016-05-20 06:29:46 -07002719 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "BitrateSentInKbps"));
2720 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateReceivedInKbps"));
2721 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "MediaBitrateSentInKbps"));
2722 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateReceivedInKbps"));
2723 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PaddingBitrateSentInKbps"));
2724 EXPECT_EQ(1,
2725 metrics::NumSamples("WebRTC.Video.PaddingBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002726 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002727 1, metrics::NumSamples(video_prefix + "RetransmittedBitrateSentInKbps"));
2728 EXPECT_EQ(1, metrics::NumSamples(
2729 "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002730
asapersson01d70a32016-05-20 06:29:46 -07002731 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendDelayInMs"));
2732 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayInMs"));
2733 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayMaxInMs"));
asapersson6f14be82015-11-16 00:40:49 -08002734
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002735 int num_rtx_samples = use_rtx ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002736 EXPECT_EQ(num_rtx_samples,
2737 metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2738 EXPECT_EQ(num_rtx_samples,
2739 metrics::NumSamples("WebRTC.Video.RtxBitrateReceivedInKbps"));
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002740
2741 int num_red_samples = use_red ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002742 EXPECT_EQ(num_red_samples,
2743 metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2744 EXPECT_EQ(num_red_samples,
2745 metrics::NumSamples("WebRTC.Video.FecBitrateReceivedInKbps"));
2746 EXPECT_EQ(num_red_samples,
2747 metrics::NumSamples("WebRTC.Video.ReceivedFecPacketsInPercent"));
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002748}
2749
Lu Liufb9e7512017-04-13 14:09:56 -07002750#if defined(WEBRTC_WIN)
2751// Disabled due to flakiness on Windows (bugs.webrtc.org/7483).
2752#define MAYBE_ContentTypeSwitches DISABLED_ContentTypeSwitches
2753#else
2754#define MAYBE_ContentTypeSwitches ContentTypeSwitches
2755#endif
2756TEST_F(EndToEndTest, MAYBE_ContentTypeSwitches) {
ilnik00d802b2017-04-11 10:34:31 -07002757 class StatsObserver : public test::BaseTest,
2758 public rtc::VideoSinkInterface<VideoFrame> {
2759 public:
2760 StatsObserver() : BaseTest(kLongTimeoutMs), num_frames_received_(0) {}
2761
2762 bool ShouldCreateReceivers() const override { return true; }
2763
2764 void OnFrame(const VideoFrame& video_frame) override {
2765 // The RTT is needed to estimate |ntp_time_ms| which is used by
2766 // end-to-end delay stats. Therefore, start counting received frames once
2767 // |ntp_time_ms| is valid.
2768 if (video_frame.ntp_time_ms() > 0 &&
2769 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() >=
2770 video_frame.ntp_time_ms()) {
2771 rtc::CritScope lock(&crit_);
2772 ++num_frames_received_;
2773 }
2774 }
2775
2776 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2777 if (MinNumberOfFramesReceived())
2778 observation_complete_.Set();
2779 return SEND_PACKET;
2780 }
2781
2782 bool MinNumberOfFramesReceived() const {
ilnikf6f808f2017-04-18 09:17:53 -07002783 // Have some room for frames with wrong content type during switch.
2784 const int kMinRequiredHistogramSamples = 200+50;
ilnik00d802b2017-04-11 10:34:31 -07002785 rtc::CritScope lock(&crit_);
2786 return num_frames_received_ > kMinRequiredHistogramSamples;
2787 }
2788
2789 // May be called several times.
2790 void PerformTest() override {
2791 EXPECT_TRUE(Wait()) << "Timed out waiting for enough packets.";
2792 // Reset frame counter so next PerformTest() call will do something.
2793 {
2794 rtc::CritScope lock(&crit_);
2795 num_frames_received_ = 0;
2796 }
2797 }
2798
2799 rtc::CriticalSection crit_;
2800 int num_frames_received_ GUARDED_BY(&crit_);
2801 } test;
2802
ilnikcf705c52017-06-08 06:18:53 -07002803 test::ScopedFieldTrials override_field_trials(
2804 "WebRTC-VideoContentTypeExtension/Enabled/");
ilnik00d802b2017-04-11 10:34:31 -07002805 metrics::Reset();
2806
2807 Call::Config send_config(test.GetSenderCallConfig());
2808 CreateSenderCall(send_config);
2809 Call::Config recv_config(test.GetReceiverCallConfig());
2810 CreateReceiverCall(recv_config);
2811 receive_transport_.reset(test.CreateReceiveTransport());
2812 send_transport_.reset(test.CreateSendTransport(sender_call_.get()));
2813 send_transport_->SetReceiver(receiver_call_->Receiver());
2814 receive_transport_->SetReceiver(sender_call_->Receiver());
2815 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
2816 CreateSendConfig(1, 0, 0, send_transport_.get());
2817 CreateMatchingReceiveConfigs(receive_transport_.get());
2818
2819 // Modify send and receive configs.
2820 video_send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2821 video_receive_configs_[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2822 video_receive_configs_[0].renderer = &test;
2823 // RTT needed for RemoteNtpTimeEstimator for the receive stream.
2824 video_receive_configs_[0].rtp.rtcp_xr.receiver_reference_time_report = true;
2825 // Start with realtime video.
2826 video_encoder_config_.content_type =
2827 VideoEncoderConfig::ContentType::kRealtimeVideo;
2828 // Second encoder config for the second part of the test uses screenshare
2829 VideoEncoderConfig encoder_config_with_screenshare_ =
2830 video_encoder_config_.Copy();
2831 encoder_config_with_screenshare_.content_type =
2832 VideoEncoderConfig::ContentType::kScreen;
2833
2834 CreateVideoStreams();
2835 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
2836 kDefaultHeight);
2837 Start();
2838
2839 test.PerformTest();
2840
2841 // Replace old send stream.
2842 sender_call_->DestroyVideoSendStream(video_send_stream_);
2843 video_send_stream_ = sender_call_->CreateVideoSendStream(
2844 video_send_config_.Copy(), encoder_config_with_screenshare_.Copy());
2845 video_send_stream_->SetSource(
2846 frame_generator_capturer_.get(),
2847 VideoSendStream::DegradationPreference::kBalanced);
2848 video_send_stream_->Start();
2849
2850 // Continue to run test but now with screenshare.
2851 test.PerformTest();
2852
2853 send_transport_->StopSending();
2854 receive_transport_->StopSending();
2855 Stop();
2856 DestroyStreams();
2857 DestroyCalls();
2858 // Delete the call for Call stats to be reported.
2859 sender_call_.reset();
2860 receiver_call_.reset();
2861
2862 // Verify that stats have been updated for both screenshare and video.
2863 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.EndToEndDelayInMs"));
2864 EXPECT_EQ(1,
2865 metrics::NumSamples("WebRTC.Video.Screenshare.EndToEndDelayInMs"));
2866 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.EndToEndDelayMaxInMs"));
2867 EXPECT_EQ(
2868 1, metrics::NumSamples("WebRTC.Video.Screenshare.EndToEndDelayMaxInMs"));
ilnik4257ab22017-07-03 01:15:58 -07002869 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
2870 EXPECT_EQ(1,
2871 metrics::NumSamples(
2872 "WebRTC.Video.Screenshare.InterframeDelayInMs"));
2873 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
2874 EXPECT_EQ(1,
2875 metrics::NumSamples(
2876 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
ilnik00d802b2017-04-11 10:34:31 -07002877}
2878
philipel277a8b52017-03-16 05:19:49 -07002879TEST_F(EndToEndTest, VerifyHistogramStatsWithRtx) {
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002880 const bool kEnabledRtx = true;
2881 const bool kEnabledRed = false;
sprangb4a1ae52015-12-03 08:10:08 -08002882 const bool kScreenshare = false;
2883 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002884}
2885
philipel277a8b52017-03-16 05:19:49 -07002886TEST_F(EndToEndTest, VerifyHistogramStatsWithRed) {
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002887 const bool kEnabledRtx = false;
2888 const bool kEnabledRed = true;
sprangb4a1ae52015-12-03 08:10:08 -08002889 const bool kScreenshare = false;
2890 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
2891}
2892
philipel277a8b52017-03-16 05:19:49 -07002893TEST_F(EndToEndTest, VerifyHistogramStatsWithScreenshare) {
sprangb4a1ae52015-12-03 08:10:08 -08002894 const bool kEnabledRtx = false;
2895 const bool kEnabledRed = false;
2896 const bool kScreenshare = true;
ilnikcf705c52017-06-08 06:18:53 -07002897 test::ScopedFieldTrials override_field_trials(
2898 "WebRTC-VideoContentTypeExtension/Enabled/");
sprangb4a1ae52015-12-03 08:10:08 -08002899 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002900}
2901
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002902void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
2903 bool send_single_ssrc_first) {
2904 class SendsSetSsrcs : public test::EndToEndTest {
2905 public:
2906 SendsSetSsrcs(const uint32_t* ssrcs,
2907 size_t num_ssrcs,
2908 bool send_single_ssrc_first)
2909 : EndToEndTest(kDefaultTimeoutMs),
2910 num_ssrcs_(num_ssrcs),
2911 send_single_ssrc_first_(send_single_ssrc_first),
2912 ssrcs_to_observe_(num_ssrcs),
sprang867fb522015-08-03 04:38:41 -07002913 expect_single_ssrc_(send_single_ssrc_first),
2914 send_stream_(nullptr) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002915 for (size_t i = 0; i < num_ssrcs; ++i)
2916 valid_ssrcs_[ssrcs[i]] = true;
2917 }
2918
2919 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002920 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002921 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002922 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002923
2924 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
2925 << "Received unknown SSRC: " << header.ssrc;
2926
2927 if (!valid_ssrcs_[header.ssrc])
Peter Boström5811a392015-12-10 13:02:50 +01002928 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002929
2930 if (!is_observed_[header.ssrc]) {
2931 is_observed_[header.ssrc] = true;
2932 --ssrcs_to_observe_;
2933 if (expect_single_ssrc_) {
2934 expect_single_ssrc_ = false;
Peter Boström5811a392015-12-10 13:02:50 +01002935 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002936 }
2937 }
2938
2939 if (ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002940 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002941
2942 return SEND_PACKET;
2943 }
2944
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002945 size_t GetNumVideoStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002946
perkjfa10b552016-10-02 23:45:26 -07002947 // This test use other VideoStream settings than the the default settings
2948 // implemented in DefaultVideoStreamFactory. Therefore this test implement
2949 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
2950 // in ModifyVideoConfigs.
2951 class VideoStreamFactory
2952 : public VideoEncoderConfig::VideoStreamFactoryInterface {
2953 public:
2954 VideoStreamFactory() {}
2955
2956 private:
2957 std::vector<VideoStream> CreateEncoderStreams(
2958 int width,
2959 int height,
2960 const VideoEncoderConfig& encoder_config) override {
2961 std::vector<VideoStream> streams =
2962 test::CreateVideoStreams(width, height, encoder_config);
2963 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
2964 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
2965 streams[i].min_bitrate_bps = 10000;
2966 streams[i].target_bitrate_bps = 15000;
2967 streams[i].max_bitrate_bps = 20000;
2968 }
2969 return streams;
2970 }
2971 };
2972
stefanff483612015-12-21 03:14:00 -08002973 void ModifyVideoConfigs(
2974 VideoSendStream::Config* send_config,
2975 std::vector<VideoReceiveStream::Config>* receive_configs,
2976 VideoEncoderConfig* encoder_config) override {
perkjfa10b552016-10-02 23:45:26 -07002977 encoder_config->video_stream_factory =
2978 new rtc::RefCountedObject<VideoStreamFactory>();
perkj26091b12016-09-01 01:17:40 -07002979 video_encoder_config_all_streams_ = encoder_config->Copy();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002980 if (send_single_ssrc_first_)
perkjfa10b552016-10-02 23:45:26 -07002981 encoder_config->number_of_streams = 1;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002982 }
2983
stefanff483612015-12-21 03:14:00 -08002984 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002985 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002986 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002987 send_stream_ = send_stream;
2988 }
2989
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002990 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002991 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2992 << (send_single_ssrc_first_ ? "first SSRC."
2993 : "SSRCs.");
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002994
2995 if (send_single_ssrc_first_) {
2996 // Set full simulcast and continue with the rest of the SSRCs.
stefanff483612015-12-21 03:14:00 -08002997 send_stream_->ReconfigureVideoEncoder(
perkj26091b12016-09-01 01:17:40 -07002998 std::move(video_encoder_config_all_streams_));
Peter Boström5811a392015-12-10 13:02:50 +01002999 EXPECT_TRUE(Wait()) << "Timed out while waiting on additional SSRCs.";
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003000 }
3001 }
3002
3003 private:
3004 std::map<uint32_t, bool> valid_ssrcs_;
3005 std::map<uint32_t, bool> is_observed_;
3006
3007 const size_t num_ssrcs_;
3008 const bool send_single_ssrc_first_;
3009
3010 size_t ssrcs_to_observe_;
3011 bool expect_single_ssrc_;
3012
3013 VideoSendStream* send_stream_;
stefanff483612015-12-21 03:14:00 -08003014 VideoEncoderConfig video_encoder_config_all_streams_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003015 } test(kVideoSendSsrcs, num_ssrcs, send_single_ssrc_first);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003016
stefane74eef12016-01-08 06:47:13 -08003017 RunBaseTest(&test);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003018}
3019
philipel277a8b52017-03-16 05:19:49 -07003020TEST_F(EndToEndTest, ReportsSetEncoderRates) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003021 class EncoderRateStatsTest : public test::EndToEndTest,
3022 public test::FakeEncoder {
3023 public:
3024 EncoderRateStatsTest()
3025 : EndToEndTest(kDefaultTimeoutMs),
sprang867fb522015-08-03 04:38:41 -07003026 FakeEncoder(Clock::GetRealTimeClock()),
3027 send_stream_(nullptr),
3028 bitrate_kbps_(0) {}
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003029
stefanff483612015-12-21 03:14:00 -08003030 void OnVideoStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003031 VideoSendStream* send_stream,
3032 const std::vector<VideoReceiveStream*>& receive_streams) override {
3033 send_stream_ = send_stream;
3034 }
3035
stefanff483612015-12-21 03:14:00 -08003036 void ModifyVideoConfigs(
3037 VideoSendStream::Config* send_config,
3038 std::vector<VideoReceiveStream::Config>* receive_configs,
3039 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003040 send_config->encoder_settings.encoder = this;
kwibergaf476c72016-11-28 15:21:39 -08003041 RTC_DCHECK_EQ(1, encoder_config->number_of_streams);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003042 }
3043
Erik Språng08127a92016-11-16 16:41:30 +01003044 int32_t SetRateAllocation(const BitrateAllocation& rate_allocation,
3045 uint32_t framerate) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003046 // Make sure not to trigger on any default zero bitrates.
Erik Språng08127a92016-11-16 16:41:30 +01003047 if (rate_allocation.get_sum_bps() == 0)
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003048 return 0;
Peter Boströmf2f82832015-05-01 13:00:41 +02003049 rtc::CritScope lock(&crit_);
Erik Språng08127a92016-11-16 16:41:30 +01003050 bitrate_kbps_ = rate_allocation.get_sum_kbps();
Peter Boström5811a392015-12-10 13:02:50 +01003051 observation_complete_.Set();
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003052 return 0;
3053 }
3054
3055 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003056 ASSERT_TRUE(Wait())
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003057 << "Timed out while waiting for encoder SetRates() call.";
perkjf5b2e512016-07-05 08:34:04 -07003058 WaitForEncoderTargetBitrateMatchStats();
3059 send_stream_->Stop();
3060 WaitForStatsReportZeroTargetBitrate();
3061 send_stream_->Start();
3062 WaitForEncoderTargetBitrateMatchStats();
3063 }
3064
3065 void WaitForEncoderTargetBitrateMatchStats() {
Peter Boström5811a392015-12-10 13:02:50 +01003066 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003067 VideoSendStream::Stats stats = send_stream_->GetStats();
3068 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003069 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003070 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
3071 static_cast<int>(bitrate_kbps_)) {
3072 return;
3073 }
3074 }
3075 SleepMs(1);
3076 }
3077 FAIL()
3078 << "Timed out waiting for stats reporting the currently set bitrate.";
3079 }
3080
perkjf5b2e512016-07-05 08:34:04 -07003081 void WaitForStatsReportZeroTargetBitrate() {
3082 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
3083 if (send_stream_->GetStats().target_media_bitrate_bps == 0) {
3084 return;
3085 }
3086 SleepMs(1);
3087 }
3088 FAIL() << "Timed out waiting for stats reporting zero bitrate.";
3089 }
3090
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003091 private:
stefanf116bd02015-10-27 08:29:42 -07003092 rtc::CriticalSection crit_;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003093 VideoSendStream* send_stream_;
3094 uint32_t bitrate_kbps_ GUARDED_BY(crit_);
3095 } test;
3096
stefane74eef12016-01-08 06:47:13 -08003097 RunBaseTest(&test);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003098}
3099
philipel277a8b52017-03-16 05:19:49 -07003100TEST_F(EndToEndTest, GetStats) {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00003101 static const int kStartBitrateBps = 3000000;
Peter Boströmdef398832015-05-27 17:59:11 +02003102 static const int kExpectedRenderDelayMs = 20;
tommi2e82f382016-06-21 00:26:43 -07003103
3104 class ReceiveStreamRenderer : public rtc::VideoSinkInterface<VideoFrame> {
3105 public:
3106 ReceiveStreamRenderer() {}
3107
3108 private:
3109 void OnFrame(const VideoFrame& video_frame) override {}
3110 };
3111
nissed30a1112016-04-18 05:15:22 -07003112 class StatsObserver : public test::EndToEndTest,
3113 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003114 public:
stefanf116bd02015-10-27 08:29:42 -07003115 StatsObserver()
3116 : EndToEndTest(kLongTimeoutMs),
Peter Boströmc6e16e32016-02-05 14:15:53 +01003117 encoder_(Clock::GetRealTimeClock(), 10),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00003118 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003119 expected_send_ssrcs_(),
Peter Boström5811a392015-12-10 13:02:50 +01003120 check_stats_event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003121
3122 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003123 Action OnSendRtp(const uint8_t* packet, size_t length) override {
sprangcd349d92016-07-13 09:11:28 -07003124 // Drop every 25th packet => 4% loss.
3125 static const int kPacketLossFrac = 25;
3126 RTPHeader header;
3127 RtpUtility::RtpHeaderParser parser(packet, length);
3128 if (parser.Parse(&header) &&
3129 expected_send_ssrcs_.find(header.ssrc) !=
3130 expected_send_ssrcs_.end() &&
3131 header.sequenceNumber % kPacketLossFrac == 0) {
3132 return DROP_PACKET;
3133 }
Peter Boström5811a392015-12-10 13:02:50 +01003134 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003135 return SEND_PACKET;
3136 }
3137
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003138 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01003139 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003140 return SEND_PACKET;
3141 }
3142
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003143 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01003144 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003145 return SEND_PACKET;
3146 }
3147
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003148 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01003149 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003150 return SEND_PACKET;
3151 }
3152
nissed30a1112016-04-18 05:15:22 -07003153 void OnFrame(const VideoFrame& video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003154 // Ensure that we have at least 5ms send side delay.
nissed30a1112016-04-18 05:15:22 -07003155 SleepMs(5);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003156 }
3157
3158 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003159 for (size_t i = 0; i < receive_streams_.size(); ++i) {
3160 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
3161 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003162
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003163 // Make sure all fields have been populated.
3164 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
3165 // always filled for all receivers.
3166 receive_stats_filled_["IncomingRate"] |=
3167 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003168
Peter Boströmb7d9a972015-12-18 16:01:11 +01003169 send_stats_filled_["DecoderImplementationName"] |=
3170 stats.decoder_implementation_name ==
3171 test::FakeDecoder::kImplementationName;
Peter Boströmdef398832015-05-27 17:59:11 +02003172 receive_stats_filled_["RenderDelayAsHighAsExpected"] |=
3173 stats.render_delay_ms >= kExpectedRenderDelayMs;
3174
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003175 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003176
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003177 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003178
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003179 receive_stats_filled_["StatisticsUpdated"] |=
3180 stats.rtcp_stats.cumulative_lost != 0 ||
3181 stats.rtcp_stats.extended_max_sequence_number != 0 ||
3182 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003183
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003184 receive_stats_filled_["DataCountersUpdated"] |=
3185 stats.rtp_stats.transmitted.payload_bytes != 0 ||
3186 stats.rtp_stats.fec.packets != 0 ||
3187 stats.rtp_stats.transmitted.header_bytes != 0 ||
3188 stats.rtp_stats.transmitted.packets != 0 ||
3189 stats.rtp_stats.transmitted.padding_bytes != 0 ||
3190 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003191
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003192 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003193 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003194
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003195 receive_stats_filled_["FrameCounts"] |=
3196 stats.frame_counts.key_frames != 0 ||
3197 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00003198
pbosbb36fdf2015-07-09 07:48:14 -07003199 receive_stats_filled_["CName"] |= !stats.c_name.empty();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00003200
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003201 receive_stats_filled_["RtcpPacketTypeCount"] |=
3202 stats.rtcp_packet_type_counts.fir_packets != 0 ||
3203 stats.rtcp_packet_type_counts.nack_packets != 0 ||
3204 stats.rtcp_packet_type_counts.pli_packets != 0 ||
3205 stats.rtcp_packet_type_counts.nack_requests != 0 ||
3206 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbosf42376c2015-08-28 07:35:32 -07003207
3208 assert(stats.current_payload_type == -1 ||
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003209 stats.current_payload_type == kFakeVideoSendPayloadType);
pbosf42376c2015-08-28 07:35:32 -07003210 receive_stats_filled_["IncomingPayloadType"] |=
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003211 stats.current_payload_type == kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003212 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003213
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003214 return AllStatsFilled(receive_stats_filled_);
3215 }
3216
3217 bool CheckSendStats() {
Peter Boström74f6e9e2016-04-04 17:56:10 +02003218 RTC_DCHECK(send_stream_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003219 VideoSendStream::Stats stats = send_stream_->GetStats();
3220
philipel20d05a92016-12-19 04:17:27 -08003221 size_t expected_num_streams = kNumSsrcs + expected_send_ssrcs_.size();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003222 send_stats_filled_["NumStreams"] |=
philipel20d05a92016-12-19 04:17:27 -08003223 stats.substreams.size() == expected_num_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003224
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00003225 send_stats_filled_["CpuOveruseMetrics"] |=
Peter Boströme4499152016-02-05 11:13:28 +01003226 stats.avg_encode_time_ms != 0 && stats.encode_usage_percent != 0;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00003227
Peter Boströmb7d9a972015-12-18 16:01:11 +01003228 send_stats_filled_["EncoderImplementationName"] |=
3229 stats.encoder_implementation_name ==
3230 test::FakeEncoder::kImplementationName;
3231
Pera48ddb72016-09-29 11:48:50 +02003232 send_stats_filled_["EncoderPreferredBitrate"] |=
3233 stats.preferred_media_bitrate_bps > 0;
3234
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003235 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003236 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003237 it != stats.substreams.end(); ++it) {
sprangcd349d92016-07-13 09:11:28 -07003238 if (expected_send_ssrcs_.find(it->first) == expected_send_ssrcs_.end())
3239 continue; // Probably RTX.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003240
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003241 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003242 stats.input_frame_rate != 0;
3243
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003244 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003245
3246 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
3247 stream_stats.rtcp_stats.cumulative_lost != 0 ||
3248 stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
3249 stream_stats.rtcp_stats.fraction_lost != 0;
3250
3251 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00003252 stream_stats.rtp_stats.fec.packets != 0 ||
3253 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
3254 stream_stats.rtp_stats.retransmitted.packets != 0 ||
3255 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003256
sprangcd349d92016-07-13 09:11:28 -07003257 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Total",
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003258 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00003259 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003260
sprangcd349d92016-07-13 09:11:28 -07003261 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Retransmit",
3262 it->first)] |=
3263 stream_stats.retransmit_bitrate_bps != 0;
3264
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003265 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00003266 stream_stats.frame_counts.delta_frames != 0 ||
3267 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003268
3269 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
3270 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00003271
3272 send_stats_filled_[CompoundKey("Delay", it->first)] |=
3273 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003274
3275 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
3276 // report dropped packets.
3277 send_stats_filled_["RtcpPacketTypeCount"] |=
3278 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
3279 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
3280 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
3281 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
3282 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003283 }
3284
3285 return AllStatsFilled(send_stats_filled_);
3286 }
3287
3288 std::string CompoundKey(const char* name, uint32_t ssrc) {
3289 std::ostringstream oss;
3290 oss << name << "_" << ssrc;
3291 return oss.str();
3292 }
3293
3294 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
sprangcd349d92016-07-13 09:11:28 -07003295 for (const auto& stat : stats_map) {
3296 if (!stat.second)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003297 return false;
3298 }
3299 return true;
3300 }
3301
stefane74eef12016-01-08 06:47:13 -08003302 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
3303 FakeNetworkPipe::Config network_config;
3304 network_config.loss_percent = 5;
minyue20c84cc2017-04-10 16:57:57 -07003305 return new test::PacketTransport(sender_call, this,
3306 test::PacketTransport::kSender,
3307 payload_type_map_, network_config);
stefane74eef12016-01-08 06:47:13 -08003308 }
3309
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003310 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00003311 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01003312 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00003313 return config;
3314 }
3315
perkjfa10b552016-10-02 23:45:26 -07003316 // This test use other VideoStream settings than the the default settings
3317 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3318 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3319 // in ModifyVideoConfigs.
3320 class VideoStreamFactory
3321 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3322 public:
3323 VideoStreamFactory() {}
3324
3325 private:
3326 std::vector<VideoStream> CreateEncoderStreams(
3327 int width,
3328 int height,
3329 const VideoEncoderConfig& encoder_config) override {
3330 std::vector<VideoStream> streams =
3331 test::CreateVideoStreams(width, height, encoder_config);
3332 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
3333 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3334 streams[i].min_bitrate_bps = 10000;
3335 streams[i].target_bitrate_bps = 15000;
3336 streams[i].max_bitrate_bps = 20000;
3337 }
3338 return streams;
3339 }
3340 };
3341
stefanff483612015-12-21 03:14:00 -08003342 void ModifyVideoConfigs(
3343 VideoSendStream::Config* send_config,
3344 std::vector<VideoReceiveStream::Config>* receive_configs,
3345 VideoEncoderConfig* encoder_config) override {
perkjfa10b552016-10-02 23:45:26 -07003346 encoder_config->video_stream_factory =
3347 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003348 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003349 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003350
sprangcd349d92016-07-13 09:11:28 -07003351 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
3352 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
3353
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003354 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003355 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003356 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003357 expected_receive_ssrcs_.push_back(
3358 (*receive_configs)[i].rtp.remote_ssrc);
Peter Boströmdef398832015-05-27 17:59:11 +02003359 (*receive_configs)[i].render_delay_ms = kExpectedRenderDelayMs;
tommi2e82f382016-06-21 00:26:43 -07003360 (*receive_configs)[i].renderer = &receive_stream_renderer_;
sprangcd349d92016-07-13 09:11:28 -07003361 (*receive_configs)[i].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
3362
brandtr14742122017-01-27 04:53:07 -08003363 (*receive_configs)[i].rtp.rtx_ssrc = kSendRtxSsrcs[i];
3364 (*receive_configs)[i].rtp.rtx_payload_types[kFakeVideoSendPayloadType] =
sprangcd349d92016-07-13 09:11:28 -07003365 kSendRtxPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003366 }
sprangcd349d92016-07-13 09:11:28 -07003367
3368 for (size_t i = 0; i < kNumSsrcs; ++i)
3369 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
3370
Peter Boströmc6e16e32016-02-05 14:15:53 +01003371 // Use a delayed encoder to make sure we see CpuOveruseMetrics stats that
3372 // are non-zero.
3373 send_config->encoder_settings.encoder = &encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003374 }
3375
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003376 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00003377
stefanff483612015-12-21 03:14:00 -08003378 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003379 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003380 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003381 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003382 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003383 }
3384
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003385 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003386 Clock* clock = Clock::GetRealTimeClock();
3387 int64_t now = clock->TimeInMilliseconds();
3388 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
3389 bool receive_ok = false;
3390 bool send_ok = false;
3391
3392 while (now < stop_time) {
3393 if (!receive_ok)
3394 receive_ok = CheckReceiveStats();
3395 if (!send_ok)
3396 send_ok = CheckSendStats();
3397
3398 if (receive_ok && send_ok)
3399 return;
3400
3401 int64_t time_until_timout_ = stop_time - now;
3402 if (time_until_timout_ > 0)
Peter Boström5811a392015-12-10 13:02:50 +01003403 check_stats_event_.Wait(time_until_timout_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003404 now = clock->TimeInMilliseconds();
3405 }
3406
3407 ADD_FAILURE() << "Timed out waiting for filled stats.";
3408 for (std::map<std::string, bool>::const_iterator it =
3409 receive_stats_filled_.begin();
3410 it != receive_stats_filled_.end();
3411 ++it) {
3412 if (!it->second) {
3413 ADD_FAILURE() << "Missing receive stats: " << it->first;
3414 }
3415 }
3416
3417 for (std::map<std::string, bool>::const_iterator it =
3418 send_stats_filled_.begin();
3419 it != send_stats_filled_.end();
3420 ++it) {
3421 if (!it->second) {
3422 ADD_FAILURE() << "Missing send stats: " << it->first;
3423 }
3424 }
3425 }
3426
Peter Boströmc6e16e32016-02-05 14:15:53 +01003427 test::DelayedEncoder encoder_;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003428 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003429 std::map<std::string, bool> receive_stats_filled_;
3430
3431 VideoSendStream* send_stream_;
3432 std::map<std::string, bool> send_stats_filled_;
3433
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003434 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003435 std::set<uint32_t> expected_send_ssrcs_;
3436 std::string expected_cname_;
3437
Peter Boström5811a392015-12-10 13:02:50 +01003438 rtc::Event check_stats_event_;
tommi2e82f382016-06-21 00:26:43 -07003439 ReceiveStreamRenderer receive_stream_renderer_;
stefanf116bd02015-10-27 08:29:42 -07003440 } test;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003441
stefane74eef12016-01-08 06:47:13 -08003442 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003443}
3444
sprang1a646ee2016-12-01 06:34:11 -08003445class RtcpXrObserver : public test::EndToEndTest {
3446 public:
sprang44b3ef62017-01-13 07:30:25 -08003447 RtcpXrObserver(bool enable_rrtr, bool enable_target_bitrate)
sprang1a646ee2016-12-01 06:34:11 -08003448 : EndToEndTest(test::CallTest::kDefaultTimeoutMs),
3449 enable_rrtr_(enable_rrtr),
sprang44b3ef62017-01-13 07:30:25 -08003450 enable_target_bitrate_(enable_target_bitrate),
sprang1a646ee2016-12-01 06:34:11 -08003451 sent_rtcp_sr_(0),
3452 sent_rtcp_rr_(0),
3453 sent_rtcp_rrtr_(0),
3454 sent_rtcp_target_bitrate_(false),
3455 sent_rtcp_dlrr_(0) {}
3456
3457 private:
3458 // Receive stream should send RR packets (and RRTR packets if enabled).
3459 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
3460 rtc::CritScope lock(&crit_);
3461 test::RtcpPacketParser parser;
3462 EXPECT_TRUE(parser.Parse(packet, length));
3463
3464 sent_rtcp_rr_ += parser.receiver_report()->num_packets();
3465 EXPECT_EQ(0, parser.sender_report()->num_packets());
3466 EXPECT_GE(1, parser.xr()->num_packets());
3467 if (parser.xr()->num_packets() > 0) {
3468 if (parser.xr()->rrtr())
3469 ++sent_rtcp_rrtr_;
3470 EXPECT_FALSE(parser.xr()->dlrr());
3471 }
3472
3473 return SEND_PACKET;
3474 }
3475 // Send stream should send SR packets (and DLRR packets if enabled).
3476 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
3477 rtc::CritScope lock(&crit_);
3478 test::RtcpPacketParser parser;
3479 EXPECT_TRUE(parser.Parse(packet, length));
3480
3481 sent_rtcp_sr_ += parser.sender_report()->num_packets();
3482 EXPECT_LE(parser.xr()->num_packets(), 1);
3483 if (parser.xr()->num_packets() > 0) {
3484 EXPECT_FALSE(parser.xr()->rrtr());
3485 if (parser.xr()->dlrr())
3486 ++sent_rtcp_dlrr_;
3487 if (parser.xr()->target_bitrate())
3488 sent_rtcp_target_bitrate_ = true;
3489 }
3490
3491 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
3492 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve &&
sprang44b3ef62017-01-13 07:30:25 -08003493 (sent_rtcp_target_bitrate_ || !enable_target_bitrate_)) {
sprang1a646ee2016-12-01 06:34:11 -08003494 if (enable_rrtr_) {
3495 EXPECT_GT(sent_rtcp_rrtr_, 0);
3496 EXPECT_GT(sent_rtcp_dlrr_, 0);
3497 } else {
3498 EXPECT_EQ(sent_rtcp_rrtr_, 0);
3499 EXPECT_EQ(sent_rtcp_dlrr_, 0);
3500 }
sprang44b3ef62017-01-13 07:30:25 -08003501 EXPECT_EQ(enable_target_bitrate_, sent_rtcp_target_bitrate_);
sprang1a646ee2016-12-01 06:34:11 -08003502 observation_complete_.Set();
3503 }
3504 return SEND_PACKET;
3505 }
3506
3507 void ModifyVideoConfigs(
3508 VideoSendStream::Config* send_config,
3509 std::vector<VideoReceiveStream::Config>* receive_configs,
3510 VideoEncoderConfig* encoder_config) override {
sprang44b3ef62017-01-13 07:30:25 -08003511 if (enable_target_bitrate_) {
3512 // TargetBitrate only signaled for screensharing.
3513 encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
3514 }
sprang1a646ee2016-12-01 06:34:11 -08003515 (*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
3516 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
3517 enable_rrtr_;
3518 }
3519
3520 void PerformTest() override {
3521 EXPECT_TRUE(Wait())
3522 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
3523 }
3524
3525 static const int kNumRtcpReportPacketsToObserve = 5;
3526
3527 rtc::CriticalSection crit_;
sprang44b3ef62017-01-13 07:30:25 -08003528 const bool enable_rrtr_;
3529 const bool enable_target_bitrate_;
sprang1a646ee2016-12-01 06:34:11 -08003530 int sent_rtcp_sr_;
3531 int sent_rtcp_rr_ GUARDED_BY(&crit_);
3532 int sent_rtcp_rrtr_ GUARDED_BY(&crit_);
3533 bool sent_rtcp_target_bitrate_ GUARDED_BY(&crit_);
3534 int sent_rtcp_dlrr_;
3535};
3536
philipel277a8b52017-03-16 05:19:49 -07003537TEST_F(EndToEndTest, TestExtendedReportsWithRrtrWithoutTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003538 RtcpXrObserver test(true, false);
sprang1a646ee2016-12-01 06:34:11 -08003539 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003540}
3541
philipel277a8b52017-03-16 05:19:49 -07003542TEST_F(EndToEndTest, TestExtendedReportsWithoutRrtrWithoutTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003543 RtcpXrObserver test(false, false);
3544 RunBaseTest(&test);
3545}
3546
philipel277a8b52017-03-16 05:19:49 -07003547TEST_F(EndToEndTest, TestExtendedReportsWithRrtrWithTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003548 RtcpXrObserver test(true, true);
3549 RunBaseTest(&test);
3550}
3551
philipel277a8b52017-03-16 05:19:49 -07003552TEST_F(EndToEndTest, TestExtendedReportsWithoutRrtrWithTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003553 RtcpXrObserver test(false, true);
sprang1a646ee2016-12-01 06:34:11 -08003554 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003555}
3556
philipel277a8b52017-03-16 05:19:49 -07003557TEST_F(EndToEndTest, TestReceivedRtpPacketStats) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003558 static const size_t kNumRtpPacketsToSend = 5;
3559 class ReceivedRtpStatsObserver : public test::EndToEndTest {
3560 public:
3561 ReceivedRtpStatsObserver()
3562 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00003563 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003564 sent_rtp_(0) {}
3565
3566 private:
stefanff483612015-12-21 03:14:00 -08003567 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003568 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003569 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003570 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003571 }
3572
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003573 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003574 if (sent_rtp_ >= kNumRtpPacketsToSend) {
3575 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00003576 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
Peter Boström5811a392015-12-10 13:02:50 +01003577 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003578 }
3579 return DROP_PACKET;
3580 }
3581 ++sent_rtp_;
3582 return SEND_PACKET;
3583 }
3584
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003585 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003586 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003587 << "Timed out while verifying number of received RTP packets.";
3588 }
3589
3590 VideoReceiveStream* receive_stream_;
3591 uint32_t sent_rtp_;
3592 } test;
3593
stefane74eef12016-01-08 06:47:13 -08003594 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003595}
3596
philipel277a8b52017-03-16 05:19:49 -07003597TEST_F(EndToEndTest, SendsSetSsrc) {
philipel266f0a42016-11-28 08:49:07 -08003598 TestSendsSetSsrcs(1, false);
3599}
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003600
philipel277a8b52017-03-16 05:19:49 -07003601TEST_F(EndToEndTest, SendsSetSimulcastSsrcs) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003602 TestSendsSetSsrcs(kNumSsrcs, false);
3603}
3604
philipel277a8b52017-03-16 05:19:49 -07003605TEST_F(EndToEndTest, CanSwitchToUseAllSsrcs) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003606 TestSendsSetSsrcs(kNumSsrcs, true);
3607}
3608
philipel277a8b52017-03-16 05:19:49 -07003609TEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003610 class ObserveRedundantPayloads: public test::EndToEndTest {
3611 public:
3612 ObserveRedundantPayloads()
3613 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003614 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003615 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
3616 }
3617 }
3618
3619 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003620 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003621 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003622 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003623
3624 if (!registered_rtx_ssrc_[header.ssrc])
3625 return SEND_PACKET;
3626
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003627 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003628 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003629 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003630
3631 if (!packet_is_redundant_payload)
3632 return SEND_PACKET;
3633
3634 if (!observed_redundant_retransmission_[header.ssrc]) {
3635 observed_redundant_retransmission_[header.ssrc] = true;
3636 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01003637 observation_complete_.Set();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003638 }
3639
3640 return SEND_PACKET;
3641 }
3642
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003643 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003644
perkjfa10b552016-10-02 23:45:26 -07003645 // This test use other VideoStream settings than the the default settings
3646 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3647 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3648 // in ModifyVideoConfigs.
3649 class VideoStreamFactory
3650 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3651 public:
3652 VideoStreamFactory() {}
3653
3654 private:
3655 std::vector<VideoStream> CreateEncoderStreams(
3656 int width,
3657 int height,
3658 const VideoEncoderConfig& encoder_config) override {
3659 std::vector<VideoStream> streams =
3660 test::CreateVideoStreams(width, height, encoder_config);
3661 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
3662 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3663 streams[i].min_bitrate_bps = 10000;
3664 streams[i].target_bitrate_bps = 15000;
3665 streams[i].max_bitrate_bps = 20000;
3666 }
3667 return streams;
3668 }
3669 };
3670
stefanff483612015-12-21 03:14:00 -08003671 void ModifyVideoConfigs(
3672 VideoSendStream::Config* send_config,
3673 std::vector<VideoReceiveStream::Config>* receive_configs,
3674 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003675 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
perkjfa10b552016-10-02 23:45:26 -07003676 encoder_config->video_stream_factory =
3677 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003678 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003679
3680 for (size_t i = 0; i < kNumSsrcs; ++i)
3681 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00003682
3683 // Significantly higher than max bitrates for all video streams -> forcing
3684 // padding to trigger redundant padding on all RTX SSRCs.
3685 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003686 }
3687
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003688 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003689 EXPECT_TRUE(Wait())
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003690 << "Timed out while waiting for redundant payloads on all SSRCs.";
3691 }
3692
3693 private:
3694 size_t ssrcs_to_observe_;
3695 std::map<uint32_t, bool> observed_redundant_retransmission_;
3696 std::map<uint32_t, bool> registered_rtx_ssrc_;
3697 } test;
3698
stefane74eef12016-01-08 06:47:13 -08003699 RunBaseTest(&test);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003700}
3701
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003702void EndToEndTest::TestRtpStatePreservation(bool use_rtx,
3703 bool provoke_rtcpsr_before_rtp) {
brandtr5e171752017-05-23 03:32:16 -07003704 // This test uses other VideoStream settings than the the default settings
3705 // implemented in DefaultVideoStreamFactory. Therefore this test implements
perkjfa10b552016-10-02 23:45:26 -07003706 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3707 // in ModifyVideoConfigs.
3708 class VideoStreamFactory
3709 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3710 public:
3711 VideoStreamFactory() {}
3712
3713 private:
3714 std::vector<VideoStream> CreateEncoderStreams(
3715 int width,
3716 int height,
3717 const VideoEncoderConfig& encoder_config) override {
3718 std::vector<VideoStream> streams =
3719 test::CreateVideoStreams(width, height, encoder_config);
3720
3721 if (encoder_config.number_of_streams > 1) {
3722 // Lower bitrates so that all streams send initially.
kwibergaf476c72016-11-28 15:21:39 -08003723 RTC_DCHECK_EQ(3, encoder_config.number_of_streams);
perkjfa10b552016-10-02 23:45:26 -07003724 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3725 streams[i].min_bitrate_bps = 10000;
3726 streams[i].target_bitrate_bps = 15000;
3727 streams[i].max_bitrate_bps = 20000;
3728 }
3729 } else {
3730 // Use the same total bitrates when sending a single stream to avoid
3731 // lowering
3732 // the bitrate estimate and requiring a subsequent rampup.
3733 streams[0].min_bitrate_bps = 3 * 10000;
3734 streams[0].target_bitrate_bps = 3 * 15000;
3735 streams[0].max_bitrate_bps = 3 * 20000;
3736 }
3737 return streams;
3738 }
3739 };
3740
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003741 class RtpSequenceObserver : public test::RtpRtcpObserver {
3742 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003743 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003744 : test::RtpRtcpObserver(kDefaultTimeoutMs),
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003745 ssrcs_to_observe_(kNumSsrcs) {
3746 for (size_t i = 0; i < kNumSsrcs; ++i) {
danilchap32cd2c42016-08-01 06:58:34 -07003747 ssrc_is_rtx_[kVideoSendSsrcs[i]] = false;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003748 if (use_rtx)
danilchap32cd2c42016-08-01 06:58:34 -07003749 ssrc_is_rtx_[kSendRtxSsrcs[i]] = true;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003750 }
3751 }
3752
3753 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
Peter Boströmf2f82832015-05-01 13:00:41 +02003754 rtc::CritScope lock(&crit_);
danilchap34877ee2016-02-01 08:25:04 -08003755 ssrc_observed_.clear();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003756 ssrcs_to_observe_ = num_expected_ssrcs;
3757 }
3758
3759 private:
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003760 void ValidateTimestampGap(uint32_t ssrc,
3761 uint32_t timestamp,
3762 bool only_padding)
3763 EXCLUSIVE_LOCKS_REQUIRED(crit_) {
3764 static const int32_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
3765 auto timestamp_it = last_observed_timestamp_.find(ssrc);
3766 if (timestamp_it == last_observed_timestamp_.end()) {
3767 EXPECT_FALSE(only_padding);
3768 last_observed_timestamp_[ssrc] = timestamp;
3769 } else {
3770 // Verify timestamps are reasonably close.
3771 uint32_t latest_observed = timestamp_it->second;
3772 // Wraparound handling is unnecessary here as long as an int variable
3773 // is used to store the result.
3774 int32_t timestamp_gap = timestamp - latest_observed;
3775 EXPECT_LE(std::abs(timestamp_gap), kMaxTimestampGap)
3776 << "Gap in timestamps (" << latest_observed << " -> " << timestamp
3777 << ") too large for SSRC: " << ssrc << ".";
3778 timestamp_it->second = timestamp;
3779 }
3780 }
3781
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003782 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003783 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003784 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003785 const uint32_t ssrc = header.ssrc;
danilchap5c35cf92016-02-03 14:14:49 -08003786 const int64_t sequence_number =
3787 seq_numbers_unwrapper_.Unwrap(header.sequenceNumber);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003788 const uint32_t timestamp = header.timestamp;
danilchap34877ee2016-02-01 08:25:04 -08003789 const bool only_padding =
3790 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003791
danilchap32cd2c42016-08-01 06:58:34 -07003792 EXPECT_TRUE(ssrc_is_rtx_.find(ssrc) != ssrc_is_rtx_.end())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003793 << "Received SSRC that wasn't configured: " << ssrc;
3794
danilchap5c35cf92016-02-03 14:14:49 -08003795 static const int64_t kMaxSequenceNumberGap = 100;
3796 std::list<int64_t>* seq_numbers = &last_observed_seq_numbers_[ssrc];
3797 if (seq_numbers->empty()) {
3798 seq_numbers->push_back(sequence_number);
3799 } else {
3800 // We shouldn't get replays of previous sequence numbers.
3801 for (int64_t observed : *seq_numbers) {
3802 EXPECT_NE(observed, sequence_number)
3803 << "Received sequence number " << sequence_number
3804 << " for SSRC " << ssrc << " 2nd time.";
3805 }
3806 // Verify sequence numbers are reasonably close.
3807 int64_t latest_observed = seq_numbers->back();
3808 int64_t sequence_number_gap = sequence_number - latest_observed;
3809 EXPECT_LE(std::abs(sequence_number_gap), kMaxSequenceNumberGap)
3810 << "Gap in sequence numbers (" << latest_observed << " -> "
3811 << sequence_number << ") too large for SSRC: " << ssrc << ".";
3812 seq_numbers->push_back(sequence_number);
3813 if (seq_numbers->size() >= kMaxSequenceNumberGap) {
3814 seq_numbers->pop_front();
3815 }
3816 }
3817
danilchap32cd2c42016-08-01 06:58:34 -07003818 if (!ssrc_is_rtx_[ssrc]) {
3819 rtc::CritScope lock(&crit_);
3820 ValidateTimestampGap(ssrc, timestamp, only_padding);
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003821
danilchap32cd2c42016-08-01 06:58:34 -07003822 // Wait for media packets on all ssrcs.
3823 if (!ssrc_observed_[ssrc] && !only_padding) {
3824 ssrc_observed_[ssrc] = true;
3825 if (--ssrcs_to_observe_ == 0)
3826 observation_complete_.Set();
3827 }
danilchap34877ee2016-02-01 08:25:04 -08003828 }
3829
danilchapf4b9c772016-01-28 06:14:24 -08003830 return SEND_PACKET;
3831 }
3832
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003833 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
3834 test::RtcpPacketParser rtcp_parser;
3835 rtcp_parser.Parse(packet, length);
3836 if (rtcp_parser.sender_report()->num_packets() > 0) {
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02003837 uint32_t ssrc = rtcp_parser.sender_report()->sender_ssrc();
3838 uint32_t rtcp_timestamp = rtcp_parser.sender_report()->rtp_timestamp();
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003839
3840 rtc::CritScope lock(&crit_);
3841 ValidateTimestampGap(ssrc, rtcp_timestamp, false);
3842 }
3843 return SEND_PACKET;
3844 }
3845
danilchap5c35cf92016-02-03 14:14:49 -08003846 SequenceNumberUnwrapper seq_numbers_unwrapper_;
3847 std::map<uint32_t, std::list<int64_t>> last_observed_seq_numbers_;
danilchap34877ee2016-02-01 08:25:04 -08003848 std::map<uint32_t, uint32_t> last_observed_timestamp_;
danilchap32cd2c42016-08-01 06:58:34 -07003849 std::map<uint32_t, bool> ssrc_is_rtx_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003850
Peter Boströmf2f82832015-05-01 13:00:41 +02003851 rtc::CriticalSection crit_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003852 size_t ssrcs_to_observe_ GUARDED_BY(crit_);
danilchap34877ee2016-02-01 08:25:04 -08003853 std::map<uint32_t, bool> ssrc_observed_ GUARDED_BY(crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003854 } observer(use_rtx);
3855
philipel4fb651d2017-04-10 03:54:05 -07003856 Call::Config config(event_log_.get());
skvlad11a9cbf2016-10-07 11:53:05 -07003857 CreateCalls(config, config);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003858
minyue20c84cc2017-04-10 16:57:57 -07003859 test::PacketTransport send_transport(
3860 sender_call_.get(), &observer, test::PacketTransport::kSender,
3861 payload_type_map_, FakeNetworkPipe::Config());
3862 test::PacketTransport receive_transport(
3863 nullptr, &observer, test::PacketTransport::kReceiver, payload_type_map_,
3864 FakeNetworkPipe::Config());
stefanf116bd02015-10-27 08:29:42 -07003865 send_transport.SetReceiver(receiver_call_->Receiver());
3866 receive_transport.SetReceiver(sender_call_->Receiver());
3867
brandtr841de6a2016-11-15 07:10:52 -08003868 CreateSendConfig(kNumSsrcs, 0, 0, &send_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003869
3870 if (use_rtx) {
3871 for (size_t i = 0; i < kNumSsrcs; ++i) {
stefanff483612015-12-21 03:14:00 -08003872 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003873 }
stefanff483612015-12-21 03:14:00 -08003874 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003875 }
3876
perkjfa10b552016-10-02 23:45:26 -07003877 video_encoder_config_.video_stream_factory =
3878 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003879 // Use the same total bitrates when sending a single stream to avoid lowering
3880 // the bitrate estimate and requiring a subsequent rampup.
perkj26091b12016-09-01 01:17:40 -07003881 VideoEncoderConfig one_stream = video_encoder_config_.Copy();
perkjfa10b552016-10-02 23:45:26 -07003882 // one_stream.streams.resize(1);
3883 one_stream.number_of_streams = 1;
stefanf116bd02015-10-27 08:29:42 -07003884 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003885
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003886 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003887 CreateFrameGeneratorCapturer(30, 1280, 720);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003888
3889 Start();
Peter Boström5811a392015-12-10 13:02:50 +01003890 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003891 << "Timed out waiting for all SSRCs to send packets.";
3892
3893 // Test stream resetting more than once to make sure that the state doesn't
3894 // get set once (this could be due to using std::map::insert for instance).
3895 for (size_t i = 0; i < 3; ++i) {
3896 frame_generator_capturer_->Stop();
stefanff483612015-12-21 03:14:00 -08003897 sender_call_->DestroyVideoSendStream(video_send_stream_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003898
3899 // Re-create VideoSendStream with only one stream.
perkj26091b12016-09-01 01:17:40 -07003900 video_send_stream_ = sender_call_->CreateVideoSendStream(
3901 video_send_config_.Copy(), one_stream.Copy());
stefanff483612015-12-21 03:14:00 -08003902 video_send_stream_->Start();
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003903 if (provoke_rtcpsr_before_rtp) {
3904 // Rapid Resync Request forces sending RTCP Sender Report back.
3905 // Using this request speeds up this test because then there is no need
3906 // to wait for a second for periodic Sender Report.
3907 rtcp::RapidResyncRequest force_send_sr_back_request;
3908 rtc::Buffer packet = force_send_sr_back_request.Build();
3909 static_cast<webrtc::test::DirectTransport&>(receive_transport)
3910 .SendRtcp(packet.data(), packet.size());
3911 }
perkjfa10b552016-10-02 23:45:26 -07003912 CreateFrameGeneratorCapturer(30, 1280, 720);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003913 frame_generator_capturer_->Start();
3914
3915 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003916 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003917
3918 // Reconfigure back to use all streams.
perkj26091b12016-09-01 01:17:40 -07003919 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003920 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003921 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003922 << "Timed out waiting for all SSRCs to send packets.";
3923
3924 // Reconfigure down to one stream.
perkj26091b12016-09-01 01:17:40 -07003925 video_send_stream_->ReconfigureVideoEncoder(one_stream.Copy());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003926 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003927 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003928
3929 // Reconfigure back to use all streams.
perkj26091b12016-09-01 01:17:40 -07003930 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003931 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003932 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003933 << "Timed out waiting for all SSRCs to send packets.";
3934 }
3935
stefanf116bd02015-10-27 08:29:42 -07003936 send_transport.StopSending();
3937 receive_transport.StopSending();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003938
3939 Stop();
3940 DestroyStreams();
3941}
3942
philipel277a8b52017-03-16 05:19:49 -07003943TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpState) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003944 TestRtpStatePreservation(false, false);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003945}
3946
philipel277a8b52017-03-16 05:19:49 -07003947TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpStatesWithRtx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003948 TestRtpStatePreservation(true, false);
3949}
3950
philipel277a8b52017-03-16 05:19:49 -07003951TEST_F(EndToEndTest, RestartingSendStreamKeepsRtpAndRtcpTimestampsSynced) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003952 TestRtpStatePreservation(true, true);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003953}
3954
brandtreb806792017-05-31 07:46:56 -07003955// This test is flaky on linux_memcheck. Disable on all linux bots until
3956// flakyness has been fixed.
3957// https://bugs.chromium.org/p/webrtc/issues/detail?id=7737
3958#if defined(WEBRTC_LINUX)
3959#define MAYBE_TestFlexfecRtpStatePreservation \
3960 DISABLED_TestFlexfecRtpStatePreservation
3961#else
3962#define MAYBE_TestFlexfecRtpStatePreservation TestFlexfecRtpStatePreservation
3963#endif
3964TEST_F(EndToEndTest, MAYBE_TestFlexfecRtpStatePreservation) {
brandtr48d21a22017-05-30 02:32:12 -07003965 class RtpSequenceObserver : public test::RtpRtcpObserver {
3966 public:
3967 RtpSequenceObserver()
3968 : test::RtpRtcpObserver(kDefaultTimeoutMs),
3969 num_flexfec_packets_sent_(0) {}
3970
3971 void ResetPacketCount() {
3972 rtc::CritScope lock(&crit_);
3973 num_flexfec_packets_sent_ = 0;
3974 }
3975
3976 private:
3977 Action OnSendRtp(const uint8_t* packet, size_t length) override {
3978 rtc::CritScope lock(&crit_);
3979
3980 RTPHeader header;
3981 EXPECT_TRUE(parser_->Parse(packet, length, &header));
3982 const uint16_t sequence_number = header.sequenceNumber;
3983 const uint32_t timestamp = header.timestamp;
3984 const uint32_t ssrc = header.ssrc;
3985
3986 if (ssrc == kVideoSendSsrcs[0] || ssrc == kSendRtxSsrcs[0]) {
3987 return SEND_PACKET;
3988 }
3989 EXPECT_EQ(kFlexfecSendSsrc, ssrc) << "Unknown SSRC sent.";
3990
3991 ++num_flexfec_packets_sent_;
3992
3993 // If this is the first packet, we have nothing to compare to.
3994 if (!last_observed_sequence_number_) {
3995 last_observed_sequence_number_.emplace(sequence_number);
3996 last_observed_timestamp_.emplace(timestamp);
3997
3998 return SEND_PACKET;
3999 }
4000
4001 // Verify continuity and monotonicity of RTP sequence numbers.
4002 EXPECT_EQ(static_cast<uint16_t>(*last_observed_sequence_number_ + 1),
4003 sequence_number);
4004 last_observed_sequence_number_.emplace(sequence_number);
4005
4006 // Timestamps should be non-decreasing...
4007 const bool timestamp_is_same_or_newer =
4008 timestamp == *last_observed_timestamp_ ||
4009 IsNewerTimestamp(timestamp, *last_observed_timestamp_);
4010 EXPECT_TRUE(timestamp_is_same_or_newer);
4011 // ...but reasonably close in time.
4012 const int k10SecondsInRtpTimestampBase = 10 * kVideoPayloadTypeFrequency;
4013 EXPECT_TRUE(IsNewerTimestamp(
4014 *last_observed_timestamp_ + k10SecondsInRtpTimestampBase, timestamp));
4015 last_observed_timestamp_.emplace(timestamp);
4016
4017 // Pass test when enough packets have been let through.
4018 if (num_flexfec_packets_sent_ >= 10) {
4019 observation_complete_.Set();
4020 }
4021
4022 return SEND_PACKET;
4023 }
4024
4025 rtc::Optional<uint16_t> last_observed_sequence_number_ GUARDED_BY(crit_);
4026 rtc::Optional<uint32_t> last_observed_timestamp_ GUARDED_BY(crit_);
4027 size_t num_flexfec_packets_sent_ GUARDED_BY(crit_);
4028 rtc::CriticalSection crit_;
4029 } observer;
4030
4031 Call::Config config(event_log_.get());
4032 CreateCalls(config, config);
4033
4034 FakeNetworkPipe::Config lossy_delayed_link;
4035 lossy_delayed_link.loss_percent = 2;
4036 lossy_delayed_link.queue_delay_ms = 50;
4037 test::PacketTransport send_transport(sender_call_.get(), &observer,
4038 test::PacketTransport::kSender,
4039 payload_type_map_, lossy_delayed_link);
4040 send_transport.SetReceiver(receiver_call_->Receiver());
4041
4042 FakeNetworkPipe::Config flawless_link;
4043 test::PacketTransport receive_transport(nullptr, &observer,
4044 test::PacketTransport::kReceiver,
4045 payload_type_map_, flawless_link);
4046 receive_transport.SetReceiver(sender_call_->Receiver());
4047
4048 // For reduced flakyness, we use a real VP8 encoder together with NACK
4049 // and RTX.
4050 const int kNumVideoStreams = 1;
4051 const int kNumFlexfecStreams = 1;
4052 CreateSendConfig(kNumVideoStreams, 0, kNumFlexfecStreams, &send_transport);
4053 std::unique_ptr<VideoEncoder> encoder(VP8Encoder::Create());
4054 video_send_config_.encoder_settings.encoder = encoder.get();
4055 video_send_config_.encoder_settings.payload_name = "VP8";
4056 video_send_config_.encoder_settings.payload_type = kVideoSendPayloadType;
4057 video_send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
4058 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
4059 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
4060
4061 CreateMatchingReceiveConfigs(&receive_transport);
4062 video_receive_configs_[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
4063 video_receive_configs_[0].rtp.rtx_ssrc = kSendRtxSsrcs[0];
4064 video_receive_configs_[0].rtp.rtx_payload_types[kVideoSendPayloadType] =
4065 kSendRtxPayloadType;
4066
4067 // The matching FlexFEC receive config is not created by
4068 // CreateMatchingReceiveConfigs since this is not a test::BaseTest.
4069 // Set up the receive config manually instead.
4070 FlexfecReceiveStream::Config flexfec_receive_config(&receive_transport);
4071 flexfec_receive_config.payload_type =
4072 video_send_config_.rtp.flexfec.payload_type;
4073 flexfec_receive_config.remote_ssrc = video_send_config_.rtp.flexfec.ssrc;
4074 flexfec_receive_config.protected_media_ssrcs =
4075 video_send_config_.rtp.flexfec.protected_media_ssrcs;
4076 flexfec_receive_config.local_ssrc = kReceiverLocalVideoSsrc;
4077 flexfec_receive_config.transport_cc = true;
4078 flexfec_receive_config.rtp_header_extensions.emplace_back(
4079 RtpExtension::kTransportSequenceNumberUri,
4080 test::kTransportSequenceNumberExtensionId);
4081 flexfec_receive_configs_.push_back(flexfec_receive_config);
4082
4083 CreateFlexfecStreams();
4084 CreateVideoStreams();
4085
4086 // RTCP might be disabled if the network is "down".
4087 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
4088 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
4089
4090 const int kFrameMaxWidth = 320;
4091 const int kFrameMaxHeight = 180;
4092 const int kFrameRate = 15;
4093 CreateFrameGeneratorCapturer(kFrameRate, kFrameMaxWidth, kFrameMaxHeight);
4094
4095 // Initial test.
4096 Start();
4097 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for packets.";
4098
4099 // Ensure monotonicity when the VideoSendStream is restarted.
4100 Stop();
4101 observer.ResetPacketCount();
4102 Start();
4103 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for packets.";
4104
4105 // Ensure monotonicity when the VideoSendStream is recreated.
4106 frame_generator_capturer_->Stop();
4107 sender_call_->DestroyVideoSendStream(video_send_stream_);
4108 observer.ResetPacketCount();
4109 video_send_stream_ = sender_call_->CreateVideoSendStream(
4110 video_send_config_.Copy(), video_encoder_config_.Copy());
4111 video_send_stream_->Start();
4112 CreateFrameGeneratorCapturer(kFrameRate, kFrameMaxWidth, kFrameMaxHeight);
4113 frame_generator_capturer_->Start();
4114 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for packets.";
4115
4116 // Cleanup.
4117 send_transport.StopSending();
4118 receive_transport.StopSending();
4119 Stop();
4120 DestroyStreams();
4121}
4122
philipel277a8b52017-03-16 05:19:49 -07004123TEST_F(EndToEndTest, RespectsNetworkState) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004124 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
4125 // down blocks until no more packets will be sent.
4126
4127 // Pacer will send from its packet list and then send required padding before
4128 // checking paused_ again. This should be enough for one round of pacing,
4129 // otherwise increase.
4130 static const int kNumAcceptedDowntimeRtp = 5;
4131 // A single RTCP may be in the pipeline.
4132 static const int kNumAcceptedDowntimeRtcp = 1;
4133 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
4134 public:
4135 NetworkStateTest()
4136 : EndToEndTest(kDefaultTimeoutMs),
4137 FakeEncoder(Clock::GetRealTimeClock()),
Peter Boström5811a392015-12-10 13:02:50 +01004138 encoded_frames_(false, false),
4139 packet_event_(false, false),
sprang867fb522015-08-03 04:38:41 -07004140 sender_call_(nullptr),
4141 receiver_call_(nullptr),
Jelena Marusiccd670222015-07-16 09:30:09 +02004142 sender_state_(kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004143 sender_rtp_(0),
4144 sender_rtcp_(0),
4145 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004146 down_frames_(0) {}
4147
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004148 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02004149 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004150 ++sender_rtp_;
Peter Boström5811a392015-12-10 13:02:50 +01004151 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004152 return SEND_PACKET;
4153 }
4154
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004155 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02004156 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004157 ++sender_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01004158 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004159 return SEND_PACKET;
4160 }
4161
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004162 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004163 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
4164 return SEND_PACKET;
4165 }
4166
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004167 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02004168 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004169 ++receiver_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01004170 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004171 return SEND_PACKET;
4172 }
4173
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004174 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004175 sender_call_ = sender_call;
4176 receiver_call_ = receiver_call;
4177 }
4178
stefanff483612015-12-21 03:14:00 -08004179 void ModifyVideoConfigs(
4180 VideoSendStream::Config* send_config,
4181 std::vector<VideoReceiveStream::Config>* receive_configs,
4182 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004183 send_config->encoder_settings.encoder = this;
4184 }
4185
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004186 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01004187 EXPECT_TRUE(encoded_frames_.Wait(kDefaultTimeoutMs))
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004188 << "No frames received by the encoder.";
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004189 // Wait for packets from both sender/receiver.
4190 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004191
skvlad7a43d252016-03-22 15:32:27 -07004192 // Sender-side network down for audio; there should be no effect on video
4193 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
4194 WaitForPacketsOrSilence(false, false);
4195
4196 // Receiver-side network down for audio; no change expected
4197 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
4198 WaitForPacketsOrSilence(false, false);
4199
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004200 // Sender-side network down.
skvlad7a43d252016-03-22 15:32:27 -07004201 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004202 {
Peter Boströmf2f82832015-05-01 13:00:41 +02004203 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004204 // After network goes down we shouldn't be encoding more frames.
Jelena Marusiccd670222015-07-16 09:30:09 +02004205 sender_state_ = kNetworkDown;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004206 }
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004207 // Wait for receiver-packets and no sender packets.
4208 WaitForPacketsOrSilence(true, false);
4209
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004210 // Receiver-side network down.
skvlad7a43d252016-03-22 15:32:27 -07004211 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
4212 WaitForPacketsOrSilence(true, true);
4213
4214 // Network up for audio for both sides; video is still not expected to
4215 // start
4216 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
4217 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004218 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004219
4220 // Network back up again for both.
4221 {
Peter Boströmf2f82832015-05-01 13:00:41 +02004222 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004223 // It's OK to encode frames again, as we're about to bring up the
4224 // network.
Jelena Marusiccd670222015-07-16 09:30:09 +02004225 sender_state_ = kNetworkUp;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004226 }
skvlad7a43d252016-03-22 15:32:27 -07004227 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
4228 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004229 WaitForPacketsOrSilence(false, false);
skvlad7a43d252016-03-22 15:32:27 -07004230
4231 // TODO(skvlad): add tests to verify that the audio streams are stopped
4232 // when the network goes down for audio once the workaround in
4233 // paced_sender.cc is removed.
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004234 }
4235
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07004236 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004237 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07004238 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004239 {
Peter Boströmf2f82832015-05-01 13:00:41 +02004240 rtc::CritScope lock(&test_crit_);
Jelena Marusiccd670222015-07-16 09:30:09 +02004241 if (sender_state_ == kNetworkDown) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004242 ++down_frames_;
4243 EXPECT_LE(down_frames_, 1)
4244 << "Encoding more than one frame while network is down.";
4245 if (down_frames_ > 1)
Peter Boström5811a392015-12-10 13:02:50 +01004246 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004247 } else {
Peter Boström5811a392015-12-10 13:02:50 +01004248 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004249 }
4250 }
4251 return test::FakeEncoder::Encode(
4252 input_image, codec_specific_info, frame_types);
4253 }
4254
4255 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004256 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
4257 int64_t initial_time_ms = clock_->TimeInMilliseconds();
4258 int initial_sender_rtp;
4259 int initial_sender_rtcp;
4260 int initial_receiver_rtcp;
4261 {
Peter Boströmf2f82832015-05-01 13:00:41 +02004262 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004263 initial_sender_rtp = sender_rtp_;
4264 initial_sender_rtcp = sender_rtcp_;
4265 initial_receiver_rtcp = receiver_rtcp_;
4266 }
4267 bool sender_done = false;
4268 bool receiver_done = false;
mflodmand1590b22015-12-09 07:07:59 -08004269 while (!sender_done || !receiver_done) {
Peter Boström5811a392015-12-10 13:02:50 +01004270 packet_event_.Wait(kSilenceTimeoutMs);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004271 int64_t time_now_ms = clock_->TimeInMilliseconds();
Peter Boströmf2f82832015-05-01 13:00:41 +02004272 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004273 if (sender_down) {
4274 ASSERT_LE(sender_rtp_ - initial_sender_rtp, kNumAcceptedDowntimeRtp)
4275 << "RTP sent during sender-side downtime.";
4276 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
4277 kNumAcceptedDowntimeRtcp)
4278 << "RTCP sent during sender-side downtime.";
4279 if (time_now_ms - initial_time_ms >=
4280 static_cast<int64_t>(kSilenceTimeoutMs)) {
4281 sender_done = true;
4282 }
4283 } else {
skvlad7a43d252016-03-22 15:32:27 -07004284 if (sender_rtp_ > initial_sender_rtp + kNumAcceptedDowntimeRtp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004285 sender_done = true;
4286 }
4287 if (receiver_down) {
4288 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
4289 kNumAcceptedDowntimeRtcp)
4290 << "RTCP sent during receiver-side downtime.";
4291 if (time_now_ms - initial_time_ms >=
4292 static_cast<int64_t>(kSilenceTimeoutMs)) {
4293 receiver_done = true;
4294 }
4295 } else {
skvlad7a43d252016-03-22 15:32:27 -07004296 if (receiver_rtcp_ > initial_receiver_rtcp + kNumAcceptedDowntimeRtcp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004297 receiver_done = true;
4298 }
4299 }
4300 }
4301
Peter Boströmf2f82832015-05-01 13:00:41 +02004302 rtc::CriticalSection test_crit_;
Peter Boström5811a392015-12-10 13:02:50 +01004303 rtc::Event encoded_frames_;
4304 rtc::Event packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004305 Call* sender_call_;
4306 Call* receiver_call_;
Jelena Marusiccd670222015-07-16 09:30:09 +02004307 NetworkState sender_state_ GUARDED_BY(test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004308 int sender_rtp_ GUARDED_BY(test_crit_);
4309 int sender_rtcp_ GUARDED_BY(test_crit_);
4310 int receiver_rtcp_ GUARDED_BY(test_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004311 int down_frames_ GUARDED_BY(test_crit_);
4312 } test;
4313
stefane74eef12016-01-08 06:47:13 -08004314 RunBaseTest(&test);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004315}
4316
philipel277a8b52017-03-16 05:19:49 -07004317TEST_F(EndToEndTest, CallReportsRttForSender) {
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004318 static const int kSendDelayMs = 30;
4319 static const int kReceiveDelayMs = 70;
philipel4fb651d2017-04-10 03:54:05 -07004320 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
solenberg4fbae2b2015-08-28 04:07:10 -07004321
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004322 FakeNetworkPipe::Config config;
4323 config.queue_delay_ms = kSendDelayMs;
minyue20c84cc2017-04-10 16:57:57 -07004324 test::DirectTransport sender_transport(config, sender_call_.get(),
4325 payload_type_map_);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004326 config.queue_delay_ms = kReceiveDelayMs;
minyue20c84cc2017-04-10 16:57:57 -07004327 test::DirectTransport receiver_transport(config, receiver_call_.get(),
4328 payload_type_map_);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004329 sender_transport.SetReceiver(receiver_call_->Receiver());
4330 receiver_transport.SetReceiver(sender_call_->Receiver());
4331
brandtr841de6a2016-11-15 07:10:52 -08004332 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07004333 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004334
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004335 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07004336 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
4337 kDefaultHeight);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004338 Start();
4339
4340 int64_t start_time_ms = clock_->TimeInMilliseconds();
4341 while (true) {
4342 Call::Stats stats = sender_call_->GetStats();
4343 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
4344 clock_->TimeInMilliseconds())
4345 << "No RTT stats before timeout!";
4346 if (stats.rtt_ms != -1) {
Danil Chapovalov10e8f8e2016-09-07 15:05:29 +02004347 // To avoid failures caused by rounding or minor ntp clock adjustments,
4348 // relax expectation by 1ms.
4349 constexpr int kAllowedErrorMs = 1;
4350 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs - kAllowedErrorMs);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004351 break;
4352 }
4353 SleepMs(10);
4354 }
4355
philipel266f0a42016-11-28 08:49:07 -08004356 sender_transport.StopSending();
4357 receiver_transport.StopSending();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004358 Stop();
4359 DestroyStreams();
philipel266f0a42016-11-28 08:49:07 -08004360 DestroyCalls();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004361}
4362
skvlad7a43d252016-03-22 15:32:27 -07004363void EndToEndTest::VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004364 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -07004365 VideoEncoder* encoder,
4366 Transport* transport) {
philipel4fb651d2017-04-10 03:54:05 -07004367 CreateSenderCall(Call::Config(event_log_.get()));
Sergey Ulanove2b15012016-11-22 16:08:30 -08004368 sender_call_->SignalChannelNetworkState(network_to_bring_up, kNetworkUp);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004369
brandtr841de6a2016-11-15 07:10:52 -08004370 CreateSendConfig(1, 0, 0, transport);
skvlad7a43d252016-03-22 15:32:27 -07004371 video_send_config_.encoder_settings.encoder = encoder;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004372 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07004373 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
4374 kDefaultHeight);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004375
4376 Start();
4377 SleepMs(kSilenceTimeoutMs);
4378 Stop();
4379
4380 DestroyStreams();
4381}
4382
skvlad7a43d252016-03-22 15:32:27 -07004383void EndToEndTest::VerifyNewVideoReceiveStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004384 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -07004385 Transport* transport) {
philipel4fb651d2017-04-10 03:54:05 -07004386 Call::Config config(event_log_.get());
skvlad11a9cbf2016-10-07 11:53:05 -07004387 CreateCalls(config, config);
Sergey Ulanove2b15012016-11-22 16:08:30 -08004388 receiver_call_->SignalChannelNetworkState(network_to_bring_up, kNetworkUp);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004389
minyue20c84cc2017-04-10 16:57:57 -07004390 test::DirectTransport sender_transport(sender_call_.get(), payload_type_map_);
solenberg4fbae2b2015-08-28 04:07:10 -07004391 sender_transport.SetReceiver(receiver_call_->Receiver());
brandtr841de6a2016-11-15 07:10:52 -08004392 CreateSendConfig(1, 0, 0, &sender_transport);
skvlad7a43d252016-03-22 15:32:27 -07004393 CreateMatchingReceiveConfigs(transport);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004394 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07004395 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
4396 kDefaultHeight);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004397
4398 Start();
4399 SleepMs(kSilenceTimeoutMs);
4400 Stop();
4401
4402 sender_transport.StopSending();
4403
4404 DestroyStreams();
4405}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00004406
philipel277a8b52017-03-16 05:19:49 -07004407TEST_F(EndToEndTest, NewVideoSendStreamsRespectVideoNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004408 class UnusedEncoder : public test::FakeEncoder {
4409 public:
4410 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
perkjfea93092016-05-14 00:58:48 -07004411
4412 int32_t InitEncode(const VideoCodec* config,
4413 int32_t number_of_cores,
4414 size_t max_payload_size) override {
4415 EXPECT_GT(config->startBitrate, 0u);
4416 return 0;
4417 }
skvlad7a43d252016-03-22 15:32:27 -07004418 int32_t Encode(const VideoFrame& input_image,
4419 const CodecSpecificInfo* codec_specific_info,
4420 const std::vector<FrameType>* frame_types) override {
4421 ADD_FAILURE() << "Unexpected frame encode.";
4422 return test::FakeEncoder::Encode(input_image, codec_specific_info,
4423 frame_types);
4424 }
4425 };
4426
4427 UnusedEncoder unused_encoder;
4428 UnusedTransport unused_transport;
4429 VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004430 MediaType::AUDIO, &unused_encoder, &unused_transport);
skvlad7a43d252016-03-22 15:32:27 -07004431}
4432
philipel277a8b52017-03-16 05:19:49 -07004433TEST_F(EndToEndTest, NewVideoSendStreamsIgnoreAudioNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004434 class RequiredEncoder : public test::FakeEncoder {
4435 public:
4436 RequiredEncoder()
4437 : FakeEncoder(Clock::GetRealTimeClock()), encoded_frame_(false) {}
4438 ~RequiredEncoder() {
4439 if (!encoded_frame_) {
4440 ADD_FAILURE() << "Didn't encode an expected frame";
4441 }
4442 }
4443 int32_t Encode(const VideoFrame& input_image,
4444 const CodecSpecificInfo* codec_specific_info,
4445 const std::vector<FrameType>* frame_types) override {
4446 encoded_frame_ = true;
4447 return test::FakeEncoder::Encode(input_image, codec_specific_info,
4448 frame_types);
4449 }
4450
4451 private:
4452 bool encoded_frame_;
4453 };
4454
4455 RequiredTransport required_transport(true /*rtp*/, false /*rtcp*/);
4456 RequiredEncoder required_encoder;
4457 VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004458 MediaType::VIDEO, &required_encoder, &required_transport);
skvlad7a43d252016-03-22 15:32:27 -07004459}
4460
philipel277a8b52017-03-16 05:19:49 -07004461TEST_F(EndToEndTest, NewVideoReceiveStreamsRespectVideoNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004462 UnusedTransport transport;
Sergey Ulanove2b15012016-11-22 16:08:30 -08004463 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::AUDIO, &transport);
skvlad7a43d252016-03-22 15:32:27 -07004464}
4465
philipel277a8b52017-03-16 05:19:49 -07004466TEST_F(EndToEndTest, NewVideoReceiveStreamsIgnoreAudioNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004467 RequiredTransport transport(false /*rtp*/, true /*rtcp*/);
Sergey Ulanove2b15012016-11-22 16:08:30 -08004468 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::VIDEO, &transport);
skvlad7a43d252016-03-22 15:32:27 -07004469}
4470
Peter Boströmd7da1202015-06-05 14:09:38 +02004471void VerifyEmptyNackConfig(const NackConfig& config) {
4472 EXPECT_EQ(0, config.rtp_history_ms)
4473 << "Enabling NACK requires rtcp-fb: nack negotiation.";
4474}
4475
brandtrb5f2c3f2016-10-04 23:28:39 -07004476void VerifyEmptyUlpfecConfig(const UlpfecConfig& config) {
Peter Boströmd7da1202015-06-05 14:09:38 +02004477 EXPECT_EQ(-1, config.ulpfec_payload_type)
brandtr535830e2016-10-31 03:45:58 -07004478 << "Enabling ULPFEC requires rtpmap: ulpfec negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02004479 EXPECT_EQ(-1, config.red_payload_type)
brandtr535830e2016-10-31 03:45:58 -07004480 << "Enabling ULPFEC requires rtpmap: red negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02004481 EXPECT_EQ(-1, config.red_rtx_payload_type)
brandtr535830e2016-10-31 03:45:58 -07004482 << "Enabling RTX in ULPFEC requires rtpmap: rtx negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02004483}
4484
brandtr3d200bd2017-01-16 06:59:19 -08004485void VerifyEmptyFlexfecConfig(
4486 const VideoSendStream::Config::Rtp::Flexfec& config) {
4487 EXPECT_EQ(-1, config.payload_type)
brandtr1e3dfbf2016-11-16 22:45:19 -08004488 << "Enabling FlexFEC requires rtpmap: flexfec negotiation.";
brandtr3d200bd2017-01-16 06:59:19 -08004489 EXPECT_EQ(0U, config.ssrc)
brandtr1cfbd602016-12-08 04:17:53 -08004490 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
brandtr1e3dfbf2016-11-16 22:45:19 -08004491 EXPECT_TRUE(config.protected_media_ssrcs.empty())
4492 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
4493}
4494
philipel277a8b52017-03-16 05:19:49 -07004495TEST_F(EndToEndTest, VerifyDefaultSendConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07004496 VideoSendStream::Config default_send_config(nullptr);
Peter Boströmd7da1202015-06-05 14:09:38 +02004497 EXPECT_EQ(0, default_send_config.rtp.nack.rtp_history_ms)
4498 << "Enabling NACK require rtcp-fb: nack negotiation.";
4499 EXPECT_TRUE(default_send_config.rtp.rtx.ssrcs.empty())
4500 << "Enabling RTX requires rtpmap: rtx negotiation.";
4501 EXPECT_TRUE(default_send_config.rtp.extensions.empty())
4502 << "Enabling RTP extensions require negotiation.";
4503
4504 VerifyEmptyNackConfig(default_send_config.rtp.nack);
brandtrb5f2c3f2016-10-04 23:28:39 -07004505 VerifyEmptyUlpfecConfig(default_send_config.rtp.ulpfec);
brandtr1e3dfbf2016-11-16 22:45:19 -08004506 VerifyEmptyFlexfecConfig(default_send_config.rtp.flexfec);
Peter Boströmd7da1202015-06-05 14:09:38 +02004507}
4508
philipel277a8b52017-03-16 05:19:49 -07004509TEST_F(EndToEndTest, VerifyDefaultVideoReceiveConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07004510 VideoReceiveStream::Config default_receive_config(nullptr);
pbosda903ea2015-10-02 02:36:56 -07004511 EXPECT_EQ(RtcpMode::kCompound, default_receive_config.rtp.rtcp_mode)
Peter Boströmd7da1202015-06-05 14:09:38 +02004512 << "Reduced-size RTCP require rtcp-rsize to be negotiated.";
4513 EXPECT_FALSE(default_receive_config.rtp.remb)
4514 << "REMB require rtcp-fb: goog-remb to be negotiated.";
4515 EXPECT_FALSE(
4516 default_receive_config.rtp.rtcp_xr.receiver_reference_time_report)
4517 << "RTCP XR settings require rtcp-xr to be negotiated.";
brandtr14742122017-01-27 04:53:07 -08004518 EXPECT_EQ(0U, default_receive_config.rtp.rtx_ssrc)
4519 << "Enabling RTX requires ssrc-group: FID negotiation";
4520 EXPECT_TRUE(default_receive_config.rtp.rtx_payload_types.empty())
Peter Boströmd7da1202015-06-05 14:09:38 +02004521 << "Enabling RTX requires rtpmap: rtx negotiation.";
4522 EXPECT_TRUE(default_receive_config.rtp.extensions.empty())
4523 << "Enabling RTP extensions require negotiation.";
4524
4525 VerifyEmptyNackConfig(default_receive_config.rtp.nack);
brandtrb5f2c3f2016-10-04 23:28:39 -07004526 VerifyEmptyUlpfecConfig(default_receive_config.rtp.ulpfec);
Peter Boströmd7da1202015-06-05 14:09:38 +02004527}
4528
philipel277a8b52017-03-16 05:19:49 -07004529TEST_F(EndToEndTest, VerifyDefaultFlexfecReceiveConfigParameters) {
brandtr8313a6f2017-01-13 07:41:19 -08004530 test::NullTransport rtcp_send_transport;
4531 FlexfecReceiveStream::Config default_receive_config(&rtcp_send_transport);
brandtr1cfbd602016-12-08 04:17:53 -08004532 EXPECT_EQ(-1, default_receive_config.payload_type)
4533 << "Enabling FlexFEC requires rtpmap: flexfec negotiation.";
4534 EXPECT_EQ(0U, default_receive_config.remote_ssrc)
4535 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
4536 EXPECT_TRUE(default_receive_config.protected_media_ssrcs.empty())
4537 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
brandtr1e3dfbf2016-11-16 22:45:19 -08004538}
4539
philipel277a8b52017-03-16 05:19:49 -07004540TEST_F(EndToEndTest, TransportSeqNumOnAudioAndVideo) {
danilchap4336d732017-03-03 06:21:54 -08004541 static constexpr int kExtensionId = 8;
4542 static constexpr size_t kMinPacketsToWaitFor = 50;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004543 class TransportSequenceNumberTest : public test::EndToEndTest {
4544 public:
4545 TransportSequenceNumberTest()
4546 : EndToEndTest(kDefaultTimeoutMs),
4547 video_observed_(false),
4548 audio_observed_(false) {
4549 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
4550 kExtensionId);
4551 }
4552
4553 size_t GetNumVideoStreams() const override { return 1; }
4554 size_t GetNumAudioStreams() const override { return 1; }
4555
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004556 void ModifyAudioConfigs(
4557 AudioSendStream::Config* send_config,
4558 std::vector<AudioReceiveStream::Config>* receive_configs) override {
4559 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07004560 send_config->rtp.extensions.push_back(RtpExtension(
4561 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004562 (*receive_configs)[0].rtp.extensions.clear();
4563 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
4564 }
4565
4566 Action OnSendRtp(const uint8_t* packet, size_t length) override {
4567 RTPHeader header;
4568 EXPECT_TRUE(parser_->Parse(packet, length, &header));
4569 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
4570 // Unwrap packet id and verify uniqueness.
4571 int64_t packet_id =
4572 unwrapper_.Unwrap(header.extension.transportSequenceNumber);
4573 EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
4574
4575 if (header.ssrc == kVideoSendSsrcs[0])
4576 video_observed_ = true;
4577 if (header.ssrc == kAudioSendSsrc)
4578 audio_observed_ = true;
4579 if (audio_observed_ && video_observed_ &&
danilchap4336d732017-03-03 06:21:54 -08004580 received_packet_ids_.size() >= kMinPacketsToWaitFor) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004581 size_t packet_id_range =
4582 *received_packet_ids_.rbegin() - *received_packet_ids_.begin() + 1;
4583 EXPECT_EQ(received_packet_ids_.size(), packet_id_range);
4584 observation_complete_.Set();
4585 }
4586 return SEND_PACKET;
4587 }
4588
4589 void PerformTest() override {
4590 EXPECT_TRUE(Wait()) << "Timed out while waiting for audio and video "
4591 "packets with transport sequence number.";
4592 }
4593
danilchap4336d732017-03-03 06:21:54 -08004594 void ExpectSuccessful() {
4595 EXPECT_TRUE(video_observed_);
4596 EXPECT_TRUE(audio_observed_);
4597 EXPECT_GE(received_packet_ids_.size(), kMinPacketsToWaitFor);
4598 }
4599
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004600 private:
4601 bool video_observed_;
4602 bool audio_observed_;
4603 SequenceNumberUnwrapper unwrapper_;
4604 std::set<int64_t> received_packet_ids_;
4605 } test;
4606
stefane74eef12016-01-08 06:47:13 -08004607 RunBaseTest(&test);
danilchap4336d732017-03-03 06:21:54 -08004608 // Double check conditions for successful test to produce better error
4609 // message when the test fail.
4610 test.ExpectSuccessful();
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004611}
palmkviste75f2042016-09-28 06:19:48 -07004612
4613class EndToEndLogTest : public EndToEndTest {
4614 void SetUp() { paths_.clear(); }
4615 void TearDown() {
4616 for (const auto& path : paths_) {
4617 rtc::RemoveFile(path);
4618 }
4619 }
4620
4621 public:
4622 int AddFile() {
4623 paths_.push_back(test::TempFilename(test::OutputPath(), "test_file"));
4624 return static_cast<int>(paths_.size()) - 1;
4625 }
4626
4627 rtc::PlatformFile OpenFile(int idx) {
4628 return rtc::OpenPlatformFile(paths_[idx]);
4629 }
4630
4631 void LogSend(bool open) {
4632 if (open) {
4633 video_send_stream_->EnableEncodedFrameRecording(
4634 std::vector<rtc::PlatformFile>(1, OpenFile(AddFile())), 0);
4635 } else {
4636 video_send_stream_->DisableEncodedFrameRecording();
4637 }
4638 }
4639 void LogReceive(bool open) {
4640 if (open) {
4641 video_receive_streams_[0]->EnableEncodedFrameRecording(
4642 OpenFile(AddFile()), 0);
4643 } else {
4644 video_receive_streams_[0]->DisableEncodedFrameRecording();
4645 }
4646 }
4647
4648 std::vector<std::string> paths_;
4649};
4650
philipel277a8b52017-03-16 05:19:49 -07004651TEST_F(EndToEndLogTest, LogsEncodedFramesWhenRequested) {
palmkviste75f2042016-09-28 06:19:48 -07004652 static const int kNumFramesToRecord = 10;
4653 class LogEncodingObserver : public test::EndToEndTest,
4654 public EncodedFrameObserver {
4655 public:
4656 explicit LogEncodingObserver(EndToEndLogTest* fixture)
4657 : EndToEndTest(kDefaultTimeoutMs),
4658 fixture_(fixture),
4659 recorded_frames_(0) {}
4660
4661 void PerformTest() override {
4662 fixture_->LogSend(true);
4663 fixture_->LogReceive(true);
4664 ASSERT_TRUE(Wait()) << "Timed out while waiting for frame logging.";
4665 }
4666
4667 void ModifyVideoConfigs(
4668 VideoSendStream::Config* send_config,
4669 std::vector<VideoReceiveStream::Config>* receive_configs,
4670 VideoEncoderConfig* encoder_config) override {
magjed509e4fe2016-11-18 01:34:11 -08004671 encoder_.reset(VP8Encoder::Create());
palmkviste75f2042016-09-28 06:19:48 -07004672 decoder_.reset(VP8Decoder::Create());
4673
4674 send_config->post_encode_callback = this;
4675 send_config->encoder_settings.payload_name = "VP8";
4676 send_config->encoder_settings.encoder = encoder_.get();
4677
4678 (*receive_configs)[0].decoders.resize(1);
4679 (*receive_configs)[0].decoders[0].payload_type =
4680 send_config->encoder_settings.payload_type;
4681 (*receive_configs)[0].decoders[0].payload_name =
4682 send_config->encoder_settings.payload_name;
4683 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
4684 }
4685
4686 void EncodedFrameCallback(const EncodedFrame& encoded_frame) override {
4687 rtc::CritScope lock(&crit_);
4688 if (recorded_frames_++ > kNumFramesToRecord) {
4689 fixture_->LogSend(false);
4690 fixture_->LogReceive(false);
4691 rtc::File send_file(fixture_->OpenFile(0));
4692 rtc::File receive_file(fixture_->OpenFile(1));
4693 uint8_t out[100];
4694 // If logging has worked correctly neither file should be empty, i.e.
4695 // we should be able to read something from them.
4696 EXPECT_LT(0u, send_file.Read(out, 100));
4697 EXPECT_LT(0u, receive_file.Read(out, 100));
4698 observation_complete_.Set();
4699 }
4700 }
4701
4702 private:
4703 EndToEndLogTest* const fixture_;
4704 std::unique_ptr<VideoEncoder> encoder_;
4705 std::unique_ptr<VideoDecoder> decoder_;
4706 rtc::CriticalSection crit_;
4707 int recorded_frames_ GUARDED_BY(crit_);
4708 } test(this);
4709
4710 RunBaseTest(&test);
4711}
4712
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00004713} // namespace webrtc