blob: 6e721b60ee4c53db1a1660b63d67264acdec93ab [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
ilnikd60d06a2017-04-05 03:02:20 -070018#include "webrtc/api/video_codecs/video_encoder.h"
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000019#include "webrtc/base/checks.h"
Erik Språng6b8d3552015-09-24 15:06:57 +020020#include "webrtc/base/event.h"
palmkviste75f2042016-09-28 06:19:48 -070021#include "webrtc/base/file.h"
Erik Språng737336d2016-07-29 12:59:36 +020022#include "webrtc/base/optional.h"
brandtr35364632016-12-09 06:51:29 -080023#include "webrtc/base/random.h"
Erik Språng737336d2016-07-29 12:59:36 +020024#include "webrtc/base/rate_limiter.h"
ossuf515ab82016-12-07 04:52:58 -080025#include "webrtc/call/call.h"
pbosa96b60b2016-04-18 21:12:48 -070026#include "webrtc/common_video/include/frame_callback.h"
skvlad11a9cbf2016-10-07 11:53:05 -070027#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
sakal55d932b2016-09-30 06:19:08 -070028#include "webrtc/media/base/fakevideorenderer.h"
danilchap5c35cf92016-02-03 14:14:49 -080029#include "webrtc/modules/include/module_common_types.h"
stefan32f81542016-01-20 07:13:58 -080030#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
sprang861c55e2015-10-16 10:01:21 -070031#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
Erik Språng737336d2016-07-29 12:59:36 +020032#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h"
Danil Chapovalov70ffead2016-07-20 15:26:59 +020033#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.h"
sprangcd349d92016-07-13 09:11:28 -070034#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
hbosbab934b2016-01-27 01:36:03 -080035#include "webrtc/modules/video_coding/codecs/h264/include/h264.h"
marpan@webrtc.org5b883172014-11-01 06:10:48 +000036#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
37#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010038#include "webrtc/modules/video_coding/include/video_coding_defines.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010039#include "webrtc/system_wrappers/include/metrics.h"
asapersson01d70a32016-05-20 06:29:46 -070040#include "webrtc/system_wrappers/include/metrics_default.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010041#include "webrtc/system_wrappers/include/sleep.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000042#include "webrtc/test/call_test.h"
43#include "webrtc/test/direct_transport.h"
44#include "webrtc/test/encoder_settings.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000045#include "webrtc/test/fake_decoder.h"
46#include "webrtc/test/fake_encoder.h"
philipel266f0a42016-11-28 08:49:07 -080047#include "webrtc/test/field_trial.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000048#include "webrtc/test/frame_generator.h"
49#include "webrtc/test/frame_generator_capturer.h"
brandtr0b8bfb92017-05-19 06:51:42 -070050#include "webrtc/test/gtest.h"
brandtr56e119e2017-05-19 10:33:03 -070051#include "webrtc/test/gmock.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000052#include "webrtc/test/null_transport.h"
asapersson@webrtc.org37c05592015-01-28 13:58:27 +000053#include "webrtc/test/rtcp_packet_parser.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000054#include "webrtc/test/rtp_rtcp_observer.h"
55#include "webrtc/test/testsupport/fileutils.h"
56#include "webrtc/test/testsupport/perf_test.h"
charujainbf6a45b2016-11-03 04:21:42 -070057#include "webrtc/video/transport_adapter.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000058
aleloi7057b6b2017-03-29 02:07:33 -070059#if defined(MEMORY_SANITIZER)
60// Flaky under MemorySanitizer, see
61// https://bugs.chromium.org/p/webrtc/issues/detail?id=7419
62#define MAYBE_InitialProbing DISABLED_InitialProbing
63#else
64#define MAYBE_InitialProbing InitialProbing
65#endif
66
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000067namespace webrtc {
68
minyue20c84cc2017-04-10 16:57:57 -070069namespace {
70constexpr int kSilenceTimeoutMs = 2000;
71}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000072
philipel277a8b52017-03-16 05:19:49 -070073class EndToEndTest : public test::CallTest {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000074 public:
philipel277a8b52017-03-16 05:19:49 -070075 EndToEndTest() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000076
77 virtual ~EndToEndTest() {
stefanff483612015-12-21 03:14:00 -080078 EXPECT_EQ(nullptr, video_send_stream_);
79 EXPECT_TRUE(video_receive_streams_.empty());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000080 }
81
82 protected:
pbos2d566682015-09-28 09:59:31 -070083 class UnusedTransport : public Transport {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000084 private:
stefan1d8a5062015-10-02 03:39:33 -070085 bool SendRtp(const uint8_t* packet,
86 size_t length,
87 const PacketOptions& options) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000088 ADD_FAILURE() << "Unexpected RTP sent.";
89 return false;
90 }
91
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000092 bool SendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000093 ADD_FAILURE() << "Unexpected RTCP sent.";
94 return false;
95 }
96 };
97
skvlad7a43d252016-03-22 15:32:27 -070098 class RequiredTransport : public Transport {
99 public:
100 RequiredTransport(bool rtp_required, bool rtcp_required)
101 : need_rtp_(rtp_required), need_rtcp_(rtcp_required) {}
102 ~RequiredTransport() {
103 if (need_rtp_) {
104 ADD_FAILURE() << "Expected RTP packet not sent.";
105 }
106 if (need_rtcp_) {
107 ADD_FAILURE() << "Expected RTCP packet not sent.";
108 }
109 }
110
111 private:
112 bool SendRtp(const uint8_t* packet,
113 size_t length,
114 const PacketOptions& options) override {
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700115 rtc::CritScope lock(&crit_);
skvlad7a43d252016-03-22 15:32:27 -0700116 need_rtp_ = false;
117 return true;
118 }
119
120 bool SendRtcp(const uint8_t* packet, size_t length) override {
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700121 rtc::CritScope lock(&crit_);
skvlad7a43d252016-03-22 15:32:27 -0700122 need_rtcp_ = false;
123 return true;
124 }
125 bool need_rtp_;
126 bool need_rtcp_;
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700127 rtc::CriticalSection crit_;
skvlad7a43d252016-03-22 15:32:27 -0700128 };
129
Peter Boström39593972016-02-15 11:27:15 +0100130 void DecodesRetransmittedFrame(bool enable_rtx, bool enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000131 void ReceivesPliAndRecovers(int rtp_history_ms);
pbosda903ea2015-10-02 02:36:56 -0700132 void RespectsRtcpMode(RtcpMode rtcp_mode);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000133 void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200134 void TestRtpStatePreservation(bool use_rtx, bool provoke_rtcpsr_before_rtp);
sprangb4a1ae52015-12-03 08:10:08 -0800135 void VerifyHistogramStats(bool use_rtx, bool use_red, bool screenshare);
skvlad7a43d252016-03-22 15:32:27 -0700136 void VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -0800137 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -0700138 VideoEncoder* encoder,
139 Transport* transport);
140 void VerifyNewVideoReceiveStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -0800141 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -0700142 Transport* transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000143};
144
philipel277a8b52017-03-16 05:19:49 -0700145TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
philipel4fb651d2017-04-10 03:54:05 -0700146 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000147
solenberg4fbae2b2015-08-28 04:07:10 -0700148 test::NullTransport transport;
brandtr841de6a2016-11-15 07:10:52 -0800149 CreateSendConfig(1, 0, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700150 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000151
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100152 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000153
stefanff483612015-12-21 03:14:00 -0800154 video_receive_streams_[0]->Start();
155 video_receive_streams_[0]->Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000156
157 DestroyStreams();
158}
159
philipel277a8b52017-03-16 05:19:49 -0700160TEST_F(EndToEndTest, ReceiverCanBeStoppedTwice) {
philipel4fb651d2017-04-10 03:54:05 -0700161 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000162
solenberg4fbae2b2015-08-28 04:07:10 -0700163 test::NullTransport transport;
brandtr841de6a2016-11-15 07:10:52 -0800164 CreateSendConfig(1, 0, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700165 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000166
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100167 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000168
stefanff483612015-12-21 03:14:00 -0800169 video_receive_streams_[0]->Stop();
170 video_receive_streams_[0]->Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000171
172 DestroyStreams();
173}
174
philipel277a8b52017-03-16 05:19:49 -0700175TEST_F(EndToEndTest, ReceiverCanBeStoppedAndRestarted) {
philipel4fb651d2017-04-10 03:54:05 -0700176 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
sprang113bdca2016-10-11 03:10:10 -0700177
178 test::NullTransport transport;
brandtr841de6a2016-11-15 07:10:52 -0800179 CreateSendConfig(1, 0, 0, &transport);
sprang113bdca2016-10-11 03:10:10 -0700180 CreateMatchingReceiveConfigs(&transport);
181
182 CreateVideoStreams();
183
184 video_receive_streams_[0]->Stop();
185 video_receive_streams_[0]->Start();
186 video_receive_streams_[0]->Stop();
187
188 DestroyStreams();
189}
190
philipel277a8b52017-03-16 05:19:49 -0700191TEST_F(EndToEndTest, RendersSingleDelayedFrame) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000192 static const int kWidth = 320;
193 static const int kHeight = 240;
194 // This constant is chosen to be higher than the timeout in the video_render
195 // module. This makes sure that frames aren't dropped if there are no other
196 // frames in the queue.
nisse76bc8e82017-02-07 09:37:41 -0800197 static const int kRenderDelayMs = 1000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000198
nisse7ade7b32016-03-23 04:48:10 -0700199 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000200 public:
Peter Boström5811a392015-12-10 13:02:50 +0100201 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000202
nisse76bc8e82017-02-07 09:37:41 -0800203 void OnFrame(const VideoFrame& video_frame) override {
204 SleepMs(kRenderDelayMs);
205 event_.Set();
206 }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000207
Peter Boström5811a392015-12-10 13:02:50 +0100208 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000209
Peter Boström5811a392015-12-10 13:02:50 +0100210 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000211 } renderer;
212
philipel4fb651d2017-04-10 03:54:05 -0700213 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
solenberg4fbae2b2015-08-28 04:07:10 -0700214
minyue20c84cc2017-04-10 16:57:57 -0700215 test::DirectTransport sender_transport(sender_call_.get(), payload_type_map_);
216 test::DirectTransport receiver_transport(receiver_call_.get(),
217 payload_type_map_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000218 sender_transport.SetReceiver(receiver_call_->Receiver());
219 receiver_transport.SetReceiver(sender_call_->Receiver());
220
brandtr841de6a2016-11-15 07:10:52 -0800221 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700222 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000223
stefanff483612015-12-21 03:14:00 -0800224 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000225
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100226 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000227 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000228
229 // Create frames that are smaller than the send width/height, this is done to
230 // check that the callbacks are done after processing video.
kwiberg27f982b2016-03-01 11:52:33 -0800231 std::unique_ptr<test::FrameGenerator> frame_generator(
perkja8ba1952017-02-27 06:52:10 -0800232 test::FrameGenerator::CreateSquareGenerator(kWidth, kHeight));
perkja49cbd32016-09-16 07:53:41 -0700233 test::FrameForwarder frame_forwarder;
perkj803d97f2016-11-01 11:45:46 -0700234 video_send_stream_->SetSource(
sprangc5d62e22017-04-02 23:53:04 -0700235 &frame_forwarder,
236 VideoSendStream::DegradationPreference::kMaintainFramerate);
perkja49cbd32016-09-16 07:53:41 -0700237
238 frame_forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
Peter Boström5811a392015-12-10 13:02:50 +0100239 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000240 << "Timed out while waiting for the frame to render.";
241
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000242 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000243
244 sender_transport.StopSending();
245 receiver_transport.StopSending();
246
247 DestroyStreams();
248}
249
philipel277a8b52017-03-16 05:19:49 -0700250TEST_F(EndToEndTest, TransmitsFirstFrame) {
nisse7ade7b32016-03-23 04:48:10 -0700251 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000252 public:
Peter Boström5811a392015-12-10 13:02:50 +0100253 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000254
nisseeb83a1a2016-03-21 01:27:56 -0700255 void OnFrame(const VideoFrame& video_frame) override { event_.Set(); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000256
Peter Boström5811a392015-12-10 13:02:50 +0100257 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000258
Peter Boström5811a392015-12-10 13:02:50 +0100259 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000260 } renderer;
261
philipel4fb651d2017-04-10 03:54:05 -0700262 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
solenberg4fbae2b2015-08-28 04:07:10 -0700263
minyue20c84cc2017-04-10 16:57:57 -0700264 test::DirectTransport sender_transport(sender_call_.get(), payload_type_map_);
265 test::DirectTransport receiver_transport(receiver_call_.get(),
266 payload_type_map_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000267 sender_transport.SetReceiver(receiver_call_->Receiver());
268 receiver_transport.SetReceiver(sender_call_->Receiver());
269
brandtr841de6a2016-11-15 07:10:52 -0800270 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700271 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -0800272 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000273
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100274 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000275 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000276
kwiberg27f982b2016-03-01 11:52:33 -0800277 std::unique_ptr<test::FrameGenerator> frame_generator(
perkja8ba1952017-02-27 06:52:10 -0800278 test::FrameGenerator::CreateSquareGenerator(kDefaultWidth,
perkjfa10b552016-10-02 23:45:26 -0700279 kDefaultHeight));
perkja49cbd32016-09-16 07:53:41 -0700280 test::FrameForwarder frame_forwarder;
perkj803d97f2016-11-01 11:45:46 -0700281 video_send_stream_->SetSource(
sprangc5d62e22017-04-02 23:53:04 -0700282 &frame_forwarder,
283 VideoSendStream::DegradationPreference::kMaintainFramerate);
perkja49cbd32016-09-16 07:53:41 -0700284 frame_forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000285
Peter Boström5811a392015-12-10 13:02:50 +0100286 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000287 << "Timed out while waiting for the frame to render.";
288
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000289 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000290
291 sender_transport.StopSending();
292 receiver_transport.StopSending();
293
294 DestroyStreams();
295}
296
Perba7dc722016-04-19 15:01:23 +0200297class CodecObserver : public test::EndToEndTest,
nisse7ade7b32016-03-23 04:48:10 -0700298 public rtc::VideoSinkInterface<VideoFrame> {
Perba7dc722016-04-19 15:01:23 +0200299 public:
300 CodecObserver(int no_frames_to_wait_for,
301 VideoRotation rotation_to_test,
302 const std::string& payload_name,
303 webrtc::VideoEncoder* encoder,
304 webrtc::VideoDecoder* decoder)
hta9aa96882016-12-06 05:36:03 -0800305 : EndToEndTest(4 * webrtc::EndToEndTest::kDefaultTimeoutMs),
306 // TODO(hta): This timeout (120 seconds) is excessive.
307 // https://bugs.webrtc.org/6830
Perba7dc722016-04-19 15:01:23 +0200308 no_frames_to_wait_for_(no_frames_to_wait_for),
309 expected_rotation_(rotation_to_test),
310 payload_name_(payload_name),
311 encoder_(encoder),
312 decoder_(decoder),
313 frame_counter_(0) {}
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000314
Perba7dc722016-04-19 15:01:23 +0200315 void PerformTest() override {
316 EXPECT_TRUE(Wait())
317 << "Timed out while waiting for enough frames to be decoded.";
318 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000319
Perba7dc722016-04-19 15:01:23 +0200320 void ModifyVideoConfigs(
321 VideoSendStream::Config* send_config,
322 std::vector<VideoReceiveStream::Config>* receive_configs,
323 VideoEncoderConfig* encoder_config) override {
324 send_config->encoder_settings.encoder = encoder_.get();
325 send_config->encoder_settings.payload_name = payload_name_;
minyue20c84cc2017-04-10 16:57:57 -0700326 send_config->encoder_settings.payload_type =
327 test::CallTest::kVideoSendPayloadType;
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000328
Perba7dc722016-04-19 15:01:23 +0200329 (*receive_configs)[0].renderer = this;
330 (*receive_configs)[0].decoders.resize(1);
331 (*receive_configs)[0].decoders[0].payload_type =
332 send_config->encoder_settings.payload_type;
333 (*receive_configs)[0].decoders[0].payload_name =
334 send_config->encoder_settings.payload_name;
335 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
336 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000337
Perba7dc722016-04-19 15:01:23 +0200338 void OnFrame(const VideoFrame& video_frame) override {
339 EXPECT_EQ(expected_rotation_, video_frame.rotation());
340 if (++frame_counter_ == no_frames_to_wait_for_)
341 observation_complete_.Set();
342 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000343
Perba7dc722016-04-19 15:01:23 +0200344 void OnFrameGeneratorCapturerCreated(
345 test::FrameGeneratorCapturer* frame_generator_capturer) override {
346 frame_generator_capturer->SetFakeRotation(expected_rotation_);
347 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000348
Perba7dc722016-04-19 15:01:23 +0200349 private:
350 int no_frames_to_wait_for_;
351 VideoRotation expected_rotation_;
352 std::string payload_name_;
353 std::unique_ptr<webrtc::VideoEncoder> encoder_;
354 std::unique_ptr<webrtc::VideoDecoder> decoder_;
355 int frame_counter_;
356};
357
philipel277a8b52017-03-16 05:19:49 -0700358TEST_F(EndToEndTest, SendsAndReceivesVP8) {
philipel266f0a42016-11-28 08:49:07 -0800359 CodecObserver test(5, kVideoRotation_0, "VP8", VP8Encoder::Create(),
360 VP8Decoder::Create());
361 RunBaseTest(&test);
362}
363
philipel277a8b52017-03-16 05:19:49 -0700364TEST_F(EndToEndTest, SendsAndReceivesVP8Rotation90) {
magjed509e4fe2016-11-18 01:34:11 -0800365 CodecObserver test(5, kVideoRotation_90, "VP8", VP8Encoder::Create(),
Perba7dc722016-04-19 15:01:23 +0200366 VP8Decoder::Create());
367 RunBaseTest(&test);
368}
369
Peter Boström12996152016-05-14 02:03:18 +0200370#if !defined(RTC_DISABLE_VP9)
philipel277a8b52017-03-16 05:19:49 -0700371TEST_F(EndToEndTest, SendsAndReceivesVP9) {
magjed509e4fe2016-11-18 01:34:11 -0800372 CodecObserver test(500, kVideoRotation_0, "VP9", VP9Encoder::Create(),
Perba7dc722016-04-19 15:01:23 +0200373 VP9Decoder::Create());
374 RunBaseTest(&test);
375}
376
philipel277a8b52017-03-16 05:19:49 -0700377TEST_F(EndToEndTest, SendsAndReceivesVP9VideoRotation90) {
magjed509e4fe2016-11-18 01:34:11 -0800378 CodecObserver test(5, kVideoRotation_90, "VP9", VP9Encoder::Create(),
Perba7dc722016-04-19 15:01:23 +0200379 VP9Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800380 RunBaseTest(&test);
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000381}
Peter Boström12996152016-05-14 02:03:18 +0200382#endif // !defined(RTC_DISABLE_VP9)
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000383
brandtr445fb8f2016-11-14 04:11:23 -0800384#if defined(WEBRTC_USE_H264)
philipel277a8b52017-03-16 05:19:49 -0700385TEST_F(EndToEndTest, SendsAndReceivesH264) {
magjedceecea42016-11-28 07:20:21 -0800386 CodecObserver test(500, kVideoRotation_0, "H264",
387 H264Encoder::Create(cricket::VideoCodec("H264")),
Perba7dc722016-04-19 15:01:23 +0200388 H264Decoder::Create());
389 RunBaseTest(&test);
390}
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000391
philipel277a8b52017-03-16 05:19:49 -0700392TEST_F(EndToEndTest, SendsAndReceivesH264VideoRotation90) {
magjedceecea42016-11-28 07:20:21 -0800393 CodecObserver test(5, kVideoRotation_90, "H264",
394 H264Encoder::Create(cricket::VideoCodec("H264")),
Perba7dc722016-04-19 15:01:23 +0200395 H264Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800396 RunBaseTest(&test);
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000397}
hta9aa96882016-12-06 05:36:03 -0800398
philipel277a8b52017-03-16 05:19:49 -0700399TEST_F(EndToEndTest, SendsAndReceivesH264PacketizationMode0) {
hta9aa96882016-12-06 05:36:03 -0800400 cricket::VideoCodec codec = cricket::VideoCodec("H264");
401 codec.SetParam(cricket::kH264FmtpPacketizationMode, "0");
402 CodecObserver test(500, kVideoRotation_0, "H264", H264Encoder::Create(codec),
403 H264Decoder::Create());
404 RunBaseTest(&test);
405}
406
philipel277a8b52017-03-16 05:19:49 -0700407TEST_F(EndToEndTest, SendsAndReceivesH264PacketizationMode1) {
hta9aa96882016-12-06 05:36:03 -0800408 cricket::VideoCodec codec = cricket::VideoCodec("H264");
409 codec.SetParam(cricket::kH264FmtpPacketizationMode, "1");
410 CodecObserver test(500, kVideoRotation_0, "H264", H264Encoder::Create(codec),
411 H264Decoder::Create());
412 RunBaseTest(&test);
413}
414
brandtr445fb8f2016-11-14 04:11:23 -0800415#endif // defined(WEBRTC_USE_H264)
hbosbab934b2016-01-27 01:36:03 -0800416
philipel277a8b52017-03-16 05:19:49 -0700417TEST_F(EndToEndTest, ReceiverUsesLocalSsrc) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000418 class SyncRtcpObserver : public test::EndToEndTest {
419 public:
420 SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {}
421
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000422 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
danilchap3dc929e2016-11-02 08:21:59 -0700423 test::RtcpPacketParser parser;
424 EXPECT_TRUE(parser.Parse(packet, length));
425 EXPECT_EQ(kReceiverLocalVideoSsrc, parser.sender_ssrc());
Peter Boström5811a392015-12-10 13:02:50 +0100426 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000427
428 return SEND_PACKET;
429 }
430
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000431 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100432 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000433 << "Timed out while waiting for a receiver RTCP packet to be sent.";
434 }
435 } test;
436
stefane74eef12016-01-08 06:47:13 -0800437 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000438}
439
philipel277a8b52017-03-16 05:19:49 -0700440TEST_F(EndToEndTest, ReceivesAndRetransmitsNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000441 static const int kNumberOfNacksToObserve = 2;
442 static const int kLossBurstSize = 2;
443 static const int kPacketsBetweenLossBursts = 9;
444 class NackObserver : public test::EndToEndTest {
445 public:
446 NackObserver()
447 : EndToEndTest(kLongTimeoutMs),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000448 sent_rtp_packets_(0),
449 packets_left_to_drop_(0),
450 nacks_left_(kNumberOfNacksToObserve) {}
451
452 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000453 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700454 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000455 RTPHeader header;
Peter Boström03671cb2015-12-07 15:22:24 +0100456 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000457
458 // Never drop retransmitted packets.
459 if (dropped_packets_.find(header.sequenceNumber) !=
460 dropped_packets_.end()) {
461 retransmitted_packets_.insert(header.sequenceNumber);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000462 return SEND_PACKET;
463 }
464
philipel8054c7e2017-01-10 05:19:19 -0800465 if (nacks_left_ <= 0 &&
466 retransmitted_packets_.size() == dropped_packets_.size()) {
467 observation_complete_.Set();
468 }
469
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000470 ++sent_rtp_packets_;
471
472 // Enough NACKs received, stop dropping packets.
Stefan Holmer586b19b2015-09-18 11:14:31 +0200473 if (nacks_left_ <= 0)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000474 return SEND_PACKET;
475
476 // Check if it's time for a new loss burst.
477 if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
478 packets_left_to_drop_ = kLossBurstSize;
479
Stefan Holmer01b48882015-05-05 10:21:24 +0200480 // Never drop padding packets as those won't be retransmitted.
481 if (packets_left_to_drop_ > 0 && header.paddingLength == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000482 --packets_left_to_drop_;
483 dropped_packets_.insert(header.sequenceNumber);
484 return DROP_PACKET;
485 }
486
487 return SEND_PACKET;
488 }
489
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000490 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700491 rtc::CritScope lock(&crit_);
danilchap3dc929e2016-11-02 08:21:59 -0700492 test::RtcpPacketParser parser;
493 EXPECT_TRUE(parser.Parse(packet, length));
494 nacks_left_ -= parser.nack()->num_packets();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000495 return SEND_PACKET;
496 }
497
stefanff483612015-12-21 03:14:00 -0800498 void ModifyVideoConfigs(
499 VideoSendStream::Config* send_config,
500 std::vector<VideoReceiveStream::Config>* receive_configs,
501 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000502 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000503 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000504 }
505
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000506 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100507 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000508 << "Timed out waiting for packets to be NACKed, retransmitted and "
509 "rendered.";
510 }
511
stefanf116bd02015-10-27 08:29:42 -0700512 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000513 std::set<uint16_t> dropped_packets_;
514 std::set<uint16_t> retransmitted_packets_;
515 uint64_t sent_rtp_packets_;
516 int packets_left_to_drop_;
stefanf116bd02015-10-27 08:29:42 -0700517 int nacks_left_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000518 } test;
519
stefane74eef12016-01-08 06:47:13 -0800520 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000521}
522
philipel277a8b52017-03-16 05:19:49 -0700523TEST_F(EndToEndTest, ReceivesNackAndRetransmitsAudio) {
Erik Språng737336d2016-07-29 12:59:36 +0200524 class NackObserver : public test::EndToEndTest {
525 public:
526 NackObserver()
527 : EndToEndTest(kLongTimeoutMs),
528 local_ssrc_(0),
529 remote_ssrc_(0),
530 receive_transport_(nullptr) {}
531
532 private:
533 size_t GetNumVideoStreams() const override { return 0; }
534 size_t GetNumAudioStreams() const override { return 1; }
535
536 test::PacketTransport* CreateReceiveTransport() override {
537 test::PacketTransport* receive_transport = new test::PacketTransport(
minyue20c84cc2017-04-10 16:57:57 -0700538 nullptr, this, test::PacketTransport::kReceiver, payload_type_map_,
Erik Språng737336d2016-07-29 12:59:36 +0200539 FakeNetworkPipe::Config());
540 receive_transport_ = receive_transport;
541 return receive_transport;
542 }
543
544 Action OnSendRtp(const uint8_t* packet, size_t length) override {
545 RTPHeader header;
546 EXPECT_TRUE(parser_->Parse(packet, length, &header));
547
548 if (!sequence_number_to_retransmit_) {
549 sequence_number_to_retransmit_ =
550 rtc::Optional<uint16_t>(header.sequenceNumber);
551
552 // Don't ask for retransmission straight away, may be deduped in pacer.
553 } else if (header.sequenceNumber == *sequence_number_to_retransmit_) {
554 observation_complete_.Set();
555 } else {
556 // Send a NACK as often as necessary until retransmission is received.
557 rtcp::Nack nack;
danilchap822a16f2016-09-27 09:27:47 -0700558 nack.SetSenderSsrc(local_ssrc_);
559 nack.SetMediaSsrc(remote_ssrc_);
Erik Språng737336d2016-07-29 12:59:36 +0200560 uint16_t nack_list[] = {*sequence_number_to_retransmit_};
danilchap822a16f2016-09-27 09:27:47 -0700561 nack.SetPacketIds(nack_list, 1);
Erik Språng737336d2016-07-29 12:59:36 +0200562 rtc::Buffer buffer = nack.Build();
563
564 EXPECT_TRUE(receive_transport_->SendRtcp(buffer.data(), buffer.size()));
565 }
566
567 return SEND_PACKET;
568 }
569
570 void ModifyAudioConfigs(
571 AudioSendStream::Config* send_config,
572 std::vector<AudioReceiveStream::Config>* receive_configs) override {
573 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
574 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
575 local_ssrc_ = (*receive_configs)[0].rtp.local_ssrc;
576 remote_ssrc_ = (*receive_configs)[0].rtp.remote_ssrc;
577 }
578
579 void PerformTest() override {
580 EXPECT_TRUE(Wait())
581 << "Timed out waiting for packets to be NACKed, retransmitted and "
582 "rendered.";
583 }
584
585 uint32_t local_ssrc_;
586 uint32_t remote_ssrc_;
587 Transport* receive_transport_;
588 rtc::Optional<uint16_t> sequence_number_to_retransmit_;
589 } test;
590
591 RunBaseTest(&test);
592}
593
brandtrc55f27a2017-03-20 06:32:59 -0700594TEST_F(EndToEndTest, ReceivesUlpfec) {
brandtr535830e2016-10-31 03:45:58 -0700595 class UlpfecRenderObserver : public test::EndToEndTest,
596 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000597 public:
brandtr535830e2016-10-31 03:45:58 -0700598 UlpfecRenderObserver()
brandtr1134b7b2017-02-06 06:35:47 -0800599 : EndToEndTest(kDefaultTimeoutMs),
brandtrc55f27a2017-03-20 06:32:59 -0700600 encoder_(VP8Encoder::Create()),
brandtr1134b7b2017-02-06 06:35:47 -0800601 random_(0xcafef00d1),
602 num_packets_sent_(0) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000603
604 private:
stefanf116bd02015-10-27 08:29:42 -0700605 Action OnSendRtp(const uint8_t* packet, size_t length) override {
606 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000607 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000608 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000609
brandtrc55f27a2017-03-20 06:32:59 -0700610 EXPECT_TRUE(header.payloadType == kVideoSendPayloadType ||
brandtr1134b7b2017-02-06 06:35:47 -0800611 header.payloadType == kRedPayloadType)
612 << "Unknown payload type received.";
613 EXPECT_EQ(kVideoSendSsrcs[0], header.ssrc) << "Unknown SSRC received.";
614
615 // Parse RED header.
Stefan Holmer01b48882015-05-05 10:21:24 +0200616 int encapsulated_payload_type = -1;
617 if (header.payloadType == kRedPayloadType) {
618 encapsulated_payload_type =
619 static_cast<int>(packet[header.headerLength]);
brandtr1134b7b2017-02-06 06:35:47 -0800620
brandtrc55f27a2017-03-20 06:32:59 -0700621 EXPECT_TRUE(encapsulated_payload_type == kVideoSendPayloadType ||
brandtr1134b7b2017-02-06 06:35:47 -0800622 encapsulated_payload_type == kUlpfecPayloadType)
623 << "Unknown encapsulated payload type received.";
Stefan Holmer01b48882015-05-05 10:21:24 +0200624 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000625
brandtrc55f27a2017-03-20 06:32:59 -0700626 // To minimize test flakiness, always let ULPFEC packets through.
brandtr1134b7b2017-02-06 06:35:47 -0800627 if (encapsulated_payload_type == kUlpfecPayloadType) {
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000628 return SEND_PACKET;
629 }
630
brandtr1134b7b2017-02-06 06:35:47 -0800631 // Simulate 5% video packet loss after rampup period. Record the
632 // corresponding timestamps that were dropped.
633 if (num_packets_sent_++ > 100 && random_.Rand(1, 100) <= 5) {
brandtrc55f27a2017-03-20 06:32:59 -0700634 if (encapsulated_payload_type == kVideoSendPayloadType) {
brandtr1134b7b2017-02-06 06:35:47 -0800635 dropped_sequence_numbers_.insert(header.sequenceNumber);
636 dropped_timestamps_.insert(header.timestamp);
637 }
brandtr1134b7b2017-02-06 06:35:47 -0800638 return DROP_PACKET;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000639 }
640
641 return SEND_PACKET;
642 }
643
nisseeb83a1a2016-03-21 01:27:56 -0700644 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200645 rtc::CritScope lock(&crit_);
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000646 // Rendering frame with timestamp of packet that was dropped -> FEC
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000647 // protection worked.
brandtr1134b7b2017-02-06 06:35:47 -0800648 auto it = dropped_timestamps_.find(video_frame.timestamp());
649 if (it != dropped_timestamps_.end()) {
Peter Boström5811a392015-12-10 13:02:50 +0100650 observation_complete_.Set();
brandtr1134b7b2017-02-06 06:35:47 -0800651 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000652 }
653
stefanff483612015-12-21 03:14:00 -0800654 void ModifyVideoConfigs(
655 VideoSendStream::Config* send_config,
656 std::vector<VideoReceiveStream::Config>* receive_configs,
657 VideoEncoderConfig* encoder_config) override {
brandtrc55f27a2017-03-20 06:32:59 -0700658 // Use VP8 instead of FAKE, since the latter does not have PictureID
659 // in the packetization headers.
660 send_config->encoder_settings.encoder = encoder_.get();
661 send_config->encoder_settings.payload_name = "VP8";
662 send_config->encoder_settings.payload_type = kVideoSendPayloadType;
663 VideoReceiveStream::Decoder decoder =
664 test::CreateMatchingDecoder(send_config->encoder_settings);
665 decoder_.reset(decoder.decoder);
666 (*receive_configs)[0].decoders.clear();
667 (*receive_configs)[0].decoders.push_back(decoder);
668
669 // Enable ULPFEC over RED.
brandtrb5f2c3f2016-10-04 23:28:39 -0700670 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
671 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
brandtrb5f2c3f2016-10-04 23:28:39 -0700672 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
673 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
brandtrc55f27a2017-03-20 06:32:59 -0700674
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000675 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000676 }
677
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000678 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100679 EXPECT_TRUE(Wait())
brandtr1e3dfbf2016-11-16 22:45:19 -0800680 << "Timed out waiting for dropped frames to be rendered.";
681 }
682
683 rtc::CriticalSection crit_;
brandtrc55f27a2017-03-20 06:32:59 -0700684 std::unique_ptr<VideoEncoder> encoder_;
685 std::unique_ptr<VideoDecoder> decoder_;
brandtr1134b7b2017-02-06 06:35:47 -0800686 std::set<uint32_t> dropped_sequence_numbers_ GUARDED_BY(crit_);
687 // Several packets can have the same timestamp.
688 std::multiset<uint32_t> dropped_timestamps_ GUARDED_BY(crit_);
689 Random random_;
brandtrc55f27a2017-03-20 06:32:59 -0700690 int num_packets_sent_ GUARDED_BY(crit_);
brandtr1e3dfbf2016-11-16 22:45:19 -0800691 } test;
692
693 RunBaseTest(&test);
694}
695
brandtrfa5a3682017-01-17 01:33:54 -0800696class FlexfecRenderObserver : public test::EndToEndTest,
697 public rtc::VideoSinkInterface<VideoFrame> {
698 public:
699 static constexpr uint32_t kVideoLocalSsrc = 123;
700 static constexpr uint32_t kFlexfecLocalSsrc = 456;
brandtr1e3dfbf2016-11-16 22:45:19 -0800701
brandtr1134b7b2017-02-06 06:35:47 -0800702 explicit FlexfecRenderObserver(bool enable_nack, bool expect_flexfec_rtcp)
brandtrfa5a3682017-01-17 01:33:54 -0800703 : test::EndToEndTest(test::CallTest::kDefaultTimeoutMs),
brandtr1134b7b2017-02-06 06:35:47 -0800704 enable_nack_(enable_nack),
brandtrfa5a3682017-01-17 01:33:54 -0800705 expect_flexfec_rtcp_(expect_flexfec_rtcp),
706 received_flexfec_rtcp_(false),
brandtr1134b7b2017-02-06 06:35:47 -0800707 random_(0xcafef00d1),
708 num_packets_sent_(0) {}
brandtr1e3dfbf2016-11-16 22:45:19 -0800709
brandtrfa5a3682017-01-17 01:33:54 -0800710 size_t GetNumFlexfecStreams() const override { return 1; }
brandtr1e3dfbf2016-11-16 22:45:19 -0800711
brandtrfa5a3682017-01-17 01:33:54 -0800712 private:
713 Action OnSendRtp(const uint8_t* packet, size_t length) override {
714 rtc::CritScope lock(&crit_);
715 RTPHeader header;
716 EXPECT_TRUE(parser_->Parse(packet, length, &header));
brandtr1e3dfbf2016-11-16 22:45:19 -0800717
brandtr1134b7b2017-02-06 06:35:47 -0800718 EXPECT_TRUE(header.payloadType ==
719 test::CallTest::kFakeVideoSendPayloadType ||
720 header.payloadType == test::CallTest::kFlexfecPayloadType ||
721 (enable_nack_ &&
722 header.payloadType == test::CallTest::kSendRtxPayloadType))
723 << "Unknown payload type received.";
724 EXPECT_TRUE(
725 header.ssrc == test::CallTest::kVideoSendSsrcs[0] ||
726 header.ssrc == test::CallTest::kFlexfecSendSsrc ||
727 (enable_nack_ && header.ssrc == test::CallTest::kSendRtxSsrcs[0]))
728 << "Unknown SSRC received.";
729
730 // To reduce test flakiness, always let FlexFEC packets through.
731 if (header.payloadType == test::CallTest::kFlexfecPayloadType) {
732 EXPECT_EQ(test::CallTest::kFlexfecSendSsrc, header.ssrc);
733
734 return SEND_PACKET;
brandtr1e3dfbf2016-11-16 22:45:19 -0800735 }
736
brandtr1134b7b2017-02-06 06:35:47 -0800737 // To reduce test flakiness, always let RTX packets through.
738 if (header.payloadType == test::CallTest::kSendRtxPayloadType) {
739 EXPECT_EQ(test::CallTest::kSendRtxSsrcs[0], header.ssrc);
740
741 // Parse RTX header.
742 uint16_t original_sequence_number =
743 ByteReader<uint16_t>::ReadBigEndian(&packet[header.headerLength]);
744
745 // From the perspective of FEC, a retransmitted packet is no longer
746 // dropped, so remove it from list of dropped packets.
747 auto seq_num_it =
748 dropped_sequence_numbers_.find(original_sequence_number);
brandtrfa5a3682017-01-17 01:33:54 -0800749 if (seq_num_it != dropped_sequence_numbers_.end()) {
750 dropped_sequence_numbers_.erase(seq_num_it);
751 auto ts_it = dropped_timestamps_.find(header.timestamp);
752 EXPECT_NE(ts_it, dropped_timestamps_.end());
753 dropped_timestamps_.erase(ts_it);
brandtrfd8d2652017-02-06 06:19:51 -0800754 }
brandtr1134b7b2017-02-06 06:35:47 -0800755
756 return SEND_PACKET;
brandtrfa5a3682017-01-17 01:33:54 -0800757 }
758
brandtr1134b7b2017-02-06 06:35:47 -0800759 // Simulate 5% video packet loss after rampup period. Record the
760 // corresponding timestamps that were dropped.
761 if (num_packets_sent_++ > 100 && random_.Rand(1, 100) <= 5) {
762 EXPECT_EQ(test::CallTest::kFakeVideoSendPayloadType, header.payloadType);
763 EXPECT_EQ(test::CallTest::kVideoSendSsrcs[0], header.ssrc);
764
765 dropped_sequence_numbers_.insert(header.sequenceNumber);
766 dropped_timestamps_.insert(header.timestamp);
brandtrfa5a3682017-01-17 01:33:54 -0800767
768 return DROP_PACKET;
769 }
770
771 return SEND_PACKET;
772 }
773
774 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
775 test::RtcpPacketParser parser;
776
777 parser.Parse(data, length);
778 if (parser.sender_ssrc() == kFlexfecLocalSsrc) {
779 EXPECT_EQ(1, parser.receiver_report()->num_packets());
780 const std::vector<rtcp::ReportBlock>& report_blocks =
781 parser.receiver_report()->report_blocks();
782 if (!report_blocks.empty()) {
783 EXPECT_EQ(1U, report_blocks.size());
784 EXPECT_EQ(test::CallTest::kFlexfecSendSsrc,
785 report_blocks[0].source_ssrc());
brandtr1d2d7892017-01-18 00:40:07 -0800786 rtc::CritScope lock(&crit_);
brandtrfa5a3682017-01-17 01:33:54 -0800787 received_flexfec_rtcp_ = true;
788 }
789 }
790
791 return SEND_PACKET;
792 }
793
brandtr1134b7b2017-02-06 06:35:47 -0800794 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
795 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
796 const int kNetworkDelayMs = 100;
797 FakeNetworkPipe::Config config;
798 config.queue_delay_ms = kNetworkDelayMs;
799 return new test::PacketTransport(sender_call, this,
nissee5ad5ca2017-03-29 23:57:43 -0700800 test::PacketTransport::kSender,
minyue20c84cc2017-04-10 16:57:57 -0700801 test::CallTest::payload_type_map_, config);
brandtr1134b7b2017-02-06 06:35:47 -0800802 }
803
brandtrfa5a3682017-01-17 01:33:54 -0800804 void OnFrame(const VideoFrame& video_frame) override {
805 rtc::CritScope lock(&crit_);
806 // Rendering frame with timestamp of packet that was dropped -> FEC
807 // protection worked.
808 auto it = dropped_timestamps_.find(video_frame.timestamp());
809 if (it != dropped_timestamps_.end()) {
810 if (!expect_flexfec_rtcp_ || received_flexfec_rtcp_) {
brandtr1e3dfbf2016-11-16 22:45:19 -0800811 observation_complete_.Set();
brandtrfa5a3682017-01-17 01:33:54 -0800812 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800813 }
brandtrfa5a3682017-01-17 01:33:54 -0800814 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800815
brandtrfa5a3682017-01-17 01:33:54 -0800816 void ModifyVideoConfigs(
817 VideoSendStream::Config* send_config,
818 std::vector<VideoReceiveStream::Config>* receive_configs,
819 VideoEncoderConfig* encoder_config) override {
820 (*receive_configs)[0].rtp.local_ssrc = kVideoLocalSsrc;
821 (*receive_configs)[0].renderer = this;
brandtr1134b7b2017-02-06 06:35:47 -0800822
823 if (enable_nack_) {
824 send_config->rtp.nack.rtp_history_ms = test::CallTest::kNackRtpHistoryMs;
825 send_config->rtp.ulpfec.red_rtx_payload_type =
826 test::CallTest::kRtxRedPayloadType;
827 send_config->rtp.rtx.ssrcs.push_back(test::CallTest::kSendRtxSsrcs[0]);
828 send_config->rtp.rtx.payload_type = test::CallTest::kSendRtxPayloadType;
829
830 (*receive_configs)[0].rtp.nack.rtp_history_ms =
831 test::CallTest::kNackRtpHistoryMs;
832 (*receive_configs)[0].rtp.ulpfec.red_rtx_payload_type =
833 test::CallTest::kRtxRedPayloadType;
834
835 (*receive_configs)[0].rtp.rtx_ssrc = test::CallTest::kSendRtxSsrcs[0];
836 (*receive_configs)[0]
837 .rtp.rtx_payload_types[test::CallTest::kVideoSendPayloadType] =
838 test::CallTest::kSendRtxPayloadType;
839 }
brandtrfa5a3682017-01-17 01:33:54 -0800840 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800841
brandtrfa5a3682017-01-17 01:33:54 -0800842 void ModifyFlexfecConfigs(
843 std::vector<FlexfecReceiveStream::Config>* receive_configs) override {
844 (*receive_configs)[0].local_ssrc = kFlexfecLocalSsrc;
845 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000846
brandtrfa5a3682017-01-17 01:33:54 -0800847 void PerformTest() override {
848 EXPECT_TRUE(Wait())
849 << "Timed out waiting for dropped frames to be rendered.";
850 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000851
brandtrfa5a3682017-01-17 01:33:54 -0800852 rtc::CriticalSection crit_;
853 std::set<uint32_t> dropped_sequence_numbers_ GUARDED_BY(crit_);
brandtr1134b7b2017-02-06 06:35:47 -0800854 // Several packets can have the same timestamp.
brandtrfa5a3682017-01-17 01:33:54 -0800855 std::multiset<uint32_t> dropped_timestamps_ GUARDED_BY(crit_);
brandtr1134b7b2017-02-06 06:35:47 -0800856 const bool enable_nack_;
brandtr1d2d7892017-01-18 00:40:07 -0800857 const bool expect_flexfec_rtcp_;
858 bool received_flexfec_rtcp_ GUARDED_BY(crit_);
brandtrfa5a3682017-01-17 01:33:54 -0800859 Random random_;
brandtr1134b7b2017-02-06 06:35:47 -0800860 int num_packets_sent_;
brandtrfa5a3682017-01-17 01:33:54 -0800861};
862
philipel277a8b52017-03-16 05:19:49 -0700863TEST_F(EndToEndTest, RecoversWithFlexfec) {
brandtr1134b7b2017-02-06 06:35:47 -0800864 FlexfecRenderObserver test(false, false);
brandtrfa5a3682017-01-17 01:33:54 -0800865 RunBaseTest(&test);
866}
867
philipel277a8b52017-03-16 05:19:49 -0700868TEST_F(EndToEndTest, RecoversWithFlexfecAndNack) {
brandtr1134b7b2017-02-06 06:35:47 -0800869 FlexfecRenderObserver test(true, false);
870 RunBaseTest(&test);
871}
872
philipel277a8b52017-03-16 05:19:49 -0700873TEST_F(EndToEndTest, RecoversWithFlexfecAndSendsCorrespondingRtcp) {
brandtr1134b7b2017-02-06 06:35:47 -0800874 FlexfecRenderObserver test(false, true);
stefane74eef12016-01-08 06:47:13 -0800875 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000876}
877
philipel277a8b52017-03-16 05:19:49 -0700878TEST_F(EndToEndTest, ReceivedUlpfecPacketsNotNacked) {
brandtr535830e2016-10-31 03:45:58 -0700879 class UlpfecNackObserver : public test::EndToEndTest {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000880 public:
brandtr535830e2016-10-31 03:45:58 -0700881 UlpfecNackObserver()
stefanf116bd02015-10-27 08:29:42 -0700882 : EndToEndTest(kDefaultTimeoutMs),
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000883 state_(kFirstPacket),
brandtr535830e2016-10-31 03:45:58 -0700884 ulpfec_sequence_number_(0),
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000885 has_last_sequence_number_(false),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200886 last_sequence_number_(0),
magjed509e4fe2016-11-18 01:34:11 -0800887 encoder_(VP8Encoder::Create()),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200888 decoder_(VP8Decoder::Create()) {}
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000889
890 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000891 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800892 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000893 RTPHeader header;
894 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000895
Stefan Holmer01b48882015-05-05 10:21:24 +0200896 int encapsulated_payload_type = -1;
897 if (header.payloadType == kRedPayloadType) {
898 encapsulated_payload_type =
899 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100900 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200901 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
902 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100903 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200904 }
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000905
906 if (has_last_sequence_number_ &&
907 !IsNewerSequenceNumber(header.sequenceNumber,
908 last_sequence_number_)) {
909 // Drop retransmitted packets.
910 return DROP_PACKET;
911 }
912 last_sequence_number_ = header.sequenceNumber;
913 has_last_sequence_number_ = true;
914
brandtr535830e2016-10-31 03:45:58 -0700915 bool ulpfec_packet = encapsulated_payload_type == kUlpfecPayloadType;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000916 switch (state_) {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000917 case kFirstPacket:
brandtr535830e2016-10-31 03:45:58 -0700918 state_ = kDropEveryOtherPacketUntilUlpfec;
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000919 break;
brandtr535830e2016-10-31 03:45:58 -0700920 case kDropEveryOtherPacketUntilUlpfec:
921 if (ulpfec_packet) {
922 state_ = kDropAllMediaPacketsUntilUlpfec;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000923 } else if (header.sequenceNumber % 2 == 0) {
924 return DROP_PACKET;
925 }
926 break;
brandtr535830e2016-10-31 03:45:58 -0700927 case kDropAllMediaPacketsUntilUlpfec:
928 if (!ulpfec_packet)
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000929 return DROP_PACKET;
brandtr535830e2016-10-31 03:45:58 -0700930 ulpfec_sequence_number_ = header.sequenceNumber;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200931 state_ = kDropOneMediaPacket;
932 break;
933 case kDropOneMediaPacket:
brandtr535830e2016-10-31 03:45:58 -0700934 if (ulpfec_packet)
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200935 return DROP_PACKET;
936 state_ = kPassOneMediaPacket;
937 return DROP_PACKET;
938 break;
939 case kPassOneMediaPacket:
brandtr535830e2016-10-31 03:45:58 -0700940 if (ulpfec_packet)
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200941 return DROP_PACKET;
942 // Pass one media packet after dropped packet after last FEC,
943 // otherwise receiver might never see a seq_no after
brandtr535830e2016-10-31 03:45:58 -0700944 // |ulpfec_sequence_number_|
945 state_ = kVerifyUlpfecPacketNotInNackList;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000946 break;
brandtr535830e2016-10-31 03:45:58 -0700947 case kVerifyUlpfecPacketNotInNackList:
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000948 // Continue to drop packets. Make sure no frame can be decoded.
brandtr535830e2016-10-31 03:45:58 -0700949 if (ulpfec_packet || header.sequenceNumber % 2 == 0)
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000950 return DROP_PACKET;
951 break;
952 }
953 return SEND_PACKET;
954 }
955
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000956 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800957 rtc::CritScope lock_(&crit_);
brandtr535830e2016-10-31 03:45:58 -0700958 if (state_ == kVerifyUlpfecPacketNotInNackList) {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000959 test::RtcpPacketParser rtcp_parser;
960 rtcp_parser.Parse(packet, length);
Danil Chapovalovba6f7be2016-09-02 18:29:10 +0200961 const std::vector<uint16_t>& nacks = rtcp_parser.nack()->packet_ids();
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200962 EXPECT_TRUE(std::find(nacks.begin(), nacks.end(),
brandtr535830e2016-10-31 03:45:58 -0700963 ulpfec_sequence_number_) == nacks.end())
964 << "Got nack for ULPFEC packet";
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000965 if (!nacks.empty() &&
brandtr535830e2016-10-31 03:45:58 -0700966 IsNewerSequenceNumber(nacks.back(), ulpfec_sequence_number_)) {
Peter Boström5811a392015-12-10 13:02:50 +0100967 observation_complete_.Set();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000968 }
969 }
970 return SEND_PACKET;
971 }
972
stefane74eef12016-01-08 06:47:13 -0800973 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
974 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
975 // Configure some network delay.
976 const int kNetworkDelayMs = 50;
977 FakeNetworkPipe::Config config;
978 config.queue_delay_ms = kNetworkDelayMs;
979 return new test::PacketTransport(sender_call, this,
nissee5ad5ca2017-03-29 23:57:43 -0700980 test::PacketTransport::kSender,
minyue20c84cc2017-04-10 16:57:57 -0700981 payload_type_map_, config);
stefane74eef12016-01-08 06:47:13 -0800982 }
983
Stefan Holmere5904162015-03-26 11:11:06 +0100984 // TODO(holmer): Investigate why we don't send FEC packets when the bitrate
985 // is 10 kbps.
986 Call::Config GetSenderCallConfig() override {
philipel4fb651d2017-04-10 03:54:05 -0700987 Call::Config config(event_log_.get());
Stefan Holmere5904162015-03-26 11:11:06 +0100988 const int kMinBitrateBps = 30000;
989 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
990 return config;
991 }
992
stefanff483612015-12-21 03:14:00 -0800993 void ModifyVideoConfigs(
994 VideoSendStream::Config* send_config,
995 std::vector<VideoReceiveStream::Config>* receive_configs,
996 VideoEncoderConfig* encoder_config) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000997 // Configure hybrid NACK/FEC.
998 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
brandtrb5f2c3f2016-10-04 23:28:39 -0700999 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
1000 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001001 // Set codec to VP8, otherwise NACK/FEC hybrid will be disabled.
1002 send_config->encoder_settings.encoder = encoder_.get();
1003 send_config->encoder_settings.payload_name = "VP8";
1004 send_config->encoder_settings.payload_type = kFakeVideoSendPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001005
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001006 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
brandtrb5f2c3f2016-10-04 23:28:39 -07001007 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
1008 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001009
1010 (*receive_configs)[0].decoders.resize(1);
1011 (*receive_configs)[0].decoders[0].payload_type =
1012 send_config->encoder_settings.payload_type;
1013 (*receive_configs)[0].decoders[0].payload_name =
1014 send_config->encoder_settings.payload_name;
1015 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001016 }
1017
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001018 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001019 EXPECT_TRUE(Wait())
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001020 << "Timed out while waiting for FEC packets to be received.";
1021 }
1022
1023 enum {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +00001024 kFirstPacket,
brandtr535830e2016-10-31 03:45:58 -07001025 kDropEveryOtherPacketUntilUlpfec,
1026 kDropAllMediaPacketsUntilUlpfec,
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001027 kDropOneMediaPacket,
1028 kPassOneMediaPacket,
brandtr535830e2016-10-31 03:45:58 -07001029 kVerifyUlpfecPacketNotInNackList,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001030 } state_;
1031
stefan608213e2015-11-01 14:56:10 -08001032 rtc::CriticalSection crit_;
brandtr535830e2016-10-31 03:45:58 -07001033 uint16_t ulpfec_sequence_number_ GUARDED_BY(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001034 bool has_last_sequence_number_;
1035 uint16_t last_sequence_number_;
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001036 std::unique_ptr<webrtc::VideoEncoder> encoder_;
1037 std::unique_ptr<webrtc::VideoDecoder> decoder_;
stefanf116bd02015-10-27 08:29:42 -07001038 } test;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001039
stefane74eef12016-01-08 06:47:13 -08001040 RunBaseTest(&test);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001041}
1042
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001043// This test drops second RTP packet with a marker bit set, makes sure it's
1044// retransmitted and renders. Retransmission SSRCs are also checked.
Peter Boström39593972016-02-15 11:27:15 +01001045void EndToEndTest::DecodesRetransmittedFrame(bool enable_rtx, bool enable_red) {
Peter Boström67680c12016-02-17 11:10:04 +01001046 static const int kDroppedFrameNumber = 10;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001047 class RetransmissionObserver : public test::EndToEndTest,
nisse76bc8e82017-02-07 09:37:41 -08001048 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001049 public:
Peter Boström39593972016-02-15 11:27:15 +01001050 RetransmissionObserver(bool enable_rtx, bool enable_red)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001051 : EndToEndTest(kDefaultTimeoutMs),
Peter Boström39593972016-02-15 11:27:15 +01001052 payload_type_(GetPayloadType(false, enable_red)),
1053 retransmission_ssrc_(enable_rtx ? kSendRtxSsrcs[0]
1054 : kVideoSendSsrcs[0]),
1055 retransmission_payload_type_(GetPayloadType(enable_rtx, enable_red)),
magjed509e4fe2016-11-18 01:34:11 -08001056 encoder_(VP8Encoder::Create()),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001057 marker_bits_observed_(0),
danilchap192717e2016-07-25 08:20:51 -07001058 retransmitted_timestamp_(0) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001059
1060 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001061 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001062 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001063 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001064 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001065
Peter Boström67680c12016-02-17 11:10:04 +01001066 // Ignore padding-only packets over RTX.
1067 if (header.payloadType != payload_type_) {
1068 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
1069 if (length == header.headerLength + header.paddingLength)
1070 return SEND_PACKET;
Stefan Holmer586b19b2015-09-18 11:14:31 +02001071 }
Peter Boström67680c12016-02-17 11:10:04 +01001072
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001073 if (header.timestamp == retransmitted_timestamp_) {
1074 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
1075 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001076 return SEND_PACKET;
1077 }
1078
Stefan Holmer586b19b2015-09-18 11:14:31 +02001079 // Found the final packet of the frame to inflict loss to, drop this and
1080 // expect a retransmission.
danilchapfdd381c2016-07-25 04:03:20 -07001081 if (header.payloadType == payload_type_ && header.markerBit &&
1082 ++marker_bits_observed_ == kDroppedFrameNumber) {
Danil Chapovalov18c65a42016-06-29 15:29:34 +02001083 // This should be the only dropped packet.
1084 EXPECT_EQ(0u, retransmitted_timestamp_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001085 retransmitted_timestamp_ = header.timestamp;
danilchap192717e2016-07-25 08:20:51 -07001086 if (std::find(rendered_timestamps_.begin(), rendered_timestamps_.end(),
1087 retransmitted_timestamp_) != rendered_timestamps_.end()) {
1088 // Frame was rendered before last packet was scheduled for sending.
1089 // This is extremly rare but possible scenario because prober able to
1090 // resend packet before it was send.
1091 // TODO(danilchap): Remove this corner case when prober would not be
1092 // able to sneak in between packet saved to history for resending and
1093 // pacer notified about existance of that packet for sending.
1094 // See https://bugs.chromium.org/p/webrtc/issues/detail?id=5540 for
1095 // details.
1096 observation_complete_.Set();
1097 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001098 return DROP_PACKET;
1099 }
1100
1101 return SEND_PACKET;
1102 }
1103
nisse76bc8e82017-02-07 09:37:41 -08001104 void OnFrame(const VideoFrame& frame) override {
stefan5d837802017-02-08 07:09:05 -08001105 {
1106 rtc::CritScope lock(&crit_);
1107 if (frame.timestamp() == retransmitted_timestamp_)
1108 observation_complete_.Set();
1109 rendered_timestamps_.push_back(frame.timestamp());
1110 }
nisse76bc8e82017-02-07 09:37:41 -08001111 orig_renderer_->OnFrame(frame);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001112 }
1113
stefanff483612015-12-21 03:14:00 -08001114 void ModifyVideoConfigs(
1115 VideoSendStream::Config* send_config,
1116 std::vector<VideoReceiveStream::Config>* receive_configs,
1117 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001118 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
nisse76bc8e82017-02-07 09:37:41 -08001119
1120 // Insert ourselves into the rendering pipeline.
1121 RTC_DCHECK(!orig_renderer_);
1122 orig_renderer_ = (*receive_configs)[0].renderer;
1123 RTC_DCHECK(orig_renderer_);
stefan5d837802017-02-08 07:09:05 -08001124 (*receive_configs)[0].disable_prerenderer_smoothing = true;
nisse76bc8e82017-02-07 09:37:41 -08001125 (*receive_configs)[0].renderer = this;
1126
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001127 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
Shao Changbine62202f2015-04-21 20:24:50 +08001128
1129 if (payload_type_ == kRedPayloadType) {
brandtrb5f2c3f2016-10-04 23:28:39 -07001130 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
1131 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +01001132 if (retransmission_ssrc_ == kSendRtxSsrcs[0])
brandtrb5f2c3f2016-10-04 23:28:39 -07001133 send_config->rtp.ulpfec.red_rtx_payload_type = kRtxRedPayloadType;
1134 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type =
1135 send_config->rtp.ulpfec.ulpfec_payload_type;
1136 (*receive_configs)[0].rtp.ulpfec.red_payload_type =
1137 send_config->rtp.ulpfec.red_payload_type;
1138 (*receive_configs)[0].rtp.ulpfec.red_rtx_payload_type =
1139 send_config->rtp.ulpfec.red_rtx_payload_type;
Shao Changbine62202f2015-04-21 20:24:50 +08001140 }
1141
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001142 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
1143 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001144 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
brandtr14742122017-01-27 04:53:07 -08001145 (*receive_configs)[0].rtp.rtx_ssrc = kSendRtxSsrcs[0];
1146 (*receive_configs)[0].rtp.rtx_payload_types[payload_type_] =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001147 kSendRtxPayloadType;
1148 }
Peter Boström39593972016-02-15 11:27:15 +01001149 // Configure encoding and decoding with VP8, since generic packetization
1150 // doesn't support FEC with NACK.
kwibergaf476c72016-11-28 15:21:39 -08001151 RTC_DCHECK_EQ(1, (*receive_configs)[0].decoders.size());
Peter Boström39593972016-02-15 11:27:15 +01001152 send_config->encoder_settings.encoder = encoder_.get();
1153 send_config->encoder_settings.payload_name = "VP8";
1154 (*receive_configs)[0].decoders[0].payload_name = "VP8";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001155 }
1156
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001157 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001158 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001159 << "Timed out while waiting for retransmission to render.";
1160 }
1161
Shao Changbine62202f2015-04-21 20:24:50 +08001162 int GetPayloadType(bool use_rtx, bool use_red) {
Stefan Holmer10880012016-02-03 13:29:59 +01001163 if (use_red) {
1164 if (use_rtx)
1165 return kRtxRedPayloadType;
1166 return kRedPayloadType;
1167 }
1168 if (use_rtx)
1169 return kSendRtxPayloadType;
1170 return kFakeVideoSendPayloadType;
Shao Changbine62202f2015-04-21 20:24:50 +08001171 }
1172
stefanf116bd02015-10-27 08:29:42 -07001173 rtc::CriticalSection crit_;
nisse76bc8e82017-02-07 09:37:41 -08001174 rtc::VideoSinkInterface<VideoFrame>* orig_renderer_ = nullptr;
Shao Changbine62202f2015-04-21 20:24:50 +08001175 const int payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001176 const uint32_t retransmission_ssrc_;
1177 const int retransmission_payload_type_;
kwiberg27f982b2016-03-01 11:52:33 -08001178 std::unique_ptr<VideoEncoder> encoder_;
Peter Boström39593972016-02-15 11:27:15 +01001179 const std::string payload_name_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001180 int marker_bits_observed_;
stefanf116bd02015-10-27 08:29:42 -07001181 uint32_t retransmitted_timestamp_ GUARDED_BY(&crit_);
danilchap192717e2016-07-25 08:20:51 -07001182 std::vector<uint32_t> rendered_timestamps_ GUARDED_BY(&crit_);
Peter Boström39593972016-02-15 11:27:15 +01001183 } test(enable_rtx, enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001184
stefane74eef12016-01-08 06:47:13 -08001185 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001186}
1187
philipel277a8b52017-03-16 05:19:49 -07001188TEST_F(EndToEndTest, DecodesRetransmittedFrame) {
Shao Changbine62202f2015-04-21 20:24:50 +08001189 DecodesRetransmittedFrame(false, false);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001190}
1191
philipel277a8b52017-03-16 05:19:49 -07001192TEST_F(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +08001193 DecodesRetransmittedFrame(true, false);
1194}
1195
philipel277a8b52017-03-16 05:19:49 -07001196TEST_F(EndToEndTest, DecodesRetransmittedFrameByRed) {
Shao Changbine62202f2015-04-21 20:24:50 +08001197 DecodesRetransmittedFrame(false, true);
1198}
1199
philipel277a8b52017-03-16 05:19:49 -07001200TEST_F(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +08001201 DecodesRetransmittedFrame(true, true);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001202}
1203
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001204void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
1205 static const int kPacketsToDrop = 1;
1206
nisse7ade7b32016-03-23 04:48:10 -07001207 class PliObserver : public test::EndToEndTest,
1208 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001209 public:
1210 explicit PliObserver(int rtp_history_ms)
1211 : EndToEndTest(kLongTimeoutMs),
1212 rtp_history_ms_(rtp_history_ms),
1213 nack_enabled_(rtp_history_ms > 0),
1214 highest_dropped_timestamp_(0),
1215 frames_to_drop_(0),
1216 received_pli_(false) {}
1217
1218 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001219 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001220 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001221 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001222 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001223
1224 // Drop all retransmitted packets to force a PLI.
1225 if (header.timestamp <= highest_dropped_timestamp_)
1226 return DROP_PACKET;
1227
1228 if (frames_to_drop_ > 0) {
1229 highest_dropped_timestamp_ = header.timestamp;
1230 --frames_to_drop_;
1231 return DROP_PACKET;
1232 }
1233
1234 return SEND_PACKET;
1235 }
1236
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001237 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001238 rtc::CritScope lock(&crit_);
danilchap3dc929e2016-11-02 08:21:59 -07001239 test::RtcpPacketParser parser;
1240 EXPECT_TRUE(parser.Parse(packet, length));
1241 if (!nack_enabled_)
1242 EXPECT_EQ(0, parser.nack()->num_packets());
1243 if (parser.pli()->num_packets() > 0)
1244 received_pli_ = true;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001245 return SEND_PACKET;
1246 }
1247
nisseeb83a1a2016-03-21 01:27:56 -07001248 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001249 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001250 if (received_pli_ &&
1251 video_frame.timestamp() > highest_dropped_timestamp_) {
Peter Boström5811a392015-12-10 13:02:50 +01001252 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001253 }
1254 if (!received_pli_)
1255 frames_to_drop_ = kPacketsToDrop;
1256 }
1257
stefanff483612015-12-21 03:14:00 -08001258 void ModifyVideoConfigs(
1259 VideoSendStream::Config* send_config,
1260 std::vector<VideoReceiveStream::Config>* receive_configs,
1261 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001262 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001263 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
1264 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001265 }
1266
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001267 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001268 EXPECT_TRUE(Wait()) << "Timed out waiting for PLI to be "
1269 "received and a frame to be "
1270 "rendered afterwards.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001271 }
1272
stefanf116bd02015-10-27 08:29:42 -07001273 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001274 int rtp_history_ms_;
1275 bool nack_enabled_;
stefanf116bd02015-10-27 08:29:42 -07001276 uint32_t highest_dropped_timestamp_ GUARDED_BY(&crit_);
1277 int frames_to_drop_ GUARDED_BY(&crit_);
1278 bool received_pli_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001279 } test(rtp_history_ms);
1280
stefane74eef12016-01-08 06:47:13 -08001281 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001282}
1283
philipel277a8b52017-03-16 05:19:49 -07001284TEST_F(EndToEndTest, ReceivesPliAndRecoversWithNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001285 ReceivesPliAndRecovers(1000);
1286}
1287
philipel277a8b52017-03-16 05:19:49 -07001288TEST_F(EndToEndTest, ReceivesPliAndRecoversWithoutNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001289 ReceivesPliAndRecovers(0);
1290}
1291
philipel277a8b52017-03-16 05:19:49 -07001292TEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001293 class PacketInputObserver : public PacketReceiver {
1294 public:
1295 explicit PacketInputObserver(PacketReceiver* receiver)
Peter Boström5811a392015-12-10 13:02:50 +01001296 : receiver_(receiver), delivered_packet_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001297
Peter Boström5811a392015-12-10 13:02:50 +01001298 bool Wait() { return delivered_packet_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001299
1300 private:
stefan68786d22015-09-08 05:36:15 -07001301 DeliveryStatus DeliverPacket(MediaType media_type,
1302 const uint8_t* packet,
1303 size_t length,
1304 const PacketTime& packet_time) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001305 if (RtpHeaderParser::IsRtcp(packet, length)) {
stefan68786d22015-09-08 05:36:15 -07001306 return receiver_->DeliverPacket(media_type, packet, length,
1307 packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001308 } else {
1309 DeliveryStatus delivery_status =
stefan68786d22015-09-08 05:36:15 -07001310 receiver_->DeliverPacket(media_type, packet, length, packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001311 EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
Peter Boström5811a392015-12-10 13:02:50 +01001312 delivered_packet_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001313 return delivery_status;
1314 }
1315 }
1316
1317 PacketReceiver* receiver_;
Peter Boström5811a392015-12-10 13:02:50 +01001318 rtc::Event delivered_packet_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001319 };
1320
philipel4fb651d2017-04-10 03:54:05 -07001321 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
solenberg4fbae2b2015-08-28 04:07:10 -07001322
minyue20c84cc2017-04-10 16:57:57 -07001323 test::DirectTransport send_transport(sender_call_.get(), payload_type_map_);
1324 test::DirectTransport receive_transport(receiver_call_.get(),
1325 payload_type_map_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001326 PacketInputObserver input_observer(receiver_call_->Receiver());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001327 send_transport.SetReceiver(&input_observer);
1328 receive_transport.SetReceiver(sender_call_->Receiver());
1329
brandtr841de6a2016-11-15 07:10:52 -08001330 CreateSendConfig(1, 0, 0, &send_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001331 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001332
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001333 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07001334 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
1335 kDefaultHeight);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001336 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001337
stefanff483612015-12-21 03:14:00 -08001338 receiver_call_->DestroyVideoReceiveStream(video_receive_streams_[0]);
1339 video_receive_streams_.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001340
1341 // Wait() waits for a received packet.
Peter Boström5811a392015-12-10 13:02:50 +01001342 EXPECT_TRUE(input_observer.Wait());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001343
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001344 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001345
1346 DestroyStreams();
1347
1348 send_transport.StopSending();
1349 receive_transport.StopSending();
1350}
1351
pbosda903ea2015-10-02 02:36:56 -07001352void EndToEndTest::RespectsRtcpMode(RtcpMode rtcp_mode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001353 static const int kNumCompoundRtcpPacketsToObserve = 10;
1354 class RtcpModeObserver : public test::EndToEndTest {
1355 public:
pbosda903ea2015-10-02 02:36:56 -07001356 explicit RtcpModeObserver(RtcpMode rtcp_mode)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001357 : EndToEndTest(kDefaultTimeoutMs),
1358 rtcp_mode_(rtcp_mode),
1359 sent_rtp_(0),
1360 sent_rtcp_(0) {}
1361
1362 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001363 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanb77c7162017-02-06 06:29:38 -08001364 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001365 if (++sent_rtp_ % 3 == 0)
1366 return DROP_PACKET;
1367
1368 return SEND_PACKET;
1369 }
1370
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001371 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanb77c7162017-02-06 06:29:38 -08001372 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001373 ++sent_rtcp_;
danilchap3dc929e2016-11-02 08:21:59 -07001374 test::RtcpPacketParser parser;
1375 EXPECT_TRUE(parser.Parse(packet, length));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001376
danilchap3dc929e2016-11-02 08:21:59 -07001377 EXPECT_EQ(0, parser.sender_report()->num_packets());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001378
1379 switch (rtcp_mode_) {
pbosda903ea2015-10-02 02:36:56 -07001380 case RtcpMode::kCompound:
stefanb77c7162017-02-06 06:29:38 -08001381 // TODO(holmer): We shouldn't send transport feedback alone if
1382 // compound RTCP is negotiated.
1383 if (parser.receiver_report()->num_packets() == 0 &&
1384 parser.transport_feedback()->num_packets() == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001385 ADD_FAILURE() << "Received RTCP packet without receiver report for "
pbosda903ea2015-10-02 02:36:56 -07001386 "RtcpMode::kCompound.";
Peter Boström5811a392015-12-10 13:02:50 +01001387 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001388 }
1389
1390 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
Peter Boström5811a392015-12-10 13:02:50 +01001391 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001392
1393 break;
pbosda903ea2015-10-02 02:36:56 -07001394 case RtcpMode::kReducedSize:
danilchap3dc929e2016-11-02 08:21:59 -07001395 if (parser.receiver_report()->num_packets() == 0)
Peter Boström5811a392015-12-10 13:02:50 +01001396 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001397 break;
pbosda903ea2015-10-02 02:36:56 -07001398 case RtcpMode::kOff:
1399 RTC_NOTREACHED();
1400 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001401 }
1402
1403 return SEND_PACKET;
1404 }
1405
stefanff483612015-12-21 03:14:00 -08001406 void ModifyVideoConfigs(
1407 VideoSendStream::Config* send_config,
1408 std::vector<VideoReceiveStream::Config>* receive_configs,
1409 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001410 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001411 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1412 (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001413 }
1414
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001415 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001416 EXPECT_TRUE(Wait())
pbosda903ea2015-10-02 02:36:56 -07001417 << (rtcp_mode_ == RtcpMode::kCompound
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001418 ? "Timed out before observing enough compound packets."
1419 : "Timed out before receiving a non-compound RTCP packet.");
1420 }
1421
pbosda903ea2015-10-02 02:36:56 -07001422 RtcpMode rtcp_mode_;
stefanb77c7162017-02-06 06:29:38 -08001423 rtc::CriticalSection crit_;
1424 // Must be protected since RTCP can be sent by both the process thread
1425 // and the pacer thread.
1426 int sent_rtp_ GUARDED_BY(&crit_);
1427 int sent_rtcp_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001428 } test(rtcp_mode);
1429
stefane74eef12016-01-08 06:47:13 -08001430 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001431}
1432
philipel277a8b52017-03-16 05:19:49 -07001433TEST_F(EndToEndTest, UsesRtcpCompoundMode) {
pbosda903ea2015-10-02 02:36:56 -07001434 RespectsRtcpMode(RtcpMode::kCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001435}
1436
philipel277a8b52017-03-16 05:19:49 -07001437TEST_F(EndToEndTest, UsesRtcpReducedSizeMode) {
pbosda903ea2015-10-02 02:36:56 -07001438 RespectsRtcpMode(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001439}
1440
1441// Test sets up a Call multiple senders with different resolutions and SSRCs.
1442// Another is set up to receive all three of these with different renderers.
sprang867fb522015-08-03 04:38:41 -07001443class MultiStreamTest {
1444 public:
minyue20c84cc2017-04-10 16:57:57 -07001445 static constexpr size_t kNumStreams = 3;
1446 const uint8_t kVideoPayloadType = 124;
1447 const std::map<uint8_t, MediaType> payload_type_map_ = {
1448 {kVideoPayloadType, MediaType::VIDEO}};
1449
sprang867fb522015-08-03 04:38:41 -07001450 struct CodecSettings {
1451 uint32_t ssrc;
1452 int width;
1453 int height;
1454 } codec_settings[kNumStreams];
1455
1456 MultiStreamTest() {
1457 // TODO(sprang): Cleanup when msvc supports explicit initializers for array.
1458 codec_settings[0] = {1, 640, 480};
1459 codec_settings[1] = {2, 320, 240};
1460 codec_settings[2] = {3, 240, 160};
1461 }
1462
1463 virtual ~MultiStreamTest() {}
1464
1465 void RunTest() {
skvlad11a9cbf2016-10-07 11:53:05 -07001466 webrtc::RtcEventLogNullImpl event_log;
1467 Call::Config config(&event_log);
1468 std::unique_ptr<Call> sender_call(Call::Create(config));
1469 std::unique_ptr<Call> receiver_call(Call::Create(config));
kwiberg27f982b2016-03-01 11:52:33 -08001470 std::unique_ptr<test::DirectTransport> sender_transport(
stefanf116bd02015-10-27 08:29:42 -07001471 CreateSendTransport(sender_call.get()));
kwiberg27f982b2016-03-01 11:52:33 -08001472 std::unique_ptr<test::DirectTransport> receiver_transport(
stefanf116bd02015-10-27 08:29:42 -07001473 CreateReceiveTransport(receiver_call.get()));
sprang867fb522015-08-03 04:38:41 -07001474 sender_transport->SetReceiver(receiver_call->Receiver());
1475 receiver_transport->SetReceiver(sender_call->Receiver());
1476
kwiberg27f982b2016-03-01 11:52:33 -08001477 std::unique_ptr<VideoEncoder> encoders[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001478 for (size_t i = 0; i < kNumStreams; ++i)
magjed509e4fe2016-11-18 01:34:11 -08001479 encoders[i].reset(VP8Encoder::Create());
sprang867fb522015-08-03 04:38:41 -07001480
1481 VideoSendStream* send_streams[kNumStreams];
1482 VideoReceiveStream* receive_streams[kNumStreams];
1483
1484 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
kwiberg4a206a92016-03-31 10:24:26 -07001485 std::vector<std::unique_ptr<VideoDecoder>> allocated_decoders;
sprang867fb522015-08-03 04:38:41 -07001486 for (size_t i = 0; i < kNumStreams; ++i) {
1487 uint32_t ssrc = codec_settings[i].ssrc;
1488 int width = codec_settings[i].width;
1489 int height = codec_settings[i].height;
1490
solenberg4fbae2b2015-08-28 04:07:10 -07001491 VideoSendStream::Config send_config(sender_transport.get());
sprang867fb522015-08-03 04:38:41 -07001492 send_config.rtp.ssrcs.push_back(ssrc);
1493 send_config.encoder_settings.encoder = encoders[i].get();
1494 send_config.encoder_settings.payload_name = "VP8";
minyue20c84cc2017-04-10 16:57:57 -07001495 send_config.encoder_settings.payload_type = kVideoPayloadType;
sprang867fb522015-08-03 04:38:41 -07001496 VideoEncoderConfig encoder_config;
perkjfa10b552016-10-02 23:45:26 -07001497 test::FillEncoderConfiguration(1, &encoder_config);
1498 encoder_config.max_bitrate_bps = 100000;
sprang867fb522015-08-03 04:38:41 -07001499
1500 UpdateSendConfig(i, &send_config, &encoder_config, &frame_generators[i]);
1501
perkj26091b12016-09-01 01:17:40 -07001502 send_streams[i] = sender_call->CreateVideoSendStream(
1503 send_config.Copy(), encoder_config.Copy());
sprang867fb522015-08-03 04:38:41 -07001504 send_streams[i]->Start();
1505
solenberg4fbae2b2015-08-28 04:07:10 -07001506 VideoReceiveStream::Config receive_config(receiver_transport.get());
sprang867fb522015-08-03 04:38:41 -07001507 receive_config.rtp.remote_ssrc = ssrc;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001508 receive_config.rtp.local_ssrc = test::CallTest::kReceiverLocalVideoSsrc;
sprang867fb522015-08-03 04:38:41 -07001509 VideoReceiveStream::Decoder decoder =
1510 test::CreateMatchingDecoder(send_config.encoder_settings);
kwiberg4a206a92016-03-31 10:24:26 -07001511 allocated_decoders.push_back(
1512 std::unique_ptr<VideoDecoder>(decoder.decoder));
sprang867fb522015-08-03 04:38:41 -07001513 receive_config.decoders.push_back(decoder);
1514
1515 UpdateReceiveConfig(i, &receive_config);
1516
1517 receive_streams[i] =
Tommi733b5472016-06-10 17:58:01 +02001518 receiver_call->CreateVideoReceiveStream(std::move(receive_config));
sprang867fb522015-08-03 04:38:41 -07001519 receive_streams[i]->Start();
1520
1521 frame_generators[i] = test::FrameGeneratorCapturer::Create(
perkja49cbd32016-09-16 07:53:41 -07001522 width, height, 30, Clock::GetRealTimeClock());
perkj803d97f2016-11-01 11:45:46 -07001523 send_streams[i]->SetSource(
1524 frame_generators[i],
sprangc5d62e22017-04-02 23:53:04 -07001525 VideoSendStream::DegradationPreference::kMaintainFramerate);
sprang867fb522015-08-03 04:38:41 -07001526 frame_generators[i]->Start();
1527 }
1528
1529 Wait();
1530
1531 for (size_t i = 0; i < kNumStreams; ++i) {
1532 frame_generators[i]->Stop();
1533 sender_call->DestroyVideoSendStream(send_streams[i]);
1534 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1535 delete frame_generators[i];
1536 }
1537
1538 sender_transport->StopSending();
1539 receiver_transport->StopSending();
1540 }
1541
1542 protected:
1543 virtual void Wait() = 0;
1544 // Note: frame_generator is a point-to-pointer, since the actual instance
1545 // hasn't been created at the time of this call. Only when packets/frames
1546 // start flowing should this be dereferenced.
1547 virtual void UpdateSendConfig(
1548 size_t stream_index,
1549 VideoSendStream::Config* send_config,
1550 VideoEncoderConfig* encoder_config,
1551 test::FrameGeneratorCapturer** frame_generator) {}
1552 virtual void UpdateReceiveConfig(size_t stream_index,
1553 VideoReceiveStream::Config* receive_config) {
1554 }
stefanf116bd02015-10-27 08:29:42 -07001555 virtual test::DirectTransport* CreateSendTransport(Call* sender_call) {
minyue20c84cc2017-04-10 16:57:57 -07001556 return new test::DirectTransport(sender_call, payload_type_map_);
sprang867fb522015-08-03 04:38:41 -07001557 }
stefanf116bd02015-10-27 08:29:42 -07001558 virtual test::DirectTransport* CreateReceiveTransport(Call* receiver_call) {
minyue20c84cc2017-04-10 16:57:57 -07001559 return new test::DirectTransport(receiver_call, payload_type_map_);
sprang867fb522015-08-03 04:38:41 -07001560 }
1561};
1562
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001563// Each renderer verifies that it receives the expected resolution, and as soon
1564// as every renderer has received a frame, the test finishes.
philipel277a8b52017-03-16 05:19:49 -07001565TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) {
nisse7ade7b32016-03-23 04:48:10 -07001566 class VideoOutputObserver : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001567 public:
sprang867fb522015-08-03 04:38:41 -07001568 VideoOutputObserver(const MultiStreamTest::CodecSettings& settings,
1569 uint32_t ssrc,
1570 test::FrameGeneratorCapturer** frame_generator)
1571 : settings_(settings),
1572 ssrc_(ssrc),
1573 frame_generator_(frame_generator),
Peter Boström5811a392015-12-10 13:02:50 +01001574 done_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001575
nisseeb83a1a2016-03-21 01:27:56 -07001576 void OnFrame(const VideoFrame& video_frame) override {
sprang867fb522015-08-03 04:38:41 -07001577 EXPECT_EQ(settings_.width, video_frame.width());
1578 EXPECT_EQ(settings_.height, video_frame.height());
1579 (*frame_generator_)->Stop();
Peter Boström5811a392015-12-10 13:02:50 +01001580 done_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001581 }
1582
sprang867fb522015-08-03 04:38:41 -07001583 uint32_t Ssrc() { return ssrc_; }
1584
Peter Boström5811a392015-12-10 13:02:50 +01001585 bool Wait() { return done_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001586
1587 private:
sprang867fb522015-08-03 04:38:41 -07001588 const MultiStreamTest::CodecSettings& settings_;
1589 const uint32_t ssrc_;
1590 test::FrameGeneratorCapturer** const frame_generator_;
Peter Boström5811a392015-12-10 13:02:50 +01001591 rtc::Event done_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001592 };
1593
sprang867fb522015-08-03 04:38:41 -07001594 class Tester : public MultiStreamTest {
1595 public:
1596 Tester() {}
1597 virtual ~Tester() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001598
sprang867fb522015-08-03 04:38:41 -07001599 protected:
1600 void Wait() override {
1601 for (const auto& observer : observers_) {
Peter Boström5811a392015-12-10 13:02:50 +01001602 EXPECT_TRUE(observer->Wait()) << "Time out waiting for from on ssrc "
1603 << observer->Ssrc();
sprang867fb522015-08-03 04:38:41 -07001604 }
1605 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001606
sprang867fb522015-08-03 04:38:41 -07001607 void UpdateSendConfig(
1608 size_t stream_index,
1609 VideoSendStream::Config* send_config,
1610 VideoEncoderConfig* encoder_config,
1611 test::FrameGeneratorCapturer** frame_generator) override {
1612 observers_[stream_index].reset(new VideoOutputObserver(
1613 codec_settings[stream_index], send_config->rtp.ssrcs.front(),
1614 frame_generator));
1615 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001616
sprang867fb522015-08-03 04:38:41 -07001617 void UpdateReceiveConfig(
1618 size_t stream_index,
1619 VideoReceiveStream::Config* receive_config) override {
1620 receive_config->renderer = observers_[stream_index].get();
1621 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001622
sprang867fb522015-08-03 04:38:41 -07001623 private:
kwiberg27f982b2016-03-01 11:52:33 -08001624 std::unique_ptr<VideoOutputObserver> observers_[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001625 } tester;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001626
sprang867fb522015-08-03 04:38:41 -07001627 tester.RunTest();
1628}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001629
philipel277a8b52017-03-16 05:19:49 -07001630TEST_F(EndToEndTest, AssignsTransportSequenceNumbers) {
sprang867fb522015-08-03 04:38:41 -07001631 static const int kExtensionId = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001632
sprang867fb522015-08-03 04:38:41 -07001633 class RtpExtensionHeaderObserver : public test::DirectTransport {
1634 public:
minyue20c84cc2017-04-10 16:57:57 -07001635 RtpExtensionHeaderObserver(
1636 Call* sender_call,
1637 const uint32_t& first_media_ssrc,
1638 const std::map<uint32_t, uint32_t>& ssrc_map,
1639 const std::map<uint8_t, MediaType>& payload_type_map)
1640 : DirectTransport(sender_call, payload_type_map),
Peter Boström5811a392015-12-10 13:02:50 +01001641 done_(false, false),
sprang867fb522015-08-03 04:38:41 -07001642 parser_(RtpHeaderParser::Create()),
sprang861c55e2015-10-16 10:01:21 -07001643 first_media_ssrc_(first_media_ssrc),
1644 rtx_to_media_ssrcs_(ssrc_map),
sprang867fb522015-08-03 04:38:41 -07001645 padding_observed_(false),
sprang861c55e2015-10-16 10:01:21 -07001646 rtx_padding_observed_(false),
1647 retransmit_observed_(false),
1648 started_(false) {
sprang867fb522015-08-03 04:38:41 -07001649 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
1650 kExtensionId);
1651 }
1652 virtual ~RtpExtensionHeaderObserver() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001653
stefan1d8a5062015-10-02 03:39:33 -07001654 bool SendRtp(const uint8_t* data,
1655 size_t length,
1656 const PacketOptions& options) override {
sprang861c55e2015-10-16 10:01:21 -07001657 {
1658 rtc::CritScope cs(&lock_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001659
Erik Språng8d629712015-08-04 16:24:03 +02001660 if (IsDone())
sprang861c55e2015-10-16 10:01:21 -07001661 return false;
1662
1663 if (started_) {
1664 RTPHeader header;
1665 EXPECT_TRUE(parser_->Parse(data, length, &header));
1666 bool drop_packet = false;
1667
1668 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
1669 EXPECT_EQ(options.packet_id,
1670 header.extension.transportSequenceNumber);
1671 if (!streams_observed_.empty()) {
1672 // Unwrap packet id and verify uniqueness.
1673 int64_t packet_id = unwrapper_.Unwrap(options.packet_id);
1674 EXPECT_TRUE(received_packed_ids_.insert(packet_id).second);
1675 }
1676
1677 // Drop (up to) every 17th packet, so we get retransmits.
1678 // Only drop media, and not on the first stream (otherwise it will be
1679 // hard to distinguish from padding, which is always sent on the first
1680 // stream).
1681 if (header.payloadType != kSendRtxPayloadType &&
1682 header.ssrc != first_media_ssrc_ &&
1683 header.extension.transportSequenceNumber % 17 == 0) {
1684 dropped_seq_[header.ssrc].insert(header.sequenceNumber);
1685 drop_packet = true;
1686 }
1687
perkja8ba1952017-02-27 06:52:10 -08001688 if (header.payloadType == kSendRtxPayloadType) {
sprang861c55e2015-10-16 10:01:21 -07001689 uint16_t original_sequence_number =
1690 ByteReader<uint16_t>::ReadBigEndian(&data[header.headerLength]);
1691 uint32_t original_ssrc =
1692 rtx_to_media_ssrcs_.find(header.ssrc)->second;
1693 std::set<uint16_t>* seq_no_map = &dropped_seq_[original_ssrc];
1694 auto it = seq_no_map->find(original_sequence_number);
1695 if (it != seq_no_map->end()) {
1696 retransmit_observed_ = true;
1697 seq_no_map->erase(it);
1698 } else {
1699 rtx_padding_observed_ = true;
1700 }
1701 } else {
1702 streams_observed_.insert(header.ssrc);
1703 }
1704
1705 if (IsDone())
Peter Boström5811a392015-12-10 13:02:50 +01001706 done_.Set();
sprang861c55e2015-10-16 10:01:21 -07001707
1708 if (drop_packet)
1709 return true;
1710 }
sprang867fb522015-08-03 04:38:41 -07001711 }
sprang861c55e2015-10-16 10:01:21 -07001712
stefan1d8a5062015-10-02 03:39:33 -07001713 return test::DirectTransport::SendRtp(data, length, options);
sprang867fb522015-08-03 04:38:41 -07001714 }
1715
Erik Språng8d629712015-08-04 16:24:03 +02001716 bool IsDone() {
sprang861c55e2015-10-16 10:01:21 -07001717 bool observed_types_ok =
1718 streams_observed_.size() == MultiStreamTest::kNumStreams &&
perkja8ba1952017-02-27 06:52:10 -08001719 retransmit_observed_ && rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001720 if (!observed_types_ok)
1721 return false;
1722 // We should not have any gaps in the sequence number range.
1723 size_t seqno_range =
1724 *received_packed_ids_.rbegin() - *received_packed_ids_.begin() + 1;
1725 return seqno_range == received_packed_ids_.size();
Erik Språng8d629712015-08-04 16:24:03 +02001726 }
1727
Peter Boström5811a392015-12-10 13:02:50 +01001728 bool Wait() {
sprang861c55e2015-10-16 10:01:21 -07001729 {
1730 // Can't be sure until this point that rtx_to_media_ssrcs_ etc have
1731 // been initialized and are OK to read.
1732 rtc::CritScope cs(&lock_);
1733 started_ = true;
1734 }
Peter Boström5811a392015-12-10 13:02:50 +01001735 return done_.Wait(kDefaultTimeoutMs);
sprang861c55e2015-10-16 10:01:21 -07001736 }
sprang867fb522015-08-03 04:38:41 -07001737
sprang861c55e2015-10-16 10:01:21 -07001738 rtc::CriticalSection lock_;
Peter Boström5811a392015-12-10 13:02:50 +01001739 rtc::Event done_;
kwiberg27f982b2016-03-01 11:52:33 -08001740 std::unique_ptr<RtpHeaderParser> parser_;
sprang861c55e2015-10-16 10:01:21 -07001741 SequenceNumberUnwrapper unwrapper_;
1742 std::set<int64_t> received_packed_ids_;
sprang867fb522015-08-03 04:38:41 -07001743 std::set<uint32_t> streams_observed_;
sprang861c55e2015-10-16 10:01:21 -07001744 std::map<uint32_t, std::set<uint16_t>> dropped_seq_;
1745 const uint32_t& first_media_ssrc_;
1746 const std::map<uint32_t, uint32_t>& rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001747 bool padding_observed_;
1748 bool rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001749 bool retransmit_observed_;
1750 bool started_;
sprang867fb522015-08-03 04:38:41 -07001751 };
1752
1753 class TransportSequenceNumberTester : public MultiStreamTest {
1754 public:
sprang861c55e2015-10-16 10:01:21 -07001755 TransportSequenceNumberTester()
1756 : first_media_ssrc_(0), observer_(nullptr) {}
sprang867fb522015-08-03 04:38:41 -07001757 virtual ~TransportSequenceNumberTester() {}
1758
1759 protected:
1760 void Wait() override {
Peter Boström74f6e9e2016-04-04 17:56:10 +02001761 RTC_DCHECK(observer_);
Peter Boström5811a392015-12-10 13:02:50 +01001762 EXPECT_TRUE(observer_->Wait());
sprang867fb522015-08-03 04:38:41 -07001763 }
1764
1765 void UpdateSendConfig(
1766 size_t stream_index,
1767 VideoSendStream::Config* send_config,
1768 VideoEncoderConfig* encoder_config,
1769 test::FrameGeneratorCapturer** frame_generator) override {
1770 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001771 send_config->rtp.extensions.push_back(RtpExtension(
1772 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sprang867fb522015-08-03 04:38:41 -07001773
perkja8ba1952017-02-27 06:52:10 -08001774 // Force some padding to be sent. Note that since we do send media
1775 // packets we can not guarantee that a padding only packet is sent.
1776 // Instead, padding will most likely be send as an RTX packet.
sprang867fb522015-08-03 04:38:41 -07001777 const int kPaddingBitrateBps = 50000;
perkja8ba1952017-02-27 06:52:10 -08001778 encoder_config->max_bitrate_bps = 200000;
sprang867fb522015-08-03 04:38:41 -07001779 encoder_config->min_transmit_bitrate_bps =
perkjfa10b552016-10-02 23:45:26 -07001780 encoder_config->max_bitrate_bps + kPaddingBitrateBps;
sprang867fb522015-08-03 04:38:41 -07001781
1782 // Configure RTX for redundant payload padding.
1783 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang861c55e2015-10-16 10:01:21 -07001784 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[stream_index]);
sprang867fb522015-08-03 04:38:41 -07001785 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
sprang861c55e2015-10-16 10:01:21 -07001786 rtx_to_media_ssrcs_[kSendRtxSsrcs[stream_index]] =
1787 send_config->rtp.ssrcs[0];
1788
1789 if (stream_index == 0)
1790 first_media_ssrc_ = send_config->rtp.ssrcs[0];
sprang867fb522015-08-03 04:38:41 -07001791 }
1792
1793 void UpdateReceiveConfig(
1794 size_t stream_index,
1795 VideoReceiveStream::Config* receive_config) override {
sprang861c55e2015-10-16 10:01:21 -07001796 receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang867fb522015-08-03 04:38:41 -07001797 receive_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001798 receive_config->rtp.extensions.push_back(RtpExtension(
1799 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sakal55d932b2016-09-30 06:19:08 -07001800 receive_config->renderer = &fake_renderer_;
sprang867fb522015-08-03 04:38:41 -07001801 }
1802
stefanf116bd02015-10-27 08:29:42 -07001803 test::DirectTransport* CreateSendTransport(Call* sender_call) override {
minyue20c84cc2017-04-10 16:57:57 -07001804 std::map<uint8_t, MediaType> payload_type_map =
1805 MultiStreamTest::payload_type_map_;
1806 RTC_DCHECK(payload_type_map.find(kSendRtxPayloadType) ==
1807 payload_type_map.end());
1808 payload_type_map[kSendRtxPayloadType] = MediaType::VIDEO;
1809 observer_ =
1810 new RtpExtensionHeaderObserver(sender_call, first_media_ssrc_,
1811 rtx_to_media_ssrcs_, payload_type_map);
sprang867fb522015-08-03 04:38:41 -07001812 return observer_;
1813 }
1814
1815 private:
sakal55d932b2016-09-30 06:19:08 -07001816 test::FakeVideoRenderer fake_renderer_;
sprang861c55e2015-10-16 10:01:21 -07001817 uint32_t first_media_ssrc_;
1818 std::map<uint32_t, uint32_t> rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001819 RtpExtensionHeaderObserver* observer_;
1820 } tester;
1821
1822 tester.RunTest();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001823}
1824
Stefan Holmer04cb7632016-01-14 20:34:30 +01001825class TransportFeedbackTester : public test::EndToEndTest {
1826 public:
1827 explicit TransportFeedbackTester(bool feedback_enabled,
1828 size_t num_video_streams,
1829 size_t num_audio_streams)
1830 : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
1831 feedback_enabled_(feedback_enabled),
1832 num_video_streams_(num_video_streams),
sprangcd349d92016-07-13 09:11:28 -07001833 num_audio_streams_(num_audio_streams),
1834 receiver_call_(nullptr) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001835 // Only one stream of each supported for now.
1836 EXPECT_LE(num_video_streams, 1u);
1837 EXPECT_LE(num_audio_streams, 1u);
1838 }
1839
1840 protected:
1841 Action OnSendRtcp(const uint8_t* data, size_t length) override {
1842 EXPECT_FALSE(HasTransportFeedback(data, length));
1843 return SEND_PACKET;
1844 }
1845
1846 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
1847 if (HasTransportFeedback(data, length))
1848 observation_complete_.Set();
1849 return SEND_PACKET;
1850 }
1851
1852 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
danilchap3dc929e2016-11-02 08:21:59 -07001853 test::RtcpPacketParser parser;
1854 EXPECT_TRUE(parser.Parse(data, length));
1855 return parser.transport_feedback()->num_packets() > 0;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001856 }
1857
1858 void PerformTest() override {
1859 const int64_t kDisabledFeedbackTimeoutMs = 5000;
1860 EXPECT_EQ(feedback_enabled_,
1861 observation_complete_.Wait(feedback_enabled_
1862 ? test::CallTest::kDefaultTimeoutMs
1863 : kDisabledFeedbackTimeoutMs));
1864 }
1865
1866 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1867 receiver_call_ = receiver_call;
1868 }
1869
1870 size_t GetNumVideoStreams() const override { return num_video_streams_; }
1871 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
1872
1873 void ModifyVideoConfigs(
1874 VideoSendStream::Config* send_config,
1875 std::vector<VideoReceiveStream::Config>* receive_configs,
1876 VideoEncoderConfig* encoder_config) override {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001877 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
1878 }
1879
1880 void ModifyAudioConfigs(
1881 AudioSendStream::Config* send_config,
1882 std::vector<AudioReceiveStream::Config>* receive_configs) override {
1883 send_config->rtp.extensions.clear();
1884 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001885 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001886 (*receive_configs)[0].rtp.extensions.clear();
1887 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1888 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001889 }
1890
1891 private:
Erik Språng6b8d3552015-09-24 15:06:57 +02001892 static const int kExtensionId = 5;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001893 const bool feedback_enabled_;
1894 const size_t num_video_streams_;
1895 const size_t num_audio_streams_;
1896 Call* receiver_call_;
1897};
Erik Språng6b8d3552015-09-24 15:06:57 +02001898
philipel277a8b52017-03-16 05:19:49 -07001899TEST_F(EndToEndTest, VideoReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001900 TransportFeedbackTester test(true, 1, 0);
1901 RunBaseTest(&test);
Erik Språng6b8d3552015-09-24 15:06:57 +02001902}
stefan43edf0f2015-11-20 18:05:48 -08001903
philipel277a8b52017-03-16 05:19:49 -07001904TEST_F(EndToEndTest, VideoTransportFeedbackNotConfigured) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001905 TransportFeedbackTester test(false, 1, 0);
1906 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001907}
1908
philipel277a8b52017-03-16 05:19:49 -07001909TEST_F(EndToEndTest, AudioReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001910 TransportFeedbackTester test(true, 0, 1);
1911 RunBaseTest(&test);
1912}
1913
philipel277a8b52017-03-16 05:19:49 -07001914TEST_F(EndToEndTest, AudioTransportFeedbackNotConfigured) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001915 TransportFeedbackTester test(false, 0, 1);
1916 RunBaseTest(&test);
1917}
1918
philipel277a8b52017-03-16 05:19:49 -07001919TEST_F(EndToEndTest, AudioVideoReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001920 TransportFeedbackTester test(true, 1, 1);
1921 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001922}
1923
philipel277a8b52017-03-16 05:19:49 -07001924TEST_F(EndToEndTest, ObserversEncodedFrames) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001925 class EncodedFrameTestObserver : public EncodedFrameObserver {
1926 public:
1927 EncodedFrameTestObserver()
Peter Boström5811a392015-12-10 13:02:50 +01001928 : length_(0), frame_type_(kEmptyFrame), called_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001929 virtual ~EncodedFrameTestObserver() {}
1930
1931 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
1932 frame_type_ = encoded_frame.frame_type_;
1933 length_ = encoded_frame.length_;
1934 buffer_.reset(new uint8_t[length_]);
1935 memcpy(buffer_.get(), encoded_frame.data_, length_);
Peter Boström5811a392015-12-10 13:02:50 +01001936 called_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001937 }
1938
Peter Boström5811a392015-12-10 13:02:50 +01001939 bool Wait() { return called_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001940
1941 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
1942 ASSERT_EQ(length_, observer.length_)
1943 << "Observed frames are of different lengths.";
1944 EXPECT_EQ(frame_type_, observer.frame_type_)
1945 << "Observed frames have different frame types.";
1946 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
1947 << "Observed encoded frames have different content.";
1948 }
1949
1950 private:
kwiberg27f982b2016-03-01 11:52:33 -08001951 std::unique_ptr<uint8_t[]> buffer_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001952 size_t length_;
1953 FrameType frame_type_;
Peter Boström5811a392015-12-10 13:02:50 +01001954 rtc::Event called_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001955 };
1956
1957 EncodedFrameTestObserver post_encode_observer;
1958 EncodedFrameTestObserver pre_decode_observer;
1959
philipel4fb651d2017-04-10 03:54:05 -07001960 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
solenberg4fbae2b2015-08-28 04:07:10 -07001961
minyue20c84cc2017-04-10 16:57:57 -07001962 test::DirectTransport sender_transport(sender_call_.get(), payload_type_map_);
1963 test::DirectTransport receiver_transport(receiver_call_.get(),
1964 payload_type_map_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001965 sender_transport.SetReceiver(receiver_call_->Receiver());
1966 receiver_transport.SetReceiver(sender_call_->Receiver());
1967
brandtr841de6a2016-11-15 07:10:52 -08001968 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001969 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -08001970 video_send_config_.post_encode_callback = &post_encode_observer;
1971 video_receive_configs_[0].pre_decode_callback = &pre_decode_observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001972
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001973 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001974 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001975
kwiberg27f982b2016-03-01 11:52:33 -08001976 std::unique_ptr<test::FrameGenerator> frame_generator(
perkja8ba1952017-02-27 06:52:10 -08001977 test::FrameGenerator::CreateSquareGenerator(kDefaultWidth,
perkjfa10b552016-10-02 23:45:26 -07001978 kDefaultHeight));
perkja49cbd32016-09-16 07:53:41 -07001979 test::FrameForwarder forwarder;
perkj803d97f2016-11-01 11:45:46 -07001980 video_send_stream_->SetSource(
sprangc5d62e22017-04-02 23:53:04 -07001981 &forwarder, VideoSendStream::DegradationPreference::kMaintainFramerate);
perkja49cbd32016-09-16 07:53:41 -07001982 forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001983
Peter Boström5811a392015-12-10 13:02:50 +01001984 EXPECT_TRUE(post_encode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001985 << "Timed out while waiting for send-side encoded-frame callback.";
1986
Peter Boström5811a392015-12-10 13:02:50 +01001987 EXPECT_TRUE(pre_decode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001988 << "Timed out while waiting for pre-decode encoded-frame callback.";
1989
1990 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
1991
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001992 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001993
1994 sender_transport.StopSending();
1995 receiver_transport.StopSending();
1996
1997 DestroyStreams();
1998}
1999
philipel277a8b52017-03-16 05:19:49 -07002000TEST_F(EndToEndTest, ReceiveStreamSendsRemb) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002001 class RembObserver : public test::EndToEndTest {
2002 public:
2003 RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
2004
stefanb77c7162017-02-06 06:29:38 -08002005 void ModifyVideoConfigs(
2006 VideoSendStream::Config* send_config,
2007 std::vector<VideoReceiveStream::Config>* receive_configs,
2008 VideoEncoderConfig* encoder_config) override {
2009 send_config->rtp.extensions.clear();
2010 send_config->rtp.extensions.push_back(RtpExtension(
2011 RtpExtension::kAbsSendTimeUri, test::kAbsSendTimeExtensionId));
2012 (*receive_configs)[0].rtp.remb = true;
2013 (*receive_configs)[0].rtp.transport_cc = false;
2014 }
2015
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002016 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
danilchap3dc929e2016-11-02 08:21:59 -07002017 test::RtcpPacketParser parser;
2018 EXPECT_TRUE(parser.Parse(packet, length));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002019
danilchap3dc929e2016-11-02 08:21:59 -07002020 if (parser.remb()->num_packets() > 0) {
2021 EXPECT_EQ(kReceiverLocalVideoSsrc, parser.remb()->sender_ssrc());
2022 EXPECT_LT(0U, parser.remb()->bitrate_bps());
2023 EXPECT_EQ(1U, parser.remb()->ssrcs().size());
2024 EXPECT_EQ(kVideoSendSsrcs[0], parser.remb()->ssrcs()[0]);
Peter Boström5811a392015-12-10 13:02:50 +01002025 observation_complete_.Set();
danilchap3dc929e2016-11-02 08:21:59 -07002026 }
2027
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002028 return SEND_PACKET;
2029 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002030 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002031 EXPECT_TRUE(Wait()) << "Timed out while waiting for a "
2032 "receiver RTCP REMB packet to be "
2033 "sent.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002034 }
2035 } test;
2036
stefane74eef12016-01-08 06:47:13 -08002037 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002038}
2039
stefanb77c7162017-02-06 06:29:38 -08002040class BandwidthStatsTest : public test::EndToEndTest {
2041 public:
2042 explicit BandwidthStatsTest(bool send_side_bwe)
2043 : EndToEndTest(test::CallTest::kDefaultTimeoutMs),
2044 sender_call_(nullptr),
2045 receiver_call_(nullptr),
2046 has_seen_pacer_delay_(false),
2047 send_side_bwe_(send_side_bwe) {}
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002048
stefanb77c7162017-02-06 06:29:38 -08002049 void ModifyVideoConfigs(
2050 VideoSendStream::Config* send_config,
2051 std::vector<VideoReceiveStream::Config>* receive_configs,
2052 VideoEncoderConfig* encoder_config) override {
2053 if (!send_side_bwe_) {
2054 send_config->rtp.extensions.clear();
2055 send_config->rtp.extensions.push_back(RtpExtension(
2056 RtpExtension::kAbsSendTimeUri, test::kAbsSendTimeExtensionId));
2057 (*receive_configs)[0].rtp.remb = true;
2058 (*receive_configs)[0].rtp.transport_cc = false;
2059 }
2060 }
2061
2062 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2063 Call::Stats sender_stats = sender_call_->GetStats();
2064 Call::Stats receiver_stats = receiver_call_->GetStats();
2065 if (!has_seen_pacer_delay_)
2066 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
2067 if (sender_stats.send_bandwidth_bps > 0 && has_seen_pacer_delay_) {
2068 if (send_side_bwe_ || receiver_stats.recv_bandwidth_bps > 0)
Peter Boström5811a392015-12-10 13:02:50 +01002069 observation_complete_.Set();
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002070 }
stefanb77c7162017-02-06 06:29:38 -08002071 return SEND_PACKET;
2072 }
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002073
stefanb77c7162017-02-06 06:29:38 -08002074 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2075 sender_call_ = sender_call;
2076 receiver_call_ = receiver_call;
2077 }
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002078
stefanb77c7162017-02-06 06:29:38 -08002079 void PerformTest() override {
2080 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2081 "non-zero bandwidth stats.";
2082 }
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002083
stefanb77c7162017-02-06 06:29:38 -08002084 private:
2085 Call* sender_call_;
2086 Call* receiver_call_;
2087 bool has_seen_pacer_delay_;
2088 const bool send_side_bwe_;
2089};
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002090
philipel277a8b52017-03-16 05:19:49 -07002091TEST_F(EndToEndTest, VerifySendSideBweStats) {
stefanb77c7162017-02-06 06:29:38 -08002092 BandwidthStatsTest test(true);
stefane74eef12016-01-08 06:47:13 -08002093 RunBaseTest(&test);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002094}
2095
philipel277a8b52017-03-16 05:19:49 -07002096TEST_F(EndToEndTest, VerifyRecvSideBweStats) {
stefanb77c7162017-02-06 06:29:38 -08002097 BandwidthStatsTest test(false);
2098 RunBaseTest(&test);
2099}
stefan32f81542016-01-20 07:13:58 -08002100
2101// Verifies that it's possible to limit the send BWE by sending a REMB.
2102// This is verified by allowing the send BWE to ramp-up to >1000 kbps,
2103// then have the test generate a REMB of 500 kbps and verify that the send BWE
2104// is reduced to exactly 500 kbps. Then a REMB of 1000 kbps is generated and the
2105// test verifies that the send BWE ramps back up to exactly 1000 kbps.
philipel277a8b52017-03-16 05:19:49 -07002106TEST_F(EndToEndTest, RembWithSendSideBwe) {
stefan32f81542016-01-20 07:13:58 -08002107 class BweObserver : public test::EndToEndTest {
2108 public:
2109 BweObserver()
2110 : EndToEndTest(kDefaultTimeoutMs),
2111 sender_call_(nullptr),
2112 clock_(Clock::GetRealTimeClock()),
2113 sender_ssrc_(0),
2114 remb_bitrate_bps_(1000000),
2115 receive_transport_(nullptr),
Tommi5dd5f5a2017-02-21 14:22:59 +01002116 stop_event_(false, false),
stefan32f81542016-01-20 07:13:58 -08002117 poller_thread_(&BitrateStatsPollingThread,
2118 this,
2119 "BitrateStatsPollingThread"),
Erik Språng737336d2016-07-29 12:59:36 +02002120 state_(kWaitForFirstRampUp),
2121 retransmission_rate_limiter_(clock_, 1000) {}
stefan32f81542016-01-20 07:13:58 -08002122
2123 ~BweObserver() {}
2124
nisseef8b61e2016-04-29 06:09:15 -07002125 test::PacketTransport* CreateReceiveTransport() override {
stefan32f81542016-01-20 07:13:58 -08002126 receive_transport_ = new test::PacketTransport(
minyue20c84cc2017-04-10 16:57:57 -07002127 nullptr, this, test::PacketTransport::kReceiver, payload_type_map_,
stefan32f81542016-01-20 07:13:58 -08002128 FakeNetworkPipe::Config());
2129 return receive_transport_;
2130 }
2131
2132 Call::Config GetSenderCallConfig() override {
philipel4fb651d2017-04-10 03:54:05 -07002133 Call::Config config(event_log_.get());
stefan32f81542016-01-20 07:13:58 -08002134 // Set a high start bitrate to reduce the test completion time.
2135 config.bitrate_config.start_bitrate_bps = remb_bitrate_bps_;
2136 return config;
2137 }
2138
2139 void ModifyVideoConfigs(
2140 VideoSendStream::Config* send_config,
2141 std::vector<VideoReceiveStream::Config>* receive_configs,
2142 VideoEncoderConfig* encoder_config) override {
2143 ASSERT_EQ(1u, send_config->rtp.ssrcs.size());
stefan32f81542016-01-20 07:13:58 -08002144 sender_ssrc_ = send_config->rtp.ssrcs[0];
2145
perkjfa10b552016-10-02 23:45:26 -07002146 encoder_config->max_bitrate_bps = 2000000;
stefan32f81542016-01-20 07:13:58 -08002147
2148 ASSERT_EQ(1u, receive_configs->size());
stefan32f81542016-01-20 07:13:58 -08002149 RtpRtcp::Configuration config;
2150 config.receiver_only = true;
2151 config.clock = clock_;
2152 config.outgoing_transport = receive_transport_;
Erik Språng737336d2016-07-29 12:59:36 +02002153 config.retransmission_rate_limiter = &retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08002154 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
2155 rtp_rtcp_->SetRemoteSSRC((*receive_configs)[0].rtp.remote_ssrc);
2156 rtp_rtcp_->SetSSRC((*receive_configs)[0].rtp.local_ssrc);
2157 rtp_rtcp_->SetREMBStatus(true);
stefan32f81542016-01-20 07:13:58 -08002158 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
2159 }
2160
2161 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2162 sender_call_ = sender_call;
2163 }
2164
tommi0f8b4032017-02-22 11:22:05 -08002165 static void BitrateStatsPollingThread(void* obj) {
2166 static_cast<BweObserver*>(obj)->PollStats();
stefan32f81542016-01-20 07:13:58 -08002167 }
2168
tommi0f8b4032017-02-22 11:22:05 -08002169 void PollStats() {
2170 do {
2171 if (sender_call_) {
2172 Call::Stats stats = sender_call_->GetStats();
2173 switch (state_) {
2174 case kWaitForFirstRampUp:
2175 if (stats.send_bandwidth_bps >= remb_bitrate_bps_) {
2176 state_ = kWaitForRemb;
2177 remb_bitrate_bps_ /= 2;
2178 rtp_rtcp_->SetREMBData(
2179 remb_bitrate_bps_,
2180 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
2181 rtp_rtcp_->SendRTCP(kRtcpRr);
2182 }
2183 break;
stefan32f81542016-01-20 07:13:58 -08002184
tommi0f8b4032017-02-22 11:22:05 -08002185 case kWaitForRemb:
2186 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
2187 state_ = kWaitForSecondRampUp;
2188 remb_bitrate_bps_ *= 2;
2189 rtp_rtcp_->SetREMBData(
2190 remb_bitrate_bps_,
2191 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
2192 rtp_rtcp_->SendRTCP(kRtcpRr);
2193 }
2194 break;
stefan32f81542016-01-20 07:13:58 -08002195
tommi0f8b4032017-02-22 11:22:05 -08002196 case kWaitForSecondRampUp:
2197 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
2198 observation_complete_.Set();
2199 }
2200 break;
2201 }
stefan32f81542016-01-20 07:13:58 -08002202 }
tommi0f8b4032017-02-22 11:22:05 -08002203 } while (!stop_event_.Wait(1000));
stefan32f81542016-01-20 07:13:58 -08002204 }
2205
2206 void PerformTest() override {
2207 poller_thread_.Start();
2208 EXPECT_TRUE(Wait())
2209 << "Timed out while waiting for bitrate to change according to REMB.";
Tommi5dd5f5a2017-02-21 14:22:59 +01002210 stop_event_.Set();
stefan32f81542016-01-20 07:13:58 -08002211 poller_thread_.Stop();
2212 }
2213
2214 private:
2215 enum TestState { kWaitForFirstRampUp, kWaitForRemb, kWaitForSecondRampUp };
2216
2217 Call* sender_call_;
2218 Clock* const clock_;
2219 uint32_t sender_ssrc_;
2220 int remb_bitrate_bps_;
kwiberg27f982b2016-03-01 11:52:33 -08002221 std::unique_ptr<RtpRtcp> rtp_rtcp_;
stefan32f81542016-01-20 07:13:58 -08002222 test::PacketTransport* receive_transport_;
Tommi5dd5f5a2017-02-21 14:22:59 +01002223 rtc::Event stop_event_;
stefan32f81542016-01-20 07:13:58 -08002224 rtc::PlatformThread poller_thread_;
2225 TestState state_;
Erik Språng737336d2016-07-29 12:59:36 +02002226 RateLimiter retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08002227 } test;
2228
2229 RunBaseTest(&test);
2230}
2231
philipel3184f8e2017-05-18 08:08:53 -07002232TEST_F(EndToEndTest, StopSendingKeyframeRequestsForInactiveStream) {
2233 class KeyframeRequestObserver : public test::EndToEndTest {
2234 public:
2235 KeyframeRequestObserver() : clock_(Clock::GetRealTimeClock()) {}
2236
2237 void OnVideoStreamsCreated(
2238 VideoSendStream* send_stream,
2239 const std::vector<VideoReceiveStream*>& receive_streams) override {
2240 RTC_DCHECK_EQ(1, receive_streams.size());
2241 send_stream_ = send_stream;
2242 receive_stream_ = receive_streams[0];
2243 }
2244
2245 void PerformTest() override {
2246 bool frame_decoded = false;
2247 int64_t start_time = clock_->TimeInMilliseconds();
2248 while (clock_->TimeInMilliseconds() - start_time <= 5000) {
2249 if (receive_stream_->GetStats().frames_decoded > 0) {
2250 frame_decoded = true;
2251 break;
2252 }
2253 SleepMs(100);
2254 }
2255 ASSERT_TRUE(frame_decoded);
2256 send_stream_->Stop();
2257 SleepMs(10000);
2258 ASSERT_EQ(
2259 1U, receive_stream_->GetStats().rtcp_packet_type_counts.pli_packets);
2260 }
2261
2262 private:
2263 Clock* clock_;
2264 VideoSendStream* send_stream_;
2265 VideoReceiveStream* receive_stream_;
2266 } test;
2267
2268 RunBaseTest(&test);
2269}
2270
philipele828c962017-03-21 03:24:27 -07002271class ProbingTest : public test::EndToEndTest {
2272 public:
2273 explicit ProbingTest(int start_bitrate_bps)
2274 : clock_(Clock::GetRealTimeClock()),
2275 start_bitrate_bps_(start_bitrate_bps),
2276 state_(0),
2277 sender_call_(nullptr) {}
2278
2279 ~ProbingTest() {}
2280
2281 Call::Config GetSenderCallConfig() override {
philipel4fb651d2017-04-10 03:54:05 -07002282 Call::Config config(event_log_.get());
philipele828c962017-03-21 03:24:27 -07002283 config.bitrate_config.start_bitrate_bps = start_bitrate_bps_;
2284 return config;
2285 }
2286
2287 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2288 sender_call_ = sender_call;
2289 }
2290
2291 protected:
2292 Clock* const clock_;
2293 const int start_bitrate_bps_;
2294 int state_;
2295 Call* sender_call_;
2296};
2297
aleloi7057b6b2017-03-29 02:07:33 -07002298TEST_F(EndToEndTest, MAYBE_InitialProbing) {
philipele828c962017-03-21 03:24:27 -07002299 class InitialProbingTest : public ProbingTest {
2300 public:
philipel8a256522017-03-30 05:06:22 -07002301 explicit InitialProbingTest(bool* success)
2302 : ProbingTest(300000), success_(success) {}
philipele828c962017-03-21 03:24:27 -07002303
2304 void PerformTest() override {
2305 int64_t start_time_ms = clock_->TimeInMilliseconds();
2306 do {
philipel8a256522017-03-30 05:06:22 -07002307 if (clock_->TimeInMilliseconds() - start_time_ms > kTimeoutMs)
philipele828c962017-03-21 03:24:27 -07002308 break;
philipele828c962017-03-21 03:24:27 -07002309
2310 Call::Stats stats = sender_call_->GetStats();
2311 // Initial probing is done with a x3 and x6 multiplier of the start
2312 // bitrate, so a x4 multiplier is a high enough threshold.
philipel8a256522017-03-30 05:06:22 -07002313 if (stats.send_bandwidth_bps > 4 * 300000) {
2314 *success_ = true;
philipele828c962017-03-21 03:24:27 -07002315 break;
philipel8a256522017-03-30 05:06:22 -07002316 }
philipele828c962017-03-21 03:24:27 -07002317 } while (!observation_complete_.Wait(20));
2318 }
2319
2320 private:
2321 const int kTimeoutMs = 1000;
philipel8a256522017-03-30 05:06:22 -07002322 bool* const success_;
2323 };
philipele828c962017-03-21 03:24:27 -07002324
philipel8a256522017-03-30 05:06:22 -07002325 bool success;
2326 const int kMaxAttempts = 3;
2327 for (int i = 0; i < kMaxAttempts; ++i) {
2328 InitialProbingTest test(&success);
2329 RunBaseTest(&test);
2330 if (success)
2331 return;
2332 }
2333 RTC_DCHECK(success) << "Failed to perform mid initial probing ("
2334 << kMaxAttempts << " attempts).";
philipele828c962017-03-21 03:24:27 -07002335}
2336
aleloi18703f92017-03-30 04:24:08 -07002337// Fails on Linux MSan: bugs.webrtc.org/7428
2338#if defined(MEMORY_SANITIZER)
2339TEST_F(EndToEndTest, DISABLED_TriggerMidCallProbing) {
2340#else
philipele828c962017-03-21 03:24:27 -07002341TEST_F(EndToEndTest, TriggerMidCallProbing) {
aleloi18703f92017-03-30 04:24:08 -07002342#endif
2343
philipele828c962017-03-21 03:24:27 -07002344 class TriggerMidCallProbingTest : public ProbingTest {
2345 public:
philipel8a256522017-03-30 05:06:22 -07002346 explicit TriggerMidCallProbingTest(bool* success)
2347 : ProbingTest(300000), success_(success) {}
philipele828c962017-03-21 03:24:27 -07002348
2349 void PerformTest() override {
philipel8a256522017-03-30 05:06:22 -07002350 *success_ = false;
philipele828c962017-03-21 03:24:27 -07002351 int64_t start_time_ms = clock_->TimeInMilliseconds();
2352 do {
philipel8a256522017-03-30 05:06:22 -07002353 if (clock_->TimeInMilliseconds() - start_time_ms > kTimeoutMs)
philipele828c962017-03-21 03:24:27 -07002354 break;
philipele828c962017-03-21 03:24:27 -07002355
2356 Call::Stats stats = sender_call_->GetStats();
2357
2358 switch (state_) {
2359 case 0:
2360 if (stats.send_bandwidth_bps > 5 * 300000) {
2361 Call::Config::BitrateConfig bitrate_config;
2362 bitrate_config.max_bitrate_bps = 100000;
2363 sender_call_->SetBitrateConfig(bitrate_config);
2364 ++state_;
2365 }
2366 break;
2367 case 1:
2368 if (stats.send_bandwidth_bps < 110000) {
2369 Call::Config::BitrateConfig bitrate_config;
2370 bitrate_config.max_bitrate_bps = 2500000;
2371 sender_call_->SetBitrateConfig(bitrate_config);
2372 ++state_;
2373 }
2374 break;
2375 case 2:
2376 // During high cpu load the pacer will not be able to pace packets
2377 // at the correct speed, but if we go from 110 to 1250 kbps
2378 // in 5 seconds then it is due to probing.
philipel8a256522017-03-30 05:06:22 -07002379 if (stats.send_bandwidth_bps > 1250000) {
2380 *success_ = true;
philipele828c962017-03-21 03:24:27 -07002381 observation_complete_.Set();
philipel8a256522017-03-30 05:06:22 -07002382 }
philipele828c962017-03-21 03:24:27 -07002383 break;
2384 }
2385 } while (!observation_complete_.Wait(20));
2386 }
2387
2388 private:
2389 const int kTimeoutMs = 5000;
philipel8a256522017-03-30 05:06:22 -07002390 bool* const success_;
2391 };
philipele828c962017-03-21 03:24:27 -07002392
philipel8a256522017-03-30 05:06:22 -07002393 bool success;
2394 const int kMaxAttempts = 3;
2395 for (int i = 0; i < kMaxAttempts; ++i) {
2396 TriggerMidCallProbingTest test(&success);
2397 RunBaseTest(&test);
2398 if (success)
2399 return;
2400 }
2401 RTC_DCHECK(success) << "Failed to perform mid call probing (" << kMaxAttempts
2402 << " attempts).";
philipele828c962017-03-21 03:24:27 -07002403}
2404
philipel277a8b52017-03-16 05:19:49 -07002405TEST_F(EndToEndTest, VerifyNackStats) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002406 static const int kPacketNumberToDrop = 200;
2407 class NackObserver : public test::EndToEndTest {
2408 public:
2409 NackObserver()
2410 : EndToEndTest(kLongTimeoutMs),
2411 sent_rtp_packets_(0),
2412 dropped_rtp_packet_(0),
2413 dropped_rtp_packet_requested_(false),
2414 send_stream_(nullptr),
2415 start_runtime_ms_(-1) {}
2416
2417 private:
2418 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002419 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002420 if (++sent_rtp_packets_ == kPacketNumberToDrop) {
kwiberg27f982b2016-03-01 11:52:33 -08002421 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
Åsa Persson352b2d72015-04-15 18:00:40 +02002422 RTPHeader header;
2423 EXPECT_TRUE(parser->Parse(packet, length, &header));
2424 dropped_rtp_packet_ = header.sequenceNumber;
2425 return DROP_PACKET;
2426 }
2427 VerifyStats();
2428 return SEND_PACKET;
2429 }
2430
2431 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002432 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002433 test::RtcpPacketParser rtcp_parser;
2434 rtcp_parser.Parse(packet, length);
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02002435 const std::vector<uint16_t>& nacks = rtcp_parser.nack()->packet_ids();
Åsa Persson352b2d72015-04-15 18:00:40 +02002436 if (!nacks.empty() && std::find(
2437 nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) {
2438 dropped_rtp_packet_requested_ = true;
2439 }
2440 return SEND_PACKET;
2441 }
2442
stefan608213e2015-11-01 14:56:10 -08002443 void VerifyStats() EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002444 if (!dropped_rtp_packet_requested_)
2445 return;
2446 int send_stream_nack_packets = 0;
2447 int receive_stream_nack_packets = 0;
2448 VideoSendStream::Stats stats = send_stream_->GetStats();
2449 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
2450 stats.substreams.begin(); it != stats.substreams.end(); ++it) {
2451 const VideoSendStream::StreamStats& stream_stats = it->second;
2452 send_stream_nack_packets +=
2453 stream_stats.rtcp_packet_type_counts.nack_packets;
2454 }
2455 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2456 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2457 receive_stream_nack_packets +=
2458 stats.rtcp_packet_type_counts.nack_packets;
2459 }
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002460 if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002461 // NACK packet sent on receive stream and received on sent stream.
2462 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002463 observation_complete_.Set();
Åsa Persson352b2d72015-04-15 18:00:40 +02002464 }
2465 }
2466
2467 bool MinMetricRunTimePassed() {
2468 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2469 if (start_runtime_ms_ == -1) {
2470 start_runtime_ms_ = now;
2471 return false;
2472 }
2473 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2474 return elapsed_sec > metrics::kMinRunTimeInSeconds;
2475 }
2476
stefanff483612015-12-21 03:14:00 -08002477 void ModifyVideoConfigs(
2478 VideoSendStream::Config* send_config,
2479 std::vector<VideoReceiveStream::Config>* receive_configs,
2480 VideoEncoderConfig* encoder_config) override {
Åsa Persson352b2d72015-04-15 18:00:40 +02002481 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2482 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sakal55d932b2016-09-30 06:19:08 -07002483 (*receive_configs)[0].renderer = &fake_renderer_;
Åsa Persson352b2d72015-04-15 18:00:40 +02002484 }
2485
stefanff483612015-12-21 03:14:00 -08002486 void OnVideoStreamsCreated(
Åsa Persson352b2d72015-04-15 18:00:40 +02002487 VideoSendStream* send_stream,
2488 const std::vector<VideoReceiveStream*>& receive_streams) override {
2489 send_stream_ = send_stream;
2490 receive_streams_ = receive_streams;
2491 }
2492
2493 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002494 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson352b2d72015-04-15 18:00:40 +02002495 }
2496
sakal55d932b2016-09-30 06:19:08 -07002497 test::FakeVideoRenderer fake_renderer_;
stefan608213e2015-11-01 14:56:10 -08002498 rtc::CriticalSection crit_;
Åsa Persson352b2d72015-04-15 18:00:40 +02002499 uint64_t sent_rtp_packets_;
stefan608213e2015-11-01 14:56:10 -08002500 uint16_t dropped_rtp_packet_ GUARDED_BY(&crit_);
2501 bool dropped_rtp_packet_requested_ GUARDED_BY(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002502 std::vector<VideoReceiveStream*> receive_streams_;
2503 VideoSendStream* send_stream_;
2504 int64_t start_runtime_ms_;
2505 } test;
2506
asapersson01d70a32016-05-20 06:29:46 -07002507 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002508 RunBaseTest(&test);
Åsa Persson352b2d72015-04-15 18:00:40 +02002509
asapersson01d70a32016-05-20 06:29:46 -07002510 EXPECT_EQ(
2511 1, metrics::NumSamples("WebRTC.Video.UniqueNackRequestsSentInPercent"));
2512 EXPECT_EQ(1, metrics::NumSamples(
2513 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
2514 EXPECT_GT(metrics::MinSample("WebRTC.Video.NackPacketsSentPerMinute"), 0);
Åsa Persson352b2d72015-04-15 18:00:40 +02002515}
2516
sprangb4a1ae52015-12-03 08:10:08 -08002517void EndToEndTest::VerifyHistogramStats(bool use_rtx,
2518 bool use_red,
2519 bool screenshare) {
tommi2e82f382016-06-21 00:26:43 -07002520 class StatsObserver : public test::EndToEndTest,
2521 public rtc::VideoSinkInterface<VideoFrame> {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002522 public:
sprangb4a1ae52015-12-03 08:10:08 -08002523 StatsObserver(bool use_rtx, bool use_red, bool screenshare)
Åsa Persson3c391cb2015-04-27 10:09:49 +02002524 : EndToEndTest(kLongTimeoutMs),
2525 use_rtx_(use_rtx),
2526 use_red_(use_red),
sprangb4a1ae52015-12-03 08:10:08 -08002527 screenshare_(screenshare),
Peter Boström39593972016-02-15 11:27:15 +01002528 // This test uses NACK, so to send FEC we can't use a fake encoder.
magjed509e4fe2016-11-18 01:34:11 -08002529 vp8_encoder_(use_red ? VP8Encoder::Create() : nullptr),
Åsa Persson3c391cb2015-04-27 10:09:49 +02002530 sender_call_(nullptr),
2531 receiver_call_(nullptr),
asapersson1394c7b2016-10-18 11:50:50 -07002532 start_runtime_ms_(-1),
2533 num_frames_received_(0) {}
Åsa Persson3c391cb2015-04-27 10:09:49 +02002534
2535 private:
asapersson1394c7b2016-10-18 11:50:50 -07002536 void OnFrame(const VideoFrame& video_frame) override {
2537 // The RTT is needed to estimate |ntp_time_ms| which is used by
2538 // end-to-end delay stats. Therefore, start counting received frames once
2539 // |ntp_time_ms| is valid.
2540 if (video_frame.ntp_time_ms() > 0 &&
2541 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() >=
2542 video_frame.ntp_time_ms()) {
2543 rtc::CritScope lock(&crit_);
2544 ++num_frames_received_;
2545 }
2546 }
tommi2e82f382016-06-21 00:26:43 -07002547
Åsa Persson3c391cb2015-04-27 10:09:49 +02002548 Action OnSendRtp(const uint8_t* packet, size_t length) override {
asapersson1394c7b2016-10-18 11:50:50 -07002549 if (MinMetricRunTimePassed() && MinNumberOfFramesReceived())
Peter Boström5811a392015-12-10 13:02:50 +01002550 observation_complete_.Set();
Åsa Persson3c391cb2015-04-27 10:09:49 +02002551
stefanf116bd02015-10-27 08:29:42 -07002552 return SEND_PACKET;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002553 }
2554
2555 bool MinMetricRunTimePassed() {
2556 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2557 if (start_runtime_ms_ == -1) {
2558 start_runtime_ms_ = now;
2559 return false;
2560 }
2561 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2562 return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
2563 }
2564
asapersson1394c7b2016-10-18 11:50:50 -07002565 bool MinNumberOfFramesReceived() const {
2566 const int kMinRequiredHistogramSamples = 200;
2567 rtc::CritScope lock(&crit_);
2568 return num_frames_received_ > kMinRequiredHistogramSamples;
2569 }
2570
stefanff483612015-12-21 03:14:00 -08002571 void ModifyVideoConfigs(
2572 VideoSendStream::Config* send_config,
2573 std::vector<VideoReceiveStream::Config>* receive_configs,
2574 VideoEncoderConfig* encoder_config) override {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002575 // NACK
2576 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2577 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
tommi2e82f382016-06-21 00:26:43 -07002578 (*receive_configs)[0].renderer = this;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002579 // FEC
2580 if (use_red_) {
brandtrb5f2c3f2016-10-04 23:28:39 -07002581 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
2582 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
Peter Boström39593972016-02-15 11:27:15 +01002583 send_config->encoder_settings.encoder = vp8_encoder_.get();
2584 send_config->encoder_settings.payload_name = "VP8";
2585 (*receive_configs)[0].decoders[0].payload_name = "VP8";
brandtrb5f2c3f2016-10-04 23:28:39 -07002586 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
2587 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type =
2588 kUlpfecPayloadType;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002589 }
2590 // RTX
2591 if (use_rtx_) {
2592 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
2593 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
brandtr14742122017-01-27 04:53:07 -08002594 (*receive_configs)[0].rtp.rtx_ssrc = kSendRtxSsrcs[0];
2595 (*receive_configs)[0].rtp.rtx_payload_types[kFakeVideoSendPayloadType] =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002596 kSendRtxPayloadType;
2597 }
asapersson1490f7a2016-09-23 02:09:46 -07002598 // RTT needed for RemoteNtpTimeEstimator for the receive stream.
2599 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = true;
sprangb4a1ae52015-12-03 08:10:08 -08002600 encoder_config->content_type =
2601 screenshare_ ? VideoEncoderConfig::ContentType::kScreen
2602 : VideoEncoderConfig::ContentType::kRealtimeVideo;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002603 }
2604
2605 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2606 sender_call_ = sender_call;
2607 receiver_call_ = receiver_call;
2608 }
2609
Åsa Persson3c391cb2015-04-27 10:09:49 +02002610 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002611 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson3c391cb2015-04-27 10:09:49 +02002612 }
2613
asapersson1394c7b2016-10-18 11:50:50 -07002614 rtc::CriticalSection crit_;
sprangb4a1ae52015-12-03 08:10:08 -08002615 const bool use_rtx_;
2616 const bool use_red_;
2617 const bool screenshare_;
kwiberg27f982b2016-03-01 11:52:33 -08002618 const std::unique_ptr<VideoEncoder> vp8_encoder_;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002619 Call* sender_call_;
2620 Call* receiver_call_;
2621 int64_t start_runtime_ms_;
asapersson1394c7b2016-10-18 11:50:50 -07002622 int num_frames_received_ GUARDED_BY(&crit_);
sprangb4a1ae52015-12-03 08:10:08 -08002623 } test(use_rtx, use_red, screenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002624
asapersson01d70a32016-05-20 06:29:46 -07002625 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002626 RunBaseTest(&test);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002627
stefan91d92602015-11-11 10:13:02 -08002628 // Delete the call for Call stats to be reported.
stefan18adf0a2015-11-17 06:24:56 -08002629 sender_call_.reset();
stefan91d92602015-11-11 10:13:02 -08002630 receiver_call_.reset();
2631
sprangb4a1ae52015-12-03 08:10:08 -08002632 std::string video_prefix =
2633 screenshare ? "WebRTC.Video.Screenshare." : "WebRTC.Video.";
2634
Åsa Persson3c391cb2015-04-27 10:09:49 +02002635 // Verify that stats have been updated once.
asapersson4374a092016-07-27 00:39:09 -07002636 EXPECT_EQ(2, metrics::NumSamples("WebRTC.Call.LifetimeInSeconds"));
asapersson01d70a32016-05-20 06:29:46 -07002637 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
2638 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.RtcpBitrateReceivedInBps"));
2639 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.BitrateReceivedInKbps"));
2640 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.EstimatedSendBitrateInKbps"));
2641 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.PacerBitrateInKbps"));
2642
asapersson4374a092016-07-27 00:39:09 -07002643 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
2644 EXPECT_EQ(1,
2645 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
2646
asapersson01d70a32016-05-20 06:29:46 -07002647 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
stefan91d92602015-11-11 10:13:02 -08002648 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002649 metrics::NumSamples(video_prefix + "NackPacketsReceivedPerMinute"));
2650 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
asaperssond89920b2015-07-22 06:52:00 -07002651 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002652 metrics::NumSamples(video_prefix + "FirPacketsReceivedPerMinute"));
2653 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
sprangb4a1ae52015-12-03 08:10:08 -08002654 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002655 metrics::NumSamples(video_prefix + "PliPacketsReceivedPerMinute"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002656
asapersson01d70a32016-05-20 06:29:46 -07002657 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "KeyFramesSentInPermille"));
2658 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
2659
2660 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentPacketsLostInPercent"));
2661 EXPECT_EQ(1,
2662 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
2663
2664 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputWidthInPixels"));
2665 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputHeightInPixels"));
2666 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentWidthInPixels"));
2667 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentHeightInPixels"));
2668 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
2669 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
2670
perkjfa10b552016-10-02 23:45:26 -07002671 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputWidthInPixels",
2672 kDefaultWidth));
2673 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputHeightInPixels",
2674 kDefaultHeight));
2675 EXPECT_EQ(
2676 1, metrics::NumEvents(video_prefix + "SentWidthInPixels", kDefaultWidth));
2677 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "SentHeightInPixels",
2678 kDefaultHeight));
2679 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedWidthInPixels",
2680 kDefaultWidth));
2681 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedHeightInPixels",
2682 kDefaultHeight));
asapersson01d70a32016-05-20 06:29:46 -07002683
2684 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputFramesPerSecond"));
2685 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentFramesPerSecond"));
2686 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
2687 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
2688
2689 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
2690 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
2691 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
2692 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
2693
ilnik00d802b2017-04-11 10:34:31 -07002694 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EndToEndDelayInMs"));
2695 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EndToEndDelayMaxInMs"));
asapersson01d70a32016-05-20 06:29:46 -07002696 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
2697
2698 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EncodeTimeInMs"));
2699 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
2700
asapersson66d4b372016-12-19 06:50:53 -08002701 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "NumberOfPauseEvents"));
2702 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PausedTimeInPercent"));
2703
asapersson01d70a32016-05-20 06:29:46 -07002704 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "BitrateSentInKbps"));
2705 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateReceivedInKbps"));
2706 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "MediaBitrateSentInKbps"));
2707 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateReceivedInKbps"));
2708 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PaddingBitrateSentInKbps"));
2709 EXPECT_EQ(1,
2710 metrics::NumSamples("WebRTC.Video.PaddingBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002711 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002712 1, metrics::NumSamples(video_prefix + "RetransmittedBitrateSentInKbps"));
2713 EXPECT_EQ(1, metrics::NumSamples(
2714 "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002715
asapersson01d70a32016-05-20 06:29:46 -07002716 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendDelayInMs"));
2717 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayInMs"));
2718 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayMaxInMs"));
asapersson6f14be82015-11-16 00:40:49 -08002719
Åsa Persson3c391cb2015-04-27 10:09:49 +02002720 int num_rtx_samples = use_rtx ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002721 EXPECT_EQ(num_rtx_samples,
2722 metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2723 EXPECT_EQ(num_rtx_samples,
2724 metrics::NumSamples("WebRTC.Video.RtxBitrateReceivedInKbps"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002725
2726 int num_red_samples = use_red ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002727 EXPECT_EQ(num_red_samples,
2728 metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2729 EXPECT_EQ(num_red_samples,
2730 metrics::NumSamples("WebRTC.Video.FecBitrateReceivedInKbps"));
2731 EXPECT_EQ(num_red_samples,
2732 metrics::NumSamples("WebRTC.Video.ReceivedFecPacketsInPercent"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002733}
2734
Lu Liufb9e7512017-04-13 14:09:56 -07002735#if defined(WEBRTC_WIN)
2736// Disabled due to flakiness on Windows (bugs.webrtc.org/7483).
2737#define MAYBE_ContentTypeSwitches DISABLED_ContentTypeSwitches
2738#else
2739#define MAYBE_ContentTypeSwitches ContentTypeSwitches
2740#endif
2741TEST_F(EndToEndTest, MAYBE_ContentTypeSwitches) {
ilnik00d802b2017-04-11 10:34:31 -07002742 class StatsObserver : public test::BaseTest,
2743 public rtc::VideoSinkInterface<VideoFrame> {
2744 public:
2745 StatsObserver() : BaseTest(kLongTimeoutMs), num_frames_received_(0) {}
2746
2747 bool ShouldCreateReceivers() const override { return true; }
2748
2749 void OnFrame(const VideoFrame& video_frame) override {
2750 // The RTT is needed to estimate |ntp_time_ms| which is used by
2751 // end-to-end delay stats. Therefore, start counting received frames once
2752 // |ntp_time_ms| is valid.
2753 if (video_frame.ntp_time_ms() > 0 &&
2754 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() >=
2755 video_frame.ntp_time_ms()) {
2756 rtc::CritScope lock(&crit_);
2757 ++num_frames_received_;
2758 }
2759 }
2760
2761 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2762 if (MinNumberOfFramesReceived())
2763 observation_complete_.Set();
2764 return SEND_PACKET;
2765 }
2766
2767 bool MinNumberOfFramesReceived() const {
ilnikf6f808f2017-04-18 09:17:53 -07002768 // Have some room for frames with wrong content type during switch.
2769 const int kMinRequiredHistogramSamples = 200+50;
ilnik00d802b2017-04-11 10:34:31 -07002770 rtc::CritScope lock(&crit_);
2771 return num_frames_received_ > kMinRequiredHistogramSamples;
2772 }
2773
2774 // May be called several times.
2775 void PerformTest() override {
2776 EXPECT_TRUE(Wait()) << "Timed out waiting for enough packets.";
2777 // Reset frame counter so next PerformTest() call will do something.
2778 {
2779 rtc::CritScope lock(&crit_);
2780 num_frames_received_ = 0;
2781 }
2782 }
2783
2784 rtc::CriticalSection crit_;
2785 int num_frames_received_ GUARDED_BY(&crit_);
2786 } test;
2787
2788 metrics::Reset();
2789
2790 Call::Config send_config(test.GetSenderCallConfig());
2791 CreateSenderCall(send_config);
2792 Call::Config recv_config(test.GetReceiverCallConfig());
2793 CreateReceiverCall(recv_config);
2794 receive_transport_.reset(test.CreateReceiveTransport());
2795 send_transport_.reset(test.CreateSendTransport(sender_call_.get()));
2796 send_transport_->SetReceiver(receiver_call_->Receiver());
2797 receive_transport_->SetReceiver(sender_call_->Receiver());
2798 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
2799 CreateSendConfig(1, 0, 0, send_transport_.get());
2800 CreateMatchingReceiveConfigs(receive_transport_.get());
2801
2802 // Modify send and receive configs.
2803 video_send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2804 video_receive_configs_[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2805 video_receive_configs_[0].renderer = &test;
2806 // RTT needed for RemoteNtpTimeEstimator for the receive stream.
2807 video_receive_configs_[0].rtp.rtcp_xr.receiver_reference_time_report = true;
2808 // Start with realtime video.
2809 video_encoder_config_.content_type =
2810 VideoEncoderConfig::ContentType::kRealtimeVideo;
2811 // Second encoder config for the second part of the test uses screenshare
2812 VideoEncoderConfig encoder_config_with_screenshare_ =
2813 video_encoder_config_.Copy();
2814 encoder_config_with_screenshare_.content_type =
2815 VideoEncoderConfig::ContentType::kScreen;
2816
2817 CreateVideoStreams();
2818 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
2819 kDefaultHeight);
2820 Start();
2821
2822 test.PerformTest();
2823
2824 // Replace old send stream.
2825 sender_call_->DestroyVideoSendStream(video_send_stream_);
2826 video_send_stream_ = sender_call_->CreateVideoSendStream(
2827 video_send_config_.Copy(), encoder_config_with_screenshare_.Copy());
2828 video_send_stream_->SetSource(
2829 frame_generator_capturer_.get(),
2830 VideoSendStream::DegradationPreference::kBalanced);
2831 video_send_stream_->Start();
2832
2833 // Continue to run test but now with screenshare.
2834 test.PerformTest();
2835
2836 send_transport_->StopSending();
2837 receive_transport_->StopSending();
2838 Stop();
2839 DestroyStreams();
2840 DestroyCalls();
2841 // Delete the call for Call stats to be reported.
2842 sender_call_.reset();
2843 receiver_call_.reset();
2844
2845 // Verify that stats have been updated for both screenshare and video.
2846 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.EndToEndDelayInMs"));
2847 EXPECT_EQ(1,
2848 metrics::NumSamples("WebRTC.Video.Screenshare.EndToEndDelayInMs"));
2849 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.EndToEndDelayMaxInMs"));
2850 EXPECT_EQ(
2851 1, metrics::NumSamples("WebRTC.Video.Screenshare.EndToEndDelayMaxInMs"));
2852}
2853
philipel277a8b52017-03-16 05:19:49 -07002854TEST_F(EndToEndTest, VerifyHistogramStatsWithRtx) {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002855 const bool kEnabledRtx = true;
2856 const bool kEnabledRed = false;
sprangb4a1ae52015-12-03 08:10:08 -08002857 const bool kScreenshare = false;
2858 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002859}
2860
philipel277a8b52017-03-16 05:19:49 -07002861TEST_F(EndToEndTest, VerifyHistogramStatsWithRed) {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002862 const bool kEnabledRtx = false;
2863 const bool kEnabledRed = true;
sprangb4a1ae52015-12-03 08:10:08 -08002864 const bool kScreenshare = false;
2865 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
2866}
2867
philipel277a8b52017-03-16 05:19:49 -07002868TEST_F(EndToEndTest, VerifyHistogramStatsWithScreenshare) {
sprangb4a1ae52015-12-03 08:10:08 -08002869 const bool kEnabledRtx = false;
2870 const bool kEnabledRed = false;
2871 const bool kScreenshare = true;
2872 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002873}
2874
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002875void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
2876 bool send_single_ssrc_first) {
2877 class SendsSetSsrcs : public test::EndToEndTest {
2878 public:
2879 SendsSetSsrcs(const uint32_t* ssrcs,
2880 size_t num_ssrcs,
2881 bool send_single_ssrc_first)
2882 : EndToEndTest(kDefaultTimeoutMs),
2883 num_ssrcs_(num_ssrcs),
2884 send_single_ssrc_first_(send_single_ssrc_first),
2885 ssrcs_to_observe_(num_ssrcs),
sprang867fb522015-08-03 04:38:41 -07002886 expect_single_ssrc_(send_single_ssrc_first),
2887 send_stream_(nullptr) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002888 for (size_t i = 0; i < num_ssrcs; ++i)
2889 valid_ssrcs_[ssrcs[i]] = true;
2890 }
2891
2892 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002893 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002894 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002895 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002896
2897 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
2898 << "Received unknown SSRC: " << header.ssrc;
2899
2900 if (!valid_ssrcs_[header.ssrc])
Peter Boström5811a392015-12-10 13:02:50 +01002901 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002902
2903 if (!is_observed_[header.ssrc]) {
2904 is_observed_[header.ssrc] = true;
2905 --ssrcs_to_observe_;
2906 if (expect_single_ssrc_) {
2907 expect_single_ssrc_ = false;
Peter Boström5811a392015-12-10 13:02:50 +01002908 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002909 }
2910 }
2911
2912 if (ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002913 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002914
2915 return SEND_PACKET;
2916 }
2917
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002918 size_t GetNumVideoStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002919
perkjfa10b552016-10-02 23:45:26 -07002920 // This test use other VideoStream settings than the the default settings
2921 // implemented in DefaultVideoStreamFactory. Therefore this test implement
2922 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
2923 // in ModifyVideoConfigs.
2924 class VideoStreamFactory
2925 : public VideoEncoderConfig::VideoStreamFactoryInterface {
2926 public:
2927 VideoStreamFactory() {}
2928
2929 private:
2930 std::vector<VideoStream> CreateEncoderStreams(
2931 int width,
2932 int height,
2933 const VideoEncoderConfig& encoder_config) override {
2934 std::vector<VideoStream> streams =
2935 test::CreateVideoStreams(width, height, encoder_config);
2936 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
2937 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
2938 streams[i].min_bitrate_bps = 10000;
2939 streams[i].target_bitrate_bps = 15000;
2940 streams[i].max_bitrate_bps = 20000;
2941 }
2942 return streams;
2943 }
2944 };
2945
stefanff483612015-12-21 03:14:00 -08002946 void ModifyVideoConfigs(
2947 VideoSendStream::Config* send_config,
2948 std::vector<VideoReceiveStream::Config>* receive_configs,
2949 VideoEncoderConfig* encoder_config) override {
perkjfa10b552016-10-02 23:45:26 -07002950 encoder_config->video_stream_factory =
2951 new rtc::RefCountedObject<VideoStreamFactory>();
perkj26091b12016-09-01 01:17:40 -07002952 video_encoder_config_all_streams_ = encoder_config->Copy();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002953 if (send_single_ssrc_first_)
perkjfa10b552016-10-02 23:45:26 -07002954 encoder_config->number_of_streams = 1;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002955 }
2956
stefanff483612015-12-21 03:14:00 -08002957 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002958 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002959 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002960 send_stream_ = send_stream;
2961 }
2962
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002963 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002964 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2965 << (send_single_ssrc_first_ ? "first SSRC."
2966 : "SSRCs.");
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002967
2968 if (send_single_ssrc_first_) {
2969 // Set full simulcast and continue with the rest of the SSRCs.
stefanff483612015-12-21 03:14:00 -08002970 send_stream_->ReconfigureVideoEncoder(
perkj26091b12016-09-01 01:17:40 -07002971 std::move(video_encoder_config_all_streams_));
Peter Boström5811a392015-12-10 13:02:50 +01002972 EXPECT_TRUE(Wait()) << "Timed out while waiting on additional SSRCs.";
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002973 }
2974 }
2975
2976 private:
2977 std::map<uint32_t, bool> valid_ssrcs_;
2978 std::map<uint32_t, bool> is_observed_;
2979
2980 const size_t num_ssrcs_;
2981 const bool send_single_ssrc_first_;
2982
2983 size_t ssrcs_to_observe_;
2984 bool expect_single_ssrc_;
2985
2986 VideoSendStream* send_stream_;
stefanff483612015-12-21 03:14:00 -08002987 VideoEncoderConfig video_encoder_config_all_streams_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002988 } test(kVideoSendSsrcs, num_ssrcs, send_single_ssrc_first);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002989
stefane74eef12016-01-08 06:47:13 -08002990 RunBaseTest(&test);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002991}
2992
philipel277a8b52017-03-16 05:19:49 -07002993TEST_F(EndToEndTest, ReportsSetEncoderRates) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002994 class EncoderRateStatsTest : public test::EndToEndTest,
2995 public test::FakeEncoder {
2996 public:
2997 EncoderRateStatsTest()
2998 : EndToEndTest(kDefaultTimeoutMs),
sprang867fb522015-08-03 04:38:41 -07002999 FakeEncoder(Clock::GetRealTimeClock()),
3000 send_stream_(nullptr),
3001 bitrate_kbps_(0) {}
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003002
stefanff483612015-12-21 03:14:00 -08003003 void OnVideoStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003004 VideoSendStream* send_stream,
3005 const std::vector<VideoReceiveStream*>& receive_streams) override {
3006 send_stream_ = send_stream;
3007 }
3008
stefanff483612015-12-21 03:14:00 -08003009 void ModifyVideoConfigs(
3010 VideoSendStream::Config* send_config,
3011 std::vector<VideoReceiveStream::Config>* receive_configs,
3012 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003013 send_config->encoder_settings.encoder = this;
kwibergaf476c72016-11-28 15:21:39 -08003014 RTC_DCHECK_EQ(1, encoder_config->number_of_streams);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003015 }
3016
Erik Språng08127a92016-11-16 16:41:30 +01003017 int32_t SetRateAllocation(const BitrateAllocation& rate_allocation,
3018 uint32_t framerate) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003019 // Make sure not to trigger on any default zero bitrates.
Erik Språng08127a92016-11-16 16:41:30 +01003020 if (rate_allocation.get_sum_bps() == 0)
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003021 return 0;
Peter Boströmf2f82832015-05-01 13:00:41 +02003022 rtc::CritScope lock(&crit_);
Erik Språng08127a92016-11-16 16:41:30 +01003023 bitrate_kbps_ = rate_allocation.get_sum_kbps();
Peter Boström5811a392015-12-10 13:02:50 +01003024 observation_complete_.Set();
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003025 return 0;
3026 }
3027
3028 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003029 ASSERT_TRUE(Wait())
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003030 << "Timed out while waiting for encoder SetRates() call.";
perkjf5b2e512016-07-05 08:34:04 -07003031 WaitForEncoderTargetBitrateMatchStats();
3032 send_stream_->Stop();
3033 WaitForStatsReportZeroTargetBitrate();
3034 send_stream_->Start();
3035 WaitForEncoderTargetBitrateMatchStats();
3036 }
3037
3038 void WaitForEncoderTargetBitrateMatchStats() {
Peter Boström5811a392015-12-10 13:02:50 +01003039 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003040 VideoSendStream::Stats stats = send_stream_->GetStats();
3041 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003042 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003043 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
3044 static_cast<int>(bitrate_kbps_)) {
3045 return;
3046 }
3047 }
3048 SleepMs(1);
3049 }
3050 FAIL()
3051 << "Timed out waiting for stats reporting the currently set bitrate.";
3052 }
3053
perkjf5b2e512016-07-05 08:34:04 -07003054 void WaitForStatsReportZeroTargetBitrate() {
3055 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
3056 if (send_stream_->GetStats().target_media_bitrate_bps == 0) {
3057 return;
3058 }
3059 SleepMs(1);
3060 }
3061 FAIL() << "Timed out waiting for stats reporting zero bitrate.";
3062 }
3063
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003064 private:
stefanf116bd02015-10-27 08:29:42 -07003065 rtc::CriticalSection crit_;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003066 VideoSendStream* send_stream_;
3067 uint32_t bitrate_kbps_ GUARDED_BY(crit_);
3068 } test;
3069
stefane74eef12016-01-08 06:47:13 -08003070 RunBaseTest(&test);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003071}
3072
philipel277a8b52017-03-16 05:19:49 -07003073TEST_F(EndToEndTest, GetStats) {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00003074 static const int kStartBitrateBps = 3000000;
Peter Boströmdef398832015-05-27 17:59:11 +02003075 static const int kExpectedRenderDelayMs = 20;
tommi2e82f382016-06-21 00:26:43 -07003076
3077 class ReceiveStreamRenderer : public rtc::VideoSinkInterface<VideoFrame> {
3078 public:
3079 ReceiveStreamRenderer() {}
3080
3081 private:
3082 void OnFrame(const VideoFrame& video_frame) override {}
3083 };
3084
nissed30a1112016-04-18 05:15:22 -07003085 class StatsObserver : public test::EndToEndTest,
3086 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003087 public:
stefanf116bd02015-10-27 08:29:42 -07003088 StatsObserver()
3089 : EndToEndTest(kLongTimeoutMs),
Peter Boströmc6e16e32016-02-05 14:15:53 +01003090 encoder_(Clock::GetRealTimeClock(), 10),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00003091 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003092 expected_send_ssrcs_(),
Peter Boström5811a392015-12-10 13:02:50 +01003093 check_stats_event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003094
3095 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003096 Action OnSendRtp(const uint8_t* packet, size_t length) override {
sprangcd349d92016-07-13 09:11:28 -07003097 // Drop every 25th packet => 4% loss.
3098 static const int kPacketLossFrac = 25;
3099 RTPHeader header;
3100 RtpUtility::RtpHeaderParser parser(packet, length);
3101 if (parser.Parse(&header) &&
3102 expected_send_ssrcs_.find(header.ssrc) !=
3103 expected_send_ssrcs_.end() &&
3104 header.sequenceNumber % kPacketLossFrac == 0) {
3105 return DROP_PACKET;
3106 }
Peter Boström5811a392015-12-10 13:02:50 +01003107 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003108 return SEND_PACKET;
3109 }
3110
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003111 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01003112 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003113 return SEND_PACKET;
3114 }
3115
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003116 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01003117 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003118 return SEND_PACKET;
3119 }
3120
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003121 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01003122 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003123 return SEND_PACKET;
3124 }
3125
nissed30a1112016-04-18 05:15:22 -07003126 void OnFrame(const VideoFrame& video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003127 // Ensure that we have at least 5ms send side delay.
nissed30a1112016-04-18 05:15:22 -07003128 SleepMs(5);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003129 }
3130
3131 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003132 for (size_t i = 0; i < receive_streams_.size(); ++i) {
3133 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
3134 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003135
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003136 // Make sure all fields have been populated.
3137 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
3138 // always filled for all receivers.
3139 receive_stats_filled_["IncomingRate"] |=
3140 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003141
Peter Boströmb7d9a972015-12-18 16:01:11 +01003142 send_stats_filled_["DecoderImplementationName"] |=
3143 stats.decoder_implementation_name ==
3144 test::FakeDecoder::kImplementationName;
Peter Boströmdef398832015-05-27 17:59:11 +02003145 receive_stats_filled_["RenderDelayAsHighAsExpected"] |=
3146 stats.render_delay_ms >= kExpectedRenderDelayMs;
3147
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003148 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003149
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003150 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003151
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003152 receive_stats_filled_["StatisticsUpdated"] |=
3153 stats.rtcp_stats.cumulative_lost != 0 ||
3154 stats.rtcp_stats.extended_max_sequence_number != 0 ||
3155 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003156
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003157 receive_stats_filled_["DataCountersUpdated"] |=
3158 stats.rtp_stats.transmitted.payload_bytes != 0 ||
3159 stats.rtp_stats.fec.packets != 0 ||
3160 stats.rtp_stats.transmitted.header_bytes != 0 ||
3161 stats.rtp_stats.transmitted.packets != 0 ||
3162 stats.rtp_stats.transmitted.padding_bytes != 0 ||
3163 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003164
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003165 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003166 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003167
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003168 receive_stats_filled_["FrameCounts"] |=
3169 stats.frame_counts.key_frames != 0 ||
3170 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00003171
pbosbb36fdf2015-07-09 07:48:14 -07003172 receive_stats_filled_["CName"] |= !stats.c_name.empty();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00003173
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003174 receive_stats_filled_["RtcpPacketTypeCount"] |=
3175 stats.rtcp_packet_type_counts.fir_packets != 0 ||
3176 stats.rtcp_packet_type_counts.nack_packets != 0 ||
3177 stats.rtcp_packet_type_counts.pli_packets != 0 ||
3178 stats.rtcp_packet_type_counts.nack_requests != 0 ||
3179 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbosf42376c2015-08-28 07:35:32 -07003180
3181 assert(stats.current_payload_type == -1 ||
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003182 stats.current_payload_type == kFakeVideoSendPayloadType);
pbosf42376c2015-08-28 07:35:32 -07003183 receive_stats_filled_["IncomingPayloadType"] |=
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003184 stats.current_payload_type == kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003185 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003186
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003187 return AllStatsFilled(receive_stats_filled_);
3188 }
3189
3190 bool CheckSendStats() {
Peter Boström74f6e9e2016-04-04 17:56:10 +02003191 RTC_DCHECK(send_stream_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003192 VideoSendStream::Stats stats = send_stream_->GetStats();
3193
philipel20d05a92016-12-19 04:17:27 -08003194 size_t expected_num_streams = kNumSsrcs + expected_send_ssrcs_.size();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003195 send_stats_filled_["NumStreams"] |=
philipel20d05a92016-12-19 04:17:27 -08003196 stats.substreams.size() == expected_num_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003197
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00003198 send_stats_filled_["CpuOveruseMetrics"] |=
Peter Boströme4499152016-02-05 11:13:28 +01003199 stats.avg_encode_time_ms != 0 && stats.encode_usage_percent != 0;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00003200
Peter Boströmb7d9a972015-12-18 16:01:11 +01003201 send_stats_filled_["EncoderImplementationName"] |=
3202 stats.encoder_implementation_name ==
3203 test::FakeEncoder::kImplementationName;
3204
Pera48ddb72016-09-29 11:48:50 +02003205 send_stats_filled_["EncoderPreferredBitrate"] |=
3206 stats.preferred_media_bitrate_bps > 0;
3207
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003208 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003209 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003210 it != stats.substreams.end(); ++it) {
sprangcd349d92016-07-13 09:11:28 -07003211 if (expected_send_ssrcs_.find(it->first) == expected_send_ssrcs_.end())
3212 continue; // Probably RTX.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003213
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003214 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003215 stats.input_frame_rate != 0;
3216
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003217 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003218
3219 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
3220 stream_stats.rtcp_stats.cumulative_lost != 0 ||
3221 stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
3222 stream_stats.rtcp_stats.fraction_lost != 0;
3223
3224 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00003225 stream_stats.rtp_stats.fec.packets != 0 ||
3226 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
3227 stream_stats.rtp_stats.retransmitted.packets != 0 ||
3228 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003229
sprangcd349d92016-07-13 09:11:28 -07003230 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Total",
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003231 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00003232 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003233
sprangcd349d92016-07-13 09:11:28 -07003234 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Retransmit",
3235 it->first)] |=
3236 stream_stats.retransmit_bitrate_bps != 0;
3237
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003238 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00003239 stream_stats.frame_counts.delta_frames != 0 ||
3240 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003241
3242 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
3243 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00003244
3245 send_stats_filled_[CompoundKey("Delay", it->first)] |=
3246 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003247
3248 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
3249 // report dropped packets.
3250 send_stats_filled_["RtcpPacketTypeCount"] |=
3251 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
3252 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
3253 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
3254 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
3255 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003256 }
3257
3258 return AllStatsFilled(send_stats_filled_);
3259 }
3260
3261 std::string CompoundKey(const char* name, uint32_t ssrc) {
3262 std::ostringstream oss;
3263 oss << name << "_" << ssrc;
3264 return oss.str();
3265 }
3266
3267 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
sprangcd349d92016-07-13 09:11:28 -07003268 for (const auto& stat : stats_map) {
3269 if (!stat.second)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003270 return false;
3271 }
3272 return true;
3273 }
3274
stefane74eef12016-01-08 06:47:13 -08003275 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
3276 FakeNetworkPipe::Config network_config;
3277 network_config.loss_percent = 5;
minyue20c84cc2017-04-10 16:57:57 -07003278 return new test::PacketTransport(sender_call, this,
3279 test::PacketTransport::kSender,
3280 payload_type_map_, network_config);
stefane74eef12016-01-08 06:47:13 -08003281 }
3282
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003283 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00003284 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01003285 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00003286 return config;
3287 }
3288
perkjfa10b552016-10-02 23:45:26 -07003289 // This test use other VideoStream settings than the the default settings
3290 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3291 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3292 // in ModifyVideoConfigs.
3293 class VideoStreamFactory
3294 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3295 public:
3296 VideoStreamFactory() {}
3297
3298 private:
3299 std::vector<VideoStream> CreateEncoderStreams(
3300 int width,
3301 int height,
3302 const VideoEncoderConfig& encoder_config) override {
3303 std::vector<VideoStream> streams =
3304 test::CreateVideoStreams(width, height, encoder_config);
3305 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
3306 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3307 streams[i].min_bitrate_bps = 10000;
3308 streams[i].target_bitrate_bps = 15000;
3309 streams[i].max_bitrate_bps = 20000;
3310 }
3311 return streams;
3312 }
3313 };
3314
stefanff483612015-12-21 03:14:00 -08003315 void ModifyVideoConfigs(
3316 VideoSendStream::Config* send_config,
3317 std::vector<VideoReceiveStream::Config>* receive_configs,
3318 VideoEncoderConfig* encoder_config) override {
perkjfa10b552016-10-02 23:45:26 -07003319 encoder_config->video_stream_factory =
3320 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003321 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003322 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003323
sprangcd349d92016-07-13 09:11:28 -07003324 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
3325 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
3326
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003327 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003328 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003329 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003330 expected_receive_ssrcs_.push_back(
3331 (*receive_configs)[i].rtp.remote_ssrc);
Peter Boströmdef398832015-05-27 17:59:11 +02003332 (*receive_configs)[i].render_delay_ms = kExpectedRenderDelayMs;
tommi2e82f382016-06-21 00:26:43 -07003333 (*receive_configs)[i].renderer = &receive_stream_renderer_;
sprangcd349d92016-07-13 09:11:28 -07003334 (*receive_configs)[i].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
3335
brandtr14742122017-01-27 04:53:07 -08003336 (*receive_configs)[i].rtp.rtx_ssrc = kSendRtxSsrcs[i];
3337 (*receive_configs)[i].rtp.rtx_payload_types[kFakeVideoSendPayloadType] =
sprangcd349d92016-07-13 09:11:28 -07003338 kSendRtxPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003339 }
sprangcd349d92016-07-13 09:11:28 -07003340
3341 for (size_t i = 0; i < kNumSsrcs; ++i)
3342 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
3343
Peter Boströmc6e16e32016-02-05 14:15:53 +01003344 // Use a delayed encoder to make sure we see CpuOveruseMetrics stats that
3345 // are non-zero.
3346 send_config->encoder_settings.encoder = &encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003347 }
3348
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003349 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00003350
stefanff483612015-12-21 03:14:00 -08003351 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003352 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003353 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003354 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003355 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003356 }
3357
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003358 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003359 Clock* clock = Clock::GetRealTimeClock();
3360 int64_t now = clock->TimeInMilliseconds();
3361 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
3362 bool receive_ok = false;
3363 bool send_ok = false;
3364
3365 while (now < stop_time) {
3366 if (!receive_ok)
3367 receive_ok = CheckReceiveStats();
3368 if (!send_ok)
3369 send_ok = CheckSendStats();
3370
3371 if (receive_ok && send_ok)
3372 return;
3373
3374 int64_t time_until_timout_ = stop_time - now;
3375 if (time_until_timout_ > 0)
Peter Boström5811a392015-12-10 13:02:50 +01003376 check_stats_event_.Wait(time_until_timout_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003377 now = clock->TimeInMilliseconds();
3378 }
3379
3380 ADD_FAILURE() << "Timed out waiting for filled stats.";
3381 for (std::map<std::string, bool>::const_iterator it =
3382 receive_stats_filled_.begin();
3383 it != receive_stats_filled_.end();
3384 ++it) {
3385 if (!it->second) {
3386 ADD_FAILURE() << "Missing receive stats: " << it->first;
3387 }
3388 }
3389
3390 for (std::map<std::string, bool>::const_iterator it =
3391 send_stats_filled_.begin();
3392 it != send_stats_filled_.end();
3393 ++it) {
3394 if (!it->second) {
3395 ADD_FAILURE() << "Missing send stats: " << it->first;
3396 }
3397 }
3398 }
3399
Peter Boströmc6e16e32016-02-05 14:15:53 +01003400 test::DelayedEncoder encoder_;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003401 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003402 std::map<std::string, bool> receive_stats_filled_;
3403
3404 VideoSendStream* send_stream_;
3405 std::map<std::string, bool> send_stats_filled_;
3406
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003407 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003408 std::set<uint32_t> expected_send_ssrcs_;
3409 std::string expected_cname_;
3410
Peter Boström5811a392015-12-10 13:02:50 +01003411 rtc::Event check_stats_event_;
tommi2e82f382016-06-21 00:26:43 -07003412 ReceiveStreamRenderer receive_stream_renderer_;
stefanf116bd02015-10-27 08:29:42 -07003413 } test;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003414
stefane74eef12016-01-08 06:47:13 -08003415 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003416}
3417
sprang1a646ee2016-12-01 06:34:11 -08003418class RtcpXrObserver : public test::EndToEndTest {
3419 public:
sprang44b3ef62017-01-13 07:30:25 -08003420 RtcpXrObserver(bool enable_rrtr, bool enable_target_bitrate)
sprang1a646ee2016-12-01 06:34:11 -08003421 : EndToEndTest(test::CallTest::kDefaultTimeoutMs),
3422 enable_rrtr_(enable_rrtr),
sprang44b3ef62017-01-13 07:30:25 -08003423 enable_target_bitrate_(enable_target_bitrate),
sprang1a646ee2016-12-01 06:34:11 -08003424 sent_rtcp_sr_(0),
3425 sent_rtcp_rr_(0),
3426 sent_rtcp_rrtr_(0),
3427 sent_rtcp_target_bitrate_(false),
3428 sent_rtcp_dlrr_(0) {}
3429
3430 private:
3431 // Receive stream should send RR packets (and RRTR packets if enabled).
3432 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
3433 rtc::CritScope lock(&crit_);
3434 test::RtcpPacketParser parser;
3435 EXPECT_TRUE(parser.Parse(packet, length));
3436
3437 sent_rtcp_rr_ += parser.receiver_report()->num_packets();
3438 EXPECT_EQ(0, parser.sender_report()->num_packets());
3439 EXPECT_GE(1, parser.xr()->num_packets());
3440 if (parser.xr()->num_packets() > 0) {
3441 if (parser.xr()->rrtr())
3442 ++sent_rtcp_rrtr_;
3443 EXPECT_FALSE(parser.xr()->dlrr());
3444 }
3445
3446 return SEND_PACKET;
3447 }
3448 // Send stream should send SR packets (and DLRR packets if enabled).
3449 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
3450 rtc::CritScope lock(&crit_);
3451 test::RtcpPacketParser parser;
3452 EXPECT_TRUE(parser.Parse(packet, length));
3453
3454 sent_rtcp_sr_ += parser.sender_report()->num_packets();
3455 EXPECT_LE(parser.xr()->num_packets(), 1);
3456 if (parser.xr()->num_packets() > 0) {
3457 EXPECT_FALSE(parser.xr()->rrtr());
3458 if (parser.xr()->dlrr())
3459 ++sent_rtcp_dlrr_;
3460 if (parser.xr()->target_bitrate())
3461 sent_rtcp_target_bitrate_ = true;
3462 }
3463
3464 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
3465 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve &&
sprang44b3ef62017-01-13 07:30:25 -08003466 (sent_rtcp_target_bitrate_ || !enable_target_bitrate_)) {
sprang1a646ee2016-12-01 06:34:11 -08003467 if (enable_rrtr_) {
3468 EXPECT_GT(sent_rtcp_rrtr_, 0);
3469 EXPECT_GT(sent_rtcp_dlrr_, 0);
3470 } else {
3471 EXPECT_EQ(sent_rtcp_rrtr_, 0);
3472 EXPECT_EQ(sent_rtcp_dlrr_, 0);
3473 }
sprang44b3ef62017-01-13 07:30:25 -08003474 EXPECT_EQ(enable_target_bitrate_, sent_rtcp_target_bitrate_);
sprang1a646ee2016-12-01 06:34:11 -08003475 observation_complete_.Set();
3476 }
3477 return SEND_PACKET;
3478 }
3479
3480 void ModifyVideoConfigs(
3481 VideoSendStream::Config* send_config,
3482 std::vector<VideoReceiveStream::Config>* receive_configs,
3483 VideoEncoderConfig* encoder_config) override {
sprang44b3ef62017-01-13 07:30:25 -08003484 if (enable_target_bitrate_) {
3485 // TargetBitrate only signaled for screensharing.
3486 encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
3487 }
sprang1a646ee2016-12-01 06:34:11 -08003488 (*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
3489 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
3490 enable_rrtr_;
3491 }
3492
3493 void PerformTest() override {
3494 EXPECT_TRUE(Wait())
3495 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
3496 }
3497
3498 static const int kNumRtcpReportPacketsToObserve = 5;
3499
3500 rtc::CriticalSection crit_;
sprang44b3ef62017-01-13 07:30:25 -08003501 const bool enable_rrtr_;
3502 const bool enable_target_bitrate_;
sprang1a646ee2016-12-01 06:34:11 -08003503 int sent_rtcp_sr_;
3504 int sent_rtcp_rr_ GUARDED_BY(&crit_);
3505 int sent_rtcp_rrtr_ GUARDED_BY(&crit_);
3506 bool sent_rtcp_target_bitrate_ GUARDED_BY(&crit_);
3507 int sent_rtcp_dlrr_;
3508};
3509
philipel277a8b52017-03-16 05:19:49 -07003510TEST_F(EndToEndTest, TestExtendedReportsWithRrtrWithoutTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003511 RtcpXrObserver test(true, false);
sprang1a646ee2016-12-01 06:34:11 -08003512 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003513}
3514
philipel277a8b52017-03-16 05:19:49 -07003515TEST_F(EndToEndTest, TestExtendedReportsWithoutRrtrWithoutTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003516 RtcpXrObserver test(false, false);
3517 RunBaseTest(&test);
3518}
3519
philipel277a8b52017-03-16 05:19:49 -07003520TEST_F(EndToEndTest, TestExtendedReportsWithRrtrWithTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003521 RtcpXrObserver test(true, true);
3522 RunBaseTest(&test);
3523}
3524
philipel277a8b52017-03-16 05:19:49 -07003525TEST_F(EndToEndTest, TestExtendedReportsWithoutRrtrWithTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003526 RtcpXrObserver test(false, true);
sprang1a646ee2016-12-01 06:34:11 -08003527 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003528}
3529
philipel277a8b52017-03-16 05:19:49 -07003530TEST_F(EndToEndTest, TestReceivedRtpPacketStats) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003531 static const size_t kNumRtpPacketsToSend = 5;
3532 class ReceivedRtpStatsObserver : public test::EndToEndTest {
3533 public:
3534 ReceivedRtpStatsObserver()
3535 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00003536 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003537 sent_rtp_(0) {}
3538
3539 private:
stefanff483612015-12-21 03:14:00 -08003540 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003541 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003542 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003543 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003544 }
3545
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003546 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003547 if (sent_rtp_ >= kNumRtpPacketsToSend) {
3548 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00003549 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
Peter Boström5811a392015-12-10 13:02:50 +01003550 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003551 }
3552 return DROP_PACKET;
3553 }
3554 ++sent_rtp_;
3555 return SEND_PACKET;
3556 }
3557
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003558 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003559 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003560 << "Timed out while verifying number of received RTP packets.";
3561 }
3562
3563 VideoReceiveStream* receive_stream_;
3564 uint32_t sent_rtp_;
3565 } test;
3566
stefane74eef12016-01-08 06:47:13 -08003567 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003568}
3569
philipel277a8b52017-03-16 05:19:49 -07003570TEST_F(EndToEndTest, SendsSetSsrc) {
philipel266f0a42016-11-28 08:49:07 -08003571 TestSendsSetSsrcs(1, false);
3572}
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003573
philipel277a8b52017-03-16 05:19:49 -07003574TEST_F(EndToEndTest, SendsSetSimulcastSsrcs) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003575 TestSendsSetSsrcs(kNumSsrcs, false);
3576}
3577
philipel277a8b52017-03-16 05:19:49 -07003578TEST_F(EndToEndTest, CanSwitchToUseAllSsrcs) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003579 TestSendsSetSsrcs(kNumSsrcs, true);
3580}
3581
philipel277a8b52017-03-16 05:19:49 -07003582TEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003583 class ObserveRedundantPayloads: public test::EndToEndTest {
3584 public:
3585 ObserveRedundantPayloads()
3586 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003587 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003588 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
3589 }
3590 }
3591
3592 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003593 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003594 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003595 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003596
3597 if (!registered_rtx_ssrc_[header.ssrc])
3598 return SEND_PACKET;
3599
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003600 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003601 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003602 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003603
3604 if (!packet_is_redundant_payload)
3605 return SEND_PACKET;
3606
3607 if (!observed_redundant_retransmission_[header.ssrc]) {
3608 observed_redundant_retransmission_[header.ssrc] = true;
3609 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01003610 observation_complete_.Set();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003611 }
3612
3613 return SEND_PACKET;
3614 }
3615
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003616 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003617
perkjfa10b552016-10-02 23:45:26 -07003618 // This test use other VideoStream settings than the the default settings
3619 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3620 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3621 // in ModifyVideoConfigs.
3622 class VideoStreamFactory
3623 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3624 public:
3625 VideoStreamFactory() {}
3626
3627 private:
3628 std::vector<VideoStream> CreateEncoderStreams(
3629 int width,
3630 int height,
3631 const VideoEncoderConfig& encoder_config) override {
3632 std::vector<VideoStream> streams =
3633 test::CreateVideoStreams(width, height, encoder_config);
3634 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
3635 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3636 streams[i].min_bitrate_bps = 10000;
3637 streams[i].target_bitrate_bps = 15000;
3638 streams[i].max_bitrate_bps = 20000;
3639 }
3640 return streams;
3641 }
3642 };
3643
stefanff483612015-12-21 03:14:00 -08003644 void ModifyVideoConfigs(
3645 VideoSendStream::Config* send_config,
3646 std::vector<VideoReceiveStream::Config>* receive_configs,
3647 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003648 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
perkjfa10b552016-10-02 23:45:26 -07003649 encoder_config->video_stream_factory =
3650 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003651 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003652
3653 for (size_t i = 0; i < kNumSsrcs; ++i)
3654 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00003655
3656 // Significantly higher than max bitrates for all video streams -> forcing
3657 // padding to trigger redundant padding on all RTX SSRCs.
3658 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003659 }
3660
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003661 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003662 EXPECT_TRUE(Wait())
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003663 << "Timed out while waiting for redundant payloads on all SSRCs.";
3664 }
3665
3666 private:
3667 size_t ssrcs_to_observe_;
3668 std::map<uint32_t, bool> observed_redundant_retransmission_;
3669 std::map<uint32_t, bool> registered_rtx_ssrc_;
3670 } test;
3671
stefane74eef12016-01-08 06:47:13 -08003672 RunBaseTest(&test);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003673}
3674
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003675void EndToEndTest::TestRtpStatePreservation(bool use_rtx,
3676 bool provoke_rtcpsr_before_rtp) {
brandtr56e119e2017-05-19 10:33:03 -07003677 // This test use other VideoStream settings than the the default settings
3678 // implemented in DefaultVideoStreamFactory. Therefore this test implement
perkjfa10b552016-10-02 23:45:26 -07003679 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3680 // in ModifyVideoConfigs.
3681 class VideoStreamFactory
3682 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3683 public:
3684 VideoStreamFactory() {}
3685
3686 private:
3687 std::vector<VideoStream> CreateEncoderStreams(
3688 int width,
3689 int height,
3690 const VideoEncoderConfig& encoder_config) override {
3691 std::vector<VideoStream> streams =
3692 test::CreateVideoStreams(width, height, encoder_config);
3693
3694 if (encoder_config.number_of_streams > 1) {
3695 // Lower bitrates so that all streams send initially.
kwibergaf476c72016-11-28 15:21:39 -08003696 RTC_DCHECK_EQ(3, encoder_config.number_of_streams);
perkjfa10b552016-10-02 23:45:26 -07003697 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3698 streams[i].min_bitrate_bps = 10000;
3699 streams[i].target_bitrate_bps = 15000;
3700 streams[i].max_bitrate_bps = 20000;
3701 }
3702 } else {
3703 // Use the same total bitrates when sending a single stream to avoid
3704 // lowering
3705 // the bitrate estimate and requiring a subsequent rampup.
3706 streams[0].min_bitrate_bps = 3 * 10000;
3707 streams[0].target_bitrate_bps = 3 * 15000;
3708 streams[0].max_bitrate_bps = 3 * 20000;
3709 }
3710 return streams;
3711 }
3712 };
3713
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003714 class RtpSequenceObserver : public test::RtpRtcpObserver {
3715 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003716 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003717 : test::RtpRtcpObserver(kDefaultTimeoutMs),
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003718 ssrcs_to_observe_(kNumSsrcs) {
3719 for (size_t i = 0; i < kNumSsrcs; ++i) {
danilchap32cd2c42016-08-01 06:58:34 -07003720 ssrc_is_rtx_[kVideoSendSsrcs[i]] = false;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003721 if (use_rtx)
danilchap32cd2c42016-08-01 06:58:34 -07003722 ssrc_is_rtx_[kSendRtxSsrcs[i]] = true;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003723 }
3724 }
3725
3726 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
Peter Boströmf2f82832015-05-01 13:00:41 +02003727 rtc::CritScope lock(&crit_);
danilchap34877ee2016-02-01 08:25:04 -08003728 ssrc_observed_.clear();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003729 ssrcs_to_observe_ = num_expected_ssrcs;
3730 }
3731
3732 private:
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003733 void ValidateTimestampGap(uint32_t ssrc,
3734 uint32_t timestamp,
3735 bool only_padding)
3736 EXCLUSIVE_LOCKS_REQUIRED(crit_) {
3737 static const int32_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
3738 auto timestamp_it = last_observed_timestamp_.find(ssrc);
3739 if (timestamp_it == last_observed_timestamp_.end()) {
3740 EXPECT_FALSE(only_padding);
3741 last_observed_timestamp_[ssrc] = timestamp;
3742 } else {
3743 // Verify timestamps are reasonably close.
3744 uint32_t latest_observed = timestamp_it->second;
3745 // Wraparound handling is unnecessary here as long as an int variable
3746 // is used to store the result.
3747 int32_t timestamp_gap = timestamp - latest_observed;
3748 EXPECT_LE(std::abs(timestamp_gap), kMaxTimestampGap)
3749 << "Gap in timestamps (" << latest_observed << " -> " << timestamp
3750 << ") too large for SSRC: " << ssrc << ".";
3751 timestamp_it->second = timestamp;
3752 }
3753 }
3754
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003755 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003756 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003757 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003758 const uint32_t ssrc = header.ssrc;
danilchap5c35cf92016-02-03 14:14:49 -08003759 const int64_t sequence_number =
3760 seq_numbers_unwrapper_.Unwrap(header.sequenceNumber);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003761 const uint32_t timestamp = header.timestamp;
danilchap34877ee2016-02-01 08:25:04 -08003762 const bool only_padding =
3763 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003764
danilchap32cd2c42016-08-01 06:58:34 -07003765 EXPECT_TRUE(ssrc_is_rtx_.find(ssrc) != ssrc_is_rtx_.end())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003766 << "Received SSRC that wasn't configured: " << ssrc;
3767
danilchap5c35cf92016-02-03 14:14:49 -08003768 static const int64_t kMaxSequenceNumberGap = 100;
3769 std::list<int64_t>* seq_numbers = &last_observed_seq_numbers_[ssrc];
3770 if (seq_numbers->empty()) {
3771 seq_numbers->push_back(sequence_number);
3772 } else {
3773 // We shouldn't get replays of previous sequence numbers.
3774 for (int64_t observed : *seq_numbers) {
3775 EXPECT_NE(observed, sequence_number)
3776 << "Received sequence number " << sequence_number
3777 << " for SSRC " << ssrc << " 2nd time.";
3778 }
3779 // Verify sequence numbers are reasonably close.
3780 int64_t latest_observed = seq_numbers->back();
3781 int64_t sequence_number_gap = sequence_number - latest_observed;
3782 EXPECT_LE(std::abs(sequence_number_gap), kMaxSequenceNumberGap)
3783 << "Gap in sequence numbers (" << latest_observed << " -> "
3784 << sequence_number << ") too large for SSRC: " << ssrc << ".";
3785 seq_numbers->push_back(sequence_number);
3786 if (seq_numbers->size() >= kMaxSequenceNumberGap) {
3787 seq_numbers->pop_front();
3788 }
3789 }
3790
danilchap32cd2c42016-08-01 06:58:34 -07003791 if (!ssrc_is_rtx_[ssrc]) {
3792 rtc::CritScope lock(&crit_);
3793 ValidateTimestampGap(ssrc, timestamp, only_padding);
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003794
danilchap32cd2c42016-08-01 06:58:34 -07003795 // Wait for media packets on all ssrcs.
3796 if (!ssrc_observed_[ssrc] && !only_padding) {
3797 ssrc_observed_[ssrc] = true;
3798 if (--ssrcs_to_observe_ == 0)
3799 observation_complete_.Set();
3800 }
danilchap34877ee2016-02-01 08:25:04 -08003801 }
3802
danilchapf4b9c772016-01-28 06:14:24 -08003803 return SEND_PACKET;
3804 }
3805
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003806 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
3807 test::RtcpPacketParser rtcp_parser;
3808 rtcp_parser.Parse(packet, length);
3809 if (rtcp_parser.sender_report()->num_packets() > 0) {
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02003810 uint32_t ssrc = rtcp_parser.sender_report()->sender_ssrc();
3811 uint32_t rtcp_timestamp = rtcp_parser.sender_report()->rtp_timestamp();
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003812
3813 rtc::CritScope lock(&crit_);
3814 ValidateTimestampGap(ssrc, rtcp_timestamp, false);
3815 }
3816 return SEND_PACKET;
3817 }
3818
danilchap5c35cf92016-02-03 14:14:49 -08003819 SequenceNumberUnwrapper seq_numbers_unwrapper_;
3820 std::map<uint32_t, std::list<int64_t>> last_observed_seq_numbers_;
danilchap34877ee2016-02-01 08:25:04 -08003821 std::map<uint32_t, uint32_t> last_observed_timestamp_;
danilchap32cd2c42016-08-01 06:58:34 -07003822 std::map<uint32_t, bool> ssrc_is_rtx_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003823
Peter Boströmf2f82832015-05-01 13:00:41 +02003824 rtc::CriticalSection crit_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003825 size_t ssrcs_to_observe_ GUARDED_BY(crit_);
danilchap34877ee2016-02-01 08:25:04 -08003826 std::map<uint32_t, bool> ssrc_observed_ GUARDED_BY(crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003827 } observer(use_rtx);
3828
philipel4fb651d2017-04-10 03:54:05 -07003829 Call::Config config(event_log_.get());
skvlad11a9cbf2016-10-07 11:53:05 -07003830 CreateCalls(config, config);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003831
minyue20c84cc2017-04-10 16:57:57 -07003832 test::PacketTransport send_transport(
3833 sender_call_.get(), &observer, test::PacketTransport::kSender,
3834 payload_type_map_, FakeNetworkPipe::Config());
3835 test::PacketTransport receive_transport(
3836 nullptr, &observer, test::PacketTransport::kReceiver, payload_type_map_,
3837 FakeNetworkPipe::Config());
stefanf116bd02015-10-27 08:29:42 -07003838 send_transport.SetReceiver(receiver_call_->Receiver());
3839 receive_transport.SetReceiver(sender_call_->Receiver());
3840
brandtr841de6a2016-11-15 07:10:52 -08003841 CreateSendConfig(kNumSsrcs, 0, 0, &send_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003842
3843 if (use_rtx) {
3844 for (size_t i = 0; i < kNumSsrcs; ++i) {
stefanff483612015-12-21 03:14:00 -08003845 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003846 }
stefanff483612015-12-21 03:14:00 -08003847 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003848 }
3849
perkjfa10b552016-10-02 23:45:26 -07003850 video_encoder_config_.video_stream_factory =
3851 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003852 // Use the same total bitrates when sending a single stream to avoid lowering
3853 // the bitrate estimate and requiring a subsequent rampup.
perkj26091b12016-09-01 01:17:40 -07003854 VideoEncoderConfig one_stream = video_encoder_config_.Copy();
perkjfa10b552016-10-02 23:45:26 -07003855 // one_stream.streams.resize(1);
3856 one_stream.number_of_streams = 1;
stefanf116bd02015-10-27 08:29:42 -07003857 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003858
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003859 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003860 CreateFrameGeneratorCapturer(30, 1280, 720);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003861
3862 Start();
Peter Boström5811a392015-12-10 13:02:50 +01003863 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003864 << "Timed out waiting for all SSRCs to send packets.";
3865
3866 // Test stream resetting more than once to make sure that the state doesn't
3867 // get set once (this could be due to using std::map::insert for instance).
3868 for (size_t i = 0; i < 3; ++i) {
3869 frame_generator_capturer_->Stop();
stefanff483612015-12-21 03:14:00 -08003870 sender_call_->DestroyVideoSendStream(video_send_stream_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003871
3872 // Re-create VideoSendStream with only one stream.
perkj26091b12016-09-01 01:17:40 -07003873 video_send_stream_ = sender_call_->CreateVideoSendStream(
3874 video_send_config_.Copy(), one_stream.Copy());
stefanff483612015-12-21 03:14:00 -08003875 video_send_stream_->Start();
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003876 if (provoke_rtcpsr_before_rtp) {
3877 // Rapid Resync Request forces sending RTCP Sender Report back.
3878 // Using this request speeds up this test because then there is no need
3879 // to wait for a second for periodic Sender Report.
3880 rtcp::RapidResyncRequest force_send_sr_back_request;
3881 rtc::Buffer packet = force_send_sr_back_request.Build();
3882 static_cast<webrtc::test::DirectTransport&>(receive_transport)
3883 .SendRtcp(packet.data(), packet.size());
3884 }
perkjfa10b552016-10-02 23:45:26 -07003885 CreateFrameGeneratorCapturer(30, 1280, 720);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003886 frame_generator_capturer_->Start();
3887
3888 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003889 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003890
3891 // Reconfigure back to use all streams.
perkj26091b12016-09-01 01:17:40 -07003892 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003893 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003894 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003895 << "Timed out waiting for all SSRCs to send packets.";
3896
3897 // Reconfigure down to one stream.
perkj26091b12016-09-01 01:17:40 -07003898 video_send_stream_->ReconfigureVideoEncoder(one_stream.Copy());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003899 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003900 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003901
3902 // Reconfigure back to use all streams.
perkj26091b12016-09-01 01:17:40 -07003903 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003904 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003905 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003906 << "Timed out waiting for all SSRCs to send packets.";
3907 }
3908
stefanf116bd02015-10-27 08:29:42 -07003909 send_transport.StopSending();
3910 receive_transport.StopSending();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003911
3912 Stop();
3913 DestroyStreams();
3914}
3915
philipel277a8b52017-03-16 05:19:49 -07003916TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpState) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003917 TestRtpStatePreservation(false, false);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003918}
3919
philipel277a8b52017-03-16 05:19:49 -07003920TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpStatesWithRtx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003921 TestRtpStatePreservation(true, false);
3922}
3923
philipel277a8b52017-03-16 05:19:49 -07003924TEST_F(EndToEndTest, RestartingSendStreamKeepsRtpAndRtcpTimestampsSynced) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003925 TestRtpStatePreservation(true, true);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003926}
3927
philipel277a8b52017-03-16 05:19:49 -07003928TEST_F(EndToEndTest, RespectsNetworkState) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003929 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
3930 // down blocks until no more packets will be sent.
3931
3932 // Pacer will send from its packet list and then send required padding before
3933 // checking paused_ again. This should be enough for one round of pacing,
3934 // otherwise increase.
3935 static const int kNumAcceptedDowntimeRtp = 5;
3936 // A single RTCP may be in the pipeline.
3937 static const int kNumAcceptedDowntimeRtcp = 1;
3938 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
3939 public:
3940 NetworkStateTest()
3941 : EndToEndTest(kDefaultTimeoutMs),
3942 FakeEncoder(Clock::GetRealTimeClock()),
Peter Boström5811a392015-12-10 13:02:50 +01003943 encoded_frames_(false, false),
3944 packet_event_(false, false),
sprang867fb522015-08-03 04:38:41 -07003945 sender_call_(nullptr),
3946 receiver_call_(nullptr),
Jelena Marusiccd670222015-07-16 09:30:09 +02003947 sender_state_(kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003948 sender_rtp_(0),
3949 sender_rtcp_(0),
3950 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003951 down_frames_(0) {}
3952
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003953 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003954 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003955 ++sender_rtp_;
Peter Boström5811a392015-12-10 13:02:50 +01003956 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003957 return SEND_PACKET;
3958 }
3959
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003960 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003961 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003962 ++sender_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003963 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003964 return SEND_PACKET;
3965 }
3966
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003967 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003968 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
3969 return SEND_PACKET;
3970 }
3971
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003972 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003973 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003974 ++receiver_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003975 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003976 return SEND_PACKET;
3977 }
3978
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003979 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003980 sender_call_ = sender_call;
3981 receiver_call_ = receiver_call;
3982 }
3983
stefanff483612015-12-21 03:14:00 -08003984 void ModifyVideoConfigs(
3985 VideoSendStream::Config* send_config,
3986 std::vector<VideoReceiveStream::Config>* receive_configs,
3987 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003988 send_config->encoder_settings.encoder = this;
3989 }
3990
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003991 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003992 EXPECT_TRUE(encoded_frames_.Wait(kDefaultTimeoutMs))
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003993 << "No frames received by the encoder.";
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003994 // Wait for packets from both sender/receiver.
3995 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003996
skvlad7a43d252016-03-22 15:32:27 -07003997 // Sender-side network down for audio; there should be no effect on video
3998 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3999 WaitForPacketsOrSilence(false, false);
4000
4001 // Receiver-side network down for audio; no change expected
4002 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
4003 WaitForPacketsOrSilence(false, false);
4004
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004005 // Sender-side network down.
skvlad7a43d252016-03-22 15:32:27 -07004006 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004007 {
Peter Boströmf2f82832015-05-01 13:00:41 +02004008 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004009 // After network goes down we shouldn't be encoding more frames.
Jelena Marusiccd670222015-07-16 09:30:09 +02004010 sender_state_ = kNetworkDown;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004011 }
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004012 // Wait for receiver-packets and no sender packets.
4013 WaitForPacketsOrSilence(true, false);
4014
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004015 // Receiver-side network down.
skvlad7a43d252016-03-22 15:32:27 -07004016 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
4017 WaitForPacketsOrSilence(true, true);
4018
4019 // Network up for audio for both sides; video is still not expected to
4020 // start
4021 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
4022 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004023 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004024
4025 // Network back up again for both.
4026 {
Peter Boströmf2f82832015-05-01 13:00:41 +02004027 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004028 // It's OK to encode frames again, as we're about to bring up the
4029 // network.
Jelena Marusiccd670222015-07-16 09:30:09 +02004030 sender_state_ = kNetworkUp;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004031 }
skvlad7a43d252016-03-22 15:32:27 -07004032 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
4033 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004034 WaitForPacketsOrSilence(false, false);
skvlad7a43d252016-03-22 15:32:27 -07004035
4036 // TODO(skvlad): add tests to verify that the audio streams are stopped
4037 // when the network goes down for audio once the workaround in
4038 // paced_sender.cc is removed.
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004039 }
4040
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07004041 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004042 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07004043 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004044 {
Peter Boströmf2f82832015-05-01 13:00:41 +02004045 rtc::CritScope lock(&test_crit_);
Jelena Marusiccd670222015-07-16 09:30:09 +02004046 if (sender_state_ == kNetworkDown) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004047 ++down_frames_;
4048 EXPECT_LE(down_frames_, 1)
4049 << "Encoding more than one frame while network is down.";
4050 if (down_frames_ > 1)
Peter Boström5811a392015-12-10 13:02:50 +01004051 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004052 } else {
Peter Boström5811a392015-12-10 13:02:50 +01004053 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004054 }
4055 }
4056 return test::FakeEncoder::Encode(
4057 input_image, codec_specific_info, frame_types);
4058 }
4059
4060 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004061 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
4062 int64_t initial_time_ms = clock_->TimeInMilliseconds();
4063 int initial_sender_rtp;
4064 int initial_sender_rtcp;
4065 int initial_receiver_rtcp;
4066 {
Peter Boströmf2f82832015-05-01 13:00:41 +02004067 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004068 initial_sender_rtp = sender_rtp_;
4069 initial_sender_rtcp = sender_rtcp_;
4070 initial_receiver_rtcp = receiver_rtcp_;
4071 }
4072 bool sender_done = false;
4073 bool receiver_done = false;
mflodmand1590b22015-12-09 07:07:59 -08004074 while (!sender_done || !receiver_done) {
Peter Boström5811a392015-12-10 13:02:50 +01004075 packet_event_.Wait(kSilenceTimeoutMs);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004076 int64_t time_now_ms = clock_->TimeInMilliseconds();
Peter Boströmf2f82832015-05-01 13:00:41 +02004077 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004078 if (sender_down) {
4079 ASSERT_LE(sender_rtp_ - initial_sender_rtp, kNumAcceptedDowntimeRtp)
4080 << "RTP sent during sender-side downtime.";
4081 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
4082 kNumAcceptedDowntimeRtcp)
4083 << "RTCP sent during sender-side downtime.";
4084 if (time_now_ms - initial_time_ms >=
4085 static_cast<int64_t>(kSilenceTimeoutMs)) {
4086 sender_done = true;
4087 }
4088 } else {
skvlad7a43d252016-03-22 15:32:27 -07004089 if (sender_rtp_ > initial_sender_rtp + kNumAcceptedDowntimeRtp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004090 sender_done = true;
4091 }
4092 if (receiver_down) {
4093 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
4094 kNumAcceptedDowntimeRtcp)
4095 << "RTCP sent during receiver-side downtime.";
4096 if (time_now_ms - initial_time_ms >=
4097 static_cast<int64_t>(kSilenceTimeoutMs)) {
4098 receiver_done = true;
4099 }
4100 } else {
skvlad7a43d252016-03-22 15:32:27 -07004101 if (receiver_rtcp_ > initial_receiver_rtcp + kNumAcceptedDowntimeRtcp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004102 receiver_done = true;
4103 }
4104 }
4105 }
4106
Peter Boströmf2f82832015-05-01 13:00:41 +02004107 rtc::CriticalSection test_crit_;
Peter Boström5811a392015-12-10 13:02:50 +01004108 rtc::Event encoded_frames_;
4109 rtc::Event packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004110 Call* sender_call_;
4111 Call* receiver_call_;
Jelena Marusiccd670222015-07-16 09:30:09 +02004112 NetworkState sender_state_ GUARDED_BY(test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004113 int sender_rtp_ GUARDED_BY(test_crit_);
4114 int sender_rtcp_ GUARDED_BY(test_crit_);
4115 int receiver_rtcp_ GUARDED_BY(test_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004116 int down_frames_ GUARDED_BY(test_crit_);
4117 } test;
4118
stefane74eef12016-01-08 06:47:13 -08004119 RunBaseTest(&test);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004120}
4121
philipel277a8b52017-03-16 05:19:49 -07004122TEST_F(EndToEndTest, CallReportsRttForSender) {
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004123 static const int kSendDelayMs = 30;
4124 static const int kReceiveDelayMs = 70;
philipel4fb651d2017-04-10 03:54:05 -07004125 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
solenberg4fbae2b2015-08-28 04:07:10 -07004126
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004127 FakeNetworkPipe::Config config;
4128 config.queue_delay_ms = kSendDelayMs;
minyue20c84cc2017-04-10 16:57:57 -07004129 test::DirectTransport sender_transport(config, sender_call_.get(),
4130 payload_type_map_);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004131 config.queue_delay_ms = kReceiveDelayMs;
minyue20c84cc2017-04-10 16:57:57 -07004132 test::DirectTransport receiver_transport(config, receiver_call_.get(),
4133 payload_type_map_);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004134 sender_transport.SetReceiver(receiver_call_->Receiver());
4135 receiver_transport.SetReceiver(sender_call_->Receiver());
4136
brandtr841de6a2016-11-15 07:10:52 -08004137 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07004138 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004139
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004140 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07004141 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
4142 kDefaultHeight);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004143 Start();
4144
4145 int64_t start_time_ms = clock_->TimeInMilliseconds();
4146 while (true) {
4147 Call::Stats stats = sender_call_->GetStats();
4148 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
4149 clock_->TimeInMilliseconds())
4150 << "No RTT stats before timeout!";
4151 if (stats.rtt_ms != -1) {
Danil Chapovalov10e8f8e2016-09-07 15:05:29 +02004152 // To avoid failures caused by rounding or minor ntp clock adjustments,
4153 // relax expectation by 1ms.
4154 constexpr int kAllowedErrorMs = 1;
4155 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs - kAllowedErrorMs);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004156 break;
4157 }
4158 SleepMs(10);
4159 }
4160
philipel266f0a42016-11-28 08:49:07 -08004161 sender_transport.StopSending();
4162 receiver_transport.StopSending();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004163 Stop();
4164 DestroyStreams();
philipel266f0a42016-11-28 08:49:07 -08004165 DestroyCalls();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004166}
4167
skvlad7a43d252016-03-22 15:32:27 -07004168void EndToEndTest::VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004169 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -07004170 VideoEncoder* encoder,
4171 Transport* transport) {
philipel4fb651d2017-04-10 03:54:05 -07004172 CreateSenderCall(Call::Config(event_log_.get()));
Sergey Ulanove2b15012016-11-22 16:08:30 -08004173 sender_call_->SignalChannelNetworkState(network_to_bring_up, kNetworkUp);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004174
brandtr841de6a2016-11-15 07:10:52 -08004175 CreateSendConfig(1, 0, 0, transport);
skvlad7a43d252016-03-22 15:32:27 -07004176 video_send_config_.encoder_settings.encoder = encoder;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004177 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07004178 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
4179 kDefaultHeight);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004180
4181 Start();
4182 SleepMs(kSilenceTimeoutMs);
4183 Stop();
4184
4185 DestroyStreams();
4186}
4187
skvlad7a43d252016-03-22 15:32:27 -07004188void EndToEndTest::VerifyNewVideoReceiveStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004189 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -07004190 Transport* transport) {
philipel4fb651d2017-04-10 03:54:05 -07004191 Call::Config config(event_log_.get());
skvlad11a9cbf2016-10-07 11:53:05 -07004192 CreateCalls(config, config);
Sergey Ulanove2b15012016-11-22 16:08:30 -08004193 receiver_call_->SignalChannelNetworkState(network_to_bring_up, kNetworkUp);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004194
minyue20c84cc2017-04-10 16:57:57 -07004195 test::DirectTransport sender_transport(sender_call_.get(), payload_type_map_);
solenberg4fbae2b2015-08-28 04:07:10 -07004196 sender_transport.SetReceiver(receiver_call_->Receiver());
brandtr841de6a2016-11-15 07:10:52 -08004197 CreateSendConfig(1, 0, 0, &sender_transport);
skvlad7a43d252016-03-22 15:32:27 -07004198 CreateMatchingReceiveConfigs(transport);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004199 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07004200 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
4201 kDefaultHeight);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004202
4203 Start();
4204 SleepMs(kSilenceTimeoutMs);
4205 Stop();
4206
4207 sender_transport.StopSending();
4208
4209 DestroyStreams();
4210}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00004211
philipel277a8b52017-03-16 05:19:49 -07004212TEST_F(EndToEndTest, NewVideoSendStreamsRespectVideoNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004213 class UnusedEncoder : public test::FakeEncoder {
4214 public:
4215 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
perkjfea93092016-05-14 00:58:48 -07004216
4217 int32_t InitEncode(const VideoCodec* config,
4218 int32_t number_of_cores,
4219 size_t max_payload_size) override {
4220 EXPECT_GT(config->startBitrate, 0u);
4221 return 0;
4222 }
skvlad7a43d252016-03-22 15:32:27 -07004223 int32_t Encode(const VideoFrame& input_image,
4224 const CodecSpecificInfo* codec_specific_info,
4225 const std::vector<FrameType>* frame_types) override {
4226 ADD_FAILURE() << "Unexpected frame encode.";
4227 return test::FakeEncoder::Encode(input_image, codec_specific_info,
4228 frame_types);
4229 }
4230 };
4231
4232 UnusedEncoder unused_encoder;
4233 UnusedTransport unused_transport;
4234 VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004235 MediaType::AUDIO, &unused_encoder, &unused_transport);
skvlad7a43d252016-03-22 15:32:27 -07004236}
4237
philipel277a8b52017-03-16 05:19:49 -07004238TEST_F(EndToEndTest, NewVideoSendStreamsIgnoreAudioNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004239 class RequiredEncoder : public test::FakeEncoder {
4240 public:
4241 RequiredEncoder()
4242 : FakeEncoder(Clock::GetRealTimeClock()), encoded_frame_(false) {}
4243 ~RequiredEncoder() {
4244 if (!encoded_frame_) {
4245 ADD_FAILURE() << "Didn't encode an expected frame";
4246 }
4247 }
4248 int32_t Encode(const VideoFrame& input_image,
4249 const CodecSpecificInfo* codec_specific_info,
4250 const std::vector<FrameType>* frame_types) override {
4251 encoded_frame_ = true;
4252 return test::FakeEncoder::Encode(input_image, codec_specific_info,
4253 frame_types);
4254 }
4255
4256 private:
4257 bool encoded_frame_;
4258 };
4259
4260 RequiredTransport required_transport(true /*rtp*/, false /*rtcp*/);
4261 RequiredEncoder required_encoder;
4262 VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004263 MediaType::VIDEO, &required_encoder, &required_transport);
skvlad7a43d252016-03-22 15:32:27 -07004264}
4265
philipel277a8b52017-03-16 05:19:49 -07004266TEST_F(EndToEndTest, NewVideoReceiveStreamsRespectVideoNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004267 UnusedTransport transport;
Sergey Ulanove2b15012016-11-22 16:08:30 -08004268 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::AUDIO, &transport);
skvlad7a43d252016-03-22 15:32:27 -07004269}
4270
philipel277a8b52017-03-16 05:19:49 -07004271TEST_F(EndToEndTest, NewVideoReceiveStreamsIgnoreAudioNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004272 RequiredTransport transport(false /*rtp*/, true /*rtcp*/);
Sergey Ulanove2b15012016-11-22 16:08:30 -08004273 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::VIDEO, &transport);
skvlad7a43d252016-03-22 15:32:27 -07004274}
4275
Peter Boströmd7da1202015-06-05 14:09:38 +02004276void VerifyEmptyNackConfig(const NackConfig& config) {
4277 EXPECT_EQ(0, config.rtp_history_ms)
4278 << "Enabling NACK requires rtcp-fb: nack negotiation.";
4279}
4280
brandtrb5f2c3f2016-10-04 23:28:39 -07004281void VerifyEmptyUlpfecConfig(const UlpfecConfig& config) {
Peter Boströmd7da1202015-06-05 14:09:38 +02004282 EXPECT_EQ(-1, config.ulpfec_payload_type)
brandtr535830e2016-10-31 03:45:58 -07004283 << "Enabling ULPFEC requires rtpmap: ulpfec negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02004284 EXPECT_EQ(-1, config.red_payload_type)
brandtr535830e2016-10-31 03:45:58 -07004285 << "Enabling ULPFEC requires rtpmap: red negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02004286 EXPECT_EQ(-1, config.red_rtx_payload_type)
brandtr535830e2016-10-31 03:45:58 -07004287 << "Enabling RTX in ULPFEC requires rtpmap: rtx negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02004288}
4289
brandtr3d200bd2017-01-16 06:59:19 -08004290void VerifyEmptyFlexfecConfig(
4291 const VideoSendStream::Config::Rtp::Flexfec& config) {
4292 EXPECT_EQ(-1, config.payload_type)
brandtr1e3dfbf2016-11-16 22:45:19 -08004293 << "Enabling FlexFEC requires rtpmap: flexfec negotiation.";
brandtr3d200bd2017-01-16 06:59:19 -08004294 EXPECT_EQ(0U, config.ssrc)
brandtr1cfbd602016-12-08 04:17:53 -08004295 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
brandtr1e3dfbf2016-11-16 22:45:19 -08004296 EXPECT_TRUE(config.protected_media_ssrcs.empty())
4297 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
4298}
4299
philipel277a8b52017-03-16 05:19:49 -07004300TEST_F(EndToEndTest, VerifyDefaultSendConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07004301 VideoSendStream::Config default_send_config(nullptr);
Peter Boströmd7da1202015-06-05 14:09:38 +02004302 EXPECT_EQ(0, default_send_config.rtp.nack.rtp_history_ms)
4303 << "Enabling NACK require rtcp-fb: nack negotiation.";
4304 EXPECT_TRUE(default_send_config.rtp.rtx.ssrcs.empty())
4305 << "Enabling RTX requires rtpmap: rtx negotiation.";
4306 EXPECT_TRUE(default_send_config.rtp.extensions.empty())
4307 << "Enabling RTP extensions require negotiation.";
4308
4309 VerifyEmptyNackConfig(default_send_config.rtp.nack);
brandtrb5f2c3f2016-10-04 23:28:39 -07004310 VerifyEmptyUlpfecConfig(default_send_config.rtp.ulpfec);
brandtr1e3dfbf2016-11-16 22:45:19 -08004311 VerifyEmptyFlexfecConfig(default_send_config.rtp.flexfec);
Peter Boströmd7da1202015-06-05 14:09:38 +02004312}
4313
philipel277a8b52017-03-16 05:19:49 -07004314TEST_F(EndToEndTest, VerifyDefaultVideoReceiveConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07004315 VideoReceiveStream::Config default_receive_config(nullptr);
pbosda903ea2015-10-02 02:36:56 -07004316 EXPECT_EQ(RtcpMode::kCompound, default_receive_config.rtp.rtcp_mode)
Peter Boströmd7da1202015-06-05 14:09:38 +02004317 << "Reduced-size RTCP require rtcp-rsize to be negotiated.";
4318 EXPECT_FALSE(default_receive_config.rtp.remb)
4319 << "REMB require rtcp-fb: goog-remb to be negotiated.";
4320 EXPECT_FALSE(
4321 default_receive_config.rtp.rtcp_xr.receiver_reference_time_report)
4322 << "RTCP XR settings require rtcp-xr to be negotiated.";
brandtr14742122017-01-27 04:53:07 -08004323 EXPECT_EQ(0U, default_receive_config.rtp.rtx_ssrc)
4324 << "Enabling RTX requires ssrc-group: FID negotiation";
4325 EXPECT_TRUE(default_receive_config.rtp.rtx_payload_types.empty())
Peter Boströmd7da1202015-06-05 14:09:38 +02004326 << "Enabling RTX requires rtpmap: rtx negotiation.";
4327 EXPECT_TRUE(default_receive_config.rtp.extensions.empty())
4328 << "Enabling RTP extensions require negotiation.";
4329
4330 VerifyEmptyNackConfig(default_receive_config.rtp.nack);
brandtrb5f2c3f2016-10-04 23:28:39 -07004331 VerifyEmptyUlpfecConfig(default_receive_config.rtp.ulpfec);
Peter Boströmd7da1202015-06-05 14:09:38 +02004332}
4333
philipel277a8b52017-03-16 05:19:49 -07004334TEST_F(EndToEndTest, VerifyDefaultFlexfecReceiveConfigParameters) {
brandtr8313a6f2017-01-13 07:41:19 -08004335 test::NullTransport rtcp_send_transport;
4336 FlexfecReceiveStream::Config default_receive_config(&rtcp_send_transport);
brandtr1cfbd602016-12-08 04:17:53 -08004337 EXPECT_EQ(-1, default_receive_config.payload_type)
4338 << "Enabling FlexFEC requires rtpmap: flexfec negotiation.";
4339 EXPECT_EQ(0U, default_receive_config.remote_ssrc)
4340 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
4341 EXPECT_TRUE(default_receive_config.protected_media_ssrcs.empty())
4342 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
brandtr1e3dfbf2016-11-16 22:45:19 -08004343}
4344
philipel277a8b52017-03-16 05:19:49 -07004345TEST_F(EndToEndTest, TransportSeqNumOnAudioAndVideo) {
danilchap4336d732017-03-03 06:21:54 -08004346 static constexpr int kExtensionId = 8;
4347 static constexpr size_t kMinPacketsToWaitFor = 50;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004348 class TransportSequenceNumberTest : public test::EndToEndTest {
4349 public:
4350 TransportSequenceNumberTest()
4351 : EndToEndTest(kDefaultTimeoutMs),
4352 video_observed_(false),
4353 audio_observed_(false) {
4354 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
4355 kExtensionId);
4356 }
4357
4358 size_t GetNumVideoStreams() const override { return 1; }
4359 size_t GetNumAudioStreams() const override { return 1; }
4360
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004361 void ModifyAudioConfigs(
4362 AudioSendStream::Config* send_config,
4363 std::vector<AudioReceiveStream::Config>* receive_configs) override {
4364 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07004365 send_config->rtp.extensions.push_back(RtpExtension(
4366 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004367 (*receive_configs)[0].rtp.extensions.clear();
4368 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
4369 }
4370
4371 Action OnSendRtp(const uint8_t* packet, size_t length) override {
4372 RTPHeader header;
4373 EXPECT_TRUE(parser_->Parse(packet, length, &header));
4374 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
4375 // Unwrap packet id and verify uniqueness.
4376 int64_t packet_id =
4377 unwrapper_.Unwrap(header.extension.transportSequenceNumber);
4378 EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
4379
4380 if (header.ssrc == kVideoSendSsrcs[0])
4381 video_observed_ = true;
4382 if (header.ssrc == kAudioSendSsrc)
4383 audio_observed_ = true;
4384 if (audio_observed_ && video_observed_ &&
danilchap4336d732017-03-03 06:21:54 -08004385 received_packet_ids_.size() >= kMinPacketsToWaitFor) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004386 size_t packet_id_range =
4387 *received_packet_ids_.rbegin() - *received_packet_ids_.begin() + 1;
4388 EXPECT_EQ(received_packet_ids_.size(), packet_id_range);
4389 observation_complete_.Set();
4390 }
4391 return SEND_PACKET;
4392 }
4393
4394 void PerformTest() override {
4395 EXPECT_TRUE(Wait()) << "Timed out while waiting for audio and video "
4396 "packets with transport sequence number.";
4397 }
4398
danilchap4336d732017-03-03 06:21:54 -08004399 void ExpectSuccessful() {
4400 EXPECT_TRUE(video_observed_);
4401 EXPECT_TRUE(audio_observed_);
4402 EXPECT_GE(received_packet_ids_.size(), kMinPacketsToWaitFor);
4403 }
4404
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004405 private:
4406 bool video_observed_;
4407 bool audio_observed_;
4408 SequenceNumberUnwrapper unwrapper_;
4409 std::set<int64_t> received_packet_ids_;
4410 } test;
4411
stefane74eef12016-01-08 06:47:13 -08004412 RunBaseTest(&test);
danilchap4336d732017-03-03 06:21:54 -08004413 // Double check conditions for successful test to produce better error
4414 // message when the test fail.
4415 test.ExpectSuccessful();
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004416}
palmkviste75f2042016-09-28 06:19:48 -07004417
4418class EndToEndLogTest : public EndToEndTest {
4419 void SetUp() { paths_.clear(); }
4420 void TearDown() {
4421 for (const auto& path : paths_) {
4422 rtc::RemoveFile(path);
4423 }
4424 }
4425
4426 public:
4427 int AddFile() {
4428 paths_.push_back(test::TempFilename(test::OutputPath(), "test_file"));
4429 return static_cast<int>(paths_.size()) - 1;
4430 }
4431
4432 rtc::PlatformFile OpenFile(int idx) {
4433 return rtc::OpenPlatformFile(paths_[idx]);
4434 }
4435
4436 void LogSend(bool open) {
4437 if (open) {
4438 video_send_stream_->EnableEncodedFrameRecording(
4439 std::vector<rtc::PlatformFile>(1, OpenFile(AddFile())), 0);
4440 } else {
4441 video_send_stream_->DisableEncodedFrameRecording();
4442 }
4443 }
4444 void LogReceive(bool open) {
4445 if (open) {
4446 video_receive_streams_[0]->EnableEncodedFrameRecording(
4447 OpenFile(AddFile()), 0);
4448 } else {
4449 video_receive_streams_[0]->DisableEncodedFrameRecording();
4450 }
4451 }
4452
4453 std::vector<std::string> paths_;
4454};
4455
philipel277a8b52017-03-16 05:19:49 -07004456TEST_F(EndToEndLogTest, LogsEncodedFramesWhenRequested) {
palmkviste75f2042016-09-28 06:19:48 -07004457 static const int kNumFramesToRecord = 10;
4458 class LogEncodingObserver : public test::EndToEndTest,
4459 public EncodedFrameObserver {
4460 public:
4461 explicit LogEncodingObserver(EndToEndLogTest* fixture)
4462 : EndToEndTest(kDefaultTimeoutMs),
4463 fixture_(fixture),
4464 recorded_frames_(0) {}
4465
4466 void PerformTest() override {
4467 fixture_->LogSend(true);
4468 fixture_->LogReceive(true);
4469 ASSERT_TRUE(Wait()) << "Timed out while waiting for frame logging.";
4470 }
4471
4472 void ModifyVideoConfigs(
4473 VideoSendStream::Config* send_config,
4474 std::vector<VideoReceiveStream::Config>* receive_configs,
4475 VideoEncoderConfig* encoder_config) override {
magjed509e4fe2016-11-18 01:34:11 -08004476 encoder_.reset(VP8Encoder::Create());
palmkviste75f2042016-09-28 06:19:48 -07004477 decoder_.reset(VP8Decoder::Create());
4478
4479 send_config->post_encode_callback = this;
4480 send_config->encoder_settings.payload_name = "VP8";
4481 send_config->encoder_settings.encoder = encoder_.get();
4482
4483 (*receive_configs)[0].decoders.resize(1);
4484 (*receive_configs)[0].decoders[0].payload_type =
4485 send_config->encoder_settings.payload_type;
4486 (*receive_configs)[0].decoders[0].payload_name =
4487 send_config->encoder_settings.payload_name;
4488 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
4489 }
4490
4491 void EncodedFrameCallback(const EncodedFrame& encoded_frame) override {
4492 rtc::CritScope lock(&crit_);
4493 if (recorded_frames_++ > kNumFramesToRecord) {
4494 fixture_->LogSend(false);
4495 fixture_->LogReceive(false);
4496 rtc::File send_file(fixture_->OpenFile(0));
4497 rtc::File receive_file(fixture_->OpenFile(1));
4498 uint8_t out[100];
4499 // If logging has worked correctly neither file should be empty, i.e.
4500 // we should be able to read something from them.
4501 EXPECT_LT(0u, send_file.Read(out, 100));
4502 EXPECT_LT(0u, receive_file.Read(out, 100));
4503 observation_complete_.Set();
4504 }
4505 }
4506
4507 private:
4508 EndToEndLogTest* const fixture_;
4509 std::unique_ptr<VideoEncoder> encoder_;
4510 std::unique_ptr<VideoDecoder> decoder_;
4511 rtc::CriticalSection crit_;
4512 int recorded_frames_ GUARDED_BY(crit_);
4513 } test(this);
4514
4515 RunBaseTest(&test);
4516}
4517
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00004518} // namespace webrtc