blob: 528338defe0adee2c5242abad5f09e1c6a59ef0c [file] [log] [blame]
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001/*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000010#include <algorithm>
danilchap5c35cf92016-02-03 14:14:49 -080011#include <list>
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000012#include <map>
kwiberg27f982b2016-03-01 11:52:33 -080013#include <memory>
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000014#include <sstream>
15#include <string>
kwiberg4a206a92016-03-31 10:24:26 -070016#include <vector>
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000017
18#include "testing/gtest/include/gtest/gtest.h"
19
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000020#include "webrtc/base/checks.h"
Erik Språng6b8d3552015-09-24 15:06:57 +020021#include "webrtc/base/event.h"
Erik Språng737336d2016-07-29 12:59:36 +020022#include "webrtc/base/optional.h"
23#include "webrtc/base/rate_limiter.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000024#include "webrtc/call.h"
Peter Boström5c389d32015-09-25 13:58:30 +020025#include "webrtc/call/transport_adapter.h"
pbosa96b60b2016-04-18 21:12:48 -070026#include "webrtc/common_video/include/frame_callback.h"
danilchap5c35cf92016-02-03 14:14:49 -080027#include "webrtc/modules/include/module_common_types.h"
stefan32f81542016-01-20 07:13:58 -080028#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
sprang861c55e2015-10-16 10:01:21 -070029#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
Erik Språng737336d2016-07-29 12:59:36 +020030#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h"
Danil Chapovalov70ffead2016-07-20 15:26:59 +020031#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000032#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
sprangcd349d92016-07-13 09:11:28 -070033#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
hbosbab934b2016-01-27 01:36:03 -080034#include "webrtc/modules/video_coding/codecs/h264/include/h264.h"
marpan@webrtc.org5b883172014-11-01 06:10:48 +000035#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
36#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010037#include "webrtc/modules/video_coding/include/video_coding_defines.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010038#include "webrtc/system_wrappers/include/metrics.h"
asapersson01d70a32016-05-20 06:29:46 -070039#include "webrtc/system_wrappers/include/metrics_default.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010040#include "webrtc/system_wrappers/include/sleep.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000041#include "webrtc/test/call_test.h"
42#include "webrtc/test/direct_transport.h"
43#include "webrtc/test/encoder_settings.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000044#include "webrtc/test/fake_decoder.h"
45#include "webrtc/test/fake_encoder.h"
46#include "webrtc/test/frame_generator.h"
47#include "webrtc/test/frame_generator_capturer.h"
48#include "webrtc/test/null_transport.h"
asapersson@webrtc.org37c05592015-01-28 13:58:27 +000049#include "webrtc/test/rtcp_packet_parser.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000050#include "webrtc/test/rtp_rtcp_observer.h"
51#include "webrtc/test/testsupport/fileutils.h"
52#include "webrtc/test/testsupport/perf_test.h"
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +000053#include "webrtc/video_encoder.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000054
55namespace webrtc {
56
Peter Boström5811a392015-12-10 13:02:50 +010057static const int kSilenceTimeoutMs = 2000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000058
59class EndToEndTest : public test::CallTest {
60 public:
61 EndToEndTest() {}
62
63 virtual ~EndToEndTest() {
stefanff483612015-12-21 03:14:00 -080064 EXPECT_EQ(nullptr, video_send_stream_);
65 EXPECT_TRUE(video_receive_streams_.empty());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000066 }
67
68 protected:
pbos2d566682015-09-28 09:59:31 -070069 class UnusedTransport : public Transport {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000070 private:
stefan1d8a5062015-10-02 03:39:33 -070071 bool SendRtp(const uint8_t* packet,
72 size_t length,
73 const PacketOptions& options) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000074 ADD_FAILURE() << "Unexpected RTP sent.";
75 return false;
76 }
77
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000078 bool SendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000079 ADD_FAILURE() << "Unexpected RTCP sent.";
80 return false;
81 }
82 };
83
skvlad7a43d252016-03-22 15:32:27 -070084 class RequiredTransport : public Transport {
85 public:
86 RequiredTransport(bool rtp_required, bool rtcp_required)
87 : need_rtp_(rtp_required), need_rtcp_(rtcp_required) {}
88 ~RequiredTransport() {
89 if (need_rtp_) {
90 ADD_FAILURE() << "Expected RTP packet not sent.";
91 }
92 if (need_rtcp_) {
93 ADD_FAILURE() << "Expected RTCP packet not sent.";
94 }
95 }
96
97 private:
98 bool SendRtp(const uint8_t* packet,
99 size_t length,
100 const PacketOptions& options) override {
101 need_rtp_ = false;
102 return true;
103 }
104
105 bool SendRtcp(const uint8_t* packet, size_t length) override {
106 need_rtcp_ = false;
107 return true;
108 }
109 bool need_rtp_;
110 bool need_rtcp_;
111 };
112
Peter Boström39593972016-02-15 11:27:15 +0100113 void DecodesRetransmittedFrame(bool enable_rtx, bool enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000114 void ReceivesPliAndRecovers(int rtp_history_ms);
pbosda903ea2015-10-02 02:36:56 -0700115 void RespectsRtcpMode(RtcpMode rtcp_mode);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000116 void TestXrReceiverReferenceTimeReport(bool enable_rrtr);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000117 void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200118 void TestRtpStatePreservation(bool use_rtx, bool provoke_rtcpsr_before_rtp);
sprangb4a1ae52015-12-03 08:10:08 -0800119 void VerifyHistogramStats(bool use_rtx, bool use_red, bool screenshare);
skvlad7a43d252016-03-22 15:32:27 -0700120 void VerifyNewVideoSendStreamsRespectNetworkState(
121 MediaType network_to_bring_down,
122 VideoEncoder* encoder,
123 Transport* transport);
124 void VerifyNewVideoReceiveStreamsRespectNetworkState(
125 MediaType network_to_bring_down,
126 Transport* transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000127};
128
129TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
solenberg4fbae2b2015-08-28 04:07:10 -0700130 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000131
solenberg4fbae2b2015-08-28 04:07:10 -0700132 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100133 CreateSendConfig(1, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700134 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000135
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100136 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000137
stefanff483612015-12-21 03:14:00 -0800138 video_receive_streams_[0]->Start();
139 video_receive_streams_[0]->Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000140
141 DestroyStreams();
142}
143
144TEST_F(EndToEndTest, ReceiverCanBeStoppedTwice) {
solenberg4fbae2b2015-08-28 04:07:10 -0700145 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000146
solenberg4fbae2b2015-08-28 04:07:10 -0700147 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100148 CreateSendConfig(1, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700149 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000150
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100151 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000152
stefanff483612015-12-21 03:14:00 -0800153 video_receive_streams_[0]->Stop();
154 video_receive_streams_[0]->Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000155
156 DestroyStreams();
157}
158
159TEST_F(EndToEndTest, RendersSingleDelayedFrame) {
160 static const int kWidth = 320;
161 static const int kHeight = 240;
162 // This constant is chosen to be higher than the timeout in the video_render
163 // module. This makes sure that frames aren't dropped if there are no other
164 // frames in the queue.
165 static const int kDelayRenderCallbackMs = 1000;
166
nisse7ade7b32016-03-23 04:48:10 -0700167 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000168 public:
Peter Boström5811a392015-12-10 13:02:50 +0100169 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000170
nisseeb83a1a2016-03-21 01:27:56 -0700171 void OnFrame(const VideoFrame& video_frame) override { event_.Set(); }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000172
Peter Boström5811a392015-12-10 13:02:50 +0100173 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000174
Peter Boström5811a392015-12-10 13:02:50 +0100175 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000176 } renderer;
177
178 class TestFrameCallback : public I420FrameCallback {
179 public:
Peter Boström5811a392015-12-10 13:02:50 +0100180 TestFrameCallback() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000181
Peter Boström5811a392015-12-10 13:02:50 +0100182 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000183
184 private:
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700185 void FrameCallback(VideoFrame* frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000186 SleepMs(kDelayRenderCallbackMs);
Peter Boström5811a392015-12-10 13:02:50 +0100187 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000188 }
189
Peter Boström5811a392015-12-10 13:02:50 +0100190 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000191 };
192
solenberg4fbae2b2015-08-28 04:07:10 -0700193 CreateCalls(Call::Config(), Call::Config());
194
stefanf116bd02015-10-27 08:29:42 -0700195 test::DirectTransport sender_transport(sender_call_.get());
196 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000197 sender_transport.SetReceiver(receiver_call_->Receiver());
198 receiver_transport.SetReceiver(sender_call_->Receiver());
199
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100200 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700201 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000202
203 TestFrameCallback pre_render_callback;
stefanff483612015-12-21 03:14:00 -0800204 video_receive_configs_[0].pre_render_callback = &pre_render_callback;
205 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000206
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100207 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000208 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000209
210 // Create frames that are smaller than the send width/height, this is done to
211 // check that the callbacks are done after processing video.
kwiberg27f982b2016-03-01 11:52:33 -0800212 std::unique_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000213 test::FrameGenerator::CreateChromaGenerator(kWidth, kHeight));
stefanff483612015-12-21 03:14:00 -0800214 video_send_stream_->Input()->IncomingCapturedFrame(
215 *frame_generator->NextFrame());
Peter Boström5811a392015-12-10 13:02:50 +0100216 EXPECT_TRUE(pre_render_callback.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000217 << "Timed out while waiting for pre-render callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100218 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000219 << "Timed out while waiting for the frame to render.";
220
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000221 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000222
223 sender_transport.StopSending();
224 receiver_transport.StopSending();
225
226 DestroyStreams();
227}
228
229TEST_F(EndToEndTest, TransmitsFirstFrame) {
nisse7ade7b32016-03-23 04:48:10 -0700230 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000231 public:
Peter Boström5811a392015-12-10 13:02:50 +0100232 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000233
nisseeb83a1a2016-03-21 01:27:56 -0700234 void OnFrame(const VideoFrame& video_frame) override { event_.Set(); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000235
Peter Boström5811a392015-12-10 13:02:50 +0100236 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000237
Peter Boström5811a392015-12-10 13:02:50 +0100238 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000239 } renderer;
240
solenberg4fbae2b2015-08-28 04:07:10 -0700241 CreateCalls(Call::Config(), Call::Config());
242
stefanf116bd02015-10-27 08:29:42 -0700243 test::DirectTransport sender_transport(sender_call_.get());
244 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000245 sender_transport.SetReceiver(receiver_call_->Receiver());
246 receiver_transport.SetReceiver(sender_call_->Receiver());
247
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100248 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700249 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -0800250 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000251
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100252 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000253 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000254
kwiberg27f982b2016-03-01 11:52:33 -0800255 std::unique_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000256 test::FrameGenerator::CreateChromaGenerator(
stefanff483612015-12-21 03:14:00 -0800257 video_encoder_config_.streams[0].width,
258 video_encoder_config_.streams[0].height));
259 video_send_stream_->Input()->IncomingCapturedFrame(
260 *frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000261
Peter Boström5811a392015-12-10 13:02:50 +0100262 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000263 << "Timed out while waiting for the frame to render.";
264
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000265 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000266
267 sender_transport.StopSending();
268 receiver_transport.StopSending();
269
270 DestroyStreams();
271}
272
Perba7dc722016-04-19 15:01:23 +0200273class CodecObserver : public test::EndToEndTest,
nisse7ade7b32016-03-23 04:48:10 -0700274 public rtc::VideoSinkInterface<VideoFrame> {
Perba7dc722016-04-19 15:01:23 +0200275 public:
276 CodecObserver(int no_frames_to_wait_for,
277 VideoRotation rotation_to_test,
278 const std::string& payload_name,
279 webrtc::VideoEncoder* encoder,
280 webrtc::VideoDecoder* decoder)
281 : EndToEndTest(2 * webrtc::EndToEndTest::kDefaultTimeoutMs),
282 no_frames_to_wait_for_(no_frames_to_wait_for),
283 expected_rotation_(rotation_to_test),
284 payload_name_(payload_name),
285 encoder_(encoder),
286 decoder_(decoder),
287 frame_counter_(0) {}
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000288
Perba7dc722016-04-19 15:01:23 +0200289 void PerformTest() override {
290 EXPECT_TRUE(Wait())
291 << "Timed out while waiting for enough frames to be decoded.";
292 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000293
Perba7dc722016-04-19 15:01:23 +0200294 void ModifyVideoConfigs(
295 VideoSendStream::Config* send_config,
296 std::vector<VideoReceiveStream::Config>* receive_configs,
297 VideoEncoderConfig* encoder_config) override {
298 send_config->encoder_settings.encoder = encoder_.get();
299 send_config->encoder_settings.payload_name = payload_name_;
300 send_config->encoder_settings.payload_type = 126;
301 encoder_config->streams[0].min_bitrate_bps = 50000;
302 encoder_config->streams[0].target_bitrate_bps =
303 encoder_config->streams[0].max_bitrate_bps = 2000000;
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000304
Perba7dc722016-04-19 15:01:23 +0200305 (*receive_configs)[0].renderer = this;
306 (*receive_configs)[0].decoders.resize(1);
307 (*receive_configs)[0].decoders[0].payload_type =
308 send_config->encoder_settings.payload_type;
309 (*receive_configs)[0].decoders[0].payload_name =
310 send_config->encoder_settings.payload_name;
311 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
312 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000313
Perba7dc722016-04-19 15:01:23 +0200314 void OnFrame(const VideoFrame& video_frame) override {
315 EXPECT_EQ(expected_rotation_, video_frame.rotation());
316 if (++frame_counter_ == no_frames_to_wait_for_)
317 observation_complete_.Set();
318 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000319
Perba7dc722016-04-19 15:01:23 +0200320 void OnFrameGeneratorCapturerCreated(
321 test::FrameGeneratorCapturer* frame_generator_capturer) override {
322 frame_generator_capturer->SetFakeRotation(expected_rotation_);
323 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000324
Perba7dc722016-04-19 15:01:23 +0200325 private:
326 int no_frames_to_wait_for_;
327 VideoRotation expected_rotation_;
328 std::string payload_name_;
329 std::unique_ptr<webrtc::VideoEncoder> encoder_;
330 std::unique_ptr<webrtc::VideoDecoder> decoder_;
331 int frame_counter_;
332};
333
334TEST_F(EndToEndTest, SendsAndReceivesVP8Rotation90) {
335 CodecObserver test(5, kVideoRotation_90, "VP8",
336 VideoEncoder::Create(VideoEncoder::kVp8),
337 VP8Decoder::Create());
338 RunBaseTest(&test);
339}
340
Peter Boström12996152016-05-14 02:03:18 +0200341#if !defined(RTC_DISABLE_VP9)
Perba7dc722016-04-19 15:01:23 +0200342TEST_F(EndToEndTest, SendsAndReceivesVP9) {
343 CodecObserver test(500, kVideoRotation_0, "VP9",
344 VideoEncoder::Create(VideoEncoder::kVp9),
345 VP9Decoder::Create());
346 RunBaseTest(&test);
347}
348
349TEST_F(EndToEndTest, SendsAndReceivesVP9VideoRotation90) {
350 CodecObserver test(5, kVideoRotation_90, "VP9",
351 VideoEncoder::Create(VideoEncoder::kVp9),
352 VP9Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800353 RunBaseTest(&test);
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000354}
Peter Boström12996152016-05-14 02:03:18 +0200355#endif // !defined(RTC_DISABLE_VP9)
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000356
hbosbab934b2016-01-27 01:36:03 -0800357#if defined(WEBRTC_END_TO_END_H264_TESTS)
358
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000359TEST_F(EndToEndTest, SendsAndReceivesH264) {
Perba7dc722016-04-19 15:01:23 +0200360 CodecObserver test(500, kVideoRotation_0, "H264",
361 VideoEncoder::Create(VideoEncoder::kH264),
362 H264Decoder::Create());
363 RunBaseTest(&test);
364}
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000365
Perba7dc722016-04-19 15:01:23 +0200366TEST_F(EndToEndTest, SendsAndReceivesH264VideoRotation90) {
367 CodecObserver test(5, kVideoRotation_90, "H264",
368 VideoEncoder::Create(VideoEncoder::kH264),
369 H264Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800370 RunBaseTest(&test);
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000371}
372
hbosbab934b2016-01-27 01:36:03 -0800373#endif // defined(WEBRTC_END_TO_END_H264_TESTS)
374
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000375TEST_F(EndToEndTest, ReceiverUsesLocalSsrc) {
376 class SyncRtcpObserver : public test::EndToEndTest {
377 public:
378 SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {}
379
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000380 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000381 RTCPUtility::RTCPParserV2 parser(packet, length, true);
382 EXPECT_TRUE(parser.IsValid());
383 uint32_t ssrc = 0;
384 ssrc |= static_cast<uint32_t>(packet[4]) << 24;
385 ssrc |= static_cast<uint32_t>(packet[5]) << 16;
386 ssrc |= static_cast<uint32_t>(packet[6]) << 8;
387 ssrc |= static_cast<uint32_t>(packet[7]) << 0;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100388 EXPECT_EQ(kReceiverLocalVideoSsrc, ssrc);
Peter Boström5811a392015-12-10 13:02:50 +0100389 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000390
391 return SEND_PACKET;
392 }
393
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000394 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100395 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000396 << "Timed out while waiting for a receiver RTCP packet to be sent.";
397 }
398 } test;
399
stefane74eef12016-01-08 06:47:13 -0800400 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000401}
402
403TEST_F(EndToEndTest, ReceivesAndRetransmitsNack) {
404 static const int kNumberOfNacksToObserve = 2;
405 static const int kLossBurstSize = 2;
406 static const int kPacketsBetweenLossBursts = 9;
407 class NackObserver : public test::EndToEndTest {
408 public:
409 NackObserver()
410 : EndToEndTest(kLongTimeoutMs),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000411 sent_rtp_packets_(0),
412 packets_left_to_drop_(0),
413 nacks_left_(kNumberOfNacksToObserve) {}
414
415 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000416 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700417 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000418 RTPHeader header;
Peter Boström03671cb2015-12-07 15:22:24 +0100419 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000420
421 // Never drop retransmitted packets.
422 if (dropped_packets_.find(header.sequenceNumber) !=
423 dropped_packets_.end()) {
424 retransmitted_packets_.insert(header.sequenceNumber);
Stefan Holmer586b19b2015-09-18 11:14:31 +0200425 if (nacks_left_ <= 0 &&
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000426 retransmitted_packets_.size() == dropped_packets_.size()) {
Peter Boström5811a392015-12-10 13:02:50 +0100427 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000428 }
429 return SEND_PACKET;
430 }
431
432 ++sent_rtp_packets_;
433
434 // Enough NACKs received, stop dropping packets.
Stefan Holmer586b19b2015-09-18 11:14:31 +0200435 if (nacks_left_ <= 0)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000436 return SEND_PACKET;
437
438 // Check if it's time for a new loss burst.
439 if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
440 packets_left_to_drop_ = kLossBurstSize;
441
Stefan Holmer01b48882015-05-05 10:21:24 +0200442 // Never drop padding packets as those won't be retransmitted.
443 if (packets_left_to_drop_ > 0 && header.paddingLength == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000444 --packets_left_to_drop_;
445 dropped_packets_.insert(header.sequenceNumber);
446 return DROP_PACKET;
447 }
448
449 return SEND_PACKET;
450 }
451
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000452 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700453 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000454 RTCPUtility::RTCPParserV2 parser(packet, length, true);
455 EXPECT_TRUE(parser.IsValid());
456
457 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +0200458 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
459 if (packet_type == RTCPUtility::RTCPPacketTypes::kRtpfbNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000460 --nacks_left_;
461 break;
462 }
463 packet_type = parser.Iterate();
464 }
465 return SEND_PACKET;
466 }
467
stefanff483612015-12-21 03:14:00 -0800468 void ModifyVideoConfigs(
469 VideoSendStream::Config* send_config,
470 std::vector<VideoReceiveStream::Config>* receive_configs,
471 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000472 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000473 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000474 }
475
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000476 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100477 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000478 << "Timed out waiting for packets to be NACKed, retransmitted and "
479 "rendered.";
480 }
481
stefanf116bd02015-10-27 08:29:42 -0700482 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000483 std::set<uint16_t> dropped_packets_;
484 std::set<uint16_t> retransmitted_packets_;
485 uint64_t sent_rtp_packets_;
486 int packets_left_to_drop_;
stefanf116bd02015-10-27 08:29:42 -0700487 int nacks_left_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000488 } test;
489
stefane74eef12016-01-08 06:47:13 -0800490 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000491}
492
Erik Språng737336d2016-07-29 12:59:36 +0200493TEST_F(EndToEndTest, ReceivesNackAndRetransmitsAudio) {
494 class NackObserver : public test::EndToEndTest {
495 public:
496 NackObserver()
497 : EndToEndTest(kLongTimeoutMs),
498 local_ssrc_(0),
499 remote_ssrc_(0),
500 receive_transport_(nullptr) {}
501
502 private:
503 size_t GetNumVideoStreams() const override { return 0; }
504 size_t GetNumAudioStreams() const override { return 1; }
505
506 test::PacketTransport* CreateReceiveTransport() override {
507 test::PacketTransport* receive_transport = new test::PacketTransport(
508 nullptr, this, test::PacketTransport::kReceiver,
509 FakeNetworkPipe::Config());
510 receive_transport_ = receive_transport;
511 return receive_transport;
512 }
513
514 Action OnSendRtp(const uint8_t* packet, size_t length) override {
515 RTPHeader header;
516 EXPECT_TRUE(parser_->Parse(packet, length, &header));
517
518 if (!sequence_number_to_retransmit_) {
519 sequence_number_to_retransmit_ =
520 rtc::Optional<uint16_t>(header.sequenceNumber);
521
522 // Don't ask for retransmission straight away, may be deduped in pacer.
523 } else if (header.sequenceNumber == *sequence_number_to_retransmit_) {
524 observation_complete_.Set();
525 } else {
526 // Send a NACK as often as necessary until retransmission is received.
527 rtcp::Nack nack;
528 nack.From(local_ssrc_);
529 nack.To(remote_ssrc_);
530 uint16_t nack_list[] = {*sequence_number_to_retransmit_};
531 nack.WithList(nack_list, 1);
532 rtc::Buffer buffer = nack.Build();
533
534 EXPECT_TRUE(receive_transport_->SendRtcp(buffer.data(), buffer.size()));
535 }
536
537 return SEND_PACKET;
538 }
539
540 void ModifyAudioConfigs(
541 AudioSendStream::Config* send_config,
542 std::vector<AudioReceiveStream::Config>* receive_configs) override {
543 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
544 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
545 local_ssrc_ = (*receive_configs)[0].rtp.local_ssrc;
546 remote_ssrc_ = (*receive_configs)[0].rtp.remote_ssrc;
547 }
548
549 void PerformTest() override {
550 EXPECT_TRUE(Wait())
551 << "Timed out waiting for packets to be NACKed, retransmitted and "
552 "rendered.";
553 }
554
555 uint32_t local_ssrc_;
556 uint32_t remote_ssrc_;
557 Transport* receive_transport_;
558 rtc::Optional<uint16_t> sequence_number_to_retransmit_;
559 } test;
560
561 RunBaseTest(&test);
562}
563
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000564TEST_F(EndToEndTest, CanReceiveFec) {
nisse7ade7b32016-03-23 04:48:10 -0700565 class FecRenderObserver : public test::EndToEndTest,
566 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000567 public:
568 FecRenderObserver()
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000569 : EndToEndTest(kDefaultTimeoutMs), state_(kFirstPacket) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000570
571 private:
stefanf116bd02015-10-27 08:29:42 -0700572 Action OnSendRtp(const uint8_t* packet, size_t length) override {
573 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000574 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000575 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000576
Stefan Holmer01b48882015-05-05 10:21:24 +0200577 int encapsulated_payload_type = -1;
578 if (header.payloadType == kRedPayloadType) {
579 encapsulated_payload_type =
580 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100581 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200582 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
583 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100584 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200585 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000586
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000587 if (protected_sequence_numbers_.count(header.sequenceNumber) != 0) {
588 // Retransmitted packet, should not count.
589 protected_sequence_numbers_.erase(header.sequenceNumber);
590 EXPECT_GT(protected_timestamps_.count(header.timestamp), 0u);
591 protected_timestamps_.erase(header.timestamp);
592 return SEND_PACKET;
593 }
594
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000595 switch (state_) {
596 case kFirstPacket:
597 state_ = kDropEveryOtherPacketUntilFec;
598 break;
599 case kDropEveryOtherPacketUntilFec:
600 if (encapsulated_payload_type == kUlpfecPayloadType) {
601 state_ = kDropNextMediaPacket;
602 return SEND_PACKET;
603 }
604 if (header.sequenceNumber % 2 == 0)
605 return DROP_PACKET;
606 break;
607 case kDropNextMediaPacket:
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100608 if (encapsulated_payload_type == kFakeVideoSendPayloadType) {
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000609 protected_sequence_numbers_.insert(header.sequenceNumber);
610 protected_timestamps_.insert(header.timestamp);
611 state_ = kDropEveryOtherPacketUntilFec;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000612 return DROP_PACKET;
613 }
614 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000615 }
616
617 return SEND_PACKET;
618 }
619
nisseeb83a1a2016-03-21 01:27:56 -0700620 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200621 rtc::CritScope lock(&crit_);
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000622 // Rendering frame with timestamp of packet that was dropped -> FEC
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000623 // protection worked.
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000624 if (protected_timestamps_.count(video_frame.timestamp()) != 0)
Peter Boström5811a392015-12-10 13:02:50 +0100625 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000626 }
627
628 enum {
629 kFirstPacket,
630 kDropEveryOtherPacketUntilFec,
631 kDropNextMediaPacket,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000632 } state_;
633
stefanff483612015-12-21 03:14:00 -0800634 void ModifyVideoConfigs(
635 VideoSendStream::Config* send_config,
636 std::vector<VideoReceiveStream::Config>* receive_configs,
637 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000638 // TODO(pbos): Run this test with combined NACK/FEC enabled as well.
639 // int rtp_history_ms = 1000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000640 // (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000641 // send_config->rtp.nack.rtp_history_ms = rtp_history_ms;
642 send_config->rtp.fec.red_payload_type = kRedPayloadType;
643 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
644
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000645 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
646 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
647 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000648 }
649
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000650 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100651 EXPECT_TRUE(Wait())
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000652 << "Timed out waiting for dropped frames frames to be rendered.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000653 }
654
stefanf116bd02015-10-27 08:29:42 -0700655 rtc::CriticalSection crit_;
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000656 std::set<uint32_t> protected_sequence_numbers_ GUARDED_BY(crit_);
657 std::set<uint32_t> protected_timestamps_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000658 } test;
659
stefane74eef12016-01-08 06:47:13 -0800660 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000661}
662
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200663TEST_F(EndToEndTest, ReceivedFecPacketsNotNacked) {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000664 class FecNackObserver : public test::EndToEndTest {
665 public:
mflodmand1590b22015-12-09 07:07:59 -0800666 FecNackObserver()
stefanf116bd02015-10-27 08:29:42 -0700667 : EndToEndTest(kDefaultTimeoutMs),
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000668 state_(kFirstPacket),
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000669 fec_sequence_number_(0),
670 has_last_sequence_number_(false),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200671 last_sequence_number_(0),
672 encoder_(VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)),
673 decoder_(VP8Decoder::Create()) {}
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000674
675 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000676 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800677 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000678 RTPHeader header;
679 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000680
Stefan Holmer01b48882015-05-05 10:21:24 +0200681 int encapsulated_payload_type = -1;
682 if (header.payloadType == kRedPayloadType) {
683 encapsulated_payload_type =
684 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100685 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200686 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
687 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100688 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200689 }
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000690
691 if (has_last_sequence_number_ &&
692 !IsNewerSequenceNumber(header.sequenceNumber,
693 last_sequence_number_)) {
694 // Drop retransmitted packets.
695 return DROP_PACKET;
696 }
697 last_sequence_number_ = header.sequenceNumber;
698 has_last_sequence_number_ = true;
699
700 bool fec_packet = encapsulated_payload_type == kUlpfecPayloadType;
701 switch (state_) {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000702 case kFirstPacket:
703 state_ = kDropEveryOtherPacketUntilFec;
704 break;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000705 case kDropEveryOtherPacketUntilFec:
706 if (fec_packet) {
707 state_ = kDropAllMediaPacketsUntilFec;
708 } else if (header.sequenceNumber % 2 == 0) {
709 return DROP_PACKET;
710 }
711 break;
712 case kDropAllMediaPacketsUntilFec:
713 if (!fec_packet)
714 return DROP_PACKET;
715 fec_sequence_number_ = header.sequenceNumber;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200716 state_ = kDropOneMediaPacket;
717 break;
718 case kDropOneMediaPacket:
719 if (fec_packet)
720 return DROP_PACKET;
721 state_ = kPassOneMediaPacket;
722 return DROP_PACKET;
723 break;
724 case kPassOneMediaPacket:
725 if (fec_packet)
726 return DROP_PACKET;
727 // Pass one media packet after dropped packet after last FEC,
728 // otherwise receiver might never see a seq_no after
729 // |fec_sequence_number_|
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000730 state_ = kVerifyFecPacketNotInNackList;
731 break;
732 case kVerifyFecPacketNotInNackList:
733 // Continue to drop packets. Make sure no frame can be decoded.
734 if (fec_packet || header.sequenceNumber % 2 == 0)
735 return DROP_PACKET;
736 break;
737 }
738 return SEND_PACKET;
739 }
740
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000741 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800742 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000743 if (state_ == kVerifyFecPacketNotInNackList) {
744 test::RtcpPacketParser rtcp_parser;
745 rtcp_parser.Parse(packet, length);
746 std::vector<uint16_t> nacks = rtcp_parser.nack_item()->last_nack_list();
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200747 EXPECT_TRUE(std::find(nacks.begin(), nacks.end(),
748 fec_sequence_number_) == nacks.end())
749 << "Got nack for FEC packet";
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000750 if (!nacks.empty() &&
751 IsNewerSequenceNumber(nacks.back(), fec_sequence_number_)) {
Peter Boström5811a392015-12-10 13:02:50 +0100752 observation_complete_.Set();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000753 }
754 }
755 return SEND_PACKET;
756 }
757
stefane74eef12016-01-08 06:47:13 -0800758 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
759 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
760 // Configure some network delay.
761 const int kNetworkDelayMs = 50;
762 FakeNetworkPipe::Config config;
763 config.queue_delay_ms = kNetworkDelayMs;
764 return new test::PacketTransport(sender_call, this,
765 test::PacketTransport::kSender, config);
766 }
767
Stefan Holmere5904162015-03-26 11:11:06 +0100768 // TODO(holmer): Investigate why we don't send FEC packets when the bitrate
769 // is 10 kbps.
770 Call::Config GetSenderCallConfig() override {
solenberg4fbae2b2015-08-28 04:07:10 -0700771 Call::Config config;
Stefan Holmere5904162015-03-26 11:11:06 +0100772 const int kMinBitrateBps = 30000;
773 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
774 return config;
775 }
776
stefanff483612015-12-21 03:14:00 -0800777 void ModifyVideoConfigs(
778 VideoSendStream::Config* send_config,
779 std::vector<VideoReceiveStream::Config>* receive_configs,
780 VideoEncoderConfig* encoder_config) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000781 // Configure hybrid NACK/FEC.
782 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
783 send_config->rtp.fec.red_payload_type = kRedPayloadType;
784 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200785 // Set codec to VP8, otherwise NACK/FEC hybrid will be disabled.
786 send_config->encoder_settings.encoder = encoder_.get();
787 send_config->encoder_settings.payload_name = "VP8";
788 send_config->encoder_settings.payload_type = kFakeVideoSendPayloadType;
789 encoder_config->streams[0].min_bitrate_bps = 50000;
790 encoder_config->streams[0].max_bitrate_bps =
791 encoder_config->streams[0].target_bitrate_bps = 2000000;
792
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000793 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
794 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
795 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200796
797 (*receive_configs)[0].decoders.resize(1);
798 (*receive_configs)[0].decoders[0].payload_type =
799 send_config->encoder_settings.payload_type;
800 (*receive_configs)[0].decoders[0].payload_name =
801 send_config->encoder_settings.payload_name;
802 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000803 }
804
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000805 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100806 EXPECT_TRUE(Wait())
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000807 << "Timed out while waiting for FEC packets to be received.";
808 }
809
810 enum {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000811 kFirstPacket,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000812 kDropEveryOtherPacketUntilFec,
813 kDropAllMediaPacketsUntilFec,
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200814 kDropOneMediaPacket,
815 kPassOneMediaPacket,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000816 kVerifyFecPacketNotInNackList,
817 } state_;
818
stefan608213e2015-11-01 14:56:10 -0800819 rtc::CriticalSection crit_;
820 uint16_t fec_sequence_number_ GUARDED_BY(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000821 bool has_last_sequence_number_;
822 uint16_t last_sequence_number_;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200823 std::unique_ptr<webrtc::VideoEncoder> encoder_;
824 std::unique_ptr<webrtc::VideoDecoder> decoder_;
stefanf116bd02015-10-27 08:29:42 -0700825 } test;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000826
stefane74eef12016-01-08 06:47:13 -0800827 RunBaseTest(&test);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000828}
829
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000830// This test drops second RTP packet with a marker bit set, makes sure it's
831// retransmitted and renders. Retransmission SSRCs are also checked.
Peter Boström39593972016-02-15 11:27:15 +0100832void EndToEndTest::DecodesRetransmittedFrame(bool enable_rtx, bool enable_red) {
Peter Boström67680c12016-02-17 11:10:04 +0100833 static const int kDroppedFrameNumber = 10;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000834 class RetransmissionObserver : public test::EndToEndTest,
835 public I420FrameCallback {
836 public:
Peter Boström39593972016-02-15 11:27:15 +0100837 RetransmissionObserver(bool enable_rtx, bool enable_red)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000838 : EndToEndTest(kDefaultTimeoutMs),
Peter Boström39593972016-02-15 11:27:15 +0100839 payload_type_(GetPayloadType(false, enable_red)),
840 retransmission_ssrc_(enable_rtx ? kSendRtxSsrcs[0]
841 : kVideoSendSsrcs[0]),
842 retransmission_payload_type_(GetPayloadType(enable_rtx, enable_red)),
843 encoder_(VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000844 marker_bits_observed_(0),
danilchap192717e2016-07-25 08:20:51 -0700845 retransmitted_timestamp_(0) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000846
847 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000848 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700849 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000850 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000851 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000852
Peter Boström67680c12016-02-17 11:10:04 +0100853 // Ignore padding-only packets over RTX.
854 if (header.payloadType != payload_type_) {
855 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
856 if (length == header.headerLength + header.paddingLength)
857 return SEND_PACKET;
Stefan Holmer586b19b2015-09-18 11:14:31 +0200858 }
Peter Boström67680c12016-02-17 11:10:04 +0100859
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000860 if (header.timestamp == retransmitted_timestamp_) {
861 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
862 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000863 return SEND_PACKET;
864 }
865
Stefan Holmer586b19b2015-09-18 11:14:31 +0200866 // Found the final packet of the frame to inflict loss to, drop this and
867 // expect a retransmission.
danilchapfdd381c2016-07-25 04:03:20 -0700868 if (header.payloadType == payload_type_ && header.markerBit &&
869 ++marker_bits_observed_ == kDroppedFrameNumber) {
Danil Chapovalov18c65a42016-06-29 15:29:34 +0200870 // This should be the only dropped packet.
871 EXPECT_EQ(0u, retransmitted_timestamp_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000872 retransmitted_timestamp_ = header.timestamp;
danilchap192717e2016-07-25 08:20:51 -0700873 if (std::find(rendered_timestamps_.begin(), rendered_timestamps_.end(),
874 retransmitted_timestamp_) != rendered_timestamps_.end()) {
875 // Frame was rendered before last packet was scheduled for sending.
876 // This is extremly rare but possible scenario because prober able to
877 // resend packet before it was send.
878 // TODO(danilchap): Remove this corner case when prober would not be
879 // able to sneak in between packet saved to history for resending and
880 // pacer notified about existance of that packet for sending.
881 // See https://bugs.chromium.org/p/webrtc/issues/detail?id=5540 for
882 // details.
883 observation_complete_.Set();
884 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000885 return DROP_PACKET;
886 }
887
888 return SEND_PACKET;
889 }
890
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700891 void FrameCallback(VideoFrame* frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200892 rtc::CritScope lock(&crit_);
danilchap192717e2016-07-25 08:20:51 -0700893 if (frame->timestamp() == retransmitted_timestamp_)
Peter Boström5811a392015-12-10 13:02:50 +0100894 observation_complete_.Set();
danilchap192717e2016-07-25 08:20:51 -0700895 rendered_timestamps_.push_back(frame->timestamp());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000896 }
897
stefanff483612015-12-21 03:14:00 -0800898 void ModifyVideoConfigs(
899 VideoSendStream::Config* send_config,
900 std::vector<VideoReceiveStream::Config>* receive_configs,
901 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000902 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000903 (*receive_configs)[0].pre_render_callback = this;
904 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
Shao Changbine62202f2015-04-21 20:24:50 +0800905
906 if (payload_type_ == kRedPayloadType) {
907 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
908 send_config->rtp.fec.red_payload_type = kRedPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +0100909 if (retransmission_ssrc_ == kSendRtxSsrcs[0])
910 send_config->rtp.fec.red_rtx_payload_type = kRtxRedPayloadType;
911 (*receive_configs)[0].rtp.fec.ulpfec_payload_type =
912 send_config->rtp.fec.ulpfec_payload_type;
913 (*receive_configs)[0].rtp.fec.red_payload_type =
914 send_config->rtp.fec.red_payload_type;
915 (*receive_configs)[0].rtp.fec.red_rtx_payload_type =
916 send_config->rtp.fec.red_rtx_payload_type;
Shao Changbine62202f2015-04-21 20:24:50 +0800917 }
918
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000919 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
920 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000921 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +0100922 (*receive_configs)[0].rtp.rtx[payload_type_].ssrc = kSendRtxSsrcs[0];
923 (*receive_configs)[0].rtp.rtx[payload_type_].payload_type =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000924 kSendRtxPayloadType;
925 }
Peter Boström39593972016-02-15 11:27:15 +0100926 // Configure encoding and decoding with VP8, since generic packetization
927 // doesn't support FEC with NACK.
928 RTC_DCHECK_EQ(1u, (*receive_configs)[0].decoders.size());
929 send_config->encoder_settings.encoder = encoder_.get();
930 send_config->encoder_settings.payload_name = "VP8";
931 (*receive_configs)[0].decoders[0].payload_name = "VP8";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000932 }
933
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000934 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100935 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000936 << "Timed out while waiting for retransmission to render.";
937 }
938
Shao Changbine62202f2015-04-21 20:24:50 +0800939 int GetPayloadType(bool use_rtx, bool use_red) {
Stefan Holmer10880012016-02-03 13:29:59 +0100940 if (use_red) {
941 if (use_rtx)
942 return kRtxRedPayloadType;
943 return kRedPayloadType;
944 }
945 if (use_rtx)
946 return kSendRtxPayloadType;
947 return kFakeVideoSendPayloadType;
Shao Changbine62202f2015-04-21 20:24:50 +0800948 }
949
stefanf116bd02015-10-27 08:29:42 -0700950 rtc::CriticalSection crit_;
Shao Changbine62202f2015-04-21 20:24:50 +0800951 const int payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000952 const uint32_t retransmission_ssrc_;
953 const int retransmission_payload_type_;
kwiberg27f982b2016-03-01 11:52:33 -0800954 std::unique_ptr<VideoEncoder> encoder_;
Peter Boström39593972016-02-15 11:27:15 +0100955 const std::string payload_name_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000956 int marker_bits_observed_;
stefanf116bd02015-10-27 08:29:42 -0700957 uint32_t retransmitted_timestamp_ GUARDED_BY(&crit_);
danilchap192717e2016-07-25 08:20:51 -0700958 std::vector<uint32_t> rendered_timestamps_ GUARDED_BY(&crit_);
Peter Boström39593972016-02-15 11:27:15 +0100959 } test(enable_rtx, enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000960
stefane74eef12016-01-08 06:47:13 -0800961 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000962}
963
964TEST_F(EndToEndTest, DecodesRetransmittedFrame) {
Shao Changbine62202f2015-04-21 20:24:50 +0800965 DecodesRetransmittedFrame(false, false);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000966}
967
968TEST_F(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +0800969 DecodesRetransmittedFrame(true, false);
970}
971
972TEST_F(EndToEndTest, DecodesRetransmittedFrameByRed) {
973 DecodesRetransmittedFrame(false, true);
974}
975
976TEST_F(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
977 DecodesRetransmittedFrame(true, true);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000978}
979
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000980void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
981 static const int kPacketsToDrop = 1;
982
nisse7ade7b32016-03-23 04:48:10 -0700983 class PliObserver : public test::EndToEndTest,
984 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000985 public:
986 explicit PliObserver(int rtp_history_ms)
987 : EndToEndTest(kLongTimeoutMs),
988 rtp_history_ms_(rtp_history_ms),
989 nack_enabled_(rtp_history_ms > 0),
990 highest_dropped_timestamp_(0),
991 frames_to_drop_(0),
992 received_pli_(false) {}
993
994 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000995 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700996 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000997 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000998 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000999
1000 // Drop all retransmitted packets to force a PLI.
1001 if (header.timestamp <= highest_dropped_timestamp_)
1002 return DROP_PACKET;
1003
1004 if (frames_to_drop_ > 0) {
1005 highest_dropped_timestamp_ = header.timestamp;
1006 --frames_to_drop_;
1007 return DROP_PACKET;
1008 }
1009
1010 return SEND_PACKET;
1011 }
1012
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001013 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001014 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001015 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1016 EXPECT_TRUE(parser.IsValid());
1017
1018 for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02001019 packet_type != RTCPUtility::RTCPPacketTypes::kInvalid;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001020 packet_type = parser.Iterate()) {
1021 if (!nack_enabled_)
Erik Språng242e22b2015-05-11 10:17:43 +02001022 EXPECT_NE(packet_type, RTCPUtility::RTCPPacketTypes::kRtpfbNack);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001023
Erik Språng242e22b2015-05-11 10:17:43 +02001024 if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbPli) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001025 received_pli_ = true;
1026 break;
1027 }
1028 }
1029 return SEND_PACKET;
1030 }
1031
nisseeb83a1a2016-03-21 01:27:56 -07001032 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001033 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001034 if (received_pli_ &&
1035 video_frame.timestamp() > highest_dropped_timestamp_) {
Peter Boström5811a392015-12-10 13:02:50 +01001036 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001037 }
1038 if (!received_pli_)
1039 frames_to_drop_ = kPacketsToDrop;
1040 }
1041
stefanff483612015-12-21 03:14:00 -08001042 void ModifyVideoConfigs(
1043 VideoSendStream::Config* send_config,
1044 std::vector<VideoReceiveStream::Config>* receive_configs,
1045 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001046 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001047 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
1048 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001049 }
1050
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001051 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001052 EXPECT_TRUE(Wait()) << "Timed out waiting for PLI to be "
1053 "received and a frame to be "
1054 "rendered afterwards.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001055 }
1056
stefanf116bd02015-10-27 08:29:42 -07001057 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001058 int rtp_history_ms_;
1059 bool nack_enabled_;
stefanf116bd02015-10-27 08:29:42 -07001060 uint32_t highest_dropped_timestamp_ GUARDED_BY(&crit_);
1061 int frames_to_drop_ GUARDED_BY(&crit_);
1062 bool received_pli_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001063 } test(rtp_history_ms);
1064
stefane74eef12016-01-08 06:47:13 -08001065 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001066}
1067
1068TEST_F(EndToEndTest, ReceivesPliAndRecoversWithNack) {
1069 ReceivesPliAndRecovers(1000);
1070}
1071
jbauchdb81ffd2015-11-23 03:59:02 -08001072TEST_F(EndToEndTest, ReceivesPliAndRecoversWithoutNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001073 ReceivesPliAndRecovers(0);
1074}
1075
1076TEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
1077 class PacketInputObserver : public PacketReceiver {
1078 public:
1079 explicit PacketInputObserver(PacketReceiver* receiver)
Peter Boström5811a392015-12-10 13:02:50 +01001080 : receiver_(receiver), delivered_packet_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001081
Peter Boström5811a392015-12-10 13:02:50 +01001082 bool Wait() { return delivered_packet_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001083
1084 private:
stefan68786d22015-09-08 05:36:15 -07001085 DeliveryStatus DeliverPacket(MediaType media_type,
1086 const uint8_t* packet,
1087 size_t length,
1088 const PacketTime& packet_time) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001089 if (RtpHeaderParser::IsRtcp(packet, length)) {
stefan68786d22015-09-08 05:36:15 -07001090 return receiver_->DeliverPacket(media_type, packet, length,
1091 packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001092 } else {
1093 DeliveryStatus delivery_status =
stefan68786d22015-09-08 05:36:15 -07001094 receiver_->DeliverPacket(media_type, packet, length, packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001095 EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
Peter Boström5811a392015-12-10 13:02:50 +01001096 delivered_packet_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001097 return delivery_status;
1098 }
1099 }
1100
1101 PacketReceiver* receiver_;
Peter Boström5811a392015-12-10 13:02:50 +01001102 rtc::Event delivered_packet_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001103 };
1104
solenberg4fbae2b2015-08-28 04:07:10 -07001105 CreateCalls(Call::Config(), Call::Config());
1106
stefanf116bd02015-10-27 08:29:42 -07001107 test::DirectTransport send_transport(sender_call_.get());
1108 test::DirectTransport receive_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001109 PacketInputObserver input_observer(receiver_call_->Receiver());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001110 send_transport.SetReceiver(&input_observer);
1111 receive_transport.SetReceiver(sender_call_->Receiver());
1112
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001113 CreateSendConfig(1, 0, &send_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001114 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001115
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001116 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001117 CreateFrameGeneratorCapturer();
1118 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001119
stefanff483612015-12-21 03:14:00 -08001120 receiver_call_->DestroyVideoReceiveStream(video_receive_streams_[0]);
1121 video_receive_streams_.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001122
1123 // Wait() waits for a received packet.
Peter Boström5811a392015-12-10 13:02:50 +01001124 EXPECT_TRUE(input_observer.Wait());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001125
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001126 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001127
1128 DestroyStreams();
1129
1130 send_transport.StopSending();
1131 receive_transport.StopSending();
1132}
1133
pbosda903ea2015-10-02 02:36:56 -07001134void EndToEndTest::RespectsRtcpMode(RtcpMode rtcp_mode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001135 static const int kNumCompoundRtcpPacketsToObserve = 10;
1136 class RtcpModeObserver : public test::EndToEndTest {
1137 public:
pbosda903ea2015-10-02 02:36:56 -07001138 explicit RtcpModeObserver(RtcpMode rtcp_mode)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001139 : EndToEndTest(kDefaultTimeoutMs),
1140 rtcp_mode_(rtcp_mode),
1141 sent_rtp_(0),
1142 sent_rtcp_(0) {}
1143
1144 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001145 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001146 if (++sent_rtp_ % 3 == 0)
1147 return DROP_PACKET;
1148
1149 return SEND_PACKET;
1150 }
1151
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001152 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001153 ++sent_rtcp_;
1154 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1155 EXPECT_TRUE(parser.IsValid());
1156
1157 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1158 bool has_report_block = false;
Erik Språng242e22b2015-05-11 10:17:43 +02001159 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1160 EXPECT_NE(RTCPUtility::RTCPPacketTypes::kSr, packet_type);
1161 if (packet_type == RTCPUtility::RTCPPacketTypes::kRr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001162 has_report_block = true;
1163 break;
1164 }
1165 packet_type = parser.Iterate();
1166 }
1167
1168 switch (rtcp_mode_) {
pbosda903ea2015-10-02 02:36:56 -07001169 case RtcpMode::kCompound:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001170 if (!has_report_block) {
1171 ADD_FAILURE() << "Received RTCP packet without receiver report for "
pbosda903ea2015-10-02 02:36:56 -07001172 "RtcpMode::kCompound.";
Peter Boström5811a392015-12-10 13:02:50 +01001173 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001174 }
1175
1176 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
Peter Boström5811a392015-12-10 13:02:50 +01001177 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001178
1179 break;
pbosda903ea2015-10-02 02:36:56 -07001180 case RtcpMode::kReducedSize:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001181 if (!has_report_block)
Peter Boström5811a392015-12-10 13:02:50 +01001182 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001183 break;
pbosda903ea2015-10-02 02:36:56 -07001184 case RtcpMode::kOff:
1185 RTC_NOTREACHED();
1186 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001187 }
1188
1189 return SEND_PACKET;
1190 }
1191
stefanff483612015-12-21 03:14:00 -08001192 void ModifyVideoConfigs(
1193 VideoSendStream::Config* send_config,
1194 std::vector<VideoReceiveStream::Config>* receive_configs,
1195 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001196 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001197 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1198 (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001199 }
1200
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001201 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001202 EXPECT_TRUE(Wait())
pbosda903ea2015-10-02 02:36:56 -07001203 << (rtcp_mode_ == RtcpMode::kCompound
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001204 ? "Timed out before observing enough compound packets."
1205 : "Timed out before receiving a non-compound RTCP packet.");
1206 }
1207
pbosda903ea2015-10-02 02:36:56 -07001208 RtcpMode rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001209 int sent_rtp_;
1210 int sent_rtcp_;
1211 } test(rtcp_mode);
1212
stefane74eef12016-01-08 06:47:13 -08001213 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001214}
1215
1216TEST_F(EndToEndTest, UsesRtcpCompoundMode) {
pbosda903ea2015-10-02 02:36:56 -07001217 RespectsRtcpMode(RtcpMode::kCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001218}
1219
1220TEST_F(EndToEndTest, UsesRtcpReducedSizeMode) {
pbosda903ea2015-10-02 02:36:56 -07001221 RespectsRtcpMode(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001222}
1223
1224// Test sets up a Call multiple senders with different resolutions and SSRCs.
1225// Another is set up to receive all three of these with different renderers.
sprang867fb522015-08-03 04:38:41 -07001226class MultiStreamTest {
1227 public:
1228 static const size_t kNumStreams = 3;
1229 struct CodecSettings {
1230 uint32_t ssrc;
1231 int width;
1232 int height;
1233 } codec_settings[kNumStreams];
1234
1235 MultiStreamTest() {
1236 // TODO(sprang): Cleanup when msvc supports explicit initializers for array.
1237 codec_settings[0] = {1, 640, 480};
1238 codec_settings[1] = {2, 320, 240};
1239 codec_settings[2] = {3, 240, 160};
1240 }
1241
1242 virtual ~MultiStreamTest() {}
1243
1244 void RunTest() {
kwiberg27f982b2016-03-01 11:52:33 -08001245 std::unique_ptr<Call> sender_call(Call::Create(Call::Config()));
1246 std::unique_ptr<Call> receiver_call(Call::Create(Call::Config()));
1247 std::unique_ptr<test::DirectTransport> sender_transport(
stefanf116bd02015-10-27 08:29:42 -07001248 CreateSendTransport(sender_call.get()));
kwiberg27f982b2016-03-01 11:52:33 -08001249 std::unique_ptr<test::DirectTransport> receiver_transport(
stefanf116bd02015-10-27 08:29:42 -07001250 CreateReceiveTransport(receiver_call.get()));
sprang867fb522015-08-03 04:38:41 -07001251 sender_transport->SetReceiver(receiver_call->Receiver());
1252 receiver_transport->SetReceiver(sender_call->Receiver());
1253
kwiberg27f982b2016-03-01 11:52:33 -08001254 std::unique_ptr<VideoEncoder> encoders[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001255 for (size_t i = 0; i < kNumStreams; ++i)
1256 encoders[i].reset(VideoEncoder::Create(VideoEncoder::kVp8));
1257
1258 VideoSendStream* send_streams[kNumStreams];
1259 VideoReceiveStream* receive_streams[kNumStreams];
1260
1261 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
kwiberg4a206a92016-03-31 10:24:26 -07001262 std::vector<std::unique_ptr<VideoDecoder>> allocated_decoders;
sprang867fb522015-08-03 04:38:41 -07001263 for (size_t i = 0; i < kNumStreams; ++i) {
1264 uint32_t ssrc = codec_settings[i].ssrc;
1265 int width = codec_settings[i].width;
1266 int height = codec_settings[i].height;
1267
solenberg4fbae2b2015-08-28 04:07:10 -07001268 VideoSendStream::Config send_config(sender_transport.get());
sprang867fb522015-08-03 04:38:41 -07001269 send_config.rtp.ssrcs.push_back(ssrc);
1270 send_config.encoder_settings.encoder = encoders[i].get();
1271 send_config.encoder_settings.payload_name = "VP8";
1272 send_config.encoder_settings.payload_type = 124;
1273 VideoEncoderConfig encoder_config;
1274 encoder_config.streams = test::CreateVideoStreams(1);
1275 VideoStream* stream = &encoder_config.streams[0];
1276 stream->width = width;
1277 stream->height = height;
1278 stream->max_framerate = 5;
1279 stream->min_bitrate_bps = stream->target_bitrate_bps =
1280 stream->max_bitrate_bps = 100000;
1281
1282 UpdateSendConfig(i, &send_config, &encoder_config, &frame_generators[i]);
1283
perkj8eb37a32016-08-16 02:40:55 -07001284 send_streams[i] =
1285 sender_call->CreateVideoSendStream(send_config, encoder_config);
sprang867fb522015-08-03 04:38:41 -07001286 send_streams[i]->Start();
1287
solenberg4fbae2b2015-08-28 04:07:10 -07001288 VideoReceiveStream::Config receive_config(receiver_transport.get());
sprang867fb522015-08-03 04:38:41 -07001289 receive_config.rtp.remote_ssrc = ssrc;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001290 receive_config.rtp.local_ssrc = test::CallTest::kReceiverLocalVideoSsrc;
sprang867fb522015-08-03 04:38:41 -07001291 VideoReceiveStream::Decoder decoder =
1292 test::CreateMatchingDecoder(send_config.encoder_settings);
kwiberg4a206a92016-03-31 10:24:26 -07001293 allocated_decoders.push_back(
1294 std::unique_ptr<VideoDecoder>(decoder.decoder));
sprang867fb522015-08-03 04:38:41 -07001295 receive_config.decoders.push_back(decoder);
1296
1297 UpdateReceiveConfig(i, &receive_config);
1298
1299 receive_streams[i] =
Tommi733b5472016-06-10 17:58:01 +02001300 receiver_call->CreateVideoReceiveStream(std::move(receive_config));
sprang867fb522015-08-03 04:38:41 -07001301 receive_streams[i]->Start();
1302
1303 frame_generators[i] = test::FrameGeneratorCapturer::Create(
1304 send_streams[i]->Input(), width, height, 30,
1305 Clock::GetRealTimeClock());
1306 frame_generators[i]->Start();
1307 }
1308
1309 Wait();
1310
1311 for (size_t i = 0; i < kNumStreams; ++i) {
1312 frame_generators[i]->Stop();
1313 sender_call->DestroyVideoSendStream(send_streams[i]);
1314 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1315 delete frame_generators[i];
1316 }
1317
1318 sender_transport->StopSending();
1319 receiver_transport->StopSending();
1320 }
1321
1322 protected:
1323 virtual void Wait() = 0;
1324 // Note: frame_generator is a point-to-pointer, since the actual instance
1325 // hasn't been created at the time of this call. Only when packets/frames
1326 // start flowing should this be dereferenced.
1327 virtual void UpdateSendConfig(
1328 size_t stream_index,
1329 VideoSendStream::Config* send_config,
1330 VideoEncoderConfig* encoder_config,
1331 test::FrameGeneratorCapturer** frame_generator) {}
1332 virtual void UpdateReceiveConfig(size_t stream_index,
1333 VideoReceiveStream::Config* receive_config) {
1334 }
stefanf116bd02015-10-27 08:29:42 -07001335 virtual test::DirectTransport* CreateSendTransport(Call* sender_call) {
1336 return new test::DirectTransport(sender_call);
sprang867fb522015-08-03 04:38:41 -07001337 }
stefanf116bd02015-10-27 08:29:42 -07001338 virtual test::DirectTransport* CreateReceiveTransport(Call* receiver_call) {
1339 return new test::DirectTransport(receiver_call);
sprang867fb522015-08-03 04:38:41 -07001340 }
1341};
1342
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001343// Each renderer verifies that it receives the expected resolution, and as soon
1344// as every renderer has received a frame, the test finishes.
andresp@webrtc.org02686112014-09-19 08:24:19 +00001345TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) {
nisse7ade7b32016-03-23 04:48:10 -07001346 class VideoOutputObserver : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001347 public:
sprang867fb522015-08-03 04:38:41 -07001348 VideoOutputObserver(const MultiStreamTest::CodecSettings& settings,
1349 uint32_t ssrc,
1350 test::FrameGeneratorCapturer** frame_generator)
1351 : settings_(settings),
1352 ssrc_(ssrc),
1353 frame_generator_(frame_generator),
Peter Boström5811a392015-12-10 13:02:50 +01001354 done_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001355
nisseeb83a1a2016-03-21 01:27:56 -07001356 void OnFrame(const VideoFrame& video_frame) override {
sprang867fb522015-08-03 04:38:41 -07001357 EXPECT_EQ(settings_.width, video_frame.width());
1358 EXPECT_EQ(settings_.height, video_frame.height());
1359 (*frame_generator_)->Stop();
Peter Boström5811a392015-12-10 13:02:50 +01001360 done_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001361 }
1362
sprang867fb522015-08-03 04:38:41 -07001363 uint32_t Ssrc() { return ssrc_; }
1364
Peter Boström5811a392015-12-10 13:02:50 +01001365 bool Wait() { return done_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001366
1367 private:
sprang867fb522015-08-03 04:38:41 -07001368 const MultiStreamTest::CodecSettings& settings_;
1369 const uint32_t ssrc_;
1370 test::FrameGeneratorCapturer** const frame_generator_;
Peter Boström5811a392015-12-10 13:02:50 +01001371 rtc::Event done_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001372 };
1373
sprang867fb522015-08-03 04:38:41 -07001374 class Tester : public MultiStreamTest {
1375 public:
1376 Tester() {}
1377 virtual ~Tester() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001378
sprang867fb522015-08-03 04:38:41 -07001379 protected:
1380 void Wait() override {
1381 for (const auto& observer : observers_) {
Peter Boström5811a392015-12-10 13:02:50 +01001382 EXPECT_TRUE(observer->Wait()) << "Time out waiting for from on ssrc "
1383 << observer->Ssrc();
sprang867fb522015-08-03 04:38:41 -07001384 }
1385 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001386
sprang867fb522015-08-03 04:38:41 -07001387 void UpdateSendConfig(
1388 size_t stream_index,
1389 VideoSendStream::Config* send_config,
1390 VideoEncoderConfig* encoder_config,
1391 test::FrameGeneratorCapturer** frame_generator) override {
1392 observers_[stream_index].reset(new VideoOutputObserver(
1393 codec_settings[stream_index], send_config->rtp.ssrcs.front(),
1394 frame_generator));
1395 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001396
sprang867fb522015-08-03 04:38:41 -07001397 void UpdateReceiveConfig(
1398 size_t stream_index,
1399 VideoReceiveStream::Config* receive_config) override {
1400 receive_config->renderer = observers_[stream_index].get();
1401 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001402
sprang867fb522015-08-03 04:38:41 -07001403 private:
kwiberg27f982b2016-03-01 11:52:33 -08001404 std::unique_ptr<VideoOutputObserver> observers_[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001405 } tester;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001406
sprang867fb522015-08-03 04:38:41 -07001407 tester.RunTest();
1408}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001409
sprang867fb522015-08-03 04:38:41 -07001410TEST_F(EndToEndTest, AssignsTransportSequenceNumbers) {
sprang867fb522015-08-03 04:38:41 -07001411 static const int kExtensionId = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001412
sprang867fb522015-08-03 04:38:41 -07001413 class RtpExtensionHeaderObserver : public test::DirectTransport {
1414 public:
stefanf116bd02015-10-27 08:29:42 -07001415 RtpExtensionHeaderObserver(Call* sender_call,
1416 const uint32_t& first_media_ssrc,
sprang861c55e2015-10-16 10:01:21 -07001417 const std::map<uint32_t, uint32_t>& ssrc_map)
stefanf116bd02015-10-27 08:29:42 -07001418 : DirectTransport(sender_call),
Peter Boström5811a392015-12-10 13:02:50 +01001419 done_(false, false),
sprang867fb522015-08-03 04:38:41 -07001420 parser_(RtpHeaderParser::Create()),
sprang861c55e2015-10-16 10:01:21 -07001421 first_media_ssrc_(first_media_ssrc),
1422 rtx_to_media_ssrcs_(ssrc_map),
sprang867fb522015-08-03 04:38:41 -07001423 padding_observed_(false),
sprang861c55e2015-10-16 10:01:21 -07001424 rtx_padding_observed_(false),
1425 retransmit_observed_(false),
1426 started_(false) {
sprang867fb522015-08-03 04:38:41 -07001427 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
1428 kExtensionId);
1429 }
1430 virtual ~RtpExtensionHeaderObserver() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001431
stefan1d8a5062015-10-02 03:39:33 -07001432 bool SendRtp(const uint8_t* data,
1433 size_t length,
1434 const PacketOptions& options) override {
sprang861c55e2015-10-16 10:01:21 -07001435 {
1436 rtc::CritScope cs(&lock_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001437
Erik Språng8d629712015-08-04 16:24:03 +02001438 if (IsDone())
sprang861c55e2015-10-16 10:01:21 -07001439 return false;
1440
1441 if (started_) {
1442 RTPHeader header;
1443 EXPECT_TRUE(parser_->Parse(data, length, &header));
1444 bool drop_packet = false;
1445
1446 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
1447 EXPECT_EQ(options.packet_id,
1448 header.extension.transportSequenceNumber);
1449 if (!streams_observed_.empty()) {
1450 // Unwrap packet id and verify uniqueness.
1451 int64_t packet_id = unwrapper_.Unwrap(options.packet_id);
1452 EXPECT_TRUE(received_packed_ids_.insert(packet_id).second);
1453 }
1454
1455 // Drop (up to) every 17th packet, so we get retransmits.
1456 // Only drop media, and not on the first stream (otherwise it will be
1457 // hard to distinguish from padding, which is always sent on the first
1458 // stream).
1459 if (header.payloadType != kSendRtxPayloadType &&
1460 header.ssrc != first_media_ssrc_ &&
1461 header.extension.transportSequenceNumber % 17 == 0) {
1462 dropped_seq_[header.ssrc].insert(header.sequenceNumber);
1463 drop_packet = true;
1464 }
1465
1466 size_t payload_length =
1467 length - (header.headerLength + header.paddingLength);
1468 if (payload_length == 0) {
1469 padding_observed_ = true;
1470 } else if (header.payloadType == kSendRtxPayloadType) {
1471 uint16_t original_sequence_number =
1472 ByteReader<uint16_t>::ReadBigEndian(&data[header.headerLength]);
1473 uint32_t original_ssrc =
1474 rtx_to_media_ssrcs_.find(header.ssrc)->second;
1475 std::set<uint16_t>* seq_no_map = &dropped_seq_[original_ssrc];
1476 auto it = seq_no_map->find(original_sequence_number);
1477 if (it != seq_no_map->end()) {
1478 retransmit_observed_ = true;
1479 seq_no_map->erase(it);
1480 } else {
1481 rtx_padding_observed_ = true;
1482 }
1483 } else {
1484 streams_observed_.insert(header.ssrc);
1485 }
1486
1487 if (IsDone())
Peter Boström5811a392015-12-10 13:02:50 +01001488 done_.Set();
sprang861c55e2015-10-16 10:01:21 -07001489
1490 if (drop_packet)
1491 return true;
1492 }
sprang867fb522015-08-03 04:38:41 -07001493 }
sprang861c55e2015-10-16 10:01:21 -07001494
stefan1d8a5062015-10-02 03:39:33 -07001495 return test::DirectTransport::SendRtp(data, length, options);
sprang867fb522015-08-03 04:38:41 -07001496 }
1497
Erik Språng8d629712015-08-04 16:24:03 +02001498 bool IsDone() {
sprang861c55e2015-10-16 10:01:21 -07001499 bool observed_types_ok =
1500 streams_observed_.size() == MultiStreamTest::kNumStreams &&
1501 padding_observed_ && retransmit_observed_ && rtx_padding_observed_;
1502 if (!observed_types_ok)
1503 return false;
1504 // We should not have any gaps in the sequence number range.
1505 size_t seqno_range =
1506 *received_packed_ids_.rbegin() - *received_packed_ids_.begin() + 1;
1507 return seqno_range == received_packed_ids_.size();
Erik Språng8d629712015-08-04 16:24:03 +02001508 }
1509
Peter Boström5811a392015-12-10 13:02:50 +01001510 bool Wait() {
sprang861c55e2015-10-16 10:01:21 -07001511 {
1512 // Can't be sure until this point that rtx_to_media_ssrcs_ etc have
1513 // been initialized and are OK to read.
1514 rtc::CritScope cs(&lock_);
1515 started_ = true;
1516 }
Peter Boström5811a392015-12-10 13:02:50 +01001517 return done_.Wait(kDefaultTimeoutMs);
sprang861c55e2015-10-16 10:01:21 -07001518 }
sprang867fb522015-08-03 04:38:41 -07001519
sprang861c55e2015-10-16 10:01:21 -07001520 rtc::CriticalSection lock_;
Peter Boström5811a392015-12-10 13:02:50 +01001521 rtc::Event done_;
kwiberg27f982b2016-03-01 11:52:33 -08001522 std::unique_ptr<RtpHeaderParser> parser_;
sprang861c55e2015-10-16 10:01:21 -07001523 SequenceNumberUnwrapper unwrapper_;
1524 std::set<int64_t> received_packed_ids_;
sprang867fb522015-08-03 04:38:41 -07001525 std::set<uint32_t> streams_observed_;
sprang861c55e2015-10-16 10:01:21 -07001526 std::map<uint32_t, std::set<uint16_t>> dropped_seq_;
1527 const uint32_t& first_media_ssrc_;
1528 const std::map<uint32_t, uint32_t>& rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001529 bool padding_observed_;
1530 bool rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001531 bool retransmit_observed_;
1532 bool started_;
sprang867fb522015-08-03 04:38:41 -07001533 };
1534
1535 class TransportSequenceNumberTester : public MultiStreamTest {
1536 public:
sprang861c55e2015-10-16 10:01:21 -07001537 TransportSequenceNumberTester()
1538 : first_media_ssrc_(0), observer_(nullptr) {}
sprang867fb522015-08-03 04:38:41 -07001539 virtual ~TransportSequenceNumberTester() {}
1540
1541 protected:
1542 void Wait() override {
Peter Boström74f6e9e2016-04-04 17:56:10 +02001543 RTC_DCHECK(observer_);
Peter Boström5811a392015-12-10 13:02:50 +01001544 EXPECT_TRUE(observer_->Wait());
sprang867fb522015-08-03 04:38:41 -07001545 }
1546
1547 void UpdateSendConfig(
1548 size_t stream_index,
1549 VideoSendStream::Config* send_config,
1550 VideoEncoderConfig* encoder_config,
1551 test::FrameGeneratorCapturer** frame_generator) override {
1552 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001553 send_config->rtp.extensions.push_back(RtpExtension(
1554 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sprang867fb522015-08-03 04:38:41 -07001555
1556 // Force some padding to be sent.
1557 const int kPaddingBitrateBps = 50000;
1558 int total_target_bitrate = 0;
1559 for (const VideoStream& stream : encoder_config->streams)
1560 total_target_bitrate += stream.target_bitrate_bps;
1561 encoder_config->min_transmit_bitrate_bps =
1562 total_target_bitrate + kPaddingBitrateBps;
1563
1564 // Configure RTX for redundant payload padding.
1565 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang861c55e2015-10-16 10:01:21 -07001566 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[stream_index]);
sprang867fb522015-08-03 04:38:41 -07001567 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
sprang861c55e2015-10-16 10:01:21 -07001568 rtx_to_media_ssrcs_[kSendRtxSsrcs[stream_index]] =
1569 send_config->rtp.ssrcs[0];
1570
1571 if (stream_index == 0)
1572 first_media_ssrc_ = send_config->rtp.ssrcs[0];
sprang867fb522015-08-03 04:38:41 -07001573 }
1574
1575 void UpdateReceiveConfig(
1576 size_t stream_index,
1577 VideoReceiveStream::Config* receive_config) override {
sprang861c55e2015-10-16 10:01:21 -07001578 receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang867fb522015-08-03 04:38:41 -07001579 receive_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001580 receive_config->rtp.extensions.push_back(RtpExtension(
1581 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sprang867fb522015-08-03 04:38:41 -07001582 }
1583
stefanf116bd02015-10-27 08:29:42 -07001584 test::DirectTransport* CreateSendTransport(Call* sender_call) override {
1585 observer_ = new RtpExtensionHeaderObserver(sender_call, first_media_ssrc_,
sprang861c55e2015-10-16 10:01:21 -07001586 rtx_to_media_ssrcs_);
sprang867fb522015-08-03 04:38:41 -07001587 return observer_;
1588 }
1589
1590 private:
sprang861c55e2015-10-16 10:01:21 -07001591 uint32_t first_media_ssrc_;
1592 std::map<uint32_t, uint32_t> rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001593 RtpExtensionHeaderObserver* observer_;
1594 } tester;
1595
1596 tester.RunTest();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001597}
1598
Stefan Holmer04cb7632016-01-14 20:34:30 +01001599class TransportFeedbackTester : public test::EndToEndTest {
1600 public:
1601 explicit TransportFeedbackTester(bool feedback_enabled,
1602 size_t num_video_streams,
1603 size_t num_audio_streams)
1604 : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
1605 feedback_enabled_(feedback_enabled),
1606 num_video_streams_(num_video_streams),
sprangcd349d92016-07-13 09:11:28 -07001607 num_audio_streams_(num_audio_streams),
1608 receiver_call_(nullptr) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001609 // Only one stream of each supported for now.
1610 EXPECT_LE(num_video_streams, 1u);
1611 EXPECT_LE(num_audio_streams, 1u);
1612 }
1613
1614 protected:
1615 Action OnSendRtcp(const uint8_t* data, size_t length) override {
1616 EXPECT_FALSE(HasTransportFeedback(data, length));
1617 return SEND_PACKET;
1618 }
1619
1620 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
1621 if (HasTransportFeedback(data, length))
1622 observation_complete_.Set();
1623 return SEND_PACKET;
1624 }
1625
1626 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
1627 RTCPUtility::RTCPParserV2 parser(data, length, true);
1628 EXPECT_TRUE(parser.IsValid());
1629
1630 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1631 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1632 if (packet_type == RTCPUtility::RTCPPacketTypes::kTransportFeedback)
1633 return true;
1634 packet_type = parser.Iterate();
1635 }
1636
1637 return false;
1638 }
1639
1640 void PerformTest() override {
1641 const int64_t kDisabledFeedbackTimeoutMs = 5000;
1642 EXPECT_EQ(feedback_enabled_,
1643 observation_complete_.Wait(feedback_enabled_
1644 ? test::CallTest::kDefaultTimeoutMs
1645 : kDisabledFeedbackTimeoutMs));
1646 }
1647
1648 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1649 receiver_call_ = receiver_call;
1650 }
1651
1652 size_t GetNumVideoStreams() const override { return num_video_streams_; }
1653 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
1654
1655 void ModifyVideoConfigs(
1656 VideoSendStream::Config* send_config,
1657 std::vector<VideoReceiveStream::Config>* receive_configs,
1658 VideoEncoderConfig* encoder_config) override {
1659 send_config->rtp.extensions.clear();
1660 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001661 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001662 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1663 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
1664 }
1665
1666 void ModifyAudioConfigs(
1667 AudioSendStream::Config* send_config,
1668 std::vector<AudioReceiveStream::Config>* receive_configs) override {
1669 send_config->rtp.extensions.clear();
1670 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001671 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001672 (*receive_configs)[0].rtp.extensions.clear();
1673 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1674 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001675 }
1676
1677 private:
Erik Språng6b8d3552015-09-24 15:06:57 +02001678 static const int kExtensionId = 5;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001679 const bool feedback_enabled_;
1680 const size_t num_video_streams_;
1681 const size_t num_audio_streams_;
1682 Call* receiver_call_;
1683};
Erik Språng6b8d3552015-09-24 15:06:57 +02001684
Stefan Holmer04cb7632016-01-14 20:34:30 +01001685TEST_F(EndToEndTest, VideoReceivesTransportFeedback) {
1686 TransportFeedbackTester test(true, 1, 0);
1687 RunBaseTest(&test);
Erik Språng6b8d3552015-09-24 15:06:57 +02001688}
stefan43edf0f2015-11-20 18:05:48 -08001689
Stefan Holmer04cb7632016-01-14 20:34:30 +01001690TEST_F(EndToEndTest, VideoTransportFeedbackNotConfigured) {
1691 TransportFeedbackTester test(false, 1, 0);
1692 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001693}
1694
Stefan Holmer04cb7632016-01-14 20:34:30 +01001695TEST_F(EndToEndTest, AudioReceivesTransportFeedback) {
1696 TransportFeedbackTester test(true, 0, 1);
1697 RunBaseTest(&test);
1698}
1699
1700TEST_F(EndToEndTest, AudioTransportFeedbackNotConfigured) {
1701 TransportFeedbackTester test(false, 0, 1);
1702 RunBaseTest(&test);
1703}
1704
1705TEST_F(EndToEndTest, AudioVideoReceivesTransportFeedback) {
1706 TransportFeedbackTester test(true, 1, 1);
1707 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001708}
1709
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001710TEST_F(EndToEndTest, ObserversEncodedFrames) {
1711 class EncodedFrameTestObserver : public EncodedFrameObserver {
1712 public:
1713 EncodedFrameTestObserver()
Peter Boström5811a392015-12-10 13:02:50 +01001714 : length_(0), frame_type_(kEmptyFrame), called_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001715 virtual ~EncodedFrameTestObserver() {}
1716
1717 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
1718 frame_type_ = encoded_frame.frame_type_;
1719 length_ = encoded_frame.length_;
1720 buffer_.reset(new uint8_t[length_]);
1721 memcpy(buffer_.get(), encoded_frame.data_, length_);
Peter Boström5811a392015-12-10 13:02:50 +01001722 called_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001723 }
1724
Peter Boström5811a392015-12-10 13:02:50 +01001725 bool Wait() { return called_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001726
1727 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
1728 ASSERT_EQ(length_, observer.length_)
1729 << "Observed frames are of different lengths.";
1730 EXPECT_EQ(frame_type_, observer.frame_type_)
1731 << "Observed frames have different frame types.";
1732 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
1733 << "Observed encoded frames have different content.";
1734 }
1735
1736 private:
kwiberg27f982b2016-03-01 11:52:33 -08001737 std::unique_ptr<uint8_t[]> buffer_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001738 size_t length_;
1739 FrameType frame_type_;
Peter Boström5811a392015-12-10 13:02:50 +01001740 rtc::Event called_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001741 };
1742
1743 EncodedFrameTestObserver post_encode_observer;
1744 EncodedFrameTestObserver pre_decode_observer;
1745
solenberg4fbae2b2015-08-28 04:07:10 -07001746 CreateCalls(Call::Config(), Call::Config());
1747
stefanf116bd02015-10-27 08:29:42 -07001748 test::DirectTransport sender_transport(sender_call_.get());
1749 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001750 sender_transport.SetReceiver(receiver_call_->Receiver());
1751 receiver_transport.SetReceiver(sender_call_->Receiver());
1752
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001753 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001754 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -08001755 video_send_config_.post_encode_callback = &post_encode_observer;
1756 video_receive_configs_[0].pre_decode_callback = &pre_decode_observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001757
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001758 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001759 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001760
kwiberg27f982b2016-03-01 11:52:33 -08001761 std::unique_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +00001762 test::FrameGenerator::CreateChromaGenerator(
stefanff483612015-12-21 03:14:00 -08001763 video_encoder_config_.streams[0].width,
1764 video_encoder_config_.streams[0].height));
1765 video_send_stream_->Input()->IncomingCapturedFrame(
1766 *frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001767
Peter Boström5811a392015-12-10 13:02:50 +01001768 EXPECT_TRUE(post_encode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001769 << "Timed out while waiting for send-side encoded-frame callback.";
1770
Peter Boström5811a392015-12-10 13:02:50 +01001771 EXPECT_TRUE(pre_decode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001772 << "Timed out while waiting for pre-decode encoded-frame callback.";
1773
1774 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
1775
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001776 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001777
1778 sender_transport.StopSending();
1779 receiver_transport.StopSending();
1780
1781 DestroyStreams();
1782}
1783
1784TEST_F(EndToEndTest, ReceiveStreamSendsRemb) {
1785 class RembObserver : public test::EndToEndTest {
1786 public:
1787 RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
1788
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001789 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001790 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1791 EXPECT_TRUE(parser.IsValid());
1792
1793 bool received_psfb = false;
1794 bool received_remb = false;
1795 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02001796 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1797 if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbRemb) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001798 const RTCPUtility::RTCPPacket& packet = parser.Packet();
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001799 EXPECT_EQ(packet.PSFBAPP.SenderSSRC, kReceiverLocalVideoSsrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001800 received_psfb = true;
Erik Språng242e22b2015-05-11 10:17:43 +02001801 } else if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbRembItem) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001802 const RTCPUtility::RTCPPacket& packet = parser.Packet();
1803 EXPECT_GT(packet.REMBItem.BitRate, 0u);
1804 EXPECT_EQ(packet.REMBItem.NumberOfSSRCs, 1u);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001805 EXPECT_EQ(packet.REMBItem.SSRCs[0], kVideoSendSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001806 received_remb = true;
1807 }
1808 packet_type = parser.Iterate();
1809 }
1810 if (received_psfb && received_remb)
Peter Boström5811a392015-12-10 13:02:50 +01001811 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001812 return SEND_PACKET;
1813 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001814 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001815 EXPECT_TRUE(Wait()) << "Timed out while waiting for a "
1816 "receiver RTCP REMB packet to be "
1817 "sent.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001818 }
1819 } test;
1820
stefane74eef12016-01-08 06:47:13 -08001821 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001822}
1823
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001824TEST_F(EndToEndTest, VerifyBandwidthStats) {
stefanf116bd02015-10-27 08:29:42 -07001825 class RtcpObserver : public test::EndToEndTest {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001826 public:
1827 RtcpObserver()
1828 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001829 sender_call_(nullptr),
1830 receiver_call_(nullptr),
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001831 has_seen_pacer_delay_(false) {}
1832
stefanf116bd02015-10-27 08:29:42 -07001833 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001834 Call::Stats sender_stats = sender_call_->GetStats();
1835 Call::Stats receiver_stats = receiver_call_->GetStats();
1836 if (!has_seen_pacer_delay_)
1837 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
1838 if (sender_stats.send_bandwidth_bps > 0 &&
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001839 receiver_stats.recv_bandwidth_bps > 0 && has_seen_pacer_delay_) {
Peter Boström5811a392015-12-10 13:02:50 +01001840 observation_complete_.Set();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001841 }
stefanf116bd02015-10-27 08:29:42 -07001842 return SEND_PACKET;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001843 }
1844
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001845 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001846 sender_call_ = sender_call;
1847 receiver_call_ = receiver_call;
1848 }
1849
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001850 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001851 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
1852 "non-zero bandwidth stats.";
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001853 }
1854
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001855 private:
1856 Call* sender_call_;
1857 Call* receiver_call_;
1858 bool has_seen_pacer_delay_;
1859 } test;
1860
stefane74eef12016-01-08 06:47:13 -08001861 RunBaseTest(&test);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001862}
1863
stefan32f81542016-01-20 07:13:58 -08001864
1865// Verifies that it's possible to limit the send BWE by sending a REMB.
1866// This is verified by allowing the send BWE to ramp-up to >1000 kbps,
1867// then have the test generate a REMB of 500 kbps and verify that the send BWE
1868// is reduced to exactly 500 kbps. Then a REMB of 1000 kbps is generated and the
1869// test verifies that the send BWE ramps back up to exactly 1000 kbps.
1870TEST_F(EndToEndTest, RembWithSendSideBwe) {
1871 class BweObserver : public test::EndToEndTest {
1872 public:
1873 BweObserver()
1874 : EndToEndTest(kDefaultTimeoutMs),
1875 sender_call_(nullptr),
1876 clock_(Clock::GetRealTimeClock()),
1877 sender_ssrc_(0),
1878 remb_bitrate_bps_(1000000),
1879 receive_transport_(nullptr),
1880 event_(false, false),
1881 poller_thread_(&BitrateStatsPollingThread,
1882 this,
1883 "BitrateStatsPollingThread"),
Erik Språng737336d2016-07-29 12:59:36 +02001884 state_(kWaitForFirstRampUp),
1885 retransmission_rate_limiter_(clock_, 1000) {}
stefan32f81542016-01-20 07:13:58 -08001886
1887 ~BweObserver() {}
1888
nisseef8b61e2016-04-29 06:09:15 -07001889 test::PacketTransport* CreateReceiveTransport() override {
stefan32f81542016-01-20 07:13:58 -08001890 receive_transport_ = new test::PacketTransport(
1891 nullptr, this, test::PacketTransport::kReceiver,
1892 FakeNetworkPipe::Config());
1893 return receive_transport_;
1894 }
1895
1896 Call::Config GetSenderCallConfig() override {
1897 Call::Config config;
1898 // Set a high start bitrate to reduce the test completion time.
1899 config.bitrate_config.start_bitrate_bps = remb_bitrate_bps_;
1900 return config;
1901 }
1902
1903 void ModifyVideoConfigs(
1904 VideoSendStream::Config* send_config,
1905 std::vector<VideoReceiveStream::Config>* receive_configs,
1906 VideoEncoderConfig* encoder_config) override {
1907 ASSERT_EQ(1u, send_config->rtp.ssrcs.size());
1908 send_config->rtp.extensions.clear();
1909 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001910 RtpExtension(RtpExtension::kTransportSequenceNumberUri,
stefan32f81542016-01-20 07:13:58 -08001911 test::kTransportSequenceNumberExtensionId));
1912 sender_ssrc_ = send_config->rtp.ssrcs[0];
1913
1914 encoder_config->streams[0].max_bitrate_bps =
1915 encoder_config->streams[0].target_bitrate_bps = 2000000;
1916
1917 ASSERT_EQ(1u, receive_configs->size());
1918 (*receive_configs)[0].rtp.remb = false;
1919 (*receive_configs)[0].rtp.transport_cc = true;
1920 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1921 RtpRtcp::Configuration config;
1922 config.receiver_only = true;
1923 config.clock = clock_;
1924 config.outgoing_transport = receive_transport_;
Erik Språng737336d2016-07-29 12:59:36 +02001925 config.retransmission_rate_limiter = &retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08001926 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
1927 rtp_rtcp_->SetRemoteSSRC((*receive_configs)[0].rtp.remote_ssrc);
1928 rtp_rtcp_->SetSSRC((*receive_configs)[0].rtp.local_ssrc);
1929 rtp_rtcp_->SetREMBStatus(true);
1930 rtp_rtcp_->SetSendingStatus(true);
1931 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
1932 }
1933
1934 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1935 sender_call_ = sender_call;
1936 }
1937
1938 static bool BitrateStatsPollingThread(void* obj) {
1939 return static_cast<BweObserver*>(obj)->PollStats();
1940 }
1941
1942 bool PollStats() {
1943 if (sender_call_) {
1944 Call::Stats stats = sender_call_->GetStats();
1945 switch (state_) {
1946 case kWaitForFirstRampUp:
1947 if (stats.send_bandwidth_bps >= remb_bitrate_bps_) {
1948 state_ = kWaitForRemb;
1949 remb_bitrate_bps_ /= 2;
1950 rtp_rtcp_->SetREMBData(
1951 remb_bitrate_bps_,
1952 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
1953 rtp_rtcp_->SendRTCP(kRtcpRr);
1954 }
1955 break;
1956
1957 case kWaitForRemb:
1958 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
1959 state_ = kWaitForSecondRampUp;
1960 remb_bitrate_bps_ *= 2;
1961 rtp_rtcp_->SetREMBData(
1962 remb_bitrate_bps_,
1963 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
1964 rtp_rtcp_->SendRTCP(kRtcpRr);
1965 }
1966 break;
1967
1968 case kWaitForSecondRampUp:
1969 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
1970 observation_complete_.Set();
1971 }
1972 break;
1973 }
1974 }
1975
1976 return !event_.Wait(1000);
1977 }
1978
1979 void PerformTest() override {
1980 poller_thread_.Start();
1981 EXPECT_TRUE(Wait())
1982 << "Timed out while waiting for bitrate to change according to REMB.";
1983 poller_thread_.Stop();
1984 }
1985
1986 private:
1987 enum TestState { kWaitForFirstRampUp, kWaitForRemb, kWaitForSecondRampUp };
1988
1989 Call* sender_call_;
1990 Clock* const clock_;
1991 uint32_t sender_ssrc_;
1992 int remb_bitrate_bps_;
kwiberg27f982b2016-03-01 11:52:33 -08001993 std::unique_ptr<RtpRtcp> rtp_rtcp_;
stefan32f81542016-01-20 07:13:58 -08001994 test::PacketTransport* receive_transport_;
1995 rtc::Event event_;
1996 rtc::PlatformThread poller_thread_;
1997 TestState state_;
Erik Språng737336d2016-07-29 12:59:36 +02001998 RateLimiter retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08001999 } test;
2000
2001 RunBaseTest(&test);
2002}
2003
Åsa Persson352b2d72015-04-15 18:00:40 +02002004TEST_F(EndToEndTest, VerifyNackStats) {
2005 static const int kPacketNumberToDrop = 200;
2006 class NackObserver : public test::EndToEndTest {
2007 public:
2008 NackObserver()
2009 : EndToEndTest(kLongTimeoutMs),
2010 sent_rtp_packets_(0),
2011 dropped_rtp_packet_(0),
2012 dropped_rtp_packet_requested_(false),
2013 send_stream_(nullptr),
2014 start_runtime_ms_(-1) {}
2015
2016 private:
2017 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002018 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002019 if (++sent_rtp_packets_ == kPacketNumberToDrop) {
kwiberg27f982b2016-03-01 11:52:33 -08002020 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
Åsa Persson352b2d72015-04-15 18:00:40 +02002021 RTPHeader header;
2022 EXPECT_TRUE(parser->Parse(packet, length, &header));
2023 dropped_rtp_packet_ = header.sequenceNumber;
2024 return DROP_PACKET;
2025 }
2026 VerifyStats();
2027 return SEND_PACKET;
2028 }
2029
2030 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002031 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002032 test::RtcpPacketParser rtcp_parser;
2033 rtcp_parser.Parse(packet, length);
2034 std::vector<uint16_t> nacks = rtcp_parser.nack_item()->last_nack_list();
2035 if (!nacks.empty() && std::find(
2036 nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) {
2037 dropped_rtp_packet_requested_ = true;
2038 }
2039 return SEND_PACKET;
2040 }
2041
stefan608213e2015-11-01 14:56:10 -08002042 void VerifyStats() EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002043 if (!dropped_rtp_packet_requested_)
2044 return;
2045 int send_stream_nack_packets = 0;
2046 int receive_stream_nack_packets = 0;
2047 VideoSendStream::Stats stats = send_stream_->GetStats();
2048 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
2049 stats.substreams.begin(); it != stats.substreams.end(); ++it) {
2050 const VideoSendStream::StreamStats& stream_stats = it->second;
2051 send_stream_nack_packets +=
2052 stream_stats.rtcp_packet_type_counts.nack_packets;
2053 }
2054 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2055 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2056 receive_stream_nack_packets +=
2057 stats.rtcp_packet_type_counts.nack_packets;
2058 }
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002059 if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002060 // NACK packet sent on receive stream and received on sent stream.
2061 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002062 observation_complete_.Set();
Åsa Persson352b2d72015-04-15 18:00:40 +02002063 }
2064 }
2065
2066 bool MinMetricRunTimePassed() {
2067 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2068 if (start_runtime_ms_ == -1) {
2069 start_runtime_ms_ = now;
2070 return false;
2071 }
2072 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2073 return elapsed_sec > metrics::kMinRunTimeInSeconds;
2074 }
2075
stefanff483612015-12-21 03:14:00 -08002076 void ModifyVideoConfigs(
2077 VideoSendStream::Config* send_config,
2078 std::vector<VideoReceiveStream::Config>* receive_configs,
2079 VideoEncoderConfig* encoder_config) override {
Åsa Persson352b2d72015-04-15 18:00:40 +02002080 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2081 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2082 }
2083
stefanff483612015-12-21 03:14:00 -08002084 void OnVideoStreamsCreated(
Åsa Persson352b2d72015-04-15 18:00:40 +02002085 VideoSendStream* send_stream,
2086 const std::vector<VideoReceiveStream*>& receive_streams) override {
2087 send_stream_ = send_stream;
2088 receive_streams_ = receive_streams;
2089 }
2090
2091 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002092 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson352b2d72015-04-15 18:00:40 +02002093 }
2094
stefan608213e2015-11-01 14:56:10 -08002095 rtc::CriticalSection crit_;
Åsa Persson352b2d72015-04-15 18:00:40 +02002096 uint64_t sent_rtp_packets_;
stefan608213e2015-11-01 14:56:10 -08002097 uint16_t dropped_rtp_packet_ GUARDED_BY(&crit_);
2098 bool dropped_rtp_packet_requested_ GUARDED_BY(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002099 std::vector<VideoReceiveStream*> receive_streams_;
2100 VideoSendStream* send_stream_;
2101 int64_t start_runtime_ms_;
2102 } test;
2103
asapersson01d70a32016-05-20 06:29:46 -07002104 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002105 RunBaseTest(&test);
Åsa Persson352b2d72015-04-15 18:00:40 +02002106
asapersson01d70a32016-05-20 06:29:46 -07002107 EXPECT_EQ(
2108 1, metrics::NumSamples("WebRTC.Video.UniqueNackRequestsSentInPercent"));
2109 EXPECT_EQ(1, metrics::NumSamples(
2110 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
2111 EXPECT_GT(metrics::MinSample("WebRTC.Video.NackPacketsSentPerMinute"), 0);
Åsa Persson352b2d72015-04-15 18:00:40 +02002112}
2113
sprangb4a1ae52015-12-03 08:10:08 -08002114void EndToEndTest::VerifyHistogramStats(bool use_rtx,
2115 bool use_red,
2116 bool screenshare) {
tommi2e82f382016-06-21 00:26:43 -07002117 class StatsObserver : public test::EndToEndTest,
2118 public rtc::VideoSinkInterface<VideoFrame> {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002119 public:
sprangb4a1ae52015-12-03 08:10:08 -08002120 StatsObserver(bool use_rtx, bool use_red, bool screenshare)
Åsa Persson3c391cb2015-04-27 10:09:49 +02002121 : EndToEndTest(kLongTimeoutMs),
2122 use_rtx_(use_rtx),
2123 use_red_(use_red),
sprangb4a1ae52015-12-03 08:10:08 -08002124 screenshare_(screenshare),
Peter Boström39593972016-02-15 11:27:15 +01002125 // This test uses NACK, so to send FEC we can't use a fake encoder.
2126 vp8_encoder_(
2127 use_red ? VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)
2128 : nullptr),
Åsa Persson3c391cb2015-04-27 10:09:49 +02002129 sender_call_(nullptr),
2130 receiver_call_(nullptr),
2131 start_runtime_ms_(-1) {}
2132
2133 private:
tommi2e82f382016-06-21 00:26:43 -07002134 void OnFrame(const VideoFrame& video_frame) override {}
2135
Åsa Persson3c391cb2015-04-27 10:09:49 +02002136 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2137 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002138 observation_complete_.Set();
Åsa Persson3c391cb2015-04-27 10:09:49 +02002139
stefanf116bd02015-10-27 08:29:42 -07002140 return SEND_PACKET;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002141 }
2142
2143 bool MinMetricRunTimePassed() {
2144 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2145 if (start_runtime_ms_ == -1) {
2146 start_runtime_ms_ = now;
2147 return false;
2148 }
2149 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2150 return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
2151 }
2152
stefanff483612015-12-21 03:14:00 -08002153 void ModifyVideoConfigs(
2154 VideoSendStream::Config* send_config,
2155 std::vector<VideoReceiveStream::Config>* receive_configs,
2156 VideoEncoderConfig* encoder_config) override {
stefana23fc622016-07-28 07:56:38 -07002157 static const int kExtensionId = 8;
2158 send_config->rtp.extensions.push_back(RtpExtension(
2159 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
2160 (*receive_configs)[0].rtp.extensions.push_back(RtpExtension(
2161 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002162 // NACK
2163 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2164 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
tommi2e82f382016-06-21 00:26:43 -07002165 (*receive_configs)[0].renderer = this;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002166 // FEC
2167 if (use_red_) {
2168 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
2169 send_config->rtp.fec.red_payload_type = kRedPayloadType;
Peter Boström39593972016-02-15 11:27:15 +01002170 send_config->encoder_settings.encoder = vp8_encoder_.get();
2171 send_config->encoder_settings.payload_name = "VP8";
2172 (*receive_configs)[0].decoders[0].payload_name = "VP8";
Åsa Persson3c391cb2015-04-27 10:09:49 +02002173 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
2174 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
2175 }
2176 // RTX
2177 if (use_rtx_) {
2178 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
2179 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002180 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002181 kSendRtxSsrcs[0];
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002182 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002183 kSendRtxPayloadType;
2184 }
sprangb4a1ae52015-12-03 08:10:08 -08002185 encoder_config->content_type =
2186 screenshare_ ? VideoEncoderConfig::ContentType::kScreen
2187 : VideoEncoderConfig::ContentType::kRealtimeVideo;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002188 }
2189
2190 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2191 sender_call_ = sender_call;
2192 receiver_call_ = receiver_call;
2193 }
2194
Åsa Persson3c391cb2015-04-27 10:09:49 +02002195 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002196 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson3c391cb2015-04-27 10:09:49 +02002197 }
2198
sprangb4a1ae52015-12-03 08:10:08 -08002199 const bool use_rtx_;
2200 const bool use_red_;
2201 const bool screenshare_;
kwiberg27f982b2016-03-01 11:52:33 -08002202 const std::unique_ptr<VideoEncoder> vp8_encoder_;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002203 Call* sender_call_;
2204 Call* receiver_call_;
2205 int64_t start_runtime_ms_;
sprangb4a1ae52015-12-03 08:10:08 -08002206 } test(use_rtx, use_red, screenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002207
asapersson01d70a32016-05-20 06:29:46 -07002208 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002209 RunBaseTest(&test);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002210
stefan91d92602015-11-11 10:13:02 -08002211 // Delete the call for Call stats to be reported.
stefan18adf0a2015-11-17 06:24:56 -08002212 sender_call_.reset();
stefan91d92602015-11-11 10:13:02 -08002213 receiver_call_.reset();
2214
sprangb4a1ae52015-12-03 08:10:08 -08002215 std::string video_prefix =
2216 screenshare ? "WebRTC.Video.Screenshare." : "WebRTC.Video.";
2217
Åsa Persson3c391cb2015-04-27 10:09:49 +02002218 // Verify that stats have been updated once.
asapersson4374a092016-07-27 00:39:09 -07002219 EXPECT_EQ(2, metrics::NumSamples("WebRTC.Call.LifetimeInSeconds"));
asapersson01d70a32016-05-20 06:29:46 -07002220 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
2221 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.RtcpBitrateReceivedInBps"));
2222 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.BitrateReceivedInKbps"));
2223 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.EstimatedSendBitrateInKbps"));
2224 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.PacerBitrateInKbps"));
2225
asapersson4374a092016-07-27 00:39:09 -07002226 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
2227 EXPECT_EQ(1,
2228 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
2229
asapersson01d70a32016-05-20 06:29:46 -07002230 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
stefan91d92602015-11-11 10:13:02 -08002231 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002232 metrics::NumSamples(video_prefix + "NackPacketsReceivedPerMinute"));
2233 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
asaperssond89920b2015-07-22 06:52:00 -07002234 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002235 metrics::NumSamples(video_prefix + "FirPacketsReceivedPerMinute"));
2236 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
sprangb4a1ae52015-12-03 08:10:08 -08002237 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002238 metrics::NumSamples(video_prefix + "PliPacketsReceivedPerMinute"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002239
asapersson01d70a32016-05-20 06:29:46 -07002240 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "KeyFramesSentInPermille"));
2241 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
2242
2243 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentPacketsLostInPercent"));
2244 EXPECT_EQ(1,
2245 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
2246
2247 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputWidthInPixels"));
2248 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputHeightInPixels"));
2249 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentWidthInPixels"));
2250 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentHeightInPixels"));
2251 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
2252 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
2253
2254 EXPECT_EQ(1, metrics::NumEvents(
2255 video_prefix + "InputWidthInPixels",
2256 static_cast<int>(video_encoder_config_.streams[0].width)));
2257 EXPECT_EQ(1, metrics::NumEvents(
2258 video_prefix + "InputHeightInPixels",
2259 static_cast<int>(video_encoder_config_.streams[0].height)));
2260 EXPECT_EQ(1, metrics::NumEvents(
2261 video_prefix + "SentWidthInPixels",
2262 static_cast<int>(video_encoder_config_.streams[0].width)));
2263 EXPECT_EQ(1, metrics::NumEvents(
2264 video_prefix + "SentHeightInPixels",
2265 static_cast<int>(video_encoder_config_.streams[0].height)));
2266 EXPECT_EQ(1, metrics::NumEvents(
2267 "WebRTC.Video.ReceivedWidthInPixels",
2268 static_cast<int>(video_encoder_config_.streams[0].width)));
2269 EXPECT_EQ(1, metrics::NumEvents(
2270 "WebRTC.Video.ReceivedHeightInPixels",
2271 static_cast<int>(video_encoder_config_.streams[0].height)));
2272
2273 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputFramesPerSecond"));
2274 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentFramesPerSecond"));
2275 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
2276 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
2277
2278 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
2279 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
2280 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
2281 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
2282
2283 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
2284
2285 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EncodeTimeInMs"));
2286 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
2287
2288 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "BitrateSentInKbps"));
2289 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateReceivedInKbps"));
2290 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "MediaBitrateSentInKbps"));
2291 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateReceivedInKbps"));
2292 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PaddingBitrateSentInKbps"));
2293 EXPECT_EQ(1,
2294 metrics::NumSamples("WebRTC.Video.PaddingBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002295 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002296 1, metrics::NumSamples(video_prefix + "RetransmittedBitrateSentInKbps"));
2297 EXPECT_EQ(1, metrics::NumSamples(
2298 "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002299
asapersson01d70a32016-05-20 06:29:46 -07002300 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendDelayInMs"));
2301 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayInMs"));
2302 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayMaxInMs"));
asapersson6f14be82015-11-16 00:40:49 -08002303
Åsa Persson3c391cb2015-04-27 10:09:49 +02002304 int num_rtx_samples = use_rtx ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002305 EXPECT_EQ(num_rtx_samples,
2306 metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2307 EXPECT_EQ(num_rtx_samples,
2308 metrics::NumSamples("WebRTC.Video.RtxBitrateReceivedInKbps"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002309
2310 int num_red_samples = use_red ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002311 EXPECT_EQ(num_red_samples,
2312 metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2313 EXPECT_EQ(num_red_samples,
2314 metrics::NumSamples("WebRTC.Video.FecBitrateReceivedInKbps"));
2315 EXPECT_EQ(num_red_samples,
2316 metrics::NumSamples("WebRTC.Video.ReceivedFecPacketsInPercent"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002317}
2318
2319TEST_F(EndToEndTest, VerifyHistogramStatsWithRtx) {
2320 const bool kEnabledRtx = true;
2321 const bool kEnabledRed = false;
sprangb4a1ae52015-12-03 08:10:08 -08002322 const bool kScreenshare = false;
2323 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002324}
2325
2326TEST_F(EndToEndTest, VerifyHistogramStatsWithRed) {
2327 const bool kEnabledRtx = false;
2328 const bool kEnabledRed = true;
sprangb4a1ae52015-12-03 08:10:08 -08002329 const bool kScreenshare = false;
2330 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
2331}
2332
2333TEST_F(EndToEndTest, VerifyHistogramStatsWithScreenshare) {
2334 const bool kEnabledRtx = false;
2335 const bool kEnabledRed = false;
2336 const bool kScreenshare = true;
2337 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002338}
2339
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002340void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
2341 static const int kNumRtcpReportPacketsToObserve = 5;
2342 class RtcpXrObserver : public test::EndToEndTest {
2343 public:
2344 explicit RtcpXrObserver(bool enable_rrtr)
2345 : EndToEndTest(kDefaultTimeoutMs),
2346 enable_rrtr_(enable_rrtr),
2347 sent_rtcp_sr_(0),
2348 sent_rtcp_rr_(0),
2349 sent_rtcp_rrtr_(0),
2350 sent_rtcp_dlrr_(0) {}
2351
2352 private:
2353 // Receive stream should send RR packets (and RRTR packets if enabled).
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002354 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002355 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002356 RTCPUtility::RTCPParserV2 parser(packet, length, true);
2357 EXPECT_TRUE(parser.IsValid());
2358
2359 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02002360 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
2361 if (packet_type == RTCPUtility::RTCPPacketTypes::kRr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002362 ++sent_rtcp_rr_;
2363 } else if (packet_type ==
Erik Språng242e22b2015-05-11 10:17:43 +02002364 RTCPUtility::RTCPPacketTypes::kXrReceiverReferenceTime) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002365 ++sent_rtcp_rrtr_;
2366 }
Erik Språng242e22b2015-05-11 10:17:43 +02002367 EXPECT_NE(packet_type, RTCPUtility::RTCPPacketTypes::kSr);
2368 EXPECT_NE(packet_type,
2369 RTCPUtility::RTCPPacketTypes::kXrDlrrReportBlockItem);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002370 packet_type = parser.Iterate();
2371 }
2372 return SEND_PACKET;
2373 }
2374 // Send stream should send SR packets (and DLRR packets if enabled).
nisseef8b61e2016-04-29 06:09:15 -07002375 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002376 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002377 RTCPUtility::RTCPParserV2 parser(packet, length, true);
2378 EXPECT_TRUE(parser.IsValid());
2379
2380 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02002381 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
2382 if (packet_type == RTCPUtility::RTCPPacketTypes::kSr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002383 ++sent_rtcp_sr_;
Erik Språng242e22b2015-05-11 10:17:43 +02002384 } else if (packet_type ==
2385 RTCPUtility::RTCPPacketTypes::kXrDlrrReportBlockItem) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002386 ++sent_rtcp_dlrr_;
2387 }
Erik Språng242e22b2015-05-11 10:17:43 +02002388 EXPECT_NE(packet_type,
2389 RTCPUtility::RTCPPacketTypes::kXrReceiverReferenceTime);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002390 packet_type = parser.Iterate();
2391 }
2392 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
2393 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve) {
2394 if (enable_rrtr_) {
2395 EXPECT_GT(sent_rtcp_rrtr_, 0);
2396 EXPECT_GT(sent_rtcp_dlrr_, 0);
2397 } else {
2398 EXPECT_EQ(0, sent_rtcp_rrtr_);
2399 EXPECT_EQ(0, sent_rtcp_dlrr_);
2400 }
Peter Boström5811a392015-12-10 13:02:50 +01002401 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002402 }
2403 return SEND_PACKET;
2404 }
2405
stefanff483612015-12-21 03:14:00 -08002406 void ModifyVideoConfigs(
2407 VideoSendStream::Config* send_config,
2408 std::vector<VideoReceiveStream::Config>* receive_configs,
2409 VideoEncoderConfig* encoder_config) override {
pbosda903ea2015-10-02 02:36:56 -07002410 (*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002411 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
2412 enable_rrtr_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002413 }
2414
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002415 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002416 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002417 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
2418 }
2419
stefan608213e2015-11-01 14:56:10 -08002420 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002421 bool enable_rrtr_;
2422 int sent_rtcp_sr_;
stefan608213e2015-11-01 14:56:10 -08002423 int sent_rtcp_rr_ GUARDED_BY(&crit_);
2424 int sent_rtcp_rrtr_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002425 int sent_rtcp_dlrr_;
2426 } test(enable_rrtr);
2427
stefane74eef12016-01-08 06:47:13 -08002428 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002429}
2430
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002431void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
2432 bool send_single_ssrc_first) {
2433 class SendsSetSsrcs : public test::EndToEndTest {
2434 public:
2435 SendsSetSsrcs(const uint32_t* ssrcs,
2436 size_t num_ssrcs,
2437 bool send_single_ssrc_first)
2438 : EndToEndTest(kDefaultTimeoutMs),
2439 num_ssrcs_(num_ssrcs),
2440 send_single_ssrc_first_(send_single_ssrc_first),
2441 ssrcs_to_observe_(num_ssrcs),
sprang867fb522015-08-03 04:38:41 -07002442 expect_single_ssrc_(send_single_ssrc_first),
2443 send_stream_(nullptr) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002444 for (size_t i = 0; i < num_ssrcs; ++i)
2445 valid_ssrcs_[ssrcs[i]] = true;
2446 }
2447
2448 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002449 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002450 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002451 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002452
2453 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
2454 << "Received unknown SSRC: " << header.ssrc;
2455
2456 if (!valid_ssrcs_[header.ssrc])
Peter Boström5811a392015-12-10 13:02:50 +01002457 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002458
2459 if (!is_observed_[header.ssrc]) {
2460 is_observed_[header.ssrc] = true;
2461 --ssrcs_to_observe_;
2462 if (expect_single_ssrc_) {
2463 expect_single_ssrc_ = false;
Peter Boström5811a392015-12-10 13:02:50 +01002464 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002465 }
2466 }
2467
2468 if (ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002469 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002470
2471 return SEND_PACKET;
2472 }
2473
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002474 size_t GetNumVideoStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002475
stefanff483612015-12-21 03:14:00 -08002476 void ModifyVideoConfigs(
2477 VideoSendStream::Config* send_config,
2478 std::vector<VideoReceiveStream::Config>* receive_configs,
2479 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002480 if (num_ssrcs_ > 1) {
2481 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002482 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2483 encoder_config->streams[i].min_bitrate_bps = 10000;
2484 encoder_config->streams[i].target_bitrate_bps = 15000;
2485 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002486 }
2487 }
2488
perkj8eb37a32016-08-16 02:40:55 -07002489 video_encoder_config_all_streams_ = *encoder_config;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002490 if (send_single_ssrc_first_)
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002491 encoder_config->streams.resize(1);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002492 }
2493
stefanff483612015-12-21 03:14:00 -08002494 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002495 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002496 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002497 send_stream_ = send_stream;
2498 }
2499
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002500 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002501 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2502 << (send_single_ssrc_first_ ? "first SSRC."
2503 : "SSRCs.");
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002504
2505 if (send_single_ssrc_first_) {
2506 // Set full simulcast and continue with the rest of the SSRCs.
stefanff483612015-12-21 03:14:00 -08002507 send_stream_->ReconfigureVideoEncoder(
perkj8eb37a32016-08-16 02:40:55 -07002508 video_encoder_config_all_streams_);
Peter Boström5811a392015-12-10 13:02:50 +01002509 EXPECT_TRUE(Wait()) << "Timed out while waiting on additional SSRCs.";
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002510 }
2511 }
2512
2513 private:
2514 std::map<uint32_t, bool> valid_ssrcs_;
2515 std::map<uint32_t, bool> is_observed_;
2516
2517 const size_t num_ssrcs_;
2518 const bool send_single_ssrc_first_;
2519
2520 size_t ssrcs_to_observe_;
2521 bool expect_single_ssrc_;
2522
2523 VideoSendStream* send_stream_;
stefanff483612015-12-21 03:14:00 -08002524 VideoEncoderConfig video_encoder_config_all_streams_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002525 } test(kVideoSendSsrcs, num_ssrcs, send_single_ssrc_first);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002526
stefane74eef12016-01-08 06:47:13 -08002527 RunBaseTest(&test);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002528}
2529
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002530TEST_F(EndToEndTest, ReportsSetEncoderRates) {
2531 class EncoderRateStatsTest : public test::EndToEndTest,
2532 public test::FakeEncoder {
2533 public:
2534 EncoderRateStatsTest()
2535 : EndToEndTest(kDefaultTimeoutMs),
sprang867fb522015-08-03 04:38:41 -07002536 FakeEncoder(Clock::GetRealTimeClock()),
2537 send_stream_(nullptr),
2538 bitrate_kbps_(0) {}
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002539
stefanff483612015-12-21 03:14:00 -08002540 void OnVideoStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002541 VideoSendStream* send_stream,
2542 const std::vector<VideoReceiveStream*>& receive_streams) override {
2543 send_stream_ = send_stream;
2544 }
2545
stefanff483612015-12-21 03:14:00 -08002546 void ModifyVideoConfigs(
2547 VideoSendStream::Config* send_config,
2548 std::vector<VideoReceiveStream::Config>* receive_configs,
2549 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002550 send_config->encoder_settings.encoder = this;
perkj57c21f92016-06-17 07:27:16 -07002551 RTC_DCHECK_EQ(1u, encoder_config->streams.size());
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002552 }
2553
2554 int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override {
2555 // Make sure not to trigger on any default zero bitrates.
2556 if (new_target_bitrate == 0)
2557 return 0;
Peter Boströmf2f82832015-05-01 13:00:41 +02002558 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002559 bitrate_kbps_ = new_target_bitrate;
Peter Boström5811a392015-12-10 13:02:50 +01002560 observation_complete_.Set();
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002561 return 0;
2562 }
2563
2564 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002565 ASSERT_TRUE(Wait())
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002566 << "Timed out while waiting for encoder SetRates() call.";
perkjf5b2e512016-07-05 08:34:04 -07002567 WaitForEncoderTargetBitrateMatchStats();
2568 send_stream_->Stop();
2569 WaitForStatsReportZeroTargetBitrate();
2570 send_stream_->Start();
2571 WaitForEncoderTargetBitrateMatchStats();
2572 }
2573
2574 void WaitForEncoderTargetBitrateMatchStats() {
Peter Boström5811a392015-12-10 13:02:50 +01002575 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002576 VideoSendStream::Stats stats = send_stream_->GetStats();
2577 {
Peter Boströmf2f82832015-05-01 13:00:41 +02002578 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002579 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
2580 static_cast<int>(bitrate_kbps_)) {
2581 return;
2582 }
2583 }
2584 SleepMs(1);
2585 }
2586 FAIL()
2587 << "Timed out waiting for stats reporting the currently set bitrate.";
2588 }
2589
perkjf5b2e512016-07-05 08:34:04 -07002590 void WaitForStatsReportZeroTargetBitrate() {
2591 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
2592 if (send_stream_->GetStats().target_media_bitrate_bps == 0) {
2593 return;
2594 }
2595 SleepMs(1);
2596 }
2597 FAIL() << "Timed out waiting for stats reporting zero bitrate.";
2598 }
2599
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002600 private:
stefanf116bd02015-10-27 08:29:42 -07002601 rtc::CriticalSection crit_;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002602 VideoSendStream* send_stream_;
2603 uint32_t bitrate_kbps_ GUARDED_BY(crit_);
2604 } test;
2605
stefane74eef12016-01-08 06:47:13 -08002606 RunBaseTest(&test);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002607}
2608
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002609TEST_F(EndToEndTest, GetStats) {
2610 static const int kStartBitrateBps = 3000000;
Peter Boströmdef398832015-05-27 17:59:11 +02002611 static const int kExpectedRenderDelayMs = 20;
tommi2e82f382016-06-21 00:26:43 -07002612
2613 class ReceiveStreamRenderer : public rtc::VideoSinkInterface<VideoFrame> {
2614 public:
2615 ReceiveStreamRenderer() {}
2616
2617 private:
2618 void OnFrame(const VideoFrame& video_frame) override {}
2619 };
2620
nissed30a1112016-04-18 05:15:22 -07002621 class StatsObserver : public test::EndToEndTest,
2622 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002623 public:
stefanf116bd02015-10-27 08:29:42 -07002624 StatsObserver()
2625 : EndToEndTest(kLongTimeoutMs),
Peter Boströmc6e16e32016-02-05 14:15:53 +01002626 encoder_(Clock::GetRealTimeClock(), 10),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002627 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002628 expected_send_ssrcs_(),
Peter Boström5811a392015-12-10 13:02:50 +01002629 check_stats_event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002630
2631 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002632 Action OnSendRtp(const uint8_t* packet, size_t length) override {
sprangcd349d92016-07-13 09:11:28 -07002633 // Drop every 25th packet => 4% loss.
2634 static const int kPacketLossFrac = 25;
2635 RTPHeader header;
2636 RtpUtility::RtpHeaderParser parser(packet, length);
2637 if (parser.Parse(&header) &&
2638 expected_send_ssrcs_.find(header.ssrc) !=
2639 expected_send_ssrcs_.end() &&
2640 header.sequenceNumber % kPacketLossFrac == 0) {
2641 return DROP_PACKET;
2642 }
Peter Boström5811a392015-12-10 13:02:50 +01002643 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002644 return SEND_PACKET;
2645 }
2646
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002647 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002648 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002649 return SEND_PACKET;
2650 }
2651
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002652 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002653 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002654 return SEND_PACKET;
2655 }
2656
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002657 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002658 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002659 return SEND_PACKET;
2660 }
2661
nissed30a1112016-04-18 05:15:22 -07002662 void OnFrame(const VideoFrame& video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002663 // Ensure that we have at least 5ms send side delay.
nissed30a1112016-04-18 05:15:22 -07002664 SleepMs(5);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002665 }
2666
2667 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002668 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2669 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2670 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002671
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002672 // Make sure all fields have been populated.
2673 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
2674 // always filled for all receivers.
2675 receive_stats_filled_["IncomingRate"] |=
2676 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002677
Peter Boströmb7d9a972015-12-18 16:01:11 +01002678 send_stats_filled_["DecoderImplementationName"] |=
2679 stats.decoder_implementation_name ==
2680 test::FakeDecoder::kImplementationName;
Peter Boströmdef398832015-05-27 17:59:11 +02002681 receive_stats_filled_["RenderDelayAsHighAsExpected"] |=
2682 stats.render_delay_ms >= kExpectedRenderDelayMs;
2683
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002684 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002685
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002686 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002687
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002688 receive_stats_filled_["StatisticsUpdated"] |=
2689 stats.rtcp_stats.cumulative_lost != 0 ||
2690 stats.rtcp_stats.extended_max_sequence_number != 0 ||
2691 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002692
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002693 receive_stats_filled_["DataCountersUpdated"] |=
2694 stats.rtp_stats.transmitted.payload_bytes != 0 ||
2695 stats.rtp_stats.fec.packets != 0 ||
2696 stats.rtp_stats.transmitted.header_bytes != 0 ||
2697 stats.rtp_stats.transmitted.packets != 0 ||
2698 stats.rtp_stats.transmitted.padding_bytes != 0 ||
2699 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002700
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002701 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002702 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002703
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002704 receive_stats_filled_["FrameCounts"] |=
2705 stats.frame_counts.key_frames != 0 ||
2706 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002707
pbosbb36fdf2015-07-09 07:48:14 -07002708 receive_stats_filled_["CName"] |= !stats.c_name.empty();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002709
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002710 receive_stats_filled_["RtcpPacketTypeCount"] |=
2711 stats.rtcp_packet_type_counts.fir_packets != 0 ||
2712 stats.rtcp_packet_type_counts.nack_packets != 0 ||
2713 stats.rtcp_packet_type_counts.pli_packets != 0 ||
2714 stats.rtcp_packet_type_counts.nack_requests != 0 ||
2715 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbosf42376c2015-08-28 07:35:32 -07002716
2717 assert(stats.current_payload_type == -1 ||
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002718 stats.current_payload_type == kFakeVideoSendPayloadType);
pbosf42376c2015-08-28 07:35:32 -07002719 receive_stats_filled_["IncomingPayloadType"] |=
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002720 stats.current_payload_type == kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002721 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002722
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002723 return AllStatsFilled(receive_stats_filled_);
2724 }
2725
2726 bool CheckSendStats() {
Peter Boström74f6e9e2016-04-04 17:56:10 +02002727 RTC_DCHECK(send_stream_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002728 VideoSendStream::Stats stats = send_stream_->GetStats();
2729
2730 send_stats_filled_["NumStreams"] |=
2731 stats.substreams.size() == expected_send_ssrcs_.size();
2732
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002733 send_stats_filled_["CpuOveruseMetrics"] |=
Peter Boströme4499152016-02-05 11:13:28 +01002734 stats.avg_encode_time_ms != 0 && stats.encode_usage_percent != 0;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002735
Peter Boströmb7d9a972015-12-18 16:01:11 +01002736 send_stats_filled_["EncoderImplementationName"] |=
2737 stats.encoder_implementation_name ==
2738 test::FakeEncoder::kImplementationName;
2739
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002740 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002741 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002742 it != stats.substreams.end(); ++it) {
sprangcd349d92016-07-13 09:11:28 -07002743 if (expected_send_ssrcs_.find(it->first) == expected_send_ssrcs_.end())
2744 continue; // Probably RTX.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002745
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002746 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002747 stats.input_frame_rate != 0;
2748
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002749 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002750
2751 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
2752 stream_stats.rtcp_stats.cumulative_lost != 0 ||
2753 stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
2754 stream_stats.rtcp_stats.fraction_lost != 0;
2755
2756 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002757 stream_stats.rtp_stats.fec.packets != 0 ||
2758 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
2759 stream_stats.rtp_stats.retransmitted.packets != 0 ||
2760 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002761
sprangcd349d92016-07-13 09:11:28 -07002762 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Total",
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002763 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002764 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002765
sprangcd349d92016-07-13 09:11:28 -07002766 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Retransmit",
2767 it->first)] |=
2768 stream_stats.retransmit_bitrate_bps != 0;
2769
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002770 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002771 stream_stats.frame_counts.delta_frames != 0 ||
2772 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002773
2774 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
2775 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00002776
2777 send_stats_filled_[CompoundKey("Delay", it->first)] |=
2778 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002779
2780 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
2781 // report dropped packets.
2782 send_stats_filled_["RtcpPacketTypeCount"] |=
2783 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
2784 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
2785 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
2786 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
2787 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002788 }
2789
2790 return AllStatsFilled(send_stats_filled_);
2791 }
2792
2793 std::string CompoundKey(const char* name, uint32_t ssrc) {
2794 std::ostringstream oss;
2795 oss << name << "_" << ssrc;
2796 return oss.str();
2797 }
2798
2799 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
sprangcd349d92016-07-13 09:11:28 -07002800 for (const auto& stat : stats_map) {
2801 if (!stat.second)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002802 return false;
2803 }
2804 return true;
2805 }
2806
stefane74eef12016-01-08 06:47:13 -08002807 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
2808 FakeNetworkPipe::Config network_config;
2809 network_config.loss_percent = 5;
2810 return new test::PacketTransport(
2811 sender_call, this, test::PacketTransport::kSender, network_config);
2812 }
2813
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002814 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002815 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01002816 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002817 return config;
2818 }
2819
stefanff483612015-12-21 03:14:00 -08002820 void ModifyVideoConfigs(
2821 VideoSendStream::Config* send_config,
2822 std::vector<VideoReceiveStream::Config>* receive_configs,
2823 VideoEncoderConfig* encoder_config) override {
sprangcd349d92016-07-13 09:11:28 -07002824 // Set low rates to avoid waiting for rampup.
2825 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2826 encoder_config->streams[i].min_bitrate_bps = 10000;
2827 encoder_config->streams[i].target_bitrate_bps = 15000;
2828 encoder_config->streams[i].max_bitrate_bps = 20000;
2829 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002830 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002831 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002832
sprangcd349d92016-07-13 09:11:28 -07002833 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2834 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
2835
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002836 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002837 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002838 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002839 expected_receive_ssrcs_.push_back(
2840 (*receive_configs)[i].rtp.remote_ssrc);
Peter Boströmdef398832015-05-27 17:59:11 +02002841 (*receive_configs)[i].render_delay_ms = kExpectedRenderDelayMs;
tommi2e82f382016-06-21 00:26:43 -07002842 (*receive_configs)[i].renderer = &receive_stream_renderer_;
sprangcd349d92016-07-13 09:11:28 -07002843 (*receive_configs)[i].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2844
2845 (*receive_configs)[i].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
2846 kSendRtxSsrcs[i];
2847 (*receive_configs)[i].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
2848 kSendRtxPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002849 }
sprangcd349d92016-07-13 09:11:28 -07002850
2851 for (size_t i = 0; i < kNumSsrcs; ++i)
2852 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
2853
Peter Boströmc6e16e32016-02-05 14:15:53 +01002854 // Use a delayed encoder to make sure we see CpuOveruseMetrics stats that
2855 // are non-zero.
2856 send_config->encoder_settings.encoder = &encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002857 }
2858
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002859 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00002860
stefanff483612015-12-21 03:14:00 -08002861 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002862 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002863 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002864 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002865 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002866 }
2867
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002868 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002869 Clock* clock = Clock::GetRealTimeClock();
2870 int64_t now = clock->TimeInMilliseconds();
2871 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
2872 bool receive_ok = false;
2873 bool send_ok = false;
2874
2875 while (now < stop_time) {
2876 if (!receive_ok)
2877 receive_ok = CheckReceiveStats();
2878 if (!send_ok)
2879 send_ok = CheckSendStats();
2880
2881 if (receive_ok && send_ok)
2882 return;
2883
2884 int64_t time_until_timout_ = stop_time - now;
2885 if (time_until_timout_ > 0)
Peter Boström5811a392015-12-10 13:02:50 +01002886 check_stats_event_.Wait(time_until_timout_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002887 now = clock->TimeInMilliseconds();
2888 }
2889
2890 ADD_FAILURE() << "Timed out waiting for filled stats.";
2891 for (std::map<std::string, bool>::const_iterator it =
2892 receive_stats_filled_.begin();
2893 it != receive_stats_filled_.end();
2894 ++it) {
2895 if (!it->second) {
2896 ADD_FAILURE() << "Missing receive stats: " << it->first;
2897 }
2898 }
2899
2900 for (std::map<std::string, bool>::const_iterator it =
2901 send_stats_filled_.begin();
2902 it != send_stats_filled_.end();
2903 ++it) {
2904 if (!it->second) {
2905 ADD_FAILURE() << "Missing send stats: " << it->first;
2906 }
2907 }
2908 }
2909
Peter Boströmc6e16e32016-02-05 14:15:53 +01002910 test::DelayedEncoder encoder_;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002911 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002912 std::map<std::string, bool> receive_stats_filled_;
2913
2914 VideoSendStream* send_stream_;
2915 std::map<std::string, bool> send_stats_filled_;
2916
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002917 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002918 std::set<uint32_t> expected_send_ssrcs_;
2919 std::string expected_cname_;
2920
Peter Boström5811a392015-12-10 13:02:50 +01002921 rtc::Event check_stats_event_;
tommi2e82f382016-06-21 00:26:43 -07002922 ReceiveStreamRenderer receive_stream_renderer_;
stefanf116bd02015-10-27 08:29:42 -07002923 } test;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002924
stefane74eef12016-01-08 06:47:13 -08002925 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002926}
2927
2928TEST_F(EndToEndTest, ReceiverReferenceTimeReportEnabled) {
2929 TestXrReceiverReferenceTimeReport(true);
2930}
2931
2932TEST_F(EndToEndTest, ReceiverReferenceTimeReportDisabled) {
2933 TestXrReceiverReferenceTimeReport(false);
2934}
2935
2936TEST_F(EndToEndTest, TestReceivedRtpPacketStats) {
2937 static const size_t kNumRtpPacketsToSend = 5;
2938 class ReceivedRtpStatsObserver : public test::EndToEndTest {
2939 public:
2940 ReceivedRtpStatsObserver()
2941 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002942 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002943 sent_rtp_(0) {}
2944
2945 private:
stefanff483612015-12-21 03:14:00 -08002946 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002947 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002948 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002949 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002950 }
2951
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002952 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002953 if (sent_rtp_ >= kNumRtpPacketsToSend) {
2954 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002955 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
Peter Boström5811a392015-12-10 13:02:50 +01002956 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002957 }
2958 return DROP_PACKET;
2959 }
2960 ++sent_rtp_;
2961 return SEND_PACKET;
2962 }
2963
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002964 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002965 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002966 << "Timed out while verifying number of received RTP packets.";
2967 }
2968
2969 VideoReceiveStream* receive_stream_;
2970 uint32_t sent_rtp_;
2971 } test;
2972
stefane74eef12016-01-08 06:47:13 -08002973 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002974}
2975
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002976TEST_F(EndToEndTest, SendsSetSsrc) { TestSendsSetSsrcs(1, false); }
2977
2978TEST_F(EndToEndTest, SendsSetSimulcastSsrcs) {
2979 TestSendsSetSsrcs(kNumSsrcs, false);
2980}
2981
2982TEST_F(EndToEndTest, CanSwitchToUseAllSsrcs) {
2983 TestSendsSetSsrcs(kNumSsrcs, true);
2984}
2985
mflodman@webrtc.orgf9460682014-07-24 16:41:25 +00002986TEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002987 class ObserveRedundantPayloads: public test::EndToEndTest {
2988 public:
2989 ObserveRedundantPayloads()
2990 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00002991 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002992 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
2993 }
2994 }
2995
2996 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002997 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002998 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002999 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003000
3001 if (!registered_rtx_ssrc_[header.ssrc])
3002 return SEND_PACKET;
3003
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003004 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003005 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003006 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003007
3008 if (!packet_is_redundant_payload)
3009 return SEND_PACKET;
3010
3011 if (!observed_redundant_retransmission_[header.ssrc]) {
3012 observed_redundant_retransmission_[header.ssrc] = true;
3013 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01003014 observation_complete_.Set();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003015 }
3016
3017 return SEND_PACKET;
3018 }
3019
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003020 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003021
stefanff483612015-12-21 03:14:00 -08003022 void ModifyVideoConfigs(
3023 VideoSendStream::Config* send_config,
3024 std::vector<VideoReceiveStream::Config>* receive_configs,
3025 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003026 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00003027 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
3028 encoder_config->streams[i].min_bitrate_bps = 10000;
3029 encoder_config->streams[i].target_bitrate_bps = 15000;
3030 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003031 }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003032
3033 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003034
3035 for (size_t i = 0; i < kNumSsrcs; ++i)
3036 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00003037
3038 // Significantly higher than max bitrates for all video streams -> forcing
3039 // padding to trigger redundant padding on all RTX SSRCs.
3040 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003041 }
3042
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003043 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003044 EXPECT_TRUE(Wait())
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003045 << "Timed out while waiting for redundant payloads on all SSRCs.";
3046 }
3047
3048 private:
3049 size_t ssrcs_to_observe_;
3050 std::map<uint32_t, bool> observed_redundant_retransmission_;
3051 std::map<uint32_t, bool> registered_rtx_ssrc_;
3052 } test;
3053
stefane74eef12016-01-08 06:47:13 -08003054 RunBaseTest(&test);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003055}
3056
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003057void EndToEndTest::TestRtpStatePreservation(bool use_rtx,
3058 bool provoke_rtcpsr_before_rtp) {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003059 class RtpSequenceObserver : public test::RtpRtcpObserver {
3060 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003061 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003062 : test::RtpRtcpObserver(kDefaultTimeoutMs),
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003063 ssrcs_to_observe_(kNumSsrcs) {
3064 for (size_t i = 0; i < kNumSsrcs; ++i) {
danilchap32cd2c42016-08-01 06:58:34 -07003065 ssrc_is_rtx_[kVideoSendSsrcs[i]] = false;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003066 if (use_rtx)
danilchap32cd2c42016-08-01 06:58:34 -07003067 ssrc_is_rtx_[kSendRtxSsrcs[i]] = true;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003068 }
3069 }
3070
3071 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
Peter Boströmf2f82832015-05-01 13:00:41 +02003072 rtc::CritScope lock(&crit_);
danilchap34877ee2016-02-01 08:25:04 -08003073 ssrc_observed_.clear();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003074 ssrcs_to_observe_ = num_expected_ssrcs;
3075 }
3076
3077 private:
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003078 void ValidateTimestampGap(uint32_t ssrc,
3079 uint32_t timestamp,
3080 bool only_padding)
3081 EXCLUSIVE_LOCKS_REQUIRED(crit_) {
3082 static const int32_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
3083 auto timestamp_it = last_observed_timestamp_.find(ssrc);
3084 if (timestamp_it == last_observed_timestamp_.end()) {
3085 EXPECT_FALSE(only_padding);
3086 last_observed_timestamp_[ssrc] = timestamp;
3087 } else {
3088 // Verify timestamps are reasonably close.
3089 uint32_t latest_observed = timestamp_it->second;
3090 // Wraparound handling is unnecessary here as long as an int variable
3091 // is used to store the result.
3092 int32_t timestamp_gap = timestamp - latest_observed;
3093 EXPECT_LE(std::abs(timestamp_gap), kMaxTimestampGap)
3094 << "Gap in timestamps (" << latest_observed << " -> " << timestamp
3095 << ") too large for SSRC: " << ssrc << ".";
3096 timestamp_it->second = timestamp;
3097 }
3098 }
3099
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003100 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003101 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003102 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003103 const uint32_t ssrc = header.ssrc;
danilchap5c35cf92016-02-03 14:14:49 -08003104 const int64_t sequence_number =
3105 seq_numbers_unwrapper_.Unwrap(header.sequenceNumber);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003106 const uint32_t timestamp = header.timestamp;
danilchap34877ee2016-02-01 08:25:04 -08003107 const bool only_padding =
3108 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003109
danilchap32cd2c42016-08-01 06:58:34 -07003110 EXPECT_TRUE(ssrc_is_rtx_.find(ssrc) != ssrc_is_rtx_.end())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003111 << "Received SSRC that wasn't configured: " << ssrc;
3112
danilchap5c35cf92016-02-03 14:14:49 -08003113 static const int64_t kMaxSequenceNumberGap = 100;
3114 std::list<int64_t>* seq_numbers = &last_observed_seq_numbers_[ssrc];
3115 if (seq_numbers->empty()) {
3116 seq_numbers->push_back(sequence_number);
3117 } else {
3118 // We shouldn't get replays of previous sequence numbers.
3119 for (int64_t observed : *seq_numbers) {
3120 EXPECT_NE(observed, sequence_number)
3121 << "Received sequence number " << sequence_number
3122 << " for SSRC " << ssrc << " 2nd time.";
3123 }
3124 // Verify sequence numbers are reasonably close.
3125 int64_t latest_observed = seq_numbers->back();
3126 int64_t sequence_number_gap = sequence_number - latest_observed;
3127 EXPECT_LE(std::abs(sequence_number_gap), kMaxSequenceNumberGap)
3128 << "Gap in sequence numbers (" << latest_observed << " -> "
3129 << sequence_number << ") too large for SSRC: " << ssrc << ".";
3130 seq_numbers->push_back(sequence_number);
3131 if (seq_numbers->size() >= kMaxSequenceNumberGap) {
3132 seq_numbers->pop_front();
3133 }
3134 }
3135
danilchap32cd2c42016-08-01 06:58:34 -07003136 if (!ssrc_is_rtx_[ssrc]) {
3137 rtc::CritScope lock(&crit_);
3138 ValidateTimestampGap(ssrc, timestamp, only_padding);
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003139
danilchap32cd2c42016-08-01 06:58:34 -07003140 // Wait for media packets on all ssrcs.
3141 if (!ssrc_observed_[ssrc] && !only_padding) {
3142 ssrc_observed_[ssrc] = true;
3143 if (--ssrcs_to_observe_ == 0)
3144 observation_complete_.Set();
3145 }
danilchap34877ee2016-02-01 08:25:04 -08003146 }
3147
danilchapf4b9c772016-01-28 06:14:24 -08003148 return SEND_PACKET;
3149 }
3150
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003151 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
3152 test::RtcpPacketParser rtcp_parser;
3153 rtcp_parser.Parse(packet, length);
3154 if (rtcp_parser.sender_report()->num_packets() > 0) {
3155 uint32_t ssrc = rtcp_parser.sender_report()->Ssrc();
3156 uint32_t rtcp_timestamp = rtcp_parser.sender_report()->RtpTimestamp();
3157
3158 rtc::CritScope lock(&crit_);
3159 ValidateTimestampGap(ssrc, rtcp_timestamp, false);
3160 }
3161 return SEND_PACKET;
3162 }
3163
danilchap5c35cf92016-02-03 14:14:49 -08003164 SequenceNumberUnwrapper seq_numbers_unwrapper_;
3165 std::map<uint32_t, std::list<int64_t>> last_observed_seq_numbers_;
danilchap34877ee2016-02-01 08:25:04 -08003166 std::map<uint32_t, uint32_t> last_observed_timestamp_;
danilchap32cd2c42016-08-01 06:58:34 -07003167 std::map<uint32_t, bool> ssrc_is_rtx_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003168
Peter Boströmf2f82832015-05-01 13:00:41 +02003169 rtc::CriticalSection crit_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003170 size_t ssrcs_to_observe_ GUARDED_BY(crit_);
danilchap34877ee2016-02-01 08:25:04 -08003171 std::map<uint32_t, bool> ssrc_observed_ GUARDED_BY(crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003172 } observer(use_rtx);
3173
solenberg4fbae2b2015-08-28 04:07:10 -07003174 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003175
stefanf116bd02015-10-27 08:29:42 -07003176 test::PacketTransport send_transport(sender_call_.get(), &observer,
3177 test::PacketTransport::kSender,
3178 FakeNetworkPipe::Config());
3179 test::PacketTransport receive_transport(nullptr, &observer,
3180 test::PacketTransport::kReceiver,
3181 FakeNetworkPipe::Config());
3182 send_transport.SetReceiver(receiver_call_->Receiver());
3183 receive_transport.SetReceiver(sender_call_->Receiver());
3184
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003185 CreateSendConfig(kNumSsrcs, 0, &send_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003186
3187 if (use_rtx) {
3188 for (size_t i = 0; i < kNumSsrcs; ++i) {
stefanff483612015-12-21 03:14:00 -08003189 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003190 }
stefanff483612015-12-21 03:14:00 -08003191 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003192 }
3193
3194 // Lower bitrates so that all streams send initially.
stefanff483612015-12-21 03:14:00 -08003195 for (size_t i = 0; i < video_encoder_config_.streams.size(); ++i) {
3196 video_encoder_config_.streams[i].min_bitrate_bps = 10000;
3197 video_encoder_config_.streams[i].target_bitrate_bps = 15000;
3198 video_encoder_config_.streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003199 }
3200
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003201 // Use the same total bitrates when sending a single stream to avoid lowering
3202 // the bitrate estimate and requiring a subsequent rampup.
perkj8eb37a32016-08-16 02:40:55 -07003203 VideoEncoderConfig one_stream = video_encoder_config_;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003204 one_stream.streams.resize(1);
stefanff483612015-12-21 03:14:00 -08003205 for (size_t i = 1; i < video_encoder_config_.streams.size(); ++i) {
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003206 one_stream.streams.front().min_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003207 video_encoder_config_.streams[i].min_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003208 one_stream.streams.front().target_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003209 video_encoder_config_.streams[i].target_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003210 one_stream.streams.front().max_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003211 video_encoder_config_.streams[i].max_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003212 }
3213
stefanf116bd02015-10-27 08:29:42 -07003214 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003215
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003216 CreateVideoStreams();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003217 CreateFrameGeneratorCapturer();
3218
3219 Start();
Peter Boström5811a392015-12-10 13:02:50 +01003220 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003221 << "Timed out waiting for all SSRCs to send packets.";
3222
3223 // Test stream resetting more than once to make sure that the state doesn't
3224 // get set once (this could be due to using std::map::insert for instance).
3225 for (size_t i = 0; i < 3; ++i) {
3226 frame_generator_capturer_->Stop();
stefanff483612015-12-21 03:14:00 -08003227 sender_call_->DestroyVideoSendStream(video_send_stream_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003228
3229 // Re-create VideoSendStream with only one stream.
perkj8eb37a32016-08-16 02:40:55 -07003230 video_send_stream_ =
3231 sender_call_->CreateVideoSendStream(video_send_config_, one_stream);
stefanff483612015-12-21 03:14:00 -08003232 video_send_stream_->Start();
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003233 if (provoke_rtcpsr_before_rtp) {
3234 // Rapid Resync Request forces sending RTCP Sender Report back.
3235 // Using this request speeds up this test because then there is no need
3236 // to wait for a second for periodic Sender Report.
3237 rtcp::RapidResyncRequest force_send_sr_back_request;
3238 rtc::Buffer packet = force_send_sr_back_request.Build();
3239 static_cast<webrtc::test::DirectTransport&>(receive_transport)
3240 .SendRtcp(packet.data(), packet.size());
3241 }
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003242 CreateFrameGeneratorCapturer();
3243 frame_generator_capturer_->Start();
3244
3245 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003246 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003247
3248 // Reconfigure back to use all streams.
perkj8eb37a32016-08-16 02:40:55 -07003249 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003250 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003251 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003252 << "Timed out waiting for all SSRCs to send packets.";
3253
3254 // Reconfigure down to one stream.
perkj8eb37a32016-08-16 02:40:55 -07003255 video_send_stream_->ReconfigureVideoEncoder(one_stream);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003256 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003257 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003258
3259 // Reconfigure back to use all streams.
perkj8eb37a32016-08-16 02:40:55 -07003260 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003261 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003262 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003263 << "Timed out waiting for all SSRCs to send packets.";
3264 }
3265
stefanf116bd02015-10-27 08:29:42 -07003266 send_transport.StopSending();
3267 receive_transport.StopSending();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003268
3269 Stop();
3270 DestroyStreams();
3271}
3272
Peter Boströmfc968a22016-02-19 16:14:37 +01003273TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpState) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003274 TestRtpStatePreservation(false, false);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003275}
3276
danilchap32cd2c42016-08-01 06:58:34 -07003277TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpStatesWithRtx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003278 TestRtpStatePreservation(true, false);
3279}
3280
danilchap32cd2c42016-08-01 06:58:34 -07003281TEST_F(EndToEndTest, RestartingSendStreamKeepsRtpAndRtcpTimestampsSynced) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003282 TestRtpStatePreservation(true, true);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003283}
3284
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003285TEST_F(EndToEndTest, RespectsNetworkState) {
3286 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
3287 // down blocks until no more packets will be sent.
3288
3289 // Pacer will send from its packet list and then send required padding before
3290 // checking paused_ again. This should be enough for one round of pacing,
3291 // otherwise increase.
3292 static const int kNumAcceptedDowntimeRtp = 5;
3293 // A single RTCP may be in the pipeline.
3294 static const int kNumAcceptedDowntimeRtcp = 1;
3295 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
3296 public:
3297 NetworkStateTest()
3298 : EndToEndTest(kDefaultTimeoutMs),
3299 FakeEncoder(Clock::GetRealTimeClock()),
Peter Boström5811a392015-12-10 13:02:50 +01003300 encoded_frames_(false, false),
3301 packet_event_(false, false),
sprang867fb522015-08-03 04:38:41 -07003302 sender_call_(nullptr),
3303 receiver_call_(nullptr),
Jelena Marusiccd670222015-07-16 09:30:09 +02003304 sender_state_(kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003305 sender_rtp_(0),
3306 sender_rtcp_(0),
3307 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003308 down_frames_(0) {}
3309
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003310 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003311 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003312 ++sender_rtp_;
Peter Boström5811a392015-12-10 13:02:50 +01003313 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003314 return SEND_PACKET;
3315 }
3316
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003317 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003318 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003319 ++sender_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003320 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003321 return SEND_PACKET;
3322 }
3323
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003324 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003325 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
3326 return SEND_PACKET;
3327 }
3328
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003329 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003330 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003331 ++receiver_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003332 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003333 return SEND_PACKET;
3334 }
3335
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003336 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003337 sender_call_ = sender_call;
3338 receiver_call_ = receiver_call;
3339 }
3340
stefanff483612015-12-21 03:14:00 -08003341 void ModifyVideoConfigs(
3342 VideoSendStream::Config* send_config,
3343 std::vector<VideoReceiveStream::Config>* receive_configs,
3344 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003345 send_config->encoder_settings.encoder = this;
3346 }
3347
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003348 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003349 EXPECT_TRUE(encoded_frames_.Wait(kDefaultTimeoutMs))
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003350 << "No frames received by the encoder.";
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003351 // Wait for packets from both sender/receiver.
3352 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003353
skvlad7a43d252016-03-22 15:32:27 -07003354 // Sender-side network down for audio; there should be no effect on video
3355 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3356 WaitForPacketsOrSilence(false, false);
3357
3358 // Receiver-side network down for audio; no change expected
3359 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3360 WaitForPacketsOrSilence(false, false);
3361
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003362 // Sender-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003363 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003364 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003365 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003366 // After network goes down we shouldn't be encoding more frames.
Jelena Marusiccd670222015-07-16 09:30:09 +02003367 sender_state_ = kNetworkDown;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003368 }
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003369 // Wait for receiver-packets and no sender packets.
3370 WaitForPacketsOrSilence(true, false);
3371
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003372 // Receiver-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003373 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
3374 WaitForPacketsOrSilence(true, true);
3375
3376 // Network up for audio for both sides; video is still not expected to
3377 // start
3378 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
3379 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003380 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003381
3382 // Network back up again for both.
3383 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003384 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003385 // It's OK to encode frames again, as we're about to bring up the
3386 // network.
Jelena Marusiccd670222015-07-16 09:30:09 +02003387 sender_state_ = kNetworkUp;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003388 }
skvlad7a43d252016-03-22 15:32:27 -07003389 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
3390 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003391 WaitForPacketsOrSilence(false, false);
skvlad7a43d252016-03-22 15:32:27 -07003392
3393 // TODO(skvlad): add tests to verify that the audio streams are stopped
3394 // when the network goes down for audio once the workaround in
3395 // paced_sender.cc is removed.
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003396 }
3397
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07003398 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003399 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07003400 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003401 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003402 rtc::CritScope lock(&test_crit_);
Jelena Marusiccd670222015-07-16 09:30:09 +02003403 if (sender_state_ == kNetworkDown) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003404 ++down_frames_;
3405 EXPECT_LE(down_frames_, 1)
3406 << "Encoding more than one frame while network is down.";
3407 if (down_frames_ > 1)
Peter Boström5811a392015-12-10 13:02:50 +01003408 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003409 } else {
Peter Boström5811a392015-12-10 13:02:50 +01003410 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003411 }
3412 }
3413 return test::FakeEncoder::Encode(
3414 input_image, codec_specific_info, frame_types);
3415 }
3416
3417 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003418 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
3419 int64_t initial_time_ms = clock_->TimeInMilliseconds();
3420 int initial_sender_rtp;
3421 int initial_sender_rtcp;
3422 int initial_receiver_rtcp;
3423 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003424 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003425 initial_sender_rtp = sender_rtp_;
3426 initial_sender_rtcp = sender_rtcp_;
3427 initial_receiver_rtcp = receiver_rtcp_;
3428 }
3429 bool sender_done = false;
3430 bool receiver_done = false;
mflodmand1590b22015-12-09 07:07:59 -08003431 while (!sender_done || !receiver_done) {
Peter Boström5811a392015-12-10 13:02:50 +01003432 packet_event_.Wait(kSilenceTimeoutMs);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003433 int64_t time_now_ms = clock_->TimeInMilliseconds();
Peter Boströmf2f82832015-05-01 13:00:41 +02003434 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003435 if (sender_down) {
3436 ASSERT_LE(sender_rtp_ - initial_sender_rtp, kNumAcceptedDowntimeRtp)
3437 << "RTP sent during sender-side downtime.";
3438 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
3439 kNumAcceptedDowntimeRtcp)
3440 << "RTCP sent during sender-side downtime.";
3441 if (time_now_ms - initial_time_ms >=
3442 static_cast<int64_t>(kSilenceTimeoutMs)) {
3443 sender_done = true;
3444 }
3445 } else {
skvlad7a43d252016-03-22 15:32:27 -07003446 if (sender_rtp_ > initial_sender_rtp + kNumAcceptedDowntimeRtp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003447 sender_done = true;
3448 }
3449 if (receiver_down) {
3450 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
3451 kNumAcceptedDowntimeRtcp)
3452 << "RTCP sent during receiver-side downtime.";
3453 if (time_now_ms - initial_time_ms >=
3454 static_cast<int64_t>(kSilenceTimeoutMs)) {
3455 receiver_done = true;
3456 }
3457 } else {
skvlad7a43d252016-03-22 15:32:27 -07003458 if (receiver_rtcp_ > initial_receiver_rtcp + kNumAcceptedDowntimeRtcp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003459 receiver_done = true;
3460 }
3461 }
3462 }
3463
Peter Boströmf2f82832015-05-01 13:00:41 +02003464 rtc::CriticalSection test_crit_;
Peter Boström5811a392015-12-10 13:02:50 +01003465 rtc::Event encoded_frames_;
3466 rtc::Event packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003467 Call* sender_call_;
3468 Call* receiver_call_;
Jelena Marusiccd670222015-07-16 09:30:09 +02003469 NetworkState sender_state_ GUARDED_BY(test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003470 int sender_rtp_ GUARDED_BY(test_crit_);
3471 int sender_rtcp_ GUARDED_BY(test_crit_);
3472 int receiver_rtcp_ GUARDED_BY(test_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003473 int down_frames_ GUARDED_BY(test_crit_);
3474 } test;
3475
stefane74eef12016-01-08 06:47:13 -08003476 RunBaseTest(&test);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003477}
3478
danilchapa6a70072016-06-01 11:20:43 -07003479TEST_F(EndToEndTest, CallReportsRttForSender) {
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003480 static const int kSendDelayMs = 30;
3481 static const int kReceiveDelayMs = 70;
3482
solenberg4fbae2b2015-08-28 04:07:10 -07003483 CreateCalls(Call::Config(), Call::Config());
3484
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003485 FakeNetworkPipe::Config config;
3486 config.queue_delay_ms = kSendDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003487 test::DirectTransport sender_transport(config, sender_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003488 config.queue_delay_ms = kReceiveDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003489 test::DirectTransport receiver_transport(config, receiver_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003490 sender_transport.SetReceiver(receiver_call_->Receiver());
3491 receiver_transport.SetReceiver(sender_call_->Receiver());
3492
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003493 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07003494 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003495
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003496 CreateVideoStreams();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003497 CreateFrameGeneratorCapturer();
3498 Start();
3499
3500 int64_t start_time_ms = clock_->TimeInMilliseconds();
3501 while (true) {
3502 Call::Stats stats = sender_call_->GetStats();
3503 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
3504 clock_->TimeInMilliseconds())
3505 << "No RTT stats before timeout!";
3506 if (stats.rtt_ms != -1) {
3507 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs);
3508 break;
3509 }
3510 SleepMs(10);
3511 }
3512
3513 Stop();
3514 DestroyStreams();
3515}
3516
skvlad7a43d252016-03-22 15:32:27 -07003517void EndToEndTest::VerifyNewVideoSendStreamsRespectNetworkState(
3518 MediaType network_to_bring_down,
3519 VideoEncoder* encoder,
3520 Transport* transport) {
solenberg4fbae2b2015-08-28 04:07:10 -07003521 CreateSenderCall(Call::Config());
skvlad7a43d252016-03-22 15:32:27 -07003522 sender_call_->SignalChannelNetworkState(network_to_bring_down, kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003523
skvlad7a43d252016-03-22 15:32:27 -07003524 CreateSendConfig(1, 0, transport);
3525 video_send_config_.encoder_settings.encoder = encoder;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003526 CreateVideoStreams();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003527 CreateFrameGeneratorCapturer();
3528
3529 Start();
3530 SleepMs(kSilenceTimeoutMs);
3531 Stop();
3532
3533 DestroyStreams();
3534}
3535
skvlad7a43d252016-03-22 15:32:27 -07003536void EndToEndTest::VerifyNewVideoReceiveStreamsRespectNetworkState(
3537 MediaType network_to_bring_down,
3538 Transport* transport) {
solenberg4fbae2b2015-08-28 04:07:10 -07003539 CreateCalls(Call::Config(), Call::Config());
skvlad7a43d252016-03-22 15:32:27 -07003540 receiver_call_->SignalChannelNetworkState(network_to_bring_down,
3541 kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003542
stefanf116bd02015-10-27 08:29:42 -07003543 test::DirectTransport sender_transport(sender_call_.get());
solenberg4fbae2b2015-08-28 04:07:10 -07003544 sender_transport.SetReceiver(receiver_call_->Receiver());
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003545 CreateSendConfig(1, 0, &sender_transport);
skvlad7a43d252016-03-22 15:32:27 -07003546 CreateMatchingReceiveConfigs(transport);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003547 CreateVideoStreams();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003548 CreateFrameGeneratorCapturer();
3549
3550 Start();
3551 SleepMs(kSilenceTimeoutMs);
3552 Stop();
3553
3554 sender_transport.StopSending();
3555
3556 DestroyStreams();
3557}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00003558
skvlad7a43d252016-03-22 15:32:27 -07003559TEST_F(EndToEndTest, NewVideoSendStreamsRespectVideoNetworkDown) {
3560 class UnusedEncoder : public test::FakeEncoder {
3561 public:
3562 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
perkjfea93092016-05-14 00:58:48 -07003563
3564 int32_t InitEncode(const VideoCodec* config,
3565 int32_t number_of_cores,
3566 size_t max_payload_size) override {
3567 EXPECT_GT(config->startBitrate, 0u);
3568 return 0;
3569 }
skvlad7a43d252016-03-22 15:32:27 -07003570 int32_t Encode(const VideoFrame& input_image,
3571 const CodecSpecificInfo* codec_specific_info,
3572 const std::vector<FrameType>* frame_types) override {
3573 ADD_FAILURE() << "Unexpected frame encode.";
3574 return test::FakeEncoder::Encode(input_image, codec_specific_info,
3575 frame_types);
3576 }
3577 };
3578
3579 UnusedEncoder unused_encoder;
3580 UnusedTransport unused_transport;
3581 VerifyNewVideoSendStreamsRespectNetworkState(
3582 MediaType::VIDEO, &unused_encoder, &unused_transport);
3583}
3584
3585TEST_F(EndToEndTest, NewVideoSendStreamsIgnoreAudioNetworkDown) {
3586 class RequiredEncoder : public test::FakeEncoder {
3587 public:
3588 RequiredEncoder()
3589 : FakeEncoder(Clock::GetRealTimeClock()), encoded_frame_(false) {}
3590 ~RequiredEncoder() {
3591 if (!encoded_frame_) {
3592 ADD_FAILURE() << "Didn't encode an expected frame";
3593 }
3594 }
3595 int32_t Encode(const VideoFrame& input_image,
3596 const CodecSpecificInfo* codec_specific_info,
3597 const std::vector<FrameType>* frame_types) override {
3598 encoded_frame_ = true;
3599 return test::FakeEncoder::Encode(input_image, codec_specific_info,
3600 frame_types);
3601 }
3602
3603 private:
3604 bool encoded_frame_;
3605 };
3606
3607 RequiredTransport required_transport(true /*rtp*/, false /*rtcp*/);
3608 RequiredEncoder required_encoder;
3609 VerifyNewVideoSendStreamsRespectNetworkState(
3610 MediaType::AUDIO, &required_encoder, &required_transport);
3611}
3612
3613TEST_F(EndToEndTest, NewVideoReceiveStreamsRespectVideoNetworkDown) {
3614 UnusedTransport transport;
3615 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::VIDEO, &transport);
3616}
3617
3618TEST_F(EndToEndTest, NewVideoReceiveStreamsIgnoreAudioNetworkDown) {
3619 RequiredTransport transport(false /*rtp*/, true /*rtcp*/);
3620 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::AUDIO, &transport);
3621}
3622
Peter Boströmd7da1202015-06-05 14:09:38 +02003623void VerifyEmptyNackConfig(const NackConfig& config) {
3624 EXPECT_EQ(0, config.rtp_history_ms)
3625 << "Enabling NACK requires rtcp-fb: nack negotiation.";
3626}
3627
3628void VerifyEmptyFecConfig(const FecConfig& config) {
3629 EXPECT_EQ(-1, config.ulpfec_payload_type)
3630 << "Enabling FEC requires rtpmap: ulpfec negotiation.";
3631 EXPECT_EQ(-1, config.red_payload_type)
3632 << "Enabling FEC requires rtpmap: red negotiation.";
3633 EXPECT_EQ(-1, config.red_rtx_payload_type)
3634 << "Enabling RTX in FEC requires rtpmap: rtx negotiation.";
3635}
3636
3637TEST_F(EndToEndTest, VerifyDefaultSendConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003638 VideoSendStream::Config default_send_config(nullptr);
Peter Boströmd7da1202015-06-05 14:09:38 +02003639 EXPECT_EQ(0, default_send_config.rtp.nack.rtp_history_ms)
3640 << "Enabling NACK require rtcp-fb: nack negotiation.";
3641 EXPECT_TRUE(default_send_config.rtp.rtx.ssrcs.empty())
3642 << "Enabling RTX requires rtpmap: rtx negotiation.";
3643 EXPECT_TRUE(default_send_config.rtp.extensions.empty())
3644 << "Enabling RTP extensions require negotiation.";
3645
3646 VerifyEmptyNackConfig(default_send_config.rtp.nack);
3647 VerifyEmptyFecConfig(default_send_config.rtp.fec);
3648}
3649
3650TEST_F(EndToEndTest, VerifyDefaultReceiveConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003651 VideoReceiveStream::Config default_receive_config(nullptr);
pbosda903ea2015-10-02 02:36:56 -07003652 EXPECT_EQ(RtcpMode::kCompound, default_receive_config.rtp.rtcp_mode)
Peter Boströmd7da1202015-06-05 14:09:38 +02003653 << "Reduced-size RTCP require rtcp-rsize to be negotiated.";
3654 EXPECT_FALSE(default_receive_config.rtp.remb)
3655 << "REMB require rtcp-fb: goog-remb to be negotiated.";
3656 EXPECT_FALSE(
3657 default_receive_config.rtp.rtcp_xr.receiver_reference_time_report)
3658 << "RTCP XR settings require rtcp-xr to be negotiated.";
3659 EXPECT_TRUE(default_receive_config.rtp.rtx.empty())
3660 << "Enabling RTX requires rtpmap: rtx negotiation.";
3661 EXPECT_TRUE(default_receive_config.rtp.extensions.empty())
3662 << "Enabling RTP extensions require negotiation.";
3663
3664 VerifyEmptyNackConfig(default_receive_config.rtp.nack);
3665 VerifyEmptyFecConfig(default_receive_config.rtp.fec);
3666}
3667
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003668TEST_F(EndToEndTest, TransportSeqNumOnAudioAndVideo) {
3669 static const int kExtensionId = 8;
3670 class TransportSequenceNumberTest : public test::EndToEndTest {
3671 public:
3672 TransportSequenceNumberTest()
3673 : EndToEndTest(kDefaultTimeoutMs),
3674 video_observed_(false),
3675 audio_observed_(false) {
3676 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
3677 kExtensionId);
3678 }
3679
3680 size_t GetNumVideoStreams() const override { return 1; }
3681 size_t GetNumAudioStreams() const override { return 1; }
3682
3683 void ModifyVideoConfigs(
3684 VideoSendStream::Config* send_config,
3685 std::vector<VideoReceiveStream::Config>* receive_configs,
3686 VideoEncoderConfig* encoder_config) override {
3687 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07003688 send_config->rtp.extensions.push_back(RtpExtension(
3689 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003690 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3691 }
3692
3693 void ModifyAudioConfigs(
3694 AudioSendStream::Config* send_config,
3695 std::vector<AudioReceiveStream::Config>* receive_configs) override {
3696 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07003697 send_config->rtp.extensions.push_back(RtpExtension(
3698 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003699 (*receive_configs)[0].rtp.extensions.clear();
3700 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3701 }
3702
3703 Action OnSendRtp(const uint8_t* packet, size_t length) override {
3704 RTPHeader header;
3705 EXPECT_TRUE(parser_->Parse(packet, length, &header));
3706 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
3707 // Unwrap packet id and verify uniqueness.
3708 int64_t packet_id =
3709 unwrapper_.Unwrap(header.extension.transportSequenceNumber);
3710 EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
3711
3712 if (header.ssrc == kVideoSendSsrcs[0])
3713 video_observed_ = true;
3714 if (header.ssrc == kAudioSendSsrc)
3715 audio_observed_ = true;
3716 if (audio_observed_ && video_observed_ &&
3717 received_packet_ids_.size() == 50) {
3718 size_t packet_id_range =
3719 *received_packet_ids_.rbegin() - *received_packet_ids_.begin() + 1;
3720 EXPECT_EQ(received_packet_ids_.size(), packet_id_range);
3721 observation_complete_.Set();
3722 }
3723 return SEND_PACKET;
3724 }
3725
3726 void PerformTest() override {
3727 EXPECT_TRUE(Wait()) << "Timed out while waiting for audio and video "
3728 "packets with transport sequence number.";
3729 }
3730
3731 private:
3732 bool video_observed_;
3733 bool audio_observed_;
3734 SequenceNumberUnwrapper unwrapper_;
3735 std::set<int64_t> received_packet_ids_;
3736 } test;
3737
stefane74eef12016-01-08 06:47:13 -08003738 RunBaseTest(&test);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003739}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003740} // namespace webrtc