blob: d7553500da3aa3b9808f3fc50139af0766feec29 [file] [log] [blame]
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001/*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000010#include <algorithm>
danilchap5c35cf92016-02-03 14:14:49 -080011#include <list>
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000012#include <map>
kwiberg27f982b2016-03-01 11:52:33 -080013#include <memory>
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000014#include <sstream>
15#include <string>
kwiberg4a206a92016-03-31 10:24:26 -070016#include <vector>
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000017
18#include "testing/gtest/include/gtest/gtest.h"
19
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000020#include "webrtc/base/checks.h"
Erik Språng6b8d3552015-09-24 15:06:57 +020021#include "webrtc/base/event.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000022#include "webrtc/call.h"
Peter Boström5c389d32015-09-25 13:58:30 +020023#include "webrtc/call/transport_adapter.h"
pbosa96b60b2016-04-18 21:12:48 -070024#include "webrtc/common_video/include/frame_callback.h"
danilchap5c35cf92016-02-03 14:14:49 -080025#include "webrtc/modules/include/module_common_types.h"
stefan32f81542016-01-20 07:13:58 -080026#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
sprang861c55e2015-10-16 10:01:21 -070027#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
Danil Chapovalov70ffead2016-07-20 15:26:59 +020028#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000029#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
sprangcd349d92016-07-13 09:11:28 -070030#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
hbosbab934b2016-01-27 01:36:03 -080031#include "webrtc/modules/video_coding/codecs/h264/include/h264.h"
marpan@webrtc.org5b883172014-11-01 06:10:48 +000032#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
33#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010034#include "webrtc/modules/video_coding/include/video_coding_defines.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010035#include "webrtc/system_wrappers/include/metrics.h"
asapersson01d70a32016-05-20 06:29:46 -070036#include "webrtc/system_wrappers/include/metrics_default.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010037#include "webrtc/system_wrappers/include/sleep.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000038#include "webrtc/test/call_test.h"
39#include "webrtc/test/direct_transport.h"
40#include "webrtc/test/encoder_settings.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000041#include "webrtc/test/fake_decoder.h"
42#include "webrtc/test/fake_encoder.h"
43#include "webrtc/test/frame_generator.h"
44#include "webrtc/test/frame_generator_capturer.h"
45#include "webrtc/test/null_transport.h"
asapersson@webrtc.org37c05592015-01-28 13:58:27 +000046#include "webrtc/test/rtcp_packet_parser.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000047#include "webrtc/test/rtp_rtcp_observer.h"
48#include "webrtc/test/testsupport/fileutils.h"
49#include "webrtc/test/testsupport/perf_test.h"
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +000050#include "webrtc/video_encoder.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000051
52namespace webrtc {
53
Peter Boström5811a392015-12-10 13:02:50 +010054static const int kSilenceTimeoutMs = 2000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000055
56class EndToEndTest : public test::CallTest {
57 public:
58 EndToEndTest() {}
59
60 virtual ~EndToEndTest() {
stefanff483612015-12-21 03:14:00 -080061 EXPECT_EQ(nullptr, video_send_stream_);
62 EXPECT_TRUE(video_receive_streams_.empty());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000063 }
64
65 protected:
pbos2d566682015-09-28 09:59:31 -070066 class UnusedTransport : public Transport {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000067 private:
stefan1d8a5062015-10-02 03:39:33 -070068 bool SendRtp(const uint8_t* packet,
69 size_t length,
70 const PacketOptions& options) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000071 ADD_FAILURE() << "Unexpected RTP sent.";
72 return false;
73 }
74
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000075 bool SendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000076 ADD_FAILURE() << "Unexpected RTCP sent.";
77 return false;
78 }
79 };
80
skvlad7a43d252016-03-22 15:32:27 -070081 class RequiredTransport : public Transport {
82 public:
83 RequiredTransport(bool rtp_required, bool rtcp_required)
84 : need_rtp_(rtp_required), need_rtcp_(rtcp_required) {}
85 ~RequiredTransport() {
86 if (need_rtp_) {
87 ADD_FAILURE() << "Expected RTP packet not sent.";
88 }
89 if (need_rtcp_) {
90 ADD_FAILURE() << "Expected RTCP packet not sent.";
91 }
92 }
93
94 private:
95 bool SendRtp(const uint8_t* packet,
96 size_t length,
97 const PacketOptions& options) override {
98 need_rtp_ = false;
99 return true;
100 }
101
102 bool SendRtcp(const uint8_t* packet, size_t length) override {
103 need_rtcp_ = false;
104 return true;
105 }
106 bool need_rtp_;
107 bool need_rtcp_;
108 };
109
Peter Boström39593972016-02-15 11:27:15 +0100110 void DecodesRetransmittedFrame(bool enable_rtx, bool enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000111 void ReceivesPliAndRecovers(int rtp_history_ms);
pbosda903ea2015-10-02 02:36:56 -0700112 void RespectsRtcpMode(RtcpMode rtcp_mode);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000113 void TestXrReceiverReferenceTimeReport(bool enable_rrtr);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000114 void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200115 void TestRtpStatePreservation(bool use_rtx, bool provoke_rtcpsr_before_rtp);
sprangb4a1ae52015-12-03 08:10:08 -0800116 void VerifyHistogramStats(bool use_rtx, bool use_red, bool screenshare);
skvlad7a43d252016-03-22 15:32:27 -0700117 void VerifyNewVideoSendStreamsRespectNetworkState(
118 MediaType network_to_bring_down,
119 VideoEncoder* encoder,
120 Transport* transport);
121 void VerifyNewVideoReceiveStreamsRespectNetworkState(
122 MediaType network_to_bring_down,
123 Transport* transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000124};
125
126TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
solenberg4fbae2b2015-08-28 04:07:10 -0700127 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000128
solenberg4fbae2b2015-08-28 04:07:10 -0700129 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100130 CreateSendConfig(1, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700131 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000132
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100133 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000134
stefanff483612015-12-21 03:14:00 -0800135 video_receive_streams_[0]->Start();
136 video_receive_streams_[0]->Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000137
138 DestroyStreams();
139}
140
141TEST_F(EndToEndTest, ReceiverCanBeStoppedTwice) {
solenberg4fbae2b2015-08-28 04:07:10 -0700142 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000143
solenberg4fbae2b2015-08-28 04:07:10 -0700144 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100145 CreateSendConfig(1, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700146 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000147
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100148 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000149
stefanff483612015-12-21 03:14:00 -0800150 video_receive_streams_[0]->Stop();
151 video_receive_streams_[0]->Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000152
153 DestroyStreams();
154}
155
156TEST_F(EndToEndTest, RendersSingleDelayedFrame) {
157 static const int kWidth = 320;
158 static const int kHeight = 240;
159 // This constant is chosen to be higher than the timeout in the video_render
160 // module. This makes sure that frames aren't dropped if there are no other
161 // frames in the queue.
162 static const int kDelayRenderCallbackMs = 1000;
163
nisse7ade7b32016-03-23 04:48:10 -0700164 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000165 public:
Peter Boström5811a392015-12-10 13:02:50 +0100166 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000167
nisseeb83a1a2016-03-21 01:27:56 -0700168 void OnFrame(const VideoFrame& video_frame) override { event_.Set(); }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000169
Peter Boström5811a392015-12-10 13:02:50 +0100170 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000171
Peter Boström5811a392015-12-10 13:02:50 +0100172 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000173 } renderer;
174
175 class TestFrameCallback : public I420FrameCallback {
176 public:
Peter Boström5811a392015-12-10 13:02:50 +0100177 TestFrameCallback() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000178
Peter Boström5811a392015-12-10 13:02:50 +0100179 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000180
181 private:
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700182 void FrameCallback(VideoFrame* frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000183 SleepMs(kDelayRenderCallbackMs);
Peter Boström5811a392015-12-10 13:02:50 +0100184 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000185 }
186
Peter Boström5811a392015-12-10 13:02:50 +0100187 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000188 };
189
solenberg4fbae2b2015-08-28 04:07:10 -0700190 CreateCalls(Call::Config(), Call::Config());
191
stefanf116bd02015-10-27 08:29:42 -0700192 test::DirectTransport sender_transport(sender_call_.get());
193 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000194 sender_transport.SetReceiver(receiver_call_->Receiver());
195 receiver_transport.SetReceiver(sender_call_->Receiver());
196
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100197 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700198 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000199
200 TestFrameCallback pre_render_callback;
stefanff483612015-12-21 03:14:00 -0800201 video_receive_configs_[0].pre_render_callback = &pre_render_callback;
202 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000203
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100204 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000205 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000206
207 // Create frames that are smaller than the send width/height, this is done to
208 // check that the callbacks are done after processing video.
kwiberg27f982b2016-03-01 11:52:33 -0800209 std::unique_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000210 test::FrameGenerator::CreateChromaGenerator(kWidth, kHeight));
stefanff483612015-12-21 03:14:00 -0800211 video_send_stream_->Input()->IncomingCapturedFrame(
212 *frame_generator->NextFrame());
Peter Boström5811a392015-12-10 13:02:50 +0100213 EXPECT_TRUE(pre_render_callback.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000214 << "Timed out while waiting for pre-render callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100215 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000216 << "Timed out while waiting for the frame to render.";
217
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000218 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000219
220 sender_transport.StopSending();
221 receiver_transport.StopSending();
222
223 DestroyStreams();
224}
225
226TEST_F(EndToEndTest, TransmitsFirstFrame) {
nisse7ade7b32016-03-23 04:48:10 -0700227 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000228 public:
Peter Boström5811a392015-12-10 13:02:50 +0100229 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000230
nisseeb83a1a2016-03-21 01:27:56 -0700231 void OnFrame(const VideoFrame& video_frame) override { event_.Set(); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000232
Peter Boström5811a392015-12-10 13:02:50 +0100233 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000234
Peter Boström5811a392015-12-10 13:02:50 +0100235 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000236 } renderer;
237
solenberg4fbae2b2015-08-28 04:07:10 -0700238 CreateCalls(Call::Config(), Call::Config());
239
stefanf116bd02015-10-27 08:29:42 -0700240 test::DirectTransport sender_transport(sender_call_.get());
241 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000242 sender_transport.SetReceiver(receiver_call_->Receiver());
243 receiver_transport.SetReceiver(sender_call_->Receiver());
244
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100245 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700246 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -0800247 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000248
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100249 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000250 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000251
kwiberg27f982b2016-03-01 11:52:33 -0800252 std::unique_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000253 test::FrameGenerator::CreateChromaGenerator(
stefanff483612015-12-21 03:14:00 -0800254 video_encoder_config_.streams[0].width,
255 video_encoder_config_.streams[0].height));
256 video_send_stream_->Input()->IncomingCapturedFrame(
257 *frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000258
Peter Boström5811a392015-12-10 13:02:50 +0100259 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000260 << "Timed out while waiting for the frame to render.";
261
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000262 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000263
264 sender_transport.StopSending();
265 receiver_transport.StopSending();
266
267 DestroyStreams();
268}
269
Perba7dc722016-04-19 15:01:23 +0200270class CodecObserver : public test::EndToEndTest,
nisse7ade7b32016-03-23 04:48:10 -0700271 public rtc::VideoSinkInterface<VideoFrame> {
Perba7dc722016-04-19 15:01:23 +0200272 public:
273 CodecObserver(int no_frames_to_wait_for,
274 VideoRotation rotation_to_test,
275 const std::string& payload_name,
276 webrtc::VideoEncoder* encoder,
277 webrtc::VideoDecoder* decoder)
278 : EndToEndTest(2 * webrtc::EndToEndTest::kDefaultTimeoutMs),
279 no_frames_to_wait_for_(no_frames_to_wait_for),
280 expected_rotation_(rotation_to_test),
281 payload_name_(payload_name),
282 encoder_(encoder),
283 decoder_(decoder),
284 frame_counter_(0) {}
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000285
Perba7dc722016-04-19 15:01:23 +0200286 void PerformTest() override {
287 EXPECT_TRUE(Wait())
288 << "Timed out while waiting for enough frames to be decoded.";
289 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000290
Perba7dc722016-04-19 15:01:23 +0200291 void ModifyVideoConfigs(
292 VideoSendStream::Config* send_config,
293 std::vector<VideoReceiveStream::Config>* receive_configs,
294 VideoEncoderConfig* encoder_config) override {
295 send_config->encoder_settings.encoder = encoder_.get();
296 send_config->encoder_settings.payload_name = payload_name_;
297 send_config->encoder_settings.payload_type = 126;
298 encoder_config->streams[0].min_bitrate_bps = 50000;
299 encoder_config->streams[0].target_bitrate_bps =
300 encoder_config->streams[0].max_bitrate_bps = 2000000;
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000301
Perba7dc722016-04-19 15:01:23 +0200302 (*receive_configs)[0].renderer = this;
303 (*receive_configs)[0].decoders.resize(1);
304 (*receive_configs)[0].decoders[0].payload_type =
305 send_config->encoder_settings.payload_type;
306 (*receive_configs)[0].decoders[0].payload_name =
307 send_config->encoder_settings.payload_name;
308 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
309 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000310
Perba7dc722016-04-19 15:01:23 +0200311 void OnFrame(const VideoFrame& video_frame) override {
312 EXPECT_EQ(expected_rotation_, video_frame.rotation());
313 if (++frame_counter_ == no_frames_to_wait_for_)
314 observation_complete_.Set();
315 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000316
Perba7dc722016-04-19 15:01:23 +0200317 void OnFrameGeneratorCapturerCreated(
318 test::FrameGeneratorCapturer* frame_generator_capturer) override {
319 frame_generator_capturer->SetFakeRotation(expected_rotation_);
320 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000321
Perba7dc722016-04-19 15:01:23 +0200322 private:
323 int no_frames_to_wait_for_;
324 VideoRotation expected_rotation_;
325 std::string payload_name_;
326 std::unique_ptr<webrtc::VideoEncoder> encoder_;
327 std::unique_ptr<webrtc::VideoDecoder> decoder_;
328 int frame_counter_;
329};
330
331TEST_F(EndToEndTest, SendsAndReceivesVP8Rotation90) {
332 CodecObserver test(5, kVideoRotation_90, "VP8",
333 VideoEncoder::Create(VideoEncoder::kVp8),
334 VP8Decoder::Create());
335 RunBaseTest(&test);
336}
337
Peter Boström12996152016-05-14 02:03:18 +0200338#if !defined(RTC_DISABLE_VP9)
Perba7dc722016-04-19 15:01:23 +0200339TEST_F(EndToEndTest, SendsAndReceivesVP9) {
340 CodecObserver test(500, kVideoRotation_0, "VP9",
341 VideoEncoder::Create(VideoEncoder::kVp9),
342 VP9Decoder::Create());
343 RunBaseTest(&test);
344}
345
346TEST_F(EndToEndTest, SendsAndReceivesVP9VideoRotation90) {
347 CodecObserver test(5, kVideoRotation_90, "VP9",
348 VideoEncoder::Create(VideoEncoder::kVp9),
349 VP9Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800350 RunBaseTest(&test);
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000351}
Peter Boström12996152016-05-14 02:03:18 +0200352#endif // !defined(RTC_DISABLE_VP9)
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000353
hbosbab934b2016-01-27 01:36:03 -0800354#if defined(WEBRTC_END_TO_END_H264_TESTS)
355
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000356TEST_F(EndToEndTest, SendsAndReceivesH264) {
Perba7dc722016-04-19 15:01:23 +0200357 CodecObserver test(500, kVideoRotation_0, "H264",
358 VideoEncoder::Create(VideoEncoder::kH264),
359 H264Decoder::Create());
360 RunBaseTest(&test);
361}
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000362
Perba7dc722016-04-19 15:01:23 +0200363TEST_F(EndToEndTest, SendsAndReceivesH264VideoRotation90) {
364 CodecObserver test(5, kVideoRotation_90, "H264",
365 VideoEncoder::Create(VideoEncoder::kH264),
366 H264Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800367 RunBaseTest(&test);
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000368}
369
hbosbab934b2016-01-27 01:36:03 -0800370#endif // defined(WEBRTC_END_TO_END_H264_TESTS)
371
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000372TEST_F(EndToEndTest, ReceiverUsesLocalSsrc) {
373 class SyncRtcpObserver : public test::EndToEndTest {
374 public:
375 SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {}
376
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000377 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000378 RTCPUtility::RTCPParserV2 parser(packet, length, true);
379 EXPECT_TRUE(parser.IsValid());
380 uint32_t ssrc = 0;
381 ssrc |= static_cast<uint32_t>(packet[4]) << 24;
382 ssrc |= static_cast<uint32_t>(packet[5]) << 16;
383 ssrc |= static_cast<uint32_t>(packet[6]) << 8;
384 ssrc |= static_cast<uint32_t>(packet[7]) << 0;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100385 EXPECT_EQ(kReceiverLocalVideoSsrc, ssrc);
Peter Boström5811a392015-12-10 13:02:50 +0100386 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000387
388 return SEND_PACKET;
389 }
390
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000391 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100392 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000393 << "Timed out while waiting for a receiver RTCP packet to be sent.";
394 }
395 } test;
396
stefane74eef12016-01-08 06:47:13 -0800397 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000398}
399
400TEST_F(EndToEndTest, ReceivesAndRetransmitsNack) {
401 static const int kNumberOfNacksToObserve = 2;
402 static const int kLossBurstSize = 2;
403 static const int kPacketsBetweenLossBursts = 9;
404 class NackObserver : public test::EndToEndTest {
405 public:
406 NackObserver()
407 : EndToEndTest(kLongTimeoutMs),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000408 sent_rtp_packets_(0),
409 packets_left_to_drop_(0),
410 nacks_left_(kNumberOfNacksToObserve) {}
411
412 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000413 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700414 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000415 RTPHeader header;
Peter Boström03671cb2015-12-07 15:22:24 +0100416 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000417
418 // Never drop retransmitted packets.
419 if (dropped_packets_.find(header.sequenceNumber) !=
420 dropped_packets_.end()) {
421 retransmitted_packets_.insert(header.sequenceNumber);
Stefan Holmer586b19b2015-09-18 11:14:31 +0200422 if (nacks_left_ <= 0 &&
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000423 retransmitted_packets_.size() == dropped_packets_.size()) {
Peter Boström5811a392015-12-10 13:02:50 +0100424 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000425 }
426 return SEND_PACKET;
427 }
428
429 ++sent_rtp_packets_;
430
431 // Enough NACKs received, stop dropping packets.
Stefan Holmer586b19b2015-09-18 11:14:31 +0200432 if (nacks_left_ <= 0)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000433 return SEND_PACKET;
434
435 // Check if it's time for a new loss burst.
436 if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
437 packets_left_to_drop_ = kLossBurstSize;
438
Stefan Holmer01b48882015-05-05 10:21:24 +0200439 // Never drop padding packets as those won't be retransmitted.
440 if (packets_left_to_drop_ > 0 && header.paddingLength == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000441 --packets_left_to_drop_;
442 dropped_packets_.insert(header.sequenceNumber);
443 return DROP_PACKET;
444 }
445
446 return SEND_PACKET;
447 }
448
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000449 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700450 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000451 RTCPUtility::RTCPParserV2 parser(packet, length, true);
452 EXPECT_TRUE(parser.IsValid());
453
454 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +0200455 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
456 if (packet_type == RTCPUtility::RTCPPacketTypes::kRtpfbNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000457 --nacks_left_;
458 break;
459 }
460 packet_type = parser.Iterate();
461 }
462 return SEND_PACKET;
463 }
464
stefanff483612015-12-21 03:14:00 -0800465 void ModifyVideoConfigs(
466 VideoSendStream::Config* send_config,
467 std::vector<VideoReceiveStream::Config>* receive_configs,
468 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000469 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000470 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000471 }
472
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000473 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100474 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000475 << "Timed out waiting for packets to be NACKed, retransmitted and "
476 "rendered.";
477 }
478
stefanf116bd02015-10-27 08:29:42 -0700479 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000480 std::set<uint16_t> dropped_packets_;
481 std::set<uint16_t> retransmitted_packets_;
482 uint64_t sent_rtp_packets_;
483 int packets_left_to_drop_;
stefanf116bd02015-10-27 08:29:42 -0700484 int nacks_left_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000485 } test;
486
stefane74eef12016-01-08 06:47:13 -0800487 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000488}
489
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000490TEST_F(EndToEndTest, CanReceiveFec) {
nisse7ade7b32016-03-23 04:48:10 -0700491 class FecRenderObserver : public test::EndToEndTest,
492 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000493 public:
494 FecRenderObserver()
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000495 : EndToEndTest(kDefaultTimeoutMs), state_(kFirstPacket) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000496
497 private:
stefanf116bd02015-10-27 08:29:42 -0700498 Action OnSendRtp(const uint8_t* packet, size_t length) override {
499 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000500 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000501 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000502
Stefan Holmer01b48882015-05-05 10:21:24 +0200503 int encapsulated_payload_type = -1;
504 if (header.payloadType == kRedPayloadType) {
505 encapsulated_payload_type =
506 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100507 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200508 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
509 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100510 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200511 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000512
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000513 if (protected_sequence_numbers_.count(header.sequenceNumber) != 0) {
514 // Retransmitted packet, should not count.
515 protected_sequence_numbers_.erase(header.sequenceNumber);
516 EXPECT_GT(protected_timestamps_.count(header.timestamp), 0u);
517 protected_timestamps_.erase(header.timestamp);
518 return SEND_PACKET;
519 }
520
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000521 switch (state_) {
522 case kFirstPacket:
523 state_ = kDropEveryOtherPacketUntilFec;
524 break;
525 case kDropEveryOtherPacketUntilFec:
526 if (encapsulated_payload_type == kUlpfecPayloadType) {
527 state_ = kDropNextMediaPacket;
528 return SEND_PACKET;
529 }
530 if (header.sequenceNumber % 2 == 0)
531 return DROP_PACKET;
532 break;
533 case kDropNextMediaPacket:
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100534 if (encapsulated_payload_type == kFakeVideoSendPayloadType) {
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000535 protected_sequence_numbers_.insert(header.sequenceNumber);
536 protected_timestamps_.insert(header.timestamp);
537 state_ = kDropEveryOtherPacketUntilFec;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000538 return DROP_PACKET;
539 }
540 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000541 }
542
543 return SEND_PACKET;
544 }
545
nisseeb83a1a2016-03-21 01:27:56 -0700546 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200547 rtc::CritScope lock(&crit_);
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000548 // Rendering frame with timestamp of packet that was dropped -> FEC
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000549 // protection worked.
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000550 if (protected_timestamps_.count(video_frame.timestamp()) != 0)
Peter Boström5811a392015-12-10 13:02:50 +0100551 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000552 }
553
554 enum {
555 kFirstPacket,
556 kDropEveryOtherPacketUntilFec,
557 kDropNextMediaPacket,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000558 } state_;
559
stefanff483612015-12-21 03:14:00 -0800560 void ModifyVideoConfigs(
561 VideoSendStream::Config* send_config,
562 std::vector<VideoReceiveStream::Config>* receive_configs,
563 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000564 // TODO(pbos): Run this test with combined NACK/FEC enabled as well.
565 // int rtp_history_ms = 1000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000566 // (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000567 // send_config->rtp.nack.rtp_history_ms = rtp_history_ms;
568 send_config->rtp.fec.red_payload_type = kRedPayloadType;
569 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
570
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000571 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
572 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
573 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000574 }
575
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000576 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100577 EXPECT_TRUE(Wait())
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000578 << "Timed out waiting for dropped frames frames to be rendered.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000579 }
580
stefanf116bd02015-10-27 08:29:42 -0700581 rtc::CriticalSection crit_;
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000582 std::set<uint32_t> protected_sequence_numbers_ GUARDED_BY(crit_);
583 std::set<uint32_t> protected_timestamps_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000584 } test;
585
stefane74eef12016-01-08 06:47:13 -0800586 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000587}
588
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200589TEST_F(EndToEndTest, ReceivedFecPacketsNotNacked) {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000590 class FecNackObserver : public test::EndToEndTest {
591 public:
mflodmand1590b22015-12-09 07:07:59 -0800592 FecNackObserver()
stefanf116bd02015-10-27 08:29:42 -0700593 : EndToEndTest(kDefaultTimeoutMs),
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000594 state_(kFirstPacket),
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000595 fec_sequence_number_(0),
596 has_last_sequence_number_(false),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200597 last_sequence_number_(0),
598 encoder_(VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)),
599 decoder_(VP8Decoder::Create()) {}
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000600
601 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000602 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800603 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000604 RTPHeader header;
605 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000606
Stefan Holmer01b48882015-05-05 10:21:24 +0200607 int encapsulated_payload_type = -1;
608 if (header.payloadType == kRedPayloadType) {
609 encapsulated_payload_type =
610 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100611 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200612 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
613 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100614 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200615 }
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000616
617 if (has_last_sequence_number_ &&
618 !IsNewerSequenceNumber(header.sequenceNumber,
619 last_sequence_number_)) {
620 // Drop retransmitted packets.
621 return DROP_PACKET;
622 }
623 last_sequence_number_ = header.sequenceNumber;
624 has_last_sequence_number_ = true;
625
626 bool fec_packet = encapsulated_payload_type == kUlpfecPayloadType;
627 switch (state_) {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000628 case kFirstPacket:
629 state_ = kDropEveryOtherPacketUntilFec;
630 break;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000631 case kDropEveryOtherPacketUntilFec:
632 if (fec_packet) {
633 state_ = kDropAllMediaPacketsUntilFec;
634 } else if (header.sequenceNumber % 2 == 0) {
635 return DROP_PACKET;
636 }
637 break;
638 case kDropAllMediaPacketsUntilFec:
639 if (!fec_packet)
640 return DROP_PACKET;
641 fec_sequence_number_ = header.sequenceNumber;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200642 state_ = kDropOneMediaPacket;
643 break;
644 case kDropOneMediaPacket:
645 if (fec_packet)
646 return DROP_PACKET;
647 state_ = kPassOneMediaPacket;
648 return DROP_PACKET;
649 break;
650 case kPassOneMediaPacket:
651 if (fec_packet)
652 return DROP_PACKET;
653 // Pass one media packet after dropped packet after last FEC,
654 // otherwise receiver might never see a seq_no after
655 // |fec_sequence_number_|
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000656 state_ = kVerifyFecPacketNotInNackList;
657 break;
658 case kVerifyFecPacketNotInNackList:
659 // Continue to drop packets. Make sure no frame can be decoded.
660 if (fec_packet || header.sequenceNumber % 2 == 0)
661 return DROP_PACKET;
662 break;
663 }
664 return SEND_PACKET;
665 }
666
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000667 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800668 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000669 if (state_ == kVerifyFecPacketNotInNackList) {
670 test::RtcpPacketParser rtcp_parser;
671 rtcp_parser.Parse(packet, length);
672 std::vector<uint16_t> nacks = rtcp_parser.nack_item()->last_nack_list();
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200673 EXPECT_TRUE(std::find(nacks.begin(), nacks.end(),
674 fec_sequence_number_) == nacks.end())
675 << "Got nack for FEC packet";
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000676 if (!nacks.empty() &&
677 IsNewerSequenceNumber(nacks.back(), fec_sequence_number_)) {
Peter Boström5811a392015-12-10 13:02:50 +0100678 observation_complete_.Set();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000679 }
680 }
681 return SEND_PACKET;
682 }
683
stefane74eef12016-01-08 06:47:13 -0800684 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
685 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
686 // Configure some network delay.
687 const int kNetworkDelayMs = 50;
688 FakeNetworkPipe::Config config;
689 config.queue_delay_ms = kNetworkDelayMs;
690 return new test::PacketTransport(sender_call, this,
691 test::PacketTransport::kSender, config);
692 }
693
Stefan Holmere5904162015-03-26 11:11:06 +0100694 // TODO(holmer): Investigate why we don't send FEC packets when the bitrate
695 // is 10 kbps.
696 Call::Config GetSenderCallConfig() override {
solenberg4fbae2b2015-08-28 04:07:10 -0700697 Call::Config config;
Stefan Holmere5904162015-03-26 11:11:06 +0100698 const int kMinBitrateBps = 30000;
699 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
700 return config;
701 }
702
stefanff483612015-12-21 03:14:00 -0800703 void ModifyVideoConfigs(
704 VideoSendStream::Config* send_config,
705 std::vector<VideoReceiveStream::Config>* receive_configs,
706 VideoEncoderConfig* encoder_config) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000707 // Configure hybrid NACK/FEC.
708 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
709 send_config->rtp.fec.red_payload_type = kRedPayloadType;
710 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200711 // Set codec to VP8, otherwise NACK/FEC hybrid will be disabled.
712 send_config->encoder_settings.encoder = encoder_.get();
713 send_config->encoder_settings.payload_name = "VP8";
714 send_config->encoder_settings.payload_type = kFakeVideoSendPayloadType;
715 encoder_config->streams[0].min_bitrate_bps = 50000;
716 encoder_config->streams[0].max_bitrate_bps =
717 encoder_config->streams[0].target_bitrate_bps = 2000000;
718
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000719 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
720 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
721 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200722
723 (*receive_configs)[0].decoders.resize(1);
724 (*receive_configs)[0].decoders[0].payload_type =
725 send_config->encoder_settings.payload_type;
726 (*receive_configs)[0].decoders[0].payload_name =
727 send_config->encoder_settings.payload_name;
728 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000729 }
730
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000731 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100732 EXPECT_TRUE(Wait())
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000733 << "Timed out while waiting for FEC packets to be received.";
734 }
735
736 enum {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000737 kFirstPacket,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000738 kDropEveryOtherPacketUntilFec,
739 kDropAllMediaPacketsUntilFec,
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200740 kDropOneMediaPacket,
741 kPassOneMediaPacket,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000742 kVerifyFecPacketNotInNackList,
743 } state_;
744
stefan608213e2015-11-01 14:56:10 -0800745 rtc::CriticalSection crit_;
746 uint16_t fec_sequence_number_ GUARDED_BY(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000747 bool has_last_sequence_number_;
748 uint16_t last_sequence_number_;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200749 std::unique_ptr<webrtc::VideoEncoder> encoder_;
750 std::unique_ptr<webrtc::VideoDecoder> decoder_;
stefanf116bd02015-10-27 08:29:42 -0700751 } test;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000752
stefane74eef12016-01-08 06:47:13 -0800753 RunBaseTest(&test);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000754}
755
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000756// This test drops second RTP packet with a marker bit set, makes sure it's
757// retransmitted and renders. Retransmission SSRCs are also checked.
Peter Boström39593972016-02-15 11:27:15 +0100758void EndToEndTest::DecodesRetransmittedFrame(bool enable_rtx, bool enable_red) {
Peter Boström67680c12016-02-17 11:10:04 +0100759 static const int kDroppedFrameNumber = 10;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000760 class RetransmissionObserver : public test::EndToEndTest,
761 public I420FrameCallback {
762 public:
Peter Boström39593972016-02-15 11:27:15 +0100763 RetransmissionObserver(bool enable_rtx, bool enable_red)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000764 : EndToEndTest(kDefaultTimeoutMs),
Peter Boström39593972016-02-15 11:27:15 +0100765 payload_type_(GetPayloadType(false, enable_red)),
766 retransmission_ssrc_(enable_rtx ? kSendRtxSsrcs[0]
767 : kVideoSendSsrcs[0]),
768 retransmission_payload_type_(GetPayloadType(enable_rtx, enable_red)),
769 encoder_(VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000770 marker_bits_observed_(0),
771 retransmitted_timestamp_(0),
772 frame_retransmitted_(false) {}
773
774 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000775 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700776 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000777 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000778 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000779
Peter Boström67680c12016-02-17 11:10:04 +0100780 // Ignore padding-only packets over RTX.
781 if (header.payloadType != payload_type_) {
782 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
783 if (length == header.headerLength + header.paddingLength)
784 return SEND_PACKET;
Stefan Holmer586b19b2015-09-18 11:14:31 +0200785 }
Peter Boström67680c12016-02-17 11:10:04 +0100786
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000787 if (header.timestamp == retransmitted_timestamp_) {
788 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
789 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
790 frame_retransmitted_ = true;
791 return SEND_PACKET;
792 }
793
Stefan Holmer586b19b2015-09-18 11:14:31 +0200794 // Found the final packet of the frame to inflict loss to, drop this and
795 // expect a retransmission.
danilchapfdd381c2016-07-25 04:03:20 -0700796 if (header.payloadType == payload_type_ && header.markerBit &&
797 ++marker_bits_observed_ == kDroppedFrameNumber) {
Danil Chapovalov18c65a42016-06-29 15:29:34 +0200798 // This should be the only dropped packet.
799 EXPECT_EQ(0u, retransmitted_timestamp_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000800 retransmitted_timestamp_ = header.timestamp;
801 return DROP_PACKET;
802 }
803
804 return SEND_PACKET;
805 }
806
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700807 void FrameCallback(VideoFrame* frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200808 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000809 if (frame->timestamp() == retransmitted_timestamp_) {
810 EXPECT_TRUE(frame_retransmitted_);
Peter Boström5811a392015-12-10 13:02:50 +0100811 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000812 }
813 }
814
stefanff483612015-12-21 03:14:00 -0800815 void ModifyVideoConfigs(
816 VideoSendStream::Config* send_config,
817 std::vector<VideoReceiveStream::Config>* receive_configs,
818 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000819 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000820 (*receive_configs)[0].pre_render_callback = this;
821 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
Shao Changbine62202f2015-04-21 20:24:50 +0800822
823 if (payload_type_ == kRedPayloadType) {
824 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
825 send_config->rtp.fec.red_payload_type = kRedPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +0100826 if (retransmission_ssrc_ == kSendRtxSsrcs[0])
827 send_config->rtp.fec.red_rtx_payload_type = kRtxRedPayloadType;
828 (*receive_configs)[0].rtp.fec.ulpfec_payload_type =
829 send_config->rtp.fec.ulpfec_payload_type;
830 (*receive_configs)[0].rtp.fec.red_payload_type =
831 send_config->rtp.fec.red_payload_type;
832 (*receive_configs)[0].rtp.fec.red_rtx_payload_type =
833 send_config->rtp.fec.red_rtx_payload_type;
Shao Changbine62202f2015-04-21 20:24:50 +0800834 }
835
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000836 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
837 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000838 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +0100839 (*receive_configs)[0].rtp.rtx[payload_type_].ssrc = kSendRtxSsrcs[0];
840 (*receive_configs)[0].rtp.rtx[payload_type_].payload_type =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000841 kSendRtxPayloadType;
842 }
Peter Boström39593972016-02-15 11:27:15 +0100843 // Configure encoding and decoding with VP8, since generic packetization
844 // doesn't support FEC with NACK.
845 RTC_DCHECK_EQ(1u, (*receive_configs)[0].decoders.size());
846 send_config->encoder_settings.encoder = encoder_.get();
847 send_config->encoder_settings.payload_name = "VP8";
848 (*receive_configs)[0].decoders[0].payload_name = "VP8";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000849 }
850
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000851 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100852 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000853 << "Timed out while waiting for retransmission to render.";
854 }
855
Shao Changbine62202f2015-04-21 20:24:50 +0800856 int GetPayloadType(bool use_rtx, bool use_red) {
Stefan Holmer10880012016-02-03 13:29:59 +0100857 if (use_red) {
858 if (use_rtx)
859 return kRtxRedPayloadType;
860 return kRedPayloadType;
861 }
862 if (use_rtx)
863 return kSendRtxPayloadType;
864 return kFakeVideoSendPayloadType;
Shao Changbine62202f2015-04-21 20:24:50 +0800865 }
866
stefanf116bd02015-10-27 08:29:42 -0700867 rtc::CriticalSection crit_;
Shao Changbine62202f2015-04-21 20:24:50 +0800868 const int payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000869 const uint32_t retransmission_ssrc_;
870 const int retransmission_payload_type_;
kwiberg27f982b2016-03-01 11:52:33 -0800871 std::unique_ptr<VideoEncoder> encoder_;
Peter Boström39593972016-02-15 11:27:15 +0100872 const std::string payload_name_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000873 int marker_bits_observed_;
stefanf116bd02015-10-27 08:29:42 -0700874 uint32_t retransmitted_timestamp_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000875 bool frame_retransmitted_;
Peter Boström39593972016-02-15 11:27:15 +0100876 } test(enable_rtx, enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000877
stefane74eef12016-01-08 06:47:13 -0800878 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000879}
880
881TEST_F(EndToEndTest, DecodesRetransmittedFrame) {
Shao Changbine62202f2015-04-21 20:24:50 +0800882 DecodesRetransmittedFrame(false, false);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000883}
884
885TEST_F(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +0800886 DecodesRetransmittedFrame(true, false);
887}
888
889TEST_F(EndToEndTest, DecodesRetransmittedFrameByRed) {
890 DecodesRetransmittedFrame(false, true);
891}
892
893TEST_F(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
894 DecodesRetransmittedFrame(true, true);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000895}
896
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000897void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
898 static const int kPacketsToDrop = 1;
899
nisse7ade7b32016-03-23 04:48:10 -0700900 class PliObserver : public test::EndToEndTest,
901 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000902 public:
903 explicit PliObserver(int rtp_history_ms)
904 : EndToEndTest(kLongTimeoutMs),
905 rtp_history_ms_(rtp_history_ms),
906 nack_enabled_(rtp_history_ms > 0),
907 highest_dropped_timestamp_(0),
908 frames_to_drop_(0),
909 received_pli_(false) {}
910
911 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000912 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700913 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000914 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000915 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000916
917 // Drop all retransmitted packets to force a PLI.
918 if (header.timestamp <= highest_dropped_timestamp_)
919 return DROP_PACKET;
920
921 if (frames_to_drop_ > 0) {
922 highest_dropped_timestamp_ = header.timestamp;
923 --frames_to_drop_;
924 return DROP_PACKET;
925 }
926
927 return SEND_PACKET;
928 }
929
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000930 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700931 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000932 RTCPUtility::RTCPParserV2 parser(packet, length, true);
933 EXPECT_TRUE(parser.IsValid());
934
935 for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +0200936 packet_type != RTCPUtility::RTCPPacketTypes::kInvalid;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000937 packet_type = parser.Iterate()) {
938 if (!nack_enabled_)
Erik Språng242e22b2015-05-11 10:17:43 +0200939 EXPECT_NE(packet_type, RTCPUtility::RTCPPacketTypes::kRtpfbNack);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000940
Erik Språng242e22b2015-05-11 10:17:43 +0200941 if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbPli) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000942 received_pli_ = true;
943 break;
944 }
945 }
946 return SEND_PACKET;
947 }
948
nisseeb83a1a2016-03-21 01:27:56 -0700949 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200950 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000951 if (received_pli_ &&
952 video_frame.timestamp() > highest_dropped_timestamp_) {
Peter Boström5811a392015-12-10 13:02:50 +0100953 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000954 }
955 if (!received_pli_)
956 frames_to_drop_ = kPacketsToDrop;
957 }
958
stefanff483612015-12-21 03:14:00 -0800959 void ModifyVideoConfigs(
960 VideoSendStream::Config* send_config,
961 std::vector<VideoReceiveStream::Config>* receive_configs,
962 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000963 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000964 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
965 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000966 }
967
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000968 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100969 EXPECT_TRUE(Wait()) << "Timed out waiting for PLI to be "
970 "received and a frame to be "
971 "rendered afterwards.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000972 }
973
stefanf116bd02015-10-27 08:29:42 -0700974 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000975 int rtp_history_ms_;
976 bool nack_enabled_;
stefanf116bd02015-10-27 08:29:42 -0700977 uint32_t highest_dropped_timestamp_ GUARDED_BY(&crit_);
978 int frames_to_drop_ GUARDED_BY(&crit_);
979 bool received_pli_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000980 } test(rtp_history_ms);
981
stefane74eef12016-01-08 06:47:13 -0800982 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000983}
984
985TEST_F(EndToEndTest, ReceivesPliAndRecoversWithNack) {
986 ReceivesPliAndRecovers(1000);
987}
988
jbauchdb81ffd2015-11-23 03:59:02 -0800989TEST_F(EndToEndTest, ReceivesPliAndRecoversWithoutNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000990 ReceivesPliAndRecovers(0);
991}
992
993TEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
994 class PacketInputObserver : public PacketReceiver {
995 public:
996 explicit PacketInputObserver(PacketReceiver* receiver)
Peter Boström5811a392015-12-10 13:02:50 +0100997 : receiver_(receiver), delivered_packet_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000998
Peter Boström5811a392015-12-10 13:02:50 +0100999 bool Wait() { return delivered_packet_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001000
1001 private:
stefan68786d22015-09-08 05:36:15 -07001002 DeliveryStatus DeliverPacket(MediaType media_type,
1003 const uint8_t* packet,
1004 size_t length,
1005 const PacketTime& packet_time) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001006 if (RtpHeaderParser::IsRtcp(packet, length)) {
stefan68786d22015-09-08 05:36:15 -07001007 return receiver_->DeliverPacket(media_type, packet, length,
1008 packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001009 } else {
1010 DeliveryStatus delivery_status =
stefan68786d22015-09-08 05:36:15 -07001011 receiver_->DeliverPacket(media_type, packet, length, packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001012 EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
Peter Boström5811a392015-12-10 13:02:50 +01001013 delivered_packet_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001014 return delivery_status;
1015 }
1016 }
1017
1018 PacketReceiver* receiver_;
Peter Boström5811a392015-12-10 13:02:50 +01001019 rtc::Event delivered_packet_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001020 };
1021
solenberg4fbae2b2015-08-28 04:07:10 -07001022 CreateCalls(Call::Config(), Call::Config());
1023
stefanf116bd02015-10-27 08:29:42 -07001024 test::DirectTransport send_transport(sender_call_.get());
1025 test::DirectTransport receive_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001026 PacketInputObserver input_observer(receiver_call_->Receiver());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001027 send_transport.SetReceiver(&input_observer);
1028 receive_transport.SetReceiver(sender_call_->Receiver());
1029
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001030 CreateSendConfig(1, 0, &send_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001031 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001032
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001033 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001034 CreateFrameGeneratorCapturer();
1035 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001036
stefanff483612015-12-21 03:14:00 -08001037 receiver_call_->DestroyVideoReceiveStream(video_receive_streams_[0]);
1038 video_receive_streams_.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001039
1040 // Wait() waits for a received packet.
Peter Boström5811a392015-12-10 13:02:50 +01001041 EXPECT_TRUE(input_observer.Wait());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001042
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001043 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001044
1045 DestroyStreams();
1046
1047 send_transport.StopSending();
1048 receive_transport.StopSending();
1049}
1050
pbosda903ea2015-10-02 02:36:56 -07001051void EndToEndTest::RespectsRtcpMode(RtcpMode rtcp_mode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001052 static const int kNumCompoundRtcpPacketsToObserve = 10;
1053 class RtcpModeObserver : public test::EndToEndTest {
1054 public:
pbosda903ea2015-10-02 02:36:56 -07001055 explicit RtcpModeObserver(RtcpMode rtcp_mode)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001056 : EndToEndTest(kDefaultTimeoutMs),
1057 rtcp_mode_(rtcp_mode),
1058 sent_rtp_(0),
1059 sent_rtcp_(0) {}
1060
1061 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001062 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001063 if (++sent_rtp_ % 3 == 0)
1064 return DROP_PACKET;
1065
1066 return SEND_PACKET;
1067 }
1068
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001069 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001070 ++sent_rtcp_;
1071 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1072 EXPECT_TRUE(parser.IsValid());
1073
1074 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1075 bool has_report_block = false;
Erik Språng242e22b2015-05-11 10:17:43 +02001076 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1077 EXPECT_NE(RTCPUtility::RTCPPacketTypes::kSr, packet_type);
1078 if (packet_type == RTCPUtility::RTCPPacketTypes::kRr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001079 has_report_block = true;
1080 break;
1081 }
1082 packet_type = parser.Iterate();
1083 }
1084
1085 switch (rtcp_mode_) {
pbosda903ea2015-10-02 02:36:56 -07001086 case RtcpMode::kCompound:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001087 if (!has_report_block) {
1088 ADD_FAILURE() << "Received RTCP packet without receiver report for "
pbosda903ea2015-10-02 02:36:56 -07001089 "RtcpMode::kCompound.";
Peter Boström5811a392015-12-10 13:02:50 +01001090 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001091 }
1092
1093 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
Peter Boström5811a392015-12-10 13:02:50 +01001094 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001095
1096 break;
pbosda903ea2015-10-02 02:36:56 -07001097 case RtcpMode::kReducedSize:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001098 if (!has_report_block)
Peter Boström5811a392015-12-10 13:02:50 +01001099 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001100 break;
pbosda903ea2015-10-02 02:36:56 -07001101 case RtcpMode::kOff:
1102 RTC_NOTREACHED();
1103 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001104 }
1105
1106 return SEND_PACKET;
1107 }
1108
stefanff483612015-12-21 03:14:00 -08001109 void ModifyVideoConfigs(
1110 VideoSendStream::Config* send_config,
1111 std::vector<VideoReceiveStream::Config>* receive_configs,
1112 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001113 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001114 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1115 (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001116 }
1117
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001118 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001119 EXPECT_TRUE(Wait())
pbosda903ea2015-10-02 02:36:56 -07001120 << (rtcp_mode_ == RtcpMode::kCompound
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001121 ? "Timed out before observing enough compound packets."
1122 : "Timed out before receiving a non-compound RTCP packet.");
1123 }
1124
pbosda903ea2015-10-02 02:36:56 -07001125 RtcpMode rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001126 int sent_rtp_;
1127 int sent_rtcp_;
1128 } test(rtcp_mode);
1129
stefane74eef12016-01-08 06:47:13 -08001130 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001131}
1132
1133TEST_F(EndToEndTest, UsesRtcpCompoundMode) {
pbosda903ea2015-10-02 02:36:56 -07001134 RespectsRtcpMode(RtcpMode::kCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001135}
1136
1137TEST_F(EndToEndTest, UsesRtcpReducedSizeMode) {
pbosda903ea2015-10-02 02:36:56 -07001138 RespectsRtcpMode(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001139}
1140
1141// Test sets up a Call multiple senders with different resolutions and SSRCs.
1142// Another is set up to receive all three of these with different renderers.
sprang867fb522015-08-03 04:38:41 -07001143class MultiStreamTest {
1144 public:
1145 static const size_t kNumStreams = 3;
1146 struct CodecSettings {
1147 uint32_t ssrc;
1148 int width;
1149 int height;
1150 } codec_settings[kNumStreams];
1151
1152 MultiStreamTest() {
1153 // TODO(sprang): Cleanup when msvc supports explicit initializers for array.
1154 codec_settings[0] = {1, 640, 480};
1155 codec_settings[1] = {2, 320, 240};
1156 codec_settings[2] = {3, 240, 160};
1157 }
1158
1159 virtual ~MultiStreamTest() {}
1160
1161 void RunTest() {
kwiberg27f982b2016-03-01 11:52:33 -08001162 std::unique_ptr<Call> sender_call(Call::Create(Call::Config()));
1163 std::unique_ptr<Call> receiver_call(Call::Create(Call::Config()));
1164 std::unique_ptr<test::DirectTransport> sender_transport(
stefanf116bd02015-10-27 08:29:42 -07001165 CreateSendTransport(sender_call.get()));
kwiberg27f982b2016-03-01 11:52:33 -08001166 std::unique_ptr<test::DirectTransport> receiver_transport(
stefanf116bd02015-10-27 08:29:42 -07001167 CreateReceiveTransport(receiver_call.get()));
sprang867fb522015-08-03 04:38:41 -07001168 sender_transport->SetReceiver(receiver_call->Receiver());
1169 receiver_transport->SetReceiver(sender_call->Receiver());
1170
kwiberg27f982b2016-03-01 11:52:33 -08001171 std::unique_ptr<VideoEncoder> encoders[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001172 for (size_t i = 0; i < kNumStreams; ++i)
1173 encoders[i].reset(VideoEncoder::Create(VideoEncoder::kVp8));
1174
1175 VideoSendStream* send_streams[kNumStreams];
1176 VideoReceiveStream* receive_streams[kNumStreams];
1177
1178 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
kwiberg4a206a92016-03-31 10:24:26 -07001179 std::vector<std::unique_ptr<VideoDecoder>> allocated_decoders;
sprang867fb522015-08-03 04:38:41 -07001180 for (size_t i = 0; i < kNumStreams; ++i) {
1181 uint32_t ssrc = codec_settings[i].ssrc;
1182 int width = codec_settings[i].width;
1183 int height = codec_settings[i].height;
1184
solenberg4fbae2b2015-08-28 04:07:10 -07001185 VideoSendStream::Config send_config(sender_transport.get());
sprang867fb522015-08-03 04:38:41 -07001186 send_config.rtp.ssrcs.push_back(ssrc);
1187 send_config.encoder_settings.encoder = encoders[i].get();
1188 send_config.encoder_settings.payload_name = "VP8";
1189 send_config.encoder_settings.payload_type = 124;
1190 VideoEncoderConfig encoder_config;
1191 encoder_config.streams = test::CreateVideoStreams(1);
1192 VideoStream* stream = &encoder_config.streams[0];
1193 stream->width = width;
1194 stream->height = height;
1195 stream->max_framerate = 5;
1196 stream->min_bitrate_bps = stream->target_bitrate_bps =
1197 stream->max_bitrate_bps = 100000;
1198
1199 UpdateSendConfig(i, &send_config, &encoder_config, &frame_generators[i]);
1200
1201 send_streams[i] =
1202 sender_call->CreateVideoSendStream(send_config, encoder_config);
1203 send_streams[i]->Start();
1204
solenberg4fbae2b2015-08-28 04:07:10 -07001205 VideoReceiveStream::Config receive_config(receiver_transport.get());
sprang867fb522015-08-03 04:38:41 -07001206 receive_config.rtp.remote_ssrc = ssrc;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001207 receive_config.rtp.local_ssrc = test::CallTest::kReceiverLocalVideoSsrc;
sprang867fb522015-08-03 04:38:41 -07001208 VideoReceiveStream::Decoder decoder =
1209 test::CreateMatchingDecoder(send_config.encoder_settings);
kwiberg4a206a92016-03-31 10:24:26 -07001210 allocated_decoders.push_back(
1211 std::unique_ptr<VideoDecoder>(decoder.decoder));
sprang867fb522015-08-03 04:38:41 -07001212 receive_config.decoders.push_back(decoder);
1213
1214 UpdateReceiveConfig(i, &receive_config);
1215
1216 receive_streams[i] =
Tommi733b5472016-06-10 17:58:01 +02001217 receiver_call->CreateVideoReceiveStream(std::move(receive_config));
sprang867fb522015-08-03 04:38:41 -07001218 receive_streams[i]->Start();
1219
1220 frame_generators[i] = test::FrameGeneratorCapturer::Create(
1221 send_streams[i]->Input(), width, height, 30,
1222 Clock::GetRealTimeClock());
1223 frame_generators[i]->Start();
1224 }
1225
1226 Wait();
1227
1228 for (size_t i = 0; i < kNumStreams; ++i) {
1229 frame_generators[i]->Stop();
1230 sender_call->DestroyVideoSendStream(send_streams[i]);
1231 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1232 delete frame_generators[i];
1233 }
1234
1235 sender_transport->StopSending();
1236 receiver_transport->StopSending();
1237 }
1238
1239 protected:
1240 virtual void Wait() = 0;
1241 // Note: frame_generator is a point-to-pointer, since the actual instance
1242 // hasn't been created at the time of this call. Only when packets/frames
1243 // start flowing should this be dereferenced.
1244 virtual void UpdateSendConfig(
1245 size_t stream_index,
1246 VideoSendStream::Config* send_config,
1247 VideoEncoderConfig* encoder_config,
1248 test::FrameGeneratorCapturer** frame_generator) {}
1249 virtual void UpdateReceiveConfig(size_t stream_index,
1250 VideoReceiveStream::Config* receive_config) {
1251 }
stefanf116bd02015-10-27 08:29:42 -07001252 virtual test::DirectTransport* CreateSendTransport(Call* sender_call) {
1253 return new test::DirectTransport(sender_call);
sprang867fb522015-08-03 04:38:41 -07001254 }
stefanf116bd02015-10-27 08:29:42 -07001255 virtual test::DirectTransport* CreateReceiveTransport(Call* receiver_call) {
1256 return new test::DirectTransport(receiver_call);
sprang867fb522015-08-03 04:38:41 -07001257 }
1258};
1259
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001260// Each renderer verifies that it receives the expected resolution, and as soon
1261// as every renderer has received a frame, the test finishes.
andresp@webrtc.org02686112014-09-19 08:24:19 +00001262TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) {
nisse7ade7b32016-03-23 04:48:10 -07001263 class VideoOutputObserver : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001264 public:
sprang867fb522015-08-03 04:38:41 -07001265 VideoOutputObserver(const MultiStreamTest::CodecSettings& settings,
1266 uint32_t ssrc,
1267 test::FrameGeneratorCapturer** frame_generator)
1268 : settings_(settings),
1269 ssrc_(ssrc),
1270 frame_generator_(frame_generator),
Peter Boström5811a392015-12-10 13:02:50 +01001271 done_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001272
nisseeb83a1a2016-03-21 01:27:56 -07001273 void OnFrame(const VideoFrame& video_frame) override {
sprang867fb522015-08-03 04:38:41 -07001274 EXPECT_EQ(settings_.width, video_frame.width());
1275 EXPECT_EQ(settings_.height, video_frame.height());
1276 (*frame_generator_)->Stop();
Peter Boström5811a392015-12-10 13:02:50 +01001277 done_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001278 }
1279
sprang867fb522015-08-03 04:38:41 -07001280 uint32_t Ssrc() { return ssrc_; }
1281
Peter Boström5811a392015-12-10 13:02:50 +01001282 bool Wait() { return done_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001283
1284 private:
sprang867fb522015-08-03 04:38:41 -07001285 const MultiStreamTest::CodecSettings& settings_;
1286 const uint32_t ssrc_;
1287 test::FrameGeneratorCapturer** const frame_generator_;
Peter Boström5811a392015-12-10 13:02:50 +01001288 rtc::Event done_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001289 };
1290
sprang867fb522015-08-03 04:38:41 -07001291 class Tester : public MultiStreamTest {
1292 public:
1293 Tester() {}
1294 virtual ~Tester() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001295
sprang867fb522015-08-03 04:38:41 -07001296 protected:
1297 void Wait() override {
1298 for (const auto& observer : observers_) {
Peter Boström5811a392015-12-10 13:02:50 +01001299 EXPECT_TRUE(observer->Wait()) << "Time out waiting for from on ssrc "
1300 << observer->Ssrc();
sprang867fb522015-08-03 04:38:41 -07001301 }
1302 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001303
sprang867fb522015-08-03 04:38:41 -07001304 void UpdateSendConfig(
1305 size_t stream_index,
1306 VideoSendStream::Config* send_config,
1307 VideoEncoderConfig* encoder_config,
1308 test::FrameGeneratorCapturer** frame_generator) override {
1309 observers_[stream_index].reset(new VideoOutputObserver(
1310 codec_settings[stream_index], send_config->rtp.ssrcs.front(),
1311 frame_generator));
1312 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001313
sprang867fb522015-08-03 04:38:41 -07001314 void UpdateReceiveConfig(
1315 size_t stream_index,
1316 VideoReceiveStream::Config* receive_config) override {
1317 receive_config->renderer = observers_[stream_index].get();
1318 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001319
sprang867fb522015-08-03 04:38:41 -07001320 private:
kwiberg27f982b2016-03-01 11:52:33 -08001321 std::unique_ptr<VideoOutputObserver> observers_[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001322 } tester;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001323
sprang867fb522015-08-03 04:38:41 -07001324 tester.RunTest();
1325}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001326
sprang867fb522015-08-03 04:38:41 -07001327TEST_F(EndToEndTest, AssignsTransportSequenceNumbers) {
sprang867fb522015-08-03 04:38:41 -07001328 static const int kExtensionId = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001329
sprang867fb522015-08-03 04:38:41 -07001330 class RtpExtensionHeaderObserver : public test::DirectTransport {
1331 public:
stefanf116bd02015-10-27 08:29:42 -07001332 RtpExtensionHeaderObserver(Call* sender_call,
1333 const uint32_t& first_media_ssrc,
sprang861c55e2015-10-16 10:01:21 -07001334 const std::map<uint32_t, uint32_t>& ssrc_map)
stefanf116bd02015-10-27 08:29:42 -07001335 : DirectTransport(sender_call),
Peter Boström5811a392015-12-10 13:02:50 +01001336 done_(false, false),
sprang867fb522015-08-03 04:38:41 -07001337 parser_(RtpHeaderParser::Create()),
sprang861c55e2015-10-16 10:01:21 -07001338 first_media_ssrc_(first_media_ssrc),
1339 rtx_to_media_ssrcs_(ssrc_map),
sprang867fb522015-08-03 04:38:41 -07001340 padding_observed_(false),
sprang861c55e2015-10-16 10:01:21 -07001341 rtx_padding_observed_(false),
1342 retransmit_observed_(false),
1343 started_(false) {
sprang867fb522015-08-03 04:38:41 -07001344 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
1345 kExtensionId);
1346 }
1347 virtual ~RtpExtensionHeaderObserver() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001348
stefan1d8a5062015-10-02 03:39:33 -07001349 bool SendRtp(const uint8_t* data,
1350 size_t length,
1351 const PacketOptions& options) override {
sprang861c55e2015-10-16 10:01:21 -07001352 {
1353 rtc::CritScope cs(&lock_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001354
Erik Språng8d629712015-08-04 16:24:03 +02001355 if (IsDone())
sprang861c55e2015-10-16 10:01:21 -07001356 return false;
1357
1358 if (started_) {
1359 RTPHeader header;
1360 EXPECT_TRUE(parser_->Parse(data, length, &header));
1361 bool drop_packet = false;
1362
1363 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
1364 EXPECT_EQ(options.packet_id,
1365 header.extension.transportSequenceNumber);
1366 if (!streams_observed_.empty()) {
1367 // Unwrap packet id and verify uniqueness.
1368 int64_t packet_id = unwrapper_.Unwrap(options.packet_id);
1369 EXPECT_TRUE(received_packed_ids_.insert(packet_id).second);
1370 }
1371
1372 // Drop (up to) every 17th packet, so we get retransmits.
1373 // Only drop media, and not on the first stream (otherwise it will be
1374 // hard to distinguish from padding, which is always sent on the first
1375 // stream).
1376 if (header.payloadType != kSendRtxPayloadType &&
1377 header.ssrc != first_media_ssrc_ &&
1378 header.extension.transportSequenceNumber % 17 == 0) {
1379 dropped_seq_[header.ssrc].insert(header.sequenceNumber);
1380 drop_packet = true;
1381 }
1382
1383 size_t payload_length =
1384 length - (header.headerLength + header.paddingLength);
1385 if (payload_length == 0) {
1386 padding_observed_ = true;
1387 } else if (header.payloadType == kSendRtxPayloadType) {
1388 uint16_t original_sequence_number =
1389 ByteReader<uint16_t>::ReadBigEndian(&data[header.headerLength]);
1390 uint32_t original_ssrc =
1391 rtx_to_media_ssrcs_.find(header.ssrc)->second;
1392 std::set<uint16_t>* seq_no_map = &dropped_seq_[original_ssrc];
1393 auto it = seq_no_map->find(original_sequence_number);
1394 if (it != seq_no_map->end()) {
1395 retransmit_observed_ = true;
1396 seq_no_map->erase(it);
1397 } else {
1398 rtx_padding_observed_ = true;
1399 }
1400 } else {
1401 streams_observed_.insert(header.ssrc);
1402 }
1403
1404 if (IsDone())
Peter Boström5811a392015-12-10 13:02:50 +01001405 done_.Set();
sprang861c55e2015-10-16 10:01:21 -07001406
1407 if (drop_packet)
1408 return true;
1409 }
sprang867fb522015-08-03 04:38:41 -07001410 }
sprang861c55e2015-10-16 10:01:21 -07001411
stefan1d8a5062015-10-02 03:39:33 -07001412 return test::DirectTransport::SendRtp(data, length, options);
sprang867fb522015-08-03 04:38:41 -07001413 }
1414
Erik Språng8d629712015-08-04 16:24:03 +02001415 bool IsDone() {
sprang861c55e2015-10-16 10:01:21 -07001416 bool observed_types_ok =
1417 streams_observed_.size() == MultiStreamTest::kNumStreams &&
1418 padding_observed_ && retransmit_observed_ && rtx_padding_observed_;
1419 if (!observed_types_ok)
1420 return false;
1421 // We should not have any gaps in the sequence number range.
1422 size_t seqno_range =
1423 *received_packed_ids_.rbegin() - *received_packed_ids_.begin() + 1;
1424 return seqno_range == received_packed_ids_.size();
Erik Språng8d629712015-08-04 16:24:03 +02001425 }
1426
Peter Boström5811a392015-12-10 13:02:50 +01001427 bool Wait() {
sprang861c55e2015-10-16 10:01:21 -07001428 {
1429 // Can't be sure until this point that rtx_to_media_ssrcs_ etc have
1430 // been initialized and are OK to read.
1431 rtc::CritScope cs(&lock_);
1432 started_ = true;
1433 }
Peter Boström5811a392015-12-10 13:02:50 +01001434 return done_.Wait(kDefaultTimeoutMs);
sprang861c55e2015-10-16 10:01:21 -07001435 }
sprang867fb522015-08-03 04:38:41 -07001436
sprang861c55e2015-10-16 10:01:21 -07001437 rtc::CriticalSection lock_;
Peter Boström5811a392015-12-10 13:02:50 +01001438 rtc::Event done_;
kwiberg27f982b2016-03-01 11:52:33 -08001439 std::unique_ptr<RtpHeaderParser> parser_;
sprang861c55e2015-10-16 10:01:21 -07001440 SequenceNumberUnwrapper unwrapper_;
1441 std::set<int64_t> received_packed_ids_;
sprang867fb522015-08-03 04:38:41 -07001442 std::set<uint32_t> streams_observed_;
sprang861c55e2015-10-16 10:01:21 -07001443 std::map<uint32_t, std::set<uint16_t>> dropped_seq_;
1444 const uint32_t& first_media_ssrc_;
1445 const std::map<uint32_t, uint32_t>& rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001446 bool padding_observed_;
1447 bool rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001448 bool retransmit_observed_;
1449 bool started_;
sprang867fb522015-08-03 04:38:41 -07001450 };
1451
1452 class TransportSequenceNumberTester : public MultiStreamTest {
1453 public:
sprang861c55e2015-10-16 10:01:21 -07001454 TransportSequenceNumberTester()
1455 : first_media_ssrc_(0), observer_(nullptr) {}
sprang867fb522015-08-03 04:38:41 -07001456 virtual ~TransportSequenceNumberTester() {}
1457
1458 protected:
1459 void Wait() override {
Peter Boström74f6e9e2016-04-04 17:56:10 +02001460 RTC_DCHECK(observer_);
Peter Boström5811a392015-12-10 13:02:50 +01001461 EXPECT_TRUE(observer_->Wait());
sprang867fb522015-08-03 04:38:41 -07001462 }
1463
1464 void UpdateSendConfig(
1465 size_t stream_index,
1466 VideoSendStream::Config* send_config,
1467 VideoEncoderConfig* encoder_config,
1468 test::FrameGeneratorCapturer** frame_generator) override {
1469 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001470 send_config->rtp.extensions.push_back(RtpExtension(
1471 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sprang867fb522015-08-03 04:38:41 -07001472
1473 // Force some padding to be sent.
1474 const int kPaddingBitrateBps = 50000;
1475 int total_target_bitrate = 0;
1476 for (const VideoStream& stream : encoder_config->streams)
1477 total_target_bitrate += stream.target_bitrate_bps;
1478 encoder_config->min_transmit_bitrate_bps =
1479 total_target_bitrate + kPaddingBitrateBps;
1480
1481 // Configure RTX for redundant payload padding.
1482 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang861c55e2015-10-16 10:01:21 -07001483 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[stream_index]);
sprang867fb522015-08-03 04:38:41 -07001484 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
sprang861c55e2015-10-16 10:01:21 -07001485 rtx_to_media_ssrcs_[kSendRtxSsrcs[stream_index]] =
1486 send_config->rtp.ssrcs[0];
1487
1488 if (stream_index == 0)
1489 first_media_ssrc_ = send_config->rtp.ssrcs[0];
sprang867fb522015-08-03 04:38:41 -07001490 }
1491
1492 void UpdateReceiveConfig(
1493 size_t stream_index,
1494 VideoReceiveStream::Config* receive_config) override {
sprang861c55e2015-10-16 10:01:21 -07001495 receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang867fb522015-08-03 04:38:41 -07001496 receive_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001497 receive_config->rtp.extensions.push_back(RtpExtension(
1498 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sprang867fb522015-08-03 04:38:41 -07001499 }
1500
stefanf116bd02015-10-27 08:29:42 -07001501 test::DirectTransport* CreateSendTransport(Call* sender_call) override {
1502 observer_ = new RtpExtensionHeaderObserver(sender_call, first_media_ssrc_,
sprang861c55e2015-10-16 10:01:21 -07001503 rtx_to_media_ssrcs_);
sprang867fb522015-08-03 04:38:41 -07001504 return observer_;
1505 }
1506
1507 private:
sprang861c55e2015-10-16 10:01:21 -07001508 uint32_t first_media_ssrc_;
1509 std::map<uint32_t, uint32_t> rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001510 RtpExtensionHeaderObserver* observer_;
1511 } tester;
1512
1513 tester.RunTest();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001514}
1515
Stefan Holmer04cb7632016-01-14 20:34:30 +01001516class TransportFeedbackTester : public test::EndToEndTest {
1517 public:
1518 explicit TransportFeedbackTester(bool feedback_enabled,
1519 size_t num_video_streams,
1520 size_t num_audio_streams)
1521 : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
1522 feedback_enabled_(feedback_enabled),
1523 num_video_streams_(num_video_streams),
sprangcd349d92016-07-13 09:11:28 -07001524 num_audio_streams_(num_audio_streams),
1525 receiver_call_(nullptr) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001526 // Only one stream of each supported for now.
1527 EXPECT_LE(num_video_streams, 1u);
1528 EXPECT_LE(num_audio_streams, 1u);
1529 }
1530
1531 protected:
1532 Action OnSendRtcp(const uint8_t* data, size_t length) override {
1533 EXPECT_FALSE(HasTransportFeedback(data, length));
1534 return SEND_PACKET;
1535 }
1536
1537 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
1538 if (HasTransportFeedback(data, length))
1539 observation_complete_.Set();
1540 return SEND_PACKET;
1541 }
1542
1543 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
1544 RTCPUtility::RTCPParserV2 parser(data, length, true);
1545 EXPECT_TRUE(parser.IsValid());
1546
1547 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1548 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1549 if (packet_type == RTCPUtility::RTCPPacketTypes::kTransportFeedback)
1550 return true;
1551 packet_type = parser.Iterate();
1552 }
1553
1554 return false;
1555 }
1556
1557 void PerformTest() override {
1558 const int64_t kDisabledFeedbackTimeoutMs = 5000;
1559 EXPECT_EQ(feedback_enabled_,
1560 observation_complete_.Wait(feedback_enabled_
1561 ? test::CallTest::kDefaultTimeoutMs
1562 : kDisabledFeedbackTimeoutMs));
1563 }
1564
1565 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1566 receiver_call_ = receiver_call;
1567 }
1568
1569 size_t GetNumVideoStreams() const override { return num_video_streams_; }
1570 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
1571
1572 void ModifyVideoConfigs(
1573 VideoSendStream::Config* send_config,
1574 std::vector<VideoReceiveStream::Config>* receive_configs,
1575 VideoEncoderConfig* encoder_config) override {
1576 send_config->rtp.extensions.clear();
1577 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001578 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001579 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1580 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
1581 }
1582
1583 void ModifyAudioConfigs(
1584 AudioSendStream::Config* send_config,
1585 std::vector<AudioReceiveStream::Config>* receive_configs) override {
1586 send_config->rtp.extensions.clear();
1587 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001588 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001589 (*receive_configs)[0].rtp.extensions.clear();
1590 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1591 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001592 }
1593
1594 private:
Erik Språng6b8d3552015-09-24 15:06:57 +02001595 static const int kExtensionId = 5;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001596 const bool feedback_enabled_;
1597 const size_t num_video_streams_;
1598 const size_t num_audio_streams_;
1599 Call* receiver_call_;
1600};
Erik Språng6b8d3552015-09-24 15:06:57 +02001601
Stefan Holmer04cb7632016-01-14 20:34:30 +01001602TEST_F(EndToEndTest, VideoReceivesTransportFeedback) {
1603 TransportFeedbackTester test(true, 1, 0);
1604 RunBaseTest(&test);
Erik Språng6b8d3552015-09-24 15:06:57 +02001605}
stefan43edf0f2015-11-20 18:05:48 -08001606
Stefan Holmer04cb7632016-01-14 20:34:30 +01001607TEST_F(EndToEndTest, VideoTransportFeedbackNotConfigured) {
1608 TransportFeedbackTester test(false, 1, 0);
1609 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001610}
1611
Stefan Holmer04cb7632016-01-14 20:34:30 +01001612TEST_F(EndToEndTest, AudioReceivesTransportFeedback) {
1613 TransportFeedbackTester test(true, 0, 1);
1614 RunBaseTest(&test);
1615}
1616
1617TEST_F(EndToEndTest, AudioTransportFeedbackNotConfigured) {
1618 TransportFeedbackTester test(false, 0, 1);
1619 RunBaseTest(&test);
1620}
1621
1622TEST_F(EndToEndTest, AudioVideoReceivesTransportFeedback) {
1623 TransportFeedbackTester test(true, 1, 1);
1624 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001625}
1626
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001627TEST_F(EndToEndTest, ObserversEncodedFrames) {
1628 class EncodedFrameTestObserver : public EncodedFrameObserver {
1629 public:
1630 EncodedFrameTestObserver()
Peter Boström5811a392015-12-10 13:02:50 +01001631 : length_(0), frame_type_(kEmptyFrame), called_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001632 virtual ~EncodedFrameTestObserver() {}
1633
1634 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
1635 frame_type_ = encoded_frame.frame_type_;
1636 length_ = encoded_frame.length_;
1637 buffer_.reset(new uint8_t[length_]);
1638 memcpy(buffer_.get(), encoded_frame.data_, length_);
Peter Boström5811a392015-12-10 13:02:50 +01001639 called_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001640 }
1641
Peter Boström5811a392015-12-10 13:02:50 +01001642 bool Wait() { return called_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001643
1644 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
1645 ASSERT_EQ(length_, observer.length_)
1646 << "Observed frames are of different lengths.";
1647 EXPECT_EQ(frame_type_, observer.frame_type_)
1648 << "Observed frames have different frame types.";
1649 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
1650 << "Observed encoded frames have different content.";
1651 }
1652
1653 private:
kwiberg27f982b2016-03-01 11:52:33 -08001654 std::unique_ptr<uint8_t[]> buffer_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001655 size_t length_;
1656 FrameType frame_type_;
Peter Boström5811a392015-12-10 13:02:50 +01001657 rtc::Event called_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001658 };
1659
1660 EncodedFrameTestObserver post_encode_observer;
1661 EncodedFrameTestObserver pre_decode_observer;
1662
solenberg4fbae2b2015-08-28 04:07:10 -07001663 CreateCalls(Call::Config(), Call::Config());
1664
stefanf116bd02015-10-27 08:29:42 -07001665 test::DirectTransport sender_transport(sender_call_.get());
1666 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001667 sender_transport.SetReceiver(receiver_call_->Receiver());
1668 receiver_transport.SetReceiver(sender_call_->Receiver());
1669
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001670 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001671 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -08001672 video_send_config_.post_encode_callback = &post_encode_observer;
1673 video_receive_configs_[0].pre_decode_callback = &pre_decode_observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001674
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001675 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001676 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001677
kwiberg27f982b2016-03-01 11:52:33 -08001678 std::unique_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +00001679 test::FrameGenerator::CreateChromaGenerator(
stefanff483612015-12-21 03:14:00 -08001680 video_encoder_config_.streams[0].width,
1681 video_encoder_config_.streams[0].height));
1682 video_send_stream_->Input()->IncomingCapturedFrame(
1683 *frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001684
Peter Boström5811a392015-12-10 13:02:50 +01001685 EXPECT_TRUE(post_encode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001686 << "Timed out while waiting for send-side encoded-frame callback.";
1687
Peter Boström5811a392015-12-10 13:02:50 +01001688 EXPECT_TRUE(pre_decode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001689 << "Timed out while waiting for pre-decode encoded-frame callback.";
1690
1691 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
1692
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001693 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001694
1695 sender_transport.StopSending();
1696 receiver_transport.StopSending();
1697
1698 DestroyStreams();
1699}
1700
1701TEST_F(EndToEndTest, ReceiveStreamSendsRemb) {
1702 class RembObserver : public test::EndToEndTest {
1703 public:
1704 RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
1705
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001706 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001707 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1708 EXPECT_TRUE(parser.IsValid());
1709
1710 bool received_psfb = false;
1711 bool received_remb = false;
1712 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02001713 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1714 if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbRemb) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001715 const RTCPUtility::RTCPPacket& packet = parser.Packet();
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001716 EXPECT_EQ(packet.PSFBAPP.SenderSSRC, kReceiverLocalVideoSsrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001717 received_psfb = true;
Erik Språng242e22b2015-05-11 10:17:43 +02001718 } else if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbRembItem) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001719 const RTCPUtility::RTCPPacket& packet = parser.Packet();
1720 EXPECT_GT(packet.REMBItem.BitRate, 0u);
1721 EXPECT_EQ(packet.REMBItem.NumberOfSSRCs, 1u);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001722 EXPECT_EQ(packet.REMBItem.SSRCs[0], kVideoSendSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001723 received_remb = true;
1724 }
1725 packet_type = parser.Iterate();
1726 }
1727 if (received_psfb && received_remb)
Peter Boström5811a392015-12-10 13:02:50 +01001728 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001729 return SEND_PACKET;
1730 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001731 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001732 EXPECT_TRUE(Wait()) << "Timed out while waiting for a "
1733 "receiver RTCP REMB packet to be "
1734 "sent.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001735 }
1736 } test;
1737
stefane74eef12016-01-08 06:47:13 -08001738 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001739}
1740
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001741TEST_F(EndToEndTest, VerifyBandwidthStats) {
stefanf116bd02015-10-27 08:29:42 -07001742 class RtcpObserver : public test::EndToEndTest {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001743 public:
1744 RtcpObserver()
1745 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001746 sender_call_(nullptr),
1747 receiver_call_(nullptr),
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001748 has_seen_pacer_delay_(false) {}
1749
stefanf116bd02015-10-27 08:29:42 -07001750 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001751 Call::Stats sender_stats = sender_call_->GetStats();
1752 Call::Stats receiver_stats = receiver_call_->GetStats();
1753 if (!has_seen_pacer_delay_)
1754 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
1755 if (sender_stats.send_bandwidth_bps > 0 &&
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001756 receiver_stats.recv_bandwidth_bps > 0 && has_seen_pacer_delay_) {
Peter Boström5811a392015-12-10 13:02:50 +01001757 observation_complete_.Set();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001758 }
stefanf116bd02015-10-27 08:29:42 -07001759 return SEND_PACKET;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001760 }
1761
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001762 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001763 sender_call_ = sender_call;
1764 receiver_call_ = receiver_call;
1765 }
1766
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001767 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001768 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
1769 "non-zero bandwidth stats.";
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001770 }
1771
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001772 private:
1773 Call* sender_call_;
1774 Call* receiver_call_;
1775 bool has_seen_pacer_delay_;
1776 } test;
1777
stefane74eef12016-01-08 06:47:13 -08001778 RunBaseTest(&test);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001779}
1780
stefan32f81542016-01-20 07:13:58 -08001781
1782// Verifies that it's possible to limit the send BWE by sending a REMB.
1783// This is verified by allowing the send BWE to ramp-up to >1000 kbps,
1784// then have the test generate a REMB of 500 kbps and verify that the send BWE
1785// is reduced to exactly 500 kbps. Then a REMB of 1000 kbps is generated and the
1786// test verifies that the send BWE ramps back up to exactly 1000 kbps.
1787TEST_F(EndToEndTest, RembWithSendSideBwe) {
1788 class BweObserver : public test::EndToEndTest {
1789 public:
1790 BweObserver()
1791 : EndToEndTest(kDefaultTimeoutMs),
1792 sender_call_(nullptr),
1793 clock_(Clock::GetRealTimeClock()),
1794 sender_ssrc_(0),
1795 remb_bitrate_bps_(1000000),
1796 receive_transport_(nullptr),
1797 event_(false, false),
1798 poller_thread_(&BitrateStatsPollingThread,
1799 this,
1800 "BitrateStatsPollingThread"),
1801 state_(kWaitForFirstRampUp) {}
1802
1803 ~BweObserver() {}
1804
nisseef8b61e2016-04-29 06:09:15 -07001805 test::PacketTransport* CreateReceiveTransport() override {
stefan32f81542016-01-20 07:13:58 -08001806 receive_transport_ = new test::PacketTransport(
1807 nullptr, this, test::PacketTransport::kReceiver,
1808 FakeNetworkPipe::Config());
1809 return receive_transport_;
1810 }
1811
1812 Call::Config GetSenderCallConfig() override {
1813 Call::Config config;
1814 // Set a high start bitrate to reduce the test completion time.
1815 config.bitrate_config.start_bitrate_bps = remb_bitrate_bps_;
1816 return config;
1817 }
1818
1819 void ModifyVideoConfigs(
1820 VideoSendStream::Config* send_config,
1821 std::vector<VideoReceiveStream::Config>* receive_configs,
1822 VideoEncoderConfig* encoder_config) override {
1823 ASSERT_EQ(1u, send_config->rtp.ssrcs.size());
1824 send_config->rtp.extensions.clear();
1825 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001826 RtpExtension(RtpExtension::kTransportSequenceNumberUri,
stefan32f81542016-01-20 07:13:58 -08001827 test::kTransportSequenceNumberExtensionId));
1828 sender_ssrc_ = send_config->rtp.ssrcs[0];
1829
1830 encoder_config->streams[0].max_bitrate_bps =
1831 encoder_config->streams[0].target_bitrate_bps = 2000000;
1832
1833 ASSERT_EQ(1u, receive_configs->size());
1834 (*receive_configs)[0].rtp.remb = false;
1835 (*receive_configs)[0].rtp.transport_cc = true;
1836 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1837 RtpRtcp::Configuration config;
1838 config.receiver_only = true;
1839 config.clock = clock_;
1840 config.outgoing_transport = receive_transport_;
1841 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
1842 rtp_rtcp_->SetRemoteSSRC((*receive_configs)[0].rtp.remote_ssrc);
1843 rtp_rtcp_->SetSSRC((*receive_configs)[0].rtp.local_ssrc);
1844 rtp_rtcp_->SetREMBStatus(true);
1845 rtp_rtcp_->SetSendingStatus(true);
1846 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
1847 }
1848
1849 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1850 sender_call_ = sender_call;
1851 }
1852
1853 static bool BitrateStatsPollingThread(void* obj) {
1854 return static_cast<BweObserver*>(obj)->PollStats();
1855 }
1856
1857 bool PollStats() {
1858 if (sender_call_) {
1859 Call::Stats stats = sender_call_->GetStats();
1860 switch (state_) {
1861 case kWaitForFirstRampUp:
1862 if (stats.send_bandwidth_bps >= remb_bitrate_bps_) {
1863 state_ = kWaitForRemb;
1864 remb_bitrate_bps_ /= 2;
1865 rtp_rtcp_->SetREMBData(
1866 remb_bitrate_bps_,
1867 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
1868 rtp_rtcp_->SendRTCP(kRtcpRr);
1869 }
1870 break;
1871
1872 case kWaitForRemb:
1873 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
1874 state_ = kWaitForSecondRampUp;
1875 remb_bitrate_bps_ *= 2;
1876 rtp_rtcp_->SetREMBData(
1877 remb_bitrate_bps_,
1878 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
1879 rtp_rtcp_->SendRTCP(kRtcpRr);
1880 }
1881 break;
1882
1883 case kWaitForSecondRampUp:
1884 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
1885 observation_complete_.Set();
1886 }
1887 break;
1888 }
1889 }
1890
1891 return !event_.Wait(1000);
1892 }
1893
1894 void PerformTest() override {
1895 poller_thread_.Start();
1896 EXPECT_TRUE(Wait())
1897 << "Timed out while waiting for bitrate to change according to REMB.";
1898 poller_thread_.Stop();
1899 }
1900
1901 private:
1902 enum TestState { kWaitForFirstRampUp, kWaitForRemb, kWaitForSecondRampUp };
1903
1904 Call* sender_call_;
1905 Clock* const clock_;
1906 uint32_t sender_ssrc_;
1907 int remb_bitrate_bps_;
kwiberg27f982b2016-03-01 11:52:33 -08001908 std::unique_ptr<RtpRtcp> rtp_rtcp_;
stefan32f81542016-01-20 07:13:58 -08001909 test::PacketTransport* receive_transport_;
1910 rtc::Event event_;
1911 rtc::PlatformThread poller_thread_;
1912 TestState state_;
1913 } test;
1914
1915 RunBaseTest(&test);
1916}
1917
Åsa Persson352b2d72015-04-15 18:00:40 +02001918TEST_F(EndToEndTest, VerifyNackStats) {
1919 static const int kPacketNumberToDrop = 200;
1920 class NackObserver : public test::EndToEndTest {
1921 public:
1922 NackObserver()
1923 : EndToEndTest(kLongTimeoutMs),
1924 sent_rtp_packets_(0),
1925 dropped_rtp_packet_(0),
1926 dropped_rtp_packet_requested_(false),
1927 send_stream_(nullptr),
1928 start_runtime_ms_(-1) {}
1929
1930 private:
1931 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08001932 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02001933 if (++sent_rtp_packets_ == kPacketNumberToDrop) {
kwiberg27f982b2016-03-01 11:52:33 -08001934 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
Åsa Persson352b2d72015-04-15 18:00:40 +02001935 RTPHeader header;
1936 EXPECT_TRUE(parser->Parse(packet, length, &header));
1937 dropped_rtp_packet_ = header.sequenceNumber;
1938 return DROP_PACKET;
1939 }
1940 VerifyStats();
1941 return SEND_PACKET;
1942 }
1943
1944 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08001945 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02001946 test::RtcpPacketParser rtcp_parser;
1947 rtcp_parser.Parse(packet, length);
1948 std::vector<uint16_t> nacks = rtcp_parser.nack_item()->last_nack_list();
1949 if (!nacks.empty() && std::find(
1950 nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) {
1951 dropped_rtp_packet_requested_ = true;
1952 }
1953 return SEND_PACKET;
1954 }
1955
stefan608213e2015-11-01 14:56:10 -08001956 void VerifyStats() EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
Åsa Persson352b2d72015-04-15 18:00:40 +02001957 if (!dropped_rtp_packet_requested_)
1958 return;
1959 int send_stream_nack_packets = 0;
1960 int receive_stream_nack_packets = 0;
1961 VideoSendStream::Stats stats = send_stream_->GetStats();
1962 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
1963 stats.substreams.begin(); it != stats.substreams.end(); ++it) {
1964 const VideoSendStream::StreamStats& stream_stats = it->second;
1965 send_stream_nack_packets +=
1966 stream_stats.rtcp_packet_type_counts.nack_packets;
1967 }
1968 for (size_t i = 0; i < receive_streams_.size(); ++i) {
1969 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
1970 receive_stream_nack_packets +=
1971 stats.rtcp_packet_type_counts.nack_packets;
1972 }
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001973 if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) {
Åsa Persson352b2d72015-04-15 18:00:40 +02001974 // NACK packet sent on receive stream and received on sent stream.
1975 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01001976 observation_complete_.Set();
Åsa Persson352b2d72015-04-15 18:00:40 +02001977 }
1978 }
1979
1980 bool MinMetricRunTimePassed() {
1981 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
1982 if (start_runtime_ms_ == -1) {
1983 start_runtime_ms_ = now;
1984 return false;
1985 }
1986 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
1987 return elapsed_sec > metrics::kMinRunTimeInSeconds;
1988 }
1989
stefanff483612015-12-21 03:14:00 -08001990 void ModifyVideoConfigs(
1991 VideoSendStream::Config* send_config,
1992 std::vector<VideoReceiveStream::Config>* receive_configs,
1993 VideoEncoderConfig* encoder_config) override {
Åsa Persson352b2d72015-04-15 18:00:40 +02001994 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1995 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1996 }
1997
stefanff483612015-12-21 03:14:00 -08001998 void OnVideoStreamsCreated(
Åsa Persson352b2d72015-04-15 18:00:40 +02001999 VideoSendStream* send_stream,
2000 const std::vector<VideoReceiveStream*>& receive_streams) override {
2001 send_stream_ = send_stream;
2002 receive_streams_ = receive_streams;
2003 }
2004
2005 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002006 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson352b2d72015-04-15 18:00:40 +02002007 }
2008
stefan608213e2015-11-01 14:56:10 -08002009 rtc::CriticalSection crit_;
Åsa Persson352b2d72015-04-15 18:00:40 +02002010 uint64_t sent_rtp_packets_;
stefan608213e2015-11-01 14:56:10 -08002011 uint16_t dropped_rtp_packet_ GUARDED_BY(&crit_);
2012 bool dropped_rtp_packet_requested_ GUARDED_BY(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002013 std::vector<VideoReceiveStream*> receive_streams_;
2014 VideoSendStream* send_stream_;
2015 int64_t start_runtime_ms_;
2016 } test;
2017
asapersson01d70a32016-05-20 06:29:46 -07002018 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002019 RunBaseTest(&test);
Åsa Persson352b2d72015-04-15 18:00:40 +02002020
asapersson01d70a32016-05-20 06:29:46 -07002021 EXPECT_EQ(
2022 1, metrics::NumSamples("WebRTC.Video.UniqueNackRequestsSentInPercent"));
2023 EXPECT_EQ(1, metrics::NumSamples(
2024 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
2025 EXPECT_GT(metrics::MinSample("WebRTC.Video.NackPacketsSentPerMinute"), 0);
Åsa Persson352b2d72015-04-15 18:00:40 +02002026}
2027
sprangb4a1ae52015-12-03 08:10:08 -08002028void EndToEndTest::VerifyHistogramStats(bool use_rtx,
2029 bool use_red,
2030 bool screenshare) {
tommi2e82f382016-06-21 00:26:43 -07002031 class StatsObserver : public test::EndToEndTest,
2032 public rtc::VideoSinkInterface<VideoFrame> {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002033 public:
sprangb4a1ae52015-12-03 08:10:08 -08002034 StatsObserver(bool use_rtx, bool use_red, bool screenshare)
Åsa Persson3c391cb2015-04-27 10:09:49 +02002035 : EndToEndTest(kLongTimeoutMs),
2036 use_rtx_(use_rtx),
2037 use_red_(use_red),
sprangb4a1ae52015-12-03 08:10:08 -08002038 screenshare_(screenshare),
Peter Boström39593972016-02-15 11:27:15 +01002039 // This test uses NACK, so to send FEC we can't use a fake encoder.
2040 vp8_encoder_(
2041 use_red ? VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)
2042 : nullptr),
Åsa Persson3c391cb2015-04-27 10:09:49 +02002043 sender_call_(nullptr),
2044 receiver_call_(nullptr),
2045 start_runtime_ms_(-1) {}
2046
2047 private:
tommi2e82f382016-06-21 00:26:43 -07002048 void OnFrame(const VideoFrame& video_frame) override {}
2049
Åsa Persson3c391cb2015-04-27 10:09:49 +02002050 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2051 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002052 observation_complete_.Set();
Åsa Persson3c391cb2015-04-27 10:09:49 +02002053
stefanf116bd02015-10-27 08:29:42 -07002054 return SEND_PACKET;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002055 }
2056
2057 bool MinMetricRunTimePassed() {
2058 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2059 if (start_runtime_ms_ == -1) {
2060 start_runtime_ms_ = now;
2061 return false;
2062 }
2063 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2064 return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
2065 }
2066
stefanff483612015-12-21 03:14:00 -08002067 void ModifyVideoConfigs(
2068 VideoSendStream::Config* send_config,
2069 std::vector<VideoReceiveStream::Config>* receive_configs,
2070 VideoEncoderConfig* encoder_config) override {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002071 // NACK
2072 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2073 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
tommi2e82f382016-06-21 00:26:43 -07002074 (*receive_configs)[0].renderer = this;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002075 // FEC
2076 if (use_red_) {
2077 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
2078 send_config->rtp.fec.red_payload_type = kRedPayloadType;
Peter Boström39593972016-02-15 11:27:15 +01002079 send_config->encoder_settings.encoder = vp8_encoder_.get();
2080 send_config->encoder_settings.payload_name = "VP8";
2081 (*receive_configs)[0].decoders[0].payload_name = "VP8";
Åsa Persson3c391cb2015-04-27 10:09:49 +02002082 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
2083 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
2084 }
2085 // RTX
2086 if (use_rtx_) {
2087 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
2088 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002089 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002090 kSendRtxSsrcs[0];
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002091 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002092 kSendRtxPayloadType;
2093 }
sprangb4a1ae52015-12-03 08:10:08 -08002094 encoder_config->content_type =
2095 screenshare_ ? VideoEncoderConfig::ContentType::kScreen
2096 : VideoEncoderConfig::ContentType::kRealtimeVideo;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002097 }
2098
2099 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2100 sender_call_ = sender_call;
2101 receiver_call_ = receiver_call;
2102 }
2103
Åsa Persson3c391cb2015-04-27 10:09:49 +02002104 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002105 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson3c391cb2015-04-27 10:09:49 +02002106 }
2107
sprangb4a1ae52015-12-03 08:10:08 -08002108 const bool use_rtx_;
2109 const bool use_red_;
2110 const bool screenshare_;
kwiberg27f982b2016-03-01 11:52:33 -08002111 const std::unique_ptr<VideoEncoder> vp8_encoder_;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002112 Call* sender_call_;
2113 Call* receiver_call_;
2114 int64_t start_runtime_ms_;
sprangb4a1ae52015-12-03 08:10:08 -08002115 } test(use_rtx, use_red, screenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002116
asapersson01d70a32016-05-20 06:29:46 -07002117 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002118 RunBaseTest(&test);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002119
stefan91d92602015-11-11 10:13:02 -08002120 // Delete the call for Call stats to be reported.
stefan18adf0a2015-11-17 06:24:56 -08002121 sender_call_.reset();
stefan91d92602015-11-11 10:13:02 -08002122 receiver_call_.reset();
2123
sprangb4a1ae52015-12-03 08:10:08 -08002124 std::string video_prefix =
2125 screenshare ? "WebRTC.Video.Screenshare." : "WebRTC.Video.";
2126
Åsa Persson3c391cb2015-04-27 10:09:49 +02002127 // Verify that stats have been updated once.
asapersson01d70a32016-05-20 06:29:46 -07002128 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
2129 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.RtcpBitrateReceivedInBps"));
2130 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.BitrateReceivedInKbps"));
2131 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.EstimatedSendBitrateInKbps"));
2132 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.PacerBitrateInKbps"));
2133
2134 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
stefan91d92602015-11-11 10:13:02 -08002135 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002136 metrics::NumSamples(video_prefix + "NackPacketsReceivedPerMinute"));
2137 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
asaperssond89920b2015-07-22 06:52:00 -07002138 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002139 metrics::NumSamples(video_prefix + "FirPacketsReceivedPerMinute"));
2140 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
sprangb4a1ae52015-12-03 08:10:08 -08002141 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002142 metrics::NumSamples(video_prefix + "PliPacketsReceivedPerMinute"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002143
asapersson01d70a32016-05-20 06:29:46 -07002144 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "KeyFramesSentInPermille"));
2145 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
2146
2147 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentPacketsLostInPercent"));
2148 EXPECT_EQ(1,
2149 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
2150
2151 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputWidthInPixels"));
2152 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputHeightInPixels"));
2153 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentWidthInPixels"));
2154 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentHeightInPixels"));
2155 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
2156 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
2157
2158 EXPECT_EQ(1, metrics::NumEvents(
2159 video_prefix + "InputWidthInPixels",
2160 static_cast<int>(video_encoder_config_.streams[0].width)));
2161 EXPECT_EQ(1, metrics::NumEvents(
2162 video_prefix + "InputHeightInPixels",
2163 static_cast<int>(video_encoder_config_.streams[0].height)));
2164 EXPECT_EQ(1, metrics::NumEvents(
2165 video_prefix + "SentWidthInPixels",
2166 static_cast<int>(video_encoder_config_.streams[0].width)));
2167 EXPECT_EQ(1, metrics::NumEvents(
2168 video_prefix + "SentHeightInPixels",
2169 static_cast<int>(video_encoder_config_.streams[0].height)));
2170 EXPECT_EQ(1, metrics::NumEvents(
2171 "WebRTC.Video.ReceivedWidthInPixels",
2172 static_cast<int>(video_encoder_config_.streams[0].width)));
2173 EXPECT_EQ(1, metrics::NumEvents(
2174 "WebRTC.Video.ReceivedHeightInPixels",
2175 static_cast<int>(video_encoder_config_.streams[0].height)));
2176
2177 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputFramesPerSecond"));
2178 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentFramesPerSecond"));
2179 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
2180 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
2181
2182 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
2183 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
2184 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
2185 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
2186
2187 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
2188
2189 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EncodeTimeInMs"));
2190 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
2191
2192 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "BitrateSentInKbps"));
2193 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateReceivedInKbps"));
2194 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "MediaBitrateSentInKbps"));
2195 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateReceivedInKbps"));
2196 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PaddingBitrateSentInKbps"));
2197 EXPECT_EQ(1,
2198 metrics::NumSamples("WebRTC.Video.PaddingBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002199 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002200 1, metrics::NumSamples(video_prefix + "RetransmittedBitrateSentInKbps"));
2201 EXPECT_EQ(1, metrics::NumSamples(
2202 "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002203
asapersson01d70a32016-05-20 06:29:46 -07002204 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendDelayInMs"));
2205 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayInMs"));
2206 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayMaxInMs"));
asapersson6f14be82015-11-16 00:40:49 -08002207
Åsa Persson3c391cb2015-04-27 10:09:49 +02002208 int num_rtx_samples = use_rtx ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002209 EXPECT_EQ(num_rtx_samples,
2210 metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2211 EXPECT_EQ(num_rtx_samples,
2212 metrics::NumSamples("WebRTC.Video.RtxBitrateReceivedInKbps"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002213
2214 int num_red_samples = use_red ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002215 EXPECT_EQ(num_red_samples,
2216 metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2217 EXPECT_EQ(num_red_samples,
2218 metrics::NumSamples("WebRTC.Video.FecBitrateReceivedInKbps"));
2219 EXPECT_EQ(num_red_samples,
2220 metrics::NumSamples("WebRTC.Video.ReceivedFecPacketsInPercent"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002221}
2222
2223TEST_F(EndToEndTest, VerifyHistogramStatsWithRtx) {
2224 const bool kEnabledRtx = true;
2225 const bool kEnabledRed = false;
sprangb4a1ae52015-12-03 08:10:08 -08002226 const bool kScreenshare = false;
2227 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002228}
2229
2230TEST_F(EndToEndTest, VerifyHistogramStatsWithRed) {
2231 const bool kEnabledRtx = false;
2232 const bool kEnabledRed = true;
sprangb4a1ae52015-12-03 08:10:08 -08002233 const bool kScreenshare = false;
2234 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
2235}
2236
2237TEST_F(EndToEndTest, VerifyHistogramStatsWithScreenshare) {
2238 const bool kEnabledRtx = false;
2239 const bool kEnabledRed = false;
2240 const bool kScreenshare = true;
2241 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002242}
2243
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002244void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
2245 static const int kNumRtcpReportPacketsToObserve = 5;
2246 class RtcpXrObserver : public test::EndToEndTest {
2247 public:
2248 explicit RtcpXrObserver(bool enable_rrtr)
2249 : EndToEndTest(kDefaultTimeoutMs),
2250 enable_rrtr_(enable_rrtr),
2251 sent_rtcp_sr_(0),
2252 sent_rtcp_rr_(0),
2253 sent_rtcp_rrtr_(0),
2254 sent_rtcp_dlrr_(0) {}
2255
2256 private:
2257 // Receive stream should send RR packets (and RRTR packets if enabled).
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002258 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002259 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002260 RTCPUtility::RTCPParserV2 parser(packet, length, true);
2261 EXPECT_TRUE(parser.IsValid());
2262
2263 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02002264 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
2265 if (packet_type == RTCPUtility::RTCPPacketTypes::kRr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002266 ++sent_rtcp_rr_;
2267 } else if (packet_type ==
Erik Språng242e22b2015-05-11 10:17:43 +02002268 RTCPUtility::RTCPPacketTypes::kXrReceiverReferenceTime) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002269 ++sent_rtcp_rrtr_;
2270 }
Erik Språng242e22b2015-05-11 10:17:43 +02002271 EXPECT_NE(packet_type, RTCPUtility::RTCPPacketTypes::kSr);
2272 EXPECT_NE(packet_type,
2273 RTCPUtility::RTCPPacketTypes::kXrDlrrReportBlockItem);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002274 packet_type = parser.Iterate();
2275 }
2276 return SEND_PACKET;
2277 }
2278 // Send stream should send SR packets (and DLRR packets if enabled).
nisseef8b61e2016-04-29 06:09:15 -07002279 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002280 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002281 RTCPUtility::RTCPParserV2 parser(packet, length, true);
2282 EXPECT_TRUE(parser.IsValid());
2283
2284 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02002285 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
2286 if (packet_type == RTCPUtility::RTCPPacketTypes::kSr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002287 ++sent_rtcp_sr_;
Erik Språng242e22b2015-05-11 10:17:43 +02002288 } else if (packet_type ==
2289 RTCPUtility::RTCPPacketTypes::kXrDlrrReportBlockItem) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002290 ++sent_rtcp_dlrr_;
2291 }
Erik Språng242e22b2015-05-11 10:17:43 +02002292 EXPECT_NE(packet_type,
2293 RTCPUtility::RTCPPacketTypes::kXrReceiverReferenceTime);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002294 packet_type = parser.Iterate();
2295 }
2296 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
2297 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve) {
2298 if (enable_rrtr_) {
2299 EXPECT_GT(sent_rtcp_rrtr_, 0);
2300 EXPECT_GT(sent_rtcp_dlrr_, 0);
2301 } else {
2302 EXPECT_EQ(0, sent_rtcp_rrtr_);
2303 EXPECT_EQ(0, sent_rtcp_dlrr_);
2304 }
Peter Boström5811a392015-12-10 13:02:50 +01002305 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002306 }
2307 return SEND_PACKET;
2308 }
2309
stefanff483612015-12-21 03:14:00 -08002310 void ModifyVideoConfigs(
2311 VideoSendStream::Config* send_config,
2312 std::vector<VideoReceiveStream::Config>* receive_configs,
2313 VideoEncoderConfig* encoder_config) override {
pbosda903ea2015-10-02 02:36:56 -07002314 (*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002315 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
2316 enable_rrtr_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002317 }
2318
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002319 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002320 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002321 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
2322 }
2323
stefan608213e2015-11-01 14:56:10 -08002324 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002325 bool enable_rrtr_;
2326 int sent_rtcp_sr_;
stefan608213e2015-11-01 14:56:10 -08002327 int sent_rtcp_rr_ GUARDED_BY(&crit_);
2328 int sent_rtcp_rrtr_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002329 int sent_rtcp_dlrr_;
2330 } test(enable_rrtr);
2331
stefane74eef12016-01-08 06:47:13 -08002332 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002333}
2334
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002335void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
2336 bool send_single_ssrc_first) {
2337 class SendsSetSsrcs : public test::EndToEndTest {
2338 public:
2339 SendsSetSsrcs(const uint32_t* ssrcs,
2340 size_t num_ssrcs,
2341 bool send_single_ssrc_first)
2342 : EndToEndTest(kDefaultTimeoutMs),
2343 num_ssrcs_(num_ssrcs),
2344 send_single_ssrc_first_(send_single_ssrc_first),
2345 ssrcs_to_observe_(num_ssrcs),
sprang867fb522015-08-03 04:38:41 -07002346 expect_single_ssrc_(send_single_ssrc_first),
2347 send_stream_(nullptr) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002348 for (size_t i = 0; i < num_ssrcs; ++i)
2349 valid_ssrcs_[ssrcs[i]] = true;
2350 }
2351
2352 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002353 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002354 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002355 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002356
2357 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
2358 << "Received unknown SSRC: " << header.ssrc;
2359
2360 if (!valid_ssrcs_[header.ssrc])
Peter Boström5811a392015-12-10 13:02:50 +01002361 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002362
2363 if (!is_observed_[header.ssrc]) {
2364 is_observed_[header.ssrc] = true;
2365 --ssrcs_to_observe_;
2366 if (expect_single_ssrc_) {
2367 expect_single_ssrc_ = false;
Peter Boström5811a392015-12-10 13:02:50 +01002368 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002369 }
2370 }
2371
2372 if (ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002373 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002374
2375 return SEND_PACKET;
2376 }
2377
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002378 size_t GetNumVideoStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002379
stefanff483612015-12-21 03:14:00 -08002380 void ModifyVideoConfigs(
2381 VideoSendStream::Config* send_config,
2382 std::vector<VideoReceiveStream::Config>* receive_configs,
2383 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002384 if (num_ssrcs_ > 1) {
2385 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002386 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2387 encoder_config->streams[i].min_bitrate_bps = 10000;
2388 encoder_config->streams[i].target_bitrate_bps = 15000;
2389 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002390 }
2391 }
2392
stefanff483612015-12-21 03:14:00 -08002393 video_encoder_config_all_streams_ = *encoder_config;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002394 if (send_single_ssrc_first_)
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002395 encoder_config->streams.resize(1);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002396 }
2397
stefanff483612015-12-21 03:14:00 -08002398 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002399 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002400 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002401 send_stream_ = send_stream;
2402 }
2403
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002404 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002405 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2406 << (send_single_ssrc_first_ ? "first SSRC."
2407 : "SSRCs.");
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002408
2409 if (send_single_ssrc_first_) {
2410 // Set full simulcast and continue with the rest of the SSRCs.
stefanff483612015-12-21 03:14:00 -08002411 send_stream_->ReconfigureVideoEncoder(
2412 video_encoder_config_all_streams_);
Peter Boström5811a392015-12-10 13:02:50 +01002413 EXPECT_TRUE(Wait()) << "Timed out while waiting on additional SSRCs.";
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002414 }
2415 }
2416
2417 private:
2418 std::map<uint32_t, bool> valid_ssrcs_;
2419 std::map<uint32_t, bool> is_observed_;
2420
2421 const size_t num_ssrcs_;
2422 const bool send_single_ssrc_first_;
2423
2424 size_t ssrcs_to_observe_;
2425 bool expect_single_ssrc_;
2426
2427 VideoSendStream* send_stream_;
stefanff483612015-12-21 03:14:00 -08002428 VideoEncoderConfig video_encoder_config_all_streams_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002429 } test(kVideoSendSsrcs, num_ssrcs, send_single_ssrc_first);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002430
stefane74eef12016-01-08 06:47:13 -08002431 RunBaseTest(&test);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002432}
2433
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002434TEST_F(EndToEndTest, ReportsSetEncoderRates) {
2435 class EncoderRateStatsTest : public test::EndToEndTest,
2436 public test::FakeEncoder {
2437 public:
2438 EncoderRateStatsTest()
2439 : EndToEndTest(kDefaultTimeoutMs),
sprang867fb522015-08-03 04:38:41 -07002440 FakeEncoder(Clock::GetRealTimeClock()),
2441 send_stream_(nullptr),
2442 bitrate_kbps_(0) {}
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002443
stefanff483612015-12-21 03:14:00 -08002444 void OnVideoStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002445 VideoSendStream* send_stream,
2446 const std::vector<VideoReceiveStream*>& receive_streams) override {
2447 send_stream_ = send_stream;
2448 }
2449
stefanff483612015-12-21 03:14:00 -08002450 void ModifyVideoConfigs(
2451 VideoSendStream::Config* send_config,
2452 std::vector<VideoReceiveStream::Config>* receive_configs,
2453 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002454 send_config->encoder_settings.encoder = this;
perkj57c21f92016-06-17 07:27:16 -07002455 RTC_DCHECK_EQ(1u, encoder_config->streams.size());
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002456 }
2457
2458 int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override {
2459 // Make sure not to trigger on any default zero bitrates.
2460 if (new_target_bitrate == 0)
2461 return 0;
Peter Boströmf2f82832015-05-01 13:00:41 +02002462 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002463 bitrate_kbps_ = new_target_bitrate;
Peter Boström5811a392015-12-10 13:02:50 +01002464 observation_complete_.Set();
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002465 return 0;
2466 }
2467
2468 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002469 ASSERT_TRUE(Wait())
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002470 << "Timed out while waiting for encoder SetRates() call.";
perkjf5b2e512016-07-05 08:34:04 -07002471 WaitForEncoderTargetBitrateMatchStats();
2472 send_stream_->Stop();
2473 WaitForStatsReportZeroTargetBitrate();
2474 send_stream_->Start();
2475 WaitForEncoderTargetBitrateMatchStats();
2476 }
2477
2478 void WaitForEncoderTargetBitrateMatchStats() {
Peter Boström5811a392015-12-10 13:02:50 +01002479 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002480 VideoSendStream::Stats stats = send_stream_->GetStats();
2481 {
Peter Boströmf2f82832015-05-01 13:00:41 +02002482 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002483 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
2484 static_cast<int>(bitrate_kbps_)) {
2485 return;
2486 }
2487 }
2488 SleepMs(1);
2489 }
2490 FAIL()
2491 << "Timed out waiting for stats reporting the currently set bitrate.";
2492 }
2493
perkjf5b2e512016-07-05 08:34:04 -07002494 void WaitForStatsReportZeroTargetBitrate() {
2495 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
2496 if (send_stream_->GetStats().target_media_bitrate_bps == 0) {
2497 return;
2498 }
2499 SleepMs(1);
2500 }
2501 FAIL() << "Timed out waiting for stats reporting zero bitrate.";
2502 }
2503
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002504 private:
stefanf116bd02015-10-27 08:29:42 -07002505 rtc::CriticalSection crit_;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002506 VideoSendStream* send_stream_;
2507 uint32_t bitrate_kbps_ GUARDED_BY(crit_);
2508 } test;
2509
stefane74eef12016-01-08 06:47:13 -08002510 RunBaseTest(&test);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002511}
2512
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002513TEST_F(EndToEndTest, GetStats) {
2514 static const int kStartBitrateBps = 3000000;
Peter Boströmdef398832015-05-27 17:59:11 +02002515 static const int kExpectedRenderDelayMs = 20;
tommi2e82f382016-06-21 00:26:43 -07002516
2517 class ReceiveStreamRenderer : public rtc::VideoSinkInterface<VideoFrame> {
2518 public:
2519 ReceiveStreamRenderer() {}
2520
2521 private:
2522 void OnFrame(const VideoFrame& video_frame) override {}
2523 };
2524
nissed30a1112016-04-18 05:15:22 -07002525 class StatsObserver : public test::EndToEndTest,
2526 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002527 public:
stefanf116bd02015-10-27 08:29:42 -07002528 StatsObserver()
2529 : EndToEndTest(kLongTimeoutMs),
Peter Boströmc6e16e32016-02-05 14:15:53 +01002530 encoder_(Clock::GetRealTimeClock(), 10),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002531 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002532 expected_send_ssrcs_(),
Peter Boström5811a392015-12-10 13:02:50 +01002533 check_stats_event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002534
2535 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002536 Action OnSendRtp(const uint8_t* packet, size_t length) override {
sprangcd349d92016-07-13 09:11:28 -07002537 // Drop every 25th packet => 4% loss.
2538 static const int kPacketLossFrac = 25;
2539 RTPHeader header;
2540 RtpUtility::RtpHeaderParser parser(packet, length);
2541 if (parser.Parse(&header) &&
2542 expected_send_ssrcs_.find(header.ssrc) !=
2543 expected_send_ssrcs_.end() &&
2544 header.sequenceNumber % kPacketLossFrac == 0) {
2545 return DROP_PACKET;
2546 }
Peter Boström5811a392015-12-10 13:02:50 +01002547 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002548 return SEND_PACKET;
2549 }
2550
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002551 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002552 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002553 return SEND_PACKET;
2554 }
2555
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002556 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002557 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002558 return SEND_PACKET;
2559 }
2560
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002561 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002562 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002563 return SEND_PACKET;
2564 }
2565
nissed30a1112016-04-18 05:15:22 -07002566 void OnFrame(const VideoFrame& video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002567 // Ensure that we have at least 5ms send side delay.
nissed30a1112016-04-18 05:15:22 -07002568 SleepMs(5);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002569 }
2570
2571 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002572 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2573 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2574 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002575
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002576 // Make sure all fields have been populated.
2577 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
2578 // always filled for all receivers.
2579 receive_stats_filled_["IncomingRate"] |=
2580 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002581
Peter Boströmb7d9a972015-12-18 16:01:11 +01002582 send_stats_filled_["DecoderImplementationName"] |=
2583 stats.decoder_implementation_name ==
2584 test::FakeDecoder::kImplementationName;
Peter Boströmdef398832015-05-27 17:59:11 +02002585 receive_stats_filled_["RenderDelayAsHighAsExpected"] |=
2586 stats.render_delay_ms >= kExpectedRenderDelayMs;
2587
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002588 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002589
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002590 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002591
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002592 receive_stats_filled_["StatisticsUpdated"] |=
2593 stats.rtcp_stats.cumulative_lost != 0 ||
2594 stats.rtcp_stats.extended_max_sequence_number != 0 ||
2595 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002596
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002597 receive_stats_filled_["DataCountersUpdated"] |=
2598 stats.rtp_stats.transmitted.payload_bytes != 0 ||
2599 stats.rtp_stats.fec.packets != 0 ||
2600 stats.rtp_stats.transmitted.header_bytes != 0 ||
2601 stats.rtp_stats.transmitted.packets != 0 ||
2602 stats.rtp_stats.transmitted.padding_bytes != 0 ||
2603 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002604
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002605 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002606 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002607
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002608 receive_stats_filled_["FrameCounts"] |=
2609 stats.frame_counts.key_frames != 0 ||
2610 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002611
pbosbb36fdf2015-07-09 07:48:14 -07002612 receive_stats_filled_["CName"] |= !stats.c_name.empty();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002613
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002614 receive_stats_filled_["RtcpPacketTypeCount"] |=
2615 stats.rtcp_packet_type_counts.fir_packets != 0 ||
2616 stats.rtcp_packet_type_counts.nack_packets != 0 ||
2617 stats.rtcp_packet_type_counts.pli_packets != 0 ||
2618 stats.rtcp_packet_type_counts.nack_requests != 0 ||
2619 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbosf42376c2015-08-28 07:35:32 -07002620
2621 assert(stats.current_payload_type == -1 ||
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002622 stats.current_payload_type == kFakeVideoSendPayloadType);
pbosf42376c2015-08-28 07:35:32 -07002623 receive_stats_filled_["IncomingPayloadType"] |=
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002624 stats.current_payload_type == kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002625 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002626
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002627 return AllStatsFilled(receive_stats_filled_);
2628 }
2629
2630 bool CheckSendStats() {
Peter Boström74f6e9e2016-04-04 17:56:10 +02002631 RTC_DCHECK(send_stream_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002632 VideoSendStream::Stats stats = send_stream_->GetStats();
2633
2634 send_stats_filled_["NumStreams"] |=
2635 stats.substreams.size() == expected_send_ssrcs_.size();
2636
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002637 send_stats_filled_["CpuOveruseMetrics"] |=
Peter Boströme4499152016-02-05 11:13:28 +01002638 stats.avg_encode_time_ms != 0 && stats.encode_usage_percent != 0;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002639
Peter Boströmb7d9a972015-12-18 16:01:11 +01002640 send_stats_filled_["EncoderImplementationName"] |=
2641 stats.encoder_implementation_name ==
2642 test::FakeEncoder::kImplementationName;
2643
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002644 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002645 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002646 it != stats.substreams.end(); ++it) {
sprangcd349d92016-07-13 09:11:28 -07002647 if (expected_send_ssrcs_.find(it->first) == expected_send_ssrcs_.end())
2648 continue; // Probably RTX.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002649
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002650 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002651 stats.input_frame_rate != 0;
2652
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002653 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002654
2655 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
2656 stream_stats.rtcp_stats.cumulative_lost != 0 ||
2657 stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
2658 stream_stats.rtcp_stats.fraction_lost != 0;
2659
2660 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002661 stream_stats.rtp_stats.fec.packets != 0 ||
2662 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
2663 stream_stats.rtp_stats.retransmitted.packets != 0 ||
2664 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002665
sprangcd349d92016-07-13 09:11:28 -07002666 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Total",
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002667 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002668 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002669
sprangcd349d92016-07-13 09:11:28 -07002670 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Retransmit",
2671 it->first)] |=
2672 stream_stats.retransmit_bitrate_bps != 0;
2673
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002674 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002675 stream_stats.frame_counts.delta_frames != 0 ||
2676 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002677
2678 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
2679 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00002680
2681 send_stats_filled_[CompoundKey("Delay", it->first)] |=
2682 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002683
2684 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
2685 // report dropped packets.
2686 send_stats_filled_["RtcpPacketTypeCount"] |=
2687 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
2688 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
2689 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
2690 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
2691 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002692 }
2693
2694 return AllStatsFilled(send_stats_filled_);
2695 }
2696
2697 std::string CompoundKey(const char* name, uint32_t ssrc) {
2698 std::ostringstream oss;
2699 oss << name << "_" << ssrc;
2700 return oss.str();
2701 }
2702
2703 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
sprangcd349d92016-07-13 09:11:28 -07002704 for (const auto& stat : stats_map) {
2705 if (!stat.second)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002706 return false;
2707 }
2708 return true;
2709 }
2710
stefane74eef12016-01-08 06:47:13 -08002711 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
2712 FakeNetworkPipe::Config network_config;
2713 network_config.loss_percent = 5;
2714 return new test::PacketTransport(
2715 sender_call, this, test::PacketTransport::kSender, network_config);
2716 }
2717
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002718 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002719 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01002720 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002721 return config;
2722 }
2723
stefanff483612015-12-21 03:14:00 -08002724 void ModifyVideoConfigs(
2725 VideoSendStream::Config* send_config,
2726 std::vector<VideoReceiveStream::Config>* receive_configs,
2727 VideoEncoderConfig* encoder_config) override {
sprangcd349d92016-07-13 09:11:28 -07002728 // Set low rates to avoid waiting for rampup.
2729 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2730 encoder_config->streams[i].min_bitrate_bps = 10000;
2731 encoder_config->streams[i].target_bitrate_bps = 15000;
2732 encoder_config->streams[i].max_bitrate_bps = 20000;
2733 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002734 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002735 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002736
sprangcd349d92016-07-13 09:11:28 -07002737 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2738 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
2739
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002740 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002741 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002742 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002743 expected_receive_ssrcs_.push_back(
2744 (*receive_configs)[i].rtp.remote_ssrc);
Peter Boströmdef398832015-05-27 17:59:11 +02002745 (*receive_configs)[i].render_delay_ms = kExpectedRenderDelayMs;
tommi2e82f382016-06-21 00:26:43 -07002746 (*receive_configs)[i].renderer = &receive_stream_renderer_;
sprangcd349d92016-07-13 09:11:28 -07002747 (*receive_configs)[i].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2748
2749 (*receive_configs)[i].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
2750 kSendRtxSsrcs[i];
2751 (*receive_configs)[i].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
2752 kSendRtxPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002753 }
sprangcd349d92016-07-13 09:11:28 -07002754
2755 for (size_t i = 0; i < kNumSsrcs; ++i)
2756 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
2757
Peter Boströmc6e16e32016-02-05 14:15:53 +01002758 // Use a delayed encoder to make sure we see CpuOveruseMetrics stats that
2759 // are non-zero.
2760 send_config->encoder_settings.encoder = &encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002761 }
2762
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002763 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00002764
stefanff483612015-12-21 03:14:00 -08002765 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002766 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002767 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002768 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002769 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002770 }
2771
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002772 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002773 Clock* clock = Clock::GetRealTimeClock();
2774 int64_t now = clock->TimeInMilliseconds();
2775 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
2776 bool receive_ok = false;
2777 bool send_ok = false;
2778
2779 while (now < stop_time) {
2780 if (!receive_ok)
2781 receive_ok = CheckReceiveStats();
2782 if (!send_ok)
2783 send_ok = CheckSendStats();
2784
2785 if (receive_ok && send_ok)
2786 return;
2787
2788 int64_t time_until_timout_ = stop_time - now;
2789 if (time_until_timout_ > 0)
Peter Boström5811a392015-12-10 13:02:50 +01002790 check_stats_event_.Wait(time_until_timout_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002791 now = clock->TimeInMilliseconds();
2792 }
2793
2794 ADD_FAILURE() << "Timed out waiting for filled stats.";
2795 for (std::map<std::string, bool>::const_iterator it =
2796 receive_stats_filled_.begin();
2797 it != receive_stats_filled_.end();
2798 ++it) {
2799 if (!it->second) {
2800 ADD_FAILURE() << "Missing receive stats: " << it->first;
2801 }
2802 }
2803
2804 for (std::map<std::string, bool>::const_iterator it =
2805 send_stats_filled_.begin();
2806 it != send_stats_filled_.end();
2807 ++it) {
2808 if (!it->second) {
2809 ADD_FAILURE() << "Missing send stats: " << it->first;
2810 }
2811 }
2812 }
2813
Peter Boströmc6e16e32016-02-05 14:15:53 +01002814 test::DelayedEncoder encoder_;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002815 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002816 std::map<std::string, bool> receive_stats_filled_;
2817
2818 VideoSendStream* send_stream_;
2819 std::map<std::string, bool> send_stats_filled_;
2820
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002821 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002822 std::set<uint32_t> expected_send_ssrcs_;
2823 std::string expected_cname_;
2824
Peter Boström5811a392015-12-10 13:02:50 +01002825 rtc::Event check_stats_event_;
tommi2e82f382016-06-21 00:26:43 -07002826 ReceiveStreamRenderer receive_stream_renderer_;
stefanf116bd02015-10-27 08:29:42 -07002827 } test;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002828
stefane74eef12016-01-08 06:47:13 -08002829 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002830}
2831
2832TEST_F(EndToEndTest, ReceiverReferenceTimeReportEnabled) {
2833 TestXrReceiverReferenceTimeReport(true);
2834}
2835
2836TEST_F(EndToEndTest, ReceiverReferenceTimeReportDisabled) {
2837 TestXrReceiverReferenceTimeReport(false);
2838}
2839
2840TEST_F(EndToEndTest, TestReceivedRtpPacketStats) {
2841 static const size_t kNumRtpPacketsToSend = 5;
2842 class ReceivedRtpStatsObserver : public test::EndToEndTest {
2843 public:
2844 ReceivedRtpStatsObserver()
2845 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002846 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002847 sent_rtp_(0) {}
2848
2849 private:
stefanff483612015-12-21 03:14:00 -08002850 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002851 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002852 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002853 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002854 }
2855
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002856 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002857 if (sent_rtp_ >= kNumRtpPacketsToSend) {
2858 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002859 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
Peter Boström5811a392015-12-10 13:02:50 +01002860 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002861 }
2862 return DROP_PACKET;
2863 }
2864 ++sent_rtp_;
2865 return SEND_PACKET;
2866 }
2867
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002868 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002869 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002870 << "Timed out while verifying number of received RTP packets.";
2871 }
2872
2873 VideoReceiveStream* receive_stream_;
2874 uint32_t sent_rtp_;
2875 } test;
2876
stefane74eef12016-01-08 06:47:13 -08002877 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002878}
2879
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002880TEST_F(EndToEndTest, SendsSetSsrc) { TestSendsSetSsrcs(1, false); }
2881
2882TEST_F(EndToEndTest, SendsSetSimulcastSsrcs) {
2883 TestSendsSetSsrcs(kNumSsrcs, false);
2884}
2885
2886TEST_F(EndToEndTest, CanSwitchToUseAllSsrcs) {
2887 TestSendsSetSsrcs(kNumSsrcs, true);
2888}
2889
mflodman@webrtc.orgf9460682014-07-24 16:41:25 +00002890TEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002891 class ObserveRedundantPayloads: public test::EndToEndTest {
2892 public:
2893 ObserveRedundantPayloads()
2894 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00002895 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002896 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
2897 }
2898 }
2899
2900 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002901 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002902 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002903 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002904
2905 if (!registered_rtx_ssrc_[header.ssrc])
2906 return SEND_PACKET;
2907
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002908 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002909 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002910 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002911
2912 if (!packet_is_redundant_payload)
2913 return SEND_PACKET;
2914
2915 if (!observed_redundant_retransmission_[header.ssrc]) {
2916 observed_redundant_retransmission_[header.ssrc] = true;
2917 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002918 observation_complete_.Set();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002919 }
2920
2921 return SEND_PACKET;
2922 }
2923
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002924 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002925
stefanff483612015-12-21 03:14:00 -08002926 void ModifyVideoConfigs(
2927 VideoSendStream::Config* send_config,
2928 std::vector<VideoReceiveStream::Config>* receive_configs,
2929 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002930 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002931 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2932 encoder_config->streams[i].min_bitrate_bps = 10000;
2933 encoder_config->streams[i].target_bitrate_bps = 15000;
2934 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002935 }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002936
2937 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002938
2939 for (size_t i = 0; i < kNumSsrcs; ++i)
2940 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00002941
2942 // Significantly higher than max bitrates for all video streams -> forcing
2943 // padding to trigger redundant padding on all RTX SSRCs.
2944 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002945 }
2946
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002947 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002948 EXPECT_TRUE(Wait())
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002949 << "Timed out while waiting for redundant payloads on all SSRCs.";
2950 }
2951
2952 private:
2953 size_t ssrcs_to_observe_;
2954 std::map<uint32_t, bool> observed_redundant_retransmission_;
2955 std::map<uint32_t, bool> registered_rtx_ssrc_;
2956 } test;
2957
stefane74eef12016-01-08 06:47:13 -08002958 RunBaseTest(&test);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002959}
2960
Danil Chapovalov70ffead2016-07-20 15:26:59 +02002961void EndToEndTest::TestRtpStatePreservation(bool use_rtx,
2962 bool provoke_rtcpsr_before_rtp) {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002963 class RtpSequenceObserver : public test::RtpRtcpObserver {
2964 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00002965 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002966 : test::RtpRtcpObserver(kDefaultTimeoutMs),
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002967 ssrcs_to_observe_(kNumSsrcs) {
2968 for (size_t i = 0; i < kNumSsrcs; ++i) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002969 configured_ssrcs_[kVideoSendSsrcs[i]] = true;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002970 if (use_rtx)
2971 configured_ssrcs_[kSendRtxSsrcs[i]] = true;
2972 }
2973 }
2974
2975 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
Peter Boströmf2f82832015-05-01 13:00:41 +02002976 rtc::CritScope lock(&crit_);
danilchap34877ee2016-02-01 08:25:04 -08002977 ssrc_observed_.clear();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002978 ssrcs_to_observe_ = num_expected_ssrcs;
2979 }
2980
2981 private:
Danil Chapovalov70ffead2016-07-20 15:26:59 +02002982 void ValidateTimestampGap(uint32_t ssrc,
2983 uint32_t timestamp,
2984 bool only_padding)
2985 EXCLUSIVE_LOCKS_REQUIRED(crit_) {
2986 static const int32_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
2987 auto timestamp_it = last_observed_timestamp_.find(ssrc);
2988 if (timestamp_it == last_observed_timestamp_.end()) {
2989 EXPECT_FALSE(only_padding);
2990 last_observed_timestamp_[ssrc] = timestamp;
2991 } else {
2992 // Verify timestamps are reasonably close.
2993 uint32_t latest_observed = timestamp_it->second;
2994 // Wraparound handling is unnecessary here as long as an int variable
2995 // is used to store the result.
2996 int32_t timestamp_gap = timestamp - latest_observed;
2997 EXPECT_LE(std::abs(timestamp_gap), kMaxTimestampGap)
2998 << "Gap in timestamps (" << latest_observed << " -> " << timestamp
2999 << ") too large for SSRC: " << ssrc << ".";
3000 timestamp_it->second = timestamp;
3001 }
3002 }
3003
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003004 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003005 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003006 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003007 const uint32_t ssrc = header.ssrc;
danilchap5c35cf92016-02-03 14:14:49 -08003008 const int64_t sequence_number =
3009 seq_numbers_unwrapper_.Unwrap(header.sequenceNumber);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003010 const uint32_t timestamp = header.timestamp;
danilchap34877ee2016-02-01 08:25:04 -08003011 const bool only_padding =
3012 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003013
3014 EXPECT_TRUE(configured_ssrcs_[ssrc])
3015 << "Received SSRC that wasn't configured: " << ssrc;
3016
danilchap5c35cf92016-02-03 14:14:49 -08003017 static const int64_t kMaxSequenceNumberGap = 100;
3018 std::list<int64_t>* seq_numbers = &last_observed_seq_numbers_[ssrc];
3019 if (seq_numbers->empty()) {
3020 seq_numbers->push_back(sequence_number);
3021 } else {
3022 // We shouldn't get replays of previous sequence numbers.
3023 for (int64_t observed : *seq_numbers) {
3024 EXPECT_NE(observed, sequence_number)
3025 << "Received sequence number " << sequence_number
3026 << " for SSRC " << ssrc << " 2nd time.";
3027 }
3028 // Verify sequence numbers are reasonably close.
3029 int64_t latest_observed = seq_numbers->back();
3030 int64_t sequence_number_gap = sequence_number - latest_observed;
3031 EXPECT_LE(std::abs(sequence_number_gap), kMaxSequenceNumberGap)
3032 << "Gap in sequence numbers (" << latest_observed << " -> "
3033 << sequence_number << ") too large for SSRC: " << ssrc << ".";
3034 seq_numbers->push_back(sequence_number);
3035 if (seq_numbers->size() >= kMaxSequenceNumberGap) {
3036 seq_numbers->pop_front();
3037 }
3038 }
3039
danilchap34877ee2016-02-01 08:25:04 -08003040 rtc::CritScope lock(&crit_);
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003041 ValidateTimestampGap(ssrc, timestamp, only_padding);
3042
danilchap34877ee2016-02-01 08:25:04 -08003043 // Wait for media packets on all ssrcs.
3044 if (!ssrc_observed_[ssrc] && !only_padding) {
3045 ssrc_observed_[ssrc] = true;
3046 if (--ssrcs_to_observe_ == 0)
3047 observation_complete_.Set();
3048 }
3049
danilchapf4b9c772016-01-28 06:14:24 -08003050 return SEND_PACKET;
3051 }
3052
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003053 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
3054 test::RtcpPacketParser rtcp_parser;
3055 rtcp_parser.Parse(packet, length);
3056 if (rtcp_parser.sender_report()->num_packets() > 0) {
3057 uint32_t ssrc = rtcp_parser.sender_report()->Ssrc();
3058 uint32_t rtcp_timestamp = rtcp_parser.sender_report()->RtpTimestamp();
3059
3060 rtc::CritScope lock(&crit_);
3061 ValidateTimestampGap(ssrc, rtcp_timestamp, false);
3062 }
3063 return SEND_PACKET;
3064 }
3065
danilchap5c35cf92016-02-03 14:14:49 -08003066 SequenceNumberUnwrapper seq_numbers_unwrapper_;
3067 std::map<uint32_t, std::list<int64_t>> last_observed_seq_numbers_;
danilchap34877ee2016-02-01 08:25:04 -08003068 std::map<uint32_t, uint32_t> last_observed_timestamp_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003069 std::map<uint32_t, bool> configured_ssrcs_;
3070
Peter Boströmf2f82832015-05-01 13:00:41 +02003071 rtc::CriticalSection crit_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003072 size_t ssrcs_to_observe_ GUARDED_BY(crit_);
danilchap34877ee2016-02-01 08:25:04 -08003073 std::map<uint32_t, bool> ssrc_observed_ GUARDED_BY(crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003074 } observer(use_rtx);
3075
solenberg4fbae2b2015-08-28 04:07:10 -07003076 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003077
stefanf116bd02015-10-27 08:29:42 -07003078 test::PacketTransport send_transport(sender_call_.get(), &observer,
3079 test::PacketTransport::kSender,
3080 FakeNetworkPipe::Config());
3081 test::PacketTransport receive_transport(nullptr, &observer,
3082 test::PacketTransport::kReceiver,
3083 FakeNetworkPipe::Config());
3084 send_transport.SetReceiver(receiver_call_->Receiver());
3085 receive_transport.SetReceiver(sender_call_->Receiver());
3086
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003087 CreateSendConfig(kNumSsrcs, 0, &send_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003088
3089 if (use_rtx) {
3090 for (size_t i = 0; i < kNumSsrcs; ++i) {
stefanff483612015-12-21 03:14:00 -08003091 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003092 }
stefanff483612015-12-21 03:14:00 -08003093 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003094 }
3095
3096 // Lower bitrates so that all streams send initially.
stefanff483612015-12-21 03:14:00 -08003097 for (size_t i = 0; i < video_encoder_config_.streams.size(); ++i) {
3098 video_encoder_config_.streams[i].min_bitrate_bps = 10000;
3099 video_encoder_config_.streams[i].target_bitrate_bps = 15000;
3100 video_encoder_config_.streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003101 }
3102
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003103 // Use the same total bitrates when sending a single stream to avoid lowering
3104 // the bitrate estimate and requiring a subsequent rampup.
stefanff483612015-12-21 03:14:00 -08003105 VideoEncoderConfig one_stream = video_encoder_config_;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003106 one_stream.streams.resize(1);
stefanff483612015-12-21 03:14:00 -08003107 for (size_t i = 1; i < video_encoder_config_.streams.size(); ++i) {
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003108 one_stream.streams.front().min_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003109 video_encoder_config_.streams[i].min_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003110 one_stream.streams.front().target_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003111 video_encoder_config_.streams[i].target_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003112 one_stream.streams.front().max_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003113 video_encoder_config_.streams[i].max_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003114 }
3115
stefanf116bd02015-10-27 08:29:42 -07003116 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003117
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003118 CreateVideoStreams();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003119 CreateFrameGeneratorCapturer();
3120
3121 Start();
Peter Boström5811a392015-12-10 13:02:50 +01003122 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003123 << "Timed out waiting for all SSRCs to send packets.";
3124
3125 // Test stream resetting more than once to make sure that the state doesn't
3126 // get set once (this could be due to using std::map::insert for instance).
3127 for (size_t i = 0; i < 3; ++i) {
3128 frame_generator_capturer_->Stop();
stefanff483612015-12-21 03:14:00 -08003129 sender_call_->DestroyVideoSendStream(video_send_stream_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003130
3131 // Re-create VideoSendStream with only one stream.
stefanff483612015-12-21 03:14:00 -08003132 video_send_stream_ =
3133 sender_call_->CreateVideoSendStream(video_send_config_, one_stream);
3134 video_send_stream_->Start();
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003135 if (provoke_rtcpsr_before_rtp) {
3136 // Rapid Resync Request forces sending RTCP Sender Report back.
3137 // Using this request speeds up this test because then there is no need
3138 // to wait for a second for periodic Sender Report.
3139 rtcp::RapidResyncRequest force_send_sr_back_request;
3140 rtc::Buffer packet = force_send_sr_back_request.Build();
3141 static_cast<webrtc::test::DirectTransport&>(receive_transport)
3142 .SendRtcp(packet.data(), packet.size());
3143 }
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003144 CreateFrameGeneratorCapturer();
3145 frame_generator_capturer_->Start();
3146
3147 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003148 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003149
3150 // Reconfigure back to use all streams.
stefanff483612015-12-21 03:14:00 -08003151 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003152 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003153 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003154 << "Timed out waiting for all SSRCs to send packets.";
3155
3156 // Reconfigure down to one stream.
stefanff483612015-12-21 03:14:00 -08003157 video_send_stream_->ReconfigureVideoEncoder(one_stream);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003158 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003159 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003160
3161 // Reconfigure back to use all streams.
stefanff483612015-12-21 03:14:00 -08003162 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003163 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003164 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003165 << "Timed out waiting for all SSRCs to send packets.";
3166 }
3167
stefanf116bd02015-10-27 08:29:42 -07003168 send_transport.StopSending();
3169 receive_transport.StopSending();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003170
3171 Stop();
3172 DestroyStreams();
3173}
3174
Peter Boströmfc968a22016-02-19 16:14:37 +01003175TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpState) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003176 TestRtpStatePreservation(false, false);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003177}
3178
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003179// These tests are flaky. See:
deadbeef1caff882016-06-27 13:09:52 -07003180// https://bugs.chromium.org/p/webrtc/issues/detail?id=4332
3181TEST_F(EndToEndTest, DISABLED_RestartingSendStreamPreservesRtpStatesWithRtx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003182 TestRtpStatePreservation(true, false);
3183}
3184
3185TEST_F(EndToEndTest,
3186 DISABLED_RestartingSendStreamKeepsRtpAndRtcpTimestampsSynced) {
3187 TestRtpStatePreservation(true, true);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003188}
3189
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003190TEST_F(EndToEndTest, RespectsNetworkState) {
3191 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
3192 // down blocks until no more packets will be sent.
3193
3194 // Pacer will send from its packet list and then send required padding before
3195 // checking paused_ again. This should be enough for one round of pacing,
3196 // otherwise increase.
3197 static const int kNumAcceptedDowntimeRtp = 5;
3198 // A single RTCP may be in the pipeline.
3199 static const int kNumAcceptedDowntimeRtcp = 1;
3200 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
3201 public:
3202 NetworkStateTest()
3203 : EndToEndTest(kDefaultTimeoutMs),
3204 FakeEncoder(Clock::GetRealTimeClock()),
Peter Boström5811a392015-12-10 13:02:50 +01003205 encoded_frames_(false, false),
3206 packet_event_(false, false),
sprang867fb522015-08-03 04:38:41 -07003207 sender_call_(nullptr),
3208 receiver_call_(nullptr),
Jelena Marusiccd670222015-07-16 09:30:09 +02003209 sender_state_(kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003210 sender_rtp_(0),
3211 sender_rtcp_(0),
3212 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003213 down_frames_(0) {}
3214
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003215 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003216 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003217 ++sender_rtp_;
Peter Boström5811a392015-12-10 13:02:50 +01003218 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003219 return SEND_PACKET;
3220 }
3221
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003222 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003223 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003224 ++sender_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003225 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003226 return SEND_PACKET;
3227 }
3228
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003229 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003230 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
3231 return SEND_PACKET;
3232 }
3233
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003234 Action OnReceiveRtcp(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 ++receiver_rtcp_;
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 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003242 sender_call_ = sender_call;
3243 receiver_call_ = receiver_call;
3244 }
3245
stefanff483612015-12-21 03:14:00 -08003246 void ModifyVideoConfigs(
3247 VideoSendStream::Config* send_config,
3248 std::vector<VideoReceiveStream::Config>* receive_configs,
3249 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003250 send_config->encoder_settings.encoder = this;
3251 }
3252
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003253 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003254 EXPECT_TRUE(encoded_frames_.Wait(kDefaultTimeoutMs))
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003255 << "No frames received by the encoder.";
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003256 // Wait for packets from both sender/receiver.
3257 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003258
skvlad7a43d252016-03-22 15:32:27 -07003259 // Sender-side network down for audio; there should be no effect on video
3260 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3261 WaitForPacketsOrSilence(false, false);
3262
3263 // Receiver-side network down for audio; no change expected
3264 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3265 WaitForPacketsOrSilence(false, false);
3266
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003267 // Sender-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003268 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003269 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003270 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003271 // After network goes down we shouldn't be encoding more frames.
Jelena Marusiccd670222015-07-16 09:30:09 +02003272 sender_state_ = kNetworkDown;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003273 }
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003274 // Wait for receiver-packets and no sender packets.
3275 WaitForPacketsOrSilence(true, false);
3276
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003277 // Receiver-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003278 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
3279 WaitForPacketsOrSilence(true, true);
3280
3281 // Network up for audio for both sides; video is still not expected to
3282 // start
3283 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
3284 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003285 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003286
3287 // Network back up again for both.
3288 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003289 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003290 // It's OK to encode frames again, as we're about to bring up the
3291 // network.
Jelena Marusiccd670222015-07-16 09:30:09 +02003292 sender_state_ = kNetworkUp;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003293 }
skvlad7a43d252016-03-22 15:32:27 -07003294 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
3295 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003296 WaitForPacketsOrSilence(false, false);
skvlad7a43d252016-03-22 15:32:27 -07003297
3298 // TODO(skvlad): add tests to verify that the audio streams are stopped
3299 // when the network goes down for audio once the workaround in
3300 // paced_sender.cc is removed.
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003301 }
3302
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07003303 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003304 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07003305 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003306 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003307 rtc::CritScope lock(&test_crit_);
Jelena Marusiccd670222015-07-16 09:30:09 +02003308 if (sender_state_ == kNetworkDown) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003309 ++down_frames_;
3310 EXPECT_LE(down_frames_, 1)
3311 << "Encoding more than one frame while network is down.";
3312 if (down_frames_ > 1)
Peter Boström5811a392015-12-10 13:02:50 +01003313 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003314 } else {
Peter Boström5811a392015-12-10 13:02:50 +01003315 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003316 }
3317 }
3318 return test::FakeEncoder::Encode(
3319 input_image, codec_specific_info, frame_types);
3320 }
3321
3322 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003323 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
3324 int64_t initial_time_ms = clock_->TimeInMilliseconds();
3325 int initial_sender_rtp;
3326 int initial_sender_rtcp;
3327 int initial_receiver_rtcp;
3328 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003329 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003330 initial_sender_rtp = sender_rtp_;
3331 initial_sender_rtcp = sender_rtcp_;
3332 initial_receiver_rtcp = receiver_rtcp_;
3333 }
3334 bool sender_done = false;
3335 bool receiver_done = false;
mflodmand1590b22015-12-09 07:07:59 -08003336 while (!sender_done || !receiver_done) {
Peter Boström5811a392015-12-10 13:02:50 +01003337 packet_event_.Wait(kSilenceTimeoutMs);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003338 int64_t time_now_ms = clock_->TimeInMilliseconds();
Peter Boströmf2f82832015-05-01 13:00:41 +02003339 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003340 if (sender_down) {
3341 ASSERT_LE(sender_rtp_ - initial_sender_rtp, kNumAcceptedDowntimeRtp)
3342 << "RTP sent during sender-side downtime.";
3343 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
3344 kNumAcceptedDowntimeRtcp)
3345 << "RTCP sent during sender-side downtime.";
3346 if (time_now_ms - initial_time_ms >=
3347 static_cast<int64_t>(kSilenceTimeoutMs)) {
3348 sender_done = true;
3349 }
3350 } else {
skvlad7a43d252016-03-22 15:32:27 -07003351 if (sender_rtp_ > initial_sender_rtp + kNumAcceptedDowntimeRtp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003352 sender_done = true;
3353 }
3354 if (receiver_down) {
3355 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
3356 kNumAcceptedDowntimeRtcp)
3357 << "RTCP sent during receiver-side downtime.";
3358 if (time_now_ms - initial_time_ms >=
3359 static_cast<int64_t>(kSilenceTimeoutMs)) {
3360 receiver_done = true;
3361 }
3362 } else {
skvlad7a43d252016-03-22 15:32:27 -07003363 if (receiver_rtcp_ > initial_receiver_rtcp + kNumAcceptedDowntimeRtcp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003364 receiver_done = true;
3365 }
3366 }
3367 }
3368
Peter Boströmf2f82832015-05-01 13:00:41 +02003369 rtc::CriticalSection test_crit_;
Peter Boström5811a392015-12-10 13:02:50 +01003370 rtc::Event encoded_frames_;
3371 rtc::Event packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003372 Call* sender_call_;
3373 Call* receiver_call_;
Jelena Marusiccd670222015-07-16 09:30:09 +02003374 NetworkState sender_state_ GUARDED_BY(test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003375 int sender_rtp_ GUARDED_BY(test_crit_);
3376 int sender_rtcp_ GUARDED_BY(test_crit_);
3377 int receiver_rtcp_ GUARDED_BY(test_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003378 int down_frames_ GUARDED_BY(test_crit_);
3379 } test;
3380
stefane74eef12016-01-08 06:47:13 -08003381 RunBaseTest(&test);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003382}
3383
danilchapa6a70072016-06-01 11:20:43 -07003384TEST_F(EndToEndTest, CallReportsRttForSender) {
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003385 static const int kSendDelayMs = 30;
3386 static const int kReceiveDelayMs = 70;
3387
solenberg4fbae2b2015-08-28 04:07:10 -07003388 CreateCalls(Call::Config(), Call::Config());
3389
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003390 FakeNetworkPipe::Config config;
3391 config.queue_delay_ms = kSendDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003392 test::DirectTransport sender_transport(config, sender_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003393 config.queue_delay_ms = kReceiveDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003394 test::DirectTransport receiver_transport(config, receiver_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003395 sender_transport.SetReceiver(receiver_call_->Receiver());
3396 receiver_transport.SetReceiver(sender_call_->Receiver());
3397
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003398 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07003399 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003400
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003401 CreateVideoStreams();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003402 CreateFrameGeneratorCapturer();
3403 Start();
3404
3405 int64_t start_time_ms = clock_->TimeInMilliseconds();
3406 while (true) {
3407 Call::Stats stats = sender_call_->GetStats();
3408 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
3409 clock_->TimeInMilliseconds())
3410 << "No RTT stats before timeout!";
3411 if (stats.rtt_ms != -1) {
3412 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs);
3413 break;
3414 }
3415 SleepMs(10);
3416 }
3417
3418 Stop();
3419 DestroyStreams();
3420}
3421
skvlad7a43d252016-03-22 15:32:27 -07003422void EndToEndTest::VerifyNewVideoSendStreamsRespectNetworkState(
3423 MediaType network_to_bring_down,
3424 VideoEncoder* encoder,
3425 Transport* transport) {
solenberg4fbae2b2015-08-28 04:07:10 -07003426 CreateSenderCall(Call::Config());
skvlad7a43d252016-03-22 15:32:27 -07003427 sender_call_->SignalChannelNetworkState(network_to_bring_down, kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003428
skvlad7a43d252016-03-22 15:32:27 -07003429 CreateSendConfig(1, 0, transport);
3430 video_send_config_.encoder_settings.encoder = encoder;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003431 CreateVideoStreams();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003432 CreateFrameGeneratorCapturer();
3433
3434 Start();
3435 SleepMs(kSilenceTimeoutMs);
3436 Stop();
3437
3438 DestroyStreams();
3439}
3440
skvlad7a43d252016-03-22 15:32:27 -07003441void EndToEndTest::VerifyNewVideoReceiveStreamsRespectNetworkState(
3442 MediaType network_to_bring_down,
3443 Transport* transport) {
solenberg4fbae2b2015-08-28 04:07:10 -07003444 CreateCalls(Call::Config(), Call::Config());
skvlad7a43d252016-03-22 15:32:27 -07003445 receiver_call_->SignalChannelNetworkState(network_to_bring_down,
3446 kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003447
stefanf116bd02015-10-27 08:29:42 -07003448 test::DirectTransport sender_transport(sender_call_.get());
solenberg4fbae2b2015-08-28 04:07:10 -07003449 sender_transport.SetReceiver(receiver_call_->Receiver());
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003450 CreateSendConfig(1, 0, &sender_transport);
skvlad7a43d252016-03-22 15:32:27 -07003451 CreateMatchingReceiveConfigs(transport);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003452 CreateVideoStreams();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003453 CreateFrameGeneratorCapturer();
3454
3455 Start();
3456 SleepMs(kSilenceTimeoutMs);
3457 Stop();
3458
3459 sender_transport.StopSending();
3460
3461 DestroyStreams();
3462}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00003463
skvlad7a43d252016-03-22 15:32:27 -07003464TEST_F(EndToEndTest, NewVideoSendStreamsRespectVideoNetworkDown) {
3465 class UnusedEncoder : public test::FakeEncoder {
3466 public:
3467 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
perkjfea93092016-05-14 00:58:48 -07003468
3469 int32_t InitEncode(const VideoCodec* config,
3470 int32_t number_of_cores,
3471 size_t max_payload_size) override {
3472 EXPECT_GT(config->startBitrate, 0u);
3473 return 0;
3474 }
skvlad7a43d252016-03-22 15:32:27 -07003475 int32_t Encode(const VideoFrame& input_image,
3476 const CodecSpecificInfo* codec_specific_info,
3477 const std::vector<FrameType>* frame_types) override {
3478 ADD_FAILURE() << "Unexpected frame encode.";
3479 return test::FakeEncoder::Encode(input_image, codec_specific_info,
3480 frame_types);
3481 }
3482 };
3483
3484 UnusedEncoder unused_encoder;
3485 UnusedTransport unused_transport;
3486 VerifyNewVideoSendStreamsRespectNetworkState(
3487 MediaType::VIDEO, &unused_encoder, &unused_transport);
3488}
3489
3490TEST_F(EndToEndTest, NewVideoSendStreamsIgnoreAudioNetworkDown) {
3491 class RequiredEncoder : public test::FakeEncoder {
3492 public:
3493 RequiredEncoder()
3494 : FakeEncoder(Clock::GetRealTimeClock()), encoded_frame_(false) {}
3495 ~RequiredEncoder() {
3496 if (!encoded_frame_) {
3497 ADD_FAILURE() << "Didn't encode an expected frame";
3498 }
3499 }
3500 int32_t Encode(const VideoFrame& input_image,
3501 const CodecSpecificInfo* codec_specific_info,
3502 const std::vector<FrameType>* frame_types) override {
3503 encoded_frame_ = true;
3504 return test::FakeEncoder::Encode(input_image, codec_specific_info,
3505 frame_types);
3506 }
3507
3508 private:
3509 bool encoded_frame_;
3510 };
3511
3512 RequiredTransport required_transport(true /*rtp*/, false /*rtcp*/);
3513 RequiredEncoder required_encoder;
3514 VerifyNewVideoSendStreamsRespectNetworkState(
3515 MediaType::AUDIO, &required_encoder, &required_transport);
3516}
3517
3518TEST_F(EndToEndTest, NewVideoReceiveStreamsRespectVideoNetworkDown) {
3519 UnusedTransport transport;
3520 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::VIDEO, &transport);
3521}
3522
3523TEST_F(EndToEndTest, NewVideoReceiveStreamsIgnoreAudioNetworkDown) {
3524 RequiredTransport transport(false /*rtp*/, true /*rtcp*/);
3525 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::AUDIO, &transport);
3526}
3527
Peter Boströmd7da1202015-06-05 14:09:38 +02003528void VerifyEmptyNackConfig(const NackConfig& config) {
3529 EXPECT_EQ(0, config.rtp_history_ms)
3530 << "Enabling NACK requires rtcp-fb: nack negotiation.";
3531}
3532
3533void VerifyEmptyFecConfig(const FecConfig& config) {
3534 EXPECT_EQ(-1, config.ulpfec_payload_type)
3535 << "Enabling FEC requires rtpmap: ulpfec negotiation.";
3536 EXPECT_EQ(-1, config.red_payload_type)
3537 << "Enabling FEC requires rtpmap: red negotiation.";
3538 EXPECT_EQ(-1, config.red_rtx_payload_type)
3539 << "Enabling RTX in FEC requires rtpmap: rtx negotiation.";
3540}
3541
3542TEST_F(EndToEndTest, VerifyDefaultSendConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003543 VideoSendStream::Config default_send_config(nullptr);
Peter Boströmd7da1202015-06-05 14:09:38 +02003544 EXPECT_EQ(0, default_send_config.rtp.nack.rtp_history_ms)
3545 << "Enabling NACK require rtcp-fb: nack negotiation.";
3546 EXPECT_TRUE(default_send_config.rtp.rtx.ssrcs.empty())
3547 << "Enabling RTX requires rtpmap: rtx negotiation.";
3548 EXPECT_TRUE(default_send_config.rtp.extensions.empty())
3549 << "Enabling RTP extensions require negotiation.";
3550
3551 VerifyEmptyNackConfig(default_send_config.rtp.nack);
3552 VerifyEmptyFecConfig(default_send_config.rtp.fec);
3553}
3554
3555TEST_F(EndToEndTest, VerifyDefaultReceiveConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003556 VideoReceiveStream::Config default_receive_config(nullptr);
pbosda903ea2015-10-02 02:36:56 -07003557 EXPECT_EQ(RtcpMode::kCompound, default_receive_config.rtp.rtcp_mode)
Peter Boströmd7da1202015-06-05 14:09:38 +02003558 << "Reduced-size RTCP require rtcp-rsize to be negotiated.";
3559 EXPECT_FALSE(default_receive_config.rtp.remb)
3560 << "REMB require rtcp-fb: goog-remb to be negotiated.";
3561 EXPECT_FALSE(
3562 default_receive_config.rtp.rtcp_xr.receiver_reference_time_report)
3563 << "RTCP XR settings require rtcp-xr to be negotiated.";
3564 EXPECT_TRUE(default_receive_config.rtp.rtx.empty())
3565 << "Enabling RTX requires rtpmap: rtx negotiation.";
3566 EXPECT_TRUE(default_receive_config.rtp.extensions.empty())
3567 << "Enabling RTP extensions require negotiation.";
3568
3569 VerifyEmptyNackConfig(default_receive_config.rtp.nack);
3570 VerifyEmptyFecConfig(default_receive_config.rtp.fec);
3571}
3572
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003573TEST_F(EndToEndTest, TransportSeqNumOnAudioAndVideo) {
3574 static const int kExtensionId = 8;
3575 class TransportSequenceNumberTest : public test::EndToEndTest {
3576 public:
3577 TransportSequenceNumberTest()
3578 : EndToEndTest(kDefaultTimeoutMs),
3579 video_observed_(false),
3580 audio_observed_(false) {
3581 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
3582 kExtensionId);
3583 }
3584
3585 size_t GetNumVideoStreams() const override { return 1; }
3586 size_t GetNumAudioStreams() const override { return 1; }
3587
3588 void ModifyVideoConfigs(
3589 VideoSendStream::Config* send_config,
3590 std::vector<VideoReceiveStream::Config>* receive_configs,
3591 VideoEncoderConfig* encoder_config) override {
3592 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07003593 send_config->rtp.extensions.push_back(RtpExtension(
3594 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003595 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3596 }
3597
3598 void ModifyAudioConfigs(
3599 AudioSendStream::Config* send_config,
3600 std::vector<AudioReceiveStream::Config>* receive_configs) override {
3601 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07003602 send_config->rtp.extensions.push_back(RtpExtension(
3603 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003604 (*receive_configs)[0].rtp.extensions.clear();
3605 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3606 }
3607
3608 Action OnSendRtp(const uint8_t* packet, size_t length) override {
3609 RTPHeader header;
3610 EXPECT_TRUE(parser_->Parse(packet, length, &header));
3611 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
3612 // Unwrap packet id and verify uniqueness.
3613 int64_t packet_id =
3614 unwrapper_.Unwrap(header.extension.transportSequenceNumber);
3615 EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
3616
3617 if (header.ssrc == kVideoSendSsrcs[0])
3618 video_observed_ = true;
3619 if (header.ssrc == kAudioSendSsrc)
3620 audio_observed_ = true;
3621 if (audio_observed_ && video_observed_ &&
3622 received_packet_ids_.size() == 50) {
3623 size_t packet_id_range =
3624 *received_packet_ids_.rbegin() - *received_packet_ids_.begin() + 1;
3625 EXPECT_EQ(received_packet_ids_.size(), packet_id_range);
3626 observation_complete_.Set();
3627 }
3628 return SEND_PACKET;
3629 }
3630
3631 void PerformTest() override {
3632 EXPECT_TRUE(Wait()) << "Timed out while waiting for audio and video "
3633 "packets with transport sequence number.";
3634 }
3635
3636 private:
3637 bool video_observed_;
3638 bool audio_observed_;
3639 SequenceNumberUnwrapper unwrapper_;
3640 std::set<int64_t> received_packet_ids_;
3641 } test;
3642
stefane74eef12016-01-08 06:47:13 -08003643 RunBaseTest(&test);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003644}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003645} // namespace webrtc