blob: 7b796c00b440e4955425115f4857d18cf419b1f2 [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"
22#include "webrtc/base/rate_limiter.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000023#include "webrtc/call.h"
Peter Boström5c389d32015-09-25 13:58:30 +020024#include "webrtc/call/transport_adapter.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"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000033#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
sprangcd349d92016-07-13 09:11:28 -070034#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
hbosbab934b2016-01-27 01:36:03 -080035#include "webrtc/modules/video_coding/codecs/h264/include/h264.h"
marpan@webrtc.org5b883172014-11-01 06:10:48 +000036#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
37#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010038#include "webrtc/modules/video_coding/include/video_coding_defines.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010039#include "webrtc/system_wrappers/include/metrics.h"
asapersson01d70a32016-05-20 06:29:46 -070040#include "webrtc/system_wrappers/include/metrics_default.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010041#include "webrtc/system_wrappers/include/sleep.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000042#include "webrtc/test/call_test.h"
43#include "webrtc/test/direct_transport.h"
44#include "webrtc/test/encoder_settings.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000045#include "webrtc/test/fake_decoder.h"
46#include "webrtc/test/fake_encoder.h"
47#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"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000050#include "webrtc/test/null_transport.h"
asapersson@webrtc.org37c05592015-01-28 13:58:27 +000051#include "webrtc/test/rtcp_packet_parser.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000052#include "webrtc/test/rtp_rtcp_observer.h"
53#include "webrtc/test/testsupport/fileutils.h"
54#include "webrtc/test/testsupport/perf_test.h"
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +000055#include "webrtc/video_encoder.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000056
57namespace webrtc {
58
Peter Boström5811a392015-12-10 13:02:50 +010059static const int kSilenceTimeoutMs = 2000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000060
61class EndToEndTest : public test::CallTest {
62 public:
63 EndToEndTest() {}
64
65 virtual ~EndToEndTest() {
stefanff483612015-12-21 03:14:00 -080066 EXPECT_EQ(nullptr, video_send_stream_);
67 EXPECT_TRUE(video_receive_streams_.empty());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000068 }
69
70 protected:
pbos2d566682015-09-28 09:59:31 -070071 class UnusedTransport : public Transport {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000072 private:
stefan1d8a5062015-10-02 03:39:33 -070073 bool SendRtp(const uint8_t* packet,
74 size_t length,
75 const PacketOptions& options) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000076 ADD_FAILURE() << "Unexpected RTP sent.";
77 return false;
78 }
79
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000080 bool SendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000081 ADD_FAILURE() << "Unexpected RTCP sent.";
82 return false;
83 }
84 };
85
skvlad7a43d252016-03-22 15:32:27 -070086 class RequiredTransport : public Transport {
87 public:
88 RequiredTransport(bool rtp_required, bool rtcp_required)
89 : need_rtp_(rtp_required), need_rtcp_(rtcp_required) {}
90 ~RequiredTransport() {
91 if (need_rtp_) {
92 ADD_FAILURE() << "Expected RTP packet not sent.";
93 }
94 if (need_rtcp_) {
95 ADD_FAILURE() << "Expected RTCP packet not sent.";
96 }
97 }
98
99 private:
100 bool SendRtp(const uint8_t* packet,
101 size_t length,
102 const PacketOptions& options) override {
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700103 rtc::CritScope lock(&crit_);
skvlad7a43d252016-03-22 15:32:27 -0700104 need_rtp_ = false;
105 return true;
106 }
107
108 bool SendRtcp(const uint8_t* packet, size_t length) override {
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700109 rtc::CritScope lock(&crit_);
skvlad7a43d252016-03-22 15:32:27 -0700110 need_rtcp_ = false;
111 return true;
112 }
113 bool need_rtp_;
114 bool need_rtcp_;
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700115 rtc::CriticalSection crit_;
skvlad7a43d252016-03-22 15:32:27 -0700116 };
117
Peter Boström39593972016-02-15 11:27:15 +0100118 void DecodesRetransmittedFrame(bool enable_rtx, bool enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000119 void ReceivesPliAndRecovers(int rtp_history_ms);
pbosda903ea2015-10-02 02:36:56 -0700120 void RespectsRtcpMode(RtcpMode rtcp_mode);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000121 void TestXrReceiverReferenceTimeReport(bool enable_rrtr);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000122 void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200123 void TestRtpStatePreservation(bool use_rtx, bool provoke_rtcpsr_before_rtp);
sprangb4a1ae52015-12-03 08:10:08 -0800124 void VerifyHistogramStats(bool use_rtx, bool use_red, bool screenshare);
skvlad7a43d252016-03-22 15:32:27 -0700125 void VerifyNewVideoSendStreamsRespectNetworkState(
126 MediaType network_to_bring_down,
127 VideoEncoder* encoder,
128 Transport* transport);
129 void VerifyNewVideoReceiveStreamsRespectNetworkState(
130 MediaType network_to_bring_down,
131 Transport* transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000132};
133
134TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
skvlad11a9cbf2016-10-07 11:53:05 -0700135 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000136
solenberg4fbae2b2015-08-28 04:07:10 -0700137 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100138 CreateSendConfig(1, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700139 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000140
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100141 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000142
stefanff483612015-12-21 03:14:00 -0800143 video_receive_streams_[0]->Start();
144 video_receive_streams_[0]->Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000145
146 DestroyStreams();
147}
148
149TEST_F(EndToEndTest, ReceiverCanBeStoppedTwice) {
skvlad11a9cbf2016-10-07 11:53:05 -0700150 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000151
solenberg4fbae2b2015-08-28 04:07:10 -0700152 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100153 CreateSendConfig(1, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700154 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000155
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100156 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000157
stefanff483612015-12-21 03:14:00 -0800158 video_receive_streams_[0]->Stop();
159 video_receive_streams_[0]->Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000160
161 DestroyStreams();
162}
163
sprang113bdca2016-10-11 03:10:10 -0700164TEST_F(EndToEndTest, ReceiverCanBeStoppedAndRestarted) {
165 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
166
167 test::NullTransport transport;
168 CreateSendConfig(1, 0, &transport);
169 CreateMatchingReceiveConfigs(&transport);
170
171 CreateVideoStreams();
172
173 video_receive_streams_[0]->Stop();
174 video_receive_streams_[0]->Start();
175 video_receive_streams_[0]->Stop();
176
177 DestroyStreams();
178}
179
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000180TEST_F(EndToEndTest, RendersSingleDelayedFrame) {
181 static const int kWidth = 320;
182 static const int kHeight = 240;
183 // This constant is chosen to be higher than the timeout in the video_render
184 // module. This makes sure that frames aren't dropped if there are no other
185 // frames in the queue.
186 static const int kDelayRenderCallbackMs = 1000;
187
nisse7ade7b32016-03-23 04:48:10 -0700188 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000189 public:
Peter Boström5811a392015-12-10 13:02:50 +0100190 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000191
nisseeb83a1a2016-03-21 01:27:56 -0700192 void OnFrame(const VideoFrame& video_frame) override { event_.Set(); }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000193
Peter Boström5811a392015-12-10 13:02:50 +0100194 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000195
Peter Boström5811a392015-12-10 13:02:50 +0100196 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000197 } renderer;
198
199 class TestFrameCallback : public I420FrameCallback {
200 public:
Peter Boström5811a392015-12-10 13:02:50 +0100201 TestFrameCallback() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000202
Peter Boström5811a392015-12-10 13:02:50 +0100203 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000204
205 private:
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700206 void FrameCallback(VideoFrame* frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000207 SleepMs(kDelayRenderCallbackMs);
Peter Boström5811a392015-12-10 13:02:50 +0100208 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000209 }
210
Peter Boström5811a392015-12-10 13:02:50 +0100211 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000212 };
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
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100221 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700222 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000223
224 TestFrameCallback pre_render_callback;
stefanff483612015-12-21 03:14:00 -0800225 video_receive_configs_[0].pre_render_callback = &pre_render_callback;
226 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000227
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100228 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000229 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000230
231 // Create frames that are smaller than the send width/height, this is done to
232 // check that the callbacks are done after processing video.
kwiberg27f982b2016-03-01 11:52:33 -0800233 std::unique_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000234 test::FrameGenerator::CreateChromaGenerator(kWidth, kHeight));
perkja49cbd32016-09-16 07:53:41 -0700235 test::FrameForwarder frame_forwarder;
perkj803d97f2016-11-01 11:45:46 -0700236 video_send_stream_->SetSource(
237 &frame_forwarder, VideoSendStream::DegradationPreference::kBalanced);
perkja49cbd32016-09-16 07:53:41 -0700238
239 frame_forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
Peter Boström5811a392015-12-10 13:02:50 +0100240 EXPECT_TRUE(pre_render_callback.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000241 << "Timed out while waiting for pre-render callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100242 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000243 << "Timed out while waiting for the frame to render.";
244
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000245 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000246
247 sender_transport.StopSending();
248 receiver_transport.StopSending();
249
250 DestroyStreams();
251}
252
253TEST_F(EndToEndTest, TransmitsFirstFrame) {
nisse7ade7b32016-03-23 04:48:10 -0700254 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000255 public:
Peter Boström5811a392015-12-10 13:02:50 +0100256 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000257
nisseeb83a1a2016-03-21 01:27:56 -0700258 void OnFrame(const VideoFrame& video_frame) override { event_.Set(); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000259
Peter Boström5811a392015-12-10 13:02:50 +0100260 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000261
Peter Boström5811a392015-12-10 13:02:50 +0100262 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000263 } renderer;
264
skvlad11a9cbf2016-10-07 11:53:05 -0700265 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -0700266
stefanf116bd02015-10-27 08:29:42 -0700267 test::DirectTransport sender_transport(sender_call_.get());
268 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000269 sender_transport.SetReceiver(receiver_call_->Receiver());
270 receiver_transport.SetReceiver(sender_call_->Receiver());
271
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100272 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700273 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -0800274 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000275
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100276 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000277 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000278
kwiberg27f982b2016-03-01 11:52:33 -0800279 std::unique_ptr<test::FrameGenerator> frame_generator(
perkjfa10b552016-10-02 23:45:26 -0700280 test::FrameGenerator::CreateChromaGenerator(kDefaultWidth,
281 kDefaultHeight));
perkja49cbd32016-09-16 07:53:41 -0700282 test::FrameForwarder frame_forwarder;
perkj803d97f2016-11-01 11:45:46 -0700283 video_send_stream_->SetSource(
284 &frame_forwarder, VideoSendStream::DegradationPreference::kBalanced);
perkja49cbd32016-09-16 07:53:41 -0700285 frame_forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000286
Peter Boström5811a392015-12-10 13:02:50 +0100287 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000288 << "Timed out while waiting for the frame to render.";
289
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000290 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000291
292 sender_transport.StopSending();
293 receiver_transport.StopSending();
294
295 DestroyStreams();
296}
297
Perba7dc722016-04-19 15:01:23 +0200298class CodecObserver : public test::EndToEndTest,
nisse7ade7b32016-03-23 04:48:10 -0700299 public rtc::VideoSinkInterface<VideoFrame> {
Perba7dc722016-04-19 15:01:23 +0200300 public:
301 CodecObserver(int no_frames_to_wait_for,
302 VideoRotation rotation_to_test,
303 const std::string& payload_name,
304 webrtc::VideoEncoder* encoder,
305 webrtc::VideoDecoder* decoder)
306 : EndToEndTest(2 * webrtc::EndToEndTest::kDefaultTimeoutMs),
307 no_frames_to_wait_for_(no_frames_to_wait_for),
308 expected_rotation_(rotation_to_test),
309 payload_name_(payload_name),
310 encoder_(encoder),
311 decoder_(decoder),
312 frame_counter_(0) {}
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000313
Perba7dc722016-04-19 15:01:23 +0200314 void PerformTest() override {
315 EXPECT_TRUE(Wait())
316 << "Timed out while waiting for enough frames to be decoded.";
317 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000318
Perba7dc722016-04-19 15:01:23 +0200319 void ModifyVideoConfigs(
320 VideoSendStream::Config* send_config,
321 std::vector<VideoReceiveStream::Config>* receive_configs,
322 VideoEncoderConfig* encoder_config) override {
323 send_config->encoder_settings.encoder = encoder_.get();
324 send_config->encoder_settings.payload_name = payload_name_;
325 send_config->encoder_settings.payload_type = 126;
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000326
Perba7dc722016-04-19 15:01:23 +0200327 (*receive_configs)[0].renderer = this;
328 (*receive_configs)[0].decoders.resize(1);
329 (*receive_configs)[0].decoders[0].payload_type =
330 send_config->encoder_settings.payload_type;
331 (*receive_configs)[0].decoders[0].payload_name =
332 send_config->encoder_settings.payload_name;
333 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
334 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000335
Perba7dc722016-04-19 15:01:23 +0200336 void OnFrame(const VideoFrame& video_frame) override {
337 EXPECT_EQ(expected_rotation_, video_frame.rotation());
338 if (++frame_counter_ == no_frames_to_wait_for_)
339 observation_complete_.Set();
340 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000341
Perba7dc722016-04-19 15:01:23 +0200342 void OnFrameGeneratorCapturerCreated(
343 test::FrameGeneratorCapturer* frame_generator_capturer) override {
344 frame_generator_capturer->SetFakeRotation(expected_rotation_);
345 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000346
Perba7dc722016-04-19 15:01:23 +0200347 private:
348 int no_frames_to_wait_for_;
349 VideoRotation expected_rotation_;
350 std::string payload_name_;
351 std::unique_ptr<webrtc::VideoEncoder> encoder_;
352 std::unique_ptr<webrtc::VideoDecoder> decoder_;
353 int frame_counter_;
354};
355
356TEST_F(EndToEndTest, SendsAndReceivesVP8Rotation90) {
357 CodecObserver test(5, kVideoRotation_90, "VP8",
358 VideoEncoder::Create(VideoEncoder::kVp8),
359 VP8Decoder::Create());
360 RunBaseTest(&test);
361}
362
Peter Boström12996152016-05-14 02:03:18 +0200363#if !defined(RTC_DISABLE_VP9)
Perba7dc722016-04-19 15:01:23 +0200364TEST_F(EndToEndTest, SendsAndReceivesVP9) {
365 CodecObserver test(500, kVideoRotation_0, "VP9",
366 VideoEncoder::Create(VideoEncoder::kVp9),
367 VP9Decoder::Create());
368 RunBaseTest(&test);
369}
370
371TEST_F(EndToEndTest, SendsAndReceivesVP9VideoRotation90) {
372 CodecObserver test(5, kVideoRotation_90, "VP9",
373 VideoEncoder::Create(VideoEncoder::kVp9),
374 VP9Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800375 RunBaseTest(&test);
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000376}
Peter Boström12996152016-05-14 02:03:18 +0200377#endif // !defined(RTC_DISABLE_VP9)
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000378
hbosbab934b2016-01-27 01:36:03 -0800379#if defined(WEBRTC_END_TO_END_H264_TESTS)
380
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000381TEST_F(EndToEndTest, SendsAndReceivesH264) {
Perba7dc722016-04-19 15:01:23 +0200382 CodecObserver test(500, kVideoRotation_0, "H264",
383 VideoEncoder::Create(VideoEncoder::kH264),
384 H264Decoder::Create());
385 RunBaseTest(&test);
386}
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000387
Perba7dc722016-04-19 15:01:23 +0200388TEST_F(EndToEndTest, SendsAndReceivesH264VideoRotation90) {
389 CodecObserver test(5, kVideoRotation_90, "H264",
390 VideoEncoder::Create(VideoEncoder::kH264),
391 H264Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800392 RunBaseTest(&test);
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000393}
394
hbosbab934b2016-01-27 01:36:03 -0800395#endif // defined(WEBRTC_END_TO_END_H264_TESTS)
396
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000397TEST_F(EndToEndTest, ReceiverUsesLocalSsrc) {
398 class SyncRtcpObserver : public test::EndToEndTest {
399 public:
400 SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {}
401
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000402 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000403 RTCPUtility::RTCPParserV2 parser(packet, length, true);
404 EXPECT_TRUE(parser.IsValid());
405 uint32_t ssrc = 0;
406 ssrc |= static_cast<uint32_t>(packet[4]) << 24;
407 ssrc |= static_cast<uint32_t>(packet[5]) << 16;
408 ssrc |= static_cast<uint32_t>(packet[6]) << 8;
409 ssrc |= static_cast<uint32_t>(packet[7]) << 0;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100410 EXPECT_EQ(kReceiverLocalVideoSsrc, ssrc);
Peter Boström5811a392015-12-10 13:02:50 +0100411 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000412
413 return SEND_PACKET;
414 }
415
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000416 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100417 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000418 << "Timed out while waiting for a receiver RTCP packet to be sent.";
419 }
420 } test;
421
stefane74eef12016-01-08 06:47:13 -0800422 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000423}
424
425TEST_F(EndToEndTest, ReceivesAndRetransmitsNack) {
426 static const int kNumberOfNacksToObserve = 2;
427 static const int kLossBurstSize = 2;
428 static const int kPacketsBetweenLossBursts = 9;
429 class NackObserver : public test::EndToEndTest {
430 public:
431 NackObserver()
432 : EndToEndTest(kLongTimeoutMs),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000433 sent_rtp_packets_(0),
434 packets_left_to_drop_(0),
435 nacks_left_(kNumberOfNacksToObserve) {}
436
437 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000438 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700439 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000440 RTPHeader header;
Peter Boström03671cb2015-12-07 15:22:24 +0100441 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000442
443 // Never drop retransmitted packets.
444 if (dropped_packets_.find(header.sequenceNumber) !=
445 dropped_packets_.end()) {
446 retransmitted_packets_.insert(header.sequenceNumber);
Stefan Holmer586b19b2015-09-18 11:14:31 +0200447 if (nacks_left_ <= 0 &&
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000448 retransmitted_packets_.size() == dropped_packets_.size()) {
Peter Boström5811a392015-12-10 13:02:50 +0100449 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000450 }
451 return SEND_PACKET;
452 }
453
454 ++sent_rtp_packets_;
455
456 // Enough NACKs received, stop dropping packets.
Stefan Holmer586b19b2015-09-18 11:14:31 +0200457 if (nacks_left_ <= 0)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000458 return SEND_PACKET;
459
460 // Check if it's time for a new loss burst.
461 if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
462 packets_left_to_drop_ = kLossBurstSize;
463
Stefan Holmer01b48882015-05-05 10:21:24 +0200464 // Never drop padding packets as those won't be retransmitted.
465 if (packets_left_to_drop_ > 0 && header.paddingLength == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000466 --packets_left_to_drop_;
467 dropped_packets_.insert(header.sequenceNumber);
468 return DROP_PACKET;
469 }
470
471 return SEND_PACKET;
472 }
473
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000474 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700475 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000476 RTCPUtility::RTCPParserV2 parser(packet, length, true);
477 EXPECT_TRUE(parser.IsValid());
478
479 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +0200480 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
481 if (packet_type == RTCPUtility::RTCPPacketTypes::kRtpfbNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000482 --nacks_left_;
483 break;
484 }
485 packet_type = parser.Iterate();
486 }
487 return SEND_PACKET;
488 }
489
stefanff483612015-12-21 03:14:00 -0800490 void ModifyVideoConfigs(
491 VideoSendStream::Config* send_config,
492 std::vector<VideoReceiveStream::Config>* receive_configs,
493 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000494 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000495 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000496 }
497
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000498 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100499 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000500 << "Timed out waiting for packets to be NACKed, retransmitted and "
501 "rendered.";
502 }
503
stefanf116bd02015-10-27 08:29:42 -0700504 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000505 std::set<uint16_t> dropped_packets_;
506 std::set<uint16_t> retransmitted_packets_;
507 uint64_t sent_rtp_packets_;
508 int packets_left_to_drop_;
stefanf116bd02015-10-27 08:29:42 -0700509 int nacks_left_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000510 } test;
511
stefane74eef12016-01-08 06:47:13 -0800512 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000513}
514
Erik Språng737336d2016-07-29 12:59:36 +0200515TEST_F(EndToEndTest, ReceivesNackAndRetransmitsAudio) {
516 class NackObserver : public test::EndToEndTest {
517 public:
518 NackObserver()
519 : EndToEndTest(kLongTimeoutMs),
520 local_ssrc_(0),
521 remote_ssrc_(0),
522 receive_transport_(nullptr) {}
523
524 private:
525 size_t GetNumVideoStreams() const override { return 0; }
526 size_t GetNumAudioStreams() const override { return 1; }
527
528 test::PacketTransport* CreateReceiveTransport() override {
529 test::PacketTransport* receive_transport = new test::PacketTransport(
530 nullptr, this, test::PacketTransport::kReceiver,
531 FakeNetworkPipe::Config());
532 receive_transport_ = receive_transport;
533 return receive_transport;
534 }
535
536 Action OnSendRtp(const uint8_t* packet, size_t length) override {
537 RTPHeader header;
538 EXPECT_TRUE(parser_->Parse(packet, length, &header));
539
540 if (!sequence_number_to_retransmit_) {
541 sequence_number_to_retransmit_ =
542 rtc::Optional<uint16_t>(header.sequenceNumber);
543
544 // Don't ask for retransmission straight away, may be deduped in pacer.
545 } else if (header.sequenceNumber == *sequence_number_to_retransmit_) {
546 observation_complete_.Set();
547 } else {
548 // Send a NACK as often as necessary until retransmission is received.
549 rtcp::Nack nack;
danilchap822a16f2016-09-27 09:27:47 -0700550 nack.SetSenderSsrc(local_ssrc_);
551 nack.SetMediaSsrc(remote_ssrc_);
Erik Språng737336d2016-07-29 12:59:36 +0200552 uint16_t nack_list[] = {*sequence_number_to_retransmit_};
danilchap822a16f2016-09-27 09:27:47 -0700553 nack.SetPacketIds(nack_list, 1);
Erik Språng737336d2016-07-29 12:59:36 +0200554 rtc::Buffer buffer = nack.Build();
555
556 EXPECT_TRUE(receive_transport_->SendRtcp(buffer.data(), buffer.size()));
557 }
558
559 return SEND_PACKET;
560 }
561
562 void ModifyAudioConfigs(
563 AudioSendStream::Config* send_config,
564 std::vector<AudioReceiveStream::Config>* receive_configs) override {
565 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
566 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
567 local_ssrc_ = (*receive_configs)[0].rtp.local_ssrc;
568 remote_ssrc_ = (*receive_configs)[0].rtp.remote_ssrc;
569 }
570
571 void PerformTest() override {
572 EXPECT_TRUE(Wait())
573 << "Timed out waiting for packets to be NACKed, retransmitted and "
574 "rendered.";
575 }
576
577 uint32_t local_ssrc_;
578 uint32_t remote_ssrc_;
579 Transport* receive_transport_;
580 rtc::Optional<uint16_t> sequence_number_to_retransmit_;
581 } test;
582
583 RunBaseTest(&test);
584}
585
brandtr535830e2016-10-31 03:45:58 -0700586TEST_F(EndToEndTest, CanReceiveUlpfec) {
587 class UlpfecRenderObserver : public test::EndToEndTest,
588 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000589 public:
brandtr535830e2016-10-31 03:45:58 -0700590 UlpfecRenderObserver()
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000591 : EndToEndTest(kDefaultTimeoutMs), state_(kFirstPacket) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000592
593 private:
stefanf116bd02015-10-27 08:29:42 -0700594 Action OnSendRtp(const uint8_t* packet, size_t length) override {
595 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000596 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000597 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000598
Stefan Holmer01b48882015-05-05 10:21:24 +0200599 int encapsulated_payload_type = -1;
600 if (header.payloadType == kRedPayloadType) {
601 encapsulated_payload_type =
602 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100603 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200604 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
605 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100606 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200607 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000608
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000609 if (protected_sequence_numbers_.count(header.sequenceNumber) != 0) {
610 // Retransmitted packet, should not count.
611 protected_sequence_numbers_.erase(header.sequenceNumber);
612 EXPECT_GT(protected_timestamps_.count(header.timestamp), 0u);
613 protected_timestamps_.erase(header.timestamp);
614 return SEND_PACKET;
615 }
616
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000617 switch (state_) {
618 case kFirstPacket:
brandtr535830e2016-10-31 03:45:58 -0700619 state_ = kDropEveryOtherPacketUntilUlpfec;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000620 break;
brandtr535830e2016-10-31 03:45:58 -0700621 case kDropEveryOtherPacketUntilUlpfec:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000622 if (encapsulated_payload_type == kUlpfecPayloadType) {
623 state_ = kDropNextMediaPacket;
624 return SEND_PACKET;
625 }
626 if (header.sequenceNumber % 2 == 0)
627 return DROP_PACKET;
628 break;
629 case kDropNextMediaPacket:
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100630 if (encapsulated_payload_type == kFakeVideoSendPayloadType) {
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000631 protected_sequence_numbers_.insert(header.sequenceNumber);
632 protected_timestamps_.insert(header.timestamp);
brandtr535830e2016-10-31 03:45:58 -0700633 state_ = kDropEveryOtherPacketUntilUlpfec;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000634 return DROP_PACKET;
635 }
636 break;
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.
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000646 if (protected_timestamps_.count(video_frame.timestamp()) != 0)
Peter Boström5811a392015-12-10 13:02:50 +0100647 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000648 }
649
650 enum {
651 kFirstPacket,
brandtr535830e2016-10-31 03:45:58 -0700652 kDropEveryOtherPacketUntilUlpfec,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000653 kDropNextMediaPacket,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000654 } state_;
655
stefanff483612015-12-21 03:14:00 -0800656 void ModifyVideoConfigs(
657 VideoSendStream::Config* send_config,
658 std::vector<VideoReceiveStream::Config>* receive_configs,
659 VideoEncoderConfig* encoder_config) override {
brandtr535830e2016-10-31 03:45:58 -0700660 // TODO(pbos): Run this test with combined NACK/ULPFEC enabled as well.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000661 // int rtp_history_ms = 1000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000662 // (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000663 // send_config->rtp.nack.rtp_history_ms = rtp_history_ms;
brandtrb5f2c3f2016-10-04 23:28:39 -0700664 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
665 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000666
brandtrb5f2c3f2016-10-04 23:28:39 -0700667 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
668 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000669 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000670 }
671
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000672 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100673 EXPECT_TRUE(Wait())
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000674 << "Timed out waiting for dropped frames frames to be rendered.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000675 }
676
stefanf116bd02015-10-27 08:29:42 -0700677 rtc::CriticalSection crit_;
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000678 std::set<uint32_t> protected_sequence_numbers_ GUARDED_BY(crit_);
679 std::set<uint32_t> protected_timestamps_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000680 } test;
681
stefane74eef12016-01-08 06:47:13 -0800682 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000683}
684
brandtr535830e2016-10-31 03:45:58 -0700685TEST_F(EndToEndTest, ReceivedUlpfecPacketsNotNacked) {
686 class UlpfecNackObserver : public test::EndToEndTest {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000687 public:
brandtr535830e2016-10-31 03:45:58 -0700688 UlpfecNackObserver()
stefanf116bd02015-10-27 08:29:42 -0700689 : EndToEndTest(kDefaultTimeoutMs),
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000690 state_(kFirstPacket),
brandtr535830e2016-10-31 03:45:58 -0700691 ulpfec_sequence_number_(0),
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000692 has_last_sequence_number_(false),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200693 last_sequence_number_(0),
694 encoder_(VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)),
695 decoder_(VP8Decoder::Create()) {}
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000696
697 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000698 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800699 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000700 RTPHeader header;
701 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000702
Stefan Holmer01b48882015-05-05 10:21:24 +0200703 int encapsulated_payload_type = -1;
704 if (header.payloadType == kRedPayloadType) {
705 encapsulated_payload_type =
706 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100707 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200708 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
709 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100710 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200711 }
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000712
713 if (has_last_sequence_number_ &&
714 !IsNewerSequenceNumber(header.sequenceNumber,
715 last_sequence_number_)) {
716 // Drop retransmitted packets.
717 return DROP_PACKET;
718 }
719 last_sequence_number_ = header.sequenceNumber;
720 has_last_sequence_number_ = true;
721
brandtr535830e2016-10-31 03:45:58 -0700722 bool ulpfec_packet = encapsulated_payload_type == kUlpfecPayloadType;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000723 switch (state_) {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000724 case kFirstPacket:
brandtr535830e2016-10-31 03:45:58 -0700725 state_ = kDropEveryOtherPacketUntilUlpfec;
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000726 break;
brandtr535830e2016-10-31 03:45:58 -0700727 case kDropEveryOtherPacketUntilUlpfec:
728 if (ulpfec_packet) {
729 state_ = kDropAllMediaPacketsUntilUlpfec;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000730 } else if (header.sequenceNumber % 2 == 0) {
731 return DROP_PACKET;
732 }
733 break;
brandtr535830e2016-10-31 03:45:58 -0700734 case kDropAllMediaPacketsUntilUlpfec:
735 if (!ulpfec_packet)
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000736 return DROP_PACKET;
brandtr535830e2016-10-31 03:45:58 -0700737 ulpfec_sequence_number_ = header.sequenceNumber;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200738 state_ = kDropOneMediaPacket;
739 break;
740 case kDropOneMediaPacket:
brandtr535830e2016-10-31 03:45:58 -0700741 if (ulpfec_packet)
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200742 return DROP_PACKET;
743 state_ = kPassOneMediaPacket;
744 return DROP_PACKET;
745 break;
746 case kPassOneMediaPacket:
brandtr535830e2016-10-31 03:45:58 -0700747 if (ulpfec_packet)
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200748 return DROP_PACKET;
749 // Pass one media packet after dropped packet after last FEC,
750 // otherwise receiver might never see a seq_no after
brandtr535830e2016-10-31 03:45:58 -0700751 // |ulpfec_sequence_number_|
752 state_ = kVerifyUlpfecPacketNotInNackList;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000753 break;
brandtr535830e2016-10-31 03:45:58 -0700754 case kVerifyUlpfecPacketNotInNackList:
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000755 // Continue to drop packets. Make sure no frame can be decoded.
brandtr535830e2016-10-31 03:45:58 -0700756 if (ulpfec_packet || header.sequenceNumber % 2 == 0)
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000757 return DROP_PACKET;
758 break;
759 }
760 return SEND_PACKET;
761 }
762
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000763 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800764 rtc::CritScope lock_(&crit_);
brandtr535830e2016-10-31 03:45:58 -0700765 if (state_ == kVerifyUlpfecPacketNotInNackList) {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000766 test::RtcpPacketParser rtcp_parser;
767 rtcp_parser.Parse(packet, length);
Danil Chapovalovba6f7be2016-09-02 18:29:10 +0200768 const std::vector<uint16_t>& nacks = rtcp_parser.nack()->packet_ids();
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200769 EXPECT_TRUE(std::find(nacks.begin(), nacks.end(),
brandtr535830e2016-10-31 03:45:58 -0700770 ulpfec_sequence_number_) == nacks.end())
771 << "Got nack for ULPFEC packet";
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000772 if (!nacks.empty() &&
brandtr535830e2016-10-31 03:45:58 -0700773 IsNewerSequenceNumber(nacks.back(), ulpfec_sequence_number_)) {
Peter Boström5811a392015-12-10 13:02:50 +0100774 observation_complete_.Set();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000775 }
776 }
777 return SEND_PACKET;
778 }
779
stefane74eef12016-01-08 06:47:13 -0800780 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
781 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
782 // Configure some network delay.
783 const int kNetworkDelayMs = 50;
784 FakeNetworkPipe::Config config;
785 config.queue_delay_ms = kNetworkDelayMs;
786 return new test::PacketTransport(sender_call, this,
787 test::PacketTransport::kSender, config);
788 }
789
Stefan Holmere5904162015-03-26 11:11:06 +0100790 // TODO(holmer): Investigate why we don't send FEC packets when the bitrate
791 // is 10 kbps.
792 Call::Config GetSenderCallConfig() override {
skvlad11a9cbf2016-10-07 11:53:05 -0700793 Call::Config config(&event_log_);
Stefan Holmere5904162015-03-26 11:11:06 +0100794 const int kMinBitrateBps = 30000;
795 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
796 return config;
797 }
798
stefanff483612015-12-21 03:14:00 -0800799 void ModifyVideoConfigs(
800 VideoSendStream::Config* send_config,
801 std::vector<VideoReceiveStream::Config>* receive_configs,
802 VideoEncoderConfig* encoder_config) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000803 // Configure hybrid NACK/FEC.
804 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
brandtrb5f2c3f2016-10-04 23:28:39 -0700805 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
806 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200807 // Set codec to VP8, otherwise NACK/FEC hybrid will be disabled.
808 send_config->encoder_settings.encoder = encoder_.get();
809 send_config->encoder_settings.payload_name = "VP8";
810 send_config->encoder_settings.payload_type = kFakeVideoSendPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200811
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000812 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
brandtrb5f2c3f2016-10-04 23:28:39 -0700813 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
814 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200815
816 (*receive_configs)[0].decoders.resize(1);
817 (*receive_configs)[0].decoders[0].payload_type =
818 send_config->encoder_settings.payload_type;
819 (*receive_configs)[0].decoders[0].payload_name =
820 send_config->encoder_settings.payload_name;
821 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000822 }
823
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000824 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100825 EXPECT_TRUE(Wait())
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000826 << "Timed out while waiting for FEC packets to be received.";
827 }
828
829 enum {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000830 kFirstPacket,
brandtr535830e2016-10-31 03:45:58 -0700831 kDropEveryOtherPacketUntilUlpfec,
832 kDropAllMediaPacketsUntilUlpfec,
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200833 kDropOneMediaPacket,
834 kPassOneMediaPacket,
brandtr535830e2016-10-31 03:45:58 -0700835 kVerifyUlpfecPacketNotInNackList,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000836 } state_;
837
stefan608213e2015-11-01 14:56:10 -0800838 rtc::CriticalSection crit_;
brandtr535830e2016-10-31 03:45:58 -0700839 uint16_t ulpfec_sequence_number_ GUARDED_BY(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000840 bool has_last_sequence_number_;
841 uint16_t last_sequence_number_;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200842 std::unique_ptr<webrtc::VideoEncoder> encoder_;
843 std::unique_ptr<webrtc::VideoDecoder> decoder_;
stefanf116bd02015-10-27 08:29:42 -0700844 } test;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000845
stefane74eef12016-01-08 06:47:13 -0800846 RunBaseTest(&test);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000847}
848
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000849// This test drops second RTP packet with a marker bit set, makes sure it's
850// retransmitted and renders. Retransmission SSRCs are also checked.
Peter Boström39593972016-02-15 11:27:15 +0100851void EndToEndTest::DecodesRetransmittedFrame(bool enable_rtx, bool enable_red) {
Peter Boström67680c12016-02-17 11:10:04 +0100852 static const int kDroppedFrameNumber = 10;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000853 class RetransmissionObserver : public test::EndToEndTest,
854 public I420FrameCallback {
855 public:
Peter Boström39593972016-02-15 11:27:15 +0100856 RetransmissionObserver(bool enable_rtx, bool enable_red)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000857 : EndToEndTest(kDefaultTimeoutMs),
Peter Boström39593972016-02-15 11:27:15 +0100858 payload_type_(GetPayloadType(false, enable_red)),
859 retransmission_ssrc_(enable_rtx ? kSendRtxSsrcs[0]
860 : kVideoSendSsrcs[0]),
861 retransmission_payload_type_(GetPayloadType(enable_rtx, enable_red)),
862 encoder_(VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000863 marker_bits_observed_(0),
danilchap192717e2016-07-25 08:20:51 -0700864 retransmitted_timestamp_(0) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000865
866 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000867 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700868 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000869 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000870 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000871
Peter Boström67680c12016-02-17 11:10:04 +0100872 // Ignore padding-only packets over RTX.
873 if (header.payloadType != payload_type_) {
874 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
875 if (length == header.headerLength + header.paddingLength)
876 return SEND_PACKET;
Stefan Holmer586b19b2015-09-18 11:14:31 +0200877 }
Peter Boström67680c12016-02-17 11:10:04 +0100878
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000879 if (header.timestamp == retransmitted_timestamp_) {
880 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
881 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000882 return SEND_PACKET;
883 }
884
Stefan Holmer586b19b2015-09-18 11:14:31 +0200885 // Found the final packet of the frame to inflict loss to, drop this and
886 // expect a retransmission.
danilchapfdd381c2016-07-25 04:03:20 -0700887 if (header.payloadType == payload_type_ && header.markerBit &&
888 ++marker_bits_observed_ == kDroppedFrameNumber) {
Danil Chapovalov18c65a42016-06-29 15:29:34 +0200889 // This should be the only dropped packet.
890 EXPECT_EQ(0u, retransmitted_timestamp_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000891 retransmitted_timestamp_ = header.timestamp;
danilchap192717e2016-07-25 08:20:51 -0700892 if (std::find(rendered_timestamps_.begin(), rendered_timestamps_.end(),
893 retransmitted_timestamp_) != rendered_timestamps_.end()) {
894 // Frame was rendered before last packet was scheduled for sending.
895 // This is extremly rare but possible scenario because prober able to
896 // resend packet before it was send.
897 // TODO(danilchap): Remove this corner case when prober would not be
898 // able to sneak in between packet saved to history for resending and
899 // pacer notified about existance of that packet for sending.
900 // See https://bugs.chromium.org/p/webrtc/issues/detail?id=5540 for
901 // details.
902 observation_complete_.Set();
903 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000904 return DROP_PACKET;
905 }
906
907 return SEND_PACKET;
908 }
909
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700910 void FrameCallback(VideoFrame* frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200911 rtc::CritScope lock(&crit_);
danilchap192717e2016-07-25 08:20:51 -0700912 if (frame->timestamp() == retransmitted_timestamp_)
Peter Boström5811a392015-12-10 13:02:50 +0100913 observation_complete_.Set();
danilchap192717e2016-07-25 08:20:51 -0700914 rendered_timestamps_.push_back(frame->timestamp());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000915 }
916
stefanff483612015-12-21 03:14:00 -0800917 void ModifyVideoConfigs(
918 VideoSendStream::Config* send_config,
919 std::vector<VideoReceiveStream::Config>* receive_configs,
920 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000921 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000922 (*receive_configs)[0].pre_render_callback = this;
923 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
Shao Changbine62202f2015-04-21 20:24:50 +0800924
925 if (payload_type_ == kRedPayloadType) {
brandtrb5f2c3f2016-10-04 23:28:39 -0700926 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
927 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +0100928 if (retransmission_ssrc_ == kSendRtxSsrcs[0])
brandtrb5f2c3f2016-10-04 23:28:39 -0700929 send_config->rtp.ulpfec.red_rtx_payload_type = kRtxRedPayloadType;
930 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type =
931 send_config->rtp.ulpfec.ulpfec_payload_type;
932 (*receive_configs)[0].rtp.ulpfec.red_payload_type =
933 send_config->rtp.ulpfec.red_payload_type;
934 (*receive_configs)[0].rtp.ulpfec.red_rtx_payload_type =
935 send_config->rtp.ulpfec.red_rtx_payload_type;
Shao Changbine62202f2015-04-21 20:24:50 +0800936 }
937
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000938 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
939 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000940 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +0100941 (*receive_configs)[0].rtp.rtx[payload_type_].ssrc = kSendRtxSsrcs[0];
942 (*receive_configs)[0].rtp.rtx[payload_type_].payload_type =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000943 kSendRtxPayloadType;
944 }
Peter Boström39593972016-02-15 11:27:15 +0100945 // Configure encoding and decoding with VP8, since generic packetization
946 // doesn't support FEC with NACK.
947 RTC_DCHECK_EQ(1u, (*receive_configs)[0].decoders.size());
948 send_config->encoder_settings.encoder = encoder_.get();
949 send_config->encoder_settings.payload_name = "VP8";
950 (*receive_configs)[0].decoders[0].payload_name = "VP8";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000951 }
952
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000953 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100954 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000955 << "Timed out while waiting for retransmission to render.";
956 }
957
Shao Changbine62202f2015-04-21 20:24:50 +0800958 int GetPayloadType(bool use_rtx, bool use_red) {
Stefan Holmer10880012016-02-03 13:29:59 +0100959 if (use_red) {
960 if (use_rtx)
961 return kRtxRedPayloadType;
962 return kRedPayloadType;
963 }
964 if (use_rtx)
965 return kSendRtxPayloadType;
966 return kFakeVideoSendPayloadType;
Shao Changbine62202f2015-04-21 20:24:50 +0800967 }
968
stefanf116bd02015-10-27 08:29:42 -0700969 rtc::CriticalSection crit_;
Shao Changbine62202f2015-04-21 20:24:50 +0800970 const int payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000971 const uint32_t retransmission_ssrc_;
972 const int retransmission_payload_type_;
kwiberg27f982b2016-03-01 11:52:33 -0800973 std::unique_ptr<VideoEncoder> encoder_;
Peter Boström39593972016-02-15 11:27:15 +0100974 const std::string payload_name_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000975 int marker_bits_observed_;
stefanf116bd02015-10-27 08:29:42 -0700976 uint32_t retransmitted_timestamp_ GUARDED_BY(&crit_);
danilchap192717e2016-07-25 08:20:51 -0700977 std::vector<uint32_t> rendered_timestamps_ GUARDED_BY(&crit_);
Peter Boström39593972016-02-15 11:27:15 +0100978 } test(enable_rtx, enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000979
stefane74eef12016-01-08 06:47:13 -0800980 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000981}
982
983TEST_F(EndToEndTest, DecodesRetransmittedFrame) {
Shao Changbine62202f2015-04-21 20:24:50 +0800984 DecodesRetransmittedFrame(false, false);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000985}
986
987TEST_F(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +0800988 DecodesRetransmittedFrame(true, false);
989}
990
991TEST_F(EndToEndTest, DecodesRetransmittedFrameByRed) {
992 DecodesRetransmittedFrame(false, true);
993}
994
995TEST_F(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
996 DecodesRetransmittedFrame(true, true);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000997}
998
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000999void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
1000 static const int kPacketsToDrop = 1;
1001
nisse7ade7b32016-03-23 04:48:10 -07001002 class PliObserver : public test::EndToEndTest,
1003 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001004 public:
1005 explicit PliObserver(int rtp_history_ms)
1006 : EndToEndTest(kLongTimeoutMs),
1007 rtp_history_ms_(rtp_history_ms),
1008 nack_enabled_(rtp_history_ms > 0),
1009 highest_dropped_timestamp_(0),
1010 frames_to_drop_(0),
1011 received_pli_(false) {}
1012
1013 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001014 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001015 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001016 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001017 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001018
1019 // Drop all retransmitted packets to force a PLI.
1020 if (header.timestamp <= highest_dropped_timestamp_)
1021 return DROP_PACKET;
1022
1023 if (frames_to_drop_ > 0) {
1024 highest_dropped_timestamp_ = header.timestamp;
1025 --frames_to_drop_;
1026 return DROP_PACKET;
1027 }
1028
1029 return SEND_PACKET;
1030 }
1031
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001032 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001033 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001034 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1035 EXPECT_TRUE(parser.IsValid());
1036
1037 for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02001038 packet_type != RTCPUtility::RTCPPacketTypes::kInvalid;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001039 packet_type = parser.Iterate()) {
1040 if (!nack_enabled_)
Erik Språng242e22b2015-05-11 10:17:43 +02001041 EXPECT_NE(packet_type, RTCPUtility::RTCPPacketTypes::kRtpfbNack);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001042
Erik Språng242e22b2015-05-11 10:17:43 +02001043 if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbPli) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001044 received_pli_ = true;
1045 break;
1046 }
1047 }
1048 return SEND_PACKET;
1049 }
1050
nisseeb83a1a2016-03-21 01:27:56 -07001051 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001052 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001053 if (received_pli_ &&
1054 video_frame.timestamp() > highest_dropped_timestamp_) {
Peter Boström5811a392015-12-10 13:02:50 +01001055 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001056 }
1057 if (!received_pli_)
1058 frames_to_drop_ = kPacketsToDrop;
1059 }
1060
stefanff483612015-12-21 03:14:00 -08001061 void ModifyVideoConfigs(
1062 VideoSendStream::Config* send_config,
1063 std::vector<VideoReceiveStream::Config>* receive_configs,
1064 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001065 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001066 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
1067 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001068 }
1069
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001070 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001071 EXPECT_TRUE(Wait()) << "Timed out waiting for PLI to be "
1072 "received and a frame to be "
1073 "rendered afterwards.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001074 }
1075
stefanf116bd02015-10-27 08:29:42 -07001076 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001077 int rtp_history_ms_;
1078 bool nack_enabled_;
stefanf116bd02015-10-27 08:29:42 -07001079 uint32_t highest_dropped_timestamp_ GUARDED_BY(&crit_);
1080 int frames_to_drop_ GUARDED_BY(&crit_);
1081 bool received_pli_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001082 } test(rtp_history_ms);
1083
stefane74eef12016-01-08 06:47:13 -08001084 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001085}
1086
1087TEST_F(EndToEndTest, ReceivesPliAndRecoversWithNack) {
1088 ReceivesPliAndRecovers(1000);
1089}
1090
jbauchdb81ffd2015-11-23 03:59:02 -08001091TEST_F(EndToEndTest, ReceivesPliAndRecoversWithoutNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001092 ReceivesPliAndRecovers(0);
1093}
1094
1095TEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
1096 class PacketInputObserver : public PacketReceiver {
1097 public:
1098 explicit PacketInputObserver(PacketReceiver* receiver)
Peter Boström5811a392015-12-10 13:02:50 +01001099 : receiver_(receiver), delivered_packet_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001100
Peter Boström5811a392015-12-10 13:02:50 +01001101 bool Wait() { return delivered_packet_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001102
1103 private:
stefan68786d22015-09-08 05:36:15 -07001104 DeliveryStatus DeliverPacket(MediaType media_type,
1105 const uint8_t* packet,
1106 size_t length,
1107 const PacketTime& packet_time) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001108 if (RtpHeaderParser::IsRtcp(packet, length)) {
stefan68786d22015-09-08 05:36:15 -07001109 return receiver_->DeliverPacket(media_type, packet, length,
1110 packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001111 } else {
1112 DeliveryStatus delivery_status =
stefan68786d22015-09-08 05:36:15 -07001113 receiver_->DeliverPacket(media_type, packet, length, packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001114 EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
Peter Boström5811a392015-12-10 13:02:50 +01001115 delivered_packet_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001116 return delivery_status;
1117 }
1118 }
1119
1120 PacketReceiver* receiver_;
Peter Boström5811a392015-12-10 13:02:50 +01001121 rtc::Event delivered_packet_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001122 };
1123
skvlad11a9cbf2016-10-07 11:53:05 -07001124 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -07001125
stefanf116bd02015-10-27 08:29:42 -07001126 test::DirectTransport send_transport(sender_call_.get());
1127 test::DirectTransport receive_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001128 PacketInputObserver input_observer(receiver_call_->Receiver());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001129 send_transport.SetReceiver(&input_observer);
1130 receive_transport.SetReceiver(sender_call_->Receiver());
1131
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001132 CreateSendConfig(1, 0, &send_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001133 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001134
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001135 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07001136 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
1137 kDefaultHeight);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001138 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001139
stefanff483612015-12-21 03:14:00 -08001140 receiver_call_->DestroyVideoReceiveStream(video_receive_streams_[0]);
1141 video_receive_streams_.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001142
1143 // Wait() waits for a received packet.
Peter Boström5811a392015-12-10 13:02:50 +01001144 EXPECT_TRUE(input_observer.Wait());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001145
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001146 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001147
1148 DestroyStreams();
1149
1150 send_transport.StopSending();
1151 receive_transport.StopSending();
1152}
1153
pbosda903ea2015-10-02 02:36:56 -07001154void EndToEndTest::RespectsRtcpMode(RtcpMode rtcp_mode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001155 static const int kNumCompoundRtcpPacketsToObserve = 10;
1156 class RtcpModeObserver : public test::EndToEndTest {
1157 public:
pbosda903ea2015-10-02 02:36:56 -07001158 explicit RtcpModeObserver(RtcpMode rtcp_mode)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001159 : EndToEndTest(kDefaultTimeoutMs),
1160 rtcp_mode_(rtcp_mode),
1161 sent_rtp_(0),
1162 sent_rtcp_(0) {}
1163
1164 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001165 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001166 if (++sent_rtp_ % 3 == 0)
1167 return DROP_PACKET;
1168
1169 return SEND_PACKET;
1170 }
1171
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001172 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001173 ++sent_rtcp_;
1174 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1175 EXPECT_TRUE(parser.IsValid());
1176
1177 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1178 bool has_report_block = false;
Erik Språng242e22b2015-05-11 10:17:43 +02001179 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1180 EXPECT_NE(RTCPUtility::RTCPPacketTypes::kSr, packet_type);
1181 if (packet_type == RTCPUtility::RTCPPacketTypes::kRr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001182 has_report_block = true;
1183 break;
1184 }
1185 packet_type = parser.Iterate();
1186 }
1187
1188 switch (rtcp_mode_) {
pbosda903ea2015-10-02 02:36:56 -07001189 case RtcpMode::kCompound:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001190 if (!has_report_block) {
1191 ADD_FAILURE() << "Received RTCP packet without receiver report for "
pbosda903ea2015-10-02 02:36:56 -07001192 "RtcpMode::kCompound.";
Peter Boström5811a392015-12-10 13:02:50 +01001193 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001194 }
1195
1196 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
Peter Boström5811a392015-12-10 13:02:50 +01001197 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001198
1199 break;
pbosda903ea2015-10-02 02:36:56 -07001200 case RtcpMode::kReducedSize:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001201 if (!has_report_block)
Peter Boström5811a392015-12-10 13:02:50 +01001202 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001203 break;
pbosda903ea2015-10-02 02:36:56 -07001204 case RtcpMode::kOff:
1205 RTC_NOTREACHED();
1206 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001207 }
1208
1209 return SEND_PACKET;
1210 }
1211
stefanff483612015-12-21 03:14:00 -08001212 void ModifyVideoConfigs(
1213 VideoSendStream::Config* send_config,
1214 std::vector<VideoReceiveStream::Config>* receive_configs,
1215 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001216 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001217 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1218 (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001219 }
1220
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001221 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001222 EXPECT_TRUE(Wait())
pbosda903ea2015-10-02 02:36:56 -07001223 << (rtcp_mode_ == RtcpMode::kCompound
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001224 ? "Timed out before observing enough compound packets."
1225 : "Timed out before receiving a non-compound RTCP packet.");
1226 }
1227
pbosda903ea2015-10-02 02:36:56 -07001228 RtcpMode rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001229 int sent_rtp_;
1230 int sent_rtcp_;
1231 } test(rtcp_mode);
1232
stefane74eef12016-01-08 06:47:13 -08001233 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001234}
1235
1236TEST_F(EndToEndTest, UsesRtcpCompoundMode) {
pbosda903ea2015-10-02 02:36:56 -07001237 RespectsRtcpMode(RtcpMode::kCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001238}
1239
1240TEST_F(EndToEndTest, UsesRtcpReducedSizeMode) {
pbosda903ea2015-10-02 02:36:56 -07001241 RespectsRtcpMode(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001242}
1243
1244// Test sets up a Call multiple senders with different resolutions and SSRCs.
1245// Another is set up to receive all three of these with different renderers.
sprang867fb522015-08-03 04:38:41 -07001246class MultiStreamTest {
1247 public:
1248 static const size_t kNumStreams = 3;
1249 struct CodecSettings {
1250 uint32_t ssrc;
1251 int width;
1252 int height;
1253 } codec_settings[kNumStreams];
1254
1255 MultiStreamTest() {
1256 // TODO(sprang): Cleanup when msvc supports explicit initializers for array.
1257 codec_settings[0] = {1, 640, 480};
1258 codec_settings[1] = {2, 320, 240};
1259 codec_settings[2] = {3, 240, 160};
1260 }
1261
1262 virtual ~MultiStreamTest() {}
1263
1264 void RunTest() {
skvlad11a9cbf2016-10-07 11:53:05 -07001265 webrtc::RtcEventLogNullImpl event_log;
1266 Call::Config config(&event_log);
1267 std::unique_ptr<Call> sender_call(Call::Create(config));
1268 std::unique_ptr<Call> receiver_call(Call::Create(config));
kwiberg27f982b2016-03-01 11:52:33 -08001269 std::unique_ptr<test::DirectTransport> sender_transport(
stefanf116bd02015-10-27 08:29:42 -07001270 CreateSendTransport(sender_call.get()));
kwiberg27f982b2016-03-01 11:52:33 -08001271 std::unique_ptr<test::DirectTransport> receiver_transport(
stefanf116bd02015-10-27 08:29:42 -07001272 CreateReceiveTransport(receiver_call.get()));
sprang867fb522015-08-03 04:38:41 -07001273 sender_transport->SetReceiver(receiver_call->Receiver());
1274 receiver_transport->SetReceiver(sender_call->Receiver());
1275
kwiberg27f982b2016-03-01 11:52:33 -08001276 std::unique_ptr<VideoEncoder> encoders[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001277 for (size_t i = 0; i < kNumStreams; ++i)
1278 encoders[i].reset(VideoEncoder::Create(VideoEncoder::kVp8));
1279
1280 VideoSendStream* send_streams[kNumStreams];
1281 VideoReceiveStream* receive_streams[kNumStreams];
1282
1283 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
kwiberg4a206a92016-03-31 10:24:26 -07001284 std::vector<std::unique_ptr<VideoDecoder>> allocated_decoders;
sprang867fb522015-08-03 04:38:41 -07001285 for (size_t i = 0; i < kNumStreams; ++i) {
1286 uint32_t ssrc = codec_settings[i].ssrc;
1287 int width = codec_settings[i].width;
1288 int height = codec_settings[i].height;
1289
solenberg4fbae2b2015-08-28 04:07:10 -07001290 VideoSendStream::Config send_config(sender_transport.get());
sprang867fb522015-08-03 04:38:41 -07001291 send_config.rtp.ssrcs.push_back(ssrc);
1292 send_config.encoder_settings.encoder = encoders[i].get();
1293 send_config.encoder_settings.payload_name = "VP8";
1294 send_config.encoder_settings.payload_type = 124;
1295 VideoEncoderConfig encoder_config;
perkjfa10b552016-10-02 23:45:26 -07001296 test::FillEncoderConfiguration(1, &encoder_config);
1297 encoder_config.max_bitrate_bps = 100000;
sprang867fb522015-08-03 04:38:41 -07001298
1299 UpdateSendConfig(i, &send_config, &encoder_config, &frame_generators[i]);
1300
perkj26091b12016-09-01 01:17:40 -07001301 send_streams[i] = sender_call->CreateVideoSendStream(
1302 send_config.Copy(), encoder_config.Copy());
sprang867fb522015-08-03 04:38:41 -07001303 send_streams[i]->Start();
1304
solenberg4fbae2b2015-08-28 04:07:10 -07001305 VideoReceiveStream::Config receive_config(receiver_transport.get());
sprang867fb522015-08-03 04:38:41 -07001306 receive_config.rtp.remote_ssrc = ssrc;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001307 receive_config.rtp.local_ssrc = test::CallTest::kReceiverLocalVideoSsrc;
sprang867fb522015-08-03 04:38:41 -07001308 VideoReceiveStream::Decoder decoder =
1309 test::CreateMatchingDecoder(send_config.encoder_settings);
kwiberg4a206a92016-03-31 10:24:26 -07001310 allocated_decoders.push_back(
1311 std::unique_ptr<VideoDecoder>(decoder.decoder));
sprang867fb522015-08-03 04:38:41 -07001312 receive_config.decoders.push_back(decoder);
1313
1314 UpdateReceiveConfig(i, &receive_config);
1315
1316 receive_streams[i] =
Tommi733b5472016-06-10 17:58:01 +02001317 receiver_call->CreateVideoReceiveStream(std::move(receive_config));
sprang867fb522015-08-03 04:38:41 -07001318 receive_streams[i]->Start();
1319
1320 frame_generators[i] = test::FrameGeneratorCapturer::Create(
perkja49cbd32016-09-16 07:53:41 -07001321 width, height, 30, Clock::GetRealTimeClock());
perkj803d97f2016-11-01 11:45:46 -07001322 send_streams[i]->SetSource(
1323 frame_generators[i],
1324 VideoSendStream::DegradationPreference::kBalanced);
sprang867fb522015-08-03 04:38:41 -07001325 frame_generators[i]->Start();
1326 }
1327
1328 Wait();
1329
1330 for (size_t i = 0; i < kNumStreams; ++i) {
1331 frame_generators[i]->Stop();
1332 sender_call->DestroyVideoSendStream(send_streams[i]);
1333 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1334 delete frame_generators[i];
1335 }
1336
1337 sender_transport->StopSending();
1338 receiver_transport->StopSending();
1339 }
1340
1341 protected:
1342 virtual void Wait() = 0;
1343 // Note: frame_generator is a point-to-pointer, since the actual instance
1344 // hasn't been created at the time of this call. Only when packets/frames
1345 // start flowing should this be dereferenced.
1346 virtual void UpdateSendConfig(
1347 size_t stream_index,
1348 VideoSendStream::Config* send_config,
1349 VideoEncoderConfig* encoder_config,
1350 test::FrameGeneratorCapturer** frame_generator) {}
1351 virtual void UpdateReceiveConfig(size_t stream_index,
1352 VideoReceiveStream::Config* receive_config) {
1353 }
stefanf116bd02015-10-27 08:29:42 -07001354 virtual test::DirectTransport* CreateSendTransport(Call* sender_call) {
1355 return new test::DirectTransport(sender_call);
sprang867fb522015-08-03 04:38:41 -07001356 }
stefanf116bd02015-10-27 08:29:42 -07001357 virtual test::DirectTransport* CreateReceiveTransport(Call* receiver_call) {
1358 return new test::DirectTransport(receiver_call);
sprang867fb522015-08-03 04:38:41 -07001359 }
1360};
1361
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001362// Each renderer verifies that it receives the expected resolution, and as soon
1363// as every renderer has received a frame, the test finishes.
andresp@webrtc.org02686112014-09-19 08:24:19 +00001364TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) {
nisse7ade7b32016-03-23 04:48:10 -07001365 class VideoOutputObserver : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001366 public:
sprang867fb522015-08-03 04:38:41 -07001367 VideoOutputObserver(const MultiStreamTest::CodecSettings& settings,
1368 uint32_t ssrc,
1369 test::FrameGeneratorCapturer** frame_generator)
1370 : settings_(settings),
1371 ssrc_(ssrc),
1372 frame_generator_(frame_generator),
Peter Boström5811a392015-12-10 13:02:50 +01001373 done_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001374
nisseeb83a1a2016-03-21 01:27:56 -07001375 void OnFrame(const VideoFrame& video_frame) override {
sprang867fb522015-08-03 04:38:41 -07001376 EXPECT_EQ(settings_.width, video_frame.width());
1377 EXPECT_EQ(settings_.height, video_frame.height());
1378 (*frame_generator_)->Stop();
Peter Boström5811a392015-12-10 13:02:50 +01001379 done_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001380 }
1381
sprang867fb522015-08-03 04:38:41 -07001382 uint32_t Ssrc() { return ssrc_; }
1383
Peter Boström5811a392015-12-10 13:02:50 +01001384 bool Wait() { return done_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001385
1386 private:
sprang867fb522015-08-03 04:38:41 -07001387 const MultiStreamTest::CodecSettings& settings_;
1388 const uint32_t ssrc_;
1389 test::FrameGeneratorCapturer** const frame_generator_;
Peter Boström5811a392015-12-10 13:02:50 +01001390 rtc::Event done_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001391 };
1392
sprang867fb522015-08-03 04:38:41 -07001393 class Tester : public MultiStreamTest {
1394 public:
1395 Tester() {}
1396 virtual ~Tester() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001397
sprang867fb522015-08-03 04:38:41 -07001398 protected:
1399 void Wait() override {
1400 for (const auto& observer : observers_) {
Peter Boström5811a392015-12-10 13:02:50 +01001401 EXPECT_TRUE(observer->Wait()) << "Time out waiting for from on ssrc "
1402 << observer->Ssrc();
sprang867fb522015-08-03 04:38:41 -07001403 }
1404 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001405
sprang867fb522015-08-03 04:38:41 -07001406 void UpdateSendConfig(
1407 size_t stream_index,
1408 VideoSendStream::Config* send_config,
1409 VideoEncoderConfig* encoder_config,
1410 test::FrameGeneratorCapturer** frame_generator) override {
1411 observers_[stream_index].reset(new VideoOutputObserver(
1412 codec_settings[stream_index], send_config->rtp.ssrcs.front(),
1413 frame_generator));
1414 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001415
sprang867fb522015-08-03 04:38:41 -07001416 void UpdateReceiveConfig(
1417 size_t stream_index,
1418 VideoReceiveStream::Config* receive_config) override {
1419 receive_config->renderer = observers_[stream_index].get();
1420 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001421
sprang867fb522015-08-03 04:38:41 -07001422 private:
kwiberg27f982b2016-03-01 11:52:33 -08001423 std::unique_ptr<VideoOutputObserver> observers_[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001424 } tester;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001425
sprang867fb522015-08-03 04:38:41 -07001426 tester.RunTest();
1427}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001428
sprang867fb522015-08-03 04:38:41 -07001429TEST_F(EndToEndTest, AssignsTransportSequenceNumbers) {
sprang867fb522015-08-03 04:38:41 -07001430 static const int kExtensionId = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001431
sprang867fb522015-08-03 04:38:41 -07001432 class RtpExtensionHeaderObserver : public test::DirectTransport {
1433 public:
stefanf116bd02015-10-27 08:29:42 -07001434 RtpExtensionHeaderObserver(Call* sender_call,
1435 const uint32_t& first_media_ssrc,
sprang861c55e2015-10-16 10:01:21 -07001436 const std::map<uint32_t, uint32_t>& ssrc_map)
stefanf116bd02015-10-27 08:29:42 -07001437 : DirectTransport(sender_call),
Peter Boström5811a392015-12-10 13:02:50 +01001438 done_(false, false),
sprang867fb522015-08-03 04:38:41 -07001439 parser_(RtpHeaderParser::Create()),
sprang861c55e2015-10-16 10:01:21 -07001440 first_media_ssrc_(first_media_ssrc),
1441 rtx_to_media_ssrcs_(ssrc_map),
sprang867fb522015-08-03 04:38:41 -07001442 padding_observed_(false),
sprang861c55e2015-10-16 10:01:21 -07001443 rtx_padding_observed_(false),
1444 retransmit_observed_(false),
1445 started_(false) {
sprang867fb522015-08-03 04:38:41 -07001446 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
1447 kExtensionId);
1448 }
1449 virtual ~RtpExtensionHeaderObserver() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001450
stefan1d8a5062015-10-02 03:39:33 -07001451 bool SendRtp(const uint8_t* data,
1452 size_t length,
1453 const PacketOptions& options) override {
sprang861c55e2015-10-16 10:01:21 -07001454 {
1455 rtc::CritScope cs(&lock_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001456
Erik Språng8d629712015-08-04 16:24:03 +02001457 if (IsDone())
sprang861c55e2015-10-16 10:01:21 -07001458 return false;
1459
1460 if (started_) {
1461 RTPHeader header;
1462 EXPECT_TRUE(parser_->Parse(data, length, &header));
1463 bool drop_packet = false;
1464
1465 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
1466 EXPECT_EQ(options.packet_id,
1467 header.extension.transportSequenceNumber);
1468 if (!streams_observed_.empty()) {
1469 // Unwrap packet id and verify uniqueness.
1470 int64_t packet_id = unwrapper_.Unwrap(options.packet_id);
1471 EXPECT_TRUE(received_packed_ids_.insert(packet_id).second);
1472 }
1473
1474 // Drop (up to) every 17th packet, so we get retransmits.
1475 // Only drop media, and not on the first stream (otherwise it will be
1476 // hard to distinguish from padding, which is always sent on the first
1477 // stream).
1478 if (header.payloadType != kSendRtxPayloadType &&
1479 header.ssrc != first_media_ssrc_ &&
1480 header.extension.transportSequenceNumber % 17 == 0) {
1481 dropped_seq_[header.ssrc].insert(header.sequenceNumber);
1482 drop_packet = true;
1483 }
1484
1485 size_t payload_length =
1486 length - (header.headerLength + header.paddingLength);
1487 if (payload_length == 0) {
1488 padding_observed_ = true;
1489 } else if (header.payloadType == kSendRtxPayloadType) {
1490 uint16_t original_sequence_number =
1491 ByteReader<uint16_t>::ReadBigEndian(&data[header.headerLength]);
1492 uint32_t original_ssrc =
1493 rtx_to_media_ssrcs_.find(header.ssrc)->second;
1494 std::set<uint16_t>* seq_no_map = &dropped_seq_[original_ssrc];
1495 auto it = seq_no_map->find(original_sequence_number);
1496 if (it != seq_no_map->end()) {
1497 retransmit_observed_ = true;
1498 seq_no_map->erase(it);
1499 } else {
1500 rtx_padding_observed_ = true;
1501 }
1502 } else {
1503 streams_observed_.insert(header.ssrc);
1504 }
1505
1506 if (IsDone())
Peter Boström5811a392015-12-10 13:02:50 +01001507 done_.Set();
sprang861c55e2015-10-16 10:01:21 -07001508
1509 if (drop_packet)
1510 return true;
1511 }
sprang867fb522015-08-03 04:38:41 -07001512 }
sprang861c55e2015-10-16 10:01:21 -07001513
stefan1d8a5062015-10-02 03:39:33 -07001514 return test::DirectTransport::SendRtp(data, length, options);
sprang867fb522015-08-03 04:38:41 -07001515 }
1516
Erik Språng8d629712015-08-04 16:24:03 +02001517 bool IsDone() {
sprang861c55e2015-10-16 10:01:21 -07001518 bool observed_types_ok =
1519 streams_observed_.size() == MultiStreamTest::kNumStreams &&
1520 padding_observed_ && retransmit_observed_ && rtx_padding_observed_;
1521 if (!observed_types_ok)
1522 return false;
1523 // We should not have any gaps in the sequence number range.
1524 size_t seqno_range =
1525 *received_packed_ids_.rbegin() - *received_packed_ids_.begin() + 1;
1526 return seqno_range == received_packed_ids_.size();
Erik Språng8d629712015-08-04 16:24:03 +02001527 }
1528
Peter Boström5811a392015-12-10 13:02:50 +01001529 bool Wait() {
sprang861c55e2015-10-16 10:01:21 -07001530 {
1531 // Can't be sure until this point that rtx_to_media_ssrcs_ etc have
1532 // been initialized and are OK to read.
1533 rtc::CritScope cs(&lock_);
1534 started_ = true;
1535 }
Peter Boström5811a392015-12-10 13:02:50 +01001536 return done_.Wait(kDefaultTimeoutMs);
sprang861c55e2015-10-16 10:01:21 -07001537 }
sprang867fb522015-08-03 04:38:41 -07001538
sprang861c55e2015-10-16 10:01:21 -07001539 rtc::CriticalSection lock_;
Peter Boström5811a392015-12-10 13:02:50 +01001540 rtc::Event done_;
kwiberg27f982b2016-03-01 11:52:33 -08001541 std::unique_ptr<RtpHeaderParser> parser_;
sprang861c55e2015-10-16 10:01:21 -07001542 SequenceNumberUnwrapper unwrapper_;
1543 std::set<int64_t> received_packed_ids_;
sprang867fb522015-08-03 04:38:41 -07001544 std::set<uint32_t> streams_observed_;
sprang861c55e2015-10-16 10:01:21 -07001545 std::map<uint32_t, std::set<uint16_t>> dropped_seq_;
1546 const uint32_t& first_media_ssrc_;
1547 const std::map<uint32_t, uint32_t>& rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001548 bool padding_observed_;
1549 bool rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001550 bool retransmit_observed_;
1551 bool started_;
sprang867fb522015-08-03 04:38:41 -07001552 };
1553
1554 class TransportSequenceNumberTester : public MultiStreamTest {
1555 public:
sprang861c55e2015-10-16 10:01:21 -07001556 TransportSequenceNumberTester()
1557 : first_media_ssrc_(0), observer_(nullptr) {}
sprang867fb522015-08-03 04:38:41 -07001558 virtual ~TransportSequenceNumberTester() {}
1559
1560 protected:
1561 void Wait() override {
Peter Boström74f6e9e2016-04-04 17:56:10 +02001562 RTC_DCHECK(observer_);
Peter Boström5811a392015-12-10 13:02:50 +01001563 EXPECT_TRUE(observer_->Wait());
sprang867fb522015-08-03 04:38:41 -07001564 }
1565
1566 void UpdateSendConfig(
1567 size_t stream_index,
1568 VideoSendStream::Config* send_config,
1569 VideoEncoderConfig* encoder_config,
1570 test::FrameGeneratorCapturer** frame_generator) override {
1571 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001572 send_config->rtp.extensions.push_back(RtpExtension(
1573 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sprang867fb522015-08-03 04:38:41 -07001574
1575 // Force some padding to be sent.
1576 const int kPaddingBitrateBps = 50000;
perkjfa10b552016-10-02 23:45:26 -07001577 encoder_config->max_bitrate_bps = 1000000;
sprang867fb522015-08-03 04:38:41 -07001578 encoder_config->min_transmit_bitrate_bps =
perkjfa10b552016-10-02 23:45:26 -07001579 encoder_config->max_bitrate_bps + kPaddingBitrateBps;
sprang867fb522015-08-03 04:38:41 -07001580
1581 // Configure RTX for redundant payload padding.
1582 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang861c55e2015-10-16 10:01:21 -07001583 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[stream_index]);
sprang867fb522015-08-03 04:38:41 -07001584 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
sprang861c55e2015-10-16 10:01:21 -07001585 rtx_to_media_ssrcs_[kSendRtxSsrcs[stream_index]] =
1586 send_config->rtp.ssrcs[0];
1587
1588 if (stream_index == 0)
1589 first_media_ssrc_ = send_config->rtp.ssrcs[0];
sprang867fb522015-08-03 04:38:41 -07001590 }
1591
1592 void UpdateReceiveConfig(
1593 size_t stream_index,
1594 VideoReceiveStream::Config* receive_config) override {
sprang861c55e2015-10-16 10:01:21 -07001595 receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang867fb522015-08-03 04:38:41 -07001596 receive_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001597 receive_config->rtp.extensions.push_back(RtpExtension(
1598 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sakal55d932b2016-09-30 06:19:08 -07001599 receive_config->renderer = &fake_renderer_;
sprang867fb522015-08-03 04:38:41 -07001600 }
1601
stefanf116bd02015-10-27 08:29:42 -07001602 test::DirectTransport* CreateSendTransport(Call* sender_call) override {
1603 observer_ = new RtpExtensionHeaderObserver(sender_call, first_media_ssrc_,
sprang861c55e2015-10-16 10:01:21 -07001604 rtx_to_media_ssrcs_);
sprang867fb522015-08-03 04:38:41 -07001605 return observer_;
1606 }
1607
1608 private:
sakal55d932b2016-09-30 06:19:08 -07001609 test::FakeVideoRenderer fake_renderer_;
sprang861c55e2015-10-16 10:01:21 -07001610 uint32_t first_media_ssrc_;
1611 std::map<uint32_t, uint32_t> rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001612 RtpExtensionHeaderObserver* observer_;
1613 } tester;
1614
1615 tester.RunTest();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001616}
1617
Stefan Holmer04cb7632016-01-14 20:34:30 +01001618class TransportFeedbackTester : public test::EndToEndTest {
1619 public:
1620 explicit TransportFeedbackTester(bool feedback_enabled,
1621 size_t num_video_streams,
1622 size_t num_audio_streams)
1623 : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
1624 feedback_enabled_(feedback_enabled),
1625 num_video_streams_(num_video_streams),
sprangcd349d92016-07-13 09:11:28 -07001626 num_audio_streams_(num_audio_streams),
1627 receiver_call_(nullptr) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001628 // Only one stream of each supported for now.
1629 EXPECT_LE(num_video_streams, 1u);
1630 EXPECT_LE(num_audio_streams, 1u);
1631 }
1632
1633 protected:
1634 Action OnSendRtcp(const uint8_t* data, size_t length) override {
1635 EXPECT_FALSE(HasTransportFeedback(data, length));
1636 return SEND_PACKET;
1637 }
1638
1639 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
1640 if (HasTransportFeedback(data, length))
1641 observation_complete_.Set();
1642 return SEND_PACKET;
1643 }
1644
1645 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
1646 RTCPUtility::RTCPParserV2 parser(data, length, true);
1647 EXPECT_TRUE(parser.IsValid());
1648
1649 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1650 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1651 if (packet_type == RTCPUtility::RTCPPacketTypes::kTransportFeedback)
1652 return true;
1653 packet_type = parser.Iterate();
1654 }
1655
1656 return false;
1657 }
1658
1659 void PerformTest() override {
1660 const int64_t kDisabledFeedbackTimeoutMs = 5000;
1661 EXPECT_EQ(feedback_enabled_,
1662 observation_complete_.Wait(feedback_enabled_
1663 ? test::CallTest::kDefaultTimeoutMs
1664 : kDisabledFeedbackTimeoutMs));
1665 }
1666
1667 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1668 receiver_call_ = receiver_call;
1669 }
1670
1671 size_t GetNumVideoStreams() const override { return num_video_streams_; }
1672 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
1673
1674 void ModifyVideoConfigs(
1675 VideoSendStream::Config* send_config,
1676 std::vector<VideoReceiveStream::Config>* receive_configs,
1677 VideoEncoderConfig* encoder_config) override {
1678 send_config->rtp.extensions.clear();
1679 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001680 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001681 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1682 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
1683 }
1684
1685 void ModifyAudioConfigs(
1686 AudioSendStream::Config* send_config,
1687 std::vector<AudioReceiveStream::Config>* receive_configs) override {
1688 send_config->rtp.extensions.clear();
1689 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001690 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001691 (*receive_configs)[0].rtp.extensions.clear();
1692 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1693 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001694 }
1695
1696 private:
Erik Språng6b8d3552015-09-24 15:06:57 +02001697 static const int kExtensionId = 5;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001698 const bool feedback_enabled_;
1699 const size_t num_video_streams_;
1700 const size_t num_audio_streams_;
1701 Call* receiver_call_;
1702};
Erik Språng6b8d3552015-09-24 15:06:57 +02001703
Stefan Holmer04cb7632016-01-14 20:34:30 +01001704TEST_F(EndToEndTest, VideoReceivesTransportFeedback) {
1705 TransportFeedbackTester test(true, 1, 0);
1706 RunBaseTest(&test);
Erik Språng6b8d3552015-09-24 15:06:57 +02001707}
stefan43edf0f2015-11-20 18:05:48 -08001708
Stefan Holmer04cb7632016-01-14 20:34:30 +01001709TEST_F(EndToEndTest, VideoTransportFeedbackNotConfigured) {
1710 TransportFeedbackTester test(false, 1, 0);
1711 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001712}
1713
Stefan Holmer04cb7632016-01-14 20:34:30 +01001714TEST_F(EndToEndTest, AudioReceivesTransportFeedback) {
1715 TransportFeedbackTester test(true, 0, 1);
1716 RunBaseTest(&test);
1717}
1718
1719TEST_F(EndToEndTest, AudioTransportFeedbackNotConfigured) {
1720 TransportFeedbackTester test(false, 0, 1);
1721 RunBaseTest(&test);
1722}
1723
1724TEST_F(EndToEndTest, AudioVideoReceivesTransportFeedback) {
1725 TransportFeedbackTester test(true, 1, 1);
1726 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001727}
1728
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001729TEST_F(EndToEndTest, ObserversEncodedFrames) {
1730 class EncodedFrameTestObserver : public EncodedFrameObserver {
1731 public:
1732 EncodedFrameTestObserver()
Peter Boström5811a392015-12-10 13:02:50 +01001733 : length_(0), frame_type_(kEmptyFrame), called_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001734 virtual ~EncodedFrameTestObserver() {}
1735
1736 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
1737 frame_type_ = encoded_frame.frame_type_;
1738 length_ = encoded_frame.length_;
1739 buffer_.reset(new uint8_t[length_]);
1740 memcpy(buffer_.get(), encoded_frame.data_, length_);
Peter Boström5811a392015-12-10 13:02:50 +01001741 called_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001742 }
1743
Peter Boström5811a392015-12-10 13:02:50 +01001744 bool Wait() { return called_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001745
1746 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
1747 ASSERT_EQ(length_, observer.length_)
1748 << "Observed frames are of different lengths.";
1749 EXPECT_EQ(frame_type_, observer.frame_type_)
1750 << "Observed frames have different frame types.";
1751 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
1752 << "Observed encoded frames have different content.";
1753 }
1754
1755 private:
kwiberg27f982b2016-03-01 11:52:33 -08001756 std::unique_ptr<uint8_t[]> buffer_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001757 size_t length_;
1758 FrameType frame_type_;
Peter Boström5811a392015-12-10 13:02:50 +01001759 rtc::Event called_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001760 };
1761
1762 EncodedFrameTestObserver post_encode_observer;
1763 EncodedFrameTestObserver pre_decode_observer;
1764
skvlad11a9cbf2016-10-07 11:53:05 -07001765 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -07001766
stefanf116bd02015-10-27 08:29:42 -07001767 test::DirectTransport sender_transport(sender_call_.get());
1768 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001769 sender_transport.SetReceiver(receiver_call_->Receiver());
1770 receiver_transport.SetReceiver(sender_call_->Receiver());
1771
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001772 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001773 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -08001774 video_send_config_.post_encode_callback = &post_encode_observer;
1775 video_receive_configs_[0].pre_decode_callback = &pre_decode_observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001776
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001777 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001778 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001779
kwiberg27f982b2016-03-01 11:52:33 -08001780 std::unique_ptr<test::FrameGenerator> frame_generator(
perkjfa10b552016-10-02 23:45:26 -07001781 test::FrameGenerator::CreateChromaGenerator(kDefaultWidth,
1782 kDefaultHeight));
perkja49cbd32016-09-16 07:53:41 -07001783 test::FrameForwarder forwarder;
perkj803d97f2016-11-01 11:45:46 -07001784 video_send_stream_->SetSource(
1785 &forwarder, VideoSendStream::DegradationPreference::kBalanced);
perkja49cbd32016-09-16 07:53:41 -07001786 forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001787
Peter Boström5811a392015-12-10 13:02:50 +01001788 EXPECT_TRUE(post_encode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001789 << "Timed out while waiting for send-side encoded-frame callback.";
1790
Peter Boström5811a392015-12-10 13:02:50 +01001791 EXPECT_TRUE(pre_decode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001792 << "Timed out while waiting for pre-decode encoded-frame callback.";
1793
1794 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
1795
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001796 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001797
1798 sender_transport.StopSending();
1799 receiver_transport.StopSending();
1800
1801 DestroyStreams();
1802}
1803
1804TEST_F(EndToEndTest, ReceiveStreamSendsRemb) {
1805 class RembObserver : public test::EndToEndTest {
1806 public:
1807 RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
1808
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001809 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001810 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1811 EXPECT_TRUE(parser.IsValid());
1812
1813 bool received_psfb = false;
1814 bool received_remb = false;
1815 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02001816 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1817 if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbRemb) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001818 const RTCPUtility::RTCPPacket& packet = parser.Packet();
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001819 EXPECT_EQ(packet.PSFBAPP.SenderSSRC, kReceiverLocalVideoSsrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001820 received_psfb = true;
Erik Språng242e22b2015-05-11 10:17:43 +02001821 } else if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbRembItem) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001822 const RTCPUtility::RTCPPacket& packet = parser.Packet();
1823 EXPECT_GT(packet.REMBItem.BitRate, 0u);
1824 EXPECT_EQ(packet.REMBItem.NumberOfSSRCs, 1u);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001825 EXPECT_EQ(packet.REMBItem.SSRCs[0], kVideoSendSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001826 received_remb = true;
1827 }
1828 packet_type = parser.Iterate();
1829 }
1830 if (received_psfb && received_remb)
Peter Boström5811a392015-12-10 13:02:50 +01001831 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001832 return SEND_PACKET;
1833 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001834 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001835 EXPECT_TRUE(Wait()) << "Timed out while waiting for a "
1836 "receiver RTCP REMB packet to be "
1837 "sent.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001838 }
1839 } test;
1840
stefane74eef12016-01-08 06:47:13 -08001841 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001842}
1843
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001844TEST_F(EndToEndTest, VerifyBandwidthStats) {
stefanf116bd02015-10-27 08:29:42 -07001845 class RtcpObserver : public test::EndToEndTest {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001846 public:
1847 RtcpObserver()
1848 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001849 sender_call_(nullptr),
1850 receiver_call_(nullptr),
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001851 has_seen_pacer_delay_(false) {}
1852
stefanf116bd02015-10-27 08:29:42 -07001853 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001854 Call::Stats sender_stats = sender_call_->GetStats();
1855 Call::Stats receiver_stats = receiver_call_->GetStats();
1856 if (!has_seen_pacer_delay_)
1857 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
1858 if (sender_stats.send_bandwidth_bps > 0 &&
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001859 receiver_stats.recv_bandwidth_bps > 0 && has_seen_pacer_delay_) {
Peter Boström5811a392015-12-10 13:02:50 +01001860 observation_complete_.Set();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001861 }
stefanf116bd02015-10-27 08:29:42 -07001862 return SEND_PACKET;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001863 }
1864
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001865 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001866 sender_call_ = sender_call;
1867 receiver_call_ = receiver_call;
1868 }
1869
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001870 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001871 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
1872 "non-zero bandwidth stats.";
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001873 }
1874
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001875 private:
1876 Call* sender_call_;
1877 Call* receiver_call_;
1878 bool has_seen_pacer_delay_;
1879 } test;
1880
stefane74eef12016-01-08 06:47:13 -08001881 RunBaseTest(&test);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001882}
1883
stefan32f81542016-01-20 07:13:58 -08001884
1885// Verifies that it's possible to limit the send BWE by sending a REMB.
1886// This is verified by allowing the send BWE to ramp-up to >1000 kbps,
1887// then have the test generate a REMB of 500 kbps and verify that the send BWE
1888// is reduced to exactly 500 kbps. Then a REMB of 1000 kbps is generated and the
1889// test verifies that the send BWE ramps back up to exactly 1000 kbps.
1890TEST_F(EndToEndTest, RembWithSendSideBwe) {
1891 class BweObserver : public test::EndToEndTest {
1892 public:
1893 BweObserver()
1894 : EndToEndTest(kDefaultTimeoutMs),
1895 sender_call_(nullptr),
1896 clock_(Clock::GetRealTimeClock()),
1897 sender_ssrc_(0),
1898 remb_bitrate_bps_(1000000),
1899 receive_transport_(nullptr),
1900 event_(false, false),
1901 poller_thread_(&BitrateStatsPollingThread,
1902 this,
1903 "BitrateStatsPollingThread"),
Erik Språng737336d2016-07-29 12:59:36 +02001904 state_(kWaitForFirstRampUp),
1905 retransmission_rate_limiter_(clock_, 1000) {}
stefan32f81542016-01-20 07:13:58 -08001906
1907 ~BweObserver() {}
1908
nisseef8b61e2016-04-29 06:09:15 -07001909 test::PacketTransport* CreateReceiveTransport() override {
stefan32f81542016-01-20 07:13:58 -08001910 receive_transport_ = new test::PacketTransport(
1911 nullptr, this, test::PacketTransport::kReceiver,
1912 FakeNetworkPipe::Config());
1913 return receive_transport_;
1914 }
1915
1916 Call::Config GetSenderCallConfig() override {
skvlad11a9cbf2016-10-07 11:53:05 -07001917 Call::Config config(&event_log_);
stefan32f81542016-01-20 07:13:58 -08001918 // Set a high start bitrate to reduce the test completion time.
1919 config.bitrate_config.start_bitrate_bps = remb_bitrate_bps_;
1920 return config;
1921 }
1922
1923 void ModifyVideoConfigs(
1924 VideoSendStream::Config* send_config,
1925 std::vector<VideoReceiveStream::Config>* receive_configs,
1926 VideoEncoderConfig* encoder_config) override {
1927 ASSERT_EQ(1u, send_config->rtp.ssrcs.size());
1928 send_config->rtp.extensions.clear();
1929 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001930 RtpExtension(RtpExtension::kTransportSequenceNumberUri,
stefan32f81542016-01-20 07:13:58 -08001931 test::kTransportSequenceNumberExtensionId));
1932 sender_ssrc_ = send_config->rtp.ssrcs[0];
1933
perkjfa10b552016-10-02 23:45:26 -07001934 encoder_config->max_bitrate_bps = 2000000;
stefan32f81542016-01-20 07:13:58 -08001935
1936 ASSERT_EQ(1u, receive_configs->size());
1937 (*receive_configs)[0].rtp.remb = false;
1938 (*receive_configs)[0].rtp.transport_cc = true;
1939 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1940 RtpRtcp::Configuration config;
1941 config.receiver_only = true;
1942 config.clock = clock_;
1943 config.outgoing_transport = receive_transport_;
Erik Språng737336d2016-07-29 12:59:36 +02001944 config.retransmission_rate_limiter = &retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08001945 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
1946 rtp_rtcp_->SetRemoteSSRC((*receive_configs)[0].rtp.remote_ssrc);
1947 rtp_rtcp_->SetSSRC((*receive_configs)[0].rtp.local_ssrc);
1948 rtp_rtcp_->SetREMBStatus(true);
1949 rtp_rtcp_->SetSendingStatus(true);
1950 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
1951 }
1952
1953 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1954 sender_call_ = sender_call;
1955 }
1956
1957 static bool BitrateStatsPollingThread(void* obj) {
1958 return static_cast<BweObserver*>(obj)->PollStats();
1959 }
1960
1961 bool PollStats() {
1962 if (sender_call_) {
1963 Call::Stats stats = sender_call_->GetStats();
1964 switch (state_) {
1965 case kWaitForFirstRampUp:
1966 if (stats.send_bandwidth_bps >= remb_bitrate_bps_) {
1967 state_ = kWaitForRemb;
1968 remb_bitrate_bps_ /= 2;
1969 rtp_rtcp_->SetREMBData(
1970 remb_bitrate_bps_,
1971 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
1972 rtp_rtcp_->SendRTCP(kRtcpRr);
1973 }
1974 break;
1975
1976 case kWaitForRemb:
1977 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
1978 state_ = kWaitForSecondRampUp;
1979 remb_bitrate_bps_ *= 2;
1980 rtp_rtcp_->SetREMBData(
1981 remb_bitrate_bps_,
1982 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
1983 rtp_rtcp_->SendRTCP(kRtcpRr);
1984 }
1985 break;
1986
1987 case kWaitForSecondRampUp:
1988 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
1989 observation_complete_.Set();
1990 }
1991 break;
1992 }
1993 }
1994
1995 return !event_.Wait(1000);
1996 }
1997
1998 void PerformTest() override {
1999 poller_thread_.Start();
2000 EXPECT_TRUE(Wait())
2001 << "Timed out while waiting for bitrate to change according to REMB.";
2002 poller_thread_.Stop();
2003 }
2004
2005 private:
2006 enum TestState { kWaitForFirstRampUp, kWaitForRemb, kWaitForSecondRampUp };
2007
2008 Call* sender_call_;
2009 Clock* const clock_;
2010 uint32_t sender_ssrc_;
2011 int remb_bitrate_bps_;
kwiberg27f982b2016-03-01 11:52:33 -08002012 std::unique_ptr<RtpRtcp> rtp_rtcp_;
stefan32f81542016-01-20 07:13:58 -08002013 test::PacketTransport* receive_transport_;
2014 rtc::Event event_;
2015 rtc::PlatformThread poller_thread_;
2016 TestState state_;
Erik Språng737336d2016-07-29 12:59:36 +02002017 RateLimiter retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08002018 } test;
2019
2020 RunBaseTest(&test);
2021}
2022
Åsa Persson352b2d72015-04-15 18:00:40 +02002023TEST_F(EndToEndTest, VerifyNackStats) {
2024 static const int kPacketNumberToDrop = 200;
2025 class NackObserver : public test::EndToEndTest {
2026 public:
2027 NackObserver()
2028 : EndToEndTest(kLongTimeoutMs),
2029 sent_rtp_packets_(0),
2030 dropped_rtp_packet_(0),
2031 dropped_rtp_packet_requested_(false),
2032 send_stream_(nullptr),
2033 start_runtime_ms_(-1) {}
2034
2035 private:
2036 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002037 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002038 if (++sent_rtp_packets_ == kPacketNumberToDrop) {
kwiberg27f982b2016-03-01 11:52:33 -08002039 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
Åsa Persson352b2d72015-04-15 18:00:40 +02002040 RTPHeader header;
2041 EXPECT_TRUE(parser->Parse(packet, length, &header));
2042 dropped_rtp_packet_ = header.sequenceNumber;
2043 return DROP_PACKET;
2044 }
2045 VerifyStats();
2046 return SEND_PACKET;
2047 }
2048
2049 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002050 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002051 test::RtcpPacketParser rtcp_parser;
2052 rtcp_parser.Parse(packet, length);
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02002053 const std::vector<uint16_t>& nacks = rtcp_parser.nack()->packet_ids();
Åsa Persson352b2d72015-04-15 18:00:40 +02002054 if (!nacks.empty() && std::find(
2055 nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) {
2056 dropped_rtp_packet_requested_ = true;
2057 }
2058 return SEND_PACKET;
2059 }
2060
stefan608213e2015-11-01 14:56:10 -08002061 void VerifyStats() EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002062 if (!dropped_rtp_packet_requested_)
2063 return;
2064 int send_stream_nack_packets = 0;
2065 int receive_stream_nack_packets = 0;
2066 VideoSendStream::Stats stats = send_stream_->GetStats();
2067 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
2068 stats.substreams.begin(); it != stats.substreams.end(); ++it) {
2069 const VideoSendStream::StreamStats& stream_stats = it->second;
2070 send_stream_nack_packets +=
2071 stream_stats.rtcp_packet_type_counts.nack_packets;
2072 }
2073 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2074 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2075 receive_stream_nack_packets +=
2076 stats.rtcp_packet_type_counts.nack_packets;
2077 }
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002078 if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002079 // NACK packet sent on receive stream and received on sent stream.
2080 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002081 observation_complete_.Set();
Åsa Persson352b2d72015-04-15 18:00:40 +02002082 }
2083 }
2084
2085 bool MinMetricRunTimePassed() {
2086 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2087 if (start_runtime_ms_ == -1) {
2088 start_runtime_ms_ = now;
2089 return false;
2090 }
2091 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2092 return elapsed_sec > metrics::kMinRunTimeInSeconds;
2093 }
2094
stefanff483612015-12-21 03:14:00 -08002095 void ModifyVideoConfigs(
2096 VideoSendStream::Config* send_config,
2097 std::vector<VideoReceiveStream::Config>* receive_configs,
2098 VideoEncoderConfig* encoder_config) override {
Åsa Persson352b2d72015-04-15 18:00:40 +02002099 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2100 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sakal55d932b2016-09-30 06:19:08 -07002101 (*receive_configs)[0].renderer = &fake_renderer_;
Åsa Persson352b2d72015-04-15 18:00:40 +02002102 }
2103
stefanff483612015-12-21 03:14:00 -08002104 void OnVideoStreamsCreated(
Åsa Persson352b2d72015-04-15 18:00:40 +02002105 VideoSendStream* send_stream,
2106 const std::vector<VideoReceiveStream*>& receive_streams) override {
2107 send_stream_ = send_stream;
2108 receive_streams_ = receive_streams;
2109 }
2110
2111 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002112 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson352b2d72015-04-15 18:00:40 +02002113 }
2114
sakal55d932b2016-09-30 06:19:08 -07002115 test::FakeVideoRenderer fake_renderer_;
stefan608213e2015-11-01 14:56:10 -08002116 rtc::CriticalSection crit_;
Åsa Persson352b2d72015-04-15 18:00:40 +02002117 uint64_t sent_rtp_packets_;
stefan608213e2015-11-01 14:56:10 -08002118 uint16_t dropped_rtp_packet_ GUARDED_BY(&crit_);
2119 bool dropped_rtp_packet_requested_ GUARDED_BY(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002120 std::vector<VideoReceiveStream*> receive_streams_;
2121 VideoSendStream* send_stream_;
2122 int64_t start_runtime_ms_;
2123 } test;
2124
asapersson01d70a32016-05-20 06:29:46 -07002125 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002126 RunBaseTest(&test);
Åsa Persson352b2d72015-04-15 18:00:40 +02002127
asapersson01d70a32016-05-20 06:29:46 -07002128 EXPECT_EQ(
2129 1, metrics::NumSamples("WebRTC.Video.UniqueNackRequestsSentInPercent"));
2130 EXPECT_EQ(1, metrics::NumSamples(
2131 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
2132 EXPECT_GT(metrics::MinSample("WebRTC.Video.NackPacketsSentPerMinute"), 0);
Åsa Persson352b2d72015-04-15 18:00:40 +02002133}
2134
sprangb4a1ae52015-12-03 08:10:08 -08002135void EndToEndTest::VerifyHistogramStats(bool use_rtx,
2136 bool use_red,
2137 bool screenshare) {
tommi2e82f382016-06-21 00:26:43 -07002138 class StatsObserver : public test::EndToEndTest,
2139 public rtc::VideoSinkInterface<VideoFrame> {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002140 public:
sprangb4a1ae52015-12-03 08:10:08 -08002141 StatsObserver(bool use_rtx, bool use_red, bool screenshare)
Åsa Persson3c391cb2015-04-27 10:09:49 +02002142 : EndToEndTest(kLongTimeoutMs),
2143 use_rtx_(use_rtx),
2144 use_red_(use_red),
sprangb4a1ae52015-12-03 08:10:08 -08002145 screenshare_(screenshare),
Peter Boström39593972016-02-15 11:27:15 +01002146 // This test uses NACK, so to send FEC we can't use a fake encoder.
2147 vp8_encoder_(
2148 use_red ? VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)
2149 : nullptr),
Åsa Persson3c391cb2015-04-27 10:09:49 +02002150 sender_call_(nullptr),
2151 receiver_call_(nullptr),
asapersson1394c7b2016-10-18 11:50:50 -07002152 start_runtime_ms_(-1),
2153 num_frames_received_(0) {}
Åsa Persson3c391cb2015-04-27 10:09:49 +02002154
2155 private:
asapersson1394c7b2016-10-18 11:50:50 -07002156 void OnFrame(const VideoFrame& video_frame) override {
2157 // The RTT is needed to estimate |ntp_time_ms| which is used by
2158 // end-to-end delay stats. Therefore, start counting received frames once
2159 // |ntp_time_ms| is valid.
2160 if (video_frame.ntp_time_ms() > 0 &&
2161 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() >=
2162 video_frame.ntp_time_ms()) {
2163 rtc::CritScope lock(&crit_);
2164 ++num_frames_received_;
2165 }
2166 }
tommi2e82f382016-06-21 00:26:43 -07002167
Åsa Persson3c391cb2015-04-27 10:09:49 +02002168 Action OnSendRtp(const uint8_t* packet, size_t length) override {
asapersson1394c7b2016-10-18 11:50:50 -07002169 if (MinMetricRunTimePassed() && MinNumberOfFramesReceived())
Peter Boström5811a392015-12-10 13:02:50 +01002170 observation_complete_.Set();
Åsa Persson3c391cb2015-04-27 10:09:49 +02002171
stefanf116bd02015-10-27 08:29:42 -07002172 return SEND_PACKET;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002173 }
2174
2175 bool MinMetricRunTimePassed() {
2176 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2177 if (start_runtime_ms_ == -1) {
2178 start_runtime_ms_ = now;
2179 return false;
2180 }
2181 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2182 return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
2183 }
2184
asapersson1394c7b2016-10-18 11:50:50 -07002185 bool MinNumberOfFramesReceived() const {
2186 const int kMinRequiredHistogramSamples = 200;
2187 rtc::CritScope lock(&crit_);
2188 return num_frames_received_ > kMinRequiredHistogramSamples;
2189 }
2190
stefanff483612015-12-21 03:14:00 -08002191 void ModifyVideoConfigs(
2192 VideoSendStream::Config* send_config,
2193 std::vector<VideoReceiveStream::Config>* receive_configs,
2194 VideoEncoderConfig* encoder_config) override {
stefana23fc622016-07-28 07:56:38 -07002195 static const int kExtensionId = 8;
2196 send_config->rtp.extensions.push_back(RtpExtension(
2197 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
2198 (*receive_configs)[0].rtp.extensions.push_back(RtpExtension(
2199 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002200 // NACK
2201 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2202 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
tommi2e82f382016-06-21 00:26:43 -07002203 (*receive_configs)[0].renderer = this;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002204 // FEC
2205 if (use_red_) {
brandtrb5f2c3f2016-10-04 23:28:39 -07002206 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
2207 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
Peter Boström39593972016-02-15 11:27:15 +01002208 send_config->encoder_settings.encoder = vp8_encoder_.get();
2209 send_config->encoder_settings.payload_name = "VP8";
2210 (*receive_configs)[0].decoders[0].payload_name = "VP8";
brandtrb5f2c3f2016-10-04 23:28:39 -07002211 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
2212 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type =
2213 kUlpfecPayloadType;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002214 }
2215 // RTX
2216 if (use_rtx_) {
2217 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
2218 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002219 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002220 kSendRtxSsrcs[0];
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002221 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002222 kSendRtxPayloadType;
2223 }
asapersson1490f7a2016-09-23 02:09:46 -07002224 // RTT needed for RemoteNtpTimeEstimator for the receive stream.
2225 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = true;
sprangb4a1ae52015-12-03 08:10:08 -08002226 encoder_config->content_type =
2227 screenshare_ ? VideoEncoderConfig::ContentType::kScreen
2228 : VideoEncoderConfig::ContentType::kRealtimeVideo;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002229 }
2230
2231 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2232 sender_call_ = sender_call;
2233 receiver_call_ = receiver_call;
2234 }
2235
Åsa Persson3c391cb2015-04-27 10:09:49 +02002236 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002237 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson3c391cb2015-04-27 10:09:49 +02002238 }
2239
asapersson1394c7b2016-10-18 11:50:50 -07002240 rtc::CriticalSection crit_;
sprangb4a1ae52015-12-03 08:10:08 -08002241 const bool use_rtx_;
2242 const bool use_red_;
2243 const bool screenshare_;
kwiberg27f982b2016-03-01 11:52:33 -08002244 const std::unique_ptr<VideoEncoder> vp8_encoder_;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002245 Call* sender_call_;
2246 Call* receiver_call_;
2247 int64_t start_runtime_ms_;
asapersson1394c7b2016-10-18 11:50:50 -07002248 int num_frames_received_ GUARDED_BY(&crit_);
sprangb4a1ae52015-12-03 08:10:08 -08002249 } test(use_rtx, use_red, screenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002250
asapersson01d70a32016-05-20 06:29:46 -07002251 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002252 RunBaseTest(&test);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002253
stefan91d92602015-11-11 10:13:02 -08002254 // Delete the call for Call stats to be reported.
stefan18adf0a2015-11-17 06:24:56 -08002255 sender_call_.reset();
stefan91d92602015-11-11 10:13:02 -08002256 receiver_call_.reset();
2257
sprangb4a1ae52015-12-03 08:10:08 -08002258 std::string video_prefix =
2259 screenshare ? "WebRTC.Video.Screenshare." : "WebRTC.Video.";
2260
Åsa Persson3c391cb2015-04-27 10:09:49 +02002261 // Verify that stats have been updated once.
asapersson4374a092016-07-27 00:39:09 -07002262 EXPECT_EQ(2, metrics::NumSamples("WebRTC.Call.LifetimeInSeconds"));
asapersson01d70a32016-05-20 06:29:46 -07002263 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
2264 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.RtcpBitrateReceivedInBps"));
2265 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.BitrateReceivedInKbps"));
2266 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.EstimatedSendBitrateInKbps"));
2267 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.PacerBitrateInKbps"));
2268
asapersson4374a092016-07-27 00:39:09 -07002269 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
2270 EXPECT_EQ(1,
2271 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
2272
asapersson01d70a32016-05-20 06:29:46 -07002273 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
stefan91d92602015-11-11 10:13:02 -08002274 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002275 metrics::NumSamples(video_prefix + "NackPacketsReceivedPerMinute"));
2276 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
asaperssond89920b2015-07-22 06:52:00 -07002277 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002278 metrics::NumSamples(video_prefix + "FirPacketsReceivedPerMinute"));
2279 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
sprangb4a1ae52015-12-03 08:10:08 -08002280 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002281 metrics::NumSamples(video_prefix + "PliPacketsReceivedPerMinute"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002282
asapersson01d70a32016-05-20 06:29:46 -07002283 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "KeyFramesSentInPermille"));
2284 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
2285
2286 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentPacketsLostInPercent"));
2287 EXPECT_EQ(1,
2288 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
2289
2290 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputWidthInPixels"));
2291 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputHeightInPixels"));
2292 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentWidthInPixels"));
2293 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentHeightInPixels"));
2294 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
2295 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
2296
perkjfa10b552016-10-02 23:45:26 -07002297 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputWidthInPixels",
2298 kDefaultWidth));
2299 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputHeightInPixels",
2300 kDefaultHeight));
2301 EXPECT_EQ(
2302 1, metrics::NumEvents(video_prefix + "SentWidthInPixels", kDefaultWidth));
2303 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "SentHeightInPixels",
2304 kDefaultHeight));
2305 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedWidthInPixels",
2306 kDefaultWidth));
2307 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedHeightInPixels",
2308 kDefaultHeight));
asapersson01d70a32016-05-20 06:29:46 -07002309
2310 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputFramesPerSecond"));
2311 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentFramesPerSecond"));
2312 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
2313 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
2314
2315 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
2316 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
2317 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
2318 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
2319
asapersson1490f7a2016-09-23 02:09:46 -07002320 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.EndToEndDelayInMs"));
asapersson01d70a32016-05-20 06:29:46 -07002321 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
2322
2323 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EncodeTimeInMs"));
2324 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
2325
2326 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "BitrateSentInKbps"));
2327 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateReceivedInKbps"));
2328 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "MediaBitrateSentInKbps"));
2329 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateReceivedInKbps"));
2330 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PaddingBitrateSentInKbps"));
2331 EXPECT_EQ(1,
2332 metrics::NumSamples("WebRTC.Video.PaddingBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002333 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002334 1, metrics::NumSamples(video_prefix + "RetransmittedBitrateSentInKbps"));
2335 EXPECT_EQ(1, metrics::NumSamples(
2336 "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002337
asapersson01d70a32016-05-20 06:29:46 -07002338 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendDelayInMs"));
2339 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayInMs"));
2340 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayMaxInMs"));
asapersson6f14be82015-11-16 00:40:49 -08002341
Åsa Persson3c391cb2015-04-27 10:09:49 +02002342 int num_rtx_samples = use_rtx ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002343 EXPECT_EQ(num_rtx_samples,
2344 metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2345 EXPECT_EQ(num_rtx_samples,
2346 metrics::NumSamples("WebRTC.Video.RtxBitrateReceivedInKbps"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002347
2348 int num_red_samples = use_red ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002349 EXPECT_EQ(num_red_samples,
2350 metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2351 EXPECT_EQ(num_red_samples,
2352 metrics::NumSamples("WebRTC.Video.FecBitrateReceivedInKbps"));
2353 EXPECT_EQ(num_red_samples,
2354 metrics::NumSamples("WebRTC.Video.ReceivedFecPacketsInPercent"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002355}
2356
2357TEST_F(EndToEndTest, VerifyHistogramStatsWithRtx) {
2358 const bool kEnabledRtx = true;
2359 const bool kEnabledRed = false;
sprangb4a1ae52015-12-03 08:10:08 -08002360 const bool kScreenshare = false;
2361 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002362}
2363
2364TEST_F(EndToEndTest, VerifyHistogramStatsWithRed) {
2365 const bool kEnabledRtx = false;
2366 const bool kEnabledRed = true;
sprangb4a1ae52015-12-03 08:10:08 -08002367 const bool kScreenshare = false;
2368 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
2369}
2370
2371TEST_F(EndToEndTest, VerifyHistogramStatsWithScreenshare) {
2372 const bool kEnabledRtx = false;
2373 const bool kEnabledRed = false;
2374 const bool kScreenshare = true;
2375 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002376}
2377
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002378void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
2379 static const int kNumRtcpReportPacketsToObserve = 5;
2380 class RtcpXrObserver : public test::EndToEndTest {
2381 public:
2382 explicit RtcpXrObserver(bool enable_rrtr)
2383 : EndToEndTest(kDefaultTimeoutMs),
2384 enable_rrtr_(enable_rrtr),
2385 sent_rtcp_sr_(0),
2386 sent_rtcp_rr_(0),
2387 sent_rtcp_rrtr_(0),
2388 sent_rtcp_dlrr_(0) {}
2389
2390 private:
2391 // Receive stream should send RR packets (and RRTR packets if enabled).
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002392 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002393 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002394 RTCPUtility::RTCPParserV2 parser(packet, length, true);
2395 EXPECT_TRUE(parser.IsValid());
2396
2397 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02002398 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
2399 if (packet_type == RTCPUtility::RTCPPacketTypes::kRr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002400 ++sent_rtcp_rr_;
2401 } else if (packet_type ==
Erik Språng242e22b2015-05-11 10:17:43 +02002402 RTCPUtility::RTCPPacketTypes::kXrReceiverReferenceTime) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002403 ++sent_rtcp_rrtr_;
2404 }
Erik Språng242e22b2015-05-11 10:17:43 +02002405 EXPECT_NE(packet_type, RTCPUtility::RTCPPacketTypes::kSr);
2406 EXPECT_NE(packet_type,
2407 RTCPUtility::RTCPPacketTypes::kXrDlrrReportBlockItem);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002408 packet_type = parser.Iterate();
2409 }
2410 return SEND_PACKET;
2411 }
2412 // Send stream should send SR packets (and DLRR packets if enabled).
nisseef8b61e2016-04-29 06:09:15 -07002413 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002414 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002415 RTCPUtility::RTCPParserV2 parser(packet, length, true);
2416 EXPECT_TRUE(parser.IsValid());
2417
2418 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02002419 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
2420 if (packet_type == RTCPUtility::RTCPPacketTypes::kSr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002421 ++sent_rtcp_sr_;
Erik Språng242e22b2015-05-11 10:17:43 +02002422 } else if (packet_type ==
2423 RTCPUtility::RTCPPacketTypes::kXrDlrrReportBlockItem) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002424 ++sent_rtcp_dlrr_;
2425 }
Erik Språng242e22b2015-05-11 10:17:43 +02002426 EXPECT_NE(packet_type,
2427 RTCPUtility::RTCPPacketTypes::kXrReceiverReferenceTime);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002428 packet_type = parser.Iterate();
2429 }
2430 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
2431 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve) {
2432 if (enable_rrtr_) {
2433 EXPECT_GT(sent_rtcp_rrtr_, 0);
2434 EXPECT_GT(sent_rtcp_dlrr_, 0);
2435 } else {
2436 EXPECT_EQ(0, sent_rtcp_rrtr_);
2437 EXPECT_EQ(0, sent_rtcp_dlrr_);
2438 }
Peter Boström5811a392015-12-10 13:02:50 +01002439 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002440 }
2441 return SEND_PACKET;
2442 }
2443
stefanff483612015-12-21 03:14:00 -08002444 void ModifyVideoConfigs(
2445 VideoSendStream::Config* send_config,
2446 std::vector<VideoReceiveStream::Config>* receive_configs,
2447 VideoEncoderConfig* encoder_config) override {
pbosda903ea2015-10-02 02:36:56 -07002448 (*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002449 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
2450 enable_rrtr_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002451 }
2452
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002453 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002454 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002455 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
2456 }
2457
stefan608213e2015-11-01 14:56:10 -08002458 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002459 bool enable_rrtr_;
2460 int sent_rtcp_sr_;
stefan608213e2015-11-01 14:56:10 -08002461 int sent_rtcp_rr_ GUARDED_BY(&crit_);
2462 int sent_rtcp_rrtr_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002463 int sent_rtcp_dlrr_;
2464 } test(enable_rrtr);
2465
stefane74eef12016-01-08 06:47:13 -08002466 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002467}
2468
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002469void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
2470 bool send_single_ssrc_first) {
2471 class SendsSetSsrcs : public test::EndToEndTest {
2472 public:
2473 SendsSetSsrcs(const uint32_t* ssrcs,
2474 size_t num_ssrcs,
2475 bool send_single_ssrc_first)
2476 : EndToEndTest(kDefaultTimeoutMs),
2477 num_ssrcs_(num_ssrcs),
2478 send_single_ssrc_first_(send_single_ssrc_first),
2479 ssrcs_to_observe_(num_ssrcs),
sprang867fb522015-08-03 04:38:41 -07002480 expect_single_ssrc_(send_single_ssrc_first),
2481 send_stream_(nullptr) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002482 for (size_t i = 0; i < num_ssrcs; ++i)
2483 valid_ssrcs_[ssrcs[i]] = true;
2484 }
2485
2486 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002487 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002488 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002489 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002490
2491 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
2492 << "Received unknown SSRC: " << header.ssrc;
2493
2494 if (!valid_ssrcs_[header.ssrc])
Peter Boström5811a392015-12-10 13:02:50 +01002495 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002496
2497 if (!is_observed_[header.ssrc]) {
2498 is_observed_[header.ssrc] = true;
2499 --ssrcs_to_observe_;
2500 if (expect_single_ssrc_) {
2501 expect_single_ssrc_ = false;
Peter Boström5811a392015-12-10 13:02:50 +01002502 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002503 }
2504 }
2505
2506 if (ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002507 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002508
2509 return SEND_PACKET;
2510 }
2511
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002512 size_t GetNumVideoStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002513
perkjfa10b552016-10-02 23:45:26 -07002514 // This test use other VideoStream settings than the the default settings
2515 // implemented in DefaultVideoStreamFactory. Therefore this test implement
2516 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
2517 // in ModifyVideoConfigs.
2518 class VideoStreamFactory
2519 : public VideoEncoderConfig::VideoStreamFactoryInterface {
2520 public:
2521 VideoStreamFactory() {}
2522
2523 private:
2524 std::vector<VideoStream> CreateEncoderStreams(
2525 int width,
2526 int height,
2527 const VideoEncoderConfig& encoder_config) override {
2528 std::vector<VideoStream> streams =
2529 test::CreateVideoStreams(width, height, encoder_config);
2530 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
2531 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
2532 streams[i].min_bitrate_bps = 10000;
2533 streams[i].target_bitrate_bps = 15000;
2534 streams[i].max_bitrate_bps = 20000;
2535 }
2536 return streams;
2537 }
2538 };
2539
stefanff483612015-12-21 03:14:00 -08002540 void ModifyVideoConfigs(
2541 VideoSendStream::Config* send_config,
2542 std::vector<VideoReceiveStream::Config>* receive_configs,
2543 VideoEncoderConfig* encoder_config) override {
perkjfa10b552016-10-02 23:45:26 -07002544 encoder_config->video_stream_factory =
2545 new rtc::RefCountedObject<VideoStreamFactory>();
perkj26091b12016-09-01 01:17:40 -07002546 video_encoder_config_all_streams_ = encoder_config->Copy();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002547 if (send_single_ssrc_first_)
perkjfa10b552016-10-02 23:45:26 -07002548 encoder_config->number_of_streams = 1;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002549 }
2550
stefanff483612015-12-21 03:14:00 -08002551 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002552 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002553 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002554 send_stream_ = send_stream;
2555 }
2556
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002557 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002558 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2559 << (send_single_ssrc_first_ ? "first SSRC."
2560 : "SSRCs.");
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002561
2562 if (send_single_ssrc_first_) {
2563 // Set full simulcast and continue with the rest of the SSRCs.
stefanff483612015-12-21 03:14:00 -08002564 send_stream_->ReconfigureVideoEncoder(
perkj26091b12016-09-01 01:17:40 -07002565 std::move(video_encoder_config_all_streams_));
Peter Boström5811a392015-12-10 13:02:50 +01002566 EXPECT_TRUE(Wait()) << "Timed out while waiting on additional SSRCs.";
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002567 }
2568 }
2569
2570 private:
2571 std::map<uint32_t, bool> valid_ssrcs_;
2572 std::map<uint32_t, bool> is_observed_;
2573
2574 const size_t num_ssrcs_;
2575 const bool send_single_ssrc_first_;
2576
2577 size_t ssrcs_to_observe_;
2578 bool expect_single_ssrc_;
2579
2580 VideoSendStream* send_stream_;
stefanff483612015-12-21 03:14:00 -08002581 VideoEncoderConfig video_encoder_config_all_streams_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002582 } test(kVideoSendSsrcs, num_ssrcs, send_single_ssrc_first);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002583
stefane74eef12016-01-08 06:47:13 -08002584 RunBaseTest(&test);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002585}
2586
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002587TEST_F(EndToEndTest, ReportsSetEncoderRates) {
2588 class EncoderRateStatsTest : public test::EndToEndTest,
2589 public test::FakeEncoder {
2590 public:
2591 EncoderRateStatsTest()
2592 : EndToEndTest(kDefaultTimeoutMs),
sprang867fb522015-08-03 04:38:41 -07002593 FakeEncoder(Clock::GetRealTimeClock()),
2594 send_stream_(nullptr),
2595 bitrate_kbps_(0) {}
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002596
stefanff483612015-12-21 03:14:00 -08002597 void OnVideoStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002598 VideoSendStream* send_stream,
2599 const std::vector<VideoReceiveStream*>& receive_streams) override {
2600 send_stream_ = send_stream;
2601 }
2602
stefanff483612015-12-21 03:14:00 -08002603 void ModifyVideoConfigs(
2604 VideoSendStream::Config* send_config,
2605 std::vector<VideoReceiveStream::Config>* receive_configs,
2606 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002607 send_config->encoder_settings.encoder = this;
perkjfa10b552016-10-02 23:45:26 -07002608 RTC_DCHECK_EQ(1u, encoder_config->number_of_streams);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002609 }
2610
2611 int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override {
2612 // Make sure not to trigger on any default zero bitrates.
2613 if (new_target_bitrate == 0)
2614 return 0;
Peter Boströmf2f82832015-05-01 13:00:41 +02002615 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002616 bitrate_kbps_ = new_target_bitrate;
Peter Boström5811a392015-12-10 13:02:50 +01002617 observation_complete_.Set();
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002618 return 0;
2619 }
2620
2621 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002622 ASSERT_TRUE(Wait())
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002623 << "Timed out while waiting for encoder SetRates() call.";
perkjf5b2e512016-07-05 08:34:04 -07002624 WaitForEncoderTargetBitrateMatchStats();
2625 send_stream_->Stop();
2626 WaitForStatsReportZeroTargetBitrate();
2627 send_stream_->Start();
2628 WaitForEncoderTargetBitrateMatchStats();
2629 }
2630
2631 void WaitForEncoderTargetBitrateMatchStats() {
Peter Boström5811a392015-12-10 13:02:50 +01002632 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002633 VideoSendStream::Stats stats = send_stream_->GetStats();
2634 {
Peter Boströmf2f82832015-05-01 13:00:41 +02002635 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002636 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
2637 static_cast<int>(bitrate_kbps_)) {
2638 return;
2639 }
2640 }
2641 SleepMs(1);
2642 }
2643 FAIL()
2644 << "Timed out waiting for stats reporting the currently set bitrate.";
2645 }
2646
perkjf5b2e512016-07-05 08:34:04 -07002647 void WaitForStatsReportZeroTargetBitrate() {
2648 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
2649 if (send_stream_->GetStats().target_media_bitrate_bps == 0) {
2650 return;
2651 }
2652 SleepMs(1);
2653 }
2654 FAIL() << "Timed out waiting for stats reporting zero bitrate.";
2655 }
2656
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002657 private:
stefanf116bd02015-10-27 08:29:42 -07002658 rtc::CriticalSection crit_;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002659 VideoSendStream* send_stream_;
2660 uint32_t bitrate_kbps_ GUARDED_BY(crit_);
2661 } test;
2662
stefane74eef12016-01-08 06:47:13 -08002663 RunBaseTest(&test);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002664}
2665
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002666TEST_F(EndToEndTest, GetStats) {
2667 static const int kStartBitrateBps = 3000000;
Peter Boströmdef398832015-05-27 17:59:11 +02002668 static const int kExpectedRenderDelayMs = 20;
tommi2e82f382016-06-21 00:26:43 -07002669
2670 class ReceiveStreamRenderer : public rtc::VideoSinkInterface<VideoFrame> {
2671 public:
2672 ReceiveStreamRenderer() {}
2673
2674 private:
2675 void OnFrame(const VideoFrame& video_frame) override {}
2676 };
2677
nissed30a1112016-04-18 05:15:22 -07002678 class StatsObserver : public test::EndToEndTest,
2679 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002680 public:
stefanf116bd02015-10-27 08:29:42 -07002681 StatsObserver()
2682 : EndToEndTest(kLongTimeoutMs),
Peter Boströmc6e16e32016-02-05 14:15:53 +01002683 encoder_(Clock::GetRealTimeClock(), 10),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002684 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002685 expected_send_ssrcs_(),
Peter Boström5811a392015-12-10 13:02:50 +01002686 check_stats_event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002687
2688 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002689 Action OnSendRtp(const uint8_t* packet, size_t length) override {
sprangcd349d92016-07-13 09:11:28 -07002690 // Drop every 25th packet => 4% loss.
2691 static const int kPacketLossFrac = 25;
2692 RTPHeader header;
2693 RtpUtility::RtpHeaderParser parser(packet, length);
2694 if (parser.Parse(&header) &&
2695 expected_send_ssrcs_.find(header.ssrc) !=
2696 expected_send_ssrcs_.end() &&
2697 header.sequenceNumber % kPacketLossFrac == 0) {
2698 return DROP_PACKET;
2699 }
Peter Boström5811a392015-12-10 13:02:50 +01002700 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002701 return SEND_PACKET;
2702 }
2703
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002704 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002705 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002706 return SEND_PACKET;
2707 }
2708
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002709 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002710 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002711 return SEND_PACKET;
2712 }
2713
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002714 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002715 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002716 return SEND_PACKET;
2717 }
2718
nissed30a1112016-04-18 05:15:22 -07002719 void OnFrame(const VideoFrame& video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002720 // Ensure that we have at least 5ms send side delay.
nissed30a1112016-04-18 05:15:22 -07002721 SleepMs(5);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002722 }
2723
2724 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002725 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2726 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2727 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002728
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002729 // Make sure all fields have been populated.
2730 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
2731 // always filled for all receivers.
2732 receive_stats_filled_["IncomingRate"] |=
2733 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002734
Peter Boströmb7d9a972015-12-18 16:01:11 +01002735 send_stats_filled_["DecoderImplementationName"] |=
2736 stats.decoder_implementation_name ==
2737 test::FakeDecoder::kImplementationName;
Peter Boströmdef398832015-05-27 17:59:11 +02002738 receive_stats_filled_["RenderDelayAsHighAsExpected"] |=
2739 stats.render_delay_ms >= kExpectedRenderDelayMs;
2740
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002741 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002742
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002743 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002744
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002745 receive_stats_filled_["StatisticsUpdated"] |=
2746 stats.rtcp_stats.cumulative_lost != 0 ||
2747 stats.rtcp_stats.extended_max_sequence_number != 0 ||
2748 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002749
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002750 receive_stats_filled_["DataCountersUpdated"] |=
2751 stats.rtp_stats.transmitted.payload_bytes != 0 ||
2752 stats.rtp_stats.fec.packets != 0 ||
2753 stats.rtp_stats.transmitted.header_bytes != 0 ||
2754 stats.rtp_stats.transmitted.packets != 0 ||
2755 stats.rtp_stats.transmitted.padding_bytes != 0 ||
2756 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002757
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002758 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002759 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002760
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002761 receive_stats_filled_["FrameCounts"] |=
2762 stats.frame_counts.key_frames != 0 ||
2763 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002764
pbosbb36fdf2015-07-09 07:48:14 -07002765 receive_stats_filled_["CName"] |= !stats.c_name.empty();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002766
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002767 receive_stats_filled_["RtcpPacketTypeCount"] |=
2768 stats.rtcp_packet_type_counts.fir_packets != 0 ||
2769 stats.rtcp_packet_type_counts.nack_packets != 0 ||
2770 stats.rtcp_packet_type_counts.pli_packets != 0 ||
2771 stats.rtcp_packet_type_counts.nack_requests != 0 ||
2772 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbosf42376c2015-08-28 07:35:32 -07002773
2774 assert(stats.current_payload_type == -1 ||
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002775 stats.current_payload_type == kFakeVideoSendPayloadType);
pbosf42376c2015-08-28 07:35:32 -07002776 receive_stats_filled_["IncomingPayloadType"] |=
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002777 stats.current_payload_type == kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002778 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002779
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002780 return AllStatsFilled(receive_stats_filled_);
2781 }
2782
2783 bool CheckSendStats() {
Peter Boström74f6e9e2016-04-04 17:56:10 +02002784 RTC_DCHECK(send_stream_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002785 VideoSendStream::Stats stats = send_stream_->GetStats();
2786
2787 send_stats_filled_["NumStreams"] |=
2788 stats.substreams.size() == expected_send_ssrcs_.size();
2789
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002790 send_stats_filled_["CpuOveruseMetrics"] |=
Peter Boströme4499152016-02-05 11:13:28 +01002791 stats.avg_encode_time_ms != 0 && stats.encode_usage_percent != 0;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002792
Peter Boströmb7d9a972015-12-18 16:01:11 +01002793 send_stats_filled_["EncoderImplementationName"] |=
2794 stats.encoder_implementation_name ==
2795 test::FakeEncoder::kImplementationName;
2796
Pera48ddb72016-09-29 11:48:50 +02002797 send_stats_filled_["EncoderPreferredBitrate"] |=
2798 stats.preferred_media_bitrate_bps > 0;
2799
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002800 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002801 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002802 it != stats.substreams.end(); ++it) {
sprangcd349d92016-07-13 09:11:28 -07002803 if (expected_send_ssrcs_.find(it->first) == expected_send_ssrcs_.end())
2804 continue; // Probably RTX.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002805
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002806 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002807 stats.input_frame_rate != 0;
2808
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002809 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002810
2811 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
2812 stream_stats.rtcp_stats.cumulative_lost != 0 ||
2813 stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
2814 stream_stats.rtcp_stats.fraction_lost != 0;
2815
2816 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002817 stream_stats.rtp_stats.fec.packets != 0 ||
2818 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
2819 stream_stats.rtp_stats.retransmitted.packets != 0 ||
2820 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002821
sprangcd349d92016-07-13 09:11:28 -07002822 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Total",
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002823 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002824 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002825
sprangcd349d92016-07-13 09:11:28 -07002826 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Retransmit",
2827 it->first)] |=
2828 stream_stats.retransmit_bitrate_bps != 0;
2829
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002830 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002831 stream_stats.frame_counts.delta_frames != 0 ||
2832 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002833
2834 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
2835 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00002836
2837 send_stats_filled_[CompoundKey("Delay", it->first)] |=
2838 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002839
2840 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
2841 // report dropped packets.
2842 send_stats_filled_["RtcpPacketTypeCount"] |=
2843 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
2844 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
2845 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
2846 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
2847 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002848 }
2849
2850 return AllStatsFilled(send_stats_filled_);
2851 }
2852
2853 std::string CompoundKey(const char* name, uint32_t ssrc) {
2854 std::ostringstream oss;
2855 oss << name << "_" << ssrc;
2856 return oss.str();
2857 }
2858
2859 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
sprangcd349d92016-07-13 09:11:28 -07002860 for (const auto& stat : stats_map) {
2861 if (!stat.second)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002862 return false;
2863 }
2864 return true;
2865 }
2866
stefane74eef12016-01-08 06:47:13 -08002867 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
2868 FakeNetworkPipe::Config network_config;
2869 network_config.loss_percent = 5;
2870 return new test::PacketTransport(
2871 sender_call, this, test::PacketTransport::kSender, network_config);
2872 }
2873
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002874 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002875 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01002876 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002877 return config;
2878 }
2879
perkjfa10b552016-10-02 23:45:26 -07002880 // This test use other VideoStream settings than the the default settings
2881 // implemented in DefaultVideoStreamFactory. Therefore this test implement
2882 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
2883 // in ModifyVideoConfigs.
2884 class VideoStreamFactory
2885 : public VideoEncoderConfig::VideoStreamFactoryInterface {
2886 public:
2887 VideoStreamFactory() {}
2888
2889 private:
2890 std::vector<VideoStream> CreateEncoderStreams(
2891 int width,
2892 int height,
2893 const VideoEncoderConfig& encoder_config) override {
2894 std::vector<VideoStream> streams =
2895 test::CreateVideoStreams(width, height, encoder_config);
2896 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
2897 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
2898 streams[i].min_bitrate_bps = 10000;
2899 streams[i].target_bitrate_bps = 15000;
2900 streams[i].max_bitrate_bps = 20000;
2901 }
2902 return streams;
2903 }
2904 };
2905
stefanff483612015-12-21 03:14:00 -08002906 void ModifyVideoConfigs(
2907 VideoSendStream::Config* send_config,
2908 std::vector<VideoReceiveStream::Config>* receive_configs,
2909 VideoEncoderConfig* encoder_config) override {
perkjfa10b552016-10-02 23:45:26 -07002910 encoder_config->video_stream_factory =
2911 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002912 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002913 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002914
sprangcd349d92016-07-13 09:11:28 -07002915 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2916 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
2917
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002918 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002919 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002920 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002921 expected_receive_ssrcs_.push_back(
2922 (*receive_configs)[i].rtp.remote_ssrc);
Peter Boströmdef398832015-05-27 17:59:11 +02002923 (*receive_configs)[i].render_delay_ms = kExpectedRenderDelayMs;
tommi2e82f382016-06-21 00:26:43 -07002924 (*receive_configs)[i].renderer = &receive_stream_renderer_;
sprangcd349d92016-07-13 09:11:28 -07002925 (*receive_configs)[i].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2926
2927 (*receive_configs)[i].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
2928 kSendRtxSsrcs[i];
2929 (*receive_configs)[i].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
2930 kSendRtxPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002931 }
sprangcd349d92016-07-13 09:11:28 -07002932
2933 for (size_t i = 0; i < kNumSsrcs; ++i)
2934 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
2935
Peter Boströmc6e16e32016-02-05 14:15:53 +01002936 // Use a delayed encoder to make sure we see CpuOveruseMetrics stats that
2937 // are non-zero.
2938 send_config->encoder_settings.encoder = &encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002939 }
2940
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002941 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00002942
stefanff483612015-12-21 03:14:00 -08002943 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002944 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002945 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002946 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002947 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002948 }
2949
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002950 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002951 Clock* clock = Clock::GetRealTimeClock();
2952 int64_t now = clock->TimeInMilliseconds();
2953 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
2954 bool receive_ok = false;
2955 bool send_ok = false;
2956
2957 while (now < stop_time) {
2958 if (!receive_ok)
2959 receive_ok = CheckReceiveStats();
2960 if (!send_ok)
2961 send_ok = CheckSendStats();
2962
2963 if (receive_ok && send_ok)
2964 return;
2965
2966 int64_t time_until_timout_ = stop_time - now;
2967 if (time_until_timout_ > 0)
Peter Boström5811a392015-12-10 13:02:50 +01002968 check_stats_event_.Wait(time_until_timout_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002969 now = clock->TimeInMilliseconds();
2970 }
2971
2972 ADD_FAILURE() << "Timed out waiting for filled stats.";
2973 for (std::map<std::string, bool>::const_iterator it =
2974 receive_stats_filled_.begin();
2975 it != receive_stats_filled_.end();
2976 ++it) {
2977 if (!it->second) {
2978 ADD_FAILURE() << "Missing receive stats: " << it->first;
2979 }
2980 }
2981
2982 for (std::map<std::string, bool>::const_iterator it =
2983 send_stats_filled_.begin();
2984 it != send_stats_filled_.end();
2985 ++it) {
2986 if (!it->second) {
2987 ADD_FAILURE() << "Missing send stats: " << it->first;
2988 }
2989 }
2990 }
2991
Peter Boströmc6e16e32016-02-05 14:15:53 +01002992 test::DelayedEncoder encoder_;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002993 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002994 std::map<std::string, bool> receive_stats_filled_;
2995
2996 VideoSendStream* send_stream_;
2997 std::map<std::string, bool> send_stats_filled_;
2998
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002999 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003000 std::set<uint32_t> expected_send_ssrcs_;
3001 std::string expected_cname_;
3002
Peter Boström5811a392015-12-10 13:02:50 +01003003 rtc::Event check_stats_event_;
tommi2e82f382016-06-21 00:26:43 -07003004 ReceiveStreamRenderer receive_stream_renderer_;
stefanf116bd02015-10-27 08:29:42 -07003005 } test;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003006
stefane74eef12016-01-08 06:47:13 -08003007 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003008}
3009
3010TEST_F(EndToEndTest, ReceiverReferenceTimeReportEnabled) {
3011 TestXrReceiverReferenceTimeReport(true);
3012}
3013
3014TEST_F(EndToEndTest, ReceiverReferenceTimeReportDisabled) {
3015 TestXrReceiverReferenceTimeReport(false);
3016}
3017
3018TEST_F(EndToEndTest, TestReceivedRtpPacketStats) {
3019 static const size_t kNumRtpPacketsToSend = 5;
3020 class ReceivedRtpStatsObserver : public test::EndToEndTest {
3021 public:
3022 ReceivedRtpStatsObserver()
3023 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00003024 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003025 sent_rtp_(0) {}
3026
3027 private:
stefanff483612015-12-21 03:14:00 -08003028 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003029 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003030 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003031 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003032 }
3033
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003034 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003035 if (sent_rtp_ >= kNumRtpPacketsToSend) {
3036 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00003037 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
Peter Boström5811a392015-12-10 13:02:50 +01003038 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003039 }
3040 return DROP_PACKET;
3041 }
3042 ++sent_rtp_;
3043 return SEND_PACKET;
3044 }
3045
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003046 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003047 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003048 << "Timed out while verifying number of received RTP packets.";
3049 }
3050
3051 VideoReceiveStream* receive_stream_;
3052 uint32_t sent_rtp_;
3053 } test;
3054
stefane74eef12016-01-08 06:47:13 -08003055 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003056}
3057
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003058TEST_F(EndToEndTest, SendsSetSsrc) { TestSendsSetSsrcs(1, false); }
3059
3060TEST_F(EndToEndTest, SendsSetSimulcastSsrcs) {
3061 TestSendsSetSsrcs(kNumSsrcs, false);
3062}
3063
3064TEST_F(EndToEndTest, CanSwitchToUseAllSsrcs) {
3065 TestSendsSetSsrcs(kNumSsrcs, true);
3066}
3067
mflodman@webrtc.orgf9460682014-07-24 16:41:25 +00003068TEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003069 class ObserveRedundantPayloads: public test::EndToEndTest {
3070 public:
3071 ObserveRedundantPayloads()
3072 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003073 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003074 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
3075 }
3076 }
3077
3078 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003079 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003080 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003081 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003082
3083 if (!registered_rtx_ssrc_[header.ssrc])
3084 return SEND_PACKET;
3085
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003086 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003087 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003088 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003089
3090 if (!packet_is_redundant_payload)
3091 return SEND_PACKET;
3092
3093 if (!observed_redundant_retransmission_[header.ssrc]) {
3094 observed_redundant_retransmission_[header.ssrc] = true;
3095 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01003096 observation_complete_.Set();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003097 }
3098
3099 return SEND_PACKET;
3100 }
3101
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003102 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003103
perkjfa10b552016-10-02 23:45:26 -07003104 // This test use other VideoStream settings than the the default settings
3105 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3106 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3107 // in ModifyVideoConfigs.
3108 class VideoStreamFactory
3109 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3110 public:
3111 VideoStreamFactory() {}
3112
3113 private:
3114 std::vector<VideoStream> CreateEncoderStreams(
3115 int width,
3116 int height,
3117 const VideoEncoderConfig& encoder_config) override {
3118 std::vector<VideoStream> streams =
3119 test::CreateVideoStreams(width, height, encoder_config);
3120 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
3121 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3122 streams[i].min_bitrate_bps = 10000;
3123 streams[i].target_bitrate_bps = 15000;
3124 streams[i].max_bitrate_bps = 20000;
3125 }
3126 return streams;
3127 }
3128 };
3129
stefanff483612015-12-21 03:14:00 -08003130 void ModifyVideoConfigs(
3131 VideoSendStream::Config* send_config,
3132 std::vector<VideoReceiveStream::Config>* receive_configs,
3133 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003134 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
perkjfa10b552016-10-02 23:45:26 -07003135 encoder_config->video_stream_factory =
3136 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003137 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003138
3139 for (size_t i = 0; i < kNumSsrcs; ++i)
3140 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00003141
3142 // Significantly higher than max bitrates for all video streams -> forcing
3143 // padding to trigger redundant padding on all RTX SSRCs.
3144 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003145 }
3146
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003147 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003148 EXPECT_TRUE(Wait())
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003149 << "Timed out while waiting for redundant payloads on all SSRCs.";
3150 }
3151
3152 private:
3153 size_t ssrcs_to_observe_;
3154 std::map<uint32_t, bool> observed_redundant_retransmission_;
3155 std::map<uint32_t, bool> registered_rtx_ssrc_;
3156 } test;
3157
stefane74eef12016-01-08 06:47:13 -08003158 RunBaseTest(&test);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003159}
3160
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003161void EndToEndTest::TestRtpStatePreservation(bool use_rtx,
3162 bool provoke_rtcpsr_before_rtp) {
perkjfa10b552016-10-02 23:45:26 -07003163 // This test use other VideoStream settings than the the default settings
3164 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3165 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3166 // in ModifyVideoConfigs.
3167 class VideoStreamFactory
3168 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3169 public:
3170 VideoStreamFactory() {}
3171
3172 private:
3173 std::vector<VideoStream> CreateEncoderStreams(
3174 int width,
3175 int height,
3176 const VideoEncoderConfig& encoder_config) override {
3177 std::vector<VideoStream> streams =
3178 test::CreateVideoStreams(width, height, encoder_config);
3179
3180 if (encoder_config.number_of_streams > 1) {
3181 // Lower bitrates so that all streams send initially.
3182 RTC_DCHECK_EQ(3u, encoder_config.number_of_streams);
3183 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3184 streams[i].min_bitrate_bps = 10000;
3185 streams[i].target_bitrate_bps = 15000;
3186 streams[i].max_bitrate_bps = 20000;
3187 }
3188 } else {
3189 // Use the same total bitrates when sending a single stream to avoid
3190 // lowering
3191 // the bitrate estimate and requiring a subsequent rampup.
3192 streams[0].min_bitrate_bps = 3 * 10000;
3193 streams[0].target_bitrate_bps = 3 * 15000;
3194 streams[0].max_bitrate_bps = 3 * 20000;
3195 }
3196 return streams;
3197 }
3198 };
3199
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003200 class RtpSequenceObserver : public test::RtpRtcpObserver {
3201 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003202 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003203 : test::RtpRtcpObserver(kDefaultTimeoutMs),
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003204 ssrcs_to_observe_(kNumSsrcs) {
3205 for (size_t i = 0; i < kNumSsrcs; ++i) {
danilchap32cd2c42016-08-01 06:58:34 -07003206 ssrc_is_rtx_[kVideoSendSsrcs[i]] = false;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003207 if (use_rtx)
danilchap32cd2c42016-08-01 06:58:34 -07003208 ssrc_is_rtx_[kSendRtxSsrcs[i]] = true;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003209 }
3210 }
3211
3212 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
Peter Boströmf2f82832015-05-01 13:00:41 +02003213 rtc::CritScope lock(&crit_);
danilchap34877ee2016-02-01 08:25:04 -08003214 ssrc_observed_.clear();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003215 ssrcs_to_observe_ = num_expected_ssrcs;
3216 }
3217
3218 private:
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003219 void ValidateTimestampGap(uint32_t ssrc,
3220 uint32_t timestamp,
3221 bool only_padding)
3222 EXCLUSIVE_LOCKS_REQUIRED(crit_) {
3223 static const int32_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
3224 auto timestamp_it = last_observed_timestamp_.find(ssrc);
3225 if (timestamp_it == last_observed_timestamp_.end()) {
3226 EXPECT_FALSE(only_padding);
3227 last_observed_timestamp_[ssrc] = timestamp;
3228 } else {
3229 // Verify timestamps are reasonably close.
3230 uint32_t latest_observed = timestamp_it->second;
3231 // Wraparound handling is unnecessary here as long as an int variable
3232 // is used to store the result.
3233 int32_t timestamp_gap = timestamp - latest_observed;
3234 EXPECT_LE(std::abs(timestamp_gap), kMaxTimestampGap)
3235 << "Gap in timestamps (" << latest_observed << " -> " << timestamp
3236 << ") too large for SSRC: " << ssrc << ".";
3237 timestamp_it->second = timestamp;
3238 }
3239 }
3240
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003241 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003242 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003243 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003244 const uint32_t ssrc = header.ssrc;
danilchap5c35cf92016-02-03 14:14:49 -08003245 const int64_t sequence_number =
3246 seq_numbers_unwrapper_.Unwrap(header.sequenceNumber);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003247 const uint32_t timestamp = header.timestamp;
danilchap34877ee2016-02-01 08:25:04 -08003248 const bool only_padding =
3249 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003250
danilchap32cd2c42016-08-01 06:58:34 -07003251 EXPECT_TRUE(ssrc_is_rtx_.find(ssrc) != ssrc_is_rtx_.end())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003252 << "Received SSRC that wasn't configured: " << ssrc;
3253
danilchap5c35cf92016-02-03 14:14:49 -08003254 static const int64_t kMaxSequenceNumberGap = 100;
3255 std::list<int64_t>* seq_numbers = &last_observed_seq_numbers_[ssrc];
3256 if (seq_numbers->empty()) {
3257 seq_numbers->push_back(sequence_number);
3258 } else {
3259 // We shouldn't get replays of previous sequence numbers.
3260 for (int64_t observed : *seq_numbers) {
3261 EXPECT_NE(observed, sequence_number)
3262 << "Received sequence number " << sequence_number
3263 << " for SSRC " << ssrc << " 2nd time.";
3264 }
3265 // Verify sequence numbers are reasonably close.
3266 int64_t latest_observed = seq_numbers->back();
3267 int64_t sequence_number_gap = sequence_number - latest_observed;
3268 EXPECT_LE(std::abs(sequence_number_gap), kMaxSequenceNumberGap)
3269 << "Gap in sequence numbers (" << latest_observed << " -> "
3270 << sequence_number << ") too large for SSRC: " << ssrc << ".";
3271 seq_numbers->push_back(sequence_number);
3272 if (seq_numbers->size() >= kMaxSequenceNumberGap) {
3273 seq_numbers->pop_front();
3274 }
3275 }
3276
danilchap32cd2c42016-08-01 06:58:34 -07003277 if (!ssrc_is_rtx_[ssrc]) {
3278 rtc::CritScope lock(&crit_);
3279 ValidateTimestampGap(ssrc, timestamp, only_padding);
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003280
danilchap32cd2c42016-08-01 06:58:34 -07003281 // Wait for media packets on all ssrcs.
3282 if (!ssrc_observed_[ssrc] && !only_padding) {
3283 ssrc_observed_[ssrc] = true;
3284 if (--ssrcs_to_observe_ == 0)
3285 observation_complete_.Set();
3286 }
danilchap34877ee2016-02-01 08:25:04 -08003287 }
3288
danilchapf4b9c772016-01-28 06:14:24 -08003289 return SEND_PACKET;
3290 }
3291
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003292 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
3293 test::RtcpPacketParser rtcp_parser;
3294 rtcp_parser.Parse(packet, length);
3295 if (rtcp_parser.sender_report()->num_packets() > 0) {
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02003296 uint32_t ssrc = rtcp_parser.sender_report()->sender_ssrc();
3297 uint32_t rtcp_timestamp = rtcp_parser.sender_report()->rtp_timestamp();
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003298
3299 rtc::CritScope lock(&crit_);
3300 ValidateTimestampGap(ssrc, rtcp_timestamp, false);
3301 }
3302 return SEND_PACKET;
3303 }
3304
danilchap5c35cf92016-02-03 14:14:49 -08003305 SequenceNumberUnwrapper seq_numbers_unwrapper_;
3306 std::map<uint32_t, std::list<int64_t>> last_observed_seq_numbers_;
danilchap34877ee2016-02-01 08:25:04 -08003307 std::map<uint32_t, uint32_t> last_observed_timestamp_;
danilchap32cd2c42016-08-01 06:58:34 -07003308 std::map<uint32_t, bool> ssrc_is_rtx_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003309
Peter Boströmf2f82832015-05-01 13:00:41 +02003310 rtc::CriticalSection crit_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003311 size_t ssrcs_to_observe_ GUARDED_BY(crit_);
danilchap34877ee2016-02-01 08:25:04 -08003312 std::map<uint32_t, bool> ssrc_observed_ GUARDED_BY(crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003313 } observer(use_rtx);
3314
skvlad11a9cbf2016-10-07 11:53:05 -07003315 Call::Config config(&event_log_);
3316 CreateCalls(config, config);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003317
stefanf116bd02015-10-27 08:29:42 -07003318 test::PacketTransport send_transport(sender_call_.get(), &observer,
3319 test::PacketTransport::kSender,
3320 FakeNetworkPipe::Config());
3321 test::PacketTransport receive_transport(nullptr, &observer,
3322 test::PacketTransport::kReceiver,
3323 FakeNetworkPipe::Config());
3324 send_transport.SetReceiver(receiver_call_->Receiver());
3325 receive_transport.SetReceiver(sender_call_->Receiver());
3326
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003327 CreateSendConfig(kNumSsrcs, 0, &send_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003328
3329 if (use_rtx) {
3330 for (size_t i = 0; i < kNumSsrcs; ++i) {
stefanff483612015-12-21 03:14:00 -08003331 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003332 }
stefanff483612015-12-21 03:14:00 -08003333 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003334 }
3335
perkjfa10b552016-10-02 23:45:26 -07003336 video_encoder_config_.video_stream_factory =
3337 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003338 // Use the same total bitrates when sending a single stream to avoid lowering
3339 // the bitrate estimate and requiring a subsequent rampup.
perkj26091b12016-09-01 01:17:40 -07003340 VideoEncoderConfig one_stream = video_encoder_config_.Copy();
perkjfa10b552016-10-02 23:45:26 -07003341 // one_stream.streams.resize(1);
3342 one_stream.number_of_streams = 1;
stefanf116bd02015-10-27 08:29:42 -07003343 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003344
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003345 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003346 CreateFrameGeneratorCapturer(30, 1280, 720);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003347
3348 Start();
Peter Boström5811a392015-12-10 13:02:50 +01003349 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003350 << "Timed out waiting for all SSRCs to send packets.";
3351
3352 // Test stream resetting more than once to make sure that the state doesn't
3353 // get set once (this could be due to using std::map::insert for instance).
3354 for (size_t i = 0; i < 3; ++i) {
3355 frame_generator_capturer_->Stop();
stefanff483612015-12-21 03:14:00 -08003356 sender_call_->DestroyVideoSendStream(video_send_stream_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003357
3358 // Re-create VideoSendStream with only one stream.
perkj26091b12016-09-01 01:17:40 -07003359 video_send_stream_ = sender_call_->CreateVideoSendStream(
3360 video_send_config_.Copy(), one_stream.Copy());
stefanff483612015-12-21 03:14:00 -08003361 video_send_stream_->Start();
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003362 if (provoke_rtcpsr_before_rtp) {
3363 // Rapid Resync Request forces sending RTCP Sender Report back.
3364 // Using this request speeds up this test because then there is no need
3365 // to wait for a second for periodic Sender Report.
3366 rtcp::RapidResyncRequest force_send_sr_back_request;
3367 rtc::Buffer packet = force_send_sr_back_request.Build();
3368 static_cast<webrtc::test::DirectTransport&>(receive_transport)
3369 .SendRtcp(packet.data(), packet.size());
3370 }
perkjfa10b552016-10-02 23:45:26 -07003371 CreateFrameGeneratorCapturer(30, 1280, 720);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003372 frame_generator_capturer_->Start();
3373
3374 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003375 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003376
3377 // Reconfigure back to use all streams.
perkj26091b12016-09-01 01:17:40 -07003378 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003379 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003380 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003381 << "Timed out waiting for all SSRCs to send packets.";
3382
3383 // Reconfigure down to one stream.
perkj26091b12016-09-01 01:17:40 -07003384 video_send_stream_->ReconfigureVideoEncoder(one_stream.Copy());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003385 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003386 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003387
3388 // Reconfigure back to use all streams.
perkj26091b12016-09-01 01:17:40 -07003389 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003390 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003391 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003392 << "Timed out waiting for all SSRCs to send packets.";
3393 }
3394
stefanf116bd02015-10-27 08:29:42 -07003395 send_transport.StopSending();
3396 receive_transport.StopSending();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003397
3398 Stop();
3399 DestroyStreams();
3400}
3401
Peter Boströmfc968a22016-02-19 16:14:37 +01003402TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpState) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003403 TestRtpStatePreservation(false, false);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003404}
3405
danilchap32cd2c42016-08-01 06:58:34 -07003406TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpStatesWithRtx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003407 TestRtpStatePreservation(true, false);
3408}
3409
danilchap32cd2c42016-08-01 06:58:34 -07003410TEST_F(EndToEndTest, RestartingSendStreamKeepsRtpAndRtcpTimestampsSynced) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003411 TestRtpStatePreservation(true, true);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003412}
3413
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003414TEST_F(EndToEndTest, RespectsNetworkState) {
3415 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
3416 // down blocks until no more packets will be sent.
3417
3418 // Pacer will send from its packet list and then send required padding before
3419 // checking paused_ again. This should be enough for one round of pacing,
3420 // otherwise increase.
3421 static const int kNumAcceptedDowntimeRtp = 5;
3422 // A single RTCP may be in the pipeline.
3423 static const int kNumAcceptedDowntimeRtcp = 1;
3424 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
3425 public:
3426 NetworkStateTest()
3427 : EndToEndTest(kDefaultTimeoutMs),
3428 FakeEncoder(Clock::GetRealTimeClock()),
Peter Boström5811a392015-12-10 13:02:50 +01003429 encoded_frames_(false, false),
3430 packet_event_(false, false),
sprang867fb522015-08-03 04:38:41 -07003431 sender_call_(nullptr),
3432 receiver_call_(nullptr),
Jelena Marusiccd670222015-07-16 09:30:09 +02003433 sender_state_(kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003434 sender_rtp_(0),
3435 sender_rtcp_(0),
3436 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003437 down_frames_(0) {}
3438
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003439 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003440 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003441 ++sender_rtp_;
Peter Boström5811a392015-12-10 13:02:50 +01003442 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003443 return SEND_PACKET;
3444 }
3445
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003446 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003447 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003448 ++sender_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003449 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003450 return SEND_PACKET;
3451 }
3452
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003453 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003454 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
3455 return SEND_PACKET;
3456 }
3457
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003458 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003459 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003460 ++receiver_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003461 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003462 return SEND_PACKET;
3463 }
3464
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003465 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003466 sender_call_ = sender_call;
3467 receiver_call_ = receiver_call;
3468 }
3469
stefanff483612015-12-21 03:14:00 -08003470 void ModifyVideoConfigs(
3471 VideoSendStream::Config* send_config,
3472 std::vector<VideoReceiveStream::Config>* receive_configs,
3473 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003474 send_config->encoder_settings.encoder = this;
3475 }
3476
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003477 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003478 EXPECT_TRUE(encoded_frames_.Wait(kDefaultTimeoutMs))
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003479 << "No frames received by the encoder.";
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003480 // Wait for packets from both sender/receiver.
3481 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003482
skvlad7a43d252016-03-22 15:32:27 -07003483 // Sender-side network down for audio; there should be no effect on video
3484 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3485 WaitForPacketsOrSilence(false, false);
3486
3487 // Receiver-side network down for audio; no change expected
3488 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3489 WaitForPacketsOrSilence(false, false);
3490
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003491 // Sender-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003492 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003493 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003494 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003495 // After network goes down we shouldn't be encoding more frames.
Jelena Marusiccd670222015-07-16 09:30:09 +02003496 sender_state_ = kNetworkDown;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003497 }
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003498 // Wait for receiver-packets and no sender packets.
3499 WaitForPacketsOrSilence(true, false);
3500
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003501 // Receiver-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003502 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
3503 WaitForPacketsOrSilence(true, true);
3504
3505 // Network up for audio for both sides; video is still not expected to
3506 // start
3507 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
3508 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003509 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003510
3511 // Network back up again for both.
3512 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003513 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003514 // It's OK to encode frames again, as we're about to bring up the
3515 // network.
Jelena Marusiccd670222015-07-16 09:30:09 +02003516 sender_state_ = kNetworkUp;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003517 }
skvlad7a43d252016-03-22 15:32:27 -07003518 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
3519 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003520 WaitForPacketsOrSilence(false, false);
skvlad7a43d252016-03-22 15:32:27 -07003521
3522 // TODO(skvlad): add tests to verify that the audio streams are stopped
3523 // when the network goes down for audio once the workaround in
3524 // paced_sender.cc is removed.
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003525 }
3526
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07003527 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003528 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07003529 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003530 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003531 rtc::CritScope lock(&test_crit_);
Jelena Marusiccd670222015-07-16 09:30:09 +02003532 if (sender_state_ == kNetworkDown) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003533 ++down_frames_;
3534 EXPECT_LE(down_frames_, 1)
3535 << "Encoding more than one frame while network is down.";
3536 if (down_frames_ > 1)
Peter Boström5811a392015-12-10 13:02:50 +01003537 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003538 } else {
Peter Boström5811a392015-12-10 13:02:50 +01003539 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003540 }
3541 }
3542 return test::FakeEncoder::Encode(
3543 input_image, codec_specific_info, frame_types);
3544 }
3545
3546 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003547 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
3548 int64_t initial_time_ms = clock_->TimeInMilliseconds();
3549 int initial_sender_rtp;
3550 int initial_sender_rtcp;
3551 int initial_receiver_rtcp;
3552 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003553 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003554 initial_sender_rtp = sender_rtp_;
3555 initial_sender_rtcp = sender_rtcp_;
3556 initial_receiver_rtcp = receiver_rtcp_;
3557 }
3558 bool sender_done = false;
3559 bool receiver_done = false;
mflodmand1590b22015-12-09 07:07:59 -08003560 while (!sender_done || !receiver_done) {
Peter Boström5811a392015-12-10 13:02:50 +01003561 packet_event_.Wait(kSilenceTimeoutMs);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003562 int64_t time_now_ms = clock_->TimeInMilliseconds();
Peter Boströmf2f82832015-05-01 13:00:41 +02003563 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003564 if (sender_down) {
3565 ASSERT_LE(sender_rtp_ - initial_sender_rtp, kNumAcceptedDowntimeRtp)
3566 << "RTP sent during sender-side downtime.";
3567 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
3568 kNumAcceptedDowntimeRtcp)
3569 << "RTCP sent during sender-side downtime.";
3570 if (time_now_ms - initial_time_ms >=
3571 static_cast<int64_t>(kSilenceTimeoutMs)) {
3572 sender_done = true;
3573 }
3574 } else {
skvlad7a43d252016-03-22 15:32:27 -07003575 if (sender_rtp_ > initial_sender_rtp + kNumAcceptedDowntimeRtp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003576 sender_done = true;
3577 }
3578 if (receiver_down) {
3579 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
3580 kNumAcceptedDowntimeRtcp)
3581 << "RTCP sent during receiver-side downtime.";
3582 if (time_now_ms - initial_time_ms >=
3583 static_cast<int64_t>(kSilenceTimeoutMs)) {
3584 receiver_done = true;
3585 }
3586 } else {
skvlad7a43d252016-03-22 15:32:27 -07003587 if (receiver_rtcp_ > initial_receiver_rtcp + kNumAcceptedDowntimeRtcp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003588 receiver_done = true;
3589 }
3590 }
3591 }
3592
Peter Boströmf2f82832015-05-01 13:00:41 +02003593 rtc::CriticalSection test_crit_;
Peter Boström5811a392015-12-10 13:02:50 +01003594 rtc::Event encoded_frames_;
3595 rtc::Event packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003596 Call* sender_call_;
3597 Call* receiver_call_;
Jelena Marusiccd670222015-07-16 09:30:09 +02003598 NetworkState sender_state_ GUARDED_BY(test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003599 int sender_rtp_ GUARDED_BY(test_crit_);
3600 int sender_rtcp_ GUARDED_BY(test_crit_);
3601 int receiver_rtcp_ GUARDED_BY(test_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003602 int down_frames_ GUARDED_BY(test_crit_);
3603 } test;
3604
stefane74eef12016-01-08 06:47:13 -08003605 RunBaseTest(&test);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003606}
3607
danilchapa6a70072016-06-01 11:20:43 -07003608TEST_F(EndToEndTest, CallReportsRttForSender) {
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003609 static const int kSendDelayMs = 30;
3610 static const int kReceiveDelayMs = 70;
skvlad11a9cbf2016-10-07 11:53:05 -07003611 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -07003612
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003613 FakeNetworkPipe::Config config;
3614 config.queue_delay_ms = kSendDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003615 test::DirectTransport sender_transport(config, sender_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003616 config.queue_delay_ms = kReceiveDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003617 test::DirectTransport receiver_transport(config, receiver_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003618 sender_transport.SetReceiver(receiver_call_->Receiver());
3619 receiver_transport.SetReceiver(sender_call_->Receiver());
3620
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003621 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07003622 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003623
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003624 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003625 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
3626 kDefaultHeight);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003627 Start();
3628
3629 int64_t start_time_ms = clock_->TimeInMilliseconds();
3630 while (true) {
3631 Call::Stats stats = sender_call_->GetStats();
3632 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
3633 clock_->TimeInMilliseconds())
3634 << "No RTT stats before timeout!";
3635 if (stats.rtt_ms != -1) {
Danil Chapovalov10e8f8e2016-09-07 15:05:29 +02003636 // To avoid failures caused by rounding or minor ntp clock adjustments,
3637 // relax expectation by 1ms.
3638 constexpr int kAllowedErrorMs = 1;
3639 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs - kAllowedErrorMs);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003640 break;
3641 }
3642 SleepMs(10);
3643 }
3644
3645 Stop();
3646 DestroyStreams();
3647}
3648
skvlad7a43d252016-03-22 15:32:27 -07003649void EndToEndTest::VerifyNewVideoSendStreamsRespectNetworkState(
3650 MediaType network_to_bring_down,
3651 VideoEncoder* encoder,
3652 Transport* transport) {
skvlad11a9cbf2016-10-07 11:53:05 -07003653 CreateSenderCall(Call::Config(&event_log_));
skvlad7a43d252016-03-22 15:32:27 -07003654 sender_call_->SignalChannelNetworkState(network_to_bring_down, kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003655
skvlad7a43d252016-03-22 15:32:27 -07003656 CreateSendConfig(1, 0, transport);
3657 video_send_config_.encoder_settings.encoder = encoder;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003658 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003659 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
3660 kDefaultHeight);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003661
3662 Start();
3663 SleepMs(kSilenceTimeoutMs);
3664 Stop();
3665
3666 DestroyStreams();
3667}
3668
skvlad7a43d252016-03-22 15:32:27 -07003669void EndToEndTest::VerifyNewVideoReceiveStreamsRespectNetworkState(
3670 MediaType network_to_bring_down,
3671 Transport* transport) {
skvlad11a9cbf2016-10-07 11:53:05 -07003672 Call::Config config(&event_log_);
3673 CreateCalls(config, config);
skvlad7a43d252016-03-22 15:32:27 -07003674 receiver_call_->SignalChannelNetworkState(network_to_bring_down,
3675 kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003676
stefanf116bd02015-10-27 08:29:42 -07003677 test::DirectTransport sender_transport(sender_call_.get());
solenberg4fbae2b2015-08-28 04:07:10 -07003678 sender_transport.SetReceiver(receiver_call_->Receiver());
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003679 CreateSendConfig(1, 0, &sender_transport);
skvlad7a43d252016-03-22 15:32:27 -07003680 CreateMatchingReceiveConfigs(transport);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003681 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003682 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
3683 kDefaultHeight);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003684
3685 Start();
3686 SleepMs(kSilenceTimeoutMs);
3687 Stop();
3688
3689 sender_transport.StopSending();
3690
3691 DestroyStreams();
3692}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00003693
skvlad7a43d252016-03-22 15:32:27 -07003694TEST_F(EndToEndTest, NewVideoSendStreamsRespectVideoNetworkDown) {
3695 class UnusedEncoder : public test::FakeEncoder {
3696 public:
3697 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
perkjfea93092016-05-14 00:58:48 -07003698
3699 int32_t InitEncode(const VideoCodec* config,
3700 int32_t number_of_cores,
3701 size_t max_payload_size) override {
3702 EXPECT_GT(config->startBitrate, 0u);
3703 return 0;
3704 }
skvlad7a43d252016-03-22 15:32:27 -07003705 int32_t Encode(const VideoFrame& input_image,
3706 const CodecSpecificInfo* codec_specific_info,
3707 const std::vector<FrameType>* frame_types) override {
3708 ADD_FAILURE() << "Unexpected frame encode.";
3709 return test::FakeEncoder::Encode(input_image, codec_specific_info,
3710 frame_types);
3711 }
3712 };
3713
3714 UnusedEncoder unused_encoder;
3715 UnusedTransport unused_transport;
3716 VerifyNewVideoSendStreamsRespectNetworkState(
3717 MediaType::VIDEO, &unused_encoder, &unused_transport);
3718}
3719
3720TEST_F(EndToEndTest, NewVideoSendStreamsIgnoreAudioNetworkDown) {
3721 class RequiredEncoder : public test::FakeEncoder {
3722 public:
3723 RequiredEncoder()
3724 : FakeEncoder(Clock::GetRealTimeClock()), encoded_frame_(false) {}
3725 ~RequiredEncoder() {
3726 if (!encoded_frame_) {
3727 ADD_FAILURE() << "Didn't encode an expected frame";
3728 }
3729 }
3730 int32_t Encode(const VideoFrame& input_image,
3731 const CodecSpecificInfo* codec_specific_info,
3732 const std::vector<FrameType>* frame_types) override {
3733 encoded_frame_ = true;
3734 return test::FakeEncoder::Encode(input_image, codec_specific_info,
3735 frame_types);
3736 }
3737
3738 private:
3739 bool encoded_frame_;
3740 };
3741
3742 RequiredTransport required_transport(true /*rtp*/, false /*rtcp*/);
3743 RequiredEncoder required_encoder;
3744 VerifyNewVideoSendStreamsRespectNetworkState(
3745 MediaType::AUDIO, &required_encoder, &required_transport);
3746}
3747
3748TEST_F(EndToEndTest, NewVideoReceiveStreamsRespectVideoNetworkDown) {
3749 UnusedTransport transport;
3750 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::VIDEO, &transport);
3751}
3752
3753TEST_F(EndToEndTest, NewVideoReceiveStreamsIgnoreAudioNetworkDown) {
3754 RequiredTransport transport(false /*rtp*/, true /*rtcp*/);
3755 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::AUDIO, &transport);
3756}
3757
Peter Boströmd7da1202015-06-05 14:09:38 +02003758void VerifyEmptyNackConfig(const NackConfig& config) {
3759 EXPECT_EQ(0, config.rtp_history_ms)
3760 << "Enabling NACK requires rtcp-fb: nack negotiation.";
3761}
3762
brandtrb5f2c3f2016-10-04 23:28:39 -07003763void VerifyEmptyUlpfecConfig(const UlpfecConfig& config) {
Peter Boströmd7da1202015-06-05 14:09:38 +02003764 EXPECT_EQ(-1, config.ulpfec_payload_type)
brandtr535830e2016-10-31 03:45:58 -07003765 << "Enabling ULPFEC requires rtpmap: ulpfec negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02003766 EXPECT_EQ(-1, config.red_payload_type)
brandtr535830e2016-10-31 03:45:58 -07003767 << "Enabling ULPFEC requires rtpmap: red negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02003768 EXPECT_EQ(-1, config.red_rtx_payload_type)
brandtr535830e2016-10-31 03:45:58 -07003769 << "Enabling RTX in ULPFEC requires rtpmap: rtx negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02003770}
3771
3772TEST_F(EndToEndTest, VerifyDefaultSendConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003773 VideoSendStream::Config default_send_config(nullptr);
Peter Boströmd7da1202015-06-05 14:09:38 +02003774 EXPECT_EQ(0, default_send_config.rtp.nack.rtp_history_ms)
3775 << "Enabling NACK require rtcp-fb: nack negotiation.";
3776 EXPECT_TRUE(default_send_config.rtp.rtx.ssrcs.empty())
3777 << "Enabling RTX requires rtpmap: rtx negotiation.";
3778 EXPECT_TRUE(default_send_config.rtp.extensions.empty())
3779 << "Enabling RTP extensions require negotiation.";
3780
3781 VerifyEmptyNackConfig(default_send_config.rtp.nack);
brandtrb5f2c3f2016-10-04 23:28:39 -07003782 VerifyEmptyUlpfecConfig(default_send_config.rtp.ulpfec);
Peter Boströmd7da1202015-06-05 14:09:38 +02003783}
3784
3785TEST_F(EndToEndTest, VerifyDefaultReceiveConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003786 VideoReceiveStream::Config default_receive_config(nullptr);
pbosda903ea2015-10-02 02:36:56 -07003787 EXPECT_EQ(RtcpMode::kCompound, default_receive_config.rtp.rtcp_mode)
Peter Boströmd7da1202015-06-05 14:09:38 +02003788 << "Reduced-size RTCP require rtcp-rsize to be negotiated.";
3789 EXPECT_FALSE(default_receive_config.rtp.remb)
3790 << "REMB require rtcp-fb: goog-remb to be negotiated.";
3791 EXPECT_FALSE(
3792 default_receive_config.rtp.rtcp_xr.receiver_reference_time_report)
3793 << "RTCP XR settings require rtcp-xr to be negotiated.";
3794 EXPECT_TRUE(default_receive_config.rtp.rtx.empty())
3795 << "Enabling RTX requires rtpmap: rtx negotiation.";
3796 EXPECT_TRUE(default_receive_config.rtp.extensions.empty())
3797 << "Enabling RTP extensions require negotiation.";
3798
3799 VerifyEmptyNackConfig(default_receive_config.rtp.nack);
brandtrb5f2c3f2016-10-04 23:28:39 -07003800 VerifyEmptyUlpfecConfig(default_receive_config.rtp.ulpfec);
Peter Boströmd7da1202015-06-05 14:09:38 +02003801}
3802
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003803TEST_F(EndToEndTest, TransportSeqNumOnAudioAndVideo) {
3804 static const int kExtensionId = 8;
3805 class TransportSequenceNumberTest : public test::EndToEndTest {
3806 public:
3807 TransportSequenceNumberTest()
3808 : EndToEndTest(kDefaultTimeoutMs),
3809 video_observed_(false),
3810 audio_observed_(false) {
3811 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
3812 kExtensionId);
3813 }
3814
3815 size_t GetNumVideoStreams() const override { return 1; }
3816 size_t GetNumAudioStreams() const override { return 1; }
3817
3818 void ModifyVideoConfigs(
3819 VideoSendStream::Config* send_config,
3820 std::vector<VideoReceiveStream::Config>* receive_configs,
3821 VideoEncoderConfig* encoder_config) override {
3822 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07003823 send_config->rtp.extensions.push_back(RtpExtension(
3824 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003825 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3826 }
3827
3828 void ModifyAudioConfigs(
3829 AudioSendStream::Config* send_config,
3830 std::vector<AudioReceiveStream::Config>* receive_configs) override {
3831 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07003832 send_config->rtp.extensions.push_back(RtpExtension(
3833 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003834 (*receive_configs)[0].rtp.extensions.clear();
3835 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3836 }
3837
3838 Action OnSendRtp(const uint8_t* packet, size_t length) override {
3839 RTPHeader header;
3840 EXPECT_TRUE(parser_->Parse(packet, length, &header));
3841 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
3842 // Unwrap packet id and verify uniqueness.
3843 int64_t packet_id =
3844 unwrapper_.Unwrap(header.extension.transportSequenceNumber);
3845 EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
3846
3847 if (header.ssrc == kVideoSendSsrcs[0])
3848 video_observed_ = true;
3849 if (header.ssrc == kAudioSendSsrc)
3850 audio_observed_ = true;
3851 if (audio_observed_ && video_observed_ &&
3852 received_packet_ids_.size() == 50) {
3853 size_t packet_id_range =
3854 *received_packet_ids_.rbegin() - *received_packet_ids_.begin() + 1;
3855 EXPECT_EQ(received_packet_ids_.size(), packet_id_range);
3856 observation_complete_.Set();
3857 }
3858 return SEND_PACKET;
3859 }
3860
3861 void PerformTest() override {
3862 EXPECT_TRUE(Wait()) << "Timed out while waiting for audio and video "
3863 "packets with transport sequence number.";
3864 }
3865
3866 private:
3867 bool video_observed_;
3868 bool audio_observed_;
3869 SequenceNumberUnwrapper unwrapper_;
3870 std::set<int64_t> received_packet_ids_;
3871 } test;
3872
stefane74eef12016-01-08 06:47:13 -08003873 RunBaseTest(&test);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003874}
palmkviste75f2042016-09-28 06:19:48 -07003875
3876class EndToEndLogTest : public EndToEndTest {
3877 void SetUp() { paths_.clear(); }
3878 void TearDown() {
3879 for (const auto& path : paths_) {
3880 rtc::RemoveFile(path);
3881 }
3882 }
3883
3884 public:
3885 int AddFile() {
3886 paths_.push_back(test::TempFilename(test::OutputPath(), "test_file"));
3887 return static_cast<int>(paths_.size()) - 1;
3888 }
3889
3890 rtc::PlatformFile OpenFile(int idx) {
3891 return rtc::OpenPlatformFile(paths_[idx]);
3892 }
3893
3894 void LogSend(bool open) {
3895 if (open) {
3896 video_send_stream_->EnableEncodedFrameRecording(
3897 std::vector<rtc::PlatformFile>(1, OpenFile(AddFile())), 0);
3898 } else {
3899 video_send_stream_->DisableEncodedFrameRecording();
3900 }
3901 }
3902 void LogReceive(bool open) {
3903 if (open) {
3904 video_receive_streams_[0]->EnableEncodedFrameRecording(
3905 OpenFile(AddFile()), 0);
3906 } else {
3907 video_receive_streams_[0]->DisableEncodedFrameRecording();
3908 }
3909 }
3910
3911 std::vector<std::string> paths_;
3912};
3913
3914TEST_F(EndToEndLogTest, LogsEncodedFramesWhenRequested) {
3915 static const int kNumFramesToRecord = 10;
3916 class LogEncodingObserver : public test::EndToEndTest,
3917 public EncodedFrameObserver {
3918 public:
3919 explicit LogEncodingObserver(EndToEndLogTest* fixture)
3920 : EndToEndTest(kDefaultTimeoutMs),
3921 fixture_(fixture),
3922 recorded_frames_(0) {}
3923
3924 void PerformTest() override {
3925 fixture_->LogSend(true);
3926 fixture_->LogReceive(true);
3927 ASSERT_TRUE(Wait()) << "Timed out while waiting for frame logging.";
3928 }
3929
3930 void ModifyVideoConfigs(
3931 VideoSendStream::Config* send_config,
3932 std::vector<VideoReceiveStream::Config>* receive_configs,
3933 VideoEncoderConfig* encoder_config) override {
3934 encoder_.reset(VideoEncoder::Create(VideoEncoder::kVp8));
3935 decoder_.reset(VP8Decoder::Create());
3936
3937 send_config->post_encode_callback = this;
3938 send_config->encoder_settings.payload_name = "VP8";
3939 send_config->encoder_settings.encoder = encoder_.get();
3940
3941 (*receive_configs)[0].decoders.resize(1);
3942 (*receive_configs)[0].decoders[0].payload_type =
3943 send_config->encoder_settings.payload_type;
3944 (*receive_configs)[0].decoders[0].payload_name =
3945 send_config->encoder_settings.payload_name;
3946 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
3947 }
3948
3949 void EncodedFrameCallback(const EncodedFrame& encoded_frame) override {
3950 rtc::CritScope lock(&crit_);
3951 if (recorded_frames_++ > kNumFramesToRecord) {
3952 fixture_->LogSend(false);
3953 fixture_->LogReceive(false);
3954 rtc::File send_file(fixture_->OpenFile(0));
3955 rtc::File receive_file(fixture_->OpenFile(1));
3956 uint8_t out[100];
3957 // If logging has worked correctly neither file should be empty, i.e.
3958 // we should be able to read something from them.
3959 EXPECT_LT(0u, send_file.Read(out, 100));
3960 EXPECT_LT(0u, receive_file.Read(out, 100));
3961 observation_complete_.Set();
3962 }
3963 }
3964
3965 private:
3966 EndToEndLogTest* const fixture_;
3967 std::unique_ptr<VideoEncoder> encoder_;
3968 std::unique_ptr<VideoDecoder> decoder_;
3969 rtc::CriticalSection crit_;
3970 int recorded_frames_ GUARDED_BY(crit_);
3971 } test(this);
3972
3973 RunBaseTest(&test);
3974}
3975
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003976} // namespace webrtc