blob: e9e330fdc61de1f836db991caf65eeeb869e4ea8 [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>
16
17#include "testing/gtest/include/gtest/gtest.h"
18
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000019#include "webrtc/base/checks.h"
Erik Språng6b8d3552015-09-24 15:06:57 +020020#include "webrtc/base/event.h"
danilchap5c35cf92016-02-03 14:14:49 -080021#include "webrtc/base/timeutils.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"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000024#include "webrtc/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"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000028#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
hbosbab934b2016-01-27 01:36:03 -080029#include "webrtc/modules/video_coding/codecs/h264/include/h264.h"
marpan@webrtc.org5b883172014-11-01 06:10:48 +000030#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
31#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010032#include "webrtc/modules/video_coding/include/video_coding_defines.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010033#include "webrtc/system_wrappers/include/metrics.h"
34#include "webrtc/system_wrappers/include/sleep.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000035#include "webrtc/test/call_test.h"
36#include "webrtc/test/direct_transport.h"
37#include "webrtc/test/encoder_settings.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000038#include "webrtc/test/fake_decoder.h"
39#include "webrtc/test/fake_encoder.h"
40#include "webrtc/test/frame_generator.h"
41#include "webrtc/test/frame_generator_capturer.h"
Åsa Persson352b2d72015-04-15 18:00:40 +020042#include "webrtc/test/histogram.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000043#include "webrtc/test/null_transport.h"
asapersson@webrtc.org37c05592015-01-28 13:58:27 +000044#include "webrtc/test/rtcp_packet_parser.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000045#include "webrtc/test/rtp_rtcp_observer.h"
46#include "webrtc/test/testsupport/fileutils.h"
47#include "webrtc/test/testsupport/perf_test.h"
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +000048#include "webrtc/video_encoder.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000049
50namespace webrtc {
51
Peter Boström5811a392015-12-10 13:02:50 +010052static const int kSilenceTimeoutMs = 2000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000053
54class EndToEndTest : public test::CallTest {
55 public:
56 EndToEndTest() {}
57
58 virtual ~EndToEndTest() {
stefanff483612015-12-21 03:14:00 -080059 EXPECT_EQ(nullptr, video_send_stream_);
60 EXPECT_TRUE(video_receive_streams_.empty());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000061 }
62
63 protected:
pbos2d566682015-09-28 09:59:31 -070064 class UnusedTransport : public Transport {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000065 private:
stefan1d8a5062015-10-02 03:39:33 -070066 bool SendRtp(const uint8_t* packet,
67 size_t length,
68 const PacketOptions& options) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000069 ADD_FAILURE() << "Unexpected RTP sent.";
70 return false;
71 }
72
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000073 bool SendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000074 ADD_FAILURE() << "Unexpected RTCP sent.";
75 return false;
76 }
77 };
78
skvlad7a43d252016-03-22 15:32:27 -070079 class RequiredTransport : public Transport {
80 public:
81 RequiredTransport(bool rtp_required, bool rtcp_required)
82 : need_rtp_(rtp_required), need_rtcp_(rtcp_required) {}
83 ~RequiredTransport() {
84 if (need_rtp_) {
85 ADD_FAILURE() << "Expected RTP packet not sent.";
86 }
87 if (need_rtcp_) {
88 ADD_FAILURE() << "Expected RTCP packet not sent.";
89 }
90 }
91
92 private:
93 bool SendRtp(const uint8_t* packet,
94 size_t length,
95 const PacketOptions& options) override {
96 need_rtp_ = false;
97 return true;
98 }
99
100 bool SendRtcp(const uint8_t* packet, size_t length) override {
101 need_rtcp_ = false;
102 return true;
103 }
104 bool need_rtp_;
105 bool need_rtcp_;
106 };
107
Peter Boström39593972016-02-15 11:27:15 +0100108 void DecodesRetransmittedFrame(bool enable_rtx, bool enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000109 void ReceivesPliAndRecovers(int rtp_history_ms);
pbosda903ea2015-10-02 02:36:56 -0700110 void RespectsRtcpMode(RtcpMode rtcp_mode);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000111 void TestXrReceiverReferenceTimeReport(bool enable_rrtr);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000112 void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000113 void TestRtpStatePreservation(bool use_rtx);
sprangb4a1ae52015-12-03 08:10:08 -0800114 void VerifyHistogramStats(bool use_rtx, bool use_red, bool screenshare);
skvlad7a43d252016-03-22 15:32:27 -0700115 void VerifyNewVideoSendStreamsRespectNetworkState(
116 MediaType network_to_bring_down,
117 VideoEncoder* encoder,
118 Transport* transport);
119 void VerifyNewVideoReceiveStreamsRespectNetworkState(
120 MediaType network_to_bring_down,
121 Transport* transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000122};
123
124TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
solenberg4fbae2b2015-08-28 04:07:10 -0700125 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000126
solenberg4fbae2b2015-08-28 04:07:10 -0700127 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100128 CreateSendConfig(1, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700129 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000130
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100131 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000132
stefanff483612015-12-21 03:14:00 -0800133 video_receive_streams_[0]->Start();
134 video_receive_streams_[0]->Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000135
136 DestroyStreams();
137}
138
139TEST_F(EndToEndTest, ReceiverCanBeStoppedTwice) {
solenberg4fbae2b2015-08-28 04:07:10 -0700140 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000141
solenberg4fbae2b2015-08-28 04:07:10 -0700142 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100143 CreateSendConfig(1, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700144 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000145
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100146 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000147
stefanff483612015-12-21 03:14:00 -0800148 video_receive_streams_[0]->Stop();
149 video_receive_streams_[0]->Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000150
151 DestroyStreams();
152}
153
154TEST_F(EndToEndTest, RendersSingleDelayedFrame) {
155 static const int kWidth = 320;
156 static const int kHeight = 240;
157 // This constant is chosen to be higher than the timeout in the video_render
158 // module. This makes sure that frames aren't dropped if there are no other
159 // frames in the queue.
160 static const int kDelayRenderCallbackMs = 1000;
161
162 class Renderer : public VideoRenderer {
163 public:
Peter Boström5811a392015-12-10 13:02:50 +0100164 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000165
nisseeb83a1a2016-03-21 01:27:56 -0700166 void OnFrame(const VideoFrame& video_frame) override { event_.Set(); }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000167
Peter Boström5811a392015-12-10 13:02:50 +0100168 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000169
Peter Boström5811a392015-12-10 13:02:50 +0100170 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000171 } renderer;
172
173 class TestFrameCallback : public I420FrameCallback {
174 public:
Peter Boström5811a392015-12-10 13:02:50 +0100175 TestFrameCallback() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000176
Peter Boström5811a392015-12-10 13:02:50 +0100177 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000178
179 private:
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700180 void FrameCallback(VideoFrame* frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000181 SleepMs(kDelayRenderCallbackMs);
Peter Boström5811a392015-12-10 13:02:50 +0100182 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000183 }
184
Peter Boström5811a392015-12-10 13:02:50 +0100185 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000186 };
187
solenberg4fbae2b2015-08-28 04:07:10 -0700188 CreateCalls(Call::Config(), Call::Config());
189
stefanf116bd02015-10-27 08:29:42 -0700190 test::DirectTransport sender_transport(sender_call_.get());
191 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000192 sender_transport.SetReceiver(receiver_call_->Receiver());
193 receiver_transport.SetReceiver(sender_call_->Receiver());
194
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100195 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700196 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000197
198 TestFrameCallback pre_render_callback;
stefanff483612015-12-21 03:14:00 -0800199 video_receive_configs_[0].pre_render_callback = &pre_render_callback;
200 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000201
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100202 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000203 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000204
205 // Create frames that are smaller than the send width/height, this is done to
206 // check that the callbacks are done after processing video.
kwiberg27f982b2016-03-01 11:52:33 -0800207 std::unique_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000208 test::FrameGenerator::CreateChromaGenerator(kWidth, kHeight));
stefanff483612015-12-21 03:14:00 -0800209 video_send_stream_->Input()->IncomingCapturedFrame(
210 *frame_generator->NextFrame());
Peter Boström5811a392015-12-10 13:02:50 +0100211 EXPECT_TRUE(pre_render_callback.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000212 << "Timed out while waiting for pre-render callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100213 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000214 << "Timed out while waiting for the frame to render.";
215
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000216 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000217
218 sender_transport.StopSending();
219 receiver_transport.StopSending();
220
221 DestroyStreams();
222}
223
224TEST_F(EndToEndTest, TransmitsFirstFrame) {
225 class Renderer : public VideoRenderer {
226 public:
Peter Boström5811a392015-12-10 13:02:50 +0100227 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000228
nisseeb83a1a2016-03-21 01:27:56 -0700229 void OnFrame(const VideoFrame& video_frame) override { event_.Set(); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000230
Peter Boström5811a392015-12-10 13:02:50 +0100231 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000232
Peter Boström5811a392015-12-10 13:02:50 +0100233 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000234 } renderer;
235
solenberg4fbae2b2015-08-28 04:07:10 -0700236 CreateCalls(Call::Config(), Call::Config());
237
stefanf116bd02015-10-27 08:29:42 -0700238 test::DirectTransport sender_transport(sender_call_.get());
239 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000240 sender_transport.SetReceiver(receiver_call_->Receiver());
241 receiver_transport.SetReceiver(sender_call_->Receiver());
242
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100243 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700244 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -0800245 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000246
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100247 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000248 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000249
kwiberg27f982b2016-03-01 11:52:33 -0800250 std::unique_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000251 test::FrameGenerator::CreateChromaGenerator(
stefanff483612015-12-21 03:14:00 -0800252 video_encoder_config_.streams[0].width,
253 video_encoder_config_.streams[0].height));
254 video_send_stream_->Input()->IncomingCapturedFrame(
255 *frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000256
Peter Boström5811a392015-12-10 13:02:50 +0100257 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000258 << "Timed out while waiting for the frame to render.";
259
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000260 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000261
262 sender_transport.StopSending();
263 receiver_transport.StopSending();
264
265 DestroyStreams();
266}
267
marpan@webrtc.org5f1e2e42014-11-06 02:02:28 +0000268TEST_F(EndToEndTest, SendsAndReceivesVP9) {
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000269 class VP9Observer : public test::EndToEndTest, public VideoRenderer {
270 public:
271 VP9Observer()
272 : EndToEndTest(2 * kDefaultTimeoutMs),
273 encoder_(VideoEncoder::Create(VideoEncoder::kVp9)),
274 decoder_(VP9Decoder::Create()),
275 frame_counter_(0) {}
276
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000277 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100278 EXPECT_TRUE(Wait())
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000279 << "Timed out while waiting for enough frames to be decoded.";
280 }
281
stefanff483612015-12-21 03:14:00 -0800282 void ModifyVideoConfigs(
283 VideoSendStream::Config* send_config,
284 std::vector<VideoReceiveStream::Config>* receive_configs,
285 VideoEncoderConfig* encoder_config) override {
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000286 send_config->encoder_settings.encoder = encoder_.get();
287 send_config->encoder_settings.payload_name = "VP9";
pbosa7d70542015-07-07 07:35:49 -0700288 send_config->encoder_settings.payload_type = 124;
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000289 encoder_config->streams[0].min_bitrate_bps = 50000;
290 encoder_config->streams[0].target_bitrate_bps =
291 encoder_config->streams[0].max_bitrate_bps = 2000000;
292
293 (*receive_configs)[0].renderer = this;
294 (*receive_configs)[0].decoders.resize(1);
295 (*receive_configs)[0].decoders[0].payload_type =
296 send_config->encoder_settings.payload_type;
297 (*receive_configs)[0].decoders[0].payload_name =
298 send_config->encoder_settings.payload_name;
299 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
300 }
301
nisseeb83a1a2016-03-21 01:27:56 -0700302 void OnFrame(const VideoFrame& video_frame) override {
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000303 const int kRequiredFrames = 500;
304 if (++frame_counter_ == kRequiredFrames)
Peter Boström5811a392015-12-10 13:02:50 +0100305 observation_complete_.Set();
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000306 }
307
308 private:
kwiberg27f982b2016-03-01 11:52:33 -0800309 std::unique_ptr<webrtc::VideoEncoder> encoder_;
310 std::unique_ptr<webrtc::VideoDecoder> decoder_;
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000311 int frame_counter_;
312 } test;
313
stefane74eef12016-01-08 06:47:13 -0800314 RunBaseTest(&test);
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000315}
316
hbosbab934b2016-01-27 01:36:03 -0800317#if defined(WEBRTC_END_TO_END_H264_TESTS)
318
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000319TEST_F(EndToEndTest, SendsAndReceivesH264) {
320 class H264Observer : public test::EndToEndTest, public VideoRenderer {
321 public:
322 H264Observer()
323 : EndToEndTest(2 * kDefaultTimeoutMs),
hbosbab934b2016-01-27 01:36:03 -0800324 encoder_(VideoEncoder::Create(VideoEncoder::kH264)),
325 decoder_(H264Decoder::Create()),
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000326 frame_counter_(0) {}
327
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000328 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100329 EXPECT_TRUE(Wait())
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000330 << "Timed out while waiting for enough frames to be decoded.";
331 }
332
stefanff483612015-12-21 03:14:00 -0800333 void ModifyVideoConfigs(
334 VideoSendStream::Config* send_config,
335 std::vector<VideoReceiveStream::Config>* receive_configs,
336 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org8278c072015-02-23 11:11:49 +0000337 send_config->rtp.nack.rtp_history_ms =
338 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
hbosbab934b2016-01-27 01:36:03 -0800339 send_config->encoder_settings.encoder = encoder_.get();
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000340 send_config->encoder_settings.payload_name = "H264";
hbosbab934b2016-01-27 01:36:03 -0800341 send_config->encoder_settings.payload_type = 126;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000342 encoder_config->streams[0].min_bitrate_bps = 50000;
343 encoder_config->streams[0].target_bitrate_bps =
344 encoder_config->streams[0].max_bitrate_bps = 2000000;
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000345
346 (*receive_configs)[0].renderer = this;
pbos@webrtc.org776e6f22014-10-29 15:28:39 +0000347 (*receive_configs)[0].decoders.resize(1);
348 (*receive_configs)[0].decoders[0].payload_type =
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000349 send_config->encoder_settings.payload_type;
pbos@webrtc.org776e6f22014-10-29 15:28:39 +0000350 (*receive_configs)[0].decoders[0].payload_name =
351 send_config->encoder_settings.payload_name;
hbosbab934b2016-01-27 01:36:03 -0800352 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000353 }
354
nisseeb83a1a2016-03-21 01:27:56 -0700355 void OnFrame(const VideoFrame& video_frame) override {
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000356 const int kRequiredFrames = 500;
357 if (++frame_counter_ == kRequiredFrames)
Peter Boström5811a392015-12-10 13:02:50 +0100358 observation_complete_.Set();
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000359 }
360
361 private:
kwiberg27f982b2016-03-01 11:52:33 -0800362 std::unique_ptr<webrtc::VideoEncoder> encoder_;
363 std::unique_ptr<webrtc::VideoDecoder> decoder_;
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000364 int frame_counter_;
365 } test;
366
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) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000491 class FecRenderObserver : public test::EndToEndTest, public VideoRenderer {
492 public:
493 FecRenderObserver()
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000494 : EndToEndTest(kDefaultTimeoutMs), state_(kFirstPacket) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000495
496 private:
stefanf116bd02015-10-27 08:29:42 -0700497 Action OnSendRtp(const uint8_t* packet, size_t length) override {
498 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000499 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000500 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000501
Stefan Holmer01b48882015-05-05 10:21:24 +0200502 int encapsulated_payload_type = -1;
503 if (header.payloadType == kRedPayloadType) {
504 encapsulated_payload_type =
505 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100506 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200507 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
508 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100509 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200510 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000511
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000512 if (protected_sequence_numbers_.count(header.sequenceNumber) != 0) {
513 // Retransmitted packet, should not count.
514 protected_sequence_numbers_.erase(header.sequenceNumber);
515 EXPECT_GT(protected_timestamps_.count(header.timestamp), 0u);
516 protected_timestamps_.erase(header.timestamp);
517 return SEND_PACKET;
518 }
519
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000520 switch (state_) {
521 case kFirstPacket:
522 state_ = kDropEveryOtherPacketUntilFec;
523 break;
524 case kDropEveryOtherPacketUntilFec:
525 if (encapsulated_payload_type == kUlpfecPayloadType) {
526 state_ = kDropNextMediaPacket;
527 return SEND_PACKET;
528 }
529 if (header.sequenceNumber % 2 == 0)
530 return DROP_PACKET;
531 break;
532 case kDropNextMediaPacket:
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100533 if (encapsulated_payload_type == kFakeVideoSendPayloadType) {
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000534 protected_sequence_numbers_.insert(header.sequenceNumber);
535 protected_timestamps_.insert(header.timestamp);
536 state_ = kDropEveryOtherPacketUntilFec;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000537 return DROP_PACKET;
538 }
539 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000540 }
541
542 return SEND_PACKET;
543 }
544
nisseeb83a1a2016-03-21 01:27:56 -0700545 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200546 rtc::CritScope lock(&crit_);
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000547 // Rendering frame with timestamp of packet that was dropped -> FEC
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000548 // protection worked.
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000549 if (protected_timestamps_.count(video_frame.timestamp()) != 0)
Peter Boström5811a392015-12-10 13:02:50 +0100550 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000551 }
552
553 enum {
554 kFirstPacket,
555 kDropEveryOtherPacketUntilFec,
556 kDropNextMediaPacket,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000557 } state_;
558
stefanff483612015-12-21 03:14:00 -0800559 void ModifyVideoConfigs(
560 VideoSendStream::Config* send_config,
561 std::vector<VideoReceiveStream::Config>* receive_configs,
562 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000563 // TODO(pbos): Run this test with combined NACK/FEC enabled as well.
564 // int rtp_history_ms = 1000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000565 // (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000566 // send_config->rtp.nack.rtp_history_ms = rtp_history_ms;
567 send_config->rtp.fec.red_payload_type = kRedPayloadType;
568 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
569
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000570 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
571 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
572 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000573 }
574
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000575 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100576 EXPECT_TRUE(Wait())
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000577 << "Timed out waiting for dropped frames frames to be rendered.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000578 }
579
stefanf116bd02015-10-27 08:29:42 -0700580 rtc::CriticalSection crit_;
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000581 std::set<uint32_t> protected_sequence_numbers_ GUARDED_BY(crit_);
582 std::set<uint32_t> protected_timestamps_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000583 } test;
584
stefane74eef12016-01-08 06:47:13 -0800585 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000586}
587
Henrik Kjellanderdb313b62015-04-02 08:45:41 +0200588// Flacky on all platforms. See webrtc:4328.
589TEST_F(EndToEndTest, DISABLED_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),
597 last_sequence_number_(0) {}
598
599 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000600 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800601 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000602 RTPHeader header;
603 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000604
Stefan Holmer01b48882015-05-05 10:21:24 +0200605 int encapsulated_payload_type = -1;
606 if (header.payloadType == kRedPayloadType) {
607 encapsulated_payload_type =
608 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100609 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200610 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
611 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100612 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200613 }
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000614
615 if (has_last_sequence_number_ &&
616 !IsNewerSequenceNumber(header.sequenceNumber,
617 last_sequence_number_)) {
618 // Drop retransmitted packets.
619 return DROP_PACKET;
620 }
621 last_sequence_number_ = header.sequenceNumber;
622 has_last_sequence_number_ = true;
623
624 bool fec_packet = encapsulated_payload_type == kUlpfecPayloadType;
625 switch (state_) {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000626 case kFirstPacket:
627 state_ = kDropEveryOtherPacketUntilFec;
628 break;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000629 case kDropEveryOtherPacketUntilFec:
630 if (fec_packet) {
631 state_ = kDropAllMediaPacketsUntilFec;
632 } else if (header.sequenceNumber % 2 == 0) {
633 return DROP_PACKET;
634 }
635 break;
636 case kDropAllMediaPacketsUntilFec:
637 if (!fec_packet)
638 return DROP_PACKET;
639 fec_sequence_number_ = header.sequenceNumber;
640 state_ = kVerifyFecPacketNotInNackList;
641 break;
642 case kVerifyFecPacketNotInNackList:
643 // Continue to drop packets. Make sure no frame can be decoded.
644 if (fec_packet || header.sequenceNumber % 2 == 0)
645 return DROP_PACKET;
646 break;
647 }
648 return SEND_PACKET;
649 }
650
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000651 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800652 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000653 if (state_ == kVerifyFecPacketNotInNackList) {
654 test::RtcpPacketParser rtcp_parser;
655 rtcp_parser.Parse(packet, length);
656 std::vector<uint16_t> nacks = rtcp_parser.nack_item()->last_nack_list();
657 if (!nacks.empty() &&
658 IsNewerSequenceNumber(nacks.back(), fec_sequence_number_)) {
659 EXPECT_TRUE(std::find(
660 nacks.begin(), nacks.end(), fec_sequence_number_) == nacks.end());
Peter Boström5811a392015-12-10 13:02:50 +0100661 observation_complete_.Set();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000662 }
663 }
664 return SEND_PACKET;
665 }
666
stefane74eef12016-01-08 06:47:13 -0800667 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
668 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
669 // Configure some network delay.
670 const int kNetworkDelayMs = 50;
671 FakeNetworkPipe::Config config;
672 config.queue_delay_ms = kNetworkDelayMs;
673 return new test::PacketTransport(sender_call, this,
674 test::PacketTransport::kSender, config);
675 }
676
Stefan Holmere5904162015-03-26 11:11:06 +0100677 // TODO(holmer): Investigate why we don't send FEC packets when the bitrate
678 // is 10 kbps.
679 Call::Config GetSenderCallConfig() override {
solenberg4fbae2b2015-08-28 04:07:10 -0700680 Call::Config config;
Stefan Holmere5904162015-03-26 11:11:06 +0100681 const int kMinBitrateBps = 30000;
682 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
683 return config;
684 }
685
stefanff483612015-12-21 03:14:00 -0800686 void ModifyVideoConfigs(
687 VideoSendStream::Config* send_config,
688 std::vector<VideoReceiveStream::Config>* receive_configs,
689 VideoEncoderConfig* encoder_config) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000690 // Configure hybrid NACK/FEC.
691 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
692 send_config->rtp.fec.red_payload_type = kRedPayloadType;
693 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
694 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
695 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
696 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
697 }
698
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000699 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100700 EXPECT_TRUE(Wait())
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000701 << "Timed out while waiting for FEC packets to be received.";
702 }
703
704 enum {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000705 kFirstPacket,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000706 kDropEveryOtherPacketUntilFec,
707 kDropAllMediaPacketsUntilFec,
708 kVerifyFecPacketNotInNackList,
709 } state_;
710
stefan608213e2015-11-01 14:56:10 -0800711 rtc::CriticalSection crit_;
712 uint16_t fec_sequence_number_ GUARDED_BY(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000713 bool has_last_sequence_number_;
714 uint16_t last_sequence_number_;
stefanf116bd02015-10-27 08:29:42 -0700715 } test;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000716
stefane74eef12016-01-08 06:47:13 -0800717 RunBaseTest(&test);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000718}
719
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000720// This test drops second RTP packet with a marker bit set, makes sure it's
721// retransmitted and renders. Retransmission SSRCs are also checked.
Peter Boström39593972016-02-15 11:27:15 +0100722void EndToEndTest::DecodesRetransmittedFrame(bool enable_rtx, bool enable_red) {
Peter Boström67680c12016-02-17 11:10:04 +0100723 static const int kDroppedFrameNumber = 10;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000724 class RetransmissionObserver : public test::EndToEndTest,
725 public I420FrameCallback {
726 public:
Peter Boström39593972016-02-15 11:27:15 +0100727 RetransmissionObserver(bool enable_rtx, bool enable_red)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000728 : EndToEndTest(kDefaultTimeoutMs),
Peter Boström39593972016-02-15 11:27:15 +0100729 payload_type_(GetPayloadType(false, enable_red)),
730 retransmission_ssrc_(enable_rtx ? kSendRtxSsrcs[0]
731 : kVideoSendSsrcs[0]),
732 retransmission_payload_type_(GetPayloadType(enable_rtx, enable_red)),
733 encoder_(VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000734 marker_bits_observed_(0),
735 retransmitted_timestamp_(0),
736 frame_retransmitted_(false) {}
737
738 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000739 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700740 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000741 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000742 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000743
Peter Boström67680c12016-02-17 11:10:04 +0100744 // Ignore padding-only packets over RTX.
745 if (header.payloadType != payload_type_) {
746 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
747 if (length == header.headerLength + header.paddingLength)
748 return SEND_PACKET;
Stefan Holmer586b19b2015-09-18 11:14:31 +0200749 }
Peter Boström67680c12016-02-17 11:10:04 +0100750
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000751 if (header.timestamp == retransmitted_timestamp_) {
752 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
753 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
754 frame_retransmitted_ = true;
755 return SEND_PACKET;
756 }
757
Stefan Holmer10880012016-02-03 13:29:59 +0100758 EXPECT_EQ(kVideoSendSsrcs[0], header.ssrc)
759 << "Payload type " << static_cast<int>(header.payloadType)
760 << " not expected.";
Shao Changbine62202f2015-04-21 20:24:50 +0800761 EXPECT_EQ(payload_type_, header.payloadType);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000762
Stefan Holmer586b19b2015-09-18 11:14:31 +0200763 // Found the final packet of the frame to inflict loss to, drop this and
764 // expect a retransmission.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000765 if (header.markerBit && ++marker_bits_observed_ == kDroppedFrameNumber) {
766 retransmitted_timestamp_ = header.timestamp;
767 return DROP_PACKET;
768 }
769
770 return SEND_PACKET;
771 }
772
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700773 void FrameCallback(VideoFrame* frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200774 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000775 if (frame->timestamp() == retransmitted_timestamp_) {
776 EXPECT_TRUE(frame_retransmitted_);
Peter Boström5811a392015-12-10 13:02:50 +0100777 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000778 }
779 }
780
stefanff483612015-12-21 03:14:00 -0800781 void ModifyVideoConfigs(
782 VideoSendStream::Config* send_config,
783 std::vector<VideoReceiveStream::Config>* receive_configs,
784 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000785 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000786 (*receive_configs)[0].pre_render_callback = this;
787 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
Shao Changbine62202f2015-04-21 20:24:50 +0800788
789 if (payload_type_ == kRedPayloadType) {
790 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
791 send_config->rtp.fec.red_payload_type = kRedPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +0100792 if (retransmission_ssrc_ == kSendRtxSsrcs[0])
793 send_config->rtp.fec.red_rtx_payload_type = kRtxRedPayloadType;
794 (*receive_configs)[0].rtp.fec.ulpfec_payload_type =
795 send_config->rtp.fec.ulpfec_payload_type;
796 (*receive_configs)[0].rtp.fec.red_payload_type =
797 send_config->rtp.fec.red_payload_type;
798 (*receive_configs)[0].rtp.fec.red_rtx_payload_type =
799 send_config->rtp.fec.red_rtx_payload_type;
Shao Changbine62202f2015-04-21 20:24:50 +0800800 }
801
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000802 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
803 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000804 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +0100805 (*receive_configs)[0].rtp.rtx[payload_type_].ssrc = kSendRtxSsrcs[0];
806 (*receive_configs)[0].rtp.rtx[payload_type_].payload_type =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000807 kSendRtxPayloadType;
808 }
Peter Boström39593972016-02-15 11:27:15 +0100809 // Configure encoding and decoding with VP8, since generic packetization
810 // doesn't support FEC with NACK.
811 RTC_DCHECK_EQ(1u, (*receive_configs)[0].decoders.size());
812 send_config->encoder_settings.encoder = encoder_.get();
813 send_config->encoder_settings.payload_name = "VP8";
814 (*receive_configs)[0].decoders[0].payload_name = "VP8";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000815 }
816
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000817 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100818 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000819 << "Timed out while waiting for retransmission to render.";
820 }
821
Shao Changbine62202f2015-04-21 20:24:50 +0800822 int GetPayloadType(bool use_rtx, bool use_red) {
Stefan Holmer10880012016-02-03 13:29:59 +0100823 if (use_red) {
824 if (use_rtx)
825 return kRtxRedPayloadType;
826 return kRedPayloadType;
827 }
828 if (use_rtx)
829 return kSendRtxPayloadType;
830 return kFakeVideoSendPayloadType;
Shao Changbine62202f2015-04-21 20:24:50 +0800831 }
832
stefanf116bd02015-10-27 08:29:42 -0700833 rtc::CriticalSection crit_;
Shao Changbine62202f2015-04-21 20:24:50 +0800834 const int payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000835 const uint32_t retransmission_ssrc_;
836 const int retransmission_payload_type_;
kwiberg27f982b2016-03-01 11:52:33 -0800837 std::unique_ptr<VideoEncoder> encoder_;
Peter Boström39593972016-02-15 11:27:15 +0100838 const std::string payload_name_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000839 int marker_bits_observed_;
stefanf116bd02015-10-27 08:29:42 -0700840 uint32_t retransmitted_timestamp_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000841 bool frame_retransmitted_;
Peter Boström39593972016-02-15 11:27:15 +0100842 } test(enable_rtx, enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000843
stefane74eef12016-01-08 06:47:13 -0800844 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000845}
846
847TEST_F(EndToEndTest, DecodesRetransmittedFrame) {
Shao Changbine62202f2015-04-21 20:24:50 +0800848 DecodesRetransmittedFrame(false, false);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000849}
850
851TEST_F(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +0800852 DecodesRetransmittedFrame(true, false);
853}
854
855TEST_F(EndToEndTest, DecodesRetransmittedFrameByRed) {
856 DecodesRetransmittedFrame(false, true);
857}
858
859TEST_F(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
860 DecodesRetransmittedFrame(true, true);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000861}
862
andresp@webrtc.org02686112014-09-19 08:24:19 +0000863TEST_F(EndToEndTest, UsesFrameCallbacks) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000864 static const int kWidth = 320;
865 static const int kHeight = 240;
866
867 class Renderer : public VideoRenderer {
868 public:
Peter Boström5811a392015-12-10 13:02:50 +0100869 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000870
nisseeb83a1a2016-03-21 01:27:56 -0700871 void OnFrame(const VideoFrame& video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000872 EXPECT_EQ(0, *video_frame.buffer(kYPlane))
873 << "Rendered frame should have zero luma which is applied by the "
874 "pre-render callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100875 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000876 }
877
Peter Boström5811a392015-12-10 13:02:50 +0100878 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
879 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000880 } renderer;
881
882 class TestFrameCallback : public I420FrameCallback {
883 public:
884 TestFrameCallback(int expected_luma_byte, int next_luma_byte)
Peter Boström5811a392015-12-10 13:02:50 +0100885 : event_(false, false),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000886 expected_luma_byte_(expected_luma_byte),
887 next_luma_byte_(next_luma_byte) {}
888
Peter Boström5811a392015-12-10 13:02:50 +0100889 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000890
891 private:
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700892 virtual void FrameCallback(VideoFrame* frame) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000893 EXPECT_EQ(kWidth, frame->width())
894 << "Width not as expected, callback done before resize?";
895 EXPECT_EQ(kHeight, frame->height())
896 << "Height not as expected, callback done before resize?";
897
898 // Previous luma specified, observed luma should be fairly close.
899 if (expected_luma_byte_ != -1) {
900 EXPECT_NEAR(expected_luma_byte_, *frame->buffer(kYPlane), 10);
901 }
902
903 memset(frame->buffer(kYPlane),
904 next_luma_byte_,
905 frame->allocated_size(kYPlane));
906
Peter Boström5811a392015-12-10 13:02:50 +0100907 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000908 }
909
Peter Boström5811a392015-12-10 13:02:50 +0100910 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000911 int expected_luma_byte_;
912 int next_luma_byte_;
913 };
914
915 TestFrameCallback pre_encode_callback(-1, 255); // Changes luma to 255.
916 TestFrameCallback pre_render_callback(255, 0); // Changes luma from 255 to 0.
917
solenberg4fbae2b2015-08-28 04:07:10 -0700918 CreateCalls(Call::Config(), Call::Config());
919
stefanf116bd02015-10-27 08:29:42 -0700920 test::DirectTransport sender_transport(sender_call_.get());
921 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000922 sender_transport.SetReceiver(receiver_call_->Receiver());
923 receiver_transport.SetReceiver(sender_call_->Receiver());
924
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100925 CreateSendConfig(1, 0, &sender_transport);
kwiberg27f982b2016-03-01 11:52:33 -0800926 std::unique_ptr<VideoEncoder> encoder(
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +0000927 VideoEncoder::Create(VideoEncoder::kVp8));
stefanff483612015-12-21 03:14:00 -0800928 video_send_config_.encoder_settings.encoder = encoder.get();
929 video_send_config_.encoder_settings.payload_name = "VP8";
930 ASSERT_EQ(1u, video_encoder_config_.streams.size()) << "Test setup error.";
931 video_encoder_config_.streams[0].width = kWidth;
932 video_encoder_config_.streams[0].height = kHeight;
933 video_send_config_.pre_encode_callback = &pre_encode_callback;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000934
solenberg4fbae2b2015-08-28 04:07:10 -0700935 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -0800936 video_receive_configs_[0].pre_render_callback = &pre_render_callback;
937 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000938
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100939 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000940 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000941
942 // Create frames that are smaller than the send width/height, this is done to
943 // check that the callbacks are done after processing video.
kwiberg27f982b2016-03-01 11:52:33 -0800944 std::unique_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000945 test::FrameGenerator::CreateChromaGenerator(kWidth / 2, kHeight / 2));
stefanff483612015-12-21 03:14:00 -0800946 video_send_stream_->Input()->IncomingCapturedFrame(
947 *frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000948
Peter Boström5811a392015-12-10 13:02:50 +0100949 EXPECT_TRUE(pre_encode_callback.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000950 << "Timed out while waiting for pre-encode callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100951 EXPECT_TRUE(pre_render_callback.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000952 << "Timed out while waiting for pre-render callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100953 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000954 << "Timed out while waiting for the frame to render.";
955
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000956 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000957
958 sender_transport.StopSending();
959 receiver_transport.StopSending();
960
961 DestroyStreams();
962}
963
964void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
965 static const int kPacketsToDrop = 1;
966
967 class PliObserver : public test::EndToEndTest, public VideoRenderer {
968 public:
969 explicit PliObserver(int rtp_history_ms)
970 : EndToEndTest(kLongTimeoutMs),
971 rtp_history_ms_(rtp_history_ms),
972 nack_enabled_(rtp_history_ms > 0),
973 highest_dropped_timestamp_(0),
974 frames_to_drop_(0),
975 received_pli_(false) {}
976
977 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000978 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700979 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000980 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000981 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000982
983 // Drop all retransmitted packets to force a PLI.
984 if (header.timestamp <= highest_dropped_timestamp_)
985 return DROP_PACKET;
986
987 if (frames_to_drop_ > 0) {
988 highest_dropped_timestamp_ = header.timestamp;
989 --frames_to_drop_;
990 return DROP_PACKET;
991 }
992
993 return SEND_PACKET;
994 }
995
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000996 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700997 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000998 RTCPUtility::RTCPParserV2 parser(packet, length, true);
999 EXPECT_TRUE(parser.IsValid());
1000
1001 for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02001002 packet_type != RTCPUtility::RTCPPacketTypes::kInvalid;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001003 packet_type = parser.Iterate()) {
1004 if (!nack_enabled_)
Erik Språng242e22b2015-05-11 10:17:43 +02001005 EXPECT_NE(packet_type, RTCPUtility::RTCPPacketTypes::kRtpfbNack);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001006
Erik Språng242e22b2015-05-11 10:17:43 +02001007 if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbPli) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001008 received_pli_ = true;
1009 break;
1010 }
1011 }
1012 return SEND_PACKET;
1013 }
1014
nisseeb83a1a2016-03-21 01:27:56 -07001015 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001016 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001017 if (received_pli_ &&
1018 video_frame.timestamp() > highest_dropped_timestamp_) {
Peter Boström5811a392015-12-10 13:02:50 +01001019 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001020 }
1021 if (!received_pli_)
1022 frames_to_drop_ = kPacketsToDrop;
1023 }
1024
stefanff483612015-12-21 03:14:00 -08001025 void ModifyVideoConfigs(
1026 VideoSendStream::Config* send_config,
1027 std::vector<VideoReceiveStream::Config>* receive_configs,
1028 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001029 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001030 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
1031 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001032 }
1033
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001034 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001035 EXPECT_TRUE(Wait()) << "Timed out waiting for PLI to be "
1036 "received and a frame to be "
1037 "rendered afterwards.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001038 }
1039
stefanf116bd02015-10-27 08:29:42 -07001040 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001041 int rtp_history_ms_;
1042 bool nack_enabled_;
stefanf116bd02015-10-27 08:29:42 -07001043 uint32_t highest_dropped_timestamp_ GUARDED_BY(&crit_);
1044 int frames_to_drop_ GUARDED_BY(&crit_);
1045 bool received_pli_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001046 } test(rtp_history_ms);
1047
stefane74eef12016-01-08 06:47:13 -08001048 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001049}
1050
1051TEST_F(EndToEndTest, ReceivesPliAndRecoversWithNack) {
1052 ReceivesPliAndRecovers(1000);
1053}
1054
jbauchdb81ffd2015-11-23 03:59:02 -08001055TEST_F(EndToEndTest, ReceivesPliAndRecoversWithoutNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001056 ReceivesPliAndRecovers(0);
1057}
1058
1059TEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
1060 class PacketInputObserver : public PacketReceiver {
1061 public:
1062 explicit PacketInputObserver(PacketReceiver* receiver)
Peter Boström5811a392015-12-10 13:02:50 +01001063 : receiver_(receiver), delivered_packet_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001064
Peter Boström5811a392015-12-10 13:02:50 +01001065 bool Wait() { return delivered_packet_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001066
1067 private:
stefan68786d22015-09-08 05:36:15 -07001068 DeliveryStatus DeliverPacket(MediaType media_type,
1069 const uint8_t* packet,
1070 size_t length,
1071 const PacketTime& packet_time) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001072 if (RtpHeaderParser::IsRtcp(packet, length)) {
stefan68786d22015-09-08 05:36:15 -07001073 return receiver_->DeliverPacket(media_type, packet, length,
1074 packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001075 } else {
1076 DeliveryStatus delivery_status =
stefan68786d22015-09-08 05:36:15 -07001077 receiver_->DeliverPacket(media_type, packet, length, packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001078 EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
Peter Boström5811a392015-12-10 13:02:50 +01001079 delivered_packet_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001080 return delivery_status;
1081 }
1082 }
1083
1084 PacketReceiver* receiver_;
Peter Boström5811a392015-12-10 13:02:50 +01001085 rtc::Event delivered_packet_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001086 };
1087
solenberg4fbae2b2015-08-28 04:07:10 -07001088 CreateCalls(Call::Config(), Call::Config());
1089
stefanf116bd02015-10-27 08:29:42 -07001090 test::DirectTransport send_transport(sender_call_.get());
1091 test::DirectTransport receive_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001092 PacketInputObserver input_observer(receiver_call_->Receiver());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001093 send_transport.SetReceiver(&input_observer);
1094 receive_transport.SetReceiver(sender_call_->Receiver());
1095
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001096 CreateSendConfig(1, 0, &send_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001097 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001098
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001099 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001100 CreateFrameGeneratorCapturer();
1101 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001102
stefanff483612015-12-21 03:14:00 -08001103 receiver_call_->DestroyVideoReceiveStream(video_receive_streams_[0]);
1104 video_receive_streams_.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001105
1106 // Wait() waits for a received packet.
Peter Boström5811a392015-12-10 13:02:50 +01001107 EXPECT_TRUE(input_observer.Wait());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001108
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001109 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001110
1111 DestroyStreams();
1112
1113 send_transport.StopSending();
1114 receive_transport.StopSending();
1115}
1116
pbosda903ea2015-10-02 02:36:56 -07001117void EndToEndTest::RespectsRtcpMode(RtcpMode rtcp_mode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001118 static const int kNumCompoundRtcpPacketsToObserve = 10;
1119 class RtcpModeObserver : public test::EndToEndTest {
1120 public:
pbosda903ea2015-10-02 02:36:56 -07001121 explicit RtcpModeObserver(RtcpMode rtcp_mode)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001122 : EndToEndTest(kDefaultTimeoutMs),
1123 rtcp_mode_(rtcp_mode),
1124 sent_rtp_(0),
1125 sent_rtcp_(0) {}
1126
1127 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001128 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001129 if (++sent_rtp_ % 3 == 0)
1130 return DROP_PACKET;
1131
1132 return SEND_PACKET;
1133 }
1134
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001135 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001136 ++sent_rtcp_;
1137 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1138 EXPECT_TRUE(parser.IsValid());
1139
1140 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1141 bool has_report_block = false;
Erik Språng242e22b2015-05-11 10:17:43 +02001142 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1143 EXPECT_NE(RTCPUtility::RTCPPacketTypes::kSr, packet_type);
1144 if (packet_type == RTCPUtility::RTCPPacketTypes::kRr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001145 has_report_block = true;
1146 break;
1147 }
1148 packet_type = parser.Iterate();
1149 }
1150
1151 switch (rtcp_mode_) {
pbosda903ea2015-10-02 02:36:56 -07001152 case RtcpMode::kCompound:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001153 if (!has_report_block) {
1154 ADD_FAILURE() << "Received RTCP packet without receiver report for "
pbosda903ea2015-10-02 02:36:56 -07001155 "RtcpMode::kCompound.";
Peter Boström5811a392015-12-10 13:02:50 +01001156 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001157 }
1158
1159 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
Peter Boström5811a392015-12-10 13:02:50 +01001160 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001161
1162 break;
pbosda903ea2015-10-02 02:36:56 -07001163 case RtcpMode::kReducedSize:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001164 if (!has_report_block)
Peter Boström5811a392015-12-10 13:02:50 +01001165 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001166 break;
pbosda903ea2015-10-02 02:36:56 -07001167 case RtcpMode::kOff:
1168 RTC_NOTREACHED();
1169 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001170 }
1171
1172 return SEND_PACKET;
1173 }
1174
stefanff483612015-12-21 03:14:00 -08001175 void ModifyVideoConfigs(
1176 VideoSendStream::Config* send_config,
1177 std::vector<VideoReceiveStream::Config>* receive_configs,
1178 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001179 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001180 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1181 (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001182 }
1183
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001184 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001185 EXPECT_TRUE(Wait())
pbosda903ea2015-10-02 02:36:56 -07001186 << (rtcp_mode_ == RtcpMode::kCompound
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001187 ? "Timed out before observing enough compound packets."
1188 : "Timed out before receiving a non-compound RTCP packet.");
1189 }
1190
pbosda903ea2015-10-02 02:36:56 -07001191 RtcpMode rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001192 int sent_rtp_;
1193 int sent_rtcp_;
1194 } test(rtcp_mode);
1195
stefane74eef12016-01-08 06:47:13 -08001196 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001197}
1198
1199TEST_F(EndToEndTest, UsesRtcpCompoundMode) {
pbosda903ea2015-10-02 02:36:56 -07001200 RespectsRtcpMode(RtcpMode::kCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001201}
1202
1203TEST_F(EndToEndTest, UsesRtcpReducedSizeMode) {
pbosda903ea2015-10-02 02:36:56 -07001204 RespectsRtcpMode(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001205}
1206
1207// Test sets up a Call multiple senders with different resolutions and SSRCs.
1208// Another is set up to receive all three of these with different renderers.
sprang867fb522015-08-03 04:38:41 -07001209class MultiStreamTest {
1210 public:
1211 static const size_t kNumStreams = 3;
1212 struct CodecSettings {
1213 uint32_t ssrc;
1214 int width;
1215 int height;
1216 } codec_settings[kNumStreams];
1217
1218 MultiStreamTest() {
1219 // TODO(sprang): Cleanup when msvc supports explicit initializers for array.
1220 codec_settings[0] = {1, 640, 480};
1221 codec_settings[1] = {2, 320, 240};
1222 codec_settings[2] = {3, 240, 160};
1223 }
1224
1225 virtual ~MultiStreamTest() {}
1226
1227 void RunTest() {
kwiberg27f982b2016-03-01 11:52:33 -08001228 std::unique_ptr<Call> sender_call(Call::Create(Call::Config()));
1229 std::unique_ptr<Call> receiver_call(Call::Create(Call::Config()));
1230 std::unique_ptr<test::DirectTransport> sender_transport(
stefanf116bd02015-10-27 08:29:42 -07001231 CreateSendTransport(sender_call.get()));
kwiberg27f982b2016-03-01 11:52:33 -08001232 std::unique_ptr<test::DirectTransport> receiver_transport(
stefanf116bd02015-10-27 08:29:42 -07001233 CreateReceiveTransport(receiver_call.get()));
sprang867fb522015-08-03 04:38:41 -07001234 sender_transport->SetReceiver(receiver_call->Receiver());
1235 receiver_transport->SetReceiver(sender_call->Receiver());
1236
kwiberg27f982b2016-03-01 11:52:33 -08001237 std::unique_ptr<VideoEncoder> encoders[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001238 for (size_t i = 0; i < kNumStreams; ++i)
1239 encoders[i].reset(VideoEncoder::Create(VideoEncoder::kVp8));
1240
1241 VideoSendStream* send_streams[kNumStreams];
1242 VideoReceiveStream* receive_streams[kNumStreams];
1243
1244 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
1245 ScopedVector<VideoDecoder> allocated_decoders;
1246 for (size_t i = 0; i < kNumStreams; ++i) {
1247 uint32_t ssrc = codec_settings[i].ssrc;
1248 int width = codec_settings[i].width;
1249 int height = codec_settings[i].height;
1250
solenberg4fbae2b2015-08-28 04:07:10 -07001251 VideoSendStream::Config send_config(sender_transport.get());
sprang867fb522015-08-03 04:38:41 -07001252 send_config.rtp.ssrcs.push_back(ssrc);
1253 send_config.encoder_settings.encoder = encoders[i].get();
1254 send_config.encoder_settings.payload_name = "VP8";
1255 send_config.encoder_settings.payload_type = 124;
1256 VideoEncoderConfig encoder_config;
1257 encoder_config.streams = test::CreateVideoStreams(1);
1258 VideoStream* stream = &encoder_config.streams[0];
1259 stream->width = width;
1260 stream->height = height;
1261 stream->max_framerate = 5;
1262 stream->min_bitrate_bps = stream->target_bitrate_bps =
1263 stream->max_bitrate_bps = 100000;
1264
1265 UpdateSendConfig(i, &send_config, &encoder_config, &frame_generators[i]);
1266
1267 send_streams[i] =
1268 sender_call->CreateVideoSendStream(send_config, encoder_config);
1269 send_streams[i]->Start();
1270
solenberg4fbae2b2015-08-28 04:07:10 -07001271 VideoReceiveStream::Config receive_config(receiver_transport.get());
sprang867fb522015-08-03 04:38:41 -07001272 receive_config.rtp.remote_ssrc = ssrc;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001273 receive_config.rtp.local_ssrc = test::CallTest::kReceiverLocalVideoSsrc;
sprang867fb522015-08-03 04:38:41 -07001274 VideoReceiveStream::Decoder decoder =
1275 test::CreateMatchingDecoder(send_config.encoder_settings);
1276 allocated_decoders.push_back(decoder.decoder);
1277 receive_config.decoders.push_back(decoder);
1278
1279 UpdateReceiveConfig(i, &receive_config);
1280
1281 receive_streams[i] =
1282 receiver_call->CreateVideoReceiveStream(receive_config);
1283 receive_streams[i]->Start();
1284
1285 frame_generators[i] = test::FrameGeneratorCapturer::Create(
1286 send_streams[i]->Input(), width, height, 30,
1287 Clock::GetRealTimeClock());
1288 frame_generators[i]->Start();
1289 }
1290
1291 Wait();
1292
1293 for (size_t i = 0; i < kNumStreams; ++i) {
1294 frame_generators[i]->Stop();
1295 sender_call->DestroyVideoSendStream(send_streams[i]);
1296 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1297 delete frame_generators[i];
1298 }
1299
1300 sender_transport->StopSending();
1301 receiver_transport->StopSending();
1302 }
1303
1304 protected:
1305 virtual void Wait() = 0;
1306 // Note: frame_generator is a point-to-pointer, since the actual instance
1307 // hasn't been created at the time of this call. Only when packets/frames
1308 // start flowing should this be dereferenced.
1309 virtual void UpdateSendConfig(
1310 size_t stream_index,
1311 VideoSendStream::Config* send_config,
1312 VideoEncoderConfig* encoder_config,
1313 test::FrameGeneratorCapturer** frame_generator) {}
1314 virtual void UpdateReceiveConfig(size_t stream_index,
1315 VideoReceiveStream::Config* receive_config) {
1316 }
stefanf116bd02015-10-27 08:29:42 -07001317 virtual test::DirectTransport* CreateSendTransport(Call* sender_call) {
1318 return new test::DirectTransport(sender_call);
sprang867fb522015-08-03 04:38:41 -07001319 }
stefanf116bd02015-10-27 08:29:42 -07001320 virtual test::DirectTransport* CreateReceiveTransport(Call* receiver_call) {
1321 return new test::DirectTransport(receiver_call);
sprang867fb522015-08-03 04:38:41 -07001322 }
1323};
1324
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001325// Each renderer verifies that it receives the expected resolution, and as soon
1326// as every renderer has received a frame, the test finishes.
andresp@webrtc.org02686112014-09-19 08:24:19 +00001327TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001328 class VideoOutputObserver : public VideoRenderer {
1329 public:
sprang867fb522015-08-03 04:38:41 -07001330 VideoOutputObserver(const MultiStreamTest::CodecSettings& settings,
1331 uint32_t ssrc,
1332 test::FrameGeneratorCapturer** frame_generator)
1333 : settings_(settings),
1334 ssrc_(ssrc),
1335 frame_generator_(frame_generator),
Peter Boström5811a392015-12-10 13:02:50 +01001336 done_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001337
nisseeb83a1a2016-03-21 01:27:56 -07001338 void OnFrame(const VideoFrame& video_frame) override {
sprang867fb522015-08-03 04:38:41 -07001339 EXPECT_EQ(settings_.width, video_frame.width());
1340 EXPECT_EQ(settings_.height, video_frame.height());
1341 (*frame_generator_)->Stop();
Peter Boström5811a392015-12-10 13:02:50 +01001342 done_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001343 }
1344
sprang867fb522015-08-03 04:38:41 -07001345 uint32_t Ssrc() { return ssrc_; }
1346
Peter Boström5811a392015-12-10 13:02:50 +01001347 bool Wait() { return done_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001348
1349 private:
sprang867fb522015-08-03 04:38:41 -07001350 const MultiStreamTest::CodecSettings& settings_;
1351 const uint32_t ssrc_;
1352 test::FrameGeneratorCapturer** const frame_generator_;
Peter Boström5811a392015-12-10 13:02:50 +01001353 rtc::Event done_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001354 };
1355
sprang867fb522015-08-03 04:38:41 -07001356 class Tester : public MultiStreamTest {
1357 public:
1358 Tester() {}
1359 virtual ~Tester() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001360
sprang867fb522015-08-03 04:38:41 -07001361 protected:
1362 void Wait() override {
1363 for (const auto& observer : observers_) {
Peter Boström5811a392015-12-10 13:02:50 +01001364 EXPECT_TRUE(observer->Wait()) << "Time out waiting for from on ssrc "
1365 << observer->Ssrc();
sprang867fb522015-08-03 04:38:41 -07001366 }
1367 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001368
sprang867fb522015-08-03 04:38:41 -07001369 void UpdateSendConfig(
1370 size_t stream_index,
1371 VideoSendStream::Config* send_config,
1372 VideoEncoderConfig* encoder_config,
1373 test::FrameGeneratorCapturer** frame_generator) override {
1374 observers_[stream_index].reset(new VideoOutputObserver(
1375 codec_settings[stream_index], send_config->rtp.ssrcs.front(),
1376 frame_generator));
1377 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001378
sprang867fb522015-08-03 04:38:41 -07001379 void UpdateReceiveConfig(
1380 size_t stream_index,
1381 VideoReceiveStream::Config* receive_config) override {
1382 receive_config->renderer = observers_[stream_index].get();
1383 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001384
sprang867fb522015-08-03 04:38:41 -07001385 private:
kwiberg27f982b2016-03-01 11:52:33 -08001386 std::unique_ptr<VideoOutputObserver> observers_[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001387 } tester;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001388
sprang867fb522015-08-03 04:38:41 -07001389 tester.RunTest();
1390}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001391
sprang867fb522015-08-03 04:38:41 -07001392TEST_F(EndToEndTest, AssignsTransportSequenceNumbers) {
sprang867fb522015-08-03 04:38:41 -07001393 static const int kExtensionId = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001394
sprang867fb522015-08-03 04:38:41 -07001395 class RtpExtensionHeaderObserver : public test::DirectTransport {
1396 public:
stefanf116bd02015-10-27 08:29:42 -07001397 RtpExtensionHeaderObserver(Call* sender_call,
1398 const uint32_t& first_media_ssrc,
sprang861c55e2015-10-16 10:01:21 -07001399 const std::map<uint32_t, uint32_t>& ssrc_map)
stefanf116bd02015-10-27 08:29:42 -07001400 : DirectTransport(sender_call),
Peter Boström5811a392015-12-10 13:02:50 +01001401 done_(false, false),
sprang867fb522015-08-03 04:38:41 -07001402 parser_(RtpHeaderParser::Create()),
sprang861c55e2015-10-16 10:01:21 -07001403 first_media_ssrc_(first_media_ssrc),
1404 rtx_to_media_ssrcs_(ssrc_map),
sprang867fb522015-08-03 04:38:41 -07001405 padding_observed_(false),
sprang861c55e2015-10-16 10:01:21 -07001406 rtx_padding_observed_(false),
1407 retransmit_observed_(false),
1408 started_(false) {
sprang867fb522015-08-03 04:38:41 -07001409 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
1410 kExtensionId);
1411 }
1412 virtual ~RtpExtensionHeaderObserver() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001413
stefan1d8a5062015-10-02 03:39:33 -07001414 bool SendRtp(const uint8_t* data,
1415 size_t length,
1416 const PacketOptions& options) override {
sprang861c55e2015-10-16 10:01:21 -07001417 {
1418 rtc::CritScope cs(&lock_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001419
Erik Språng8d629712015-08-04 16:24:03 +02001420 if (IsDone())
sprang861c55e2015-10-16 10:01:21 -07001421 return false;
1422
1423 if (started_) {
1424 RTPHeader header;
1425 EXPECT_TRUE(parser_->Parse(data, length, &header));
1426 bool drop_packet = false;
1427
1428 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
1429 EXPECT_EQ(options.packet_id,
1430 header.extension.transportSequenceNumber);
1431 if (!streams_observed_.empty()) {
1432 // Unwrap packet id and verify uniqueness.
1433 int64_t packet_id = unwrapper_.Unwrap(options.packet_id);
1434 EXPECT_TRUE(received_packed_ids_.insert(packet_id).second);
1435 }
1436
1437 // Drop (up to) every 17th packet, so we get retransmits.
1438 // Only drop media, and not on the first stream (otherwise it will be
1439 // hard to distinguish from padding, which is always sent on the first
1440 // stream).
1441 if (header.payloadType != kSendRtxPayloadType &&
1442 header.ssrc != first_media_ssrc_ &&
1443 header.extension.transportSequenceNumber % 17 == 0) {
1444 dropped_seq_[header.ssrc].insert(header.sequenceNumber);
1445 drop_packet = true;
1446 }
1447
1448 size_t payload_length =
1449 length - (header.headerLength + header.paddingLength);
1450 if (payload_length == 0) {
1451 padding_observed_ = true;
1452 } else if (header.payloadType == kSendRtxPayloadType) {
1453 uint16_t original_sequence_number =
1454 ByteReader<uint16_t>::ReadBigEndian(&data[header.headerLength]);
1455 uint32_t original_ssrc =
1456 rtx_to_media_ssrcs_.find(header.ssrc)->second;
1457 std::set<uint16_t>* seq_no_map = &dropped_seq_[original_ssrc];
1458 auto it = seq_no_map->find(original_sequence_number);
1459 if (it != seq_no_map->end()) {
1460 retransmit_observed_ = true;
1461 seq_no_map->erase(it);
1462 } else {
1463 rtx_padding_observed_ = true;
1464 }
1465 } else {
1466 streams_observed_.insert(header.ssrc);
1467 }
1468
1469 if (IsDone())
Peter Boström5811a392015-12-10 13:02:50 +01001470 done_.Set();
sprang861c55e2015-10-16 10:01:21 -07001471
1472 if (drop_packet)
1473 return true;
1474 }
sprang867fb522015-08-03 04:38:41 -07001475 }
sprang861c55e2015-10-16 10:01:21 -07001476
stefan1d8a5062015-10-02 03:39:33 -07001477 return test::DirectTransport::SendRtp(data, length, options);
sprang867fb522015-08-03 04:38:41 -07001478 }
1479
Erik Språng8d629712015-08-04 16:24:03 +02001480 bool IsDone() {
sprang861c55e2015-10-16 10:01:21 -07001481 bool observed_types_ok =
1482 streams_observed_.size() == MultiStreamTest::kNumStreams &&
1483 padding_observed_ && retransmit_observed_ && rtx_padding_observed_;
1484 if (!observed_types_ok)
1485 return false;
1486 // We should not have any gaps in the sequence number range.
1487 size_t seqno_range =
1488 *received_packed_ids_.rbegin() - *received_packed_ids_.begin() + 1;
1489 return seqno_range == received_packed_ids_.size();
Erik Språng8d629712015-08-04 16:24:03 +02001490 }
1491
Peter Boström5811a392015-12-10 13:02:50 +01001492 bool Wait() {
sprang861c55e2015-10-16 10:01:21 -07001493 {
1494 // Can't be sure until this point that rtx_to_media_ssrcs_ etc have
1495 // been initialized and are OK to read.
1496 rtc::CritScope cs(&lock_);
1497 started_ = true;
1498 }
Peter Boström5811a392015-12-10 13:02:50 +01001499 return done_.Wait(kDefaultTimeoutMs);
sprang861c55e2015-10-16 10:01:21 -07001500 }
sprang867fb522015-08-03 04:38:41 -07001501
sprang861c55e2015-10-16 10:01:21 -07001502 rtc::CriticalSection lock_;
Peter Boström5811a392015-12-10 13:02:50 +01001503 rtc::Event done_;
kwiberg27f982b2016-03-01 11:52:33 -08001504 std::unique_ptr<RtpHeaderParser> parser_;
sprang861c55e2015-10-16 10:01:21 -07001505 SequenceNumberUnwrapper unwrapper_;
1506 std::set<int64_t> received_packed_ids_;
sprang867fb522015-08-03 04:38:41 -07001507 std::set<uint32_t> streams_observed_;
sprang861c55e2015-10-16 10:01:21 -07001508 std::map<uint32_t, std::set<uint16_t>> dropped_seq_;
1509 const uint32_t& first_media_ssrc_;
1510 const std::map<uint32_t, uint32_t>& rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001511 bool padding_observed_;
1512 bool rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001513 bool retransmit_observed_;
1514 bool started_;
sprang867fb522015-08-03 04:38:41 -07001515 };
1516
1517 class TransportSequenceNumberTester : public MultiStreamTest {
1518 public:
sprang861c55e2015-10-16 10:01:21 -07001519 TransportSequenceNumberTester()
1520 : first_media_ssrc_(0), observer_(nullptr) {}
sprang867fb522015-08-03 04:38:41 -07001521 virtual ~TransportSequenceNumberTester() {}
1522
1523 protected:
1524 void Wait() override {
henrikg91d6ede2015-09-17 00:24:34 -07001525 RTC_DCHECK(observer_ != nullptr);
Peter Boström5811a392015-12-10 13:02:50 +01001526 EXPECT_TRUE(observer_->Wait());
sprang867fb522015-08-03 04:38:41 -07001527 }
1528
1529 void UpdateSendConfig(
1530 size_t stream_index,
1531 VideoSendStream::Config* send_config,
1532 VideoEncoderConfig* encoder_config,
1533 test::FrameGeneratorCapturer** frame_generator) override {
1534 send_config->rtp.extensions.clear();
1535 send_config->rtp.extensions.push_back(
1536 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
1537
1538 // Force some padding to be sent.
1539 const int kPaddingBitrateBps = 50000;
1540 int total_target_bitrate = 0;
1541 for (const VideoStream& stream : encoder_config->streams)
1542 total_target_bitrate += stream.target_bitrate_bps;
1543 encoder_config->min_transmit_bitrate_bps =
1544 total_target_bitrate + kPaddingBitrateBps;
1545
1546 // Configure RTX for redundant payload padding.
1547 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang861c55e2015-10-16 10:01:21 -07001548 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[stream_index]);
sprang867fb522015-08-03 04:38:41 -07001549 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
sprang861c55e2015-10-16 10:01:21 -07001550 rtx_to_media_ssrcs_[kSendRtxSsrcs[stream_index]] =
1551 send_config->rtp.ssrcs[0];
1552
1553 if (stream_index == 0)
1554 first_media_ssrc_ = send_config->rtp.ssrcs[0];
sprang867fb522015-08-03 04:38:41 -07001555 }
1556
1557 void UpdateReceiveConfig(
1558 size_t stream_index,
1559 VideoReceiveStream::Config* receive_config) override {
sprang861c55e2015-10-16 10:01:21 -07001560 receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang867fb522015-08-03 04:38:41 -07001561 receive_config->rtp.extensions.clear();
1562 receive_config->rtp.extensions.push_back(
1563 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
1564 }
1565
stefanf116bd02015-10-27 08:29:42 -07001566 test::DirectTransport* CreateSendTransport(Call* sender_call) override {
1567 observer_ = new RtpExtensionHeaderObserver(sender_call, first_media_ssrc_,
sprang861c55e2015-10-16 10:01:21 -07001568 rtx_to_media_ssrcs_);
sprang867fb522015-08-03 04:38:41 -07001569 return observer_;
1570 }
1571
1572 private:
sprang861c55e2015-10-16 10:01:21 -07001573 uint32_t first_media_ssrc_;
1574 std::map<uint32_t, uint32_t> rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001575 RtpExtensionHeaderObserver* observer_;
1576 } tester;
1577
1578 tester.RunTest();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001579}
1580
Stefan Holmer04cb7632016-01-14 20:34:30 +01001581class TransportFeedbackTester : public test::EndToEndTest {
1582 public:
1583 explicit TransportFeedbackTester(bool feedback_enabled,
1584 size_t num_video_streams,
1585 size_t num_audio_streams)
1586 : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
1587 feedback_enabled_(feedback_enabled),
1588 num_video_streams_(num_video_streams),
1589 num_audio_streams_(num_audio_streams) {
1590 // Only one stream of each supported for now.
1591 EXPECT_LE(num_video_streams, 1u);
1592 EXPECT_LE(num_audio_streams, 1u);
1593 }
1594
1595 protected:
1596 Action OnSendRtcp(const uint8_t* data, size_t length) override {
1597 EXPECT_FALSE(HasTransportFeedback(data, length));
1598 return SEND_PACKET;
1599 }
1600
1601 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
1602 if (HasTransportFeedback(data, length))
1603 observation_complete_.Set();
1604 return SEND_PACKET;
1605 }
1606
1607 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
1608 RTCPUtility::RTCPParserV2 parser(data, length, true);
1609 EXPECT_TRUE(parser.IsValid());
1610
1611 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1612 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1613 if (packet_type == RTCPUtility::RTCPPacketTypes::kTransportFeedback)
1614 return true;
1615 packet_type = parser.Iterate();
1616 }
1617
1618 return false;
1619 }
1620
1621 void PerformTest() override {
1622 const int64_t kDisabledFeedbackTimeoutMs = 5000;
1623 EXPECT_EQ(feedback_enabled_,
1624 observation_complete_.Wait(feedback_enabled_
1625 ? test::CallTest::kDefaultTimeoutMs
1626 : kDisabledFeedbackTimeoutMs));
1627 }
1628
1629 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1630 receiver_call_ = receiver_call;
1631 }
1632
1633 size_t GetNumVideoStreams() const override { return num_video_streams_; }
1634 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
1635
1636 void ModifyVideoConfigs(
1637 VideoSendStream::Config* send_config,
1638 std::vector<VideoReceiveStream::Config>* receive_configs,
1639 VideoEncoderConfig* encoder_config) override {
1640 send_config->rtp.extensions.clear();
1641 send_config->rtp.extensions.push_back(
1642 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
1643 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1644 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
1645 }
1646
1647 void ModifyAudioConfigs(
1648 AudioSendStream::Config* send_config,
1649 std::vector<AudioReceiveStream::Config>* receive_configs) override {
1650 send_config->rtp.extensions.clear();
1651 send_config->rtp.extensions.push_back(
1652 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
1653 (*receive_configs)[0].rtp.extensions.clear();
1654 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1655 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001656 }
1657
1658 private:
Erik Språng6b8d3552015-09-24 15:06:57 +02001659 static const int kExtensionId = 5;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001660 const bool feedback_enabled_;
1661 const size_t num_video_streams_;
1662 const size_t num_audio_streams_;
1663 Call* receiver_call_;
1664};
Erik Språng6b8d3552015-09-24 15:06:57 +02001665
Stefan Holmer04cb7632016-01-14 20:34:30 +01001666TEST_F(EndToEndTest, VideoReceivesTransportFeedback) {
1667 TransportFeedbackTester test(true, 1, 0);
1668 RunBaseTest(&test);
Erik Språng6b8d3552015-09-24 15:06:57 +02001669}
stefan43edf0f2015-11-20 18:05:48 -08001670
Stefan Holmer04cb7632016-01-14 20:34:30 +01001671TEST_F(EndToEndTest, VideoTransportFeedbackNotConfigured) {
1672 TransportFeedbackTester test(false, 1, 0);
1673 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001674}
1675
Stefan Holmer04cb7632016-01-14 20:34:30 +01001676TEST_F(EndToEndTest, AudioReceivesTransportFeedback) {
1677 TransportFeedbackTester test(true, 0, 1);
1678 RunBaseTest(&test);
1679}
1680
1681TEST_F(EndToEndTest, AudioTransportFeedbackNotConfigured) {
1682 TransportFeedbackTester test(false, 0, 1);
1683 RunBaseTest(&test);
1684}
1685
1686TEST_F(EndToEndTest, AudioVideoReceivesTransportFeedback) {
1687 TransportFeedbackTester test(true, 1, 1);
1688 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001689}
1690
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001691TEST_F(EndToEndTest, ObserversEncodedFrames) {
1692 class EncodedFrameTestObserver : public EncodedFrameObserver {
1693 public:
1694 EncodedFrameTestObserver()
Peter Boström5811a392015-12-10 13:02:50 +01001695 : length_(0), frame_type_(kEmptyFrame), called_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001696 virtual ~EncodedFrameTestObserver() {}
1697
1698 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
1699 frame_type_ = encoded_frame.frame_type_;
1700 length_ = encoded_frame.length_;
1701 buffer_.reset(new uint8_t[length_]);
1702 memcpy(buffer_.get(), encoded_frame.data_, length_);
Peter Boström5811a392015-12-10 13:02:50 +01001703 called_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001704 }
1705
Peter Boström5811a392015-12-10 13:02:50 +01001706 bool Wait() { return called_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001707
1708 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
1709 ASSERT_EQ(length_, observer.length_)
1710 << "Observed frames are of different lengths.";
1711 EXPECT_EQ(frame_type_, observer.frame_type_)
1712 << "Observed frames have different frame types.";
1713 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
1714 << "Observed encoded frames have different content.";
1715 }
1716
1717 private:
kwiberg27f982b2016-03-01 11:52:33 -08001718 std::unique_ptr<uint8_t[]> buffer_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001719 size_t length_;
1720 FrameType frame_type_;
Peter Boström5811a392015-12-10 13:02:50 +01001721 rtc::Event called_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001722 };
1723
1724 EncodedFrameTestObserver post_encode_observer;
1725 EncodedFrameTestObserver pre_decode_observer;
1726
solenberg4fbae2b2015-08-28 04:07:10 -07001727 CreateCalls(Call::Config(), Call::Config());
1728
stefanf116bd02015-10-27 08:29:42 -07001729 test::DirectTransport sender_transport(sender_call_.get());
1730 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001731 sender_transport.SetReceiver(receiver_call_->Receiver());
1732 receiver_transport.SetReceiver(sender_call_->Receiver());
1733
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001734 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001735 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -08001736 video_send_config_.post_encode_callback = &post_encode_observer;
1737 video_receive_configs_[0].pre_decode_callback = &pre_decode_observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001738
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001739 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001740 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001741
kwiberg27f982b2016-03-01 11:52:33 -08001742 std::unique_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +00001743 test::FrameGenerator::CreateChromaGenerator(
stefanff483612015-12-21 03:14:00 -08001744 video_encoder_config_.streams[0].width,
1745 video_encoder_config_.streams[0].height));
1746 video_send_stream_->Input()->IncomingCapturedFrame(
1747 *frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001748
Peter Boström5811a392015-12-10 13:02:50 +01001749 EXPECT_TRUE(post_encode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001750 << "Timed out while waiting for send-side encoded-frame callback.";
1751
Peter Boström5811a392015-12-10 13:02:50 +01001752 EXPECT_TRUE(pre_decode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001753 << "Timed out while waiting for pre-decode encoded-frame callback.";
1754
1755 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
1756
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001757 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001758
1759 sender_transport.StopSending();
1760 receiver_transport.StopSending();
1761
1762 DestroyStreams();
1763}
1764
1765TEST_F(EndToEndTest, ReceiveStreamSendsRemb) {
1766 class RembObserver : public test::EndToEndTest {
1767 public:
1768 RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
1769
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001770 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001771 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1772 EXPECT_TRUE(parser.IsValid());
1773
1774 bool received_psfb = false;
1775 bool received_remb = false;
1776 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02001777 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1778 if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbRemb) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001779 const RTCPUtility::RTCPPacket& packet = parser.Packet();
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001780 EXPECT_EQ(packet.PSFBAPP.SenderSSRC, kReceiverLocalVideoSsrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001781 received_psfb = true;
Erik Språng242e22b2015-05-11 10:17:43 +02001782 } else if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbRembItem) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001783 const RTCPUtility::RTCPPacket& packet = parser.Packet();
1784 EXPECT_GT(packet.REMBItem.BitRate, 0u);
1785 EXPECT_EQ(packet.REMBItem.NumberOfSSRCs, 1u);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001786 EXPECT_EQ(packet.REMBItem.SSRCs[0], kVideoSendSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001787 received_remb = true;
1788 }
1789 packet_type = parser.Iterate();
1790 }
1791 if (received_psfb && received_remb)
Peter Boström5811a392015-12-10 13:02:50 +01001792 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001793 return SEND_PACKET;
1794 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001795 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001796 EXPECT_TRUE(Wait()) << "Timed out while waiting for a "
1797 "receiver RTCP REMB packet to be "
1798 "sent.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001799 }
1800 } test;
1801
stefane74eef12016-01-08 06:47:13 -08001802 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001803}
1804
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001805TEST_F(EndToEndTest, VerifyBandwidthStats) {
stefanf116bd02015-10-27 08:29:42 -07001806 class RtcpObserver : public test::EndToEndTest {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001807 public:
1808 RtcpObserver()
1809 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001810 sender_call_(nullptr),
1811 receiver_call_(nullptr),
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001812 has_seen_pacer_delay_(false) {}
1813
stefanf116bd02015-10-27 08:29:42 -07001814 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001815 Call::Stats sender_stats = sender_call_->GetStats();
1816 Call::Stats receiver_stats = receiver_call_->GetStats();
1817 if (!has_seen_pacer_delay_)
1818 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
1819 if (sender_stats.send_bandwidth_bps > 0 &&
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001820 receiver_stats.recv_bandwidth_bps > 0 && has_seen_pacer_delay_) {
Peter Boström5811a392015-12-10 13:02:50 +01001821 observation_complete_.Set();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001822 }
stefanf116bd02015-10-27 08:29:42 -07001823 return SEND_PACKET;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001824 }
1825
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001826 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001827 sender_call_ = sender_call;
1828 receiver_call_ = receiver_call;
1829 }
1830
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001831 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001832 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
1833 "non-zero bandwidth stats.";
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001834 }
1835
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001836 private:
1837 Call* sender_call_;
1838 Call* receiver_call_;
1839 bool has_seen_pacer_delay_;
1840 } test;
1841
stefane74eef12016-01-08 06:47:13 -08001842 RunBaseTest(&test);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001843}
1844
stefan32f81542016-01-20 07:13:58 -08001845
1846// Verifies that it's possible to limit the send BWE by sending a REMB.
1847// This is verified by allowing the send BWE to ramp-up to >1000 kbps,
1848// then have the test generate a REMB of 500 kbps and verify that the send BWE
1849// is reduced to exactly 500 kbps. Then a REMB of 1000 kbps is generated and the
1850// test verifies that the send BWE ramps back up to exactly 1000 kbps.
1851TEST_F(EndToEndTest, RembWithSendSideBwe) {
1852 class BweObserver : public test::EndToEndTest {
1853 public:
1854 BweObserver()
1855 : EndToEndTest(kDefaultTimeoutMs),
1856 sender_call_(nullptr),
1857 clock_(Clock::GetRealTimeClock()),
1858 sender_ssrc_(0),
1859 remb_bitrate_bps_(1000000),
1860 receive_transport_(nullptr),
1861 event_(false, false),
1862 poller_thread_(&BitrateStatsPollingThread,
1863 this,
1864 "BitrateStatsPollingThread"),
1865 state_(kWaitForFirstRampUp) {}
1866
1867 ~BweObserver() {}
1868
1869 test::PacketTransport* CreateReceiveTransport() {
1870 receive_transport_ = new test::PacketTransport(
1871 nullptr, this, test::PacketTransport::kReceiver,
1872 FakeNetworkPipe::Config());
1873 return receive_transport_;
1874 }
1875
1876 Call::Config GetSenderCallConfig() override {
1877 Call::Config config;
1878 // Set a high start bitrate to reduce the test completion time.
1879 config.bitrate_config.start_bitrate_bps = remb_bitrate_bps_;
1880 return config;
1881 }
1882
1883 void ModifyVideoConfigs(
1884 VideoSendStream::Config* send_config,
1885 std::vector<VideoReceiveStream::Config>* receive_configs,
1886 VideoEncoderConfig* encoder_config) override {
1887 ASSERT_EQ(1u, send_config->rtp.ssrcs.size());
1888 send_config->rtp.extensions.clear();
1889 send_config->rtp.extensions.push_back(
1890 RtpExtension(RtpExtension::kTransportSequenceNumber,
1891 test::kTransportSequenceNumberExtensionId));
1892 sender_ssrc_ = send_config->rtp.ssrcs[0];
1893
1894 encoder_config->streams[0].max_bitrate_bps =
1895 encoder_config->streams[0].target_bitrate_bps = 2000000;
1896
1897 ASSERT_EQ(1u, receive_configs->size());
1898 (*receive_configs)[0].rtp.remb = false;
1899 (*receive_configs)[0].rtp.transport_cc = true;
1900 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1901 RtpRtcp::Configuration config;
1902 config.receiver_only = true;
1903 config.clock = clock_;
1904 config.outgoing_transport = receive_transport_;
1905 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
1906 rtp_rtcp_->SetRemoteSSRC((*receive_configs)[0].rtp.remote_ssrc);
1907 rtp_rtcp_->SetSSRC((*receive_configs)[0].rtp.local_ssrc);
1908 rtp_rtcp_->SetREMBStatus(true);
1909 rtp_rtcp_->SetSendingStatus(true);
1910 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
1911 }
1912
1913 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1914 sender_call_ = sender_call;
1915 }
1916
1917 static bool BitrateStatsPollingThread(void* obj) {
1918 return static_cast<BweObserver*>(obj)->PollStats();
1919 }
1920
1921 bool PollStats() {
1922 if (sender_call_) {
1923 Call::Stats stats = sender_call_->GetStats();
1924 switch (state_) {
1925 case kWaitForFirstRampUp:
1926 if (stats.send_bandwidth_bps >= remb_bitrate_bps_) {
1927 state_ = kWaitForRemb;
1928 remb_bitrate_bps_ /= 2;
1929 rtp_rtcp_->SetREMBData(
1930 remb_bitrate_bps_,
1931 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
1932 rtp_rtcp_->SendRTCP(kRtcpRr);
1933 }
1934 break;
1935
1936 case kWaitForRemb:
1937 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
1938 state_ = kWaitForSecondRampUp;
1939 remb_bitrate_bps_ *= 2;
1940 rtp_rtcp_->SetREMBData(
1941 remb_bitrate_bps_,
1942 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
1943 rtp_rtcp_->SendRTCP(kRtcpRr);
1944 }
1945 break;
1946
1947 case kWaitForSecondRampUp:
1948 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
1949 observation_complete_.Set();
1950 }
1951 break;
1952 }
1953 }
1954
1955 return !event_.Wait(1000);
1956 }
1957
1958 void PerformTest() override {
1959 poller_thread_.Start();
1960 EXPECT_TRUE(Wait())
1961 << "Timed out while waiting for bitrate to change according to REMB.";
1962 poller_thread_.Stop();
1963 }
1964
1965 private:
1966 enum TestState { kWaitForFirstRampUp, kWaitForRemb, kWaitForSecondRampUp };
1967
1968 Call* sender_call_;
1969 Clock* const clock_;
1970 uint32_t sender_ssrc_;
1971 int remb_bitrate_bps_;
kwiberg27f982b2016-03-01 11:52:33 -08001972 std::unique_ptr<RtpRtcp> rtp_rtcp_;
stefan32f81542016-01-20 07:13:58 -08001973 test::PacketTransport* receive_transport_;
1974 rtc::Event event_;
1975 rtc::PlatformThread poller_thread_;
1976 TestState state_;
1977 } test;
1978
1979 RunBaseTest(&test);
1980}
1981
Åsa Persson352b2d72015-04-15 18:00:40 +02001982TEST_F(EndToEndTest, VerifyNackStats) {
1983 static const int kPacketNumberToDrop = 200;
1984 class NackObserver : public test::EndToEndTest {
1985 public:
1986 NackObserver()
1987 : EndToEndTest(kLongTimeoutMs),
1988 sent_rtp_packets_(0),
1989 dropped_rtp_packet_(0),
1990 dropped_rtp_packet_requested_(false),
1991 send_stream_(nullptr),
1992 start_runtime_ms_(-1) {}
1993
1994 private:
1995 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08001996 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02001997 if (++sent_rtp_packets_ == kPacketNumberToDrop) {
kwiberg27f982b2016-03-01 11:52:33 -08001998 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
Åsa Persson352b2d72015-04-15 18:00:40 +02001999 RTPHeader header;
2000 EXPECT_TRUE(parser->Parse(packet, length, &header));
2001 dropped_rtp_packet_ = header.sequenceNumber;
2002 return DROP_PACKET;
2003 }
2004 VerifyStats();
2005 return SEND_PACKET;
2006 }
2007
2008 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002009 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002010 test::RtcpPacketParser rtcp_parser;
2011 rtcp_parser.Parse(packet, length);
2012 std::vector<uint16_t> nacks = rtcp_parser.nack_item()->last_nack_list();
2013 if (!nacks.empty() && std::find(
2014 nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) {
2015 dropped_rtp_packet_requested_ = true;
2016 }
2017 return SEND_PACKET;
2018 }
2019
stefan608213e2015-11-01 14:56:10 -08002020 void VerifyStats() EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002021 if (!dropped_rtp_packet_requested_)
2022 return;
2023 int send_stream_nack_packets = 0;
2024 int receive_stream_nack_packets = 0;
2025 VideoSendStream::Stats stats = send_stream_->GetStats();
2026 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
2027 stats.substreams.begin(); it != stats.substreams.end(); ++it) {
2028 const VideoSendStream::StreamStats& stream_stats = it->second;
2029 send_stream_nack_packets +=
2030 stream_stats.rtcp_packet_type_counts.nack_packets;
2031 }
2032 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2033 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2034 receive_stream_nack_packets +=
2035 stats.rtcp_packet_type_counts.nack_packets;
2036 }
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002037 if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002038 // NACK packet sent on receive stream and received on sent stream.
2039 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002040 observation_complete_.Set();
Åsa Persson352b2d72015-04-15 18:00:40 +02002041 }
2042 }
2043
2044 bool MinMetricRunTimePassed() {
2045 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2046 if (start_runtime_ms_ == -1) {
2047 start_runtime_ms_ = now;
2048 return false;
2049 }
2050 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2051 return elapsed_sec > metrics::kMinRunTimeInSeconds;
2052 }
2053
stefanff483612015-12-21 03:14:00 -08002054 void ModifyVideoConfigs(
2055 VideoSendStream::Config* send_config,
2056 std::vector<VideoReceiveStream::Config>* receive_configs,
2057 VideoEncoderConfig* encoder_config) override {
Åsa Persson352b2d72015-04-15 18:00:40 +02002058 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2059 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2060 }
2061
stefanff483612015-12-21 03:14:00 -08002062 void OnVideoStreamsCreated(
Åsa Persson352b2d72015-04-15 18:00:40 +02002063 VideoSendStream* send_stream,
2064 const std::vector<VideoReceiveStream*>& receive_streams) override {
2065 send_stream_ = send_stream;
2066 receive_streams_ = receive_streams;
2067 }
2068
2069 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002070 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson352b2d72015-04-15 18:00:40 +02002071 }
2072
stefan608213e2015-11-01 14:56:10 -08002073 rtc::CriticalSection crit_;
Åsa Persson352b2d72015-04-15 18:00:40 +02002074 uint64_t sent_rtp_packets_;
stefan608213e2015-11-01 14:56:10 -08002075 uint16_t dropped_rtp_packet_ GUARDED_BY(&crit_);
2076 bool dropped_rtp_packet_requested_ GUARDED_BY(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002077 std::vector<VideoReceiveStream*> receive_streams_;
2078 VideoSendStream* send_stream_;
2079 int64_t start_runtime_ms_;
2080 } test;
2081
Åsa Persson3c391cb2015-04-27 10:09:49 +02002082 test::ClearHistograms();
stefane74eef12016-01-08 06:47:13 -08002083 RunBaseTest(&test);
Åsa Persson352b2d72015-04-15 18:00:40 +02002084
Åsa Persson3c391cb2015-04-27 10:09:49 +02002085 EXPECT_EQ(1, test::NumHistogramSamples(
Åsa Persson352b2d72015-04-15 18:00:40 +02002086 "WebRTC.Video.UniqueNackRequestsSentInPercent"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002087 EXPECT_EQ(1, test::NumHistogramSamples(
Åsa Persson352b2d72015-04-15 18:00:40 +02002088 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
2089 EXPECT_GT(test::LastHistogramSample(
2090 "WebRTC.Video.NackPacketsSentPerMinute"), 0);
2091 EXPECT_GT(test::LastHistogramSample(
2092 "WebRTC.Video.NackPacketsReceivedPerMinute"), 0);
2093}
2094
sprangb4a1ae52015-12-03 08:10:08 -08002095void EndToEndTest::VerifyHistogramStats(bool use_rtx,
2096 bool use_red,
2097 bool screenshare) {
stefanf116bd02015-10-27 08:29:42 -07002098 class StatsObserver : public test::EndToEndTest {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002099 public:
sprangb4a1ae52015-12-03 08:10:08 -08002100 StatsObserver(bool use_rtx, bool use_red, bool screenshare)
Åsa Persson3c391cb2015-04-27 10:09:49 +02002101 : EndToEndTest(kLongTimeoutMs),
2102 use_rtx_(use_rtx),
2103 use_red_(use_red),
sprangb4a1ae52015-12-03 08:10:08 -08002104 screenshare_(screenshare),
Peter Boström39593972016-02-15 11:27:15 +01002105 // This test uses NACK, so to send FEC we can't use a fake encoder.
2106 vp8_encoder_(
2107 use_red ? VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)
2108 : nullptr),
Åsa Persson3c391cb2015-04-27 10:09:49 +02002109 sender_call_(nullptr),
2110 receiver_call_(nullptr),
2111 start_runtime_ms_(-1) {}
2112
2113 private:
2114 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2115 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002116 observation_complete_.Set();
Åsa Persson3c391cb2015-04-27 10:09:49 +02002117
stefanf116bd02015-10-27 08:29:42 -07002118 return SEND_PACKET;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002119 }
2120
2121 bool MinMetricRunTimePassed() {
2122 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2123 if (start_runtime_ms_ == -1) {
2124 start_runtime_ms_ = now;
2125 return false;
2126 }
2127 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2128 return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
2129 }
2130
stefanff483612015-12-21 03:14:00 -08002131 void ModifyVideoConfigs(
2132 VideoSendStream::Config* send_config,
2133 std::vector<VideoReceiveStream::Config>* receive_configs,
2134 VideoEncoderConfig* encoder_config) override {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002135 // NACK
2136 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2137 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2138 // FEC
2139 if (use_red_) {
2140 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
2141 send_config->rtp.fec.red_payload_type = kRedPayloadType;
Peter Boström39593972016-02-15 11:27:15 +01002142 send_config->encoder_settings.encoder = vp8_encoder_.get();
2143 send_config->encoder_settings.payload_name = "VP8";
2144 (*receive_configs)[0].decoders[0].payload_name = "VP8";
Åsa Persson3c391cb2015-04-27 10:09:49 +02002145 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
2146 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
2147 }
2148 // RTX
2149 if (use_rtx_) {
2150 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
2151 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002152 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002153 kSendRtxSsrcs[0];
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002154 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002155 kSendRtxPayloadType;
2156 }
asapersson52495992016-03-08 02:10:16 -08002157 // RTT needed for RemoteNtpTimeEstimator for the receive stream.
2158 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = true;
sprangb4a1ae52015-12-03 08:10:08 -08002159 encoder_config->content_type =
2160 screenshare_ ? VideoEncoderConfig::ContentType::kScreen
2161 : VideoEncoderConfig::ContentType::kRealtimeVideo;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002162 }
2163
2164 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2165 sender_call_ = sender_call;
2166 receiver_call_ = receiver_call;
2167 }
2168
Åsa Persson3c391cb2015-04-27 10:09:49 +02002169 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002170 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson3c391cb2015-04-27 10:09:49 +02002171 }
2172
sprangb4a1ae52015-12-03 08:10:08 -08002173 const bool use_rtx_;
2174 const bool use_red_;
2175 const bool screenshare_;
kwiberg27f982b2016-03-01 11:52:33 -08002176 const std::unique_ptr<VideoEncoder> vp8_encoder_;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002177 Call* sender_call_;
2178 Call* receiver_call_;
2179 int64_t start_runtime_ms_;
sprangb4a1ae52015-12-03 08:10:08 -08002180 } test(use_rtx, use_red, screenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002181
2182 test::ClearHistograms();
stefane74eef12016-01-08 06:47:13 -08002183 RunBaseTest(&test);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002184
stefan91d92602015-11-11 10:13:02 -08002185 // Delete the call for Call stats to be reported.
stefan18adf0a2015-11-17 06:24:56 -08002186 sender_call_.reset();
stefan91d92602015-11-11 10:13:02 -08002187 receiver_call_.reset();
2188
sprangb4a1ae52015-12-03 08:10:08 -08002189 std::string video_prefix =
2190 screenshare ? "WebRTC.Video.Screenshare." : "WebRTC.Video.";
2191
Åsa Persson3c391cb2015-04-27 10:09:49 +02002192 // Verify that stats have been updated once.
stefan91d92602015-11-11 10:13:02 -08002193 EXPECT_EQ(
2194 1, test::NumHistogramSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
2195 EXPECT_EQ(1,
2196 test::NumHistogramSamples("WebRTC.Call.RtcpBitrateReceivedInBps"));
2197 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Call.BitrateReceivedInKbps"));
stefan18adf0a2015-11-17 06:24:56 -08002198 EXPECT_EQ(
2199 1, test::NumHistogramSamples("WebRTC.Call.EstimatedSendBitrateInKbps"));
2200 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Call.PacerBitrateInKbps"));
stefan91d92602015-11-11 10:13:02 -08002201
Åsa Persson3c391cb2015-04-27 10:09:49 +02002202 EXPECT_EQ(1, test::NumHistogramSamples(
2203 "WebRTC.Video.NackPacketsSentPerMinute"));
sprang07fb9be2016-02-24 07:55:00 -08002204 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix +
2205 "NackPacketsReceivedPerMinute"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002206 EXPECT_EQ(1, test::NumHistogramSamples(
2207 "WebRTC.Video.FirPacketsSentPerMinute"));
sprang07fb9be2016-02-24 07:55:00 -08002208 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix +
2209 "FirPacketsReceivedPerMinute"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002210 EXPECT_EQ(1, test::NumHistogramSamples(
2211 "WebRTC.Video.PliPacketsSentPerMinute"));
sprang07fb9be2016-02-24 07:55:00 -08002212 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix +
2213 "PliPacketsReceivedPerMinute"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002214
sprangb4a1ae52015-12-03 08:10:08 -08002215 EXPECT_EQ(
2216 1, test::NumHistogramSamples(video_prefix + "KeyFramesSentInPermille"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002217 EXPECT_EQ(1, test::NumHistogramSamples(
2218 "WebRTC.Video.KeyFramesReceivedInPermille"));
2219
sprange2d83d62016-02-19 09:03:26 -08002220 EXPECT_EQ(
2221 1, test::NumHistogramSamples(video_prefix + "SentPacketsLostInPercent"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002222 EXPECT_EQ(1, test::NumHistogramSamples(
2223 "WebRTC.Video.ReceivedPacketsLostInPercent"));
2224
sprangb4a1ae52015-12-03 08:10:08 -08002225 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "InputWidthInPixels"));
2226 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "InputHeightInPixels"));
2227 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SentWidthInPixels"));
2228 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SentHeightInPixels"));
asaperssond89920b2015-07-22 06:52:00 -07002229 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.ReceivedWidthInPixels"));
2230 EXPECT_EQ(1,
2231 test::NumHistogramSamples("WebRTC.Video.ReceivedHeightInPixels"));
2232
stefanff483612015-12-21 03:14:00 -08002233 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].width),
sprangb4a1ae52015-12-03 08:10:08 -08002234 test::LastHistogramSample(video_prefix + "InputWidthInPixels"));
stefanff483612015-12-21 03:14:00 -08002235 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].height),
sprangb4a1ae52015-12-03 08:10:08 -08002236 test::LastHistogramSample(video_prefix + "InputHeightInPixels"));
stefanff483612015-12-21 03:14:00 -08002237 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].width),
sprangb4a1ae52015-12-03 08:10:08 -08002238 test::LastHistogramSample(video_prefix + "SentWidthInPixels"));
stefanff483612015-12-21 03:14:00 -08002239 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].height),
sprangb4a1ae52015-12-03 08:10:08 -08002240 test::LastHistogramSample(video_prefix + "SentHeightInPixels"));
stefanff483612015-12-21 03:14:00 -08002241 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].width),
asaperssond89920b2015-07-22 06:52:00 -07002242 test::LastHistogramSample("WebRTC.Video.ReceivedWidthInPixels"));
stefanff483612015-12-21 03:14:00 -08002243 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].height),
asaperssond89920b2015-07-22 06:52:00 -07002244 test::LastHistogramSample("WebRTC.Video.ReceivedHeightInPixels"));
2245
sprangb4a1ae52015-12-03 08:10:08 -08002246 EXPECT_EQ(1,
2247 test::NumHistogramSamples(video_prefix + "InputFramesPerSecond"));
2248 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SentFramesPerSecond"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002249 EXPECT_EQ(1, test::NumHistogramSamples(
2250 "WebRTC.Video.DecodedFramesPerSecond"));
asaperssond89920b2015-07-22 06:52:00 -07002251 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.RenderFramesPerSecond"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002252
asapersson6f14be82015-11-16 00:40:49 -08002253 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.OnewayDelayInMs"));
2254 EXPECT_EQ(
2255 1, test::NumHistogramSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
2256
sprangb4a1ae52015-12-03 08:10:08 -08002257 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "EncodeTimeInMs"));
asapersson6718e972015-07-24 00:20:58 -07002258 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.DecodeTimeInMs"));
2259
Erik Språng22c2b482016-03-01 09:40:42 +01002260 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "BitrateSentInKbps"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002261 EXPECT_EQ(1, test::NumHistogramSamples(
2262 "WebRTC.Video.BitrateReceivedInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002263 EXPECT_EQ(1,
2264 test::NumHistogramSamples(video_prefix + "MediaBitrateSentInKbps"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002265 EXPECT_EQ(1, test::NumHistogramSamples(
2266 "WebRTC.Video.MediaBitrateReceivedInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002267 EXPECT_EQ(
2268 1, test::NumHistogramSamples(video_prefix + "PaddingBitrateSentInKbps"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002269 EXPECT_EQ(1, test::NumHistogramSamples(
2270 "WebRTC.Video.PaddingBitrateReceivedInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002271 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix +
2272 "RetransmittedBitrateSentInKbps"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002273 EXPECT_EQ(1, test::NumHistogramSamples(
2274 "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
2275
sprangb4a1ae52015-12-03 08:10:08 -08002276 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SendSideDelayInMs"));
2277 EXPECT_EQ(1,
2278 test::NumHistogramSamples(video_prefix + "SendSideDelayMaxInMs"));
asapersson6f14be82015-11-16 00:40:49 -08002279
Åsa Persson3c391cb2015-04-27 10:09:49 +02002280 int num_rtx_samples = use_rtx ? 1 : 0;
2281 EXPECT_EQ(num_rtx_samples, test::NumHistogramSamples(
2282 "WebRTC.Video.RtxBitrateSentInKbps"));
2283 EXPECT_EQ(num_rtx_samples, test::NumHistogramSamples(
2284 "WebRTC.Video.RtxBitrateReceivedInKbps"));
2285
2286 int num_red_samples = use_red ? 1 : 0;
2287 EXPECT_EQ(num_red_samples, test::NumHistogramSamples(
2288 "WebRTC.Video.FecBitrateSentInKbps"));
2289 EXPECT_EQ(num_red_samples, test::NumHistogramSamples(
2290 "WebRTC.Video.FecBitrateReceivedInKbps"));
2291 EXPECT_EQ(num_red_samples, test::NumHistogramSamples(
2292 "WebRTC.Video.ReceivedFecPacketsInPercent"));
2293}
2294
2295TEST_F(EndToEndTest, VerifyHistogramStatsWithRtx) {
2296 const bool kEnabledRtx = true;
2297 const bool kEnabledRed = false;
sprangb4a1ae52015-12-03 08:10:08 -08002298 const bool kScreenshare = false;
2299 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002300}
2301
2302TEST_F(EndToEndTest, VerifyHistogramStatsWithRed) {
2303 const bool kEnabledRtx = false;
2304 const bool kEnabledRed = true;
sprangb4a1ae52015-12-03 08:10:08 -08002305 const bool kScreenshare = false;
2306 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
2307}
2308
2309TEST_F(EndToEndTest, VerifyHistogramStatsWithScreenshare) {
2310 const bool kEnabledRtx = false;
2311 const bool kEnabledRed = false;
2312 const bool kScreenshare = true;
2313 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002314}
2315
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002316void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
2317 static const int kNumRtcpReportPacketsToObserve = 5;
2318 class RtcpXrObserver : public test::EndToEndTest {
2319 public:
2320 explicit RtcpXrObserver(bool enable_rrtr)
2321 : EndToEndTest(kDefaultTimeoutMs),
2322 enable_rrtr_(enable_rrtr),
2323 sent_rtcp_sr_(0),
2324 sent_rtcp_rr_(0),
2325 sent_rtcp_rrtr_(0),
2326 sent_rtcp_dlrr_(0) {}
2327
2328 private:
2329 // Receive stream should send RR packets (and RRTR packets if enabled).
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002330 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002331 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002332 RTCPUtility::RTCPParserV2 parser(packet, length, true);
2333 EXPECT_TRUE(parser.IsValid());
2334
2335 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02002336 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
2337 if (packet_type == RTCPUtility::RTCPPacketTypes::kRr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002338 ++sent_rtcp_rr_;
2339 } else if (packet_type ==
Erik Språng242e22b2015-05-11 10:17:43 +02002340 RTCPUtility::RTCPPacketTypes::kXrReceiverReferenceTime) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002341 ++sent_rtcp_rrtr_;
2342 }
Erik Språng242e22b2015-05-11 10:17:43 +02002343 EXPECT_NE(packet_type, RTCPUtility::RTCPPacketTypes::kSr);
2344 EXPECT_NE(packet_type,
2345 RTCPUtility::RTCPPacketTypes::kXrDlrrReportBlockItem);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002346 packet_type = parser.Iterate();
2347 }
2348 return SEND_PACKET;
2349 }
2350 // Send stream should send SR packets (and DLRR packets if enabled).
2351 virtual Action OnSendRtcp(const uint8_t* packet, size_t length) {
stefan608213e2015-11-01 14:56:10 -08002352 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002353 RTCPUtility::RTCPParserV2 parser(packet, length, true);
2354 EXPECT_TRUE(parser.IsValid());
2355
2356 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02002357 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
2358 if (packet_type == RTCPUtility::RTCPPacketTypes::kSr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002359 ++sent_rtcp_sr_;
Erik Språng242e22b2015-05-11 10:17:43 +02002360 } else if (packet_type ==
2361 RTCPUtility::RTCPPacketTypes::kXrDlrrReportBlockItem) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002362 ++sent_rtcp_dlrr_;
2363 }
Erik Språng242e22b2015-05-11 10:17:43 +02002364 EXPECT_NE(packet_type,
2365 RTCPUtility::RTCPPacketTypes::kXrReceiverReferenceTime);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002366 packet_type = parser.Iterate();
2367 }
2368 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
2369 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve) {
2370 if (enable_rrtr_) {
2371 EXPECT_GT(sent_rtcp_rrtr_, 0);
2372 EXPECT_GT(sent_rtcp_dlrr_, 0);
2373 } else {
2374 EXPECT_EQ(0, sent_rtcp_rrtr_);
2375 EXPECT_EQ(0, sent_rtcp_dlrr_);
2376 }
Peter Boström5811a392015-12-10 13:02:50 +01002377 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002378 }
2379 return SEND_PACKET;
2380 }
2381
stefanff483612015-12-21 03:14:00 -08002382 void ModifyVideoConfigs(
2383 VideoSendStream::Config* send_config,
2384 std::vector<VideoReceiveStream::Config>* receive_configs,
2385 VideoEncoderConfig* encoder_config) override {
pbosda903ea2015-10-02 02:36:56 -07002386 (*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002387 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
2388 enable_rrtr_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002389 }
2390
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002391 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002392 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002393 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
2394 }
2395
stefan608213e2015-11-01 14:56:10 -08002396 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002397 bool enable_rrtr_;
2398 int sent_rtcp_sr_;
stefan608213e2015-11-01 14:56:10 -08002399 int sent_rtcp_rr_ GUARDED_BY(&crit_);
2400 int sent_rtcp_rrtr_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002401 int sent_rtcp_dlrr_;
2402 } test(enable_rrtr);
2403
stefane74eef12016-01-08 06:47:13 -08002404 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002405}
2406
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002407void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
2408 bool send_single_ssrc_first) {
2409 class SendsSetSsrcs : public test::EndToEndTest {
2410 public:
2411 SendsSetSsrcs(const uint32_t* ssrcs,
2412 size_t num_ssrcs,
2413 bool send_single_ssrc_first)
2414 : EndToEndTest(kDefaultTimeoutMs),
2415 num_ssrcs_(num_ssrcs),
2416 send_single_ssrc_first_(send_single_ssrc_first),
2417 ssrcs_to_observe_(num_ssrcs),
sprang867fb522015-08-03 04:38:41 -07002418 expect_single_ssrc_(send_single_ssrc_first),
2419 send_stream_(nullptr) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002420 for (size_t i = 0; i < num_ssrcs; ++i)
2421 valid_ssrcs_[ssrcs[i]] = true;
2422 }
2423
2424 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002425 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002426 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002427 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002428
2429 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
2430 << "Received unknown SSRC: " << header.ssrc;
2431
2432 if (!valid_ssrcs_[header.ssrc])
Peter Boström5811a392015-12-10 13:02:50 +01002433 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002434
2435 if (!is_observed_[header.ssrc]) {
2436 is_observed_[header.ssrc] = true;
2437 --ssrcs_to_observe_;
2438 if (expect_single_ssrc_) {
2439 expect_single_ssrc_ = false;
Peter Boström5811a392015-12-10 13:02:50 +01002440 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002441 }
2442 }
2443
2444 if (ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002445 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002446
2447 return SEND_PACKET;
2448 }
2449
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002450 size_t GetNumVideoStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002451
stefanff483612015-12-21 03:14:00 -08002452 void ModifyVideoConfigs(
2453 VideoSendStream::Config* send_config,
2454 std::vector<VideoReceiveStream::Config>* receive_configs,
2455 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002456 if (num_ssrcs_ > 1) {
2457 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002458 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2459 encoder_config->streams[i].min_bitrate_bps = 10000;
2460 encoder_config->streams[i].target_bitrate_bps = 15000;
2461 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002462 }
2463 }
2464
stefanff483612015-12-21 03:14:00 -08002465 video_encoder_config_all_streams_ = *encoder_config;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002466 if (send_single_ssrc_first_)
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002467 encoder_config->streams.resize(1);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002468 }
2469
stefanff483612015-12-21 03:14:00 -08002470 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002471 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002472 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002473 send_stream_ = send_stream;
2474 }
2475
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002476 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002477 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2478 << (send_single_ssrc_first_ ? "first SSRC."
2479 : "SSRCs.");
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002480
2481 if (send_single_ssrc_first_) {
2482 // Set full simulcast and continue with the rest of the SSRCs.
stefanff483612015-12-21 03:14:00 -08002483 send_stream_->ReconfigureVideoEncoder(
2484 video_encoder_config_all_streams_);
Peter Boström5811a392015-12-10 13:02:50 +01002485 EXPECT_TRUE(Wait()) << "Timed out while waiting on additional SSRCs.";
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002486 }
2487 }
2488
2489 private:
2490 std::map<uint32_t, bool> valid_ssrcs_;
2491 std::map<uint32_t, bool> is_observed_;
2492
2493 const size_t num_ssrcs_;
2494 const bool send_single_ssrc_first_;
2495
2496 size_t ssrcs_to_observe_;
2497 bool expect_single_ssrc_;
2498
2499 VideoSendStream* send_stream_;
stefanff483612015-12-21 03:14:00 -08002500 VideoEncoderConfig video_encoder_config_all_streams_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002501 } test(kVideoSendSsrcs, num_ssrcs, send_single_ssrc_first);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002502
stefane74eef12016-01-08 06:47:13 -08002503 RunBaseTest(&test);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002504}
2505
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002506TEST_F(EndToEndTest, ReportsSetEncoderRates) {
2507 class EncoderRateStatsTest : public test::EndToEndTest,
2508 public test::FakeEncoder {
2509 public:
2510 EncoderRateStatsTest()
2511 : EndToEndTest(kDefaultTimeoutMs),
sprang867fb522015-08-03 04:38:41 -07002512 FakeEncoder(Clock::GetRealTimeClock()),
2513 send_stream_(nullptr),
2514 bitrate_kbps_(0) {}
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002515
stefanff483612015-12-21 03:14:00 -08002516 void OnVideoStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002517 VideoSendStream* send_stream,
2518 const std::vector<VideoReceiveStream*>& receive_streams) override {
2519 send_stream_ = send_stream;
2520 }
2521
stefanff483612015-12-21 03:14:00 -08002522 void ModifyVideoConfigs(
2523 VideoSendStream::Config* send_config,
2524 std::vector<VideoReceiveStream::Config>* receive_configs,
2525 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002526 send_config->encoder_settings.encoder = this;
2527 }
2528
2529 int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override {
2530 // Make sure not to trigger on any default zero bitrates.
2531 if (new_target_bitrate == 0)
2532 return 0;
Peter Boströmf2f82832015-05-01 13:00:41 +02002533 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002534 bitrate_kbps_ = new_target_bitrate;
Peter Boström5811a392015-12-10 13:02:50 +01002535 observation_complete_.Set();
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002536 return 0;
2537 }
2538
2539 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002540 ASSERT_TRUE(Wait())
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002541 << "Timed out while waiting for encoder SetRates() call.";
2542 // Wait for GetStats to report a corresponding bitrate.
Peter Boström5811a392015-12-10 13:02:50 +01002543 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002544 VideoSendStream::Stats stats = send_stream_->GetStats();
2545 {
Peter Boströmf2f82832015-05-01 13:00:41 +02002546 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002547 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
2548 static_cast<int>(bitrate_kbps_)) {
2549 return;
2550 }
2551 }
2552 SleepMs(1);
2553 }
2554 FAIL()
2555 << "Timed out waiting for stats reporting the currently set bitrate.";
2556 }
2557
2558 private:
stefanf116bd02015-10-27 08:29:42 -07002559 rtc::CriticalSection crit_;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002560 VideoSendStream* send_stream_;
2561 uint32_t bitrate_kbps_ GUARDED_BY(crit_);
2562 } test;
2563
stefane74eef12016-01-08 06:47:13 -08002564 RunBaseTest(&test);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002565}
2566
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002567TEST_F(EndToEndTest, GetStats) {
2568 static const int kStartBitrateBps = 3000000;
Peter Boströmdef398832015-05-27 17:59:11 +02002569 static const int kExpectedRenderDelayMs = 20;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002570 class StatsObserver : public test::EndToEndTest, public I420FrameCallback {
2571 public:
stefanf116bd02015-10-27 08:29:42 -07002572 StatsObserver()
2573 : EndToEndTest(kLongTimeoutMs),
Peter Boströmc6e16e32016-02-05 14:15:53 +01002574 encoder_(Clock::GetRealTimeClock(), 10),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002575 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002576 expected_send_ssrcs_(),
Peter Boström5811a392015-12-10 13:02:50 +01002577 check_stats_event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002578
2579 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002580 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002581 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002582 return SEND_PACKET;
2583 }
2584
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002585 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002586 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002587 return SEND_PACKET;
2588 }
2589
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002590 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002591 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002592 return SEND_PACKET;
2593 }
2594
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002595 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002596 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002597 return SEND_PACKET;
2598 }
2599
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07002600 void FrameCallback(VideoFrame* video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002601 // Ensure that we have at least 5ms send side delay.
2602 int64_t render_time = video_frame->render_time_ms();
2603 if (render_time > 0)
2604 video_frame->set_render_time_ms(render_time - 5);
2605 }
2606
2607 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002608 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2609 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2610 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002611
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002612 // Make sure all fields have been populated.
2613 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
2614 // always filled for all receivers.
2615 receive_stats_filled_["IncomingRate"] |=
2616 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002617
Peter Boströmb7d9a972015-12-18 16:01:11 +01002618 send_stats_filled_["DecoderImplementationName"] |=
2619 stats.decoder_implementation_name ==
2620 test::FakeDecoder::kImplementationName;
Peter Boströmdef398832015-05-27 17:59:11 +02002621 receive_stats_filled_["RenderDelayAsHighAsExpected"] |=
2622 stats.render_delay_ms >= kExpectedRenderDelayMs;
2623
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002624 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002625
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002626 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002627
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002628 receive_stats_filled_["StatisticsUpdated"] |=
2629 stats.rtcp_stats.cumulative_lost != 0 ||
2630 stats.rtcp_stats.extended_max_sequence_number != 0 ||
2631 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002632
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002633 receive_stats_filled_["DataCountersUpdated"] |=
2634 stats.rtp_stats.transmitted.payload_bytes != 0 ||
2635 stats.rtp_stats.fec.packets != 0 ||
2636 stats.rtp_stats.transmitted.header_bytes != 0 ||
2637 stats.rtp_stats.transmitted.packets != 0 ||
2638 stats.rtp_stats.transmitted.padding_bytes != 0 ||
2639 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002640
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002641 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002642 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002643
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002644 receive_stats_filled_["FrameCounts"] |=
2645 stats.frame_counts.key_frames != 0 ||
2646 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002647
pbosbb36fdf2015-07-09 07:48:14 -07002648 receive_stats_filled_["CName"] |= !stats.c_name.empty();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002649
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002650 receive_stats_filled_["RtcpPacketTypeCount"] |=
2651 stats.rtcp_packet_type_counts.fir_packets != 0 ||
2652 stats.rtcp_packet_type_counts.nack_packets != 0 ||
2653 stats.rtcp_packet_type_counts.pli_packets != 0 ||
2654 stats.rtcp_packet_type_counts.nack_requests != 0 ||
2655 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbosf42376c2015-08-28 07:35:32 -07002656
2657 assert(stats.current_payload_type == -1 ||
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002658 stats.current_payload_type == kFakeVideoSendPayloadType);
pbosf42376c2015-08-28 07:35:32 -07002659 receive_stats_filled_["IncomingPayloadType"] |=
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002660 stats.current_payload_type == kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002661 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002662
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002663 return AllStatsFilled(receive_stats_filled_);
2664 }
2665
2666 bool CheckSendStats() {
henrikg91d6ede2015-09-17 00:24:34 -07002667 RTC_DCHECK(send_stream_ != nullptr);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002668 VideoSendStream::Stats stats = send_stream_->GetStats();
2669
2670 send_stats_filled_["NumStreams"] |=
2671 stats.substreams.size() == expected_send_ssrcs_.size();
2672
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002673 send_stats_filled_["CpuOveruseMetrics"] |=
Peter Boströme4499152016-02-05 11:13:28 +01002674 stats.avg_encode_time_ms != 0 && stats.encode_usage_percent != 0;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002675
Peter Boströmb7d9a972015-12-18 16:01:11 +01002676 send_stats_filled_["EncoderImplementationName"] |=
2677 stats.encoder_implementation_name ==
2678 test::FakeEncoder::kImplementationName;
2679
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002680 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002681 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002682 it != stats.substreams.end(); ++it) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002683 EXPECT_TRUE(expected_send_ssrcs_.find(it->first) !=
2684 expected_send_ssrcs_.end());
2685
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002686 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002687 stats.input_frame_rate != 0;
2688
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002689 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002690
2691 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
2692 stream_stats.rtcp_stats.cumulative_lost != 0 ||
2693 stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
2694 stream_stats.rtcp_stats.fraction_lost != 0;
2695
2696 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002697 stream_stats.rtp_stats.fec.packets != 0 ||
2698 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
2699 stream_stats.rtp_stats.retransmitted.packets != 0 ||
2700 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002701
2702 send_stats_filled_[CompoundKey("BitrateStatisticsObserver",
2703 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002704 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002705
2706 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002707 stream_stats.frame_counts.delta_frames != 0 ||
2708 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002709
2710 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
2711 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00002712
2713 send_stats_filled_[CompoundKey("Delay", it->first)] |=
2714 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002715
2716 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
2717 // report dropped packets.
2718 send_stats_filled_["RtcpPacketTypeCount"] |=
2719 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
2720 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
2721 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
2722 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
2723 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002724 }
2725
2726 return AllStatsFilled(send_stats_filled_);
2727 }
2728
2729 std::string CompoundKey(const char* name, uint32_t ssrc) {
2730 std::ostringstream oss;
2731 oss << name << "_" << ssrc;
2732 return oss.str();
2733 }
2734
2735 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
2736 for (std::map<std::string, bool>::const_iterator it = stats_map.begin();
2737 it != stats_map.end();
2738 ++it) {
2739 if (!it->second)
2740 return false;
2741 }
2742 return true;
2743 }
2744
stefane74eef12016-01-08 06:47:13 -08002745 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
2746 FakeNetworkPipe::Config network_config;
2747 network_config.loss_percent = 5;
2748 return new test::PacketTransport(
2749 sender_call, this, test::PacketTransport::kSender, network_config);
2750 }
2751
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002752 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002753 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01002754 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002755 return config;
2756 }
2757
stefanff483612015-12-21 03:14:00 -08002758 void ModifyVideoConfigs(
2759 VideoSendStream::Config* send_config,
2760 std::vector<VideoReceiveStream::Config>* receive_configs,
2761 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002762 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002763 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002764
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002765 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002766 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002767 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002768 expected_receive_ssrcs_.push_back(
2769 (*receive_configs)[i].rtp.remote_ssrc);
Peter Boströmdef398832015-05-27 17:59:11 +02002770 (*receive_configs)[i].render_delay_ms = kExpectedRenderDelayMs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002771 }
Peter Boströmc6e16e32016-02-05 14:15:53 +01002772 // Use a delayed encoder to make sure we see CpuOveruseMetrics stats that
2773 // are non-zero.
2774 send_config->encoder_settings.encoder = &encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002775 }
2776
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002777 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00002778
stefanff483612015-12-21 03:14:00 -08002779 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002780 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002781 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002782 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002783 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002784 }
2785
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002786 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002787 Clock* clock = Clock::GetRealTimeClock();
2788 int64_t now = clock->TimeInMilliseconds();
2789 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
2790 bool receive_ok = false;
2791 bool send_ok = false;
2792
2793 while (now < stop_time) {
2794 if (!receive_ok)
2795 receive_ok = CheckReceiveStats();
2796 if (!send_ok)
2797 send_ok = CheckSendStats();
2798
2799 if (receive_ok && send_ok)
2800 return;
2801
2802 int64_t time_until_timout_ = stop_time - now;
2803 if (time_until_timout_ > 0)
Peter Boström5811a392015-12-10 13:02:50 +01002804 check_stats_event_.Wait(time_until_timout_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002805 now = clock->TimeInMilliseconds();
2806 }
2807
2808 ADD_FAILURE() << "Timed out waiting for filled stats.";
2809 for (std::map<std::string, bool>::const_iterator it =
2810 receive_stats_filled_.begin();
2811 it != receive_stats_filled_.end();
2812 ++it) {
2813 if (!it->second) {
2814 ADD_FAILURE() << "Missing receive stats: " << it->first;
2815 }
2816 }
2817
2818 for (std::map<std::string, bool>::const_iterator it =
2819 send_stats_filled_.begin();
2820 it != send_stats_filled_.end();
2821 ++it) {
2822 if (!it->second) {
2823 ADD_FAILURE() << "Missing send stats: " << it->first;
2824 }
2825 }
2826 }
2827
Peter Boströmc6e16e32016-02-05 14:15:53 +01002828 test::DelayedEncoder encoder_;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002829 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002830 std::map<std::string, bool> receive_stats_filled_;
2831
2832 VideoSendStream* send_stream_;
2833 std::map<std::string, bool> send_stats_filled_;
2834
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002835 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002836 std::set<uint32_t> expected_send_ssrcs_;
2837 std::string expected_cname_;
2838
Peter Boström5811a392015-12-10 13:02:50 +01002839 rtc::Event check_stats_event_;
stefanf116bd02015-10-27 08:29:42 -07002840 } test;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002841
stefane74eef12016-01-08 06:47:13 -08002842 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002843}
2844
2845TEST_F(EndToEndTest, ReceiverReferenceTimeReportEnabled) {
2846 TestXrReceiverReferenceTimeReport(true);
2847}
2848
2849TEST_F(EndToEndTest, ReceiverReferenceTimeReportDisabled) {
2850 TestXrReceiverReferenceTimeReport(false);
2851}
2852
2853TEST_F(EndToEndTest, TestReceivedRtpPacketStats) {
2854 static const size_t kNumRtpPacketsToSend = 5;
2855 class ReceivedRtpStatsObserver : public test::EndToEndTest {
2856 public:
2857 ReceivedRtpStatsObserver()
2858 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002859 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002860 sent_rtp_(0) {}
2861
2862 private:
stefanff483612015-12-21 03:14:00 -08002863 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002864 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002865 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002866 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002867 }
2868
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002869 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002870 if (sent_rtp_ >= kNumRtpPacketsToSend) {
2871 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002872 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
Peter Boström5811a392015-12-10 13:02:50 +01002873 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002874 }
2875 return DROP_PACKET;
2876 }
2877 ++sent_rtp_;
2878 return SEND_PACKET;
2879 }
2880
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002881 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002882 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002883 << "Timed out while verifying number of received RTP packets.";
2884 }
2885
2886 VideoReceiveStream* receive_stream_;
2887 uint32_t sent_rtp_;
2888 } test;
2889
stefane74eef12016-01-08 06:47:13 -08002890 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002891}
2892
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002893TEST_F(EndToEndTest, SendsSetSsrc) { TestSendsSetSsrcs(1, false); }
2894
2895TEST_F(EndToEndTest, SendsSetSimulcastSsrcs) {
2896 TestSendsSetSsrcs(kNumSsrcs, false);
2897}
2898
2899TEST_F(EndToEndTest, CanSwitchToUseAllSsrcs) {
2900 TestSendsSetSsrcs(kNumSsrcs, true);
2901}
2902
mflodman@webrtc.orgf9460682014-07-24 16:41:25 +00002903TEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002904 class ObserveRedundantPayloads: public test::EndToEndTest {
2905 public:
2906 ObserveRedundantPayloads()
2907 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00002908 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002909 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
2910 }
2911 }
2912
2913 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002914 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002915 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002916 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002917
2918 if (!registered_rtx_ssrc_[header.ssrc])
2919 return SEND_PACKET;
2920
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002921 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002922 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002923 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002924
2925 if (!packet_is_redundant_payload)
2926 return SEND_PACKET;
2927
2928 if (!observed_redundant_retransmission_[header.ssrc]) {
2929 observed_redundant_retransmission_[header.ssrc] = true;
2930 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002931 observation_complete_.Set();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002932 }
2933
2934 return SEND_PACKET;
2935 }
2936
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002937 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002938
stefanff483612015-12-21 03:14:00 -08002939 void ModifyVideoConfigs(
2940 VideoSendStream::Config* send_config,
2941 std::vector<VideoReceiveStream::Config>* receive_configs,
2942 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002943 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002944 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2945 encoder_config->streams[i].min_bitrate_bps = 10000;
2946 encoder_config->streams[i].target_bitrate_bps = 15000;
2947 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002948 }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002949
2950 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002951
2952 for (size_t i = 0; i < kNumSsrcs; ++i)
2953 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00002954
2955 // Significantly higher than max bitrates for all video streams -> forcing
2956 // padding to trigger redundant padding on all RTX SSRCs.
2957 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002958 }
2959
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002960 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002961 EXPECT_TRUE(Wait())
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002962 << "Timed out while waiting for redundant payloads on all SSRCs.";
2963 }
2964
2965 private:
2966 size_t ssrcs_to_observe_;
2967 std::map<uint32_t, bool> observed_redundant_retransmission_;
2968 std::map<uint32_t, bool> registered_rtx_ssrc_;
2969 } test;
2970
stefane74eef12016-01-08 06:47:13 -08002971 RunBaseTest(&test);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002972}
2973
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002974void EndToEndTest::TestRtpStatePreservation(bool use_rtx) {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002975 class RtpSequenceObserver : public test::RtpRtcpObserver {
2976 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00002977 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002978 : test::RtpRtcpObserver(kDefaultTimeoutMs),
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002979 ssrcs_to_observe_(kNumSsrcs) {
2980 for (size_t i = 0; i < kNumSsrcs; ++i) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002981 configured_ssrcs_[kVideoSendSsrcs[i]] = true;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002982 if (use_rtx)
2983 configured_ssrcs_[kSendRtxSsrcs[i]] = true;
2984 }
2985 }
2986
2987 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
Peter Boströmf2f82832015-05-01 13:00:41 +02002988 rtc::CritScope lock(&crit_);
danilchap34877ee2016-02-01 08:25:04 -08002989 ssrc_observed_.clear();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002990 ssrcs_to_observe_ = num_expected_ssrcs;
2991 }
2992
2993 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002994 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002995 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002996 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002997 const uint32_t ssrc = header.ssrc;
danilchap5c35cf92016-02-03 14:14:49 -08002998 const int64_t sequence_number =
2999 seq_numbers_unwrapper_.Unwrap(header.sequenceNumber);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003000 const uint32_t timestamp = header.timestamp;
danilchap34877ee2016-02-01 08:25:04 -08003001 const bool only_padding =
3002 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003003
3004 EXPECT_TRUE(configured_ssrcs_[ssrc])
3005 << "Received SSRC that wasn't configured: " << ssrc;
3006
danilchap5c35cf92016-02-03 14:14:49 -08003007 static const int64_t kMaxSequenceNumberGap = 100;
3008 std::list<int64_t>* seq_numbers = &last_observed_seq_numbers_[ssrc];
3009 if (seq_numbers->empty()) {
3010 seq_numbers->push_back(sequence_number);
3011 } else {
3012 // We shouldn't get replays of previous sequence numbers.
3013 for (int64_t observed : *seq_numbers) {
3014 EXPECT_NE(observed, sequence_number)
3015 << "Received sequence number " << sequence_number
3016 << " for SSRC " << ssrc << " 2nd time.";
3017 }
3018 // Verify sequence numbers are reasonably close.
3019 int64_t latest_observed = seq_numbers->back();
3020 int64_t sequence_number_gap = sequence_number - latest_observed;
3021 EXPECT_LE(std::abs(sequence_number_gap), kMaxSequenceNumberGap)
3022 << "Gap in sequence numbers (" << latest_observed << " -> "
3023 << sequence_number << ") too large for SSRC: " << ssrc << ".";
3024 seq_numbers->push_back(sequence_number);
3025 if (seq_numbers->size() >= kMaxSequenceNumberGap) {
3026 seq_numbers->pop_front();
3027 }
3028 }
3029
3030 static const int32_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
3031 auto timestamp_it = last_observed_timestamp_.find(ssrc);
3032 if (timestamp_it == last_observed_timestamp_.end()) {
danilchap34877ee2016-02-01 08:25:04 -08003033 last_observed_timestamp_[ssrc] = timestamp;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003034 } else {
danilchap5c35cf92016-02-03 14:14:49 -08003035 // Verify timestamps are reasonably close.
3036 uint32_t latest_observed = timestamp_it->second;
3037 int32_t timestamp_gap = rtc::TimeDiff(timestamp, latest_observed);
3038 EXPECT_LE(std::abs(timestamp_gap), kMaxTimestampGap)
3039 << "Gap in timestamps (" << latest_observed << " -> "
3040 << timestamp << ") too large for SSRC: " << ssrc << ".";
3041 timestamp_it->second = timestamp;
danilchapf4b9c772016-01-28 06:14:24 -08003042 }
danilchap34877ee2016-02-01 08:25:04 -08003043
3044 rtc::CritScope lock(&crit_);
3045 // Wait for media packets on all ssrcs.
3046 if (!ssrc_observed_[ssrc] && !only_padding) {
3047 ssrc_observed_[ssrc] = true;
3048 if (--ssrcs_to_observe_ == 0)
3049 observation_complete_.Set();
3050 }
3051
danilchapf4b9c772016-01-28 06:14:24 -08003052 return SEND_PACKET;
3053 }
3054
danilchap5c35cf92016-02-03 14:14:49 -08003055 SequenceNumberUnwrapper seq_numbers_unwrapper_;
3056 std::map<uint32_t, std::list<int64_t>> last_observed_seq_numbers_;
danilchap34877ee2016-02-01 08:25:04 -08003057 std::map<uint32_t, uint32_t> last_observed_timestamp_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003058 std::map<uint32_t, bool> configured_ssrcs_;
3059
Peter Boströmf2f82832015-05-01 13:00:41 +02003060 rtc::CriticalSection crit_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003061 size_t ssrcs_to_observe_ GUARDED_BY(crit_);
danilchap34877ee2016-02-01 08:25:04 -08003062 std::map<uint32_t, bool> ssrc_observed_ GUARDED_BY(crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003063 } observer(use_rtx);
3064
solenberg4fbae2b2015-08-28 04:07:10 -07003065 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003066
stefanf116bd02015-10-27 08:29:42 -07003067 test::PacketTransport send_transport(sender_call_.get(), &observer,
3068 test::PacketTransport::kSender,
3069 FakeNetworkPipe::Config());
3070 test::PacketTransport receive_transport(nullptr, &observer,
3071 test::PacketTransport::kReceiver,
3072 FakeNetworkPipe::Config());
3073 send_transport.SetReceiver(receiver_call_->Receiver());
3074 receive_transport.SetReceiver(sender_call_->Receiver());
3075
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003076 CreateSendConfig(kNumSsrcs, 0, &send_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003077
3078 if (use_rtx) {
3079 for (size_t i = 0; i < kNumSsrcs; ++i) {
stefanff483612015-12-21 03:14:00 -08003080 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003081 }
stefanff483612015-12-21 03:14:00 -08003082 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003083 }
3084
3085 // Lower bitrates so that all streams send initially.
stefanff483612015-12-21 03:14:00 -08003086 for (size_t i = 0; i < video_encoder_config_.streams.size(); ++i) {
3087 video_encoder_config_.streams[i].min_bitrate_bps = 10000;
3088 video_encoder_config_.streams[i].target_bitrate_bps = 15000;
3089 video_encoder_config_.streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003090 }
3091
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003092 // Use the same total bitrates when sending a single stream to avoid lowering
3093 // the bitrate estimate and requiring a subsequent rampup.
stefanff483612015-12-21 03:14:00 -08003094 VideoEncoderConfig one_stream = video_encoder_config_;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003095 one_stream.streams.resize(1);
stefanff483612015-12-21 03:14:00 -08003096 for (size_t i = 1; i < video_encoder_config_.streams.size(); ++i) {
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003097 one_stream.streams.front().min_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003098 video_encoder_config_.streams[i].min_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003099 one_stream.streams.front().target_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003100 video_encoder_config_.streams[i].target_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003101 one_stream.streams.front().max_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003102 video_encoder_config_.streams[i].max_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003103 }
3104
stefanf116bd02015-10-27 08:29:42 -07003105 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003106
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003107 CreateVideoStreams();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003108 CreateFrameGeneratorCapturer();
3109
3110 Start();
Peter Boström5811a392015-12-10 13:02:50 +01003111 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003112 << "Timed out waiting for all SSRCs to send packets.";
3113
3114 // Test stream resetting more than once to make sure that the state doesn't
3115 // get set once (this could be due to using std::map::insert for instance).
3116 for (size_t i = 0; i < 3; ++i) {
3117 frame_generator_capturer_->Stop();
stefanff483612015-12-21 03:14:00 -08003118 sender_call_->DestroyVideoSendStream(video_send_stream_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003119
3120 // Re-create VideoSendStream with only one stream.
stefanff483612015-12-21 03:14:00 -08003121 video_send_stream_ =
3122 sender_call_->CreateVideoSendStream(video_send_config_, one_stream);
3123 video_send_stream_->Start();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003124 CreateFrameGeneratorCapturer();
3125 frame_generator_capturer_->Start();
3126
3127 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003128 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003129
3130 // Reconfigure back to use all streams.
stefanff483612015-12-21 03:14:00 -08003131 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003132 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003133 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003134 << "Timed out waiting for all SSRCs to send packets.";
3135
3136 // Reconfigure down to one stream.
stefanff483612015-12-21 03:14:00 -08003137 video_send_stream_->ReconfigureVideoEncoder(one_stream);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003138 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003139 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003140
3141 // Reconfigure back to use all streams.
stefanff483612015-12-21 03:14:00 -08003142 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003143 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003144 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003145 << "Timed out waiting for all SSRCs to send packets.";
3146 }
3147
stefanf116bd02015-10-27 08:29:42 -07003148 send_transport.StopSending();
3149 receive_transport.StopSending();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003150
3151 Stop();
3152 DestroyStreams();
3153}
3154
Peter Boströmfc968a22016-02-19 16:14:37 +01003155TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpState) {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003156 TestRtpStatePreservation(false);
3157}
3158
3159TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpStatesWithRtx) {
3160 TestRtpStatePreservation(true);
3161}
3162
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003163TEST_F(EndToEndTest, RespectsNetworkState) {
3164 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
3165 // down blocks until no more packets will be sent.
3166
3167 // Pacer will send from its packet list and then send required padding before
3168 // checking paused_ again. This should be enough for one round of pacing,
3169 // otherwise increase.
3170 static const int kNumAcceptedDowntimeRtp = 5;
3171 // A single RTCP may be in the pipeline.
3172 static const int kNumAcceptedDowntimeRtcp = 1;
3173 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
3174 public:
3175 NetworkStateTest()
3176 : EndToEndTest(kDefaultTimeoutMs),
3177 FakeEncoder(Clock::GetRealTimeClock()),
Peter Boström5811a392015-12-10 13:02:50 +01003178 encoded_frames_(false, false),
3179 packet_event_(false, false),
sprang867fb522015-08-03 04:38:41 -07003180 sender_call_(nullptr),
3181 receiver_call_(nullptr),
Jelena Marusiccd670222015-07-16 09:30:09 +02003182 sender_state_(kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003183 sender_rtp_(0),
3184 sender_rtcp_(0),
3185 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003186 down_frames_(0) {}
3187
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003188 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003189 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003190 ++sender_rtp_;
Peter Boström5811a392015-12-10 13:02:50 +01003191 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003192 return SEND_PACKET;
3193 }
3194
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003195 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003196 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003197 ++sender_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003198 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003199 return SEND_PACKET;
3200 }
3201
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003202 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003203 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
3204 return SEND_PACKET;
3205 }
3206
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003207 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003208 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003209 ++receiver_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003210 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003211 return SEND_PACKET;
3212 }
3213
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003214 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003215 sender_call_ = sender_call;
3216 receiver_call_ = receiver_call;
3217 }
3218
stefanff483612015-12-21 03:14:00 -08003219 void ModifyVideoConfigs(
3220 VideoSendStream::Config* send_config,
3221 std::vector<VideoReceiveStream::Config>* receive_configs,
3222 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003223 send_config->encoder_settings.encoder = this;
3224 }
3225
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003226 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003227 EXPECT_TRUE(encoded_frames_.Wait(kDefaultTimeoutMs))
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003228 << "No frames received by the encoder.";
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003229 // Wait for packets from both sender/receiver.
3230 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003231
skvlad7a43d252016-03-22 15:32:27 -07003232 // Sender-side network down for audio; there should be no effect on video
3233 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3234 WaitForPacketsOrSilence(false, false);
3235
3236 // Receiver-side network down for audio; no change expected
3237 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3238 WaitForPacketsOrSilence(false, false);
3239
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003240 // Sender-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003241 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003242 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003243 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003244 // After network goes down we shouldn't be encoding more frames.
Jelena Marusiccd670222015-07-16 09:30:09 +02003245 sender_state_ = kNetworkDown;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003246 }
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003247 // Wait for receiver-packets and no sender packets.
3248 WaitForPacketsOrSilence(true, false);
3249
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003250 // Receiver-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003251 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
3252 WaitForPacketsOrSilence(true, true);
3253
3254 // Network up for audio for both sides; video is still not expected to
3255 // start
3256 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
3257 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003258 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003259
3260 // Network back up again for both.
3261 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003262 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003263 // It's OK to encode frames again, as we're about to bring up the
3264 // network.
Jelena Marusiccd670222015-07-16 09:30:09 +02003265 sender_state_ = kNetworkUp;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003266 }
skvlad7a43d252016-03-22 15:32:27 -07003267 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
3268 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003269 WaitForPacketsOrSilence(false, false);
skvlad7a43d252016-03-22 15:32:27 -07003270
3271 // TODO(skvlad): add tests to verify that the audio streams are stopped
3272 // when the network goes down for audio once the workaround in
3273 // paced_sender.cc is removed.
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003274 }
3275
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07003276 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003277 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07003278 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003279 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003280 rtc::CritScope lock(&test_crit_);
Jelena Marusiccd670222015-07-16 09:30:09 +02003281 if (sender_state_ == kNetworkDown) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003282 ++down_frames_;
3283 EXPECT_LE(down_frames_, 1)
3284 << "Encoding more than one frame while network is down.";
3285 if (down_frames_ > 1)
Peter Boström5811a392015-12-10 13:02:50 +01003286 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003287 } else {
Peter Boström5811a392015-12-10 13:02:50 +01003288 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003289 }
3290 }
3291 return test::FakeEncoder::Encode(
3292 input_image, codec_specific_info, frame_types);
3293 }
3294
3295 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003296 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
3297 int64_t initial_time_ms = clock_->TimeInMilliseconds();
3298 int initial_sender_rtp;
3299 int initial_sender_rtcp;
3300 int initial_receiver_rtcp;
3301 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003302 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003303 initial_sender_rtp = sender_rtp_;
3304 initial_sender_rtcp = sender_rtcp_;
3305 initial_receiver_rtcp = receiver_rtcp_;
3306 }
3307 bool sender_done = false;
3308 bool receiver_done = false;
mflodmand1590b22015-12-09 07:07:59 -08003309 while (!sender_done || !receiver_done) {
Peter Boström5811a392015-12-10 13:02:50 +01003310 packet_event_.Wait(kSilenceTimeoutMs);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003311 int64_t time_now_ms = clock_->TimeInMilliseconds();
Peter Boströmf2f82832015-05-01 13:00:41 +02003312 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003313 if (sender_down) {
3314 ASSERT_LE(sender_rtp_ - initial_sender_rtp, kNumAcceptedDowntimeRtp)
3315 << "RTP sent during sender-side downtime.";
3316 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
3317 kNumAcceptedDowntimeRtcp)
3318 << "RTCP sent during sender-side downtime.";
3319 if (time_now_ms - initial_time_ms >=
3320 static_cast<int64_t>(kSilenceTimeoutMs)) {
3321 sender_done = true;
3322 }
3323 } else {
skvlad7a43d252016-03-22 15:32:27 -07003324 if (sender_rtp_ > initial_sender_rtp + kNumAcceptedDowntimeRtp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003325 sender_done = true;
3326 }
3327 if (receiver_down) {
3328 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
3329 kNumAcceptedDowntimeRtcp)
3330 << "RTCP sent during receiver-side downtime.";
3331 if (time_now_ms - initial_time_ms >=
3332 static_cast<int64_t>(kSilenceTimeoutMs)) {
3333 receiver_done = true;
3334 }
3335 } else {
skvlad7a43d252016-03-22 15:32:27 -07003336 if (receiver_rtcp_ > initial_receiver_rtcp + kNumAcceptedDowntimeRtcp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003337 receiver_done = true;
3338 }
3339 }
3340 }
3341
Peter Boströmf2f82832015-05-01 13:00:41 +02003342 rtc::CriticalSection test_crit_;
Peter Boström5811a392015-12-10 13:02:50 +01003343 rtc::Event encoded_frames_;
3344 rtc::Event packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003345 Call* sender_call_;
3346 Call* receiver_call_;
Jelena Marusiccd670222015-07-16 09:30:09 +02003347 NetworkState sender_state_ GUARDED_BY(test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003348 int sender_rtp_ GUARDED_BY(test_crit_);
3349 int sender_rtcp_ GUARDED_BY(test_crit_);
3350 int receiver_rtcp_ GUARDED_BY(test_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003351 int down_frames_ GUARDED_BY(test_crit_);
3352 } test;
3353
stefane74eef12016-01-08 06:47:13 -08003354 RunBaseTest(&test);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003355}
3356
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003357TEST_F(EndToEndTest, CallReportsRttForSender) {
3358 static const int kSendDelayMs = 30;
3359 static const int kReceiveDelayMs = 70;
3360
solenberg4fbae2b2015-08-28 04:07:10 -07003361 CreateCalls(Call::Config(), Call::Config());
3362
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003363 FakeNetworkPipe::Config config;
3364 config.queue_delay_ms = kSendDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003365 test::DirectTransport sender_transport(config, sender_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003366 config.queue_delay_ms = kReceiveDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003367 test::DirectTransport receiver_transport(config, receiver_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003368 sender_transport.SetReceiver(receiver_call_->Receiver());
3369 receiver_transport.SetReceiver(sender_call_->Receiver());
3370
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003371 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07003372 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003373
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003374 CreateVideoStreams();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003375 CreateFrameGeneratorCapturer();
3376 Start();
3377
3378 int64_t start_time_ms = clock_->TimeInMilliseconds();
3379 while (true) {
3380 Call::Stats stats = sender_call_->GetStats();
3381 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
3382 clock_->TimeInMilliseconds())
3383 << "No RTT stats before timeout!";
3384 if (stats.rtt_ms != -1) {
3385 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs);
3386 break;
3387 }
3388 SleepMs(10);
3389 }
3390
3391 Stop();
3392 DestroyStreams();
3393}
3394
skvlad7a43d252016-03-22 15:32:27 -07003395void EndToEndTest::VerifyNewVideoSendStreamsRespectNetworkState(
3396 MediaType network_to_bring_down,
3397 VideoEncoder* encoder,
3398 Transport* transport) {
solenberg4fbae2b2015-08-28 04:07:10 -07003399 CreateSenderCall(Call::Config());
skvlad7a43d252016-03-22 15:32:27 -07003400 sender_call_->SignalChannelNetworkState(network_to_bring_down, kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003401
skvlad7a43d252016-03-22 15:32:27 -07003402 CreateSendConfig(1, 0, transport);
3403 video_send_config_.encoder_settings.encoder = encoder;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003404 CreateVideoStreams();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003405 CreateFrameGeneratorCapturer();
3406
3407 Start();
3408 SleepMs(kSilenceTimeoutMs);
3409 Stop();
3410
3411 DestroyStreams();
3412}
3413
skvlad7a43d252016-03-22 15:32:27 -07003414void EndToEndTest::VerifyNewVideoReceiveStreamsRespectNetworkState(
3415 MediaType network_to_bring_down,
3416 Transport* transport) {
solenberg4fbae2b2015-08-28 04:07:10 -07003417 CreateCalls(Call::Config(), Call::Config());
skvlad7a43d252016-03-22 15:32:27 -07003418 receiver_call_->SignalChannelNetworkState(network_to_bring_down,
3419 kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003420
stefanf116bd02015-10-27 08:29:42 -07003421 test::DirectTransport sender_transport(sender_call_.get());
solenberg4fbae2b2015-08-28 04:07:10 -07003422 sender_transport.SetReceiver(receiver_call_->Receiver());
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003423 CreateSendConfig(1, 0, &sender_transport);
skvlad7a43d252016-03-22 15:32:27 -07003424 CreateMatchingReceiveConfigs(transport);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003425 CreateVideoStreams();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003426 CreateFrameGeneratorCapturer();
3427
3428 Start();
3429 SleepMs(kSilenceTimeoutMs);
3430 Stop();
3431
3432 sender_transport.StopSending();
3433
3434 DestroyStreams();
3435}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00003436
skvlad7a43d252016-03-22 15:32:27 -07003437TEST_F(EndToEndTest, NewVideoSendStreamsRespectVideoNetworkDown) {
3438 class UnusedEncoder : public test::FakeEncoder {
3439 public:
3440 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
3441 int32_t Encode(const VideoFrame& input_image,
3442 const CodecSpecificInfo* codec_specific_info,
3443 const std::vector<FrameType>* frame_types) override {
3444 ADD_FAILURE() << "Unexpected frame encode.";
3445 return test::FakeEncoder::Encode(input_image, codec_specific_info,
3446 frame_types);
3447 }
3448 };
3449
3450 UnusedEncoder unused_encoder;
3451 UnusedTransport unused_transport;
3452 VerifyNewVideoSendStreamsRespectNetworkState(
3453 MediaType::VIDEO, &unused_encoder, &unused_transport);
3454}
3455
3456TEST_F(EndToEndTest, NewVideoSendStreamsIgnoreAudioNetworkDown) {
3457 class RequiredEncoder : public test::FakeEncoder {
3458 public:
3459 RequiredEncoder()
3460 : FakeEncoder(Clock::GetRealTimeClock()), encoded_frame_(false) {}
3461 ~RequiredEncoder() {
3462 if (!encoded_frame_) {
3463 ADD_FAILURE() << "Didn't encode an expected frame";
3464 }
3465 }
3466 int32_t Encode(const VideoFrame& input_image,
3467 const CodecSpecificInfo* codec_specific_info,
3468 const std::vector<FrameType>* frame_types) override {
3469 encoded_frame_ = true;
3470 return test::FakeEncoder::Encode(input_image, codec_specific_info,
3471 frame_types);
3472 }
3473
3474 private:
3475 bool encoded_frame_;
3476 };
3477
3478 RequiredTransport required_transport(true /*rtp*/, false /*rtcp*/);
3479 RequiredEncoder required_encoder;
3480 VerifyNewVideoSendStreamsRespectNetworkState(
3481 MediaType::AUDIO, &required_encoder, &required_transport);
3482}
3483
3484TEST_F(EndToEndTest, NewVideoReceiveStreamsRespectVideoNetworkDown) {
3485 UnusedTransport transport;
3486 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::VIDEO, &transport);
3487}
3488
3489TEST_F(EndToEndTest, NewVideoReceiveStreamsIgnoreAudioNetworkDown) {
3490 RequiredTransport transport(false /*rtp*/, true /*rtcp*/);
3491 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::AUDIO, &transport);
3492}
3493
Peter Boströmd7da1202015-06-05 14:09:38 +02003494void VerifyEmptyNackConfig(const NackConfig& config) {
3495 EXPECT_EQ(0, config.rtp_history_ms)
3496 << "Enabling NACK requires rtcp-fb: nack negotiation.";
3497}
3498
3499void VerifyEmptyFecConfig(const FecConfig& config) {
3500 EXPECT_EQ(-1, config.ulpfec_payload_type)
3501 << "Enabling FEC requires rtpmap: ulpfec negotiation.";
3502 EXPECT_EQ(-1, config.red_payload_type)
3503 << "Enabling FEC requires rtpmap: red negotiation.";
3504 EXPECT_EQ(-1, config.red_rtx_payload_type)
3505 << "Enabling RTX in FEC requires rtpmap: rtx negotiation.";
3506}
3507
3508TEST_F(EndToEndTest, VerifyDefaultSendConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003509 VideoSendStream::Config default_send_config(nullptr);
Peter Boströmd7da1202015-06-05 14:09:38 +02003510 EXPECT_EQ(0, default_send_config.rtp.nack.rtp_history_ms)
3511 << "Enabling NACK require rtcp-fb: nack negotiation.";
3512 EXPECT_TRUE(default_send_config.rtp.rtx.ssrcs.empty())
3513 << "Enabling RTX requires rtpmap: rtx negotiation.";
3514 EXPECT_TRUE(default_send_config.rtp.extensions.empty())
3515 << "Enabling RTP extensions require negotiation.";
3516
3517 VerifyEmptyNackConfig(default_send_config.rtp.nack);
3518 VerifyEmptyFecConfig(default_send_config.rtp.fec);
3519}
3520
3521TEST_F(EndToEndTest, VerifyDefaultReceiveConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003522 VideoReceiveStream::Config default_receive_config(nullptr);
pbosda903ea2015-10-02 02:36:56 -07003523 EXPECT_EQ(RtcpMode::kCompound, default_receive_config.rtp.rtcp_mode)
Peter Boströmd7da1202015-06-05 14:09:38 +02003524 << "Reduced-size RTCP require rtcp-rsize to be negotiated.";
3525 EXPECT_FALSE(default_receive_config.rtp.remb)
3526 << "REMB require rtcp-fb: goog-remb to be negotiated.";
3527 EXPECT_FALSE(
3528 default_receive_config.rtp.rtcp_xr.receiver_reference_time_report)
3529 << "RTCP XR settings require rtcp-xr to be negotiated.";
3530 EXPECT_TRUE(default_receive_config.rtp.rtx.empty())
3531 << "Enabling RTX requires rtpmap: rtx negotiation.";
3532 EXPECT_TRUE(default_receive_config.rtp.extensions.empty())
3533 << "Enabling RTP extensions require negotiation.";
3534
3535 VerifyEmptyNackConfig(default_receive_config.rtp.nack);
3536 VerifyEmptyFecConfig(default_receive_config.rtp.fec);
3537}
3538
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003539TEST_F(EndToEndTest, TransportSeqNumOnAudioAndVideo) {
3540 static const int kExtensionId = 8;
3541 class TransportSequenceNumberTest : public test::EndToEndTest {
3542 public:
3543 TransportSequenceNumberTest()
3544 : EndToEndTest(kDefaultTimeoutMs),
3545 video_observed_(false),
3546 audio_observed_(false) {
3547 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
3548 kExtensionId);
3549 }
3550
3551 size_t GetNumVideoStreams() const override { return 1; }
3552 size_t GetNumAudioStreams() const override { return 1; }
3553
3554 void ModifyVideoConfigs(
3555 VideoSendStream::Config* send_config,
3556 std::vector<VideoReceiveStream::Config>* receive_configs,
3557 VideoEncoderConfig* encoder_config) override {
3558 send_config->rtp.extensions.clear();
3559 send_config->rtp.extensions.push_back(
3560 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
3561 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3562 }
3563
3564 void ModifyAudioConfigs(
3565 AudioSendStream::Config* send_config,
3566 std::vector<AudioReceiveStream::Config>* receive_configs) override {
3567 send_config->rtp.extensions.clear();
3568 send_config->rtp.extensions.push_back(
3569 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
3570 (*receive_configs)[0].rtp.extensions.clear();
3571 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3572 }
3573
3574 Action OnSendRtp(const uint8_t* packet, size_t length) override {
3575 RTPHeader header;
3576 EXPECT_TRUE(parser_->Parse(packet, length, &header));
3577 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
3578 // Unwrap packet id and verify uniqueness.
3579 int64_t packet_id =
3580 unwrapper_.Unwrap(header.extension.transportSequenceNumber);
3581 EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
3582
3583 if (header.ssrc == kVideoSendSsrcs[0])
3584 video_observed_ = true;
3585 if (header.ssrc == kAudioSendSsrc)
3586 audio_observed_ = true;
3587 if (audio_observed_ && video_observed_ &&
3588 received_packet_ids_.size() == 50) {
3589 size_t packet_id_range =
3590 *received_packet_ids_.rbegin() - *received_packet_ids_.begin() + 1;
3591 EXPECT_EQ(received_packet_ids_.size(), packet_id_range);
3592 observation_complete_.Set();
3593 }
3594 return SEND_PACKET;
3595 }
3596
3597 void PerformTest() override {
3598 EXPECT_TRUE(Wait()) << "Timed out while waiting for audio and video "
3599 "packets with transport sequence number.";
3600 }
3601
3602 private:
3603 bool video_observed_;
3604 bool audio_observed_;
3605 SequenceNumberUnwrapper unwrapper_;
3606 std::set<int64_t> received_packet_ids_;
3607 } test;
3608
stefane74eef12016-01-08 06:47:13 -08003609 RunBaseTest(&test);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003610}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003611} // namespace webrtc