blob: 52ff43e11d37a353482d60bc3d1600c4111d30c2 [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"
pbosa96b60b2016-04-18 21:12:48 -070024#include "webrtc/common_video/include/frame_callback.h"
skvlad11a9cbf2016-10-07 11:53:05 -070025#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
sakal55d932b2016-09-30 06:19:08 -070026#include "webrtc/media/base/fakevideorenderer.h"
danilchap5c35cf92016-02-03 14:14:49 -080027#include "webrtc/modules/include/module_common_types.h"
stefan32f81542016-01-20 07:13:58 -080028#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
sprang861c55e2015-10-16 10:01:21 -070029#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
Erik Språng737336d2016-07-29 12:59:36 +020030#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h"
Danil Chapovalov70ffead2016-07-20 15:26:59 +020031#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.h"
sprangcd349d92016-07-13 09:11:28 -070032#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
hbosbab934b2016-01-27 01:36:03 -080033#include "webrtc/modules/video_coding/codecs/h264/include/h264.h"
marpan@webrtc.org5b883172014-11-01 06:10:48 +000034#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
35#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010036#include "webrtc/modules/video_coding/include/video_coding_defines.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010037#include "webrtc/system_wrappers/include/metrics.h"
asapersson01d70a32016-05-20 06:29:46 -070038#include "webrtc/system_wrappers/include/metrics_default.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010039#include "webrtc/system_wrappers/include/sleep.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000040#include "webrtc/test/call_test.h"
41#include "webrtc/test/direct_transport.h"
42#include "webrtc/test/encoder_settings.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000043#include "webrtc/test/fake_decoder.h"
44#include "webrtc/test/fake_encoder.h"
45#include "webrtc/test/frame_generator.h"
46#include "webrtc/test/frame_generator_capturer.h"
kwibergac9f8762016-09-30 22:29:43 -070047#include "webrtc/test/gtest.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000048#include "webrtc/test/null_transport.h"
asapersson@webrtc.org37c05592015-01-28 13:58:27 +000049#include "webrtc/test/rtcp_packet_parser.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000050#include "webrtc/test/rtp_rtcp_observer.h"
51#include "webrtc/test/testsupport/fileutils.h"
52#include "webrtc/test/testsupport/perf_test.h"
charujainbf6a45b2016-11-03 04:21:42 -070053#include "webrtc/video/transport_adapter.h"
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +000054#include "webrtc/video_encoder.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000055
56namespace webrtc {
57
Peter Boström5811a392015-12-10 13:02:50 +010058static const int kSilenceTimeoutMs = 2000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000059
60class EndToEndTest : public test::CallTest {
61 public:
62 EndToEndTest() {}
63
64 virtual ~EndToEndTest() {
stefanff483612015-12-21 03:14:00 -080065 EXPECT_EQ(nullptr, video_send_stream_);
66 EXPECT_TRUE(video_receive_streams_.empty());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000067 }
68
69 protected:
pbos2d566682015-09-28 09:59:31 -070070 class UnusedTransport : public Transport {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000071 private:
stefan1d8a5062015-10-02 03:39:33 -070072 bool SendRtp(const uint8_t* packet,
73 size_t length,
74 const PacketOptions& options) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000075 ADD_FAILURE() << "Unexpected RTP sent.";
76 return false;
77 }
78
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000079 bool SendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000080 ADD_FAILURE() << "Unexpected RTCP sent.";
81 return false;
82 }
83 };
84
skvlad7a43d252016-03-22 15:32:27 -070085 class RequiredTransport : public Transport {
86 public:
87 RequiredTransport(bool rtp_required, bool rtcp_required)
88 : need_rtp_(rtp_required), need_rtcp_(rtcp_required) {}
89 ~RequiredTransport() {
90 if (need_rtp_) {
91 ADD_FAILURE() << "Expected RTP packet not sent.";
92 }
93 if (need_rtcp_) {
94 ADD_FAILURE() << "Expected RTCP packet not sent.";
95 }
96 }
97
98 private:
99 bool SendRtp(const uint8_t* packet,
100 size_t length,
101 const PacketOptions& options) override {
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700102 rtc::CritScope lock(&crit_);
skvlad7a43d252016-03-22 15:32:27 -0700103 need_rtp_ = false;
104 return true;
105 }
106
107 bool SendRtcp(const uint8_t* packet, size_t length) override {
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700108 rtc::CritScope lock(&crit_);
skvlad7a43d252016-03-22 15:32:27 -0700109 need_rtcp_ = false;
110 return true;
111 }
112 bool need_rtp_;
113 bool need_rtcp_;
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700114 rtc::CriticalSection crit_;
skvlad7a43d252016-03-22 15:32:27 -0700115 };
116
Peter Boström39593972016-02-15 11:27:15 +0100117 void DecodesRetransmittedFrame(bool enable_rtx, bool enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000118 void ReceivesPliAndRecovers(int rtp_history_ms);
pbosda903ea2015-10-02 02:36:56 -0700119 void RespectsRtcpMode(RtcpMode rtcp_mode);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000120 void TestXrReceiverReferenceTimeReport(bool enable_rrtr);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000121 void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200122 void TestRtpStatePreservation(bool use_rtx, bool provoke_rtcpsr_before_rtp);
sprangb4a1ae52015-12-03 08:10:08 -0800123 void VerifyHistogramStats(bool use_rtx, bool use_red, bool screenshare);
skvlad7a43d252016-03-22 15:32:27 -0700124 void VerifyNewVideoSendStreamsRespectNetworkState(
125 MediaType network_to_bring_down,
126 VideoEncoder* encoder,
127 Transport* transport);
128 void VerifyNewVideoReceiveStreamsRespectNetworkState(
129 MediaType network_to_bring_down,
130 Transport* transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000131};
132
133TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
skvlad11a9cbf2016-10-07 11:53:05 -0700134 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000135
solenberg4fbae2b2015-08-28 04:07:10 -0700136 test::NullTransport transport;
brandtr841de6a2016-11-15 07:10:52 -0800137 CreateSendConfig(1, 0, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700138 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000139
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100140 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000141
stefanff483612015-12-21 03:14:00 -0800142 video_receive_streams_[0]->Start();
143 video_receive_streams_[0]->Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000144
145 DestroyStreams();
146}
147
148TEST_F(EndToEndTest, ReceiverCanBeStoppedTwice) {
skvlad11a9cbf2016-10-07 11:53:05 -0700149 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000150
solenberg4fbae2b2015-08-28 04:07:10 -0700151 test::NullTransport transport;
brandtr841de6a2016-11-15 07:10:52 -0800152 CreateSendConfig(1, 0, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700153 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000154
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100155 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000156
stefanff483612015-12-21 03:14:00 -0800157 video_receive_streams_[0]->Stop();
158 video_receive_streams_[0]->Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000159
160 DestroyStreams();
161}
162
sprang113bdca2016-10-11 03:10:10 -0700163TEST_F(EndToEndTest, ReceiverCanBeStoppedAndRestarted) {
164 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
165
166 test::NullTransport transport;
brandtr841de6a2016-11-15 07:10:52 -0800167 CreateSendConfig(1, 0, 0, &transport);
sprang113bdca2016-10-11 03:10:10 -0700168 CreateMatchingReceiveConfigs(&transport);
169
170 CreateVideoStreams();
171
172 video_receive_streams_[0]->Stop();
173 video_receive_streams_[0]->Start();
174 video_receive_streams_[0]->Stop();
175
176 DestroyStreams();
177}
178
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000179TEST_F(EndToEndTest, RendersSingleDelayedFrame) {
180 static const int kWidth = 320;
181 static const int kHeight = 240;
182 // This constant is chosen to be higher than the timeout in the video_render
183 // module. This makes sure that frames aren't dropped if there are no other
184 // frames in the queue.
185 static const int kDelayRenderCallbackMs = 1000;
186
nisse7ade7b32016-03-23 04:48:10 -0700187 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000188 public:
Peter Boström5811a392015-12-10 13:02:50 +0100189 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000190
nisseeb83a1a2016-03-21 01:27:56 -0700191 void OnFrame(const VideoFrame& video_frame) override { event_.Set(); }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000192
Peter Boström5811a392015-12-10 13:02:50 +0100193 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000194
Peter Boström5811a392015-12-10 13:02:50 +0100195 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000196 } renderer;
197
198 class TestFrameCallback : public I420FrameCallback {
199 public:
Peter Boström5811a392015-12-10 13:02:50 +0100200 TestFrameCallback() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000201
Peter Boström5811a392015-12-10 13:02:50 +0100202 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000203
204 private:
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700205 void FrameCallback(VideoFrame* frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000206 SleepMs(kDelayRenderCallbackMs);
Peter Boström5811a392015-12-10 13:02:50 +0100207 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000208 }
209
Peter Boström5811a392015-12-10 13:02:50 +0100210 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000211 };
212
skvlad11a9cbf2016-10-07 11:53:05 -0700213 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -0700214
stefanf116bd02015-10-27 08:29:42 -0700215 test::DirectTransport sender_transport(sender_call_.get());
216 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000217 sender_transport.SetReceiver(receiver_call_->Receiver());
218 receiver_transport.SetReceiver(sender_call_->Receiver());
219
brandtr841de6a2016-11-15 07:10:52 -0800220 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700221 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000222
223 TestFrameCallback pre_render_callback;
stefanff483612015-12-21 03:14:00 -0800224 video_receive_configs_[0].pre_render_callback = &pre_render_callback;
225 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000226
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100227 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000228 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000229
230 // Create frames that are smaller than the send width/height, this is done to
231 // check that the callbacks are done after processing video.
kwiberg27f982b2016-03-01 11:52:33 -0800232 std::unique_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000233 test::FrameGenerator::CreateChromaGenerator(kWidth, kHeight));
perkja49cbd32016-09-16 07:53:41 -0700234 test::FrameForwarder frame_forwarder;
perkj803d97f2016-11-01 11:45:46 -0700235 video_send_stream_->SetSource(
236 &frame_forwarder, VideoSendStream::DegradationPreference::kBalanced);
perkja49cbd32016-09-16 07:53:41 -0700237
238 frame_forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
Peter Boström5811a392015-12-10 13:02:50 +0100239 EXPECT_TRUE(pre_render_callback.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000240 << "Timed out while waiting for pre-render callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100241 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000242 << "Timed out while waiting for the frame to render.";
243
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000244 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000245
246 sender_transport.StopSending();
247 receiver_transport.StopSending();
248
249 DestroyStreams();
250}
251
252TEST_F(EndToEndTest, TransmitsFirstFrame) {
nisse7ade7b32016-03-23 04:48:10 -0700253 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000254 public:
Peter Boström5811a392015-12-10 13:02:50 +0100255 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000256
nisseeb83a1a2016-03-21 01:27:56 -0700257 void OnFrame(const VideoFrame& video_frame) override { event_.Set(); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000258
Peter Boström5811a392015-12-10 13:02:50 +0100259 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000260
Peter Boström5811a392015-12-10 13:02:50 +0100261 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000262 } renderer;
263
skvlad11a9cbf2016-10-07 11:53:05 -0700264 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -0700265
stefanf116bd02015-10-27 08:29:42 -0700266 test::DirectTransport sender_transport(sender_call_.get());
267 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000268 sender_transport.SetReceiver(receiver_call_->Receiver());
269 receiver_transport.SetReceiver(sender_call_->Receiver());
270
brandtr841de6a2016-11-15 07:10:52 -0800271 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700272 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -0800273 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000274
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100275 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000276 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000277
kwiberg27f982b2016-03-01 11:52:33 -0800278 std::unique_ptr<test::FrameGenerator> frame_generator(
perkjfa10b552016-10-02 23:45:26 -0700279 test::FrameGenerator::CreateChromaGenerator(kDefaultWidth,
280 kDefaultHeight));
perkja49cbd32016-09-16 07:53:41 -0700281 test::FrameForwarder frame_forwarder;
perkj803d97f2016-11-01 11:45:46 -0700282 video_send_stream_->SetSource(
283 &frame_forwarder, VideoSendStream::DegradationPreference::kBalanced);
perkja49cbd32016-09-16 07:53:41 -0700284 frame_forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000285
Peter Boström5811a392015-12-10 13:02:50 +0100286 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000287 << "Timed out while waiting for the frame to render.";
288
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000289 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000290
291 sender_transport.StopSending();
292 receiver_transport.StopSending();
293
294 DestroyStreams();
295}
296
Perba7dc722016-04-19 15:01:23 +0200297class CodecObserver : public test::EndToEndTest,
nisse7ade7b32016-03-23 04:48:10 -0700298 public rtc::VideoSinkInterface<VideoFrame> {
Perba7dc722016-04-19 15:01:23 +0200299 public:
300 CodecObserver(int no_frames_to_wait_for,
301 VideoRotation rotation_to_test,
302 const std::string& payload_name,
303 webrtc::VideoEncoder* encoder,
304 webrtc::VideoDecoder* decoder)
305 : EndToEndTest(2 * webrtc::EndToEndTest::kDefaultTimeoutMs),
306 no_frames_to_wait_for_(no_frames_to_wait_for),
307 expected_rotation_(rotation_to_test),
308 payload_name_(payload_name),
309 encoder_(encoder),
310 decoder_(decoder),
311 frame_counter_(0) {}
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000312
Perba7dc722016-04-19 15:01:23 +0200313 void PerformTest() override {
314 EXPECT_TRUE(Wait())
315 << "Timed out while waiting for enough frames to be decoded.";
316 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000317
Perba7dc722016-04-19 15:01:23 +0200318 void ModifyVideoConfigs(
319 VideoSendStream::Config* send_config,
320 std::vector<VideoReceiveStream::Config>* receive_configs,
321 VideoEncoderConfig* encoder_config) override {
322 send_config->encoder_settings.encoder = encoder_.get();
323 send_config->encoder_settings.payload_name = payload_name_;
324 send_config->encoder_settings.payload_type = 126;
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000325
Perba7dc722016-04-19 15:01:23 +0200326 (*receive_configs)[0].renderer = this;
327 (*receive_configs)[0].decoders.resize(1);
328 (*receive_configs)[0].decoders[0].payload_type =
329 send_config->encoder_settings.payload_type;
330 (*receive_configs)[0].decoders[0].payload_name =
331 send_config->encoder_settings.payload_name;
332 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
333 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000334
Perba7dc722016-04-19 15:01:23 +0200335 void OnFrame(const VideoFrame& video_frame) override {
336 EXPECT_EQ(expected_rotation_, video_frame.rotation());
337 if (++frame_counter_ == no_frames_to_wait_for_)
338 observation_complete_.Set();
339 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000340
Perba7dc722016-04-19 15:01:23 +0200341 void OnFrameGeneratorCapturerCreated(
342 test::FrameGeneratorCapturer* frame_generator_capturer) override {
343 frame_generator_capturer->SetFakeRotation(expected_rotation_);
344 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000345
Perba7dc722016-04-19 15:01:23 +0200346 private:
347 int no_frames_to_wait_for_;
348 VideoRotation expected_rotation_;
349 std::string payload_name_;
350 std::unique_ptr<webrtc::VideoEncoder> encoder_;
351 std::unique_ptr<webrtc::VideoDecoder> decoder_;
352 int frame_counter_;
353};
354
355TEST_F(EndToEndTest, SendsAndReceivesVP8Rotation90) {
356 CodecObserver test(5, kVideoRotation_90, "VP8",
357 VideoEncoder::Create(VideoEncoder::kVp8),
358 VP8Decoder::Create());
359 RunBaseTest(&test);
360}
361
Peter Boström12996152016-05-14 02:03:18 +0200362#if !defined(RTC_DISABLE_VP9)
Perba7dc722016-04-19 15:01:23 +0200363TEST_F(EndToEndTest, SendsAndReceivesVP9) {
364 CodecObserver test(500, kVideoRotation_0, "VP9",
365 VideoEncoder::Create(VideoEncoder::kVp9),
366 VP9Decoder::Create());
367 RunBaseTest(&test);
368}
369
370TEST_F(EndToEndTest, SendsAndReceivesVP9VideoRotation90) {
371 CodecObserver test(5, kVideoRotation_90, "VP9",
372 VideoEncoder::Create(VideoEncoder::kVp9),
373 VP9Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800374 RunBaseTest(&test);
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000375}
Peter Boström12996152016-05-14 02:03:18 +0200376#endif // !defined(RTC_DISABLE_VP9)
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000377
brandtr445fb8f2016-11-14 04:11:23 -0800378#if defined(WEBRTC_USE_H264)
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000379TEST_F(EndToEndTest, SendsAndReceivesH264) {
Perba7dc722016-04-19 15:01:23 +0200380 CodecObserver test(500, kVideoRotation_0, "H264",
381 VideoEncoder::Create(VideoEncoder::kH264),
382 H264Decoder::Create());
383 RunBaseTest(&test);
384}
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000385
Perba7dc722016-04-19 15:01:23 +0200386TEST_F(EndToEndTest, SendsAndReceivesH264VideoRotation90) {
387 CodecObserver test(5, kVideoRotation_90, "H264",
388 VideoEncoder::Create(VideoEncoder::kH264),
389 H264Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800390 RunBaseTest(&test);
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000391}
brandtr445fb8f2016-11-14 04:11:23 -0800392#endif // defined(WEBRTC_USE_H264)
hbosbab934b2016-01-27 01:36:03 -0800393
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000394TEST_F(EndToEndTest, ReceiverUsesLocalSsrc) {
395 class SyncRtcpObserver : public test::EndToEndTest {
396 public:
397 SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {}
398
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000399 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
danilchap3dc929e2016-11-02 08:21:59 -0700400 test::RtcpPacketParser parser;
401 EXPECT_TRUE(parser.Parse(packet, length));
402 EXPECT_EQ(kReceiverLocalVideoSsrc, parser.sender_ssrc());
Peter Boström5811a392015-12-10 13:02:50 +0100403 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000404
405 return SEND_PACKET;
406 }
407
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000408 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100409 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000410 << "Timed out while waiting for a receiver RTCP packet to be sent.";
411 }
412 } test;
413
stefane74eef12016-01-08 06:47:13 -0800414 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000415}
416
417TEST_F(EndToEndTest, ReceivesAndRetransmitsNack) {
418 static const int kNumberOfNacksToObserve = 2;
419 static const int kLossBurstSize = 2;
420 static const int kPacketsBetweenLossBursts = 9;
421 class NackObserver : public test::EndToEndTest {
422 public:
423 NackObserver()
424 : EndToEndTest(kLongTimeoutMs),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000425 sent_rtp_packets_(0),
426 packets_left_to_drop_(0),
427 nacks_left_(kNumberOfNacksToObserve) {}
428
429 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000430 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700431 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000432 RTPHeader header;
Peter Boström03671cb2015-12-07 15:22:24 +0100433 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000434
435 // Never drop retransmitted packets.
436 if (dropped_packets_.find(header.sequenceNumber) !=
437 dropped_packets_.end()) {
438 retransmitted_packets_.insert(header.sequenceNumber);
Stefan Holmer586b19b2015-09-18 11:14:31 +0200439 if (nacks_left_ <= 0 &&
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000440 retransmitted_packets_.size() == dropped_packets_.size()) {
Peter Boström5811a392015-12-10 13:02:50 +0100441 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000442 }
443 return SEND_PACKET;
444 }
445
446 ++sent_rtp_packets_;
447
448 // Enough NACKs received, stop dropping packets.
Stefan Holmer586b19b2015-09-18 11:14:31 +0200449 if (nacks_left_ <= 0)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000450 return SEND_PACKET;
451
452 // Check if it's time for a new loss burst.
453 if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
454 packets_left_to_drop_ = kLossBurstSize;
455
Stefan Holmer01b48882015-05-05 10:21:24 +0200456 // Never drop padding packets as those won't be retransmitted.
457 if (packets_left_to_drop_ > 0 && header.paddingLength == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000458 --packets_left_to_drop_;
459 dropped_packets_.insert(header.sequenceNumber);
460 return DROP_PACKET;
461 }
462
463 return SEND_PACKET;
464 }
465
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000466 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700467 rtc::CritScope lock(&crit_);
danilchap3dc929e2016-11-02 08:21:59 -0700468 test::RtcpPacketParser parser;
469 EXPECT_TRUE(parser.Parse(packet, length));
470 nacks_left_ -= parser.nack()->num_packets();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000471 return SEND_PACKET;
472 }
473
stefanff483612015-12-21 03:14:00 -0800474 void ModifyVideoConfigs(
475 VideoSendStream::Config* send_config,
476 std::vector<VideoReceiveStream::Config>* receive_configs,
477 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000478 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000479 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000480 }
481
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000482 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100483 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000484 << "Timed out waiting for packets to be NACKed, retransmitted and "
485 "rendered.";
486 }
487
stefanf116bd02015-10-27 08:29:42 -0700488 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000489 std::set<uint16_t> dropped_packets_;
490 std::set<uint16_t> retransmitted_packets_;
491 uint64_t sent_rtp_packets_;
492 int packets_left_to_drop_;
stefanf116bd02015-10-27 08:29:42 -0700493 int nacks_left_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000494 } test;
495
stefane74eef12016-01-08 06:47:13 -0800496 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000497}
498
Erik Språng737336d2016-07-29 12:59:36 +0200499TEST_F(EndToEndTest, ReceivesNackAndRetransmitsAudio) {
500 class NackObserver : public test::EndToEndTest {
501 public:
502 NackObserver()
503 : EndToEndTest(kLongTimeoutMs),
504 local_ssrc_(0),
505 remote_ssrc_(0),
506 receive_transport_(nullptr) {}
507
508 private:
509 size_t GetNumVideoStreams() const override { return 0; }
510 size_t GetNumAudioStreams() const override { return 1; }
511
512 test::PacketTransport* CreateReceiveTransport() override {
513 test::PacketTransport* receive_transport = new test::PacketTransport(
514 nullptr, this, test::PacketTransport::kReceiver,
515 FakeNetworkPipe::Config());
516 receive_transport_ = receive_transport;
517 return receive_transport;
518 }
519
520 Action OnSendRtp(const uint8_t* packet, size_t length) override {
521 RTPHeader header;
522 EXPECT_TRUE(parser_->Parse(packet, length, &header));
523
524 if (!sequence_number_to_retransmit_) {
525 sequence_number_to_retransmit_ =
526 rtc::Optional<uint16_t>(header.sequenceNumber);
527
528 // Don't ask for retransmission straight away, may be deduped in pacer.
529 } else if (header.sequenceNumber == *sequence_number_to_retransmit_) {
530 observation_complete_.Set();
531 } else {
532 // Send a NACK as often as necessary until retransmission is received.
533 rtcp::Nack nack;
danilchap822a16f2016-09-27 09:27:47 -0700534 nack.SetSenderSsrc(local_ssrc_);
535 nack.SetMediaSsrc(remote_ssrc_);
Erik Språng737336d2016-07-29 12:59:36 +0200536 uint16_t nack_list[] = {*sequence_number_to_retransmit_};
danilchap822a16f2016-09-27 09:27:47 -0700537 nack.SetPacketIds(nack_list, 1);
Erik Språng737336d2016-07-29 12:59:36 +0200538 rtc::Buffer buffer = nack.Build();
539
540 EXPECT_TRUE(receive_transport_->SendRtcp(buffer.data(), buffer.size()));
541 }
542
543 return SEND_PACKET;
544 }
545
546 void ModifyAudioConfigs(
547 AudioSendStream::Config* send_config,
548 std::vector<AudioReceiveStream::Config>* receive_configs) override {
549 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
550 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
551 local_ssrc_ = (*receive_configs)[0].rtp.local_ssrc;
552 remote_ssrc_ = (*receive_configs)[0].rtp.remote_ssrc;
553 }
554
555 void PerformTest() override {
556 EXPECT_TRUE(Wait())
557 << "Timed out waiting for packets to be NACKed, retransmitted and "
558 "rendered.";
559 }
560
561 uint32_t local_ssrc_;
562 uint32_t remote_ssrc_;
563 Transport* receive_transport_;
564 rtc::Optional<uint16_t> sequence_number_to_retransmit_;
565 } test;
566
567 RunBaseTest(&test);
568}
569
brandtr535830e2016-10-31 03:45:58 -0700570TEST_F(EndToEndTest, CanReceiveUlpfec) {
571 class UlpfecRenderObserver : public test::EndToEndTest,
572 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000573 public:
brandtr535830e2016-10-31 03:45:58 -0700574 UlpfecRenderObserver()
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000575 : EndToEndTest(kDefaultTimeoutMs), state_(kFirstPacket) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000576
577 private:
stefanf116bd02015-10-27 08:29:42 -0700578 Action OnSendRtp(const uint8_t* packet, size_t length) override {
579 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000580 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000581 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000582
Stefan Holmer01b48882015-05-05 10:21:24 +0200583 int encapsulated_payload_type = -1;
584 if (header.payloadType == kRedPayloadType) {
585 encapsulated_payload_type =
586 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100587 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200588 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
589 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100590 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200591 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000592
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000593 if (protected_sequence_numbers_.count(header.sequenceNumber) != 0) {
594 // Retransmitted packet, should not count.
595 protected_sequence_numbers_.erase(header.sequenceNumber);
596 EXPECT_GT(protected_timestamps_.count(header.timestamp), 0u);
597 protected_timestamps_.erase(header.timestamp);
598 return SEND_PACKET;
599 }
600
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000601 switch (state_) {
602 case kFirstPacket:
brandtr535830e2016-10-31 03:45:58 -0700603 state_ = kDropEveryOtherPacketUntilUlpfec;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000604 break;
brandtr535830e2016-10-31 03:45:58 -0700605 case kDropEveryOtherPacketUntilUlpfec:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000606 if (encapsulated_payload_type == kUlpfecPayloadType) {
607 state_ = kDropNextMediaPacket;
608 return SEND_PACKET;
609 }
610 if (header.sequenceNumber % 2 == 0)
611 return DROP_PACKET;
612 break;
613 case kDropNextMediaPacket:
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100614 if (encapsulated_payload_type == kFakeVideoSendPayloadType) {
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000615 protected_sequence_numbers_.insert(header.sequenceNumber);
616 protected_timestamps_.insert(header.timestamp);
brandtr535830e2016-10-31 03:45:58 -0700617 state_ = kDropEveryOtherPacketUntilUlpfec;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000618 return DROP_PACKET;
619 }
620 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000621 }
622
623 return SEND_PACKET;
624 }
625
nisseeb83a1a2016-03-21 01:27:56 -0700626 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200627 rtc::CritScope lock(&crit_);
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000628 // Rendering frame with timestamp of packet that was dropped -> FEC
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000629 // protection worked.
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000630 if (protected_timestamps_.count(video_frame.timestamp()) != 0)
Peter Boström5811a392015-12-10 13:02:50 +0100631 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000632 }
633
634 enum {
635 kFirstPacket,
brandtr535830e2016-10-31 03:45:58 -0700636 kDropEveryOtherPacketUntilUlpfec,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000637 kDropNextMediaPacket,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000638 } state_;
639
stefanff483612015-12-21 03:14:00 -0800640 void ModifyVideoConfigs(
641 VideoSendStream::Config* send_config,
642 std::vector<VideoReceiveStream::Config>* receive_configs,
643 VideoEncoderConfig* encoder_config) override {
brandtr535830e2016-10-31 03:45:58 -0700644 // TODO(pbos): Run this test with combined NACK/ULPFEC enabled as well.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000645 // int rtp_history_ms = 1000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000646 // (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000647 // send_config->rtp.nack.rtp_history_ms = rtp_history_ms;
brandtrb5f2c3f2016-10-04 23:28:39 -0700648 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
649 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000650
brandtrb5f2c3f2016-10-04 23:28:39 -0700651 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
652 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000653 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000654 }
655
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000656 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100657 EXPECT_TRUE(Wait())
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000658 << "Timed out waiting for dropped frames frames to be rendered.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000659 }
660
stefanf116bd02015-10-27 08:29:42 -0700661 rtc::CriticalSection crit_;
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000662 std::set<uint32_t> protected_sequence_numbers_ GUARDED_BY(crit_);
663 std::set<uint32_t> protected_timestamps_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000664 } test;
665
stefane74eef12016-01-08 06:47:13 -0800666 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000667}
668
brandtr535830e2016-10-31 03:45:58 -0700669TEST_F(EndToEndTest, ReceivedUlpfecPacketsNotNacked) {
670 class UlpfecNackObserver : public test::EndToEndTest {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000671 public:
brandtr535830e2016-10-31 03:45:58 -0700672 UlpfecNackObserver()
stefanf116bd02015-10-27 08:29:42 -0700673 : EndToEndTest(kDefaultTimeoutMs),
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000674 state_(kFirstPacket),
brandtr535830e2016-10-31 03:45:58 -0700675 ulpfec_sequence_number_(0),
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000676 has_last_sequence_number_(false),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200677 last_sequence_number_(0),
678 encoder_(VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)),
679 decoder_(VP8Decoder::Create()) {}
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000680
681 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000682 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800683 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000684 RTPHeader header;
685 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000686
Stefan Holmer01b48882015-05-05 10:21:24 +0200687 int encapsulated_payload_type = -1;
688 if (header.payloadType == kRedPayloadType) {
689 encapsulated_payload_type =
690 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100691 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200692 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
693 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100694 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200695 }
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000696
697 if (has_last_sequence_number_ &&
698 !IsNewerSequenceNumber(header.sequenceNumber,
699 last_sequence_number_)) {
700 // Drop retransmitted packets.
701 return DROP_PACKET;
702 }
703 last_sequence_number_ = header.sequenceNumber;
704 has_last_sequence_number_ = true;
705
brandtr535830e2016-10-31 03:45:58 -0700706 bool ulpfec_packet = encapsulated_payload_type == kUlpfecPayloadType;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000707 switch (state_) {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000708 case kFirstPacket:
brandtr535830e2016-10-31 03:45:58 -0700709 state_ = kDropEveryOtherPacketUntilUlpfec;
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000710 break;
brandtr535830e2016-10-31 03:45:58 -0700711 case kDropEveryOtherPacketUntilUlpfec:
712 if (ulpfec_packet) {
713 state_ = kDropAllMediaPacketsUntilUlpfec;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000714 } else if (header.sequenceNumber % 2 == 0) {
715 return DROP_PACKET;
716 }
717 break;
brandtr535830e2016-10-31 03:45:58 -0700718 case kDropAllMediaPacketsUntilUlpfec:
719 if (!ulpfec_packet)
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000720 return DROP_PACKET;
brandtr535830e2016-10-31 03:45:58 -0700721 ulpfec_sequence_number_ = header.sequenceNumber;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200722 state_ = kDropOneMediaPacket;
723 break;
724 case kDropOneMediaPacket:
brandtr535830e2016-10-31 03:45:58 -0700725 if (ulpfec_packet)
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200726 return DROP_PACKET;
727 state_ = kPassOneMediaPacket;
728 return DROP_PACKET;
729 break;
730 case kPassOneMediaPacket:
brandtr535830e2016-10-31 03:45:58 -0700731 if (ulpfec_packet)
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200732 return DROP_PACKET;
733 // Pass one media packet after dropped packet after last FEC,
734 // otherwise receiver might never see a seq_no after
brandtr535830e2016-10-31 03:45:58 -0700735 // |ulpfec_sequence_number_|
736 state_ = kVerifyUlpfecPacketNotInNackList;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000737 break;
brandtr535830e2016-10-31 03:45:58 -0700738 case kVerifyUlpfecPacketNotInNackList:
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000739 // Continue to drop packets. Make sure no frame can be decoded.
brandtr535830e2016-10-31 03:45:58 -0700740 if (ulpfec_packet || header.sequenceNumber % 2 == 0)
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000741 return DROP_PACKET;
742 break;
743 }
744 return SEND_PACKET;
745 }
746
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000747 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800748 rtc::CritScope lock_(&crit_);
brandtr535830e2016-10-31 03:45:58 -0700749 if (state_ == kVerifyUlpfecPacketNotInNackList) {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000750 test::RtcpPacketParser rtcp_parser;
751 rtcp_parser.Parse(packet, length);
Danil Chapovalovba6f7be2016-09-02 18:29:10 +0200752 const std::vector<uint16_t>& nacks = rtcp_parser.nack()->packet_ids();
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200753 EXPECT_TRUE(std::find(nacks.begin(), nacks.end(),
brandtr535830e2016-10-31 03:45:58 -0700754 ulpfec_sequence_number_) == nacks.end())
755 << "Got nack for ULPFEC packet";
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000756 if (!nacks.empty() &&
brandtr535830e2016-10-31 03:45:58 -0700757 IsNewerSequenceNumber(nacks.back(), ulpfec_sequence_number_)) {
Peter Boström5811a392015-12-10 13:02:50 +0100758 observation_complete_.Set();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000759 }
760 }
761 return SEND_PACKET;
762 }
763
stefane74eef12016-01-08 06:47:13 -0800764 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
765 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
766 // Configure some network delay.
767 const int kNetworkDelayMs = 50;
768 FakeNetworkPipe::Config config;
769 config.queue_delay_ms = kNetworkDelayMs;
770 return new test::PacketTransport(sender_call, this,
771 test::PacketTransport::kSender, config);
772 }
773
Stefan Holmere5904162015-03-26 11:11:06 +0100774 // TODO(holmer): Investigate why we don't send FEC packets when the bitrate
775 // is 10 kbps.
776 Call::Config GetSenderCallConfig() override {
skvlad11a9cbf2016-10-07 11:53:05 -0700777 Call::Config config(&event_log_);
Stefan Holmere5904162015-03-26 11:11:06 +0100778 const int kMinBitrateBps = 30000;
779 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
780 return config;
781 }
782
stefanff483612015-12-21 03:14:00 -0800783 void ModifyVideoConfigs(
784 VideoSendStream::Config* send_config,
785 std::vector<VideoReceiveStream::Config>* receive_configs,
786 VideoEncoderConfig* encoder_config) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000787 // Configure hybrid NACK/FEC.
788 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
brandtrb5f2c3f2016-10-04 23:28:39 -0700789 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
790 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200791 // Set codec to VP8, otherwise NACK/FEC hybrid will be disabled.
792 send_config->encoder_settings.encoder = encoder_.get();
793 send_config->encoder_settings.payload_name = "VP8";
794 send_config->encoder_settings.payload_type = kFakeVideoSendPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200795
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000796 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
brandtrb5f2c3f2016-10-04 23:28:39 -0700797 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
798 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200799
800 (*receive_configs)[0].decoders.resize(1);
801 (*receive_configs)[0].decoders[0].payload_type =
802 send_config->encoder_settings.payload_type;
803 (*receive_configs)[0].decoders[0].payload_name =
804 send_config->encoder_settings.payload_name;
805 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000806 }
807
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000808 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100809 EXPECT_TRUE(Wait())
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000810 << "Timed out while waiting for FEC packets to be received.";
811 }
812
813 enum {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000814 kFirstPacket,
brandtr535830e2016-10-31 03:45:58 -0700815 kDropEveryOtherPacketUntilUlpfec,
816 kDropAllMediaPacketsUntilUlpfec,
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200817 kDropOneMediaPacket,
818 kPassOneMediaPacket,
brandtr535830e2016-10-31 03:45:58 -0700819 kVerifyUlpfecPacketNotInNackList,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000820 } state_;
821
stefan608213e2015-11-01 14:56:10 -0800822 rtc::CriticalSection crit_;
brandtr535830e2016-10-31 03:45:58 -0700823 uint16_t ulpfec_sequence_number_ GUARDED_BY(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000824 bool has_last_sequence_number_;
825 uint16_t last_sequence_number_;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200826 std::unique_ptr<webrtc::VideoEncoder> encoder_;
827 std::unique_ptr<webrtc::VideoDecoder> decoder_;
stefanf116bd02015-10-27 08:29:42 -0700828 } test;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000829
stefane74eef12016-01-08 06:47:13 -0800830 RunBaseTest(&test);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000831}
832
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000833// This test drops second RTP packet with a marker bit set, makes sure it's
834// retransmitted and renders. Retransmission SSRCs are also checked.
Peter Boström39593972016-02-15 11:27:15 +0100835void EndToEndTest::DecodesRetransmittedFrame(bool enable_rtx, bool enable_red) {
Peter Boström67680c12016-02-17 11:10:04 +0100836 static const int kDroppedFrameNumber = 10;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000837 class RetransmissionObserver : public test::EndToEndTest,
838 public I420FrameCallback {
839 public:
Peter Boström39593972016-02-15 11:27:15 +0100840 RetransmissionObserver(bool enable_rtx, bool enable_red)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000841 : EndToEndTest(kDefaultTimeoutMs),
Peter Boström39593972016-02-15 11:27:15 +0100842 payload_type_(GetPayloadType(false, enable_red)),
843 retransmission_ssrc_(enable_rtx ? kSendRtxSsrcs[0]
844 : kVideoSendSsrcs[0]),
845 retransmission_payload_type_(GetPayloadType(enable_rtx, enable_red)),
846 encoder_(VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000847 marker_bits_observed_(0),
danilchap192717e2016-07-25 08:20:51 -0700848 retransmitted_timestamp_(0) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000849
850 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000851 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700852 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000853 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000854 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000855
Peter Boström67680c12016-02-17 11:10:04 +0100856 // Ignore padding-only packets over RTX.
857 if (header.payloadType != payload_type_) {
858 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
859 if (length == header.headerLength + header.paddingLength)
860 return SEND_PACKET;
Stefan Holmer586b19b2015-09-18 11:14:31 +0200861 }
Peter Boström67680c12016-02-17 11:10:04 +0100862
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000863 if (header.timestamp == retransmitted_timestamp_) {
864 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
865 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000866 return SEND_PACKET;
867 }
868
Stefan Holmer586b19b2015-09-18 11:14:31 +0200869 // Found the final packet of the frame to inflict loss to, drop this and
870 // expect a retransmission.
danilchapfdd381c2016-07-25 04:03:20 -0700871 if (header.payloadType == payload_type_ && header.markerBit &&
872 ++marker_bits_observed_ == kDroppedFrameNumber) {
Danil Chapovalov18c65a42016-06-29 15:29:34 +0200873 // This should be the only dropped packet.
874 EXPECT_EQ(0u, retransmitted_timestamp_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000875 retransmitted_timestamp_ = header.timestamp;
danilchap192717e2016-07-25 08:20:51 -0700876 if (std::find(rendered_timestamps_.begin(), rendered_timestamps_.end(),
877 retransmitted_timestamp_) != rendered_timestamps_.end()) {
878 // Frame was rendered before last packet was scheduled for sending.
879 // This is extremly rare but possible scenario because prober able to
880 // resend packet before it was send.
881 // TODO(danilchap): Remove this corner case when prober would not be
882 // able to sneak in between packet saved to history for resending and
883 // pacer notified about existance of that packet for sending.
884 // See https://bugs.chromium.org/p/webrtc/issues/detail?id=5540 for
885 // details.
886 observation_complete_.Set();
887 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000888 return DROP_PACKET;
889 }
890
891 return SEND_PACKET;
892 }
893
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700894 void FrameCallback(VideoFrame* frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200895 rtc::CritScope lock(&crit_);
danilchap192717e2016-07-25 08:20:51 -0700896 if (frame->timestamp() == retransmitted_timestamp_)
Peter Boström5811a392015-12-10 13:02:50 +0100897 observation_complete_.Set();
danilchap192717e2016-07-25 08:20:51 -0700898 rendered_timestamps_.push_back(frame->timestamp());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000899 }
900
stefanff483612015-12-21 03:14:00 -0800901 void ModifyVideoConfigs(
902 VideoSendStream::Config* send_config,
903 std::vector<VideoReceiveStream::Config>* receive_configs,
904 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000905 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000906 (*receive_configs)[0].pre_render_callback = this;
907 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
Shao Changbine62202f2015-04-21 20:24:50 +0800908
909 if (payload_type_ == kRedPayloadType) {
brandtrb5f2c3f2016-10-04 23:28:39 -0700910 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
911 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +0100912 if (retransmission_ssrc_ == kSendRtxSsrcs[0])
brandtrb5f2c3f2016-10-04 23:28:39 -0700913 send_config->rtp.ulpfec.red_rtx_payload_type = kRtxRedPayloadType;
914 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type =
915 send_config->rtp.ulpfec.ulpfec_payload_type;
916 (*receive_configs)[0].rtp.ulpfec.red_payload_type =
917 send_config->rtp.ulpfec.red_payload_type;
918 (*receive_configs)[0].rtp.ulpfec.red_rtx_payload_type =
919 send_config->rtp.ulpfec.red_rtx_payload_type;
Shao Changbine62202f2015-04-21 20:24:50 +0800920 }
921
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000922 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
923 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000924 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +0100925 (*receive_configs)[0].rtp.rtx[payload_type_].ssrc = kSendRtxSsrcs[0];
926 (*receive_configs)[0].rtp.rtx[payload_type_].payload_type =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000927 kSendRtxPayloadType;
928 }
Peter Boström39593972016-02-15 11:27:15 +0100929 // Configure encoding and decoding with VP8, since generic packetization
930 // doesn't support FEC with NACK.
931 RTC_DCHECK_EQ(1u, (*receive_configs)[0].decoders.size());
932 send_config->encoder_settings.encoder = encoder_.get();
933 send_config->encoder_settings.payload_name = "VP8";
934 (*receive_configs)[0].decoders[0].payload_name = "VP8";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000935 }
936
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000937 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100938 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000939 << "Timed out while waiting for retransmission to render.";
940 }
941
Shao Changbine62202f2015-04-21 20:24:50 +0800942 int GetPayloadType(bool use_rtx, bool use_red) {
Stefan Holmer10880012016-02-03 13:29:59 +0100943 if (use_red) {
944 if (use_rtx)
945 return kRtxRedPayloadType;
946 return kRedPayloadType;
947 }
948 if (use_rtx)
949 return kSendRtxPayloadType;
950 return kFakeVideoSendPayloadType;
Shao Changbine62202f2015-04-21 20:24:50 +0800951 }
952
stefanf116bd02015-10-27 08:29:42 -0700953 rtc::CriticalSection crit_;
Shao Changbine62202f2015-04-21 20:24:50 +0800954 const int payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000955 const uint32_t retransmission_ssrc_;
956 const int retransmission_payload_type_;
kwiberg27f982b2016-03-01 11:52:33 -0800957 std::unique_ptr<VideoEncoder> encoder_;
Peter Boström39593972016-02-15 11:27:15 +0100958 const std::string payload_name_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000959 int marker_bits_observed_;
stefanf116bd02015-10-27 08:29:42 -0700960 uint32_t retransmitted_timestamp_ GUARDED_BY(&crit_);
danilchap192717e2016-07-25 08:20:51 -0700961 std::vector<uint32_t> rendered_timestamps_ GUARDED_BY(&crit_);
Peter Boström39593972016-02-15 11:27:15 +0100962 } test(enable_rtx, enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000963
stefane74eef12016-01-08 06:47:13 -0800964 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000965}
966
967TEST_F(EndToEndTest, DecodesRetransmittedFrame) {
Shao Changbine62202f2015-04-21 20:24:50 +0800968 DecodesRetransmittedFrame(false, false);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000969}
970
971TEST_F(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +0800972 DecodesRetransmittedFrame(true, false);
973}
974
975TEST_F(EndToEndTest, DecodesRetransmittedFrameByRed) {
976 DecodesRetransmittedFrame(false, true);
977}
978
979TEST_F(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
980 DecodesRetransmittedFrame(true, true);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000981}
982
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000983void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
984 static const int kPacketsToDrop = 1;
985
nisse7ade7b32016-03-23 04:48:10 -0700986 class PliObserver : public test::EndToEndTest,
987 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000988 public:
989 explicit PliObserver(int rtp_history_ms)
990 : EndToEndTest(kLongTimeoutMs),
991 rtp_history_ms_(rtp_history_ms),
992 nack_enabled_(rtp_history_ms > 0),
993 highest_dropped_timestamp_(0),
994 frames_to_drop_(0),
995 received_pli_(false) {}
996
997 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000998 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700999 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001000 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001001 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001002
1003 // Drop all retransmitted packets to force a PLI.
1004 if (header.timestamp <= highest_dropped_timestamp_)
1005 return DROP_PACKET;
1006
1007 if (frames_to_drop_ > 0) {
1008 highest_dropped_timestamp_ = header.timestamp;
1009 --frames_to_drop_;
1010 return DROP_PACKET;
1011 }
1012
1013 return SEND_PACKET;
1014 }
1015
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001016 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001017 rtc::CritScope lock(&crit_);
danilchap3dc929e2016-11-02 08:21:59 -07001018 test::RtcpPacketParser parser;
1019 EXPECT_TRUE(parser.Parse(packet, length));
1020 if (!nack_enabled_)
1021 EXPECT_EQ(0, parser.nack()->num_packets());
1022 if (parser.pli()->num_packets() > 0)
1023 received_pli_ = true;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001024 return SEND_PACKET;
1025 }
1026
nisseeb83a1a2016-03-21 01:27:56 -07001027 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001028 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001029 if (received_pli_ &&
1030 video_frame.timestamp() > highest_dropped_timestamp_) {
Peter Boström5811a392015-12-10 13:02:50 +01001031 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001032 }
1033 if (!received_pli_)
1034 frames_to_drop_ = kPacketsToDrop;
1035 }
1036
stefanff483612015-12-21 03:14:00 -08001037 void ModifyVideoConfigs(
1038 VideoSendStream::Config* send_config,
1039 std::vector<VideoReceiveStream::Config>* receive_configs,
1040 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001041 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001042 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
1043 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001044 }
1045
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001046 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001047 EXPECT_TRUE(Wait()) << "Timed out waiting for PLI to be "
1048 "received and a frame to be "
1049 "rendered afterwards.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001050 }
1051
stefanf116bd02015-10-27 08:29:42 -07001052 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001053 int rtp_history_ms_;
1054 bool nack_enabled_;
stefanf116bd02015-10-27 08:29:42 -07001055 uint32_t highest_dropped_timestamp_ GUARDED_BY(&crit_);
1056 int frames_to_drop_ GUARDED_BY(&crit_);
1057 bool received_pli_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001058 } test(rtp_history_ms);
1059
stefane74eef12016-01-08 06:47:13 -08001060 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001061}
1062
1063TEST_F(EndToEndTest, ReceivesPliAndRecoversWithNack) {
1064 ReceivesPliAndRecovers(1000);
1065}
1066
jbauchdb81ffd2015-11-23 03:59:02 -08001067TEST_F(EndToEndTest, ReceivesPliAndRecoversWithoutNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001068 ReceivesPliAndRecovers(0);
1069}
1070
1071TEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
1072 class PacketInputObserver : public PacketReceiver {
1073 public:
1074 explicit PacketInputObserver(PacketReceiver* receiver)
Peter Boström5811a392015-12-10 13:02:50 +01001075 : receiver_(receiver), delivered_packet_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001076
Peter Boström5811a392015-12-10 13:02:50 +01001077 bool Wait() { return delivered_packet_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001078
1079 private:
stefan68786d22015-09-08 05:36:15 -07001080 DeliveryStatus DeliverPacket(MediaType media_type,
1081 const uint8_t* packet,
1082 size_t length,
1083 const PacketTime& packet_time) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001084 if (RtpHeaderParser::IsRtcp(packet, length)) {
stefan68786d22015-09-08 05:36:15 -07001085 return receiver_->DeliverPacket(media_type, packet, length,
1086 packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001087 } else {
1088 DeliveryStatus delivery_status =
stefan68786d22015-09-08 05:36:15 -07001089 receiver_->DeliverPacket(media_type, packet, length, packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001090 EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
Peter Boström5811a392015-12-10 13:02:50 +01001091 delivered_packet_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001092 return delivery_status;
1093 }
1094 }
1095
1096 PacketReceiver* receiver_;
Peter Boström5811a392015-12-10 13:02:50 +01001097 rtc::Event delivered_packet_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001098 };
1099
skvlad11a9cbf2016-10-07 11:53:05 -07001100 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -07001101
stefanf116bd02015-10-27 08:29:42 -07001102 test::DirectTransport send_transport(sender_call_.get());
1103 test::DirectTransport receive_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001104 PacketInputObserver input_observer(receiver_call_->Receiver());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001105 send_transport.SetReceiver(&input_observer);
1106 receive_transport.SetReceiver(sender_call_->Receiver());
1107
brandtr841de6a2016-11-15 07:10:52 -08001108 CreateSendConfig(1, 0, 0, &send_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001109 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001110
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001111 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07001112 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
1113 kDefaultHeight);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001114 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001115
stefanff483612015-12-21 03:14:00 -08001116 receiver_call_->DestroyVideoReceiveStream(video_receive_streams_[0]);
1117 video_receive_streams_.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001118
1119 // Wait() waits for a received packet.
Peter Boström5811a392015-12-10 13:02:50 +01001120 EXPECT_TRUE(input_observer.Wait());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001121
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001122 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001123
1124 DestroyStreams();
1125
1126 send_transport.StopSending();
1127 receive_transport.StopSending();
1128}
1129
pbosda903ea2015-10-02 02:36:56 -07001130void EndToEndTest::RespectsRtcpMode(RtcpMode rtcp_mode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001131 static const int kNumCompoundRtcpPacketsToObserve = 10;
1132 class RtcpModeObserver : public test::EndToEndTest {
1133 public:
pbosda903ea2015-10-02 02:36:56 -07001134 explicit RtcpModeObserver(RtcpMode rtcp_mode)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001135 : EndToEndTest(kDefaultTimeoutMs),
1136 rtcp_mode_(rtcp_mode),
1137 sent_rtp_(0),
1138 sent_rtcp_(0) {}
1139
1140 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001141 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001142 if (++sent_rtp_ % 3 == 0)
1143 return DROP_PACKET;
1144
1145 return SEND_PACKET;
1146 }
1147
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001148 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001149 ++sent_rtcp_;
danilchap3dc929e2016-11-02 08:21:59 -07001150 test::RtcpPacketParser parser;
1151 EXPECT_TRUE(parser.Parse(packet, length));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001152
danilchap3dc929e2016-11-02 08:21:59 -07001153 EXPECT_EQ(0, parser.sender_report()->num_packets());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001154
1155 switch (rtcp_mode_) {
pbosda903ea2015-10-02 02:36:56 -07001156 case RtcpMode::kCompound:
danilchap3dc929e2016-11-02 08:21:59 -07001157 if (parser.receiver_report()->num_packets() == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001158 ADD_FAILURE() << "Received RTCP packet without receiver report for "
pbosda903ea2015-10-02 02:36:56 -07001159 "RtcpMode::kCompound.";
Peter Boström5811a392015-12-10 13:02:50 +01001160 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001161 }
1162
1163 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
Peter Boström5811a392015-12-10 13:02:50 +01001164 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001165
1166 break;
pbosda903ea2015-10-02 02:36:56 -07001167 case RtcpMode::kReducedSize:
danilchap3dc929e2016-11-02 08:21:59 -07001168 if (parser.receiver_report()->num_packets() == 0)
Peter Boström5811a392015-12-10 13:02:50 +01001169 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001170 break;
pbosda903ea2015-10-02 02:36:56 -07001171 case RtcpMode::kOff:
1172 RTC_NOTREACHED();
1173 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001174 }
1175
1176 return SEND_PACKET;
1177 }
1178
stefanff483612015-12-21 03:14:00 -08001179 void ModifyVideoConfigs(
1180 VideoSendStream::Config* send_config,
1181 std::vector<VideoReceiveStream::Config>* receive_configs,
1182 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001183 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001184 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1185 (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001186 }
1187
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001188 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001189 EXPECT_TRUE(Wait())
pbosda903ea2015-10-02 02:36:56 -07001190 << (rtcp_mode_ == RtcpMode::kCompound
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001191 ? "Timed out before observing enough compound packets."
1192 : "Timed out before receiving a non-compound RTCP packet.");
1193 }
1194
pbosda903ea2015-10-02 02:36:56 -07001195 RtcpMode rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001196 int sent_rtp_;
1197 int sent_rtcp_;
1198 } test(rtcp_mode);
1199
stefane74eef12016-01-08 06:47:13 -08001200 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001201}
1202
1203TEST_F(EndToEndTest, UsesRtcpCompoundMode) {
pbosda903ea2015-10-02 02:36:56 -07001204 RespectsRtcpMode(RtcpMode::kCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001205}
1206
1207TEST_F(EndToEndTest, UsesRtcpReducedSizeMode) {
pbosda903ea2015-10-02 02:36:56 -07001208 RespectsRtcpMode(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001209}
1210
1211// Test sets up a Call multiple senders with different resolutions and SSRCs.
1212// Another is set up to receive all three of these with different renderers.
sprang867fb522015-08-03 04:38:41 -07001213class MultiStreamTest {
1214 public:
1215 static const size_t kNumStreams = 3;
1216 struct CodecSettings {
1217 uint32_t ssrc;
1218 int width;
1219 int height;
1220 } codec_settings[kNumStreams];
1221
1222 MultiStreamTest() {
1223 // TODO(sprang): Cleanup when msvc supports explicit initializers for array.
1224 codec_settings[0] = {1, 640, 480};
1225 codec_settings[1] = {2, 320, 240};
1226 codec_settings[2] = {3, 240, 160};
1227 }
1228
1229 virtual ~MultiStreamTest() {}
1230
1231 void RunTest() {
skvlad11a9cbf2016-10-07 11:53:05 -07001232 webrtc::RtcEventLogNullImpl event_log;
1233 Call::Config config(&event_log);
1234 std::unique_ptr<Call> sender_call(Call::Create(config));
1235 std::unique_ptr<Call> receiver_call(Call::Create(config));
kwiberg27f982b2016-03-01 11:52:33 -08001236 std::unique_ptr<test::DirectTransport> sender_transport(
stefanf116bd02015-10-27 08:29:42 -07001237 CreateSendTransport(sender_call.get()));
kwiberg27f982b2016-03-01 11:52:33 -08001238 std::unique_ptr<test::DirectTransport> receiver_transport(
stefanf116bd02015-10-27 08:29:42 -07001239 CreateReceiveTransport(receiver_call.get()));
sprang867fb522015-08-03 04:38:41 -07001240 sender_transport->SetReceiver(receiver_call->Receiver());
1241 receiver_transport->SetReceiver(sender_call->Receiver());
1242
kwiberg27f982b2016-03-01 11:52:33 -08001243 std::unique_ptr<VideoEncoder> encoders[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001244 for (size_t i = 0; i < kNumStreams; ++i)
1245 encoders[i].reset(VideoEncoder::Create(VideoEncoder::kVp8));
1246
1247 VideoSendStream* send_streams[kNumStreams];
1248 VideoReceiveStream* receive_streams[kNumStreams];
1249
1250 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
kwiberg4a206a92016-03-31 10:24:26 -07001251 std::vector<std::unique_ptr<VideoDecoder>> allocated_decoders;
sprang867fb522015-08-03 04:38:41 -07001252 for (size_t i = 0; i < kNumStreams; ++i) {
1253 uint32_t ssrc = codec_settings[i].ssrc;
1254 int width = codec_settings[i].width;
1255 int height = codec_settings[i].height;
1256
solenberg4fbae2b2015-08-28 04:07:10 -07001257 VideoSendStream::Config send_config(sender_transport.get());
sprang867fb522015-08-03 04:38:41 -07001258 send_config.rtp.ssrcs.push_back(ssrc);
1259 send_config.encoder_settings.encoder = encoders[i].get();
1260 send_config.encoder_settings.payload_name = "VP8";
1261 send_config.encoder_settings.payload_type = 124;
1262 VideoEncoderConfig encoder_config;
perkjfa10b552016-10-02 23:45:26 -07001263 test::FillEncoderConfiguration(1, &encoder_config);
1264 encoder_config.max_bitrate_bps = 100000;
sprang867fb522015-08-03 04:38:41 -07001265
1266 UpdateSendConfig(i, &send_config, &encoder_config, &frame_generators[i]);
1267
perkj26091b12016-09-01 01:17:40 -07001268 send_streams[i] = sender_call->CreateVideoSendStream(
1269 send_config.Copy(), encoder_config.Copy());
sprang867fb522015-08-03 04:38:41 -07001270 send_streams[i]->Start();
1271
solenberg4fbae2b2015-08-28 04:07:10 -07001272 VideoReceiveStream::Config receive_config(receiver_transport.get());
sprang867fb522015-08-03 04:38:41 -07001273 receive_config.rtp.remote_ssrc = ssrc;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001274 receive_config.rtp.local_ssrc = test::CallTest::kReceiverLocalVideoSsrc;
sprang867fb522015-08-03 04:38:41 -07001275 VideoReceiveStream::Decoder decoder =
1276 test::CreateMatchingDecoder(send_config.encoder_settings);
kwiberg4a206a92016-03-31 10:24:26 -07001277 allocated_decoders.push_back(
1278 std::unique_ptr<VideoDecoder>(decoder.decoder));
sprang867fb522015-08-03 04:38:41 -07001279 receive_config.decoders.push_back(decoder);
1280
1281 UpdateReceiveConfig(i, &receive_config);
1282
1283 receive_streams[i] =
Tommi733b5472016-06-10 17:58:01 +02001284 receiver_call->CreateVideoReceiveStream(std::move(receive_config));
sprang867fb522015-08-03 04:38:41 -07001285 receive_streams[i]->Start();
1286
1287 frame_generators[i] = test::FrameGeneratorCapturer::Create(
perkja49cbd32016-09-16 07:53:41 -07001288 width, height, 30, Clock::GetRealTimeClock());
perkj803d97f2016-11-01 11:45:46 -07001289 send_streams[i]->SetSource(
1290 frame_generators[i],
1291 VideoSendStream::DegradationPreference::kBalanced);
sprang867fb522015-08-03 04:38:41 -07001292 frame_generators[i]->Start();
1293 }
1294
1295 Wait();
1296
1297 for (size_t i = 0; i < kNumStreams; ++i) {
1298 frame_generators[i]->Stop();
1299 sender_call->DestroyVideoSendStream(send_streams[i]);
1300 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1301 delete frame_generators[i];
1302 }
1303
1304 sender_transport->StopSending();
1305 receiver_transport->StopSending();
1306 }
1307
1308 protected:
1309 virtual void Wait() = 0;
1310 // Note: frame_generator is a point-to-pointer, since the actual instance
1311 // hasn't been created at the time of this call. Only when packets/frames
1312 // start flowing should this be dereferenced.
1313 virtual void UpdateSendConfig(
1314 size_t stream_index,
1315 VideoSendStream::Config* send_config,
1316 VideoEncoderConfig* encoder_config,
1317 test::FrameGeneratorCapturer** frame_generator) {}
1318 virtual void UpdateReceiveConfig(size_t stream_index,
1319 VideoReceiveStream::Config* receive_config) {
1320 }
stefanf116bd02015-10-27 08:29:42 -07001321 virtual test::DirectTransport* CreateSendTransport(Call* sender_call) {
1322 return new test::DirectTransport(sender_call);
sprang867fb522015-08-03 04:38:41 -07001323 }
stefanf116bd02015-10-27 08:29:42 -07001324 virtual test::DirectTransport* CreateReceiveTransport(Call* receiver_call) {
1325 return new test::DirectTransport(receiver_call);
sprang867fb522015-08-03 04:38:41 -07001326 }
1327};
1328
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001329// Each renderer verifies that it receives the expected resolution, and as soon
1330// as every renderer has received a frame, the test finishes.
andresp@webrtc.org02686112014-09-19 08:24:19 +00001331TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) {
nisse7ade7b32016-03-23 04:48:10 -07001332 class VideoOutputObserver : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001333 public:
sprang867fb522015-08-03 04:38:41 -07001334 VideoOutputObserver(const MultiStreamTest::CodecSettings& settings,
1335 uint32_t ssrc,
1336 test::FrameGeneratorCapturer** frame_generator)
1337 : settings_(settings),
1338 ssrc_(ssrc),
1339 frame_generator_(frame_generator),
Peter Boström5811a392015-12-10 13:02:50 +01001340 done_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001341
nisseeb83a1a2016-03-21 01:27:56 -07001342 void OnFrame(const VideoFrame& video_frame) override {
sprang867fb522015-08-03 04:38:41 -07001343 EXPECT_EQ(settings_.width, video_frame.width());
1344 EXPECT_EQ(settings_.height, video_frame.height());
1345 (*frame_generator_)->Stop();
Peter Boström5811a392015-12-10 13:02:50 +01001346 done_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001347 }
1348
sprang867fb522015-08-03 04:38:41 -07001349 uint32_t Ssrc() { return ssrc_; }
1350
Peter Boström5811a392015-12-10 13:02:50 +01001351 bool Wait() { return done_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001352
1353 private:
sprang867fb522015-08-03 04:38:41 -07001354 const MultiStreamTest::CodecSettings& settings_;
1355 const uint32_t ssrc_;
1356 test::FrameGeneratorCapturer** const frame_generator_;
Peter Boström5811a392015-12-10 13:02:50 +01001357 rtc::Event done_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001358 };
1359
sprang867fb522015-08-03 04:38:41 -07001360 class Tester : public MultiStreamTest {
1361 public:
1362 Tester() {}
1363 virtual ~Tester() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001364
sprang867fb522015-08-03 04:38:41 -07001365 protected:
1366 void Wait() override {
1367 for (const auto& observer : observers_) {
Peter Boström5811a392015-12-10 13:02:50 +01001368 EXPECT_TRUE(observer->Wait()) << "Time out waiting for from on ssrc "
1369 << observer->Ssrc();
sprang867fb522015-08-03 04:38:41 -07001370 }
1371 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001372
sprang867fb522015-08-03 04:38:41 -07001373 void UpdateSendConfig(
1374 size_t stream_index,
1375 VideoSendStream::Config* send_config,
1376 VideoEncoderConfig* encoder_config,
1377 test::FrameGeneratorCapturer** frame_generator) override {
1378 observers_[stream_index].reset(new VideoOutputObserver(
1379 codec_settings[stream_index], send_config->rtp.ssrcs.front(),
1380 frame_generator));
1381 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001382
sprang867fb522015-08-03 04:38:41 -07001383 void UpdateReceiveConfig(
1384 size_t stream_index,
1385 VideoReceiveStream::Config* receive_config) override {
1386 receive_config->renderer = observers_[stream_index].get();
1387 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001388
sprang867fb522015-08-03 04:38:41 -07001389 private:
kwiberg27f982b2016-03-01 11:52:33 -08001390 std::unique_ptr<VideoOutputObserver> observers_[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001391 } tester;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001392
sprang867fb522015-08-03 04:38:41 -07001393 tester.RunTest();
1394}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001395
sprang867fb522015-08-03 04:38:41 -07001396TEST_F(EndToEndTest, AssignsTransportSequenceNumbers) {
sprang867fb522015-08-03 04:38:41 -07001397 static const int kExtensionId = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001398
sprang867fb522015-08-03 04:38:41 -07001399 class RtpExtensionHeaderObserver : public test::DirectTransport {
1400 public:
stefanf116bd02015-10-27 08:29:42 -07001401 RtpExtensionHeaderObserver(Call* sender_call,
1402 const uint32_t& first_media_ssrc,
sprang861c55e2015-10-16 10:01:21 -07001403 const std::map<uint32_t, uint32_t>& ssrc_map)
stefanf116bd02015-10-27 08:29:42 -07001404 : DirectTransport(sender_call),
Peter Boström5811a392015-12-10 13:02:50 +01001405 done_(false, false),
sprang867fb522015-08-03 04:38:41 -07001406 parser_(RtpHeaderParser::Create()),
sprang861c55e2015-10-16 10:01:21 -07001407 first_media_ssrc_(first_media_ssrc),
1408 rtx_to_media_ssrcs_(ssrc_map),
sprang867fb522015-08-03 04:38:41 -07001409 padding_observed_(false),
sprang861c55e2015-10-16 10:01:21 -07001410 rtx_padding_observed_(false),
1411 retransmit_observed_(false),
1412 started_(false) {
sprang867fb522015-08-03 04:38:41 -07001413 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
1414 kExtensionId);
1415 }
1416 virtual ~RtpExtensionHeaderObserver() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001417
stefan1d8a5062015-10-02 03:39:33 -07001418 bool SendRtp(const uint8_t* data,
1419 size_t length,
1420 const PacketOptions& options) override {
sprang861c55e2015-10-16 10:01:21 -07001421 {
1422 rtc::CritScope cs(&lock_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001423
Erik Språng8d629712015-08-04 16:24:03 +02001424 if (IsDone())
sprang861c55e2015-10-16 10:01:21 -07001425 return false;
1426
1427 if (started_) {
1428 RTPHeader header;
1429 EXPECT_TRUE(parser_->Parse(data, length, &header));
1430 bool drop_packet = false;
1431
1432 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
1433 EXPECT_EQ(options.packet_id,
1434 header.extension.transportSequenceNumber);
1435 if (!streams_observed_.empty()) {
1436 // Unwrap packet id and verify uniqueness.
1437 int64_t packet_id = unwrapper_.Unwrap(options.packet_id);
1438 EXPECT_TRUE(received_packed_ids_.insert(packet_id).second);
1439 }
1440
1441 // Drop (up to) every 17th packet, so we get retransmits.
1442 // Only drop media, and not on the first stream (otherwise it will be
1443 // hard to distinguish from padding, which is always sent on the first
1444 // stream).
1445 if (header.payloadType != kSendRtxPayloadType &&
1446 header.ssrc != first_media_ssrc_ &&
1447 header.extension.transportSequenceNumber % 17 == 0) {
1448 dropped_seq_[header.ssrc].insert(header.sequenceNumber);
1449 drop_packet = true;
1450 }
1451
1452 size_t payload_length =
1453 length - (header.headerLength + header.paddingLength);
1454 if (payload_length == 0) {
1455 padding_observed_ = true;
1456 } else if (header.payloadType == kSendRtxPayloadType) {
1457 uint16_t original_sequence_number =
1458 ByteReader<uint16_t>::ReadBigEndian(&data[header.headerLength]);
1459 uint32_t original_ssrc =
1460 rtx_to_media_ssrcs_.find(header.ssrc)->second;
1461 std::set<uint16_t>* seq_no_map = &dropped_seq_[original_ssrc];
1462 auto it = seq_no_map->find(original_sequence_number);
1463 if (it != seq_no_map->end()) {
1464 retransmit_observed_ = true;
1465 seq_no_map->erase(it);
1466 } else {
1467 rtx_padding_observed_ = true;
1468 }
1469 } else {
1470 streams_observed_.insert(header.ssrc);
1471 }
1472
1473 if (IsDone())
Peter Boström5811a392015-12-10 13:02:50 +01001474 done_.Set();
sprang861c55e2015-10-16 10:01:21 -07001475
1476 if (drop_packet)
1477 return true;
1478 }
sprang867fb522015-08-03 04:38:41 -07001479 }
sprang861c55e2015-10-16 10:01:21 -07001480
stefan1d8a5062015-10-02 03:39:33 -07001481 return test::DirectTransport::SendRtp(data, length, options);
sprang867fb522015-08-03 04:38:41 -07001482 }
1483
Erik Språng8d629712015-08-04 16:24:03 +02001484 bool IsDone() {
sprang861c55e2015-10-16 10:01:21 -07001485 bool observed_types_ok =
1486 streams_observed_.size() == MultiStreamTest::kNumStreams &&
1487 padding_observed_ && retransmit_observed_ && rtx_padding_observed_;
1488 if (!observed_types_ok)
1489 return false;
1490 // We should not have any gaps in the sequence number range.
1491 size_t seqno_range =
1492 *received_packed_ids_.rbegin() - *received_packed_ids_.begin() + 1;
1493 return seqno_range == received_packed_ids_.size();
Erik Språng8d629712015-08-04 16:24:03 +02001494 }
1495
Peter Boström5811a392015-12-10 13:02:50 +01001496 bool Wait() {
sprang861c55e2015-10-16 10:01:21 -07001497 {
1498 // Can't be sure until this point that rtx_to_media_ssrcs_ etc have
1499 // been initialized and are OK to read.
1500 rtc::CritScope cs(&lock_);
1501 started_ = true;
1502 }
Peter Boström5811a392015-12-10 13:02:50 +01001503 return done_.Wait(kDefaultTimeoutMs);
sprang861c55e2015-10-16 10:01:21 -07001504 }
sprang867fb522015-08-03 04:38:41 -07001505
sprang861c55e2015-10-16 10:01:21 -07001506 rtc::CriticalSection lock_;
Peter Boström5811a392015-12-10 13:02:50 +01001507 rtc::Event done_;
kwiberg27f982b2016-03-01 11:52:33 -08001508 std::unique_ptr<RtpHeaderParser> parser_;
sprang861c55e2015-10-16 10:01:21 -07001509 SequenceNumberUnwrapper unwrapper_;
1510 std::set<int64_t> received_packed_ids_;
sprang867fb522015-08-03 04:38:41 -07001511 std::set<uint32_t> streams_observed_;
sprang861c55e2015-10-16 10:01:21 -07001512 std::map<uint32_t, std::set<uint16_t>> dropped_seq_;
1513 const uint32_t& first_media_ssrc_;
1514 const std::map<uint32_t, uint32_t>& rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001515 bool padding_observed_;
1516 bool rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001517 bool retransmit_observed_;
1518 bool started_;
sprang867fb522015-08-03 04:38:41 -07001519 };
1520
1521 class TransportSequenceNumberTester : public MultiStreamTest {
1522 public:
sprang861c55e2015-10-16 10:01:21 -07001523 TransportSequenceNumberTester()
1524 : first_media_ssrc_(0), observer_(nullptr) {}
sprang867fb522015-08-03 04:38:41 -07001525 virtual ~TransportSequenceNumberTester() {}
1526
1527 protected:
1528 void Wait() override {
Peter Boström74f6e9e2016-04-04 17:56:10 +02001529 RTC_DCHECK(observer_);
Peter Boström5811a392015-12-10 13:02:50 +01001530 EXPECT_TRUE(observer_->Wait());
sprang867fb522015-08-03 04:38:41 -07001531 }
1532
1533 void UpdateSendConfig(
1534 size_t stream_index,
1535 VideoSendStream::Config* send_config,
1536 VideoEncoderConfig* encoder_config,
1537 test::FrameGeneratorCapturer** frame_generator) override {
1538 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001539 send_config->rtp.extensions.push_back(RtpExtension(
1540 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sprang867fb522015-08-03 04:38:41 -07001541
1542 // Force some padding to be sent.
1543 const int kPaddingBitrateBps = 50000;
perkjfa10b552016-10-02 23:45:26 -07001544 encoder_config->max_bitrate_bps = 1000000;
sprang867fb522015-08-03 04:38:41 -07001545 encoder_config->min_transmit_bitrate_bps =
perkjfa10b552016-10-02 23:45:26 -07001546 encoder_config->max_bitrate_bps + kPaddingBitrateBps;
sprang867fb522015-08-03 04:38:41 -07001547
1548 // Configure RTX for redundant payload padding.
1549 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang861c55e2015-10-16 10:01:21 -07001550 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[stream_index]);
sprang867fb522015-08-03 04:38:41 -07001551 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
sprang861c55e2015-10-16 10:01:21 -07001552 rtx_to_media_ssrcs_[kSendRtxSsrcs[stream_index]] =
1553 send_config->rtp.ssrcs[0];
1554
1555 if (stream_index == 0)
1556 first_media_ssrc_ = send_config->rtp.ssrcs[0];
sprang867fb522015-08-03 04:38:41 -07001557 }
1558
1559 void UpdateReceiveConfig(
1560 size_t stream_index,
1561 VideoReceiveStream::Config* receive_config) override {
sprang861c55e2015-10-16 10:01:21 -07001562 receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang867fb522015-08-03 04:38:41 -07001563 receive_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001564 receive_config->rtp.extensions.push_back(RtpExtension(
1565 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sakal55d932b2016-09-30 06:19:08 -07001566 receive_config->renderer = &fake_renderer_;
sprang867fb522015-08-03 04:38:41 -07001567 }
1568
stefanf116bd02015-10-27 08:29:42 -07001569 test::DirectTransport* CreateSendTransport(Call* sender_call) override {
1570 observer_ = new RtpExtensionHeaderObserver(sender_call, first_media_ssrc_,
sprang861c55e2015-10-16 10:01:21 -07001571 rtx_to_media_ssrcs_);
sprang867fb522015-08-03 04:38:41 -07001572 return observer_;
1573 }
1574
1575 private:
sakal55d932b2016-09-30 06:19:08 -07001576 test::FakeVideoRenderer fake_renderer_;
sprang861c55e2015-10-16 10:01:21 -07001577 uint32_t first_media_ssrc_;
1578 std::map<uint32_t, uint32_t> rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001579 RtpExtensionHeaderObserver* observer_;
1580 } tester;
1581
1582 tester.RunTest();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001583}
1584
Stefan Holmer04cb7632016-01-14 20:34:30 +01001585class TransportFeedbackTester : public test::EndToEndTest {
1586 public:
1587 explicit TransportFeedbackTester(bool feedback_enabled,
1588 size_t num_video_streams,
1589 size_t num_audio_streams)
1590 : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
1591 feedback_enabled_(feedback_enabled),
1592 num_video_streams_(num_video_streams),
sprangcd349d92016-07-13 09:11:28 -07001593 num_audio_streams_(num_audio_streams),
1594 receiver_call_(nullptr) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001595 // Only one stream of each supported for now.
1596 EXPECT_LE(num_video_streams, 1u);
1597 EXPECT_LE(num_audio_streams, 1u);
1598 }
1599
1600 protected:
1601 Action OnSendRtcp(const uint8_t* data, size_t length) override {
1602 EXPECT_FALSE(HasTransportFeedback(data, length));
1603 return SEND_PACKET;
1604 }
1605
1606 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
1607 if (HasTransportFeedback(data, length))
1608 observation_complete_.Set();
1609 return SEND_PACKET;
1610 }
1611
1612 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
danilchap3dc929e2016-11-02 08:21:59 -07001613 test::RtcpPacketParser parser;
1614 EXPECT_TRUE(parser.Parse(data, length));
1615 return parser.transport_feedback()->num_packets() > 0;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001616 }
1617
1618 void PerformTest() override {
1619 const int64_t kDisabledFeedbackTimeoutMs = 5000;
1620 EXPECT_EQ(feedback_enabled_,
1621 observation_complete_.Wait(feedback_enabled_
1622 ? test::CallTest::kDefaultTimeoutMs
1623 : kDisabledFeedbackTimeoutMs));
1624 }
1625
1626 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1627 receiver_call_ = receiver_call;
1628 }
1629
1630 size_t GetNumVideoStreams() const override { return num_video_streams_; }
1631 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
1632
1633 void ModifyVideoConfigs(
1634 VideoSendStream::Config* send_config,
1635 std::vector<VideoReceiveStream::Config>* receive_configs,
1636 VideoEncoderConfig* encoder_config) override {
1637 send_config->rtp.extensions.clear();
1638 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001639 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001640 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1641 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
1642 }
1643
1644 void ModifyAudioConfigs(
1645 AudioSendStream::Config* send_config,
1646 std::vector<AudioReceiveStream::Config>* receive_configs) override {
1647 send_config->rtp.extensions.clear();
1648 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001649 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001650 (*receive_configs)[0].rtp.extensions.clear();
1651 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1652 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001653 }
1654
1655 private:
Erik Språng6b8d3552015-09-24 15:06:57 +02001656 static const int kExtensionId = 5;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001657 const bool feedback_enabled_;
1658 const size_t num_video_streams_;
1659 const size_t num_audio_streams_;
1660 Call* receiver_call_;
1661};
Erik Språng6b8d3552015-09-24 15:06:57 +02001662
Stefan Holmer04cb7632016-01-14 20:34:30 +01001663TEST_F(EndToEndTest, VideoReceivesTransportFeedback) {
1664 TransportFeedbackTester test(true, 1, 0);
1665 RunBaseTest(&test);
Erik Språng6b8d3552015-09-24 15:06:57 +02001666}
stefan43edf0f2015-11-20 18:05:48 -08001667
Stefan Holmer04cb7632016-01-14 20:34:30 +01001668TEST_F(EndToEndTest, VideoTransportFeedbackNotConfigured) {
1669 TransportFeedbackTester test(false, 1, 0);
1670 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001671}
1672
Stefan Holmer04cb7632016-01-14 20:34:30 +01001673TEST_F(EndToEndTest, AudioReceivesTransportFeedback) {
1674 TransportFeedbackTester test(true, 0, 1);
1675 RunBaseTest(&test);
1676}
1677
1678TEST_F(EndToEndTest, AudioTransportFeedbackNotConfigured) {
1679 TransportFeedbackTester test(false, 0, 1);
1680 RunBaseTest(&test);
1681}
1682
1683TEST_F(EndToEndTest, AudioVideoReceivesTransportFeedback) {
1684 TransportFeedbackTester test(true, 1, 1);
1685 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001686}
1687
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001688TEST_F(EndToEndTest, ObserversEncodedFrames) {
1689 class EncodedFrameTestObserver : public EncodedFrameObserver {
1690 public:
1691 EncodedFrameTestObserver()
Peter Boström5811a392015-12-10 13:02:50 +01001692 : length_(0), frame_type_(kEmptyFrame), called_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001693 virtual ~EncodedFrameTestObserver() {}
1694
1695 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
1696 frame_type_ = encoded_frame.frame_type_;
1697 length_ = encoded_frame.length_;
1698 buffer_.reset(new uint8_t[length_]);
1699 memcpy(buffer_.get(), encoded_frame.data_, length_);
Peter Boström5811a392015-12-10 13:02:50 +01001700 called_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001701 }
1702
Peter Boström5811a392015-12-10 13:02:50 +01001703 bool Wait() { return called_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001704
1705 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
1706 ASSERT_EQ(length_, observer.length_)
1707 << "Observed frames are of different lengths.";
1708 EXPECT_EQ(frame_type_, observer.frame_type_)
1709 << "Observed frames have different frame types.";
1710 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
1711 << "Observed encoded frames have different content.";
1712 }
1713
1714 private:
kwiberg27f982b2016-03-01 11:52:33 -08001715 std::unique_ptr<uint8_t[]> buffer_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001716 size_t length_;
1717 FrameType frame_type_;
Peter Boström5811a392015-12-10 13:02:50 +01001718 rtc::Event called_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001719 };
1720
1721 EncodedFrameTestObserver post_encode_observer;
1722 EncodedFrameTestObserver pre_decode_observer;
1723
skvlad11a9cbf2016-10-07 11:53:05 -07001724 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -07001725
stefanf116bd02015-10-27 08:29:42 -07001726 test::DirectTransport sender_transport(sender_call_.get());
1727 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001728 sender_transport.SetReceiver(receiver_call_->Receiver());
1729 receiver_transport.SetReceiver(sender_call_->Receiver());
1730
brandtr841de6a2016-11-15 07:10:52 -08001731 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001732 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -08001733 video_send_config_.post_encode_callback = &post_encode_observer;
1734 video_receive_configs_[0].pre_decode_callback = &pre_decode_observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001735
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001736 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001737 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001738
kwiberg27f982b2016-03-01 11:52:33 -08001739 std::unique_ptr<test::FrameGenerator> frame_generator(
perkjfa10b552016-10-02 23:45:26 -07001740 test::FrameGenerator::CreateChromaGenerator(kDefaultWidth,
1741 kDefaultHeight));
perkja49cbd32016-09-16 07:53:41 -07001742 test::FrameForwarder forwarder;
perkj803d97f2016-11-01 11:45:46 -07001743 video_send_stream_->SetSource(
1744 &forwarder, VideoSendStream::DegradationPreference::kBalanced);
perkja49cbd32016-09-16 07:53:41 -07001745 forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001746
Peter Boström5811a392015-12-10 13:02:50 +01001747 EXPECT_TRUE(post_encode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001748 << "Timed out while waiting for send-side encoded-frame callback.";
1749
Peter Boström5811a392015-12-10 13:02:50 +01001750 EXPECT_TRUE(pre_decode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001751 << "Timed out while waiting for pre-decode encoded-frame callback.";
1752
1753 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
1754
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001755 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001756
1757 sender_transport.StopSending();
1758 receiver_transport.StopSending();
1759
1760 DestroyStreams();
1761}
1762
1763TEST_F(EndToEndTest, ReceiveStreamSendsRemb) {
1764 class RembObserver : public test::EndToEndTest {
1765 public:
1766 RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
1767
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001768 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
danilchap3dc929e2016-11-02 08:21:59 -07001769 test::RtcpPacketParser parser;
1770 EXPECT_TRUE(parser.Parse(packet, length));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001771
danilchap3dc929e2016-11-02 08:21:59 -07001772 if (parser.remb()->num_packets() > 0) {
1773 EXPECT_EQ(kReceiverLocalVideoSsrc, parser.remb()->sender_ssrc());
1774 EXPECT_LT(0U, parser.remb()->bitrate_bps());
1775 EXPECT_EQ(1U, parser.remb()->ssrcs().size());
1776 EXPECT_EQ(kVideoSendSsrcs[0], parser.remb()->ssrcs()[0]);
Peter Boström5811a392015-12-10 13:02:50 +01001777 observation_complete_.Set();
danilchap3dc929e2016-11-02 08:21:59 -07001778 }
1779
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001780 return SEND_PACKET;
1781 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001782 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001783 EXPECT_TRUE(Wait()) << "Timed out while waiting for a "
1784 "receiver RTCP REMB packet to be "
1785 "sent.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001786 }
1787 } test;
1788
stefane74eef12016-01-08 06:47:13 -08001789 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001790}
1791
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001792TEST_F(EndToEndTest, VerifyBandwidthStats) {
stefanf116bd02015-10-27 08:29:42 -07001793 class RtcpObserver : public test::EndToEndTest {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001794 public:
1795 RtcpObserver()
1796 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001797 sender_call_(nullptr),
1798 receiver_call_(nullptr),
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001799 has_seen_pacer_delay_(false) {}
1800
stefanf116bd02015-10-27 08:29:42 -07001801 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001802 Call::Stats sender_stats = sender_call_->GetStats();
1803 Call::Stats receiver_stats = receiver_call_->GetStats();
1804 if (!has_seen_pacer_delay_)
1805 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
1806 if (sender_stats.send_bandwidth_bps > 0 &&
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001807 receiver_stats.recv_bandwidth_bps > 0 && has_seen_pacer_delay_) {
Peter Boström5811a392015-12-10 13:02:50 +01001808 observation_complete_.Set();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001809 }
stefanf116bd02015-10-27 08:29:42 -07001810 return SEND_PACKET;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001811 }
1812
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001813 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001814 sender_call_ = sender_call;
1815 receiver_call_ = receiver_call;
1816 }
1817
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001818 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001819 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
1820 "non-zero bandwidth stats.";
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001821 }
1822
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001823 private:
1824 Call* sender_call_;
1825 Call* receiver_call_;
1826 bool has_seen_pacer_delay_;
1827 } test;
1828
stefane74eef12016-01-08 06:47:13 -08001829 RunBaseTest(&test);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001830}
1831
stefan32f81542016-01-20 07:13:58 -08001832
1833// Verifies that it's possible to limit the send BWE by sending a REMB.
1834// This is verified by allowing the send BWE to ramp-up to >1000 kbps,
1835// then have the test generate a REMB of 500 kbps and verify that the send BWE
1836// is reduced to exactly 500 kbps. Then a REMB of 1000 kbps is generated and the
1837// test verifies that the send BWE ramps back up to exactly 1000 kbps.
1838TEST_F(EndToEndTest, RembWithSendSideBwe) {
1839 class BweObserver : public test::EndToEndTest {
1840 public:
1841 BweObserver()
1842 : EndToEndTest(kDefaultTimeoutMs),
1843 sender_call_(nullptr),
1844 clock_(Clock::GetRealTimeClock()),
1845 sender_ssrc_(0),
1846 remb_bitrate_bps_(1000000),
1847 receive_transport_(nullptr),
1848 event_(false, false),
1849 poller_thread_(&BitrateStatsPollingThread,
1850 this,
1851 "BitrateStatsPollingThread"),
Erik Språng737336d2016-07-29 12:59:36 +02001852 state_(kWaitForFirstRampUp),
1853 retransmission_rate_limiter_(clock_, 1000) {}
stefan32f81542016-01-20 07:13:58 -08001854
1855 ~BweObserver() {}
1856
nisseef8b61e2016-04-29 06:09:15 -07001857 test::PacketTransport* CreateReceiveTransport() override {
stefan32f81542016-01-20 07:13:58 -08001858 receive_transport_ = new test::PacketTransport(
1859 nullptr, this, test::PacketTransport::kReceiver,
1860 FakeNetworkPipe::Config());
1861 return receive_transport_;
1862 }
1863
1864 Call::Config GetSenderCallConfig() override {
skvlad11a9cbf2016-10-07 11:53:05 -07001865 Call::Config config(&event_log_);
stefan32f81542016-01-20 07:13:58 -08001866 // Set a high start bitrate to reduce the test completion time.
1867 config.bitrate_config.start_bitrate_bps = remb_bitrate_bps_;
1868 return config;
1869 }
1870
1871 void ModifyVideoConfigs(
1872 VideoSendStream::Config* send_config,
1873 std::vector<VideoReceiveStream::Config>* receive_configs,
1874 VideoEncoderConfig* encoder_config) override {
1875 ASSERT_EQ(1u, send_config->rtp.ssrcs.size());
1876 send_config->rtp.extensions.clear();
1877 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001878 RtpExtension(RtpExtension::kTransportSequenceNumberUri,
stefan32f81542016-01-20 07:13:58 -08001879 test::kTransportSequenceNumberExtensionId));
1880 sender_ssrc_ = send_config->rtp.ssrcs[0];
1881
perkjfa10b552016-10-02 23:45:26 -07001882 encoder_config->max_bitrate_bps = 2000000;
stefan32f81542016-01-20 07:13:58 -08001883
1884 ASSERT_EQ(1u, receive_configs->size());
1885 (*receive_configs)[0].rtp.remb = false;
1886 (*receive_configs)[0].rtp.transport_cc = true;
1887 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1888 RtpRtcp::Configuration config;
1889 config.receiver_only = true;
1890 config.clock = clock_;
1891 config.outgoing_transport = receive_transport_;
Erik Språng737336d2016-07-29 12:59:36 +02001892 config.retransmission_rate_limiter = &retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08001893 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
1894 rtp_rtcp_->SetRemoteSSRC((*receive_configs)[0].rtp.remote_ssrc);
1895 rtp_rtcp_->SetSSRC((*receive_configs)[0].rtp.local_ssrc);
1896 rtp_rtcp_->SetREMBStatus(true);
1897 rtp_rtcp_->SetSendingStatus(true);
1898 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
1899 }
1900
1901 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1902 sender_call_ = sender_call;
1903 }
1904
1905 static bool BitrateStatsPollingThread(void* obj) {
1906 return static_cast<BweObserver*>(obj)->PollStats();
1907 }
1908
1909 bool PollStats() {
1910 if (sender_call_) {
1911 Call::Stats stats = sender_call_->GetStats();
1912 switch (state_) {
1913 case kWaitForFirstRampUp:
1914 if (stats.send_bandwidth_bps >= remb_bitrate_bps_) {
1915 state_ = kWaitForRemb;
1916 remb_bitrate_bps_ /= 2;
1917 rtp_rtcp_->SetREMBData(
1918 remb_bitrate_bps_,
1919 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
1920 rtp_rtcp_->SendRTCP(kRtcpRr);
1921 }
1922 break;
1923
1924 case kWaitForRemb:
1925 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
1926 state_ = kWaitForSecondRampUp;
1927 remb_bitrate_bps_ *= 2;
1928 rtp_rtcp_->SetREMBData(
1929 remb_bitrate_bps_,
1930 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
1931 rtp_rtcp_->SendRTCP(kRtcpRr);
1932 }
1933 break;
1934
1935 case kWaitForSecondRampUp:
1936 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
1937 observation_complete_.Set();
1938 }
1939 break;
1940 }
1941 }
1942
1943 return !event_.Wait(1000);
1944 }
1945
1946 void PerformTest() override {
1947 poller_thread_.Start();
1948 EXPECT_TRUE(Wait())
1949 << "Timed out while waiting for bitrate to change according to REMB.";
1950 poller_thread_.Stop();
1951 }
1952
1953 private:
1954 enum TestState { kWaitForFirstRampUp, kWaitForRemb, kWaitForSecondRampUp };
1955
1956 Call* sender_call_;
1957 Clock* const clock_;
1958 uint32_t sender_ssrc_;
1959 int remb_bitrate_bps_;
kwiberg27f982b2016-03-01 11:52:33 -08001960 std::unique_ptr<RtpRtcp> rtp_rtcp_;
stefan32f81542016-01-20 07:13:58 -08001961 test::PacketTransport* receive_transport_;
1962 rtc::Event event_;
1963 rtc::PlatformThread poller_thread_;
1964 TestState state_;
Erik Språng737336d2016-07-29 12:59:36 +02001965 RateLimiter retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08001966 } test;
1967
1968 RunBaseTest(&test);
1969}
1970
Åsa Persson352b2d72015-04-15 18:00:40 +02001971TEST_F(EndToEndTest, VerifyNackStats) {
1972 static const int kPacketNumberToDrop = 200;
1973 class NackObserver : public test::EndToEndTest {
1974 public:
1975 NackObserver()
1976 : EndToEndTest(kLongTimeoutMs),
1977 sent_rtp_packets_(0),
1978 dropped_rtp_packet_(0),
1979 dropped_rtp_packet_requested_(false),
1980 send_stream_(nullptr),
1981 start_runtime_ms_(-1) {}
1982
1983 private:
1984 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08001985 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02001986 if (++sent_rtp_packets_ == kPacketNumberToDrop) {
kwiberg27f982b2016-03-01 11:52:33 -08001987 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
Åsa Persson352b2d72015-04-15 18:00:40 +02001988 RTPHeader header;
1989 EXPECT_TRUE(parser->Parse(packet, length, &header));
1990 dropped_rtp_packet_ = header.sequenceNumber;
1991 return DROP_PACKET;
1992 }
1993 VerifyStats();
1994 return SEND_PACKET;
1995 }
1996
1997 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08001998 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02001999 test::RtcpPacketParser rtcp_parser;
2000 rtcp_parser.Parse(packet, length);
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02002001 const std::vector<uint16_t>& nacks = rtcp_parser.nack()->packet_ids();
Åsa Persson352b2d72015-04-15 18:00:40 +02002002 if (!nacks.empty() && std::find(
2003 nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) {
2004 dropped_rtp_packet_requested_ = true;
2005 }
2006 return SEND_PACKET;
2007 }
2008
stefan608213e2015-11-01 14:56:10 -08002009 void VerifyStats() EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002010 if (!dropped_rtp_packet_requested_)
2011 return;
2012 int send_stream_nack_packets = 0;
2013 int receive_stream_nack_packets = 0;
2014 VideoSendStream::Stats stats = send_stream_->GetStats();
2015 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
2016 stats.substreams.begin(); it != stats.substreams.end(); ++it) {
2017 const VideoSendStream::StreamStats& stream_stats = it->second;
2018 send_stream_nack_packets +=
2019 stream_stats.rtcp_packet_type_counts.nack_packets;
2020 }
2021 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2022 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2023 receive_stream_nack_packets +=
2024 stats.rtcp_packet_type_counts.nack_packets;
2025 }
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002026 if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002027 // NACK packet sent on receive stream and received on sent stream.
2028 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002029 observation_complete_.Set();
Åsa Persson352b2d72015-04-15 18:00:40 +02002030 }
2031 }
2032
2033 bool MinMetricRunTimePassed() {
2034 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2035 if (start_runtime_ms_ == -1) {
2036 start_runtime_ms_ = now;
2037 return false;
2038 }
2039 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2040 return elapsed_sec > metrics::kMinRunTimeInSeconds;
2041 }
2042
stefanff483612015-12-21 03:14:00 -08002043 void ModifyVideoConfigs(
2044 VideoSendStream::Config* send_config,
2045 std::vector<VideoReceiveStream::Config>* receive_configs,
2046 VideoEncoderConfig* encoder_config) override {
Åsa Persson352b2d72015-04-15 18:00:40 +02002047 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2048 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sakal55d932b2016-09-30 06:19:08 -07002049 (*receive_configs)[0].renderer = &fake_renderer_;
Åsa Persson352b2d72015-04-15 18:00:40 +02002050 }
2051
stefanff483612015-12-21 03:14:00 -08002052 void OnVideoStreamsCreated(
Åsa Persson352b2d72015-04-15 18:00:40 +02002053 VideoSendStream* send_stream,
2054 const std::vector<VideoReceiveStream*>& receive_streams) override {
2055 send_stream_ = send_stream;
2056 receive_streams_ = receive_streams;
2057 }
2058
2059 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002060 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson352b2d72015-04-15 18:00:40 +02002061 }
2062
sakal55d932b2016-09-30 06:19:08 -07002063 test::FakeVideoRenderer fake_renderer_;
stefan608213e2015-11-01 14:56:10 -08002064 rtc::CriticalSection crit_;
Åsa Persson352b2d72015-04-15 18:00:40 +02002065 uint64_t sent_rtp_packets_;
stefan608213e2015-11-01 14:56:10 -08002066 uint16_t dropped_rtp_packet_ GUARDED_BY(&crit_);
2067 bool dropped_rtp_packet_requested_ GUARDED_BY(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002068 std::vector<VideoReceiveStream*> receive_streams_;
2069 VideoSendStream* send_stream_;
2070 int64_t start_runtime_ms_;
2071 } test;
2072
asapersson01d70a32016-05-20 06:29:46 -07002073 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002074 RunBaseTest(&test);
Åsa Persson352b2d72015-04-15 18:00:40 +02002075
asapersson01d70a32016-05-20 06:29:46 -07002076 EXPECT_EQ(
2077 1, metrics::NumSamples("WebRTC.Video.UniqueNackRequestsSentInPercent"));
2078 EXPECT_EQ(1, metrics::NumSamples(
2079 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
2080 EXPECT_GT(metrics::MinSample("WebRTC.Video.NackPacketsSentPerMinute"), 0);
Åsa Persson352b2d72015-04-15 18:00:40 +02002081}
2082
sprangb4a1ae52015-12-03 08:10:08 -08002083void EndToEndTest::VerifyHistogramStats(bool use_rtx,
2084 bool use_red,
2085 bool screenshare) {
tommi2e82f382016-06-21 00:26:43 -07002086 class StatsObserver : public test::EndToEndTest,
2087 public rtc::VideoSinkInterface<VideoFrame> {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002088 public:
sprangb4a1ae52015-12-03 08:10:08 -08002089 StatsObserver(bool use_rtx, bool use_red, bool screenshare)
Åsa Persson3c391cb2015-04-27 10:09:49 +02002090 : EndToEndTest(kLongTimeoutMs),
2091 use_rtx_(use_rtx),
2092 use_red_(use_red),
sprangb4a1ae52015-12-03 08:10:08 -08002093 screenshare_(screenshare),
Peter Boström39593972016-02-15 11:27:15 +01002094 // This test uses NACK, so to send FEC we can't use a fake encoder.
2095 vp8_encoder_(
2096 use_red ? VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)
2097 : nullptr),
Åsa Persson3c391cb2015-04-27 10:09:49 +02002098 sender_call_(nullptr),
2099 receiver_call_(nullptr),
asapersson1394c7b2016-10-18 11:50:50 -07002100 start_runtime_ms_(-1),
2101 num_frames_received_(0) {}
Åsa Persson3c391cb2015-04-27 10:09:49 +02002102
2103 private:
asapersson1394c7b2016-10-18 11:50:50 -07002104 void OnFrame(const VideoFrame& video_frame) override {
2105 // The RTT is needed to estimate |ntp_time_ms| which is used by
2106 // end-to-end delay stats. Therefore, start counting received frames once
2107 // |ntp_time_ms| is valid.
2108 if (video_frame.ntp_time_ms() > 0 &&
2109 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() >=
2110 video_frame.ntp_time_ms()) {
2111 rtc::CritScope lock(&crit_);
2112 ++num_frames_received_;
2113 }
2114 }
tommi2e82f382016-06-21 00:26:43 -07002115
Åsa Persson3c391cb2015-04-27 10:09:49 +02002116 Action OnSendRtp(const uint8_t* packet, size_t length) override {
asapersson1394c7b2016-10-18 11:50:50 -07002117 if (MinMetricRunTimePassed() && MinNumberOfFramesReceived())
Peter Boström5811a392015-12-10 13:02:50 +01002118 observation_complete_.Set();
Åsa Persson3c391cb2015-04-27 10:09:49 +02002119
stefanf116bd02015-10-27 08:29:42 -07002120 return SEND_PACKET;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002121 }
2122
2123 bool MinMetricRunTimePassed() {
2124 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2125 if (start_runtime_ms_ == -1) {
2126 start_runtime_ms_ = now;
2127 return false;
2128 }
2129 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2130 return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
2131 }
2132
asapersson1394c7b2016-10-18 11:50:50 -07002133 bool MinNumberOfFramesReceived() const {
2134 const int kMinRequiredHistogramSamples = 200;
2135 rtc::CritScope lock(&crit_);
2136 return num_frames_received_ > kMinRequiredHistogramSamples;
2137 }
2138
stefanff483612015-12-21 03:14:00 -08002139 void ModifyVideoConfigs(
2140 VideoSendStream::Config* send_config,
2141 std::vector<VideoReceiveStream::Config>* receive_configs,
2142 VideoEncoderConfig* encoder_config) override {
stefana23fc622016-07-28 07:56:38 -07002143 static const int kExtensionId = 8;
2144 send_config->rtp.extensions.push_back(RtpExtension(
2145 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
2146 (*receive_configs)[0].rtp.extensions.push_back(RtpExtension(
2147 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002148 // NACK
2149 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2150 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
tommi2e82f382016-06-21 00:26:43 -07002151 (*receive_configs)[0].renderer = this;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002152 // FEC
2153 if (use_red_) {
brandtrb5f2c3f2016-10-04 23:28:39 -07002154 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
2155 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
Peter Boström39593972016-02-15 11:27:15 +01002156 send_config->encoder_settings.encoder = vp8_encoder_.get();
2157 send_config->encoder_settings.payload_name = "VP8";
2158 (*receive_configs)[0].decoders[0].payload_name = "VP8";
brandtrb5f2c3f2016-10-04 23:28:39 -07002159 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
2160 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type =
2161 kUlpfecPayloadType;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002162 }
2163 // RTX
2164 if (use_rtx_) {
2165 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
2166 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002167 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002168 kSendRtxSsrcs[0];
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002169 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002170 kSendRtxPayloadType;
2171 }
asapersson1490f7a2016-09-23 02:09:46 -07002172 // RTT needed for RemoteNtpTimeEstimator for the receive stream.
2173 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = true;
sprangb4a1ae52015-12-03 08:10:08 -08002174 encoder_config->content_type =
2175 screenshare_ ? VideoEncoderConfig::ContentType::kScreen
2176 : VideoEncoderConfig::ContentType::kRealtimeVideo;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002177 }
2178
2179 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2180 sender_call_ = sender_call;
2181 receiver_call_ = receiver_call;
2182 }
2183
Åsa Persson3c391cb2015-04-27 10:09:49 +02002184 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002185 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson3c391cb2015-04-27 10:09:49 +02002186 }
2187
asapersson1394c7b2016-10-18 11:50:50 -07002188 rtc::CriticalSection crit_;
sprangb4a1ae52015-12-03 08:10:08 -08002189 const bool use_rtx_;
2190 const bool use_red_;
2191 const bool screenshare_;
kwiberg27f982b2016-03-01 11:52:33 -08002192 const std::unique_ptr<VideoEncoder> vp8_encoder_;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002193 Call* sender_call_;
2194 Call* receiver_call_;
2195 int64_t start_runtime_ms_;
asapersson1394c7b2016-10-18 11:50:50 -07002196 int num_frames_received_ GUARDED_BY(&crit_);
sprangb4a1ae52015-12-03 08:10:08 -08002197 } test(use_rtx, use_red, screenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002198
asapersson01d70a32016-05-20 06:29:46 -07002199 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002200 RunBaseTest(&test);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002201
stefan91d92602015-11-11 10:13:02 -08002202 // Delete the call for Call stats to be reported.
stefan18adf0a2015-11-17 06:24:56 -08002203 sender_call_.reset();
stefan91d92602015-11-11 10:13:02 -08002204 receiver_call_.reset();
2205
sprangb4a1ae52015-12-03 08:10:08 -08002206 std::string video_prefix =
2207 screenshare ? "WebRTC.Video.Screenshare." : "WebRTC.Video.";
2208
Åsa Persson3c391cb2015-04-27 10:09:49 +02002209 // Verify that stats have been updated once.
asapersson4374a092016-07-27 00:39:09 -07002210 EXPECT_EQ(2, metrics::NumSamples("WebRTC.Call.LifetimeInSeconds"));
asapersson01d70a32016-05-20 06:29:46 -07002211 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
2212 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.RtcpBitrateReceivedInBps"));
2213 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.BitrateReceivedInKbps"));
2214 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.EstimatedSendBitrateInKbps"));
2215 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.PacerBitrateInKbps"));
2216
asapersson4374a092016-07-27 00:39:09 -07002217 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
2218 EXPECT_EQ(1,
2219 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
2220
asapersson01d70a32016-05-20 06:29:46 -07002221 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
stefan91d92602015-11-11 10:13:02 -08002222 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002223 metrics::NumSamples(video_prefix + "NackPacketsReceivedPerMinute"));
2224 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
asaperssond89920b2015-07-22 06:52:00 -07002225 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002226 metrics::NumSamples(video_prefix + "FirPacketsReceivedPerMinute"));
2227 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
sprangb4a1ae52015-12-03 08:10:08 -08002228 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002229 metrics::NumSamples(video_prefix + "PliPacketsReceivedPerMinute"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002230
asapersson01d70a32016-05-20 06:29:46 -07002231 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "KeyFramesSentInPermille"));
2232 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
2233
2234 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentPacketsLostInPercent"));
2235 EXPECT_EQ(1,
2236 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
2237
2238 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputWidthInPixels"));
2239 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputHeightInPixels"));
2240 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentWidthInPixels"));
2241 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentHeightInPixels"));
2242 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
2243 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
2244
perkjfa10b552016-10-02 23:45:26 -07002245 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputWidthInPixels",
2246 kDefaultWidth));
2247 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputHeightInPixels",
2248 kDefaultHeight));
2249 EXPECT_EQ(
2250 1, metrics::NumEvents(video_prefix + "SentWidthInPixels", kDefaultWidth));
2251 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "SentHeightInPixels",
2252 kDefaultHeight));
2253 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedWidthInPixels",
2254 kDefaultWidth));
2255 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedHeightInPixels",
2256 kDefaultHeight));
asapersson01d70a32016-05-20 06:29:46 -07002257
2258 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputFramesPerSecond"));
2259 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentFramesPerSecond"));
2260 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
2261 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
2262
2263 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
2264 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
2265 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
2266 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
2267
asapersson1490f7a2016-09-23 02:09:46 -07002268 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.EndToEndDelayInMs"));
asapersson01d70a32016-05-20 06:29:46 -07002269 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
2270
2271 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EncodeTimeInMs"));
2272 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
2273
2274 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "BitrateSentInKbps"));
2275 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateReceivedInKbps"));
2276 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "MediaBitrateSentInKbps"));
2277 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateReceivedInKbps"));
2278 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PaddingBitrateSentInKbps"));
2279 EXPECT_EQ(1,
2280 metrics::NumSamples("WebRTC.Video.PaddingBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002281 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002282 1, metrics::NumSamples(video_prefix + "RetransmittedBitrateSentInKbps"));
2283 EXPECT_EQ(1, metrics::NumSamples(
2284 "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002285
asapersson01d70a32016-05-20 06:29:46 -07002286 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendDelayInMs"));
2287 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayInMs"));
2288 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayMaxInMs"));
asapersson6f14be82015-11-16 00:40:49 -08002289
Åsa Persson3c391cb2015-04-27 10:09:49 +02002290 int num_rtx_samples = use_rtx ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002291 EXPECT_EQ(num_rtx_samples,
2292 metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2293 EXPECT_EQ(num_rtx_samples,
2294 metrics::NumSamples("WebRTC.Video.RtxBitrateReceivedInKbps"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002295
2296 int num_red_samples = use_red ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002297 EXPECT_EQ(num_red_samples,
2298 metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2299 EXPECT_EQ(num_red_samples,
2300 metrics::NumSamples("WebRTC.Video.FecBitrateReceivedInKbps"));
2301 EXPECT_EQ(num_red_samples,
2302 metrics::NumSamples("WebRTC.Video.ReceivedFecPacketsInPercent"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002303}
2304
2305TEST_F(EndToEndTest, VerifyHistogramStatsWithRtx) {
2306 const bool kEnabledRtx = true;
2307 const bool kEnabledRed = false;
sprangb4a1ae52015-12-03 08:10:08 -08002308 const bool kScreenshare = false;
2309 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002310}
2311
2312TEST_F(EndToEndTest, VerifyHistogramStatsWithRed) {
2313 const bool kEnabledRtx = false;
2314 const bool kEnabledRed = true;
sprangb4a1ae52015-12-03 08:10:08 -08002315 const bool kScreenshare = false;
2316 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
2317}
2318
2319TEST_F(EndToEndTest, VerifyHistogramStatsWithScreenshare) {
2320 const bool kEnabledRtx = false;
2321 const bool kEnabledRed = false;
2322 const bool kScreenshare = true;
2323 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002324}
2325
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002326void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
2327 static const int kNumRtcpReportPacketsToObserve = 5;
2328 class RtcpXrObserver : public test::EndToEndTest {
2329 public:
2330 explicit RtcpXrObserver(bool enable_rrtr)
2331 : EndToEndTest(kDefaultTimeoutMs),
2332 enable_rrtr_(enable_rrtr),
2333 sent_rtcp_sr_(0),
2334 sent_rtcp_rr_(0),
2335 sent_rtcp_rrtr_(0),
2336 sent_rtcp_dlrr_(0) {}
2337
2338 private:
2339 // Receive stream should send RR packets (and RRTR packets if enabled).
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002340 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002341 rtc::CritScope lock(&crit_);
danilchap3dc929e2016-11-02 08:21:59 -07002342 test::RtcpPacketParser parser;
2343 EXPECT_TRUE(parser.Parse(packet, length));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002344
danilchap3dc929e2016-11-02 08:21:59 -07002345 sent_rtcp_rr_ += parser.receiver_report()->num_packets();
2346 EXPECT_EQ(0, parser.sender_report()->num_packets());
2347 EXPECT_GE(1, parser.xr()->num_packets());
2348 if (parser.xr()->num_packets() > 0) {
2349 if (parser.xr()->rrtr())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002350 ++sent_rtcp_rrtr_;
danilchap3dc929e2016-11-02 08:21:59 -07002351 EXPECT_FALSE(parser.xr()->dlrr());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002352 }
danilchap3dc929e2016-11-02 08:21:59 -07002353
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002354 return SEND_PACKET;
2355 }
2356 // Send stream should send SR packets (and DLRR packets if enabled).
nisseef8b61e2016-04-29 06:09:15 -07002357 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002358 rtc::CritScope lock(&crit_);
danilchap3dc929e2016-11-02 08:21:59 -07002359 test::RtcpPacketParser parser;
2360 EXPECT_TRUE(parser.Parse(packet, length));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002361
danilchap3dc929e2016-11-02 08:21:59 -07002362 sent_rtcp_sr_ += parser.sender_report()->num_packets();
2363 EXPECT_GE(1, parser.xr()->num_packets());
2364 if (parser.xr()->num_packets() > 0) {
2365 EXPECT_FALSE(parser.xr()->rrtr());
2366 if (parser.xr()->dlrr())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002367 ++sent_rtcp_dlrr_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002368 }
danilchap3dc929e2016-11-02 08:21:59 -07002369
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002370 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
2371 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve) {
2372 if (enable_rrtr_) {
danilchap3dc929e2016-11-02 08:21:59 -07002373 EXPECT_LT(0, sent_rtcp_rrtr_);
2374 EXPECT_LT(0, sent_rtcp_dlrr_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002375 } else {
2376 EXPECT_EQ(0, sent_rtcp_rrtr_);
2377 EXPECT_EQ(0, sent_rtcp_dlrr_);
2378 }
Peter Boström5811a392015-12-10 13:02:50 +01002379 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002380 }
2381 return SEND_PACKET;
2382 }
2383
stefanff483612015-12-21 03:14:00 -08002384 void ModifyVideoConfigs(
2385 VideoSendStream::Config* send_config,
2386 std::vector<VideoReceiveStream::Config>* receive_configs,
2387 VideoEncoderConfig* encoder_config) override {
pbosda903ea2015-10-02 02:36:56 -07002388 (*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002389 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
2390 enable_rrtr_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002391 }
2392
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002393 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002394 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002395 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
2396 }
2397
stefan608213e2015-11-01 14:56:10 -08002398 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002399 bool enable_rrtr_;
2400 int sent_rtcp_sr_;
stefan608213e2015-11-01 14:56:10 -08002401 int sent_rtcp_rr_ GUARDED_BY(&crit_);
2402 int sent_rtcp_rrtr_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002403 int sent_rtcp_dlrr_;
2404 } test(enable_rrtr);
2405
stefane74eef12016-01-08 06:47:13 -08002406 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002407}
2408
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002409void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
2410 bool send_single_ssrc_first) {
2411 class SendsSetSsrcs : public test::EndToEndTest {
2412 public:
2413 SendsSetSsrcs(const uint32_t* ssrcs,
2414 size_t num_ssrcs,
2415 bool send_single_ssrc_first)
2416 : EndToEndTest(kDefaultTimeoutMs),
2417 num_ssrcs_(num_ssrcs),
2418 send_single_ssrc_first_(send_single_ssrc_first),
2419 ssrcs_to_observe_(num_ssrcs),
sprang867fb522015-08-03 04:38:41 -07002420 expect_single_ssrc_(send_single_ssrc_first),
2421 send_stream_(nullptr) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002422 for (size_t i = 0; i < num_ssrcs; ++i)
2423 valid_ssrcs_[ssrcs[i]] = true;
2424 }
2425
2426 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002427 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002428 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002429 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002430
2431 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
2432 << "Received unknown SSRC: " << header.ssrc;
2433
2434 if (!valid_ssrcs_[header.ssrc])
Peter Boström5811a392015-12-10 13:02:50 +01002435 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002436
2437 if (!is_observed_[header.ssrc]) {
2438 is_observed_[header.ssrc] = true;
2439 --ssrcs_to_observe_;
2440 if (expect_single_ssrc_) {
2441 expect_single_ssrc_ = false;
Peter Boström5811a392015-12-10 13:02:50 +01002442 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002443 }
2444 }
2445
2446 if (ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002447 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002448
2449 return SEND_PACKET;
2450 }
2451
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002452 size_t GetNumVideoStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002453
perkjfa10b552016-10-02 23:45:26 -07002454 // This test use other VideoStream settings than the the default settings
2455 // implemented in DefaultVideoStreamFactory. Therefore this test implement
2456 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
2457 // in ModifyVideoConfigs.
2458 class VideoStreamFactory
2459 : public VideoEncoderConfig::VideoStreamFactoryInterface {
2460 public:
2461 VideoStreamFactory() {}
2462
2463 private:
2464 std::vector<VideoStream> CreateEncoderStreams(
2465 int width,
2466 int height,
2467 const VideoEncoderConfig& encoder_config) override {
2468 std::vector<VideoStream> streams =
2469 test::CreateVideoStreams(width, height, encoder_config);
2470 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
2471 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
2472 streams[i].min_bitrate_bps = 10000;
2473 streams[i].target_bitrate_bps = 15000;
2474 streams[i].max_bitrate_bps = 20000;
2475 }
2476 return streams;
2477 }
2478 };
2479
stefanff483612015-12-21 03:14:00 -08002480 void ModifyVideoConfigs(
2481 VideoSendStream::Config* send_config,
2482 std::vector<VideoReceiveStream::Config>* receive_configs,
2483 VideoEncoderConfig* encoder_config) override {
perkjfa10b552016-10-02 23:45:26 -07002484 encoder_config->video_stream_factory =
2485 new rtc::RefCountedObject<VideoStreamFactory>();
perkj26091b12016-09-01 01:17:40 -07002486 video_encoder_config_all_streams_ = encoder_config->Copy();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002487 if (send_single_ssrc_first_)
perkjfa10b552016-10-02 23:45:26 -07002488 encoder_config->number_of_streams = 1;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002489 }
2490
stefanff483612015-12-21 03:14:00 -08002491 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002492 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002493 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002494 send_stream_ = send_stream;
2495 }
2496
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002497 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002498 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2499 << (send_single_ssrc_first_ ? "first SSRC."
2500 : "SSRCs.");
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002501
2502 if (send_single_ssrc_first_) {
2503 // Set full simulcast and continue with the rest of the SSRCs.
stefanff483612015-12-21 03:14:00 -08002504 send_stream_->ReconfigureVideoEncoder(
perkj26091b12016-09-01 01:17:40 -07002505 std::move(video_encoder_config_all_streams_));
Peter Boström5811a392015-12-10 13:02:50 +01002506 EXPECT_TRUE(Wait()) << "Timed out while waiting on additional SSRCs.";
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002507 }
2508 }
2509
2510 private:
2511 std::map<uint32_t, bool> valid_ssrcs_;
2512 std::map<uint32_t, bool> is_observed_;
2513
2514 const size_t num_ssrcs_;
2515 const bool send_single_ssrc_first_;
2516
2517 size_t ssrcs_to_observe_;
2518 bool expect_single_ssrc_;
2519
2520 VideoSendStream* send_stream_;
stefanff483612015-12-21 03:14:00 -08002521 VideoEncoderConfig video_encoder_config_all_streams_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002522 } test(kVideoSendSsrcs, num_ssrcs, send_single_ssrc_first);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002523
stefane74eef12016-01-08 06:47:13 -08002524 RunBaseTest(&test);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002525}
2526
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002527TEST_F(EndToEndTest, ReportsSetEncoderRates) {
2528 class EncoderRateStatsTest : public test::EndToEndTest,
2529 public test::FakeEncoder {
2530 public:
2531 EncoderRateStatsTest()
2532 : EndToEndTest(kDefaultTimeoutMs),
sprang867fb522015-08-03 04:38:41 -07002533 FakeEncoder(Clock::GetRealTimeClock()),
2534 send_stream_(nullptr),
2535 bitrate_kbps_(0) {}
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002536
stefanff483612015-12-21 03:14:00 -08002537 void OnVideoStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002538 VideoSendStream* send_stream,
2539 const std::vector<VideoReceiveStream*>& receive_streams) override {
2540 send_stream_ = send_stream;
2541 }
2542
stefanff483612015-12-21 03:14:00 -08002543 void ModifyVideoConfigs(
2544 VideoSendStream::Config* send_config,
2545 std::vector<VideoReceiveStream::Config>* receive_configs,
2546 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002547 send_config->encoder_settings.encoder = this;
perkjfa10b552016-10-02 23:45:26 -07002548 RTC_DCHECK_EQ(1u, encoder_config->number_of_streams);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002549 }
2550
sprang1369c832016-11-10 08:30:33 -08002551 int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002552 // Make sure not to trigger on any default zero bitrates.
sprang1369c832016-11-10 08:30:33 -08002553 if (new_target_bitrate == 0)
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002554 return 0;
Peter Boströmf2f82832015-05-01 13:00:41 +02002555 rtc::CritScope lock(&crit_);
sprang1369c832016-11-10 08:30:33 -08002556 bitrate_kbps_ = new_target_bitrate;
Peter Boström5811a392015-12-10 13:02:50 +01002557 observation_complete_.Set();
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002558 return 0;
2559 }
2560
2561 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002562 ASSERT_TRUE(Wait())
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002563 << "Timed out while waiting for encoder SetRates() call.";
perkjf5b2e512016-07-05 08:34:04 -07002564 WaitForEncoderTargetBitrateMatchStats();
2565 send_stream_->Stop();
2566 WaitForStatsReportZeroTargetBitrate();
2567 send_stream_->Start();
2568 WaitForEncoderTargetBitrateMatchStats();
2569 }
2570
2571 void WaitForEncoderTargetBitrateMatchStats() {
Peter Boström5811a392015-12-10 13:02:50 +01002572 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002573 VideoSendStream::Stats stats = send_stream_->GetStats();
2574 {
Peter Boströmf2f82832015-05-01 13:00:41 +02002575 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002576 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
2577 static_cast<int>(bitrate_kbps_)) {
2578 return;
2579 }
2580 }
2581 SleepMs(1);
2582 }
2583 FAIL()
2584 << "Timed out waiting for stats reporting the currently set bitrate.";
2585 }
2586
perkjf5b2e512016-07-05 08:34:04 -07002587 void WaitForStatsReportZeroTargetBitrate() {
2588 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
2589 if (send_stream_->GetStats().target_media_bitrate_bps == 0) {
2590 return;
2591 }
2592 SleepMs(1);
2593 }
2594 FAIL() << "Timed out waiting for stats reporting zero bitrate.";
2595 }
2596
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002597 private:
stefanf116bd02015-10-27 08:29:42 -07002598 rtc::CriticalSection crit_;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002599 VideoSendStream* send_stream_;
2600 uint32_t bitrate_kbps_ GUARDED_BY(crit_);
2601 } test;
2602
stefane74eef12016-01-08 06:47:13 -08002603 RunBaseTest(&test);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002604}
2605
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002606TEST_F(EndToEndTest, GetStats) {
2607 static const int kStartBitrateBps = 3000000;
Peter Boströmdef398832015-05-27 17:59:11 +02002608 static const int kExpectedRenderDelayMs = 20;
tommi2e82f382016-06-21 00:26:43 -07002609
2610 class ReceiveStreamRenderer : public rtc::VideoSinkInterface<VideoFrame> {
2611 public:
2612 ReceiveStreamRenderer() {}
2613
2614 private:
2615 void OnFrame(const VideoFrame& video_frame) override {}
2616 };
2617
nissed30a1112016-04-18 05:15:22 -07002618 class StatsObserver : public test::EndToEndTest,
2619 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002620 public:
stefanf116bd02015-10-27 08:29:42 -07002621 StatsObserver()
2622 : EndToEndTest(kLongTimeoutMs),
Peter Boströmc6e16e32016-02-05 14:15:53 +01002623 encoder_(Clock::GetRealTimeClock(), 10),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002624 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002625 expected_send_ssrcs_(),
Peter Boström5811a392015-12-10 13:02:50 +01002626 check_stats_event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002627
2628 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002629 Action OnSendRtp(const uint8_t* packet, size_t length) override {
sprangcd349d92016-07-13 09:11:28 -07002630 // Drop every 25th packet => 4% loss.
2631 static const int kPacketLossFrac = 25;
2632 RTPHeader header;
2633 RtpUtility::RtpHeaderParser parser(packet, length);
2634 if (parser.Parse(&header) &&
2635 expected_send_ssrcs_.find(header.ssrc) !=
2636 expected_send_ssrcs_.end() &&
2637 header.sequenceNumber % kPacketLossFrac == 0) {
2638 return DROP_PACKET;
2639 }
Peter Boström5811a392015-12-10 13:02:50 +01002640 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002641 return SEND_PACKET;
2642 }
2643
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002644 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002645 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002646 return SEND_PACKET;
2647 }
2648
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002649 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002650 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002651 return SEND_PACKET;
2652 }
2653
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002654 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002655 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002656 return SEND_PACKET;
2657 }
2658
nissed30a1112016-04-18 05:15:22 -07002659 void OnFrame(const VideoFrame& video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002660 // Ensure that we have at least 5ms send side delay.
nissed30a1112016-04-18 05:15:22 -07002661 SleepMs(5);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002662 }
2663
2664 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002665 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2666 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2667 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002668
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002669 // Make sure all fields have been populated.
2670 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
2671 // always filled for all receivers.
2672 receive_stats_filled_["IncomingRate"] |=
2673 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002674
Peter Boströmb7d9a972015-12-18 16:01:11 +01002675 send_stats_filled_["DecoderImplementationName"] |=
2676 stats.decoder_implementation_name ==
2677 test::FakeDecoder::kImplementationName;
Peter Boströmdef398832015-05-27 17:59:11 +02002678 receive_stats_filled_["RenderDelayAsHighAsExpected"] |=
2679 stats.render_delay_ms >= kExpectedRenderDelayMs;
2680
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002681 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002682
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002683 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002684
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002685 receive_stats_filled_["StatisticsUpdated"] |=
2686 stats.rtcp_stats.cumulative_lost != 0 ||
2687 stats.rtcp_stats.extended_max_sequence_number != 0 ||
2688 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002689
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002690 receive_stats_filled_["DataCountersUpdated"] |=
2691 stats.rtp_stats.transmitted.payload_bytes != 0 ||
2692 stats.rtp_stats.fec.packets != 0 ||
2693 stats.rtp_stats.transmitted.header_bytes != 0 ||
2694 stats.rtp_stats.transmitted.packets != 0 ||
2695 stats.rtp_stats.transmitted.padding_bytes != 0 ||
2696 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002697
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002698 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002699 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002700
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002701 receive_stats_filled_["FrameCounts"] |=
2702 stats.frame_counts.key_frames != 0 ||
2703 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002704
pbosbb36fdf2015-07-09 07:48:14 -07002705 receive_stats_filled_["CName"] |= !stats.c_name.empty();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002706
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002707 receive_stats_filled_["RtcpPacketTypeCount"] |=
2708 stats.rtcp_packet_type_counts.fir_packets != 0 ||
2709 stats.rtcp_packet_type_counts.nack_packets != 0 ||
2710 stats.rtcp_packet_type_counts.pli_packets != 0 ||
2711 stats.rtcp_packet_type_counts.nack_requests != 0 ||
2712 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbosf42376c2015-08-28 07:35:32 -07002713
2714 assert(stats.current_payload_type == -1 ||
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002715 stats.current_payload_type == kFakeVideoSendPayloadType);
pbosf42376c2015-08-28 07:35:32 -07002716 receive_stats_filled_["IncomingPayloadType"] |=
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002717 stats.current_payload_type == kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002718 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002719
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002720 return AllStatsFilled(receive_stats_filled_);
2721 }
2722
2723 bool CheckSendStats() {
Peter Boström74f6e9e2016-04-04 17:56:10 +02002724 RTC_DCHECK(send_stream_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002725 VideoSendStream::Stats stats = send_stream_->GetStats();
2726
2727 send_stats_filled_["NumStreams"] |=
2728 stats.substreams.size() == expected_send_ssrcs_.size();
2729
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002730 send_stats_filled_["CpuOveruseMetrics"] |=
Peter Boströme4499152016-02-05 11:13:28 +01002731 stats.avg_encode_time_ms != 0 && stats.encode_usage_percent != 0;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002732
Peter Boströmb7d9a972015-12-18 16:01:11 +01002733 send_stats_filled_["EncoderImplementationName"] |=
2734 stats.encoder_implementation_name ==
2735 test::FakeEncoder::kImplementationName;
2736
Pera48ddb72016-09-29 11:48:50 +02002737 send_stats_filled_["EncoderPreferredBitrate"] |=
2738 stats.preferred_media_bitrate_bps > 0;
2739
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002740 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002741 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002742 it != stats.substreams.end(); ++it) {
sprangcd349d92016-07-13 09:11:28 -07002743 if (expected_send_ssrcs_.find(it->first) == expected_send_ssrcs_.end())
2744 continue; // Probably RTX.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002745
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002746 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002747 stats.input_frame_rate != 0;
2748
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002749 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002750
2751 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
2752 stream_stats.rtcp_stats.cumulative_lost != 0 ||
2753 stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
2754 stream_stats.rtcp_stats.fraction_lost != 0;
2755
2756 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002757 stream_stats.rtp_stats.fec.packets != 0 ||
2758 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
2759 stream_stats.rtp_stats.retransmitted.packets != 0 ||
2760 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002761
sprangcd349d92016-07-13 09:11:28 -07002762 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Total",
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002763 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002764 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002765
sprangcd349d92016-07-13 09:11:28 -07002766 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Retransmit",
2767 it->first)] |=
2768 stream_stats.retransmit_bitrate_bps != 0;
2769
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002770 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002771 stream_stats.frame_counts.delta_frames != 0 ||
2772 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002773
2774 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
2775 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00002776
2777 send_stats_filled_[CompoundKey("Delay", it->first)] |=
2778 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002779
2780 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
2781 // report dropped packets.
2782 send_stats_filled_["RtcpPacketTypeCount"] |=
2783 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
2784 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
2785 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
2786 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
2787 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002788 }
2789
2790 return AllStatsFilled(send_stats_filled_);
2791 }
2792
2793 std::string CompoundKey(const char* name, uint32_t ssrc) {
2794 std::ostringstream oss;
2795 oss << name << "_" << ssrc;
2796 return oss.str();
2797 }
2798
2799 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
sprangcd349d92016-07-13 09:11:28 -07002800 for (const auto& stat : stats_map) {
2801 if (!stat.second)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002802 return false;
2803 }
2804 return true;
2805 }
2806
stefane74eef12016-01-08 06:47:13 -08002807 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
2808 FakeNetworkPipe::Config network_config;
2809 network_config.loss_percent = 5;
2810 return new test::PacketTransport(
2811 sender_call, this, test::PacketTransport::kSender, network_config);
2812 }
2813
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002814 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002815 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01002816 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002817 return config;
2818 }
2819
perkjfa10b552016-10-02 23:45:26 -07002820 // This test use other VideoStream settings than the the default settings
2821 // implemented in DefaultVideoStreamFactory. Therefore this test implement
2822 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
2823 // in ModifyVideoConfigs.
2824 class VideoStreamFactory
2825 : public VideoEncoderConfig::VideoStreamFactoryInterface {
2826 public:
2827 VideoStreamFactory() {}
2828
2829 private:
2830 std::vector<VideoStream> CreateEncoderStreams(
2831 int width,
2832 int height,
2833 const VideoEncoderConfig& encoder_config) override {
2834 std::vector<VideoStream> streams =
2835 test::CreateVideoStreams(width, height, encoder_config);
2836 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
2837 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
2838 streams[i].min_bitrate_bps = 10000;
2839 streams[i].target_bitrate_bps = 15000;
2840 streams[i].max_bitrate_bps = 20000;
2841 }
2842 return streams;
2843 }
2844 };
2845
stefanff483612015-12-21 03:14:00 -08002846 void ModifyVideoConfigs(
2847 VideoSendStream::Config* send_config,
2848 std::vector<VideoReceiveStream::Config>* receive_configs,
2849 VideoEncoderConfig* encoder_config) override {
perkjfa10b552016-10-02 23:45:26 -07002850 encoder_config->video_stream_factory =
2851 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002852 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002853 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002854
sprangcd349d92016-07-13 09:11:28 -07002855 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2856 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
2857
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002858 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002859 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002860 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002861 expected_receive_ssrcs_.push_back(
2862 (*receive_configs)[i].rtp.remote_ssrc);
Peter Boströmdef398832015-05-27 17:59:11 +02002863 (*receive_configs)[i].render_delay_ms = kExpectedRenderDelayMs;
tommi2e82f382016-06-21 00:26:43 -07002864 (*receive_configs)[i].renderer = &receive_stream_renderer_;
sprangcd349d92016-07-13 09:11:28 -07002865 (*receive_configs)[i].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2866
2867 (*receive_configs)[i].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
2868 kSendRtxSsrcs[i];
2869 (*receive_configs)[i].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
2870 kSendRtxPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002871 }
sprangcd349d92016-07-13 09:11:28 -07002872
2873 for (size_t i = 0; i < kNumSsrcs; ++i)
2874 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
2875
Peter Boströmc6e16e32016-02-05 14:15:53 +01002876 // Use a delayed encoder to make sure we see CpuOveruseMetrics stats that
2877 // are non-zero.
2878 send_config->encoder_settings.encoder = &encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002879 }
2880
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002881 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00002882
stefanff483612015-12-21 03:14:00 -08002883 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002884 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002885 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002886 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002887 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002888 }
2889
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002890 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002891 Clock* clock = Clock::GetRealTimeClock();
2892 int64_t now = clock->TimeInMilliseconds();
2893 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
2894 bool receive_ok = false;
2895 bool send_ok = false;
2896
2897 while (now < stop_time) {
2898 if (!receive_ok)
2899 receive_ok = CheckReceiveStats();
2900 if (!send_ok)
2901 send_ok = CheckSendStats();
2902
2903 if (receive_ok && send_ok)
2904 return;
2905
2906 int64_t time_until_timout_ = stop_time - now;
2907 if (time_until_timout_ > 0)
Peter Boström5811a392015-12-10 13:02:50 +01002908 check_stats_event_.Wait(time_until_timout_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002909 now = clock->TimeInMilliseconds();
2910 }
2911
2912 ADD_FAILURE() << "Timed out waiting for filled stats.";
2913 for (std::map<std::string, bool>::const_iterator it =
2914 receive_stats_filled_.begin();
2915 it != receive_stats_filled_.end();
2916 ++it) {
2917 if (!it->second) {
2918 ADD_FAILURE() << "Missing receive stats: " << it->first;
2919 }
2920 }
2921
2922 for (std::map<std::string, bool>::const_iterator it =
2923 send_stats_filled_.begin();
2924 it != send_stats_filled_.end();
2925 ++it) {
2926 if (!it->second) {
2927 ADD_FAILURE() << "Missing send stats: " << it->first;
2928 }
2929 }
2930 }
2931
Peter Boströmc6e16e32016-02-05 14:15:53 +01002932 test::DelayedEncoder encoder_;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002933 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002934 std::map<std::string, bool> receive_stats_filled_;
2935
2936 VideoSendStream* send_stream_;
2937 std::map<std::string, bool> send_stats_filled_;
2938
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002939 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002940 std::set<uint32_t> expected_send_ssrcs_;
2941 std::string expected_cname_;
2942
Peter Boström5811a392015-12-10 13:02:50 +01002943 rtc::Event check_stats_event_;
tommi2e82f382016-06-21 00:26:43 -07002944 ReceiveStreamRenderer receive_stream_renderer_;
stefanf116bd02015-10-27 08:29:42 -07002945 } test;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002946
stefane74eef12016-01-08 06:47:13 -08002947 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002948}
2949
2950TEST_F(EndToEndTest, ReceiverReferenceTimeReportEnabled) {
2951 TestXrReceiverReferenceTimeReport(true);
2952}
2953
2954TEST_F(EndToEndTest, ReceiverReferenceTimeReportDisabled) {
2955 TestXrReceiverReferenceTimeReport(false);
2956}
2957
2958TEST_F(EndToEndTest, TestReceivedRtpPacketStats) {
2959 static const size_t kNumRtpPacketsToSend = 5;
2960 class ReceivedRtpStatsObserver : public test::EndToEndTest {
2961 public:
2962 ReceivedRtpStatsObserver()
2963 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002964 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002965 sent_rtp_(0) {}
2966
2967 private:
stefanff483612015-12-21 03:14:00 -08002968 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002969 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002970 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002971 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002972 }
2973
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002974 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002975 if (sent_rtp_ >= kNumRtpPacketsToSend) {
2976 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002977 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
Peter Boström5811a392015-12-10 13:02:50 +01002978 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002979 }
2980 return DROP_PACKET;
2981 }
2982 ++sent_rtp_;
2983 return SEND_PACKET;
2984 }
2985
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002986 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002987 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002988 << "Timed out while verifying number of received RTP packets.";
2989 }
2990
2991 VideoReceiveStream* receive_stream_;
2992 uint32_t sent_rtp_;
2993 } test;
2994
stefane74eef12016-01-08 06:47:13 -08002995 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002996}
2997
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002998TEST_F(EndToEndTest, SendsSetSsrc) { TestSendsSetSsrcs(1, false); }
2999
3000TEST_F(EndToEndTest, SendsSetSimulcastSsrcs) {
3001 TestSendsSetSsrcs(kNumSsrcs, false);
3002}
3003
3004TEST_F(EndToEndTest, CanSwitchToUseAllSsrcs) {
3005 TestSendsSetSsrcs(kNumSsrcs, true);
3006}
3007
mflodman@webrtc.orgf9460682014-07-24 16:41:25 +00003008TEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003009 class ObserveRedundantPayloads: public test::EndToEndTest {
3010 public:
3011 ObserveRedundantPayloads()
3012 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003013 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003014 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
3015 }
3016 }
3017
3018 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003019 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003020 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003021 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003022
3023 if (!registered_rtx_ssrc_[header.ssrc])
3024 return SEND_PACKET;
3025
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003026 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003027 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003028 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003029
3030 if (!packet_is_redundant_payload)
3031 return SEND_PACKET;
3032
3033 if (!observed_redundant_retransmission_[header.ssrc]) {
3034 observed_redundant_retransmission_[header.ssrc] = true;
3035 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01003036 observation_complete_.Set();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003037 }
3038
3039 return SEND_PACKET;
3040 }
3041
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003042 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003043
perkjfa10b552016-10-02 23:45:26 -07003044 // This test use other VideoStream settings than the the default settings
3045 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3046 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3047 // in ModifyVideoConfigs.
3048 class VideoStreamFactory
3049 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3050 public:
3051 VideoStreamFactory() {}
3052
3053 private:
3054 std::vector<VideoStream> CreateEncoderStreams(
3055 int width,
3056 int height,
3057 const VideoEncoderConfig& encoder_config) override {
3058 std::vector<VideoStream> streams =
3059 test::CreateVideoStreams(width, height, encoder_config);
3060 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
3061 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3062 streams[i].min_bitrate_bps = 10000;
3063 streams[i].target_bitrate_bps = 15000;
3064 streams[i].max_bitrate_bps = 20000;
3065 }
3066 return streams;
3067 }
3068 };
3069
stefanff483612015-12-21 03:14:00 -08003070 void ModifyVideoConfigs(
3071 VideoSendStream::Config* send_config,
3072 std::vector<VideoReceiveStream::Config>* receive_configs,
3073 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003074 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
perkjfa10b552016-10-02 23:45:26 -07003075 encoder_config->video_stream_factory =
3076 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003077 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003078
3079 for (size_t i = 0; i < kNumSsrcs; ++i)
3080 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00003081
3082 // Significantly higher than max bitrates for all video streams -> forcing
3083 // padding to trigger redundant padding on all RTX SSRCs.
3084 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003085 }
3086
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003087 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003088 EXPECT_TRUE(Wait())
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003089 << "Timed out while waiting for redundant payloads on all SSRCs.";
3090 }
3091
3092 private:
3093 size_t ssrcs_to_observe_;
3094 std::map<uint32_t, bool> observed_redundant_retransmission_;
3095 std::map<uint32_t, bool> registered_rtx_ssrc_;
3096 } test;
3097
stefane74eef12016-01-08 06:47:13 -08003098 RunBaseTest(&test);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003099}
3100
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003101void EndToEndTest::TestRtpStatePreservation(bool use_rtx,
3102 bool provoke_rtcpsr_before_rtp) {
perkjfa10b552016-10-02 23:45:26 -07003103 // This test use other VideoStream settings than the the default settings
3104 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3105 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3106 // in ModifyVideoConfigs.
3107 class VideoStreamFactory
3108 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3109 public:
3110 VideoStreamFactory() {}
3111
3112 private:
3113 std::vector<VideoStream> CreateEncoderStreams(
3114 int width,
3115 int height,
3116 const VideoEncoderConfig& encoder_config) override {
3117 std::vector<VideoStream> streams =
3118 test::CreateVideoStreams(width, height, encoder_config);
3119
3120 if (encoder_config.number_of_streams > 1) {
3121 // Lower bitrates so that all streams send initially.
3122 RTC_DCHECK_EQ(3u, encoder_config.number_of_streams);
3123 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3124 streams[i].min_bitrate_bps = 10000;
3125 streams[i].target_bitrate_bps = 15000;
3126 streams[i].max_bitrate_bps = 20000;
3127 }
3128 } else {
3129 // Use the same total bitrates when sending a single stream to avoid
3130 // lowering
3131 // the bitrate estimate and requiring a subsequent rampup.
3132 streams[0].min_bitrate_bps = 3 * 10000;
3133 streams[0].target_bitrate_bps = 3 * 15000;
3134 streams[0].max_bitrate_bps = 3 * 20000;
3135 }
3136 return streams;
3137 }
3138 };
3139
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003140 class RtpSequenceObserver : public test::RtpRtcpObserver {
3141 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003142 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003143 : test::RtpRtcpObserver(kDefaultTimeoutMs),
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003144 ssrcs_to_observe_(kNumSsrcs) {
3145 for (size_t i = 0; i < kNumSsrcs; ++i) {
danilchap32cd2c42016-08-01 06:58:34 -07003146 ssrc_is_rtx_[kVideoSendSsrcs[i]] = false;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003147 if (use_rtx)
danilchap32cd2c42016-08-01 06:58:34 -07003148 ssrc_is_rtx_[kSendRtxSsrcs[i]] = true;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003149 }
3150 }
3151
3152 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
Peter Boströmf2f82832015-05-01 13:00:41 +02003153 rtc::CritScope lock(&crit_);
danilchap34877ee2016-02-01 08:25:04 -08003154 ssrc_observed_.clear();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003155 ssrcs_to_observe_ = num_expected_ssrcs;
3156 }
3157
3158 private:
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003159 void ValidateTimestampGap(uint32_t ssrc,
3160 uint32_t timestamp,
3161 bool only_padding)
3162 EXCLUSIVE_LOCKS_REQUIRED(crit_) {
3163 static const int32_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
3164 auto timestamp_it = last_observed_timestamp_.find(ssrc);
3165 if (timestamp_it == last_observed_timestamp_.end()) {
3166 EXPECT_FALSE(only_padding);
3167 last_observed_timestamp_[ssrc] = timestamp;
3168 } else {
3169 // Verify timestamps are reasonably close.
3170 uint32_t latest_observed = timestamp_it->second;
3171 // Wraparound handling is unnecessary here as long as an int variable
3172 // is used to store the result.
3173 int32_t timestamp_gap = timestamp - latest_observed;
3174 EXPECT_LE(std::abs(timestamp_gap), kMaxTimestampGap)
3175 << "Gap in timestamps (" << latest_observed << " -> " << timestamp
3176 << ") too large for SSRC: " << ssrc << ".";
3177 timestamp_it->second = timestamp;
3178 }
3179 }
3180
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003181 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003182 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003183 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003184 const uint32_t ssrc = header.ssrc;
danilchap5c35cf92016-02-03 14:14:49 -08003185 const int64_t sequence_number =
3186 seq_numbers_unwrapper_.Unwrap(header.sequenceNumber);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003187 const uint32_t timestamp = header.timestamp;
danilchap34877ee2016-02-01 08:25:04 -08003188 const bool only_padding =
3189 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003190
danilchap32cd2c42016-08-01 06:58:34 -07003191 EXPECT_TRUE(ssrc_is_rtx_.find(ssrc) != ssrc_is_rtx_.end())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003192 << "Received SSRC that wasn't configured: " << ssrc;
3193
danilchap5c35cf92016-02-03 14:14:49 -08003194 static const int64_t kMaxSequenceNumberGap = 100;
3195 std::list<int64_t>* seq_numbers = &last_observed_seq_numbers_[ssrc];
3196 if (seq_numbers->empty()) {
3197 seq_numbers->push_back(sequence_number);
3198 } else {
3199 // We shouldn't get replays of previous sequence numbers.
3200 for (int64_t observed : *seq_numbers) {
3201 EXPECT_NE(observed, sequence_number)
3202 << "Received sequence number " << sequence_number
3203 << " for SSRC " << ssrc << " 2nd time.";
3204 }
3205 // Verify sequence numbers are reasonably close.
3206 int64_t latest_observed = seq_numbers->back();
3207 int64_t sequence_number_gap = sequence_number - latest_observed;
3208 EXPECT_LE(std::abs(sequence_number_gap), kMaxSequenceNumberGap)
3209 << "Gap in sequence numbers (" << latest_observed << " -> "
3210 << sequence_number << ") too large for SSRC: " << ssrc << ".";
3211 seq_numbers->push_back(sequence_number);
3212 if (seq_numbers->size() >= kMaxSequenceNumberGap) {
3213 seq_numbers->pop_front();
3214 }
3215 }
3216
danilchap32cd2c42016-08-01 06:58:34 -07003217 if (!ssrc_is_rtx_[ssrc]) {
3218 rtc::CritScope lock(&crit_);
3219 ValidateTimestampGap(ssrc, timestamp, only_padding);
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003220
danilchap32cd2c42016-08-01 06:58:34 -07003221 // Wait for media packets on all ssrcs.
3222 if (!ssrc_observed_[ssrc] && !only_padding) {
3223 ssrc_observed_[ssrc] = true;
3224 if (--ssrcs_to_observe_ == 0)
3225 observation_complete_.Set();
3226 }
danilchap34877ee2016-02-01 08:25:04 -08003227 }
3228
danilchapf4b9c772016-01-28 06:14:24 -08003229 return SEND_PACKET;
3230 }
3231
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003232 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
3233 test::RtcpPacketParser rtcp_parser;
3234 rtcp_parser.Parse(packet, length);
3235 if (rtcp_parser.sender_report()->num_packets() > 0) {
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02003236 uint32_t ssrc = rtcp_parser.sender_report()->sender_ssrc();
3237 uint32_t rtcp_timestamp = rtcp_parser.sender_report()->rtp_timestamp();
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003238
3239 rtc::CritScope lock(&crit_);
3240 ValidateTimestampGap(ssrc, rtcp_timestamp, false);
3241 }
3242 return SEND_PACKET;
3243 }
3244
danilchap5c35cf92016-02-03 14:14:49 -08003245 SequenceNumberUnwrapper seq_numbers_unwrapper_;
3246 std::map<uint32_t, std::list<int64_t>> last_observed_seq_numbers_;
danilchap34877ee2016-02-01 08:25:04 -08003247 std::map<uint32_t, uint32_t> last_observed_timestamp_;
danilchap32cd2c42016-08-01 06:58:34 -07003248 std::map<uint32_t, bool> ssrc_is_rtx_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003249
Peter Boströmf2f82832015-05-01 13:00:41 +02003250 rtc::CriticalSection crit_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003251 size_t ssrcs_to_observe_ GUARDED_BY(crit_);
danilchap34877ee2016-02-01 08:25:04 -08003252 std::map<uint32_t, bool> ssrc_observed_ GUARDED_BY(crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003253 } observer(use_rtx);
3254
skvlad11a9cbf2016-10-07 11:53:05 -07003255 Call::Config config(&event_log_);
3256 CreateCalls(config, config);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003257
stefanf116bd02015-10-27 08:29:42 -07003258 test::PacketTransport send_transport(sender_call_.get(), &observer,
3259 test::PacketTransport::kSender,
3260 FakeNetworkPipe::Config());
3261 test::PacketTransport receive_transport(nullptr, &observer,
3262 test::PacketTransport::kReceiver,
3263 FakeNetworkPipe::Config());
3264 send_transport.SetReceiver(receiver_call_->Receiver());
3265 receive_transport.SetReceiver(sender_call_->Receiver());
3266
brandtr841de6a2016-11-15 07:10:52 -08003267 CreateSendConfig(kNumSsrcs, 0, 0, &send_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003268
3269 if (use_rtx) {
3270 for (size_t i = 0; i < kNumSsrcs; ++i) {
stefanff483612015-12-21 03:14:00 -08003271 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003272 }
stefanff483612015-12-21 03:14:00 -08003273 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003274 }
3275
perkjfa10b552016-10-02 23:45:26 -07003276 video_encoder_config_.video_stream_factory =
3277 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003278 // Use the same total bitrates when sending a single stream to avoid lowering
3279 // the bitrate estimate and requiring a subsequent rampup.
perkj26091b12016-09-01 01:17:40 -07003280 VideoEncoderConfig one_stream = video_encoder_config_.Copy();
perkjfa10b552016-10-02 23:45:26 -07003281 // one_stream.streams.resize(1);
3282 one_stream.number_of_streams = 1;
stefanf116bd02015-10-27 08:29:42 -07003283 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003284
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003285 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003286 CreateFrameGeneratorCapturer(30, 1280, 720);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003287
3288 Start();
Peter Boström5811a392015-12-10 13:02:50 +01003289 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003290 << "Timed out waiting for all SSRCs to send packets.";
3291
3292 // Test stream resetting more than once to make sure that the state doesn't
3293 // get set once (this could be due to using std::map::insert for instance).
3294 for (size_t i = 0; i < 3; ++i) {
3295 frame_generator_capturer_->Stop();
stefanff483612015-12-21 03:14:00 -08003296 sender_call_->DestroyVideoSendStream(video_send_stream_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003297
3298 // Re-create VideoSendStream with only one stream.
perkj26091b12016-09-01 01:17:40 -07003299 video_send_stream_ = sender_call_->CreateVideoSendStream(
3300 video_send_config_.Copy(), one_stream.Copy());
stefanff483612015-12-21 03:14:00 -08003301 video_send_stream_->Start();
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003302 if (provoke_rtcpsr_before_rtp) {
3303 // Rapid Resync Request forces sending RTCP Sender Report back.
3304 // Using this request speeds up this test because then there is no need
3305 // to wait for a second for periodic Sender Report.
3306 rtcp::RapidResyncRequest force_send_sr_back_request;
3307 rtc::Buffer packet = force_send_sr_back_request.Build();
3308 static_cast<webrtc::test::DirectTransport&>(receive_transport)
3309 .SendRtcp(packet.data(), packet.size());
3310 }
perkjfa10b552016-10-02 23:45:26 -07003311 CreateFrameGeneratorCapturer(30, 1280, 720);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003312 frame_generator_capturer_->Start();
3313
3314 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003315 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003316
3317 // Reconfigure back to use all streams.
perkj26091b12016-09-01 01:17:40 -07003318 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003319 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003320 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003321 << "Timed out waiting for all SSRCs to send packets.";
3322
3323 // Reconfigure down to one stream.
perkj26091b12016-09-01 01:17:40 -07003324 video_send_stream_->ReconfigureVideoEncoder(one_stream.Copy());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003325 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003326 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003327
3328 // Reconfigure back to use all streams.
perkj26091b12016-09-01 01:17:40 -07003329 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003330 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003331 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003332 << "Timed out waiting for all SSRCs to send packets.";
3333 }
3334
stefanf116bd02015-10-27 08:29:42 -07003335 send_transport.StopSending();
3336 receive_transport.StopSending();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003337
3338 Stop();
3339 DestroyStreams();
3340}
3341
Peter Boströmfc968a22016-02-19 16:14:37 +01003342TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpState) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003343 TestRtpStatePreservation(false, false);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003344}
3345
danilchap32cd2c42016-08-01 06:58:34 -07003346TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpStatesWithRtx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003347 TestRtpStatePreservation(true, false);
3348}
3349
danilchap32cd2c42016-08-01 06:58:34 -07003350TEST_F(EndToEndTest, RestartingSendStreamKeepsRtpAndRtcpTimestampsSynced) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003351 TestRtpStatePreservation(true, true);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003352}
3353
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003354TEST_F(EndToEndTest, RespectsNetworkState) {
3355 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
3356 // down blocks until no more packets will be sent.
3357
3358 // Pacer will send from its packet list and then send required padding before
3359 // checking paused_ again. This should be enough for one round of pacing,
3360 // otherwise increase.
3361 static const int kNumAcceptedDowntimeRtp = 5;
3362 // A single RTCP may be in the pipeline.
3363 static const int kNumAcceptedDowntimeRtcp = 1;
3364 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
3365 public:
3366 NetworkStateTest()
3367 : EndToEndTest(kDefaultTimeoutMs),
3368 FakeEncoder(Clock::GetRealTimeClock()),
Peter Boström5811a392015-12-10 13:02:50 +01003369 encoded_frames_(false, false),
3370 packet_event_(false, false),
sprang867fb522015-08-03 04:38:41 -07003371 sender_call_(nullptr),
3372 receiver_call_(nullptr),
Jelena Marusiccd670222015-07-16 09:30:09 +02003373 sender_state_(kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003374 sender_rtp_(0),
3375 sender_rtcp_(0),
3376 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003377 down_frames_(0) {}
3378
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003379 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003380 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003381 ++sender_rtp_;
Peter Boström5811a392015-12-10 13:02:50 +01003382 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003383 return SEND_PACKET;
3384 }
3385
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003386 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003387 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003388 ++sender_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003389 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003390 return SEND_PACKET;
3391 }
3392
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003393 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003394 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
3395 return SEND_PACKET;
3396 }
3397
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003398 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003399 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003400 ++receiver_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003401 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003402 return SEND_PACKET;
3403 }
3404
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003405 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003406 sender_call_ = sender_call;
3407 receiver_call_ = receiver_call;
3408 }
3409
stefanff483612015-12-21 03:14:00 -08003410 void ModifyVideoConfigs(
3411 VideoSendStream::Config* send_config,
3412 std::vector<VideoReceiveStream::Config>* receive_configs,
3413 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003414 send_config->encoder_settings.encoder = this;
3415 }
3416
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003417 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003418 EXPECT_TRUE(encoded_frames_.Wait(kDefaultTimeoutMs))
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003419 << "No frames received by the encoder.";
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003420 // Wait for packets from both sender/receiver.
3421 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003422
skvlad7a43d252016-03-22 15:32:27 -07003423 // Sender-side network down for audio; there should be no effect on video
3424 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3425 WaitForPacketsOrSilence(false, false);
3426
3427 // Receiver-side network down for audio; no change expected
3428 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3429 WaitForPacketsOrSilence(false, false);
3430
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003431 // Sender-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003432 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003433 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003434 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003435 // After network goes down we shouldn't be encoding more frames.
Jelena Marusiccd670222015-07-16 09:30:09 +02003436 sender_state_ = kNetworkDown;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003437 }
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003438 // Wait for receiver-packets and no sender packets.
3439 WaitForPacketsOrSilence(true, false);
3440
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003441 // Receiver-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003442 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
3443 WaitForPacketsOrSilence(true, true);
3444
3445 // Network up for audio for both sides; video is still not expected to
3446 // start
3447 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
3448 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003449 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003450
3451 // Network back up again for both.
3452 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003453 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003454 // It's OK to encode frames again, as we're about to bring up the
3455 // network.
Jelena Marusiccd670222015-07-16 09:30:09 +02003456 sender_state_ = kNetworkUp;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003457 }
skvlad7a43d252016-03-22 15:32:27 -07003458 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
3459 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003460 WaitForPacketsOrSilence(false, false);
skvlad7a43d252016-03-22 15:32:27 -07003461
3462 // TODO(skvlad): add tests to verify that the audio streams are stopped
3463 // when the network goes down for audio once the workaround in
3464 // paced_sender.cc is removed.
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003465 }
3466
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07003467 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003468 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07003469 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003470 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003471 rtc::CritScope lock(&test_crit_);
Jelena Marusiccd670222015-07-16 09:30:09 +02003472 if (sender_state_ == kNetworkDown) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003473 ++down_frames_;
3474 EXPECT_LE(down_frames_, 1)
3475 << "Encoding more than one frame while network is down.";
3476 if (down_frames_ > 1)
Peter Boström5811a392015-12-10 13:02:50 +01003477 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003478 } else {
Peter Boström5811a392015-12-10 13:02:50 +01003479 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003480 }
3481 }
3482 return test::FakeEncoder::Encode(
3483 input_image, codec_specific_info, frame_types);
3484 }
3485
3486 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003487 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
3488 int64_t initial_time_ms = clock_->TimeInMilliseconds();
3489 int initial_sender_rtp;
3490 int initial_sender_rtcp;
3491 int initial_receiver_rtcp;
3492 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003493 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003494 initial_sender_rtp = sender_rtp_;
3495 initial_sender_rtcp = sender_rtcp_;
3496 initial_receiver_rtcp = receiver_rtcp_;
3497 }
3498 bool sender_done = false;
3499 bool receiver_done = false;
mflodmand1590b22015-12-09 07:07:59 -08003500 while (!sender_done || !receiver_done) {
Peter Boström5811a392015-12-10 13:02:50 +01003501 packet_event_.Wait(kSilenceTimeoutMs);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003502 int64_t time_now_ms = clock_->TimeInMilliseconds();
Peter Boströmf2f82832015-05-01 13:00:41 +02003503 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003504 if (sender_down) {
3505 ASSERT_LE(sender_rtp_ - initial_sender_rtp, kNumAcceptedDowntimeRtp)
3506 << "RTP sent during sender-side downtime.";
3507 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
3508 kNumAcceptedDowntimeRtcp)
3509 << "RTCP sent during sender-side downtime.";
3510 if (time_now_ms - initial_time_ms >=
3511 static_cast<int64_t>(kSilenceTimeoutMs)) {
3512 sender_done = true;
3513 }
3514 } else {
skvlad7a43d252016-03-22 15:32:27 -07003515 if (sender_rtp_ > initial_sender_rtp + kNumAcceptedDowntimeRtp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003516 sender_done = true;
3517 }
3518 if (receiver_down) {
3519 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
3520 kNumAcceptedDowntimeRtcp)
3521 << "RTCP sent during receiver-side downtime.";
3522 if (time_now_ms - initial_time_ms >=
3523 static_cast<int64_t>(kSilenceTimeoutMs)) {
3524 receiver_done = true;
3525 }
3526 } else {
skvlad7a43d252016-03-22 15:32:27 -07003527 if (receiver_rtcp_ > initial_receiver_rtcp + kNumAcceptedDowntimeRtcp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003528 receiver_done = true;
3529 }
3530 }
3531 }
3532
Peter Boströmf2f82832015-05-01 13:00:41 +02003533 rtc::CriticalSection test_crit_;
Peter Boström5811a392015-12-10 13:02:50 +01003534 rtc::Event encoded_frames_;
3535 rtc::Event packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003536 Call* sender_call_;
3537 Call* receiver_call_;
Jelena Marusiccd670222015-07-16 09:30:09 +02003538 NetworkState sender_state_ GUARDED_BY(test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003539 int sender_rtp_ GUARDED_BY(test_crit_);
3540 int sender_rtcp_ GUARDED_BY(test_crit_);
3541 int receiver_rtcp_ GUARDED_BY(test_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003542 int down_frames_ GUARDED_BY(test_crit_);
3543 } test;
3544
stefane74eef12016-01-08 06:47:13 -08003545 RunBaseTest(&test);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003546}
3547
danilchapa6a70072016-06-01 11:20:43 -07003548TEST_F(EndToEndTest, CallReportsRttForSender) {
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003549 static const int kSendDelayMs = 30;
3550 static const int kReceiveDelayMs = 70;
skvlad11a9cbf2016-10-07 11:53:05 -07003551 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -07003552
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003553 FakeNetworkPipe::Config config;
3554 config.queue_delay_ms = kSendDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003555 test::DirectTransport sender_transport(config, sender_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003556 config.queue_delay_ms = kReceiveDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003557 test::DirectTransport receiver_transport(config, receiver_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003558 sender_transport.SetReceiver(receiver_call_->Receiver());
3559 receiver_transport.SetReceiver(sender_call_->Receiver());
3560
brandtr841de6a2016-11-15 07:10:52 -08003561 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07003562 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003563
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003564 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003565 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
3566 kDefaultHeight);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003567 Start();
3568
3569 int64_t start_time_ms = clock_->TimeInMilliseconds();
3570 while (true) {
3571 Call::Stats stats = sender_call_->GetStats();
3572 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
3573 clock_->TimeInMilliseconds())
3574 << "No RTT stats before timeout!";
3575 if (stats.rtt_ms != -1) {
Danil Chapovalov10e8f8e2016-09-07 15:05:29 +02003576 // To avoid failures caused by rounding or minor ntp clock adjustments,
3577 // relax expectation by 1ms.
3578 constexpr int kAllowedErrorMs = 1;
3579 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs - kAllowedErrorMs);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003580 break;
3581 }
3582 SleepMs(10);
3583 }
3584
3585 Stop();
3586 DestroyStreams();
3587}
3588
skvlad7a43d252016-03-22 15:32:27 -07003589void EndToEndTest::VerifyNewVideoSendStreamsRespectNetworkState(
3590 MediaType network_to_bring_down,
3591 VideoEncoder* encoder,
3592 Transport* transport) {
skvlad11a9cbf2016-10-07 11:53:05 -07003593 CreateSenderCall(Call::Config(&event_log_));
skvlad7a43d252016-03-22 15:32:27 -07003594 sender_call_->SignalChannelNetworkState(network_to_bring_down, kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003595
brandtr841de6a2016-11-15 07:10:52 -08003596 CreateSendConfig(1, 0, 0, transport);
skvlad7a43d252016-03-22 15:32:27 -07003597 video_send_config_.encoder_settings.encoder = encoder;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003598 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003599 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
3600 kDefaultHeight);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003601
3602 Start();
3603 SleepMs(kSilenceTimeoutMs);
3604 Stop();
3605
3606 DestroyStreams();
3607}
3608
skvlad7a43d252016-03-22 15:32:27 -07003609void EndToEndTest::VerifyNewVideoReceiveStreamsRespectNetworkState(
3610 MediaType network_to_bring_down,
3611 Transport* transport) {
skvlad11a9cbf2016-10-07 11:53:05 -07003612 Call::Config config(&event_log_);
3613 CreateCalls(config, config);
skvlad7a43d252016-03-22 15:32:27 -07003614 receiver_call_->SignalChannelNetworkState(network_to_bring_down,
3615 kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003616
stefanf116bd02015-10-27 08:29:42 -07003617 test::DirectTransport sender_transport(sender_call_.get());
solenberg4fbae2b2015-08-28 04:07:10 -07003618 sender_transport.SetReceiver(receiver_call_->Receiver());
brandtr841de6a2016-11-15 07:10:52 -08003619 CreateSendConfig(1, 0, 0, &sender_transport);
skvlad7a43d252016-03-22 15:32:27 -07003620 CreateMatchingReceiveConfigs(transport);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003621 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003622 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
3623 kDefaultHeight);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003624
3625 Start();
3626 SleepMs(kSilenceTimeoutMs);
3627 Stop();
3628
3629 sender_transport.StopSending();
3630
3631 DestroyStreams();
3632}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00003633
skvlad7a43d252016-03-22 15:32:27 -07003634TEST_F(EndToEndTest, NewVideoSendStreamsRespectVideoNetworkDown) {
3635 class UnusedEncoder : public test::FakeEncoder {
3636 public:
3637 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
perkjfea93092016-05-14 00:58:48 -07003638
3639 int32_t InitEncode(const VideoCodec* config,
3640 int32_t number_of_cores,
3641 size_t max_payload_size) override {
3642 EXPECT_GT(config->startBitrate, 0u);
3643 return 0;
3644 }
skvlad7a43d252016-03-22 15:32:27 -07003645 int32_t Encode(const VideoFrame& input_image,
3646 const CodecSpecificInfo* codec_specific_info,
3647 const std::vector<FrameType>* frame_types) override {
3648 ADD_FAILURE() << "Unexpected frame encode.";
3649 return test::FakeEncoder::Encode(input_image, codec_specific_info,
3650 frame_types);
3651 }
3652 };
3653
3654 UnusedEncoder unused_encoder;
3655 UnusedTransport unused_transport;
3656 VerifyNewVideoSendStreamsRespectNetworkState(
3657 MediaType::VIDEO, &unused_encoder, &unused_transport);
3658}
3659
3660TEST_F(EndToEndTest, NewVideoSendStreamsIgnoreAudioNetworkDown) {
3661 class RequiredEncoder : public test::FakeEncoder {
3662 public:
3663 RequiredEncoder()
3664 : FakeEncoder(Clock::GetRealTimeClock()), encoded_frame_(false) {}
3665 ~RequiredEncoder() {
3666 if (!encoded_frame_) {
3667 ADD_FAILURE() << "Didn't encode an expected frame";
3668 }
3669 }
3670 int32_t Encode(const VideoFrame& input_image,
3671 const CodecSpecificInfo* codec_specific_info,
3672 const std::vector<FrameType>* frame_types) override {
3673 encoded_frame_ = true;
3674 return test::FakeEncoder::Encode(input_image, codec_specific_info,
3675 frame_types);
3676 }
3677
3678 private:
3679 bool encoded_frame_;
3680 };
3681
3682 RequiredTransport required_transport(true /*rtp*/, false /*rtcp*/);
3683 RequiredEncoder required_encoder;
3684 VerifyNewVideoSendStreamsRespectNetworkState(
3685 MediaType::AUDIO, &required_encoder, &required_transport);
3686}
3687
3688TEST_F(EndToEndTest, NewVideoReceiveStreamsRespectVideoNetworkDown) {
3689 UnusedTransport transport;
3690 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::VIDEO, &transport);
3691}
3692
3693TEST_F(EndToEndTest, NewVideoReceiveStreamsIgnoreAudioNetworkDown) {
3694 RequiredTransport transport(false /*rtp*/, true /*rtcp*/);
3695 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::AUDIO, &transport);
3696}
3697
Peter Boströmd7da1202015-06-05 14:09:38 +02003698void VerifyEmptyNackConfig(const NackConfig& config) {
3699 EXPECT_EQ(0, config.rtp_history_ms)
3700 << "Enabling NACK requires rtcp-fb: nack negotiation.";
3701}
3702
brandtrb5f2c3f2016-10-04 23:28:39 -07003703void VerifyEmptyUlpfecConfig(const UlpfecConfig& config) {
Peter Boströmd7da1202015-06-05 14:09:38 +02003704 EXPECT_EQ(-1, config.ulpfec_payload_type)
brandtr535830e2016-10-31 03:45:58 -07003705 << "Enabling ULPFEC requires rtpmap: ulpfec negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02003706 EXPECT_EQ(-1, config.red_payload_type)
brandtr535830e2016-10-31 03:45:58 -07003707 << "Enabling ULPFEC requires rtpmap: red negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02003708 EXPECT_EQ(-1, config.red_rtx_payload_type)
brandtr535830e2016-10-31 03:45:58 -07003709 << "Enabling RTX in ULPFEC requires rtpmap: rtx negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02003710}
3711
3712TEST_F(EndToEndTest, VerifyDefaultSendConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003713 VideoSendStream::Config default_send_config(nullptr);
Peter Boströmd7da1202015-06-05 14:09:38 +02003714 EXPECT_EQ(0, default_send_config.rtp.nack.rtp_history_ms)
3715 << "Enabling NACK require rtcp-fb: nack negotiation.";
3716 EXPECT_TRUE(default_send_config.rtp.rtx.ssrcs.empty())
3717 << "Enabling RTX requires rtpmap: rtx negotiation.";
3718 EXPECT_TRUE(default_send_config.rtp.extensions.empty())
3719 << "Enabling RTP extensions require negotiation.";
3720
3721 VerifyEmptyNackConfig(default_send_config.rtp.nack);
brandtrb5f2c3f2016-10-04 23:28:39 -07003722 VerifyEmptyUlpfecConfig(default_send_config.rtp.ulpfec);
Peter Boströmd7da1202015-06-05 14:09:38 +02003723}
3724
3725TEST_F(EndToEndTest, VerifyDefaultReceiveConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003726 VideoReceiveStream::Config default_receive_config(nullptr);
pbosda903ea2015-10-02 02:36:56 -07003727 EXPECT_EQ(RtcpMode::kCompound, default_receive_config.rtp.rtcp_mode)
Peter Boströmd7da1202015-06-05 14:09:38 +02003728 << "Reduced-size RTCP require rtcp-rsize to be negotiated.";
3729 EXPECT_FALSE(default_receive_config.rtp.remb)
3730 << "REMB require rtcp-fb: goog-remb to be negotiated.";
3731 EXPECT_FALSE(
3732 default_receive_config.rtp.rtcp_xr.receiver_reference_time_report)
3733 << "RTCP XR settings require rtcp-xr to be negotiated.";
3734 EXPECT_TRUE(default_receive_config.rtp.rtx.empty())
3735 << "Enabling RTX requires rtpmap: rtx negotiation.";
3736 EXPECT_TRUE(default_receive_config.rtp.extensions.empty())
3737 << "Enabling RTP extensions require negotiation.";
3738
3739 VerifyEmptyNackConfig(default_receive_config.rtp.nack);
brandtrb5f2c3f2016-10-04 23:28:39 -07003740 VerifyEmptyUlpfecConfig(default_receive_config.rtp.ulpfec);
Peter Boströmd7da1202015-06-05 14:09:38 +02003741}
3742
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003743TEST_F(EndToEndTest, TransportSeqNumOnAudioAndVideo) {
3744 static const int kExtensionId = 8;
3745 class TransportSequenceNumberTest : public test::EndToEndTest {
3746 public:
3747 TransportSequenceNumberTest()
3748 : EndToEndTest(kDefaultTimeoutMs),
3749 video_observed_(false),
3750 audio_observed_(false) {
3751 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
3752 kExtensionId);
3753 }
3754
3755 size_t GetNumVideoStreams() const override { return 1; }
3756 size_t GetNumAudioStreams() const override { return 1; }
3757
3758 void ModifyVideoConfigs(
3759 VideoSendStream::Config* send_config,
3760 std::vector<VideoReceiveStream::Config>* receive_configs,
3761 VideoEncoderConfig* encoder_config) override {
3762 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07003763 send_config->rtp.extensions.push_back(RtpExtension(
3764 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003765 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3766 }
3767
3768 void ModifyAudioConfigs(
3769 AudioSendStream::Config* send_config,
3770 std::vector<AudioReceiveStream::Config>* receive_configs) override {
3771 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07003772 send_config->rtp.extensions.push_back(RtpExtension(
3773 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003774 (*receive_configs)[0].rtp.extensions.clear();
3775 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3776 }
3777
3778 Action OnSendRtp(const uint8_t* packet, size_t length) override {
3779 RTPHeader header;
3780 EXPECT_TRUE(parser_->Parse(packet, length, &header));
3781 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
3782 // Unwrap packet id and verify uniqueness.
3783 int64_t packet_id =
3784 unwrapper_.Unwrap(header.extension.transportSequenceNumber);
3785 EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
3786
3787 if (header.ssrc == kVideoSendSsrcs[0])
3788 video_observed_ = true;
3789 if (header.ssrc == kAudioSendSsrc)
3790 audio_observed_ = true;
3791 if (audio_observed_ && video_observed_ &&
3792 received_packet_ids_.size() == 50) {
3793 size_t packet_id_range =
3794 *received_packet_ids_.rbegin() - *received_packet_ids_.begin() + 1;
3795 EXPECT_EQ(received_packet_ids_.size(), packet_id_range);
3796 observation_complete_.Set();
3797 }
3798 return SEND_PACKET;
3799 }
3800
3801 void PerformTest() override {
3802 EXPECT_TRUE(Wait()) << "Timed out while waiting for audio and video "
3803 "packets with transport sequence number.";
3804 }
3805
3806 private:
3807 bool video_observed_;
3808 bool audio_observed_;
3809 SequenceNumberUnwrapper unwrapper_;
3810 std::set<int64_t> received_packet_ids_;
3811 } test;
3812
stefane74eef12016-01-08 06:47:13 -08003813 RunBaseTest(&test);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003814}
palmkviste75f2042016-09-28 06:19:48 -07003815
3816class EndToEndLogTest : public EndToEndTest {
3817 void SetUp() { paths_.clear(); }
3818 void TearDown() {
3819 for (const auto& path : paths_) {
3820 rtc::RemoveFile(path);
3821 }
3822 }
3823
3824 public:
3825 int AddFile() {
3826 paths_.push_back(test::TempFilename(test::OutputPath(), "test_file"));
3827 return static_cast<int>(paths_.size()) - 1;
3828 }
3829
3830 rtc::PlatformFile OpenFile(int idx) {
3831 return rtc::OpenPlatformFile(paths_[idx]);
3832 }
3833
3834 void LogSend(bool open) {
3835 if (open) {
3836 video_send_stream_->EnableEncodedFrameRecording(
3837 std::vector<rtc::PlatformFile>(1, OpenFile(AddFile())), 0);
3838 } else {
3839 video_send_stream_->DisableEncodedFrameRecording();
3840 }
3841 }
3842 void LogReceive(bool open) {
3843 if (open) {
3844 video_receive_streams_[0]->EnableEncodedFrameRecording(
3845 OpenFile(AddFile()), 0);
3846 } else {
3847 video_receive_streams_[0]->DisableEncodedFrameRecording();
3848 }
3849 }
3850
3851 std::vector<std::string> paths_;
3852};
3853
3854TEST_F(EndToEndLogTest, LogsEncodedFramesWhenRequested) {
3855 static const int kNumFramesToRecord = 10;
3856 class LogEncodingObserver : public test::EndToEndTest,
3857 public EncodedFrameObserver {
3858 public:
3859 explicit LogEncodingObserver(EndToEndLogTest* fixture)
3860 : EndToEndTest(kDefaultTimeoutMs),
3861 fixture_(fixture),
3862 recorded_frames_(0) {}
3863
3864 void PerformTest() override {
3865 fixture_->LogSend(true);
3866 fixture_->LogReceive(true);
3867 ASSERT_TRUE(Wait()) << "Timed out while waiting for frame logging.";
3868 }
3869
3870 void ModifyVideoConfigs(
3871 VideoSendStream::Config* send_config,
3872 std::vector<VideoReceiveStream::Config>* receive_configs,
3873 VideoEncoderConfig* encoder_config) override {
3874 encoder_.reset(VideoEncoder::Create(VideoEncoder::kVp8));
3875 decoder_.reset(VP8Decoder::Create());
3876
3877 send_config->post_encode_callback = this;
3878 send_config->encoder_settings.payload_name = "VP8";
3879 send_config->encoder_settings.encoder = encoder_.get();
3880
3881 (*receive_configs)[0].decoders.resize(1);
3882 (*receive_configs)[0].decoders[0].payload_type =
3883 send_config->encoder_settings.payload_type;
3884 (*receive_configs)[0].decoders[0].payload_name =
3885 send_config->encoder_settings.payload_name;
3886 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
3887 }
3888
3889 void EncodedFrameCallback(const EncodedFrame& encoded_frame) override {
3890 rtc::CritScope lock(&crit_);
3891 if (recorded_frames_++ > kNumFramesToRecord) {
3892 fixture_->LogSend(false);
3893 fixture_->LogReceive(false);
3894 rtc::File send_file(fixture_->OpenFile(0));
3895 rtc::File receive_file(fixture_->OpenFile(1));
3896 uint8_t out[100];
3897 // If logging has worked correctly neither file should be empty, i.e.
3898 // we should be able to read something from them.
3899 EXPECT_LT(0u, send_file.Read(out, 100));
3900 EXPECT_LT(0u, receive_file.Read(out, 100));
3901 observation_complete_.Set();
3902 }
3903 }
3904
3905 private:
3906 EndToEndLogTest* const fixture_;
3907 std::unique_ptr<VideoEncoder> encoder_;
3908 std::unique_ptr<VideoDecoder> decoder_;
3909 rtc::CriticalSection crit_;
3910 int recorded_frames_ GUARDED_BY(crit_);
3911 } test(this);
3912
3913 RunBaseTest(&test);
3914}
3915
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003916} // namespace webrtc