blob: 034d06381414668902f4cad15bc18912be295d97 [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),
danilchap192717e2016-07-25 08:20:51 -0700771 retransmitted_timestamp_(0) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000772
773 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000774 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700775 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000776 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000777 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000778
Peter Boström67680c12016-02-17 11:10:04 +0100779 // Ignore padding-only packets over RTX.
780 if (header.payloadType != payload_type_) {
781 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
782 if (length == header.headerLength + header.paddingLength)
783 return SEND_PACKET;
Stefan Holmer586b19b2015-09-18 11:14:31 +0200784 }
Peter Boström67680c12016-02-17 11:10:04 +0100785
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000786 if (header.timestamp == retransmitted_timestamp_) {
787 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
788 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000789 return SEND_PACKET;
790 }
791
Stefan Holmer586b19b2015-09-18 11:14:31 +0200792 // Found the final packet of the frame to inflict loss to, drop this and
793 // expect a retransmission.
danilchapfdd381c2016-07-25 04:03:20 -0700794 if (header.payloadType == payload_type_ && header.markerBit &&
795 ++marker_bits_observed_ == kDroppedFrameNumber) {
Danil Chapovalov18c65a42016-06-29 15:29:34 +0200796 // This should be the only dropped packet.
797 EXPECT_EQ(0u, retransmitted_timestamp_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000798 retransmitted_timestamp_ = header.timestamp;
danilchap192717e2016-07-25 08:20:51 -0700799 if (std::find(rendered_timestamps_.begin(), rendered_timestamps_.end(),
800 retransmitted_timestamp_) != rendered_timestamps_.end()) {
801 // Frame was rendered before last packet was scheduled for sending.
802 // This is extremly rare but possible scenario because prober able to
803 // resend packet before it was send.
804 // TODO(danilchap): Remove this corner case when prober would not be
805 // able to sneak in between packet saved to history for resending and
806 // pacer notified about existance of that packet for sending.
807 // See https://bugs.chromium.org/p/webrtc/issues/detail?id=5540 for
808 // details.
809 observation_complete_.Set();
810 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000811 return DROP_PACKET;
812 }
813
814 return SEND_PACKET;
815 }
816
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700817 void FrameCallback(VideoFrame* frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200818 rtc::CritScope lock(&crit_);
danilchap192717e2016-07-25 08:20:51 -0700819 if (frame->timestamp() == retransmitted_timestamp_)
Peter Boström5811a392015-12-10 13:02:50 +0100820 observation_complete_.Set();
danilchap192717e2016-07-25 08:20:51 -0700821 rendered_timestamps_.push_back(frame->timestamp());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000822 }
823
stefanff483612015-12-21 03:14:00 -0800824 void ModifyVideoConfigs(
825 VideoSendStream::Config* send_config,
826 std::vector<VideoReceiveStream::Config>* receive_configs,
827 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000828 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000829 (*receive_configs)[0].pre_render_callback = this;
830 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
Shao Changbine62202f2015-04-21 20:24:50 +0800831
832 if (payload_type_ == kRedPayloadType) {
833 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
834 send_config->rtp.fec.red_payload_type = kRedPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +0100835 if (retransmission_ssrc_ == kSendRtxSsrcs[0])
836 send_config->rtp.fec.red_rtx_payload_type = kRtxRedPayloadType;
837 (*receive_configs)[0].rtp.fec.ulpfec_payload_type =
838 send_config->rtp.fec.ulpfec_payload_type;
839 (*receive_configs)[0].rtp.fec.red_payload_type =
840 send_config->rtp.fec.red_payload_type;
841 (*receive_configs)[0].rtp.fec.red_rtx_payload_type =
842 send_config->rtp.fec.red_rtx_payload_type;
Shao Changbine62202f2015-04-21 20:24:50 +0800843 }
844
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000845 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
846 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000847 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +0100848 (*receive_configs)[0].rtp.rtx[payload_type_].ssrc = kSendRtxSsrcs[0];
849 (*receive_configs)[0].rtp.rtx[payload_type_].payload_type =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000850 kSendRtxPayloadType;
851 }
Peter Boström39593972016-02-15 11:27:15 +0100852 // Configure encoding and decoding with VP8, since generic packetization
853 // doesn't support FEC with NACK.
854 RTC_DCHECK_EQ(1u, (*receive_configs)[0].decoders.size());
855 send_config->encoder_settings.encoder = encoder_.get();
856 send_config->encoder_settings.payload_name = "VP8";
857 (*receive_configs)[0].decoders[0].payload_name = "VP8";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000858 }
859
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000860 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100861 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000862 << "Timed out while waiting for retransmission to render.";
863 }
864
Shao Changbine62202f2015-04-21 20:24:50 +0800865 int GetPayloadType(bool use_rtx, bool use_red) {
Stefan Holmer10880012016-02-03 13:29:59 +0100866 if (use_red) {
867 if (use_rtx)
868 return kRtxRedPayloadType;
869 return kRedPayloadType;
870 }
871 if (use_rtx)
872 return kSendRtxPayloadType;
873 return kFakeVideoSendPayloadType;
Shao Changbine62202f2015-04-21 20:24:50 +0800874 }
875
stefanf116bd02015-10-27 08:29:42 -0700876 rtc::CriticalSection crit_;
Shao Changbine62202f2015-04-21 20:24:50 +0800877 const int payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000878 const uint32_t retransmission_ssrc_;
879 const int retransmission_payload_type_;
kwiberg27f982b2016-03-01 11:52:33 -0800880 std::unique_ptr<VideoEncoder> encoder_;
Peter Boström39593972016-02-15 11:27:15 +0100881 const std::string payload_name_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000882 int marker_bits_observed_;
stefanf116bd02015-10-27 08:29:42 -0700883 uint32_t retransmitted_timestamp_ GUARDED_BY(&crit_);
danilchap192717e2016-07-25 08:20:51 -0700884 std::vector<uint32_t> rendered_timestamps_ GUARDED_BY(&crit_);
Peter Boström39593972016-02-15 11:27:15 +0100885 } test(enable_rtx, enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000886
stefane74eef12016-01-08 06:47:13 -0800887 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000888}
889
890TEST_F(EndToEndTest, DecodesRetransmittedFrame) {
Shao Changbine62202f2015-04-21 20:24:50 +0800891 DecodesRetransmittedFrame(false, false);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000892}
893
894TEST_F(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +0800895 DecodesRetransmittedFrame(true, false);
896}
897
898TEST_F(EndToEndTest, DecodesRetransmittedFrameByRed) {
899 DecodesRetransmittedFrame(false, true);
900}
901
902TEST_F(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
903 DecodesRetransmittedFrame(true, true);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000904}
905
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000906void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
907 static const int kPacketsToDrop = 1;
908
nisse7ade7b32016-03-23 04:48:10 -0700909 class PliObserver : public test::EndToEndTest,
910 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000911 public:
912 explicit PliObserver(int rtp_history_ms)
913 : EndToEndTest(kLongTimeoutMs),
914 rtp_history_ms_(rtp_history_ms),
915 nack_enabled_(rtp_history_ms > 0),
916 highest_dropped_timestamp_(0),
917 frames_to_drop_(0),
918 received_pli_(false) {}
919
920 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000921 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700922 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000923 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000924 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000925
926 // Drop all retransmitted packets to force a PLI.
927 if (header.timestamp <= highest_dropped_timestamp_)
928 return DROP_PACKET;
929
930 if (frames_to_drop_ > 0) {
931 highest_dropped_timestamp_ = header.timestamp;
932 --frames_to_drop_;
933 return DROP_PACKET;
934 }
935
936 return SEND_PACKET;
937 }
938
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000939 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700940 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000941 RTCPUtility::RTCPParserV2 parser(packet, length, true);
942 EXPECT_TRUE(parser.IsValid());
943
944 for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +0200945 packet_type != RTCPUtility::RTCPPacketTypes::kInvalid;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000946 packet_type = parser.Iterate()) {
947 if (!nack_enabled_)
Erik Språng242e22b2015-05-11 10:17:43 +0200948 EXPECT_NE(packet_type, RTCPUtility::RTCPPacketTypes::kRtpfbNack);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000949
Erik Språng242e22b2015-05-11 10:17:43 +0200950 if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbPli) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000951 received_pli_ = true;
952 break;
953 }
954 }
955 return SEND_PACKET;
956 }
957
nisseeb83a1a2016-03-21 01:27:56 -0700958 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200959 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000960 if (received_pli_ &&
961 video_frame.timestamp() > highest_dropped_timestamp_) {
Peter Boström5811a392015-12-10 13:02:50 +0100962 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000963 }
964 if (!received_pli_)
965 frames_to_drop_ = kPacketsToDrop;
966 }
967
stefanff483612015-12-21 03:14:00 -0800968 void ModifyVideoConfigs(
969 VideoSendStream::Config* send_config,
970 std::vector<VideoReceiveStream::Config>* receive_configs,
971 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000972 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000973 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
974 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000975 }
976
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000977 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100978 EXPECT_TRUE(Wait()) << "Timed out waiting for PLI to be "
979 "received and a frame to be "
980 "rendered afterwards.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000981 }
982
stefanf116bd02015-10-27 08:29:42 -0700983 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000984 int rtp_history_ms_;
985 bool nack_enabled_;
stefanf116bd02015-10-27 08:29:42 -0700986 uint32_t highest_dropped_timestamp_ GUARDED_BY(&crit_);
987 int frames_to_drop_ GUARDED_BY(&crit_);
988 bool received_pli_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000989 } test(rtp_history_ms);
990
stefane74eef12016-01-08 06:47:13 -0800991 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000992}
993
994TEST_F(EndToEndTest, ReceivesPliAndRecoversWithNack) {
995 ReceivesPliAndRecovers(1000);
996}
997
jbauchdb81ffd2015-11-23 03:59:02 -0800998TEST_F(EndToEndTest, ReceivesPliAndRecoversWithoutNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000999 ReceivesPliAndRecovers(0);
1000}
1001
1002TEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
1003 class PacketInputObserver : public PacketReceiver {
1004 public:
1005 explicit PacketInputObserver(PacketReceiver* receiver)
Peter Boström5811a392015-12-10 13:02:50 +01001006 : receiver_(receiver), delivered_packet_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001007
Peter Boström5811a392015-12-10 13:02:50 +01001008 bool Wait() { return delivered_packet_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001009
1010 private:
stefan68786d22015-09-08 05:36:15 -07001011 DeliveryStatus DeliverPacket(MediaType media_type,
1012 const uint8_t* packet,
1013 size_t length,
1014 const PacketTime& packet_time) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001015 if (RtpHeaderParser::IsRtcp(packet, length)) {
stefan68786d22015-09-08 05:36:15 -07001016 return receiver_->DeliverPacket(media_type, packet, length,
1017 packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001018 } else {
1019 DeliveryStatus delivery_status =
stefan68786d22015-09-08 05:36:15 -07001020 receiver_->DeliverPacket(media_type, packet, length, packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001021 EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
Peter Boström5811a392015-12-10 13:02:50 +01001022 delivered_packet_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001023 return delivery_status;
1024 }
1025 }
1026
1027 PacketReceiver* receiver_;
Peter Boström5811a392015-12-10 13:02:50 +01001028 rtc::Event delivered_packet_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001029 };
1030
solenberg4fbae2b2015-08-28 04:07:10 -07001031 CreateCalls(Call::Config(), Call::Config());
1032
stefanf116bd02015-10-27 08:29:42 -07001033 test::DirectTransport send_transport(sender_call_.get());
1034 test::DirectTransport receive_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001035 PacketInputObserver input_observer(receiver_call_->Receiver());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001036 send_transport.SetReceiver(&input_observer);
1037 receive_transport.SetReceiver(sender_call_->Receiver());
1038
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001039 CreateSendConfig(1, 0, &send_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001040 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001041
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001042 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001043 CreateFrameGeneratorCapturer();
1044 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001045
stefanff483612015-12-21 03:14:00 -08001046 receiver_call_->DestroyVideoReceiveStream(video_receive_streams_[0]);
1047 video_receive_streams_.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001048
1049 // Wait() waits for a received packet.
Peter Boström5811a392015-12-10 13:02:50 +01001050 EXPECT_TRUE(input_observer.Wait());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001051
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001052 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001053
1054 DestroyStreams();
1055
1056 send_transport.StopSending();
1057 receive_transport.StopSending();
1058}
1059
pbosda903ea2015-10-02 02:36:56 -07001060void EndToEndTest::RespectsRtcpMode(RtcpMode rtcp_mode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001061 static const int kNumCompoundRtcpPacketsToObserve = 10;
1062 class RtcpModeObserver : public test::EndToEndTest {
1063 public:
pbosda903ea2015-10-02 02:36:56 -07001064 explicit RtcpModeObserver(RtcpMode rtcp_mode)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001065 : EndToEndTest(kDefaultTimeoutMs),
1066 rtcp_mode_(rtcp_mode),
1067 sent_rtp_(0),
1068 sent_rtcp_(0) {}
1069
1070 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001071 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001072 if (++sent_rtp_ % 3 == 0)
1073 return DROP_PACKET;
1074
1075 return SEND_PACKET;
1076 }
1077
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001078 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001079 ++sent_rtcp_;
1080 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1081 EXPECT_TRUE(parser.IsValid());
1082
1083 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1084 bool has_report_block = false;
Erik Språng242e22b2015-05-11 10:17:43 +02001085 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1086 EXPECT_NE(RTCPUtility::RTCPPacketTypes::kSr, packet_type);
1087 if (packet_type == RTCPUtility::RTCPPacketTypes::kRr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001088 has_report_block = true;
1089 break;
1090 }
1091 packet_type = parser.Iterate();
1092 }
1093
1094 switch (rtcp_mode_) {
pbosda903ea2015-10-02 02:36:56 -07001095 case RtcpMode::kCompound:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001096 if (!has_report_block) {
1097 ADD_FAILURE() << "Received RTCP packet without receiver report for "
pbosda903ea2015-10-02 02:36:56 -07001098 "RtcpMode::kCompound.";
Peter Boström5811a392015-12-10 13:02:50 +01001099 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001100 }
1101
1102 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
Peter Boström5811a392015-12-10 13:02:50 +01001103 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001104
1105 break;
pbosda903ea2015-10-02 02:36:56 -07001106 case RtcpMode::kReducedSize:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001107 if (!has_report_block)
Peter Boström5811a392015-12-10 13:02:50 +01001108 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001109 break;
pbosda903ea2015-10-02 02:36:56 -07001110 case RtcpMode::kOff:
1111 RTC_NOTREACHED();
1112 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001113 }
1114
1115 return SEND_PACKET;
1116 }
1117
stefanff483612015-12-21 03:14:00 -08001118 void ModifyVideoConfigs(
1119 VideoSendStream::Config* send_config,
1120 std::vector<VideoReceiveStream::Config>* receive_configs,
1121 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001122 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001123 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1124 (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001125 }
1126
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001127 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001128 EXPECT_TRUE(Wait())
pbosda903ea2015-10-02 02:36:56 -07001129 << (rtcp_mode_ == RtcpMode::kCompound
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001130 ? "Timed out before observing enough compound packets."
1131 : "Timed out before receiving a non-compound RTCP packet.");
1132 }
1133
pbosda903ea2015-10-02 02:36:56 -07001134 RtcpMode rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001135 int sent_rtp_;
1136 int sent_rtcp_;
1137 } test(rtcp_mode);
1138
stefane74eef12016-01-08 06:47:13 -08001139 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001140}
1141
1142TEST_F(EndToEndTest, UsesRtcpCompoundMode) {
pbosda903ea2015-10-02 02:36:56 -07001143 RespectsRtcpMode(RtcpMode::kCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001144}
1145
1146TEST_F(EndToEndTest, UsesRtcpReducedSizeMode) {
pbosda903ea2015-10-02 02:36:56 -07001147 RespectsRtcpMode(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001148}
1149
1150// Test sets up a Call multiple senders with different resolutions and SSRCs.
1151// Another is set up to receive all three of these with different renderers.
sprang867fb522015-08-03 04:38:41 -07001152class MultiStreamTest {
1153 public:
1154 static const size_t kNumStreams = 3;
1155 struct CodecSettings {
1156 uint32_t ssrc;
1157 int width;
1158 int height;
1159 } codec_settings[kNumStreams];
1160
1161 MultiStreamTest() {
1162 // TODO(sprang): Cleanup when msvc supports explicit initializers for array.
1163 codec_settings[0] = {1, 640, 480};
1164 codec_settings[1] = {2, 320, 240};
1165 codec_settings[2] = {3, 240, 160};
1166 }
1167
1168 virtual ~MultiStreamTest() {}
1169
1170 void RunTest() {
kwiberg27f982b2016-03-01 11:52:33 -08001171 std::unique_ptr<Call> sender_call(Call::Create(Call::Config()));
1172 std::unique_ptr<Call> receiver_call(Call::Create(Call::Config()));
1173 std::unique_ptr<test::DirectTransport> sender_transport(
stefanf116bd02015-10-27 08:29:42 -07001174 CreateSendTransport(sender_call.get()));
kwiberg27f982b2016-03-01 11:52:33 -08001175 std::unique_ptr<test::DirectTransport> receiver_transport(
stefanf116bd02015-10-27 08:29:42 -07001176 CreateReceiveTransport(receiver_call.get()));
sprang867fb522015-08-03 04:38:41 -07001177 sender_transport->SetReceiver(receiver_call->Receiver());
1178 receiver_transport->SetReceiver(sender_call->Receiver());
1179
kwiberg27f982b2016-03-01 11:52:33 -08001180 std::unique_ptr<VideoEncoder> encoders[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001181 for (size_t i = 0; i < kNumStreams; ++i)
1182 encoders[i].reset(VideoEncoder::Create(VideoEncoder::kVp8));
1183
1184 VideoSendStream* send_streams[kNumStreams];
1185 VideoReceiveStream* receive_streams[kNumStreams];
1186
1187 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
kwiberg4a206a92016-03-31 10:24:26 -07001188 std::vector<std::unique_ptr<VideoDecoder>> allocated_decoders;
sprang867fb522015-08-03 04:38:41 -07001189 for (size_t i = 0; i < kNumStreams; ++i) {
1190 uint32_t ssrc = codec_settings[i].ssrc;
1191 int width = codec_settings[i].width;
1192 int height = codec_settings[i].height;
1193
solenberg4fbae2b2015-08-28 04:07:10 -07001194 VideoSendStream::Config send_config(sender_transport.get());
sprang867fb522015-08-03 04:38:41 -07001195 send_config.rtp.ssrcs.push_back(ssrc);
1196 send_config.encoder_settings.encoder = encoders[i].get();
1197 send_config.encoder_settings.payload_name = "VP8";
1198 send_config.encoder_settings.payload_type = 124;
1199 VideoEncoderConfig encoder_config;
1200 encoder_config.streams = test::CreateVideoStreams(1);
1201 VideoStream* stream = &encoder_config.streams[0];
1202 stream->width = width;
1203 stream->height = height;
1204 stream->max_framerate = 5;
1205 stream->min_bitrate_bps = stream->target_bitrate_bps =
1206 stream->max_bitrate_bps = 100000;
1207
1208 UpdateSendConfig(i, &send_config, &encoder_config, &frame_generators[i]);
1209
1210 send_streams[i] =
1211 sender_call->CreateVideoSendStream(send_config, encoder_config);
1212 send_streams[i]->Start();
1213
solenberg4fbae2b2015-08-28 04:07:10 -07001214 VideoReceiveStream::Config receive_config(receiver_transport.get());
sprang867fb522015-08-03 04:38:41 -07001215 receive_config.rtp.remote_ssrc = ssrc;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001216 receive_config.rtp.local_ssrc = test::CallTest::kReceiverLocalVideoSsrc;
sprang867fb522015-08-03 04:38:41 -07001217 VideoReceiveStream::Decoder decoder =
1218 test::CreateMatchingDecoder(send_config.encoder_settings);
kwiberg4a206a92016-03-31 10:24:26 -07001219 allocated_decoders.push_back(
1220 std::unique_ptr<VideoDecoder>(decoder.decoder));
sprang867fb522015-08-03 04:38:41 -07001221 receive_config.decoders.push_back(decoder);
1222
1223 UpdateReceiveConfig(i, &receive_config);
1224
1225 receive_streams[i] =
Tommi733b5472016-06-10 17:58:01 +02001226 receiver_call->CreateVideoReceiveStream(std::move(receive_config));
sprang867fb522015-08-03 04:38:41 -07001227 receive_streams[i]->Start();
1228
1229 frame_generators[i] = test::FrameGeneratorCapturer::Create(
1230 send_streams[i]->Input(), width, height, 30,
1231 Clock::GetRealTimeClock());
1232 frame_generators[i]->Start();
1233 }
1234
1235 Wait();
1236
1237 for (size_t i = 0; i < kNumStreams; ++i) {
1238 frame_generators[i]->Stop();
1239 sender_call->DestroyVideoSendStream(send_streams[i]);
1240 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1241 delete frame_generators[i];
1242 }
1243
1244 sender_transport->StopSending();
1245 receiver_transport->StopSending();
1246 }
1247
1248 protected:
1249 virtual void Wait() = 0;
1250 // Note: frame_generator is a point-to-pointer, since the actual instance
1251 // hasn't been created at the time of this call. Only when packets/frames
1252 // start flowing should this be dereferenced.
1253 virtual void UpdateSendConfig(
1254 size_t stream_index,
1255 VideoSendStream::Config* send_config,
1256 VideoEncoderConfig* encoder_config,
1257 test::FrameGeneratorCapturer** frame_generator) {}
1258 virtual void UpdateReceiveConfig(size_t stream_index,
1259 VideoReceiveStream::Config* receive_config) {
1260 }
stefanf116bd02015-10-27 08:29:42 -07001261 virtual test::DirectTransport* CreateSendTransport(Call* sender_call) {
1262 return new test::DirectTransport(sender_call);
sprang867fb522015-08-03 04:38:41 -07001263 }
stefanf116bd02015-10-27 08:29:42 -07001264 virtual test::DirectTransport* CreateReceiveTransport(Call* receiver_call) {
1265 return new test::DirectTransport(receiver_call);
sprang867fb522015-08-03 04:38:41 -07001266 }
1267};
1268
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001269// Each renderer verifies that it receives the expected resolution, and as soon
1270// as every renderer has received a frame, the test finishes.
andresp@webrtc.org02686112014-09-19 08:24:19 +00001271TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) {
nisse7ade7b32016-03-23 04:48:10 -07001272 class VideoOutputObserver : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001273 public:
sprang867fb522015-08-03 04:38:41 -07001274 VideoOutputObserver(const MultiStreamTest::CodecSettings& settings,
1275 uint32_t ssrc,
1276 test::FrameGeneratorCapturer** frame_generator)
1277 : settings_(settings),
1278 ssrc_(ssrc),
1279 frame_generator_(frame_generator),
Peter Boström5811a392015-12-10 13:02:50 +01001280 done_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001281
nisseeb83a1a2016-03-21 01:27:56 -07001282 void OnFrame(const VideoFrame& video_frame) override {
sprang867fb522015-08-03 04:38:41 -07001283 EXPECT_EQ(settings_.width, video_frame.width());
1284 EXPECT_EQ(settings_.height, video_frame.height());
1285 (*frame_generator_)->Stop();
Peter Boström5811a392015-12-10 13:02:50 +01001286 done_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001287 }
1288
sprang867fb522015-08-03 04:38:41 -07001289 uint32_t Ssrc() { return ssrc_; }
1290
Peter Boström5811a392015-12-10 13:02:50 +01001291 bool Wait() { return done_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001292
1293 private:
sprang867fb522015-08-03 04:38:41 -07001294 const MultiStreamTest::CodecSettings& settings_;
1295 const uint32_t ssrc_;
1296 test::FrameGeneratorCapturer** const frame_generator_;
Peter Boström5811a392015-12-10 13:02:50 +01001297 rtc::Event done_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001298 };
1299
sprang867fb522015-08-03 04:38:41 -07001300 class Tester : public MultiStreamTest {
1301 public:
1302 Tester() {}
1303 virtual ~Tester() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001304
sprang867fb522015-08-03 04:38:41 -07001305 protected:
1306 void Wait() override {
1307 for (const auto& observer : observers_) {
Peter Boström5811a392015-12-10 13:02:50 +01001308 EXPECT_TRUE(observer->Wait()) << "Time out waiting for from on ssrc "
1309 << observer->Ssrc();
sprang867fb522015-08-03 04:38:41 -07001310 }
1311 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001312
sprang867fb522015-08-03 04:38:41 -07001313 void UpdateSendConfig(
1314 size_t stream_index,
1315 VideoSendStream::Config* send_config,
1316 VideoEncoderConfig* encoder_config,
1317 test::FrameGeneratorCapturer** frame_generator) override {
1318 observers_[stream_index].reset(new VideoOutputObserver(
1319 codec_settings[stream_index], send_config->rtp.ssrcs.front(),
1320 frame_generator));
1321 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001322
sprang867fb522015-08-03 04:38:41 -07001323 void UpdateReceiveConfig(
1324 size_t stream_index,
1325 VideoReceiveStream::Config* receive_config) override {
1326 receive_config->renderer = observers_[stream_index].get();
1327 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001328
sprang867fb522015-08-03 04:38:41 -07001329 private:
kwiberg27f982b2016-03-01 11:52:33 -08001330 std::unique_ptr<VideoOutputObserver> observers_[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001331 } tester;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001332
sprang867fb522015-08-03 04:38:41 -07001333 tester.RunTest();
1334}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001335
sprang867fb522015-08-03 04:38:41 -07001336TEST_F(EndToEndTest, AssignsTransportSequenceNumbers) {
sprang867fb522015-08-03 04:38:41 -07001337 static const int kExtensionId = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001338
sprang867fb522015-08-03 04:38:41 -07001339 class RtpExtensionHeaderObserver : public test::DirectTransport {
1340 public:
stefanf116bd02015-10-27 08:29:42 -07001341 RtpExtensionHeaderObserver(Call* sender_call,
1342 const uint32_t& first_media_ssrc,
sprang861c55e2015-10-16 10:01:21 -07001343 const std::map<uint32_t, uint32_t>& ssrc_map)
stefanf116bd02015-10-27 08:29:42 -07001344 : DirectTransport(sender_call),
Peter Boström5811a392015-12-10 13:02:50 +01001345 done_(false, false),
sprang867fb522015-08-03 04:38:41 -07001346 parser_(RtpHeaderParser::Create()),
sprang861c55e2015-10-16 10:01:21 -07001347 first_media_ssrc_(first_media_ssrc),
1348 rtx_to_media_ssrcs_(ssrc_map),
sprang867fb522015-08-03 04:38:41 -07001349 padding_observed_(false),
sprang861c55e2015-10-16 10:01:21 -07001350 rtx_padding_observed_(false),
1351 retransmit_observed_(false),
1352 started_(false) {
sprang867fb522015-08-03 04:38:41 -07001353 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
1354 kExtensionId);
1355 }
1356 virtual ~RtpExtensionHeaderObserver() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001357
stefan1d8a5062015-10-02 03:39:33 -07001358 bool SendRtp(const uint8_t* data,
1359 size_t length,
1360 const PacketOptions& options) override {
sprang861c55e2015-10-16 10:01:21 -07001361 {
1362 rtc::CritScope cs(&lock_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001363
Erik Språng8d629712015-08-04 16:24:03 +02001364 if (IsDone())
sprang861c55e2015-10-16 10:01:21 -07001365 return false;
1366
1367 if (started_) {
1368 RTPHeader header;
1369 EXPECT_TRUE(parser_->Parse(data, length, &header));
1370 bool drop_packet = false;
1371
1372 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
1373 EXPECT_EQ(options.packet_id,
1374 header.extension.transportSequenceNumber);
1375 if (!streams_observed_.empty()) {
1376 // Unwrap packet id and verify uniqueness.
1377 int64_t packet_id = unwrapper_.Unwrap(options.packet_id);
1378 EXPECT_TRUE(received_packed_ids_.insert(packet_id).second);
1379 }
1380
1381 // Drop (up to) every 17th packet, so we get retransmits.
1382 // Only drop media, and not on the first stream (otherwise it will be
1383 // hard to distinguish from padding, which is always sent on the first
1384 // stream).
1385 if (header.payloadType != kSendRtxPayloadType &&
1386 header.ssrc != first_media_ssrc_ &&
1387 header.extension.transportSequenceNumber % 17 == 0) {
1388 dropped_seq_[header.ssrc].insert(header.sequenceNumber);
1389 drop_packet = true;
1390 }
1391
1392 size_t payload_length =
1393 length - (header.headerLength + header.paddingLength);
1394 if (payload_length == 0) {
1395 padding_observed_ = true;
1396 } else if (header.payloadType == kSendRtxPayloadType) {
1397 uint16_t original_sequence_number =
1398 ByteReader<uint16_t>::ReadBigEndian(&data[header.headerLength]);
1399 uint32_t original_ssrc =
1400 rtx_to_media_ssrcs_.find(header.ssrc)->second;
1401 std::set<uint16_t>* seq_no_map = &dropped_seq_[original_ssrc];
1402 auto it = seq_no_map->find(original_sequence_number);
1403 if (it != seq_no_map->end()) {
1404 retransmit_observed_ = true;
1405 seq_no_map->erase(it);
1406 } else {
1407 rtx_padding_observed_ = true;
1408 }
1409 } else {
1410 streams_observed_.insert(header.ssrc);
1411 }
1412
1413 if (IsDone())
Peter Boström5811a392015-12-10 13:02:50 +01001414 done_.Set();
sprang861c55e2015-10-16 10:01:21 -07001415
1416 if (drop_packet)
1417 return true;
1418 }
sprang867fb522015-08-03 04:38:41 -07001419 }
sprang861c55e2015-10-16 10:01:21 -07001420
stefan1d8a5062015-10-02 03:39:33 -07001421 return test::DirectTransport::SendRtp(data, length, options);
sprang867fb522015-08-03 04:38:41 -07001422 }
1423
Erik Språng8d629712015-08-04 16:24:03 +02001424 bool IsDone() {
sprang861c55e2015-10-16 10:01:21 -07001425 bool observed_types_ok =
1426 streams_observed_.size() == MultiStreamTest::kNumStreams &&
1427 padding_observed_ && retransmit_observed_ && rtx_padding_observed_;
1428 if (!observed_types_ok)
1429 return false;
1430 // We should not have any gaps in the sequence number range.
1431 size_t seqno_range =
1432 *received_packed_ids_.rbegin() - *received_packed_ids_.begin() + 1;
1433 return seqno_range == received_packed_ids_.size();
Erik Språng8d629712015-08-04 16:24:03 +02001434 }
1435
Peter Boström5811a392015-12-10 13:02:50 +01001436 bool Wait() {
sprang861c55e2015-10-16 10:01:21 -07001437 {
1438 // Can't be sure until this point that rtx_to_media_ssrcs_ etc have
1439 // been initialized and are OK to read.
1440 rtc::CritScope cs(&lock_);
1441 started_ = true;
1442 }
Peter Boström5811a392015-12-10 13:02:50 +01001443 return done_.Wait(kDefaultTimeoutMs);
sprang861c55e2015-10-16 10:01:21 -07001444 }
sprang867fb522015-08-03 04:38:41 -07001445
sprang861c55e2015-10-16 10:01:21 -07001446 rtc::CriticalSection lock_;
Peter Boström5811a392015-12-10 13:02:50 +01001447 rtc::Event done_;
kwiberg27f982b2016-03-01 11:52:33 -08001448 std::unique_ptr<RtpHeaderParser> parser_;
sprang861c55e2015-10-16 10:01:21 -07001449 SequenceNumberUnwrapper unwrapper_;
1450 std::set<int64_t> received_packed_ids_;
sprang867fb522015-08-03 04:38:41 -07001451 std::set<uint32_t> streams_observed_;
sprang861c55e2015-10-16 10:01:21 -07001452 std::map<uint32_t, std::set<uint16_t>> dropped_seq_;
1453 const uint32_t& first_media_ssrc_;
1454 const std::map<uint32_t, uint32_t>& rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001455 bool padding_observed_;
1456 bool rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001457 bool retransmit_observed_;
1458 bool started_;
sprang867fb522015-08-03 04:38:41 -07001459 };
1460
1461 class TransportSequenceNumberTester : public MultiStreamTest {
1462 public:
sprang861c55e2015-10-16 10:01:21 -07001463 TransportSequenceNumberTester()
1464 : first_media_ssrc_(0), observer_(nullptr) {}
sprang867fb522015-08-03 04:38:41 -07001465 virtual ~TransportSequenceNumberTester() {}
1466
1467 protected:
1468 void Wait() override {
Peter Boström74f6e9e2016-04-04 17:56:10 +02001469 RTC_DCHECK(observer_);
Peter Boström5811a392015-12-10 13:02:50 +01001470 EXPECT_TRUE(observer_->Wait());
sprang867fb522015-08-03 04:38:41 -07001471 }
1472
1473 void UpdateSendConfig(
1474 size_t stream_index,
1475 VideoSendStream::Config* send_config,
1476 VideoEncoderConfig* encoder_config,
1477 test::FrameGeneratorCapturer** frame_generator) override {
1478 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001479 send_config->rtp.extensions.push_back(RtpExtension(
1480 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sprang867fb522015-08-03 04:38:41 -07001481
1482 // Force some padding to be sent.
1483 const int kPaddingBitrateBps = 50000;
1484 int total_target_bitrate = 0;
1485 for (const VideoStream& stream : encoder_config->streams)
1486 total_target_bitrate += stream.target_bitrate_bps;
1487 encoder_config->min_transmit_bitrate_bps =
1488 total_target_bitrate + kPaddingBitrateBps;
1489
1490 // Configure RTX for redundant payload padding.
1491 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang861c55e2015-10-16 10:01:21 -07001492 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[stream_index]);
sprang867fb522015-08-03 04:38:41 -07001493 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
sprang861c55e2015-10-16 10:01:21 -07001494 rtx_to_media_ssrcs_[kSendRtxSsrcs[stream_index]] =
1495 send_config->rtp.ssrcs[0];
1496
1497 if (stream_index == 0)
1498 first_media_ssrc_ = send_config->rtp.ssrcs[0];
sprang867fb522015-08-03 04:38:41 -07001499 }
1500
1501 void UpdateReceiveConfig(
1502 size_t stream_index,
1503 VideoReceiveStream::Config* receive_config) override {
sprang861c55e2015-10-16 10:01:21 -07001504 receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang867fb522015-08-03 04:38:41 -07001505 receive_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001506 receive_config->rtp.extensions.push_back(RtpExtension(
1507 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sprang867fb522015-08-03 04:38:41 -07001508 }
1509
stefanf116bd02015-10-27 08:29:42 -07001510 test::DirectTransport* CreateSendTransport(Call* sender_call) override {
1511 observer_ = new RtpExtensionHeaderObserver(sender_call, first_media_ssrc_,
sprang861c55e2015-10-16 10:01:21 -07001512 rtx_to_media_ssrcs_);
sprang867fb522015-08-03 04:38:41 -07001513 return observer_;
1514 }
1515
1516 private:
sprang861c55e2015-10-16 10:01:21 -07001517 uint32_t first_media_ssrc_;
1518 std::map<uint32_t, uint32_t> rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001519 RtpExtensionHeaderObserver* observer_;
1520 } tester;
1521
1522 tester.RunTest();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001523}
1524
Stefan Holmer04cb7632016-01-14 20:34:30 +01001525class TransportFeedbackTester : public test::EndToEndTest {
1526 public:
1527 explicit TransportFeedbackTester(bool feedback_enabled,
1528 size_t num_video_streams,
1529 size_t num_audio_streams)
1530 : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
1531 feedback_enabled_(feedback_enabled),
1532 num_video_streams_(num_video_streams),
sprangcd349d92016-07-13 09:11:28 -07001533 num_audio_streams_(num_audio_streams),
1534 receiver_call_(nullptr) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001535 // Only one stream of each supported for now.
1536 EXPECT_LE(num_video_streams, 1u);
1537 EXPECT_LE(num_audio_streams, 1u);
1538 }
1539
1540 protected:
1541 Action OnSendRtcp(const uint8_t* data, size_t length) override {
1542 EXPECT_FALSE(HasTransportFeedback(data, length));
1543 return SEND_PACKET;
1544 }
1545
1546 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
1547 if (HasTransportFeedback(data, length))
1548 observation_complete_.Set();
1549 return SEND_PACKET;
1550 }
1551
1552 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
1553 RTCPUtility::RTCPParserV2 parser(data, length, true);
1554 EXPECT_TRUE(parser.IsValid());
1555
1556 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1557 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1558 if (packet_type == RTCPUtility::RTCPPacketTypes::kTransportFeedback)
1559 return true;
1560 packet_type = parser.Iterate();
1561 }
1562
1563 return false;
1564 }
1565
1566 void PerformTest() override {
1567 const int64_t kDisabledFeedbackTimeoutMs = 5000;
1568 EXPECT_EQ(feedback_enabled_,
1569 observation_complete_.Wait(feedback_enabled_
1570 ? test::CallTest::kDefaultTimeoutMs
1571 : kDisabledFeedbackTimeoutMs));
1572 }
1573
1574 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1575 receiver_call_ = receiver_call;
1576 }
1577
1578 size_t GetNumVideoStreams() const override { return num_video_streams_; }
1579 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
1580
1581 void ModifyVideoConfigs(
1582 VideoSendStream::Config* send_config,
1583 std::vector<VideoReceiveStream::Config>* receive_configs,
1584 VideoEncoderConfig* encoder_config) override {
1585 send_config->rtp.extensions.clear();
1586 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001587 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001588 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1589 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
1590 }
1591
1592 void ModifyAudioConfigs(
1593 AudioSendStream::Config* send_config,
1594 std::vector<AudioReceiveStream::Config>* receive_configs) override {
1595 send_config->rtp.extensions.clear();
1596 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001597 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001598 (*receive_configs)[0].rtp.extensions.clear();
1599 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1600 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001601 }
1602
1603 private:
Erik Språng6b8d3552015-09-24 15:06:57 +02001604 static const int kExtensionId = 5;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001605 const bool feedback_enabled_;
1606 const size_t num_video_streams_;
1607 const size_t num_audio_streams_;
1608 Call* receiver_call_;
1609};
Erik Språng6b8d3552015-09-24 15:06:57 +02001610
Stefan Holmer04cb7632016-01-14 20:34:30 +01001611TEST_F(EndToEndTest, VideoReceivesTransportFeedback) {
1612 TransportFeedbackTester test(true, 1, 0);
1613 RunBaseTest(&test);
Erik Språng6b8d3552015-09-24 15:06:57 +02001614}
stefan43edf0f2015-11-20 18:05:48 -08001615
Stefan Holmer04cb7632016-01-14 20:34:30 +01001616TEST_F(EndToEndTest, VideoTransportFeedbackNotConfigured) {
1617 TransportFeedbackTester test(false, 1, 0);
1618 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001619}
1620
Stefan Holmer04cb7632016-01-14 20:34:30 +01001621TEST_F(EndToEndTest, AudioReceivesTransportFeedback) {
1622 TransportFeedbackTester test(true, 0, 1);
1623 RunBaseTest(&test);
1624}
1625
1626TEST_F(EndToEndTest, AudioTransportFeedbackNotConfigured) {
1627 TransportFeedbackTester test(false, 0, 1);
1628 RunBaseTest(&test);
1629}
1630
1631TEST_F(EndToEndTest, AudioVideoReceivesTransportFeedback) {
1632 TransportFeedbackTester test(true, 1, 1);
1633 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001634}
1635
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001636TEST_F(EndToEndTest, ObserversEncodedFrames) {
1637 class EncodedFrameTestObserver : public EncodedFrameObserver {
1638 public:
1639 EncodedFrameTestObserver()
Peter Boström5811a392015-12-10 13:02:50 +01001640 : length_(0), frame_type_(kEmptyFrame), called_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001641 virtual ~EncodedFrameTestObserver() {}
1642
1643 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
1644 frame_type_ = encoded_frame.frame_type_;
1645 length_ = encoded_frame.length_;
1646 buffer_.reset(new uint8_t[length_]);
1647 memcpy(buffer_.get(), encoded_frame.data_, length_);
Peter Boström5811a392015-12-10 13:02:50 +01001648 called_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001649 }
1650
Peter Boström5811a392015-12-10 13:02:50 +01001651 bool Wait() { return called_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001652
1653 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
1654 ASSERT_EQ(length_, observer.length_)
1655 << "Observed frames are of different lengths.";
1656 EXPECT_EQ(frame_type_, observer.frame_type_)
1657 << "Observed frames have different frame types.";
1658 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
1659 << "Observed encoded frames have different content.";
1660 }
1661
1662 private:
kwiberg27f982b2016-03-01 11:52:33 -08001663 std::unique_ptr<uint8_t[]> buffer_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001664 size_t length_;
1665 FrameType frame_type_;
Peter Boström5811a392015-12-10 13:02:50 +01001666 rtc::Event called_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001667 };
1668
1669 EncodedFrameTestObserver post_encode_observer;
1670 EncodedFrameTestObserver pre_decode_observer;
1671
solenberg4fbae2b2015-08-28 04:07:10 -07001672 CreateCalls(Call::Config(), Call::Config());
1673
stefanf116bd02015-10-27 08:29:42 -07001674 test::DirectTransport sender_transport(sender_call_.get());
1675 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001676 sender_transport.SetReceiver(receiver_call_->Receiver());
1677 receiver_transport.SetReceiver(sender_call_->Receiver());
1678
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001679 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001680 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -08001681 video_send_config_.post_encode_callback = &post_encode_observer;
1682 video_receive_configs_[0].pre_decode_callback = &pre_decode_observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001683
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001684 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001685 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001686
kwiberg27f982b2016-03-01 11:52:33 -08001687 std::unique_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +00001688 test::FrameGenerator::CreateChromaGenerator(
stefanff483612015-12-21 03:14:00 -08001689 video_encoder_config_.streams[0].width,
1690 video_encoder_config_.streams[0].height));
1691 video_send_stream_->Input()->IncomingCapturedFrame(
1692 *frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001693
Peter Boström5811a392015-12-10 13:02:50 +01001694 EXPECT_TRUE(post_encode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001695 << "Timed out while waiting for send-side encoded-frame callback.";
1696
Peter Boström5811a392015-12-10 13:02:50 +01001697 EXPECT_TRUE(pre_decode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001698 << "Timed out while waiting for pre-decode encoded-frame callback.";
1699
1700 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
1701
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001702 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001703
1704 sender_transport.StopSending();
1705 receiver_transport.StopSending();
1706
1707 DestroyStreams();
1708}
1709
1710TEST_F(EndToEndTest, ReceiveStreamSendsRemb) {
1711 class RembObserver : public test::EndToEndTest {
1712 public:
1713 RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
1714
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001715 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001716 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1717 EXPECT_TRUE(parser.IsValid());
1718
1719 bool received_psfb = false;
1720 bool received_remb = false;
1721 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02001722 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1723 if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbRemb) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001724 const RTCPUtility::RTCPPacket& packet = parser.Packet();
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001725 EXPECT_EQ(packet.PSFBAPP.SenderSSRC, kReceiverLocalVideoSsrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001726 received_psfb = true;
Erik Språng242e22b2015-05-11 10:17:43 +02001727 } else if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbRembItem) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001728 const RTCPUtility::RTCPPacket& packet = parser.Packet();
1729 EXPECT_GT(packet.REMBItem.BitRate, 0u);
1730 EXPECT_EQ(packet.REMBItem.NumberOfSSRCs, 1u);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001731 EXPECT_EQ(packet.REMBItem.SSRCs[0], kVideoSendSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001732 received_remb = true;
1733 }
1734 packet_type = parser.Iterate();
1735 }
1736 if (received_psfb && received_remb)
Peter Boström5811a392015-12-10 13:02:50 +01001737 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001738 return SEND_PACKET;
1739 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001740 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001741 EXPECT_TRUE(Wait()) << "Timed out while waiting for a "
1742 "receiver RTCP REMB packet to be "
1743 "sent.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001744 }
1745 } test;
1746
stefane74eef12016-01-08 06:47:13 -08001747 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001748}
1749
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001750TEST_F(EndToEndTest, VerifyBandwidthStats) {
stefanf116bd02015-10-27 08:29:42 -07001751 class RtcpObserver : public test::EndToEndTest {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001752 public:
1753 RtcpObserver()
1754 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001755 sender_call_(nullptr),
1756 receiver_call_(nullptr),
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001757 has_seen_pacer_delay_(false) {}
1758
stefanf116bd02015-10-27 08:29:42 -07001759 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001760 Call::Stats sender_stats = sender_call_->GetStats();
1761 Call::Stats receiver_stats = receiver_call_->GetStats();
1762 if (!has_seen_pacer_delay_)
1763 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
1764 if (sender_stats.send_bandwidth_bps > 0 &&
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001765 receiver_stats.recv_bandwidth_bps > 0 && has_seen_pacer_delay_) {
Peter Boström5811a392015-12-10 13:02:50 +01001766 observation_complete_.Set();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001767 }
stefanf116bd02015-10-27 08:29:42 -07001768 return SEND_PACKET;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001769 }
1770
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001771 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001772 sender_call_ = sender_call;
1773 receiver_call_ = receiver_call;
1774 }
1775
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001776 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001777 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
1778 "non-zero bandwidth stats.";
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001779 }
1780
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001781 private:
1782 Call* sender_call_;
1783 Call* receiver_call_;
1784 bool has_seen_pacer_delay_;
1785 } test;
1786
stefane74eef12016-01-08 06:47:13 -08001787 RunBaseTest(&test);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001788}
1789
stefan32f81542016-01-20 07:13:58 -08001790
1791// Verifies that it's possible to limit the send BWE by sending a REMB.
1792// This is verified by allowing the send BWE to ramp-up to >1000 kbps,
1793// then have the test generate a REMB of 500 kbps and verify that the send BWE
1794// is reduced to exactly 500 kbps. Then a REMB of 1000 kbps is generated and the
1795// test verifies that the send BWE ramps back up to exactly 1000 kbps.
1796TEST_F(EndToEndTest, RembWithSendSideBwe) {
1797 class BweObserver : public test::EndToEndTest {
1798 public:
1799 BweObserver()
1800 : EndToEndTest(kDefaultTimeoutMs),
1801 sender_call_(nullptr),
1802 clock_(Clock::GetRealTimeClock()),
1803 sender_ssrc_(0),
1804 remb_bitrate_bps_(1000000),
1805 receive_transport_(nullptr),
1806 event_(false, false),
1807 poller_thread_(&BitrateStatsPollingThread,
1808 this,
1809 "BitrateStatsPollingThread"),
1810 state_(kWaitForFirstRampUp) {}
1811
1812 ~BweObserver() {}
1813
nisseef8b61e2016-04-29 06:09:15 -07001814 test::PacketTransport* CreateReceiveTransport() override {
stefan32f81542016-01-20 07:13:58 -08001815 receive_transport_ = new test::PacketTransport(
1816 nullptr, this, test::PacketTransport::kReceiver,
1817 FakeNetworkPipe::Config());
1818 return receive_transport_;
1819 }
1820
1821 Call::Config GetSenderCallConfig() override {
1822 Call::Config config;
1823 // Set a high start bitrate to reduce the test completion time.
1824 config.bitrate_config.start_bitrate_bps = remb_bitrate_bps_;
1825 return config;
1826 }
1827
1828 void ModifyVideoConfigs(
1829 VideoSendStream::Config* send_config,
1830 std::vector<VideoReceiveStream::Config>* receive_configs,
1831 VideoEncoderConfig* encoder_config) override {
1832 ASSERT_EQ(1u, send_config->rtp.ssrcs.size());
1833 send_config->rtp.extensions.clear();
1834 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001835 RtpExtension(RtpExtension::kTransportSequenceNumberUri,
stefan32f81542016-01-20 07:13:58 -08001836 test::kTransportSequenceNumberExtensionId));
1837 sender_ssrc_ = send_config->rtp.ssrcs[0];
1838
1839 encoder_config->streams[0].max_bitrate_bps =
1840 encoder_config->streams[0].target_bitrate_bps = 2000000;
1841
1842 ASSERT_EQ(1u, receive_configs->size());
1843 (*receive_configs)[0].rtp.remb = false;
1844 (*receive_configs)[0].rtp.transport_cc = true;
1845 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1846 RtpRtcp::Configuration config;
1847 config.receiver_only = true;
1848 config.clock = clock_;
1849 config.outgoing_transport = receive_transport_;
1850 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
1851 rtp_rtcp_->SetRemoteSSRC((*receive_configs)[0].rtp.remote_ssrc);
1852 rtp_rtcp_->SetSSRC((*receive_configs)[0].rtp.local_ssrc);
1853 rtp_rtcp_->SetREMBStatus(true);
1854 rtp_rtcp_->SetSendingStatus(true);
1855 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
1856 }
1857
1858 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1859 sender_call_ = sender_call;
1860 }
1861
1862 static bool BitrateStatsPollingThread(void* obj) {
1863 return static_cast<BweObserver*>(obj)->PollStats();
1864 }
1865
1866 bool PollStats() {
1867 if (sender_call_) {
1868 Call::Stats stats = sender_call_->GetStats();
1869 switch (state_) {
1870 case kWaitForFirstRampUp:
1871 if (stats.send_bandwidth_bps >= remb_bitrate_bps_) {
1872 state_ = kWaitForRemb;
1873 remb_bitrate_bps_ /= 2;
1874 rtp_rtcp_->SetREMBData(
1875 remb_bitrate_bps_,
1876 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
1877 rtp_rtcp_->SendRTCP(kRtcpRr);
1878 }
1879 break;
1880
1881 case kWaitForRemb:
1882 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
1883 state_ = kWaitForSecondRampUp;
1884 remb_bitrate_bps_ *= 2;
1885 rtp_rtcp_->SetREMBData(
1886 remb_bitrate_bps_,
1887 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
1888 rtp_rtcp_->SendRTCP(kRtcpRr);
1889 }
1890 break;
1891
1892 case kWaitForSecondRampUp:
1893 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
1894 observation_complete_.Set();
1895 }
1896 break;
1897 }
1898 }
1899
1900 return !event_.Wait(1000);
1901 }
1902
1903 void PerformTest() override {
1904 poller_thread_.Start();
1905 EXPECT_TRUE(Wait())
1906 << "Timed out while waiting for bitrate to change according to REMB.";
1907 poller_thread_.Stop();
1908 }
1909
1910 private:
1911 enum TestState { kWaitForFirstRampUp, kWaitForRemb, kWaitForSecondRampUp };
1912
1913 Call* sender_call_;
1914 Clock* const clock_;
1915 uint32_t sender_ssrc_;
1916 int remb_bitrate_bps_;
kwiberg27f982b2016-03-01 11:52:33 -08001917 std::unique_ptr<RtpRtcp> rtp_rtcp_;
stefan32f81542016-01-20 07:13:58 -08001918 test::PacketTransport* receive_transport_;
1919 rtc::Event event_;
1920 rtc::PlatformThread poller_thread_;
1921 TestState state_;
1922 } test;
1923
1924 RunBaseTest(&test);
1925}
1926
Åsa Persson352b2d72015-04-15 18:00:40 +02001927TEST_F(EndToEndTest, VerifyNackStats) {
1928 static const int kPacketNumberToDrop = 200;
1929 class NackObserver : public test::EndToEndTest {
1930 public:
1931 NackObserver()
1932 : EndToEndTest(kLongTimeoutMs),
1933 sent_rtp_packets_(0),
1934 dropped_rtp_packet_(0),
1935 dropped_rtp_packet_requested_(false),
1936 send_stream_(nullptr),
1937 start_runtime_ms_(-1) {}
1938
1939 private:
1940 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08001941 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02001942 if (++sent_rtp_packets_ == kPacketNumberToDrop) {
kwiberg27f982b2016-03-01 11:52:33 -08001943 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
Åsa Persson352b2d72015-04-15 18:00:40 +02001944 RTPHeader header;
1945 EXPECT_TRUE(parser->Parse(packet, length, &header));
1946 dropped_rtp_packet_ = header.sequenceNumber;
1947 return DROP_PACKET;
1948 }
1949 VerifyStats();
1950 return SEND_PACKET;
1951 }
1952
1953 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08001954 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02001955 test::RtcpPacketParser rtcp_parser;
1956 rtcp_parser.Parse(packet, length);
1957 std::vector<uint16_t> nacks = rtcp_parser.nack_item()->last_nack_list();
1958 if (!nacks.empty() && std::find(
1959 nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) {
1960 dropped_rtp_packet_requested_ = true;
1961 }
1962 return SEND_PACKET;
1963 }
1964
stefan608213e2015-11-01 14:56:10 -08001965 void VerifyStats() EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
Åsa Persson352b2d72015-04-15 18:00:40 +02001966 if (!dropped_rtp_packet_requested_)
1967 return;
1968 int send_stream_nack_packets = 0;
1969 int receive_stream_nack_packets = 0;
1970 VideoSendStream::Stats stats = send_stream_->GetStats();
1971 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
1972 stats.substreams.begin(); it != stats.substreams.end(); ++it) {
1973 const VideoSendStream::StreamStats& stream_stats = it->second;
1974 send_stream_nack_packets +=
1975 stream_stats.rtcp_packet_type_counts.nack_packets;
1976 }
1977 for (size_t i = 0; i < receive_streams_.size(); ++i) {
1978 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
1979 receive_stream_nack_packets +=
1980 stats.rtcp_packet_type_counts.nack_packets;
1981 }
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001982 if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) {
Åsa Persson352b2d72015-04-15 18:00:40 +02001983 // NACK packet sent on receive stream and received on sent stream.
1984 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01001985 observation_complete_.Set();
Åsa Persson352b2d72015-04-15 18:00:40 +02001986 }
1987 }
1988
1989 bool MinMetricRunTimePassed() {
1990 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
1991 if (start_runtime_ms_ == -1) {
1992 start_runtime_ms_ = now;
1993 return false;
1994 }
1995 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
1996 return elapsed_sec > metrics::kMinRunTimeInSeconds;
1997 }
1998
stefanff483612015-12-21 03:14:00 -08001999 void ModifyVideoConfigs(
2000 VideoSendStream::Config* send_config,
2001 std::vector<VideoReceiveStream::Config>* receive_configs,
2002 VideoEncoderConfig* encoder_config) override {
Åsa Persson352b2d72015-04-15 18:00:40 +02002003 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2004 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2005 }
2006
stefanff483612015-12-21 03:14:00 -08002007 void OnVideoStreamsCreated(
Åsa Persson352b2d72015-04-15 18:00:40 +02002008 VideoSendStream* send_stream,
2009 const std::vector<VideoReceiveStream*>& receive_streams) override {
2010 send_stream_ = send_stream;
2011 receive_streams_ = receive_streams;
2012 }
2013
2014 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002015 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson352b2d72015-04-15 18:00:40 +02002016 }
2017
stefan608213e2015-11-01 14:56:10 -08002018 rtc::CriticalSection crit_;
Åsa Persson352b2d72015-04-15 18:00:40 +02002019 uint64_t sent_rtp_packets_;
stefan608213e2015-11-01 14:56:10 -08002020 uint16_t dropped_rtp_packet_ GUARDED_BY(&crit_);
2021 bool dropped_rtp_packet_requested_ GUARDED_BY(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002022 std::vector<VideoReceiveStream*> receive_streams_;
2023 VideoSendStream* send_stream_;
2024 int64_t start_runtime_ms_;
2025 } test;
2026
asapersson01d70a32016-05-20 06:29:46 -07002027 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002028 RunBaseTest(&test);
Åsa Persson352b2d72015-04-15 18:00:40 +02002029
asapersson01d70a32016-05-20 06:29:46 -07002030 EXPECT_EQ(
2031 1, metrics::NumSamples("WebRTC.Video.UniqueNackRequestsSentInPercent"));
2032 EXPECT_EQ(1, metrics::NumSamples(
2033 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
2034 EXPECT_GT(metrics::MinSample("WebRTC.Video.NackPacketsSentPerMinute"), 0);
Åsa Persson352b2d72015-04-15 18:00:40 +02002035}
2036
sprangb4a1ae52015-12-03 08:10:08 -08002037void EndToEndTest::VerifyHistogramStats(bool use_rtx,
2038 bool use_red,
2039 bool screenshare) {
tommi2e82f382016-06-21 00:26:43 -07002040 class StatsObserver : public test::EndToEndTest,
2041 public rtc::VideoSinkInterface<VideoFrame> {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002042 public:
sprangb4a1ae52015-12-03 08:10:08 -08002043 StatsObserver(bool use_rtx, bool use_red, bool screenshare)
Åsa Persson3c391cb2015-04-27 10:09:49 +02002044 : EndToEndTest(kLongTimeoutMs),
2045 use_rtx_(use_rtx),
2046 use_red_(use_red),
sprangb4a1ae52015-12-03 08:10:08 -08002047 screenshare_(screenshare),
Peter Boström39593972016-02-15 11:27:15 +01002048 // This test uses NACK, so to send FEC we can't use a fake encoder.
2049 vp8_encoder_(
2050 use_red ? VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)
2051 : nullptr),
Åsa Persson3c391cb2015-04-27 10:09:49 +02002052 sender_call_(nullptr),
2053 receiver_call_(nullptr),
2054 start_runtime_ms_(-1) {}
2055
2056 private:
tommi2e82f382016-06-21 00:26:43 -07002057 void OnFrame(const VideoFrame& video_frame) override {}
2058
Åsa Persson3c391cb2015-04-27 10:09:49 +02002059 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2060 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002061 observation_complete_.Set();
Åsa Persson3c391cb2015-04-27 10:09:49 +02002062
stefanf116bd02015-10-27 08:29:42 -07002063 return SEND_PACKET;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002064 }
2065
2066 bool MinMetricRunTimePassed() {
2067 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2068 if (start_runtime_ms_ == -1) {
2069 start_runtime_ms_ = now;
2070 return false;
2071 }
2072 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2073 return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
2074 }
2075
stefanff483612015-12-21 03:14:00 -08002076 void ModifyVideoConfigs(
2077 VideoSendStream::Config* send_config,
2078 std::vector<VideoReceiveStream::Config>* receive_configs,
2079 VideoEncoderConfig* encoder_config) override {
stefana23fc622016-07-28 07:56:38 -07002080 static const int kExtensionId = 8;
2081 send_config->rtp.extensions.push_back(RtpExtension(
2082 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
2083 (*receive_configs)[0].rtp.extensions.push_back(RtpExtension(
2084 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002085 // NACK
2086 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2087 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
tommi2e82f382016-06-21 00:26:43 -07002088 (*receive_configs)[0].renderer = this;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002089 // FEC
2090 if (use_red_) {
2091 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
2092 send_config->rtp.fec.red_payload_type = kRedPayloadType;
Peter Boström39593972016-02-15 11:27:15 +01002093 send_config->encoder_settings.encoder = vp8_encoder_.get();
2094 send_config->encoder_settings.payload_name = "VP8";
2095 (*receive_configs)[0].decoders[0].payload_name = "VP8";
Åsa Persson3c391cb2015-04-27 10:09:49 +02002096 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
2097 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
2098 }
2099 // RTX
2100 if (use_rtx_) {
2101 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
2102 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002103 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002104 kSendRtxSsrcs[0];
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002105 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002106 kSendRtxPayloadType;
2107 }
sprangb4a1ae52015-12-03 08:10:08 -08002108 encoder_config->content_type =
2109 screenshare_ ? VideoEncoderConfig::ContentType::kScreen
2110 : VideoEncoderConfig::ContentType::kRealtimeVideo;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002111 }
2112
2113 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2114 sender_call_ = sender_call;
2115 receiver_call_ = receiver_call;
2116 }
2117
Åsa Persson3c391cb2015-04-27 10:09:49 +02002118 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002119 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson3c391cb2015-04-27 10:09:49 +02002120 }
2121
sprangb4a1ae52015-12-03 08:10:08 -08002122 const bool use_rtx_;
2123 const bool use_red_;
2124 const bool screenshare_;
kwiberg27f982b2016-03-01 11:52:33 -08002125 const std::unique_ptr<VideoEncoder> vp8_encoder_;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002126 Call* sender_call_;
2127 Call* receiver_call_;
2128 int64_t start_runtime_ms_;
sprangb4a1ae52015-12-03 08:10:08 -08002129 } test(use_rtx, use_red, screenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002130
asapersson01d70a32016-05-20 06:29:46 -07002131 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002132 RunBaseTest(&test);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002133
stefan91d92602015-11-11 10:13:02 -08002134 // Delete the call for Call stats to be reported.
stefan18adf0a2015-11-17 06:24:56 -08002135 sender_call_.reset();
stefan91d92602015-11-11 10:13:02 -08002136 receiver_call_.reset();
2137
sprangb4a1ae52015-12-03 08:10:08 -08002138 std::string video_prefix =
2139 screenshare ? "WebRTC.Video.Screenshare." : "WebRTC.Video.";
2140
Åsa Persson3c391cb2015-04-27 10:09:49 +02002141 // Verify that stats have been updated once.
asapersson4374a092016-07-27 00:39:09 -07002142 EXPECT_EQ(2, metrics::NumSamples("WebRTC.Call.LifetimeInSeconds"));
asapersson01d70a32016-05-20 06:29:46 -07002143 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
2144 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.RtcpBitrateReceivedInBps"));
2145 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.BitrateReceivedInKbps"));
2146 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.EstimatedSendBitrateInKbps"));
2147 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.PacerBitrateInKbps"));
2148
asapersson4374a092016-07-27 00:39:09 -07002149 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
2150 EXPECT_EQ(1,
2151 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
2152
asapersson01d70a32016-05-20 06:29:46 -07002153 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
stefan91d92602015-11-11 10:13:02 -08002154 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002155 metrics::NumSamples(video_prefix + "NackPacketsReceivedPerMinute"));
2156 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
asaperssond89920b2015-07-22 06:52:00 -07002157 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002158 metrics::NumSamples(video_prefix + "FirPacketsReceivedPerMinute"));
2159 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
sprangb4a1ae52015-12-03 08:10:08 -08002160 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002161 metrics::NumSamples(video_prefix + "PliPacketsReceivedPerMinute"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002162
asapersson01d70a32016-05-20 06:29:46 -07002163 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "KeyFramesSentInPermille"));
2164 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
2165
2166 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentPacketsLostInPercent"));
2167 EXPECT_EQ(1,
2168 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
2169
2170 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputWidthInPixels"));
2171 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputHeightInPixels"));
2172 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentWidthInPixels"));
2173 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentHeightInPixels"));
2174 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
2175 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
2176
2177 EXPECT_EQ(1, metrics::NumEvents(
2178 video_prefix + "InputWidthInPixels",
2179 static_cast<int>(video_encoder_config_.streams[0].width)));
2180 EXPECT_EQ(1, metrics::NumEvents(
2181 video_prefix + "InputHeightInPixels",
2182 static_cast<int>(video_encoder_config_.streams[0].height)));
2183 EXPECT_EQ(1, metrics::NumEvents(
2184 video_prefix + "SentWidthInPixels",
2185 static_cast<int>(video_encoder_config_.streams[0].width)));
2186 EXPECT_EQ(1, metrics::NumEvents(
2187 video_prefix + "SentHeightInPixels",
2188 static_cast<int>(video_encoder_config_.streams[0].height)));
2189 EXPECT_EQ(1, metrics::NumEvents(
2190 "WebRTC.Video.ReceivedWidthInPixels",
2191 static_cast<int>(video_encoder_config_.streams[0].width)));
2192 EXPECT_EQ(1, metrics::NumEvents(
2193 "WebRTC.Video.ReceivedHeightInPixels",
2194 static_cast<int>(video_encoder_config_.streams[0].height)));
2195
2196 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputFramesPerSecond"));
2197 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentFramesPerSecond"));
2198 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
2199 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
2200
2201 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
2202 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
2203 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
2204 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
2205
2206 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
2207
2208 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EncodeTimeInMs"));
2209 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
2210
2211 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "BitrateSentInKbps"));
2212 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateReceivedInKbps"));
2213 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "MediaBitrateSentInKbps"));
2214 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateReceivedInKbps"));
2215 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PaddingBitrateSentInKbps"));
2216 EXPECT_EQ(1,
2217 metrics::NumSamples("WebRTC.Video.PaddingBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002218 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002219 1, metrics::NumSamples(video_prefix + "RetransmittedBitrateSentInKbps"));
2220 EXPECT_EQ(1, metrics::NumSamples(
2221 "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002222
asapersson01d70a32016-05-20 06:29:46 -07002223 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendDelayInMs"));
2224 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayInMs"));
2225 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayMaxInMs"));
asapersson6f14be82015-11-16 00:40:49 -08002226
Åsa Persson3c391cb2015-04-27 10:09:49 +02002227 int num_rtx_samples = use_rtx ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002228 EXPECT_EQ(num_rtx_samples,
2229 metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2230 EXPECT_EQ(num_rtx_samples,
2231 metrics::NumSamples("WebRTC.Video.RtxBitrateReceivedInKbps"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002232
2233 int num_red_samples = use_red ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002234 EXPECT_EQ(num_red_samples,
2235 metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2236 EXPECT_EQ(num_red_samples,
2237 metrics::NumSamples("WebRTC.Video.FecBitrateReceivedInKbps"));
2238 EXPECT_EQ(num_red_samples,
2239 metrics::NumSamples("WebRTC.Video.ReceivedFecPacketsInPercent"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002240}
2241
2242TEST_F(EndToEndTest, VerifyHistogramStatsWithRtx) {
2243 const bool kEnabledRtx = true;
2244 const bool kEnabledRed = false;
sprangb4a1ae52015-12-03 08:10:08 -08002245 const bool kScreenshare = false;
2246 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002247}
2248
2249TEST_F(EndToEndTest, VerifyHistogramStatsWithRed) {
2250 const bool kEnabledRtx = false;
2251 const bool kEnabledRed = true;
sprangb4a1ae52015-12-03 08:10:08 -08002252 const bool kScreenshare = false;
2253 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
2254}
2255
2256TEST_F(EndToEndTest, VerifyHistogramStatsWithScreenshare) {
2257 const bool kEnabledRtx = false;
2258 const bool kEnabledRed = false;
2259 const bool kScreenshare = true;
2260 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002261}
2262
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002263void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
2264 static const int kNumRtcpReportPacketsToObserve = 5;
2265 class RtcpXrObserver : public test::EndToEndTest {
2266 public:
2267 explicit RtcpXrObserver(bool enable_rrtr)
2268 : EndToEndTest(kDefaultTimeoutMs),
2269 enable_rrtr_(enable_rrtr),
2270 sent_rtcp_sr_(0),
2271 sent_rtcp_rr_(0),
2272 sent_rtcp_rrtr_(0),
2273 sent_rtcp_dlrr_(0) {}
2274
2275 private:
2276 // Receive stream should send RR packets (and RRTR packets if enabled).
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002277 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002278 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002279 RTCPUtility::RTCPParserV2 parser(packet, length, true);
2280 EXPECT_TRUE(parser.IsValid());
2281
2282 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02002283 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
2284 if (packet_type == RTCPUtility::RTCPPacketTypes::kRr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002285 ++sent_rtcp_rr_;
2286 } else if (packet_type ==
Erik Språng242e22b2015-05-11 10:17:43 +02002287 RTCPUtility::RTCPPacketTypes::kXrReceiverReferenceTime) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002288 ++sent_rtcp_rrtr_;
2289 }
Erik Språng242e22b2015-05-11 10:17:43 +02002290 EXPECT_NE(packet_type, RTCPUtility::RTCPPacketTypes::kSr);
2291 EXPECT_NE(packet_type,
2292 RTCPUtility::RTCPPacketTypes::kXrDlrrReportBlockItem);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002293 packet_type = parser.Iterate();
2294 }
2295 return SEND_PACKET;
2296 }
2297 // Send stream should send SR packets (and DLRR packets if enabled).
nisseef8b61e2016-04-29 06:09:15 -07002298 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002299 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002300 RTCPUtility::RTCPParserV2 parser(packet, length, true);
2301 EXPECT_TRUE(parser.IsValid());
2302
2303 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02002304 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
2305 if (packet_type == RTCPUtility::RTCPPacketTypes::kSr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002306 ++sent_rtcp_sr_;
Erik Språng242e22b2015-05-11 10:17:43 +02002307 } else if (packet_type ==
2308 RTCPUtility::RTCPPacketTypes::kXrDlrrReportBlockItem) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002309 ++sent_rtcp_dlrr_;
2310 }
Erik Språng242e22b2015-05-11 10:17:43 +02002311 EXPECT_NE(packet_type,
2312 RTCPUtility::RTCPPacketTypes::kXrReceiverReferenceTime);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002313 packet_type = parser.Iterate();
2314 }
2315 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
2316 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve) {
2317 if (enable_rrtr_) {
2318 EXPECT_GT(sent_rtcp_rrtr_, 0);
2319 EXPECT_GT(sent_rtcp_dlrr_, 0);
2320 } else {
2321 EXPECT_EQ(0, sent_rtcp_rrtr_);
2322 EXPECT_EQ(0, sent_rtcp_dlrr_);
2323 }
Peter Boström5811a392015-12-10 13:02:50 +01002324 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002325 }
2326 return SEND_PACKET;
2327 }
2328
stefanff483612015-12-21 03:14:00 -08002329 void ModifyVideoConfigs(
2330 VideoSendStream::Config* send_config,
2331 std::vector<VideoReceiveStream::Config>* receive_configs,
2332 VideoEncoderConfig* encoder_config) override {
pbosda903ea2015-10-02 02:36:56 -07002333 (*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002334 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
2335 enable_rrtr_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002336 }
2337
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002338 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002339 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002340 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
2341 }
2342
stefan608213e2015-11-01 14:56:10 -08002343 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002344 bool enable_rrtr_;
2345 int sent_rtcp_sr_;
stefan608213e2015-11-01 14:56:10 -08002346 int sent_rtcp_rr_ GUARDED_BY(&crit_);
2347 int sent_rtcp_rrtr_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002348 int sent_rtcp_dlrr_;
2349 } test(enable_rrtr);
2350
stefane74eef12016-01-08 06:47:13 -08002351 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002352}
2353
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002354void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
2355 bool send_single_ssrc_first) {
2356 class SendsSetSsrcs : public test::EndToEndTest {
2357 public:
2358 SendsSetSsrcs(const uint32_t* ssrcs,
2359 size_t num_ssrcs,
2360 bool send_single_ssrc_first)
2361 : EndToEndTest(kDefaultTimeoutMs),
2362 num_ssrcs_(num_ssrcs),
2363 send_single_ssrc_first_(send_single_ssrc_first),
2364 ssrcs_to_observe_(num_ssrcs),
sprang867fb522015-08-03 04:38:41 -07002365 expect_single_ssrc_(send_single_ssrc_first),
2366 send_stream_(nullptr) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002367 for (size_t i = 0; i < num_ssrcs; ++i)
2368 valid_ssrcs_[ssrcs[i]] = true;
2369 }
2370
2371 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002372 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002373 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002374 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002375
2376 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
2377 << "Received unknown SSRC: " << header.ssrc;
2378
2379 if (!valid_ssrcs_[header.ssrc])
Peter Boström5811a392015-12-10 13:02:50 +01002380 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002381
2382 if (!is_observed_[header.ssrc]) {
2383 is_observed_[header.ssrc] = true;
2384 --ssrcs_to_observe_;
2385 if (expect_single_ssrc_) {
2386 expect_single_ssrc_ = false;
Peter Boström5811a392015-12-10 13:02:50 +01002387 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002388 }
2389 }
2390
2391 if (ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002392 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002393
2394 return SEND_PACKET;
2395 }
2396
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002397 size_t GetNumVideoStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002398
stefanff483612015-12-21 03:14:00 -08002399 void ModifyVideoConfigs(
2400 VideoSendStream::Config* send_config,
2401 std::vector<VideoReceiveStream::Config>* receive_configs,
2402 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002403 if (num_ssrcs_ > 1) {
2404 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002405 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2406 encoder_config->streams[i].min_bitrate_bps = 10000;
2407 encoder_config->streams[i].target_bitrate_bps = 15000;
2408 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002409 }
2410 }
2411
stefanff483612015-12-21 03:14:00 -08002412 video_encoder_config_all_streams_ = *encoder_config;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002413 if (send_single_ssrc_first_)
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002414 encoder_config->streams.resize(1);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002415 }
2416
stefanff483612015-12-21 03:14:00 -08002417 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002418 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002419 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002420 send_stream_ = send_stream;
2421 }
2422
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002423 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002424 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2425 << (send_single_ssrc_first_ ? "first SSRC."
2426 : "SSRCs.");
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002427
2428 if (send_single_ssrc_first_) {
2429 // Set full simulcast and continue with the rest of the SSRCs.
stefanff483612015-12-21 03:14:00 -08002430 send_stream_->ReconfigureVideoEncoder(
2431 video_encoder_config_all_streams_);
Peter Boström5811a392015-12-10 13:02:50 +01002432 EXPECT_TRUE(Wait()) << "Timed out while waiting on additional SSRCs.";
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002433 }
2434 }
2435
2436 private:
2437 std::map<uint32_t, bool> valid_ssrcs_;
2438 std::map<uint32_t, bool> is_observed_;
2439
2440 const size_t num_ssrcs_;
2441 const bool send_single_ssrc_first_;
2442
2443 size_t ssrcs_to_observe_;
2444 bool expect_single_ssrc_;
2445
2446 VideoSendStream* send_stream_;
stefanff483612015-12-21 03:14:00 -08002447 VideoEncoderConfig video_encoder_config_all_streams_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002448 } test(kVideoSendSsrcs, num_ssrcs, send_single_ssrc_first);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002449
stefane74eef12016-01-08 06:47:13 -08002450 RunBaseTest(&test);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002451}
2452
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002453TEST_F(EndToEndTest, ReportsSetEncoderRates) {
2454 class EncoderRateStatsTest : public test::EndToEndTest,
2455 public test::FakeEncoder {
2456 public:
2457 EncoderRateStatsTest()
2458 : EndToEndTest(kDefaultTimeoutMs),
sprang867fb522015-08-03 04:38:41 -07002459 FakeEncoder(Clock::GetRealTimeClock()),
2460 send_stream_(nullptr),
2461 bitrate_kbps_(0) {}
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002462
stefanff483612015-12-21 03:14:00 -08002463 void OnVideoStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002464 VideoSendStream* send_stream,
2465 const std::vector<VideoReceiveStream*>& receive_streams) override {
2466 send_stream_ = send_stream;
2467 }
2468
stefanff483612015-12-21 03:14:00 -08002469 void ModifyVideoConfigs(
2470 VideoSendStream::Config* send_config,
2471 std::vector<VideoReceiveStream::Config>* receive_configs,
2472 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002473 send_config->encoder_settings.encoder = this;
perkj57c21f92016-06-17 07:27:16 -07002474 RTC_DCHECK_EQ(1u, encoder_config->streams.size());
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002475 }
2476
2477 int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override {
2478 // Make sure not to trigger on any default zero bitrates.
2479 if (new_target_bitrate == 0)
2480 return 0;
Peter Boströmf2f82832015-05-01 13:00:41 +02002481 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002482 bitrate_kbps_ = new_target_bitrate;
Peter Boström5811a392015-12-10 13:02:50 +01002483 observation_complete_.Set();
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002484 return 0;
2485 }
2486
2487 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002488 ASSERT_TRUE(Wait())
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002489 << "Timed out while waiting for encoder SetRates() call.";
perkjf5b2e512016-07-05 08:34:04 -07002490 WaitForEncoderTargetBitrateMatchStats();
2491 send_stream_->Stop();
2492 WaitForStatsReportZeroTargetBitrate();
2493 send_stream_->Start();
2494 WaitForEncoderTargetBitrateMatchStats();
2495 }
2496
2497 void WaitForEncoderTargetBitrateMatchStats() {
Peter Boström5811a392015-12-10 13:02:50 +01002498 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002499 VideoSendStream::Stats stats = send_stream_->GetStats();
2500 {
Peter Boströmf2f82832015-05-01 13:00:41 +02002501 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002502 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
2503 static_cast<int>(bitrate_kbps_)) {
2504 return;
2505 }
2506 }
2507 SleepMs(1);
2508 }
2509 FAIL()
2510 << "Timed out waiting for stats reporting the currently set bitrate.";
2511 }
2512
perkjf5b2e512016-07-05 08:34:04 -07002513 void WaitForStatsReportZeroTargetBitrate() {
2514 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
2515 if (send_stream_->GetStats().target_media_bitrate_bps == 0) {
2516 return;
2517 }
2518 SleepMs(1);
2519 }
2520 FAIL() << "Timed out waiting for stats reporting zero bitrate.";
2521 }
2522
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002523 private:
stefanf116bd02015-10-27 08:29:42 -07002524 rtc::CriticalSection crit_;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002525 VideoSendStream* send_stream_;
2526 uint32_t bitrate_kbps_ GUARDED_BY(crit_);
2527 } test;
2528
stefane74eef12016-01-08 06:47:13 -08002529 RunBaseTest(&test);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002530}
2531
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002532TEST_F(EndToEndTest, GetStats) {
2533 static const int kStartBitrateBps = 3000000;
Peter Boströmdef398832015-05-27 17:59:11 +02002534 static const int kExpectedRenderDelayMs = 20;
tommi2e82f382016-06-21 00:26:43 -07002535
2536 class ReceiveStreamRenderer : public rtc::VideoSinkInterface<VideoFrame> {
2537 public:
2538 ReceiveStreamRenderer() {}
2539
2540 private:
2541 void OnFrame(const VideoFrame& video_frame) override {}
2542 };
2543
nissed30a1112016-04-18 05:15:22 -07002544 class StatsObserver : public test::EndToEndTest,
2545 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002546 public:
stefanf116bd02015-10-27 08:29:42 -07002547 StatsObserver()
2548 : EndToEndTest(kLongTimeoutMs),
Peter Boströmc6e16e32016-02-05 14:15:53 +01002549 encoder_(Clock::GetRealTimeClock(), 10),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002550 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002551 expected_send_ssrcs_(),
Peter Boström5811a392015-12-10 13:02:50 +01002552 check_stats_event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002553
2554 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002555 Action OnSendRtp(const uint8_t* packet, size_t length) override {
sprangcd349d92016-07-13 09:11:28 -07002556 // Drop every 25th packet => 4% loss.
2557 static const int kPacketLossFrac = 25;
2558 RTPHeader header;
2559 RtpUtility::RtpHeaderParser parser(packet, length);
2560 if (parser.Parse(&header) &&
2561 expected_send_ssrcs_.find(header.ssrc) !=
2562 expected_send_ssrcs_.end() &&
2563 header.sequenceNumber % kPacketLossFrac == 0) {
2564 return DROP_PACKET;
2565 }
Peter Boström5811a392015-12-10 13:02:50 +01002566 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002567 return SEND_PACKET;
2568 }
2569
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002570 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002571 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002572 return SEND_PACKET;
2573 }
2574
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002575 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002576 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002577 return SEND_PACKET;
2578 }
2579
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002580 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002581 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002582 return SEND_PACKET;
2583 }
2584
nissed30a1112016-04-18 05:15:22 -07002585 void OnFrame(const VideoFrame& video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002586 // Ensure that we have at least 5ms send side delay.
nissed30a1112016-04-18 05:15:22 -07002587 SleepMs(5);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002588 }
2589
2590 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002591 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2592 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2593 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002594
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002595 // Make sure all fields have been populated.
2596 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
2597 // always filled for all receivers.
2598 receive_stats_filled_["IncomingRate"] |=
2599 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002600
Peter Boströmb7d9a972015-12-18 16:01:11 +01002601 send_stats_filled_["DecoderImplementationName"] |=
2602 stats.decoder_implementation_name ==
2603 test::FakeDecoder::kImplementationName;
Peter Boströmdef398832015-05-27 17:59:11 +02002604 receive_stats_filled_["RenderDelayAsHighAsExpected"] |=
2605 stats.render_delay_ms >= kExpectedRenderDelayMs;
2606
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002607 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002608
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002609 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002610
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002611 receive_stats_filled_["StatisticsUpdated"] |=
2612 stats.rtcp_stats.cumulative_lost != 0 ||
2613 stats.rtcp_stats.extended_max_sequence_number != 0 ||
2614 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002615
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002616 receive_stats_filled_["DataCountersUpdated"] |=
2617 stats.rtp_stats.transmitted.payload_bytes != 0 ||
2618 stats.rtp_stats.fec.packets != 0 ||
2619 stats.rtp_stats.transmitted.header_bytes != 0 ||
2620 stats.rtp_stats.transmitted.packets != 0 ||
2621 stats.rtp_stats.transmitted.padding_bytes != 0 ||
2622 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002623
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002624 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002625 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002626
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002627 receive_stats_filled_["FrameCounts"] |=
2628 stats.frame_counts.key_frames != 0 ||
2629 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002630
pbosbb36fdf2015-07-09 07:48:14 -07002631 receive_stats_filled_["CName"] |= !stats.c_name.empty();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002632
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002633 receive_stats_filled_["RtcpPacketTypeCount"] |=
2634 stats.rtcp_packet_type_counts.fir_packets != 0 ||
2635 stats.rtcp_packet_type_counts.nack_packets != 0 ||
2636 stats.rtcp_packet_type_counts.pli_packets != 0 ||
2637 stats.rtcp_packet_type_counts.nack_requests != 0 ||
2638 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbosf42376c2015-08-28 07:35:32 -07002639
2640 assert(stats.current_payload_type == -1 ||
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002641 stats.current_payload_type == kFakeVideoSendPayloadType);
pbosf42376c2015-08-28 07:35:32 -07002642 receive_stats_filled_["IncomingPayloadType"] |=
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002643 stats.current_payload_type == kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002644 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002645
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002646 return AllStatsFilled(receive_stats_filled_);
2647 }
2648
2649 bool CheckSendStats() {
Peter Boström74f6e9e2016-04-04 17:56:10 +02002650 RTC_DCHECK(send_stream_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002651 VideoSendStream::Stats stats = send_stream_->GetStats();
2652
2653 send_stats_filled_["NumStreams"] |=
2654 stats.substreams.size() == expected_send_ssrcs_.size();
2655
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002656 send_stats_filled_["CpuOveruseMetrics"] |=
Peter Boströme4499152016-02-05 11:13:28 +01002657 stats.avg_encode_time_ms != 0 && stats.encode_usage_percent != 0;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002658
Peter Boströmb7d9a972015-12-18 16:01:11 +01002659 send_stats_filled_["EncoderImplementationName"] |=
2660 stats.encoder_implementation_name ==
2661 test::FakeEncoder::kImplementationName;
2662
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002663 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002664 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002665 it != stats.substreams.end(); ++it) {
sprangcd349d92016-07-13 09:11:28 -07002666 if (expected_send_ssrcs_.find(it->first) == expected_send_ssrcs_.end())
2667 continue; // Probably RTX.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002668
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002669 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002670 stats.input_frame_rate != 0;
2671
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002672 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002673
2674 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
2675 stream_stats.rtcp_stats.cumulative_lost != 0 ||
2676 stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
2677 stream_stats.rtcp_stats.fraction_lost != 0;
2678
2679 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002680 stream_stats.rtp_stats.fec.packets != 0 ||
2681 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
2682 stream_stats.rtp_stats.retransmitted.packets != 0 ||
2683 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002684
sprangcd349d92016-07-13 09:11:28 -07002685 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Total",
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002686 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002687 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002688
sprangcd349d92016-07-13 09:11:28 -07002689 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Retransmit",
2690 it->first)] |=
2691 stream_stats.retransmit_bitrate_bps != 0;
2692
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002693 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002694 stream_stats.frame_counts.delta_frames != 0 ||
2695 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002696
2697 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
2698 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00002699
2700 send_stats_filled_[CompoundKey("Delay", it->first)] |=
2701 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002702
2703 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
2704 // report dropped packets.
2705 send_stats_filled_["RtcpPacketTypeCount"] |=
2706 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
2707 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
2708 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
2709 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
2710 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002711 }
2712
2713 return AllStatsFilled(send_stats_filled_);
2714 }
2715
2716 std::string CompoundKey(const char* name, uint32_t ssrc) {
2717 std::ostringstream oss;
2718 oss << name << "_" << ssrc;
2719 return oss.str();
2720 }
2721
2722 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
sprangcd349d92016-07-13 09:11:28 -07002723 for (const auto& stat : stats_map) {
2724 if (!stat.second)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002725 return false;
2726 }
2727 return true;
2728 }
2729
stefane74eef12016-01-08 06:47:13 -08002730 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
2731 FakeNetworkPipe::Config network_config;
2732 network_config.loss_percent = 5;
2733 return new test::PacketTransport(
2734 sender_call, this, test::PacketTransport::kSender, network_config);
2735 }
2736
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002737 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002738 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01002739 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002740 return config;
2741 }
2742
stefanff483612015-12-21 03:14:00 -08002743 void ModifyVideoConfigs(
2744 VideoSendStream::Config* send_config,
2745 std::vector<VideoReceiveStream::Config>* receive_configs,
2746 VideoEncoderConfig* encoder_config) override {
sprangcd349d92016-07-13 09:11:28 -07002747 // Set low rates to avoid waiting for rampup.
2748 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2749 encoder_config->streams[i].min_bitrate_bps = 10000;
2750 encoder_config->streams[i].target_bitrate_bps = 15000;
2751 encoder_config->streams[i].max_bitrate_bps = 20000;
2752 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002753 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002754 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002755
sprangcd349d92016-07-13 09:11:28 -07002756 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2757 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
2758
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002759 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002760 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002761 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002762 expected_receive_ssrcs_.push_back(
2763 (*receive_configs)[i].rtp.remote_ssrc);
Peter Boströmdef398832015-05-27 17:59:11 +02002764 (*receive_configs)[i].render_delay_ms = kExpectedRenderDelayMs;
tommi2e82f382016-06-21 00:26:43 -07002765 (*receive_configs)[i].renderer = &receive_stream_renderer_;
sprangcd349d92016-07-13 09:11:28 -07002766 (*receive_configs)[i].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2767
2768 (*receive_configs)[i].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
2769 kSendRtxSsrcs[i];
2770 (*receive_configs)[i].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
2771 kSendRtxPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002772 }
sprangcd349d92016-07-13 09:11:28 -07002773
2774 for (size_t i = 0; i < kNumSsrcs; ++i)
2775 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
2776
Peter Boströmc6e16e32016-02-05 14:15:53 +01002777 // Use a delayed encoder to make sure we see CpuOveruseMetrics stats that
2778 // are non-zero.
2779 send_config->encoder_settings.encoder = &encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002780 }
2781
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002782 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00002783
stefanff483612015-12-21 03:14:00 -08002784 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002785 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002786 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002787 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002788 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002789 }
2790
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002791 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002792 Clock* clock = Clock::GetRealTimeClock();
2793 int64_t now = clock->TimeInMilliseconds();
2794 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
2795 bool receive_ok = false;
2796 bool send_ok = false;
2797
2798 while (now < stop_time) {
2799 if (!receive_ok)
2800 receive_ok = CheckReceiveStats();
2801 if (!send_ok)
2802 send_ok = CheckSendStats();
2803
2804 if (receive_ok && send_ok)
2805 return;
2806
2807 int64_t time_until_timout_ = stop_time - now;
2808 if (time_until_timout_ > 0)
Peter Boström5811a392015-12-10 13:02:50 +01002809 check_stats_event_.Wait(time_until_timout_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002810 now = clock->TimeInMilliseconds();
2811 }
2812
2813 ADD_FAILURE() << "Timed out waiting for filled stats.";
2814 for (std::map<std::string, bool>::const_iterator it =
2815 receive_stats_filled_.begin();
2816 it != receive_stats_filled_.end();
2817 ++it) {
2818 if (!it->second) {
2819 ADD_FAILURE() << "Missing receive stats: " << it->first;
2820 }
2821 }
2822
2823 for (std::map<std::string, bool>::const_iterator it =
2824 send_stats_filled_.begin();
2825 it != send_stats_filled_.end();
2826 ++it) {
2827 if (!it->second) {
2828 ADD_FAILURE() << "Missing send stats: " << it->first;
2829 }
2830 }
2831 }
2832
Peter Boströmc6e16e32016-02-05 14:15:53 +01002833 test::DelayedEncoder encoder_;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002834 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002835 std::map<std::string, bool> receive_stats_filled_;
2836
2837 VideoSendStream* send_stream_;
2838 std::map<std::string, bool> send_stats_filled_;
2839
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002840 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002841 std::set<uint32_t> expected_send_ssrcs_;
2842 std::string expected_cname_;
2843
Peter Boström5811a392015-12-10 13:02:50 +01002844 rtc::Event check_stats_event_;
tommi2e82f382016-06-21 00:26:43 -07002845 ReceiveStreamRenderer receive_stream_renderer_;
stefanf116bd02015-10-27 08:29:42 -07002846 } test;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002847
stefane74eef12016-01-08 06:47:13 -08002848 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002849}
2850
2851TEST_F(EndToEndTest, ReceiverReferenceTimeReportEnabled) {
2852 TestXrReceiverReferenceTimeReport(true);
2853}
2854
2855TEST_F(EndToEndTest, ReceiverReferenceTimeReportDisabled) {
2856 TestXrReceiverReferenceTimeReport(false);
2857}
2858
2859TEST_F(EndToEndTest, TestReceivedRtpPacketStats) {
2860 static const size_t kNumRtpPacketsToSend = 5;
2861 class ReceivedRtpStatsObserver : public test::EndToEndTest {
2862 public:
2863 ReceivedRtpStatsObserver()
2864 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002865 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002866 sent_rtp_(0) {}
2867
2868 private:
stefanff483612015-12-21 03:14:00 -08002869 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002870 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002871 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002872 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002873 }
2874
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002875 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002876 if (sent_rtp_ >= kNumRtpPacketsToSend) {
2877 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002878 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
Peter Boström5811a392015-12-10 13:02:50 +01002879 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002880 }
2881 return DROP_PACKET;
2882 }
2883 ++sent_rtp_;
2884 return SEND_PACKET;
2885 }
2886
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002887 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002888 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002889 << "Timed out while verifying number of received RTP packets.";
2890 }
2891
2892 VideoReceiveStream* receive_stream_;
2893 uint32_t sent_rtp_;
2894 } test;
2895
stefane74eef12016-01-08 06:47:13 -08002896 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002897}
2898
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002899TEST_F(EndToEndTest, SendsSetSsrc) { TestSendsSetSsrcs(1, false); }
2900
2901TEST_F(EndToEndTest, SendsSetSimulcastSsrcs) {
2902 TestSendsSetSsrcs(kNumSsrcs, false);
2903}
2904
2905TEST_F(EndToEndTest, CanSwitchToUseAllSsrcs) {
2906 TestSendsSetSsrcs(kNumSsrcs, true);
2907}
2908
mflodman@webrtc.orgf9460682014-07-24 16:41:25 +00002909TEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002910 class ObserveRedundantPayloads: public test::EndToEndTest {
2911 public:
2912 ObserveRedundantPayloads()
2913 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00002914 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002915 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
2916 }
2917 }
2918
2919 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002920 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002921 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002922 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002923
2924 if (!registered_rtx_ssrc_[header.ssrc])
2925 return SEND_PACKET;
2926
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002927 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002928 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002929 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002930
2931 if (!packet_is_redundant_payload)
2932 return SEND_PACKET;
2933
2934 if (!observed_redundant_retransmission_[header.ssrc]) {
2935 observed_redundant_retransmission_[header.ssrc] = true;
2936 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002937 observation_complete_.Set();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002938 }
2939
2940 return SEND_PACKET;
2941 }
2942
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002943 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002944
stefanff483612015-12-21 03:14:00 -08002945 void ModifyVideoConfigs(
2946 VideoSendStream::Config* send_config,
2947 std::vector<VideoReceiveStream::Config>* receive_configs,
2948 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002949 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002950 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2951 encoder_config->streams[i].min_bitrate_bps = 10000;
2952 encoder_config->streams[i].target_bitrate_bps = 15000;
2953 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002954 }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002955
2956 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002957
2958 for (size_t i = 0; i < kNumSsrcs; ++i)
2959 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00002960
2961 // Significantly higher than max bitrates for all video streams -> forcing
2962 // padding to trigger redundant padding on all RTX SSRCs.
2963 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002964 }
2965
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002966 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002967 EXPECT_TRUE(Wait())
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002968 << "Timed out while waiting for redundant payloads on all SSRCs.";
2969 }
2970
2971 private:
2972 size_t ssrcs_to_observe_;
2973 std::map<uint32_t, bool> observed_redundant_retransmission_;
2974 std::map<uint32_t, bool> registered_rtx_ssrc_;
2975 } test;
2976
stefane74eef12016-01-08 06:47:13 -08002977 RunBaseTest(&test);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002978}
2979
Danil Chapovalov70ffead2016-07-20 15:26:59 +02002980void EndToEndTest::TestRtpStatePreservation(bool use_rtx,
2981 bool provoke_rtcpsr_before_rtp) {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002982 class RtpSequenceObserver : public test::RtpRtcpObserver {
2983 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00002984 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002985 : test::RtpRtcpObserver(kDefaultTimeoutMs),
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002986 ssrcs_to_observe_(kNumSsrcs) {
2987 for (size_t i = 0; i < kNumSsrcs; ++i) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002988 configured_ssrcs_[kVideoSendSsrcs[i]] = true;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002989 if (use_rtx)
2990 configured_ssrcs_[kSendRtxSsrcs[i]] = true;
2991 }
2992 }
2993
2994 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
Peter Boströmf2f82832015-05-01 13:00:41 +02002995 rtc::CritScope lock(&crit_);
danilchap34877ee2016-02-01 08:25:04 -08002996 ssrc_observed_.clear();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002997 ssrcs_to_observe_ = num_expected_ssrcs;
2998 }
2999
3000 private:
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003001 void ValidateTimestampGap(uint32_t ssrc,
3002 uint32_t timestamp,
3003 bool only_padding)
3004 EXCLUSIVE_LOCKS_REQUIRED(crit_) {
3005 static const int32_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
3006 auto timestamp_it = last_observed_timestamp_.find(ssrc);
3007 if (timestamp_it == last_observed_timestamp_.end()) {
3008 EXPECT_FALSE(only_padding);
3009 last_observed_timestamp_[ssrc] = timestamp;
3010 } else {
3011 // Verify timestamps are reasonably close.
3012 uint32_t latest_observed = timestamp_it->second;
3013 // Wraparound handling is unnecessary here as long as an int variable
3014 // is used to store the result.
3015 int32_t timestamp_gap = timestamp - latest_observed;
3016 EXPECT_LE(std::abs(timestamp_gap), kMaxTimestampGap)
3017 << "Gap in timestamps (" << latest_observed << " -> " << timestamp
3018 << ") too large for SSRC: " << ssrc << ".";
3019 timestamp_it->second = timestamp;
3020 }
3021 }
3022
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003023 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003024 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003025 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003026 const uint32_t ssrc = header.ssrc;
danilchap5c35cf92016-02-03 14:14:49 -08003027 const int64_t sequence_number =
3028 seq_numbers_unwrapper_.Unwrap(header.sequenceNumber);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003029 const uint32_t timestamp = header.timestamp;
danilchap34877ee2016-02-01 08:25:04 -08003030 const bool only_padding =
3031 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003032
3033 EXPECT_TRUE(configured_ssrcs_[ssrc])
3034 << "Received SSRC that wasn't configured: " << ssrc;
3035
danilchap5c35cf92016-02-03 14:14:49 -08003036 static const int64_t kMaxSequenceNumberGap = 100;
3037 std::list<int64_t>* seq_numbers = &last_observed_seq_numbers_[ssrc];
3038 if (seq_numbers->empty()) {
3039 seq_numbers->push_back(sequence_number);
3040 } else {
3041 // We shouldn't get replays of previous sequence numbers.
3042 for (int64_t observed : *seq_numbers) {
3043 EXPECT_NE(observed, sequence_number)
3044 << "Received sequence number " << sequence_number
3045 << " for SSRC " << ssrc << " 2nd time.";
3046 }
3047 // Verify sequence numbers are reasonably close.
3048 int64_t latest_observed = seq_numbers->back();
3049 int64_t sequence_number_gap = sequence_number - latest_observed;
3050 EXPECT_LE(std::abs(sequence_number_gap), kMaxSequenceNumberGap)
3051 << "Gap in sequence numbers (" << latest_observed << " -> "
3052 << sequence_number << ") too large for SSRC: " << ssrc << ".";
3053 seq_numbers->push_back(sequence_number);
3054 if (seq_numbers->size() >= kMaxSequenceNumberGap) {
3055 seq_numbers->pop_front();
3056 }
3057 }
3058
danilchap34877ee2016-02-01 08:25:04 -08003059 rtc::CritScope lock(&crit_);
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003060 ValidateTimestampGap(ssrc, timestamp, only_padding);
3061
danilchap34877ee2016-02-01 08:25:04 -08003062 // Wait for media packets on all ssrcs.
3063 if (!ssrc_observed_[ssrc] && !only_padding) {
3064 ssrc_observed_[ssrc] = true;
3065 if (--ssrcs_to_observe_ == 0)
3066 observation_complete_.Set();
3067 }
3068
danilchapf4b9c772016-01-28 06:14:24 -08003069 return SEND_PACKET;
3070 }
3071
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003072 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
3073 test::RtcpPacketParser rtcp_parser;
3074 rtcp_parser.Parse(packet, length);
3075 if (rtcp_parser.sender_report()->num_packets() > 0) {
3076 uint32_t ssrc = rtcp_parser.sender_report()->Ssrc();
3077 uint32_t rtcp_timestamp = rtcp_parser.sender_report()->RtpTimestamp();
3078
3079 rtc::CritScope lock(&crit_);
3080 ValidateTimestampGap(ssrc, rtcp_timestamp, false);
3081 }
3082 return SEND_PACKET;
3083 }
3084
danilchap5c35cf92016-02-03 14:14:49 -08003085 SequenceNumberUnwrapper seq_numbers_unwrapper_;
3086 std::map<uint32_t, std::list<int64_t>> last_observed_seq_numbers_;
danilchap34877ee2016-02-01 08:25:04 -08003087 std::map<uint32_t, uint32_t> last_observed_timestamp_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003088 std::map<uint32_t, bool> configured_ssrcs_;
3089
Peter Boströmf2f82832015-05-01 13:00:41 +02003090 rtc::CriticalSection crit_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003091 size_t ssrcs_to_observe_ GUARDED_BY(crit_);
danilchap34877ee2016-02-01 08:25:04 -08003092 std::map<uint32_t, bool> ssrc_observed_ GUARDED_BY(crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003093 } observer(use_rtx);
3094
solenberg4fbae2b2015-08-28 04:07:10 -07003095 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003096
stefanf116bd02015-10-27 08:29:42 -07003097 test::PacketTransport send_transport(sender_call_.get(), &observer,
3098 test::PacketTransport::kSender,
3099 FakeNetworkPipe::Config());
3100 test::PacketTransport receive_transport(nullptr, &observer,
3101 test::PacketTransport::kReceiver,
3102 FakeNetworkPipe::Config());
3103 send_transport.SetReceiver(receiver_call_->Receiver());
3104 receive_transport.SetReceiver(sender_call_->Receiver());
3105
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003106 CreateSendConfig(kNumSsrcs, 0, &send_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003107
3108 if (use_rtx) {
3109 for (size_t i = 0; i < kNumSsrcs; ++i) {
stefanff483612015-12-21 03:14:00 -08003110 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003111 }
stefanff483612015-12-21 03:14:00 -08003112 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003113 }
3114
3115 // Lower bitrates so that all streams send initially.
stefanff483612015-12-21 03:14:00 -08003116 for (size_t i = 0; i < video_encoder_config_.streams.size(); ++i) {
3117 video_encoder_config_.streams[i].min_bitrate_bps = 10000;
3118 video_encoder_config_.streams[i].target_bitrate_bps = 15000;
3119 video_encoder_config_.streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003120 }
3121
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003122 // Use the same total bitrates when sending a single stream to avoid lowering
3123 // the bitrate estimate and requiring a subsequent rampup.
stefanff483612015-12-21 03:14:00 -08003124 VideoEncoderConfig one_stream = video_encoder_config_;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003125 one_stream.streams.resize(1);
stefanff483612015-12-21 03:14:00 -08003126 for (size_t i = 1; i < video_encoder_config_.streams.size(); ++i) {
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003127 one_stream.streams.front().min_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003128 video_encoder_config_.streams[i].min_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003129 one_stream.streams.front().target_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003130 video_encoder_config_.streams[i].target_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003131 one_stream.streams.front().max_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003132 video_encoder_config_.streams[i].max_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003133 }
3134
stefanf116bd02015-10-27 08:29:42 -07003135 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003136
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003137 CreateVideoStreams();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003138 CreateFrameGeneratorCapturer();
3139
3140 Start();
Peter Boström5811a392015-12-10 13:02:50 +01003141 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003142 << "Timed out waiting for all SSRCs to send packets.";
3143
3144 // Test stream resetting more than once to make sure that the state doesn't
3145 // get set once (this could be due to using std::map::insert for instance).
3146 for (size_t i = 0; i < 3; ++i) {
3147 frame_generator_capturer_->Stop();
stefanff483612015-12-21 03:14:00 -08003148 sender_call_->DestroyVideoSendStream(video_send_stream_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003149
3150 // Re-create VideoSendStream with only one stream.
stefanff483612015-12-21 03:14:00 -08003151 video_send_stream_ =
3152 sender_call_->CreateVideoSendStream(video_send_config_, one_stream);
3153 video_send_stream_->Start();
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003154 if (provoke_rtcpsr_before_rtp) {
3155 // Rapid Resync Request forces sending RTCP Sender Report back.
3156 // Using this request speeds up this test because then there is no need
3157 // to wait for a second for periodic Sender Report.
3158 rtcp::RapidResyncRequest force_send_sr_back_request;
3159 rtc::Buffer packet = force_send_sr_back_request.Build();
3160 static_cast<webrtc::test::DirectTransport&>(receive_transport)
3161 .SendRtcp(packet.data(), packet.size());
3162 }
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003163 CreateFrameGeneratorCapturer();
3164 frame_generator_capturer_->Start();
3165
3166 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 // Reconfigure down to one stream.
stefanff483612015-12-21 03:14:00 -08003176 video_send_stream_->ReconfigureVideoEncoder(one_stream);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003177 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003178 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003179
3180 // Reconfigure back to use all streams.
stefanff483612015-12-21 03:14:00 -08003181 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003182 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003183 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003184 << "Timed out waiting for all SSRCs to send packets.";
3185 }
3186
stefanf116bd02015-10-27 08:29:42 -07003187 send_transport.StopSending();
3188 receive_transport.StopSending();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003189
3190 Stop();
3191 DestroyStreams();
3192}
3193
Peter Boströmfc968a22016-02-19 16:14:37 +01003194TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpState) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003195 TestRtpStatePreservation(false, false);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003196}
3197
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003198// These tests are flaky. See:
deadbeef1caff882016-06-27 13:09:52 -07003199// https://bugs.chromium.org/p/webrtc/issues/detail?id=4332
3200TEST_F(EndToEndTest, DISABLED_RestartingSendStreamPreservesRtpStatesWithRtx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003201 TestRtpStatePreservation(true, false);
3202}
3203
3204TEST_F(EndToEndTest,
3205 DISABLED_RestartingSendStreamKeepsRtpAndRtcpTimestampsSynced) {
3206 TestRtpStatePreservation(true, true);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003207}
3208
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003209TEST_F(EndToEndTest, RespectsNetworkState) {
3210 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
3211 // down blocks until no more packets will be sent.
3212
3213 // Pacer will send from its packet list and then send required padding before
3214 // checking paused_ again. This should be enough for one round of pacing,
3215 // otherwise increase.
3216 static const int kNumAcceptedDowntimeRtp = 5;
3217 // A single RTCP may be in the pipeline.
3218 static const int kNumAcceptedDowntimeRtcp = 1;
3219 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
3220 public:
3221 NetworkStateTest()
3222 : EndToEndTest(kDefaultTimeoutMs),
3223 FakeEncoder(Clock::GetRealTimeClock()),
Peter Boström5811a392015-12-10 13:02:50 +01003224 encoded_frames_(false, false),
3225 packet_event_(false, false),
sprang867fb522015-08-03 04:38:41 -07003226 sender_call_(nullptr),
3227 receiver_call_(nullptr),
Jelena Marusiccd670222015-07-16 09:30:09 +02003228 sender_state_(kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003229 sender_rtp_(0),
3230 sender_rtcp_(0),
3231 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003232 down_frames_(0) {}
3233
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003234 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003235 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003236 ++sender_rtp_;
Peter Boström5811a392015-12-10 13:02:50 +01003237 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003238 return SEND_PACKET;
3239 }
3240
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003241 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003242 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003243 ++sender_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003244 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003245 return SEND_PACKET;
3246 }
3247
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003248 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003249 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
3250 return SEND_PACKET;
3251 }
3252
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003253 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003254 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003255 ++receiver_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003256 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003257 return SEND_PACKET;
3258 }
3259
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003260 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003261 sender_call_ = sender_call;
3262 receiver_call_ = receiver_call;
3263 }
3264
stefanff483612015-12-21 03:14:00 -08003265 void ModifyVideoConfigs(
3266 VideoSendStream::Config* send_config,
3267 std::vector<VideoReceiveStream::Config>* receive_configs,
3268 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003269 send_config->encoder_settings.encoder = this;
3270 }
3271
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003272 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003273 EXPECT_TRUE(encoded_frames_.Wait(kDefaultTimeoutMs))
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003274 << "No frames received by the encoder.";
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003275 // Wait for packets from both sender/receiver.
3276 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003277
skvlad7a43d252016-03-22 15:32:27 -07003278 // Sender-side network down for audio; there should be no effect on video
3279 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3280 WaitForPacketsOrSilence(false, false);
3281
3282 // Receiver-side network down for audio; no change expected
3283 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3284 WaitForPacketsOrSilence(false, false);
3285
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003286 // Sender-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003287 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003288 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003289 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003290 // After network goes down we shouldn't be encoding more frames.
Jelena Marusiccd670222015-07-16 09:30:09 +02003291 sender_state_ = kNetworkDown;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003292 }
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003293 // Wait for receiver-packets and no sender packets.
3294 WaitForPacketsOrSilence(true, false);
3295
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003296 // Receiver-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003297 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
3298 WaitForPacketsOrSilence(true, true);
3299
3300 // Network up for audio for both sides; video is still not expected to
3301 // start
3302 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
3303 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003304 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003305
3306 // Network back up again for both.
3307 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003308 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003309 // It's OK to encode frames again, as we're about to bring up the
3310 // network.
Jelena Marusiccd670222015-07-16 09:30:09 +02003311 sender_state_ = kNetworkUp;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003312 }
skvlad7a43d252016-03-22 15:32:27 -07003313 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
3314 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003315 WaitForPacketsOrSilence(false, false);
skvlad7a43d252016-03-22 15:32:27 -07003316
3317 // TODO(skvlad): add tests to verify that the audio streams are stopped
3318 // when the network goes down for audio once the workaround in
3319 // paced_sender.cc is removed.
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003320 }
3321
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07003322 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003323 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07003324 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003325 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003326 rtc::CritScope lock(&test_crit_);
Jelena Marusiccd670222015-07-16 09:30:09 +02003327 if (sender_state_ == kNetworkDown) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003328 ++down_frames_;
3329 EXPECT_LE(down_frames_, 1)
3330 << "Encoding more than one frame while network is down.";
3331 if (down_frames_ > 1)
Peter Boström5811a392015-12-10 13:02:50 +01003332 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003333 } else {
Peter Boström5811a392015-12-10 13:02:50 +01003334 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003335 }
3336 }
3337 return test::FakeEncoder::Encode(
3338 input_image, codec_specific_info, frame_types);
3339 }
3340
3341 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003342 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
3343 int64_t initial_time_ms = clock_->TimeInMilliseconds();
3344 int initial_sender_rtp;
3345 int initial_sender_rtcp;
3346 int initial_receiver_rtcp;
3347 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003348 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003349 initial_sender_rtp = sender_rtp_;
3350 initial_sender_rtcp = sender_rtcp_;
3351 initial_receiver_rtcp = receiver_rtcp_;
3352 }
3353 bool sender_done = false;
3354 bool receiver_done = false;
mflodmand1590b22015-12-09 07:07:59 -08003355 while (!sender_done || !receiver_done) {
Peter Boström5811a392015-12-10 13:02:50 +01003356 packet_event_.Wait(kSilenceTimeoutMs);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003357 int64_t time_now_ms = clock_->TimeInMilliseconds();
Peter Boströmf2f82832015-05-01 13:00:41 +02003358 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003359 if (sender_down) {
3360 ASSERT_LE(sender_rtp_ - initial_sender_rtp, kNumAcceptedDowntimeRtp)
3361 << "RTP sent during sender-side downtime.";
3362 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
3363 kNumAcceptedDowntimeRtcp)
3364 << "RTCP sent during sender-side downtime.";
3365 if (time_now_ms - initial_time_ms >=
3366 static_cast<int64_t>(kSilenceTimeoutMs)) {
3367 sender_done = true;
3368 }
3369 } else {
skvlad7a43d252016-03-22 15:32:27 -07003370 if (sender_rtp_ > initial_sender_rtp + kNumAcceptedDowntimeRtp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003371 sender_done = true;
3372 }
3373 if (receiver_down) {
3374 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
3375 kNumAcceptedDowntimeRtcp)
3376 << "RTCP sent during receiver-side downtime.";
3377 if (time_now_ms - initial_time_ms >=
3378 static_cast<int64_t>(kSilenceTimeoutMs)) {
3379 receiver_done = true;
3380 }
3381 } else {
skvlad7a43d252016-03-22 15:32:27 -07003382 if (receiver_rtcp_ > initial_receiver_rtcp + kNumAcceptedDowntimeRtcp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003383 receiver_done = true;
3384 }
3385 }
3386 }
3387
Peter Boströmf2f82832015-05-01 13:00:41 +02003388 rtc::CriticalSection test_crit_;
Peter Boström5811a392015-12-10 13:02:50 +01003389 rtc::Event encoded_frames_;
3390 rtc::Event packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003391 Call* sender_call_;
3392 Call* receiver_call_;
Jelena Marusiccd670222015-07-16 09:30:09 +02003393 NetworkState sender_state_ GUARDED_BY(test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003394 int sender_rtp_ GUARDED_BY(test_crit_);
3395 int sender_rtcp_ GUARDED_BY(test_crit_);
3396 int receiver_rtcp_ GUARDED_BY(test_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003397 int down_frames_ GUARDED_BY(test_crit_);
3398 } test;
3399
stefane74eef12016-01-08 06:47:13 -08003400 RunBaseTest(&test);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003401}
3402
danilchapa6a70072016-06-01 11:20:43 -07003403TEST_F(EndToEndTest, CallReportsRttForSender) {
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003404 static const int kSendDelayMs = 30;
3405 static const int kReceiveDelayMs = 70;
3406
solenberg4fbae2b2015-08-28 04:07:10 -07003407 CreateCalls(Call::Config(), Call::Config());
3408
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003409 FakeNetworkPipe::Config config;
3410 config.queue_delay_ms = kSendDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003411 test::DirectTransport sender_transport(config, sender_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003412 config.queue_delay_ms = kReceiveDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003413 test::DirectTransport receiver_transport(config, receiver_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003414 sender_transport.SetReceiver(receiver_call_->Receiver());
3415 receiver_transport.SetReceiver(sender_call_->Receiver());
3416
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003417 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07003418 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003419
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003420 CreateVideoStreams();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003421 CreateFrameGeneratorCapturer();
3422 Start();
3423
3424 int64_t start_time_ms = clock_->TimeInMilliseconds();
3425 while (true) {
3426 Call::Stats stats = sender_call_->GetStats();
3427 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
3428 clock_->TimeInMilliseconds())
3429 << "No RTT stats before timeout!";
3430 if (stats.rtt_ms != -1) {
3431 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs);
3432 break;
3433 }
3434 SleepMs(10);
3435 }
3436
3437 Stop();
3438 DestroyStreams();
3439}
3440
skvlad7a43d252016-03-22 15:32:27 -07003441void EndToEndTest::VerifyNewVideoSendStreamsRespectNetworkState(
3442 MediaType network_to_bring_down,
3443 VideoEncoder* encoder,
3444 Transport* transport) {
solenberg4fbae2b2015-08-28 04:07:10 -07003445 CreateSenderCall(Call::Config());
skvlad7a43d252016-03-22 15:32:27 -07003446 sender_call_->SignalChannelNetworkState(network_to_bring_down, kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003447
skvlad7a43d252016-03-22 15:32:27 -07003448 CreateSendConfig(1, 0, transport);
3449 video_send_config_.encoder_settings.encoder = encoder;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003450 CreateVideoStreams();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003451 CreateFrameGeneratorCapturer();
3452
3453 Start();
3454 SleepMs(kSilenceTimeoutMs);
3455 Stop();
3456
3457 DestroyStreams();
3458}
3459
skvlad7a43d252016-03-22 15:32:27 -07003460void EndToEndTest::VerifyNewVideoReceiveStreamsRespectNetworkState(
3461 MediaType network_to_bring_down,
3462 Transport* transport) {
solenberg4fbae2b2015-08-28 04:07:10 -07003463 CreateCalls(Call::Config(), Call::Config());
skvlad7a43d252016-03-22 15:32:27 -07003464 receiver_call_->SignalChannelNetworkState(network_to_bring_down,
3465 kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003466
stefanf116bd02015-10-27 08:29:42 -07003467 test::DirectTransport sender_transport(sender_call_.get());
solenberg4fbae2b2015-08-28 04:07:10 -07003468 sender_transport.SetReceiver(receiver_call_->Receiver());
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003469 CreateSendConfig(1, 0, &sender_transport);
skvlad7a43d252016-03-22 15:32:27 -07003470 CreateMatchingReceiveConfigs(transport);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003471 CreateVideoStreams();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003472 CreateFrameGeneratorCapturer();
3473
3474 Start();
3475 SleepMs(kSilenceTimeoutMs);
3476 Stop();
3477
3478 sender_transport.StopSending();
3479
3480 DestroyStreams();
3481}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00003482
skvlad7a43d252016-03-22 15:32:27 -07003483TEST_F(EndToEndTest, NewVideoSendStreamsRespectVideoNetworkDown) {
3484 class UnusedEncoder : public test::FakeEncoder {
3485 public:
3486 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
perkjfea93092016-05-14 00:58:48 -07003487
3488 int32_t InitEncode(const VideoCodec* config,
3489 int32_t number_of_cores,
3490 size_t max_payload_size) override {
3491 EXPECT_GT(config->startBitrate, 0u);
3492 return 0;
3493 }
skvlad7a43d252016-03-22 15:32:27 -07003494 int32_t Encode(const VideoFrame& input_image,
3495 const CodecSpecificInfo* codec_specific_info,
3496 const std::vector<FrameType>* frame_types) override {
3497 ADD_FAILURE() << "Unexpected frame encode.";
3498 return test::FakeEncoder::Encode(input_image, codec_specific_info,
3499 frame_types);
3500 }
3501 };
3502
3503 UnusedEncoder unused_encoder;
3504 UnusedTransport unused_transport;
3505 VerifyNewVideoSendStreamsRespectNetworkState(
3506 MediaType::VIDEO, &unused_encoder, &unused_transport);
3507}
3508
3509TEST_F(EndToEndTest, NewVideoSendStreamsIgnoreAudioNetworkDown) {
3510 class RequiredEncoder : public test::FakeEncoder {
3511 public:
3512 RequiredEncoder()
3513 : FakeEncoder(Clock::GetRealTimeClock()), encoded_frame_(false) {}
3514 ~RequiredEncoder() {
3515 if (!encoded_frame_) {
3516 ADD_FAILURE() << "Didn't encode an expected frame";
3517 }
3518 }
3519 int32_t Encode(const VideoFrame& input_image,
3520 const CodecSpecificInfo* codec_specific_info,
3521 const std::vector<FrameType>* frame_types) override {
3522 encoded_frame_ = true;
3523 return test::FakeEncoder::Encode(input_image, codec_specific_info,
3524 frame_types);
3525 }
3526
3527 private:
3528 bool encoded_frame_;
3529 };
3530
3531 RequiredTransport required_transport(true /*rtp*/, false /*rtcp*/);
3532 RequiredEncoder required_encoder;
3533 VerifyNewVideoSendStreamsRespectNetworkState(
3534 MediaType::AUDIO, &required_encoder, &required_transport);
3535}
3536
3537TEST_F(EndToEndTest, NewVideoReceiveStreamsRespectVideoNetworkDown) {
3538 UnusedTransport transport;
3539 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::VIDEO, &transport);
3540}
3541
3542TEST_F(EndToEndTest, NewVideoReceiveStreamsIgnoreAudioNetworkDown) {
3543 RequiredTransport transport(false /*rtp*/, true /*rtcp*/);
3544 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::AUDIO, &transport);
3545}
3546
Peter Boströmd7da1202015-06-05 14:09:38 +02003547void VerifyEmptyNackConfig(const NackConfig& config) {
3548 EXPECT_EQ(0, config.rtp_history_ms)
3549 << "Enabling NACK requires rtcp-fb: nack negotiation.";
3550}
3551
3552void VerifyEmptyFecConfig(const FecConfig& config) {
3553 EXPECT_EQ(-1, config.ulpfec_payload_type)
3554 << "Enabling FEC requires rtpmap: ulpfec negotiation.";
3555 EXPECT_EQ(-1, config.red_payload_type)
3556 << "Enabling FEC requires rtpmap: red negotiation.";
3557 EXPECT_EQ(-1, config.red_rtx_payload_type)
3558 << "Enabling RTX in FEC requires rtpmap: rtx negotiation.";
3559}
3560
3561TEST_F(EndToEndTest, VerifyDefaultSendConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003562 VideoSendStream::Config default_send_config(nullptr);
Peter Boströmd7da1202015-06-05 14:09:38 +02003563 EXPECT_EQ(0, default_send_config.rtp.nack.rtp_history_ms)
3564 << "Enabling NACK require rtcp-fb: nack negotiation.";
3565 EXPECT_TRUE(default_send_config.rtp.rtx.ssrcs.empty())
3566 << "Enabling RTX requires rtpmap: rtx negotiation.";
3567 EXPECT_TRUE(default_send_config.rtp.extensions.empty())
3568 << "Enabling RTP extensions require negotiation.";
3569
3570 VerifyEmptyNackConfig(default_send_config.rtp.nack);
3571 VerifyEmptyFecConfig(default_send_config.rtp.fec);
3572}
3573
3574TEST_F(EndToEndTest, VerifyDefaultReceiveConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003575 VideoReceiveStream::Config default_receive_config(nullptr);
pbosda903ea2015-10-02 02:36:56 -07003576 EXPECT_EQ(RtcpMode::kCompound, default_receive_config.rtp.rtcp_mode)
Peter Boströmd7da1202015-06-05 14:09:38 +02003577 << "Reduced-size RTCP require rtcp-rsize to be negotiated.";
3578 EXPECT_FALSE(default_receive_config.rtp.remb)
3579 << "REMB require rtcp-fb: goog-remb to be negotiated.";
3580 EXPECT_FALSE(
3581 default_receive_config.rtp.rtcp_xr.receiver_reference_time_report)
3582 << "RTCP XR settings require rtcp-xr to be negotiated.";
3583 EXPECT_TRUE(default_receive_config.rtp.rtx.empty())
3584 << "Enabling RTX requires rtpmap: rtx negotiation.";
3585 EXPECT_TRUE(default_receive_config.rtp.extensions.empty())
3586 << "Enabling RTP extensions require negotiation.";
3587
3588 VerifyEmptyNackConfig(default_receive_config.rtp.nack);
3589 VerifyEmptyFecConfig(default_receive_config.rtp.fec);
3590}
3591
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003592TEST_F(EndToEndTest, TransportSeqNumOnAudioAndVideo) {
3593 static const int kExtensionId = 8;
3594 class TransportSequenceNumberTest : public test::EndToEndTest {
3595 public:
3596 TransportSequenceNumberTest()
3597 : EndToEndTest(kDefaultTimeoutMs),
3598 video_observed_(false),
3599 audio_observed_(false) {
3600 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
3601 kExtensionId);
3602 }
3603
3604 size_t GetNumVideoStreams() const override { return 1; }
3605 size_t GetNumAudioStreams() const override { return 1; }
3606
3607 void ModifyVideoConfigs(
3608 VideoSendStream::Config* send_config,
3609 std::vector<VideoReceiveStream::Config>* receive_configs,
3610 VideoEncoderConfig* encoder_config) override {
3611 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07003612 send_config->rtp.extensions.push_back(RtpExtension(
3613 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003614 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3615 }
3616
3617 void ModifyAudioConfigs(
3618 AudioSendStream::Config* send_config,
3619 std::vector<AudioReceiveStream::Config>* receive_configs) override {
3620 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07003621 send_config->rtp.extensions.push_back(RtpExtension(
3622 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003623 (*receive_configs)[0].rtp.extensions.clear();
3624 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3625 }
3626
3627 Action OnSendRtp(const uint8_t* packet, size_t length) override {
3628 RTPHeader header;
3629 EXPECT_TRUE(parser_->Parse(packet, length, &header));
3630 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
3631 // Unwrap packet id and verify uniqueness.
3632 int64_t packet_id =
3633 unwrapper_.Unwrap(header.extension.transportSequenceNumber);
3634 EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
3635
3636 if (header.ssrc == kVideoSendSsrcs[0])
3637 video_observed_ = true;
3638 if (header.ssrc == kAudioSendSsrc)
3639 audio_observed_ = true;
3640 if (audio_observed_ && video_observed_ &&
3641 received_packet_ids_.size() == 50) {
3642 size_t packet_id_range =
3643 *received_packet_ids_.rbegin() - *received_packet_ids_.begin() + 1;
3644 EXPECT_EQ(received_packet_ids_.size(), packet_id_range);
3645 observation_complete_.Set();
3646 }
3647 return SEND_PACKET;
3648 }
3649
3650 void PerformTest() override {
3651 EXPECT_TRUE(Wait()) << "Timed out while waiting for audio and video "
3652 "packets with transport sequence number.";
3653 }
3654
3655 private:
3656 bool video_observed_;
3657 bool audio_observed_;
3658 SequenceNumberUnwrapper unwrapper_;
3659 std::set<int64_t> received_packet_ids_;
3660 } test;
3661
stefane74eef12016-01-08 06:47:13 -08003662 RunBaseTest(&test);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003663}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003664} // namespace webrtc