blob: 1f4ed77ffa35e3b945f1231e9dec74d30c88b8cf [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
18#include "testing/gtest/include/gtest/gtest.h"
19
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000020#include "webrtc/base/checks.h"
Erik Språng6b8d3552015-09-24 15:06:57 +020021#include "webrtc/base/event.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000022#include "webrtc/call.h"
Peter Boström5c389d32015-09-25 13:58:30 +020023#include "webrtc/call/transport_adapter.h"
pbosa96b60b2016-04-18 21:12:48 -070024#include "webrtc/common_video/include/frame_callback.h"
danilchap5c35cf92016-02-03 14:14:49 -080025#include "webrtc/modules/include/module_common_types.h"
stefan32f81542016-01-20 07:13:58 -080026#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
sprang861c55e2015-10-16 10:01:21 -070027#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
Danil Chapovalov70ffead2016-07-20 15:26:59 +020028#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000029#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
sprangcd349d92016-07-13 09:11:28 -070030#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
hbosbab934b2016-01-27 01:36:03 -080031#include "webrtc/modules/video_coding/codecs/h264/include/h264.h"
marpan@webrtc.org5b883172014-11-01 06:10:48 +000032#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
33#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010034#include "webrtc/modules/video_coding/include/video_coding_defines.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010035#include "webrtc/system_wrappers/include/metrics.h"
asapersson01d70a32016-05-20 06:29:46 -070036#include "webrtc/system_wrappers/include/metrics_default.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010037#include "webrtc/system_wrappers/include/sleep.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000038#include "webrtc/test/call_test.h"
39#include "webrtc/test/direct_transport.h"
40#include "webrtc/test/encoder_settings.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000041#include "webrtc/test/fake_decoder.h"
42#include "webrtc/test/fake_encoder.h"
43#include "webrtc/test/frame_generator.h"
44#include "webrtc/test/frame_generator_capturer.h"
45#include "webrtc/test/null_transport.h"
asapersson@webrtc.org37c05592015-01-28 13:58:27 +000046#include "webrtc/test/rtcp_packet_parser.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000047#include "webrtc/test/rtp_rtcp_observer.h"
48#include "webrtc/test/testsupport/fileutils.h"
49#include "webrtc/test/testsupport/perf_test.h"
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +000050#include "webrtc/video_encoder.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000051
52namespace webrtc {
53
Peter Boström5811a392015-12-10 13:02:50 +010054static const int kSilenceTimeoutMs = 2000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000055
56class EndToEndTest : public test::CallTest {
57 public:
58 EndToEndTest() {}
59
60 virtual ~EndToEndTest() {
stefanff483612015-12-21 03:14:00 -080061 EXPECT_EQ(nullptr, video_send_stream_);
62 EXPECT_TRUE(video_receive_streams_.empty());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000063 }
64
65 protected:
pbos2d566682015-09-28 09:59:31 -070066 class UnusedTransport : public Transport {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000067 private:
stefan1d8a5062015-10-02 03:39:33 -070068 bool SendRtp(const uint8_t* packet,
69 size_t length,
70 const PacketOptions& options) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000071 ADD_FAILURE() << "Unexpected RTP sent.";
72 return false;
73 }
74
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000075 bool SendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000076 ADD_FAILURE() << "Unexpected RTCP sent.";
77 return false;
78 }
79 };
80
skvlad7a43d252016-03-22 15:32:27 -070081 class RequiredTransport : public Transport {
82 public:
83 RequiredTransport(bool rtp_required, bool rtcp_required)
84 : need_rtp_(rtp_required), need_rtcp_(rtcp_required) {}
85 ~RequiredTransport() {
86 if (need_rtp_) {
87 ADD_FAILURE() << "Expected RTP packet not sent.";
88 }
89 if (need_rtcp_) {
90 ADD_FAILURE() << "Expected RTCP packet not sent.";
91 }
92 }
93
94 private:
95 bool SendRtp(const uint8_t* packet,
96 size_t length,
97 const PacketOptions& options) override {
98 need_rtp_ = false;
99 return true;
100 }
101
102 bool SendRtcp(const uint8_t* packet, size_t length) override {
103 need_rtcp_ = false;
104 return true;
105 }
106 bool need_rtp_;
107 bool need_rtcp_;
108 };
109
Peter Boström39593972016-02-15 11:27:15 +0100110 void DecodesRetransmittedFrame(bool enable_rtx, bool enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000111 void ReceivesPliAndRecovers(int rtp_history_ms);
pbosda903ea2015-10-02 02:36:56 -0700112 void RespectsRtcpMode(RtcpMode rtcp_mode);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000113 void TestXrReceiverReferenceTimeReport(bool enable_rrtr);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000114 void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200115 void TestRtpStatePreservation(bool use_rtx, bool provoke_rtcpsr_before_rtp);
sprangb4a1ae52015-12-03 08:10:08 -0800116 void VerifyHistogramStats(bool use_rtx, bool use_red, bool screenshare);
skvlad7a43d252016-03-22 15:32:27 -0700117 void VerifyNewVideoSendStreamsRespectNetworkState(
118 MediaType network_to_bring_down,
119 VideoEncoder* encoder,
120 Transport* transport);
121 void VerifyNewVideoReceiveStreamsRespectNetworkState(
122 MediaType network_to_bring_down,
123 Transport* transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000124};
125
126TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
solenberg4fbae2b2015-08-28 04:07:10 -0700127 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000128
solenberg4fbae2b2015-08-28 04:07:10 -0700129 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100130 CreateSendConfig(1, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700131 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000132
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100133 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000134
stefanff483612015-12-21 03:14:00 -0800135 video_receive_streams_[0]->Start();
136 video_receive_streams_[0]->Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000137
138 DestroyStreams();
139}
140
141TEST_F(EndToEndTest, ReceiverCanBeStoppedTwice) {
solenberg4fbae2b2015-08-28 04:07:10 -0700142 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000143
solenberg4fbae2b2015-08-28 04:07:10 -0700144 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100145 CreateSendConfig(1, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700146 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000147
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100148 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000149
stefanff483612015-12-21 03:14:00 -0800150 video_receive_streams_[0]->Stop();
151 video_receive_streams_[0]->Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000152
153 DestroyStreams();
154}
155
156TEST_F(EndToEndTest, RendersSingleDelayedFrame) {
157 static const int kWidth = 320;
158 static const int kHeight = 240;
159 // This constant is chosen to be higher than the timeout in the video_render
160 // module. This makes sure that frames aren't dropped if there are no other
161 // frames in the queue.
162 static const int kDelayRenderCallbackMs = 1000;
163
nisse7ade7b32016-03-23 04:48:10 -0700164 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000165 public:
Peter Boström5811a392015-12-10 13:02:50 +0100166 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000167
nisseeb83a1a2016-03-21 01:27:56 -0700168 void OnFrame(const VideoFrame& video_frame) override { event_.Set(); }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000169
Peter Boström5811a392015-12-10 13:02:50 +0100170 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000171
Peter Boström5811a392015-12-10 13:02:50 +0100172 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000173 } renderer;
174
175 class TestFrameCallback : public I420FrameCallback {
176 public:
Peter Boström5811a392015-12-10 13:02:50 +0100177 TestFrameCallback() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000178
Peter Boström5811a392015-12-10 13:02:50 +0100179 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000180
181 private:
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700182 void FrameCallback(VideoFrame* frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000183 SleepMs(kDelayRenderCallbackMs);
Peter Boström5811a392015-12-10 13:02:50 +0100184 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000185 }
186
Peter Boström5811a392015-12-10 13:02:50 +0100187 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000188 };
189
solenberg4fbae2b2015-08-28 04:07:10 -0700190 CreateCalls(Call::Config(), Call::Config());
191
stefanf116bd02015-10-27 08:29:42 -0700192 test::DirectTransport sender_transport(sender_call_.get());
193 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000194 sender_transport.SetReceiver(receiver_call_->Receiver());
195 receiver_transport.SetReceiver(sender_call_->Receiver());
196
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100197 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700198 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000199
200 TestFrameCallback pre_render_callback;
stefanff483612015-12-21 03:14:00 -0800201 video_receive_configs_[0].pre_render_callback = &pre_render_callback;
202 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000203
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100204 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000205 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000206
207 // Create frames that are smaller than the send width/height, this is done to
208 // check that the callbacks are done after processing video.
kwiberg27f982b2016-03-01 11:52:33 -0800209 std::unique_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000210 test::FrameGenerator::CreateChromaGenerator(kWidth, kHeight));
stefanff483612015-12-21 03:14:00 -0800211 video_send_stream_->Input()->IncomingCapturedFrame(
212 *frame_generator->NextFrame());
Peter Boström5811a392015-12-10 13:02:50 +0100213 EXPECT_TRUE(pre_render_callback.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000214 << "Timed out while waiting for pre-render callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100215 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000216 << "Timed out while waiting for the frame to render.";
217
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000218 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000219
220 sender_transport.StopSending();
221 receiver_transport.StopSending();
222
223 DestroyStreams();
224}
225
226TEST_F(EndToEndTest, TransmitsFirstFrame) {
nisse7ade7b32016-03-23 04:48:10 -0700227 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000228 public:
Peter Boström5811a392015-12-10 13:02:50 +0100229 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000230
nisseeb83a1a2016-03-21 01:27:56 -0700231 void OnFrame(const VideoFrame& video_frame) override { event_.Set(); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000232
Peter Boström5811a392015-12-10 13:02:50 +0100233 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000234
Peter Boström5811a392015-12-10 13:02:50 +0100235 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000236 } renderer;
237
solenberg4fbae2b2015-08-28 04:07:10 -0700238 CreateCalls(Call::Config(), Call::Config());
239
stefanf116bd02015-10-27 08:29:42 -0700240 test::DirectTransport sender_transport(sender_call_.get());
241 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000242 sender_transport.SetReceiver(receiver_call_->Receiver());
243 receiver_transport.SetReceiver(sender_call_->Receiver());
244
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100245 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700246 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -0800247 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000248
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100249 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000250 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000251
kwiberg27f982b2016-03-01 11:52:33 -0800252 std::unique_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000253 test::FrameGenerator::CreateChromaGenerator(
stefanff483612015-12-21 03:14:00 -0800254 video_encoder_config_.streams[0].width,
255 video_encoder_config_.streams[0].height));
256 video_send_stream_->Input()->IncomingCapturedFrame(
257 *frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000258
Peter Boström5811a392015-12-10 13:02:50 +0100259 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000260 << "Timed out while waiting for the frame to render.";
261
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000262 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000263
264 sender_transport.StopSending();
265 receiver_transport.StopSending();
266
267 DestroyStreams();
268}
269
Perba7dc722016-04-19 15:01:23 +0200270class CodecObserver : public test::EndToEndTest,
nisse7ade7b32016-03-23 04:48:10 -0700271 public rtc::VideoSinkInterface<VideoFrame> {
Perba7dc722016-04-19 15:01:23 +0200272 public:
273 CodecObserver(int no_frames_to_wait_for,
274 VideoRotation rotation_to_test,
275 const std::string& payload_name,
276 webrtc::VideoEncoder* encoder,
277 webrtc::VideoDecoder* decoder)
278 : EndToEndTest(2 * webrtc::EndToEndTest::kDefaultTimeoutMs),
279 no_frames_to_wait_for_(no_frames_to_wait_for),
280 expected_rotation_(rotation_to_test),
281 payload_name_(payload_name),
282 encoder_(encoder),
283 decoder_(decoder),
284 frame_counter_(0) {}
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000285
Perba7dc722016-04-19 15:01:23 +0200286 void PerformTest() override {
287 EXPECT_TRUE(Wait())
288 << "Timed out while waiting for enough frames to be decoded.";
289 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000290
Perba7dc722016-04-19 15:01:23 +0200291 void ModifyVideoConfigs(
292 VideoSendStream::Config* send_config,
293 std::vector<VideoReceiveStream::Config>* receive_configs,
294 VideoEncoderConfig* encoder_config) override {
295 send_config->encoder_settings.encoder = encoder_.get();
296 send_config->encoder_settings.payload_name = payload_name_;
297 send_config->encoder_settings.payload_type = 126;
298 encoder_config->streams[0].min_bitrate_bps = 50000;
299 encoder_config->streams[0].target_bitrate_bps =
300 encoder_config->streams[0].max_bitrate_bps = 2000000;
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000301
Perba7dc722016-04-19 15:01:23 +0200302 (*receive_configs)[0].renderer = this;
303 (*receive_configs)[0].decoders.resize(1);
304 (*receive_configs)[0].decoders[0].payload_type =
305 send_config->encoder_settings.payload_type;
306 (*receive_configs)[0].decoders[0].payload_name =
307 send_config->encoder_settings.payload_name;
308 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
309 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000310
Perba7dc722016-04-19 15:01:23 +0200311 void OnFrame(const VideoFrame& video_frame) override {
312 EXPECT_EQ(expected_rotation_, video_frame.rotation());
313 if (++frame_counter_ == no_frames_to_wait_for_)
314 observation_complete_.Set();
315 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000316
Perba7dc722016-04-19 15:01:23 +0200317 void OnFrameGeneratorCapturerCreated(
318 test::FrameGeneratorCapturer* frame_generator_capturer) override {
319 frame_generator_capturer->SetFakeRotation(expected_rotation_);
320 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000321
Perba7dc722016-04-19 15:01:23 +0200322 private:
323 int no_frames_to_wait_for_;
324 VideoRotation expected_rotation_;
325 std::string payload_name_;
326 std::unique_ptr<webrtc::VideoEncoder> encoder_;
327 std::unique_ptr<webrtc::VideoDecoder> decoder_;
328 int frame_counter_;
329};
330
331TEST_F(EndToEndTest, SendsAndReceivesVP8Rotation90) {
332 CodecObserver test(5, kVideoRotation_90, "VP8",
333 VideoEncoder::Create(VideoEncoder::kVp8),
334 VP8Decoder::Create());
335 RunBaseTest(&test);
336}
337
Peter Boström12996152016-05-14 02:03:18 +0200338#if !defined(RTC_DISABLE_VP9)
Perba7dc722016-04-19 15:01:23 +0200339TEST_F(EndToEndTest, SendsAndReceivesVP9) {
340 CodecObserver test(500, kVideoRotation_0, "VP9",
341 VideoEncoder::Create(VideoEncoder::kVp9),
342 VP9Decoder::Create());
343 RunBaseTest(&test);
344}
345
346TEST_F(EndToEndTest, SendsAndReceivesVP9VideoRotation90) {
347 CodecObserver test(5, kVideoRotation_90, "VP9",
348 VideoEncoder::Create(VideoEncoder::kVp9),
349 VP9Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800350 RunBaseTest(&test);
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000351}
Peter Boström12996152016-05-14 02:03:18 +0200352#endif // !defined(RTC_DISABLE_VP9)
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000353
hbosbab934b2016-01-27 01:36:03 -0800354#if defined(WEBRTC_END_TO_END_H264_TESTS)
355
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000356TEST_F(EndToEndTest, SendsAndReceivesH264) {
Perba7dc722016-04-19 15:01:23 +0200357 CodecObserver test(500, kVideoRotation_0, "H264",
358 VideoEncoder::Create(VideoEncoder::kH264),
359 H264Decoder::Create());
360 RunBaseTest(&test);
361}
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000362
Perba7dc722016-04-19 15:01:23 +0200363TEST_F(EndToEndTest, SendsAndReceivesH264VideoRotation90) {
364 CodecObserver test(5, kVideoRotation_90, "H264",
365 VideoEncoder::Create(VideoEncoder::kH264),
366 H264Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800367 RunBaseTest(&test);
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000368}
369
hbosbab934b2016-01-27 01:36:03 -0800370#endif // defined(WEBRTC_END_TO_END_H264_TESTS)
371
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000372TEST_F(EndToEndTest, ReceiverUsesLocalSsrc) {
373 class SyncRtcpObserver : public test::EndToEndTest {
374 public:
375 SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {}
376
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000377 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000378 RTCPUtility::RTCPParserV2 parser(packet, length, true);
379 EXPECT_TRUE(parser.IsValid());
380 uint32_t ssrc = 0;
381 ssrc |= static_cast<uint32_t>(packet[4]) << 24;
382 ssrc |= static_cast<uint32_t>(packet[5]) << 16;
383 ssrc |= static_cast<uint32_t>(packet[6]) << 8;
384 ssrc |= static_cast<uint32_t>(packet[7]) << 0;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100385 EXPECT_EQ(kReceiverLocalVideoSsrc, ssrc);
Peter Boström5811a392015-12-10 13:02:50 +0100386 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000387
388 return SEND_PACKET;
389 }
390
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000391 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100392 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000393 << "Timed out while waiting for a receiver RTCP packet to be sent.";
394 }
395 } test;
396
stefane74eef12016-01-08 06:47:13 -0800397 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000398}
399
400TEST_F(EndToEndTest, ReceivesAndRetransmitsNack) {
401 static const int kNumberOfNacksToObserve = 2;
402 static const int kLossBurstSize = 2;
403 static const int kPacketsBetweenLossBursts = 9;
404 class NackObserver : public test::EndToEndTest {
405 public:
406 NackObserver()
407 : EndToEndTest(kLongTimeoutMs),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000408 sent_rtp_packets_(0),
409 packets_left_to_drop_(0),
410 nacks_left_(kNumberOfNacksToObserve) {}
411
412 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000413 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700414 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000415 RTPHeader header;
Peter Boström03671cb2015-12-07 15:22:24 +0100416 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000417
418 // Never drop retransmitted packets.
419 if (dropped_packets_.find(header.sequenceNumber) !=
420 dropped_packets_.end()) {
421 retransmitted_packets_.insert(header.sequenceNumber);
Stefan Holmer586b19b2015-09-18 11:14:31 +0200422 if (nacks_left_ <= 0 &&
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000423 retransmitted_packets_.size() == dropped_packets_.size()) {
Peter Boström5811a392015-12-10 13:02:50 +0100424 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000425 }
426 return SEND_PACKET;
427 }
428
429 ++sent_rtp_packets_;
430
431 // Enough NACKs received, stop dropping packets.
Stefan Holmer586b19b2015-09-18 11:14:31 +0200432 if (nacks_left_ <= 0)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000433 return SEND_PACKET;
434
435 // Check if it's time for a new loss burst.
436 if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
437 packets_left_to_drop_ = kLossBurstSize;
438
Stefan Holmer01b48882015-05-05 10:21:24 +0200439 // Never drop padding packets as those won't be retransmitted.
440 if (packets_left_to_drop_ > 0 && header.paddingLength == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000441 --packets_left_to_drop_;
442 dropped_packets_.insert(header.sequenceNumber);
443 return DROP_PACKET;
444 }
445
446 return SEND_PACKET;
447 }
448
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000449 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700450 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000451 RTCPUtility::RTCPParserV2 parser(packet, length, true);
452 EXPECT_TRUE(parser.IsValid());
453
454 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +0200455 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
456 if (packet_type == RTCPUtility::RTCPPacketTypes::kRtpfbNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000457 --nacks_left_;
458 break;
459 }
460 packet_type = parser.Iterate();
461 }
462 return SEND_PACKET;
463 }
464
stefanff483612015-12-21 03:14:00 -0800465 void ModifyVideoConfigs(
466 VideoSendStream::Config* send_config,
467 std::vector<VideoReceiveStream::Config>* receive_configs,
468 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000469 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000470 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000471 }
472
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000473 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100474 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000475 << "Timed out waiting for packets to be NACKed, retransmitted and "
476 "rendered.";
477 }
478
stefanf116bd02015-10-27 08:29:42 -0700479 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000480 std::set<uint16_t> dropped_packets_;
481 std::set<uint16_t> retransmitted_packets_;
482 uint64_t sent_rtp_packets_;
483 int packets_left_to_drop_;
stefanf116bd02015-10-27 08:29:42 -0700484 int nacks_left_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000485 } test;
486
stefane74eef12016-01-08 06:47:13 -0800487 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000488}
489
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000490TEST_F(EndToEndTest, CanReceiveFec) {
nisse7ade7b32016-03-23 04:48:10 -0700491 class FecRenderObserver : public test::EndToEndTest,
492 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000493 public:
494 FecRenderObserver()
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000495 : EndToEndTest(kDefaultTimeoutMs), state_(kFirstPacket) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000496
497 private:
stefanf116bd02015-10-27 08:29:42 -0700498 Action OnSendRtp(const uint8_t* packet, size_t length) override {
499 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000500 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000501 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000502
Stefan Holmer01b48882015-05-05 10:21:24 +0200503 int encapsulated_payload_type = -1;
504 if (header.payloadType == kRedPayloadType) {
505 encapsulated_payload_type =
506 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100507 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200508 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
509 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100510 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200511 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000512
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000513 if (protected_sequence_numbers_.count(header.sequenceNumber) != 0) {
514 // Retransmitted packet, should not count.
515 protected_sequence_numbers_.erase(header.sequenceNumber);
516 EXPECT_GT(protected_timestamps_.count(header.timestamp), 0u);
517 protected_timestamps_.erase(header.timestamp);
518 return SEND_PACKET;
519 }
520
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000521 switch (state_) {
522 case kFirstPacket:
523 state_ = kDropEveryOtherPacketUntilFec;
524 break;
525 case kDropEveryOtherPacketUntilFec:
526 if (encapsulated_payload_type == kUlpfecPayloadType) {
527 state_ = kDropNextMediaPacket;
528 return SEND_PACKET;
529 }
530 if (header.sequenceNumber % 2 == 0)
531 return DROP_PACKET;
532 break;
533 case kDropNextMediaPacket:
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100534 if (encapsulated_payload_type == kFakeVideoSendPayloadType) {
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000535 protected_sequence_numbers_.insert(header.sequenceNumber);
536 protected_timestamps_.insert(header.timestamp);
537 state_ = kDropEveryOtherPacketUntilFec;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000538 return DROP_PACKET;
539 }
540 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000541 }
542
543 return SEND_PACKET;
544 }
545
nisseeb83a1a2016-03-21 01:27:56 -0700546 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200547 rtc::CritScope lock(&crit_);
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000548 // Rendering frame with timestamp of packet that was dropped -> FEC
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000549 // protection worked.
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000550 if (protected_timestamps_.count(video_frame.timestamp()) != 0)
Peter Boström5811a392015-12-10 13:02:50 +0100551 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000552 }
553
554 enum {
555 kFirstPacket,
556 kDropEveryOtherPacketUntilFec,
557 kDropNextMediaPacket,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000558 } state_;
559
stefanff483612015-12-21 03:14:00 -0800560 void ModifyVideoConfigs(
561 VideoSendStream::Config* send_config,
562 std::vector<VideoReceiveStream::Config>* receive_configs,
563 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000564 // TODO(pbos): Run this test with combined NACK/FEC enabled as well.
565 // int rtp_history_ms = 1000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000566 // (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000567 // send_config->rtp.nack.rtp_history_ms = rtp_history_ms;
568 send_config->rtp.fec.red_payload_type = kRedPayloadType;
569 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
570
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000571 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
572 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
573 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000574 }
575
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000576 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100577 EXPECT_TRUE(Wait())
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000578 << "Timed out waiting for dropped frames frames to be rendered.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000579 }
580
stefanf116bd02015-10-27 08:29:42 -0700581 rtc::CriticalSection crit_;
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000582 std::set<uint32_t> protected_sequence_numbers_ GUARDED_BY(crit_);
583 std::set<uint32_t> protected_timestamps_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000584 } test;
585
stefane74eef12016-01-08 06:47:13 -0800586 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000587}
588
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200589TEST_F(EndToEndTest, ReceivedFecPacketsNotNacked) {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000590 class FecNackObserver : public test::EndToEndTest {
591 public:
mflodmand1590b22015-12-09 07:07:59 -0800592 FecNackObserver()
stefanf116bd02015-10-27 08:29:42 -0700593 : EndToEndTest(kDefaultTimeoutMs),
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000594 state_(kFirstPacket),
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000595 fec_sequence_number_(0),
596 has_last_sequence_number_(false),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200597 last_sequence_number_(0),
598 encoder_(VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)),
599 decoder_(VP8Decoder::Create()) {}
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000600
601 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000602 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800603 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000604 RTPHeader header;
605 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000606
Stefan Holmer01b48882015-05-05 10:21:24 +0200607 int encapsulated_payload_type = -1;
608 if (header.payloadType == kRedPayloadType) {
609 encapsulated_payload_type =
610 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100611 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200612 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
613 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100614 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200615 }
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000616
617 if (has_last_sequence_number_ &&
618 !IsNewerSequenceNumber(header.sequenceNumber,
619 last_sequence_number_)) {
620 // Drop retransmitted packets.
621 return DROP_PACKET;
622 }
623 last_sequence_number_ = header.sequenceNumber;
624 has_last_sequence_number_ = true;
625
626 bool fec_packet = encapsulated_payload_type == kUlpfecPayloadType;
627 switch (state_) {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000628 case kFirstPacket:
629 state_ = kDropEveryOtherPacketUntilFec;
630 break;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000631 case kDropEveryOtherPacketUntilFec:
632 if (fec_packet) {
633 state_ = kDropAllMediaPacketsUntilFec;
634 } else if (header.sequenceNumber % 2 == 0) {
635 return DROP_PACKET;
636 }
637 break;
638 case kDropAllMediaPacketsUntilFec:
639 if (!fec_packet)
640 return DROP_PACKET;
641 fec_sequence_number_ = header.sequenceNumber;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200642 state_ = kDropOneMediaPacket;
643 break;
644 case kDropOneMediaPacket:
645 if (fec_packet)
646 return DROP_PACKET;
647 state_ = kPassOneMediaPacket;
648 return DROP_PACKET;
649 break;
650 case kPassOneMediaPacket:
651 if (fec_packet)
652 return DROP_PACKET;
653 // Pass one media packet after dropped packet after last FEC,
654 // otherwise receiver might never see a seq_no after
655 // |fec_sequence_number_|
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000656 state_ = kVerifyFecPacketNotInNackList;
657 break;
658 case kVerifyFecPacketNotInNackList:
659 // Continue to drop packets. Make sure no frame can be decoded.
660 if (fec_packet || header.sequenceNumber % 2 == 0)
661 return DROP_PACKET;
662 break;
663 }
664 return SEND_PACKET;
665 }
666
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000667 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800668 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000669 if (state_ == kVerifyFecPacketNotInNackList) {
670 test::RtcpPacketParser rtcp_parser;
671 rtcp_parser.Parse(packet, length);
672 std::vector<uint16_t> nacks = rtcp_parser.nack_item()->last_nack_list();
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200673 EXPECT_TRUE(std::find(nacks.begin(), nacks.end(),
674 fec_sequence_number_) == nacks.end())
675 << "Got nack for FEC packet";
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000676 if (!nacks.empty() &&
677 IsNewerSequenceNumber(nacks.back(), fec_sequence_number_)) {
Peter Boström5811a392015-12-10 13:02:50 +0100678 observation_complete_.Set();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000679 }
680 }
681 return SEND_PACKET;
682 }
683
stefane74eef12016-01-08 06:47:13 -0800684 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
685 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
686 // Configure some network delay.
687 const int kNetworkDelayMs = 50;
688 FakeNetworkPipe::Config config;
689 config.queue_delay_ms = kNetworkDelayMs;
690 return new test::PacketTransport(sender_call, this,
691 test::PacketTransport::kSender, config);
692 }
693
Stefan Holmere5904162015-03-26 11:11:06 +0100694 // TODO(holmer): Investigate why we don't send FEC packets when the bitrate
695 // is 10 kbps.
696 Call::Config GetSenderCallConfig() override {
solenberg4fbae2b2015-08-28 04:07:10 -0700697 Call::Config config;
Stefan Holmere5904162015-03-26 11:11:06 +0100698 const int kMinBitrateBps = 30000;
699 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
700 return config;
701 }
702
stefanff483612015-12-21 03:14:00 -0800703 void ModifyVideoConfigs(
704 VideoSendStream::Config* send_config,
705 std::vector<VideoReceiveStream::Config>* receive_configs,
706 VideoEncoderConfig* encoder_config) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000707 // Configure hybrid NACK/FEC.
708 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
709 send_config->rtp.fec.red_payload_type = kRedPayloadType;
710 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200711 // Set codec to VP8, otherwise NACK/FEC hybrid will be disabled.
712 send_config->encoder_settings.encoder = encoder_.get();
713 send_config->encoder_settings.payload_name = "VP8";
714 send_config->encoder_settings.payload_type = kFakeVideoSendPayloadType;
715 encoder_config->streams[0].min_bitrate_bps = 50000;
716 encoder_config->streams[0].max_bitrate_bps =
717 encoder_config->streams[0].target_bitrate_bps = 2000000;
718
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000719 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
720 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
721 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200722
723 (*receive_configs)[0].decoders.resize(1);
724 (*receive_configs)[0].decoders[0].payload_type =
725 send_config->encoder_settings.payload_type;
726 (*receive_configs)[0].decoders[0].payload_name =
727 send_config->encoder_settings.payload_name;
728 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000729 }
730
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000731 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100732 EXPECT_TRUE(Wait())
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000733 << "Timed out while waiting for FEC packets to be received.";
734 }
735
736 enum {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000737 kFirstPacket,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000738 kDropEveryOtherPacketUntilFec,
739 kDropAllMediaPacketsUntilFec,
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200740 kDropOneMediaPacket,
741 kPassOneMediaPacket,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000742 kVerifyFecPacketNotInNackList,
743 } state_;
744
stefan608213e2015-11-01 14:56:10 -0800745 rtc::CriticalSection crit_;
746 uint16_t fec_sequence_number_ GUARDED_BY(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000747 bool has_last_sequence_number_;
748 uint16_t last_sequence_number_;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200749 std::unique_ptr<webrtc::VideoEncoder> encoder_;
750 std::unique_ptr<webrtc::VideoDecoder> decoder_;
stefanf116bd02015-10-27 08:29:42 -0700751 } test;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000752
stefane74eef12016-01-08 06:47:13 -0800753 RunBaseTest(&test);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000754}
755
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000756// This test drops second RTP packet with a marker bit set, makes sure it's
757// retransmitted and renders. Retransmission SSRCs are also checked.
Peter Boström39593972016-02-15 11:27:15 +0100758void EndToEndTest::DecodesRetransmittedFrame(bool enable_rtx, bool enable_red) {
Peter Boström67680c12016-02-17 11:10:04 +0100759 static const int kDroppedFrameNumber = 10;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000760 class RetransmissionObserver : public test::EndToEndTest,
761 public I420FrameCallback {
762 public:
Peter Boström39593972016-02-15 11:27:15 +0100763 RetransmissionObserver(bool enable_rtx, bool enable_red)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000764 : EndToEndTest(kDefaultTimeoutMs),
Peter Boström39593972016-02-15 11:27:15 +0100765 payload_type_(GetPayloadType(false, enable_red)),
766 retransmission_ssrc_(enable_rtx ? kSendRtxSsrcs[0]
767 : kVideoSendSsrcs[0]),
768 retransmission_payload_type_(GetPayloadType(enable_rtx, enable_red)),
769 encoder_(VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000770 marker_bits_observed_(0),
771 retransmitted_timestamp_(0),
772 frame_retransmitted_(false) {}
773
774 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000775 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700776 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000777 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000778 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000779
Peter Boström67680c12016-02-17 11:10:04 +0100780 // Ignore padding-only packets over RTX.
781 if (header.payloadType != payload_type_) {
782 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
783 if (length == header.headerLength + header.paddingLength)
784 return SEND_PACKET;
Stefan Holmer586b19b2015-09-18 11:14:31 +0200785 }
Peter Boström67680c12016-02-17 11:10:04 +0100786
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000787 if (header.timestamp == retransmitted_timestamp_) {
788 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
789 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
790 frame_retransmitted_ = true;
791 return SEND_PACKET;
792 }
793
Stefan Holmer10880012016-02-03 13:29:59 +0100794 EXPECT_EQ(kVideoSendSsrcs[0], header.ssrc)
Danil Chapovalov18c65a42016-06-29 15:29:34 +0200795 << "Unexpected packet length " << length
796 << ", header_length " << header.headerLength
797 << ", padding_length " << header.paddingLength
798 << ", timestamp " << header.timestamp
799 << ", expected timestamp " << retransmitted_timestamp_
800 << ", payload type " << static_cast<int>(header.payloadType);
Shao Changbine62202f2015-04-21 20:24:50 +0800801 EXPECT_EQ(payload_type_, header.payloadType);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000802
Stefan Holmer586b19b2015-09-18 11:14:31 +0200803 // Found the final packet of the frame to inflict loss to, drop this and
804 // expect a retransmission.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000805 if (header.markerBit && ++marker_bits_observed_ == kDroppedFrameNumber) {
Danil Chapovalov18c65a42016-06-29 15:29:34 +0200806 // This should be the only dropped packet.
807 EXPECT_EQ(0u, retransmitted_timestamp_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000808 retransmitted_timestamp_ = header.timestamp;
809 return DROP_PACKET;
810 }
811
812 return SEND_PACKET;
813 }
814
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700815 void FrameCallback(VideoFrame* frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200816 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000817 if (frame->timestamp() == retransmitted_timestamp_) {
818 EXPECT_TRUE(frame_retransmitted_);
Peter Boström5811a392015-12-10 13:02:50 +0100819 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000820 }
821 }
822
stefanff483612015-12-21 03:14:00 -0800823 void ModifyVideoConfigs(
824 VideoSendStream::Config* send_config,
825 std::vector<VideoReceiveStream::Config>* receive_configs,
826 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000827 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000828 (*receive_configs)[0].pre_render_callback = this;
829 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
Shao Changbine62202f2015-04-21 20:24:50 +0800830
831 if (payload_type_ == kRedPayloadType) {
832 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
833 send_config->rtp.fec.red_payload_type = kRedPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +0100834 if (retransmission_ssrc_ == kSendRtxSsrcs[0])
835 send_config->rtp.fec.red_rtx_payload_type = kRtxRedPayloadType;
836 (*receive_configs)[0].rtp.fec.ulpfec_payload_type =
837 send_config->rtp.fec.ulpfec_payload_type;
838 (*receive_configs)[0].rtp.fec.red_payload_type =
839 send_config->rtp.fec.red_payload_type;
840 (*receive_configs)[0].rtp.fec.red_rtx_payload_type =
841 send_config->rtp.fec.red_rtx_payload_type;
Shao Changbine62202f2015-04-21 20:24:50 +0800842 }
843
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000844 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
845 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000846 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +0100847 (*receive_configs)[0].rtp.rtx[payload_type_].ssrc = kSendRtxSsrcs[0];
848 (*receive_configs)[0].rtp.rtx[payload_type_].payload_type =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000849 kSendRtxPayloadType;
850 }
Peter Boström39593972016-02-15 11:27:15 +0100851 // Configure encoding and decoding with VP8, since generic packetization
852 // doesn't support FEC with NACK.
853 RTC_DCHECK_EQ(1u, (*receive_configs)[0].decoders.size());
854 send_config->encoder_settings.encoder = encoder_.get();
855 send_config->encoder_settings.payload_name = "VP8";
856 (*receive_configs)[0].decoders[0].payload_name = "VP8";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000857 }
858
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000859 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100860 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000861 << "Timed out while waiting for retransmission to render.";
862 }
863
Shao Changbine62202f2015-04-21 20:24:50 +0800864 int GetPayloadType(bool use_rtx, bool use_red) {
Stefan Holmer10880012016-02-03 13:29:59 +0100865 if (use_red) {
866 if (use_rtx)
867 return kRtxRedPayloadType;
868 return kRedPayloadType;
869 }
870 if (use_rtx)
871 return kSendRtxPayloadType;
872 return kFakeVideoSendPayloadType;
Shao Changbine62202f2015-04-21 20:24:50 +0800873 }
874
stefanf116bd02015-10-27 08:29:42 -0700875 rtc::CriticalSection crit_;
Shao Changbine62202f2015-04-21 20:24:50 +0800876 const int payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000877 const uint32_t retransmission_ssrc_;
878 const int retransmission_payload_type_;
kwiberg27f982b2016-03-01 11:52:33 -0800879 std::unique_ptr<VideoEncoder> encoder_;
Peter Boström39593972016-02-15 11:27:15 +0100880 const std::string payload_name_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000881 int marker_bits_observed_;
stefanf116bd02015-10-27 08:29:42 -0700882 uint32_t retransmitted_timestamp_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000883 bool frame_retransmitted_;
Peter Boström39593972016-02-15 11:27:15 +0100884 } test(enable_rtx, enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000885
stefane74eef12016-01-08 06:47:13 -0800886 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000887}
888
889TEST_F(EndToEndTest, DecodesRetransmittedFrame) {
Shao Changbine62202f2015-04-21 20:24:50 +0800890 DecodesRetransmittedFrame(false, false);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000891}
892
893TEST_F(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +0800894 DecodesRetransmittedFrame(true, false);
895}
896
897TEST_F(EndToEndTest, DecodesRetransmittedFrameByRed) {
898 DecodesRetransmittedFrame(false, true);
899}
900
901TEST_F(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
902 DecodesRetransmittedFrame(true, true);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000903}
904
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000905void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
906 static const int kPacketsToDrop = 1;
907
nisse7ade7b32016-03-23 04:48:10 -0700908 class PliObserver : public test::EndToEndTest,
909 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000910 public:
911 explicit PliObserver(int rtp_history_ms)
912 : EndToEndTest(kLongTimeoutMs),
913 rtp_history_ms_(rtp_history_ms),
914 nack_enabled_(rtp_history_ms > 0),
915 highest_dropped_timestamp_(0),
916 frames_to_drop_(0),
917 received_pli_(false) {}
918
919 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000920 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700921 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000922 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000923 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000924
925 // Drop all retransmitted packets to force a PLI.
926 if (header.timestamp <= highest_dropped_timestamp_)
927 return DROP_PACKET;
928
929 if (frames_to_drop_ > 0) {
930 highest_dropped_timestamp_ = header.timestamp;
931 --frames_to_drop_;
932 return DROP_PACKET;
933 }
934
935 return SEND_PACKET;
936 }
937
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000938 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700939 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000940 RTCPUtility::RTCPParserV2 parser(packet, length, true);
941 EXPECT_TRUE(parser.IsValid());
942
943 for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +0200944 packet_type != RTCPUtility::RTCPPacketTypes::kInvalid;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000945 packet_type = parser.Iterate()) {
946 if (!nack_enabled_)
Erik Språng242e22b2015-05-11 10:17:43 +0200947 EXPECT_NE(packet_type, RTCPUtility::RTCPPacketTypes::kRtpfbNack);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000948
Erik Språng242e22b2015-05-11 10:17:43 +0200949 if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbPli) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000950 received_pli_ = true;
951 break;
952 }
953 }
954 return SEND_PACKET;
955 }
956
nisseeb83a1a2016-03-21 01:27:56 -0700957 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200958 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000959 if (received_pli_ &&
960 video_frame.timestamp() > highest_dropped_timestamp_) {
Peter Boström5811a392015-12-10 13:02:50 +0100961 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000962 }
963 if (!received_pli_)
964 frames_to_drop_ = kPacketsToDrop;
965 }
966
stefanff483612015-12-21 03:14:00 -0800967 void ModifyVideoConfigs(
968 VideoSendStream::Config* send_config,
969 std::vector<VideoReceiveStream::Config>* receive_configs,
970 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000971 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000972 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
973 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000974 }
975
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000976 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100977 EXPECT_TRUE(Wait()) << "Timed out waiting for PLI to be "
978 "received and a frame to be "
979 "rendered afterwards.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000980 }
981
stefanf116bd02015-10-27 08:29:42 -0700982 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000983 int rtp_history_ms_;
984 bool nack_enabled_;
stefanf116bd02015-10-27 08:29:42 -0700985 uint32_t highest_dropped_timestamp_ GUARDED_BY(&crit_);
986 int frames_to_drop_ GUARDED_BY(&crit_);
987 bool received_pli_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000988 } test(rtp_history_ms);
989
stefane74eef12016-01-08 06:47:13 -0800990 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000991}
992
993TEST_F(EndToEndTest, ReceivesPliAndRecoversWithNack) {
994 ReceivesPliAndRecovers(1000);
995}
996
jbauchdb81ffd2015-11-23 03:59:02 -0800997TEST_F(EndToEndTest, ReceivesPliAndRecoversWithoutNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000998 ReceivesPliAndRecovers(0);
999}
1000
1001TEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
1002 class PacketInputObserver : public PacketReceiver {
1003 public:
1004 explicit PacketInputObserver(PacketReceiver* receiver)
Peter Boström5811a392015-12-10 13:02:50 +01001005 : receiver_(receiver), delivered_packet_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001006
Peter Boström5811a392015-12-10 13:02:50 +01001007 bool Wait() { return delivered_packet_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001008
1009 private:
stefan68786d22015-09-08 05:36:15 -07001010 DeliveryStatus DeliverPacket(MediaType media_type,
1011 const uint8_t* packet,
1012 size_t length,
1013 const PacketTime& packet_time) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001014 if (RtpHeaderParser::IsRtcp(packet, length)) {
stefan68786d22015-09-08 05:36:15 -07001015 return receiver_->DeliverPacket(media_type, packet, length,
1016 packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001017 } else {
1018 DeliveryStatus delivery_status =
stefan68786d22015-09-08 05:36:15 -07001019 receiver_->DeliverPacket(media_type, packet, length, packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001020 EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
Peter Boström5811a392015-12-10 13:02:50 +01001021 delivered_packet_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001022 return delivery_status;
1023 }
1024 }
1025
1026 PacketReceiver* receiver_;
Peter Boström5811a392015-12-10 13:02:50 +01001027 rtc::Event delivered_packet_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001028 };
1029
solenberg4fbae2b2015-08-28 04:07:10 -07001030 CreateCalls(Call::Config(), Call::Config());
1031
stefanf116bd02015-10-27 08:29:42 -07001032 test::DirectTransport send_transport(sender_call_.get());
1033 test::DirectTransport receive_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001034 PacketInputObserver input_observer(receiver_call_->Receiver());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001035 send_transport.SetReceiver(&input_observer);
1036 receive_transport.SetReceiver(sender_call_->Receiver());
1037
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001038 CreateSendConfig(1, 0, &send_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001039 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001040
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001041 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001042 CreateFrameGeneratorCapturer();
1043 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001044
stefanff483612015-12-21 03:14:00 -08001045 receiver_call_->DestroyVideoReceiveStream(video_receive_streams_[0]);
1046 video_receive_streams_.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001047
1048 // Wait() waits for a received packet.
Peter Boström5811a392015-12-10 13:02:50 +01001049 EXPECT_TRUE(input_observer.Wait());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001050
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001051 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001052
1053 DestroyStreams();
1054
1055 send_transport.StopSending();
1056 receive_transport.StopSending();
1057}
1058
pbosda903ea2015-10-02 02:36:56 -07001059void EndToEndTest::RespectsRtcpMode(RtcpMode rtcp_mode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001060 static const int kNumCompoundRtcpPacketsToObserve = 10;
1061 class RtcpModeObserver : public test::EndToEndTest {
1062 public:
pbosda903ea2015-10-02 02:36:56 -07001063 explicit RtcpModeObserver(RtcpMode rtcp_mode)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001064 : EndToEndTest(kDefaultTimeoutMs),
1065 rtcp_mode_(rtcp_mode),
1066 sent_rtp_(0),
1067 sent_rtcp_(0) {}
1068
1069 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001070 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001071 if (++sent_rtp_ % 3 == 0)
1072 return DROP_PACKET;
1073
1074 return SEND_PACKET;
1075 }
1076
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001077 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001078 ++sent_rtcp_;
1079 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1080 EXPECT_TRUE(parser.IsValid());
1081
1082 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1083 bool has_report_block = false;
Erik Språng242e22b2015-05-11 10:17:43 +02001084 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1085 EXPECT_NE(RTCPUtility::RTCPPacketTypes::kSr, packet_type);
1086 if (packet_type == RTCPUtility::RTCPPacketTypes::kRr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001087 has_report_block = true;
1088 break;
1089 }
1090 packet_type = parser.Iterate();
1091 }
1092
1093 switch (rtcp_mode_) {
pbosda903ea2015-10-02 02:36:56 -07001094 case RtcpMode::kCompound:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001095 if (!has_report_block) {
1096 ADD_FAILURE() << "Received RTCP packet without receiver report for "
pbosda903ea2015-10-02 02:36:56 -07001097 "RtcpMode::kCompound.";
Peter Boström5811a392015-12-10 13:02:50 +01001098 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001099 }
1100
1101 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
Peter Boström5811a392015-12-10 13:02:50 +01001102 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001103
1104 break;
pbosda903ea2015-10-02 02:36:56 -07001105 case RtcpMode::kReducedSize:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001106 if (!has_report_block)
Peter Boström5811a392015-12-10 13:02:50 +01001107 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001108 break;
pbosda903ea2015-10-02 02:36:56 -07001109 case RtcpMode::kOff:
1110 RTC_NOTREACHED();
1111 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001112 }
1113
1114 return SEND_PACKET;
1115 }
1116
stefanff483612015-12-21 03:14:00 -08001117 void ModifyVideoConfigs(
1118 VideoSendStream::Config* send_config,
1119 std::vector<VideoReceiveStream::Config>* receive_configs,
1120 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001121 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001122 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1123 (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001124 }
1125
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001126 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001127 EXPECT_TRUE(Wait())
pbosda903ea2015-10-02 02:36:56 -07001128 << (rtcp_mode_ == RtcpMode::kCompound
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001129 ? "Timed out before observing enough compound packets."
1130 : "Timed out before receiving a non-compound RTCP packet.");
1131 }
1132
pbosda903ea2015-10-02 02:36:56 -07001133 RtcpMode rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001134 int sent_rtp_;
1135 int sent_rtcp_;
1136 } test(rtcp_mode);
1137
stefane74eef12016-01-08 06:47:13 -08001138 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001139}
1140
1141TEST_F(EndToEndTest, UsesRtcpCompoundMode) {
pbosda903ea2015-10-02 02:36:56 -07001142 RespectsRtcpMode(RtcpMode::kCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001143}
1144
1145TEST_F(EndToEndTest, UsesRtcpReducedSizeMode) {
pbosda903ea2015-10-02 02:36:56 -07001146 RespectsRtcpMode(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001147}
1148
1149// Test sets up a Call multiple senders with different resolutions and SSRCs.
1150// Another is set up to receive all three of these with different renderers.
sprang867fb522015-08-03 04:38:41 -07001151class MultiStreamTest {
1152 public:
1153 static const size_t kNumStreams = 3;
1154 struct CodecSettings {
1155 uint32_t ssrc;
1156 int width;
1157 int height;
1158 } codec_settings[kNumStreams];
1159
1160 MultiStreamTest() {
1161 // TODO(sprang): Cleanup when msvc supports explicit initializers for array.
1162 codec_settings[0] = {1, 640, 480};
1163 codec_settings[1] = {2, 320, 240};
1164 codec_settings[2] = {3, 240, 160};
1165 }
1166
1167 virtual ~MultiStreamTest() {}
1168
1169 void RunTest() {
kwiberg27f982b2016-03-01 11:52:33 -08001170 std::unique_ptr<Call> sender_call(Call::Create(Call::Config()));
1171 std::unique_ptr<Call> receiver_call(Call::Create(Call::Config()));
1172 std::unique_ptr<test::DirectTransport> sender_transport(
stefanf116bd02015-10-27 08:29:42 -07001173 CreateSendTransport(sender_call.get()));
kwiberg27f982b2016-03-01 11:52:33 -08001174 std::unique_ptr<test::DirectTransport> receiver_transport(
stefanf116bd02015-10-27 08:29:42 -07001175 CreateReceiveTransport(receiver_call.get()));
sprang867fb522015-08-03 04:38:41 -07001176 sender_transport->SetReceiver(receiver_call->Receiver());
1177 receiver_transport->SetReceiver(sender_call->Receiver());
1178
kwiberg27f982b2016-03-01 11:52:33 -08001179 std::unique_ptr<VideoEncoder> encoders[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001180 for (size_t i = 0; i < kNumStreams; ++i)
1181 encoders[i].reset(VideoEncoder::Create(VideoEncoder::kVp8));
1182
1183 VideoSendStream* send_streams[kNumStreams];
1184 VideoReceiveStream* receive_streams[kNumStreams];
1185
1186 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
kwiberg4a206a92016-03-31 10:24:26 -07001187 std::vector<std::unique_ptr<VideoDecoder>> allocated_decoders;
sprang867fb522015-08-03 04:38:41 -07001188 for (size_t i = 0; i < kNumStreams; ++i) {
1189 uint32_t ssrc = codec_settings[i].ssrc;
1190 int width = codec_settings[i].width;
1191 int height = codec_settings[i].height;
1192
solenberg4fbae2b2015-08-28 04:07:10 -07001193 VideoSendStream::Config send_config(sender_transport.get());
sprang867fb522015-08-03 04:38:41 -07001194 send_config.rtp.ssrcs.push_back(ssrc);
1195 send_config.encoder_settings.encoder = encoders[i].get();
1196 send_config.encoder_settings.payload_name = "VP8";
1197 send_config.encoder_settings.payload_type = 124;
1198 VideoEncoderConfig encoder_config;
1199 encoder_config.streams = test::CreateVideoStreams(1);
1200 VideoStream* stream = &encoder_config.streams[0];
1201 stream->width = width;
1202 stream->height = height;
1203 stream->max_framerate = 5;
1204 stream->min_bitrate_bps = stream->target_bitrate_bps =
1205 stream->max_bitrate_bps = 100000;
1206
1207 UpdateSendConfig(i, &send_config, &encoder_config, &frame_generators[i]);
1208
1209 send_streams[i] =
1210 sender_call->CreateVideoSendStream(send_config, encoder_config);
1211 send_streams[i]->Start();
1212
solenberg4fbae2b2015-08-28 04:07:10 -07001213 VideoReceiveStream::Config receive_config(receiver_transport.get());
sprang867fb522015-08-03 04:38:41 -07001214 receive_config.rtp.remote_ssrc = ssrc;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001215 receive_config.rtp.local_ssrc = test::CallTest::kReceiverLocalVideoSsrc;
sprang867fb522015-08-03 04:38:41 -07001216 VideoReceiveStream::Decoder decoder =
1217 test::CreateMatchingDecoder(send_config.encoder_settings);
kwiberg4a206a92016-03-31 10:24:26 -07001218 allocated_decoders.push_back(
1219 std::unique_ptr<VideoDecoder>(decoder.decoder));
sprang867fb522015-08-03 04:38:41 -07001220 receive_config.decoders.push_back(decoder);
1221
1222 UpdateReceiveConfig(i, &receive_config);
1223
1224 receive_streams[i] =
Tommi733b5472016-06-10 17:58:01 +02001225 receiver_call->CreateVideoReceiveStream(std::move(receive_config));
sprang867fb522015-08-03 04:38:41 -07001226 receive_streams[i]->Start();
1227
1228 frame_generators[i] = test::FrameGeneratorCapturer::Create(
1229 send_streams[i]->Input(), width, height, 30,
1230 Clock::GetRealTimeClock());
1231 frame_generators[i]->Start();
1232 }
1233
1234 Wait();
1235
1236 for (size_t i = 0; i < kNumStreams; ++i) {
1237 frame_generators[i]->Stop();
1238 sender_call->DestroyVideoSendStream(send_streams[i]);
1239 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1240 delete frame_generators[i];
1241 }
1242
1243 sender_transport->StopSending();
1244 receiver_transport->StopSending();
1245 }
1246
1247 protected:
1248 virtual void Wait() = 0;
1249 // Note: frame_generator is a point-to-pointer, since the actual instance
1250 // hasn't been created at the time of this call. Only when packets/frames
1251 // start flowing should this be dereferenced.
1252 virtual void UpdateSendConfig(
1253 size_t stream_index,
1254 VideoSendStream::Config* send_config,
1255 VideoEncoderConfig* encoder_config,
1256 test::FrameGeneratorCapturer** frame_generator) {}
1257 virtual void UpdateReceiveConfig(size_t stream_index,
1258 VideoReceiveStream::Config* receive_config) {
1259 }
stefanf116bd02015-10-27 08:29:42 -07001260 virtual test::DirectTransport* CreateSendTransport(Call* sender_call) {
1261 return new test::DirectTransport(sender_call);
sprang867fb522015-08-03 04:38:41 -07001262 }
stefanf116bd02015-10-27 08:29:42 -07001263 virtual test::DirectTransport* CreateReceiveTransport(Call* receiver_call) {
1264 return new test::DirectTransport(receiver_call);
sprang867fb522015-08-03 04:38:41 -07001265 }
1266};
1267
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001268// Each renderer verifies that it receives the expected resolution, and as soon
1269// as every renderer has received a frame, the test finishes.
andresp@webrtc.org02686112014-09-19 08:24:19 +00001270TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) {
nisse7ade7b32016-03-23 04:48:10 -07001271 class VideoOutputObserver : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001272 public:
sprang867fb522015-08-03 04:38:41 -07001273 VideoOutputObserver(const MultiStreamTest::CodecSettings& settings,
1274 uint32_t ssrc,
1275 test::FrameGeneratorCapturer** frame_generator)
1276 : settings_(settings),
1277 ssrc_(ssrc),
1278 frame_generator_(frame_generator),
Peter Boström5811a392015-12-10 13:02:50 +01001279 done_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001280
nisseeb83a1a2016-03-21 01:27:56 -07001281 void OnFrame(const VideoFrame& video_frame) override {
sprang867fb522015-08-03 04:38:41 -07001282 EXPECT_EQ(settings_.width, video_frame.width());
1283 EXPECT_EQ(settings_.height, video_frame.height());
1284 (*frame_generator_)->Stop();
Peter Boström5811a392015-12-10 13:02:50 +01001285 done_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001286 }
1287
sprang867fb522015-08-03 04:38:41 -07001288 uint32_t Ssrc() { return ssrc_; }
1289
Peter Boström5811a392015-12-10 13:02:50 +01001290 bool Wait() { return done_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001291
1292 private:
sprang867fb522015-08-03 04:38:41 -07001293 const MultiStreamTest::CodecSettings& settings_;
1294 const uint32_t ssrc_;
1295 test::FrameGeneratorCapturer** const frame_generator_;
Peter Boström5811a392015-12-10 13:02:50 +01001296 rtc::Event done_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001297 };
1298
sprang867fb522015-08-03 04:38:41 -07001299 class Tester : public MultiStreamTest {
1300 public:
1301 Tester() {}
1302 virtual ~Tester() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001303
sprang867fb522015-08-03 04:38:41 -07001304 protected:
1305 void Wait() override {
1306 for (const auto& observer : observers_) {
Peter Boström5811a392015-12-10 13:02:50 +01001307 EXPECT_TRUE(observer->Wait()) << "Time out waiting for from on ssrc "
1308 << observer->Ssrc();
sprang867fb522015-08-03 04:38:41 -07001309 }
1310 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001311
sprang867fb522015-08-03 04:38:41 -07001312 void UpdateSendConfig(
1313 size_t stream_index,
1314 VideoSendStream::Config* send_config,
1315 VideoEncoderConfig* encoder_config,
1316 test::FrameGeneratorCapturer** frame_generator) override {
1317 observers_[stream_index].reset(new VideoOutputObserver(
1318 codec_settings[stream_index], send_config->rtp.ssrcs.front(),
1319 frame_generator));
1320 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001321
sprang867fb522015-08-03 04:38:41 -07001322 void UpdateReceiveConfig(
1323 size_t stream_index,
1324 VideoReceiveStream::Config* receive_config) override {
1325 receive_config->renderer = observers_[stream_index].get();
1326 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001327
sprang867fb522015-08-03 04:38:41 -07001328 private:
kwiberg27f982b2016-03-01 11:52:33 -08001329 std::unique_ptr<VideoOutputObserver> observers_[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001330 } tester;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001331
sprang867fb522015-08-03 04:38:41 -07001332 tester.RunTest();
1333}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001334
sprang867fb522015-08-03 04:38:41 -07001335TEST_F(EndToEndTest, AssignsTransportSequenceNumbers) {
sprang867fb522015-08-03 04:38:41 -07001336 static const int kExtensionId = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001337
sprang867fb522015-08-03 04:38:41 -07001338 class RtpExtensionHeaderObserver : public test::DirectTransport {
1339 public:
stefanf116bd02015-10-27 08:29:42 -07001340 RtpExtensionHeaderObserver(Call* sender_call,
1341 const uint32_t& first_media_ssrc,
sprang861c55e2015-10-16 10:01:21 -07001342 const std::map<uint32_t, uint32_t>& ssrc_map)
stefanf116bd02015-10-27 08:29:42 -07001343 : DirectTransport(sender_call),
Peter Boström5811a392015-12-10 13:02:50 +01001344 done_(false, false),
sprang867fb522015-08-03 04:38:41 -07001345 parser_(RtpHeaderParser::Create()),
sprang861c55e2015-10-16 10:01:21 -07001346 first_media_ssrc_(first_media_ssrc),
1347 rtx_to_media_ssrcs_(ssrc_map),
sprang867fb522015-08-03 04:38:41 -07001348 padding_observed_(false),
sprang861c55e2015-10-16 10:01:21 -07001349 rtx_padding_observed_(false),
1350 retransmit_observed_(false),
1351 started_(false) {
sprang867fb522015-08-03 04:38:41 -07001352 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
1353 kExtensionId);
1354 }
1355 virtual ~RtpExtensionHeaderObserver() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001356
stefan1d8a5062015-10-02 03:39:33 -07001357 bool SendRtp(const uint8_t* data,
1358 size_t length,
1359 const PacketOptions& options) override {
sprang861c55e2015-10-16 10:01:21 -07001360 {
1361 rtc::CritScope cs(&lock_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001362
Erik Språng8d629712015-08-04 16:24:03 +02001363 if (IsDone())
sprang861c55e2015-10-16 10:01:21 -07001364 return false;
1365
1366 if (started_) {
1367 RTPHeader header;
1368 EXPECT_TRUE(parser_->Parse(data, length, &header));
1369 bool drop_packet = false;
1370
1371 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
1372 EXPECT_EQ(options.packet_id,
1373 header.extension.transportSequenceNumber);
1374 if (!streams_observed_.empty()) {
1375 // Unwrap packet id and verify uniqueness.
1376 int64_t packet_id = unwrapper_.Unwrap(options.packet_id);
1377 EXPECT_TRUE(received_packed_ids_.insert(packet_id).second);
1378 }
1379
1380 // Drop (up to) every 17th packet, so we get retransmits.
1381 // Only drop media, and not on the first stream (otherwise it will be
1382 // hard to distinguish from padding, which is always sent on the first
1383 // stream).
1384 if (header.payloadType != kSendRtxPayloadType &&
1385 header.ssrc != first_media_ssrc_ &&
1386 header.extension.transportSequenceNumber % 17 == 0) {
1387 dropped_seq_[header.ssrc].insert(header.sequenceNumber);
1388 drop_packet = true;
1389 }
1390
1391 size_t payload_length =
1392 length - (header.headerLength + header.paddingLength);
1393 if (payload_length == 0) {
1394 padding_observed_ = true;
1395 } else if (header.payloadType == kSendRtxPayloadType) {
1396 uint16_t original_sequence_number =
1397 ByteReader<uint16_t>::ReadBigEndian(&data[header.headerLength]);
1398 uint32_t original_ssrc =
1399 rtx_to_media_ssrcs_.find(header.ssrc)->second;
1400 std::set<uint16_t>* seq_no_map = &dropped_seq_[original_ssrc];
1401 auto it = seq_no_map->find(original_sequence_number);
1402 if (it != seq_no_map->end()) {
1403 retransmit_observed_ = true;
1404 seq_no_map->erase(it);
1405 } else {
1406 rtx_padding_observed_ = true;
1407 }
1408 } else {
1409 streams_observed_.insert(header.ssrc);
1410 }
1411
1412 if (IsDone())
Peter Boström5811a392015-12-10 13:02:50 +01001413 done_.Set();
sprang861c55e2015-10-16 10:01:21 -07001414
1415 if (drop_packet)
1416 return true;
1417 }
sprang867fb522015-08-03 04:38:41 -07001418 }
sprang861c55e2015-10-16 10:01:21 -07001419
stefan1d8a5062015-10-02 03:39:33 -07001420 return test::DirectTransport::SendRtp(data, length, options);
sprang867fb522015-08-03 04:38:41 -07001421 }
1422
Erik Språng8d629712015-08-04 16:24:03 +02001423 bool IsDone() {
sprang861c55e2015-10-16 10:01:21 -07001424 bool observed_types_ok =
1425 streams_observed_.size() == MultiStreamTest::kNumStreams &&
1426 padding_observed_ && retransmit_observed_ && rtx_padding_observed_;
1427 if (!observed_types_ok)
1428 return false;
1429 // We should not have any gaps in the sequence number range.
1430 size_t seqno_range =
1431 *received_packed_ids_.rbegin() - *received_packed_ids_.begin() + 1;
1432 return seqno_range == received_packed_ids_.size();
Erik Språng8d629712015-08-04 16:24:03 +02001433 }
1434
Peter Boström5811a392015-12-10 13:02:50 +01001435 bool Wait() {
sprang861c55e2015-10-16 10:01:21 -07001436 {
1437 // Can't be sure until this point that rtx_to_media_ssrcs_ etc have
1438 // been initialized and are OK to read.
1439 rtc::CritScope cs(&lock_);
1440 started_ = true;
1441 }
Peter Boström5811a392015-12-10 13:02:50 +01001442 return done_.Wait(kDefaultTimeoutMs);
sprang861c55e2015-10-16 10:01:21 -07001443 }
sprang867fb522015-08-03 04:38:41 -07001444
sprang861c55e2015-10-16 10:01:21 -07001445 rtc::CriticalSection lock_;
Peter Boström5811a392015-12-10 13:02:50 +01001446 rtc::Event done_;
kwiberg27f982b2016-03-01 11:52:33 -08001447 std::unique_ptr<RtpHeaderParser> parser_;
sprang861c55e2015-10-16 10:01:21 -07001448 SequenceNumberUnwrapper unwrapper_;
1449 std::set<int64_t> received_packed_ids_;
sprang867fb522015-08-03 04:38:41 -07001450 std::set<uint32_t> streams_observed_;
sprang861c55e2015-10-16 10:01:21 -07001451 std::map<uint32_t, std::set<uint16_t>> dropped_seq_;
1452 const uint32_t& first_media_ssrc_;
1453 const std::map<uint32_t, uint32_t>& rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001454 bool padding_observed_;
1455 bool rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001456 bool retransmit_observed_;
1457 bool started_;
sprang867fb522015-08-03 04:38:41 -07001458 };
1459
1460 class TransportSequenceNumberTester : public MultiStreamTest {
1461 public:
sprang861c55e2015-10-16 10:01:21 -07001462 TransportSequenceNumberTester()
1463 : first_media_ssrc_(0), observer_(nullptr) {}
sprang867fb522015-08-03 04:38:41 -07001464 virtual ~TransportSequenceNumberTester() {}
1465
1466 protected:
1467 void Wait() override {
Peter Boström74f6e9e2016-04-04 17:56:10 +02001468 RTC_DCHECK(observer_);
Peter Boström5811a392015-12-10 13:02:50 +01001469 EXPECT_TRUE(observer_->Wait());
sprang867fb522015-08-03 04:38:41 -07001470 }
1471
1472 void UpdateSendConfig(
1473 size_t stream_index,
1474 VideoSendStream::Config* send_config,
1475 VideoEncoderConfig* encoder_config,
1476 test::FrameGeneratorCapturer** frame_generator) override {
1477 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001478 send_config->rtp.extensions.push_back(RtpExtension(
1479 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sprang867fb522015-08-03 04:38:41 -07001480
1481 // Force some padding to be sent.
1482 const int kPaddingBitrateBps = 50000;
1483 int total_target_bitrate = 0;
1484 for (const VideoStream& stream : encoder_config->streams)
1485 total_target_bitrate += stream.target_bitrate_bps;
1486 encoder_config->min_transmit_bitrate_bps =
1487 total_target_bitrate + kPaddingBitrateBps;
1488
1489 // Configure RTX for redundant payload padding.
1490 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang861c55e2015-10-16 10:01:21 -07001491 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[stream_index]);
sprang867fb522015-08-03 04:38:41 -07001492 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
sprang861c55e2015-10-16 10:01:21 -07001493 rtx_to_media_ssrcs_[kSendRtxSsrcs[stream_index]] =
1494 send_config->rtp.ssrcs[0];
1495
1496 if (stream_index == 0)
1497 first_media_ssrc_ = send_config->rtp.ssrcs[0];
sprang867fb522015-08-03 04:38:41 -07001498 }
1499
1500 void UpdateReceiveConfig(
1501 size_t stream_index,
1502 VideoReceiveStream::Config* receive_config) override {
sprang861c55e2015-10-16 10:01:21 -07001503 receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang867fb522015-08-03 04:38:41 -07001504 receive_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001505 receive_config->rtp.extensions.push_back(RtpExtension(
1506 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sprang867fb522015-08-03 04:38:41 -07001507 }
1508
stefanf116bd02015-10-27 08:29:42 -07001509 test::DirectTransport* CreateSendTransport(Call* sender_call) override {
1510 observer_ = new RtpExtensionHeaderObserver(sender_call, first_media_ssrc_,
sprang861c55e2015-10-16 10:01:21 -07001511 rtx_to_media_ssrcs_);
sprang867fb522015-08-03 04:38:41 -07001512 return observer_;
1513 }
1514
1515 private:
sprang861c55e2015-10-16 10:01:21 -07001516 uint32_t first_media_ssrc_;
1517 std::map<uint32_t, uint32_t> rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001518 RtpExtensionHeaderObserver* observer_;
1519 } tester;
1520
1521 tester.RunTest();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001522}
1523
Stefan Holmer04cb7632016-01-14 20:34:30 +01001524class TransportFeedbackTester : public test::EndToEndTest {
1525 public:
1526 explicit TransportFeedbackTester(bool feedback_enabled,
1527 size_t num_video_streams,
1528 size_t num_audio_streams)
1529 : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
1530 feedback_enabled_(feedback_enabled),
1531 num_video_streams_(num_video_streams),
sprangcd349d92016-07-13 09:11:28 -07001532 num_audio_streams_(num_audio_streams),
1533 receiver_call_(nullptr) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001534 // Only one stream of each supported for now.
1535 EXPECT_LE(num_video_streams, 1u);
1536 EXPECT_LE(num_audio_streams, 1u);
1537 }
1538
1539 protected:
1540 Action OnSendRtcp(const uint8_t* data, size_t length) override {
1541 EXPECT_FALSE(HasTransportFeedback(data, length));
1542 return SEND_PACKET;
1543 }
1544
1545 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
1546 if (HasTransportFeedback(data, length))
1547 observation_complete_.Set();
1548 return SEND_PACKET;
1549 }
1550
1551 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
1552 RTCPUtility::RTCPParserV2 parser(data, length, true);
1553 EXPECT_TRUE(parser.IsValid());
1554
1555 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1556 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1557 if (packet_type == RTCPUtility::RTCPPacketTypes::kTransportFeedback)
1558 return true;
1559 packet_type = parser.Iterate();
1560 }
1561
1562 return false;
1563 }
1564
1565 void PerformTest() override {
1566 const int64_t kDisabledFeedbackTimeoutMs = 5000;
1567 EXPECT_EQ(feedback_enabled_,
1568 observation_complete_.Wait(feedback_enabled_
1569 ? test::CallTest::kDefaultTimeoutMs
1570 : kDisabledFeedbackTimeoutMs));
1571 }
1572
1573 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1574 receiver_call_ = receiver_call;
1575 }
1576
1577 size_t GetNumVideoStreams() const override { return num_video_streams_; }
1578 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
1579
1580 void ModifyVideoConfigs(
1581 VideoSendStream::Config* send_config,
1582 std::vector<VideoReceiveStream::Config>* receive_configs,
1583 VideoEncoderConfig* encoder_config) override {
1584 send_config->rtp.extensions.clear();
1585 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001586 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001587 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1588 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
1589 }
1590
1591 void ModifyAudioConfigs(
1592 AudioSendStream::Config* send_config,
1593 std::vector<AudioReceiveStream::Config>* receive_configs) override {
1594 send_config->rtp.extensions.clear();
1595 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001596 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001597 (*receive_configs)[0].rtp.extensions.clear();
1598 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1599 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001600 }
1601
1602 private:
Erik Språng6b8d3552015-09-24 15:06:57 +02001603 static const int kExtensionId = 5;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001604 const bool feedback_enabled_;
1605 const size_t num_video_streams_;
1606 const size_t num_audio_streams_;
1607 Call* receiver_call_;
1608};
Erik Språng6b8d3552015-09-24 15:06:57 +02001609
Stefan Holmer04cb7632016-01-14 20:34:30 +01001610TEST_F(EndToEndTest, VideoReceivesTransportFeedback) {
1611 TransportFeedbackTester test(true, 1, 0);
1612 RunBaseTest(&test);
Erik Språng6b8d3552015-09-24 15:06:57 +02001613}
stefan43edf0f2015-11-20 18:05:48 -08001614
Stefan Holmer04cb7632016-01-14 20:34:30 +01001615TEST_F(EndToEndTest, VideoTransportFeedbackNotConfigured) {
1616 TransportFeedbackTester test(false, 1, 0);
1617 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001618}
1619
Stefan Holmer04cb7632016-01-14 20:34:30 +01001620TEST_F(EndToEndTest, AudioReceivesTransportFeedback) {
1621 TransportFeedbackTester test(true, 0, 1);
1622 RunBaseTest(&test);
1623}
1624
1625TEST_F(EndToEndTest, AudioTransportFeedbackNotConfigured) {
1626 TransportFeedbackTester test(false, 0, 1);
1627 RunBaseTest(&test);
1628}
1629
1630TEST_F(EndToEndTest, AudioVideoReceivesTransportFeedback) {
1631 TransportFeedbackTester test(true, 1, 1);
1632 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001633}
1634
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001635TEST_F(EndToEndTest, ObserversEncodedFrames) {
1636 class EncodedFrameTestObserver : public EncodedFrameObserver {
1637 public:
1638 EncodedFrameTestObserver()
Peter Boström5811a392015-12-10 13:02:50 +01001639 : length_(0), frame_type_(kEmptyFrame), called_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001640 virtual ~EncodedFrameTestObserver() {}
1641
1642 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
1643 frame_type_ = encoded_frame.frame_type_;
1644 length_ = encoded_frame.length_;
1645 buffer_.reset(new uint8_t[length_]);
1646 memcpy(buffer_.get(), encoded_frame.data_, length_);
Peter Boström5811a392015-12-10 13:02:50 +01001647 called_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001648 }
1649
Peter Boström5811a392015-12-10 13:02:50 +01001650 bool Wait() { return called_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001651
1652 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
1653 ASSERT_EQ(length_, observer.length_)
1654 << "Observed frames are of different lengths.";
1655 EXPECT_EQ(frame_type_, observer.frame_type_)
1656 << "Observed frames have different frame types.";
1657 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
1658 << "Observed encoded frames have different content.";
1659 }
1660
1661 private:
kwiberg27f982b2016-03-01 11:52:33 -08001662 std::unique_ptr<uint8_t[]> buffer_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001663 size_t length_;
1664 FrameType frame_type_;
Peter Boström5811a392015-12-10 13:02:50 +01001665 rtc::Event called_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001666 };
1667
1668 EncodedFrameTestObserver post_encode_observer;
1669 EncodedFrameTestObserver pre_decode_observer;
1670
solenberg4fbae2b2015-08-28 04:07:10 -07001671 CreateCalls(Call::Config(), Call::Config());
1672
stefanf116bd02015-10-27 08:29:42 -07001673 test::DirectTransport sender_transport(sender_call_.get());
1674 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001675 sender_transport.SetReceiver(receiver_call_->Receiver());
1676 receiver_transport.SetReceiver(sender_call_->Receiver());
1677
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001678 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001679 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -08001680 video_send_config_.post_encode_callback = &post_encode_observer;
1681 video_receive_configs_[0].pre_decode_callback = &pre_decode_observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001682
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001683 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001684 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001685
kwiberg27f982b2016-03-01 11:52:33 -08001686 std::unique_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +00001687 test::FrameGenerator::CreateChromaGenerator(
stefanff483612015-12-21 03:14:00 -08001688 video_encoder_config_.streams[0].width,
1689 video_encoder_config_.streams[0].height));
1690 video_send_stream_->Input()->IncomingCapturedFrame(
1691 *frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001692
Peter Boström5811a392015-12-10 13:02:50 +01001693 EXPECT_TRUE(post_encode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001694 << "Timed out while waiting for send-side encoded-frame callback.";
1695
Peter Boström5811a392015-12-10 13:02:50 +01001696 EXPECT_TRUE(pre_decode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001697 << "Timed out while waiting for pre-decode encoded-frame callback.";
1698
1699 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
1700
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001701 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001702
1703 sender_transport.StopSending();
1704 receiver_transport.StopSending();
1705
1706 DestroyStreams();
1707}
1708
1709TEST_F(EndToEndTest, ReceiveStreamSendsRemb) {
1710 class RembObserver : public test::EndToEndTest {
1711 public:
1712 RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
1713
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001714 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001715 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1716 EXPECT_TRUE(parser.IsValid());
1717
1718 bool received_psfb = false;
1719 bool received_remb = false;
1720 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02001721 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1722 if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbRemb) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001723 const RTCPUtility::RTCPPacket& packet = parser.Packet();
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001724 EXPECT_EQ(packet.PSFBAPP.SenderSSRC, kReceiverLocalVideoSsrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001725 received_psfb = true;
Erik Språng242e22b2015-05-11 10:17:43 +02001726 } else if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbRembItem) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001727 const RTCPUtility::RTCPPacket& packet = parser.Packet();
1728 EXPECT_GT(packet.REMBItem.BitRate, 0u);
1729 EXPECT_EQ(packet.REMBItem.NumberOfSSRCs, 1u);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001730 EXPECT_EQ(packet.REMBItem.SSRCs[0], kVideoSendSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001731 received_remb = true;
1732 }
1733 packet_type = parser.Iterate();
1734 }
1735 if (received_psfb && received_remb)
Peter Boström5811a392015-12-10 13:02:50 +01001736 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001737 return SEND_PACKET;
1738 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001739 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001740 EXPECT_TRUE(Wait()) << "Timed out while waiting for a "
1741 "receiver RTCP REMB packet to be "
1742 "sent.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001743 }
1744 } test;
1745
stefane74eef12016-01-08 06:47:13 -08001746 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001747}
1748
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001749TEST_F(EndToEndTest, VerifyBandwidthStats) {
stefanf116bd02015-10-27 08:29:42 -07001750 class RtcpObserver : public test::EndToEndTest {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001751 public:
1752 RtcpObserver()
1753 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001754 sender_call_(nullptr),
1755 receiver_call_(nullptr),
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001756 has_seen_pacer_delay_(false) {}
1757
stefanf116bd02015-10-27 08:29:42 -07001758 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001759 Call::Stats sender_stats = sender_call_->GetStats();
1760 Call::Stats receiver_stats = receiver_call_->GetStats();
1761 if (!has_seen_pacer_delay_)
1762 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
1763 if (sender_stats.send_bandwidth_bps > 0 &&
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001764 receiver_stats.recv_bandwidth_bps > 0 && has_seen_pacer_delay_) {
Peter Boström5811a392015-12-10 13:02:50 +01001765 observation_complete_.Set();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001766 }
stefanf116bd02015-10-27 08:29:42 -07001767 return SEND_PACKET;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001768 }
1769
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001770 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001771 sender_call_ = sender_call;
1772 receiver_call_ = receiver_call;
1773 }
1774
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001775 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001776 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
1777 "non-zero bandwidth stats.";
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001778 }
1779
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001780 private:
1781 Call* sender_call_;
1782 Call* receiver_call_;
1783 bool has_seen_pacer_delay_;
1784 } test;
1785
stefane74eef12016-01-08 06:47:13 -08001786 RunBaseTest(&test);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001787}
1788
stefan32f81542016-01-20 07:13:58 -08001789
1790// Verifies that it's possible to limit the send BWE by sending a REMB.
1791// This is verified by allowing the send BWE to ramp-up to >1000 kbps,
1792// then have the test generate a REMB of 500 kbps and verify that the send BWE
1793// is reduced to exactly 500 kbps. Then a REMB of 1000 kbps is generated and the
1794// test verifies that the send BWE ramps back up to exactly 1000 kbps.
1795TEST_F(EndToEndTest, RembWithSendSideBwe) {
1796 class BweObserver : public test::EndToEndTest {
1797 public:
1798 BweObserver()
1799 : EndToEndTest(kDefaultTimeoutMs),
1800 sender_call_(nullptr),
1801 clock_(Clock::GetRealTimeClock()),
1802 sender_ssrc_(0),
1803 remb_bitrate_bps_(1000000),
1804 receive_transport_(nullptr),
1805 event_(false, false),
1806 poller_thread_(&BitrateStatsPollingThread,
1807 this,
1808 "BitrateStatsPollingThread"),
1809 state_(kWaitForFirstRampUp) {}
1810
1811 ~BweObserver() {}
1812
nisseef8b61e2016-04-29 06:09:15 -07001813 test::PacketTransport* CreateReceiveTransport() override {
stefan32f81542016-01-20 07:13:58 -08001814 receive_transport_ = new test::PacketTransport(
1815 nullptr, this, test::PacketTransport::kReceiver,
1816 FakeNetworkPipe::Config());
1817 return receive_transport_;
1818 }
1819
1820 Call::Config GetSenderCallConfig() override {
1821 Call::Config config;
1822 // Set a high start bitrate to reduce the test completion time.
1823 config.bitrate_config.start_bitrate_bps = remb_bitrate_bps_;
1824 return config;
1825 }
1826
1827 void ModifyVideoConfigs(
1828 VideoSendStream::Config* send_config,
1829 std::vector<VideoReceiveStream::Config>* receive_configs,
1830 VideoEncoderConfig* encoder_config) override {
1831 ASSERT_EQ(1u, send_config->rtp.ssrcs.size());
1832 send_config->rtp.extensions.clear();
1833 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001834 RtpExtension(RtpExtension::kTransportSequenceNumberUri,
stefan32f81542016-01-20 07:13:58 -08001835 test::kTransportSequenceNumberExtensionId));
1836 sender_ssrc_ = send_config->rtp.ssrcs[0];
1837
1838 encoder_config->streams[0].max_bitrate_bps =
1839 encoder_config->streams[0].target_bitrate_bps = 2000000;
1840
1841 ASSERT_EQ(1u, receive_configs->size());
1842 (*receive_configs)[0].rtp.remb = false;
1843 (*receive_configs)[0].rtp.transport_cc = true;
1844 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1845 RtpRtcp::Configuration config;
1846 config.receiver_only = true;
1847 config.clock = clock_;
1848 config.outgoing_transport = receive_transport_;
1849 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
1850 rtp_rtcp_->SetRemoteSSRC((*receive_configs)[0].rtp.remote_ssrc);
1851 rtp_rtcp_->SetSSRC((*receive_configs)[0].rtp.local_ssrc);
1852 rtp_rtcp_->SetREMBStatus(true);
1853 rtp_rtcp_->SetSendingStatus(true);
1854 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
1855 }
1856
1857 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1858 sender_call_ = sender_call;
1859 }
1860
1861 static bool BitrateStatsPollingThread(void* obj) {
1862 return static_cast<BweObserver*>(obj)->PollStats();
1863 }
1864
1865 bool PollStats() {
1866 if (sender_call_) {
1867 Call::Stats stats = sender_call_->GetStats();
1868 switch (state_) {
1869 case kWaitForFirstRampUp:
1870 if (stats.send_bandwidth_bps >= remb_bitrate_bps_) {
1871 state_ = kWaitForRemb;
1872 remb_bitrate_bps_ /= 2;
1873 rtp_rtcp_->SetREMBData(
1874 remb_bitrate_bps_,
1875 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
1876 rtp_rtcp_->SendRTCP(kRtcpRr);
1877 }
1878 break;
1879
1880 case kWaitForRemb:
1881 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
1882 state_ = kWaitForSecondRampUp;
1883 remb_bitrate_bps_ *= 2;
1884 rtp_rtcp_->SetREMBData(
1885 remb_bitrate_bps_,
1886 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
1887 rtp_rtcp_->SendRTCP(kRtcpRr);
1888 }
1889 break;
1890
1891 case kWaitForSecondRampUp:
1892 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
1893 observation_complete_.Set();
1894 }
1895 break;
1896 }
1897 }
1898
1899 return !event_.Wait(1000);
1900 }
1901
1902 void PerformTest() override {
1903 poller_thread_.Start();
1904 EXPECT_TRUE(Wait())
1905 << "Timed out while waiting for bitrate to change according to REMB.";
1906 poller_thread_.Stop();
1907 }
1908
1909 private:
1910 enum TestState { kWaitForFirstRampUp, kWaitForRemb, kWaitForSecondRampUp };
1911
1912 Call* sender_call_;
1913 Clock* const clock_;
1914 uint32_t sender_ssrc_;
1915 int remb_bitrate_bps_;
kwiberg27f982b2016-03-01 11:52:33 -08001916 std::unique_ptr<RtpRtcp> rtp_rtcp_;
stefan32f81542016-01-20 07:13:58 -08001917 test::PacketTransport* receive_transport_;
1918 rtc::Event event_;
1919 rtc::PlatformThread poller_thread_;
1920 TestState state_;
1921 } test;
1922
1923 RunBaseTest(&test);
1924}
1925
Åsa Persson352b2d72015-04-15 18:00:40 +02001926TEST_F(EndToEndTest, VerifyNackStats) {
1927 static const int kPacketNumberToDrop = 200;
1928 class NackObserver : public test::EndToEndTest {
1929 public:
1930 NackObserver()
1931 : EndToEndTest(kLongTimeoutMs),
1932 sent_rtp_packets_(0),
1933 dropped_rtp_packet_(0),
1934 dropped_rtp_packet_requested_(false),
1935 send_stream_(nullptr),
1936 start_runtime_ms_(-1) {}
1937
1938 private:
1939 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08001940 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02001941 if (++sent_rtp_packets_ == kPacketNumberToDrop) {
kwiberg27f982b2016-03-01 11:52:33 -08001942 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
Åsa Persson352b2d72015-04-15 18:00:40 +02001943 RTPHeader header;
1944 EXPECT_TRUE(parser->Parse(packet, length, &header));
1945 dropped_rtp_packet_ = header.sequenceNumber;
1946 return DROP_PACKET;
1947 }
1948 VerifyStats();
1949 return SEND_PACKET;
1950 }
1951
1952 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08001953 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02001954 test::RtcpPacketParser rtcp_parser;
1955 rtcp_parser.Parse(packet, length);
1956 std::vector<uint16_t> nacks = rtcp_parser.nack_item()->last_nack_list();
1957 if (!nacks.empty() && std::find(
1958 nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) {
1959 dropped_rtp_packet_requested_ = true;
1960 }
1961 return SEND_PACKET;
1962 }
1963
stefan608213e2015-11-01 14:56:10 -08001964 void VerifyStats() EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
Åsa Persson352b2d72015-04-15 18:00:40 +02001965 if (!dropped_rtp_packet_requested_)
1966 return;
1967 int send_stream_nack_packets = 0;
1968 int receive_stream_nack_packets = 0;
1969 VideoSendStream::Stats stats = send_stream_->GetStats();
1970 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
1971 stats.substreams.begin(); it != stats.substreams.end(); ++it) {
1972 const VideoSendStream::StreamStats& stream_stats = it->second;
1973 send_stream_nack_packets +=
1974 stream_stats.rtcp_packet_type_counts.nack_packets;
1975 }
1976 for (size_t i = 0; i < receive_streams_.size(); ++i) {
1977 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
1978 receive_stream_nack_packets +=
1979 stats.rtcp_packet_type_counts.nack_packets;
1980 }
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001981 if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) {
Åsa Persson352b2d72015-04-15 18:00:40 +02001982 // NACK packet sent on receive stream and received on sent stream.
1983 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01001984 observation_complete_.Set();
Åsa Persson352b2d72015-04-15 18:00:40 +02001985 }
1986 }
1987
1988 bool MinMetricRunTimePassed() {
1989 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
1990 if (start_runtime_ms_ == -1) {
1991 start_runtime_ms_ = now;
1992 return false;
1993 }
1994 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
1995 return elapsed_sec > metrics::kMinRunTimeInSeconds;
1996 }
1997
stefanff483612015-12-21 03:14:00 -08001998 void ModifyVideoConfigs(
1999 VideoSendStream::Config* send_config,
2000 std::vector<VideoReceiveStream::Config>* receive_configs,
2001 VideoEncoderConfig* encoder_config) override {
Åsa Persson352b2d72015-04-15 18:00:40 +02002002 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2003 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2004 }
2005
stefanff483612015-12-21 03:14:00 -08002006 void OnVideoStreamsCreated(
Åsa Persson352b2d72015-04-15 18:00:40 +02002007 VideoSendStream* send_stream,
2008 const std::vector<VideoReceiveStream*>& receive_streams) override {
2009 send_stream_ = send_stream;
2010 receive_streams_ = receive_streams;
2011 }
2012
2013 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002014 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson352b2d72015-04-15 18:00:40 +02002015 }
2016
stefan608213e2015-11-01 14:56:10 -08002017 rtc::CriticalSection crit_;
Åsa Persson352b2d72015-04-15 18:00:40 +02002018 uint64_t sent_rtp_packets_;
stefan608213e2015-11-01 14:56:10 -08002019 uint16_t dropped_rtp_packet_ GUARDED_BY(&crit_);
2020 bool dropped_rtp_packet_requested_ GUARDED_BY(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002021 std::vector<VideoReceiveStream*> receive_streams_;
2022 VideoSendStream* send_stream_;
2023 int64_t start_runtime_ms_;
2024 } test;
2025
asapersson01d70a32016-05-20 06:29:46 -07002026 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002027 RunBaseTest(&test);
Åsa Persson352b2d72015-04-15 18:00:40 +02002028
asapersson01d70a32016-05-20 06:29:46 -07002029 EXPECT_EQ(
2030 1, metrics::NumSamples("WebRTC.Video.UniqueNackRequestsSentInPercent"));
2031 EXPECT_EQ(1, metrics::NumSamples(
2032 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
2033 EXPECT_GT(metrics::MinSample("WebRTC.Video.NackPacketsSentPerMinute"), 0);
Åsa Persson352b2d72015-04-15 18:00:40 +02002034}
2035
sprangb4a1ae52015-12-03 08:10:08 -08002036void EndToEndTest::VerifyHistogramStats(bool use_rtx,
2037 bool use_red,
2038 bool screenshare) {
tommi2e82f382016-06-21 00:26:43 -07002039 class StatsObserver : public test::EndToEndTest,
2040 public rtc::VideoSinkInterface<VideoFrame> {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002041 public:
sprangb4a1ae52015-12-03 08:10:08 -08002042 StatsObserver(bool use_rtx, bool use_red, bool screenshare)
Åsa Persson3c391cb2015-04-27 10:09:49 +02002043 : EndToEndTest(kLongTimeoutMs),
2044 use_rtx_(use_rtx),
2045 use_red_(use_red),
sprangb4a1ae52015-12-03 08:10:08 -08002046 screenshare_(screenshare),
Peter Boström39593972016-02-15 11:27:15 +01002047 // This test uses NACK, so to send FEC we can't use a fake encoder.
2048 vp8_encoder_(
2049 use_red ? VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)
2050 : nullptr),
Åsa Persson3c391cb2015-04-27 10:09:49 +02002051 sender_call_(nullptr),
2052 receiver_call_(nullptr),
2053 start_runtime_ms_(-1) {}
2054
2055 private:
tommi2e82f382016-06-21 00:26:43 -07002056 void OnFrame(const VideoFrame& video_frame) override {}
2057
Åsa Persson3c391cb2015-04-27 10:09:49 +02002058 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2059 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002060 observation_complete_.Set();
Åsa Persson3c391cb2015-04-27 10:09:49 +02002061
stefanf116bd02015-10-27 08:29:42 -07002062 return SEND_PACKET;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002063 }
2064
2065 bool MinMetricRunTimePassed() {
2066 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2067 if (start_runtime_ms_ == -1) {
2068 start_runtime_ms_ = now;
2069 return false;
2070 }
2071 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2072 return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
2073 }
2074
stefanff483612015-12-21 03:14:00 -08002075 void ModifyVideoConfigs(
2076 VideoSendStream::Config* send_config,
2077 std::vector<VideoReceiveStream::Config>* receive_configs,
2078 VideoEncoderConfig* encoder_config) override {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002079 // NACK
2080 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2081 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
tommi2e82f382016-06-21 00:26:43 -07002082 (*receive_configs)[0].renderer = this;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002083 // FEC
2084 if (use_red_) {
2085 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
2086 send_config->rtp.fec.red_payload_type = kRedPayloadType;
Peter Boström39593972016-02-15 11:27:15 +01002087 send_config->encoder_settings.encoder = vp8_encoder_.get();
2088 send_config->encoder_settings.payload_name = "VP8";
2089 (*receive_configs)[0].decoders[0].payload_name = "VP8";
Åsa Persson3c391cb2015-04-27 10:09:49 +02002090 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
2091 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
2092 }
2093 // RTX
2094 if (use_rtx_) {
2095 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
2096 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002097 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002098 kSendRtxSsrcs[0];
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002099 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002100 kSendRtxPayloadType;
2101 }
sprangb4a1ae52015-12-03 08:10:08 -08002102 encoder_config->content_type =
2103 screenshare_ ? VideoEncoderConfig::ContentType::kScreen
2104 : VideoEncoderConfig::ContentType::kRealtimeVideo;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002105 }
2106
2107 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2108 sender_call_ = sender_call;
2109 receiver_call_ = receiver_call;
2110 }
2111
Åsa Persson3c391cb2015-04-27 10:09:49 +02002112 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002113 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson3c391cb2015-04-27 10:09:49 +02002114 }
2115
sprangb4a1ae52015-12-03 08:10:08 -08002116 const bool use_rtx_;
2117 const bool use_red_;
2118 const bool screenshare_;
kwiberg27f982b2016-03-01 11:52:33 -08002119 const std::unique_ptr<VideoEncoder> vp8_encoder_;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002120 Call* sender_call_;
2121 Call* receiver_call_;
2122 int64_t start_runtime_ms_;
sprangb4a1ae52015-12-03 08:10:08 -08002123 } test(use_rtx, use_red, screenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002124
asapersson01d70a32016-05-20 06:29:46 -07002125 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002126 RunBaseTest(&test);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002127
stefan91d92602015-11-11 10:13:02 -08002128 // Delete the call for Call stats to be reported.
stefan18adf0a2015-11-17 06:24:56 -08002129 sender_call_.reset();
stefan91d92602015-11-11 10:13:02 -08002130 receiver_call_.reset();
2131
sprangb4a1ae52015-12-03 08:10:08 -08002132 std::string video_prefix =
2133 screenshare ? "WebRTC.Video.Screenshare." : "WebRTC.Video.";
2134
Åsa Persson3c391cb2015-04-27 10:09:49 +02002135 // Verify that stats have been updated once.
asapersson01d70a32016-05-20 06:29:46 -07002136 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
2137 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.RtcpBitrateReceivedInBps"));
2138 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.BitrateReceivedInKbps"));
2139 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.EstimatedSendBitrateInKbps"));
2140 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.PacerBitrateInKbps"));
2141
2142 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
stefan91d92602015-11-11 10:13:02 -08002143 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002144 metrics::NumSamples(video_prefix + "NackPacketsReceivedPerMinute"));
2145 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
asaperssond89920b2015-07-22 06:52:00 -07002146 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002147 metrics::NumSamples(video_prefix + "FirPacketsReceivedPerMinute"));
2148 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
sprangb4a1ae52015-12-03 08:10:08 -08002149 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002150 metrics::NumSamples(video_prefix + "PliPacketsReceivedPerMinute"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002151
asapersson01d70a32016-05-20 06:29:46 -07002152 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "KeyFramesSentInPermille"));
2153 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
2154
2155 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentPacketsLostInPercent"));
2156 EXPECT_EQ(1,
2157 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
2158
2159 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputWidthInPixels"));
2160 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputHeightInPixels"));
2161 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentWidthInPixels"));
2162 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentHeightInPixels"));
2163 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
2164 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
2165
2166 EXPECT_EQ(1, metrics::NumEvents(
2167 video_prefix + "InputWidthInPixels",
2168 static_cast<int>(video_encoder_config_.streams[0].width)));
2169 EXPECT_EQ(1, metrics::NumEvents(
2170 video_prefix + "InputHeightInPixels",
2171 static_cast<int>(video_encoder_config_.streams[0].height)));
2172 EXPECT_EQ(1, metrics::NumEvents(
2173 video_prefix + "SentWidthInPixels",
2174 static_cast<int>(video_encoder_config_.streams[0].width)));
2175 EXPECT_EQ(1, metrics::NumEvents(
2176 video_prefix + "SentHeightInPixels",
2177 static_cast<int>(video_encoder_config_.streams[0].height)));
2178 EXPECT_EQ(1, metrics::NumEvents(
2179 "WebRTC.Video.ReceivedWidthInPixels",
2180 static_cast<int>(video_encoder_config_.streams[0].width)));
2181 EXPECT_EQ(1, metrics::NumEvents(
2182 "WebRTC.Video.ReceivedHeightInPixels",
2183 static_cast<int>(video_encoder_config_.streams[0].height)));
2184
2185 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputFramesPerSecond"));
2186 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentFramesPerSecond"));
2187 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
2188 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
2189
2190 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
2191 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
2192 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
2193 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
2194
2195 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
2196
2197 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EncodeTimeInMs"));
2198 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
2199
2200 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "BitrateSentInKbps"));
2201 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateReceivedInKbps"));
2202 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "MediaBitrateSentInKbps"));
2203 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateReceivedInKbps"));
2204 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PaddingBitrateSentInKbps"));
2205 EXPECT_EQ(1,
2206 metrics::NumSamples("WebRTC.Video.PaddingBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002207 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002208 1, metrics::NumSamples(video_prefix + "RetransmittedBitrateSentInKbps"));
2209 EXPECT_EQ(1, metrics::NumSamples(
2210 "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002211
asapersson01d70a32016-05-20 06:29:46 -07002212 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendDelayInMs"));
2213 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayInMs"));
2214 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayMaxInMs"));
asapersson6f14be82015-11-16 00:40:49 -08002215
Åsa Persson3c391cb2015-04-27 10:09:49 +02002216 int num_rtx_samples = use_rtx ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002217 EXPECT_EQ(num_rtx_samples,
2218 metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2219 EXPECT_EQ(num_rtx_samples,
2220 metrics::NumSamples("WebRTC.Video.RtxBitrateReceivedInKbps"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002221
2222 int num_red_samples = use_red ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002223 EXPECT_EQ(num_red_samples,
2224 metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2225 EXPECT_EQ(num_red_samples,
2226 metrics::NumSamples("WebRTC.Video.FecBitrateReceivedInKbps"));
2227 EXPECT_EQ(num_red_samples,
2228 metrics::NumSamples("WebRTC.Video.ReceivedFecPacketsInPercent"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002229}
2230
2231TEST_F(EndToEndTest, VerifyHistogramStatsWithRtx) {
2232 const bool kEnabledRtx = true;
2233 const bool kEnabledRed = false;
sprangb4a1ae52015-12-03 08:10:08 -08002234 const bool kScreenshare = false;
2235 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002236}
2237
2238TEST_F(EndToEndTest, VerifyHistogramStatsWithRed) {
2239 const bool kEnabledRtx = false;
2240 const bool kEnabledRed = true;
sprangb4a1ae52015-12-03 08:10:08 -08002241 const bool kScreenshare = false;
2242 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
2243}
2244
2245TEST_F(EndToEndTest, VerifyHistogramStatsWithScreenshare) {
2246 const bool kEnabledRtx = false;
2247 const bool kEnabledRed = false;
2248 const bool kScreenshare = true;
2249 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002250}
2251
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002252void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
2253 static const int kNumRtcpReportPacketsToObserve = 5;
2254 class RtcpXrObserver : public test::EndToEndTest {
2255 public:
2256 explicit RtcpXrObserver(bool enable_rrtr)
2257 : EndToEndTest(kDefaultTimeoutMs),
2258 enable_rrtr_(enable_rrtr),
2259 sent_rtcp_sr_(0),
2260 sent_rtcp_rr_(0),
2261 sent_rtcp_rrtr_(0),
2262 sent_rtcp_dlrr_(0) {}
2263
2264 private:
2265 // Receive stream should send RR packets (and RRTR packets if enabled).
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002266 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002267 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002268 RTCPUtility::RTCPParserV2 parser(packet, length, true);
2269 EXPECT_TRUE(parser.IsValid());
2270
2271 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02002272 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
2273 if (packet_type == RTCPUtility::RTCPPacketTypes::kRr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002274 ++sent_rtcp_rr_;
2275 } else if (packet_type ==
Erik Språng242e22b2015-05-11 10:17:43 +02002276 RTCPUtility::RTCPPacketTypes::kXrReceiverReferenceTime) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002277 ++sent_rtcp_rrtr_;
2278 }
Erik Språng242e22b2015-05-11 10:17:43 +02002279 EXPECT_NE(packet_type, RTCPUtility::RTCPPacketTypes::kSr);
2280 EXPECT_NE(packet_type,
2281 RTCPUtility::RTCPPacketTypes::kXrDlrrReportBlockItem);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002282 packet_type = parser.Iterate();
2283 }
2284 return SEND_PACKET;
2285 }
2286 // Send stream should send SR packets (and DLRR packets if enabled).
nisseef8b61e2016-04-29 06:09:15 -07002287 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002288 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002289 RTCPUtility::RTCPParserV2 parser(packet, length, true);
2290 EXPECT_TRUE(parser.IsValid());
2291
2292 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02002293 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
2294 if (packet_type == RTCPUtility::RTCPPacketTypes::kSr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002295 ++sent_rtcp_sr_;
Erik Språng242e22b2015-05-11 10:17:43 +02002296 } else if (packet_type ==
2297 RTCPUtility::RTCPPacketTypes::kXrDlrrReportBlockItem) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002298 ++sent_rtcp_dlrr_;
2299 }
Erik Språng242e22b2015-05-11 10:17:43 +02002300 EXPECT_NE(packet_type,
2301 RTCPUtility::RTCPPacketTypes::kXrReceiverReferenceTime);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002302 packet_type = parser.Iterate();
2303 }
2304 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
2305 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve) {
2306 if (enable_rrtr_) {
2307 EXPECT_GT(sent_rtcp_rrtr_, 0);
2308 EXPECT_GT(sent_rtcp_dlrr_, 0);
2309 } else {
2310 EXPECT_EQ(0, sent_rtcp_rrtr_);
2311 EXPECT_EQ(0, sent_rtcp_dlrr_);
2312 }
Peter Boström5811a392015-12-10 13:02:50 +01002313 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002314 }
2315 return SEND_PACKET;
2316 }
2317
stefanff483612015-12-21 03:14:00 -08002318 void ModifyVideoConfigs(
2319 VideoSendStream::Config* send_config,
2320 std::vector<VideoReceiveStream::Config>* receive_configs,
2321 VideoEncoderConfig* encoder_config) override {
pbosda903ea2015-10-02 02:36:56 -07002322 (*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002323 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
2324 enable_rrtr_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002325 }
2326
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002327 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002328 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002329 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
2330 }
2331
stefan608213e2015-11-01 14:56:10 -08002332 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002333 bool enable_rrtr_;
2334 int sent_rtcp_sr_;
stefan608213e2015-11-01 14:56:10 -08002335 int sent_rtcp_rr_ GUARDED_BY(&crit_);
2336 int sent_rtcp_rrtr_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002337 int sent_rtcp_dlrr_;
2338 } test(enable_rrtr);
2339
stefane74eef12016-01-08 06:47:13 -08002340 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002341}
2342
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002343void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
2344 bool send_single_ssrc_first) {
2345 class SendsSetSsrcs : public test::EndToEndTest {
2346 public:
2347 SendsSetSsrcs(const uint32_t* ssrcs,
2348 size_t num_ssrcs,
2349 bool send_single_ssrc_first)
2350 : EndToEndTest(kDefaultTimeoutMs),
2351 num_ssrcs_(num_ssrcs),
2352 send_single_ssrc_first_(send_single_ssrc_first),
2353 ssrcs_to_observe_(num_ssrcs),
sprang867fb522015-08-03 04:38:41 -07002354 expect_single_ssrc_(send_single_ssrc_first),
2355 send_stream_(nullptr) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002356 for (size_t i = 0; i < num_ssrcs; ++i)
2357 valid_ssrcs_[ssrcs[i]] = true;
2358 }
2359
2360 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002361 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002362 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002363 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002364
2365 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
2366 << "Received unknown SSRC: " << header.ssrc;
2367
2368 if (!valid_ssrcs_[header.ssrc])
Peter Boström5811a392015-12-10 13:02:50 +01002369 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002370
2371 if (!is_observed_[header.ssrc]) {
2372 is_observed_[header.ssrc] = true;
2373 --ssrcs_to_observe_;
2374 if (expect_single_ssrc_) {
2375 expect_single_ssrc_ = false;
Peter Boström5811a392015-12-10 13:02:50 +01002376 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002377 }
2378 }
2379
2380 if (ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002381 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002382
2383 return SEND_PACKET;
2384 }
2385
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002386 size_t GetNumVideoStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002387
stefanff483612015-12-21 03:14:00 -08002388 void ModifyVideoConfigs(
2389 VideoSendStream::Config* send_config,
2390 std::vector<VideoReceiveStream::Config>* receive_configs,
2391 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002392 if (num_ssrcs_ > 1) {
2393 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002394 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2395 encoder_config->streams[i].min_bitrate_bps = 10000;
2396 encoder_config->streams[i].target_bitrate_bps = 15000;
2397 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002398 }
2399 }
2400
stefanff483612015-12-21 03:14:00 -08002401 video_encoder_config_all_streams_ = *encoder_config;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002402 if (send_single_ssrc_first_)
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002403 encoder_config->streams.resize(1);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002404 }
2405
stefanff483612015-12-21 03:14:00 -08002406 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002407 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002408 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002409 send_stream_ = send_stream;
2410 }
2411
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002412 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002413 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2414 << (send_single_ssrc_first_ ? "first SSRC."
2415 : "SSRCs.");
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002416
2417 if (send_single_ssrc_first_) {
2418 // Set full simulcast and continue with the rest of the SSRCs.
stefanff483612015-12-21 03:14:00 -08002419 send_stream_->ReconfigureVideoEncoder(
2420 video_encoder_config_all_streams_);
Peter Boström5811a392015-12-10 13:02:50 +01002421 EXPECT_TRUE(Wait()) << "Timed out while waiting on additional SSRCs.";
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002422 }
2423 }
2424
2425 private:
2426 std::map<uint32_t, bool> valid_ssrcs_;
2427 std::map<uint32_t, bool> is_observed_;
2428
2429 const size_t num_ssrcs_;
2430 const bool send_single_ssrc_first_;
2431
2432 size_t ssrcs_to_observe_;
2433 bool expect_single_ssrc_;
2434
2435 VideoSendStream* send_stream_;
stefanff483612015-12-21 03:14:00 -08002436 VideoEncoderConfig video_encoder_config_all_streams_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002437 } test(kVideoSendSsrcs, num_ssrcs, send_single_ssrc_first);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002438
stefane74eef12016-01-08 06:47:13 -08002439 RunBaseTest(&test);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002440}
2441
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002442TEST_F(EndToEndTest, ReportsSetEncoderRates) {
2443 class EncoderRateStatsTest : public test::EndToEndTest,
2444 public test::FakeEncoder {
2445 public:
2446 EncoderRateStatsTest()
2447 : EndToEndTest(kDefaultTimeoutMs),
sprang867fb522015-08-03 04:38:41 -07002448 FakeEncoder(Clock::GetRealTimeClock()),
2449 send_stream_(nullptr),
2450 bitrate_kbps_(0) {}
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002451
stefanff483612015-12-21 03:14:00 -08002452 void OnVideoStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002453 VideoSendStream* send_stream,
2454 const std::vector<VideoReceiveStream*>& receive_streams) override {
2455 send_stream_ = send_stream;
2456 }
2457
stefanff483612015-12-21 03:14:00 -08002458 void ModifyVideoConfigs(
2459 VideoSendStream::Config* send_config,
2460 std::vector<VideoReceiveStream::Config>* receive_configs,
2461 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002462 send_config->encoder_settings.encoder = this;
perkj57c21f92016-06-17 07:27:16 -07002463 RTC_DCHECK_EQ(1u, encoder_config->streams.size());
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002464 }
2465
2466 int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override {
2467 // Make sure not to trigger on any default zero bitrates.
2468 if (new_target_bitrate == 0)
2469 return 0;
Peter Boströmf2f82832015-05-01 13:00:41 +02002470 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002471 bitrate_kbps_ = new_target_bitrate;
Peter Boström5811a392015-12-10 13:02:50 +01002472 observation_complete_.Set();
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002473 return 0;
2474 }
2475
2476 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002477 ASSERT_TRUE(Wait())
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002478 << "Timed out while waiting for encoder SetRates() call.";
perkjf5b2e512016-07-05 08:34:04 -07002479 WaitForEncoderTargetBitrateMatchStats();
2480 send_stream_->Stop();
2481 WaitForStatsReportZeroTargetBitrate();
2482 send_stream_->Start();
2483 WaitForEncoderTargetBitrateMatchStats();
2484 }
2485
2486 void WaitForEncoderTargetBitrateMatchStats() {
Peter Boström5811a392015-12-10 13:02:50 +01002487 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002488 VideoSendStream::Stats stats = send_stream_->GetStats();
2489 {
Peter Boströmf2f82832015-05-01 13:00:41 +02002490 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002491 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
2492 static_cast<int>(bitrate_kbps_)) {
2493 return;
2494 }
2495 }
2496 SleepMs(1);
2497 }
2498 FAIL()
2499 << "Timed out waiting for stats reporting the currently set bitrate.";
2500 }
2501
perkjf5b2e512016-07-05 08:34:04 -07002502 void WaitForStatsReportZeroTargetBitrate() {
2503 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
2504 if (send_stream_->GetStats().target_media_bitrate_bps == 0) {
2505 return;
2506 }
2507 SleepMs(1);
2508 }
2509 FAIL() << "Timed out waiting for stats reporting zero bitrate.";
2510 }
2511
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002512 private:
stefanf116bd02015-10-27 08:29:42 -07002513 rtc::CriticalSection crit_;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002514 VideoSendStream* send_stream_;
2515 uint32_t bitrate_kbps_ GUARDED_BY(crit_);
2516 } test;
2517
stefane74eef12016-01-08 06:47:13 -08002518 RunBaseTest(&test);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002519}
2520
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002521TEST_F(EndToEndTest, GetStats) {
2522 static const int kStartBitrateBps = 3000000;
Peter Boströmdef398832015-05-27 17:59:11 +02002523 static const int kExpectedRenderDelayMs = 20;
tommi2e82f382016-06-21 00:26:43 -07002524
2525 class ReceiveStreamRenderer : public rtc::VideoSinkInterface<VideoFrame> {
2526 public:
2527 ReceiveStreamRenderer() {}
2528
2529 private:
2530 void OnFrame(const VideoFrame& video_frame) override {}
2531 };
2532
nissed30a1112016-04-18 05:15:22 -07002533 class StatsObserver : public test::EndToEndTest,
2534 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002535 public:
stefanf116bd02015-10-27 08:29:42 -07002536 StatsObserver()
2537 : EndToEndTest(kLongTimeoutMs),
Peter Boströmc6e16e32016-02-05 14:15:53 +01002538 encoder_(Clock::GetRealTimeClock(), 10),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002539 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002540 expected_send_ssrcs_(),
Peter Boström5811a392015-12-10 13:02:50 +01002541 check_stats_event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002542
2543 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002544 Action OnSendRtp(const uint8_t* packet, size_t length) override {
sprangcd349d92016-07-13 09:11:28 -07002545 // Drop every 25th packet => 4% loss.
2546 static const int kPacketLossFrac = 25;
2547 RTPHeader header;
2548 RtpUtility::RtpHeaderParser parser(packet, length);
2549 if (parser.Parse(&header) &&
2550 expected_send_ssrcs_.find(header.ssrc) !=
2551 expected_send_ssrcs_.end() &&
2552 header.sequenceNumber % kPacketLossFrac == 0) {
2553 return DROP_PACKET;
2554 }
Peter Boström5811a392015-12-10 13:02:50 +01002555 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002556 return SEND_PACKET;
2557 }
2558
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002559 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002560 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002561 return SEND_PACKET;
2562 }
2563
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002564 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002565 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002566 return SEND_PACKET;
2567 }
2568
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002569 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002570 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002571 return SEND_PACKET;
2572 }
2573
nissed30a1112016-04-18 05:15:22 -07002574 void OnFrame(const VideoFrame& video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002575 // Ensure that we have at least 5ms send side delay.
nissed30a1112016-04-18 05:15:22 -07002576 SleepMs(5);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002577 }
2578
2579 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002580 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2581 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2582 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002583
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002584 // Make sure all fields have been populated.
2585 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
2586 // always filled for all receivers.
2587 receive_stats_filled_["IncomingRate"] |=
2588 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002589
Peter Boströmb7d9a972015-12-18 16:01:11 +01002590 send_stats_filled_["DecoderImplementationName"] |=
2591 stats.decoder_implementation_name ==
2592 test::FakeDecoder::kImplementationName;
Peter Boströmdef398832015-05-27 17:59:11 +02002593 receive_stats_filled_["RenderDelayAsHighAsExpected"] |=
2594 stats.render_delay_ms >= kExpectedRenderDelayMs;
2595
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002596 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002597
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002598 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002599
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002600 receive_stats_filled_["StatisticsUpdated"] |=
2601 stats.rtcp_stats.cumulative_lost != 0 ||
2602 stats.rtcp_stats.extended_max_sequence_number != 0 ||
2603 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002604
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002605 receive_stats_filled_["DataCountersUpdated"] |=
2606 stats.rtp_stats.transmitted.payload_bytes != 0 ||
2607 stats.rtp_stats.fec.packets != 0 ||
2608 stats.rtp_stats.transmitted.header_bytes != 0 ||
2609 stats.rtp_stats.transmitted.packets != 0 ||
2610 stats.rtp_stats.transmitted.padding_bytes != 0 ||
2611 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002612
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002613 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002614 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002615
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002616 receive_stats_filled_["FrameCounts"] |=
2617 stats.frame_counts.key_frames != 0 ||
2618 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002619
pbosbb36fdf2015-07-09 07:48:14 -07002620 receive_stats_filled_["CName"] |= !stats.c_name.empty();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002621
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002622 receive_stats_filled_["RtcpPacketTypeCount"] |=
2623 stats.rtcp_packet_type_counts.fir_packets != 0 ||
2624 stats.rtcp_packet_type_counts.nack_packets != 0 ||
2625 stats.rtcp_packet_type_counts.pli_packets != 0 ||
2626 stats.rtcp_packet_type_counts.nack_requests != 0 ||
2627 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbosf42376c2015-08-28 07:35:32 -07002628
2629 assert(stats.current_payload_type == -1 ||
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002630 stats.current_payload_type == kFakeVideoSendPayloadType);
pbosf42376c2015-08-28 07:35:32 -07002631 receive_stats_filled_["IncomingPayloadType"] |=
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002632 stats.current_payload_type == kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002633 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002634
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002635 return AllStatsFilled(receive_stats_filled_);
2636 }
2637
2638 bool CheckSendStats() {
Peter Boström74f6e9e2016-04-04 17:56:10 +02002639 RTC_DCHECK(send_stream_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002640 VideoSendStream::Stats stats = send_stream_->GetStats();
2641
2642 send_stats_filled_["NumStreams"] |=
2643 stats.substreams.size() == expected_send_ssrcs_.size();
2644
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002645 send_stats_filled_["CpuOveruseMetrics"] |=
Peter Boströme4499152016-02-05 11:13:28 +01002646 stats.avg_encode_time_ms != 0 && stats.encode_usage_percent != 0;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002647
Peter Boströmb7d9a972015-12-18 16:01:11 +01002648 send_stats_filled_["EncoderImplementationName"] |=
2649 stats.encoder_implementation_name ==
2650 test::FakeEncoder::kImplementationName;
2651
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002652 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002653 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002654 it != stats.substreams.end(); ++it) {
sprangcd349d92016-07-13 09:11:28 -07002655 if (expected_send_ssrcs_.find(it->first) == expected_send_ssrcs_.end())
2656 continue; // Probably RTX.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002657
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002658 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002659 stats.input_frame_rate != 0;
2660
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002661 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002662
2663 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
2664 stream_stats.rtcp_stats.cumulative_lost != 0 ||
2665 stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
2666 stream_stats.rtcp_stats.fraction_lost != 0;
2667
2668 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002669 stream_stats.rtp_stats.fec.packets != 0 ||
2670 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
2671 stream_stats.rtp_stats.retransmitted.packets != 0 ||
2672 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002673
sprangcd349d92016-07-13 09:11:28 -07002674 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Total",
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002675 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002676 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002677
sprangcd349d92016-07-13 09:11:28 -07002678 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Retransmit",
2679 it->first)] |=
2680 stream_stats.retransmit_bitrate_bps != 0;
2681
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002682 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002683 stream_stats.frame_counts.delta_frames != 0 ||
2684 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002685
2686 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
2687 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00002688
2689 send_stats_filled_[CompoundKey("Delay", it->first)] |=
2690 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002691
2692 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
2693 // report dropped packets.
2694 send_stats_filled_["RtcpPacketTypeCount"] |=
2695 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
2696 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
2697 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
2698 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
2699 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002700 }
2701
2702 return AllStatsFilled(send_stats_filled_);
2703 }
2704
2705 std::string CompoundKey(const char* name, uint32_t ssrc) {
2706 std::ostringstream oss;
2707 oss << name << "_" << ssrc;
2708 return oss.str();
2709 }
2710
2711 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
sprangcd349d92016-07-13 09:11:28 -07002712 for (const auto& stat : stats_map) {
2713 if (!stat.second)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002714 return false;
2715 }
2716 return true;
2717 }
2718
stefane74eef12016-01-08 06:47:13 -08002719 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
2720 FakeNetworkPipe::Config network_config;
2721 network_config.loss_percent = 5;
2722 return new test::PacketTransport(
2723 sender_call, this, test::PacketTransport::kSender, network_config);
2724 }
2725
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002726 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002727 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01002728 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002729 return config;
2730 }
2731
stefanff483612015-12-21 03:14:00 -08002732 void ModifyVideoConfigs(
2733 VideoSendStream::Config* send_config,
2734 std::vector<VideoReceiveStream::Config>* receive_configs,
2735 VideoEncoderConfig* encoder_config) override {
sprangcd349d92016-07-13 09:11:28 -07002736 // Set low rates to avoid waiting for rampup.
2737 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2738 encoder_config->streams[i].min_bitrate_bps = 10000;
2739 encoder_config->streams[i].target_bitrate_bps = 15000;
2740 encoder_config->streams[i].max_bitrate_bps = 20000;
2741 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002742 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002743 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002744
sprangcd349d92016-07-13 09:11:28 -07002745 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2746 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
2747
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002748 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002749 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002750 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002751 expected_receive_ssrcs_.push_back(
2752 (*receive_configs)[i].rtp.remote_ssrc);
Peter Boströmdef398832015-05-27 17:59:11 +02002753 (*receive_configs)[i].render_delay_ms = kExpectedRenderDelayMs;
tommi2e82f382016-06-21 00:26:43 -07002754 (*receive_configs)[i].renderer = &receive_stream_renderer_;
sprangcd349d92016-07-13 09:11:28 -07002755 (*receive_configs)[i].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2756
2757 (*receive_configs)[i].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
2758 kSendRtxSsrcs[i];
2759 (*receive_configs)[i].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
2760 kSendRtxPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002761 }
sprangcd349d92016-07-13 09:11:28 -07002762
2763 for (size_t i = 0; i < kNumSsrcs; ++i)
2764 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
2765
Peter Boströmc6e16e32016-02-05 14:15:53 +01002766 // Use a delayed encoder to make sure we see CpuOveruseMetrics stats that
2767 // are non-zero.
2768 send_config->encoder_settings.encoder = &encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002769 }
2770
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002771 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00002772
stefanff483612015-12-21 03:14:00 -08002773 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002774 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002775 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002776 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002777 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002778 }
2779
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002780 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002781 Clock* clock = Clock::GetRealTimeClock();
2782 int64_t now = clock->TimeInMilliseconds();
2783 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
2784 bool receive_ok = false;
2785 bool send_ok = false;
2786
2787 while (now < stop_time) {
2788 if (!receive_ok)
2789 receive_ok = CheckReceiveStats();
2790 if (!send_ok)
2791 send_ok = CheckSendStats();
2792
2793 if (receive_ok && send_ok)
2794 return;
2795
2796 int64_t time_until_timout_ = stop_time - now;
2797 if (time_until_timout_ > 0)
Peter Boström5811a392015-12-10 13:02:50 +01002798 check_stats_event_.Wait(time_until_timout_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002799 now = clock->TimeInMilliseconds();
2800 }
2801
2802 ADD_FAILURE() << "Timed out waiting for filled stats.";
2803 for (std::map<std::string, bool>::const_iterator it =
2804 receive_stats_filled_.begin();
2805 it != receive_stats_filled_.end();
2806 ++it) {
2807 if (!it->second) {
2808 ADD_FAILURE() << "Missing receive stats: " << it->first;
2809 }
2810 }
2811
2812 for (std::map<std::string, bool>::const_iterator it =
2813 send_stats_filled_.begin();
2814 it != send_stats_filled_.end();
2815 ++it) {
2816 if (!it->second) {
2817 ADD_FAILURE() << "Missing send stats: " << it->first;
2818 }
2819 }
2820 }
2821
Peter Boströmc6e16e32016-02-05 14:15:53 +01002822 test::DelayedEncoder encoder_;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002823 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002824 std::map<std::string, bool> receive_stats_filled_;
2825
2826 VideoSendStream* send_stream_;
2827 std::map<std::string, bool> send_stats_filled_;
2828
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002829 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002830 std::set<uint32_t> expected_send_ssrcs_;
2831 std::string expected_cname_;
2832
Peter Boström5811a392015-12-10 13:02:50 +01002833 rtc::Event check_stats_event_;
tommi2e82f382016-06-21 00:26:43 -07002834 ReceiveStreamRenderer receive_stream_renderer_;
stefanf116bd02015-10-27 08:29:42 -07002835 } test;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002836
stefane74eef12016-01-08 06:47:13 -08002837 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002838}
2839
2840TEST_F(EndToEndTest, ReceiverReferenceTimeReportEnabled) {
2841 TestXrReceiverReferenceTimeReport(true);
2842}
2843
2844TEST_F(EndToEndTest, ReceiverReferenceTimeReportDisabled) {
2845 TestXrReceiverReferenceTimeReport(false);
2846}
2847
2848TEST_F(EndToEndTest, TestReceivedRtpPacketStats) {
2849 static const size_t kNumRtpPacketsToSend = 5;
2850 class ReceivedRtpStatsObserver : public test::EndToEndTest {
2851 public:
2852 ReceivedRtpStatsObserver()
2853 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002854 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002855 sent_rtp_(0) {}
2856
2857 private:
stefanff483612015-12-21 03:14:00 -08002858 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002859 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002860 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002861 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002862 }
2863
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002864 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002865 if (sent_rtp_ >= kNumRtpPacketsToSend) {
2866 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002867 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
Peter Boström5811a392015-12-10 13:02:50 +01002868 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002869 }
2870 return DROP_PACKET;
2871 }
2872 ++sent_rtp_;
2873 return SEND_PACKET;
2874 }
2875
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002876 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002877 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002878 << "Timed out while verifying number of received RTP packets.";
2879 }
2880
2881 VideoReceiveStream* receive_stream_;
2882 uint32_t sent_rtp_;
2883 } test;
2884
stefane74eef12016-01-08 06:47:13 -08002885 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002886}
2887
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002888TEST_F(EndToEndTest, SendsSetSsrc) { TestSendsSetSsrcs(1, false); }
2889
2890TEST_F(EndToEndTest, SendsSetSimulcastSsrcs) {
2891 TestSendsSetSsrcs(kNumSsrcs, false);
2892}
2893
2894TEST_F(EndToEndTest, CanSwitchToUseAllSsrcs) {
2895 TestSendsSetSsrcs(kNumSsrcs, true);
2896}
2897
mflodman@webrtc.orgf9460682014-07-24 16:41:25 +00002898TEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002899 class ObserveRedundantPayloads: public test::EndToEndTest {
2900 public:
2901 ObserveRedundantPayloads()
2902 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00002903 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002904 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
2905 }
2906 }
2907
2908 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002909 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002910 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002911 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002912
2913 if (!registered_rtx_ssrc_[header.ssrc])
2914 return SEND_PACKET;
2915
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002916 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002917 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002918 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002919
2920 if (!packet_is_redundant_payload)
2921 return SEND_PACKET;
2922
2923 if (!observed_redundant_retransmission_[header.ssrc]) {
2924 observed_redundant_retransmission_[header.ssrc] = true;
2925 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002926 observation_complete_.Set();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002927 }
2928
2929 return SEND_PACKET;
2930 }
2931
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002932 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002933
stefanff483612015-12-21 03:14:00 -08002934 void ModifyVideoConfigs(
2935 VideoSendStream::Config* send_config,
2936 std::vector<VideoReceiveStream::Config>* receive_configs,
2937 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002938 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002939 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2940 encoder_config->streams[i].min_bitrate_bps = 10000;
2941 encoder_config->streams[i].target_bitrate_bps = 15000;
2942 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002943 }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002944
2945 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002946
2947 for (size_t i = 0; i < kNumSsrcs; ++i)
2948 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00002949
2950 // Significantly higher than max bitrates for all video streams -> forcing
2951 // padding to trigger redundant padding on all RTX SSRCs.
2952 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002953 }
2954
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002955 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002956 EXPECT_TRUE(Wait())
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002957 << "Timed out while waiting for redundant payloads on all SSRCs.";
2958 }
2959
2960 private:
2961 size_t ssrcs_to_observe_;
2962 std::map<uint32_t, bool> observed_redundant_retransmission_;
2963 std::map<uint32_t, bool> registered_rtx_ssrc_;
2964 } test;
2965
stefane74eef12016-01-08 06:47:13 -08002966 RunBaseTest(&test);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002967}
2968
Danil Chapovalov70ffead2016-07-20 15:26:59 +02002969void EndToEndTest::TestRtpStatePreservation(bool use_rtx,
2970 bool provoke_rtcpsr_before_rtp) {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002971 class RtpSequenceObserver : public test::RtpRtcpObserver {
2972 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00002973 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002974 : test::RtpRtcpObserver(kDefaultTimeoutMs),
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002975 ssrcs_to_observe_(kNumSsrcs) {
2976 for (size_t i = 0; i < kNumSsrcs; ++i) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002977 configured_ssrcs_[kVideoSendSsrcs[i]] = true;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002978 if (use_rtx)
2979 configured_ssrcs_[kSendRtxSsrcs[i]] = true;
2980 }
2981 }
2982
2983 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
Peter Boströmf2f82832015-05-01 13:00:41 +02002984 rtc::CritScope lock(&crit_);
danilchap34877ee2016-02-01 08:25:04 -08002985 ssrc_observed_.clear();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002986 ssrcs_to_observe_ = num_expected_ssrcs;
2987 }
2988
2989 private:
Danil Chapovalov70ffead2016-07-20 15:26:59 +02002990 void ValidateTimestampGap(uint32_t ssrc,
2991 uint32_t timestamp,
2992 bool only_padding)
2993 EXCLUSIVE_LOCKS_REQUIRED(crit_) {
2994 static const int32_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
2995 auto timestamp_it = last_observed_timestamp_.find(ssrc);
2996 if (timestamp_it == last_observed_timestamp_.end()) {
2997 EXPECT_FALSE(only_padding);
2998 last_observed_timestamp_[ssrc] = timestamp;
2999 } else {
3000 // Verify timestamps are reasonably close.
3001 uint32_t latest_observed = timestamp_it->second;
3002 // Wraparound handling is unnecessary here as long as an int variable
3003 // is used to store the result.
3004 int32_t timestamp_gap = timestamp - latest_observed;
3005 EXPECT_LE(std::abs(timestamp_gap), kMaxTimestampGap)
3006 << "Gap in timestamps (" << latest_observed << " -> " << timestamp
3007 << ") too large for SSRC: " << ssrc << ".";
3008 timestamp_it->second = timestamp;
3009 }
3010 }
3011
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003012 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003013 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003014 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003015 const uint32_t ssrc = header.ssrc;
danilchap5c35cf92016-02-03 14:14:49 -08003016 const int64_t sequence_number =
3017 seq_numbers_unwrapper_.Unwrap(header.sequenceNumber);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003018 const uint32_t timestamp = header.timestamp;
danilchap34877ee2016-02-01 08:25:04 -08003019 const bool only_padding =
3020 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003021
3022 EXPECT_TRUE(configured_ssrcs_[ssrc])
3023 << "Received SSRC that wasn't configured: " << ssrc;
3024
danilchap5c35cf92016-02-03 14:14:49 -08003025 static const int64_t kMaxSequenceNumberGap = 100;
3026 std::list<int64_t>* seq_numbers = &last_observed_seq_numbers_[ssrc];
3027 if (seq_numbers->empty()) {
3028 seq_numbers->push_back(sequence_number);
3029 } else {
3030 // We shouldn't get replays of previous sequence numbers.
3031 for (int64_t observed : *seq_numbers) {
3032 EXPECT_NE(observed, sequence_number)
3033 << "Received sequence number " << sequence_number
3034 << " for SSRC " << ssrc << " 2nd time.";
3035 }
3036 // Verify sequence numbers are reasonably close.
3037 int64_t latest_observed = seq_numbers->back();
3038 int64_t sequence_number_gap = sequence_number - latest_observed;
3039 EXPECT_LE(std::abs(sequence_number_gap), kMaxSequenceNumberGap)
3040 << "Gap in sequence numbers (" << latest_observed << " -> "
3041 << sequence_number << ") too large for SSRC: " << ssrc << ".";
3042 seq_numbers->push_back(sequence_number);
3043 if (seq_numbers->size() >= kMaxSequenceNumberGap) {
3044 seq_numbers->pop_front();
3045 }
3046 }
3047
danilchap34877ee2016-02-01 08:25:04 -08003048 rtc::CritScope lock(&crit_);
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003049 ValidateTimestampGap(ssrc, timestamp, only_padding);
3050
danilchap34877ee2016-02-01 08:25:04 -08003051 // Wait for media packets on all ssrcs.
3052 if (!ssrc_observed_[ssrc] && !only_padding) {
3053 ssrc_observed_[ssrc] = true;
3054 if (--ssrcs_to_observe_ == 0)
3055 observation_complete_.Set();
3056 }
3057
danilchapf4b9c772016-01-28 06:14:24 -08003058 return SEND_PACKET;
3059 }
3060
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003061 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
3062 test::RtcpPacketParser rtcp_parser;
3063 rtcp_parser.Parse(packet, length);
3064 if (rtcp_parser.sender_report()->num_packets() > 0) {
3065 uint32_t ssrc = rtcp_parser.sender_report()->Ssrc();
3066 uint32_t rtcp_timestamp = rtcp_parser.sender_report()->RtpTimestamp();
3067
3068 rtc::CritScope lock(&crit_);
3069 ValidateTimestampGap(ssrc, rtcp_timestamp, false);
3070 }
3071 return SEND_PACKET;
3072 }
3073
danilchap5c35cf92016-02-03 14:14:49 -08003074 SequenceNumberUnwrapper seq_numbers_unwrapper_;
3075 std::map<uint32_t, std::list<int64_t>> last_observed_seq_numbers_;
danilchap34877ee2016-02-01 08:25:04 -08003076 std::map<uint32_t, uint32_t> last_observed_timestamp_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003077 std::map<uint32_t, bool> configured_ssrcs_;
3078
Peter Boströmf2f82832015-05-01 13:00:41 +02003079 rtc::CriticalSection crit_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003080 size_t ssrcs_to_observe_ GUARDED_BY(crit_);
danilchap34877ee2016-02-01 08:25:04 -08003081 std::map<uint32_t, bool> ssrc_observed_ GUARDED_BY(crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003082 } observer(use_rtx);
3083
solenberg4fbae2b2015-08-28 04:07:10 -07003084 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003085
stefanf116bd02015-10-27 08:29:42 -07003086 test::PacketTransport send_transport(sender_call_.get(), &observer,
3087 test::PacketTransport::kSender,
3088 FakeNetworkPipe::Config());
3089 test::PacketTransport receive_transport(nullptr, &observer,
3090 test::PacketTransport::kReceiver,
3091 FakeNetworkPipe::Config());
3092 send_transport.SetReceiver(receiver_call_->Receiver());
3093 receive_transport.SetReceiver(sender_call_->Receiver());
3094
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003095 CreateSendConfig(kNumSsrcs, 0, &send_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003096
3097 if (use_rtx) {
3098 for (size_t i = 0; i < kNumSsrcs; ++i) {
stefanff483612015-12-21 03:14:00 -08003099 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003100 }
stefanff483612015-12-21 03:14:00 -08003101 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003102 }
3103
3104 // Lower bitrates so that all streams send initially.
stefanff483612015-12-21 03:14:00 -08003105 for (size_t i = 0; i < video_encoder_config_.streams.size(); ++i) {
3106 video_encoder_config_.streams[i].min_bitrate_bps = 10000;
3107 video_encoder_config_.streams[i].target_bitrate_bps = 15000;
3108 video_encoder_config_.streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003109 }
3110
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003111 // Use the same total bitrates when sending a single stream to avoid lowering
3112 // the bitrate estimate and requiring a subsequent rampup.
stefanff483612015-12-21 03:14:00 -08003113 VideoEncoderConfig one_stream = video_encoder_config_;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003114 one_stream.streams.resize(1);
stefanff483612015-12-21 03:14:00 -08003115 for (size_t i = 1; i < video_encoder_config_.streams.size(); ++i) {
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003116 one_stream.streams.front().min_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003117 video_encoder_config_.streams[i].min_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003118 one_stream.streams.front().target_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003119 video_encoder_config_.streams[i].target_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003120 one_stream.streams.front().max_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003121 video_encoder_config_.streams[i].max_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003122 }
3123
stefanf116bd02015-10-27 08:29:42 -07003124 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003125
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003126 CreateVideoStreams();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003127 CreateFrameGeneratorCapturer();
3128
3129 Start();
Peter Boström5811a392015-12-10 13:02:50 +01003130 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003131 << "Timed out waiting for all SSRCs to send packets.";
3132
3133 // Test stream resetting more than once to make sure that the state doesn't
3134 // get set once (this could be due to using std::map::insert for instance).
3135 for (size_t i = 0; i < 3; ++i) {
3136 frame_generator_capturer_->Stop();
stefanff483612015-12-21 03:14:00 -08003137 sender_call_->DestroyVideoSendStream(video_send_stream_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003138
3139 // Re-create VideoSendStream with only one stream.
stefanff483612015-12-21 03:14:00 -08003140 video_send_stream_ =
3141 sender_call_->CreateVideoSendStream(video_send_config_, one_stream);
3142 video_send_stream_->Start();
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003143 if (provoke_rtcpsr_before_rtp) {
3144 // Rapid Resync Request forces sending RTCP Sender Report back.
3145 // Using this request speeds up this test because then there is no need
3146 // to wait for a second for periodic Sender Report.
3147 rtcp::RapidResyncRequest force_send_sr_back_request;
3148 rtc::Buffer packet = force_send_sr_back_request.Build();
3149 static_cast<webrtc::test::DirectTransport&>(receive_transport)
3150 .SendRtcp(packet.data(), packet.size());
3151 }
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003152 CreateFrameGeneratorCapturer();
3153 frame_generator_capturer_->Start();
3154
3155 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003156 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003157
3158 // Reconfigure back to use all streams.
stefanff483612015-12-21 03:14:00 -08003159 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003160 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003161 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003162 << "Timed out waiting for all SSRCs to send packets.";
3163
3164 // Reconfigure down to one stream.
stefanff483612015-12-21 03:14:00 -08003165 video_send_stream_->ReconfigureVideoEncoder(one_stream);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003166 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003167 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003168
3169 // Reconfigure back to use all streams.
stefanff483612015-12-21 03:14:00 -08003170 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003171 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003172 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003173 << "Timed out waiting for all SSRCs to send packets.";
3174 }
3175
stefanf116bd02015-10-27 08:29:42 -07003176 send_transport.StopSending();
3177 receive_transport.StopSending();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003178
3179 Stop();
3180 DestroyStreams();
3181}
3182
Peter Boströmfc968a22016-02-19 16:14:37 +01003183TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpState) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003184 TestRtpStatePreservation(false, false);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003185}
3186
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003187// These tests are flaky. See:
deadbeef1caff882016-06-27 13:09:52 -07003188// https://bugs.chromium.org/p/webrtc/issues/detail?id=4332
3189TEST_F(EndToEndTest, DISABLED_RestartingSendStreamPreservesRtpStatesWithRtx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003190 TestRtpStatePreservation(true, false);
3191}
3192
3193TEST_F(EndToEndTest,
3194 DISABLED_RestartingSendStreamKeepsRtpAndRtcpTimestampsSynced) {
3195 TestRtpStatePreservation(true, true);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003196}
3197
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003198TEST_F(EndToEndTest, RespectsNetworkState) {
3199 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
3200 // down blocks until no more packets will be sent.
3201
3202 // Pacer will send from its packet list and then send required padding before
3203 // checking paused_ again. This should be enough for one round of pacing,
3204 // otherwise increase.
3205 static const int kNumAcceptedDowntimeRtp = 5;
3206 // A single RTCP may be in the pipeline.
3207 static const int kNumAcceptedDowntimeRtcp = 1;
3208 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
3209 public:
3210 NetworkStateTest()
3211 : EndToEndTest(kDefaultTimeoutMs),
3212 FakeEncoder(Clock::GetRealTimeClock()),
Peter Boström5811a392015-12-10 13:02:50 +01003213 encoded_frames_(false, false),
3214 packet_event_(false, false),
sprang867fb522015-08-03 04:38:41 -07003215 sender_call_(nullptr),
3216 receiver_call_(nullptr),
Jelena Marusiccd670222015-07-16 09:30:09 +02003217 sender_state_(kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003218 sender_rtp_(0),
3219 sender_rtcp_(0),
3220 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003221 down_frames_(0) {}
3222
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003223 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003224 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003225 ++sender_rtp_;
Peter Boström5811a392015-12-10 13:02:50 +01003226 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003227 return SEND_PACKET;
3228 }
3229
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003230 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003231 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003232 ++sender_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003233 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003234 return SEND_PACKET;
3235 }
3236
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003237 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003238 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
3239 return SEND_PACKET;
3240 }
3241
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003242 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003243 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003244 ++receiver_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003245 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003246 return SEND_PACKET;
3247 }
3248
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003249 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003250 sender_call_ = sender_call;
3251 receiver_call_ = receiver_call;
3252 }
3253
stefanff483612015-12-21 03:14:00 -08003254 void ModifyVideoConfigs(
3255 VideoSendStream::Config* send_config,
3256 std::vector<VideoReceiveStream::Config>* receive_configs,
3257 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003258 send_config->encoder_settings.encoder = this;
3259 }
3260
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003261 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003262 EXPECT_TRUE(encoded_frames_.Wait(kDefaultTimeoutMs))
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003263 << "No frames received by the encoder.";
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003264 // Wait for packets from both sender/receiver.
3265 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003266
skvlad7a43d252016-03-22 15:32:27 -07003267 // Sender-side network down for audio; there should be no effect on video
3268 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3269 WaitForPacketsOrSilence(false, false);
3270
3271 // Receiver-side network down for audio; no change expected
3272 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3273 WaitForPacketsOrSilence(false, false);
3274
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003275 // Sender-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003276 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003277 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003278 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003279 // After network goes down we shouldn't be encoding more frames.
Jelena Marusiccd670222015-07-16 09:30:09 +02003280 sender_state_ = kNetworkDown;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003281 }
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003282 // Wait for receiver-packets and no sender packets.
3283 WaitForPacketsOrSilence(true, false);
3284
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003285 // Receiver-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003286 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
3287 WaitForPacketsOrSilence(true, true);
3288
3289 // Network up for audio for both sides; video is still not expected to
3290 // start
3291 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
3292 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003293 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003294
3295 // Network back up again for both.
3296 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003297 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003298 // It's OK to encode frames again, as we're about to bring up the
3299 // network.
Jelena Marusiccd670222015-07-16 09:30:09 +02003300 sender_state_ = kNetworkUp;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003301 }
skvlad7a43d252016-03-22 15:32:27 -07003302 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
3303 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003304 WaitForPacketsOrSilence(false, false);
skvlad7a43d252016-03-22 15:32:27 -07003305
3306 // TODO(skvlad): add tests to verify that the audio streams are stopped
3307 // when the network goes down for audio once the workaround in
3308 // paced_sender.cc is removed.
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003309 }
3310
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07003311 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003312 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07003313 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003314 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003315 rtc::CritScope lock(&test_crit_);
Jelena Marusiccd670222015-07-16 09:30:09 +02003316 if (sender_state_ == kNetworkDown) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003317 ++down_frames_;
3318 EXPECT_LE(down_frames_, 1)
3319 << "Encoding more than one frame while network is down.";
3320 if (down_frames_ > 1)
Peter Boström5811a392015-12-10 13:02:50 +01003321 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003322 } else {
Peter Boström5811a392015-12-10 13:02:50 +01003323 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003324 }
3325 }
3326 return test::FakeEncoder::Encode(
3327 input_image, codec_specific_info, frame_types);
3328 }
3329
3330 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003331 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
3332 int64_t initial_time_ms = clock_->TimeInMilliseconds();
3333 int initial_sender_rtp;
3334 int initial_sender_rtcp;
3335 int initial_receiver_rtcp;
3336 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003337 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003338 initial_sender_rtp = sender_rtp_;
3339 initial_sender_rtcp = sender_rtcp_;
3340 initial_receiver_rtcp = receiver_rtcp_;
3341 }
3342 bool sender_done = false;
3343 bool receiver_done = false;
mflodmand1590b22015-12-09 07:07:59 -08003344 while (!sender_done || !receiver_done) {
Peter Boström5811a392015-12-10 13:02:50 +01003345 packet_event_.Wait(kSilenceTimeoutMs);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003346 int64_t time_now_ms = clock_->TimeInMilliseconds();
Peter Boströmf2f82832015-05-01 13:00:41 +02003347 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003348 if (sender_down) {
3349 ASSERT_LE(sender_rtp_ - initial_sender_rtp, kNumAcceptedDowntimeRtp)
3350 << "RTP sent during sender-side downtime.";
3351 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
3352 kNumAcceptedDowntimeRtcp)
3353 << "RTCP sent during sender-side downtime.";
3354 if (time_now_ms - initial_time_ms >=
3355 static_cast<int64_t>(kSilenceTimeoutMs)) {
3356 sender_done = true;
3357 }
3358 } else {
skvlad7a43d252016-03-22 15:32:27 -07003359 if (sender_rtp_ > initial_sender_rtp + kNumAcceptedDowntimeRtp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003360 sender_done = true;
3361 }
3362 if (receiver_down) {
3363 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
3364 kNumAcceptedDowntimeRtcp)
3365 << "RTCP sent during receiver-side downtime.";
3366 if (time_now_ms - initial_time_ms >=
3367 static_cast<int64_t>(kSilenceTimeoutMs)) {
3368 receiver_done = true;
3369 }
3370 } else {
skvlad7a43d252016-03-22 15:32:27 -07003371 if (receiver_rtcp_ > initial_receiver_rtcp + kNumAcceptedDowntimeRtcp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003372 receiver_done = true;
3373 }
3374 }
3375 }
3376
Peter Boströmf2f82832015-05-01 13:00:41 +02003377 rtc::CriticalSection test_crit_;
Peter Boström5811a392015-12-10 13:02:50 +01003378 rtc::Event encoded_frames_;
3379 rtc::Event packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003380 Call* sender_call_;
3381 Call* receiver_call_;
Jelena Marusiccd670222015-07-16 09:30:09 +02003382 NetworkState sender_state_ GUARDED_BY(test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003383 int sender_rtp_ GUARDED_BY(test_crit_);
3384 int sender_rtcp_ GUARDED_BY(test_crit_);
3385 int receiver_rtcp_ GUARDED_BY(test_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003386 int down_frames_ GUARDED_BY(test_crit_);
3387 } test;
3388
stefane74eef12016-01-08 06:47:13 -08003389 RunBaseTest(&test);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003390}
3391
danilchapa6a70072016-06-01 11:20:43 -07003392TEST_F(EndToEndTest, CallReportsRttForSender) {
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003393 static const int kSendDelayMs = 30;
3394 static const int kReceiveDelayMs = 70;
3395
solenberg4fbae2b2015-08-28 04:07:10 -07003396 CreateCalls(Call::Config(), Call::Config());
3397
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003398 FakeNetworkPipe::Config config;
3399 config.queue_delay_ms = kSendDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003400 test::DirectTransport sender_transport(config, sender_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003401 config.queue_delay_ms = kReceiveDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003402 test::DirectTransport receiver_transport(config, receiver_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003403 sender_transport.SetReceiver(receiver_call_->Receiver());
3404 receiver_transport.SetReceiver(sender_call_->Receiver());
3405
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003406 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07003407 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003408
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003409 CreateVideoStreams();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003410 CreateFrameGeneratorCapturer();
3411 Start();
3412
3413 int64_t start_time_ms = clock_->TimeInMilliseconds();
3414 while (true) {
3415 Call::Stats stats = sender_call_->GetStats();
3416 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
3417 clock_->TimeInMilliseconds())
3418 << "No RTT stats before timeout!";
3419 if (stats.rtt_ms != -1) {
3420 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs);
3421 break;
3422 }
3423 SleepMs(10);
3424 }
3425
3426 Stop();
3427 DestroyStreams();
3428}
3429
skvlad7a43d252016-03-22 15:32:27 -07003430void EndToEndTest::VerifyNewVideoSendStreamsRespectNetworkState(
3431 MediaType network_to_bring_down,
3432 VideoEncoder* encoder,
3433 Transport* transport) {
solenberg4fbae2b2015-08-28 04:07:10 -07003434 CreateSenderCall(Call::Config());
skvlad7a43d252016-03-22 15:32:27 -07003435 sender_call_->SignalChannelNetworkState(network_to_bring_down, kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003436
skvlad7a43d252016-03-22 15:32:27 -07003437 CreateSendConfig(1, 0, transport);
3438 video_send_config_.encoder_settings.encoder = encoder;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003439 CreateVideoStreams();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003440 CreateFrameGeneratorCapturer();
3441
3442 Start();
3443 SleepMs(kSilenceTimeoutMs);
3444 Stop();
3445
3446 DestroyStreams();
3447}
3448
skvlad7a43d252016-03-22 15:32:27 -07003449void EndToEndTest::VerifyNewVideoReceiveStreamsRespectNetworkState(
3450 MediaType network_to_bring_down,
3451 Transport* transport) {
solenberg4fbae2b2015-08-28 04:07:10 -07003452 CreateCalls(Call::Config(), Call::Config());
skvlad7a43d252016-03-22 15:32:27 -07003453 receiver_call_->SignalChannelNetworkState(network_to_bring_down,
3454 kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003455
stefanf116bd02015-10-27 08:29:42 -07003456 test::DirectTransport sender_transport(sender_call_.get());
solenberg4fbae2b2015-08-28 04:07:10 -07003457 sender_transport.SetReceiver(receiver_call_->Receiver());
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003458 CreateSendConfig(1, 0, &sender_transport);
skvlad7a43d252016-03-22 15:32:27 -07003459 CreateMatchingReceiveConfigs(transport);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003460 CreateVideoStreams();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003461 CreateFrameGeneratorCapturer();
3462
3463 Start();
3464 SleepMs(kSilenceTimeoutMs);
3465 Stop();
3466
3467 sender_transport.StopSending();
3468
3469 DestroyStreams();
3470}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00003471
skvlad7a43d252016-03-22 15:32:27 -07003472TEST_F(EndToEndTest, NewVideoSendStreamsRespectVideoNetworkDown) {
3473 class UnusedEncoder : public test::FakeEncoder {
3474 public:
3475 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
perkjfea93092016-05-14 00:58:48 -07003476
3477 int32_t InitEncode(const VideoCodec* config,
3478 int32_t number_of_cores,
3479 size_t max_payload_size) override {
3480 EXPECT_GT(config->startBitrate, 0u);
3481 return 0;
3482 }
skvlad7a43d252016-03-22 15:32:27 -07003483 int32_t Encode(const VideoFrame& input_image,
3484 const CodecSpecificInfo* codec_specific_info,
3485 const std::vector<FrameType>* frame_types) override {
3486 ADD_FAILURE() << "Unexpected frame encode.";
3487 return test::FakeEncoder::Encode(input_image, codec_specific_info,
3488 frame_types);
3489 }
3490 };
3491
3492 UnusedEncoder unused_encoder;
3493 UnusedTransport unused_transport;
3494 VerifyNewVideoSendStreamsRespectNetworkState(
3495 MediaType::VIDEO, &unused_encoder, &unused_transport);
3496}
3497
3498TEST_F(EndToEndTest, NewVideoSendStreamsIgnoreAudioNetworkDown) {
3499 class RequiredEncoder : public test::FakeEncoder {
3500 public:
3501 RequiredEncoder()
3502 : FakeEncoder(Clock::GetRealTimeClock()), encoded_frame_(false) {}
3503 ~RequiredEncoder() {
3504 if (!encoded_frame_) {
3505 ADD_FAILURE() << "Didn't encode an expected frame";
3506 }
3507 }
3508 int32_t Encode(const VideoFrame& input_image,
3509 const CodecSpecificInfo* codec_specific_info,
3510 const std::vector<FrameType>* frame_types) override {
3511 encoded_frame_ = true;
3512 return test::FakeEncoder::Encode(input_image, codec_specific_info,
3513 frame_types);
3514 }
3515
3516 private:
3517 bool encoded_frame_;
3518 };
3519
3520 RequiredTransport required_transport(true /*rtp*/, false /*rtcp*/);
3521 RequiredEncoder required_encoder;
3522 VerifyNewVideoSendStreamsRespectNetworkState(
3523 MediaType::AUDIO, &required_encoder, &required_transport);
3524}
3525
3526TEST_F(EndToEndTest, NewVideoReceiveStreamsRespectVideoNetworkDown) {
3527 UnusedTransport transport;
3528 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::VIDEO, &transport);
3529}
3530
3531TEST_F(EndToEndTest, NewVideoReceiveStreamsIgnoreAudioNetworkDown) {
3532 RequiredTransport transport(false /*rtp*/, true /*rtcp*/);
3533 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::AUDIO, &transport);
3534}
3535
Peter Boströmd7da1202015-06-05 14:09:38 +02003536void VerifyEmptyNackConfig(const NackConfig& config) {
3537 EXPECT_EQ(0, config.rtp_history_ms)
3538 << "Enabling NACK requires rtcp-fb: nack negotiation.";
3539}
3540
3541void VerifyEmptyFecConfig(const FecConfig& config) {
3542 EXPECT_EQ(-1, config.ulpfec_payload_type)
3543 << "Enabling FEC requires rtpmap: ulpfec negotiation.";
3544 EXPECT_EQ(-1, config.red_payload_type)
3545 << "Enabling FEC requires rtpmap: red negotiation.";
3546 EXPECT_EQ(-1, config.red_rtx_payload_type)
3547 << "Enabling RTX in FEC requires rtpmap: rtx negotiation.";
3548}
3549
3550TEST_F(EndToEndTest, VerifyDefaultSendConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003551 VideoSendStream::Config default_send_config(nullptr);
Peter Boströmd7da1202015-06-05 14:09:38 +02003552 EXPECT_EQ(0, default_send_config.rtp.nack.rtp_history_ms)
3553 << "Enabling NACK require rtcp-fb: nack negotiation.";
3554 EXPECT_TRUE(default_send_config.rtp.rtx.ssrcs.empty())
3555 << "Enabling RTX requires rtpmap: rtx negotiation.";
3556 EXPECT_TRUE(default_send_config.rtp.extensions.empty())
3557 << "Enabling RTP extensions require negotiation.";
3558
3559 VerifyEmptyNackConfig(default_send_config.rtp.nack);
3560 VerifyEmptyFecConfig(default_send_config.rtp.fec);
3561}
3562
3563TEST_F(EndToEndTest, VerifyDefaultReceiveConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003564 VideoReceiveStream::Config default_receive_config(nullptr);
pbosda903ea2015-10-02 02:36:56 -07003565 EXPECT_EQ(RtcpMode::kCompound, default_receive_config.rtp.rtcp_mode)
Peter Boströmd7da1202015-06-05 14:09:38 +02003566 << "Reduced-size RTCP require rtcp-rsize to be negotiated.";
3567 EXPECT_FALSE(default_receive_config.rtp.remb)
3568 << "REMB require rtcp-fb: goog-remb to be negotiated.";
3569 EXPECT_FALSE(
3570 default_receive_config.rtp.rtcp_xr.receiver_reference_time_report)
3571 << "RTCP XR settings require rtcp-xr to be negotiated.";
3572 EXPECT_TRUE(default_receive_config.rtp.rtx.empty())
3573 << "Enabling RTX requires rtpmap: rtx negotiation.";
3574 EXPECT_TRUE(default_receive_config.rtp.extensions.empty())
3575 << "Enabling RTP extensions require negotiation.";
3576
3577 VerifyEmptyNackConfig(default_receive_config.rtp.nack);
3578 VerifyEmptyFecConfig(default_receive_config.rtp.fec);
3579}
3580
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003581TEST_F(EndToEndTest, TransportSeqNumOnAudioAndVideo) {
3582 static const int kExtensionId = 8;
3583 class TransportSequenceNumberTest : public test::EndToEndTest {
3584 public:
3585 TransportSequenceNumberTest()
3586 : EndToEndTest(kDefaultTimeoutMs),
3587 video_observed_(false),
3588 audio_observed_(false) {
3589 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
3590 kExtensionId);
3591 }
3592
3593 size_t GetNumVideoStreams() const override { return 1; }
3594 size_t GetNumAudioStreams() const override { return 1; }
3595
3596 void ModifyVideoConfigs(
3597 VideoSendStream::Config* send_config,
3598 std::vector<VideoReceiveStream::Config>* receive_configs,
3599 VideoEncoderConfig* encoder_config) override {
3600 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07003601 send_config->rtp.extensions.push_back(RtpExtension(
3602 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003603 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3604 }
3605
3606 void ModifyAudioConfigs(
3607 AudioSendStream::Config* send_config,
3608 std::vector<AudioReceiveStream::Config>* receive_configs) override {
3609 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07003610 send_config->rtp.extensions.push_back(RtpExtension(
3611 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003612 (*receive_configs)[0].rtp.extensions.clear();
3613 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3614 }
3615
3616 Action OnSendRtp(const uint8_t* packet, size_t length) override {
3617 RTPHeader header;
3618 EXPECT_TRUE(parser_->Parse(packet, length, &header));
3619 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
3620 // Unwrap packet id and verify uniqueness.
3621 int64_t packet_id =
3622 unwrapper_.Unwrap(header.extension.transportSequenceNumber);
3623 EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
3624
3625 if (header.ssrc == kVideoSendSsrcs[0])
3626 video_observed_ = true;
3627 if (header.ssrc == kAudioSendSsrc)
3628 audio_observed_ = true;
3629 if (audio_observed_ && video_observed_ &&
3630 received_packet_ids_.size() == 50) {
3631 size_t packet_id_range =
3632 *received_packet_ids_.rbegin() - *received_packet_ids_.begin() + 1;
3633 EXPECT_EQ(received_packet_ids_.size(), packet_id_range);
3634 observation_complete_.Set();
3635 }
3636 return SEND_PACKET;
3637 }
3638
3639 void PerformTest() override {
3640 EXPECT_TRUE(Wait()) << "Timed out while waiting for audio and video "
3641 "packets with transport sequence number.";
3642 }
3643
3644 private:
3645 bool video_observed_;
3646 bool audio_observed_;
3647 SequenceNumberUnwrapper unwrapper_;
3648 std::set<int64_t> received_packet_ids_;
3649 } test;
3650
stefane74eef12016-01-08 06:47:13 -08003651 RunBaseTest(&test);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003652}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003653} // namespace webrtc