blob: 946d81d5df7405f5f53ea7a3df5053d60e59d9fe [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
philipel266f0a42016-11-28 08:49:07 -0800708TEST_P(EndToEndTest, CanReceiveFlexfec) {
brandtr1e3dfbf2016-11-16 22:45:19 -0800709 class FlexfecRenderObserver : public test::EndToEndTest,
710 public rtc::VideoSinkInterface<VideoFrame> {
711 public:
712 FlexfecRenderObserver()
brandtr35364632016-12-09 06:51:29 -0800713 : EndToEndTest(kDefaultTimeoutMs), random_(0xcafef00d1) {}
brandtr1e3dfbf2016-11-16 22:45:19 -0800714
715 size_t GetNumFlexfecStreams() const override { return 1; }
716
717 private:
718 Action OnSendRtp(const uint8_t* packet, size_t length) override {
719 rtc::CritScope lock(&crit_);
720 RTPHeader header;
721 EXPECT_TRUE(parser_->Parse(packet, length, &header));
722
723 uint8_t payload_type = header.payloadType;
724 if (payload_type != kFakeVideoSendPayloadType) {
725 EXPECT_EQ(kFlexfecPayloadType, payload_type);
726 }
727
brandtr35364632016-12-09 06:51:29 -0800728 // Is this a retransmitted media packet? From the perspective of FEC, this
729 // packet is then no longer dropped, so remove it from the list of
730 // dropped packets.
731 if (payload_type == kFakeVideoSendPayloadType) {
732 auto seq_num_it = dropped_sequence_numbers_.find(header.sequenceNumber);
733 if (seq_num_it != dropped_sequence_numbers_.end()) {
734 dropped_sequence_numbers_.erase(seq_num_it);
735 auto ts_it = dropped_timestamps_.find(header.timestamp);
736 EXPECT_NE(ts_it, dropped_timestamps_.end());
737 dropped_timestamps_.erase(ts_it);
738
739 return SEND_PACKET;
740 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800741 }
742
brandtr35364632016-12-09 06:51:29 -0800743 // Simulate 5% packet loss. Record what media packets, and corresponding
744 // timestamps, that were dropped.
745 if (random_.Rand(1, 100) <= 5) {
746 if (payload_type == kFakeVideoSendPayloadType) {
747 dropped_sequence_numbers_.insert(header.sequenceNumber);
748 dropped_timestamps_.insert(header.timestamp);
749 }
750
751 return DROP_PACKET;
brandtr1e3dfbf2016-11-16 22:45:19 -0800752 }
753
754 return SEND_PACKET;
755 }
756
757 void OnFrame(const VideoFrame& video_frame) override {
758 rtc::CritScope lock(&crit_);
759 // Rendering frame with timestamp of packet that was dropped -> FEC
760 // protection worked.
brandtr35364632016-12-09 06:51:29 -0800761 auto it = dropped_timestamps_.find(video_frame.timestamp());
762 if (it != dropped_timestamps_.end())
brandtr1e3dfbf2016-11-16 22:45:19 -0800763 observation_complete_.Set();
764 }
765
brandtr1e3dfbf2016-11-16 22:45:19 -0800766 void ModifyVideoConfigs(
767 VideoSendStream::Config* send_config,
768 std::vector<VideoReceiveStream::Config>* receive_configs,
769 VideoEncoderConfig* encoder_config) override {
770 (*receive_configs)[0].renderer = this;
771 }
772
773 void PerformTest() override {
774 EXPECT_TRUE(Wait())
775 << "Timed out waiting for dropped frames to be rendered.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000776 }
777
stefanf116bd02015-10-27 08:29:42 -0700778 rtc::CriticalSection crit_;
brandtr35364632016-12-09 06:51:29 -0800779 std::set<uint32_t> dropped_sequence_numbers_ GUARDED_BY(crit_);
philipel266f0a42016-11-28 08:49:07 -0800780 // Since several packets can have the same timestamp a multiset is used
781 // instead of a set.
brandtr35364632016-12-09 06:51:29 -0800782 std::multiset<uint32_t> dropped_timestamps_ GUARDED_BY(crit_);
783 Random random_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000784 } test;
785
stefane74eef12016-01-08 06:47:13 -0800786 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000787}
788
philipel266f0a42016-11-28 08:49:07 -0800789TEST_P(EndToEndTest, ReceivedUlpfecPacketsNotNacked) {
brandtr535830e2016-10-31 03:45:58 -0700790 class UlpfecNackObserver : public test::EndToEndTest {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000791 public:
brandtr535830e2016-10-31 03:45:58 -0700792 UlpfecNackObserver()
stefanf116bd02015-10-27 08:29:42 -0700793 : EndToEndTest(kDefaultTimeoutMs),
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000794 state_(kFirstPacket),
brandtr535830e2016-10-31 03:45:58 -0700795 ulpfec_sequence_number_(0),
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000796 has_last_sequence_number_(false),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200797 last_sequence_number_(0),
magjed509e4fe2016-11-18 01:34:11 -0800798 encoder_(VP8Encoder::Create()),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200799 decoder_(VP8Decoder::Create()) {}
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000800
801 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000802 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800803 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000804 RTPHeader header;
805 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000806
Stefan Holmer01b48882015-05-05 10:21:24 +0200807 int encapsulated_payload_type = -1;
808 if (header.payloadType == kRedPayloadType) {
809 encapsulated_payload_type =
810 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100811 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200812 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
813 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100814 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200815 }
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000816
817 if (has_last_sequence_number_ &&
818 !IsNewerSequenceNumber(header.sequenceNumber,
819 last_sequence_number_)) {
820 // Drop retransmitted packets.
821 return DROP_PACKET;
822 }
823 last_sequence_number_ = header.sequenceNumber;
824 has_last_sequence_number_ = true;
825
brandtr535830e2016-10-31 03:45:58 -0700826 bool ulpfec_packet = encapsulated_payload_type == kUlpfecPayloadType;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000827 switch (state_) {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000828 case kFirstPacket:
brandtr535830e2016-10-31 03:45:58 -0700829 state_ = kDropEveryOtherPacketUntilUlpfec;
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000830 break;
brandtr535830e2016-10-31 03:45:58 -0700831 case kDropEveryOtherPacketUntilUlpfec:
832 if (ulpfec_packet) {
833 state_ = kDropAllMediaPacketsUntilUlpfec;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000834 } else if (header.sequenceNumber % 2 == 0) {
835 return DROP_PACKET;
836 }
837 break;
brandtr535830e2016-10-31 03:45:58 -0700838 case kDropAllMediaPacketsUntilUlpfec:
839 if (!ulpfec_packet)
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000840 return DROP_PACKET;
brandtr535830e2016-10-31 03:45:58 -0700841 ulpfec_sequence_number_ = header.sequenceNumber;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200842 state_ = kDropOneMediaPacket;
843 break;
844 case kDropOneMediaPacket:
brandtr535830e2016-10-31 03:45:58 -0700845 if (ulpfec_packet)
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200846 return DROP_PACKET;
847 state_ = kPassOneMediaPacket;
848 return DROP_PACKET;
849 break;
850 case kPassOneMediaPacket:
brandtr535830e2016-10-31 03:45:58 -0700851 if (ulpfec_packet)
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200852 return DROP_PACKET;
853 // Pass one media packet after dropped packet after last FEC,
854 // otherwise receiver might never see a seq_no after
brandtr535830e2016-10-31 03:45:58 -0700855 // |ulpfec_sequence_number_|
856 state_ = kVerifyUlpfecPacketNotInNackList;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000857 break;
brandtr535830e2016-10-31 03:45:58 -0700858 case kVerifyUlpfecPacketNotInNackList:
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000859 // Continue to drop packets. Make sure no frame can be decoded.
brandtr535830e2016-10-31 03:45:58 -0700860 if (ulpfec_packet || header.sequenceNumber % 2 == 0)
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000861 return DROP_PACKET;
862 break;
863 }
864 return SEND_PACKET;
865 }
866
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000867 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800868 rtc::CritScope lock_(&crit_);
brandtr535830e2016-10-31 03:45:58 -0700869 if (state_ == kVerifyUlpfecPacketNotInNackList) {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000870 test::RtcpPacketParser rtcp_parser;
871 rtcp_parser.Parse(packet, length);
Danil Chapovalovba6f7be2016-09-02 18:29:10 +0200872 const std::vector<uint16_t>& nacks = rtcp_parser.nack()->packet_ids();
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200873 EXPECT_TRUE(std::find(nacks.begin(), nacks.end(),
brandtr535830e2016-10-31 03:45:58 -0700874 ulpfec_sequence_number_) == nacks.end())
875 << "Got nack for ULPFEC packet";
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000876 if (!nacks.empty() &&
brandtr535830e2016-10-31 03:45:58 -0700877 IsNewerSequenceNumber(nacks.back(), ulpfec_sequence_number_)) {
Peter Boström5811a392015-12-10 13:02:50 +0100878 observation_complete_.Set();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000879 }
880 }
881 return SEND_PACKET;
882 }
883
stefane74eef12016-01-08 06:47:13 -0800884 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
885 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
886 // Configure some network delay.
887 const int kNetworkDelayMs = 50;
888 FakeNetworkPipe::Config config;
889 config.queue_delay_ms = kNetworkDelayMs;
890 return new test::PacketTransport(sender_call, this,
891 test::PacketTransport::kSender, config);
892 }
893
Stefan Holmere5904162015-03-26 11:11:06 +0100894 // TODO(holmer): Investigate why we don't send FEC packets when the bitrate
895 // is 10 kbps.
896 Call::Config GetSenderCallConfig() override {
skvlad11a9cbf2016-10-07 11:53:05 -0700897 Call::Config config(&event_log_);
Stefan Holmere5904162015-03-26 11:11:06 +0100898 const int kMinBitrateBps = 30000;
899 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
900 return config;
901 }
902
stefanff483612015-12-21 03:14:00 -0800903 void ModifyVideoConfigs(
904 VideoSendStream::Config* send_config,
905 std::vector<VideoReceiveStream::Config>* receive_configs,
906 VideoEncoderConfig* encoder_config) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000907 // Configure hybrid NACK/FEC.
908 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
brandtrb5f2c3f2016-10-04 23:28:39 -0700909 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
910 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200911 // Set codec to VP8, otherwise NACK/FEC hybrid will be disabled.
912 send_config->encoder_settings.encoder = encoder_.get();
913 send_config->encoder_settings.payload_name = "VP8";
914 send_config->encoder_settings.payload_type = kFakeVideoSendPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200915
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000916 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
brandtrb5f2c3f2016-10-04 23:28:39 -0700917 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
918 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200919
920 (*receive_configs)[0].decoders.resize(1);
921 (*receive_configs)[0].decoders[0].payload_type =
922 send_config->encoder_settings.payload_type;
923 (*receive_configs)[0].decoders[0].payload_name =
924 send_config->encoder_settings.payload_name;
925 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000926 }
927
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000928 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100929 EXPECT_TRUE(Wait())
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000930 << "Timed out while waiting for FEC packets to be received.";
931 }
932
933 enum {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000934 kFirstPacket,
brandtr535830e2016-10-31 03:45:58 -0700935 kDropEveryOtherPacketUntilUlpfec,
936 kDropAllMediaPacketsUntilUlpfec,
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200937 kDropOneMediaPacket,
938 kPassOneMediaPacket,
brandtr535830e2016-10-31 03:45:58 -0700939 kVerifyUlpfecPacketNotInNackList,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000940 } state_;
941
stefan608213e2015-11-01 14:56:10 -0800942 rtc::CriticalSection crit_;
brandtr535830e2016-10-31 03:45:58 -0700943 uint16_t ulpfec_sequence_number_ GUARDED_BY(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000944 bool has_last_sequence_number_;
945 uint16_t last_sequence_number_;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200946 std::unique_ptr<webrtc::VideoEncoder> encoder_;
947 std::unique_ptr<webrtc::VideoDecoder> decoder_;
stefanf116bd02015-10-27 08:29:42 -0700948 } test;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000949
stefane74eef12016-01-08 06:47:13 -0800950 RunBaseTest(&test);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000951}
952
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000953// This test drops second RTP packet with a marker bit set, makes sure it's
954// retransmitted and renders. Retransmission SSRCs are also checked.
Peter Boström39593972016-02-15 11:27:15 +0100955void EndToEndTest::DecodesRetransmittedFrame(bool enable_rtx, bool enable_red) {
Peter Boström67680c12016-02-17 11:10:04 +0100956 static const int kDroppedFrameNumber = 10;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000957 class RetransmissionObserver : public test::EndToEndTest,
958 public I420FrameCallback {
959 public:
Peter Boström39593972016-02-15 11:27:15 +0100960 RetransmissionObserver(bool enable_rtx, bool enable_red)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000961 : EndToEndTest(kDefaultTimeoutMs),
Peter Boström39593972016-02-15 11:27:15 +0100962 payload_type_(GetPayloadType(false, enable_red)),
963 retransmission_ssrc_(enable_rtx ? kSendRtxSsrcs[0]
964 : kVideoSendSsrcs[0]),
965 retransmission_payload_type_(GetPayloadType(enable_rtx, enable_red)),
magjed509e4fe2016-11-18 01:34:11 -0800966 encoder_(VP8Encoder::Create()),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000967 marker_bits_observed_(0),
danilchap192717e2016-07-25 08:20:51 -0700968 retransmitted_timestamp_(0) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000969
970 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000971 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700972 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000973 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000974 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000975
Peter Boström67680c12016-02-17 11:10:04 +0100976 // Ignore padding-only packets over RTX.
977 if (header.payloadType != payload_type_) {
978 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
979 if (length == header.headerLength + header.paddingLength)
980 return SEND_PACKET;
Stefan Holmer586b19b2015-09-18 11:14:31 +0200981 }
Peter Boström67680c12016-02-17 11:10:04 +0100982
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000983 if (header.timestamp == retransmitted_timestamp_) {
984 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
985 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000986 return SEND_PACKET;
987 }
988
Stefan Holmer586b19b2015-09-18 11:14:31 +0200989 // Found the final packet of the frame to inflict loss to, drop this and
990 // expect a retransmission.
danilchapfdd381c2016-07-25 04:03:20 -0700991 if (header.payloadType == payload_type_ && header.markerBit &&
992 ++marker_bits_observed_ == kDroppedFrameNumber) {
Danil Chapovalov18c65a42016-06-29 15:29:34 +0200993 // This should be the only dropped packet.
994 EXPECT_EQ(0u, retransmitted_timestamp_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000995 retransmitted_timestamp_ = header.timestamp;
danilchap192717e2016-07-25 08:20:51 -0700996 if (std::find(rendered_timestamps_.begin(), rendered_timestamps_.end(),
997 retransmitted_timestamp_) != rendered_timestamps_.end()) {
998 // Frame was rendered before last packet was scheduled for sending.
999 // This is extremly rare but possible scenario because prober able to
1000 // resend packet before it was send.
1001 // TODO(danilchap): Remove this corner case when prober would not be
1002 // able to sneak in between packet saved to history for resending and
1003 // pacer notified about existance of that packet for sending.
1004 // See https://bugs.chromium.org/p/webrtc/issues/detail?id=5540 for
1005 // details.
1006 observation_complete_.Set();
1007 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001008 return DROP_PACKET;
1009 }
1010
1011 return SEND_PACKET;
1012 }
1013
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001014 void FrameCallback(VideoFrame* frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001015 rtc::CritScope lock(&crit_);
danilchap192717e2016-07-25 08:20:51 -07001016 if (frame->timestamp() == retransmitted_timestamp_)
Peter Boström5811a392015-12-10 13:02:50 +01001017 observation_complete_.Set();
danilchap192717e2016-07-25 08:20:51 -07001018 rendered_timestamps_.push_back(frame->timestamp());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001019 }
1020
stefanff483612015-12-21 03:14:00 -08001021 void ModifyVideoConfigs(
1022 VideoSendStream::Config* send_config,
1023 std::vector<VideoReceiveStream::Config>* receive_configs,
1024 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001025 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001026 (*receive_configs)[0].pre_render_callback = this;
1027 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
Shao Changbine62202f2015-04-21 20:24:50 +08001028
1029 if (payload_type_ == kRedPayloadType) {
brandtrb5f2c3f2016-10-04 23:28:39 -07001030 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
1031 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +01001032 if (retransmission_ssrc_ == kSendRtxSsrcs[0])
brandtrb5f2c3f2016-10-04 23:28:39 -07001033 send_config->rtp.ulpfec.red_rtx_payload_type = kRtxRedPayloadType;
1034 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type =
1035 send_config->rtp.ulpfec.ulpfec_payload_type;
1036 (*receive_configs)[0].rtp.ulpfec.red_payload_type =
1037 send_config->rtp.ulpfec.red_payload_type;
1038 (*receive_configs)[0].rtp.ulpfec.red_rtx_payload_type =
1039 send_config->rtp.ulpfec.red_rtx_payload_type;
Shao Changbine62202f2015-04-21 20:24:50 +08001040 }
1041
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001042 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
1043 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001044 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +01001045 (*receive_configs)[0].rtp.rtx[payload_type_].ssrc = kSendRtxSsrcs[0];
1046 (*receive_configs)[0].rtp.rtx[payload_type_].payload_type =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001047 kSendRtxPayloadType;
1048 }
Peter Boström39593972016-02-15 11:27:15 +01001049 // Configure encoding and decoding with VP8, since generic packetization
1050 // doesn't support FEC with NACK.
kwibergaf476c72016-11-28 15:21:39 -08001051 RTC_DCHECK_EQ(1, (*receive_configs)[0].decoders.size());
Peter Boström39593972016-02-15 11:27:15 +01001052 send_config->encoder_settings.encoder = encoder_.get();
1053 send_config->encoder_settings.payload_name = "VP8";
1054 (*receive_configs)[0].decoders[0].payload_name = "VP8";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001055 }
1056
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001057 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001058 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001059 << "Timed out while waiting for retransmission to render.";
1060 }
1061
Shao Changbine62202f2015-04-21 20:24:50 +08001062 int GetPayloadType(bool use_rtx, bool use_red) {
Stefan Holmer10880012016-02-03 13:29:59 +01001063 if (use_red) {
1064 if (use_rtx)
1065 return kRtxRedPayloadType;
1066 return kRedPayloadType;
1067 }
1068 if (use_rtx)
1069 return kSendRtxPayloadType;
1070 return kFakeVideoSendPayloadType;
Shao Changbine62202f2015-04-21 20:24:50 +08001071 }
1072
stefanf116bd02015-10-27 08:29:42 -07001073 rtc::CriticalSection crit_;
Shao Changbine62202f2015-04-21 20:24:50 +08001074 const int payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001075 const uint32_t retransmission_ssrc_;
1076 const int retransmission_payload_type_;
kwiberg27f982b2016-03-01 11:52:33 -08001077 std::unique_ptr<VideoEncoder> encoder_;
Peter Boström39593972016-02-15 11:27:15 +01001078 const std::string payload_name_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001079 int marker_bits_observed_;
stefanf116bd02015-10-27 08:29:42 -07001080 uint32_t retransmitted_timestamp_ GUARDED_BY(&crit_);
danilchap192717e2016-07-25 08:20:51 -07001081 std::vector<uint32_t> rendered_timestamps_ GUARDED_BY(&crit_);
Peter Boström39593972016-02-15 11:27:15 +01001082 } test(enable_rtx, enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001083
stefane74eef12016-01-08 06:47:13 -08001084 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001085}
1086
philipel266f0a42016-11-28 08:49:07 -08001087TEST_P(EndToEndTest, DecodesRetransmittedFrame) {
Shao Changbine62202f2015-04-21 20:24:50 +08001088 DecodesRetransmittedFrame(false, false);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001089}
1090
philipel266f0a42016-11-28 08:49:07 -08001091TEST_P(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +08001092 DecodesRetransmittedFrame(true, false);
1093}
1094
philipel266f0a42016-11-28 08:49:07 -08001095TEST_P(EndToEndTest, DecodesRetransmittedFrameByRed) {
Shao Changbine62202f2015-04-21 20:24:50 +08001096 DecodesRetransmittedFrame(false, true);
1097}
1098
philipel266f0a42016-11-28 08:49:07 -08001099TEST_P(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +08001100 DecodesRetransmittedFrame(true, true);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001101}
1102
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001103void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
1104 static const int kPacketsToDrop = 1;
1105
nisse7ade7b32016-03-23 04:48:10 -07001106 class PliObserver : public test::EndToEndTest,
1107 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001108 public:
1109 explicit PliObserver(int rtp_history_ms)
1110 : EndToEndTest(kLongTimeoutMs),
1111 rtp_history_ms_(rtp_history_ms),
1112 nack_enabled_(rtp_history_ms > 0),
1113 highest_dropped_timestamp_(0),
1114 frames_to_drop_(0),
1115 received_pli_(false) {}
1116
1117 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001118 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001119 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001120 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001121 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001122
1123 // Drop all retransmitted packets to force a PLI.
1124 if (header.timestamp <= highest_dropped_timestamp_)
1125 return DROP_PACKET;
1126
1127 if (frames_to_drop_ > 0) {
1128 highest_dropped_timestamp_ = header.timestamp;
1129 --frames_to_drop_;
1130 return DROP_PACKET;
1131 }
1132
1133 return SEND_PACKET;
1134 }
1135
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001136 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001137 rtc::CritScope lock(&crit_);
danilchap3dc929e2016-11-02 08:21:59 -07001138 test::RtcpPacketParser parser;
1139 EXPECT_TRUE(parser.Parse(packet, length));
1140 if (!nack_enabled_)
1141 EXPECT_EQ(0, parser.nack()->num_packets());
1142 if (parser.pli()->num_packets() > 0)
1143 received_pli_ = true;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001144 return SEND_PACKET;
1145 }
1146
nisseeb83a1a2016-03-21 01:27:56 -07001147 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001148 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001149 if (received_pli_ &&
1150 video_frame.timestamp() > highest_dropped_timestamp_) {
Peter Boström5811a392015-12-10 13:02:50 +01001151 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001152 }
1153 if (!received_pli_)
1154 frames_to_drop_ = kPacketsToDrop;
1155 }
1156
stefanff483612015-12-21 03:14:00 -08001157 void ModifyVideoConfigs(
1158 VideoSendStream::Config* send_config,
1159 std::vector<VideoReceiveStream::Config>* receive_configs,
1160 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001161 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001162 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
1163 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001164 }
1165
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001166 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001167 EXPECT_TRUE(Wait()) << "Timed out waiting for PLI to be "
1168 "received and a frame to be "
1169 "rendered afterwards.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001170 }
1171
stefanf116bd02015-10-27 08:29:42 -07001172 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001173 int rtp_history_ms_;
1174 bool nack_enabled_;
stefanf116bd02015-10-27 08:29:42 -07001175 uint32_t highest_dropped_timestamp_ GUARDED_BY(&crit_);
1176 int frames_to_drop_ GUARDED_BY(&crit_);
1177 bool received_pli_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001178 } test(rtp_history_ms);
1179
stefane74eef12016-01-08 06:47:13 -08001180 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001181}
1182
philipel266f0a42016-11-28 08:49:07 -08001183TEST_P(EndToEndTest, ReceivesPliAndRecoversWithNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001184 ReceivesPliAndRecovers(1000);
1185}
1186
philipel266f0a42016-11-28 08:49:07 -08001187TEST_P(EndToEndTest, ReceivesPliAndRecoversWithoutNack) {
1188 // This test makes no sense for the new video jitter buffer.
1189 if (GetParam() == new_jb_enabled)
1190 return;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001191 ReceivesPliAndRecovers(0);
1192}
1193
philipel266f0a42016-11-28 08:49:07 -08001194TEST_P(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001195 class PacketInputObserver : public PacketReceiver {
1196 public:
1197 explicit PacketInputObserver(PacketReceiver* receiver)
Peter Boström5811a392015-12-10 13:02:50 +01001198 : receiver_(receiver), delivered_packet_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001199
Peter Boström5811a392015-12-10 13:02:50 +01001200 bool Wait() { return delivered_packet_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001201
1202 private:
stefan68786d22015-09-08 05:36:15 -07001203 DeliveryStatus DeliverPacket(MediaType media_type,
1204 const uint8_t* packet,
1205 size_t length,
1206 const PacketTime& packet_time) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001207 if (RtpHeaderParser::IsRtcp(packet, length)) {
stefan68786d22015-09-08 05:36:15 -07001208 return receiver_->DeliverPacket(media_type, packet, length,
1209 packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001210 } else {
1211 DeliveryStatus delivery_status =
stefan68786d22015-09-08 05:36:15 -07001212 receiver_->DeliverPacket(media_type, packet, length, packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001213 EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
Peter Boström5811a392015-12-10 13:02:50 +01001214 delivered_packet_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001215 return delivery_status;
1216 }
1217 }
1218
1219 PacketReceiver* receiver_;
Peter Boström5811a392015-12-10 13:02:50 +01001220 rtc::Event delivered_packet_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001221 };
1222
skvlad11a9cbf2016-10-07 11:53:05 -07001223 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -07001224
stefanf116bd02015-10-27 08:29:42 -07001225 test::DirectTransport send_transport(sender_call_.get());
1226 test::DirectTransport receive_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001227 PacketInputObserver input_observer(receiver_call_->Receiver());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001228 send_transport.SetReceiver(&input_observer);
1229 receive_transport.SetReceiver(sender_call_->Receiver());
1230
brandtr841de6a2016-11-15 07:10:52 -08001231 CreateSendConfig(1, 0, 0, &send_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001232 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001233
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001234 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07001235 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
1236 kDefaultHeight);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001237 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001238
stefanff483612015-12-21 03:14:00 -08001239 receiver_call_->DestroyVideoReceiveStream(video_receive_streams_[0]);
1240 video_receive_streams_.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001241
1242 // Wait() waits for a received packet.
Peter Boström5811a392015-12-10 13:02:50 +01001243 EXPECT_TRUE(input_observer.Wait());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001244
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001245 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001246
1247 DestroyStreams();
1248
1249 send_transport.StopSending();
1250 receive_transport.StopSending();
1251}
1252
pbosda903ea2015-10-02 02:36:56 -07001253void EndToEndTest::RespectsRtcpMode(RtcpMode rtcp_mode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001254 static const int kNumCompoundRtcpPacketsToObserve = 10;
1255 class RtcpModeObserver : public test::EndToEndTest {
1256 public:
pbosda903ea2015-10-02 02:36:56 -07001257 explicit RtcpModeObserver(RtcpMode rtcp_mode)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001258 : EndToEndTest(kDefaultTimeoutMs),
1259 rtcp_mode_(rtcp_mode),
1260 sent_rtp_(0),
1261 sent_rtcp_(0) {}
1262
1263 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001264 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001265 if (++sent_rtp_ % 3 == 0)
1266 return DROP_PACKET;
1267
1268 return SEND_PACKET;
1269 }
1270
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001271 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001272 ++sent_rtcp_;
danilchap3dc929e2016-11-02 08:21:59 -07001273 test::RtcpPacketParser parser;
1274 EXPECT_TRUE(parser.Parse(packet, length));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001275
danilchap3dc929e2016-11-02 08:21:59 -07001276 EXPECT_EQ(0, parser.sender_report()->num_packets());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001277
1278 switch (rtcp_mode_) {
pbosda903ea2015-10-02 02:36:56 -07001279 case RtcpMode::kCompound:
danilchap3dc929e2016-11-02 08:21:59 -07001280 if (parser.receiver_report()->num_packets() == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001281 ADD_FAILURE() << "Received RTCP packet without receiver report for "
pbosda903ea2015-10-02 02:36:56 -07001282 "RtcpMode::kCompound.";
Peter Boström5811a392015-12-10 13:02:50 +01001283 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001284 }
1285
1286 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
Peter Boström5811a392015-12-10 13:02:50 +01001287 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001288
1289 break;
pbosda903ea2015-10-02 02:36:56 -07001290 case RtcpMode::kReducedSize:
danilchap3dc929e2016-11-02 08:21:59 -07001291 if (parser.receiver_report()->num_packets() == 0)
Peter Boström5811a392015-12-10 13:02:50 +01001292 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001293 break;
pbosda903ea2015-10-02 02:36:56 -07001294 case RtcpMode::kOff:
1295 RTC_NOTREACHED();
1296 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001297 }
1298
1299 return SEND_PACKET;
1300 }
1301
stefanff483612015-12-21 03:14:00 -08001302 void ModifyVideoConfigs(
1303 VideoSendStream::Config* send_config,
1304 std::vector<VideoReceiveStream::Config>* receive_configs,
1305 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001306 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001307 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1308 (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001309 }
1310
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001311 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001312 EXPECT_TRUE(Wait())
pbosda903ea2015-10-02 02:36:56 -07001313 << (rtcp_mode_ == RtcpMode::kCompound
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001314 ? "Timed out before observing enough compound packets."
1315 : "Timed out before receiving a non-compound RTCP packet.");
1316 }
1317
pbosda903ea2015-10-02 02:36:56 -07001318 RtcpMode rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001319 int sent_rtp_;
1320 int sent_rtcp_;
1321 } test(rtcp_mode);
1322
stefane74eef12016-01-08 06:47:13 -08001323 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001324}
1325
philipel266f0a42016-11-28 08:49:07 -08001326TEST_P(EndToEndTest, UsesRtcpCompoundMode) {
pbosda903ea2015-10-02 02:36:56 -07001327 RespectsRtcpMode(RtcpMode::kCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001328}
1329
philipel266f0a42016-11-28 08:49:07 -08001330TEST_P(EndToEndTest, UsesRtcpReducedSizeMode) {
pbosda903ea2015-10-02 02:36:56 -07001331 RespectsRtcpMode(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001332}
1333
1334// Test sets up a Call multiple senders with different resolutions and SSRCs.
1335// Another is set up to receive all three of these with different renderers.
sprang867fb522015-08-03 04:38:41 -07001336class MultiStreamTest {
1337 public:
1338 static const size_t kNumStreams = 3;
1339 struct CodecSettings {
1340 uint32_t ssrc;
1341 int width;
1342 int height;
1343 } codec_settings[kNumStreams];
1344
1345 MultiStreamTest() {
1346 // TODO(sprang): Cleanup when msvc supports explicit initializers for array.
1347 codec_settings[0] = {1, 640, 480};
1348 codec_settings[1] = {2, 320, 240};
1349 codec_settings[2] = {3, 240, 160};
1350 }
1351
1352 virtual ~MultiStreamTest() {}
1353
1354 void RunTest() {
skvlad11a9cbf2016-10-07 11:53:05 -07001355 webrtc::RtcEventLogNullImpl event_log;
1356 Call::Config config(&event_log);
1357 std::unique_ptr<Call> sender_call(Call::Create(config));
1358 std::unique_ptr<Call> receiver_call(Call::Create(config));
kwiberg27f982b2016-03-01 11:52:33 -08001359 std::unique_ptr<test::DirectTransport> sender_transport(
stefanf116bd02015-10-27 08:29:42 -07001360 CreateSendTransport(sender_call.get()));
kwiberg27f982b2016-03-01 11:52:33 -08001361 std::unique_ptr<test::DirectTransport> receiver_transport(
stefanf116bd02015-10-27 08:29:42 -07001362 CreateReceiveTransport(receiver_call.get()));
sprang867fb522015-08-03 04:38:41 -07001363 sender_transport->SetReceiver(receiver_call->Receiver());
1364 receiver_transport->SetReceiver(sender_call->Receiver());
1365
kwiberg27f982b2016-03-01 11:52:33 -08001366 std::unique_ptr<VideoEncoder> encoders[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001367 for (size_t i = 0; i < kNumStreams; ++i)
magjed509e4fe2016-11-18 01:34:11 -08001368 encoders[i].reset(VP8Encoder::Create());
sprang867fb522015-08-03 04:38:41 -07001369
1370 VideoSendStream* send_streams[kNumStreams];
1371 VideoReceiveStream* receive_streams[kNumStreams];
1372
1373 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
kwiberg4a206a92016-03-31 10:24:26 -07001374 std::vector<std::unique_ptr<VideoDecoder>> allocated_decoders;
sprang867fb522015-08-03 04:38:41 -07001375 for (size_t i = 0; i < kNumStreams; ++i) {
1376 uint32_t ssrc = codec_settings[i].ssrc;
1377 int width = codec_settings[i].width;
1378 int height = codec_settings[i].height;
1379
solenberg4fbae2b2015-08-28 04:07:10 -07001380 VideoSendStream::Config send_config(sender_transport.get());
sprang867fb522015-08-03 04:38:41 -07001381 send_config.rtp.ssrcs.push_back(ssrc);
1382 send_config.encoder_settings.encoder = encoders[i].get();
1383 send_config.encoder_settings.payload_name = "VP8";
1384 send_config.encoder_settings.payload_type = 124;
1385 VideoEncoderConfig encoder_config;
perkjfa10b552016-10-02 23:45:26 -07001386 test::FillEncoderConfiguration(1, &encoder_config);
1387 encoder_config.max_bitrate_bps = 100000;
sprang867fb522015-08-03 04:38:41 -07001388
1389 UpdateSendConfig(i, &send_config, &encoder_config, &frame_generators[i]);
1390
perkj26091b12016-09-01 01:17:40 -07001391 send_streams[i] = sender_call->CreateVideoSendStream(
1392 send_config.Copy(), encoder_config.Copy());
sprang867fb522015-08-03 04:38:41 -07001393 send_streams[i]->Start();
1394
solenberg4fbae2b2015-08-28 04:07:10 -07001395 VideoReceiveStream::Config receive_config(receiver_transport.get());
sprang867fb522015-08-03 04:38:41 -07001396 receive_config.rtp.remote_ssrc = ssrc;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001397 receive_config.rtp.local_ssrc = test::CallTest::kReceiverLocalVideoSsrc;
sprang867fb522015-08-03 04:38:41 -07001398 VideoReceiveStream::Decoder decoder =
1399 test::CreateMatchingDecoder(send_config.encoder_settings);
kwiberg4a206a92016-03-31 10:24:26 -07001400 allocated_decoders.push_back(
1401 std::unique_ptr<VideoDecoder>(decoder.decoder));
sprang867fb522015-08-03 04:38:41 -07001402 receive_config.decoders.push_back(decoder);
1403
1404 UpdateReceiveConfig(i, &receive_config);
1405
1406 receive_streams[i] =
Tommi733b5472016-06-10 17:58:01 +02001407 receiver_call->CreateVideoReceiveStream(std::move(receive_config));
sprang867fb522015-08-03 04:38:41 -07001408 receive_streams[i]->Start();
1409
1410 frame_generators[i] = test::FrameGeneratorCapturer::Create(
perkja49cbd32016-09-16 07:53:41 -07001411 width, height, 30, Clock::GetRealTimeClock());
perkj803d97f2016-11-01 11:45:46 -07001412 send_streams[i]->SetSource(
1413 frame_generators[i],
1414 VideoSendStream::DegradationPreference::kBalanced);
sprang867fb522015-08-03 04:38:41 -07001415 frame_generators[i]->Start();
1416 }
1417
1418 Wait();
1419
1420 for (size_t i = 0; i < kNumStreams; ++i) {
1421 frame_generators[i]->Stop();
1422 sender_call->DestroyVideoSendStream(send_streams[i]);
1423 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1424 delete frame_generators[i];
1425 }
1426
1427 sender_transport->StopSending();
1428 receiver_transport->StopSending();
1429 }
1430
1431 protected:
1432 virtual void Wait() = 0;
1433 // Note: frame_generator is a point-to-pointer, since the actual instance
1434 // hasn't been created at the time of this call. Only when packets/frames
1435 // start flowing should this be dereferenced.
1436 virtual void UpdateSendConfig(
1437 size_t stream_index,
1438 VideoSendStream::Config* send_config,
1439 VideoEncoderConfig* encoder_config,
1440 test::FrameGeneratorCapturer** frame_generator) {}
1441 virtual void UpdateReceiveConfig(size_t stream_index,
1442 VideoReceiveStream::Config* receive_config) {
1443 }
stefanf116bd02015-10-27 08:29:42 -07001444 virtual test::DirectTransport* CreateSendTransport(Call* sender_call) {
1445 return new test::DirectTransport(sender_call);
sprang867fb522015-08-03 04:38:41 -07001446 }
stefanf116bd02015-10-27 08:29:42 -07001447 virtual test::DirectTransport* CreateReceiveTransport(Call* receiver_call) {
1448 return new test::DirectTransport(receiver_call);
sprang867fb522015-08-03 04:38:41 -07001449 }
1450};
1451
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001452// Each renderer verifies that it receives the expected resolution, and as soon
1453// as every renderer has received a frame, the test finishes.
philipel266f0a42016-11-28 08:49:07 -08001454TEST_P(EndToEndTest, SendsAndReceivesMultipleStreams) {
nisse7ade7b32016-03-23 04:48:10 -07001455 class VideoOutputObserver : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001456 public:
sprang867fb522015-08-03 04:38:41 -07001457 VideoOutputObserver(const MultiStreamTest::CodecSettings& settings,
1458 uint32_t ssrc,
1459 test::FrameGeneratorCapturer** frame_generator)
1460 : settings_(settings),
1461 ssrc_(ssrc),
1462 frame_generator_(frame_generator),
Peter Boström5811a392015-12-10 13:02:50 +01001463 done_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001464
nisseeb83a1a2016-03-21 01:27:56 -07001465 void OnFrame(const VideoFrame& video_frame) override {
sprang867fb522015-08-03 04:38:41 -07001466 EXPECT_EQ(settings_.width, video_frame.width());
1467 EXPECT_EQ(settings_.height, video_frame.height());
1468 (*frame_generator_)->Stop();
Peter Boström5811a392015-12-10 13:02:50 +01001469 done_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001470 }
1471
sprang867fb522015-08-03 04:38:41 -07001472 uint32_t Ssrc() { return ssrc_; }
1473
Peter Boström5811a392015-12-10 13:02:50 +01001474 bool Wait() { return done_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001475
1476 private:
sprang867fb522015-08-03 04:38:41 -07001477 const MultiStreamTest::CodecSettings& settings_;
1478 const uint32_t ssrc_;
1479 test::FrameGeneratorCapturer** const frame_generator_;
Peter Boström5811a392015-12-10 13:02:50 +01001480 rtc::Event done_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001481 };
1482
sprang867fb522015-08-03 04:38:41 -07001483 class Tester : public MultiStreamTest {
1484 public:
1485 Tester() {}
1486 virtual ~Tester() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001487
sprang867fb522015-08-03 04:38:41 -07001488 protected:
1489 void Wait() override {
1490 for (const auto& observer : observers_) {
Peter Boström5811a392015-12-10 13:02:50 +01001491 EXPECT_TRUE(observer->Wait()) << "Time out waiting for from on ssrc "
1492 << observer->Ssrc();
sprang867fb522015-08-03 04:38:41 -07001493 }
1494 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001495
sprang867fb522015-08-03 04:38:41 -07001496 void UpdateSendConfig(
1497 size_t stream_index,
1498 VideoSendStream::Config* send_config,
1499 VideoEncoderConfig* encoder_config,
1500 test::FrameGeneratorCapturer** frame_generator) override {
1501 observers_[stream_index].reset(new VideoOutputObserver(
1502 codec_settings[stream_index], send_config->rtp.ssrcs.front(),
1503 frame_generator));
1504 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001505
sprang867fb522015-08-03 04:38:41 -07001506 void UpdateReceiveConfig(
1507 size_t stream_index,
1508 VideoReceiveStream::Config* receive_config) override {
1509 receive_config->renderer = observers_[stream_index].get();
1510 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001511
sprang867fb522015-08-03 04:38:41 -07001512 private:
kwiberg27f982b2016-03-01 11:52:33 -08001513 std::unique_ptr<VideoOutputObserver> observers_[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001514 } tester;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001515
sprang867fb522015-08-03 04:38:41 -07001516 tester.RunTest();
1517}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001518
philipel266f0a42016-11-28 08:49:07 -08001519TEST_P(EndToEndTest, AssignsTransportSequenceNumbers) {
sprang867fb522015-08-03 04:38:41 -07001520 static const int kExtensionId = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001521
sprang867fb522015-08-03 04:38:41 -07001522 class RtpExtensionHeaderObserver : public test::DirectTransport {
1523 public:
stefanf116bd02015-10-27 08:29:42 -07001524 RtpExtensionHeaderObserver(Call* sender_call,
1525 const uint32_t& first_media_ssrc,
sprang861c55e2015-10-16 10:01:21 -07001526 const std::map<uint32_t, uint32_t>& ssrc_map)
stefanf116bd02015-10-27 08:29:42 -07001527 : DirectTransport(sender_call),
Peter Boström5811a392015-12-10 13:02:50 +01001528 done_(false, false),
sprang867fb522015-08-03 04:38:41 -07001529 parser_(RtpHeaderParser::Create()),
sprang861c55e2015-10-16 10:01:21 -07001530 first_media_ssrc_(first_media_ssrc),
1531 rtx_to_media_ssrcs_(ssrc_map),
sprang867fb522015-08-03 04:38:41 -07001532 padding_observed_(false),
sprang861c55e2015-10-16 10:01:21 -07001533 rtx_padding_observed_(false),
1534 retransmit_observed_(false),
1535 started_(false) {
sprang867fb522015-08-03 04:38:41 -07001536 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
1537 kExtensionId);
1538 }
1539 virtual ~RtpExtensionHeaderObserver() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001540
stefan1d8a5062015-10-02 03:39:33 -07001541 bool SendRtp(const uint8_t* data,
1542 size_t length,
1543 const PacketOptions& options) override {
sprang861c55e2015-10-16 10:01:21 -07001544 {
1545 rtc::CritScope cs(&lock_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001546
Erik Språng8d629712015-08-04 16:24:03 +02001547 if (IsDone())
sprang861c55e2015-10-16 10:01:21 -07001548 return false;
1549
1550 if (started_) {
1551 RTPHeader header;
1552 EXPECT_TRUE(parser_->Parse(data, length, &header));
1553 bool drop_packet = false;
1554
1555 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
1556 EXPECT_EQ(options.packet_id,
1557 header.extension.transportSequenceNumber);
1558 if (!streams_observed_.empty()) {
1559 // Unwrap packet id and verify uniqueness.
1560 int64_t packet_id = unwrapper_.Unwrap(options.packet_id);
1561 EXPECT_TRUE(received_packed_ids_.insert(packet_id).second);
1562 }
1563
1564 // Drop (up to) every 17th packet, so we get retransmits.
1565 // Only drop media, and not on the first stream (otherwise it will be
1566 // hard to distinguish from padding, which is always sent on the first
1567 // stream).
1568 if (header.payloadType != kSendRtxPayloadType &&
1569 header.ssrc != first_media_ssrc_ &&
1570 header.extension.transportSequenceNumber % 17 == 0) {
1571 dropped_seq_[header.ssrc].insert(header.sequenceNumber);
1572 drop_packet = true;
1573 }
1574
1575 size_t payload_length =
1576 length - (header.headerLength + header.paddingLength);
1577 if (payload_length == 0) {
1578 padding_observed_ = true;
1579 } else if (header.payloadType == kSendRtxPayloadType) {
1580 uint16_t original_sequence_number =
1581 ByteReader<uint16_t>::ReadBigEndian(&data[header.headerLength]);
1582 uint32_t original_ssrc =
1583 rtx_to_media_ssrcs_.find(header.ssrc)->second;
1584 std::set<uint16_t>* seq_no_map = &dropped_seq_[original_ssrc];
1585 auto it = seq_no_map->find(original_sequence_number);
1586 if (it != seq_no_map->end()) {
1587 retransmit_observed_ = true;
1588 seq_no_map->erase(it);
1589 } else {
1590 rtx_padding_observed_ = true;
1591 }
1592 } else {
1593 streams_observed_.insert(header.ssrc);
1594 }
1595
1596 if (IsDone())
Peter Boström5811a392015-12-10 13:02:50 +01001597 done_.Set();
sprang861c55e2015-10-16 10:01:21 -07001598
1599 if (drop_packet)
1600 return true;
1601 }
sprang867fb522015-08-03 04:38:41 -07001602 }
sprang861c55e2015-10-16 10:01:21 -07001603
stefan1d8a5062015-10-02 03:39:33 -07001604 return test::DirectTransport::SendRtp(data, length, options);
sprang867fb522015-08-03 04:38:41 -07001605 }
1606
Erik Språng8d629712015-08-04 16:24:03 +02001607 bool IsDone() {
sprang861c55e2015-10-16 10:01:21 -07001608 bool observed_types_ok =
1609 streams_observed_.size() == MultiStreamTest::kNumStreams &&
1610 padding_observed_ && retransmit_observed_ && rtx_padding_observed_;
1611 if (!observed_types_ok)
1612 return false;
1613 // We should not have any gaps in the sequence number range.
1614 size_t seqno_range =
1615 *received_packed_ids_.rbegin() - *received_packed_ids_.begin() + 1;
1616 return seqno_range == received_packed_ids_.size();
Erik Språng8d629712015-08-04 16:24:03 +02001617 }
1618
Peter Boström5811a392015-12-10 13:02:50 +01001619 bool Wait() {
sprang861c55e2015-10-16 10:01:21 -07001620 {
1621 // Can't be sure until this point that rtx_to_media_ssrcs_ etc have
1622 // been initialized and are OK to read.
1623 rtc::CritScope cs(&lock_);
1624 started_ = true;
1625 }
Peter Boström5811a392015-12-10 13:02:50 +01001626 return done_.Wait(kDefaultTimeoutMs);
sprang861c55e2015-10-16 10:01:21 -07001627 }
sprang867fb522015-08-03 04:38:41 -07001628
sprang861c55e2015-10-16 10:01:21 -07001629 rtc::CriticalSection lock_;
Peter Boström5811a392015-12-10 13:02:50 +01001630 rtc::Event done_;
kwiberg27f982b2016-03-01 11:52:33 -08001631 std::unique_ptr<RtpHeaderParser> parser_;
sprang861c55e2015-10-16 10:01:21 -07001632 SequenceNumberUnwrapper unwrapper_;
1633 std::set<int64_t> received_packed_ids_;
sprang867fb522015-08-03 04:38:41 -07001634 std::set<uint32_t> streams_observed_;
sprang861c55e2015-10-16 10:01:21 -07001635 std::map<uint32_t, std::set<uint16_t>> dropped_seq_;
1636 const uint32_t& first_media_ssrc_;
1637 const std::map<uint32_t, uint32_t>& rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001638 bool padding_observed_;
1639 bool rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001640 bool retransmit_observed_;
1641 bool started_;
sprang867fb522015-08-03 04:38:41 -07001642 };
1643
1644 class TransportSequenceNumberTester : public MultiStreamTest {
1645 public:
sprang861c55e2015-10-16 10:01:21 -07001646 TransportSequenceNumberTester()
1647 : first_media_ssrc_(0), observer_(nullptr) {}
sprang867fb522015-08-03 04:38:41 -07001648 virtual ~TransportSequenceNumberTester() {}
1649
1650 protected:
1651 void Wait() override {
Peter Boström74f6e9e2016-04-04 17:56:10 +02001652 RTC_DCHECK(observer_);
Peter Boström5811a392015-12-10 13:02:50 +01001653 EXPECT_TRUE(observer_->Wait());
sprang867fb522015-08-03 04:38:41 -07001654 }
1655
1656 void UpdateSendConfig(
1657 size_t stream_index,
1658 VideoSendStream::Config* send_config,
1659 VideoEncoderConfig* encoder_config,
1660 test::FrameGeneratorCapturer** frame_generator) override {
1661 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001662 send_config->rtp.extensions.push_back(RtpExtension(
1663 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sprang867fb522015-08-03 04:38:41 -07001664
1665 // Force some padding to be sent.
1666 const int kPaddingBitrateBps = 50000;
perkjfa10b552016-10-02 23:45:26 -07001667 encoder_config->max_bitrate_bps = 1000000;
sprang867fb522015-08-03 04:38:41 -07001668 encoder_config->min_transmit_bitrate_bps =
perkjfa10b552016-10-02 23:45:26 -07001669 encoder_config->max_bitrate_bps + kPaddingBitrateBps;
sprang867fb522015-08-03 04:38:41 -07001670
1671 // Configure RTX for redundant payload padding.
1672 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang861c55e2015-10-16 10:01:21 -07001673 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[stream_index]);
sprang867fb522015-08-03 04:38:41 -07001674 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
sprang861c55e2015-10-16 10:01:21 -07001675 rtx_to_media_ssrcs_[kSendRtxSsrcs[stream_index]] =
1676 send_config->rtp.ssrcs[0];
1677
1678 if (stream_index == 0)
1679 first_media_ssrc_ = send_config->rtp.ssrcs[0];
sprang867fb522015-08-03 04:38:41 -07001680 }
1681
1682 void UpdateReceiveConfig(
1683 size_t stream_index,
1684 VideoReceiveStream::Config* receive_config) override {
sprang861c55e2015-10-16 10:01:21 -07001685 receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang867fb522015-08-03 04:38:41 -07001686 receive_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001687 receive_config->rtp.extensions.push_back(RtpExtension(
1688 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sakal55d932b2016-09-30 06:19:08 -07001689 receive_config->renderer = &fake_renderer_;
sprang867fb522015-08-03 04:38:41 -07001690 }
1691
stefanf116bd02015-10-27 08:29:42 -07001692 test::DirectTransport* CreateSendTransport(Call* sender_call) override {
1693 observer_ = new RtpExtensionHeaderObserver(sender_call, first_media_ssrc_,
sprang861c55e2015-10-16 10:01:21 -07001694 rtx_to_media_ssrcs_);
sprang867fb522015-08-03 04:38:41 -07001695 return observer_;
1696 }
1697
1698 private:
sakal55d932b2016-09-30 06:19:08 -07001699 test::FakeVideoRenderer fake_renderer_;
sprang861c55e2015-10-16 10:01:21 -07001700 uint32_t first_media_ssrc_;
1701 std::map<uint32_t, uint32_t> rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001702 RtpExtensionHeaderObserver* observer_;
1703 } tester;
1704
1705 tester.RunTest();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001706}
1707
Stefan Holmer04cb7632016-01-14 20:34:30 +01001708class TransportFeedbackTester : public test::EndToEndTest {
1709 public:
1710 explicit TransportFeedbackTester(bool feedback_enabled,
1711 size_t num_video_streams,
1712 size_t num_audio_streams)
1713 : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
1714 feedback_enabled_(feedback_enabled),
1715 num_video_streams_(num_video_streams),
sprangcd349d92016-07-13 09:11:28 -07001716 num_audio_streams_(num_audio_streams),
1717 receiver_call_(nullptr) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001718 // Only one stream of each supported for now.
1719 EXPECT_LE(num_video_streams, 1u);
1720 EXPECT_LE(num_audio_streams, 1u);
1721 }
1722
1723 protected:
1724 Action OnSendRtcp(const uint8_t* data, size_t length) override {
1725 EXPECT_FALSE(HasTransportFeedback(data, length));
1726 return SEND_PACKET;
1727 }
1728
1729 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
1730 if (HasTransportFeedback(data, length))
1731 observation_complete_.Set();
1732 return SEND_PACKET;
1733 }
1734
1735 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
danilchap3dc929e2016-11-02 08:21:59 -07001736 test::RtcpPacketParser parser;
1737 EXPECT_TRUE(parser.Parse(data, length));
1738 return parser.transport_feedback()->num_packets() > 0;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001739 }
1740
1741 void PerformTest() override {
1742 const int64_t kDisabledFeedbackTimeoutMs = 5000;
1743 EXPECT_EQ(feedback_enabled_,
1744 observation_complete_.Wait(feedback_enabled_
1745 ? test::CallTest::kDefaultTimeoutMs
1746 : kDisabledFeedbackTimeoutMs));
1747 }
1748
1749 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1750 receiver_call_ = receiver_call;
1751 }
1752
1753 size_t GetNumVideoStreams() const override { return num_video_streams_; }
1754 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
1755
1756 void ModifyVideoConfigs(
1757 VideoSendStream::Config* send_config,
1758 std::vector<VideoReceiveStream::Config>* receive_configs,
1759 VideoEncoderConfig* encoder_config) override {
1760 send_config->rtp.extensions.clear();
1761 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001762 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001763 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1764 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
1765 }
1766
1767 void ModifyAudioConfigs(
1768 AudioSendStream::Config* send_config,
1769 std::vector<AudioReceiveStream::Config>* receive_configs) override {
1770 send_config->rtp.extensions.clear();
1771 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001772 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001773 (*receive_configs)[0].rtp.extensions.clear();
1774 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1775 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001776 }
1777
1778 private:
Erik Språng6b8d3552015-09-24 15:06:57 +02001779 static const int kExtensionId = 5;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001780 const bool feedback_enabled_;
1781 const size_t num_video_streams_;
1782 const size_t num_audio_streams_;
1783 Call* receiver_call_;
1784};
Erik Språng6b8d3552015-09-24 15:06:57 +02001785
philipel266f0a42016-11-28 08:49:07 -08001786TEST_P(EndToEndTest, VideoReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001787 TransportFeedbackTester test(true, 1, 0);
1788 RunBaseTest(&test);
Erik Språng6b8d3552015-09-24 15:06:57 +02001789}
stefan43edf0f2015-11-20 18:05:48 -08001790
philipel266f0a42016-11-28 08:49:07 -08001791TEST_P(EndToEndTest, VideoTransportFeedbackNotConfigured) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001792 TransportFeedbackTester test(false, 1, 0);
1793 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001794}
1795
philipel266f0a42016-11-28 08:49:07 -08001796TEST_P(EndToEndTest, AudioReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001797 TransportFeedbackTester test(true, 0, 1);
1798 RunBaseTest(&test);
1799}
1800
philipel266f0a42016-11-28 08:49:07 -08001801TEST_P(EndToEndTest, AudioTransportFeedbackNotConfigured) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001802 TransportFeedbackTester test(false, 0, 1);
1803 RunBaseTest(&test);
1804}
1805
philipel266f0a42016-11-28 08:49:07 -08001806TEST_P(EndToEndTest, AudioVideoReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001807 TransportFeedbackTester test(true, 1, 1);
1808 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001809}
1810
philipel266f0a42016-11-28 08:49:07 -08001811TEST_P(EndToEndTest, ObserversEncodedFrames) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001812 class EncodedFrameTestObserver : public EncodedFrameObserver {
1813 public:
1814 EncodedFrameTestObserver()
Peter Boström5811a392015-12-10 13:02:50 +01001815 : length_(0), frame_type_(kEmptyFrame), called_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001816 virtual ~EncodedFrameTestObserver() {}
1817
1818 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
1819 frame_type_ = encoded_frame.frame_type_;
1820 length_ = encoded_frame.length_;
1821 buffer_.reset(new uint8_t[length_]);
1822 memcpy(buffer_.get(), encoded_frame.data_, length_);
Peter Boström5811a392015-12-10 13:02:50 +01001823 called_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001824 }
1825
Peter Boström5811a392015-12-10 13:02:50 +01001826 bool Wait() { return called_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001827
1828 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
1829 ASSERT_EQ(length_, observer.length_)
1830 << "Observed frames are of different lengths.";
1831 EXPECT_EQ(frame_type_, observer.frame_type_)
1832 << "Observed frames have different frame types.";
1833 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
1834 << "Observed encoded frames have different content.";
1835 }
1836
1837 private:
kwiberg27f982b2016-03-01 11:52:33 -08001838 std::unique_ptr<uint8_t[]> buffer_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001839 size_t length_;
1840 FrameType frame_type_;
Peter Boström5811a392015-12-10 13:02:50 +01001841 rtc::Event called_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001842 };
1843
1844 EncodedFrameTestObserver post_encode_observer;
1845 EncodedFrameTestObserver pre_decode_observer;
1846
skvlad11a9cbf2016-10-07 11:53:05 -07001847 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -07001848
stefanf116bd02015-10-27 08:29:42 -07001849 test::DirectTransport sender_transport(sender_call_.get());
1850 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001851 sender_transport.SetReceiver(receiver_call_->Receiver());
1852 receiver_transport.SetReceiver(sender_call_->Receiver());
1853
brandtr841de6a2016-11-15 07:10:52 -08001854 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001855 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -08001856 video_send_config_.post_encode_callback = &post_encode_observer;
1857 video_receive_configs_[0].pre_decode_callback = &pre_decode_observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001858
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001859 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001860 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001861
kwiberg27f982b2016-03-01 11:52:33 -08001862 std::unique_ptr<test::FrameGenerator> frame_generator(
perkjfa10b552016-10-02 23:45:26 -07001863 test::FrameGenerator::CreateChromaGenerator(kDefaultWidth,
1864 kDefaultHeight));
perkja49cbd32016-09-16 07:53:41 -07001865 test::FrameForwarder forwarder;
perkj803d97f2016-11-01 11:45:46 -07001866 video_send_stream_->SetSource(
1867 &forwarder, VideoSendStream::DegradationPreference::kBalanced);
perkja49cbd32016-09-16 07:53:41 -07001868 forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001869
Peter Boström5811a392015-12-10 13:02:50 +01001870 EXPECT_TRUE(post_encode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001871 << "Timed out while waiting for send-side encoded-frame callback.";
1872
Peter Boström5811a392015-12-10 13:02:50 +01001873 EXPECT_TRUE(pre_decode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001874 << "Timed out while waiting for pre-decode encoded-frame callback.";
1875
1876 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
1877
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001878 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001879
1880 sender_transport.StopSending();
1881 receiver_transport.StopSending();
1882
1883 DestroyStreams();
1884}
1885
philipel266f0a42016-11-28 08:49:07 -08001886TEST_P(EndToEndTest, ReceiveStreamSendsRemb) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001887 class RembObserver : public test::EndToEndTest {
1888 public:
1889 RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
1890
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001891 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
danilchap3dc929e2016-11-02 08:21:59 -07001892 test::RtcpPacketParser parser;
1893 EXPECT_TRUE(parser.Parse(packet, length));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001894
danilchap3dc929e2016-11-02 08:21:59 -07001895 if (parser.remb()->num_packets() > 0) {
1896 EXPECT_EQ(kReceiverLocalVideoSsrc, parser.remb()->sender_ssrc());
1897 EXPECT_LT(0U, parser.remb()->bitrate_bps());
1898 EXPECT_EQ(1U, parser.remb()->ssrcs().size());
1899 EXPECT_EQ(kVideoSendSsrcs[0], parser.remb()->ssrcs()[0]);
Peter Boström5811a392015-12-10 13:02:50 +01001900 observation_complete_.Set();
danilchap3dc929e2016-11-02 08:21:59 -07001901 }
1902
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001903 return SEND_PACKET;
1904 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001905 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001906 EXPECT_TRUE(Wait()) << "Timed out while waiting for a "
1907 "receiver RTCP REMB packet to be "
1908 "sent.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001909 }
1910 } test;
1911
stefane74eef12016-01-08 06:47:13 -08001912 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001913}
1914
philipel266f0a42016-11-28 08:49:07 -08001915TEST_P(EndToEndTest, VerifyBandwidthStats) {
stefanf116bd02015-10-27 08:29:42 -07001916 class RtcpObserver : public test::EndToEndTest {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001917 public:
1918 RtcpObserver()
1919 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001920 sender_call_(nullptr),
1921 receiver_call_(nullptr),
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001922 has_seen_pacer_delay_(false) {}
1923
stefanf116bd02015-10-27 08:29:42 -07001924 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001925 Call::Stats sender_stats = sender_call_->GetStats();
1926 Call::Stats receiver_stats = receiver_call_->GetStats();
1927 if (!has_seen_pacer_delay_)
1928 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
1929 if (sender_stats.send_bandwidth_bps > 0 &&
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001930 receiver_stats.recv_bandwidth_bps > 0 && has_seen_pacer_delay_) {
Peter Boström5811a392015-12-10 13:02:50 +01001931 observation_complete_.Set();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001932 }
stefanf116bd02015-10-27 08:29:42 -07001933 return SEND_PACKET;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001934 }
1935
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001936 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001937 sender_call_ = sender_call;
1938 receiver_call_ = receiver_call;
1939 }
1940
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001941 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001942 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
1943 "non-zero bandwidth stats.";
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001944 }
1945
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001946 private:
1947 Call* sender_call_;
1948 Call* receiver_call_;
1949 bool has_seen_pacer_delay_;
1950 } test;
1951
stefane74eef12016-01-08 06:47:13 -08001952 RunBaseTest(&test);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001953}
1954
stefan32f81542016-01-20 07:13:58 -08001955
1956// Verifies that it's possible to limit the send BWE by sending a REMB.
1957// This is verified by allowing the send BWE to ramp-up to >1000 kbps,
1958// then have the test generate a REMB of 500 kbps and verify that the send BWE
1959// is reduced to exactly 500 kbps. Then a REMB of 1000 kbps is generated and the
1960// test verifies that the send BWE ramps back up to exactly 1000 kbps.
philipel266f0a42016-11-28 08:49:07 -08001961TEST_P(EndToEndTest, RembWithSendSideBwe) {
stefan32f81542016-01-20 07:13:58 -08001962 class BweObserver : public test::EndToEndTest {
1963 public:
1964 BweObserver()
1965 : EndToEndTest(kDefaultTimeoutMs),
1966 sender_call_(nullptr),
1967 clock_(Clock::GetRealTimeClock()),
1968 sender_ssrc_(0),
1969 remb_bitrate_bps_(1000000),
1970 receive_transport_(nullptr),
1971 event_(false, false),
1972 poller_thread_(&BitrateStatsPollingThread,
1973 this,
1974 "BitrateStatsPollingThread"),
Erik Språng737336d2016-07-29 12:59:36 +02001975 state_(kWaitForFirstRampUp),
1976 retransmission_rate_limiter_(clock_, 1000) {}
stefan32f81542016-01-20 07:13:58 -08001977
1978 ~BweObserver() {}
1979
nisseef8b61e2016-04-29 06:09:15 -07001980 test::PacketTransport* CreateReceiveTransport() override {
stefan32f81542016-01-20 07:13:58 -08001981 receive_transport_ = new test::PacketTransport(
1982 nullptr, this, test::PacketTransport::kReceiver,
1983 FakeNetworkPipe::Config());
1984 return receive_transport_;
1985 }
1986
1987 Call::Config GetSenderCallConfig() override {
skvlad11a9cbf2016-10-07 11:53:05 -07001988 Call::Config config(&event_log_);
stefan32f81542016-01-20 07:13:58 -08001989 // Set a high start bitrate to reduce the test completion time.
1990 config.bitrate_config.start_bitrate_bps = remb_bitrate_bps_;
1991 return config;
1992 }
1993
1994 void ModifyVideoConfigs(
1995 VideoSendStream::Config* send_config,
1996 std::vector<VideoReceiveStream::Config>* receive_configs,
1997 VideoEncoderConfig* encoder_config) override {
1998 ASSERT_EQ(1u, send_config->rtp.ssrcs.size());
1999 send_config->rtp.extensions.clear();
2000 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07002001 RtpExtension(RtpExtension::kTransportSequenceNumberUri,
stefan32f81542016-01-20 07:13:58 -08002002 test::kTransportSequenceNumberExtensionId));
2003 sender_ssrc_ = send_config->rtp.ssrcs[0];
2004
perkjfa10b552016-10-02 23:45:26 -07002005 encoder_config->max_bitrate_bps = 2000000;
stefan32f81542016-01-20 07:13:58 -08002006
2007 ASSERT_EQ(1u, receive_configs->size());
2008 (*receive_configs)[0].rtp.remb = false;
2009 (*receive_configs)[0].rtp.transport_cc = true;
2010 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
2011 RtpRtcp::Configuration config;
2012 config.receiver_only = true;
2013 config.clock = clock_;
2014 config.outgoing_transport = receive_transport_;
Erik Språng737336d2016-07-29 12:59:36 +02002015 config.retransmission_rate_limiter = &retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08002016 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
2017 rtp_rtcp_->SetRemoteSSRC((*receive_configs)[0].rtp.remote_ssrc);
2018 rtp_rtcp_->SetSSRC((*receive_configs)[0].rtp.local_ssrc);
2019 rtp_rtcp_->SetREMBStatus(true);
2020 rtp_rtcp_->SetSendingStatus(true);
2021 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
2022 }
2023
2024 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2025 sender_call_ = sender_call;
2026 }
2027
2028 static bool BitrateStatsPollingThread(void* obj) {
2029 return static_cast<BweObserver*>(obj)->PollStats();
2030 }
2031
2032 bool PollStats() {
2033 if (sender_call_) {
2034 Call::Stats stats = sender_call_->GetStats();
2035 switch (state_) {
2036 case kWaitForFirstRampUp:
2037 if (stats.send_bandwidth_bps >= remb_bitrate_bps_) {
2038 state_ = kWaitForRemb;
2039 remb_bitrate_bps_ /= 2;
2040 rtp_rtcp_->SetREMBData(
2041 remb_bitrate_bps_,
2042 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
2043 rtp_rtcp_->SendRTCP(kRtcpRr);
2044 }
2045 break;
2046
2047 case kWaitForRemb:
2048 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
2049 state_ = kWaitForSecondRampUp;
2050 remb_bitrate_bps_ *= 2;
2051 rtp_rtcp_->SetREMBData(
2052 remb_bitrate_bps_,
2053 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
2054 rtp_rtcp_->SendRTCP(kRtcpRr);
2055 }
2056 break;
2057
2058 case kWaitForSecondRampUp:
2059 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
2060 observation_complete_.Set();
2061 }
2062 break;
2063 }
2064 }
2065
2066 return !event_.Wait(1000);
2067 }
2068
2069 void PerformTest() override {
2070 poller_thread_.Start();
2071 EXPECT_TRUE(Wait())
2072 << "Timed out while waiting for bitrate to change according to REMB.";
2073 poller_thread_.Stop();
2074 }
2075
2076 private:
2077 enum TestState { kWaitForFirstRampUp, kWaitForRemb, kWaitForSecondRampUp };
2078
2079 Call* sender_call_;
2080 Clock* const clock_;
2081 uint32_t sender_ssrc_;
2082 int remb_bitrate_bps_;
kwiberg27f982b2016-03-01 11:52:33 -08002083 std::unique_ptr<RtpRtcp> rtp_rtcp_;
stefan32f81542016-01-20 07:13:58 -08002084 test::PacketTransport* receive_transport_;
2085 rtc::Event event_;
2086 rtc::PlatformThread poller_thread_;
2087 TestState state_;
Erik Språng737336d2016-07-29 12:59:36 +02002088 RateLimiter retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08002089 } test;
2090
2091 RunBaseTest(&test);
2092}
2093
philipel266f0a42016-11-28 08:49:07 -08002094TEST_P(EndToEndTest, VerifyNackStats) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002095 static const int kPacketNumberToDrop = 200;
2096 class NackObserver : public test::EndToEndTest {
2097 public:
2098 NackObserver()
2099 : EndToEndTest(kLongTimeoutMs),
2100 sent_rtp_packets_(0),
2101 dropped_rtp_packet_(0),
2102 dropped_rtp_packet_requested_(false),
2103 send_stream_(nullptr),
2104 start_runtime_ms_(-1) {}
2105
2106 private:
2107 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002108 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002109 if (++sent_rtp_packets_ == kPacketNumberToDrop) {
kwiberg27f982b2016-03-01 11:52:33 -08002110 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
Åsa Persson352b2d72015-04-15 18:00:40 +02002111 RTPHeader header;
2112 EXPECT_TRUE(parser->Parse(packet, length, &header));
2113 dropped_rtp_packet_ = header.sequenceNumber;
2114 return DROP_PACKET;
2115 }
2116 VerifyStats();
2117 return SEND_PACKET;
2118 }
2119
2120 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002121 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002122 test::RtcpPacketParser rtcp_parser;
2123 rtcp_parser.Parse(packet, length);
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02002124 const std::vector<uint16_t>& nacks = rtcp_parser.nack()->packet_ids();
Åsa Persson352b2d72015-04-15 18:00:40 +02002125 if (!nacks.empty() && std::find(
2126 nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) {
2127 dropped_rtp_packet_requested_ = true;
2128 }
2129 return SEND_PACKET;
2130 }
2131
stefan608213e2015-11-01 14:56:10 -08002132 void VerifyStats() EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002133 if (!dropped_rtp_packet_requested_)
2134 return;
2135 int send_stream_nack_packets = 0;
2136 int receive_stream_nack_packets = 0;
2137 VideoSendStream::Stats stats = send_stream_->GetStats();
2138 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
2139 stats.substreams.begin(); it != stats.substreams.end(); ++it) {
2140 const VideoSendStream::StreamStats& stream_stats = it->second;
2141 send_stream_nack_packets +=
2142 stream_stats.rtcp_packet_type_counts.nack_packets;
2143 }
2144 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2145 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2146 receive_stream_nack_packets +=
2147 stats.rtcp_packet_type_counts.nack_packets;
2148 }
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002149 if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002150 // NACK packet sent on receive stream and received on sent stream.
2151 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002152 observation_complete_.Set();
Åsa Persson352b2d72015-04-15 18:00:40 +02002153 }
2154 }
2155
2156 bool MinMetricRunTimePassed() {
2157 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2158 if (start_runtime_ms_ == -1) {
2159 start_runtime_ms_ = now;
2160 return false;
2161 }
2162 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2163 return elapsed_sec > metrics::kMinRunTimeInSeconds;
2164 }
2165
stefanff483612015-12-21 03:14:00 -08002166 void ModifyVideoConfigs(
2167 VideoSendStream::Config* send_config,
2168 std::vector<VideoReceiveStream::Config>* receive_configs,
2169 VideoEncoderConfig* encoder_config) override {
Åsa Persson352b2d72015-04-15 18:00:40 +02002170 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2171 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sakal55d932b2016-09-30 06:19:08 -07002172 (*receive_configs)[0].renderer = &fake_renderer_;
Åsa Persson352b2d72015-04-15 18:00:40 +02002173 }
2174
stefanff483612015-12-21 03:14:00 -08002175 void OnVideoStreamsCreated(
Åsa Persson352b2d72015-04-15 18:00:40 +02002176 VideoSendStream* send_stream,
2177 const std::vector<VideoReceiveStream*>& receive_streams) override {
2178 send_stream_ = send_stream;
2179 receive_streams_ = receive_streams;
2180 }
2181
2182 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002183 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson352b2d72015-04-15 18:00:40 +02002184 }
2185
sakal55d932b2016-09-30 06:19:08 -07002186 test::FakeVideoRenderer fake_renderer_;
stefan608213e2015-11-01 14:56:10 -08002187 rtc::CriticalSection crit_;
Åsa Persson352b2d72015-04-15 18:00:40 +02002188 uint64_t sent_rtp_packets_;
stefan608213e2015-11-01 14:56:10 -08002189 uint16_t dropped_rtp_packet_ GUARDED_BY(&crit_);
2190 bool dropped_rtp_packet_requested_ GUARDED_BY(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002191 std::vector<VideoReceiveStream*> receive_streams_;
2192 VideoSendStream* send_stream_;
2193 int64_t start_runtime_ms_;
2194 } test;
2195
asapersson01d70a32016-05-20 06:29:46 -07002196 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002197 RunBaseTest(&test);
Åsa Persson352b2d72015-04-15 18:00:40 +02002198
asapersson01d70a32016-05-20 06:29:46 -07002199 EXPECT_EQ(
2200 1, metrics::NumSamples("WebRTC.Video.UniqueNackRequestsSentInPercent"));
2201 EXPECT_EQ(1, metrics::NumSamples(
2202 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
2203 EXPECT_GT(metrics::MinSample("WebRTC.Video.NackPacketsSentPerMinute"), 0);
Åsa Persson352b2d72015-04-15 18:00:40 +02002204}
2205
sprangb4a1ae52015-12-03 08:10:08 -08002206void EndToEndTest::VerifyHistogramStats(bool use_rtx,
2207 bool use_red,
2208 bool screenshare) {
tommi2e82f382016-06-21 00:26:43 -07002209 class StatsObserver : public test::EndToEndTest,
2210 public rtc::VideoSinkInterface<VideoFrame> {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002211 public:
sprangb4a1ae52015-12-03 08:10:08 -08002212 StatsObserver(bool use_rtx, bool use_red, bool screenshare)
Åsa Persson3c391cb2015-04-27 10:09:49 +02002213 : EndToEndTest(kLongTimeoutMs),
2214 use_rtx_(use_rtx),
2215 use_red_(use_red),
sprangb4a1ae52015-12-03 08:10:08 -08002216 screenshare_(screenshare),
Peter Boström39593972016-02-15 11:27:15 +01002217 // This test uses NACK, so to send FEC we can't use a fake encoder.
magjed509e4fe2016-11-18 01:34:11 -08002218 vp8_encoder_(use_red ? VP8Encoder::Create() : nullptr),
Åsa Persson3c391cb2015-04-27 10:09:49 +02002219 sender_call_(nullptr),
2220 receiver_call_(nullptr),
asapersson1394c7b2016-10-18 11:50:50 -07002221 start_runtime_ms_(-1),
2222 num_frames_received_(0) {}
Åsa Persson3c391cb2015-04-27 10:09:49 +02002223
2224 private:
asapersson1394c7b2016-10-18 11:50:50 -07002225 void OnFrame(const VideoFrame& video_frame) override {
2226 // The RTT is needed to estimate |ntp_time_ms| which is used by
2227 // end-to-end delay stats. Therefore, start counting received frames once
2228 // |ntp_time_ms| is valid.
2229 if (video_frame.ntp_time_ms() > 0 &&
2230 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() >=
2231 video_frame.ntp_time_ms()) {
2232 rtc::CritScope lock(&crit_);
2233 ++num_frames_received_;
2234 }
2235 }
tommi2e82f382016-06-21 00:26:43 -07002236
Åsa Persson3c391cb2015-04-27 10:09:49 +02002237 Action OnSendRtp(const uint8_t* packet, size_t length) override {
asapersson1394c7b2016-10-18 11:50:50 -07002238 if (MinMetricRunTimePassed() && MinNumberOfFramesReceived())
Peter Boström5811a392015-12-10 13:02:50 +01002239 observation_complete_.Set();
Åsa Persson3c391cb2015-04-27 10:09:49 +02002240
stefanf116bd02015-10-27 08:29:42 -07002241 return SEND_PACKET;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002242 }
2243
2244 bool MinMetricRunTimePassed() {
2245 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2246 if (start_runtime_ms_ == -1) {
2247 start_runtime_ms_ = now;
2248 return false;
2249 }
2250 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2251 return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
2252 }
2253
asapersson1394c7b2016-10-18 11:50:50 -07002254 bool MinNumberOfFramesReceived() const {
2255 const int kMinRequiredHistogramSamples = 200;
2256 rtc::CritScope lock(&crit_);
2257 return num_frames_received_ > kMinRequiredHistogramSamples;
2258 }
2259
stefanff483612015-12-21 03:14:00 -08002260 void ModifyVideoConfigs(
2261 VideoSendStream::Config* send_config,
2262 std::vector<VideoReceiveStream::Config>* receive_configs,
2263 VideoEncoderConfig* encoder_config) override {
stefana23fc622016-07-28 07:56:38 -07002264 static const int kExtensionId = 8;
2265 send_config->rtp.extensions.push_back(RtpExtension(
2266 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
2267 (*receive_configs)[0].rtp.extensions.push_back(RtpExtension(
2268 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002269 // NACK
2270 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2271 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
tommi2e82f382016-06-21 00:26:43 -07002272 (*receive_configs)[0].renderer = this;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002273 // FEC
2274 if (use_red_) {
brandtrb5f2c3f2016-10-04 23:28:39 -07002275 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
2276 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
Peter Boström39593972016-02-15 11:27:15 +01002277 send_config->encoder_settings.encoder = vp8_encoder_.get();
2278 send_config->encoder_settings.payload_name = "VP8";
2279 (*receive_configs)[0].decoders[0].payload_name = "VP8";
brandtrb5f2c3f2016-10-04 23:28:39 -07002280 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
2281 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type =
2282 kUlpfecPayloadType;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002283 }
2284 // RTX
2285 if (use_rtx_) {
2286 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
2287 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002288 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002289 kSendRtxSsrcs[0];
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002290 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002291 kSendRtxPayloadType;
2292 }
asapersson1490f7a2016-09-23 02:09:46 -07002293 // RTT needed for RemoteNtpTimeEstimator for the receive stream.
2294 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = true;
sprangb4a1ae52015-12-03 08:10:08 -08002295 encoder_config->content_type =
2296 screenshare_ ? VideoEncoderConfig::ContentType::kScreen
2297 : VideoEncoderConfig::ContentType::kRealtimeVideo;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002298 }
2299
2300 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2301 sender_call_ = sender_call;
2302 receiver_call_ = receiver_call;
2303 }
2304
Åsa Persson3c391cb2015-04-27 10:09:49 +02002305 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002306 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson3c391cb2015-04-27 10:09:49 +02002307 }
2308
asapersson1394c7b2016-10-18 11:50:50 -07002309 rtc::CriticalSection crit_;
sprangb4a1ae52015-12-03 08:10:08 -08002310 const bool use_rtx_;
2311 const bool use_red_;
2312 const bool screenshare_;
kwiberg27f982b2016-03-01 11:52:33 -08002313 const std::unique_ptr<VideoEncoder> vp8_encoder_;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002314 Call* sender_call_;
2315 Call* receiver_call_;
2316 int64_t start_runtime_ms_;
asapersson1394c7b2016-10-18 11:50:50 -07002317 int num_frames_received_ GUARDED_BY(&crit_);
sprangb4a1ae52015-12-03 08:10:08 -08002318 } test(use_rtx, use_red, screenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002319
asapersson01d70a32016-05-20 06:29:46 -07002320 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002321 RunBaseTest(&test);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002322
stefan91d92602015-11-11 10:13:02 -08002323 // Delete the call for Call stats to be reported.
stefan18adf0a2015-11-17 06:24:56 -08002324 sender_call_.reset();
stefan91d92602015-11-11 10:13:02 -08002325 receiver_call_.reset();
2326
sprangb4a1ae52015-12-03 08:10:08 -08002327 std::string video_prefix =
2328 screenshare ? "WebRTC.Video.Screenshare." : "WebRTC.Video.";
2329
Åsa Persson3c391cb2015-04-27 10:09:49 +02002330 // Verify that stats have been updated once.
asapersson4374a092016-07-27 00:39:09 -07002331 EXPECT_EQ(2, metrics::NumSamples("WebRTC.Call.LifetimeInSeconds"));
asapersson01d70a32016-05-20 06:29:46 -07002332 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
2333 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.RtcpBitrateReceivedInBps"));
2334 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.BitrateReceivedInKbps"));
2335 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.EstimatedSendBitrateInKbps"));
2336 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.PacerBitrateInKbps"));
2337
asapersson4374a092016-07-27 00:39:09 -07002338 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
2339 EXPECT_EQ(1,
2340 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
2341
asapersson01d70a32016-05-20 06:29:46 -07002342 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
stefan91d92602015-11-11 10:13:02 -08002343 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002344 metrics::NumSamples(video_prefix + "NackPacketsReceivedPerMinute"));
2345 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
asaperssond89920b2015-07-22 06:52:00 -07002346 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002347 metrics::NumSamples(video_prefix + "FirPacketsReceivedPerMinute"));
2348 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
sprangb4a1ae52015-12-03 08:10:08 -08002349 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002350 metrics::NumSamples(video_prefix + "PliPacketsReceivedPerMinute"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002351
asapersson01d70a32016-05-20 06:29:46 -07002352 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "KeyFramesSentInPermille"));
2353 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
2354
2355 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentPacketsLostInPercent"));
2356 EXPECT_EQ(1,
2357 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
2358
2359 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputWidthInPixels"));
2360 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputHeightInPixels"));
2361 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentWidthInPixels"));
2362 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentHeightInPixels"));
2363 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
2364 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
2365
perkjfa10b552016-10-02 23:45:26 -07002366 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputWidthInPixels",
2367 kDefaultWidth));
2368 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputHeightInPixels",
2369 kDefaultHeight));
2370 EXPECT_EQ(
2371 1, metrics::NumEvents(video_prefix + "SentWidthInPixels", kDefaultWidth));
2372 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "SentHeightInPixels",
2373 kDefaultHeight));
2374 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedWidthInPixels",
2375 kDefaultWidth));
2376 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedHeightInPixels",
2377 kDefaultHeight));
asapersson01d70a32016-05-20 06:29:46 -07002378
2379 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputFramesPerSecond"));
2380 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentFramesPerSecond"));
2381 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
2382 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
2383
2384 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
2385 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
2386 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
2387 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
2388
asapersson1490f7a2016-09-23 02:09:46 -07002389 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.EndToEndDelayInMs"));
asapersson01d70a32016-05-20 06:29:46 -07002390 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
2391
2392 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EncodeTimeInMs"));
2393 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
2394
asapersson66d4b372016-12-19 06:50:53 -08002395 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "NumberOfPauseEvents"));
2396 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PausedTimeInPercent"));
2397
asapersson01d70a32016-05-20 06:29:46 -07002398 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "BitrateSentInKbps"));
2399 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateReceivedInKbps"));
2400 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "MediaBitrateSentInKbps"));
2401 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateReceivedInKbps"));
2402 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PaddingBitrateSentInKbps"));
2403 EXPECT_EQ(1,
2404 metrics::NumSamples("WebRTC.Video.PaddingBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002405 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002406 1, metrics::NumSamples(video_prefix + "RetransmittedBitrateSentInKbps"));
2407 EXPECT_EQ(1, metrics::NumSamples(
2408 "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002409
asapersson01d70a32016-05-20 06:29:46 -07002410 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendDelayInMs"));
2411 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayInMs"));
2412 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayMaxInMs"));
asapersson6f14be82015-11-16 00:40:49 -08002413
Åsa Persson3c391cb2015-04-27 10:09:49 +02002414 int num_rtx_samples = use_rtx ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002415 EXPECT_EQ(num_rtx_samples,
2416 metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2417 EXPECT_EQ(num_rtx_samples,
2418 metrics::NumSamples("WebRTC.Video.RtxBitrateReceivedInKbps"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002419
2420 int num_red_samples = use_red ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002421 EXPECT_EQ(num_red_samples,
2422 metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2423 EXPECT_EQ(num_red_samples,
2424 metrics::NumSamples("WebRTC.Video.FecBitrateReceivedInKbps"));
2425 EXPECT_EQ(num_red_samples,
2426 metrics::NumSamples("WebRTC.Video.ReceivedFecPacketsInPercent"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002427}
2428
philipel266f0a42016-11-28 08:49:07 -08002429TEST_P(EndToEndTest, VerifyHistogramStatsWithRtx) {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002430 const bool kEnabledRtx = true;
2431 const bool kEnabledRed = false;
sprangb4a1ae52015-12-03 08:10:08 -08002432 const bool kScreenshare = false;
2433 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002434}
2435
philipel266f0a42016-11-28 08:49:07 -08002436TEST_P(EndToEndTest, VerifyHistogramStatsWithRed) {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002437 const bool kEnabledRtx = false;
2438 const bool kEnabledRed = true;
sprangb4a1ae52015-12-03 08:10:08 -08002439 const bool kScreenshare = false;
2440 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
2441}
2442
philipel266f0a42016-11-28 08:49:07 -08002443TEST_P(EndToEndTest, VerifyHistogramStatsWithScreenshare) {
sprangb4a1ae52015-12-03 08:10:08 -08002444 const bool kEnabledRtx = false;
2445 const bool kEnabledRed = false;
2446 const bool kScreenshare = true;
2447 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002448}
2449
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002450void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
2451 bool send_single_ssrc_first) {
2452 class SendsSetSsrcs : public test::EndToEndTest {
2453 public:
2454 SendsSetSsrcs(const uint32_t* ssrcs,
2455 size_t num_ssrcs,
2456 bool send_single_ssrc_first)
2457 : EndToEndTest(kDefaultTimeoutMs),
2458 num_ssrcs_(num_ssrcs),
2459 send_single_ssrc_first_(send_single_ssrc_first),
2460 ssrcs_to_observe_(num_ssrcs),
sprang867fb522015-08-03 04:38:41 -07002461 expect_single_ssrc_(send_single_ssrc_first),
2462 send_stream_(nullptr) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002463 for (size_t i = 0; i < num_ssrcs; ++i)
2464 valid_ssrcs_[ssrcs[i]] = true;
2465 }
2466
2467 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002468 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002469 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002470 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002471
2472 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
2473 << "Received unknown SSRC: " << header.ssrc;
2474
2475 if (!valid_ssrcs_[header.ssrc])
Peter Boström5811a392015-12-10 13:02:50 +01002476 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002477
2478 if (!is_observed_[header.ssrc]) {
2479 is_observed_[header.ssrc] = true;
2480 --ssrcs_to_observe_;
2481 if (expect_single_ssrc_) {
2482 expect_single_ssrc_ = false;
Peter Boström5811a392015-12-10 13:02:50 +01002483 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002484 }
2485 }
2486
2487 if (ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002488 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002489
2490 return SEND_PACKET;
2491 }
2492
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002493 size_t GetNumVideoStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002494
perkjfa10b552016-10-02 23:45:26 -07002495 // This test use other VideoStream settings than the the default settings
2496 // implemented in DefaultVideoStreamFactory. Therefore this test implement
2497 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
2498 // in ModifyVideoConfigs.
2499 class VideoStreamFactory
2500 : public VideoEncoderConfig::VideoStreamFactoryInterface {
2501 public:
2502 VideoStreamFactory() {}
2503
2504 private:
2505 std::vector<VideoStream> CreateEncoderStreams(
2506 int width,
2507 int height,
2508 const VideoEncoderConfig& encoder_config) override {
2509 std::vector<VideoStream> streams =
2510 test::CreateVideoStreams(width, height, encoder_config);
2511 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
2512 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
2513 streams[i].min_bitrate_bps = 10000;
2514 streams[i].target_bitrate_bps = 15000;
2515 streams[i].max_bitrate_bps = 20000;
2516 }
2517 return streams;
2518 }
2519 };
2520
stefanff483612015-12-21 03:14:00 -08002521 void ModifyVideoConfigs(
2522 VideoSendStream::Config* send_config,
2523 std::vector<VideoReceiveStream::Config>* receive_configs,
2524 VideoEncoderConfig* encoder_config) override {
perkjfa10b552016-10-02 23:45:26 -07002525 encoder_config->video_stream_factory =
2526 new rtc::RefCountedObject<VideoStreamFactory>();
perkj26091b12016-09-01 01:17:40 -07002527 video_encoder_config_all_streams_ = encoder_config->Copy();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002528 if (send_single_ssrc_first_)
perkjfa10b552016-10-02 23:45:26 -07002529 encoder_config->number_of_streams = 1;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002530 }
2531
stefanff483612015-12-21 03:14:00 -08002532 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002533 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002534 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002535 send_stream_ = send_stream;
2536 }
2537
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002538 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002539 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2540 << (send_single_ssrc_first_ ? "first SSRC."
2541 : "SSRCs.");
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002542
2543 if (send_single_ssrc_first_) {
2544 // Set full simulcast and continue with the rest of the SSRCs.
stefanff483612015-12-21 03:14:00 -08002545 send_stream_->ReconfigureVideoEncoder(
perkj26091b12016-09-01 01:17:40 -07002546 std::move(video_encoder_config_all_streams_));
Peter Boström5811a392015-12-10 13:02:50 +01002547 EXPECT_TRUE(Wait()) << "Timed out while waiting on additional SSRCs.";
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002548 }
2549 }
2550
2551 private:
2552 std::map<uint32_t, bool> valid_ssrcs_;
2553 std::map<uint32_t, bool> is_observed_;
2554
2555 const size_t num_ssrcs_;
2556 const bool send_single_ssrc_first_;
2557
2558 size_t ssrcs_to_observe_;
2559 bool expect_single_ssrc_;
2560
2561 VideoSendStream* send_stream_;
stefanff483612015-12-21 03:14:00 -08002562 VideoEncoderConfig video_encoder_config_all_streams_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002563 } test(kVideoSendSsrcs, num_ssrcs, send_single_ssrc_first);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002564
stefane74eef12016-01-08 06:47:13 -08002565 RunBaseTest(&test);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002566}
2567
philipel266f0a42016-11-28 08:49:07 -08002568TEST_P(EndToEndTest, ReportsSetEncoderRates) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002569 class EncoderRateStatsTest : public test::EndToEndTest,
2570 public test::FakeEncoder {
2571 public:
2572 EncoderRateStatsTest()
2573 : EndToEndTest(kDefaultTimeoutMs),
sprang867fb522015-08-03 04:38:41 -07002574 FakeEncoder(Clock::GetRealTimeClock()),
2575 send_stream_(nullptr),
2576 bitrate_kbps_(0) {}
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002577
stefanff483612015-12-21 03:14:00 -08002578 void OnVideoStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002579 VideoSendStream* send_stream,
2580 const std::vector<VideoReceiveStream*>& receive_streams) override {
2581 send_stream_ = send_stream;
2582 }
2583
stefanff483612015-12-21 03:14:00 -08002584 void ModifyVideoConfigs(
2585 VideoSendStream::Config* send_config,
2586 std::vector<VideoReceiveStream::Config>* receive_configs,
2587 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002588 send_config->encoder_settings.encoder = this;
kwibergaf476c72016-11-28 15:21:39 -08002589 RTC_DCHECK_EQ(1, encoder_config->number_of_streams);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002590 }
2591
Erik Språng08127a92016-11-16 16:41:30 +01002592 int32_t SetRateAllocation(const BitrateAllocation& rate_allocation,
2593 uint32_t framerate) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002594 // Make sure not to trigger on any default zero bitrates.
Erik Språng08127a92016-11-16 16:41:30 +01002595 if (rate_allocation.get_sum_bps() == 0)
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002596 return 0;
Peter Boströmf2f82832015-05-01 13:00:41 +02002597 rtc::CritScope lock(&crit_);
Erik Språng08127a92016-11-16 16:41:30 +01002598 bitrate_kbps_ = rate_allocation.get_sum_kbps();
Peter Boström5811a392015-12-10 13:02:50 +01002599 observation_complete_.Set();
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002600 return 0;
2601 }
2602
2603 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002604 ASSERT_TRUE(Wait())
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002605 << "Timed out while waiting for encoder SetRates() call.";
perkjf5b2e512016-07-05 08:34:04 -07002606 WaitForEncoderTargetBitrateMatchStats();
2607 send_stream_->Stop();
2608 WaitForStatsReportZeroTargetBitrate();
2609 send_stream_->Start();
2610 WaitForEncoderTargetBitrateMatchStats();
2611 }
2612
2613 void WaitForEncoderTargetBitrateMatchStats() {
Peter Boström5811a392015-12-10 13:02:50 +01002614 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002615 VideoSendStream::Stats stats = send_stream_->GetStats();
2616 {
Peter Boströmf2f82832015-05-01 13:00:41 +02002617 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002618 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
2619 static_cast<int>(bitrate_kbps_)) {
2620 return;
2621 }
2622 }
2623 SleepMs(1);
2624 }
2625 FAIL()
2626 << "Timed out waiting for stats reporting the currently set bitrate.";
2627 }
2628
perkjf5b2e512016-07-05 08:34:04 -07002629 void WaitForStatsReportZeroTargetBitrate() {
2630 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
2631 if (send_stream_->GetStats().target_media_bitrate_bps == 0) {
2632 return;
2633 }
2634 SleepMs(1);
2635 }
2636 FAIL() << "Timed out waiting for stats reporting zero bitrate.";
2637 }
2638
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002639 private:
stefanf116bd02015-10-27 08:29:42 -07002640 rtc::CriticalSection crit_;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002641 VideoSendStream* send_stream_;
2642 uint32_t bitrate_kbps_ GUARDED_BY(crit_);
2643 } test;
2644
stefane74eef12016-01-08 06:47:13 -08002645 RunBaseTest(&test);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002646}
2647
philipel266f0a42016-11-28 08:49:07 -08002648TEST_P(EndToEndTest, GetStats) {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002649 static const int kStartBitrateBps = 3000000;
Peter Boströmdef398832015-05-27 17:59:11 +02002650 static const int kExpectedRenderDelayMs = 20;
tommi2e82f382016-06-21 00:26:43 -07002651
2652 class ReceiveStreamRenderer : public rtc::VideoSinkInterface<VideoFrame> {
2653 public:
2654 ReceiveStreamRenderer() {}
2655
2656 private:
2657 void OnFrame(const VideoFrame& video_frame) override {}
2658 };
2659
nissed30a1112016-04-18 05:15:22 -07002660 class StatsObserver : public test::EndToEndTest,
2661 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002662 public:
stefanf116bd02015-10-27 08:29:42 -07002663 StatsObserver()
2664 : EndToEndTest(kLongTimeoutMs),
Peter Boströmc6e16e32016-02-05 14:15:53 +01002665 encoder_(Clock::GetRealTimeClock(), 10),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002666 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002667 expected_send_ssrcs_(),
Peter Boström5811a392015-12-10 13:02:50 +01002668 check_stats_event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002669
2670 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002671 Action OnSendRtp(const uint8_t* packet, size_t length) override {
sprangcd349d92016-07-13 09:11:28 -07002672 // Drop every 25th packet => 4% loss.
2673 static const int kPacketLossFrac = 25;
2674 RTPHeader header;
2675 RtpUtility::RtpHeaderParser parser(packet, length);
2676 if (parser.Parse(&header) &&
2677 expected_send_ssrcs_.find(header.ssrc) !=
2678 expected_send_ssrcs_.end() &&
2679 header.sequenceNumber % kPacketLossFrac == 0) {
2680 return DROP_PACKET;
2681 }
Peter Boström5811a392015-12-10 13:02:50 +01002682 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002683 return SEND_PACKET;
2684 }
2685
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002686 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002687 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002688 return SEND_PACKET;
2689 }
2690
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002691 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002692 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002693 return SEND_PACKET;
2694 }
2695
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002696 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002697 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002698 return SEND_PACKET;
2699 }
2700
nissed30a1112016-04-18 05:15:22 -07002701 void OnFrame(const VideoFrame& video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002702 // Ensure that we have at least 5ms send side delay.
nissed30a1112016-04-18 05:15:22 -07002703 SleepMs(5);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002704 }
2705
2706 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002707 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2708 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2709 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002710
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002711 // Make sure all fields have been populated.
2712 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
2713 // always filled for all receivers.
2714 receive_stats_filled_["IncomingRate"] |=
2715 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002716
Peter Boströmb7d9a972015-12-18 16:01:11 +01002717 send_stats_filled_["DecoderImplementationName"] |=
2718 stats.decoder_implementation_name ==
2719 test::FakeDecoder::kImplementationName;
Peter Boströmdef398832015-05-27 17:59:11 +02002720 receive_stats_filled_["RenderDelayAsHighAsExpected"] |=
2721 stats.render_delay_ms >= kExpectedRenderDelayMs;
2722
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002723 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002724
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002725 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002726
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002727 receive_stats_filled_["StatisticsUpdated"] |=
2728 stats.rtcp_stats.cumulative_lost != 0 ||
2729 stats.rtcp_stats.extended_max_sequence_number != 0 ||
2730 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002731
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002732 receive_stats_filled_["DataCountersUpdated"] |=
2733 stats.rtp_stats.transmitted.payload_bytes != 0 ||
2734 stats.rtp_stats.fec.packets != 0 ||
2735 stats.rtp_stats.transmitted.header_bytes != 0 ||
2736 stats.rtp_stats.transmitted.packets != 0 ||
2737 stats.rtp_stats.transmitted.padding_bytes != 0 ||
2738 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002739
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002740 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002741 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002742
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002743 receive_stats_filled_["FrameCounts"] |=
2744 stats.frame_counts.key_frames != 0 ||
2745 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002746
pbosbb36fdf2015-07-09 07:48:14 -07002747 receive_stats_filled_["CName"] |= !stats.c_name.empty();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002748
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002749 receive_stats_filled_["RtcpPacketTypeCount"] |=
2750 stats.rtcp_packet_type_counts.fir_packets != 0 ||
2751 stats.rtcp_packet_type_counts.nack_packets != 0 ||
2752 stats.rtcp_packet_type_counts.pli_packets != 0 ||
2753 stats.rtcp_packet_type_counts.nack_requests != 0 ||
2754 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbosf42376c2015-08-28 07:35:32 -07002755
2756 assert(stats.current_payload_type == -1 ||
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002757 stats.current_payload_type == kFakeVideoSendPayloadType);
pbosf42376c2015-08-28 07:35:32 -07002758 receive_stats_filled_["IncomingPayloadType"] |=
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002759 stats.current_payload_type == kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002760 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002761
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002762 return AllStatsFilled(receive_stats_filled_);
2763 }
2764
2765 bool CheckSendStats() {
Peter Boström74f6e9e2016-04-04 17:56:10 +02002766 RTC_DCHECK(send_stream_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002767 VideoSendStream::Stats stats = send_stream_->GetStats();
2768
philipel20d05a92016-12-19 04:17:27 -08002769 size_t expected_num_streams = kNumSsrcs + expected_send_ssrcs_.size();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002770 send_stats_filled_["NumStreams"] |=
philipel20d05a92016-12-19 04:17:27 -08002771 stats.substreams.size() == expected_num_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002772
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002773 send_stats_filled_["CpuOveruseMetrics"] |=
Peter Boströme4499152016-02-05 11:13:28 +01002774 stats.avg_encode_time_ms != 0 && stats.encode_usage_percent != 0;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002775
Peter Boströmb7d9a972015-12-18 16:01:11 +01002776 send_stats_filled_["EncoderImplementationName"] |=
2777 stats.encoder_implementation_name ==
2778 test::FakeEncoder::kImplementationName;
2779
Pera48ddb72016-09-29 11:48:50 +02002780 send_stats_filled_["EncoderPreferredBitrate"] |=
2781 stats.preferred_media_bitrate_bps > 0;
2782
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002783 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002784 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002785 it != stats.substreams.end(); ++it) {
sprangcd349d92016-07-13 09:11:28 -07002786 if (expected_send_ssrcs_.find(it->first) == expected_send_ssrcs_.end())
2787 continue; // Probably RTX.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002788
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002789 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002790 stats.input_frame_rate != 0;
2791
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002792 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002793
2794 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
2795 stream_stats.rtcp_stats.cumulative_lost != 0 ||
2796 stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
2797 stream_stats.rtcp_stats.fraction_lost != 0;
2798
2799 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002800 stream_stats.rtp_stats.fec.packets != 0 ||
2801 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
2802 stream_stats.rtp_stats.retransmitted.packets != 0 ||
2803 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002804
sprangcd349d92016-07-13 09:11:28 -07002805 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Total",
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002806 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002807 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002808
sprangcd349d92016-07-13 09:11:28 -07002809 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Retransmit",
2810 it->first)] |=
2811 stream_stats.retransmit_bitrate_bps != 0;
2812
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002813 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002814 stream_stats.frame_counts.delta_frames != 0 ||
2815 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002816
2817 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
2818 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00002819
2820 send_stats_filled_[CompoundKey("Delay", it->first)] |=
2821 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002822
2823 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
2824 // report dropped packets.
2825 send_stats_filled_["RtcpPacketTypeCount"] |=
2826 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
2827 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
2828 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
2829 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
2830 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002831 }
2832
2833 return AllStatsFilled(send_stats_filled_);
2834 }
2835
2836 std::string CompoundKey(const char* name, uint32_t ssrc) {
2837 std::ostringstream oss;
2838 oss << name << "_" << ssrc;
2839 return oss.str();
2840 }
2841
2842 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
sprangcd349d92016-07-13 09:11:28 -07002843 for (const auto& stat : stats_map) {
2844 if (!stat.second)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002845 return false;
2846 }
2847 return true;
2848 }
2849
stefane74eef12016-01-08 06:47:13 -08002850 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
2851 FakeNetworkPipe::Config network_config;
2852 network_config.loss_percent = 5;
2853 return new test::PacketTransport(
2854 sender_call, this, test::PacketTransport::kSender, network_config);
2855 }
2856
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002857 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002858 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01002859 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002860 return config;
2861 }
2862
perkjfa10b552016-10-02 23:45:26 -07002863 // This test use other VideoStream settings than the the default settings
2864 // implemented in DefaultVideoStreamFactory. Therefore this test implement
2865 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
2866 // in ModifyVideoConfigs.
2867 class VideoStreamFactory
2868 : public VideoEncoderConfig::VideoStreamFactoryInterface {
2869 public:
2870 VideoStreamFactory() {}
2871
2872 private:
2873 std::vector<VideoStream> CreateEncoderStreams(
2874 int width,
2875 int height,
2876 const VideoEncoderConfig& encoder_config) override {
2877 std::vector<VideoStream> streams =
2878 test::CreateVideoStreams(width, height, encoder_config);
2879 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
2880 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
2881 streams[i].min_bitrate_bps = 10000;
2882 streams[i].target_bitrate_bps = 15000;
2883 streams[i].max_bitrate_bps = 20000;
2884 }
2885 return streams;
2886 }
2887 };
2888
stefanff483612015-12-21 03:14:00 -08002889 void ModifyVideoConfigs(
2890 VideoSendStream::Config* send_config,
2891 std::vector<VideoReceiveStream::Config>* receive_configs,
2892 VideoEncoderConfig* encoder_config) override {
perkjfa10b552016-10-02 23:45:26 -07002893 encoder_config->video_stream_factory =
2894 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002895 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002896 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002897
sprangcd349d92016-07-13 09:11:28 -07002898 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2899 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
2900
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002901 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002902 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002903 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002904 expected_receive_ssrcs_.push_back(
2905 (*receive_configs)[i].rtp.remote_ssrc);
Peter Boströmdef398832015-05-27 17:59:11 +02002906 (*receive_configs)[i].render_delay_ms = kExpectedRenderDelayMs;
tommi2e82f382016-06-21 00:26:43 -07002907 (*receive_configs)[i].renderer = &receive_stream_renderer_;
sprangcd349d92016-07-13 09:11:28 -07002908 (*receive_configs)[i].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2909
2910 (*receive_configs)[i].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
2911 kSendRtxSsrcs[i];
2912 (*receive_configs)[i].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
2913 kSendRtxPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002914 }
sprangcd349d92016-07-13 09:11:28 -07002915
2916 for (size_t i = 0; i < kNumSsrcs; ++i)
2917 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
2918
Peter Boströmc6e16e32016-02-05 14:15:53 +01002919 // Use a delayed encoder to make sure we see CpuOveruseMetrics stats that
2920 // are non-zero.
2921 send_config->encoder_settings.encoder = &encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002922 }
2923
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002924 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00002925
stefanff483612015-12-21 03:14:00 -08002926 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002927 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002928 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002929 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002930 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002931 }
2932
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002933 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002934 Clock* clock = Clock::GetRealTimeClock();
2935 int64_t now = clock->TimeInMilliseconds();
2936 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
2937 bool receive_ok = false;
2938 bool send_ok = false;
2939
2940 while (now < stop_time) {
2941 if (!receive_ok)
2942 receive_ok = CheckReceiveStats();
2943 if (!send_ok)
2944 send_ok = CheckSendStats();
2945
2946 if (receive_ok && send_ok)
2947 return;
2948
2949 int64_t time_until_timout_ = stop_time - now;
2950 if (time_until_timout_ > 0)
Peter Boström5811a392015-12-10 13:02:50 +01002951 check_stats_event_.Wait(time_until_timout_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002952 now = clock->TimeInMilliseconds();
2953 }
2954
2955 ADD_FAILURE() << "Timed out waiting for filled stats.";
2956 for (std::map<std::string, bool>::const_iterator it =
2957 receive_stats_filled_.begin();
2958 it != receive_stats_filled_.end();
2959 ++it) {
2960 if (!it->second) {
2961 ADD_FAILURE() << "Missing receive stats: " << it->first;
2962 }
2963 }
2964
2965 for (std::map<std::string, bool>::const_iterator it =
2966 send_stats_filled_.begin();
2967 it != send_stats_filled_.end();
2968 ++it) {
2969 if (!it->second) {
2970 ADD_FAILURE() << "Missing send stats: " << it->first;
2971 }
2972 }
2973 }
2974
Peter Boströmc6e16e32016-02-05 14:15:53 +01002975 test::DelayedEncoder encoder_;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002976 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002977 std::map<std::string, bool> receive_stats_filled_;
2978
2979 VideoSendStream* send_stream_;
2980 std::map<std::string, bool> send_stats_filled_;
2981
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002982 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002983 std::set<uint32_t> expected_send_ssrcs_;
2984 std::string expected_cname_;
2985
Peter Boström5811a392015-12-10 13:02:50 +01002986 rtc::Event check_stats_event_;
tommi2e82f382016-06-21 00:26:43 -07002987 ReceiveStreamRenderer receive_stream_renderer_;
stefanf116bd02015-10-27 08:29:42 -07002988 } test;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002989
philipel266f0a42016-11-28 08:49:07 -08002990 // TODO(philipel): Implement statistics for the new video jitter buffer.
2991 if (GetParam() == new_jb_enabled)
2992 return;
2993
stefane74eef12016-01-08 06:47:13 -08002994 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002995}
2996
sprang1a646ee2016-12-01 06:34:11 -08002997class RtcpXrObserver : public test::EndToEndTest {
2998 public:
sprang44b3ef62017-01-13 07:30:25 -08002999 RtcpXrObserver(bool enable_rrtr, bool enable_target_bitrate)
sprang1a646ee2016-12-01 06:34:11 -08003000 : EndToEndTest(test::CallTest::kDefaultTimeoutMs),
3001 enable_rrtr_(enable_rrtr),
sprang44b3ef62017-01-13 07:30:25 -08003002 enable_target_bitrate_(enable_target_bitrate),
sprang1a646ee2016-12-01 06:34:11 -08003003 sent_rtcp_sr_(0),
3004 sent_rtcp_rr_(0),
3005 sent_rtcp_rrtr_(0),
3006 sent_rtcp_target_bitrate_(false),
3007 sent_rtcp_dlrr_(0) {}
3008
3009 private:
3010 // Receive stream should send RR packets (and RRTR packets if enabled).
3011 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
3012 rtc::CritScope lock(&crit_);
3013 test::RtcpPacketParser parser;
3014 EXPECT_TRUE(parser.Parse(packet, length));
3015
3016 sent_rtcp_rr_ += parser.receiver_report()->num_packets();
3017 EXPECT_EQ(0, parser.sender_report()->num_packets());
3018 EXPECT_GE(1, parser.xr()->num_packets());
3019 if (parser.xr()->num_packets() > 0) {
3020 if (parser.xr()->rrtr())
3021 ++sent_rtcp_rrtr_;
3022 EXPECT_FALSE(parser.xr()->dlrr());
3023 }
3024
3025 return SEND_PACKET;
3026 }
3027 // Send stream should send SR packets (and DLRR packets if enabled).
3028 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
3029 rtc::CritScope lock(&crit_);
3030 test::RtcpPacketParser parser;
3031 EXPECT_TRUE(parser.Parse(packet, length));
3032
3033 sent_rtcp_sr_ += parser.sender_report()->num_packets();
3034 EXPECT_LE(parser.xr()->num_packets(), 1);
3035 if (parser.xr()->num_packets() > 0) {
3036 EXPECT_FALSE(parser.xr()->rrtr());
3037 if (parser.xr()->dlrr())
3038 ++sent_rtcp_dlrr_;
3039 if (parser.xr()->target_bitrate())
3040 sent_rtcp_target_bitrate_ = true;
3041 }
3042
3043 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
3044 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve &&
sprang44b3ef62017-01-13 07:30:25 -08003045 (sent_rtcp_target_bitrate_ || !enable_target_bitrate_)) {
sprang1a646ee2016-12-01 06:34:11 -08003046 if (enable_rrtr_) {
3047 EXPECT_GT(sent_rtcp_rrtr_, 0);
3048 EXPECT_GT(sent_rtcp_dlrr_, 0);
3049 } else {
3050 EXPECT_EQ(sent_rtcp_rrtr_, 0);
3051 EXPECT_EQ(sent_rtcp_dlrr_, 0);
3052 }
sprang44b3ef62017-01-13 07:30:25 -08003053 EXPECT_EQ(enable_target_bitrate_, sent_rtcp_target_bitrate_);
sprang1a646ee2016-12-01 06:34:11 -08003054 observation_complete_.Set();
3055 }
3056 return SEND_PACKET;
3057 }
3058
3059 void ModifyVideoConfigs(
3060 VideoSendStream::Config* send_config,
3061 std::vector<VideoReceiveStream::Config>* receive_configs,
3062 VideoEncoderConfig* encoder_config) override {
sprang44b3ef62017-01-13 07:30:25 -08003063 if (enable_target_bitrate_) {
3064 // TargetBitrate only signaled for screensharing.
3065 encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
3066 }
sprang1a646ee2016-12-01 06:34:11 -08003067 (*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
3068 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
3069 enable_rrtr_;
3070 }
3071
3072 void PerformTest() override {
3073 EXPECT_TRUE(Wait())
3074 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
3075 }
3076
3077 static const int kNumRtcpReportPacketsToObserve = 5;
3078
3079 rtc::CriticalSection crit_;
sprang44b3ef62017-01-13 07:30:25 -08003080 const bool enable_rrtr_;
3081 const bool enable_target_bitrate_;
sprang1a646ee2016-12-01 06:34:11 -08003082 int sent_rtcp_sr_;
3083 int sent_rtcp_rr_ GUARDED_BY(&crit_);
3084 int sent_rtcp_rrtr_ GUARDED_BY(&crit_);
3085 bool sent_rtcp_target_bitrate_ GUARDED_BY(&crit_);
3086 int sent_rtcp_dlrr_;
3087};
3088
sprang44b3ef62017-01-13 07:30:25 -08003089TEST_P(EndToEndTest, TestExtendedReportsWithRrtrWithoutTargetBitrate) {
3090 RtcpXrObserver test(true, false);
sprang1a646ee2016-12-01 06:34:11 -08003091 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003092}
3093
sprang44b3ef62017-01-13 07:30:25 -08003094TEST_P(EndToEndTest, TestExtendedReportsWithoutRrtrWithoutTargetBitrate) {
3095 RtcpXrObserver test(false, false);
3096 RunBaseTest(&test);
3097}
3098
3099TEST_P(EndToEndTest, TestExtendedReportsWithRrtrWithTargetBitrate) {
3100 RtcpXrObserver test(true, true);
3101 RunBaseTest(&test);
3102}
3103
3104TEST_P(EndToEndTest, TestExtendedReportsWithoutRrtrWithTargetBitrate) {
3105 RtcpXrObserver test(false, true);
sprang1a646ee2016-12-01 06:34:11 -08003106 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003107}
3108
philipel266f0a42016-11-28 08:49:07 -08003109TEST_P(EndToEndTest, TestReceivedRtpPacketStats) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003110 static const size_t kNumRtpPacketsToSend = 5;
3111 class ReceivedRtpStatsObserver : public test::EndToEndTest {
3112 public:
3113 ReceivedRtpStatsObserver()
3114 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00003115 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003116 sent_rtp_(0) {}
3117
3118 private:
stefanff483612015-12-21 03:14:00 -08003119 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003120 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003121 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003122 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003123 }
3124
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003125 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003126 if (sent_rtp_ >= kNumRtpPacketsToSend) {
3127 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00003128 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
Peter Boström5811a392015-12-10 13:02:50 +01003129 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003130 }
3131 return DROP_PACKET;
3132 }
3133 ++sent_rtp_;
3134 return SEND_PACKET;
3135 }
3136
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003137 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003138 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003139 << "Timed out while verifying number of received RTP packets.";
3140 }
3141
3142 VideoReceiveStream* receive_stream_;
3143 uint32_t sent_rtp_;
3144 } test;
3145
stefane74eef12016-01-08 06:47:13 -08003146 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003147}
3148
philipel266f0a42016-11-28 08:49:07 -08003149TEST_P(EndToEndTest, SendsSetSsrc) {
3150 TestSendsSetSsrcs(1, false);
3151}
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003152
philipel266f0a42016-11-28 08:49:07 -08003153TEST_P(EndToEndTest, SendsSetSimulcastSsrcs) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003154 TestSendsSetSsrcs(kNumSsrcs, false);
3155}
3156
philipel266f0a42016-11-28 08:49:07 -08003157TEST_P(EndToEndTest, CanSwitchToUseAllSsrcs) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003158 TestSendsSetSsrcs(kNumSsrcs, true);
3159}
3160
philipel266f0a42016-11-28 08:49:07 -08003161TEST_P(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003162 class ObserveRedundantPayloads: public test::EndToEndTest {
3163 public:
3164 ObserveRedundantPayloads()
3165 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003166 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003167 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
3168 }
3169 }
3170
3171 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003172 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003173 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003174 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003175
3176 if (!registered_rtx_ssrc_[header.ssrc])
3177 return SEND_PACKET;
3178
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003179 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003180 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003181 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003182
3183 if (!packet_is_redundant_payload)
3184 return SEND_PACKET;
3185
3186 if (!observed_redundant_retransmission_[header.ssrc]) {
3187 observed_redundant_retransmission_[header.ssrc] = true;
3188 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01003189 observation_complete_.Set();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003190 }
3191
3192 return SEND_PACKET;
3193 }
3194
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003195 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003196
perkjfa10b552016-10-02 23:45:26 -07003197 // This test use other VideoStream settings than the the default settings
3198 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3199 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3200 // in ModifyVideoConfigs.
3201 class VideoStreamFactory
3202 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3203 public:
3204 VideoStreamFactory() {}
3205
3206 private:
3207 std::vector<VideoStream> CreateEncoderStreams(
3208 int width,
3209 int height,
3210 const VideoEncoderConfig& encoder_config) override {
3211 std::vector<VideoStream> streams =
3212 test::CreateVideoStreams(width, height, encoder_config);
3213 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
3214 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3215 streams[i].min_bitrate_bps = 10000;
3216 streams[i].target_bitrate_bps = 15000;
3217 streams[i].max_bitrate_bps = 20000;
3218 }
3219 return streams;
3220 }
3221 };
3222
stefanff483612015-12-21 03:14:00 -08003223 void ModifyVideoConfigs(
3224 VideoSendStream::Config* send_config,
3225 std::vector<VideoReceiveStream::Config>* receive_configs,
3226 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003227 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
perkjfa10b552016-10-02 23:45:26 -07003228 encoder_config->video_stream_factory =
3229 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003230 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003231
3232 for (size_t i = 0; i < kNumSsrcs; ++i)
3233 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00003234
3235 // Significantly higher than max bitrates for all video streams -> forcing
3236 // padding to trigger redundant padding on all RTX SSRCs.
3237 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003238 }
3239
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003240 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003241 EXPECT_TRUE(Wait())
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003242 << "Timed out while waiting for redundant payloads on all SSRCs.";
3243 }
3244
3245 private:
3246 size_t ssrcs_to_observe_;
3247 std::map<uint32_t, bool> observed_redundant_retransmission_;
3248 std::map<uint32_t, bool> registered_rtx_ssrc_;
3249 } test;
3250
stefane74eef12016-01-08 06:47:13 -08003251 RunBaseTest(&test);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003252}
3253
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003254void EndToEndTest::TestRtpStatePreservation(bool use_rtx,
3255 bool provoke_rtcpsr_before_rtp) {
perkjfa10b552016-10-02 23:45:26 -07003256 // This test use other VideoStream settings than the the default settings
3257 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3258 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3259 // in ModifyVideoConfigs.
3260 class VideoStreamFactory
3261 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3262 public:
3263 VideoStreamFactory() {}
3264
3265 private:
3266 std::vector<VideoStream> CreateEncoderStreams(
3267 int width,
3268 int height,
3269 const VideoEncoderConfig& encoder_config) override {
3270 std::vector<VideoStream> streams =
3271 test::CreateVideoStreams(width, height, encoder_config);
3272
3273 if (encoder_config.number_of_streams > 1) {
3274 // Lower bitrates so that all streams send initially.
kwibergaf476c72016-11-28 15:21:39 -08003275 RTC_DCHECK_EQ(3, encoder_config.number_of_streams);
perkjfa10b552016-10-02 23:45:26 -07003276 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3277 streams[i].min_bitrate_bps = 10000;
3278 streams[i].target_bitrate_bps = 15000;
3279 streams[i].max_bitrate_bps = 20000;
3280 }
3281 } else {
3282 // Use the same total bitrates when sending a single stream to avoid
3283 // lowering
3284 // the bitrate estimate and requiring a subsequent rampup.
3285 streams[0].min_bitrate_bps = 3 * 10000;
3286 streams[0].target_bitrate_bps = 3 * 15000;
3287 streams[0].max_bitrate_bps = 3 * 20000;
3288 }
3289 return streams;
3290 }
3291 };
3292
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003293 class RtpSequenceObserver : public test::RtpRtcpObserver {
3294 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003295 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003296 : test::RtpRtcpObserver(kDefaultTimeoutMs),
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003297 ssrcs_to_observe_(kNumSsrcs) {
3298 for (size_t i = 0; i < kNumSsrcs; ++i) {
danilchap32cd2c42016-08-01 06:58:34 -07003299 ssrc_is_rtx_[kVideoSendSsrcs[i]] = false;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003300 if (use_rtx)
danilchap32cd2c42016-08-01 06:58:34 -07003301 ssrc_is_rtx_[kSendRtxSsrcs[i]] = true;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003302 }
3303 }
3304
3305 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
Peter Boströmf2f82832015-05-01 13:00:41 +02003306 rtc::CritScope lock(&crit_);
danilchap34877ee2016-02-01 08:25:04 -08003307 ssrc_observed_.clear();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003308 ssrcs_to_observe_ = num_expected_ssrcs;
3309 }
3310
3311 private:
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003312 void ValidateTimestampGap(uint32_t ssrc,
3313 uint32_t timestamp,
3314 bool only_padding)
3315 EXCLUSIVE_LOCKS_REQUIRED(crit_) {
3316 static const int32_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
3317 auto timestamp_it = last_observed_timestamp_.find(ssrc);
3318 if (timestamp_it == last_observed_timestamp_.end()) {
3319 EXPECT_FALSE(only_padding);
3320 last_observed_timestamp_[ssrc] = timestamp;
3321 } else {
3322 // Verify timestamps are reasonably close.
3323 uint32_t latest_observed = timestamp_it->second;
3324 // Wraparound handling is unnecessary here as long as an int variable
3325 // is used to store the result.
3326 int32_t timestamp_gap = timestamp - latest_observed;
3327 EXPECT_LE(std::abs(timestamp_gap), kMaxTimestampGap)
3328 << "Gap in timestamps (" << latest_observed << " -> " << timestamp
3329 << ") too large for SSRC: " << ssrc << ".";
3330 timestamp_it->second = timestamp;
3331 }
3332 }
3333
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003334 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003335 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003336 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003337 const uint32_t ssrc = header.ssrc;
danilchap5c35cf92016-02-03 14:14:49 -08003338 const int64_t sequence_number =
3339 seq_numbers_unwrapper_.Unwrap(header.sequenceNumber);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003340 const uint32_t timestamp = header.timestamp;
danilchap34877ee2016-02-01 08:25:04 -08003341 const bool only_padding =
3342 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003343
danilchap32cd2c42016-08-01 06:58:34 -07003344 EXPECT_TRUE(ssrc_is_rtx_.find(ssrc) != ssrc_is_rtx_.end())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003345 << "Received SSRC that wasn't configured: " << ssrc;
3346
danilchap5c35cf92016-02-03 14:14:49 -08003347 static const int64_t kMaxSequenceNumberGap = 100;
3348 std::list<int64_t>* seq_numbers = &last_observed_seq_numbers_[ssrc];
3349 if (seq_numbers->empty()) {
3350 seq_numbers->push_back(sequence_number);
3351 } else {
3352 // We shouldn't get replays of previous sequence numbers.
3353 for (int64_t observed : *seq_numbers) {
3354 EXPECT_NE(observed, sequence_number)
3355 << "Received sequence number " << sequence_number
3356 << " for SSRC " << ssrc << " 2nd time.";
3357 }
3358 // Verify sequence numbers are reasonably close.
3359 int64_t latest_observed = seq_numbers->back();
3360 int64_t sequence_number_gap = sequence_number - latest_observed;
3361 EXPECT_LE(std::abs(sequence_number_gap), kMaxSequenceNumberGap)
3362 << "Gap in sequence numbers (" << latest_observed << " -> "
3363 << sequence_number << ") too large for SSRC: " << ssrc << ".";
3364 seq_numbers->push_back(sequence_number);
3365 if (seq_numbers->size() >= kMaxSequenceNumberGap) {
3366 seq_numbers->pop_front();
3367 }
3368 }
3369
danilchap32cd2c42016-08-01 06:58:34 -07003370 if (!ssrc_is_rtx_[ssrc]) {
3371 rtc::CritScope lock(&crit_);
3372 ValidateTimestampGap(ssrc, timestamp, only_padding);
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003373
danilchap32cd2c42016-08-01 06:58:34 -07003374 // Wait for media packets on all ssrcs.
3375 if (!ssrc_observed_[ssrc] && !only_padding) {
3376 ssrc_observed_[ssrc] = true;
3377 if (--ssrcs_to_observe_ == 0)
3378 observation_complete_.Set();
3379 }
danilchap34877ee2016-02-01 08:25:04 -08003380 }
3381
danilchapf4b9c772016-01-28 06:14:24 -08003382 return SEND_PACKET;
3383 }
3384
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003385 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
3386 test::RtcpPacketParser rtcp_parser;
3387 rtcp_parser.Parse(packet, length);
3388 if (rtcp_parser.sender_report()->num_packets() > 0) {
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02003389 uint32_t ssrc = rtcp_parser.sender_report()->sender_ssrc();
3390 uint32_t rtcp_timestamp = rtcp_parser.sender_report()->rtp_timestamp();
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003391
3392 rtc::CritScope lock(&crit_);
3393 ValidateTimestampGap(ssrc, rtcp_timestamp, false);
3394 }
3395 return SEND_PACKET;
3396 }
3397
danilchap5c35cf92016-02-03 14:14:49 -08003398 SequenceNumberUnwrapper seq_numbers_unwrapper_;
3399 std::map<uint32_t, std::list<int64_t>> last_observed_seq_numbers_;
danilchap34877ee2016-02-01 08:25:04 -08003400 std::map<uint32_t, uint32_t> last_observed_timestamp_;
danilchap32cd2c42016-08-01 06:58:34 -07003401 std::map<uint32_t, bool> ssrc_is_rtx_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003402
Peter Boströmf2f82832015-05-01 13:00:41 +02003403 rtc::CriticalSection crit_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003404 size_t ssrcs_to_observe_ GUARDED_BY(crit_);
danilchap34877ee2016-02-01 08:25:04 -08003405 std::map<uint32_t, bool> ssrc_observed_ GUARDED_BY(crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003406 } observer(use_rtx);
3407
skvlad11a9cbf2016-10-07 11:53:05 -07003408 Call::Config config(&event_log_);
3409 CreateCalls(config, config);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003410
stefanf116bd02015-10-27 08:29:42 -07003411 test::PacketTransport send_transport(sender_call_.get(), &observer,
3412 test::PacketTransport::kSender,
3413 FakeNetworkPipe::Config());
3414 test::PacketTransport receive_transport(nullptr, &observer,
3415 test::PacketTransport::kReceiver,
3416 FakeNetworkPipe::Config());
3417 send_transport.SetReceiver(receiver_call_->Receiver());
3418 receive_transport.SetReceiver(sender_call_->Receiver());
3419
brandtr841de6a2016-11-15 07:10:52 -08003420 CreateSendConfig(kNumSsrcs, 0, 0, &send_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003421
3422 if (use_rtx) {
3423 for (size_t i = 0; i < kNumSsrcs; ++i) {
stefanff483612015-12-21 03:14:00 -08003424 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003425 }
stefanff483612015-12-21 03:14:00 -08003426 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003427 }
3428
perkjfa10b552016-10-02 23:45:26 -07003429 video_encoder_config_.video_stream_factory =
3430 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003431 // Use the same total bitrates when sending a single stream to avoid lowering
3432 // the bitrate estimate and requiring a subsequent rampup.
perkj26091b12016-09-01 01:17:40 -07003433 VideoEncoderConfig one_stream = video_encoder_config_.Copy();
perkjfa10b552016-10-02 23:45:26 -07003434 // one_stream.streams.resize(1);
3435 one_stream.number_of_streams = 1;
stefanf116bd02015-10-27 08:29:42 -07003436 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003437
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003438 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003439 CreateFrameGeneratorCapturer(30, 1280, 720);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003440
3441 Start();
Peter Boström5811a392015-12-10 13:02:50 +01003442 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003443 << "Timed out waiting for all SSRCs to send packets.";
3444
3445 // Test stream resetting more than once to make sure that the state doesn't
3446 // get set once (this could be due to using std::map::insert for instance).
3447 for (size_t i = 0; i < 3; ++i) {
3448 frame_generator_capturer_->Stop();
stefanff483612015-12-21 03:14:00 -08003449 sender_call_->DestroyVideoSendStream(video_send_stream_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003450
3451 // Re-create VideoSendStream with only one stream.
perkj26091b12016-09-01 01:17:40 -07003452 video_send_stream_ = sender_call_->CreateVideoSendStream(
3453 video_send_config_.Copy(), one_stream.Copy());
stefanff483612015-12-21 03:14:00 -08003454 video_send_stream_->Start();
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003455 if (provoke_rtcpsr_before_rtp) {
3456 // Rapid Resync Request forces sending RTCP Sender Report back.
3457 // Using this request speeds up this test because then there is no need
3458 // to wait for a second for periodic Sender Report.
3459 rtcp::RapidResyncRequest force_send_sr_back_request;
3460 rtc::Buffer packet = force_send_sr_back_request.Build();
3461 static_cast<webrtc::test::DirectTransport&>(receive_transport)
3462 .SendRtcp(packet.data(), packet.size());
3463 }
perkjfa10b552016-10-02 23:45:26 -07003464 CreateFrameGeneratorCapturer(30, 1280, 720);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003465 frame_generator_capturer_->Start();
3466
3467 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003468 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003469
3470 // Reconfigure back to use all streams.
perkj26091b12016-09-01 01:17:40 -07003471 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003472 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003473 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003474 << "Timed out waiting for all SSRCs to send packets.";
3475
3476 // Reconfigure down to one stream.
perkj26091b12016-09-01 01:17:40 -07003477 video_send_stream_->ReconfigureVideoEncoder(one_stream.Copy());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003478 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003479 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003480
3481 // Reconfigure back to use all streams.
perkj26091b12016-09-01 01:17:40 -07003482 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003483 observer.ResetExpectedSsrcs(kNumSsrcs);
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
stefanf116bd02015-10-27 08:29:42 -07003488 send_transport.StopSending();
3489 receive_transport.StopSending();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003490
3491 Stop();
3492 DestroyStreams();
3493}
3494
philipel266f0a42016-11-28 08:49:07 -08003495TEST_P(EndToEndTest, RestartingSendStreamPreservesRtpState) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003496 TestRtpStatePreservation(false, false);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003497}
3498
philipel266f0a42016-11-28 08:49:07 -08003499TEST_P(EndToEndTest, RestartingSendStreamPreservesRtpStatesWithRtx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003500 TestRtpStatePreservation(true, false);
3501}
3502
philipel266f0a42016-11-28 08:49:07 -08003503TEST_P(EndToEndTest, RestartingSendStreamKeepsRtpAndRtcpTimestampsSynced) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003504 TestRtpStatePreservation(true, true);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003505}
3506
philipel266f0a42016-11-28 08:49:07 -08003507TEST_P(EndToEndTest, RespectsNetworkState) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003508 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
3509 // down blocks until no more packets will be sent.
3510
3511 // Pacer will send from its packet list and then send required padding before
3512 // checking paused_ again. This should be enough for one round of pacing,
3513 // otherwise increase.
3514 static const int kNumAcceptedDowntimeRtp = 5;
3515 // A single RTCP may be in the pipeline.
3516 static const int kNumAcceptedDowntimeRtcp = 1;
3517 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
3518 public:
3519 NetworkStateTest()
3520 : EndToEndTest(kDefaultTimeoutMs),
3521 FakeEncoder(Clock::GetRealTimeClock()),
Peter Boström5811a392015-12-10 13:02:50 +01003522 encoded_frames_(false, false),
3523 packet_event_(false, false),
sprang867fb522015-08-03 04:38:41 -07003524 sender_call_(nullptr),
3525 receiver_call_(nullptr),
Jelena Marusiccd670222015-07-16 09:30:09 +02003526 sender_state_(kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003527 sender_rtp_(0),
3528 sender_rtcp_(0),
3529 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003530 down_frames_(0) {}
3531
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003532 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003533 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003534 ++sender_rtp_;
Peter Boström5811a392015-12-10 13:02:50 +01003535 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003536 return SEND_PACKET;
3537 }
3538
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003539 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003540 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003541 ++sender_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003542 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003543 return SEND_PACKET;
3544 }
3545
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003546 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003547 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
3548 return SEND_PACKET;
3549 }
3550
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003551 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003552 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003553 ++receiver_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003554 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003555 return SEND_PACKET;
3556 }
3557
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003558 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003559 sender_call_ = sender_call;
3560 receiver_call_ = receiver_call;
3561 }
3562
stefanff483612015-12-21 03:14:00 -08003563 void ModifyVideoConfigs(
3564 VideoSendStream::Config* send_config,
3565 std::vector<VideoReceiveStream::Config>* receive_configs,
3566 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003567 send_config->encoder_settings.encoder = this;
3568 }
3569
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003570 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003571 EXPECT_TRUE(encoded_frames_.Wait(kDefaultTimeoutMs))
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003572 << "No frames received by the encoder.";
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003573 // Wait for packets from both sender/receiver.
3574 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003575
skvlad7a43d252016-03-22 15:32:27 -07003576 // Sender-side network down for audio; there should be no effect on video
3577 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3578 WaitForPacketsOrSilence(false, false);
3579
3580 // Receiver-side network down for audio; no change expected
3581 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3582 WaitForPacketsOrSilence(false, false);
3583
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003584 // Sender-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003585 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003586 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003587 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003588 // After network goes down we shouldn't be encoding more frames.
Jelena Marusiccd670222015-07-16 09:30:09 +02003589 sender_state_ = kNetworkDown;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003590 }
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003591 // Wait for receiver-packets and no sender packets.
3592 WaitForPacketsOrSilence(true, false);
3593
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003594 // Receiver-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003595 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
3596 WaitForPacketsOrSilence(true, true);
3597
3598 // Network up for audio for both sides; video is still not expected to
3599 // start
3600 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
3601 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003602 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003603
3604 // Network back up again for both.
3605 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003606 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003607 // It's OK to encode frames again, as we're about to bring up the
3608 // network.
Jelena Marusiccd670222015-07-16 09:30:09 +02003609 sender_state_ = kNetworkUp;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003610 }
skvlad7a43d252016-03-22 15:32:27 -07003611 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
3612 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003613 WaitForPacketsOrSilence(false, false);
skvlad7a43d252016-03-22 15:32:27 -07003614
3615 // TODO(skvlad): add tests to verify that the audio streams are stopped
3616 // when the network goes down for audio once the workaround in
3617 // paced_sender.cc is removed.
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003618 }
3619
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07003620 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003621 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07003622 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003623 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003624 rtc::CritScope lock(&test_crit_);
Jelena Marusiccd670222015-07-16 09:30:09 +02003625 if (sender_state_ == kNetworkDown) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003626 ++down_frames_;
3627 EXPECT_LE(down_frames_, 1)
3628 << "Encoding more than one frame while network is down.";
3629 if (down_frames_ > 1)
Peter Boström5811a392015-12-10 13:02:50 +01003630 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003631 } else {
Peter Boström5811a392015-12-10 13:02:50 +01003632 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003633 }
3634 }
3635 return test::FakeEncoder::Encode(
3636 input_image, codec_specific_info, frame_types);
3637 }
3638
3639 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003640 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
3641 int64_t initial_time_ms = clock_->TimeInMilliseconds();
3642 int initial_sender_rtp;
3643 int initial_sender_rtcp;
3644 int initial_receiver_rtcp;
3645 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003646 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003647 initial_sender_rtp = sender_rtp_;
3648 initial_sender_rtcp = sender_rtcp_;
3649 initial_receiver_rtcp = receiver_rtcp_;
3650 }
3651 bool sender_done = false;
3652 bool receiver_done = false;
mflodmand1590b22015-12-09 07:07:59 -08003653 while (!sender_done || !receiver_done) {
Peter Boström5811a392015-12-10 13:02:50 +01003654 packet_event_.Wait(kSilenceTimeoutMs);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003655 int64_t time_now_ms = clock_->TimeInMilliseconds();
Peter Boströmf2f82832015-05-01 13:00:41 +02003656 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003657 if (sender_down) {
3658 ASSERT_LE(sender_rtp_ - initial_sender_rtp, kNumAcceptedDowntimeRtp)
3659 << "RTP sent during sender-side downtime.";
3660 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
3661 kNumAcceptedDowntimeRtcp)
3662 << "RTCP sent during sender-side downtime.";
3663 if (time_now_ms - initial_time_ms >=
3664 static_cast<int64_t>(kSilenceTimeoutMs)) {
3665 sender_done = true;
3666 }
3667 } else {
skvlad7a43d252016-03-22 15:32:27 -07003668 if (sender_rtp_ > initial_sender_rtp + kNumAcceptedDowntimeRtp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003669 sender_done = true;
3670 }
3671 if (receiver_down) {
3672 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
3673 kNumAcceptedDowntimeRtcp)
3674 << "RTCP sent during receiver-side downtime.";
3675 if (time_now_ms - initial_time_ms >=
3676 static_cast<int64_t>(kSilenceTimeoutMs)) {
3677 receiver_done = true;
3678 }
3679 } else {
skvlad7a43d252016-03-22 15:32:27 -07003680 if (receiver_rtcp_ > initial_receiver_rtcp + kNumAcceptedDowntimeRtcp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003681 receiver_done = true;
3682 }
3683 }
3684 }
3685
Peter Boströmf2f82832015-05-01 13:00:41 +02003686 rtc::CriticalSection test_crit_;
Peter Boström5811a392015-12-10 13:02:50 +01003687 rtc::Event encoded_frames_;
3688 rtc::Event packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003689 Call* sender_call_;
3690 Call* receiver_call_;
Jelena Marusiccd670222015-07-16 09:30:09 +02003691 NetworkState sender_state_ GUARDED_BY(test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003692 int sender_rtp_ GUARDED_BY(test_crit_);
3693 int sender_rtcp_ GUARDED_BY(test_crit_);
3694 int receiver_rtcp_ GUARDED_BY(test_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003695 int down_frames_ GUARDED_BY(test_crit_);
3696 } test;
3697
stefane74eef12016-01-08 06:47:13 -08003698 RunBaseTest(&test);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003699}
3700
philipel266f0a42016-11-28 08:49:07 -08003701TEST_P(EndToEndTest, CallReportsRttForSender) {
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003702 static const int kSendDelayMs = 30;
3703 static const int kReceiveDelayMs = 70;
skvlad11a9cbf2016-10-07 11:53:05 -07003704 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -07003705
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003706 FakeNetworkPipe::Config config;
3707 config.queue_delay_ms = kSendDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003708 test::DirectTransport sender_transport(config, sender_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003709 config.queue_delay_ms = kReceiveDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003710 test::DirectTransport receiver_transport(config, receiver_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003711 sender_transport.SetReceiver(receiver_call_->Receiver());
3712 receiver_transport.SetReceiver(sender_call_->Receiver());
3713
brandtr841de6a2016-11-15 07:10:52 -08003714 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07003715 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003716
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003717 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003718 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
3719 kDefaultHeight);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003720 Start();
3721
3722 int64_t start_time_ms = clock_->TimeInMilliseconds();
3723 while (true) {
3724 Call::Stats stats = sender_call_->GetStats();
3725 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
3726 clock_->TimeInMilliseconds())
3727 << "No RTT stats before timeout!";
3728 if (stats.rtt_ms != -1) {
Danil Chapovalov10e8f8e2016-09-07 15:05:29 +02003729 // To avoid failures caused by rounding or minor ntp clock adjustments,
3730 // relax expectation by 1ms.
3731 constexpr int kAllowedErrorMs = 1;
3732 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs - kAllowedErrorMs);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003733 break;
3734 }
3735 SleepMs(10);
3736 }
3737
philipel266f0a42016-11-28 08:49:07 -08003738 sender_transport.StopSending();
3739 receiver_transport.StopSending();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003740 Stop();
3741 DestroyStreams();
philipel266f0a42016-11-28 08:49:07 -08003742 DestroyCalls();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003743}
3744
skvlad7a43d252016-03-22 15:32:27 -07003745void EndToEndTest::VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08003746 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -07003747 VideoEncoder* encoder,
3748 Transport* transport) {
skvlad11a9cbf2016-10-07 11:53:05 -07003749 CreateSenderCall(Call::Config(&event_log_));
Sergey Ulanove2b15012016-11-22 16:08:30 -08003750 sender_call_->SignalChannelNetworkState(network_to_bring_up, kNetworkUp);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003751
brandtr841de6a2016-11-15 07:10:52 -08003752 CreateSendConfig(1, 0, 0, transport);
skvlad7a43d252016-03-22 15:32:27 -07003753 video_send_config_.encoder_settings.encoder = encoder;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003754 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003755 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
3756 kDefaultHeight);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003757
3758 Start();
3759 SleepMs(kSilenceTimeoutMs);
3760 Stop();
3761
3762 DestroyStreams();
3763}
3764
skvlad7a43d252016-03-22 15:32:27 -07003765void EndToEndTest::VerifyNewVideoReceiveStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08003766 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -07003767 Transport* transport) {
skvlad11a9cbf2016-10-07 11:53:05 -07003768 Call::Config config(&event_log_);
3769 CreateCalls(config, config);
Sergey Ulanove2b15012016-11-22 16:08:30 -08003770 receiver_call_->SignalChannelNetworkState(network_to_bring_up, kNetworkUp);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003771
stefanf116bd02015-10-27 08:29:42 -07003772 test::DirectTransport sender_transport(sender_call_.get());
solenberg4fbae2b2015-08-28 04:07:10 -07003773 sender_transport.SetReceiver(receiver_call_->Receiver());
brandtr841de6a2016-11-15 07:10:52 -08003774 CreateSendConfig(1, 0, 0, &sender_transport);
skvlad7a43d252016-03-22 15:32:27 -07003775 CreateMatchingReceiveConfigs(transport);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003776 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003777 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
3778 kDefaultHeight);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003779
3780 Start();
3781 SleepMs(kSilenceTimeoutMs);
3782 Stop();
3783
3784 sender_transport.StopSending();
3785
3786 DestroyStreams();
3787}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00003788
philipel266f0a42016-11-28 08:49:07 -08003789TEST_P(EndToEndTest, NewVideoSendStreamsRespectVideoNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07003790 class UnusedEncoder : public test::FakeEncoder {
3791 public:
3792 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
perkjfea93092016-05-14 00:58:48 -07003793
3794 int32_t InitEncode(const VideoCodec* config,
3795 int32_t number_of_cores,
3796 size_t max_payload_size) override {
3797 EXPECT_GT(config->startBitrate, 0u);
3798 return 0;
3799 }
skvlad7a43d252016-03-22 15:32:27 -07003800 int32_t Encode(const VideoFrame& input_image,
3801 const CodecSpecificInfo* codec_specific_info,
3802 const std::vector<FrameType>* frame_types) override {
3803 ADD_FAILURE() << "Unexpected frame encode.";
3804 return test::FakeEncoder::Encode(input_image, codec_specific_info,
3805 frame_types);
3806 }
3807 };
3808
3809 UnusedEncoder unused_encoder;
3810 UnusedTransport unused_transport;
3811 VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08003812 MediaType::AUDIO, &unused_encoder, &unused_transport);
skvlad7a43d252016-03-22 15:32:27 -07003813}
3814
philipel266f0a42016-11-28 08:49:07 -08003815TEST_P(EndToEndTest, NewVideoSendStreamsIgnoreAudioNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07003816 class RequiredEncoder : public test::FakeEncoder {
3817 public:
3818 RequiredEncoder()
3819 : FakeEncoder(Clock::GetRealTimeClock()), encoded_frame_(false) {}
3820 ~RequiredEncoder() {
3821 if (!encoded_frame_) {
3822 ADD_FAILURE() << "Didn't encode an expected frame";
3823 }
3824 }
3825 int32_t Encode(const VideoFrame& input_image,
3826 const CodecSpecificInfo* codec_specific_info,
3827 const std::vector<FrameType>* frame_types) override {
3828 encoded_frame_ = true;
3829 return test::FakeEncoder::Encode(input_image, codec_specific_info,
3830 frame_types);
3831 }
3832
3833 private:
3834 bool encoded_frame_;
3835 };
3836
3837 RequiredTransport required_transport(true /*rtp*/, false /*rtcp*/);
3838 RequiredEncoder required_encoder;
3839 VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08003840 MediaType::VIDEO, &required_encoder, &required_transport);
skvlad7a43d252016-03-22 15:32:27 -07003841}
3842
philipel266f0a42016-11-28 08:49:07 -08003843TEST_P(EndToEndTest, NewVideoReceiveStreamsRespectVideoNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07003844 UnusedTransport transport;
Sergey Ulanove2b15012016-11-22 16:08:30 -08003845 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::AUDIO, &transport);
skvlad7a43d252016-03-22 15:32:27 -07003846}
3847
philipel266f0a42016-11-28 08:49:07 -08003848TEST_P(EndToEndTest, NewVideoReceiveStreamsIgnoreAudioNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07003849 RequiredTransport transport(false /*rtp*/, true /*rtcp*/);
Sergey Ulanove2b15012016-11-22 16:08:30 -08003850 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::VIDEO, &transport);
skvlad7a43d252016-03-22 15:32:27 -07003851}
3852
Peter Boströmd7da1202015-06-05 14:09:38 +02003853void VerifyEmptyNackConfig(const NackConfig& config) {
3854 EXPECT_EQ(0, config.rtp_history_ms)
3855 << "Enabling NACK requires rtcp-fb: nack negotiation.";
3856}
3857
brandtrb5f2c3f2016-10-04 23:28:39 -07003858void VerifyEmptyUlpfecConfig(const UlpfecConfig& config) {
Peter Boströmd7da1202015-06-05 14:09:38 +02003859 EXPECT_EQ(-1, config.ulpfec_payload_type)
brandtr535830e2016-10-31 03:45:58 -07003860 << "Enabling ULPFEC requires rtpmap: ulpfec negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02003861 EXPECT_EQ(-1, config.red_payload_type)
brandtr535830e2016-10-31 03:45:58 -07003862 << "Enabling ULPFEC requires rtpmap: red negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02003863 EXPECT_EQ(-1, config.red_rtx_payload_type)
brandtr535830e2016-10-31 03:45:58 -07003864 << "Enabling RTX in ULPFEC requires rtpmap: rtx negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02003865}
3866
brandtr3d200bd2017-01-16 06:59:19 -08003867void VerifyEmptyFlexfecConfig(
3868 const VideoSendStream::Config::Rtp::Flexfec& config) {
3869 EXPECT_EQ(-1, config.payload_type)
brandtr1e3dfbf2016-11-16 22:45:19 -08003870 << "Enabling FlexFEC requires rtpmap: flexfec negotiation.";
brandtr3d200bd2017-01-16 06:59:19 -08003871 EXPECT_EQ(0U, config.ssrc)
brandtr1cfbd602016-12-08 04:17:53 -08003872 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
brandtr1e3dfbf2016-11-16 22:45:19 -08003873 EXPECT_TRUE(config.protected_media_ssrcs.empty())
3874 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
3875}
3876
philipel266f0a42016-11-28 08:49:07 -08003877TEST_P(EndToEndTest, VerifyDefaultSendConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003878 VideoSendStream::Config default_send_config(nullptr);
Peter Boströmd7da1202015-06-05 14:09:38 +02003879 EXPECT_EQ(0, default_send_config.rtp.nack.rtp_history_ms)
3880 << "Enabling NACK require rtcp-fb: nack negotiation.";
3881 EXPECT_TRUE(default_send_config.rtp.rtx.ssrcs.empty())
3882 << "Enabling RTX requires rtpmap: rtx negotiation.";
3883 EXPECT_TRUE(default_send_config.rtp.extensions.empty())
3884 << "Enabling RTP extensions require negotiation.";
3885
3886 VerifyEmptyNackConfig(default_send_config.rtp.nack);
brandtrb5f2c3f2016-10-04 23:28:39 -07003887 VerifyEmptyUlpfecConfig(default_send_config.rtp.ulpfec);
brandtr1e3dfbf2016-11-16 22:45:19 -08003888 VerifyEmptyFlexfecConfig(default_send_config.rtp.flexfec);
Peter Boströmd7da1202015-06-05 14:09:38 +02003889}
3890
philipel266f0a42016-11-28 08:49:07 -08003891TEST_P(EndToEndTest, VerifyDefaultVideoReceiveConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003892 VideoReceiveStream::Config default_receive_config(nullptr);
pbosda903ea2015-10-02 02:36:56 -07003893 EXPECT_EQ(RtcpMode::kCompound, default_receive_config.rtp.rtcp_mode)
Peter Boströmd7da1202015-06-05 14:09:38 +02003894 << "Reduced-size RTCP require rtcp-rsize to be negotiated.";
3895 EXPECT_FALSE(default_receive_config.rtp.remb)
3896 << "REMB require rtcp-fb: goog-remb to be negotiated.";
3897 EXPECT_FALSE(
3898 default_receive_config.rtp.rtcp_xr.receiver_reference_time_report)
3899 << "RTCP XR settings require rtcp-xr to be negotiated.";
3900 EXPECT_TRUE(default_receive_config.rtp.rtx.empty())
3901 << "Enabling RTX requires rtpmap: rtx negotiation.";
3902 EXPECT_TRUE(default_receive_config.rtp.extensions.empty())
3903 << "Enabling RTP extensions require negotiation.";
3904
3905 VerifyEmptyNackConfig(default_receive_config.rtp.nack);
brandtrb5f2c3f2016-10-04 23:28:39 -07003906 VerifyEmptyUlpfecConfig(default_receive_config.rtp.ulpfec);
Peter Boströmd7da1202015-06-05 14:09:38 +02003907}
3908
philipel266f0a42016-11-28 08:49:07 -08003909TEST_P(EndToEndTest, VerifyDefaultFlexfecReceiveConfigParameters) {
brandtr8313a6f2017-01-13 07:41:19 -08003910 test::NullTransport rtcp_send_transport;
3911 FlexfecReceiveStream::Config default_receive_config(&rtcp_send_transport);
brandtr1cfbd602016-12-08 04:17:53 -08003912 EXPECT_EQ(-1, default_receive_config.payload_type)
3913 << "Enabling FlexFEC requires rtpmap: flexfec negotiation.";
3914 EXPECT_EQ(0U, default_receive_config.remote_ssrc)
3915 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
3916 EXPECT_TRUE(default_receive_config.protected_media_ssrcs.empty())
3917 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
brandtr1e3dfbf2016-11-16 22:45:19 -08003918}
3919
philipel266f0a42016-11-28 08:49:07 -08003920TEST_P(EndToEndTest, TransportSeqNumOnAudioAndVideo) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003921 static const int kExtensionId = 8;
3922 class TransportSequenceNumberTest : public test::EndToEndTest {
3923 public:
3924 TransportSequenceNumberTest()
3925 : EndToEndTest(kDefaultTimeoutMs),
3926 video_observed_(false),
3927 audio_observed_(false) {
3928 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
3929 kExtensionId);
3930 }
3931
3932 size_t GetNumVideoStreams() const override { return 1; }
3933 size_t GetNumAudioStreams() const override { return 1; }
3934
3935 void ModifyVideoConfigs(
3936 VideoSendStream::Config* send_config,
3937 std::vector<VideoReceiveStream::Config>* receive_configs,
3938 VideoEncoderConfig* encoder_config) override {
3939 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07003940 send_config->rtp.extensions.push_back(RtpExtension(
3941 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003942 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3943 }
3944
3945 void ModifyAudioConfigs(
3946 AudioSendStream::Config* send_config,
3947 std::vector<AudioReceiveStream::Config>* receive_configs) override {
3948 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07003949 send_config->rtp.extensions.push_back(RtpExtension(
3950 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003951 (*receive_configs)[0].rtp.extensions.clear();
3952 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3953 }
3954
3955 Action OnSendRtp(const uint8_t* packet, size_t length) override {
3956 RTPHeader header;
3957 EXPECT_TRUE(parser_->Parse(packet, length, &header));
3958 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
3959 // Unwrap packet id and verify uniqueness.
3960 int64_t packet_id =
3961 unwrapper_.Unwrap(header.extension.transportSequenceNumber);
3962 EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
3963
3964 if (header.ssrc == kVideoSendSsrcs[0])
3965 video_observed_ = true;
3966 if (header.ssrc == kAudioSendSsrc)
3967 audio_observed_ = true;
3968 if (audio_observed_ && video_observed_ &&
3969 received_packet_ids_.size() == 50) {
3970 size_t packet_id_range =
3971 *received_packet_ids_.rbegin() - *received_packet_ids_.begin() + 1;
3972 EXPECT_EQ(received_packet_ids_.size(), packet_id_range);
3973 observation_complete_.Set();
3974 }
3975 return SEND_PACKET;
3976 }
3977
3978 void PerformTest() override {
3979 EXPECT_TRUE(Wait()) << "Timed out while waiting for audio and video "
3980 "packets with transport sequence number.";
3981 }
3982
3983 private:
3984 bool video_observed_;
3985 bool audio_observed_;
3986 SequenceNumberUnwrapper unwrapper_;
3987 std::set<int64_t> received_packet_ids_;
3988 } test;
3989
stefane74eef12016-01-08 06:47:13 -08003990 RunBaseTest(&test);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003991}
palmkviste75f2042016-09-28 06:19:48 -07003992
3993class EndToEndLogTest : public EndToEndTest {
3994 void SetUp() { paths_.clear(); }
3995 void TearDown() {
3996 for (const auto& path : paths_) {
3997 rtc::RemoveFile(path);
3998 }
3999 }
4000
4001 public:
4002 int AddFile() {
4003 paths_.push_back(test::TempFilename(test::OutputPath(), "test_file"));
4004 return static_cast<int>(paths_.size()) - 1;
4005 }
4006
4007 rtc::PlatformFile OpenFile(int idx) {
4008 return rtc::OpenPlatformFile(paths_[idx]);
4009 }
4010
4011 void LogSend(bool open) {
4012 if (open) {
4013 video_send_stream_->EnableEncodedFrameRecording(
4014 std::vector<rtc::PlatformFile>(1, OpenFile(AddFile())), 0);
4015 } else {
4016 video_send_stream_->DisableEncodedFrameRecording();
4017 }
4018 }
4019 void LogReceive(bool open) {
4020 if (open) {
4021 video_receive_streams_[0]->EnableEncodedFrameRecording(
4022 OpenFile(AddFile()), 0);
4023 } else {
4024 video_receive_streams_[0]->DisableEncodedFrameRecording();
4025 }
4026 }
4027
4028 std::vector<std::string> paths_;
4029};
4030
philipel266f0a42016-11-28 08:49:07 -08004031TEST_P(EndToEndLogTest, LogsEncodedFramesWhenRequested) {
palmkviste75f2042016-09-28 06:19:48 -07004032 static const int kNumFramesToRecord = 10;
4033 class LogEncodingObserver : public test::EndToEndTest,
4034 public EncodedFrameObserver {
4035 public:
4036 explicit LogEncodingObserver(EndToEndLogTest* fixture)
4037 : EndToEndTest(kDefaultTimeoutMs),
4038 fixture_(fixture),
4039 recorded_frames_(0) {}
4040
4041 void PerformTest() override {
4042 fixture_->LogSend(true);
4043 fixture_->LogReceive(true);
4044 ASSERT_TRUE(Wait()) << "Timed out while waiting for frame logging.";
4045 }
4046
4047 void ModifyVideoConfigs(
4048 VideoSendStream::Config* send_config,
4049 std::vector<VideoReceiveStream::Config>* receive_configs,
4050 VideoEncoderConfig* encoder_config) override {
magjed509e4fe2016-11-18 01:34:11 -08004051 encoder_.reset(VP8Encoder::Create());
palmkviste75f2042016-09-28 06:19:48 -07004052 decoder_.reset(VP8Decoder::Create());
4053
4054 send_config->post_encode_callback = this;
4055 send_config->encoder_settings.payload_name = "VP8";
4056 send_config->encoder_settings.encoder = encoder_.get();
4057
4058 (*receive_configs)[0].decoders.resize(1);
4059 (*receive_configs)[0].decoders[0].payload_type =
4060 send_config->encoder_settings.payload_type;
4061 (*receive_configs)[0].decoders[0].payload_name =
4062 send_config->encoder_settings.payload_name;
4063 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
4064 }
4065
4066 void EncodedFrameCallback(const EncodedFrame& encoded_frame) override {
4067 rtc::CritScope lock(&crit_);
4068 if (recorded_frames_++ > kNumFramesToRecord) {
4069 fixture_->LogSend(false);
4070 fixture_->LogReceive(false);
4071 rtc::File send_file(fixture_->OpenFile(0));
4072 rtc::File receive_file(fixture_->OpenFile(1));
4073 uint8_t out[100];
4074 // If logging has worked correctly neither file should be empty, i.e.
4075 // we should be able to read something from them.
4076 EXPECT_LT(0u, send_file.Read(out, 100));
4077 EXPECT_LT(0u, receive_file.Read(out, 100));
4078 observation_complete_.Set();
4079 }
4080 }
4081
4082 private:
4083 EndToEndLogTest* const fixture_;
4084 std::unique_ptr<VideoEncoder> encoder_;
4085 std::unique_ptr<VideoDecoder> decoder_;
4086 rtc::CriticalSection crit_;
4087 int recorded_frames_ GUARDED_BY(crit_);
4088 } test(this);
4089
4090 RunBaseTest(&test);
4091}
4092
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00004093} // namespace webrtc