blob: 6812467cb7062e384aae80075961261b655cdb9d [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
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000018#include "webrtc/base/checks.h"
Erik Språng6b8d3552015-09-24 15:06:57 +020019#include "webrtc/base/event.h"
palmkviste75f2042016-09-28 06:19:48 -070020#include "webrtc/base/file.h"
Erik Språng737336d2016-07-29 12:59:36 +020021#include "webrtc/base/optional.h"
brandtr35364632016-12-09 06:51:29 -080022#include "webrtc/base/random.h"
Erik Språng737336d2016-07-29 12:59:36 +020023#include "webrtc/base/rate_limiter.h"
ossuf515ab82016-12-07 04:52:58 -080024#include "webrtc/call/call.h"
pbosa96b60b2016-04-18 21:12:48 -070025#include "webrtc/common_video/include/frame_callback.h"
skvlad11a9cbf2016-10-07 11:53:05 -070026#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
sakal55d932b2016-09-30 06:19:08 -070027#include "webrtc/media/base/fakevideorenderer.h"
danilchap5c35cf92016-02-03 14:14:49 -080028#include "webrtc/modules/include/module_common_types.h"
stefan32f81542016-01-20 07:13:58 -080029#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
sprang861c55e2015-10-16 10:01:21 -070030#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
Erik Språng737336d2016-07-29 12:59:36 +020031#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h"
Danil Chapovalov70ffead2016-07-20 15:26:59 +020032#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.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"
philipel266f0a42016-11-28 08:49:07 -080046#include "webrtc/test/field_trial.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000047#include "webrtc/test/frame_generator.h"
48#include "webrtc/test/frame_generator_capturer.h"
kwibergac9f8762016-09-30 22:29:43 -070049#include "webrtc/test/gtest.h"
philipel266f0a42016-11-28 08:49:07 -080050#include "webrtc/test/gmock.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000051#include "webrtc/test/null_transport.h"
asapersson@webrtc.org37c05592015-01-28 13:58:27 +000052#include "webrtc/test/rtcp_packet_parser.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000053#include "webrtc/test/rtp_rtcp_observer.h"
54#include "webrtc/test/testsupport/fileutils.h"
55#include "webrtc/test/testsupport/perf_test.h"
charujainbf6a45b2016-11-03 04:21:42 -070056#include "webrtc/video/transport_adapter.h"
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +000057#include "webrtc/video_encoder.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000058
59namespace webrtc {
60
philipel266f0a42016-11-28 08:49:07 -080061namespace {
62const char new_jb_enabled[] = "WebRTC-NewVideoJitterBuffer/Enabled/";
63const char new_jb_disabled[] = "WebRTC-NewVideoJitterBuffer/Disabled/";
64} // anonymous namespace
65
Peter Boström5811a392015-12-10 13:02:50 +010066static const int kSilenceTimeoutMs = 2000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000067
philipel266f0a42016-11-28 08:49:07 -080068class EndToEndTest : public test::CallTest,
69 public ::testing::WithParamInterface<std::string> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000070 public:
philipel266f0a42016-11-28 08:49:07 -080071 EndToEndTest() : scoped_field_trial_(GetParam()) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000072
73 virtual ~EndToEndTest() {
stefanff483612015-12-21 03:14:00 -080074 EXPECT_EQ(nullptr, video_send_stream_);
75 EXPECT_TRUE(video_receive_streams_.empty());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000076 }
77
78 protected:
pbos2d566682015-09-28 09:59:31 -070079 class UnusedTransport : public Transport {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000080 private:
stefan1d8a5062015-10-02 03:39:33 -070081 bool SendRtp(const uint8_t* packet,
82 size_t length,
83 const PacketOptions& options) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000084 ADD_FAILURE() << "Unexpected RTP sent.";
85 return false;
86 }
87
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000088 bool SendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000089 ADD_FAILURE() << "Unexpected RTCP sent.";
90 return false;
91 }
92 };
93
skvlad7a43d252016-03-22 15:32:27 -070094 class RequiredTransport : public Transport {
95 public:
96 RequiredTransport(bool rtp_required, bool rtcp_required)
97 : need_rtp_(rtp_required), need_rtcp_(rtcp_required) {}
98 ~RequiredTransport() {
99 if (need_rtp_) {
100 ADD_FAILURE() << "Expected RTP packet not sent.";
101 }
102 if (need_rtcp_) {
103 ADD_FAILURE() << "Expected RTCP packet not sent.";
104 }
105 }
106
107 private:
108 bool SendRtp(const uint8_t* packet,
109 size_t length,
110 const PacketOptions& options) override {
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700111 rtc::CritScope lock(&crit_);
skvlad7a43d252016-03-22 15:32:27 -0700112 need_rtp_ = false;
113 return true;
114 }
115
116 bool SendRtcp(const uint8_t* packet, size_t length) override {
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700117 rtc::CritScope lock(&crit_);
skvlad7a43d252016-03-22 15:32:27 -0700118 need_rtcp_ = false;
119 return true;
120 }
121 bool need_rtp_;
122 bool need_rtcp_;
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700123 rtc::CriticalSection crit_;
skvlad7a43d252016-03-22 15:32:27 -0700124 };
125
Peter Boström39593972016-02-15 11:27:15 +0100126 void DecodesRetransmittedFrame(bool enable_rtx, bool enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000127 void ReceivesPliAndRecovers(int rtp_history_ms);
pbosda903ea2015-10-02 02:36:56 -0700128 void RespectsRtcpMode(RtcpMode rtcp_mode);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000129 void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200130 void TestRtpStatePreservation(bool use_rtx, bool provoke_rtcpsr_before_rtp);
sprangb4a1ae52015-12-03 08:10:08 -0800131 void VerifyHistogramStats(bool use_rtx, bool use_red, bool screenshare);
skvlad7a43d252016-03-22 15:32:27 -0700132 void VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -0800133 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -0700134 VideoEncoder* encoder,
135 Transport* transport);
136 void VerifyNewVideoReceiveStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -0800137 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -0700138 Transport* transport);
philipel266f0a42016-11-28 08:49:07 -0800139 test::ScopedFieldTrials scoped_field_trial_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000140};
141
philipel266f0a42016-11-28 08:49:07 -0800142INSTANTIATE_TEST_CASE_P(TestWithNewVideoJitterBuffer,
143 EndToEndTest,
144 ::testing::Values(new_jb_enabled, new_jb_disabled));
145
146TEST_P(EndToEndTest, ReceiverCanBeStartedTwice) {
skvlad11a9cbf2016-10-07 11:53:05 -0700147 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000148
solenberg4fbae2b2015-08-28 04:07:10 -0700149 test::NullTransport transport;
brandtr841de6a2016-11-15 07:10:52 -0800150 CreateSendConfig(1, 0, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700151 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000152
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100153 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000154
stefanff483612015-12-21 03:14:00 -0800155 video_receive_streams_[0]->Start();
156 video_receive_streams_[0]->Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000157
158 DestroyStreams();
159}
160
philipel266f0a42016-11-28 08:49:07 -0800161TEST_P(EndToEndTest, ReceiverCanBeStoppedTwice) {
skvlad11a9cbf2016-10-07 11:53:05 -0700162 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000163
solenberg4fbae2b2015-08-28 04:07:10 -0700164 test::NullTransport transport;
brandtr841de6a2016-11-15 07:10:52 -0800165 CreateSendConfig(1, 0, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700166 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000167
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100168 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000169
stefanff483612015-12-21 03:14:00 -0800170 video_receive_streams_[0]->Stop();
171 video_receive_streams_[0]->Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000172
173 DestroyStreams();
174}
175
philipel266f0a42016-11-28 08:49:07 -0800176TEST_P(EndToEndTest, ReceiverCanBeStoppedAndRestarted) {
sprang113bdca2016-10-11 03:10:10 -0700177 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
178
179 test::NullTransport transport;
brandtr841de6a2016-11-15 07:10:52 -0800180 CreateSendConfig(1, 0, 0, &transport);
sprang113bdca2016-10-11 03:10:10 -0700181 CreateMatchingReceiveConfigs(&transport);
182
183 CreateVideoStreams();
184
185 video_receive_streams_[0]->Stop();
186 video_receive_streams_[0]->Start();
187 video_receive_streams_[0]->Stop();
188
189 DestroyStreams();
190}
191
philipel266f0a42016-11-28 08:49:07 -0800192TEST_P(EndToEndTest, RendersSingleDelayedFrame) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000193 static const int kWidth = 320;
194 static const int kHeight = 240;
195 // This constant is chosen to be higher than the timeout in the video_render
196 // module. This makes sure that frames aren't dropped if there are no other
197 // frames in the queue.
198 static const int kDelayRenderCallbackMs = 1000;
199
nisse7ade7b32016-03-23 04:48:10 -0700200 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000201 public:
Peter Boström5811a392015-12-10 13:02:50 +0100202 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000203
nisseeb83a1a2016-03-21 01:27:56 -0700204 void OnFrame(const VideoFrame& video_frame) override { event_.Set(); }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000205
Peter Boström5811a392015-12-10 13:02:50 +0100206 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000207
Peter Boström5811a392015-12-10 13:02:50 +0100208 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000209 } renderer;
210
211 class TestFrameCallback : public I420FrameCallback {
212 public:
Peter Boström5811a392015-12-10 13:02:50 +0100213 TestFrameCallback() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000214
Peter Boström5811a392015-12-10 13:02:50 +0100215 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000216
217 private:
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700218 void FrameCallback(VideoFrame* frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000219 SleepMs(kDelayRenderCallbackMs);
Peter Boström5811a392015-12-10 13:02:50 +0100220 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000221 }
222
Peter Boström5811a392015-12-10 13:02:50 +0100223 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000224 };
225
skvlad11a9cbf2016-10-07 11:53:05 -0700226 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -0700227
stefanf116bd02015-10-27 08:29:42 -0700228 test::DirectTransport sender_transport(sender_call_.get());
229 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000230 sender_transport.SetReceiver(receiver_call_->Receiver());
231 receiver_transport.SetReceiver(sender_call_->Receiver());
232
brandtr841de6a2016-11-15 07:10:52 -0800233 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700234 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000235
236 TestFrameCallback pre_render_callback;
stefanff483612015-12-21 03:14:00 -0800237 video_receive_configs_[0].pre_render_callback = &pre_render_callback;
238 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000239
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100240 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000241 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000242
243 // Create frames that are smaller than the send width/height, this is done to
244 // check that the callbacks are done after processing video.
kwiberg27f982b2016-03-01 11:52:33 -0800245 std::unique_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000246 test::FrameGenerator::CreateChromaGenerator(kWidth, kHeight));
perkja49cbd32016-09-16 07:53:41 -0700247 test::FrameForwarder frame_forwarder;
perkj803d97f2016-11-01 11:45:46 -0700248 video_send_stream_->SetSource(
249 &frame_forwarder, VideoSendStream::DegradationPreference::kBalanced);
perkja49cbd32016-09-16 07:53:41 -0700250
251 frame_forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
Peter Boström5811a392015-12-10 13:02:50 +0100252 EXPECT_TRUE(pre_render_callback.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000253 << "Timed out while waiting for pre-render callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100254 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000255 << "Timed out while waiting for the frame to render.";
256
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000257 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000258
259 sender_transport.StopSending();
260 receiver_transport.StopSending();
261
262 DestroyStreams();
263}
264
philipel266f0a42016-11-28 08:49:07 -0800265TEST_P(EndToEndTest, TransmitsFirstFrame) {
nisse7ade7b32016-03-23 04:48:10 -0700266 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000267 public:
Peter Boström5811a392015-12-10 13:02:50 +0100268 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000269
nisseeb83a1a2016-03-21 01:27:56 -0700270 void OnFrame(const VideoFrame& video_frame) override { event_.Set(); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000271
Peter Boström5811a392015-12-10 13:02:50 +0100272 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000273
Peter Boström5811a392015-12-10 13:02:50 +0100274 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000275 } renderer;
276
skvlad11a9cbf2016-10-07 11:53:05 -0700277 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -0700278
stefanf116bd02015-10-27 08:29:42 -0700279 test::DirectTransport sender_transport(sender_call_.get());
280 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000281 sender_transport.SetReceiver(receiver_call_->Receiver());
282 receiver_transport.SetReceiver(sender_call_->Receiver());
283
brandtr841de6a2016-11-15 07:10:52 -0800284 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700285 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -0800286 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000287
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100288 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000289 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000290
kwiberg27f982b2016-03-01 11:52:33 -0800291 std::unique_ptr<test::FrameGenerator> frame_generator(
perkjfa10b552016-10-02 23:45:26 -0700292 test::FrameGenerator::CreateChromaGenerator(kDefaultWidth,
293 kDefaultHeight));
perkja49cbd32016-09-16 07:53:41 -0700294 test::FrameForwarder frame_forwarder;
perkj803d97f2016-11-01 11:45:46 -0700295 video_send_stream_->SetSource(
296 &frame_forwarder, VideoSendStream::DegradationPreference::kBalanced);
perkja49cbd32016-09-16 07:53:41 -0700297 frame_forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000298
Peter Boström5811a392015-12-10 13:02:50 +0100299 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000300 << "Timed out while waiting for the frame to render.";
301
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000302 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000303
304 sender_transport.StopSending();
305 receiver_transport.StopSending();
306
307 DestroyStreams();
308}
309
Perba7dc722016-04-19 15:01:23 +0200310class CodecObserver : public test::EndToEndTest,
nisse7ade7b32016-03-23 04:48:10 -0700311 public rtc::VideoSinkInterface<VideoFrame> {
Perba7dc722016-04-19 15:01:23 +0200312 public:
313 CodecObserver(int no_frames_to_wait_for,
314 VideoRotation rotation_to_test,
315 const std::string& payload_name,
316 webrtc::VideoEncoder* encoder,
317 webrtc::VideoDecoder* decoder)
hta9aa96882016-12-06 05:36:03 -0800318 : EndToEndTest(4 * webrtc::EndToEndTest::kDefaultTimeoutMs),
319 // TODO(hta): This timeout (120 seconds) is excessive.
320 // https://bugs.webrtc.org/6830
Perba7dc722016-04-19 15:01:23 +0200321 no_frames_to_wait_for_(no_frames_to_wait_for),
322 expected_rotation_(rotation_to_test),
323 payload_name_(payload_name),
324 encoder_(encoder),
325 decoder_(decoder),
326 frame_counter_(0) {}
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000327
Perba7dc722016-04-19 15:01:23 +0200328 void PerformTest() override {
329 EXPECT_TRUE(Wait())
330 << "Timed out while waiting for enough frames to be decoded.";
331 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000332
Perba7dc722016-04-19 15:01:23 +0200333 void ModifyVideoConfigs(
334 VideoSendStream::Config* send_config,
335 std::vector<VideoReceiveStream::Config>* receive_configs,
336 VideoEncoderConfig* encoder_config) override {
337 send_config->encoder_settings.encoder = encoder_.get();
338 send_config->encoder_settings.payload_name = payload_name_;
339 send_config->encoder_settings.payload_type = 126;
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000340
Perba7dc722016-04-19 15:01:23 +0200341 (*receive_configs)[0].renderer = this;
342 (*receive_configs)[0].decoders.resize(1);
343 (*receive_configs)[0].decoders[0].payload_type =
344 send_config->encoder_settings.payload_type;
345 (*receive_configs)[0].decoders[0].payload_name =
346 send_config->encoder_settings.payload_name;
347 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
348 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000349
Perba7dc722016-04-19 15:01:23 +0200350 void OnFrame(const VideoFrame& video_frame) override {
351 EXPECT_EQ(expected_rotation_, video_frame.rotation());
352 if (++frame_counter_ == no_frames_to_wait_for_)
353 observation_complete_.Set();
354 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000355
Perba7dc722016-04-19 15:01:23 +0200356 void OnFrameGeneratorCapturerCreated(
357 test::FrameGeneratorCapturer* frame_generator_capturer) override {
358 frame_generator_capturer->SetFakeRotation(expected_rotation_);
359 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000360
Perba7dc722016-04-19 15:01:23 +0200361 private:
362 int no_frames_to_wait_for_;
363 VideoRotation expected_rotation_;
364 std::string payload_name_;
365 std::unique_ptr<webrtc::VideoEncoder> encoder_;
366 std::unique_ptr<webrtc::VideoDecoder> decoder_;
367 int frame_counter_;
368};
369
philipel266f0a42016-11-28 08:49:07 -0800370TEST_P(EndToEndTest, SendsAndReceivesVP8) {
371 CodecObserver test(5, kVideoRotation_0, "VP8", VP8Encoder::Create(),
372 VP8Decoder::Create());
373 RunBaseTest(&test);
374}
375
376TEST_P(EndToEndTest, SendsAndReceivesVP8Rotation90) {
magjed509e4fe2016-11-18 01:34:11 -0800377 CodecObserver test(5, kVideoRotation_90, "VP8", VP8Encoder::Create(),
Perba7dc722016-04-19 15:01:23 +0200378 VP8Decoder::Create());
379 RunBaseTest(&test);
380}
381
Peter Boström12996152016-05-14 02:03:18 +0200382#if !defined(RTC_DISABLE_VP9)
philipel266f0a42016-11-28 08:49:07 -0800383TEST_P(EndToEndTest, SendsAndReceivesVP9) {
magjed509e4fe2016-11-18 01:34:11 -0800384 CodecObserver test(500, kVideoRotation_0, "VP9", VP9Encoder::Create(),
Perba7dc722016-04-19 15:01:23 +0200385 VP9Decoder::Create());
386 RunBaseTest(&test);
387}
388
philipel266f0a42016-11-28 08:49:07 -0800389TEST_P(EndToEndTest, SendsAndReceivesVP9VideoRotation90) {
magjed509e4fe2016-11-18 01:34:11 -0800390 CodecObserver test(5, kVideoRotation_90, "VP9", VP9Encoder::Create(),
Perba7dc722016-04-19 15:01:23 +0200391 VP9Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800392 RunBaseTest(&test);
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000393}
Peter Boström12996152016-05-14 02:03:18 +0200394#endif // !defined(RTC_DISABLE_VP9)
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000395
brandtr445fb8f2016-11-14 04:11:23 -0800396#if defined(WEBRTC_USE_H264)
philipel266f0a42016-11-28 08:49:07 -0800397TEST_P(EndToEndTest, SendsAndReceivesH264) {
magjedceecea42016-11-28 07:20:21 -0800398 CodecObserver test(500, kVideoRotation_0, "H264",
399 H264Encoder::Create(cricket::VideoCodec("H264")),
Perba7dc722016-04-19 15:01:23 +0200400 H264Decoder::Create());
401 RunBaseTest(&test);
402}
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000403
philipel266f0a42016-11-28 08:49:07 -0800404TEST_P(EndToEndTest, SendsAndReceivesH264VideoRotation90) {
magjedceecea42016-11-28 07:20:21 -0800405 CodecObserver test(5, kVideoRotation_90, "H264",
406 H264Encoder::Create(cricket::VideoCodec("H264")),
Perba7dc722016-04-19 15:01:23 +0200407 H264Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800408 RunBaseTest(&test);
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000409}
hta9aa96882016-12-06 05:36:03 -0800410
411TEST_P(EndToEndTest, SendsAndReceivesH264PacketizationMode0) {
412 cricket::VideoCodec codec = cricket::VideoCodec("H264");
413 codec.SetParam(cricket::kH264FmtpPacketizationMode, "0");
414 CodecObserver test(500, kVideoRotation_0, "H264", H264Encoder::Create(codec),
415 H264Decoder::Create());
416 RunBaseTest(&test);
417}
418
419TEST_P(EndToEndTest, SendsAndReceivesH264PacketizationMode1) {
420 cricket::VideoCodec codec = cricket::VideoCodec("H264");
421 codec.SetParam(cricket::kH264FmtpPacketizationMode, "1");
422 CodecObserver test(500, kVideoRotation_0, "H264", H264Encoder::Create(codec),
423 H264Decoder::Create());
424 RunBaseTest(&test);
425}
426
brandtr445fb8f2016-11-14 04:11:23 -0800427#endif // defined(WEBRTC_USE_H264)
hbosbab934b2016-01-27 01:36:03 -0800428
philipel266f0a42016-11-28 08:49:07 -0800429TEST_P(EndToEndTest, ReceiverUsesLocalSsrc) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000430 class SyncRtcpObserver : public test::EndToEndTest {
431 public:
432 SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {}
433
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000434 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
danilchap3dc929e2016-11-02 08:21:59 -0700435 test::RtcpPacketParser parser;
436 EXPECT_TRUE(parser.Parse(packet, length));
437 EXPECT_EQ(kReceiverLocalVideoSsrc, parser.sender_ssrc());
Peter Boström5811a392015-12-10 13:02:50 +0100438 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000439
440 return SEND_PACKET;
441 }
442
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000443 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100444 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000445 << "Timed out while waiting for a receiver RTCP packet to be sent.";
446 }
447 } test;
448
stefane74eef12016-01-08 06:47:13 -0800449 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000450}
451
philipel266f0a42016-11-28 08:49:07 -0800452TEST_P(EndToEndTest, ReceivesAndRetransmitsNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000453 static const int kNumberOfNacksToObserve = 2;
454 static const int kLossBurstSize = 2;
455 static const int kPacketsBetweenLossBursts = 9;
456 class NackObserver : public test::EndToEndTest {
457 public:
458 NackObserver()
459 : EndToEndTest(kLongTimeoutMs),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000460 sent_rtp_packets_(0),
461 packets_left_to_drop_(0),
462 nacks_left_(kNumberOfNacksToObserve) {}
463
464 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000465 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700466 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000467 RTPHeader header;
Peter Boström03671cb2015-12-07 15:22:24 +0100468 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000469
470 // Never drop retransmitted packets.
471 if (dropped_packets_.find(header.sequenceNumber) !=
472 dropped_packets_.end()) {
473 retransmitted_packets_.insert(header.sequenceNumber);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000474 return SEND_PACKET;
475 }
476
philipel8054c7e2017-01-10 05:19:19 -0800477 if (nacks_left_ <= 0 &&
478 retransmitted_packets_.size() == dropped_packets_.size()) {
479 observation_complete_.Set();
480 }
481
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000482 ++sent_rtp_packets_;
483
484 // Enough NACKs received, stop dropping packets.
Stefan Holmer586b19b2015-09-18 11:14:31 +0200485 if (nacks_left_ <= 0)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000486 return SEND_PACKET;
487
488 // Check if it's time for a new loss burst.
489 if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
490 packets_left_to_drop_ = kLossBurstSize;
491
Stefan Holmer01b48882015-05-05 10:21:24 +0200492 // Never drop padding packets as those won't be retransmitted.
493 if (packets_left_to_drop_ > 0 && header.paddingLength == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000494 --packets_left_to_drop_;
495 dropped_packets_.insert(header.sequenceNumber);
496 return DROP_PACKET;
497 }
498
499 return SEND_PACKET;
500 }
501
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000502 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700503 rtc::CritScope lock(&crit_);
danilchap3dc929e2016-11-02 08:21:59 -0700504 test::RtcpPacketParser parser;
505 EXPECT_TRUE(parser.Parse(packet, length));
506 nacks_left_ -= parser.nack()->num_packets();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000507 return SEND_PACKET;
508 }
509
stefanff483612015-12-21 03:14:00 -0800510 void ModifyVideoConfigs(
511 VideoSendStream::Config* send_config,
512 std::vector<VideoReceiveStream::Config>* receive_configs,
513 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000514 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000515 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000516 }
517
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000518 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100519 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000520 << "Timed out waiting for packets to be NACKed, retransmitted and "
521 "rendered.";
522 }
523
stefanf116bd02015-10-27 08:29:42 -0700524 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000525 std::set<uint16_t> dropped_packets_;
526 std::set<uint16_t> retransmitted_packets_;
527 uint64_t sent_rtp_packets_;
528 int packets_left_to_drop_;
stefanf116bd02015-10-27 08:29:42 -0700529 int nacks_left_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000530 } test;
531
stefane74eef12016-01-08 06:47:13 -0800532 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000533}
534
philipel266f0a42016-11-28 08:49:07 -0800535TEST_P(EndToEndTest, ReceivesNackAndRetransmitsAudio) {
Erik Språng737336d2016-07-29 12:59:36 +0200536 class NackObserver : public test::EndToEndTest {
537 public:
538 NackObserver()
539 : EndToEndTest(kLongTimeoutMs),
540 local_ssrc_(0),
541 remote_ssrc_(0),
542 receive_transport_(nullptr) {}
543
544 private:
545 size_t GetNumVideoStreams() const override { return 0; }
546 size_t GetNumAudioStreams() const override { return 1; }
547
548 test::PacketTransport* CreateReceiveTransport() override {
549 test::PacketTransport* receive_transport = new test::PacketTransport(
550 nullptr, this, test::PacketTransport::kReceiver,
551 FakeNetworkPipe::Config());
552 receive_transport_ = receive_transport;
553 return receive_transport;
554 }
555
556 Action OnSendRtp(const uint8_t* packet, size_t length) override {
557 RTPHeader header;
558 EXPECT_TRUE(parser_->Parse(packet, length, &header));
559
560 if (!sequence_number_to_retransmit_) {
561 sequence_number_to_retransmit_ =
562 rtc::Optional<uint16_t>(header.sequenceNumber);
563
564 // Don't ask for retransmission straight away, may be deduped in pacer.
565 } else if (header.sequenceNumber == *sequence_number_to_retransmit_) {
566 observation_complete_.Set();
567 } else {
568 // Send a NACK as often as necessary until retransmission is received.
569 rtcp::Nack nack;
danilchap822a16f2016-09-27 09:27:47 -0700570 nack.SetSenderSsrc(local_ssrc_);
571 nack.SetMediaSsrc(remote_ssrc_);
Erik Språng737336d2016-07-29 12:59:36 +0200572 uint16_t nack_list[] = {*sequence_number_to_retransmit_};
danilchap822a16f2016-09-27 09:27:47 -0700573 nack.SetPacketIds(nack_list, 1);
Erik Språng737336d2016-07-29 12:59:36 +0200574 rtc::Buffer buffer = nack.Build();
575
576 EXPECT_TRUE(receive_transport_->SendRtcp(buffer.data(), buffer.size()));
577 }
578
579 return SEND_PACKET;
580 }
581
582 void ModifyAudioConfigs(
583 AudioSendStream::Config* send_config,
584 std::vector<AudioReceiveStream::Config>* receive_configs) override {
585 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
586 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
587 local_ssrc_ = (*receive_configs)[0].rtp.local_ssrc;
588 remote_ssrc_ = (*receive_configs)[0].rtp.remote_ssrc;
589 }
590
591 void PerformTest() override {
592 EXPECT_TRUE(Wait())
593 << "Timed out waiting for packets to be NACKed, retransmitted and "
594 "rendered.";
595 }
596
597 uint32_t local_ssrc_;
598 uint32_t remote_ssrc_;
599 Transport* receive_transport_;
600 rtc::Optional<uint16_t> sequence_number_to_retransmit_;
601 } test;
602
603 RunBaseTest(&test);
604}
605
brandtrfd8d2652017-02-06 06:19:51 -0800606// Disable due to failure, see bugs.webrtc.org/7050 for
607// details.
608TEST_P(EndToEndTest, DISABLED_CanReceiveUlpfec) {
brandtr535830e2016-10-31 03:45:58 -0700609 class UlpfecRenderObserver : public test::EndToEndTest,
610 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000611 public:
brandtr535830e2016-10-31 03:45:58 -0700612 UlpfecRenderObserver()
brandtrfd8d2652017-02-06 06:19:51 -0800613 : EndToEndTest(kDefaultTimeoutMs), state_(kFirstPacket) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000614
615 private:
stefanf116bd02015-10-27 08:29:42 -0700616 Action OnSendRtp(const uint8_t* packet, size_t length) override {
617 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000618 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000619 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000620
Stefan Holmer01b48882015-05-05 10:21:24 +0200621 int encapsulated_payload_type = -1;
622 if (header.payloadType == kRedPayloadType) {
623 encapsulated_payload_type =
624 static_cast<int>(packet[header.headerLength]);
brandtrfd8d2652017-02-06 06:19:51 -0800625 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
626 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
627 } else {
628 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200629 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000630
brandtrfd8d2652017-02-06 06:19:51 -0800631 if (protected_sequence_numbers_.count(header.sequenceNumber) != 0) {
632 // Retransmitted packet, should not count.
633 protected_sequence_numbers_.erase(header.sequenceNumber);
634 auto ts_it = protected_timestamps_.find(header.timestamp);
635 EXPECT_NE(ts_it, protected_timestamps_.end());
636 protected_timestamps_.erase(ts_it);
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000637 return SEND_PACKET;
638 }
639
brandtrfd8d2652017-02-06 06:19:51 -0800640 switch (state_) {
641 case kFirstPacket:
642 state_ = kDropEveryOtherPacketUntilUlpfec;
643 break;
644 case kDropEveryOtherPacketUntilUlpfec:
645 if (encapsulated_payload_type == kUlpfecPayloadType) {
646 state_ = kDropNextMediaPacket;
647 return SEND_PACKET;
648 }
649 if (header.sequenceNumber % 2 == 0)
650 return DROP_PACKET;
651 break;
652 case kDropNextMediaPacket:
653 if (encapsulated_payload_type == kFakeVideoSendPayloadType) {
654 protected_sequence_numbers_.insert(header.sequenceNumber);
655 protected_timestamps_.insert(header.timestamp);
656 state_ = kDropEveryOtherPacketUntilUlpfec;
657 return DROP_PACKET;
658 }
659 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000660 }
661
662 return SEND_PACKET;
663 }
664
nisseeb83a1a2016-03-21 01:27:56 -0700665 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200666 rtc::CritScope lock(&crit_);
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000667 // Rendering frame with timestamp of packet that was dropped -> FEC
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000668 // protection worked.
brandtrfd8d2652017-02-06 06:19:51 -0800669 if (protected_timestamps_.count(video_frame.timestamp()) != 0)
Peter Boström5811a392015-12-10 13:02:50 +0100670 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000671 }
672
brandtrfd8d2652017-02-06 06:19:51 -0800673 enum {
674 kFirstPacket,
675 kDropEveryOtherPacketUntilUlpfec,
676 kDropNextMediaPacket,
677 } state_;
678
stefanff483612015-12-21 03:14:00 -0800679 void ModifyVideoConfigs(
680 VideoSendStream::Config* send_config,
681 std::vector<VideoReceiveStream::Config>* receive_configs,
682 VideoEncoderConfig* encoder_config) override {
brandtrfd8d2652017-02-06 06:19:51 -0800683 // TODO(pbos): Run this test with combined NACK/ULPFEC enabled as well.
684 // int rtp_history_ms = 1000;
685 // (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms;
686 // send_config->rtp.nack.rtp_history_ms = rtp_history_ms;
brandtrb5f2c3f2016-10-04 23:28:39 -0700687 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
688 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000689
brandtrb5f2c3f2016-10-04 23:28:39 -0700690 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
691 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000692 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000693 }
694
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000695 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100696 EXPECT_TRUE(Wait())
brandtr1e3dfbf2016-11-16 22:45:19 -0800697 << "Timed out waiting for dropped frames to be rendered.";
698 }
699
700 rtc::CriticalSection crit_;
brandtrfd8d2652017-02-06 06:19:51 -0800701 std::set<uint32_t> protected_sequence_numbers_ GUARDED_BY(crit_);
702 // Since several packets can have the same timestamp a multiset is used
703 // instead of a set.
704 std::multiset<uint32_t> protected_timestamps_ GUARDED_BY(crit_);
brandtr1e3dfbf2016-11-16 22:45:19 -0800705 } test;
706
707 RunBaseTest(&test);
708}
709
brandtrfa5a3682017-01-17 01:33:54 -0800710class FlexfecRenderObserver : public test::EndToEndTest,
711 public rtc::VideoSinkInterface<VideoFrame> {
712 public:
713 static constexpr uint32_t kVideoLocalSsrc = 123;
714 static constexpr uint32_t kFlexfecLocalSsrc = 456;
brandtr1e3dfbf2016-11-16 22:45:19 -0800715
brandtrfd8d2652017-02-06 06:19:51 -0800716 explicit FlexfecRenderObserver(bool expect_flexfec_rtcp)
brandtrfa5a3682017-01-17 01:33:54 -0800717 : test::EndToEndTest(test::CallTest::kDefaultTimeoutMs),
718 expect_flexfec_rtcp_(expect_flexfec_rtcp),
719 received_flexfec_rtcp_(false),
brandtrfd8d2652017-02-06 06:19:51 -0800720 random_(0xcafef00d1) {}
brandtr1e3dfbf2016-11-16 22:45:19 -0800721
brandtrfa5a3682017-01-17 01:33:54 -0800722 size_t GetNumFlexfecStreams() const override { return 1; }
brandtr1e3dfbf2016-11-16 22:45:19 -0800723
brandtrfa5a3682017-01-17 01:33:54 -0800724 private:
725 Action OnSendRtp(const uint8_t* packet, size_t length) override {
726 rtc::CritScope lock(&crit_);
727 RTPHeader header;
728 EXPECT_TRUE(parser_->Parse(packet, length, &header));
brandtr1e3dfbf2016-11-16 22:45:19 -0800729
brandtrfd8d2652017-02-06 06:19:51 -0800730 uint8_t payload_type = header.payloadType;
731 if (payload_type != test::CallTest::kFakeVideoSendPayloadType) {
732 EXPECT_EQ(test::CallTest::kFlexfecPayloadType, payload_type);
brandtr1e3dfbf2016-11-16 22:45:19 -0800733 }
734
brandtrfd8d2652017-02-06 06:19:51 -0800735 // Is this a retransmitted media packet? From the perspective of FEC, this
736 // packet is then no longer dropped, so remove it from the list of
737 // dropped packets.
738 if (payload_type == test::CallTest::kFakeVideoSendPayloadType) {
739 auto seq_num_it = dropped_sequence_numbers_.find(header.sequenceNumber);
brandtrfa5a3682017-01-17 01:33:54 -0800740 if (seq_num_it != dropped_sequence_numbers_.end()) {
741 dropped_sequence_numbers_.erase(seq_num_it);
742 auto ts_it = dropped_timestamps_.find(header.timestamp);
743 EXPECT_NE(ts_it, dropped_timestamps_.end());
744 dropped_timestamps_.erase(ts_it);
brandtrd40b0f32017-02-06 05:54:43 -0800745
brandtrfd8d2652017-02-06 06:19:51 -0800746 return SEND_PACKET;
747 }
brandtrfa5a3682017-01-17 01:33:54 -0800748 }
749
brandtrfd8d2652017-02-06 06:19:51 -0800750 // Simulate 5% packet loss. Record what media packets, and corresponding
751 // timestamps, that were dropped.
752 if (random_.Rand(1, 100) <= 5) {
753 if (payload_type == test::CallTest::kFakeVideoSendPayloadType) {
754 dropped_sequence_numbers_.insert(header.sequenceNumber);
755 dropped_timestamps_.insert(header.timestamp);
756 }
brandtrfa5a3682017-01-17 01:33:54 -0800757
758 return DROP_PACKET;
759 }
760
761 return SEND_PACKET;
762 }
763
764 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
765 test::RtcpPacketParser parser;
766
767 parser.Parse(data, length);
768 if (parser.sender_ssrc() == kFlexfecLocalSsrc) {
769 EXPECT_EQ(1, parser.receiver_report()->num_packets());
770 const std::vector<rtcp::ReportBlock>& report_blocks =
771 parser.receiver_report()->report_blocks();
772 if (!report_blocks.empty()) {
773 EXPECT_EQ(1U, report_blocks.size());
774 EXPECT_EQ(test::CallTest::kFlexfecSendSsrc,
775 report_blocks[0].source_ssrc());
brandtr1d2d7892017-01-18 00:40:07 -0800776 rtc::CritScope lock(&crit_);
brandtrfa5a3682017-01-17 01:33:54 -0800777 received_flexfec_rtcp_ = true;
778 }
779 }
780
781 return SEND_PACKET;
782 }
783
784 void OnFrame(const VideoFrame& video_frame) override {
785 rtc::CritScope lock(&crit_);
786 // Rendering frame with timestamp of packet that was dropped -> FEC
787 // protection worked.
788 auto it = dropped_timestamps_.find(video_frame.timestamp());
789 if (it != dropped_timestamps_.end()) {
790 if (!expect_flexfec_rtcp_ || received_flexfec_rtcp_) {
brandtr1e3dfbf2016-11-16 22:45:19 -0800791 observation_complete_.Set();
brandtrfa5a3682017-01-17 01:33:54 -0800792 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800793 }
brandtrfa5a3682017-01-17 01:33:54 -0800794 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800795
brandtrfa5a3682017-01-17 01:33:54 -0800796 void ModifyVideoConfigs(
797 VideoSendStream::Config* send_config,
798 std::vector<VideoReceiveStream::Config>* receive_configs,
799 VideoEncoderConfig* encoder_config) override {
800 (*receive_configs)[0].rtp.local_ssrc = kVideoLocalSsrc;
801 (*receive_configs)[0].renderer = this;
802 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800803
brandtrfa5a3682017-01-17 01:33:54 -0800804 void ModifyFlexfecConfigs(
805 std::vector<FlexfecReceiveStream::Config>* receive_configs) override {
806 (*receive_configs)[0].local_ssrc = kFlexfecLocalSsrc;
807 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000808
brandtrfa5a3682017-01-17 01:33:54 -0800809 void PerformTest() override {
810 EXPECT_TRUE(Wait())
811 << "Timed out waiting for dropped frames to be rendered.";
812 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000813
brandtrfa5a3682017-01-17 01:33:54 -0800814 rtc::CriticalSection crit_;
815 std::set<uint32_t> dropped_sequence_numbers_ GUARDED_BY(crit_);
brandtrfd8d2652017-02-06 06:19:51 -0800816 // Since several packets can have the same timestamp a multiset is used
817 // instead of a set.
brandtrfa5a3682017-01-17 01:33:54 -0800818 std::multiset<uint32_t> dropped_timestamps_ GUARDED_BY(crit_);
brandtr1d2d7892017-01-18 00:40:07 -0800819 const bool expect_flexfec_rtcp_;
820 bool received_flexfec_rtcp_ GUARDED_BY(crit_);
brandtrfa5a3682017-01-17 01:33:54 -0800821 Random random_;
822};
823
brandtrfd8d2652017-02-06 06:19:51 -0800824// Disable due to failure, see bugs.webrtc.org/7050 for
825// details.
826TEST_P(EndToEndTest, DISABLED_ReceivesFlexfec) {
827 FlexfecRenderObserver test(false);
brandtrfa5a3682017-01-17 01:33:54 -0800828 RunBaseTest(&test);
829}
830
brandtrfd8d2652017-02-06 06:19:51 -0800831// Disable due to failure, see bugs.webrtc.org/7050 for
832// details.
833TEST_P(EndToEndTest, DISABLED_ReceivesFlexfecAndSendsCorrespondingRtcp) {
834 FlexfecRenderObserver test(true);
stefane74eef12016-01-08 06:47:13 -0800835 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000836}
837
philipel266f0a42016-11-28 08:49:07 -0800838TEST_P(EndToEndTest, ReceivedUlpfecPacketsNotNacked) {
brandtr535830e2016-10-31 03:45:58 -0700839 class UlpfecNackObserver : public test::EndToEndTest {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000840 public:
brandtr535830e2016-10-31 03:45:58 -0700841 UlpfecNackObserver()
stefanf116bd02015-10-27 08:29:42 -0700842 : EndToEndTest(kDefaultTimeoutMs),
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000843 state_(kFirstPacket),
brandtr535830e2016-10-31 03:45:58 -0700844 ulpfec_sequence_number_(0),
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000845 has_last_sequence_number_(false),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200846 last_sequence_number_(0),
magjed509e4fe2016-11-18 01:34:11 -0800847 encoder_(VP8Encoder::Create()),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200848 decoder_(VP8Decoder::Create()) {}
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000849
850 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000851 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800852 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000853 RTPHeader header;
854 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000855
Stefan Holmer01b48882015-05-05 10:21:24 +0200856 int encapsulated_payload_type = -1;
857 if (header.payloadType == kRedPayloadType) {
858 encapsulated_payload_type =
859 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100860 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200861 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
862 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100863 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200864 }
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000865
866 if (has_last_sequence_number_ &&
867 !IsNewerSequenceNumber(header.sequenceNumber,
868 last_sequence_number_)) {
869 // Drop retransmitted packets.
870 return DROP_PACKET;
871 }
872 last_sequence_number_ = header.sequenceNumber;
873 has_last_sequence_number_ = true;
874
brandtr535830e2016-10-31 03:45:58 -0700875 bool ulpfec_packet = encapsulated_payload_type == kUlpfecPayloadType;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000876 switch (state_) {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000877 case kFirstPacket:
brandtr535830e2016-10-31 03:45:58 -0700878 state_ = kDropEveryOtherPacketUntilUlpfec;
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000879 break;
brandtr535830e2016-10-31 03:45:58 -0700880 case kDropEveryOtherPacketUntilUlpfec:
881 if (ulpfec_packet) {
882 state_ = kDropAllMediaPacketsUntilUlpfec;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000883 } else if (header.sequenceNumber % 2 == 0) {
884 return DROP_PACKET;
885 }
886 break;
brandtr535830e2016-10-31 03:45:58 -0700887 case kDropAllMediaPacketsUntilUlpfec:
888 if (!ulpfec_packet)
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000889 return DROP_PACKET;
brandtr535830e2016-10-31 03:45:58 -0700890 ulpfec_sequence_number_ = header.sequenceNumber;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200891 state_ = kDropOneMediaPacket;
892 break;
893 case kDropOneMediaPacket:
brandtr535830e2016-10-31 03:45:58 -0700894 if (ulpfec_packet)
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200895 return DROP_PACKET;
896 state_ = kPassOneMediaPacket;
897 return DROP_PACKET;
898 break;
899 case kPassOneMediaPacket:
brandtr535830e2016-10-31 03:45:58 -0700900 if (ulpfec_packet)
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200901 return DROP_PACKET;
902 // Pass one media packet after dropped packet after last FEC,
903 // otherwise receiver might never see a seq_no after
brandtr535830e2016-10-31 03:45:58 -0700904 // |ulpfec_sequence_number_|
905 state_ = kVerifyUlpfecPacketNotInNackList;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000906 break;
brandtr535830e2016-10-31 03:45:58 -0700907 case kVerifyUlpfecPacketNotInNackList:
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000908 // Continue to drop packets. Make sure no frame can be decoded.
brandtr535830e2016-10-31 03:45:58 -0700909 if (ulpfec_packet || header.sequenceNumber % 2 == 0)
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000910 return DROP_PACKET;
911 break;
912 }
913 return SEND_PACKET;
914 }
915
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000916 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800917 rtc::CritScope lock_(&crit_);
brandtr535830e2016-10-31 03:45:58 -0700918 if (state_ == kVerifyUlpfecPacketNotInNackList) {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000919 test::RtcpPacketParser rtcp_parser;
920 rtcp_parser.Parse(packet, length);
Danil Chapovalovba6f7be2016-09-02 18:29:10 +0200921 const std::vector<uint16_t>& nacks = rtcp_parser.nack()->packet_ids();
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200922 EXPECT_TRUE(std::find(nacks.begin(), nacks.end(),
brandtr535830e2016-10-31 03:45:58 -0700923 ulpfec_sequence_number_) == nacks.end())
924 << "Got nack for ULPFEC packet";
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000925 if (!nacks.empty() &&
brandtr535830e2016-10-31 03:45:58 -0700926 IsNewerSequenceNumber(nacks.back(), ulpfec_sequence_number_)) {
Peter Boström5811a392015-12-10 13:02:50 +0100927 observation_complete_.Set();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000928 }
929 }
930 return SEND_PACKET;
931 }
932
stefane74eef12016-01-08 06:47:13 -0800933 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
934 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
935 // Configure some network delay.
936 const int kNetworkDelayMs = 50;
937 FakeNetworkPipe::Config config;
938 config.queue_delay_ms = kNetworkDelayMs;
939 return new test::PacketTransport(sender_call, this,
940 test::PacketTransport::kSender, config);
941 }
942
Stefan Holmere5904162015-03-26 11:11:06 +0100943 // TODO(holmer): Investigate why we don't send FEC packets when the bitrate
944 // is 10 kbps.
945 Call::Config GetSenderCallConfig() override {
skvlad11a9cbf2016-10-07 11:53:05 -0700946 Call::Config config(&event_log_);
Stefan Holmere5904162015-03-26 11:11:06 +0100947 const int kMinBitrateBps = 30000;
948 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
949 return config;
950 }
951
stefanff483612015-12-21 03:14:00 -0800952 void ModifyVideoConfigs(
953 VideoSendStream::Config* send_config,
954 std::vector<VideoReceiveStream::Config>* receive_configs,
955 VideoEncoderConfig* encoder_config) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000956 // Configure hybrid NACK/FEC.
957 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
brandtrb5f2c3f2016-10-04 23:28:39 -0700958 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
959 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200960 // Set codec to VP8, otherwise NACK/FEC hybrid will be disabled.
961 send_config->encoder_settings.encoder = encoder_.get();
962 send_config->encoder_settings.payload_name = "VP8";
963 send_config->encoder_settings.payload_type = kFakeVideoSendPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200964
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000965 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
brandtrb5f2c3f2016-10-04 23:28:39 -0700966 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
967 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200968
969 (*receive_configs)[0].decoders.resize(1);
970 (*receive_configs)[0].decoders[0].payload_type =
971 send_config->encoder_settings.payload_type;
972 (*receive_configs)[0].decoders[0].payload_name =
973 send_config->encoder_settings.payload_name;
974 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000975 }
976
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000977 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100978 EXPECT_TRUE(Wait())
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000979 << "Timed out while waiting for FEC packets to be received.";
980 }
981
982 enum {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000983 kFirstPacket,
brandtr535830e2016-10-31 03:45:58 -0700984 kDropEveryOtherPacketUntilUlpfec,
985 kDropAllMediaPacketsUntilUlpfec,
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200986 kDropOneMediaPacket,
987 kPassOneMediaPacket,
brandtr535830e2016-10-31 03:45:58 -0700988 kVerifyUlpfecPacketNotInNackList,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000989 } state_;
990
stefan608213e2015-11-01 14:56:10 -0800991 rtc::CriticalSection crit_;
brandtr535830e2016-10-31 03:45:58 -0700992 uint16_t ulpfec_sequence_number_ GUARDED_BY(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000993 bool has_last_sequence_number_;
994 uint16_t last_sequence_number_;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200995 std::unique_ptr<webrtc::VideoEncoder> encoder_;
996 std::unique_ptr<webrtc::VideoDecoder> decoder_;
stefanf116bd02015-10-27 08:29:42 -0700997 } test;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000998
stefane74eef12016-01-08 06:47:13 -0800999 RunBaseTest(&test);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001000}
1001
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001002// This test drops second RTP packet with a marker bit set, makes sure it's
1003// retransmitted and renders. Retransmission SSRCs are also checked.
Peter Boström39593972016-02-15 11:27:15 +01001004void EndToEndTest::DecodesRetransmittedFrame(bool enable_rtx, bool enable_red) {
Peter Boström67680c12016-02-17 11:10:04 +01001005 static const int kDroppedFrameNumber = 10;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001006 class RetransmissionObserver : public test::EndToEndTest,
1007 public I420FrameCallback {
1008 public:
Peter Boström39593972016-02-15 11:27:15 +01001009 RetransmissionObserver(bool enable_rtx, bool enable_red)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001010 : EndToEndTest(kDefaultTimeoutMs),
Peter Boström39593972016-02-15 11:27:15 +01001011 payload_type_(GetPayloadType(false, enable_red)),
1012 retransmission_ssrc_(enable_rtx ? kSendRtxSsrcs[0]
1013 : kVideoSendSsrcs[0]),
1014 retransmission_payload_type_(GetPayloadType(enable_rtx, enable_red)),
magjed509e4fe2016-11-18 01:34:11 -08001015 encoder_(VP8Encoder::Create()),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001016 marker_bits_observed_(0),
danilchap192717e2016-07-25 08:20:51 -07001017 retransmitted_timestamp_(0) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001018
1019 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001020 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001021 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001022 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001023 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001024
Peter Boström67680c12016-02-17 11:10:04 +01001025 // Ignore padding-only packets over RTX.
1026 if (header.payloadType != payload_type_) {
1027 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
1028 if (length == header.headerLength + header.paddingLength)
1029 return SEND_PACKET;
Stefan Holmer586b19b2015-09-18 11:14:31 +02001030 }
Peter Boström67680c12016-02-17 11:10:04 +01001031
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001032 if (header.timestamp == retransmitted_timestamp_) {
1033 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
1034 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001035 return SEND_PACKET;
1036 }
1037
Stefan Holmer586b19b2015-09-18 11:14:31 +02001038 // Found the final packet of the frame to inflict loss to, drop this and
1039 // expect a retransmission.
danilchapfdd381c2016-07-25 04:03:20 -07001040 if (header.payloadType == payload_type_ && header.markerBit &&
1041 ++marker_bits_observed_ == kDroppedFrameNumber) {
Danil Chapovalov18c65a42016-06-29 15:29:34 +02001042 // This should be the only dropped packet.
1043 EXPECT_EQ(0u, retransmitted_timestamp_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001044 retransmitted_timestamp_ = header.timestamp;
danilchap192717e2016-07-25 08:20:51 -07001045 if (std::find(rendered_timestamps_.begin(), rendered_timestamps_.end(),
1046 retransmitted_timestamp_) != rendered_timestamps_.end()) {
1047 // Frame was rendered before last packet was scheduled for sending.
1048 // This is extremly rare but possible scenario because prober able to
1049 // resend packet before it was send.
1050 // TODO(danilchap): Remove this corner case when prober would not be
1051 // able to sneak in between packet saved to history for resending and
1052 // pacer notified about existance of that packet for sending.
1053 // See https://bugs.chromium.org/p/webrtc/issues/detail?id=5540 for
1054 // details.
1055 observation_complete_.Set();
1056 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001057 return DROP_PACKET;
1058 }
1059
1060 return SEND_PACKET;
1061 }
1062
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001063 void FrameCallback(VideoFrame* frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001064 rtc::CritScope lock(&crit_);
danilchap192717e2016-07-25 08:20:51 -07001065 if (frame->timestamp() == retransmitted_timestamp_)
Peter Boström5811a392015-12-10 13:02:50 +01001066 observation_complete_.Set();
danilchap192717e2016-07-25 08:20:51 -07001067 rendered_timestamps_.push_back(frame->timestamp());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001068 }
1069
stefanff483612015-12-21 03:14:00 -08001070 void ModifyVideoConfigs(
1071 VideoSendStream::Config* send_config,
1072 std::vector<VideoReceiveStream::Config>* receive_configs,
1073 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001074 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001075 (*receive_configs)[0].pre_render_callback = this;
1076 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
Shao Changbine62202f2015-04-21 20:24:50 +08001077
1078 if (payload_type_ == kRedPayloadType) {
brandtrb5f2c3f2016-10-04 23:28:39 -07001079 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
1080 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +01001081 if (retransmission_ssrc_ == kSendRtxSsrcs[0])
brandtrb5f2c3f2016-10-04 23:28:39 -07001082 send_config->rtp.ulpfec.red_rtx_payload_type = kRtxRedPayloadType;
1083 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type =
1084 send_config->rtp.ulpfec.ulpfec_payload_type;
1085 (*receive_configs)[0].rtp.ulpfec.red_payload_type =
1086 send_config->rtp.ulpfec.red_payload_type;
1087 (*receive_configs)[0].rtp.ulpfec.red_rtx_payload_type =
1088 send_config->rtp.ulpfec.red_rtx_payload_type;
Shao Changbine62202f2015-04-21 20:24:50 +08001089 }
1090
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001091 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
1092 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001093 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
brandtr14742122017-01-27 04:53:07 -08001094 (*receive_configs)[0].rtp.rtx_ssrc = kSendRtxSsrcs[0];
1095 (*receive_configs)[0].rtp.rtx_payload_types[payload_type_] =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001096 kSendRtxPayloadType;
1097 }
Peter Boström39593972016-02-15 11:27:15 +01001098 // Configure encoding and decoding with VP8, since generic packetization
1099 // doesn't support FEC with NACK.
kwibergaf476c72016-11-28 15:21:39 -08001100 RTC_DCHECK_EQ(1, (*receive_configs)[0].decoders.size());
Peter Boström39593972016-02-15 11:27:15 +01001101 send_config->encoder_settings.encoder = encoder_.get();
1102 send_config->encoder_settings.payload_name = "VP8";
1103 (*receive_configs)[0].decoders[0].payload_name = "VP8";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001104 }
1105
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001106 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001107 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001108 << "Timed out while waiting for retransmission to render.";
1109 }
1110
Shao Changbine62202f2015-04-21 20:24:50 +08001111 int GetPayloadType(bool use_rtx, bool use_red) {
Stefan Holmer10880012016-02-03 13:29:59 +01001112 if (use_red) {
1113 if (use_rtx)
1114 return kRtxRedPayloadType;
1115 return kRedPayloadType;
1116 }
1117 if (use_rtx)
1118 return kSendRtxPayloadType;
1119 return kFakeVideoSendPayloadType;
Shao Changbine62202f2015-04-21 20:24:50 +08001120 }
1121
stefanf116bd02015-10-27 08:29:42 -07001122 rtc::CriticalSection crit_;
Shao Changbine62202f2015-04-21 20:24:50 +08001123 const int payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001124 const uint32_t retransmission_ssrc_;
1125 const int retransmission_payload_type_;
kwiberg27f982b2016-03-01 11:52:33 -08001126 std::unique_ptr<VideoEncoder> encoder_;
Peter Boström39593972016-02-15 11:27:15 +01001127 const std::string payload_name_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001128 int marker_bits_observed_;
stefanf116bd02015-10-27 08:29:42 -07001129 uint32_t retransmitted_timestamp_ GUARDED_BY(&crit_);
danilchap192717e2016-07-25 08:20:51 -07001130 std::vector<uint32_t> rendered_timestamps_ GUARDED_BY(&crit_);
Peter Boström39593972016-02-15 11:27:15 +01001131 } test(enable_rtx, enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001132
stefane74eef12016-01-08 06:47:13 -08001133 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001134}
1135
philipel266f0a42016-11-28 08:49:07 -08001136TEST_P(EndToEndTest, DecodesRetransmittedFrame) {
Shao Changbine62202f2015-04-21 20:24:50 +08001137 DecodesRetransmittedFrame(false, false);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001138}
1139
philipel266f0a42016-11-28 08:49:07 -08001140TEST_P(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +08001141 DecodesRetransmittedFrame(true, false);
1142}
1143
philipel266f0a42016-11-28 08:49:07 -08001144TEST_P(EndToEndTest, DecodesRetransmittedFrameByRed) {
Shao Changbine62202f2015-04-21 20:24:50 +08001145 DecodesRetransmittedFrame(false, true);
1146}
1147
philipel266f0a42016-11-28 08:49:07 -08001148TEST_P(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +08001149 DecodesRetransmittedFrame(true, true);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001150}
1151
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001152void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
1153 static const int kPacketsToDrop = 1;
1154
nisse7ade7b32016-03-23 04:48:10 -07001155 class PliObserver : public test::EndToEndTest,
1156 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001157 public:
1158 explicit PliObserver(int rtp_history_ms)
1159 : EndToEndTest(kLongTimeoutMs),
1160 rtp_history_ms_(rtp_history_ms),
1161 nack_enabled_(rtp_history_ms > 0),
1162 highest_dropped_timestamp_(0),
1163 frames_to_drop_(0),
1164 received_pli_(false) {}
1165
1166 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001167 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001168 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001169 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001170 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001171
1172 // Drop all retransmitted packets to force a PLI.
1173 if (header.timestamp <= highest_dropped_timestamp_)
1174 return DROP_PACKET;
1175
1176 if (frames_to_drop_ > 0) {
1177 highest_dropped_timestamp_ = header.timestamp;
1178 --frames_to_drop_;
1179 return DROP_PACKET;
1180 }
1181
1182 return SEND_PACKET;
1183 }
1184
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001185 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001186 rtc::CritScope lock(&crit_);
danilchap3dc929e2016-11-02 08:21:59 -07001187 test::RtcpPacketParser parser;
1188 EXPECT_TRUE(parser.Parse(packet, length));
1189 if (!nack_enabled_)
1190 EXPECT_EQ(0, parser.nack()->num_packets());
1191 if (parser.pli()->num_packets() > 0)
1192 received_pli_ = true;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001193 return SEND_PACKET;
1194 }
1195
nisseeb83a1a2016-03-21 01:27:56 -07001196 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001197 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001198 if (received_pli_ &&
1199 video_frame.timestamp() > highest_dropped_timestamp_) {
Peter Boström5811a392015-12-10 13:02:50 +01001200 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001201 }
1202 if (!received_pli_)
1203 frames_to_drop_ = kPacketsToDrop;
1204 }
1205
stefanff483612015-12-21 03:14:00 -08001206 void ModifyVideoConfigs(
1207 VideoSendStream::Config* send_config,
1208 std::vector<VideoReceiveStream::Config>* receive_configs,
1209 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001210 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001211 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
1212 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001213 }
1214
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001215 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001216 EXPECT_TRUE(Wait()) << "Timed out waiting for PLI to be "
1217 "received and a frame to be "
1218 "rendered afterwards.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001219 }
1220
stefanf116bd02015-10-27 08:29:42 -07001221 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001222 int rtp_history_ms_;
1223 bool nack_enabled_;
stefanf116bd02015-10-27 08:29:42 -07001224 uint32_t highest_dropped_timestamp_ GUARDED_BY(&crit_);
1225 int frames_to_drop_ GUARDED_BY(&crit_);
1226 bool received_pli_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001227 } test(rtp_history_ms);
1228
stefane74eef12016-01-08 06:47:13 -08001229 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001230}
1231
philipel266f0a42016-11-28 08:49:07 -08001232TEST_P(EndToEndTest, ReceivesPliAndRecoversWithNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001233 ReceivesPliAndRecovers(1000);
1234}
1235
philipel266f0a42016-11-28 08:49:07 -08001236TEST_P(EndToEndTest, ReceivesPliAndRecoversWithoutNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001237 ReceivesPliAndRecovers(0);
1238}
1239
philipel266f0a42016-11-28 08:49:07 -08001240TEST_P(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001241 class PacketInputObserver : public PacketReceiver {
1242 public:
1243 explicit PacketInputObserver(PacketReceiver* receiver)
Peter Boström5811a392015-12-10 13:02:50 +01001244 : receiver_(receiver), delivered_packet_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001245
Peter Boström5811a392015-12-10 13:02:50 +01001246 bool Wait() { return delivered_packet_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001247
1248 private:
stefan68786d22015-09-08 05:36:15 -07001249 DeliveryStatus DeliverPacket(MediaType media_type,
1250 const uint8_t* packet,
1251 size_t length,
1252 const PacketTime& packet_time) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001253 if (RtpHeaderParser::IsRtcp(packet, length)) {
stefan68786d22015-09-08 05:36:15 -07001254 return receiver_->DeliverPacket(media_type, packet, length,
1255 packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001256 } else {
1257 DeliveryStatus delivery_status =
stefan68786d22015-09-08 05:36:15 -07001258 receiver_->DeliverPacket(media_type, packet, length, packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001259 EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
Peter Boström5811a392015-12-10 13:02:50 +01001260 delivered_packet_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001261 return delivery_status;
1262 }
1263 }
1264
1265 PacketReceiver* receiver_;
Peter Boström5811a392015-12-10 13:02:50 +01001266 rtc::Event delivered_packet_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001267 };
1268
skvlad11a9cbf2016-10-07 11:53:05 -07001269 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -07001270
stefanf116bd02015-10-27 08:29:42 -07001271 test::DirectTransport send_transport(sender_call_.get());
1272 test::DirectTransport receive_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001273 PacketInputObserver input_observer(receiver_call_->Receiver());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001274 send_transport.SetReceiver(&input_observer);
1275 receive_transport.SetReceiver(sender_call_->Receiver());
1276
brandtr841de6a2016-11-15 07:10:52 -08001277 CreateSendConfig(1, 0, 0, &send_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001278 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001279
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001280 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07001281 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
1282 kDefaultHeight);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001283 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001284
stefanff483612015-12-21 03:14:00 -08001285 receiver_call_->DestroyVideoReceiveStream(video_receive_streams_[0]);
1286 video_receive_streams_.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001287
1288 // Wait() waits for a received packet.
Peter Boström5811a392015-12-10 13:02:50 +01001289 EXPECT_TRUE(input_observer.Wait());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001290
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001291 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001292
1293 DestroyStreams();
1294
1295 send_transport.StopSending();
1296 receive_transport.StopSending();
1297}
1298
pbosda903ea2015-10-02 02:36:56 -07001299void EndToEndTest::RespectsRtcpMode(RtcpMode rtcp_mode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001300 static const int kNumCompoundRtcpPacketsToObserve = 10;
1301 class RtcpModeObserver : public test::EndToEndTest {
1302 public:
pbosda903ea2015-10-02 02:36:56 -07001303 explicit RtcpModeObserver(RtcpMode rtcp_mode)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001304 : EndToEndTest(kDefaultTimeoutMs),
1305 rtcp_mode_(rtcp_mode),
1306 sent_rtp_(0),
1307 sent_rtcp_(0) {}
1308
1309 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001310 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001311 if (++sent_rtp_ % 3 == 0)
1312 return DROP_PACKET;
1313
1314 return SEND_PACKET;
1315 }
1316
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001317 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001318 ++sent_rtcp_;
danilchap3dc929e2016-11-02 08:21:59 -07001319 test::RtcpPacketParser parser;
1320 EXPECT_TRUE(parser.Parse(packet, length));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001321
danilchap3dc929e2016-11-02 08:21:59 -07001322 EXPECT_EQ(0, parser.sender_report()->num_packets());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001323
1324 switch (rtcp_mode_) {
pbosda903ea2015-10-02 02:36:56 -07001325 case RtcpMode::kCompound:
danilchap3dc929e2016-11-02 08:21:59 -07001326 if (parser.receiver_report()->num_packets() == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001327 ADD_FAILURE() << "Received RTCP packet without receiver report for "
pbosda903ea2015-10-02 02:36:56 -07001328 "RtcpMode::kCompound.";
Peter Boström5811a392015-12-10 13:02:50 +01001329 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001330 }
1331
1332 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
Peter Boström5811a392015-12-10 13:02:50 +01001333 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001334
1335 break;
pbosda903ea2015-10-02 02:36:56 -07001336 case RtcpMode::kReducedSize:
danilchap3dc929e2016-11-02 08:21:59 -07001337 if (parser.receiver_report()->num_packets() == 0)
Peter Boström5811a392015-12-10 13:02:50 +01001338 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001339 break;
pbosda903ea2015-10-02 02:36:56 -07001340 case RtcpMode::kOff:
1341 RTC_NOTREACHED();
1342 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001343 }
1344
1345 return SEND_PACKET;
1346 }
1347
stefanff483612015-12-21 03:14:00 -08001348 void ModifyVideoConfigs(
1349 VideoSendStream::Config* send_config,
1350 std::vector<VideoReceiveStream::Config>* receive_configs,
1351 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001352 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001353 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1354 (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001355 }
1356
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001357 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001358 EXPECT_TRUE(Wait())
pbosda903ea2015-10-02 02:36:56 -07001359 << (rtcp_mode_ == RtcpMode::kCompound
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001360 ? "Timed out before observing enough compound packets."
1361 : "Timed out before receiving a non-compound RTCP packet.");
1362 }
1363
pbosda903ea2015-10-02 02:36:56 -07001364 RtcpMode rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001365 int sent_rtp_;
1366 int sent_rtcp_;
1367 } test(rtcp_mode);
1368
stefane74eef12016-01-08 06:47:13 -08001369 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001370}
1371
philipel266f0a42016-11-28 08:49:07 -08001372TEST_P(EndToEndTest, UsesRtcpCompoundMode) {
pbosda903ea2015-10-02 02:36:56 -07001373 RespectsRtcpMode(RtcpMode::kCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001374}
1375
philipel266f0a42016-11-28 08:49:07 -08001376TEST_P(EndToEndTest, UsesRtcpReducedSizeMode) {
pbosda903ea2015-10-02 02:36:56 -07001377 RespectsRtcpMode(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001378}
1379
1380// Test sets up a Call multiple senders with different resolutions and SSRCs.
1381// Another is set up to receive all three of these with different renderers.
sprang867fb522015-08-03 04:38:41 -07001382class MultiStreamTest {
1383 public:
1384 static const size_t kNumStreams = 3;
1385 struct CodecSettings {
1386 uint32_t ssrc;
1387 int width;
1388 int height;
1389 } codec_settings[kNumStreams];
1390
1391 MultiStreamTest() {
1392 // TODO(sprang): Cleanup when msvc supports explicit initializers for array.
1393 codec_settings[0] = {1, 640, 480};
1394 codec_settings[1] = {2, 320, 240};
1395 codec_settings[2] = {3, 240, 160};
1396 }
1397
1398 virtual ~MultiStreamTest() {}
1399
1400 void RunTest() {
skvlad11a9cbf2016-10-07 11:53:05 -07001401 webrtc::RtcEventLogNullImpl event_log;
1402 Call::Config config(&event_log);
1403 std::unique_ptr<Call> sender_call(Call::Create(config));
1404 std::unique_ptr<Call> receiver_call(Call::Create(config));
kwiberg27f982b2016-03-01 11:52:33 -08001405 std::unique_ptr<test::DirectTransport> sender_transport(
stefanf116bd02015-10-27 08:29:42 -07001406 CreateSendTransport(sender_call.get()));
kwiberg27f982b2016-03-01 11:52:33 -08001407 std::unique_ptr<test::DirectTransport> receiver_transport(
stefanf116bd02015-10-27 08:29:42 -07001408 CreateReceiveTransport(receiver_call.get()));
sprang867fb522015-08-03 04:38:41 -07001409 sender_transport->SetReceiver(receiver_call->Receiver());
1410 receiver_transport->SetReceiver(sender_call->Receiver());
1411
kwiberg27f982b2016-03-01 11:52:33 -08001412 std::unique_ptr<VideoEncoder> encoders[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001413 for (size_t i = 0; i < kNumStreams; ++i)
magjed509e4fe2016-11-18 01:34:11 -08001414 encoders[i].reset(VP8Encoder::Create());
sprang867fb522015-08-03 04:38:41 -07001415
1416 VideoSendStream* send_streams[kNumStreams];
1417 VideoReceiveStream* receive_streams[kNumStreams];
1418
1419 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
kwiberg4a206a92016-03-31 10:24:26 -07001420 std::vector<std::unique_ptr<VideoDecoder>> allocated_decoders;
sprang867fb522015-08-03 04:38:41 -07001421 for (size_t i = 0; i < kNumStreams; ++i) {
1422 uint32_t ssrc = codec_settings[i].ssrc;
1423 int width = codec_settings[i].width;
1424 int height = codec_settings[i].height;
1425
solenberg4fbae2b2015-08-28 04:07:10 -07001426 VideoSendStream::Config send_config(sender_transport.get());
sprang867fb522015-08-03 04:38:41 -07001427 send_config.rtp.ssrcs.push_back(ssrc);
1428 send_config.encoder_settings.encoder = encoders[i].get();
1429 send_config.encoder_settings.payload_name = "VP8";
1430 send_config.encoder_settings.payload_type = 124;
1431 VideoEncoderConfig encoder_config;
perkjfa10b552016-10-02 23:45:26 -07001432 test::FillEncoderConfiguration(1, &encoder_config);
1433 encoder_config.max_bitrate_bps = 100000;
sprang867fb522015-08-03 04:38:41 -07001434
1435 UpdateSendConfig(i, &send_config, &encoder_config, &frame_generators[i]);
1436
perkj26091b12016-09-01 01:17:40 -07001437 send_streams[i] = sender_call->CreateVideoSendStream(
1438 send_config.Copy(), encoder_config.Copy());
sprang867fb522015-08-03 04:38:41 -07001439 send_streams[i]->Start();
1440
solenberg4fbae2b2015-08-28 04:07:10 -07001441 VideoReceiveStream::Config receive_config(receiver_transport.get());
sprang867fb522015-08-03 04:38:41 -07001442 receive_config.rtp.remote_ssrc = ssrc;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001443 receive_config.rtp.local_ssrc = test::CallTest::kReceiverLocalVideoSsrc;
sprang867fb522015-08-03 04:38:41 -07001444 VideoReceiveStream::Decoder decoder =
1445 test::CreateMatchingDecoder(send_config.encoder_settings);
kwiberg4a206a92016-03-31 10:24:26 -07001446 allocated_decoders.push_back(
1447 std::unique_ptr<VideoDecoder>(decoder.decoder));
sprang867fb522015-08-03 04:38:41 -07001448 receive_config.decoders.push_back(decoder);
1449
1450 UpdateReceiveConfig(i, &receive_config);
1451
1452 receive_streams[i] =
Tommi733b5472016-06-10 17:58:01 +02001453 receiver_call->CreateVideoReceiveStream(std::move(receive_config));
sprang867fb522015-08-03 04:38:41 -07001454 receive_streams[i]->Start();
1455
1456 frame_generators[i] = test::FrameGeneratorCapturer::Create(
perkja49cbd32016-09-16 07:53:41 -07001457 width, height, 30, Clock::GetRealTimeClock());
perkj803d97f2016-11-01 11:45:46 -07001458 send_streams[i]->SetSource(
1459 frame_generators[i],
1460 VideoSendStream::DegradationPreference::kBalanced);
sprang867fb522015-08-03 04:38:41 -07001461 frame_generators[i]->Start();
1462 }
1463
1464 Wait();
1465
1466 for (size_t i = 0; i < kNumStreams; ++i) {
1467 frame_generators[i]->Stop();
1468 sender_call->DestroyVideoSendStream(send_streams[i]);
1469 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1470 delete frame_generators[i];
1471 }
1472
1473 sender_transport->StopSending();
1474 receiver_transport->StopSending();
1475 }
1476
1477 protected:
1478 virtual void Wait() = 0;
1479 // Note: frame_generator is a point-to-pointer, since the actual instance
1480 // hasn't been created at the time of this call. Only when packets/frames
1481 // start flowing should this be dereferenced.
1482 virtual void UpdateSendConfig(
1483 size_t stream_index,
1484 VideoSendStream::Config* send_config,
1485 VideoEncoderConfig* encoder_config,
1486 test::FrameGeneratorCapturer** frame_generator) {}
1487 virtual void UpdateReceiveConfig(size_t stream_index,
1488 VideoReceiveStream::Config* receive_config) {
1489 }
stefanf116bd02015-10-27 08:29:42 -07001490 virtual test::DirectTransport* CreateSendTransport(Call* sender_call) {
1491 return new test::DirectTransport(sender_call);
sprang867fb522015-08-03 04:38:41 -07001492 }
stefanf116bd02015-10-27 08:29:42 -07001493 virtual test::DirectTransport* CreateReceiveTransport(Call* receiver_call) {
1494 return new test::DirectTransport(receiver_call);
sprang867fb522015-08-03 04:38:41 -07001495 }
1496};
1497
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001498// Each renderer verifies that it receives the expected resolution, and as soon
1499// as every renderer has received a frame, the test finishes.
philipel266f0a42016-11-28 08:49:07 -08001500TEST_P(EndToEndTest, SendsAndReceivesMultipleStreams) {
nisse7ade7b32016-03-23 04:48:10 -07001501 class VideoOutputObserver : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001502 public:
sprang867fb522015-08-03 04:38:41 -07001503 VideoOutputObserver(const MultiStreamTest::CodecSettings& settings,
1504 uint32_t ssrc,
1505 test::FrameGeneratorCapturer** frame_generator)
1506 : settings_(settings),
1507 ssrc_(ssrc),
1508 frame_generator_(frame_generator),
Peter Boström5811a392015-12-10 13:02:50 +01001509 done_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001510
nisseeb83a1a2016-03-21 01:27:56 -07001511 void OnFrame(const VideoFrame& video_frame) override {
sprang867fb522015-08-03 04:38:41 -07001512 EXPECT_EQ(settings_.width, video_frame.width());
1513 EXPECT_EQ(settings_.height, video_frame.height());
1514 (*frame_generator_)->Stop();
Peter Boström5811a392015-12-10 13:02:50 +01001515 done_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001516 }
1517
sprang867fb522015-08-03 04:38:41 -07001518 uint32_t Ssrc() { return ssrc_; }
1519
Peter Boström5811a392015-12-10 13:02:50 +01001520 bool Wait() { return done_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001521
1522 private:
sprang867fb522015-08-03 04:38:41 -07001523 const MultiStreamTest::CodecSettings& settings_;
1524 const uint32_t ssrc_;
1525 test::FrameGeneratorCapturer** const frame_generator_;
Peter Boström5811a392015-12-10 13:02:50 +01001526 rtc::Event done_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001527 };
1528
sprang867fb522015-08-03 04:38:41 -07001529 class Tester : public MultiStreamTest {
1530 public:
1531 Tester() {}
1532 virtual ~Tester() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001533
sprang867fb522015-08-03 04:38:41 -07001534 protected:
1535 void Wait() override {
1536 for (const auto& observer : observers_) {
Peter Boström5811a392015-12-10 13:02:50 +01001537 EXPECT_TRUE(observer->Wait()) << "Time out waiting for from on ssrc "
1538 << observer->Ssrc();
sprang867fb522015-08-03 04:38:41 -07001539 }
1540 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001541
sprang867fb522015-08-03 04:38:41 -07001542 void UpdateSendConfig(
1543 size_t stream_index,
1544 VideoSendStream::Config* send_config,
1545 VideoEncoderConfig* encoder_config,
1546 test::FrameGeneratorCapturer** frame_generator) override {
1547 observers_[stream_index].reset(new VideoOutputObserver(
1548 codec_settings[stream_index], send_config->rtp.ssrcs.front(),
1549 frame_generator));
1550 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001551
sprang867fb522015-08-03 04:38:41 -07001552 void UpdateReceiveConfig(
1553 size_t stream_index,
1554 VideoReceiveStream::Config* receive_config) override {
1555 receive_config->renderer = observers_[stream_index].get();
1556 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001557
sprang867fb522015-08-03 04:38:41 -07001558 private:
kwiberg27f982b2016-03-01 11:52:33 -08001559 std::unique_ptr<VideoOutputObserver> observers_[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001560 } tester;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001561
sprang867fb522015-08-03 04:38:41 -07001562 tester.RunTest();
1563}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001564
philipel266f0a42016-11-28 08:49:07 -08001565TEST_P(EndToEndTest, AssignsTransportSequenceNumbers) {
sprang867fb522015-08-03 04:38:41 -07001566 static const int kExtensionId = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001567
sprang867fb522015-08-03 04:38:41 -07001568 class RtpExtensionHeaderObserver : public test::DirectTransport {
1569 public:
stefanf116bd02015-10-27 08:29:42 -07001570 RtpExtensionHeaderObserver(Call* sender_call,
1571 const uint32_t& first_media_ssrc,
sprang861c55e2015-10-16 10:01:21 -07001572 const std::map<uint32_t, uint32_t>& ssrc_map)
stefanf116bd02015-10-27 08:29:42 -07001573 : DirectTransport(sender_call),
Peter Boström5811a392015-12-10 13:02:50 +01001574 done_(false, false),
sprang867fb522015-08-03 04:38:41 -07001575 parser_(RtpHeaderParser::Create()),
sprang861c55e2015-10-16 10:01:21 -07001576 first_media_ssrc_(first_media_ssrc),
1577 rtx_to_media_ssrcs_(ssrc_map),
sprang867fb522015-08-03 04:38:41 -07001578 padding_observed_(false),
sprang861c55e2015-10-16 10:01:21 -07001579 rtx_padding_observed_(false),
1580 retransmit_observed_(false),
1581 started_(false) {
sprang867fb522015-08-03 04:38:41 -07001582 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
1583 kExtensionId);
1584 }
1585 virtual ~RtpExtensionHeaderObserver() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001586
stefan1d8a5062015-10-02 03:39:33 -07001587 bool SendRtp(const uint8_t* data,
1588 size_t length,
1589 const PacketOptions& options) override {
sprang861c55e2015-10-16 10:01:21 -07001590 {
1591 rtc::CritScope cs(&lock_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001592
Erik Språng8d629712015-08-04 16:24:03 +02001593 if (IsDone())
sprang861c55e2015-10-16 10:01:21 -07001594 return false;
1595
1596 if (started_) {
1597 RTPHeader header;
1598 EXPECT_TRUE(parser_->Parse(data, length, &header));
1599 bool drop_packet = false;
1600
1601 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
1602 EXPECT_EQ(options.packet_id,
1603 header.extension.transportSequenceNumber);
1604 if (!streams_observed_.empty()) {
1605 // Unwrap packet id and verify uniqueness.
1606 int64_t packet_id = unwrapper_.Unwrap(options.packet_id);
1607 EXPECT_TRUE(received_packed_ids_.insert(packet_id).second);
1608 }
1609
1610 // Drop (up to) every 17th packet, so we get retransmits.
1611 // Only drop media, and not on the first stream (otherwise it will be
1612 // hard to distinguish from padding, which is always sent on the first
1613 // stream).
1614 if (header.payloadType != kSendRtxPayloadType &&
1615 header.ssrc != first_media_ssrc_ &&
1616 header.extension.transportSequenceNumber % 17 == 0) {
1617 dropped_seq_[header.ssrc].insert(header.sequenceNumber);
1618 drop_packet = true;
1619 }
1620
1621 size_t payload_length =
1622 length - (header.headerLength + header.paddingLength);
1623 if (payload_length == 0) {
1624 padding_observed_ = true;
1625 } else if (header.payloadType == kSendRtxPayloadType) {
1626 uint16_t original_sequence_number =
1627 ByteReader<uint16_t>::ReadBigEndian(&data[header.headerLength]);
1628 uint32_t original_ssrc =
1629 rtx_to_media_ssrcs_.find(header.ssrc)->second;
1630 std::set<uint16_t>* seq_no_map = &dropped_seq_[original_ssrc];
1631 auto it = seq_no_map->find(original_sequence_number);
1632 if (it != seq_no_map->end()) {
1633 retransmit_observed_ = true;
1634 seq_no_map->erase(it);
1635 } else {
1636 rtx_padding_observed_ = true;
1637 }
1638 } else {
1639 streams_observed_.insert(header.ssrc);
1640 }
1641
1642 if (IsDone())
Peter Boström5811a392015-12-10 13:02:50 +01001643 done_.Set();
sprang861c55e2015-10-16 10:01:21 -07001644
1645 if (drop_packet)
1646 return true;
1647 }
sprang867fb522015-08-03 04:38:41 -07001648 }
sprang861c55e2015-10-16 10:01:21 -07001649
stefan1d8a5062015-10-02 03:39:33 -07001650 return test::DirectTransport::SendRtp(data, length, options);
sprang867fb522015-08-03 04:38:41 -07001651 }
1652
Erik Språng8d629712015-08-04 16:24:03 +02001653 bool IsDone() {
sprang861c55e2015-10-16 10:01:21 -07001654 bool observed_types_ok =
1655 streams_observed_.size() == MultiStreamTest::kNumStreams &&
1656 padding_observed_ && retransmit_observed_ && rtx_padding_observed_;
1657 if (!observed_types_ok)
1658 return false;
1659 // We should not have any gaps in the sequence number range.
1660 size_t seqno_range =
1661 *received_packed_ids_.rbegin() - *received_packed_ids_.begin() + 1;
1662 return seqno_range == received_packed_ids_.size();
Erik Språng8d629712015-08-04 16:24:03 +02001663 }
1664
Peter Boström5811a392015-12-10 13:02:50 +01001665 bool Wait() {
sprang861c55e2015-10-16 10:01:21 -07001666 {
1667 // Can't be sure until this point that rtx_to_media_ssrcs_ etc have
1668 // been initialized and are OK to read.
1669 rtc::CritScope cs(&lock_);
1670 started_ = true;
1671 }
Peter Boström5811a392015-12-10 13:02:50 +01001672 return done_.Wait(kDefaultTimeoutMs);
sprang861c55e2015-10-16 10:01:21 -07001673 }
sprang867fb522015-08-03 04:38:41 -07001674
sprang861c55e2015-10-16 10:01:21 -07001675 rtc::CriticalSection lock_;
Peter Boström5811a392015-12-10 13:02:50 +01001676 rtc::Event done_;
kwiberg27f982b2016-03-01 11:52:33 -08001677 std::unique_ptr<RtpHeaderParser> parser_;
sprang861c55e2015-10-16 10:01:21 -07001678 SequenceNumberUnwrapper unwrapper_;
1679 std::set<int64_t> received_packed_ids_;
sprang867fb522015-08-03 04:38:41 -07001680 std::set<uint32_t> streams_observed_;
sprang861c55e2015-10-16 10:01:21 -07001681 std::map<uint32_t, std::set<uint16_t>> dropped_seq_;
1682 const uint32_t& first_media_ssrc_;
1683 const std::map<uint32_t, uint32_t>& rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001684 bool padding_observed_;
1685 bool rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001686 bool retransmit_observed_;
1687 bool started_;
sprang867fb522015-08-03 04:38:41 -07001688 };
1689
1690 class TransportSequenceNumberTester : public MultiStreamTest {
1691 public:
sprang861c55e2015-10-16 10:01:21 -07001692 TransportSequenceNumberTester()
1693 : first_media_ssrc_(0), observer_(nullptr) {}
sprang867fb522015-08-03 04:38:41 -07001694 virtual ~TransportSequenceNumberTester() {}
1695
1696 protected:
1697 void Wait() override {
Peter Boström74f6e9e2016-04-04 17:56:10 +02001698 RTC_DCHECK(observer_);
Peter Boström5811a392015-12-10 13:02:50 +01001699 EXPECT_TRUE(observer_->Wait());
sprang867fb522015-08-03 04:38:41 -07001700 }
1701
1702 void UpdateSendConfig(
1703 size_t stream_index,
1704 VideoSendStream::Config* send_config,
1705 VideoEncoderConfig* encoder_config,
1706 test::FrameGeneratorCapturer** frame_generator) override {
1707 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001708 send_config->rtp.extensions.push_back(RtpExtension(
1709 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sprang867fb522015-08-03 04:38:41 -07001710
1711 // Force some padding to be sent.
1712 const int kPaddingBitrateBps = 50000;
perkjfa10b552016-10-02 23:45:26 -07001713 encoder_config->max_bitrate_bps = 1000000;
sprang867fb522015-08-03 04:38:41 -07001714 encoder_config->min_transmit_bitrate_bps =
perkjfa10b552016-10-02 23:45:26 -07001715 encoder_config->max_bitrate_bps + kPaddingBitrateBps;
sprang867fb522015-08-03 04:38:41 -07001716
1717 // Configure RTX for redundant payload padding.
1718 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang861c55e2015-10-16 10:01:21 -07001719 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[stream_index]);
sprang867fb522015-08-03 04:38:41 -07001720 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
sprang861c55e2015-10-16 10:01:21 -07001721 rtx_to_media_ssrcs_[kSendRtxSsrcs[stream_index]] =
1722 send_config->rtp.ssrcs[0];
1723
1724 if (stream_index == 0)
1725 first_media_ssrc_ = send_config->rtp.ssrcs[0];
sprang867fb522015-08-03 04:38:41 -07001726 }
1727
1728 void UpdateReceiveConfig(
1729 size_t stream_index,
1730 VideoReceiveStream::Config* receive_config) override {
sprang861c55e2015-10-16 10:01:21 -07001731 receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang867fb522015-08-03 04:38:41 -07001732 receive_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001733 receive_config->rtp.extensions.push_back(RtpExtension(
1734 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sakal55d932b2016-09-30 06:19:08 -07001735 receive_config->renderer = &fake_renderer_;
sprang867fb522015-08-03 04:38:41 -07001736 }
1737
stefanf116bd02015-10-27 08:29:42 -07001738 test::DirectTransport* CreateSendTransport(Call* sender_call) override {
1739 observer_ = new RtpExtensionHeaderObserver(sender_call, first_media_ssrc_,
sprang861c55e2015-10-16 10:01:21 -07001740 rtx_to_media_ssrcs_);
sprang867fb522015-08-03 04:38:41 -07001741 return observer_;
1742 }
1743
1744 private:
sakal55d932b2016-09-30 06:19:08 -07001745 test::FakeVideoRenderer fake_renderer_;
sprang861c55e2015-10-16 10:01:21 -07001746 uint32_t first_media_ssrc_;
1747 std::map<uint32_t, uint32_t> rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001748 RtpExtensionHeaderObserver* observer_;
1749 } tester;
1750
1751 tester.RunTest();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001752}
1753
Stefan Holmer04cb7632016-01-14 20:34:30 +01001754class TransportFeedbackTester : public test::EndToEndTest {
1755 public:
1756 explicit TransportFeedbackTester(bool feedback_enabled,
1757 size_t num_video_streams,
1758 size_t num_audio_streams)
1759 : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
1760 feedback_enabled_(feedback_enabled),
1761 num_video_streams_(num_video_streams),
sprangcd349d92016-07-13 09:11:28 -07001762 num_audio_streams_(num_audio_streams),
1763 receiver_call_(nullptr) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001764 // Only one stream of each supported for now.
1765 EXPECT_LE(num_video_streams, 1u);
1766 EXPECT_LE(num_audio_streams, 1u);
1767 }
1768
1769 protected:
1770 Action OnSendRtcp(const uint8_t* data, size_t length) override {
1771 EXPECT_FALSE(HasTransportFeedback(data, length));
1772 return SEND_PACKET;
1773 }
1774
1775 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
1776 if (HasTransportFeedback(data, length))
1777 observation_complete_.Set();
1778 return SEND_PACKET;
1779 }
1780
1781 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
danilchap3dc929e2016-11-02 08:21:59 -07001782 test::RtcpPacketParser parser;
1783 EXPECT_TRUE(parser.Parse(data, length));
1784 return parser.transport_feedback()->num_packets() > 0;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001785 }
1786
1787 void PerformTest() override {
1788 const int64_t kDisabledFeedbackTimeoutMs = 5000;
1789 EXPECT_EQ(feedback_enabled_,
1790 observation_complete_.Wait(feedback_enabled_
1791 ? test::CallTest::kDefaultTimeoutMs
1792 : kDisabledFeedbackTimeoutMs));
1793 }
1794
1795 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1796 receiver_call_ = receiver_call;
1797 }
1798
1799 size_t GetNumVideoStreams() const override { return num_video_streams_; }
1800 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
1801
1802 void ModifyVideoConfigs(
1803 VideoSendStream::Config* send_config,
1804 std::vector<VideoReceiveStream::Config>* receive_configs,
1805 VideoEncoderConfig* encoder_config) override {
1806 send_config->rtp.extensions.clear();
1807 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001808 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001809 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1810 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
1811 }
1812
1813 void ModifyAudioConfigs(
1814 AudioSendStream::Config* send_config,
1815 std::vector<AudioReceiveStream::Config>* receive_configs) override {
1816 send_config->rtp.extensions.clear();
1817 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001818 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001819 (*receive_configs)[0].rtp.extensions.clear();
1820 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1821 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001822 }
1823
1824 private:
Erik Språng6b8d3552015-09-24 15:06:57 +02001825 static const int kExtensionId = 5;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001826 const bool feedback_enabled_;
1827 const size_t num_video_streams_;
1828 const size_t num_audio_streams_;
1829 Call* receiver_call_;
1830};
Erik Språng6b8d3552015-09-24 15:06:57 +02001831
philipel266f0a42016-11-28 08:49:07 -08001832TEST_P(EndToEndTest, VideoReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001833 TransportFeedbackTester test(true, 1, 0);
1834 RunBaseTest(&test);
Erik Språng6b8d3552015-09-24 15:06:57 +02001835}
stefan43edf0f2015-11-20 18:05:48 -08001836
philipel266f0a42016-11-28 08:49:07 -08001837TEST_P(EndToEndTest, VideoTransportFeedbackNotConfigured) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001838 TransportFeedbackTester test(false, 1, 0);
1839 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001840}
1841
philipel266f0a42016-11-28 08:49:07 -08001842TEST_P(EndToEndTest, AudioReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001843 TransportFeedbackTester test(true, 0, 1);
1844 RunBaseTest(&test);
1845}
1846
philipel266f0a42016-11-28 08:49:07 -08001847TEST_P(EndToEndTest, AudioTransportFeedbackNotConfigured) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001848 TransportFeedbackTester test(false, 0, 1);
1849 RunBaseTest(&test);
1850}
1851
philipel266f0a42016-11-28 08:49:07 -08001852TEST_P(EndToEndTest, AudioVideoReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001853 TransportFeedbackTester test(true, 1, 1);
1854 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001855}
1856
philipel266f0a42016-11-28 08:49:07 -08001857TEST_P(EndToEndTest, ObserversEncodedFrames) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001858 class EncodedFrameTestObserver : public EncodedFrameObserver {
1859 public:
1860 EncodedFrameTestObserver()
Peter Boström5811a392015-12-10 13:02:50 +01001861 : length_(0), frame_type_(kEmptyFrame), called_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001862 virtual ~EncodedFrameTestObserver() {}
1863
1864 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
1865 frame_type_ = encoded_frame.frame_type_;
1866 length_ = encoded_frame.length_;
1867 buffer_.reset(new uint8_t[length_]);
1868 memcpy(buffer_.get(), encoded_frame.data_, length_);
Peter Boström5811a392015-12-10 13:02:50 +01001869 called_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001870 }
1871
Peter Boström5811a392015-12-10 13:02:50 +01001872 bool Wait() { return called_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001873
1874 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
1875 ASSERT_EQ(length_, observer.length_)
1876 << "Observed frames are of different lengths.";
1877 EXPECT_EQ(frame_type_, observer.frame_type_)
1878 << "Observed frames have different frame types.";
1879 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
1880 << "Observed encoded frames have different content.";
1881 }
1882
1883 private:
kwiberg27f982b2016-03-01 11:52:33 -08001884 std::unique_ptr<uint8_t[]> buffer_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001885 size_t length_;
1886 FrameType frame_type_;
Peter Boström5811a392015-12-10 13:02:50 +01001887 rtc::Event called_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001888 };
1889
1890 EncodedFrameTestObserver post_encode_observer;
1891 EncodedFrameTestObserver pre_decode_observer;
1892
skvlad11a9cbf2016-10-07 11:53:05 -07001893 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -07001894
stefanf116bd02015-10-27 08:29:42 -07001895 test::DirectTransport sender_transport(sender_call_.get());
1896 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001897 sender_transport.SetReceiver(receiver_call_->Receiver());
1898 receiver_transport.SetReceiver(sender_call_->Receiver());
1899
brandtr841de6a2016-11-15 07:10:52 -08001900 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001901 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -08001902 video_send_config_.post_encode_callback = &post_encode_observer;
1903 video_receive_configs_[0].pre_decode_callback = &pre_decode_observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001904
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001905 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001906 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001907
kwiberg27f982b2016-03-01 11:52:33 -08001908 std::unique_ptr<test::FrameGenerator> frame_generator(
perkjfa10b552016-10-02 23:45:26 -07001909 test::FrameGenerator::CreateChromaGenerator(kDefaultWidth,
1910 kDefaultHeight));
perkja49cbd32016-09-16 07:53:41 -07001911 test::FrameForwarder forwarder;
perkj803d97f2016-11-01 11:45:46 -07001912 video_send_stream_->SetSource(
1913 &forwarder, VideoSendStream::DegradationPreference::kBalanced);
perkja49cbd32016-09-16 07:53:41 -07001914 forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001915
Peter Boström5811a392015-12-10 13:02:50 +01001916 EXPECT_TRUE(post_encode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001917 << "Timed out while waiting for send-side encoded-frame callback.";
1918
Peter Boström5811a392015-12-10 13:02:50 +01001919 EXPECT_TRUE(pre_decode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001920 << "Timed out while waiting for pre-decode encoded-frame callback.";
1921
1922 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
1923
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001924 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001925
1926 sender_transport.StopSending();
1927 receiver_transport.StopSending();
1928
1929 DestroyStreams();
1930}
1931
philipel266f0a42016-11-28 08:49:07 -08001932TEST_P(EndToEndTest, ReceiveStreamSendsRemb) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001933 class RembObserver : public test::EndToEndTest {
1934 public:
1935 RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
1936
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001937 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
danilchap3dc929e2016-11-02 08:21:59 -07001938 test::RtcpPacketParser parser;
1939 EXPECT_TRUE(parser.Parse(packet, length));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001940
danilchap3dc929e2016-11-02 08:21:59 -07001941 if (parser.remb()->num_packets() > 0) {
1942 EXPECT_EQ(kReceiverLocalVideoSsrc, parser.remb()->sender_ssrc());
1943 EXPECT_LT(0U, parser.remb()->bitrate_bps());
1944 EXPECT_EQ(1U, parser.remb()->ssrcs().size());
1945 EXPECT_EQ(kVideoSendSsrcs[0], parser.remb()->ssrcs()[0]);
Peter Boström5811a392015-12-10 13:02:50 +01001946 observation_complete_.Set();
danilchap3dc929e2016-11-02 08:21:59 -07001947 }
1948
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001949 return SEND_PACKET;
1950 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001951 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001952 EXPECT_TRUE(Wait()) << "Timed out while waiting for a "
1953 "receiver RTCP REMB packet to be "
1954 "sent.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001955 }
1956 } test;
1957
stefane74eef12016-01-08 06:47:13 -08001958 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001959}
1960
philipel266f0a42016-11-28 08:49:07 -08001961TEST_P(EndToEndTest, VerifyBandwidthStats) {
stefanf116bd02015-10-27 08:29:42 -07001962 class RtcpObserver : public test::EndToEndTest {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001963 public:
1964 RtcpObserver()
1965 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001966 sender_call_(nullptr),
1967 receiver_call_(nullptr),
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001968 has_seen_pacer_delay_(false) {}
1969
stefanf116bd02015-10-27 08:29:42 -07001970 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001971 Call::Stats sender_stats = sender_call_->GetStats();
1972 Call::Stats receiver_stats = receiver_call_->GetStats();
1973 if (!has_seen_pacer_delay_)
1974 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
1975 if (sender_stats.send_bandwidth_bps > 0 &&
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001976 receiver_stats.recv_bandwidth_bps > 0 && has_seen_pacer_delay_) {
Peter Boström5811a392015-12-10 13:02:50 +01001977 observation_complete_.Set();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001978 }
stefanf116bd02015-10-27 08:29:42 -07001979 return SEND_PACKET;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001980 }
1981
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001982 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001983 sender_call_ = sender_call;
1984 receiver_call_ = receiver_call;
1985 }
1986
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001987 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001988 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
1989 "non-zero bandwidth stats.";
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001990 }
1991
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001992 private:
1993 Call* sender_call_;
1994 Call* receiver_call_;
1995 bool has_seen_pacer_delay_;
1996 } test;
1997
stefane74eef12016-01-08 06:47:13 -08001998 RunBaseTest(&test);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001999}
2000
stefan32f81542016-01-20 07:13:58 -08002001
2002// Verifies that it's possible to limit the send BWE by sending a REMB.
2003// This is verified by allowing the send BWE to ramp-up to >1000 kbps,
2004// then have the test generate a REMB of 500 kbps and verify that the send BWE
2005// is reduced to exactly 500 kbps. Then a REMB of 1000 kbps is generated and the
2006// test verifies that the send BWE ramps back up to exactly 1000 kbps.
philipel266f0a42016-11-28 08:49:07 -08002007TEST_P(EndToEndTest, RembWithSendSideBwe) {
stefan32f81542016-01-20 07:13:58 -08002008 class BweObserver : public test::EndToEndTest {
2009 public:
2010 BweObserver()
2011 : EndToEndTest(kDefaultTimeoutMs),
2012 sender_call_(nullptr),
2013 clock_(Clock::GetRealTimeClock()),
2014 sender_ssrc_(0),
2015 remb_bitrate_bps_(1000000),
2016 receive_transport_(nullptr),
2017 event_(false, false),
2018 poller_thread_(&BitrateStatsPollingThread,
2019 this,
2020 "BitrateStatsPollingThread"),
Erik Språng737336d2016-07-29 12:59:36 +02002021 state_(kWaitForFirstRampUp),
2022 retransmission_rate_limiter_(clock_, 1000) {}
stefan32f81542016-01-20 07:13:58 -08002023
2024 ~BweObserver() {}
2025
nisseef8b61e2016-04-29 06:09:15 -07002026 test::PacketTransport* CreateReceiveTransport() override {
stefan32f81542016-01-20 07:13:58 -08002027 receive_transport_ = new test::PacketTransport(
2028 nullptr, this, test::PacketTransport::kReceiver,
2029 FakeNetworkPipe::Config());
2030 return receive_transport_;
2031 }
2032
2033 Call::Config GetSenderCallConfig() override {
skvlad11a9cbf2016-10-07 11:53:05 -07002034 Call::Config config(&event_log_);
stefan32f81542016-01-20 07:13:58 -08002035 // Set a high start bitrate to reduce the test completion time.
2036 config.bitrate_config.start_bitrate_bps = remb_bitrate_bps_;
2037 return config;
2038 }
2039
2040 void ModifyVideoConfigs(
2041 VideoSendStream::Config* send_config,
2042 std::vector<VideoReceiveStream::Config>* receive_configs,
2043 VideoEncoderConfig* encoder_config) override {
2044 ASSERT_EQ(1u, send_config->rtp.ssrcs.size());
2045 send_config->rtp.extensions.clear();
2046 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07002047 RtpExtension(RtpExtension::kTransportSequenceNumberUri,
stefan32f81542016-01-20 07:13:58 -08002048 test::kTransportSequenceNumberExtensionId));
2049 sender_ssrc_ = send_config->rtp.ssrcs[0];
2050
perkjfa10b552016-10-02 23:45:26 -07002051 encoder_config->max_bitrate_bps = 2000000;
stefan32f81542016-01-20 07:13:58 -08002052
2053 ASSERT_EQ(1u, receive_configs->size());
2054 (*receive_configs)[0].rtp.remb = false;
2055 (*receive_configs)[0].rtp.transport_cc = true;
2056 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
2057 RtpRtcp::Configuration config;
2058 config.receiver_only = true;
2059 config.clock = clock_;
2060 config.outgoing_transport = receive_transport_;
Erik Språng737336d2016-07-29 12:59:36 +02002061 config.retransmission_rate_limiter = &retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08002062 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
2063 rtp_rtcp_->SetRemoteSSRC((*receive_configs)[0].rtp.remote_ssrc);
2064 rtp_rtcp_->SetSSRC((*receive_configs)[0].rtp.local_ssrc);
2065 rtp_rtcp_->SetREMBStatus(true);
2066 rtp_rtcp_->SetSendingStatus(true);
2067 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
2068 }
2069
2070 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2071 sender_call_ = sender_call;
2072 }
2073
2074 static bool BitrateStatsPollingThread(void* obj) {
2075 return static_cast<BweObserver*>(obj)->PollStats();
2076 }
2077
2078 bool PollStats() {
2079 if (sender_call_) {
2080 Call::Stats stats = sender_call_->GetStats();
2081 switch (state_) {
2082 case kWaitForFirstRampUp:
2083 if (stats.send_bandwidth_bps >= remb_bitrate_bps_) {
2084 state_ = kWaitForRemb;
2085 remb_bitrate_bps_ /= 2;
2086 rtp_rtcp_->SetREMBData(
2087 remb_bitrate_bps_,
2088 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
2089 rtp_rtcp_->SendRTCP(kRtcpRr);
2090 }
2091 break;
2092
2093 case kWaitForRemb:
2094 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
2095 state_ = kWaitForSecondRampUp;
2096 remb_bitrate_bps_ *= 2;
2097 rtp_rtcp_->SetREMBData(
2098 remb_bitrate_bps_,
2099 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
2100 rtp_rtcp_->SendRTCP(kRtcpRr);
2101 }
2102 break;
2103
2104 case kWaitForSecondRampUp:
2105 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
2106 observation_complete_.Set();
2107 }
2108 break;
2109 }
2110 }
2111
2112 return !event_.Wait(1000);
2113 }
2114
2115 void PerformTest() override {
2116 poller_thread_.Start();
2117 EXPECT_TRUE(Wait())
2118 << "Timed out while waiting for bitrate to change according to REMB.";
2119 poller_thread_.Stop();
2120 }
2121
2122 private:
2123 enum TestState { kWaitForFirstRampUp, kWaitForRemb, kWaitForSecondRampUp };
2124
2125 Call* sender_call_;
2126 Clock* const clock_;
2127 uint32_t sender_ssrc_;
2128 int remb_bitrate_bps_;
kwiberg27f982b2016-03-01 11:52:33 -08002129 std::unique_ptr<RtpRtcp> rtp_rtcp_;
stefan32f81542016-01-20 07:13:58 -08002130 test::PacketTransport* receive_transport_;
2131 rtc::Event event_;
2132 rtc::PlatformThread poller_thread_;
2133 TestState state_;
Erik Språng737336d2016-07-29 12:59:36 +02002134 RateLimiter retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08002135 } test;
2136
2137 RunBaseTest(&test);
2138}
2139
philipel266f0a42016-11-28 08:49:07 -08002140TEST_P(EndToEndTest, VerifyNackStats) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002141 static const int kPacketNumberToDrop = 200;
2142 class NackObserver : public test::EndToEndTest {
2143 public:
2144 NackObserver()
2145 : EndToEndTest(kLongTimeoutMs),
2146 sent_rtp_packets_(0),
2147 dropped_rtp_packet_(0),
2148 dropped_rtp_packet_requested_(false),
2149 send_stream_(nullptr),
2150 start_runtime_ms_(-1) {}
2151
2152 private:
2153 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002154 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002155 if (++sent_rtp_packets_ == kPacketNumberToDrop) {
kwiberg27f982b2016-03-01 11:52:33 -08002156 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
Åsa Persson352b2d72015-04-15 18:00:40 +02002157 RTPHeader header;
2158 EXPECT_TRUE(parser->Parse(packet, length, &header));
2159 dropped_rtp_packet_ = header.sequenceNumber;
2160 return DROP_PACKET;
2161 }
2162 VerifyStats();
2163 return SEND_PACKET;
2164 }
2165
2166 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002167 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002168 test::RtcpPacketParser rtcp_parser;
2169 rtcp_parser.Parse(packet, length);
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02002170 const std::vector<uint16_t>& nacks = rtcp_parser.nack()->packet_ids();
Åsa Persson352b2d72015-04-15 18:00:40 +02002171 if (!nacks.empty() && std::find(
2172 nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) {
2173 dropped_rtp_packet_requested_ = true;
2174 }
2175 return SEND_PACKET;
2176 }
2177
stefan608213e2015-11-01 14:56:10 -08002178 void VerifyStats() EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002179 if (!dropped_rtp_packet_requested_)
2180 return;
2181 int send_stream_nack_packets = 0;
2182 int receive_stream_nack_packets = 0;
2183 VideoSendStream::Stats stats = send_stream_->GetStats();
2184 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
2185 stats.substreams.begin(); it != stats.substreams.end(); ++it) {
2186 const VideoSendStream::StreamStats& stream_stats = it->second;
2187 send_stream_nack_packets +=
2188 stream_stats.rtcp_packet_type_counts.nack_packets;
2189 }
2190 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2191 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2192 receive_stream_nack_packets +=
2193 stats.rtcp_packet_type_counts.nack_packets;
2194 }
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002195 if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002196 // NACK packet sent on receive stream and received on sent stream.
2197 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002198 observation_complete_.Set();
Åsa Persson352b2d72015-04-15 18:00:40 +02002199 }
2200 }
2201
2202 bool MinMetricRunTimePassed() {
2203 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2204 if (start_runtime_ms_ == -1) {
2205 start_runtime_ms_ = now;
2206 return false;
2207 }
2208 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2209 return elapsed_sec > metrics::kMinRunTimeInSeconds;
2210 }
2211
stefanff483612015-12-21 03:14:00 -08002212 void ModifyVideoConfigs(
2213 VideoSendStream::Config* send_config,
2214 std::vector<VideoReceiveStream::Config>* receive_configs,
2215 VideoEncoderConfig* encoder_config) override {
Åsa Persson352b2d72015-04-15 18:00:40 +02002216 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2217 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sakal55d932b2016-09-30 06:19:08 -07002218 (*receive_configs)[0].renderer = &fake_renderer_;
Åsa Persson352b2d72015-04-15 18:00:40 +02002219 }
2220
stefanff483612015-12-21 03:14:00 -08002221 void OnVideoStreamsCreated(
Åsa Persson352b2d72015-04-15 18:00:40 +02002222 VideoSendStream* send_stream,
2223 const std::vector<VideoReceiveStream*>& receive_streams) override {
2224 send_stream_ = send_stream;
2225 receive_streams_ = receive_streams;
2226 }
2227
2228 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002229 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson352b2d72015-04-15 18:00:40 +02002230 }
2231
sakal55d932b2016-09-30 06:19:08 -07002232 test::FakeVideoRenderer fake_renderer_;
stefan608213e2015-11-01 14:56:10 -08002233 rtc::CriticalSection crit_;
Åsa Persson352b2d72015-04-15 18:00:40 +02002234 uint64_t sent_rtp_packets_;
stefan608213e2015-11-01 14:56:10 -08002235 uint16_t dropped_rtp_packet_ GUARDED_BY(&crit_);
2236 bool dropped_rtp_packet_requested_ GUARDED_BY(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002237 std::vector<VideoReceiveStream*> receive_streams_;
2238 VideoSendStream* send_stream_;
2239 int64_t start_runtime_ms_;
2240 } test;
2241
asapersson01d70a32016-05-20 06:29:46 -07002242 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002243 RunBaseTest(&test);
Åsa Persson352b2d72015-04-15 18:00:40 +02002244
asapersson01d70a32016-05-20 06:29:46 -07002245 EXPECT_EQ(
2246 1, metrics::NumSamples("WebRTC.Video.UniqueNackRequestsSentInPercent"));
2247 EXPECT_EQ(1, metrics::NumSamples(
2248 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
2249 EXPECT_GT(metrics::MinSample("WebRTC.Video.NackPacketsSentPerMinute"), 0);
Åsa Persson352b2d72015-04-15 18:00:40 +02002250}
2251
sprangb4a1ae52015-12-03 08:10:08 -08002252void EndToEndTest::VerifyHistogramStats(bool use_rtx,
2253 bool use_red,
2254 bool screenshare) {
tommi2e82f382016-06-21 00:26:43 -07002255 class StatsObserver : public test::EndToEndTest,
2256 public rtc::VideoSinkInterface<VideoFrame> {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002257 public:
sprangb4a1ae52015-12-03 08:10:08 -08002258 StatsObserver(bool use_rtx, bool use_red, bool screenshare)
Åsa Persson3c391cb2015-04-27 10:09:49 +02002259 : EndToEndTest(kLongTimeoutMs),
2260 use_rtx_(use_rtx),
2261 use_red_(use_red),
sprangb4a1ae52015-12-03 08:10:08 -08002262 screenshare_(screenshare),
Peter Boström39593972016-02-15 11:27:15 +01002263 // This test uses NACK, so to send FEC we can't use a fake encoder.
magjed509e4fe2016-11-18 01:34:11 -08002264 vp8_encoder_(use_red ? VP8Encoder::Create() : nullptr),
Åsa Persson3c391cb2015-04-27 10:09:49 +02002265 sender_call_(nullptr),
2266 receiver_call_(nullptr),
asapersson1394c7b2016-10-18 11:50:50 -07002267 start_runtime_ms_(-1),
2268 num_frames_received_(0) {}
Åsa Persson3c391cb2015-04-27 10:09:49 +02002269
2270 private:
asapersson1394c7b2016-10-18 11:50:50 -07002271 void OnFrame(const VideoFrame& video_frame) override {
2272 // The RTT is needed to estimate |ntp_time_ms| which is used by
2273 // end-to-end delay stats. Therefore, start counting received frames once
2274 // |ntp_time_ms| is valid.
2275 if (video_frame.ntp_time_ms() > 0 &&
2276 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() >=
2277 video_frame.ntp_time_ms()) {
2278 rtc::CritScope lock(&crit_);
2279 ++num_frames_received_;
2280 }
2281 }
tommi2e82f382016-06-21 00:26:43 -07002282
Åsa Persson3c391cb2015-04-27 10:09:49 +02002283 Action OnSendRtp(const uint8_t* packet, size_t length) override {
asapersson1394c7b2016-10-18 11:50:50 -07002284 if (MinMetricRunTimePassed() && MinNumberOfFramesReceived())
Peter Boström5811a392015-12-10 13:02:50 +01002285 observation_complete_.Set();
Åsa Persson3c391cb2015-04-27 10:09:49 +02002286
stefanf116bd02015-10-27 08:29:42 -07002287 return SEND_PACKET;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002288 }
2289
2290 bool MinMetricRunTimePassed() {
2291 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2292 if (start_runtime_ms_ == -1) {
2293 start_runtime_ms_ = now;
2294 return false;
2295 }
2296 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2297 return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
2298 }
2299
asapersson1394c7b2016-10-18 11:50:50 -07002300 bool MinNumberOfFramesReceived() const {
2301 const int kMinRequiredHistogramSamples = 200;
2302 rtc::CritScope lock(&crit_);
2303 return num_frames_received_ > kMinRequiredHistogramSamples;
2304 }
2305
stefanff483612015-12-21 03:14:00 -08002306 void ModifyVideoConfigs(
2307 VideoSendStream::Config* send_config,
2308 std::vector<VideoReceiveStream::Config>* receive_configs,
2309 VideoEncoderConfig* encoder_config) override {
stefana23fc622016-07-28 07:56:38 -07002310 static const int kExtensionId = 8;
2311 send_config->rtp.extensions.push_back(RtpExtension(
2312 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
2313 (*receive_configs)[0].rtp.extensions.push_back(RtpExtension(
2314 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002315 // NACK
2316 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2317 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
tommi2e82f382016-06-21 00:26:43 -07002318 (*receive_configs)[0].renderer = this;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002319 // FEC
2320 if (use_red_) {
brandtrb5f2c3f2016-10-04 23:28:39 -07002321 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
2322 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
Peter Boström39593972016-02-15 11:27:15 +01002323 send_config->encoder_settings.encoder = vp8_encoder_.get();
2324 send_config->encoder_settings.payload_name = "VP8";
2325 (*receive_configs)[0].decoders[0].payload_name = "VP8";
brandtrb5f2c3f2016-10-04 23:28:39 -07002326 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
2327 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type =
2328 kUlpfecPayloadType;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002329 }
2330 // RTX
2331 if (use_rtx_) {
2332 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
2333 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
brandtr14742122017-01-27 04:53:07 -08002334 (*receive_configs)[0].rtp.rtx_ssrc = kSendRtxSsrcs[0];
2335 (*receive_configs)[0].rtp.rtx_payload_types[kFakeVideoSendPayloadType] =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002336 kSendRtxPayloadType;
2337 }
asapersson1490f7a2016-09-23 02:09:46 -07002338 // RTT needed for RemoteNtpTimeEstimator for the receive stream.
2339 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = true;
sprangb4a1ae52015-12-03 08:10:08 -08002340 encoder_config->content_type =
2341 screenshare_ ? VideoEncoderConfig::ContentType::kScreen
2342 : VideoEncoderConfig::ContentType::kRealtimeVideo;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002343 }
2344
2345 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2346 sender_call_ = sender_call;
2347 receiver_call_ = receiver_call;
2348 }
2349
Åsa Persson3c391cb2015-04-27 10:09:49 +02002350 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002351 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson3c391cb2015-04-27 10:09:49 +02002352 }
2353
asapersson1394c7b2016-10-18 11:50:50 -07002354 rtc::CriticalSection crit_;
sprangb4a1ae52015-12-03 08:10:08 -08002355 const bool use_rtx_;
2356 const bool use_red_;
2357 const bool screenshare_;
kwiberg27f982b2016-03-01 11:52:33 -08002358 const std::unique_ptr<VideoEncoder> vp8_encoder_;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002359 Call* sender_call_;
2360 Call* receiver_call_;
2361 int64_t start_runtime_ms_;
asapersson1394c7b2016-10-18 11:50:50 -07002362 int num_frames_received_ GUARDED_BY(&crit_);
sprangb4a1ae52015-12-03 08:10:08 -08002363 } test(use_rtx, use_red, screenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002364
asapersson01d70a32016-05-20 06:29:46 -07002365 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002366 RunBaseTest(&test);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002367
stefan91d92602015-11-11 10:13:02 -08002368 // Delete the call for Call stats to be reported.
stefan18adf0a2015-11-17 06:24:56 -08002369 sender_call_.reset();
stefan91d92602015-11-11 10:13:02 -08002370 receiver_call_.reset();
2371
sprangb4a1ae52015-12-03 08:10:08 -08002372 std::string video_prefix =
2373 screenshare ? "WebRTC.Video.Screenshare." : "WebRTC.Video.";
2374
Åsa Persson3c391cb2015-04-27 10:09:49 +02002375 // Verify that stats have been updated once.
asapersson4374a092016-07-27 00:39:09 -07002376 EXPECT_EQ(2, metrics::NumSamples("WebRTC.Call.LifetimeInSeconds"));
asapersson01d70a32016-05-20 06:29:46 -07002377 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
2378 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.RtcpBitrateReceivedInBps"));
2379 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.BitrateReceivedInKbps"));
2380 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.EstimatedSendBitrateInKbps"));
2381 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.PacerBitrateInKbps"));
2382
asapersson4374a092016-07-27 00:39:09 -07002383 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
2384 EXPECT_EQ(1,
2385 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
2386
asapersson01d70a32016-05-20 06:29:46 -07002387 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
stefan91d92602015-11-11 10:13:02 -08002388 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002389 metrics::NumSamples(video_prefix + "NackPacketsReceivedPerMinute"));
2390 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
asaperssond89920b2015-07-22 06:52:00 -07002391 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002392 metrics::NumSamples(video_prefix + "FirPacketsReceivedPerMinute"));
2393 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
sprangb4a1ae52015-12-03 08:10:08 -08002394 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002395 metrics::NumSamples(video_prefix + "PliPacketsReceivedPerMinute"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002396
asapersson01d70a32016-05-20 06:29:46 -07002397 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "KeyFramesSentInPermille"));
2398 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
2399
2400 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentPacketsLostInPercent"));
2401 EXPECT_EQ(1,
2402 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
2403
2404 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputWidthInPixels"));
2405 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputHeightInPixels"));
2406 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentWidthInPixels"));
2407 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentHeightInPixels"));
2408 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
2409 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
2410
perkjfa10b552016-10-02 23:45:26 -07002411 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputWidthInPixels",
2412 kDefaultWidth));
2413 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputHeightInPixels",
2414 kDefaultHeight));
2415 EXPECT_EQ(
2416 1, metrics::NumEvents(video_prefix + "SentWidthInPixels", kDefaultWidth));
2417 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "SentHeightInPixels",
2418 kDefaultHeight));
2419 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedWidthInPixels",
2420 kDefaultWidth));
2421 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedHeightInPixels",
2422 kDefaultHeight));
asapersson01d70a32016-05-20 06:29:46 -07002423
2424 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputFramesPerSecond"));
2425 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentFramesPerSecond"));
2426 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
2427 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
2428
2429 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
2430 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
2431 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
2432 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
2433
asapersson1490f7a2016-09-23 02:09:46 -07002434 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.EndToEndDelayInMs"));
asapersson01d70a32016-05-20 06:29:46 -07002435 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
2436
2437 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EncodeTimeInMs"));
2438 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
2439
asapersson66d4b372016-12-19 06:50:53 -08002440 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "NumberOfPauseEvents"));
2441 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PausedTimeInPercent"));
2442
asapersson01d70a32016-05-20 06:29:46 -07002443 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "BitrateSentInKbps"));
2444 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateReceivedInKbps"));
2445 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "MediaBitrateSentInKbps"));
2446 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateReceivedInKbps"));
2447 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PaddingBitrateSentInKbps"));
2448 EXPECT_EQ(1,
2449 metrics::NumSamples("WebRTC.Video.PaddingBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002450 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002451 1, metrics::NumSamples(video_prefix + "RetransmittedBitrateSentInKbps"));
2452 EXPECT_EQ(1, metrics::NumSamples(
2453 "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002454
asapersson01d70a32016-05-20 06:29:46 -07002455 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendDelayInMs"));
2456 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayInMs"));
2457 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayMaxInMs"));
asapersson6f14be82015-11-16 00:40:49 -08002458
Åsa Persson3c391cb2015-04-27 10:09:49 +02002459 int num_rtx_samples = use_rtx ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002460 EXPECT_EQ(num_rtx_samples,
2461 metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2462 EXPECT_EQ(num_rtx_samples,
2463 metrics::NumSamples("WebRTC.Video.RtxBitrateReceivedInKbps"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002464
2465 int num_red_samples = use_red ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002466 EXPECT_EQ(num_red_samples,
2467 metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2468 EXPECT_EQ(num_red_samples,
2469 metrics::NumSamples("WebRTC.Video.FecBitrateReceivedInKbps"));
2470 EXPECT_EQ(num_red_samples,
2471 metrics::NumSamples("WebRTC.Video.ReceivedFecPacketsInPercent"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002472}
2473
philipel266f0a42016-11-28 08:49:07 -08002474TEST_P(EndToEndTest, VerifyHistogramStatsWithRtx) {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002475 const bool kEnabledRtx = true;
2476 const bool kEnabledRed = false;
sprangb4a1ae52015-12-03 08:10:08 -08002477 const bool kScreenshare = false;
2478 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002479}
2480
philipel266f0a42016-11-28 08:49:07 -08002481TEST_P(EndToEndTest, VerifyHistogramStatsWithRed) {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002482 const bool kEnabledRtx = false;
2483 const bool kEnabledRed = true;
sprangb4a1ae52015-12-03 08:10:08 -08002484 const bool kScreenshare = false;
2485 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
2486}
2487
philipel266f0a42016-11-28 08:49:07 -08002488TEST_P(EndToEndTest, VerifyHistogramStatsWithScreenshare) {
sprangb4a1ae52015-12-03 08:10:08 -08002489 const bool kEnabledRtx = false;
2490 const bool kEnabledRed = false;
2491 const bool kScreenshare = true;
2492 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002493}
2494
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002495void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
2496 bool send_single_ssrc_first) {
2497 class SendsSetSsrcs : public test::EndToEndTest {
2498 public:
2499 SendsSetSsrcs(const uint32_t* ssrcs,
2500 size_t num_ssrcs,
2501 bool send_single_ssrc_first)
2502 : EndToEndTest(kDefaultTimeoutMs),
2503 num_ssrcs_(num_ssrcs),
2504 send_single_ssrc_first_(send_single_ssrc_first),
2505 ssrcs_to_observe_(num_ssrcs),
sprang867fb522015-08-03 04:38:41 -07002506 expect_single_ssrc_(send_single_ssrc_first),
2507 send_stream_(nullptr) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002508 for (size_t i = 0; i < num_ssrcs; ++i)
2509 valid_ssrcs_[ssrcs[i]] = true;
2510 }
2511
2512 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002513 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002514 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002515 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002516
2517 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
2518 << "Received unknown SSRC: " << header.ssrc;
2519
2520 if (!valid_ssrcs_[header.ssrc])
Peter Boström5811a392015-12-10 13:02:50 +01002521 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002522
2523 if (!is_observed_[header.ssrc]) {
2524 is_observed_[header.ssrc] = true;
2525 --ssrcs_to_observe_;
2526 if (expect_single_ssrc_) {
2527 expect_single_ssrc_ = false;
Peter Boström5811a392015-12-10 13:02:50 +01002528 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002529 }
2530 }
2531
2532 if (ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002533 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002534
2535 return SEND_PACKET;
2536 }
2537
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002538 size_t GetNumVideoStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002539
perkjfa10b552016-10-02 23:45:26 -07002540 // This test use other VideoStream settings than the the default settings
2541 // implemented in DefaultVideoStreamFactory. Therefore this test implement
2542 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
2543 // in ModifyVideoConfigs.
2544 class VideoStreamFactory
2545 : public VideoEncoderConfig::VideoStreamFactoryInterface {
2546 public:
2547 VideoStreamFactory() {}
2548
2549 private:
2550 std::vector<VideoStream> CreateEncoderStreams(
2551 int width,
2552 int height,
2553 const VideoEncoderConfig& encoder_config) override {
2554 std::vector<VideoStream> streams =
2555 test::CreateVideoStreams(width, height, encoder_config);
2556 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
2557 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
2558 streams[i].min_bitrate_bps = 10000;
2559 streams[i].target_bitrate_bps = 15000;
2560 streams[i].max_bitrate_bps = 20000;
2561 }
2562 return streams;
2563 }
2564 };
2565
stefanff483612015-12-21 03:14:00 -08002566 void ModifyVideoConfigs(
2567 VideoSendStream::Config* send_config,
2568 std::vector<VideoReceiveStream::Config>* receive_configs,
2569 VideoEncoderConfig* encoder_config) override {
perkjfa10b552016-10-02 23:45:26 -07002570 encoder_config->video_stream_factory =
2571 new rtc::RefCountedObject<VideoStreamFactory>();
perkj26091b12016-09-01 01:17:40 -07002572 video_encoder_config_all_streams_ = encoder_config->Copy();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002573 if (send_single_ssrc_first_)
perkjfa10b552016-10-02 23:45:26 -07002574 encoder_config->number_of_streams = 1;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002575 }
2576
stefanff483612015-12-21 03:14:00 -08002577 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002578 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002579 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002580 send_stream_ = send_stream;
2581 }
2582
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002583 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002584 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2585 << (send_single_ssrc_first_ ? "first SSRC."
2586 : "SSRCs.");
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002587
2588 if (send_single_ssrc_first_) {
2589 // Set full simulcast and continue with the rest of the SSRCs.
stefanff483612015-12-21 03:14:00 -08002590 send_stream_->ReconfigureVideoEncoder(
perkj26091b12016-09-01 01:17:40 -07002591 std::move(video_encoder_config_all_streams_));
Peter Boström5811a392015-12-10 13:02:50 +01002592 EXPECT_TRUE(Wait()) << "Timed out while waiting on additional SSRCs.";
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002593 }
2594 }
2595
2596 private:
2597 std::map<uint32_t, bool> valid_ssrcs_;
2598 std::map<uint32_t, bool> is_observed_;
2599
2600 const size_t num_ssrcs_;
2601 const bool send_single_ssrc_first_;
2602
2603 size_t ssrcs_to_observe_;
2604 bool expect_single_ssrc_;
2605
2606 VideoSendStream* send_stream_;
stefanff483612015-12-21 03:14:00 -08002607 VideoEncoderConfig video_encoder_config_all_streams_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002608 } test(kVideoSendSsrcs, num_ssrcs, send_single_ssrc_first);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002609
stefane74eef12016-01-08 06:47:13 -08002610 RunBaseTest(&test);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002611}
2612
philipel266f0a42016-11-28 08:49:07 -08002613TEST_P(EndToEndTest, ReportsSetEncoderRates) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002614 class EncoderRateStatsTest : public test::EndToEndTest,
2615 public test::FakeEncoder {
2616 public:
2617 EncoderRateStatsTest()
2618 : EndToEndTest(kDefaultTimeoutMs),
sprang867fb522015-08-03 04:38:41 -07002619 FakeEncoder(Clock::GetRealTimeClock()),
2620 send_stream_(nullptr),
2621 bitrate_kbps_(0) {}
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002622
stefanff483612015-12-21 03:14:00 -08002623 void OnVideoStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002624 VideoSendStream* send_stream,
2625 const std::vector<VideoReceiveStream*>& receive_streams) override {
2626 send_stream_ = send_stream;
2627 }
2628
stefanff483612015-12-21 03:14:00 -08002629 void ModifyVideoConfigs(
2630 VideoSendStream::Config* send_config,
2631 std::vector<VideoReceiveStream::Config>* receive_configs,
2632 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002633 send_config->encoder_settings.encoder = this;
kwibergaf476c72016-11-28 15:21:39 -08002634 RTC_DCHECK_EQ(1, encoder_config->number_of_streams);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002635 }
2636
Erik Språng08127a92016-11-16 16:41:30 +01002637 int32_t SetRateAllocation(const BitrateAllocation& rate_allocation,
2638 uint32_t framerate) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002639 // Make sure not to trigger on any default zero bitrates.
Erik Språng08127a92016-11-16 16:41:30 +01002640 if (rate_allocation.get_sum_bps() == 0)
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002641 return 0;
Peter Boströmf2f82832015-05-01 13:00:41 +02002642 rtc::CritScope lock(&crit_);
Erik Språng08127a92016-11-16 16:41:30 +01002643 bitrate_kbps_ = rate_allocation.get_sum_kbps();
Peter Boström5811a392015-12-10 13:02:50 +01002644 observation_complete_.Set();
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002645 return 0;
2646 }
2647
2648 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002649 ASSERT_TRUE(Wait())
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002650 << "Timed out while waiting for encoder SetRates() call.";
perkjf5b2e512016-07-05 08:34:04 -07002651 WaitForEncoderTargetBitrateMatchStats();
2652 send_stream_->Stop();
2653 WaitForStatsReportZeroTargetBitrate();
2654 send_stream_->Start();
2655 WaitForEncoderTargetBitrateMatchStats();
2656 }
2657
2658 void WaitForEncoderTargetBitrateMatchStats() {
Peter Boström5811a392015-12-10 13:02:50 +01002659 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002660 VideoSendStream::Stats stats = send_stream_->GetStats();
2661 {
Peter Boströmf2f82832015-05-01 13:00:41 +02002662 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002663 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
2664 static_cast<int>(bitrate_kbps_)) {
2665 return;
2666 }
2667 }
2668 SleepMs(1);
2669 }
2670 FAIL()
2671 << "Timed out waiting for stats reporting the currently set bitrate.";
2672 }
2673
perkjf5b2e512016-07-05 08:34:04 -07002674 void WaitForStatsReportZeroTargetBitrate() {
2675 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
2676 if (send_stream_->GetStats().target_media_bitrate_bps == 0) {
2677 return;
2678 }
2679 SleepMs(1);
2680 }
2681 FAIL() << "Timed out waiting for stats reporting zero bitrate.";
2682 }
2683
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002684 private:
stefanf116bd02015-10-27 08:29:42 -07002685 rtc::CriticalSection crit_;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002686 VideoSendStream* send_stream_;
2687 uint32_t bitrate_kbps_ GUARDED_BY(crit_);
2688 } test;
2689
stefane74eef12016-01-08 06:47:13 -08002690 RunBaseTest(&test);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002691}
2692
philipel266f0a42016-11-28 08:49:07 -08002693TEST_P(EndToEndTest, GetStats) {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002694 static const int kStartBitrateBps = 3000000;
Peter Boströmdef398832015-05-27 17:59:11 +02002695 static const int kExpectedRenderDelayMs = 20;
tommi2e82f382016-06-21 00:26:43 -07002696
2697 class ReceiveStreamRenderer : public rtc::VideoSinkInterface<VideoFrame> {
2698 public:
2699 ReceiveStreamRenderer() {}
2700
2701 private:
2702 void OnFrame(const VideoFrame& video_frame) override {}
2703 };
2704
nissed30a1112016-04-18 05:15:22 -07002705 class StatsObserver : public test::EndToEndTest,
2706 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002707 public:
stefanf116bd02015-10-27 08:29:42 -07002708 StatsObserver()
2709 : EndToEndTest(kLongTimeoutMs),
Peter Boströmc6e16e32016-02-05 14:15:53 +01002710 encoder_(Clock::GetRealTimeClock(), 10),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002711 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002712 expected_send_ssrcs_(),
Peter Boström5811a392015-12-10 13:02:50 +01002713 check_stats_event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002714
2715 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002716 Action OnSendRtp(const uint8_t* packet, size_t length) override {
sprangcd349d92016-07-13 09:11:28 -07002717 // Drop every 25th packet => 4% loss.
2718 static const int kPacketLossFrac = 25;
2719 RTPHeader header;
2720 RtpUtility::RtpHeaderParser parser(packet, length);
2721 if (parser.Parse(&header) &&
2722 expected_send_ssrcs_.find(header.ssrc) !=
2723 expected_send_ssrcs_.end() &&
2724 header.sequenceNumber % kPacketLossFrac == 0) {
2725 return DROP_PACKET;
2726 }
Peter Boström5811a392015-12-10 13:02:50 +01002727 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002728 return SEND_PACKET;
2729 }
2730
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002731 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002732 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002733 return SEND_PACKET;
2734 }
2735
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002736 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002737 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002738 return SEND_PACKET;
2739 }
2740
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002741 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002742 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002743 return SEND_PACKET;
2744 }
2745
nissed30a1112016-04-18 05:15:22 -07002746 void OnFrame(const VideoFrame& video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002747 // Ensure that we have at least 5ms send side delay.
nissed30a1112016-04-18 05:15:22 -07002748 SleepMs(5);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002749 }
2750
2751 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002752 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2753 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2754 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002755
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002756 // Make sure all fields have been populated.
2757 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
2758 // always filled for all receivers.
2759 receive_stats_filled_["IncomingRate"] |=
2760 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002761
Peter Boströmb7d9a972015-12-18 16:01:11 +01002762 send_stats_filled_["DecoderImplementationName"] |=
2763 stats.decoder_implementation_name ==
2764 test::FakeDecoder::kImplementationName;
Peter Boströmdef398832015-05-27 17:59:11 +02002765 receive_stats_filled_["RenderDelayAsHighAsExpected"] |=
2766 stats.render_delay_ms >= kExpectedRenderDelayMs;
2767
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002768 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002769
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002770 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002771
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002772 receive_stats_filled_["StatisticsUpdated"] |=
2773 stats.rtcp_stats.cumulative_lost != 0 ||
2774 stats.rtcp_stats.extended_max_sequence_number != 0 ||
2775 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002776
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002777 receive_stats_filled_["DataCountersUpdated"] |=
2778 stats.rtp_stats.transmitted.payload_bytes != 0 ||
2779 stats.rtp_stats.fec.packets != 0 ||
2780 stats.rtp_stats.transmitted.header_bytes != 0 ||
2781 stats.rtp_stats.transmitted.packets != 0 ||
2782 stats.rtp_stats.transmitted.padding_bytes != 0 ||
2783 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002784
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002785 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002786 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002787
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002788 receive_stats_filled_["FrameCounts"] |=
2789 stats.frame_counts.key_frames != 0 ||
2790 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002791
pbosbb36fdf2015-07-09 07:48:14 -07002792 receive_stats_filled_["CName"] |= !stats.c_name.empty();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002793
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002794 receive_stats_filled_["RtcpPacketTypeCount"] |=
2795 stats.rtcp_packet_type_counts.fir_packets != 0 ||
2796 stats.rtcp_packet_type_counts.nack_packets != 0 ||
2797 stats.rtcp_packet_type_counts.pli_packets != 0 ||
2798 stats.rtcp_packet_type_counts.nack_requests != 0 ||
2799 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbosf42376c2015-08-28 07:35:32 -07002800
2801 assert(stats.current_payload_type == -1 ||
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002802 stats.current_payload_type == kFakeVideoSendPayloadType);
pbosf42376c2015-08-28 07:35:32 -07002803 receive_stats_filled_["IncomingPayloadType"] |=
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002804 stats.current_payload_type == kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002805 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002806
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002807 return AllStatsFilled(receive_stats_filled_);
2808 }
2809
2810 bool CheckSendStats() {
Peter Boström74f6e9e2016-04-04 17:56:10 +02002811 RTC_DCHECK(send_stream_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002812 VideoSendStream::Stats stats = send_stream_->GetStats();
2813
philipel20d05a92016-12-19 04:17:27 -08002814 size_t expected_num_streams = kNumSsrcs + expected_send_ssrcs_.size();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002815 send_stats_filled_["NumStreams"] |=
philipel20d05a92016-12-19 04:17:27 -08002816 stats.substreams.size() == expected_num_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002817
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002818 send_stats_filled_["CpuOveruseMetrics"] |=
Peter Boströme4499152016-02-05 11:13:28 +01002819 stats.avg_encode_time_ms != 0 && stats.encode_usage_percent != 0;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002820
Peter Boströmb7d9a972015-12-18 16:01:11 +01002821 send_stats_filled_["EncoderImplementationName"] |=
2822 stats.encoder_implementation_name ==
2823 test::FakeEncoder::kImplementationName;
2824
Pera48ddb72016-09-29 11:48:50 +02002825 send_stats_filled_["EncoderPreferredBitrate"] |=
2826 stats.preferred_media_bitrate_bps > 0;
2827
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002828 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002829 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002830 it != stats.substreams.end(); ++it) {
sprangcd349d92016-07-13 09:11:28 -07002831 if (expected_send_ssrcs_.find(it->first) == expected_send_ssrcs_.end())
2832 continue; // Probably RTX.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002833
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002834 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002835 stats.input_frame_rate != 0;
2836
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002837 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002838
2839 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
2840 stream_stats.rtcp_stats.cumulative_lost != 0 ||
2841 stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
2842 stream_stats.rtcp_stats.fraction_lost != 0;
2843
2844 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002845 stream_stats.rtp_stats.fec.packets != 0 ||
2846 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
2847 stream_stats.rtp_stats.retransmitted.packets != 0 ||
2848 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002849
sprangcd349d92016-07-13 09:11:28 -07002850 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Total",
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002851 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002852 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002853
sprangcd349d92016-07-13 09:11:28 -07002854 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Retransmit",
2855 it->first)] |=
2856 stream_stats.retransmit_bitrate_bps != 0;
2857
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002858 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002859 stream_stats.frame_counts.delta_frames != 0 ||
2860 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002861
2862 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
2863 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00002864
2865 send_stats_filled_[CompoundKey("Delay", it->first)] |=
2866 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002867
2868 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
2869 // report dropped packets.
2870 send_stats_filled_["RtcpPacketTypeCount"] |=
2871 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
2872 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
2873 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
2874 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
2875 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002876 }
2877
2878 return AllStatsFilled(send_stats_filled_);
2879 }
2880
2881 std::string CompoundKey(const char* name, uint32_t ssrc) {
2882 std::ostringstream oss;
2883 oss << name << "_" << ssrc;
2884 return oss.str();
2885 }
2886
2887 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
sprangcd349d92016-07-13 09:11:28 -07002888 for (const auto& stat : stats_map) {
2889 if (!stat.second)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002890 return false;
2891 }
2892 return true;
2893 }
2894
stefane74eef12016-01-08 06:47:13 -08002895 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
2896 FakeNetworkPipe::Config network_config;
2897 network_config.loss_percent = 5;
2898 return new test::PacketTransport(
2899 sender_call, this, test::PacketTransport::kSender, network_config);
2900 }
2901
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002902 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002903 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01002904 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002905 return config;
2906 }
2907
perkjfa10b552016-10-02 23:45:26 -07002908 // This test use other VideoStream settings than the the default settings
2909 // implemented in DefaultVideoStreamFactory. Therefore this test implement
2910 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
2911 // in ModifyVideoConfigs.
2912 class VideoStreamFactory
2913 : public VideoEncoderConfig::VideoStreamFactoryInterface {
2914 public:
2915 VideoStreamFactory() {}
2916
2917 private:
2918 std::vector<VideoStream> CreateEncoderStreams(
2919 int width,
2920 int height,
2921 const VideoEncoderConfig& encoder_config) override {
2922 std::vector<VideoStream> streams =
2923 test::CreateVideoStreams(width, height, encoder_config);
2924 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
2925 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
2926 streams[i].min_bitrate_bps = 10000;
2927 streams[i].target_bitrate_bps = 15000;
2928 streams[i].max_bitrate_bps = 20000;
2929 }
2930 return streams;
2931 }
2932 };
2933
stefanff483612015-12-21 03:14:00 -08002934 void ModifyVideoConfigs(
2935 VideoSendStream::Config* send_config,
2936 std::vector<VideoReceiveStream::Config>* receive_configs,
2937 VideoEncoderConfig* encoder_config) override {
perkjfa10b552016-10-02 23:45:26 -07002938 encoder_config->video_stream_factory =
2939 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002940 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002941 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002942
sprangcd349d92016-07-13 09:11:28 -07002943 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2944 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
2945
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002946 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002947 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002948 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002949 expected_receive_ssrcs_.push_back(
2950 (*receive_configs)[i].rtp.remote_ssrc);
Peter Boströmdef398832015-05-27 17:59:11 +02002951 (*receive_configs)[i].render_delay_ms = kExpectedRenderDelayMs;
tommi2e82f382016-06-21 00:26:43 -07002952 (*receive_configs)[i].renderer = &receive_stream_renderer_;
sprangcd349d92016-07-13 09:11:28 -07002953 (*receive_configs)[i].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2954
brandtr14742122017-01-27 04:53:07 -08002955 (*receive_configs)[i].rtp.rtx_ssrc = kSendRtxSsrcs[i];
2956 (*receive_configs)[i].rtp.rtx_payload_types[kFakeVideoSendPayloadType] =
sprangcd349d92016-07-13 09:11:28 -07002957 kSendRtxPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002958 }
sprangcd349d92016-07-13 09:11:28 -07002959
2960 for (size_t i = 0; i < kNumSsrcs; ++i)
2961 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
2962
Peter Boströmc6e16e32016-02-05 14:15:53 +01002963 // Use a delayed encoder to make sure we see CpuOveruseMetrics stats that
2964 // are non-zero.
2965 send_config->encoder_settings.encoder = &encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002966 }
2967
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002968 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00002969
stefanff483612015-12-21 03:14:00 -08002970 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002971 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002972 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002973 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002974 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002975 }
2976
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002977 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002978 Clock* clock = Clock::GetRealTimeClock();
2979 int64_t now = clock->TimeInMilliseconds();
2980 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
2981 bool receive_ok = false;
2982 bool send_ok = false;
2983
2984 while (now < stop_time) {
2985 if (!receive_ok)
2986 receive_ok = CheckReceiveStats();
2987 if (!send_ok)
2988 send_ok = CheckSendStats();
2989
2990 if (receive_ok && send_ok)
2991 return;
2992
2993 int64_t time_until_timout_ = stop_time - now;
2994 if (time_until_timout_ > 0)
Peter Boström5811a392015-12-10 13:02:50 +01002995 check_stats_event_.Wait(time_until_timout_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002996 now = clock->TimeInMilliseconds();
2997 }
2998
2999 ADD_FAILURE() << "Timed out waiting for filled stats.";
3000 for (std::map<std::string, bool>::const_iterator it =
3001 receive_stats_filled_.begin();
3002 it != receive_stats_filled_.end();
3003 ++it) {
3004 if (!it->second) {
3005 ADD_FAILURE() << "Missing receive stats: " << it->first;
3006 }
3007 }
3008
3009 for (std::map<std::string, bool>::const_iterator it =
3010 send_stats_filled_.begin();
3011 it != send_stats_filled_.end();
3012 ++it) {
3013 if (!it->second) {
3014 ADD_FAILURE() << "Missing send stats: " << it->first;
3015 }
3016 }
3017 }
3018
Peter Boströmc6e16e32016-02-05 14:15:53 +01003019 test::DelayedEncoder encoder_;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003020 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003021 std::map<std::string, bool> receive_stats_filled_;
3022
3023 VideoSendStream* send_stream_;
3024 std::map<std::string, bool> send_stats_filled_;
3025
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003026 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003027 std::set<uint32_t> expected_send_ssrcs_;
3028 std::string expected_cname_;
3029
Peter Boström5811a392015-12-10 13:02:50 +01003030 rtc::Event check_stats_event_;
tommi2e82f382016-06-21 00:26:43 -07003031 ReceiveStreamRenderer receive_stream_renderer_;
stefanf116bd02015-10-27 08:29:42 -07003032 } test;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003033
stefane74eef12016-01-08 06:47:13 -08003034 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003035}
3036
sprang1a646ee2016-12-01 06:34:11 -08003037class RtcpXrObserver : public test::EndToEndTest {
3038 public:
sprang44b3ef62017-01-13 07:30:25 -08003039 RtcpXrObserver(bool enable_rrtr, bool enable_target_bitrate)
sprang1a646ee2016-12-01 06:34:11 -08003040 : EndToEndTest(test::CallTest::kDefaultTimeoutMs),
3041 enable_rrtr_(enable_rrtr),
sprang44b3ef62017-01-13 07:30:25 -08003042 enable_target_bitrate_(enable_target_bitrate),
sprang1a646ee2016-12-01 06:34:11 -08003043 sent_rtcp_sr_(0),
3044 sent_rtcp_rr_(0),
3045 sent_rtcp_rrtr_(0),
3046 sent_rtcp_target_bitrate_(false),
3047 sent_rtcp_dlrr_(0) {}
3048
3049 private:
3050 // Receive stream should send RR packets (and RRTR packets if enabled).
3051 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
3052 rtc::CritScope lock(&crit_);
3053 test::RtcpPacketParser parser;
3054 EXPECT_TRUE(parser.Parse(packet, length));
3055
3056 sent_rtcp_rr_ += parser.receiver_report()->num_packets();
3057 EXPECT_EQ(0, parser.sender_report()->num_packets());
3058 EXPECT_GE(1, parser.xr()->num_packets());
3059 if (parser.xr()->num_packets() > 0) {
3060 if (parser.xr()->rrtr())
3061 ++sent_rtcp_rrtr_;
3062 EXPECT_FALSE(parser.xr()->dlrr());
3063 }
3064
3065 return SEND_PACKET;
3066 }
3067 // Send stream should send SR packets (and DLRR packets if enabled).
3068 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
3069 rtc::CritScope lock(&crit_);
3070 test::RtcpPacketParser parser;
3071 EXPECT_TRUE(parser.Parse(packet, length));
3072
3073 sent_rtcp_sr_ += parser.sender_report()->num_packets();
3074 EXPECT_LE(parser.xr()->num_packets(), 1);
3075 if (parser.xr()->num_packets() > 0) {
3076 EXPECT_FALSE(parser.xr()->rrtr());
3077 if (parser.xr()->dlrr())
3078 ++sent_rtcp_dlrr_;
3079 if (parser.xr()->target_bitrate())
3080 sent_rtcp_target_bitrate_ = true;
3081 }
3082
3083 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
3084 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve &&
sprang44b3ef62017-01-13 07:30:25 -08003085 (sent_rtcp_target_bitrate_ || !enable_target_bitrate_)) {
sprang1a646ee2016-12-01 06:34:11 -08003086 if (enable_rrtr_) {
3087 EXPECT_GT(sent_rtcp_rrtr_, 0);
3088 EXPECT_GT(sent_rtcp_dlrr_, 0);
3089 } else {
3090 EXPECT_EQ(sent_rtcp_rrtr_, 0);
3091 EXPECT_EQ(sent_rtcp_dlrr_, 0);
3092 }
sprang44b3ef62017-01-13 07:30:25 -08003093 EXPECT_EQ(enable_target_bitrate_, sent_rtcp_target_bitrate_);
sprang1a646ee2016-12-01 06:34:11 -08003094 observation_complete_.Set();
3095 }
3096 return SEND_PACKET;
3097 }
3098
3099 void ModifyVideoConfigs(
3100 VideoSendStream::Config* send_config,
3101 std::vector<VideoReceiveStream::Config>* receive_configs,
3102 VideoEncoderConfig* encoder_config) override {
sprang44b3ef62017-01-13 07:30:25 -08003103 if (enable_target_bitrate_) {
3104 // TargetBitrate only signaled for screensharing.
3105 encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
3106 }
sprang1a646ee2016-12-01 06:34:11 -08003107 (*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
3108 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
3109 enable_rrtr_;
3110 }
3111
3112 void PerformTest() override {
3113 EXPECT_TRUE(Wait())
3114 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
3115 }
3116
3117 static const int kNumRtcpReportPacketsToObserve = 5;
3118
3119 rtc::CriticalSection crit_;
sprang44b3ef62017-01-13 07:30:25 -08003120 const bool enable_rrtr_;
3121 const bool enable_target_bitrate_;
sprang1a646ee2016-12-01 06:34:11 -08003122 int sent_rtcp_sr_;
3123 int sent_rtcp_rr_ GUARDED_BY(&crit_);
3124 int sent_rtcp_rrtr_ GUARDED_BY(&crit_);
3125 bool sent_rtcp_target_bitrate_ GUARDED_BY(&crit_);
3126 int sent_rtcp_dlrr_;
3127};
3128
sprang44b3ef62017-01-13 07:30:25 -08003129TEST_P(EndToEndTest, TestExtendedReportsWithRrtrWithoutTargetBitrate) {
3130 RtcpXrObserver test(true, false);
sprang1a646ee2016-12-01 06:34:11 -08003131 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003132}
3133
sprang44b3ef62017-01-13 07:30:25 -08003134TEST_P(EndToEndTest, TestExtendedReportsWithoutRrtrWithoutTargetBitrate) {
3135 RtcpXrObserver test(false, false);
3136 RunBaseTest(&test);
3137}
3138
3139TEST_P(EndToEndTest, TestExtendedReportsWithRrtrWithTargetBitrate) {
3140 RtcpXrObserver test(true, true);
3141 RunBaseTest(&test);
3142}
3143
3144TEST_P(EndToEndTest, TestExtendedReportsWithoutRrtrWithTargetBitrate) {
3145 RtcpXrObserver test(false, true);
sprang1a646ee2016-12-01 06:34:11 -08003146 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003147}
3148
philipel266f0a42016-11-28 08:49:07 -08003149TEST_P(EndToEndTest, TestReceivedRtpPacketStats) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003150 static const size_t kNumRtpPacketsToSend = 5;
3151 class ReceivedRtpStatsObserver : public test::EndToEndTest {
3152 public:
3153 ReceivedRtpStatsObserver()
3154 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00003155 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003156 sent_rtp_(0) {}
3157
3158 private:
stefanff483612015-12-21 03:14:00 -08003159 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003160 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003161 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003162 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003163 }
3164
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003165 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003166 if (sent_rtp_ >= kNumRtpPacketsToSend) {
3167 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00003168 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
Peter Boström5811a392015-12-10 13:02:50 +01003169 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003170 }
3171 return DROP_PACKET;
3172 }
3173 ++sent_rtp_;
3174 return SEND_PACKET;
3175 }
3176
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003177 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003178 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003179 << "Timed out while verifying number of received RTP packets.";
3180 }
3181
3182 VideoReceiveStream* receive_stream_;
3183 uint32_t sent_rtp_;
3184 } test;
3185
stefane74eef12016-01-08 06:47:13 -08003186 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003187}
3188
philipel266f0a42016-11-28 08:49:07 -08003189TEST_P(EndToEndTest, SendsSetSsrc) {
3190 TestSendsSetSsrcs(1, false);
3191}
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003192
philipel266f0a42016-11-28 08:49:07 -08003193TEST_P(EndToEndTest, SendsSetSimulcastSsrcs) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003194 TestSendsSetSsrcs(kNumSsrcs, false);
3195}
3196
philipel266f0a42016-11-28 08:49:07 -08003197TEST_P(EndToEndTest, CanSwitchToUseAllSsrcs) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003198 TestSendsSetSsrcs(kNumSsrcs, true);
3199}
3200
philipel266f0a42016-11-28 08:49:07 -08003201TEST_P(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003202 class ObserveRedundantPayloads: public test::EndToEndTest {
3203 public:
3204 ObserveRedundantPayloads()
3205 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003206 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003207 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
3208 }
3209 }
3210
3211 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003212 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003213 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003214 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003215
3216 if (!registered_rtx_ssrc_[header.ssrc])
3217 return SEND_PACKET;
3218
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003219 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003220 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003221 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003222
3223 if (!packet_is_redundant_payload)
3224 return SEND_PACKET;
3225
3226 if (!observed_redundant_retransmission_[header.ssrc]) {
3227 observed_redundant_retransmission_[header.ssrc] = true;
3228 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01003229 observation_complete_.Set();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003230 }
3231
3232 return SEND_PACKET;
3233 }
3234
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003235 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003236
perkjfa10b552016-10-02 23:45:26 -07003237 // This test use other VideoStream settings than the the default settings
3238 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3239 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3240 // in ModifyVideoConfigs.
3241 class VideoStreamFactory
3242 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3243 public:
3244 VideoStreamFactory() {}
3245
3246 private:
3247 std::vector<VideoStream> CreateEncoderStreams(
3248 int width,
3249 int height,
3250 const VideoEncoderConfig& encoder_config) override {
3251 std::vector<VideoStream> streams =
3252 test::CreateVideoStreams(width, height, encoder_config);
3253 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
3254 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3255 streams[i].min_bitrate_bps = 10000;
3256 streams[i].target_bitrate_bps = 15000;
3257 streams[i].max_bitrate_bps = 20000;
3258 }
3259 return streams;
3260 }
3261 };
3262
stefanff483612015-12-21 03:14:00 -08003263 void ModifyVideoConfigs(
3264 VideoSendStream::Config* send_config,
3265 std::vector<VideoReceiveStream::Config>* receive_configs,
3266 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003267 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
perkjfa10b552016-10-02 23:45:26 -07003268 encoder_config->video_stream_factory =
3269 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003270 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003271
3272 for (size_t i = 0; i < kNumSsrcs; ++i)
3273 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00003274
3275 // Significantly higher than max bitrates for all video streams -> forcing
3276 // padding to trigger redundant padding on all RTX SSRCs.
3277 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003278 }
3279
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003280 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003281 EXPECT_TRUE(Wait())
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003282 << "Timed out while waiting for redundant payloads on all SSRCs.";
3283 }
3284
3285 private:
3286 size_t ssrcs_to_observe_;
3287 std::map<uint32_t, bool> observed_redundant_retransmission_;
3288 std::map<uint32_t, bool> registered_rtx_ssrc_;
3289 } test;
3290
stefane74eef12016-01-08 06:47:13 -08003291 RunBaseTest(&test);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003292}
3293
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003294void EndToEndTest::TestRtpStatePreservation(bool use_rtx,
3295 bool provoke_rtcpsr_before_rtp) {
perkjfa10b552016-10-02 23:45:26 -07003296 // This test use other VideoStream settings than the the default settings
3297 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3298 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3299 // in ModifyVideoConfigs.
3300 class VideoStreamFactory
3301 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3302 public:
3303 VideoStreamFactory() {}
3304
3305 private:
3306 std::vector<VideoStream> CreateEncoderStreams(
3307 int width,
3308 int height,
3309 const VideoEncoderConfig& encoder_config) override {
3310 std::vector<VideoStream> streams =
3311 test::CreateVideoStreams(width, height, encoder_config);
3312
3313 if (encoder_config.number_of_streams > 1) {
3314 // Lower bitrates so that all streams send initially.
kwibergaf476c72016-11-28 15:21:39 -08003315 RTC_DCHECK_EQ(3, encoder_config.number_of_streams);
perkjfa10b552016-10-02 23:45:26 -07003316 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3317 streams[i].min_bitrate_bps = 10000;
3318 streams[i].target_bitrate_bps = 15000;
3319 streams[i].max_bitrate_bps = 20000;
3320 }
3321 } else {
3322 // Use the same total bitrates when sending a single stream to avoid
3323 // lowering
3324 // the bitrate estimate and requiring a subsequent rampup.
3325 streams[0].min_bitrate_bps = 3 * 10000;
3326 streams[0].target_bitrate_bps = 3 * 15000;
3327 streams[0].max_bitrate_bps = 3 * 20000;
3328 }
3329 return streams;
3330 }
3331 };
3332
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003333 class RtpSequenceObserver : public test::RtpRtcpObserver {
3334 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003335 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003336 : test::RtpRtcpObserver(kDefaultTimeoutMs),
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003337 ssrcs_to_observe_(kNumSsrcs) {
3338 for (size_t i = 0; i < kNumSsrcs; ++i) {
danilchap32cd2c42016-08-01 06:58:34 -07003339 ssrc_is_rtx_[kVideoSendSsrcs[i]] = false;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003340 if (use_rtx)
danilchap32cd2c42016-08-01 06:58:34 -07003341 ssrc_is_rtx_[kSendRtxSsrcs[i]] = true;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003342 }
3343 }
3344
3345 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
Peter Boströmf2f82832015-05-01 13:00:41 +02003346 rtc::CritScope lock(&crit_);
danilchap34877ee2016-02-01 08:25:04 -08003347 ssrc_observed_.clear();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003348 ssrcs_to_observe_ = num_expected_ssrcs;
3349 }
3350
3351 private:
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003352 void ValidateTimestampGap(uint32_t ssrc,
3353 uint32_t timestamp,
3354 bool only_padding)
3355 EXCLUSIVE_LOCKS_REQUIRED(crit_) {
3356 static const int32_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
3357 auto timestamp_it = last_observed_timestamp_.find(ssrc);
3358 if (timestamp_it == last_observed_timestamp_.end()) {
3359 EXPECT_FALSE(only_padding);
3360 last_observed_timestamp_[ssrc] = timestamp;
3361 } else {
3362 // Verify timestamps are reasonably close.
3363 uint32_t latest_observed = timestamp_it->second;
3364 // Wraparound handling is unnecessary here as long as an int variable
3365 // is used to store the result.
3366 int32_t timestamp_gap = timestamp - latest_observed;
3367 EXPECT_LE(std::abs(timestamp_gap), kMaxTimestampGap)
3368 << "Gap in timestamps (" << latest_observed << " -> " << timestamp
3369 << ") too large for SSRC: " << ssrc << ".";
3370 timestamp_it->second = timestamp;
3371 }
3372 }
3373
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003374 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003375 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003376 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003377 const uint32_t ssrc = header.ssrc;
danilchap5c35cf92016-02-03 14:14:49 -08003378 const int64_t sequence_number =
3379 seq_numbers_unwrapper_.Unwrap(header.sequenceNumber);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003380 const uint32_t timestamp = header.timestamp;
danilchap34877ee2016-02-01 08:25:04 -08003381 const bool only_padding =
3382 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003383
danilchap32cd2c42016-08-01 06:58:34 -07003384 EXPECT_TRUE(ssrc_is_rtx_.find(ssrc) != ssrc_is_rtx_.end())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003385 << "Received SSRC that wasn't configured: " << ssrc;
3386
danilchap5c35cf92016-02-03 14:14:49 -08003387 static const int64_t kMaxSequenceNumberGap = 100;
3388 std::list<int64_t>* seq_numbers = &last_observed_seq_numbers_[ssrc];
3389 if (seq_numbers->empty()) {
3390 seq_numbers->push_back(sequence_number);
3391 } else {
3392 // We shouldn't get replays of previous sequence numbers.
3393 for (int64_t observed : *seq_numbers) {
3394 EXPECT_NE(observed, sequence_number)
3395 << "Received sequence number " << sequence_number
3396 << " for SSRC " << ssrc << " 2nd time.";
3397 }
3398 // Verify sequence numbers are reasonably close.
3399 int64_t latest_observed = seq_numbers->back();
3400 int64_t sequence_number_gap = sequence_number - latest_observed;
3401 EXPECT_LE(std::abs(sequence_number_gap), kMaxSequenceNumberGap)
3402 << "Gap in sequence numbers (" << latest_observed << " -> "
3403 << sequence_number << ") too large for SSRC: " << ssrc << ".";
3404 seq_numbers->push_back(sequence_number);
3405 if (seq_numbers->size() >= kMaxSequenceNumberGap) {
3406 seq_numbers->pop_front();
3407 }
3408 }
3409
danilchap32cd2c42016-08-01 06:58:34 -07003410 if (!ssrc_is_rtx_[ssrc]) {
3411 rtc::CritScope lock(&crit_);
3412 ValidateTimestampGap(ssrc, timestamp, only_padding);
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003413
danilchap32cd2c42016-08-01 06:58:34 -07003414 // Wait for media packets on all ssrcs.
3415 if (!ssrc_observed_[ssrc] && !only_padding) {
3416 ssrc_observed_[ssrc] = true;
3417 if (--ssrcs_to_observe_ == 0)
3418 observation_complete_.Set();
3419 }
danilchap34877ee2016-02-01 08:25:04 -08003420 }
3421
danilchapf4b9c772016-01-28 06:14:24 -08003422 return SEND_PACKET;
3423 }
3424
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003425 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
3426 test::RtcpPacketParser rtcp_parser;
3427 rtcp_parser.Parse(packet, length);
3428 if (rtcp_parser.sender_report()->num_packets() > 0) {
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02003429 uint32_t ssrc = rtcp_parser.sender_report()->sender_ssrc();
3430 uint32_t rtcp_timestamp = rtcp_parser.sender_report()->rtp_timestamp();
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003431
3432 rtc::CritScope lock(&crit_);
3433 ValidateTimestampGap(ssrc, rtcp_timestamp, false);
3434 }
3435 return SEND_PACKET;
3436 }
3437
danilchap5c35cf92016-02-03 14:14:49 -08003438 SequenceNumberUnwrapper seq_numbers_unwrapper_;
3439 std::map<uint32_t, std::list<int64_t>> last_observed_seq_numbers_;
danilchap34877ee2016-02-01 08:25:04 -08003440 std::map<uint32_t, uint32_t> last_observed_timestamp_;
danilchap32cd2c42016-08-01 06:58:34 -07003441 std::map<uint32_t, bool> ssrc_is_rtx_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003442
Peter Boströmf2f82832015-05-01 13:00:41 +02003443 rtc::CriticalSection crit_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003444 size_t ssrcs_to_observe_ GUARDED_BY(crit_);
danilchap34877ee2016-02-01 08:25:04 -08003445 std::map<uint32_t, bool> ssrc_observed_ GUARDED_BY(crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003446 } observer(use_rtx);
3447
skvlad11a9cbf2016-10-07 11:53:05 -07003448 Call::Config config(&event_log_);
3449 CreateCalls(config, config);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003450
stefanf116bd02015-10-27 08:29:42 -07003451 test::PacketTransport send_transport(sender_call_.get(), &observer,
3452 test::PacketTransport::kSender,
3453 FakeNetworkPipe::Config());
3454 test::PacketTransport receive_transport(nullptr, &observer,
3455 test::PacketTransport::kReceiver,
3456 FakeNetworkPipe::Config());
3457 send_transport.SetReceiver(receiver_call_->Receiver());
3458 receive_transport.SetReceiver(sender_call_->Receiver());
3459
brandtr841de6a2016-11-15 07:10:52 -08003460 CreateSendConfig(kNumSsrcs, 0, 0, &send_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003461
3462 if (use_rtx) {
3463 for (size_t i = 0; i < kNumSsrcs; ++i) {
stefanff483612015-12-21 03:14:00 -08003464 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003465 }
stefanff483612015-12-21 03:14:00 -08003466 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003467 }
3468
perkjfa10b552016-10-02 23:45:26 -07003469 video_encoder_config_.video_stream_factory =
3470 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003471 // Use the same total bitrates when sending a single stream to avoid lowering
3472 // the bitrate estimate and requiring a subsequent rampup.
perkj26091b12016-09-01 01:17:40 -07003473 VideoEncoderConfig one_stream = video_encoder_config_.Copy();
perkjfa10b552016-10-02 23:45:26 -07003474 // one_stream.streams.resize(1);
3475 one_stream.number_of_streams = 1;
stefanf116bd02015-10-27 08:29:42 -07003476 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003477
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003478 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003479 CreateFrameGeneratorCapturer(30, 1280, 720);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003480
3481 Start();
Peter Boström5811a392015-12-10 13:02:50 +01003482 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003483 << "Timed out waiting for all SSRCs to send packets.";
3484
3485 // Test stream resetting more than once to make sure that the state doesn't
3486 // get set once (this could be due to using std::map::insert for instance).
3487 for (size_t i = 0; i < 3; ++i) {
3488 frame_generator_capturer_->Stop();
stefanff483612015-12-21 03:14:00 -08003489 sender_call_->DestroyVideoSendStream(video_send_stream_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003490
3491 // Re-create VideoSendStream with only one stream.
perkj26091b12016-09-01 01:17:40 -07003492 video_send_stream_ = sender_call_->CreateVideoSendStream(
3493 video_send_config_.Copy(), one_stream.Copy());
stefanff483612015-12-21 03:14:00 -08003494 video_send_stream_->Start();
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003495 if (provoke_rtcpsr_before_rtp) {
3496 // Rapid Resync Request forces sending RTCP Sender Report back.
3497 // Using this request speeds up this test because then there is no need
3498 // to wait for a second for periodic Sender Report.
3499 rtcp::RapidResyncRequest force_send_sr_back_request;
3500 rtc::Buffer packet = force_send_sr_back_request.Build();
3501 static_cast<webrtc::test::DirectTransport&>(receive_transport)
3502 .SendRtcp(packet.data(), packet.size());
3503 }
perkjfa10b552016-10-02 23:45:26 -07003504 CreateFrameGeneratorCapturer(30, 1280, 720);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003505 frame_generator_capturer_->Start();
3506
3507 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003508 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003509
3510 // Reconfigure back to use all streams.
perkj26091b12016-09-01 01:17:40 -07003511 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003512 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003513 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003514 << "Timed out waiting for all SSRCs to send packets.";
3515
3516 // Reconfigure down to one stream.
perkj26091b12016-09-01 01:17:40 -07003517 video_send_stream_->ReconfigureVideoEncoder(one_stream.Copy());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003518 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003519 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003520
3521 // Reconfigure back to use all streams.
perkj26091b12016-09-01 01:17:40 -07003522 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003523 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003524 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003525 << "Timed out waiting for all SSRCs to send packets.";
3526 }
3527
stefanf116bd02015-10-27 08:29:42 -07003528 send_transport.StopSending();
3529 receive_transport.StopSending();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003530
3531 Stop();
3532 DestroyStreams();
3533}
3534
philipel266f0a42016-11-28 08:49:07 -08003535TEST_P(EndToEndTest, RestartingSendStreamPreservesRtpState) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003536 TestRtpStatePreservation(false, false);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003537}
3538
philipel266f0a42016-11-28 08:49:07 -08003539TEST_P(EndToEndTest, RestartingSendStreamPreservesRtpStatesWithRtx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003540 TestRtpStatePreservation(true, false);
3541}
3542
philipel266f0a42016-11-28 08:49:07 -08003543TEST_P(EndToEndTest, RestartingSendStreamKeepsRtpAndRtcpTimestampsSynced) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003544 TestRtpStatePreservation(true, true);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003545}
3546
philipel266f0a42016-11-28 08:49:07 -08003547TEST_P(EndToEndTest, RespectsNetworkState) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003548 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
3549 // down blocks until no more packets will be sent.
3550
3551 // Pacer will send from its packet list and then send required padding before
3552 // checking paused_ again. This should be enough for one round of pacing,
3553 // otherwise increase.
3554 static const int kNumAcceptedDowntimeRtp = 5;
3555 // A single RTCP may be in the pipeline.
3556 static const int kNumAcceptedDowntimeRtcp = 1;
3557 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
3558 public:
3559 NetworkStateTest()
3560 : EndToEndTest(kDefaultTimeoutMs),
3561 FakeEncoder(Clock::GetRealTimeClock()),
Peter Boström5811a392015-12-10 13:02:50 +01003562 encoded_frames_(false, false),
3563 packet_event_(false, false),
sprang867fb522015-08-03 04:38:41 -07003564 sender_call_(nullptr),
3565 receiver_call_(nullptr),
Jelena Marusiccd670222015-07-16 09:30:09 +02003566 sender_state_(kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003567 sender_rtp_(0),
3568 sender_rtcp_(0),
3569 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003570 down_frames_(0) {}
3571
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003572 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003573 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003574 ++sender_rtp_;
Peter Boström5811a392015-12-10 13:02:50 +01003575 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003576 return SEND_PACKET;
3577 }
3578
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003579 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003580 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003581 ++sender_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003582 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003583 return SEND_PACKET;
3584 }
3585
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003586 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003587 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
3588 return SEND_PACKET;
3589 }
3590
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003591 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003592 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003593 ++receiver_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003594 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003595 return SEND_PACKET;
3596 }
3597
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003598 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003599 sender_call_ = sender_call;
3600 receiver_call_ = receiver_call;
3601 }
3602
stefanff483612015-12-21 03:14:00 -08003603 void ModifyVideoConfigs(
3604 VideoSendStream::Config* send_config,
3605 std::vector<VideoReceiveStream::Config>* receive_configs,
3606 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003607 send_config->encoder_settings.encoder = this;
3608 }
3609
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003610 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003611 EXPECT_TRUE(encoded_frames_.Wait(kDefaultTimeoutMs))
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003612 << "No frames received by the encoder.";
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003613 // Wait for packets from both sender/receiver.
3614 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003615
skvlad7a43d252016-03-22 15:32:27 -07003616 // Sender-side network down for audio; there should be no effect on video
3617 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3618 WaitForPacketsOrSilence(false, false);
3619
3620 // Receiver-side network down for audio; no change expected
3621 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3622 WaitForPacketsOrSilence(false, false);
3623
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003624 // Sender-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003625 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003626 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003627 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003628 // After network goes down we shouldn't be encoding more frames.
Jelena Marusiccd670222015-07-16 09:30:09 +02003629 sender_state_ = kNetworkDown;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003630 }
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003631 // Wait for receiver-packets and no sender packets.
3632 WaitForPacketsOrSilence(true, false);
3633
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003634 // Receiver-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003635 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
3636 WaitForPacketsOrSilence(true, true);
3637
3638 // Network up for audio for both sides; video is still not expected to
3639 // start
3640 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
3641 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003642 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003643
3644 // Network back up again for both.
3645 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003646 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003647 // It's OK to encode frames again, as we're about to bring up the
3648 // network.
Jelena Marusiccd670222015-07-16 09:30:09 +02003649 sender_state_ = kNetworkUp;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003650 }
skvlad7a43d252016-03-22 15:32:27 -07003651 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
3652 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003653 WaitForPacketsOrSilence(false, false);
skvlad7a43d252016-03-22 15:32:27 -07003654
3655 // TODO(skvlad): add tests to verify that the audio streams are stopped
3656 // when the network goes down for audio once the workaround in
3657 // paced_sender.cc is removed.
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003658 }
3659
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07003660 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003661 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07003662 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003663 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003664 rtc::CritScope lock(&test_crit_);
Jelena Marusiccd670222015-07-16 09:30:09 +02003665 if (sender_state_ == kNetworkDown) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003666 ++down_frames_;
3667 EXPECT_LE(down_frames_, 1)
3668 << "Encoding more than one frame while network is down.";
3669 if (down_frames_ > 1)
Peter Boström5811a392015-12-10 13:02:50 +01003670 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003671 } else {
Peter Boström5811a392015-12-10 13:02:50 +01003672 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003673 }
3674 }
3675 return test::FakeEncoder::Encode(
3676 input_image, codec_specific_info, frame_types);
3677 }
3678
3679 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003680 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
3681 int64_t initial_time_ms = clock_->TimeInMilliseconds();
3682 int initial_sender_rtp;
3683 int initial_sender_rtcp;
3684 int initial_receiver_rtcp;
3685 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003686 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003687 initial_sender_rtp = sender_rtp_;
3688 initial_sender_rtcp = sender_rtcp_;
3689 initial_receiver_rtcp = receiver_rtcp_;
3690 }
3691 bool sender_done = false;
3692 bool receiver_done = false;
mflodmand1590b22015-12-09 07:07:59 -08003693 while (!sender_done || !receiver_done) {
Peter Boström5811a392015-12-10 13:02:50 +01003694 packet_event_.Wait(kSilenceTimeoutMs);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003695 int64_t time_now_ms = clock_->TimeInMilliseconds();
Peter Boströmf2f82832015-05-01 13:00:41 +02003696 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003697 if (sender_down) {
3698 ASSERT_LE(sender_rtp_ - initial_sender_rtp, kNumAcceptedDowntimeRtp)
3699 << "RTP sent during sender-side downtime.";
3700 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
3701 kNumAcceptedDowntimeRtcp)
3702 << "RTCP sent during sender-side downtime.";
3703 if (time_now_ms - initial_time_ms >=
3704 static_cast<int64_t>(kSilenceTimeoutMs)) {
3705 sender_done = true;
3706 }
3707 } else {
skvlad7a43d252016-03-22 15:32:27 -07003708 if (sender_rtp_ > initial_sender_rtp + kNumAcceptedDowntimeRtp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003709 sender_done = true;
3710 }
3711 if (receiver_down) {
3712 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
3713 kNumAcceptedDowntimeRtcp)
3714 << "RTCP sent during receiver-side downtime.";
3715 if (time_now_ms - initial_time_ms >=
3716 static_cast<int64_t>(kSilenceTimeoutMs)) {
3717 receiver_done = true;
3718 }
3719 } else {
skvlad7a43d252016-03-22 15:32:27 -07003720 if (receiver_rtcp_ > initial_receiver_rtcp + kNumAcceptedDowntimeRtcp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003721 receiver_done = true;
3722 }
3723 }
3724 }
3725
Peter Boströmf2f82832015-05-01 13:00:41 +02003726 rtc::CriticalSection test_crit_;
Peter Boström5811a392015-12-10 13:02:50 +01003727 rtc::Event encoded_frames_;
3728 rtc::Event packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003729 Call* sender_call_;
3730 Call* receiver_call_;
Jelena Marusiccd670222015-07-16 09:30:09 +02003731 NetworkState sender_state_ GUARDED_BY(test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003732 int sender_rtp_ GUARDED_BY(test_crit_);
3733 int sender_rtcp_ GUARDED_BY(test_crit_);
3734 int receiver_rtcp_ GUARDED_BY(test_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003735 int down_frames_ GUARDED_BY(test_crit_);
3736 } test;
3737
stefane74eef12016-01-08 06:47:13 -08003738 RunBaseTest(&test);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003739}
3740
philipel266f0a42016-11-28 08:49:07 -08003741TEST_P(EndToEndTest, CallReportsRttForSender) {
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003742 static const int kSendDelayMs = 30;
3743 static const int kReceiveDelayMs = 70;
skvlad11a9cbf2016-10-07 11:53:05 -07003744 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -07003745
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003746 FakeNetworkPipe::Config config;
3747 config.queue_delay_ms = kSendDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003748 test::DirectTransport sender_transport(config, sender_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003749 config.queue_delay_ms = kReceiveDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003750 test::DirectTransport receiver_transport(config, receiver_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003751 sender_transport.SetReceiver(receiver_call_->Receiver());
3752 receiver_transport.SetReceiver(sender_call_->Receiver());
3753
brandtr841de6a2016-11-15 07:10:52 -08003754 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07003755 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003756
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003757 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003758 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
3759 kDefaultHeight);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003760 Start();
3761
3762 int64_t start_time_ms = clock_->TimeInMilliseconds();
3763 while (true) {
3764 Call::Stats stats = sender_call_->GetStats();
3765 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
3766 clock_->TimeInMilliseconds())
3767 << "No RTT stats before timeout!";
3768 if (stats.rtt_ms != -1) {
Danil Chapovalov10e8f8e2016-09-07 15:05:29 +02003769 // To avoid failures caused by rounding or minor ntp clock adjustments,
3770 // relax expectation by 1ms.
3771 constexpr int kAllowedErrorMs = 1;
3772 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs - kAllowedErrorMs);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003773 break;
3774 }
3775 SleepMs(10);
3776 }
3777
philipel266f0a42016-11-28 08:49:07 -08003778 sender_transport.StopSending();
3779 receiver_transport.StopSending();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003780 Stop();
3781 DestroyStreams();
philipel266f0a42016-11-28 08:49:07 -08003782 DestroyCalls();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003783}
3784
skvlad7a43d252016-03-22 15:32:27 -07003785void EndToEndTest::VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08003786 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -07003787 VideoEncoder* encoder,
3788 Transport* transport) {
skvlad11a9cbf2016-10-07 11:53:05 -07003789 CreateSenderCall(Call::Config(&event_log_));
Sergey Ulanove2b15012016-11-22 16:08:30 -08003790 sender_call_->SignalChannelNetworkState(network_to_bring_up, kNetworkUp);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003791
brandtr841de6a2016-11-15 07:10:52 -08003792 CreateSendConfig(1, 0, 0, transport);
skvlad7a43d252016-03-22 15:32:27 -07003793 video_send_config_.encoder_settings.encoder = encoder;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003794 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003795 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
3796 kDefaultHeight);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003797
3798 Start();
3799 SleepMs(kSilenceTimeoutMs);
3800 Stop();
3801
3802 DestroyStreams();
3803}
3804
skvlad7a43d252016-03-22 15:32:27 -07003805void EndToEndTest::VerifyNewVideoReceiveStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08003806 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -07003807 Transport* transport) {
skvlad11a9cbf2016-10-07 11:53:05 -07003808 Call::Config config(&event_log_);
3809 CreateCalls(config, config);
Sergey Ulanove2b15012016-11-22 16:08:30 -08003810 receiver_call_->SignalChannelNetworkState(network_to_bring_up, kNetworkUp);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003811
stefanf116bd02015-10-27 08:29:42 -07003812 test::DirectTransport sender_transport(sender_call_.get());
solenberg4fbae2b2015-08-28 04:07:10 -07003813 sender_transport.SetReceiver(receiver_call_->Receiver());
brandtr841de6a2016-11-15 07:10:52 -08003814 CreateSendConfig(1, 0, 0, &sender_transport);
skvlad7a43d252016-03-22 15:32:27 -07003815 CreateMatchingReceiveConfigs(transport);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003816 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003817 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
3818 kDefaultHeight);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003819
3820 Start();
3821 SleepMs(kSilenceTimeoutMs);
3822 Stop();
3823
3824 sender_transport.StopSending();
3825
3826 DestroyStreams();
3827}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00003828
philipel266f0a42016-11-28 08:49:07 -08003829TEST_P(EndToEndTest, NewVideoSendStreamsRespectVideoNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07003830 class UnusedEncoder : public test::FakeEncoder {
3831 public:
3832 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
perkjfea93092016-05-14 00:58:48 -07003833
3834 int32_t InitEncode(const VideoCodec* config,
3835 int32_t number_of_cores,
3836 size_t max_payload_size) override {
3837 EXPECT_GT(config->startBitrate, 0u);
3838 return 0;
3839 }
skvlad7a43d252016-03-22 15:32:27 -07003840 int32_t Encode(const VideoFrame& input_image,
3841 const CodecSpecificInfo* codec_specific_info,
3842 const std::vector<FrameType>* frame_types) override {
3843 ADD_FAILURE() << "Unexpected frame encode.";
3844 return test::FakeEncoder::Encode(input_image, codec_specific_info,
3845 frame_types);
3846 }
3847 };
3848
3849 UnusedEncoder unused_encoder;
3850 UnusedTransport unused_transport;
3851 VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08003852 MediaType::AUDIO, &unused_encoder, &unused_transport);
skvlad7a43d252016-03-22 15:32:27 -07003853}
3854
philipel266f0a42016-11-28 08:49:07 -08003855TEST_P(EndToEndTest, NewVideoSendStreamsIgnoreAudioNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07003856 class RequiredEncoder : public test::FakeEncoder {
3857 public:
3858 RequiredEncoder()
3859 : FakeEncoder(Clock::GetRealTimeClock()), encoded_frame_(false) {}
3860 ~RequiredEncoder() {
3861 if (!encoded_frame_) {
3862 ADD_FAILURE() << "Didn't encode an expected frame";
3863 }
3864 }
3865 int32_t Encode(const VideoFrame& input_image,
3866 const CodecSpecificInfo* codec_specific_info,
3867 const std::vector<FrameType>* frame_types) override {
3868 encoded_frame_ = true;
3869 return test::FakeEncoder::Encode(input_image, codec_specific_info,
3870 frame_types);
3871 }
3872
3873 private:
3874 bool encoded_frame_;
3875 };
3876
3877 RequiredTransport required_transport(true /*rtp*/, false /*rtcp*/);
3878 RequiredEncoder required_encoder;
3879 VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08003880 MediaType::VIDEO, &required_encoder, &required_transport);
skvlad7a43d252016-03-22 15:32:27 -07003881}
3882
philipel266f0a42016-11-28 08:49:07 -08003883TEST_P(EndToEndTest, NewVideoReceiveStreamsRespectVideoNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07003884 UnusedTransport transport;
Sergey Ulanove2b15012016-11-22 16:08:30 -08003885 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::AUDIO, &transport);
skvlad7a43d252016-03-22 15:32:27 -07003886}
3887
philipel266f0a42016-11-28 08:49:07 -08003888TEST_P(EndToEndTest, NewVideoReceiveStreamsIgnoreAudioNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07003889 RequiredTransport transport(false /*rtp*/, true /*rtcp*/);
Sergey Ulanove2b15012016-11-22 16:08:30 -08003890 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::VIDEO, &transport);
skvlad7a43d252016-03-22 15:32:27 -07003891}
3892
Peter Boströmd7da1202015-06-05 14:09:38 +02003893void VerifyEmptyNackConfig(const NackConfig& config) {
3894 EXPECT_EQ(0, config.rtp_history_ms)
3895 << "Enabling NACK requires rtcp-fb: nack negotiation.";
3896}
3897
brandtrb5f2c3f2016-10-04 23:28:39 -07003898void VerifyEmptyUlpfecConfig(const UlpfecConfig& config) {
Peter Boströmd7da1202015-06-05 14:09:38 +02003899 EXPECT_EQ(-1, config.ulpfec_payload_type)
brandtr535830e2016-10-31 03:45:58 -07003900 << "Enabling ULPFEC requires rtpmap: ulpfec negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02003901 EXPECT_EQ(-1, config.red_payload_type)
brandtr535830e2016-10-31 03:45:58 -07003902 << "Enabling ULPFEC requires rtpmap: red negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02003903 EXPECT_EQ(-1, config.red_rtx_payload_type)
brandtr535830e2016-10-31 03:45:58 -07003904 << "Enabling RTX in ULPFEC requires rtpmap: rtx negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02003905}
3906
brandtr3d200bd2017-01-16 06:59:19 -08003907void VerifyEmptyFlexfecConfig(
3908 const VideoSendStream::Config::Rtp::Flexfec& config) {
3909 EXPECT_EQ(-1, config.payload_type)
brandtr1e3dfbf2016-11-16 22:45:19 -08003910 << "Enabling FlexFEC requires rtpmap: flexfec negotiation.";
brandtr3d200bd2017-01-16 06:59:19 -08003911 EXPECT_EQ(0U, config.ssrc)
brandtr1cfbd602016-12-08 04:17:53 -08003912 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
brandtr1e3dfbf2016-11-16 22:45:19 -08003913 EXPECT_TRUE(config.protected_media_ssrcs.empty())
3914 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
3915}
3916
philipel266f0a42016-11-28 08:49:07 -08003917TEST_P(EndToEndTest, VerifyDefaultSendConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003918 VideoSendStream::Config default_send_config(nullptr);
Peter Boströmd7da1202015-06-05 14:09:38 +02003919 EXPECT_EQ(0, default_send_config.rtp.nack.rtp_history_ms)
3920 << "Enabling NACK require rtcp-fb: nack negotiation.";
3921 EXPECT_TRUE(default_send_config.rtp.rtx.ssrcs.empty())
3922 << "Enabling RTX requires rtpmap: rtx negotiation.";
3923 EXPECT_TRUE(default_send_config.rtp.extensions.empty())
3924 << "Enabling RTP extensions require negotiation.";
3925
3926 VerifyEmptyNackConfig(default_send_config.rtp.nack);
brandtrb5f2c3f2016-10-04 23:28:39 -07003927 VerifyEmptyUlpfecConfig(default_send_config.rtp.ulpfec);
brandtr1e3dfbf2016-11-16 22:45:19 -08003928 VerifyEmptyFlexfecConfig(default_send_config.rtp.flexfec);
Peter Boströmd7da1202015-06-05 14:09:38 +02003929}
3930
philipel266f0a42016-11-28 08:49:07 -08003931TEST_P(EndToEndTest, VerifyDefaultVideoReceiveConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003932 VideoReceiveStream::Config default_receive_config(nullptr);
pbosda903ea2015-10-02 02:36:56 -07003933 EXPECT_EQ(RtcpMode::kCompound, default_receive_config.rtp.rtcp_mode)
Peter Boströmd7da1202015-06-05 14:09:38 +02003934 << "Reduced-size RTCP require rtcp-rsize to be negotiated.";
3935 EXPECT_FALSE(default_receive_config.rtp.remb)
3936 << "REMB require rtcp-fb: goog-remb to be negotiated.";
3937 EXPECT_FALSE(
3938 default_receive_config.rtp.rtcp_xr.receiver_reference_time_report)
3939 << "RTCP XR settings require rtcp-xr to be negotiated.";
brandtr14742122017-01-27 04:53:07 -08003940 EXPECT_EQ(0U, default_receive_config.rtp.rtx_ssrc)
3941 << "Enabling RTX requires ssrc-group: FID negotiation";
3942 EXPECT_TRUE(default_receive_config.rtp.rtx_payload_types.empty())
Peter Boströmd7da1202015-06-05 14:09:38 +02003943 << "Enabling RTX requires rtpmap: rtx negotiation.";
3944 EXPECT_TRUE(default_receive_config.rtp.extensions.empty())
3945 << "Enabling RTP extensions require negotiation.";
3946
3947 VerifyEmptyNackConfig(default_receive_config.rtp.nack);
brandtrb5f2c3f2016-10-04 23:28:39 -07003948 VerifyEmptyUlpfecConfig(default_receive_config.rtp.ulpfec);
Peter Boströmd7da1202015-06-05 14:09:38 +02003949}
3950
philipel266f0a42016-11-28 08:49:07 -08003951TEST_P(EndToEndTest, VerifyDefaultFlexfecReceiveConfigParameters) {
brandtr8313a6f2017-01-13 07:41:19 -08003952 test::NullTransport rtcp_send_transport;
3953 FlexfecReceiveStream::Config default_receive_config(&rtcp_send_transport);
brandtr1cfbd602016-12-08 04:17:53 -08003954 EXPECT_EQ(-1, default_receive_config.payload_type)
3955 << "Enabling FlexFEC requires rtpmap: flexfec negotiation.";
3956 EXPECT_EQ(0U, default_receive_config.remote_ssrc)
3957 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
3958 EXPECT_TRUE(default_receive_config.protected_media_ssrcs.empty())
3959 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
brandtr1e3dfbf2016-11-16 22:45:19 -08003960}
3961
philipel266f0a42016-11-28 08:49:07 -08003962TEST_P(EndToEndTest, TransportSeqNumOnAudioAndVideo) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003963 static const int kExtensionId = 8;
3964 class TransportSequenceNumberTest : public test::EndToEndTest {
3965 public:
3966 TransportSequenceNumberTest()
3967 : EndToEndTest(kDefaultTimeoutMs),
3968 video_observed_(false),
3969 audio_observed_(false) {
3970 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
3971 kExtensionId);
3972 }
3973
3974 size_t GetNumVideoStreams() const override { return 1; }
3975 size_t GetNumAudioStreams() const override { return 1; }
3976
3977 void ModifyVideoConfigs(
3978 VideoSendStream::Config* send_config,
3979 std::vector<VideoReceiveStream::Config>* receive_configs,
3980 VideoEncoderConfig* encoder_config) override {
3981 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07003982 send_config->rtp.extensions.push_back(RtpExtension(
3983 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003984 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3985 }
3986
3987 void ModifyAudioConfigs(
3988 AudioSendStream::Config* send_config,
3989 std::vector<AudioReceiveStream::Config>* receive_configs) override {
3990 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07003991 send_config->rtp.extensions.push_back(RtpExtension(
3992 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003993 (*receive_configs)[0].rtp.extensions.clear();
3994 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3995 }
3996
3997 Action OnSendRtp(const uint8_t* packet, size_t length) override {
3998 RTPHeader header;
3999 EXPECT_TRUE(parser_->Parse(packet, length, &header));
4000 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
4001 // Unwrap packet id and verify uniqueness.
4002 int64_t packet_id =
4003 unwrapper_.Unwrap(header.extension.transportSequenceNumber);
4004 EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
4005
4006 if (header.ssrc == kVideoSendSsrcs[0])
4007 video_observed_ = true;
4008 if (header.ssrc == kAudioSendSsrc)
4009 audio_observed_ = true;
4010 if (audio_observed_ && video_observed_ &&
4011 received_packet_ids_.size() == 50) {
4012 size_t packet_id_range =
4013 *received_packet_ids_.rbegin() - *received_packet_ids_.begin() + 1;
4014 EXPECT_EQ(received_packet_ids_.size(), packet_id_range);
4015 observation_complete_.Set();
4016 }
4017 return SEND_PACKET;
4018 }
4019
4020 void PerformTest() override {
4021 EXPECT_TRUE(Wait()) << "Timed out while waiting for audio and video "
4022 "packets with transport sequence number.";
4023 }
4024
4025 private:
4026 bool video_observed_;
4027 bool audio_observed_;
4028 SequenceNumberUnwrapper unwrapper_;
4029 std::set<int64_t> received_packet_ids_;
4030 } test;
4031
stefane74eef12016-01-08 06:47:13 -08004032 RunBaseTest(&test);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004033}
palmkviste75f2042016-09-28 06:19:48 -07004034
4035class EndToEndLogTest : public EndToEndTest {
4036 void SetUp() { paths_.clear(); }
4037 void TearDown() {
4038 for (const auto& path : paths_) {
4039 rtc::RemoveFile(path);
4040 }
4041 }
4042
4043 public:
4044 int AddFile() {
4045 paths_.push_back(test::TempFilename(test::OutputPath(), "test_file"));
4046 return static_cast<int>(paths_.size()) - 1;
4047 }
4048
4049 rtc::PlatformFile OpenFile(int idx) {
4050 return rtc::OpenPlatformFile(paths_[idx]);
4051 }
4052
4053 void LogSend(bool open) {
4054 if (open) {
4055 video_send_stream_->EnableEncodedFrameRecording(
4056 std::vector<rtc::PlatformFile>(1, OpenFile(AddFile())), 0);
4057 } else {
4058 video_send_stream_->DisableEncodedFrameRecording();
4059 }
4060 }
4061 void LogReceive(bool open) {
4062 if (open) {
4063 video_receive_streams_[0]->EnableEncodedFrameRecording(
4064 OpenFile(AddFile()), 0);
4065 } else {
4066 video_receive_streams_[0]->DisableEncodedFrameRecording();
4067 }
4068 }
4069
4070 std::vector<std::string> paths_;
4071};
4072
philipel266f0a42016-11-28 08:49:07 -08004073TEST_P(EndToEndLogTest, LogsEncodedFramesWhenRequested) {
palmkviste75f2042016-09-28 06:19:48 -07004074 static const int kNumFramesToRecord = 10;
4075 class LogEncodingObserver : public test::EndToEndTest,
4076 public EncodedFrameObserver {
4077 public:
4078 explicit LogEncodingObserver(EndToEndLogTest* fixture)
4079 : EndToEndTest(kDefaultTimeoutMs),
4080 fixture_(fixture),
4081 recorded_frames_(0) {}
4082
4083 void PerformTest() override {
4084 fixture_->LogSend(true);
4085 fixture_->LogReceive(true);
4086 ASSERT_TRUE(Wait()) << "Timed out while waiting for frame logging.";
4087 }
4088
4089 void ModifyVideoConfigs(
4090 VideoSendStream::Config* send_config,
4091 std::vector<VideoReceiveStream::Config>* receive_configs,
4092 VideoEncoderConfig* encoder_config) override {
magjed509e4fe2016-11-18 01:34:11 -08004093 encoder_.reset(VP8Encoder::Create());
palmkviste75f2042016-09-28 06:19:48 -07004094 decoder_.reset(VP8Decoder::Create());
4095
4096 send_config->post_encode_callback = this;
4097 send_config->encoder_settings.payload_name = "VP8";
4098 send_config->encoder_settings.encoder = encoder_.get();
4099
4100 (*receive_configs)[0].decoders.resize(1);
4101 (*receive_configs)[0].decoders[0].payload_type =
4102 send_config->encoder_settings.payload_type;
4103 (*receive_configs)[0].decoders[0].payload_name =
4104 send_config->encoder_settings.payload_name;
4105 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
4106 }
4107
4108 void EncodedFrameCallback(const EncodedFrame& encoded_frame) override {
4109 rtc::CritScope lock(&crit_);
4110 if (recorded_frames_++ > kNumFramesToRecord) {
4111 fixture_->LogSend(false);
4112 fixture_->LogReceive(false);
4113 rtc::File send_file(fixture_->OpenFile(0));
4114 rtc::File receive_file(fixture_->OpenFile(1));
4115 uint8_t out[100];
4116 // If logging has worked correctly neither file should be empty, i.e.
4117 // we should be able to read something from them.
4118 EXPECT_LT(0u, send_file.Read(out, 100));
4119 EXPECT_LT(0u, receive_file.Read(out, 100));
4120 observation_complete_.Set();
4121 }
4122 }
4123
4124 private:
4125 EndToEndLogTest* const fixture_;
4126 std::unique_ptr<VideoEncoder> encoder_;
4127 std::unique_ptr<VideoDecoder> decoder_;
4128 rtc::CriticalSection crit_;
4129 int recorded_frames_ GUARDED_BY(crit_);
4130 } test(this);
4131
4132 RunBaseTest(&test);
4133}
4134
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00004135} // namespace webrtc