blob: 502851bbcee267c09dfa18fcadc2994097cafee1 [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
philipel266f0a42016-11-28 08:49:07 -0800606TEST_P(EndToEndTest, CanReceiveUlpfec) {
brandtr535830e2016-10-31 03:45:58 -0700607 class UlpfecRenderObserver : public test::EndToEndTest,
608 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000609 public:
brandtr535830e2016-10-31 03:45:58 -0700610 UlpfecRenderObserver()
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000611 : EndToEndTest(kDefaultTimeoutMs), state_(kFirstPacket) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000612
613 private:
stefanf116bd02015-10-27 08:29:42 -0700614 Action OnSendRtp(const uint8_t* packet, size_t length) override {
615 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000616 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000617 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000618
Stefan Holmer01b48882015-05-05 10:21:24 +0200619 int encapsulated_payload_type = -1;
620 if (header.payloadType == kRedPayloadType) {
621 encapsulated_payload_type =
622 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100623 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200624 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
625 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100626 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200627 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000628
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000629 if (protected_sequence_numbers_.count(header.sequenceNumber) != 0) {
630 // Retransmitted packet, should not count.
631 protected_sequence_numbers_.erase(header.sequenceNumber);
philipel266f0a42016-11-28 08:49:07 -0800632 auto ts_it = protected_timestamps_.find(header.timestamp);
633 EXPECT_NE(ts_it, protected_timestamps_.end());
634 protected_timestamps_.erase(ts_it);
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000635 return SEND_PACKET;
636 }
637
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000638 switch (state_) {
639 case kFirstPacket:
brandtr535830e2016-10-31 03:45:58 -0700640 state_ = kDropEveryOtherPacketUntilUlpfec;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000641 break;
brandtr535830e2016-10-31 03:45:58 -0700642 case kDropEveryOtherPacketUntilUlpfec:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000643 if (encapsulated_payload_type == kUlpfecPayloadType) {
644 state_ = kDropNextMediaPacket;
645 return SEND_PACKET;
646 }
647 if (header.sequenceNumber % 2 == 0)
648 return DROP_PACKET;
649 break;
650 case kDropNextMediaPacket:
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100651 if (encapsulated_payload_type == kFakeVideoSendPayloadType) {
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000652 protected_sequence_numbers_.insert(header.sequenceNumber);
653 protected_timestamps_.insert(header.timestamp);
brandtr535830e2016-10-31 03:45:58 -0700654 state_ = kDropEveryOtherPacketUntilUlpfec;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000655 return DROP_PACKET;
656 }
657 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000658 }
659
660 return SEND_PACKET;
661 }
662
nisseeb83a1a2016-03-21 01:27:56 -0700663 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200664 rtc::CritScope lock(&crit_);
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000665 // Rendering frame with timestamp of packet that was dropped -> FEC
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000666 // protection worked.
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000667 if (protected_timestamps_.count(video_frame.timestamp()) != 0)
Peter Boström5811a392015-12-10 13:02:50 +0100668 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000669 }
670
671 enum {
672 kFirstPacket,
brandtr535830e2016-10-31 03:45:58 -0700673 kDropEveryOtherPacketUntilUlpfec,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000674 kDropNextMediaPacket,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000675 } state_;
676
stefanff483612015-12-21 03:14:00 -0800677 void ModifyVideoConfigs(
678 VideoSendStream::Config* send_config,
679 std::vector<VideoReceiveStream::Config>* receive_configs,
680 VideoEncoderConfig* encoder_config) override {
brandtr535830e2016-10-31 03:45:58 -0700681 // TODO(pbos): Run this test with combined NACK/ULPFEC enabled as well.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000682 // int rtp_history_ms = 1000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000683 // (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000684 // send_config->rtp.nack.rtp_history_ms = rtp_history_ms;
brandtrb5f2c3f2016-10-04 23:28:39 -0700685 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
686 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000687
brandtrb5f2c3f2016-10-04 23:28:39 -0700688 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
689 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000690 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000691 }
692
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000693 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100694 EXPECT_TRUE(Wait())
brandtr1e3dfbf2016-11-16 22:45:19 -0800695 << "Timed out waiting for dropped frames to be rendered.";
696 }
697
698 rtc::CriticalSection crit_;
699 std::set<uint32_t> protected_sequence_numbers_ GUARDED_BY(crit_);
philipel266f0a42016-11-28 08:49:07 -0800700 // Since several packets can have the same timestamp a multiset is used
701 // instead of a set.
702 std::multiset<uint32_t> protected_timestamps_ GUARDED_BY(crit_);
brandtr1e3dfbf2016-11-16 22:45:19 -0800703 } test;
704
705 RunBaseTest(&test);
706}
707
brandtrfa5a3682017-01-17 01:33:54 -0800708class FlexfecRenderObserver : public test::EndToEndTest,
709 public rtc::VideoSinkInterface<VideoFrame> {
710 public:
711 static constexpr uint32_t kVideoLocalSsrc = 123;
712 static constexpr uint32_t kFlexfecLocalSsrc = 456;
brandtr1e3dfbf2016-11-16 22:45:19 -0800713
brandtrfa5a3682017-01-17 01:33:54 -0800714 explicit FlexfecRenderObserver(bool expect_flexfec_rtcp)
715 : test::EndToEndTest(test::CallTest::kDefaultTimeoutMs),
716 expect_flexfec_rtcp_(expect_flexfec_rtcp),
717 received_flexfec_rtcp_(false),
718 random_(0xcafef00d1) {}
brandtr1e3dfbf2016-11-16 22:45:19 -0800719
brandtrfa5a3682017-01-17 01:33:54 -0800720 size_t GetNumFlexfecStreams() const override { return 1; }
brandtr1e3dfbf2016-11-16 22:45:19 -0800721
brandtrfa5a3682017-01-17 01:33:54 -0800722 private:
723 Action OnSendRtp(const uint8_t* packet, size_t length) override {
724 rtc::CritScope lock(&crit_);
725 RTPHeader header;
726 EXPECT_TRUE(parser_->Parse(packet, length, &header));
brandtr1e3dfbf2016-11-16 22:45:19 -0800727
brandtrfa5a3682017-01-17 01:33:54 -0800728 uint8_t payload_type = header.payloadType;
729 if (payload_type != test::CallTest::kFakeVideoSendPayloadType) {
730 EXPECT_EQ(test::CallTest::kFlexfecPayloadType, payload_type);
brandtr1e3dfbf2016-11-16 22:45:19 -0800731 }
732
brandtrfa5a3682017-01-17 01:33:54 -0800733 // Is this a retransmitted media packet? From the perspective of FEC, this
734 // packet is then no longer dropped, so remove it from the list of
735 // dropped packets.
736 if (payload_type == test::CallTest::kFakeVideoSendPayloadType) {
737 auto seq_num_it = dropped_sequence_numbers_.find(header.sequenceNumber);
738 if (seq_num_it != dropped_sequence_numbers_.end()) {
739 dropped_sequence_numbers_.erase(seq_num_it);
740 auto ts_it = dropped_timestamps_.find(header.timestamp);
741 EXPECT_NE(ts_it, dropped_timestamps_.end());
742 dropped_timestamps_.erase(ts_it);
743
744 return SEND_PACKET;
745 }
746 }
747
748 // Simulate 5% packet loss. Record what media packets, and corresponding
749 // timestamps, that were dropped.
750 if (random_.Rand(1, 100) <= 5) {
751 if (payload_type == test::CallTest::kFakeVideoSendPayloadType) {
752 dropped_sequence_numbers_.insert(header.sequenceNumber);
753 dropped_timestamps_.insert(header.timestamp);
754 }
755
756 return DROP_PACKET;
757 }
758
759 return SEND_PACKET;
760 }
761
762 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
763 test::RtcpPacketParser parser;
764
765 parser.Parse(data, length);
766 if (parser.sender_ssrc() == kFlexfecLocalSsrc) {
767 EXPECT_EQ(1, parser.receiver_report()->num_packets());
768 const std::vector<rtcp::ReportBlock>& report_blocks =
769 parser.receiver_report()->report_blocks();
770 if (!report_blocks.empty()) {
771 EXPECT_EQ(1U, report_blocks.size());
772 EXPECT_EQ(test::CallTest::kFlexfecSendSsrc,
773 report_blocks[0].source_ssrc());
774 received_flexfec_rtcp_ = true;
775 }
776 }
777
778 return SEND_PACKET;
779 }
780
781 void OnFrame(const VideoFrame& video_frame) override {
782 rtc::CritScope lock(&crit_);
783 // Rendering frame with timestamp of packet that was dropped -> FEC
784 // protection worked.
785 auto it = dropped_timestamps_.find(video_frame.timestamp());
786 if (it != dropped_timestamps_.end()) {
787 if (!expect_flexfec_rtcp_ || received_flexfec_rtcp_) {
brandtr1e3dfbf2016-11-16 22:45:19 -0800788 observation_complete_.Set();
brandtrfa5a3682017-01-17 01:33:54 -0800789 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800790 }
brandtrfa5a3682017-01-17 01:33:54 -0800791 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800792
brandtrfa5a3682017-01-17 01:33:54 -0800793 void ModifyVideoConfigs(
794 VideoSendStream::Config* send_config,
795 std::vector<VideoReceiveStream::Config>* receive_configs,
796 VideoEncoderConfig* encoder_config) override {
797 (*receive_configs)[0].rtp.local_ssrc = kVideoLocalSsrc;
798 (*receive_configs)[0].renderer = this;
799 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800800
brandtrfa5a3682017-01-17 01:33:54 -0800801 void ModifyFlexfecConfigs(
802 std::vector<FlexfecReceiveStream::Config>* receive_configs) override {
803 (*receive_configs)[0].local_ssrc = kFlexfecLocalSsrc;
804 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000805
brandtrfa5a3682017-01-17 01:33:54 -0800806 void PerformTest() override {
807 EXPECT_TRUE(Wait())
808 << "Timed out waiting for dropped frames to be rendered.";
809 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000810
brandtrfa5a3682017-01-17 01:33:54 -0800811 rtc::CriticalSection crit_;
812 std::set<uint32_t> dropped_sequence_numbers_ GUARDED_BY(crit_);
813 // Since several packets can have the same timestamp a multiset is used
814 // instead of a set.
815 std::multiset<uint32_t> dropped_timestamps_ GUARDED_BY(crit_);
816 bool expect_flexfec_rtcp_;
817 bool received_flexfec_rtcp_;
818 Random random_;
819};
820
821TEST_P(EndToEndTest, ReceivesFlexfec) {
822 FlexfecRenderObserver test(false);
823 RunBaseTest(&test);
824}
825
826TEST_P(EndToEndTest, ReceivesFlexfecAndSendsCorrespondingRtcp) {
827 FlexfecRenderObserver test(true);
stefane74eef12016-01-08 06:47:13 -0800828 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000829}
830
philipel266f0a42016-11-28 08:49:07 -0800831TEST_P(EndToEndTest, ReceivedUlpfecPacketsNotNacked) {
brandtr535830e2016-10-31 03:45:58 -0700832 class UlpfecNackObserver : public test::EndToEndTest {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000833 public:
brandtr535830e2016-10-31 03:45:58 -0700834 UlpfecNackObserver()
stefanf116bd02015-10-27 08:29:42 -0700835 : EndToEndTest(kDefaultTimeoutMs),
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000836 state_(kFirstPacket),
brandtr535830e2016-10-31 03:45:58 -0700837 ulpfec_sequence_number_(0),
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000838 has_last_sequence_number_(false),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200839 last_sequence_number_(0),
magjed509e4fe2016-11-18 01:34:11 -0800840 encoder_(VP8Encoder::Create()),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200841 decoder_(VP8Decoder::Create()) {}
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000842
843 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000844 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800845 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000846 RTPHeader header;
847 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000848
Stefan Holmer01b48882015-05-05 10:21:24 +0200849 int encapsulated_payload_type = -1;
850 if (header.payloadType == kRedPayloadType) {
851 encapsulated_payload_type =
852 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100853 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200854 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
855 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100856 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200857 }
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000858
859 if (has_last_sequence_number_ &&
860 !IsNewerSequenceNumber(header.sequenceNumber,
861 last_sequence_number_)) {
862 // Drop retransmitted packets.
863 return DROP_PACKET;
864 }
865 last_sequence_number_ = header.sequenceNumber;
866 has_last_sequence_number_ = true;
867
brandtr535830e2016-10-31 03:45:58 -0700868 bool ulpfec_packet = encapsulated_payload_type == kUlpfecPayloadType;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000869 switch (state_) {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000870 case kFirstPacket:
brandtr535830e2016-10-31 03:45:58 -0700871 state_ = kDropEveryOtherPacketUntilUlpfec;
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000872 break;
brandtr535830e2016-10-31 03:45:58 -0700873 case kDropEveryOtherPacketUntilUlpfec:
874 if (ulpfec_packet) {
875 state_ = kDropAllMediaPacketsUntilUlpfec;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000876 } else if (header.sequenceNumber % 2 == 0) {
877 return DROP_PACKET;
878 }
879 break;
brandtr535830e2016-10-31 03:45:58 -0700880 case kDropAllMediaPacketsUntilUlpfec:
881 if (!ulpfec_packet)
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000882 return DROP_PACKET;
brandtr535830e2016-10-31 03:45:58 -0700883 ulpfec_sequence_number_ = header.sequenceNumber;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200884 state_ = kDropOneMediaPacket;
885 break;
886 case kDropOneMediaPacket:
brandtr535830e2016-10-31 03:45:58 -0700887 if (ulpfec_packet)
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200888 return DROP_PACKET;
889 state_ = kPassOneMediaPacket;
890 return DROP_PACKET;
891 break;
892 case kPassOneMediaPacket:
brandtr535830e2016-10-31 03:45:58 -0700893 if (ulpfec_packet)
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200894 return DROP_PACKET;
895 // Pass one media packet after dropped packet after last FEC,
896 // otherwise receiver might never see a seq_no after
brandtr535830e2016-10-31 03:45:58 -0700897 // |ulpfec_sequence_number_|
898 state_ = kVerifyUlpfecPacketNotInNackList;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000899 break;
brandtr535830e2016-10-31 03:45:58 -0700900 case kVerifyUlpfecPacketNotInNackList:
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000901 // Continue to drop packets. Make sure no frame can be decoded.
brandtr535830e2016-10-31 03:45:58 -0700902 if (ulpfec_packet || header.sequenceNumber % 2 == 0)
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000903 return DROP_PACKET;
904 break;
905 }
906 return SEND_PACKET;
907 }
908
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000909 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800910 rtc::CritScope lock_(&crit_);
brandtr535830e2016-10-31 03:45:58 -0700911 if (state_ == kVerifyUlpfecPacketNotInNackList) {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000912 test::RtcpPacketParser rtcp_parser;
913 rtcp_parser.Parse(packet, length);
Danil Chapovalovba6f7be2016-09-02 18:29:10 +0200914 const std::vector<uint16_t>& nacks = rtcp_parser.nack()->packet_ids();
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200915 EXPECT_TRUE(std::find(nacks.begin(), nacks.end(),
brandtr535830e2016-10-31 03:45:58 -0700916 ulpfec_sequence_number_) == nacks.end())
917 << "Got nack for ULPFEC packet";
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000918 if (!nacks.empty() &&
brandtr535830e2016-10-31 03:45:58 -0700919 IsNewerSequenceNumber(nacks.back(), ulpfec_sequence_number_)) {
Peter Boström5811a392015-12-10 13:02:50 +0100920 observation_complete_.Set();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000921 }
922 }
923 return SEND_PACKET;
924 }
925
stefane74eef12016-01-08 06:47:13 -0800926 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
927 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
928 // Configure some network delay.
929 const int kNetworkDelayMs = 50;
930 FakeNetworkPipe::Config config;
931 config.queue_delay_ms = kNetworkDelayMs;
932 return new test::PacketTransport(sender_call, this,
933 test::PacketTransport::kSender, config);
934 }
935
Stefan Holmere5904162015-03-26 11:11:06 +0100936 // TODO(holmer): Investigate why we don't send FEC packets when the bitrate
937 // is 10 kbps.
938 Call::Config GetSenderCallConfig() override {
skvlad11a9cbf2016-10-07 11:53:05 -0700939 Call::Config config(&event_log_);
Stefan Holmere5904162015-03-26 11:11:06 +0100940 const int kMinBitrateBps = 30000;
941 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
942 return config;
943 }
944
stefanff483612015-12-21 03:14:00 -0800945 void ModifyVideoConfigs(
946 VideoSendStream::Config* send_config,
947 std::vector<VideoReceiveStream::Config>* receive_configs,
948 VideoEncoderConfig* encoder_config) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000949 // Configure hybrid NACK/FEC.
950 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
brandtrb5f2c3f2016-10-04 23:28:39 -0700951 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
952 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200953 // Set codec to VP8, otherwise NACK/FEC hybrid will be disabled.
954 send_config->encoder_settings.encoder = encoder_.get();
955 send_config->encoder_settings.payload_name = "VP8";
956 send_config->encoder_settings.payload_type = kFakeVideoSendPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200957
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000958 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
brandtrb5f2c3f2016-10-04 23:28:39 -0700959 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
960 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200961
962 (*receive_configs)[0].decoders.resize(1);
963 (*receive_configs)[0].decoders[0].payload_type =
964 send_config->encoder_settings.payload_type;
965 (*receive_configs)[0].decoders[0].payload_name =
966 send_config->encoder_settings.payload_name;
967 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000968 }
969
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000970 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100971 EXPECT_TRUE(Wait())
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000972 << "Timed out while waiting for FEC packets to be received.";
973 }
974
975 enum {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000976 kFirstPacket,
brandtr535830e2016-10-31 03:45:58 -0700977 kDropEveryOtherPacketUntilUlpfec,
978 kDropAllMediaPacketsUntilUlpfec,
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200979 kDropOneMediaPacket,
980 kPassOneMediaPacket,
brandtr535830e2016-10-31 03:45:58 -0700981 kVerifyUlpfecPacketNotInNackList,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000982 } state_;
983
stefan608213e2015-11-01 14:56:10 -0800984 rtc::CriticalSection crit_;
brandtr535830e2016-10-31 03:45:58 -0700985 uint16_t ulpfec_sequence_number_ GUARDED_BY(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000986 bool has_last_sequence_number_;
987 uint16_t last_sequence_number_;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200988 std::unique_ptr<webrtc::VideoEncoder> encoder_;
989 std::unique_ptr<webrtc::VideoDecoder> decoder_;
stefanf116bd02015-10-27 08:29:42 -0700990 } test;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000991
stefane74eef12016-01-08 06:47:13 -0800992 RunBaseTest(&test);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000993}
994
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000995// This test drops second RTP packet with a marker bit set, makes sure it's
996// retransmitted and renders. Retransmission SSRCs are also checked.
Peter Boström39593972016-02-15 11:27:15 +0100997void EndToEndTest::DecodesRetransmittedFrame(bool enable_rtx, bool enable_red) {
Peter Boström67680c12016-02-17 11:10:04 +0100998 static const int kDroppedFrameNumber = 10;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000999 class RetransmissionObserver : public test::EndToEndTest,
1000 public I420FrameCallback {
1001 public:
Peter Boström39593972016-02-15 11:27:15 +01001002 RetransmissionObserver(bool enable_rtx, bool enable_red)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001003 : EndToEndTest(kDefaultTimeoutMs),
Peter Boström39593972016-02-15 11:27:15 +01001004 payload_type_(GetPayloadType(false, enable_red)),
1005 retransmission_ssrc_(enable_rtx ? kSendRtxSsrcs[0]
1006 : kVideoSendSsrcs[0]),
1007 retransmission_payload_type_(GetPayloadType(enable_rtx, enable_red)),
magjed509e4fe2016-11-18 01:34:11 -08001008 encoder_(VP8Encoder::Create()),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001009 marker_bits_observed_(0),
danilchap192717e2016-07-25 08:20:51 -07001010 retransmitted_timestamp_(0) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001011
1012 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001013 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001014 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001015 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001016 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001017
Peter Boström67680c12016-02-17 11:10:04 +01001018 // Ignore padding-only packets over RTX.
1019 if (header.payloadType != payload_type_) {
1020 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
1021 if (length == header.headerLength + header.paddingLength)
1022 return SEND_PACKET;
Stefan Holmer586b19b2015-09-18 11:14:31 +02001023 }
Peter Boström67680c12016-02-17 11:10:04 +01001024
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001025 if (header.timestamp == retransmitted_timestamp_) {
1026 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
1027 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001028 return SEND_PACKET;
1029 }
1030
Stefan Holmer586b19b2015-09-18 11:14:31 +02001031 // Found the final packet of the frame to inflict loss to, drop this and
1032 // expect a retransmission.
danilchapfdd381c2016-07-25 04:03:20 -07001033 if (header.payloadType == payload_type_ && header.markerBit &&
1034 ++marker_bits_observed_ == kDroppedFrameNumber) {
Danil Chapovalov18c65a42016-06-29 15:29:34 +02001035 // This should be the only dropped packet.
1036 EXPECT_EQ(0u, retransmitted_timestamp_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001037 retransmitted_timestamp_ = header.timestamp;
danilchap192717e2016-07-25 08:20:51 -07001038 if (std::find(rendered_timestamps_.begin(), rendered_timestamps_.end(),
1039 retransmitted_timestamp_) != rendered_timestamps_.end()) {
1040 // Frame was rendered before last packet was scheduled for sending.
1041 // This is extremly rare but possible scenario because prober able to
1042 // resend packet before it was send.
1043 // TODO(danilchap): Remove this corner case when prober would not be
1044 // able to sneak in between packet saved to history for resending and
1045 // pacer notified about existance of that packet for sending.
1046 // See https://bugs.chromium.org/p/webrtc/issues/detail?id=5540 for
1047 // details.
1048 observation_complete_.Set();
1049 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001050 return DROP_PACKET;
1051 }
1052
1053 return SEND_PACKET;
1054 }
1055
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001056 void FrameCallback(VideoFrame* frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001057 rtc::CritScope lock(&crit_);
danilchap192717e2016-07-25 08:20:51 -07001058 if (frame->timestamp() == retransmitted_timestamp_)
Peter Boström5811a392015-12-10 13:02:50 +01001059 observation_complete_.Set();
danilchap192717e2016-07-25 08:20:51 -07001060 rendered_timestamps_.push_back(frame->timestamp());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001061 }
1062
stefanff483612015-12-21 03:14:00 -08001063 void ModifyVideoConfigs(
1064 VideoSendStream::Config* send_config,
1065 std::vector<VideoReceiveStream::Config>* receive_configs,
1066 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001067 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001068 (*receive_configs)[0].pre_render_callback = this;
1069 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
Shao Changbine62202f2015-04-21 20:24:50 +08001070
1071 if (payload_type_ == kRedPayloadType) {
brandtrb5f2c3f2016-10-04 23:28:39 -07001072 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
1073 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +01001074 if (retransmission_ssrc_ == kSendRtxSsrcs[0])
brandtrb5f2c3f2016-10-04 23:28:39 -07001075 send_config->rtp.ulpfec.red_rtx_payload_type = kRtxRedPayloadType;
1076 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type =
1077 send_config->rtp.ulpfec.ulpfec_payload_type;
1078 (*receive_configs)[0].rtp.ulpfec.red_payload_type =
1079 send_config->rtp.ulpfec.red_payload_type;
1080 (*receive_configs)[0].rtp.ulpfec.red_rtx_payload_type =
1081 send_config->rtp.ulpfec.red_rtx_payload_type;
Shao Changbine62202f2015-04-21 20:24:50 +08001082 }
1083
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001084 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
1085 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001086 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +01001087 (*receive_configs)[0].rtp.rtx[payload_type_].ssrc = kSendRtxSsrcs[0];
1088 (*receive_configs)[0].rtp.rtx[payload_type_].payload_type =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001089 kSendRtxPayloadType;
1090 }
Peter Boström39593972016-02-15 11:27:15 +01001091 // Configure encoding and decoding with VP8, since generic packetization
1092 // doesn't support FEC with NACK.
kwibergaf476c72016-11-28 15:21:39 -08001093 RTC_DCHECK_EQ(1, (*receive_configs)[0].decoders.size());
Peter Boström39593972016-02-15 11:27:15 +01001094 send_config->encoder_settings.encoder = encoder_.get();
1095 send_config->encoder_settings.payload_name = "VP8";
1096 (*receive_configs)[0].decoders[0].payload_name = "VP8";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001097 }
1098
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001099 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001100 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001101 << "Timed out while waiting for retransmission to render.";
1102 }
1103
Shao Changbine62202f2015-04-21 20:24:50 +08001104 int GetPayloadType(bool use_rtx, bool use_red) {
Stefan Holmer10880012016-02-03 13:29:59 +01001105 if (use_red) {
1106 if (use_rtx)
1107 return kRtxRedPayloadType;
1108 return kRedPayloadType;
1109 }
1110 if (use_rtx)
1111 return kSendRtxPayloadType;
1112 return kFakeVideoSendPayloadType;
Shao Changbine62202f2015-04-21 20:24:50 +08001113 }
1114
stefanf116bd02015-10-27 08:29:42 -07001115 rtc::CriticalSection crit_;
Shao Changbine62202f2015-04-21 20:24:50 +08001116 const int payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001117 const uint32_t retransmission_ssrc_;
1118 const int retransmission_payload_type_;
kwiberg27f982b2016-03-01 11:52:33 -08001119 std::unique_ptr<VideoEncoder> encoder_;
Peter Boström39593972016-02-15 11:27:15 +01001120 const std::string payload_name_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001121 int marker_bits_observed_;
stefanf116bd02015-10-27 08:29:42 -07001122 uint32_t retransmitted_timestamp_ GUARDED_BY(&crit_);
danilchap192717e2016-07-25 08:20:51 -07001123 std::vector<uint32_t> rendered_timestamps_ GUARDED_BY(&crit_);
Peter Boström39593972016-02-15 11:27:15 +01001124 } test(enable_rtx, enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001125
stefane74eef12016-01-08 06:47:13 -08001126 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001127}
1128
philipel266f0a42016-11-28 08:49:07 -08001129TEST_P(EndToEndTest, DecodesRetransmittedFrame) {
Shao Changbine62202f2015-04-21 20:24:50 +08001130 DecodesRetransmittedFrame(false, false);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001131}
1132
philipel266f0a42016-11-28 08:49:07 -08001133TEST_P(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +08001134 DecodesRetransmittedFrame(true, false);
1135}
1136
philipel266f0a42016-11-28 08:49:07 -08001137TEST_P(EndToEndTest, DecodesRetransmittedFrameByRed) {
Shao Changbine62202f2015-04-21 20:24:50 +08001138 DecodesRetransmittedFrame(false, true);
1139}
1140
philipel266f0a42016-11-28 08:49:07 -08001141TEST_P(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +08001142 DecodesRetransmittedFrame(true, true);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001143}
1144
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001145void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
1146 static const int kPacketsToDrop = 1;
1147
nisse7ade7b32016-03-23 04:48:10 -07001148 class PliObserver : public test::EndToEndTest,
1149 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001150 public:
1151 explicit PliObserver(int rtp_history_ms)
1152 : EndToEndTest(kLongTimeoutMs),
1153 rtp_history_ms_(rtp_history_ms),
1154 nack_enabled_(rtp_history_ms > 0),
1155 highest_dropped_timestamp_(0),
1156 frames_to_drop_(0),
1157 received_pli_(false) {}
1158
1159 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001160 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001161 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001162 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001163 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001164
1165 // Drop all retransmitted packets to force a PLI.
1166 if (header.timestamp <= highest_dropped_timestamp_)
1167 return DROP_PACKET;
1168
1169 if (frames_to_drop_ > 0) {
1170 highest_dropped_timestamp_ = header.timestamp;
1171 --frames_to_drop_;
1172 return DROP_PACKET;
1173 }
1174
1175 return SEND_PACKET;
1176 }
1177
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001178 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001179 rtc::CritScope lock(&crit_);
danilchap3dc929e2016-11-02 08:21:59 -07001180 test::RtcpPacketParser parser;
1181 EXPECT_TRUE(parser.Parse(packet, length));
1182 if (!nack_enabled_)
1183 EXPECT_EQ(0, parser.nack()->num_packets());
1184 if (parser.pli()->num_packets() > 0)
1185 received_pli_ = true;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001186 return SEND_PACKET;
1187 }
1188
nisseeb83a1a2016-03-21 01:27:56 -07001189 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001190 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001191 if (received_pli_ &&
1192 video_frame.timestamp() > highest_dropped_timestamp_) {
Peter Boström5811a392015-12-10 13:02:50 +01001193 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001194 }
1195 if (!received_pli_)
1196 frames_to_drop_ = kPacketsToDrop;
1197 }
1198
stefanff483612015-12-21 03:14:00 -08001199 void ModifyVideoConfigs(
1200 VideoSendStream::Config* send_config,
1201 std::vector<VideoReceiveStream::Config>* receive_configs,
1202 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001203 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001204 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
1205 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001206 }
1207
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001208 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001209 EXPECT_TRUE(Wait()) << "Timed out waiting for PLI to be "
1210 "received and a frame to be "
1211 "rendered afterwards.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001212 }
1213
stefanf116bd02015-10-27 08:29:42 -07001214 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001215 int rtp_history_ms_;
1216 bool nack_enabled_;
stefanf116bd02015-10-27 08:29:42 -07001217 uint32_t highest_dropped_timestamp_ GUARDED_BY(&crit_);
1218 int frames_to_drop_ GUARDED_BY(&crit_);
1219 bool received_pli_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001220 } test(rtp_history_ms);
1221
stefane74eef12016-01-08 06:47:13 -08001222 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001223}
1224
philipel266f0a42016-11-28 08:49:07 -08001225TEST_P(EndToEndTest, ReceivesPliAndRecoversWithNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001226 ReceivesPliAndRecovers(1000);
1227}
1228
philipel266f0a42016-11-28 08:49:07 -08001229TEST_P(EndToEndTest, ReceivesPliAndRecoversWithoutNack) {
1230 // This test makes no sense for the new video jitter buffer.
1231 if (GetParam() == new_jb_enabled)
1232 return;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001233 ReceivesPliAndRecovers(0);
1234}
1235
philipel266f0a42016-11-28 08:49:07 -08001236TEST_P(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001237 class PacketInputObserver : public PacketReceiver {
1238 public:
1239 explicit PacketInputObserver(PacketReceiver* receiver)
Peter Boström5811a392015-12-10 13:02:50 +01001240 : receiver_(receiver), delivered_packet_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001241
Peter Boström5811a392015-12-10 13:02:50 +01001242 bool Wait() { return delivered_packet_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001243
1244 private:
stefan68786d22015-09-08 05:36:15 -07001245 DeliveryStatus DeliverPacket(MediaType media_type,
1246 const uint8_t* packet,
1247 size_t length,
1248 const PacketTime& packet_time) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001249 if (RtpHeaderParser::IsRtcp(packet, length)) {
stefan68786d22015-09-08 05:36:15 -07001250 return receiver_->DeliverPacket(media_type, packet, length,
1251 packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001252 } else {
1253 DeliveryStatus delivery_status =
stefan68786d22015-09-08 05:36:15 -07001254 receiver_->DeliverPacket(media_type, packet, length, packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001255 EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
Peter Boström5811a392015-12-10 13:02:50 +01001256 delivered_packet_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001257 return delivery_status;
1258 }
1259 }
1260
1261 PacketReceiver* receiver_;
Peter Boström5811a392015-12-10 13:02:50 +01001262 rtc::Event delivered_packet_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001263 };
1264
skvlad11a9cbf2016-10-07 11:53:05 -07001265 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -07001266
stefanf116bd02015-10-27 08:29:42 -07001267 test::DirectTransport send_transport(sender_call_.get());
1268 test::DirectTransport receive_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001269 PacketInputObserver input_observer(receiver_call_->Receiver());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001270 send_transport.SetReceiver(&input_observer);
1271 receive_transport.SetReceiver(sender_call_->Receiver());
1272
brandtr841de6a2016-11-15 07:10:52 -08001273 CreateSendConfig(1, 0, 0, &send_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001274 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001275
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001276 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07001277 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
1278 kDefaultHeight);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001279 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001280
stefanff483612015-12-21 03:14:00 -08001281 receiver_call_->DestroyVideoReceiveStream(video_receive_streams_[0]);
1282 video_receive_streams_.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001283
1284 // Wait() waits for a received packet.
Peter Boström5811a392015-12-10 13:02:50 +01001285 EXPECT_TRUE(input_observer.Wait());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001286
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001287 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001288
1289 DestroyStreams();
1290
1291 send_transport.StopSending();
1292 receive_transport.StopSending();
1293}
1294
pbosda903ea2015-10-02 02:36:56 -07001295void EndToEndTest::RespectsRtcpMode(RtcpMode rtcp_mode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001296 static const int kNumCompoundRtcpPacketsToObserve = 10;
1297 class RtcpModeObserver : public test::EndToEndTest {
1298 public:
pbosda903ea2015-10-02 02:36:56 -07001299 explicit RtcpModeObserver(RtcpMode rtcp_mode)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001300 : EndToEndTest(kDefaultTimeoutMs),
1301 rtcp_mode_(rtcp_mode),
1302 sent_rtp_(0),
1303 sent_rtcp_(0) {}
1304
1305 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001306 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001307 if (++sent_rtp_ % 3 == 0)
1308 return DROP_PACKET;
1309
1310 return SEND_PACKET;
1311 }
1312
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001313 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001314 ++sent_rtcp_;
danilchap3dc929e2016-11-02 08:21:59 -07001315 test::RtcpPacketParser parser;
1316 EXPECT_TRUE(parser.Parse(packet, length));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001317
danilchap3dc929e2016-11-02 08:21:59 -07001318 EXPECT_EQ(0, parser.sender_report()->num_packets());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001319
1320 switch (rtcp_mode_) {
pbosda903ea2015-10-02 02:36:56 -07001321 case RtcpMode::kCompound:
danilchap3dc929e2016-11-02 08:21:59 -07001322 if (parser.receiver_report()->num_packets() == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001323 ADD_FAILURE() << "Received RTCP packet without receiver report for "
pbosda903ea2015-10-02 02:36:56 -07001324 "RtcpMode::kCompound.";
Peter Boström5811a392015-12-10 13:02:50 +01001325 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001326 }
1327
1328 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
Peter Boström5811a392015-12-10 13:02:50 +01001329 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001330
1331 break;
pbosda903ea2015-10-02 02:36:56 -07001332 case RtcpMode::kReducedSize:
danilchap3dc929e2016-11-02 08:21:59 -07001333 if (parser.receiver_report()->num_packets() == 0)
Peter Boström5811a392015-12-10 13:02:50 +01001334 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001335 break;
pbosda903ea2015-10-02 02:36:56 -07001336 case RtcpMode::kOff:
1337 RTC_NOTREACHED();
1338 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001339 }
1340
1341 return SEND_PACKET;
1342 }
1343
stefanff483612015-12-21 03:14:00 -08001344 void ModifyVideoConfigs(
1345 VideoSendStream::Config* send_config,
1346 std::vector<VideoReceiveStream::Config>* receive_configs,
1347 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001348 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001349 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1350 (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001351 }
1352
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001353 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001354 EXPECT_TRUE(Wait())
pbosda903ea2015-10-02 02:36:56 -07001355 << (rtcp_mode_ == RtcpMode::kCompound
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001356 ? "Timed out before observing enough compound packets."
1357 : "Timed out before receiving a non-compound RTCP packet.");
1358 }
1359
pbosda903ea2015-10-02 02:36:56 -07001360 RtcpMode rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001361 int sent_rtp_;
1362 int sent_rtcp_;
1363 } test(rtcp_mode);
1364
stefane74eef12016-01-08 06:47:13 -08001365 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001366}
1367
philipel266f0a42016-11-28 08:49:07 -08001368TEST_P(EndToEndTest, UsesRtcpCompoundMode) {
pbosda903ea2015-10-02 02:36:56 -07001369 RespectsRtcpMode(RtcpMode::kCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001370}
1371
philipel266f0a42016-11-28 08:49:07 -08001372TEST_P(EndToEndTest, UsesRtcpReducedSizeMode) {
pbosda903ea2015-10-02 02:36:56 -07001373 RespectsRtcpMode(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001374}
1375
1376// Test sets up a Call multiple senders with different resolutions and SSRCs.
1377// Another is set up to receive all three of these with different renderers.
sprang867fb522015-08-03 04:38:41 -07001378class MultiStreamTest {
1379 public:
1380 static const size_t kNumStreams = 3;
1381 struct CodecSettings {
1382 uint32_t ssrc;
1383 int width;
1384 int height;
1385 } codec_settings[kNumStreams];
1386
1387 MultiStreamTest() {
1388 // TODO(sprang): Cleanup when msvc supports explicit initializers for array.
1389 codec_settings[0] = {1, 640, 480};
1390 codec_settings[1] = {2, 320, 240};
1391 codec_settings[2] = {3, 240, 160};
1392 }
1393
1394 virtual ~MultiStreamTest() {}
1395
1396 void RunTest() {
skvlad11a9cbf2016-10-07 11:53:05 -07001397 webrtc::RtcEventLogNullImpl event_log;
1398 Call::Config config(&event_log);
1399 std::unique_ptr<Call> sender_call(Call::Create(config));
1400 std::unique_ptr<Call> receiver_call(Call::Create(config));
kwiberg27f982b2016-03-01 11:52:33 -08001401 std::unique_ptr<test::DirectTransport> sender_transport(
stefanf116bd02015-10-27 08:29:42 -07001402 CreateSendTransport(sender_call.get()));
kwiberg27f982b2016-03-01 11:52:33 -08001403 std::unique_ptr<test::DirectTransport> receiver_transport(
stefanf116bd02015-10-27 08:29:42 -07001404 CreateReceiveTransport(receiver_call.get()));
sprang867fb522015-08-03 04:38:41 -07001405 sender_transport->SetReceiver(receiver_call->Receiver());
1406 receiver_transport->SetReceiver(sender_call->Receiver());
1407
kwiberg27f982b2016-03-01 11:52:33 -08001408 std::unique_ptr<VideoEncoder> encoders[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001409 for (size_t i = 0; i < kNumStreams; ++i)
magjed509e4fe2016-11-18 01:34:11 -08001410 encoders[i].reset(VP8Encoder::Create());
sprang867fb522015-08-03 04:38:41 -07001411
1412 VideoSendStream* send_streams[kNumStreams];
1413 VideoReceiveStream* receive_streams[kNumStreams];
1414
1415 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
kwiberg4a206a92016-03-31 10:24:26 -07001416 std::vector<std::unique_ptr<VideoDecoder>> allocated_decoders;
sprang867fb522015-08-03 04:38:41 -07001417 for (size_t i = 0; i < kNumStreams; ++i) {
1418 uint32_t ssrc = codec_settings[i].ssrc;
1419 int width = codec_settings[i].width;
1420 int height = codec_settings[i].height;
1421
solenberg4fbae2b2015-08-28 04:07:10 -07001422 VideoSendStream::Config send_config(sender_transport.get());
sprang867fb522015-08-03 04:38:41 -07001423 send_config.rtp.ssrcs.push_back(ssrc);
1424 send_config.encoder_settings.encoder = encoders[i].get();
1425 send_config.encoder_settings.payload_name = "VP8";
1426 send_config.encoder_settings.payload_type = 124;
1427 VideoEncoderConfig encoder_config;
perkjfa10b552016-10-02 23:45:26 -07001428 test::FillEncoderConfiguration(1, &encoder_config);
1429 encoder_config.max_bitrate_bps = 100000;
sprang867fb522015-08-03 04:38:41 -07001430
1431 UpdateSendConfig(i, &send_config, &encoder_config, &frame_generators[i]);
1432
perkj26091b12016-09-01 01:17:40 -07001433 send_streams[i] = sender_call->CreateVideoSendStream(
1434 send_config.Copy(), encoder_config.Copy());
sprang867fb522015-08-03 04:38:41 -07001435 send_streams[i]->Start();
1436
solenberg4fbae2b2015-08-28 04:07:10 -07001437 VideoReceiveStream::Config receive_config(receiver_transport.get());
sprang867fb522015-08-03 04:38:41 -07001438 receive_config.rtp.remote_ssrc = ssrc;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001439 receive_config.rtp.local_ssrc = test::CallTest::kReceiverLocalVideoSsrc;
sprang867fb522015-08-03 04:38:41 -07001440 VideoReceiveStream::Decoder decoder =
1441 test::CreateMatchingDecoder(send_config.encoder_settings);
kwiberg4a206a92016-03-31 10:24:26 -07001442 allocated_decoders.push_back(
1443 std::unique_ptr<VideoDecoder>(decoder.decoder));
sprang867fb522015-08-03 04:38:41 -07001444 receive_config.decoders.push_back(decoder);
1445
1446 UpdateReceiveConfig(i, &receive_config);
1447
1448 receive_streams[i] =
Tommi733b5472016-06-10 17:58:01 +02001449 receiver_call->CreateVideoReceiveStream(std::move(receive_config));
sprang867fb522015-08-03 04:38:41 -07001450 receive_streams[i]->Start();
1451
1452 frame_generators[i] = test::FrameGeneratorCapturer::Create(
perkja49cbd32016-09-16 07:53:41 -07001453 width, height, 30, Clock::GetRealTimeClock());
perkj803d97f2016-11-01 11:45:46 -07001454 send_streams[i]->SetSource(
1455 frame_generators[i],
1456 VideoSendStream::DegradationPreference::kBalanced);
sprang867fb522015-08-03 04:38:41 -07001457 frame_generators[i]->Start();
1458 }
1459
1460 Wait();
1461
1462 for (size_t i = 0; i < kNumStreams; ++i) {
1463 frame_generators[i]->Stop();
1464 sender_call->DestroyVideoSendStream(send_streams[i]);
1465 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1466 delete frame_generators[i];
1467 }
1468
1469 sender_transport->StopSending();
1470 receiver_transport->StopSending();
1471 }
1472
1473 protected:
1474 virtual void Wait() = 0;
1475 // Note: frame_generator is a point-to-pointer, since the actual instance
1476 // hasn't been created at the time of this call. Only when packets/frames
1477 // start flowing should this be dereferenced.
1478 virtual void UpdateSendConfig(
1479 size_t stream_index,
1480 VideoSendStream::Config* send_config,
1481 VideoEncoderConfig* encoder_config,
1482 test::FrameGeneratorCapturer** frame_generator) {}
1483 virtual void UpdateReceiveConfig(size_t stream_index,
1484 VideoReceiveStream::Config* receive_config) {
1485 }
stefanf116bd02015-10-27 08:29:42 -07001486 virtual test::DirectTransport* CreateSendTransport(Call* sender_call) {
1487 return new test::DirectTransport(sender_call);
sprang867fb522015-08-03 04:38:41 -07001488 }
stefanf116bd02015-10-27 08:29:42 -07001489 virtual test::DirectTransport* CreateReceiveTransport(Call* receiver_call) {
1490 return new test::DirectTransport(receiver_call);
sprang867fb522015-08-03 04:38:41 -07001491 }
1492};
1493
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001494// Each renderer verifies that it receives the expected resolution, and as soon
1495// as every renderer has received a frame, the test finishes.
philipel266f0a42016-11-28 08:49:07 -08001496TEST_P(EndToEndTest, SendsAndReceivesMultipleStreams) {
nisse7ade7b32016-03-23 04:48:10 -07001497 class VideoOutputObserver : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001498 public:
sprang867fb522015-08-03 04:38:41 -07001499 VideoOutputObserver(const MultiStreamTest::CodecSettings& settings,
1500 uint32_t ssrc,
1501 test::FrameGeneratorCapturer** frame_generator)
1502 : settings_(settings),
1503 ssrc_(ssrc),
1504 frame_generator_(frame_generator),
Peter Boström5811a392015-12-10 13:02:50 +01001505 done_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001506
nisseeb83a1a2016-03-21 01:27:56 -07001507 void OnFrame(const VideoFrame& video_frame) override {
sprang867fb522015-08-03 04:38:41 -07001508 EXPECT_EQ(settings_.width, video_frame.width());
1509 EXPECT_EQ(settings_.height, video_frame.height());
1510 (*frame_generator_)->Stop();
Peter Boström5811a392015-12-10 13:02:50 +01001511 done_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001512 }
1513
sprang867fb522015-08-03 04:38:41 -07001514 uint32_t Ssrc() { return ssrc_; }
1515
Peter Boström5811a392015-12-10 13:02:50 +01001516 bool Wait() { return done_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001517
1518 private:
sprang867fb522015-08-03 04:38:41 -07001519 const MultiStreamTest::CodecSettings& settings_;
1520 const uint32_t ssrc_;
1521 test::FrameGeneratorCapturer** const frame_generator_;
Peter Boström5811a392015-12-10 13:02:50 +01001522 rtc::Event done_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001523 };
1524
sprang867fb522015-08-03 04:38:41 -07001525 class Tester : public MultiStreamTest {
1526 public:
1527 Tester() {}
1528 virtual ~Tester() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001529
sprang867fb522015-08-03 04:38:41 -07001530 protected:
1531 void Wait() override {
1532 for (const auto& observer : observers_) {
Peter Boström5811a392015-12-10 13:02:50 +01001533 EXPECT_TRUE(observer->Wait()) << "Time out waiting for from on ssrc "
1534 << observer->Ssrc();
sprang867fb522015-08-03 04:38:41 -07001535 }
1536 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001537
sprang867fb522015-08-03 04:38:41 -07001538 void UpdateSendConfig(
1539 size_t stream_index,
1540 VideoSendStream::Config* send_config,
1541 VideoEncoderConfig* encoder_config,
1542 test::FrameGeneratorCapturer** frame_generator) override {
1543 observers_[stream_index].reset(new VideoOutputObserver(
1544 codec_settings[stream_index], send_config->rtp.ssrcs.front(),
1545 frame_generator));
1546 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001547
sprang867fb522015-08-03 04:38:41 -07001548 void UpdateReceiveConfig(
1549 size_t stream_index,
1550 VideoReceiveStream::Config* receive_config) override {
1551 receive_config->renderer = observers_[stream_index].get();
1552 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001553
sprang867fb522015-08-03 04:38:41 -07001554 private:
kwiberg27f982b2016-03-01 11:52:33 -08001555 std::unique_ptr<VideoOutputObserver> observers_[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001556 } tester;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001557
sprang867fb522015-08-03 04:38:41 -07001558 tester.RunTest();
1559}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001560
philipel266f0a42016-11-28 08:49:07 -08001561TEST_P(EndToEndTest, AssignsTransportSequenceNumbers) {
sprang867fb522015-08-03 04:38:41 -07001562 static const int kExtensionId = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001563
sprang867fb522015-08-03 04:38:41 -07001564 class RtpExtensionHeaderObserver : public test::DirectTransport {
1565 public:
stefanf116bd02015-10-27 08:29:42 -07001566 RtpExtensionHeaderObserver(Call* sender_call,
1567 const uint32_t& first_media_ssrc,
sprang861c55e2015-10-16 10:01:21 -07001568 const std::map<uint32_t, uint32_t>& ssrc_map)
stefanf116bd02015-10-27 08:29:42 -07001569 : DirectTransport(sender_call),
Peter Boström5811a392015-12-10 13:02:50 +01001570 done_(false, false),
sprang867fb522015-08-03 04:38:41 -07001571 parser_(RtpHeaderParser::Create()),
sprang861c55e2015-10-16 10:01:21 -07001572 first_media_ssrc_(first_media_ssrc),
1573 rtx_to_media_ssrcs_(ssrc_map),
sprang867fb522015-08-03 04:38:41 -07001574 padding_observed_(false),
sprang861c55e2015-10-16 10:01:21 -07001575 rtx_padding_observed_(false),
1576 retransmit_observed_(false),
1577 started_(false) {
sprang867fb522015-08-03 04:38:41 -07001578 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
1579 kExtensionId);
1580 }
1581 virtual ~RtpExtensionHeaderObserver() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001582
stefan1d8a5062015-10-02 03:39:33 -07001583 bool SendRtp(const uint8_t* data,
1584 size_t length,
1585 const PacketOptions& options) override {
sprang861c55e2015-10-16 10:01:21 -07001586 {
1587 rtc::CritScope cs(&lock_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001588
Erik Språng8d629712015-08-04 16:24:03 +02001589 if (IsDone())
sprang861c55e2015-10-16 10:01:21 -07001590 return false;
1591
1592 if (started_) {
1593 RTPHeader header;
1594 EXPECT_TRUE(parser_->Parse(data, length, &header));
1595 bool drop_packet = false;
1596
1597 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
1598 EXPECT_EQ(options.packet_id,
1599 header.extension.transportSequenceNumber);
1600 if (!streams_observed_.empty()) {
1601 // Unwrap packet id and verify uniqueness.
1602 int64_t packet_id = unwrapper_.Unwrap(options.packet_id);
1603 EXPECT_TRUE(received_packed_ids_.insert(packet_id).second);
1604 }
1605
1606 // Drop (up to) every 17th packet, so we get retransmits.
1607 // Only drop media, and not on the first stream (otherwise it will be
1608 // hard to distinguish from padding, which is always sent on the first
1609 // stream).
1610 if (header.payloadType != kSendRtxPayloadType &&
1611 header.ssrc != first_media_ssrc_ &&
1612 header.extension.transportSequenceNumber % 17 == 0) {
1613 dropped_seq_[header.ssrc].insert(header.sequenceNumber);
1614 drop_packet = true;
1615 }
1616
1617 size_t payload_length =
1618 length - (header.headerLength + header.paddingLength);
1619 if (payload_length == 0) {
1620 padding_observed_ = true;
1621 } else if (header.payloadType == kSendRtxPayloadType) {
1622 uint16_t original_sequence_number =
1623 ByteReader<uint16_t>::ReadBigEndian(&data[header.headerLength]);
1624 uint32_t original_ssrc =
1625 rtx_to_media_ssrcs_.find(header.ssrc)->second;
1626 std::set<uint16_t>* seq_no_map = &dropped_seq_[original_ssrc];
1627 auto it = seq_no_map->find(original_sequence_number);
1628 if (it != seq_no_map->end()) {
1629 retransmit_observed_ = true;
1630 seq_no_map->erase(it);
1631 } else {
1632 rtx_padding_observed_ = true;
1633 }
1634 } else {
1635 streams_observed_.insert(header.ssrc);
1636 }
1637
1638 if (IsDone())
Peter Boström5811a392015-12-10 13:02:50 +01001639 done_.Set();
sprang861c55e2015-10-16 10:01:21 -07001640
1641 if (drop_packet)
1642 return true;
1643 }
sprang867fb522015-08-03 04:38:41 -07001644 }
sprang861c55e2015-10-16 10:01:21 -07001645
stefan1d8a5062015-10-02 03:39:33 -07001646 return test::DirectTransport::SendRtp(data, length, options);
sprang867fb522015-08-03 04:38:41 -07001647 }
1648
Erik Språng8d629712015-08-04 16:24:03 +02001649 bool IsDone() {
sprang861c55e2015-10-16 10:01:21 -07001650 bool observed_types_ok =
1651 streams_observed_.size() == MultiStreamTest::kNumStreams &&
1652 padding_observed_ && retransmit_observed_ && rtx_padding_observed_;
1653 if (!observed_types_ok)
1654 return false;
1655 // We should not have any gaps in the sequence number range.
1656 size_t seqno_range =
1657 *received_packed_ids_.rbegin() - *received_packed_ids_.begin() + 1;
1658 return seqno_range == received_packed_ids_.size();
Erik Språng8d629712015-08-04 16:24:03 +02001659 }
1660
Peter Boström5811a392015-12-10 13:02:50 +01001661 bool Wait() {
sprang861c55e2015-10-16 10:01:21 -07001662 {
1663 // Can't be sure until this point that rtx_to_media_ssrcs_ etc have
1664 // been initialized and are OK to read.
1665 rtc::CritScope cs(&lock_);
1666 started_ = true;
1667 }
Peter Boström5811a392015-12-10 13:02:50 +01001668 return done_.Wait(kDefaultTimeoutMs);
sprang861c55e2015-10-16 10:01:21 -07001669 }
sprang867fb522015-08-03 04:38:41 -07001670
sprang861c55e2015-10-16 10:01:21 -07001671 rtc::CriticalSection lock_;
Peter Boström5811a392015-12-10 13:02:50 +01001672 rtc::Event done_;
kwiberg27f982b2016-03-01 11:52:33 -08001673 std::unique_ptr<RtpHeaderParser> parser_;
sprang861c55e2015-10-16 10:01:21 -07001674 SequenceNumberUnwrapper unwrapper_;
1675 std::set<int64_t> received_packed_ids_;
sprang867fb522015-08-03 04:38:41 -07001676 std::set<uint32_t> streams_observed_;
sprang861c55e2015-10-16 10:01:21 -07001677 std::map<uint32_t, std::set<uint16_t>> dropped_seq_;
1678 const uint32_t& first_media_ssrc_;
1679 const std::map<uint32_t, uint32_t>& rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001680 bool padding_observed_;
1681 bool rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001682 bool retransmit_observed_;
1683 bool started_;
sprang867fb522015-08-03 04:38:41 -07001684 };
1685
1686 class TransportSequenceNumberTester : public MultiStreamTest {
1687 public:
sprang861c55e2015-10-16 10:01:21 -07001688 TransportSequenceNumberTester()
1689 : first_media_ssrc_(0), observer_(nullptr) {}
sprang867fb522015-08-03 04:38:41 -07001690 virtual ~TransportSequenceNumberTester() {}
1691
1692 protected:
1693 void Wait() override {
Peter Boström74f6e9e2016-04-04 17:56:10 +02001694 RTC_DCHECK(observer_);
Peter Boström5811a392015-12-10 13:02:50 +01001695 EXPECT_TRUE(observer_->Wait());
sprang867fb522015-08-03 04:38:41 -07001696 }
1697
1698 void UpdateSendConfig(
1699 size_t stream_index,
1700 VideoSendStream::Config* send_config,
1701 VideoEncoderConfig* encoder_config,
1702 test::FrameGeneratorCapturer** frame_generator) override {
1703 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001704 send_config->rtp.extensions.push_back(RtpExtension(
1705 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sprang867fb522015-08-03 04:38:41 -07001706
1707 // Force some padding to be sent.
1708 const int kPaddingBitrateBps = 50000;
perkjfa10b552016-10-02 23:45:26 -07001709 encoder_config->max_bitrate_bps = 1000000;
sprang867fb522015-08-03 04:38:41 -07001710 encoder_config->min_transmit_bitrate_bps =
perkjfa10b552016-10-02 23:45:26 -07001711 encoder_config->max_bitrate_bps + kPaddingBitrateBps;
sprang867fb522015-08-03 04:38:41 -07001712
1713 // Configure RTX for redundant payload padding.
1714 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang861c55e2015-10-16 10:01:21 -07001715 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[stream_index]);
sprang867fb522015-08-03 04:38:41 -07001716 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
sprang861c55e2015-10-16 10:01:21 -07001717 rtx_to_media_ssrcs_[kSendRtxSsrcs[stream_index]] =
1718 send_config->rtp.ssrcs[0];
1719
1720 if (stream_index == 0)
1721 first_media_ssrc_ = send_config->rtp.ssrcs[0];
sprang867fb522015-08-03 04:38:41 -07001722 }
1723
1724 void UpdateReceiveConfig(
1725 size_t stream_index,
1726 VideoReceiveStream::Config* receive_config) override {
sprang861c55e2015-10-16 10:01:21 -07001727 receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang867fb522015-08-03 04:38:41 -07001728 receive_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001729 receive_config->rtp.extensions.push_back(RtpExtension(
1730 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sakal55d932b2016-09-30 06:19:08 -07001731 receive_config->renderer = &fake_renderer_;
sprang867fb522015-08-03 04:38:41 -07001732 }
1733
stefanf116bd02015-10-27 08:29:42 -07001734 test::DirectTransport* CreateSendTransport(Call* sender_call) override {
1735 observer_ = new RtpExtensionHeaderObserver(sender_call, first_media_ssrc_,
sprang861c55e2015-10-16 10:01:21 -07001736 rtx_to_media_ssrcs_);
sprang867fb522015-08-03 04:38:41 -07001737 return observer_;
1738 }
1739
1740 private:
sakal55d932b2016-09-30 06:19:08 -07001741 test::FakeVideoRenderer fake_renderer_;
sprang861c55e2015-10-16 10:01:21 -07001742 uint32_t first_media_ssrc_;
1743 std::map<uint32_t, uint32_t> rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001744 RtpExtensionHeaderObserver* observer_;
1745 } tester;
1746
1747 tester.RunTest();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001748}
1749
Stefan Holmer04cb7632016-01-14 20:34:30 +01001750class TransportFeedbackTester : public test::EndToEndTest {
1751 public:
1752 explicit TransportFeedbackTester(bool feedback_enabled,
1753 size_t num_video_streams,
1754 size_t num_audio_streams)
1755 : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
1756 feedback_enabled_(feedback_enabled),
1757 num_video_streams_(num_video_streams),
sprangcd349d92016-07-13 09:11:28 -07001758 num_audio_streams_(num_audio_streams),
1759 receiver_call_(nullptr) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001760 // Only one stream of each supported for now.
1761 EXPECT_LE(num_video_streams, 1u);
1762 EXPECT_LE(num_audio_streams, 1u);
1763 }
1764
1765 protected:
1766 Action OnSendRtcp(const uint8_t* data, size_t length) override {
1767 EXPECT_FALSE(HasTransportFeedback(data, length));
1768 return SEND_PACKET;
1769 }
1770
1771 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
1772 if (HasTransportFeedback(data, length))
1773 observation_complete_.Set();
1774 return SEND_PACKET;
1775 }
1776
1777 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
danilchap3dc929e2016-11-02 08:21:59 -07001778 test::RtcpPacketParser parser;
1779 EXPECT_TRUE(parser.Parse(data, length));
1780 return parser.transport_feedback()->num_packets() > 0;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001781 }
1782
1783 void PerformTest() override {
1784 const int64_t kDisabledFeedbackTimeoutMs = 5000;
1785 EXPECT_EQ(feedback_enabled_,
1786 observation_complete_.Wait(feedback_enabled_
1787 ? test::CallTest::kDefaultTimeoutMs
1788 : kDisabledFeedbackTimeoutMs));
1789 }
1790
1791 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1792 receiver_call_ = receiver_call;
1793 }
1794
1795 size_t GetNumVideoStreams() const override { return num_video_streams_; }
1796 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
1797
1798 void ModifyVideoConfigs(
1799 VideoSendStream::Config* send_config,
1800 std::vector<VideoReceiveStream::Config>* receive_configs,
1801 VideoEncoderConfig* encoder_config) override {
1802 send_config->rtp.extensions.clear();
1803 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001804 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001805 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1806 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
1807 }
1808
1809 void ModifyAudioConfigs(
1810 AudioSendStream::Config* send_config,
1811 std::vector<AudioReceiveStream::Config>* receive_configs) override {
1812 send_config->rtp.extensions.clear();
1813 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001814 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001815 (*receive_configs)[0].rtp.extensions.clear();
1816 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1817 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001818 }
1819
1820 private:
Erik Språng6b8d3552015-09-24 15:06:57 +02001821 static const int kExtensionId = 5;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001822 const bool feedback_enabled_;
1823 const size_t num_video_streams_;
1824 const size_t num_audio_streams_;
1825 Call* receiver_call_;
1826};
Erik Språng6b8d3552015-09-24 15:06:57 +02001827
philipel266f0a42016-11-28 08:49:07 -08001828TEST_P(EndToEndTest, VideoReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001829 TransportFeedbackTester test(true, 1, 0);
1830 RunBaseTest(&test);
Erik Språng6b8d3552015-09-24 15:06:57 +02001831}
stefan43edf0f2015-11-20 18:05:48 -08001832
philipel266f0a42016-11-28 08:49:07 -08001833TEST_P(EndToEndTest, VideoTransportFeedbackNotConfigured) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001834 TransportFeedbackTester test(false, 1, 0);
1835 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001836}
1837
philipel266f0a42016-11-28 08:49:07 -08001838TEST_P(EndToEndTest, AudioReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001839 TransportFeedbackTester test(true, 0, 1);
1840 RunBaseTest(&test);
1841}
1842
philipel266f0a42016-11-28 08:49:07 -08001843TEST_P(EndToEndTest, AudioTransportFeedbackNotConfigured) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001844 TransportFeedbackTester test(false, 0, 1);
1845 RunBaseTest(&test);
1846}
1847
philipel266f0a42016-11-28 08:49:07 -08001848TEST_P(EndToEndTest, AudioVideoReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001849 TransportFeedbackTester test(true, 1, 1);
1850 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001851}
1852
philipel266f0a42016-11-28 08:49:07 -08001853TEST_P(EndToEndTest, ObserversEncodedFrames) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001854 class EncodedFrameTestObserver : public EncodedFrameObserver {
1855 public:
1856 EncodedFrameTestObserver()
Peter Boström5811a392015-12-10 13:02:50 +01001857 : length_(0), frame_type_(kEmptyFrame), called_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001858 virtual ~EncodedFrameTestObserver() {}
1859
1860 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
1861 frame_type_ = encoded_frame.frame_type_;
1862 length_ = encoded_frame.length_;
1863 buffer_.reset(new uint8_t[length_]);
1864 memcpy(buffer_.get(), encoded_frame.data_, length_);
Peter Boström5811a392015-12-10 13:02:50 +01001865 called_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001866 }
1867
Peter Boström5811a392015-12-10 13:02:50 +01001868 bool Wait() { return called_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001869
1870 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
1871 ASSERT_EQ(length_, observer.length_)
1872 << "Observed frames are of different lengths.";
1873 EXPECT_EQ(frame_type_, observer.frame_type_)
1874 << "Observed frames have different frame types.";
1875 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
1876 << "Observed encoded frames have different content.";
1877 }
1878
1879 private:
kwiberg27f982b2016-03-01 11:52:33 -08001880 std::unique_ptr<uint8_t[]> buffer_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001881 size_t length_;
1882 FrameType frame_type_;
Peter Boström5811a392015-12-10 13:02:50 +01001883 rtc::Event called_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001884 };
1885
1886 EncodedFrameTestObserver post_encode_observer;
1887 EncodedFrameTestObserver pre_decode_observer;
1888
skvlad11a9cbf2016-10-07 11:53:05 -07001889 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -07001890
stefanf116bd02015-10-27 08:29:42 -07001891 test::DirectTransport sender_transport(sender_call_.get());
1892 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001893 sender_transport.SetReceiver(receiver_call_->Receiver());
1894 receiver_transport.SetReceiver(sender_call_->Receiver());
1895
brandtr841de6a2016-11-15 07:10:52 -08001896 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001897 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -08001898 video_send_config_.post_encode_callback = &post_encode_observer;
1899 video_receive_configs_[0].pre_decode_callback = &pre_decode_observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001900
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001901 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001902 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001903
kwiberg27f982b2016-03-01 11:52:33 -08001904 std::unique_ptr<test::FrameGenerator> frame_generator(
perkjfa10b552016-10-02 23:45:26 -07001905 test::FrameGenerator::CreateChromaGenerator(kDefaultWidth,
1906 kDefaultHeight));
perkja49cbd32016-09-16 07:53:41 -07001907 test::FrameForwarder forwarder;
perkj803d97f2016-11-01 11:45:46 -07001908 video_send_stream_->SetSource(
1909 &forwarder, VideoSendStream::DegradationPreference::kBalanced);
perkja49cbd32016-09-16 07:53:41 -07001910 forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001911
Peter Boström5811a392015-12-10 13:02:50 +01001912 EXPECT_TRUE(post_encode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001913 << "Timed out while waiting for send-side encoded-frame callback.";
1914
Peter Boström5811a392015-12-10 13:02:50 +01001915 EXPECT_TRUE(pre_decode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001916 << "Timed out while waiting for pre-decode encoded-frame callback.";
1917
1918 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
1919
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001920 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001921
1922 sender_transport.StopSending();
1923 receiver_transport.StopSending();
1924
1925 DestroyStreams();
1926}
1927
philipel266f0a42016-11-28 08:49:07 -08001928TEST_P(EndToEndTest, ReceiveStreamSendsRemb) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001929 class RembObserver : public test::EndToEndTest {
1930 public:
1931 RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
1932
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001933 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
danilchap3dc929e2016-11-02 08:21:59 -07001934 test::RtcpPacketParser parser;
1935 EXPECT_TRUE(parser.Parse(packet, length));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001936
danilchap3dc929e2016-11-02 08:21:59 -07001937 if (parser.remb()->num_packets() > 0) {
1938 EXPECT_EQ(kReceiverLocalVideoSsrc, parser.remb()->sender_ssrc());
1939 EXPECT_LT(0U, parser.remb()->bitrate_bps());
1940 EXPECT_EQ(1U, parser.remb()->ssrcs().size());
1941 EXPECT_EQ(kVideoSendSsrcs[0], parser.remb()->ssrcs()[0]);
Peter Boström5811a392015-12-10 13:02:50 +01001942 observation_complete_.Set();
danilchap3dc929e2016-11-02 08:21:59 -07001943 }
1944
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001945 return SEND_PACKET;
1946 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001947 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001948 EXPECT_TRUE(Wait()) << "Timed out while waiting for a "
1949 "receiver RTCP REMB packet to be "
1950 "sent.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001951 }
1952 } test;
1953
stefane74eef12016-01-08 06:47:13 -08001954 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001955}
1956
philipel266f0a42016-11-28 08:49:07 -08001957TEST_P(EndToEndTest, VerifyBandwidthStats) {
stefanf116bd02015-10-27 08:29:42 -07001958 class RtcpObserver : public test::EndToEndTest {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001959 public:
1960 RtcpObserver()
1961 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001962 sender_call_(nullptr),
1963 receiver_call_(nullptr),
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001964 has_seen_pacer_delay_(false) {}
1965
stefanf116bd02015-10-27 08:29:42 -07001966 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001967 Call::Stats sender_stats = sender_call_->GetStats();
1968 Call::Stats receiver_stats = receiver_call_->GetStats();
1969 if (!has_seen_pacer_delay_)
1970 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
1971 if (sender_stats.send_bandwidth_bps > 0 &&
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001972 receiver_stats.recv_bandwidth_bps > 0 && has_seen_pacer_delay_) {
Peter Boström5811a392015-12-10 13:02:50 +01001973 observation_complete_.Set();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001974 }
stefanf116bd02015-10-27 08:29:42 -07001975 return SEND_PACKET;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001976 }
1977
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001978 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001979 sender_call_ = sender_call;
1980 receiver_call_ = receiver_call;
1981 }
1982
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001983 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001984 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
1985 "non-zero bandwidth stats.";
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001986 }
1987
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001988 private:
1989 Call* sender_call_;
1990 Call* receiver_call_;
1991 bool has_seen_pacer_delay_;
1992 } test;
1993
stefane74eef12016-01-08 06:47:13 -08001994 RunBaseTest(&test);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001995}
1996
stefan32f81542016-01-20 07:13:58 -08001997
1998// Verifies that it's possible to limit the send BWE by sending a REMB.
1999// This is verified by allowing the send BWE to ramp-up to >1000 kbps,
2000// then have the test generate a REMB of 500 kbps and verify that the send BWE
2001// is reduced to exactly 500 kbps. Then a REMB of 1000 kbps is generated and the
2002// test verifies that the send BWE ramps back up to exactly 1000 kbps.
philipel266f0a42016-11-28 08:49:07 -08002003TEST_P(EndToEndTest, RembWithSendSideBwe) {
stefan32f81542016-01-20 07:13:58 -08002004 class BweObserver : public test::EndToEndTest {
2005 public:
2006 BweObserver()
2007 : EndToEndTest(kDefaultTimeoutMs),
2008 sender_call_(nullptr),
2009 clock_(Clock::GetRealTimeClock()),
2010 sender_ssrc_(0),
2011 remb_bitrate_bps_(1000000),
2012 receive_transport_(nullptr),
2013 event_(false, false),
2014 poller_thread_(&BitrateStatsPollingThread,
2015 this,
2016 "BitrateStatsPollingThread"),
Erik Språng737336d2016-07-29 12:59:36 +02002017 state_(kWaitForFirstRampUp),
2018 retransmission_rate_limiter_(clock_, 1000) {}
stefan32f81542016-01-20 07:13:58 -08002019
2020 ~BweObserver() {}
2021
nisseef8b61e2016-04-29 06:09:15 -07002022 test::PacketTransport* CreateReceiveTransport() override {
stefan32f81542016-01-20 07:13:58 -08002023 receive_transport_ = new test::PacketTransport(
2024 nullptr, this, test::PacketTransport::kReceiver,
2025 FakeNetworkPipe::Config());
2026 return receive_transport_;
2027 }
2028
2029 Call::Config GetSenderCallConfig() override {
skvlad11a9cbf2016-10-07 11:53:05 -07002030 Call::Config config(&event_log_);
stefan32f81542016-01-20 07:13:58 -08002031 // Set a high start bitrate to reduce the test completion time.
2032 config.bitrate_config.start_bitrate_bps = remb_bitrate_bps_;
2033 return config;
2034 }
2035
2036 void ModifyVideoConfigs(
2037 VideoSendStream::Config* send_config,
2038 std::vector<VideoReceiveStream::Config>* receive_configs,
2039 VideoEncoderConfig* encoder_config) override {
2040 ASSERT_EQ(1u, send_config->rtp.ssrcs.size());
2041 send_config->rtp.extensions.clear();
2042 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07002043 RtpExtension(RtpExtension::kTransportSequenceNumberUri,
stefan32f81542016-01-20 07:13:58 -08002044 test::kTransportSequenceNumberExtensionId));
2045 sender_ssrc_ = send_config->rtp.ssrcs[0];
2046
perkjfa10b552016-10-02 23:45:26 -07002047 encoder_config->max_bitrate_bps = 2000000;
stefan32f81542016-01-20 07:13:58 -08002048
2049 ASSERT_EQ(1u, receive_configs->size());
2050 (*receive_configs)[0].rtp.remb = false;
2051 (*receive_configs)[0].rtp.transport_cc = true;
2052 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
2053 RtpRtcp::Configuration config;
2054 config.receiver_only = true;
2055 config.clock = clock_;
2056 config.outgoing_transport = receive_transport_;
Erik Språng737336d2016-07-29 12:59:36 +02002057 config.retransmission_rate_limiter = &retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08002058 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
2059 rtp_rtcp_->SetRemoteSSRC((*receive_configs)[0].rtp.remote_ssrc);
2060 rtp_rtcp_->SetSSRC((*receive_configs)[0].rtp.local_ssrc);
2061 rtp_rtcp_->SetREMBStatus(true);
2062 rtp_rtcp_->SetSendingStatus(true);
2063 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
2064 }
2065
2066 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2067 sender_call_ = sender_call;
2068 }
2069
2070 static bool BitrateStatsPollingThread(void* obj) {
2071 return static_cast<BweObserver*>(obj)->PollStats();
2072 }
2073
2074 bool PollStats() {
2075 if (sender_call_) {
2076 Call::Stats stats = sender_call_->GetStats();
2077 switch (state_) {
2078 case kWaitForFirstRampUp:
2079 if (stats.send_bandwidth_bps >= remb_bitrate_bps_) {
2080 state_ = kWaitForRemb;
2081 remb_bitrate_bps_ /= 2;
2082 rtp_rtcp_->SetREMBData(
2083 remb_bitrate_bps_,
2084 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
2085 rtp_rtcp_->SendRTCP(kRtcpRr);
2086 }
2087 break;
2088
2089 case kWaitForRemb:
2090 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
2091 state_ = kWaitForSecondRampUp;
2092 remb_bitrate_bps_ *= 2;
2093 rtp_rtcp_->SetREMBData(
2094 remb_bitrate_bps_,
2095 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
2096 rtp_rtcp_->SendRTCP(kRtcpRr);
2097 }
2098 break;
2099
2100 case kWaitForSecondRampUp:
2101 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
2102 observation_complete_.Set();
2103 }
2104 break;
2105 }
2106 }
2107
2108 return !event_.Wait(1000);
2109 }
2110
2111 void PerformTest() override {
2112 poller_thread_.Start();
2113 EXPECT_TRUE(Wait())
2114 << "Timed out while waiting for bitrate to change according to REMB.";
2115 poller_thread_.Stop();
2116 }
2117
2118 private:
2119 enum TestState { kWaitForFirstRampUp, kWaitForRemb, kWaitForSecondRampUp };
2120
2121 Call* sender_call_;
2122 Clock* const clock_;
2123 uint32_t sender_ssrc_;
2124 int remb_bitrate_bps_;
kwiberg27f982b2016-03-01 11:52:33 -08002125 std::unique_ptr<RtpRtcp> rtp_rtcp_;
stefan32f81542016-01-20 07:13:58 -08002126 test::PacketTransport* receive_transport_;
2127 rtc::Event event_;
2128 rtc::PlatformThread poller_thread_;
2129 TestState state_;
Erik Språng737336d2016-07-29 12:59:36 +02002130 RateLimiter retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08002131 } test;
2132
2133 RunBaseTest(&test);
2134}
2135
philipel266f0a42016-11-28 08:49:07 -08002136TEST_P(EndToEndTest, VerifyNackStats) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002137 static const int kPacketNumberToDrop = 200;
2138 class NackObserver : public test::EndToEndTest {
2139 public:
2140 NackObserver()
2141 : EndToEndTest(kLongTimeoutMs),
2142 sent_rtp_packets_(0),
2143 dropped_rtp_packet_(0),
2144 dropped_rtp_packet_requested_(false),
2145 send_stream_(nullptr),
2146 start_runtime_ms_(-1) {}
2147
2148 private:
2149 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002150 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002151 if (++sent_rtp_packets_ == kPacketNumberToDrop) {
kwiberg27f982b2016-03-01 11:52:33 -08002152 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
Åsa Persson352b2d72015-04-15 18:00:40 +02002153 RTPHeader header;
2154 EXPECT_TRUE(parser->Parse(packet, length, &header));
2155 dropped_rtp_packet_ = header.sequenceNumber;
2156 return DROP_PACKET;
2157 }
2158 VerifyStats();
2159 return SEND_PACKET;
2160 }
2161
2162 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002163 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002164 test::RtcpPacketParser rtcp_parser;
2165 rtcp_parser.Parse(packet, length);
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02002166 const std::vector<uint16_t>& nacks = rtcp_parser.nack()->packet_ids();
Åsa Persson352b2d72015-04-15 18:00:40 +02002167 if (!nacks.empty() && std::find(
2168 nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) {
2169 dropped_rtp_packet_requested_ = true;
2170 }
2171 return SEND_PACKET;
2172 }
2173
stefan608213e2015-11-01 14:56:10 -08002174 void VerifyStats() EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002175 if (!dropped_rtp_packet_requested_)
2176 return;
2177 int send_stream_nack_packets = 0;
2178 int receive_stream_nack_packets = 0;
2179 VideoSendStream::Stats stats = send_stream_->GetStats();
2180 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
2181 stats.substreams.begin(); it != stats.substreams.end(); ++it) {
2182 const VideoSendStream::StreamStats& stream_stats = it->second;
2183 send_stream_nack_packets +=
2184 stream_stats.rtcp_packet_type_counts.nack_packets;
2185 }
2186 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2187 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2188 receive_stream_nack_packets +=
2189 stats.rtcp_packet_type_counts.nack_packets;
2190 }
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002191 if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002192 // NACK packet sent on receive stream and received on sent stream.
2193 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002194 observation_complete_.Set();
Åsa Persson352b2d72015-04-15 18:00:40 +02002195 }
2196 }
2197
2198 bool MinMetricRunTimePassed() {
2199 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2200 if (start_runtime_ms_ == -1) {
2201 start_runtime_ms_ = now;
2202 return false;
2203 }
2204 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2205 return elapsed_sec > metrics::kMinRunTimeInSeconds;
2206 }
2207
stefanff483612015-12-21 03:14:00 -08002208 void ModifyVideoConfigs(
2209 VideoSendStream::Config* send_config,
2210 std::vector<VideoReceiveStream::Config>* receive_configs,
2211 VideoEncoderConfig* encoder_config) override {
Åsa Persson352b2d72015-04-15 18:00:40 +02002212 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2213 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sakal55d932b2016-09-30 06:19:08 -07002214 (*receive_configs)[0].renderer = &fake_renderer_;
Åsa Persson352b2d72015-04-15 18:00:40 +02002215 }
2216
stefanff483612015-12-21 03:14:00 -08002217 void OnVideoStreamsCreated(
Åsa Persson352b2d72015-04-15 18:00:40 +02002218 VideoSendStream* send_stream,
2219 const std::vector<VideoReceiveStream*>& receive_streams) override {
2220 send_stream_ = send_stream;
2221 receive_streams_ = receive_streams;
2222 }
2223
2224 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002225 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson352b2d72015-04-15 18:00:40 +02002226 }
2227
sakal55d932b2016-09-30 06:19:08 -07002228 test::FakeVideoRenderer fake_renderer_;
stefan608213e2015-11-01 14:56:10 -08002229 rtc::CriticalSection crit_;
Åsa Persson352b2d72015-04-15 18:00:40 +02002230 uint64_t sent_rtp_packets_;
stefan608213e2015-11-01 14:56:10 -08002231 uint16_t dropped_rtp_packet_ GUARDED_BY(&crit_);
2232 bool dropped_rtp_packet_requested_ GUARDED_BY(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002233 std::vector<VideoReceiveStream*> receive_streams_;
2234 VideoSendStream* send_stream_;
2235 int64_t start_runtime_ms_;
2236 } test;
2237
asapersson01d70a32016-05-20 06:29:46 -07002238 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002239 RunBaseTest(&test);
Åsa Persson352b2d72015-04-15 18:00:40 +02002240
asapersson01d70a32016-05-20 06:29:46 -07002241 EXPECT_EQ(
2242 1, metrics::NumSamples("WebRTC.Video.UniqueNackRequestsSentInPercent"));
2243 EXPECT_EQ(1, metrics::NumSamples(
2244 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
2245 EXPECT_GT(metrics::MinSample("WebRTC.Video.NackPacketsSentPerMinute"), 0);
Åsa Persson352b2d72015-04-15 18:00:40 +02002246}
2247
sprangb4a1ae52015-12-03 08:10:08 -08002248void EndToEndTest::VerifyHistogramStats(bool use_rtx,
2249 bool use_red,
2250 bool screenshare) {
tommi2e82f382016-06-21 00:26:43 -07002251 class StatsObserver : public test::EndToEndTest,
2252 public rtc::VideoSinkInterface<VideoFrame> {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002253 public:
sprangb4a1ae52015-12-03 08:10:08 -08002254 StatsObserver(bool use_rtx, bool use_red, bool screenshare)
Åsa Persson3c391cb2015-04-27 10:09:49 +02002255 : EndToEndTest(kLongTimeoutMs),
2256 use_rtx_(use_rtx),
2257 use_red_(use_red),
sprangb4a1ae52015-12-03 08:10:08 -08002258 screenshare_(screenshare),
Peter Boström39593972016-02-15 11:27:15 +01002259 // This test uses NACK, so to send FEC we can't use a fake encoder.
magjed509e4fe2016-11-18 01:34:11 -08002260 vp8_encoder_(use_red ? VP8Encoder::Create() : nullptr),
Åsa Persson3c391cb2015-04-27 10:09:49 +02002261 sender_call_(nullptr),
2262 receiver_call_(nullptr),
asapersson1394c7b2016-10-18 11:50:50 -07002263 start_runtime_ms_(-1),
2264 num_frames_received_(0) {}
Åsa Persson3c391cb2015-04-27 10:09:49 +02002265
2266 private:
asapersson1394c7b2016-10-18 11:50:50 -07002267 void OnFrame(const VideoFrame& video_frame) override {
2268 // The RTT is needed to estimate |ntp_time_ms| which is used by
2269 // end-to-end delay stats. Therefore, start counting received frames once
2270 // |ntp_time_ms| is valid.
2271 if (video_frame.ntp_time_ms() > 0 &&
2272 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() >=
2273 video_frame.ntp_time_ms()) {
2274 rtc::CritScope lock(&crit_);
2275 ++num_frames_received_;
2276 }
2277 }
tommi2e82f382016-06-21 00:26:43 -07002278
Åsa Persson3c391cb2015-04-27 10:09:49 +02002279 Action OnSendRtp(const uint8_t* packet, size_t length) override {
asapersson1394c7b2016-10-18 11:50:50 -07002280 if (MinMetricRunTimePassed() && MinNumberOfFramesReceived())
Peter Boström5811a392015-12-10 13:02:50 +01002281 observation_complete_.Set();
Åsa Persson3c391cb2015-04-27 10:09:49 +02002282
stefanf116bd02015-10-27 08:29:42 -07002283 return SEND_PACKET;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002284 }
2285
2286 bool MinMetricRunTimePassed() {
2287 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2288 if (start_runtime_ms_ == -1) {
2289 start_runtime_ms_ = now;
2290 return false;
2291 }
2292 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2293 return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
2294 }
2295
asapersson1394c7b2016-10-18 11:50:50 -07002296 bool MinNumberOfFramesReceived() const {
2297 const int kMinRequiredHistogramSamples = 200;
2298 rtc::CritScope lock(&crit_);
2299 return num_frames_received_ > kMinRequiredHistogramSamples;
2300 }
2301
stefanff483612015-12-21 03:14:00 -08002302 void ModifyVideoConfigs(
2303 VideoSendStream::Config* send_config,
2304 std::vector<VideoReceiveStream::Config>* receive_configs,
2305 VideoEncoderConfig* encoder_config) override {
stefana23fc622016-07-28 07:56:38 -07002306 static const int kExtensionId = 8;
2307 send_config->rtp.extensions.push_back(RtpExtension(
2308 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
2309 (*receive_configs)[0].rtp.extensions.push_back(RtpExtension(
2310 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002311 // NACK
2312 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2313 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
tommi2e82f382016-06-21 00:26:43 -07002314 (*receive_configs)[0].renderer = this;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002315 // FEC
2316 if (use_red_) {
brandtrb5f2c3f2016-10-04 23:28:39 -07002317 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
2318 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
Peter Boström39593972016-02-15 11:27:15 +01002319 send_config->encoder_settings.encoder = vp8_encoder_.get();
2320 send_config->encoder_settings.payload_name = "VP8";
2321 (*receive_configs)[0].decoders[0].payload_name = "VP8";
brandtrb5f2c3f2016-10-04 23:28:39 -07002322 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
2323 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type =
2324 kUlpfecPayloadType;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002325 }
2326 // RTX
2327 if (use_rtx_) {
2328 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
2329 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002330 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002331 kSendRtxSsrcs[0];
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002332 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002333 kSendRtxPayloadType;
2334 }
asapersson1490f7a2016-09-23 02:09:46 -07002335 // RTT needed for RemoteNtpTimeEstimator for the receive stream.
2336 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = true;
sprangb4a1ae52015-12-03 08:10:08 -08002337 encoder_config->content_type =
2338 screenshare_ ? VideoEncoderConfig::ContentType::kScreen
2339 : VideoEncoderConfig::ContentType::kRealtimeVideo;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002340 }
2341
2342 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2343 sender_call_ = sender_call;
2344 receiver_call_ = receiver_call;
2345 }
2346
Åsa Persson3c391cb2015-04-27 10:09:49 +02002347 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002348 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson3c391cb2015-04-27 10:09:49 +02002349 }
2350
asapersson1394c7b2016-10-18 11:50:50 -07002351 rtc::CriticalSection crit_;
sprangb4a1ae52015-12-03 08:10:08 -08002352 const bool use_rtx_;
2353 const bool use_red_;
2354 const bool screenshare_;
kwiberg27f982b2016-03-01 11:52:33 -08002355 const std::unique_ptr<VideoEncoder> vp8_encoder_;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002356 Call* sender_call_;
2357 Call* receiver_call_;
2358 int64_t start_runtime_ms_;
asapersson1394c7b2016-10-18 11:50:50 -07002359 int num_frames_received_ GUARDED_BY(&crit_);
sprangb4a1ae52015-12-03 08:10:08 -08002360 } test(use_rtx, use_red, screenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002361
asapersson01d70a32016-05-20 06:29:46 -07002362 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002363 RunBaseTest(&test);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002364
stefan91d92602015-11-11 10:13:02 -08002365 // Delete the call for Call stats to be reported.
stefan18adf0a2015-11-17 06:24:56 -08002366 sender_call_.reset();
stefan91d92602015-11-11 10:13:02 -08002367 receiver_call_.reset();
2368
sprangb4a1ae52015-12-03 08:10:08 -08002369 std::string video_prefix =
2370 screenshare ? "WebRTC.Video.Screenshare." : "WebRTC.Video.";
2371
Åsa Persson3c391cb2015-04-27 10:09:49 +02002372 // Verify that stats have been updated once.
asapersson4374a092016-07-27 00:39:09 -07002373 EXPECT_EQ(2, metrics::NumSamples("WebRTC.Call.LifetimeInSeconds"));
asapersson01d70a32016-05-20 06:29:46 -07002374 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
2375 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.RtcpBitrateReceivedInBps"));
2376 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.BitrateReceivedInKbps"));
2377 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.EstimatedSendBitrateInKbps"));
2378 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.PacerBitrateInKbps"));
2379
asapersson4374a092016-07-27 00:39:09 -07002380 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
2381 EXPECT_EQ(1,
2382 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
2383
asapersson01d70a32016-05-20 06:29:46 -07002384 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
stefan91d92602015-11-11 10:13:02 -08002385 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002386 metrics::NumSamples(video_prefix + "NackPacketsReceivedPerMinute"));
2387 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
asaperssond89920b2015-07-22 06:52:00 -07002388 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002389 metrics::NumSamples(video_prefix + "FirPacketsReceivedPerMinute"));
2390 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
sprangb4a1ae52015-12-03 08:10:08 -08002391 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002392 metrics::NumSamples(video_prefix + "PliPacketsReceivedPerMinute"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002393
asapersson01d70a32016-05-20 06:29:46 -07002394 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "KeyFramesSentInPermille"));
2395 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
2396
2397 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentPacketsLostInPercent"));
2398 EXPECT_EQ(1,
2399 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
2400
2401 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputWidthInPixels"));
2402 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputHeightInPixels"));
2403 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentWidthInPixels"));
2404 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentHeightInPixels"));
2405 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
2406 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
2407
perkjfa10b552016-10-02 23:45:26 -07002408 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputWidthInPixels",
2409 kDefaultWidth));
2410 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputHeightInPixels",
2411 kDefaultHeight));
2412 EXPECT_EQ(
2413 1, metrics::NumEvents(video_prefix + "SentWidthInPixels", kDefaultWidth));
2414 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "SentHeightInPixels",
2415 kDefaultHeight));
2416 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedWidthInPixels",
2417 kDefaultWidth));
2418 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedHeightInPixels",
2419 kDefaultHeight));
asapersson01d70a32016-05-20 06:29:46 -07002420
2421 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputFramesPerSecond"));
2422 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentFramesPerSecond"));
2423 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
2424 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
2425
2426 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
2427 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
2428 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
2429 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
2430
asapersson1490f7a2016-09-23 02:09:46 -07002431 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.EndToEndDelayInMs"));
asapersson01d70a32016-05-20 06:29:46 -07002432 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
2433
2434 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EncodeTimeInMs"));
2435 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
2436
asapersson66d4b372016-12-19 06:50:53 -08002437 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "NumberOfPauseEvents"));
2438 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PausedTimeInPercent"));
2439
asapersson01d70a32016-05-20 06:29:46 -07002440 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "BitrateSentInKbps"));
2441 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateReceivedInKbps"));
2442 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "MediaBitrateSentInKbps"));
2443 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateReceivedInKbps"));
2444 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PaddingBitrateSentInKbps"));
2445 EXPECT_EQ(1,
2446 metrics::NumSamples("WebRTC.Video.PaddingBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002447 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002448 1, metrics::NumSamples(video_prefix + "RetransmittedBitrateSentInKbps"));
2449 EXPECT_EQ(1, metrics::NumSamples(
2450 "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002451
asapersson01d70a32016-05-20 06:29:46 -07002452 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendDelayInMs"));
2453 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayInMs"));
2454 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayMaxInMs"));
asapersson6f14be82015-11-16 00:40:49 -08002455
Åsa Persson3c391cb2015-04-27 10:09:49 +02002456 int num_rtx_samples = use_rtx ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002457 EXPECT_EQ(num_rtx_samples,
2458 metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2459 EXPECT_EQ(num_rtx_samples,
2460 metrics::NumSamples("WebRTC.Video.RtxBitrateReceivedInKbps"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002461
2462 int num_red_samples = use_red ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002463 EXPECT_EQ(num_red_samples,
2464 metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2465 EXPECT_EQ(num_red_samples,
2466 metrics::NumSamples("WebRTC.Video.FecBitrateReceivedInKbps"));
2467 EXPECT_EQ(num_red_samples,
2468 metrics::NumSamples("WebRTC.Video.ReceivedFecPacketsInPercent"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002469}
2470
philipel266f0a42016-11-28 08:49:07 -08002471TEST_P(EndToEndTest, VerifyHistogramStatsWithRtx) {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002472 const bool kEnabledRtx = true;
2473 const bool kEnabledRed = false;
sprangb4a1ae52015-12-03 08:10:08 -08002474 const bool kScreenshare = false;
2475 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002476}
2477
philipel266f0a42016-11-28 08:49:07 -08002478TEST_P(EndToEndTest, VerifyHistogramStatsWithRed) {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002479 const bool kEnabledRtx = false;
2480 const bool kEnabledRed = true;
sprangb4a1ae52015-12-03 08:10:08 -08002481 const bool kScreenshare = false;
2482 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
2483}
2484
philipel266f0a42016-11-28 08:49:07 -08002485TEST_P(EndToEndTest, VerifyHistogramStatsWithScreenshare) {
sprangb4a1ae52015-12-03 08:10:08 -08002486 const bool kEnabledRtx = false;
2487 const bool kEnabledRed = false;
2488 const bool kScreenshare = true;
2489 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002490}
2491
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002492void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
2493 bool send_single_ssrc_first) {
2494 class SendsSetSsrcs : public test::EndToEndTest {
2495 public:
2496 SendsSetSsrcs(const uint32_t* ssrcs,
2497 size_t num_ssrcs,
2498 bool send_single_ssrc_first)
2499 : EndToEndTest(kDefaultTimeoutMs),
2500 num_ssrcs_(num_ssrcs),
2501 send_single_ssrc_first_(send_single_ssrc_first),
2502 ssrcs_to_observe_(num_ssrcs),
sprang867fb522015-08-03 04:38:41 -07002503 expect_single_ssrc_(send_single_ssrc_first),
2504 send_stream_(nullptr) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002505 for (size_t i = 0; i < num_ssrcs; ++i)
2506 valid_ssrcs_[ssrcs[i]] = true;
2507 }
2508
2509 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002510 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002511 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002512 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002513
2514 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
2515 << "Received unknown SSRC: " << header.ssrc;
2516
2517 if (!valid_ssrcs_[header.ssrc])
Peter Boström5811a392015-12-10 13:02:50 +01002518 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002519
2520 if (!is_observed_[header.ssrc]) {
2521 is_observed_[header.ssrc] = true;
2522 --ssrcs_to_observe_;
2523 if (expect_single_ssrc_) {
2524 expect_single_ssrc_ = false;
Peter Boström5811a392015-12-10 13:02:50 +01002525 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002526 }
2527 }
2528
2529 if (ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002530 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002531
2532 return SEND_PACKET;
2533 }
2534
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002535 size_t GetNumVideoStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002536
perkjfa10b552016-10-02 23:45:26 -07002537 // This test use other VideoStream settings than the the default settings
2538 // implemented in DefaultVideoStreamFactory. Therefore this test implement
2539 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
2540 // in ModifyVideoConfigs.
2541 class VideoStreamFactory
2542 : public VideoEncoderConfig::VideoStreamFactoryInterface {
2543 public:
2544 VideoStreamFactory() {}
2545
2546 private:
2547 std::vector<VideoStream> CreateEncoderStreams(
2548 int width,
2549 int height,
2550 const VideoEncoderConfig& encoder_config) override {
2551 std::vector<VideoStream> streams =
2552 test::CreateVideoStreams(width, height, encoder_config);
2553 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
2554 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
2555 streams[i].min_bitrate_bps = 10000;
2556 streams[i].target_bitrate_bps = 15000;
2557 streams[i].max_bitrate_bps = 20000;
2558 }
2559 return streams;
2560 }
2561 };
2562
stefanff483612015-12-21 03:14:00 -08002563 void ModifyVideoConfigs(
2564 VideoSendStream::Config* send_config,
2565 std::vector<VideoReceiveStream::Config>* receive_configs,
2566 VideoEncoderConfig* encoder_config) override {
perkjfa10b552016-10-02 23:45:26 -07002567 encoder_config->video_stream_factory =
2568 new rtc::RefCountedObject<VideoStreamFactory>();
perkj26091b12016-09-01 01:17:40 -07002569 video_encoder_config_all_streams_ = encoder_config->Copy();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002570 if (send_single_ssrc_first_)
perkjfa10b552016-10-02 23:45:26 -07002571 encoder_config->number_of_streams = 1;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002572 }
2573
stefanff483612015-12-21 03:14:00 -08002574 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002575 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002576 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002577 send_stream_ = send_stream;
2578 }
2579
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002580 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002581 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2582 << (send_single_ssrc_first_ ? "first SSRC."
2583 : "SSRCs.");
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002584
2585 if (send_single_ssrc_first_) {
2586 // Set full simulcast and continue with the rest of the SSRCs.
stefanff483612015-12-21 03:14:00 -08002587 send_stream_->ReconfigureVideoEncoder(
perkj26091b12016-09-01 01:17:40 -07002588 std::move(video_encoder_config_all_streams_));
Peter Boström5811a392015-12-10 13:02:50 +01002589 EXPECT_TRUE(Wait()) << "Timed out while waiting on additional SSRCs.";
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002590 }
2591 }
2592
2593 private:
2594 std::map<uint32_t, bool> valid_ssrcs_;
2595 std::map<uint32_t, bool> is_observed_;
2596
2597 const size_t num_ssrcs_;
2598 const bool send_single_ssrc_first_;
2599
2600 size_t ssrcs_to_observe_;
2601 bool expect_single_ssrc_;
2602
2603 VideoSendStream* send_stream_;
stefanff483612015-12-21 03:14:00 -08002604 VideoEncoderConfig video_encoder_config_all_streams_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002605 } test(kVideoSendSsrcs, num_ssrcs, send_single_ssrc_first);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002606
stefane74eef12016-01-08 06:47:13 -08002607 RunBaseTest(&test);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002608}
2609
philipel266f0a42016-11-28 08:49:07 -08002610TEST_P(EndToEndTest, ReportsSetEncoderRates) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002611 class EncoderRateStatsTest : public test::EndToEndTest,
2612 public test::FakeEncoder {
2613 public:
2614 EncoderRateStatsTest()
2615 : EndToEndTest(kDefaultTimeoutMs),
sprang867fb522015-08-03 04:38:41 -07002616 FakeEncoder(Clock::GetRealTimeClock()),
2617 send_stream_(nullptr),
2618 bitrate_kbps_(0) {}
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002619
stefanff483612015-12-21 03:14:00 -08002620 void OnVideoStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002621 VideoSendStream* send_stream,
2622 const std::vector<VideoReceiveStream*>& receive_streams) override {
2623 send_stream_ = send_stream;
2624 }
2625
stefanff483612015-12-21 03:14:00 -08002626 void ModifyVideoConfigs(
2627 VideoSendStream::Config* send_config,
2628 std::vector<VideoReceiveStream::Config>* receive_configs,
2629 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002630 send_config->encoder_settings.encoder = this;
kwibergaf476c72016-11-28 15:21:39 -08002631 RTC_DCHECK_EQ(1, encoder_config->number_of_streams);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002632 }
2633
Erik Språng08127a92016-11-16 16:41:30 +01002634 int32_t SetRateAllocation(const BitrateAllocation& rate_allocation,
2635 uint32_t framerate) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002636 // Make sure not to trigger on any default zero bitrates.
Erik Språng08127a92016-11-16 16:41:30 +01002637 if (rate_allocation.get_sum_bps() == 0)
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002638 return 0;
Peter Boströmf2f82832015-05-01 13:00:41 +02002639 rtc::CritScope lock(&crit_);
Erik Språng08127a92016-11-16 16:41:30 +01002640 bitrate_kbps_ = rate_allocation.get_sum_kbps();
Peter Boström5811a392015-12-10 13:02:50 +01002641 observation_complete_.Set();
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002642 return 0;
2643 }
2644
2645 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002646 ASSERT_TRUE(Wait())
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002647 << "Timed out while waiting for encoder SetRates() call.";
perkjf5b2e512016-07-05 08:34:04 -07002648 WaitForEncoderTargetBitrateMatchStats();
2649 send_stream_->Stop();
2650 WaitForStatsReportZeroTargetBitrate();
2651 send_stream_->Start();
2652 WaitForEncoderTargetBitrateMatchStats();
2653 }
2654
2655 void WaitForEncoderTargetBitrateMatchStats() {
Peter Boström5811a392015-12-10 13:02:50 +01002656 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002657 VideoSendStream::Stats stats = send_stream_->GetStats();
2658 {
Peter Boströmf2f82832015-05-01 13:00:41 +02002659 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002660 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
2661 static_cast<int>(bitrate_kbps_)) {
2662 return;
2663 }
2664 }
2665 SleepMs(1);
2666 }
2667 FAIL()
2668 << "Timed out waiting for stats reporting the currently set bitrate.";
2669 }
2670
perkjf5b2e512016-07-05 08:34:04 -07002671 void WaitForStatsReportZeroTargetBitrate() {
2672 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
2673 if (send_stream_->GetStats().target_media_bitrate_bps == 0) {
2674 return;
2675 }
2676 SleepMs(1);
2677 }
2678 FAIL() << "Timed out waiting for stats reporting zero bitrate.";
2679 }
2680
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002681 private:
stefanf116bd02015-10-27 08:29:42 -07002682 rtc::CriticalSection crit_;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002683 VideoSendStream* send_stream_;
2684 uint32_t bitrate_kbps_ GUARDED_BY(crit_);
2685 } test;
2686
stefane74eef12016-01-08 06:47:13 -08002687 RunBaseTest(&test);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002688}
2689
philipel266f0a42016-11-28 08:49:07 -08002690TEST_P(EndToEndTest, GetStats) {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002691 static const int kStartBitrateBps = 3000000;
Peter Boströmdef398832015-05-27 17:59:11 +02002692 static const int kExpectedRenderDelayMs = 20;
tommi2e82f382016-06-21 00:26:43 -07002693
2694 class ReceiveStreamRenderer : public rtc::VideoSinkInterface<VideoFrame> {
2695 public:
2696 ReceiveStreamRenderer() {}
2697
2698 private:
2699 void OnFrame(const VideoFrame& video_frame) override {}
2700 };
2701
nissed30a1112016-04-18 05:15:22 -07002702 class StatsObserver : public test::EndToEndTest,
2703 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002704 public:
stefanf116bd02015-10-27 08:29:42 -07002705 StatsObserver()
2706 : EndToEndTest(kLongTimeoutMs),
Peter Boströmc6e16e32016-02-05 14:15:53 +01002707 encoder_(Clock::GetRealTimeClock(), 10),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002708 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002709 expected_send_ssrcs_(),
Peter Boström5811a392015-12-10 13:02:50 +01002710 check_stats_event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002711
2712 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002713 Action OnSendRtp(const uint8_t* packet, size_t length) override {
sprangcd349d92016-07-13 09:11:28 -07002714 // Drop every 25th packet => 4% loss.
2715 static const int kPacketLossFrac = 25;
2716 RTPHeader header;
2717 RtpUtility::RtpHeaderParser parser(packet, length);
2718 if (parser.Parse(&header) &&
2719 expected_send_ssrcs_.find(header.ssrc) !=
2720 expected_send_ssrcs_.end() &&
2721 header.sequenceNumber % kPacketLossFrac == 0) {
2722 return DROP_PACKET;
2723 }
Peter Boström5811a392015-12-10 13:02:50 +01002724 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002725 return SEND_PACKET;
2726 }
2727
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002728 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002729 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002730 return SEND_PACKET;
2731 }
2732
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002733 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002734 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002735 return SEND_PACKET;
2736 }
2737
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002738 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002739 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002740 return SEND_PACKET;
2741 }
2742
nissed30a1112016-04-18 05:15:22 -07002743 void OnFrame(const VideoFrame& video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002744 // Ensure that we have at least 5ms send side delay.
nissed30a1112016-04-18 05:15:22 -07002745 SleepMs(5);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002746 }
2747
2748 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002749 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2750 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2751 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002752
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002753 // Make sure all fields have been populated.
2754 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
2755 // always filled for all receivers.
2756 receive_stats_filled_["IncomingRate"] |=
2757 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002758
Peter Boströmb7d9a972015-12-18 16:01:11 +01002759 send_stats_filled_["DecoderImplementationName"] |=
2760 stats.decoder_implementation_name ==
2761 test::FakeDecoder::kImplementationName;
Peter Boströmdef398832015-05-27 17:59:11 +02002762 receive_stats_filled_["RenderDelayAsHighAsExpected"] |=
2763 stats.render_delay_ms >= kExpectedRenderDelayMs;
2764
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002765 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002766
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002767 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002768
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002769 receive_stats_filled_["StatisticsUpdated"] |=
2770 stats.rtcp_stats.cumulative_lost != 0 ||
2771 stats.rtcp_stats.extended_max_sequence_number != 0 ||
2772 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002773
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002774 receive_stats_filled_["DataCountersUpdated"] |=
2775 stats.rtp_stats.transmitted.payload_bytes != 0 ||
2776 stats.rtp_stats.fec.packets != 0 ||
2777 stats.rtp_stats.transmitted.header_bytes != 0 ||
2778 stats.rtp_stats.transmitted.packets != 0 ||
2779 stats.rtp_stats.transmitted.padding_bytes != 0 ||
2780 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002781
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002782 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002783 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002784
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002785 receive_stats_filled_["FrameCounts"] |=
2786 stats.frame_counts.key_frames != 0 ||
2787 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002788
pbosbb36fdf2015-07-09 07:48:14 -07002789 receive_stats_filled_["CName"] |= !stats.c_name.empty();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002790
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002791 receive_stats_filled_["RtcpPacketTypeCount"] |=
2792 stats.rtcp_packet_type_counts.fir_packets != 0 ||
2793 stats.rtcp_packet_type_counts.nack_packets != 0 ||
2794 stats.rtcp_packet_type_counts.pli_packets != 0 ||
2795 stats.rtcp_packet_type_counts.nack_requests != 0 ||
2796 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbosf42376c2015-08-28 07:35:32 -07002797
2798 assert(stats.current_payload_type == -1 ||
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002799 stats.current_payload_type == kFakeVideoSendPayloadType);
pbosf42376c2015-08-28 07:35:32 -07002800 receive_stats_filled_["IncomingPayloadType"] |=
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002801 stats.current_payload_type == kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002802 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002803
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002804 return AllStatsFilled(receive_stats_filled_);
2805 }
2806
2807 bool CheckSendStats() {
Peter Boström74f6e9e2016-04-04 17:56:10 +02002808 RTC_DCHECK(send_stream_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002809 VideoSendStream::Stats stats = send_stream_->GetStats();
2810
philipel20d05a92016-12-19 04:17:27 -08002811 size_t expected_num_streams = kNumSsrcs + expected_send_ssrcs_.size();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002812 send_stats_filled_["NumStreams"] |=
philipel20d05a92016-12-19 04:17:27 -08002813 stats.substreams.size() == expected_num_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002814
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002815 send_stats_filled_["CpuOveruseMetrics"] |=
Peter Boströme4499152016-02-05 11:13:28 +01002816 stats.avg_encode_time_ms != 0 && stats.encode_usage_percent != 0;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002817
Peter Boströmb7d9a972015-12-18 16:01:11 +01002818 send_stats_filled_["EncoderImplementationName"] |=
2819 stats.encoder_implementation_name ==
2820 test::FakeEncoder::kImplementationName;
2821
Pera48ddb72016-09-29 11:48:50 +02002822 send_stats_filled_["EncoderPreferredBitrate"] |=
2823 stats.preferred_media_bitrate_bps > 0;
2824
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002825 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002826 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002827 it != stats.substreams.end(); ++it) {
sprangcd349d92016-07-13 09:11:28 -07002828 if (expected_send_ssrcs_.find(it->first) == expected_send_ssrcs_.end())
2829 continue; // Probably RTX.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002830
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002831 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002832 stats.input_frame_rate != 0;
2833
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002834 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002835
2836 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
2837 stream_stats.rtcp_stats.cumulative_lost != 0 ||
2838 stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
2839 stream_stats.rtcp_stats.fraction_lost != 0;
2840
2841 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002842 stream_stats.rtp_stats.fec.packets != 0 ||
2843 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
2844 stream_stats.rtp_stats.retransmitted.packets != 0 ||
2845 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002846
sprangcd349d92016-07-13 09:11:28 -07002847 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Total",
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002848 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002849 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002850
sprangcd349d92016-07-13 09:11:28 -07002851 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Retransmit",
2852 it->first)] |=
2853 stream_stats.retransmit_bitrate_bps != 0;
2854
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002855 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002856 stream_stats.frame_counts.delta_frames != 0 ||
2857 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002858
2859 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
2860 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00002861
2862 send_stats_filled_[CompoundKey("Delay", it->first)] |=
2863 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002864
2865 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
2866 // report dropped packets.
2867 send_stats_filled_["RtcpPacketTypeCount"] |=
2868 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
2869 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
2870 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
2871 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
2872 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002873 }
2874
2875 return AllStatsFilled(send_stats_filled_);
2876 }
2877
2878 std::string CompoundKey(const char* name, uint32_t ssrc) {
2879 std::ostringstream oss;
2880 oss << name << "_" << ssrc;
2881 return oss.str();
2882 }
2883
2884 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
sprangcd349d92016-07-13 09:11:28 -07002885 for (const auto& stat : stats_map) {
2886 if (!stat.second)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002887 return false;
2888 }
2889 return true;
2890 }
2891
stefane74eef12016-01-08 06:47:13 -08002892 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
2893 FakeNetworkPipe::Config network_config;
2894 network_config.loss_percent = 5;
2895 return new test::PacketTransport(
2896 sender_call, this, test::PacketTransport::kSender, network_config);
2897 }
2898
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002899 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002900 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01002901 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002902 return config;
2903 }
2904
perkjfa10b552016-10-02 23:45:26 -07002905 // This test use other VideoStream settings than the the default settings
2906 // implemented in DefaultVideoStreamFactory. Therefore this test implement
2907 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
2908 // in ModifyVideoConfigs.
2909 class VideoStreamFactory
2910 : public VideoEncoderConfig::VideoStreamFactoryInterface {
2911 public:
2912 VideoStreamFactory() {}
2913
2914 private:
2915 std::vector<VideoStream> CreateEncoderStreams(
2916 int width,
2917 int height,
2918 const VideoEncoderConfig& encoder_config) override {
2919 std::vector<VideoStream> streams =
2920 test::CreateVideoStreams(width, height, encoder_config);
2921 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
2922 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
2923 streams[i].min_bitrate_bps = 10000;
2924 streams[i].target_bitrate_bps = 15000;
2925 streams[i].max_bitrate_bps = 20000;
2926 }
2927 return streams;
2928 }
2929 };
2930
stefanff483612015-12-21 03:14:00 -08002931 void ModifyVideoConfigs(
2932 VideoSendStream::Config* send_config,
2933 std::vector<VideoReceiveStream::Config>* receive_configs,
2934 VideoEncoderConfig* encoder_config) override {
perkjfa10b552016-10-02 23:45:26 -07002935 encoder_config->video_stream_factory =
2936 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002937 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002938 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002939
sprangcd349d92016-07-13 09:11:28 -07002940 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2941 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
2942
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002943 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002944 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002945 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002946 expected_receive_ssrcs_.push_back(
2947 (*receive_configs)[i].rtp.remote_ssrc);
Peter Boströmdef398832015-05-27 17:59:11 +02002948 (*receive_configs)[i].render_delay_ms = kExpectedRenderDelayMs;
tommi2e82f382016-06-21 00:26:43 -07002949 (*receive_configs)[i].renderer = &receive_stream_renderer_;
sprangcd349d92016-07-13 09:11:28 -07002950 (*receive_configs)[i].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2951
2952 (*receive_configs)[i].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
2953 kSendRtxSsrcs[i];
2954 (*receive_configs)[i].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
2955 kSendRtxPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002956 }
sprangcd349d92016-07-13 09:11:28 -07002957
2958 for (size_t i = 0; i < kNumSsrcs; ++i)
2959 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
2960
Peter Boströmc6e16e32016-02-05 14:15:53 +01002961 // Use a delayed encoder to make sure we see CpuOveruseMetrics stats that
2962 // are non-zero.
2963 send_config->encoder_settings.encoder = &encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002964 }
2965
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002966 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00002967
stefanff483612015-12-21 03:14:00 -08002968 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002969 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002970 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002971 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002972 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002973 }
2974
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002975 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002976 Clock* clock = Clock::GetRealTimeClock();
2977 int64_t now = clock->TimeInMilliseconds();
2978 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
2979 bool receive_ok = false;
2980 bool send_ok = false;
2981
2982 while (now < stop_time) {
2983 if (!receive_ok)
2984 receive_ok = CheckReceiveStats();
2985 if (!send_ok)
2986 send_ok = CheckSendStats();
2987
2988 if (receive_ok && send_ok)
2989 return;
2990
2991 int64_t time_until_timout_ = stop_time - now;
2992 if (time_until_timout_ > 0)
Peter Boström5811a392015-12-10 13:02:50 +01002993 check_stats_event_.Wait(time_until_timout_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002994 now = clock->TimeInMilliseconds();
2995 }
2996
2997 ADD_FAILURE() << "Timed out waiting for filled stats.";
2998 for (std::map<std::string, bool>::const_iterator it =
2999 receive_stats_filled_.begin();
3000 it != receive_stats_filled_.end();
3001 ++it) {
3002 if (!it->second) {
3003 ADD_FAILURE() << "Missing receive stats: " << it->first;
3004 }
3005 }
3006
3007 for (std::map<std::string, bool>::const_iterator it =
3008 send_stats_filled_.begin();
3009 it != send_stats_filled_.end();
3010 ++it) {
3011 if (!it->second) {
3012 ADD_FAILURE() << "Missing send stats: " << it->first;
3013 }
3014 }
3015 }
3016
Peter Boströmc6e16e32016-02-05 14:15:53 +01003017 test::DelayedEncoder encoder_;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003018 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003019 std::map<std::string, bool> receive_stats_filled_;
3020
3021 VideoSendStream* send_stream_;
3022 std::map<std::string, bool> send_stats_filled_;
3023
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003024 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003025 std::set<uint32_t> expected_send_ssrcs_;
3026 std::string expected_cname_;
3027
Peter Boström5811a392015-12-10 13:02:50 +01003028 rtc::Event check_stats_event_;
tommi2e82f382016-06-21 00:26:43 -07003029 ReceiveStreamRenderer receive_stream_renderer_;
stefanf116bd02015-10-27 08:29:42 -07003030 } test;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003031
philipel266f0a42016-11-28 08:49:07 -08003032 // TODO(philipel): Implement statistics for the new video jitter buffer.
3033 if (GetParam() == new_jb_enabled)
3034 return;
3035
stefane74eef12016-01-08 06:47:13 -08003036 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003037}
3038
sprang1a646ee2016-12-01 06:34:11 -08003039class RtcpXrObserver : public test::EndToEndTest {
3040 public:
sprang44b3ef62017-01-13 07:30:25 -08003041 RtcpXrObserver(bool enable_rrtr, bool enable_target_bitrate)
sprang1a646ee2016-12-01 06:34:11 -08003042 : EndToEndTest(test::CallTest::kDefaultTimeoutMs),
3043 enable_rrtr_(enable_rrtr),
sprang44b3ef62017-01-13 07:30:25 -08003044 enable_target_bitrate_(enable_target_bitrate),
sprang1a646ee2016-12-01 06:34:11 -08003045 sent_rtcp_sr_(0),
3046 sent_rtcp_rr_(0),
3047 sent_rtcp_rrtr_(0),
3048 sent_rtcp_target_bitrate_(false),
3049 sent_rtcp_dlrr_(0) {}
3050
3051 private:
3052 // Receive stream should send RR packets (and RRTR packets if enabled).
3053 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
3054 rtc::CritScope lock(&crit_);
3055 test::RtcpPacketParser parser;
3056 EXPECT_TRUE(parser.Parse(packet, length));
3057
3058 sent_rtcp_rr_ += parser.receiver_report()->num_packets();
3059 EXPECT_EQ(0, parser.sender_report()->num_packets());
3060 EXPECT_GE(1, parser.xr()->num_packets());
3061 if (parser.xr()->num_packets() > 0) {
3062 if (parser.xr()->rrtr())
3063 ++sent_rtcp_rrtr_;
3064 EXPECT_FALSE(parser.xr()->dlrr());
3065 }
3066
3067 return SEND_PACKET;
3068 }
3069 // Send stream should send SR packets (and DLRR packets if enabled).
3070 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
3071 rtc::CritScope lock(&crit_);
3072 test::RtcpPacketParser parser;
3073 EXPECT_TRUE(parser.Parse(packet, length));
3074
3075 sent_rtcp_sr_ += parser.sender_report()->num_packets();
3076 EXPECT_LE(parser.xr()->num_packets(), 1);
3077 if (parser.xr()->num_packets() > 0) {
3078 EXPECT_FALSE(parser.xr()->rrtr());
3079 if (parser.xr()->dlrr())
3080 ++sent_rtcp_dlrr_;
3081 if (parser.xr()->target_bitrate())
3082 sent_rtcp_target_bitrate_ = true;
3083 }
3084
3085 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
3086 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve &&
sprang44b3ef62017-01-13 07:30:25 -08003087 (sent_rtcp_target_bitrate_ || !enable_target_bitrate_)) {
sprang1a646ee2016-12-01 06:34:11 -08003088 if (enable_rrtr_) {
3089 EXPECT_GT(sent_rtcp_rrtr_, 0);
3090 EXPECT_GT(sent_rtcp_dlrr_, 0);
3091 } else {
3092 EXPECT_EQ(sent_rtcp_rrtr_, 0);
3093 EXPECT_EQ(sent_rtcp_dlrr_, 0);
3094 }
sprang44b3ef62017-01-13 07:30:25 -08003095 EXPECT_EQ(enable_target_bitrate_, sent_rtcp_target_bitrate_);
sprang1a646ee2016-12-01 06:34:11 -08003096 observation_complete_.Set();
3097 }
3098 return SEND_PACKET;
3099 }
3100
3101 void ModifyVideoConfigs(
3102 VideoSendStream::Config* send_config,
3103 std::vector<VideoReceiveStream::Config>* receive_configs,
3104 VideoEncoderConfig* encoder_config) override {
sprang44b3ef62017-01-13 07:30:25 -08003105 if (enable_target_bitrate_) {
3106 // TargetBitrate only signaled for screensharing.
3107 encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
3108 }
sprang1a646ee2016-12-01 06:34:11 -08003109 (*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
3110 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
3111 enable_rrtr_;
3112 }
3113
3114 void PerformTest() override {
3115 EXPECT_TRUE(Wait())
3116 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
3117 }
3118
3119 static const int kNumRtcpReportPacketsToObserve = 5;
3120
3121 rtc::CriticalSection crit_;
sprang44b3ef62017-01-13 07:30:25 -08003122 const bool enable_rrtr_;
3123 const bool enable_target_bitrate_;
sprang1a646ee2016-12-01 06:34:11 -08003124 int sent_rtcp_sr_;
3125 int sent_rtcp_rr_ GUARDED_BY(&crit_);
3126 int sent_rtcp_rrtr_ GUARDED_BY(&crit_);
3127 bool sent_rtcp_target_bitrate_ GUARDED_BY(&crit_);
3128 int sent_rtcp_dlrr_;
3129};
3130
sprang44b3ef62017-01-13 07:30:25 -08003131TEST_P(EndToEndTest, TestExtendedReportsWithRrtrWithoutTargetBitrate) {
3132 RtcpXrObserver test(true, false);
sprang1a646ee2016-12-01 06:34:11 -08003133 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003134}
3135
sprang44b3ef62017-01-13 07:30:25 -08003136TEST_P(EndToEndTest, TestExtendedReportsWithoutRrtrWithoutTargetBitrate) {
3137 RtcpXrObserver test(false, false);
3138 RunBaseTest(&test);
3139}
3140
3141TEST_P(EndToEndTest, TestExtendedReportsWithRrtrWithTargetBitrate) {
3142 RtcpXrObserver test(true, true);
3143 RunBaseTest(&test);
3144}
3145
3146TEST_P(EndToEndTest, TestExtendedReportsWithoutRrtrWithTargetBitrate) {
3147 RtcpXrObserver test(false, true);
sprang1a646ee2016-12-01 06:34:11 -08003148 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003149}
3150
philipel266f0a42016-11-28 08:49:07 -08003151TEST_P(EndToEndTest, TestReceivedRtpPacketStats) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003152 static const size_t kNumRtpPacketsToSend = 5;
3153 class ReceivedRtpStatsObserver : public test::EndToEndTest {
3154 public:
3155 ReceivedRtpStatsObserver()
3156 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00003157 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003158 sent_rtp_(0) {}
3159
3160 private:
stefanff483612015-12-21 03:14:00 -08003161 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003162 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003163 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003164 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003165 }
3166
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003167 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003168 if (sent_rtp_ >= kNumRtpPacketsToSend) {
3169 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00003170 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
Peter Boström5811a392015-12-10 13:02:50 +01003171 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003172 }
3173 return DROP_PACKET;
3174 }
3175 ++sent_rtp_;
3176 return SEND_PACKET;
3177 }
3178
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003179 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003180 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003181 << "Timed out while verifying number of received RTP packets.";
3182 }
3183
3184 VideoReceiveStream* receive_stream_;
3185 uint32_t sent_rtp_;
3186 } test;
3187
stefane74eef12016-01-08 06:47:13 -08003188 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003189}
3190
philipel266f0a42016-11-28 08:49:07 -08003191TEST_P(EndToEndTest, SendsSetSsrc) {
3192 TestSendsSetSsrcs(1, false);
3193}
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003194
philipel266f0a42016-11-28 08:49:07 -08003195TEST_P(EndToEndTest, SendsSetSimulcastSsrcs) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003196 TestSendsSetSsrcs(kNumSsrcs, false);
3197}
3198
philipel266f0a42016-11-28 08:49:07 -08003199TEST_P(EndToEndTest, CanSwitchToUseAllSsrcs) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003200 TestSendsSetSsrcs(kNumSsrcs, true);
3201}
3202
philipel266f0a42016-11-28 08:49:07 -08003203TEST_P(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003204 class ObserveRedundantPayloads: public test::EndToEndTest {
3205 public:
3206 ObserveRedundantPayloads()
3207 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003208 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003209 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
3210 }
3211 }
3212
3213 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003214 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003215 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003216 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003217
3218 if (!registered_rtx_ssrc_[header.ssrc])
3219 return SEND_PACKET;
3220
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003221 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003222 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003223 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003224
3225 if (!packet_is_redundant_payload)
3226 return SEND_PACKET;
3227
3228 if (!observed_redundant_retransmission_[header.ssrc]) {
3229 observed_redundant_retransmission_[header.ssrc] = true;
3230 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01003231 observation_complete_.Set();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003232 }
3233
3234 return SEND_PACKET;
3235 }
3236
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003237 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003238
perkjfa10b552016-10-02 23:45:26 -07003239 // This test use other VideoStream settings than the the default settings
3240 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3241 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3242 // in ModifyVideoConfigs.
3243 class VideoStreamFactory
3244 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3245 public:
3246 VideoStreamFactory() {}
3247
3248 private:
3249 std::vector<VideoStream> CreateEncoderStreams(
3250 int width,
3251 int height,
3252 const VideoEncoderConfig& encoder_config) override {
3253 std::vector<VideoStream> streams =
3254 test::CreateVideoStreams(width, height, encoder_config);
3255 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
3256 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3257 streams[i].min_bitrate_bps = 10000;
3258 streams[i].target_bitrate_bps = 15000;
3259 streams[i].max_bitrate_bps = 20000;
3260 }
3261 return streams;
3262 }
3263 };
3264
stefanff483612015-12-21 03:14:00 -08003265 void ModifyVideoConfigs(
3266 VideoSendStream::Config* send_config,
3267 std::vector<VideoReceiveStream::Config>* receive_configs,
3268 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003269 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
perkjfa10b552016-10-02 23:45:26 -07003270 encoder_config->video_stream_factory =
3271 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003272 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003273
3274 for (size_t i = 0; i < kNumSsrcs; ++i)
3275 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00003276
3277 // Significantly higher than max bitrates for all video streams -> forcing
3278 // padding to trigger redundant padding on all RTX SSRCs.
3279 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003280 }
3281
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003282 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003283 EXPECT_TRUE(Wait())
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003284 << "Timed out while waiting for redundant payloads on all SSRCs.";
3285 }
3286
3287 private:
3288 size_t ssrcs_to_observe_;
3289 std::map<uint32_t, bool> observed_redundant_retransmission_;
3290 std::map<uint32_t, bool> registered_rtx_ssrc_;
3291 } test;
3292
stefane74eef12016-01-08 06:47:13 -08003293 RunBaseTest(&test);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003294}
3295
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003296void EndToEndTest::TestRtpStatePreservation(bool use_rtx,
3297 bool provoke_rtcpsr_before_rtp) {
perkjfa10b552016-10-02 23:45:26 -07003298 // This test use other VideoStream settings than the the default settings
3299 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3300 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3301 // in ModifyVideoConfigs.
3302 class VideoStreamFactory
3303 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3304 public:
3305 VideoStreamFactory() {}
3306
3307 private:
3308 std::vector<VideoStream> CreateEncoderStreams(
3309 int width,
3310 int height,
3311 const VideoEncoderConfig& encoder_config) override {
3312 std::vector<VideoStream> streams =
3313 test::CreateVideoStreams(width, height, encoder_config);
3314
3315 if (encoder_config.number_of_streams > 1) {
3316 // Lower bitrates so that all streams send initially.
kwibergaf476c72016-11-28 15:21:39 -08003317 RTC_DCHECK_EQ(3, encoder_config.number_of_streams);
perkjfa10b552016-10-02 23:45:26 -07003318 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3319 streams[i].min_bitrate_bps = 10000;
3320 streams[i].target_bitrate_bps = 15000;
3321 streams[i].max_bitrate_bps = 20000;
3322 }
3323 } else {
3324 // Use the same total bitrates when sending a single stream to avoid
3325 // lowering
3326 // the bitrate estimate and requiring a subsequent rampup.
3327 streams[0].min_bitrate_bps = 3 * 10000;
3328 streams[0].target_bitrate_bps = 3 * 15000;
3329 streams[0].max_bitrate_bps = 3 * 20000;
3330 }
3331 return streams;
3332 }
3333 };
3334
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003335 class RtpSequenceObserver : public test::RtpRtcpObserver {
3336 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003337 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003338 : test::RtpRtcpObserver(kDefaultTimeoutMs),
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003339 ssrcs_to_observe_(kNumSsrcs) {
3340 for (size_t i = 0; i < kNumSsrcs; ++i) {
danilchap32cd2c42016-08-01 06:58:34 -07003341 ssrc_is_rtx_[kVideoSendSsrcs[i]] = false;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003342 if (use_rtx)
danilchap32cd2c42016-08-01 06:58:34 -07003343 ssrc_is_rtx_[kSendRtxSsrcs[i]] = true;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003344 }
3345 }
3346
3347 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
Peter Boströmf2f82832015-05-01 13:00:41 +02003348 rtc::CritScope lock(&crit_);
danilchap34877ee2016-02-01 08:25:04 -08003349 ssrc_observed_.clear();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003350 ssrcs_to_observe_ = num_expected_ssrcs;
3351 }
3352
3353 private:
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003354 void ValidateTimestampGap(uint32_t ssrc,
3355 uint32_t timestamp,
3356 bool only_padding)
3357 EXCLUSIVE_LOCKS_REQUIRED(crit_) {
3358 static const int32_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
3359 auto timestamp_it = last_observed_timestamp_.find(ssrc);
3360 if (timestamp_it == last_observed_timestamp_.end()) {
3361 EXPECT_FALSE(only_padding);
3362 last_observed_timestamp_[ssrc] = timestamp;
3363 } else {
3364 // Verify timestamps are reasonably close.
3365 uint32_t latest_observed = timestamp_it->second;
3366 // Wraparound handling is unnecessary here as long as an int variable
3367 // is used to store the result.
3368 int32_t timestamp_gap = timestamp - latest_observed;
3369 EXPECT_LE(std::abs(timestamp_gap), kMaxTimestampGap)
3370 << "Gap in timestamps (" << latest_observed << " -> " << timestamp
3371 << ") too large for SSRC: " << ssrc << ".";
3372 timestamp_it->second = timestamp;
3373 }
3374 }
3375
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003376 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003377 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003378 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003379 const uint32_t ssrc = header.ssrc;
danilchap5c35cf92016-02-03 14:14:49 -08003380 const int64_t sequence_number =
3381 seq_numbers_unwrapper_.Unwrap(header.sequenceNumber);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003382 const uint32_t timestamp = header.timestamp;
danilchap34877ee2016-02-01 08:25:04 -08003383 const bool only_padding =
3384 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003385
danilchap32cd2c42016-08-01 06:58:34 -07003386 EXPECT_TRUE(ssrc_is_rtx_.find(ssrc) != ssrc_is_rtx_.end())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003387 << "Received SSRC that wasn't configured: " << ssrc;
3388
danilchap5c35cf92016-02-03 14:14:49 -08003389 static const int64_t kMaxSequenceNumberGap = 100;
3390 std::list<int64_t>* seq_numbers = &last_observed_seq_numbers_[ssrc];
3391 if (seq_numbers->empty()) {
3392 seq_numbers->push_back(sequence_number);
3393 } else {
3394 // We shouldn't get replays of previous sequence numbers.
3395 for (int64_t observed : *seq_numbers) {
3396 EXPECT_NE(observed, sequence_number)
3397 << "Received sequence number " << sequence_number
3398 << " for SSRC " << ssrc << " 2nd time.";
3399 }
3400 // Verify sequence numbers are reasonably close.
3401 int64_t latest_observed = seq_numbers->back();
3402 int64_t sequence_number_gap = sequence_number - latest_observed;
3403 EXPECT_LE(std::abs(sequence_number_gap), kMaxSequenceNumberGap)
3404 << "Gap in sequence numbers (" << latest_observed << " -> "
3405 << sequence_number << ") too large for SSRC: " << ssrc << ".";
3406 seq_numbers->push_back(sequence_number);
3407 if (seq_numbers->size() >= kMaxSequenceNumberGap) {
3408 seq_numbers->pop_front();
3409 }
3410 }
3411
danilchap32cd2c42016-08-01 06:58:34 -07003412 if (!ssrc_is_rtx_[ssrc]) {
3413 rtc::CritScope lock(&crit_);
3414 ValidateTimestampGap(ssrc, timestamp, only_padding);
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003415
danilchap32cd2c42016-08-01 06:58:34 -07003416 // Wait for media packets on all ssrcs.
3417 if (!ssrc_observed_[ssrc] && !only_padding) {
3418 ssrc_observed_[ssrc] = true;
3419 if (--ssrcs_to_observe_ == 0)
3420 observation_complete_.Set();
3421 }
danilchap34877ee2016-02-01 08:25:04 -08003422 }
3423
danilchapf4b9c772016-01-28 06:14:24 -08003424 return SEND_PACKET;
3425 }
3426
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003427 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
3428 test::RtcpPacketParser rtcp_parser;
3429 rtcp_parser.Parse(packet, length);
3430 if (rtcp_parser.sender_report()->num_packets() > 0) {
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02003431 uint32_t ssrc = rtcp_parser.sender_report()->sender_ssrc();
3432 uint32_t rtcp_timestamp = rtcp_parser.sender_report()->rtp_timestamp();
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003433
3434 rtc::CritScope lock(&crit_);
3435 ValidateTimestampGap(ssrc, rtcp_timestamp, false);
3436 }
3437 return SEND_PACKET;
3438 }
3439
danilchap5c35cf92016-02-03 14:14:49 -08003440 SequenceNumberUnwrapper seq_numbers_unwrapper_;
3441 std::map<uint32_t, std::list<int64_t>> last_observed_seq_numbers_;
danilchap34877ee2016-02-01 08:25:04 -08003442 std::map<uint32_t, uint32_t> last_observed_timestamp_;
danilchap32cd2c42016-08-01 06:58:34 -07003443 std::map<uint32_t, bool> ssrc_is_rtx_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003444
Peter Boströmf2f82832015-05-01 13:00:41 +02003445 rtc::CriticalSection crit_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003446 size_t ssrcs_to_observe_ GUARDED_BY(crit_);
danilchap34877ee2016-02-01 08:25:04 -08003447 std::map<uint32_t, bool> ssrc_observed_ GUARDED_BY(crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003448 } observer(use_rtx);
3449
skvlad11a9cbf2016-10-07 11:53:05 -07003450 Call::Config config(&event_log_);
3451 CreateCalls(config, config);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003452
stefanf116bd02015-10-27 08:29:42 -07003453 test::PacketTransport send_transport(sender_call_.get(), &observer,
3454 test::PacketTransport::kSender,
3455 FakeNetworkPipe::Config());
3456 test::PacketTransport receive_transport(nullptr, &observer,
3457 test::PacketTransport::kReceiver,
3458 FakeNetworkPipe::Config());
3459 send_transport.SetReceiver(receiver_call_->Receiver());
3460 receive_transport.SetReceiver(sender_call_->Receiver());
3461
brandtr841de6a2016-11-15 07:10:52 -08003462 CreateSendConfig(kNumSsrcs, 0, 0, &send_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003463
3464 if (use_rtx) {
3465 for (size_t i = 0; i < kNumSsrcs; ++i) {
stefanff483612015-12-21 03:14:00 -08003466 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003467 }
stefanff483612015-12-21 03:14:00 -08003468 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003469 }
3470
perkjfa10b552016-10-02 23:45:26 -07003471 video_encoder_config_.video_stream_factory =
3472 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003473 // Use the same total bitrates when sending a single stream to avoid lowering
3474 // the bitrate estimate and requiring a subsequent rampup.
perkj26091b12016-09-01 01:17:40 -07003475 VideoEncoderConfig one_stream = video_encoder_config_.Copy();
perkjfa10b552016-10-02 23:45:26 -07003476 // one_stream.streams.resize(1);
3477 one_stream.number_of_streams = 1;
stefanf116bd02015-10-27 08:29:42 -07003478 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003479
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003480 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003481 CreateFrameGeneratorCapturer(30, 1280, 720);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003482
3483 Start();
Peter Boström5811a392015-12-10 13:02:50 +01003484 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003485 << "Timed out waiting for all SSRCs to send packets.";
3486
3487 // Test stream resetting more than once to make sure that the state doesn't
3488 // get set once (this could be due to using std::map::insert for instance).
3489 for (size_t i = 0; i < 3; ++i) {
3490 frame_generator_capturer_->Stop();
stefanff483612015-12-21 03:14:00 -08003491 sender_call_->DestroyVideoSendStream(video_send_stream_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003492
3493 // Re-create VideoSendStream with only one stream.
perkj26091b12016-09-01 01:17:40 -07003494 video_send_stream_ = sender_call_->CreateVideoSendStream(
3495 video_send_config_.Copy(), one_stream.Copy());
stefanff483612015-12-21 03:14:00 -08003496 video_send_stream_->Start();
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003497 if (provoke_rtcpsr_before_rtp) {
3498 // Rapid Resync Request forces sending RTCP Sender Report back.
3499 // Using this request speeds up this test because then there is no need
3500 // to wait for a second for periodic Sender Report.
3501 rtcp::RapidResyncRequest force_send_sr_back_request;
3502 rtc::Buffer packet = force_send_sr_back_request.Build();
3503 static_cast<webrtc::test::DirectTransport&>(receive_transport)
3504 .SendRtcp(packet.data(), packet.size());
3505 }
perkjfa10b552016-10-02 23:45:26 -07003506 CreateFrameGeneratorCapturer(30, 1280, 720);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003507 frame_generator_capturer_->Start();
3508
3509 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003510 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003511
3512 // Reconfigure back to use all streams.
perkj26091b12016-09-01 01:17:40 -07003513 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003514 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003515 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003516 << "Timed out waiting for all SSRCs to send packets.";
3517
3518 // Reconfigure down to one stream.
perkj26091b12016-09-01 01:17:40 -07003519 video_send_stream_->ReconfigureVideoEncoder(one_stream.Copy());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003520 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003521 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003522
3523 // Reconfigure back to use all streams.
perkj26091b12016-09-01 01:17:40 -07003524 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003525 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003526 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003527 << "Timed out waiting for all SSRCs to send packets.";
3528 }
3529
stefanf116bd02015-10-27 08:29:42 -07003530 send_transport.StopSending();
3531 receive_transport.StopSending();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003532
3533 Stop();
3534 DestroyStreams();
3535}
3536
philipel266f0a42016-11-28 08:49:07 -08003537TEST_P(EndToEndTest, RestartingSendStreamPreservesRtpState) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003538 TestRtpStatePreservation(false, false);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003539}
3540
philipel266f0a42016-11-28 08:49:07 -08003541TEST_P(EndToEndTest, RestartingSendStreamPreservesRtpStatesWithRtx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003542 TestRtpStatePreservation(true, false);
3543}
3544
philipel266f0a42016-11-28 08:49:07 -08003545TEST_P(EndToEndTest, RestartingSendStreamKeepsRtpAndRtcpTimestampsSynced) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003546 TestRtpStatePreservation(true, true);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003547}
3548
philipel266f0a42016-11-28 08:49:07 -08003549TEST_P(EndToEndTest, RespectsNetworkState) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003550 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
3551 // down blocks until no more packets will be sent.
3552
3553 // Pacer will send from its packet list and then send required padding before
3554 // checking paused_ again. This should be enough for one round of pacing,
3555 // otherwise increase.
3556 static const int kNumAcceptedDowntimeRtp = 5;
3557 // A single RTCP may be in the pipeline.
3558 static const int kNumAcceptedDowntimeRtcp = 1;
3559 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
3560 public:
3561 NetworkStateTest()
3562 : EndToEndTest(kDefaultTimeoutMs),
3563 FakeEncoder(Clock::GetRealTimeClock()),
Peter Boström5811a392015-12-10 13:02:50 +01003564 encoded_frames_(false, false),
3565 packet_event_(false, false),
sprang867fb522015-08-03 04:38:41 -07003566 sender_call_(nullptr),
3567 receiver_call_(nullptr),
Jelena Marusiccd670222015-07-16 09:30:09 +02003568 sender_state_(kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003569 sender_rtp_(0),
3570 sender_rtcp_(0),
3571 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003572 down_frames_(0) {}
3573
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003574 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003575 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003576 ++sender_rtp_;
Peter Boström5811a392015-12-10 13:02:50 +01003577 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003578 return SEND_PACKET;
3579 }
3580
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003581 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003582 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003583 ++sender_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003584 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003585 return SEND_PACKET;
3586 }
3587
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003588 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003589 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
3590 return SEND_PACKET;
3591 }
3592
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003593 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003594 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003595 ++receiver_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003596 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003597 return SEND_PACKET;
3598 }
3599
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003600 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003601 sender_call_ = sender_call;
3602 receiver_call_ = receiver_call;
3603 }
3604
stefanff483612015-12-21 03:14:00 -08003605 void ModifyVideoConfigs(
3606 VideoSendStream::Config* send_config,
3607 std::vector<VideoReceiveStream::Config>* receive_configs,
3608 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003609 send_config->encoder_settings.encoder = this;
3610 }
3611
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003612 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003613 EXPECT_TRUE(encoded_frames_.Wait(kDefaultTimeoutMs))
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003614 << "No frames received by the encoder.";
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003615 // Wait for packets from both sender/receiver.
3616 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003617
skvlad7a43d252016-03-22 15:32:27 -07003618 // Sender-side network down for audio; there should be no effect on video
3619 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3620 WaitForPacketsOrSilence(false, false);
3621
3622 // Receiver-side network down for audio; no change expected
3623 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3624 WaitForPacketsOrSilence(false, false);
3625
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003626 // Sender-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003627 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003628 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003629 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003630 // After network goes down we shouldn't be encoding more frames.
Jelena Marusiccd670222015-07-16 09:30:09 +02003631 sender_state_ = kNetworkDown;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003632 }
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003633 // Wait for receiver-packets and no sender packets.
3634 WaitForPacketsOrSilence(true, false);
3635
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003636 // Receiver-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003637 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
3638 WaitForPacketsOrSilence(true, true);
3639
3640 // Network up for audio for both sides; video is still not expected to
3641 // start
3642 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
3643 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003644 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003645
3646 // Network back up again for both.
3647 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003648 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003649 // It's OK to encode frames again, as we're about to bring up the
3650 // network.
Jelena Marusiccd670222015-07-16 09:30:09 +02003651 sender_state_ = kNetworkUp;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003652 }
skvlad7a43d252016-03-22 15:32:27 -07003653 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
3654 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003655 WaitForPacketsOrSilence(false, false);
skvlad7a43d252016-03-22 15:32:27 -07003656
3657 // TODO(skvlad): add tests to verify that the audio streams are stopped
3658 // when the network goes down for audio once the workaround in
3659 // paced_sender.cc is removed.
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003660 }
3661
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07003662 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003663 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07003664 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003665 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003666 rtc::CritScope lock(&test_crit_);
Jelena Marusiccd670222015-07-16 09:30:09 +02003667 if (sender_state_ == kNetworkDown) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003668 ++down_frames_;
3669 EXPECT_LE(down_frames_, 1)
3670 << "Encoding more than one frame while network is down.";
3671 if (down_frames_ > 1)
Peter Boström5811a392015-12-10 13:02:50 +01003672 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003673 } else {
Peter Boström5811a392015-12-10 13:02:50 +01003674 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003675 }
3676 }
3677 return test::FakeEncoder::Encode(
3678 input_image, codec_specific_info, frame_types);
3679 }
3680
3681 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003682 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
3683 int64_t initial_time_ms = clock_->TimeInMilliseconds();
3684 int initial_sender_rtp;
3685 int initial_sender_rtcp;
3686 int initial_receiver_rtcp;
3687 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003688 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003689 initial_sender_rtp = sender_rtp_;
3690 initial_sender_rtcp = sender_rtcp_;
3691 initial_receiver_rtcp = receiver_rtcp_;
3692 }
3693 bool sender_done = false;
3694 bool receiver_done = false;
mflodmand1590b22015-12-09 07:07:59 -08003695 while (!sender_done || !receiver_done) {
Peter Boström5811a392015-12-10 13:02:50 +01003696 packet_event_.Wait(kSilenceTimeoutMs);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003697 int64_t time_now_ms = clock_->TimeInMilliseconds();
Peter Boströmf2f82832015-05-01 13:00:41 +02003698 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003699 if (sender_down) {
3700 ASSERT_LE(sender_rtp_ - initial_sender_rtp, kNumAcceptedDowntimeRtp)
3701 << "RTP sent during sender-side downtime.";
3702 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
3703 kNumAcceptedDowntimeRtcp)
3704 << "RTCP sent during sender-side downtime.";
3705 if (time_now_ms - initial_time_ms >=
3706 static_cast<int64_t>(kSilenceTimeoutMs)) {
3707 sender_done = true;
3708 }
3709 } else {
skvlad7a43d252016-03-22 15:32:27 -07003710 if (sender_rtp_ > initial_sender_rtp + kNumAcceptedDowntimeRtp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003711 sender_done = true;
3712 }
3713 if (receiver_down) {
3714 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
3715 kNumAcceptedDowntimeRtcp)
3716 << "RTCP sent during receiver-side downtime.";
3717 if (time_now_ms - initial_time_ms >=
3718 static_cast<int64_t>(kSilenceTimeoutMs)) {
3719 receiver_done = true;
3720 }
3721 } else {
skvlad7a43d252016-03-22 15:32:27 -07003722 if (receiver_rtcp_ > initial_receiver_rtcp + kNumAcceptedDowntimeRtcp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003723 receiver_done = true;
3724 }
3725 }
3726 }
3727
Peter Boströmf2f82832015-05-01 13:00:41 +02003728 rtc::CriticalSection test_crit_;
Peter Boström5811a392015-12-10 13:02:50 +01003729 rtc::Event encoded_frames_;
3730 rtc::Event packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003731 Call* sender_call_;
3732 Call* receiver_call_;
Jelena Marusiccd670222015-07-16 09:30:09 +02003733 NetworkState sender_state_ GUARDED_BY(test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003734 int sender_rtp_ GUARDED_BY(test_crit_);
3735 int sender_rtcp_ GUARDED_BY(test_crit_);
3736 int receiver_rtcp_ GUARDED_BY(test_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003737 int down_frames_ GUARDED_BY(test_crit_);
3738 } test;
3739
stefane74eef12016-01-08 06:47:13 -08003740 RunBaseTest(&test);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003741}
3742
philipel266f0a42016-11-28 08:49:07 -08003743TEST_P(EndToEndTest, CallReportsRttForSender) {
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003744 static const int kSendDelayMs = 30;
3745 static const int kReceiveDelayMs = 70;
skvlad11a9cbf2016-10-07 11:53:05 -07003746 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -07003747
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003748 FakeNetworkPipe::Config config;
3749 config.queue_delay_ms = kSendDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003750 test::DirectTransport sender_transport(config, sender_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003751 config.queue_delay_ms = kReceiveDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003752 test::DirectTransport receiver_transport(config, receiver_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003753 sender_transport.SetReceiver(receiver_call_->Receiver());
3754 receiver_transport.SetReceiver(sender_call_->Receiver());
3755
brandtr841de6a2016-11-15 07:10:52 -08003756 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07003757 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003758
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003759 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003760 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
3761 kDefaultHeight);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003762 Start();
3763
3764 int64_t start_time_ms = clock_->TimeInMilliseconds();
3765 while (true) {
3766 Call::Stats stats = sender_call_->GetStats();
3767 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
3768 clock_->TimeInMilliseconds())
3769 << "No RTT stats before timeout!";
3770 if (stats.rtt_ms != -1) {
Danil Chapovalov10e8f8e2016-09-07 15:05:29 +02003771 // To avoid failures caused by rounding or minor ntp clock adjustments,
3772 // relax expectation by 1ms.
3773 constexpr int kAllowedErrorMs = 1;
3774 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs - kAllowedErrorMs);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003775 break;
3776 }
3777 SleepMs(10);
3778 }
3779
philipel266f0a42016-11-28 08:49:07 -08003780 sender_transport.StopSending();
3781 receiver_transport.StopSending();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003782 Stop();
3783 DestroyStreams();
philipel266f0a42016-11-28 08:49:07 -08003784 DestroyCalls();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003785}
3786
skvlad7a43d252016-03-22 15:32:27 -07003787void EndToEndTest::VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08003788 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -07003789 VideoEncoder* encoder,
3790 Transport* transport) {
skvlad11a9cbf2016-10-07 11:53:05 -07003791 CreateSenderCall(Call::Config(&event_log_));
Sergey Ulanove2b15012016-11-22 16:08:30 -08003792 sender_call_->SignalChannelNetworkState(network_to_bring_up, kNetworkUp);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003793
brandtr841de6a2016-11-15 07:10:52 -08003794 CreateSendConfig(1, 0, 0, transport);
skvlad7a43d252016-03-22 15:32:27 -07003795 video_send_config_.encoder_settings.encoder = encoder;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003796 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003797 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
3798 kDefaultHeight);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003799
3800 Start();
3801 SleepMs(kSilenceTimeoutMs);
3802 Stop();
3803
3804 DestroyStreams();
3805}
3806
skvlad7a43d252016-03-22 15:32:27 -07003807void EndToEndTest::VerifyNewVideoReceiveStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08003808 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -07003809 Transport* transport) {
skvlad11a9cbf2016-10-07 11:53:05 -07003810 Call::Config config(&event_log_);
3811 CreateCalls(config, config);
Sergey Ulanove2b15012016-11-22 16:08:30 -08003812 receiver_call_->SignalChannelNetworkState(network_to_bring_up, kNetworkUp);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003813
stefanf116bd02015-10-27 08:29:42 -07003814 test::DirectTransport sender_transport(sender_call_.get());
solenberg4fbae2b2015-08-28 04:07:10 -07003815 sender_transport.SetReceiver(receiver_call_->Receiver());
brandtr841de6a2016-11-15 07:10:52 -08003816 CreateSendConfig(1, 0, 0, &sender_transport);
skvlad7a43d252016-03-22 15:32:27 -07003817 CreateMatchingReceiveConfigs(transport);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003818 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003819 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
3820 kDefaultHeight);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003821
3822 Start();
3823 SleepMs(kSilenceTimeoutMs);
3824 Stop();
3825
3826 sender_transport.StopSending();
3827
3828 DestroyStreams();
3829}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00003830
philipel266f0a42016-11-28 08:49:07 -08003831TEST_P(EndToEndTest, NewVideoSendStreamsRespectVideoNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07003832 class UnusedEncoder : public test::FakeEncoder {
3833 public:
3834 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
perkjfea93092016-05-14 00:58:48 -07003835
3836 int32_t InitEncode(const VideoCodec* config,
3837 int32_t number_of_cores,
3838 size_t max_payload_size) override {
3839 EXPECT_GT(config->startBitrate, 0u);
3840 return 0;
3841 }
skvlad7a43d252016-03-22 15:32:27 -07003842 int32_t Encode(const VideoFrame& input_image,
3843 const CodecSpecificInfo* codec_specific_info,
3844 const std::vector<FrameType>* frame_types) override {
3845 ADD_FAILURE() << "Unexpected frame encode.";
3846 return test::FakeEncoder::Encode(input_image, codec_specific_info,
3847 frame_types);
3848 }
3849 };
3850
3851 UnusedEncoder unused_encoder;
3852 UnusedTransport unused_transport;
3853 VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08003854 MediaType::AUDIO, &unused_encoder, &unused_transport);
skvlad7a43d252016-03-22 15:32:27 -07003855}
3856
philipel266f0a42016-11-28 08:49:07 -08003857TEST_P(EndToEndTest, NewVideoSendStreamsIgnoreAudioNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07003858 class RequiredEncoder : public test::FakeEncoder {
3859 public:
3860 RequiredEncoder()
3861 : FakeEncoder(Clock::GetRealTimeClock()), encoded_frame_(false) {}
3862 ~RequiredEncoder() {
3863 if (!encoded_frame_) {
3864 ADD_FAILURE() << "Didn't encode an expected frame";
3865 }
3866 }
3867 int32_t Encode(const VideoFrame& input_image,
3868 const CodecSpecificInfo* codec_specific_info,
3869 const std::vector<FrameType>* frame_types) override {
3870 encoded_frame_ = true;
3871 return test::FakeEncoder::Encode(input_image, codec_specific_info,
3872 frame_types);
3873 }
3874
3875 private:
3876 bool encoded_frame_;
3877 };
3878
3879 RequiredTransport required_transport(true /*rtp*/, false /*rtcp*/);
3880 RequiredEncoder required_encoder;
3881 VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08003882 MediaType::VIDEO, &required_encoder, &required_transport);
skvlad7a43d252016-03-22 15:32:27 -07003883}
3884
philipel266f0a42016-11-28 08:49:07 -08003885TEST_P(EndToEndTest, NewVideoReceiveStreamsRespectVideoNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07003886 UnusedTransport transport;
Sergey Ulanove2b15012016-11-22 16:08:30 -08003887 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::AUDIO, &transport);
skvlad7a43d252016-03-22 15:32:27 -07003888}
3889
philipel266f0a42016-11-28 08:49:07 -08003890TEST_P(EndToEndTest, NewVideoReceiveStreamsIgnoreAudioNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07003891 RequiredTransport transport(false /*rtp*/, true /*rtcp*/);
Sergey Ulanove2b15012016-11-22 16:08:30 -08003892 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::VIDEO, &transport);
skvlad7a43d252016-03-22 15:32:27 -07003893}
3894
Peter Boströmd7da1202015-06-05 14:09:38 +02003895void VerifyEmptyNackConfig(const NackConfig& config) {
3896 EXPECT_EQ(0, config.rtp_history_ms)
3897 << "Enabling NACK requires rtcp-fb: nack negotiation.";
3898}
3899
brandtrb5f2c3f2016-10-04 23:28:39 -07003900void VerifyEmptyUlpfecConfig(const UlpfecConfig& config) {
Peter Boströmd7da1202015-06-05 14:09:38 +02003901 EXPECT_EQ(-1, config.ulpfec_payload_type)
brandtr535830e2016-10-31 03:45:58 -07003902 << "Enabling ULPFEC requires rtpmap: ulpfec negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02003903 EXPECT_EQ(-1, config.red_payload_type)
brandtr535830e2016-10-31 03:45:58 -07003904 << "Enabling ULPFEC requires rtpmap: red negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02003905 EXPECT_EQ(-1, config.red_rtx_payload_type)
brandtr535830e2016-10-31 03:45:58 -07003906 << "Enabling RTX in ULPFEC requires rtpmap: rtx negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02003907}
3908
brandtr3d200bd2017-01-16 06:59:19 -08003909void VerifyEmptyFlexfecConfig(
3910 const VideoSendStream::Config::Rtp::Flexfec& config) {
3911 EXPECT_EQ(-1, config.payload_type)
brandtr1e3dfbf2016-11-16 22:45:19 -08003912 << "Enabling FlexFEC requires rtpmap: flexfec negotiation.";
brandtr3d200bd2017-01-16 06:59:19 -08003913 EXPECT_EQ(0U, config.ssrc)
brandtr1cfbd602016-12-08 04:17:53 -08003914 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
brandtr1e3dfbf2016-11-16 22:45:19 -08003915 EXPECT_TRUE(config.protected_media_ssrcs.empty())
3916 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
3917}
3918
philipel266f0a42016-11-28 08:49:07 -08003919TEST_P(EndToEndTest, VerifyDefaultSendConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003920 VideoSendStream::Config default_send_config(nullptr);
Peter Boströmd7da1202015-06-05 14:09:38 +02003921 EXPECT_EQ(0, default_send_config.rtp.nack.rtp_history_ms)
3922 << "Enabling NACK require rtcp-fb: nack negotiation.";
3923 EXPECT_TRUE(default_send_config.rtp.rtx.ssrcs.empty())
3924 << "Enabling RTX requires rtpmap: rtx negotiation.";
3925 EXPECT_TRUE(default_send_config.rtp.extensions.empty())
3926 << "Enabling RTP extensions require negotiation.";
3927
3928 VerifyEmptyNackConfig(default_send_config.rtp.nack);
brandtrb5f2c3f2016-10-04 23:28:39 -07003929 VerifyEmptyUlpfecConfig(default_send_config.rtp.ulpfec);
brandtr1e3dfbf2016-11-16 22:45:19 -08003930 VerifyEmptyFlexfecConfig(default_send_config.rtp.flexfec);
Peter Boströmd7da1202015-06-05 14:09:38 +02003931}
3932
philipel266f0a42016-11-28 08:49:07 -08003933TEST_P(EndToEndTest, VerifyDefaultVideoReceiveConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003934 VideoReceiveStream::Config default_receive_config(nullptr);
pbosda903ea2015-10-02 02:36:56 -07003935 EXPECT_EQ(RtcpMode::kCompound, default_receive_config.rtp.rtcp_mode)
Peter Boströmd7da1202015-06-05 14:09:38 +02003936 << "Reduced-size RTCP require rtcp-rsize to be negotiated.";
3937 EXPECT_FALSE(default_receive_config.rtp.remb)
3938 << "REMB require rtcp-fb: goog-remb to be negotiated.";
3939 EXPECT_FALSE(
3940 default_receive_config.rtp.rtcp_xr.receiver_reference_time_report)
3941 << "RTCP XR settings require rtcp-xr to be negotiated.";
3942 EXPECT_TRUE(default_receive_config.rtp.rtx.empty())
3943 << "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