blob: f6a74fbc112a255c07ec58d792c8a390084e4c0c [file] [log] [blame]
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001/*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000010#include <algorithm>
danilchap5c35cf92016-02-03 14:14:49 -080011#include <list>
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000012#include <map>
kwiberg27f982b2016-03-01 11:52:33 -080013#include <memory>
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000014#include <sstream>
15#include <string>
kwiberg4a206a92016-03-31 10:24:26 -070016#include <vector>
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000017
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000018#include "webrtc/base/checks.h"
Erik Språng6b8d3552015-09-24 15:06:57 +020019#include "webrtc/base/event.h"
palmkviste75f2042016-09-28 06:19:48 -070020#include "webrtc/base/file.h"
Erik Språng737336d2016-07-29 12:59:36 +020021#include "webrtc/base/optional.h"
brandtr35364632016-12-09 06:51:29 -080022#include "webrtc/base/random.h"
Erik Språng737336d2016-07-29 12:59:36 +020023#include "webrtc/base/rate_limiter.h"
ossuf515ab82016-12-07 04:52:58 -080024#include "webrtc/call/call.h"
pbosa96b60b2016-04-18 21:12:48 -070025#include "webrtc/common_video/include/frame_callback.h"
skvlad11a9cbf2016-10-07 11:53:05 -070026#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
sakal55d932b2016-09-30 06:19:08 -070027#include "webrtc/media/base/fakevideorenderer.h"
danilchap5c35cf92016-02-03 14:14:49 -080028#include "webrtc/modules/include/module_common_types.h"
stefan32f81542016-01-20 07:13:58 -080029#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
sprang861c55e2015-10-16 10:01:21 -070030#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
Erik Språng737336d2016-07-29 12:59:36 +020031#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h"
Danil Chapovalov70ffead2016-07-20 15:26:59 +020032#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.h"
sprangcd349d92016-07-13 09:11:28 -070033#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
hbosbab934b2016-01-27 01:36:03 -080034#include "webrtc/modules/video_coding/codecs/h264/include/h264.h"
marpan@webrtc.org5b883172014-11-01 06:10:48 +000035#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
36#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010037#include "webrtc/modules/video_coding/include/video_coding_defines.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010038#include "webrtc/system_wrappers/include/metrics.h"
asapersson01d70a32016-05-20 06:29:46 -070039#include "webrtc/system_wrappers/include/metrics_default.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010040#include "webrtc/system_wrappers/include/sleep.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000041#include "webrtc/test/call_test.h"
42#include "webrtc/test/direct_transport.h"
43#include "webrtc/test/encoder_settings.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000044#include "webrtc/test/fake_decoder.h"
45#include "webrtc/test/fake_encoder.h"
philipel266f0a42016-11-28 08:49:07 -080046#include "webrtc/test/field_trial.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000047#include "webrtc/test/frame_generator.h"
48#include "webrtc/test/frame_generator_capturer.h"
kwibergac9f8762016-09-30 22:29:43 -070049#include "webrtc/test/gtest.h"
philipel266f0a42016-11-28 08:49:07 -080050#include "webrtc/test/gmock.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000051#include "webrtc/test/null_transport.h"
asapersson@webrtc.org37c05592015-01-28 13:58:27 +000052#include "webrtc/test/rtcp_packet_parser.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000053#include "webrtc/test/rtp_rtcp_observer.h"
54#include "webrtc/test/testsupport/fileutils.h"
55#include "webrtc/test/testsupport/perf_test.h"
charujainbf6a45b2016-11-03 04:21:42 -070056#include "webrtc/video/transport_adapter.h"
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +000057#include "webrtc/video_encoder.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000058
59namespace webrtc {
60
philipel266f0a42016-11-28 08:49:07 -080061namespace {
62const char new_jb_enabled[] = "WebRTC-NewVideoJitterBuffer/Enabled/";
63const char new_jb_disabled[] = "WebRTC-NewVideoJitterBuffer/Disabled/";
64} // anonymous namespace
65
Peter Boström5811a392015-12-10 13:02:50 +010066static const int kSilenceTimeoutMs = 2000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000067
philipel266f0a42016-11-28 08:49:07 -080068class EndToEndTest : public test::CallTest,
69 public ::testing::WithParamInterface<std::string> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000070 public:
philipel266f0a42016-11-28 08:49:07 -080071 EndToEndTest() : scoped_field_trial_(GetParam()) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000072
73 virtual ~EndToEndTest() {
stefanff483612015-12-21 03:14:00 -080074 EXPECT_EQ(nullptr, video_send_stream_);
75 EXPECT_TRUE(video_receive_streams_.empty());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000076 }
77
78 protected:
pbos2d566682015-09-28 09:59:31 -070079 class UnusedTransport : public Transport {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000080 private:
stefan1d8a5062015-10-02 03:39:33 -070081 bool SendRtp(const uint8_t* packet,
82 size_t length,
83 const PacketOptions& options) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000084 ADD_FAILURE() << "Unexpected RTP sent.";
85 return false;
86 }
87
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000088 bool SendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000089 ADD_FAILURE() << "Unexpected RTCP sent.";
90 return false;
91 }
92 };
93
skvlad7a43d252016-03-22 15:32:27 -070094 class RequiredTransport : public Transport {
95 public:
96 RequiredTransport(bool rtp_required, bool rtcp_required)
97 : need_rtp_(rtp_required), need_rtcp_(rtcp_required) {}
98 ~RequiredTransport() {
99 if (need_rtp_) {
100 ADD_FAILURE() << "Expected RTP packet not sent.";
101 }
102 if (need_rtcp_) {
103 ADD_FAILURE() << "Expected RTCP packet not sent.";
104 }
105 }
106
107 private:
108 bool SendRtp(const uint8_t* packet,
109 size_t length,
110 const PacketOptions& options) override {
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700111 rtc::CritScope lock(&crit_);
skvlad7a43d252016-03-22 15:32:27 -0700112 need_rtp_ = false;
113 return true;
114 }
115
116 bool SendRtcp(const uint8_t* packet, size_t length) override {
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700117 rtc::CritScope lock(&crit_);
skvlad7a43d252016-03-22 15:32:27 -0700118 need_rtcp_ = false;
119 return true;
120 }
121 bool need_rtp_;
122 bool need_rtcp_;
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700123 rtc::CriticalSection crit_;
skvlad7a43d252016-03-22 15:32:27 -0700124 };
125
Peter Boström39593972016-02-15 11:27:15 +0100126 void DecodesRetransmittedFrame(bool enable_rtx, bool enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000127 void ReceivesPliAndRecovers(int rtp_history_ms);
pbosda903ea2015-10-02 02:36:56 -0700128 void RespectsRtcpMode(RtcpMode rtcp_mode);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000129 void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200130 void TestRtpStatePreservation(bool use_rtx, bool provoke_rtcpsr_before_rtp);
sprangb4a1ae52015-12-03 08:10:08 -0800131 void VerifyHistogramStats(bool use_rtx, bool use_red, bool screenshare);
skvlad7a43d252016-03-22 15:32:27 -0700132 void VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -0800133 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -0700134 VideoEncoder* encoder,
135 Transport* transport);
136 void VerifyNewVideoReceiveStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -0800137 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -0700138 Transport* transport);
philipel266f0a42016-11-28 08:49:07 -0800139 test::ScopedFieldTrials scoped_field_trial_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000140};
141
philipel266f0a42016-11-28 08:49:07 -0800142INSTANTIATE_TEST_CASE_P(TestWithNewVideoJitterBuffer,
143 EndToEndTest,
144 ::testing::Values(new_jb_enabled, new_jb_disabled));
145
146TEST_P(EndToEndTest, ReceiverCanBeStartedTwice) {
skvlad11a9cbf2016-10-07 11:53:05 -0700147 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000148
solenberg4fbae2b2015-08-28 04:07:10 -0700149 test::NullTransport transport;
brandtr841de6a2016-11-15 07:10:52 -0800150 CreateSendConfig(1, 0, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700151 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000152
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100153 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000154
stefanff483612015-12-21 03:14:00 -0800155 video_receive_streams_[0]->Start();
156 video_receive_streams_[0]->Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000157
158 DestroyStreams();
159}
160
philipel266f0a42016-11-28 08:49:07 -0800161TEST_P(EndToEndTest, ReceiverCanBeStoppedTwice) {
skvlad11a9cbf2016-10-07 11:53:05 -0700162 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000163
solenberg4fbae2b2015-08-28 04:07:10 -0700164 test::NullTransport transport;
brandtr841de6a2016-11-15 07:10:52 -0800165 CreateSendConfig(1, 0, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700166 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000167
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100168 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000169
stefanff483612015-12-21 03:14:00 -0800170 video_receive_streams_[0]->Stop();
171 video_receive_streams_[0]->Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000172
173 DestroyStreams();
174}
175
philipel266f0a42016-11-28 08:49:07 -0800176TEST_P(EndToEndTest, ReceiverCanBeStoppedAndRestarted) {
sprang113bdca2016-10-11 03:10:10 -0700177 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
178
179 test::NullTransport transport;
brandtr841de6a2016-11-15 07:10:52 -0800180 CreateSendConfig(1, 0, 0, &transport);
sprang113bdca2016-10-11 03:10:10 -0700181 CreateMatchingReceiveConfigs(&transport);
182
183 CreateVideoStreams();
184
185 video_receive_streams_[0]->Stop();
186 video_receive_streams_[0]->Start();
187 video_receive_streams_[0]->Stop();
188
189 DestroyStreams();
190}
191
philipel266f0a42016-11-28 08:49:07 -0800192TEST_P(EndToEndTest, RendersSingleDelayedFrame) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000193 static const int kWidth = 320;
194 static const int kHeight = 240;
195 // This constant is chosen to be higher than the timeout in the video_render
196 // module. This makes sure that frames aren't dropped if there are no other
197 // frames in the queue.
nisse76bc8e82017-02-07 09:37:41 -0800198 static const int kRenderDelayMs = 1000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000199
nisse7ade7b32016-03-23 04:48:10 -0700200 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000201 public:
Peter Boström5811a392015-12-10 13:02:50 +0100202 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000203
nisse76bc8e82017-02-07 09:37:41 -0800204 void OnFrame(const VideoFrame& video_frame) override {
205 SleepMs(kRenderDelayMs);
206 event_.Set();
207 }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000208
Peter Boström5811a392015-12-10 13:02:50 +0100209 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000210
Peter Boström5811a392015-12-10 13:02:50 +0100211 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000212 } renderer;
213
skvlad11a9cbf2016-10-07 11:53:05 -0700214 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -0700215
stefanf116bd02015-10-27 08:29:42 -0700216 test::DirectTransport sender_transport(sender_call_.get());
217 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000218 sender_transport.SetReceiver(receiver_call_->Receiver());
219 receiver_transport.SetReceiver(sender_call_->Receiver());
220
brandtr841de6a2016-11-15 07:10:52 -0800221 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700222 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000223
stefanff483612015-12-21 03:14:00 -0800224 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000225
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100226 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000227 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000228
229 // Create frames that are smaller than the send width/height, this is done to
230 // check that the callbacks are done after processing video.
kwiberg27f982b2016-03-01 11:52:33 -0800231 std::unique_ptr<test::FrameGenerator> frame_generator(
perkja8ba1952017-02-27 06:52:10 -0800232 test::FrameGenerator::CreateSquareGenerator(kWidth, kHeight));
perkja49cbd32016-09-16 07:53:41 -0700233 test::FrameForwarder frame_forwarder;
perkj803d97f2016-11-01 11:45:46 -0700234 video_send_stream_->SetSource(
235 &frame_forwarder, VideoSendStream::DegradationPreference::kBalanced);
perkja49cbd32016-09-16 07:53:41 -0700236
237 frame_forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
Peter Boström5811a392015-12-10 13:02:50 +0100238 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000239 << "Timed out while waiting for the frame to render.";
240
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000241 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000242
243 sender_transport.StopSending();
244 receiver_transport.StopSending();
245
246 DestroyStreams();
247}
248
philipel266f0a42016-11-28 08:49:07 -0800249TEST_P(EndToEndTest, TransmitsFirstFrame) {
nisse7ade7b32016-03-23 04:48:10 -0700250 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000251 public:
Peter Boström5811a392015-12-10 13:02:50 +0100252 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000253
nisseeb83a1a2016-03-21 01:27:56 -0700254 void OnFrame(const VideoFrame& video_frame) override { event_.Set(); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000255
Peter Boström5811a392015-12-10 13:02:50 +0100256 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000257
Peter Boström5811a392015-12-10 13:02:50 +0100258 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000259 } renderer;
260
skvlad11a9cbf2016-10-07 11:53:05 -0700261 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -0700262
stefanf116bd02015-10-27 08:29:42 -0700263 test::DirectTransport sender_transport(sender_call_.get());
264 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000265 sender_transport.SetReceiver(receiver_call_->Receiver());
266 receiver_transport.SetReceiver(sender_call_->Receiver());
267
brandtr841de6a2016-11-15 07:10:52 -0800268 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700269 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -0800270 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000271
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100272 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000273 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000274
kwiberg27f982b2016-03-01 11:52:33 -0800275 std::unique_ptr<test::FrameGenerator> frame_generator(
perkja8ba1952017-02-27 06:52:10 -0800276 test::FrameGenerator::CreateSquareGenerator(kDefaultWidth,
perkjfa10b552016-10-02 23:45:26 -0700277 kDefaultHeight));
perkja49cbd32016-09-16 07:53:41 -0700278 test::FrameForwarder frame_forwarder;
perkj803d97f2016-11-01 11:45:46 -0700279 video_send_stream_->SetSource(
280 &frame_forwarder, VideoSendStream::DegradationPreference::kBalanced);
perkja49cbd32016-09-16 07:53:41 -0700281 frame_forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000282
Peter Boström5811a392015-12-10 13:02:50 +0100283 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000284 << "Timed out while waiting for the frame to render.";
285
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000286 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000287
288 sender_transport.StopSending();
289 receiver_transport.StopSending();
290
291 DestroyStreams();
292}
293
Perba7dc722016-04-19 15:01:23 +0200294class CodecObserver : public test::EndToEndTest,
nisse7ade7b32016-03-23 04:48:10 -0700295 public rtc::VideoSinkInterface<VideoFrame> {
Perba7dc722016-04-19 15:01:23 +0200296 public:
297 CodecObserver(int no_frames_to_wait_for,
298 VideoRotation rotation_to_test,
299 const std::string& payload_name,
300 webrtc::VideoEncoder* encoder,
301 webrtc::VideoDecoder* decoder)
hta9aa96882016-12-06 05:36:03 -0800302 : EndToEndTest(4 * webrtc::EndToEndTest::kDefaultTimeoutMs),
303 // TODO(hta): This timeout (120 seconds) is excessive.
304 // https://bugs.webrtc.org/6830
Perba7dc722016-04-19 15:01:23 +0200305 no_frames_to_wait_for_(no_frames_to_wait_for),
306 expected_rotation_(rotation_to_test),
307 payload_name_(payload_name),
308 encoder_(encoder),
309 decoder_(decoder),
310 frame_counter_(0) {}
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000311
Perba7dc722016-04-19 15:01:23 +0200312 void PerformTest() override {
313 EXPECT_TRUE(Wait())
314 << "Timed out while waiting for enough frames to be decoded.";
315 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000316
Perba7dc722016-04-19 15:01:23 +0200317 void ModifyVideoConfigs(
318 VideoSendStream::Config* send_config,
319 std::vector<VideoReceiveStream::Config>* receive_configs,
320 VideoEncoderConfig* encoder_config) override {
321 send_config->encoder_settings.encoder = encoder_.get();
322 send_config->encoder_settings.payload_name = payload_name_;
323 send_config->encoder_settings.payload_type = 126;
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000324
Perba7dc722016-04-19 15:01:23 +0200325 (*receive_configs)[0].renderer = this;
326 (*receive_configs)[0].decoders.resize(1);
327 (*receive_configs)[0].decoders[0].payload_type =
328 send_config->encoder_settings.payload_type;
329 (*receive_configs)[0].decoders[0].payload_name =
330 send_config->encoder_settings.payload_name;
331 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
332 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000333
Perba7dc722016-04-19 15:01:23 +0200334 void OnFrame(const VideoFrame& video_frame) override {
335 EXPECT_EQ(expected_rotation_, video_frame.rotation());
336 if (++frame_counter_ == no_frames_to_wait_for_)
337 observation_complete_.Set();
338 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000339
Perba7dc722016-04-19 15:01:23 +0200340 void OnFrameGeneratorCapturerCreated(
341 test::FrameGeneratorCapturer* frame_generator_capturer) override {
342 frame_generator_capturer->SetFakeRotation(expected_rotation_);
343 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000344
Perba7dc722016-04-19 15:01:23 +0200345 private:
346 int no_frames_to_wait_for_;
347 VideoRotation expected_rotation_;
348 std::string payload_name_;
349 std::unique_ptr<webrtc::VideoEncoder> encoder_;
350 std::unique_ptr<webrtc::VideoDecoder> decoder_;
351 int frame_counter_;
352};
353
philipel266f0a42016-11-28 08:49:07 -0800354TEST_P(EndToEndTest, SendsAndReceivesVP8) {
355 CodecObserver test(5, kVideoRotation_0, "VP8", VP8Encoder::Create(),
356 VP8Decoder::Create());
357 RunBaseTest(&test);
358}
359
360TEST_P(EndToEndTest, SendsAndReceivesVP8Rotation90) {
magjed509e4fe2016-11-18 01:34:11 -0800361 CodecObserver test(5, kVideoRotation_90, "VP8", VP8Encoder::Create(),
Perba7dc722016-04-19 15:01:23 +0200362 VP8Decoder::Create());
363 RunBaseTest(&test);
364}
365
Peter Boström12996152016-05-14 02:03:18 +0200366#if !defined(RTC_DISABLE_VP9)
philipel266f0a42016-11-28 08:49:07 -0800367TEST_P(EndToEndTest, SendsAndReceivesVP9) {
magjed509e4fe2016-11-18 01:34:11 -0800368 CodecObserver test(500, kVideoRotation_0, "VP9", VP9Encoder::Create(),
Perba7dc722016-04-19 15:01:23 +0200369 VP9Decoder::Create());
370 RunBaseTest(&test);
371}
372
philipel266f0a42016-11-28 08:49:07 -0800373TEST_P(EndToEndTest, SendsAndReceivesVP9VideoRotation90) {
magjed509e4fe2016-11-18 01:34:11 -0800374 CodecObserver test(5, kVideoRotation_90, "VP9", VP9Encoder::Create(),
Perba7dc722016-04-19 15:01:23 +0200375 VP9Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800376 RunBaseTest(&test);
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000377}
Peter Boström12996152016-05-14 02:03:18 +0200378#endif // !defined(RTC_DISABLE_VP9)
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000379
brandtr445fb8f2016-11-14 04:11:23 -0800380#if defined(WEBRTC_USE_H264)
philipel266f0a42016-11-28 08:49:07 -0800381TEST_P(EndToEndTest, SendsAndReceivesH264) {
magjedceecea42016-11-28 07:20:21 -0800382 CodecObserver test(500, kVideoRotation_0, "H264",
383 H264Encoder::Create(cricket::VideoCodec("H264")),
Perba7dc722016-04-19 15:01:23 +0200384 H264Decoder::Create());
385 RunBaseTest(&test);
386}
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000387
philipel266f0a42016-11-28 08:49:07 -0800388TEST_P(EndToEndTest, SendsAndReceivesH264VideoRotation90) {
magjedceecea42016-11-28 07:20:21 -0800389 CodecObserver test(5, kVideoRotation_90, "H264",
390 H264Encoder::Create(cricket::VideoCodec("H264")),
Perba7dc722016-04-19 15:01:23 +0200391 H264Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800392 RunBaseTest(&test);
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000393}
hta9aa96882016-12-06 05:36:03 -0800394
395TEST_P(EndToEndTest, SendsAndReceivesH264PacketizationMode0) {
396 cricket::VideoCodec codec = cricket::VideoCodec("H264");
397 codec.SetParam(cricket::kH264FmtpPacketizationMode, "0");
398 CodecObserver test(500, kVideoRotation_0, "H264", H264Encoder::Create(codec),
399 H264Decoder::Create());
400 RunBaseTest(&test);
401}
402
403TEST_P(EndToEndTest, SendsAndReceivesH264PacketizationMode1) {
404 cricket::VideoCodec codec = cricket::VideoCodec("H264");
405 codec.SetParam(cricket::kH264FmtpPacketizationMode, "1");
406 CodecObserver test(500, kVideoRotation_0, "H264", H264Encoder::Create(codec),
407 H264Decoder::Create());
408 RunBaseTest(&test);
409}
410
brandtr445fb8f2016-11-14 04:11:23 -0800411#endif // defined(WEBRTC_USE_H264)
hbosbab934b2016-01-27 01:36:03 -0800412
philipel266f0a42016-11-28 08:49:07 -0800413TEST_P(EndToEndTest, ReceiverUsesLocalSsrc) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000414 class SyncRtcpObserver : public test::EndToEndTest {
415 public:
416 SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {}
417
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000418 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
danilchap3dc929e2016-11-02 08:21:59 -0700419 test::RtcpPacketParser parser;
420 EXPECT_TRUE(parser.Parse(packet, length));
421 EXPECT_EQ(kReceiverLocalVideoSsrc, parser.sender_ssrc());
Peter Boström5811a392015-12-10 13:02:50 +0100422 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000423
424 return SEND_PACKET;
425 }
426
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000427 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100428 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000429 << "Timed out while waiting for a receiver RTCP packet to be sent.";
430 }
431 } test;
432
stefane74eef12016-01-08 06:47:13 -0800433 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000434}
435
philipel266f0a42016-11-28 08:49:07 -0800436TEST_P(EndToEndTest, ReceivesAndRetransmitsNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000437 static const int kNumberOfNacksToObserve = 2;
438 static const int kLossBurstSize = 2;
439 static const int kPacketsBetweenLossBursts = 9;
440 class NackObserver : public test::EndToEndTest {
441 public:
442 NackObserver()
443 : EndToEndTest(kLongTimeoutMs),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000444 sent_rtp_packets_(0),
445 packets_left_to_drop_(0),
446 nacks_left_(kNumberOfNacksToObserve) {}
447
448 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000449 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700450 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000451 RTPHeader header;
Peter Boström03671cb2015-12-07 15:22:24 +0100452 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000453
454 // Never drop retransmitted packets.
455 if (dropped_packets_.find(header.sequenceNumber) !=
456 dropped_packets_.end()) {
457 retransmitted_packets_.insert(header.sequenceNumber);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000458 return SEND_PACKET;
459 }
460
philipel8054c7e2017-01-10 05:19:19 -0800461 if (nacks_left_ <= 0 &&
462 retransmitted_packets_.size() == dropped_packets_.size()) {
463 observation_complete_.Set();
464 }
465
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000466 ++sent_rtp_packets_;
467
468 // Enough NACKs received, stop dropping packets.
Stefan Holmer586b19b2015-09-18 11:14:31 +0200469 if (nacks_left_ <= 0)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000470 return SEND_PACKET;
471
472 // Check if it's time for a new loss burst.
473 if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
474 packets_left_to_drop_ = kLossBurstSize;
475
Stefan Holmer01b48882015-05-05 10:21:24 +0200476 // Never drop padding packets as those won't be retransmitted.
477 if (packets_left_to_drop_ > 0 && header.paddingLength == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000478 --packets_left_to_drop_;
479 dropped_packets_.insert(header.sequenceNumber);
480 return DROP_PACKET;
481 }
482
483 return SEND_PACKET;
484 }
485
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000486 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700487 rtc::CritScope lock(&crit_);
danilchap3dc929e2016-11-02 08:21:59 -0700488 test::RtcpPacketParser parser;
489 EXPECT_TRUE(parser.Parse(packet, length));
490 nacks_left_ -= parser.nack()->num_packets();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000491 return SEND_PACKET;
492 }
493
stefanff483612015-12-21 03:14:00 -0800494 void ModifyVideoConfigs(
495 VideoSendStream::Config* send_config,
496 std::vector<VideoReceiveStream::Config>* receive_configs,
497 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000498 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000499 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000500 }
501
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000502 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100503 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000504 << "Timed out waiting for packets to be NACKed, retransmitted and "
505 "rendered.";
506 }
507
stefanf116bd02015-10-27 08:29:42 -0700508 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000509 std::set<uint16_t> dropped_packets_;
510 std::set<uint16_t> retransmitted_packets_;
511 uint64_t sent_rtp_packets_;
512 int packets_left_to_drop_;
stefanf116bd02015-10-27 08:29:42 -0700513 int nacks_left_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000514 } test;
515
stefane74eef12016-01-08 06:47:13 -0800516 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000517}
518
philipel266f0a42016-11-28 08:49:07 -0800519TEST_P(EndToEndTest, ReceivesNackAndRetransmitsAudio) {
Erik Språng737336d2016-07-29 12:59:36 +0200520 class NackObserver : public test::EndToEndTest {
521 public:
522 NackObserver()
523 : EndToEndTest(kLongTimeoutMs),
524 local_ssrc_(0),
525 remote_ssrc_(0),
526 receive_transport_(nullptr) {}
527
528 private:
529 size_t GetNumVideoStreams() const override { return 0; }
530 size_t GetNumAudioStreams() const override { return 1; }
531
532 test::PacketTransport* CreateReceiveTransport() override {
533 test::PacketTransport* receive_transport = new test::PacketTransport(
534 nullptr, this, test::PacketTransport::kReceiver,
535 FakeNetworkPipe::Config());
536 receive_transport_ = receive_transport;
537 return receive_transport;
538 }
539
540 Action OnSendRtp(const uint8_t* packet, size_t length) override {
541 RTPHeader header;
542 EXPECT_TRUE(parser_->Parse(packet, length, &header));
543
544 if (!sequence_number_to_retransmit_) {
545 sequence_number_to_retransmit_ =
546 rtc::Optional<uint16_t>(header.sequenceNumber);
547
548 // Don't ask for retransmission straight away, may be deduped in pacer.
549 } else if (header.sequenceNumber == *sequence_number_to_retransmit_) {
550 observation_complete_.Set();
551 } else {
552 // Send a NACK as often as necessary until retransmission is received.
553 rtcp::Nack nack;
danilchap822a16f2016-09-27 09:27:47 -0700554 nack.SetSenderSsrc(local_ssrc_);
555 nack.SetMediaSsrc(remote_ssrc_);
Erik Språng737336d2016-07-29 12:59:36 +0200556 uint16_t nack_list[] = {*sequence_number_to_retransmit_};
danilchap822a16f2016-09-27 09:27:47 -0700557 nack.SetPacketIds(nack_list, 1);
Erik Språng737336d2016-07-29 12:59:36 +0200558 rtc::Buffer buffer = nack.Build();
559
560 EXPECT_TRUE(receive_transport_->SendRtcp(buffer.data(), buffer.size()));
561 }
562
563 return SEND_PACKET;
564 }
565
566 void ModifyAudioConfigs(
567 AudioSendStream::Config* send_config,
568 std::vector<AudioReceiveStream::Config>* receive_configs) override {
569 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
570 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
571 local_ssrc_ = (*receive_configs)[0].rtp.local_ssrc;
572 remote_ssrc_ = (*receive_configs)[0].rtp.remote_ssrc;
573 }
574
575 void PerformTest() override {
576 EXPECT_TRUE(Wait())
577 << "Timed out waiting for packets to be NACKed, retransmitted and "
578 "rendered.";
579 }
580
581 uint32_t local_ssrc_;
582 uint32_t remote_ssrc_;
583 Transport* receive_transport_;
584 rtc::Optional<uint16_t> sequence_number_to_retransmit_;
585 } test;
586
587 RunBaseTest(&test);
588}
589
brandtr1134b7b2017-02-06 06:35:47 -0800590// Disabled due to flakyness, see
591// https://bugs.chromium.org/p/webrtc/issues/detail?id=7047.
592TEST_P(EndToEndTest, DISABLED_ReceivesUlpfec) {
brandtr535830e2016-10-31 03:45:58 -0700593 class UlpfecRenderObserver : public test::EndToEndTest,
594 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000595 public:
brandtr535830e2016-10-31 03:45:58 -0700596 UlpfecRenderObserver()
brandtr1134b7b2017-02-06 06:35:47 -0800597 : EndToEndTest(kDefaultTimeoutMs),
598 random_(0xcafef00d1),
599 num_packets_sent_(0) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000600
601 private:
stefanf116bd02015-10-27 08:29:42 -0700602 Action OnSendRtp(const uint8_t* packet, size_t length) override {
603 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000604 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000605 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000606
brandtr1134b7b2017-02-06 06:35:47 -0800607 EXPECT_TRUE(header.payloadType == kFakeVideoSendPayloadType ||
608 header.payloadType == kRedPayloadType)
609 << "Unknown payload type received.";
610 EXPECT_EQ(kVideoSendSsrcs[0], header.ssrc) << "Unknown SSRC received.";
611
612 // Parse RED header.
Stefan Holmer01b48882015-05-05 10:21:24 +0200613 int encapsulated_payload_type = -1;
614 if (header.payloadType == kRedPayloadType) {
615 encapsulated_payload_type =
616 static_cast<int>(packet[header.headerLength]);
brandtr1134b7b2017-02-06 06:35:47 -0800617
618 EXPECT_TRUE(encapsulated_payload_type == kFakeVideoSendPayloadType ||
619 encapsulated_payload_type == kUlpfecPayloadType)
620 << "Unknown encapsulated payload type received.";
Stefan Holmer01b48882015-05-05 10:21:24 +0200621 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000622
brandtr1134b7b2017-02-06 06:35:47 -0800623 // To reduce test flakiness, always let ULPFEC packets through.
624 if (encapsulated_payload_type == kUlpfecPayloadType) {
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000625 return SEND_PACKET;
626 }
627
brandtr1134b7b2017-02-06 06:35:47 -0800628 // Simulate 5% video packet loss after rampup period. Record the
629 // corresponding timestamps that were dropped.
630 if (num_packets_sent_++ > 100 && random_.Rand(1, 100) <= 5) {
631 if (encapsulated_payload_type == kFakeVideoSendPayloadType) {
632 dropped_sequence_numbers_.insert(header.sequenceNumber);
633 dropped_timestamps_.insert(header.timestamp);
634 }
635
636 return DROP_PACKET;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000637 }
638
639 return SEND_PACKET;
640 }
641
nisseeb83a1a2016-03-21 01:27:56 -0700642 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200643 rtc::CritScope lock(&crit_);
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000644 // Rendering frame with timestamp of packet that was dropped -> FEC
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000645 // protection worked.
brandtr1134b7b2017-02-06 06:35:47 -0800646 auto it = dropped_timestamps_.find(video_frame.timestamp());
647 if (it != dropped_timestamps_.end()) {
Peter Boström5811a392015-12-10 13:02:50 +0100648 observation_complete_.Set();
brandtr1134b7b2017-02-06 06:35:47 -0800649 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000650 }
651
stefanff483612015-12-21 03:14:00 -0800652 void ModifyVideoConfigs(
653 VideoSendStream::Config* send_config,
654 std::vector<VideoReceiveStream::Config>* receive_configs,
655 VideoEncoderConfig* encoder_config) override {
brandtr1134b7b2017-02-06 06:35:47 -0800656 send_config->rtp.extensions.push_back(
657 RtpExtension(RtpExtension::kTransportSequenceNumberUri,
658 test::kTransportSequenceNumberExtensionId));
brandtrb5f2c3f2016-10-04 23:28:39 -0700659 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
660 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000661
brandtr1134b7b2017-02-06 06:35:47 -0800662 (*receive_configs)[0].rtp.transport_cc = true;
brandtrb5f2c3f2016-10-04 23:28:39 -0700663 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
664 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000665 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000666 }
667
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000668 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100669 EXPECT_TRUE(Wait())
brandtr1e3dfbf2016-11-16 22:45:19 -0800670 << "Timed out waiting for dropped frames to be rendered.";
671 }
672
673 rtc::CriticalSection crit_;
brandtr1134b7b2017-02-06 06:35:47 -0800674 std::set<uint32_t> dropped_sequence_numbers_ GUARDED_BY(crit_);
675 // Several packets can have the same timestamp.
676 std::multiset<uint32_t> dropped_timestamps_ GUARDED_BY(crit_);
677 Random random_;
678 int num_packets_sent_;
brandtr1e3dfbf2016-11-16 22:45:19 -0800679 } test;
680
681 RunBaseTest(&test);
682}
683
brandtrfa5a3682017-01-17 01:33:54 -0800684class FlexfecRenderObserver : public test::EndToEndTest,
685 public rtc::VideoSinkInterface<VideoFrame> {
686 public:
687 static constexpr uint32_t kVideoLocalSsrc = 123;
688 static constexpr uint32_t kFlexfecLocalSsrc = 456;
brandtr1e3dfbf2016-11-16 22:45:19 -0800689
brandtr1134b7b2017-02-06 06:35:47 -0800690 explicit FlexfecRenderObserver(bool enable_nack, bool expect_flexfec_rtcp)
brandtrfa5a3682017-01-17 01:33:54 -0800691 : test::EndToEndTest(test::CallTest::kDefaultTimeoutMs),
brandtr1134b7b2017-02-06 06:35:47 -0800692 enable_nack_(enable_nack),
brandtrfa5a3682017-01-17 01:33:54 -0800693 expect_flexfec_rtcp_(expect_flexfec_rtcp),
694 received_flexfec_rtcp_(false),
brandtr1134b7b2017-02-06 06:35:47 -0800695 random_(0xcafef00d1),
696 num_packets_sent_(0) {}
brandtr1e3dfbf2016-11-16 22:45:19 -0800697
brandtrfa5a3682017-01-17 01:33:54 -0800698 size_t GetNumFlexfecStreams() const override { return 1; }
brandtr1e3dfbf2016-11-16 22:45:19 -0800699
brandtrfa5a3682017-01-17 01:33:54 -0800700 private:
701 Action OnSendRtp(const uint8_t* packet, size_t length) override {
702 rtc::CritScope lock(&crit_);
703 RTPHeader header;
704 EXPECT_TRUE(parser_->Parse(packet, length, &header));
brandtr1e3dfbf2016-11-16 22:45:19 -0800705
brandtr1134b7b2017-02-06 06:35:47 -0800706 EXPECT_TRUE(header.payloadType ==
707 test::CallTest::kFakeVideoSendPayloadType ||
708 header.payloadType == test::CallTest::kFlexfecPayloadType ||
709 (enable_nack_ &&
710 header.payloadType == test::CallTest::kSendRtxPayloadType))
711 << "Unknown payload type received.";
712 EXPECT_TRUE(
713 header.ssrc == test::CallTest::kVideoSendSsrcs[0] ||
714 header.ssrc == test::CallTest::kFlexfecSendSsrc ||
715 (enable_nack_ && header.ssrc == test::CallTest::kSendRtxSsrcs[0]))
716 << "Unknown SSRC received.";
717
718 // To reduce test flakiness, always let FlexFEC packets through.
719 if (header.payloadType == test::CallTest::kFlexfecPayloadType) {
720 EXPECT_EQ(test::CallTest::kFlexfecSendSsrc, header.ssrc);
721
722 return SEND_PACKET;
brandtr1e3dfbf2016-11-16 22:45:19 -0800723 }
724
brandtr1134b7b2017-02-06 06:35:47 -0800725 // To reduce test flakiness, always let RTX packets through.
726 if (header.payloadType == test::CallTest::kSendRtxPayloadType) {
727 EXPECT_EQ(test::CallTest::kSendRtxSsrcs[0], header.ssrc);
728
729 // Parse RTX header.
730 uint16_t original_sequence_number =
731 ByteReader<uint16_t>::ReadBigEndian(&packet[header.headerLength]);
732
733 // From the perspective of FEC, a retransmitted packet is no longer
734 // dropped, so remove it from list of dropped packets.
735 auto seq_num_it =
736 dropped_sequence_numbers_.find(original_sequence_number);
brandtrfa5a3682017-01-17 01:33:54 -0800737 if (seq_num_it != dropped_sequence_numbers_.end()) {
738 dropped_sequence_numbers_.erase(seq_num_it);
739 auto ts_it = dropped_timestamps_.find(header.timestamp);
740 EXPECT_NE(ts_it, dropped_timestamps_.end());
741 dropped_timestamps_.erase(ts_it);
brandtrfd8d2652017-02-06 06:19:51 -0800742 }
brandtr1134b7b2017-02-06 06:35:47 -0800743
744 return SEND_PACKET;
brandtrfa5a3682017-01-17 01:33:54 -0800745 }
746
brandtr1134b7b2017-02-06 06:35:47 -0800747 // Simulate 5% video packet loss after rampup period. Record the
748 // corresponding timestamps that were dropped.
749 if (num_packets_sent_++ > 100 && random_.Rand(1, 100) <= 5) {
750 EXPECT_EQ(test::CallTest::kFakeVideoSendPayloadType, header.payloadType);
751 EXPECT_EQ(test::CallTest::kVideoSendSsrcs[0], header.ssrc);
752
753 dropped_sequence_numbers_.insert(header.sequenceNumber);
754 dropped_timestamps_.insert(header.timestamp);
brandtrfa5a3682017-01-17 01:33:54 -0800755
756 return DROP_PACKET;
757 }
758
759 return SEND_PACKET;
760 }
761
762 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
763 test::RtcpPacketParser parser;
764
765 parser.Parse(data, length);
766 if (parser.sender_ssrc() == kFlexfecLocalSsrc) {
767 EXPECT_EQ(1, parser.receiver_report()->num_packets());
768 const std::vector<rtcp::ReportBlock>& report_blocks =
769 parser.receiver_report()->report_blocks();
770 if (!report_blocks.empty()) {
771 EXPECT_EQ(1U, report_blocks.size());
772 EXPECT_EQ(test::CallTest::kFlexfecSendSsrc,
773 report_blocks[0].source_ssrc());
brandtr1d2d7892017-01-18 00:40:07 -0800774 rtc::CritScope lock(&crit_);
brandtrfa5a3682017-01-17 01:33:54 -0800775 received_flexfec_rtcp_ = true;
776 }
777 }
778
779 return SEND_PACKET;
780 }
781
brandtr1134b7b2017-02-06 06:35:47 -0800782 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
783 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
784 const int kNetworkDelayMs = 100;
785 FakeNetworkPipe::Config config;
786 config.queue_delay_ms = kNetworkDelayMs;
787 return new test::PacketTransport(sender_call, this,
788 test::PacketTransport::kSender, config);
789 }
790
brandtrfa5a3682017-01-17 01:33:54 -0800791 void OnFrame(const VideoFrame& video_frame) override {
792 rtc::CritScope lock(&crit_);
793 // Rendering frame with timestamp of packet that was dropped -> FEC
794 // protection worked.
795 auto it = dropped_timestamps_.find(video_frame.timestamp());
796 if (it != dropped_timestamps_.end()) {
797 if (!expect_flexfec_rtcp_ || received_flexfec_rtcp_) {
brandtr1e3dfbf2016-11-16 22:45:19 -0800798 observation_complete_.Set();
brandtrfa5a3682017-01-17 01:33:54 -0800799 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800800 }
brandtrfa5a3682017-01-17 01:33:54 -0800801 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800802
brandtrfa5a3682017-01-17 01:33:54 -0800803 void ModifyVideoConfigs(
804 VideoSendStream::Config* send_config,
805 std::vector<VideoReceiveStream::Config>* receive_configs,
806 VideoEncoderConfig* encoder_config) override {
brandtr1134b7b2017-02-06 06:35:47 -0800807 send_config->rtp.extensions.push_back(
808 RtpExtension(RtpExtension::kTransportSequenceNumberUri,
809 test::kTransportSequenceNumberExtensionId));
810
brandtrfa5a3682017-01-17 01:33:54 -0800811 (*receive_configs)[0].rtp.local_ssrc = kVideoLocalSsrc;
brandtr1134b7b2017-02-06 06:35:47 -0800812 (*receive_configs)[0].rtp.transport_cc = true;
brandtrfa5a3682017-01-17 01:33:54 -0800813 (*receive_configs)[0].renderer = this;
brandtr1134b7b2017-02-06 06:35:47 -0800814
815 if (enable_nack_) {
816 send_config->rtp.nack.rtp_history_ms = test::CallTest::kNackRtpHistoryMs;
817 send_config->rtp.ulpfec.red_rtx_payload_type =
818 test::CallTest::kRtxRedPayloadType;
819 send_config->rtp.rtx.ssrcs.push_back(test::CallTest::kSendRtxSsrcs[0]);
820 send_config->rtp.rtx.payload_type = test::CallTest::kSendRtxPayloadType;
821
822 (*receive_configs)[0].rtp.nack.rtp_history_ms =
823 test::CallTest::kNackRtpHistoryMs;
824 (*receive_configs)[0].rtp.ulpfec.red_rtx_payload_type =
825 test::CallTest::kRtxRedPayloadType;
826
827 (*receive_configs)[0].rtp.rtx_ssrc = test::CallTest::kSendRtxSsrcs[0];
828 (*receive_configs)[0]
829 .rtp.rtx_payload_types[test::CallTest::kVideoSendPayloadType] =
830 test::CallTest::kSendRtxPayloadType;
831 }
brandtrfa5a3682017-01-17 01:33:54 -0800832 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800833
brandtrfa5a3682017-01-17 01:33:54 -0800834 void ModifyFlexfecConfigs(
835 std::vector<FlexfecReceiveStream::Config>* receive_configs) override {
836 (*receive_configs)[0].local_ssrc = kFlexfecLocalSsrc;
837 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000838
brandtrfa5a3682017-01-17 01:33:54 -0800839 void PerformTest() override {
840 EXPECT_TRUE(Wait())
841 << "Timed out waiting for dropped frames to be rendered.";
842 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000843
brandtrfa5a3682017-01-17 01:33:54 -0800844 rtc::CriticalSection crit_;
845 std::set<uint32_t> dropped_sequence_numbers_ GUARDED_BY(crit_);
brandtr1134b7b2017-02-06 06:35:47 -0800846 // Several packets can have the same timestamp.
brandtrfa5a3682017-01-17 01:33:54 -0800847 std::multiset<uint32_t> dropped_timestamps_ GUARDED_BY(crit_);
brandtr1134b7b2017-02-06 06:35:47 -0800848 const bool enable_nack_;
brandtr1d2d7892017-01-18 00:40:07 -0800849 const bool expect_flexfec_rtcp_;
850 bool received_flexfec_rtcp_ GUARDED_BY(crit_);
brandtrfa5a3682017-01-17 01:33:54 -0800851 Random random_;
brandtr1134b7b2017-02-06 06:35:47 -0800852 int num_packets_sent_;
brandtrfa5a3682017-01-17 01:33:54 -0800853};
854
brandtr1134b7b2017-02-06 06:35:47 -0800855TEST_P(EndToEndTest, RecoversWithFlexfec) {
856 FlexfecRenderObserver test(false, false);
brandtrfa5a3682017-01-17 01:33:54 -0800857 RunBaseTest(&test);
858}
859
brandtr1134b7b2017-02-06 06:35:47 -0800860TEST_P(EndToEndTest, RecoversWithFlexfecAndNack) {
861 FlexfecRenderObserver test(true, false);
862 RunBaseTest(&test);
863}
864
865TEST_P(EndToEndTest, RecoversWithFlexfecAndSendsCorrespondingRtcp) {
866 FlexfecRenderObserver test(false, true);
stefane74eef12016-01-08 06:47:13 -0800867 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000868}
869
philipel266f0a42016-11-28 08:49:07 -0800870TEST_P(EndToEndTest, ReceivedUlpfecPacketsNotNacked) {
brandtr535830e2016-10-31 03:45:58 -0700871 class UlpfecNackObserver : public test::EndToEndTest {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000872 public:
brandtr535830e2016-10-31 03:45:58 -0700873 UlpfecNackObserver()
stefanf116bd02015-10-27 08:29:42 -0700874 : EndToEndTest(kDefaultTimeoutMs),
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000875 state_(kFirstPacket),
brandtr535830e2016-10-31 03:45:58 -0700876 ulpfec_sequence_number_(0),
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000877 has_last_sequence_number_(false),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200878 last_sequence_number_(0),
magjed509e4fe2016-11-18 01:34:11 -0800879 encoder_(VP8Encoder::Create()),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200880 decoder_(VP8Decoder::Create()) {}
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000881
882 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000883 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800884 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000885 RTPHeader header;
886 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000887
Stefan Holmer01b48882015-05-05 10:21:24 +0200888 int encapsulated_payload_type = -1;
889 if (header.payloadType == kRedPayloadType) {
890 encapsulated_payload_type =
891 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100892 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200893 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
894 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100895 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200896 }
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000897
898 if (has_last_sequence_number_ &&
899 !IsNewerSequenceNumber(header.sequenceNumber,
900 last_sequence_number_)) {
901 // Drop retransmitted packets.
902 return DROP_PACKET;
903 }
904 last_sequence_number_ = header.sequenceNumber;
905 has_last_sequence_number_ = true;
906
brandtr535830e2016-10-31 03:45:58 -0700907 bool ulpfec_packet = encapsulated_payload_type == kUlpfecPayloadType;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000908 switch (state_) {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000909 case kFirstPacket:
brandtr535830e2016-10-31 03:45:58 -0700910 state_ = kDropEveryOtherPacketUntilUlpfec;
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000911 break;
brandtr535830e2016-10-31 03:45:58 -0700912 case kDropEveryOtherPacketUntilUlpfec:
913 if (ulpfec_packet) {
914 state_ = kDropAllMediaPacketsUntilUlpfec;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000915 } else if (header.sequenceNumber % 2 == 0) {
916 return DROP_PACKET;
917 }
918 break;
brandtr535830e2016-10-31 03:45:58 -0700919 case kDropAllMediaPacketsUntilUlpfec:
920 if (!ulpfec_packet)
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000921 return DROP_PACKET;
brandtr535830e2016-10-31 03:45:58 -0700922 ulpfec_sequence_number_ = header.sequenceNumber;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200923 state_ = kDropOneMediaPacket;
924 break;
925 case kDropOneMediaPacket:
brandtr535830e2016-10-31 03:45:58 -0700926 if (ulpfec_packet)
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200927 return DROP_PACKET;
928 state_ = kPassOneMediaPacket;
929 return DROP_PACKET;
930 break;
931 case kPassOneMediaPacket:
brandtr535830e2016-10-31 03:45:58 -0700932 if (ulpfec_packet)
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200933 return DROP_PACKET;
934 // Pass one media packet after dropped packet after last FEC,
935 // otherwise receiver might never see a seq_no after
brandtr535830e2016-10-31 03:45:58 -0700936 // |ulpfec_sequence_number_|
937 state_ = kVerifyUlpfecPacketNotInNackList;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000938 break;
brandtr535830e2016-10-31 03:45:58 -0700939 case kVerifyUlpfecPacketNotInNackList:
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000940 // Continue to drop packets. Make sure no frame can be decoded.
brandtr535830e2016-10-31 03:45:58 -0700941 if (ulpfec_packet || header.sequenceNumber % 2 == 0)
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000942 return DROP_PACKET;
943 break;
944 }
945 return SEND_PACKET;
946 }
947
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000948 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800949 rtc::CritScope lock_(&crit_);
brandtr535830e2016-10-31 03:45:58 -0700950 if (state_ == kVerifyUlpfecPacketNotInNackList) {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000951 test::RtcpPacketParser rtcp_parser;
952 rtcp_parser.Parse(packet, length);
Danil Chapovalovba6f7be2016-09-02 18:29:10 +0200953 const std::vector<uint16_t>& nacks = rtcp_parser.nack()->packet_ids();
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200954 EXPECT_TRUE(std::find(nacks.begin(), nacks.end(),
brandtr535830e2016-10-31 03:45:58 -0700955 ulpfec_sequence_number_) == nacks.end())
956 << "Got nack for ULPFEC packet";
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000957 if (!nacks.empty() &&
brandtr535830e2016-10-31 03:45:58 -0700958 IsNewerSequenceNumber(nacks.back(), ulpfec_sequence_number_)) {
Peter Boström5811a392015-12-10 13:02:50 +0100959 observation_complete_.Set();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000960 }
961 }
962 return SEND_PACKET;
963 }
964
stefane74eef12016-01-08 06:47:13 -0800965 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
966 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
967 // Configure some network delay.
968 const int kNetworkDelayMs = 50;
969 FakeNetworkPipe::Config config;
970 config.queue_delay_ms = kNetworkDelayMs;
971 return new test::PacketTransport(sender_call, this,
972 test::PacketTransport::kSender, config);
973 }
974
Stefan Holmere5904162015-03-26 11:11:06 +0100975 // TODO(holmer): Investigate why we don't send FEC packets when the bitrate
976 // is 10 kbps.
977 Call::Config GetSenderCallConfig() override {
skvlad11a9cbf2016-10-07 11:53:05 -0700978 Call::Config config(&event_log_);
Stefan Holmere5904162015-03-26 11:11:06 +0100979 const int kMinBitrateBps = 30000;
980 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
981 return config;
982 }
983
stefanff483612015-12-21 03:14:00 -0800984 void ModifyVideoConfigs(
985 VideoSendStream::Config* send_config,
986 std::vector<VideoReceiveStream::Config>* receive_configs,
987 VideoEncoderConfig* encoder_config) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000988 // Configure hybrid NACK/FEC.
989 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
brandtrb5f2c3f2016-10-04 23:28:39 -0700990 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
991 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200992 // Set codec to VP8, otherwise NACK/FEC hybrid will be disabled.
993 send_config->encoder_settings.encoder = encoder_.get();
994 send_config->encoder_settings.payload_name = "VP8";
995 send_config->encoder_settings.payload_type = kFakeVideoSendPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200996
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000997 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
brandtrb5f2c3f2016-10-04 23:28:39 -0700998 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
999 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001000
1001 (*receive_configs)[0].decoders.resize(1);
1002 (*receive_configs)[0].decoders[0].payload_type =
1003 send_config->encoder_settings.payload_type;
1004 (*receive_configs)[0].decoders[0].payload_name =
1005 send_config->encoder_settings.payload_name;
1006 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001007 }
1008
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001009 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001010 EXPECT_TRUE(Wait())
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001011 << "Timed out while waiting for FEC packets to be received.";
1012 }
1013
1014 enum {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +00001015 kFirstPacket,
brandtr535830e2016-10-31 03:45:58 -07001016 kDropEveryOtherPacketUntilUlpfec,
1017 kDropAllMediaPacketsUntilUlpfec,
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001018 kDropOneMediaPacket,
1019 kPassOneMediaPacket,
brandtr535830e2016-10-31 03:45:58 -07001020 kVerifyUlpfecPacketNotInNackList,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001021 } state_;
1022
stefan608213e2015-11-01 14:56:10 -08001023 rtc::CriticalSection crit_;
brandtr535830e2016-10-31 03:45:58 -07001024 uint16_t ulpfec_sequence_number_ GUARDED_BY(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001025 bool has_last_sequence_number_;
1026 uint16_t last_sequence_number_;
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001027 std::unique_ptr<webrtc::VideoEncoder> encoder_;
1028 std::unique_ptr<webrtc::VideoDecoder> decoder_;
stefanf116bd02015-10-27 08:29:42 -07001029 } test;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001030
stefane74eef12016-01-08 06:47:13 -08001031 RunBaseTest(&test);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001032}
1033
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001034// This test drops second RTP packet with a marker bit set, makes sure it's
1035// retransmitted and renders. Retransmission SSRCs are also checked.
Peter Boström39593972016-02-15 11:27:15 +01001036void EndToEndTest::DecodesRetransmittedFrame(bool enable_rtx, bool enable_red) {
Peter Boström67680c12016-02-17 11:10:04 +01001037 static const int kDroppedFrameNumber = 10;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001038 class RetransmissionObserver : public test::EndToEndTest,
nisse76bc8e82017-02-07 09:37:41 -08001039 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001040 public:
Peter Boström39593972016-02-15 11:27:15 +01001041 RetransmissionObserver(bool enable_rtx, bool enable_red)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001042 : EndToEndTest(kDefaultTimeoutMs),
Peter Boström39593972016-02-15 11:27:15 +01001043 payload_type_(GetPayloadType(false, enable_red)),
1044 retransmission_ssrc_(enable_rtx ? kSendRtxSsrcs[0]
1045 : kVideoSendSsrcs[0]),
1046 retransmission_payload_type_(GetPayloadType(enable_rtx, enable_red)),
magjed509e4fe2016-11-18 01:34:11 -08001047 encoder_(VP8Encoder::Create()),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001048 marker_bits_observed_(0),
danilchap192717e2016-07-25 08:20:51 -07001049 retransmitted_timestamp_(0) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001050
1051 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001052 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001053 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001054 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001055 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001056
Peter Boström67680c12016-02-17 11:10:04 +01001057 // Ignore padding-only packets over RTX.
1058 if (header.payloadType != payload_type_) {
1059 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
1060 if (length == header.headerLength + header.paddingLength)
1061 return SEND_PACKET;
Stefan Holmer586b19b2015-09-18 11:14:31 +02001062 }
Peter Boström67680c12016-02-17 11:10:04 +01001063
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001064 if (header.timestamp == retransmitted_timestamp_) {
1065 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
1066 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001067 return SEND_PACKET;
1068 }
1069
Stefan Holmer586b19b2015-09-18 11:14:31 +02001070 // Found the final packet of the frame to inflict loss to, drop this and
1071 // expect a retransmission.
danilchapfdd381c2016-07-25 04:03:20 -07001072 if (header.payloadType == payload_type_ && header.markerBit &&
1073 ++marker_bits_observed_ == kDroppedFrameNumber) {
Danil Chapovalov18c65a42016-06-29 15:29:34 +02001074 // This should be the only dropped packet.
1075 EXPECT_EQ(0u, retransmitted_timestamp_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001076 retransmitted_timestamp_ = header.timestamp;
danilchap192717e2016-07-25 08:20:51 -07001077 if (std::find(rendered_timestamps_.begin(), rendered_timestamps_.end(),
1078 retransmitted_timestamp_) != rendered_timestamps_.end()) {
1079 // Frame was rendered before last packet was scheduled for sending.
1080 // This is extremly rare but possible scenario because prober able to
1081 // resend packet before it was send.
1082 // TODO(danilchap): Remove this corner case when prober would not be
1083 // able to sneak in between packet saved to history for resending and
1084 // pacer notified about existance of that packet for sending.
1085 // See https://bugs.chromium.org/p/webrtc/issues/detail?id=5540 for
1086 // details.
1087 observation_complete_.Set();
1088 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001089 return DROP_PACKET;
1090 }
1091
1092 return SEND_PACKET;
1093 }
1094
nisse76bc8e82017-02-07 09:37:41 -08001095 void OnFrame(const VideoFrame& frame) override {
stefan5d837802017-02-08 07:09:05 -08001096 {
1097 rtc::CritScope lock(&crit_);
1098 if (frame.timestamp() == retransmitted_timestamp_)
1099 observation_complete_.Set();
1100 rendered_timestamps_.push_back(frame.timestamp());
1101 }
nisse76bc8e82017-02-07 09:37:41 -08001102 orig_renderer_->OnFrame(frame);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001103 }
1104
stefanff483612015-12-21 03:14:00 -08001105 void ModifyVideoConfigs(
1106 VideoSendStream::Config* send_config,
1107 std::vector<VideoReceiveStream::Config>* receive_configs,
1108 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001109 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
nisse76bc8e82017-02-07 09:37:41 -08001110
1111 // Insert ourselves into the rendering pipeline.
1112 RTC_DCHECK(!orig_renderer_);
1113 orig_renderer_ = (*receive_configs)[0].renderer;
1114 RTC_DCHECK(orig_renderer_);
stefan5d837802017-02-08 07:09:05 -08001115 (*receive_configs)[0].disable_prerenderer_smoothing = true;
nisse76bc8e82017-02-07 09:37:41 -08001116 (*receive_configs)[0].renderer = this;
1117
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001118 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
Shao Changbine62202f2015-04-21 20:24:50 +08001119
1120 if (payload_type_ == kRedPayloadType) {
brandtrb5f2c3f2016-10-04 23:28:39 -07001121 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
1122 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +01001123 if (retransmission_ssrc_ == kSendRtxSsrcs[0])
brandtrb5f2c3f2016-10-04 23:28:39 -07001124 send_config->rtp.ulpfec.red_rtx_payload_type = kRtxRedPayloadType;
1125 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type =
1126 send_config->rtp.ulpfec.ulpfec_payload_type;
1127 (*receive_configs)[0].rtp.ulpfec.red_payload_type =
1128 send_config->rtp.ulpfec.red_payload_type;
1129 (*receive_configs)[0].rtp.ulpfec.red_rtx_payload_type =
1130 send_config->rtp.ulpfec.red_rtx_payload_type;
Shao Changbine62202f2015-04-21 20:24:50 +08001131 }
1132
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001133 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
1134 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001135 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
brandtr14742122017-01-27 04:53:07 -08001136 (*receive_configs)[0].rtp.rtx_ssrc = kSendRtxSsrcs[0];
1137 (*receive_configs)[0].rtp.rtx_payload_types[payload_type_] =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001138 kSendRtxPayloadType;
1139 }
Peter Boström39593972016-02-15 11:27:15 +01001140 // Configure encoding and decoding with VP8, since generic packetization
1141 // doesn't support FEC with NACK.
kwibergaf476c72016-11-28 15:21:39 -08001142 RTC_DCHECK_EQ(1, (*receive_configs)[0].decoders.size());
Peter Boström39593972016-02-15 11:27:15 +01001143 send_config->encoder_settings.encoder = encoder_.get();
1144 send_config->encoder_settings.payload_name = "VP8";
1145 (*receive_configs)[0].decoders[0].payload_name = "VP8";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001146 }
1147
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001148 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001149 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001150 << "Timed out while waiting for retransmission to render.";
1151 }
1152
Shao Changbine62202f2015-04-21 20:24:50 +08001153 int GetPayloadType(bool use_rtx, bool use_red) {
Stefan Holmer10880012016-02-03 13:29:59 +01001154 if (use_red) {
1155 if (use_rtx)
1156 return kRtxRedPayloadType;
1157 return kRedPayloadType;
1158 }
1159 if (use_rtx)
1160 return kSendRtxPayloadType;
1161 return kFakeVideoSendPayloadType;
Shao Changbine62202f2015-04-21 20:24:50 +08001162 }
1163
stefanf116bd02015-10-27 08:29:42 -07001164 rtc::CriticalSection crit_;
nisse76bc8e82017-02-07 09:37:41 -08001165 rtc::VideoSinkInterface<VideoFrame>* orig_renderer_ = nullptr;
Shao Changbine62202f2015-04-21 20:24:50 +08001166 const int payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001167 const uint32_t retransmission_ssrc_;
1168 const int retransmission_payload_type_;
kwiberg27f982b2016-03-01 11:52:33 -08001169 std::unique_ptr<VideoEncoder> encoder_;
Peter Boström39593972016-02-15 11:27:15 +01001170 const std::string payload_name_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001171 int marker_bits_observed_;
stefanf116bd02015-10-27 08:29:42 -07001172 uint32_t retransmitted_timestamp_ GUARDED_BY(&crit_);
danilchap192717e2016-07-25 08:20:51 -07001173 std::vector<uint32_t> rendered_timestamps_ GUARDED_BY(&crit_);
Peter Boström39593972016-02-15 11:27:15 +01001174 } test(enable_rtx, enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001175
stefane74eef12016-01-08 06:47:13 -08001176 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001177}
1178
philipel266f0a42016-11-28 08:49:07 -08001179TEST_P(EndToEndTest, DecodesRetransmittedFrame) {
Shao Changbine62202f2015-04-21 20:24:50 +08001180 DecodesRetransmittedFrame(false, false);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001181}
1182
philipel266f0a42016-11-28 08:49:07 -08001183TEST_P(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +08001184 DecodesRetransmittedFrame(true, false);
1185}
1186
philipel266f0a42016-11-28 08:49:07 -08001187TEST_P(EndToEndTest, DecodesRetransmittedFrameByRed) {
Shao Changbine62202f2015-04-21 20:24:50 +08001188 DecodesRetransmittedFrame(false, true);
1189}
1190
philipel266f0a42016-11-28 08:49:07 -08001191TEST_P(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +08001192 DecodesRetransmittedFrame(true, true);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001193}
1194
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001195void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
1196 static const int kPacketsToDrop = 1;
1197
nisse7ade7b32016-03-23 04:48:10 -07001198 class PliObserver : public test::EndToEndTest,
1199 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001200 public:
1201 explicit PliObserver(int rtp_history_ms)
1202 : EndToEndTest(kLongTimeoutMs),
1203 rtp_history_ms_(rtp_history_ms),
1204 nack_enabled_(rtp_history_ms > 0),
1205 highest_dropped_timestamp_(0),
1206 frames_to_drop_(0),
1207 received_pli_(false) {}
1208
1209 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001210 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001211 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001212 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001213 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001214
1215 // Drop all retransmitted packets to force a PLI.
1216 if (header.timestamp <= highest_dropped_timestamp_)
1217 return DROP_PACKET;
1218
1219 if (frames_to_drop_ > 0) {
1220 highest_dropped_timestamp_ = header.timestamp;
1221 --frames_to_drop_;
1222 return DROP_PACKET;
1223 }
1224
1225 return SEND_PACKET;
1226 }
1227
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001228 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001229 rtc::CritScope lock(&crit_);
danilchap3dc929e2016-11-02 08:21:59 -07001230 test::RtcpPacketParser parser;
1231 EXPECT_TRUE(parser.Parse(packet, length));
1232 if (!nack_enabled_)
1233 EXPECT_EQ(0, parser.nack()->num_packets());
1234 if (parser.pli()->num_packets() > 0)
1235 received_pli_ = true;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001236 return SEND_PACKET;
1237 }
1238
nisseeb83a1a2016-03-21 01:27:56 -07001239 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001240 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001241 if (received_pli_ &&
1242 video_frame.timestamp() > highest_dropped_timestamp_) {
Peter Boström5811a392015-12-10 13:02:50 +01001243 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001244 }
1245 if (!received_pli_)
1246 frames_to_drop_ = kPacketsToDrop;
1247 }
1248
stefanff483612015-12-21 03:14:00 -08001249 void ModifyVideoConfigs(
1250 VideoSendStream::Config* send_config,
1251 std::vector<VideoReceiveStream::Config>* receive_configs,
1252 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001253 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001254 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
1255 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001256 }
1257
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001258 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001259 EXPECT_TRUE(Wait()) << "Timed out waiting for PLI to be "
1260 "received and a frame to be "
1261 "rendered afterwards.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001262 }
1263
stefanf116bd02015-10-27 08:29:42 -07001264 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001265 int rtp_history_ms_;
1266 bool nack_enabled_;
stefanf116bd02015-10-27 08:29:42 -07001267 uint32_t highest_dropped_timestamp_ GUARDED_BY(&crit_);
1268 int frames_to_drop_ GUARDED_BY(&crit_);
1269 bool received_pli_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001270 } test(rtp_history_ms);
1271
stefane74eef12016-01-08 06:47:13 -08001272 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001273}
1274
philipel266f0a42016-11-28 08:49:07 -08001275TEST_P(EndToEndTest, ReceivesPliAndRecoversWithNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001276 ReceivesPliAndRecovers(1000);
1277}
1278
philipel266f0a42016-11-28 08:49:07 -08001279TEST_P(EndToEndTest, ReceivesPliAndRecoversWithoutNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001280 ReceivesPliAndRecovers(0);
1281}
1282
philipel266f0a42016-11-28 08:49:07 -08001283TEST_P(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001284 class PacketInputObserver : public PacketReceiver {
1285 public:
1286 explicit PacketInputObserver(PacketReceiver* receiver)
Peter Boström5811a392015-12-10 13:02:50 +01001287 : receiver_(receiver), delivered_packet_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001288
Peter Boström5811a392015-12-10 13:02:50 +01001289 bool Wait() { return delivered_packet_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001290
1291 private:
stefan68786d22015-09-08 05:36:15 -07001292 DeliveryStatus DeliverPacket(MediaType media_type,
1293 const uint8_t* packet,
1294 size_t length,
1295 const PacketTime& packet_time) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001296 if (RtpHeaderParser::IsRtcp(packet, length)) {
stefan68786d22015-09-08 05:36:15 -07001297 return receiver_->DeliverPacket(media_type, packet, length,
1298 packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001299 } else {
1300 DeliveryStatus delivery_status =
stefan68786d22015-09-08 05:36:15 -07001301 receiver_->DeliverPacket(media_type, packet, length, packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001302 EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
Peter Boström5811a392015-12-10 13:02:50 +01001303 delivered_packet_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001304 return delivery_status;
1305 }
1306 }
1307
1308 PacketReceiver* receiver_;
Peter Boström5811a392015-12-10 13:02:50 +01001309 rtc::Event delivered_packet_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001310 };
1311
skvlad11a9cbf2016-10-07 11:53:05 -07001312 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -07001313
stefanf116bd02015-10-27 08:29:42 -07001314 test::DirectTransport send_transport(sender_call_.get());
1315 test::DirectTransport receive_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001316 PacketInputObserver input_observer(receiver_call_->Receiver());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001317 send_transport.SetReceiver(&input_observer);
1318 receive_transport.SetReceiver(sender_call_->Receiver());
1319
brandtr841de6a2016-11-15 07:10:52 -08001320 CreateSendConfig(1, 0, 0, &send_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001321 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001322
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001323 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07001324 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
1325 kDefaultHeight);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001326 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001327
stefanff483612015-12-21 03:14:00 -08001328 receiver_call_->DestroyVideoReceiveStream(video_receive_streams_[0]);
1329 video_receive_streams_.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001330
1331 // Wait() waits for a received packet.
Peter Boström5811a392015-12-10 13:02:50 +01001332 EXPECT_TRUE(input_observer.Wait());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001333
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001334 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001335
1336 DestroyStreams();
1337
1338 send_transport.StopSending();
1339 receive_transport.StopSending();
1340}
1341
pbosda903ea2015-10-02 02:36:56 -07001342void EndToEndTest::RespectsRtcpMode(RtcpMode rtcp_mode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001343 static const int kNumCompoundRtcpPacketsToObserve = 10;
1344 class RtcpModeObserver : public test::EndToEndTest {
1345 public:
pbosda903ea2015-10-02 02:36:56 -07001346 explicit RtcpModeObserver(RtcpMode rtcp_mode)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001347 : EndToEndTest(kDefaultTimeoutMs),
1348 rtcp_mode_(rtcp_mode),
1349 sent_rtp_(0),
1350 sent_rtcp_(0) {}
1351
1352 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001353 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanb77c7162017-02-06 06:29:38 -08001354 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001355 if (++sent_rtp_ % 3 == 0)
1356 return DROP_PACKET;
1357
1358 return SEND_PACKET;
1359 }
1360
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001361 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanb77c7162017-02-06 06:29:38 -08001362 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001363 ++sent_rtcp_;
danilchap3dc929e2016-11-02 08:21:59 -07001364 test::RtcpPacketParser parser;
1365 EXPECT_TRUE(parser.Parse(packet, length));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001366
danilchap3dc929e2016-11-02 08:21:59 -07001367 EXPECT_EQ(0, parser.sender_report()->num_packets());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001368
1369 switch (rtcp_mode_) {
pbosda903ea2015-10-02 02:36:56 -07001370 case RtcpMode::kCompound:
stefanb77c7162017-02-06 06:29:38 -08001371 // TODO(holmer): We shouldn't send transport feedback alone if
1372 // compound RTCP is negotiated.
1373 if (parser.receiver_report()->num_packets() == 0 &&
1374 parser.transport_feedback()->num_packets() == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001375 ADD_FAILURE() << "Received RTCP packet without receiver report for "
pbosda903ea2015-10-02 02:36:56 -07001376 "RtcpMode::kCompound.";
Peter Boström5811a392015-12-10 13:02:50 +01001377 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001378 }
1379
1380 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
Peter Boström5811a392015-12-10 13:02:50 +01001381 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001382
1383 break;
pbosda903ea2015-10-02 02:36:56 -07001384 case RtcpMode::kReducedSize:
danilchap3dc929e2016-11-02 08:21:59 -07001385 if (parser.receiver_report()->num_packets() == 0)
Peter Boström5811a392015-12-10 13:02:50 +01001386 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001387 break;
pbosda903ea2015-10-02 02:36:56 -07001388 case RtcpMode::kOff:
1389 RTC_NOTREACHED();
1390 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001391 }
1392
1393 return SEND_PACKET;
1394 }
1395
stefanff483612015-12-21 03:14:00 -08001396 void ModifyVideoConfigs(
1397 VideoSendStream::Config* send_config,
1398 std::vector<VideoReceiveStream::Config>* receive_configs,
1399 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001400 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001401 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1402 (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001403 }
1404
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001405 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001406 EXPECT_TRUE(Wait())
pbosda903ea2015-10-02 02:36:56 -07001407 << (rtcp_mode_ == RtcpMode::kCompound
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001408 ? "Timed out before observing enough compound packets."
1409 : "Timed out before receiving a non-compound RTCP packet.");
1410 }
1411
pbosda903ea2015-10-02 02:36:56 -07001412 RtcpMode rtcp_mode_;
stefanb77c7162017-02-06 06:29:38 -08001413 rtc::CriticalSection crit_;
1414 // Must be protected since RTCP can be sent by both the process thread
1415 // and the pacer thread.
1416 int sent_rtp_ GUARDED_BY(&crit_);
1417 int sent_rtcp_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001418 } test(rtcp_mode);
1419
stefane74eef12016-01-08 06:47:13 -08001420 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001421}
1422
philipel266f0a42016-11-28 08:49:07 -08001423TEST_P(EndToEndTest, UsesRtcpCompoundMode) {
pbosda903ea2015-10-02 02:36:56 -07001424 RespectsRtcpMode(RtcpMode::kCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001425}
1426
philipel266f0a42016-11-28 08:49:07 -08001427TEST_P(EndToEndTest, UsesRtcpReducedSizeMode) {
pbosda903ea2015-10-02 02:36:56 -07001428 RespectsRtcpMode(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001429}
1430
1431// Test sets up a Call multiple senders with different resolutions and SSRCs.
1432// Another is set up to receive all three of these with different renderers.
sprang867fb522015-08-03 04:38:41 -07001433class MultiStreamTest {
1434 public:
1435 static const size_t kNumStreams = 3;
1436 struct CodecSettings {
1437 uint32_t ssrc;
1438 int width;
1439 int height;
1440 } codec_settings[kNumStreams];
1441
1442 MultiStreamTest() {
1443 // TODO(sprang): Cleanup when msvc supports explicit initializers for array.
1444 codec_settings[0] = {1, 640, 480};
1445 codec_settings[1] = {2, 320, 240};
1446 codec_settings[2] = {3, 240, 160};
1447 }
1448
1449 virtual ~MultiStreamTest() {}
1450
1451 void RunTest() {
skvlad11a9cbf2016-10-07 11:53:05 -07001452 webrtc::RtcEventLogNullImpl event_log;
1453 Call::Config config(&event_log);
1454 std::unique_ptr<Call> sender_call(Call::Create(config));
1455 std::unique_ptr<Call> receiver_call(Call::Create(config));
kwiberg27f982b2016-03-01 11:52:33 -08001456 std::unique_ptr<test::DirectTransport> sender_transport(
stefanf116bd02015-10-27 08:29:42 -07001457 CreateSendTransport(sender_call.get()));
kwiberg27f982b2016-03-01 11:52:33 -08001458 std::unique_ptr<test::DirectTransport> receiver_transport(
stefanf116bd02015-10-27 08:29:42 -07001459 CreateReceiveTransport(receiver_call.get()));
sprang867fb522015-08-03 04:38:41 -07001460 sender_transport->SetReceiver(receiver_call->Receiver());
1461 receiver_transport->SetReceiver(sender_call->Receiver());
1462
kwiberg27f982b2016-03-01 11:52:33 -08001463 std::unique_ptr<VideoEncoder> encoders[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001464 for (size_t i = 0; i < kNumStreams; ++i)
magjed509e4fe2016-11-18 01:34:11 -08001465 encoders[i].reset(VP8Encoder::Create());
sprang867fb522015-08-03 04:38:41 -07001466
1467 VideoSendStream* send_streams[kNumStreams];
1468 VideoReceiveStream* receive_streams[kNumStreams];
1469
1470 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
kwiberg4a206a92016-03-31 10:24:26 -07001471 std::vector<std::unique_ptr<VideoDecoder>> allocated_decoders;
sprang867fb522015-08-03 04:38:41 -07001472 for (size_t i = 0; i < kNumStreams; ++i) {
1473 uint32_t ssrc = codec_settings[i].ssrc;
1474 int width = codec_settings[i].width;
1475 int height = codec_settings[i].height;
1476
solenberg4fbae2b2015-08-28 04:07:10 -07001477 VideoSendStream::Config send_config(sender_transport.get());
sprang867fb522015-08-03 04:38:41 -07001478 send_config.rtp.ssrcs.push_back(ssrc);
1479 send_config.encoder_settings.encoder = encoders[i].get();
1480 send_config.encoder_settings.payload_name = "VP8";
1481 send_config.encoder_settings.payload_type = 124;
1482 VideoEncoderConfig encoder_config;
perkjfa10b552016-10-02 23:45:26 -07001483 test::FillEncoderConfiguration(1, &encoder_config);
1484 encoder_config.max_bitrate_bps = 100000;
sprang867fb522015-08-03 04:38:41 -07001485
1486 UpdateSendConfig(i, &send_config, &encoder_config, &frame_generators[i]);
1487
perkj26091b12016-09-01 01:17:40 -07001488 send_streams[i] = sender_call->CreateVideoSendStream(
1489 send_config.Copy(), encoder_config.Copy());
sprang867fb522015-08-03 04:38:41 -07001490 send_streams[i]->Start();
1491
solenberg4fbae2b2015-08-28 04:07:10 -07001492 VideoReceiveStream::Config receive_config(receiver_transport.get());
sprang867fb522015-08-03 04:38:41 -07001493 receive_config.rtp.remote_ssrc = ssrc;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001494 receive_config.rtp.local_ssrc = test::CallTest::kReceiverLocalVideoSsrc;
sprang867fb522015-08-03 04:38:41 -07001495 VideoReceiveStream::Decoder decoder =
1496 test::CreateMatchingDecoder(send_config.encoder_settings);
kwiberg4a206a92016-03-31 10:24:26 -07001497 allocated_decoders.push_back(
1498 std::unique_ptr<VideoDecoder>(decoder.decoder));
sprang867fb522015-08-03 04:38:41 -07001499 receive_config.decoders.push_back(decoder);
1500
1501 UpdateReceiveConfig(i, &receive_config);
1502
1503 receive_streams[i] =
Tommi733b5472016-06-10 17:58:01 +02001504 receiver_call->CreateVideoReceiveStream(std::move(receive_config));
sprang867fb522015-08-03 04:38:41 -07001505 receive_streams[i]->Start();
1506
1507 frame_generators[i] = test::FrameGeneratorCapturer::Create(
perkja49cbd32016-09-16 07:53:41 -07001508 width, height, 30, Clock::GetRealTimeClock());
perkj803d97f2016-11-01 11:45:46 -07001509 send_streams[i]->SetSource(
1510 frame_generators[i],
1511 VideoSendStream::DegradationPreference::kBalanced);
sprang867fb522015-08-03 04:38:41 -07001512 frame_generators[i]->Start();
1513 }
1514
1515 Wait();
1516
1517 for (size_t i = 0; i < kNumStreams; ++i) {
1518 frame_generators[i]->Stop();
1519 sender_call->DestroyVideoSendStream(send_streams[i]);
1520 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1521 delete frame_generators[i];
1522 }
1523
1524 sender_transport->StopSending();
1525 receiver_transport->StopSending();
1526 }
1527
1528 protected:
1529 virtual void Wait() = 0;
1530 // Note: frame_generator is a point-to-pointer, since the actual instance
1531 // hasn't been created at the time of this call. Only when packets/frames
1532 // start flowing should this be dereferenced.
1533 virtual void UpdateSendConfig(
1534 size_t stream_index,
1535 VideoSendStream::Config* send_config,
1536 VideoEncoderConfig* encoder_config,
1537 test::FrameGeneratorCapturer** frame_generator) {}
1538 virtual void UpdateReceiveConfig(size_t stream_index,
1539 VideoReceiveStream::Config* receive_config) {
1540 }
stefanf116bd02015-10-27 08:29:42 -07001541 virtual test::DirectTransport* CreateSendTransport(Call* sender_call) {
1542 return new test::DirectTransport(sender_call);
sprang867fb522015-08-03 04:38:41 -07001543 }
stefanf116bd02015-10-27 08:29:42 -07001544 virtual test::DirectTransport* CreateReceiveTransport(Call* receiver_call) {
1545 return new test::DirectTransport(receiver_call);
sprang867fb522015-08-03 04:38:41 -07001546 }
1547};
1548
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001549// Each renderer verifies that it receives the expected resolution, and as soon
1550// as every renderer has received a frame, the test finishes.
philipel266f0a42016-11-28 08:49:07 -08001551TEST_P(EndToEndTest, SendsAndReceivesMultipleStreams) {
nisse7ade7b32016-03-23 04:48:10 -07001552 class VideoOutputObserver : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001553 public:
sprang867fb522015-08-03 04:38:41 -07001554 VideoOutputObserver(const MultiStreamTest::CodecSettings& settings,
1555 uint32_t ssrc,
1556 test::FrameGeneratorCapturer** frame_generator)
1557 : settings_(settings),
1558 ssrc_(ssrc),
1559 frame_generator_(frame_generator),
Peter Boström5811a392015-12-10 13:02:50 +01001560 done_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001561
nisseeb83a1a2016-03-21 01:27:56 -07001562 void OnFrame(const VideoFrame& video_frame) override {
sprang867fb522015-08-03 04:38:41 -07001563 EXPECT_EQ(settings_.width, video_frame.width());
1564 EXPECT_EQ(settings_.height, video_frame.height());
1565 (*frame_generator_)->Stop();
Peter Boström5811a392015-12-10 13:02:50 +01001566 done_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001567 }
1568
sprang867fb522015-08-03 04:38:41 -07001569 uint32_t Ssrc() { return ssrc_; }
1570
Peter Boström5811a392015-12-10 13:02:50 +01001571 bool Wait() { return done_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001572
1573 private:
sprang867fb522015-08-03 04:38:41 -07001574 const MultiStreamTest::CodecSettings& settings_;
1575 const uint32_t ssrc_;
1576 test::FrameGeneratorCapturer** const frame_generator_;
Peter Boström5811a392015-12-10 13:02:50 +01001577 rtc::Event done_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001578 };
1579
sprang867fb522015-08-03 04:38:41 -07001580 class Tester : public MultiStreamTest {
1581 public:
1582 Tester() {}
1583 virtual ~Tester() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001584
sprang867fb522015-08-03 04:38:41 -07001585 protected:
1586 void Wait() override {
1587 for (const auto& observer : observers_) {
Peter Boström5811a392015-12-10 13:02:50 +01001588 EXPECT_TRUE(observer->Wait()) << "Time out waiting for from on ssrc "
1589 << observer->Ssrc();
sprang867fb522015-08-03 04:38:41 -07001590 }
1591 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001592
sprang867fb522015-08-03 04:38:41 -07001593 void UpdateSendConfig(
1594 size_t stream_index,
1595 VideoSendStream::Config* send_config,
1596 VideoEncoderConfig* encoder_config,
1597 test::FrameGeneratorCapturer** frame_generator) override {
1598 observers_[stream_index].reset(new VideoOutputObserver(
1599 codec_settings[stream_index], send_config->rtp.ssrcs.front(),
1600 frame_generator));
1601 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001602
sprang867fb522015-08-03 04:38:41 -07001603 void UpdateReceiveConfig(
1604 size_t stream_index,
1605 VideoReceiveStream::Config* receive_config) override {
1606 receive_config->renderer = observers_[stream_index].get();
1607 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001608
sprang867fb522015-08-03 04:38:41 -07001609 private:
kwiberg27f982b2016-03-01 11:52:33 -08001610 std::unique_ptr<VideoOutputObserver> observers_[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001611 } tester;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001612
sprang867fb522015-08-03 04:38:41 -07001613 tester.RunTest();
1614}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001615
philipel266f0a42016-11-28 08:49:07 -08001616TEST_P(EndToEndTest, AssignsTransportSequenceNumbers) {
sprang867fb522015-08-03 04:38:41 -07001617 static const int kExtensionId = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001618
sprang867fb522015-08-03 04:38:41 -07001619 class RtpExtensionHeaderObserver : public test::DirectTransport {
1620 public:
stefanf116bd02015-10-27 08:29:42 -07001621 RtpExtensionHeaderObserver(Call* sender_call,
1622 const uint32_t& first_media_ssrc,
sprang861c55e2015-10-16 10:01:21 -07001623 const std::map<uint32_t, uint32_t>& ssrc_map)
stefanf116bd02015-10-27 08:29:42 -07001624 : DirectTransport(sender_call),
Peter Boström5811a392015-12-10 13:02:50 +01001625 done_(false, false),
sprang867fb522015-08-03 04:38:41 -07001626 parser_(RtpHeaderParser::Create()),
sprang861c55e2015-10-16 10:01:21 -07001627 first_media_ssrc_(first_media_ssrc),
1628 rtx_to_media_ssrcs_(ssrc_map),
sprang867fb522015-08-03 04:38:41 -07001629 padding_observed_(false),
sprang861c55e2015-10-16 10:01:21 -07001630 rtx_padding_observed_(false),
1631 retransmit_observed_(false),
1632 started_(false) {
sprang867fb522015-08-03 04:38:41 -07001633 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
1634 kExtensionId);
1635 }
1636 virtual ~RtpExtensionHeaderObserver() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001637
stefan1d8a5062015-10-02 03:39:33 -07001638 bool SendRtp(const uint8_t* data,
1639 size_t length,
1640 const PacketOptions& options) override {
sprang861c55e2015-10-16 10:01:21 -07001641 {
1642 rtc::CritScope cs(&lock_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001643
Erik Språng8d629712015-08-04 16:24:03 +02001644 if (IsDone())
sprang861c55e2015-10-16 10:01:21 -07001645 return false;
1646
1647 if (started_) {
1648 RTPHeader header;
1649 EXPECT_TRUE(parser_->Parse(data, length, &header));
1650 bool drop_packet = false;
1651
1652 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
1653 EXPECT_EQ(options.packet_id,
1654 header.extension.transportSequenceNumber);
1655 if (!streams_observed_.empty()) {
1656 // Unwrap packet id and verify uniqueness.
1657 int64_t packet_id = unwrapper_.Unwrap(options.packet_id);
1658 EXPECT_TRUE(received_packed_ids_.insert(packet_id).second);
1659 }
1660
1661 // Drop (up to) every 17th packet, so we get retransmits.
1662 // Only drop media, and not on the first stream (otherwise it will be
1663 // hard to distinguish from padding, which is always sent on the first
1664 // stream).
1665 if (header.payloadType != kSendRtxPayloadType &&
1666 header.ssrc != first_media_ssrc_ &&
1667 header.extension.transportSequenceNumber % 17 == 0) {
1668 dropped_seq_[header.ssrc].insert(header.sequenceNumber);
1669 drop_packet = true;
1670 }
1671
perkja8ba1952017-02-27 06:52:10 -08001672 if (header.payloadType == kSendRtxPayloadType) {
sprang861c55e2015-10-16 10:01:21 -07001673 uint16_t original_sequence_number =
1674 ByteReader<uint16_t>::ReadBigEndian(&data[header.headerLength]);
1675 uint32_t original_ssrc =
1676 rtx_to_media_ssrcs_.find(header.ssrc)->second;
1677 std::set<uint16_t>* seq_no_map = &dropped_seq_[original_ssrc];
1678 auto it = seq_no_map->find(original_sequence_number);
1679 if (it != seq_no_map->end()) {
1680 retransmit_observed_ = true;
1681 seq_no_map->erase(it);
1682 } else {
1683 rtx_padding_observed_ = true;
1684 }
1685 } else {
1686 streams_observed_.insert(header.ssrc);
1687 }
1688
1689 if (IsDone())
Peter Boström5811a392015-12-10 13:02:50 +01001690 done_.Set();
sprang861c55e2015-10-16 10:01:21 -07001691
1692 if (drop_packet)
1693 return true;
1694 }
sprang867fb522015-08-03 04:38:41 -07001695 }
sprang861c55e2015-10-16 10:01:21 -07001696
stefan1d8a5062015-10-02 03:39:33 -07001697 return test::DirectTransport::SendRtp(data, length, options);
sprang867fb522015-08-03 04:38:41 -07001698 }
1699
Erik Språng8d629712015-08-04 16:24:03 +02001700 bool IsDone() {
sprang861c55e2015-10-16 10:01:21 -07001701 bool observed_types_ok =
1702 streams_observed_.size() == MultiStreamTest::kNumStreams &&
perkja8ba1952017-02-27 06:52:10 -08001703 retransmit_observed_ && rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001704 if (!observed_types_ok)
1705 return false;
1706 // We should not have any gaps in the sequence number range.
1707 size_t seqno_range =
1708 *received_packed_ids_.rbegin() - *received_packed_ids_.begin() + 1;
1709 return seqno_range == received_packed_ids_.size();
Erik Språng8d629712015-08-04 16:24:03 +02001710 }
1711
Peter Boström5811a392015-12-10 13:02:50 +01001712 bool Wait() {
sprang861c55e2015-10-16 10:01:21 -07001713 {
1714 // Can't be sure until this point that rtx_to_media_ssrcs_ etc have
1715 // been initialized and are OK to read.
1716 rtc::CritScope cs(&lock_);
1717 started_ = true;
1718 }
Peter Boström5811a392015-12-10 13:02:50 +01001719 return done_.Wait(kDefaultTimeoutMs);
sprang861c55e2015-10-16 10:01:21 -07001720 }
sprang867fb522015-08-03 04:38:41 -07001721
sprang861c55e2015-10-16 10:01:21 -07001722 rtc::CriticalSection lock_;
Peter Boström5811a392015-12-10 13:02:50 +01001723 rtc::Event done_;
kwiberg27f982b2016-03-01 11:52:33 -08001724 std::unique_ptr<RtpHeaderParser> parser_;
sprang861c55e2015-10-16 10:01:21 -07001725 SequenceNumberUnwrapper unwrapper_;
1726 std::set<int64_t> received_packed_ids_;
sprang867fb522015-08-03 04:38:41 -07001727 std::set<uint32_t> streams_observed_;
sprang861c55e2015-10-16 10:01:21 -07001728 std::map<uint32_t, std::set<uint16_t>> dropped_seq_;
1729 const uint32_t& first_media_ssrc_;
1730 const std::map<uint32_t, uint32_t>& rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001731 bool padding_observed_;
1732 bool rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001733 bool retransmit_observed_;
1734 bool started_;
sprang867fb522015-08-03 04:38:41 -07001735 };
1736
1737 class TransportSequenceNumberTester : public MultiStreamTest {
1738 public:
sprang861c55e2015-10-16 10:01:21 -07001739 TransportSequenceNumberTester()
1740 : first_media_ssrc_(0), observer_(nullptr) {}
sprang867fb522015-08-03 04:38:41 -07001741 virtual ~TransportSequenceNumberTester() {}
1742
1743 protected:
1744 void Wait() override {
Peter Boström74f6e9e2016-04-04 17:56:10 +02001745 RTC_DCHECK(observer_);
Peter Boström5811a392015-12-10 13:02:50 +01001746 EXPECT_TRUE(observer_->Wait());
sprang867fb522015-08-03 04:38:41 -07001747 }
1748
1749 void UpdateSendConfig(
1750 size_t stream_index,
1751 VideoSendStream::Config* send_config,
1752 VideoEncoderConfig* encoder_config,
1753 test::FrameGeneratorCapturer** frame_generator) override {
1754 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001755 send_config->rtp.extensions.push_back(RtpExtension(
1756 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sprang867fb522015-08-03 04:38:41 -07001757
perkja8ba1952017-02-27 06:52:10 -08001758 // Force some padding to be sent. Note that since we do send media
1759 // packets we can not guarantee that a padding only packet is sent.
1760 // Instead, padding will most likely be send as an RTX packet.
sprang867fb522015-08-03 04:38:41 -07001761 const int kPaddingBitrateBps = 50000;
perkja8ba1952017-02-27 06:52:10 -08001762 encoder_config->max_bitrate_bps = 200000;
sprang867fb522015-08-03 04:38:41 -07001763 encoder_config->min_transmit_bitrate_bps =
perkjfa10b552016-10-02 23:45:26 -07001764 encoder_config->max_bitrate_bps + kPaddingBitrateBps;
sprang867fb522015-08-03 04:38:41 -07001765
1766 // Configure RTX for redundant payload padding.
1767 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang861c55e2015-10-16 10:01:21 -07001768 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[stream_index]);
sprang867fb522015-08-03 04:38:41 -07001769 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
sprang861c55e2015-10-16 10:01:21 -07001770 rtx_to_media_ssrcs_[kSendRtxSsrcs[stream_index]] =
1771 send_config->rtp.ssrcs[0];
1772
1773 if (stream_index == 0)
1774 first_media_ssrc_ = send_config->rtp.ssrcs[0];
sprang867fb522015-08-03 04:38:41 -07001775 }
1776
1777 void UpdateReceiveConfig(
1778 size_t stream_index,
1779 VideoReceiveStream::Config* receive_config) override {
sprang861c55e2015-10-16 10:01:21 -07001780 receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang867fb522015-08-03 04:38:41 -07001781 receive_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001782 receive_config->rtp.extensions.push_back(RtpExtension(
1783 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sakal55d932b2016-09-30 06:19:08 -07001784 receive_config->renderer = &fake_renderer_;
sprang867fb522015-08-03 04:38:41 -07001785 }
1786
stefanf116bd02015-10-27 08:29:42 -07001787 test::DirectTransport* CreateSendTransport(Call* sender_call) override {
1788 observer_ = new RtpExtensionHeaderObserver(sender_call, first_media_ssrc_,
sprang861c55e2015-10-16 10:01:21 -07001789 rtx_to_media_ssrcs_);
sprang867fb522015-08-03 04:38:41 -07001790 return observer_;
1791 }
1792
1793 private:
sakal55d932b2016-09-30 06:19:08 -07001794 test::FakeVideoRenderer fake_renderer_;
sprang861c55e2015-10-16 10:01:21 -07001795 uint32_t first_media_ssrc_;
1796 std::map<uint32_t, uint32_t> rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001797 RtpExtensionHeaderObserver* observer_;
1798 } tester;
1799
1800 tester.RunTest();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001801}
1802
Stefan Holmer04cb7632016-01-14 20:34:30 +01001803class TransportFeedbackTester : public test::EndToEndTest {
1804 public:
1805 explicit TransportFeedbackTester(bool feedback_enabled,
1806 size_t num_video_streams,
1807 size_t num_audio_streams)
1808 : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
1809 feedback_enabled_(feedback_enabled),
1810 num_video_streams_(num_video_streams),
sprangcd349d92016-07-13 09:11:28 -07001811 num_audio_streams_(num_audio_streams),
1812 receiver_call_(nullptr) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001813 // Only one stream of each supported for now.
1814 EXPECT_LE(num_video_streams, 1u);
1815 EXPECT_LE(num_audio_streams, 1u);
1816 }
1817
1818 protected:
1819 Action OnSendRtcp(const uint8_t* data, size_t length) override {
1820 EXPECT_FALSE(HasTransportFeedback(data, length));
1821 return SEND_PACKET;
1822 }
1823
1824 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
1825 if (HasTransportFeedback(data, length))
1826 observation_complete_.Set();
1827 return SEND_PACKET;
1828 }
1829
1830 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
danilchap3dc929e2016-11-02 08:21:59 -07001831 test::RtcpPacketParser parser;
1832 EXPECT_TRUE(parser.Parse(data, length));
1833 return parser.transport_feedback()->num_packets() > 0;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001834 }
1835
1836 void PerformTest() override {
1837 const int64_t kDisabledFeedbackTimeoutMs = 5000;
1838 EXPECT_EQ(feedback_enabled_,
1839 observation_complete_.Wait(feedback_enabled_
1840 ? test::CallTest::kDefaultTimeoutMs
1841 : kDisabledFeedbackTimeoutMs));
1842 }
1843
1844 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1845 receiver_call_ = receiver_call;
1846 }
1847
1848 size_t GetNumVideoStreams() const override { return num_video_streams_; }
1849 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
1850
1851 void ModifyVideoConfigs(
1852 VideoSendStream::Config* send_config,
1853 std::vector<VideoReceiveStream::Config>* receive_configs,
1854 VideoEncoderConfig* encoder_config) override {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001855 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
1856 }
1857
1858 void ModifyAudioConfigs(
1859 AudioSendStream::Config* send_config,
1860 std::vector<AudioReceiveStream::Config>* receive_configs) override {
1861 send_config->rtp.extensions.clear();
1862 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001863 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001864 (*receive_configs)[0].rtp.extensions.clear();
1865 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1866 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001867 }
1868
1869 private:
Erik Språng6b8d3552015-09-24 15:06:57 +02001870 static const int kExtensionId = 5;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001871 const bool feedback_enabled_;
1872 const size_t num_video_streams_;
1873 const size_t num_audio_streams_;
1874 Call* receiver_call_;
1875};
Erik Språng6b8d3552015-09-24 15:06:57 +02001876
philipel266f0a42016-11-28 08:49:07 -08001877TEST_P(EndToEndTest, VideoReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001878 TransportFeedbackTester test(true, 1, 0);
1879 RunBaseTest(&test);
Erik Språng6b8d3552015-09-24 15:06:57 +02001880}
stefan43edf0f2015-11-20 18:05:48 -08001881
philipel266f0a42016-11-28 08:49:07 -08001882TEST_P(EndToEndTest, VideoTransportFeedbackNotConfigured) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001883 TransportFeedbackTester test(false, 1, 0);
1884 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001885}
1886
philipel266f0a42016-11-28 08:49:07 -08001887TEST_P(EndToEndTest, AudioReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001888 TransportFeedbackTester test(true, 0, 1);
1889 RunBaseTest(&test);
1890}
1891
philipel266f0a42016-11-28 08:49:07 -08001892TEST_P(EndToEndTest, AudioTransportFeedbackNotConfigured) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001893 TransportFeedbackTester test(false, 0, 1);
1894 RunBaseTest(&test);
1895}
1896
philipel266f0a42016-11-28 08:49:07 -08001897TEST_P(EndToEndTest, AudioVideoReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001898 TransportFeedbackTester test(true, 1, 1);
1899 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001900}
1901
philipel266f0a42016-11-28 08:49:07 -08001902TEST_P(EndToEndTest, ObserversEncodedFrames) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001903 class EncodedFrameTestObserver : public EncodedFrameObserver {
1904 public:
1905 EncodedFrameTestObserver()
Peter Boström5811a392015-12-10 13:02:50 +01001906 : length_(0), frame_type_(kEmptyFrame), called_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001907 virtual ~EncodedFrameTestObserver() {}
1908
1909 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
1910 frame_type_ = encoded_frame.frame_type_;
1911 length_ = encoded_frame.length_;
1912 buffer_.reset(new uint8_t[length_]);
1913 memcpy(buffer_.get(), encoded_frame.data_, length_);
Peter Boström5811a392015-12-10 13:02:50 +01001914 called_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001915 }
1916
Peter Boström5811a392015-12-10 13:02:50 +01001917 bool Wait() { return called_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001918
1919 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
1920 ASSERT_EQ(length_, observer.length_)
1921 << "Observed frames are of different lengths.";
1922 EXPECT_EQ(frame_type_, observer.frame_type_)
1923 << "Observed frames have different frame types.";
1924 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
1925 << "Observed encoded frames have different content.";
1926 }
1927
1928 private:
kwiberg27f982b2016-03-01 11:52:33 -08001929 std::unique_ptr<uint8_t[]> buffer_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001930 size_t length_;
1931 FrameType frame_type_;
Peter Boström5811a392015-12-10 13:02:50 +01001932 rtc::Event called_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001933 };
1934
1935 EncodedFrameTestObserver post_encode_observer;
1936 EncodedFrameTestObserver pre_decode_observer;
1937
skvlad11a9cbf2016-10-07 11:53:05 -07001938 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -07001939
stefanf116bd02015-10-27 08:29:42 -07001940 test::DirectTransport sender_transport(sender_call_.get());
1941 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001942 sender_transport.SetReceiver(receiver_call_->Receiver());
1943 receiver_transport.SetReceiver(sender_call_->Receiver());
1944
brandtr841de6a2016-11-15 07:10:52 -08001945 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001946 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -08001947 video_send_config_.post_encode_callback = &post_encode_observer;
1948 video_receive_configs_[0].pre_decode_callback = &pre_decode_observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001949
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001950 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001951 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001952
kwiberg27f982b2016-03-01 11:52:33 -08001953 std::unique_ptr<test::FrameGenerator> frame_generator(
perkja8ba1952017-02-27 06:52:10 -08001954 test::FrameGenerator::CreateSquareGenerator(kDefaultWidth,
perkjfa10b552016-10-02 23:45:26 -07001955 kDefaultHeight));
perkja49cbd32016-09-16 07:53:41 -07001956 test::FrameForwarder forwarder;
perkj803d97f2016-11-01 11:45:46 -07001957 video_send_stream_->SetSource(
1958 &forwarder, VideoSendStream::DegradationPreference::kBalanced);
perkja49cbd32016-09-16 07:53:41 -07001959 forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001960
Peter Boström5811a392015-12-10 13:02:50 +01001961 EXPECT_TRUE(post_encode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001962 << "Timed out while waiting for send-side encoded-frame callback.";
1963
Peter Boström5811a392015-12-10 13:02:50 +01001964 EXPECT_TRUE(pre_decode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001965 << "Timed out while waiting for pre-decode encoded-frame callback.";
1966
1967 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
1968
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001969 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001970
1971 sender_transport.StopSending();
1972 receiver_transport.StopSending();
1973
1974 DestroyStreams();
1975}
1976
philipel266f0a42016-11-28 08:49:07 -08001977TEST_P(EndToEndTest, ReceiveStreamSendsRemb) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001978 class RembObserver : public test::EndToEndTest {
1979 public:
1980 RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
1981
stefanb77c7162017-02-06 06:29:38 -08001982 void ModifyVideoConfigs(
1983 VideoSendStream::Config* send_config,
1984 std::vector<VideoReceiveStream::Config>* receive_configs,
1985 VideoEncoderConfig* encoder_config) override {
1986 send_config->rtp.extensions.clear();
1987 send_config->rtp.extensions.push_back(RtpExtension(
1988 RtpExtension::kAbsSendTimeUri, test::kAbsSendTimeExtensionId));
1989 (*receive_configs)[0].rtp.remb = true;
1990 (*receive_configs)[0].rtp.transport_cc = false;
1991 }
1992
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001993 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
danilchap3dc929e2016-11-02 08:21:59 -07001994 test::RtcpPacketParser parser;
1995 EXPECT_TRUE(parser.Parse(packet, length));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001996
danilchap3dc929e2016-11-02 08:21:59 -07001997 if (parser.remb()->num_packets() > 0) {
1998 EXPECT_EQ(kReceiverLocalVideoSsrc, parser.remb()->sender_ssrc());
1999 EXPECT_LT(0U, parser.remb()->bitrate_bps());
2000 EXPECT_EQ(1U, parser.remb()->ssrcs().size());
2001 EXPECT_EQ(kVideoSendSsrcs[0], parser.remb()->ssrcs()[0]);
Peter Boström5811a392015-12-10 13:02:50 +01002002 observation_complete_.Set();
danilchap3dc929e2016-11-02 08:21:59 -07002003 }
2004
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002005 return SEND_PACKET;
2006 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002007 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002008 EXPECT_TRUE(Wait()) << "Timed out while waiting for a "
2009 "receiver RTCP REMB packet to be "
2010 "sent.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002011 }
2012 } test;
2013
stefane74eef12016-01-08 06:47:13 -08002014 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002015}
2016
stefanb77c7162017-02-06 06:29:38 -08002017class BandwidthStatsTest : public test::EndToEndTest {
2018 public:
2019 explicit BandwidthStatsTest(bool send_side_bwe)
2020 : EndToEndTest(test::CallTest::kDefaultTimeoutMs),
2021 sender_call_(nullptr),
2022 receiver_call_(nullptr),
2023 has_seen_pacer_delay_(false),
2024 send_side_bwe_(send_side_bwe) {}
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002025
stefanb77c7162017-02-06 06:29:38 -08002026 void ModifyVideoConfigs(
2027 VideoSendStream::Config* send_config,
2028 std::vector<VideoReceiveStream::Config>* receive_configs,
2029 VideoEncoderConfig* encoder_config) override {
2030 if (!send_side_bwe_) {
2031 send_config->rtp.extensions.clear();
2032 send_config->rtp.extensions.push_back(RtpExtension(
2033 RtpExtension::kAbsSendTimeUri, test::kAbsSendTimeExtensionId));
2034 (*receive_configs)[0].rtp.remb = true;
2035 (*receive_configs)[0].rtp.transport_cc = false;
2036 }
2037 }
2038
2039 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2040 Call::Stats sender_stats = sender_call_->GetStats();
2041 Call::Stats receiver_stats = receiver_call_->GetStats();
2042 if (!has_seen_pacer_delay_)
2043 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
2044 if (sender_stats.send_bandwidth_bps > 0 && has_seen_pacer_delay_) {
2045 if (send_side_bwe_ || receiver_stats.recv_bandwidth_bps > 0)
Peter Boström5811a392015-12-10 13:02:50 +01002046 observation_complete_.Set();
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002047 }
stefanb77c7162017-02-06 06:29:38 -08002048 return SEND_PACKET;
2049 }
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002050
stefanb77c7162017-02-06 06:29:38 -08002051 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2052 sender_call_ = sender_call;
2053 receiver_call_ = receiver_call;
2054 }
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002055
stefanb77c7162017-02-06 06:29:38 -08002056 void PerformTest() override {
2057 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2058 "non-zero bandwidth stats.";
2059 }
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002060
stefanb77c7162017-02-06 06:29:38 -08002061 private:
2062 Call* sender_call_;
2063 Call* receiver_call_;
2064 bool has_seen_pacer_delay_;
2065 const bool send_side_bwe_;
2066};
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002067
stefanb77c7162017-02-06 06:29:38 -08002068TEST_P(EndToEndTest, VerifySendSideBweStats) {
2069 BandwidthStatsTest test(true);
stefane74eef12016-01-08 06:47:13 -08002070 RunBaseTest(&test);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002071}
2072
stefanb77c7162017-02-06 06:29:38 -08002073TEST_P(EndToEndTest, VerifyRecvSideBweStats) {
2074 BandwidthStatsTest test(false);
2075 RunBaseTest(&test);
2076}
stefan32f81542016-01-20 07:13:58 -08002077
2078// Verifies that it's possible to limit the send BWE by sending a REMB.
2079// This is verified by allowing the send BWE to ramp-up to >1000 kbps,
2080// then have the test generate a REMB of 500 kbps and verify that the send BWE
2081// is reduced to exactly 500 kbps. Then a REMB of 1000 kbps is generated and the
2082// test verifies that the send BWE ramps back up to exactly 1000 kbps.
philipel266f0a42016-11-28 08:49:07 -08002083TEST_P(EndToEndTest, RembWithSendSideBwe) {
stefan32f81542016-01-20 07:13:58 -08002084 class BweObserver : public test::EndToEndTest {
2085 public:
2086 BweObserver()
2087 : EndToEndTest(kDefaultTimeoutMs),
2088 sender_call_(nullptr),
2089 clock_(Clock::GetRealTimeClock()),
2090 sender_ssrc_(0),
2091 remb_bitrate_bps_(1000000),
2092 receive_transport_(nullptr),
Tommi5dd5f5a2017-02-21 14:22:59 +01002093 stop_event_(false, false),
stefan32f81542016-01-20 07:13:58 -08002094 poller_thread_(&BitrateStatsPollingThread,
2095 this,
2096 "BitrateStatsPollingThread"),
Erik Språng737336d2016-07-29 12:59:36 +02002097 state_(kWaitForFirstRampUp),
2098 retransmission_rate_limiter_(clock_, 1000) {}
stefan32f81542016-01-20 07:13:58 -08002099
2100 ~BweObserver() {}
2101
nisseef8b61e2016-04-29 06:09:15 -07002102 test::PacketTransport* CreateReceiveTransport() override {
stefan32f81542016-01-20 07:13:58 -08002103 receive_transport_ = new test::PacketTransport(
2104 nullptr, this, test::PacketTransport::kReceiver,
2105 FakeNetworkPipe::Config());
2106 return receive_transport_;
2107 }
2108
2109 Call::Config GetSenderCallConfig() override {
skvlad11a9cbf2016-10-07 11:53:05 -07002110 Call::Config config(&event_log_);
stefan32f81542016-01-20 07:13:58 -08002111 // Set a high start bitrate to reduce the test completion time.
2112 config.bitrate_config.start_bitrate_bps = remb_bitrate_bps_;
2113 return config;
2114 }
2115
2116 void ModifyVideoConfigs(
2117 VideoSendStream::Config* send_config,
2118 std::vector<VideoReceiveStream::Config>* receive_configs,
2119 VideoEncoderConfig* encoder_config) override {
2120 ASSERT_EQ(1u, send_config->rtp.ssrcs.size());
stefan32f81542016-01-20 07:13:58 -08002121 sender_ssrc_ = send_config->rtp.ssrcs[0];
2122
perkjfa10b552016-10-02 23:45:26 -07002123 encoder_config->max_bitrate_bps = 2000000;
stefan32f81542016-01-20 07:13:58 -08002124
2125 ASSERT_EQ(1u, receive_configs->size());
stefan32f81542016-01-20 07:13:58 -08002126 RtpRtcp::Configuration config;
2127 config.receiver_only = true;
2128 config.clock = clock_;
2129 config.outgoing_transport = receive_transport_;
Erik Språng737336d2016-07-29 12:59:36 +02002130 config.retransmission_rate_limiter = &retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08002131 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
2132 rtp_rtcp_->SetRemoteSSRC((*receive_configs)[0].rtp.remote_ssrc);
2133 rtp_rtcp_->SetSSRC((*receive_configs)[0].rtp.local_ssrc);
2134 rtp_rtcp_->SetREMBStatus(true);
2135 rtp_rtcp_->SetSendingStatus(true);
2136 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
2137 }
2138
2139 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2140 sender_call_ = sender_call;
2141 }
2142
tommi0f8b4032017-02-22 11:22:05 -08002143 static void BitrateStatsPollingThread(void* obj) {
2144 static_cast<BweObserver*>(obj)->PollStats();
stefan32f81542016-01-20 07:13:58 -08002145 }
2146
tommi0f8b4032017-02-22 11:22:05 -08002147 void PollStats() {
2148 do {
2149 if (sender_call_) {
2150 Call::Stats stats = sender_call_->GetStats();
2151 switch (state_) {
2152 case kWaitForFirstRampUp:
2153 if (stats.send_bandwidth_bps >= remb_bitrate_bps_) {
2154 state_ = kWaitForRemb;
2155 remb_bitrate_bps_ /= 2;
2156 rtp_rtcp_->SetREMBData(
2157 remb_bitrate_bps_,
2158 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
2159 rtp_rtcp_->SendRTCP(kRtcpRr);
2160 }
2161 break;
stefan32f81542016-01-20 07:13:58 -08002162
tommi0f8b4032017-02-22 11:22:05 -08002163 case kWaitForRemb:
2164 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
2165 state_ = kWaitForSecondRampUp;
2166 remb_bitrate_bps_ *= 2;
2167 rtp_rtcp_->SetREMBData(
2168 remb_bitrate_bps_,
2169 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
2170 rtp_rtcp_->SendRTCP(kRtcpRr);
2171 }
2172 break;
stefan32f81542016-01-20 07:13:58 -08002173
tommi0f8b4032017-02-22 11:22:05 -08002174 case kWaitForSecondRampUp:
2175 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
2176 observation_complete_.Set();
2177 }
2178 break;
2179 }
stefan32f81542016-01-20 07:13:58 -08002180 }
tommi0f8b4032017-02-22 11:22:05 -08002181 } while (!stop_event_.Wait(1000));
stefan32f81542016-01-20 07:13:58 -08002182 }
2183
2184 void PerformTest() override {
2185 poller_thread_.Start();
2186 EXPECT_TRUE(Wait())
2187 << "Timed out while waiting for bitrate to change according to REMB.";
Tommi5dd5f5a2017-02-21 14:22:59 +01002188 stop_event_.Set();
stefan32f81542016-01-20 07:13:58 -08002189 poller_thread_.Stop();
2190 }
2191
2192 private:
2193 enum TestState { kWaitForFirstRampUp, kWaitForRemb, kWaitForSecondRampUp };
2194
2195 Call* sender_call_;
2196 Clock* const clock_;
2197 uint32_t sender_ssrc_;
2198 int remb_bitrate_bps_;
kwiberg27f982b2016-03-01 11:52:33 -08002199 std::unique_ptr<RtpRtcp> rtp_rtcp_;
stefan32f81542016-01-20 07:13:58 -08002200 test::PacketTransport* receive_transport_;
Tommi5dd5f5a2017-02-21 14:22:59 +01002201 rtc::Event stop_event_;
stefan32f81542016-01-20 07:13:58 -08002202 rtc::PlatformThread poller_thread_;
2203 TestState state_;
Erik Språng737336d2016-07-29 12:59:36 +02002204 RateLimiter retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08002205 } test;
2206
2207 RunBaseTest(&test);
2208}
2209
philipel266f0a42016-11-28 08:49:07 -08002210TEST_P(EndToEndTest, VerifyNackStats) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002211 static const int kPacketNumberToDrop = 200;
2212 class NackObserver : public test::EndToEndTest {
2213 public:
2214 NackObserver()
2215 : EndToEndTest(kLongTimeoutMs),
2216 sent_rtp_packets_(0),
2217 dropped_rtp_packet_(0),
2218 dropped_rtp_packet_requested_(false),
2219 send_stream_(nullptr),
2220 start_runtime_ms_(-1) {}
2221
2222 private:
2223 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002224 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002225 if (++sent_rtp_packets_ == kPacketNumberToDrop) {
kwiberg27f982b2016-03-01 11:52:33 -08002226 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
Åsa Persson352b2d72015-04-15 18:00:40 +02002227 RTPHeader header;
2228 EXPECT_TRUE(parser->Parse(packet, length, &header));
2229 dropped_rtp_packet_ = header.sequenceNumber;
2230 return DROP_PACKET;
2231 }
2232 VerifyStats();
2233 return SEND_PACKET;
2234 }
2235
2236 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002237 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002238 test::RtcpPacketParser rtcp_parser;
2239 rtcp_parser.Parse(packet, length);
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02002240 const std::vector<uint16_t>& nacks = rtcp_parser.nack()->packet_ids();
Åsa Persson352b2d72015-04-15 18:00:40 +02002241 if (!nacks.empty() && std::find(
2242 nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) {
2243 dropped_rtp_packet_requested_ = true;
2244 }
2245 return SEND_PACKET;
2246 }
2247
stefan608213e2015-11-01 14:56:10 -08002248 void VerifyStats() EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002249 if (!dropped_rtp_packet_requested_)
2250 return;
2251 int send_stream_nack_packets = 0;
2252 int receive_stream_nack_packets = 0;
2253 VideoSendStream::Stats stats = send_stream_->GetStats();
2254 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
2255 stats.substreams.begin(); it != stats.substreams.end(); ++it) {
2256 const VideoSendStream::StreamStats& stream_stats = it->second;
2257 send_stream_nack_packets +=
2258 stream_stats.rtcp_packet_type_counts.nack_packets;
2259 }
2260 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2261 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2262 receive_stream_nack_packets +=
2263 stats.rtcp_packet_type_counts.nack_packets;
2264 }
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002265 if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002266 // NACK packet sent on receive stream and received on sent stream.
2267 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002268 observation_complete_.Set();
Åsa Persson352b2d72015-04-15 18:00:40 +02002269 }
2270 }
2271
2272 bool MinMetricRunTimePassed() {
2273 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2274 if (start_runtime_ms_ == -1) {
2275 start_runtime_ms_ = now;
2276 return false;
2277 }
2278 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2279 return elapsed_sec > metrics::kMinRunTimeInSeconds;
2280 }
2281
stefanff483612015-12-21 03:14:00 -08002282 void ModifyVideoConfigs(
2283 VideoSendStream::Config* send_config,
2284 std::vector<VideoReceiveStream::Config>* receive_configs,
2285 VideoEncoderConfig* encoder_config) override {
Åsa Persson352b2d72015-04-15 18:00:40 +02002286 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2287 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sakal55d932b2016-09-30 06:19:08 -07002288 (*receive_configs)[0].renderer = &fake_renderer_;
Åsa Persson352b2d72015-04-15 18:00:40 +02002289 }
2290
stefanff483612015-12-21 03:14:00 -08002291 void OnVideoStreamsCreated(
Åsa Persson352b2d72015-04-15 18:00:40 +02002292 VideoSendStream* send_stream,
2293 const std::vector<VideoReceiveStream*>& receive_streams) override {
2294 send_stream_ = send_stream;
2295 receive_streams_ = receive_streams;
2296 }
2297
2298 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002299 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson352b2d72015-04-15 18:00:40 +02002300 }
2301
sakal55d932b2016-09-30 06:19:08 -07002302 test::FakeVideoRenderer fake_renderer_;
stefan608213e2015-11-01 14:56:10 -08002303 rtc::CriticalSection crit_;
Åsa Persson352b2d72015-04-15 18:00:40 +02002304 uint64_t sent_rtp_packets_;
stefan608213e2015-11-01 14:56:10 -08002305 uint16_t dropped_rtp_packet_ GUARDED_BY(&crit_);
2306 bool dropped_rtp_packet_requested_ GUARDED_BY(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002307 std::vector<VideoReceiveStream*> receive_streams_;
2308 VideoSendStream* send_stream_;
2309 int64_t start_runtime_ms_;
2310 } test;
2311
asapersson01d70a32016-05-20 06:29:46 -07002312 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002313 RunBaseTest(&test);
Åsa Persson352b2d72015-04-15 18:00:40 +02002314
asapersson01d70a32016-05-20 06:29:46 -07002315 EXPECT_EQ(
2316 1, metrics::NumSamples("WebRTC.Video.UniqueNackRequestsSentInPercent"));
2317 EXPECT_EQ(1, metrics::NumSamples(
2318 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
2319 EXPECT_GT(metrics::MinSample("WebRTC.Video.NackPacketsSentPerMinute"), 0);
Åsa Persson352b2d72015-04-15 18:00:40 +02002320}
2321
sprangb4a1ae52015-12-03 08:10:08 -08002322void EndToEndTest::VerifyHistogramStats(bool use_rtx,
2323 bool use_red,
2324 bool screenshare) {
tommi2e82f382016-06-21 00:26:43 -07002325 class StatsObserver : public test::EndToEndTest,
2326 public rtc::VideoSinkInterface<VideoFrame> {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002327 public:
sprangb4a1ae52015-12-03 08:10:08 -08002328 StatsObserver(bool use_rtx, bool use_red, bool screenshare)
Åsa Persson3c391cb2015-04-27 10:09:49 +02002329 : EndToEndTest(kLongTimeoutMs),
2330 use_rtx_(use_rtx),
2331 use_red_(use_red),
sprangb4a1ae52015-12-03 08:10:08 -08002332 screenshare_(screenshare),
Peter Boström39593972016-02-15 11:27:15 +01002333 // This test uses NACK, so to send FEC we can't use a fake encoder.
magjed509e4fe2016-11-18 01:34:11 -08002334 vp8_encoder_(use_red ? VP8Encoder::Create() : nullptr),
Åsa Persson3c391cb2015-04-27 10:09:49 +02002335 sender_call_(nullptr),
2336 receiver_call_(nullptr),
asapersson1394c7b2016-10-18 11:50:50 -07002337 start_runtime_ms_(-1),
2338 num_frames_received_(0) {}
Åsa Persson3c391cb2015-04-27 10:09:49 +02002339
2340 private:
asapersson1394c7b2016-10-18 11:50:50 -07002341 void OnFrame(const VideoFrame& video_frame) override {
2342 // The RTT is needed to estimate |ntp_time_ms| which is used by
2343 // end-to-end delay stats. Therefore, start counting received frames once
2344 // |ntp_time_ms| is valid.
2345 if (video_frame.ntp_time_ms() > 0 &&
2346 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() >=
2347 video_frame.ntp_time_ms()) {
2348 rtc::CritScope lock(&crit_);
2349 ++num_frames_received_;
2350 }
2351 }
tommi2e82f382016-06-21 00:26:43 -07002352
Åsa Persson3c391cb2015-04-27 10:09:49 +02002353 Action OnSendRtp(const uint8_t* packet, size_t length) override {
asapersson1394c7b2016-10-18 11:50:50 -07002354 if (MinMetricRunTimePassed() && MinNumberOfFramesReceived())
Peter Boström5811a392015-12-10 13:02:50 +01002355 observation_complete_.Set();
Åsa Persson3c391cb2015-04-27 10:09:49 +02002356
stefanf116bd02015-10-27 08:29:42 -07002357 return SEND_PACKET;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002358 }
2359
2360 bool MinMetricRunTimePassed() {
2361 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2362 if (start_runtime_ms_ == -1) {
2363 start_runtime_ms_ = now;
2364 return false;
2365 }
2366 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2367 return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
2368 }
2369
asapersson1394c7b2016-10-18 11:50:50 -07002370 bool MinNumberOfFramesReceived() const {
2371 const int kMinRequiredHistogramSamples = 200;
2372 rtc::CritScope lock(&crit_);
2373 return num_frames_received_ > kMinRequiredHistogramSamples;
2374 }
2375
stefanff483612015-12-21 03:14:00 -08002376 void ModifyVideoConfigs(
2377 VideoSendStream::Config* send_config,
2378 std::vector<VideoReceiveStream::Config>* receive_configs,
2379 VideoEncoderConfig* encoder_config) override {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002380 // NACK
2381 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2382 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
tommi2e82f382016-06-21 00:26:43 -07002383 (*receive_configs)[0].renderer = this;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002384 // FEC
2385 if (use_red_) {
brandtrb5f2c3f2016-10-04 23:28:39 -07002386 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
2387 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
Peter Boström39593972016-02-15 11:27:15 +01002388 send_config->encoder_settings.encoder = vp8_encoder_.get();
2389 send_config->encoder_settings.payload_name = "VP8";
2390 (*receive_configs)[0].decoders[0].payload_name = "VP8";
brandtrb5f2c3f2016-10-04 23:28:39 -07002391 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
2392 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type =
2393 kUlpfecPayloadType;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002394 }
2395 // RTX
2396 if (use_rtx_) {
2397 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
2398 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
brandtr14742122017-01-27 04:53:07 -08002399 (*receive_configs)[0].rtp.rtx_ssrc = kSendRtxSsrcs[0];
2400 (*receive_configs)[0].rtp.rtx_payload_types[kFakeVideoSendPayloadType] =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002401 kSendRtxPayloadType;
2402 }
asapersson1490f7a2016-09-23 02:09:46 -07002403 // RTT needed for RemoteNtpTimeEstimator for the receive stream.
2404 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = true;
sprangb4a1ae52015-12-03 08:10:08 -08002405 encoder_config->content_type =
2406 screenshare_ ? VideoEncoderConfig::ContentType::kScreen
2407 : VideoEncoderConfig::ContentType::kRealtimeVideo;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002408 }
2409
2410 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2411 sender_call_ = sender_call;
2412 receiver_call_ = receiver_call;
2413 }
2414
Åsa Persson3c391cb2015-04-27 10:09:49 +02002415 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002416 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson3c391cb2015-04-27 10:09:49 +02002417 }
2418
asapersson1394c7b2016-10-18 11:50:50 -07002419 rtc::CriticalSection crit_;
sprangb4a1ae52015-12-03 08:10:08 -08002420 const bool use_rtx_;
2421 const bool use_red_;
2422 const bool screenshare_;
kwiberg27f982b2016-03-01 11:52:33 -08002423 const std::unique_ptr<VideoEncoder> vp8_encoder_;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002424 Call* sender_call_;
2425 Call* receiver_call_;
2426 int64_t start_runtime_ms_;
asapersson1394c7b2016-10-18 11:50:50 -07002427 int num_frames_received_ GUARDED_BY(&crit_);
sprangb4a1ae52015-12-03 08:10:08 -08002428 } test(use_rtx, use_red, screenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002429
asapersson01d70a32016-05-20 06:29:46 -07002430 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002431 RunBaseTest(&test);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002432
stefan91d92602015-11-11 10:13:02 -08002433 // Delete the call for Call stats to be reported.
stefan18adf0a2015-11-17 06:24:56 -08002434 sender_call_.reset();
stefan91d92602015-11-11 10:13:02 -08002435 receiver_call_.reset();
2436
sprangb4a1ae52015-12-03 08:10:08 -08002437 std::string video_prefix =
2438 screenshare ? "WebRTC.Video.Screenshare." : "WebRTC.Video.";
2439
Åsa Persson3c391cb2015-04-27 10:09:49 +02002440 // Verify that stats have been updated once.
asapersson4374a092016-07-27 00:39:09 -07002441 EXPECT_EQ(2, metrics::NumSamples("WebRTC.Call.LifetimeInSeconds"));
asapersson01d70a32016-05-20 06:29:46 -07002442 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
2443 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.RtcpBitrateReceivedInBps"));
2444 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.BitrateReceivedInKbps"));
2445 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.EstimatedSendBitrateInKbps"));
2446 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.PacerBitrateInKbps"));
2447
asapersson4374a092016-07-27 00:39:09 -07002448 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
2449 EXPECT_EQ(1,
2450 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
2451
asapersson01d70a32016-05-20 06:29:46 -07002452 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
stefan91d92602015-11-11 10:13:02 -08002453 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002454 metrics::NumSamples(video_prefix + "NackPacketsReceivedPerMinute"));
2455 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
asaperssond89920b2015-07-22 06:52:00 -07002456 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002457 metrics::NumSamples(video_prefix + "FirPacketsReceivedPerMinute"));
2458 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
sprangb4a1ae52015-12-03 08:10:08 -08002459 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002460 metrics::NumSamples(video_prefix + "PliPacketsReceivedPerMinute"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002461
asapersson01d70a32016-05-20 06:29:46 -07002462 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "KeyFramesSentInPermille"));
2463 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
2464
2465 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentPacketsLostInPercent"));
2466 EXPECT_EQ(1,
2467 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
2468
2469 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputWidthInPixels"));
2470 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputHeightInPixels"));
2471 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentWidthInPixels"));
2472 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentHeightInPixels"));
2473 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
2474 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
2475
perkjfa10b552016-10-02 23:45:26 -07002476 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputWidthInPixels",
2477 kDefaultWidth));
2478 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputHeightInPixels",
2479 kDefaultHeight));
2480 EXPECT_EQ(
2481 1, metrics::NumEvents(video_prefix + "SentWidthInPixels", kDefaultWidth));
2482 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "SentHeightInPixels",
2483 kDefaultHeight));
2484 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedWidthInPixels",
2485 kDefaultWidth));
2486 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedHeightInPixels",
2487 kDefaultHeight));
asapersson01d70a32016-05-20 06:29:46 -07002488
2489 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputFramesPerSecond"));
2490 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentFramesPerSecond"));
2491 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
2492 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
2493
2494 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
2495 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
2496 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
2497 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
2498
asapersson1490f7a2016-09-23 02:09:46 -07002499 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.EndToEndDelayInMs"));
asapersson01d70a32016-05-20 06:29:46 -07002500 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
2501
2502 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EncodeTimeInMs"));
2503 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
2504
asapersson66d4b372016-12-19 06:50:53 -08002505 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "NumberOfPauseEvents"));
2506 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PausedTimeInPercent"));
2507
asapersson01d70a32016-05-20 06:29:46 -07002508 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "BitrateSentInKbps"));
2509 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateReceivedInKbps"));
2510 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "MediaBitrateSentInKbps"));
2511 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateReceivedInKbps"));
2512 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PaddingBitrateSentInKbps"));
2513 EXPECT_EQ(1,
2514 metrics::NumSamples("WebRTC.Video.PaddingBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002515 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002516 1, metrics::NumSamples(video_prefix + "RetransmittedBitrateSentInKbps"));
2517 EXPECT_EQ(1, metrics::NumSamples(
2518 "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002519
asapersson01d70a32016-05-20 06:29:46 -07002520 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendDelayInMs"));
2521 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayInMs"));
2522 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayMaxInMs"));
asapersson6f14be82015-11-16 00:40:49 -08002523
Åsa Persson3c391cb2015-04-27 10:09:49 +02002524 int num_rtx_samples = use_rtx ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002525 EXPECT_EQ(num_rtx_samples,
2526 metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2527 EXPECT_EQ(num_rtx_samples,
2528 metrics::NumSamples("WebRTC.Video.RtxBitrateReceivedInKbps"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002529
2530 int num_red_samples = use_red ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002531 EXPECT_EQ(num_red_samples,
2532 metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2533 EXPECT_EQ(num_red_samples,
2534 metrics::NumSamples("WebRTC.Video.FecBitrateReceivedInKbps"));
2535 EXPECT_EQ(num_red_samples,
2536 metrics::NumSamples("WebRTC.Video.ReceivedFecPacketsInPercent"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002537}
2538
philipel266f0a42016-11-28 08:49:07 -08002539TEST_P(EndToEndTest, VerifyHistogramStatsWithRtx) {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002540 const bool kEnabledRtx = true;
2541 const bool kEnabledRed = false;
sprangb4a1ae52015-12-03 08:10:08 -08002542 const bool kScreenshare = false;
2543 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002544}
2545
philipel266f0a42016-11-28 08:49:07 -08002546TEST_P(EndToEndTest, VerifyHistogramStatsWithRed) {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002547 const bool kEnabledRtx = false;
2548 const bool kEnabledRed = true;
sprangb4a1ae52015-12-03 08:10:08 -08002549 const bool kScreenshare = false;
2550 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
2551}
2552
philipel266f0a42016-11-28 08:49:07 -08002553TEST_P(EndToEndTest, VerifyHistogramStatsWithScreenshare) {
sprangb4a1ae52015-12-03 08:10:08 -08002554 const bool kEnabledRtx = false;
2555 const bool kEnabledRed = false;
2556 const bool kScreenshare = true;
2557 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002558}
2559
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002560void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
2561 bool send_single_ssrc_first) {
2562 class SendsSetSsrcs : public test::EndToEndTest {
2563 public:
2564 SendsSetSsrcs(const uint32_t* ssrcs,
2565 size_t num_ssrcs,
2566 bool send_single_ssrc_first)
2567 : EndToEndTest(kDefaultTimeoutMs),
2568 num_ssrcs_(num_ssrcs),
2569 send_single_ssrc_first_(send_single_ssrc_first),
2570 ssrcs_to_observe_(num_ssrcs),
sprang867fb522015-08-03 04:38:41 -07002571 expect_single_ssrc_(send_single_ssrc_first),
2572 send_stream_(nullptr) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002573 for (size_t i = 0; i < num_ssrcs; ++i)
2574 valid_ssrcs_[ssrcs[i]] = true;
2575 }
2576
2577 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002578 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002579 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002580 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002581
2582 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
2583 << "Received unknown SSRC: " << header.ssrc;
2584
2585 if (!valid_ssrcs_[header.ssrc])
Peter Boström5811a392015-12-10 13:02:50 +01002586 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002587
2588 if (!is_observed_[header.ssrc]) {
2589 is_observed_[header.ssrc] = true;
2590 --ssrcs_to_observe_;
2591 if (expect_single_ssrc_) {
2592 expect_single_ssrc_ = false;
Peter Boström5811a392015-12-10 13:02:50 +01002593 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002594 }
2595 }
2596
2597 if (ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002598 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002599
2600 return SEND_PACKET;
2601 }
2602
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002603 size_t GetNumVideoStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002604
perkjfa10b552016-10-02 23:45:26 -07002605 // This test use other VideoStream settings than the the default settings
2606 // implemented in DefaultVideoStreamFactory. Therefore this test implement
2607 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
2608 // in ModifyVideoConfigs.
2609 class VideoStreamFactory
2610 : public VideoEncoderConfig::VideoStreamFactoryInterface {
2611 public:
2612 VideoStreamFactory() {}
2613
2614 private:
2615 std::vector<VideoStream> CreateEncoderStreams(
2616 int width,
2617 int height,
2618 const VideoEncoderConfig& encoder_config) override {
2619 std::vector<VideoStream> streams =
2620 test::CreateVideoStreams(width, height, encoder_config);
2621 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
2622 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
2623 streams[i].min_bitrate_bps = 10000;
2624 streams[i].target_bitrate_bps = 15000;
2625 streams[i].max_bitrate_bps = 20000;
2626 }
2627 return streams;
2628 }
2629 };
2630
stefanff483612015-12-21 03:14:00 -08002631 void ModifyVideoConfigs(
2632 VideoSendStream::Config* send_config,
2633 std::vector<VideoReceiveStream::Config>* receive_configs,
2634 VideoEncoderConfig* encoder_config) override {
perkjfa10b552016-10-02 23:45:26 -07002635 encoder_config->video_stream_factory =
2636 new rtc::RefCountedObject<VideoStreamFactory>();
perkj26091b12016-09-01 01:17:40 -07002637 video_encoder_config_all_streams_ = encoder_config->Copy();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002638 if (send_single_ssrc_first_)
perkjfa10b552016-10-02 23:45:26 -07002639 encoder_config->number_of_streams = 1;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002640 }
2641
stefanff483612015-12-21 03:14:00 -08002642 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002643 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002644 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002645 send_stream_ = send_stream;
2646 }
2647
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002648 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002649 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2650 << (send_single_ssrc_first_ ? "first SSRC."
2651 : "SSRCs.");
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002652
2653 if (send_single_ssrc_first_) {
2654 // Set full simulcast and continue with the rest of the SSRCs.
stefanff483612015-12-21 03:14:00 -08002655 send_stream_->ReconfigureVideoEncoder(
perkj26091b12016-09-01 01:17:40 -07002656 std::move(video_encoder_config_all_streams_));
Peter Boström5811a392015-12-10 13:02:50 +01002657 EXPECT_TRUE(Wait()) << "Timed out while waiting on additional SSRCs.";
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002658 }
2659 }
2660
2661 private:
2662 std::map<uint32_t, bool> valid_ssrcs_;
2663 std::map<uint32_t, bool> is_observed_;
2664
2665 const size_t num_ssrcs_;
2666 const bool send_single_ssrc_first_;
2667
2668 size_t ssrcs_to_observe_;
2669 bool expect_single_ssrc_;
2670
2671 VideoSendStream* send_stream_;
stefanff483612015-12-21 03:14:00 -08002672 VideoEncoderConfig video_encoder_config_all_streams_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002673 } test(kVideoSendSsrcs, num_ssrcs, send_single_ssrc_first);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002674
stefane74eef12016-01-08 06:47:13 -08002675 RunBaseTest(&test);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002676}
2677
philipel266f0a42016-11-28 08:49:07 -08002678TEST_P(EndToEndTest, ReportsSetEncoderRates) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002679 class EncoderRateStatsTest : public test::EndToEndTest,
2680 public test::FakeEncoder {
2681 public:
2682 EncoderRateStatsTest()
2683 : EndToEndTest(kDefaultTimeoutMs),
sprang867fb522015-08-03 04:38:41 -07002684 FakeEncoder(Clock::GetRealTimeClock()),
2685 send_stream_(nullptr),
2686 bitrate_kbps_(0) {}
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002687
stefanff483612015-12-21 03:14:00 -08002688 void OnVideoStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002689 VideoSendStream* send_stream,
2690 const std::vector<VideoReceiveStream*>& receive_streams) override {
2691 send_stream_ = send_stream;
2692 }
2693
stefanff483612015-12-21 03:14:00 -08002694 void ModifyVideoConfigs(
2695 VideoSendStream::Config* send_config,
2696 std::vector<VideoReceiveStream::Config>* receive_configs,
2697 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002698 send_config->encoder_settings.encoder = this;
kwibergaf476c72016-11-28 15:21:39 -08002699 RTC_DCHECK_EQ(1, encoder_config->number_of_streams);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002700 }
2701
Erik Språng08127a92016-11-16 16:41:30 +01002702 int32_t SetRateAllocation(const BitrateAllocation& rate_allocation,
2703 uint32_t framerate) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002704 // Make sure not to trigger on any default zero bitrates.
Erik Språng08127a92016-11-16 16:41:30 +01002705 if (rate_allocation.get_sum_bps() == 0)
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002706 return 0;
Peter Boströmf2f82832015-05-01 13:00:41 +02002707 rtc::CritScope lock(&crit_);
Erik Språng08127a92016-11-16 16:41:30 +01002708 bitrate_kbps_ = rate_allocation.get_sum_kbps();
Peter Boström5811a392015-12-10 13:02:50 +01002709 observation_complete_.Set();
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002710 return 0;
2711 }
2712
2713 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002714 ASSERT_TRUE(Wait())
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002715 << "Timed out while waiting for encoder SetRates() call.";
perkjf5b2e512016-07-05 08:34:04 -07002716 WaitForEncoderTargetBitrateMatchStats();
2717 send_stream_->Stop();
2718 WaitForStatsReportZeroTargetBitrate();
2719 send_stream_->Start();
2720 WaitForEncoderTargetBitrateMatchStats();
2721 }
2722
2723 void WaitForEncoderTargetBitrateMatchStats() {
Peter Boström5811a392015-12-10 13:02:50 +01002724 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002725 VideoSendStream::Stats stats = send_stream_->GetStats();
2726 {
Peter Boströmf2f82832015-05-01 13:00:41 +02002727 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002728 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
2729 static_cast<int>(bitrate_kbps_)) {
2730 return;
2731 }
2732 }
2733 SleepMs(1);
2734 }
2735 FAIL()
2736 << "Timed out waiting for stats reporting the currently set bitrate.";
2737 }
2738
perkjf5b2e512016-07-05 08:34:04 -07002739 void WaitForStatsReportZeroTargetBitrate() {
2740 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
2741 if (send_stream_->GetStats().target_media_bitrate_bps == 0) {
2742 return;
2743 }
2744 SleepMs(1);
2745 }
2746 FAIL() << "Timed out waiting for stats reporting zero bitrate.";
2747 }
2748
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002749 private:
stefanf116bd02015-10-27 08:29:42 -07002750 rtc::CriticalSection crit_;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002751 VideoSendStream* send_stream_;
2752 uint32_t bitrate_kbps_ GUARDED_BY(crit_);
2753 } test;
2754
stefane74eef12016-01-08 06:47:13 -08002755 RunBaseTest(&test);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002756}
2757
philipel266f0a42016-11-28 08:49:07 -08002758TEST_P(EndToEndTest, GetStats) {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002759 static const int kStartBitrateBps = 3000000;
Peter Boströmdef398832015-05-27 17:59:11 +02002760 static const int kExpectedRenderDelayMs = 20;
tommi2e82f382016-06-21 00:26:43 -07002761
2762 class ReceiveStreamRenderer : public rtc::VideoSinkInterface<VideoFrame> {
2763 public:
2764 ReceiveStreamRenderer() {}
2765
2766 private:
2767 void OnFrame(const VideoFrame& video_frame) override {}
2768 };
2769
nissed30a1112016-04-18 05:15:22 -07002770 class StatsObserver : public test::EndToEndTest,
2771 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002772 public:
stefanf116bd02015-10-27 08:29:42 -07002773 StatsObserver()
2774 : EndToEndTest(kLongTimeoutMs),
Peter Boströmc6e16e32016-02-05 14:15:53 +01002775 encoder_(Clock::GetRealTimeClock(), 10),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002776 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002777 expected_send_ssrcs_(),
Peter Boström5811a392015-12-10 13:02:50 +01002778 check_stats_event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002779
2780 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002781 Action OnSendRtp(const uint8_t* packet, size_t length) override {
sprangcd349d92016-07-13 09:11:28 -07002782 // Drop every 25th packet => 4% loss.
2783 static const int kPacketLossFrac = 25;
2784 RTPHeader header;
2785 RtpUtility::RtpHeaderParser parser(packet, length);
2786 if (parser.Parse(&header) &&
2787 expected_send_ssrcs_.find(header.ssrc) !=
2788 expected_send_ssrcs_.end() &&
2789 header.sequenceNumber % kPacketLossFrac == 0) {
2790 return DROP_PACKET;
2791 }
Peter Boström5811a392015-12-10 13:02:50 +01002792 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002793 return SEND_PACKET;
2794 }
2795
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002796 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002797 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002798 return SEND_PACKET;
2799 }
2800
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002801 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002802 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002803 return SEND_PACKET;
2804 }
2805
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002806 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002807 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002808 return SEND_PACKET;
2809 }
2810
nissed30a1112016-04-18 05:15:22 -07002811 void OnFrame(const VideoFrame& video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002812 // Ensure that we have at least 5ms send side delay.
nissed30a1112016-04-18 05:15:22 -07002813 SleepMs(5);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002814 }
2815
2816 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002817 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2818 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2819 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002820
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002821 // Make sure all fields have been populated.
2822 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
2823 // always filled for all receivers.
2824 receive_stats_filled_["IncomingRate"] |=
2825 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002826
Peter Boströmb7d9a972015-12-18 16:01:11 +01002827 send_stats_filled_["DecoderImplementationName"] |=
2828 stats.decoder_implementation_name ==
2829 test::FakeDecoder::kImplementationName;
Peter Boströmdef398832015-05-27 17:59:11 +02002830 receive_stats_filled_["RenderDelayAsHighAsExpected"] |=
2831 stats.render_delay_ms >= kExpectedRenderDelayMs;
2832
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002833 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002834
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002835 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002836
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002837 receive_stats_filled_["StatisticsUpdated"] |=
2838 stats.rtcp_stats.cumulative_lost != 0 ||
2839 stats.rtcp_stats.extended_max_sequence_number != 0 ||
2840 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002841
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002842 receive_stats_filled_["DataCountersUpdated"] |=
2843 stats.rtp_stats.transmitted.payload_bytes != 0 ||
2844 stats.rtp_stats.fec.packets != 0 ||
2845 stats.rtp_stats.transmitted.header_bytes != 0 ||
2846 stats.rtp_stats.transmitted.packets != 0 ||
2847 stats.rtp_stats.transmitted.padding_bytes != 0 ||
2848 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002849
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002850 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002851 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002852
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002853 receive_stats_filled_["FrameCounts"] |=
2854 stats.frame_counts.key_frames != 0 ||
2855 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002856
pbosbb36fdf2015-07-09 07:48:14 -07002857 receive_stats_filled_["CName"] |= !stats.c_name.empty();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002858
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002859 receive_stats_filled_["RtcpPacketTypeCount"] |=
2860 stats.rtcp_packet_type_counts.fir_packets != 0 ||
2861 stats.rtcp_packet_type_counts.nack_packets != 0 ||
2862 stats.rtcp_packet_type_counts.pli_packets != 0 ||
2863 stats.rtcp_packet_type_counts.nack_requests != 0 ||
2864 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbosf42376c2015-08-28 07:35:32 -07002865
2866 assert(stats.current_payload_type == -1 ||
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002867 stats.current_payload_type == kFakeVideoSendPayloadType);
pbosf42376c2015-08-28 07:35:32 -07002868 receive_stats_filled_["IncomingPayloadType"] |=
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002869 stats.current_payload_type == kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002870 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002871
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002872 return AllStatsFilled(receive_stats_filled_);
2873 }
2874
2875 bool CheckSendStats() {
Peter Boström74f6e9e2016-04-04 17:56:10 +02002876 RTC_DCHECK(send_stream_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002877 VideoSendStream::Stats stats = send_stream_->GetStats();
2878
philipel20d05a92016-12-19 04:17:27 -08002879 size_t expected_num_streams = kNumSsrcs + expected_send_ssrcs_.size();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002880 send_stats_filled_["NumStreams"] |=
philipel20d05a92016-12-19 04:17:27 -08002881 stats.substreams.size() == expected_num_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002882
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002883 send_stats_filled_["CpuOveruseMetrics"] |=
Peter Boströme4499152016-02-05 11:13:28 +01002884 stats.avg_encode_time_ms != 0 && stats.encode_usage_percent != 0;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002885
Peter Boströmb7d9a972015-12-18 16:01:11 +01002886 send_stats_filled_["EncoderImplementationName"] |=
2887 stats.encoder_implementation_name ==
2888 test::FakeEncoder::kImplementationName;
2889
Pera48ddb72016-09-29 11:48:50 +02002890 send_stats_filled_["EncoderPreferredBitrate"] |=
2891 stats.preferred_media_bitrate_bps > 0;
2892
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002893 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002894 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002895 it != stats.substreams.end(); ++it) {
sprangcd349d92016-07-13 09:11:28 -07002896 if (expected_send_ssrcs_.find(it->first) == expected_send_ssrcs_.end())
2897 continue; // Probably RTX.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002898
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002899 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002900 stats.input_frame_rate != 0;
2901
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002902 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002903
2904 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
2905 stream_stats.rtcp_stats.cumulative_lost != 0 ||
2906 stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
2907 stream_stats.rtcp_stats.fraction_lost != 0;
2908
2909 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002910 stream_stats.rtp_stats.fec.packets != 0 ||
2911 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
2912 stream_stats.rtp_stats.retransmitted.packets != 0 ||
2913 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002914
sprangcd349d92016-07-13 09:11:28 -07002915 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Total",
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002916 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002917 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002918
sprangcd349d92016-07-13 09:11:28 -07002919 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Retransmit",
2920 it->first)] |=
2921 stream_stats.retransmit_bitrate_bps != 0;
2922
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002923 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002924 stream_stats.frame_counts.delta_frames != 0 ||
2925 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002926
2927 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
2928 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00002929
2930 send_stats_filled_[CompoundKey("Delay", it->first)] |=
2931 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002932
2933 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
2934 // report dropped packets.
2935 send_stats_filled_["RtcpPacketTypeCount"] |=
2936 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
2937 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
2938 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
2939 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
2940 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002941 }
2942
2943 return AllStatsFilled(send_stats_filled_);
2944 }
2945
2946 std::string CompoundKey(const char* name, uint32_t ssrc) {
2947 std::ostringstream oss;
2948 oss << name << "_" << ssrc;
2949 return oss.str();
2950 }
2951
2952 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
sprangcd349d92016-07-13 09:11:28 -07002953 for (const auto& stat : stats_map) {
2954 if (!stat.second)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002955 return false;
2956 }
2957 return true;
2958 }
2959
stefane74eef12016-01-08 06:47:13 -08002960 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
2961 FakeNetworkPipe::Config network_config;
2962 network_config.loss_percent = 5;
2963 return new test::PacketTransport(
2964 sender_call, this, test::PacketTransport::kSender, network_config);
2965 }
2966
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002967 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002968 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01002969 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002970 return config;
2971 }
2972
perkjfa10b552016-10-02 23:45:26 -07002973 // This test use other VideoStream settings than the the default settings
2974 // implemented in DefaultVideoStreamFactory. Therefore this test implement
2975 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
2976 // in ModifyVideoConfigs.
2977 class VideoStreamFactory
2978 : public VideoEncoderConfig::VideoStreamFactoryInterface {
2979 public:
2980 VideoStreamFactory() {}
2981
2982 private:
2983 std::vector<VideoStream> CreateEncoderStreams(
2984 int width,
2985 int height,
2986 const VideoEncoderConfig& encoder_config) override {
2987 std::vector<VideoStream> streams =
2988 test::CreateVideoStreams(width, height, encoder_config);
2989 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
2990 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
2991 streams[i].min_bitrate_bps = 10000;
2992 streams[i].target_bitrate_bps = 15000;
2993 streams[i].max_bitrate_bps = 20000;
2994 }
2995 return streams;
2996 }
2997 };
2998
stefanff483612015-12-21 03:14:00 -08002999 void ModifyVideoConfigs(
3000 VideoSendStream::Config* send_config,
3001 std::vector<VideoReceiveStream::Config>* receive_configs,
3002 VideoEncoderConfig* encoder_config) override {
perkjfa10b552016-10-02 23:45:26 -07003003 encoder_config->video_stream_factory =
3004 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003005 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003006 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003007
sprangcd349d92016-07-13 09:11:28 -07003008 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
3009 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
3010
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003011 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003012 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003013 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003014 expected_receive_ssrcs_.push_back(
3015 (*receive_configs)[i].rtp.remote_ssrc);
Peter Boströmdef398832015-05-27 17:59:11 +02003016 (*receive_configs)[i].render_delay_ms = kExpectedRenderDelayMs;
tommi2e82f382016-06-21 00:26:43 -07003017 (*receive_configs)[i].renderer = &receive_stream_renderer_;
sprangcd349d92016-07-13 09:11:28 -07003018 (*receive_configs)[i].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
3019
brandtr14742122017-01-27 04:53:07 -08003020 (*receive_configs)[i].rtp.rtx_ssrc = kSendRtxSsrcs[i];
3021 (*receive_configs)[i].rtp.rtx_payload_types[kFakeVideoSendPayloadType] =
sprangcd349d92016-07-13 09:11:28 -07003022 kSendRtxPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003023 }
sprangcd349d92016-07-13 09:11:28 -07003024
3025 for (size_t i = 0; i < kNumSsrcs; ++i)
3026 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
3027
Peter Boströmc6e16e32016-02-05 14:15:53 +01003028 // Use a delayed encoder to make sure we see CpuOveruseMetrics stats that
3029 // are non-zero.
3030 send_config->encoder_settings.encoder = &encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003031 }
3032
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003033 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00003034
stefanff483612015-12-21 03:14:00 -08003035 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003036 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003037 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003038 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003039 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003040 }
3041
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003042 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003043 Clock* clock = Clock::GetRealTimeClock();
3044 int64_t now = clock->TimeInMilliseconds();
3045 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
3046 bool receive_ok = false;
3047 bool send_ok = false;
3048
3049 while (now < stop_time) {
3050 if (!receive_ok)
3051 receive_ok = CheckReceiveStats();
3052 if (!send_ok)
3053 send_ok = CheckSendStats();
3054
3055 if (receive_ok && send_ok)
3056 return;
3057
3058 int64_t time_until_timout_ = stop_time - now;
3059 if (time_until_timout_ > 0)
Peter Boström5811a392015-12-10 13:02:50 +01003060 check_stats_event_.Wait(time_until_timout_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003061 now = clock->TimeInMilliseconds();
3062 }
3063
3064 ADD_FAILURE() << "Timed out waiting for filled stats.";
3065 for (std::map<std::string, bool>::const_iterator it =
3066 receive_stats_filled_.begin();
3067 it != receive_stats_filled_.end();
3068 ++it) {
3069 if (!it->second) {
3070 ADD_FAILURE() << "Missing receive stats: " << it->first;
3071 }
3072 }
3073
3074 for (std::map<std::string, bool>::const_iterator it =
3075 send_stats_filled_.begin();
3076 it != send_stats_filled_.end();
3077 ++it) {
3078 if (!it->second) {
3079 ADD_FAILURE() << "Missing send stats: " << it->first;
3080 }
3081 }
3082 }
3083
Peter Boströmc6e16e32016-02-05 14:15:53 +01003084 test::DelayedEncoder encoder_;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003085 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003086 std::map<std::string, bool> receive_stats_filled_;
3087
3088 VideoSendStream* send_stream_;
3089 std::map<std::string, bool> send_stats_filled_;
3090
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003091 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003092 std::set<uint32_t> expected_send_ssrcs_;
3093 std::string expected_cname_;
3094
Peter Boström5811a392015-12-10 13:02:50 +01003095 rtc::Event check_stats_event_;
tommi2e82f382016-06-21 00:26:43 -07003096 ReceiveStreamRenderer receive_stream_renderer_;
stefanf116bd02015-10-27 08:29:42 -07003097 } test;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003098
stefane74eef12016-01-08 06:47:13 -08003099 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003100}
3101
sprang1a646ee2016-12-01 06:34:11 -08003102class RtcpXrObserver : public test::EndToEndTest {
3103 public:
sprang44b3ef62017-01-13 07:30:25 -08003104 RtcpXrObserver(bool enable_rrtr, bool enable_target_bitrate)
sprang1a646ee2016-12-01 06:34:11 -08003105 : EndToEndTest(test::CallTest::kDefaultTimeoutMs),
3106 enable_rrtr_(enable_rrtr),
sprang44b3ef62017-01-13 07:30:25 -08003107 enable_target_bitrate_(enable_target_bitrate),
sprang1a646ee2016-12-01 06:34:11 -08003108 sent_rtcp_sr_(0),
3109 sent_rtcp_rr_(0),
3110 sent_rtcp_rrtr_(0),
3111 sent_rtcp_target_bitrate_(false),
3112 sent_rtcp_dlrr_(0) {}
3113
3114 private:
3115 // Receive stream should send RR packets (and RRTR packets if enabled).
3116 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
3117 rtc::CritScope lock(&crit_);
3118 test::RtcpPacketParser parser;
3119 EXPECT_TRUE(parser.Parse(packet, length));
3120
3121 sent_rtcp_rr_ += parser.receiver_report()->num_packets();
3122 EXPECT_EQ(0, parser.sender_report()->num_packets());
3123 EXPECT_GE(1, parser.xr()->num_packets());
3124 if (parser.xr()->num_packets() > 0) {
3125 if (parser.xr()->rrtr())
3126 ++sent_rtcp_rrtr_;
3127 EXPECT_FALSE(parser.xr()->dlrr());
3128 }
3129
3130 return SEND_PACKET;
3131 }
3132 // Send stream should send SR packets (and DLRR packets if enabled).
3133 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
3134 rtc::CritScope lock(&crit_);
3135 test::RtcpPacketParser parser;
3136 EXPECT_TRUE(parser.Parse(packet, length));
3137
3138 sent_rtcp_sr_ += parser.sender_report()->num_packets();
3139 EXPECT_LE(parser.xr()->num_packets(), 1);
3140 if (parser.xr()->num_packets() > 0) {
3141 EXPECT_FALSE(parser.xr()->rrtr());
3142 if (parser.xr()->dlrr())
3143 ++sent_rtcp_dlrr_;
3144 if (parser.xr()->target_bitrate())
3145 sent_rtcp_target_bitrate_ = true;
3146 }
3147
3148 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
3149 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve &&
sprang44b3ef62017-01-13 07:30:25 -08003150 (sent_rtcp_target_bitrate_ || !enable_target_bitrate_)) {
sprang1a646ee2016-12-01 06:34:11 -08003151 if (enable_rrtr_) {
3152 EXPECT_GT(sent_rtcp_rrtr_, 0);
3153 EXPECT_GT(sent_rtcp_dlrr_, 0);
3154 } else {
3155 EXPECT_EQ(sent_rtcp_rrtr_, 0);
3156 EXPECT_EQ(sent_rtcp_dlrr_, 0);
3157 }
sprang44b3ef62017-01-13 07:30:25 -08003158 EXPECT_EQ(enable_target_bitrate_, sent_rtcp_target_bitrate_);
sprang1a646ee2016-12-01 06:34:11 -08003159 observation_complete_.Set();
3160 }
3161 return SEND_PACKET;
3162 }
3163
3164 void ModifyVideoConfigs(
3165 VideoSendStream::Config* send_config,
3166 std::vector<VideoReceiveStream::Config>* receive_configs,
3167 VideoEncoderConfig* encoder_config) override {
sprang44b3ef62017-01-13 07:30:25 -08003168 if (enable_target_bitrate_) {
3169 // TargetBitrate only signaled for screensharing.
3170 encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
3171 }
sprang1a646ee2016-12-01 06:34:11 -08003172 (*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
3173 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
3174 enable_rrtr_;
3175 }
3176
3177 void PerformTest() override {
3178 EXPECT_TRUE(Wait())
3179 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
3180 }
3181
3182 static const int kNumRtcpReportPacketsToObserve = 5;
3183
3184 rtc::CriticalSection crit_;
sprang44b3ef62017-01-13 07:30:25 -08003185 const bool enable_rrtr_;
3186 const bool enable_target_bitrate_;
sprang1a646ee2016-12-01 06:34:11 -08003187 int sent_rtcp_sr_;
3188 int sent_rtcp_rr_ GUARDED_BY(&crit_);
3189 int sent_rtcp_rrtr_ GUARDED_BY(&crit_);
3190 bool sent_rtcp_target_bitrate_ GUARDED_BY(&crit_);
3191 int sent_rtcp_dlrr_;
3192};
3193
sprang44b3ef62017-01-13 07:30:25 -08003194TEST_P(EndToEndTest, TestExtendedReportsWithRrtrWithoutTargetBitrate) {
3195 RtcpXrObserver test(true, false);
sprang1a646ee2016-12-01 06:34:11 -08003196 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003197}
3198
sprang44b3ef62017-01-13 07:30:25 -08003199TEST_P(EndToEndTest, TestExtendedReportsWithoutRrtrWithoutTargetBitrate) {
3200 RtcpXrObserver test(false, false);
3201 RunBaseTest(&test);
3202}
3203
3204TEST_P(EndToEndTest, TestExtendedReportsWithRrtrWithTargetBitrate) {
3205 RtcpXrObserver test(true, true);
3206 RunBaseTest(&test);
3207}
3208
3209TEST_P(EndToEndTest, TestExtendedReportsWithoutRrtrWithTargetBitrate) {
3210 RtcpXrObserver test(false, true);
sprang1a646ee2016-12-01 06:34:11 -08003211 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003212}
3213
philipel266f0a42016-11-28 08:49:07 -08003214TEST_P(EndToEndTest, TestReceivedRtpPacketStats) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003215 static const size_t kNumRtpPacketsToSend = 5;
3216 class ReceivedRtpStatsObserver : public test::EndToEndTest {
3217 public:
3218 ReceivedRtpStatsObserver()
3219 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00003220 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003221 sent_rtp_(0) {}
3222
3223 private:
stefanff483612015-12-21 03:14:00 -08003224 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003225 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003226 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003227 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003228 }
3229
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003230 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003231 if (sent_rtp_ >= kNumRtpPacketsToSend) {
3232 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00003233 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
Peter Boström5811a392015-12-10 13:02:50 +01003234 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003235 }
3236 return DROP_PACKET;
3237 }
3238 ++sent_rtp_;
3239 return SEND_PACKET;
3240 }
3241
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003242 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003243 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003244 << "Timed out while verifying number of received RTP packets.";
3245 }
3246
3247 VideoReceiveStream* receive_stream_;
3248 uint32_t sent_rtp_;
3249 } test;
3250
stefane74eef12016-01-08 06:47:13 -08003251 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003252}
3253
philipel266f0a42016-11-28 08:49:07 -08003254TEST_P(EndToEndTest, SendsSetSsrc) {
3255 TestSendsSetSsrcs(1, false);
3256}
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003257
philipel266f0a42016-11-28 08:49:07 -08003258TEST_P(EndToEndTest, SendsSetSimulcastSsrcs) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003259 TestSendsSetSsrcs(kNumSsrcs, false);
3260}
3261
philipel266f0a42016-11-28 08:49:07 -08003262TEST_P(EndToEndTest, CanSwitchToUseAllSsrcs) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003263 TestSendsSetSsrcs(kNumSsrcs, true);
3264}
3265
philipel266f0a42016-11-28 08:49:07 -08003266TEST_P(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003267 class ObserveRedundantPayloads: public test::EndToEndTest {
3268 public:
3269 ObserveRedundantPayloads()
3270 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003271 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003272 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
3273 }
3274 }
3275
3276 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003277 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003278 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003279 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003280
3281 if (!registered_rtx_ssrc_[header.ssrc])
3282 return SEND_PACKET;
3283
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003284 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003285 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003286 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003287
3288 if (!packet_is_redundant_payload)
3289 return SEND_PACKET;
3290
3291 if (!observed_redundant_retransmission_[header.ssrc]) {
3292 observed_redundant_retransmission_[header.ssrc] = true;
3293 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01003294 observation_complete_.Set();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003295 }
3296
3297 return SEND_PACKET;
3298 }
3299
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003300 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003301
perkjfa10b552016-10-02 23:45:26 -07003302 // This test use other VideoStream settings than the the default settings
3303 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3304 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3305 // in ModifyVideoConfigs.
3306 class VideoStreamFactory
3307 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3308 public:
3309 VideoStreamFactory() {}
3310
3311 private:
3312 std::vector<VideoStream> CreateEncoderStreams(
3313 int width,
3314 int height,
3315 const VideoEncoderConfig& encoder_config) override {
3316 std::vector<VideoStream> streams =
3317 test::CreateVideoStreams(width, height, encoder_config);
3318 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
3319 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3320 streams[i].min_bitrate_bps = 10000;
3321 streams[i].target_bitrate_bps = 15000;
3322 streams[i].max_bitrate_bps = 20000;
3323 }
3324 return streams;
3325 }
3326 };
3327
stefanff483612015-12-21 03:14:00 -08003328 void ModifyVideoConfigs(
3329 VideoSendStream::Config* send_config,
3330 std::vector<VideoReceiveStream::Config>* receive_configs,
3331 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003332 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
perkjfa10b552016-10-02 23:45:26 -07003333 encoder_config->video_stream_factory =
3334 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003335 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003336
3337 for (size_t i = 0; i < kNumSsrcs; ++i)
3338 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00003339
3340 // Significantly higher than max bitrates for all video streams -> forcing
3341 // padding to trigger redundant padding on all RTX SSRCs.
3342 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003343 }
3344
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003345 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003346 EXPECT_TRUE(Wait())
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003347 << "Timed out while waiting for redundant payloads on all SSRCs.";
3348 }
3349
3350 private:
3351 size_t ssrcs_to_observe_;
3352 std::map<uint32_t, bool> observed_redundant_retransmission_;
3353 std::map<uint32_t, bool> registered_rtx_ssrc_;
3354 } test;
3355
stefane74eef12016-01-08 06:47:13 -08003356 RunBaseTest(&test);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003357}
3358
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003359void EndToEndTest::TestRtpStatePreservation(bool use_rtx,
3360 bool provoke_rtcpsr_before_rtp) {
perkjfa10b552016-10-02 23:45:26 -07003361 // This test use other VideoStream settings than the the default settings
3362 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3363 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3364 // in ModifyVideoConfigs.
3365 class VideoStreamFactory
3366 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3367 public:
3368 VideoStreamFactory() {}
3369
3370 private:
3371 std::vector<VideoStream> CreateEncoderStreams(
3372 int width,
3373 int height,
3374 const VideoEncoderConfig& encoder_config) override {
3375 std::vector<VideoStream> streams =
3376 test::CreateVideoStreams(width, height, encoder_config);
3377
3378 if (encoder_config.number_of_streams > 1) {
3379 // Lower bitrates so that all streams send initially.
kwibergaf476c72016-11-28 15:21:39 -08003380 RTC_DCHECK_EQ(3, encoder_config.number_of_streams);
perkjfa10b552016-10-02 23:45:26 -07003381 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3382 streams[i].min_bitrate_bps = 10000;
3383 streams[i].target_bitrate_bps = 15000;
3384 streams[i].max_bitrate_bps = 20000;
3385 }
3386 } else {
3387 // Use the same total bitrates when sending a single stream to avoid
3388 // lowering
3389 // the bitrate estimate and requiring a subsequent rampup.
3390 streams[0].min_bitrate_bps = 3 * 10000;
3391 streams[0].target_bitrate_bps = 3 * 15000;
3392 streams[0].max_bitrate_bps = 3 * 20000;
3393 }
3394 return streams;
3395 }
3396 };
3397
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003398 class RtpSequenceObserver : public test::RtpRtcpObserver {
3399 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003400 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003401 : test::RtpRtcpObserver(kDefaultTimeoutMs),
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003402 ssrcs_to_observe_(kNumSsrcs) {
3403 for (size_t i = 0; i < kNumSsrcs; ++i) {
danilchap32cd2c42016-08-01 06:58:34 -07003404 ssrc_is_rtx_[kVideoSendSsrcs[i]] = false;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003405 if (use_rtx)
danilchap32cd2c42016-08-01 06:58:34 -07003406 ssrc_is_rtx_[kSendRtxSsrcs[i]] = true;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003407 }
3408 }
3409
3410 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
Peter Boströmf2f82832015-05-01 13:00:41 +02003411 rtc::CritScope lock(&crit_);
danilchap34877ee2016-02-01 08:25:04 -08003412 ssrc_observed_.clear();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003413 ssrcs_to_observe_ = num_expected_ssrcs;
3414 }
3415
3416 private:
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003417 void ValidateTimestampGap(uint32_t ssrc,
3418 uint32_t timestamp,
3419 bool only_padding)
3420 EXCLUSIVE_LOCKS_REQUIRED(crit_) {
3421 static const int32_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
3422 auto timestamp_it = last_observed_timestamp_.find(ssrc);
3423 if (timestamp_it == last_observed_timestamp_.end()) {
3424 EXPECT_FALSE(only_padding);
3425 last_observed_timestamp_[ssrc] = timestamp;
3426 } else {
3427 // Verify timestamps are reasonably close.
3428 uint32_t latest_observed = timestamp_it->second;
3429 // Wraparound handling is unnecessary here as long as an int variable
3430 // is used to store the result.
3431 int32_t timestamp_gap = timestamp - latest_observed;
3432 EXPECT_LE(std::abs(timestamp_gap), kMaxTimestampGap)
3433 << "Gap in timestamps (" << latest_observed << " -> " << timestamp
3434 << ") too large for SSRC: " << ssrc << ".";
3435 timestamp_it->second = timestamp;
3436 }
3437 }
3438
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003439 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003440 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003441 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003442 const uint32_t ssrc = header.ssrc;
danilchap5c35cf92016-02-03 14:14:49 -08003443 const int64_t sequence_number =
3444 seq_numbers_unwrapper_.Unwrap(header.sequenceNumber);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003445 const uint32_t timestamp = header.timestamp;
danilchap34877ee2016-02-01 08:25:04 -08003446 const bool only_padding =
3447 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003448
danilchap32cd2c42016-08-01 06:58:34 -07003449 EXPECT_TRUE(ssrc_is_rtx_.find(ssrc) != ssrc_is_rtx_.end())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003450 << "Received SSRC that wasn't configured: " << ssrc;
3451
danilchap5c35cf92016-02-03 14:14:49 -08003452 static const int64_t kMaxSequenceNumberGap = 100;
3453 std::list<int64_t>* seq_numbers = &last_observed_seq_numbers_[ssrc];
3454 if (seq_numbers->empty()) {
3455 seq_numbers->push_back(sequence_number);
3456 } else {
3457 // We shouldn't get replays of previous sequence numbers.
3458 for (int64_t observed : *seq_numbers) {
3459 EXPECT_NE(observed, sequence_number)
3460 << "Received sequence number " << sequence_number
3461 << " for SSRC " << ssrc << " 2nd time.";
3462 }
3463 // Verify sequence numbers are reasonably close.
3464 int64_t latest_observed = seq_numbers->back();
3465 int64_t sequence_number_gap = sequence_number - latest_observed;
3466 EXPECT_LE(std::abs(sequence_number_gap), kMaxSequenceNumberGap)
3467 << "Gap in sequence numbers (" << latest_observed << " -> "
3468 << sequence_number << ") too large for SSRC: " << ssrc << ".";
3469 seq_numbers->push_back(sequence_number);
3470 if (seq_numbers->size() >= kMaxSequenceNumberGap) {
3471 seq_numbers->pop_front();
3472 }
3473 }
3474
danilchap32cd2c42016-08-01 06:58:34 -07003475 if (!ssrc_is_rtx_[ssrc]) {
3476 rtc::CritScope lock(&crit_);
3477 ValidateTimestampGap(ssrc, timestamp, only_padding);
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003478
danilchap32cd2c42016-08-01 06:58:34 -07003479 // Wait for media packets on all ssrcs.
3480 if (!ssrc_observed_[ssrc] && !only_padding) {
3481 ssrc_observed_[ssrc] = true;
3482 if (--ssrcs_to_observe_ == 0)
3483 observation_complete_.Set();
3484 }
danilchap34877ee2016-02-01 08:25:04 -08003485 }
3486
danilchapf4b9c772016-01-28 06:14:24 -08003487 return SEND_PACKET;
3488 }
3489
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003490 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
3491 test::RtcpPacketParser rtcp_parser;
3492 rtcp_parser.Parse(packet, length);
3493 if (rtcp_parser.sender_report()->num_packets() > 0) {
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02003494 uint32_t ssrc = rtcp_parser.sender_report()->sender_ssrc();
3495 uint32_t rtcp_timestamp = rtcp_parser.sender_report()->rtp_timestamp();
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003496
3497 rtc::CritScope lock(&crit_);
3498 ValidateTimestampGap(ssrc, rtcp_timestamp, false);
3499 }
3500 return SEND_PACKET;
3501 }
3502
danilchap5c35cf92016-02-03 14:14:49 -08003503 SequenceNumberUnwrapper seq_numbers_unwrapper_;
3504 std::map<uint32_t, std::list<int64_t>> last_observed_seq_numbers_;
danilchap34877ee2016-02-01 08:25:04 -08003505 std::map<uint32_t, uint32_t> last_observed_timestamp_;
danilchap32cd2c42016-08-01 06:58:34 -07003506 std::map<uint32_t, bool> ssrc_is_rtx_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003507
Peter Boströmf2f82832015-05-01 13:00:41 +02003508 rtc::CriticalSection crit_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003509 size_t ssrcs_to_observe_ GUARDED_BY(crit_);
danilchap34877ee2016-02-01 08:25:04 -08003510 std::map<uint32_t, bool> ssrc_observed_ GUARDED_BY(crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003511 } observer(use_rtx);
3512
skvlad11a9cbf2016-10-07 11:53:05 -07003513 Call::Config config(&event_log_);
3514 CreateCalls(config, config);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003515
stefanf116bd02015-10-27 08:29:42 -07003516 test::PacketTransport send_transport(sender_call_.get(), &observer,
3517 test::PacketTransport::kSender,
3518 FakeNetworkPipe::Config());
3519 test::PacketTransport receive_transport(nullptr, &observer,
3520 test::PacketTransport::kReceiver,
3521 FakeNetworkPipe::Config());
3522 send_transport.SetReceiver(receiver_call_->Receiver());
3523 receive_transport.SetReceiver(sender_call_->Receiver());
3524
brandtr841de6a2016-11-15 07:10:52 -08003525 CreateSendConfig(kNumSsrcs, 0, 0, &send_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003526
3527 if (use_rtx) {
3528 for (size_t i = 0; i < kNumSsrcs; ++i) {
stefanff483612015-12-21 03:14:00 -08003529 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003530 }
stefanff483612015-12-21 03:14:00 -08003531 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003532 }
3533
perkjfa10b552016-10-02 23:45:26 -07003534 video_encoder_config_.video_stream_factory =
3535 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003536 // Use the same total bitrates when sending a single stream to avoid lowering
3537 // the bitrate estimate and requiring a subsequent rampup.
perkj26091b12016-09-01 01:17:40 -07003538 VideoEncoderConfig one_stream = video_encoder_config_.Copy();
perkjfa10b552016-10-02 23:45:26 -07003539 // one_stream.streams.resize(1);
3540 one_stream.number_of_streams = 1;
stefanf116bd02015-10-27 08:29:42 -07003541 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003542
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003543 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003544 CreateFrameGeneratorCapturer(30, 1280, 720);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003545
3546 Start();
Peter Boström5811a392015-12-10 13:02:50 +01003547 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003548 << "Timed out waiting for all SSRCs to send packets.";
3549
3550 // Test stream resetting more than once to make sure that the state doesn't
3551 // get set once (this could be due to using std::map::insert for instance).
3552 for (size_t i = 0; i < 3; ++i) {
3553 frame_generator_capturer_->Stop();
stefanff483612015-12-21 03:14:00 -08003554 sender_call_->DestroyVideoSendStream(video_send_stream_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003555
3556 // Re-create VideoSendStream with only one stream.
perkj26091b12016-09-01 01:17:40 -07003557 video_send_stream_ = sender_call_->CreateVideoSendStream(
3558 video_send_config_.Copy(), one_stream.Copy());
stefanff483612015-12-21 03:14:00 -08003559 video_send_stream_->Start();
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003560 if (provoke_rtcpsr_before_rtp) {
3561 // Rapid Resync Request forces sending RTCP Sender Report back.
3562 // Using this request speeds up this test because then there is no need
3563 // to wait for a second for periodic Sender Report.
3564 rtcp::RapidResyncRequest force_send_sr_back_request;
3565 rtc::Buffer packet = force_send_sr_back_request.Build();
3566 static_cast<webrtc::test::DirectTransport&>(receive_transport)
3567 .SendRtcp(packet.data(), packet.size());
3568 }
perkjfa10b552016-10-02 23:45:26 -07003569 CreateFrameGeneratorCapturer(30, 1280, 720);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003570 frame_generator_capturer_->Start();
3571
3572 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003573 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003574
3575 // Reconfigure back to use all streams.
perkj26091b12016-09-01 01:17:40 -07003576 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003577 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003578 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003579 << "Timed out waiting for all SSRCs to send packets.";
3580
3581 // Reconfigure down to one stream.
perkj26091b12016-09-01 01:17:40 -07003582 video_send_stream_->ReconfigureVideoEncoder(one_stream.Copy());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003583 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003584 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003585
3586 // Reconfigure back to use all streams.
perkj26091b12016-09-01 01:17:40 -07003587 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003588 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003589 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003590 << "Timed out waiting for all SSRCs to send packets.";
3591 }
3592
stefanf116bd02015-10-27 08:29:42 -07003593 send_transport.StopSending();
3594 receive_transport.StopSending();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003595
3596 Stop();
3597 DestroyStreams();
3598}
3599
philipel266f0a42016-11-28 08:49:07 -08003600TEST_P(EndToEndTest, RestartingSendStreamPreservesRtpState) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003601 TestRtpStatePreservation(false, false);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003602}
3603
philipel266f0a42016-11-28 08:49:07 -08003604TEST_P(EndToEndTest, RestartingSendStreamPreservesRtpStatesWithRtx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003605 TestRtpStatePreservation(true, false);
3606}
3607
philipel266f0a42016-11-28 08:49:07 -08003608TEST_P(EndToEndTest, RestartingSendStreamKeepsRtpAndRtcpTimestampsSynced) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003609 TestRtpStatePreservation(true, true);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003610}
3611
philipel266f0a42016-11-28 08:49:07 -08003612TEST_P(EndToEndTest, RespectsNetworkState) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003613 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
3614 // down blocks until no more packets will be sent.
3615
3616 // Pacer will send from its packet list and then send required padding before
3617 // checking paused_ again. This should be enough for one round of pacing,
3618 // otherwise increase.
3619 static const int kNumAcceptedDowntimeRtp = 5;
3620 // A single RTCP may be in the pipeline.
3621 static const int kNumAcceptedDowntimeRtcp = 1;
3622 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
3623 public:
3624 NetworkStateTest()
3625 : EndToEndTest(kDefaultTimeoutMs),
3626 FakeEncoder(Clock::GetRealTimeClock()),
Peter Boström5811a392015-12-10 13:02:50 +01003627 encoded_frames_(false, false),
3628 packet_event_(false, false),
sprang867fb522015-08-03 04:38:41 -07003629 sender_call_(nullptr),
3630 receiver_call_(nullptr),
Jelena Marusiccd670222015-07-16 09:30:09 +02003631 sender_state_(kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003632 sender_rtp_(0),
3633 sender_rtcp_(0),
3634 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003635 down_frames_(0) {}
3636
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003637 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003638 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003639 ++sender_rtp_;
Peter Boström5811a392015-12-10 13:02:50 +01003640 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003641 return SEND_PACKET;
3642 }
3643
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003644 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003645 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003646 ++sender_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003647 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003648 return SEND_PACKET;
3649 }
3650
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003651 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003652 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
3653 return SEND_PACKET;
3654 }
3655
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003656 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003657 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003658 ++receiver_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003659 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003660 return SEND_PACKET;
3661 }
3662
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003663 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003664 sender_call_ = sender_call;
3665 receiver_call_ = receiver_call;
3666 }
3667
stefanff483612015-12-21 03:14:00 -08003668 void ModifyVideoConfigs(
3669 VideoSendStream::Config* send_config,
3670 std::vector<VideoReceiveStream::Config>* receive_configs,
3671 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003672 send_config->encoder_settings.encoder = this;
3673 }
3674
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003675 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003676 EXPECT_TRUE(encoded_frames_.Wait(kDefaultTimeoutMs))
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003677 << "No frames received by the encoder.";
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003678 // Wait for packets from both sender/receiver.
3679 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003680
skvlad7a43d252016-03-22 15:32:27 -07003681 // Sender-side network down for audio; there should be no effect on video
3682 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3683 WaitForPacketsOrSilence(false, false);
3684
3685 // Receiver-side network down for audio; no change expected
3686 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3687 WaitForPacketsOrSilence(false, false);
3688
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003689 // Sender-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003690 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003691 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003692 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003693 // After network goes down we shouldn't be encoding more frames.
Jelena Marusiccd670222015-07-16 09:30:09 +02003694 sender_state_ = kNetworkDown;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003695 }
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003696 // Wait for receiver-packets and no sender packets.
3697 WaitForPacketsOrSilence(true, false);
3698
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003699 // Receiver-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003700 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
3701 WaitForPacketsOrSilence(true, true);
3702
3703 // Network up for audio for both sides; video is still not expected to
3704 // start
3705 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
3706 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003707 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003708
3709 // Network back up again for both.
3710 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003711 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003712 // It's OK to encode frames again, as we're about to bring up the
3713 // network.
Jelena Marusiccd670222015-07-16 09:30:09 +02003714 sender_state_ = kNetworkUp;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003715 }
skvlad7a43d252016-03-22 15:32:27 -07003716 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
3717 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003718 WaitForPacketsOrSilence(false, false);
skvlad7a43d252016-03-22 15:32:27 -07003719
3720 // TODO(skvlad): add tests to verify that the audio streams are stopped
3721 // when the network goes down for audio once the workaround in
3722 // paced_sender.cc is removed.
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003723 }
3724
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07003725 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003726 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07003727 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003728 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003729 rtc::CritScope lock(&test_crit_);
Jelena Marusiccd670222015-07-16 09:30:09 +02003730 if (sender_state_ == kNetworkDown) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003731 ++down_frames_;
3732 EXPECT_LE(down_frames_, 1)
3733 << "Encoding more than one frame while network is down.";
3734 if (down_frames_ > 1)
Peter Boström5811a392015-12-10 13:02:50 +01003735 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003736 } else {
Peter Boström5811a392015-12-10 13:02:50 +01003737 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003738 }
3739 }
3740 return test::FakeEncoder::Encode(
3741 input_image, codec_specific_info, frame_types);
3742 }
3743
3744 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003745 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
3746 int64_t initial_time_ms = clock_->TimeInMilliseconds();
3747 int initial_sender_rtp;
3748 int initial_sender_rtcp;
3749 int initial_receiver_rtcp;
3750 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003751 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003752 initial_sender_rtp = sender_rtp_;
3753 initial_sender_rtcp = sender_rtcp_;
3754 initial_receiver_rtcp = receiver_rtcp_;
3755 }
3756 bool sender_done = false;
3757 bool receiver_done = false;
mflodmand1590b22015-12-09 07:07:59 -08003758 while (!sender_done || !receiver_done) {
Peter Boström5811a392015-12-10 13:02:50 +01003759 packet_event_.Wait(kSilenceTimeoutMs);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003760 int64_t time_now_ms = clock_->TimeInMilliseconds();
Peter Boströmf2f82832015-05-01 13:00:41 +02003761 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003762 if (sender_down) {
3763 ASSERT_LE(sender_rtp_ - initial_sender_rtp, kNumAcceptedDowntimeRtp)
3764 << "RTP sent during sender-side downtime.";
3765 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
3766 kNumAcceptedDowntimeRtcp)
3767 << "RTCP sent during sender-side downtime.";
3768 if (time_now_ms - initial_time_ms >=
3769 static_cast<int64_t>(kSilenceTimeoutMs)) {
3770 sender_done = true;
3771 }
3772 } else {
skvlad7a43d252016-03-22 15:32:27 -07003773 if (sender_rtp_ > initial_sender_rtp + kNumAcceptedDowntimeRtp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003774 sender_done = true;
3775 }
3776 if (receiver_down) {
3777 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
3778 kNumAcceptedDowntimeRtcp)
3779 << "RTCP sent during receiver-side downtime.";
3780 if (time_now_ms - initial_time_ms >=
3781 static_cast<int64_t>(kSilenceTimeoutMs)) {
3782 receiver_done = true;
3783 }
3784 } else {
skvlad7a43d252016-03-22 15:32:27 -07003785 if (receiver_rtcp_ > initial_receiver_rtcp + kNumAcceptedDowntimeRtcp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003786 receiver_done = true;
3787 }
3788 }
3789 }
3790
Peter Boströmf2f82832015-05-01 13:00:41 +02003791 rtc::CriticalSection test_crit_;
Peter Boström5811a392015-12-10 13:02:50 +01003792 rtc::Event encoded_frames_;
3793 rtc::Event packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003794 Call* sender_call_;
3795 Call* receiver_call_;
Jelena Marusiccd670222015-07-16 09:30:09 +02003796 NetworkState sender_state_ GUARDED_BY(test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003797 int sender_rtp_ GUARDED_BY(test_crit_);
3798 int sender_rtcp_ GUARDED_BY(test_crit_);
3799 int receiver_rtcp_ GUARDED_BY(test_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003800 int down_frames_ GUARDED_BY(test_crit_);
3801 } test;
3802
stefane74eef12016-01-08 06:47:13 -08003803 RunBaseTest(&test);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003804}
3805
philipel266f0a42016-11-28 08:49:07 -08003806TEST_P(EndToEndTest, CallReportsRttForSender) {
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003807 static const int kSendDelayMs = 30;
3808 static const int kReceiveDelayMs = 70;
skvlad11a9cbf2016-10-07 11:53:05 -07003809 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -07003810
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003811 FakeNetworkPipe::Config config;
3812 config.queue_delay_ms = kSendDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003813 test::DirectTransport sender_transport(config, sender_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003814 config.queue_delay_ms = kReceiveDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003815 test::DirectTransport receiver_transport(config, receiver_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003816 sender_transport.SetReceiver(receiver_call_->Receiver());
3817 receiver_transport.SetReceiver(sender_call_->Receiver());
3818
brandtr841de6a2016-11-15 07:10:52 -08003819 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07003820 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003821
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003822 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003823 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
3824 kDefaultHeight);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003825 Start();
3826
3827 int64_t start_time_ms = clock_->TimeInMilliseconds();
3828 while (true) {
3829 Call::Stats stats = sender_call_->GetStats();
3830 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
3831 clock_->TimeInMilliseconds())
3832 << "No RTT stats before timeout!";
3833 if (stats.rtt_ms != -1) {
Danil Chapovalov10e8f8e2016-09-07 15:05:29 +02003834 // To avoid failures caused by rounding or minor ntp clock adjustments,
3835 // relax expectation by 1ms.
3836 constexpr int kAllowedErrorMs = 1;
3837 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs - kAllowedErrorMs);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003838 break;
3839 }
3840 SleepMs(10);
3841 }
3842
philipel266f0a42016-11-28 08:49:07 -08003843 sender_transport.StopSending();
3844 receiver_transport.StopSending();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003845 Stop();
3846 DestroyStreams();
philipel266f0a42016-11-28 08:49:07 -08003847 DestroyCalls();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003848}
3849
skvlad7a43d252016-03-22 15:32:27 -07003850void EndToEndTest::VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08003851 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -07003852 VideoEncoder* encoder,
3853 Transport* transport) {
skvlad11a9cbf2016-10-07 11:53:05 -07003854 CreateSenderCall(Call::Config(&event_log_));
Sergey Ulanove2b15012016-11-22 16:08:30 -08003855 sender_call_->SignalChannelNetworkState(network_to_bring_up, kNetworkUp);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003856
brandtr841de6a2016-11-15 07:10:52 -08003857 CreateSendConfig(1, 0, 0, transport);
skvlad7a43d252016-03-22 15:32:27 -07003858 video_send_config_.encoder_settings.encoder = encoder;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003859 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003860 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
3861 kDefaultHeight);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003862
3863 Start();
3864 SleepMs(kSilenceTimeoutMs);
3865 Stop();
3866
3867 DestroyStreams();
3868}
3869
skvlad7a43d252016-03-22 15:32:27 -07003870void EndToEndTest::VerifyNewVideoReceiveStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08003871 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -07003872 Transport* transport) {
skvlad11a9cbf2016-10-07 11:53:05 -07003873 Call::Config config(&event_log_);
3874 CreateCalls(config, config);
Sergey Ulanove2b15012016-11-22 16:08:30 -08003875 receiver_call_->SignalChannelNetworkState(network_to_bring_up, kNetworkUp);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003876
stefanf116bd02015-10-27 08:29:42 -07003877 test::DirectTransport sender_transport(sender_call_.get());
solenberg4fbae2b2015-08-28 04:07:10 -07003878 sender_transport.SetReceiver(receiver_call_->Receiver());
brandtr841de6a2016-11-15 07:10:52 -08003879 CreateSendConfig(1, 0, 0, &sender_transport);
skvlad7a43d252016-03-22 15:32:27 -07003880 CreateMatchingReceiveConfigs(transport);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003881 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003882 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
3883 kDefaultHeight);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003884
3885 Start();
3886 SleepMs(kSilenceTimeoutMs);
3887 Stop();
3888
3889 sender_transport.StopSending();
3890
3891 DestroyStreams();
3892}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00003893
philipel266f0a42016-11-28 08:49:07 -08003894TEST_P(EndToEndTest, NewVideoSendStreamsRespectVideoNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07003895 class UnusedEncoder : public test::FakeEncoder {
3896 public:
3897 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
perkjfea93092016-05-14 00:58:48 -07003898
3899 int32_t InitEncode(const VideoCodec* config,
3900 int32_t number_of_cores,
3901 size_t max_payload_size) override {
3902 EXPECT_GT(config->startBitrate, 0u);
3903 return 0;
3904 }
skvlad7a43d252016-03-22 15:32:27 -07003905 int32_t Encode(const VideoFrame& input_image,
3906 const CodecSpecificInfo* codec_specific_info,
3907 const std::vector<FrameType>* frame_types) override {
3908 ADD_FAILURE() << "Unexpected frame encode.";
3909 return test::FakeEncoder::Encode(input_image, codec_specific_info,
3910 frame_types);
3911 }
3912 };
3913
3914 UnusedEncoder unused_encoder;
3915 UnusedTransport unused_transport;
3916 VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08003917 MediaType::AUDIO, &unused_encoder, &unused_transport);
skvlad7a43d252016-03-22 15:32:27 -07003918}
3919
philipel266f0a42016-11-28 08:49:07 -08003920TEST_P(EndToEndTest, NewVideoSendStreamsIgnoreAudioNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07003921 class RequiredEncoder : public test::FakeEncoder {
3922 public:
3923 RequiredEncoder()
3924 : FakeEncoder(Clock::GetRealTimeClock()), encoded_frame_(false) {}
3925 ~RequiredEncoder() {
3926 if (!encoded_frame_) {
3927 ADD_FAILURE() << "Didn't encode an expected frame";
3928 }
3929 }
3930 int32_t Encode(const VideoFrame& input_image,
3931 const CodecSpecificInfo* codec_specific_info,
3932 const std::vector<FrameType>* frame_types) override {
3933 encoded_frame_ = true;
3934 return test::FakeEncoder::Encode(input_image, codec_specific_info,
3935 frame_types);
3936 }
3937
3938 private:
3939 bool encoded_frame_;
3940 };
3941
3942 RequiredTransport required_transport(true /*rtp*/, false /*rtcp*/);
3943 RequiredEncoder required_encoder;
3944 VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08003945 MediaType::VIDEO, &required_encoder, &required_transport);
skvlad7a43d252016-03-22 15:32:27 -07003946}
3947
philipel266f0a42016-11-28 08:49:07 -08003948TEST_P(EndToEndTest, NewVideoReceiveStreamsRespectVideoNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07003949 UnusedTransport transport;
Sergey Ulanove2b15012016-11-22 16:08:30 -08003950 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::AUDIO, &transport);
skvlad7a43d252016-03-22 15:32:27 -07003951}
3952
philipel266f0a42016-11-28 08:49:07 -08003953TEST_P(EndToEndTest, NewVideoReceiveStreamsIgnoreAudioNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07003954 RequiredTransport transport(false /*rtp*/, true /*rtcp*/);
Sergey Ulanove2b15012016-11-22 16:08:30 -08003955 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::VIDEO, &transport);
skvlad7a43d252016-03-22 15:32:27 -07003956}
3957
Peter Boströmd7da1202015-06-05 14:09:38 +02003958void VerifyEmptyNackConfig(const NackConfig& config) {
3959 EXPECT_EQ(0, config.rtp_history_ms)
3960 << "Enabling NACK requires rtcp-fb: nack negotiation.";
3961}
3962
brandtrb5f2c3f2016-10-04 23:28:39 -07003963void VerifyEmptyUlpfecConfig(const UlpfecConfig& config) {
Peter Boströmd7da1202015-06-05 14:09:38 +02003964 EXPECT_EQ(-1, config.ulpfec_payload_type)
brandtr535830e2016-10-31 03:45:58 -07003965 << "Enabling ULPFEC requires rtpmap: ulpfec negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02003966 EXPECT_EQ(-1, config.red_payload_type)
brandtr535830e2016-10-31 03:45:58 -07003967 << "Enabling ULPFEC requires rtpmap: red negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02003968 EXPECT_EQ(-1, config.red_rtx_payload_type)
brandtr535830e2016-10-31 03:45:58 -07003969 << "Enabling RTX in ULPFEC requires rtpmap: rtx negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02003970}
3971
brandtr3d200bd2017-01-16 06:59:19 -08003972void VerifyEmptyFlexfecConfig(
3973 const VideoSendStream::Config::Rtp::Flexfec& config) {
3974 EXPECT_EQ(-1, config.payload_type)
brandtr1e3dfbf2016-11-16 22:45:19 -08003975 << "Enabling FlexFEC requires rtpmap: flexfec negotiation.";
brandtr3d200bd2017-01-16 06:59:19 -08003976 EXPECT_EQ(0U, config.ssrc)
brandtr1cfbd602016-12-08 04:17:53 -08003977 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
brandtr1e3dfbf2016-11-16 22:45:19 -08003978 EXPECT_TRUE(config.protected_media_ssrcs.empty())
3979 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
3980}
3981
philipel266f0a42016-11-28 08:49:07 -08003982TEST_P(EndToEndTest, VerifyDefaultSendConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003983 VideoSendStream::Config default_send_config(nullptr);
Peter Boströmd7da1202015-06-05 14:09:38 +02003984 EXPECT_EQ(0, default_send_config.rtp.nack.rtp_history_ms)
3985 << "Enabling NACK require rtcp-fb: nack negotiation.";
3986 EXPECT_TRUE(default_send_config.rtp.rtx.ssrcs.empty())
3987 << "Enabling RTX requires rtpmap: rtx negotiation.";
3988 EXPECT_TRUE(default_send_config.rtp.extensions.empty())
3989 << "Enabling RTP extensions require negotiation.";
3990
3991 VerifyEmptyNackConfig(default_send_config.rtp.nack);
brandtrb5f2c3f2016-10-04 23:28:39 -07003992 VerifyEmptyUlpfecConfig(default_send_config.rtp.ulpfec);
brandtr1e3dfbf2016-11-16 22:45:19 -08003993 VerifyEmptyFlexfecConfig(default_send_config.rtp.flexfec);
Peter Boströmd7da1202015-06-05 14:09:38 +02003994}
3995
philipel266f0a42016-11-28 08:49:07 -08003996TEST_P(EndToEndTest, VerifyDefaultVideoReceiveConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003997 VideoReceiveStream::Config default_receive_config(nullptr);
pbosda903ea2015-10-02 02:36:56 -07003998 EXPECT_EQ(RtcpMode::kCompound, default_receive_config.rtp.rtcp_mode)
Peter Boströmd7da1202015-06-05 14:09:38 +02003999 << "Reduced-size RTCP require rtcp-rsize to be negotiated.";
4000 EXPECT_FALSE(default_receive_config.rtp.remb)
4001 << "REMB require rtcp-fb: goog-remb to be negotiated.";
4002 EXPECT_FALSE(
4003 default_receive_config.rtp.rtcp_xr.receiver_reference_time_report)
4004 << "RTCP XR settings require rtcp-xr to be negotiated.";
brandtr14742122017-01-27 04:53:07 -08004005 EXPECT_EQ(0U, default_receive_config.rtp.rtx_ssrc)
4006 << "Enabling RTX requires ssrc-group: FID negotiation";
4007 EXPECT_TRUE(default_receive_config.rtp.rtx_payload_types.empty())
Peter Boströmd7da1202015-06-05 14:09:38 +02004008 << "Enabling RTX requires rtpmap: rtx negotiation.";
4009 EXPECT_TRUE(default_receive_config.rtp.extensions.empty())
4010 << "Enabling RTP extensions require negotiation.";
4011
4012 VerifyEmptyNackConfig(default_receive_config.rtp.nack);
brandtrb5f2c3f2016-10-04 23:28:39 -07004013 VerifyEmptyUlpfecConfig(default_receive_config.rtp.ulpfec);
Peter Boströmd7da1202015-06-05 14:09:38 +02004014}
4015
philipel266f0a42016-11-28 08:49:07 -08004016TEST_P(EndToEndTest, VerifyDefaultFlexfecReceiveConfigParameters) {
brandtr8313a6f2017-01-13 07:41:19 -08004017 test::NullTransport rtcp_send_transport;
4018 FlexfecReceiveStream::Config default_receive_config(&rtcp_send_transport);
brandtr1cfbd602016-12-08 04:17:53 -08004019 EXPECT_EQ(-1, default_receive_config.payload_type)
4020 << "Enabling FlexFEC requires rtpmap: flexfec negotiation.";
4021 EXPECT_EQ(0U, default_receive_config.remote_ssrc)
4022 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
4023 EXPECT_TRUE(default_receive_config.protected_media_ssrcs.empty())
4024 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
brandtr1e3dfbf2016-11-16 22:45:19 -08004025}
4026
philipel266f0a42016-11-28 08:49:07 -08004027TEST_P(EndToEndTest, TransportSeqNumOnAudioAndVideo) {
danilchap4336d732017-03-03 06:21:54 -08004028 static constexpr int kExtensionId = 8;
4029 static constexpr size_t kMinPacketsToWaitFor = 50;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004030 class TransportSequenceNumberTest : public test::EndToEndTest {
4031 public:
4032 TransportSequenceNumberTest()
4033 : EndToEndTest(kDefaultTimeoutMs),
4034 video_observed_(false),
4035 audio_observed_(false) {
4036 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
4037 kExtensionId);
4038 }
4039
4040 size_t GetNumVideoStreams() const override { return 1; }
4041 size_t GetNumAudioStreams() const override { return 1; }
4042
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004043 void ModifyAudioConfigs(
4044 AudioSendStream::Config* send_config,
4045 std::vector<AudioReceiveStream::Config>* receive_configs) override {
4046 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07004047 send_config->rtp.extensions.push_back(RtpExtension(
4048 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004049 (*receive_configs)[0].rtp.extensions.clear();
4050 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
4051 }
4052
4053 Action OnSendRtp(const uint8_t* packet, size_t length) override {
4054 RTPHeader header;
4055 EXPECT_TRUE(parser_->Parse(packet, length, &header));
4056 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
4057 // Unwrap packet id and verify uniqueness.
4058 int64_t packet_id =
4059 unwrapper_.Unwrap(header.extension.transportSequenceNumber);
4060 EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
4061
4062 if (header.ssrc == kVideoSendSsrcs[0])
4063 video_observed_ = true;
4064 if (header.ssrc == kAudioSendSsrc)
4065 audio_observed_ = true;
4066 if (audio_observed_ && video_observed_ &&
danilchap4336d732017-03-03 06:21:54 -08004067 received_packet_ids_.size() >= kMinPacketsToWaitFor) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004068 size_t packet_id_range =
4069 *received_packet_ids_.rbegin() - *received_packet_ids_.begin() + 1;
4070 EXPECT_EQ(received_packet_ids_.size(), packet_id_range);
4071 observation_complete_.Set();
4072 }
4073 return SEND_PACKET;
4074 }
4075
4076 void PerformTest() override {
4077 EXPECT_TRUE(Wait()) << "Timed out while waiting for audio and video "
4078 "packets with transport sequence number.";
4079 }
4080
danilchap4336d732017-03-03 06:21:54 -08004081 void ExpectSuccessful() {
4082 EXPECT_TRUE(video_observed_);
4083 EXPECT_TRUE(audio_observed_);
4084 EXPECT_GE(received_packet_ids_.size(), kMinPacketsToWaitFor);
4085 }
4086
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004087 private:
4088 bool video_observed_;
4089 bool audio_observed_;
4090 SequenceNumberUnwrapper unwrapper_;
4091 std::set<int64_t> received_packet_ids_;
4092 } test;
4093
stefane74eef12016-01-08 06:47:13 -08004094 RunBaseTest(&test);
danilchap4336d732017-03-03 06:21:54 -08004095 // Double check conditions for successful test to produce better error
4096 // message when the test fail.
4097 test.ExpectSuccessful();
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004098}
palmkviste75f2042016-09-28 06:19:48 -07004099
4100class EndToEndLogTest : public EndToEndTest {
4101 void SetUp() { paths_.clear(); }
4102 void TearDown() {
4103 for (const auto& path : paths_) {
4104 rtc::RemoveFile(path);
4105 }
4106 }
4107
4108 public:
4109 int AddFile() {
4110 paths_.push_back(test::TempFilename(test::OutputPath(), "test_file"));
4111 return static_cast<int>(paths_.size()) - 1;
4112 }
4113
4114 rtc::PlatformFile OpenFile(int idx) {
4115 return rtc::OpenPlatformFile(paths_[idx]);
4116 }
4117
4118 void LogSend(bool open) {
4119 if (open) {
4120 video_send_stream_->EnableEncodedFrameRecording(
4121 std::vector<rtc::PlatformFile>(1, OpenFile(AddFile())), 0);
4122 } else {
4123 video_send_stream_->DisableEncodedFrameRecording();
4124 }
4125 }
4126 void LogReceive(bool open) {
4127 if (open) {
4128 video_receive_streams_[0]->EnableEncodedFrameRecording(
4129 OpenFile(AddFile()), 0);
4130 } else {
4131 video_receive_streams_[0]->DisableEncodedFrameRecording();
4132 }
4133 }
4134
4135 std::vector<std::string> paths_;
4136};
4137
philipel266f0a42016-11-28 08:49:07 -08004138TEST_P(EndToEndLogTest, LogsEncodedFramesWhenRequested) {
palmkviste75f2042016-09-28 06:19:48 -07004139 static const int kNumFramesToRecord = 10;
4140 class LogEncodingObserver : public test::EndToEndTest,
4141 public EncodedFrameObserver {
4142 public:
4143 explicit LogEncodingObserver(EndToEndLogTest* fixture)
4144 : EndToEndTest(kDefaultTimeoutMs),
4145 fixture_(fixture),
4146 recorded_frames_(0) {}
4147
4148 void PerformTest() override {
4149 fixture_->LogSend(true);
4150 fixture_->LogReceive(true);
4151 ASSERT_TRUE(Wait()) << "Timed out while waiting for frame logging.";
4152 }
4153
4154 void ModifyVideoConfigs(
4155 VideoSendStream::Config* send_config,
4156 std::vector<VideoReceiveStream::Config>* receive_configs,
4157 VideoEncoderConfig* encoder_config) override {
magjed509e4fe2016-11-18 01:34:11 -08004158 encoder_.reset(VP8Encoder::Create());
palmkviste75f2042016-09-28 06:19:48 -07004159 decoder_.reset(VP8Decoder::Create());
4160
4161 send_config->post_encode_callback = this;
4162 send_config->encoder_settings.payload_name = "VP8";
4163 send_config->encoder_settings.encoder = encoder_.get();
4164
4165 (*receive_configs)[0].decoders.resize(1);
4166 (*receive_configs)[0].decoders[0].payload_type =
4167 send_config->encoder_settings.payload_type;
4168 (*receive_configs)[0].decoders[0].payload_name =
4169 send_config->encoder_settings.payload_name;
4170 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
4171 }
4172
4173 void EncodedFrameCallback(const EncodedFrame& encoded_frame) override {
4174 rtc::CritScope lock(&crit_);
4175 if (recorded_frames_++ > kNumFramesToRecord) {
4176 fixture_->LogSend(false);
4177 fixture_->LogReceive(false);
4178 rtc::File send_file(fixture_->OpenFile(0));
4179 rtc::File receive_file(fixture_->OpenFile(1));
4180 uint8_t out[100];
4181 // If logging has worked correctly neither file should be empty, i.e.
4182 // we should be able to read something from them.
4183 EXPECT_LT(0u, send_file.Read(out, 100));
4184 EXPECT_LT(0u, receive_file.Read(out, 100));
4185 observation_complete_.Set();
4186 }
4187 }
4188
4189 private:
4190 EndToEndLogTest* const fixture_;
4191 std::unique_ptr<VideoEncoder> encoder_;
4192 std::unique_ptr<VideoDecoder> decoder_;
4193 rtc::CriticalSection crit_;
4194 int recorded_frames_ GUARDED_BY(crit_);
4195 } test(this);
4196
4197 RunBaseTest(&test);
4198}
4199
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00004200} // namespace webrtc